Compare commits

...

136 Commits
1.1.4 ... 1.1.8

Author SHA1 Message Date
Kevin Hester
21751da5a2 Merge pull request #512 from geeksville/dev
Dev
2020-11-07 04:19:36 -08:00
Kevin Hester
c2e8ac7173 1.1.8 2020-11-07 19:20:38 +08:00
Kevin Hester
2fd5ce00ce fix build for esp32 targets 2020-11-07 15:09:05 +08:00
Kevin Hester
952c216bf7 Merge remote-tracking branch 'root/master' into dev 2020-11-07 14:08:22 +08:00
Kevin Hester
ff4b03b8c1 Fix #509 was causing failure on non GPS equipped boards 2020-11-07 09:15:28 +08:00
Kevin Hester
c5903a790b update for portduino 2020-10-31 15:50:39 +08:00
Kevin Hester
bbc36f7b6f switch to my new SD 7.2.0 S113 based bootloader 2020-10-31 12:22:20 +08:00
Kevin Hester
d7368d5a51 begin deep sleep support for nrf52 2020-10-30 17:05:32 +08:00
Kevin Hester
47bbde3c60 fix #505 allow forced standby mode to not assert fail 2020-10-29 16:13:44 +08:00
Kevin Hester
04942a3570 fix #505 - device can reboot due to race condition in sending 2020-10-29 15:27:05 +08:00
Kevin Hester
62a8c968e8 Merge pull request #504 from geeksville/dev
Dev
2020-10-28 23:14:52 -07:00
Kevin Hester
b9a1cae72d 1.1.7 2020-10-29 13:27:52 +08:00
Kevin Hester
6b442784f3 Merge remote-tracking branch 'root/master' into dev 2020-10-29 13:26:49 +08:00
Kevin Hester
cfcb62bd18 Make region changes take effect immedately 2020-10-29 13:26:36 +08:00
Kevin Hester
f698883c02 add pinetab docs 2020-10-29 13:26:14 +08:00
Kevin Hester
4a5cef886e Merge pull request #450 from BeardyWalrus/master
Fix for #357 - Bluetooth pairing pin disable on devices with no display
2020-10-28 18:44:58 -07:00
Kevin Hester
f6ec129288 Merge branch 'master' into master 2020-10-28 18:38:27 -07:00
Kevin Hester
17763034a0 Merge pull request #503 from geeksville/ppr1
Ppr1
2020-10-27 22:26:18 -07:00
Kevin Hester
4ad562b9f4 The new 7.2.0 soft device works on nrf52833 2020-10-28 13:01:50 +08:00
Kevin Hester
6b838002d4 switch back to tbeam for merge to master 2020-10-28 09:51:30 +08:00
Kevin Hester
5e0d53a1e3 ppr1 todo updates 2020-10-28 09:48:28 +08:00
Kevin Hester
7597d5b3fd PPR1 - GPS serial now works 2020-10-25 17:07:54 +08:00
Kevin Hester
1a8891c33d ppr1: add crude version of charge controller driver 2020-10-24 18:40:47 +08:00
Kevin Hester
f0eeaf01d4 ppr1 lcd is 'good enough' for now 2020-10-24 09:49:14 +08:00
Kevin Hester
d4e95e95a6 fix long-press handling on alternate button 2020-10-24 08:44:54 +08:00
Kevin Hester
0767c8be03 PPR1 fix screen mirroring on LCD 2020-10-24 08:16:15 +08:00
Kevin Hester
18bbf3523e remove unused display code 2020-10-23 22:18:22 +08:00
Kevin Hester
b081a6da56 ppr1 st7567 lcd kinda works now 2020-10-23 18:00:43 +08:00
Kevin Hester
a102e49fdb PPR1 WIP - hacky code to make LCD talk on I2C. Works! 2020-10-23 17:10:48 +08:00
Kevin Hester
c078c08c3e Merge branch 'dev' into ppr1 2020-10-23 16:53:38 +08:00
Kevin Hester
4dd50df810 Merge pull request #498 from geeksville/dev
1.1.6
2020-10-21 04:28:55 -07:00
Kevin Hester
14c4022c18 1.1.6 (and screen layout tweaks) 2020-10-21 19:18:03 +08:00
Kevin Hester
a5d7bacdbf Show current region on the boot screen 2020-10-21 17:27:13 +08:00
Kevin Hester
0b3c25f6d9 use correct code for "talking to phone" fixes OTA update while a router 2020-10-21 16:50:09 +08:00
Kevin Hester
ad7a474a52 update buildscript to generate universal/regionless roms 2020-10-21 12:48:04 +08:00
Kevin Hester
430186ec53 Merge remote-tracking branch 'root/master' into dev 2020-10-21 10:44:56 +08:00
Jm Casler
227c6fc27e Merge pull request #494 from meshtastic/dev-https
Added the x-protobuf-schema, initial integration of javascript library, tuning of the CPU throttle timer.
2020-10-18 22:03:46 -07:00
Jm Casler
a37844d7e5 Merge pull request #493 from mc-hamster/master
update case of meshhttpStatic.h
2020-10-18 21:55:25 -07:00
Jm Casler
ff20b29c3c update case of meshhttpStatic.h 2020-10-18 21:44:55 -07:00
Jm Casler
64c29c4a35 Merge pull request #490 from mc-hamster/master
Update filename, cpu clock timer, add more debug info on the web server startup
2020-10-18 21:41:34 -07:00
Jm Casler
d4df3f8a7e mDNS server http://meshtastic.local 2020-10-18 21:39:02 -07:00
Jm Casler
a16c3af30a Clarified debug message regardding the Web Server startup status. 2020-10-18 18:44:08 -07:00
Jm Casler
3061860dab Update sleep timer for the CPU clock 2020-10-18 18:30:19 -07:00
Jm Casler
2450d98b59 Merge branch 'master' of https://github.com/mc-hamster/Meshtastic-device 2020-10-18 18:08:03 -07:00
Jm Casler
a371592ad9 Added instructions for David 2020-10-18 18:07:44 -07:00
Jm Casler
f7aaf48ae9 Merge pull request #20 from meshtastic/dev-https
Update my branch from dev-https
2020-10-18 18:04:49 -07:00
Jm Casler
1fb604ebc8 Merge pull request #488 from mc-hamster/master
Update dev-https from my fork.
2020-10-18 16:44:01 -07:00
Jm Casler
df2733a3b5 readded nodeScriptScriptsJS. it got lost in the transition to the new webserver 2020-10-17 20:28:19 -07:00
Kevin Hester
8fd3cb1aac add crude charging detection for 'dumb' voltage based battery sensors 2020-10-18 09:44:29 +08:00
Kevin Hester
485c476f17 cleaner battery debug messages 2020-10-18 09:32:12 +08:00
Jm Casler
7dd4ce32d2 Moved style.css into meshhttpStatic.h
Also created /data to store static files before they go into meshhttpStatic.h
2020-10-17 17:33:29 -07:00
Jm Casler
7f12af73d4 Updated to be host and protocol agnostic 2020-10-17 12:00:21 -07:00
Jm Casler
63113d57b3 Initial integration of meshtastic.js and sample code 2020-10-17 11:30:59 -07:00
Jm Casler
32850ff39d Merge pull request #487 from mc-hamster/master
Some cleanup and implement the X-Protobuf-Schema header
2020-10-16 23:40:48 -07:00
Jm Casler
2901f773a4 Some cleanup and implement the X-Protobuf-Schema header 2020-10-16 23:33:50 -07:00
Kevin Hester
a7c54e4ad7 Merge remote-tracking branch 'root/master' into dev 2020-10-17 13:41:51 +08:00
Kevin Hester
e1f0e11cb8 ppr1 WIP DO NOT MERGE - will break other clients 2020-10-17 13:15:12 +08:00
Kevin Hester
c73ee98739 Merge branch 'master' into ppr1 2020-10-17 11:00:28 +08:00
Jm Casler
c2a1141dfa Merge pull request #485 from mc-hamster/master
update class case of HttpAPI
2020-10-16 19:40:32 -07:00
Jm Casler
5b4472ab56 fix case of HttpAPI class 2020-10-16 19:38:59 -07:00
Jm Casler
3262f732d8 Merge pull request #19 from meshtastic/master
update my branch from master
2020-10-16 19:31:59 -07:00
Jm Casler
cff21ca130 Merge pull request #484 from meshtastic/dev-https
Functional protobuf/rest interface.
2020-10-16 19:28:40 -07:00
Jm Casler
81ce04d3da Merge branch 'master' into dev-https 2020-10-16 19:21:06 -07:00
Jm Casler
f4d2b10840 Merge pull request #483 from mc-hamster/master
Update for interface with the JS client.
2020-10-16 19:18:31 -07:00
Jm Casler
2370cb8aac Merge pull request #482 from meshtastic/dev-https
Merge from dev-https to master.
2020-10-16 19:10:04 -07:00
Kevin Hester
59ec87f5b0 oops tbeam was inheriting from arduino, it should inherit from esp32 2020-10-17 09:58:34 +08:00
Jm Casler
0d9481b6ea add allow-headers 2020-10-16 18:00:28 -07:00
Jm Casler
8f0105ccd9 don't send content-type when options is set 2020-10-16 17:46:22 -07:00
Kevin Hester
05ca3c3d56 Update to work with my font size change 2020-10-17 08:44:04 +08:00
Jm Casler
ba549d8fcd Return OPTIONS when requested for toradio 2020-10-16 17:41:08 -07:00
Jm Casler
b9df2c00fa fromradio all option
requesting fromradio will return one protobuf
4:56
requesting fromradio?all=true will give you all of them.
2020-10-16 17:07:35 -07:00
Kevin Hester
d9dcb33576 Merge branch 'master' into dev-https 2020-10-16 17:05:06 -07:00
Jm Casler
f698231be7 Merge branch 'master' of https://github.com/mc-hamster/Meshtastic-device 2020-10-16 16:36:55 -07:00
Jm Casler
8414f4a6a3 Added access-control-allow headers 2020-10-16 16:36:52 -07:00
Kevin Hester
8505020be5 Merge branch 'dev' into ppr1 2020-10-16 17:03:30 +08:00
Kevin Hester
f3b93d55fb oops fix for esp32 2020-10-16 17:03:04 +08:00
Kevin Hester
9e0731a956 Merge branch 'dev' into ppr1 2020-10-16 17:01:42 +08:00
Kevin Hester
2b373048c6 fix battery voltage sensing on NRF52 boards 2020-10-16 17:00:27 +08:00
Kevin Hester
22f23bb07d Merge branch 'dev' into ppr1
# Conflicts:
#	src/gps/NMEAGPS.cpp
2020-10-16 15:59:55 +08:00
Kevin Hester
b32e3f1269 Merge pull request #479 from geeksville/dev
minor eink things
2020-10-15 23:44:15 -07:00
Kevin Hester
68ddb712f5 properly keep nrf52s from sleeping 2020-10-16 14:00:56 +08:00
Kevin Hester
2fb5cd8c1c work with more NMEA gps sentences 2020-10-16 14:00:17 +08:00
Kevin Hester
79aea8231f make screen positions less hardwired wrt font size 2020-10-16 11:22:07 +08:00
Kevin Hester
b0837c10c6 eink display improvements 2020-10-16 10:53:55 +08:00
Jm Casler
cd811951b1 Merge pull request #481 from mc-hamster/master
Update from mchamster to dev-https
2020-10-15 19:53:03 -07:00
Jm Casler
df2976dad0 Merge pull request #18 from meshtastic/dev-https
From Dev https to mc-hamster master
2020-10-15 19:40:49 -07:00
Jm Casler
4ccbe6ff71 Merge pull request #480 from meshtastic/master
Updating dev-https from master
2020-10-15 19:40:01 -07:00
Jm Casler
038ddb887f Be a little smarter with setting the CPU frequency
in the event we have HTTPS and HTTP requests within close periods, let the speed set by the HTTPS request take presidence.
2020-10-15 19:28:20 -07:00
Kevin Hester
9134faaed1 turn off segger debug in ttgo eink build 2020-10-15 16:11:40 +08:00
Kevin Hester
649a120fe0 make eink screen look nicer 2020-10-15 15:56:38 +08:00
Kevin Hester
4db0c4a563 Make screen code resolution agnostic. Look better on big TFT/eink screens 2020-10-15 15:12:27 +08:00
Kevin Hester
5f2f3c94b9 PPR1 and allow boards to set lower or higher sx1262 power limits 2020-10-15 13:47:10 +08:00
Jm Casler
3b2f5fa5e3 fromRadio now returns all the vailable protobufs. a request to http sets the cpu clock to 160mhz, https to 240mhz then will clock it back down after 2 minutes. 2020-10-14 20:24:19 -07:00
Jm Casler
97adb598b6 toRadio is functional 2020-10-14 16:17:12 -07:00
Kevin Hester
152ebf0dff Merge branch 'dev' into ppr1 2020-10-14 10:24:39 +08:00
Kevin Hester
5b1511c930 ppr1 make jlink scripts 2020-10-14 10:21:55 +08:00
Kevin Hester
7ef2cc8623 Merge pull request #478 from geeksville/dev
1.1.5
2020-10-13 18:11:15 -07:00
Kevin Hester
b41a32c6b6 1.1.5 2020-10-14 09:04:20 +08:00
Kevin Hester
1ebd7b0c3e make lightsleep default time 5 minutes, with 1 minute in for BLE syncing 2020-10-14 08:53:12 +08:00
Kevin Hester
5457541244 fix #477: sleep behavior was broken in app due to device bug since 1.1.1
+        // NOTE: The phone app needs to know the ls_secs value so it can properly expect sleep behavior.
+        // So even if we internally use 0 to represent 'use default' we still need to send the value we are
+        // using to the app (so that even old phone apps work with new device loads).
2020-10-14 08:45:29 +08:00
Kevin Hester
ca77d48b20 corvus2 gps still doesn't work WIP 2020-10-13 14:43:28 +08:00
Kevin Hester
965c2bda8d corvus2 board builds 2020-10-13 13:59:06 +08:00
Jm Casler
02e3438d5e Added a favicon.ico 2020-10-11 22:13:14 -07:00
Jm Casler
02b1ece6ac Update meshhttp.cpp 2020-10-11 21:30:14 -07:00
Jm Casler
9fdef366f7 Merge pull request #473 from mc-hamster/master
update dev-https from my fork
2020-10-11 21:20:50 -07:00
Jm Casler
284816229e Merge pull request #17 from meshtastic/master
update my fork from head
2020-10-11 21:19:39 -07:00
Jm Casler
10008d4eef fix merge conflict 2020-10-11 21:19:22 -07:00
Jm Casler
58cfd1317c Merge branch 'master' of https://github.com/mc-hamster/Meshtastic-device 2020-10-11 20:38:13 -07:00
Jm Casler
3d3f7869d4 Increase CPU frequency on HTTPS requests. Clock back down after a period of time. 2020-10-11 20:38:09 -07:00
Kevin Hester
ef325289eb fix a doc error 2020-10-12 11:09:53 +08:00
Jm Casler
876d32c9ee Merge pull request #16 from geeksville/mc-master
fix build for linux (by moving esp32 specific lib to esp32 tree)
2020-10-11 18:17:20 -07:00
Kevin Hester
b9ce75b09c fix build for linux (by moving esp32 specific lib to esp32 tree) 2020-10-12 09:03:04 +08:00
Jm Casler
48e6a60a07 Merge pull request #470 from mc-hamster/master
Merge pull request #15 from meshtastic/master
2020-10-10 22:30:34 -07:00
Jm Casler
ca48079545 Merge pull request #15 from meshtastic/master
updated my branch from head
2020-10-10 22:29:09 -07:00
Jm Casler
76b4be3b87 Merge pull request #469 from mc-hamster/master
Switched to esp32_https_server from the Espressif (Issue #452) and Enable RX LNA (#466)
2020-10-10 22:28:08 -07:00
Jm Casler
d39cc3d57b Checking if ESP32 for the frequency display 2020-10-10 22:06:56 -07:00
Jm Casler
b17a8d7a6a Removed powerExit -- it wasn't working 2020-10-10 21:54:27 -07:00
Jm Casler
c16acb904e Merge branch 'master' of https://github.com/mc-hamster/Meshtastic-device 2020-10-10 17:59:46 -07:00
Jm Casler
5b777219be Enable the RX LNA #466
Enabling the RX LNA
2020-10-10 17:59:32 -07:00
Jm Casler
32ea11d2af Merge pull request #14 from meshtastic/master
Update from head
2020-10-10 17:23:13 -07:00
Jm Casler
db8faa9faf added powerExit 2020-10-09 23:07:37 -07:00
Jm Casler
6d178ebc91 Added esp32_https_server to the meshtastic project 2020-10-07 22:18:46 -07:00
Jm Casler
f75a256631 Merge branch 'master' of https://github.com/mc-hamster/Meshtastic-device 2020-10-07 22:02:59 -07:00
Jm Casler
4f659b7563 Initial check in of HTTPS server for #452
This switches from the espressif web server to esp32_https_server. Both HTTPS and HTTP have been migrated. On board SSL key generation.
2020-10-07 22:02:53 -07:00
Jm Casler
dffcea1f4d Merge pull request #13 from meshtastic/master
Update my fork from head with 1.1 changes
2020-10-07 08:32:54 -07:00
BeardyWalrus
b4b1b24c84 always need double press, even if you dont have a screen 2020-10-05 20:13:04 -04:00
BeardyWalrus
4d7cd0a09d conditional on needing ESP32 bluetooth header loaded 2020-10-03 17:23:36 -04:00
BeardyWalrus
fed8e80ae4 Merge branch 'master' into master 2020-10-03 17:04:47 -04:00
BeardyWalrus
b38bcffafb Merge branch 'master' of https://github.com/BeardyWalrus/Meshtastic-device 2020-10-03 17:02:19 -04:00
BeardyWalrus
530432411e revised fix for #357
Now supports default password for devices with no display, and override with double press of user button
2020-10-03 17:02:17 -04:00
BeardyWalrus
f30c84012f Merge branch 'master' into master 2020-10-01 22:24:30 -04:00
BeardyWalrus
5150d15997 Merge branch 'master' into master 2020-09-29 19:57:01 -04:00
BeardyWalrus
7d6dbcfa3f Update BluetoothUtil.cpp
fix for #357
use presence of ssd1306 display to set display functionality for bluetooth security.
2020-09-29 19:51:39 -04:00
BeardyWalrus
26bafb4082 Merge pull request #3 from meshtastic/master
Update from upstream
2020-09-27 19:23:26 -04:00
BeardyWalrus
0b1a78c028 Merge pull request #2 from meshtastic/master
Pull to live
2020-06-14 16:06:06 -04:00
BeardyWalrus
b8e1b28958 Merge pull request #1 from meshtastic/master
Resync with Upstream
2020-05-21 20:36:06 -04:00
73 changed files with 4747 additions and 925 deletions

View File

@@ -9,11 +9,10 @@ COUNTRIES="US EU433 EU865 CN JP ANZ KR"
#COUNTRIES=CN
BOARDS_ESP32="tlora-v2 tlora-v1 tlora-v2-1-1.6 tbeam heltec tbeam0.7"
# BOARDS_ESP32=tbeam
# FIXME note nrf52840dk build is for some reason only generating a BIN file but not a HEX file nrf52840dk-geeksville is fine
BOARDS_NRF52="lora-relay-v1"
BOARDS="$BOARDS_ESP32 $BOARDS_NRF52"
#BOARDS=tbeam
OUTDIR=release/latest
@@ -22,22 +21,61 @@ ARCHIVEDIR=release/archive
rm -f $OUTDIR/firmware*
mkdir -p $OUTDIR/bins $OUTDIR/elfs
rm -f $OUTDIR/bins/*
mkdir -p $OUTDIR/bins
rm -r $OUTDIR/bins/*
mkdir -p $OUTDIR/bins/universal $OUTDIR/elfs/universal
# build the named environment and copy the bins to the release directory
function do_build {
echo "Building for $BOARD with $PLATFORMIO_BUILD_FLAGS"
function do_build() {
BOARD=$1
COUNTRY=$2
isNrf=$3
echo "Building $COUNTRY for $BOARD with $PLATFORMIO_BUILD_FLAGS"
rm -f .pio/build/$BOARD/firmware.*
# The shell vars the build tool expects to find
export HW_VERSION="1.0-$COUNTRY"
export APP_VERSION=$VERSION
export COUNTRY
# Are we building a universal/regionless rom?
if [ "x$COUNTRY" != "x" ]
then
export HW_VERSION="1.0-$COUNTRY"
export COUNTRY
basename=firmware-$BOARD-$COUNTRY-$VERSION
else
export HW_VERSION="1.0"
unset COUNTRY
basename=universal/firmware-$BOARD-$VERSION
fi
pio run --jobs 4 --environment $BOARD # -v
SRCELF=.pio/build/$BOARD/firmware.elf
cp $SRCELF $OUTDIR/elfs/firmware-$BOARD-$COUNTRY-$VERSION.elf
cp $SRCELF $OUTDIR/elfs/$basename.elf
if [ "$isNrf" = "false" ]
then
echo "Copying ESP32 bin file"
SRCBIN=.pio/build/$BOARD/firmware.bin
cp $SRCBIN $OUTDIR/bins/$basename.bin
else
echo "Generating NRF52 uf2 file"
SRCHEX=.pio/build/$BOARD/firmware.hex
bin/uf2conv.py $SRCHEX -c -o $OUTDIR/bins/$basename.uf2 -f 0xADA52840
fi
}
function do_boards() {
declare boards=$1
declare isNrf=$2
for board in $boards; do
for country in $COUNTRIES; do
do_build $board $country "$isNrf"
done
# Build universal
do_build $board "" "$isNrf"
done
}
# Make sure our submodules are current
@@ -46,26 +84,16 @@ git submodule update
# Important to pull latest version of libs into all device flavors, otherwise some devices might be stale
platformio lib update
for COUNTRY in $COUNTRIES; do
for BOARD in $BOARDS; do
do_build $BOARD
done
echo "Copying ESP32 bin files"
for BOARD in $BOARDS_ESP32; do
SRCBIN=.pio/build/$BOARD/firmware.bin
cp $SRCBIN $OUTDIR/bins/firmware-$BOARD-$COUNTRY-$VERSION.bin
done
echo "Generating NRF52 uf2 files"
for BOARD in $BOARDS_NRF52; do
SRCHEX=.pio/build/$BOARD/firmware.hex
bin/uf2conv.py $SRCHEX -c -o $OUTDIR/bins/firmware-$BOARD-$COUNTRY-$VERSION.uf2 -f 0xADA52840
done
done
do_boards "$BOARDS_ESP32" "false"
do_boards "$BOARDS_NRF52" "true"
# keep the bins in archive also
cp $OUTDIR/bins/firmware* $OUTDIR/elfs/firmware* $ARCHIVEDIR
cp $OUTDIR/bins/firmware* $OUTDIR/elfs/firmware* $OUTDIR/bins/universal/firmware* $OUTDIR/elfs/universal/firmware* $ARCHIVEDIR
echo Updating android bins $OUTDIR/forandroid
rm -rf $OUTDIR/forandroid
mkdir -p $OUTDIR/forandroid
cp -a $OUTDIR/bins/universal/*.bin $OUTDIR/forandroid/
cat >$OUTDIR/curfirmwareversion.xml <<XML
<?xml version="1.0" encoding="utf-8"?>
@@ -79,6 +107,7 @@ Generated by bin/buildall.sh -->
</resources>
XML
echo Generating $ARCHIVEDIR/firmware-$VERSION.zip
rm -f $ARCHIVEDIR/firmware-$VERSION.zip
zip --junk-paths $ARCHIVEDIR/firmware-$VERSION.zip $OUTDIR/bins/firmware-*-$VERSION.* images/system-info.bin bin/device-install.sh bin/device-update.sh

View File

@@ -2,7 +2,20 @@
set -e
# dependencies
# apt install srecord
BOOTDIR=/home/kevinh/development/meshtastic/Adafruit_nRF52_Bootloader
BOARD=othernet_ppr1
BOOTVER=0.3.2
BOOTNUM=128
BOOTSHA=gc01b9ea
SDCODE=s113
SDVER=7.2.0
PROJ=ppr1
# FIXME for nRF52840 use 0xff000, for nRF52833 use 0x7f000
BOOTSET=0x7f000
nrfjprog --eraseall -f nrf52
@@ -11,12 +24,12 @@ nrfjprog --eraseall -f nrf52
# first 4 bytes should be 0x01 to indicate valid app image
# second 4 bytes should be 0x00 to indicate no CRC required for image
echo "01 00 00 00 00 00 00 00" | xxd -r -p - >/tmp/bootconf.bin
srec_cat /tmp/bootconf.bin -binary -offset 0xff000 -output /tmp/bootconf.hex -intel
srec_cat /tmp/bootconf.bin -binary -offset $BOOTSET -output /tmp/bootconf.hex -intel
echo Generating merged hex file
mergehex -m $BOOTDIR/_build/build-ttgo_eink/ttgo_eink_bootloader-0.3.2-124-g69bd8eb-dirty_s140_6.1.1.hex .pio/build/eink/firmware.hex /tmp/bootconf.hex -o ttgo_eink_full.hex
echo Generating merged hex file from .pio/build/$PROJ/firmware.hex
mergehex -o ${BOARD}_full.hex -m $BOOTDIR/_build/build-$BOARD/${BOARD}_bootloader-$BOOTVER-$BOOTNUM-$BOOTSHA-dirty_${SDCODE}_$SDVER.hex .pio/build/$PROJ/firmware.hex /tmp/bootconf.hex
echo Telling bootloader app region is valid and telling CPU to run
nrfjprog --program ttgo_eink_full.hex -f nrf52 --reset
nrfjprog --program ${BOARD}_full.hex -f nrf52 --reset
# nrfjprog --readuicr /tmp/uicr.hex; objdump -s /tmp/uicr.hex | less

22
bin/install-eink.sh Executable file
View File

@@ -0,0 +1,22 @@
# You probably don't want to use this script, it programs a custom bootloader build onto a nrf52 board
set -e
BOOTDIR=/home/kevinh/development/meshtastic/Adafruit_nRF52_Bootloader
nrfjprog --eraseall -f nrf52
# this generates an intel hex file that can be programmed into a NRF52 to tell the adafruit bootloader that the current app image is valid
# Bootloader settings are at BOOTLOADER_SETTINGS (rw) : ORIGIN = 0xFF000, LENGTH = 0x1000
# first 4 bytes should be 0x01 to indicate valid app image
# second 4 bytes should be 0x00 to indicate no CRC required for image
echo "01 00 00 00 00 00 00 00" | xxd -r -p - >/tmp/bootconf.bin
srec_cat /tmp/bootconf.bin -binary -offset 0xff000 -output /tmp/bootconf.hex -intel
echo Generating merged hex file
mergehex -m $BOOTDIR/_build/build-ttgo_eink/ttgo_eink_bootloader-0.3.2-125-gf38f8f4-dirty_s140_6.1.1.hex .pio/build/eink/firmware.hex /tmp/bootconf.hex -o ttgo_eink_full.hex
echo Telling bootloader app region is valid and telling CPU to run
nrfjprog --program ttgo_eink_full.hex -f nrf52 --reset
# nrfjprog --readuicr /tmp/uicr.hex; objdump -s /tmp/uicr.hex | less

View File

@@ -1,3 +1,3 @@
JLinkGDBServerCLExe -if SWD -select USB -port 2331 -device NRF52840_XXAA
JLinkGDBServerCLExe -if SWD -select USB -port 2331 -device NRF52832_XXAA

3
bin/nrf52833-gdbserver.sh Executable file
View File

@@ -0,0 +1,3 @@
JLinkGDBServerCLExe -if SWD -select USB -port 2331 -device NRF52833_XXAA

View File

@@ -1,3 +1,3 @@
JLinkGDBServerCLExe -if SWD -select USB -port 2331 -device NRF52832_XXAA
JLinkGDBServerCLExe -if SWD -select USB -port 2331 -device NRF52840_XXAA

View File

@@ -1,4 +1,4 @@
echo "Converting to uf2 for NRF52 Adafruit bootloader"
bin/uf2conv.py .pio/build/lora-relay-v1/firmware.hex -f 0xADA52840
bin/uf2conv.py .pio/build/lora-relay-v2/firmware.hex -f 0xADA52840
# cp flash.uf2 /media/kevinh/FTH*BOOT/

View File

@@ -1,3 +1,3 @@
export VERSION=1.1.4
export VERSION=1.1.8

2
bin/view-map.sh Executable file
View File

@@ -0,0 +1,2 @@
echo using amap tool to display memory map
amap .pio/build/output.map

View File

@@ -5,7 +5,7 @@
},
"core": "nRF5",
"cpu": "cortex-m4",
"extra_flags": "-DARDUINO_NRF52840_LORA_RELAY_V1 -DNRF52840_XXAA",
"extra_flags": "-DARDUINO_NRF52840_TTGO_EINK -DNRF52840_XXAA",
"f_cpu": "64000000L",
"hwids": [
[

46
boards/lora-relay-v2.json Normal file
View File

@@ -0,0 +1,46 @@
{
"build": {
"arduino": {
"ldscript": "nrf52840_s140_v6.ld"
},
"core": "nRF5",
"cpu": "cortex-m4",
"extra_flags": "-DARDUINO_NRF52840_LORA_RELAY_V2 -DNRF52840_XXAA",
"f_cpu": "64000000L",
"hwids": [["0x239A", "0x4406"]],
"usb_product": "LORA_RELAY",
"mcu": "nrf52840",
"variant": "lora_relay_v2",
"variants_dir": "variants",
"bsp": {
"name": "adafruit"
},
"softdevice": {
"sd_flags": "-DS140",
"sd_name": "s140",
"sd_version": "6.1.1",
"sd_fwid": "0x00B6"
},
"bootloader": {
"settings_addr": "0xFF000"
}
},
"connectivity": ["bluetooth"],
"debug": {
"jlink_device": "nRF52840_xxAA",
"onboard_tools": ["jlink"],
"svd_path": "nrf52840.svd"
},
"frameworks": ["arduino"],
"name": "Meshtastic Lora Relay V1 (Adafruit BSP)",
"upload": {
"maximum_ram_size": 248832,
"maximum_size": 815104,
"require_upload_port": true,
"speed": 115200,
"protocol": "jlink",
"protocols": ["jlink", "nrfjprog", "stlink"]
},
"url": "https://github.com/BigCorvus/SX1262-LoRa-BLE-Relay",
"vendor": "BigCorvus"
}

View File

@@ -1,7 +1,7 @@
{
"build": {
"arduino": {
"ldscript": "nrf52840_s140_v6.ld"
"ldscript": "nrf52840_s113_v7.ld"
},
"core": "nRF5",
"cpu": "cortex-m4",
@@ -16,9 +16,9 @@
"name": "adafruit"
},
"softdevice": {
"sd_flags": "-DS140",
"sd_name": "s140",
"sd_version": "6.1.1",
"sd_flags": "-DS113",
"sd_name": "s113",
"sd_version": "7.2.0",
"sd_fwid": "0x00B6"
},
"bootloader": {

46
boards/ppr1.json Normal file
View File

@@ -0,0 +1,46 @@
{
"build": {
"arduino": {
"ldscript": "nrf52833_s113_v7.ld"
},
"core": "nRF5",
"cpu": "cortex-m4",
"extra_flags": "-DARDUINO_NRF52833_PPR -DNRF52833_XXAA",
"f_cpu": "64000000L",
"hwids": [["0x239A", "0x4406"]],
"usb_product": "PPR",
"mcu": "nrf52833",
"variant": "ppr",
"variants_dir": "variants",
"bsp": {
"name": "adafruit"
},
"softdevice": {
"sd_flags": "-DS113",
"sd_name": "s113",
"sd_version": "7.2.0",
"sd_fwid": "0x00b6"
},
"bootloader": {
"settings_addr": "0xFF000"
}
},
"connectivity": ["bluetooth"],
"debug": {
"jlink_device": "nRF52833_xxAA",
"onboard_tools": ["jlink"],
"svd_path": "nrf52833.svd"
},
"frameworks": ["arduino"],
"name": "Meshtastic PPR1 (Adafruit BSP)",
"upload": {
"maximum_ram_size": 248832,
"maximum_size": 815104,
"require_upload_port": true,
"speed": 115200,
"protocol": "jlink",
"protocols": ["jlink", "nrfjprog", "stlink"]
},
"url": "https://meshtastic.org/",
"vendor": "Othernet"
}

277
data/style.css Normal file
View File

@@ -0,0 +1,277 @@
/* latin-ext */
@font-face {
font-family: 'Lato';
font-style: normal;
font-weight: 400;
src: local('Lato Regular'), local('Lato-Regular'), url(./Google.woff2) format('woff2');
unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
*, *:before, *:after {
box-sizing: border-box;
}
body {
background: #C5DDEB;
font: 14px/20px "Lato", Arial, sans-serif;
padding: 40px 0;
color: white;
}
.grid {
display: grid;
grid-template-columns:
1fr 4fr;
grid-template-areas:
"header header"
"sidebar content";
margin: 0 auto;
width: 750px;
background: #444753;
border-radius: 5px;
}
.top {grid-area: header;}
.side {grid-area: sidebar;}
.main {grid-area: content;}
.top {
border-bottom: 2px solid white;
}
.top-text {
font-weight: bold;
font-size: 24px;
text-align: center;
padding: 20px;
}
.side {
width: 260px;
float: left;
}
.side .side-header {
padding: 20px;
border-bottom: 2px solid white;
}
.side .side-header .side-text {
padding-left: 10px;
margin-top: 6px;
font-size: 16px;
text-align: left;
font-weight: bold;
}
.channel-list ul {
padding: 20px;
height: 570px;
list-style-type: none;
}
.channel-list ul li {
padding-bottom: 20px;
}
.channel-list .channel-name {
font-size: 20px;
margin-top: 8px;
padding-left: 8px;
}
.channel-list .message-count {
padding-left: 16px;
color: #92959E;
}
.icon {
display: inline-block;
width: 1em;
height: 1em;
stroke-width: 0;
stroke: currentColor;
fill: currentColor;
}
.icon-map-marker {
width: 0.5714285714285714em;
}
.icon-circle {
width: 0.8571428571428571em;
}
.content {
display: flex;
flex-direction: column;
flex-wrap: nowrap;
/* width: 490px; */
float: left;
background: #F2F5F8;
/* border-top-right-radius: 5px;
border-bottom-right-radius: 5px; */
color: #434651;
}
.content .content-header {
flex-grow: 0;
padding: 20px;
border-bottom: 2px solid white;
}
.content .content-header .content-from {
padding-left: 10px;
margin-top: 6px;
font-size: 20px;
text-align: center;
font-size: 16px;
}
.content .content-header .content-from .content-from-highlight {
font-weight: bold;
}
.content .content-header .content-num-messages {
color: #92959E;
}
.content .content-history {
flex-grow: 1;
padding: 20px 20px 20px;
border-bottom: 2px solid white;
overflow-y: scroll;
height: 375px;
}
.content .content-history ul {
list-style-type: none;
padding-inline-start: 10px;
}
.content .content-history .message-data {
margin-bottom: 10px;
}
.content .content-history .message-data-time {
color: #a8aab1;
padding-left: 6px;
}
.content .content-history .message {
color: white;
padding: 8px 10px;
line-height: 20px;
font-size: 14px;
border-radius: 7px;
margin-bottom: 30px;
width: 90%;
position: relative;
}
.content .content-history .message:after {
bottom: 100%;
left: 7%;
border: solid transparent;
content: " ";
height: 0;
width: 0;
position: absolute;
pointer-events: none;
border-bottom-color: #86BB71;
border-width: 10px;
margin-left: -10px;
}
.content .content-history .my-message {
background: #86BB71;
}
.content .content-history .other-message {
background: #94C2ED;
}
.content .content-history .other-message:after {
border-bottom-color: #94C2ED;
left: 93%;
}
.content .content-message {
flex-grow: 0;
padding: 10px;
}
.content .content-message textarea {
width: 100%;
border: none;
padding: 10px 10px;
font: 14px/22px "Lato", Arial, sans-serif;
margin-bottom: 10px;
border-radius: 5px;
resize: none;
}
.content .content-message button {
float: right;
color: #94C2ED;
font-size: 16px;
text-transform: uppercase;
border: none;
cursor: pointer;
font-weight: bold;
background: #F2F5F8;
}
.content .content-message button:hover {
color: #75b1e8;
}
/* Tooltip container */
.tooltip {
color: #86BB71;
position: relative;
display: inline-block;
border-bottom: 1px dotted black; /* If you want dots under the hoverable text */
}
/* Tooltip text */
.tooltip .tooltiptext {
visibility: hidden;
width: 120px;
background-color: #444753;
color: #fff;
text-align: center;
padding: 5px 0;
border-radius: 6px;
/* Position the tooltip text - see examples below! */
position: absolute;
z-index: 1;
}
/* Show the tooltip text when you mouse over the tooltip container */
.tooltip:hover .tooltiptext {
visibility: visible;
}
.online, .offline, .me {
margin-right: 3px;
font-size: 10px;
}
.online {
color: #86BB71;
}
.offline {
color: #E38968;
}
.me {
color: #94C2ED;
}
.align-left {
text-align: left;
}
.align-right {
text-align: right;
}
.float-right {
float: right;
}
.clearfix:after {
visibility: hidden;
display: block;
font-size: 0;
content: " ";
clear: both;
height: 0;
}

BIN
data/style.css.gz Normal file

Binary file not shown.

Binary file not shown.

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 272 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 417 KiB

View File

@@ -2,15 +2,11 @@
You probably don't care about this section - skip to the next one.
Threading tasks:
For high speed/lots of devices/short range tasks:
- Use https://github.com/ivanseidel/ArduinoThread? rather than full coroutines
- clean up main loop()
- check that we are mostly asleep, show which thread is causing us to wake
-
- use tickless idle on nrf52, and sleep X msec or until an interrupt occurs or the cooperative scheduling changes. https://devzone.nordicsemi.com/f/nordic-q-a/12363/nrf52-freertos-power-consumption-tickless-idle
- BAD IDEA: use vTaskDelay and https://www.freertos.org/xTaskAbortDelay.html if scheduling changes. (define INCLUDE_xTaskAbortDelay on ESP32 and NRF52 - seems impossible to find?)
- GOOD IDEA: use xSemaphoreTake to take a semaphore using a timeout. Expect semaphore to not be set, but set it to indicate scheduling has changed.
- When guessing numhops for sending: if I've heard from many local (0 hop neighbors) decrease hopcount by 2 rather than 1.
This should nicely help 'router' nodes do the right thing when long range, or if there are many local nodes for short range.
- fix timeouts/delays to be based on packet length at current radio settings
Nimble tasks:

View File

@@ -42,7 +42,6 @@ Expected sequence for initial download:
- Read a RadioConfig from "radio" - used to get the channel and radio settings
- Read a User from "user" - to get the username for this node
- Read a MyNodeInfo from "mynode" to get information about this local device
- Write an empty record to "nodeinfo" to restart the nodeinfo reading state machine
- Read a series of NodeInfo packets to build the phone's copy of the current NodeDB for the mesh
- Read a endConfig packet that indicates that the entire state you need has been sent.
- Read a series of MeshPackets until it returns empty to get any messages that arrived for this node while the phone was away

View File

@@ -5,7 +5,27 @@
## RAK815
TODO:
### PPR1 TODO
* V_BK for the GPS should probably be supplied from something always on
* use S113 soft device 7.2.0
* properly test charge controller config and read battery/charge status
* fix bluetooth
* fix LCD max contrast (currently too high, needs to be about 40?)
* save brightness settings in flash
* make ST7567Wire driver less ugly, move OLED stuff into a common class treee
* add LCD power save mode for lcd per page 31 of datasheet
* add LCD power off sequence per datasheet to lcd driver
* leave LCD screen on most of the time (because it needs little power)
### general nrf52 TODO:
- turn off transitions on eink screens
- change update interval on eink from 1/sec frames to one frame every 5 mins
- enter SDS state at correct time (to protect battery or loss of phone contact)
- show screen on eink when we enter SDS state (with app info and say sleeping)
- require button press to pair
- shrink soft device RAM usage
- get nrf52832 working again (currently OOM)

View File

@@ -2,18 +2,25 @@
These are **preliminary** notes on support for Meshtastic in the Pinetab.
A RF95 is connected via a CS341 USB-SPI chip.
A RF95 is connected via a CH341 USB-SPI chip.
Pin assignments:
CS0 from RF95 goes to CS0 on CS341
DIO0 from RF95 goes to INT on CS341
RST from RF95 goes to RST on CS341
CS0 from RF95 goes to CS0 on CH341
DIO0 from RF95 goes to INT on CH341
RST from RF95 goes to RST on CH341
This linux driver claims to provide USB-SPI support: https://github.com/gschorcht/spi-ch341-usb
Notes here on using that driver: https://www.linuxquestions.org/questions/linux-hardware-18/ch341-usb-to-spi-adaptor-driver-doesn%27t-work-4175622736/
Or if **absolutely** necessary could bitbang: https://www.cnx-software.com/2018/02/16/wch-ch341-usb-to-serial-chip-gets-linux-driver-to-control-gpios-over-usb/
## Portduino tasks
* How to access spi devices via ioctl (spidev): https://www.raspberrypi.org/documentation/hardware/raspberrypi/spi/README.md#:~:text=Troubleshooting-,Overview,bus)%2C%20UARTs%2C%20etc.
* access gpio via libgpiod?
* Use dkms to distribute driver?
* echo 100 > /sys/module/spi_ch341_usb/parameters/poll_period
## Task list
* Port meshtastic to build (under platformio) for a poxix target. spec: no screen, no gpios, sim network interface, posix threads, posix semaphores & queues, IO to the console only

View File

@@ -36,7 +36,6 @@ build_flags = -Wno-missing-field-initializers -Isrc -Isrc/mesh -Isrc/gps -Ilib/n
;upload_port = /dev/ttyUSB0
;monitor_port = /dev/ttyUSB0
; geeksville: I think setting this should not be required - it breaks linux
;upload_port = /dev/cu.SLAB_USBtoUART
;monitor_port = /dev/cu.SLAB_USBtoUART
@@ -95,6 +94,9 @@ build_flags =
${arduino_base.build_flags} -Wall -Wextra -Isrc/esp32 -Isrc/esp32-mfix-esp32-psram-cache-issue -lnimble -std=c++11
-DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG -DCORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_DEBUG
-DAXP_DEBUG_PORT=Serial
lib_deps =
${arduino_base.lib_deps}
https://github.com/meshtastic/esp32_https_server.git
# Hmm - this doesn't work yet
# board_build.ldscript = linker/esp32.extram.bss.ld
lib_ignore = segger_rtt
@@ -117,7 +119,7 @@ board_build.partitions = partition-table.csv
extends = esp32_base
board = ttgo-t-beam
lib_deps =
${arduino_base.lib_deps}
${esp32_base.lib_deps}
build_flags =
${esp32_base.build_flags} -D TBEAM_V10
@@ -234,6 +236,15 @@ lib_deps =
${arduino_base.lib_deps}
UC1701
; The PPR board
[env:ppr1]
extends = nrf52_base
board = ppr1
build_flags = ${nrf52_base.build_flags} -Ivariants/ppr1
src_filter = ${nrf52_base.src_filter} +<../variants/ppr1>
lib_deps =
${arduino_base.lib_deps}
; Prototype eink/nrf52840/sx1262 device
[env:eink]
extends = nrf52_base
@@ -269,7 +280,30 @@ lib_deps =
${arduino_base.lib_deps}
SparkFun BQ27441 LiPo Fuel Gauge Arduino Library
TFT_eSPI
# Adafruit ST7735 and ST7789 Library
; The https://github.com/BigCorvus/LoRa-BLE-Relay-v2 board by @BigCorvus
[env:lora-relay-v2]
extends = nrf52_base
board = lora-relay-v2
# add our variants files to the include and src paths
# define build flags for the TFT_eSPI library
build_flags = ${nrf52_base.build_flags} -Ivariants/lora_relay_v2
-DUSER_SETUP_LOADED
-DTFT_WIDTH=80
-DTFT_HEIGHT=160
-DST7735_GREENTAB160x80
-DST7735_DRIVER
-DTFT_CS=ST7735_CS
-DTFT_DC=ST7735_RS
-DTFT_RST=ST7735_RESET
-DSPI_FREQUENCY=27000000
-DTFT_WR=ST7735_SDA
-DTFT_SCLK=ST7735_SCK
src_filter = ${nrf52_base.src_filter} +<../variants/lora_relay_v2>
lib_deps =
${arduino_base.lib_deps}
SparkFun BQ27441 LiPo Fuel Gauge Arduino Library
TFT_eSPI
; The Portduino based sim environment on top of linux
[env:linux]

View File

@@ -18,6 +18,21 @@ Power *power;
using namespace meshtastic;
#if defined(NRF52_SERIES)
/*
* Internal Reference is +/-0.6V, with an adjustable gain of 1/6, 1/5, 1/4,
* 1/3, 1/2 or 1, meaning 3.6, 3.0, 2.4, 1.8, 1.2 or 0.6V for the ADC levels.
*
* External Reference is VDD/4, with an adjustable gain of 1, 2 or 4, meaning
* VDD/4, VDD/2 or VDD for the ADC levels.
*
* Default settings are internal reference with 1/6 gain (GND..3.6V ADC range)
*/
#define AREF_VOLTAGE 3.6
#else
#define AREF_VOLTAGE 3.3
#endif
/**
* If this board has a battery level sensor, set this to a valid implementation
*/
@@ -37,10 +52,13 @@ class AnalogBatteryLevel : public HasBatteryLevel
{
float v = getBattVoltage() / 1000;
if (v < 2.1)
if (v < noBatVolt)
return -1; // If voltage is super low assume no battery installed
return 100 * (v - 3.27) / (4.2 - 3.27);
if (v > chargingVolt)
return 0; // While charging we can't report % full on the battery
return 100 * (v - emptyVolt) / (fullVolt - emptyVolt);
}
/**
@@ -48,9 +66,11 @@ class AnalogBatteryLevel : public HasBatteryLevel
*/
virtual float getBattVoltage()
{
// Tested ttgo eink nrf52 board and the reported value is perfect
// DEBUG_MSG("raw val %u", raw);
return
#ifdef BATTERY_PIN
1000.0 * analogRead(BATTERY_PIN) * 2.0 * (3.3 / 1024.0);
1000.0 * 2.0 * (AREF_VOLTAGE / 1024.0) * analogRead(BATTERY_PIN);
#else
NAN;
#endif
@@ -59,7 +79,20 @@ class AnalogBatteryLevel : public HasBatteryLevel
/**
* return true if there is a battery installed in this unit
*/
virtual bool isBatteryConnect() { return getBattVoltage() != -1; }
virtual bool isBatteryConnect() { return getBattPercentage() != -1; }
/// If we see a battery voltage higher than physics allows - assume charger is pumping
/// in power
virtual bool isVBUSPlug() { return getBattVoltage() > chargingVolt; }
/// Assume charging if we have a battery and external power is connected.
/// we can't be smart enough to say 'full'?
virtual bool isChargeing() { return isBatteryConnect() && isVBUSPlug(); }
private:
/// If we see a battery voltage higher than physics allows - assume charger is pumping
/// in power
const float fullVolt = 4.2, emptyVolt = 3.27, chargingVolt = 4.3, noBatVolt = 2.1;
} analogLevel;
Power::Power() : OSThread("Power") {}
@@ -68,10 +101,18 @@ bool Power::analogInit()
{
#ifdef BATTERY_PIN
DEBUG_MSG("Using analog input for battery level\n");
// disable any internal pullups
pinMode(BATTERY_PIN, INPUT);
#ifndef NO_ESP32
// ESP32 needs special analog stuff
adcAttachPin(BATTERY_PIN);
#endif
#ifdef NRF52_SERIES
analogReference(AR_INTERNAL); // 3.6V
#endif
// adcStart(BATTERY_PIN);
analogReadResolution(10); // Default of 12 is not very linear. Recommended to use 10 or 11 depending on needed resolution.
batteryLevel = &analogLevel;
@@ -121,7 +162,8 @@ void Power::readPowerStatus()
const PowerStatus powerStatus =
PowerStatus(hasBattery ? OptTrue : OptFalse, batteryLevel->isVBUSPlug() ? OptTrue : OptFalse,
batteryLevel->isChargeing() ? OptTrue : OptFalse, batteryVoltageMv, batteryChargePercent);
DEBUG_MSG("Read power stat %d\n", powerStatus.getHasUSB());
DEBUG_MSG("Battery: usbPower=%d, isCharging=%d, batMv=%d, batPct=%d\n", powerStatus.getHasUSB(),
powerStatus.getIsCharging(), powerStatus.getBatteryVoltageMv(), powerStatus.getBatteryChargePercent());
newStatus.notifyObservers(&powerStatus);
// If we have a battery at all and it is less than 10% full, force deep sleep

View File

@@ -149,6 +149,7 @@ static void onEnter()
service.sendNetworkPing(displayedNodeNum, true); // Refresh the currently displayed node
lastPingMs = now;
}
}
static void screenPress()
@@ -244,20 +245,24 @@ void PowerFSM_setup()
powerFSM.add_timed_transition(&stateON, &stateDARK, getPref_screen_on_secs() * 1000, NULL, "Screen-on timeout");
powerFSM.add_timed_transition(&stateDARK, &stateNB, getPref_phone_timeout_secs() * 1000, NULL, "Phone timeout");
// On most boards we use light-sleep to be our main state, but on NRF52 we just stay in DARK
State *lowPowerState = &stateLS;
#ifndef NRF52_SERIES
// We never enter light-sleep state on NRF52 (because the CPU uses so little power normally)
powerFSM.add_timed_transition(&stateNB, &stateLS, getPref_min_wake_secs() * 1000, NULL, "Min wake timeout");
// We never enter light-sleep or NB states on NRF52 (because the CPU uses so little power normally)
powerFSM.add_timed_transition(&stateDARK, &stateNB, getPref_phone_timeout_secs() * 1000, NULL, "Phone timeout");
powerFSM.add_timed_transition(&stateNB, &stateLS, getPref_min_wake_secs() * 1000, NULL, "Min wake timeout");
powerFSM.add_timed_transition(&stateDARK, &stateLS, getPref_wait_bluetooth_secs() * 1000, NULL, "Bluetooth timeout");
#else
lowPowerState = &stateDARK;
#endif
auto meshSds = getPref_mesh_sds_timeout_secs();
if (meshSds != UINT32_MAX)
powerFSM.add_timed_transition(&stateLS, &stateSDS, meshSds * 1000, NULL, "mesh timeout");
powerFSM.add_timed_transition(lowPowerState, &stateSDS, meshSds * 1000, NULL, "mesh timeout");
// removing for now, because some users don't even have phones
// powerFSM.add_timed_transition(&stateLS, &stateSDS, getPref_phone_sds_timeout_sec() * 1000, NULL, "phone
// powerFSM.add_timed_transition(lowPowerState, &stateSDS, getPref_phone_sds_timeout_sec() * 1000, NULL, "phone
// timeout");
powerFSM.run_machine(); // run one interation of the state machine, so we run our on enter tasks for the initial DARK state

View File

@@ -82,7 +82,7 @@ class PowerStatus : public Status
isCharging = newStatus->isCharging;
}
if (isDirty) {
DEBUG_MSG("Battery %dmV %d%%\n", batteryVoltageMv, batteryChargePercent);
// DEBUG_MSG("Battery %dmV %d%%\n", batteryVoltageMv, batteryChargePercent);
onNewStatus.notifyObservers(this);
}
return 0;

