Compare commits

...
Author SHA1 Message Date
Ben Meadors 404d0dda79 Fix - Add GeoChat To field to payloads and handle compression (#3199)
* WIP ATAK plugin message handling

* Log

* Update size and regen

* Rework protos and remove compression

* Track

* Altitude

* Protos

* Protos and formatting

* Add to column

* Fixes / updates

* Doh!

* S

* Refactoring and compression fixes

* Fix missing (to) from ATAK geochat

* Trunk

* Explicitly set has_to

* Fmt

* Protobufs
2024-02-10 14:20:04 -06:00
github-actions[bot]andthebentern 514c19a68e [create-pull-request] automated change (#3198)
Co-authored-by: thebentern <thebentern@users.noreply.github.com>
2024-02-10 14:16:46 -06:00
Ben Meadors 1085b54069 ATAK plugin (#3189)
* WIP ATAK plugin message handling

* Log

* Update size and regen

* Rework protos and remove compression

* Track

* Altitude

* Protos

* Protos and formatting

* Add to column

* Fixes / updates

* Doh!

* S

* Refactoring and compression fixes
2024-02-09 20:31:10 -06:00
GUVWAFandBen Meadors bcbc2f229d Only cancel packet in Tx queue if it was already sent out via LoRa (#3191)
To avoid canceling a transmission if it was already ACKed via MQTT

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2024-02-09 17:36:16 -06:00
Andrew YongandBen Meadors 74b90d3505 Add Singapore Region (#3165)
Add 923MHz band for Singapore.

Regulatory reference: https://www.imda.gov.sg/-/media/imda/files/regulation-licensing-and-consultations/ict-standards/telecommunication-standards/radio-comms/imdatssrd.pdf bands 30d.

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2024-02-09 15:52:08 -06:00
github-actions[bot]andthebentern d246c47ae7 [create-pull-request] automated change (#3192)
Co-authored-by: thebentern <thebentern@users.noreply.github.com>
2024-02-09 15:50:00 -06:00
Manuel 54e52ae05f Improved button-click accuracy (#3188)
* IRQ triggers button fsm

* revert change that causes raspbian compile-error
2024-02-09 12:06:56 -06:00
todd-herbertandBen Meadors 8130b1cf43 feat: initial support for Heltec Wireless Paper v1.0 (#3181)
E-ink panel is DEPG0213BNS800. Otherwise, identical to v1.1 (?)
Partial refresh supported, but not implemented in this commit.

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2024-02-08 19:00:13 -06:00
github-actions[bot]andthebentern 9d4c4f8bd1 [create-pull-request] automated change (#3186)
Co-authored-by: thebentern <thebentern@users.noreply.github.com>
2024-02-08 18:57:23 -06:00
Jonathan Bennett 3b0169ba7a Adafruit display (#3179)
* Use uint8_t instead of char in icon_bits

* Add Adafruit PiTFT support
2024-02-08 16:29:15 -06:00
github-actions[bot]andthebentern 996e72a816 [create-pull-request] automated change (#3185)
Co-authored-by: thebentern <thebentern@users.noreply.github.com>
2024-02-08 16:14:58 -06:00
GUVWAF a40b4e4d69 MQTT JSON downlink fixes (#3183)
* Fix getting channel name from MQTT topic

* Allow specifying channel index in JSON field "channel" for downlink
Still requires JSON message to be published to channel named "mqtt"

* Make non-breaking if someone adds another slash
2024-02-08 15:43:24 -06:00
code8buster f4151a7108 Merge pull request #3184 from meshtastic/rp2040-ADC-hotfix
Fix analog adc init resolution for all architectures
2024-02-08 21:36:08 +00:00
Ben Meadors a3755dfce5 Trunk fmt 2024-02-08 14:56:46 -06:00
code8buster ca5795d3e7 Fix init resolution for all architectures 2024-02-08 20:46:22 +00:00
Tommy Ekstrand 990ee5dacf Update link to docs from webserver when file not found (#3175) 2024-02-08 14:06:29 -06:00
4c55d5d9e4 GPS rework phase 2 updates for M8 and stub for M10 (#3166)
* Portduino multiple logging levels

* Fixes based on GPSFan work

* Fix derped logic

* Correct size field for AID message

* Reformat to add comments, beginning of GPS rework

* Update PM2 message for Neo-6

* Correct ECO mode logic as ECO mode is only for Neo-6

* Cleanup ubx.h add a few more comments

* GPS rework, changes for M8 and stub for M10

---------

Co-authored-by: Jonathan Bennett <jbennett@incomsystems.biz>
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2024-02-05 09:02:30 -06:00
github-actions[bot]andthebentern 7db02ad722 [create-pull-request] automated change (#3161)
Co-authored-by: thebentern <thebentern@users.noreply.github.com>
2024-02-01 16:33:40 -06:00
Ben Meadorsandmverch67 7f7c5cbd62 Triple GPS state (#3157)
* Triple state GPS refactoring

* Skip probe

* Move GPS toggle into the GPSThread

* Consolidate

* make all happy (including me)

* corrected screen texts

* NOT_PRESENT guard in main.cpp

---------

Co-authored-by: mverch67 <manuel.verch@gmx.de>
2024-02-01 15:24:39 -06:00
GUVWAFandBen Meadors 0c0a3c4b55 Fix: mark packet sent to MQTT as ACKed only after we sent it out via LoRa (#3155)
* Fix: mark packet via MQTT as ACKed only after we sent it out via LoRa

* Don't need to check for broadcast, DMs also get implicit ACKs

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2024-01-31 14:04:52 -06:00
github-actions[bot]andthebentern bf762bc58d [create-pull-request] automated change (#3156)
Co-authored-by: thebentern <thebentern@users.noreply.github.com>
2024-01-31 13:47:17 -06:00
Ben Meadors 84e578323e Update version.properties 2024-01-31 13:46:48 -06:00
Ben Meadors bdbe42dfd0 Update version.properties 2024-01-31 12:58:04 -06:00
github-actions[bot]andthebentern 4f64c4f7b9 [create-pull-request] automated change (#3154)
Co-authored-by: thebentern <thebentern@users.noreply.github.com>
2024-01-30 20:01:00 -06:00
Jonathan Bennett af5ac32048 Re-order GPS check to eliminate TOO old message (#3152) 2024-01-30 17:44:08 -06:00
9586c68c65 GPS updates (#3142)
* Portduino multiple logging levels

* Fixes based on GPSFan work

* Fix derped logic

* Correct size field for AID message

* Reformat to add comments, beginning of GPS rework

* Update PM2 message for Neo-6

* Correct ECO mode logic as ECO mode is only for Neo-6

* Cleanup ubx.h add a few more comments

---------

Co-authored-by: Jonathan Bennett <jbennett@incomsystems.biz>
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2024-01-30 17:38:31 -06:00
ca45888f3e feat(variants): Add support for TXCO on TLORA_V2_1_6 devices (#3124)
* feat(variants): Add support for TXCO on TLORA_V2_1_6 devices

* chore: remove long comment

* feat(variants): Add tlora-v2-1-1_6-tcxo to build matrix

* feat(variants): Use RADIOLIB_NC as DIO1 pin for tlora_v2_1_16 with TXCO

* Use generic naming scheme, add variant to build envs

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
Co-authored-by: code8buster <20384924+code8buster@users.noreply.github.com>
2024-01-30 07:06:47 -06:00
Andre K 1e4ecea6fc update to Meshtastic_nRF52_factory_erase_v2 (#3146) 2024-01-29 20:07:09 -06:00
code8busterandBen Meadors d1ea589757 Allow NRF52 ADC overrides; begin simplifying analog battery logic (#3134)
* Isolate esp32 adc logic gymnastics, try simplifying getBattVoltage

* Set sense resolution for pico platforms

* try silencing cppcheck when variant has no battery pin

* ADC channel for esp-idf calibration

* Missed an rp2040 device

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2024-01-29 06:14:21 -06:00
GUVWAFandBen Meadors af52dcecdf Restrict MQTT JSON downlink messages (#3141)
Channel needs to be named "mqtt"
"from" field should be set to the node number of the transmitter

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2024-01-29 06:13:56 -06:00
Ben Meadors 0ae4622393 Admin message to delete file (#3144)
* Protos

* Delete file admin message
2024-01-29 06:10:48 -06:00
Jonathan Bennett a49740cd56 Adds i2c device configuration to native (#3143) 2024-01-28 20:15:29 -06:00
GUVWAF 417feee47f Fix: return failure when PhoneAPI times out (#3136)
* Add debug options for RP2040

* Rename: "observed" should be plural: "observables"

* PhoneAPI: return failure on timeout
In `onNotify()`, when disconnected, PhoneAPI removed itself from the list of observers that was looped through in `notifyObservers()`. We should exit that loop in that case.
2024-01-28 07:53:39 -06:00
Jonathan Bennett d604a76c73 Use correct define for native gos (#3133) 2024-01-26 09:06:15 -06:00
Ken McGuireandcode8buster ac9c5f81b9 Add CircutMess Chatter 2 (#3125)
* Add Chatter 2 default_envs

* Add Chatter 2 to varients

* Add Chatter 2 specific code to esp32 platform code

* Parameterize TFT_INVERT for Chatter 2 and specify setRotation to 1

* Fix formatting to make Trunk happy

* Remove commented out #define USE_LCC68

* Fix formatting again

* Add chatter2 to the CI matrix

---------

Co-authored-by: code8buster <20384924+code8buster@users.noreply.github.com>
2024-01-26 08:40:16 -06:00
Andre KandBen Meadors d6fa190025 fix: allow MQTT encryption_enabled with json_enabled (#3126)
* fix: allow MQTT `encryption_enabled` with `json_enabled`

* fix: copy decoded MeshPacket and release memory after use

* fix: use `packetPool` allocCopy and release methods

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2024-01-25 08:42:34 -06:00
Manuel f2c04c5504 fix MQTT crash (#3127) 2024-01-24 14:01:50 -06:00
Jonathan Bennett 4ae5443c3b Don't ever delete own node from DB (#3122) 2024-01-22 20:13:27 -06:00
Jonathan Bennett 6b5101ec67 Portduino logging enhancements (#3121)
* Portduino logging enhancements

* Extra debugging for SPI device
2024-01-22 01:27:06 -06:00
Jonathan Bennett 062c646814 TinyGPS fix for empty terms (#3120) 2024-01-21 19:13:54 -06:00
github-actions[bot]andthebentern bccc0d47eb [create-pull-request] automated change (#3119)
Co-authored-by: thebentern <thebentern@users.noreply.github.com>
2024-01-20 19:11:21 -06:00
GUVWAFandBen Meadors 8f6a2836b8 Mark packets received via MQTT and add option to ignore them (#3117)
* Mark packets received via MQTT and add option to ignore them

* Don't send packets received via MQTT back into MQTT
Generate implicit ACK for packets we as an MQTT gateway sent

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2024-01-20 14:22:09 -06:00
github-actions[bot]andthebentern 4f76239d48 [create-pull-request] automated change (#3118)
Co-authored-by: thebentern <thebentern@users.noreply.github.com>
2024-01-20 09:40:28 -06:00
rcarterazandBen Meadors 486bf79690 update default (#3114)
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2024-01-19 13:41:24 -06:00
Ben Meadors 2efaaea625 Update oled dep to include RP2040 fix (#3112) 2024-01-19 13:14:27 -06:00
Manuel af157d276a fix T-Watch flip screen (#3113) 2024-01-19 13:11:19 -06:00
Ben Meadors b489ee08c8 Update radiolib 2024-01-19 10:53:00 -06:00
751bdf94aa Initial Partial Updates on t-echo (#3090)
Co-authored-by: Jonathan Bennett <jbennett@incomsystems.biz>
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2024-01-19 10:28:26 -06:00
Ben Meadors e2a3b0306f Default mqtt root to msh/region from unset (#3111)
* Default mqtt root to msh/region from unset

* Correct segments
2024-01-19 07:40:14 -06:00
github-actions[bot]andthebentern a8b7490b6e [create-pull-request] automated change (#3106)
Co-authored-by: thebentern <thebentern@users.noreply.github.com>
2024-01-17 18:15:00 -06:00
Andre KandBen Meadors 4056d34bed fix: ipv4_config byte order already little endian (#3073)
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2024-01-17 18:14:44 -06:00
GUVWAFandBen Meadors fd8b1687a1 Update channel of node in updateUser and write to flash if needed (#3094)
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2024-01-15 20:11:35 -06:00
Jonathan Bennett 8b362dee3a RadioLib 6.4.0 fixes (#3098) 2024-01-15 10:56:17 -06:00
github-actions[bot]andthebentern 30e3a28014 [create-pull-request] automated change (#3099)
Co-authored-by: thebentern <thebentern@users.noreply.github.com>
2024-01-15 07:28:20 -06:00
Jonathan Bennett 14736775e2 Update define for RadioLib 6.4.0 2024-01-14 14:51:37 -06:00
Jonathan Bennett a7019b7206 Update for Radiolib 6.4.0 to fix build 2024-01-14 14:38:57 -06:00
Jonathan Bennett 6284f4ffe6 Update Linux binaries to use arch names (#3093) 2024-01-13 19:11:59 -06:00
Jonathan Bennett e4e9a1559e Drop the Raspbian and Linux targets (#3091)
* Drop the Raspbian and Linux targets

* Add lovyanGFX libdep to native
2024-01-13 16:12:26 -06:00
GUVWAF 92110276d7 Use ::printf for Portduino only 2024-01-13 14:54:43 -06:00
GUVWAF c22340eaf7 Add necessary libs to Dockerfile for native build 2024-01-13 14:54:43 -06:00
KodinLanewaveandBen Meadors 6f96fbfb74 INA3221 library branch to support negative values (#3084)
* INA3221 library branch to support negative values

Original INA3221 library does not handle negative values properly due to mishandling of signed bits in sensor reading and processing.  I have branched the library, changed the code, and tested with several deployed nodes to confirm functionality.

* Update INA3221 library reference to use version tag

Updated my library repo to reflect a version tag properly per request by meshtastic code reviewer

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2024-01-12 10:02:51 -06:00
Jonathan BennettandBen Meadors 4a867c81c0 Portduino work (#3049)
* Move to Portduino's getMacAddr()

* Add ST7735/S screen support

* Push Raspbian support into native target

* Remove latent pigpio references.

* CardKB defensive programming

* Adds configurable spidev

* Fixes to build on Fedora 40

* ENUMs are not #defines. Pull latest portduino

* Add more configuration options for SPI displays

* Add config.yaml option to set DIO3_TCXO_VOLTAGE

* change tft clear() to fillScreen()
Maintains compatability with ESPI driver.

* Adds TXen and RXen pins to portduino

* Add -c --config options to specify config file

* Fail when a specified config file is unavailable

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2024-01-12 02:00:31 -06:00
github-actions[bot]andthebentern 7e53a96ee5 [create-pull-request] automated change (#3082)
Co-authored-by: thebentern <thebentern@users.noreply.github.com>
2024-01-11 12:44:46 -06:00
github-actions[bot]andthebentern 3e21e05a2c [create-pull-request] automated change (#3079)
Co-authored-by: thebentern <thebentern@users.noreply.github.com>
2024-01-11 11:52:01 -06:00
Ben MeadorsandJonathan Bennett e9bde80b57 change tft clear() to fillScreen() (#3077)
Maintains compatability with ESPI driver.

Co-authored-by: Jonathan Bennett <jbennett@incomsystems.biz>
2024-01-11 10:06:26 -06:00
Mark Trevor Birss ccb5485510 Add SX1262 to M5Stack CoreInk (#3078)
* Update platformio.ini

* Update variant.h

* Update variant.h

* Update variant.h

* Update variant.h

* Update variant.h

* Update variant.h

* Update variant.h

* Update variant.h
2024-01-11 10:06:02 -06:00
Ben MeadorsandNfN Orange 0d85069bec Heltec paper (#3069)
* Attempts at getting the Heltec Wireless Paper eink operational

* Bogus comment

* Fixing Support For Heltec Wireless Paper

---------

Co-authored-by: NfN Orange <orange@reveb.la>
2024-01-09 19:48:21 -06:00
GUVWAF 77ff1704db Allow button press if CannedMessage updown1 or rotary1 are not enabled (#3067)
`BUTTON_PIN` may be 0, which is equal to `inputbroker_pin_press` by default
2024-01-09 19:45:54 -06:00
GUVWAF 613a2bfb70 Update exception decoder for other platforms (#3070) 2024-01-09 19:45:03 -06:00
Ben Meadors ea651c2f8f Remove gps_attempt_time and use broadcast interval instead (#3064) 2024-01-07 09:35:19 -06:00
MictronicsandBen Meadors c2afa879b8 Fix LED pinout for T-Echo board marked v1.0, date 2021-6-28 (#3051)
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2024-01-07 07:40:12 -06:00
Ben Meadors 59253d9c78 Don't reboot after removing node from DB (#3065) 2024-01-07 07:37:13 -06:00
github-actions[bot]andthebentern be46f9ea24 [create-pull-request] automated change (#3063)
Co-authored-by: thebentern <thebentern@users.noreply.github.com>
2024-01-06 15:23:40 -06:00
Ben Meadors 674fd32349 RP2040 Enter uf2 DFU mode (#3062)
* Pico enter dfu mode

* Ungaurd pico
2024-01-06 14:39:27 -06:00
Amin Husni bacc525d0a Add Malaysia Region (#3053)
* Add Malaysia Region

Add frequency for 433MHz and 919MHz with specific power limit and limitation.

* Update RadioInterface.cpp

Formatting issues
2024-01-05 15:37:31 -06:00
github-actions[bot]andthebentern aa10a3ec40 [create-pull-request] automated change (#3055)
Co-authored-by: thebentern <thebentern@users.noreply.github.com>
2024-01-04 18:54:44 -06:00
Jonathan Bennett e3c768bf10 Update platformio.ini -- set target default to tbeam (#3054) 2024-01-04 12:22:45 -06:00
GUVWAFandBen Meadors 943367edd0 Fix "watch GPIOs" feature of Remote Hardware module (#3047)
* Fix watch GPIO feature of Remote Hardware

* Add Remote Hardware messages to JSON output

* Add curly brackets

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2024-01-03 15:08:28 -06:00
Jonathan Bennett 4577646f8b Get rid of max-parallel build for rp2040 2023-12-29 17:49:25 -06:00
Jonathan Bennett 1ae02a9a28 Add dependencies for native build 2023-12-29 16:47:42 -06:00
Jonathan Bennett 28951ea1e0 Add libbluetooth-dev to build image 2023-12-29 12:35:42 -06:00
github-actions[bot]andthebentern 2e9cc73ebb [create-pull-request] automated change (#3046)
Co-authored-by: thebentern <thebentern@users.noreply.github.com>
2023-12-27 18:40:54 -06:00
Ben Meadors dbac2b1cad Implemented enter (Uf2 usb) DFU mode admin message on NRF52 (#3045)
* Added enter DFU mode admin message

* Trunk
2023-12-27 14:26:40 -06:00
github-actions[bot]andthebentern 2b7eb1e489 [create-pull-request] automated change (#3044)
Co-authored-by: thebentern <thebentern@users.noreply.github.com>
2023-12-27 12:48:30 -06:00
S5NCandBen Meadors d401040e51 Remove old SX126x and SX128x boosted gain commented-out code (#2976)
* Update SX126xInterface.cpp

* Update SX128xInterface.cpp

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2023-12-27 08:18:26 -06:00
5110de4838 Portduino reboot (#3033)
* Portduino reboot

* separate blocks

---------

Co-authored-by: Jonathan Bennett <jbennett@incomsystems.biz>
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2023-12-27 08:16:53 -06:00
GUVWAFandBen Meadors 2d35f72d85 SimRadio: send queue status to phone (#3041)
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2023-12-27 08:16:04 -06:00
MictronicsandBen Meadors d318d34c3c Fix #3032 (#3040)
* Fixed bug #3023 in upstream master. Wire.begin doesn't accept two arguments in RP2040 framework.

* Fix typo.

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2023-12-27 08:15:38 -06:00
Wolfgang NageleandBen Meadors 06b4638f6b Allow override of HWID using environment variable (#3036)
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2023-12-27 08:14:55 -06:00
GUVWAF 16c18d0da9 Add Traceroute, DetectionSensor and Paxcounter to MQTT JSON (#3043)
* Add Traceroute, DetectionSensor and Paxcounter to MQTT JSON

* Guard Paxcounter for ESP32 only
2023-12-27 08:14:25 -06:00
Jonathan Bennett 8d37d93e05 Hash function needs uint32_t for some platforms. (#3038) 2023-12-26 13:21:09 -06:00
Wolfgang NageleandBen Meadors 7334ee7349 Time Fix (#3035)
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2023-12-25 16:40:16 -06:00
Wolfgang Nagele ba98da55a7 Align glibc with Debian builder (#3034) 2023-12-25 09:47:19 -06:00
GUVWAF db8f8db8e8 Don't disconnect WiFi when we're actively reconnecting (#3026)
WiFiEvents may happen asynchronously
2023-12-21 14:59:45 -06:00
GUVWAF d88baea627 Make implicit ACKs work on MQTT (#3028)
Don't filter out messages we originally sent via LoRa
2023-12-21 14:59:16 -06:00
Mark Trevor BirssandJonathan Bennett 16a3a32f2a [Add] SX1280 to linux native Portduino (#3023)
* Update PortduinoGlue.cpp

* Update PortduinoGlue.h

* Update main.cpp

* Update config-dist.yaml

* Update config-dist.yaml

* Fix whitespace in main.cpp

---------

Co-authored-by: Jonathan Bennett <jbennett@incomsystems.biz>
2023-12-17 18:05:04 -06:00
Thomas Göttgens a138e9cb6b Merge pull request #3020 from meshtastic/paxcounter
Include Libpax
2023-12-17 19:20:04 +01:00
Thomas Göttgens 86475a1719 admin getters and setters 2023-12-17 18:30:38 +01:00
Thomas Göttgens c5a2dc758f rule of thumb, last minute changes are dumb. 2023-12-17 18:30:38 +01:00
Thomas Göttgens add78a459b Include Libpax - WIP 2023-12-17 18:30:38 +01:00
Thomas Göttgens f1b380882d Merge pull request #3022 from meshtastic/create-pull-request/patch
Changes by create-pull-request action
2023-12-17 18:30:19 +01:00
caveman99 bbe21766be [create-pull-request] automated change 2023-12-17 17:29:49 +00:00
Thomas Göttgens dfa537415d Merge pull request #3021 from meshtastic/nodeinfo-shading
local variable and class variable may not be named the same
2023-12-17 17:09:44 +01:00
Thomas Göttgens 24c4ee9bfa local variable and class variable may not be named the same 2023-12-17 16:28:48 +01:00
Jonathan Bennett 71c0726838 Ignore keyboard input while sending CannedMessages packet 2023-12-16 23:03:41 -06:00
github-actions[bot]andthebentern 45f90fb39b [create-pull-request] automated change (#3018)
Co-authored-by: thebentern <thebentern@users.noreply.github.com>
2023-12-16 19:21:54 -06:00
Ben Meadors 1c6acfd734 Set NRF cpu brownout at 2.4V instead of running down to the limit (#3016) 2023-12-16 06:57:01 -06:00
Jonathan Bennett c6ae66dcaa Add fallthrough option to avoid a GPS stuck off. 2023-12-14 21:39:41 -06:00
Jonathan Bennett fc365a1fee Keep WiFi defines out of platforms without WiFi 2023-12-14 20:16:36 -06:00
Jonathan Bennett 6c1db94ae7 Add raspbian reboot and shutdown behavior 2023-12-14 19:53:42 -06:00
Thomas Göttgens ded1cbf4dd Merge pull request #3015 from meshtastic/esp32s2fix
ESP32-S2 fix
2023-12-14 18:24:00 +01:00
Ben Meadors 399b9f8f6d Merge branch 'master' into esp32s2fix 2023-12-14 07:37:59 -06:00
Ben Meadors 4720b2874f Cpp-check warnings cleanup (#3014)
* cpp-check warnings cleanup

* Supressions and more fixes
2023-12-14 07:35:46 -06:00
Thomas Göttgens 1af3e0ddaa ESP32-S2 fix
ESP32-S2 does not have bluetooth
2023-12-14 13:40:22 +01:00
Ben Meadors 9f85279e74 Lost and found mode (#3012)
* Lost and found WIP

* 5 minutes

* ASCII bell character correction

* Memory
2023-12-13 17:43:20 -06:00
Jonathan Bennett dd96848bec Change type to fix compilation in new code 2023-12-12 21:35:01 -06:00
Thomas Göttgens 4932e277f1 remove char counter when changing destination
shorten destination to make room for char counter, only on small displays.
2023-12-12 21:35:01 -06:00
Thomas Göttgens dad05d7873 Select Node and channel in Canned Message module. 2023-12-12 21:35:01 -06:00
Thomas Göttgens 4b7fbeca29 only ever emit the up/down action if we have actual messages stored 2023-12-12 21:35:01 -06:00
Jonathan BennettandBen Meadors 2ebaea317a Refactor display handling add Raspbian TFT display (#2998)
* Refactor display handling add Raspbian TFT display

* Add missed change

* Add static casts

* Add missed TFT refactor for RAK14014

* Add missed GPIO configuration

* Adds Native keyboard input option

* Get the ifdefs right

* CannedMessage send via queue, not run immediately.

* Fixup systemd service file

* Add display blanking for Raspberry Pi

* Add a couple missed key definitions

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2023-12-12 20:27:31 -06:00
Ben Meadors d14d2c89c3 RTTTL ringtones on T-Deck / T-Watch S3 and potentially more I2S audio enabled devices (#2917)
* WIP

* ESP8266 SAM fun

* I2S audio / ext. notification module

* Remove

* Protos

* Add use_i2s_as_buzzer from protos

* Fixes

* Stuff

* Thing

* Ext. Notification working(ish)

* Remove SAM commented code

* Trunk upgrade

* Trunk

* Fixes

* Slow not fast... :-|

* T-Deck and T-Watch don't use normal buttons

* Stop ext. notification nagging with touchscreen as well

* Add button gpio back for T-Deck, but guard against long-press during ext. notification

* Ext. notification wrap up

* Better place to guard against long-press false positives

* Adjust default gain and guard against non-i2s devices referencing audio-thread

* Simplify guard logic with a boolean

* Supress uninitMemberVar

* Protos merge got out of wack

* Trunk resolution

* Remove extra crap

* Cleanup and thread-interval

* Default to alert message buzzer and add nag timeout

* Formatting
2023-12-12 08:36:37 -06:00
Thomas Göttgens 35938392f1 Merge pull request #2739 from meshtastic/delivery-report
UI/UX: Display delivered message on incoming ACK.
2023-12-11 22:59:19 +01:00
Thomas Göttgens d952da8b1e make sure the queue stays in te same order
the memory pool can NOT be iterated easily, since it's not a linear object.
2023-12-11 15:44:32 +01:00
Thomas Göttgens 385b29c977 we don't use the static MemoryPool anywhere, ditch dead code. 2023-12-11 15:35:22 +01:00
Thomas Göttgens dc309f61e8 Look into tophone queue for the received packet.
- only works if we don't have a phone connected, but that is probably dsired
- this will send a copy of device-originating text messgaes to a connected phone. Breaking change.
- this will iterate the tophone queue by deconstructing and reconstructing it every time we look for an ID. Probably also mangles the queue oder since it aborts when a ID is found.
- Can we navigate the packet pool instead? If so, how?
- Let's keep this in draft state for now
2023-12-11 15:11:10 +01:00
Thomas Göttgens 512399c8f5 Merge branch 'delivery-report' of https://github.com/meshtastic/firmware into delivery-report 2023-12-11 12:38:22 +01:00
GUVWAF 5d94bb601a Distinguish between ACK/NAK by checking for error reason 2023-12-11 12:30:33 +01:00
Thomas Göttgens 796592b586 UI/UX: Display delivered message on incoming ACK.
Needs more work
2023-12-11 12:30:33 +01:00
Ben Meadors d552ee3556 Add heltec-ht62 to CI (#3007) 2023-12-09 19:12:51 -06:00
Ben Meadors 14b31d4d14 Fix INA sensor dual use between environment telem and device battery reading (#3002) 2023-12-08 19:26:37 -06:00
Ken McGuire 4de6eb2e1d Reduce Serial Traffic on Heltec Wireless Trackers GNSS port (#3004)
* Fix typo in GNSS_MODEL defination and usages for the UC6580
Correct the $CFGSYS init string for the UC6580 to init the receiver for:
GPS L1 & L5 + BDS B1I & B2a + GLONASS L1 + GALILEO E1 & E5a + SBAS

* Reduce GNSS serial traffic on Helted Wireless Tracker
Turn off GSV and NOTIFY __TXT messages as neither are
necessary to Meshtastic operation.
2023-12-08 14:51:50 -06:00
Ben Meadors abaa37133d Repeater and other power optimizations (#2999)
* End wire if we find no i2c devices

* Set tx-power to 0 on nrf bluetooth shutdown

* Change polling interval of PowerFSM to 100ms instead of 10ms

* Guard 3v3
2023-12-08 11:13:15 -06:00
Jonathan Bennett 5eac227550 Fix whitespace in workflow 2023-12-07 21:29:04 -06:00
Jonathan Bennett 671112f47d Update pull-request-artifacts config 2023-12-07 21:22:30 -06:00
Jonathan Bennett 8ea19d665a Update pull-request-artifacts 2023-12-07 20:22:22 -06:00
Ben Meadors 8f57cfaaf4 Makersense rp2040 variant fixes (#2997)
* WIP

* Do the right things

* Add to build matrix

* Yaml lint has annoyed me for the final time

* Fixes to variant
2023-12-07 17:12:51 -06:00
Ben Meadors a54e3826e9 Remove truffle-hog tool for now since it's breaking CI 2023-12-07 07:14:41 -06:00
Ben Meadors 9188a9a1f2 Makersense RP2040 support (#2996)
* WIP

* Do the right things

* Add to build matrix

* Yaml lint has annoyed me for the final time
2023-12-06 21:42:06 -06:00
github-actions[bot]andthebentern 17f1a450b2 [create-pull-request] automated change (#2995)
Co-authored-by: thebentern <thebentern@users.noreply.github.com>
2023-12-06 18:14:41 -06:00
GUVWAFandBen Meadors ba021c97b2 Pico W: Handle Wi-Fi reconnects and update core (#2994)
* Fix time lost on the Pico W right after NTP
Shouldn't check for `#ifdef` as it will always be defined, but might be set to 0

* Handle reconnect for Wi-Fi on RP2040

* Update arduino-core for Wi-Fi + FreeRTOS fixes

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2023-12-06 15:49:56 -06:00
Ben Meadors b4ad6b0f41 Added client-hidden role behavior (#2992)
* Added client-hidden role behavior

* Trunkt

* That line got all boogered up
2023-12-06 14:04:09 -06:00
Ben Meadors 28502a762f Added Known-Only rebroadcast mode behavior (#2993) 2023-12-06 14:02:41 -06:00
github-actions[bot]andthebentern 89f0464233 [create-pull-request] automated change (#2991)
Co-authored-by: thebentern <thebentern@users.noreply.github.com>
2023-12-06 06:17:50 -06:00
GUVWAF 46d02affe8 Pico W: Wi-Fi improvements (#2989)
* Pico W: Initial WiFi support: connects, but freezes after a while

* Update arduino-pico core to fix hang with Wi-Fi

* Add `picow` to workflow since it's different from `pico` now

* Show Wi-Fi frame on screen for all devices with Wi-Fi

* Pico W: Disable mDNS as it's unsupported with FreeRTOS

* Fix printing IP address

* Fix Raspbian build
2023-12-04 15:45:07 -06:00
Ken McGuire 62329ad11f Fix typo in GNSS_MODEL defination and usages for the UC6580 (#2988)
Correct the $CFGSYS init string for the UC6580 to init the receiver for:
GPS L1 & L5 + BDS B1I & B2a + GLONASS L1 + GALILEO E1 & E5a + SBAS
2023-12-04 12:35:26 -06:00
Thomas Göttgens 72b4fe51b1 radiolib is stable
just use one definition for all targets
2023-12-04 11:33:32 +01:00
Thomas Göttgens 07fc5df9c1 update trunk and linters to latest version 2023-12-03 13:02:14 +01:00
Thomas Göttgens 1c22d2c885 switch onebutton back to PIO registry, since they finally updated the lib there 2023-12-03 13:00:15 +01:00
github-actions[bot]andthebentern 1f931a5e55 [create-pull-request] automated change (#2981)
Co-authored-by: thebentern <thebentern@users.noreply.github.com>
2023-12-02 17:19:29 -06:00
Ben Meadors 31c4693c66 Missed the version bump apparently 2023-12-02 15:50:17 -06:00
GUVWAF 6ff61b3e04 Pico W: Initial Wi-Fi support (#2980)
* Pico W: Initial WiFi support: connects, but freezes after a while

* Update arduino-pico core to fix hang with Wi-Fi

* Add `picow` to workflow since it's different from `pico` now
2023-12-02 14:47:52 -06:00
S5NCandBen Meadors 9e90b4af02 Update variant.h (#2930)
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2023-12-02 07:46:25 -06:00
2544733ad4 Standardise order for setting GPIO pin default values (#2942)
* Update SX126xInterface.cpp

* Update GPS.cpp

* Update TFTDisplay.cpp

* Update SX128xInterface.cpp

* Update EInkDisplay2.cpp

* trunk fmt

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
Co-authored-by: Thomas Göttgens <tgoettgens@gmail.com>
2023-12-02 07:40:31 -06:00
Thomas GöttgensandBen Meadors 1b6c11c5f1 tryfix crash (#2964)
* tryfix crash

* only use this when wifi is not enabled. (poking around)

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2023-12-02 07:00:20 -06:00
S5NC 4c69d06ac0 Update Power.cpp (#2979) 2023-12-02 06:30:00 -06:00
code8buster 85cbde75fe Merge pull request #2977 from meshtastic/g2-defaults
Factory Defaults for Nano G2 Ultra
2023-12-02 00:36:31 +00:00
GUVWAF 5e70fb9851 Distinguish between ACK/NAK by checking for error reason 2023-12-01 18:28:38 +01:00
Thomas Göttgens 6e967421a5 UI/UX: Display delivered message on incoming ACK.
Needs more work
2023-12-01 18:28:38 +01:00
Ben Meadors a05bab35ad = 2023-12-01 07:17:38 -06:00
Ben Meadors ac506a581c Merge branch 'master' into g2-defaults 2023-12-01 07:07:59 -06:00
Ben Meadors def4ec5822 Always set user (nodeinfo) role to device config's current role (#2973) 2023-12-01 07:00:19 -06:00
Ben Meadors 209fb585b0 Default to what G2 comes with 2023-11-30 20:49:00 -06:00
fb89482129 Set default LoRa SPI pins individually on ESP32 architecture (#2971)
* Each pin individually

* Correction

---------

Co-authored-by: Jonathan Bennett <jbennett@incomsystems.biz>
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2023-11-30 06:39:46 -06:00
Thomas Göttgens 8e742f2f80 Update portduino.ini 2023-11-30 11:53:47 +01:00
Thomas Göttgens 238cf8cdeb fix portduino 2023-11-30 11:53:47 +01:00
Thomas Göttgens 5df7f07f95 unpin radiolib 2023-11-30 11:53:47 +01:00
Thomas Göttgens 6fa026a78b fix radiolib API for 6.3.0 release 2023-11-30 10:59:01 +01:00
Jonathan Bennett 39743832ad Revert Portduino RadioLib to 6.1.0 2023-11-29 20:19:10 -06:00
Jonathan Bennett bd2675caf1 Temporarily Pin RadioLib to 6.2.0 2023-11-29 20:19:10 -06:00
Jonathan Bennett c489c251ab Pull in Portduino changes for Raspberry Pi support 2023-11-29 20:19:10 -06:00
Jonathan Bennett 14d03a2bda Initial implementation of I2C 2023-11-29 20:19:10 -06:00
Jonathan Bennett 423b8ad603 Adds real GPS support to Raspberry Pi arch 2023-11-29 20:19:10 -06:00
Jonathan Bennett ce8342d3e5 Drop Pi HAL 2023-11-29 20:19:10 -06:00
Jonathan Bennett 57227c0f85 Add gpiochip setting 2023-11-29 20:19:10 -06:00
Jonathan Bennett 1ca2923658 Fix missed #if defined() logic 2023-11-29 20:19:10 -06:00
Jonathan Bennett d10b1e1d00 Add better error reporting for RF95 init failure 2023-11-29 20:19:10 -06:00
Jonathan Bennett d3e64350d9 Remove RADIOLIB_SPI_PARANOID compile option, as it does nothing 2023-11-29 20:19:10 -06:00
Jonathan Bennett 102efd4954 Move to portduino GPIO, adding user button support 2023-11-29 20:19:10 -06:00
S5NCandBen Meadors 18cf8ca4fa Generalise SPI pin names (#2970)
* Generalise SPI pin names

* CS not NSS

* trunk fmt

* Update variant.h

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2023-11-29 15:51:05 -06:00
Ben Meadors c7f6071f70 Enable IO2 toggling on RAK if the coast is clear (#2968)
* Enable IO2 toggling on RAK if the coast is clear

* Guard against monteops target which doesn't use 3V3 pin

* Also check for en_gpio = 0 to avoid re-setting the value
2023-11-28 20:40:51 -06:00
Thomas Göttgens c7e3485dd7 Revert "same change for STM32WL - also update trunk"
This reverts commit f9fdb0f98d5e095b5537e9b740231368fc088210.
2023-11-26 14:49:11 +01:00
Thomas Göttgens 603e564db3 same change for STM32WL - also update trunk 2023-11-26 14:49:11 +01:00
Thomas Göttgens ac318a9850 Swapped out crypto engine for one that also works with AES-256 2023-11-26 14:49:11 +01:00
Ben Meadors 1feb74f525 Add number of sats to default position flags (#2962) 2023-11-25 19:34:30 -06:00
Thomas Göttgens d6fc1c314f WIP: Add battery level for Nimble 2023-11-25 16:03:39 +01:00
Thomas Göttgens b3852322ef Add config example for Elecrow Hat
NFC
2023-11-24 14:40:20 +01:00
HookdomPonixandBen Meadors cbb8eb65ba Add USB detection to RAK4631 based boards. (#2956)
* Add support for the rak10701 board, no touch

* Moved tftblack fillin and changed teh src flags

* Added rak10701 to platformio.ini

* Add USB detection to RAK4631 units.

* Eliminate spurious symbol in comment field.

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2023-11-22 10:30:55 -06:00
Jonathan Bennett 4712b1ca65 Add manual run option to package_raspbian.yml (#2954) 2023-11-22 07:17:48 -06:00
Ric In New MexicoandJonathan Bennett 57542ce9e6 Retain device nodeinfo during reset-nodedb (#2951)
* INA3221 bugfixes & refinement
Reorganized and refactored some INA3221 code
Added comments
Added missing shunt resistor value (100mΩ)
Added INA3221 Channel 1 to getINAVoltage() for device battery monitoring
	modified:   src/Power.cpp
	modified:   src/modules/Telemetry/PowerTelemetry.cpp
	modified:   src/modules/Telemetry/Sensor/INA3221Sensor.cpp
	modified:   src/modules/Telemetry/Sensor/INA3221Sensor.h
	modified:   src/power.h

* reset-nodedb retain device nodeinfo
	modified:   src/mesh/NodeDB.cpp

* reset-nodedb #2
	modified:   src/mesh/NodeDB.cpp

---------

Co-authored-by: Jonathan Bennett <jbennett@incomsystems.biz>
2023-11-20 06:33:14 -06:00
Jonathan Bennett 1b20a82b55 Update package_raspbian.yml
Trunk
2023-11-19 20:28:37 -06:00
Jonathan Bennett 195706e0e5 Update package_raspbian.yml to pull correct code for PR runs 2023-11-19 20:19:43 -06:00
Jonathan Bennett c1f5878648 Add Raspbian to firmware zip 2023-11-19 17:11:54 -06:00
Jonathan Bennett 7380f3b170 Trunk fmt fix whitespace 2023-11-19 16:53:00 -06:00
Jonathan Bennett a9d846c1b3 make package_raspbian.yml a reusable workflow 2023-11-19 16:45:06 -06:00
Jonathan Bennett cfb09ee115 add .deb to release 2023-11-19 16:41:47 -06:00
Jonathan Bennett 8f0ce606db Update package_raspbian.yml upload .deb as artifact 2023-11-19 16:07:08 -06:00
Jonathan Bennett d04ff29c2a Update package_raspbian.yml use ubuntu-latest 2023-11-19 15:56:41 -06:00
Jonathan Bennett 8e92754b59 Update package_raspbian.yml 2023-11-19 15:48:43 -06:00
Jonathan Bennett dad824c0e9 Update package_raspbian.yml -- add checkout step 2023-11-19 15:16:11 -06:00
Jonathan Bennett 31d7c6826d Update package_raspbian.yml
Properly run build_raspbian as a step
2023-11-19 15:03:46 -06:00
Jonathan Bennett d33521ee86 Add package-raspbian workflow 2023-11-19 14:53:49 -06:00
Jonathan Bennett 5ad12fed60 Chill out, yamllint 2023-11-19 14:53:49 -06:00
Jonathan Bennett 4af90eeb39 Revamp yaml config for Raspbian 2023-11-19 14:53:49 -06:00
Jonathan Bennett 08297bb0b7 Copy and Paste output file location for workflow 2023-11-18 15:36:41 -06:00
Jonathan Bennett 16ef40b21f Add even moar workflow debugging 2023-11-18 15:16:36 -06:00
Jonathan Bennett 7ef4abb974 Add debugging output to main workflow 2023-11-18 14:56:40 -06:00
Jonathan Bennett 297267d037 Try harder to find Raspbian binary 2023-11-18 13:26:05 -06:00
Jonathan Bennett f8e766ebc7 Include Raspbian in release zip 2023-11-18 12:05:51 -06:00
Jonathan Bennett 7bd2b07024 Disable radiolib debug 2023-11-18 12:05:51 -06:00
Jonathan Bennett b6ddbd0087 More CI work for Raspbian (#2949)
* More CI work for Raspbian

* Workaround quirks of Arm64/debian runners
2023-11-18 11:04:21 -06:00
Jonathan Bennett dc8903ec42 Add Raspbian to Main CI (#2948) 2023-11-18 08:55:19 -06:00
Ben MeadorsandJonathan Bennett 46bd6ca7ba YAML based config for PI / Portduino (#2943)
* Add configuration via /etc/meshtastic/config.yaml

* Move example config, support more locations

* Fix config check

* Use access() to check for config file presence

* Throw an error and exit on radio init fail

* Adds error check for reading Bluetooth MAC

* Settle on meshtasticd, add install script

* Shell fixes

* Fine. I'll put it back and then disable you

* Get wrekt, shellchekt

* Firat attempt at adding raspbian CI build

* Tickle the workflow

* Beatings will continue til morale improves

* Permissions are overrated

---------

Co-authored-by: Jonathan Bennett <jbennett@incomsystems.biz>
2023-11-18 08:12:34 -06:00
Ric In New Mexico 9d4af1146e INA3221 bugfixes & refinement (#2944)
Reorganized and refactored some INA3221 code
Added comments
Added missing shunt resistor value (100mΩ)
Added INA3221 Channel 1 to getINAVoltage() for device battery monitoring
	modified:   src/Power.cpp
	modified:   src/modules/Telemetry/PowerTelemetry.cpp
	modified:   src/modules/Telemetry/Sensor/INA3221Sensor.cpp
	modified:   src/modules/Telemetry/Sensor/INA3221Sensor.h
	modified:   src/power.h
2023-11-17 06:46:59 -06:00
Thomas Göttgens 5ce6ca25f2 Merge pull request #2083 from meshtastic/raspi-portduino
Start working on RF95 attached to Raspberry Pi
2023-11-16 15:07:02 +01:00
Ben Meadors f2210d8f8d Merge branch 'master' into raspi-portduino 2023-11-16 06:57:52 -06:00
Ben Meadors 5d917885df Added Remove node by nodenum admin message (#2941)
* Remove node by nodenum

* It were backerds! DERP
2023-11-16 06:57:22 -06:00
Jonathan Bennett e99ae64ece Add Pi library only to Raspbian 2023-11-15 21:16:27 -06:00
Jonathan Bennett 61f888e952 Add missed ifdef 2023-11-15 21:01:17 -06:00
Jonathan Bennett a144d5d6cc Clean up, fix reboot, minimize changes 2023-11-15 20:33:53 -06:00
Ben Meadors c3e3569c14 Merge branch 'master' into raspi-portduino 2023-11-15 19:39:19 -06:00
Jonathan Bennett b1b5bafdda Add PiHal and get Waveshare SX1262 XXXM working 2023-11-15 17:04:41 -06:00
Ben Meadors 91e399a2b6 Added detection sensor en pin to fix issues with RAK microwave (#2940) 2023-11-15 09:26:47 -06:00
HookdomPonixandBen Meadors 8b16367597 Add support for the rak10701 board, no touch (#2933)
* Add support for the rak10701 board, no touch

* Moved tftblack fillin and changed teh src flags

* Added rak10701 to platformio.ini

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2023-11-13 06:20:49 -06:00
S5NC 0b9accc3b6 Remove redundant checks for power of 0 (#2934)
* Add comment explaining necessity for second 0 check

Thank you @GUVWAF

* Update RF95Interface.cpp

* Update STM32WLE5JCInterface.cpp

* Update SX126xInterface.cpp

* Update SX128xInterface.cpp

* remove whitespace...

* Update SX128xInterface.cpp
2023-11-13 06:19:02 -06:00
GUVWAF 590b0bbff4 Merge pull request #2935 from S5NC/add-missing-has-sensor
Add missing defaulting for HAS_SENSOR to configuration.h
2023-11-10 09:57:44 +01:00
S5NC 19be230b24 Update configuration.h 2023-11-08 21:58:33 +00:00
Jonathan Bennett 8df16ad6a6 Add ctime include to fix native compile 2023-11-08 14:36:12 -06:00
Ben Meadors 2d62f00ac3 Merge branch 'master' into raspi-portduino 2023-11-08 09:54:18 -06:00
pdxlocations 9f93b9ab9d fix sizeof error 2023-11-08 12:40:51 +01:00
pdxlocations fc3200134d party time 2023-11-08 12:40:51 +01:00
Ben Meadors 470264b7f9 Merge branch 'master' into raspi-portduino 2023-11-07 05:58:42 -06:00
Ben Lipsey 600541ac25 Fix Documentation Links in Comments (#2929)
* update external notification

* ContentHandler
2023-11-06 22:03:44 +00:00
github-actions[bot]andthebentern 298b383127 [create-pull-request] automated change (#2927)
Co-authored-by: thebentern <thebentern@users.noreply.github.com>
2023-11-05 06:50:02 -06:00
Ric In New MexicoandBen Meadors f57020412e INA3221 / Power Telemetry Payload Variant Implementation (#2916)
* INA3221 / Power Telemetry Variant Implementation
	modified:   platformio.ini
	modified:   src/configuration.h
	modified:   src/detect/ScanI2C.h
	modified:   src/detect/ScanI2CTwoWire.cpp
	modified:   src/main.cpp
	modified:   src/modules/Modules.cpp
	new file:   src/modules/Telemetry/PowerTelemetry.cpp
	new file:   src/modules/Telemetry/PowerTelemetry.h
	new file:   src/modules/Telemetry/Sensor/INA3221Sensor.cpp
	new file:   src/modules/Telemetry/Sensor/INA3221Sensor.h
	modified:   src/mqtt/MQTT.cpp

* ifdef for portduino / linux native
	modified:   src/modules/Telemetry/PowerTelemetry.cpp

* try #2
	modified:   src/modules/Modules.cpp
	modified:   src/modules/Telemetry/PowerTelemetry.cpp
	deleted:    variants/xiao_ble/1.0.0/libraries/SPI/SPI.cpp

* try #3
	modified:   src/modules/Modules.cpp

* try #4
	modified:   src/modules/Telemetry/PowerTelemetry.cpp

* try #5?
	modified:   src/modules/Telemetry/PowerTelemetry.cpp

* try #6
	modified:   src/modules/Telemetry/PowerTelemetry.cpp

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2023-11-04 20:07:00 -05:00
Ben Meadors 4a6cc8fd8c Extend packet history expire time to 10 minutes (#2921) 2023-11-03 15:43:26 -05:00
Tyler JangandBen Meadors 45c5e0e730 cleanup disables (#2924)
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2023-11-03 06:50:30 -05:00
github-actions[bot]andthebentern 527bffb7e0 [create-pull-request] automated change (#2926)
Co-authored-by: thebentern <thebentern@users.noreply.github.com>
2023-11-03 06:36:24 -05:00
GUVWAF 4c35a7fb7d Handle AmbientLighting Module config (#2923) 2023-11-03 07:36:36 +00:00
GUVWAF 0f9936a0e0 Change default Coding Rate to 4/5 for <=LongFast (#2920)
Increases througput at the cost of a little bit of sensitivity
Non-breaking as the CR is sent in the LoRa header
2023-11-02 09:21:07 -05:00
Thomas Göttgens 40395bef01 Merge branch 'master' into raspi-portduino 2023-10-31 14:09:38 +01:00
GUVWAF 8b8fffda81 Drop packets if toPhoneQueue is full, unless it's text/RangeTest (#2918) 2023-10-30 06:12:22 -05:00
Ric In New Mexico 4052194dfe Fix for is_licensed save / reboot (#2911)
* Fix is_licensed save / reboot

* Revert "Fix is_licensed save / reboot"

This reverts commit 634151b8ec6f4063dc95966102234ef7aba8cefd.

* Changed reloadConfig to saveChanges /w reboot
2023-10-26 06:25:06 -05:00
Ben Meadors b36ffe5200 Trunk fmt fix 2023-10-24 18:52:46 -05:00
S5NC a60b4d08bf Hydra variant rectification (#2903)
* Update variant.h

* Update variant.h

* Update platformio.ini
2023-10-24 18:47:36 -05:00
github-actions[bot]andthebentern 227467f638 [create-pull-request] automated change (#2897)
Co-authored-by: thebentern <thebentern@users.noreply.github.com>
2023-10-20 09:52:56 -05:00
Tavis 092e6f2424 add rssi and snr to json output (#2894)
* add rssi and snr to json output

* explicitly cast to int and float
2023-10-17 06:50:36 -05:00
Andre KandBen Meadors e6b20bff77 refactor: simplify MQTT defaults (#2893)
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2023-10-15 18:56:47 -05:00
Andre KandBen Meadors 2c625f6ba1 fix: channel routing for decoded MQTT packets (#2892)
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2023-10-15 06:41:40 -05:00
Manuel 142d56c663 allow sensors connected to second I2C port (#2891) 2023-10-14 19:33:45 -05:00
Ben Meadors f4b40562d3 Start of TAK role (#2890)
* Start of TAK role

* Position flags change for CoT friendly altitudes

* Trunk
2023-10-14 06:49:38 -05:00
github-actions[bot] 9e203532d0 [create-pull-request] automated change (#2889) 2023-10-13 20:02:59 -05:00
code8buster 8bd7b5e779 Merge pull request #2887 from yupyvovarov/fix-hwids-address
Fix typo in tbeam-s3-core hwids address
2023-10-13 10:24:49 +00:00
Yurii Pyvovarov 1af970765f Fix typo in tbeam-s3-core hwids address 2023-10-13 11:31:10 +03:00
Ben Meadors def55ec063 Remove specific upload ports from pio 2023-10-11 10:21:58 -05:00
Ben Meadors 092c6cac66 Convert from inline to static class methods (#2883) 2023-10-11 06:17:05 -05:00
Ben Meadors e39f129bd6 More comprehensively clear current position info (#2881) 2023-10-10 19:33:58 -05:00
S5NC 9d1fe8c245 Update architecture.h (#2880) 2023-10-10 15:35:07 -05:00
786248a6b1 Dragino TrackerD wip (#2324)
* Dragino TrackerD initial variant

* fmt

---------

Co-authored-by: Thomas Göttgens <tgoettgens@gmail.com>
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2023-10-10 06:20:46 -05:00
github-actions[bot]andthebentern d1ac2dc6ea [create-pull-request] automated change (#2879)
Co-authored-by: thebentern <thebentern@users.noreply.github.com>
2023-10-09 20:43:42 -05:00
Ben Meadors 87396d9105 Refactor away some code duplication in screen frames and display formatter for modem presets (#2872)
* Refactor away some duplication

* Refactor preset names to display formatter method

* Remove unused screen brightness adjustment and extract wifi disconnect reason name to display formatter method

* Tronk

* Let's be more clear with this naming

* Effed

* DisplayFormatters static class and use native wifi disconnect reason names method

* git mv file so casing should match now

* Include titlecase

* Trunk
2023-10-09 20:43:16 -05:00
Ben Meadors b388f8edcd Merge branch 'master' into raspi-portduino 2023-10-09 19:45:08 -05:00
Ben MeadorsandJonathan Bennett 10265aabd5 Fix buggy phone positions (#2876)
* Guard-clause channel util. to reduce nesting

* Try-fix PhoneAPI position not updating

* Trunk

* Missed it

* Really disable GPS when asked to

---------

Co-authored-by: Jonathan Bennett <jbennett@incomsystems.biz>
2023-10-09 18:33:04 -05:00
Jonathan Bennett 8780d93941 Remove missed GPS definition (#2878) 2023-10-09 13:30:51 -05:00
Sacha Weatherstone 54f0c045e4 Update README.md 2023-10-09 22:30:02 +10:00
github-actions[bot]andthebentern 3ddad671a5 [create-pull-request] automated change (#2875)
Co-authored-by: thebentern <thebentern@users.noreply.github.com>
2023-10-08 08:12:42 -05:00
pat-trunk-ioandBen Meadors dc6f0b8e0b mention trunk is beta on windows (#2871)
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2023-10-06 15:31:04 -05:00
pat-trunk-io 33f28c3d56 Add trunk githooks to the repo (#2870) 2023-10-06 15:02:27 -05:00
github-actions[bot] ef1d8c8eee [create-pull-request] automated change (#2869) 2023-10-05 17:51:23 -05:00
Ben Meadors 950d5f0946 Power saving sensor (#2865)
* Trunk

* Again

* This thing just keeps updating itself

* Ignore tools

* Sleepy sensor

* Batrunkadunk
2023-10-05 12:42:03 -05:00
fc06754e1f Possibly fix #2704 "Heltec Wireless Tracker screen doesn't display anything" (#2749)
* fix #2704


Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
Co-authored-by: Jonathan Bennett <jbennett@incomsystems.biz>
2023-10-04 22:24:25 -05:00
github-actions[bot]andthebentern fbf74fc0b2 [create-pull-request] automated change (#2863)
Co-authored-by: thebentern <thebentern@users.noreply.github.com>
2023-10-04 10:23:55 -05:00
code8busterandBen Meadors 7cebd79475 Use doNotEnterOff flag to prevent GNSS poweroff before fix acquisition (#2861)
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2023-10-03 19:50:27 -05:00
Jonathan BennettandBen Meadors aa38f53aed Fix for T-Beam 1.2 GPS (#2858)
* Fix for T-Beam 1.2 GPS, with DEBUG enabled

* Don't break other devices

* Saving GPS data on this breaks on next boot. Fix.

* derp

* disable the extra verbosity

* Try the same sort of factory reset as the Lilygo image

* Catch GPS reboots and squash

* trunk

* GPS

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2023-10-03 12:05:40 -05:00
Ben Meadors 2a6c8be684 Avoid problematic sleep state transitions for power saving sensors and trackers (#2860)
* Avoid problematic sleep state transitions for power saving sensors and trackers

* Line got duped :-|
2023-10-03 10:09:27 -05:00
GUVWAFandBen Meadors 37c3d15978 Check if packet is decrypted before using portnum when converting to JSON (#2857)
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2023-10-03 06:39:35 -05:00
Manuel f301e236eb fix crash during shutdown (#2859)
* fix null pointer access

* ptr initialize
2023-10-03 06:37:46 -05:00
ManuelandBen Meadors 94c2ade272 make esp32 deepsleep button wakeup functional again (#2854)
* make deepsleep button wakeup functional again

* Remove unused var

* Cleanup comment

* suppress screen wake on button

* add resume screen

* trunk fmt

* added missing #ifdef

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2023-10-02 16:16:29 -05:00
Ben Meadors a6e4402e41 Screen on secs router default (#2855) 2023-10-02 06:28:05 -05:00
Jonathan Bennett 50db2d0e9b Add timeout to ublox PMREQ command (#2851) 2023-10-01 20:39:18 -05:00
Ben Meadors 5ecdbd0dbb Removed non-functional deep sleep button awake functionality (user can RST instead) (#2852)
* Fixed mask length

* Don't want_response if we're a tracker or sensor

* Fixes

* Removing non-functioning deep sleep button awake
2023-10-01 12:48:12 -05:00
Jonathan Bennett 47c6738c0d Fix GPS init bug -- power up even when disabled (#2850) 2023-09-30 23:38:51 -05:00
Ben Meadors 1552aa0081 Tracker role wakeup and sleep cycle when power.is_power_saving true (#2846)
* WIP

* Sleepy sleepy low power tracker

* Sleepy tracker clear

* NRF52 PoC

* Simplify NRF52 "sleep"

* Trackers aren't polite

* Remove unnecessary include

* Removed accidental commit

* Fixed not-so-sleepy T-Beam due to button gpio mask precendence

* Added sleepOnNextExecution for allowing fulfillment of pending messages before shutting down

* Cleanup

* Don't wantResponse for trackers

* Heltec wireless tracker doesn't like the button interrupt (maybe all s3 because user button press doubles as bootloader mode trigger?)
2023-09-30 21:09:17 -05:00
github-actions[bot]andthebentern 6ebec8fcd9 [create-pull-request] automated change (#2849)
Co-authored-by: thebentern <thebentern@users.noreply.github.com>
2023-09-30 20:40:04 -05:00
Manuel e9215a5d70 revert KB_POWERON changes (#2847) 2023-09-30 06:43:36 -05:00
Thomas Göttgens 5075849ec0 Add missing endif 2023-09-28 10:50:26 +02:00
Thomas Göttgens 7f16b6b342 Merge branch 'master' into raspi-portduino 2023-09-28 09:29:45 +02:00
S5NCandBen Meadors 4e3576ae48 Simplify SX126x variant configuration (#2813)
* Update SX126xInterface.cpp

* Update variant.h

* Update variant.h

* Update variant.h

* Update variant.h

* Update variant.h

* Update variant.h

* Update variant.h

* Update variant.h

* Update variant.h

* Update variant.h

* Update variant.h

* Update variant.h

* Update variant.h

* Update variant.h

* Update variant.h

* Update variant.h

* Update variant.h

* Update variant.h

* Update variant.h

* Update variant.h

* Update variant.h

* Update variant.h

* Update variant.h

* Update variant.h

* Update variant.h

* Update variant.h

* Update variant.h

* Update variant.h

* Update variant.h

* Update variant.h

* Update variant.h

* Update variant.h

* Update variant.h

* Update variant.h

* Update variant.h

* Update variant.h

* Update variant.h

* Update variant.h

* Update SX126xInterface.cpp

* Update SX126xInterface.cpp

* Update variant.h

* Update variant.h

* trunk fmt

* trunk fmt

* Update variant.h

* trunk fmt

* trunk fmt

* Update variant.h

* Update variant.h

* Update variant.h

* Update variant.h

* Update variant.h

* Update variant.h

* Update variant.h

* Update pins_arduino.h

* Update pins_arduino.h

* Update variant.h

* Update variant.h

* Update variant.h

* Update variant.h

* Update variant.h

* Update variant.h

* trunk fmt

* Update variant.h

* Update variant.h

* Update variant.h

* Update variant.h

* trunk fmt

* trunk fmt

* Update variant.h

* Update variant.h

* Update variant.h

* Update variant.h

Specify behavior

* Update variant.h

Maintain behavior

* trunk fmt

* Update variant.h

* Update variant.h

* Update variant.h

* Update variant.h

* Update variant.h

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2023-09-27 16:01:40 -05:00
TavisandBen Meadors 98290e5d7b Re issue: #2496 Populate the position log entries from PositionModule with data fields (#2839)
* Populate the position log entries with data fields

includes datafields with no data as 0

* trunk check formatted.

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2023-09-27 16:00:56 -05:00
Ben Meadors ad529924f1 Code duplication cleanup for smart position logic (#2840) 2023-09-27 10:32:35 -05:00
github-actions[bot] 07d51a2ca4 [create-pull-request] automated change (#2837) 2023-09-26 14:54:35 -05:00
github-actions[bot]andthebentern 47301a5ac0 [create-pull-request] automated change (#2836)
Co-authored-by: thebentern <thebentern@users.noreply.github.com>
2023-09-26 11:11:54 -05:00
Ben Meadors 0d023ea215 Revert "Fix compression (#2806) (#2819)" (#2835)
This reverts commit cdac643749.
2023-09-26 07:02:06 -05:00
Ben Meadors b5e952db24 No more goober traffic on public mqtt (#2831)
* No more goober traffic on public mqtt

* Oops
2023-09-26 06:19:17 -05:00
GUVWAFandBen Meadors a1c433748a RP2040: Add SerialModule support (#2830)
* Support for SerialModule on RP2040

* Remove one !defined too many

* Increase serial RX_BUFFER: more reliable for long packets
Even results into an error for ESP32

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2023-09-26 05:45:34 -05:00
Jonathan Bennett 04b2ab82dc Add GPS pin definitions missed in revamp (#2834) 2023-09-26 05:44:08 -05:00
github-actions[bot]andthebentern e96ba7cbcf [create-pull-request] automated change (#2827)
Co-authored-by: thebentern <thebentern@users.noreply.github.com>
2023-09-25 06:31:22 -05:00
Andre KandBen Meadors 61f6fb22c5 move STATE_SEND_METADATA to beginning of wantConfig (#2820)
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2023-09-24 07:22:54 -05:00
github-actions[bot]andthebentern db7b77c76e [create-pull-request] automated change (#2823)
Co-authored-by: thebentern <thebentern@users.noreply.github.com>
2023-09-24 07:01:46 -05:00
Andre KandBen Meadors 350090ec0d remove residual code for mesh_sds_timeout_secs (#2821)
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2023-09-24 06:49:35 -05:00
GUVWAFandBen Meadors cdac643749 Fix compression (#2806) (#2819)
* Fix compression: encode to bytes after `decoded` is modified

* Change payload size to decompressed length

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2023-09-24 06:49:21 -05:00
1a2c7f00e1 Gps cleanup and powersave (#2807)
* Refactor GPS to not probe if pins not defined

* Use Named Constructor to clean up code

* Move doGPSPowerSave to GPS class

* Make sure to set GPS awake on triple-click

* Cleanup and remove dead code

* Rename GPS_PIN_WAKE to GPS_PIN_STANDBY

* Actually put GPS to sleep between fixes

* add GPS_POWER_TOGGLE for heltec-tracker and t-deck

* Change GPS_THREAD_INTERVAL to 200 ms

* More dead code, compiler warnings, and add returns

* Add Number of sats to log output

* Add pgs enable and triple-click config

* Track average GPS fix time to judge low-power time

* Feed PositionModule on GPS fix

* Don't turn off the 3v3_s line on RAK4631
when the rotary is present.

* Add GPS power standbyOnly option

* Delay setting time currentQuality
to avoid strange log message.

* Typos, comments, and remove unused variable

* Short-circuit the setAwake logic on GPS disable

* heltec-tracker 0.3 GPS power saving

* set en_gpio to defined state

* Fix fixed_position logic with GPS disabled

* Don't process GPS serial when not isAwake

* Add quirk for Heltec Tracker GPS powersave

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
Co-authored-by: mverch67 <manuel.verch@gmx.de>
Co-authored-by: Manuel <71137295+mverch67@users.noreply.github.com>
2023-09-23 23:45:35 -05:00
Jonathan Bennett 7eff5e7bcb Fix for Pi Pico hang (#2817)
* Fix for Pi Pico hang

* Pi Pico fix part 2: Electric Boogaloo
2023-09-20 19:34:45 -05:00
Jonathan Bennett 17207681ef Remove GPS pins from devices lacking built-in GPS (#2812) 2023-09-19 10:55:14 -05:00
Thomas Göttgens 94f7c7e472 Merge pull request #2814 from meshtastic/create-pull-request/patch
Changes by create-pull-request action
2023-09-19 12:46:26 +02:00
caveman99 0a12d67d19 [create-pull-request] automated change 2023-09-19 10:45:28 +00:00
Thomas Göttgens 3175a3d630 Merge pull request #2811 from meshtastic/create-pull-request/patch
Changes by create-pull-request action
2023-09-19 10:48:41 +02:00
thebentern 4e9bf75340 [create-pull-request] automated change 2023-09-18 19:49:42 +00:00
github-actions[bot]andthebentern e8970ad66b [create-pull-request] automated change (#2810)
Co-authored-by: thebentern <thebentern@users.noreply.github.com>
2023-09-18 13:26:09 -05:00
code8buster f737ee59ec Deny maxhops to anyone who sets >7 (#2808)
* Deny maxhops to anyone who sets >7

* Use reliable hop count instead of 3
2023-09-18 12:58:09 -05:00
Ric In New Mexico 6d211815d9 Temp fix for S3 bluetooth (#2809)
Need to roll back espressif to v6.3.2
2023-09-18 14:26:19 +02:00
Manuel 1bae926576 fix: nodenum 4 (#2798)
* tryfix: nodenum 4

* trunk fmt

* rename vars and fix brackets

* purge invalid db entries

* trunk fmt
2023-09-18 06:16:37 -05:00
Thomas Göttgens a1514b8b64 Enable (new) ADC and GPS capability. (#2792)
* Enable (new) ADC and GPS capability.
* Make Picomputer a canon device and define ADC for new board revision
2023-09-18 11:38:33 +02:00
Jonathan BennettandBen Meadors 8b82ae6fe3 refactor and avoid needless probe (#2799)
* Use UINT32_MAX to indicate no configured GPS

* Refactor GPS to not probe if pins not defined

* Minor cleanups related to rework

* Use Named Constructor to clean up code

* Actually disable the GPS thread

* Don't actually disable the GPS thread

* Move doGPSPowerSave to GPS class

* Make sure to set GPS awake on triple-click

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2023-09-16 23:10:10 -05:00
Ric In New MexicoandBen Meadors 822c150e0d Fixing typo in src/mesh/mesh-pb-constants.cpp logging (#2800)
* Update variant.h

Add second i2c channel on external connector for Station G1

* Create trunk-check.yml

* Fix typo in logging

Corrected typo in pb_msgdesc logging for packets failing to be decoded.

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2023-09-16 15:24:59 -05:00
github-actions[bot]andthebentern 0731902744 [create-pull-request] automated change (#2791)
Co-authored-by: thebentern <thebentern@users.noreply.github.com>
2023-09-12 18:00:29 -05:00
github-actions[bot]andthebentern b53cb38a09 [create-pull-request] automated change (#2790)
Co-authored-by: thebentern <thebentern@users.noreply.github.com>
2023-09-12 16:50:52 -05:00
Jonathan BennettandBen Meadors b02dd0e964 Move partial GPS initialization earlier in boot (#2788)
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2023-09-12 16:46:46 -05:00
Ben Meadors c608f0ba81 Fix time=0 bug for fixed_position nodes (#2789) 2023-09-12 15:54:50 -05:00
Jonathan Bennett e1839e33f2 Lazy probe of GPS (#2781)
* First attempt at lazy config of GPS

* More GPS rework
Break GPS init into smaller, interruptable steps
Move more GPS commands into ubx.h
Combine Setup functions

* Move the rest of UBX messages to ubs.h
2023-09-10 22:21:14 -05:00
ManuelandBen Meadors d6d51bc3f4 T-Deck/T-Watch: enhancements/fixes (#2786)
* T-Deck: enhancements/fixes

* trunk fmt

* T-Watch board update

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2023-09-10 06:54:25 -05:00
github-actions[bot]andthebentern 44a77a10e1 [create-pull-request] automated change (#2785)
Co-authored-by: thebentern <thebentern@users.noreply.github.com>
2023-09-10 06:34:48 -05:00
Ben Meadors 8255128eae Trunk finally spilled the beans about what it's upset about 2023-09-09 19:40:57 -05:00
Ric In New MexicoandBen Meadors d7a98519f4 Update variant.h (#2778)
* Update variant.h

Add second i2c channel on external connector for Station G1

* Create trunk-check.yml

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2023-09-09 19:37:35 -05:00
github-actions[bot]andthebentern e256520336 [create-pull-request] automated change (#2782)
Co-authored-by: thebentern <thebentern@users.noreply.github.com>
2023-09-08 14:34:58 -05:00
Ben Meadors fcf798df98 Experiment with moving gps init (#2780)
* Move it move it

* Moving to the end of the main setup method

* NimBLE version
2023-09-07 16:01:35 -05:00
Ben Meadors dcdf9b64de Ambient lighting (#2779)
* This was already defined and throwing a ton of warnings

* Ambient lighting module feature

* Use local instance type
2023-09-07 12:24:47 -05:00
Jonathan Bennett fd563e41f1 Add ubx-cfg-rxm and cfg-pm2 for ublock 6 powersave (#2777) 2023-09-07 12:24:21 -05:00
Jonathan Bennett 0fa3685161 Fix crash in GPS setup when GPS is disabled 2023-09-06 12:38:58 -05:00
code8buster 899f9dd7bf Merge pull request #2775 from GUVWAF/disabledNeighbor
Only update neighbors when module is enabled
2023-09-05 23:43:09 +00:00
GUVWAF 9af4ecf48f Remove unnecessary line when disabled 2023-09-05 21:42:39 +02:00
GUVWAF cfb6a1394c Only update neighbors when module is enabled 2023-09-05 19:56:42 +02:00
code8buster 1254031f7d Merge pull request #2772 from meshtastic/ubx-pmreq
UBX-RXM-PMREQ soft-off implemented
2023-09-05 17:15:12 +00:00
code8buster c91e306659 Move packet scratch declaration to header 2023-09-05 11:59:34 -04:00
code8buster 4ff343b20f no byte... just 8 unsigned bits please 2023-09-05 00:32:53 -04:00
code8buster 134fc75b67 UBX-RXM-PMREQ soft-off implemented 2023-09-05 00:26:42 -04:00
Ben Meadors fb23e479ac Update ESP32 platform (#2770) 2023-09-04 20:20:20 -05:00
github-actions[bot]andthebentern 5a61695016 [create-pull-request] automated change (#2769)
Co-authored-by: thebentern <thebentern@users.noreply.github.com>
2023-09-04 19:45:46 -05:00
github-actions[bot]andthebentern 3bcab0e223 [create-pull-request] automated change (#2768)
Co-authored-by: thebentern <thebentern@users.noreply.github.com>
2023-09-04 18:38:58 -05:00
GUVWAFandBen Meadors 17617ce031 Fix possible memory leak in NeighborInfo Module (#2765)
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2023-09-04 18:38:16 -05:00
Jonathan Bennett 97f0c734e0 Fix Neighborinfo crash
neighbors object wasn't initialized when module disabled, this
initializes it to a safe, empty object.
2023-09-04 18:15:27 -05:00
Jonathan Bennett e943fffe8c GPS fixes
Work aroung Serial reset issue on ESP32
Don't send unsupported command to G60xx GPS
2023-09-04 15:00:05 -05:00
ffcb131171 GPS toggle for RAK4631 (patch 2 of 2) (#2764)
* Added triple-press GPS toggle button changes

* Revert edits to extensions.json

* comma'd

* Update variant.h

Added the line:

// Define pin to enable GPS toggle (set GPIO to LOW) via user button triple press
#define PIN_GPS_EN 34 // GPS power enable pin

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
Co-authored-by: code8buster <communismisgreat@national.shitposting.agency>
2023-09-04 13:17:01 -05:00
bb1fe7cad3 GPS toggle for RAK4631 (patch 1 of 2) (#2763)
* Added triple-press GPS toggle button changes

* Revert edits to extensions.json

* comma'd

* Update platformio.ini

Added line:

-DGPS_POWER_TOGGLE ; comment this line to disable triple press function on the user button to turn off gps entirely.

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
Co-authored-by: code8buster <communismisgreat@national.shitposting.agency>
2023-09-04 13:16:39 -05:00
Ben Meadors ad40493a39 Add speed, heading, and DOP to default position flags (#2759)
* Add speed and heading

* Add DOP
2023-09-04 06:46:27 -05:00
Jonathan Bennett ac62330e1c Found lost byte dropped from moduleinfo
Attempt to fix CFG-GNSS for neo-6m
2023-09-03 22:38:03 -05:00
code8buster 53f6a43661 Merge pull request #2752 from meshtastic/nmea-rate
Adds GPS Serial Speed scanning, fixes ublox GNSS setup errors
2023-09-03 21:57:51 +00:00
Jonathan Bennett 7ad94da1c6 Add more to GPS_DEBUG and fix ubx7 CFG-GNSS 2023-09-03 16:20:01 -05:00
Jonathan Bennett ecdb75aae0 Correct UBX-CFG-PMS message 2023-09-03 02:16:29 -05:00
Jonathan Bennett 7c98445ca3 Cleanup in prep for commiting
Fix some compilation warnings
gate debug code behind GPS_DEBUG
minor fix in u-blox protocol detection
Begin to gate GPS messages based on protover
2023-09-03 01:50:11 -05:00
Jonathan Bennett b21368ecfa Add delay and debug code for GPS probe 2023-09-02 20:35:38 -05:00
Jonathan Bennett 1a178c7d33 Add check for GPS Frame Errors message 2023-09-02 04:29:48 -05:00
Jonathan Bennett 5d6f0ea6c4 Fix possible edge case in GPS detection 2023-09-01 16:24:28 -05:00
Ben Meadors 5bd861f3d8 Merge branch 'master' into nmea-rate 2023-09-01 15:08:32 -05:00
GUVWAF 6d93fab495 Add neighbor IDs to MQTT JSON (#2756)
* Add neighbor IDs to JSON

* Limit #neighbors to what we can actually save

* Put neighbor IDs in an array

* Add SNR to neighbors in nested objects
2023-09-01 14:35:57 -05:00
Jonathan Bennett 6803fd7949 More fixes for GPS chips with unexpected baud 2023-09-01 12:11:39 -05:00
Jonathan Bennett a61f969773 Increase GPS detection timeout slightly 2023-08-31 22:19:50 -05:00
Jonathan Bennett 79cfc4b725 Avoid Serial output mangling with RTOS. 2023-08-31 20:40:01 -05:00
Jonathan Bennett cf762bbd42 Cut down delay times for GPS probe and init 2023-08-31 20:39:23 -05:00
code8buster 3d2c419d0d Remove leftover debug msg 2023-08-30 16:24:56 -04:00
Jonathan Bennett 903f619609 Add GPS serial speed scan 2023-08-28 19:01:14 -05:00
Jonathan Bennett 2e3f762d3d Catch a nullptr return rather than crash 2023-08-28 04:05:45 -05:00
Jonathan Bennett a42266f74b GPS: Fix checksum and remove spurious returns 2023-08-28 04:05:45 -05:00
github-actions[bot]andthebentern a605c69eb4 [create-pull-request] automated change (#2748)
Co-authored-by: thebentern <thebentern@users.noreply.github.com>
2023-08-26 07:36:04 -05:00
Thomas Göttgens 282cc0b16a Merge pull request #2737 from meshtastic/BBQ10Kb-Fix
Bbq10 kb fix
2023-08-26 11:22:35 +02:00
Thomas Göttgens 4ab67f3668 IGOR! Fetch me the brain! 2023-08-25 16:44:39 +02:00
Thomas Göttgens 312028b161 Possble fix ESC 2023-08-25 09:27:09 +02:00
Ben Meadors ecd48db69c Merge branch 'master' into BBQ10Kb-Fix 2023-08-24 19:57:49 -05:00
Ben Meadors 03dc36ea12 Use fixed position regardless of gps lock (#2744) 2023-08-24 10:55:49 -05:00
Mark Trevor Birss c2ae38405e Update architecture.h (#2746) 2023-08-24 07:58:24 -05:00
Thomas Göttgens 2a1d8c40b4 add TAB and ESC handling 2023-08-24 14:24:26 +02:00
Ben Meadors e2441c425a Merge branch 'master' into BBQ10Kb-Fix 2023-08-24 07:06:42 -05:00
00ffe73ebd Heltec ESP32-C3 HT-CT62 support (#2741)
* Add files via upload

* Update platformio.ini

* Update variant.h

* Update platformio.ini

* Switch to our new HW_MODEL

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
Co-authored-by: Ben Meadors <thebentern@tuta.io>
2023-08-23 07:59:21 -05:00
Thomas Göttgens 3355019de3 Merge branch 'master' into BBQ10Kb-Fix 2023-08-23 09:45:06 +02:00
Thomas Göttgens 5bb207d88b reset sym after second keypress
also remove debug print and non-working scancodes.
2023-08-23 09:44:20 +02:00
github-actions[bot]andthebentern 5453e4d123 [create-pull-request] automated change (#2742)
Co-authored-by: thebentern <thebentern@users.noreply.github.com>
2023-08-22 17:11:22 -05:00
Thomas Göttgens 7f1b58a222 trunk fmt 2023-08-22 21:23:37 +02:00
Thomas Göttgens 39357b2686 Merge branch 'BBQ10Kb-Fix' of github.com:meshtastic/firmware into BBQ10Kb-Fix 2023-08-22 21:23:00 +02:00
Thomas Göttgens d6b629ae04 update SYM Scancode 2023-08-22 21:19:51 +02:00
Thomas Göttgens 7b1aeb60cd Try manual scancode for SYM 2023-08-22 21:19:51 +02:00
Thomas Göttgens 5c7c1cd253 silence compiler warnings 2023-08-22 21:19:51 +02:00
Thomas Göttgens 8cfe130df3 update SYM Scancode 2023-08-22 21:11:19 +02:00
Thomas Göttgens feef86942d Merge pull request #2738 from meshtastic/neighbourinfo-fix
fix crash and Debug logging in NeighbourInfo
2023-08-22 16:27:52 +02:00
Thomas Göttgens 5f3a8b4924 fix crash and Debug logging in NeighbourInfo 2023-08-22 15:43:21 +02:00
Thomas Göttgens 0fcaaf39b0 Try manual scancode for SYM 2023-08-22 11:23:19 +02:00
Thomas Göttgens a55eac5c20 silence compiler warnings 2023-08-22 10:58:54 +02:00
b47c9c165a [create-pull-request] automated change (#2733)
Co-authored-by: thebentern <thebentern@users.noreply.github.com>
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2023-08-19 18:06:33 -05:00
Thomas Göttgens ecceb10910 different debug print 2023-08-19 21:28:02 +02:00
Thomas Göttgens 6fc76103a0 temporarily Enable debug print 2023-08-19 20:55:50 +02:00
Ben Meadors f35c7be917 Just putting back DELAYED_INTERVAL for reliability. Ran into problems 2023-08-19 09:45:48 -05:00
Ben Meadors 364364263b Remove range_test goalie from drawing frames 2023-08-19 09:44:40 -05:00
ef957bfac5 support BB Q10 keyboard (#2703)
* support BB Q10 keyboard

* remove debug code

* fix wrong logic

* fix left/right keys for cardkb

* Try to enable Q10 kb after all

* cppcheck

* Only fire on Key release and assume 0x0a is a enter as well

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
Co-authored-by: Thomas Göttgens <tgoettgens@gmail.com>
2023-08-19 08:37:42 -05:00
Ben Meadors 5d78795065 Portnum promiscuity for text messages from other modules (#2732)
* Add interested portnums to TextMessageModule

* Send Detection Sensor Module messages on its own portnum

* Add to Ext. Notification and consolidate logic

* RANGE_TEST_APP portnum for RangeTestModule
2023-08-19 07:46:34 -05:00
github-actions[bot]andthebentern 2dbdda204f [create-pull-request] automated change (#2731)
Co-authored-by: thebentern <thebentern@users.noreply.github.com>
2023-08-18 10:17:55 -05:00
Jonathan Bennett 4767bd5497 Rename utils.h to avoid collision with library. (#2730) 2023-08-17 20:22:34 -05:00
Thomas Göttgens 05efd68097 Merge pull request #2729 from meshtastic/trunk-fmt
update trunk to latest version
2023-08-17 13:46:44 +02:00
Thomas Göttgens a90eef432f update trunk to latest version 2023-08-17 12:17:36 +02:00
Thomas Göttgens 762166495f Merge branch 'master' into raspi-portduino 2023-08-17 10:06:34 +02:00
Ben Meadors 929b8f6209 Fix thread to use getConfiguredOrDefaultMs (#2727)
* WIP

* Updates

* Move it out of the macro guard so portduino can build

* Changes from feedback

* Use minimum_broadcast_secs as interval if we just broadcasted to avoid wasting cpu cycles

* Fmt

* Merge conflict resolution boogered me up

* Missed a spot

* getConfiguredOrDefaultMs

* Get the minimum interval
2023-08-16 15:08:06 -05:00
Thomas Göttgens 5d76771fab Permanently Enable Canned Messages on T-Deck and Picomputer (#2728)
* - Permanently Enable Canned Messages on T-Deck and Picomputer
- picomputer has a really dark TFT; switch color to white for better UX.

* well, you know... bullock...
2023-08-16 15:07:22 -05:00
Thomas Göttgens 91eb64d7b7 Fix warning about init order (#2725) 2023-08-15 20:17:15 -05:00
Ben Meadors 03fe4c629a Dection Sensor module duty cycle interval optimization (#2723)
* WIP

* Updates

* Move it out of the macro guard so portduino can build

* Changes from feedback

* Use minimum_broadcast_secs as interval if we just broadcasted to avoid wasting cpu cycles

* Fmt

* Merge conflict resolution boogered me up

* Missed a spot
2023-08-15 12:23:07 -05:00
Ben Meadors 144dfe9805 Initial Detection sensor module feature (#2722)
* WIP

* Updates

* Doh!

* Move it out of the macro guard so portduino can build

* Changes from feedback
2023-08-14 19:00:51 -05:00
rcarterazandBen Meadors 18899fd168 Update variant.h (#2719)
remove HAS_GPS 0 so users can add gps

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2023-08-13 23:45:23 -05:00
code8buster fcfd83bc89 Remove auto GPS shutoff for fixed position nodes (#2720) 2023-08-13 15:56:49 -05:00
github-actions[bot]andthebentern a3d2b6166c [create-pull-request] automated change (#2716)
Co-authored-by: thebentern <thebentern@users.noreply.github.com>
2023-08-12 20:49:42 -05:00
Manuel fb5f2e48a5 fix T-Deck trackball crashes (#2714)
* try-fix: nodenum crash during boot

* Revert "try-fix: nodenum crash during boot"

This reverts commit 632012e197632aafdbd5ef09872622274e00bcc0.

* fix/workaround: trackball interrupt crashes

* trunk fmt

* add OSThread to trackballInterrupt
2023-08-12 19:44:05 -05:00
Jonathan Bennett d29c975e3c Comment out extra-chatty debug message (#2715) 2023-08-12 13:51:31 -05:00
Ben Meadors 00ea6ef5ad Merge branch 'master' into raspi-portduino 2023-08-12 09:40:26 -05:00
Jonathan BennettandBen Meadors c44986127e More GPS work (#2711)
Increase GPS buffer on esp32
Check for and flush GPS buffer when overfilled and corrupted.

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2023-08-12 09:29:44 -05:00
Ben Meadors 6e0b6684ee Extend node max to 100 and remove mesh_sds_timeout_secs (#2713)
* Extend node max to 100 and remove mesh_sds_timeout_secs

* Const pointers for you and you and you

* Fixes and supressions

* Missed it

* uint

* Resize

* Derp
2023-08-12 09:29:19 -05:00
ManuelandBen Meadors 84ddfea491 try-fix: max nodes crash during boot (#2712)
* try-fix: nodenum crash during boot

* Revert "try-fix: nodenum crash during boot"

This reverts commit 632012e197632aafdbd5ef09872622274e00bcc0.

* try-fix: max nodes crash during boot

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2023-08-12 09:28:58 -05:00
Ben Meadors 3d6fb13f9a Stop failing on low severity styling issues 2023-08-12 06:43:13 -05:00
Manuel 54c48329c8 Merge pull request #2710 from meshtastic/fix-screen-setup
fix repeater crash during screen setup
2023-08-12 10:46:07 +02:00
mverch67 ede31a2080 fix repeater crash 2023-08-11 19:41:21 +02:00
Jonathan BennettandBen Meadors 9470d4694b Pickier parsing of NMEA to detect an L76K chip (#2699)
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2023-08-10 11:21:35 -05:00
github-actions[bot]andthebentern 2074c76780 [create-pull-request] automated change (#2697)
Co-authored-by: thebentern <thebentern@users.noreply.github.com>
2023-08-10 05:53:55 -05:00
Thomas Göttgens b5b66f43f2 Merge branch 'master' into raspi-portduino 2023-08-09 11:19:23 +02:00
Thomas Göttgens 9f6584bd67 Merge pull request #2694 from mverch67/t-watch-fixes
T-Watch S3 fixes
2023-08-08 22:49:37 +02:00
mverch67 dd69de9f32 trunk fmt 2023-08-08 20:21:20 +02:00
mverch67 616553ed72 doing the math :) 2023-08-08 20:14:12 +02:00
mverch67 1986267d65 check payload size 2023-08-08 20:02:29 +02:00
mverch67 1d0ac2caf7 trunk fmt 2023-08-08 18:55:00 +02:00
mverch67 746d7268a2 fix picomputer 2023-08-08 18:51:11 +02:00
Manuel 9a7777dbdb Merge branch 'master' into t-watch-fixes 2023-08-08 18:21:57 +02:00
mverch67 0fe99b0caa T-Watch fixes 2023-08-08 18:06:39 +02:00
Ben Meadors f9798b7dda Bump to 2.2 2023-08-08 08:05:43 -05:00
Ben Meadors 23fb377fd7 Don't cancel sending "seen" messages on MQTT enabled nodes (#2690) 2023-08-08 06:27:26 -05:00
Thomas Göttgens 4808a5c57f also update other boards with those (#2691) 2023-08-07 23:22:17 +00:00
Thomas GöttgensandBen Meadors d25c368985 Try enabling the secondary I2C bus on Heltec V3 (#2689)
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2023-08-07 15:17:26 -05:00
GUVWAFandBen Meadors a5f3dea40b Clarify that when rebooting is not implemented some settings may not apply (#2688)
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2023-08-07 15:16:56 -05:00
Thomas Göttgens f026c3308c add picomputer 2023-08-07 21:34:01 +02:00
Thomas Göttgens ed4e7a4cee Change Target Name 2023-08-07 21:33:42 +02:00
Thomas Göttgens 95f67d70ea Merge pull request #2493 from meshtastic/picomputer-s3
Add variant an plumbing for #2468
2023-08-07 21:17:24 +02:00
Thomas Göttgens e3260c1d19 Merge branch 'master' into picomputer-s3 2023-08-07 20:27:44 +02:00
Thomas Göttgens 98f3be0665 Merge pull request #2647 from meshtastic/2.2-working-changes
2.2 Changes
2023-08-07 20:27:05 +02:00
Ben Meadors dc31024764 Merge remote-tracking branch 'origin/master' into 2.2-working-changes 2023-08-07 13:24:10 -05:00
Ben Meadors 5bbcb40f7a Updated protos 2023-08-07 13:23:21 -05:00
Thomas Göttgens 8218a729e0 Merge branch 'picomputer-s3' of github.com:meshtastic/firmware into picomputer-s3 2023-08-07 19:58:48 +02:00
Thomas Göttgens cbc3e605dd fix building for other platforms 2023-08-07 19:57:47 +02:00
Thomas Göttgens 94c41a4fed Merge branch 'master' into picomputer-s3 2023-08-07 19:47:29 +02:00
caveman99 1afe9f75bd [create-pull-request] automated change 2023-08-07 19:46:28 +02:00
Thomas Göttgens 402f8ba524 Let's see what this breaks... 2023-08-07 19:34:42 +02:00
Ben Meadors 04bbdc6b8a Platform / dep updates (#2684)
* Update nordic platform

* Update sensor libs
2023-08-06 10:06:08 -05:00
Thomas Göttgens 0084c0881d Merge branch 'picomputer-s3' of github.com:meshtastic/firmware into picomputer-s3 2023-08-06 16:57:03 +02:00
Thomas Göttgens 8552cc44b9 Merge branch 'master' into picomputer-s3 2023-08-06 16:55:28 +02:00
Thomas Göttgens 684cce7640 trunk fmt 2023-08-06 16:53:37 +02:00
Thomas Göttgens 114eb0c952 enable Canned Messages on T-Deck without presets 2023-08-06 16:53:37 +02:00
Thomas Göttgens bed2bfa074 trunk fmt 2023-08-06 16:47:55 +02:00
Thomas Göttgens 0aef8703b6 - use LovyanGFX for m5stack
- update some comments
2023-08-06 16:47:55 +02:00
Thomas Göttgens f5d323fdd3 trunk fmt 2023-08-06 16:21:39 +02:00
Thomas Göttgens 568cc259af Don't crash when no radio detected. 2023-08-06 16:21:39 +02:00
Neil HaoandBen Meadors 42039e27e7 Initialize the L76K Chip, use GPS + GLONASS + BEIDOU (#2680)
* 'nano-g2-ultra'

* revert overcommit

* nano-g2-ultra-fmt

* revert overcommit

* revert overcommit

* Added BEIDOU support to L76K

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2023-08-06 08:28:37 -05:00
Mark Trevor Birss 400b71c152 Update variant.h 2023-08-05 17:42:51 +02:00
Mark Trevor Birss b1f6ff1280 Update variant.h 2023-08-05 17:42:51 +02:00
Ben Meadors cfe5c7f31d Tweaking Power FSM states (#2676)
* Tweaking Power FSM states

* Turn bluetooth back on after serial disconnected

* Remove references to deprecated mesh_sds_timeout_secs
2023-08-04 06:01:01 -05:00
Thomas Göttgens 1e71d346ae Merge branch 'master' into raspi-portduino 2023-08-03 21:36:43 +02:00
Thomas Göttgens 4e54bec525 Force small fonts on Low DPI screens, no matter what the driver default uses. Up till now we assumed large fonts on E-Paper and TFT Screens. (#2677) 2023-08-03 06:58:19 -05:00
Thomas Göttgens e0bf15b80e trunk fmt 2023-08-03 10:05:38 +02:00
Jm Casler 26264fd908 more fixes for trunk 2023-08-03 10:05:38 +02:00
Jm Casler 794948d7e4 fixing trunk problems 2023-08-03 10:05:38 +02:00
Jm Casler e9cbe54eca add more documentaiton 2023-08-03 10:05:38 +02:00
Jm Casler 641d117106 Update extensions.json 2023-08-03 10:05:38 +02:00
Jm Casler 5f38e79b8f Add documentation to a few areas 2023-08-03 10:05:38 +02:00
Thomas Göttgens b238aebe38 Merge branch 'picomputer-s3' of github.com:meshtastic/firmware into picomputer-s3 2023-08-03 09:37:32 +02:00
GUVWAF e05c8e60d9 Save Neighbors to flash 2023-08-02 20:56:24 +02:00
Ben Meadors f1bcc300d9 Merge branch 'master' into 2.2-working-changes 2023-08-02 12:58:32 -05:00
Jonathan Bennett 06a6a992c2 GPS Fixes for nrf52 (#2675)
Expands board serial buffer from 64 (!) to 1024
Adds some debugging messages when problems are detected.
2023-08-02 10:08:59 -05:00
Ben Meadors 11be856507 Merge branch 'master' into 2.2-working-changes 2023-08-01 21:00:58 -05:00
github-actions[bot]andthebentern 7fe815a327 [create-pull-request] automated change (#2674)
Co-authored-by: thebentern <thebentern@users.noreply.github.com>
2023-08-01 21:00:34 -05:00
Ben Meadors 191a69dd26 Don't create potential NodeInfo storm on telemetry reponse from Repeater (#2673)
* Don't create potential NodeInfo storm on telemetry reponse from Repeaters

* Check decoded
2023-08-01 18:24:40 -05:00
Ben Meadors 9eeec6c083 Reply to Repeater in DeviceTelemetry module (#2661) 2023-08-01 16:18:10 -05:00
Ben Meadors 919b2d1e48 Merge branch 'master' into raspi-portduino 2023-07-31 19:00:00 -05:00
Ben Meadors c4474a7b99 Merge branch 'master' into picomputer-s3 2023-07-31 18:59:50 -05:00
Ben Meadors 0821cff1c8 Merge remote-tracking branch 'origin/master' into 2.2-working-changes 2023-07-31 18:54:53 -05:00
github-actions[bot]andthebentern b799b7bf62 [create-pull-request] automated change (#2672)
Co-authored-by: thebentern <thebentern@users.noreply.github.com>
2023-07-31 18:51:15 -05:00
Ben Meadors 90ec8eae6c Backmerge master protos 2023-07-31 18:28:27 -05:00
Thomas Göttgens ba172aae32 Merge branch 'picomputer-s3' of github.com:meshtastic/firmware into picomputer-s3 2023-07-31 22:28:04 +02:00
Thomas Göttgens 26338b8f2b Merge branch 'master' into picomputer-s3 2023-07-31 22:27:24 +02:00
Jonathan BennettandBen Meadors 939a359e7e Adds DOP fields to JSON MQTT output (#2671)
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2023-07-31 15:19:36 -05:00
GUVWAF 5a5af4707c SerialModule SIMPLE mode: use write() instead of printf() 2023-07-31 22:18:42 +02:00
Thomas Göttgens ef5e21d3da Enable Trunk on Windows 2023-07-31 21:37:55 +02:00
Ben Meadors 8a49221b7f Update version.properties 2023-07-30 20:17:57 -05:00
Ben Meadors 76dc805184 Add Nano-g2-ultra 2023-07-30 14:07:17 -05:00
GUVWAF 297708a50b Manually update protos 2023-07-30 17:27:43 +02:00
GUVWAF a61a4fad3e Merge pull request #2667 from GUVWAF/removeNeighbors
Remove neighbors after twice their broadcast interval
2023-07-30 17:17:17 +02:00
GUVWAF c66b68b0cc Remove neighbors after twice their broadcast interval 2023-07-30 16:54:39 +02:00
Ben Meadors 97d7a89644 Update protobufs 2023-07-30 07:58:11 -05:00
Ben Meadors 04cba45c60 Merge branch 'master' into 2.2-working-changes 2023-07-30 07:54:11 -05:00
ManuelandBen Meadors 502a6596a3 T deck: support keyboard, trackball and touchscreen (#2665)
* add hwid for auto-detection

* fix: heltec-wireless-tracker USB serial

* T-Deck support

* trunk fmt

* set FRAMERATE to 1

* fix some defines

* trunk fmt

* corrected vendor link

* T-Deck: support keyboard, trackball & touch screen

* T-Watch add touchscreen defs, remove getTouch

* fix warnings

* getTouch uint16 -> int16

* fix touch x,y

* fix I2C port

* CannedMsgModule: use entire display height

* trunk fmt

* fix I2C issue for T-Watch

* allow dest selection in canned mode

* fix: allow dest selection in canned mode

* use tft.setBrightness() to poweroff display

* Increased t-watch framerate and added back haptic feedback

* add da ref

* Move to touched

* improved sensitivity and accuracy of touch events

* use double tap to send canned message

* fix warning

* trunk fmt

* Remove extra hapticFeedback()

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2023-07-30 07:51:26 -05:00
Ben Meadors 5aedd84c7d Merge branch 'master' into 2.2-working-changes 2023-07-29 08:15:17 -05:00
Neil HaoandBen Meadors b9c9f0f865 nano-g2-ultra (#2660)
* 'nano-g2-ultra'

* revert overcommit

* nano-g2-ultra-fmt

* revert overcommit

* revert overcommit

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2023-07-29 07:54:56 -05:00
GUVWAF ffcc1a0275 RP2040: Enable ExternalNotification and RangeTest Module, set randomSeed (#2664)
* Enable ExternalNotification (and RangeTest) Module

* Set a random seed at boot
2023-07-29 07:19:58 -05:00
Ben Meadors 3d697f8cf4 Enable SX126X RX Boosted gain by default (#2663) 2023-07-28 10:39:40 -05:00
Ben Meadors 38c9a1ea07 neighborInfo->node_broadcast_interval_secs 2023-07-28 10:36:44 -05:00
Ben Meadors 0eefd0912f Move node_broadcast_interval_secs 2023-07-28 10:28:14 -05:00
Ben Meadors 0cda8e6087 Start plumbing node_broadcast_interval_secs 2023-07-28 06:58:28 -05:00
Ben Meadors 2cf648928a Add node_broadcast_interval_secs to Neighbor 2023-07-28 06:43:21 -05:00
Andre K 3cd7d8d6af update min_app_version to 2.2.0 2023-07-28 06:22:16 -03:00
Ben Meadors 702a83b525 Bumb device state version 2023-07-27 16:03:57 -05:00
GUVWAF 32246850aa Convert protobuf values that are unsigned properly to uint in JSON (#2659) 2023-07-27 13:53:20 -05:00
Ben Meadors 74650ca276 Words are important 2023-07-27 13:23:18 -05:00
Ben Meadors 0141bbe772 Regen 2023-07-27 12:59:06 -05:00
Ben Meadors 049c587ca2 Add phoneapi plumbing. Need to regen protos on my other machine 2023-07-27 12:51:31 -05:00
Ben Meadors 1a28225cd5 Merge branch 'master' into 2.2-working-changes 2023-07-27 08:55:48 -05:00
Ben Meadors 6bd870c454 I guess we have to use SHAs (lame) 2023-07-27 07:59:39 -05:00
Ben Meadors c782380373 Fix semgrep errors 2023-07-27 07:04:00 -05:00
Ben Meadors 4fd756acd8 Merge branch 'master' into 2.2-working-changes 2023-07-27 06:42:02 -05:00
Ben Meadors 0b509c7e79 Remove concurrency groups for now. They seem to cause CI hangs 2023-07-27 06:41:39 -05:00
Ben Lipsey 86af578df9 Preferred units when distance unknown (#2652)
* units when distance unknown

* replace deleted comment
2023-07-26 18:06:31 -05:00
Thomas Göttgens ff11506922 Merge pull request #2649 from meshtastic/neighborinfo
add Neighborinfo
2023-07-26 13:07:01 +02:00
Ben Meadors f35b422365 Trunk 2023-07-25 20:54:01 -05:00
Ben Meadors 08f1ac785a Gut NodeDb and remove deprecated protos 2023-07-25 19:13:19 -05:00
Ben Meadors 146ed067a1 Merge branch 'master' into neighborinfo 2023-07-25 16:14:50 -05:00
Ben Meadors bdcf17a3f7 Add T-Deck to S3 ota logical branch (#2644)
* Add T-Deck to S3 ota logical branch

* Revert "Add T-Deck to S3 ota logical branch"

This reverts commit d0aef9dc26d6caadadf5769d8a3535f322ad5eed.

* Add targets

* Get the bat file too
2023-07-25 16:13:32 -05:00
github-actions[bot]andthebentern 81edf363d7 [create-pull-request] automated change (#2645)
Co-authored-by: thebentern <thebentern@users.noreply.github.com>
2023-07-25 05:46:11 -05:00
Ben Meadors 96c6a20e03 Ensure that MQTT is enabled and log initialization (#2643) 2023-07-24 12:33:01 -05:00
Ben Meadors 3fbe2d771c Hopefully this cancels previous CI runs for a branch (#2642) 2023-07-24 09:47:16 -05:00
Jonathan BennettandBen Meadors ac9c81f6d1 Check Position Request for Primary Channel (#2638)
Prevents leaking location data to secondary channels.

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2023-07-24 09:37:56 -05:00
Ben Meadors 2e7c95a110 Merge branch 'master' into neighborinfo 2023-07-24 07:24:34 -05:00
Ben Meadors 490abdac96 Whoops 2023-07-24 07:22:04 -05:00
Ben Meadors b17436a023 Patch gather-artifacts 2023-07-24 06:54:05 -05:00
rcarteraz b9ae63cb3c Update Bug Report.yml (#2640)
Add T-Deck, T-Watch, Wireless Paper, and Wireless Tacker to device list.
2023-07-24 06:44:19 -05:00
github-actions[bot]andthebentern 55701692fd [create-pull-request] automated change (#2637)
Co-authored-by: thebentern <thebentern@users.noreply.github.com>
2023-07-24 06:43:47 -05:00
Thomas Göttgens 171cca435e Merge branch 'master' into raspi-portduino 2023-07-24 11:00:58 +02:00
Ben Meadors 470363d294 Update Hydra to use new TXEN->DIO2 macro (#2636) 2023-07-22 18:59:33 -05:00
github-actions[bot]andthebentern fb21bfe0f5 [create-pull-request] automated change (#2635)
Co-authored-by: thebentern <thebentern@users.noreply.github.com>
2023-07-22 09:37:51 -05:00
Ben Meadors 0739bc0cea T-Watch S3 Support (#2632)
* T-Watch WIP

* Updates

* Temp

* Update screen spi bus and and backlight en

* Peripherals progress

* Fixes

* Fixes

* Updates

* DRV scaffolding

* Fixed touch-screen driver selection. WIP on DRV haptic feedback

* DRV2605 pmu channel

* Trunk

* Fixes and defaults

* Dropped an s

* Move PMU and turn off screen that way

* Add t-deck and t-watch-s3 to CI and cleanup

* More cleanup
2023-07-22 09:26:54 -05:00
Ben Meadors 3a24882e76 Merge branch 'master' into neighborinfo 2023-07-22 08:46:27 -05:00
andrew-morozandBen Meadors 1c74479555 xiao-ble: add initial support for the Xiao BLE + Ebyte E22-900M30S (#2633)
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2023-07-21 20:37:00 -05:00
rcarteraz 084ad1b722 Update main_matrix.yml (#2634)
Add Heltec Wireless Paper to S3 Boards
2023-07-21 19:32:39 -05:00
Manuel 2486892e6d Basic T-Deck support (#2630)
* add hwid for auto-detection

* fix: heltec-wireless-tracker USB serial

* T-Deck support

* trunk fmt

* set FRAMERATE to 1

* fix some defines

* trunk fmt

* corrected vendor link
2023-07-19 08:13:51 -05:00
github-actions[bot]andthebentern 77efbb3f5d [create-pull-request] automated change (#2626)
Co-authored-by: thebentern <thebentern@users.noreply.github.com>
2023-07-18 10:00:12 -05:00
Ben Meadors 41b07de5a2 Merge branch 'master' into neighborinfo 2023-07-17 09:21:08 -05:00
Thomas Göttgens 1745722dac Merge branch 'picomputer-s3' of github.com:meshtastic/firmware into picomputer-s3 2023-06-28 09:12:10 +02:00
Ben Meadors 849599cd8e Merge branch 'master' into picomputer-s3 2023-06-27 15:40:13 -05:00
Thomas Göttgens e878f55ed3 Merge branch 'master' into raspi-portduino 2023-06-27 18:13:24 +02:00
Thomas Göttgens bfc567ad89 Add variant an plumbing for #2468 2023-06-27 18:11:58 +02:00
Thomas Göttgens b665786c77 Merge branch 'master' into neighborinfo 2023-06-27 18:00:20 +02:00
GUVWAF e60a5f1cf2 Setter for NeighborInfo 2023-06-25 15:41:19 +02:00
GUVWAF 6bdf67c9be Conversion to NodeInfoLite 2023-06-25 15:41:06 +02:00
Ben Meadors bbfd62c47e Merge branch 'master' into neighborinfo 2023-06-21 21:11:06 -05:00
Ben Meadors a07e30544d Merge branch 'master' into neighborinfo 2023-06-19 06:16:42 -05:00
Ben Meadors 9716bd8bec Merge branch 'master' into neighborinfo 2023-06-13 05:44:48 -05:00
Ben Meadors c2168dd450 Merge branch 'master' into neighborinfo 2023-06-09 19:51:22 -05:00
GUVWAF 66c71250b8 Update last_sent_by_id in FloodingRouter 2023-06-08 20:59:09 +02:00
Ben Meadors 5c438ae792 Merge branch 'master' into neighborinfo 2023-06-06 19:29:59 -05:00
GUVWAF cdf44ce7fa Move module init out of repeater clause 2023-06-06 21:07:12 +02:00
GUVWAF d70bd23260 Use float print specifier for SNR 2023-06-06 21:06:19 +02:00
Ben Meadors b42ead4400 Merge branch 'master' into neighborinfo 2023-06-02 06:46:45 -05:00
Ben Meadors b2704a0082 Merge branch 'master' into neighborinfo 2023-06-01 06:02:42 -05:00
Ben Meadors 9b94701699 Merge branch 'master' into neighborinfo 2023-05-31 20:08:50 -05:00
Thomas Göttgens 61661aed50 Broadcast neighbor info
also update trunk
2023-05-31 13:18:43 +02:00
Thomas Göttgens 3a25d6d3b3 Merge branch 'picomputer-s3' of github.com:meshtastic/firmware into picomputer-s3 2023-05-30 14:52:24 +02:00
Ben Meadors fd4e9daa7f Merge branch 'master' into picomputer-s3 2023-05-30 07:36:53 -05:00
Thomas Göttgens b6f7b7fa47 Merge branch 'picomputer-s3' of github.com:meshtastic/firmware into picomputer-s3 2023-05-30 13:07:29 +02:00
Thomas Göttgens a92a960682 Merge branch 'master' into picomputer-s3 2023-05-30 09:55:33 +02:00
Thomas Göttgens 5d2ab65a81 Merge branch 'picomputer-s3' of github.com:meshtastic/firmware into picomputer-s3 2023-05-27 13:08:57 +02:00
Thomas Göttgens f3b7f7251c Add variant an plumbing for #2468 2023-05-27 13:08:27 +02:00
Thomas Göttgens 2f60bbe5f2 Merge branch 'picomputer-s3' of github.com:meshtastic/firmware into picomputer-s3 2023-05-24 01:48:44 +02:00
Thomas Göttgens 0261754269 Add variant an plumbing for #2468 2023-05-24 01:48:01 +02:00
Thomas Göttgens d74cbdaa8b update platform def 2023-05-23 21:55:12 +02:00
Ben Meadors 3a5b79e4c1 Merge branch 'master' into raspi-portduino 2023-05-23 07:51:32 -05:00
Ben Meadors 9bee35118f Merge branch 'master' into raspi-portduino 2023-05-18 06:47:56 -05:00
Thomas Göttgens e6fc2af21f Merge branch 'picomputer-s3' of github.com:meshtastic/firmware into picomputer-s3 2023-05-17 20:28:49 +02:00
Ben Meadors ae41944a89 Merge branch 'master' into picomputer-s3 2023-05-16 10:38:12 -05:00
Thomas Göttgens 62259583e6 Add variant an plumbing for #2468 2023-05-15 17:18:06 +02:00
Thomas Göttgens c5d87fe581 Add variant an plumbing for #2468 2023-05-15 17:17:14 +02:00
Thomas Göttgens 80f029aa32 Merge branch 'master' into raspi-portduino 2023-05-10 17:13:32 +02:00
Thomas Göttgens b75aa79da5 Merge branch 'master' into raspi-portduino 2023-05-08 10:32:36 +02:00
Thomas Göttgens 49febc0d9d Merge branch 'master' into raspi-portduino 2023-04-24 14:58:20 +02:00
Thomas Göttgens 85818b8dfd Merge branch 'master' into raspi-portduino 2023-04-21 16:50:48 +02:00
Thomas Göttgens 7d299b06a7 Merge branch 'master' into raspi-portduino 2023-04-04 15:00:31 +02:00
Thomas Göttgens 14080d4667 Merge branch 'master' into raspi-portduino 2023-04-02 21:24:49 +02:00
Thomas Göttgens 8a806efb95 Merge branch 'master' into raspi-portduino 2023-03-27 15:30:05 +02:00
Thomas Göttgens ef2d0cb830 Merge branch 'master' into raspi-portduino 2023-03-21 09:31:49 +01:00
Ben Meadors 5e779bfb33 Merge branch 'master' into raspi-portduino 2023-03-16 14:43:23 -05:00
Thomas Göttgens 498964e04e Merge branch 'master' into raspi-portduino 2023-03-04 17:24:37 +01:00
Thomas Göttgens 7d0bea267a Merge branch 'master' into raspi-portduino 2023-02-22 10:08:20 +01:00
Thomas Göttgens ed1aa9ddb0 Merge branch 'master' into raspi-portduino 2023-02-17 12:34:00 +01:00
Thomas Göttgens 97a0b164be Merge branch 'master' into raspi-portduino 2023-02-10 00:21:47 +01:00
Ben Meadors 82706a961f Merge branch 'master' into raspi-portduino 2023-02-08 07:40:36 -06:00
Thomas Göttgens 06a1b079da even more cleanup-ing and revert-ing 2023-02-02 11:47:47 +01:00
Thomas Göttgens 56afed84df revert some more 2023-02-02 11:35:30 +01:00
Thomas Göttgens 945fd7a05c revert readprops change 2023-02-02 11:32:00 +01:00
Thomas Göttgens e9a55fc296 revert them trunk shite 2023-02-02 11:29:55 +01:00
Thomas Göttgens 472c43aace Merge remote-tracking branch 'remotes/origin/master' into raspi-portduino 2023-02-02 10:49:45 +01:00
Thomas Göttgens 8b5937892b Merge pull request #2100 from meshtastic/develop
Update Raspi branch
2023-01-04 21:11:47 +01:00
Thomas Göttgens 8c20fe5ec4 Start working on RF95 attached to Raspberry Pi 2022-12-30 21:44:51 +01:00
350 changed files with 12866 additions and 3667 deletions
+4
View File
@@ -37,7 +37,9 @@ body:
- T-Lora v1 - T-Lora v1
- T-Lora v1.3 - T-Lora v1.3
- T-Lora v2 1.6 - T-Lora v2 1.6
- T-Deck
- T-Echo - T-Echo
- T-Watch
- Rak4631 - Rak4631
- Rak11200 - Rak11200
- Rak11310 - Rak11310
@@ -45,6 +47,8 @@ body:
- Heltec v2 - Heltec v2
- Heltec v2.1 - Heltec v2.1
- Heltec V3 - Heltec V3
- Heltec Wireless Paper
- Heltec Wireless Tracker
- Raspberry Pi Pico (W) - Raspberry Pi Pico (W)
- Relay v1 - Relay v1
- Relay v2 - Relay v2
+13
View File
@@ -16,6 +16,19 @@ runs:
run: | run: |
sudo apt-get install -y cppcheck sudo apt-get install -y cppcheck
- name: Install libbluetooth
shell: bash
run: |
sudo apt-get install -y libbluetooth-dev
- name: Install libgpiod
shell: bash
run: |
sudo apt-get install -y libgpiod-dev
- name: Install libyaml-cpp
shell: bash
run: |
sudo apt-get install -y libyaml-cpp-dev
- name: Setup Python - name: Setup Python
uses: actions/setup-python@v4 uses: actions/setup-python@v4
with: with:
+1 -1
View File
@@ -7,7 +7,7 @@
is appreciated." This will allow other devs to potentially save you time by not accidentially duplicating work etc... is appreciated." This will allow other devs to potentially save you time by not accidentially duplicating work etc...
- Please do not check in files that don't have real changes - Please do not check in files that don't have real changes
- Please do not reformat lines that you didn't have to change the code on - Please do not reformat lines that you didn't have to change the code on
- We recommend using the [Visual Studio Code](https://platformio.org/install/ide?install=vscode) editor along with the ['Trunk Check' extension](https://marketplace.visualstudio.com/items?itemName=trunk.io) (WSL2 is required on windows), - We recommend using the [Visual Studio Code](https://platformio.org/install/ide?install=vscode) editor along with the ['Trunk Check' extension](https://marketplace.visualstudio.com/items?itemName=trunk.io) (In beta for windows, WSL2 for the linux version),
because it automatically follows our indentation rules and its auto reformatting will not cause spurious changes to lines. because it automatically follows our indentation rules and its auto reformatting will not cause spurious changes to lines.
- If your PR fixes a bug, mention "fixes #bugnum" somewhere in your pull request description. - If your PR fixes a bug, mention "fixes #bugnum" somewhere in your pull request description.
- If your other co-developers have comments on your PR please tweak as needed. - If your other co-developers have comments on your PR please tweak as needed.
+8 -8
View File
@@ -17,11 +17,11 @@ jobs:
uses: ./.github/actions/setup-base uses: ./.github/actions/setup-base
- name: Pull web ui - name: Pull web ui
uses: dsaltares/fetch-gh-release-asset@master uses: dsaltares/fetch-gh-release-asset@a40c8b4a0471f9ab81bdf73a010f74cc51476ad4
with: with:
repo: "meshtastic/web" repo: meshtastic/web
file: "build.tar" file: build.tar
target: "build.tar" target: build.tar
token: ${{ secrets.GITHUB_TOKEN }} token: ${{ secrets.GITHUB_TOKEN }}
- name: Unpack web ui - name: Unpack web ui
@@ -40,11 +40,11 @@ jobs:
run: bin/build-esp32.sh ${{ inputs.board }} run: bin/build-esp32.sh ${{ inputs.board }}
- name: Pull OTA Firmware - name: Pull OTA Firmware
uses: dsaltares/fetch-gh-release-asset@master uses: dsaltares/fetch-gh-release-asset@a40c8b4a0471f9ab81bdf73a010f74cc51476ad4
with: with:
repo: "meshtastic/firmware-ota" repo: meshtastic/firmware-ota
file: "firmware.bin" file: firmware.bin
target: "release/bleota.bin" target: release/bleota.bin
token: ${{ secrets.GITHUB_TOKEN }} token: ${{ secrets.GITHUB_TOKEN }}
- name: Get release version string - name: Get release version string
+8 -8
View File
@@ -17,11 +17,11 @@ jobs:
uses: ./.github/actions/setup-base uses: ./.github/actions/setup-base
- name: Pull web ui - name: Pull web ui
uses: dsaltares/fetch-gh-release-asset@master uses: dsaltares/fetch-gh-release-asset@a40c8b4a0471f9ab81bdf73a010f74cc51476ad4
with: with:
repo: "meshtastic/web" repo: meshtastic/web
file: "build.tar" file: build.tar
target: "build.tar" target: build.tar
token: ${{ secrets.GITHUB_TOKEN }} token: ${{ secrets.GITHUB_TOKEN }}
- name: Unpack web ui - name: Unpack web ui
@@ -38,11 +38,11 @@ jobs:
run: bin/build-esp32.sh ${{ inputs.board }} run: bin/build-esp32.sh ${{ inputs.board }}
- name: Pull OTA Firmware - name: Pull OTA Firmware
uses: dsaltares/fetch-gh-release-asset@master uses: dsaltares/fetch-gh-release-asset@a40c8b4a0471f9ab81bdf73a010f74cc51476ad4
with: with:
repo: "meshtastic/firmware-ota" repo: meshtastic/firmware-ota
file: "firmware-s3.bin" file: firmware-s3.bin
target: "release/bleota-s3.bin" target: release/bleota-s3.bin
token: ${{ secrets.GITHUB_TOKEN }} token: ${{ secrets.GITHUB_TOKEN }}
- name: Get release version string - name: Get release version string
+45
View File
@@ -0,0 +1,45 @@
name: Build Raspbian
on: workflow_call
permissions:
contents: write
packages: write
jobs:
build-raspbian:
runs-on: [self-hosted, linux, ARM64]
steps:
- name: Checkout code
uses: actions/checkout@v3
with:
submodules: recursive
ref: ${{github.event.pull_request.head.ref}}
repository: ${{github.event.pull_request.head.repo.full_name}}
- name: Upgrade python tools
shell: bash
run: |
python -m pip install --upgrade pip
pip install -U platformio adafruit-nrfutil
pip install -U meshtastic --pre
- name: Upgrade platformio
shell: bash
run: |
pio upgrade
- name: Build Raspbian
run: bin/build-native.sh
- name: Get release version string
run: echo "version=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
id: version
- name: Store binaries as an artifact
uses: actions/upload-artifact@v3
with:
name: firmware-raspbian-${{ steps.version.outputs.version }}.zip
path: |
release/meshtasticd_linux_aarch64
bin/config-dist.yaml
+62 -7
View File
@@ -1,4 +1,7 @@
name: CI name: CI
#concurrency:
# group: ${{ github.ref }}
# cancel-in-progress: ${{ github.ref != 'refs/heads/master' }}
on: on:
# # Triggers the workflow on push but only for the master branch # # Triggers the workflow on push but only for the master branch
push: push:
@@ -33,6 +36,8 @@ jobs:
- board: m5stack-coreink - board: m5stack-coreink
- board: tbeam-s3-core - board: tbeam-s3-core
- board: tlora-t3s3-v1 - board: tlora-t3s3-v1
- board: t-watch-s3
- board: t-deck
#- board: rak11310 #- board: rak11310
runs-on: ubuntu-latest runs-on: ubuntu-latest
@@ -44,7 +49,7 @@ jobs:
- name: Trunk Check - name: Trunk Check
if: ${{ github.event_name != 'workflow_dispatch' }} if: ${{ github.event_name != 'workflow_dispatch' }}
uses: trunk-io/trunk-action@v1 uses: trunk-io/trunk-action@782e83f803ca6e369f035d64c6ba2768174ba61b
- name: Check ${{ matrix.board }} - name: Check ${{ matrix.board }}
run: bin/check-all.sh ${{ matrix.board }} run: bin/check-all.sh ${{ matrix.board }}
@@ -59,8 +64,10 @@ jobs:
- board: tlora-v1 - board: tlora-v1
- board: tlora_v1_3 - board: tlora_v1_3
- board: tlora-v2-1-1_6 - board: tlora-v2-1-1_6
- board: tlora-v2-1-1_6-tcxo
- board: tlora-v2-1-1_8 - board: tlora-v2-1-1_8
- board: tbeam - board: tbeam
- board: heltec-ht62-esp32c3-sx1262
- board: heltec-v1 - board: heltec-v1
- board: heltec-v2_0 - board: heltec-v2_0
- board: heltec-v2_1 - board: heltec-v2_1
@@ -73,6 +80,7 @@ jobs:
- board: m5stack-core - board: m5stack-core
- board: m5stack-coreink - board: m5stack-coreink
- board: nano-g1-explorer - board: nano-g1-explorer
- board: chatter2
uses: ./.github/workflows/build_esp32.yml uses: ./.github/workflows/build_esp32.yml
with: with:
board: ${{ matrix.board }} board: ${{ matrix.board }}
@@ -85,8 +93,12 @@ jobs:
- board: heltec-v3 - board: heltec-v3
- board: heltec-wsl-v3 - board: heltec-wsl-v3
- board: heltec-wireless-tracker - board: heltec-wireless-tracker
- board: heltec-wireless-paper
- board: tbeam-s3-core - board: tbeam-s3-core
- board: tlora-t3s3-v1 - board: tlora-t3s3-v1
- board: t-watch-s3
- board: t-deck
- board: picomputer-s3
uses: ./.github/workflows/build_esp32_s3.yml uses: ./.github/workflows/build_esp32_s3.yml
with: with:
board: ${{ matrix.board }} board: ${{ matrix.board }}
@@ -94,7 +106,6 @@ jobs:
build-nrf52: build-nrf52:
strategy: strategy:
fail-fast: false fail-fast: false
max-parallel: 2
matrix: matrix:
include: include:
- board: rak4631 - board: rak4631
@@ -103,6 +114,7 @@ jobs:
- board: t-echo - board: t-echo
- board: pca10059_diy_eink - board: pca10059_diy_eink
- board: feather_diy - board: feather_diy
- board: nano-g2-ultra
uses: ./.github/workflows/build_nrf52.yml uses: ./.github/workflows/build_nrf52.yml
with: with:
board: ${{ matrix.board }} board: ${{ matrix.board }}
@@ -110,15 +122,25 @@ jobs:
build-rpi2040: build-rpi2040:
strategy: strategy:
fail-fast: false fail-fast: false
max-parallel: 2
matrix: matrix:
include: include:
- board: pico - board: pico
- board: picow
- board: rak11310 - board: rak11310
- board: senselora_rp2040
uses: ./.github/workflows/build_rpi2040.yml uses: ./.github/workflows/build_rpi2040.yml
with: with:
board: ${{ matrix.board }} board: ${{ matrix.board }}
build-raspbian:
strategy:
fail-fast: false
max-parallel: 1
uses: ./.github/workflows/build_raspbian.yml
package-raspbian:
uses: ./.github/workflows/package_raspbian.yml
build-native: build-native:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
@@ -192,9 +214,20 @@ jobs:
repository: ${{github.event.pull_request.head.repo.full_name}} repository: ${{github.event.pull_request.head.repo.full_name}}
gather-artifacts: gather-artifacts:
permissions:
contents: write
pull-requests: write
runs-on: ubuntu-latest runs-on: ubuntu-latest
needs: needs:
[build-esp32, build-esp32-s3, build-nrf52, build-native, build-rpi2040] [
build-esp32,
build-esp32-s3,
build-nrf52,
build-raspbian,
build-native,
build-rpi2040,
package-raspbian,
]
steps: steps:
- name: Checkout code - name: Checkout code
uses: actions/checkout@v3 uses: actions/checkout@v3
@@ -206,12 +239,15 @@ jobs:
with: with:
path: ./ path: ./
- name: Display structure of downloaded files
run: ls -R
- name: Get release version string - name: Get release version string
run: echo "version=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT run: echo "version=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
id: version id: version
- name: Move files up - name: Move files up
run: mv -b -t ./ ./*tbeam-2*/littlefs*.bin ./*tbeam-2*/bleota.bin ./*tbeam-s3*/bleota-s3.bin ./**/firmware*.bin ./*t-echo*/Meshtastic_nRF52_factory_erase.uf2 ./**/firmware-*.uf2 ./**/firmware-*-ota.zip ./**/*.elf ./*native*/*device-*.sh ./*native*/*device-*.bat run: mv -b -t ./ ./*tbeam-2*/littlefs*.bin ./*tbeam-2*/bleota.bin ./*tbeam-s3*/bleota-s3.bin ./**/firmware*.bin ./*t-echo*/Meshtastic_nRF52_factory_erase_v2.uf2 ./**/firmware-*.uf2 ./**/firmware-*-ota.zip ./**/*.elf ./*native*/*device-*.sh ./*native*/*device-*.bat ./firmware-raspbian-*/release/meshtasticd_linux_aarch64 ./firmware-raspbian-*/bin/config-dist.yaml
- name: Repackage in single firmware zip - name: Repackage in single firmware zip
uses: actions/upload-artifact@v3 uses: actions/upload-artifact@v3
@@ -223,6 +259,8 @@ jobs:
./firmware-*-ota.zip ./firmware-*-ota.zip
./device-*.sh ./device-*.sh
./device-*.bat ./device-*.bat
./meshtasticd_linux_arm64
./config-dist.yaml
retention-days: 90 retention-days: 90
- uses: actions/download-artifact@v3 - uses: actions/download-artifact@v3
@@ -250,15 +288,15 @@ jobs:
retention-days: 30 retention-days: 30
- name: Create request artifacts - name: Create request artifacts
continue-on-error: true # FIXME: Why are we getting 502, but things still work?
if: ${{ github.event_name == 'pull_request_target' || github.event_name == 'pull_request' }} if: ${{ github.event_name == 'pull_request_target' || github.event_name == 'pull_request' }}
uses: gavv/pull-request-artifacts@v1.1.0 uses: gavv/pull-request-artifacts@v2.1.0
with: with:
commit: ${{ (github.event.pull_request_target || github.event.pull_request).head.sha }} commit: ${{ (github.event.pull_request_target || github.event.pull_request).head.sha }}
repo-token: ${{ secrets.GITHUB_TOKEN }} repo-token: ${{ secrets.GITHUB_TOKEN }}
artifacts-token: ${{ secrets.ARTIFACTS_TOKEN }} artifacts-token: ${{ secrets.ARTIFACTS_TOKEN }}
artifacts-repo: meshtastic/artifacts artifacts-repo: meshtastic/artifacts
artifacts-branch: device artifacts-branch: device
artifacts-dir: pr
artifacts: ./firmware-${{ steps.version.outputs.version }}.zip artifacts: ./firmware-${{ steps.version.outputs.version }}.zip
release-artifacts: release-artifacts:
@@ -283,6 +321,13 @@ jobs:
name: firmware-${{ steps.version.outputs.version }} name: firmware-${{ steps.version.outputs.version }}
path: ./output path: ./output
- uses: actions/download-artifact@v3
with:
name: artifact-deb
- name: Display structure of downloaded files
run: ls -R
- name: Device scripts permissions - name: Device scripts permissions
run: | run: |
chmod +x ./output/device-install.sh chmod +x ./output/device-install.sh
@@ -336,6 +381,16 @@ jobs:
asset_name: debug-elfs-${{ steps.version.outputs.version }}.zip asset_name: debug-elfs-${{ steps.version.outputs.version }}.zip
asset_content_type: application/zip asset_content_type: application/zip
- name: Add raspbian .deb
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ github.token }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: ./meshtasticd_${{ steps.version.outputs.version }}_arm64.deb
asset_name: meshtasticd_${{ steps.version.outputs.version }}_arm64.deb
asset_content_type: application/vnd.debian.binary-package
- name: Bump version.properties - name: Bump version.properties
run: >- run: >-
bin/bump_version.py bin/bump_version.py
+1 -1
View File
@@ -14,6 +14,6 @@ jobs:
uses: actions/checkout@v3 uses: actions/checkout@v3
- name: Trunk Check - name: Trunk Check
uses: trunk-io/trunk-action@v1 uses: trunk-io/trunk-action@782e83f803ca6e369f035d64c6ba2768174ba61b
with: with:
trunk-token: ${{ secrets.TRUNK_TOKEN }} trunk-token: ${{ secrets.TRUNK_TOKEN }}
+62
View File
@@ -0,0 +1,62 @@
name: Package Raspbian
on:
workflow_call:
workflow_dispatch:
permissions:
contents: write
packages: write
jobs:
build-raspbian:
uses: ./.github/workflows/build_raspbian.yml
package-raspbian:
runs-on: ubuntu-latest
needs: build-raspbian
steps:
- name: Checkout code
uses: actions/checkout@v3
with:
submodules: recursive
ref: ${{github.event.pull_request.head.ref}}
repository: ${{github.event.pull_request.head.repo.full_name}}
- name: Get release version string
run: echo "version=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
id: version
- name: Download artifacts
uses: actions/download-artifact@v3
with:
name: firmware-raspbian-${{ steps.version.outputs.version }}.zip
- name: Display structure of downloaded files
run: ls -R
- name: build .debpkg
run: |
mkdir -p .debpkg/usr/sbin
mkdir -p .debpkg/etc/meshtasticd
mkdir -p .debpkg/usr/lib/systemd/system/
cp release/meshtasticd_linux_aarch64 .debpkg/usr/sbin/meshtasticd
cp bin/config-dist.yaml .debpkg/etc/meshtasticd/config.yaml
chmod +x .debpkg/usr/sbin/meshtasticd
cp bin/meshtasticd.service .debpkg/usr/lib/systemd/system/meshtasticd.service
- uses: jiro4989/build-deb-action@v3
with:
package: meshtasticd
package_root: .debpkg
maintainer: Jonathan Bennett
version: ${{ steps.version.outputs.version }} # refs/tags/v*.*.*
arch: arm64
depends: libyaml-cpp0.7
desc: Native Linux Meshtastic binary.
- uses: actions/upload-artifact@v3
with:
name: artifact-deb
path: |
./*.deb
+22
View File
@@ -0,0 +1,22 @@
name: Pull Request
on: [pull_request]
concurrency:
group: ${{ github.head_ref || github.run_id }}
cancel-in-progress: true
permissions: read-all
jobs:
trunk_check:
name: Trunk Check Runner
runs-on: ubuntu-latest
permissions:
checks: write # For trunk to post annotations
contents: read # For repo checkout
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Trunk Check
uses: trunk-io/trunk-action@v1
+1 -1
View File
@@ -2,7 +2,7 @@
*logs *logs
*actions *actions
*notifications *notifications
*tools
plugins plugins
user_trunk.yaml user_trunk.yaml
user.yaml user.yaml
shims
+3
View File
@@ -1,7 +1,10 @@
enable=all enable=all
source-path=SCRIPTDIR source-path=SCRIPTDIR
disable=SC2154 disable=SC2154
disable=SC2248
disable=SC2250
# If you're having issues with shellcheck following source, disable the errors via: # If you're having issues with shellcheck following source, disable the errors via:
# disable=SC1090 # disable=SC1090
# disable=SC1091 # disable=SC1091
#
+1 -1
View File
@@ -3,7 +3,7 @@ rules:
required: only-when-needed required: only-when-needed
extra-allowed: ["{|}"] extra-allowed: ["{|}"]
empty-values: empty-values:
forbid-in-block-mappings: true forbid-in-block-mappings: false
forbid-in-flow-mappings: true forbid-in-flow-mappings: true
key-duplicates: {} key-duplicates: {}
octal-values: octal-values:
+22 -27
View File
@@ -1,48 +1,43 @@
version: 0.1 version: 0.1
cli: cli:
version: 1.9.1 version: 1.17.2
plugins: plugins:
sources: sources:
- id: trunk - id: trunk
ref: v0.0.17 ref: v1.3.0
uri: https://github.com/trunk-io/plugins uri: https://github.com/trunk-io/plugins
lint: lint:
enabled: enabled:
- taplo@0.7.0 - bandit@1.7.5
- ruff@0.0.265 - checkov@3.1.9
- yamllint@1.31.0 - terrascan@1.18.5
- trivy@0.47.0
#- trufflehog@3.63.2-rc0
- taplo@0.8.1
- ruff@0.1.6
- isort@5.12.0 - isort@5.12.0
- markdownlint@0.34.0 - markdownlint@0.37.0
- oxipng@8.0.0 - oxipng@9.0.0
- svgo@3.0.2 - svgo@3.0.5
- actionlint@1.6.24 - actionlint@1.6.26
- flake8@6.0.0 - flake8@6.1.0
- hadolint@2.12.0 - hadolint@2.12.0
- shfmt@3.5.0 - shfmt@3.6.0
- shellcheck@0.9.0 - shellcheck@0.9.0
- black@23.3.0 - black@23.9.1
- git-diff-check - git-diff-check
- gitleaks@8.16.3 - gitleaks@8.18.1
- clang-format@14.0.0 - clang-format@16.0.3
- prettier@2.8.8 - prettier@3.1.0
disabled:
- taplo@0.7.0
- shellcheck@0.9.0
- shfmt@3.5.0
- oxipng@8.0.0
- actionlint@1.6.22
- markdownlint@0.34.0
- hadolint@2.12.0
- svgo@3.0.2
runtimes: runtimes:
enabled: enabled:
- python@3.10.8 - python@3.10.8
- go@1.19.5 - go@1.21.0
- node@18.12.1 - node@18.12.1
actions: actions:
disabled: disabled:
- trunk-announce - trunk-announce
- trunk-check-pre-push
- trunk-fmt-pre-commit
enabled: enabled:
- trunk-fmt-pre-commit
- trunk-check-pre-push
- trunk-upgrade-available - trunk-upgrade-available
+1 -1
View File
@@ -6,4 +6,4 @@
"platformio.platformio-ide", "platformio.platformio-ide",
"trunk.io" "trunk.io"
], ],
} }
+2 -1
View File
@@ -1,4 +1,5 @@
{ {
"editor.formatOnSave": true, "editor.formatOnSave": true,
"editor.defaultFormatter": "trunk.io" "editor.defaultFormatter": "trunk.io",
"trunk.enableWindows": true
} }
+5 -5
View File
@@ -12,7 +12,7 @@ SHELL ["/bin/bash", "-o", "pipefail", "-c"]
# Install build deps # Install build deps
USER root USER root
RUN apt-get update && \ RUN apt-get update && \
apt-get -y install wget python3 g++ zip python3-venv git vim ca-certificates apt-get -y install wget python3 g++ zip python3-venv git vim ca-certificates libgpiod-dev libyaml-cpp-dev libbluetooth-dev
# create a non-priveleged user & group # create a non-priveleged user & group
RUN groupadd -g 1000 mesh && useradd -ml -u 1000 -g 1000 mesh RUN groupadd -g 1000 mesh && useradd -ml -u 1000 -g 1000 mesh
@@ -27,15 +27,15 @@ RUN wget https://raw.githubusercontent.com/platformio/platformio-core-installer/
source ~/.platformio/penv/bin/activate && \ source ~/.platformio/penv/bin/activate && \
./bin/build-native.sh ./bin/build-native.sh
FROM frolvlad/alpine-glibc FROM frolvlad/alpine-glibc:glibc-2.31
RUN apk --update add --no-cache g++ shadow && \ RUN apk --update add --no-cache g++ shadow && \
groupadd -g 1000 mesh && useradd -ml -u 1000 -g 1000 mesh groupadd -g 1000 mesh && useradd -ml -u 1000 -g 1000 mesh
COPY --from=builder /tmp/firmware/release/meshtasticd_linux_amd64 /home/mesh/ COPY --from=builder /tmp/firmware/release/meshtasticd_linux_x86_64 /home/mesh/
USER mesh USER mesh
WORKDIR /home/mesh WORKDIR /home/mesh
CMD sh -cx "./meshtasticd_linux_amd64 --hwid '$RANDOM'" CMD sh -cx "./meshtasticd_linux_x86_64 --hwid '${HWID:-$RANDOM}'"
HEALTHCHECK NONE HEALTHCHECK NONE
+2 -2
View File
@@ -10,8 +10,8 @@
This repository contains the device firmware for the Meshtastic project. This repository contains the device firmware for the Meshtastic project.
**[Building Instructions](https://meshtastic.org/docs/development/firmware/build)** - **[Building Instructions](https://meshtastic.org/docs/development/firmware/build)**
**[Flashing Instructions](https://meshtastic.org/docs/getting-started/flashing-firmware/)** - **[Flashing Instructions](https://meshtastic.org/docs/getting-started/flashing-firmware/)**
## Stats ## Stats
+7 -3
View File
@@ -1,7 +1,7 @@
; Common settings for ESP targes, mixin with extends = esp32_base ; Common settings for ESP targes, mixin with extends = esp32_base
[esp32_base] [esp32_base]
extends = arduino_base extends = arduino_base
platform = platformio/espressif32@^6.3.2 platform = platformio/espressif32@6.3.2 # This is a temporary fix to the S3-based devices bluetooth issues until we can determine what within ESP-IDF changed and can develop a suitable patch.
build_src_filter = build_src_filter =
${arduino_base.build_src_filter} -<platform/nrf52/> -<platform/stm32wl> -<platform/rp2040> -<mesh/eth/> ${arduino_base.build_src_filter} -<platform/nrf52/> -<platform/stm32wl> -<platform/rp2040> -<mesh/eth/>
@@ -30,6 +30,10 @@ build_flags =
-DCONFIG_BT_NIMBLE_MAX_CCCDS=20 -DCONFIG_BT_NIMBLE_MAX_CCCDS=20
-DCONFIG_BT_NIMBLE_HOST_TASK_STACK_SIZE=5120 -DCONFIG_BT_NIMBLE_HOST_TASK_STACK_SIZE=5120
-DESP_OPENSSL_SUPPRESS_LEGACY_WARNING -DESP_OPENSSL_SUPPRESS_LEGACY_WARNING
-DSERIAL_BUFFER_SIZE=4096
-DLIBPAX_ARDUINO
-DLIBPAX_WIFI
-DLIBPAX_BLE
;-DDEBUG_HEAP ;-DDEBUG_HEAP
lib_deps = lib_deps =
@@ -37,8 +41,8 @@ lib_deps =
${networking_base.lib_deps} ${networking_base.lib_deps}
${environmental_base.lib_deps} ${environmental_base.lib_deps}
https://github.com/meshtastic/esp32_https_server.git#23665b3adc080a311dcbb586ed5941b5f94d6ea2 https://github.com/meshtastic/esp32_https_server.git#23665b3adc080a311dcbb586ed5941b5f94d6ea2
h2zero/NimBLE-Arduino@^1.4.0 h2zero/NimBLE-Arduino@^1.4.1
jgromes/RadioLib@^6.1.0 https://github.com/dbSuS/libpax.git#7bcd3fcab75037505be9b122ab2b24cc5176b587
https://github.com/lewisxhe/XPowersLib.git#84b7373faea3118b6c37954d52f98b8a337148d6 https://github.com/lewisxhe/XPowersLib.git#84b7373faea3118b6c37954d52f98b8a337148d6
https://github.com/meshtastic/ESP32_Codec2.git#633326c78ac251c059ab3a8c430fcdf25b41672f https://github.com/meshtastic/ESP32_Codec2.git#633326c78ac251c059ab3a8c430fcdf25b41672f
+5 -4
View File
@@ -1,19 +1,20 @@
[nrf52_base] [nrf52_base]
; Instead of the standard nordicnrf52 platform, we use our fork which has our added variant files ; Instead of the standard nordicnrf52 platform, we use our fork which has our added variant files
platform = platformio/nordicnrf52@^10.0.0 platform = platformio/nordicnrf52@^10.1.0
extends = arduino_base extends = arduino_base
build_type = debug ; I'm debugging with ICE a lot now build_type = debug ; I'm debugging with ICE a lot now
build_flags = build_flags =
${arduino_base.build_flags} -Wno-unused-variable ${arduino_base.build_flags}
-DSERIAL_BUFFER_SIZE=1024
-Wno-unused-variable
-Isrc/platform/nrf52 -Isrc/platform/nrf52
build_src_filter = build_src_filter =
${arduino_base.build_src_filter} -<platform/esp32/> -<platform/stm32wl> -<nimble/> -<mesh/api/> -<mesh/http/> -<modules/esp32> -<platform/rp2040> -<mesh/eth/> ${arduino_base.build_src_filter} -<platform/esp32/> -<platform/stm32wl> -<nimble/> -<mesh/wifi/> -<mesh/api/> -<mesh/http/> -<modules/esp32> -<platform/rp2040> -<mesh/eth/>
lib_deps= lib_deps=
${arduino_base.lib_deps} ${arduino_base.lib_deps}
jgromes/RadioLib@^6.1.0
lib_ignore = lib_ignore =
BluetoothOTA BluetoothOTA
+9 -3
View File
@@ -1,6 +1,6 @@
; The Portduino based sim environment on top of any host OS, all hardware will be simulated ; The Portduino based sim environment on top of any host OS, all hardware will be simulated
[portduino_base] [portduino_base]
platform = https://github.com/meshtastic/platform-native.git#489ff929dca0bb768256ba2de45f95815111490f platform = https://github.com/meshtastic/platform-native.git#a28dd5a9ccd5c48a9bede46037855ff83915d74b
framework = arduino framework = arduino
build_src_filter = build_src_filter =
@@ -10,6 +10,7 @@ build_src_filter =
-<platform/nrf52/> -<platform/nrf52/>
-<platform/stm32wl/> -<platform/stm32wl/>
-<platform/rp2040> -<platform/rp2040>
-<mesh/wifi/>
-<mesh/http/> -<mesh/http/>
-<mesh/eth/> -<mesh/eth/>
-<modules/esp32> -<modules/esp32>
@@ -22,9 +23,14 @@ lib_deps =
${env.lib_deps} ${env.lib_deps}
${networking_base.lib_deps} ${networking_base.lib_deps}
rweather/Crypto@^0.4.0 rweather/Crypto@^0.4.0
jgromes/RadioLib@6.1.0 lovyan03/LovyanGFX@^1.1.12
build_flags = build_flags =
${arduino_base.build_flags} ${arduino_base.build_flags}
-fPIC -fPIC
-Isrc/platform/portduino -Isrc/platform/portduino
-DRADIOLIB_EEPROM_UNSUPPORTED
-DPORTDUINO_LINUX_HARDWARE
-lbluetooth
-lgpiod
-lyaml-cpp
+4 -5
View File
@@ -1,8 +1,8 @@
; Common settings for rp2040 Processor based targets ; Common settings for rp2040 Processor based targets
[rp2040_base] [rp2040_base]
platform = https://github.com/maxgerhardt/platform-raspberrypi.git#0c33219f53faa035e188925ea1324f472e8b93d2 platform = https://github.com/maxgerhardt/platform-raspberrypi.git#612de5399d68b359053f1307ed223d400aea975c
extends = arduino_base extends = arduino_base
platform_packages = framework-arduinopico@https://github.com/earlephilhower/arduino-pico.git#3.2.2 platform_packages = framework-arduinopico@https://github.com/earlephilhower/arduino-pico.git#3.6.2
board_build.core = earlephilhower board_build.core = earlephilhower
board_build.filesystem_size = 0.5m board_build.filesystem_size = 0.5m
@@ -12,7 +12,7 @@ build_flags =
-D__PLAT_RP2040__ -D__PLAT_RP2040__
# -D _POSIX_THREADS # -D _POSIX_THREADS
build_src_filter = build_src_filter =
${arduino_base.build_src_filter} -<platform/esp32/> -<nimble/> -<mesh/api/> -<mesh/http/> -<modules/esp32> -<platform/nrf52/> -<platform/stm32wl> -<mesh/eth/> ${arduino_base.build_src_filter} -<platform/esp32/> -<nimble/> -<modules/esp32> -<platform/nrf52/> -<platform/stm32wl> -<mesh/eth/> -<mesh/wifi/> -<mesh/http/>
lib_ignore = lib_ignore =
BluetoothOTA BluetoothOTA
@@ -20,5 +20,4 @@ lib_ignore =
lib_deps = lib_deps =
${arduino_base.lib_deps} ${arduino_base.lib_deps}
${environmental_base.lib_deps} ${environmental_base.lib_deps}
jgromes/RadioLib@^6.1.0 rweather/Crypto
https://github.com/kokke/tiny-AES-c.git#f06ac37fc31dfdaca2e0d9bec83f90d5663c319b
+2 -3
View File
@@ -13,17 +13,16 @@ build_flags =
-DVECT_TAB_OFFSET=0x08000000 -DVECT_TAB_OFFSET=0x08000000
build_src_filter = build_src_filter =
${arduino_base.build_src_filter} -<platform/esp32/> -<nimble/> -<mesh/api/> -<mesh/http/> -<modules/esp32> -<mesh/eth/> -<input> -<buzz> -<modules/Telemetry> -<platform/nrf52> -<platform/portduino> -<platform/rp2040> ${arduino_base.build_src_filter} -<platform/esp32/> -<nimble/> -<mesh/api/> -<mesh/wifi/> -<mesh/http/> -<modules/esp32> -<mesh/eth/> -<input> -<buzz> -<modules/Telemetry> -<platform/nrf52> -<platform/portduino> -<platform/rp2040>
board_upload.offset_address = 0x08000000 board_upload.offset_address = 0x08000000
upload_protocol = stlink upload_protocol = stlink
lib_deps = lib_deps =
${env.lib_deps} ${env.lib_deps}
jgromes/RadioLib@^6.1.0
https://github.com/kokke/tiny-AES-c.git#f06ac37fc31dfdaca2e0d9bec83f90d5663c319b https://github.com/kokke/tiny-AES-c.git#f06ac37fc31dfdaca2e0d9bec83f90d5663c319b
https://github.com/littlefs-project/littlefs.git#v2.5.1 https://github.com/littlefs-project/littlefs.git#v2.5.1
https://github.com/stm32duino/STM32FreeRTOS.git#10.3.1 https://github.com/stm32duino/STM32FreeRTOS.git#10.3.1
lib_ignore = lib_ignore =
https://github.com/mathertel/OneButton#2.1.0 mathertel/OneButton
Binary file not shown.
+4 -7
View File
@@ -2,8 +2,8 @@
set -e set -e
VERSION=`bin/buildinfo.py long` VERSION=$(bin/buildinfo.py long)
SHORT_VERSION=`bin/buildinfo.py short` SHORT_VERSION=$(bin/buildinfo.py short)
OUTDIR=release/ OUTDIR=release/
@@ -13,11 +13,8 @@ mkdir -p $OUTDIR/
rm -r $OUTDIR/* || true rm -r $OUTDIR/* || true
# Important to pull latest version of libs into all device flavors, otherwise some devices might be stale # Important to pull latest version of libs into all device flavors, otherwise some devices might be stale
platformio pkg update platformio pkg update
pio run --environment native pio run --environment native
cp .pio/build/native/program $OUTDIR/meshtasticd_linux_amd64 cp .pio/build/native/program "$OUTDIR/meshtasticd_linux_$(arch)"
cp bin/device-install.* $OUTDIR cp bin/device-install.* $OUTDIR
cp bin/device-update.* $OUTDIR cp bin/device-update.* $OUTDIR
+6 -6
View File
@@ -4,23 +4,23 @@
set -e set -e
VERSION=`bin/buildinfo.py long` VERSION=$(bin/buildinfo.py long)
# The shell vars the build tool expects to find # The shell vars the build tool expects to find
export APP_VERSION=$VERSION export APP_VERSION=$VERSION
if [[ $# -gt 0 ]]; then if [[ $# -gt 0 ]]; then
# can override which environment by passing arg # can override which environment by passing arg
BOARDS="$@" BOARDS="$@"
else else
BOARDS="tlora-v2 tlora-v1 tlora_v1_3 tlora-v2-1-1.6 tbeam heltec-v1 heltec-v2.0 heltec-v2.1 tbeam0.7 meshtastic-diy-v1 rak4631 rak4631_eink rak11200 t-echo pca10059_diy_eink" BOARDS="tlora-v2 tlora-v1 tlora_v1_3 tlora-v2-1-1.6 tbeam heltec-v1 heltec-v2.0 heltec-v2.1 tbeam0.7 meshtastic-diy-v1 rak4631 rak4631_eink rak11200 t-echo pca10059_diy_eink"
fi fi
echo "BOARDS:${BOARDS}" echo "BOARDS:${BOARDS}"
CHECK="" CHECK=""
for BOARD in $BOARDS; do for BOARD in $BOARDS; do
CHECK="${CHECK} -e ${BOARD}" CHECK="${CHECK} -e ${BOARD}"
done done
pio check --flags "-DAPP_VERSION=${APP_VERSION} --suppressions-list=suppressions.txt" $CHECK --skip-packages --pattern="src/" --fail-on-defect=low --fail-on-defect=medium --fail-on-defect=high pio check --flags "-DAPP_VERSION=${APP_VERSION} --suppressions-list=suppressions.txt" $CHECK --skip-packages --pattern="src/" --fail-on-defect=medium --fail-on-defect=high
+119
View File
@@ -0,0 +1,119 @@
### Define your devices here using Broadcom pin numbering
### Uncomment the block that corresponds to your hardware
---
Lora:
# Module: sx1262 # Waveshare SX126X XXXM
# DIO2_AS_RF_SWITCH: true
# CS: 21
# IRQ: 16
# Busy: 20
# Reset: 18
# Module: sx1262 # Waveshare SX1302 LISTEN ONLY AT THIS TIME!
# CS: 7
# IRQ: 17
# Reset: 22
# Module: sx1262 # pinedio
# CS: 0
# IRQ: 10
# Busy: 11
# spidev: spidev0.1
# Module: RF95 # Adafruit RFM9x
# Reset: 25
# CS: 7
# IRQ: 22
# Busy: 23
# Module: RF95 # Elecrow Lora RFM95 IOT https://www.elecrow.com/lora-rfm95-iot-board-for-rpi.html
# Reset: 22
# CS: 7
# IRQ: 25
# Module: sx1280 # SX1280
# CS: 21
# IRQ: 16
# Busy: 20
# Reset: 18
# DIO3_TCXO_VOLTAGE: true # the Waveshare Core1262 and others are known to need this setting
# TXen: x # TX and RX enable pins
# RXen: x
### Set gpio chip to use in /dev/. Defaults to 0.
### Notably the Raspberry Pi 5 puts the GPIO header on gpiochip4
# gpiochip: 4
### Specify the SPI device to use in /dev/. Defaults to spidev0.0
### Some devices, like the pinedio, may require spidev0.1 as a workaround.
# spidev: spidev0.0
### Define GPIO buttons here:
GPIO:
# User: 6
### Define GPS
GPS:
# SerialPath: /dev/ttyS0
### Specify I2C device, or leave blank for none
I2C:
# I2CDevice: /dev/i2c-1
### Set up SPI displays here. Note that I2C displays are generally auto-detected.
Display:
### Waveshare 2.8inch RPi LCD
# Panel: ST7789
# CS: 8
# DC: 22 # Data/Command pin
# Backlight: 18
# Width: 240
# Height: 320
# Reset: 27
# Rotate: true
# Invert: true
### Waveshare 1.44inch LCD HAT
# Panel: ST7735S
# CS: 8 #Chip Select
# DC: 25 # Data/Command pin
# Backlight: 24
# Width: 128
# Height: 128
# Reset: 27
# OffsetX: 0
# OffsetY: 0
### Adafruit PiTFT 2.8 TFT+Touchscreen
# Panel: ILI9341
# CS: 8
# DC: 25
# Backlight: 2
# Width: 320
# Height: 240
Touchscreen:
# Module: STMPE610
# CS: 7
# IRQ: 24
# Module: XPT2046
# CS: 7
# IRQ: 17
### Configure device for direct keyboard input
Input:
# KeyboardDevice: /dev/input/event0
###
Logging:
LogLevel: info # debug, info, warn, error
+1 -1
View File
@@ -32,7 +32,7 @@ IF EXIST %FILENAME% IF x%FILENAME:update=%==x%FILENAME% (
%PYTHON% -m esptool --baud 115200 write_flash 0x00 %FILENAME% %PYTHON% -m esptool --baud 115200 write_flash 0x00 %FILENAME%
@REM Account for S3 board's different OTA partition @REM Account for S3 board's different OTA partition
IF x%FILENAME:s3=%==x%FILENAME% IF x%FILENAME:v3=%==x%FILENAME% ( IF x%FILENAME:s3=%==x%FILENAME% IF x%FILENAME:v3=%==x%FILENAME% IF x%FILENAME:t-deck=%==x%FILENAME% IF x%FILENAME:wireless-paper=%==x%FILENAME% IF x%FILENAME:wireless-tracker=%==x%FILENAME% (
%PYTHON% -m esptool --baud 115200 write_flash 0x260000 bleota.bin %PYTHON% -m esptool --baud 115200 write_flash 0x260000 bleota.bin
) else ( ) else (
%PYTHON% -m esptool --baud 115200 write_flash 0x260000 bleota-s3.bin %PYTHON% -m esptool --baud 115200 write_flash 0x260000 bleota-s3.bin
+1 -1
View File
@@ -50,7 +50,7 @@ if [ -f "${FILENAME}" ] && [ ! -z "${FILENAME##*"update"*}" ]; then
"$PYTHON" -m esptool erase_flash "$PYTHON" -m esptool erase_flash
"$PYTHON" -m esptool write_flash 0x00 ${FILENAME} "$PYTHON" -m esptool write_flash 0x00 ${FILENAME}
# Account for S3 board's different OTA partition # Account for S3 board's different OTA partition
if [ ! -z "${FILENAME##*"s3"*}" ] && [ ! -z "${FILENAME##*"-v3"*}" ]; then if [ ! -z "${FILENAME##*"s3"*}" ] && [ ! -z "${FILENAME##*"-v3"*}" ] && [ ! -z "${FILENAME##*"t-deck"*}" ] && [ ! -z "${FILENAME##*"wireless-paper"*}" ] && [ ! -z "${FILENAME##*"wireless-tracker"*}" ]; then
"$PYTHON" -m esptool write_flash 0x260000 bleota.bin "$PYTHON" -m esptool write_flash 0x260000 bleota.bin
else else
"$PYTHON" -m esptool write_flash 0x260000 bleota-s3.bin "$PYTHON" -m esptool write_flash 0x260000 bleota-s3.bin
+103 -42
View File
@@ -11,19 +11,22 @@ Meshtastic notes:
* version that's checked into meshtastic repo is based on: https://github.com/me21/EspArduinoExceptionDecoder * version that's checked into meshtastic repo is based on: https://github.com/me21/EspArduinoExceptionDecoder
which adds in ESP32 Backtrace decoding. which adds in ESP32 Backtrace decoding.
* this also updates the defaults to use ESP32, instead of ESP8266 and defaults to the built firmware.bin * this also updates the defaults to use ESP32, instead of ESP8266 and defaults to the built firmware.bin
* also updated the toolchain name, which will be set according to the platform
To use, copy the "Backtrace: 0x...." line to a file, e.g., backtrace.txt, then run: To use, copy the "Backtrace: 0x...." line to a file, e.g., backtrace.txt, then run:
$ bin/exception_decoder.py backtrace.txt $ bin/exception_decoder.py backtrace.txt
For a platform other than ESP32, use the -p option, e.g.:
$ bin/exception_decoder.py -p ESP32S3 backtrace.txt
To specify a specific .elf file, use the -e option, e.g.:
$ bin/exception_decoder.py -e firmware.elf backtrace.txt
""" """
import argparse import argparse
import os
import re import re
import subprocess import subprocess
from collections import namedtuple
import sys import sys
from collections import namedtuple
import os
EXCEPTIONS = [ EXCEPTIONS = [
"Illegal instruction", "Illegal instruction",
@@ -55,24 +58,39 @@ EXCEPTIONS = [
"LoadStorePrivilege: A load or store referenced a virtual address at a ring level less than CRING", "LoadStorePrivilege: A load or store referenced a virtual address at a ring level less than CRING",
"reserved", "reserved",
"LoadProhibited: A load referenced a page mapped with an attribute that does not permit loads", "LoadProhibited: A load referenced a page mapped with an attribute that does not permit loads",
"StoreProhibited: A store referenced a page mapped with an attribute that does not permit stores" "StoreProhibited: A store referenced a page mapped with an attribute that does not permit stores",
] ]
PLATFORMS = { PLATFORMS = {
"ESP8266": "lx106", "ESP8266": "xtensa-lx106",
"ESP32": "esp32" "ESP32": "xtensa-esp32",
"ESP32S3": "xtensa-esp32s3",
"ESP32C3": "riscv32-esp",
}
TOOLS = {
"ESP8266": "xtensa",
"ESP32": "xtensa-esp32",
"ESP32S3": "xtensa-esp32s3",
"ESP32C3": "riscv32-esp",
} }
BACKTRACE_REGEX = re.compile(r"(?:\s+(0x40[0-2](?:\d|[a-f]|[A-F]){5}):0x(?:\d|[a-f]|[A-F]){8})\b") BACKTRACE_REGEX = re.compile(
r"(?:\s+(0x40[0-2](?:\d|[a-f]|[A-F]){5}):0x(?:\d|[a-f]|[A-F]){8})\b"
)
EXCEPTION_REGEX = re.compile("^Exception \\((?P<exc>[0-9]*)\\):$") EXCEPTION_REGEX = re.compile("^Exception \\((?P<exc>[0-9]*)\\):$")
COUNTER_REGEX = re.compile('^epc1=(?P<epc1>0x[0-9a-f]+) epc2=(?P<epc2>0x[0-9a-f]+) epc3=(?P<epc3>0x[0-9a-f]+) ' COUNTER_REGEX = re.compile(
'excvaddr=(?P<excvaddr>0x[0-9a-f]+) depc=(?P<depc>0x[0-9a-f]+)$') "^epc1=(?P<epc1>0x[0-9a-f]+) epc2=(?P<epc2>0x[0-9a-f]+) epc3=(?P<epc3>0x[0-9a-f]+) "
"excvaddr=(?P<excvaddr>0x[0-9a-f]+) depc=(?P<depc>0x[0-9a-f]+)$"
)
CTX_REGEX = re.compile("^ctx: (?P<ctx>.+)$") CTX_REGEX = re.compile("^ctx: (?P<ctx>.+)$")
POINTER_REGEX = re.compile('^sp: (?P<sp>[0-9a-f]+) end: (?P<end>[0-9a-f]+) offset: (?P<offset>[0-9a-f]+)$') POINTER_REGEX = re.compile(
STACK_BEGIN = '>>>stack>>>' "^sp: (?P<sp>[0-9a-f]+) end: (?P<end>[0-9a-f]+) offset: (?P<offset>[0-9a-f]+)$"
STACK_END = '<<<stack<<<' )
STACK_BEGIN = ">>>stack>>>"
STACK_END = "<<<stack<<<"
STACK_REGEX = re.compile( STACK_REGEX = re.compile(
'^(?P<off>[0-9a-f]+):\W+(?P<c1>[0-9a-f]+) (?P<c2>[0-9a-f]+) (?P<c3>[0-9a-f]+) (?P<c4>[0-9a-f]+)(\W.*)?$') "^(?P<off>[0-9a-f]+):\W+(?P<c1>[0-9a-f]+) (?P<c2>[0-9a-f]+) (?P<c3>[0-9a-f]+) (?P<c4>[0-9a-f]+)(\W.*)?$"
)
StackLine = namedtuple("StackLine", ["offset", "content"]) StackLine = namedtuple("StackLine", ["offset", "content"])
@@ -96,15 +114,18 @@ class ExceptionDataParser(object):
self.stack = [] self.stack = []
def _parse_backtrace(self, line): def _parse_backtrace(self, line):
if line.startswith('Backtrace:'): if line.startswith("Backtrace:"):
self.stack = [StackLine(offset=0, content=(addr,)) for addr in BACKTRACE_REGEX.findall(line)] self.stack = [
StackLine(offset=0, content=(addr,))
for addr in BACKTRACE_REGEX.findall(line)
]
return None return None
return self._parse_backtrace return self._parse_backtrace
def _parse_exception(self, line): def _parse_exception(self, line):
match = EXCEPTION_REGEX.match(line) match = EXCEPTION_REGEX.match(line)
if match is not None: if match is not None:
self.exception = int(match.group('exc')) self.exception = int(match.group("exc"))
return self._parse_counters return self._parse_counters
return self._parse_exception return self._parse_exception
@@ -144,14 +165,22 @@ class ExceptionDataParser(object):
if line != STACK_END: if line != STACK_END:
match = STACK_REGEX.match(line) match = STACK_REGEX.match(line)
if match is not None: if match is not None:
self.stack.append(StackLine(offset=match.group("off"), self.stack.append(
content=(match.group("c1"), match.group("c2"), match.group("c3"), StackLine(
match.group("c4")))) offset=match.group("off"),
content=(
match.group("c1"),
match.group("c2"),
match.group("c3"),
match.group("c4"),
),
)
)
return self._parse_stack_line return self._parse_stack_line
return None return None
def parse_file(self, file, platform, stack_only=False): def parse_file(self, file, platform, stack_only=False):
if platform == 'ESP32': if platform != "ESP8266":
func = self._parse_backtrace func = self._parse_backtrace
else: else:
func = self._parse_exception func = self._parse_exception
@@ -175,7 +204,9 @@ class AddressResolver(object):
self._address_map = {} self._address_map = {}
def _lookup(self, addresses): def _lookup(self, addresses):
cmd = [self._tool, "-aipfC", "-e", self._elf] + [addr for addr in addresses if addr is not None] cmd = [self._tool, "-aipfC", "-e", self._elf] + [
addr for addr in addresses if addr is not None
]
if sys.version_info[0] < 3: if sys.version_info[0] < 3:
output = subprocess.check_output(cmd) output = subprocess.check_output(cmd)
@@ -190,19 +221,27 @@ class AddressResolver(object):
match = line_regex.match(line) match = line_regex.match(line)
if match is None: if match is None:
if last is not None and line.startswith('(inlined by)'): if last is not None and line.startswith("(inlined by)"):
line = line [12:].strip() line = line[12:].strip()
self._address_map[last] += ("\n \-> inlined by: " + line) self._address_map[last] += "\n \-> inlined by: " + line
continue continue
if match.group("result") == '?? ??:0': if match.group("result") == "?? ??:0":
continue continue
self._address_map[match.group("addr")] = match.group("result") self._address_map[match.group("addr")] = match.group("result")
last = match.group("addr") last = match.group("addr")
def fill(self, parser): def fill(self, parser):
addresses = [parser.epc1, parser.epc2, parser.epc3, parser.excvaddr, parser.sp, parser.end, parser.offset] addresses = [
parser.epc1,
parser.epc2,
parser.epc3,
parser.excvaddr,
parser.sp,
parser.end,
parser.offset,
]
for line in parser.stack: for line in parser.stack:
addresses.extend(line.content) addresses.extend(line.content)
@@ -257,8 +296,10 @@ def print_stack(lines, resolver):
def print_result(parser, resolver, platform, full=True, stack_only=False): def print_result(parser, resolver, platform, full=True, stack_only=False):
if platform == 'ESP8266' and not stack_only: if platform == "ESP8266" and not stack_only:
print('Exception: {} ({})'.format(parser.exception, EXCEPTIONS[parser.exception])) print(
"Exception: {} ({})".format(parser.exception, EXCEPTIONS[parser.exception])
)
print("") print("")
print_addr("epc1", parser.epc1, resolver) print_addr("epc1", parser.epc1, resolver)
@@ -285,15 +326,33 @@ def print_result(parser, resolver, platform, full=True, stack_only=False):
def parse_args(): def parse_args():
parser = argparse.ArgumentParser(description="decode ESP Stacktraces.") parser = argparse.ArgumentParser(description="decode ESP Stacktraces.")
parser.add_argument("-p", "--platform", help="The platform to decode from", choices=PLATFORMS.keys(), parser.add_argument(
default="ESP32") "-p",
parser.add_argument("-t", "--tool", help="Path to the xtensa toolchain", "--platform",
default="~/.platformio/packages/toolchain-xtensa32/") help="The platform to decode from",
parser.add_argument("-e", "--elf", help="path to elf file", choices=PLATFORMS.keys(),
default=".pio/build/esp32/firmware.elf") default="ESP32",
parser.add_argument("-f", "--full", help="Print full stack dump", action="store_true") )
parser.add_argument("-s", "--stack_only", help="Decode only a stractrace", action="store_true") parser.add_argument(
parser.add_argument("file", help="The file to read the exception data from ('-' for STDIN)", default="-") "-t",
"--tool",
help="Path to the toolchain (without specific platform)",
default="~/.platformio/packages/toolchain-",
)
parser.add_argument(
"-e", "--elf", help="path to elf file", default=".pio/build/tbeam/firmware.elf"
)
parser.add_argument(
"-f", "--full", help="Print full stack dump", action="store_true"
)
parser.add_argument(
"-s", "--stack_only", help="Decode only a stractrace", action="store_true"
)
parser.add_argument(
"file",
help="The file to read the exception data from ('-' for STDIN)",
default="-",
)
return parser.parse_args() return parser.parse_args()
@@ -309,10 +368,12 @@ if __name__ == "__main__":
sys.exit(1) sys.exit(1)
file = open(args.file, "r") file = open(args.file, "r")
addr2line = os.path.join(os.path.abspath(os.path.expanduser(args.tool)), addr2line = os.path.join(
"bin/xtensa-" + PLATFORMS[args.platform] + "-elf-addr2line") os.path.abspath(os.path.expanduser(args.tool + TOOLS[args.platform])),
if os.name == 'nt': "bin/" + PLATFORMS[args.platform] + "-elf-addr2line",
addr2line += '.exe' )
if os.name == "nt":
addr2line += ".exe"
if not os.path.exists(addr2line): if not os.path.exists(addr2line):
print("ERROR: addr2line not found (" + addr2line + ")") print("ERROR: addr2line not found (" + addr2line + ")")
+12
View File
@@ -0,0 +1,12 @@
[Unit]
Description=Meshtastic Native Daemon
After=network-online.target
[Service]
User=root
Group=root
Type=simple
ExecStart=/usr/sbin/meshtasticd
[Install]
WantedBy=multi-user.target
+10
View File
@@ -0,0 +1,10 @@
#!/usr/bin/env bash
cp "release/meshtasticd_linux_$(arch)" /usr/sbin/meshtasticd
mkdir /etc/meshtasticd
if [[ -f "/etc/meshtasticd/config.yaml" ]]; then
cp bin/config-dist.yaml /etc/meshtasticd/config-upgrade.yaml
else
cp bin/config-dist.yaml /etc/meshtasticd/config.yaml
fi
cp bin/meshtasticd.service /usr/lib/systemd/system/meshtasticd.service
-2
View File
@@ -28,8 +28,6 @@
"flash_size": "8MB", "flash_size": "8MB",
"maximum_ram_size": 327680, "maximum_ram_size": 327680,
"maximum_size": 8388608, "maximum_size": 8388608,
"use_1200bps_touch": true,
"wait_for_upload_port": true,
"require_upload_port": true, "require_upload_port": true,
"speed": 921600 "speed": 921600
}, },
+51
View File
@@ -0,0 +1,51 @@
{
"build": {
"arduino": {
"ldscript": "nrf52840_s140_v6.ld"
},
"core": "nRF5",
"cpu": "cortex-m4",
"extra_flags": "-DARDUINO_NRF52840_FEATHER -DNRF52840_XXAA",
"f_cpu": "64000000L",
"hwids": [
["0x239A", "0x8029"],
["0x239A", "0x0029"],
["0x239A", "0x002A"],
["0x239A", "0x802A"]
],
"usb_product": "BQ nRF52840",
"mcu": "nrf52840",
"variant": "nano-g2-ultra",
"bsp": {
"name": "adafruit"
},
"softdevice": {
"sd_flags": "-DS140",
"sd_name": "s140",
"sd_version": "6.1.1",
"sd_fwid": "0x00B6"
},
"bootloader": {
"settings_addr": "0xFF000"
}
},
"connectivity": ["bluetooth"],
"debug": {
"jlink_device": "nRF52840_xxAA",
"svd_path": "nrf52840.svd"
},
"frameworks": ["arduino"],
"name": "BQ nRF52840",
"upload": {
"maximum_ram_size": 248832,
"maximum_size": 815104,
"speed": 115200,
"protocol": "nrfutil",
"protocols": ["jlink", "nrfjprog", "nrfutil", "stlink"],
"use_1200bps_touch": true,
"require_upload_port": true,
"wait_for_upload_port": true
},
"url": "https://wiki.uniteng.com/en/meshtastic/nano-g2-ultra",
"vendor": "BQ Consulting"
}
+41
View File
@@ -0,0 +1,41 @@
{
"build": {
"arduino": {
"ldscript": "esp32s3_out.ld",
"memory_type": "qio_opi"
},
"core": "esp32",
"extra_flags": [
"-DBOARD_HAS_PSRAM",
"-DARDUINO_USB_CDC_ON_BOOT=1",
"-DARDUINO_USB_MODE=0",
"-DARDUINO_RUNNING_CORE=1",
"-DARDUINO_EVENT_RUNNING_CORE=0"
],
"f_cpu": "240000000L",
"f_flash": "80000000L",
"flash_mode": "qio",
"hwids": [["0x303A", "0x1001"]],
"mcu": "esp32s3",
"variant": "t-deck"
},
"connectivity": ["wifi", "bluetooth", "lora"],
"debug": {
"default_tool": "esp-builtin",
"onboard_tools": ["esp-builtin"],
"openocd_target": "esp32s3.cfg"
},
"frameworks": ["arduino", "espidf"],
"name": "Espressif Systems LilyGO T-Deck (16 MB FLASH, 8 MB PSRAM)",
"upload": {
"flash_size": "16MB",
"maximum_ram_size": 327680,
"maximum_size": 16777216,
"use_1200bps_touch": true,
"wait_for_upload_port": true,
"require_upload_port": true,
"speed": 921600
},
"url": "https://www.lilygo.cc/en-pl/products/t-deck",
"vendor": "LilyGO"
}
+1
View File
@@ -9,6 +9,7 @@
"f_cpu": "64000000L", "f_cpu": "64000000L",
"hwids": [ "hwids": [
["0x239A", "0x4405"], ["0x239A", "0x4405"],
["0x239A", "0x0029"],
["0x239A", "0x002A"] ["0x239A", "0x002A"]
], ],
"usb_product": "TTGO_eink", "usb_product": "TTGO_eink",
+43
View File
@@ -0,0 +1,43 @@
{
"build": {
"arduino": {
"ldscript": "esp32s3_out.ld",
"memory_type": "qio_opi"
},
"core": "esp32",
"extra_flags": [
"-DBOARD_HAS_PSRAM",
"-DT_WATCH_S3",
"-DARDUINO_USB_CDC_ON_BOOT=1",
"-DARDUINO_USB_MODE=0",
"-DARDUINO_RUNNING_CORE=1",
"-DARDUINO_EVENT_RUNNING_CORE=1"
],
"f_cpu": "240000000L",
"f_flash": "80000000L",
"flash_mode": "qio",
"hwids": [
["0x303A", "0x1001"],
["0x303A", "0x0002"]
],
"mcu": "esp32s3",
"variant": "t-watch-s3"
},
"connectivity": ["wifi"],
"debug": {
"openocd_target": "esp32s3.cfg"
},
"frameworks": ["arduino"],
"name": "LilyGo T-Watch 2020 V3",
"upload": {
"flash_size": "8MB",
"maximum_ram_size": 327680,
"maximum_size": 8388608,
"require_upload_port": true,
"use_1200bps_touch": true,
"wait_for_upload_port": true,
"speed": 921600
},
"url": "https://www.lilygo.cc/en-pl/products/t-watch-s3",
"vendor": "LilyGo"
}
+1 -1
View File
@@ -15,7 +15,7 @@
"f_cpu": "240000000L", "f_cpu": "240000000L",
"f_flash": "80000000L", "f_flash": "80000000L",
"flash_mode": "dio", "flash_mode": "dio",
"hwids": [["0X303A", "0x1001"]], "hwids": [["0x303A", "0x1001"]],
"mcu": "esp32s3", "mcu": "esp32s3",
"variant": "tbeam-s3-core" "variant": "tbeam-s3-core"
}, },
+57
View File
@@ -0,0 +1,57 @@
{
"build": {
"arduino": {
"ldscript": "nrf52840_s140_v7.ld"
},
"core": "nRF5",
"cpu": "cortex-m4",
"extra_flags": "-DARDUINO_MDBT50Q_RX -DNRF52840_XXAA",
"f_cpu": "64000000L",
"hwids": [
["0x239A", "0x810B"],
["0x239A", "0x010B"],
["0x239A", "0x810C"]
],
"usb_product": "XIAO-BOOT",
"mcu": "nrf52840",
"variant": "Seeed_XIAO_nRF52840_Sense",
"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": "Seeed Xiao BLE Sense",
"upload": {
"maximum_ram_size": 248832,
"maximum_size": 815104,
"speed": 115200,
"protocol": "nrfutil",
"protocols": [
"jlink",
"nrfjprog",
"nrfutil",
"stlink",
"cmsis-dap",
"blackmagic"
],
"use_1200bps_touch": true,
"require_upload_port": true,
"wait_for_upload_port": true
},
"url": "https://www.seeedstudio.com/Seeed-XIAO-BLE-Sense-nRF52840-p-5253.html",
"vendor": "Seeed Studio"
}
+17 -10
View File
@@ -2,7 +2,7 @@
; https://docs.platformio.org/page/projectconf.html ; https://docs.platformio.org/page/projectconf.html
[platformio] [platformio]
;default_envs = tbeam default_envs = tbeam
;default_envs = pico ;default_envs = pico
;default_envs = tbeam-s3-core ;default_envs = tbeam-s3-core
;default_envs = tbeam0.7 ;default_envs = tbeam0.7
@@ -10,10 +10,12 @@
;default_envs = heltec-v2_0 ;default_envs = heltec-v2_0
;default_envs = heltec-v2_1 ;default_envs = heltec-v2_1
;default_envs = heltec-wireless-tracker ;default_envs = heltec-wireless-tracker
;default_envs = chatter2
;default_envs = tlora-v1 ;default_envs = tlora-v1
;default_envs = tlora_v1_3 ;default_envs = tlora_v1_3
;default_envs = tlora-v2 ;default_envs = tlora-v2
;default_envs = tlora-v2-1-1_6 ;default_envs = tlora-v2-1-1_6
;default_envs = tlora-v2-1-1_6-tcxo
;default_envs = tlora-t3s3-v1 ;default_envs = tlora-t3s3-v1
;default_envs = lora-relay-v1 # nrf board ;default_envs = lora-relay-v1 # nrf board
;default_envs = t-echo ;default_envs = t-echo
@@ -26,7 +28,8 @@
;default_envs = meshtastic-dr-dev ;default_envs = meshtastic-dr-dev
;default_envs = m5stack-coreink ;default_envs = m5stack-coreink
;default_envs = rak4631 ;default_envs = rak4631
default_envs = wio-e5 ;default_envs = rak10701
;default_envs = wio-e5
extra_configs = extra_configs =
arch/*/*.ini arch/*/*.ini
@@ -50,6 +53,7 @@ build_flags = -Wno-missing-field-initializers
-DRADIOLIB_EXCLUDE_NRF24 -DRADIOLIB_EXCLUDE_NRF24
-DRADIOLIB_EXCLUDE_RF69 -DRADIOLIB_EXCLUDE_RF69
-DRADIOLIB_EXCLUDE_SX1231 -DRADIOLIB_EXCLUDE_SX1231
-DRADIOLIB_EXCLUDE_SX1233
-DRADIOLIB_EXCLUDE_SI443X -DRADIOLIB_EXCLUDE_SI443X
-DRADIOLIB_EXCLUDE_RFM2X -DRADIOLIB_EXCLUDE_RFM2X
-DRADIOLIB_EXCLUDE_AFSK -DRADIOLIB_EXCLUDE_AFSK
@@ -67,10 +71,11 @@ build_flags = -Wno-missing-field-initializers
monitor_speed = 115200 monitor_speed = 115200
lib_deps = lib_deps =
https://github.com/meshtastic/esp8266-oled-ssd1306.git#b38094e03dfa964fbc0e799bc374e91a605c1223 ; ESP8266_SSD1306 jgromes/RadioLib@^6.4.0
https://github.com/mathertel/OneButton#2.1.0 ; OneButton library for non-blocking button debounce https://github.com/meshtastic/esp8266-oled-ssd1306.git#ee628ee6c9588d4c56c9e3da35f0fc9448ad54a8 ; ESP8266_SSD1306
mathertel/OneButton@^2.5.0 ; OneButton library for non-blocking button debounce
https://github.com/meshtastic/arduino-fsm.git#7db3702bf0cfe97b783d6c72595e3f38e0b19159 https://github.com/meshtastic/arduino-fsm.git#7db3702bf0cfe97b783d6c72595e3f38e0b19159
https://github.com/meshtastic/TinyGPSPlus.git#127ad674ef85f0201cb68a065879653ed94792c4 https://github.com/meshtastic/TinyGPSPlus.git#2044b2c51e91ab4cd8cc93b15e40658cd808dd06
https://github.com/meshtastic/ArduinoThread.git#72921ac222eed6f526ba1682023cee290d9aa1b3 https://github.com/meshtastic/ArduinoThread.git#72921ac222eed6f526ba1682023cee290d9aa1b3
nanopb/Nanopb@^0.4.7 nanopb/Nanopb@^0.4.7
erriez/ErriezCRC32@^1.0.1 erriez/ErriezCRC32@^1.0.1
@@ -88,11 +93,11 @@ check_flags =
framework = arduino framework = arduino
lib_deps = lib_deps =
${env.lib_deps} ${env.lib_deps}
mprograms/QMC5883LCompass@^1.1.1 mprograms/QMC5883LCompass@^1.2.0
end2endzone/NonBlockingRTTTL@^1.3.0 end2endzone/NonBlockingRTTTL@^1.3.0
https://github.com/meshtastic/SparkFun_ATECCX08a_Arduino_Library.git#5cf62b36c6f30bc72a07bdb2c11fc9a22d1e31da https://github.com/meshtastic/SparkFun_ATECCX08a_Arduino_Library.git#5cf62b36c6f30bc72a07bdb2c11fc9a22d1e31da
build_flags = ${env.build_flags} -Os -DRADIOLIB_SPI_PARANOID=0 build_flags = ${env.build_flags} -Os
build_src_filter = ${env.build_src_filter} -<platform/portduino/> build_src_filter = ${env.build_src_filter} -<platform/portduino/>
; Common libs for communicating over TCP/IP networks such as MQTT ; Common libs for communicating over TCP/IP networks such as MQTT
@@ -107,17 +112,19 @@ lib_deps =
[environmental_base] [environmental_base]
lib_deps = lib_deps =
adafruit/Adafruit BusIO@^1.11.4 adafruit/Adafruit BusIO@^1.11.4
adafruit/Adafruit Unified Sensor@^1.1.9 adafruit/Adafruit Unified Sensor@^1.1.11
adafruit/Adafruit BMP280 Library@^2.6.6 adafruit/Adafruit BMP280 Library@^2.6.8
adafruit/Adafruit BME280 Library@^2.2.2 adafruit/Adafruit BME280 Library@^2.2.2
https://github.com/boschsensortec/Bosch-BSEC2-Library#v1.5.2400 https://github.com/boschsensortec/Bosch-BSEC2-Library#v1.5.2400
boschsensortec/BME68x Sensor Library@^1.1.40407 boschsensortec/BME68x Sensor Library@^1.1.40407
adafruit/Adafruit MCP9808 Library@^2.0.0 adafruit/Adafruit MCP9808 Library@^2.0.0
https://github.com/KodinLanewave/INA3221@^1.0.0
adafruit/Adafruit INA260 Library@^1.5.0 adafruit/Adafruit INA260 Library@^1.5.0
adafruit/Adafruit INA219@^1.2.0 adafruit/Adafruit INA219@^1.2.0
adafruit/Adafruit SHTC3 Library@^1.0.0 adafruit/Adafruit SHTC3 Library@^1.0.0
adafruit/Adafruit LPS2X@^2.0.4 adafruit/Adafruit LPS2X@^2.0.4
adafruit/Adafruit SHT31 Library@^2.2.0 adafruit/Adafruit SHT31 Library@^2.2.2
adafruit/Adafruit PM25 AQI Sensor@^1.0.6 adafruit/Adafruit PM25 AQI Sensor@^1.0.6
adafruit/Adafruit MPU6050@^2.2.4 adafruit/Adafruit MPU6050@^2.2.4
adafruit/Adafruit LIS3DH@^1.2.4 adafruit/Adafruit LIS3DH@^1.2.4
https://github.com/lewisxhe/BMA423_Library@^0.0.1
+90 -8
View File
@@ -6,16 +6,43 @@
#include <Adafruit_LIS3DH.h> #include <Adafruit_LIS3DH.h>
#include <Adafruit_MPU6050.h> #include <Adafruit_MPU6050.h>
#include <Arduino.h>
#include <Wire.h>
#include <bma.h>
BMA423 bmaSensor;
bool BMA_IRQ = false;
#define ACCELEROMETER_CHECK_INTERVAL_MS 100 #define ACCELEROMETER_CHECK_INTERVAL_MS 100
#define ACCELEROMETER_CLICK_THRESHOLD 40 #define ACCELEROMETER_CLICK_THRESHOLD 40
uint16_t readRegister(uint8_t address, uint8_t reg, uint8_t *data, uint16_t len)
{
Wire.beginTransmission(address);
Wire.write(reg);
Wire.endTransmission();
Wire.requestFrom((uint8_t)address, (uint8_t)len);
uint8_t i = 0;
while (Wire.available()) {
data[i++] = Wire.read();
}
return 0; // Pass
}
uint16_t writeRegister(uint8_t address, uint8_t reg, uint8_t *data, uint16_t len)
{
Wire.beginTransmission(address);
Wire.write(reg);
Wire.write(data, len);
return (0 != Wire.endTransmission());
}
namespace concurrency namespace concurrency
{ {
class AccelerometerThread : public concurrency::OSThread class AccelerometerThread : public concurrency::OSThread
{ {
public: public:
AccelerometerThread(ScanI2C::DeviceType type = ScanI2C::DeviceType::NONE) : OSThread("AccelerometerThread") explicit AccelerometerThread(ScanI2C::DeviceType type) : OSThread("AccelerometerThread")
{ {
if (accelerometer_found.port == ScanI2C::I2CPort::NO_I2C) { if (accelerometer_found.port == ScanI2C::I2CPort::NO_I2C) {
LOG_DEBUG("AccelerometerThread disabling due to no sensors found\n"); LOG_DEBUG("AccelerometerThread disabling due to no sensors found\n");
@@ -29,10 +56,10 @@ class AccelerometerThread : public concurrency::OSThread
return; return;
} }
accleremoter_type = type; acceleremoter_type = type;
LOG_DEBUG("AccelerometerThread initializing\n"); LOG_DEBUG("AccelerometerThread initializing\n");
if (accleremoter_type == ScanI2C::DeviceType::MPU6050 && mpu.begin(accelerometer_found.address)) { if (acceleremoter_type == ScanI2C::DeviceType::MPU6050 && mpu.begin(accelerometer_found.address)) {
LOG_DEBUG("MPU6050 initializing\n"); LOG_DEBUG("MPU6050 initializing\n");
// setup motion detection // setup motion detection
mpu.setHighPassFilter(MPU6050_HIGHPASS_0_63_HZ); mpu.setHighPassFilter(MPU6050_HIGHPASS_0_63_HZ);
@@ -40,11 +67,60 @@ class AccelerometerThread : public concurrency::OSThread
mpu.setMotionDetectionDuration(20); mpu.setMotionDetectionDuration(20);
mpu.setInterruptPinLatch(true); // Keep it latched. Will turn off when reinitialized. mpu.setInterruptPinLatch(true); // Keep it latched. Will turn off when reinitialized.
mpu.setInterruptPinPolarity(true); mpu.setInterruptPinPolarity(true);
} else if (accleremoter_type == ScanI2C::DeviceType::LIS3DH && lis.begin(accelerometer_found.address)) { } else if (acceleremoter_type == ScanI2C::DeviceType::LIS3DH && lis.begin(accelerometer_found.address)) {
LOG_DEBUG("LIS3DH initializing\n"); LOG_DEBUG("LIS3DH initializing\n");
lis.setRange(LIS3DH_RANGE_2_G); lis.setRange(LIS3DH_RANGE_2_G);
// Adjust threshold, higher numbers are less sensitive // Adjust threshold, higher numbers are less sensitive
lis.setClick(config.device.double_tap_as_button_press ? 2 : 1, ACCELEROMETER_CLICK_THRESHOLD); lis.setClick(config.device.double_tap_as_button_press ? 2 : 1, ACCELEROMETER_CLICK_THRESHOLD);
} else if (acceleremoter_type == ScanI2C::DeviceType::BMA423 && bmaSensor.begin(readRegister, writeRegister, delay)) {
LOG_DEBUG("BMA423 initializing\n");
Acfg cfg;
cfg.odr = BMA4_OUTPUT_DATA_RATE_100HZ;
cfg.range = BMA4_ACCEL_RANGE_2G;
cfg.bandwidth = BMA4_ACCEL_NORMAL_AVG4;
cfg.perf_mode = BMA4_CONTINUOUS_MODE;
bmaSensor.setAccelConfig(cfg);
bmaSensor.enableAccel();
struct bma4_int_pin_config pin_config;
pin_config.edge_ctrl = BMA4_LEVEL_TRIGGER;
pin_config.lvl = BMA4_ACTIVE_HIGH;
pin_config.od = BMA4_PUSH_PULL;
pin_config.output_en = BMA4_OUTPUT_ENABLE;
pin_config.input_en = BMA4_INPUT_DISABLE;
// The correct trigger interrupt needs to be configured as needed
bmaSensor.setINTPinConfig(pin_config, BMA4_INTR1_MAP);
#ifdef BMA423_INT
pinMode(BMA4XX_INT, INPUT);
attachInterrupt(
BMA4XX_INT,
[] {
// Set interrupt to set irq value to true
BMA_IRQ = true;
},
RISING); // Select the interrupt mode according to the actual circuit
#endif
struct bma423_axes_remap remap_data;
remap_data.x_axis = 0;
remap_data.x_axis_sign = 1;
remap_data.y_axis = 1;
remap_data.y_axis_sign = 0;
remap_data.z_axis = 2;
remap_data.z_axis_sign = 1;
// Need to raise the wrist function, need to set the correct axis
bmaSensor.setRemapAxes(&remap_data);
// sensor.enableFeature(BMA423_STEP_CNTR, true);
bmaSensor.enableFeature(BMA423_TILT, true);
bmaSensor.enableFeature(BMA423_WAKEUP, true);
// sensor.resetStepCounter();
// Turn on feature interrupt
bmaSensor.enableStepCountInterrupt();
bmaSensor.enableTiltInterrupt();
// It corresponds to isDoubleClick interrupt
bmaSensor.enableWakeupInterrupt();
} }
} }
@@ -53,9 +129,9 @@ class AccelerometerThread : public concurrency::OSThread
{ {
canSleep = true; // Assume we should not keep the board awake canSleep = true; // Assume we should not keep the board awake
if (accleremoter_type == ScanI2C::DeviceType::MPU6050 && mpu.getMotionInterruptStatus()) { if (acceleremoter_type == ScanI2C::DeviceType::MPU6050 && mpu.getMotionInterruptStatus()) {
wakeScreen(); wakeScreen();
} else if (accleremoter_type == ScanI2C::DeviceType::LIS3DH && lis.getClick() > 0) { } else if (acceleremoter_type == ScanI2C::DeviceType::LIS3DH && lis.getClick() > 0) {
uint8_t click = lis.getClick(); uint8_t click = lis.getClick();
if (!config.device.double_tap_as_button_press) { if (!config.device.double_tap_as_button_press) {
wakeScreen(); wakeScreen();
@@ -65,7 +141,13 @@ class AccelerometerThread : public concurrency::OSThread
buttonPress(); buttonPress();
return 500; return 500;
} }
} else if (acceleremoter_type == ScanI2C::DeviceType::BMA423 && bmaSensor.getINT()) {
if (bmaSensor.isTilt() || bmaSensor.isDoubleClick()) {
wakeScreen();
return 500;
}
} }
return ACCELEROMETER_CHECK_INTERVAL_MS; return ACCELEROMETER_CHECK_INTERVAL_MS;
} }
@@ -84,9 +166,9 @@ class AccelerometerThread : public concurrency::OSThread
powerFSM.trigger(EVENT_PRESS); powerFSM.trigger(EVENT_PRESS);
} }
ScanI2C::DeviceType accleremoter_type; ScanI2C::DeviceType acceleremoter_type;
Adafruit_MPU6050 mpu; Adafruit_MPU6050 mpu;
Adafruit_LIS3DH lis; Adafruit_LIS3DH lis;
}; };
} // namespace concurrency } // namespace concurrency
+75
View File
@@ -0,0 +1,75 @@
#include "configuration.h"
#ifdef HAS_NCP5623
#include <graphics/RAKled.h>
NCP5623 rgb;
#endif
namespace concurrency
{
class AmbientLightingThread : public concurrency::OSThread
{
public:
explicit AmbientLightingThread(ScanI2C::DeviceType type) : OSThread("AmbientLightingThread")
{
// Uncomment to test module
// moduleConfig.ambient_lighting.led_state = true;
// moduleConfig.ambient_lighting.current = 10;
// // Default to a color based on our node number
// moduleConfig.ambient_lighting.red = (myNodeInfo.my_node_num & 0xFF0000) >> 16;
// moduleConfig.ambient_lighting.green = (myNodeInfo.my_node_num & 0x00FF00) >> 8;
// moduleConfig.ambient_lighting.blue = myNodeInfo.my_node_num & 0x0000FF;
#ifdef HAS_NCP5623
_type = type;
if (_type == ScanI2C::DeviceType::NONE) {
LOG_DEBUG("AmbientLightingThread disabling due to no RGB leds found on I2C bus\n");
disable();
return;
}
if (!moduleConfig.ambient_lighting.led_state) {
LOG_DEBUG("AmbientLightingThread disabling due to moduleConfig.ambient_lighting.led_state OFF\n");
disable();
return;
}
LOG_DEBUG("AmbientLightingThread initializing\n");
if (_type == ScanI2C::NCP5623) {
rgb.begin();
setLighting();
}
#endif
}
protected:
int32_t runOnce() override
{
#ifdef HAS_NCP5623
if (_type == ScanI2C::NCP5623 && moduleConfig.ambient_lighting.led_state) {
setLighting();
return 30000; // 30 seconds to reset from any animations that may have been running from Ext. Notification
} else {
return disable();
}
#else
return disable();
#endif
}
private:
ScanI2C::DeviceType _type = ScanI2C::DeviceType::NONE;
void setLighting()
{
#ifdef HAS_NCP5623
rgb.setCurrent(moduleConfig.ambient_lighting.current);
rgb.setRed(moduleConfig.ambient_lighting.red);
rgb.setGreen(moduleConfig.ambient_lighting.green);
rgb.setBlue(moduleConfig.ambient_lighting.blue);
LOG_DEBUG("Initializing Ambient lighting w/ current=%d, red=%d, green=%d, blue=%d\n",
moduleConfig.ambient_lighting.current, moduleConfig.ambient_lighting.red, moduleConfig.ambient_lighting.green,
moduleConfig.ambient_lighting.blue);
#endif
}
};
} // namespace concurrency
+77
View File
@@ -0,0 +1,77 @@
#pragma once
#include "PowerFSM.h"
#include "concurrency/OSThread.h"
#include "configuration.h"
#include "main.h"
#include "sleep.h"
#ifdef HAS_I2S
#include <AudioFileSourcePROGMEM.h>
#include <AudioGeneratorRTTTL.h>
#include <AudioOutputI2S.h>
#include <ESP8266SAM.h>
#define AUDIO_THREAD_INTERVAL_MS 100
class AudioThread : public concurrency::OSThread
{
public:
AudioThread() : OSThread("AudioThread") { initOutput(); }
void beginRttl(const void *data, uint32_t len)
{
setCPUFast(true);
rtttlFile = new AudioFileSourcePROGMEM(data, len);
i2sRtttl = new AudioGeneratorRTTTL();
i2sRtttl->begin(rtttlFile, audioOut);
}
bool isPlaying()
{
if (i2sRtttl != nullptr) {
return i2sRtttl->isRunning() && i2sRtttl->loop();
}
return false;
}
void stop()
{
if (i2sRtttl != nullptr) {
i2sRtttl->stop();
delete i2sRtttl;
i2sRtttl = nullptr;
}
if (rtttlFile != nullptr) {
delete rtttlFile;
rtttlFile = nullptr;
}
setCPUFast(false);
}
protected:
int32_t runOnce() override
{
canSleep = true; // Assume we should not keep the board awake
// if (i2sRtttl != nullptr && i2sRtttl->isRunning()) {
// i2sRtttl->loop();
// }
return AUDIO_THREAD_INTERVAL_MS;
}
private:
void initOutput()
{
audioOut = new AudioOutputI2S(1, AudioOutputI2S::EXTERNAL_I2S);
audioOut->SetPinout(DAC_I2S_BCK, DAC_I2S_WS, DAC_I2S_DOUT);
audioOut->SetGain(0.2);
};
AudioGeneratorRTTTL *i2sRtttl = nullptr;
AudioOutputI2S *audioOut;
AudioFileSourcePROGMEM *rtttlFile;
};
#endif
+56 -15
View File
@@ -4,6 +4,8 @@
#include "concurrency/OSThread.h" #include "concurrency/OSThread.h"
#include "configuration.h" #include "configuration.h"
#include "graphics/Screen.h" #include "graphics/Screen.h"
#include "main.h"
#include "modules/ExternalNotificationModule.h"
#include "power.h" #include "power.h"
#include <OneButton.h> #include <OneButton.h>
@@ -35,6 +37,9 @@ class ButtonThread : public concurrency::OSThread
#endif #endif
#ifdef BUTTON_PIN_TOUCH #ifdef BUTTON_PIN_TOUCH
OneButton userButtonTouch; OneButton userButtonTouch;
#endif
#if defined(ARCH_PORTDUINO)
OneButton userButton;
#endif #endif
static bool shutdown_on_long_stop; static bool shutdown_on_long_stop;
@@ -44,20 +49,42 @@ class ButtonThread : public concurrency::OSThread
// callback returns the period for the next callback invocation (or 0 if we should no longer be called) // callback returns the period for the next callback invocation (or 0 if we should no longer be called)
ButtonThread() : OSThread("Button") ButtonThread() : OSThread("Button")
{ {
#ifdef BUTTON_PIN #if defined(ARCH_PORTDUINO) || defined(BUTTON_PIN)
userButton = OneButton(config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN, true, true); #if defined(ARCH_PORTDUINO)
if (settingsMap.count(user) != 0 && settingsMap[user] != RADIOLIB_NC)
userButton = OneButton(settingsMap[user], true, true);
#elif defined(BUTTON_PIN)
int pin = config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN;
userButton = OneButton(pin, true, true);
#endif
#ifdef INPUT_PULLUP_SENSE #ifdef INPUT_PULLUP_SENSE
// Some platforms (nrf52) have a SENSE variant which allows wake from sleep - override what OneButton did // Some platforms (nrf52) have a SENSE variant which allows wake from sleep - override what OneButton did
pinMode(config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN, INPUT_PULLUP_SENSE); pinMode(pin, INPUT_PULLUP_SENSE);
#endif #endif
userButton.attachClick(userButtonPressed); userButton.attachClick(userButtonPressed);
userButton.setClickMs(300); userButton.setClickMs(400);
userButton.setPressMs(1000);
userButton.setDebounceMs(10);
userButton.attachDuringLongPress(userButtonPressedLong); userButton.attachDuringLongPress(userButtonPressedLong);
userButton.attachDoubleClick(userButtonDoublePressed); userButton.attachDoubleClick(userButtonDoublePressed);
userButton.attachMultiClick(userButtonMultiPressed); userButton.attachMultiClick(userButtonMultiPressed);
userButton.attachLongPressStart(userButtonPressedLongStart); userButton.attachLongPressStart(userButtonPressedLongStart);
userButton.attachLongPressStop(userButtonPressedLongStop); userButton.attachLongPressStop(userButtonPressedLongStop);
wakeOnIrq(config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN, FALLING); #if defined(ARCH_PORTDUINO)
if (settingsMap.count(user) != 0 && settingsMap[user] != RADIOLIB_NC)
wakeOnIrq(settingsMap[user], FALLING);
#else
static OneButton *pBtn = &userButton; // only one instance of ButtonThread is created, so static is safe
attachInterrupt(
pin,
[]() {
BaseType_t higherWake = 0;
mainDelay.interruptFromISR(&higherWake);
pBtn->tick();
},
CHANGE);
#endif
#endif #endif
#ifdef BUTTON_PIN_ALT #ifdef BUTTON_PIN_ALT
userButtonAlt = OneButton(BUTTON_PIN_ALT, true, true); userButtonAlt = OneButton(BUTTON_PIN_ALT, true, true);
@@ -86,9 +113,14 @@ class ButtonThread : public concurrency::OSThread
{ {
canSleep = true; // Assume we should not keep the board awake canSleep = true; // Assume we should not keep the board awake
#ifdef BUTTON_PIN #if defined(BUTTON_PIN)
userButton.tick(); userButton.tick();
canSleep &= userButton.isIdle(); canSleep &= userButton.isIdle();
#elif defined(ARCH_PORTDUINO)
if (settingsMap.count(user) != 0 && settingsMap[user] != RADIOLIB_NC) {
userButton.tick();
canSleep &= userButton.isIdle();
}
#endif #endif
#ifdef BUTTON_PIN_ALT #ifdef BUTTON_PIN_ALT
userButtonAlt.tick(); userButtonAlt.tick();
@@ -101,7 +133,7 @@ class ButtonThread : public concurrency::OSThread
// if (!canSleep) LOG_DEBUG("Suppressing sleep!\n"); // if (!canSleep) LOG_DEBUG("Suppressing sleep!\n");
// else LOG_DEBUG("sleep ok\n"); // else LOG_DEBUG("sleep ok\n");
return 5; return 50;
} }
private: private:
@@ -117,6 +149,14 @@ class ButtonThread : public concurrency::OSThread
#ifdef BUTTON_PIN #ifdef BUTTON_PIN
if (((config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN) != if (((config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN) !=
moduleConfig.canned_message.inputbroker_pin_press) || moduleConfig.canned_message.inputbroker_pin_press) ||
!(moduleConfig.canned_message.updown1_enabled || moduleConfig.canned_message.rotary1_enabled) ||
!moduleConfig.canned_message.enabled) {
powerFSM.trigger(EVENT_PRESS);
}
#endif
#if defined(ARCH_PORTDUINO)
if ((settingsMap.count(user) != 0 && settingsMap[user] != RADIOLIB_NC) &&
(settingsMap[user] != moduleConfig.canned_message.inputbroker_pin_press) ||
!moduleConfig.canned_message.enabled) { !moduleConfig.canned_message.enabled) {
powerFSM.trigger(EVENT_PRESS); powerFSM.trigger(EVENT_PRESS);
} }
@@ -163,19 +203,20 @@ class ButtonThread : public concurrency::OSThread
static void userButtonMultiPressed() static void userButtonMultiPressed()
{ {
#if defined(GPS_POWER_TOGGLE) if (!config.device.disable_triple_click && (gps != nullptr)) {
if (config.position.gps_enabled) { gps->toggleGpsMode();
LOG_DEBUG("Flag set to false for gps power\n"); screen->forceDisplay();
} else {
LOG_DEBUG("Flag set to true to restore power\n");
} }
config.position.gps_enabled = !(config.position.gps_enabled);
doGPSpowersave(config.position.gps_enabled);
#endif
} }
static void userButtonPressedLongStart() static void userButtonPressedLongStart()
{ {
#ifdef T_DECK
// False positive long-press triggered on T-Deck with i2s audio, so short circuit
if (moduleConfig.external_notification.enabled && (externalNotificationModule->nagCycleCutoff != UINT32_MAX)) {
return;
}
#endif
if (millis() > 30 * 1000) { if (millis() > 30 * 1000) {
LOG_DEBUG("Long press start!\n"); LOG_DEBUG("Long press start!\n");
longPressTime = millis(); longPressTime = millis();
+34
View File
@@ -0,0 +1,34 @@
#include "DisplayFormatters.h"
const char *DisplayFormatters::getModemPresetDisplayName(meshtastic_Config_LoRaConfig_ModemPreset preset, bool useShortName)
{
switch (preset) {
case meshtastic_Config_LoRaConfig_ModemPreset_SHORT_SLOW:
return useShortName ? "ShortS" : "ShortSlow";
break;
case meshtastic_Config_LoRaConfig_ModemPreset_SHORT_FAST:
return useShortName ? "ShortF" : "ShortFast";
break;
case meshtastic_Config_LoRaConfig_ModemPreset_MEDIUM_SLOW:
return useShortName ? "MedS" : "MediumSlow";
break;
case meshtastic_Config_LoRaConfig_ModemPreset_MEDIUM_FAST:
return useShortName ? "MedF" : "MediumFast";
break;
case meshtastic_Config_LoRaConfig_ModemPreset_LONG_SLOW:
return useShortName ? "LongS" : "LongSlow";
break;
case meshtastic_Config_LoRaConfig_ModemPreset_LONG_FAST:
return useShortName ? "LongF" : "LongFast";
break;
case meshtastic_Config_LoRaConfig_ModemPreset_LONG_MODERATE:
return useShortName ? "LongM" : "LongMod";
break;
case meshtastic_Config_LoRaConfig_ModemPreset_VERY_LONG_SLOW:
return useShortName ? "VeryL" : "VLongSlow";
break;
default:
return useShortName ? "Custom" : "Invalid";
break;
}
}
+8
View File
@@ -0,0 +1,8 @@
#pragma once
#include "NodeDB.h"
class DisplayFormatters
{
public:
static const char *getModemPresetDisplayName(meshtastic_Config_LoRaConfig_ModemPreset preset, bool useShortName);
};
+45 -1
View File
@@ -1,3 +1,13 @@
/**
* @file FSCommon.cpp
* @brief This file contains functions for common filesystem operations such as copying, renaming, listing and deleting files and
* directories.
*
* The functions in this file are used to perform common filesystem operations such as copying, renaming, listing and deleting
* files and directories. These functions are used in the Meshtastic-device project to manage files and directories on the
* device's filesystem.
*
*/
#include "FSCommon.h" #include "FSCommon.h"
#include "configuration.h" #include "configuration.h"
@@ -8,10 +18,19 @@
#ifdef SDCARD_USE_SPI1 #ifdef SDCARD_USE_SPI1
SPIClass SPI1(HSPI); SPIClass SPI1(HSPI);
#define SDHandler SPI1 #define SDHandler SPI1
#else
#define SDHandler SPI
#endif #endif
#endif // HAS_SDCARD #endif // HAS_SDCARD
/**
* @brief Copies a file from one location to another.
*
* @param from The path of the source file.
* @param to The path of the destination file.
* @return true if the file was successfully copied, false otherwise.
*/
bool copyFile(const char *from, const char *to) bool copyFile(const char *from, const char *to)
{ {
#ifdef FSCom #ifdef FSCom
@@ -41,6 +60,14 @@ bool copyFile(const char *from, const char *to)
#endif #endif
} }
/**
* Renames a file from pathFrom to pathTo.
*
* @param pathFrom The original path of the file.
* @param pathTo The new path of the file.
*
* @return True if the file was successfully renamed, false otherwise.
*/
bool renameFile(const char *pathFrom, const char *pathTo) bool renameFile(const char *pathFrom, const char *pathTo)
{ {
#ifdef FSCom #ifdef FSCom
@@ -57,6 +84,13 @@ bool renameFile(const char *pathFrom, const char *pathTo)
#endif #endif
} }
/**
* Lists the contents of a directory.
*
* @param dirname The name of the directory to list.
* @param levels The number of levels of subdirectories to list.
* @param del Whether or not to delete the contents of the directory after listing.
*/
void listDir(const char *dirname, uint8_t levels, bool del = false) void listDir(const char *dirname, uint8_t levels, bool del = false)
{ {
#ifdef FSCom #ifdef FSCom
@@ -152,6 +186,13 @@ void listDir(const char *dirname, uint8_t levels, bool del = false)
#endif #endif
} }
/**
* @brief Removes a directory and all its contents.
*
* This function recursively removes a directory and all its contents, including subdirectories and files.
*
* @param dirname The name of the directory to remove.
*/
void rmDir(const char *dirname) void rmDir(const char *dirname)
{ {
#ifdef FSCom #ifdef FSCom
@@ -180,6 +221,9 @@ void fsInit()
#endif #endif
} }
/**
* Initializes the SD card and mounts the file system.
*/
void setupSDCard() void setupSDCard()
{ {
#ifdef HAS_SDCARD #ifdef HAS_SDCARD
@@ -210,4 +254,4 @@ void setupSDCard()
LOG_DEBUG("Total space: %llu MB\n", SD.totalBytes() / (1024 * 1024)); LOG_DEBUG("Total space: %llu MB\n", SD.totalBytes() / (1024 * 1024));
LOG_DEBUG("Used space: %llu MB\n", SD.usedBytes() / (1024 * 1024)); LOG_DEBUG("Used space: %llu MB\n", SD.usedBytes() / (1024 * 1024));
#endif #endif
} }
+10
View File
@@ -29,6 +29,16 @@ static void IRAM_ATTR onTimer()
(*tCallback)(tParam1, tParam2); (*tCallback)(tParam1, tParam2);
} }
/**
* Schedules a hardware callback function to be executed after a specified delay.
*
* @param callback The function to be executed.
* @param param1 The first parameter to be passed to the function.
* @param param2 The second parameter to be passed to the function.
* @param delayMsec The delay time in milliseconds before the function is executed.
*
* @return True if the function was successfully scheduled, false otherwise.
*/
bool scheduleHWCallback(PendableFunction callback, void *param1, uint32_t param2, uint32_t delayMsec) bool scheduleHWCallback(PendableFunction callback, void *param1, uint32_t param2, uint32_t delayMsec)
{ {
if (!timer) { if (!timer) {
+7 -7
View File
@@ -10,12 +10,12 @@ template <class T> class Observable;
*/ */
template <class T> class Observer template <class T> class Observer
{ {
std::list<Observable<T> *> observed; std::list<Observable<T> *> observables;
public: public:
virtual ~Observer(); virtual ~Observer();
/// Stop watching the obserable /// Stop watching the observable
void unobserve(Observable<T> *o); void unobserve(Observable<T> *o);
/// Start watching a specified observable /// Start watching a specified observable
@@ -86,21 +86,21 @@ template <class T> class Observable
template <class T> Observer<T>::~Observer() template <class T> Observer<T>::~Observer()
{ {
for (typename std::list<Observable<T> *>::const_iterator iterator = observed.begin(); iterator != observed.end(); for (typename std::list<Observable<T> *>::const_iterator iterator = observables.begin(); iterator != observables.end();
++iterator) { ++iterator) {
(*iterator)->removeObserver(this); (*iterator)->removeObserver(this);
} }
observed.clear(); observables.clear();
} }
template <class T> void Observer<T>::unobserve(Observable<T> *o) template <class T> void Observer<T>::unobserve(Observable<T> *o)
{ {
o->removeObserver(this); o->removeObserver(this);
observed.remove(o); observables.remove(o);
} }
template <class T> void Observer<T>::observe(Observable<T> *o) template <class T> void Observer<T>::observe(Observable<T> *o)
{ {
observed.push_back(o); observables.push_back(o);
o->addObserver(this); o->addObserver(this);
} }
+122 -63
View File
@@ -1,11 +1,28 @@
/**
* @file Power.cpp
* @brief This file contains the implementation of the Power class, which is responsible for managing power-related functionality
* of the device. It includes battery level sensing, power management unit (PMU) control, and power state machine management. The
* Power class is used by the main device class to manage power-related functionality.
*
* The file also includes implementations of various battery level sensors, such as the AnalogBatteryLevel class, which assumes
* the battery voltage is attached via a voltage-divider to an analog input.
*
* This file is part of the Meshtastic project.
* For more information, see: https://meshtastic.org/
*/
#include "power.h" #include "power.h"
#include "NodeDB.h" #include "NodeDB.h"
#include "PowerFSM.h" #include "PowerFSM.h"
#include "buzz/buzz.h" #include "buzz/buzz.h"
#include "configuration.h" #include "configuration.h"
#include "main.h" #include "main.h"
#include "meshUtils.h"
#include "sleep.h" #include "sleep.h"
#include "utils.h"
// Working USB detection for powered/charging states on the RAK platform
#ifdef NRF_APM
#include "nrfx_power.h"
#endif
#ifdef DEBUG_HEAP_MQTT #ifdef DEBUG_HEAP_MQTT
#include "mqtt/MQTT.h" #include "mqtt/MQTT.h"
@@ -40,6 +57,7 @@ static const adc_atten_t atten = ADC_ATTENUATION;
#if HAS_TELEMETRY && !defined(ARCH_PORTDUINO) #if HAS_TELEMETRY && !defined(ARCH_PORTDUINO)
INA260Sensor ina260Sensor; INA260Sensor ina260Sensor;
INA219Sensor ina219Sensor; INA219Sensor ina219Sensor;
INA3221Sensor ina3221Sensor;
#endif #endif
#ifdef HAS_PMU #ifdef HAS_PMU
@@ -146,7 +164,8 @@ class AnalogBatteryLevel : public HasBatteryLevel
#endif #endif
#ifndef BATTERY_SENSE_SAMPLES #ifndef BATTERY_SENSE_SAMPLES
#define BATTERY_SENSE_SAMPLES 30 #define BATTERY_SENSE_SAMPLES \
30 // Set the number of samples, it has an effect of increasing sensitivity in complex electromagnetic environment.
#endif #endif
#ifdef BATTERY_PIN #ifdef BATTERY_PIN
@@ -158,61 +177,75 @@ class AnalogBatteryLevel : public HasBatteryLevel
if (millis() - last_read_time_ms > min_read_interval) { if (millis() - last_read_time_ms > min_read_interval) {
last_read_time_ms = millis(); last_read_time_ms = millis();
// Set the number of samples, it has an effect of increasing sensitivity, especially in complex electromagnetic
// environment.
uint32_t raw = 0; uint32_t raw = 0;
#ifdef ARCH_ESP32 float scaled = 0;
#ifndef BAT_MEASURE_ADC_UNIT // ADC1
for (int i = 0; i < BATTERY_SENSE_SAMPLES; i++) { #ifdef ARCH_ESP32 // ADC block for espressif platforms
raw += adc1_get_raw(adc_channel); raw = espAdcRead();
} scaled = esp_adc_cal_raw_to_voltage(raw, adc_characs);
#else // ADC2 scaled *= operativeAdcMultiplier;
int32_t adc_buf = 0; #else // block for all other platforms
for (int i = 0; i < BATTERY_SENSE_SAMPLES; i++) {
// ADC2 wifi bug workaround, see
// https://github.com/espressif/arduino-esp32/issues/102
WRITE_PERI_REG(SENS_SAR_READ_CTRL2_REG, RTC_reg_b);
SET_PERI_REG_MASK(SENS_SAR_READ_CTRL2_REG, SENS_SAR2_DATA_INV);
adc2_get_raw(adc_channel, ADC_WIDTH_BIT_12, &adc_buf);
raw += adc_buf;
}
#endif // BAT_MEASURE_ADC_UNIT
#else // !ARCH_ESP32
for (uint32_t i = 0; i < BATTERY_SENSE_SAMPLES; i++) { for (uint32_t i = 0; i < BATTERY_SENSE_SAMPLES; i++) {
raw += analogRead(BATTERY_PIN); raw += analogRead(BATTERY_PIN);
} }
#endif
raw = raw / BATTERY_SENSE_SAMPLES; raw = raw / BATTERY_SENSE_SAMPLES;
float scaled; scaled = operativeAdcMultiplier * ((1000 * AREF_VOLTAGE) / pow(2, BATTERY_SENSE_RESOLUTION_BITS)) * raw;
#ifdef ARCH_ESP32 #endif
scaled = esp_adc_cal_raw_to_voltage(raw, adc_characs); // LOG_DEBUG("battery gpio %d raw val=%u scaled=%u\n", BATTERY_PIN, raw, (uint32_t)(scaled));
scaled *= operativeAdcMultiplier;
#else
#ifndef VBAT_RAW_TO_SCALED
scaled = 1000.0 * operativeAdcMultiplier * (AREF_VOLTAGE / 1024.0) * raw;
#else
scaled = VBAT_RAW_TO_SCALED(raw); // defined in variant.h
#endif // VBAT RAW TO SCALED
#endif // ARCH_ESP32
// LOG_DEBUG("battery gpio %d raw val=%u scaled=%u\n", BATTERY_PIN, raw, (uint32_t)(scaled));
last_read_value = scaled; last_read_value = scaled;
return scaled; return scaled;
} else { } else {
return last_read_value; return last_read_value;
} }
#else
return 0;
#endif // BATTERY_PIN #endif // BATTERY_PIN
return 0;
} }
#if defined(ARCH_ESP32) && !defined(HAS_PMU) && defined(BATTERY_PIN)
/**
* ESP32 specific function for getting calibrated ADC reads
*/
uint32_t espAdcRead()
{
uint32_t raw = 0;
#ifndef BAT_MEASURE_ADC_UNIT // ADC1
#ifdef ADC_CTRL
if (heltec_version == 5) {
pinMode(ADC_CTRL, OUTPUT);
digitalWrite(ADC_CTRL, HIGH);
delay(10);
}
#endif
for (int i = 0; i < BATTERY_SENSE_SAMPLES; i++) {
raw += adc1_get_raw(adc_channel);
}
#ifdef ADC_CTRL
if (heltec_version == 5) {
digitalWrite(ADC_CTRL, LOW);
}
#endif
#else // ADC2
int32_t adc_buf = 0;
for (int i = 0; i < BATTERY_SENSE_SAMPLES; i++) {
// ADC2 wifi bug workaround, see
// https://github.com/espressif/arduino-esp32/issues/102
WRITE_PERI_REG(SENS_SAR_READ_CTRL2_REG, RTC_reg_b);
SET_PERI_REG_MASK(SENS_SAR_READ_CTRL2_REG, SENS_SAR2_DATA_INV);
adc2_get_raw(adc_channel, ADC_WIDTH_BIT_12, &adc_buf);
raw += adc_buf;
}
#endif // BAT_MEASURE_ADC_UNIT
raw = raw / BATTERY_SENSE_SAMPLES;
return raw;
}
#endif
/** /**
* return true if there is a battery installed in this unit * return true if there is a battery installed in this unit
*/ */
virtual bool isBatteryConnect() override virtual bool isBatteryConnect() override { return getBatteryPercent() != -1; }
{
return getBatteryPercent() != -1;
}
/// If we see a battery voltage higher than physics allows - assume charger is pumping /// If we see a battery voltage higher than physics allows - assume charger is pumping
/// in power /// in power
@@ -233,10 +266,7 @@ class AnalogBatteryLevel : public HasBatteryLevel
/// Assume charging if we have a battery and external power is connected. /// Assume charging if we have a battery and external power is connected.
/// we can't be smart enough to say 'full'? /// we can't be smart enough to say 'full'?
virtual bool isCharging() override virtual bool isCharging() override { return isBatteryConnect() && isVbusIn(); }
{
return isBatteryConnect() && isVbusIn();
}
private: private:
/// If we see a battery voltage higher than physics allows - assume charger is pumping /// If we see a battery voltage higher than physics allows - assume charger is pumping
@@ -263,10 +293,14 @@ class AnalogBatteryLevel : public HasBatteryLevel
#if defined(HAS_TELEMETRY) && !defined(ARCH_PORTDUINO) #if defined(HAS_TELEMETRY) && !defined(ARCH_PORTDUINO)
uint16_t getINAVoltage() uint16_t getINAVoltage()
{ {
if (nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_INA219] == config.power.device_battery_ina_address) { if (nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_INA219].first == config.power.device_battery_ina_address) {
return ina219Sensor.getBusVoltageMv(); return ina219Sensor.getBusVoltageMv();
} else if (nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_INA260] == config.power.device_battery_ina_address) { } else if (nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_INA260].first ==
config.power.device_battery_ina_address) {
return ina260Sensor.getBusVoltageMv(); return ina260Sensor.getBusVoltageMv();
} else if (nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_INA3221].first ==
config.power.device_battery_ina_address) {
return ina3221Sensor.getBusVoltageMv();
} }
return 0; return 0;
} }
@@ -276,11 +310,12 @@ class AnalogBatteryLevel : public HasBatteryLevel
if (!config.power.device_battery_ina_address) { if (!config.power.device_battery_ina_address) {
return false; return false;
} }
if (nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_INA219] == config.power.device_battery_ina_address) { if (nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_INA219].first == config.power.device_battery_ina_address) {
if (!ina219Sensor.isInitialized()) if (!ina219Sensor.isInitialized())
return ina219Sensor.runOnce() > 0; return ina219Sensor.runOnce() > 0;
return ina219Sensor.isRunning(); return ina219Sensor.isRunning();
} else if (nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_INA260] == config.power.device_battery_ina_address) { } else if (nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_INA260].first ==
config.power.device_battery_ina_address) {
if (!ina260Sensor.isInitialized()) if (!ina260Sensor.isInitialized())
return ina260Sensor.runOnce() > 0; return ina260Sensor.runOnce() > 0;
return ina260Sensor.isRunning(); return ina260Sensor.isRunning();
@@ -354,10 +389,8 @@ bool Power::analogInit()
#else #else
analogReference(AR_INTERNAL); // 3.6V analogReference(AR_INTERNAL); // 3.6V
#endif #endif
analogReadResolution(BATTERY_SENSE_RESOLUTION_BITS); // Default of 12 is not very linear. Recommended to use 10 or 11
// depending on needed resolution.
#endif // ARCH_NRF52 #endif // ARCH_NRF52
analogReadResolution(BATTERY_SENSE_RESOLUTION_BITS);
batteryLevel = &analogLevel; batteryLevel = &analogLevel;
return true; return true;
@@ -366,13 +399,15 @@ bool Power::analogInit()
#endif #endif
} }
/**
* Initializes the Power class.
*
* @return true if the setup was successful, false otherwise.
*/
bool Power::setup() bool Power::setup()
{ {
bool found = axpChipInit(); bool found = axpChipInit() || analogInit();
if (!found) {
found = analogInit();
}
enabled = found; enabled = found;
low_voltage_counter = 0; low_voltage_counter = 0;
@@ -401,9 +436,9 @@ void Power::shutdown()
ledOff(PIN_LED2); ledOff(PIN_LED2);
#endif #endif
#ifdef PIN_LED3 #ifdef PIN_LED3
ledOff(PIN_LED2); ledOff(PIN_LED3);
#endif #endif
doDeepSleep(DELAY_FOREVER); doDeepSleep(DELAY_FOREVER, false);
#endif #endif
} }
@@ -431,10 +466,25 @@ void Power::readPowerStatus()
} }
} }
OptionalBool NRF_USB = OptFalse;
#ifdef NRF_APM // Section of code detects USB power on the RAK4631 and updates the power states. Takes 20 seconds or so to detect
// changes.
nrfx_power_usb_state_t nrf_usb_state = nrfx_power_usbstatus_get();
if (nrf_usb_state == NRFX_POWER_USB_STATE_DISCONNECTED) {
powerFSM.trigger(EVENT_POWER_DISCONNECTED);
NRF_USB = OptFalse;
} else {
powerFSM.trigger(EVENT_POWER_CONNECTED);
NRF_USB = OptTrue;
}
#endif
// Notify any status instances that are observing us // Notify any status instances that are observing us
const PowerStatus powerStatus2 = const PowerStatus powerStatus2 = PowerStatus(
PowerStatus(hasBattery ? OptTrue : OptFalse, batteryLevel->isVbusIn() ? OptTrue : OptFalse, hasBattery ? OptTrue : OptFalse, batteryLevel->isVbusIn() || NRF_USB == OptTrue ? OptTrue : OptFalse,
batteryLevel->isCharging() ? OptTrue : OptFalse, batteryVoltageMv, batteryChargePercent); batteryLevel->isCharging() || NRF_USB == OptTrue ? OptTrue : OptFalse, batteryVoltageMv, batteryChargePercent);
LOG_DEBUG("Battery: usbPower=%d, isCharging=%d, batMv=%d, batPct=%d\n", powerStatus2.getHasUSB(), LOG_DEBUG("Battery: usbPower=%d, isCharging=%d, batMv=%d, batPct=%d\n", powerStatus2.getHasUSB(),
powerStatus2.getIsCharging(), powerStatus2.getBatteryVoltageMv(), powerStatus2.getBatteryChargePercent()); powerStatus2.getIsCharging(), powerStatus2.getBatteryVoltageMv(), powerStatus2.getBatteryChargePercent());
newStatus.notifyObservers(&powerStatus2); newStatus.notifyObservers(&powerStatus2);
@@ -540,10 +590,12 @@ int32_t Power::runOnce()
LOG_DEBUG("Battery removed\n"); LOG_DEBUG("Battery removed\n");
} }
*/ */
#ifndef T_WATCH_S3 // FIXME - why is this triggering on the T-Watch S3?
if (PMU->isPekeyLongPressIrq()) { if (PMU->isPekeyLongPressIrq()) {
LOG_DEBUG("PEK long button press\n"); LOG_DEBUG("PEK long button press\n");
screen->setOn(false); screen->setOn(false);
} }
#endif
PMU->clearIrqStatus(); PMU->clearIrqStatus();
} }
@@ -681,7 +733,8 @@ bool Power::axpChipInit()
// GNSS VDD 3300mV // GNSS VDD 3300mV
PMU->setPowerChannelVoltage(XPOWERS_ALDO3, 3300); PMU->setPowerChannelVoltage(XPOWERS_ALDO3, 3300);
PMU->enablePowerOutput(XPOWERS_ALDO3); PMU->enablePowerOutput(XPOWERS_ALDO3);
} else if (HW_VENDOR == meshtastic_HardwareModel_LILYGO_TBEAM_S3_CORE) { } else if (HW_VENDOR == meshtastic_HardwareModel_LILYGO_TBEAM_S3_CORE ||
HW_VENDOR == meshtastic_HardwareModel_T_WATCH_S3) {
// t-beam s3 core // t-beam s3 core
/** /**
* gnss module power channel * gnss module power channel
@@ -716,6 +769,12 @@ bool Power::axpChipInit()
PMU->setPowerChannelVoltage(XPOWERS_BLDO1, 3300); PMU->setPowerChannelVoltage(XPOWERS_BLDO1, 3300);
PMU->enablePowerOutput(XPOWERS_BLDO1); PMU->enablePowerOutput(XPOWERS_BLDO1);
#ifdef T_WATCH_S3
// DRV2605 power channel
PMU->setPowerChannelVoltage(XPOWERS_BLDO2, 3300);
PMU->enablePowerOutput(XPOWERS_BLDO2);
#endif
// PMU->setPowerChannelVoltage(XPOWERS_DCDC4, 3300); // PMU->setPowerChannelVoltage(XPOWERS_DCDC4, 3300);
// PMU->enablePowerOutput(XPOWERS_DCDC4); // PMU->enablePowerOutput(XPOWERS_DCDC4);
@@ -839,4 +898,4 @@ bool Power::axpChipInit()
#else #else
return false; return false;
#endif #endif
} }
+28 -15
View File
@@ -1,5 +1,13 @@
/**
* @file PowerFSM.cpp
* @brief Implements the finite state machine for power management.
*
* This file contains the implementation of the finite state machine (FSM) for power management.
* The FSM controls the power states of the device, including SDS (shallow deep sleep), LS (light sleep),
* NB (normal mode), and POWER (powered mode). The FSM also handles transitions between states and
* actions to be taken upon entering or exiting each state.
*/
#include "PowerFSM.h" #include "PowerFSM.h"
#include "GPS.h"
#include "MeshService.h" #include "MeshService.h"
#include "NodeDB.h" #include "NodeDB.h"
#include "configuration.h" #include "configuration.h"
@@ -37,7 +45,7 @@ static void sdsEnter()
{ {
LOG_DEBUG("Enter state: SDS\n"); LOG_DEBUG("Enter state: SDS\n");
// FIXME - make sure GPS and LORA radio are off first - because we want close to zero current draw // FIXME - make sure GPS and LORA radio are off first - because we want close to zero current draw
doDeepSleep(getConfiguredOrDefaultMs(config.power.sds_secs)); doDeepSleep(getConfiguredOrDefaultMs(config.power.sds_secs), false);
} }
extern Power *power; extern Power *power;
@@ -128,16 +136,16 @@ static void lsIdle()
static void lsExit() static void lsExit()
{ {
LOG_INFO("Exit state: LS\n"); LOG_INFO("Exit state: LS\n");
// setGPSPower(true); // restore GPS power
if (gps)
gps->forceWake(true);
} }
static void nbEnter() static void nbEnter()
{ {
LOG_DEBUG("Enter state: NB\n"); LOG_DEBUG("Enter state: NB\n");
screen->setOn(false); screen->setOn(false);
#ifdef ARCH_ESP32
// Only ESP32 should turn off bluetooth
setBluetoothEnable(false); setBluetoothEnable(false);
#endif
// FIXME - check if we already have packets for phone and immediately trigger EVENT_PACKETS_FOR_PHONE // FIXME - check if we already have packets for phone and immediately trigger EVENT_PACKETS_FOR_PHONE
} }
@@ -158,12 +166,14 @@ static void serialEnter()
static void serialExit() static void serialExit()
{ {
// Turn bluetooth back on when we leave serial stream API
setBluetoothEnable(true);
screen->print("Serial disconnected\n"); screen->print("Serial disconnected\n");
} }
static void powerEnter() static void powerEnter()
{ {
LOG_DEBUG("Enter state: POWER\n"); // LOG_DEBUG("Enter state: POWER\n");
if (!isPowered()) { if (!isPowered()) {
// If we got here, we are in the wrong state - we should be in powered, let that state ahndle things // If we got here, we are in the wrong state - we should be in powered, let that state ahndle things
LOG_INFO("Loss of power in Powered\n"); LOG_INFO("Loss of power in Powered\n");
@@ -235,6 +245,8 @@ Fsm powerFSM(&stateBOOT);
void PowerFSM_setup() void PowerFSM_setup()
{ {
bool isRouter = (config.device.role == meshtastic_Config_DeviceConfig_Role_ROUTER ? 1 : 0); bool isRouter = (config.device.role == meshtastic_Config_DeviceConfig_Role_ROUTER ? 1 : 0);
bool isTrackerOrSensor = config.device.role == meshtastic_Config_DeviceConfig_Role_TRACKER ||
config.device.role == meshtastic_Config_DeviceConfig_Role_SENSOR;
bool hasPower = isPowered(); bool hasPower = isPowered();
LOG_INFO("PowerFSM init, USB power=%d\n", hasPower ? 1 : 0); LOG_INFO("PowerFSM init, USB power=%d\n", hasPower ? 1 : 0);
@@ -242,7 +254,11 @@ void PowerFSM_setup()
// wake timer expired or a packet arrived // wake timer expired or a packet arrived
// if we are a router node, we go to NB (no need for bluetooth) otherwise we go to DARK (so we can send message to phone) // if we are a router node, we go to NB (no need for bluetooth) otherwise we go to DARK (so we can send message to phone)
#ifdef ARCH_ESP32
powerFSM.add_transition(&stateLS, isRouter ? &stateNB : &stateDARK, EVENT_WAKE_TIMER, NULL, "Wake timer"); powerFSM.add_transition(&stateLS, isRouter ? &stateNB : &stateDARK, EVENT_WAKE_TIMER, NULL, "Wake timer");
#else // Don't go into a no-bluetooth state on low power platforms
powerFSM.add_transition(&stateLS, &stateDARK, EVENT_WAKE_TIMER, NULL, "Wake timer");
#endif
// We need this transition, because we might not transition if we were waiting to enter light-sleep, because when we wake from // We need this transition, because we might not transition if we were waiting to enter light-sleep, because when we wake from
// light sleep we _always_ transition to NB or dark and // light sleep we _always_ transition to NB or dark and
@@ -279,7 +295,8 @@ void PowerFSM_setup()
powerFSM.add_transition(&stateLS, &stateON, EVENT_INPUT, NULL, "Input Device"); powerFSM.add_transition(&stateLS, &stateON, EVENT_INPUT, NULL, "Input Device");
powerFSM.add_transition(&stateNB, &stateON, EVENT_INPUT, NULL, "Input Device"); powerFSM.add_transition(&stateNB, &stateON, EVENT_INPUT, NULL, "Input Device");
powerFSM.add_transition(&stateDARK, &stateON, EVENT_INPUT, NULL, "Input Device"); powerFSM.add_transition(&stateDARK, &stateON, EVENT_INPUT, NULL, "Input Device");
powerFSM.add_transition(&stateON, &stateON, EVENT_INPUT, NULL, "Input Device"); // restarts the sleep timer powerFSM.add_transition(&stateON, &stateON, EVENT_INPUT, NULL, "Input Device"); // restarts the sleep timer
powerFSM.add_transition(&statePOWER, &statePOWER, EVENT_INPUT, NULL, "Input Device"); // restarts the sleep timer
powerFSM.add_transition(&stateDARK, &stateON, EVENT_BLUETOOTH_PAIR, NULL, "Bluetooth pairing"); powerFSM.add_transition(&stateDARK, &stateON, EVENT_BLUETOOTH_PAIR, NULL, "Bluetooth pairing");
powerFSM.add_transition(&stateON, &stateON, EVENT_BLUETOOTH_PAIR, NULL, "Bluetooth pairing"); powerFSM.add_transition(&stateON, &stateON, EVENT_BLUETOOTH_PAIR, NULL, "Bluetooth pairing");
@@ -333,12 +350,12 @@ void PowerFSM_setup()
getConfiguredOrDefaultMs(config.display.screen_on_secs, default_screen_on_secs), NULL, getConfiguredOrDefaultMs(config.display.screen_on_secs, default_screen_on_secs), NULL,
"Screen-on timeout"); "Screen-on timeout");
// We never enter light-sleep or NB states on NRF52 (because the CPU uses so little power normally)
#ifdef ARCH_ESP32 #ifdef ARCH_ESP32
State *lowPowerState = &stateLS;
// We never enter light-sleep or NB states on NRF52 (because the CPU uses so little power normally)
// See: https://github.com/meshtastic/firmware/issues/1071 // See: https://github.com/meshtastic/firmware/issues/1071
if (isRouter || config.power.is_power_saving) { // Don't add power saving transitions if we are a power saving tracker or sensor. Sleep will be initiatiated through the
// modules
if ((isRouter || config.power.is_power_saving) && !isTrackerOrSensor) {
powerFSM.add_timed_transition(&stateNB, &stateLS, powerFSM.add_timed_transition(&stateNB, &stateLS,
getConfiguredOrDefaultMs(config.power.min_wake_secs, default_min_wake_secs), NULL, getConfiguredOrDefaultMs(config.power.min_wake_secs, default_min_wake_secs), NULL,
"Min wake timeout"); "Min wake timeout");
@@ -346,10 +363,6 @@ void PowerFSM_setup()
getConfiguredOrDefaultMs(config.power.wait_bluetooth_secs, default_wait_bluetooth_secs), getConfiguredOrDefaultMs(config.power.wait_bluetooth_secs, default_wait_bluetooth_secs),
NULL, "Bluetooth timeout"); NULL, "Bluetooth timeout");
} }
if (config.power.sds_secs != UINT32_MAX)
powerFSM.add_timed_transition(lowPowerState, &stateSDS, getConfiguredOrDefaultMs(config.power.sds_secs), NULL,
"mesh timeout");
#endif #endif
powerFSM.run_machine(); // run one iteration of the state machine, so we run our on enter tasks for the initial DARK state powerFSM.run_machine(); // run one iteration of the state machine, so we run our on enter tasks for the initial DARK state
+2 -2
View File
@@ -21,7 +21,7 @@ class PowerFSMThread : public OSThread
/// If we are in power state we force the CPU to wake every 10ms to check for serial characters (we don't yet wake /// If we are in power state we force the CPU to wake every 10ms to check for serial characters (we don't yet wake
/// cpu for serial rx - FIXME) /// cpu for serial rx - FIXME)
auto state = powerFSM.getState(); const State *state = powerFSM.getState();
canSleep = (state != &statePOWER) && (state != &stateSERIAL); canSleep = (state != &statePOWER) && (state != &stateSERIAL);
if (powerStatus->getHasUSB()) { if (powerStatus->getHasUSB()) {
@@ -33,7 +33,7 @@ class PowerFSMThread : public OSThread
powerFSM.trigger(EVENT_SHUTDOWN); powerFSM.trigger(EVENT_SHUTDOWN);
} }
return 10; return 100;
} }
}; };
+35 -3
View File
@@ -10,6 +10,10 @@
#include <sys/time.h> #include <sys/time.h>
#include <time.h> #include <time.h>
#ifdef ARCH_PORTDUINO
#include "platform/portduino/PortduinoGlue.h"
#endif
/** /**
* A printer that doesn't go anywhere * A printer that doesn't go anywhere
*/ */
@@ -18,6 +22,12 @@ NoopPrint noopPrint;
#if HAS_WIFI || HAS_ETHERNET #if HAS_WIFI || HAS_ETHERNET
extern Syslog syslog; extern Syslog syslog;
#endif #endif
void RedirectablePrint::rpInit()
{
#ifdef HAS_FREE_RTOS
inDebugPrint = xSemaphoreCreateMutexStatic(&this->_MutexStorageSpace);
#endif
}
void RedirectablePrint::setDestination(Print *_dest) void RedirectablePrint::setDestination(Print *_dest)
{ {
@@ -62,13 +72,24 @@ size_t RedirectablePrint::vprintf(const char *format, va_list arg)
size_t RedirectablePrint::log(const char *logLevel, const char *format, ...) size_t RedirectablePrint::log(const char *logLevel, const char *format, ...)
{ {
if (moduleConfig.serial.override_console_serial_port && strcmp(logLevel, "DEBUG") == 0) { #ifdef ARCH_PORTDUINO
if (settingsMap[logoutputlevel] < level_debug && strcmp(logLevel, MESHTASTIC_LOG_LEVEL_DEBUG) == 0)
return 0;
else if (settingsMap[logoutputlevel] < level_info && strcmp(logLevel, MESHTASTIC_LOG_LEVEL_INFO) == 0)
return 0;
else if (settingsMap[logoutputlevel] < level_warn && strcmp(logLevel, MESHTASTIC_LOG_LEVEL_WARN) == 0)
return 0;
#endif
if (moduleConfig.serial.override_console_serial_port && strcmp(logLevel, MESHTASTIC_LOG_LEVEL_DEBUG) == 0) {
return 0; return 0;
} }
size_t r = 0; size_t r = 0;
#ifdef HAS_FREE_RTOS
if (inDebugPrint != nullptr && xSemaphoreTake(inDebugPrint, portMAX_DELAY) == pdTRUE) {
#else
if (!inDebugPrint) { if (!inDebugPrint) {
inDebugPrint = true; inDebugPrint = true;
#endif
va_list arg; va_list arg;
va_start(arg, format); va_start(arg, format);
@@ -90,10 +111,17 @@ size_t RedirectablePrint::log(const char *logLevel, const char *format, ...)
int hour = hms / SEC_PER_HOUR; int hour = hms / SEC_PER_HOUR;
int min = (hms % SEC_PER_HOUR) / SEC_PER_MIN; int min = (hms % SEC_PER_HOUR) / SEC_PER_MIN;
int sec = (hms % SEC_PER_HOUR) % SEC_PER_MIN; // or hms % SEC_PER_MIN int sec = (hms % SEC_PER_HOUR) % SEC_PER_MIN; // or hms % SEC_PER_MIN
#ifdef ARCH_PORTDUINO
r += ::printf("%s | %02d:%02d:%02d %u ", logLevel, hour, min, sec, millis() / 1000);
#else
r += printf("%s | %02d:%02d:%02d %u ", logLevel, hour, min, sec, millis() / 1000); r += printf("%s | %02d:%02d:%02d %u ", logLevel, hour, min, sec, millis() / 1000);
#endif
} else } else
#ifdef ARCH_PORTDUINO
r += ::printf("%s | ??:??:?? %u ", logLevel, millis() / 1000);
#else
r += printf("%s | ??:??:?? %u ", logLevel, millis() / 1000); r += printf("%s | ??:??:?? %u ", logLevel, millis() / 1000);
#endif
auto thread = concurrency::OSThread::currentThread; auto thread = concurrency::OSThread::currentThread;
if (thread) { if (thread) {
@@ -141,7 +169,11 @@ size_t RedirectablePrint::log(const char *logLevel, const char *format, ...)
va_end(arg); va_end(arg);
isContinuationMessage = !hasNewline; isContinuationMessage = !hasNewline;
#ifdef HAS_FREE_RTOS
xSemaphoreGive(inDebugPrint);
#else
inDebugPrint = false; inDebugPrint = false;
#endif
} }
return r; return r;
+8 -2
View File
@@ -1,5 +1,6 @@
#pragma once #pragma once
#include "../freertosinc.h"
#include <Print.h> #include <Print.h>
#include <stdarg.h> #include <stdarg.h>
#include <string> #include <string>
@@ -16,14 +17,19 @@ class RedirectablePrint : public Print
/// Used to allow multiple logDebug messages to appear on a single log line /// Used to allow multiple logDebug messages to appear on a single log line
bool isContinuationMessage = false; bool isContinuationMessage = false;
#ifdef HAS_FREE_RTOS
SemaphoreHandle_t inDebugPrint = nullptr;
StaticSemaphore_t _MutexStorageSpace;
#else
volatile bool inDebugPrint = false; volatile bool inDebugPrint = false;
#endif
public: public:
explicit RedirectablePrint(Print *_dest) : dest(_dest) {} explicit RedirectablePrint(Print *_dest) : dest(_dest) {}
/** /**
* Set a new destination * Set a new destination
*/ */
void rpInit();
void setDestination(Print *dest); void setDestination(Print *dest);
virtual size_t write(uint8_t c); virtual size_t write(uint8_t c);
@@ -54,4 +60,4 @@ class NoopPrint : public Print
/** /**
* A printer that doesn't go anywhere * A printer that doesn't go anywhere
*/ */
extern NoopPrint noopPrint; extern NoopPrint noopPrint;
+1
View File
@@ -12,6 +12,7 @@ SerialConsole *console;
void consoleInit() void consoleInit()
{ {
new SerialConsole(); // Must be dynamically allocated because we are now inheriting from thread new SerialConsole(); // Must be dynamically allocated because we are now inheriting from thread
DEBUG_PORT.rpInit(); // Simply sets up semaphore
} }
void consolePrintf(const char *format, ...) void consolePrintf(const char *format, ...)
+2
View File
@@ -15,4 +15,6 @@ enum class Cmd {
PRINT, PRINT,
START_SHUTDOWN_SCREEN, START_SHUTDOWN_SCREEN,
START_REBOOT_SCREEN, START_REBOOT_SCREEN,
SHOW_PREV_FRAME,
SHOW_NEXT_FRAME
}; };
+3 -2
View File
@@ -53,7 +53,7 @@ class OSThread : public Thread
static void setup(); static void setup();
int32_t disable(); virtual int32_t disable();
/** /**
* Wait a specified number msecs starting from the current time (rather than the last time we were run) * Wait a specified number msecs starting from the current time (rather than the last time we were run)
@@ -67,6 +67,7 @@ class OSThread : public Thread
* Returns desired period for next invocation (or RUN_SAME for no change) * Returns desired period for next invocation (or RUN_SAME for no change)
*/ */
virtual int32_t runOnce() = 0; virtual int32_t runOnce() = 0;
bool sleepOnNextExecution = false;
// Do not override this // Do not override this
virtual void run(); virtual void run();
@@ -87,4 +88,4 @@ extern bool hasBeenSetup;
void assertIsSetup(); void assertIsSetup();
} // namespace concurrency } // namespace concurrency
+21 -5
View File
@@ -57,8 +57,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define REQUIRE_RADIO true // If true, we will fail to start if the radio is not found #define REQUIRE_RADIO true // If true, we will fail to start if the radio is not found
/// Convert a preprocessor name into a quoted string /// Convert a preprocessor name into a quoted string
#define xstr(s) str(s) #define xstr(s) ystr(s)
#define str(s) #s #define ystr(s) #s
/// Convert a preprocessor name into a quoted string and if that string is empty use "unset" /// Convert a preprocessor name into a quoted string and if that string is empty use "unset"
#define optstr(s) (xstr(s)[0] ? xstr(s) : "unset") #define optstr(s) (xstr(s)[0] ? xstr(s) : "unset")
@@ -98,8 +98,10 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
// Define if screen should be mirrored left to right // Define if screen should be mirrored left to right
// #define SCREEN_MIRROR // #define SCREEN_MIRROR
// The m5stack I2C Keyboard (also RAK14004) // I2C Keyboards (M5Stack, RAK14004, T-Deck)
#define CARDKB_ADDR 0x5F #define CARDKB_ADDR 0x5F
#define TDECK_KB_ADDR 0x55
#define BBQ10_KB_ADDR 0x1F
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// SENSOR // SENSOR
@@ -109,6 +111,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define MCP9808_ADDR 0x18 #define MCP9808_ADDR 0x18
#define INA_ADDR 0x40 #define INA_ADDR 0x40
#define INA_ADDR_ALTERNATE 0x41 #define INA_ADDR_ALTERNATE 0x41
#define INA3221_ADDR 0x42
#define QMC6310_ADDR 0x1C #define QMC6310_ADDR 0x1C
#define QMI8658_ADDR 0x6B #define QMI8658_ADDR 0x6B
#define QMC5883L_ADDR 0x1E #define QMC5883L_ADDR 0x1E
@@ -123,6 +126,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
#define MPU6050_ADDR 0x68 #define MPU6050_ADDR 0x68
#define LIS3DH_ADR 0x18 #define LIS3DH_ADR 0x18
#define BMA423_ADDR 0x19
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// LED // LED
@@ -142,9 +146,12 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define GPS_BAUDRATE 9600 #define GPS_BAUDRATE 9600
#ifndef GPS_THREAD_INTERVAL #ifndef GPS_THREAD_INTERVAL
#define GPS_THREAD_INTERVAL 100 #define GPS_THREAD_INTERVAL 200
#endif #endif
// convert 24-bit color to 16-bit (56K)
#define COLOR565(r, g, b) (((r & 0xF8) << 8) | ((g & 0xFC) << 3) | ((b & 0xF8) >> 3))
/* Step #1: offer chance for variant-specific defines */ /* Step #1: offer chance for variant-specific defines */
#include "variant.h" #include "variant.h"
@@ -172,9 +179,18 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifndef HAS_BUTTON #ifndef HAS_BUTTON
#define HAS_BUTTON 0 #define HAS_BUTTON 0
#endif #endif
#ifndef HAS_TRACKBALL
#define HAS_TRACKBALL 0
#endif
#ifndef HAS_TOUCHSCREEN
#define HAS_TOUCHSCREEN 0
#endif
#ifndef HAS_TELEMETRY #ifndef HAS_TELEMETRY
#define HAS_TELEMETRY 0 #define HAS_TELEMETRY 0
#endif #endif
#ifndef HAS_SENSOR
#define HAS_SENSOR 0
#endif
#ifndef HAS_RADIO #ifndef HAS_RADIO
#define HAS_RADIO 0 #define HAS_RADIO 0
#endif #endif
@@ -193,4 +209,4 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifndef HW_VENDOR #ifndef HW_VENDOR
#error HW_VENDOR must be defined #error HW_VENDOR must be defined
#endif #endif
+5 -5
View File
@@ -30,14 +30,14 @@ ScanI2C::FoundDevice ScanI2C::firstRTC() const
ScanI2C::FoundDevice ScanI2C::firstKeyboard() const ScanI2C::FoundDevice ScanI2C::firstKeyboard() const
{ {
ScanI2C::DeviceType types[] = {CARDKB, RAK14004}; ScanI2C::DeviceType types[] = {CARDKB, TDECKKB, BBQ10KB, RAK14004};
return firstOfOrNONE(2, types); return firstOfOrNONE(4, types);
} }
ScanI2C::FoundDevice ScanI2C::firstAccelerometer() const ScanI2C::FoundDevice ScanI2C::firstAccelerometer() const
{ {
ScanI2C::DeviceType types[] = {MPU6050, LIS3DH}; ScanI2C::DeviceType types[] = {MPU6050, LIS3DH, BMA423};
return firstOfOrNONE(2, types); return firstOfOrNONE(3, types);
} }
ScanI2C::FoundDevice ScanI2C::find(ScanI2C::DeviceType) const ScanI2C::FoundDevice ScanI2C::find(ScanI2C::DeviceType) const
@@ -73,4 +73,4 @@ bool ScanI2C::DeviceAddress::operator<(const ScanI2C::DeviceAddress &other) cons
|| (port != NO_I2C && other.port != NO_I2C && (address < other.address)); || (port != NO_I2C && other.port != NO_I2C && (address < other.address));
} }
ScanI2C::FoundDevice::FoundDevice(ScanI2C::DeviceType type, ScanI2C::DeviceAddress address) : type(type), address(address) {} ScanI2C::FoundDevice::FoundDevice(ScanI2C::DeviceType type, ScanI2C::DeviceAddress address) : type(type), address(address) {}
+4
View File
@@ -16,6 +16,8 @@ class ScanI2C
RTC_RV3028, RTC_RV3028,
RTC_PCF8563, RTC_PCF8563,
CARDKB, CARDKB,
TDECKKB,
BBQ10KB,
RAK14004, RAK14004,
PMU_AXP192_AXP2101, PMU_AXP192_AXP2101,
BME_680, BME_680,
@@ -23,6 +25,7 @@ class ScanI2C
BMP_280, BMP_280,
INA260, INA260,
INA219, INA219,
INA3221,
MCP9808, MCP9808,
SHT31, SHT31,
SHTC3, SHTC3,
@@ -33,6 +36,7 @@ class ScanI2C
PMSA0031, PMSA0031,
MPU6050, MPU6050,
LIS3DH, LIS3DH,
BMA423,
#ifdef HAS_NCP5623 #ifdef HAS_NCP5623
NCP5623, NCP5623,
#endif #endif
+17 -2
View File
@@ -2,7 +2,9 @@
#include "concurrency/LockGuard.h" #include "concurrency/LockGuard.h"
#include "configuration.h" #include "configuration.h"
#if defined(ARCH_PORTDUINO)
#include "linux/LinuxHardwareI2C.h"
#endif
#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL) #if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL)
#include "main.h" // atecc #include "main.h" // atecc
#endif #endif
@@ -162,7 +164,14 @@ void ScanI2CTwoWire::scanPort(I2CPort port)
for (addr.address = 1; addr.address < 127; addr.address++) { for (addr.address = 1; addr.address < 127; addr.address++) {
i2cBus->beginTransmission(addr.address); i2cBus->beginTransmission(addr.address);
#ifdef ARCH_PORTDUINO
if (i2cBus->read() != -1)
err = 0;
else
err = 2;
#else
err = i2cBus->endTransmission(); err = i2cBus->endTransmission();
#endif
type = NONE; type = NONE;
if (err == 0) { if (err == 0) {
LOG_DEBUG("I2C device found at address 0x%x\n", addr.address); LOG_DEBUG("I2C device found at address 0x%x\n", addr.address);
@@ -212,6 +221,8 @@ void ScanI2CTwoWire::scanPort(I2CPort port)
} }
break; break;
SCAN_SIMPLE_CASE(TDECK_KB_ADDR, TDECKKB, "T-Deck keyboard found\n");
SCAN_SIMPLE_CASE(BBQ10_KB_ADDR, BBQ10KB, "BB Q10 keyboard found\n");
SCAN_SIMPLE_CASE(ST7567_ADDRESS, SCREEN_ST7567, "st7567 display found\n"); SCAN_SIMPLE_CASE(ST7567_ADDRESS, SCREEN_ST7567, "st7567 display found\n");
#ifdef HAS_NCP5623 #ifdef HAS_NCP5623
SCAN_SIMPLE_CASE(NCP5623_ADDR, NCP5623, "NCP5623 RGB LED found\n"); SCAN_SIMPLE_CASE(NCP5623_ADDR, NCP5623, "NCP5623 RGB LED found\n");
@@ -249,7 +260,10 @@ void ScanI2CTwoWire::scanPort(I2CPort port)
type = INA219; type = INA219;
} }
break; break;
case INA3221_ADDR:
LOG_INFO("INA3221 sensor found at address 0x%x\n", (uint8_t)addr.address);
type = INA3221;
break;
case MCP9808_ADDR: case MCP9808_ADDR:
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x07), 2); registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x07), 2);
if (registerValue == 0x0400) { if (registerValue == 0x0400) {
@@ -274,6 +288,7 @@ void ScanI2CTwoWire::scanPort(I2CPort port)
SCAN_SIMPLE_CASE(PMSA0031_ADDR, PMSA0031, "PMSA0031 air quality sensor found\n") SCAN_SIMPLE_CASE(PMSA0031_ADDR, PMSA0031, "PMSA0031 air quality sensor found\n")
SCAN_SIMPLE_CASE(MPU6050_ADDR, MPU6050, "MPU6050 accelerometer found\n"); SCAN_SIMPLE_CASE(MPU6050_ADDR, MPU6050, "MPU6050 accelerometer found\n");
SCAN_SIMPLE_CASE(BMA423_ADDR, BMA423, "BMA423 accelerometer found\n");
default: default:
LOG_INFO("Device found at address 0x%x was not able to be enumerated\n", addr.address); LOG_INFO("Device found at address 0x%x was not able to be enumerated\n", addr.address);
+2 -2
View File
@@ -18,6 +18,8 @@ class ScanI2CTwoWire : public ScanI2C
ScanI2C::FoundDevice find(ScanI2C::DeviceType) const override; ScanI2C::FoundDevice find(ScanI2C::DeviceType) const override;
TwoWire *fetchI2CBus(ScanI2C::DeviceAddress) const;
bool exists(ScanI2C::DeviceType) const override; bool exists(ScanI2C::DeviceType) const override;
size_t countDevices() const override; size_t countDevices() const override;
@@ -51,6 +53,4 @@ class ScanI2CTwoWire : public ScanI2C
uint16_t getRegisterValue(const RegisterLocation &, ResponseWidth) const; uint16_t getRegisterValue(const RegisterLocation &, ResponseWidth) const;
DeviceType probeOLED(ScanI2C::DeviceAddress) const; DeviceType probeOLED(ScanI2C::DeviceAddress) const;
TwoWire *fetchI2CBus(ScanI2C::DeviceAddress) const;
}; };
+897 -572
View File
File diff suppressed because it is too large Load Diff
+143 -73
View File
@@ -2,7 +2,16 @@
#include "GPSStatus.h" #include "GPSStatus.h"
#include "Observer.h" #include "Observer.h"
#include "TinyGPS++.h"
#include "concurrency/OSThread.h" #include "concurrency/OSThread.h"
#include "input/RotaryEncoderInterruptImpl1.h"
#include "input/UpDownInterruptImpl1.h"
#include "modules/PositionModule.h"
// Allow defining the polarity of the ENABLE output. default is active high
#ifndef GPS_EN_ACTIVE
#define GPS_EN_ACTIVE 1
#endif
struct uBloxGnssModelInfo { struct uBloxGnssModelInfo {
char swVersion[30]; char swVersion[30];
@@ -14,10 +23,17 @@ struct uBloxGnssModelInfo {
typedef enum { typedef enum {
GNSS_MODEL_MTK, GNSS_MODEL_MTK,
GNSS_MODEL_UBLOX, GNSS_MODEL_UBLOX,
GNSS_MODEL_UC6850, GNSS_MODEL_UC6580,
GNSS_MODEL_UNKNOWN, GNSS_MODEL_UNKNOWN,
} GnssModel_t; } GnssModel_t;
typedef enum {
GNSS_RESPONSE_NONE,
GNSS_RESPONSE_NAK,
GNSS_RESPONSE_FRAME_ERRORS,
GNSS_RESPONSE_OK,
} GPS_RESPONSE;
// Generate a string representation of DOP // Generate a string representation of DOP
const char *getDOPString(uint32_t dop); const char *getDOPString(uint32_t dop);
@@ -28,26 +44,49 @@ const char *getDOPString(uint32_t dop);
*/ */
class GPS : private concurrency::OSThread class GPS : private concurrency::OSThread
{ {
TinyGPSPlus reader;
uint8_t fixQual = 0; // fix quality from GPGGA
uint32_t lastChecksumFailCount = 0;
#ifndef TINYGPS_OPTION_NO_CUSTOM_FIELDS
// (20210908) TinyGps++ can only read the GPGSA "FIX TYPE" field
// via optional feature "custom fields", currently disabled (bug #525)
TinyGPSCustom gsafixtype; // custom extract fix type from GPGSA
TinyGPSCustom gsapdop; // custom extract PDOP from GPGSA
uint8_t fixType = 0; // fix type from GPGSA
#endif
private: private:
uint32_t lastWakeStartMsec = 0, lastSleepStartMsec = 0, lastWhileActiveMsec = 0; uint32_t lastWakeStartMsec = 0, lastSleepStartMsec = 0;
const int serialSpeeds[6] = {9600, 4800, 38400, 57600, 115200, 9600};
uint32_t rx_gpio = 0;
uint32_t tx_gpio = 0;
uint32_t en_gpio = 0;
int32_t averageLockTime = 0;
uint32_t GPSCycles = 0;
int speedSelect = 0;
int probeTries = 2;
/** /**
* hasValidLocation - indicates that the position variables contain a complete * hasValidLocation - indicates that the position variables contain a complete
* GPS location, valid and fresh (< gps_update_interval + gps_attempt_time) * GPS location, valid and fresh (< gps_update_interval + position_broadcast_secs)
*/ */
bool hasValidLocation = false; // default to false, until we complete our first read bool hasValidLocation = false; // default to false, until we complete our first read
bool isAwake = false; // true if we want a location right now bool isAwake = false; // true if we want a location right now
bool wakeAllowed = true; // false if gps must be forced to sleep regardless of what time it is bool isInPowersave = false;
bool shouldPublish = false; // If we've changed GPS state, this will force a publish the next loop() bool shouldPublish = false; // If we've changed GPS state, this will force a publish the next loop()
bool hasGPS = false; // Do we have a GPS we are talking to bool hasGPS = false; // Do we have a GPS we are talking to
bool GPSInitFinished = false; // Init thread finished?
bool GPSInitStarted = false; // Init thread finished?
uint8_t numSatellites = 0; uint8_t numSatellites = 0;
CallbackObserver<GPS, void *> notifySleepObserver = CallbackObserver<GPS, void *>(this, &GPS::prepareSleep);
CallbackObserver<GPS, void *> notifyDeepSleepObserver = CallbackObserver<GPS, void *>(this, &GPS::prepareDeepSleep); CallbackObserver<GPS, void *> notifyDeepSleepObserver = CallbackObserver<GPS, void *>(this, &GPS::prepareDeepSleep);
CallbackObserver<GPS, void *> notifyGPSSleepObserver = CallbackObserver<GPS, void *>(this, &GPS::prepareDeepSleep); CallbackObserver<GPS, void *> notifyGPSSleepObserver = CallbackObserver<GPS, void *>(this, &GPS::prepareDeepSleep);
@@ -55,6 +94,29 @@ class GPS : private concurrency::OSThread
/** If !NULL we will use this serial port to construct our GPS */ /** If !NULL we will use this serial port to construct our GPS */
static HardwareSerial *_serial_gps; static HardwareSerial *_serial_gps;
static uint8_t _message_PMREQ[];
static uint8_t _message_PMREQ_10[];
static const uint8_t _message_CFG_RXM_PSM[];
static const uint8_t _message_CFG_RXM_ECO[];
static const uint8_t _message_CFG_PM2[];
static const uint8_t _message_GNSS_7[];
static const uint8_t _message_GNSS_8[];
static const uint8_t _message_JAM_6_7[];
static const uint8_t _message_JAM_8[];
static const uint8_t _message_NAVX5[];
static const uint8_t _message_NAVX5_8[];
static const uint8_t _message_NMEA[];
static const uint8_t _message_1HZ[];
static const uint8_t _message_GLL[];
static const uint8_t _message_GSA[];
static const uint8_t _message_GSV[];
static const uint8_t _message_VTG[];
static const uint8_t _message_RMC[];
static const uint8_t _message_AID[];
static const uint8_t _message_GGA[];
static const uint8_t _message_PMS[];
static const uint8_t _message_SAVE[];
meshtastic_Position p = meshtastic_Position_init_default; meshtastic_Position p = meshtastic_Position_init_default;
GPS() : concurrency::OSThread("GPS") {} GPS() : concurrency::OSThread("GPS") {}
@@ -69,6 +131,17 @@ class GPS : private concurrency::OSThread
*/ */
virtual bool setup(); virtual bool setup();
// re-enable the thread
void enable();
// Disable the thread
int32_t disable() override;
// toggle between enabled/disabled
void toggleGpsMode();
void setGPSPower(bool on, bool standbyOnly, uint32_t sleepTime);
/// Returns true if we have acquired GPS lock. /// Returns true if we have acquired GPS lock.
virtual bool hasLock(); virtual bool hasLock();
@@ -78,70 +151,22 @@ class GPS : private concurrency::OSThread
/// Return true if we are connected to a GPS /// Return true if we are connected to a GPS
bool isConnected() const { return hasGPS; } bool isConnected() const { return hasGPS; }
bool isPowerSaving() const { return !config.position.gps_enabled; } bool isPowerSaving() const { return config.position.gps_mode != meshtastic_Config_PositionConfig_GpsMode_ENABLED; }
/** // Empty the input buffer as quickly as possible
* Restart our lock attempt - try to get and broadcast a GPS reading ASAP void clearBuffer();
* called after the CPU wakes from light-sleep state
*
* Or set to false, to disallow any sort of waking
* */
void forceWake(bool on);
// Some GPS modules (ublock) require factory reset // Create a ublox packet for editing in memory
virtual bool factoryReset() { return true; } uint8_t makeUBXPacket(uint8_t class_id, uint8_t msg_id, uint8_t payload_size, const uint8_t *msg);
protected: // scratch space for creating ublox packets
/// Do gps chipset specific init, return true for success uint8_t UBXscratch[250] = {0};
virtual bool setupGPS();
/// If possible force the GPS into sleep/low power mode int rebootsSeen = 0;
virtual void sleep();
/// wake the GPS into normal operation mode int getACK(uint8_t *buffer, uint16_t size, uint8_t requestedClass, uint8_t requestedID, uint32_t waitMillis);
virtual void wake(); GPS_RESPONSE getACK(uint8_t c, uint8_t i, uint32_t waitMillis);
GPS_RESPONSE getACK(const char *message, uint32_t waitMillis);
/** Subclasses should look for serial rx characters here and feed it to their GPS parser
*
* Return true if we received a valid message from the GPS
*/
virtual bool whileIdle() = 0;
/** Idle processing while GPS is looking for lock, called once per secondish */
virtual void whileActive() {}
/**
* Perform any processing that should be done only while the GPS is awake and looking for a fix.
* Override this method to check for new locations
*
* @return true if we've acquired a time
*/
virtual bool lookForTime() = 0;
/**
* Perform any processing that should be done only while the GPS is awake and looking for a fix.
* Override this method to check for new locations
*
* @return true if we've acquired a new location
*/
virtual bool lookForLocation() = 0;
/// Record that we have a GPS
void setConnected();
void setNumSatellites(uint8_t n);
private:
/// Prepare the GPS for the cpu entering deep or light sleep, expect to be gone for at least 100s of msecs
/// always returns 0 to indicate okay to sleep
int prepareSleep(void *unused);
/// Prepare the GPS for the cpu entering deep sleep, expect to be gone for at least 100s of msecs
/// always returns 0 to indicate okay to sleep
int prepareDeepSleep(void *unused);
// Calculate checksum
void UBXChecksum(byte *message, size_t length);
/** /**
* Switch the GPS into a mode where we are actively looking for a lock, or alternatively switch GPS into a low power mode * Switch the GPS into a mode where we are actively looking for a lock, or alternatively switch GPS into a low power mode
@@ -149,6 +174,59 @@ class GPS : private concurrency::OSThread
* calls sleep/wake * calls sleep/wake
*/ */
void setAwake(bool on); void setAwake(bool on);
virtual bool factoryReset();
// Creates an instance of the GPS class.
// Returns the new instance or null if the GPS is not present.
static GPS *createGps();
protected:
/**
* Perform any processing that should be done only while the GPS is awake and looking for a fix.
* Override this method to check for new locations
*
* @return true if we've acquired a time
*/
/**
* Perform any processing that should be done only while the GPS is awake and looking for a fix.
* Override this method to check for new locations
*
* @return true if we've acquired a new location
*/
/// Record that we have a GPS
void setConnected();
/** Subclasses should look for serial rx characters here and feed it to their GPS parser
*
* Return true if we received a valid message from the GPS
*/
virtual bool whileIdle();
/**
* Perform any processing that should be done only while the GPS is awake and looking for a fix.
* Override this method to check for new locations
*
* @return true if we've acquired a time
*/
virtual bool lookForTime();
/**
* Perform any processing that should be done only while the GPS is awake and looking for a fix.
* Override this method to check for new locations
*
* @return true if we've acquired a new location
*/
virtual bool lookForLocation();
private:
/// Prepare the GPS for the cpu entering deep sleep, expect to be gone for at least 100s of msecs
/// always returns 0 to indicate okay to sleep
int prepareDeepSleep(void *unused);
// Calculate checksum
void UBXChecksum(uint8_t *message, size_t length);
/** Get how long we should stay looking for each aquisition /** Get how long we should stay looking for each aquisition
*/ */
@@ -158,8 +236,6 @@ class GPS : private concurrency::OSThread
*/ */
uint32_t getSleepTime() const; uint32_t getSleepTime() const;
bool getACK(uint8_t c, uint8_t i);
/** /**
* Tell users we have new GPS readings * Tell users we have new GPS readings
*/ */
@@ -169,9 +245,7 @@ class GPS : private concurrency::OSThread
// Get GNSS model // Get GNSS model
String getNMEA(); String getNMEA();
GnssModel_t probe(); GnssModel_t probe(int serialSpeed);
int getAck(uint8_t *buffer, uint16_t size, uint8_t requestedClass, uint8_t requestedID);
// delay counter to allow more sats before fixed position stops GPS thread // delay counter to allow more sats before fixed position stops GPS thread
uint8_t fixeddelayCtr = 0; uint8_t fixeddelayCtr = 0;
@@ -180,8 +254,4 @@ class GPS : private concurrency::OSThread
GnssModel_t gnssModel = GNSS_MODEL_UNKNOWN; GnssModel_t gnssModel = GNSS_MODEL_UNKNOWN;
}; };
// Creates an instance of the GPS class.
// Returns the new instance or null if the GPS is not present.
GPS *createGps();
extern GPS *gps; extern GPS *gps;
-255
View File
@@ -1,255 +0,0 @@
#include "NMEAGPS.h"
#include "RTC.h"
#include "configuration.h"
#include <TinyGPS++.h>
// GPS solutions older than this will be rejected - see TinyGPSDatum::age()
#define GPS_SOL_EXPIRY_MS 5000 // in millis. give 1 second time to combine different sentences. NMEA Frequency isn't higher anyway
#define NMEA_MSG_GXGSA "GNGSA" // GSA message (GPGSA, GNGSA etc)
static int32_t toDegInt(RawDegrees d)
{
int32_t degMult = 10000000; // 1e7
int32_t r = d.deg * degMult + d.billionths / 100;
if (d.negative)
r *= -1;
return r;
}
bool NMEAGPS::factoryReset()
{
#ifdef PIN_GPS_REINIT
// The L76K GNSS on the T-Echo requires the RESET pin to be pulled LOW
digitalWrite(PIN_GPS_REINIT, 0);
pinMode(PIN_GPS_REINIT, OUTPUT);
delay(150); // The L76K datasheet calls for at least 100MS delay
digitalWrite(PIN_GPS_REINIT, 1);
#endif
// send the UBLOX Factory Reset Command regardless of detect state, something is very wrong, just assume it's UBLOX.
// Factory Reset
byte _message_reset[] = {0xB5, 0x62, 0x06, 0x09, 0x0D, 0x00, 0xFF, 0xFB, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x17, 0x2B, 0x7E};
_serial_gps->write(_message_reset, sizeof(_message_reset));
delay(1000);
return true;
}
bool NMEAGPS::setupGPS()
{
GPS::setupGPS();
#ifdef PIN_GPS_PPS
// pulse per second
// FIXME - move into shared GPS code
pinMode(PIN_GPS_PPS, INPUT);
#endif
// Currently disabled per issue #525 (TinyGPS++ crash bug)
// when fixed upstream, can be un-disabled to enable 3D FixType and PDOP
#ifndef TINYGPS_OPTION_NO_CUSTOM_FIELDS
// see NMEAGPS.h
gsafixtype.begin(reader, NMEA_MSG_GXGSA, 2);
gsapdop.begin(reader, NMEA_MSG_GXGSA, 15);
LOG_DEBUG("Using " NMEA_MSG_GXGSA " for 3DFIX and PDOP\n");
#else
LOG_DEBUG("GxGSA NOT available\n");
#endif
return true;
}
/**
* Perform any processing that should be done only while the GPS is awake and looking for a fix.
* Override this method to check for new locations
*
* @return true if we've acquired a new location
*/
bool NMEAGPS::lookForTime()
{
auto ti = reader.time;
auto d = reader.date;
if (ti.isValid() && d.isValid()) { // Note: we don't check for updated, because we'll only be called if needed
/* Convert to unix time
The Unix epoch (or Unix time or POSIX time or Unix timestamp) is the number of seconds that have elapsed since January 1, 1970
(midnight UTC/GMT), not counting leap seconds (in ISO 8601: 1970-01-01T00:00:00Z).
*/
struct tm t;
t.tm_sec = ti.second();
t.tm_min = ti.minute();
t.tm_hour = ti.hour();
t.tm_mday = d.day();
t.tm_mon = d.month() - 1;
t.tm_year = d.year() - 1900;
t.tm_isdst = false;
if (t.tm_mon > -1) {
LOG_DEBUG("NMEA GPS time %02d-%02d-%02d %02d:%02d:%02d\n", d.year(), d.month(), t.tm_mday, t.tm_hour, t.tm_min,
t.tm_sec);
perhapsSetRTC(RTCQualityGPS, t);
return true;
} else
return false;
} else
return false;
}
/**
* Perform any processing that should be done only while the GPS is awake and looking for a fix.
* Override this method to check for new locations
*
* @return true if we've acquired a new location
*/
bool NMEAGPS::lookForLocation()
{
// By default, TinyGPS++ does not parse GPGSA lines, which give us
// the 2D/3D fixType (see NMEAGPS.h)
// At a minimum, use the fixQuality indicator in GPGGA (FIXME?)
fixQual = reader.fixQuality();
#ifndef TINYGPS_OPTION_NO_CUSTOM_FIELDS
fixType = atoi(gsafixtype.value()); // will set to zero if no data
// LOG_DEBUG("FIX QUAL=%d, TYPE=%d\n", fixQual, fixType);
#endif
// check if GPS has an acceptable lock
if (!hasLock())
return false;
#ifdef GPS_EXTRAVERBOSE
LOG_DEBUG("AGE: LOC=%d FIX=%d DATE=%d TIME=%d\n", reader.location.age(),
#ifndef TINYGPS_OPTION_NO_CUSTOM_FIELDS
gsafixtype.age(),
#else
0,
#endif
reader.date.age(), reader.time.age());
#endif // GPS_EXTRAVERBOSE
// check if a complete GPS solution set is available for reading
// tinyGPSDatum::age() also includes isValid() test
// FIXME
if (!((reader.location.age() < GPS_SOL_EXPIRY_MS) &&
#ifndef TINYGPS_OPTION_NO_CUSTOM_FIELDS
(gsafixtype.age() < GPS_SOL_EXPIRY_MS) &&
#endif
(reader.time.age() < GPS_SOL_EXPIRY_MS) && (reader.date.age() < GPS_SOL_EXPIRY_MS))) {
LOG_WARN("SOME data is TOO OLD: LOC %u, TIME %u, DATE %u\n", reader.location.age(), reader.time.age(), reader.date.age());
return false;
}
// Is this a new point or are we re-reading the previous one?
if (!reader.location.isUpdated())
return false;
// We know the solution is fresh and valid, so just read the data
auto loc = reader.location.value();
// Bail out EARLY to avoid overwriting previous good data (like #857)
if (toDegInt(loc.lat) > 900000000) {
#ifdef GPS_EXTRAVERBOSE
LOG_DEBUG("Bail out EARLY on LAT %i\n", toDegInt(loc.lat));
#endif
return false;
}
if (toDegInt(loc.lng) > 1800000000) {
#ifdef GPS_EXTRAVERBOSE
LOG_DEBUG("Bail out EARLY on LNG %i\n", toDegInt(loc.lng));
#endif
return false;
}
p.location_source = meshtastic_Position_LocSource_LOC_INTERNAL;
// Dilution of precision (an accuracy metric) is reported in 10^2 units, so we need to scale down when we use it
#ifndef TINYGPS_OPTION_NO_CUSTOM_FIELDS
p.HDOP = reader.hdop.value();
p.PDOP = TinyGPSPlus::parseDecimal(gsapdop.value());
// LOG_DEBUG("PDOP=%d, HDOP=%d\n", p.PDOP, p.HDOP);
#else
// FIXME! naive PDOP emulation (assumes VDOP==HDOP)
// correct formula is PDOP = SQRT(HDOP^2 + VDOP^2)
p.HDOP = reader.hdop.value();
p.PDOP = 1.41 * reader.hdop.value();
#endif
// Discard incomplete or erroneous readings
if (reader.hdop.value() == 0)
return false;
p.latitude_i = toDegInt(loc.lat);
p.longitude_i = toDegInt(loc.lng);
p.altitude_geoidal_separation = reader.geoidHeight.meters();
p.altitude_hae = reader.altitude.meters() + p.altitude_geoidal_separation;
p.altitude = reader.altitude.meters();
p.fix_quality = fixQual;
#ifndef TINYGPS_OPTION_NO_CUSTOM_FIELDS
p.fix_type = fixType;
#endif
// positional timestamp
struct tm t;
t.tm_sec = reader.time.second();
t.tm_min = reader.time.minute();
t.tm_hour = reader.time.hour();
t.tm_mday = reader.date.day();
t.tm_mon = reader.date.month() - 1;
t.tm_year = reader.date.year() - 1900;
t.tm_isdst = false;
p.timestamp = mktime(&t);
// Nice to have, if available
if (reader.satellites.isUpdated()) {
p.sats_in_view = reader.satellites.value();
}
if (reader.course.isUpdated() && reader.course.isValid()) {
if (reader.course.value() < 36000) { // sanity check
p.ground_track =
reader.course.value() * 1e3; // Scale the heading (in degrees * 10^-2) to match the expected degrees * 10^-5
} else {
LOG_WARN("BOGUS course.value() REJECTED: %d\n", reader.course.value());
}
}
if (reader.speed.isUpdated() && reader.speed.isValid()) {
p.ground_speed = reader.speed.kmph();
}
return true;
}
bool NMEAGPS::hasLock()
{
// Using GPGGA fix quality indicator
if (fixQual >= 1 && fixQual <= 5) {
#ifndef TINYGPS_OPTION_NO_CUSTOM_FIELDS
// Use GPGSA fix type 2D/3D (better) if available
if (fixType == 3 || fixType == 0) // zero means "no data received"
#endif
return true;
}
return false;
}
bool NMEAGPS::hasFlow()
{
return reader.passedChecksum() > 0;
}
bool NMEAGPS::whileIdle()
{
bool isValid = false;
// First consume any chars that have piled up at the receiver
while (_serial_gps->available() > 0) {
int c = _serial_gps->read();
// LOG_DEBUG("%c", c);
isValid |= reader.encode(c);
}
return isValid;
}
-56
View File
@@ -1,56 +0,0 @@
#pragma once
#include "GPS.h"
#include "Observer.h"
#include "TinyGPS++.h"
/**
* A gps class thatreads from a NMEA GPS stream (and FIXME - eventually keeps the gps powered down except when reading)
*
* When new data is available it will notify observers.
*/
class NMEAGPS : public GPS
{
TinyGPSPlus reader;
uint8_t fixQual = 0; // fix quality from GPGGA
#ifndef TINYGPS_OPTION_NO_CUSTOM_FIELDS
// (20210908) TinyGps++ can only read the GPGSA "FIX TYPE" field
// via optional feature "custom fields", currently disabled (bug #525)
TinyGPSCustom gsafixtype; // custom extract fix type from GPGSA
TinyGPSCustom gsapdop; // custom extract PDOP from GPGSA
uint8_t fixType = 0; // fix type from GPGSA
#endif
public:
virtual bool setupGPS() override;
virtual bool factoryReset() override;
protected:
/** Subclasses should look for serial rx characters here and feed it to their GPS parser
*
* Return true if we received a valid message from the GPS
*/
virtual bool whileIdle() override;
/**
* Perform any processing that should be done only while the GPS is awake and looking for a fix.
* Override this method to check for new locations
*
* @return true if we've acquired a time
*/
virtual bool lookForTime() override;
/**
* Perform any processing that should be done only while the GPS is awake and looking for a fix.
* Override this method to check for new locations
*
* @return true if we've acquired a new location
*/
virtual bool lookForLocation() override;
virtual bool hasLock() override;
virtual bool hasFlow() override;
};
+34 -5
View File
@@ -17,6 +17,10 @@ static uint32_t
timeStartMsec; // Once we have a GPS lock, this is where we hold the initial msec clock that corresponds to that time timeStartMsec; // Once we have a GPS lock, this is where we hold the initial msec clock that corresponds to that time
static uint64_t zeroOffsetSecs; // GPS based time in secs since 1970 - only updated once on initial lock static uint64_t zeroOffsetSecs; // GPS based time in secs since 1970 - only updated once on initial lock
/**
* Reads the current date and time from the RTC module and updates the system time.
* @return True if the RTC was successfully read and the system time was updated, false otherwise.
*/
void readFromRTC() void readFromRTC()
{ {
struct timeval tv; /* btw settimeofday() is helpful here too*/ struct timeval tv; /* btw settimeofday() is helpful here too*/
@@ -83,7 +87,15 @@ void readFromRTC()
#endif #endif
} }
/// If we haven't yet set our RTC this boot, set it from a GPS derived time /**
* Sets the RTC (Real-Time Clock) if the provided time is of higher quality than the current RTC time.
*
* @param q The quality of the provided time.
* @param tv A pointer to a timeval struct containing the time to potentially set the RTC to.
* @return True if the RTC was set, false otherwise.
*
* If we haven't yet set our RTC this boot, set it from a GPS derived time
*/
bool perhapsSetRTC(RTCQuality q, const struct timeval *tv) bool perhapsSetRTC(RTCQuality q, const struct timeval *tv)
{ {
static uint32_t lastSetMsec = 0; static uint32_t lastSetMsec = 0;
@@ -91,9 +103,8 @@ bool perhapsSetRTC(RTCQuality q, const struct timeval *tv)
bool shouldSet; bool shouldSet;
if (q > currentQuality) { if (q > currentQuality) {
currentQuality = q;
shouldSet = true; shouldSet = true;
LOG_DEBUG("Upgrading time to RTC %ld secs (quality %d)\n", tv->tv_sec, q); LOG_DEBUG("Upgrading time to quality %d\n", q);
} else if (q == RTCQualityGPS && (now - lastSetMsec) > (12 * 60 * 60 * 1000UL)) { } else if (q == RTCQualityGPS && (now - lastSetMsec) > (12 * 60 * 60 * 1000UL)) {
// Every 12 hrs we will slam in a new GPS time, to correct for local RTC clock drift // Every 12 hrs we will slam in a new GPS time, to correct for local RTC clock drift
shouldSet = true; shouldSet = true;
@@ -102,12 +113,12 @@ bool perhapsSetRTC(RTCQuality q, const struct timeval *tv)
shouldSet = false; shouldSet = false;
if (shouldSet) { if (shouldSet) {
currentQuality = q;
lastSetMsec = now; lastSetMsec = now;
// This delta value works on all platforms // This delta value works on all platforms
timeStartMsec = now; timeStartMsec = now;
zeroOffsetSecs = tv->tv_sec; zeroOffsetSecs = tv->tv_sec;
// If this platform has a setable RTC, set it // If this platform has a setable RTC, set it
#ifdef RV3028_RTC #ifdef RV3028_RTC
if (rtc_found.address == RV3028_RTC) { if (rtc_found.address == RV3028_RTC) {
@@ -141,7 +152,7 @@ bool perhapsSetRTC(RTCQuality q, const struct timeval *tv)
#endif #endif
// nrf52 doesn't have a readable RTC (yet - software not written) // nrf52 doesn't have a readable RTC (yet - software not written)
#ifdef HAS_RTC #if HAS_RTC
readFromRTC(); readFromRTC();
#endif #endif
@@ -151,6 +162,13 @@ bool perhapsSetRTC(RTCQuality q, const struct timeval *tv)
} }
} }
/**
* Sets the RTC time if the provided time is of higher quality than the current RTC time.
*
* @param q The quality of the provided time.
* @param t The time to potentially set the RTC to.
* @return True if the RTC was set to the provided time, false otherwise.
*/
bool perhapsSetRTC(RTCQuality q, struct tm &t) bool perhapsSetRTC(RTCQuality q, struct tm &t)
{ {
/* Convert to unix time /* Convert to unix time
@@ -171,11 +189,22 @@ bool perhapsSetRTC(RTCQuality q, struct tm &t)
} }
} }
/**
* Returns the current time in seconds since the Unix epoch (January 1, 1970).
*
* @return The current time in seconds since the Unix epoch.
*/
uint32_t getTime() uint32_t getTime()
{ {
return (((uint32_t)millis() - timeStartMsec) / 1000) + zeroOffsetSecs; return (((uint32_t)millis() - timeStartMsec) / 1000) + zeroOffsetSecs;
} }
/**
* Returns the current time from the RTC if the quality of the time is at least minQuality.
*
* @param minQuality The minimum quality of the RTC time required for it to be considered valid.
* @return The current time from the RTC if it meets the minimum quality requirement, or 0 if the time is not valid.
*/
uint32_t getValidTime(RTCQuality minQuality) uint32_t getValidTime(RTCQuality minQuality)
{ {
return (currentQuality >= minQuality) ? getTime() : 0; return (currentQuality >= minQuality) ? getTime() : 0;
+300
View File
@@ -0,0 +1,300 @@
uint8_t GPS::_message_PMREQ[] PROGMEM = {
0x00, 0x00, // 4 bytes duration of request task
0x00, 0x00, // (milliseconds)
0x02, 0x00, // Task flag bitfield
0x00, 0x00, // byte index 1 = sleep mode
};
uint8_t GPS::_message_PMREQ_10[] PROGMEM = {
0x00, 0x00, // 4 bytes duration of request task
0x00, 0x00, // (milliseconds)
0x02, 0x00, // Task flag bitfield
0x00, 0x00, // byte index 1 = sleep mode
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // wakeupSources
};
const uint8_t GPS::_message_CFG_RXM_PSM[] PROGMEM = {
0x08, // Reserved
0x01 // Power save mode
};
// only for Neo-6
const uint8_t GPS::_message_CFG_RXM_ECO[] PROGMEM = {
0x08, // Reserved
0x04 // eco mode
};
const uint8_t GPS::_message_CFG_PM2[] PROGMEM = {
0x01, // version
0x00, // Reserved 1, set to 0x06 by u-Center
0x00, // Reserved 2
0x00, // Reserved 1
0x00, 0x11, 0x03, 0x00, // flags-> cyclic mode, wait for normal fix ok, do not wake to update RTC, doNotEnterOff,
// LimitPeakCurrent
0xE8, 0x03, 0x00, 0x00, // update period 1000 ms
0x10, 0x27, 0x00, 0x00, // search period 10s
0x00, 0x00, 0x00, 0x00, // Grid offset 0
0x01, 0x00, // onTime 1 second
0x00, 0x00, // min search time 0
0x00, 0x00, // 0x2C, 0x01, // reserved 4
0x00, 0x00, // 0x00, 0x00, // reserved 5
0x00, 0x00, 0x00, 0x00, // 0x4F, 0xC1, 0x03, 0x00, // reserved 6
0x00, 0x00, 0x00, 0x00, // 0x87, 0x02, 0x00, 0x00, // reserved 7
0x00, // 0xFF, // reserved 8
0x00, // 0x00, // reserved 9
0x00, 0x00, // 0x00, 0x00, // reserved 10
0x00, 0x00, 0x00, 0x00 // 0x64, 0x40, 0x01, 0x00 // reserved 11
};
const uint8_t GPS::_message_GNSS_7[] = {
0x00, // msgVer (0 for this version)
0x00, // numTrkChHw (max number of hardware channels, read only, so it's always 0)
0xff, // numTrkChUse (max number of channels to use, 0xff = max available)
0x02, // numConfigBlocks (number of GNSS systems), most modules support maximum 3 GNSS systems
// GNSS config format: gnssId, resTrkCh, maxTrkCh, reserved1, flags
0x00, 0x08, 0x10, 0x00, 0x01, 0x00, 0x00, 0x01, // GPS
0x01, 0x01, 0x03, 0x00, 0x01, 0x00, 0x00, 0x01 // SBAS
};
// It's not critical if the module doesn't acknowledge this configuration.
// The module should operate adequately with its factory or previously saved settings.
// It appears that there is a firmware bug in some GPS modules: When an attempt is made
// to overwrite a saved state with identical values, no ACK/NAK is received, contrary to
// what is specified in the Ublox documentation.
// There is also a possibility that the module may be GPS-only.
// For M8 GPS, GLONASS, Galileo, SBAS, QZSS
const uint8_t GPS::_message_GNSS_8[] = {
0x00, // msgVer (0 for this version)
0x00, // numTrkChHw (max number of hardware channels, read only, so it's always 0)
0xff, // numTrkChUse (max number of channels to use, 0xff = max available)
0x05, // numConfigBlocks (number of GNSS systems)
// GNSS config format: gnssId, resTrkCh, maxTrkCh, reserved1, flags
0x00, 0x08, 0x10, 0x00, 0x01, 0x00, 0x01, 0x01, // GPS
0x01, 0x01, 0x03, 0x00, 0x01, 0x00, 0x01, 0x01, // SBAS
0x02, 0x04, 0x08, 0x00, 0x01, 0x00, 0x01, 0x01, // Galileo
0x05, 0x00, 0x03, 0x00, 0x01, 0x00, 0x01, 0x01, // QZSS
0x06, 0x08, 0x0E, 0x00, 0x01, 0x00, 0x01, 0x01 // GLONASS
};
/*
// For M8 GPS, GLONASS, BeiDou, SBAS, QZSS
const uint8_t GPS::_message_GNSS_8_B[] = {
0x00, // msgVer (0 for this version)
0x00, // numTrkChHw (max number of hardware channels, read only, so it's always 0)
0xff, // numTrkChUse (max number of channels to use, 0xff = max available) read only for protocol >23
0x05, // numConfigBlocks (number of GNSS systems)
// GNSS config format: gnssId, resTrkCh, maxTrkCh, reserved1, flags
0x00, 0x08, 0x10, 0x00, 0x01, 0x00, 0x01, 0x01, // GPS
0x01, 0x01, 0x03, 0x00, 0x01, 0x00, 0x01, 0x01, // SBAS
0x03, 0x08, 0x10, 0x00, 0x01, 0x00, 0x01, 0x01, // BeiDou
0x05, 0x00, 0x03, 0x00, 0x01, 0x00, 0x01, 0x01, // QZSS
0x06, 0x08, 0x0E, 0x00, 0x01, 0x00, 0x01, 0x01 // GLONASS
};
*/
// For M8 we want to enable NMEA version 4.10 messages to allow for Galileo and or BeiDou
const uint8_t GPS::_message_NMEA[]{
0x00, // filter flags
0x41, // NMEA Version
0x00, // Max number of SVs to report per TaklerId
0x02, // flags
0x00, 0x00, 0x00, 0x00, // gnssToFilter
0x00, // svNumbering
0x00, // mainTalkerId
0x00, // gsvTalkerId
0x01, // Message version
0x00, 0x00, // bdsTalkerId 2 chars 0=default
0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // Reserved
};
// Enable jamming/interference monitor
// For Neo-6, Max-7 and Neo-7
const uint8_t GPS::_message_JAM_6_7[] = {
0xf3, 0xac, 0x62, 0xad, // config1 bbThreshold = 3, cwThreshold = 15, enable = 1, reserved bits 0x16B156
0x1e, 0x03, 0x00, 0x00 // config2 antennaSetting Unknown = 0, reserved 3, = 0x00,0x00, reserved 2 = 0x31E
};
// For M8
const uint8_t GPS::_message_JAM_8[] = {
0xf3, 0xac, 0x62, 0xad, // config1 bbThreshold = 3, cwThreshold = 15, enable1 = 1, reserved bits 0x16B156
0x1e, 0x43, 0x00, 0x00 // config2 antennaSetting Unknown = 0, enable2 = 1, generalBits = 0x31E
};
// Configure navigation engine expert settings:
// there are many variations of what were Reserved fields for the Neo-6 in later versions
// ToDo: check UBX-MON-VER for module type and protocol version
// For the Neo-6
const uint8_t GPS::_message_NAVX5[] = {
0x00, 0x00, // msgVer (0 for this version)
0x4c, 0x66, // mask1
0x00, 0x00, 0x00, 0x00, // Reserved 0
0x00, // Reserved 1
0x00, // Reserved 2
0x03, // minSVs (Minimum number of satellites for navigation) = 3
0x10, // maxSVs (Maximum number of satellites for navigation) = 16
0x06, // minCNO (Minimum satellite signal level for navigation) = 6 dBHz
0x00, // Reserved 5
0x00, // iniFix3D (Initial fix must be 3D) (0 = false 1 = true)
0x00, // Reserved 6
0x00, // Reserved 7
0x00, // Reserved 8
0x00, 0x00, // wknRollover 0 = firmware default
0x00, 0x00, 0x00, 0x00, // Reserved 9
0x00, // Reserved 10
0x00, // Reserved 11
0x00, // usePPP (Precice Point Positioning) (0 = false, 1 = true)
0x01, // useAOP (AssistNow Autonomous configuration) = 1 (enabled)
0x00, // Reserved 12
0x00, // Reserved 13
0x00, 0x00, // aopOrbMaxErr = 0 to reset to firmware default
0x00, // Reserved 14
0x00, // Reserved 15
0x00, 0x00, // Reserved 3
0x00, 0x00, 0x00, 0x00 // Reserved 4
};
// For the M8
const uint8_t GPS::_message_NAVX5_8[] = {
0x02, 0x00, // msgVer (2 for this version)
0x4c, 0x66, // mask1
0x00, 0x00, 0x00, 0x00, // mask2
0x00, 0x00, // Reserved 1
0x03, // minSVs (Minimum number of satellites for navigation) = 3
0x10, // maxSVs (Maximum number of satellites for navigation) = 16
0x06, // minCNO (Minimum satellite signal level for navigation) = 6 dBHz
0x00, // Reserved 2
0x00, // iniFix3D (Initial fix must be 3D) (0 = false 1 = true)
0x00, 0x00, // Reserved 3
0x00, // ackAiding
0x00, 0x00, // wknRollover 0 = firmware default
0x00, // sigAttenCompMode
0x00, // Reserved 4
0x00, 0x00, // Reserved 5
0x00, 0x00, // Reserved 6
0x00, // usePPP (Precice Point Positioning) (0 = false, 1 = true)
0x01, // aopCfg (AssistNow Autonomous configuration) = 1 (enabled)
0x00, 0x00, // Reserved 7
0x00, 0x00, // aopOrbMaxErr = 0 to reset to firmware default
0x00, 0x00, 0x00, 0x00, // Reserved 8
0x00, 0x00, 0x00, // Reserved 9
0x00 // useAdr
};
// Set GPS update rate to 1Hz
// Lowering the update rate helps to save power.
// Additionally, for some new modules like the M9/M10, an update rate lower than 5Hz
// is recommended to avoid a known issue with satellites disappearing.
// The module defaults for M8, M9, M10 are the same as we use here so no update is necessary
const uint8_t GPS::_message_1HZ[] = {
0xE8, 0x03, // Measurement Rate (1000ms for 1Hz)
0x01, 0x00, // Navigation rate, always 1 in GPS mode
0x01, 0x00 // Time reference
};
// Disable GLL. GLL - Geographic position (latitude and longitude), which provides the current geographical
// coordinates.
const uint8_t GPS::_message_GLL[] = {
0xF0, 0x01, // NMEA ID for GLL
0x00, // Rate for DDC
0x00, // Rate for UART1
0x00, // Rate for UART2
0x00, // Rate for USB
0x00, // Rate for SPI
0x00 // Reserved
};
// Enable GSA. GSA - GPS DOP and active satellites, used for detailing the satellites used in the positioning and
// the DOP (Dilution of Precision)
const uint8_t GPS::_message_GSA[] = {
0xF0, 0x02, // NMEA ID for GSA
0x00, // Rate for DDC
0x01, // Rate for UART1
0x00, // Rate for UART2
0x00, // Rate for USB
0x00, // Rate for SPI
0x00 // Reserved
};
// Disable GSV. GSV - Satellites in view, details the number and location of satellites in view.
const uint8_t GPS::_message_GSV[] = {
0xF0, 0x03, // NMEA ID for GSV
0x00, // Rate for DDC
0x00, // Rate for UART1
0x00, // Rate for UART2
0x00, // Rate for USB
0x00, // Rate for SPI
0x00 // Reserved
};
// Disable VTG. VTG - Track made good and ground speed, which provides course and speed information relative to
// the ground.
const uint8_t GPS::_message_VTG[] = {
0xF0, 0x05, // NMEA ID for VTG
0x00, // Rate for DDC
0x00, // Rate for UART1
0x00, // Rate for UART2
0x00, // Rate for USB
0x00, // Rate for SPI
0x00 // Reserved
};
// Enable RMC. RMC - Recommended Minimum data, the essential gps pvt (position, velocity, time) data.
const uint8_t GPS::_message_RMC[] = {
0xF0, 0x04, // NMEA ID for RMC
0x00, // Rate for DDC
0x01, // Rate for UART1
0x00, // Rate for UART2
0x00, // Rate for USB
0x00, // Rate for SPI
0x00 // Reserved
};
// Enable GGA. GGA - Global Positioning System Fix Data, which provides 3D location and accuracy data.
const uint8_t GPS::_message_GGA[] = {
0xF0, 0x00, // NMEA ID for GGA
0x00, // Rate for DDC
0x01, // Rate for UART1
0x00, // Rate for UART2
0x00, // Rate for USB
0x00, // Rate for SPI
0x00 // Reserved
};
// Disable UBX-AID-ALPSRV as it may confuse TinyGPS. The Neo-6 seems to send this message
// whether the AID Autonomous is enabled or not
const uint8_t GPS::_message_AID[] = {
0x0B, 0x32, // NMEA ID for UBX-AID-ALPSRV
0x00, // Rate for DDC
0x00, // Rate for UART1
0x00, // Rate for UART2
0x00, // Rate for USB
0x00, // Rate for SPI
0x00 // Reserved
};
// The Power Management configuration allows the GPS module to operate in different power modes for optimized
// power consumption. The modes supported are: 0x00 = Full power: The module operates at full power with no power
// saving. 0x01 = Balanced: The module dynamically adjusts the tracking behavior to balance power consumption.
// 0x02 = Interval: The module operates in a periodic mode, cycling between tracking and power saving states.
// 0x03 = Aggressive with 1 Hz: The module operates in a power saving mode with a 1 Hz update rate.
// 0x04 = Aggressive with 2 Hz: The module operates in a power saving mode with a 2 Hz update rate.
// 0x05 = Aggressive with 4 Hz: The module operates in a power saving mode with a 4 Hz update rate.
// The 'period' field specifies the position update and search period. It is only valid when the powerSetupValue
// is set to Interval; otherwise, it must be set to '0'. The 'onTime' field specifies the duration of the ON phase
// and must be smaller than the period. It is only valid when the powerSetupValue is set to Interval; otherwise,
// it must be set to '0'.
// This command applies to M8 and higher products
const uint8_t GPS::_message_PMS[] = {
0x00, // Version (0)
0x03, // Power setup value 3 = Agresssive 1Hz
0x00, 0x00, // period: not applicable, set to 0
0x00, 0x00, // onTime: not applicable, set to 0
0x00, 0x00 // reserved, generated by u-center
};
const uint8_t GPS::_message_SAVE[] = {
0x00, 0x00, 0x00, 0x00, // clearMask: no sections cleared
0xFF, 0xFF, 0x00, 0x00, // saveMask: save all sections
0x00, 0x00, 0x00, 0x00, // loadMask: no sections loaded
0x17 // deviceMask: BBR, Flash, EEPROM, and SPI Flash
};
+76 -18
View File
@@ -7,9 +7,9 @@
#include "main.h" #include "main.h"
#include <SPI.h> #include <SPI.h>
// #ifdef HELTEC_WIRELESS_PAPER #if defined(HELTEC_WIRELESS_PAPER) || defined(HELTEC_WIRELESS_PAPER_V1_0)
// SPIClass *hspi = NULL; SPIClass *hspi = NULL;
// #endif #endif
#define COLORED GxEPD_BLACK #define COLORED GxEPD_BLACK
#define UNCOLORED GxEPD_WHITE #define UNCOLORED GxEPD_WHITE
@@ -46,8 +46,13 @@
#define TECHO_DISPLAY_MODEL GxEPD2_154_M09 #define TECHO_DISPLAY_MODEL GxEPD2_154_M09
#elif defined(HELTEC_WIRELESS_PAPER) #elif defined(HELTEC_WIRELESS_PAPER)
//#define TECHO_DISPLAY_MODEL GxEPD2_213_T5D // #define TECHO_DISPLAY_MODEL GxEPD2_213_T5D
#define TECHO_DISPLAY_MODEL GxEPD2_213_FC1
#elif defined(HELTEC_WIRELESS_PAPER_V1_0)
// 2.13" 122x250 - DEPG0213BNS800
#define TECHO_DISPLAY_MODEL GxEPD2_213_BN #define TECHO_DISPLAY_MODEL GxEPD2_213_BN
#endif #endif
GxEPD2_BW<TECHO_DISPLAY_MODEL, TECHO_DISPLAY_MODEL::HEIGHT> *adafruitDisplay; GxEPD2_BW<TECHO_DISPLAY_MODEL, TECHO_DISPLAY_MODEL::HEIGHT> *adafruitDisplay;
@@ -55,7 +60,7 @@ GxEPD2_BW<TECHO_DISPLAY_MODEL, TECHO_DISPLAY_MODEL::HEIGHT> *adafruitDisplay;
EInkDisplay::EInkDisplay(uint8_t address, int sda, int scl, OLEDDISPLAY_GEOMETRY geometry, HW_I2C i2cBus) EInkDisplay::EInkDisplay(uint8_t address, int sda, int scl, OLEDDISPLAY_GEOMETRY geometry, HW_I2C i2cBus)
{ {
#if defined(TTGO_T_ECHO) #if defined(TTGO_T_ECHO)
setGeometry(GEOMETRY_RAWMODE, TECHO_DISPLAY_MODEL::WIDTH, TECHO_DISPLAY_MODEL::HEIGHT); setGeometry(GEOMETRY_RAWMODE, 200, 200);
#elif defined(RAK4630) #elif defined(RAK4630)
// GxEPD2_213_BN - RAK14000 2.13 inch b/w 250x122 // GxEPD2_213_BN - RAK14000 2.13 inch b/w 250x122
@@ -70,8 +75,19 @@ EInkDisplay::EInkDisplay(uint8_t address, int sda, int scl, OLEDDISPLAY_GEOMETRY
// GxEPD2_154_M09 // GxEPD2_154_M09
// setGeometry(GEOMETRY_RAWMODE, 200, 200); // setGeometry(GEOMETRY_RAWMODE, 200, 200);
#elif defined(HELTEC_WIRELESS_PAPER_V1_0)
// The display's memory is actually 128px x 250px
// Setting the buffersize manually prevents 122/8 truncating to a 15 byte width
// (Or something like that..)
this->geometry = GEOMETRY_RAWMODE;
this->displayWidth = 250;
this->displayHeight = 122;
this->displayBufferSize = 250 * (128 / 8);
#elif defined(HELTEC_WIRELESS_PAPER) #elif defined(HELTEC_WIRELESS_PAPER)
// setGeometry(GEOMETRY_RAWMODE, 212, 104); // GxEPD2_213_BN - 2.13 inch b/w 250x122
setGeometry(GEOMETRY_RAWMODE, 250, 122); setGeometry(GEOMETRY_RAWMODE, 250, 122);
#elif defined(MAKERPYTHON) #elif defined(MAKERPYTHON)
// GxEPD2_290_T5D // GxEPD2_290_T5D
@@ -119,7 +135,6 @@ bool EInkDisplay::forceDisplay(uint32_t msecLimit)
// tft.drawBitmap(0, 0, buffer, 128, 64, TFT_YELLOW, TFT_BLACK); // tft.drawBitmap(0, 0, buffer, 128, 64, TFT_YELLOW, TFT_BLACK);
for (uint32_t y = 0; y < displayHeight; y++) { for (uint32_t y = 0; y < displayHeight; y++) {
for (uint32_t x = 0; x < displayWidth; x++) { for (uint32_t x = 0; x < displayWidth; x++) {
// get src pixel in the page based ordering the OLED lib uses FIXME, super inefficient // get src pixel in the page based ordering the OLED lib uses FIXME, super inefficient
auto b = buffer[x + (y / 8) * displayWidth]; auto b = buffer[x + (y / 8) * displayWidth];
auto isset = b & (1 << (y & 7)); auto isset = b & (1 << (y & 7));
@@ -130,8 +145,7 @@ bool EInkDisplay::forceDisplay(uint32_t msecLimit)
LOG_DEBUG("Updating E-Paper... "); LOG_DEBUG("Updating E-Paper... ");
#if defined(TTGO_T_ECHO) #if defined(TTGO_T_ECHO)
// ePaper.Reset(); // wake the screen from sleep adafruitDisplay->nextPage();
adafruitDisplay->display(false); // FIXME, use partial update mode
#elif defined(RAK4630) || defined(MAKERPYTHON) #elif defined(RAK4630) || defined(MAKERPYTHON)
// RAK14000 2.13 inch b/w 250x122 actually now does support partial updates // RAK14000 2.13 inch b/w 250x122 actually now does support partial updates
@@ -148,7 +162,10 @@ bool EInkDisplay::forceDisplay(uint32_t msecLimit)
#elif defined(PCA10059) || defined(M5_COREINK) #elif defined(PCA10059) || defined(M5_COREINK)
adafruitDisplay->nextPage(); adafruitDisplay->nextPage();
#elif defined(HELTEC_WIRELESS_PAPER_V1_0)
adafruitDisplay->nextPage();
#elif defined(HELTEC_WIRELESS_PAPER)
adafruitDisplay->nextPage();
#elif defined(PRIVATE_HW) || defined(my) #elif defined(PRIVATE_HW) || defined(my)
adafruitDisplay->nextPage(); adafruitDisplay->nextPage();
@@ -193,14 +210,14 @@ bool EInkDisplay::connect()
LOG_INFO("Doing EInk init\n"); LOG_INFO("Doing EInk init\n");
#ifdef PIN_EINK_PWR_ON #ifdef PIN_EINK_PWR_ON
digitalWrite(PIN_EINK_PWR_ON, HIGH); // If we need to assert a pin to power external peripherals
pinMode(PIN_EINK_PWR_ON, OUTPUT); pinMode(PIN_EINK_PWR_ON, OUTPUT);
digitalWrite(PIN_EINK_PWR_ON, HIGH); // If we need to assert a pin to power external peripherals
#endif #endif
#ifdef PIN_EINK_EN #ifdef PIN_EINK_EN
// backlight power, HIGH is backlight on, LOW is off // backlight power, HIGH is backlight on, LOW is off
digitalWrite(PIN_EINK_EN, LOW);
pinMode(PIN_EINK_EN, OUTPUT); pinMode(PIN_EINK_EN, OUTPUT);
digitalWrite(PIN_EINK_EN, LOW);
#endif #endif
#if defined(TTGO_T_ECHO) #if defined(TTGO_T_ECHO)
@@ -210,6 +227,7 @@ bool EInkDisplay::connect()
adafruitDisplay = new GxEPD2_BW<TECHO_DISPLAY_MODEL, TECHO_DISPLAY_MODEL::HEIGHT>(*lowLevel); adafruitDisplay = new GxEPD2_BW<TECHO_DISPLAY_MODEL, TECHO_DISPLAY_MODEL::HEIGHT>(*lowLevel);
adafruitDisplay->init(); adafruitDisplay->init();
adafruitDisplay->setRotation(3); adafruitDisplay->setRotation(3);
adafruitDisplay->setPartialWindow(0, 0, displayWidth, displayHeight);
} }
#elif defined(RAK4630) || defined(MAKERPYTHON) #elif defined(RAK4630) || defined(MAKERPYTHON)
{ {
@@ -229,15 +247,55 @@ bool EInkDisplay::connect()
(void)adafruitDisplay; (void)adafruitDisplay;
} }
} }
#elif defined(HELTEC_WIRELESS_PAPER_V1_0)
{
// Is this a normal boot, or a wake from deep sleep?
esp_sleep_wakeup_cause_t wakeReason = esp_sleep_get_wakeup_cause();
// If waking from sleep, need to reverse rtc_gpio_isolate(), called in cpuDeepSleep()
// Otherwise, SPI won't work
if (wakeReason != ESP_SLEEP_WAKEUP_UNDEFINED) {
// HSPI + other display pins
rtc_gpio_hold_dis((gpio_num_t)PIN_EINK_SCLK);
rtc_gpio_hold_dis((gpio_num_t)PIN_EINK_DC);
rtc_gpio_hold_dis((gpio_num_t)PIN_EINK_RES);
rtc_gpio_hold_dis((gpio_num_t)PIN_EINK_BUSY);
rtc_gpio_hold_dis((gpio_num_t)PIN_EINK_CS);
rtc_gpio_hold_dis((gpio_num_t)PIN_EINK_MOSI);
}
// Start HSPI
hspi = new SPIClass(HSPI);
hspi->begin(PIN_EINK_SCLK, -1, PIN_EINK_MOSI, PIN_EINK_CS); // SCLK, MISO, MOSI, SS
// Enable VExt (ACTIVE LOW)
// Unsure if called elsewhere first?
delay(100);
pinMode(Vext, OUTPUT);
digitalWrite(Vext, LOW);
delay(100);
// Create GxEPD2 objects
auto lowLevel = new TECHO_DISPLAY_MODEL(PIN_EINK_CS, PIN_EINK_DC, PIN_EINK_RES, PIN_EINK_BUSY, *hspi);
adafruitDisplay = new GxEPD2_BW<TECHO_DISPLAY_MODEL, TECHO_DISPLAY_MODEL::HEIGHT>(*lowLevel);
// Init GxEPD2
adafruitDisplay->init();
adafruitDisplay->setRotation(3);
}
#elif defined(HELTEC_WIRELESS_PAPER) #elif defined(HELTEC_WIRELESS_PAPER)
{ {
auto lowLevel = new TECHO_DISPLAY_MODEL(PIN_EINK_CS, PIN_EINK_DC, PIN_EINK_RES, PIN_EINK_BUSY); hspi = new SPIClass(HSPI);
hspi->begin(PIN_EINK_SCLK, -1, PIN_EINK_MOSI, PIN_EINK_CS); // SCLK, MISO, MOSI, SS
delay(100);
pinMode(Vext, OUTPUT);
digitalWrite(Vext, LOW);
delay(100);
auto lowLevel = new TECHO_DISPLAY_MODEL(PIN_EINK_CS, PIN_EINK_DC, PIN_EINK_RES, PIN_EINK_BUSY, *hspi);
adafruitDisplay = new GxEPD2_BW<TECHO_DISPLAY_MODEL, TECHO_DISPLAY_MODEL::HEIGHT>(*lowLevel); adafruitDisplay = new GxEPD2_BW<TECHO_DISPLAY_MODEL, TECHO_DISPLAY_MODEL::HEIGHT>(*lowLevel);
// hspi = new SPIClass(HSPI); adafruitDisplay->init();
// hspi->begin(PIN_EINK_SCLK, -1, PIN_EINK_MOSI, PIN_EINK_CS); // SCLK, MISO, MOSI, SS
adafruitDisplay->init(115200, true, 10, false, SPI, SPISettings(6000000, MSBFIRST, SPI_MODE0));
adafruitDisplay->setRotation(3); adafruitDisplay->setRotation(3);
adafruitDisplay->setPartialWindow(0, 0, displayWidth, displayHeight);
} }
#elif defined(PCA10059) #elif defined(PCA10059)
{ {
@@ -271,4 +329,4 @@ bool EInkDisplay::connect()
return true; return true;
} }
#endif #endif
+6 -1
View File
@@ -2,8 +2,13 @@
#include <OLEDDisplay.h> #include <OLEDDisplay.h>
#if defined(HELTEC_WIRELESS_PAPER_V1_0)
// Re-enable SPI after deep sleep: rtc_gpio_hold_dis()
#include "driver/rtc_io.h"
#endif
/** /**
* An adapter class that allows using the TFT_eSPI library as if it was an OLEDDisplay implementation. * An adapter class that allows using the GxEPD2 library as if it was an OLEDDisplay implementation.
* *
* Remaining TODO: * Remaining TODO:
* optimize display() to only draw changed pixels (see other OLED subclasses for examples) * optimize display() to only draw changed pixels (see other OLED subclasses for examples)
-2
View File
@@ -1,5 +1,3 @@
#include "main.h"
#ifdef HAS_NCP5623 #ifdef HAS_NCP5623
#include <NCP5623.h> #include <NCP5623.h>
extern NCP5623 rgb; extern NCP5623 rgb;
+259 -251
View File
@@ -24,6 +24,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#if HAS_SCREEN #if HAS_SCREEN
#include <OLEDDisplay.h> #include <OLEDDisplay.h>
#include "DisplayFormatters.h"
#include "GPS.h" #include "GPS.h"
#include "MeshService.h" #include "MeshService.h"
#include "NodeDB.h" #include "NodeDB.h"
@@ -31,22 +32,30 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "gps/GeoCoord.h" #include "gps/GeoCoord.h"
#include "gps/RTC.h" #include "gps/RTC.h"
#include "graphics/images.h" #include "graphics/images.h"
#include "input/TouchScreenImpl1.h"
#include "main.h" #include "main.h"
#include "mesh-pb-constants.h" #include "mesh-pb-constants.h"
#include "mesh/Channels.h" #include "mesh/Channels.h"
#include "mesh/generated/meshtastic/deviceonly.pb.h" #include "mesh/generated/meshtastic/deviceonly.pb.h"
#include "meshUtils.h"
#include "modules/ExternalNotificationModule.h" #include "modules/ExternalNotificationModule.h"
#include "modules/TextMessageModule.h" #include "modules/TextMessageModule.h"
#include "sleep.h" #include "sleep.h"
#include "target_specific.h" #include "target_specific.h"
#include "utils.h"
#if HAS_WIFI && !defined(ARCH_PORTDUINO)
#include "mesh/wifi/WiFiAPClient.h"
#endif
#ifdef ARCH_ESP32 #ifdef ARCH_ESP32
#include "esp_task_wdt.h" #include "esp_task_wdt.h"
#include "mesh/http/WiFiAPClient.h"
#include "modules/esp32/StoreForwardModule.h" #include "modules/esp32/StoreForwardModule.h"
#endif #endif
#if ARCH_PORTDUINO
#include "platform/portduino/PortduinoGlue.h"
#endif
#ifdef OLED_RU #ifdef OLED_RU
#include "fonts/OLEDDisplayFontsRU.h" #include "fonts/OLEDDisplayFontsRU.h"
#endif #endif
@@ -102,7 +111,8 @@ static uint16_t displayWidth, displayHeight;
#define SCREEN_WIDTH displayWidth #define SCREEN_WIDTH displayWidth
#define SCREEN_HEIGHT displayHeight #define SCREEN_HEIGHT displayHeight
#if defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7735_CS) #if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7735_CS) || defined(ST7789_CS)) && \
!defined(DISPLAY_FORCE_SMALL_FONTS)
// The screen is bigger so use bigger fonts // The screen is bigger so use bigger fonts
#define FONT_SMALL ArialMT_Plain_16 // Height: 19 #define FONT_SMALL ArialMT_Plain_16 // Height: 19
#define FONT_MEDIUM ArialMT_Plain_24 // Height: 28 #define FONT_MEDIUM ArialMT_Plain_24 // Height: 28
@@ -140,7 +150,7 @@ static void drawIconScreen(const char *upperMsg, OLEDDisplay *display, OLEDDispl
// draw centered icon left to right and centered above the one line of app text // draw centered icon left to right and centered above the one line of app text
display->drawXbm(x + (SCREEN_WIDTH - icon_width) / 2, y + (SCREEN_HEIGHT - FONT_HEIGHT_MEDIUM - icon_height) / 2 + 2, display->drawXbm(x + (SCREEN_WIDTH - icon_width) / 2, y + (SCREEN_HEIGHT - FONT_HEIGHT_MEDIUM - icon_height) / 2 + 2,
icon_width, icon_height, (const uint8_t *)icon_bits); icon_width, icon_height, icon_bits);
display->setFont(FONT_MEDIUM); display->setFont(FONT_MEDIUM);
display->setTextAlignment(TEXT_ALIGN_LEFT); display->setTextAlignment(TEXT_ALIGN_LEFT);
@@ -158,17 +168,9 @@ static void drawIconScreen(const char *upperMsg, OLEDDisplay *display, OLEDDispl
xstr(APP_VERSION_SHORT)); // Note: we don't bother printing region or now, it makes the string too long xstr(APP_VERSION_SHORT)); // Note: we don't bother printing region or now, it makes the string too long
display->drawString(x + SCREEN_WIDTH - display->getStringWidth(buf), y + 0, buf); display->drawString(x + SCREEN_WIDTH - display->getStringWidth(buf), y + 0, buf);
screen->forceDisplay(); screen->forceDisplay();
// FIXME - draw serial # somewhere? // FIXME - draw serial # somewhere?
} }
static void drawBootScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
{
// Draw region in upper left
const char *region = myRegion ? myRegion->name : NULL;
drawIconScreen(region, display, state, x, y);
}
static void drawOEMIconScreen(const char *upperMsg, OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y) static void drawOEMIconScreen(const char *upperMsg, OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
{ {
// draw an xbm image. // draw an xbm image.
@@ -218,6 +220,28 @@ static void drawOEMBootScreen(OLEDDisplay *display, OLEDDisplayUiState *state, i
drawOEMIconScreen(region, display, state, x, y); drawOEMIconScreen(region, display, state, x, y);
} }
static void drawFrameText(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y, const char *message)
{
uint16_t x_offset = display->width() / 2;
display->setTextAlignment(TEXT_ALIGN_CENTER);
display->setFont(FONT_MEDIUM);
display->drawString(x_offset + x, 26 + y, message);
}
static void drawBootScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
{
#ifdef ARCH_ESP32
if (wakeCause == ESP_SLEEP_WAKEUP_TIMER || wakeCause == ESP_SLEEP_WAKEUP_EXT1) {
drawFrameText(display, state, x, y, "Resuming...");
} else
#endif
{
// Draw region in upper left
const char *region = myRegion ? myRegion->name : NULL;
drawIconScreen(region, display, state, x, y);
}
}
// Used on boot when a certificate is being created // Used on boot when a certificate is being created
static void drawSSLScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y) static void drawSSLScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
{ {
@@ -318,22 +342,6 @@ static void drawFrameBluetooth(OLEDDisplay *display, OLEDDisplayUiState *state,
display->drawString(x_offset + x, y_offset + y, deviceName); display->drawString(x_offset + x, y_offset + y, deviceName);
} }
static void drawFrameShutdown(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
{
uint16_t x_offset = display->width() / 2;
display->setTextAlignment(TEXT_ALIGN_CENTER);
display->setFont(FONT_MEDIUM);
display->drawString(x_offset + x, 26 + y, "Shutting down...");
}
static void drawFrameReboot(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
{
uint16_t x_offset = display->width() / 2;
display->setTextAlignment(TEXT_ALIGN_CENTER);
display->setFont(FONT_MEDIUM);
display->drawString(x_offset + x, 26 + y, "Rebooting...");
}
static void drawFrameFirmware(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y) static void drawFrameFirmware(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
{ {
display->setTextAlignment(TEXT_ALIGN_CENTER); display->setTextAlignment(TEXT_ALIGN_CENTER);
@@ -363,7 +371,7 @@ static void drawCriticalFaultFrame(OLEDDisplay *display, OLEDDisplayUiState *sta
// Ignore messages originating from phone (from the current node 0x0) unless range test or store and forward module are enabled // Ignore messages originating from phone (from the current node 0x0) unless range test or store and forward module are enabled
static bool shouldDrawMessage(const meshtastic_MeshPacket *packet) static bool shouldDrawMessage(const meshtastic_MeshPacket *packet)
{ {
return packet->from != 0 && !moduleConfig.range_test.enabled && !moduleConfig.store_forward.enabled; return packet->from != 0 && !moduleConfig.store_forward.enabled;
} }
/// Draw the last text message we received /// Draw the last text message we received
@@ -372,7 +380,7 @@ static void drawTextMessageFrame(OLEDDisplay *display, OLEDDisplayUiState *state
// the max length of this buffer is much longer than we can possibly print // the max length of this buffer is much longer than we can possibly print
static char tempBuf[237]; static char tempBuf[237];
meshtastic_MeshPacket &mp = devicestate.rx_text_message; const meshtastic_MeshPacket &mp = devicestate.rx_text_message;
meshtastic_NodeInfoLite *node = nodeDB.getMeshNode(getFrom(&mp)); meshtastic_NodeInfoLite *node = nodeDB.getMeshNode(getFrom(&mp));
// LOG_DEBUG("drawing text message from 0x%x: %s\n", mp.from, // LOG_DEBUG("drawing text message from 0x%x: %s\n", mp.from,
// mp.decoded.variant.data.decoded.bytes); // mp.decoded.variant.data.decoded.bytes);
@@ -488,11 +496,12 @@ static void drawBattery(OLEDDisplay *display, int16_t x, int16_t y, uint8_t *img
} }
// Draw nodes status // Draw nodes status
static void drawNodes(OLEDDisplay *display, int16_t x, int16_t y, NodeStatus *nodeStatus) static void drawNodes(OLEDDisplay *display, int16_t x, int16_t y, const NodeStatus *nodeStatus)
{ {
char usersString[20]; char usersString[20];
snprintf(usersString, sizeof(usersString), "%d/%d", nodeStatus->getNumOnline(), nodeStatus->getNumTotal()); snprintf(usersString, sizeof(usersString), "%d/%d", nodeStatus->getNumOnline(), nodeStatus->getNumTotal());
#if defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7735_CS) #if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7735_CS) || defined(ST7789_CS)) && \
!defined(DISPLAY_FORCE_SMALL_FONTS)
display->drawFastImage(x, y + 3, 8, 8, imgUser); display->drawFastImage(x, y + 3, 8, 8, imgUser);
#else #else
display->drawFastImage(x, y, 8, 8, imgUser); display->drawFastImage(x, y, 8, 8, imgUser);
@@ -549,15 +558,20 @@ static void drawGPS(OLEDDisplay *display, int16_t x, int16_t y, const GPSStatus
} }
} }
// Draw status when gps is disabled by PMU // Draw status when GPS is disabled or not present
static void drawGPSpowerstat(OLEDDisplay *display, int16_t x, int16_t y, const GPSStatus *gps) static void drawGPSpowerstat(OLEDDisplay *display, int16_t x, int16_t y, const GPSStatus *gps)
{ {
String displayLine = "GPS disabled"; String displayLine;
int16_t xPos = display->getStringWidth(displayLine); int pos;
if (y < FONT_HEIGHT_SMALL) { // Line 1: use short string
if (!config.position.gps_enabled) { displayLine = config.position.gps_mode == meshtastic_Config_PositionConfig_GpsMode_NOT_PRESENT ? "No GPS" : "GPS off";
display->drawString(x + xPos, y, displayLine); pos = SCREEN_WIDTH - display->getStringWidth(displayLine);
} else {
displayLine = config.position.gps_mode == meshtastic_Config_PositionConfig_GpsMode_NOT_PRESENT ? "GPS not present"
: "GPS is disabled";
pos = (SCREEN_WIDTH - display->getStringWidth(displayLine)) / 2;
} }
display->drawString(x + pos, y, displayLine);
} }
static void drawGPSAltitude(OLEDDisplay *display, int16_t x, int16_t y, const GPSStatus *gps) static void drawGPSAltitude(OLEDDisplay *display, int16_t x, int16_t y, const GPSStatus *gps)
@@ -585,7 +599,7 @@ static void drawGPScoordinates(OLEDDisplay *display, int16_t x, int16_t y, const
String displayLine = ""; String displayLine = "";
if (!gps->getIsConnected() && !config.position.fixed_position) { if (!gps->getIsConnected() && !config.position.fixed_position) {
displayLine = "No GPS Module"; displayLine = "No GPS present";
display->drawString(x + (SCREEN_WIDTH - (display->getStringWidth(displayLine))) / 2, y, displayLine); display->drawString(x + (SCREEN_WIDTH - (display->getStringWidth(displayLine))) / 2, y, displayLine);
} else if (!gps->getHasLock() && !config.position.fixed_position) { } else if (!gps->getHasLock() && !config.position.fixed_position) {
displayLine = "No GPS Lock"; displayLine = "No GPS Lock";
@@ -835,7 +849,11 @@ static void drawNodeInfo(OLEDDisplay *display, OLEDDisplayUiState *state, int16_
} }
static char distStr[20]; static char distStr[20];
strncpy(distStr, "? km", sizeof(distStr)); // might not have location data if (config.display.units == meshtastic_Config_DisplayConfig_DisplayUnits_IMPERIAL) {
strncpy(distStr, "? mi", sizeof(distStr)); // might not have location data
} else {
strncpy(distStr, "? km", sizeof(distStr));
}
meshtastic_NodeInfoLite *ourNode = nodeDB.getMeshNode(nodeDB.getNodeNum()); meshtastic_NodeInfoLite *ourNode = nodeDB.getMeshNode(nodeDB.getNodeNum());
const char *fields[] = {username, distStr, signalStr, lastStr, NULL}; const char *fields[] = {username, distStr, signalStr, lastStr, NULL};
int16_t compassX = 0, compassY = 0; int16_t compassX = 0, compassY = 0;
@@ -851,14 +869,14 @@ static void drawNodeInfo(OLEDDisplay *display, OLEDDisplayUiState *state, int16_
bool hasNodeHeading = false; bool hasNodeHeading = false;
if (ourNode && hasValidPosition(ourNode)) { if (ourNode && hasValidPosition(ourNode)) {
meshtastic_PositionLite &op = ourNode->position; const meshtastic_PositionLite &op = ourNode->position;
float myHeading = estimatedHeading(DegD(op.latitude_i), DegD(op.longitude_i)); float myHeading = estimatedHeading(DegD(op.latitude_i), DegD(op.longitude_i));
drawCompassNorth(display, compassX, compassY, myHeading); drawCompassNorth(display, compassX, compassY, myHeading);
if (hasValidPosition(node)) { if (hasValidPosition(node)) {
// display direction toward node // display direction toward node
hasNodeHeading = true; hasNodeHeading = true;
meshtastic_PositionLite &p = node->position; const meshtastic_PositionLite &p = node->position;
float d = float d =
GeoCoord::latLongToMeter(DegD(p.latitude_i), DegD(p.longitude_i), DegD(op.latitude_i), DegD(op.longitude_i)); GeoCoord::latLongToMeter(DegD(p.latitude_i), DegD(p.longitude_i), DegD(op.latitude_i), DegD(op.longitude_i));
@@ -899,28 +917,44 @@ static void drawNodeInfo(OLEDDisplay *display, OLEDDisplayUiState *state, int16_
drawColumns(display, x, y, fields); drawColumns(display, x, y, fields);
} }
// #ifdef RAK4630
// Screen::Screen(uint8_t address, int sda, int scl) : OSThread("Screen"), cmdQueue(32), dispdev(address, sda, scl),
// dispdev_oled(address, sda, scl), ui(&dispdev)
// {
// address_found = address;
// cmdQueue.setReader(this);
// if (screen_found) {
// (void)dispdev;
// AutoOLEDWire dispdev = dispdev_oled;
// (void)ui;
// OLEDDisplayUi ui(&dispdev);
// }
// }
// #else
Screen::Screen(ScanI2C::DeviceAddress address, meshtastic_Config_DisplayConfig_OledType screenType, OLEDDISPLAY_GEOMETRY geometry) Screen::Screen(ScanI2C::DeviceAddress address, meshtastic_Config_DisplayConfig_OledType screenType, OLEDDISPLAY_GEOMETRY geometry)
: concurrency::OSThread("Screen"), address_found(address), model(screenType), geometry(geometry), cmdQueue(32), : concurrency::OSThread("Screen"), address_found(address), model(screenType), geometry(geometry), cmdQueue(32)
dispdev(address.address, -1, -1, geometry, (address.port == ScanI2C::I2CPort::WIRE1) ? HW_I2C::I2C_TWO : HW_I2C::I2C_ONE),
ui(&dispdev)
{ {
#if defined(USE_SH1106) || defined(USE_SH1107) || defined(USE_SH1107_128_64)
dispdev = new SH1106Wire(address.address, -1, -1, geometry,
(address.port == ScanI2C::I2CPort::WIRE1) ? HW_I2C::I2C_TWO : HW_I2C::I2C_ONE);
#elif defined(USE_SSD1306)
dispdev = new SSD1306Wire(address.address, -1, -1, geometry,
(address.port == ScanI2C::I2CPort::WIRE1) ? HW_I2C::I2C_TWO : HW_I2C::I2C_ONE);
#elif defined(ST7735_CS) || defined(ILI9341_DRIVER) || defined(ST7789_CS) || defined(RAK14014)
dispdev = new TFTDisplay(address.address, -1, -1, geometry,
(address.port == ScanI2C::I2CPort::WIRE1) ? HW_I2C::I2C_TWO : HW_I2C::I2C_ONE);
#elif defined(USE_EINK)
dispdev = new EInkDisplay(address.address, -1, -1, geometry,
(address.port == ScanI2C::I2CPort::WIRE1) ? HW_I2C::I2C_TWO : HW_I2C::I2C_ONE);
#elif defined(USE_ST7567)
dispdev = new ST7567Wire(address.address, -1, -1, geometry,
(address.port == ScanI2C::I2CPort::WIRE1) ? HW_I2C::I2C_TWO : HW_I2C::I2C_ONE);
#elif ARCH_PORTDUINO
if (settingsMap[displayPanel] != no_screen) {
LOG_DEBUG("Making TFTDisplay!\n");
dispdev = new TFTDisplay(address.address, -1, -1, geometry,
(address.port == ScanI2C::I2CPort::WIRE1) ? HW_I2C::I2C_TWO : HW_I2C::I2C_ONE);
} else {
dispdev = new AutoOLEDWire(address.address, -1, -1, geometry,
(address.port == ScanI2C::I2CPort::WIRE1) ? HW_I2C::I2C_TWO : HW_I2C::I2C_ONE);
isAUTOOled = true;
}
#else
dispdev = new AutoOLEDWire(address.address, -1, -1, geometry,
(address.port == ScanI2C::I2CPort::WIRE1) ? HW_I2C::I2C_TWO : HW_I2C::I2C_ONE);
isAUTOOled = true;
#endif
ui = new OLEDDisplayUi(dispdev);
cmdQueue.setReader(this); cmdQueue.setReader(this);
} }
// #endif
/** /**
* Prepare the display for the unit going to the lowest power mode possible. Most screens will just * Prepare the display for the unit going to the lowest power mode possible. Most screens will just
* poweroff, but eink screens will show a "I'm sleeping" graphic, possibly with a QR code * poweroff, but eink screens will show a "I'm sleeping" graphic, possibly with a QR code
@@ -930,8 +964,8 @@ void Screen::doDeepSleep()
#ifdef USE_EINK #ifdef USE_EINK
static FrameCallback sleepFrames[] = {drawSleepScreen}; static FrameCallback sleepFrames[] = {drawSleepScreen};
static const int sleepFrameCount = sizeof(sleepFrames) / sizeof(sleepFrames[0]); static const int sleepFrameCount = sizeof(sleepFrames) / sizeof(sleepFrames[0]);
ui.setFrames(sleepFrames, sleepFrameCount); ui->setFrames(sleepFrames, sleepFrameCount);
ui.update(); ui->update();
#endif #endif
setOn(false); setOn(false);
} }
@@ -944,14 +978,22 @@ void Screen::handleSetOn(bool on)
if (on != screenOn) { if (on != screenOn) {
if (on) { if (on) {
LOG_INFO("Turning on screen\n"); LOG_INFO("Turning on screen\n");
dispdev.displayOn(); #ifdef T_WATCH_S3
dispdev.displayOn(); PMU->enablePowerOutput(XPOWERS_ALDO2);
#endif
#if !ARCH_PORTDUINO
dispdev->displayOn();
#endif
dispdev->displayOn();
enabled = true; enabled = true;
setInterval(0); // Draw ASAP setInterval(0); // Draw ASAP
runASAP = true; runASAP = true;
} else { } else {
LOG_INFO("Turning off screen\n"); LOG_INFO("Turning off screen\n");
dispdev.displayOff(); dispdev->displayOff();
#ifdef T_WATCH_S3
PMU->disablePowerOutput(XPOWERS_ALDO2);
#endif
enabled = false; enabled = false;
} }
screenOn = on; screenOn = on;
@@ -965,32 +1007,33 @@ void Screen::setup()
useDisplay = true; useDisplay = true;
#ifdef AutoOLEDWire_h #ifdef AutoOLEDWire_h
dispdev.setDetected(model); if (isAUTOOled)
static_cast<AutoOLEDWire *>(dispdev)->setDetected(model);
#endif #endif
#ifdef USE_SH1107_128_64 #ifdef USE_SH1107_128_64
dispdev.setSubtype(7); static_cast<SH1106Wire *>(dispdev)->setSubtype(7);
#endif #endif
// Initialising the UI will init the display too. // Initialising the UI will init the display too.
ui.init(); ui->init();
displayWidth = dispdev.width(); displayWidth = dispdev->width();
displayHeight = dispdev.height(); displayHeight = dispdev->height();
ui.setTimePerTransition(0); ui->setTimePerTransition(0);
ui.setIndicatorPosition(BOTTOM); ui->setIndicatorPosition(BOTTOM);
// Defines where the first frame is located in the bar. // Defines where the first frame is located in the bar.
ui.setIndicatorDirection(LEFT_RIGHT); ui->setIndicatorDirection(LEFT_RIGHT);
ui.setFrameAnimation(SLIDE_LEFT); ui->setFrameAnimation(SLIDE_LEFT);
// Don't show the page swipe dots while in boot screen. // Don't show the page swipe dots while in boot screen.
ui.disableAllIndicators(); ui->disableAllIndicators();
// Store a pointer to Screen so we can get to it from static functions. // Store a pointer to Screen so we can get to it from static functions.
ui.getUiState()->userData = this; ui->getUiState()->userData = this;
// Set the utf8 conversion function // Set the utf8 conversion function
dispdev.setFontTableLookupFunction(customFontTableLookup); dispdev->setFontTableLookupFunction(customFontTableLookup);
if (strlen(oemStore.oem_text) > 0) if (strlen(oemStore.oem_text) > 0)
logo_timeout *= 2; logo_timeout *= 2;
@@ -998,23 +1041,27 @@ void Screen::setup()
// Add frames. // Add frames.
static FrameCallback bootFrames[] = {drawBootScreen}; static FrameCallback bootFrames[] = {drawBootScreen};
static const int bootFrameCount = sizeof(bootFrames) / sizeof(bootFrames[0]); static const int bootFrameCount = sizeof(bootFrames) / sizeof(bootFrames[0]);
ui.setFrames(bootFrames, bootFrameCount); ui->setFrames(bootFrames, bootFrameCount);
// No overlays. // No overlays.
ui.setOverlays(nullptr, 0); ui->setOverlays(nullptr, 0);
// Require presses to switch between frames. // Require presses to switch between frames.
ui.disableAutoTransition(); ui->disableAutoTransition();
// Set up a log buffer with 3 lines, 32 chars each. // Set up a log buffer with 3 lines, 32 chars each.
dispdev.setLogBuffer(3, 32); dispdev->setLogBuffer(3, 32);
#ifdef SCREEN_MIRROR #ifdef SCREEN_MIRROR
dispdev.mirrorScreen(); dispdev->mirrorScreen();
#else #else
// Standard behaviour is to FLIP the screen (needed on T-Beam). If this config item is set, unflip it, and thereby logically // Standard behaviour is to FLIP the screen (needed on T-Beam). If this config item is set, unflip it, and thereby logically
// flip it. If you have a headache now, you're welcome. // flip it. If you have a headache now, you're welcome.
if (!config.display.flip_screen) { if (!config.display.flip_screen) {
dispdev.flipScreenVertically(); #if defined(ST7735_CS) || defined(ILI9341_DRIVER) || defined(ST7789_CS) || defined(RAK14014)
static_cast<TFTDisplay *>(dispdev)->flipScreenVertically();
#else
dispdev->flipScreenVertically();
#endif
} }
#endif #endif
@@ -1022,24 +1069,41 @@ void Screen::setup()
uint8_t dmac[6]; uint8_t dmac[6];
getMacAddr(dmac); getMacAddr(dmac);
snprintf(ourId, sizeof(ourId), "%02x%02x", dmac[4], dmac[5]); snprintf(ourId, sizeof(ourId), "%02x%02x", dmac[4], dmac[5]);
#if ARCH_PORTDUINO
handleSetOn(false); // force clean init
#endif
// Turn on the display. // Turn on the display.
handleSetOn(true); handleSetOn(true);
// On some ssd1306 clones, the first draw command is discarded, so draw it // On some ssd1306 clones, the first draw command is discarded, so draw it
// twice initially. Skip this for EINK Displays to save a few seconds during boot // twice initially. Skip this for EINK Displays to save a few seconds during boot
ui.update(); ui->update();
#ifndef USE_EINK #ifndef USE_EINK
ui.update(); ui->update();
#endif #endif
serialSinceMsec = millis(); serialSinceMsec = millis();
#if ARCH_PORTDUINO
if (settingsMap[touchscreenModule]) {
touchScreenImpl1 =
new TouchScreenImpl1(dispdev->getWidth(), dispdev->getHeight(), static_cast<TFTDisplay *>(dispdev)->getTouch);
touchScreenImpl1->init();
}
#elif HAS_TOUCHSCREEN
touchScreenImpl1 =
new TouchScreenImpl1(dispdev->getWidth(), dispdev->getHeight(), static_cast<TFTDisplay *>(dispdev)->getTouch);
touchScreenImpl1->init();
#endif
// Subscribe to status updates // Subscribe to status updates
powerStatusObserver.observe(&powerStatus->onNewStatus); powerStatusObserver.observe(&powerStatus->onNewStatus);
gpsStatusObserver.observe(&gpsStatus->onNewStatus); gpsStatusObserver.observe(&gpsStatus->onNewStatus);
nodeStatusObserver.observe(&nodeStatus->onNewStatus); nodeStatusObserver.observe(&nodeStatus->onNewStatus);
if (textMessageModule) if (textMessageModule)
textMessageObserver.observe(textMessageModule); textMessageObserver.observe(textMessageModule);
if (inputBroker)
inputObserver.observe(inputBroker);
// Modules can notify screen about refresh // Modules can notify screen about refresh
MeshModule::observeUIEvents(&uiFrameEventObserver); MeshModule::observeUIEvents(&uiFrameEventObserver);
@@ -1049,7 +1113,7 @@ void Screen::forceDisplay()
{ {
// Nasty hack to force epaper updates for 'key' frames. FIXME, cleanup. // Nasty hack to force epaper updates for 'key' frames. FIXME, cleanup.
#ifdef USE_EINK #ifdef USE_EINK
dispdev.forceDisplay(); static_cast<EInkDisplay *>(dispdev)->forceDisplay();
#endif #endif
} }
@@ -1080,10 +1144,10 @@ int32_t Screen::runOnce()
// Change frames. // Change frames.
static FrameCallback bootOEMFrames[] = {drawOEMBootScreen}; static FrameCallback bootOEMFrames[] = {drawOEMBootScreen};
static const int bootOEMFrameCount = sizeof(bootOEMFrames) / sizeof(bootOEMFrames[0]); static const int bootOEMFrameCount = sizeof(bootOEMFrames) / sizeof(bootOEMFrames[0]);
ui.setFrames(bootOEMFrames, bootOEMFrameCount); ui->setFrames(bootOEMFrames, bootOEMFrameCount);
ui.update(); ui->update();
#ifndef USE_EINK #ifndef USE_EINK
ui.update(); ui->update();
#endif #endif
showingOEMBootScreen = false; showingOEMBootScreen = false;
} }
@@ -1117,6 +1181,12 @@ int32_t Screen::runOnce()
handleOnPress(); handleOnPress();
} }
break; break;
case Cmd::SHOW_PREV_FRAME:
handleShowPrevFrame();
break;
case Cmd::SHOW_NEXT_FRAME:
handleShowNextFrame();
break;
case Cmd::START_BLUETOOTH_PIN_SCREEN: case Cmd::START_BLUETOOTH_PIN_SCREEN:
handleStartBluetoothPinScreen(cmd.bluetooth_pin); handleStartBluetoothPinScreen(cmd.bluetooth_pin);
break; break;
@@ -1150,16 +1220,16 @@ int32_t Screen::runOnce()
// this must be before the frameState == FIXED check, because we always // this must be before the frameState == FIXED check, because we always
// want to draw at least one FIXED frame before doing forceDisplay // want to draw at least one FIXED frame before doing forceDisplay
ui.update(); ui->update();
// Switch to a low framerate (to save CPU) when we are not in transition // Switch to a low framerate (to save CPU) when we are not in transition
// but we should only call setTargetFPS when framestate changes, because // but we should only call setTargetFPS when framestate changes, because
// otherwise that breaks animations. // otherwise that breaks animations.
if (targetFramerate != IDLE_FRAMERATE && ui.getUiState()->frameState == FIXED) { if (targetFramerate != IDLE_FRAMERATE && ui->getUiState()->frameState == FIXED) {
// oldFrameState = ui.getUiState()->frameState; // oldFrameState = ui->getUiState()->frameState;
targetFramerate = IDLE_FRAMERATE; targetFramerate = IDLE_FRAMERATE;
ui.setTargetFPS(targetFramerate); ui->setTargetFPS(targetFramerate);
forceDisplay(); forceDisplay();
} }
@@ -1175,7 +1245,7 @@ int32_t Screen::runOnce()
} }
// LOG_DEBUG("want fps %d, fixed=%d\n", targetFramerate, // LOG_DEBUG("want fps %d, fixed=%d\n", targetFramerate,
// ui.getUiState()->frameState); If we are scrolling we need to be called // ui->getUiState()->frameState); If we are scrolling we need to be called
// soon, otherwise just 1 fps (to save CPU) We also ask to be called twice // soon, otherwise just 1 fps (to save CPU) We also ask to be called twice
// as fast as we really need so that any rounding errors still result with // as fast as we really need so that any rounding errors still result with
// the correct framerate // the correct framerate
@@ -1207,8 +1277,8 @@ void Screen::setSSLFrames()
if (address_found.address) { if (address_found.address) {
// LOG_DEBUG("showing SSL frames\n"); // LOG_DEBUG("showing SSL frames\n");
static FrameCallback sslFrames[] = {drawSSLScreen}; static FrameCallback sslFrames[] = {drawSSLScreen};
ui.setFrames(sslFrames, 1); ui->setFrames(sslFrames, 1);
ui.update(); ui->update();
} }
} }
@@ -1218,11 +1288,8 @@ void Screen::setWelcomeFrames()
{ {
if (address_found.address) { if (address_found.address) {
// LOG_DEBUG("showing Welcome frames\n"); // LOG_DEBUG("showing Welcome frames\n");
ui.disableAllIndicators(); static FrameCallback frames[] = {drawWelcomeScreen};
setFrameImmediateDraw(frames);
static FrameCallback welcomeFrames[] = {drawWelcomeScreen};
ui.setFrames(welcomeFrames, 1);
ui.update();
} }
} }
@@ -1286,7 +1353,7 @@ void Screen::setFrames()
// call a method on debugInfoScreen object (for more details) // call a method on debugInfoScreen object (for more details)
normalFrames[numframes++] = &Screen::drawDebugInfoSettingsTrampoline; normalFrames[numframes++] = &Screen::drawDebugInfoSettingsTrampoline;
#ifdef ARCH_ESP32 #if HAS_WIFI && !defined(ARCH_PORTDUINO)
if (isWifiAvailable()) { if (isWifiAvailable()) {
// call a method on debugInfoScreen object (for more details) // call a method on debugInfoScreen object (for more details)
normalFrames[numframes++] = &Screen::drawDebugInfoWiFiTrampoline; normalFrames[numframes++] = &Screen::drawDebugInfoWiFiTrampoline;
@@ -1295,8 +1362,8 @@ void Screen::setFrames()
LOG_DEBUG("Finished building frames. numframes: %d\n", numframes); LOG_DEBUG("Finished building frames. numframes: %d\n", numframes);
ui.setFrames(normalFrames, numframes); ui->setFrames(normalFrames, numframes);
ui.enableAllIndicators(); ui->enableAllIndicators();
prevFrame = -1; // Force drawNodeInfo to pick a new node (because our list prevFrame = -1; // Force drawNodeInfo to pick a new node (because our list
// just changed) // just changed)
@@ -1309,12 +1376,15 @@ void Screen::handleStartBluetoothPinScreen(uint32_t pin)
LOG_DEBUG("showing bluetooth screen\n"); LOG_DEBUG("showing bluetooth screen\n");
showingNormalScreen = false; showingNormalScreen = false;
static FrameCallback btFrames[] = {drawFrameBluetooth}; static FrameCallback frames[] = {drawFrameBluetooth};
snprintf(btPIN, sizeof(btPIN), "%06u", pin); snprintf(btPIN, sizeof(btPIN), "%06u", pin);
setFrameImmediateDraw(frames);
}
ui.disableAllIndicators(); void Screen::setFrameImmediateDraw(FrameCallback *drawFrames)
ui.setFrames(btFrames, 1); {
ui->disableAllIndicators();
ui->setFrames(drawFrames, 1);
setFastFramerate(); setFastFramerate();
} }
@@ -1323,11 +1393,12 @@ void Screen::handleShutdownScreen()
LOG_DEBUG("showing shutdown screen\n"); LOG_DEBUG("showing shutdown screen\n");
showingNormalScreen = false; showingNormalScreen = false;
static FrameCallback shutdownFrames[] = {drawFrameShutdown}; auto frame = [](OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y) -> void {
drawFrameText(display, state, x, y, "Shutting down...");
};
static FrameCallback frames[] = {frame};
ui.disableAllIndicators(); setFrameImmediateDraw(frames);
ui.setFrames(shutdownFrames, 1);
setFastFramerate();
} }
void Screen::handleRebootScreen() void Screen::handleRebootScreen()
@@ -1335,11 +1406,11 @@ void Screen::handleRebootScreen()
LOG_DEBUG("showing reboot screen\n"); LOG_DEBUG("showing reboot screen\n");
showingNormalScreen = false; showingNormalScreen = false;
static FrameCallback rebootFrames[] = {drawFrameReboot}; auto frame = [](OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y) -> void {
drawFrameText(display, state, x, y, "Rebooting...");
ui.disableAllIndicators(); };
ui.setFrames(rebootFrames, 1); static FrameCallback frames[] = {frame};
setFastFramerate(); setFrameImmediateDraw(frames);
} }
void Screen::handleStartFirmwareUpdateScreen() void Screen::handleStartFirmwareUpdateScreen()
@@ -1347,28 +1418,25 @@ void Screen::handleStartFirmwareUpdateScreen()
LOG_DEBUG("showing firmware screen\n"); LOG_DEBUG("showing firmware screen\n");
showingNormalScreen = false; showingNormalScreen = false;
static FrameCallback btFrames[] = {drawFrameFirmware}; static FrameCallback frames[] = {drawFrameFirmware};
setFrameImmediateDraw(frames);
ui.disableAllIndicators();
ui.setFrames(btFrames, 1);
setFastFramerate();
} }
void Screen::blink() void Screen::blink()
{ {
setFastFramerate(); setFastFramerate();
uint8_t count = 10; uint8_t count = 10;
dispdev.setBrightness(254); dispdev->setBrightness(254);
while (count > 0) { while (count > 0) {
dispdev.fillRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT); dispdev->fillRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
dispdev.display(); dispdev->display();
delay(50); delay(50);
dispdev.clear(); dispdev->clear();
dispdev.display(); dispdev->display();
delay(50); delay(50);
count = count - 1; count = count - 1;
} }
dispdev.setBrightness(brightness); dispdev->setBrightness(brightness);
} }
std::string Screen::drawTimeDelta(uint32_t days, uint32_t hours, uint32_t minutes, uint32_t seconds) std::string Screen::drawTimeDelta(uint32_t days, uint32_t hours, uint32_t minutes, uint32_t seconds)
@@ -1396,15 +1464,37 @@ void Screen::handlePrint(const char *text)
if (!useDisplay || !showingNormalScreen) if (!useDisplay || !showingNormalScreen)
return; return;
dispdev.print(text); dispdev->print(text);
} }
void Screen::handleOnPress() void Screen::handleOnPress()
{ {
// If screen was off, just wake it, otherwise advance to next frame // If screen was off, just wake it, otherwise advance to next frame
// If we are in a transition, the press must have bounced, drop it. // If we are in a transition, the press must have bounced, drop it.
if (ui.getUiState()->frameState == FIXED) { if (ui->getUiState()->frameState == FIXED) {
ui.nextFrame(); ui->nextFrame();
lastScreenTransition = millis();
setFastFramerate();
}
}
void Screen::handleShowPrevFrame()
{
// If screen was off, just wake it, otherwise go back to previous frame
// If we are in a transition, the press must have bounced, drop it.
if (ui->getUiState()->frameState == FIXED) {
ui->previousFrame();
lastScreenTransition = millis();
setFastFramerate();
}
}
void Screen::handleShowNextFrame()
{
// If screen was off, just wake it, otherwise advance to next frame
// If we are in a transition, the press must have bounced, drop it.
if (ui->getUiState()->frameState == FIXED) {
ui->nextFrame();
lastScreenTransition = millis(); lastScreenTransition = millis();
setFastFramerate(); setFastFramerate();
} }
@@ -1419,7 +1509,7 @@ void Screen::setFastFramerate()
// We are about to start a transition so speed up fps // We are about to start a transition so speed up fps
targetFramerate = SCREEN_TRANSITION_FRAMERATE; targetFramerate = SCREEN_TRANSITION_FRAMERATE;
ui.setTargetFPS(targetFramerate); ui->setTargetFPS(targetFramerate);
setInterval(0); // redraw ASAP setInterval(0); // redraw ASAP
runASAP = true; runASAP = true;
} }
@@ -1464,7 +1554,7 @@ void DebugInfo::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16
drawNodes(display, x + (SCREEN_WIDTH * 0.25), y + 3, nodeStatus); drawNodes(display, x + (SCREEN_WIDTH * 0.25), y + 3, nodeStatus);
} }
// Display GPS status // Display GPS status
if (!config.position.gps_enabled) { if (config.position.gps_mode != meshtastic_Config_PositionConfig_GpsMode_ENABLED) {
drawGPSpowerstat(display, x, y + 2, gpsStatus); drawGPSpowerstat(display, x, y + 2, gpsStatus);
} else { } else {
if (config.display.displaymode == meshtastic_Config_DisplayConfig_DisplayMode_DEFAULT) { if (config.display.displaymode == meshtastic_Config_DisplayConfig_DisplayMode_DEFAULT) {
@@ -1482,7 +1572,8 @@ void DebugInfo::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16
#ifdef ARCH_ESP32 #ifdef ARCH_ESP32
if (millis() - storeForwardModule->lastHeartbeat > if (millis() - storeForwardModule->lastHeartbeat >
(storeForwardModule->heartbeatInterval * 1200)) { // no heartbeat, overlap a bit (storeForwardModule->heartbeatInterval * 1200)) { // no heartbeat, overlap a bit
#if defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7735_CS) #if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7735_CS) || defined(ST7789_CS)) && \
!defined(DISPLAY_FORCE_SMALL_FONTS)
display->drawFastImage(x + SCREEN_WIDTH - 14 - display->getStringWidth(ourId), y + 3 + FONT_HEIGHT_SMALL, 12, 8, display->drawFastImage(x + SCREEN_WIDTH - 14 - display->getStringWidth(ourId), y + 3 + FONT_HEIGHT_SMALL, 12, 8,
imgQuestionL1); imgQuestionL1);
display->drawFastImage(x + SCREEN_WIDTH - 14 - display->getStringWidth(ourId), y + 11 + FONT_HEIGHT_SMALL, 12, 8, display->drawFastImage(x + SCREEN_WIDTH - 14 - display->getStringWidth(ourId), y + 11 + FONT_HEIGHT_SMALL, 12, 8,
@@ -1492,7 +1583,8 @@ void DebugInfo::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16
imgQuestion); imgQuestion);
#endif #endif
} else { } else {
#if defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7735_CS) #if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7735_CS) || defined(ST7789_CS)) && \
!defined(DISPLAY_FORCE_SMALL_FONTS)
display->drawFastImage(x + SCREEN_WIDTH - 18 - display->getStringWidth(ourId), y + 3 + FONT_HEIGHT_SMALL, 16, 8, display->drawFastImage(x + SCREEN_WIDTH - 18 - display->getStringWidth(ourId), y + 3 + FONT_HEIGHT_SMALL, 16, 8,
imgSFL1); imgSFL1);
display->drawFastImage(x + SCREEN_WIDTH - 18 - display->getStringWidth(ourId), y + 11 + FONT_HEIGHT_SMALL, 16, 8, display->drawFastImage(x + SCREEN_WIDTH - 18 - display->getStringWidth(ourId), y + 11 + FONT_HEIGHT_SMALL, 16, 8,
@@ -1504,7 +1596,9 @@ void DebugInfo::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16
} }
#endif #endif
} else { } else {
#if defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7735_CS) // TODO: Raspberry Pi supports more than just the one screen size
#if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7735_CS) || defined(ST7789_CS) || ARCH_PORTDUINO) && \
!defined(DISPLAY_FORCE_SMALL_FONTS)
display->drawFastImage(x + SCREEN_WIDTH - 14 - display->getStringWidth(ourId), y + 3 + FONT_HEIGHT_SMALL, 12, 8, display->drawFastImage(x + SCREEN_WIDTH - 14 - display->getStringWidth(ourId), y + 3 + FONT_HEIGHT_SMALL, 12, 8,
imgInfoL1); imgInfoL1);
display->drawFastImage(x + SCREEN_WIDTH - 14 - display->getStringWidth(ourId), y + 11 + FONT_HEIGHT_SMALL, 12, 8, display->drawFastImage(x + SCREEN_WIDTH - 14 - display->getStringWidth(ourId), y + 11 + FONT_HEIGHT_SMALL, 12, 8,
@@ -1530,7 +1624,7 @@ void DebugInfo::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16
// Jm // Jm
void DebugInfo::drawFrameWiFi(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y) void DebugInfo::drawFrameWiFi(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
{ {
#if HAS_WIFI #if HAS_WIFI && !defined(ARCH_PORTDUINO)
const char *wifiName = config.network.wifi_ssid; const char *wifiName = config.network.wifi_ssid;
display->setFont(FONT_SMALL); display->setFont(FONT_SMALL);
@@ -1584,69 +1678,19 @@ void DebugInfo::drawFrameWiFi(OLEDDisplay *display, OLEDDisplayUiState *state, i
display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "Connection Failed"); display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "Connection Failed");
} else if (WiFi.status() == WL_IDLE_STATUS) { } else if (WiFi.status() == WL_IDLE_STATUS) {
display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "Idle ... Reconnecting"); display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "Idle ... Reconnecting");
} else { }
#ifdef ARCH_ESP32
else {
// Codes: // Codes:
// https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/wifi.html#wi-fi-reason-code // https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/wifi.html#wi-fi-reason-code
if (getWifiDisconnectReason() == 2) { display->drawString(x, y + FONT_HEIGHT_SMALL * 1,
display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "Authentication Invalid"); WiFi.disconnectReasonName(static_cast<wifi_err_reason_t>(getWifiDisconnectReason())));
} else if (getWifiDisconnectReason() == 3) {
display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "De-authenticated");
} else if (getWifiDisconnectReason() == 4) {
display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "Disassociated Expired");
} else if (getWifiDisconnectReason() == 5) {
display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "AP - Too Many Clients");
} else if (getWifiDisconnectReason() == 6) {
display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "NOT_AUTHED");
} else if (getWifiDisconnectReason() == 7) {
display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "NOT_ASSOCED");
} else if (getWifiDisconnectReason() == 8) {
display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "Disassociated");
} else if (getWifiDisconnectReason() == 9) {
display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "ASSOC_NOT_AUTHED");
} else if (getWifiDisconnectReason() == 10) {
display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "DISASSOC_PWRCAP_BAD");
} else if (getWifiDisconnectReason() == 11) {
display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "DISASSOC_SUPCHAN_BAD");
} else if (getWifiDisconnectReason() == 13) {
display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "IE_INVALID");
} else if (getWifiDisconnectReason() == 14) {
display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "MIC_FAILURE");
} else if (getWifiDisconnectReason() == 15) {
display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "AP Handshake Timeout");
} else if (getWifiDisconnectReason() == 16) {
display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "GROUP_KEY_UPDATE_TIMEOUT");
} else if (getWifiDisconnectReason() == 17) {
display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "IE_IN_4WAY_DIFFERS");
} else if (getWifiDisconnectReason() == 18) {
display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "Invalid Group Cipher");
} else if (getWifiDisconnectReason() == 19) {
display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "Invalid Pairwise Cipher");
} else if (getWifiDisconnectReason() == 20) {
display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "AKMP_INVALID");
} else if (getWifiDisconnectReason() == 21) {
display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "UNSUPP_RSN_IE_VERSION");
} else if (getWifiDisconnectReason() == 22) {
display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "INVALID_RSN_IE_CAP");
} else if (getWifiDisconnectReason() == 23) {
display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "802_1X_AUTH_FAILED");
} else if (getWifiDisconnectReason() == 24) {
display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "CIPHER_SUITE_REJECTED");
} else if (getWifiDisconnectReason() == 200) {
display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "BEACON_TIMEOUT");
} else if (getWifiDisconnectReason() == 201) {
display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "AP Not Found");
} else if (getWifiDisconnectReason() == 202) {
display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "AUTH_FAIL");
} else if (getWifiDisconnectReason() == 203) {
display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "ASSOC_FAIL");
} else if (getWifiDisconnectReason() == 204) {
display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "HANDSHAKE_TIMEOUT");
} else if (getWifiDisconnectReason() == 205) {
display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "Connection Failed");
} else {
display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "Unknown Status");
}
} }
#else
else {
display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "Unkown status: " + String(WiFi.status()));
}
#endif
display->drawString(x, y + FONT_HEIGHT_SMALL * 2, "SSID: " + String(wifiName)); display->drawString(x, y + FONT_HEIGHT_SMALL * 2, "SSID: " + String(wifiName));
@@ -1692,37 +1736,7 @@ void DebugInfo::drawFrameSettings(OLEDDisplay *display, OLEDDisplayUiState *stat
display->drawString(x + 1, y, String("USB")); display->drawString(x + 1, y, String("USB"));
} }
auto mode = ""; auto mode = DisplayFormatters::getModemPresetDisplayName(config.lora.modem_preset, true);
switch (config.lora.modem_preset) {
case meshtastic_Config_LoRaConfig_ModemPreset_SHORT_SLOW:
mode = "ShortS";
break;
case meshtastic_Config_LoRaConfig_ModemPreset_SHORT_FAST:
mode = "ShortF";
break;
case meshtastic_Config_LoRaConfig_ModemPreset_MEDIUM_SLOW:
mode = "MedS";
break;
case meshtastic_Config_LoRaConfig_ModemPreset_MEDIUM_FAST:
mode = "MedF";
break;
case meshtastic_Config_LoRaConfig_ModemPreset_LONG_SLOW:
mode = "LongS";
break;
case meshtastic_Config_LoRaConfig_ModemPreset_LONG_FAST:
mode = "LongF";
break;
case meshtastic_Config_LoRaConfig_ModemPreset_LONG_MODERATE:
mode = "LongM";
break;
case meshtastic_Config_LoRaConfig_ModemPreset_VERY_LONG_SLOW:
mode = "VeryL";
break;
default:
mode = "Custom";
break;
}
display->drawString(x + SCREEN_WIDTH - display->getStringWidth(mode), y, mode); display->drawString(x + SCREEN_WIDTH - display->getStringWidth(mode), y, mode);
if (config.display.heading_bold) if (config.display.heading_bold)
@@ -1768,7 +1782,7 @@ void DebugInfo::drawFrameSettings(OLEDDisplay *display, OLEDDisplayUiState *stat
char chUtil[13]; char chUtil[13];
snprintf(chUtil, sizeof(chUtil), "ChUtil %2.0f%%", airTime->channelUtilizationPercent()); snprintf(chUtil, sizeof(chUtil), "ChUtil %2.0f%%", airTime->channelUtilizationPercent());
display->drawString(x + SCREEN_WIDTH - display->getStringWidth(chUtil), y + FONT_HEIGHT_SMALL * 1, chUtil); display->drawString(x + SCREEN_WIDTH - display->getStringWidth(chUtil), y + FONT_HEIGHT_SMALL * 1, chUtil);
if (config.position.gps_enabled) { if (config.position.gps_mode == meshtastic_Config_PositionConfig_GpsMode_ENABLED) {
// Line 3 // Line 3
if (config.display.gps_format != if (config.display.gps_format !=
meshtastic_Config_DisplayConfig_GpsCoordinateFormat_DMS) // if DMS then don't draw altitude meshtastic_Config_DisplayConfig_GpsCoordinateFormat_DMS) // if DMS then don't draw altitude
@@ -1777,10 +1791,7 @@ void DebugInfo::drawFrameSettings(OLEDDisplay *display, OLEDDisplayUiState *stat
// Line 4 // Line 4
drawGPScoordinates(display, x, y + FONT_HEIGHT_SMALL * 3, gpsStatus); drawGPScoordinates(display, x, y + FONT_HEIGHT_SMALL * 3, gpsStatus);
} else { } else {
drawGPSpowerstat(display, x - (SCREEN_WIDTH / 4), y + FONT_HEIGHT_SMALL * 2, gpsStatus); drawGPSpowerstat(display, x, y + FONT_HEIGHT_SMALL * 2, gpsStatus);
#ifdef GPS_POWER_TOGGLE
display->drawString(x + 30, (y + FONT_HEIGHT_SMALL * 3), " by button");
#endif
} }
/* Display a heartbeat pixel that blinks every time the frame is redrawn */ /* Display a heartbeat pixel that blinks every time the frame is redrawn */
#ifdef SHOW_REDRAWS #ifdef SHOW_REDRAWS
@@ -1789,23 +1800,6 @@ void DebugInfo::drawFrameSettings(OLEDDisplay *display, OLEDDisplayUiState *stat
heartbeat = !heartbeat; heartbeat = !heartbeat;
#endif #endif
} }
// adjust Brightness cycle through 1 to 254 as long as attachDuringLongPress is true
void Screen::adjustBrightness()
{
if (!useDisplay)
return;
if (brightness == 254) {
brightness = 0;
} else {
brightness++;
}
int width = brightness / (254.00 / SCREEN_WIDTH);
dispdev.drawRect(0, 30, SCREEN_WIDTH, 4);
dispdev.fillRect(0, 31, width, 2);
dispdev.display();
dispdev.setBrightness(brightness);
}
int Screen::handleStatusUpdate(const meshtastic::Status *arg) int Screen::handleStatusUpdate(const meshtastic::Status *arg)
{ {
@@ -1840,7 +1834,21 @@ int Screen::handleUIFrameEvent(const UIFrameEvent *event)
setFastFramerate(); setFastFramerate();
// TODO: We might also want switch to corresponding frame, // TODO: We might also want switch to corresponding frame,
// but we don't know the exact frame number. // but we don't know the exact frame number.
// ui.switchToFrame(0); // ui->switchToFrame(0);
}
}
return 0;
}
int Screen::handleInputEvent(const InputEvent *event)
{
if (showingNormalScreen && moduleFrames.size() == 0) {
// LOG_DEBUG("Screen::handleInputEvent from %s\n", event->source);
if (event->inputEvent == static_cast<char>(meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_LEFT)) {
showPrevFrame();
} else if (event->inputEvent == static_cast<char>(meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_RIGHT)) {
showNextFrame();
} }
} }
+18 -18
View File
@@ -19,7 +19,6 @@ class Screen
void setup() {} void setup() {}
void setOn(bool) {} void setOn(bool) {}
void print(const char *) {} void print(const char *) {}
void adjustBrightness() {}
void doDeepSleep() {} void doDeepSleep() {}
void forceDisplay() {} void forceDisplay() {}
void startBluetoothPinScreen(uint32_t pin) {} void startBluetoothPinScreen(uint32_t pin) {}
@@ -53,6 +52,7 @@ class Screen
#include "commands.h" #include "commands.h"
#include "concurrency/LockGuard.h" #include "concurrency/LockGuard.h"
#include "concurrency/OSThread.h" #include "concurrency/OSThread.h"
#include "input/InputBroker.h"
#include "mesh/MeshModule.h" #include "mesh/MeshModule.h"
#include "power.h" #include "power.h"
#include <string> #include <string>
@@ -118,6 +118,8 @@ class Screen : public concurrency::OSThread
CallbackObserver<Screen, const meshtastic_MeshPacket *>(this, &Screen::handleTextMessage); CallbackObserver<Screen, const meshtastic_MeshPacket *>(this, &Screen::handleTextMessage);
CallbackObserver<Screen, const UIFrameEvent *> uiFrameEventObserver = CallbackObserver<Screen, const UIFrameEvent *> uiFrameEventObserver =
CallbackObserver<Screen, const UIFrameEvent *>(this, &Screen::handleUIFrameEvent); CallbackObserver<Screen, const UIFrameEvent *>(this, &Screen::handleUIFrameEvent);
CallbackObserver<Screen, const InputEvent *> inputObserver =
CallbackObserver<Screen, const InputEvent *>(this, &Screen::handleInputEvent);
public: public:
explicit Screen(ScanI2C::DeviceAddress, meshtastic_Config_DisplayConfig_OledType, OLEDDISPLAY_GEOMETRY); explicit Screen(ScanI2C::DeviceAddress, meshtastic_Config_DisplayConfig_OledType, OLEDDISPLAY_GEOMETRY);
@@ -152,11 +154,12 @@ class Screen : public concurrency::OSThread
void blink(); void blink();
/// Handles a button press. /// Handle button press, trackball or swipe action)
void onPress() { enqueueCmd(ScreenCmd{.cmd = Cmd::ON_PRESS}); } void onPress() { enqueueCmd(ScreenCmd{.cmd = Cmd::ON_PRESS}); }
void showPrevFrame() { enqueueCmd(ScreenCmd{.cmd = Cmd::SHOW_PREV_FRAME}); }
void showNextFrame() { enqueueCmd(ScreenCmd{.cmd = Cmd::SHOW_NEXT_FRAME}); }
// Implementation to Adjust Brightness // Implementation to Adjust Brightness
void adjustBrightness();
uint8_t brightness = BRIGHTNESS_DEFAULT; uint8_t brightness = BRIGHTNESS_DEFAULT;
/// Starts showing the Bluetooth PIN screen. /// Starts showing the Bluetooth PIN screen.
@@ -301,9 +304,11 @@ class Screen : public concurrency::OSThread
// Use this handle to set things like battery status, user count, GPS status, etc. // Use this handle to set things like battery status, user count, GPS status, etc.
DebugInfo *debug_info() { return &debugInfo; } DebugInfo *debug_info() { return &debugInfo; }
// Handle observer events
int handleStatusUpdate(const meshtastic::Status *arg); int handleStatusUpdate(const meshtastic::Status *arg);
int handleTextMessage(const meshtastic_MeshPacket *arg); int handleTextMessage(const meshtastic_MeshPacket *arg);
int handleUIFrameEvent(const UIFrameEvent *arg); int handleUIFrameEvent(const UIFrameEvent *arg);
int handleInputEvent(const InputEvent *arg);
/// Used to force (super slow) eink displays to draw critical frames /// Used to force (super slow) eink displays to draw critical frames
void forceDisplay(); void forceDisplay();
@@ -319,6 +324,8 @@ class Screen : public concurrency::OSThread
// Called periodically from the main loop. // Called periodically from the main loop.
int32_t runOnce() final; int32_t runOnce() final;
bool isAUTOOled = false;
private: private:
struct ScreenCmd { struct ScreenCmd {
Cmd cmd; Cmd cmd;
@@ -343,6 +350,8 @@ class Screen : public concurrency::OSThread
// Implementations of various commands, called from doTask(). // Implementations of various commands, called from doTask().
void handleSetOn(bool on); void handleSetOn(bool on);
void handleOnPress(); void handleOnPress();
void handleShowNextFrame();
void handleShowPrevFrame();
void handleStartBluetoothPinScreen(uint32_t pin); void handleStartBluetoothPinScreen(uint32_t pin);
void handlePrint(const char *text); void handlePrint(const char *text);
void handleStartFirmwareUpdateScreen(); void handleStartFirmwareUpdateScreen();
@@ -354,6 +363,9 @@ class Screen : public concurrency::OSThread
/// Try to start drawing ASAP /// Try to start drawing ASAP
void setFastFramerate(); void setFastFramerate();
// Sets frame up for immediate drawing
void setFrameImmediateDraw(FrameCallback *drawFrames);
/// Called when debug screen is to be drawn, calls through to debugInfo.drawFrame. /// Called when debug screen is to be drawn, calls through to debugInfo.drawFrame.
static void drawDebugInfoTrampoline(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y); static void drawDebugInfoTrampoline(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y);
@@ -375,23 +387,11 @@ class Screen : public concurrency::OSThread
DebugInfo debugInfo; DebugInfo debugInfo;
/// Display device /// Display device
OLEDDisplay *dispdev;
#if defined(USE_SH1106) || defined(USE_SH1107) || defined(USE_SH1107_128_64)
SH1106Wire dispdev;
#elif defined(USE_SSD1306)
SSD1306Wire dispdev;
#elif defined(ST7735_CS) || defined(ILI9341_DRIVER)
TFTDisplay dispdev;
#elif defined(USE_EINK)
EInkDisplay dispdev;
#elif defined(USE_ST7567)
ST7567Wire dispdev;
#else
AutoOLEDWire dispdev;
#endif
/// UI helper for rendering to frames and switching between them /// UI helper for rendering to frames and switching between them
OLEDDisplayUi ui; OLEDDisplayUi *ui;
}; };
} // namespace graphics } // namespace graphics
#endif #endif
+444 -25
View File
@@ -1,12 +1,16 @@
#include "configuration.h" #include "configuration.h"
#include "main.h"
#if ARCH_PORTDUINO
#include "platform/portduino/PortduinoGlue.h"
#endif
#ifndef TFT_BACKLIGHT_ON #ifndef TFT_BACKLIGHT_ON
#define TFT_BACKLIGHT_ON HIGH #define TFT_BACKLIGHT_ON HIGH
#endif #endif
// convert 24-bit color to 16-bit (56K) #ifndef TFT_MESH
#define COLOR565(r, g, b) (((r & 0xF8) << 8) | ((g & 0xFC) << 3) | ((b & 0xF8) >> 3))
#define TFT_MESH COLOR565(0x67, 0xEA, 0x94) #define TFT_MESH COLOR565(0x67, 0xEA, 0x94)
#endif
#if defined(ST7735S) #if defined(ST7735S)
#include <LovyanGFX.hpp> // Graphics and font library for ST7735 driver chip #include <LovyanGFX.hpp> // Graphics and font library for ST7735 driver chip
@@ -15,6 +19,10 @@
#define TFT_BL ST7735_BACKLIGHT_EN #define TFT_BL ST7735_BACKLIGHT_EN
#endif #endif
#ifndef TFT_INVERT
#define TFT_INVERT true
#endif
class LGFX : public lgfx::LGFX_Device class LGFX : public lgfx::LGFX_Device
{ {
lgfx::Panel_ST7735S _panel_instance; lgfx::Panel_ST7735S _panel_instance;
@@ -64,7 +72,7 @@ class LGFX : public lgfx::LGFX_Device
cfg.dummy_read_pixel = 8; // Number of bits for dummy read before pixel readout cfg.dummy_read_pixel = 8; // Number of bits for dummy read before pixel readout
cfg.dummy_read_bits = 1; // Number of bits for dummy read before non-pixel data read cfg.dummy_read_bits = 1; // Number of bits for dummy read before non-pixel data read
cfg.readable = true; // Set to true if data can be read cfg.readable = true; // Set to true if data can be read
cfg.invert = true; // Set to true if the light/darkness of the panel is reversed cfg.invert = TFT_INVERT; // Set to true if the light/darkness of the panel is reversed
cfg.rgb_order = false; // Set to true if the panel's red and blue are swapped cfg.rgb_order = false; // Set to true if the panel's red and blue are swapped
cfg.dlen_16bit = cfg.dlen_16bit =
false; // Set to true for panels that transmit data length in 16-bit units with 16-bit parallel or SPI false; // Set to true for panels that transmit data length in 16-bit units with 16-bit parallel or SPI
@@ -81,8 +89,16 @@ class LGFX : public lgfx::LGFX_Device
{ {
auto cfg = _light_instance.config(); // Gets a structure for backlight settings. auto cfg = _light_instance.config(); // Gets a structure for backlight settings.
#ifdef ST7735_BL_V03
if (heltec_version == 3) {
cfg.pin_bl = ST7735_BL_V03;
} else {
cfg.pin_bl = ST7735_BL_V05;
}
#else
cfg.pin_bl = ST7735_BL; // Pin number to which the backlight is connected cfg.pin_bl = ST7735_BL; // Pin number to which the backlight is connected
cfg.invert = true; // true to invert the brightness of the backlight #endif
cfg.invert = true; // true to invert the brightness of the backlight
// cfg.freq = 44100; // PWM frequency of backlight // cfg.freq = 44100; // PWM frequency of backlight
// cfg.pwm_channel = 1; // PWM channel number to use // cfg.pwm_channel = 1; // PWM channel number to use
@@ -94,23 +110,318 @@ class LGFX : public lgfx::LGFX_Device
} }
}; };
static LGFX tft; static LGFX *tft = nullptr;
#elif defined(ST7735_CS) || defined(ILI9341_DRIVER) #elif defined(RAK14014)
#include <TFT_eSPI.h> // Graphics and font library for ILI9341 driver chip #include <TFT_eSPI.h>
TFT_eSPI *tft = nullptr;
static TFT_eSPI tft = TFT_eSPI(); // Invoke library, pins defined in User_Setup.h #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 #endif
#if defined(ST7735_CS) || defined(ILI9341_DRIVER) class LGFX : public lgfx::LGFX_Device
{
lgfx::Panel_ST7789 _panel_instance;
lgfx::Bus_SPI _bus_instance;
lgfx::Light_PWM _light_instance;
#if HAS_TOUCHSCREEN
#ifdef T_WATCH_S3
lgfx::Touch_FT5x06 _touch_instance;
#else
lgfx::Touch_GT911 _touch_instance;
#endif
#endif
public:
LGFX(void)
{
{
auto cfg = _bus_instance.config();
// SPI
cfg.spi_host = ST7789_SPI_HOST;
cfg.spi_mode = 0;
cfg.freq_write = SPI_FREQUENCY; // SPI clock for transmission (up to 80MHz, rounded to the value obtained by dividing
// 80MHz by an integer)
cfg.freq_read = SPI_READ_FREQUENCY; // SPI clock when receiving
cfg.spi_3wire = false;
cfg.use_lock = true; // Set to true to use transaction locking
cfg.dma_channel = SPI_DMA_CH_AUTO; // SPI_DMA_CH_AUTO; // Set DMA channel to use (0=not use DMA / 1=1ch / 2=ch /
// SPI_DMA_CH_AUTO=auto setting)
cfg.pin_sclk = ST7789_SCK; // Set SPI SCLK pin number
cfg.pin_mosi = ST7789_SDA; // Set SPI MOSI pin number
cfg.pin_miso = ST7789_MISO; // Set SPI MISO pin number (-1 = disable)
cfg.pin_dc = ST7789_RS; // Set SPI DC pin number (-1 = disable)
_bus_instance.config(cfg); // applies the set value to the bus.
_panel_instance.setBus(&_bus_instance); // set the bus on the panel.
}
{ // Set the display panel control.
auto cfg = _panel_instance.config(); // Gets a structure for display panel settings.
cfg.pin_cs = ST7789_CS; // Pin number where CS is connected (-1 = disable)
cfg.pin_rst = -1; // Pin number where RST is connected (-1 = disable)
cfg.pin_busy = -1; // Pin number where BUSY is connected (-1 = disable)
// The following setting values ​​are general initial values ​​for each panel, so please comment out any
// unknown items and try them.
cfg.panel_width = TFT_WIDTH; // actual displayable width
cfg.panel_height = TFT_HEIGHT; // actual displayable height
cfg.offset_x = TFT_OFFSET_X; // Panel offset amount in X direction
cfg.offset_y = TFT_OFFSET_Y; // Panel offset amount in Y direction
cfg.offset_rotation = TFT_OFFSET_ROTATION; // Rotation direction value offset 0~7 (4~7 is mirrored)
cfg.dummy_read_pixel = 9; // Number of bits for dummy read before pixel readout
cfg.dummy_read_bits = 1; // Number of bits for dummy read before non-pixel data read
cfg.readable = true; // Set to true if data can be read
cfg.invert = true; // Set to true if the light/darkness of the panel is reversed
cfg.rgb_order = false; // Set to true if the panel's red and blue are swapped
cfg.dlen_16bit =
false; // Set to true for panels that transmit data length in 16-bit units with 16-bit parallel or SPI
cfg.bus_shared = true; // If the bus is shared with the SD card, set to true (bus control with drawJpgFile etc.)
// Set the following only when the display is shifted with a driver with a variable number of pixels, such as the
// ST7735 or ILI9163.
// cfg.memory_width = TFT_WIDTH; // Maximum width supported by the driver IC
// cfg.memory_height = TFT_HEIGHT; // Maximum height supported by the driver IC
_panel_instance.config(cfg);
}
// Set the backlight control. (delete if not necessary)
{
auto cfg = _light_instance.config(); // Gets a structure for backlight settings.
cfg.pin_bl = ST7789_BL; // Pin number to which the backlight is connected
cfg.invert = false; // true to invert the brightness of the backlight
// cfg.pwm_channel = 0;
_light_instance.config(cfg);
_panel_instance.setLight(&_light_instance); // Set the backlight on the panel.
}
#if HAS_TOUCHSCREEN
// Configure settings for touch screen control.
{
auto cfg = _touch_instance.config();
cfg.pin_cs = -1;
cfg.x_min = 0;
cfg.x_max = TFT_HEIGHT - 1;
cfg.y_min = 0;
cfg.y_max = TFT_WIDTH - 1;
cfg.pin_int = SCREEN_TOUCH_INT;
cfg.bus_shared = true;
cfg.offset_rotation = TFT_OFFSET_ROTATION;
// cfg.freq = 2500000;
// I2C
cfg.i2c_port = TOUCH_I2C_PORT;
cfg.i2c_addr = TOUCH_SLAVE_ADDRESS;
#ifdef SCREEN_TOUCH_USE_I2C1
cfg.pin_sda = I2C_SDA1;
cfg.pin_scl = I2C_SCL1;
#else
cfg.pin_sda = I2C_SDA;
cfg.pin_scl = I2C_SCL;
#endif
// cfg.freq = 400000;
_touch_instance.config(cfg);
_panel_instance.setTouch(&_touch_instance);
}
#endif
setPanel(&_panel_instance); // Sets the panel to use.
}
};
static LGFX *tft = nullptr;
#elif defined(ILI9341_DRIVER)
#include <LovyanGFX.hpp> // Graphics and font library for ILI9341 driver chip
#if defined(ILI9341_BACKLIGHT_EN) && !defined(TFT_BL)
#define TFT_BL ILI9341_BACKLIGHT_EN
#endif
class LGFX : public lgfx::LGFX_Device
{
lgfx::Panel_ILI9341 _panel_instance;
lgfx::Bus_SPI _bus_instance;
lgfx::Light_PWM _light_instance;
public:
LGFX(void)
{
{
auto cfg = _bus_instance.config();
// configure SPI
cfg.spi_host = ILI9341_SPI_HOST; // ESP32-S2,S3,C3 : SPI2_HOST or SPI3_HOST / ESP32 : VSPI_HOST or HSPI_HOST
cfg.spi_mode = 0;
cfg.freq_write = SPI_FREQUENCY; // SPI clock for transmission (up to 80MHz, rounded to the value obtained by dividing
// 80MHz by an integer)
cfg.freq_read = SPI_READ_FREQUENCY; // SPI clock when receiving
cfg.spi_3wire = false; // Set to true if reception is done on the MOSI pin
cfg.use_lock = true; // Set to true to use transaction locking
cfg.dma_channel = SPI_DMA_CH_AUTO; // SPI_DMA_CH_AUTO; // Set DMA channel to use (0=not use DMA / 1=1ch / 2=ch /
// SPI_DMA_CH_AUTO=auto setting)
cfg.pin_sclk = TFT_SCLK; // Set SPI SCLK pin number
cfg.pin_mosi = TFT_MOSI; // Set SPI MOSI pin number
cfg.pin_miso = TFT_MISO; // Set SPI MISO pin number (-1 = disable)
cfg.pin_dc = TFT_DC; // Set SPI DC pin number (-1 = disable)
_bus_instance.config(cfg); // applies the set value to the bus.
_panel_instance.setBus(&_bus_instance); // set the bus on the panel.
}
{ // Set the display panel control.
auto cfg = _panel_instance.config(); // Gets a structure for display panel settings.
cfg.pin_cs = TFT_CS; // Pin number where CS is connected (-1 = disable)
cfg.pin_rst = TFT_RST; // Pin number where RST is connected (-1 = disable)
cfg.pin_busy = TFT_BUSY; // Pin number where BUSY is connected (-1 = disable)
// The following setting values ​​are general initial values ​​for each panel, so please comment out any
// unknown items and try them.
cfg.panel_width = TFT_WIDTH; // actual displayable width
cfg.panel_height = TFT_HEIGHT; // actual displayable height
cfg.offset_x = TFT_OFFSET_X; // Panel offset amount in X direction
cfg.offset_y = TFT_OFFSET_Y; // Panel offset amount in Y direction
cfg.offset_rotation = 0; // Rotation direction value offset 0~7 (4~7 is upside down)
cfg.dummy_read_pixel = 8; // Number of bits for dummy read before pixel readout
cfg.dummy_read_bits = 1; // Number of bits for dummy read before non-pixel data read
cfg.readable = true; // Set to true if data can be read
cfg.invert = false; // Set to true if the light/darkness of the panel is reversed
cfg.rgb_order = false; // Set to true if the panel's red and blue are swapped
cfg.dlen_16bit =
false; // Set to true for panels that transmit data length in 16-bit units with 16-bit parallel or SPI
cfg.bus_shared = true; // If the bus is shared with the SD card, set to true (bus control with drawJpgFile etc.)
// Set the following only when the display is shifted with a driver with a variable number of pixels, such as the
// ST7735 or ILI9163.
cfg.memory_width = TFT_WIDTH; // Maximum width supported by the driver IC
cfg.memory_height = TFT_HEIGHT; // Maximum height supported by the driver IC
_panel_instance.config(cfg);
}
// Set the backlight control
{
auto cfg = _light_instance.config(); // Gets a structure for backlight settings.
cfg.pin_bl = TFT_BL; // Pin number to which the backlight is connected
cfg.invert = false; // true to invert the brightness of the backlight
// cfg.freq = 44100; // PWM frequency of backlight
// cfg.pwm_channel = 1; // PWM channel number to use
_light_instance.config(cfg);
_panel_instance.setLight(&_light_instance); // Set the backlight on the panel.
}
setPanel(&_panel_instance);
}
};
static LGFX *tft = nullptr;
#elif defined(ST7735_CS)
#include <TFT_eSPI.h> // Graphics and font library for ILI9341 driver chip
static TFT_eSPI *tft = nullptr; // Invoke library, pins defined in User_Setup.h
#elif ARCH_PORTDUINO
#include <LovyanGFX.hpp> // Graphics and font library for ST7735 driver chip
class LGFX : public lgfx::LGFX_Device
{
lgfx::Panel_LCD *_panel_instance;
lgfx::Bus_SPI _bus_instance;
lgfx::ITouch *_touch_instance;
public:
LGFX(void)
{
if (settingsMap[displayPanel] == st7789)
_panel_instance = new lgfx::Panel_ST7789;
else if (settingsMap[displayPanel] == st7735)
_panel_instance = new lgfx::Panel_ST7735;
else if (settingsMap[displayPanel] == st7735s)
_panel_instance = new lgfx::Panel_ST7735S;
else if (settingsMap[displayPanel] == ili9341)
_panel_instance = new lgfx::Panel_ILI9341;
auto buscfg = _bus_instance.config();
buscfg.spi_mode = 0;
buscfg.pin_dc = settingsMap[displayDC]; // Set SPI DC pin number (-1 = disable)
_bus_instance.config(buscfg); // applies the set value to the bus.
_panel_instance->setBus(&_bus_instance); // set the bus on the panel.
auto cfg = _panel_instance->config(); // Gets a structure for display panel settings.
LOG_DEBUG("Height: %d, Width: %d \n", settingsMap[displayHeight], settingsMap[displayWidth]);
cfg.pin_cs = settingsMap[displayCS]; // Pin number where CS is connected (-1 = disable)
cfg.pin_rst = settingsMap[displayReset];
cfg.panel_width = settingsMap[displayWidth]; // actual displayable width
cfg.panel_height = settingsMap[displayHeight]; // actual displayable height
cfg.offset_x = settingsMap[displayOffsetX]; // Panel offset amount in X direction
cfg.offset_y = settingsMap[displayOffsetY]; // Panel offset amount in Y direction
cfg.offset_rotation = 0; // Rotation direction value offset 0~7 (4~7 is mirrored)
cfg.invert = settingsMap[displayInvert]; // Set to true if the light/darkness of the panel is reversed
_panel_instance->config(cfg);
// Configure settings for touch control.
if (settingsMap[touchscreenModule]) {
if (settingsMap[touchscreenModule] == xpt2046) {
_touch_instance = new lgfx::Touch_XPT2046;
} else if (settingsMap[touchscreenModule] == stmpe610) {
_touch_instance = new lgfx::Touch_STMPE610;
}
auto touch_cfg = _touch_instance->config();
touch_cfg.pin_cs = settingsMap[touchscreenCS];
touch_cfg.x_min = 0;
touch_cfg.x_max = settingsMap[displayHeight] - 1;
touch_cfg.y_min = 0;
touch_cfg.y_max = settingsMap[displayWidth] - 1;
touch_cfg.pin_int = settingsMap[touchscreenIRQ];
touch_cfg.bus_shared = true;
touch_cfg.offset_rotation = 1;
_touch_instance->config(touch_cfg);
_panel_instance->setTouch(_touch_instance);
}
setPanel(_panel_instance); // Sets the panel to use.
}
};
static LGFX *tft = nullptr;
#endif
#if defined(ST7735_CS) || defined(ST7789_CS) || defined(ILI9341_DRIVER) || defined(RAK14014) || ARCH_PORTDUINO
#include "SPILock.h" #include "SPILock.h"
#include "TFTDisplay.h" #include "TFTDisplay.h"
#include <SPI.h> #include <SPI.h>
TFTDisplay::TFTDisplay(uint8_t address, int sda, int scl, OLEDDISPLAY_GEOMETRY geometry, HW_I2C i2cBus) TFTDisplay::TFTDisplay(uint8_t address, int sda, int scl, OLEDDISPLAY_GEOMETRY geometry, HW_I2C i2cBus)
{ {
#ifdef SCREEN_ROTATE LOG_DEBUG("TFTDisplay!\n");
#if ARCH_PORTDUINO
if (settingsMap[displayRotate]) {
setGeometry(GEOMETRY_RAWMODE, settingsMap[configNames::displayHeight], settingsMap[configNames::displayWidth]);
} else {
setGeometry(GEOMETRY_RAWMODE, settingsMap[configNames::displayWidth], settingsMap[configNames::displayHeight]);
}
#elif defined(SCREEN_ROTATE)
setGeometry(GEOMETRY_RAWMODE, TFT_HEIGHT, TFT_WIDTH); setGeometry(GEOMETRY_RAWMODE, TFT_HEIGHT, TFT_WIDTH);
#else #else
setGeometry(GEOMETRY_RAWMODE, TFT_WIDTH, TFT_HEIGHT); setGeometry(GEOMETRY_RAWMODE, TFT_WIDTH, TFT_HEIGHT);
@@ -118,19 +429,26 @@ TFTDisplay::TFTDisplay(uint8_t address, int sda, int scl, OLEDDISPLAY_GEOMETRY g
} }
// Write the buffer to the display memory // Write the buffer to the display memory
void TFTDisplay::display(void) void TFTDisplay::display(bool fromBlank)
{ {
if (fromBlank)
tft->fillScreen(TFT_BLACK);
// tft->clear();
concurrency::LockGuard g(spiLock); concurrency::LockGuard g(spiLock);
uint16_t x, y; uint16_t x, y;
for (y = 0; y < displayHeight; y++) { for (y = 0; y < displayHeight; y++) {
for (x = 0; x < displayWidth; x++) { for (x = 0; x < displayWidth; x++) {
// get src pixel in the page based ordering the OLED lib uses FIXME, super inefficent
auto isset = buffer[x + (y / 8) * displayWidth] & (1 << (y & 7)); auto isset = buffer[x + (y / 8) * displayWidth] & (1 << (y & 7));
auto dblbuf_isset = buffer_back[x + (y / 8) * displayWidth] & (1 << (y & 7)); if (!fromBlank) {
if (isset != dblbuf_isset) { // get src pixel in the page based ordering the OLED lib uses FIXME, super inefficent
tft.drawPixel(x, y, isset ? TFT_MESH : TFT_BLACK); auto dblbuf_isset = buffer_back[x + (y / 8) * displayWidth] & (1 << (y & 7));
if (isset != dblbuf_isset) {
tft->drawPixel(x, y, isset ? TFT_MESH : TFT_BLACK);
}
} else if (isset) {
tft->drawPixel(x, y, TFT_MESH);
} }
} }
} }
@@ -149,20 +467,65 @@ void TFTDisplay::sendCommand(uint8_t com)
// handle display on/off directly // handle display on/off directly
switch (com) { switch (com) {
case DISPLAYON: { case DISPLAYON: {
#ifdef TFT_BL #if ARCH_PORTDUINO
display(true);
if (settingsMap[displayBacklight] > 0)
digitalWrite(settingsMap[displayBacklight], TFT_BACKLIGHT_ON);
#elif defined(ST7735_BACKLIGHT_EN_V03) && defined(TFT_BACKLIGHT_ON)
if (heltec_version == 3) {
digitalWrite(ST7735_BACKLIGHT_EN_V03, TFT_BACKLIGHT_ON);
} else {
digitalWrite(ST7735_BACKLIGHT_EN_V05, TFT_BACKLIGHT_ON);
}
#endif
#if defined(TFT_BL) && defined(TFT_BACKLIGHT_ON)
digitalWrite(TFT_BL, TFT_BACKLIGHT_ON); digitalWrite(TFT_BL, TFT_BACKLIGHT_ON);
#endif #endif
#ifdef VTFT_CTRL_V03
if (heltec_version == 3) {
digitalWrite(VTFT_CTRL_V03, LOW);
} else {
digitalWrite(VTFT_CTRL_V05, LOW);
}
#endif
#ifdef VTFT_CTRL #ifdef VTFT_CTRL
digitalWrite(VTFT_CTRL, LOW); digitalWrite(VTFT_CTRL, LOW);
#endif #endif
#ifdef RAK14014
#elif !defined(M5STACK)
tft->setBrightness(128);
#endif
break; break;
} }
case DISPLAYOFF: { case DISPLAYOFF: {
#ifdef TFT_BL #if ARCH_PORTDUINO
tft->clear();
if (settingsMap[displayBacklight] > 0)
digitalWrite(settingsMap[displayBacklight], !TFT_BACKLIGHT_ON);
#elif defined(ST7735_BACKLIGHT_EN_V03) && defined(TFT_BACKLIGHT_ON)
if (heltec_version == 3) {
digitalWrite(ST7735_BACKLIGHT_EN_V03, !TFT_BACKLIGHT_ON);
} else {
digitalWrite(ST7735_BACKLIGHT_EN_V05, !TFT_BACKLIGHT_ON);
}
#endif
#if defined(TFT_BL) && defined(TFT_BACKLIGHT_ON)
digitalWrite(TFT_BL, !TFT_BACKLIGHT_ON); digitalWrite(TFT_BL, !TFT_BACKLIGHT_ON);
#endif #endif
#ifdef VTFT_CTRL_V03
if (heltec_version == 3) {
digitalWrite(VTFT_CTRL_V03, HIGH);
} else {
digitalWrite(VTFT_CTRL_V05, HIGH);
}
#endif
#ifdef VTFT_CTRL #ifdef VTFT_CTRL
digitalWrite(VTFT_CTRL, HIGH); digitalWrite(VTFT_CTRL, HIGH);
#endif
#ifdef RAK14014
#elif !defined(M5STACK)
tft->setBrightness(0);
#endif #endif
break; break;
} }
@@ -173,6 +536,34 @@ void TFTDisplay::sendCommand(uint8_t com)
// Drop all other commands to device (we just update the buffer) // Drop all other commands to device (we just update the buffer)
} }
void TFTDisplay::flipScreenVertically()
{
#if defined(T_WATCH_S3)
LOG_DEBUG("Flip TFT vertically\n"); // T-Watch S3 right-handed orientation
tft->setRotation(0);
#endif
}
bool TFTDisplay::hasTouch(void)
{
#ifdef RAK14014
#elif !defined(M5STACK)
return tft->touch() != nullptr;
#else
return false;
#endif
}
bool TFTDisplay::getTouch(int16_t *x, int16_t *y)
{
#ifdef RAK14014
#elif !defined(M5STACK)
return tft->getTouch(x, y);
#else
return false;
#endif
}
void TFTDisplay::setDetected(uint8_t detected) void TFTDisplay::setDetected(uint8_t detected)
{ {
(void)detected; (void)detected;
@@ -183,20 +574,48 @@ bool TFTDisplay::connect()
{ {
concurrency::LockGuard g(spiLock); concurrency::LockGuard g(spiLock);
LOG_INFO("Doing TFT init\n"); LOG_INFO("Doing TFT init\n");
#ifdef RAK14014
tft = new TFT_eSPI;
#else
tft = new LGFX;
#endif
#ifdef TFT_BL #ifdef TFT_BL
digitalWrite(TFT_BL, TFT_BACKLIGHT_ON);
pinMode(TFT_BL, OUTPUT); pinMode(TFT_BL, OUTPUT);
digitalWrite(TFT_BL, TFT_BACKLIGHT_ON);
// pinMode(PIN_3V3_EN, OUTPUT);
// digitalWrite(PIN_3V3_EN, HIGH);
LOG_INFO("Power to TFT Backlight\n");
#endif #endif
tft.init(); #ifdef ST7735_BACKLIGHT_EN_V03
#ifdef M5STACK if (heltec_version == 3) {
tft.setRotation(1); // M5Stack has the TFT in landscape pinMode(ST7735_BACKLIGHT_EN_V03, OUTPUT);
#else digitalWrite(ST7735_BACKLIGHT_EN_V03, TFT_BACKLIGHT_ON);
tft.setRotation(3); // Orient horizontal and wide underneath the silkscreen name label } else {
pinMode(ST7735_BACKLIGHT_EN_V05, OUTPUT);
digitalWrite(ST7735_BACKLIGHT_EN_V05, TFT_BACKLIGHT_ON);
}
#endif #endif
tft.fillScreen(TFT_BLACK);
tft->init();
#if defined(M5STACK)
tft->setRotation(0);
#elif defined(RAK14014)
tft->setRotation(1);
tft->setSwapBytes(true);
// tft->fillScreen(TFT_BLACK);
#elif defined(T_DECK) || defined(PICOMPUTER_S3) || defined(CHATTER_2)
tft->setRotation(1); // T-Deck has the TFT in landscape
#elif defined(T_WATCH_S3)
tft->setRotation(2); // T-Watch S3 left-handed orientation
#else
tft->setRotation(3); // Orient horizontal and wide underneath the silkscreen name label
#endif
tft->fillScreen(TFT_BLACK);
return true; return true;
} }
#endif #endif
+11 -3
View File
@@ -3,7 +3,7 @@
#include <OLEDDisplay.h> #include <OLEDDisplay.h>
/** /**
* An adapter class that allows using the TFT_eSPI library as if it was an OLEDDisplay implementation. * An adapter class that allows using the LovyanGFX library as if it was an OLEDDisplay implementation.
* *
* Remaining TODO: * Remaining TODO:
* optimize display() to only draw changed pixels (see other OLED subclasses for examples) * optimize display() to only draw changed pixels (see other OLED subclasses for examples)
@@ -20,7 +20,15 @@ class TFTDisplay : public OLEDDisplay
TFTDisplay(uint8_t, int, int, OLEDDISPLAY_GEOMETRY, HW_I2C); TFTDisplay(uint8_t, int, int, OLEDDISPLAY_GEOMETRY, HW_I2C);
// Write the buffer to the display memory // Write the buffer to the display memory
virtual void display(void) override; virtual void display() override { display(false); };
virtual void display(bool fromBlank);
// Turn the display upside down
virtual void flipScreenVertically();
// Touch screen (static handlers)
static bool hasTouch(void);
static bool getTouch(int16_t *x, int16_t *y);
/** /**
* shim to make the abstraction happy * shim to make the abstraction happy
@@ -37,4 +45,4 @@ class TFTDisplay : public OLEDDisplay
// Connect to the display // Connect to the display
virtual bool connect() override; virtual bool connect() override;
}; };
+3 -2
View File
@@ -14,7 +14,8 @@ const uint8_t imgUser[] PROGMEM = {0x3C, 0x42, 0x99, 0xA5, 0xA5, 0x99, 0x42, 0x3
const uint8_t imgPositionEmpty[] PROGMEM = {0x20, 0x30, 0x28, 0x24, 0x42, 0xFF}; const uint8_t imgPositionEmpty[] PROGMEM = {0x20, 0x30, 0x28, 0x24, 0x42, 0xFF};
const uint8_t imgPositionSolid[] PROGMEM = {0x20, 0x30, 0x38, 0x3C, 0x7E, 0xFF}; const uint8_t imgPositionSolid[] PROGMEM = {0x20, 0x30, 0x38, 0x3C, 0x7E, 0xFF};
#if defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7735_CS) #if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7735_CS) || defined(ST7789_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 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}; const uint8_t imgQuestionL2[] PROGMEM = {0x0f, 0x08, 0x08, 0x08, 0x06, 0x0f, 0x0f, 0x06, 0x08, 0x08, 0x08, 0x0f};
const uint8_t imgInfoL1[] PROGMEM = {0xff, 0x01, 0x01, 0x01, 0x1e, 0x7f, 0x1e, 0x01, 0x01, 0x01, 0x01, 0xff}; const uint8_t imgInfoL1[] PROGMEM = {0xff, 0x01, 0x01, 0x01, 0x1e, 0x7f, 0x1e, 0x01, 0x01, 0x01, 0x01, 0xff};
@@ -29,4 +30,4 @@ const uint8_t imgQuestion[] PROGMEM = {0xbf, 0x41, 0xc0, 0x8b, 0xdb, 0x70, 0xa1,
const uint8_t imgSF[] PROGMEM = {0xd2, 0xb7, 0xad, 0xbb, 0x92, 0x01, 0xfd, 0xfd, 0x15, 0x85, 0xf5}; const uint8_t imgSF[] PROGMEM = {0xd2, 0xb7, 0xad, 0xbb, 0x92, 0x01, 0xfd, 0xfd, 0x15, 0x85, 0xf5};
#endif #endif
#include "img/icon.xbm" #include "img/icon.xbm"
+2 -2
View File
@@ -1,6 +1,6 @@
#define icon_width 50 #define icon_width 50
#define icon_height 28 #define icon_height 28
static char icon_bits[] = { static uint8_t icon_bits[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x03, 0x00, 0x03,
0x00, 0x00, 0x00, 0x80, 0x07, 0xC0, 0x07, 0x00, 0x00, 0x00, 0xC0, 0x1F, 0x00, 0x00, 0x00, 0x80, 0x07, 0xC0, 0x07, 0x00, 0x00, 0x00, 0xC0, 0x1F,
0xC0, 0x0F, 0x00, 0x00, 0x00, 0xE0, 0x0F, 0xE0, 0x0F, 0x00, 0x00, 0x00, 0xC0, 0x0F, 0x00, 0x00, 0x00, 0xE0, 0x0F, 0xE0, 0x0F, 0x00, 0x00, 0x00,
@@ -17,4 +17,4 @@ static char icon_bits[] = {
0xFE, 0x00, 0x00, 0xFC, 0x01, 0x7E, 0x00, 0x7F, 0x00, 0x00, 0xF8, 0x01, 0xFE, 0x00, 0x00, 0xFC, 0x01, 0x7E, 0x00, 0x7F, 0x00, 0x00, 0xF8, 0x01,
0x7E, 0x00, 0x3E, 0x00, 0x00, 0xF8, 0x01, 0x38, 0x00, 0x3C, 0x00, 0x00, 0x7E, 0x00, 0x3E, 0x00, 0x00, 0xF8, 0x01, 0x38, 0x00, 0x3C, 0x00, 0x00,
0x70, 0x00, 0x10, 0x00, 0x10, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x10, 0x00, 0x10, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, }; 0x00, 0x00, 0x00, 0x00, };
+181
View File
@@ -0,0 +1,181 @@
// Based on arturo182 arduino_bbq10kbd library https://github.com/arturo182/arduino_bbq10kbd
#include <Arduino.h>
#include "BBQ10Keyboard.h"
#define _REG_VER 1
#define _REG_CFG 2
#define _REG_INT 3
#define _REG_KEY 4
#define _REG_BKL 5
#define _REG_DEB 6
#define _REG_FRQ 7
#define _REG_RST 8
#define _REG_FIF 9
#define _WRITE_MASK (1 << 7)
#define CFG_OVERFLOW_ON (1 << 0)
#define CFG_OVERFLOW_INT (1 << 1)
#define CFG_CAPSLOCK_INT (1 << 2)
#define CFG_NUMLOCK_INT (1 << 3)
#define CFG_KEY_INT (1 << 4)
#define CFG_PANIC_INT (1 << 5)
#define CFG_REPORT_MODS (1 << 6)
#define CFG_USE_MODS (1 << 7)
#define INT_OVERFLOW (1 << 0)
#define INT_CAPSLOCK (1 << 1)
#define INT_NUMLOCK (1 << 2)
#define INT_KEY (1 << 3)
#define INT_PANIC (1 << 4)
#define KEY_CAPSLOCK (1 << 5)
#define KEY_NUMLOCK (1 << 6)
#define KEY_COUNT_MASK (0x1F)
BBQ10Keyboard::BBQ10Keyboard() : m_wire(nullptr), m_addr(0), readCallback(nullptr), writeCallback(nullptr) {}
void BBQ10Keyboard::begin(uint8_t addr, TwoWire *wire)
{
m_addr = addr;
m_wire = wire;
m_wire->begin();
reset();
}
void BBQ10Keyboard::begin(i2c_com_fptr_t r, i2c_com_fptr_t w, uint8_t addr)
{
m_addr = addr;
m_wire = nullptr;
writeCallback = w;
readCallback = r;
reset();
}
void BBQ10Keyboard::reset()
{
if (m_wire) {
m_wire->beginTransmission(m_addr);
m_wire->write(_REG_RST);
m_wire->endTransmission();
}
if (writeCallback) {
uint8_t data = 0;
writeCallback(m_addr, _REG_RST, &data, 0);
}
delay(100);
writeRegister(_REG_CFG, readRegister8(_REG_CFG) | CFG_REPORT_MODS);
delay(100);
}
void BBQ10Keyboard::attachInterrupt(uint8_t pin, void (*func)(void)) const
{
pinMode(pin, INPUT_PULLUP);
::attachInterrupt(digitalPinToInterrupt(pin), func, RISING);
}
void BBQ10Keyboard::detachInterrupt(uint8_t pin) const
{
::detachInterrupt(pin);
}
void BBQ10Keyboard::clearInterruptStatus()
{
writeRegister(_REG_INT, 0x00);
}
uint8_t BBQ10Keyboard::status() const
{
return readRegister8(_REG_KEY);
}
uint8_t BBQ10Keyboard::keyCount() const
{
return status() & KEY_COUNT_MASK;
}
BBQ10Keyboard::KeyEvent BBQ10Keyboard::keyEvent() const
{
KeyEvent event = {.key = '\0', .state = StateIdle};
if (keyCount() == 0)
return event;
const uint16_t buf = readRegister16(_REG_FIF);
event.key = buf >> 8;
event.state = KeyState(buf & 0xFF);
return event;
}
float BBQ10Keyboard::backlight() const
{
return readRegister8(_REG_BKL) / 255.0f;
}
void BBQ10Keyboard::setBacklight(float value)
{
writeRegister(_REG_BKL, value * 255);
}
uint8_t BBQ10Keyboard::readRegister8(uint8_t reg) const
{
if (m_wire) {
m_wire->beginTransmission(m_addr);
m_wire->write(reg);
m_wire->endTransmission();
m_wire->requestFrom(m_addr, (uint8_t)1);
if (m_wire->available() < 1)
return 0;
return m_wire->read();
}
if (readCallback) {
uint8_t data;
readCallback(m_addr, reg, &data, 1);
return data;
}
return 0;
}
uint16_t BBQ10Keyboard::readRegister16(uint8_t reg) const
{
uint8_t data[2] = {0};
// uint8_t low = 0, high = 0;
if (m_wire) {
m_wire->beginTransmission(m_addr);
m_wire->write(reg);
m_wire->endTransmission();
m_wire->requestFrom(m_addr, (uint8_t)2);
if (m_wire->available() < 2)
return 0;
data[0] = m_wire->read();
data[1] = m_wire->read();
}
if (readCallback) {
readCallback(m_addr, reg, data, 2);
}
return (data[1] << 8) | data[0];
}
void BBQ10Keyboard::writeRegister(uint8_t reg, uint8_t value)
{
uint8_t data[2];
data[0] = reg | _WRITE_MASK;
data[1] = value;
if (m_wire) {
m_wire->beginTransmission(m_addr);
m_wire->write(data, sizeof(uint8_t) * 2);
m_wire->endTransmission();
}
if (writeCallback) {
writeCallback(m_addr, data[0], &(data[1]), 1);
}
}
+51
View File
@@ -0,0 +1,51 @@
// Based on arturo182 arduino_bbq10kbd library https://github.com/arturo182/arduino_bbq10kbd
#include "configuration.h"
#include <Wire.h>
#define KEY_MOD_ALT (0x1A)
#define KEY_MOD_SHL (0x1B)
#define KEY_MOD_SHR (0x1C)
#define KEY_MOD_SYM (0x1D)
class BBQ10Keyboard
{
public:
typedef uint8_t (*i2c_com_fptr_t)(uint8_t dev_addr, uint8_t reg_addr, uint8_t *data, uint8_t len);
enum KeyState { StateIdle = 0, StatePress, StateLongPress, StateRelease };
struct KeyEvent {
char key;
KeyState state;
};
BBQ10Keyboard();
void begin(uint8_t addr = BBQ10_KB_ADDR, TwoWire *wire = &Wire);
void begin(i2c_com_fptr_t r, i2c_com_fptr_t w, uint8_t addr = BBQ10_KB_ADDR);
void reset(void);
void attachInterrupt(uint8_t pin, void (*func)(void)) const;
void detachInterrupt(uint8_t pin) const;
void clearInterruptStatus(void);
uint8_t status(void) const;
uint8_t keyCount(void) const;
KeyEvent keyEvent(void) const;
float backlight() const;
void setBacklight(float value);
uint8_t readRegister8(uint8_t reg) const;
uint16_t readRegister16(uint8_t reg) const;
void writeRegister(uint8_t reg, uint8_t value);
private:
TwoWire *m_wire;
uint8_t m_addr;
i2c_com_fptr_t readCallback;
i2c_com_fptr_t writeCallback;
};
+183
View File
@@ -0,0 +1,183 @@
#include "configuration.h"
#if ARCH_PORTDUINO
#include "LinuxInput.h"
#include "platform/portduino/PortduinoGlue.h"
#include <assert.h>
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
#include <linux/input.h>
#include <stdint.h>
#include <stdio.h>
#include <string>
#include <sys/epoll.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
// Inspired by https://github.com/librerpi/rpi-tools/blob/master/keyboard-proxy/main.c which is GPL-v2
LinuxInput::LinuxInput(const char *name) : concurrency::OSThread(name)
{
this->_originName = name;
}
void LinuxInput::deInit()
{
close(fd);
}
int32_t LinuxInput::runOnce()
{
if (firstTime) {
if (settingsStrings[keyboardDevice] == "")
return disable();
fd = open(settingsStrings[keyboardDevice].c_str(), O_RDWR);
if (fd < 0)
return disable();
ret = ioctl(fd, EVIOCGRAB, (void *)1);
if (ret != 0)
return disable();
epollfd = epoll_create1(0);
assert(epollfd >= 0);
ev.events = EPOLLIN;
ev.data.fd = fd;
if (epoll_ctl(epollfd, EPOLL_CTL_ADD, fd, &ev)) {
perror("unable to epoll add");
return disable();
}
// This is the first time the OSThread library has called this function, so do port setup
firstTime = 0;
}
int nfds = epoll_wait(epollfd, events, MAX_EVENTS, 1);
if (nfds < 0) {
printf("%d ", nfds);
perror("epoll_wait failed");
return disable();
} else if (nfds == 0) {
return 50;
}
int keys = 0;
memset(report, 0, 8);
for (int i = 0; i < nfds; i++) {
struct input_event ev[64];
int rd = read(events[i].data.fd, ev, sizeof(ev));
assert(rd > ((signed int)sizeof(struct input_event)));
for (int j = 0; j < rd / ((signed int)sizeof(struct input_event)); j++) {
InputEvent e;
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_NONE;
e.source = this->_originName;
e.kbchar = 0;
unsigned int type, code;
type = ev[j].type;
code = ev[j].code;
int value = ev[j].value;
// printf("Event: time %ld.%06ld, ", ev[j].time.tv_sec, ev[j].time.tv_usec);
if (type == EV_KEY) {
uint8_t mod = 0;
switch (code) {
case KEY_LEFTCTRL:
mod = 0x01;
break;
case KEY_RIGHTCTRL:
mod = 0x10;
break;
case KEY_LEFTSHIFT:
mod = 0x02;
break;
case KEY_RIGHTSHIFT:
mod = 0x20;
break;
case KEY_LEFTALT:
mod = 0x04;
break;
case KEY_RIGHTALT:
mod = 0x40;
break;
case KEY_LEFTMETA:
mod = 0x08;
break;
}
if (value == 1) {
switch (code) {
case KEY_LEFTCTRL:
mod = 0x01;
break;
case KEY_RIGHTCTRL:
mod = 0x10;
break;
case KEY_LEFTSHIFT:
mod = 0x02;
break;
case KEY_RIGHTSHIFT:
mod = 0x20;
break;
case KEY_LEFTALT:
mod = 0x04;
break;
case KEY_RIGHTALT:
mod = 0x40;
break;
case KEY_LEFTMETA:
mod = 0x08;
break;
case KEY_ESC: // ESC
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_CANCEL;
break;
case KEY_BACK: // Back
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_BACK;
// e.kbchar = key;
break;
case KEY_UP: // Up
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_UP;
break;
case KEY_DOWN: // Down
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_DOWN;
break;
case KEY_LEFT: // Left
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_LEFT;
break;
e.kbchar = 0xb4;
case KEY_RIGHT: // Right
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_RIGHT;
break;
e.kbchar = 0xb7;
case KEY_ENTER: // Enter
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_SELECT;
break;
default: // all other keys
if (keymap[code]) {
e.inputEvent = ANYKEY;
e.kbchar = keymap[code];
}
break;
}
}
if (ev[j].value) {
modifiers |= mod;
} else {
modifiers &= ~mod;
}
report[0] = modifiers;
}
if (e.inputEvent != meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_NONE) {
if (e.inputEvent == ANYKEY && (modifiers && 0x22))
e.kbchar = uppers[e.kbchar]; // doesn't get punctuation. Meh.
this->notifyObservers(&e);
}
}
}
return 50; // Keyscan every 50msec to avoid key bounce
}
#endif
+65
View File
@@ -0,0 +1,65 @@
#pragma once
#if ARCH_PORTDUINO
#include "InputBroker.h"
#include "concurrency/OSThread.h"
#include <assert.h>
#include <errno.h>
#include <fcntl.h>
#include <linux/input.h>
#include <map>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <sys/epoll.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#define MAX_EVENTS 10
class LinuxInput : public Observable<const InputEvent *>, public concurrency::OSThread
{
public:
explicit LinuxInput(const char *name);
void deInit(); // Strictly for cleanly "rebooting" the binary on native
protected:
virtual int32_t runOnce() override;
private:
const char *_originName;
bool firstTime = 1;
int shift = 0;
char key = 0;
char prevkey = 0;
InputEvent eventqueue[50]; // The Linux API will return multiple keypresses at a time. Queue them to not miss any.
int queue_length = 0;
int queue_progress = 0;
struct epoll_event events[MAX_EVENTS];
int fd;
int ret;
uint8_t report[8];
int epollfd;
struct epoll_event ev;
uint8_t modifiers = 0;
std::map<int, char> keymap{
{KEY_A, 'a'}, {KEY_B, 'b'}, {KEY_C, 'c'}, {KEY_D, 'd'}, {KEY_E, 'e'},
{KEY_F, 'f'}, {KEY_G, 'g'}, {KEY_H, 'h'}, {KEY_I, 'i'}, {KEY_J, 'j'},
{KEY_K, 'k'}, {KEY_L, 'l'}, {KEY_M, 'm'}, {KEY_N, 'n'}, {KEY_O, 'o'},
{KEY_P, 'p'}, {KEY_Q, 'q'}, {KEY_R, 'r'}, {KEY_S, 's'}, {KEY_T, 't'},
{KEY_U, 'u'}, {KEY_V, 'v'}, {KEY_W, 'w'}, {KEY_X, 'x'}, {KEY_Y, 'y'},
{KEY_Z, 'z'}, {KEY_BACKSPACE, 0x08}, {KEY_SPACE, ' '}, {KEY_1, '1'}, {KEY_2, '2'},
{KEY_3, '3'}, {KEY_4, '4'}, {KEY_5, '5'}, {KEY_6, '6'}, {KEY_7, '7'},
{KEY_8, '8'}, {KEY_9, '9'}, {KEY_0, '0'}, {KEY_DOT, '.'}, {KEY_COMMA, ','},
{KEY_MINUS, '-'}, {KEY_EQUAL, '='}, {KEY_LEFTBRACE, '['}, {KEY_RIGHTBRACE, ']'}, {KEY_BACKSLASH, '\\'},
{KEY_SEMICOLON, ';'}, {KEY_APOSTROPHE, '\''}, {KEY_SLASH, '/'}, {KEY_TAB, 0x09}};
std::map<char, char> uppers{{'a', 'A'}, {'b', 'B'}, {'c', 'C'}, {'d', 'D'}, {'e', 'E'}, {'f', 'F'}, {'g', 'G'}, {'h', 'H'},
{'i', 'I'}, {'j', 'J'}, {'k', 'K'}, {'l', 'L'}, {'m', 'M'}, {'n', 'N'}, {'o', 'O'}, {'p', 'P'},
{'q', 'Q'}, {'r', 'R'}, {'s', 'S'}, {'t', 'T'}, {'u', 'U'}, {'v', 'V'}, {'w', 'W'}, {'x', 'X'},
{'y', 'Y'}, {'z', 'Z'}, {'1', '!'}, {'2', '@'}, {'3', '#'}, {'4', '$'}, {'5', '%'}, {'6', '^'},
{'7', '&'}, {'8', '*'}, {'9', '('}, {'0', ')'}, {'.', '>'}, {',', '<'}, {'-', '_'}, {'=', '+'},
{'[', '{'}, {']', '}'}, {'\\', '|'}, {';', ':'}, {'\'', '"'}, {'/', '?'}};
};
#endif
+15
View File
@@ -0,0 +1,15 @@
#include "configuration.h"
#if ARCH_PORTDUINO
#include "InputBroker.h"
#include "LinuxInputImpl.h"
LinuxInputImpl *aLinuxInputImpl;
LinuxInputImpl::LinuxInputImpl() : LinuxInput("LinuxInput") {}
void LinuxInputImpl::init()
{
inputBroker->registerSource(this);
}
#endif
+21
View File
@@ -0,0 +1,21 @@
#ifdef ARCH_PORTDUINO
#pragma once
#include "LinuxInput.h"
#include "main.h"
/**
* @brief The idea behind this class to have static methods for the event handlers.
* Check attachInterrupt() at RotaryEncoderInteruptBase.cpp
* Technically you can have as many rotary encoders hardver attached
* to your device as you wish, but you always need to have separate event
* handlers, thus you need to have a RotaryEncoderInterrupt implementation.
*/
class LinuxInputImpl : public LinuxInput
{
public:
LinuxInputImpl();
void init();
};
extern LinuxInputImpl *aLinuxInputImpl;
#endif
+4 -3
View File
@@ -5,12 +5,12 @@ RotaryEncoderInterruptImpl1 *rotaryEncoderInterruptImpl1;
RotaryEncoderInterruptImpl1::RotaryEncoderInterruptImpl1() : RotaryEncoderInterruptBase("rotEnc1") {} RotaryEncoderInterruptImpl1::RotaryEncoderInterruptImpl1() : RotaryEncoderInterruptBase("rotEnc1") {}
void RotaryEncoderInterruptImpl1::init() bool RotaryEncoderInterruptImpl1::init()
{ {
if (!moduleConfig.canned_message.rotary1_enabled) { if (!moduleConfig.canned_message.rotary1_enabled) {
// Input device is disabled. // Input device is disabled.
disable(); disable();
return; return false;
} }
uint8_t pinA = moduleConfig.canned_message.inputbroker_pin_a; uint8_t pinA = moduleConfig.canned_message.inputbroker_pin_a;
@@ -25,6 +25,7 @@ void RotaryEncoderInterruptImpl1::init()
RotaryEncoderInterruptImpl1::handleIntA, RotaryEncoderInterruptImpl1::handleIntB, RotaryEncoderInterruptImpl1::handleIntA, RotaryEncoderInterruptImpl1::handleIntB,
RotaryEncoderInterruptImpl1::handleIntPressed); RotaryEncoderInterruptImpl1::handleIntPressed);
inputBroker->registerSource(this); inputBroker->registerSource(this);
return true;
} }
void RotaryEncoderInterruptImpl1::handleIntA() void RotaryEncoderInterruptImpl1::handleIntA()
@@ -38,4 +39,4 @@ void RotaryEncoderInterruptImpl1::handleIntB()
void RotaryEncoderInterruptImpl1::handleIntPressed() void RotaryEncoderInterruptImpl1::handleIntPressed()
{ {
rotaryEncoderInterruptImpl1->intPressHandler(); rotaryEncoderInterruptImpl1->intPressHandler();
} }
+1 -1
View File
@@ -12,7 +12,7 @@ class RotaryEncoderInterruptImpl1 : public RotaryEncoderInterruptBase
{ {
public: public:
RotaryEncoderInterruptImpl1(); RotaryEncoderInterruptImpl1();
void init(); bool init();
static void handleIntA(); static void handleIntA();
static void handleIntB(); static void handleIntB();
static void handleIntPressed(); static void handleIntPressed();
+137
View File
@@ -0,0 +1,137 @@
#include "TouchScreenBase.h"
#include "main.h"
#ifndef TIME_LONG_PRESS
#define TIME_LONG_PRESS 400
#endif
// move a minimum distance over the screen to detect a "swipe"
#ifndef TOUCH_THRESHOLD_X
#define TOUCH_THRESHOLD_X 30
#endif
#ifndef TOUCH_THRESHOLD_Y
#define TOUCH_THRESHOLD_Y 20
#endif
TouchScreenBase::TouchScreenBase(const char *name, uint16_t width, uint16_t height)
: concurrency::OSThread(name), _display_width(width), _display_height(height), _first_x(0), _last_x(0), _first_y(0),
_last_y(0), _start(0), _tapped(false), _originName(name)
{
}
void TouchScreenBase::init(bool hasTouch)
{
if (hasTouch) {
LOG_INFO("TouchScreen initialized %d %d\n", TOUCH_THRESHOLD_X, TOUCH_THRESHOLD_Y);
this->setInterval(100);
} else {
disable();
this->setInterval(UINT_MAX);
}
}
int32_t TouchScreenBase::runOnce()
{
TouchEvent e;
e.touchEvent = static_cast<char>(TOUCH_ACTION_NONE);
// process touch events
int16_t x, y;
bool touched = getTouch(x, y);
if (touched) {
this->setInterval(20);
_last_x = x;
_last_y = y;
}
if (touched != _touchedOld) {
if (touched) {
hapticFeedback();
_state = TOUCH_EVENT_OCCURRED;
_start = millis();
_first_x = x;
_first_y = y;
} else {
_state = TOUCH_EVENT_CLEARED;
time_t duration = millis() - _start;
x = _last_x;
y = _last_y;
this->setInterval(50);
// compute distance
int16_t dx = x - _first_x;
int16_t dy = y - _first_y;
uint16_t adx = abs(dx);
uint16_t ady = abs(dy);
// swipe horizontal
if (adx > ady && adx > TOUCH_THRESHOLD_X) {
if (0 > dx) { // swipe right to left
e.touchEvent = static_cast<char>(TOUCH_ACTION_LEFT);
LOG_DEBUG("action SWIPE: right to left\n");
} else { // swipe left to right
e.touchEvent = static_cast<char>(TOUCH_ACTION_RIGHT);
LOG_DEBUG("action SWIPE: left to right\n");
}
}
// swipe vertical
else if (ady > adx && ady > TOUCH_THRESHOLD_Y) {
if (0 > dy) { // swipe bottom to top
e.touchEvent = static_cast<char>(TOUCH_ACTION_UP);
LOG_DEBUG("action SWIPE: bottom to top\n");
} else { // swipe top to bottom
e.touchEvent = static_cast<char>(TOUCH_ACTION_DOWN);
LOG_DEBUG("action SWIPE: top to bottom\n");
}
}
// tap
else {
if (duration > 0 && duration < TIME_LONG_PRESS) {
if (_tapped) {
_tapped = false;
e.touchEvent = static_cast<char>(TOUCH_ACTION_DOUBLE_TAP);
LOG_DEBUG("action DOUBLE TAP(%d/%d)\n", x, y);
} else {
_tapped = true;
}
} else {
_tapped = false;
}
}
}
}
_touchedOld = touched;
// fire TAP event when no 2nd tap occured within time
if (_tapped && (time_t(millis()) - _start) > TIME_LONG_PRESS - 50) {
_tapped = false;
e.touchEvent = static_cast<char>(TOUCH_ACTION_TAP);
LOG_DEBUG("action TAP(%d/%d)\n", _last_x, _last_y);
}
// fire LONG_PRESS event without the need for release
if (touched && (time_t(millis()) - _start) > TIME_LONG_PRESS) {
// tricky: prevent reoccurring events and another touch event when releasing
_start = millis() + 30000;
e.touchEvent = static_cast<char>(TOUCH_ACTION_LONG_PRESS);
LOG_DEBUG("action LONG PRESS(%d/%d)\n", _last_x, _last_y);
}
if (e.touchEvent != TOUCH_ACTION_NONE) {
e.source = this->_originName;
e.x = _last_x;
e.y = _last_y;
onEvent(e);
}
return interval;
}
void TouchScreenBase::hapticFeedback()
{
#ifdef T_WATCH_S3
drv.setWaveform(0, 75);
drv.setWaveform(1, 0); // end waveform
drv.go();
#endif
}
+55
View File
@@ -0,0 +1,55 @@
#pragma once
#include "InputBroker.h"
#include "concurrency/OSThread.h"
#include "mesh/NodeDB.h"
typedef struct _TouchEvent {
const char *source;
char touchEvent;
uint16_t x;
uint16_t y;
} TouchEvent;
class TouchScreenBase : public Observable<const InputEvent *>, public concurrency::OSThread
{
public:
explicit TouchScreenBase(const char *name, uint16_t width, uint16_t height);
void init(bool hasTouch);
protected:
enum TouchScreenBaseStateType { TOUCH_EVENT_OCCURRED, TOUCH_EVENT_CLEARED };
enum TouchScreenBaseEventType {
TOUCH_ACTION_NONE,
TOUCH_ACTION_UP,
TOUCH_ACTION_DOWN,
TOUCH_ACTION_LEFT,
TOUCH_ACTION_RIGHT,
TOUCH_ACTION_TAP,
TOUCH_ACTION_DOUBLE_TAP,
TOUCH_ACTION_LONG_PRESS
};
virtual int32_t runOnce() override;
virtual bool getTouch(int16_t &x, int16_t &y) = 0;
virtual void onEvent(const TouchEvent &event) = 0;
volatile TouchScreenBaseStateType _state = TOUCH_EVENT_CLEARED;
volatile TouchScreenBaseEventType _action = TOUCH_ACTION_NONE;
void hapticFeedback();
protected:
uint16_t _display_width;
uint16_t _display_height;
private:
bool _touchedOld = false; // previous touch state
int16_t _first_x, _last_x; // horizontal swipe direction
int16_t _first_y, _last_y; // vertical swipe direction
time_t _start; // for LONG_PRESS
bool _tapped; // for DOUBLE_TAP
const char *_originName;
};
+89
View File
@@ -0,0 +1,89 @@
#include "TouchScreenImpl1.h"
#include "InputBroker.h"
#include "PowerFSM.h"
#include "configuration.h"
#include "modules/ExternalNotificationModule.h"
#ifdef ARCH_PORTDUINO
#include "platform/portduino/PortduinoGlue.h"
#endif
TouchScreenImpl1 *touchScreenImpl1;
TouchScreenImpl1::TouchScreenImpl1(uint16_t width, uint16_t height, bool (*getTouch)(int16_t *, int16_t *))
: TouchScreenBase("touchscreen1", width, height), _getTouch(getTouch)
{
}
void TouchScreenImpl1::init()
{
#if ARCH_PORTDUINO
if (settingsMap[touchscreenModule]) {
TouchScreenBase::init(true);
inputBroker->registerSource(this);
} else {
TouchScreenBase::init(false);
}
#elif !HAS_TOUCHSCREEN
TouchScreenBase::init(false);
return;
#else
TouchScreenBase::init(true);
inputBroker->registerSource(this);
#endif
}
bool TouchScreenImpl1::getTouch(int16_t &x, int16_t &y)
{
return _getTouch(&x, &y);
}
/**
* @brief forward touchscreen event
*
* @param event
*
* The touchscreen events are translated to input events and reversed
*/
void TouchScreenImpl1::onEvent(const TouchEvent &event)
{
InputEvent e;
e.source = event.source;
switch (event.touchEvent) {
case TOUCH_ACTION_LEFT: {
e.inputEvent = static_cast<char>(meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_RIGHT);
break;
}
case TOUCH_ACTION_RIGHT: {
e.inputEvent = static_cast<char>(meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_LEFT);
break;
}
case TOUCH_ACTION_UP: {
e.inputEvent = static_cast<char>(meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_UP);
break;
}
case TOUCH_ACTION_DOWN: {
e.inputEvent = static_cast<char>(meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_DOWN);
break;
}
case TOUCH_ACTION_DOUBLE_TAP: {
e.inputEvent = static_cast<char>(meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_SELECT);
break;
}
case TOUCH_ACTION_LONG_PRESS: {
e.inputEvent = static_cast<char>(meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_CANCEL);
break;
}
case TOUCH_ACTION_TAP: {
if (moduleConfig.external_notification.enabled && (externalNotificationModule->nagCycleCutoff != UINT32_MAX)) {
externalNotificationModule->stopNow();
} else {
powerFSM.trigger(EVENT_INPUT);
}
break;
}
default:
return;
}
this->notifyObservers(&e);
}
+17
View File
@@ -0,0 +1,17 @@
#pragma once
#include "TouchScreenBase.h"
class TouchScreenImpl1 : public TouchScreenBase
{
public:
TouchScreenImpl1(uint16_t width, uint16_t height, bool (*getTouch)(int16_t *, int16_t *));
void init(void);
protected:
virtual bool getTouch(int16_t &x, int16_t &y);
virtual void onEvent(const TouchEvent &event);
bool (*_getTouch)(int16_t *, int16_t *);
};
extern TouchScreenImpl1 *touchScreenImpl1;
+95
View File
@@ -0,0 +1,95 @@
#include "TrackballInterruptBase.h"
#include "configuration.h"
TrackballInterruptBase::TrackballInterruptBase(const char *name) : concurrency::OSThread(name), _originName(name) {}
void TrackballInterruptBase::init(uint8_t pinDown, uint8_t pinUp, uint8_t pinLeft, uint8_t pinRight, uint8_t pinPress,
char eventDown, char eventUp, char eventLeft, char eventRight, char eventPressed,
void (*onIntDown)(), void (*onIntUp)(), void (*onIntLeft)(), void (*onIntRight)(),
void (*onIntPress)())
{
this->_pinDown = pinDown;
this->_pinUp = pinUp;
this->_pinLeft = pinLeft;
this->_pinRight = pinRight;
this->_eventDown = eventDown;
this->_eventUp = eventUp;
this->_eventLeft = eventLeft;
this->_eventRight = eventRight;
this->_eventPressed = eventPressed;
pinMode(pinPress, INPUT_PULLUP);
pinMode(this->_pinDown, INPUT_PULLUP);
pinMode(this->_pinUp, INPUT_PULLUP);
pinMode(this->_pinLeft, INPUT_PULLUP);
pinMode(this->_pinRight, INPUT_PULLUP);
attachInterrupt(pinPress, onIntPress, RISING);
attachInterrupt(this->_pinDown, onIntDown, RISING);
attachInterrupt(this->_pinUp, onIntUp, RISING);
attachInterrupt(this->_pinLeft, onIntLeft, RISING);
attachInterrupt(this->_pinRight, onIntRight, RISING);
LOG_DEBUG("Trackball GPIO initialized (%d, %d, %d, %d, %d)\n", this->_pinUp, this->_pinDown, this->_pinLeft, this->_pinRight,
pinPress);
this->setInterval(100);
}
int32_t TrackballInterruptBase::runOnce()
{
InputEvent e;
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_NONE;
if (this->action == TB_ACTION_PRESSED) {
// LOG_DEBUG("Trackball event Press\n");
e.inputEvent = this->_eventPressed;
} else if (this->action == TB_ACTION_UP) {
// LOG_DEBUG("Trackball event UP\n");
e.inputEvent = this->_eventUp;
} else if (this->action == TB_ACTION_DOWN) {
// LOG_DEBUG("Trackball event DOWN\n");
e.inputEvent = this->_eventDown;
} else if (this->action == TB_ACTION_LEFT) {
// LOG_DEBUG("Trackball event LEFT\n");
e.inputEvent = this->_eventLeft;
} else if (this->action == TB_ACTION_RIGHT) {
// LOG_DEBUG("Trackball event RIGHT\n");
e.inputEvent = this->_eventRight;
}
if (e.inputEvent != meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_NONE) {
e.source = this->_originName;
e.kbchar = 0x00;
this->notifyObservers(&e);
}
this->action = TB_ACTION_NONE;
return 100;
}
void TrackballInterruptBase::intPressHandler()
{
this->action = TB_ACTION_PRESSED;
}
void TrackballInterruptBase::intDownHandler()
{
this->action = TB_ACTION_DOWN;
}
void TrackballInterruptBase::intUpHandler()
{
this->action = TB_ACTION_UP;
}
void TrackballInterruptBase::intLeftHandler()
{
this->action = TB_ACTION_LEFT;
}
void TrackballInterruptBase::intRightHandler()
{
this->action = TB_ACTION_RIGHT;
}
+44
View File
@@ -0,0 +1,44 @@
#pragma once
#include "InputBroker.h"
#include "mesh/NodeDB.h"
class TrackballInterruptBase : public Observable<const InputEvent *>, public concurrency::OSThread
{
public:
explicit TrackballInterruptBase(const char *name);
void init(uint8_t pinDown, uint8_t pinUp, uint8_t pinLeft, uint8_t pinRight, uint8_t pinPress, char eventDown, char eventUp,
char eventLeft, char eventRight, char eventPressed, void (*onIntDown)(), void (*onIntUp)(), void (*onIntLeft)(),
void (*onIntRight)(), void (*onIntPress)());
void intPressHandler();
void intDownHandler();
void intUpHandler();
void intLeftHandler();
void intRightHandler();
virtual int32_t runOnce() override;
protected:
enum TrackballInterruptBaseActionType {
TB_ACTION_NONE,
TB_ACTION_PRESSED,
TB_ACTION_UP,
TB_ACTION_DOWN,
TB_ACTION_LEFT,
TB_ACTION_RIGHT
};
volatile TrackballInterruptBaseActionType action = TB_ACTION_NONE;
private:
uint8_t _pinDown = 0;
uint8_t _pinUp = 0;
uint8_t _pinLeft = 0;
uint8_t _pinRight = 0;
char _eventDown = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_NONE;
char _eventUp = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_NONE;
char _eventLeft = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_NONE;
char _eventRight = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_NONE;
char _eventPressed = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_NONE;
const char *_originName;
};
+54
View File
@@ -0,0 +1,54 @@
#include "TrackballInterruptImpl1.h"
#include "InputBroker.h"
#include "configuration.h"
TrackballInterruptImpl1 *trackballInterruptImpl1;
TrackballInterruptImpl1::TrackballInterruptImpl1() : TrackballInterruptBase("trackball1") {}
void TrackballInterruptImpl1::init()
{
#if !HAS_TRACKBALL
// Input device is disabled.
return;
#else
uint8_t pinUp = TB_UP;
uint8_t pinDown = TB_DOWN;
uint8_t pinLeft = TB_LEFT;
uint8_t pinRight = TB_RIGHT;
uint8_t pinPress = TB_PRESS;
char eventDown = static_cast<char>(meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_DOWN);
char eventUp = static_cast<char>(meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_UP);
char eventLeft = static_cast<char>(meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_LEFT);
char eventRight = static_cast<char>(meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_RIGHT);
char eventPressed = static_cast<char>(meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_SELECT);
TrackballInterruptBase::init(pinDown, pinUp, pinLeft, pinRight, pinPress, eventDown, eventUp, eventLeft, eventRight,
eventPressed, TrackballInterruptImpl1::handleIntDown, TrackballInterruptImpl1::handleIntUp,
TrackballInterruptImpl1::handleIntLeft, TrackballInterruptImpl1::handleIntRight,
TrackballInterruptImpl1::handleIntPressed);
inputBroker->registerSource(this);
#endif
}
void TrackballInterruptImpl1::handleIntDown()
{
trackballInterruptImpl1->intDownHandler();
}
void TrackballInterruptImpl1::handleIntUp()
{
trackballInterruptImpl1->intUpHandler();
}
void TrackballInterruptImpl1::handleIntLeft()
{
trackballInterruptImpl1->intLeftHandler();
}
void TrackballInterruptImpl1::handleIntRight()
{
trackballInterruptImpl1->intRightHandler();
}
void TrackballInterruptImpl1::handleIntPressed()
{
trackballInterruptImpl1->intPressHandler();
}
+16
View File
@@ -0,0 +1,16 @@
#pragma once
#include "TrackballInterruptBase.h"
class TrackballInterruptImpl1 : public TrackballInterruptBase
{
public:
TrackballInterruptImpl1();
void init();
static void handleIntDown();
static void handleIntUp();
static void handleIntLeft();
static void handleIntRight();
static void handleIntPressed();
};
extern TrackballInterruptImpl1 *trackballInterruptImpl1;
+1 -1
View File
@@ -23,7 +23,7 @@ void UpDownInterruptBase::init(uint8_t pinDown, uint8_t pinUp, uint8_t pinPress,
attachInterrupt(this->_pinDown, onIntDown, RISING); attachInterrupt(this->_pinDown, onIntDown, RISING);
attachInterrupt(this->_pinUp, onIntUp, RISING); attachInterrupt(this->_pinUp, onIntUp, RISING);
LOG_DEBUG("GPIO initialized (%d, %d, %d)\n", this->_pinDown, this->_pinUp, pinPress); LOG_DEBUG("Up/down/press GPIO initialized (%d, %d, %d)\n", this->_pinUp, this->_pinDown, pinPress);
} }
void UpDownInterruptBase::intPressHandler() void UpDownInterruptBase::intPressHandler()
+4 -3
View File
@@ -5,12 +5,12 @@ UpDownInterruptImpl1 *upDownInterruptImpl1;
UpDownInterruptImpl1::UpDownInterruptImpl1() : UpDownInterruptBase("upDown1") {} UpDownInterruptImpl1::UpDownInterruptImpl1() : UpDownInterruptBase("upDown1") {}
void UpDownInterruptImpl1::init() bool UpDownInterruptImpl1::init()
{ {
if (!moduleConfig.canned_message.updown1_enabled) { if (!moduleConfig.canned_message.updown1_enabled) {
// Input device is disabled. // Input device is disabled.
return; return false;
} }
uint8_t pinUp = moduleConfig.canned_message.inputbroker_pin_a; uint8_t pinUp = moduleConfig.canned_message.inputbroker_pin_a;
@@ -24,6 +24,7 @@ void UpDownInterruptImpl1::init()
UpDownInterruptBase::init(pinDown, pinUp, pinPress, eventDown, eventUp, eventPressed, UpDownInterruptImpl1::handleIntDown, UpDownInterruptBase::init(pinDown, pinUp, pinPress, eventDown, eventUp, eventPressed, UpDownInterruptImpl1::handleIntDown,
UpDownInterruptImpl1::handleIntUp, UpDownInterruptImpl1::handleIntPressed); UpDownInterruptImpl1::handleIntUp, UpDownInterruptImpl1::handleIntPressed);
inputBroker->registerSource(this); inputBroker->registerSource(this);
return true;
} }
void UpDownInterruptImpl1::handleIntDown() void UpDownInterruptImpl1::handleIntDown()
@@ -37,4 +38,4 @@ void UpDownInterruptImpl1::handleIntUp()
void UpDownInterruptImpl1::handleIntPressed() void UpDownInterruptImpl1::handleIntPressed()
{ {
upDownInterruptImpl1->intPressHandler(); upDownInterruptImpl1->intPressHandler();
} }
+2 -2
View File
@@ -5,10 +5,10 @@ class UpDownInterruptImpl1 : public UpDownInterruptBase
{ {
public: public:
UpDownInterruptImpl1(); UpDownInterruptImpl1();
void init(); bool init();
static void handleIntDown(); static void handleIntDown();
static void handleIntUp(); static void handleIntUp();
static void handleIntPressed(); static void handleIntPressed();
}; };
extern UpDownInterruptImpl1 *upDownInterruptImpl1; extern UpDownInterruptImpl1 *upDownInterruptImpl1;
+1 -1
View File
@@ -7,7 +7,7 @@ CardKbI2cImpl::CardKbI2cImpl() : KbI2cBase("cardKB") {}
void CardKbI2cImpl::init() void CardKbI2cImpl::init()
{ {
if (cardkb_found.address != CARDKB_ADDR) { if (cardkb_found.address == 0x00) {
disable(); disable();
return; return;
} }
+130 -22
View File
@@ -28,20 +28,9 @@ uint8_t read_from_14004(TwoWire *i2cBus, uint8_t reg, uint8_t *data, uint8_t len
return readflag; return readflag;
} }
// Unused for now - flagging it off
#if 0
void write_to_14004(const TwoWire * i2cBus, uint8_t reg, uint8_t data)
{
i2cBus->beginTransmission(CARDKB_ADDR);
i2cBus->write(reg);
i2cBus->write(data);
i2cBus->endTransmission(); // stop transmitting
}
#endif
int32_t KbI2cBase::runOnce() int32_t KbI2cBase::runOnce()
{ {
if (cardkb_found.address != CARDKB_ADDR) { if (cardkb_found.address == 0x00) {
// Input device is not detected. // Input device is not detected.
return INT32_MAX; return INT32_MAX;
} }
@@ -52,11 +41,19 @@ int32_t KbI2cBase::runOnce()
#ifdef I2C_SDA1 #ifdef I2C_SDA1
LOG_DEBUG("Using I2C Bus 1 (the second one)\n"); LOG_DEBUG("Using I2C Bus 1 (the second one)\n");
i2cBus = &Wire1; i2cBus = &Wire1;
if (cardkb_found.address == BBQ10_KB_ADDR) {
Q10keyboard.begin(BBQ10_KB_ADDR, &Wire1);
Q10keyboard.setBacklight(0);
}
break; break;
#endif #endif
case ScanI2C::WIRE: case ScanI2C::WIRE:
LOG_DEBUG("Using I2C Bus 0 (the first one)\n"); LOG_DEBUG("Using I2C Bus 0 (the first one)\n");
i2cBus = &Wire; i2cBus = &Wire;
if (cardkb_found.address == BBQ10_KB_ADDR) {
Q10keyboard.begin(BBQ10_KB_ADDR, &Wire);
Q10keyboard.setBacklight(0);
}
break; break;
case ScanI2C::NO_I2C: case ScanI2C::NO_I2C:
default: default:
@@ -64,7 +61,105 @@ int32_t KbI2cBase::runOnce()
} }
} }
if (kb_model == 0x02) { switch (kb_model) {
case 0x11: { // BB Q10
int keyCount = Q10keyboard.keyCount();
while (keyCount--) {
const BBQ10Keyboard::KeyEvent key = Q10keyboard.keyEvent();
if ((key.key != 0x00) && (key.state == BBQ10Keyboard::StateRelease)) {
InputEvent e;
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_NONE;
e.source = this->_originName;
switch (key.key) {
case 'p': // TAB
case 't': // TAB as well
if (is_sym) {
e.inputEvent = ANYKEY;
e.kbchar = 0x09; // TAB Scancode
is_sym = false; // reset sym state after second keypress
} else {
e.inputEvent = ANYKEY;
e.kbchar = key.key;
}
break;
case 'q': // ESC
if (is_sym) {
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_CANCEL;
e.kbchar = 0x1b;
is_sym = false; // reset sym state after second keypress
} else {
e.inputEvent = ANYKEY;
e.kbchar = key.key;
}
break;
case 0x08: // Back
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_BACK;
e.kbchar = key.key;
break;
case 'e': // sym e
if (is_sym) {
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_UP;
e.kbchar = 0xb5;
is_sym = false; // reset sym state after second keypress
} else {
e.inputEvent = ANYKEY;
e.kbchar = key.key;
}
break;
case 'x': // sym x
if (is_sym) {
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_DOWN;
e.kbchar = 0xb6;
is_sym = false; // reset sym state after second keypress
} else {
e.inputEvent = ANYKEY;
e.kbchar = key.key;
}
break;
case 's': // sym s
if (is_sym) {
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_LEFT;
e.kbchar = 0x00; // tweak for destSelect
is_sym = false; // reset sym state after second keypress
} else {
e.inputEvent = ANYKEY;
e.kbchar = key.key;
}
break;
case 'f': // sym f
if (is_sym) {
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_RIGHT;
e.kbchar = 0x00; // tweak for destSelect
is_sym = false; // reset sym state after second keypress
} else {
e.inputEvent = ANYKEY;
e.kbchar = key.key;
}
break;
case 0x13: // Code scanner says the SYM key is 0x13
is_sym = !is_sym;
break;
case 0x0a: // apparently Enter on Q10 is a line feed instead of carriage return
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_SELECT;
break;
case 0x00: // nopress
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_NONE;
break;
default: // all other keys
e.inputEvent = ANYKEY;
e.kbchar = key.key;
is_sym = false; // reset sym state after second keypress
break;
}
if (e.inputEvent != meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_NONE) {
this->notifyObservers(&e);
}
}
}
break;
}
case 0x02: {
// RAK14004 // RAK14004
uint8_t rDataBuf[8] = {0}; uint8_t rDataBuf[8] = {0};
uint8_t PrintDataBuf = 0; uint8_t PrintDataBuf = 0;
@@ -85,11 +180,14 @@ int32_t KbI2cBase::runOnce()
e.kbchar = PrintDataBuf; e.kbchar = PrintDataBuf;
this->notifyObservers(&e); this->notifyObservers(&e);
} }
} else { break;
// m5 cardkb }
i2cBus->requestFrom(CARDKB_ADDR, 1); case 0x00: // CARDKB
case 0x10: { // T-DECK
while (i2cBus->available()) { i2cBus->requestFrom((int)cardkb_found.address, 1);
if (i2cBus->available()) {
char c = i2cBus->read(); char c = i2cBus->read();
InputEvent e; InputEvent e;
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_NONE; e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_NONE;
@@ -104,17 +202,19 @@ int32_t KbI2cBase::runOnce()
break; break;
case 0xb5: // Up case 0xb5: // Up
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_UP; e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_UP;
e.kbchar = 0xb5;
break; break;
case 0xb6: // Down case 0xb6: // Down
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_DOWN; e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_DOWN;
e.kbchar = 0xb6;
break; break;
case 0xb4: // Left case 0xb4: // Left
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_LEFT; e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_LEFT;
e.kbchar = c; e.kbchar = 0xb4;
break; break;
case 0xb7: // Right case 0xb7: // Right
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_RIGHT; e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_RIGHT;
e.kbchar = c; e.kbchar = 0xb7;
break; break;
case 0x0d: // Enter case 0x0d: // Enter
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_SELECT; e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_SELECT;
@@ -122,7 +222,11 @@ int32_t KbI2cBase::runOnce()
case 0x00: // nopress case 0x00: // nopress
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_NONE; e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_NONE;
break; break;
default: // all other keys default: // all other keys
if (c > 127) { // bogus key value
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_NONE;
break;
}
e.inputEvent = ANYKEY; e.inputEvent = ANYKEY;
e.kbchar = c; e.kbchar = c;
break; break;
@@ -132,6 +236,10 @@ int32_t KbI2cBase::runOnce()
this->notifyObservers(&e); this->notifyObservers(&e);
} }
} }
break;
} }
return 500; default:
} LOG_WARN("Unknown kb_model 0x%02x\n", kb_model);
}
return 300;
}
+4
View File
@@ -1,5 +1,6 @@
#pragma once #pragma once
#include "BBQ10Keyboard.h"
#include "InputBroker.h" #include "InputBroker.h"
#include "Wire.h" #include "Wire.h"
#include "concurrency/OSThread.h" #include "concurrency/OSThread.h"
@@ -16,4 +17,7 @@ class KbI2cBase : public Observable<const InputEvent *>, public concurrency::OST
const char *_originName; const char *_originName;
TwoWire *i2cBus = 0; TwoWire *i2cBus = 0;
BBQ10Keyboard Q10keyboard;
bool is_sym = false;
}; };

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