mirror of
https://github.com/meshtastic/firmware.git
synced 2025-12-23 11:10:52 +00:00
Compare commits
44 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e32b41938a | ||
|
|
ef395a1596 | ||
|
|
af35f3006c | ||
|
|
13ac686c96 | ||
|
|
05a0266fc4 | ||
|
|
3acbf31198 | ||
|
|
2e82bf3ca1 | ||
|
|
63e1a3f47e | ||
|
|
07a8972aea | ||
|
|
d1cb45aa5d | ||
|
|
1b3610d0fa | ||
|
|
2fcdc2c09f | ||
|
|
da74803ffb | ||
|
|
890511615f | ||
|
|
17de6f9532 | ||
|
|
2a15195c32 | ||
|
|
1b050a6c3d | ||
|
|
1da62e5ba1 | ||
|
|
feb6f2e59e | ||
|
|
7dabad1b70 | ||
|
|
a73f466473 | ||
|
|
1fd92cf8eb | ||
|
|
dd671ceca6 | ||
|
|
8a76931b37 | ||
|
|
b071eecce1 | ||
|
|
81734f75c8 | ||
|
|
11d57e721a | ||
|
|
9b0e329bb9 | ||
|
|
450fb7bc35 | ||
|
|
c1f8c8cca4 | ||
|
|
ea250d9cd3 | ||
|
|
be468a2183 | ||
|
|
a47d6c4d68 | ||
|
|
5386a5b224 | ||
|
|
a350b3795b | ||
|
|
cf2aa37635 | ||
|
|
d1387be015 | ||
|
|
f8857ad45b | ||
|
|
d831beab3d | ||
|
|
5c4ae6c042 | ||
|
|
a0c97825e8 | ||
|
|
cc3bac7ea0 | ||
|
|
ce21859ada | ||
|
|
54cd082bfe |
4
.vscode/launch.json
vendored
4
.vscode/launch.json
vendored
@@ -12,7 +12,7 @@
|
|||||||
"type": "platformio-debug",
|
"type": "platformio-debug",
|
||||||
"request": "launch",
|
"request": "launch",
|
||||||
"name": "PIO Debug",
|
"name": "PIO Debug",
|
||||||
"executable": "/home/kevinh/development/meshtastic/meshtastic-esp32/.pio/build/esp32/firmware.elf",
|
"executable": "/home/kevinh/development/meshtastic/meshtastic-esp32/.pio/build/tbeam/firmware.elf",
|
||||||
"toolchainBinDir": "/home/kevinh/.platformio/packages/toolchain-xtensa32/bin",
|
"toolchainBinDir": "/home/kevinh/.platformio/packages/toolchain-xtensa32/bin",
|
||||||
"preLaunchTask": {
|
"preLaunchTask": {
|
||||||
"type": "PlatformIO",
|
"type": "PlatformIO",
|
||||||
@@ -24,7 +24,7 @@
|
|||||||
"type": "platformio-debug",
|
"type": "platformio-debug",
|
||||||
"request": "launch",
|
"request": "launch",
|
||||||
"name": "PIO Debug (skip Pre-Debug)",
|
"name": "PIO Debug (skip Pre-Debug)",
|
||||||
"executable": "/home/kevinh/development/meshtastic/meshtastic-esp32/.pio/build/esp32/firmware.elf",
|
"executable": "/home/kevinh/development/meshtastic/meshtastic-esp32/.pio/build/tbeam/firmware.elf",
|
||||||
"toolchainBinDir": "/home/kevinh/.platformio/packages/toolchain-xtensa32/bin",
|
"toolchainBinDir": "/home/kevinh/.platformio/packages/toolchain-xtensa32/bin",
|
||||||
"internalConsoleOptions": "openOnSessionStart"
|
"internalConsoleOptions": "openOnSessionStart"
|
||||||
}
|
}
|
||||||
|
|||||||
51
README.md
51
README.md
@@ -1,39 +1,43 @@
|
|||||||
# Meshtastic-esp32
|
# Meshtastic-esp32
|
||||||
|
|
||||||
This is the device side code for the [meshtastic.org](https://www.meshtastic.org) project.
|
This is the device side code for the [meshtastic.org](https://www.meshtastic.org) project.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
Meshtastic is a project that lets you use
|
Meshtastic is a project that lets you use
|
||||||
inexpensive GPS mesh radios as an extensible, super long battery life mesh GPS communicator. These radios are great for hiking, skiing, paragliding -
|
inexpensive GPS mesh radios as an extensible, super long battery life mesh GPS communicator. These radios are great for hiking, skiing, paragliding -
|
||||||
essentially any hobby where you don't have reliable internet access. Each member of your private mesh can always see the location and distance of all other
|
essentially any hobby where you don't have reliable internet access. Each member of your private mesh can always see the location and distance of all other
|
||||||
members and any text messages sent to your group chat.
|
members and any text messages sent to your group chat.
|
||||||
|
|
||||||
The radios automatically create a mesh to forward packets as needed, so everyone in the group can receive messages from even the furthest member. The radios
|
The radios automatically create a mesh to forward packets as needed, so everyone in the group can receive messages from even the furthest member. The radios
|
||||||
will optionally work with your phone, but no phone is required.
|
will optionally work with your phone, but no phone is required.
|
||||||
|
|
||||||
Typical time between recharging the radios should be about eight days.
|
Typical time between recharging the radios should be about eight days.
|
||||||
|
|
||||||
This project is currently early-alpha, but if you have questions please [join our discussion forum](https://meshtastic.discourse.group/).
|
This project is currently early-alpha, but if you have questions please [join our discussion forum](https://meshtastic.discourse.group/).
|
||||||
|
|
||||||
This software is 100% open source and developed by a group of hobbyist experimenters. No warranty is provided, if you'd like to improve it - we'd love your help. Please post in the chat.
|
This software is 100% open source and developed by a group of hobbyist experimenters. No warranty is provided, if you'd like to improve it - we'd love your help. Please post in the chat.
|
||||||
|
|
||||||
## Supported hardware
|
## Supported hardware
|
||||||
We currently support three models of radios. The [TTGO T-Beam](https://www.aliexpress.com/item/4000119152086.html), [TTGO LORA32](https://www.banggood.com/LILYGO-TTGO-LORA32-868Mhz-SX1276-ESP32-Oled-Display-bluetooth-WIFI-Lora-Development-Module-Board-p-1248652.html?cur_warehouse=UK) and the [Heltec LoRa 32](https://heltec.org/project/wifi-lora-32/). Most users should buy the T-Beam and a 18650 battery (total cost less than $35). Make
|
|
||||||
sure to buy the frequency range which is legal for your country. For the USA, you should buy the 915MHz version. Getting a version that include a screen
|
We currently support three models of radios. The [TTGO T-Beam](https://www.aliexpress.com/item/4000119152086.html), [TTGO LORA32](https://www.banggood.com/LILYGO-TTGO-LORA32-868Mhz-SX1276-ESP32-Oled-Display-bluetooth-WIFI-Lora-Development-Module-Board-p-1248652.html?cur_warehouse=UK) and the [Heltec LoRa 32](https://heltec.org/project/wifi-lora-32/). Most users should buy the T-Beam and a 18650 battery (total cost less than \$35). Make
|
||||||
|
sure to buy the frequency range which is legal for your country. For the USA, you should buy the 915MHz version. Getting a version that include a screen
|
||||||
is optional, but highly recommended.
|
is optional, but highly recommended.
|
||||||
|
|
||||||
See (meshtastic.org) for 3D printable cases.
|
See (meshtastic.org) for 3D printable cases.
|
||||||
|
|
||||||
## Installing the firmware
|
## Installing the firmware
|
||||||
Prebuilt binaries for the supported radios is available in our [releases](https://github.com/meshtastic/Meshtastic-esp32/releases). Your initial installation has to happen over USB from your Mac, Windows or Linux PC. Once our software is installed, all future software updates happen over bluetooth from your phone.
|
|
||||||
|
|
||||||
The instructions currently require a few commmand lines, but it should be pretty straightforward. Please post comments on our group chat if you have problems or successes. Steps to install:
|
Prebuilt binaries for the supported radios is available in our [releases](https://github.com/meshtastic/Meshtastic-esp32/releases). Your initial installation has to happen over USB from your Mac, Windows or Linux PC. Once our software is installed, all future software updates happen over bluetooth from your phone.
|
||||||
|
|
||||||
|
The instructions currently require a few commmand lines, but it should be pretty straightforward. Please post comments on our group chat if you have problems or successes. Steps to install:
|
||||||
|
|
||||||
1. Purchase a radio (see above) with the correct frequencies for your country (915MHz for US or JP, 470MHz for CN, 433MHz and 870MHz for EU).
|
1. Purchase a radio (see above) with the correct frequencies for your country (915MHz for US or JP, 470MHz for CN, 433MHz and 870MHz for EU).
|
||||||
2. Install "pip". Pip is the python package manager we use to get the esptool installer app. Instructions [here](https://www.makeuseof.com/tag/install-pip-for-python/).
|
2. Install "pip". Pip is the python package manager we use to get the esptool installer app. Instructions [here](https://www.makeuseof.com/tag/install-pip-for-python/). If you are using OS-X, see these [special instructions](docs/software/install-OSX.md).
|
||||||
3. Run "pip install --upgrade esptool" to get esptool installed on your machine
|
3. Run "pip install --upgrade esptool" to get esptool installed on your machine
|
||||||
4. Connect your radio to your USB port
|
4. Connect your radio to your USB port
|
||||||
5. Confirm that your device is talking to your PC by running "esptool.py chip_id". The Heltec build also works on the TTGO LORA32 radio. You should see something like:
|
5. Confirm that your device is talking to your PC by running "esptool.py chip_id". The Heltec build also works on the TTGO LORA32 radio. You should see something like:
|
||||||
|
|
||||||
```
|
```
|
||||||
mydir$ esptool.py chip_id
|
mydir$ esptool.py chip_id
|
||||||
esptool.py v2.6
|
esptool.py v2.6
|
||||||
@@ -51,12 +55,14 @@ Warning: ESP32 has no Chip ID. Reading MAC instead.
|
|||||||
MAC: 24:6f:28:b5:36:71
|
MAC: 24:6f:28:b5:36:71
|
||||||
Hard resetting via RTS pin...
|
Hard resetting via RTS pin...
|
||||||
```
|
```
|
||||||
6. cd into the directory where the release zip file was expanded.
|
|
||||||
7. Install the correct firmware for your board with "device-install.sh firmware-_board_-_country_.bin". For instance "./device-install.sh firmware-HELTEC-US-0.0.3.bin".
|
|
||||||
|
|
||||||
Note: If you have previously installed meshtastic, you don't need to run this full script instead just run "esptool.py --baud 921600 write_flash 0x10000 firmware-_board_-_country_.bin". This will be faster, also all of your current preferences will be preserved.
|
6. cd into the directory where the release zip file was expanded.
|
||||||
|
7. Install the correct firmware for your board with "device-install.sh firmware-_board_-_country_.bin". For instance "./device-install.sh firmware-HELTEC-US-0.0.3.bin".
|
||||||
|
|
||||||
|
Note: If you have previously installed meshtastic, you don't need to run this full script instead just run "esptool.py --baud 921600 write*flash 0x10000 firmware-\_board*-_country_.bin". This will be faster, also all of your current preferences will be preserved.
|
||||||
|
|
||||||
You should see something like this:
|
You should see something like this:
|
||||||
|
|
||||||
```
|
```
|
||||||
kevinh@kevin-server:~/development/meshtastic/meshtastic-esp32/release/latest$ ./device-install.sh firmware-TBEAM-US-0.1.8.bin
|
kevinh@kevin-server:~/development/meshtastic/meshtastic-esp32/release/latest$ ./device-install.sh firmware-TBEAM-US-0.1.8.bin
|
||||||
Trying to flash firmware-TBEAM-US-0.1.8.bin, but first erasing and writing system information
|
Trying to flash firmware-TBEAM-US-0.1.8.bin, but first erasing and writing system information
|
||||||
@@ -120,29 +126,34 @@ Hash of data verified.
|
|||||||
Leaving...
|
Leaving...
|
||||||
Hard resetting via RTS pin...
|
Hard resetting via RTS pin...
|
||||||
```
|
```
|
||||||
|
|
||||||
8. The board will boot and show the Meshtastic logo.
|
8. The board will boot and show the Meshtastic logo.
|
||||||
9. Please post a comment on our chat so we know if these instructions worked for you ;-). If you find bugs/have-questions post there also - we will be rapidly iterating over the next few weeks.
|
9. Please post a comment on our chat so we know if these instructions worked for you ;-). If you find bugs/have-questions post there also - we will be rapidly iterating over the next few weeks.
|
||||||
|
|
||||||
## Meshtastic Android app
|
## Meshtastic Android app
|
||||||
|
|
||||||
The source code for the (optional) Meshtastic Android app is [here](https://github.com/meshtastic/Meshtastic-Android).
|
The source code for the (optional) Meshtastic Android app is [here](https://github.com/meshtastic/Meshtastic-Android).
|
||||||
|
|
||||||
Alpha test builds are current available by opting into our alpha test group. See (www.meshtastic.org) for instructions.
|
Alpha test builds are current available by opting into our alpha test group. See (www.meshtastic.org) for instructions.
|
||||||
|
|
||||||
After our rate of change slows a bit, we will make beta builds available here (without needing to join the alphatest group):
|
After our rate of change slows a bit, we will make beta builds available here (without needing to join the alphatest group):
|
||||||
[](https://play.google.com/store/apps/details?id=com.geeksville.mesh&referrer=utm_source%3Dgithub%26utm_medium%3Desp32-readme%26utm_campaign%3Dmeshtastic-esp32%2520readme%26anid%3Dadmob&pcampaignid=pcampaignidMKT-Other-global-all-co-prtnr-py-PartBadge-Mar2515-1)
|
[](https://play.google.com/store/apps/details?id=com.geeksville.mesh&referrer=utm_source%3Dgithub%26utm_medium%3Desp32-readme%26utm_campaign%3Dmeshtastic-esp32%2520readme%26anid%3Dadmob&pcampaignid=pcampaignidMKT-Other-global-all-co-prtnr-py-PartBadge-Mar2515-1)
|
||||||
|
|
||||||
# Development
|
# Development
|
||||||
|
|
||||||
We'd love to have you join us on this merry little project. Please see our [development documents](./docs/software/sw-design.md) and [join us in our discussion forum](https://meshtastic.discourse.group/).
|
We'd love to have you join us on this merry little project. Please see our [development documents](./docs/software/sw-design.md) and [join us in our discussion forum](https://meshtastic.discourse.group/).
|
||||||
|
|
||||||
# Credits
|
# Credits
|
||||||
|
|
||||||
This project is run by volunteers. Past contributors include:
|
This project is run by volunteers. Past contributors include:
|
||||||
|
|
||||||
* @astro-arphid: Added support for 433MHz radios in europe.
|
- @astro-arphid: Added support for 433MHz radios in europe.
|
||||||
* @claesg: Various documentation fixes and 3D print enclosures
|
- @claesg: Various documentation fixes and 3D print enclosures
|
||||||
* @girtsf: So far our CI system, but soon lots of device improvements
|
- @girtsf: Lots of improvements
|
||||||
|
- @spattinson: Fixed interrupt handling for the AXP192 part
|
||||||
|
|
||||||
# IMPORTANT DISCLAIMERS AND FAQ
|
# IMPORTANT DISCLAIMERS AND FAQ
|
||||||
|
|
||||||
For a listing of currently missing features and a FAQ click [here](docs/faq.md).
|
For a listing of currently missing features and a FAQ click [here](docs/faq.md).
|
||||||
|
|
||||||
|
Copyright 2019 Geeksville Industries, LLC. GPL V3 Licensed.
|
||||||
|
|||||||
@@ -7,9 +7,6 @@ source bin/version.sh
|
|||||||
COUNTRIES="US EU433 EU865 CN JP"
|
COUNTRIES="US EU433 EU865 CN JP"
|
||||||
#COUNTRIES=US
|
#COUNTRIES=US
|
||||||
|
|
||||||
SRCMAP=.pio/build/esp32/output.map
|
|
||||||
SRCBIN=.pio/build/esp32/firmware.bin
|
|
||||||
SRCELF=.pio/build/esp32/firmware.elf
|
|
||||||
OUTDIR=release/latest
|
OUTDIR=release/latest
|
||||||
|
|
||||||
# We keep all old builds (and their map files in the archive dir)
|
# We keep all old builds (and their map files in the archive dir)
|
||||||
@@ -17,29 +14,37 @@ ARCHIVEDIR=release/archive
|
|||||||
|
|
||||||
rm -f $OUTDIR/firmware*
|
rm -f $OUTDIR/firmware*
|
||||||
|
|
||||||
|
mkdir -p $OUTDIR/bins $OUTDIR/elfs
|
||||||
|
rm -f $OUTDIR/bins/*
|
||||||
|
|
||||||
|
# build the named environment and copy the bins to the release directory
|
||||||
|
function do_build {
|
||||||
|
ENV_NAME=$1
|
||||||
|
echo "Building for $ENV_NAME with $PLATFORMIO_BUILD_FLAGS"
|
||||||
|
SRCBIN=.pio/build/$ENV_NAME/firmware.bin
|
||||||
|
SRCELF=.pio/build/$ENV_NAME/firmware.elf
|
||||||
|
rm -f $SRCBIN
|
||||||
|
pio run --environment $ENV_NAME # -v
|
||||||
|
cp $SRCBIN $OUTDIR/bins/firmware-$ENV_NAME-$COUNTRY-$VERSION.bin
|
||||||
|
cp $SRCELF $OUTDIR/elfs/firmware-$ENV_NAME-$COUNTRY-$VERSION.elf
|
||||||
|
}
|
||||||
|
|
||||||
for COUNTRY in $COUNTRIES; do
|
for COUNTRY in $COUNTRIES; do
|
||||||
|
|
||||||
HWVERSTR="1.0-$COUNTRY"
|
HWVERSTR="1.0-$COUNTRY"
|
||||||
COMMONOPTS="-DAPP_VERSION=$VERSION -DHW_VERSION_$COUNTRY -DHW_VERSION=$HWVERSTR -Wall -Wextra -Wno-missing-field-initializers -Isrc -Os -Wl,-Map,.pio/build/esp32/output.map -DAXP_DEBUG_PORT=Serial"
|
COMMONOPTS="-DAPP_VERSION=$VERSION -DHW_VERSION_$COUNTRY -DHW_VERSION=$HWVERSTR -Wall -Wextra -Wno-missing-field-initializers -Isrc -Os -DAXP_DEBUG_PORT=Serial"
|
||||||
|
|
||||||
export PLATFORMIO_BUILD_FLAGS="-DT_BEAM_V10 $COMMONOPTS"
|
export PLATFORMIO_BUILD_FLAGS="$COMMONOPTS"
|
||||||
echo "Building with $PLATFORMIO_BUILD_FLAGS"
|
|
||||||
rm -f $SRCBIN $SRCMAP
|
|
||||||
pio run # -v
|
|
||||||
cp $SRCBIN $OUTDIR/firmware-TBEAM-$COUNTRY-$VERSION.bin
|
|
||||||
cp $SRCELF $OUTDIR/firmware-TBEAM-$COUNTRY-$VERSION.elf
|
|
||||||
#cp $SRCMAP $ARCHIVEDIR/firmware-TBEAM-$COUNTRY-$VERSION.map
|
|
||||||
|
|
||||||
export PLATFORMIO_BUILD_FLAGS="-DHELTEC_LORA32 $COMMONOPTS"
|
do_build "tbeam0.7"
|
||||||
rm -f $SRCBIN $SRCMAP
|
do_build "ttgo-lora32-v2"
|
||||||
pio run # -v
|
do_build "ttgo-lora32-v1"
|
||||||
cp $SRCBIN $OUTDIR/firmware-HELTEC-$COUNTRY-$VERSION.bin
|
do_build "tbeam"
|
||||||
cp $SRCELF $OUTDIR/firmware-HELTEC-$COUNTRY-$VERSION.elf
|
do_build "heltec"
|
||||||
#cp $SRCMAP $ARCHIVEDIR/firmware-HELTEC-$COUNTRY-$VERSION.map
|
|
||||||
done
|
done
|
||||||
|
|
||||||
# keep the bins in archive also
|
# keep the bins in archive also
|
||||||
cp $OUTDIR/firmware* $ARCHIVEDIR
|
cp $OUTDIR/bins/firmware* $OUTDIR/elfs/firmware* $ARCHIVEDIR
|
||||||
|
|
||||||
cat >$OUTDIR/curfirmwareversion.xml <<XML
|
cat >$OUTDIR/curfirmwareversion.xml <<XML
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
@@ -54,6 +59,6 @@ Generated by bin/buildall.sh -->
|
|||||||
XML
|
XML
|
||||||
|
|
||||||
rm -f $ARCHIVEDIR/firmware-$VERSION.zip
|
rm -f $ARCHIVEDIR/firmware-$VERSION.zip
|
||||||
zip --junk-paths $ARCHIVEDIR/firmware-$VERSION.zip $OUTDIR/firmware-*-$VERSION.* images/system-info.bin bin/device-install.sh
|
zip --junk-paths $ARCHIVEDIR/firmware-$VERSION.zip $OUTDIR/bins/firmware-*-$VERSION.* images/system-info.bin bin/device-install.sh
|
||||||
|
|
||||||
echo BUILT ALL
|
echo BUILT ALL
|
||||||
@@ -1,3 +1,3 @@
|
|||||||
|
|
||||||
|
|
||||||
export VERSION=0.1.10
|
export VERSION=0.2.3
|
||||||
@@ -17,6 +17,7 @@ Items to complete soon (next couple of alpha releases).
|
|||||||
|
|
||||||
Items to complete before the first beta release.
|
Items to complete before the first beta release.
|
||||||
|
|
||||||
|
- possibly switch to https://github.com/SlashDevin/NeoGPS for gps comms
|
||||||
- good source of battery/signal/gps icons https://materialdesignicons.com/
|
- good source of battery/signal/gps icons https://materialdesignicons.com/
|
||||||
- research and implement better mesh algorithm - investigate changing routing to https://github.com/sudomesh/LoRaLayer2 ?
|
- research and implement better mesh algorithm - investigate changing routing to https://github.com/sudomesh/LoRaLayer2 ?
|
||||||
- check fcc rules on duty cycle. we might not need to freq hop. https://www.sunfiretesting.com/LoRa-FCC-Certification-Guide/
|
- check fcc rules on duty cycle. we might not need to freq hop. https://www.sunfiretesting.com/LoRa-FCC-Certification-Guide/
|
||||||
|
|||||||
@@ -6,19 +6,15 @@ in these instructions I describe use of their command line tool.
|
|||||||
1. Purchase a suitable radio (see above)
|
1. Purchase a suitable radio (see above)
|
||||||
2. Install [PlatformIO](https://platformio.org/platformio-ide)
|
2. Install [PlatformIO](https://platformio.org/platformio-ide)
|
||||||
3. Download this git repo and cd into it
|
3. Download this git repo and cd into it
|
||||||
4. Edit configuration.h and comment out *one* of the following two lines (depending on which board you are using):
|
4. If you are outside the USA, edit [platformio.ini](/platformio.ini) to set the correct frequency range for your country. The line you need to change starts with "hw_version" and instructions are provided above that line. Options are provided for EU433, EU835, CN, JP and US. Pull-requests eagerly accepted for other countries.
|
||||||
```
|
|
||||||
// #define T_BEAM_V10
|
|
||||||
#define HELTEC_LORA32
|
|
||||||
```
|
|
||||||
5. Plug the radio into your USB port
|
5. Plug the radio into your USB port
|
||||||
6. Type "pio run -t upload" (This command will fetch dependencies, build the project and install it on the board via USB)
|
6. Type "pio run --environment XXX -t upload" (This command will fetch dependencies, build the project and install it on the board via USB). For XXX, use the board type you have (either tbeam, heltec, ttgo-lora32-v1, ttgo-lora32-v2).
|
||||||
7. Platform IO also installs a very nice VisualStudio Code based IDE, see their [tutorial](https://docs.platformio.org/en/latest/tutorials/espressif32/arduino_debugging_unit_testing.html) if you'd like to use it
|
7. Platform IO also installs a very nice VisualStudio Code based IDE, see their [tutorial](https://docs.platformio.org/en/latest/tutorials/espressif32/arduino_debugging_unit_testing.html) if you'd like to use it.
|
||||||
|
|
||||||
|
|
||||||
## Decoding stack traces
|
## Decoding stack traces
|
||||||
|
|
||||||
If you get a crash, you can decode the addresses from the `Backtrace:` line:
|
If you get a crash, you can decode the addresses from the `Backtrace:` line:
|
||||||
|
|
||||||
1. Save the `Backtrace: 0x....` line to a file, e.g., `backtrace.txt`.
|
1. Save the `Backtrace: 0x....` line to a file, e.g., `backtrace.txt`.
|
||||||
2. Run `bin/exception_decoder.py backtrace.txt` (this uses symbols from the
|
2. Run `bin/exception_decoder.py backtrace.txt` (this uses symbols from the
|
||||||
last `firmware.elf`, so you must be running the same binary that's still in
|
last `firmware.elf`, so you must be running the same binary that's still in
|
||||||
|
|||||||
27
docs/software/install-OSX.md
Normal file
27
docs/software/install-OSX.md
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
(Here's some quick tips on installing the device code from OS-X, thanks to @android606)
|
||||||
|
|
||||||
|
First time using LoRa for anything, just checking it out.
|
||||||
|
|
||||||
|
I bought a T-Beam on eBay, followed the instructions to install the firmware here:
|
||||||
|
[https://github.com/meshtastic/Meshtastic-esp32](https://github.com/meshtastic/Meshtastic-esp32)
|
||||||
|
|
||||||
|
I'm using a Mac for this, so that might account for differences in the steps to get it working. I just swapped out my SSD last month, I'm using a pretty fresh install of OS X 10.15.3/Catalina.
|
||||||
|
|
||||||
|
I got it working fairly smoothly, but there were two hang-ups I thought I'd mention:
|
||||||
|
|
||||||
|
1. I am about 0% familiar with Python, so there were some issues getting esptool.py working. Basically, this OS X comes with Python 2.7 and no pip. Pip installed okay, so I used it to install esptool. Esptool appeared to install correctly, but I couldn't get it to work to save my life. Simply typing "esptool.py" doesn't work, and I just don't know enough python to figure out why. For some reason, it installs but isn't in the \$PATH anywhere, and I don't know where it went. Python 2.7 kept giving me warning messages about being old and unsupported, so I figured that might be a hint that I should upgrade.
|
||||||
|
|
||||||
|
I ended up doing this:
|
||||||
|
|
||||||
|
- brew install pyenv (to install pyenv)
|
||||||
|
- pyenv install 3.7.7 (to install and select python 3.7.7)
|
||||||
|
- pyenv global 3.7.7 (to select the new version of python)
|
||||||
|
- brew install pip (to install pip3)
|
||||||
|
- pip3 install --upgrade esptool (note I specifically had to use "pip3", not "pip")
|
||||||
|
|
||||||
|
...then I was able to execute esptool.py
|
||||||
|
|
||||||
|
2. esptool.py didn't work though, because the virtual com port wasn't showing up as a device. I had to install a driver from Silicon Labs, which I got here:
|
||||||
|
[driver for the CP210X USB to UART bridge from Silicon Labs](https://www.silabs.com/products/development-tools/software/usb-to-uart-bridge-vcp-drivers)
|
||||||
|
|
||||||
|
After I installed that, esptool.py was completely happy and the firmware loaded right up.
|
||||||
@@ -10,7 +10,7 @@ TODO:
|
|||||||
* DONE read about mesh routing solutions (DSR and AODV)
|
* DONE read about mesh routing solutions (DSR and AODV)
|
||||||
* DONE read about general mesh flooding solutions (naive, MPR, geo assisted)
|
* DONE read about general mesh flooding solutions (naive, MPR, geo assisted)
|
||||||
* DONE reread the disaster radio protocol docs - seems based on Babel (which is AODVish)
|
* DONE reread the disaster radio protocol docs - seems based on Babel (which is AODVish)
|
||||||
* possibly dash7? https://www.slideshare.net/MaartenWeyn1/dash7-alliance-protocol-technical-presentation https://github.com/MOSAIC-LoPoW/dash7-ap-open-source-stack
|
* possibly dash7? https://www.slideshare.net/MaartenWeyn1/dash7-alliance-protocol-technical-presentation https://github.com/MOSAIC-LoPoW/dash7-ap-open-source-stack - does the opensource stack implement multihop routing? flooding? their discussion mailing list looks dead-dead
|
||||||
* update duty cycle spreadsheet for our typical usecase
|
* update duty cycle spreadsheet for our typical usecase
|
||||||
* generalize naive flooding on top of radiohead or disaster.radio? (and fix radiohead to use my new driver)
|
* generalize naive flooding on top of radiohead or disaster.radio? (and fix radiohead to use my new driver)
|
||||||
|
|
||||||
|
|||||||
@@ -9,11 +9,14 @@
|
|||||||
; https://docs.platformio.org/page/projectconf.html
|
; https://docs.platformio.org/page/projectconf.html
|
||||||
|
|
||||||
[platformio]
|
[platformio]
|
||||||
|
default_envs = tbeam
|
||||||
|
|
||||||
[env:esp32]
|
[common]
|
||||||
|
; default to a US frequency range, change it as needed for your region and hardware (CN, JP, EU433, EU865)
|
||||||
|
hw_version = US
|
||||||
|
|
||||||
|
[env]
|
||||||
platform = espressif32
|
platform = espressif32
|
||||||
board = ttgo-t-beam
|
|
||||||
; board = heltec_wifi_lora_32_V2
|
|
||||||
framework = arduino
|
framework = arduino
|
||||||
|
|
||||||
; customize the partition table
|
; customize the partition table
|
||||||
@@ -22,23 +25,24 @@ board_build.partitions = partition-table.csv
|
|||||||
|
|
||||||
; note: we add src to our include search path so that lmic_project_config can override
|
; note: we add src to our include search path so that lmic_project_config can override
|
||||||
; FIXME: fix lib/BluetoothOTA dependency back on src/ so we can remove -Isrc
|
; FIXME: fix lib/BluetoothOTA dependency back on src/ so we can remove -Isrc
|
||||||
build_flags = -Wall -Wextra -Wno-missing-field-initializers -Isrc -Os -Wl,-Map,.pio/build/esp32/output.map -DAXP_DEBUG_PORT=Serial
|
build_flags = -Wall -Wextra -Wno-missing-field-initializers -Isrc -Os -Wl,-Map,.pio/build/output.map -DAXP_DEBUG_PORT=Serial -DHW_VERSION_${common.hw_version}
|
||||||
|
|
||||||
; not needed included in ttgo-t-beam board file
|
; not needed included in ttgo-t-beam board file
|
||||||
; also to use PSRAM https://docs.platformio.org/en/latest/platforms/espressif32.html#external-ram-psram
|
; also to use PSRAM https://docs.platformio.org/en/latest/platforms/espressif32.html#external-ram-psram
|
||||||
; -DBOARD_HAS_PSRAM
|
; -DBOARD_HAS_PSRAM
|
||||||
; -mfix-esp32-psram-cache-issue
|
; -mfix-esp32-psram-cache-issue
|
||||||
|
|
||||||
|
|
||||||
; -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG -DCORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_DEBUG
|
; -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG -DCORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_DEBUG
|
||||||
|
|
||||||
|
; leave this commented out to avoid breaking Windows
|
||||||
|
;upload_port = /dev/ttyUSB0
|
||||||
|
;monitor_port = /dev/ttyUSB0
|
||||||
|
|
||||||
upload_speed = 921600
|
upload_speed = 921600
|
||||||
upload_port = /dev/ttyUSB0
|
|
||||||
|
|
||||||
; the default is esptool
|
; the default is esptool
|
||||||
; upload_protocol = esp-prog
|
; upload_protocol = esp-prog
|
||||||
|
|
||||||
monitor_port = /dev/ttyUSB0
|
|
||||||
monitor_speed = 115200
|
monitor_speed = 115200
|
||||||
|
|
||||||
# debug_tool = esp-prog
|
# debug_tool = esp-prog
|
||||||
@@ -55,10 +59,8 @@ debug_tool = jlink
|
|||||||
|
|
||||||
debug_init_break = tbreak setup
|
debug_init_break = tbreak setup
|
||||||
|
|
||||||
; Note: some libraries are specified by #ID where there are conflicting library
|
|
||||||
; names.
|
|
||||||
lib_deps =
|
lib_deps =
|
||||||
https://github.com/meshtastic/RadioHead.git
|
https://github.com/meshtastic/RadioHead.git#a87518beacfff53bc2eec5ae33c607713e9596e6
|
||||||
https://github.com/meshtastic/esp8266-oled-ssd1306.git ; ESP8266_SSD1306
|
https://github.com/meshtastic/esp8266-oled-ssd1306.git ; ESP8266_SSD1306
|
||||||
AXP202X_Library
|
AXP202X_Library
|
||||||
SPI
|
SPI
|
||||||
@@ -68,9 +70,39 @@ lib_deps =
|
|||||||
https://github.com/meshtastic/arduino-fsm.git
|
https://github.com/meshtastic/arduino-fsm.git
|
||||||
https://github.com/meshtastic/SparkFun_Ublox_Arduino_Library.git
|
https://github.com/meshtastic/SparkFun_Ublox_Arduino_Library.git
|
||||||
|
|
||||||
;[env:tbeam]
|
; The 1.0 release of the TBEAM board
|
||||||
;board = ttgo-t-beam
|
[env:tbeam]
|
||||||
|
board = ttgo-t-beam
|
||||||
|
lib_deps =
|
||||||
|
${env.lib_deps}
|
||||||
|
AXP202X_Library
|
||||||
|
build_flags =
|
||||||
|
${env.build_flags} -D TBEAM_V10
|
||||||
|
|
||||||
;[env:heltec]
|
; The original TBEAM board without the AXP power chip and a few other changes
|
||||||
|
[env:tbeam0.7]
|
||||||
|
board = ttgo-t-beam
|
||||||
|
build_flags =
|
||||||
|
${env.build_flags} -D TBEAM_V07
|
||||||
|
|
||||||
|
[env:heltec]
|
||||||
;build_type = debug ; to make it possible to step through our jtag debugger
|
;build_type = debug ; to make it possible to step through our jtag debugger
|
||||||
;board = heltec_wifi_lora_32_V2
|
board = heltec_wifi_lora_32_V2
|
||||||
|
|
||||||
|
[env:ttgo-lora32-v1]
|
||||||
|
board = ttgo-lora32-v1
|
||||||
|
build_flags =
|
||||||
|
${env.build_flags} -D TTGO_LORA_V1
|
||||||
|
|
||||||
|
; note: the platformio definition for lora32-v2 seems stale, it is missing a pins_arduino.h file, therefore I don't think it works
|
||||||
|
[env:ttgo-lora32-v2]
|
||||||
|
board = ttgo-lora32-v1
|
||||||
|
build_flags =
|
||||||
|
${env.build_flags} -D TTGO_LORA_V2
|
||||||
|
|
||||||
|
|
||||||
|
; This is a temporary build target to test turning off particular hardare bits in the build (to improve modularity)
|
||||||
|
[env:bare]
|
||||||
|
board = ttgo-lora32-v1
|
||||||
|
build_flags =
|
||||||
|
${env.build_flags} -D BARE_BOARD
|
||||||
2
proto
2
proto
Submodule proto updated: 1b2449b50d...d13d741a98
@@ -5,12 +5,14 @@
|
|||||||
#include <pb_decode.h>
|
#include <pb_decode.h>
|
||||||
#include <pb_encode.h>
|
#include <pb_encode.h>
|
||||||
|
|
||||||
|
#ifdef RF95_IRQ_GPIO
|
||||||
|
|
||||||
/// A temporary buffer used for sending/receving packets, sized to hold the biggest buffer we might need
|
/// A temporary buffer used for sending/receving packets, sized to hold the biggest buffer we might need
|
||||||
#define MAX_RHPACKETLEN 251
|
#define MAX_RHPACKETLEN 251
|
||||||
static uint8_t radiobuf[MAX_RHPACKETLEN];
|
static uint8_t radiobuf[MAX_RHPACKETLEN];
|
||||||
|
|
||||||
CustomRF95::CustomRF95(MemoryPool<MeshPacket> &_pool, PointerQueue<MeshPacket> &_rxDest)
|
CustomRF95::CustomRF95(MemoryPool<MeshPacket> &_pool, PointerQueue<MeshPacket> &_rxDest)
|
||||||
: RH_RF95(NSS_GPIO, DIO0_GPIO), pool(_pool), rxDest(_rxDest), txQueue(MAX_TX_QUEUE), sendingPacket(NULL)
|
: RH_RF95(NSS_GPIO, RF95_IRQ_GPIO), RadioInterface(_pool, _rxDest), txQueue(MAX_TX_QUEUE)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -173,3 +175,5 @@ void CustomRF95::startSend(MeshPacket *txp)
|
|||||||
int res = RH_RF95::send(radiobuf, numbytes);
|
int res = RH_RF95::send(radiobuf, numbytes);
|
||||||
assert(res);
|
assert(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -1,8 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "MemoryPool.h"
|
#include "RadioInterface.h"
|
||||||
#include "MeshTypes.h"
|
|
||||||
#include "PointerQueue.h"
|
|
||||||
#include "mesh.pb.h"
|
#include "mesh.pb.h"
|
||||||
#include <RHMesh.h>
|
#include <RHMesh.h>
|
||||||
#include <RH_RF95.h>
|
#include <RH_RF95.h>
|
||||||
@@ -12,15 +10,12 @@
|
|||||||
/**
|
/**
|
||||||
* A version of the RF95 driver which is smart enough to manage packets via queues (no polling or blocking in user threads!)
|
* A version of the RF95 driver which is smart enough to manage packets via queues (no polling or blocking in user threads!)
|
||||||
*/
|
*/
|
||||||
class CustomRF95 : public RH_RF95
|
class CustomRF95 : public RH_RF95, public RadioInterface
|
||||||
{
|
{
|
||||||
friend class MeshRadio; // for debugging we let that class touch pool
|
friend class MeshRadio; // for debugging we let that class touch pool
|
||||||
|
|
||||||
MemoryPool<MeshPacket> &pool;
|
|
||||||
PointerQueue<MeshPacket> &rxDest;
|
|
||||||
PointerQueue<MeshPacket> txQueue;
|
PointerQueue<MeshPacket> txQueue;
|
||||||
|
|
||||||
MeshPacket *sendingPacket; // The packet we are currently sending
|
|
||||||
public:
|
public:
|
||||||
/** pool is the pool we will alloc our rx packets from
|
/** pool is the pool we will alloc our rx packets from
|
||||||
* rxDest is where we will send any rx packets, it becomes receivers responsibility to return packet to the pool
|
* rxDest is where we will send any rx packets, it becomes receivers responsibility to return packet to the pool
|
||||||
|
|||||||
10
src/GPS.cpp
10
src/GPS.cpp
@@ -6,8 +6,7 @@
|
|||||||
|
|
||||||
HardwareSerial _serial_gps(GPS_SERIAL_NUM);
|
HardwareSerial _serial_gps(GPS_SERIAL_NUM);
|
||||||
|
|
||||||
RTC_DATA_ATTR bool timeSetFromGPS; // We only reset our time once per _boot_ after that point just run from the internal clock
|
bool timeSetFromGPS; // We try to set our time from GPS each time we wake from sleep
|
||||||
// (even across sleeps)
|
|
||||||
|
|
||||||
GPS gps;
|
GPS gps;
|
||||||
|
|
||||||
@@ -16,7 +15,6 @@ 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
|
||||||
|
|
||||||
static bool hasValidLocation; // default to false, until we complete our first read
|
|
||||||
static bool wantNewLocation = true;
|
static bool wantNewLocation = true;
|
||||||
|
|
||||||
GPS::GPS() : PeriodicTask() {}
|
GPS::GPS() : PeriodicTask() {}
|
||||||
@@ -177,8 +175,10 @@ The Unix epoch (or Unix time or POSIX time or Unix timestamp) is the number of s
|
|||||||
tv.tv_usec = 0; // time.centisecond() * (10 / 1000);
|
tv.tv_usec = 0; // time.centisecond() * (10 / 1000);
|
||||||
|
|
||||||
DEBUG_MSG("Got time from GPS month=%d, year=%d, unixtime=%ld\n", t.tm_mon, t.tm_year, tv.tv_sec);
|
DEBUG_MSG("Got time from GPS month=%d, year=%d, unixtime=%ld\n", t.tm_mon, t.tm_year, tv.tv_sec);
|
||||||
|
if (t.tm_year < 0 || t.tm_year >= 300)
|
||||||
perhapsSetRTC(&tv);
|
DEBUG_MSG("Ignoring invalid GPS time\n");
|
||||||
|
else
|
||||||
|
perhapsSetRTC(&tv);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((fixtype >= 3 && fixtype <= 4) && ublox.getP()) // rd fixes only
|
if ((fixtype >= 3 && fixtype <= 4) && ublox.getP()) // rd fixes only
|
||||||
|
|||||||
@@ -45,8 +45,13 @@ class GPS : public PeriodicTask, public Observable
|
|||||||
/// Restart our lock attempt - try to get and broadcast a GPS reading ASAP
|
/// Restart our lock attempt - try to get and broadcast a GPS reading ASAP
|
||||||
void startLock();
|
void startLock();
|
||||||
|
|
||||||
|
/// Returns ture if we have acquired GPS lock.
|
||||||
|
bool hasLock() const { return hasValidLocation; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void readFromRTC();
|
void readFromRTC();
|
||||||
|
|
||||||
|
bool hasValidLocation = false; // default to false, until we complete our first read
|
||||||
};
|
};
|
||||||
|
|
||||||
extern GPS gps;
|
extern GPS gps;
|
||||||
|
|||||||
@@ -106,12 +106,13 @@ class RadioCharacteristic : public ProtobufCharacteristic
|
|||||||
|
|
||||||
void onRead(BLECharacteristic *c)
|
void onRead(BLECharacteristic *c)
|
||||||
{
|
{
|
||||||
DEBUG_MSG("Reading radio config\n");
|
DEBUG_MSG("Reading radio config, sdsecs %u\n", radioConfig.preferences.sds_secs);
|
||||||
ProtobufCharacteristic::onRead(c);
|
ProtobufCharacteristic::onRead(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
void onWrite(BLECharacteristic *c)
|
void onWrite(BLECharacteristic *c)
|
||||||
{
|
{
|
||||||
|
DEBUG_MSG("Writing radio config\n");
|
||||||
ProtobufCharacteristic::onWrite(c);
|
ProtobufCharacteristic::onWrite(c);
|
||||||
service.reloadConfig();
|
service.reloadConfig();
|
||||||
}
|
}
|
||||||
@@ -263,7 +264,7 @@ See bluetooth-api.md for documentation.
|
|||||||
BLEService *createMeshBluetoothService(BLEServer *server)
|
BLEService *createMeshBluetoothService(BLEServer *server)
|
||||||
{
|
{
|
||||||
// Create the BLE Service, we need more than the default of 15 handles
|
// Create the BLE Service, we need more than the default of 15 handles
|
||||||
BLEService *service = server->createService(BLEUUID("6ba1b218-15a8-461f-9fa8-5dcae273eafd"), 25, 0);
|
BLEService *service = server->createService(BLEUUID("6ba1b218-15a8-461f-9fa8-5dcae273eafd"), 30, 0);
|
||||||
|
|
||||||
assert(!meshFromNumCharacteristic);
|
assert(!meshFromNumCharacteristic);
|
||||||
meshFromNumCharacteristic = new FromNumCharacteristic;
|
meshFromNumCharacteristic = new FromNumCharacteristic;
|
||||||
|
|||||||
@@ -10,10 +10,6 @@
|
|||||||
#include <pb_decode.h>
|
#include <pb_decode.h>
|
||||||
#include <pb_encode.h>
|
#include <pb_encode.h>
|
||||||
|
|
||||||
/// 16 bytes of random PSK for our _public_ default channel that all devices power up on
|
|
||||||
static const uint8_t defaultpsk[] = {0xd4, 0xf1, 0xbb, 0x3a, 0x20, 0x29, 0x07, 0x59,
|
|
||||||
0xf0, 0xbc, 0xff, 0xab, 0xcf, 0x4e, 0x69, 0xbf};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ## LoRaWAN for North America
|
* ## LoRaWAN for North America
|
||||||
|
|
||||||
@@ -28,18 +24,11 @@ separated by 2.16 MHz with respect to the adjacent channels. Channel zero starts
|
|||||||
/// Sometimes while debugging it is useful to set this false, to disable rf95 accesses
|
/// Sometimes while debugging it is useful to set this false, to disable rf95 accesses
|
||||||
bool useHardware = true;
|
bool useHardware = true;
|
||||||
|
|
||||||
MeshRadio::MeshRadio(MemoryPool<MeshPacket> &_pool, PointerQueue<MeshPacket> &_rxDest) : rf95(_pool, _rxDest), manager(rf95)
|
MeshRadio::MeshRadio(MemoryPool<MeshPacket> &_pool, PointerQueue<MeshPacket> &_rxDest)
|
||||||
|
: radioIf(_pool, _rxDest) // , manager(radioIf)
|
||||||
{
|
{
|
||||||
myNodeInfo.num_channels = NUM_CHANNELS;
|
myNodeInfo.num_channels = NUM_CHANNELS;
|
||||||
|
|
||||||
// radioConfig.modem_config = RadioConfig_ModemConfig_Bw125Cr45Sf128; // medium range and fast
|
|
||||||
// channelSettings.modem_config = ChannelSettings_ModemConfig_Bw500Cr45Sf128; // short range and fast, but wide bandwidth so
|
|
||||||
// incompatible radios can talk together
|
|
||||||
channelSettings.modem_config = ChannelSettings_ModemConfig_Bw125Cr48Sf4096; // slow and long range
|
|
||||||
|
|
||||||
channelSettings.tx_power = 23;
|
|
||||||
memcpy(&channelSettings.psk, &defaultpsk, sizeof(channelSettings.psk));
|
|
||||||
strcpy(channelSettings.name, "Default");
|
|
||||||
// Can't print strings this early - serial not setup yet
|
// Can't print strings this early - serial not setup yet
|
||||||
// DEBUG_MSG("Set meshradio defaults name=%s\n", channelSettings.name);
|
// DEBUG_MSG("Set meshradio defaults name=%s\n", channelSettings.name);
|
||||||
}
|
}
|
||||||
@@ -62,10 +51,10 @@ bool MeshRadio::init()
|
|||||||
delay(10);
|
delay(10);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
manager.setThisAddress(
|
radioIf.setThisAddress(
|
||||||
nodeDB.getNodeNum()); // Note: we must do this here, because the nodenum isn't inited at constructor time.
|
nodeDB.getNodeNum()); // Note: we must do this here, because the nodenum isn't inited at constructor time.
|
||||||
|
|
||||||
if (!manager.init()) {
|
if (!radioIf.init()) {
|
||||||
DEBUG_MSG("LoRa radio init failed\n");
|
DEBUG_MSG("LoRa radio init failed\n");
|
||||||
DEBUG_MSG("Uncomment '#define SERIAL_DEBUG' in RH_RF95.cpp for detailed debug info\n");
|
DEBUG_MSG("Uncomment '#define SERIAL_DEBUG' in RH_RF95.cpp for detailed debug info\n");
|
||||||
return false;
|
return false;
|
||||||
@@ -97,11 +86,11 @@ unsigned long hash(char *str)
|
|||||||
|
|
||||||
void MeshRadio::reloadConfig()
|
void MeshRadio::reloadConfig()
|
||||||
{
|
{
|
||||||
rf95.setModeIdle(); // Need to be idle before doing init
|
radioIf.setModeIdle(); // Need to be idle before doing init
|
||||||
|
|
||||||
// Set up default configuration
|
// Set up default configuration
|
||||||
// No Sync Words in LORA mode.
|
// No Sync Words in LORA mode.
|
||||||
rf95.setModemConfig(
|
radioIf.setModemConfig(
|
||||||
(RH_RF95::ModemConfigChoice)channelSettings.modem_config); // Radio default
|
(RH_RF95::ModemConfigChoice)channelSettings.modem_config); // Radio default
|
||||||
// setModemConfig(Bw125Cr48Sf4096); // slow and reliable?
|
// setModemConfig(Bw125Cr48Sf4096); // slow and reliable?
|
||||||
// rf95.setPreambleLength(8); // Default is 8
|
// rf95.setPreambleLength(8); // Default is 8
|
||||||
@@ -109,7 +98,7 @@ void MeshRadio::reloadConfig()
|
|||||||
// Defaults after init are 434.0MHz, modulation GFSK_Rb250Fd250, +13dbM
|
// Defaults after init are 434.0MHz, modulation GFSK_Rb250Fd250, +13dbM
|
||||||
int channel_num = hash(channelSettings.name) % NUM_CHANNELS;
|
int channel_num = hash(channelSettings.name) % NUM_CHANNELS;
|
||||||
float center_freq = CH0 + CH_SPACING * channel_num;
|
float center_freq = CH0 + CH_SPACING * channel_num;
|
||||||
if (!rf95.setFrequency(center_freq)) {
|
if (!radioIf.setFrequency(center_freq)) {
|
||||||
DEBUG_MSG("setFrequency failed\n");
|
DEBUG_MSG("setFrequency failed\n");
|
||||||
assert(0); // fixme panic
|
assert(0); // fixme panic
|
||||||
}
|
}
|
||||||
@@ -120,13 +109,13 @@ void MeshRadio::reloadConfig()
|
|||||||
// If you are using RFM95/96/97/98 modules which uses the PA_BOOST transmitter pin, then
|
// If you are using RFM95/96/97/98 modules which uses the PA_BOOST transmitter pin, then
|
||||||
// you can set transmitter powers from 5 to 23 dBm:
|
// you can set transmitter powers from 5 to 23 dBm:
|
||||||
// FIXME - can we do this? It seems to be in the Heltec board.
|
// FIXME - can we do this? It seems to be in the Heltec board.
|
||||||
rf95.setTxPower(channelSettings.tx_power, false);
|
radioIf.setTxPower(channelSettings.tx_power, false);
|
||||||
|
|
||||||
DEBUG_MSG("Set radio: name=%s. config=%u, ch=%d, txpower=%d\n", channelSettings.name, channelSettings.modem_config,
|
DEBUG_MSG("Set radio: name=%s, config=%u, ch=%d, txpower=%d\n", channelSettings.name, channelSettings.modem_config,
|
||||||
channel_num, channelSettings.tx_power);
|
channel_num, channelSettings.tx_power);
|
||||||
|
|
||||||
// Done with init tell radio to start receiving
|
// Done with init tell radio to start receiving
|
||||||
rf95.setModeRx();
|
radioIf.setModeRx();
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorCode MeshRadio::send(MeshPacket *p)
|
ErrorCode MeshRadio::send(MeshPacket *p)
|
||||||
@@ -134,9 +123,9 @@ ErrorCode MeshRadio::send(MeshPacket *p)
|
|||||||
lastTxStart = millis();
|
lastTxStart = millis();
|
||||||
|
|
||||||
if (useHardware)
|
if (useHardware)
|
||||||
return rf95.send(p);
|
return radioIf.send(p);
|
||||||
else {
|
else {
|
||||||
rf95.pool.release(p);
|
radioIf.pool.release(p);
|
||||||
return ERRNO_OK;
|
return ERRNO_OK;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -148,12 +137,12 @@ void MeshRadio::loop()
|
|||||||
// It should never take us more than 30 secs to send a packet, if it does, we have a bug, FIXME, move most of this
|
// It should never take us more than 30 secs to send a packet, if it does, we have a bug, FIXME, move most of this
|
||||||
// into CustomRF95
|
// into CustomRF95
|
||||||
uint32_t now = millis();
|
uint32_t now = millis();
|
||||||
if (lastTxStart != 0 && (now - lastTxStart) > TX_WATCHDOG_TIMEOUT && rf95.mode() == RHGenericDriver::RHModeTx) {
|
if (lastTxStart != 0 && (now - lastTxStart) > TX_WATCHDOG_TIMEOUT && radioIf.mode() == RHGenericDriver::RHModeTx) {
|
||||||
DEBUG_MSG("ERROR! Bug! Tx packet took too long to send, forcing radio into rx mode");
|
DEBUG_MSG("ERROR! Bug! Tx packet took too long to send, forcing radio into rx mode\n");
|
||||||
rf95.setModeRx();
|
radioIf.setModeRx();
|
||||||
if (rf95.sendingPacket) { // There was probably a packet we were trying to send, free it
|
if (radioIf.sendingPacket) { // There was probably a packet we were trying to send, free it
|
||||||
rf95.pool.release(rf95.sendingPacket);
|
radioIf.pool.release(radioIf.sendingPacket);
|
||||||
rf95.sendingPacket = NULL;
|
radioIf.sendingPacket = NULL;
|
||||||
}
|
}
|
||||||
recordCriticalError(ErrTxWatchdog);
|
recordCriticalError(ErrTxWatchdog);
|
||||||
lastTxStart = 0; // Stop checking for now, because we just warned the developer
|
lastTxStart = 0; // Stop checking for now, because we just warned the developer
|
||||||
|
|||||||
@@ -64,8 +64,14 @@
|
|||||||
class MeshRadio
|
class MeshRadio
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
// Kinda ugly way of selecting different radio implementations, but soon this MeshRadio class will be going away
|
||||||
|
// entirely. At that point we can make things pretty.
|
||||||
|
#ifdef RF95_IRQ_GPIO
|
||||||
CustomRF95
|
CustomRF95
|
||||||
rf95; // the raw radio interface - for now I'm leaving public - because this class is shrinking to be almost nothing
|
radioIf; // the raw radio interface - for now I'm leaving public - because this class is shrinking to be almost nothing
|
||||||
|
#else
|
||||||
|
SimRadio radioIf;
|
||||||
|
#endif
|
||||||
|
|
||||||
/** pool is the pool we will alloc our rx packets from
|
/** pool is the pool we will alloc our rx packets from
|
||||||
* rxDest is where we will send any rx packets, it becomes receivers responsibility to return packet to the pool
|
* rxDest is where we will send any rx packets, it becomes receivers responsibility to return packet to the pool
|
||||||
@@ -88,14 +94,8 @@ class MeshRadio
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
// RHReliableDatagram manager; // don't use mesh yet
|
// RHReliableDatagram manager; // don't use mesh yet
|
||||||
RHMesh manager;
|
// RHMesh manager;
|
||||||
|
|
||||||
/// Used for the tx timer watchdog, to check for bugs in our transmit code, msec of last time we did a send
|
/// Used for the tx timer watchdog, to check for bugs in our transmit code, msec of last time we did a send
|
||||||
uint32_t lastTxStart = 0;
|
uint32_t lastTxStart = 0;
|
||||||
|
|
||||||
/// low level send, might block for mutiple seconds
|
|
||||||
ErrorCode sendTo(NodeNum dest, const uint8_t *buf, size_t len);
|
|
||||||
|
|
||||||
/// enqueue a received packet in rxDest
|
|
||||||
void handleReceive(MeshPacket *p);
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -97,7 +97,7 @@ MeshPacket *MeshService::handleFromRadioUser(MeshPacket *mp)
|
|||||||
if (weWin) {
|
if (weWin) {
|
||||||
DEBUG_MSG("NOTE! Received a nodenum collision and we are vetoing\n");
|
DEBUG_MSG("NOTE! Received a nodenum collision and we are vetoing\n");
|
||||||
|
|
||||||
packetPool.release(mp); // discard it
|
releaseToPool(mp); // discard it
|
||||||
mp = NULL;
|
mp = NULL;
|
||||||
|
|
||||||
sendOurOwner(); // send our owner as a _broadcast_ because that other guy is mistakenly using our nodenum
|
sendOurOwner(); // send our owner as a _broadcast_ because that other guy is mistakenly using our nodenum
|
||||||
@@ -151,7 +151,7 @@ void MeshService::handleFromRadio(MeshPacket *mp)
|
|||||||
mp->rx_time = gps.getValidTime(); // store the arrival timestamp for the phone
|
mp->rx_time = gps.getValidTime(); // store the arrival timestamp for the phone
|
||||||
|
|
||||||
// If it is a position packet, perhaps set our clock (if we don't have a GPS of our own, otherwise wait for that to work)
|
// If it is a position packet, perhaps set our clock (if we don't have a GPS of our own, otherwise wait for that to work)
|
||||||
if (!myNodeInfo.has_gps)
|
if (!gps.isConnected)
|
||||||
handleIncomingPosition(mp);
|
handleIncomingPosition(mp);
|
||||||
else {
|
else {
|
||||||
DEBUG_MSG("Ignoring incoming time, because we have a GPS\n");
|
DEBUG_MSG("Ignoring incoming time, because we have a GPS\n");
|
||||||
@@ -178,8 +178,9 @@ void MeshService::handleFromRadio(MeshPacket *mp)
|
|||||||
|
|
||||||
if (mp->payload.want_response)
|
if (mp->payload.want_response)
|
||||||
sendNetworkPing(mp->from);
|
sendNetworkPing(mp->from);
|
||||||
} else
|
} else {
|
||||||
DEBUG_MSG("Dropping vetoed User message\n");
|
DEBUG_MSG("Not delivering vetoed User message\n");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MeshService::handleFromRadio()
|
void MeshService::handleFromRadio()
|
||||||
@@ -217,6 +218,7 @@ void MeshService::loop()
|
|||||||
void MeshService::reloadConfig()
|
void MeshService::reloadConfig()
|
||||||
{
|
{
|
||||||
// If we can successfully set this radio to these settings, save them to disk
|
// If we can successfully set this radio to these settings, save them to disk
|
||||||
|
nodeDB.resetRadioConfig(); // Don't let the phone send us fatally bad settings
|
||||||
radio.reloadConfig();
|
radio.reloadConfig();
|
||||||
nodeDB.saveToDisk();
|
nodeDB.saveToDisk();
|
||||||
}
|
}
|
||||||
@@ -263,7 +265,7 @@ void MeshService::sendToMesh(MeshPacket *p)
|
|||||||
// nodes shouldn't trust it anyways) Note: for now, we allow a device with a local GPS to include the time, so that gpsless
|
// nodes shouldn't trust it anyways) Note: for now, we allow a device with a local GPS to include the time, so that gpsless
|
||||||
// devices can get time.
|
// devices can get time.
|
||||||
if (p->has_payload && p->payload.which_variant == SubPacket_position_tag) {
|
if (p->has_payload && p->payload.which_variant == SubPacket_position_tag) {
|
||||||
if (!myNodeInfo.has_gps) {
|
if (!gps.isConnected) {
|
||||||
DEBUG_MSG("Stripping time %u from position send\n", p->payload.variant.position.time);
|
DEBUG_MSG("Stripping time %u from position send\n", p->payload.variant.position.time);
|
||||||
p->payload.variant.position.time = 0;
|
p->payload.variant.position.time = 0;
|
||||||
} else
|
} else
|
||||||
|
|||||||
@@ -83,7 +83,7 @@ class MeshService : private Observer
|
|||||||
/// handle all the packets that just arrived from the mesh radio
|
/// handle all the packets that just arrived from the mesh radio
|
||||||
void handleFromRadio();
|
void handleFromRadio();
|
||||||
|
|
||||||
/// Handle a packet that just arrived from the radio
|
/// Handle a packet that just arrived from the radio. We will either eventually enqueue the message to the phone or return it to the free pool
|
||||||
void handleFromRadio(MeshPacket *p);
|
void handleFromRadio(MeshPacket *p);
|
||||||
|
|
||||||
/// handle a user packet that just arrived on the radio, return NULL if we should not process this packet at all
|
/// handle a user packet that just arrived on the radio, return NULL if we should not process this packet at all
|
||||||
|
|||||||
@@ -44,9 +44,39 @@ static uint8_t ourMacAddr[6];
|
|||||||
|
|
||||||
NodeDB::NodeDB() : nodes(devicestate.node_db), numNodes(&devicestate.node_db_count) {}
|
NodeDB::NodeDB() : nodes(devicestate.node_db), numNodes(&devicestate.node_db_count) {}
|
||||||
|
|
||||||
|
void NodeDB::resetRadioConfig()
|
||||||
|
{
|
||||||
|
/// 16 bytes of random PSK for our _public_ default channel that all devices power up on
|
||||||
|
static const uint8_t defaultpsk[] = {0xd4, 0xf1, 0xbb, 0x3a, 0x20, 0x29, 0x07, 0x59,
|
||||||
|
0xf0, 0xbc, 0xff, 0xab, 0xcf, 0x4e, 0x69, 0xbf};
|
||||||
|
|
||||||
|
if (radioConfig.preferences.sds_secs == 0) {
|
||||||
|
DEBUG_MSG("RadioConfig reset!\n");
|
||||||
|
radioConfig.preferences.send_owner_interval = 4; // per sw-design.md
|
||||||
|
radioConfig.preferences.position_broadcast_secs = 15 * 60;
|
||||||
|
radioConfig.preferences.wait_bluetooth_secs = 120;
|
||||||
|
radioConfig.preferences.screen_on_secs = 30;
|
||||||
|
radioConfig.preferences.mesh_sds_timeout_secs = 2 * 60 * 60;
|
||||||
|
radioConfig.preferences.phone_sds_timeout_sec = 2 * 60 * 60;
|
||||||
|
radioConfig.preferences.sds_secs = 365 * 24 * 60 * 60; // one year
|
||||||
|
radioConfig.preferences.ls_secs = 60 * 60;
|
||||||
|
radioConfig.preferences.phone_timeout_secs = 15 * 60;
|
||||||
|
radioConfig.has_channel_settings = true;
|
||||||
|
radioConfig.has_preferences = true;
|
||||||
|
|
||||||
|
// radioConfig.modem_config = RadioConfig_ModemConfig_Bw125Cr45Sf128; // medium range and fast
|
||||||
|
// channelSettings.modem_config = ChannelSettings_ModemConfig_Bw500Cr45Sf128; // short range and fast, but wide bandwidth
|
||||||
|
// so incompatible radios can talk together
|
||||||
|
channelSettings.modem_config = ChannelSettings_ModemConfig_Bw125Cr48Sf4096; // slow and long range
|
||||||
|
|
||||||
|
channelSettings.tx_power = 23;
|
||||||
|
memcpy(&channelSettings.psk, &defaultpsk, sizeof(channelSettings.psk));
|
||||||
|
strcpy(channelSettings.name, "Default");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void NodeDB::init()
|
void NodeDB::init()
|
||||||
{
|
{
|
||||||
|
|
||||||
// init our devicestate with valid flags so protobuf writing/reading will work
|
// init our devicestate with valid flags so protobuf writing/reading will work
|
||||||
devicestate.has_my_node = true;
|
devicestate.has_my_node = true;
|
||||||
devicestate.has_radio = true;
|
devicestate.has_radio = true;
|
||||||
@@ -57,15 +87,7 @@ void NodeDB::init()
|
|||||||
devicestate.node_db_count = 0;
|
devicestate.node_db_count = 0;
|
||||||
devicestate.receive_queue_count = 0;
|
devicestate.receive_queue_count = 0;
|
||||||
|
|
||||||
radioConfig.preferences.send_owner_interval = 4; // per sw-design.md
|
resetRadioConfig();
|
||||||
radioConfig.preferences.position_broadcast_secs = 15 * 60;
|
|
||||||
radioConfig.preferences.wait_bluetooth_secs = 120;
|
|
||||||
radioConfig.preferences.screen_on_secs = 30;
|
|
||||||
radioConfig.preferences.mesh_sds_timeout_secs = 2 * 60 * 60;
|
|
||||||
radioConfig.preferences.phone_sds_timeout_sec = 2 * 60 * 60;
|
|
||||||
radioConfig.preferences.sds_secs = 365 * 24 * 60 * 60; // one year
|
|
||||||
radioConfig.preferences.ls_secs = 60 * 60;
|
|
||||||
radioConfig.preferences.phone_timeout_secs = 15 * 60;
|
|
||||||
|
|
||||||
// default to no GPS, until one has been found by probing
|
// default to no GPS, until one has been found by probing
|
||||||
myNodeInfo.has_gps = false;
|
myNodeInfo.has_gps = false;
|
||||||
@@ -102,6 +124,7 @@ void NodeDB::init()
|
|||||||
|
|
||||||
// saveToDisk();
|
// saveToDisk();
|
||||||
loadFromDisk();
|
loadFromDisk();
|
||||||
|
resetRadioConfig(); // If bogus settings got saved, then fix them
|
||||||
|
|
||||||
DEBUG_MSG("NODENUM=0x%x, dbsize=%d\n", myNodeInfo.my_node_num, *numNodes);
|
DEBUG_MSG("NODENUM=0x%x, dbsize=%d\n", myNodeInfo.my_node_num, *numNodes);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,6 +43,9 @@ class NodeDB
|
|||||||
/// write to flash
|
/// write to flash
|
||||||
void saveToDisk();
|
void saveToDisk();
|
||||||
|
|
||||||
|
// Reinit radio config if needed, because sometimes a buggy android app might send us bogus settings
|
||||||
|
void resetRadioConfig();
|
||||||
|
|
||||||
/// given a subpacket sniffed from the network, update our DB state
|
/// given a subpacket sniffed from the network, update our DB state
|
||||||
/// we updateGUI and updateGUIforNode if we think our this change is big enough for a redraw
|
/// we updateGUI and updateGUIforNode if we think our this change is big enough for a redraw
|
||||||
void updateFrom(const MeshPacket &p);
|
void updateFrom(const MeshPacket &p);
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ static void lsEnter()
|
|||||||
screen.setOn(false);
|
screen.setOn(false);
|
||||||
|
|
||||||
uint32_t now = millis();
|
uint32_t now = millis();
|
||||||
while (!service.radio.rf95.canSleep()) {
|
while (!service.radio.radioIf.canSleep()) {
|
||||||
delay(10); // Kinda yucky - wait until radio says say we can shutdown (finished in process sends/receives)
|
delay(10); // Kinda yucky - wait until radio says say we can shutdown (finished in process sends/receives)
|
||||||
|
|
||||||
if (millis() - now > 30 * 1000) { // If we wait too long just report an error and go to sleep
|
if (millis() - now > 30 * 1000) { // If we wait too long just report an error and go to sleep
|
||||||
@@ -82,7 +82,12 @@ static void lsIdle()
|
|||||||
} else {
|
} else {
|
||||||
DEBUG_MSG("wakeCause %d\n", wakeCause);
|
DEBUG_MSG("wakeCause %d\n", wakeCause);
|
||||||
|
|
||||||
if (!digitalRead(BUTTON_PIN)) // If we woke because of press, instead generate a PRESS event.
|
#ifdef BUTTON_PIN
|
||||||
|
bool pressed = !digitalRead(BUTTON_PIN);
|
||||||
|
#else
|
||||||
|
bool pressed = false;
|
||||||
|
#endif
|
||||||
|
if (pressed) // If we woke because of press, instead generate a PRESS event.
|
||||||
{
|
{
|
||||||
powerFSM.trigger(EVENT_PRESS);
|
powerFSM.trigger(EVENT_PRESS);
|
||||||
} else {
|
} else {
|
||||||
@@ -108,6 +113,7 @@ static void nbEnter()
|
|||||||
|
|
||||||
static void darkEnter()
|
static void darkEnter()
|
||||||
{
|
{
|
||||||
|
setBluetoothEnable(true);
|
||||||
screen.setOn(false);
|
screen.setOn(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
15
src/RadioInterface.cpp
Normal file
15
src/RadioInterface.cpp
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
#include "CustomRF95.h"
|
||||||
|
#include "NodeDB.h"
|
||||||
|
#include "assert.h"
|
||||||
|
#include "configuration.h"
|
||||||
|
#include <pb_decode.h>
|
||||||
|
#include <pb_encode.h>
|
||||||
|
|
||||||
|
RadioInterface::RadioInterface(MemoryPool<MeshPacket> &_pool, PointerQueue<MeshPacket> &_rxDest) : pool(_pool), rxDest(_rxDest) {}
|
||||||
|
|
||||||
|
ErrorCode SimRadio::send(MeshPacket *p)
|
||||||
|
{
|
||||||
|
DEBUG_MSG("SimRadio.send\n");
|
||||||
|
pool.release(p);
|
||||||
|
return ERRNO_OK;
|
||||||
|
}
|
||||||
123
src/RadioInterface.h
Normal file
123
src/RadioInterface.h
Normal file
@@ -0,0 +1,123 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "MemoryPool.h"
|
||||||
|
#include "MeshTypes.h"
|
||||||
|
#include "PointerQueue.h"
|
||||||
|
#include "mesh.pb.h"
|
||||||
|
#include <RH_RF95.h>
|
||||||
|
|
||||||
|
#define MAX_TX_QUEUE 16 // max number of packets which can be waiting for transmission
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Basic operations all radio chipsets must implement.
|
||||||
|
*
|
||||||
|
* This defines the SOLE API for talking to radios (because soon we will have alternate radio implementations)
|
||||||
|
*/
|
||||||
|
class RadioInterface
|
||||||
|
{
|
||||||
|
friend class MeshRadio; // for debugging we let that class touch pool
|
||||||
|
|
||||||
|
protected:
|
||||||
|
MemoryPool<MeshPacket> &pool;
|
||||||
|
PointerQueue<MeshPacket> &rxDest;
|
||||||
|
|
||||||
|
MeshPacket *sendingPacket = NULL; // The packet we are currently sending
|
||||||
|
public:
|
||||||
|
/** pool is the pool we will alloc our rx packets from
|
||||||
|
* rxDest is where we will send any rx packets, it becomes receivers responsibility to return packet to the pool
|
||||||
|
*/
|
||||||
|
RadioInterface(MemoryPool<MeshPacket> &pool, PointerQueue<MeshPacket> &rxDest);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return true if we think the board can go to sleep (i.e. our tx queue is empty, we are not sending or receiving)
|
||||||
|
*
|
||||||
|
* This method must be used before putting the CPU into deep or light sleep.
|
||||||
|
*/
|
||||||
|
virtual bool canSleep() { return true; }
|
||||||
|
|
||||||
|
/// Prepare hardware for sleep. Call this _only_ for deep sleep, not needed for light sleep.
|
||||||
|
/// return true for success
|
||||||
|
virtual bool sleep() { return true; }
|
||||||
|
|
||||||
|
/// Send a packet (possibly by enquing in a private fifo). This routine will
|
||||||
|
/// later free() the packet to pool. This routine is not allowed to stall because it is called from
|
||||||
|
/// bluetooth comms code. If the txmit queue is empty it might return an error
|
||||||
|
virtual ErrorCode send(MeshPacket *p) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class SimRadio : public RadioInterface
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/** pool is the pool we will alloc our rx packets from
|
||||||
|
* rxDest is where we will send any rx packets, it becomes receivers responsibility to return packet to the pool
|
||||||
|
*/
|
||||||
|
SimRadio(MemoryPool<MeshPacket> &_pool, PointerQueue<MeshPacket> &_rxDest) : RadioInterface(_pool, _rxDest) {}
|
||||||
|
|
||||||
|
virtual ErrorCode send(MeshPacket *p);
|
||||||
|
|
||||||
|
// methods from radiohead
|
||||||
|
|
||||||
|
/// Sets the address of this node. Defaults to 0xFF. Subclasses or the user may want to change this.
|
||||||
|
/// This will be used to test the adddress in incoming messages. In non-promiscuous mode,
|
||||||
|
/// only messages with a TO header the same as thisAddress or the broadcast addess (0xFF) will be accepted.
|
||||||
|
/// In promiscuous mode, all messages will be accepted regardless of the TO header.
|
||||||
|
/// In a conventional multinode system, all nodes will have a unique address
|
||||||
|
/// (which you could store in EEPROM).
|
||||||
|
/// You would normally set the header FROM address to be the same as thisAddress (though you dont have to,
|
||||||
|
/// allowing the possibilty of address spoofing).
|
||||||
|
/// \param[in] thisAddress The address of this node.
|
||||||
|
virtual void setThisAddress(uint8_t thisAddress) {}
|
||||||
|
|
||||||
|
/// Initialise the Driver transport hardware and software.
|
||||||
|
/// Make sure the Driver is properly configured before calling init().
|
||||||
|
/// \return true if initialisation succeeded.
|
||||||
|
virtual bool init() { return true; }
|
||||||
|
|
||||||
|
/// Sets the transmitter and receiver
|
||||||
|
/// centre frequency.
|
||||||
|
/// \param[in] centre Frequency in MHz. 137.0 to 1020.0. Caution: RFM95/96/97/98 comes in several
|
||||||
|
/// different frequency ranges, and setting a frequency outside that range of your radio will probably not work
|
||||||
|
/// \return true if the selected frquency centre is within range
|
||||||
|
bool setFrequency(float centre) { return true; }
|
||||||
|
|
||||||
|
/// Select one of the predefined modem configurations. If you need a modem configuration not provided
|
||||||
|
/// here, use setModemRegisters() with your own ModemConfig.
|
||||||
|
/// Caution: the slowest protocols may require a radio module with TCXO temperature controlled oscillator
|
||||||
|
/// for reliable operation.
|
||||||
|
/// \param[in] index The configuration choice.
|
||||||
|
/// \return true if index is a valid choice.
|
||||||
|
bool setModemConfig(RH_RF95::ModemConfigChoice index) { return true; }
|
||||||
|
|
||||||
|
/// If current mode is Rx or Tx changes it to Idle. If the transmitter or receiver is running,
|
||||||
|
/// disables them.
|
||||||
|
void setModeIdle() {}
|
||||||
|
|
||||||
|
/// If current mode is Tx or Idle, changes it to Rx.
|
||||||
|
/// Starts the receiver in the RF95/96/97/98.
|
||||||
|
void setModeRx() {}
|
||||||
|
|
||||||
|
/// Returns the operating mode of the library.
|
||||||
|
/// \return the current mode, one of RF69_MODE_*
|
||||||
|
virtual RHGenericDriver::RHMode mode() { return RHGenericDriver::RHModeIdle; }
|
||||||
|
|
||||||
|
/// Sets the transmitter power output level, and configures the transmitter pin.
|
||||||
|
/// Be a good neighbour and set the lowest power level you need.
|
||||||
|
/// Some SX1276/77/78/79 and compatible modules (such as RFM95/96/97/98)
|
||||||
|
/// use the PA_BOOST transmitter pin for high power output (and optionally the PA_DAC)
|
||||||
|
/// while some (such as the Modtronix inAir4 and inAir9)
|
||||||
|
/// use the RFO transmitter pin for lower power but higher efficiency.
|
||||||
|
/// You must set the appropriate power level and useRFO argument for your module.
|
||||||
|
/// Check with your module manufacturer which transmtter pin is used on your module
|
||||||
|
/// to ensure you are setting useRFO correctly.
|
||||||
|
/// Failure to do so will result in very low
|
||||||
|
/// transmitter power output.
|
||||||
|
/// Caution: legal power limits may apply in certain countries.
|
||||||
|
/// After init(), the power will be set to 13dBm, with useRFO false (ie PA_BOOST enabled).
|
||||||
|
/// \param[in] power Transmitter power level in dBm. For RFM95/96/97/98 LORA with useRFO false,
|
||||||
|
/// valid values are from +5 to +23.
|
||||||
|
/// For Modtronix inAir4 and inAir9 with useRFO true (ie RFO pins in use),
|
||||||
|
/// valid values are from -1 to 14.
|
||||||
|
/// \param[in] useRFO If true, enables the use of the RFO transmitter pins instead of
|
||||||
|
/// the PA_BOOST pin (false). Choose the correct setting for your module.
|
||||||
|
void setTxPower(int8_t power, bool useRFO = false) {}
|
||||||
|
};
|
||||||
@@ -39,18 +39,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||||||
// Configuration
|
// Configuration
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
// Select which board is being used. If the outside build environment has sent a choice, just use that
|
|
||||||
#if !defined(T_BEAM_V10) && !defined(HELTEC_LORA32)
|
|
||||||
#define T_BEAM_V10 // AKA Rev1 (second board released)
|
|
||||||
// #define HELTEC_LORA32
|
|
||||||
|
|
||||||
#define HW_VERSION_US // We encode the hardware freq range in the hw version string, so sw update can eventually install the
|
|
||||||
// correct build
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// If we are using the JTAG port for debugging, some pins must be left free for that (and things like GPS have to be disabled)
|
// If we are using the JTAG port for debugging, some pins must be left free for that (and things like GPS have to be disabled)
|
||||||
// we don't support jtag on the ttgo - access to gpio 12 is a PITA
|
// we don't support jtag on the ttgo - access to gpio 12 is a PITA
|
||||||
#ifdef HELTEC_LORA32
|
#ifdef ARDUINO_HELTEC_WIFI_LORA_32_V2
|
||||||
//#define USE_JTAG
|
//#define USE_JTAG
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -105,9 +96,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||||||
#define MOSI_GPIO 27
|
#define MOSI_GPIO 27
|
||||||
#define NSS_GPIO 18
|
#define NSS_GPIO 18
|
||||||
|
|
||||||
#if defined(T_BEAM_V10)
|
#if defined(TBEAM_V10)
|
||||||
// This string must exactly match the case used in release file names or the android updater won't work
|
// This string must exactly match the case used in release file names or the android updater won't work
|
||||||
#define HW_VENDOR "TBEAM"
|
#define HW_VENDOR "tbeam"
|
||||||
|
|
||||||
// #define BUTTON_NEED_PULLUP // if set we need to turn on the internal CPU pullup during sleep
|
// #define BUTTON_NEED_PULLUP // if set we need to turn on the internal CPU pullup during sleep
|
||||||
|
|
||||||
@@ -119,34 +110,98 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||||||
#ifndef USE_JTAG
|
#ifndef USE_JTAG
|
||||||
#define RESET_GPIO 14
|
#define RESET_GPIO 14
|
||||||
#endif
|
#endif
|
||||||
#define DIO0_GPIO 26
|
#define RF95_IRQ_GPIO 26
|
||||||
#define DIO1_GPIO 33 // Note: not really used on this board
|
#define DIO1_GPIO 33 // Note: not really used on this board
|
||||||
#define DIO2_GPIO 32 // Note: not really used on this board
|
#define DIO2_GPIO 32 // Note: not really used on this board
|
||||||
|
|
||||||
// Leave undefined to disable our PMU IRQ handler
|
// Leave undefined to disable our PMU IRQ handler
|
||||||
#define PMU_IRQ 35
|
#define PMU_IRQ 35
|
||||||
|
|
||||||
#elif defined(HELTEC_LORA32)
|
#elif defined(TBEAM_V07)
|
||||||
// This string must exactly match the case used in release file names or the android updater won't work
|
// This string must exactly match the case used in release file names or the android updater won't work
|
||||||
#define HW_VENDOR "HELTEC"
|
#define HW_VENDOR "tbeam0.7"
|
||||||
|
|
||||||
#ifndef USE_JTAG // gpio15 is TDO for JTAG, so no I2C on this board while doing jtag
|
// #define BUTTON_NEED_PULLUP // if set we need to turn on the internal CPU pullup during sleep
|
||||||
#define I2C_SDA 4
|
|
||||||
|
#define I2C_SDA 21
|
||||||
|
#define I2C_SCL 22
|
||||||
|
|
||||||
|
#define BUTTON_PIN 39
|
||||||
|
|
||||||
|
#ifndef USE_JTAG
|
||||||
|
#define RESET_GPIO 23
|
||||||
|
#endif
|
||||||
|
#define RF95_IRQ_GPIO 26
|
||||||
|
#define DIO1_GPIO 33 // Note: not really used on this board
|
||||||
|
#define DIO2_GPIO 32 // Note: not really used on this board
|
||||||
|
|
||||||
|
// This board has different GPS pins than all other boards
|
||||||
|
#undef GPS_RX_PIN
|
||||||
|
#undef GPS_TX_PIN
|
||||||
|
#define GPS_RX_PIN 12
|
||||||
|
#define GPS_TX_PIN 15
|
||||||
|
|
||||||
|
#elif defined(ARDUINO_HELTEC_WIFI_LORA_32_V2)
|
||||||
|
// This string must exactly match the case used in release file names or the android updater won't work
|
||||||
|
#define HW_VENDOR "heltec"
|
||||||
|
|
||||||
|
#ifndef USE_JTAG // gpio15 is TDO for JTAG, so no I2C on this board while doing jtag
|
||||||
|
#define I2C_SDA 4 // I2C pins for this board
|
||||||
#define I2C_SCL 15
|
#define I2C_SCL 15
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define RESET_OLED 16
|
#define RESET_OLED 16 // If defined, this pin will be used to reset the display controller
|
||||||
|
|
||||||
#define VEXT_ENABLE 21 // active low, powers the oled display and the lora antenna boost
|
#define VEXT_ENABLE 21 // active low, powers the oled display and the lora antenna boost
|
||||||
#define LED_PIN 25
|
#define LED_PIN 25 // If defined we will blink this LED
|
||||||
#define BUTTON_PIN 0
|
#define BUTTON_PIN 0 // If defined, this will be used for user button presses
|
||||||
|
|
||||||
#ifndef USE_JTAG
|
#ifndef USE_JTAG
|
||||||
#define RESET_GPIO 14
|
#define RESET_GPIO 14 // If defined, this pin will be used to reset the LORA radio
|
||||||
#endif
|
#endif
|
||||||
#define DIO0_GPIO 26
|
#define RF95_IRQ_GPIO 26
|
||||||
#define DIO1_GPIO 35
|
#define DIO1_GPIO 35 // DIO1 & DIO2 are not currently used, but they must be assigned to a pin number
|
||||||
#define DIO2_GPIO 34
|
#define DIO2_GPIO 34 // DIO1 & DIO2 are not currently used, but they must be assigned to a pin number
|
||||||
|
#elif defined(TTGO_LORA_V1)
|
||||||
|
// This string must exactly match the case used in release file names or the android updater won't work
|
||||||
|
#define HW_VENDOR "ttgo-lora32-v1"
|
||||||
|
|
||||||
|
#define I2C_SDA 21 // I2C pins for this board
|
||||||
|
#define I2C_SCL 22
|
||||||
|
|
||||||
|
#define RESET_OLED 16 // If defined, this pin will be used to reset the display controller
|
||||||
|
|
||||||
|
// #define VEXT_ENABLE 21 // active low, powers the oled display and the lora antenna boost
|
||||||
|
#define LED_PIN 2 // If defined we will blink this LED
|
||||||
|
#define BUTTON_PIN 0 // If defined, this will be used for user button presses
|
||||||
|
|
||||||
|
#define RESET_GPIO 14 // If defined, this pin will be used to reset the LORA radio
|
||||||
|
#define RF95_IRQ_GPIO 26 // IRQ line for the LORA radio
|
||||||
|
#define DIO1_GPIO 35 // DIO1 & DIO2 are not currently used, but they must be assigned to a pin number
|
||||||
|
#define DIO2_GPIO 34 // DIO1 & DIO2 are not currently used, but they must be assigned to a pin number
|
||||||
|
#elif defined(TTGO_LORA_V2)
|
||||||
|
// This string must exactly match the case used in release file names or the android updater won't work
|
||||||
|
#define HW_VENDOR "ttgo-lora32-v2"
|
||||||
|
|
||||||
|
#define I2C_SDA 4 // I2C pins for this board
|
||||||
|
#define I2C_SCL 15
|
||||||
|
|
||||||
|
#define RESET_OLED 16 // If defined, this pin will be used to reset the display controller
|
||||||
|
|
||||||
|
#define VEXT_ENABLE 21 // active low, powers the oled display and the lora antenna boost
|
||||||
|
#define LED_PIN 25 // If defined we will blink this LED
|
||||||
|
#define BUTTON_PIN \
|
||||||
|
0 // If defined, this will be used for user button presses, if your board doesn't have a physical switch, you can wire one
|
||||||
|
// between this pin and ground
|
||||||
|
|
||||||
|
#define RESET_GPIO 14 // If defined, this pin will be used to reset the LORA radio
|
||||||
|
#define RF95_IRQ_GPIO 26 // IRQ line for the LORA radio
|
||||||
|
#define DIO1_GPIO 35 // DIO1 & DIO2 are not currently used, but they must be assigned to a pin number
|
||||||
|
#define DIO2_GPIO 34 // DIO1 & DIO2 are not currently used, but they must be assigned to a pin number
|
||||||
|
#elif defined(BARE_BOARD)
|
||||||
|
// This string must exactly match the case used in release file names or the android updater won't work
|
||||||
|
#define HW_VENDOR "bare"
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|||||||
99
src/main.cpp
99
src/main.cpp
@@ -32,13 +32,14 @@
|
|||||||
#include "configuration.h"
|
#include "configuration.h"
|
||||||
#include "esp32/pm.h"
|
#include "esp32/pm.h"
|
||||||
#include "esp_pm.h"
|
#include "esp_pm.h"
|
||||||
|
#include "power.h"
|
||||||
#include "rom/rtc.h"
|
#include "rom/rtc.h"
|
||||||
#include "screen.h"
|
#include "screen.h"
|
||||||
#include "sleep.h"
|
#include "sleep.h"
|
||||||
#include <Wire.h>
|
#include <Wire.h>
|
||||||
#include <driver/rtc_io.h>
|
#include <driver/rtc_io.h>
|
||||||
|
|
||||||
#ifdef T_BEAM_V10
|
#ifdef TBEAM_V10
|
||||||
#include "axp20x.h"
|
#include "axp20x.h"
|
||||||
AXP20X_Class axp;
|
AXP20X_Class axp;
|
||||||
bool pmu_irq = false;
|
bool pmu_irq = false;
|
||||||
@@ -52,9 +53,8 @@ meshtastic::Screen screen(SSD1306_ADDRESS, I2C_SDA, I2C_SCL);
|
|||||||
meshtastic::Screen screen(SSD1306_ADDRESS, 0, 0);
|
meshtastic::Screen screen(SSD1306_ADDRESS, 0, 0);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// these flags are all in bss so they default false
|
// Global power status singleton
|
||||||
bool isCharging;
|
static meshtastic::PowerStatus powerStatus;
|
||||||
bool isUSBPowered;
|
|
||||||
|
|
||||||
bool ssd1306_found;
|
bool ssd1306_found;
|
||||||
bool axp192_found;
|
bool axp192_found;
|
||||||
@@ -81,7 +81,7 @@ void scanI2Cdevice(void)
|
|||||||
ssd1306_found = true;
|
ssd1306_found = true;
|
||||||
DEBUG_MSG("ssd1306 display found\n");
|
DEBUG_MSG("ssd1306 display found\n");
|
||||||
}
|
}
|
||||||
#ifdef T_BEAM_V10
|
#ifdef TBEAM_V10
|
||||||
if (addr == AXP192_SLAVE_ADDRESS) {
|
if (addr == AXP192_SLAVE_ADDRESS) {
|
||||||
axp192_found = true;
|
axp192_found = true;
|
||||||
DEBUG_MSG("axp192 PMU found\n");
|
DEBUG_MSG("axp192 PMU found\n");
|
||||||
@@ -97,6 +97,21 @@ void scanI2Cdevice(void)
|
|||||||
DEBUG_MSG("done\n");
|
DEBUG_MSG("done\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef TBEAM_V10
|
||||||
|
/// Reads power status to powerStatus singleton.
|
||||||
|
//
|
||||||
|
// TODO(girts): move this and other axp stuff to power.h/power.cpp.
|
||||||
|
void readPowerStatus()
|
||||||
|
{
|
||||||
|
powerStatus.haveBattery = axp.isBatteryConnect();
|
||||||
|
if (powerStatus.haveBattery) {
|
||||||
|
powerStatus.batteryVoltageMv = axp.getBattVoltage();
|
||||||
|
}
|
||||||
|
powerStatus.usb = axp.isVBUSPlug();
|
||||||
|
powerStatus.charging = axp.isChargeing();
|
||||||
|
}
|
||||||
|
#endif // TBEAM_V10
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Init the power manager chip
|
* Init the power manager chip
|
||||||
*
|
*
|
||||||
@@ -108,7 +123,7 @@ void scanI2Cdevice(void)
|
|||||||
*/
|
*/
|
||||||
void axp192Init()
|
void axp192Init()
|
||||||
{
|
{
|
||||||
#ifdef T_BEAM_V10
|
#ifdef TBEAM_V10
|
||||||
if (axp192_found) {
|
if (axp192_found) {
|
||||||
if (!axp.begin(Wire, AXP192_SLAVE_ADDRESS)) {
|
if (!axp.begin(Wire, AXP192_SLAVE_ADDRESS)) {
|
||||||
DEBUG_MSG("AXP192 Begin PASS\n");
|
DEBUG_MSG("AXP192 Begin PASS\n");
|
||||||
@@ -158,18 +173,18 @@ void axp192Init()
|
|||||||
axp.debugCharging();
|
axp.debugCharging();
|
||||||
|
|
||||||
#ifdef PMU_IRQ
|
#ifdef PMU_IRQ
|
||||||
pinMode(PMU_IRQ, INPUT_PULLUP);
|
pinMode(PMU_IRQ, INPUT);
|
||||||
attachInterrupt(
|
attachInterrupt(
|
||||||
PMU_IRQ, [] { pmu_irq = true; }, RISING);
|
PMU_IRQ, [] { pmu_irq = true; }, FALLING);
|
||||||
|
|
||||||
axp.adc1Enable(AXP202_BATT_CUR_ADC1, 1);
|
axp.adc1Enable(AXP202_BATT_CUR_ADC1, 1);
|
||||||
axp.enableIRQ(AXP202_VBUS_REMOVED_IRQ | AXP202_VBUS_CONNECT_IRQ | AXP202_BATT_REMOVED_IRQ | AXP202_BATT_CONNECT_IRQ,
|
axp.enableIRQ(AXP202_BATT_REMOVED_IRQ | AXP202_BATT_CONNECT_IRQ | AXP202_CHARGING_FINISHED_IRQ | AXP202_CHARGING_IRQ |
|
||||||
|
AXP202_VBUS_REMOVED_IRQ | AXP202_VBUS_CONNECT_IRQ | AXP202_PEK_SHORTPRESS_IRQ,
|
||||||
1);
|
1);
|
||||||
|
|
||||||
axp.clearIRQ();
|
axp.clearIRQ();
|
||||||
#endif
|
#endif
|
||||||
|
readPowerStatus();
|
||||||
isCharging = axp.isChargeing() ? 1 : 0;
|
|
||||||
isUSBPowered = axp.isVBUSPlug() ? 1 : 0;
|
|
||||||
} else {
|
} else {
|
||||||
DEBUG_MSG("AXP192 Begin FAIL\n");
|
DEBUG_MSG("AXP192 Begin FAIL\n");
|
||||||
}
|
}
|
||||||
@@ -302,7 +317,7 @@ uint32_t ledBlinker()
|
|||||||
setLed(ledOn);
|
setLed(ledOn);
|
||||||
|
|
||||||
// have a very sparse duty cycle of LED being on, unless charging, then blink 0.5Hz square wave rate to indicate that
|
// have a very sparse duty cycle of LED being on, unless charging, then blink 0.5Hz square wave rate to indicate that
|
||||||
return isCharging ? 1000 : (ledOn ? 2 : 1000);
|
return powerStatus.charging ? 1000 : (ledOn ? 2 : 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
Periodic ledPeriodic(ledBlinker);
|
Periodic ledPeriodic(ledBlinker);
|
||||||
@@ -310,18 +325,21 @@ Periodic ledPeriodic(ledBlinker);
|
|||||||
#if 0
|
#if 0
|
||||||
// Turn off for now
|
// Turn off for now
|
||||||
|
|
||||||
uint32_t axpReads()
|
uint32_t axpDebugRead()
|
||||||
{
|
{
|
||||||
axp.debugCharging();
|
axp.debugCharging();
|
||||||
DEBUG_MSG("vbus current %f\n", axp.getVbusCurrent());
|
DEBUG_MSG("vbus current %f\n", axp.getVbusCurrent());
|
||||||
DEBUG_MSG("charge current %f\n", axp.getBattChargeCurrent());
|
DEBUG_MSG("charge current %f\n", axp.getBattChargeCurrent());
|
||||||
DEBUG_MSG("bat voltage %f\n", axp.getBattVoltage());
|
DEBUG_MSG("bat voltage %f\n", axp.getBattVoltage());
|
||||||
DEBUG_MSG("batt pct %d\n", axp.getBattPercentage());
|
DEBUG_MSG("batt pct %d\n", axp.getBattPercentage());
|
||||||
|
DEBUG_MSG("is battery connected %d\n", axp.isBatteryConnect());
|
||||||
|
DEBUG_MSG("is USB connected %d\n", axp.isVBUSPlug());
|
||||||
|
DEBUG_MSG("is charging %d\n", axp.isChargeing());
|
||||||
|
|
||||||
return 30 * 1000;
|
return 30 * 1000;
|
||||||
}
|
}
|
||||||
|
|
||||||
Periodic axpDebugOutput(axpReads);
|
Periodic axpDebugOutput(axpDebugRead);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void loop()
|
void loop()
|
||||||
@@ -330,7 +348,6 @@ void loop()
|
|||||||
|
|
||||||
powerFSM.run_machine();
|
powerFSM.run_machine();
|
||||||
gps.loop();
|
gps.loop();
|
||||||
screen.loop();
|
|
||||||
service.loop();
|
service.loop();
|
||||||
|
|
||||||
ledPeriodic.loop();
|
ledPeriodic.loop();
|
||||||
@@ -340,27 +357,39 @@ void loop()
|
|||||||
// for debug printing
|
// for debug printing
|
||||||
// service.radio.rf95.canSleep();
|
// service.radio.rf95.canSleep();
|
||||||
|
|
||||||
#ifdef T_BEAM_V10
|
|
||||||
if (axp192_found) {
|
|
||||||
#ifdef PMU_IRQ
|
#ifdef PMU_IRQ
|
||||||
if (pmu_irq) {
|
if (pmu_irq) {
|
||||||
pmu_irq = false;
|
pmu_irq = false;
|
||||||
axp.readIRQ();
|
axp.readIRQ();
|
||||||
|
|
||||||
DEBUG_MSG("pmu irq!\n");
|
DEBUG_MSG("pmu irq!\n");
|
||||||
|
|
||||||
isCharging = axp.isChargeing() ? 1 : 0;
|
if (axp.isChargingIRQ()) {
|
||||||
isUSBPowered = axp.isVBUSPlug() ? 1 : 0;
|
DEBUG_MSG("Battery start charging\n");
|
||||||
|
}
|
||||||
axp.clearIRQ();
|
if (axp.isChargingDoneIRQ()) {
|
||||||
|
DEBUG_MSG("Battery fully charged\n");
|
||||||
|
}
|
||||||
|
if (axp.isVbusRemoveIRQ()) {
|
||||||
|
DEBUG_MSG("USB unplugged\n");
|
||||||
|
}
|
||||||
|
if (axp.isVbusPlugInIRQ()) {
|
||||||
|
DEBUG_MSG("USB plugged In\n");
|
||||||
|
}
|
||||||
|
if (axp.isBattPlugInIRQ()) {
|
||||||
|
DEBUG_MSG("Battery inserted\n");
|
||||||
|
}
|
||||||
|
if (axp.isBattRemoveIRQ()) {
|
||||||
|
DEBUG_MSG("Battery removed\n");
|
||||||
|
}
|
||||||
|
if (axp.isPEKShortPressIRQ()) {
|
||||||
|
DEBUG_MSG("PEK short button press\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME AXP192 interrupt is not firing, remove this temporary polling of battery state
|
readPowerStatus();
|
||||||
isCharging = axp.isChargeing() ? 1 : 0;
|
axp.clearIRQ();
|
||||||
isUSBPowered = axp.isVBUSPlug() ? 1 : 0;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif // T_BEAM_V10
|
||||||
|
|
||||||
#ifdef BUTTON_PIN
|
#ifdef BUTTON_PIN
|
||||||
// if user presses button for more than 3 secs, discard our network prefs and reboot (FIXME, use a debounce lib instead of
|
// if user presses button for more than 3 secs, discard our network prefs and reboot (FIXME, use a debounce lib instead of
|
||||||
@@ -390,6 +419,14 @@ void loop()
|
|||||||
showingBootScreen = false;
|
showingBootScreen = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update the screen last, after we've figured out what to show.
|
||||||
|
screen.debug()->setNodeNumbersStatus(nodeDB.getNumOnlineNodes(), nodeDB.getNumNodes());
|
||||||
|
screen.debug()->setChannelNameStatus(channelSettings.name);
|
||||||
|
screen.debug()->setPowerStatus(powerStatus);
|
||||||
|
// TODO(#4): use something based on hdop to show GPS "signal" strength.
|
||||||
|
screen.debug()->setGPSStatus(gps.hasLock() ? "ok" : ":(");
|
||||||
|
screen.loop();
|
||||||
|
|
||||||
// No GPS lock yet, let the OS put the main CPU in low power mode for 100ms (or until another interrupt comes in)
|
// No GPS lock yet, let the OS put the main CPU in low power mode for 100ms (or until another interrupt comes in)
|
||||||
// i.e. don't just keep spinning in loop as fast as we can.
|
// i.e. don't just keep spinning in loop as fast as we can.
|
||||||
// DEBUG_MSG("msecs %d\n", msecstosleep);
|
// DEBUG_MSG("msecs %d\n", msecstosleep);
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ typedef struct _MyNodeInfo {
|
|||||||
bool has_gps;
|
bool has_gps;
|
||||||
int32_t num_channels;
|
int32_t num_channels;
|
||||||
char region[12];
|
char region[12];
|
||||||
char hw_model[12];
|
char hw_model[16];
|
||||||
char firmware_version[12];
|
char firmware_version[12];
|
||||||
uint32_t error_code;
|
uint32_t error_code;
|
||||||
uint32_t error_address;
|
uint32_t error_address;
|
||||||
@@ -431,8 +431,8 @@ extern const pb_msgdesc_t ToRadio_msg;
|
|||||||
#define RadioConfig_size 120
|
#define RadioConfig_size 120
|
||||||
#define RadioConfig_UserPreferences_size 72
|
#define RadioConfig_UserPreferences_size 72
|
||||||
#define NodeInfo_size 155
|
#define NodeInfo_size 155
|
||||||
#define MyNodeInfo_size 81
|
#define MyNodeInfo_size 85
|
||||||
#define DeviceState_size 15076
|
#define DeviceState_size 15080
|
||||||
#define FromRadio_size 301
|
#define FromRadio_size 301
|
||||||
#define ToRadio_size 295
|
#define ToRadio_size 295
|
||||||
|
|
||||||
|
|||||||
18
src/power.h
Normal file
18
src/power.h
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace meshtastic
|
||||||
|
{
|
||||||
|
|
||||||
|
/// Describes the state of the power system.
|
||||||
|
struct PowerStatus {
|
||||||
|
/// Whether we have a battery connected
|
||||||
|
bool haveBattery;
|
||||||
|
/// Battery voltage in mV, valid if haveBattery is true
|
||||||
|
int batteryVoltageMv;
|
||||||
|
/// Whether USB is connected
|
||||||
|
bool usb;
|
||||||
|
/// Whether we are charging the battery
|
||||||
|
bool charging;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace meshtastic
|
||||||
@@ -135,15 +135,17 @@ static uint32_t drawRows(OLEDDisplay *display, int16_t x, int16_t y, const char
|
|||||||
display->drawString(xo, yo, *f);
|
display->drawString(xo, yo, *f);
|
||||||
xo += SCREEN_WIDTH / COLUMNS;
|
xo += SCREEN_WIDTH / COLUMNS;
|
||||||
// Wrap to next row, if needed.
|
// Wrap to next row, if needed.
|
||||||
if (++col > COLUMNS) {
|
if (++col >= COLUMNS) {
|
||||||
xo = x;
|
xo = x;
|
||||||
yo += FONT_HEIGHT;
|
yo += FONT_HEIGHT;
|
||||||
col = 0;
|
col = 0;
|
||||||
}
|
}
|
||||||
f++;
|
f++;
|
||||||
}
|
}
|
||||||
|
if (col != 0) {
|
||||||
yo += FONT_HEIGHT; // include the last line in our total
|
// Include last incomplete line in our total.
|
||||||
|
yo += FONT_HEIGHT;
|
||||||
|
}
|
||||||
|
|
||||||
return yo;
|
return yo;
|
||||||
}
|
}
|
||||||
@@ -375,36 +377,6 @@ static void drawNodeInfo(OLEDDisplay *display, OLEDDisplayUiState *state, int16_
|
|||||||
display->drawCircle(compassX, compassY, COMPASS_DIAM / 2);
|
display->drawCircle(compassX, compassY, COMPASS_DIAM / 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void drawDebugInfo(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
|
|
||||||
{
|
|
||||||
display->setFont(ArialMT_Plain_10);
|
|
||||||
|
|
||||||
// The coordinates define the left starting point of the text
|
|
||||||
display->setTextAlignment(TEXT_ALIGN_LEFT);
|
|
||||||
|
|
||||||
static char usersStr[20];
|
|
||||||
snprintf(usersStr, sizeof(usersStr), "Users %d/%d", nodeDB.getNumOnlineNodes(), nodeDB.getNumNodes());
|
|
||||||
|
|
||||||
static char channelStr[20];
|
|
||||||
snprintf(channelStr, sizeof(channelStr), "%s", channelSettings.name);
|
|
||||||
|
|
||||||
// We don't show battery levels yet - for now just lie and show debug info
|
|
||||||
static char batStr[20];
|
|
||||||
snprintf(batStr, sizeof(batStr), "Batt %x%%", (isCharging << 1) + isUSBPowered);
|
|
||||||
|
|
||||||
static char gpsStr[20];
|
|
||||||
if (myNodeInfo.has_gps)
|
|
||||||
snprintf(gpsStr, sizeof(gpsStr), "GPS %d%%",
|
|
||||||
75); // FIXME, use something based on hdop
|
|
||||||
else
|
|
||||||
gpsStr[0] = '\0'; // Just show emptystring
|
|
||||||
|
|
||||||
const char *fields[] = {batStr, gpsStr, usersStr, channelStr, NULL};
|
|
||||||
uint32_t yo = drawRows(display, x, y, fields);
|
|
||||||
|
|
||||||
display->drawLogBuffer(x, yo);
|
|
||||||
}
|
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
void _screen_header()
|
void _screen_header()
|
||||||
{
|
{
|
||||||
@@ -429,10 +401,7 @@ void _screen_header()
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
Screen::Screen(uint8_t address, uint8_t sda, uint8_t scl)
|
Screen::Screen(uint8_t address, uint8_t sda, uint8_t scl) : cmdQueue(32), dispdev(address, sda, scl), ui(&dispdev) {}
|
||||||
: cmdQueue(32), useDisplay(sda || scl), dispdev(address, sda, scl), ui(&dispdev)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void Screen::handleSetOn(bool on)
|
void Screen::handleSetOn(bool on)
|
||||||
{
|
{
|
||||||
@@ -453,8 +422,9 @@ void Screen::handleSetOn(bool on)
|
|||||||
|
|
||||||
void Screen::setup()
|
void Screen::setup()
|
||||||
{
|
{
|
||||||
if (!useDisplay)
|
// We don't set useDisplay until setup() is called, because some boards have a declaration of this object but the device
|
||||||
return;
|
// is never found when probing i2c and therefore we don't call setup and never want to do (invalid) accesses to this device.
|
||||||
|
useDisplay = true;
|
||||||
|
|
||||||
dispdev.resetOrientation();
|
dispdev.resetOrientation();
|
||||||
|
|
||||||
@@ -467,6 +437,8 @@ void Screen::setup()
|
|||||||
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.
|
||||||
|
ui.getUiState()->userData = this;
|
||||||
|
|
||||||
// Add frames.
|
// Add frames.
|
||||||
static FrameCallback bootFrames[] = {drawBootScreen};
|
static FrameCallback bootFrames[] = {drawBootScreen};
|
||||||
@@ -573,6 +545,12 @@ void Screen::doTask()
|
|||||||
setPeriod(1000 / targetFramerate);
|
setPeriod(1000 / targetFramerate);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Screen::drawDebugInfoTrampoline(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
|
||||||
|
{
|
||||||
|
Screen *screen = reinterpret_cast<Screen *>(state->userData);
|
||||||
|
screen->debugInfo.drawFrame(display, state, x, y);
|
||||||
|
}
|
||||||
|
|
||||||
// restore our regular frame list
|
// restore our regular frame list
|
||||||
void Screen::setFrames()
|
void Screen::setFrames()
|
||||||
{
|
{
|
||||||
@@ -595,7 +573,10 @@ void Screen::setFrames()
|
|||||||
normalFrames[numframes++] = drawNodeInfo;
|
normalFrames[numframes++] = drawNodeInfo;
|
||||||
|
|
||||||
// then the debug info
|
// then the debug info
|
||||||
normalFrames[numframes++] = drawDebugInfo;
|
//
|
||||||
|
// Since frames are basic function pointers, we have to use a helper to
|
||||||
|
// call a method on debugInfo object.
|
||||||
|
normalFrames[numframes++] = &Screen::drawDebugInfoTrampoline;
|
||||||
|
|
||||||
ui.setFrames(normalFrames, numframes);
|
ui.setFrames(normalFrames, numframes);
|
||||||
ui.enableAllIndicators();
|
ui.enableAllIndicators();
|
||||||
@@ -642,4 +623,42 @@ void Screen::handleOnPress()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DebugInfo::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
|
||||||
|
{
|
||||||
|
display->setFont(ArialMT_Plain_10);
|
||||||
|
|
||||||
|
// The coordinates define the left starting point of the text
|
||||||
|
display->setTextAlignment(TEXT_ALIGN_LEFT);
|
||||||
|
|
||||||
|
char usersStr[20];
|
||||||
|
char channelStr[20];
|
||||||
|
char batStr[20];
|
||||||
|
char gpsStr[20];
|
||||||
|
{
|
||||||
|
LockGuard guard(&lock);
|
||||||
|
snprintf(usersStr, sizeof(usersStr), "Users %d/%d", nodesOnline, nodesTotal);
|
||||||
|
snprintf(channelStr, sizeof(channelStr), "%s", channelName.c_str());
|
||||||
|
if (powerStatus.haveBattery) {
|
||||||
|
// TODO: draw a battery icon instead of letter "B".
|
||||||
|
int batV = powerStatus.batteryVoltageMv / 1000;
|
||||||
|
int batCv = (powerStatus.batteryVoltageMv % 1000) / 10;
|
||||||
|
snprintf(batStr, sizeof(batStr), "B %01d.%02dV%c%c", batV, batCv, powerStatus.charging ? '+' : ' ',
|
||||||
|
powerStatus.usb ? 'U' : ' ');
|
||||||
|
} else {
|
||||||
|
snprintf(batStr, sizeof(batStr), "%s", powerStatus.usb ? "USB" : "");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!gpsStatus.empty()) {
|
||||||
|
snprintf(gpsStr, sizeof(gpsStr), "GPS %s", gpsStatus.c_str());
|
||||||
|
} else {
|
||||||
|
gpsStr[0] = '\0'; // Just show empty string.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *fields[] = {batStr, gpsStr, usersStr, channelStr, nullptr};
|
||||||
|
uint32_t yo = drawRows(display, x, y, fields);
|
||||||
|
|
||||||
|
display->drawLogBuffer(x, yo);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace meshtastic
|
} // namespace meshtastic
|
||||||
|
|||||||
92
src/screen.h
92
src/screen.h
@@ -7,14 +7,84 @@
|
|||||||
|
|
||||||
#include "PeriodicTask.h"
|
#include "PeriodicTask.h"
|
||||||
#include "TypedQueue.h"
|
#include "TypedQueue.h"
|
||||||
|
#include "lock.h"
|
||||||
|
#include "power.h"
|
||||||
|
|
||||||
namespace meshtastic
|
namespace meshtastic
|
||||||
{
|
{
|
||||||
|
|
||||||
|
// Forward declarations
|
||||||
|
class Screen;
|
||||||
|
|
||||||
|
/// Handles gathering and displaying debug information.
|
||||||
|
class DebugInfo
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
DebugInfo(const DebugInfo &) = delete;
|
||||||
|
DebugInfo &operator=(const DebugInfo &) = delete;
|
||||||
|
|
||||||
|
/// Sets user statistics.
|
||||||
|
void setNodeNumbersStatus(int online, int total)
|
||||||
|
{
|
||||||
|
LockGuard guard(&lock);
|
||||||
|
nodesOnline = online;
|
||||||
|
nodesTotal = total;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sets the name of the channel.
|
||||||
|
void setChannelNameStatus(const char *name)
|
||||||
|
{
|
||||||
|
LockGuard guard(&lock);
|
||||||
|
channelName = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sets battery/charging/etc status.
|
||||||
|
//
|
||||||
|
void setPowerStatus(const PowerStatus &status)
|
||||||
|
{
|
||||||
|
LockGuard guard(&lock);
|
||||||
|
powerStatus = status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sets GPS status.
|
||||||
|
//
|
||||||
|
// If this function never gets called, we assume GPS does not exist on this
|
||||||
|
// device.
|
||||||
|
// TODO(girts): figure out what the format should be.
|
||||||
|
void setGPSStatus(const char *status)
|
||||||
|
{
|
||||||
|
LockGuard guard(&lock);
|
||||||
|
gpsStatus = status;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
friend Screen;
|
||||||
|
|
||||||
|
DebugInfo() {}
|
||||||
|
|
||||||
|
/// Renders the debug screen.
|
||||||
|
void drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y);
|
||||||
|
|
||||||
|
int nodesOnline = 0;
|
||||||
|
int nodesTotal = 0;
|
||||||
|
|
||||||
|
PowerStatus powerStatus;
|
||||||
|
|
||||||
|
std::string channelName;
|
||||||
|
|
||||||
|
std::string gpsStatus;
|
||||||
|
|
||||||
|
/// Protects all of internal state.
|
||||||
|
Lock lock;
|
||||||
|
};
|
||||||
|
|
||||||
/// Deals with showing things on the screen of the device.
|
/// Deals with showing things on the screen of the device.
|
||||||
//
|
//
|
||||||
// Other than setup(), this class is thread-safe. All state-changing calls are
|
// Other than setup(), this class is thread-safe. All state-changing calls are
|
||||||
// queued and executed when the main loop calls us.
|
// queued and executed when the main loop calls us.
|
||||||
|
//
|
||||||
|
// This class is thread-safe (as long as drawFrame is not called multiple times
|
||||||
|
// simultaneously).
|
||||||
class Screen : public PeriodicTask
|
class Screen : public PeriodicTask
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -66,6 +136,11 @@ class Screen : public PeriodicTask
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns a handle to the DebugInfo screen.
|
||||||
|
//
|
||||||
|
// Use this handle to set things like battery status, user count, GPS status, etc.
|
||||||
|
DebugInfo *debug() { return &debugInfo; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/// Updates the UI.
|
/// Updates the UI.
|
||||||
//
|
//
|
||||||
@@ -94,9 +169,13 @@ class Screen : public PeriodicTask
|
|||||||
/// Enques given command item to be processed by main loop().
|
/// Enques given command item to be processed by main loop().
|
||||||
bool enqueueCmd(const CmdItem &cmd)
|
bool enqueueCmd(const CmdItem &cmd)
|
||||||
{
|
{
|
||||||
bool success = cmdQueue.enqueue(cmd, 0);
|
if (!useDisplay)
|
||||||
setPeriod(1); // handle ASAP
|
return true; // claim success if our display is not in use
|
||||||
return success;
|
else {
|
||||||
|
bool success = cmdQueue.enqueue(cmd, 0);
|
||||||
|
setPeriod(1); // handle ASAP
|
||||||
|
return success;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implementations of various commands, called from doTask().
|
// Implementations of various commands, called from doTask().
|
||||||
@@ -108,7 +187,9 @@ class Screen : public PeriodicTask
|
|||||||
/// Rebuilds our list of frames (screens) to default ones.
|
/// Rebuilds our list of frames (screens) to default ones.
|
||||||
void setFrames();
|
void setFrames();
|
||||||
|
|
||||||
private:
|
/// 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);
|
||||||
|
|
||||||
/// Queue of commands to execute in doTask.
|
/// Queue of commands to execute in doTask.
|
||||||
TypedQueue<CmdItem> cmdQueue;
|
TypedQueue<CmdItem> cmdQueue;
|
||||||
/// Whether we are using a display
|
/// Whether we are using a display
|
||||||
@@ -118,6 +199,9 @@ class Screen : public PeriodicTask
|
|||||||
// Whether we are showing the regular screen (as opposed to booth screen or
|
// Whether we are showing the regular screen (as opposed to booth screen or
|
||||||
// Bluetooth PIN screen)
|
// Bluetooth PIN screen)
|
||||||
bool showingNormalScreen = false;
|
bool showingNormalScreen = false;
|
||||||
|
|
||||||
|
/// Holds state for debug information
|
||||||
|
DebugInfo debugInfo;
|
||||||
/// Display device
|
/// Display device
|
||||||
SSD1306Wire dispdev;
|
SSD1306Wire dispdev;
|
||||||
/// UI helper for rendering to frames and switching between them
|
/// UI helper for rendering to frames and switching between them
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
#include <Wire.h>
|
#include <Wire.h>
|
||||||
#include <driver/rtc_io.h>
|
#include <driver/rtc_io.h>
|
||||||
|
|
||||||
#ifdef T_BEAM_V10
|
#ifdef TBEAM_V10
|
||||||
#include "axp20x.h"
|
#include "axp20x.h"
|
||||||
extern AXP20X_Class axp;
|
extern AXP20X_Class axp;
|
||||||
#endif
|
#endif
|
||||||
@@ -48,7 +48,7 @@ void setLed(bool ledOn)
|
|||||||
digitalWrite(LED_PIN, ledOn);
|
digitalWrite(LED_PIN, ledOn);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef T_BEAM_V10
|
#ifdef TBEAM_V10
|
||||||
if (axp192_found) {
|
if (axp192_found) {
|
||||||
// blink the axp led
|
// blink the axp led
|
||||||
axp.setChgLEDMode(ledOn ? AXP20X_LED_LOW_LEVEL : AXP20X_LED_OFF);
|
axp.setChgLEDMode(ledOn ? AXP20X_LED_LOW_LEVEL : AXP20X_LED_OFF);
|
||||||
@@ -60,7 +60,7 @@ void setGPSPower(bool on)
|
|||||||
{
|
{
|
||||||
DEBUG_MSG("Setting GPS power=%d\n", on);
|
DEBUG_MSG("Setting GPS power=%d\n", on);
|
||||||
|
|
||||||
#ifdef T_BEAM_V10
|
#ifdef TBEAM_V10
|
||||||
if (axp192_found)
|
if (axp192_found)
|
||||||
axp.setPowerOutPut(AXP192_LDO3, on ? AXP202_ON : AXP202_OFF); // GPS main power
|
axp.setPowerOutPut(AXP192_LDO3, on ? AXP202_ON : AXP202_OFF); // GPS main power
|
||||||
#endif
|
#endif
|
||||||
@@ -110,7 +110,7 @@ void doDeepSleep(uint64_t msecToWake)
|
|||||||
screen.setOn(false); // datasheet says this will draw only 10ua
|
screen.setOn(false); // datasheet says this will draw only 10ua
|
||||||
|
|
||||||
// Put radio in sleep mode (will still draw power but only 0.2uA)
|
// Put radio in sleep mode (will still draw power but only 0.2uA)
|
||||||
service.radio.rf95.sleep();
|
service.radio.radioIf.sleep();
|
||||||
|
|
||||||
nodeDB.saveToDisk();
|
nodeDB.saveToDisk();
|
||||||
|
|
||||||
@@ -124,7 +124,7 @@ void doDeepSleep(uint64_t msecToWake)
|
|||||||
|
|
||||||
setLed(false);
|
setLed(false);
|
||||||
|
|
||||||
#ifdef T_BEAM_V10
|
#ifdef TBEAM_V10
|
||||||
if (axp192_found) {
|
if (axp192_found) {
|
||||||
// No need to turn this off if the power draw in sleep mode really is just 0.2uA and turning it off would
|
// No need to turn this off if the power draw in sleep mode really is just 0.2uA and turning it off would
|
||||||
// leave floating input for the IRQ line
|
// leave floating input for the IRQ line
|
||||||
@@ -155,18 +155,13 @@ void doDeepSleep(uint64_t msecToWake)
|
|||||||
static const uint8_t rtcGpios[] = {/* 0, */ 2,
|
static const uint8_t rtcGpios[] = {/* 0, */ 2,
|
||||||
/* 4, */
|
/* 4, */
|
||||||
#ifndef USE_JTAG
|
#ifndef USE_JTAG
|
||||||
12,
|
12, 13,
|
||||||
13,
|
/* 14, */ /* 15, */
|
||||||
/* 14, */ /* 15, */
|
|
||||||
#endif
|
#endif
|
||||||
/* 25, */ 26, /* 27, */
|
/* 25, */ 26, /* 27, */
|
||||||
32,
|
32, 33, 34, 35,
|
||||||
33,
|
36, 37
|
||||||
34,
|
/* 38, 39 */};
|
||||||
35,
|
|
||||||
36,
|
|
||||||
37,
|
|
||||||
/* 38, */ 39};
|
|
||||||
|
|
||||||
for (int i = 0; i < sizeof(rtcGpios); i++)
|
for (int i = 0; i < sizeof(rtcGpios); i++)
|
||||||
rtc_gpio_isolate((gpio_num_t)rtcGpios[i]);
|
rtc_gpio_isolate((gpio_num_t)rtcGpios[i]);
|
||||||
@@ -218,16 +213,21 @@ esp_sleep_wakeup_cause_t doLightSleep(uint64_t sleepMsec) // FIXME, use a more r
|
|||||||
gpio_pullup_en((gpio_num_t)BUTTON_PIN);
|
gpio_pullup_en((gpio_num_t)BUTTON_PIN);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef BUTTON_PIN
|
||||||
gpio_wakeup_enable((gpio_num_t)BUTTON_PIN, GPIO_INTR_LOW_LEVEL); // when user presses, this button goes low
|
gpio_wakeup_enable((gpio_num_t)BUTTON_PIN, GPIO_INTR_LOW_LEVEL); // when user presses, this button goes low
|
||||||
gpio_wakeup_enable((gpio_num_t)DIO0_GPIO, GPIO_INTR_HIGH_LEVEL); // RF95 interrupt, active high
|
#endif
|
||||||
|
#ifdef RF95_IRQ_GPIO
|
||||||
|
gpio_wakeup_enable((gpio_num_t)RF95_IRQ_GPIO, GPIO_INTR_HIGH_LEVEL); // RF95 interrupt, active high
|
||||||
|
#endif
|
||||||
#ifdef PMU_IRQ
|
#ifdef PMU_IRQ
|
||||||
// FIXME, disable wake due to PMU because it seems to fire all the time?
|
// FIXME, disable wake due to PMU because it seems to fire all the time?
|
||||||
// gpio_wakeup_enable((gpio_num_t)PMU_IRQ, GPIO_INTR_HIGH_LEVEL); // pmu irq
|
if (axp192_found)
|
||||||
|
gpio_wakeup_enable((gpio_num_t)PMU_IRQ, GPIO_INTR_LOW_LEVEL); // pmu irq
|
||||||
#endif
|
#endif
|
||||||
assert(esp_sleep_enable_gpio_wakeup() == ESP_OK);
|
assert(esp_sleep_enable_gpio_wakeup() == ESP_OK);
|
||||||
assert(esp_sleep_enable_timer_wakeup(sleepUsec) == ESP_OK);
|
assert(esp_sleep_enable_timer_wakeup(sleepUsec) == ESP_OK);
|
||||||
assert(esp_light_sleep_start() == ESP_OK);
|
assert(esp_light_sleep_start() == ESP_OK);
|
||||||
// DEBUG_MSG("Exit light sleep b=%d, rf95=%d, pmu=%d\n", digitalRead(BUTTON_PIN), digitalRead(DIO0_GPIO),
|
// DEBUG_MSG("Exit light sleep b=%d, rf95=%d, pmu=%d\n", digitalRead(BUTTON_PIN), digitalRead(RF95_IRQ_GPIO),
|
||||||
// digitalRead(PMU_IRQ));
|
// digitalRead(PMU_IRQ));
|
||||||
return esp_sleep_get_wakeup_cause();
|
return esp_sleep_get_wakeup_cause();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user