View File

@@ -139,6 +139,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
// -----------------------------------------------------------------------------
#define SSD1306_ADDRESS 0x3C
#define ST7567_ADDRESS 0x3F
// The SH1106 controller is almost, but not quite, the same as SSD1306
// Define this if you know you have that controller or your "SSD1306" misbehaves.
@@ -146,7 +147,10 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
// Flip the screen upside down by default as it makes more sense on T-BEAM
// devices. Comment this out to not rotate screen 180 degrees.
#define FLIP_SCREEN_VERTICALLY
#define SCREEN_FLIP_VERTICALLY
// Define if screen should be mirrored left to right
// #define SCREEN_MIRROR
// -----------------------------------------------------------------------------
// GPS
@@ -430,3 +434,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define GPS_POWER_CTRL_CH 3
#define LORA_POWER_CTRL_CH 2
// Default Bluetooth PIN
#define defaultBLEPin 123456

View File

@@ -72,7 +72,7 @@ int update_data_callback(uint16_t conn_handle, uint16_t attr_handle, struct ble_
crc.update(data, len);
Update.write(data, len);
updateActualSize += len;
powerFSM.trigger(EVENT_RECEIVED_TEXT_MSG); // Not exactly correct, but we want to force the device to not sleep now
powerFSM.trigger(EVENT_CONTACT_FROM_PHONE);
return 0;
}

