mirror of
https://github.com/meshtastic/firmware.git
synced 2025-12-17 16:22:48 +00:00
Compare commits
66 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
aaa6af3f38 | ||
|
|
b11b322581 | ||
|
|
60b38215ce | ||
|
|
53e68515dd | ||
|
|
7676ae9184 | ||
|
|
b385feefa5 | ||
|
|
fc50b4abc0 | ||
|
|
0104a2eb3a | ||
|
|
23fdc9d1a9 | ||
|
|
ea4a678308 | ||
|
|
6566c4f15e | ||
|
|
6f39f1740f | ||
|
|
7b61bdbfd2 | ||
|
|
8e65db19b0 | ||
|
|
698fcdad36 | ||
|
|
c25d6e974f | ||
|
|
35aae48932 | ||
|
|
f8afa2703f | ||
|
|
cd903dceb9 | ||
|
|
5843c6f25e | ||
|
|
3005373760 | ||
|
|
7678540a93 | ||
|
|
463666aec5 | ||
|
|
5847f94ece | ||
|
|
09855b76ef | ||
|
|
f4d476d160 | ||
|
|
d88d4be63e | ||
|
|
154114e900 | ||
|
|
03f019dea2 | ||
|
|
a47524b762 | ||
|
|
fd2f5a5ba4 | ||
|
|
e66b2234f6 | ||
|
|
f35b15b09c | ||
|
|
99dac51b9d | ||
|
|
656faf4ce9 | ||
|
|
d9ab6986ad | ||
|
|
514d45c219 | ||
|
|
94b7fc76c1 | ||
|
|
e9923ac257 | ||
|
|
60ad1793e4 | ||
|
|
96a15bec3b | ||
|
|
fba676fc07 | ||
|
|
9ad14ad98b | ||
|
|
477c62082d | ||
|
|
82169d4115 | ||
|
|
362d5452d5 | ||
|
|
92e5a15399 | ||
|
|
114e0c4ada | ||
|
|
075ff26499 | ||
|
|
d65f2ede81 | ||
|
|
4a9248a451 | ||
|
|
1c6092c430 | ||
|
|
0e9ed1e82f | ||
|
|
02ce0558b9 | ||
|
|
63110f0134 | ||
|
|
d8db4449be | ||
|
|
fda98bbf58 | ||
|
|
aadba1f694 | ||
|
|
2c8d152885 | ||
|
|
37c598833c | ||
|
|
e382a181f7 | ||
|
|
f02a2c0853 | ||
|
|
71a4cfefd5 | ||
|
|
1c63a70673 | ||
|
|
8022f3b920 | ||
|
|
4db176867b |
@@ -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
3
bin/dump-ram-users.sh
Executable 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'
|
||||||
@@ -1,3 +1,3 @@
|
|||||||
|
|
||||||
|
|
||||||
export VERSION=0.7.5
|
export VERSION=0.7.8
|
||||||
@@ -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:
|
||||||
|
|
||||||
[](https://play.google.com/store/apps/details?id=com.geeksville.mesh&referrer=utm_source%3Dhomepage%26anid%3Dadmob)
|
[](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:
|
||||||
|
|
||||||
|
|||||||
@@ -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) ;-)
|
||||||
|
|||||||
6
docs/hardware/cubecell-TODO.md
Normal file
6
docs/hardware/cubecell-TODO.md
Normal 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).
|
||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|||||||
@@ -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.
|
||||||
16
docs/software/esp32-arduino-build-notes.md
Normal file
16
docs/software/esp32-arduino-build-notes.md
Normal 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/
|
||||||
|
```
|
||||||
@@ -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
27
docs/software/pinetab.md
Normal 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
|
||||||
202
docs/software/ramusage-nrf52.txt
Normal file
202
docs/software/ramusage-nrf52.txt
Normal 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
|
||||||
@@ -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. */
|
||||||
|
|||||||
46
linker/nrf52840_s140_sim832.ld
Normal file
46
linker/nrf52840_s140_sim832.ld
Normal 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"
|
||||||
@@ -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
2
proto
Submodule proto updated: e7f181ef6f...72cbde93ff
@@ -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, ¬ification, portMAX_DELAY); // Wait forever
|
clearOnRead, ¬ification, portMAX_DELAY); // Wait forever
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -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
|
||||||
@@ -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
1
src/cubecell/FS.h
Normal file
@@ -0,0 +1 @@
|
|||||||
|
// Placeholder FIXME
|
||||||
@@ -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;
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -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);
|
||||||
|
|||||||
15
src/lock.cpp
15
src/lock.cpp
@@ -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)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|||||||
19
src/main.cpp
19
src/main.cpp
@@ -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.
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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++;
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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();
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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);
|
||||||
@@ -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);
|
||||||
|
|||||||
@@ -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...
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|||||||
@@ -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:
|
||||||
|
|
||||||
};
|
};
|
||||||
@@ -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
|
||||||
|
|||||||
@@ -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]))
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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 );
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}*/
|
|
||||||
@@ -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; }
|
|
||||||
};
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
// FIXME - make a FS abstraction for NRF52
|
|
||||||
@@ -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!");
|
|
||||||
}
|
|
||||||
@@ -59,12 +59,6 @@ void setBluetoothEnable(bool on)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef ARDUINO_NRF52840_PPR
|
|
||||||
#include "PmuBQ25703A.h"
|
|
||||||
|
|
||||||
PmuBQ25703A pmu;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void nrf52Setup()
|
void nrf52Setup()
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|||||||
@@ -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.
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -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));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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();
|
||||||
@@ -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)
|
||||||
|
|||||||
Reference in New Issue
Block a user