Compare commits

..

66 Commits
0.7.6 ... 0.7.8

Author SHA1 Message Date
Kevin Hester
aaa6af3f38 Merge pull request #202 from geeksville/dev
0.7.8 - build with new fixed arduino-esp32 lib
2020-06-20 14:58:19 -07:00
geeksville
b11b322581 0.7.8 2020-06-20 14:53:25 -07:00
geeksville
60b38215ce fix docs per @feh123 2020-06-20 09:58:45 -07:00
geeksville
53e68515dd Merge remote-tracking branch 'root/master' into dev 2020-06-19 13:57:21 -07:00
geeksville
7676ae9184 typo 2020-06-19 13:57:10 -07:00
Kevin Hester
b385feefa5 Merge pull request #201 from geeksville/dev
Fix crypto doc links
2020-06-19 13:50:19 -07:00
Kevin Hester
fc50b4abc0 Merge branch 'master' into dev 2020-06-19 13:47:52 -07:00
geeksville
0104a2eb3a Fix crypto doc links 2020-06-19 13:47:00 -07:00
Kevin Hester
23fdc9d1a9 Merge pull request #195 from geeksville/dev
Dev
2020-06-19 13:30:53 -07:00
geeksville
ea4a678308 Add reviewer comments on crypto 2020-06-19 13:27:31 -07:00
geeksville
6566c4f15e don't send bogus latitudes 2020-06-18 14:09:13 -07:00
geeksville
6f39f1740f add pinetab work queue 2020-06-18 11:57:29 -07:00
geeksville
7b61bdbfd2 Merge remote-tracking branch 'root/master' into dev 2020-06-18 11:50:44 -07:00
geeksville
8e65db19b0 Add notes on linux drivers & pins for pinetab #143 2020-06-18 11:50:04 -07:00
Kevin Hester
698fcdad36 Merge pull request #194 from geeksville/dev
Fix #187, Ublox GPS fixes, see below:
2020-06-18 11:25:45 -07:00
geeksville
c25d6e974f sometimes first read might return 0 for EITHER lat or lon 2020-06-18 11:22:38 -07:00
geeksville
35aae48932 0.7.7 2020-06-18 11:18:53 -07:00
geeksville
f8afa2703f Merge remote-tracking branch 'root/master' into dev 2020-06-18 11:18:15 -07:00
geeksville
cd903dceb9 Fix #187, Ublox GPS fixes, see below:
This was a good one. Two problems
1) We've apparently always been using hte sparkfun API the wrong way, but
but we mostly got lucky.
2) Changing to use the API correctly (asyncronously) exposed a bug in
the library - fixed in a seperate commit
2020-06-18 11:17:01 -07:00
Kevin Hester
5843c6f25e Merge pull request #193 from geeksville/dev
misc fixes
2020-06-17 19:29:14 -07:00
geeksville
3005373760 fix wording of GPS screen messages to be less confusing. Now:
No GPS
No Sats
GPS OK
2020-06-17 17:26:37 -07:00
geeksville
7678540a93 For #187 was not reporting GPS status on new API 2020-06-17 17:25:55 -07:00
geeksville
463666aec5 oops - can't call DEBUG_MSG this early on ESP32 2020-06-17 16:04:37 -07:00
geeksville
5847f94ece Merge remote-tracking branch 'mine/dev' into dev 2020-06-17 15:48:04 -07:00
geeksville
09855b76ef TODO updates 2020-06-17 15:45:49 -07:00
Kevin Hester
f4d476d160 Merge pull request #191 from geeksville/dev
merge cubecell/memory experiments
2020-06-17 11:41:31 -07:00
Kevin Hester
d88d4be63e Merge branch 'master' into dev 2020-06-17 11:39:23 -07:00
geeksville
154114e900 merge cubecell experiments back into master (might delete later) 2020-06-17 11:35:21 -07:00
geeksville
03f019dea2 memory size debugging 2020-06-16 19:55:14 -07:00
geeksville
a47524b762 cubecell wip 2020-06-16 17:13:26 -07:00
geeksville
fd2f5a5ba4 Merge branch 'dev' into cubecell 2020-06-16 16:18:30 -07:00
geeksville
e66b2234f6 Experiment with small ram NRF52s 2020-06-16 15:27:08 -07:00
geeksville
f35b15b09c Shrink devicestate for small mcus 2020-06-16 15:26:30 -07:00
geeksville
99dac51b9d Don't use a (huge - 16KB) scratch buffer for device state loading 2020-06-16 15:02:11 -07:00
geeksville
656faf4ce9 ram investigation notes 2020-06-16 15:01:39 -07:00
geeksville
d9ab6986ad per @dafeman 1.8V works on E22 2020-06-16 12:02:13 -07:00
geeksville
514d45c219 oops supposed to be TXEN 2020-06-16 06:38:08 -07:00
Kevin Hester
94b7fc76c1 Merge pull request #188 from geeksville/ppr
sx1262 for dafeman
2020-06-16 06:30:15 -07:00
geeksville
e9923ac257 fix LCD build for devboard 2020-06-16 06:26:34 -07:00
geeksville
60ad1793e4 sx1262 improvements attn @dafeman 2020-06-16 06:26:21 -07:00
geeksville
96a15bec3b doc updates 2020-06-16 06:25:54 -07:00
Kevin Hester
fba676fc07 Merge pull request #185 from geeksville/bringup
nrf52 backmerge into master
2020-06-15 14:53:11 -07:00
geeksville
9ad14ad98b Cleanup to merge NR52 support back into mainline 2020-06-15 14:47:14 -07:00
geeksville
477c62082d E22 SX1262 module now works!
Thanks mostly to an old github comment by @beegee-tokyo the fix was easy
(comment here https://github.com/jgromes/RadioLib/issues/12#issuecomment-520450429)

We now set DIO3 to 2.4 volts to power the oscillator inside the E22
module (undocumented in the E22 docs)
2020-06-15 14:38:09 -07:00
geeksville
82169d4115 make recent changes work on non ESP hardware 2020-06-15 13:32:06 -07:00
geeksville
362d5452d5 remove unused chip 2020-06-15 13:31:53 -07:00
geeksville
92e5a15399 Merge branch 'master' into cubecell 2020-06-15 12:42:01 -07:00
geeksville
114e0c4ada Merge branch 'master' into bringup 2020-06-15 12:41:22 -07:00
Kevin Hester
075ff26499 @mrvdb added support for SH1106 displays!
Add support for SH1106 controller
2020-06-15 12:29:59 -07:00
Kevin Hester
d65f2ede81 Merge branch 'master' into sh1106-support 2020-06-15 12:26:12 -07:00
Kevin Hester
4a9248a451 @zombodotcom added support for optional external GPS on heltec lora v2!
Fixed GPS pin Definitions for Heltec Lora V2
2020-06-15 12:25:56 -07:00
Zombodotcom
1c6092c430 Fixed GPS pin Definitions 2020-06-15 11:38:15 -06:00
Kevin Hester
0e9ed1e82f Merge pull request #183 from geeksville/dev
Dev
2020-06-15 07:19:45 -07:00
geeksville
02ce0558b9 Merge remote-tracking branch 'root/master' into dev 2020-06-15 07:13:34 -07:00
geeksville
63110f0134 Merge remote-tracking branch 'mine/dev' into dev 2020-06-15 07:12:31 -07:00
geeksville
d8db4449be 0.7.6 2020-06-15 07:04:03 -07:00
geeksville
fda98bbf58 oops BLE auth should not change 2020-06-14 15:52:06 -07:00
geeksville
aadba1f694 add printPacket for debug printing packets 2020-06-14 15:30:42 -07:00
geeksville
2c8d152885 Use old style (pre BLE 4.2) pairing, it seems more reliable 2020-06-14 15:30:21 -07:00
Marcel van der Boom
37c598833c Add support for SH1106 controller
The SH1106 is almost indistinguisable from a SSD1306.

- the nr of columns in the sh1106 is 132 vs 128
- use the proper includes/library functions when in use
2020-06-14 10:28:23 +02:00
geeksville
e382a181f7 Merge remote-tracking branch 'root/master' into dev 2020-06-13 16:50:01 -07:00
geeksville
f02a2c0853 Merge branch 'usb' into bringup 2020-06-09 18:20:34 -07:00
geeksville
71a4cfefd5 bringup WIP 2020-06-08 15:01:55 -07:00
geeksville
1c63a70673 cubecell WIP 2020-06-05 17:30:09 -07:00
geeksville
8022f3b920 Merge branch 'master' into bringup 2020-06-05 16:02:54 -07:00
geeksville
4db176867b WIP - bringup on PPR 2020-06-05 11:00:58 -07:00
59 changed files with 758 additions and 264 deletions

View File

@@ -168,7 +168,7 @@ Hard resetting via RTS pin...
# Meshtastic Android app # Meshtastic Android app
The companion (optional) Meshtastic Android app is [here](https://github.com/meshtastic/Meshtastic-Android). You can also download it on Google Play. The companion (optional) Meshtastic Android app is [here](https://play.google.com/store/apps/details?id=com.geeksville.mesh&referrer=utm_source%3Dgithub-dev-readme). You can also download it on Google Play.
# Python API # Python API

3
bin/dump-ram-users.sh Executable file
View File

@@ -0,0 +1,3 @@
arm-none-eabi-readelf -s -e .pio/build/nrf52dk/firmware.elf | head -80
nm -CSr --size-sort .pio/build/nrf52dk/firmware.elf | grep '^200'

View File

@@ -1,3 +1,3 @@
export VERSION=0.7.5 export VERSION=0.7.8

View File

@@ -28,7 +28,7 @@ Not all of these features are fully implemented yet - see **important** disclaim
- Shows direction and distance to all members of your channel - Shows direction and distance to all members of your channel
- Directed or broadcast text messages for channel members - Directed or broadcast text messages for channel members
- Open and extensible codebase supporting multiple hardware vendors - no lock in to one vendor - Open and extensible codebase supporting multiple hardware vendors - no lock in to one vendor
- Communication API for bluetooth devices (such as our Android app) to use the mesh. An iOS application is in the works. And [Meshtastic-python](https://pypi.org/project/meshtastic/) provides access from desktop computers. - Communication API for bluetooth devices (such as our Android app) to use the mesh. An iOS application is in the works. And [Meshtastic-python](https://pypi.org/project/meshtastic/) provides access from desktop computers.
- Very easy sharing of private secured channels. Just share a special link or QR code with friends and they can join your encrypted mesh - Very easy sharing of private secured channels. Just share a special link or QR code with friends and they can join your encrypted mesh
This project is currently in beta testing but it is fairly stable and feature complete - if you have questions please [join our discussion forum](https://meshtastic.discourse.group/). This project is currently in beta testing but it is fairly stable and feature complete - if you have questions please [join our discussion forum](https://meshtastic.discourse.group/).
@@ -51,7 +51,7 @@ Note: Updates are happening almost daily, only major updates are listed below. F
Our Android application is available here: Our Android application is available here:
[![Download at https://play.google.com/store/apps/details?id=com.geeksville.mesh](https://play.google.com/intl/en_us/badges/static/images/badges/en_badge_web_generic.png)](https://play.google.com/store/apps/details?id=com.geeksville.mesh&referrer=utm_source%3Dhomepage%26anid%3Dadmob) [![Download at https://play.google.com/store/apps/details?id=com.geeksville.mesh](https://play.google.com/intl/en_us/badges/static/images/badges/en_badge_web_generic.png)](https://play.google.com/store/apps/details?id=com.geeksville.mesh&referrer=utm_source%3Dgithub-homepage)
The link above will return older more stable releases. We would prefer if you join our alpha-test group, because the application is rapidly improving. Three steps to opt-in to the alpha- test: The link above will return older more stable releases. We would prefer if you join our alpha-test group, because the application is rapidly improving. Three steps to opt-in to the alpha- test:

View File

@@ -4,7 +4,7 @@ This project is still pretty young but moving at a pretty good pace. Not all fea
Most of these problems should be solved by the beta release (within three months): Most of these problems should be solved by the beta release (within three months):
- We don't make these devices and they haven't been tested by UL or the FCC. If you use them you are experimenting and we can't promise they won't burn your house down ;-) - We don't make these devices and they haven't been tested by UL or the FCC. If you use them you are experimenting and we can't promise they won't burn your house down ;-)
- The encryption [implementation](software/crypto.md) has not been reviewed by an expert. (Are you an expert? Please help us) - The encryption implementation is good but see this list of [caveats](software/crypto.md#summary-of-strengthsweaknesses-of-our-current-implementation) to determine risks you might face.
- A number of (straightforward) software work items have to be completed before battery life matches our measurements, currently battery life is about three days. Join us on chat if you want the spreadsheet of power measurements/calculations. - A number of (straightforward) software work items have to be completed before battery life matches our measurements, currently battery life is about three days. Join us on chat if you want the spreadsheet of power measurements/calculations.
- The Android API needs to be documented better - The Android API needs to be documented better
- No one has written an iOS app yet. But some good souls [are talking about it](https://github.com/meshtastic/Meshtastic-esp32/issues/14) ;-) - No one has written an iOS app yet. But some good souls [are talking about it](https://github.com/meshtastic/Meshtastic-esp32/issues/14) ;-)

View File

@@ -0,0 +1,6 @@
https://heltec-automation-docs.readthedocs.io/en/latest/cubecell/index.html
https://github.com/HelTecAutomation/ASR650x-Arduino?utm_source=platformio.org&utm_medium=docs
* Either portfreertos or make not theaded versions of Lock, WorkerThread, Queue (probably the latter).

View File

@@ -1,37 +1,33 @@
# High priority # Geeksville's current work queue
- why is the net so chatty now? You probably don't care about this section - skip to the next one.
- do a release
- device wakes, turns BLE on and phone doesn't notice (while phone was sitting in auto-connect) - bluetooth toggle enable stress test, we are not properly restarting our connect
- E22 bringup - make new android release
- encryption review findings writeup - check in our modified arduino binaries
- turn on modem-sleep mode - https://github.com/espressif/arduino-esp32/issues/1142#issuecomment-512428852 - post bug on esp32-arduino
- implement first cut of router mode: preferentially handle flooding, and change sleep and GPS behaviors
- let users set arbitrary params in android
- NRF52 BLE support
# Medium priority # Medium priority
Items to complete before the first beta release. Items to complete before 1.0.
- turn on watchdog timer (because lib code seems buggy) # Post 1.0 ideas
- show battery level as % full
- rx signal measurements -3 marginal, -9 bad, 10 great, -10 means almost unusable. So scale this into % signal strength. preferably as a graph, with an X indicating loss of comms.
# Pre-beta priority
During the beta timeframe the following improvements 'would be nice'
- finish DSR for unicast - finish DSR for unicast
- check fcc rules on duty cycle. we might not need to freq hop. https://www.sunfiretesting.com/LoRa-FCC-Certification-Guide/ . Might need to add enforcement for europe though. - check fcc rules on duty cycle. we might not need to freq hop. https://www.sunfiretesting.com/LoRa-FCC-Certification-Guide/ . Might need to add enforcement for europe though.
- pick channel center frequency based on channel name? "dolphin" would hash to 900Mhz, "cat" to 905MHz etc? allows us to hide the concept of channel # from hte user.
- make a no bluetooth configured yet screen - include this screen in the loop if the user hasn't yet paired - make a no bluetooth configured yet screen - include this screen in the loop if the user hasn't yet paired
- if radio params change fundamentally, discard the nodedb - if radio params change fundamentally, discard the nodedb
- re-enable the bluetooth battery level service on the T-BEAM - re-enable the bluetooth battery level service on the T-BEAM
- implement first cut of router mode: preferentially handle flooding, and change sleep and GPS behaviors
- provide generalized (but slow) internet message forwarding service if one of our nodes has internet connectivity (MQTT) [ Not a requirement but a personal interest ] - provide generalized (but slow) internet message forwarding service if one of our nodes has internet connectivity (MQTT) [ Not a requirement but a personal interest ]
# Low priority # Low priority ideas
Items after the first final candidate release. Items after the first final candidate release.
- dynamic frequency scaling could save a lot of power on ESP32, but it seems to corrupt uart (even with ref_tick set correctly)
- Change back to using a fixed sized MemoryPool rather than MemoryDynamic (see bug #149) - Change back to using a fixed sized MemoryPool rather than MemoryDynamic (see bug #149)
- scan to find channels with low background noise? (Use CAD mode of the RF95 to automatically find low noise channels) - scan to find channels with low background noise? (Use CAD mode of the RF95 to automatically find low noise channels)
- If the phone doesn't read fromradio mailbox within X seconds, assume the phone is gone and we can stop queing location msgs - If the phone doesn't read fromradio mailbox within X seconds, assume the phone is gone and we can stop queing location msgs
@@ -60,6 +56,7 @@ Items after the first final candidate release.
- add a watchdog timer - add a watchdog timer
- handle millis() rollover in GPS.getTime - otherwise we will break after 50 days - handle millis() rollover in GPS.getTime - otherwise we will break after 50 days
- report esp32 device code bugs back to the mothership via android - report esp32 device code bugs back to the mothership via android
- change BLE bonding to something more secure. see comment by pSecurity->setAuthenticationMode(ESP_LE_AUTH_BOND)
# Spinoff project ideas # Spinoff project ideas

View File

@@ -7,7 +7,7 @@ in these instructions I describe use of their command line tool.
2. Install [PlatformIO](https://platformio.org/platformio-ide) 2. Install [PlatformIO](https://platformio.org/platformio-ide)
3. Download this git repo and cd into it 3. Download this git repo and cd into it
4. Run `git submodule update --init --recursive` to pull in dependencies this project needs. 4. Run `git submodule update --init --recursive` to pull in dependencies this project needs.
5. If you are outside the USA, edit [platformio.ini](/platformio.ini) to set the correct frequency range for your country. The line you need to change starts with `hw_version` and instructions are provided above that line. Options are provided for `EU433`, `EU835`, `CN`, `JP` and `US` (default). Pull-requests eagerly accepted for other countries. 5. If you are outside the USA, run "export COUNTRY=EU865" (or whatever) to set the correct frequency range for your country. Options are provided for `EU433`, `EU865`, `CN`, `JP` and `US` (default). Pull-requests eagerly accepted for other countries.
6. Plug the radio into your USB port 6. Plug the radio into your USB port
7. Type `pio run --environment XXX -t upload` (This command will fetch dependencies, build the project and install it on the board via USB). For XXX, use the board type you have (either `tbeam`, `heltec`, `ttgo-lora32-v1`, `ttgo-lora32-v2`). 7. Type `pio run --environment XXX -t upload` (This command will fetch dependencies, build the project and install it on the board via USB). For XXX, use the board type you have (either `tbeam`, `heltec`, `ttgo-lora32-v1`, `ttgo-lora32-v2`).
8. Platform IO also installs a very nice VisualStudio Code based IDE, see their [tutorial](https://docs.platformio.org/en/latest/tutorials/espressif32/arduino_debugging_unit_testing.html) if you'd like to use it. 8. Platform IO also installs a very nice VisualStudio Code based IDE, see their [tutorial](https://docs.platformio.org/en/latest/tutorials/espressif32/arduino_debugging_unit_testing.html) if you'd like to use it.

View File

@@ -5,33 +5,47 @@ the project developers are not cryptography experts. Therefore we ask two things
- If you are a cryptography expert, please review these notes and our questions below. Can you help us by reviewing our - If you are a cryptography expert, please review these notes and our questions below. Can you help us by reviewing our
notes below and offering advice? We will happily give as much or as little credit as you wish ;-). notes below and offering advice? We will happily give as much or as little credit as you wish ;-).
- Consider our existing solution 'alpha' and probably fairly secure against a not particularly aggressive adversary. But until - Consider our existing solution 'alpha' and probably fairly secure against a not particularly aggressive adversary
it is reviewed by someone smarter than us, assume it might have flaws. (but we can't yet make a more confident statement).
## Notes on implementation ## Summary of strengths/weaknesses of our current implementation
Based on comments from reviewers (see below), here's some tips for usage of these radios. So you can know the level of protection offered:
* It is pretty likely that the AES256 security is implemented 'correctly' and an observer will not be able to decode your messages.
* Warning: If an attacker is able to get one of the radios in their position, they could either a) extract the channel key from that device or b) use that radio to listen to new communications.
* Warning: If an attacker is able to get the "Channel QR code/URL" that you share with others - that attacker could then be able to read any messages sent on the channel (either tomorrow or in the past - if they kept a raw copy of those broadcast packets)
Possible future areas of work (if there is enough interest - post in our [forum](https://meshtastic.discourse.group) if you want this):
1. Optionally requiring users to provide a PIN to regain access to the mesh. This could be based on: intentionally locking the device, time since last use, or any member could force all members to reauthenticate,
2. Until a device reauthenticates, any other access via BLE or USB would be blocked (this would protect against attackers who are not prepared to write custom software to extract and reverse engineer meshtastic flash memory)
3. Turning on read-back protection in the device fuse-bits (this would extend protection in #2 to block all but **extremely** advanced attacks involving chip disassembly)
4. Time limiting keys used for message transmission and automatically cycling them on a schedule. This would protect past messages from being decoded even if an attacker learns the current key.
### Notes for reviewers
If you are reviewing our implementation, this is a brief statement of our method.
- We do all crypto at the SubPacket (payload) level only, so that all meshtastic nodes will route for others - even those channels which are encrypted with a different key. - We do all crypto at the SubPacket (payload) level only, so that all meshtastic nodes will route for others - even those channels which are encrypted with a different key.
- Mostly based on reading [Wikipedia](<https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Counter_(CTR)>) and using the modes the ESP32 provides support for in hardware. - Mostly based on reading [Wikipedia](<https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Counter_(CTR)>) and using the modes the ESP32 provides support for in hardware.
- We use AES256-CTR as a stream cypher (with zero padding on the last BLOCK) because it is well supported with hardware acceleration. - We use AES256-CTR as a stream cypher (with zero padding on the last BLOCK) because it is well supported with hardware acceleration.
Parameters for our CTR implementation:
- Our AES key is 128 or 256 bits, shared as part of the 'Channel' specification. - Our AES key is 128 or 256 bits, shared as part of the 'Channel' specification.
- Each SubPacket will be sent as a series of 16 byte BLOCKS. - The node number concatenated with the packet number is used as the NONCE. This nonce will be stored in flash in the device and should essentially never repeat. If the user makes a new 'Channel' (i.e. picking a new random 256 bit key), the packet number will start at zero.
- The node number concatenated with the packet number is used as the NONCE. This counter will be stored in flash in the device and should essentially never repeat. If the user makes a new 'Channel' (i.e. picking a new random 256 bit key), the packet number will start at zero. The packet number is sent - The packet number is sent in cleartext with each packet. The node number can be derived from the "from" field of each packet. (Cleartext is acceptable because it merely provides IV for each encryption run)
in cleartext with each packet. The node number can be derived from the "from" field of each packet. - Each 16 byte BLOCK for a packet has an incrementing COUNTER. COUNTER starts at zero for the first block of each packet.
- Each BLOCK for a packet has an incrementing COUNTER. COUNTER starts at zero for the first block of each packet. - The IV for each block is constructed by concatenating the NONCE as the upper 96 bits of the IV and the COUNTER as the bottom 32 bits. Since our packets are small counter portion will really never be higher than 32 (five bits).
- The IV for each block is constructed by concatenating the NONCE as the upper 96 bits of the IV and the COUNTER as the bottom 32 bits. Note: since our packets are small counter will really never be higher than 32 (five bits).
``` ## Comments from reviewer #1
You can encrypt separate messages by dividing the nonce_counter buffer in two areas: the first one used for a per-message nonce, handled by yourself, and the second one updated by this function internally.
For example, you might reserve the first 12 bytes for the per-message nonce, and the last 4 bytes for internal use. In that case, before calling this function on a new message you need to set the first 12 bytes of nonce_counter to your chosen nonce value, the last 4 to 0, and nc_off to 0 (which will cause stream_block to be ignored). That way, you can encrypt at most 2**96 messages of up to 2**32 blocks each with the same key.
The per-message nonce (or information sufficient to reconstruct it) needs to be communicated with the ciphertext and must be unique. The recommended way to ensure uniqueness is to use a message counter. An alternative is to generate random nonces, but this limits the number of messages that can be securely encrypted: for example, with 96-bit random nonces, you should not encrypt more than 2**32 messages with the same key. This reviewer is a cryptography professional, but would like to remain anonymous. We thank them for their comments ;-):
Note that for both stategies, sizes are measured in blocks and that an AES block is 16 bytes. I'm assuming that meshtastic is being used to hike in places where someone capable is trying to break it - like you were going to walk around DefCon using these. I spent about an hour reviewing the encryption, and have the following notes:
```
## Remaining todo * The write-up isn't quite as clear as the code.
* The code is using AES-CTR mode correctly to ensure confidentiality.
* The comment for initNonce really covers the necessary information.
* I think the bigger encryption question is "what does the encryption need to do"? As it stands, an attacker who has yet to capture any of the devices cannot reasonably capture text or location data. An attacker who captures any device in the channel/mesh can read everything going to that device, everything stored on that device, and any other communication within the channel that they captured in encrypted form. If that capability basically matches your expectations, it is suitable for whatever adventures this was intended for, then, based on information publicly available or widely disclosed, the encryption is good. If those properties are distressing (like, device history is deliberately limited and you don't want a device captured today to endanger the information sent over the channel yesterday) we could talk about ways to achieve that (most likely synchronizing time and replacing the key with its own SHA256 every X hours, and ensuring the old key is not retained unnecessarily).
* Two other things to keep in mind are that AES-CTR does not itself provide authenticity (e.g. an attacker can flip bits in replaying data and scramble the resulting plaintext), and that the current scheme gives some hints about transmission in the size. So, if you worry about an adversary deliberately messing-up messages or knowing the length of a text message, it looks like those might be possible.
- Have the app change the crypto key when the user generates a new channel I'm guessing that the network behaves somewhat like a store-and-forward network - or, at least, that the goal is to avoid establishing a two-way connection to transmit data. I'm afraid I haven't worked with mesh networks much, but remember studying them briefly in school about ten years ago.

View File

@@ -0,0 +1,16 @@
# esp32-arduino build instructions
We build our own custom version of esp32-arduino, in order to get some fixes we've made but haven't yet been merged in master.
These are a set of currently unformatted notes on how to build and install them. Most developers should not care about this, because
you'll automatically get our fixed libraries.
```
last EDF release in arduino is: https://github.com/espressif/arduino-esp32/commit/1977370e6fc069e93ffd8818798fbfda27ae7d99
IDF release/v3.3 46b12a560
IDF release/v3.3 367c3c09c
https://docs.espressif.com/projects/esp-idf/en/release-v3.3/get-started/linux-setup.html
kevinh@kevin-server:~/development/meshtastic/esp32-arduino-lib-builder\$ python /home/kevinh/development/meshtastic/esp32-arduino-lib-builder/esp-idf/components/esptool*py/esptool/esptool.py --chip esp32 --port /dev/ttyUSB0 --baud 921600 --before default_reset --after hard_reset write_flash -z --flash_mode dout --flash_freq 40m --flash_size detect 0x1000 /home/kevinh/development/meshtastic/esp32-arduino-lib-builder/build/bootloader/bootloader.bin
cp -a out/tools/sdk/* components/arduino/tools/sdk
cp -ar components/arduino/ ~/.platformio/packages/framework-arduinoespressif32@src-fba9d33740f719f712e9f8b07da6ea13/
```

View File

@@ -2,11 +2,24 @@
## Misc work items ## Misc work items
RAM investigation.
nRF52832-QFAA 64KB ram, 512KB flash vs
nrf52832-QFAB 32KB ram, 512kb flash
nrf52840 256KB RAM, 1MB flash
platform.json
"framework-arduinoadafruitnrf52": {
"type": "framework",
"optional": true,
"version": "https://github.com/meshtastic/Adafruit_nRF52_Arduino.git"
},
## Initial work items ## Initial work items
Minimum items needed to make sure hardware is good. Minimum items needed to make sure hardware is good.
- set power UICR per https://devzone.nordicsemi.com/f/nordic-q-a/28562/nrf52840-regulator-configuration - DONE set power UICR per https://devzone.nordicsemi.com/f/nordic-q-a/28562/nrf52840-regulator-configuration
- switch charge controller into / out of performance mode (see 8.3.1 in datasheet) - switch charge controller into / out of performance mode (see 8.3.1 in datasheet)
- write UC1701 wrapper - write UC1701 wrapper
- Test hardfault handler for null ptrs (if one isn't already installed) - Test hardfault handler for null ptrs (if one isn't already installed)

27
docs/software/pinetab.md Normal file
View File

@@ -0,0 +1,27 @@
# Pinetab
These are **preliminary** notes on support for Meshtastic in the Pinetab.
A RF95 is connected via a CS341 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
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/
## 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
Use ARM linux: https://platformio.org/platforms/linux_arm
And linux native: https://platformio.org/platforms/native
* Test cs341 driver - just test reading/writing a register and detecting interrupts, confirm can see rf95
* Make a radiolib spi module that targets the cs341 (and builds on linux)
* use new radiolib module to hook pinebook lora to meshtastic, confirm mesh discovery works
* Make a subclass of StreamAPI that works as a posix TCP server
* Use new TCP endpoint from meshtastic-python

View File

@@ -0,0 +1,202 @@
23K + messages
+ heap of 70ish packets, 300ish bytes per packet: 20KB
+ 14KB soft device RAM
With max length Data inside the packet
Size of NodeInfo 104
Size of SubPacket 272
Size of MeshPacket 304
If Data was smaller: for 70 data packets we would save 7KB. We would need to make SubPacket.data and MeshPacket.encrypted into "type:FT_POINTER" - variably sized mallocs
Size of NodeInfo 104
Size of SubPacket 96
Size of MeshPacket 292 (could have been much smaller but I forgot to shrink MeshPacket.encrypted)
therefore:
a) we should store all ToPhone message queued messages compressed as protobufs (since they will become that anyways)
b) shrink packet pool size because none of that storage will be used for ToPhone packets
c) don't allocate any storage in RAM for the tophone messages we save inside device state, instead just use nanopb callbacks to save/load those
d) a smarter MeshPacket in memory representation would save about 7KB of RAM. call pb_release before freeing each freshly malloced MeshPacket
- nrf52 free memory https://learn.adafruit.com/bluefruit-nrf52-feather-learning-guide/hathach-memory-map
2000790c 00003558 B devicestate // 16KB
2000b53c 00001000 b _cache_buffer // 4KB flash filesystem support
20003b1c 000006b0 B console
2000d5f4 00000400 b vApplicationGetTimerTaskMemory::uxTimerTaskStack
2000da04 00000400 b _acUpBuffer
2000c558 0000036c B Bluefruit
2000c8d8 00000358 b _cdcd_itf
2000e54c 00000258 B _midid_itf
2000d0dc 00000200 b ucStaticTimerQueueStorage.9390
2000e044 00000200 b _mscd_buf
2000e284 000001cc b _vendord_itf
2000d410 00000190 b vApplicationGetIdleTaskMemory::uxIdleTaskStack
2000374c 0000016c D __global_locale
2000de48 0000012c B USBDevice
2000afa4 00000100 b Router::send(_MeshPacket*)::bytes
2000aea4 00000100 b Router::perhapsDecode(_MeshPacket*)::bytes
200039b0 000000f4 B powerFSM
20004258 000000f0 B screen
2000cd7c 000000c4 b _dcd
2000cc68 000000c0 b _usbd_qdef_buf
2000b3c4 000000bc B Wire
2000cef4 000000a8 B Serial2
2000ce4c 000000a8 B Serial1
2000e498 000000a8 B _SEGGER_RTT
2000b498 000000a4 B InternalFS
2000dfb8 0000008c b _hidd_itf
2000b260 00000088 b meshtastic::normalFrames
2000cfdc 00000064 b pxReadyTasksLists
2000b340 00000060 b meshtastic::drawTextMessageFrame(OLEDDisplay*, OLEDDisplayUiState*, short, short)::tempBuf
200036ec 00000060 d impure_data
2000b104 00000060 B bledfu
2000b0a4 00000060 B blebas
20003684 00000058 D _usbd_qdef
200038c0 00000058 d tzinfo
2000d5a0 00000054 b vApplicationGetTimerTaskMemory::xTimerTaskTCB
2000d3bc 00000054 b vApplicationGetIdleTaskMemory::xIdleTaskTCB
2000d308 00000050 b xStaticTimerQueue.9389
2000b1f4 00000050 B hrmc
2000b1a4 00000050 B bslc
20004360 0000004c B service
2000d374 00000048 b m_cb
2000df74 00000042 b _desc_str
2000cd3c 00000040 b _usbd_ctrl_buf
20004214 00000040 B realRouter
2000e244 00000040 b _mscd_itf
2000b164 00000040 B bledis
20003634 00000038 d _InternalFSConfig
2000cc30 00000031 b _usbd_dev
2000398c 00000020 B periodicScheduler
2000cfa4 00000020 b callbacksInt
2000de10 0000001f b fw_str.13525
20003974 00000018 b object.9934
2000ae68 00000018 B nodeDB
2000366c 00000018 d _cache
2000b314 00000014 b meshtastic::drawNodeInfo(OLEDDisplay*, OLEDDisplayUiState*, short, short)::signalStr
2000b300 00000014 b meshtastic::drawNodeInfo(OLEDDisplay*, OLEDDisplayUiState*, short, short)::lastStr
2000b2ec 00000014 b meshtastic::drawNodeInfo(OLEDDisplay*, OLEDDisplayUiState*, short, short)::distStr
200041e0 00000014 b getDeviceName()::name
2000d0b8 00000014 b xTasksWaitingTermination
2000d0a4 00000014 b xSuspendedTaskList
2000d08c 00000014 b xPendingReadyList
2000d06c 00000014 b xDelayedTaskList2
2000d058 00000014 b xDelayedTaskList1
2000d2f0 00000014 b xActiveTimerList2
2000d2dc 00000014 b xActiveTimerList1
2000b480 00000014 B SPI
2000c8c4 00000014 B Serial
2000cd28 00000014 b _ctrl_xfer
2000de30 00000011 b serial_str.13534
2000c544 00000010 b BLEAdvertising::_start(unsigned short, unsigned short)::gap_adv
20003614 00000010 d meshtastic::btPIN
2000434c 00000010 b sendOwnerPeriod
2000ae8c 00000010 b staticPool
2000e484 00000010 B xQueueRegistry
20003b04 00000010 B stateSERIAL
20003af4 00000010 B stateSDS
20003ae4 00000010 B stateON
20003ad4 00000010 B stateNB
20003ac4 00000010 B stateLS
20003ab4 00000010 B stateDARK
20003aa4 00000010 B stateBOOT
200041f8 00000010 B ledPeriodic
2000b244 00000010 B hrms
2000d9f4 00000010 b _acDownBuffer
2000b3b8 0000000c B preflightSleep
20004208 0000000c B powerStatus
2000e540 0000000c B nrf_nvic_state
2000b3ac 0000000c B notifySleep
2000b3a0 0000000c B notifyDeepSleep
2000e463 0000000b b __tzname_std
2000e458 0000000b b __tzname_dst
2000b338 00000008 b meshtastic::estimatedHeading(double, double)::oldLon
2000b330 00000008 b meshtastic::estimatedHeading(double, double)::oldLat
200041d0 00000008 b zeroOffsetSecs
2000ae80 00000008 b spiSettings
200038b8 00000008 D _tzname
20003b14 00000008 B noopPrint
2000cfc4 00000008 b channelMap
2000cf9c 00000008 b callbackDeferred
200043ac 00000006 b ourMacAddr
2000435c 00000004 b MeshService::onGPSChanged(void*)::lastGpsSend
2000b32c 00000004 b meshtastic::estimatedHeading(double, double)::b
2000b328 00000004 b meshtastic::drawNodeInfo(OLEDDisplay*, OLEDDisplayUiState*, short, short)::simRadian
2000362c 00000004 d meshtastic::Screen::setup()::bootFrames
20003628 00000004 d meshtastic::Screen::handleStartBluetoothPinScreen(unsigned long)::btFrames
200039ac 00000004 b onEnter()::lastPingMs
2000ae9c 00000004 b generatePacketId()::i
2000ae88 00000004 B RadioLibInterface::instance
2000b2e8 00000004 b meshtastic::nodeIndex
20003610 00000004 d meshtastic::targetFramerate
2000c554 00000004 B BLEService::lastService
200041cc 00000004 b timeStartMsec
200036dc 00000004 d sbrk_heap_top
2000d364 00000004 b _loopHandle
2000c540 00000004 b guard variable for BLEAdvertising::_start(unsigned short, unsigned short)::gap_adv
2000d0d0 00000004 b xYieldPending
2000d35c 00000004 b xTimerTaskHandle
2000d358 00000004 b xTimerQueue
2000d0cc 00000004 b xTickCount
2000d0a0 00000004 b xSchedulerRunning
2000d088 00000004 b xNumOfOverflows
2000d084 00000004 b xNextTaskUnblockTime
2000d304 00000004 b xLastTime.9343
2000d080 00000004 b xIdleTaskHandle
2000d054 00000004 b uxTopReadyPriority
2000d050 00000004 b uxTaskNumber
2000d04c 00000004 b uxSchedulerSuspended
2000d048 00000004 b uxPendedTicks
2000d044 00000004 b uxDeletedTasksWaitingCleanUp
2000d040 00000004 b uxCurrentNumberOfTasks
2000d360 00000004 b uxCriticalNesting
2000cc64 00000004 b _usbd_q
2000e478 00000004 B _timezone
200036e0 00000004 D SystemCoreClock
2000c53c 00000004 b _sem
2000d0d8 00000004 b pxOverflowTimerList
2000cfd8 00000004 b pxOverflowDelayedTaskList
2000cfd4 00000004 b pxDelayedTaskList
2000d0d4 00000004 b pxCurrentTimerList
2000cfd0 00000004 B pxCurrentTCB
2000e470 00000004 b prev_tzenv
2000360c 00000004 D preftmp
20003608 00000004 D preffile
2000b25c 00000004 B nrf52Bluetooth
2000d370 00000004 b m_usbevt_handler
2000d36c 00000004 b m_sleepevt_handler
2000d368 00000004 b m_pofwarn_handler
2000e454 00000004 B __malloc_sbrk_start
2000e450 00000004 B __malloc_free_list
2000e480 00000004 B MAIN_MonCnt
2000e47c 00000004 b initial_env
200036e8 00000004 D _impure_ptr
200041d8 00000004 B gps
2000e7a4 00000004 B errno
20003918 00000004 D environ
2000cfcc 00000004 b enabled
2000ae64 00000004 B displayedNodeNum
2000e474 00000004 B _daylight
2000b254 00000004 B crypto
2000ce44 00000004 B count_duration
2000de0c 00000004 b _cb_task
2000de08 00000004 b _cb_queue
2000de04 00000004 b _cb_qdepth
2000de44 00000004 B bootloaderVersion
200041f5 00000001 b ledBlinker()::ledOn
20003604 00000001 d loop::showingBootScreen
200041f4 00000001 b loop::wasPressed
2000b494 00000001 b DefaultFontTableLookup(unsigned char)::LASTCHAR
2000aea0 00000001 b generatePacketId()::didInit
20003624 00000001 d meshtastic::prevFrame
2000b258 00000001 b bleOn
200041dc 00000001 B timeSetFromGPS
20004348 00000001 B ssd1306_found
2000ce49 00000001 B pin_sound
2000e494 00000001 B nrfx_power_irq_enabled
2000ce48 00000001 B no_stop
20003630 00000001 D neo6M
2000ce40 00000001 b _initialized
200036e4 00000001 D __fdlib_version
20003970 00000001 b completed.9929

View File

@@ -11,7 +11,7 @@
*****************************************************************/ *****************************************************************/
/* Enable support for dynamically allocated fields */ /* Enable support for dynamically allocated fields */
/* #define PB_ENABLE_MALLOC 1 */ #define PB_ENABLE_MALLOC 1
/* Define this if your CPU / compiler combination does not support /* Define this if your CPU / compiler combination does not support
* unaligned memory access to packed structures. */ * unaligned memory access to packed structures. */

View File

@@ -0,0 +1,46 @@
/* Linker script to configure memory regions.
geeksville: modified this to simulate a nrf52832 but with a sd140 soft device. So I can
see how the memory footprint works on this lower end CPU. Note: to work with sd140 in my bootloader
I need to start ram at 0x6000 (instead of the correct 0x3600 for sd132) - so I have less
RAM available than on a real 832.
*/
SEARCH_DIR(.)
GROUP(-lgcc -lc -lnosys)
MEMORY
{
FLASH (rx) : ORIGIN = 0x26000, LENGTH = 0x6D000 - 0x26000
/* FLASH (rx) : ORIGIN = 0x26000, LENGTH = 0xED000 - 0x26000 */
/* SRAM required by S132 depend on
* - Attribute Table Size
* - Vendor UUID count
* - Max ATT MTU
* - Concurrent connection peripheral + central + secure links
* - Event Len, HVN queue, Write CMD queue
*/
/* RAM (rwx) : ORIGIN = 0x20003600, LENGTH = 0x20010000 - 0x20003600 */
RAM (rwx) : ORIGIN = 0x20006000, LENGTH = 0x20010000 - 0x20006000
}
SECTIONS
{
. = ALIGN(4);
.svc_data :
{
PROVIDE(__start_svc_data = .);
KEEP(*(.svc_data))
PROVIDE(__stop_svc_data = .);
} > RAM
.fs_data :
{
PROVIDE(__start_fs_data = .);
KEEP(*(.fs_data))
PROVIDE(__stop_fs_data = .);
} > RAM
} INSERT AFTER .data;
INCLUDE "nrf52_common.ld"

View File

@@ -17,7 +17,7 @@ default_envs = tbeam ; Note: the github actions CI test build can't yet build NR
; REQUIRED environment variables - if not set the specified default will be sued ; REQUIRED environment variables - if not set the specified default will be sued
; The following environment variables must be set in the shell if you'd like to override them. ; The following environment variables must be set in the shell if you'd like to override them.
; They are used in this ini file as systenv.VARNAME, so in your shell do export "VARNAME=fish" ; They are used in this ini file as systenv.VARNAME, so in your shell do export "VARNAME=fish"
; HW_VERSION (default US) ; COUNTRY (default US), i.e. "export COUNTRY=EU865"
; APP_VERSION (default emptystring) ; APP_VERSION (default emptystring)
; HW_VERSION (default emptystring) ; HW_VERSION (default emptystring)
@@ -125,6 +125,18 @@ board = ttgo-lora32-v1
build_flags = build_flags =
${esp32_base.build_flags} -D TTGO_LORA_V2 ${esp32_base.build_flags} -D TTGO_LORA_V2
; The Heltec Cubecell plus
; IMPORTANT NOTE: This target doesn't yet work and probably won't ever work. I'm keeping it around for now.
; For more details see my post in the forum.
[env:cubecellplus]
platform = https://github.com/HelTecAutomation/platform-asrmicro650x.git ; we use top-of-tree because stable version has too many bugs - asrmicro650x
framework = arduino
board = cubecell_board_plus
; FIXME, bug in cubecell arduino - they are supposed to set ARDUINO
build_flags = ${env.build_flags} -DARDUINO=100 -Isrc/cubecell
src_filter =
${env.src_filter} -<esp32/> -<nrf52/>
; Common settings for NRF52 based targets ; Common settings for NRF52 based targets
[nrf52_base] [nrf52_base]
platform = nordicnrf52 platform = nordicnrf52
@@ -133,7 +145,7 @@ debug_tool = jlink
build_type = debug ; I'm debugging with ICE a lot now build_type = debug ; I'm debugging with ICE a lot now
; note: liboberon provides the AES256 implementation for NRF52 (though not using the hardware acceleration of the NRF52840 - FIXME) ; note: liboberon provides the AES256 implementation for NRF52 (though not using the hardware acceleration of the NRF52840 - FIXME)
build_flags = build_flags =
${env.build_flags} -Wno-unused-variable -Isrc/nrf52 -Isdk-nrfxlib/crypto/nrf_oberon/include -Lsdk-nrfxlib/crypto/nrf_oberon/lib/cortex-m4/hard-float/ -lliboberon_3.0.3 ${env.build_flags} -Wno-unused-variable -Isrc/nrf52 -Isdk-nrfxlib/crypto/nrf_oberon/include -Lsdk-nrfxlib/crypto/nrf_oberon/lib/cortex-m4/hard-float/ -lliboberon_3.0.3
;-DCFG_DEBUG=3 ;-DCFG_DEBUG=3
src_filter = src_filter =
${env.src_filter} -<esp32/> ${env.src_filter} -<esp32/>
@@ -156,8 +168,9 @@ debug_init_break =
[env:nrf52dk] [env:nrf52dk]
extends = nrf52_base extends = nrf52_base
board = nrf52840_dk_modified board = nrf52840_dk_modified
lib_deps =
UC1701 ; for temp testing # For experimenting with RAM sizes
# board_build.ldscript = linker/nrf52840_s140_sim832.ld
; The PPR board ; The PPR board
[env:ppr] [env:ppr]
@@ -166,7 +179,7 @@ board = ppr
lib_deps = lib_deps =
${env.lib_deps} ${env.lib_deps}
UC1701 UC1701
https://github.com/meshtastic/BQ25703A.git

2
proto

Submodule proto updated: e7f181ef6f...72cbde93ff

View File

@@ -2,6 +2,8 @@
#include "debug.h" #include "debug.h"
#include <assert.h> #include <assert.h>
#ifdef configUSE_PREEMPTION
void Thread::start(const char *name, size_t stackSize, uint32_t priority) void Thread::start(const char *name, size_t stackSize, uint32_t priority)
{ {
auto r = xTaskCreate(callRun, name, stackSize, this, priority, &taskHandle); auto r = xTaskCreate(callRun, name, stackSize, this, priority, &taskHandle);
@@ -43,3 +45,5 @@ void NotifiedWorkerThread::block()
xTaskNotifyWait(0, // don't clear notification on entry xTaskNotifyWait(0, // don't clear notification on entry
clearOnRead, &notification, portMAX_DELAY); // Wait forever clearOnRead, &notification, portMAX_DELAY); // Wait forever
} }
#endif

View File

@@ -1,4 +1,7 @@
#include <Arduino.h> #include <Arduino.h>
#include "freertosinc.h"
#ifdef HAS_FREE_RTOS
class Thread class Thread
{ {
@@ -88,4 +91,6 @@ class NotifiedWorkerThread : public WorkerThread
* A method that should block execution - either waiting ona queue/mutex or a "task notification" * A method that should block execution - either waiting ona queue/mutex or a "task notification"
*/ */
virtual void block(); virtual void block();
}; };
#endif

View File

@@ -73,6 +73,20 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define BUTTON_PIN PIN_BUTTON1 #define BUTTON_PIN PIN_BUTTON1
// FIXME, use variant.h defs for all of this!!! (even on the ESP32 targets) // FIXME, use variant.h defs for all of this!!! (even on the ESP32 targets)
#elif defined(CubeCell_BoardPlus)
//
// Standard definitions for CubeCell targets
//
#define NO_ESP32 // Don't use ESP32 libs (mainly bluetooth)
// FIXME, not yet ready for NRF52
#define RTC_DATA_ATTR
#define LED_PIN -1 // FIXME totally bogus
#define BUTTON_PIN -1
#else #else
// //
@@ -104,6 +118,10 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define SSD1306_ADDRESS 0x3C #define SSD1306_ADDRESS 0x3C
// 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.
//#define USE_SH1106
// Flip the screen upside down by default as it makes more sense on T-BEAM // 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. // devices. Comment this out to not rotate screen 180 degrees.
#define FLIP_SCREEN_VERTICALLY #define FLIP_SCREEN_VERTICALLY
@@ -168,6 +186,13 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
// This string must exactly match the case used in release file names or the android updater won't work // This string must exactly match the case used in release file names or the android updater won't work
#define HW_VENDOR "heltec" #define HW_VENDOR "heltec"
// the default ESP32 Pin of 15 is the Oled SCL, set to 36 and 37 and works fine.
// Tested on Neo6m module.
#undef GPS_RX_PIN
#undef GPS_TX_PIN
#define GPS_RX_PIN 36
#define GPS_TX_PIN 37
#ifndef USE_JTAG // gpio15 is TDO for JTAG, so no I2C on this board while doing jtag #ifndef USE_JTAG // gpio15 is TDO for JTAG, so no I2C on this board while doing jtag
#define I2C_SDA 4 // I2C pins for this board #define I2C_SDA 4 // I2C pins for this board
#define I2C_SCL 15 #define I2C_SCL 15
@@ -256,7 +281,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define DEBUG_PORT console // Serial debug port #define DEBUG_PORT console // Serial debug port
#ifdef NO_ESP32 // What platforms should use SEGGER?
#ifdef NRF52_SERIES
#define USE_SEGGER #define USE_SEGGER
#else #else
#define SERIAL0_RX_GPIO 3 // Always GPIO3 on ESP32 #define SERIAL0_RX_GPIO 3 // Always GPIO3 on ESP32

1
src/cubecell/FS.h Normal file
View File

@@ -0,0 +1 @@
// Placeholder FIXME

View File

@@ -8,7 +8,6 @@
SimpleAllocator btPool; SimpleAllocator btPool;
bool _BLEClientConnected = false; bool _BLEClientConnected = false;
class MyServerCallbacks : public BLEServerCallbacks class MyServerCallbacks : public BLEServerCallbacks
@@ -67,7 +66,8 @@ BLEService *createDeviceInfomationService(BLEServer *server, std::string hwVendo
{ {
BLEService *deviceInfoService = server->createService(BLEUUID((uint16_t)ESP_GATT_UUID_DEVICE_INFO_SVC)); BLEService *deviceInfoService = server->createService(BLEUUID((uint16_t)ESP_GATT_UUID_DEVICE_INFO_SVC));
BLECharacteristic *swC = new BLECharacteristic(BLEUUID((uint16_t)ESP_GATT_UUID_SW_VERSION_STR), BLECharacteristic::PROPERTY_READ); BLECharacteristic *swC =
new BLECharacteristic(BLEUUID((uint16_t)ESP_GATT_UUID_SW_VERSION_STR), BLECharacteristic::PROPERTY_READ);
BLECharacteristic *mfC = new BLECharacteristic(BLEUUID((uint16_t)ESP_GATT_UUID_MANU_NAME), BLECharacteristic::PROPERTY_READ); BLECharacteristic *mfC = new BLECharacteristic(BLEUUID((uint16_t)ESP_GATT_UUID_MANU_NAME), BLECharacteristic::PROPERTY_READ);
// BLECharacteristic SerialNumberCharacteristic(BLEUUID((uint16_t) ESP_GATT_UUID_SERIAL_NUMBER_STR), // BLECharacteristic SerialNumberCharacteristic(BLEUUID((uint16_t) ESP_GATT_UUID_SERIAL_NUMBER_STR),
// BLECharacteristic::PROPERTY_READ); // BLECharacteristic::PROPERTY_READ);
@@ -106,7 +106,6 @@ BLEService *createDeviceInfomationService(BLEServer *server, std::string hwVendo
return deviceInfoService; return deviceInfoService;
} }
static BLECharacteristic *batteryLevelC; static BLECharacteristic *batteryLevelC;
/** /**
@@ -304,7 +303,11 @@ BLEServer *initBLE(StartBluetoothPinScreenCallback startBtPinScreen, StopBluetoo
static BLESecurity security; // static to avoid allocs static BLESecurity security; // static to avoid allocs
BLESecurity *pSecurity = &security; BLESecurity *pSecurity = &security;
pSecurity->setCapability(ESP_IO_CAP_OUT); pSecurity->setCapability(ESP_IO_CAP_OUT);
// FIXME - really should be ESP_LE_AUTH_REQ_SC_BOND but it seems there is a bug right now causing that bonding info to be lost
// occasionally?
pSecurity->setAuthenticationMode(ESP_LE_AUTH_REQ_SC_BOND); pSecurity->setAuthenticationMode(ESP_LE_AUTH_REQ_SC_BOND);
pSecurity->setInitEncryptionKey(ESP_BLE_ENC_KEY_MASK | ESP_BLE_ID_KEY_MASK); pSecurity->setInitEncryptionKey(ESP_BLE_ENC_KEY_MASK | ESP_BLE_ID_KEY_MASK);
return pServer; return pServer;

View File

@@ -4,6 +4,7 @@
#include "configuration.h" #include "configuration.h"
#include "main.h" #include "main.h"
#include "power.h" #include "power.h"
#include "sleep.h"
#include "target_specific.h" #include "target_specific.h"
bool bluetoothOn; bool bluetoothOn;
@@ -154,6 +155,18 @@ void axp192Init()
} }
#endif #endif
/*
static void printBLEinfo() {
int dev_num = esp_ble_get_bond_device_num();
esp_ble_bond_dev_t *dev_list = (esp_ble_bond_dev_t *)malloc(sizeof(esp_ble_bond_dev_t) * dev_num);
esp_ble_get_bond_device_list(&dev_num, dev_list);
for (int i = 0; i < dev_num; i++) {
// esp_ble_remove_bond_device(dev_list[i].bd_addr);
}
} */
void esp32Setup() void esp32Setup()
{ {
uint32_t seed = esp_random(); uint32_t seed = esp_random();
@@ -165,6 +178,8 @@ void esp32Setup()
DEBUG_MSG("Total PSRAM: %d\n", ESP.getPsramSize()); DEBUG_MSG("Total PSRAM: %d\n", ESP.getPsramSize());
DEBUG_MSG("Free PSRAM: %d\n", ESP.getFreePsram()); DEBUG_MSG("Free PSRAM: %d\n", ESP.getFreePsram());
// enableModemSleep();
#ifdef AXP192_SLAVE_ADDRESS #ifdef AXP192_SLAVE_ADDRESS
axp192Init(); axp192Init();
#endif #endif

View File

@@ -1,16 +1,30 @@
#pragma once #pragma once
// The FreeRTOS includes are in a different directory on ESP32 and I can't figure out how to make that work with platformio gcc options // The FreeRTOS includes are in a different directory on ESP32 and I can't figure out how to make that work with platformio gcc
// so this is my quick hack to make things work // options so this is my quick hack to make things work
#ifdef ARDUINO_ARCH_ESP32 #ifdef ARDUINO_ARCH_ESP32
#define HAS_FREE_RTOS
#include <freertos/FreeRTOS.h> #include <freertos/FreeRTOS.h>
#include <freertos/task.h>
#include <freertos/semphr.h>
#include <freertos/queue.h> #include <freertos/queue.h>
#include <freertos/semphr.h>
#include <freertos/task.h>
#else #else
// not yet supported on cubecell
#ifndef CubeCell_BoardPlus
#define HAS_FREE_RTOS
#include <FreeRTOS.h> #include <FreeRTOS.h>
#include <task.h>
#include <semphr.h>
#include <queue.h> #include <queue.h>
#include <semphr.h>
#include <task.h>
#else
#include <Arduino.h>
typedef uint32_t TickType_t;
typedef uint32_t BaseType_t;
#define portMAX_DELAY UINT32_MAX
#endif
#endif #endif

View File

@@ -86,14 +86,14 @@ void UBloxGPS::doTask()
// If we don't have a fix (a quick check), don't try waiting for a solution) // If we don't have a fix (a quick check), don't try waiting for a solution)
// Hmmm my fix type reading returns zeros for fix, which doesn't seem correct, because it is still sptting out positions // Hmmm my fix type reading returns zeros for fix, which doesn't seem correct, because it is still sptting out positions
// turn off for now // turn off for now
// fixtype = ublox.getFixType(); fixtype = ublox.getFixType(0);
// DEBUG_MSG("fix type %d\n", fixtype); DEBUG_MSG("GPS fix type %d\n", fixtype);
// DEBUG_MSG("sec %d\n", ublox.getSecond()); // DEBUG_MSG("sec %d\n", ublox.getSecond());
// DEBUG_MSG("lat %d\n", ublox.getLatitude()); // DEBUG_MSG("lat %d\n", ublox.getLatitude());
// any fix that has time // any fix that has time
if (ublox.getT()) { if (ublox.getT(0)) {
/* Convert to unix time /* 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 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). (midnight UTC/GMT), not counting leap seconds (in ISO 8601: 1970-01-01T00:00:00Z).
@@ -109,7 +109,7 @@ The Unix epoch (or Unix time or POSIX time or Unix timestamp) is the number of s
perhapsSetRTC(t); perhapsSetRTC(t);
} }
if ((fixtype >= 3 && fixtype <= 4) && ublox.getP()) // rd fixes only if ((fixtype >= 3 && fixtype <= 4) && ublox.getP(0)) // rd fixes only
{ {
// we only notify if position has changed // we only notify if position has changed
latitude = ublox.getLatitude(); latitude = ublox.getLatitude();
@@ -117,7 +117,9 @@ The Unix epoch (or Unix time or POSIX time or Unix timestamp) is the number of s
altitude = ublox.getAltitude() / 1000; // in mm convert to meters altitude = ublox.getAltitude() / 1000; // in mm convert to meters
DEBUG_MSG("new gps pos lat=%f, lon=%f, alt=%d\n", latitude * 1e-7, longitude * 1e-7, altitude); DEBUG_MSG("new gps pos lat=%f, lon=%f, alt=%d\n", latitude * 1e-7, longitude * 1e-7, altitude);
hasValidLocation = (latitude != 0) || (longitude != 0); // bogus lat lon is reported as 0,0 // bogus lat lon is reported as 0 or 0 (can be bogus just for one)
// Also: apparently when the GPS is initially reporting lock it can output a bogus latitude > 90 deg!
hasValidLocation = (latitude != 0) && (longitude != 0) && (latitude <= 900000000 && latitude >= -900000000);
if (hasValidLocation) { if (hasValidLocation) {
wantNewLocation = false; wantNewLocation = false;
notifyObservers(NULL); notifyObservers(NULL);

View File

@@ -5,6 +5,7 @@
namespace meshtastic namespace meshtastic
{ {
#ifdef configUSE_PREEMPTION
Lock::Lock() Lock::Lock()
{ {
handle = xSemaphoreCreateBinary(); handle = xSemaphoreCreateBinary();
@@ -21,6 +22,20 @@ void Lock::unlock()
{ {
assert(xSemaphoreGive(handle)); assert(xSemaphoreGive(handle));
} }
#else
Lock::Lock()
{
}
void Lock::lock()
{
}
void Lock::unlock()
{
}
#endif
LockGuard::LockGuard(Lock *lock) : lock(lock) LockGuard::LockGuard(Lock *lock) : lock(lock)
{ {

View File

@@ -25,7 +25,9 @@ class Lock
void unlock(); void unlock();
private: private:
#ifdef configUSE_PREEMPTION
SemaphoreHandle_t handle; SemaphoreHandle_t handle;
#endif
}; };
// RAII lock guard. // RAII lock guard.

View File

@@ -44,6 +44,13 @@
#include "BluetoothUtil.h" #include "BluetoothUtil.h"
#endif #endif
#include "RF95Interface.h"
#include "SX1262Interface.h"
#ifdef NRF52_SERIES
#include "variant.h"
#endif
// We always create a screen object, but we only init it if we find the hardware // We always create a screen object, but we only init it if we find the hardware
meshtastic::Screen screen(SSD1306_ADDRESS); meshtastic::Screen screen(SSD1306_ADDRESS);
@@ -117,12 +124,7 @@ static uint32_t ledBlinker()
Periodic ledPeriodic(ledBlinker); Periodic ledPeriodic(ledBlinker);
#include "RF95Interface.h"
#include "SX1262Interface.h"
#ifdef NO_ESP32
#include "variant.h"
#endif
void setup() void setup()
{ {
@@ -152,7 +154,10 @@ void setup()
#else #else
Wire.begin(); Wire.begin();
#endif #endif
// i2c still busted on new board
#ifndef ARDUINO_NRF52840_PPR
scanI2Cdevice(); scanI2Cdevice();
#endif
// Buttons & LED // Buttons & LED
#ifdef BUTTON_PIN #ifdef BUTTON_PIN
@@ -234,7 +239,7 @@ void setup()
new SimRadio(); new SimRadio();
#endif #endif
if (!rIf->init()) if (!rIf || !rIf->init())
recordCriticalError(ErrNoRadio); recordCriticalError(ErrNoRadio);
else else
router.addInterface(rIf); router.addInterface(rIf);
@@ -330,7 +335,7 @@ void loop()
screen.debug()->setChannelNameStatus(channelSettings.name); screen.debug()->setChannelNameStatus(channelSettings.name);
screen.debug()->setPowerStatus(powerStatus); screen.debug()->setPowerStatus(powerStatus);
// TODO(#4): use something based on hdop to show GPS "signal" strength. // TODO(#4): use something based on hdop to show GPS "signal" strength.
screen.debug()->setGPSStatus(gps->hasLock() ? "good" : "bad"); screen.debug()->setGPSStatus(gps->isConnected ? (gps->hasLock() ? "GPS ok" : "No Sats") : "No GPS");
// No GPS lock yet, let the OS put the main CPU in low power mode for 100ms (or until another interrupt comes in) // No GPS lock yet, let the OS put the main CPU in low power mode for 100ms (or until another interrupt comes in)
// i.e. don't just keep spinning in loop as fast as we can. // i.e. don't just keep spinning in loop as fast as we can.

View File

@@ -107,6 +107,7 @@ template <class T> class MemoryPool : public Allocator<T>
maxElements); // sanity check to make sure a programmer didn't free something that didn't come from this pool maxElements); // sanity check to make sure a programmer didn't free something that didn't come from this pool
} }
#ifdef HAS_FREE_RTOS
/// Return a buffer from an ISR, if higherPriWoken is set to true you have some work to do ;-) /// Return a buffer from an ISR, if higherPriWoken is set to true you have some work to do ;-)
void releaseFromISR(T *p, BaseType_t *higherPriWoken) void releaseFromISR(T *p, BaseType_t *higherPriWoken)
{ {
@@ -115,6 +116,7 @@ template <class T> class MemoryPool : public Allocator<T>
(size_t)(p - buf) < (size_t)(p - buf) <
maxElements); // sanity check to make sure a programmer didn't free something that didn't come from this pool maxElements); // sanity check to make sure a programmer didn't free something that didn't come from this pool
} }
#endif
protected: protected:
/// Return a queable object which has been prefilled with zeros - allow timeout to wait for available buffers (you /// Return a queable object which has been prefilled with zeros - allow timeout to wait for available buffers (you

View File

@@ -160,7 +160,7 @@ int MeshService::handleFromRadio(const MeshPacket *mp)
// If we veto a received User packet, we don't put it into the DB or forward it to the phone (to prevent confusing it) // If we veto a received User packet, we don't put it into the DB or forward it to the phone (to prevent confusing it)
if (mp) { if (mp) {
DEBUG_MSG("Forwarding to phone, from=0x%x, rx_time=%u\n", mp->from, mp->rx_time); printPacket("Forwarding to phone", mp);
nodeDB.updateFrom(*mp); // update our DB state based off sniffing every RX packet from the radio nodeDB.updateFrom(*mp); // update our DB state based off sniffing every RX packet from the radio
fromNum++; fromNum++;

View File

@@ -3,7 +3,6 @@
#include <assert.h> #include <assert.h>
#include "FS.h" #include "FS.h"
#include "SPIFFS.h"
#include "CryptoEngine.h" #include "CryptoEngine.h"
#include "GPS.h" #include "GPS.h"
@@ -30,15 +29,18 @@ DeviceState versions used to be defined in the .proto file but really only this
#define here. #define here.
*/ */
#define DEVICESTATE_CUR_VER 9 #define DEVICESTATE_CUR_VER 10
#define DEVICESTATE_MIN_VER DEVICESTATE_CUR_VER #define DEVICESTATE_MIN_VER DEVICESTATE_CUR_VER
#ifndef NO_ESP32 #ifndef NO_ESP32
// ESP32 version
#include "SPIFFS.h"
#define FS SPIFFS #define FS SPIFFS
#define FSBegin() FS.begin(true) #define FSBegin() FS.begin(true)
#define FILE_O_WRITE "w" #define FILE_O_WRITE "w"
#define FILE_O_READ "r" #define FILE_O_READ "r"
#else #else
// NRF52 version
#include "InternalFileSystem.h" #include "InternalFileSystem.h"
#define FS InternalFS #define FS InternalFS
#define FSBegin() FS.begin() #define FSBegin() FS.begin()
@@ -110,8 +112,10 @@ void NodeDB::resetRadioConfig()
*/ */
} }
void NodeDB::init() void NodeDB::installDefaultDeviceState()
{ {
memset(&devicestate, 0, sizeof(devicestate));
// init our devicestate with valid flags so protobuf writing/reading will work // init our devicestate with valid flags so protobuf writing/reading will work
devicestate.has_my_node = true; devicestate.has_my_node = true;
devicestate.has_radio = true; devicestate.has_radio = true;
@@ -119,7 +123,7 @@ void NodeDB::init()
devicestate.radio.has_channel_settings = true; devicestate.radio.has_channel_settings = true;
devicestate.radio.has_preferences = true; devicestate.radio.has_preferences = true;
devicestate.node_db_count = 0; devicestate.node_db_count = 0;
devicestate.receive_queue_count = 0; devicestate.receive_queue_count = 0; // Not yet implemented FIXME
resetRadioConfig(); resetRadioConfig();
@@ -139,12 +143,17 @@ void NodeDB::init()
pickNewNodeNum(); // Note: we will repick later, just in case the settings are corrupted, but we need a valid pickNewNodeNum(); // Note: we will repick later, just in case the settings are corrupted, but we need a valid
// owner.short_name now // owner.short_name now
sprintf(owner.long_name, "Unknown %02x%02x", ourMacAddr[4], ourMacAddr[5]); sprintf(owner.long_name, "Unknown %02x%02x", ourMacAddr[4], ourMacAddr[5]);
sprintf(owner.short_name, "?%02X", myNodeInfo.my_node_num & 0xff); sprintf(owner.short_name, "?%02X", (unsigned)(myNodeInfo.my_node_num & 0xff));
}
void NodeDB::init()
{
installDefaultDeviceState();
if (!FSBegin()) // FIXME - do this in main? if (!FSBegin()) // FIXME - do this in main?
{ {
DEBUG_MSG("ERROR filesystem mount Failed\n"); DEBUG_MSG("ERROR filesystem mount Failed\n");
// FIXME - report failure to phone assert(0); // FIXME - report failure to phone
} }
// saveToDisk(); // saveToDisk();
@@ -210,7 +219,7 @@ const char *preftmp = "/db.proto.tmp";
void NodeDB::loadFromDisk() void NodeDB::loadFromDisk()
{ {
#ifdef FS #ifdef FS
static DeviceState scratch; // static DeviceState scratch; We no longer read into a tempbuf because this structure is 15KB of valuable RAM
auto f = FS.open(preffile); auto f = FS.open(preffile);
if (f) { if (f) {
@@ -219,16 +228,17 @@ void NodeDB::loadFromDisk()
// DEBUG_MSG("Preload channel name=%s\n", channelSettings.name); // DEBUG_MSG("Preload channel name=%s\n", channelSettings.name);
memset(&scratch, 0, sizeof(scratch)); memset(&devicestate, 0, sizeof(devicestate));
if (!pb_decode(&stream, DeviceState_fields, &scratch)) { if (!pb_decode(&stream, DeviceState_fields, &devicestate)) {
DEBUG_MSG("Error: can't decode protobuf %s\n", PB_GET_ERROR(&stream)); DEBUG_MSG("Error: can't decode protobuf %s\n", PB_GET_ERROR(&stream));
installDefaultDeviceState(); // Our in RAM copy might now be corrupt
// FIXME - report failure to phone // FIXME - report failure to phone
} else { } else {
if (scratch.version < DEVICESTATE_MIN_VER) if (devicestate.version < DEVICESTATE_MIN_VER) {
DEBUG_MSG("Warn: devicestate is old, discarding\n"); DEBUG_MSG("Warn: devicestate is old, discarding\n");
else { installDefaultDeviceState();
DEBUG_MSG("Loaded saved preferences version %d\n", scratch.version); } else {
devicestate = scratch; DEBUG_MSG("Loaded saved preferences version %d\n", devicestate.version);
} }
// DEBUG_MSG("Postload channel name=%s\n", channelSettings.name); // DEBUG_MSG("Postload channel name=%s\n", channelSettings.name);
@@ -238,6 +248,7 @@ void NodeDB::loadFromDisk()
} else { } else {
DEBUG_MSG("No saved preferences found\n"); DEBUG_MSG("No saved preferences found\n");
} }
#else #else
DEBUG_MSG("ERROR: Filesystem not implemented\n"); DEBUG_MSG("ERROR: Filesystem not implemented\n");
#endif #endif

View File

@@ -93,6 +93,9 @@ class NodeDB
/// read our db from flash /// read our db from flash
void loadFromDisk(); void loadFromDisk();
/// Reinit device state from scratch (not loading from disk)
void installDefaultDeviceState();
}; };
/** /**

View File

@@ -2,8 +2,6 @@
#include "configuration.h" #include "configuration.h"
#include "mesh-pb-constants.h" #include "mesh-pb-constants.h"
PacketHistory::PacketHistory() PacketHistory::PacketHistory()
{ {
recentPackets.reserve(MAX_NUM_NODES); // Prealloc the worst case # of records - to prevent heap fragmentation recentPackets.reserve(MAX_NUM_NODES); // Prealloc the worst case # of records - to prevent heap fragmentation
@@ -48,7 +46,7 @@ bool PacketHistory::wasSeenRecently(const MeshPacket *p, bool withUpdate)
r.sender = p->from; r.sender = p->from;
r.rxTimeMsec = now; r.rxTimeMsec = now;
recentPackets.push_back(r); recentPackets.push_back(r);
DEBUG_MSG("Adding packet record for fr=0x%x,to=0x%x,id=%d\n", p->from, p->to, p->id); printPacket("Adding packet record", p);
} }
return false; return false;

View File

@@ -35,9 +35,8 @@ class PacketRecordOrderFunction
// If the timer ticks have rolled over the difference between times will be _enormous_. Handle that case specially // If the timer ticks have rolled over the difference between times will be _enormous_. Handle that case specially
uint32_t t1 = p1.rxTimeMsec, t2 = p2.rxTimeMsec; uint32_t t1 = p1.rxTimeMsec, t2 = p2.rxTimeMsec;
if (abs(t1 - t2) > if (t1 - t2 > UINT32_MAX / 2) {
UINT32_MAX / // time must have rolled over, swap them because the new little number is 'bigger' than the old big number
2) { // time must have rolled over, swap them because the new little number is 'bigger' than the old big number
t1 = t2; t1 = t2;
t2 = p1.rxTimeMsec; t2 = p1.rxTimeMsec;
} }

View File

@@ -2,6 +2,8 @@
#include "MeshService.h" #include "MeshService.h"
#include "NodeDB.h" #include "NodeDB.h"
#include "PowerFSM.h" #include "PowerFSM.h"
#include "RadioInterface.h"
#include "GPS.h"
#include <assert.h> #include <assert.h>
PhoneAPI::PhoneAPI() PhoneAPI::PhoneAPI()
@@ -43,8 +45,7 @@ void PhoneAPI::handleToRadio(const uint8_t *buf, size_t bufLength)
switch (toRadioScratch.which_variant) { switch (toRadioScratch.which_variant) {
case ToRadio_packet_tag: { case ToRadio_packet_tag: {
MeshPacket &p = toRadioScratch.variant.packet; MeshPacket &p = toRadioScratch.variant.packet;
DEBUG_MSG("PACKET FROM PHONE: id=%d, to=%x, want_ack=%d, which1=%d, which2=%d, typ=%d, buflen=%d\n", p.id, p.to, p.want_ack, p.which_payload, printPacket("PACKET FROM PHONE", &p);
p.decoded.which_payload, p.decoded.data.typ, bufLength);
service.handleToRadio(p); service.handleToRadio(p);
break; break;
} }
@@ -78,6 +79,7 @@ void PhoneAPI::handleToRadio(const uint8_t *buf, size_t bufLength)
} }
} }
/** /**
* Get the next packet we want to send to the phone, or NULL if no such packet is available. * Get the next packet we want to send to the phone, or NULL if no such packet is available.
* *
@@ -108,6 +110,7 @@ size_t PhoneAPI::getFromRadio(uint8_t *buf)
break; break;
case STATE_SEND_MY_INFO: case STATE_SEND_MY_INFO:
myNodeInfo.has_gps = gps && gps->isConnected; // Update with latest GPS connect info
fromRadioScratch.which_variant = FromRadio_my_info_tag; fromRadioScratch.which_variant = FromRadio_my_info_tag;
fromRadioScratch.variant.my_info = myNodeInfo; fromRadioScratch.variant.my_info = myNodeInfo;
state = STATE_SEND_RADIO; state = STATE_SEND_RADIO;

View File

@@ -18,6 +18,7 @@ template <class T> class PointerQueue : public TypedQueue<T *>
return this->dequeue(&p, maxWait) ? p : nullptr; return this->dequeue(&p, maxWait) ? p : nullptr;
} }
#ifdef HAS_FREE_RTOS
// returns a ptr or null if the queue was empty // returns a ptr or null if the queue was empty
T *dequeuePtrFromISR(BaseType_t *higherPriWoken) T *dequeuePtrFromISR(BaseType_t *higherPriWoken)
{ {
@@ -25,4 +26,5 @@ template <class T> class PointerQueue : public TypedQueue<T *>
return this->dequeueFromISR(&p, higherPriWoken) ? p : nullptr; return this->dequeueFromISR(&p, higherPriWoken) ? p : nullptr;
} }
#endif
}; };

View File

@@ -24,6 +24,52 @@ separated by 2.16 MHz with respect to the adjacent channels. Channel zero starts
// 1kb was too small // 1kb was too small
#define RADIO_STACK_SIZE 4096 #define RADIO_STACK_SIZE 4096
void printPacket(const char *prefix, const MeshPacket *p)
{
DEBUG_MSG("%s (id=0x%08x Fr0x%02x To0x%02x, WantAck%d, HopLim%d", prefix, p->id, p->from & 0xff, p->to & 0xff, p->want_ack,
p->hop_limit);
if (p->which_payload == MeshPacket_decoded_tag) {
auto &s = p->decoded;
switch (s.which_payload) {
case SubPacket_data_tag:
DEBUG_MSG(" Payload:Data");
break;
case SubPacket_position_tag:
DEBUG_MSG(" Payload:Position");
break;
case SubPacket_user_tag:
DEBUG_MSG(" Payload:User");
break;
case 0:
DEBUG_MSG(" Payload:None");
break;
default:
DEBUG_MSG(" Payload:%d", s.which_payload);
break;
}
if (s.want_response)
DEBUG_MSG(" WANTRESP");
if (s.source != 0)
DEBUG_MSG(" source=%08x", s.source);
if (s.dest != 0)
DEBUG_MSG(" dest=%08x", s.dest);
if (s.which_ack == SubPacket_success_id_tag)
DEBUG_MSG(" successId=%08x", s.ack.success_id);
else if (s.which_ack == SubPacket_fail_id_tag)
DEBUG_MSG(" failId=%08x", s.ack.fail_id);
} else {
DEBUG_MSG(" encrypted");
}
if (p->rx_time != 0) {
DEBUG_MSG(" rxtime=%u", p->rx_time);
}
DEBUG_MSG(")\n");
}
RadioInterface::RadioInterface() RadioInterface::RadioInterface()
{ {
assert(sizeof(PacketHeader) == 4 || sizeof(PacketHeader) == 16); // make sure the compiler did what we expected assert(sizeof(PacketHeader) == 4 || sizeof(PacketHeader) == 16); // make sure the compiler did what we expected

View File

@@ -162,3 +162,6 @@ class SimRadio : public RadioInterface
/// \return true if initialisation succeeded. /// \return true if initialisation succeeded.
virtual bool init() { return true; } virtual bool init() { return true; }
}; };
/// Debug printing for packets
void printPacket(const char *prefix, const MeshPacket *p);

View File

@@ -114,8 +114,8 @@ bool RadioLibInterface::canSendImmediately()
/// bluetooth comms code. If the txmit queue is empty it might return an error /// bluetooth comms code. If the txmit queue is empty it might return an error
ErrorCode RadioLibInterface::send(MeshPacket *p) ErrorCode RadioLibInterface::send(MeshPacket *p)
{ {
DEBUG_MSG("enqueuing for send on mesh fr=0x%x,to=0x%x,id=%d (txGood=%d,rxGood=%d,rxBad=%d)\n", p->from, p->to, p->id, txGood, printPacket("enqueuing for send", p);
rxGood, rxBad); DEBUG_MSG("txGood=%d,rxGood=%d,rxBad=%d\n", txGood, rxGood, rxBad);
ErrorCode res = txQueue.enqueue(p, 0) ? ERRNO_OK : ERRNO_UNKNOWN; ErrorCode res = txQueue.enqueue(p, 0) ? ERRNO_OK : ERRNO_UNKNOWN;
if (res != ERRNO_OK) { // we weren't able to queue it, so we must drop it to prevent leaks if (res != ERRNO_OK) { // we weren't able to queue it, so we must drop it to prevent leaks
@@ -237,7 +237,7 @@ void RadioLibInterface::completeSending()
{ {
if (sendingPacket) { if (sendingPacket) {
txGood++; txGood++;
DEBUG_MSG("Completed sending to=0x%x, id=%u\n", sendingPacket->to, sendingPacket->id); printPacket("Completed sending", sendingPacket);
// We are done sending that packet, release it // We are done sending that packet, release it
packetPool.release(sendingPacket); packetPool.release(sendingPacket);
@@ -291,7 +291,7 @@ void RadioLibInterface::handleReceiveInterrupt()
memcpy(mp->encrypted.bytes, payload, payloadLen); memcpy(mp->encrypted.bytes, payload, payloadLen);
mp->encrypted.size = payloadLen; mp->encrypted.size = payloadLen;
DEBUG_MSG("Lora RX interrupt from=0x%x, id=%u\n", mp->from, mp->id); printPacket("Lora RX", mp);
deliverToReceiver(mp); deliverToReceiver(mp);
} }
@@ -301,9 +301,11 @@ void RadioLibInterface::handleReceiveInterrupt()
/** start an immediate transmit */ /** start an immediate transmit */
void RadioLibInterface::startSend(MeshPacket *txp) void RadioLibInterface::startSend(MeshPacket *txp)
{ {
DEBUG_MSG("Starting low level send from=0x%x, to=0x%x, id=%u, want_ack=%d\n", txp->from, txp->to, txp->id, txp->want_ack); printPacket("Starting low level send", txp);
setStandby(); // Cancel any already in process receives setStandby(); // Cancel any already in process receives
configHardwareForSend(); // must be after setStandby
size_t numbytes = beginSending(txp); size_t numbytes = beginSending(txp);
int res = iface->startTransmit(radiobuf, numbytes); int res = iface->startTransmit(radiobuf, numbytes);

View File

@@ -3,6 +3,10 @@
#include "PeriodicTask.h" #include "PeriodicTask.h"
#include "RadioInterface.h" #include "RadioInterface.h"
#ifdef CubeCell_BoardPlus
#define RADIOLIB_SOFTWARE_SERIAL_UNSUPPORTED
#endif
#include <RadioLib.h> #include <RadioLib.h>
// ESP32 has special rules about ISR code // ESP32 has special rules about ISR code
@@ -91,9 +95,6 @@ class RadioLibInterface : public RadioInterface, private PeriodicTask
virtual void startReceive() = 0; virtual void startReceive() = 0;
private: private:
/** start an immediate transmit */
void startSend(MeshPacket *txp);
/** if we have something waiting to send, start a short random timer so we can come check for collision before actually doing /** if we have something waiting to send, start a short random timer so we can come check for collision before actually doing
* the transmit * the transmit
* *
@@ -108,12 +109,20 @@ class RadioLibInterface : public RadioInterface, private PeriodicTask
virtual void doTask(); virtual void doTask();
/** start an immediate transmit
* This method is virtual so subclasses can hook as needed, subclasses should not call directly
*/
virtual void startSend(MeshPacket *txp);
protected: protected:
/// Initialise the Driver transport hardware and software. /// Initialise the Driver transport hardware and software.
/// Make sure the Driver is properly configured before calling init(). /// Make sure the Driver is properly configured before calling init().
/// \return true if initialisation succeeded. /// \return true if initialisation succeeded.
virtual bool init(); virtual bool init();
/** Do any hardware setup needed on entry into send configuration for the radio. Subclasses can customize */
virtual void configHardwareForSend() {}
/** /**
* Convert our modemConfig enum into wf, sf, etc... * Convert our modemConfig enum into wf, sf, etc...
* *

View File

@@ -27,7 +27,7 @@ ErrorCode ReliableRouter::send(MeshPacket *p)
bool ReliableRouter::shouldFilterReceived(const MeshPacket *p) bool ReliableRouter::shouldFilterReceived(const MeshPacket *p)
{ {
if (p->to == NODENUM_BROADCAST && p->from == getNodeNum()) { if (p->to == NODENUM_BROADCAST && p->from == getNodeNum()) {
DEBUG_MSG("Received someone rebroadcasting for us fr=0x%x,to=0x%x,id=%d\n", p->from, p->to, p->id); printPacket("Rx someone rebroadcasting for us", p);
// We are seeing someone rebroadcast one of our broadcast attempts. // We are seeing someone rebroadcast one of our broadcast attempts.
// If this is the first time we saw this, cancel any retransmissions we have queued up and generate an internal ack for // If this is the first time we saw this, cancel any retransmissions we have queued up and generate an internal ack for

View File

@@ -48,7 +48,7 @@ struct PendingPacket {
PendingPacket() {} PendingPacket() {}
PendingPacket(MeshPacket *p); PendingPacket(MeshPacket *p);
void setNextTx() { nextTxMsec = millis() + random(20 * 1000, 22 * 1000); } void setNextTx() { nextTxMsec = millis() + random(20 * 1000L, 22 * 1000L); }
}; };
class GlobalPacketIdHashFunction class GlobalPacketIdHashFunction

View File

@@ -34,7 +34,14 @@ Allocator<MeshPacket> &packetPool = staticPool;
* *
* Currently we only allow one interface, that may change in the future * Currently we only allow one interface, that may change in the future
*/ */
Router::Router() : fromRadioQueue(MAX_RX_FROMRADIO) {} Router::Router() : fromRadioQueue(MAX_RX_FROMRADIO)
{
// This is called pre main(), don't touch anything here, the following code is not safe
/* DEBUG_MSG("Size of NodeInfo %d\n", sizeof(NodeInfo));
DEBUG_MSG("Size of SubPacket %d\n", sizeof(SubPacket));
DEBUG_MSG("Size of MeshPacket %d\n", sizeof(MeshPacket)); */
}
/** /**
* do idle processing * do idle processing
@@ -150,8 +157,8 @@ ErrorCode Router::send(MeshPacket *p)
*/ */
void Router::sniffReceived(const MeshPacket *p) void Router::sniffReceived(const MeshPacket *p)
{ {
DEBUG_MSG("FIXME-update-db Sniffing packet fr=0x%x,to=0x%x,id=%d\n", p->from, p->to, p->id); DEBUG_MSG("FIXME-update-db Sniffing packet\n");
// FIXME, update nodedb // FIXME, update nodedb here for any packet that passes through us
} }
bool Router::perhapsDecode(MeshPacket *p) bool Router::perhapsDecode(MeshPacket *p)
@@ -202,7 +209,7 @@ void Router::handleReceived(MeshPacket *p)
sniffReceived(p); sniffReceived(p);
if (p->to == NODENUM_BROADCAST || p->to == getNodeNum()) { if (p->to == NODENUM_BROADCAST || p->to == getNodeNum()) {
DEBUG_MSG("Notifying observers of received packet fr=0x%x,to=0x%x,id=%d\n", p->from, p->to, p->id); printPacket("Delivering rx packet", p);
notifyPacketReceived.notifyObservers(p); notifyPacketReceived.notifyObservers(p);
} }
} }

View File

@@ -14,7 +14,19 @@ bool SX1262Interface::init()
{ {
RadioLibInterface::init(); RadioLibInterface::init();
float tcxoVoltage = 0; // None - we use an XTAL #ifdef SX1262_RXEN // set not rx or tx mode
pinMode(SX1262_RXEN, OUTPUT);
#endif
#ifdef SX1262_TXEN
pinMode(SX1262_TXEN, OUTPUT);
#endif
#ifndef SX1262_E22
float tcxoVoltage = 0; // None - we use an XTAL
#else
float tcxoVoltage =
1.8; // E22 uses DIO3 to power tcxo per https://github.com/jgromes/RadioLib/issues/12#issuecomment-520695575
#endif
bool useRegulatorLDO = false; // Seems to depend on the connection to pin 9/DCC_SW - if an inductor DCDC? bool useRegulatorLDO = false; // Seems to depend on the connection to pin 9/DCC_SW - if an inductor DCDC?
applyModemConfig(); applyModemConfig();
@@ -23,6 +35,12 @@ bool SX1262Interface::init()
int res = lora.begin(freq, bw, sf, cr, syncWord, power, currentLimit, preambleLength, tcxoVoltage, useRegulatorLDO); int res = lora.begin(freq, bw, sf, cr, syncWord, power, currentLimit, preambleLength, tcxoVoltage, useRegulatorLDO);
DEBUG_MSG("LORA init result %d\n", res); DEBUG_MSG("LORA init result %d\n", res);
#ifdef SX1262_TXEN
// lora.begin sets Dio2 as RF switch control, which is not true if we are manually controlling RX and TX
if (res == ERR_NONE)
res = lora.setDio2AsRfSwitch(false);
#endif
if (res == ERR_NONE) if (res == ERR_NONE)
res = lora.setCRC(SX126X_LORA_CRC_ON); res = lora.setCRC(SX126X_LORA_CRC_ON);
@@ -81,6 +99,13 @@ void SX1262Interface::setStandby()
int err = lora.standby(); int err = lora.standby();
assert(err == ERR_NONE); assert(err == ERR_NONE);
#ifdef SX1262_RXEN // we have RXEN/TXEN control - turn off RX and TX power
digitalWrite(SX1262_RXEN, LOW);
#endif
#ifdef SX1262_TXEN
digitalWrite(SX1262_TXEN, LOW);
#endif
isReceiving = false; // If we were receiving, not any more isReceiving = false; // If we were receiving, not any more
disableInterrupt(); disableInterrupt();
completeSending(); // If we were sending, not anymore completeSending(); // If we were sending, not anymore
@@ -94,6 +119,18 @@ void SX1262Interface::addReceiveMetadata(MeshPacket *mp)
mp->rx_snr = lora.getSNR(); mp->rx_snr = lora.getSNR();
} }
/** start an immediate transmit
* We override to turn on transmitter power as needed.
*/
void SX1262Interface::configHardwareForSend()
{
#ifdef SX1262_TXEN // we have RXEN/TXEN control - turn on TX power / off RX power
digitalWrite(SX1262_TXEN, HIGH);
#endif
RadioLibInterface::configHardwareForSend();
}
// For power draw measurements, helpful to force radio to stay sleeping // For power draw measurements, helpful to force radio to stay sleeping
// #define SLEEP_ONLY // #define SLEEP_ONLY
@@ -102,7 +139,13 @@ void SX1262Interface::startReceive()
#ifdef SLEEP_ONLY #ifdef SLEEP_ONLY
sleep(); sleep();
#else #else
setStandby(); setStandby();
#ifdef SX1262_RXEN // we have RXEN/TXEN control - turn on RX power / off TX power
digitalWrite(SX1262_RXEN, HIGH);
#endif
// int err = lora.startReceive(); // int err = lora.startReceive();
int err = lora.startReceiveDutyCycleAuto(); // We use a 32 bit preamble so this should save some power by letting radio sit in int err = lora.startReceiveDutyCycleAuto(); // We use a 32 bit preamble so this should save some power by letting radio sit in
// standby mostly. // standby mostly.

View File

@@ -43,6 +43,12 @@ class SX1262Interface : public RadioLibInterface
* Start waiting to receive a message * Start waiting to receive a message
*/ */
virtual void startReceive(); virtual void startReceive();
/**
* We override to turn on transmitter power as needed.
*/
virtual void configHardwareForSend();
/** /**
* Add SNR data to received messages * Add SNR data to received messages
*/ */
@@ -51,5 +57,4 @@ class SX1262Interface : public RadioLibInterface
virtual void setStandby(); virtual void setStandby();
private: private:
}; };

View File

@@ -5,6 +5,8 @@
#include "freertosinc.h" #include "freertosinc.h"
#ifdef HAS_FREE_RTOS
/** /**
* A wrapper for freertos queues. Note: each element object should be small * A wrapper for freertos queues. Note: each element object should be small
* and POD (Plain Old Data type) as elements are memcpied by value. * and POD (Plain Old Data type) as elements are memcpied by value.
@@ -35,3 +37,45 @@ template <class T> class TypedQueue
bool dequeueFromISR(T *p, BaseType_t *higherPriWoken) { return xQueueReceiveFromISR(h, p, higherPriWoken); } bool dequeueFromISR(T *p, BaseType_t *higherPriWoken) { return xQueueReceiveFromISR(h, p, higherPriWoken); }
}; };
#else
#include <queue>
/**
* A wrapper for freertos queues. Note: each element object should be small
* and POD (Plain Old Data type) as elements are memcpied by value.
*/
template <class T> class TypedQueue
{
std::queue<T> q;
public:
TypedQueue(int maxElements) {}
// int numFree() { return uxQueueSpacesAvailable(h); }
bool isEmpty() { return q.empty(); }
bool enqueue(T x, TickType_t maxWait = portMAX_DELAY)
{
q.push(x);
return true;
}
// bool enqueueFromISR(T x, BaseType_t *higherPriWoken) { return xQueueSendToBackFromISR(h, &x, higherPriWoken) == pdTRUE; }
bool dequeue(T *p, TickType_t maxWait = portMAX_DELAY)
{
if (isEmpty())
return false;
else {
*p = q.front();
q.pop();
return true;
}
}
// bool dequeueFromISR(T *p, BaseType_t *higherPriWoken) { return xQueueReceiveFromISR(h, p, higherPriWoken); }
};
#endif

View File

@@ -8,7 +8,9 @@
#define member_size(type, member) sizeof(((type *)0)->member) #define member_size(type, member) sizeof(((type *)0)->member)
/// max number of packets which can be waiting for delivery to android - note, this value comes from mesh.options protobuf /// max number of packets which can be waiting for delivery to android - note, this value comes from mesh.options protobuf
#define MAX_RX_TOPHONE (member_size(DeviceState, receive_queue) / member_size(DeviceState, receive_queue[0])) // FIXME - max_count is actually 32 but we save/load this as one long string of preencoded MeshPacket bytes - not a big array in RAM
// #define MAX_RX_TOPHONE (member_size(DeviceState, receive_queue) / member_size(DeviceState, receive_queue[0]))
#define MAX_RX_TOPHONE 32
/// max number of nodes allowed in the mesh /// max number of nodes allowed in the mesh
#define MAX_NUM_NODES (member_size(DeviceState, node_db) / member_size(DeviceState, node_db[0])) #define MAX_NUM_NODES (member_size(DeviceState, node_db) / member_size(DeviceState, node_db[0]))

View File

@@ -39,7 +39,7 @@ PB_BIND(NodeInfo, NodeInfo, AUTO)
PB_BIND(MyNodeInfo, MyNodeInfo, AUTO) PB_BIND(MyNodeInfo, MyNodeInfo, AUTO)
PB_BIND(DeviceState, DeviceState, 4) PB_BIND(DeviceState, DeviceState, 2)
PB_BIND(DebugString, DebugString, 2) PB_BIND(DebugString, DebugString, 2)

View File

@@ -183,7 +183,7 @@ typedef struct _DeviceState {
pb_size_t node_db_count; pb_size_t node_db_count;
NodeInfo node_db[32]; NodeInfo node_db[32];
pb_size_t receive_queue_count; pb_size_t receive_queue_count;
MeshPacket receive_queue[32]; MeshPacket receive_queue[1];
bool has_rx_text_message; bool has_rx_text_message;
MeshPacket rx_text_message; MeshPacket rx_text_message;
uint32_t version; uint32_t version;
@@ -244,7 +244,7 @@ typedef struct _ToRadio {
#define RadioConfig_UserPreferences_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0}} #define RadioConfig_UserPreferences_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0}}
#define NodeInfo_init_default {0, false, User_init_default, false, Position_init_default, 0, 0} #define NodeInfo_init_default {0, false, User_init_default, false, Position_init_default, 0, 0}
#define MyNodeInfo_init_default {0, 0, 0, "", "", "", 0, 0, 0, 0, 0, 0, 0, 0} #define MyNodeInfo_init_default {0, 0, 0, "", "", "", 0, 0, 0, 0, 0, 0, 0, 0}
#define DeviceState_init_default {false, RadioConfig_init_default, false, MyNodeInfo_init_default, false, User_init_default, 0, {NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default}, 0, {MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default}, false, MeshPacket_init_default, 0} #define DeviceState_init_default {false, RadioConfig_init_default, false, MyNodeInfo_init_default, false, User_init_default, 0, {NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default}, 0, {MeshPacket_init_default}, false, MeshPacket_init_default, 0}
#define DebugString_init_default {""} #define DebugString_init_default {""}
#define FromRadio_init_default {0, 0, {MeshPacket_init_default}} #define FromRadio_init_default {0, 0, {MeshPacket_init_default}}
#define ToRadio_init_default {0, {MeshPacket_init_default}} #define ToRadio_init_default {0, {MeshPacket_init_default}}
@@ -260,7 +260,7 @@ typedef struct _ToRadio {
#define RadioConfig_UserPreferences_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0}} #define RadioConfig_UserPreferences_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0}}
#define NodeInfo_init_zero {0, false, User_init_zero, false, Position_init_zero, 0, 0} #define NodeInfo_init_zero {0, false, User_init_zero, false, Position_init_zero, 0, 0}
#define MyNodeInfo_init_zero {0, 0, 0, "", "", "", 0, 0, 0, 0, 0, 0, 0, 0} #define MyNodeInfo_init_zero {0, 0, 0, "", "", "", 0, 0, 0, 0, 0, 0, 0, 0}
#define DeviceState_init_zero {false, RadioConfig_init_zero, false, MyNodeInfo_init_zero, false, User_init_zero, 0, {NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero}, 0, {MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero}, false, MeshPacket_init_zero, 0} #define DeviceState_init_zero {false, RadioConfig_init_zero, false, MyNodeInfo_init_zero, false, User_init_zero, 0, {NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero}, 0, {MeshPacket_init_zero}, false, MeshPacket_init_zero, 0}
#define DebugString_init_zero {""} #define DebugString_init_zero {""}
#define FromRadio_init_zero {0, 0, {MeshPacket_init_zero}} #define FromRadio_init_zero {0, 0, {MeshPacket_init_zero}}
#define ToRadio_init_zero {0, {MeshPacket_init_zero}} #define ToRadio_init_zero {0, {MeshPacket_init_zero}}
@@ -596,7 +596,7 @@ extern const pb_msgdesc_t ManufacturingData_msg;
#define RadioConfig_UserPreferences_size 93 #define RadioConfig_UserPreferences_size 93
#define NodeInfo_size 132 #define NodeInfo_size 132
#define MyNodeInfo_size 110 #define MyNodeInfo_size 110
#define DeviceState_size 15100 #define DeviceState_size 5305
#define DebugString_size 258 #define DebugString_size 258
#define FromRadio_size 322 #define FromRadio_size 322
#define ToRadio_size 316 #define ToRadio_size 316

View File

@@ -1,100 +0,0 @@
#ifdef ARDUINO_NRF52840_PPR
#include "PmuBQ25703A.h"
#include <assert.h>
// Default address for device. Note, it is without read/write bit. When read with analyser,
// this will appear 1 bit shifted to the left
#define BQ25703ADevaddr 0xD6
const byte Lorro_BQ25703A::BQ25703Aaddr = BQ25703ADevaddr;
void PmuBQ25703A::init()
{
// Set the watchdog timer to not have a timeout
regs.chargeOption0.set_WDTMR_ADJ(0);
assert(writeRegEx(regs.chargeOption0)); // FIXME, instead log a critical hw failure and reboot
delay(15); // FIXME, why are these delays required? - check datasheet
// Set the ADC on IBAT and PSYS to record values
// When changing bitfield values, call the writeRegEx function
// This is so you can change all the bits you want before sending out the byte.
regs.chargeOption1.set_EN_IBAT(1);
regs.chargeOption1.set_EN_PSYS(1);
assert(writeRegEx(regs.chargeOption1));
delay(15);
// Set ADC to make continuous readings. (uses more power)
regs.aDCOption.set_ADC_CONV(1);
// Set individual ADC registers to read. All have default off.
regs.aDCOption.set_EN_ADC_VBUS(1);
regs.aDCOption.set_EN_ADC_PSYS(1);
regs.aDCOption.set_EN_ADC_IDCHG(1);
regs.aDCOption.set_EN_ADC_ICHG(1);
regs.aDCOption.set_EN_ADC_VSYS(1);
regs.aDCOption.set_EN_ADC_VBAT(1);
// Once bits have been twiddled, send bytes to device
assert(writeRegEx(regs.aDCOption));
delay(15);
}
#endif
/*
//Initialise the device and library
Lorro_BQ25703A BQ25703A;
//Instantiate with reference to global set
extern Lorro_BQ25703A::Regt BQ25703Areg;
uint32_t previousMillis;
uint16_t loopInterval = 1000;
void setup() {
Serial.begin(115200);
}
void loop() {
uint32_t currentMillis = millis();
if( currentMillis - previousMillis > loopInterval ){
previousMillis = currentMillis;
Serial.print( "Voltage of VBUS: " );
Serial.print( BQ25703Areg.aDCVBUSPSYS.get_VBUS() );
Serial.println( "mV" );
delay( 15 );
Serial.print( "System power usage: " );
Serial.print( BQ25703Areg.aDCVBUSPSYS.get_sysPower() );
Serial.println( "W" );
delay( 15 );
Serial.print( "Voltage of VBAT: " );
Serial.print( BQ25703Areg.aDCVSYSVBAT.get_VBAT() );
Serial.println( "mV" );
delay( 15 );
Serial.print( "Voltage of VSYS: " );
Serial.print( BQ25703Areg.aDCVSYSVBAT.get_VSYS() );
Serial.println( "mV" );
delay( 15 );
Serial.print( "Charging current: " );
Serial.print( BQ25703Areg.aDCIBAT.get_ICHG() );
Serial.println( "mA" );
delay( 15 );
Serial.print( "Voltage of VSYS: " );
Serial.print( BQ25703Areg.aDCIBAT.get_IDCHG() );
Serial.println( "mA" );
delay( 15 );
}
}*/

View File

@@ -1,22 +0,0 @@
#pragma once
#include <Lorro_BQ25703A.h>
class PmuBQ25703A : private Lorro_BQ25703A
{
Lorro_BQ25703A::Regt regs;
public:
/**
* Configure the PMU for our board
*/
void init();
// Methods to have a common API with AXP192
bool isBatteryConnect() { return true; } // FIXME
bool isVBUSPlug() { return true; }
bool isChargeing() { return true; } // FIXME, intentional misspelling
/// battery voltage in mV
int getBattVoltage() { return 3200; }
};

View File

@@ -1,3 +0,0 @@
#pragma once
// FIXME - make a FS abstraction for NRF52

View File

@@ -36,15 +36,18 @@ class UC1701Spi : public OLEDDisplay
}; };
#include "variant.h" #include "variant.h"
#ifdef ERC12864_CS
#include <UC1701.h> #include <UC1701.h>
static UC1701 lcd(PIN_SPI_SCK, PIN_SPI_MOSI, ERC12864_CS, ERC12864_CD); 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();
void testLCD() { // Write a piece of text on the first line...
// PCD8544-compatible displays may have a different resolution... lcd.setCursor(0, 0);
lcd.begin(); lcd.print("Hello, World!");
}
// Write a piece of text on the first line... #endif
lcd.setCursor(0, 0);
lcd.print("Hello, World!");
}

View File

@@ -59,12 +59,6 @@ void setBluetoothEnable(bool on)
} }
} }
#ifdef ARDUINO_NRF52840_PPR
#include "PmuBQ25703A.h"
PmuBQ25703A pmu;
#endif
void nrf52Setup() void nrf52Setup()
{ {

View File

@@ -34,7 +34,11 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define FONT_HEIGHT 14 // actually 13 for "ariel 10" but want a little extra space #define FONT_HEIGHT 14 // actually 13 for "ariel 10" but want a little extra space
#define FONT_HEIGHT_16 (ArialMT_Plain_16[1] + 1) #define FONT_HEIGHT_16 (ArialMT_Plain_16[1] + 1)
#ifdef USE_SH1106
#define SCREEN_WIDTH 132
#else
#define SCREEN_WIDTH 128 #define SCREEN_WIDTH 128
#endif
#define SCREEN_HEIGHT 64 #define SCREEN_HEIGHT 64
#define TRANSITION_FRAMERATE 30 // fps #define TRANSITION_FRAMERATE 30 // fps
#define IDLE_FRAMERATE 10 // in fps #define IDLE_FRAMERATE 10 // in fps
@@ -663,7 +667,7 @@ void DebugInfo::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16
} }
if (!gpsStatus.empty()) { if (!gpsStatus.empty()) {
snprintf(gpsStr, sizeof(gpsStr), "GPS %s", gpsStatus.c_str()); snprintf(gpsStr, sizeof(gpsStr), "%s", gpsStatus.c_str());
} else { } else {
gpsStr[0] = '\0'; // Just show empty string. gpsStr[0] = '\0'; // Just show empty string.
} }

View File

@@ -3,7 +3,12 @@
#include <cstring> #include <cstring>
#include <OLEDDisplayUi.h> #include <OLEDDisplayUi.h>
#ifdef USE_SH1106
#include <SH1106Wire.h>
#else
#include <SSD1306Wire.h> #include <SSD1306Wire.h>
#endif
#include "PeriodicTask.h" #include "PeriodicTask.h"
#include "TypedQueue.h" #include "TypedQueue.h"
@@ -211,7 +216,11 @@ class Screen : public PeriodicTask
/// Holds state for debug information /// Holds state for debug information
DebugInfo debugInfo; DebugInfo debugInfo;
/// Display device /// Display device
#ifdef USE_SH1106
SH1106Wire dispdev;
#else
SSD1306Wire dispdev; SSD1306Wire dispdev;
#endif
/// UI helper for rendering to frames and switching between them /// UI helper for rendering to frames and switching between them
OLEDDisplayUi ui; OLEDDisplayUi ui;
}; };

View File

@@ -129,7 +129,7 @@ static void waitEnterSleep()
if (millis() - now > 30 * 1000) { // If we wait too long just report an error and go to sleep if (millis() - now > 30 * 1000) { // If we wait too long just report an error and go to sleep
recordCriticalError(ErrSleepEnterWait); recordCriticalError(ErrSleepEnterWait);
ESP.restart(); // FIXME - for now we just restart, need to fix bug #167 assert(0); // FIXME - for now we just restart, need to fix bug #167
break; break;
} }
} }
@@ -289,9 +289,7 @@ esp_sleep_wakeup_cause_t doLightSleep(uint64_t sleepMsec) // FIXME, use a more r
return cause; return cause;
} }
#endif
#if 0
// not legal on the stock android ESP build // not legal on the stock android ESP build
/** /**
@@ -306,7 +304,7 @@ void enableModemSleep()
static esp_pm_config_esp32_t config; // filled with zeros because bss static esp_pm_config_esp32_t config; // filled with zeros because bss
config.max_freq_mhz = CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ; config.max_freq_mhz = CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ;
config.min_freq_mhz = 10; // 10Mhz is minimum recommended config.min_freq_mhz = 20; // 10Mhz is minimum recommended
config.light_sleep_enable = false; config.light_sleep_enable = false;
DEBUG_MSG("Sleep request result %x\n", esp_pm_configure(&config)); DEBUG_MSG("Sleep request result %x\n", esp_pm_configure(&config));
} }

View File

@@ -34,4 +34,6 @@ extern Observable<void *> preflightSleep;
extern Observable<void *> notifySleep; extern Observable<void *> notifySleep;
/// Called to tell observers we are now entering (deep) sleep and you should prepare. Must return 0 /// Called to tell observers we are now entering (deep) sleep and you should prepare. Must return 0
extern Observable<void *> notifyDeepSleep; extern Observable<void *> notifyDeepSleep;
void enableModemSleep();

View File

@@ -137,6 +137,7 @@ static const uint8_t SCK = PIN_SPI_SCK;
// #define SX1262_ANT_SW (32 + 10) // #define SX1262_ANT_SW (32 + 10)
#define SX1262_RXEN (22) #define SX1262_RXEN (22)
#define SX1262_TXEN (24) #define SX1262_TXEN (24)
#define SX1262_E22 // Indicates this SX1262 is inside of an ebyte E22 module and special config should be done for that
// ERC12864-10 LCD // ERC12864-10 LCD
#define ERC12864_CS (32 + 4) #define ERC12864_CS (32 + 4)