View File

@@ -9,6 +9,7 @@
#include "utils.h"
#include <nvs.h>
#include <nvs_flash.h>
#include <driver/rtc_io.h>
void getMacAddr(uint8_t *dmac)
{
@@ -86,4 +87,58 @@ void esp32Loop()
// for debug printing
// radio.radioIf.canSleep();
}
void cpuDeepSleep(uint64_t msecToWake)
{
/*
Some ESP32 IOs have internal pullups or pulldowns, which are enabled by default.
If an external circuit drives this pin in deep sleep mode, current consumption may
increase due to current flowing through these pullups and pulldowns.
To isolate a pin, preventing extra current draw, call rtc_gpio_isolate() function.
For example, on ESP32-WROVER module, GPIO12 is pulled up externally.
GPIO12 also has an internal pulldown in the ESP32 chip. This means that in deep sleep,
some current will flow through these external and internal resistors, increasing deep
sleep current above the minimal possible value.
Note: we don't isolate pins that are used for the LORA, LED, i2c, spi or the wake button
*/
static const uint8_t rtcGpios[] = {/* 0, */ 2,
/* 4, */
#ifndef USE_JTAG
13,
/* 14, */ /* 15, */
#endif
/* 25, */ 26, /* 27, */
32, 33, 34, 35,
36, 37
/* 38, 39 */};
for (int i = 0; i < sizeof(rtcGpios); i++)
rtc_gpio_isolate((gpio_num_t)rtcGpios[i]);
// FIXME, disable internal rtc pullups/pulldowns on the non isolated pins. for inputs that we aren't using
// to detect wake and in normal operation the external part drives them hard.
// We want RTC peripherals to stay on
esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON);
#ifdef BUTTON_PIN
// Only GPIOs which are have RTC functionality can be used in this bit map: 0,2,4,12-15,25-27,32-39.
uint64_t gpioMask = (1ULL << BUTTON_PIN);
#ifdef BUTTON_NEED_PULLUP
gpio_pullup_en((gpio_num_t)BUTTON_PIN);
#endif
// Not needed because both of the current boards have external pullups
// FIXME change polarity in hw so we can wake on ANY_HIGH instead - that would allow us to use all three buttons (instead of
// just the first) gpio_pullup_en((gpio_num_t)BUTTON_PIN);
esp_sleep_enable_ext1_wakeup(gpioMask, ESP_EXT1_WAKEUP_ALL_LOW);
#endif
esp_sleep_enable_timer_wakeup(msecToWake * 1000ULL); // call expects usecs
esp_deep_sleep_start(); // TBD mA sleep current (battery)
}

