Compare commits

..

120 Commits

Author SHA1 Message Date
Tom Fifield
9e55e6befb Minor GPS fixes (#4630)
1. Remove unused line in GPS::probe
2. update new PositionModule::hasQualityTimeSource to handle
 MESHTASTIC_EXCLUDE_GPS
2024-09-05 06:16:06 -05:00
gitbisector
bb9ddcf2b5 Same priority packets processed in enqueue order (#4608)
* Same priority packets processed in enqueue order

* Prefer same prio pkts on mesh over new ones.

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2024-09-04 08:31:30 -05:00
Thomas Göttgens
ff40a3f120 fix RF switch for Tracker E (#4621)
* fix RF switch for Tracker E

* fix all flags for Radiolib

* hopefully fix LR1110

* update to latest radiolib master - thanks @GUVWAF
2024-09-03 14:21:40 -05:00
Thomas Göttgens
8b1d7825b9 Merge pull request #4612 from meshtastic/Tracker-1000E
several small changes for Tracker 1000E
2024-09-03 14:33:03 +02:00
Thomas Göttgens
6fc4a1754b Radiolib API Changes 2024-09-03 13:12:39 +02:00
Thomas Göttgens
d83f8edd54 include radiolib CRC fix 2024-09-03 12:09:53 +02:00
Thomas Göttgens
543e7f3342 add generic bootloaders by @markbirss 2024-09-03 12:03:06 +02:00
Thomas Göttgens
f9e513f4fd Merge branch 'Tracker-1000E' of github.com:meshtastic/firmware into Tracker-1000E
# Conflicts:
#	src/mesh/LR11x0Interface.cpp
2024-09-03 09:59:44 +02:00
Thomas Göttgens
7dad2286e2 trunk fmt 2024-09-03 09:58:27 +02:00
Thomas Göttgens
190c7ecdd4 Update Erase tool for legacy softdevices to V3 2024-09-03 09:26:41 +02:00
Thomas Göttgens
8598645931 - use setRfSwitchTable
- ditch Godmode
- fixes Signedness Error in Loop.
- add V3 factory erase for 7.3.0 softdevice
2024-09-03 09:26:41 +02:00
Thomas Göttgens
3bb1cb8f1d Update Erase tool for legacy softdevices to V3 2024-09-03 09:25:33 +02:00
Tom Fifield
cdea602181 Remove unused define (#4620)
Neither RF95_DIO2 nor LORA_DIO2 are found anywhere in the code.
2024-09-02 20:08:02 -05:00
Ben Meadors
b526a3ad53 Own node should be favorited and have zero hops away (#4618) 2024-09-02 17:51:02 -05:00
Thomas Göttgens
2f0c19ebea - use setRfSwitchTable
- ditch Godmode
- fixes Signedness Error in Loop.
- add V3 factory erase for 7.3.0 softdevice
2024-09-02 15:06:06 +02:00
Thomas Göttgens
06e27bb6c2 Merge pull request #4588 from S5NC/nukeunusedvariable
Nuke proxy variable
2024-09-02 10:28:33 +02:00
Thomas Göttgens
0588d69694 Merge pull request #4527 from geeksville/pr-fix4154
for #4154 Only enable Vext regulator when needed for either Screen or GPS
2024-09-02 10:24:39 +02:00
Thomas Göttgens
367d787d74 Merge branch 'master' into pr-fix4154 2024-09-02 10:24:31 +02:00
Thomas Göttgens
c8bf43de93 Merge pull request #4482 from dhskinner/BMP388
Add BMP388 as a new pressure and temp sensor
2024-09-02 10:23:57 +02:00
Thomas Göttgens
e543b61dd8 trunk fmt 2024-09-02 10:23:31 +02:00
Thomas Göttgens
1fc6cc2d6c Merge pull request #4610 from Coloradohusky/fix_chars
Fix display of certain Unicode symbols
2024-09-02 10:16:47 +02:00
Thomas Göttgens
719faf4f97 trunk fmt 2024-09-02 10:16:32 +02:00
Thomas Göttgens
3bf20dc3a6 Merge branch 'master' into pr-fix4154 2024-09-02 09:16:52 +02:00
David
d93425fde1 Merge branch 'master' into BMP388 2024-09-02 16:48:38 +10:00
Riley Nielsen
234e652a07 Fix switch 2024-09-01 20:43:56 -07:00
Riley Nielsen
cd16b7b00a fix display of degree symbol (+ other symbols) 2024-09-01 18:26:08 -07:00
Ben Meadors
24501c30c0 Update and rename test_simulator.yml to tests.yml 2024-09-01 11:33:41 -05:00
Ben Meadors
7d2f3a3425 Hello world for MeshTestic (#4607) 2024-09-01 11:29:34 -05:00
GUVWAF
56223710b5 More priorities for different types of MeshPackets (#4606) 2024-09-01 10:29:53 -05:00
github-actions[bot]
e45a358de0 [create-pull-request] automated change (#4594)
Co-authored-by: thebentern <9000580+thebentern@users.noreply.github.com>
2024-09-01 09:20:10 -05:00
Jonathan Bennett
b71e12c5e5 Phone admin work (#4599)
* Don't throw an error on the sessionkey admin tag

* Throw an error on packet sent to 0
2024-08-31 15:04:35 -05:00
David
eb1f80f520 Fix build issue with mutex 2024-08-31 19:40:54 +10:00
David
6c0911038a Merge branch 'master' into BMP388 2024-08-31 18:18:26 +10:00
David
644e213b13 Added a singleton wrapper for bmp3xx 2024-08-31 18:15:33 +10:00
Ben Meadors
33eb073535 Ignore (from)Net time on positions with an unknown or fixed location source (#4593)
* Ignore (from)Net time on positions with an unknown or fixed location source

* Dunk a trunk
2024-08-30 19:02:48 -05:00
Ben Meadors
8729cdb699 Merge branch 'master' into pr-fix4154 2024-08-30 16:31:47 -05:00
Ben Meadors
7475cc301e GPS_POWER_TOGGLE on T114 2024-08-30 15:37:39 -05:00
GUVWAF
eb071ec80d Set high priority for text messages (#4592) 2024-08-30 14:54:44 -05:00
github-actions[bot]
8144dcbc25 [create-pull-request] automated change (#4591)
Co-authored-by: GUVWAF <78759985+GUVWAF@users.noreply.github.com>
2024-08-30 13:46:51 -05:00
Jonathan Bennett
2b0113ae82 Consider an admin timestamp to be higher quality than from net (#4589) 2024-08-30 06:02:48 -05:00
Manuel
6a24566efb Lilygo T3S3 E-Paper support (#4569)
* t3s3 e-paper support

* remove GPS autodetect (which leads to crashes during startup when no GPS present)

* update EINK defines

* keep definitions for external GPS connector but disable GPS auto scan by default
2024-08-30 05:53:06 -05:00
S5NC
dd933e6bab Add bluetooth capability marker to some ESP32S3 boards (#4587)
* Update ESP32-S3-WROOM-1-N4.json

* Update CDEBYTE_EoRa-S3.json

* Update tlora-t3s3-v1.json
2024-08-30 05:51:46 -05:00
S5NC
79925406d6 Update variant.h 2024-08-30 03:18:43 +01:00
Jonathan Bennett
5bc17a9911 Key regen and MQTT fix (#4585)
* Add public key regen

* Properly label and handle PKI MQTT packets

* Extra debug message to indicate PKI_UNKNOWN_PUBKEY

* Ternary!

* Don't call non-existant function on stm32

* Actually fix STM32 compilation
2024-08-29 16:28:03 -05:00
David
a1d0af6636 Merge branch 'master' into BMP388 2024-08-30 07:25:27 +10:00
Mark Trevor Birss
22454c95c7 [BOARD] Add Minewsemi MS24SF1 nRF52840 SX1262 Module (SoftDevice 7.3.0) (#4584)
* Update architecture.h

* Add files via upload

* Add files via upload

* Update variant.h

* Update variant.h

* Update variant.cpp

* Update variant.cpp

* Update variant.cpp
2024-08-29 16:17:44 -05:00
Thomas Göttgens
b99fd93247 Merge pull request #4572 from And137/polish-oled
Support for Polish OLED characters
2024-08-29 22:30:22 +02:00
Thomas Göttgens
50631f96fc trunk fmt 2024-08-29 21:51:06 +02:00
And137
a6cc7041d3 Merge branch 'master' into polish-oled 2024-08-29 20:04:03 +02:00
Ben Meadors
171512d2f6 Fixed buzzer 2024-08-29 11:42:27 -05:00
David
db870dc17d Update extensions.json 2024-08-29 16:40:17 +02:00
David
28d0cef427 Undo inadvertent changes to extensions.json 2024-08-29 16:40:17 +02:00
David
6d2011c172 Revert "Update nightly.yml"
This reverts commit 44b975386d042b1810d5f3e1f2796af3ba7c118a.
2024-08-29 16:40:17 +02:00
David
47e1580a62 Integration test 2024-08-29 16:40:17 +02:00
David
fc1e60ac58 Initial upload 2024-08-29 16:40:17 +02:00
David
c02bbad9f3 Update nightly.yml 2024-08-29 16:40:17 +02:00
And137
f1f66cf54a Merge branch 'master' into polish-oled 2024-08-29 12:54:06 +02:00
Jonathan Bennett
92eae39a1b Move Time set from system to main (#4583) 2024-08-29 05:39:30 -05:00
geeksville
9e20b0e9b9 Merge branch 'master' into pr-fix4154 2024-08-28 11:32:29 -07:00
Kevin Hester
dc9f6e1360 fix CI warnings (and change CI comment to be correct) 2024-08-28 11:25:54 -07:00
Ben Meadors
a1bf0d8519 Add button secondary and enable scan-select on T190 (#4577) 2024-08-28 11:25:54 -07:00
Ben Meadors
f5633bf0c5 Fix T1000-E default to turn on buzzer for Ext. Notification (#4575) 2024-08-28 11:25:54 -07:00
Thomas Göttgens
ad931799c9 trunk upgrade (#4574) 2024-08-28 11:25:54 -07:00
Ben Meadors
3ad0af5ce8 Fix super tiny T1114 tft font size and fork repo to fix compiler warnings (#4573) 2024-08-28 11:25:54 -07:00
Rafael Cortês
545d32fcec Fix devcontainer Dockerfile build 2024-08-28 11:25:54 -07:00
Thomas Göttgens
94c3bb4a56 fix #4390 (#4571) 2024-08-28 11:25:54 -07:00
Ben Meadors
72c82c1c08 Add RAK4631 hex to firmware release 2024-08-28 11:25:54 -07:00
Power Li
cc93df27a5 set current time to system time in portduino build (#4556)
* set current time to system time in portduino build

* fix includes order

---------

Co-authored-by: Jonathan Bennett <jbennett@incomsystems.biz>
2024-08-28 11:25:54 -07:00
Jonathan Bennett
e3ce3a3a4f Don't compare nodeDB macaddr to owner.macaddr, because in rare cases that may be unset. (#4562)
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2024-08-28 11:25:54 -07:00
Jonathan Bennett
3c4d964334 Mask out random bits when doing queue ordering (#4561)
* Mask out random bits when doing queue ordering

* Parenthesis
2024-08-28 11:25:54 -07:00
Jonathan Bennett
574124aee5 Deal with admin_key being repeated (#4558) 2024-08-28 11:25:54 -07:00
John Milton
1fe80e0f30 Add support for Adafruit Feather RP2040 with RFM95. (#4451)
* Add support for Adafruit Feather RP2040 with RFM95.

* Update mesh.pb.h

dropping this change from the file generated by the protobuf

* Update mesh.pb.h

remove these reverting changes

* Update mesh.pb.h

oops, missed a comma
2024-08-28 11:25:54 -07:00
Ben Meadors
927a35ef51 Protos 2024-08-28 11:25:54 -07:00
Ben Meadors
c11a66030f Userlite mem comparison (#4552) 2024-08-28 11:25:54 -07:00
github-actions[bot]
059d5582d1 [create-pull-request] automated change (#4544)
Co-authored-by: thebentern <9000580+thebentern@users.noreply.github.com>
2024-08-28 11:25:54 -07:00
John Hollowell
17b2a83b44 Add devcontainer (#4491)
devcontainers can be used by IDEs/editors like VS Code to create a standardized development environment in a container
2024-08-28 11:25:54 -07:00
Nestpebble
eddb72705f add a .yml to setup a Gitpod instance quickly (#4551)
* Create .gitpod.yml

* Update .gitpod.yml
2024-08-28 11:25:54 -07:00
geeksville
9631a1be38 remove deprecated serial/bt logging options and unify in the new (#4516)
security option.  Per discussion in https://github.com/meshtastic/firmware/issues/4375
no need to preserve the old options when changing to this new simpler
single boolean because they were newish, rarely used and only for 'advanced'
developers.
2024-08-28 11:25:54 -07:00
Kevin Hester
8a9cc727a8 for #4154 use a binary gpio transformer to manage vext on heltec-tracker (saves power) 2024-08-28 11:25:54 -07:00
Kevin Hester
cdafa87cef add lateInitVariant() as a concept. see below for docs
(from src/extra_variants/README.md)

This directory tree is designed to solve two problems.

- The ESP32 arduino/platformio project doesn't support the nice "if initVariant() is found, call that after init" behavior of the nrf52 builds (they use initVariant() internally).
- Over the years a lot of 'board specific' init code has been added to init() in main.cpp. It would be great to have a general/clean mechanism to allow developers to specify board specific/unique code in a clean fashion without mucking in main.

So we are borrowing the initVariant() ideas here (by using weak gcc references). You can now define lateInitVariant() if your board needs it.

If you'd like a board specific variant to be run, add the variant.cpp file to an appropriately named
subdirectory and check for \_VARIANT_boardname in the cpp file (so that your code is only built for your board).
You'll need to define \_VARIANT_boardname in your corresponding variant.h file.
See existing boards for examples.

This approach has no added runtime cost.
2024-08-28 11:25:54 -07:00
Kevin Hester
5ce5b7b08b Older variant.h files (IMO sloppily) don't define VEXT_ON_VALUE
But in an attempt to avoid updating lots of files, make it default to LOW
2024-08-28 11:25:54 -07:00
Ben Meadors
b285aa5bd6 Dum dum zero comparision 2024-08-28 11:25:54 -07:00
Ben Meadors
9de0b7cfac Found more places to set explicit has_optional on position (#4542) 2024-08-28 11:25:54 -07:00
Ian McEwen
fe9a80a4e0 Use the '+' wildcard for MQTT rather than '#', to subscribe only to topics one nesting level deep (#4528) 2024-08-28 11:25:54 -07:00
Michael Gjelsø
de41a054b0 Initial support for RadioMaster Bandit. (#4523)
* Initial support for RadioMaster Bandit.

* Different lighting can be made for Button 1 & 2 on the Bandit.
Changes to AmbientLighting will turn off af shutdown().

* Trunk

* Trunk again.
2024-08-28 11:25:54 -07:00
Jonathan Bennett
9b2ef971c2 Fix copyPasta in NodeDB (#4538) 2024-08-28 11:25:54 -07:00
Jonathan Bennett
710fdbd4e5 Adds has_x bools to position packet. (#4540) 2024-08-28 11:25:54 -07:00
Ben Meadors
06175737cc Save nodedb after favoriting (or removing) (#4537) 2024-08-28 11:25:54 -07:00
And137
4a2a00a227 Merge branch 'meshtastic:master' into polish-oled 2024-08-28 14:58:27 +02:00
Ben Meadors
50f06840d7 Add button secondary and enable scan-select on T190 (#4577) 2024-08-28 07:54:50 -05:00
And137
6660aec79a Merge branch 'meshtastic:master' into polish-oled 2024-08-28 14:29:26 +02:00
Ben Meadors
a34170654c Fix T1000-E default to turn on buzzer for Ext. Notification (#4575) 2024-08-28 07:24:41 -05:00
And137
d611a38ce2 Merge branch 'meshtastic:master' into polish-oled 2024-08-28 13:59:30 +02:00
Thomas Göttgens
5b3579af52 trunk upgrade (#4574) 2024-08-28 06:51:44 -05:00
Ben Meadors
f27281d3fa Fix super tiny T1114 tft font size and fork repo to fix compiler warnings (#4573) 2024-08-28 06:43:30 -05:00
FW\AM5
59ecea507f Merge branch 'polish-oled' of https://github.com/And137/firmware into polish-oled 2024-08-28 13:25:33 +02:00
Thomas Göttgens
f7f21ecefd Merge pull request #4568 from mrfyda/fix/devcontainer-docker
Fix devcontainer Dockerfile build
2024-08-28 13:14:40 +02:00
Rafael Cortês
d1e64c74de Fix devcontainer Dockerfile build 2024-08-28 13:14:32 +02:00
FW\AM5
b8609ff130 Support for Polish OLED characters
Added support for Polish OLED characters.

- Custom FONT_SMALL ArialMT_Plain_10_PL

- Automatic selection between Polish and Ukrainian/Russian characters mapping depending on the -D OLED_{LANG_NAME} flage
2024-08-28 13:11:22 +02:00
FW\AM5
ef9ecec341 Support for Polish OLED characters
Added support for Polish OLED characters.

- Custom FONT_SMALL ArialMT_Plain_10_PL

- Automatic selection between Polish and Ukrainian/Russian characters mapping depending on the -D OLED_{LANG_NAME} flage
2024-08-28 13:10:19 +02:00
Thomas Göttgens
0ee9d375b3 fix #4390 (#4571) 2024-08-28 05:43:19 -05:00
Ben Meadors
50d778d281 Add RAK4631 hex to firmware release 2024-08-27 18:24:14 -05:00
Power Li
ab62590aa9 set current time to system time in portduino build (#4556)
* set current time to system time in portduino build

* fix includes order

---------

Co-authored-by: Jonathan Bennett <jbennett@incomsystems.biz>
2024-08-27 16:26:02 -05:00
Jonathan Bennett
ada61ae178 Don't compare nodeDB macaddr to owner.macaddr, because in rare cases that may be unset. (#4562)
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2024-08-27 14:49:58 -05:00
Jonathan Bennett
b9a8683a4b Mask out random bits when doing queue ordering (#4561)
* Mask out random bits when doing queue ordering

* Parenthesis
2024-08-26 15:48:47 -05:00
Jonathan Bennett
5824a8f4c1 Deal with admin_key being repeated (#4558) 2024-08-26 12:29:44 -05:00
John Milton
777ae2b99c Add support for Adafruit Feather RP2040 with RFM95. (#4451)
* Add support for Adafruit Feather RP2040 with RFM95.

* Update mesh.pb.h

dropping this change from the file generated by the protobuf

* Update mesh.pb.h

remove these reverting changes

* Update mesh.pb.h

oops, missed a comma
2024-08-26 10:28:08 -05:00
Ben Meadors
d0fd17134e Protos 2024-08-26 07:48:07 -05:00
Kevin Hester
e6163a59cd Make specifying VEXT_ON_VALUE manatory if using VEXT_ENABLE 2024-08-22 11:26:15 -07:00
Kevin Hester
5c5cbb23cf wiphone isn't setting a valid backlight enable pin
Therefore don't just randomly be writing to a GPIO numbered -1
Instead just don't try to control the backlight
NOTE: I don't have a 'wiphone' to test with, but I saw this via inspection
while cleaning up some other stuff.
2024-08-22 10:52:17 -07:00
Kevin Hester
f77c5f6a5b Don't create backlight instances when the variant hasn't specified a pin 2024-08-22 10:50:44 -07:00
Kevin Hester
2a7cf9d387 Remove redundant defintions of ST7789_BACKLIGHT_EN 2024-08-22 10:40:12 -07:00
Kevin Hester
db6e591c07 For #4154 - change TFT driver to use virtual GPIO for backlight enable 2024-08-22 10:38:19 -07:00
Kevin Hester
02c34e6214 Merge remote-tracking branch 'root/master' into pr-fix4154 2024-08-22 10:19:18 -07:00
Kevin Hester
5570b6bbc6 change GPS to use virtual GPIOs (for #4154) 2024-08-22 10:15:23 -07:00
Kevin Hester
2dda640d27 Remove unneeded VGNSS_CTRL_V03 2024-08-22 09:33:43 -07:00
Kevin Hester
5ccb6df142 Remove all sorts of redundant VEXT_ENABLE ifdefs 2024-08-22 09:28:41 -07:00
Kevin Hester
3ae8aadaf0 Merge the three redundant backlight enables into the single TFT_BL flag 2024-08-22 09:15:59 -07:00
Kevin Hester
7fb9b094d5 Remove redundant ST7735_BL variant defs.
No need for _V05 and _V03 definitions - I think there was a slight misunderstanding
on how variant files are supposed to _decrease_ #ifdef code in the cpp files.
2024-08-22 08:59:46 -07:00
Kevin Hester
d017fc7a5d for #4154 use internal pull-ups to power ADC_Ctrl
* Currently only on heltec tracker, but could use ADC_USE_PULLUP on other boards that could benefit
* Thanks @todd-herbert and @StevenCellist for the instructions ;-)
* Remove nasty Heltec_wireless #ifdefs that got somehow added to Power.cpp, instead use proper variant defs
* Cleanup adc enable/disable code a bit for less copy-paste cruft
2024-08-21 16:53:12 -07:00
113 changed files with 25290 additions and 618 deletions

View File

@@ -12,6 +12,7 @@ RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \
libssl-dev \
libulfius-dev \
libyaml-cpp-dev \
pipx \
pkg-config \
python3 \
python3-pip \
@@ -21,4 +22,4 @@ RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \
zip \
&& apt-get clean && rm -rf /var/lib/apt/lists/*
RUN pip3 install --no-cache-dir -U platformio==6.1.15
RUN pipx install platformio==6.1.15

View File

@@ -10,7 +10,7 @@ jobs:
build-native:
runs-on: ubuntu-latest
steps:
- name: Install libbluetooth
- name: Install libs needed for native build
shell: bash
run: |
sudo apt-get update --fix-missing

View File

@@ -1,4 +1,4 @@
name: Test Simulator
name: End to end tests
on:
schedule:
@@ -55,3 +55,37 @@ jobs:
name: PlatformIO Tests
path: testreport.xml
reporter: java-junit
hardware-tests:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Upgrade python tools
shell: bash
run: |
python -m pip install --upgrade pip
pip install -U --no-build-isolation --no-cache-dir "setuptools<72"
pip install -U platformio adafruit-nrfutil --no-build-isolation
pip install -U poetry --no-build-isolation
pip install -U meshtastic --pre --no-build-isolation
- name: Upgrade platformio
shell: bash
run: |
pio upgrade
- name: Setup pnpm
uses: pnpm/action-setup@v2
with:
version: latest
- name: Install Dependencies
run: pnpm install
- name: Setup devices
run: pnpm run setup
- name: Execute end to end tests on connected hardware
run: pnpm run test

3
.gitmodules vendored
View File

@@ -1,3 +1,6 @@
[submodule "protobufs"]
path = protobufs
url = https://github.com/meshtastic/protobufs.git
[submodule "meshtestic"]
path = meshtestic
url = https://github.com/meshtastic/meshTestic

View File

@@ -1,36 +1,36 @@
version: 0.1
cli:
version: 1.22.2
version: 1.22.3
plugins:
sources:
- id: trunk
ref: v1.5.0
ref: v1.6.2
uri: https://github.com/trunk-io/plugins
lint:
enabled:
- trufflehog@3.76.3
- trufflehog@3.81.9
- yamllint@1.35.1
- bandit@1.7.8
- checkov@3.2.95
- bandit@1.7.9
- checkov@3.2.238
- terrascan@1.19.1
- trivy@0.51.1
- trivy@0.54.1
#- trufflehog@3.63.2-rc0
- taplo@0.8.1
- ruff@0.4.4
- taplo@0.9.3
- ruff@0.6.2
- isort@5.13.2
- markdownlint@0.40.0
- oxipng@9.1.1
- markdownlint@0.41.0
- oxipng@9.1.2
- svgo@3.3.2
- actionlint@1.7.0
- flake8@7.0.0
- actionlint@1.7.1
- flake8@7.1.1
- hadolint@2.12.0
- shfmt@3.6.0
- shellcheck@0.10.0
- black@24.4.2
- black@24.8.0
- git-diff-check
- gitleaks@8.18.2
- gitleaks@8.18.4
- clang-format@16.0.3
- prettier@3.2.5
- prettier@3.3.3
ignore:
- linters: [ALL]
paths:

View File

@@ -2,8 +2,9 @@
// See http://go.microsoft.com/fwlink/?LinkId=827846
// for the documentation about the extensions.json format
"recommendations": [
"ms-vscode.cpptools",
"platformio.platformio-ide",
"trunk.io"
"platformio.platformio-ide"
],
"unwantedRecommendations": [
"ms-vscode.cpptools-extension-pack"
]
}

Binary file not shown.

Binary file not shown.

View File

@@ -46,3 +46,8 @@ else
cp bin/device-update.* $OUTDIR
cp bin/*.uf2 $OUTDIR
fi
if (echo $1 | grep -q "rak4631"); then
echo "Copying hex file"
cp .pio/build/$1/firmware.hex $OUTDIR/$basename.hex
fi

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -39,4 +39,4 @@ def readProps(prefsLoc):
return verObj
# print("path is" + ','.join(sys.path))
# print("path is" + ','.join(sys.path))

View File

@@ -19,7 +19,7 @@
"mcu": "esp32s3",
"variant": "CDEBYTE_EoRa-S3"
},
"connectivity": ["wifi"],
"connectivity": ["wifi", "bluetooth"],
"debug": {
"openocd_target": "esp32s3.cfg"
},

View File

@@ -19,7 +19,7 @@
"mcu": "esp32s3",
"variant": "ESP32-S3-WROOM-1-N4"
},
"connectivity": ["wifi"],
"connectivity": ["wifi", "bluetooth"],
"debug": {
"default_tool": "esp-builtin",
"onboard_tools": ["esp-builtin"],

58
boards/ms24sf1.json Normal file
View File

@@ -0,0 +1,58 @@
{
"build": {
"arduino": {
"ldscript": "nrf52840_s140_v7.ld"
},
"core": "nRF5",
"cpu": "cortex-m4",
"extra_flags": "-DARDUINO_WIO_WM1110 -DNRF52840_XXAA",
"f_cpu": "64000000L",
"hwids": [
["0x239A", "0x8029"],
["0x239A", "0x0029"],
["0x239A", "0x002A"],
["0x239A", "0x802A"]
],
"usb_product": "MS24SF1-BOOT",
"mcu": "nrf52840",
"variant": "MINEWSEMI_MS24SF1_SX1262",
"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"
},
"frameworks": ["arduino"],
"name": "MINEWSEMI_MS24SF1_SX1262",
"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://en.minewsemi.com/lora-module/nrf52840-sx1262-ms24sf1",
"vendor": "Minesemi"
}

View File

@@ -19,7 +19,7 @@
"mcu": "esp32s3",
"variant": "tlora-t3s3-v1"
},
"connectivity": ["wifi"],
"connectivity": ["wifi", "bluetooth"],
"debug": {
"openocd_target": "esp32s3.cfg"
},

1
meshtestic Submodule

Submodule meshtestic added at 31ee3d90c8

View File

@@ -81,12 +81,14 @@ build_flags = -Wno-missing-field-initializers
-DRADIOLIB_EXCLUDE_APRS
-DRADIOLIB_EXCLUDE_LORAWAN
-DMESHTASTIC_EXCLUDE_DROPZONE=1
;-D OLED_PL
monitor_speed = 115200
monitor_filters = direct
lib_deps =
jgromes/RadioLib@~6.6.0
; jgromes/RadioLib@~6.6.0
https://github.com/jgromes/RadioLib.git#3115fc2d6700a9aee05888791ac930a910f2628f
https://github.com/meshtastic/esp8266-oled-ssd1306.git#e16cee124fe26490cb14880c679321ad8ac89c95 ; ESP8266_SSD1306
https://github.com/mathertel/OneButton@~2.6.1 ; OneButton library for non-blocking button debounce
https://github.com/meshtastic/arduino-fsm.git#7db3702bf0cfe97b783d6c72595e3f38e0b19159
@@ -130,6 +132,7 @@ lib_deps =
adafruit/Adafruit BMP280 Library@^2.6.8
adafruit/Adafruit BMP085 Library@^1.2.4
adafruit/Adafruit BME280 Library@^2.2.2
adafruit/Adafruit BMP3XX Library@^2.1.5
adafruit/Adafruit MCP9808 Library@^2.0.0
adafruit/Adafruit INA260 Library@^1.5.0
adafruit/Adafruit INA219@^1.2.0
@@ -157,4 +160,4 @@ lib_deps =
mprograms/QMC5883LCompass@^1.2.0
https://github.com/meshtastic/DFRobot_LarkWeatherStation#dee914270dc7cb3e43fbf034edd85a63a16a12ee
https://github.com/meshtastic/DFRobot_LarkWeatherStation#dee914270dc7cb3e43fbf034edd85a63a16a12ee

View File

@@ -10,6 +10,13 @@ void GpioVirtPin::set(bool value)
}
}
void GpioHwPin::set(bool value)
{
// if (num == 3) LOG_DEBUG("Setting pin %d to %d\n", num, value);
pinMode(num, OUTPUT);
digitalWrite(num, value);
}
GpioTransformer::GpioTransformer(GpioPin *outPin) : outPin(outPin) {}
void GpioTransformer::set(bool value)
@@ -17,7 +24,7 @@ void GpioTransformer::set(bool value)
outPin->set(value);
}
GpioNotTransformer::GpioNotTransformer(GpioVirtPin *inPin, GpioPin *outPin) : GpioTransformer(outPin), inPin(inPin)
GpioUnaryTransformer::GpioUnaryTransformer(GpioVirtPin *inPin, GpioPin *outPin) : GpioTransformer(outPin), inPin(inPin)
{
assert(!inPin->dependentPin); // We only allow one dependent pin
inPin->dependentPin = this;
@@ -27,6 +34,18 @@ GpioNotTransformer::GpioNotTransformer(GpioVirtPin *inPin, GpioPin *outPin) : Gp
// update();
}
/**
* Update the output pin based on the current state of the input pin.
*/
void GpioUnaryTransformer::update()
{
auto p = inPin->get();
if (p == GpioVirtPin::PinState::Unset)
return; // Not yet fully initialized
set(p);
}
/**
* Update the output pin based on the current state of the input pin.
*/
@@ -69,6 +88,7 @@ void GpioBinaryTransformer::update()
newValue = (GpioVirtPin::PinState)(p1 && p2);
break;
case Or:
// LOG_DEBUG("Doing GPIO OR\n");
newValue = (GpioVirtPin::PinState)(p1 || p2);
break;
case Xor:

View File

@@ -29,7 +29,7 @@ class GpioHwPin : public GpioPin
public:
explicit GpioHwPin(uint32_t num) : num(num) {}
void set(bool value) { digitalWrite(num, value); }
void set(bool value);
};
class GpioTransformer;
@@ -42,7 +42,7 @@ class GpioBinaryTransformer;
class GpioVirtPin : public GpioPin
{
friend class GpioBinaryTransformer;
friend class GpioNotTransformer;
friend class GpioUnaryTransformer;
public:
enum PinState { On = true, Off = false, Unset = 2 };
@@ -79,12 +79,31 @@ class GpioTransformer
};
/**
* A transformer that performs a unary NOT operation from an input.
* A transformer that just drives a hw pin based on a virtual pin.
*/
class GpioNotTransformer : public GpioTransformer
class GpioUnaryTransformer : public GpioTransformer
{
public:
GpioNotTransformer(GpioVirtPin *inPin, GpioPin *outPin);
GpioUnaryTransformer(GpioVirtPin *inPin, GpioPin *outPin);
protected:
friend class GpioVirtPin;
/**
* Update the output pin based on the current state of the input pin.
*/
virtual void update();
GpioVirtPin *inPin;
};
/**
* A transformer that performs a unary NOT operation from an input.
*/
class GpioNotTransformer : public GpioUnaryTransformer
{
public:
GpioNotTransformer(GpioVirtPin *inPin, GpioPin *outPin) : GpioUnaryTransformer(inPin, outPin) {}
protected:
friend class GpioVirtPin;
@@ -93,9 +112,6 @@ class GpioNotTransformer : public GpioTransformer
* Update the output pin based on the current state of the input pin.
*/
void update();
private:
GpioVirtPin *inPin;
};
/**

View File

@@ -136,6 +136,30 @@ using namespace meshtastic;
*/
static HasBatteryLevel *batteryLevel; // Default to NULL for no battery level sensor
static void adcEnable()
{
#ifdef ADC_CTRL // enable adc voltage divider when we need to read
#ifdef ADC_USE_PULLUP
pinMode(ADC_CTRL, INPUT_PULLUP);
#else
pinMode(ADC_CTRL, OUTPUT);
digitalWrite(ADC_CTRL, ADC_CTRL_ENABLED);
#endif
delay(10);
#endif
}
static void adcDisable()
{
#ifdef ADC_CTRL // disable adc voltage divider when we need to read
#ifdef ADC_USE_PULLUP
pinMode(ADC_CTRL, INPUT_PULLDOWN);
#else
digitalWrite(ADC_CTRL, !ADC_CTRL_ENABLED);
#endif
#endif
}
/**
* A simple battery level sensor that assumes the battery voltage is attached via a voltage-divider to an analog input
*/
@@ -226,25 +250,19 @@ class AnalogBatteryLevel : public HasBatteryLevel
uint32_t raw = 0;
float scaled = 0;
adcEnable();
#ifdef ARCH_ESP32 // ADC block for espressif platforms
raw = espAdcRead();
scaled = esp_adc_cal_raw_to_voltage(raw, adc_characs);
scaled *= operativeAdcMultiplier;
#else // block for all other platforms
#ifdef ADC_CTRL // enable adc voltage divider when we need to read
pinMode(ADC_CTRL, OUTPUT);
digitalWrite(ADC_CTRL, ADC_CTRL_ENABLED);
delay(10);
#endif
#else // block for all other platforms
for (uint32_t i = 0; i < BATTERY_SENSE_SAMPLES; i++) {
raw += analogRead(BATTERY_PIN);
}
raw = raw / BATTERY_SENSE_SAMPLES;
scaled = operativeAdcMultiplier * ((1000 * AREF_VOLTAGE) / pow(2, BATTERY_SENSE_RESOLUTION_BITS)) * raw;
#ifdef ADC_CTRL // disable adc voltage divider when we need to read
digitalWrite(ADC_CTRL, !ADC_CTRL_ENABLED);
#endif
#endif
adcDisable();
if (!initial_read_done) {
// Flush the smoothing filter with an ADC reading, if the reading is plausibly correct
@@ -275,11 +293,6 @@ class AnalogBatteryLevel : public HasBatteryLevel
uint8_t raw_c = 0; // raw reading counter
#ifndef BAT_MEASURE_ADC_UNIT // ADC1
#ifdef ADC_CTRL // enable adc voltage divider when we need to read
pinMode(ADC_CTRL, OUTPUT);
digitalWrite(ADC_CTRL, ADC_CTRL_ENABLED);
delay(10);
#endif
for (int i = 0; i < BATTERY_SENSE_SAMPLES; i++) {
int val_ = adc1_get_raw(adc_channel);
if (val_ >= 0) { // save only valid readings
@@ -288,18 +301,7 @@ class AnalogBatteryLevel : public HasBatteryLevel
}
// delayMicroseconds(100);
}
#ifdef ADC_CTRL // disable adc voltage divider when we need to read
digitalWrite(ADC_CTRL, !ADC_CTRL_ENABLED);
#endif
#else // ADC2
#ifdef ADC_CTRL
#if defined(HELTEC_WIRELESS_PAPER) || defined(HELTEC_WIRELESS_PAPER_V1_0)
pinMode(ADC_CTRL, OUTPUT);
digitalWrite(ADC_CTRL, LOW); // ACTIVE LOW
delay(10);
#endif
#endif // End ADC_CTRL
#else // ADC2
#ifdef CONFIG_IDF_TARGET_ESP32S3 // ESP32S3
// ADC2 wifi bug workaround not required, breaks compile
// On ESP32S3, ADC2 can take turns with Wifi (?)
@@ -334,12 +336,6 @@ class AnalogBatteryLevel : public HasBatteryLevel
}
#endif // BAT_MEASURE_ADC_UNIT
#ifdef ADC_CTRL
#if defined(HELTEC_WIRELESS_PAPER) || defined(HELTEC_WIRELESS_PAPER_V1_0)
digitalWrite(ADC_CTRL, HIGH);
#endif
#endif // End ADC_CTRL
#endif // End BAT_MEASURE_ADC_UNIT
return (raw / (raw_c < 1 ? 1 : raw_c));
}

View File

@@ -3,5 +3,4 @@
#define RF95_RESET LORA_RESET
#define RF95_IRQ LORA_DIO0 // on SX1262 version this is a no connect DIO0
#define RF95_DIO1 LORA_DIO1 // Note: not really used for RF95, but used for pure SX127x
#define RF95_DIO2 LORA_DIO2 // Note: not really used for RF95
#endif
#endif

View File

@@ -177,6 +177,11 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
/* Step #1: offer chance for variant-specific defines */
#include "variant.h"
#if defined(VEXT_ENABLE) && !defined(VEXT_ON_VALUE)
// Older variant.h files might not be defining this value, so stay with the old default
#define VEXT_ON_VALUE LOW
#endif
#ifndef GPS_BAUDRATE
#define GPS_BAUDRATE 9600
#endif

View File

@@ -24,6 +24,7 @@ class ScanI2C
BME_280,
BMP_280,
BMP_085,
BMP_3XX,
INA260,
INA219,
INA3221,

View File

@@ -267,8 +267,19 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize)
type = BMP_085;
break;
default:
LOG_INFO("BMP-280 sensor found at address 0x%x\n", (uint8_t)addr.address);
type = BMP_280;
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x00), 1); // GET_ID
switch (registerValue) {
case 0x50: // BMP-388 should be 0x50
LOG_INFO("BMP-388 sensor found at address 0x%x\n", (uint8_t)addr.address);
type = BMP_3XX;
break;
case 0x58: // BMP-280 should be 0x58
default:
LOG_INFO("BMP-280 sensor found at address 0x%x\n", (uint8_t)addr.address);
type = BMP_280;
break;
}
break;
}
break;
#ifndef HAS_NCP5623

View File

@@ -2,6 +2,7 @@
#if !MESHTASTIC_EXCLUDE_GPS
#include "Default.h"
#include "GPS.h"
#include "GpioLogic.h"
#include "NodeDB.h"
#include "PowerMon.h"
#include "RTC.h"
@@ -875,16 +876,8 @@ void GPS::writePinEN(bool on)
if (HW_VENDOR == meshtastic_HardwareModel_RAK4631 && (rotaryEncoderInterruptImpl1 || upDownInterruptImpl1))
return;
// Abort: if pin unset
if (!en_gpio)
return;
// Determine new value for the pin
bool val = GPS_EN_ACTIVE ? on : !on;
// Write and log
pinMode(en_gpio, OUTPUT);
digitalWrite(en_gpio, val);
enablePin->set(on);
#ifdef GPS_EXTRAVERBOSE
LOG_DEBUG("Pin EN %s\n", val == HIGH ? "HIGH" : "LOW");
#endif
@@ -1259,9 +1252,6 @@ GnssModel_t GPS::probe(int serialSpeed)
LOG_INFO("Aioha AG3335 detected, using AG3335 Module\n");
return GNSS_MODEL_AG3335;
}
// Get version information for Airoha AG3335
clearBuffer();
_serial_gps->write("$PMTK605*31\r\n");
// Get version information
clearBuffer();
@@ -1421,7 +1411,20 @@ GPS *GPS::createGps()
GPS *new_gps = new GPS;
new_gps->rx_gpio = _rx_gpio;
new_gps->tx_gpio = _tx_gpio;
new_gps->en_gpio = _en_gpio;
GpioVirtPin *virtPin = new GpioVirtPin();
new_gps->enablePin = virtPin; // Always at least populate a virtual pin
if (_en_gpio) {
GpioPin *p = new GpioHwPin(_en_gpio);
if (!GPS_EN_ACTIVE) { // Need to invert the pin before hardware
new GpioNotTransformer(
virtPin, p); // We just leave this created object on the heap so it can stay watching virtPin and driving en_gpio
} else {
new GpioUnaryTransformer(
virtPin, p); // We just leave this created object on the heap so it can stay watching virtPin and driving en_gpio
}
}
#ifdef PIN_GPS_PPS
// pulse per second
@@ -1837,4 +1840,4 @@ void GPS::toggleGpsMode()
enable();
}
}
#endif // Exclude GPS
#endif // Exclude GPS

View File

@@ -3,6 +3,7 @@
#if !MESHTASTIC_EXCLUDE_GPS
#include "GPSStatus.h"
#include "GpioLogic.h"
#include "Observer.h"
#include "TinyGPS++.h"
#include "concurrency/OSThread.h"
@@ -73,7 +74,6 @@ class GPS : private concurrency::OSThread
uint32_t lastWakeStartMsec = 0, lastSleepStartMsec = 0, lastFixStartMsec = 0;
uint32_t rx_gpio = 0;
uint32_t tx_gpio = 0;
uint32_t en_gpio = 0;
int speedSelect = 0;
int probeTries = 2;
@@ -152,6 +152,13 @@ class GPS : private concurrency::OSThread
meshtastic_Position p = meshtastic_Position_init_default;
/** This is normally bound to config.position.gps_en_gpio but some rare boards (like heltec tracker) need more advanced
* implementations. Those boards will set this public variable to a custom implementation.
*
* Normally set by GPS::createGPS()
*/
GpioVirtPin *enablePin = NULL;
GPS() : concurrency::OSThread("GPS") {}
virtual ~GPS();
@@ -303,4 +310,4 @@ class GPS : private concurrency::OSThread
};
extern GPS *gps;
#endif // Exclude GPS
#endif // Exclude GPS

View File

@@ -157,7 +157,7 @@ bool EInkDisplay::connect()
}
#elif defined(HELTEC_WIRELESS_PAPER_V1_0) || defined(HELTEC_WIRELESS_PAPER) || defined(HELTEC_VISION_MASTER_E213) || \
defined(HELTEC_VISION_MASTER_E290)
defined(HELTEC_VISION_MASTER_E290) || defined(TLORA_T3S3_EPAPER)
{
// Start HSPI
hspi = new SPIClass(HSPI);

View File

@@ -68,7 +68,7 @@ class EInkDisplay : public OLEDDisplay
// If display uses HSPI
#if defined(HELTEC_WIRELESS_PAPER) || defined(HELTEC_WIRELESS_PAPER_V1_0) || defined(HELTEC_VISION_MASTER_E213) || \
defined(HELTEC_VISION_MASTER_E290)
defined(HELTEC_VISION_MASTER_E290) || defined(TLORA_T3S3_EPAPER)
SPIClass *hspi = NULL;
#endif

View File

@@ -123,7 +123,7 @@ static bool heartbeat = false;
/// Check if the display can render a string (detect special chars; emoji)
static bool haveGlyphs(const char *str)
{
#if defined(OLED_UA) || defined(OLED_RU)
#if defined(OLED_PL) || defined(OLED_UA) || defined(OLED_RU)
// Don't want to make any assumptions about custom language support
return true;
#endif
@@ -1093,7 +1093,8 @@ 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(ST7735_CS) || defined(ST7789_CS) || defined(HX8357_CS)) && \
#if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7735_CS) || defined(ST7789_CS) || defined(USE_ST7789) || \
defined(HX8357_CS)) && \
!defined(DISPLAY_FORCE_SMALL_FONTS)
display->drawFastImage(x, y + 3, 8, 8, imgUser);
#else
@@ -2414,7 +2415,8 @@ void DebugInfo::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16
#ifdef ARCH_ESP32
if (millis() - storeForwardModule->lastHeartbeat >
(storeForwardModule->heartbeatInterval * 1200)) { // no heartbeat, overlap a bit
#if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7735_CS) || defined(ST7789_CS) || defined(HX8357_CS)) && \
#if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7735_CS) || defined(ST7789_CS) || defined(USE_ST7789) || \
defined(HX8357_CS)) && \
!defined(DISPLAY_FORCE_SMALL_FONTS)
display->drawFastImage(x + SCREEN_WIDTH - 14 - display->getStringWidth(ourId), y + 3 + FONT_HEIGHT_SMALL, 12, 8,
imgQuestionL1);
@@ -2425,7 +2427,8 @@ void DebugInfo::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16
imgQuestion);
#endif
} else {
#if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7735_CS) || defined(ST7789_CS) || defined(HX8357_CS)) && \
#if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7735_CS) || defined(ST7789_CS) || defined(USE_ST7789) || \
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);
@@ -2439,8 +2442,8 @@ void DebugInfo::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16
#endif
} else {
// TODO: Raspberry Pi supports more than just the one screen size
#if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7735_CS) || defined(ST7789_CS) || defined(HX8357_CS) || \
ARCH_PORTDUINO) && \
#if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7735_CS) || defined(ST7789_CS) || defined(USE_ST7789) || \
defined(HX8357_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);

View File

@@ -309,7 +309,7 @@ class Screen : public concurrency::OSThread
static char customFontTableLookup(const uint8_t ch)
{
// UTF-8 to font table index converter
// Code form http://playground.arduino.cc/Main/Utf8ascii
// Code from http://playground.arduino.cc/Main/Utf8ascii
static uint8_t LASTCHAR;
static bool SKIPREST; // Only display a single unconvertable-character symbol per sequence of unconvertable characters
@@ -322,11 +322,57 @@ class Screen : public concurrency::OSThread
uint8_t last = LASTCHAR; // get last char
LASTCHAR = ch;
switch (last) { // conversion depending on first UTF8-character
switch (last) {
case 0xC2: {
SKIPREST = false;
return (uint8_t)ch;
}
}
// We want to strip out prefix chars for two-byte char formats
if (ch == 0xC2)
return (uint8_t)0;
#if defined(OLED_PL)
switch (last) {
case 0xC3: {
if (ch == 147)
return (uint8_t)(ch); // Ó
else if (ch == 179)
return (uint8_t)(148); // ó
else
return (uint8_t)(ch | 0xC0);
break;
}
case 0xC4: {
SKIPREST = false;
return (uint8_t)(ch);
}
case 0xC5: {
SKIPREST = false;
if (ch == 132)
return (uint8_t)(136); // ń
else if (ch == 186)
return (uint8_t)(137); // ź
else
return (uint8_t)(ch);
break;
}
}
// We want to strip out prefix chars for two-byte char formats
if (ch == 0xC2 || ch == 0xC3 || ch == 0xC4 || ch == 0xC5)
return (uint8_t)0;
#endif
#if defined(OLED_UA) || defined(OLED_RU)
switch (last) {
case 0xC3: {
SKIPREST = false;
return (uint8_t)(ch | 0xC0);
@@ -376,6 +422,8 @@ class Screen : public concurrency::OSThread
if (ch == 0xC2 || ch == 0xC3 || ch == 0x82 || ch == 0xD0 || ch == 0xD1)
return (uint8_t)0;
#endif
// If we already returned an unconvertable-character symbol for this unconvertable-character sequence, return NULs for the
// rest of it
if (SKIPREST)

View File

@@ -1,5 +1,9 @@
#pragma once
#ifdef OLED_PL
#include "graphics/fonts/OLEDDisplayFontsPL.h"
#endif
#ifdef OLED_RU
#include "graphics/fonts/OLEDDisplayFontsRU.h"
#endif
@@ -8,13 +12,17 @@
#include "graphics/fonts/OLEDDisplayFontsUA.h"
#endif
#if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7735_CS) || defined(ST7789_CS) || defined(HX8357_CS)) && \
#if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7735_CS) || defined(ST7789_CS) || defined(USE_ST7789) || \
defined(HX8357_CS)) && \
!defined(DISPLAY_FORCE_SMALL_FONTS)
// The screen is bigger so use bigger fonts
#define FONT_SMALL ArialMT_Plain_16 // Height: 19
#define FONT_MEDIUM ArialMT_Plain_24 // Height: 28
#define FONT_LARGE ArialMT_Plain_24 // Height: 28
#else
#ifdef OLED_PL
#define FONT_SMALL ArialMT_Plain_10_PL
#else
#ifdef OLED_RU
#define FONT_SMALL ArialMT_Plain_10_RU
#else
@@ -24,6 +32,7 @@
#define FONT_SMALL ArialMT_Plain_10 // Height: 13
#endif
#endif
#endif
#define FONT_MEDIUM ArialMT_Plain_16 // Height: 19
#define FONT_LARGE ArialMT_Plain_24 // Height: 28
#endif

View File

@@ -21,10 +21,6 @@ extern SX1509 gpioExtender;
#if defined(ST7735S)
#include <LovyanGFX.hpp> // Graphics and font library for ST7735 driver chip
#if defined(ST7735_BACKLIGHT_EN) && !defined(TFT_BL)
#define TFT_BL ST7735_BACKLIGHT_EN
#endif
#ifndef TFT_INVERT
#define TFT_INVERT true
#endif
@@ -91,24 +87,20 @@ class LGFX : public lgfx::LGFX_Device
_panel_instance.config(cfg);
}
#ifdef TFT_BL
// Set the backlight control
{
auto cfg = _light_instance.config(); // Gets a structure for backlight settings.
#ifdef ST7735_BL_V03
cfg.pin_bl = ST7735_BL_V03;
#elif defined(ST7735_BL_V05)
cfg.pin_bl = ST7735_BL_V05;
#else
cfg.pin_bl = ST7735_BL; // Pin number to which the backlight is connected
#endif
cfg.invert = true; // true to invert the brightness of the backlight
cfg.pin_bl = TFT_BL; // Pin number to which the backlight is connected
cfg.invert = true; // 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
setPanel(&_panel_instance);
}
@@ -131,10 +123,6 @@ static void rak14014_tpIntHandle(void)
#elif defined(ST7789_CS)
#include <LovyanGFX.hpp> // Graphics and font library for ST7735 driver chip
#if defined(ST7789_BACKLIGHT_EN) && !defined(TFT_BL)
#define TFT_BL ST7789_BACKLIGHT_EN
#endif
class LGFX : public lgfx::LGFX_Device
{
lgfx::Panel_ST7789 _panel_instance;
@@ -204,6 +192,7 @@ class LGFX : public lgfx::LGFX_Device
_panel_instance.config(cfg);
}
#ifdef ST7789_BL
// Set the backlight control. (delete if not necessary)
{
auto cfg = _light_instance.config(); // Gets a structure for backlight settings.
@@ -215,6 +204,7 @@ class LGFX : public lgfx::LGFX_Device
_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.
@@ -324,6 +314,7 @@ class LGFX : public lgfx::LGFX_Device
_panel_instance.config(cfg);
}
#ifdef TFT_BL
// Set the backlight control
{
auto cfg = _light_instance.config(); // Gets a structure for backlight settings.
@@ -336,6 +327,7 @@ class LGFX : public lgfx::LGFX_Device
_light_instance.config(cfg);
_panel_instance.setLight(&_light_instance); // Set the backlight on the panel.
}
#endif
setPanel(&_panel_instance);
}
@@ -521,9 +513,26 @@ static LGFX *tft = nullptr;
extern unPhone unphone;
#endif
GpioPin *TFTDisplay::backlightEnable = NULL;
TFTDisplay::TFTDisplay(uint8_t address, int sda, int scl, OLEDDISPLAY_GEOMETRY geometry, HW_I2C i2cBus)
{
LOG_DEBUG("TFTDisplay!\n");
#ifdef TFT_BL
GpioPin *p = new GpioHwPin(TFT_BL);
if (!TFT_BACKLIGHT_ON) { // Need to invert the pin before hardware
auto virtPin = new GpioVirtPin();
new GpioNotTransformer(
virtPin, p); // We just leave this created object on the heap so it can stay watching virtPin and driving en_gpio
p = virtPin;
}
#else
GpioPin *p = new GpioVirtPin(); // Just simulate a pin
#endif
backlightEnable = p;
#if ARCH_PORTDUINO
if (settingsMap[displayRotate]) {
setGeometry(GEOMETRY_RAWMODE, settingsMap[configNames::displayHeight], settingsMap[configNames::displayWidth]);
@@ -577,24 +586,15 @@ void TFTDisplay::sendCommand(uint8_t com)
// handle display on/off directly
switch (com) {
case DISPLAYON: {
// LOG_DEBUG("Display on\n");
backlightEnable->set(true);
#if ARCH_PORTDUINO
display(true);
if (settingsMap[displayBacklight] > 0)
digitalWrite(settingsMap[displayBacklight], TFT_BACKLIGHT_ON);
#elif defined(ST7735_BL_V03)
digitalWrite(ST7735_BL_V03, TFT_BACKLIGHT_ON);
#elif defined(ST7735_BL_V05)
pinMode(ST7735_BL_V05, OUTPUT);
digitalWrite(ST7735_BL_V05, TFT_BACKLIGHT_ON);
#elif !defined(RAK14014) && !defined(M5STACK) && !defined(UNPHONE)
tft->wakeup();
tft->powerSaveOff();
#elif defined(TFT_BL) && defined(TFT_BACKLIGHT_ON)
digitalWrite(TFT_BL, TFT_BACKLIGHT_ON);
#endif
#ifdef VTFT_CTRL_V03
digitalWrite(VTFT_CTRL_V03, LOW);
#endif
#ifdef VTFT_CTRL
@@ -610,25 +610,17 @@ void TFTDisplay::sendCommand(uint8_t com)
break;
}
case DISPLAYOFF: {
// LOG_DEBUG("Display off\n");
backlightEnable->set(false);
#if ARCH_PORTDUINO
tft->clear();
if (settingsMap[displayBacklight] > 0)
digitalWrite(settingsMap[displayBacklight], !TFT_BACKLIGHT_ON);
#elif defined(ST7735_BL_V03)
digitalWrite(ST7735_BL_V03, !TFT_BACKLIGHT_ON);
#elif defined(ST7735_BL_V05)
pinMode(ST7735_BL_V05, OUTPUT);
digitalWrite(ST7735_BL_V05, !TFT_BACKLIGHT_ON);
#elif !defined(RAK14014) && !defined(M5STACK) && !defined(UNPHONE)
tft->sleep();
tft->powerSaveOn();
#elif defined(TFT_BL) && defined(TFT_BACKLIGHT_ON)
digitalWrite(TFT_BL, !TFT_BACKLIGHT_ON);
#endif
#ifdef VTFT_CTRL_V03
digitalWrite(VTFT_CTRL_V03, HIGH);
#endif
#ifdef VTFT_CTRL
digitalWrite(VTFT_CTRL, HIGH);
#endif
@@ -712,20 +704,9 @@ bool TFTDisplay::connect()
tft = new LGFX;
#endif
#ifdef TFT_BL
pinMode(TFT_BL, OUTPUT);
digitalWrite(TFT_BL, TFT_BACKLIGHT_ON);
// pinMode(PIN_3V3_EN, OUTPUT);
// digitalWrite(PIN_3V3_EN, HIGH);
backlightEnable->set(true);
LOG_INFO("Power to TFT Backlight\n");
#endif
#ifdef ST7735_BL_V03
digitalWrite(ST7735_BL_V03, TFT_BACKLIGHT_ON);
#elif defined(ST7735_BL_V05)
pinMode(ST7735_BL_V05, OUTPUT);
digitalWrite(ST7735_BL_V05, TFT_BACKLIGHT_ON);
#endif
#ifdef UNPHONE
unphone.backlight(true); // using unPhone library
LOG_INFO("Power to TFT Backlight\n");

View File

@@ -1,5 +1,6 @@
#pragma once
#include <GpioLogic.h>
#include <OLEDDisplay.h>
/**
@@ -39,6 +40,14 @@ class TFTDisplay : public OLEDDisplay
*/
void setDetected(uint8_t detected);
/**
* This is normally managed entirely by TFTDisplay, but some rare applications (heltec tracker) might need to replace the
* default GPIO behavior with something a bit more complex.
*
* We (cruftily) make it static so that variant.cpp can access it without needing a ptr to the TFTDisplay instance.
*/
static GpioPin *backlightEnable;
protected:
// the header size of the buffer used, e.g. for the SPI command header
virtual int getBufferOffset(void) override { return 0; }

View File

@@ -0,0 +1,440 @@
#include "OLEDDisplayFontsPL.h"
// Font generated or edited with the glyphEditor
const uint8_t ArialMT_Plain_10_PL[] PROGMEM = {
0x0A, // Width: 10
0x0D, // Height: 13
0x20, // First char: 32
0xE0, // Number of chars: 224
// Jump Table:
0xFF, 0xFF, 0x00, 0x03, // 32:65535
0x00, 0x00, 0x04, 0x03, // 33
0x00, 0x04, 0x05, 0x04, // 34
0x00, 0x09, 0x09, 0x06, // 35
0x00, 0x12, 0x0A, 0x06, // 36
0x00, 0x1C, 0x10, 0x09, // 37
0x00, 0x2C, 0x0E, 0x08, // 38
0x00, 0x3A, 0x01, 0x02, // 39
0x00, 0x3B, 0x06, 0x04, // 40
0x00, 0x41, 0x06, 0x04, // 41
0x00, 0x47, 0x05, 0x04, // 42
0x00, 0x4C, 0x09, 0x06, // 43
0x00, 0x55, 0x04, 0x03, // 44
0x00, 0x59, 0x03, 0x03, // 45
0x00, 0x5C, 0x04, 0x03, // 46
0x00, 0x60, 0x05, 0x04, // 47
0x00, 0x65, 0x0A, 0x06, // 48
0x00, 0x6F, 0x08, 0x05, // 49
0x00, 0x77, 0x0A, 0x06, // 50
0x00, 0x81, 0x0A, 0x06, // 51
0x00, 0x8B, 0x0B, 0x07, // 52
0x00, 0x96, 0x0A, 0x06, // 53
0x00, 0xA0, 0x0A, 0x06, // 54
0x00, 0xAA, 0x09, 0x06, // 55
0x00, 0xB3, 0x0A, 0x06, // 56
0x00, 0xBD, 0x0A, 0x06, // 57
0x00, 0xC7, 0x04, 0x03, // 58
0x00, 0xCB, 0x04, 0x03, // 59
0x00, 0xCF, 0x0A, 0x06, // 60
0x00, 0xD9, 0x09, 0x06, // 61
0x00, 0xE2, 0x09, 0x06, // 62
0x00, 0xEB, 0x0B, 0x07, // 63
0x00, 0xF6, 0x14, 0x0B, // 64
0x01, 0x0A, 0x0E, 0x08, // 65
0x01, 0x18, 0x0C, 0x07, // 66
0x01, 0x24, 0x0C, 0x07, // 67
0x01, 0x30, 0x0B, 0x07, // 68
0x01, 0x3B, 0x0C, 0x07, // 69
0x01, 0x47, 0x09, 0x06, // 70
0x01, 0x50, 0x0D, 0x08, // 71
0x01, 0x5D, 0x0C, 0x07, // 72
0x01, 0x69, 0x04, 0x03, // 73
0x01, 0x6D, 0x08, 0x05, // 74
0x01, 0x75, 0x0E, 0x08, // 75
0x01, 0x83, 0x0C, 0x07, // 76
0x01, 0x8F, 0x10, 0x09, // 77
0x01, 0x9F, 0x0C, 0x07, // 78
0x01, 0xAB, 0x0E, 0x08, // 79
0x01, 0xB9, 0x0B, 0x07, // 80
0x01, 0xC4, 0x0E, 0x08, // 81
0x01, 0xD2, 0x0C, 0x07, // 82
0x01, 0xDE, 0x0C, 0x07, // 83
0x01, 0xEA, 0x0B, 0x07, // 84
0x01, 0xF5, 0x0C, 0x07, // 85
0x02, 0x01, 0x0D, 0x08, // 86
0x02, 0x0E, 0x11, 0x0A, // 87
0x02, 0x1F, 0x0E, 0x08, // 88
0x02, 0x2D, 0x0D, 0x08, // 89
0x02, 0x3A, 0x0C, 0x07, // 90
0x02, 0x46, 0x06, 0x04, // 91
0x02, 0x4C, 0x06, 0x04, // 92
0x02, 0x52, 0x04, 0x03, // 93
0x02, 0x56, 0x09, 0x06, // 94
0x02, 0x5F, 0x0C, 0x07, // 95
0x02, 0x6B, 0x03, 0x03, // 96
0x02, 0x6E, 0x0A, 0x06, // 97
0x02, 0x78, 0x0A, 0x06, // 98
0x02, 0x82, 0x0A, 0x06, // 99
0x02, 0x8C, 0x0A, 0x06, // 100
0x02, 0x96, 0x0A, 0x06, // 101
0x02, 0xA0, 0x05, 0x04, // 102
0x02, 0xA5, 0x0A, 0x06, // 103
0x02, 0xAF, 0x0A, 0x06, // 104
0x02, 0xB9, 0x04, 0x03, // 105
0x02, 0xBD, 0x04, 0x03, // 106
0x02, 0xC1, 0x08, 0x05, // 107
0x02, 0xC9, 0x04, 0x03, // 108
0x02, 0xCD, 0x10, 0x09, // 109
0x02, 0xDD, 0x0A, 0x06, // 110
0x02, 0xE7, 0x0A, 0x06, // 111
0x02, 0xF1, 0x0A, 0x06, // 112
0x02, 0xFB, 0x0A, 0x06, // 113
0x03, 0x05, 0x05, 0x04, // 114
0x03, 0x0A, 0x08, 0x05, // 115
0x03, 0x12, 0x06, 0x04, // 116
0x03, 0x18, 0x0A, 0x06, // 117
0x03, 0x22, 0x09, 0x06, // 118
0x03, 0x2B, 0x0E, 0x08, // 119
0x03, 0x39, 0x0A, 0x06, // 120
0x03, 0x43, 0x09, 0x06, // 121
0x03, 0x4C, 0x0A, 0x06, // 122
0x03, 0x56, 0x06, 0x04, // 123
0x03, 0x5C, 0x04, 0x03, // 124
0x03, 0x60, 0x05, 0x04, // 125
0x03, 0x65, 0x09, 0x06, // 126
0xFF, 0xFF, 0x00, 0x0A, // 127
0xFF, 0xFF, 0x00, 0x0A, // 128
0x03, 0x6E, 0x0C, 0x07, // 129
0x03, 0x7A, 0x05, 0x04, // 130
0x03, 0x7F, 0x0C, 0x07, // 131
0x03, 0x8B, 0x0E, 0x08, // 132
0x03, 0x99, 0x0C, 0x07, // 133
0x03, 0xA5, 0x0C, 0x07, // 134
0x03, 0xB1, 0x0A, 0x06, // 135
0x03, 0xBB, 0x0A, 0x06, // 136
0x03, 0xC5, 0x0A, 0x06, // 137
0xFF, 0xFF, 0x00, 0x0A, // 138
0xFF, 0xFF, 0x00, 0x0A, // 139
0xFF, 0xFF, 0x00, 0x0A, // 140
0xFF, 0xFF, 0x00, 0x0A, // 141
0xFF, 0xFF, 0x00, 0x0A, // 142
0xFF, 0xFF, 0x00, 0x0A, // 143
0xFF, 0xFF, 0x00, 0x0A, // 144
0xFF, 0xFF, 0x00, 0x0A, // 145
0xFF, 0xFF, 0x00, 0x0A, // 146
0x03, 0xCF, 0x0E, 0x08, // 147
0x03, 0xDD, 0x0A, 0x06, // 148
0xFF, 0xFF, 0x00, 0x0A, // 149
0xFF, 0xFF, 0x00, 0x0A, // 150
0xFF, 0xFF, 0x00, 0x0A, // 151
0x03, 0xE7, 0x0C, 0x07, // 152
0x03, 0xF3, 0x0C, 0x07, // 153
0x03, 0xFF, 0x0C, 0x07, // 154
0x04, 0x0B, 0x08, 0x05, // 155
0xFF, 0xFF, 0x00, 0x0A, // 156
0xFF, 0xFF, 0x00, 0x0A, // 157
0xFF, 0xFF, 0x00, 0x0A, // 158
0xFF, 0xFF, 0x00, 0x0A, // 159
0xFF, 0xFF, 0x00, 0x0A, // 160
0x04, 0x13, 0x04, 0x03, // 161
0x04, 0x17, 0x0A, 0x06, // 162
0x04, 0x21, 0x0C, 0x07, // 163
0x04, 0x2D, 0x0A, 0x06, // 164
0x04, 0x37, 0x0A, 0x06, // 165
0x04, 0x41, 0x04, 0x03, // 166
0x04, 0x45, 0x0A, 0x06, // 167
0x04, 0x4F, 0x05, 0x04, // 168
0x04, 0x54, 0x0D, 0x08, // 169
0x04, 0x61, 0x07, 0x05, // 170
0x04, 0x68, 0x0A, 0x06, // 171
0x04, 0x72, 0x09, 0x06, // 172
0x04, 0x7B, 0x03, 0x03, // 173
0x04, 0x7E, 0x0D, 0x08, // 174
0x04, 0x8B, 0x0B, 0x07, // 175
0x04, 0x96, 0x07, 0x05, // 176
0x04, 0x9D, 0x0A, 0x06, // 177
0x04, 0xA7, 0x05, 0x04, // 178
0x04, 0xAC, 0x05, 0x04, // 179
0x04, 0xB1, 0x05, 0x04, // 180
0x04, 0xB6, 0x0A, 0x06, // 181
0x04, 0xC0, 0x09, 0x06, // 182
0x04, 0xC9, 0x03, 0x03, // 183
0x04, 0xCC, 0x06, 0x04, // 184
0x04, 0xD2, 0x0C, 0x07, // 185
0x04, 0xDE, 0x07, 0x05, // 186
0x04, 0xE5, 0x0C, 0x07, // 187
0x04, 0xF1, 0x0A, 0x06, // 188
0x04, 0xFB, 0x10, 0x09, // 189
0x05, 0x0B, 0x10, 0x09, // 190
0x05, 0x1B, 0x0A, 0x06, // 191
0x05, 0x25, 0x0E, 0x08, // 192
0x05, 0x33, 0x0E, 0x08, // 193
0x05, 0x41, 0x0E, 0x08, // 194
0x05, 0x4F, 0x0E, 0x08, // 195
0x05, 0x5D, 0x0E, 0x08, // 196
0x05, 0x6B, 0x0E, 0x08, // 197
0x05, 0x79, 0x12, 0x0A, // 198
0x05, 0x8B, 0x0C, 0x07, // 199
0x05, 0x97, 0x0C, 0x07, // 200
0x05, 0xA3, 0x0C, 0x07, // 201
0x05, 0xAF, 0x0C, 0x07, // 202
0x05, 0xBB, 0x0C, 0x07, // 203
0x05, 0xC7, 0x05, 0x04, // 204
0x05, 0xCC, 0x04, 0x03, // 205
0x05, 0xD0, 0x04, 0x03, // 206
0x05, 0xD4, 0x05, 0x04, // 207
0x05, 0xD9, 0x0B, 0x07, // 208
0x05, 0xE4, 0x0C, 0x07, // 209
0x05, 0xF0, 0x0E, 0x08, // 210
0x05, 0xFE, 0x0E, 0x08, // 211
0x06, 0x0C, 0x0E, 0x08, // 212
0x06, 0x1A, 0x0E, 0x08, // 213
0x06, 0x28, 0x0E, 0x08, // 214
0x06, 0x36, 0x0A, 0x06, // 215
0x06, 0x40, 0x0D, 0x08, // 216
0x06, 0x4D, 0x0C, 0x07, // 217
0x06, 0x59, 0x0C, 0x07, // 218
0x06, 0x65, 0x0C, 0x07, // 219
0x06, 0x71, 0x0C, 0x07, // 220
0x06, 0x7D, 0x0D, 0x08, // 221
0x06, 0x8A, 0x0B, 0x07, // 222
0x06, 0x95, 0x0C, 0x07, // 223
0x06, 0xA1, 0x0A, 0x06, // 224
0x06, 0xAB, 0x0A, 0x06, // 225
0x06, 0xB5, 0x0A, 0x06, // 226
0x06, 0xBF, 0x0A, 0x06, // 227
0x06, 0xC9, 0x0A, 0x06, // 228
0x06, 0xD3, 0x0A, 0x06, // 229
0x06, 0xDD, 0x10, 0x09, // 230
0x06, 0xED, 0x0A, 0x06, // 231
0x06, 0xF7, 0x0A, 0x06, // 232
0x07, 0x01, 0x0A, 0x06, // 233
0x07, 0x0B, 0x0A, 0x06, // 234
0x07, 0x15, 0x0A, 0x06, // 235
0x07, 0x1F, 0x05, 0x04, // 236
0x07, 0x24, 0x04, 0x03, // 237
0x07, 0x28, 0x05, 0x04, // 238
0x07, 0x2D, 0x05, 0x04, // 239
0x07, 0x32, 0x0A, 0x06, // 240
0x07, 0x3C, 0x0A, 0x06, // 241
0x07, 0x46, 0x0A, 0x06, // 242
0x07, 0x50, 0x0A, 0x06, // 243
0x07, 0x5A, 0x0A, 0x06, // 244
0x07, 0x64, 0x0A, 0x06, // 245
0x07, 0x6E, 0x0A, 0x06, // 246
0x07, 0x78, 0x09, 0x06, // 247
0x07, 0x81, 0x0A, 0x06, // 248
0x07, 0x8B, 0x0A, 0x06, // 249
0x07, 0x95, 0x0A, 0x06, // 250
0x07, 0x9F, 0x0A, 0x06, // 251
0x07, 0xA9, 0x0A, 0x06, // 252
0x07, 0xB3, 0x09, 0x06, // 253
0x07, 0xBC, 0x0A, 0x06, // 254
0x07, 0xC6, 0x09, 0x06, // 255
// Font Data:
0x00, 0x00, 0xF8, 0x02, // 33
0x38, 0x00, 0x00, 0x00, 0x38, // 34
0xA0, 0x03, 0xE0, 0x00, 0xB8, 0x03, 0xE0, 0x00, 0xB8, // 35
0x30, 0x01, 0x28, 0x02, 0xF8, 0x07, 0x48, 0x02, 0x90, 0x01, // 36
0x00, 0x00, 0x30, 0x00, 0x48, 0x00, 0x30, 0x03, 0xC0, 0x00, 0xB0, 0x01, 0x48, 0x02, 0x80, 0x01, // 37
0x80, 0x01, 0x50, 0x02, 0x68, 0x02, 0xA8, 0x02, 0x18, 0x01, 0x80, 0x03, 0x80, 0x02, // 38
0x38, // 39
0xE0, 0x03, 0x10, 0x04, 0x08, 0x08, // 40
0x08, 0x08, 0x10, 0x04, 0xE0, 0x03, // 41
0x28, 0x00, 0x18, 0x00, 0x28, // 42
0x40, 0x00, 0x40, 0x00, 0xF0, 0x01, 0x40, 0x00, 0x40, // 43
0x00, 0x00, 0x00, 0x06, // 44
0x80, 0x00, 0x80, // 45
0x00, 0x00, 0x00, 0x02, // 46
0x00, 0x03, 0xE0, 0x00, 0x18, // 47
0xF0, 0x01, 0x08, 0x02, 0x08, 0x02, 0x08, 0x02, 0xF0, 0x01, // 48
0x00, 0x00, 0x20, 0x00, 0x10, 0x00, 0xF8, 0x03, // 49
0x10, 0x02, 0x08, 0x03, 0x88, 0x02, 0x48, 0x02, 0x30, 0x02, // 50
0x10, 0x01, 0x08, 0x02, 0x48, 0x02, 0x48, 0x02, 0xB0, 0x01, // 51
0xC0, 0x00, 0xA0, 0x00, 0x90, 0x00, 0x88, 0x00, 0xF8, 0x03, 0x80, // 52
0x60, 0x01, 0x38, 0x02, 0x28, 0x02, 0x28, 0x02, 0xC8, 0x01, // 53
0xF0, 0x01, 0x28, 0x02, 0x28, 0x02, 0x28, 0x02, 0xD0, 0x01, // 54
0x08, 0x00, 0x08, 0x03, 0xC8, 0x00, 0x38, 0x00, 0x08, // 55
0xB0, 0x01, 0x48, 0x02, 0x48, 0x02, 0x48, 0x02, 0xB0, 0x01, // 56
0x70, 0x01, 0x88, 0x02, 0x88, 0x02, 0x88, 0x02, 0xF0, 0x01, // 57
0x00, 0x00, 0x20, 0x02, // 58
0x00, 0x00, 0x20, 0x06, // 59
0x00, 0x00, 0x40, 0x00, 0xA0, 0x00, 0xA0, 0x00, 0x10, 0x01, // 60
0xA0, 0x00, 0xA0, 0x00, 0xA0, 0x00, 0xA0, 0x00, 0xA0, // 61
0x00, 0x00, 0x10, 0x01, 0xA0, 0x00, 0xA0, 0x00, 0x40, // 62
0x10, 0x00, 0x08, 0x00, 0x08, 0x00, 0xC8, 0x02, 0x48, 0x00, 0x30, // 63
0x00, 0x00, 0xC0, 0x03, 0x30, 0x04, 0xD0, 0x09, 0x28, 0x0A, 0x28, 0x0A, 0xC8, 0x0B, 0x68, 0x0A, 0x10, 0x05, 0xE0, 0x04, // 64
0x00, 0x02, 0xC0, 0x01, 0xB0, 0x00, 0x88, 0x00, 0xB0, 0x00, 0xC0, 0x01, 0x00, 0x02, // 65
0x00, 0x00, 0xF8, 0x03, 0x48, 0x02, 0x48, 0x02, 0x48, 0x02, 0xF0, 0x01, // 66
0x00, 0x00, 0xF0, 0x01, 0x08, 0x02, 0x08, 0x02, 0x08, 0x02, 0x10, 0x01, // 67
0x00, 0x00, 0xF8, 0x03, 0x08, 0x02, 0x08, 0x02, 0x10, 0x01, 0xE0, // 68
0x00, 0x00, 0xF8, 0x03, 0x48, 0x02, 0x48, 0x02, 0x48, 0x02, 0x48, 0x02, // 69
0x00, 0x00, 0xF8, 0x03, 0x48, 0x00, 0x48, 0x00, 0x08, // 70
0x00, 0x00, 0xE0, 0x00, 0x10, 0x01, 0x08, 0x02, 0x48, 0x02, 0x50, 0x01, 0xC0, // 71
0x00, 0x00, 0xF8, 0x03, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0xF8, 0x03, // 72
0x00, 0x00, 0xF8, 0x03, // 73
0x00, 0x03, 0x00, 0x02, 0x00, 0x02, 0xF8, 0x01, // 74
0x00, 0x00, 0xF8, 0x03, 0x80, 0x00, 0x60, 0x00, 0x90, 0x00, 0x08, 0x01, 0x00, 0x02, // 75
0x00, 0x00, 0xF8, 0x03, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, // 76
0x00, 0x00, 0xF8, 0x03, 0x30, 0x00, 0xC0, 0x01, 0x00, 0x02, 0xC0, 0x01, 0x30, 0x00, 0xF8, 0x03, // 77
0x00, 0x00, 0xF8, 0x03, 0x30, 0x00, 0x40, 0x00, 0x80, 0x01, 0xF8, 0x03, // 78
0x00, 0x00, 0xF0, 0x01, 0x08, 0x02, 0x08, 0x02, 0x08, 0x02, 0x08, 0x02, 0xF0, 0x01, // 79
0x00, 0x00, 0xF8, 0x03, 0x48, 0x00, 0x48, 0x00, 0x48, 0x00, 0x30, // 80
0x00, 0x00, 0xF0, 0x01, 0x08, 0x02, 0x08, 0x02, 0x08, 0x03, 0x08, 0x03, 0xF0, 0x02, // 81
0x00, 0x00, 0xF8, 0x03, 0x48, 0x00, 0x48, 0x00, 0xC8, 0x00, 0x30, 0x03, // 82
0x00, 0x00, 0x30, 0x01, 0x48, 0x02, 0x48, 0x02, 0x48, 0x02, 0x90, 0x01, // 83
0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0xF8, 0x03, 0x08, 0x00, 0x08, // 84
0x00, 0x00, 0xF8, 0x01, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0xF8, 0x01, // 85
0x08, 0x00, 0x70, 0x00, 0x80, 0x01, 0x00, 0x02, 0x80, 0x01, 0x70, 0x00, 0x08, // 86
0x18, 0x00, 0xE0, 0x01, 0x00, 0x02, 0xF0, 0x01, 0x08, 0x00, 0xF0, 0x01, 0x00, 0x02, 0xE0, 0x01, 0x18, // 87
0x00, 0x02, 0x08, 0x01, 0x90, 0x00, 0x60, 0x00, 0x90, 0x00, 0x08, 0x01, 0x00, 0x02, // 88
0x08, 0x00, 0x10, 0x00, 0x20, 0x00, 0xC0, 0x03, 0x20, 0x00, 0x10, 0x00, 0x08, // 89
0x08, 0x03, 0x88, 0x02, 0xC8, 0x02, 0x68, 0x02, 0x38, 0x02, 0x18, 0x02, // 90
0x00, 0x00, 0xF8, 0x0F, 0x08, 0x08, // 91
0x18, 0x00, 0xE0, 0x00, 0x00, 0x03, // 92
0x08, 0x08, 0xF8, 0x0F, // 93
0x40, 0x00, 0x30, 0x00, 0x08, 0x00, 0x30, 0x00, 0x40, // 94
0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, // 95
0x08, 0x00, 0x10, // 96
0x00, 0x00, 0x00, 0x03, 0xA0, 0x02, 0xA0, 0x02, 0xE0, 0x03, // 97
0x00, 0x00, 0xF8, 0x03, 0x20, 0x02, 0x20, 0x02, 0xC0, 0x01, // 98
0x00, 0x00, 0xC0, 0x01, 0x20, 0x02, 0x20, 0x02, 0x40, 0x01, // 99
0x00, 0x00, 0xC0, 0x01, 0x20, 0x02, 0x20, 0x02, 0xF8, 0x03, // 100
0x00, 0x00, 0xC0, 0x01, 0xA0, 0x02, 0xA0, 0x02, 0xC0, 0x02, // 101
0x20, 0x00, 0xF0, 0x03, 0x28, // 102
0x00, 0x00, 0xC0, 0x05, 0x20, 0x0A, 0x20, 0x0A, 0xE0, 0x07, // 103
0x00, 0x00, 0xF8, 0x03, 0x20, 0x00, 0x20, 0x00, 0xC0, 0x03, // 104
0x00, 0x00, 0xE8, 0x03, // 105
0x00, 0x08, 0xE8, 0x07, // 106
0xF8, 0x03, 0x80, 0x00, 0xC0, 0x01, 0x20, 0x02, // 107
0x00, 0x00, 0xF8, 0x03, // 108
0x00, 0x00, 0xE0, 0x03, 0x20, 0x00, 0x20, 0x00, 0xE0, 0x03, 0x20, 0x00, 0x20, 0x00, 0xC0, 0x03, // 109
0x00, 0x00, 0xE0, 0x03, 0x20, 0x00, 0x20, 0x00, 0xC0, 0x03, // 110
0x00, 0x00, 0xC0, 0x01, 0x20, 0x02, 0x20, 0x02, 0xC0, 0x01, // 111
0x00, 0x00, 0xE0, 0x0F, 0x20, 0x02, 0x20, 0x02, 0xC0, 0x01, // 112
0x00, 0x00, 0xC0, 0x01, 0x20, 0x02, 0x20, 0x02, 0xE0, 0x0F, // 113
0x00, 0x00, 0xE0, 0x03, 0x20, // 114
0x40, 0x02, 0xA0, 0x02, 0xA0, 0x02, 0x20, 0x01, // 115
0x20, 0x00, 0xF8, 0x03, 0x20, 0x02, // 116
0x00, 0x00, 0xE0, 0x01, 0x00, 0x02, 0x00, 0x02, 0xE0, 0x03, // 117
0x20, 0x00, 0xC0, 0x01, 0x00, 0x02, 0xC0, 0x01, 0x20, // 118
0xE0, 0x01, 0x00, 0x02, 0xC0, 0x01, 0x20, 0x00, 0xC0, 0x01, 0x00, 0x02, 0xE0, 0x01, // 119
0x20, 0x02, 0x40, 0x01, 0x80, 0x00, 0x40, 0x01, 0x20, 0x02, // 120
0x20, 0x00, 0xC0, 0x09, 0x00, 0x06, 0xC0, 0x01, 0x20, // 121
0x20, 0x02, 0x20, 0x03, 0xA0, 0x02, 0x60, 0x02, 0x20, 0x02, // 122
0x80, 0x00, 0x78, 0x0F, 0x08, 0x08, // 123
0x00, 0x00, 0xF8, 0x0F, // 124
0x08, 0x08, 0x78, 0x0F, 0x80, // 125
0xC0, 0x00, 0x40, 0x00, 0xC0, 0x00, 0x80, 0x00, 0xC0, // 126
0x00, 0x00, 0xF8, 0x03, 0x40, 0x02, 0x20, 0x02, 0x00, 0x02, 0x00, 0x02, // 129
0x40, 0x00, 0xF8, 0x03, 0x20, // 130
0x00, 0x00, 0xF8, 0x03, 0x30, 0x00, 0x44, 0x00, 0x82, 0x01, 0xF8, 0x03, // 131
0x00, 0x02, 0xC0, 0x01, 0xB0, 0x00, 0x88, 0x00, 0xB0, 0x00, 0xC0, 0x05, 0x00, 0x0A, // 132
0x00, 0x00, 0x00, 0x03, 0xA0, 0x02, 0xA0, 0x02, 0xE0, 0x07, 0x00, 0x08, // 133
0x00, 0x00, 0xF0, 0x01, 0x08, 0x02, 0x0A, 0x02, 0x09, 0x02, 0x10, 0x01, // 134
0x00, 0x00, 0xC0, 0x01, 0x20, 0x02, 0x28, 0x02, 0x44, 0x01, // 135
0x00, 0x00, 0xE0, 0x03, 0x20, 0x00, 0x28, 0x00, 0xC4, 0x03, // 136
0x20, 0x02, 0x20, 0x03, 0xA8, 0x02, 0x64, 0x02, 0x20, 0x02, // 137
0x00, 0x00, 0xF0, 0x01, 0x08, 0x02, 0x08, 0x02, 0x0A, 0x02, 0x09, 0x02, 0xF0, 0x01, // 147
0x00, 0x00, 0xC0, 0x01, 0x20, 0x02, 0x28, 0x02, 0xC4, 0x01, // 148
0x00, 0x00, 0xF8, 0x03, 0x48, 0x02, 0x48, 0x02, 0x48, 0x06, 0x48, 0x0A, // 152
0x00, 0x00, 0xC0, 0x01, 0xA0, 0x02, 0xA0, 0x02, 0xC0, 0x06, 0x00, 0x08, // 153
0x00, 0x00, 0x30, 0x01, 0x48, 0x02, 0x4A, 0x02, 0x49, 0x02, 0x90, 0x01, // 154
0x40, 0x02, 0xA0, 0x02, 0xA8, 0x02, 0x24, 0x01, // 155
0x00, 0x00, 0xA0, 0x0F, // 161
0x00, 0x00, 0xC0, 0x01, 0xA0, 0x0F, 0x78, 0x02, 0x40, 0x01, // 162
0x40, 0x02, 0x70, 0x03, 0xC8, 0x02, 0x48, 0x02, 0x08, 0x02, 0x10, 0x02, // 163
0x00, 0x00, 0xE0, 0x01, 0x20, 0x01, 0x20, 0x01, 0xE0, 0x01, // 164
0x48, 0x01, 0x70, 0x01, 0xC0, 0x03, 0x70, 0x01, 0x48, 0x01, // 165
0x00, 0x00, 0x38, 0x0F, // 166
0xD0, 0x04, 0x28, 0x09, 0x48, 0x09, 0x48, 0x0A, 0x90, 0x05, // 167
0x08, 0x00, 0x00, 0x00, 0x08, // 168
0xE0, 0x00, 0x10, 0x01, 0x48, 0x02, 0xA8, 0x02, 0xA8, 0x02, 0x10, 0x01, 0xE0, // 169
0x68, 0x00, 0x68, 0x00, 0x68, 0x00, 0x78, // 170
0x00, 0x00, 0x80, 0x01, 0x40, 0x02, 0x80, 0x01, 0x40, 0x02, // 171
0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0xE0, // 172
0x80, 0x00, 0x80, // 173
0xE0, 0x00, 0x10, 0x01, 0xE8, 0x02, 0x68, 0x02, 0xC8, 0x02, 0x10, 0x01, 0xE0, // 174
0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, // 175
0x00, 0x00, 0x38, 0x00, 0x28, 0x00, 0x38, // 176
0x40, 0x02, 0x40, 0x02, 0xF0, 0x03, 0x40, 0x02, 0x40, 0x02, // 177
0x48, 0x00, 0x68, 0x00, 0x58, // 178
0x48, 0x00, 0x58, 0x00, 0x68, // 179
0x00, 0x00, 0x10, 0x00, 0x08, // 180
0x00, 0x00, 0xE0, 0x0F, 0x00, 0x02, 0x00, 0x02, 0xE0, 0x03, // 181
0x70, 0x00, 0xF8, 0x0F, 0x08, 0x00, 0xF8, 0x0F, 0x08, // 182
0x00, 0x00, 0x40, // 183
0x00, 0x00, 0x00, 0x14, 0x00, 0x18, // 184
0x08, 0x03, 0x88, 0x02, 0xCA, 0x02, 0x69, 0x02, 0x38, 0x02, 0x18, 0x02, // 185
0x30, 0x00, 0x48, 0x00, 0x48, 0x00, 0x30, // 186
0x08, 0x03, 0x88, 0x02, 0xC8, 0x02, 0x6A, 0x02, 0x38, 0x02, 0x18, 0x02, // 187
0x20, 0x02, 0x20, 0x03, 0xA8, 0x02, 0x60, 0x02, 0x20, 0x02, // 188
0x00, 0x00, 0x10, 0x02, 0x78, 0x01, 0x80, 0x00, 0x60, 0x00, 0x50, 0x02, 0x48, 0x03, 0xC0, 0x02, // 189
0x48, 0x00, 0x58, 0x00, 0x68, 0x03, 0x80, 0x00, 0x60, 0x01, 0x90, 0x01, 0xC8, 0x03, 0x00, 0x01, // 190
0x00, 0x00, 0x00, 0x06, 0x00, 0x09, 0xA0, 0x09, 0x00, 0x04, // 191
0x00, 0x02, 0xC0, 0x01, 0xB0, 0x00, 0x89, 0x00, 0xB2, 0x00, 0xC0, 0x01, 0x00, 0x02, // 192
0x00, 0x02, 0xC0, 0x01, 0xB0, 0x00, 0x8A, 0x00, 0xB1, 0x00, 0xC0, 0x01, 0x00, 0x02, // 193
0x00, 0x02, 0xC0, 0x01, 0xB2, 0x00, 0x89, 0x00, 0xB2, 0x00, 0xC0, 0x01, 0x00, 0x02, // 194
0x00, 0x02, 0xC2, 0x01, 0xB1, 0x00, 0x8A, 0x00, 0xB1, 0x00, 0xC0, 0x01, 0x00, 0x02, // 195
0x00, 0x02, 0xC0, 0x01, 0xB2, 0x00, 0x88, 0x00, 0xB2, 0x00, 0xC0, 0x01, 0x00, 0x02, // 196
0x00, 0x02, 0xC0, 0x01, 0xBE, 0x00, 0x8A, 0x00, 0xBE, 0x00, 0xC0, 0x01, 0x00, 0x02, // 197
0x00, 0x03, 0xC0, 0x00, 0xE0, 0x00, 0x98, 0x00, 0x88, 0x00, 0xF8, 0x03, 0x48, 0x02, 0x48, 0x02, 0x48, 0x02, // 198
0x00, 0x00, 0xF0, 0x01, 0x08, 0x02, 0x08, 0x16, 0x08, 0x1A, 0x10, 0x01, // 199
0x00, 0x00, 0xF8, 0x03, 0x49, 0x02, 0x4A, 0x02, 0x48, 0x02, 0x48, 0x02, // 200
0x00, 0x00, 0xF8, 0x03, 0x48, 0x02, 0x4A, 0x02, 0x49, 0x02, 0x48, 0x02, // 201
0x00, 0x00, 0xFA, 0x03, 0x49, 0x02, 0x4A, 0x02, 0x48, 0x02, 0x48, 0x02, // 202
0x00, 0x00, 0xF8, 0x03, 0x4A, 0x02, 0x48, 0x02, 0x4A, 0x02, 0x48, 0x02, // 203
0x00, 0x00, 0xF9, 0x03, 0x02, // 204
0x02, 0x00, 0xF9, 0x03, // 205
0x01, 0x00, 0xFA, 0x03, // 206
0x02, 0x00, 0xF8, 0x03, 0x02, // 207
0x40, 0x00, 0xF8, 0x03, 0x48, 0x02, 0x48, 0x02, 0x10, 0x01, 0xE0, // 208
0x00, 0x00, 0xFA, 0x03, 0x31, 0x00, 0x42, 0x00, 0x81, 0x01, 0xF8, 0x03, // 209
0x00, 0x00, 0xF0, 0x01, 0x08, 0x02, 0x09, 0x02, 0x0A, 0x02, 0x08, 0x02, 0xF0, 0x01, // 210
0x00, 0x00, 0xF0, 0x01, 0x08, 0x02, 0x0A, 0x02, 0x09, 0x02, 0x08, 0x02, 0xF0, 0x01, // 211
0x00, 0x00, 0xF0, 0x01, 0x08, 0x02, 0x0A, 0x02, 0x09, 0x02, 0x0A, 0x02, 0xF0, 0x01, // 212
0x00, 0x00, 0xF0, 0x01, 0x0A, 0x02, 0x09, 0x02, 0x0A, 0x02, 0x09, 0x02, 0xF0, 0x01, // 213
0x00, 0x00, 0xF0, 0x01, 0x0A, 0x02, 0x08, 0x02, 0x0A, 0x02, 0x08, 0x02, 0xF0, 0x01, // 214
0x10, 0x01, 0xA0, 0x00, 0xE0, 0x00, 0xA0, 0x00, 0x10, 0x01, // 215
0x00, 0x00, 0xF0, 0x02, 0x08, 0x03, 0xC8, 0x02, 0x28, 0x02, 0x18, 0x03, 0xE8, // 216
0x00, 0x00, 0xF8, 0x01, 0x01, 0x02, 0x02, 0x02, 0x00, 0x02, 0xF8, 0x01, // 217
0x00, 0x00, 0xF8, 0x01, 0x02, 0x02, 0x01, 0x02, 0x00, 0x02, 0xF8, 0x01, // 218
0x00, 0x00, 0xF8, 0x01, 0x02, 0x02, 0x01, 0x02, 0x02, 0x02, 0xF8, 0x01, // 219
0x00, 0x00, 0xF8, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0xF8, 0x01, // 220
0x08, 0x00, 0x10, 0x00, 0x20, 0x00, 0xC2, 0x03, 0x21, 0x00, 0x10, 0x00, 0x08, // 221
0x00, 0x00, 0xF8, 0x03, 0x10, 0x01, 0x10, 0x01, 0x10, 0x01, 0xE0, // 222
0x00, 0x00, 0xF0, 0x03, 0x08, 0x01, 0x48, 0x02, 0xB0, 0x02, 0x80, 0x01, // 223
0x00, 0x00, 0x00, 0x03, 0xA4, 0x02, 0xA8, 0x02, 0xE0, 0x03, // 224
0x00, 0x00, 0x00, 0x03, 0xA8, 0x02, 0xA4, 0x02, 0xE0, 0x03, // 225
0x00, 0x00, 0x00, 0x03, 0xA8, 0x02, 0xA4, 0x02, 0xE8, 0x03, // 226
0x00, 0x00, 0x08, 0x03, 0xA4, 0x02, 0xA8, 0x02, 0xE4, 0x03, // 227
0x00, 0x00, 0x00, 0x03, 0xA8, 0x02, 0xA0, 0x02, 0xE8, 0x03, // 228
0x00, 0x00, 0x00, 0x03, 0xAE, 0x02, 0xAA, 0x02, 0xEE, 0x03, // 229
0x00, 0x00, 0x40, 0x03, 0xA0, 0x02, 0xA0, 0x02, 0xC0, 0x01, 0xA0, 0x02, 0xA0, 0x02, 0xC0, 0x02, // 230
0x00, 0x00, 0xC0, 0x01, 0x20, 0x16, 0x20, 0x1A, 0x40, 0x01, // 231
0x00, 0x00, 0xC0, 0x01, 0xA4, 0x02, 0xA8, 0x02, 0xC0, 0x02, // 232
0x00, 0x00, 0xC0, 0x01, 0xA8, 0x02, 0xA4, 0x02, 0xC0, 0x02, // 233
0x00, 0x00, 0xC0, 0x01, 0xA8, 0x02, 0xA4, 0x02, 0xC8, 0x02, // 234
0x00, 0x00, 0xC0, 0x01, 0xA8, 0x02, 0xA0, 0x02, 0xC8, 0x02, // 235
0x00, 0x00, 0xE4, 0x03, 0x08, // 236
0x08, 0x00, 0xE4, 0x03, // 237
0x08, 0x00, 0xE4, 0x03, 0x08, // 238
0x08, 0x00, 0xE0, 0x03, 0x08, // 239
0x00, 0x00, 0xC0, 0x01, 0x28, 0x02, 0x38, 0x02, 0xE0, 0x01, // 240
0x00, 0x00, 0xE8, 0x03, 0x24, 0x00, 0x28, 0x00, 0xC4, 0x03, // 241
0x00, 0x00, 0xC0, 0x01, 0x24, 0x02, 0x28, 0x02, 0xC0, 0x01, // 242
0x00, 0x00, 0xC0, 0x01, 0x28, 0x02, 0x24, 0x02, 0xC0, 0x01, // 243
0x00, 0x00, 0xC0, 0x01, 0x28, 0x02, 0x24, 0x02, 0xC8, 0x01, // 244
0x00, 0x00, 0xC8, 0x01, 0x24, 0x02, 0x28, 0x02, 0xC4, 0x01, // 245
0x00, 0x00, 0xC0, 0x01, 0x28, 0x02, 0x20, 0x02, 0xC8, 0x01, // 246
0x40, 0x00, 0x40, 0x00, 0x50, 0x01, 0x40, 0x00, 0x40, // 247
0x00, 0x00, 0xC0, 0x02, 0xA0, 0x03, 0x60, 0x02, 0xA0, 0x01, // 248
0x00, 0x00, 0xE0, 0x01, 0x04, 0x02, 0x08, 0x02, 0xE0, 0x03, // 249
0x00, 0x00, 0xE0, 0x01, 0x08, 0x02, 0x04, 0x02, 0xE0, 0x03, // 250
0x00, 0x00, 0xE8, 0x01, 0x04, 0x02, 0x08, 0x02, 0xE0, 0x03, // 251
0x00, 0x00, 0xE0, 0x01, 0x08, 0x02, 0x00, 0x02, 0xE8, 0x03, // 252
0x20, 0x00, 0xC0, 0x09, 0x08, 0x06, 0xC4, 0x01, 0x20, // 253
0x00, 0x00, 0xF8, 0x0F, 0x20, 0x02, 0x20, 0x02, 0xC0, 0x01, // 254
0x20, 0x00, 0xC8, 0x09, 0x00, 0x06, 0xC8, 0x01, 0x20, // 255
};

View File

@@ -0,0 +1,11 @@
#ifndef OLEDDISPLAYFONTSPL_h
#define OLEDDISPLAYFONTSPL_h
#ifdef ARDUINO
#include <Arduino.h>
#elif __MBED__
#define PROGMEM
#endif
extern const uint8_t ArialMT_Plain_10_PL[] PROGMEM;
#endif

View File

@@ -20,8 +20,8 @@ const uint8_t bluetoothConnectedIcon[36] PROGMEM = {0xfe, 0x01, 0xff, 0x03, 0x03
0xfe, 0x31, 0x00, 0x30, 0x30, 0x30, 0x30, 0x30, 0xf0, 0x3f, 0xe0, 0x1f};
#endif
#if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7735_CS) || defined(ST7789_CS) || defined(HX8357_CS) || \
ARCH_PORTDUINO) && \
#if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7735_CS) || defined(ST7789_CS) || defined(USE_ST7789) || \
defined(HX8357_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};

View File

@@ -224,6 +224,11 @@ __attribute__((weak, noinline)) bool loopCanSleep()
return true;
}
// Weak empty variant initialization function.
// May be redefined by variant files.
void lateInitVariant() __attribute__((weak));
void lateInitVariant() {}
/**
* Print info as a structured log message (for automated log processing)
*/
@@ -257,6 +262,12 @@ void setup()
#ifdef DEBUG_PORT
consoleInit(); // Set serial baud rate and init our mesh console
#endif
#if ARCH_PORTDUINO
struct timeval tv;
tv.tv_sec = time(NULL);
tv.tv_usec = 0;
perhapsSetRTC(RTCQualityNTP, &tv);
#endif
powerMonInit();
@@ -278,29 +289,9 @@ void setup()
digitalWrite(LORA_TCXO_GPIO, HIGH);
#endif
#if defined(VEXT_ENABLE_V03)
pinMode(VEXT_ENABLE_V03, OUTPUT);
pinMode(ST7735_BL_V03, OUTPUT);
digitalWrite(VEXT_ENABLE_V03, 0); // turn on the display power and antenna boost
digitalWrite(ST7735_BL_V03, 1); // display backligth on
LOG_DEBUG("HELTEC Detect Tracker V1.0\n");
#elif defined(VEXT_ENABLE_V05)
pinMode(VEXT_ENABLE_V05, OUTPUT);
pinMode(ST7735_BL_V05, OUTPUT);
digitalWrite(VEXT_ENABLE_V05, 1); // turn on the lora antenna boost
digitalWrite(ST7735_BL_V05, 1); // turn on display backligth
LOG_DEBUG("HELTEC Detect Tracker V1.1\n");
#elif defined(VEXT_ENABLE) && defined(VEXT_ON_VALUE)
#if defined(VEXT_ENABLE)
pinMode(VEXT_ENABLE, OUTPUT);
digitalWrite(VEXT_ENABLE, VEXT_ON_VALUE); // turn on the display power
#elif defined(VEXT_ENABLE)
pinMode(VEXT_ENABLE, OUTPUT);
digitalWrite(VEXT_ENABLE, 0); // turn on the display power
#endif
#if defined(VTFT_CTRL_V03)
pinMode(VTFT_CTRL_V03, OUTPUT);
digitalWrite(VTFT_CTRL_V03, LOW);
#endif
#if defined(VTFT_CTRL)
@@ -556,6 +547,7 @@ void setup()
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::BME_680, meshtastic_TelemetrySensorType_BME680)
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::BME_280, meshtastic_TelemetrySensorType_BME280)
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::BMP_280, meshtastic_TelemetrySensorType_BMP280)
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::BMP_3XX, meshtastic_TelemetrySensorType_BMP3XX)
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::BMP_085, meshtastic_TelemetrySensorType_BMP085)
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::INA260, meshtastic_TelemetrySensorType_INA260)
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::INA219, meshtastic_TelemetrySensorType_INA219)
@@ -1023,6 +1015,8 @@ void setup()
}
}
lateInitVariant(); // Do board specific init (see extra_variants/README.md for documentation)
#if !MESHTASTIC_EXCLUDE_MQTT
mqttInit();
#endif
@@ -1149,4 +1143,4 @@ void loop()
}
// if (didWake) LOG_DEBUG("wake!\n");
}
#endif
#endif

View File

@@ -11,6 +11,7 @@
#include <Curve25519.h>
#include <SHA256.h>
#if !(MESHTASTIC_EXCLUDE_PKI_KEYGEN)
/**
* Create a public/private key pair with Curve25519.
*
@@ -24,6 +25,30 @@ void CryptoEngine::generateKeyPair(uint8_t *pubKey, uint8_t *privKey)
memcpy(pubKey, public_key, sizeof(public_key));
memcpy(privKey, private_key, sizeof(private_key));
}
/**
* regenerate a public key with Curve25519.
*
* @param pubKey The destination for the public key.
* @param privKey The source for the private key.
*/
bool CryptoEngine::regeneratePublicKey(uint8_t *pubKey, uint8_t *privKey)
{
if (!memfll(privKey, 0, sizeof(private_key))) {
Curve25519::eval(pubKey, privKey, 0);
if (Curve25519::isWeakPoint(pubKey)) {
LOG_ERROR("PKI key generation failed. Specified private key results in a weak\n");
memset(pubKey, 0, 32);
return false;
}
memcpy(private_key, privKey, sizeof(private_key));
memcpy(public_key, pubKey, sizeof(public_key));
} else {
LOG_WARN("X25519 key generation failed due to blank private key\n");
return false;
}
return true;
}
#endif
void CryptoEngine::clearKeys()
{

View File

@@ -21,6 +21,7 @@ struct CryptoKey {
*/
#define MAX_BLOCKSIZE 256
#define TEST_CURVE25519_FIELD_OPS // Exposes Curve25519::isWeakPoint() for testing keys
class CryptoEngine
{
@@ -33,6 +34,8 @@ class CryptoEngine
#if !(MESHTASTIC_EXCLUDE_PKI)
#if !(MESHTASTIC_EXCLUDE_PKI_KEYGEN)
virtual void generateKeyPair(uint8_t *pubKey, uint8_t *privKey);
virtual bool regeneratePublicKey(uint8_t *pubKey, uint8_t *privKey);
#endif
void clearKeys();
void setDHPrivateKey(uint8_t *_private_key);

View File

@@ -50,11 +50,23 @@ template <typename T> bool LR11x0Interface<T>::init()
limitPower();
#ifdef TRACKER_T1000_E // Tracker T1000E uses DIO5, DIO6, DIO7, DIO8 for RF switching
static const uint32_t rfswitch_dio_pins[] = {RADIOLIB_LR11X0_DIO5, RADIOLIB_LR11X0_DIO6, RADIOLIB_LR11X0_DIO7,
RADIOLIB_LR11X0_DIO8, RADIOLIB_NC};
static const Module::RfSwitchMode_t rfswitch_table[] = {
// mode DIO5 DIO6 DIO7 DIO8
{LR11x0::MODE_STBY, {LOW, LOW, LOW, LOW}}, {LR11x0::MODE_RX, {HIGH, LOW, LOW, HIGH}},
{LR11x0::MODE_TX, {HIGH, HIGH, LOW, HIGH}}, {LR11x0::MODE_TX_HP, {LOW, HIGH, LOW, HIGH}},
{LR11x0::MODE_TX_HF, {LOW, LOW, LOW, LOW}}, {LR11x0::MODE_GNSS, {LOW, LOW, HIGH, LOW}},
{LR11x0::MODE_WIFI, {LOW, LOW, LOW, LOW}}, END_OF_MODE_TABLE,
};
#else
// set RF switch configuration for Wio WM1110
// Wio WM1110 uses DIO5 and DIO6 for RF switching
// NOTE: other boards may be different. If you are
// using a different board, you may need to wrap
// this in a conditional.
static const uint32_t rfswitch_dio_pins[] = {RADIOLIB_LR11X0_DIO5, RADIOLIB_LR11X0_DIO6, RADIOLIB_NC, RADIOLIB_NC,
RADIOLIB_NC};
@@ -67,6 +79,8 @@ template <typename T> bool LR11x0Interface<T>::init()
{LR11x0::MODE_WIFI, {LOW, LOW}}, END_OF_MODE_TABLE,
};
#endif
// We need to do this before begin() call
#ifdef LR11X0_DIO_AS_RF_SWITCH
LOG_DEBUG("Setting DIO RF switch\n");
@@ -100,13 +114,6 @@ template <typename T> bool LR11x0Interface<T>::init()
// FIXME: May want to set depending on a definition, currently all LR1110 variant files use the DC-DC regulator option
if (res == RADIOLIB_ERR_NONE)
res = lora.setRegulatorDCDC();
#ifdef TRACKER_T1000_E
#ifdef LR11X0_DIO_RF_SWITCH_CONFIG
res = lora.setDioAsRfSwitch(LR11X0_DIO_RF_SWITCH_CONFIG);
#else
res = lora.setDioAsRfSwitch(0x03, 0x0, 0x01, 0x03, 0x02, 0x0, 0x0, 0x0);
#endif
#endif
if (res == RADIOLIB_ERR_NONE) {
if (config.lora.sx126x_rx_boosted_gain) { // the name is unfortunate but historically accurate
res = lora.setRxBoostedGainMode(true);
@@ -225,9 +232,7 @@ template <typename T> void LR11x0Interface<T>::startReceive()
// We use a 16 bit preamble so this should save some power by letting radio sit in standby mostly.
// Furthermore, we need the PREAMBLE_DETECTED and HEADER_VALID IRQ flag to detect whether we are actively receiving
int err = lora.startReceive(
RADIOLIB_LR11X0_RX_TIMEOUT_INF, RADIOLIB_LR11X0_IRQ_RX_DONE,
0); // only RX_DONE IRQ is needed, we'll check for PREAMBLE_DETECTED and HEADER_VALID in isActivelyReceiving
int err = lora.startReceive(RADIOLIB_LR11X0_RX_TIMEOUT_INF, RADIOLIB_IRQ_RX_DEFAULT_FLAGS, RADIOLIB_IRQ_RX_DEFAULT_MASK, 0);
assert(err == RADIOLIB_ERR_NONE);
RadioLibInterface::startReceive();

View File

@@ -25,7 +25,7 @@ template <class T> class LR11x0Interface : public RadioLibInterface
/// Prepare hardware for sleep. Call this _only_ for deep sleep, not needed for light sleep.
virtual bool sleep() override;
bool isIRQPending() override { return lora.getIrqStatus() != 0; }
bool isIRQPending() override { return lora.getIrqFlags() != 0; }
protected:
/**

View File

@@ -1,4 +1,5 @@
#include "MeshPacketQueue.h"
#include "NodeDB.h"
#include "configuration.h"
#include <assert.h>
@@ -16,12 +17,9 @@ bool CompareMeshPacketFunc(const meshtastic_MeshPacket *p1, const meshtastic_Mes
{
assert(p1 && p2);
auto p1p = getPriority(p1), p2p = getPriority(p2);
// If priorities differ, use that
// for equal priorities, order by id (older packets have higher priority - this will briefly be wrong when IDs roll over but
// no big deal)
return (p1p != p2p) ? (p1p < p2p) // prefer bigger priorities
: (p1->id >= p2->id); // prefer smaller packet ids
// for equal priorities, prefer packets already on mesh.
return (p1p != p2p) ? (p1p > p2p) : (getFrom(p1) != nodeDB->getNodeNum() && getFrom(p2) == nodeDB->getNodeNum());
}
MeshPacketQueue::MeshPacketQueue(size_t _maxLen) : maxLen(_maxLen) {}
@@ -39,26 +37,38 @@ void fixPriority(meshtastic_MeshPacket *p)
// We might receive acks from other nodes (and since generated remotely, they won't have priority assigned. Check for that
// and fix it
if (p->priority == meshtastic_MeshPacket_Priority_UNSET) {
// if acks give high priority
// if a reliable message give a bit higher default priority
p->priority = (p->decoded.portnum == meshtastic_PortNum_ROUTING_APP)
? meshtastic_MeshPacket_Priority_ACK
: (p->want_ack ? meshtastic_MeshPacket_Priority_RELIABLE : meshtastic_MeshPacket_Priority_DEFAULT);
p->priority = (p->want_ack ? meshtastic_MeshPacket_Priority_RELIABLE : meshtastic_MeshPacket_Priority_DEFAULT);
if (p->which_payload_variant == meshtastic_MeshPacket_decoded_tag) {
// if acks/naks give very high priority
if (p->decoded.portnum == meshtastic_PortNum_ROUTING_APP) {
p->priority = meshtastic_MeshPacket_Priority_ACK;
// if text or admin, give high priority
} else if (p->decoded.portnum == meshtastic_PortNum_TEXT_MESSAGE_APP ||
p->decoded.portnum == meshtastic_PortNum_ADMIN_APP) {
p->priority = meshtastic_MeshPacket_Priority_HIGH;
// if it is a response, give higher priority to let it arrive early and stop the request being relayed
} else if (p->decoded.request_id != 0) {
p->priority = meshtastic_MeshPacket_Priority_RESPONSE;
// Also if we want a response, give a bit higher priority
} else if (p->decoded.want_response) {
p->priority = meshtastic_MeshPacket_Priority_RELIABLE;
}
}
}
}
/** enqueue a packet, return false if full */
bool MeshPacketQueue::enqueue(meshtastic_MeshPacket *p)
{
fixPriority(p);
// no space - try to replace a lower priority packet in the queue
if (queue.size() >= maxLen) {
return replaceLowerPriorityPacket(p);
}
queue.push_back(p);
std::push_heap(queue.begin(), queue.end(), &CompareMeshPacketFunc);
// Find the correct position using upper_bound to maintain a stable order
auto it = std::upper_bound(queue.begin(), queue.end(), p, CompareMeshPacketFunc);
queue.insert(it, p); // Insert packet at the found position
return true;
}
@@ -69,9 +79,7 @@ meshtastic_MeshPacket *MeshPacketQueue::dequeue()
}
auto *p = queue.front();
std::pop_heap(queue.begin(), queue.end(), &CompareMeshPacketFunc);
queue.pop_back();
queue.erase(queue.begin()); // Remove the highest-priority packet
return p;
}
@@ -92,7 +100,6 @@ meshtastic_MeshPacket *MeshPacketQueue::remove(NodeNum from, PacketId id)
auto p = (*it);
if (getFrom(p) == from && p->id == id) {
queue.erase(it);
std::make_heap(queue.begin(), queue.end(), &CompareMeshPacketFunc);
return p;
}
}
@@ -103,28 +110,21 @@ meshtastic_MeshPacket *MeshPacketQueue::remove(NodeNum from, PacketId id)
/** Attempt to find and remove a packet from this queue. Returns the packet which was removed from the queue */
bool MeshPacketQueue::replaceLowerPriorityPacket(meshtastic_MeshPacket *p)
{
std::sort_heap(queue.begin(), queue.end(), &CompareMeshPacketFunc); // sort ascending based on priority (0 -> 127)
// find first packet which does not compare less (in priority) than parameter packet
auto low = std::lower_bound(queue.begin(), queue.end(), p, &CompareMeshPacketFunc);
if (low == queue.begin()) { // if already at start, there are no packets with lower priority
return false;
if (queue.empty()) {
return false; // No packets to replace
}
// Check if the packet at the back has a lower priority than the new packet
auto &backPacket = queue.back();
if (backPacket->priority < p->priority) {
// Remove the back packet
packetPool.release(backPacket);
queue.pop_back();
// Insert the new packet in the correct order
enqueue(p);
return true;
}
if (low == queue.end()) {
// all priorities in the vector are smaller than the incoming packet. Replace the lowest priority (first) element
low = queue.begin();
} else {
// 'low' iterator points to first packet which does not compare less than parameter
--low; // iterate to lower priority packet
}
if (getPriority(p) > getPriority(*low)) {
packetPool.release(*low); // deallocate and drop the packet we're replacing
*low = p; // replace low-pri packet at this position with incoming packet with higher priority
}
std::make_heap(queue.begin(), queue.end(), &CompareMeshPacketFunc);
return true;
}
// If the back packet's priority is not lower, no replacement occurs
return false;
}

View File

@@ -14,8 +14,9 @@ typedef uint32_t PacketId; // A packet sequence number
1 // Reserved to only deliver packets over high speed (non-lora) transports, such as MQTT or BLE mesh (not yet implemented)
#define ERRNO_OK 0
#define ERRNO_NO_INTERFACES 33
#define ERRNO_UNKNOWN 32 // pick something that doesn't conflict with RH_ROUTER_ERROR_UNABLE_TO_DELIVER
#define ERRNO_DISABLED 34 // the interface is disabled
#define ERRNO_UNKNOWN 32 // pick something that doesn't conflict with RH_ROUTER_ERROR_UNABLE_TO_DELIVER
#define ERRNO_DISABLED 34 // the interface is disabled
#define ID_COUNTER_MASK (UINT32_MAX >> 22) // mask to select the counter portion of the ID
/*
* Source of a received message
@@ -47,4 +48,7 @@ extern Allocator<meshtastic_MeshPacket> &packetPool;
* Most (but not always) of the time we want to treat packets 'from' the local phone (where from == 0), as if they originated on
* the local node. If from is zero this function returns our node number instead
*/
NodeNum getFrom(const meshtastic_MeshPacket *p);
NodeNum getFrom(const meshtastic_MeshPacket *p);
/* Some clients might not properly set priority, therefore we fix it here. */
void fixPriority(meshtastic_MeshPacket *p);

View File

@@ -139,14 +139,24 @@ NodeDB::NodeDB()
crypto->setDHPrivateKey(config.security.private_key.bytes);
} else {
#if !(MESHTASTIC_EXCLUDE_PKI_KEYGEN)
LOG_INFO("Generating new PKI keys\n");
crypto->generateKeyPair(config.security.public_key.bytes, config.security.private_key.bytes);
config.security.public_key.size = 32;
config.security.private_key.size = 32;
printBytes("New Pubkey", config.security.public_key.bytes, 32);
owner.public_key.size = 32;
memcpy(owner.public_key.bytes, config.security.public_key.bytes, 32);
bool keygenSuccess = false;
if (config.security.private_key.size == 32) {
LOG_INFO("Calculating PKI Public Key\n");
if (crypto->regeneratePublicKey(config.security.public_key.bytes, config.security.private_key.bytes)) {
keygenSuccess = true;
}
} else {
LOG_INFO("Generating new PKI keys\n");
crypto->generateKeyPair(config.security.public_key.bytes, config.security.private_key.bytes);
keygenSuccess = true;
}
if (keygenSuccess) {
config.security.public_key.size = 32;
config.security.private_key.size = 32;
printBytes("New Pubkey", config.security.public_key.bytes, 32);
owner.public_key.size = 32;
memcpy(owner.public_key.bytes, config.security.public_key.bytes, 32);
}
#else
LOG_INFO("No PKI keys set, and generation disabled!\n");
#endif
@@ -292,10 +302,10 @@ void NodeDB::installDefaultConfig()
config.lora.ignore_mqtt = false;
#endif
#ifdef ADMIN_KEY_USERPREFS
memcpy(config.security.admin_key.bytes, admin_key_userprefs, 32);
config.security.admin_key.size = 32;
memcpy(config.security.admin_key[0].bytes, admin_key_userprefs, 32);
config.security.admin_key[0].size = 32;
#else
config.security.admin_key.size = 0;
config.security.admin_key[0].size = 0;
#endif
config.security.public_key.size = 0;
config.security.private_key.size = 0;
@@ -307,7 +317,7 @@ void NodeDB::installDefaultConfig()
#else
config.device.disable_triple_click = true;
#endif
#if !HAS_GPS || defined(T_DECK)
#if !HAS_GPS || defined(T_DECK) || defined(TLORA_T3S3_EPAPER)
config.position.gps_mode = meshtastic_Config_PositionConfig_GpsMode_NOT_PRESENT;
#elif !defined(GPS_RX_PIN)
if (config.position.rx_gpio == 0)
@@ -395,6 +405,13 @@ void NodeDB::installDefaultModuleConfig()
moduleConfig.has_store_forward = true;
moduleConfig.has_telemetry = true;
moduleConfig.has_external_notification = true;
#if defined(PIN_BUZZER)
moduleConfig.external_notification.enabled = true;
moduleConfig.external_notification.output_buzzer = PIN_BUZZER;
moduleConfig.external_notification.use_pwm = true;
moduleConfig.external_notification.alert_message_buzzer = true;
moduleConfig.external_notification.nag_timeout = 60;
#endif
#if defined(RAK4630) || defined(RAK11310)
// Default to RAK led pin 2 (blue)
moduleConfig.external_notification.enabled = true;
@@ -404,6 +421,7 @@ void NodeDB::installDefaultModuleConfig()
moduleConfig.external_notification.output_ms = 1000;
moduleConfig.external_notification.nag_timeout = 60;
#endif
#ifdef HAS_I2S
// Don't worry about the other settings for T-Watch, we'll also use the DRV2056 behavior for notifications
moduleConfig.external_notification.enabled = true;
@@ -620,7 +638,7 @@ void NodeDB::pickNewNodeNum()
meshtastic_NodeInfoLite *found;
while ((nodeNum == NODENUM_BROADCAST || nodeNum < NUM_RESERVED) ||
((found = getMeshNode(nodeNum)) && memcmp(found->user.macaddr, owner.macaddr, sizeof(owner.macaddr)) != 0)) {
((found = getMeshNode(nodeNum)) && memcmp(found->user.macaddr, ourMacAddr, sizeof(ourMacAddr)) != 0)) {
NodeNum candidate = random(NUM_RESERVED, LONG_MAX); // try a new random choice
LOG_WARN("NOTE! Our desired nodenum 0x%x is invalid or in use, so trying for 0x%x\n", nodeNum, candidate);
nodeNum = candidate;

View File

@@ -194,6 +194,8 @@ size_t PhoneAPI::getFromRadio(uint8_t *buf)
auto us = nodeDB->readNextMeshNode(readIndex);
if (us) {
nodeInfoForPhone = TypeConversions::ConvertToNodeInfo(us);
nodeInfoForPhone.hops_away = 0;
nodeInfoForPhone.is_favorite = true;
fromRadioScratch.which_payload_variant = meshtastic_FromRadio_node_info_tag;
fromRadioScratch.node_info = nodeInfoForPhone;
// Should allow us to resume sending NodeInfo in STATE_SEND_OTHER_NODEINFOS
@@ -259,6 +261,9 @@ size_t PhoneAPI::getFromRadio(uint8_t *buf)
fromRadioScratch.config.which_payload_variant = meshtastic_Config_security_tag;
fromRadioScratch.config.payload_variant.security = config.security;
break;
case meshtastic_Config_sessionkey_tag:
fromRadioScratch.config.which_payload_variant = meshtastic_Config_sessionkey_tag;
break;
default:
LOG_ERROR("Unknown config type %d\n", config_state);
}

View File

@@ -112,7 +112,7 @@ void ReliableRouter::sniffReceived(const meshtastic_MeshPacket *p, const meshtas
sendAckNak(meshtastic_Routing_Error_NONE, getFrom(p), p->id, p->channel, p->hop_start, p->hop_limit);
} else if (p->which_payload_variant == meshtastic_MeshPacket_encrypted_tag && p->channel == 0 &&
(nodeDB->getMeshNode(p->from) == nullptr || nodeDB->getMeshNode(p->from)->user.public_key.size == 0)) {
// This looks like it might be a PKI packet from an unknown node, so send PKI_UNKNOWN_PUBKEY
LOG_INFO("This looks like it might be a PKI packet from an unknown node, so send PKI_UNKNOWN_PUBKEY\n");
sendAckNak(meshtastic_Routing_Error_PKI_UNKNOWN_PUBKEY, getFrom(p), p->id, channels.getPrimaryIndex(),
p->hop_start, p->hop_limit);
} else {

View File

@@ -109,7 +109,7 @@ PacketId generatePacketId()
rollingPacketId++;
rollingPacketId &= UINT32_MAX >> 22; // Mask out the top 22 bits
rollingPacketId &= ID_COUNTER_MASK; // Mask out the top 22 bits
PacketId id = rollingPacketId | random(UINT32_MAX & 0x7fffffff) << 10; // top 22 bits
LOG_DEBUG("Partially randomized packet id %u\n", id);
return id;
@@ -165,6 +165,9 @@ meshtastic_QueueStatus Router::getQueueStatus()
ErrorCode Router::sendLocal(meshtastic_MeshPacket *p, RxSource src)
{
if (p->to == 0) {
LOG_ERROR("Packet received with to: of 0!\n");
}
// No need to deliver externally if the destination is the local node
if (p->to == nodeDB->getNodeNum()) {
printPacket("Enqueued local", p);
@@ -252,6 +255,8 @@ ErrorCode Router::send(meshtastic_MeshPacket *p)
return meshtastic_Routing_Error_BAD_REQUEST;
}
fixPriority(p); // Before encryption, fix the priority if it's unset
// If the packet is not yet encrypted, do so now
if (p->which_payload_variant == meshtastic_MeshPacket_decoded_tag) {
ChannelIndex chIndex = p->channel; // keep as a local because we are about to change it

View File

@@ -264,9 +264,7 @@ template <typename T> void SX126xInterface<T>::startReceive()
// We use a 16 bit preamble so this should save some power by letting radio sit in standby mostly.
// Furthermore, we need the PREAMBLE_DETECTED and HEADER_VALID IRQ flag to detect whether we are actively receiving
int err = lora.startReceiveDutyCycleAuto(preambleLength, 8,
RADIOLIB_SX126X_IRQ_RX_DEFAULT | RADIOLIB_SX126X_IRQ_PREAMBLE_DETECTED |
RADIOLIB_SX126X_IRQ_HEADER_VALID);
int err = lora.startReceiveDutyCycleAuto(preambleLength, 8, RADIOLIB_IRQ_RX_DEFAULT_FLAGS | RADIOLIB_IRQ_PREAMBLE_DETECTED);
if (err != RADIOLIB_ERR_NONE)
LOG_ERROR("Radiolib error %d when attempting SX126X startReceiveDutyCycleAuto!\n", err);
assert(err == RADIOLIB_ERR_NONE);
@@ -301,7 +299,7 @@ template <typename T> bool SX126xInterface<T>::isActivelyReceiving()
// The IRQ status will be cleared when we start our read operation. Check if we've started a header, but haven't yet
// received and handled the interrupt for reading the packet/handling errors.
uint16_t irq = lora.getIrqStatus();
uint16_t irq = lora.getIrqFlags();
bool detected = (irq & (RADIOLIB_SX126X_IRQ_HEADER_VALID | RADIOLIB_SX126X_IRQ_PREAMBLE_DETECTED));
// Handle false detections
if (detected) {

View File

@@ -25,7 +25,7 @@ template <class T> class SX126xInterface : public RadioLibInterface
/// Prepare hardware for sleep. Call this _only_ for deep sleep, not needed for light sleep.
virtual bool sleep() override;
bool isIRQPending() override { return lora.getIrqStatus() != 0; }
bool isIRQPending() override { return lora.getIrqFlags() != 0; }
protected:
float currentLimit = 140; // Higher OCP limit for SX126x PA

View File

@@ -256,9 +256,7 @@ template <typename T> void SX128xInterface<T>::startReceive()
#endif
// We use the PREAMBLE_DETECTED and HEADER_VALID IRQ flag to detect whether we are actively receiving
int err =
lora.startReceive(RADIOLIB_SX128X_RX_TIMEOUT_INF, RADIOLIB_SX128X_IRQ_RX_DEFAULT | RADIOLIB_SX128X_IRQ_PREAMBLE_DETECTED |
RADIOLIB_SX128X_IRQ_HEADER_VALID);
int err = lora.startReceive(RADIOLIB_SX128X_RX_TIMEOUT_INF, RADIOLIB_IRQ_RX_DEFAULT_FLAGS | RADIOLIB_IRQ_PREAMBLE_DETECTED);
if (err != RADIOLIB_ERR_NONE)
LOG_ERROR("Radiolib error %d when attempting SX128X startReceive!\n", err);

View File

@@ -27,7 +27,7 @@ template <class T> class SX128xInterface : public RadioLibInterface
/// Prepare hardware for sleep. Call this _only_ for deep sleep, not needed for light sleep.
virtual bool sleep() override;
bool isIRQPending() override { return lora.getIrqStatus() != 0; }
bool isIRQPending() override { return lora.getIrqFlags() != 0; }
protected:
/**

View File

@@ -532,7 +532,8 @@ typedef struct _meshtastic_Config_SecurityConfig {
Used to create a shared key with a remote device. */
meshtastic_Config_SecurityConfig_private_key_t private_key;
/* The public key authorized to send admin messages to this node. */
meshtastic_Config_SecurityConfig_admin_key_t admin_key;
pb_size_t admin_key_count;
meshtastic_Config_SecurityConfig_admin_key_t admin_key[1];
/* If true, device is considered to be "managed" by a mesh administrator via admin messages
Device is managed by a mesh administrator. */
bool is_managed;
@@ -657,7 +658,7 @@ extern "C" {
#define meshtastic_Config_DisplayConfig_init_default {0, _meshtastic_Config_DisplayConfig_GpsCoordinateFormat_MIN, 0, 0, 0, _meshtastic_Config_DisplayConfig_DisplayUnits_MIN, _meshtastic_Config_DisplayConfig_OledType_MIN, _meshtastic_Config_DisplayConfig_DisplayMode_MIN, 0, 0, _meshtastic_Config_DisplayConfig_CompassOrientation_MIN}
#define meshtastic_Config_LoRaConfig_init_default {0, _meshtastic_Config_LoRaConfig_ModemPreset_MIN, 0, 0, 0, 0, _meshtastic_Config_LoRaConfig_RegionCode_MIN, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0}, 0}
#define meshtastic_Config_BluetoothConfig_init_default {0, _meshtastic_Config_BluetoothConfig_PairingMode_MIN, 0}
#define meshtastic_Config_SecurityConfig_init_default {{0, {0}}, {0, {0}}, {0, {0}}, 0, 0, 0, 0}
#define meshtastic_Config_SecurityConfig_init_default {{0, {0}}, {0, {0}}, 0, {{0, {0}}}, 0, 0, 0, 0}
#define meshtastic_Config_SessionkeyConfig_init_default {0}
#define meshtastic_Config_init_zero {0, {meshtastic_Config_DeviceConfig_init_zero}}
#define meshtastic_Config_DeviceConfig_init_zero {_meshtastic_Config_DeviceConfig_Role_MIN, 0, 0, 0, _meshtastic_Config_DeviceConfig_RebroadcastMode_MIN, 0, 0, 0, 0, "", 0}
@@ -668,7 +669,7 @@ extern "C" {
#define meshtastic_Config_DisplayConfig_init_zero {0, _meshtastic_Config_DisplayConfig_GpsCoordinateFormat_MIN, 0, 0, 0, _meshtastic_Config_DisplayConfig_DisplayUnits_MIN, _meshtastic_Config_DisplayConfig_OledType_MIN, _meshtastic_Config_DisplayConfig_DisplayMode_MIN, 0, 0, _meshtastic_Config_DisplayConfig_CompassOrientation_MIN}
#define meshtastic_Config_LoRaConfig_init_zero {0, _meshtastic_Config_LoRaConfig_ModemPreset_MIN, 0, 0, 0, 0, _meshtastic_Config_LoRaConfig_RegionCode_MIN, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0}, 0}
#define meshtastic_Config_BluetoothConfig_init_zero {0, _meshtastic_Config_BluetoothConfig_PairingMode_MIN, 0}
#define meshtastic_Config_SecurityConfig_init_zero {{0, {0}}, {0, {0}}, {0, {0}}, 0, 0, 0, 0}
#define meshtastic_Config_SecurityConfig_init_zero {{0, {0}}, {0, {0}}, 0, {{0, {0}}}, 0, 0, 0, 0}
#define meshtastic_Config_SessionkeyConfig_init_zero {0}
/* Field tags (for use in manual encoding/decoding) */
@@ -900,7 +901,7 @@ X(a, STATIC, SINGULAR, UINT32, fixed_pin, 3)
#define meshtastic_Config_SecurityConfig_FIELDLIST(X, a) \
X(a, STATIC, SINGULAR, BYTES, public_key, 1) \
X(a, STATIC, SINGULAR, BYTES, private_key, 2) \
X(a, STATIC, SINGULAR, BYTES, admin_key, 3) \
X(a, STATIC, REPEATED, BYTES, admin_key, 3) \
X(a, STATIC, SINGULAR, BOOL, is_managed, 4) \
X(a, STATIC, SINGULAR, BOOL, serial_enabled, 5) \
X(a, STATIC, SINGULAR, BOOL, debug_log_api_enabled, 6) \
@@ -948,7 +949,7 @@ extern const pb_msgdesc_t meshtastic_Config_SessionkeyConfig_msg;
#define meshtastic_Config_NetworkConfig_size 196
#define meshtastic_Config_PositionConfig_size 62
#define meshtastic_Config_PowerConfig_size 52
#define meshtastic_Config_SecurityConfig_size 110
#define meshtastic_Config_SecurityConfig_size 111
#define meshtastic_Config_SessionkeyConfig_size 0
#define meshtastic_Config_size 199

View File

@@ -358,7 +358,7 @@ extern const pb_msgdesc_t meshtastic_OEMStore_msg;
#define MESHTASTIC_MESHTASTIC_DEVICEONLY_PB_H_MAX_SIZE meshtastic_OEMStore_size
#define meshtastic_ChannelFile_size 718
#define meshtastic_NodeInfoLite_size 183
#define meshtastic_OEMStore_size 3496
#define meshtastic_OEMStore_size 3497
#define meshtastic_PositionLite_size 28
#define meshtastic_UserLite_size 96

View File

@@ -187,7 +187,7 @@ extern const pb_msgdesc_t meshtastic_LocalModuleConfig_msg;
/* Maximum encoded size of messages (where known) */
#define MESHTASTIC_MESHTASTIC_LOCALONLY_PB_H_MAX_SIZE meshtastic_LocalModuleConfig_size
#define meshtastic_LocalConfig_size 663
#define meshtastic_LocalConfig_size 664
#define meshtastic_LocalModuleConfig_size 687
#ifdef __cplusplus

View File

@@ -196,6 +196,9 @@ typedef enum _meshtastic_HardwareModel {
https://www.adafruit.com/product/938
^^^ short A0 to switch to I2C address 0x3C */
meshtastic_HardwareModel_RP2040_FEATHER_RFM95 = 76,
/* M5 esp32 based MCU modules with enclosure, TFT and LORA Shields. All Variants (Basic, Core, Fire, Core2, Paper) https://m5stack.com/ */
meshtastic_HardwareModel_M5STACK_COREBASIC = 77,
meshtastic_HardwareModel_M5STACK_CORE2 = 78,
/* ------------------------------------------------------------------------------------------------------------------------------------------
Reserved ID For developing private Ports. These will show up in live traffic sparsely, so we can use a high number. Keep it within 8 bits.
------------------------------------------------------------------------------------------------------------------------------------------ */
@@ -347,6 +350,11 @@ typedef enum _meshtastic_MeshPacket_Priority {
/* If priority is unset but the message is marked as want_ack,
assume it is important and use a slightly higher priority */
meshtastic_MeshPacket_Priority_RELIABLE = 70,
/* If priority is unset but the packet is a response to a request, we want it to get there relatively quickly.
Furthermore, responses stop relaying packets directed to a node early. */
meshtastic_MeshPacket_Priority_RESPONSE = 80,
/* Higher priority for specific message types (portnums) to distinguish between other reliable packets. */
meshtastic_MeshPacket_Priority_HIGH = 100,
/* Ack/naks are sent with very high priority to ensure that retransmission
stops as soon as possible */
meshtastic_MeshPacket_Priority_ACK = 120,

View File

@@ -69,7 +69,9 @@ typedef enum _meshtastic_TelemetrySensorType {
/* ICM-20948 9-Axis digital motion processor */
meshtastic_TelemetrySensorType_ICM20948 = 27,
/* MAX17048 1S lipo battery sensor (voltage, state of charge, time to go) */
meshtastic_TelemetrySensorType_MAX17048 = 28
meshtastic_TelemetrySensorType_MAX17048 = 28,
/* Custom I2C sensor implementation based on https://github.com/meshtastic/i2c-sensor */
meshtastic_TelemetrySensorType_CUSTOM_SENSOR = 29
} meshtastic_TelemetrySensorType;
/* Struct definitions */
@@ -265,8 +267,8 @@ extern "C" {
/* Helper constants for enums */
#define _meshtastic_TelemetrySensorType_MIN meshtastic_TelemetrySensorType_SENSOR_UNSET
#define _meshtastic_TelemetrySensorType_MAX meshtastic_TelemetrySensorType_MAX17048
#define _meshtastic_TelemetrySensorType_ARRAYSIZE ((meshtastic_TelemetrySensorType)(meshtastic_TelemetrySensorType_MAX17048+1))
#define _meshtastic_TelemetrySensorType_MAX meshtastic_TelemetrySensorType_CUSTOM_SENSOR
#define _meshtastic_TelemetrySensorType_ARRAYSIZE ((meshtastic_TelemetrySensorType)(meshtastic_TelemetrySensorType_CUSTOM_SENSOR+1))

View File

@@ -68,7 +68,7 @@ void printBytes(const char *label, const uint8_t *p, size_t numbytes)
bool memfll(const uint8_t *mem, uint8_t find, size_t numbytes)
{
for (int i = 0; i < numbytes; i++) {
for (uint8_t i = 0; i < numbytes; i++) {
if (mem[i] != find)
return false;
}

View File

@@ -75,7 +75,7 @@ bool AdminModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshta
// and only allowing responses from that remote.
if (!((mp.from == 0 && !config.security.is_managed) || messageIsResponse(r) ||
(strcasecmp(ch->settings.name, Channels::adminChannel) == 0 && config.security.admin_channel_enabled) ||
(mp.pki_encrypted && memcmp(mp.public_key.bytes, config.security.admin_key.bytes, 32) == 0))) {
(mp.pki_encrypted && memcmp(mp.public_key.bytes, config.security.admin_key[0].bytes, 32) == 0))) {
LOG_INFO("Ignoring admin payload %i\n", r->which_payload_variant);
return handled;
}
@@ -288,7 +288,7 @@ bool AdminModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshta
tv.tv_sec = r->set_time_only;
tv.tv_usec = 0;
perhapsSetRTC(RTCQualityFromNet, &tv, false);
perhapsSetRTC(RTCQualityNTP, &tv, false);
break;
}
case meshtastic_AdminMessage_enter_dfu_mode_request_tag: {
@@ -537,6 +537,15 @@ void AdminModule::handleSetConfig(const meshtastic_Config &c)
case meshtastic_Config_security_tag:
LOG_INFO("Setting config: Security\n");
config.security = c.payload_variant.security;
#if !(MESHTASTIC_EXCLUDE_PKI_KEYGEN) && !(MESHTASTIC_EXCLUDE_PKI)
// We check for a potentially valid private key, and a blank public key, and regen the public key if needed.
if (config.security.private_key.size == 32 && !memfll(config.security.private_key.bytes, 0, 32) &&
(config.security.public_key.size == 0 || memfll(config.security.public_key.bytes, 0, 32))) {
if (crypto->regeneratePublicKey(config.security.public_key.bytes, config.security.private_key.bytes)) {
config.security.public_key.size = 32;
}
}
#endif
owner.public_key.size = config.security.public_key.size;
memcpy(owner.public_key.bytes, config.security.public_key.bytes, config.security.public_key.size);
#if !MESHTASTIC_EXCLUDE_PKI
@@ -1019,4 +1028,4 @@ bool AdminModule::messageIsRequest(meshtastic_AdminMessage *r)
return true;
else
return false;
}
}

View File

@@ -107,6 +107,7 @@ void NeighborInfoModule::sendNeighborInfo(NodeNum dest, bool wantReplies)
// because we want to get neighbors for the next cycle
p->to = dest;
p->decoded.want_response = wantReplies;
p->priority = meshtastic_MeshPacket_Priority_BACKGROUND;
printNeighborInfo("SENDING", &neighborInfo);
service->sendToMesh(p, RX_SRC_LOCAL, true);
}

View File

@@ -129,6 +129,10 @@ void PositionModule::trySetRtc(meshtastic_Position p, bool isLocal, bool forceUp
LOG_DEBUG("Ignoring time from mesh because we have a GPS, RTC, or Phone/NTP time source in the past day\n");
return;
}
if (!isLocal && p.location_source < meshtastic_Position_LocSource_LOC_INTERNAL) {
LOG_DEBUG("Ignoring time from mesh because it has a unknown or manual source\n");
return;
}
struct timeval tv;
uint32_t secs = p.time;
@@ -142,7 +146,11 @@ bool PositionModule::hasQualityTimesource()
{
bool setFromPhoneOrNtpToday =
lastSetFromPhoneNtpOrGps == 0 ? false : (millis() - lastSetFromPhoneNtpOrGps) <= (SEC_PER_DAY * 1000UL);
#if MESHTASTIC_EXCLUDE_GPS
bool hasGpsOrRtc = (rtc_found.address != ScanI2C::ADDRESS_NONE.address);
#else
bool hasGpsOrRtc = (gps && gps->isConnected()) || (rtc_found.address != ScanI2C::ADDRESS_NONE.address);
#endif
return hasGpsOrRtc || setFromPhoneOrNtpToday;
}
@@ -191,6 +199,10 @@ meshtastic_MeshPacket *PositionModule::allocReply()
p.has_longitude_i = true;
p.time = getValidTime(RTCQualityNTP) > 0 ? getValidTime(RTCQualityNTP) : localPosition.time;
if (config.position.fixed_position) {
p.location_source = meshtastic_Position_LocSource_LOC_MANUAL;
}
if (pos_flags & meshtastic_Config_PositionConfig_PositionFlags_ALTITUDE) {
if (pos_flags & meshtastic_Config_PositionConfig_PositionFlags_ALTITUDE_MSL) {
p.altitude = localPosition.altitude;

View File

@@ -23,6 +23,7 @@
#include "Sensor/BME680Sensor.h"
#include "Sensor/BMP085Sensor.h"
#include "Sensor/BMP280Sensor.h"
#include "Sensor/BMP3XXSensor.h"
#include "Sensor/DFRobotLarkSensor.h"
#include "Sensor/LPS22HBSensor.h"
#include "Sensor/MCP9808Sensor.h"
@@ -54,6 +55,7 @@ AHT10Sensor aht10Sensor;
MLX90632Sensor mlx90632Sensor;
DFRobotLarkSensor dfRobotLarkSensor;
NAU7802Sensor nau7802Sensor;
BMP3XXSensor bmp3xxSensor;
#ifdef T1000X_SENSOR_EN
T1000xSensor t1000xSensor;
#endif
@@ -107,6 +109,8 @@ int32_t EnvironmentTelemetryModule::runOnce()
result = bmp280Sensor.runOnce();
if (bme280Sensor.hasSensor())
result = bme280Sensor.runOnce();
if (bmp3xxSensor.hasSensor())
result = bmp3xxSensor.runOnce();
if (bme680Sensor.hasSensor())
result = bme680Sensor.runOnce();
if (mcp9808Sensor.hasSensor())
@@ -327,6 +331,10 @@ bool EnvironmentTelemetryModule::getEnvironmentTelemetry(meshtastic_Telemetry *m
valid = valid && bme280Sensor.getMetrics(m);
hasSensor = true;
}
if (bmp3xxSensor.hasSensor()) {
valid = valid && bmp3xxSensor.getMetrics(m);
hasSensor = true;
}
if (bme680Sensor.hasSensor()) {
valid = valid && bme680Sensor.getMetrics(m);
hasSensor = true;
@@ -372,15 +380,21 @@ bool EnvironmentTelemetryModule::getEnvironmentTelemetry(meshtastic_Telemetry *m
hasSensor = true;
}
if (aht10Sensor.hasSensor()) {
if (!bmp280Sensor.hasSensor()) {
if (!bmp280Sensor.hasSensor() && !bmp3xxSensor.hasSensor()) {
valid = valid && aht10Sensor.getMetrics(m);
hasSensor = true;
} else {
} else if (bmp280Sensor.hasSensor()) {
// prefer bmp280 temp if both sensors are present, fetch only humidity
meshtastic_Telemetry m_ahtx = meshtastic_Telemetry_init_zero;
LOG_INFO("AHTX0+BMP280 module detected: using temp from BMP280 and humy from AHTX0\n");
aht10Sensor.getMetrics(&m_ahtx);
m->variant.environment_metrics.relative_humidity = m_ahtx.variant.environment_metrics.relative_humidity;
} else {
// prefer bmp3xx temp if both sensors are present, fetch only humidity
meshtastic_Telemetry m_ahtx = meshtastic_Telemetry_init_zero;
LOG_INFO("AHTX0+BMP3XX module detected: using temp from BMP3XX and humy from AHTX0\n");
aht10Sensor.getMetrics(&m_ahtx);
m->variant.environment_metrics.relative_humidity = m_ahtx.variant.environment_metrics.relative_humidity;
}
}
@@ -508,6 +522,11 @@ AdminMessageHandleResult EnvironmentTelemetryModule::handleAdminMessageForModule
if (result != AdminMessageHandleResult::NOT_HANDLED)
return result;
}
if (bmp3xxSensor.hasSensor()) {
result = bmp3xxSensor.handleAdminMessage(mp, request, response);
if (result != AdminMessageHandleResult::NOT_HANDLED)
return result;
}
if (bme680Sensor.hasSensor()) {
result = bme680Sensor.handleAdminMessage(mp, request, response);
if (result != AdminMessageHandleResult::NOT_HANDLED)

View File

@@ -0,0 +1,89 @@
#include "configuration.h"
#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR
#include "BMP3XXSensor.h"
BMP3XXSensor::BMP3XXSensor() : TelemetrySensor(meshtastic_TelemetrySensorType_BMP3XX, "BMP3XX") {}
void BMP3XXSensor::setup() {}
int32_t BMP3XXSensor::runOnce()
{
LOG_INFO("Init sensor: %s\n", sensorName);
if (!hasSensor()) {
return DEFAULT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS;
}
// Get a singleton instance and initialise the bmp3xx
if (bmp3xx == nullptr) {
bmp3xx = BMP3XXSingleton::GetInstance();
}
status = bmp3xx->begin_I2C(nodeTelemetrySensorsMap[sensorType].first, nodeTelemetrySensorsMap[sensorType].second);
// set up oversampling and filter initialization
bmp3xx->setTemperatureOversampling(BMP3_OVERSAMPLING_4X);
bmp3xx->setPressureOversampling(BMP3_OVERSAMPLING_8X);
bmp3xx->setIIRFilterCoeff(BMP3_IIR_FILTER_COEFF_3);
bmp3xx->setOutputDataRate(BMP3_ODR_25_HZ);
// take a couple of initial readings to settle the sensor filters
for (int i = 0; i < 3; i++) {
bmp3xx->performReading();
}
return initI2CSensor();
}
bool BMP3XXSensor::getMetrics(meshtastic_Telemetry *measurement)
{
if (bmp3xx == nullptr) {
bmp3xx = BMP3XXSingleton::GetInstance();
}
if ((int)measurement->which_variant == meshtastic_Telemetry_environment_metrics_tag) {
bmp3xx->performReading();
measurement->variant.environment_metrics.has_temperature = true;
measurement->variant.environment_metrics.has_barometric_pressure = true;
measurement->variant.environment_metrics.has_relative_humidity = false;
measurement->variant.environment_metrics.temperature = static_cast<float>(bmp3xx->temperature);
measurement->variant.environment_metrics.barometric_pressure = static_cast<float>(bmp3xx->pressure) / 100.0F;
measurement->variant.environment_metrics.relative_humidity = 0.0f;
LOG_DEBUG("BMP3XXSensor::getMetrics id: %i temp: %.1f press %.1f\n", measurement->which_variant,
measurement->variant.environment_metrics.temperature,
measurement->variant.environment_metrics.barometric_pressure);
} else {
LOG_DEBUG("BMP3XXSensor::getMetrics id: %i\n", measurement->which_variant);
}
return true;
}
// Get a singleton wrapper for an Adafruit_bmp3xx
BMP3XXSingleton *BMP3XXSingleton::GetInstance()
{
if (pinstance == nullptr) {
pinstance = new BMP3XXSingleton();
}
return pinstance;
}
BMP3XXSingleton::BMP3XXSingleton() {}
BMP3XXSingleton::~BMP3XXSingleton() {}
BMP3XXSingleton *BMP3XXSingleton::pinstance{nullptr};
bool BMP3XXSingleton::performReading()
{
bool result = Adafruit_BMP3XX::performReading();
if (result) {
double atmospheric = this->pressure / 100.0;
altitudeAmslMetres = 44330.0 * (1.0 - pow(atmospheric / SEAL_LEVEL_HPA, 0.1903));
} else {
altitudeAmslMetres = 0.0;
}
return result;
}
#endif

View File

@@ -0,0 +1,56 @@
#include "configuration.h"
#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR
#ifndef _BMP3XX_SENSOR_H
#define _BMP3XX_SENSOR_H
#define SEAL_LEVEL_HPA 1013.2f
#include "TelemetrySensor.h"
#include <Adafruit_BMP3XX.h>
#include <typeinfo>
// Singleton wrapper for the Adafruit_BMP3XX class
class BMP3XXSingleton : public Adafruit_BMP3XX
{
private:
static BMP3XXSingleton *pinstance;
protected:
BMP3XXSingleton();
~BMP3XXSingleton();
public:
// Create a singleton instance (not thread safe)
static BMP3XXSingleton *GetInstance();
// Singletons should not be cloneable.
BMP3XXSingleton(BMP3XXSingleton &other) = delete;
// Singletons should not be assignable.
void operator=(const BMP3XXSingleton &) = delete;
// Performs a full reading of all sensors in the BMP3XX. Assigns
// the internal temperature, pressure and altitudeAmsl variables
bool performReading();
// Altitude in metres above mean sea level, assigned after calling performReading()
double altitudeAmslMetres = 0.0f;
};
class BMP3XXSensor : public TelemetrySensor
{
protected:
BMP3XXSingleton *bmp3xx = nullptr;
virtual void setup() override;
public:
BMP3XXSensor();
virtual int32_t runOnce() override;
virtual bool getMetrics(meshtastic_Telemetry *measurement) override;
};
#endif
#endif

View File

@@ -167,9 +167,9 @@ void MQTT::onReceive(char *topic, byte *payload, size_t length)
strcmp(e.channel_id, "PKI") == 0) {
meshtastic_NodeInfoLite *tx = nodeDB->getMeshNode(getFrom(p));
meshtastic_NodeInfoLite *rx = nodeDB->getMeshNode(p->to);
// Only accept PKI messages if we have both the sender and receiver in our nodeDB, as then it's likely
// they discovered each other via a channel we have downlink enabled for
if (tx && tx->has_user && rx && rx->has_user)
// Only accept PKI messages to us, or if we have both the sender and receiver in our nodeDB, as then it's
// likely they discovered each other via a channel we have downlink enabled for
if (p->to == nodeDB->getNodeNum() || (tx && tx->has_user && rx && rx->has_user))
router->enqueueReceivedMessage(p);
} else if (router && perhapsDecode(p)) // ignore messages if we don't have the channel key
router->enqueueReceivedMessage(p);
@@ -527,7 +527,7 @@ void MQTT::onSend(const meshtastic_MeshPacket &mp, const meshtastic_MeshPacket &
}
if (ch.settings.uplink_enabled || mp.pki_encrypted) {
const char *channelId = channels.getGlobalId(chIndex); // FIXME, for now we just use the human name for the channel
const char *channelId = mp.pki_encrypted ? "PKI" : channels.getGlobalId(chIndex);
meshtastic_ServiceEnvelope *env = mqttPool.allocZeroed();
env->channel_id = (char *)channelId;
@@ -546,12 +546,7 @@ void MQTT::onSend(const meshtastic_MeshPacket &mp, const meshtastic_MeshPacket &
// FIXME - this size calculation is super sloppy, but it will go away once we dynamically alloc meshpackets
static uint8_t bytes[meshtastic_MeshPacket_size + 64];
size_t numBytes = pb_encode_to_bytes(bytes, sizeof(bytes), &meshtastic_ServiceEnvelope_msg, env);
std::string topic;
if (mp.pki_encrypted) {
topic = cryptTopic + "PKI/" + owner.id;
} else {
topic = cryptTopic + channelId + "/" + owner.id;
}
std::string topic = cryptTopic + channelId + "/" + owner.id;
LOG_DEBUG("MQTT Publish %s, %u bytes\n", topic.c_str(), numBytes);
publish(topic.c_str(), bytes, numBytes, false);
@@ -561,12 +556,7 @@ void MQTT::onSend(const meshtastic_MeshPacket &mp, const meshtastic_MeshPacket &
// handle json topic
auto jsonString = MeshPacketSerializer::JsonSerialize((meshtastic_MeshPacket *)&mp_decoded);
if (jsonString.length() != 0) {
std::string topicJson;
if (mp.pki_encrypted) {
topicJson = jsonTopic + "PKI/" + owner.id;
} else {
topicJson = jsonTopic + channelId + "/" + owner.id;
}
std::string topicJson = jsonTopic + channelId + "/" + owner.id;
LOG_INFO("JSON publish message to %s, %u bytes: %s\n", topicJson.c_str(), jsonString.length(),
jsonString.c_str());
publish(topicJson.c_str(), jsonString.c_str(), false);

View File

@@ -122,6 +122,8 @@
#define HW_VENDOR meshtastic_HardwareModel_HELTEC_WIRELESS_PAPER
#elif defined(TLORA_T3S3_V1)
#define HW_VENDOR meshtastic_HardwareModel_TLORA_T3_S3
#elif defined(TLORA_T3S3_EPAPER)
#define HW_VENDOR meshtastic_HardwareModel_TLORA_T3_S3
#elif defined(CDEBYTE_EORA_S3)
#define HW_VENDOR meshtastic_HardwareModel_CDEBYTE_EORA_S3
#elif defined(BETAFPV_2400_TX)

View File

@@ -0,0 +1,15 @@
# About extra_variants
This directory tree is designed to solve two problems.
- The ESP32 arduino/platformio project doesn't support the nice "if initVariant() is found, call that after init" behavior of the nrf52 builds (they use initVariant() internally).
- Over the years a lot of 'board specific' init code has been added to init() in main.cpp. It would be great to have a general/clean mechanism to allow developers to specify board specific/unique code in a clean fashion without mucking in main.
So we are borrowing the initVariant() ideas here (by using weak gcc references). You can now define lateInitVariant() if your board needs it.
If you'd like a board specific variant to be run, add the variant.cpp file to an appropriately named
subdirectory and check for \_VARIANT_boardname in the cpp file (so that your code is only built for your board).
You'll need to define \_VARIANT_boardname in your corresponding variant.h file.
See existing boards for examples.
This approach has no added runtime cost.

View File

@@ -0,0 +1,34 @@
#include "configuration.h"
#ifdef _VARIANT_HELTEC_WIRELESS_TRACKER
#include "GPS.h"
#include "GpioLogic.h"
#include "graphics/TFTDisplay.h"
// Heltec tracker specific init
void lateInitVariant()
{
// LOG_DEBUG("Heltec tracker initVariant\n");
#ifdef VEXT_ENABLE
GpioPin *hwEnable = new GpioHwPin(VEXT_ENABLE);
GpioVirtPin *virtGpsEnable = gps ? gps->enablePin : new GpioVirtPin();
// On this board we are actually using the backlightEnable signal to already be controlling a physical enable to the
// display controller. But we'd _ALSO_ like to have that signal drive a virtual GPIO. So nest it as needed.
GpioVirtPin *virtScreenEnable = new GpioVirtPin();
if (TFTDisplay::backlightEnable) {
GpioPin *physScreenEnable = TFTDisplay::backlightEnable;
GpioPin *splitter = new GpioSplitter(virtScreenEnable, physScreenEnable);
TFTDisplay::backlightEnable = splitter;
// Assume screen is initially powered
splitter->set(true);
}
// If either the GPS or the screen is on, turn on the external power regulator
new GpioBinaryTransformer(virtGpsEnable, virtScreenEnable, hwEnable, GpioBinaryTransformer::Or);
#endif
}
#endif

View File

@@ -67,6 +67,8 @@
#define HW_VENDOR meshtastic_HardwareModel_TRACKER_T1000_E
#elif defined(ME25LS01_4Y10TD)
#define HW_VENDOR meshtastic_HardwareModel_ME25LS01_4Y10TD
#elif defined(MS24SF1)
#define HW_VENDOR meshtastic_HardwareModel_MS24SF1
#elif defined(PRIVATE_HW) || defined(FEATHER_DIY)
#define HW_VENDOR meshtastic_HardwareModel_PRIVATE_HW
#else

View File

@@ -7,7 +7,6 @@
#include <Utility.h>
#include <assert.h>
#include <time.h>
#include "PortduinoGlue.h"
#include "linux/gpio/LinuxGPIOPin.h"
@@ -370,6 +369,7 @@ void portduinoSetup()
exit(EXIT_FAILURE);
}
}
return;
}

View File

@@ -29,4 +29,6 @@
#define HW_VENDOR meshtastic_HardwareModel_SENSELORA_RP2040
#elif defined(RP2040_LORA)
#define HW_VENDOR meshtastic_HardwareModel_RP2040_LORA
#elif defined(RP2040_FEATHER_RFM95)
#define HW_VENDOR meshtastic_HardwareModel_RP2040_FEATHER_RFM95
#endif

View File

@@ -76,6 +76,13 @@ std::string MeshPacketSerializer::JsonSerialize(const meshtastic_MeshPacket *mp,
msgPayload["wind_direction"] = new JSONValue((uint)decoded->variant.environment_metrics.wind_direction);
msgPayload["wind_gust"] = new JSONValue(decoded->variant.environment_metrics.wind_gust);
msgPayload["wind_lull"] = new JSONValue(decoded->variant.environment_metrics.wind_lull);
} else if (decoded->which_variant == meshtastic_Telemetry_air_quality_metrics_tag) {
msgPayload["pm10"] = new JSONValue((unsigned int)decoded->variant.air_quality_metrics.pm10_standard);
msgPayload["pm25"] = new JSONValue((unsigned int)decoded->variant.air_quality_metrics.pm25_standard);
msgPayload["pm100"] = new JSONValue((unsigned int)decoded->variant.air_quality_metrics.pm100_standard);
msgPayload["pm10_e"] = new JSONValue((unsigned int)decoded->variant.air_quality_metrics.pm10_environmental);
msgPayload["pm25_e"] = new JSONValue((unsigned int)decoded->variant.air_quality_metrics.pm25_environmental);
msgPayload["pm100_e"] = new JSONValue((unsigned int)decoded->variant.air_quality_metrics.pm100_environmental);
} else if (decoded->which_variant == meshtastic_Telemetry_power_metrics_tag) {
msgPayload["voltage_ch1"] = new JSONValue(decoded->variant.power_metrics.ch1_voltage);
msgPayload["current_ch1"] = new JSONValue(decoded->variant.power_metrics.ch1_current);

View File

@@ -246,15 +246,8 @@ void doDeepSleep(uint32_t msecToWake, bool skipPreflight = false)
digitalWrite(RESET_OLED, 1); // put the display in reset before killing its power
#endif
#if defined(VEXT_ENABLE_V03)
digitalWrite(VEXT_ENABLE_V03, 1); // turn off the display power
#elif defined(VEXT_ENABLE_V05)
digitalWrite(VEXT_ENABLE_V05, 0); // turn off the lora amplifier power
digitalWrite(ST7735_BL_V05, 0); // turn off the display power
#elif defined(VEXT_ENABLE) && defined(VEXT_ON_VALUE)
#if defined(VEXT_ENABLE)
digitalWrite(VEXT_ENABLE, !VEXT_ON_VALUE); // turn on the display power
#elif defined(VEXT_ENABLE)
digitalWrite(VEXT_ENABLE, 1); // turn off the display power
#endif
#ifdef ARCH_ESP32

View File

@@ -1,58 +0,0 @@
# trunk-ignore-all(bandit/B404)
import subprocess
import usb.core
def find_usb_device(vendor_id, product_id):
# Find USB devices
dev = usb.core.find(find_all=True)
# Loop through devices, printing vendor and product ids in decimal and hex
for cfg in dev:
if cfg.idVendor == vendor_id and cfg.idProduct == product_id:
return cfg
return None
# Flash esp32 target
def flash_esp32(pio_env, port):
# trunk-ignore(bandit/B603)
# trunk-ignore(bandit/B607)
subprocess.run(
["platformio", "run", "-e", pio_env, "-t", "upload", "--upload-port", port]
)
def flash_nrf52(pio_env, port):
# trunk-ignore(bandit/B603)
# trunk-ignore(bandit/B607)
subprocess.run(
["platformio", "run", "-e", pio_env, "-t", "upload", "--upload-port", port]
)
def find_usb_device(vendor_id, product_id):
# Find USB devices
dev = usb.core.find(find_all=True)
# Loop through devices, printing vendor and product ids in decimal and hex
for cfg in dev:
if cfg.idVendor == vendor_id and cfg.idProduct == product_id:
return cfg
return None
# Flash esp32 target
def flash_esp32(pio_env, port):
# trunk-ignore(bandit/B603)
# trunk-ignore(bandit/B607)
subprocess.run(
["platformio", "run", "-e", pio_env, "-t", "upload", "--upload-port", port]
)
def flash_nrf52(pio_env, port):
# trunk-ignore(bandit/B603)
# trunk-ignore(bandit/B607)
subprocess.run(
["platformio", "run", "-e", pio_env, "-t", "upload", "--upload-port", port]
)

View File

@@ -1,42 +0,0 @@
import configparser
import subprocess
def readProps(prefsLoc):
"""Read the version of our project as a string"""
config = configparser.RawConfigParser()
config.read(prefsLoc)
version = dict(config.items("VERSION"))
verObj = dict(
short="{}.{}.{}".format(version["major"], version["minor"], version["build"]),
long="unset",
)
# Try to find current build SHA if if the workspace is clean. This could fail if git is not installed
try:
sha = (
subprocess.check_output(["git", "rev-parse", "--short", "HEAD"])
.decode("utf-8")
.strip()
)
isDirty = (
subprocess.check_output(["git", "diff", "HEAD"]).decode("utf-8").strip()
)
suffix = sha
# if isDirty:
# # short for 'dirty', we want to keep our verstrings source for protobuf reasons
# suffix = sha + "-d"
verObj["long"] = "{}.{}.{}.{}".format(
version["major"], version["minor"], version["build"], suffix
)
except:
# print("Unexpected error:", sys.exc_info()[0])
# traceback.print_exc()
verObj["long"] = verObj["short"]
# print("firmware version " + verStr)
return verObj
# print("path is" + ','.join(sys.path))

View File

@@ -1,59 +0,0 @@
import time
import flash
import meshtastic
import meshtastic.serial_interface
from readprops import readProps
version = readProps("version.properties")["long"]
def setup_users_prefs(prefsLoc):
with open(prefsLoc, "r") as file:
filedata = file.read()
filedata = filedata.replace(
"// #define CONFIG_LORA_REGION_USERPREFS",
"#define CONFIG_LORA_REGION_USERPREFS",
)
filedata = filedata.replace(
"// #define LORACONFIG_CHANNEL_NUM_USERPREFS",
"#define LORACONFIG_CHANNEL_NUM_USERPREFS",
)
filedata = filedata.replace(
"// #define CHANNEL_0_PRECISION", "#define CHANNEL_0_PRECISION"
)
with open(prefsLoc, "w") as file:
file.write(filedata)
def setup_device(port, pio_env, arch):
interface = meshtastic.serial_interface.SerialInterface(port)
try:
interface.waitForConfig()
if interface.metadata.firmware_version == version:
print("Already at local ref version", version)
else:
print(
"Device has version",
interface.metadata.firmware_version,
" updating to",
version,
)
interface.close()
time.sleep(1)
flash_device(port, pio_env, arch)
time.sleep(2)
except:
interface.close()
time.sleep(1)
flash_device(port, pio_env, arch)
time.sleep(2)
interface = meshtastic.serial_interface.SerialInterface(port)
interface.waitForConfig()
def flash_device(port, pio_env, arch):
if arch == "esp32":
flash.flash_esp32(pio_env=pio_env, port=port)
elif arch == "nrf52":
flash.flash_nrf52(pio_env=pio_env, port=port)

View File

@@ -1,121 +0,0 @@
import time
from typing import Dict, List, NamedTuple
import meshtastic
import meshtastic.serial_interface
import pytest
from dotmap import DotMap
from pubsub import pub # type: ignore[import-untyped]
from setup import setup_device, setup_users_prefs # type: ignore[import-untyped]
class ConnectedDevice(NamedTuple):
port: str
pio_env: str
arch: str
interface: meshtastic.serial_interface.SerialInterface
mesh_packets: List[meshtastic.mesh_pb2.FromRadio]
devices: Dict[str, ConnectedDevice] = {}
heltec_v3 = ["/dev/cu.usbserial-0001", "heltec-v3", "esp32"]
rak4631 = ["/dev/cu.usbmodem14101", "rak4631", "nrf52"]
tbeam = ["/dev/", "rak4631", "nrf52"]
setup_users_prefs("userPrefs.h")
for port_device in [heltec_v3, rak4631]:
print("Setting up device", port_device[1], "on port", port_device[0])
setup_device(port=port_device[0], pio_env=port_device[1], arch=port_device[2])
@pytest.fixture(scope="module", params=[rak4631, heltec_v3])
def device(request):
port = request.param[0]
pio_env = request.param[1]
arch = request.param[2]
if devices.get(port) is not None and devices[port].interface.isConnected:
yield devices[port]
else:
time.sleep(1)
devices[port] = ConnectedDevice(
port=port,
pio_env=pio_env,
arch=arch,
interface=meshtastic.serial_interface.SerialInterface(port),
mesh_packets=[],
)
yield devices[port]
# Tear down devices
devices[port].interface.close()
def default_on_receive(packet, interface):
print("Received packet", packet["decoded"], "interface", interface)
# find the device that sent the packet
for port in devices:
if devices[port].interface == interface:
devices[port].mesh_packets.append(packet)
# Test want_config responses from device
def test_should_get_and_set_config(device: ConnectedDevice):
assert device is not None, "Expected connected device"
assert (
len(device.interface.nodes) > 0
), "Expected at least one node in the device NodeDB"
assert (
device.interface.localNode.localConfig is not None
), "Expected LocalConfig to be set"
assert (
device.interface.localNode.moduleConfig is not None
), "Expected ModuleConfig to be set"
assert (
len(device.interface.localNode.channels) > 0
), "Expected at least one channel in the device"
pub.subscribe(default_on_receive, "meshtastic.receive")
device.interface.waitForAckNak
def test_should_send_text_message_and_receive_ack(device: ConnectedDevice):
# Send a text message
print("Sending text from device", device.pio_env)
device.interface.sendText(text="Test broadcast", wantAck=True)
# time.sleep(1)
# device.interface.waitForAckNak()
print("Received ack from device")
time.sleep(2)
# for port in devices:
# if devices[port].port != device.port:
# print("Checking device", devices[port].pio_env, "for received message")
# print(devices[port].mesh_packets)
# # Assert should have received a message
# # find text message in packets
# textPackets = list(
# filter(
# lambda packet: packet["decoded"]["portnum"]
# == meshtastic.portnums_pb2.TEXT_MESSAGE_APP
# and packet["decoded"]["payload"].decode("utf-8")
# == "Test broadcast",
# devices[port].mesh_packets,
# )
# )
# assert (
# len(textPackets) > 0
# ), "Expected a text message received on other device"
# # Assert should have received an ack
# ackPackets = list(
# filter(
# lambda packet: packet["decoded"]["portnum"]
# == meshtastic.portnums_pb2.ROUTING_APP,
# device.mesh_packets,
# )
# )
# assert len(ackPackets) > 0, "Expected an ack from the device"
if __name__ == "__main__":
pytest.main()

View File

@@ -0,0 +1,15 @@
[env:ms24sf1]
extends = nrf52840_base
board = ms24sf1
board_level = extra
; platform = https://github.com/maxgerhardt/platform-nordicnrf52#cac6fcf943a41accd2aeb4f3659ae297a73f422e
build_flags = ${nrf52840_base.build_flags} -Ivariants/MS24SF1 -Isrc/platform/nrf52/softdevice -Isrc/platform/nrf52/softdevice/nrf52
-L "${platformio.libdeps_dir}/${this.__env__}/bsec2/src/cortex-m4/fpv4-sp-d16-hard"
-DGPS_POWER_TOGGLE ; comment this line to disable triple press function on the user button to turn off gps entirely.
board_build.ldscript = src/platform/nrf52/nrf52840_s140_v7.ld
build_src_filter = ${nrf52_base.build_src_filter} +<../variants/MS24SF1>
lib_deps =
${nrf52840_base.lib_deps}
; If not set we will default to uploading over serial (first it forces bootloader entry by talking 1200bps to cdcacm)
upload_protocol = nrfutil
upload_port = /dev/ttyACM1

View File

@@ -0,0 +1,30 @@
/*
Copyright (c) 2014-2015 Arduino LLC. All right reserved.
Copyright (c) 2016 Sandeep Mistry All right reserved.
Copyright (c) 2018, Adafruit Industries (adafruit.com)
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "variant.h"
#include "nrf.h"
#include "wiring_constants.h"
#include "wiring_digital.h"
const uint32_t g_ADigitalPinMap[] = {
// P0
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
// P1
32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47};
void initVariant() {}

139
variants/MS24SF1/variant.h Normal file
View File

@@ -0,0 +1,139 @@
/*
Copyright (c) 2014-2015 Arduino LLC. All right reserved.
Copyright (c) 2016 Sandeep Mistry All right reserved.
Copyright (c) 2018, Adafruit Industries (adafruit.com)
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _VARIANT_MINEWSEMI_MS24SF1_
#define _VARIANT_MINEWSEMI_MS24SF1_
#define ME25LS01
/** Master clock frequency */
#define VARIANT_MCK (64000000ul)
#define USE_LFXO // Board uses 32khz crystal for LF
/*----------------------------------------------------------------------------
* Headers
*----------------------------------------------------------------------------*/
#include "WVariant.h"
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
// Number of pins defined in PinDescription array
#define PINS_COUNT (48)
#define NUM_DIGITAL_PINS (48)
#define NUM_ANALOG_INPUTS (6)
#define NUM_ANALOG_OUTPUTS (0)
// Use the native nrf52 usb power detection
#define NRF_APM
#define PIN_3V3_EN (32 + 5) //-1
#define PIN_3V3_ACC_EN -1
#define PIN_LED1 (-1)
#define LED_PIN PIN_LED1
#define LED_BUILTIN -1
#define LED_BLUE -1
#define LED_STATE_ON 1 // State when LED is lit
#define BUTTON_PIN (-1)
#define BUTTON_NEED_PULLUP
#define HAS_WIRE 1
#define WIRE_INTERFACES_COUNT 1
#define PIN_WIRE_SDA (0 + 29) // P0.15
#define PIN_WIRE_SCL (0 + 30) // P0.17
/*
* Serial interfaces
*/
#define PIN_SERIAL1_RX (-1) // P0.14
#define PIN_SERIAL1_TX (-1) // P0.13
#define PIN_SERIAL2_RX (-1) // P0.17
#define PIN_SERIAL2_TX (-1) // P0.16
/*
* SPI Interfaces
*/
#define SPI_INTERFACES_COUNT 1 // 2
#define PIN_SPI_MISO (0 + 17) // MISO P0.17
#define PIN_SPI_MOSI (0 + 20) // MOSI P0.20
#define PIN_SPI_SCK (0 + 21) // SCK P0.21
// #define PIN_SPI1_MISO (-1) //
// #define PIN_SPI1_MOSI (10) // EPD_MOSI P0.10
// #define PIN_SPI1_SCK (9) // EPD_SCLK P0.09
static const uint8_t SS = (0 + 22); // LORA_CS P0.22
static const uint8_t MOSI = PIN_SPI_MOSI;
static const uint8_t MISO = PIN_SPI_MISO;
static const uint8_t SCK = PIN_SPI_SCK;
// MINEWSEMI nRF52840+SX1262 MS24SF1 (NRF82540 with integrated SX1262)
#define USE_SX1262
#define SX126X_CS (0 + 22) // LORA_CS P0.22
#define SX126X_DIO1 (0 + 16) // DIO1 P0.16
#define SX126X_BUSY (0 + 19) // LORA_BUSY P0.19
#define SX126X_RESET (0 + 12) // LORA_RESET P0.12
#define SX126X_TXEN (32 + 4) // TXEN P1.04
#define SX126X_RXEN (32 + 2) // RXEN P1.02
// DIO2 controlls an antenna switch and the TCXO voltage is controlled by DIO3
#define SX126X_DIO2_AS_RF_SWITCH
#define HAS_GPS 0
#define PIN_GPS_EN -1
#define GPS_EN_ACTIVE HIGH
#define PIN_GPS_RESET -1
#define GPS_VRTC_EN -1
#define GPS_SLEEP_INT -1
#define GPS_RTC_INT -1
#define GPS_RESETB_OUT -1
#define BATTERY_PIN -1
#define ADC_MULTIPLIER (2.0F)
#define ADC_RESOLUTION 14
#define BATTERY_SENSE_RESOLUTION_BITS 12
#undef AREF_VOLTAGE
#define AREF_VOLTAGE 3.0
#define VBAT_AR_INTERNAL AR_INTERNAL_3_0
// Buzzer
// #define PIN_BUZZER (0 + 25)
#ifdef __cplusplus
}
#endif
/*----------------------------------------------------------------------------
* Arduino objects - C++ only
*----------------------------------------------------------------------------*/
#endif // _VARIANT_MINEWSEMI_MS24SF1_

View File

@@ -54,7 +54,7 @@
#define ST7735_RESET 15
#define ST7735_MISO -1
#define ST7735_BUSY -1
#define ST7735_BL 32
#define TFT_BL 32
#define ST7735_SPI_HOST HSPI_HOST // SPI2_HOST for S3, auto may work too
#define SPI_FREQUENCY 40000000
#define SPI_READ_FREQUENCY 16000000

View File

@@ -0,0 +1,16 @@
[env:feather_rp2040_rfm95]
extends = rp2040_base
board = adafruit_feather
upload_protocol = picotool
# add our variants files to the include and src paths
build_flags = ${rp2040_base.build_flags}
-DRP2040_FEATHER_RFM95
-Ivariants/feather_rp2040_rfm95
-DDEBUG_RP2040_PORT=Serial
-DHW_SPI1_DEVICE
-L "${platformio.libdeps_dir}/${this.__env__}/bsec2/src/cortex-m0plus"
lib_deps =
${rp2040_base.lib_deps}
debug_build_flags = ${rp2040_base.build_flags}
debug_tool = cmsis-dap ; for e.g. Picotool

View File

@@ -0,0 +1,61 @@
// #define RADIOLIB_CUSTOM_ARDUINO 1
// #define RADIOLIB_TONE_UNSUPPORTED 1
// #define RADIOLIB_SOFTWARE_SERIAL_UNSUPPORTED 1
#define ARDUINO_ARCH_AVR
// #define USE_SSD1306
// #define USE_SH1106 1
// default I2C pins:
// SDA = 4
// SCL = 5
// Recommended pins for SerialModule:
// txd = 8
// rxd = 9
#define EXT_NOTIFY_OUT 22
#define BUTTON_PIN 7
// #define BUTTON_NEED_PULLUP
#define LED_PIN PIN_LED
// #define BATTERY_PIN 26
// ratio of voltage divider = 3.0 (R17=200k, R18=100k)
// #define ADC_MULTIPLIER 3.1 // 3.0 + a bit for being optimistic
#define USE_RF95 // RFM95/SX127x
#undef LORA_SCK
#undef LORA_MISO
#undef LORA_MOSI
#undef LORA_CS
// https://www.adafruit.com/product/5714
// https://learn.adafruit.com/feather-rp2040-rfm95
// https://learn.adafruit.com/assets/120283
// https://learn.adafruit.com/assets/120813
#define LORA_SCK 14 // 10 12P
#define LORA_MISO 8 // 12 10P
#define LORA_MOSI 15 // 11 11P
#define LORA_CS 16 // 3 13P
#define LORA_RESET 17 // 15 14P
#define LORA_DIO0 21 // ?? 6P
#define LORA_DIO1 22 // 20 7P
#define LORA_DIO2 23 // 2 8P
#define LORA_DIO3 19 // ?? 3P
#define LORA_DIO4 20 // ?? 4P
#define LORA_DIO5 18 // ?? 15P
#ifdef USE_SX1262
#define SX126X_CS LORA_CS
#define SX126X_DIO1 LORA_DIO1
#define SX126X_BUSY LORA_DIO2
#define SX126X_RESET LORA_RESET
#define SX126X_DIO2_AS_RF_SWITCH
// #define SX126X_DIO3_TCXO_VOLTAGE 1.8
#endif

View File

@@ -7,9 +7,10 @@ debug_tool = jlink
# add -DCFG_SYSVIEW if you want to use the Segger systemview tool for OS profiling.
build_flags = ${nrf52840_base.build_flags} -Ivariants/heltec_mesh_node_t114
-L "${platformio.libdeps_dir}/${this.__env__}/bsec2/src/cortex-m4/fpv4-sp-d16-hard"
-DGPS_POWER_TOGGLE
build_src_filter = ${nrf52_base.build_src_filter} +<../variants/heltec_mesh_node_t114>
lib_deps =
${nrf52840_base.lib_deps}
lewisxhe/PCF8563_Library@^1.0.1
https://github.com/Bei-Ji-Quan/st7789#b8e7e076714b670764139289d3829b0beff67edb
https://github.com/meshtastic/st7789#7181320e7ed05c7fb5fd2d32f14723bce6088b7b

View File

@@ -49,7 +49,7 @@ extern "C" {
// #define ST7789_BL (32+6)
#define TFT_BACKLIGHT_ON LOW
#define ST7789_SPI_HOST SPI1_HOST
// #define ST7789_BACKLIGHT_EN (32+6)
// #define TFT_BL (32+6)
#define SPI_FREQUENCY 40000000
#define SPI_READ_FREQUENCY 16000000
#define TFT_HEIGHT 135

View File

@@ -9,5 +9,5 @@ build_flags =
lib_deps =
${esp32s3_base.lib_deps}
lewisxhe/PCF8563_Library@^1.0.1
https://github.com/Bei-Ji-Quan/st7789#b8e7e076714b670764139289d3829b0beff67edb
https://github.com/meshtastic/st7789#7181320e7ed05c7fb5fd2d32f14723bce6088b7b
upload_speed = 921600

View File

@@ -1,4 +1,6 @@
#define BUTTON_PIN 0
#define BUTTON_PIN_SECONDARY 21 // Second built-in button
#define BUTTON_SECONDARY_CANNEDMESSAGES // By default, use the secondary button as canned message input
// I2C
#define I2C_SDA SDA

View File

@@ -22,6 +22,7 @@
// Power
#define VEXT_ENABLE 45 // Active low, powers the E-Ink display
#define VEXT_ON_VALUE LOW
#define ADC_CTRL 19
#define BATTERY_PIN 20
#define ADC_CHANNEL ADC2_GPIO20_CHANNEL
@@ -29,6 +30,7 @@
#define BAT_MEASURE_ADC_UNIT 2 // Use ADC2
#define ADC_ATTENUATION ADC_ATTEN_DB_12 // Voltage divider output is quite high
#define HAS_32768HZ
#define ADC_CTRL_ENABLED LOW
// LoRa
#define USE_SX1262
@@ -49,4 +51,4 @@
#define SX126X_RESET LORA_RESET
#define SX126X_DIO2_AS_RF_SWITCH
#define SX126X_DIO3_TCXO_VOLTAGE 1.8
#define SX126X_DIO3_TCXO_VOLTAGE 1.8

View File

@@ -22,6 +22,7 @@
// Power
#define VEXT_ENABLE 45 // Active low, powers the E-Ink display
#define VEXT_ON_VALUE LOW
#define ADC_CTRL 19
#define BATTERY_PIN 20
#define ADC_CHANNEL ADC2_GPIO20_CHANNEL
@@ -29,6 +30,7 @@
#define BAT_MEASURE_ADC_UNIT 2 // Use ADC2
#define ADC_ATTENUATION ADC_ATTEN_DB_12 // Voltage divider output is quite high
#define HAS_32768HZ
#define ADC_CTRL_ENABLED LOW
// LoRa
#define USE_SX1262
@@ -49,4 +51,4 @@
#define SX126X_RESET LORA_RESET
#define SX126X_DIO2_AS_RF_SWITCH
#define SX126X_DIO3_TCXO_VOLTAGE 1.8
#define SX126X_DIO3_TCXO_VOLTAGE 1.8

View File

@@ -1,5 +1,6 @@
#define LED_PIN 18
#define _VARIANT_HELTEC_WIRELESS_TRACKER
#define HELTEC_TRACKER_V1_X
// I2C
@@ -15,7 +16,7 @@
#define ST7735_RESET 39
#define ST7735_MISO -1
#define ST7735_BUSY -1
#define ST7735_BL_V05 21 /* V1.1 PCB marking */
#define TFT_BL 21 /* V1.1 PCB marking */
#define ST7735_SPI_HOST SPI3_HOST
#define SPI_FREQUENCY 40000000
#define SPI_READ_FREQUENCY 16000000
@@ -31,15 +32,17 @@
// GPS UC6580: GPS V_DET(8), VDD_IO(7), DCDC_IN(21), pulls up RESETN(17), D_SEL(33) and BOOT_MODE(34) through 10kR
// GPS LNA SW7125DE: VCC(4), pulls up SHDN(5) through 10kR
// LED: VDD, LEDA (through diode)
#define VEXT_ENABLE_V05 3 // active HIGH - powers the GPS, GPS LNA and OLED VDD/anode
#define VEXT_ENABLE 3 // active HIGH - powers the GPS, GPS LNA and OLED
#define VEXT_ON_VALUE HIGH
#define BUTTON_PIN 0
#define BATTERY_PIN 1 // A battery voltage measurement pin, voltage divider connected here to measure battery voltage
#define ADC_CHANNEL ADC1_GPIO1_CHANNEL
#define ADC_ATTENUATION ADC_ATTEN_DB_2_5 // lower dB for high resistance voltage divider
#define ADC_MULTIPLIER 4.9 * 1.045
#define ADC_CTRL 2 // active HIGH, powers the voltage divider. Only on 1.1
#define ADC_CTRL_ENABLED HIGH
#define ADC_CTRL 2 // active HIGH, powers the voltage divider. Only on 1.1
#define ADC_USE_PULLUP // Use internal pullup/pulldown instead of actively driving the output
#undef GPS_RX_PIN
#undef GPS_TX_PIN
@@ -72,4 +75,4 @@
#define SX126X_RESET LORA_RESET
#define SX126X_DIO2_AS_RF_SWITCH
#define SX126X_DIO3_TCXO_VOLTAGE 1.8
#define SX126X_DIO3_TCXO_VOLTAGE 1.8

View File

@@ -15,7 +15,7 @@
#define ST7735_RESET 39
#define ST7735_MISO -1
#define ST7735_BUSY -1
#define ST7735_BL_V03 45
#define TFT_BL 45
#define ST7735_SPI_HOST SPI3_HOST
#define SPI_FREQUENCY 40000000
#define SPI_READ_FREQUENCY 16000000
@@ -24,11 +24,12 @@
#define TFT_WIDTH DISPLAY_HEIGHT
#define TFT_OFFSET_X 26
#define TFT_OFFSET_Y -1
#define VTFT_CTRL_V03 46 // Heltec Tracker needs this pulled low for TFT
#define VTFT_CTRL 46 // Heltec Tracker needs this pulled low for TFT
#define SCREEN_TRANSITION_FRAMERATE 3 // fps
#define DISPLAY_FORCE_SMALL_FONTS
#define VEXT_ENABLE_V03 Vext // active low, powers the oled display and the lora antenna boost
#define VEXT_ENABLE Vext // active low, powers the oled display and the lora antenna boost
#define VEXT_ON_VALUE LOW
#define BUTTON_PIN 0
#define BATTERY_PIN 1 // A battery voltage measurement pin, voltage divider connected here to measure battery voltage
@@ -43,8 +44,7 @@
#define PIN_GPS_RESET 35
#define PIN_GPS_PPS 36
#define VGNSS_CTRL_V03 37 // Heltec Tracker needs this pulled low for GPS
#define PIN_GPS_EN VGNSS_CTRL_V03
#define PIN_GPS_EN 37 // Heltec Tracker needs this pulled low for GPS
#define GPS_EN_ACTIVE LOW
#define GPS_RESET_MODE LOW
@@ -69,4 +69,4 @@
#define SX126X_RESET LORA_RESET
#define SX126X_DIO2_AS_RF_SWITCH
#define SX126X_DIO3_TCXO_VOLTAGE 1.8
#define SX126X_DIO3_TCXO_VOLTAGE 1.8

View File

@@ -4,6 +4,7 @@
#define LED_PIN LED
#define VEXT_ENABLE Vext // active low, powers the oled display and the lora antenna boost
#define VEXT_ON_VALUE LOW
#define BUTTON_PIN 0
#define ADC_CTRL 37
@@ -32,4 +33,4 @@
#define SX126X_RESET LORA_RESET
#define SX126X_DIO2_AS_RF_SWITCH
#define SX126X_DIO3_TCXO_VOLTAGE 1.8
#define SX126X_DIO3_TCXO_VOLTAGE 1.8

View File

@@ -144,7 +144,7 @@ static const uint8_t SCK = PIN_SPI_SCK;
#define ST7735_RESET (11) // Output
#define ST7735_CS (12)
#define ST7735_BACKLIGHT_EN (13)
#define TFT_BL (13)
#define ST7735_RS (9)
// #define LORA_DISABLE_SENDING // The board can brownout during lora TX if you don't have a battery connected. Disable sending
@@ -158,4 +158,4 @@ static const uint8_t SCK = PIN_SPI_SCK;
* Arduino objects - C++ only
*----------------------------------------------------------------------------*/
#endif
#endif

View File

@@ -166,7 +166,7 @@ static const uint8_t SCK = PIN_SPI_SCK;
// ST7565 SPI
#define ST7735_RESET (11) // Output
#define ST7735_CS (12)
#define ST7735_BACKLIGHT_EN (13)
#define TFT_BL (13)
#define ST7735_RS (9)
#define ST7735_SDA (39) // actually spi MOSI
#define ST7735_SCK (37) // actually spi clk
@@ -185,4 +185,4 @@ static const uint8_t SCK = PIN_SPI_SCK;
* Arduino objects - C++ only
*----------------------------------------------------------------------------*/
#endif
#endif

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