View File

@@ -65,9 +65,8 @@ void Air530GPS::sendCommand(const char *cmd) {
}
void Air530GPS::sleep() {
NMEAGPS::sleep();
#ifdef PIN_GPS_WAKE
digitalWrite(PIN_GPS_WAKE, 0);
pinMode(PIN_GPS_WAKE, OUTPUT);
sendCommand("$PGKC105,4");
#endif
}
@@ -76,10 +75,7 @@ void Air530GPS::sleep() {
void Air530GPS::wake()
{
#if 1
#ifdef PIN_GPS_WAKE
digitalWrite(PIN_GPS_WAKE, 1);
pinMode(PIN_GPS_WAKE, OUTPUT);
#endif
NMEAGPS::wake();
#else
// For power testing - keep GPS sleeping forever
sleep();

View File

@@ -10,7 +10,7 @@
#ifdef GPS_RX_PIN
HardwareSerial _serial_gps_real(GPS_SERIAL_NUM);
HardwareSerial *GPS::_serial_gps = &_serial_gps_real;
#elif defined(NRF52840_XXAA)
#elif defined(NRF52840_XXAA) || defined(NRF52833_XXAA)
// Assume NRF52840
HardwareSerial *GPS::_serial_gps = &Serial1;
#else
@@ -25,17 +25,75 @@ uint8_t GPS::i2cAddress = 0;
GPS *gps;
/// Multiple GPS instances might use the same serial port (in sequence), but we can
/// only init that port once.
static bool didSerialInit;
bool GPS::setupGPS()
{
if (_serial_gps && !didSerialInit) {
didSerialInit = true;
#ifdef GPS_RX_PIN
_serial_gps->begin(GPS_BAUDRATE, SERIAL_8N1, GPS_RX_PIN, GPS_TX_PIN);
#else
_serial_gps->begin(GPS_BAUDRATE);
#endif
#ifndef NO_ESP32
_serial_gps->setRxBufferSize(2048); // the default is 256
#endif
}
return true;
}
bool GPS::setup()
{
// Master power for the GPS
#ifdef PIN_GPS_EN
digitalWrite(PIN_GPS_EN, PIN_GPS_EN);
pinMode(PIN_GPS_EN, OUTPUT);
#endif
#ifdef PIN_GPS_RESET
digitalWrite(PIN_GPS_RESET, 1); // assert for 10ms
pinMode(PIN_GPS_RESET, OUTPUT);
delay(10);
digitalWrite(PIN_GPS_RESET, 0);
#endif
setAwake(true); // Wake GPS power before doing any init
bool ok = setupGPS();
if (ok)
if (ok) {
notifySleepObserver.observe(&notifySleep);
notifyDeepSleepObserver.observe(&notifyDeepSleep);
}
return ok;
}
// Allow defining the polarity of the WAKE output. default is active high
#ifndef GPS_WAKE_ACTIVE
#define GPS_WAKE_ACTIVE 1
#endif
void GPS::wake()
{
#ifdef PIN_GPS_WAKE
digitalWrite(PIN_GPS_WAKE, GPS_WAKE_ACTIVE);
pinMode(PIN_GPS_WAKE, OUTPUT);
#endif
}
void GPS::sleep() {
#ifdef PIN_GPS_WAKE
digitalWrite(PIN_GPS_WAKE, GPS_WAKE_ACTIVE ? 0 : 1);
pinMode(PIN_GPS_WAKE, OUTPUT);
#endif
}
/// Record that we have a GPS
void GPS::setConnected()
{
@@ -225,7 +283,19 @@ void GPS::forceWake(bool on)
/// Prepare the GPS for the cpu entering deep or light sleep, expect to be gone for at least 100s of msecs
int GPS::prepareSleep(void *unused)
{
DEBUG_MSG("GPS prepare sleep!\n");
forceWake(false);
return 0;
}
/// Prepare the GPS for the cpu entering deep or light sleep, expect to be gone for at least 100s of msecs
int GPS::prepareDeepSleep(void *unused)
{
DEBUG_MSG("GPS deep sleep!\n");
// For deep sleep we also want abandon any lock attempts (because we want minimum power)
setAwake(false);
return 0;
}

View File

@@ -30,6 +30,7 @@ class GPS : private concurrency::OSThread
uint8_t numSatellites = 0;
CallbackObserver<GPS, void *> notifySleepObserver = CallbackObserver<GPS, void *>(this, &GPS::prepareSleep);
CallbackObserver<GPS, void *> notifyDeepSleepObserver = CallbackObserver<GPS, void *>(this, &GPS::prepareDeepSleep);
public:
/** If !NULL we will use this serial port to construct our GPS */
@@ -72,13 +73,13 @@ class GPS : private concurrency::OSThread
protected:
/// Do gps chipset specific init, return true for success
virtual bool setupGPS() = 0;
virtual bool setupGPS();
/// If possible force the GPS into sleep/low power mode
virtual void sleep() {}
virtual void sleep();
/// wake the GPS into normal operation mode
virtual void wake() {}
virtual void wake();
/** Subclasses should look for serial rx characters here and feed it to their GPS parser
*
@@ -115,6 +116,10 @@ class GPS : private concurrency::OSThread
/// always returns 0 to indicate okay to sleep
int prepareSleep(void *unused);
/// Prepare the GPS for the cpu entering deep sleep, expect to be gone for at least 100s of msecs
/// always returns 0 to indicate okay to sleep
int prepareDeepSleep(void *unused);
/**
* Switch the GPS into a mode where we are actively looking for a lock, or alternatively switch GPS into a low power mode
*

View File

@@ -1,6 +1,6 @@
#include "NMEAGPS.h"
#include "configuration.h"
#include "RTC.h"
#include "configuration.h"
static int32_t toDegInt(RawDegrees d)
{
@@ -13,6 +13,8 @@ static int32_t toDegInt(RawDegrees d)
bool NMEAGPS::setupGPS()
{
GPS::setupGPS();
#ifdef PIN_GPS_PPS
// pulse per second
// FIXME - move into shared GPS code
@@ -32,7 +34,7 @@ bool NMEAGPS::lookForTime()
{
auto ti = reader.time;
auto d = reader.date;
if (ti.isUpdated() && ti.isValid() && d.isValid()) {
if (ti.isValid() && d.isValid()) { // Note: we don't check for updated, because we'll only be called if needed
/* Convert to unix time
The Unix epoch (or Unix time or POSIX time or Unix timestamp) is the number of seconds that have elapsed since January 1, 1970
(midnight UTC/GMT), not counting leap seconds (in ISO 8601: 1970-01-01T00:00:00Z).
@@ -65,27 +67,27 @@ bool NMEAGPS::lookForLocation()
// uint8_t fixtype = reader.fixQuality();
// hasValidLocation = ((fixtype >= 1) && (fixtype <= 5));
if (reader.satellites.isUpdated()) {
setNumSatellites(reader.satellites.value());
}
// Diminution of precision (an accuracy metric) is reported in 10^2 units, so we need to scale down when we use it
if (reader.hdop.isUpdated()) {
dop = reader.hdop.value();
}
if (reader.course.isUpdated()) {
heading = reader.course.value() * 1e3; // Scale the heading (in degrees * 10^-2) to match the expected degrees * 10^-5
}
if (reader.altitude.isUpdated())
altitude = reader.altitude.meters();
if (reader.location.isUpdated()) {
if (reader.altitude.isValid())
altitude = reader.altitude.meters();
if (reader.location.isValid()) {
auto loc = reader.location.value();
latitude = toDegInt(loc.lat);
longitude = toDegInt(loc.lng);
foundLocation = true;
}
// Diminution of precision (an accuracy metric) is reported in 10^2 units, so we need to scale down when we use it
if (reader.hdop.isValid()) {
dop = reader.hdop.value();
}
if (reader.course.isValid()) {
heading = reader.course.value() * 1e3; // Scale the heading (in degrees * 10^-2) to match the expected degrees * 10^-5
}
if (reader.satellites.isValid()) {
setNumSatellites(reader.satellites.value());
}
auto loc = reader.location.value();
latitude = toDegInt(loc.lat);
longitude = toDegInt(loc.lng);
foundLocation = true;
// expect gps pos lat=37.520825, lon=-122.309162, alt=158
DEBUG_MSG("new NMEA GPS pos lat=%f, lon=%f, alt=%d, hdop=%g, heading=%f\n", latitude * 1e-7, longitude * 1e-7, altitude,

View File

@@ -29,16 +29,7 @@ bool UBloxGPS::tryConnect()
bool UBloxGPS::setupGPS()
{
if (_serial_gps) {
#ifdef GPS_RX_PIN
_serial_gps->begin(GPS_BAUDRATE, SERIAL_8N1, GPS_RX_PIN, GPS_TX_PIN);
#else
_serial_gps->begin(GPS_BAUDRATE);
#endif
#ifndef NO_ESP32
_serial_gps->setRxBufferSize(2048); // the default is 256
#endif
}
GPS::setupGPS();
// uncomment to see debug info
// ublox.enableDebugging(Serial);

View File

@@ -46,15 +46,18 @@ void updateDisplay(uint8_t *blackFrame = framePtr)
EInkDisplay::EInkDisplay(uint8_t address, int sda, int scl)
{
setGeometry(GEOMETRY_128_64); // FIXME - currently we lie and claim 128x64 because I'm not yet sure other resolutions will
// work ie GEOMETRY_RAWMODE
setGeometry(GEOMETRY_RAWMODE, EPD_WIDTH, EPD_HEIGHT);
// setGeometry(GEOMETRY_RAWMODE, 128, 64); // old resolution
// setGeometry(GEOMETRY_128_64); // We originally used this because I wasn't sure if rawmode worked - it does
}
// FIXME quick hack to limit drawing to a very slow rate
uint32_t lastDrawMsec;
// Write the buffer to the display memory
void EInkDisplay::display(void)
/**
* Force a display update if we haven't drawn within the specified msecLimit
*/
bool EInkDisplay::forceDisplay(uint32_t msecLimit)
{
// No need to grab this lock because we are on our own SPI bus
// concurrency::LockGuard g(spiLock);
@@ -62,16 +65,16 @@ void EInkDisplay::display(void)
uint32_t now = millis();
uint32_t sinceLast = now - lastDrawMsec;
if (framePtr && (sinceLast > 60 * 1000 || lastDrawMsec == 0)) {
if (framePtr && (sinceLast > msecLimit || lastDrawMsec == 0)) {
lastDrawMsec = now;
// FIXME - only draw bits have changed (use backbuf similar to the other displays)
// tft.drawBitmap(0, 0, buffer, 128, 64, TFT_YELLOW, TFT_BLACK);
for (uint8_t y = 0; y < SCREEN_HEIGHT; y++) {
for (uint8_t x = 0; x < SCREEN_WIDTH; x++) {
for (uint8_t y = 0; y < displayHeight; y++) {
for (uint8_t x = 0; x < displayWidth; x++) {
// get src pixel in the page based ordering the OLED lib uses FIXME, super inefficent
auto b = buffer[x + (y / 8) * SCREEN_WIDTH];
auto b = buffer[x + (y / 8) * displayWidth];
auto isset = b & (1 << (y & 7));
frame.drawPixel(x, y, isset ? INK : PAPER);
}
@@ -83,11 +86,25 @@ void EInkDisplay::display(void)
updateDisplay(); // Send image to display and refresh
DEBUG_MSG("done\n");
// Put screen to sleep to save power
// Put screen to sleep to save power
ePaper.Sleep();
return true;
} else {
// DEBUG_MSG("Skipping eink display\n");
return false;
}
}
// Write the buffer to the display memory
void EInkDisplay::display(void)
{
// We don't allow regular 'dumb' display() calls to draw on eink until we've shown
// at least one forceDisplay() keyframe. This prevents flashing when we should the critical
// bootscreen (that we want to look nice)
if (lastDrawMsec)
forceDisplay(slowUpdateMsec); // Show the first screen a few seconds after boot, then slower
}
// Send a command to the display (low level function)
void EInkDisplay::sendCommand(uint8_t com)
{

View File

@@ -14,15 +14,26 @@
*/
class EInkDisplay : public OLEDDisplay
{
/// How often should we update the display
/// thereafter we do once per 5 minutes
uint32_t slowUpdateMsec = 5 * 60 * 1000;
public:
/* constructor
FIXME - the parameters are not used, just a temporary hack to keep working like the old displays
*/
EInkDisplay(uint8_t address, int sda, int scl);
// Write the buffer to the display memory
// Write the buffer to the display memory (for eink we only do this occasionally)
virtual void display(void);
/**
* Force a display update if we haven't drawn within the specified msecLimit
*
* @return true if we did draw the screen
*/
bool forceDisplay(uint32_t msecLimit = 1000);
protected:
// the header size of the buffer used, e.g. for the SPI command header
virtual int getBufferOffset(void) { return 0; }
@@ -33,3 +44,5 @@ class EInkDisplay : public OLEDDisplay
// Connect to the display
virtual bool connect();
};

View File

@@ -58,39 +58,73 @@ static char ourId[5];
static bool heartbeat = false;
#endif
static uint16_t displayWidth, displayHeight;
#define SCREEN_WIDTH displayWidth
#define SCREEN_HEIGHT displayHeight
#ifdef HAS_EINK
// The screen is bigger so use bigger fonts
#define FONT_SMALL ArialMT_Plain_16
#define FONT_MEDIUM ArialMT_Plain_24
#define FONT_LARGE ArialMT_Plain_24
#else
#define FONT_SMALL ArialMT_Plain_10
#define FONT_MEDIUM ArialMT_Plain_16
#define FONT_LARGE ArialMT_Plain_24
#endif
#define fontHeight(font) ((font)[1] + 1) // height is position 1
#define FONT_HEIGHT_SMALL fontHeight(FONT_SMALL)
#define FONT_HEIGHT_MEDIUM fontHeight(FONT_MEDIUM)
#define getStringCenteredX(s) ((SCREEN_WIDTH - display->getStringWidth(s)) / 2)
#ifndef SCREEN_TRANSITION_MSECS
#define SCREEN_TRANSITION_MSECS 300
#endif
static void drawBootScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
{
// draw an xbm image.
// Please note that everything that should be transitioned
// needs to be drawn relative to x and y
display->drawXbm(x + 32, y, icon_width, icon_height, (const uint8_t *)icon_bits);
display->setFont(ArialMT_Plain_16);
display->setTextAlignment(TEXT_ALIGN_CENTER);
display->drawString(64 + x, SCREEN_HEIGHT - FONT_HEIGHT_16, "meshtastic.org");
display->setFont(ArialMT_Plain_10);
const char *region = xstr(HW_VERSION);
if (*region && region[3] == '-') // Skip past 1.0- in the 1.0-EU865 string
region += 4;
// draw centered left to right and centered above the one line of app text
display->drawXbm(x + (SCREEN_WIDTH - icon_width) / 2, y + (SCREEN_HEIGHT - FONT_HEIGHT_MEDIUM - icon_height) / 2 + 2,
icon_width, icon_height, (const uint8_t *)icon_bits);
display->setFont(FONT_MEDIUM);
display->setTextAlignment(TEXT_ALIGN_LEFT);
const char *title = "meshtastic.org";
display->drawString(x + getStringCenteredX(title), y + SCREEN_HEIGHT - FONT_HEIGHT_MEDIUM, title);
display->setFont(FONT_SMALL);
const char *region = myRegion ? myRegion->name : NULL;
if (region)
display->drawString(x + 0, y + 0, region);
char buf[16];
snprintf(buf, sizeof(buf), "%s",
xstr(APP_VERSION)); // Note: we don't bother printing region or now, it makes the string too long
display->drawString(SCREEN_WIDTH - 20, 0, buf);
display->drawString(x + SCREEN_WIDTH - display->getStringWidth(buf), y + 0, buf);
screen->forceDisplay();
}
static void drawFrameBluetooth(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
{
display->setTextAlignment(TEXT_ALIGN_CENTER);
display->setFont(ArialMT_Plain_16);
display->setFont(FONT_MEDIUM);
display->drawString(64 + x, y, "Bluetooth");
display->setFont(ArialMT_Plain_10);
display->drawString(64 + x, FONT_HEIGHT + y + 2, "Enter this code");
display->setFont(FONT_SMALL);
display->drawString(64 + x, FONT_HEIGHT_SMALL + y + 2, "Enter this code");
display->setFont(ArialMT_Plain_24);
display->setFont(FONT_LARGE);
display->drawString(64 + x, 26 + y, btPIN);
display->setFont(ArialMT_Plain_10);
display->setFont(FONT_SMALL);
char buf[30];
const char *name = "Name: ";
strcpy(buf, name);
@@ -112,10 +146,10 @@ static void drawTextMessageFrame(OLEDDisplay *display, OLEDDisplayUiState *state
// with the third parameter you can define the width after which words will
// be wrapped. Currently only spaces and "-" are allowed for wrapping
display->setTextAlignment(TEXT_ALIGN_LEFT);
display->setFont(ArialMT_Plain_16);
display->setFont(FONT_MEDIUM);
String sender = (node && node->has_user) ? node->user.short_name : "???";
display->drawString(0 + x, 0 + y, sender);
display->setFont(ArialMT_Plain_10);
display->setFont(FONT_SMALL);
// the max length of this buffer is much longer than we can possibly print
static char tempBuf[96];
@@ -135,8 +169,8 @@ static void drawColumns(OLEDDisplay *display, int16_t x, int16_t y, const char *
int xo = x, yo = y;
while (*f) {
display->drawString(xo, yo, *f);
yo += FONT_HEIGHT;
if (yo > SCREEN_HEIGHT - FONT_HEIGHT) {
yo += FONT_HEIGHT_SMALL;
if (yo > SCREEN_HEIGHT - FONT_HEIGHT_SMALL) {
xo += SCREEN_WIDTH / 2;
yo = 0;
}
@@ -162,14 +196,14 @@ static void drawColumns(OLEDDisplay *display, int16_t x, int16_t y, const char *
// Wrap to next row, if needed.
if (++col >= COLUMNS) {
xo = x;
yo += FONT_HEIGHT;
yo += FONT_HEIGHT_SMALL;
col = 0;
}
f++;
}
if (col != 0) {
// Include last incomplete line in our total.
yo += FONT_HEIGHT;
yo += FONT_HEIGHT_SMALL;
}
return yo;
@@ -236,7 +270,7 @@ static void drawGPS(OLEDDisplay *display, int16_t x, int16_t y, const GPSStatus
display->drawFastImage(x + 24, y, 8, 8, imgSatellite);
// Draw the number of satellites
sprintf(satsString, "%d", gps->getNumSatellites());
sprintf(satsString, "%lu", gps->getNumSatellites());
display->drawString(x + 34, y - 2, satsString);
}
}
@@ -476,7 +510,7 @@ static void drawNodeInfo(OLEDDisplay *display, OLEDDisplayUiState *state, int16_
NodeInfo *node = nodeDB.getNodeByIndex(nodeIndex);
display->setFont(ArialMT_Plain_10);
display->setFont(FONT_SMALL);
// The coordinates define the left starting point of the text
display->setTextAlignment(TEXT_ALIGN_LEFT);
@@ -489,11 +523,11 @@ static void drawNodeInfo(OLEDDisplay *display, OLEDDisplayUiState *state, int16_
uint32_t agoSecs = sinceLastSeen(node);
static char lastStr[20];
if (agoSecs < 120) // last 2 mins?
snprintf(lastStr, sizeof(lastStr), "%u seconds ago", agoSecs);
snprintf(lastStr, sizeof(lastStr), "%lu seconds ago", agoSecs);
else if (agoSecs < 120 * 60) // last 2 hrs
snprintf(lastStr, sizeof(lastStr), "%u minutes ago", agoSecs / 60);
snprintf(lastStr, sizeof(lastStr), "%lu minutes ago", agoSecs / 60);
else
snprintf(lastStr, sizeof(lastStr), "%u hours ago", agoSecs / 60 / 60);
snprintf(lastStr, sizeof(lastStr), "%lu hours ago", agoSecs / 60 / 60);
static char distStr[20];
strcpy(distStr, "? km"); // might not have location data
@@ -531,7 +565,7 @@ static void drawNodeInfo(OLEDDisplay *display, OLEDDisplayUiState *state, int16_
// direction to node is unknown so display question mark
// Debug info for gps lock errors
// DEBUG_MSG("ourNode %d, ourPos %d, theirPos %d\n", !!ourNode, ourNode && hasPosition(ourNode), hasPosition(node));
display->drawString(compassX - FONT_HEIGHT / 4, compassY - FONT_HEIGHT / 2, "?");
display->drawString(compassX - FONT_HEIGHT_SMALL / 4, compassY - FONT_HEIGHT_SMALL / 2, "?");
display->drawCircle(compassX, compassY, COMPASS_DIAM / 2);
// Must be after distStr is populated
@@ -561,7 +595,8 @@ void _screen_header()
}
#endif
Screen::Screen(uint8_t address, int sda, int scl) : OSThread("Screen"), cmdQueue(32), dispdev(address, sda, scl), ui(&dispdev) {
Screen::Screen(uint8_t address, int sda, int scl) : OSThread("Screen"), cmdQueue(32), dispdev(address, sda, scl), ui(&dispdev)
{
cmdQueue.setReader(this);
}
@@ -592,11 +627,17 @@ void Screen::setup()
// 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();
// I think this is not needed - redundant with ui.init
// dispdev.resetOrientation();
// Initialising the UI will init the display too.
ui.init();
ui.setTimePerTransition(300); // msecs
displayWidth = dispdev.width();
displayHeight = dispdev.height();
ui.setTimePerTransition(SCREEN_TRANSITION_MSECS);
ui.setIndicatorPosition(BOTTOM);
// Defines where the first frame is located in the bar.
ui.setIndicatorDirection(LEFT_RIGHT);
@@ -622,7 +663,9 @@ void Screen::setup()
// Set up a log buffer with 3 lines, 32 chars each.
dispdev.setLogBuffer(3, 32);
#ifdef FLIP_SCREEN_VERTICALLY
#ifdef SCREEN_MIRROR
dispdev.mirrorScreen();
#elif defined(SCREEN_FLIP_VERTICALLY)
dispdev.flipScreenVertically();
#endif
@@ -645,6 +688,14 @@ void Screen::setup()
nodeStatusObserver.observe(&nodeStatus->onNewStatus);
}
void Screen::forceDisplay()
{
// Nasty hack to force epaper updates for 'key' frames. FIXME, cleanup.
#ifdef HAS_EINK
dispdev.forceDisplay();
#endif
}
int32_t Screen::runOnce()
{
// If we don't have a screen, don't ever spend any CPU for us.
@@ -655,7 +706,8 @@ int32_t Screen::runOnce()
// Show boot screen for first 3 seconds, then switch to normal operation.
static bool showingBootScreen = true;
if (showingBootScreen && (millis() > 3000)) {
if (showingBootScreen && (millis() > 5000)) {
DEBUG_MSG("Done with boot screen...\n");
stopBootScreen();
showingBootScreen = false;
}
@@ -701,6 +753,10 @@ int32_t Screen::runOnce()
return 0;
}
// this must be before the frameState == FIXED check, because we always
// want to draw at least one FIXED frame before doing forceDisplay
ui.update();
// Switch to a low framerate (to save CPU) when we are not in transition
// but we should only call setTargetFPS when framestate changes, because
// otherwise that breaks animations.
@@ -709,6 +765,7 @@ int32_t Screen::runOnce()
DEBUG_MSG("Setting idle framerate\n");
targetFramerate = IDLE_FRAMERATE;
ui.setTargetFPS(targetFramerate);
forceDisplay();
}
// While showing the bootscreen or Bluetooth pair screen all of our
@@ -717,8 +774,6 @@ int32_t Screen::runOnce()
// standard screen loop handling here
}
ui.update();
// DEBUG_MSG("want fps %d, fixed=%d\n", targetFramerate,
// ui.getUiState()->frameState); If we are scrolling we need to be called
// soon, otherwise just 1 fps (to save CPU) We also ask to be called twice
@@ -785,6 +840,8 @@ void Screen::setFrames()
prevFrame = -1; // Force drawNodeInfo to pick a new node (because our list
// just changed)
setFastFramerate(); // Draw ASAP
}
void Screen::handleStartBluetoothPinScreen(uint32_t pin)
@@ -794,16 +851,17 @@ void Screen::handleStartBluetoothPinScreen(uint32_t pin)
static FrameCallback btFrames[] = {drawFrameBluetooth};
snprintf(btPIN, sizeof(btPIN), "%06u", pin);
snprintf(btPIN, sizeof(btPIN), "%06lu", pin);
ui.disableAllIndicators();
ui.setFrames(btFrames, 1);
setFastFramerate();
}
void Screen::handlePrint(const char *text)
{
DEBUG_MSG("Screen: %s", text);
if (!useDisplay)
if (!useDisplay || !showingNormalScreen)
return;
dispdev.print(text);
@@ -814,22 +872,31 @@ void Screen::handleOnPress()
// If screen was off, just wake it, otherwise advance to next frame
// If we are in a transition, the press must have bounced, drop it.
if (ui.getUiState()->frameState == FIXED) {
setInterval(0); // redraw ASAP
ui.nextFrame();
DEBUG_MSG("Setting fast framerate\n");
// We are about to start a transition so speed up fps
targetFramerate = TRANSITION_FRAMERATE;
ui.setTargetFPS(targetFramerate);
setFastFramerate();
}
}
#ifndef SCREEN_TRANSITION_FRAMERATE
#define SCREEN_TRANSITION_FRAMERATE 30 // fps
#endif
void Screen::setFastFramerate()
{
DEBUG_MSG("Setting fast framerate\n");
// We are about to start a transition so speed up fps
targetFramerate = SCREEN_TRANSITION_FRAMERATE;
ui.setTargetFPS(targetFramerate);
setInterval(0); // redraw ASAP
}
void DebugInfo::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
{
displayedNodeNum = 0; // Not currently showing a node pane
display->setFont(ArialMT_Plain_10);
display->setFont(FONT_SMALL);
// The coordinates define the left starting point of the text
display->setTextAlignment(TEXT_ALIGN_LEFT);
@@ -851,13 +918,13 @@ void DebugInfo::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16
drawGPS(display, x + (SCREEN_WIDTH * 0.63), y + 2, gpsStatus);
// Draw the channel name
display->drawString(x, y + FONT_HEIGHT, channelStr);
display->drawString(x, y + FONT_HEIGHT_SMALL, channelStr);
// Draw our hardware ID to assist with bluetooth pairing
display->drawFastImage(x + SCREEN_WIDTH - (10) - display->getStringWidth(ourId), y + 2 + FONT_HEIGHT, 8, 8, imgInfo);
display->drawString(x + SCREEN_WIDTH - display->getStringWidth(ourId), y + FONT_HEIGHT, ourId);
display->drawFastImage(x + SCREEN_WIDTH - (10) - display->getStringWidth(ourId), y + 2 + FONT_HEIGHT_SMALL, 8, 8, imgInfo);
display->drawString(x + SCREEN_WIDTH - display->getStringWidth(ourId), y + FONT_HEIGHT_SMALL, ourId);
// Draw any log messages
display->drawLogBuffer(x, y + (FONT_HEIGHT * 2));
display->drawLogBuffer(x, y + (FONT_HEIGHT_SMALL * 2));
/* Display a heartbeat pixel that blinks every time the frame is redrawn */
#ifdef SHOW_REDRAWS
@@ -876,7 +943,7 @@ void DebugInfo::drawFrameWiFi(OLEDDisplay *display, OLEDDisplayUiState *state, i
displayedNodeNum = 0; // Not currently showing a node pane
display->setFont(ArialMT_Plain_10);
display->setFont(FONT_SMALL);
// The coordinates define the left starting point of the text
display->setTextAlignment(TEXT_ALIGN_LEFT);
@@ -907,86 +974,90 @@ void DebugInfo::drawFrameWiFi(OLEDDisplay *display, OLEDDisplayUiState *state, i
if (WiFi.status() == WL_CONNECTED) {
if (radioConfig.preferences.wifi_ap_mode) {
display->drawString(x, y + FONT_HEIGHT * 1, "IP: " + String(WiFi.softAPIP().toString().c_str()));
display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "IP: " + String(WiFi.softAPIP().toString().c_str()));
} else {
display->drawString(x, y + FONT_HEIGHT * 1, "IP: " + String(WiFi.localIP().toString().c_str()));
display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "IP: " + String(WiFi.localIP().toString().c_str()));
}
} else if (WiFi.status() == WL_NO_SSID_AVAIL) {
display->drawString(x, y + FONT_HEIGHT * 1, "SSID Not Found");
display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "SSID Not Found");
} else if (WiFi.status() == WL_CONNECTION_LOST) {
display->drawString(x, y + FONT_HEIGHT * 1, "Connection Lost");
display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "Connection Lost");
} else if (WiFi.status() == WL_CONNECT_FAILED) {
display->drawString(x, y + FONT_HEIGHT * 1, "Connection Failed");
display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "Connection Failed");
//} else if (WiFi.status() == WL_DISCONNECTED) {
// display->drawString(x, y + FONT_HEIGHT * 1, "Disconnected");
// display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "Disconnected");
} else if (WiFi.status() == WL_IDLE_STATUS) {
display->drawString(x, y + FONT_HEIGHT * 1, "Idle ... Reconnecting");
display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "Idle ... Reconnecting");
} else {
// Codes:
// https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/wifi.html#wi-fi-reason-code
if (getWifiDisconnectReason() == 2) {
display->drawString(x, y + FONT_HEIGHT * 1, "Authentication Invalid");
display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "Authentication Invalid");
} else if (getWifiDisconnectReason() == 3) {
display->drawString(x, y + FONT_HEIGHT * 1, "De-authenticated");
display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "De-authenticated");
} else if (getWifiDisconnectReason() == 4) {
display->drawString(x, y + FONT_HEIGHT * 1, "Disassociated Expired");
display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "Disassociated Expired");
} else if (getWifiDisconnectReason() == 5) {
display->drawString(x, y + FONT_HEIGHT * 1, "AP - Too Many Clients");
display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "AP - Too Many Clients");
} else if (getWifiDisconnectReason() == 6) {
display->drawString(x, y + FONT_HEIGHT * 1, "NOT_AUTHED");
display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "NOT_AUTHED");
} else if (getWifiDisconnectReason() == 7) {
display->drawString(x, y + FONT_HEIGHT * 1, "NOT_ASSOCED");
display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "NOT_ASSOCED");
} else if (getWifiDisconnectReason() == 8) {
display->drawString(x, y + FONT_HEIGHT * 1, "Disassociated");
display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "Disassociated");
} else if (getWifiDisconnectReason() == 9) {
display->drawString(x, y + FONT_HEIGHT * 1, "ASSOC_NOT_AUTHED");
display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "ASSOC_NOT_AUTHED");
} else if (getWifiDisconnectReason() == 10) {
display->drawString(x, y + FONT_HEIGHT * 1, "DISASSOC_PWRCAP_BAD");
display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "DISASSOC_PWRCAP_BAD");
} else if (getWifiDisconnectReason() == 11) {
display->drawString(x, y + FONT_HEIGHT * 1, "DISASSOC_SUPCHAN_BAD");
display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "DISASSOC_SUPCHAN_BAD");
} else if (getWifiDisconnectReason() == 13) {
display->drawString(x, y + FONT_HEIGHT * 1, "IE_INVALID");
display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "IE_INVALID");
} else if (getWifiDisconnectReason() == 14) {
display->drawString(x, y + FONT_HEIGHT * 1, "MIC_FAILURE");
display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "MIC_FAILURE");
} else if (getWifiDisconnectReason() == 15) {
display->drawString(x, y + FONT_HEIGHT * 1, "AP Handshake Timeout");
display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "AP Handshake Timeout");
} else if (getWifiDisconnectReason() == 16) {
display->drawString(x, y + FONT_HEIGHT * 1, "GROUP_KEY_UPDATE_TIMEOUT");
display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "GROUP_KEY_UPDATE_TIMEOUT");
} else if (getWifiDisconnectReason() == 17) {
display->drawString(x, y + FONT_HEIGHT * 1, "IE_IN_4WAY_DIFFERS");
display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "IE_IN_4WAY_DIFFERS");
} else if (getWifiDisconnectReason() == 18) {
display->drawString(x, y + FONT_HEIGHT * 1, "Invalid Group Cipher");
display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "Invalid Group Cipher");
} else if (getWifiDisconnectReason() == 19) {
display->drawString(x, y + FONT_HEIGHT * 1, "Invalid Pairwise Cipher");
display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "Invalid Pairwise Cipher");
} else if (getWifiDisconnectReason() == 20) {
display->drawString(x, y + FONT_HEIGHT * 1, "AKMP_INVALID");
display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "AKMP_INVALID");
} else if (getWifiDisconnectReason() == 21) {
display->drawString(x, y + FONT_HEIGHT * 1, "UNSUPP_RSN_IE_VERSION");
display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "UNSUPP_RSN_IE_VERSION");
} else if (getWifiDisconnectReason() == 22) {
display->drawString(x, y + FONT_HEIGHT * 1, "INVALID_RSN_IE_CAP");
display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "INVALID_RSN_IE_CAP");
} else if (getWifiDisconnectReason() == 23) {
display->drawString(x, y + FONT_HEIGHT * 1, "802_1X_AUTH_FAILED");
display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "802_1X_AUTH_FAILED");
} else if (getWifiDisconnectReason() == 24) {
display->drawString(x, y + FONT_HEIGHT * 1, "CIPHER_SUITE_REJECTED");
display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "CIPHER_SUITE_REJECTED");
} else if (getWifiDisconnectReason() == 200) {
display->drawString(x, y + FONT_HEIGHT * 1, "BEACON_TIMEOUT");
display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "BEACON_TIMEOUT");
} else if (getWifiDisconnectReason() == 201) {
display->drawString(x, y + FONT_HEIGHT * 1, "AP Not Found");
display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "AP Not Found");
} else if (getWifiDisconnectReason() == 202) {
display->drawString(x, y + FONT_HEIGHT * 1, "AUTH_FAIL");
display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "AUTH_FAIL");
} else if (getWifiDisconnectReason() == 203) {
display->drawString(x, y + FONT_HEIGHT * 1, "ASSOC_FAIL");
display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "ASSOC_FAIL");
} else if (getWifiDisconnectReason() == 204) {
display->drawString(x, y + FONT_HEIGHT * 1, "HANDSHAKE_TIMEOUT");
display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "HANDSHAKE_TIMEOUT");
} else if (getWifiDisconnectReason() == 205) {
display->drawString(x, y + FONT_HEIGHT * 1, "Connection Failed");
display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "Connection Failed");
} else {
display->drawString(x, y + FONT_HEIGHT * 1, "Unknown Status");
display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "Unknown Status");
}
}
display->drawString(x, y + FONT_HEIGHT * 2, "SSID: " + String(wifiName));
display->drawString(x, y + FONT_HEIGHT * 3, "PWD: " + String(wifiPsw));
if ((millis() / 1000) % 2) {
display->drawString(x, y + FONT_HEIGHT_SMALL * 2, "SSID: " + String(wifiName));
} else {
display->drawString(x, y + FONT_HEIGHT_SMALL * 2, "PWD: " + String(wifiPsw));
}
display->drawString(x, y + FONT_HEIGHT_SMALL * 3, "http://meshtastic.local");
/* Display a heartbeat pixel that blinks every time the frame is redrawn */
#ifdef SHOW_REDRAWS
@@ -1001,7 +1072,7 @@ void DebugInfo::drawFrameSettings(OLEDDisplay *display, OLEDDisplayUiState *stat
{
displayedNodeNum = 0; // Not currently showing a node pane
display->setFont(ArialMT_Plain_10);
display->setFont(FONT_SMALL);
// The coordinates define the left starting point of the text
display->setTextAlignment(TEXT_ALIGN_LEFT);
@@ -1035,15 +1106,21 @@ void DebugInfo::drawFrameSettings(OLEDDisplay *display, OLEDDisplayUiState *stat
minutes %= 60;
hours %= 24;
display->drawString(x, y + FONT_HEIGHT * 1,
display->drawString(x, y + FONT_HEIGHT_SMALL * 1,
String(days) + "d " + (hours < 10 ? "0" : "") + String(hours) + ":" + (minutes < 10 ? "0" : "") +
String(minutes) + ":" + (seconds < 10 ? "0" : "") + String(seconds));
#ifndef NO_ESP32
// Show CPU Frequency.
display->drawString(x + SCREEN_WIDTH - display->getStringWidth("CPU " + String(getCpuFrequencyMhz()) + "MHz"),
y + FONT_HEIGHT_SMALL * 1, "CPU " + String(getCpuFrequencyMhz()) + "MHz");
#endif
// Line 3
drawGPSAltitude(display, x, y + FONT_HEIGHT * 2, gpsStatus);
drawGPSAltitude(display, x, y + FONT_HEIGHT_SMALL * 2, gpsStatus);
// Line 4
drawGPScoordinates(display, x, y + FONT_HEIGHT * 3, gpsStatus);
drawGPScoordinates(display, x, y + FONT_HEIGHT_SMALL * 3, gpsStatus);
/* Display a heartbeat pixel that blinks every time the frame is redrawn */
#ifdef SHOW_REDRAWS
@@ -1072,10 +1149,8 @@ int Screen::handleStatusUpdate(const meshtastic::Status *arg)
// DEBUG_MSG("Screen got status update %d\n", arg->getStatusType());
switch (arg->getStatusType()) {
case STATUS_TYPE_NODE:
if (nodeDB.updateTextMessage || nodeStatus->getLastNumTotal() != nodeStatus->getNumTotal()) {
setFrames(); // Regen the list of screens
prevFrame = -1; // Force a GUI update
setInterval(0); // Update the screen right away
if (showingNormalScreen && (nodeDB.updateTextMessage || nodeStatus->getLastNumTotal() != nodeStatus->getNumTotal())) {
setFrames(); // Regen the list of screens
}
nodeDB.updateGUI = false;
nodeDB.updateTextMessage = false;

View File

@@ -6,6 +6,8 @@
#ifdef USE_SH1106
#include <SH1106Wire.h>
#elif defined(USE_ST7567)
#include <ST7567Wire.h>
#else
#include <SSD1306Wire.h>
#endif
@@ -19,6 +21,11 @@
#include "power.h"
#include <string>
// 0 to 255, though particular variants might define different defaults
#ifndef BRIGHTNESS_DEFAULT
#define BRIGHTNESS_DEFAULT 150
#endif
namespace graphics
{
@@ -97,7 +104,7 @@ class Screen : public concurrency::OSThread
// Implementation to Adjust Brightness
void adjustBrightness();
uint8_t brightness = 150;
uint8_t brightness = BRIGHTNESS_DEFAULT;
/// Starts showing the Bluetooth PIN screen.
//
@@ -180,6 +187,9 @@ class Screen : public concurrency::OSThread
int handleStatusUpdate(const meshtastic::Status *arg);
/// Used to force (super slow) eink displays to draw critical frames
void forceDisplay();
protected:
/// Updates the UI.
//
@@ -216,6 +226,9 @@ class Screen : public concurrency::OSThread
/// Rebuilds our list of frames (screens) to default ones.
void setFrames();
/// Try to start drawing ASAP
void setFastFramerate();
/// 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);
@@ -244,6 +257,8 @@ class Screen : public concurrency::OSThread
EInkDisplay dispdev;
#elif defined(USE_SH1106)
SH1106Wire dispdev;
#elif defined(USE_ST7567)
ST7567Wire dispdev;
#else
SSD1306Wire dispdev;
#endif

View File

@@ -11,8 +11,7 @@ static TFT_eSPI tft = TFT_eSPI(); // Invoke library, pins defined in User_Setup.
TFTDisplay::TFTDisplay(uint8_t address, int sda, int scl)
{
setGeometry(GEOMETRY_128_64); // FIXME - currently we lie and claim 128x64 because I'm not yet sure other resolutions will
// work ie GEOMETRY_RAWMODE
setGeometry(GEOMETRY_RAWMODE, 160, 80);
}
// Write the buffer to the display memory
@@ -22,11 +21,11 @@ void TFTDisplay::display(void)
// FIXME - only draw bits have changed (use backbuf similar to the other displays)
// tft.drawBitmap(0, 0, buffer, 128, 64, TFT_YELLOW, TFT_BLACK);
for (uint8_t y = 0; y < SCREEN_HEIGHT; y++) {
for (uint8_t x = 0; x < SCREEN_WIDTH; x++) {
for (uint8_t y = 0; y < displayHeight; y++) {
for (uint8_t x = 0; x < displayWidth; x++) {
// get src pixel in the page based ordering the OLED lib uses FIXME, super inefficent
auto b = buffer[x + (y / 8) * SCREEN_WIDTH];
auto b = buffer[x + (y / 8) * displayWidth];
auto isset = b & (1 << (y & 7));
tft.drawPixel(x, y, isset ? TFT_WHITE : TFT_BLACK);
}

View File

@@ -2,12 +2,7 @@
#include "fonts.h"
#define FONT_HEIGHT 14 // actually 13 for "Arial 10" but want a little extra space
#define FONT_HEIGHT_16 (ArialMT_Plain_16[1] + 1)
// This means the *visible* area (sh1106 can address 132, but shows 128 for example)
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define TRANSITION_FRAMERATE 30 // fps
#define IDLE_FRAMERATE 1 // in fps
#define COMPASS_DIAM 44

View File

@@ -50,7 +50,9 @@ meshtastic::GPSStatus *gpsStatus = new meshtastic::GPSStatus();
// Global Node status
meshtastic::NodeStatus *nodeStatus = new meshtastic::NodeStatus();
bool ssd1306_found;
/// The I2C address of our display (if found)
uint8_t screen_found;
bool axp192_found;
Router *router = NULL; // Users of router don't care what sort of subclass implements that API
@@ -72,9 +74,13 @@ void scanI2Cdevice(void)
nDevices++;
if (addr == SSD1306_ADDRESS) {
ssd1306_found = true;
screen_found = addr;
DEBUG_MSG("ssd1306 display found\n");
}
if (addr == ST7567_ADDRESS) {
screen_found = addr;
DEBUG_MSG("st7567 display found\n");
}
#ifdef AXP192_SLAVE_ADDRESS
if (addr == AXP192_SLAVE_ADDRESS) {
axp192_found = true;
@@ -168,12 +174,14 @@ class ButtonThread : public OSThread
userButton = OneButton(BUTTON_PIN, true, true);
userButton.attachClick(userButtonPressed);
userButton.attachDuringLongPress(userButtonPressedLong);
userButton.attachDoubleClick(userButtonDoublePressed);
wakeOnIrq(BUTTON_PIN, FALLING);
#endif
#ifdef BUTTON_PIN_ALT
userButtonAlt = OneButton(BUTTON_PIN_ALT, true, true);
userButtonAlt.attachClick(userButtonPressed);
userButton.attachDuringLongPress(userButtonPressedLong);
userButtonAlt.attachDuringLongPress(userButtonPressedLong);
userButtonAlt.attachDoubleClick(userButtonDoublePressed);
wakeOnIrq(BUTTON_PIN_ALT, FALLING);
#endif
}
@@ -190,9 +198,10 @@ class ButtonThread : public OSThread
#endif
#ifdef BUTTON_PIN_ALT
userButtonAlt.tick();
canSleep &= userButton.isIdle();
canSleep &= userButtonAlt.isIdle();
#endif
// if(!canSleep) DEBUG_MSG("Supressing sleep!\n");
// if (!canSleep) DEBUG_MSG("Supressing sleep!\n");
//else DEBUG_MSG("sleep ok\n");
return 5;
}
@@ -203,7 +212,18 @@ class ButtonThread : public OSThread
// DEBUG_MSG("press!\n");
powerFSM.trigger(EVENT_PRESS);
}
static void userButtonPressedLong() { screen->adjustBrightness(); }
static void userButtonPressedLong()
{
DEBUG_MSG("Long press!\n");
screen->adjustBrightness();
}
static void userButtonDoublePressed()
{
#ifndef NO_ESP32
disablePin();
#endif
}
};
static Periodic *ledPeriodic;
@@ -245,13 +265,21 @@ void setup()
#else
Wire.begin();
#endif
// i2c still busted on new board
#ifndef ARDUINO_NRF52840_PPR
scanI2Cdevice();
#ifdef PIN_LCD_RESET
// FIXME - move this someplace better, LCD is at address 0x3F
pinMode(PIN_LCD_RESET, OUTPUT);
digitalWrite(PIN_LCD_RESET, 0);
delay(1);
digitalWrite(PIN_LCD_RESET, 1);
delay(1);
#endif
scanI2Cdevice();
// Buttons & LED
buttonThread = new ButtonThread();
#ifdef LED_PIN
pinMode(LED_PIN, OUTPUT);
digitalWrite(LED_PIN, 1 ^ LED_INVERTED); // turn on for now
@@ -263,7 +291,7 @@ void setup()
#ifndef NO_ESP32
// Don't init display if we don't have one or we are waking headless due to a timer event
if (wakeCause == ESP_SLEEP_WAKEUP_TIMER)
ssd1306_found = false; // forget we even have the hardware
screen_found = 0; // forget we even have the hardware
esp32Setup();
#endif
@@ -289,55 +317,58 @@ void setup()
#endif
// Initialize the screen first so we can show the logo while we start up everything else.
screen = new graphics::Screen(SSD1306_ADDRESS);
#if defined(ST7735_CS) || defined(HAS_EINK)
screen->setup();
#else
if (ssd1306_found)
screen->setup();
#endif
screen->print("Started...\n");
screen = new graphics::Screen(screen_found);
readFromRTC(); // read the main CPU RTC at first (in case we can't get GPS time)
// If we know we have a L80 GPS, don't try UBLOX
#ifndef L80_RESET
// If we don't have bidirectional comms, we can't even try talking to UBLOX
UBloxGPS *ublox = NULL;
#ifdef GPS_TX_PIN
// Init GPS - first try ublox
auto ublox = new UBloxGPS();
ublox = new UBloxGPS();
gps = ublox;
if (!gps->setup()) {
DEBUG_MSG("ERROR: No UBLOX GPS found\n");
delete ublox;
gps = ublox = NULL;
}
#endif
if (GPS::_serial_gps) {
// Some boards might have only the TX line from the GPS connected, in that case, we can't configure it at all. Just
// assume NMEA at 9600 baud.
// dumb NMEA access only work for serial GPSes)
DEBUG_MSG("Hoping that NMEA might work\n");
if (!gps && GPS::_serial_gps) {
// Some boards might have only the TX line from the GPS connected, in that case, we can't configure it at all. Just
// assume NMEA at 9600 baud.
// dumb NMEA access only work for serial GPSes)
DEBUG_MSG("Hoping that NMEA might work\n");
#ifdef HAS_AIR530_GPS
gps = new Air530GPS();
gps = new Air530GPS();
#else
gps = new NMEAGPS();
gps = new NMEAGPS();
#endif
gps->setup();
}
gps->setup();
}
#else
gps = new NMEAGPS();
gps->setup();
#endif
if (gps)
gpsStatus->observe(&gps->newStatus);
else
DEBUG_MSG("Warning: No GPS found - running without GPS\n");
nodeStatus->observe(&nodeDB.newStatus);
service.init();
// Don't call screen setup until after nodedb is setup (because we need
// the current region name)
#if defined(ST7735_CS) || defined(HAS_EINK)
screen->setup();
#else
if (screen_found)
screen->setup();
#endif
screen->print("Started...\n");
// We have now loaded our saved preferences from flash
// ONCE we will factory reset the GPS for bug #327

View File

@@ -6,7 +6,6 @@
#include "graphics/Screen.h"
extern bool axp192_found;
extern bool ssd1306_found;
extern bool isCharging;
extern bool isUSBPowered;

View File

@@ -16,4 +16,7 @@ struct RegionInfo {
const char *name; // EU433 etc
};
extern const RegionInfo regions[];
extern const RegionInfo regions[];
extern const RegionInfo *myRegion;
extern void initRegion();

View File

@@ -198,7 +198,10 @@ void MeshService::loop()
bool MeshService::reloadConfig()
{
// If we can successfully set this radio to these settings, save them to disk
// This will also update the region as needed
bool didReset = nodeDB.resetRadioConfig(); // Don't let the phone send us fatally bad settings
configChanged.notifyObservers(NULL);
nodeDB.saveToDisk();

View File

@@ -147,8 +147,12 @@ bool NodeDB::resetRadioConfig()
radioConfig.preferences.wait_bluetooth_secs = 30;
radioConfig.preferences.position_broadcast_secs = 6 * 60;
radioConfig.preferences.ls_secs = 60;
radioConfig.preferences.region = RegionCode_TW;
}
// Update the global myRegion
initRegion();
return didFactoryReset;
}

View File

@@ -144,11 +144,18 @@ const char *getChannelName();
PREF_GET(send_owner_interval, 4)
PREF_GET(position_broadcast_secs, 15 * 60)
PREF_GET(wait_bluetooth_secs, 120)
// Each time we wake into the DARK state allow 1 minute to send and receive BLE packets to the phone
PREF_GET(wait_bluetooth_secs, 60)
PREF_GET(screen_on_secs, 60)
PREF_GET(mesh_sds_timeout_secs, 2 * 60 * 60)
PREF_GET(phone_sds_timeout_sec, 2 * 60 * 60)
PREF_GET(sds_secs, 365 * 24 * 60 * 60)
PREF_GET(ls_secs, 60 * 60)
// We default to sleeping (with bluetooth off for 5 minutes at a time). This seems to be a good tradeoff between
// latency for the user sending messages and power savings because of not having to run (expensive) ESP32 bluetooth
PREF_GET(ls_secs, 5 * 60)
PREF_GET(phone_timeout_secs, 15 * 60)
PREF_GET(min_wake_secs, 10)

View File

@@ -121,7 +121,14 @@ size_t PhoneAPI::getFromRadio(uint8_t *buf)
case STATE_SEND_RADIO:
fromRadioScratch.which_variant = FromRadio_radio_tag;
fromRadioScratch.variant.radio = radioConfig;
// NOTE: The phone app needs to know the ls_secs value so it can properly expect sleep behavior.
// So even if we internally use 0 to represent 'use default' we still need to send the value we are
// using to the app (so that even old phone apps work with new device loads).
fromRadioScratch.variant.radio.preferences.ls_secs = getPref_ls_secs();
state = STATE_SEND_NODEINFO;
break;

View File

@@ -26,7 +26,18 @@ const RegionInfo regions[] = {
RDEF(Unset, 903.08f, 2.16f, 13, 0) // Assume US freqs if unset, Must be last
};
static const RegionInfo *myRegion;
const RegionInfo *myRegion;
void initRegion()
{
const RegionInfo *r = regions;
for (; r->code != RegionCode_Unset && r->code != radioConfig.preferences.region; r++)
;
myRegion = r;
DEBUG_MSG("Wanted region %d, using %s\n", radioConfig.preferences.region, r->name);
myNodeInfo.num_channels = myRegion->numChannels; // Tell our android app how many channels we have
}
/**
* ## LoRaWAN for North America
@@ -91,20 +102,10 @@ void printPacket(const char *prefix, const MeshPacket *p)
DEBUG_MSG(")\n");
}
RadioInterface::RadioInterface()
RadioInterface::RadioInterface()
{
assert(sizeof(PacketHeader) == 4 || sizeof(PacketHeader) == 16); // make sure the compiler did what we expected
if (!myRegion) {
const RegionInfo *r = regions;
for (; r->code != RegionCode_Unset && r->code != radioConfig.preferences.region; r++)
;
myRegion = r;
DEBUG_MSG("Wanted region %d, using %s\n", radioConfig.preferences.region, r->name);
myNodeInfo.num_channels = myRegion->numChannels; // Tell our android app how many channels we have
}
// Can't print strings this early - serial not setup yet
// DEBUG_MSG("Set meshradio defaults name=%s\n", channelSettings.name);
}
@@ -120,10 +121,16 @@ bool RadioInterface::init()
// we now expect interfaces to operate in promiscous mode
// radioIf.setThisAddress(nodeDB.getNodeNum()); // Note: we must do this here, because the nodenum isn't inited at constructor
// time.
return true;
}
int RadioInterface::notifyDeepSleepCb(void *unused)
{
sleep();
return 0;
}
/** hash a string into an integer
*
* djb2 by Dan Bernstein.

View File

@@ -48,7 +48,7 @@ class RadioInterface
CallbackObserver<RadioInterface, void *>(this, &RadioInterface::preflightSleepCb);
CallbackObserver<RadioInterface, void *> notifyDeepSleepObserver =
CallbackObserver<RadioInterface, void *>(this, &RadioInterface::notifyDeepSleepDb);
CallbackObserver<RadioInterface, void *>(this, &RadioInterface::notifyDeepSleepCb);
protected:
MeshPacket *sendingPacket = NULL; // The packet we are currently sending
@@ -136,11 +136,7 @@ class RadioInterface
/// Return 0 if sleep is okay
int preflightSleepCb(void *unused = NULL) { return canSleep() ? 0 : 1; }
int notifyDeepSleepDb(void *unused = NULL)
{
sleep();
return 0;
}
int notifyDeepSleepCb(void *unused = NULL);
int reloadConfig(void *unused)
{

View File

@@ -236,20 +236,25 @@ void RadioLibInterface::startTransmitTimer(bool withDelay)
void RadioLibInterface::handleTransmitInterrupt()
{
// DEBUG_MSG("handling lora TX interrupt\n");
assert(sendingPacket); // Were we sending? - FIXME, this was null coming out of light sleep due to RF95 ISR!
completeSending();
// This can be null if we forced the device to enter standby mode. In that case
// ignore the transmit interrupt
if(sendingPacket)
completeSending();
}
void RadioLibInterface::completeSending()
{
if (sendingPacket) {
// We are careful to clear sending packet before calling printPacket because
// that can take a long time
auto p = sendingPacket;
sendingPacket = NULL;
if (p) {
txGood++;
printPacket("Completed sending", sendingPacket);
printPacket("Completed sending", p);
// We are done sending that packet, release it
packetPool.release(sendingPacket);
sendingPacket = NULL;
packetPool.release(p);
// DEBUG_MSG("Done with send\n");
}
}

View File

@@ -1,6 +1,11 @@
#include "SX1262Interface.h"
#include <configuration.h>
// Particular boards might define a different max power based on what their hardware can do
#ifndef SX1262_MAX_POWER
#define SX1262_MAX_POWER 22
#endif
SX1262Interface::SX1262Interface(RADIOLIB_PIN_TYPE cs, RADIOLIB_PIN_TYPE irq, RADIOLIB_PIN_TYPE rst, RADIOLIB_PIN_TYPE busy,
SPIClass &spi)
: RadioLibInterface(cs, irq, rst, busy, spi, &lora), lora(&module)
@@ -39,10 +44,10 @@ bool SX1262Interface::init()
applyModemConfig();
if (power == 0)
power = 22;
power = SX1262_MAX_POWER;
if (power > 22) // This chip has lower power limits than some
power = 22;
if (power > SX1262_MAX_POWER) // This chip has lower power limits than some
power = SX1262_MAX_POWER;
limitPower();
@@ -82,8 +87,8 @@ bool SX1262Interface::reconfigure()
assert(err == ERR_NONE);
// Hmm - seems to lower SNR when the signal levels are high. Leaving off for now...
// err = lora.setRxGain(true);
// assert(err == ERR_NONE);
err = lora.setRxGain(true);
assert(err == ERR_NONE);
err = lora.setSyncWord(syncWord);
assert(err == ERR_NONE);
@@ -196,9 +201,21 @@ bool SX1262Interface::isActivelyReceiving()
bool SX1262Interface::sleep()
{
// put chipset into sleep mode
disableInterrupt();
lora.sleep();
// Not keeping config is busted - next time nrf52 board boots lora sending fails tcxo related? - see datasheet
DEBUG_MSG("sx1262 entering sleep mode (FIXME, don't keep config)\n");
setStandby(); // Stop any pending operations
// turn off TCXO if it was powered
// FIXME - this isn't correct
// lora.setTCXO(0);
// put chipset into sleep mode (we've already disabled interrupts by now)
bool keepConfig = true;
lora.sleep(keepConfig); // Note: we do not keep the config, full reinit will be needed
#ifdef SX1262_POWER_EN
digitalWrite(SX1262_POWER_EN, LOW);
#endif
return true;
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,9 +1,11 @@
#pragma once
#include "PhoneAPI.h"
#include <Arduino.h>
#include <functional>
void initWebServer();
void createSSLCert();
void handleNotFound();
@@ -15,8 +17,21 @@ void notifyWebUI();
void handleHotspot();
void handleStyleCSS();
void handleRoot();
void handleScriptsScriptJS();
void handleJSONChatHistoryDummy();
void handleJSONChatHistoryDummy();
class HttpAPI : public PhoneAPI
{
public:
// Nothing here yet
private:
// Nothing here yet
protected:
// Nothing here yet
};

File diff suppressed because it is too large Load Diff

View File

@@ -6,6 +6,7 @@
#include "meshwifi/meshhttp.h"
#include "target_specific.h"
#include <DNSServer.h>
#include <ESPmDNS.h>
#include <WiFi.h>
static void WiFiEvent(WiFiEvent_t event);
@@ -17,8 +18,8 @@ static WiFiServerPort *apiPort;
uint8_t wifiDisconnectReason = 0;
// Stores the last 4 of our hardware ID, to make finding the device for pairing easier
static char ourHost[16];
// Stores our hostname
char ourHost[16];
bool isWifiAvailable()
{
@@ -29,9 +30,6 @@ bool isWifiAvailable()
// strcpy(radioConfig.preferences.wifi_password, "");
if (*wifiName && *wifiPsw) {
// Once every 10 seconds, try to reconnect.
return 1;
} else {
return 0;
@@ -64,6 +62,8 @@ void initWifi()
return;
}
createSSLCert();
if (radioConfig.has_preferences) {
const char *wifiName = radioConfig.preferences.wifi_ssid;
const char *wifiPsw = radioConfig.preferences.wifi_password;
@@ -117,12 +117,23 @@ void initWifi()
}
}
}
if (!MDNS.begin( "Meshtastic" )) {
DEBUG_MSG("Error setting up MDNS responder!\n");
while (1) {
delay(1000);
}
}
DEBUG_MSG("mDNS responder started\n");
DEBUG_MSG("mDNS Host: Meshtastic.local\n");
MDNS.addService("http", "tcp", 80);
MDNS.addService("https", "tcp", 443);
} else
DEBUG_MSG("Not using WIFI\n");
}
static void initApiServer()
{
// Start API server on port 4403

View File

@@ -15,6 +15,7 @@
#include <WiFi.h>
static bool pinShowing;
static uint32_t doublepressed;
static void startCb(uint32_t pin)
{
@@ -123,6 +124,7 @@ static int gap_event(struct ble_gap_event *event, void *arg)
{
struct ble_gap_conn_desc desc;
int rc;
uint32_t now = millis();
switch (event->type) {
case BLE_GAP_EVENT_CONNECT:
@@ -221,8 +223,17 @@ static int gap_event(struct ble_gap_event *event, void *arg)
if (event->passkey.params.action == BLE_SM_IOACT_DISP) {
pkey.action = event->passkey.params.action;
pkey.passkey = random(
100000, 999999); // This is the passkey to be entered on peer - we pick a number >100,000 to ensure 6 digits
DEBUG_MSG("dp: %d now:%d\n",doublepressed, now);
if (doublepressed > 0 && (doublepressed + (30*1000)) > now)
{
DEBUG_MSG("User has overridden passkey or no display available\n");
pkey.passkey = defaultBLEPin;
}
else {
DEBUG_MSG("Using random passkey\n");
pkey.passkey = random(
100000, 999999); // This is the passkey to be entered on peer - we pick a number >100,000 to ensure 6 digits
}
DEBUG_MSG("*** Enter passkey %d on the peer side ***\n", pkey.passkey);
startCb(pkey.passkey);
@@ -443,6 +454,13 @@ int chr_readwrite8(uint8_t *v, size_t vlen, struct ble_gatt_access_ctxt *ctxt)
return 0; // success
}
void disablePin()
{
DEBUG_MSG("User Override, disabling bluetooth pin requirement\n");
// keep track of when it was pressed, so we know it was within X seconds
doublepressed = millis();
}
// This routine is called multiple times, once each time we come back from sleep
void reinitBluetooth()
{

View File

@@ -15,6 +15,7 @@ void updateBatteryLevel(uint8_t level);
void deinitBLE();
void loopBLE();
void reinitBluetooth();
void disablePin();
/**
* A helper function that implements simple read and write handling for a uint32_t

100
src/nrf52/BQ25713.cpp Normal file
View File

@@ -0,0 +1,100 @@
#include "BQ25713.h"
#include "configuration.h"
#include <Wire.h>
#ifdef BQ25703A_ADDR
const uint8_t BQ25713::devAddr = BQ25703A_ADDR;
bool BQ25713::setup()
{
DEBUG_MSG("Init BQ25713\n");
// if(!writeReg(0x34,0x9034)) return false;
//
// if(!writeReg(0x34,0x8034)) return false;
if (!writeReg(0x00, 0x0F0A))
return false; // Config Charge Option 0
if (!writeReg(0x02, 0x0224))
return false; // Config Charge Current
if (!writeReg(0x04, 0x1070))
return false; // Config Charge Voltage
if (!writeReg(0x06, 0x099C))
return false; // Config OTG Voltage
if (!writeReg(0x08, 0x5000))
return false; // Config OTG Current
// if(!writeReg(0x0A,0x0100)) return false;//Config Input Voltage
if (!writeReg(0x0C, 0x1800))
return false; // Config Minimum System Voltage
if (!writeReg(0x0E, 0x4900))
return false; // Config Input Current
if (!writeReg(0x30, 0xE210))
return false; // Config Charge Option 1
if (!writeReg(0x32, 0x32BF))
return false; // Config Charge Option 2
if (!writeReg(0x34, 0x0834))
return false; // Config Charge Option 3
if (!writeReg(0x36, 0x4A65))
return false; // Config Prochot Option 0
if (!writeReg(0x38, 0x81FF))
return false; // Config Prochot Option 1
if (!writeReg(0x3A, 0xA0FF))
return false; // Config ADC Option
return true;
}
uint16_t BQ25713::readReg(uint8_t reg)
{
Wire.beginTransmission(devAddr);
Wire.write(reg);
byte err = Wire.endTransmission();
if (!err) {
int readLen = 2;
Wire.requestFrom(devAddr, (int)(readLen + 1));
if (Wire.available() >= readLen) {
uint8_t lsb = Wire.read(), msb = Wire.read();
return (((uint16_t)msb) << 8) + lsb;
} else
return 0;
} else {
return 0;
}
}
bool BQ25713::writeReg(uint8_t reg, uint16_t v)
{
Wire.beginTransmission(devAddr);
Wire.write(reg);
Wire.write(v & 0xff);
Wire.write((v >> 8) & 0xff);
byte err = Wire.endTransmission(); // 0 for success
if (!err) {
// Do a test readback for early debugging
uint16_t found = readReg(reg);
if (found != v) {
DEBUG_MSG("Readback reg=0x%0x test failed, expected 0x%0x, found 0x%0x!\n", reg, v, found);
return true; // claim success - FIXME
}
}
return !err;
}
#endif

22
src/nrf52/BQ25713.h Normal file
View File

@@ -0,0 +1,22 @@
#pragma once
#include <Arduino.h>
/**
* Driver class to control/monitor BQ25713 charge controller
*/
class BQ25713 {
static const uint8_t devAddr;
public:
/// Return true for success
bool setup();
private:
uint16_t readReg(uint8_t reg);
/// Return true for success
bool writeReg(uint8_t reg, uint16_t v);
};

View File

@@ -202,6 +202,13 @@ void setupMeshService(void)
// FIXME, turn off soft device access for debugging
static bool isSoftDeviceAllowed = true;
void NRF52Bluetooth::shutdown()
{
// Shutdown bluetooth for minimum power draw
DEBUG_MSG("Disable NRF52 bluetooth\n");
Bluefruit.Advertising.stop();
}
void NRF52Bluetooth::setup()
{
// Initialise the Bluefruit module

View File

@@ -4,5 +4,6 @@ class NRF52Bluetooth
{
public:
void setup();
void shutdown();
};

View File

@@ -1,53 +0,0 @@
#include <OLEDDisplay.h>
class UC1701Spi : public OLEDDisplay
{
private:
uint8_t _rst;
uint8_t _dc;
uint8_t _cs;
public:
UC1701Spi() { setGeometry(GEOMETRY_128_64); }
bool connect()
{
/*
pinMode(_dc, OUTPUT);
pinMode(_cs, OUTPUT);
pinMode(_rst, OUTPUT);
SPI.begin();
SPI.setClockDivider(SPI_CLOCK_DIV2);
// Pulse Reset low for 10ms
digitalWrite(_rst, HIGH);
delay(1);
digitalWrite(_rst, LOW);
delay(10);
digitalWrite(_rst, HIGH);
*/
return true;
}
void display(void) {}
private:
};
#include "variant.h"
#ifdef ERC12864_CS
#include <UC1701.h>
static UC1701 lcd(PIN_SPI_SCK, PIN_SPI_MOSI, ERC12864_CS, ERC12864_CD);
void testLCD()
{
// PCD8544-compatible displays may have a different resolution...
lcd.begin();
// Write a piece of text on the first line...
lcd.setCursor(0, 0);
lcd.print("Hello, World!");
}
#endif

View File

@@ -49,7 +49,7 @@ void getMacAddr(uint8_t *dmac)
NRF52Bluetooth *nrf52Bluetooth;
static bool bleOn = false;
static const bool enableBle = true; // Set to false for easier debugging
static const bool enableBle = false; // Set to false for easier debugging
void setBluetoothEnable(bool on)
{
@@ -64,7 +64,8 @@ void setBluetoothEnable(bool on)
}
}
} else {
DEBUG_MSG("FIXME: implement BLE disable\n");
if(nrf52Bluetooth)
nrf52Bluetooth->shutdown();
}
bleOn = on;
}
@@ -82,6 +83,8 @@ int printf(const char *fmt, ...)
return res;
}
#include "BQ25713.h"
void nrf52Setup()
{
@@ -93,8 +96,11 @@ void nrf52Setup()
// This is the recommended setting for Monitor Mode Debugging
NVIC_SetPriority(DebugMonitor_IRQn, 6UL);
// Not yet on board
// pmu.init();
#ifdef BQ25703A_ADDR
auto *bq = new BQ25713();
if(!bq->setup())
DEBUG_MSG("ERROR! Charge controller init failed\n");
#endif
// Init random seed
// FIXME - use this to get random numbers
@@ -104,4 +110,22 @@ void nrf52Setup()
// randomSeed(r);
DEBUG_MSG("FIXME, call randomSeed\n");
// ::printf("TESTING PRINTF\n");
}
void cpuDeepSleep(uint64_t msecToWake)
{
DEBUG_MSG("FIXME: implement NRF52 deep sleep enter actions\n");
// FIXME, configure RTC to wake us
// FIXME, power down SPI, I2C, RAMs
// FIXME, use system off mode with ram retention for key state?
// FIXME, use non-init RAM per https://devzone.nordicsemi.com/f/nordic-q-a/48919/ram-retention-settings-with-softdevice-enabled
while(1) {
delay(5000);
DEBUG_MSG(".");
}
// FIXME, after wake power up SPI, I2C, RAMs, reinit LORA
DEBUG_MSG("FIXME: implement NRF52 deep sleep wake actions\n");
}

View File

@@ -1,6 +1,7 @@
#include "CryptoEngine.h"
#include "target_specific.h"
#include <Utility.h>
#include "sleep.h"
// FIXME - move getMacAddr/setBluetoothEnable into a HALPlatform class
@@ -26,6 +27,10 @@ void setBluetoothEnable(bool on)
notImplemented("setBluetoothEnable");
}
void cpuDeepSleep(uint64_t msecs) {
notImplemented("cpuDeepSleep");
}
// FIXME - implement real crypto for linux
CryptoEngine *crypto = new CryptoEngine();

View File

@@ -144,17 +144,20 @@ void doDeepSleep(uint64_t msecToWake)
{
DEBUG_MSG("Entering deep sleep for %llu seconds\n", msecToWake / 1000);
#ifndef NO_ESP32
// not using wifi yet, but once we are this is needed to shutoff the radio hw
// esp_wifi_stop();
waitEnterSleep();
notifySleep.notifyObservers(NULL); // also tell the regular sleep handlers
notifyDeepSleep.notifyObservers(NULL);
screen->setOn(false); // datasheet says this will draw only 10ua
nodeDB.saveToDisk();
// Kill GPS power completely (even if previously we just had it in sleep mode)
setGPSPower(false);
setLed(false);
#ifdef RESET_OLED
digitalWrite(RESET_OLED, 1); // put the display in reset before killing its power
#endif
@@ -163,11 +166,6 @@ void doDeepSleep(uint64_t msecToWake)
digitalWrite(VEXT_ENABLE, 1); // turn off the display power
#endif
// Kill GPS power completely (even if previously we just had it in sleep mode)
setGPSPower(false);
setLed(false);
#ifdef TBEAM_V10
if (axp192_found) {
// Obsolete comment: from back when we we used to receive lora packets while CPU was in deep sleep.
@@ -185,57 +183,7 @@ void doDeepSleep(uint64_t msecToWake)
}
#endif
/*
Some ESP32 IOs have internal pullups or pulldowns, which are enabled by default.
If an external circuit drives this pin in deep sleep mode, current consumption may
increase due to current flowing through these pullups and pulldowns.
To isolate a pin, preventing extra current draw, call rtc_gpio_isolate() function.
For example, on ESP32-WROVER module, GPIO12 is pulled up externally.
GPIO12 also has an internal pulldown in the ESP32 chip. This means that in deep sleep,
some current will flow through these external and internal resistors, increasing deep
sleep current above the minimal possible value.
Note: we don't isolate pins that are used for the LORA, LED, i2c, spi or the wake button
*/
static const uint8_t rtcGpios[] = {/* 0, */ 2,
/* 4, */
#ifndef USE_JTAG
13,
/* 14, */ /* 15, */
#endif
/* 25, */ 26, /* 27, */
32, 33, 34, 35,
36, 37
/* 38, 39 */};
for (int i = 0; i < sizeof(rtcGpios); i++)
rtc_gpio_isolate((gpio_num_t)rtcGpios[i]);
// FIXME, disable internal rtc pullups/pulldowns on the non isolated pins. for inputs that we aren't using
// to detect wake and in normal operation the external part drives them hard.
// We want RTC peripherals to stay on
esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON);
#ifdef BUTTON_PIN
// Only GPIOs which are have RTC functionality can be used in this bit map: 0,2,4,12-15,25-27,32-39.
uint64_t gpioMask = (1ULL << BUTTON_PIN);
#ifdef BUTTON_NEED_PULLUP
gpio_pullup_en((gpio_num_t)BUTTON_PIN);
#endif
// Not needed because both of the current boards have external pullups
// FIXME change polarity in hw so we can wake on ANY_HIGH instead - that would allow us to use all three buttons (instead of
// just the first) gpio_pullup_en((gpio_num_t)BUTTON_PIN);
esp_sleep_enable_ext1_wakeup(gpioMask, ESP_EXT1_WAKEUP_ALL_LOW);
#endif
esp_sleep_enable_timer_wakeup(msecToWake * 1000ULL); // call expects usecs
esp_deep_sleep_start(); // TBD mA sleep current (battery)
#endif
cpuDeepSleep(msecToWake);
}
#ifndef NO_ESP32

View File

@@ -4,7 +4,8 @@
#include "Observer.h"
#include "configuration.h"
void doDeepSleep(uint64_t msecToWake);
void doDeepSleep(uint64_t msecToWake), cpuDeepSleep(uint64_t msecToWake);
#ifndef NO_ESP32
#include "esp_sleep.h"
esp_sleep_wakeup_cause_t doLightSleep(uint64_t msecToWake);

View File

@@ -205,10 +205,14 @@ External serial flash WP25R1635FZUIL0
#define PIN_EINK_MOSI (0 + 29) // also called SDI
// Controls power for the eink display - Board power is enabled either by VBUS from USB or the CPU asserting PWR_ON
// FIXME - I think this is actually just the board power enable - it enables power to the CPU also
#define PIN_EINK_PWR_ON (0 + 12)
#define HAS_EINK
// No screen wipes on eink
#define SCREEN_TRANSITION_MSECS 0
#define PIN_SPI1_MISO \
(32 + 7) // FIXME not really needed, but for now the SPI code requires something to be defined, pick an used GPIO
#define PIN_SPI1_MOSI PIN_EINK_MOSI

View File

@@ -0,0 +1,105 @@
/*
Copyright (c) 2014-2015 Arduino LLC. All right reserved.
Copyright (c) 2016 Sandeep Mistry All right reserved.
Copyright (c) 2018, Adafruit Industries (adafruit.com)
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "variant.h"
#include "nrf.h"
#include "wiring_constants.h"
#include "wiring_digital.h"
const uint32_t g_ADigitalPinMap[] = {
// D0 .. D13
25, // D0 is P0.25 (UART TX)
24, // D1 is P0.24 (UART RX
10, // D2 is P0.10 (NFC2)
47, // D3 is P1.15 (LED1)
(32 + 10), // D4 is P1.10 (LED2)
40, // D5 is P1.08
7, // D6 is P0.07
34, // D7 is P1.02 (Switch)
16, // D8 is P0.16 (NeoPixel)
26, // D9 is P0.26 D_RS (IPS data/command control)
27, // D10 is P0.27
6, // D11 is P0.06 D_RES (IPS display reset)
8, // D12 is P0.08 D_CS (IPS display chip select)
41, // D13 is P0.23 BLT (IPS display backlight)
4, // D14 is P0.04 SX1262 RXEN
5, // D15 is P0.05 BOOST_EN (5V buck converter enable for the the radio power)
// D14 .. D21 (aka A0 .. A7)
30, // D16 is P0.30 (A0)
28, // D17 is P0.28 (A1)
2, // D18 is P0.02 (A2)
3, // D19 is P0.03 (A3)
29, // D20 is P0.29 (A4, Battery)
31, // D21 is P0.31 (A5, ARef)
// D22 .. D23 (aka I2C pins)
12, // D22 is P0.12 (SDA)
11, // D23 is P0.11 (SCL)
// D24 .. D26 (aka SPI pins)
15, // D24 is P0.15 (SPI MISO)
13, // D25 is P0.13 (SPI MOSI)
14, // D26 is P0.14 (SPI SCK )
// QSPI pins (not exposed via any header / test point)
// 19, // P0.19 (QSPI CLK)
// 20, // P0.20 (QSPI CS)
// 17, // P0.17 (QSPI Data 0)
// 22, // P0.22 (QSPI Data 1)
// 23, // P0.23 (QSPI Data 2)
// 21, // P0.21 (QSPI Data 3)
// The remaining NFC pin
9, // D27 P0.09 (NFC1, exposed only via test point on bottom of board)
// The following pins were never listed as they were considered unusable
// 0, // P0.00 is XL1 (attached to 32.768kHz crystal) Never expose as GPIOs
// 1, // P0.01 is XL2 (attached to 32.768kHz crystal)
18, // D28 P0.18 is RESET (attached to switch)
// 32, // P1.00 is SWO (attached to debug header)
// D29-D43
32 + 12, // D29 P0.27 E22-SX1262 DIO1
28, // D30 P0.28 E22-SX1262 DIO2
30, // D31 P0.30 E22-SX1262 TXEN
35, // D32 P1.03 E22-SX1262 NSS
32 + 8, // D33 P1.08 E22-SX1262 BUSY
27, // D34 P0.27 E22-SX1262 RESET
32 + 1, // D35 P1.01 BTN_UP
32, // D36 P1.0 GPS power
21, // D37 P0.21 disp_clk
36, // P1.04 BTN_OK
37, // D39 P0.19 disp_SDA
38, // D40 P1.06 BUZZER
39, // P1.07 is not connected per schematic
43, // P1.11 is not connected per schematic
45, // P1.13 is not connected per schematic
};
void initVariant()
{
// LED1 & LED2
pinMode(PIN_LED1, OUTPUT);
ledOff(PIN_LED1);
pinMode(PIN_LED2, OUTPUT);
ledOff(PIN_LED2);
}

View File

@@ -0,0 +1,178 @@
/*
Copyright (c) 2014-2015 Arduino LLC. All right reserved.
Copyright (c) 2016 Sandeep Mistry All right reserved.
Copyright (c) 2018, Adafruit Industries (adafruit.com)
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _VARIANT_LORA_RELAY_V1_
#define _VARIANT_LORA_RELAY_V1_
/** Master clock frequency */
#define VARIANT_MCK (64000000ul)
#define USE_LFXO // Board uses 32khz crystal for LF
// define USE_LFRC // Board uses RC for LF
/*
kevinh todo
ok leds
ok buttons
ok gps power
ok gps signal
ok? lcd
ok buzzer
serial flash
ok lora (inc boost en)
mention dat1 and dat2 on sd card
use hardware spi controller for lcd - not bitbang
*/
/*----------------------------------------------------------------------------
* Headers
*----------------------------------------------------------------------------*/
#include "WVariant.h"
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
// Number of pins defined in PinDescription array
#define PINS_COUNT (43)
#define NUM_DIGITAL_PINS (43)
#define NUM_ANALOG_INPUTS (6) // A6 is used for battery, A7 is analog reference
#define NUM_ANALOG_OUTPUTS (0)
// LEDs
#define PIN_LED1 (3)
#define PIN_LED2 (4)
#define PIN_NEOPIXEL (8)
#define PIN_BUZZER (40)
#define LED_BUILTIN PIN_LED1
#define LED_CONN PIN_LED2
#define LED_RED PIN_LED1
#define LED_BLUE PIN_LED2
#define LED_STATE_ON 1 // State when LED is litted
/*
* Buttons
*/
#define PIN_BUTTON1 (7)
#define PIN_BUTTON2 (35)
#define PIN_BUTTON3 (37)
/*
* Analog pins
*/
#define PIN_A0 (16)
#define PIN_A1 (17)
#define PIN_A2 (18)
#define PIN_A3 (19)
#define PIN_A4 (20)
#define PIN_A5 (21)
static const uint8_t A0 = PIN_A0;
static const uint8_t A1 = PIN_A1;
static const uint8_t A2 = PIN_A2;
static const uint8_t A3 = PIN_A3;
static const uint8_t A4 = PIN_A4;
static const uint8_t A5 = PIN_A5;
#define ADC_RESOLUTION 14
// Other pins
#define PIN_AREF PIN_A5
#define PIN_VBAT PIN_A4
#define PIN_NFC1 (33)
#define PIN_NFC2 (2)
#define PIN_PIEZO (37)
static const uint8_t AREF = PIN_AREF;
/*
* Serial interfaces
*/
#define PIN_SERIAL1_RX (1)
#define PIN_SERIAL1_TX (0)
/*
* SPI Interfaces
*/
#define SPI_INTERFACES_COUNT 1
#define PIN_SPI_MISO (24)
#define PIN_SPI_MOSI (25)
#define PIN_SPI_SCK (26)
static const uint8_t SS = (5);
static const uint8_t MOSI = PIN_SPI_MOSI;
static const uint8_t MISO = PIN_SPI_MISO;
static const uint8_t SCK = PIN_SPI_SCK;
/*
* Wire Interfaces
*/
#define WIRE_INTERFACES_COUNT 1
#define PIN_WIRE_SDA (22)
#define PIN_WIRE_SCL (23)
// I2C device addresses
#define I2C_ADDR_BQ27441 0x55 // Battery gauge
// CUSTOM GPIOs the SX1262
#define SX1262_CS (32)
// If you would prefer to get console debug output over the JTAG ICE connection rather than the CDC-ACM USB serial device, just
// define this. #define USE_SEGGER
#define SX1262_DIO1 (29)
#define SX1262_DIO2 (30)
#define SX1262_BUSY (33) // Supposed to be P0.18 but because of reworks, now on P0.31 (18)
#define SX1262_RESET (34)
// #define SX1262_ANT_SW (32 + 10)
#define SX1262_RXEN (14)
#define SX1262_TXEN (31)
#define SX1262_POWER_EN \
(15) // FIXME, see warning hre https://github.com/BigCorvus/SX1262-LoRa-BLE-Relay/blob/master/LORA_RELAY_NRF52840.ino
#define SX1262_E22 // Indicates this SX1262 is inside of an ebyte E22 module and special config should be done for that
// ST7565 SPI
#define ST7735_RESET (11) // Output
#define ST7735_CS (12)
#define ST7735_BACKLIGHT_EN (13)
#define ST7735_RS (9)
#define ST7735_SDA (39) // actually spi MOSI
#define ST7735_SCK (37) // actually spi clk
#define PIN_GPS_WAKE 36 // Just kill GPS power when we want it to sleep? FIXME
#define GPS_WAKE_ACTIVE 0 // GPS Power output is active low
// #define LORA_DISABLE_SENDING // The board can brownout during lora TX if you don't have a battery connected. Disable sending
// to allow USB power only based debugging
#ifdef __cplusplus
}
#endif
/*----------------------------------------------------------------------------
* Arduino objects - C++ only
*----------------------------------------------------------------------------*/
#endif

View File

@@ -146,6 +146,9 @@ static const uint8_t SCK = PIN_SPI_SCK;
#define SX1262_RESET (0 + 3) // P0.03
#define SX1262_ANT_SW (32 + 10) // P1.10
// To debug via the segger JLINK console rather than the CDC-ACM serial device
#define USE_SEGGER
#ifdef __cplusplus
}
#endif

43
variants/ppr1/variant.cpp Normal file
View File

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

179
variants/ppr1/variant.h Normal file
View File

@@ -0,0 +1,179 @@
/*
Copyright (c) 2014-2015 Arduino LLC. All right reserved.
Copyright (c) 2016 Sandeep Mistry All right reserved.
Copyright (c) 2018, Adafruit Industries (adafruit.com)
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#pragma once
/** Master clock frequency */
#define VARIANT_MCK (64000000ul)
// This board does have a 32khz crystal
#define USE_LFXO // Board uses 32khz crystal for LF
// #define USE_LFRC // Board uses RC for LF
/*----------------------------------------------------------------------------
* Headers
*----------------------------------------------------------------------------*/
#include "WVariant.h"
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
// Number of pins defined in PinDescription array
#define PINS_COUNT (46)
#define NUM_DIGITAL_PINS (46)
#define NUM_ANALOG_INPUTS (0)
#define NUM_ANALOG_OUTPUTS (0)
// LEDs
#define PIN_LED1 (25)
#define PIN_LED2 (11)
#define LED_BUILTIN PIN_LED1
#define LED_CONN PIN_LED2
#define LED_RED PIN_LED1
#define LED_GREEN PIN_LED2
// FIXME, bluefruit automatically blinks this led while connected. call AdafruitBluefruit::autoConnLed to change this.
#define LED_BLUE LED_GREEN
#define LED_STATE_ON 1 // State when LED is litted
/*
* Buttons
*/
#define PIN_BUTTON1 4 // up
#define PIN_BUTTON2 2 // left
#define PIN_BUTTON3 3 // center
#define PIN_BUTTON4 5 // right
#define PIN_BUTTON5 6 // down
/*
* Analog pins
*/
#define PIN_A0 (0xff)
#define PIN_A1 (0xff)
#define PIN_A2 (0xff)
#define PIN_A3 (0xff)
#define PIN_A4 (0xff)
#define PIN_A5 (0xff)
#define PIN_A6 (0xff)
#define PIN_A7 (0xff)
static const uint8_t A0 = PIN_A0;
static const uint8_t A1 = PIN_A1;
static const uint8_t A2 = PIN_A2;
static const uint8_t A3 = PIN_A3;
static const uint8_t A4 = PIN_A4;
static const uint8_t A5 = PIN_A5;
static const uint8_t A6 = PIN_A6;
static const uint8_t A7 = PIN_A7;
#define ADC_RESOLUTION 14
// Other pins
#define PIN_AREF (0xff)
//#define PIN_NFC1 (9)
//#define PIN_NFC2 (10)
static const uint8_t AREF = PIN_AREF;
/*
* Serial interfaces
*/
// GPS is on Serial1
#define PIN_SERIAL1_RX (8)
#define PIN_SERIAL1_TX (9)
// We intentionally leave this undefined so we don't even try to make a Ublox driver
// #define GPS_TX_PIN PIN_SERIAL1_TX
// #define GPS_RX_PIN PIN_SERIAL1_RX
#define PIN_GPS_RESET 29 // active high
#define PIN_GPS_PPS 28
// #define PIN_GPS_WAKE 20 // CELL_CTRL in schematic? based on their example code
#define PIN_GPS_EN 7 // GPS_EN active high
#define PIN_VUSB_EN 21
// LCD
#define PIN_LCD_RESET 23 // active low, pulse low for 20ms at boot
#define USE_ST7567
/// Charge controller I2C address
#define BQ25703A_ADDR 0x6b
// Define if screen should be mirrored left to right
#define SCREEN_MIRROR
// LCD screens are slow, so slowdown the wipe so it looks better
#define SCREEN_TRANSITION_MSECS 1000
#define SCREEN_TRANSITION_FRAMERATE 10 // fps
/*
* SPI Interfaces
*/
#define SPI_INTERFACES_COUNT 1
#define PIN_SPI_MISO (15)
#define PIN_SPI_MOSI (13)
#define PIN_SPI_SCK (12)
// static const uint8_t SS = 44;
static const uint8_t MOSI = PIN_SPI_MOSI;
static const uint8_t MISO = PIN_SPI_MISO;
static const uint8_t SCK = PIN_SPI_SCK;
/*
* Wire Interfaces
*/
#define WIRE_INTERFACES_COUNT 1
#define PIN_WIRE_SDA (32 + 2)
#define PIN_WIRE_SCL (32)
// CUSTOM GPIOs the SX1262
#define SX1262_CS (0 + 10) // FIXME - we really should define LORA_CS instead
#define SX1262_DIO1 (0 + 20)
#define SX1262_DIO2 (0 + 26)
#define SX1262_BUSY (0 + 19)
#define SX1262_RESET (0 + 17)
#define SX1262_TXEN (0 + 24)
#define SX1262_RXEN (0 + 22)
#define SX1262_E22 // Not really an E22 but this board clones using DIO3 for tcxo control
// FIXME, to prevent burning out parts I've set the power level super low, because I don't have
// an antenna wired up
#define SX1262_MAX_POWER 1
#define LORA_DISABLE_SENDING // Define this to disable transmission for testing (power testing etc...)
// To debug via the segger JLINK console rather than the CDC-ACM serial device
#define USE_SEGGER
#ifdef __cplusplus
}
#endif
/*----------------------------------------------------------------------------
* Arduino objects - C++ only
*----------------------------------------------------------------------------*/