mirror of
https://github.com/meshtastic/firmware.git
synced 2025-12-21 18:22:32 +00:00
Compare commits
6 Commits
0.8.1
...
0.8.1-fixe
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d248c6be4b | ||
|
|
39b0a89821 | ||
|
|
d9f43d3e2f | ||
|
|
08c77caaa9 | ||
|
|
cfedc97cd0 | ||
|
|
cfad226b2b |
7
.github/workflows/main.yml
vendored
7
.github/workflows/main.yml
vendored
@@ -9,8 +9,6 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@master
|
||||
- name: Checkout submodules
|
||||
uses: textbook/git-checkout-submodule-action@master
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@master
|
||||
with:
|
||||
@@ -19,8 +17,5 @@ jobs:
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install -U platformio
|
||||
- name: Install extra python tools
|
||||
run: |
|
||||
pip install -U adafruit-nrfutil
|
||||
- name: Build
|
||||
run: platformio run -e tbeam -e heltec -e nrf52840dk -e rak815
|
||||
run: platformio run
|
||||
|
||||
3
.vscode/settings.json
vendored
3
.vscode/settings.json
vendored
@@ -47,8 +47,7 @@
|
||||
"memory_resource": "cpp",
|
||||
"optional": "cpp",
|
||||
"string_view": "cpp",
|
||||
"cassert": "cpp",
|
||||
"iterator": "cpp"
|
||||
"cassert": "cpp"
|
||||
},
|
||||
"cSpell.words": [
|
||||
"Blox",
|
||||
|
||||
@@ -24,16 +24,14 @@ We currently support three models of radios.
|
||||
|
||||
- TTGO T-Beam (usually the recommended choice)
|
||||
- [T-Beam V1.1 w/ NEO-6M - special Meshtastic version](https://www.aliexpress.com/item/4001178678568.html) (Includes built-in OLED display and they have **preinstalled** the meshtastic software)
|
||||
- [T-Beam V1.1 w/ NEO-M8N](https://www.aliexpress.com/item/33047631119.html) (slightly better GPS)
|
||||
- [T-Beam V1.0 w/ NEO-M8N](https://www.aliexpress.com/item/33047631119.html) (slightly better GPS)
|
||||
- [T-Beam V0.7 w/ NEO-6M](https://www.aliexpress.com/item/4000574335430.html) (will work but **you must use the tbeam0.7 firmware ** - but the T-Beam V1.0 or later are better!)
|
||||
- board labels "TTGO T22_V07 20180711"
|
||||
- 3D printable cases
|
||||
- [T-Beam V0](https://www.thingiverse.com/thing:3773717)
|
||||
- [T-Beam V1](https://www.thingiverse.com/thing:3830711)
|
||||
|
||||
- [TTGO LORA32](https://www.aliexpress.com/item/4000211331316.html) - No GPS
|
||||
- version 2.1
|
||||
- board labels "TTGO T3_V1.6 20180606"
|
||||
|
||||
- 3D printable case
|
||||
- [TTGO LORA32 v1](https://www.thingiverse.com/thing:3385109)
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ COUNTRIES="US EU433 EU865 CN JP"
|
||||
#COUNTRIES=US
|
||||
#COUNTRIES=CN
|
||||
|
||||
BOARDS="ttgo-lora32-v2 ttgo-lora32-v1 tbeam heltec tbeam0.7"
|
||||
BOARDS="tlora-v2 tlora-v1 tlora-v2-1-1.6 tbeam heltec tbeam0.7"
|
||||
#BOARDS=tbeam
|
||||
|
||||
OUTDIR=release/latest
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
|
||||
|
||||
export VERSION=0.7.11
|
||||
export VERSION=0.8.1
|
||||
@@ -1,47 +0,0 @@
|
||||
{
|
||||
"build": {
|
||||
"arduino": {
|
||||
"ldscript": "nrf52840_s140_v6.ld"
|
||||
},
|
||||
"core": "nRF5",
|
||||
"cpu": "cortex-m4",
|
||||
"extra_flags": "-DARDUINO_NRF52840_PCA10056 -DNRF52840_XXAA",
|
||||
"f_cpu": "64000000L",
|
||||
"hwids": [["0x239A", "0x4404"]],
|
||||
"usb_product": "nrf52840dk",
|
||||
"mcu": "nrf52840",
|
||||
"variant": "pca10056",
|
||||
"variants_dir": "variants",
|
||||
"bsp": {
|
||||
"name": "adafruit"
|
||||
},
|
||||
"softdevice": {
|
||||
"sd_flags": "-DS140",
|
||||
"sd_name": "s140",
|
||||
"sd_version": "6.1.1",
|
||||
"sd_fwid": "0x00B6"
|
||||
},
|
||||
"bootloader": {
|
||||
"settings_addr": "0xFF000"
|
||||
}
|
||||
},
|
||||
"connectivity": ["bluetooth"],
|
||||
"debug": {
|
||||
"jlink_device": "nRF52840_xxAA",
|
||||
"onboard_tools": ["jlink"],
|
||||
"svd_path": "nrf52840.svd"
|
||||
},
|
||||
"frameworks": ["arduino"],
|
||||
"name": "A modified NRF52840-DK devboard (Adafruit BSP)",
|
||||
"upload": {
|
||||
"maximum_ram_size": 248832,
|
||||
"maximum_size": 815104,
|
||||
"require_upload_port": true,
|
||||
"speed": 115200,
|
||||
"protocol": "jlink",
|
||||
"protocols": ["jlink", "nrfjprog", "stlink"]
|
||||
},
|
||||
"url": "https://meshtastic.org/",
|
||||
"vendor": "Nordic Semi"
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
"extra_flags": "-DARDUINO_NRF52840_PCA10056 -DNRF52840_XXAA",
|
||||
"f_cpu": "64000000L",
|
||||
"hwids": [["0x239A", "0x4404"]],
|
||||
"usb_product": "nrf52840dk",
|
||||
"usb_product": "SimPPR",
|
||||
"mcu": "nrf52840",
|
||||
"variant": "pca10056-rc-clock",
|
||||
"variants_dir": "variants",
|
||||
|
||||
@@ -1,55 +0,0 @@
|
||||
{
|
||||
"build": {
|
||||
"arduino":{
|
||||
"ldscript": "nrf52832_s132_v6.ld"
|
||||
},
|
||||
"core": "nRF5",
|
||||
"cpu": "cortex-m4",
|
||||
"extra_flags": "-DNRF52832_XXAA -DNRF52",
|
||||
"f_cpu": "64000000L",
|
||||
"hwids": [
|
||||
[
|
||||
"0x10c4",
|
||||
"0xea60"
|
||||
]
|
||||
],
|
||||
"usb_product": "RAK815",
|
||||
"mcu": "nrf52832",
|
||||
"variant": "rak815",
|
||||
"bsp": {
|
||||
"name": "adafruit"
|
||||
},
|
||||
"softdevice": {
|
||||
"sd_flags": "-DS132",
|
||||
"sd_name": "s132",
|
||||
"sd_version": "6.1.1",
|
||||
"sd_fwid": "0x00B7"
|
||||
}
|
||||
},
|
||||
"connectivity": [
|
||||
"bluetooth"
|
||||
],
|
||||
"debug": {
|
||||
"jlink_device": "nRF52832_xxAA",
|
||||
"svd_path": "nrf52.svd"
|
||||
},
|
||||
"frameworks": [
|
||||
"arduino"
|
||||
],
|
||||
"name": "RAK RAK815",
|
||||
"upload": {
|
||||
"maximum_ram_size": 65536,
|
||||
"maximum_size": 524288,
|
||||
"require_upload_port": true,
|
||||
"speed": 115200,
|
||||
"protocol": "nrfutil",
|
||||
"protocols": [
|
||||
"jlink",
|
||||
"nrfjprog",
|
||||
"nrfutil",
|
||||
"stlink"
|
||||
]
|
||||
},
|
||||
"url": "https://store.rakwireless.com/products/rak815-hybrid-location-tracker",
|
||||
"vendor": "RAK"
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
| Vendor | Product line | Version | Board labels | Notes | URL |
|
||||
|---|---|---|---|---|---|
|
||||
| TTGO | T-Beam | 0.7 | T22_V07 20180711 | LoRa 433/470MHz *OR* LoRa 868/915MHz , <br/>GPS ublox NEO-6M , <br/>battery holder for Li-Ion 18650 | [buy](https://www.aliexpress.com/item/4000574335430.html) |
|
||||
| TTGO | T-Beam | 1.0 | | | [buy](https://www.aliexpress.com/item/4001178678568.html) |
|
||||
| TTGO | T-Beam | 1.1 | T22_V11 20191212 | LoRa 433/470MHz *OR* LoRa 868/915MHz *OR* LoRa 923MHz , <br/>GPS ublox NEO-M8N , <br/>battery holder for Li-Ion 18650 | [buy](https://www.aliexpress.com/item/4001178678568.html) |
|
||||
| TTGO | Lora32 | 2.0 | *missing* | LoRa 433/470MHz *OR* LoRa 868/915MHz , <br/>OLED SSD1306 , <br/>SD card holder | [buy](https://www.aliexpress.com/item/4000211331316.html) |
|
||||
| TTGO | Lora32 | 2.1 | T3_V1.6 20180606 | LoRa 32 (V2) , <br/>SD card holder | [buy](https://www.aliexpress.com/item/4000119208093.html) |
|
||||
| Heltec | Lora 32 | V2 | V2 | LoRa 433/470MHz *OR* LoRa 868/915MHz | [buy](https://heltec.org/project/wifi-lora-32/) |
|
||||
Binary file not shown.
Binary file not shown.
File diff suppressed because one or more lines are too long
Binary file not shown.
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -2,15 +2,6 @@
|
||||
|
||||
You probably don't care about this section - skip to the next one.
|
||||
|
||||
- brf52 ble
|
||||
- update protocol description per cyclomies
|
||||
- esp32 pairing
|
||||
- update faq with antennas https://meshtastic.discourse.group/t/range-test-ideas-requested/738/2
|
||||
- update faq on recommended android version and phones
|
||||
- add help link inside the app, reference a page on the wiki
|
||||
- turn on amazon reviews support
|
||||
- add a tablet layout (with map next to messages) in the android app
|
||||
|
||||
# Medium priority
|
||||
|
||||
Items to complete before 1.0.
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
# ANT protocol notes
|
||||
|
||||
SD340 terms are reasonable for NRF52
|
||||
https://www.thisisant.com/developer/components/nrf52832#tab_protocol_stacks_tab
|
||||
|
||||
Profiles to implement:
|
||||
|
||||
tracker
|
||||
https://www.thisisant.com/developer/ant-plus/device-profiles/#4365_tab
|
||||
|
||||
ebike
|
||||
https://www.thisisant.com/developer/ant-plus/device-profiles/#527_tab
|
||||
|
||||
no profile for messaging?
|
||||
@@ -1,26 +1,12 @@
|
||||
# Device API
|
||||
# Bluetooth API
|
||||
|
||||
The Device API is design to have only a simple stream of ToRadio and FromRadio packets and all polymorphism comes from the flexible set of Google Protocol Buffers which are sent over the wire. We use protocol buffers extensively both for the bluetooth API and for packets inside the mesh or when providing packets to other applications on the phone.
|
||||
The Bluetooth API is design to have only a few characteristics and most polymorphism comes from the flexible set of Google Protocol Buffers which are sent over the wire. We use protocol buffers extensively both for the bluetooth API and for packets inside the mesh or when providing packets to other applications on the phone.
|
||||
|
||||
## Streaming version
|
||||
## A note on MTU sizes
|
||||
|
||||
This protocol is **almost** identical when it is deployed over BLE, Serial/USB or TCP (our three currently supported transports for connecting to phone/PC). Most of this document is in terms of the original BLE version, but this section describes the small changes when this API is exposed over a Streaming (non datagram) transport. The streaming version has the following changes:
|
||||
This device will work with any MTU size, but it is highly recommended that you call your phone's "setMTU function to increase MTU to 512 bytes" as soon as you connect to a service. This will dramatically improve performance when reading/writing packets.
|
||||
|
||||
- We assume the stream is reliable (though the protocol will resynchronize if bytes are lost or corrupted). i.e. we do not include CRCs or error correction codes.
|
||||
- Packets always have a four byte header (described below) prefixed before each packet. This header provides framing characters and length.
|
||||
- The stream going towards the radio is only a series of ToRadio packets (with the extra 4 byte headers)
|
||||
- The stream going towards the PC is a stream of FromRadio packets (with the 4 byte headers), or if the receiver state machine does not see valid header bytes it can (optionally) print those bytes as the debug console from the radio. This allows the device to emit regular serial debugging messages (which can be understood by a terminal program) but also switch to a more structured set of protobufs once it sees that the PC client has sent a protobuf towards it.
|
||||
|
||||
The 4 byte header is constructed to both provide framing and to not look line 'normal' 7 bit ASCII.
|
||||
|
||||
- Byte 0: START1 (0x94)
|
||||
- Byte 1: START2 (0xc3)
|
||||
- Byte 2: MSB of protobuf length
|
||||
- Byte 3: LSB of protobuf length
|
||||
|
||||
The receiver will validate length and if >512 it will assume the packet is corrupted and return to looking for START1. While looking for START1 any other characters are printed as "debug output". For small example implementation of this reader see the meshtastic-python implementation.
|
||||
|
||||
## MeshBluetoothService (the BLE API)
|
||||
## MeshBluetoothService
|
||||
|
||||
This is the main bluetooth service for the device and provides the API your app should use to get information about the mesh, send packets or provision the radio.
|
||||
|
||||
@@ -85,20 +71,16 @@ Not all messages are kept in the fromradio queue (filtered based on SubPacket):
|
||||
- No WantNodeNum / DenyNodeNum messages are kept
|
||||
A variable keepAllPackets, if set to true will suppress this behavior and instead keep everything for forwarding to the phone (for debugging)
|
||||
|
||||
### A note on MTU sizes
|
||||
|
||||
This device will work with any MTU size, but it is highly recommended that you call your phone's "setMTU function to increase MTU to 512 bytes" as soon as you connect to a service. This will dramatically improve performance when reading/writing packets.
|
||||
|
||||
### Protobuf API
|
||||
## Protobuf API
|
||||
|
||||
On connect, you should send a want_config_id protobuf to the device. This will cause the device to send its node DB and radio config via the fromradio endpoint. After sending the full DB, the radio will send a want_config_id to indicate it is done sending the configuration.
|
||||
|
||||
### Other bluetooth services
|
||||
## Other bluetooth services
|
||||
|
||||
This document focuses on the core device protocol, but it is worth noting that the following other Bluetooth services are also
|
||||
This document focuses on the core mesh service, but it is worth noting that the following other Bluetooth services are also
|
||||
provided by the device.
|
||||
|
||||
#### BluetoothSoftwareUpdate
|
||||
### BluetoothSoftwareUpdate
|
||||
|
||||
The software update service. For a sample function that performs a software update using this API see [startUpdate](https://github.com/meshtastic/Meshtastic-Android/blob/master/app/src/main/java/com/geeksville/mesh/service/SoftwareUpdateService.kt).
|
||||
|
||||
@@ -116,10 +98,10 @@ Characteristics
|
||||
| GATT_UUID_MANU_NAME/0x2a29 | read | |
|
||||
| GATT_UUID_HW_VERSION_STR/0x2a27 | read | |
|
||||
|
||||
#### DeviceInformationService
|
||||
### DeviceInformationService
|
||||
|
||||
Implements the standard BLE contract for this service (has software version, hardware model, serial number, etc...)
|
||||
|
||||
#### BatteryLevelService
|
||||
### BatteryLevelService
|
||||
|
||||
Implements the standard BLE contract service, provides battery level in a way that most client devices should automatically understand (i.e. it should show in the bluetooth devices screen automatically)
|
||||
@@ -1,19 +1,13 @@
|
||||
# NRF52 TODO
|
||||
|
||||
|
||||
## RAK815
|
||||
|
||||
TODO:
|
||||
|
||||
- i2c gps comms not quite right
|
||||
- ble: AdafruitBluefruit::begin - adafruit_ble_task was assigned an invalid stack pointer. out of memory?
|
||||
- measure power draw
|
||||
|
||||
### Bootloader
|
||||
|
||||
Install our (temporarily hacked up) adafruit bootloader
|
||||
### Bootloader
|
||||
Installing the adafruit bootloader is optional - I think the stock bootloader will work okay for most.
|
||||
|
||||
```
|
||||
kevinh@kevin-server:~/development/meshtastic/Adafruit_nRF52_Bootloader$ make BOARD=rak815 sd flash
|
||||
kevinh@kevin-server:~/development/meshtastic/Adafruit_nRF52_Bootloader$ make BOARD=rak815 flash
|
||||
LD rak815_bootloader-0.3.2-111-g9478eb7-dirty.out
|
||||
text data bss dec hex filename
|
||||
20888 1124 15006 37018 909a _build/build-rak815/rak815_bootloader-0.3.2-111-g9478eb7-dirty.out
|
||||
@@ -37,52 +31,20 @@ Applying system reset.
|
||||
Run.
|
||||
```
|
||||
|
||||
### Appload
|
||||
|
||||
tips on installing https://github.com/platformio/platform-nordicnrf52/issues/8#issuecomment-374017768
|
||||
|
||||
to see console output over jlink:
|
||||
|
||||
```
|
||||
12:17
|
||||
in one tab run "bin/nrf52832-gdbserver.sh" - leave this running the whole time while developing/debugging
|
||||
12:17
|
||||
~/development/meshtastic/meshtastic-esp32$ bin/nrf52-console.sh
|
||||
###RTT Client: ************************************************************
|
||||
###RTT Client: * SEGGER Microcontroller GmbH *
|
||||
###RTT Client: * Solutions for real time microcontroller applications *
|
||||
###RTT Client: ************************************************************
|
||||
###RTT Client: * *
|
||||
###RTT Client: * (c) 2012 - 2016 SEGGER Microcontroller GmbH *
|
||||
###RTT Client: * *
|
||||
###RTT Client: * www.segger.com Support: support@segger.com *
|
||||
###RTT Client: * *
|
||||
###RTT Client: ************************************************************
|
||||
###RTT Client: * *
|
||||
###RTT Client: * SEGGER J-Link RTT Client Compiled Apr 7 2020 15:01:22 *
|
||||
###RTT Client: * *
|
||||
###RTT Client: ************************************************************
|
||||
###RTT Client: -----------------------------------------------
|
||||
###RTT Client: Connecting to J-Link RTT Server via localhost:19021 ..............
|
||||
###RTT Client: Connected.
|
||||
SEGGER J-Link V6.70c - Real time terminal output
|
||||
SEGGER J-Link ARM V9.6, SN=69663845
|
||||
Process: JLinkGDBServerCLExein another tab run:
|
||||
12:18
|
||||
On NRF52 I've been using the jlink fake serial console. But since the rak815 has the serial port hooked up we can switch back to that once the basics are working.
|
||||
```
|
||||
|
||||
## Misc work items
|
||||
|
||||
RAM investigation.
|
||||
nRF52832-QFAA 64KB ram, 512KB flash vs
|
||||
nrf52832-QFAB 32KB ram, 512kb flash
|
||||
nrf52833 128KB RAM
|
||||
nrf52840 256KB RAM, 1MB flash
|
||||
|
||||
Manual hacks needed to build (for now):
|
||||
platform.json
|
||||
|
||||
kevinh@kevin-server:~/.platformio/packages/framework-arduinoadafruitnrf52/variants\$ ln -s ~/development/meshtastic/meshtastic-esp32/variants/\* .
|
||||
"framework-arduinoadafruitnrf52": {
|
||||
"type": "framework",
|
||||
"optional": true,
|
||||
"version": "https://github.com/meshtastic/Adafruit_nRF52_Arduino.git"
|
||||
},
|
||||
|
||||
## Initial work items
|
||||
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
# RAK815
|
||||
|
||||
Notes on trying to get the RAK815 working with meshtastic.
|
||||
|
||||
good tutorial: https://www.hackster.io/naresh-krish/getting-started-with-rak815-tracker-module-and-arduino-1c7bc9
|
||||
(includes software serial link - possibly useful for GPS)
|
||||
@@ -74,7 +74,7 @@ lib_deps =
|
||||
Wire ; explicitly needed here because the AXP202 library forgets to add it
|
||||
https://github.com/meshtastic/arduino-fsm.git
|
||||
https://github.com/meshtastic/SparkFun_Ublox_Arduino_Library.git
|
||||
https://github.com/meshtastic/RadioLib.git#d6b12f7eb0a06bd2414c79b437b25d377e3f603f
|
||||
https://github.com/meshtastic/RadioLib.git#6aa38a85856012c99c4e9b4e7cee35e37671a4bc
|
||||
https://github.com/meshtastic/TinyGPSPlus.git
|
||||
|
||||
; Common settings for ESP targes, mixin with extends = esp32_base
|
||||
@@ -90,7 +90,7 @@ build_flags =
|
||||
# board_build.ldscript = linker/esp32.extram.bss.ld
|
||||
lib_ignore = segger_rtt
|
||||
platform_packages =
|
||||
framework-arduinoespressif32 @ https://github.com/meshtastic/arduino-esp32.git#71ed4002c953d8c87f44ed27e34fe0735f99013e
|
||||
framework-arduinoespressif32 @ https://github.com/meshtastic/arduino-esp32.git#7a78d82f1b5cf64715a14d2f096b8dd775948ac1
|
||||
|
||||
; The 1.0 release of the TBEAM board
|
||||
[env:tbeam]
|
||||
@@ -147,9 +147,7 @@ src_filter =
|
||||
|
||||
; Common settings for NRF52 based targets
|
||||
[nrf52_base]
|
||||
; Instead of the standard nordicnrf52 platform, we use our fork which has our added variant files
|
||||
; platform = nordicnrf52
|
||||
platform = https://github.com/meshtastic/platform-nordicnrf52.git#62d185fe61b6c84c554046106529b4fd8f155e2c
|
||||
platform = nordicnrf52
|
||||
debug_tool = jlink
|
||||
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)
|
||||
@@ -174,30 +172,10 @@ debug_init_break =
|
||||
;debug_init_break = tbreak Reset_Handler
|
||||
|
||||
; The NRF52840-dk development board
|
||||
; Note: By default no lora device is created for this build - it uses a simulated interface
|
||||
[env:nrf52840dk]
|
||||
extends = nrf52_base
|
||||
board = nrf52840_dk
|
||||
|
||||
; The NRF52840-dk development board, but @geeksville's board - which has a busted oscilliator
|
||||
[env:nrf52840dk-geeksville]
|
||||
[env:nrf52dk]
|
||||
extends = nrf52_base
|
||||
board = nrf52840_dk_modified
|
||||
|
||||
; Note: By default no lora device is created for this build - it uses a simulated interface
|
||||
[env:feather_nrf52832]
|
||||
extends = nrf52_base
|
||||
board = adafruit_feather_nrf52832
|
||||
|
||||
[env:rak815]
|
||||
extends = nrf52_base
|
||||
board = rak815
|
||||
debug_tool = jlink
|
||||
upload_protocol = jlink
|
||||
monitor_port = /dev/ttyUSB0
|
||||
; this board's serial chip can only run at 115200, not faster
|
||||
monitor_speed = 115200
|
||||
|
||||
# For experimenting with RAM sizes
|
||||
# board_build.ldscript = linker/nrf52840_s140_sim832.ld
|
||||
|
||||
|
||||
2
proto
2
proto
Submodule proto updated: ab281311c4...0523977d1f
@@ -1,16 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
/**
|
||||
* Common lib functions for all platforms that have bluetooth
|
||||
*/
|
||||
|
||||
#define MESH_SERVICE_UUID "6ba1b218-15a8-461f-9fa8-5dcae273eafd"
|
||||
|
||||
#define TORADIO_UUID "f75c76d2-129e-4dad-a1dd-7866124401e7"
|
||||
#define FROMRADIO_UUID "8ba2bcc2-ee02-4a55-a531-c525c5e454d5"
|
||||
#define FROMNUM_UUID "ed9da18c-a800-4f66-a670-aa7547e34453"
|
||||
|
||||
/// Given a level between 0-100, update the BLE attribute
|
||||
void updateBatteryLevel(uint8_t level);
|
||||
@@ -1,13 +1,7 @@
|
||||
#include "Thread.h"
|
||||
#include "timing.h"
|
||||
#include <assert.h>
|
||||
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
#include "esp_task_wdt.h"
|
||||
#endif
|
||||
|
||||
namespace concurrency
|
||||
{
|
||||
namespace concurrency {
|
||||
|
||||
void Thread::start(const char *name, size_t stackSize, uint32_t priority)
|
||||
{
|
||||
@@ -20,27 +14,4 @@ void Thread::callRun(void *_this)
|
||||
((Thread *)_this)->doRun();
|
||||
}
|
||||
|
||||
void Thread::serviceWatchdog()
|
||||
{
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
esp_task_wdt_reset();
|
||||
#endif
|
||||
}
|
||||
|
||||
void Thread::startWatchdog()
|
||||
{
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
auto r = esp_task_wdt_add(taskHandle);
|
||||
assert(r == ESP_OK);
|
||||
#endif
|
||||
}
|
||||
|
||||
void Thread::stopWatchdog()
|
||||
{
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
auto r = esp_task_wdt_delete(taskHandle);
|
||||
assert(r == ESP_OK);
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace concurrency
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "freertosinc.h"
|
||||
#include "esp_task_wdt.h"
|
||||
|
||||
namespace concurrency {
|
||||
|
||||
@@ -35,9 +36,17 @@ class Thread
|
||||
*
|
||||
* this only applies after startWatchdog() has been called. If you need to sleep for a long time call stopWatchdog()
|
||||
*/
|
||||
void serviceWatchdog();
|
||||
void startWatchdog();
|
||||
void stopWatchdog();
|
||||
void serviceWatchdog() { esp_task_wdt_reset(); }
|
||||
void startWatchdog()
|
||||
{
|
||||
auto r = esp_task_wdt_add(taskHandle);
|
||||
assert(r == ESP_OK);
|
||||
}
|
||||
void stopWatchdog()
|
||||
{
|
||||
auto r = esp_task_wdt_delete(taskHandle);
|
||||
assert(r == ESP_OK);
|
||||
}
|
||||
|
||||
private:
|
||||
static void callRun(void *_this);
|
||||
|
||||
@@ -55,17 +55,13 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
/// Convert a preprocessor name into a quoted string and if that string is empty use "unset"
|
||||
#define optstr(s) (xstr(s)[0] ? xstr(s) : "unset")
|
||||
|
||||
#ifdef NRF52_SERIES // All of the NRF52 targets are configured using variant.h, so this section shouldn't need to be
|
||||
// board specific
|
||||
#ifdef NRF52840_XXAA // All of the NRF52 targets are configured using variant.h, so this section shouldn't need to be
|
||||
// board specific
|
||||
|
||||
//
|
||||
// Standard definitions for NRF52 targets
|
||||
//
|
||||
|
||||
// Nop definition for these attributes - not used on NRF52
|
||||
#define EXT_RAM_ATTR
|
||||
#define IRAM_ATTR
|
||||
|
||||
#define NO_ESP32 // Don't use ESP32 libs (mainly bluetooth)
|
||||
|
||||
// We bind to the GPS using variant.h instead for this platform (Serial1)
|
||||
@@ -74,11 +70,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#define RTC_DATA_ATTR
|
||||
|
||||
#define LED_PIN PIN_LED1 // LED1 on nrf52840-DK
|
||||
|
||||
// If the variant filed defines as standard button
|
||||
#ifdef PIN_BUTTON1
|
||||
#define BUTTON_PIN PIN_BUTTON1
|
||||
#endif
|
||||
|
||||
// FIXME, use variant.h defs for all of this!!! (even on the ESP32 targets)
|
||||
#elif defined(CubeCell_BoardPlus)
|
||||
@@ -113,13 +105,10 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
// LoRa SPI
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
// NRF52 boards will define this in variant.h
|
||||
#ifndef RF95_SCK
|
||||
#define RF95_SCK 5
|
||||
#define RF95_MISO 19
|
||||
#define RF95_MOSI 27
|
||||
#define RF95_NSS 18
|
||||
#endif
|
||||
#define SCK_GPIO 5
|
||||
#define MISO_GPIO 19
|
||||
#define MOSI_GPIO 27
|
||||
#define NSS_GPIO 18
|
||||
|
||||
#endif
|
||||
|
||||
@@ -159,11 +148,11 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#define BUTTON_PIN_ALT 13 // Alternate GPIO for an external button if needed
|
||||
|
||||
#ifndef USE_JTAG
|
||||
#define RF95_RESET 14
|
||||
#define RESET_GPIO 14
|
||||
#endif
|
||||
#define RF95_IRQ 26
|
||||
#define RF95_DIO1 33 // Note: not really used on this board
|
||||
#define RF95_DIO2 32 // Note: not really used on this board
|
||||
#define RF95_IRQ_GPIO 26
|
||||
#define DIO1_GPIO 33 // Note: not really used on this board
|
||||
#define DIO2_GPIO 32 // Note: not really used on this board
|
||||
|
||||
// Leave undefined to disable our PMU IRQ handler
|
||||
#define PMU_IRQ 35
|
||||
@@ -182,11 +171,11 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#define BUTTON_PIN 39
|
||||
|
||||
#ifndef USE_JTAG
|
||||
#define RF95_RESET 23
|
||||
#define RESET_GPIO 23
|
||||
#endif
|
||||
#define RF95_IRQ 26
|
||||
#define RF95_DIO1 33 // Note: not really used on this board
|
||||
#define RF95_DIO2 32 // Note: not really used on this board
|
||||
#define RF95_IRQ_GPIO 26
|
||||
#define DIO1_GPIO 33 // Note: not really used on this board
|
||||
#define DIO2_GPIO 32 // Note: not really used on this board
|
||||
|
||||
// This board has different GPS pins than all other boards
|
||||
#undef GPS_RX_PIN
|
||||
@@ -217,11 +206,11 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#define BUTTON_PIN 0 // If defined, this will be used for user button presses
|
||||
|
||||
#ifndef USE_JTAG
|
||||
#define RF95_RESET 14 // If defined, this pin will be used to reset the LORA radio
|
||||
#define RESET_GPIO 14 // If defined, this pin will be used to reset the LORA radio
|
||||
#endif
|
||||
#define RF95_IRQ 26
|
||||
#define RF95_DIO1 35 // DIO1 & DIO2 are not currently used, but they must be assigned to a pin number
|
||||
#define RF95_DIO2 34 // DIO1 & DIO2 are not currently used, but they must be assigned to a pin number
|
||||
#define RF95_IRQ_GPIO 26
|
||||
#define DIO1_GPIO 35 // DIO1 & DIO2 are not currently used, but they must be assigned to a pin number
|
||||
#define DIO2_GPIO 34 // DIO1 & DIO2 are not currently used, but they must be assigned to a pin number
|
||||
#elif defined(TLORA_V1)
|
||||
// This string must exactly match the case used in release file names or the android updater won't work
|
||||
#define HW_VENDOR "tlora-v1"
|
||||
@@ -239,11 +228,10 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#define LED_PIN 2 // If defined we will blink this LED
|
||||
#define BUTTON_PIN 0 // If defined, this will be used for user button presses
|
||||
|
||||
#define RF95_RESET 14 // If defined, this pin will be used to reset the LORA radio
|
||||
#define RF95_IRQ 26 // IRQ line for the LORA radio
|
||||
#define RF95_DIO1 35 // DIO1 & DIO2 are not currently used, but they must be assigned to a pin number
|
||||
#define RF95_DIO2 34 // DIO1 & DIO2 are not currently used, but they must be assigned to a pin number
|
||||
|
||||
#define RESET_GPIO 14 // If defined, this pin will be used to reset the LORA radio
|
||||
#define RF95_IRQ_GPIO 26 // IRQ line for the LORA radio
|
||||
#define DIO1_GPIO 35 // DIO1 & DIO2 are not currently used, but they must be assigned to a pin number
|
||||
#define DIO2_GPIO 34 // DIO1 & DIO2 are not currently used, but they must be assigned to a pin number
|
||||
#elif defined(TLORA_V2)
|
||||
// This string must exactly match the case used in release file names or the android updater won't work
|
||||
#define HW_VENDOR "tlora-v2"
|
||||
@@ -260,9 +248,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#define VEXT_ENABLE 21 // active low, powers the oled display and the lora antenna boost
|
||||
#define LED_PIN 25 // If defined we will blink this LED
|
||||
#define BUTTON_PIN \
|
||||
0 // If defined, this will be used for user button presses, if your board doesn't have a physical switch, you can wire one
|
||||
// between this pin and ground
|
||||
#define BUTTON_PIN 0 // If defined, this will be used for user button presses, if your board doesn't have a physical switch, you can wire one between this pin and ground
|
||||
|
||||
#define RESET_GPIO 14 // If defined, this pin will be used to reset the LORA radio
|
||||
#define RF95_IRQ_GPIO 26 // IRQ line for the LORA radio
|
||||
@@ -276,7 +262,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#undef GPS_RX_PIN
|
||||
#undef GPS_TX_PIN
|
||||
#define GPS_RX_PIN 36
|
||||
#define GPS_TX_PIN 39
|
||||
#define GPS_TX_PIN 39
|
||||
|
||||
#define I2C_SDA 21 // I2C pins for this board
|
||||
#define I2C_SCL 22
|
||||
@@ -285,14 +271,12 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#define VEXT_ENABLE 21 // active low, powers the oled display and the lora antenna boost
|
||||
#define LED_PIN 25 // If defined we will blink this LED
|
||||
#define BUTTON_PIN \
|
||||
12 // If defined, this will be used for user button presses, if your board doesn't have a physical switch, you can wire one
|
||||
// between this pin and ground
|
||||
#define BUTTON_PIN 12 // If defined, this will be used for user button presses, if your board doesn't have a physical switch, you can wire one between this pin and ground
|
||||
|
||||
#define RF95_RESET 14 // If defined, this pin will be used to reset the LORA radio
|
||||
#define RF95_IRQ 26 // IRQ line for the LORA radio
|
||||
#define RF95_DIO1 35 // DIO1 & DIO2 are not currently used, but they must be assigned to a pin number
|
||||
#define RF95_DIO2 34 // DIO1 & DIO2 are not currently used, but they must be assigned to a pin number
|
||||
#define RESET_GPIO 23 // If defined, this pin will be used to reset the LORA radio
|
||||
#define RF95_IRQ_GPIO 26 // IRQ line for the LORA radio
|
||||
#define DIO1_GPIO 35 // DIO1 & DIO2 are not currently used, but they must be assigned to a pin number
|
||||
#define DIO2_GPIO 34 // DIO1 & DIO2 are not currently used, but they must be assigned to a pin number
|
||||
#endif
|
||||
|
||||
#ifdef ARDUINO_NRF52840_PCA10056
|
||||
@@ -304,25 +288,25 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#undef LED_INVERTED
|
||||
#define LED_INVERTED 1
|
||||
|
||||
// Uncomment to confirm if we can build the RF95 driver for NRF52
|
||||
#if 0
|
||||
#define RESET_GPIO 14 // If defined, this pin will be used to reset the LORA radio
|
||||
#define RF95_IRQ_GPIO 26 // IRQ line for the LORA radio
|
||||
#define DIO1_GPIO 35 // DIO1 & DIO2 are not currently used, but they must be assigned to a pin number
|
||||
#define DIO2_GPIO 34 // DIO1 & DIO2 are not currently used, but they must be assigned to a pin number
|
||||
#endif
|
||||
|
||||
#elif defined(ARDUINO_NRF52840_PPR)
|
||||
|
||||
#define HW_VENDOR "ppr"
|
||||
|
||||
#elif NRF52_SERIES
|
||||
|
||||
#define HW_VENDOR "nrf52unknown" // FIXME - unknown nrf52 board
|
||||
|
||||
#endif
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// DEBUG
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
#ifdef CONSOLE_MAX_BAUD
|
||||
#define SERIAL_BAUD CONSOLE_MAX_BAUD
|
||||
#else
|
||||
#define SERIAL_BAUD 921600 // Serial debug baud rate
|
||||
#endif
|
||||
|
||||
#include "SerialConsole.h"
|
||||
|
||||
@@ -330,24 +314,13 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
// What platforms should use SEGGER?
|
||||
#ifdef NRF52_SERIES
|
||||
|
||||
// Always include the SEGGER code on NRF52 - because useful for debugging
|
||||
#include "SEGGER_RTT.h"
|
||||
|
||||
// Debug printing to segger console
|
||||
#define SEGGER_MSG(...) SEGGER_RTT_printf(0, __VA_ARGS__)
|
||||
|
||||
// nrf52 gets its settings via variant files
|
||||
#ifndef PIN_SERIAL_RX
|
||||
// No serial ports on this board - ONLY use segger in memory console
|
||||
#define USE_SEGGER
|
||||
#endif
|
||||
|
||||
#else
|
||||
#define SERIAL0_RX_GPIO 3 // Always GPIO3 on ESP32
|
||||
#endif
|
||||
|
||||
#ifdef USE_SEGGER
|
||||
#include "SEGGER_RTT.h"
|
||||
#define DEBUG_MSG(...) SEGGER_RTT_printf(0, __VA_ARGS__)
|
||||
#else
|
||||
#ifdef DEBUG_PORT
|
||||
|
||||
@@ -35,5 +35,8 @@ BLECharacteristic *addBLECharacteristic(BLECharacteristic *c);
|
||||
/// Add a characteristic that we will delete when we restart
|
||||
BLEDescriptor *addBLEDescriptor(BLEDescriptor *c);
|
||||
|
||||
/// Given a level between 0-100, update the BLE attribute
|
||||
void updateBatteryLevel(uint8_t level);
|
||||
|
||||
/// Any bluetooth objects you allocate _must_ come from this pool if you want to be able to call deinitBLE()
|
||||
extern SimpleAllocator btPool;
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
#include <assert.h>
|
||||
#include <esp_gatt_defs.h>
|
||||
|
||||
#include "BluetoothCommon.h"
|
||||
#include "CallbackCharacteristic.h"
|
||||
#include "GPS.h"
|
||||
#include "MeshService.h"
|
||||
@@ -40,20 +39,26 @@ class BluetoothPhoneAPI : public PhoneAPI
|
||||
}
|
||||
};
|
||||
|
||||
static BluetoothPhoneAPI *bluetoothPhoneAPI;
|
||||
BluetoothPhoneAPI *bluetoothPhoneAPI;
|
||||
|
||||
|
||||
class ToRadioCharacteristic : public CallbackCharacteristic
|
||||
{
|
||||
public:
|
||||
ToRadioCharacteristic() : CallbackCharacteristic(TORADIO_UUID, BLECharacteristic::PROPERTY_WRITE) {}
|
||||
ToRadioCharacteristic() : CallbackCharacteristic("f75c76d2-129e-4dad-a1dd-7866124401e7", BLECharacteristic::PROPERTY_WRITE) {}
|
||||
|
||||
void onWrite(BLECharacteristic *c) { bluetoothPhoneAPI->handleToRadio(c->getData(), c->getValue().length()); }
|
||||
void onWrite(BLECharacteristic *c)
|
||||
{
|
||||
bluetoothPhoneAPI->handleToRadio(c->getData(), c->getValue().length());
|
||||
}
|
||||
};
|
||||
|
||||
class FromRadioCharacteristic : public CallbackCharacteristic
|
||||
{
|
||||
public:
|
||||
FromRadioCharacteristic() : CallbackCharacteristic(FROMRADIO_UUID, BLECharacteristic::PROPERTY_READ) {}
|
||||
FromRadioCharacteristic() : CallbackCharacteristic("8ba2bcc2-ee02-4a55-a531-c525c5e454d5", BLECharacteristic::PROPERTY_READ)
|
||||
{
|
||||
}
|
||||
|
||||
void onRead(BLECharacteristic *c)
|
||||
{
|
||||
@@ -73,8 +78,9 @@ class FromNumCharacteristic : public CallbackCharacteristic
|
||||
{
|
||||
public:
|
||||
FromNumCharacteristic()
|
||||
: CallbackCharacteristic(FROMNUM_UUID, BLECharacteristic::PROPERTY_WRITE | BLECharacteristic::PROPERTY_READ |
|
||||
BLECharacteristic::PROPERTY_NOTIFY)
|
||||
: CallbackCharacteristic("ed9da18c-a800-4f66-a670-aa7547e34453", BLECharacteristic::PROPERTY_WRITE |
|
||||
BLECharacteristic::PROPERTY_READ |
|
||||
BLECharacteristic::PROPERTY_NOTIFY)
|
||||
{
|
||||
// observe(&service.fromNumChanged);
|
||||
}
|
||||
@@ -94,7 +100,7 @@ BLEService *createMeshBluetoothService(BLEServer *server)
|
||||
}
|
||||
|
||||
// Create the BLE Service, we need more than the default of 15 handles
|
||||
BLEService *service = server->createService(BLEUUID(MESH_SERVICE_UUID), 30, 0);
|
||||
BLEService *service = server->createService(BLEUUID("6ba1b218-15a8-461f-9fa8-5dcae273eafd"), 30, 0);
|
||||
|
||||
assert(!meshFromNumCharacteristic);
|
||||
meshFromNumCharacteristic = new FromNumCharacteristic;
|
||||
|
||||
@@ -1,57 +0,0 @@
|
||||
#include "WiFiServerAPI.h"
|
||||
#include "PowerFSM.h"
|
||||
#include "configuration.h"
|
||||
#include <Arduino.h>
|
||||
|
||||
WiFiServerAPI::WiFiServerAPI(WiFiClient &_client) : StreamAPI(&client), client(_client)
|
||||
{
|
||||
DEBUG_MSG("Incoming connection from %s\n", client.remoteIP().toString().c_str());
|
||||
}
|
||||
|
||||
WiFiServerAPI::~WiFiServerAPI()
|
||||
{
|
||||
client.stop();
|
||||
|
||||
// FIXME - delete this if the client dropps the connection!
|
||||
}
|
||||
|
||||
/// Hookable to find out when connection changes
|
||||
void WiFiServerAPI::onConnectionChanged(bool connected)
|
||||
{
|
||||
// FIXME - we really should be doing global reference counting to see if anyone is currently using serial or wifi and if so,
|
||||
// block sleep
|
||||
|
||||
if (connected) { // To prevent user confusion, turn off bluetooth while using the serial port api
|
||||
powerFSM.trigger(EVENT_SERIAL_CONNECTED);
|
||||
} else {
|
||||
powerFSM.trigger(EVENT_SERIAL_DISCONNECTED);
|
||||
}
|
||||
}
|
||||
|
||||
void WiFiServerAPI::loop()
|
||||
{
|
||||
if (client.connected()) {
|
||||
StreamAPI::loop();
|
||||
} else {
|
||||
DEBUG_MSG("Client dropped connection, closing UDP server\n");
|
||||
delete this;
|
||||
}
|
||||
}
|
||||
|
||||
#define MESHTASTIC_PORTNUM 4403
|
||||
|
||||
WiFiServerPort::WiFiServerPort() : WiFiServer(MESHTASTIC_PORTNUM) {}
|
||||
|
||||
void WiFiServerPort::init()
|
||||
{
|
||||
DEBUG_MSG("Listening on TCP port %d\n", MESHTASTIC_PORTNUM);
|
||||
begin();
|
||||
}
|
||||
|
||||
void WiFiServerPort::loop()
|
||||
{
|
||||
auto client = available();
|
||||
if (client) {
|
||||
new WiFiServerAPI(client);
|
||||
}
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "StreamAPI.h"
|
||||
#include <WiFi.h>
|
||||
|
||||
/**
|
||||
* Provides both debug printing and, if the client starts sending protobufs to us, switches to send/receive protobufs
|
||||
* (and starts dropping debug printing - FIXME, eventually those prints should be encapsulated in protobufs).
|
||||
*/
|
||||
class WiFiServerAPI : public StreamAPI
|
||||
{
|
||||
private:
|
||||
WiFiClient client;
|
||||
|
||||
public:
|
||||
WiFiServerAPI(WiFiClient &_client);
|
||||
|
||||
virtual ~WiFiServerAPI();
|
||||
|
||||
virtual void loop(); // Check for dropped client connections
|
||||
|
||||
protected:
|
||||
/// Hookable to find out when connection changes
|
||||
virtual void onConnectionChanged(bool connected);
|
||||
};
|
||||
|
||||
/**
|
||||
* Listens for incoming connections and does accepts and creates instances of WiFiServerAPI as needed
|
||||
*/
|
||||
class WiFiServerPort : public WiFiServer
|
||||
{
|
||||
public:
|
||||
WiFiServerPort();
|
||||
|
||||
void init();
|
||||
|
||||
void loop();
|
||||
};
|
||||
@@ -7,6 +7,8 @@
|
||||
#include "sleep.h"
|
||||
#include "target_specific.h"
|
||||
#include "utils.h"
|
||||
#include <nvs.h>
|
||||
#include <nvs_flash.h>
|
||||
|
||||
bool bluetoothOn;
|
||||
|
||||
@@ -83,13 +85,19 @@ void esp32Setup()
|
||||
DEBUG_MSG("Total PSRAM: %d\n", ESP.getPsramSize());
|
||||
DEBUG_MSG("Free PSRAM: %d\n", ESP.getFreePsram());
|
||||
|
||||
nvs_stats_t nvs_stats;
|
||||
auto res = nvs_get_stats(NULL, &nvs_stats);
|
||||
assert(res == ESP_OK);
|
||||
DEBUG_MSG("NVS: UsedEntries %d, FreeEntries %d, AllEntries %d\n", nvs_stats.used_entries, nvs_stats.free_entries,
|
||||
nvs_stats.total_entries);
|
||||
|
||||
// enableModemSleep();
|
||||
|
||||
// Since we are turning on watchdogs rather late in the release schedule, we really don't want to catch any
|
||||
// false positives. The wait-to-sleep timeout for shutting down radios is 30 secs, so pick 45 for now.
|
||||
#define APP_WATCHDOG_SECS 45
|
||||
|
||||
auto res = esp_task_wdt_init(APP_WATCHDOG_SECS, true);
|
||||
res = esp_task_wdt_init(APP_WATCHDOG_SECS, true);
|
||||
assert(res == ESP_OK);
|
||||
|
||||
res = esp_task_wdt_add(NULL);
|
||||
|
||||
@@ -5,21 +5,12 @@
|
||||
#include <assert.h>
|
||||
#include <time.h>
|
||||
|
||||
// If we have a serial GPS port it will not be null
|
||||
#ifdef GPS_RX_PIN
|
||||
HardwareSerial _serial_gps_real(GPS_SERIAL_NUM);
|
||||
HardwareSerial *GPS::_serial_gps = &_serial_gps_real;
|
||||
#elif defined(NRF52840_XXAA)
|
||||
// Assume NRF52840
|
||||
HardwareSerial *GPS::_serial_gps = &Serial1;
|
||||
HardwareSerial &GPS::_serial_gps = _serial_gps_real;
|
||||
#else
|
||||
HardwareSerial *GPS::_serial_gps = NULL;
|
||||
#endif
|
||||
|
||||
#ifdef GPS_I2C_ADDRESS
|
||||
uint8_t GPS::i2cAddress = GPS_I2C_ADDRESS;
|
||||
#else
|
||||
uint8_t GPS::i2cAddress = 0;
|
||||
// Assume NRF52
|
||||
HardwareSerial &GPS::_serial_gps = Serial1;
|
||||
#endif
|
||||
|
||||
bool timeSetFromGPS; // We try to set our time from GPS each time we wake from sleep
|
||||
@@ -72,7 +63,7 @@ void perhapsSetRTC(struct tm &t)
|
||||
|
||||
// DEBUG_MSG("Got time from GPS month=%d, year=%d, unixtime=%ld\n", t.tm_mon, t.tm_year, tv.tv_sec);
|
||||
if (t.tm_year < 0 || t.tm_year >= 300)
|
||||
DEBUG_MSG("Ignoring invalid GPS month=%d, year=%d, unixtime=%ld\n", t.tm_mon, t.tm_year, tv.tv_sec);
|
||||
DEBUG_MSG("Ignoring invalid GPS time\n");
|
||||
else
|
||||
perhapsSetRTC(&tv);
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include "../concurrency/PeriodicTask.h"
|
||||
#include "GPSStatus.h"
|
||||
#include "Observer.h"
|
||||
#include "GPSStatus.h"
|
||||
#include "../concurrency/PeriodicTask.h"
|
||||
#include "sys/time.h"
|
||||
|
||||
/// If we haven't yet set our RTC this boot, set it from a GPS derived time
|
||||
@@ -30,17 +30,12 @@ class GPS : public Observable<void *>
|
||||
protected:
|
||||
bool hasValidLocation = false; // default to false, until we complete our first read
|
||||
|
||||
static HardwareSerial &_serial_gps;
|
||||
|
||||
public:
|
||||
/** If !NULL we will use this serial port to construct our GPS */
|
||||
static HardwareSerial *_serial_gps;
|
||||
|
||||
/** If !0 we will attempt to connect to the GPS over I2C */
|
||||
static uint8_t i2cAddress;
|
||||
|
||||
int32_t latitude = 0, longitude = 0; // as an int mult by 1e-7 to get value as double
|
||||
int32_t altitude = 0;
|
||||
uint32_t dop = 0; // Diminution of position; PDOP where possible (UBlox), HDOP otherwise (TinyGPS) in 10^2 units (needs
|
||||
// scaling before use)
|
||||
uint32_t dop = 0; // Diminution of position; PDOP where possible (UBlox), HDOP otherwise (TinyGPS) in 10^2 units (needs scaling before use)
|
||||
uint32_t heading = 0; // Heading of motion, in degrees * 10^-5
|
||||
uint32_t numSatellites = 0;
|
||||
|
||||
|
||||
@@ -13,8 +13,9 @@ static int32_t toDegInt(RawDegrees d)
|
||||
|
||||
void NEMAGPS::loop()
|
||||
{
|
||||
while (_serial_gps->available() > 0) {
|
||||
int c = _serial_gps->read();
|
||||
|
||||
while (_serial_gps.available() > 0) {
|
||||
int c = _serial_gps.read();
|
||||
// Serial.write(c);
|
||||
reader.encode(c);
|
||||
}
|
||||
|
||||
@@ -7,46 +7,23 @@ UBloxGPS::UBloxGPS() : concurrency::PeriodicTask()
|
||||
notifySleepObserver.observe(¬ifySleep);
|
||||
}
|
||||
|
||||
bool UBloxGPS::tryConnect()
|
||||
{
|
||||
isConnected = false;
|
||||
|
||||
if (_serial_gps)
|
||||
isConnected = ublox.begin(*_serial_gps);
|
||||
|
||||
if (!isConnected && i2cAddress) {
|
||||
extern bool neo6M; // Super skanky - if we are talking to the device i2c we assume it is a neo7 on a RAK815, which
|
||||
// supports the newer API
|
||||
neo6M = true;
|
||||
|
||||
isConnected = ublox.begin(Wire, i2cAddress);
|
||||
}
|
||||
|
||||
return isConnected;
|
||||
}
|
||||
|
||||
bool UBloxGPS::setup()
|
||||
{
|
||||
if (_serial_gps) {
|
||||
#ifdef GPS_RX_PIN
|
||||
_serial_gps->begin(GPS_BAUDRATE, SERIAL_8N1, GPS_RX_PIN, GPS_TX_PIN);
|
||||
_serial_gps.begin(GPS_BAUDRATE, SERIAL_8N1, GPS_RX_PIN, GPS_TX_PIN);
|
||||
#else
|
||||
_serial_gps->begin(GPS_BAUDRATE);
|
||||
_serial_gps.begin(GPS_BAUDRATE);
|
||||
#endif
|
||||
// _serial_gps.setRxBufferSize(1024); // the default is 256
|
||||
}
|
||||
|
||||
#ifdef GPS_POWER_EN
|
||||
pinMode(GPS_POWER_EN, OUTPUT);
|
||||
digitalWrite(GPS_POWER_EN, 1);
|
||||
delay(200); // Give time for the GPS to startup after we gave power
|
||||
#endif
|
||||
|
||||
// _serial_gps.setRxBufferSize(1024); // the default is 256
|
||||
// ublox.enableDebugging(Serial);
|
||||
|
||||
// note: the lib's implementation has the wrong docs for what the return val is
|
||||
// it is not a bool, it returns zero for success
|
||||
isConnected = ublox.begin(_serial_gps);
|
||||
|
||||
// try a second time, the ublox lib serial parsing is buggy?
|
||||
if (!tryConnect())
|
||||
tryConnect();
|
||||
if (!isConnected)
|
||||
isConnected = ublox.begin(_serial_gps);
|
||||
|
||||
if (isConnected) {
|
||||
DEBUG_MSG("Connected to UBLOX GPS successfully\n");
|
||||
@@ -58,21 +35,14 @@ bool UBloxGPS::setup()
|
||||
// GPS_TX connected)
|
||||
ublox.factoryReset();
|
||||
delay(3000);
|
||||
tryConnect();
|
||||
isConnected = ublox.begin(_serial_gps);
|
||||
DEBUG_MSG("Factory reset success=%d\n", isConnected);
|
||||
ok = ublox.saveConfiguration(3000);
|
||||
assert(ok);
|
||||
return false;
|
||||
} else {
|
||||
if (_serial_gps) {
|
||||
ok = ublox.setUART1Output(COM_TYPE_UBX, 500); // Use native API
|
||||
assert(ok);
|
||||
}
|
||||
if (i2cAddress) {
|
||||
ok = ublox.setI2COutput(COM_TYPE_UBX, 500);
|
||||
assert(ok);
|
||||
}
|
||||
|
||||
ok = ublox.setUART1Output(COM_TYPE_UBX, 500); // Use native API
|
||||
assert(ok);
|
||||
ok = ublox.setNavigationFrequency(1, 500); // Produce 4x/sec to keep the amount of time we stall in getPVT low
|
||||
assert(ok);
|
||||
// ok = ublox.setAutoPVT(false); // Not implemented on NEO-6M
|
||||
@@ -110,22 +80,20 @@ void UBloxGPS::doTask()
|
||||
|
||||
// Consume all characters that have arrived
|
||||
|
||||
// if using i2c or serial look too see if any chars are ready
|
||||
// getPVT automatically calls checkUblox
|
||||
ublox.checkUblox(); // See if new data is available. Process bytes as they come in.
|
||||
|
||||
// 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
|
||||
// turn off for now
|
||||
uint16_t maxWait = i2cAddress ? 300 : 0; // If using i2c we must poll with wait
|
||||
fixtype = ublox.getFixType(maxWait);
|
||||
fixtype = ublox.getFixType(0);
|
||||
DEBUG_MSG("GPS fix type %d\n", fixtype);
|
||||
|
||||
// DEBUG_MSG("sec %d\n", ublox.getSecond());
|
||||
// DEBUG_MSG("lat %d\n", ublox.getLatitude());
|
||||
|
||||
// any fix that has time
|
||||
|
||||
if (ublox.getT(maxWait)) {
|
||||
if (ublox.getT(0)) {
|
||||
/* Convert to unix time
|
||||
The Unix epoch (or Unix time or POSIX time or Unix timestamp) is the number of seconds that have elapsed since January 1, 1970
|
||||
(midnight UTC/GMT), not counting leap seconds (in ISO 8601: 1970-01-01T00:00:00Z).
|
||||
@@ -141,20 +109,19 @@ The Unix epoch (or Unix time or POSIX time or Unix timestamp) is the number of s
|
||||
perhapsSetRTC(t);
|
||||
}
|
||||
|
||||
latitude = ublox.getLatitude(0);
|
||||
longitude = ublox.getLongitude(0);
|
||||
altitude = ublox.getAltitude(0) / 1000; // in mm convert to meters
|
||||
dop = ublox.getPDOP(0); // PDOP (an accuracy metric) is reported in 10^2 units so we have to scale down when we use it
|
||||
heading = ublox.getHeading(0);
|
||||
numSatellites = ublox.getSIV(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) && (numSatellites > 0);
|
||||
|
||||
// we only notify if position has changed due to a new fix
|
||||
if ((fixtype >= 3 && fixtype <= 4) && ublox.getP(maxWait)) // rd fixes only
|
||||
if ((fixtype >= 3 && fixtype <= 4) && ublox.getP(0)) // rd fixes only
|
||||
{
|
||||
// we only notify if position has changed
|
||||
latitude = ublox.getLatitude(0);
|
||||
longitude = ublox.getLongitude(0);
|
||||
altitude = ublox.getAltitude(0) / 1000; // in mm convert to meters
|
||||
dop = ublox.getPDOP(0); // PDOP (an accuracy metric) is reported in 10^2 units so we have to scale down when we use it
|
||||
heading = ublox.getHeading(0);
|
||||
numSatellites = ublox.getSIV(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) {
|
||||
wantNewLocation = false;
|
||||
notifyObservers(NULL);
|
||||
@@ -164,8 +131,7 @@ The Unix epoch (or Unix time or POSIX time or Unix timestamp) is the number of s
|
||||
wantNewLocation = true;
|
||||
|
||||
// Notify any status instances that are observing us
|
||||
const meshtastic::GPSStatus status =
|
||||
meshtastic::GPSStatus(hasLock(), isConnected, latitude, longitude, altitude, dop, heading, numSatellites);
|
||||
const meshtastic::GPSStatus status = meshtastic::GPSStatus(hasLock(), isConnected, latitude, longitude, altitude, dop, heading, numSatellites);
|
||||
newStatus.notifyObservers(&status);
|
||||
|
||||
// Once we have sent a location once we only poll the GPS rarely, otherwise check back every 1s until we have something over
|
||||
|
||||
@@ -38,7 +38,4 @@ class UBloxGPS : public GPS, public concurrency::PeriodicTask
|
||||
/// Prepare the GPS for the cpu entering deep or light sleep, expect to be gone for at least 100s of msecs
|
||||
/// always returns 0 to indicate okay to sleep
|
||||
int prepareSleep(void *unused);
|
||||
|
||||
/// Attempt to connect to our GPS, returns false if no gps is present
|
||||
bool tryConnect();
|
||||
};
|
||||
|
||||
48
src/main.cpp
48
src/main.cpp
@@ -25,17 +25,17 @@
|
||||
#include "MeshService.h"
|
||||
#include "NEMAGPS.h"
|
||||
#include "NodeDB.h"
|
||||
#include "concurrency/Periodic.h"
|
||||
#include "PowerFSM.h"
|
||||
#include "UBloxGPS.h"
|
||||
#include "concurrency/Periodic.h"
|
||||
#include "configuration.h"
|
||||
#include "error.h"
|
||||
#include "power.h"
|
||||
// #include "rom/rtc.h"
|
||||
#include "DSRRouter.h"
|
||||
// #include "debug.h"
|
||||
#include "graphics/Screen.h"
|
||||
#include "debug.h"
|
||||
#include "main.h"
|
||||
#include "graphics/Screen.h"
|
||||
#include "sleep.h"
|
||||
#include "timing.h"
|
||||
#include <OneButton.h>
|
||||
@@ -152,29 +152,23 @@ void userButtonPressedLong()
|
||||
#ifndef NO_ESP32
|
||||
void initWifi()
|
||||
{
|
||||
#if 0
|
||||
// strcpy(radioConfig.preferences.wifi_ssid, "xxx");
|
||||
// strcpy(radioConfig.preferences.wifi_password, "xxx");
|
||||
strcpy(radioConfig.preferences.wifi_ssid, "geeksville");
|
||||
strcpy(radioConfig.preferences.wifi_password, "xxx");
|
||||
if (radioConfig.has_preferences) {
|
||||
const char *wifiName = radioConfig.preferences.wifi_ssid;
|
||||
|
||||
if (*wifiName) {
|
||||
const char *wifiPsw = radioConfig.preferences.wifi_password;
|
||||
if (radioConfig.preferences.wifi_ap_mode) {
|
||||
DEBUG_MSG("STARTING WIFI AP: ssid=%s, ok=%d\n", wifiName, WiFi.softAP(wifiName, wifiPsw));
|
||||
// DEBUG_MSG("STARTING WIFI AP: ssid=%s, ok=%d\n", wifiName, WiFi.softAP(wifiName, wifiPsw));
|
||||
} else {
|
||||
WiFi.mode(WIFI_MODE_STA);
|
||||
// WiFi.mode(WIFI_MODE_STA);
|
||||
DEBUG_MSG("JOINING WIFI: ssid=%s\n", wifiName);
|
||||
if (WiFi.begin(wifiName, wifiPsw) == WL_CONNECTED) {
|
||||
DEBUG_MSG("MY IP ADDRESS: %s\n", WiFi.localIP().toString().c_str());
|
||||
} else {
|
||||
DEBUG_MSG("FAILED JOINING WIFI\n");
|
||||
}
|
||||
// WiFi.begin(wifiName, wifiPsw);
|
||||
}
|
||||
}
|
||||
} else
|
||||
} else
|
||||
DEBUG_MSG("Not using WIFI\n");
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -265,18 +259,12 @@ void setup()
|
||||
// Init GPS - first try ublox
|
||||
gps = new UBloxGPS();
|
||||
if (!gps->setup()) {
|
||||
DEBUG_MSG("ERROR: No UBLOX GPS found\n");
|
||||
|
||||
if (GPS::_serial_gps) {
|
||||
// Some boards might have only the TX line from the GPS connected, in that case, we can't configure it at all. Just
|
||||
// assume NEMA at 9600 baud.
|
||||
DEBUG_MSG("Hoping that NEMA might work\n");
|
||||
delete gps;
|
||||
|
||||
// dumb NEMA access only work for serial GPSes)
|
||||
gps = new NEMAGPS();
|
||||
gps->setup();
|
||||
}
|
||||
// Some boards might have only the TX line from the GPS connected, in that case, we can't configure it at all. Just
|
||||
// assume NEMA at 9600 baud.
|
||||
DEBUG_MSG("ERROR: No UBLOX GPS found, hoping that NEMA might work\n");
|
||||
delete gps;
|
||||
gps = new NEMAGPS();
|
||||
gps->setup();
|
||||
}
|
||||
#else
|
||||
gps = new NEMAGPS();
|
||||
@@ -302,15 +290,15 @@ void setup()
|
||||
SPI.begin();
|
||||
#else
|
||||
// ESP32
|
||||
SPI.begin(RF95_SCK, RF95_MISO, RF95_MOSI, RF95_NSS);
|
||||
SPI.begin(SCK_GPIO, MISO_GPIO, MOSI_GPIO, NSS_GPIO);
|
||||
SPI.setFrequency(4000000);
|
||||
#endif
|
||||
|
||||
// MUST BE AFTER service.init, so we have our radio config settings (from nodedb init)
|
||||
RadioInterface *rIf =
|
||||
#if defined(RF95_IRQ)
|
||||
#if defined(RF95_IRQ_GPIO)
|
||||
// new CustomRF95(); old Radiohead based driver
|
||||
new RF95Interface(RF95_NSS, RF95_IRQ, RF95_RESET, SPI);
|
||||
new RF95Interface(NSS_GPIO, RF95_IRQ_GPIO, RESET_GPIO, SPI);
|
||||
#elif defined(SX1262_CS)
|
||||
new SX1262Interface(SX1262_CS, SX1262_DIO1, SX1262_RESET, SX1262_BUSY, SPI);
|
||||
#else
|
||||
|
||||
@@ -5,14 +5,14 @@
|
||||
|
||||
#include "GPS.h"
|
||||
//#include "MeshBluetoothService.h"
|
||||
#include "../concurrency/Periodic.h"
|
||||
#include "BluetoothCommon.h" // needed for updateBatteryLevel, FIXME, eventually when we pull mesh out into a lib we shouldn't be whacking bluetooth from here
|
||||
#include "MeshService.h"
|
||||
#include "NodeDB.h"
|
||||
#include "../concurrency/Periodic.h"
|
||||
#include "PowerFSM.h"
|
||||
#include "main.h"
|
||||
#include "mesh-pb-constants.h"
|
||||
#include "power.h"
|
||||
#include "BluetoothUtil.h" // needed for updateBatteryLevel, FIXME, eventually when we pull mesh out into a lib we shouldn't be whacking bluetooth from here
|
||||
#include "timing.h"
|
||||
|
||||
/*
|
||||
@@ -283,6 +283,8 @@ void MeshService::sendOurPosition(NodeNum dest, bool wantReplies)
|
||||
sendToMesh(p);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int MeshService::onGPSChanged(void *unused)
|
||||
{
|
||||
// DEBUG_MSG("got gps notify\n");
|
||||
|
||||
@@ -12,18 +12,6 @@ RF95Interface::RF95Interface(RADIOLIB_PIN_TYPE cs, RADIOLIB_PIN_TYPE irq, RADIOL
|
||||
// FIXME - we assume devices never get destroyed
|
||||
}
|
||||
|
||||
/** Some boards require GPIO control of tx vs rx paths */
|
||||
void RF95Interface::setTransmitEnable(bool txon)
|
||||
{
|
||||
#ifdef RF95_TXEN
|
||||
digitalWrite(RF95_TXEN, txon ? 1 : 0);
|
||||
#endif
|
||||
|
||||
#ifdef RF95_RXEN
|
||||
digitalWrite(RF95_RXEN, txon ? 0 : 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
/// Initialise the Driver transport hardware and software.
|
||||
/// Make sure the Driver is properly configured before calling init().
|
||||
/// \return true if initialisation succeeded.
|
||||
@@ -36,30 +24,8 @@ bool RF95Interface::init()
|
||||
power = MAX_POWER;
|
||||
|
||||
iface = lora = new RadioLibRF95(&module);
|
||||
|
||||
#ifdef RF95_TCXO
|
||||
pinMode(RF95_TCXO, OUTPUT);
|
||||
digitalWrite(RF95_TCXO, 1);
|
||||
#endif
|
||||
|
||||
/*
|
||||
#define RF95_TXEN (22) // If defined, this pin should be set high prior to transmit (controls an external analog switch)
|
||||
#define RF95_RXEN (23) // If defined, this pin should be set high prior to receive (controls an external analog switch)
|
||||
*/
|
||||
|
||||
#ifdef RF95_TXEN
|
||||
pinMode(RF95_TXEN, OUTPUT);
|
||||
digitalWrite(RF95_TXEN, 0);
|
||||
#endif
|
||||
|
||||
#ifdef RF95_RXEN
|
||||
pinMode(RF95_RXEN, OUTPUT);
|
||||
digitalWrite(RF95_RXEN, 1);
|
||||
#endif
|
||||
setTransmitEnable(false);
|
||||
|
||||
int res = lora->begin(freq, bw, sf, cr, syncWord, power, currentLimit, preambleLength);
|
||||
DEBUG_MSG("RF95 init result %d\n", res);
|
||||
DEBUG_MSG("LORA init result %d\n", res);
|
||||
|
||||
if (res == ERR_NONE)
|
||||
res = lora->setCRC(SX126X_LORA_CRC_ON);
|
||||
@@ -132,18 +98,8 @@ void RF95Interface::setStandby()
|
||||
completeSending(); // If we were sending, not anymore
|
||||
}
|
||||
|
||||
/** We override to turn on transmitter power as needed.
|
||||
*/
|
||||
void RF95Interface::configHardwareForSend()
|
||||
{
|
||||
setTransmitEnable(true);
|
||||
|
||||
RadioLibInterface::configHardwareForSend();
|
||||
}
|
||||
|
||||
void RF95Interface::startReceive()
|
||||
{
|
||||
setTransmitEnable(false);
|
||||
setStandby();
|
||||
int err = lora->startReceive();
|
||||
assert(err == ERR_NONE);
|
||||
|
||||
@@ -52,13 +52,4 @@ class RF95Interface : public RadioLibInterface
|
||||
virtual void addReceiveMetadata(MeshPacket *mp);
|
||||
|
||||
virtual void setStandby();
|
||||
|
||||
/**
|
||||
* We override to turn on transmitter power as needed.
|
||||
*/
|
||||
virtual void configHardwareForSend();
|
||||
|
||||
private:
|
||||
/** Some boards require GPIO control of tx vs rx paths */
|
||||
void setTransmitEnable(bool txon);
|
||||
};
|
||||
@@ -161,11 +161,6 @@ class SimRadio : public RadioInterface
|
||||
/// Make sure the Driver is properly configured before calling init().
|
||||
/// \return true if initialisation succeeded.
|
||||
virtual bool init() { return true; }
|
||||
|
||||
/// Apply any radio provisioning changes
|
||||
/// Make sure the Driver is properly configured before calling init().
|
||||
/// \return true if initialisation succeeded.
|
||||
virtual bool reconfigure() { return true; }
|
||||
};
|
||||
|
||||
/// Debug printing for packets
|
||||
|
||||
@@ -3,10 +3,6 @@
|
||||
#define RF95_CHIP_VERSION 0x12
|
||||
#define RF95_ALT_VERSION 0x11 // Supposedly some versions of the chip have id 0x11
|
||||
|
||||
// From datasheet but radiolib doesn't know anything about this
|
||||
#define SX127X_REG_TCXO 0x4B
|
||||
|
||||
|
||||
RadioLibRF95::RadioLibRF95(Module *mod) : SX1278(mod) {}
|
||||
|
||||
int16_t RadioLibRF95::begin(float freq, float bw, uint8_t sf, uint8_t cr, uint8_t syncWord, int8_t power, uint8_t currentLimit,
|
||||
@@ -22,11 +18,6 @@ int16_t RadioLibRF95::begin(float freq, float bw, uint8_t sf, uint8_t cr, uint8_
|
||||
state = config();
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
#ifdef RF95_TCXO
|
||||
state = _mod->SPIsetRegValue(SX127X_REG_TCXO, 0x10 | _mod->SPIgetRegValue(SX127X_REG_TCXO));
|
||||
RADIOLIB_ASSERT(state);
|
||||
#endif
|
||||
|
||||
// configure publicly accessible settings
|
||||
state = setFrequency(freq);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
@@ -24,8 +24,8 @@
|
||||
(MAX_RX_TOPHONE + MAX_RX_FROMRADIO + 2 * MAX_TX_QUEUE + \
|
||||
2) // max number of packets which can be in flight (either queued from reception or queued for sending)
|
||||
|
||||
// static MemoryPool<MeshPacket> staticPool(MAX_PACKETS);
|
||||
static MemoryDynamic<MeshPacket> staticPool;
|
||||
static MemoryPool<MeshPacket> staticPool(MAX_PACKETS);
|
||||
// static MemoryDynamic<MeshPacket> staticPool;
|
||||
|
||||
Allocator<MeshPacket> &packetPool = staticPool;
|
||||
|
||||
@@ -36,7 +36,7 @@ Allocator<MeshPacket> &packetPool = staticPool;
|
||||
*/
|
||||
Router::Router() : fromRadioQueue(MAX_RX_FROMRADIO)
|
||||
{
|
||||
// This is called pre main(), don't touch anything here, the following code is not safe
|
||||
// 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));
|
||||
|
||||
@@ -33,7 +33,7 @@ bool SX1262Interface::init()
|
||||
if (power > 22) // This chip has lower power limits than some
|
||||
power = 22;
|
||||
int res = lora.begin(freq, bw, sf, cr, syncWord, power, currentLimit, preambleLength, tcxoVoltage, useRegulatorLDO);
|
||||
DEBUG_MSG("SX1262 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
|
||||
@@ -119,7 +119,8 @@ void SX1262Interface::addReceiveMetadata(MeshPacket *mp)
|
||||
mp->rx_snr = lora.getSNR();
|
||||
}
|
||||
|
||||
/** We override to turn on transmitter power as needed.
|
||||
/** start an immediate transmit
|
||||
* We override to turn on transmitter power as needed.
|
||||
*/
|
||||
void SX1262Interface::configHardwareForSend()
|
||||
{
|
||||
|
||||
@@ -45,6 +45,10 @@ typedef struct _ChannelSettings {
|
||||
ChannelSettings_ModemConfig modem_config;
|
||||
ChannelSettings_psk_t psk;
|
||||
char name[12];
|
||||
uint32_t bandwidth;
|
||||
uint32_t spread_factor;
|
||||
uint32_t coding_rate;
|
||||
uint32_t channel_num;
|
||||
} ChannelSettings;
|
||||
|
||||
typedef PB_BYTES_ARRAY_T(240) Data_payload_t;
|
||||
@@ -241,7 +245,7 @@ typedef struct _ToRadio {
|
||||
#define RouteDiscovery_init_default {0, {0, 0, 0, 0, 0, 0, 0, 0}}
|
||||
#define SubPacket_init_default {0, {Position_init_default}, 0, 0, 0, 0, {0}, 0}
|
||||
#define MeshPacket_init_default {0, 0, 0, {SubPacket_init_default}, 0, 0, 0, 0, 0}
|
||||
#define ChannelSettings_init_default {0, _ChannelSettings_ModemConfig_MIN, {0, {0}}, ""}
|
||||
#define ChannelSettings_init_default {0, _ChannelSettings_ModemConfig_MIN, {0, {0}}, "", 0, 0, 0, 0}
|
||||
#define RadioConfig_init_default {false, RadioConfig_UserPreferences_init_default, false, ChannelSettings_init_default}
|
||||
#define RadioConfig_UserPreferences_init_default {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}
|
||||
@@ -257,7 +261,7 @@ typedef struct _ToRadio {
|
||||
#define RouteDiscovery_init_zero {0, {0, 0, 0, 0, 0, 0, 0, 0}}
|
||||
#define SubPacket_init_zero {0, {Position_init_zero}, 0, 0, 0, 0, {0}, 0}
|
||||
#define MeshPacket_init_zero {0, 0, 0, {SubPacket_init_zero}, 0, 0, 0, 0, 0}
|
||||
#define ChannelSettings_init_zero {0, _ChannelSettings_ModemConfig_MIN, {0, {0}}, ""}
|
||||
#define ChannelSettings_init_zero {0, _ChannelSettings_ModemConfig_MIN, {0, {0}}, "", 0, 0, 0, 0}
|
||||
#define RadioConfig_init_zero {false, RadioConfig_UserPreferences_init_zero, false, ChannelSettings_init_zero}
|
||||
#define RadioConfig_UserPreferences_init_zero {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}
|
||||
@@ -271,6 +275,10 @@ typedef struct _ToRadio {
|
||||
/* Field tags (for use in manual encoding/decoding) */
|
||||
#define ChannelSettings_tx_power_tag 1
|
||||
#define ChannelSettings_modem_config_tag 3
|
||||
#define ChannelSettings_bandwidth_tag 6
|
||||
#define ChannelSettings_spread_factor_tag 7
|
||||
#define ChannelSettings_coding_rate_tag 8
|
||||
#define ChannelSettings_channel_num_tag 9
|
||||
#define ChannelSettings_psk_tag 4
|
||||
#define ChannelSettings_name_tag 5
|
||||
#define Data_typ_tag 1
|
||||
@@ -436,7 +444,11 @@ X(a, STATIC, SINGULAR, BOOL, want_ack, 11)
|
||||
X(a, STATIC, SINGULAR, INT32, tx_power, 1) \
|
||||
X(a, STATIC, SINGULAR, UENUM, modem_config, 3) \
|
||||
X(a, STATIC, SINGULAR, BYTES, psk, 4) \
|
||||
X(a, STATIC, SINGULAR, STRING, name, 5)
|
||||
X(a, STATIC, SINGULAR, STRING, name, 5) \
|
||||
X(a, STATIC, SINGULAR, UINT32, bandwidth, 6) \
|
||||
X(a, STATIC, SINGULAR, UINT32, spread_factor, 7) \
|
||||
X(a, STATIC, SINGULAR, UINT32, coding_rate, 8) \
|
||||
X(a, STATIC, SINGULAR, UINT32, channel_num, 9)
|
||||
#define ChannelSettings_CALLBACK NULL
|
||||
#define ChannelSettings_DEFAULT NULL
|
||||
|
||||
@@ -597,12 +609,12 @@ extern const pb_msgdesc_t ManufacturingData_msg;
|
||||
#define RouteDiscovery_size 88
|
||||
#define SubPacket_size 274
|
||||
#define MeshPacket_size 313
|
||||
#define ChannelSettings_size 60
|
||||
#define RadioConfig_size 253
|
||||
#define ChannelSettings_size 84
|
||||
#define RadioConfig_size 277
|
||||
#define RadioConfig_UserPreferences_size 188
|
||||
#define NodeInfo_size 132
|
||||
#define MyNodeInfo_size 110
|
||||
#define DeviceState_size 5403
|
||||
#define DeviceState_size 5427
|
||||
#define DebugString_size 258
|
||||
#define FromRadio_size 322
|
||||
#define ToRadio_size 316
|
||||
|
||||
@@ -1,50 +1,22 @@
|
||||
#include "NRF52Bluetooth.h"
|
||||
#include "BluetoothCommon.h"
|
||||
#include "configuration.h"
|
||||
#include "main.h"
|
||||
#include <bluefruit.h>
|
||||
|
||||
// NRF52 wants these constants as byte arrays
|
||||
// Generated here https://yupana-engineering.com/online-uuid-to-c-array-converter - but in REVERSE BYTE ORDER
|
||||
const uint8_t MESH_SERVICE_UUID_16[16u] = {0xfd, 0xea, 0x73, 0xe2, 0xca, 0x5d, 0xa8, 0x9f,
|
||||
0x1f, 0x46, 0xa8, 0x15, 0x18, 0xb2, 0xa1, 0x6b};
|
||||
const uint8_t TORADIO_UUID_16[16u] = {0xe7, 0x01, 0x44, 0x12, 0x66, 0x78, 0xdd, 0xa1,
|
||||
0xad, 0x4d, 0x9e, 0x12, 0xd2, 0x76, 0x5c, 0xf7};
|
||||
const uint8_t FROMRADIO_UUID_16[16u] = {0xd5, 0x54, 0xe4, 0xc5, 0x25, 0xc5, 0x31, 0xa5,
|
||||
0x55, 0x4a, 0x02, 0xee, 0xc2, 0xbc, 0xa2, 0x8b};
|
||||
const uint8_t FROMNUM_UUID_16[16u] = {0x53, 0x44, 0xe3, 0x47, 0x75, 0xaa, 0x70, 0xa6,
|
||||
0x66, 0x4f, 0x00, 0xa8, 0x8c, 0xa1, 0x9d, 0xed};
|
||||
/* HRM Service Definitions
|
||||
* Heart Rate Monitor Service: 0x180D
|
||||
* Heart Rate Measurement Char: 0x2A37
|
||||
* Body Sensor Location Char: 0x2A38
|
||||
*/
|
||||
BLEService hrms = BLEService(UUID16_SVC_HEART_RATE);
|
||||
BLECharacteristic hrmc = BLECharacteristic(UUID16_CHR_HEART_RATE_MEASUREMENT);
|
||||
BLECharacteristic bslc = BLECharacteristic(UUID16_CHR_BODY_SENSOR_LOCATION);
|
||||
|
||||
static BLEService meshBleService = BLEService(BLEUuid(MESH_SERVICE_UUID_16));
|
||||
static BLECharacteristic fromNum = BLECharacteristic(BLEUuid(FROMNUM_UUID_16));
|
||||
static BLECharacteristic fromRadio = BLECharacteristic(BLEUuid(FROMRADIO_UUID_16));
|
||||
static BLECharacteristic toRadio = BLECharacteristic(BLEUuid(TORADIO_UUID_16));
|
||||
BLEDis bledis; // DIS (Device Information Service) helper class instance
|
||||
BLEBas blebas; // BAS (Battery Service) helper class instance
|
||||
BLEDfu bledfu; // DFU software update helper service
|
||||
|
||||
static BLEDis bledis; // DIS (Device Information Service) helper class instance
|
||||
static BLEBas blebas; // BAS (Battery Service) helper class instance
|
||||
static BLEDfu bledfu; // DFU software update helper service
|
||||
|
||||
// This scratch buffer is used for various bluetooth reads/writes - but it is safe because only one bt operation can be in
|
||||
// proccess at once
|
||||
// static uint8_t trBytes[_max(_max(_max(_max(ToRadio_size, RadioConfig_size), User_size), MyNodeInfo_size), FromRadio_size)];
|
||||
static uint8_t fromRadioBytes[FromRadio_size];
|
||||
static uint8_t toRadioBytes[ToRadio_size];
|
||||
|
||||
class BluetoothPhoneAPI : public PhoneAPI
|
||||
{
|
||||
/**
|
||||
* Subclasses can use this as a hook to provide custom notifications for their transport (i.e. bluetooth notifies)
|
||||
*/
|
||||
virtual void onNowHasData(uint32_t fromRadioNum)
|
||||
{
|
||||
PhoneAPI::onNowHasData(fromRadioNum);
|
||||
|
||||
DEBUG_MSG("BLE notify fromNum\n");
|
||||
fromNum.notify32(fromRadioNum);
|
||||
}
|
||||
};
|
||||
|
||||
static BluetoothPhoneAPI *bluetoothPhoneAPI;
|
||||
uint8_t bps = 0;
|
||||
|
||||
void connect_callback(uint16_t conn_handle)
|
||||
{
|
||||
@@ -54,7 +26,7 @@ void connect_callback(uint16_t conn_handle)
|
||||
char central_name[32] = {0};
|
||||
connection->getPeerName(central_name, sizeof(central_name));
|
||||
|
||||
DEBUG_MSG("BLE Connected to %s\n", central_name);
|
||||
DEBUG_MSG("Connected to %s\n", central_name);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -65,8 +37,9 @@ void connect_callback(uint16_t conn_handle)
|
||||
void disconnect_callback(uint16_t conn_handle, uint8_t reason)
|
||||
{
|
||||
(void)conn_handle;
|
||||
(void)reason;
|
||||
|
||||
DEBUG_MSG("BLE Disconnected, reason = 0x%x\n", reason);
|
||||
DEBUG_MSG("Disconnected, reason = 0x%x\n", reason);
|
||||
}
|
||||
|
||||
void cccd_callback(uint16_t conn_hdl, BLECharacteristic *chr, uint16_t cccd_value)
|
||||
@@ -76,11 +49,11 @@ void cccd_callback(uint16_t conn_hdl, BLECharacteristic *chr, uint16_t cccd_valu
|
||||
|
||||
// Check the characteristic this CCCD update is associated with in case
|
||||
// this handler is used for multiple CCCD records.
|
||||
if (chr->uuid == fromNum.uuid) {
|
||||
if (chr->uuid == hrmc.uuid) {
|
||||
if (chr->notifyEnabled(conn_hdl)) {
|
||||
DEBUG_MSG("fromNum 'Notify' enabled\n");
|
||||
DEBUG_MSG("Heart Rate Measurement 'Notify' enabled\n");
|
||||
} else {
|
||||
DEBUG_MSG("fromNum 'Notify' disabled\n");
|
||||
DEBUG_MSG("Heart Rate Measurement 'Notify' disabled\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -89,15 +62,13 @@ void startAdv(void)
|
||||
{
|
||||
// Advertising packet
|
||||
Bluefruit.Advertising.addFlags(BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE);
|
||||
Bluefruit.Advertising.addTxPower();
|
||||
|
||||
// IncludeService UUID
|
||||
// Bluefruit.ScanResponse.addService(meshBleService);
|
||||
Bluefruit.ScanResponse.addTxPower();
|
||||
Bluefruit.ScanResponse.addName();
|
||||
// Include HRM Service UUID
|
||||
Bluefruit.Advertising.addService(hrms);
|
||||
|
||||
// Include Name
|
||||
// Bluefruit.Advertising.addName();
|
||||
Bluefruit.Advertising.addService(meshBleService);
|
||||
Bluefruit.Advertising.addName();
|
||||
|
||||
/* Start Advertising
|
||||
* - Enable auto advertising if disconnected
|
||||
@@ -111,105 +82,74 @@ void startAdv(void)
|
||||
Bluefruit.Advertising.restartOnDisconnect(true);
|
||||
Bluefruit.Advertising.setInterval(32, 244); // in unit of 0.625 ms
|
||||
Bluefruit.Advertising.setFastTimeout(30); // number of seconds in fast mode
|
||||
Bluefruit.Advertising.start(0); // 0 = Don't stop advertising after n seconds. FIXME, we should stop advertising after X
|
||||
Bluefruit.Advertising.start(0); // 0 = Don't stop advertising after n seconds
|
||||
}
|
||||
|
||||
// Just ack that the caller is allowed to read
|
||||
static void authorizeRead(uint16_t conn_hdl)
|
||||
void setupHRM(void)
|
||||
{
|
||||
ble_gatts_rw_authorize_reply_params_t reply = {.type = BLE_GATTS_AUTHORIZE_TYPE_READ};
|
||||
reply.params.write.gatt_status = BLE_GATT_STATUS_SUCCESS;
|
||||
sd_ble_gatts_rw_authorize_reply(conn_hdl, &reply);
|
||||
}
|
||||
|
||||
/**
|
||||
* client is starting read, pull the bytes from our API class
|
||||
*/
|
||||
void fromRadioAuthorizeCb(uint16_t conn_hdl, BLECharacteristic *chr, ble_gatts_evt_read_t *request)
|
||||
{
|
||||
if (request->offset == 0) {
|
||||
// If the read is long, we will get multiple authorize invocations - we only populate data on the first
|
||||
|
||||
size_t numBytes = bluetoothPhoneAPI->getFromRadio(fromRadioBytes);
|
||||
|
||||
// DEBUG_MSG("fromRadioAuthorizeCb numBytes=%u\n", numBytes);
|
||||
// if (numBytes >= 2) DEBUG_MSG("fromRadio bytes %x %x\n", fromRadioBytes[0], fromRadioBytes[1]);
|
||||
|
||||
// Someone is going to read our value as soon as this callback returns. So fill it with the next message in the queue
|
||||
// or make empty if the queue is empty
|
||||
fromRadio.write(fromRadioBytes, numBytes);
|
||||
} else {
|
||||
// DEBUG_MSG("Ignoring successor read\n");
|
||||
}
|
||||
authorizeRead(conn_hdl);
|
||||
}
|
||||
|
||||
void toRadioWriteCb(uint16_t conn_hdl, BLECharacteristic *chr, uint8_t *data, uint16_t len)
|
||||
{
|
||||
DEBUG_MSG("toRadioWriteCb data %p, len %u\n", data, len);
|
||||
|
||||
bluetoothPhoneAPI->handleToRadio(data, len);
|
||||
}
|
||||
|
||||
/**
|
||||
* client is starting read, pull the bytes from our API class
|
||||
*/
|
||||
void fromNumAuthorizeCb(uint16_t conn_hdl, BLECharacteristic *chr, ble_gatts_evt_read_t *request)
|
||||
{
|
||||
DEBUG_MSG("fromNumAuthorizeCb\n");
|
||||
|
||||
authorizeRead(conn_hdl);
|
||||
}
|
||||
|
||||
void setupMeshService(void)
|
||||
{
|
||||
bluetoothPhoneAPI = new BluetoothPhoneAPI();
|
||||
bluetoothPhoneAPI->init();
|
||||
|
||||
meshBleService.begin();
|
||||
// Configure the Heart Rate Monitor service
|
||||
// See: https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.service.heart_rate.xml
|
||||
// Supported Characteristics:
|
||||
// Name UUID Requirement Properties
|
||||
// ---------------------------- ------ ----------- ----------
|
||||
// Heart Rate Measurement 0x2A37 Mandatory Notify
|
||||
// Body Sensor Location 0x2A38 Optional Read
|
||||
// Heart Rate Control Point 0x2A39 Conditional Write <-- Not used here
|
||||
hrms.begin();
|
||||
|
||||
// Note: You must call .begin() on the BLEService before calling .begin() on
|
||||
// any characteristic(s) within that service definition.. Calling .begin() on
|
||||
// a BLECharacteristic will cause it to be added to the last BLEService that
|
||||
// was 'begin()'ed!
|
||||
|
||||
fromNum.setProperties(CHR_PROPS_NOTIFY | CHR_PROPS_READ);
|
||||
fromNum.setPermission(SECMODE_OPEN, SECMODE_NO_ACCESS); // FIXME, secure this!!!
|
||||
fromNum.setFixedLen(
|
||||
0); // Variable len (either 0 or 4) FIXME consider changing protocol so it is fixed 4 byte len, where 0 means empty
|
||||
fromNum.setMaxLen(4);
|
||||
fromNum.setCccdWriteCallback(cccd_callback); // Optionally capture CCCD updates
|
||||
// We don't yet need to hook the fromNum auth callback
|
||||
// fromNum.setReadAuthorizeCallback(fromNumAuthorizeCb);
|
||||
fromNum.write32(0); // Provide default fromNum of 0
|
||||
fromNum.begin();
|
||||
// uint8_t hrmdata[2] = {0b00000110, 0x40}; // Set the characteristic to use 8-bit values, with the sensor connected and
|
||||
// detected
|
||||
// hrmc.write(hrmdata, 2);
|
||||
// Configure the Heart Rate Measurement characteristic
|
||||
// See:
|
||||
// https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.characteristic.heart_rate_measurement.xml
|
||||
// Properties = Notify
|
||||
// Min Len = 1
|
||||
// Max Len = 8
|
||||
// B0 = UINT8 - Flag (MANDATORY)
|
||||
// b5:7 = Reserved
|
||||
// b4 = RR-Internal (0 = Not present, 1 = Present)
|
||||
// b3 = Energy expended status (0 = Not present, 1 = Present)
|
||||
// b1:2 = Sensor contact status (0+1 = Not supported, 2 = Supported but contact not detected, 3 = Supported and
|
||||
// detected) b0 = Value format (0 = UINT8, 1 = UINT16)
|
||||
// B1 = UINT8 - 8-bit heart rate measurement value in BPM
|
||||
// B2:3 = UINT16 - 16-bit heart rate measurement value in BPM
|
||||
// B4:5 = UINT16 - Energy expended in joules
|
||||
// B6:7 = UINT16 - RR Internal (1/1024 second resolution)
|
||||
hrmc.setProperties(CHR_PROPS_NOTIFY);
|
||||
hrmc.setPermission(SECMODE_OPEN, SECMODE_NO_ACCESS);
|
||||
hrmc.setFixedLen(2);
|
||||
hrmc.setCccdWriteCallback(cccd_callback); // Optionally capture CCCD updates
|
||||
hrmc.begin();
|
||||
uint8_t hrmdata[2] = {0b00000110, 0x40}; // Set the characteristic to use 8-bit values, with the sensor connected and detected
|
||||
hrmc.write(hrmdata, 2);
|
||||
|
||||
fromRadio.setProperties(CHR_PROPS_READ);
|
||||
fromRadio.setPermission(SECMODE_OPEN, SECMODE_NO_ACCESS); // FIXME secure this!
|
||||
fromRadio.setMaxLen(sizeof(fromRadioBytes));
|
||||
fromRadio.setReadAuthorizeCallback(
|
||||
fromRadioAuthorizeCb,
|
||||
false); // We don't call this callback via the adafruit queue, because we can safely run in the BLE context
|
||||
fromRadio.setBuffer(fromRadioBytes, sizeof(fromRadioBytes)); // we preallocate our fromradio buffer so we won't waste space
|
||||
// for two copies
|
||||
fromRadio.begin();
|
||||
|
||||
toRadio.setProperties(CHR_PROPS_WRITE);
|
||||
toRadio.setPermission(SECMODE_OPEN, SECMODE_OPEN); // FIXME secure this!
|
||||
toRadio.setFixedLen(0);
|
||||
toRadio.setMaxLen(512);
|
||||
toRadio.setBuffer(toRadioBytes, sizeof(toRadioBytes));
|
||||
toRadio.setWriteCallback(
|
||||
toRadioWriteCb,
|
||||
false); // We don't call this callback via the adafruit queue, because we can safely run in the BLE context
|
||||
toRadio.begin();
|
||||
// Configure the Body Sensor Location characteristic
|
||||
// See:
|
||||
// https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.characteristic.body_sensor_location.xml
|
||||
// Properties = Read
|
||||
// Min Len = 1
|
||||
// Max Len = 1
|
||||
// B0 = UINT8 - Body Sensor Location
|
||||
// 0 = Other
|
||||
// 1 = Chest
|
||||
// 2 = Wrist
|
||||
// 3 = Finger
|
||||
// 4 = Hand
|
||||
// 5 = Ear Lobe
|
||||
// 6 = Foot
|
||||
// 7:255 = Reserved
|
||||
bslc.setProperties(CHR_PROPS_READ);
|
||||
bslc.setPermission(SECMODE_OPEN, SECMODE_NO_ACCESS);
|
||||
bslc.setFixedLen(1);
|
||||
bslc.begin();
|
||||
bslc.write8(2); // Set the characteristic to 'Wrist' (2)
|
||||
}
|
||||
|
||||
// FIXME, turn off soft device access for debugging
|
||||
static bool isSoftDeviceAllowed = true;
|
||||
static bool isSoftDeviceAllowed = false;
|
||||
|
||||
void NRF52Bluetooth::setup()
|
||||
{
|
||||
@@ -218,7 +158,7 @@ void NRF52Bluetooth::setup()
|
||||
Bluefruit.begin();
|
||||
|
||||
// Set the advertised device name (keep it short!)
|
||||
Bluefruit.setName(getDeviceName());
|
||||
Bluefruit.setName(getDeviceName()); // FIXME
|
||||
|
||||
// Set the connect/disconnect callback handlers
|
||||
Bluefruit.Periph.setConnectCallback(connect_callback);
|
||||
@@ -226,22 +166,21 @@ void NRF52Bluetooth::setup()
|
||||
|
||||
// Configure and Start the Device Information Service
|
||||
DEBUG_MSG("Configuring the Device Information Service\n");
|
||||
bledis.setManufacturer(HW_VENDOR);
|
||||
bledis.setModel(optstr(HW_VERSION));
|
||||
bledis.setFirmwareRev(optstr(APP_VERSION));
|
||||
bledis.setManufacturer("meshtastic.org");
|
||||
bledis.setModel("NRF52-meshtastic"); // FIXME
|
||||
bledis.begin();
|
||||
|
||||
// Start the BLE Battery Service and set it to 100%
|
||||
DEBUG_MSG("Configuring the Battery Service\n");
|
||||
blebas.begin();
|
||||
blebas.write(0); // Unknown battery level for now
|
||||
blebas.write(42); // FIXME, report real power levels
|
||||
|
||||
bledfu.begin(); // Install the DFU helper
|
||||
|
||||
// Setup the Heart Rate Monitor service using
|
||||
// BLEService and BLECharacteristic classes
|
||||
DEBUG_MSG("Configuring the Mesh bluetooth service\n");
|
||||
setupMeshService();
|
||||
DEBUG_MSG("Configuring the Heart Rate Monitor Service\n");
|
||||
setupHRM();
|
||||
|
||||
// Supposedly debugging works with soft device if you disable advertising
|
||||
if (isSoftDeviceAllowed) {
|
||||
@@ -253,8 +192,56 @@ void NRF52Bluetooth::setup()
|
||||
}
|
||||
}
|
||||
|
||||
/// Given a level between 0-100, update the BLE attribute
|
||||
void updateBatteryLevel(uint8_t level)
|
||||
/*
|
||||
void loop()
|
||||
{
|
||||
blebas.write(level);
|
||||
}
|
||||
digitalToggle(LED_RED);
|
||||
|
||||
if ( Bluefruit.connected() ) {
|
||||
uint8_t hrmdata[2] = { 0b00000110, bps++ }; // Sensor connected, increment BPS value
|
||||
|
||||
// Note: We use .notify instead of .write!
|
||||
// If it is connected but CCCD is not enabled
|
||||
// The characteristic's value is still updated although notification is not sent
|
||||
if ( hrmc.notify(hrmdata, sizeof(hrmdata)) ){
|
||||
Serial.print("Heart Rate Measurement updated to: "); Serial.println(bps);
|
||||
}else{
|
||||
Serial.println("ERROR: Notify not set in the CCCD or not connected!");
|
||||
}
|
||||
}
|
||||
|
||||
// Only send update once per second
|
||||
delay(1000);
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
examples of advanced characteristics. use setReadAuthorizeCallback to prepare data for reads by others
|
||||
|
||||
err_t BLEDfu::begin(void)
|
||||
{
|
||||
// Invoke base class begin()
|
||||
VERIFY_STATUS( BLEService::begin() );
|
||||
|
||||
// No need to keep packet & revision characteristics
|
||||
BLECharacteristic chr_packet(UUID128_CHR_DFU_PACKET);
|
||||
chr_packet.setTempMemory();
|
||||
chr_packet.setProperties(CHR_PROPS_WRITE_WO_RESP);
|
||||
chr_packet.setMaxLen(20);
|
||||
VERIFY_STATUS( chr_packet.begin() );
|
||||
|
||||
_chr_control.setProperties(CHR_PROPS_WRITE | CHR_PROPS_NOTIFY);
|
||||
_chr_control.setMaxLen(23);
|
||||
_chr_control.setWriteAuthorizeCallback(bledfu_control_wr_authorize_cb);
|
||||
VERIFY_STATUS( _chr_control.begin() );
|
||||
|
||||
BLECharacteristic chr_revision(UUID128_CHR_DFU_REVISON);
|
||||
chr_revision.setTempMemory();
|
||||
chr_revision.setProperties(CHR_PROPS_READ);
|
||||
chr_revision.setFixedLen(2);
|
||||
VERIFY_STATUS( chr_revision.begin());
|
||||
chr_revision.write16(DFU_REV_APPMODE);
|
||||
|
||||
return ERROR_NONE;
|
||||
}
|
||||
*/
|
||||
@@ -1,31 +0,0 @@
|
||||
#include "rtos.h"
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/**
|
||||
* Custom new/delete to panic if out out memory
|
||||
*/
|
||||
|
||||
void *operator new(size_t size)
|
||||
{
|
||||
auto p = rtos_malloc(size);
|
||||
assert(p);
|
||||
return p;
|
||||
}
|
||||
|
||||
void *operator new[](size_t size)
|
||||
{
|
||||
auto p = rtos_malloc(size);
|
||||
assert(p);
|
||||
return p;
|
||||
}
|
||||
|
||||
void operator delete(void *ptr)
|
||||
{
|
||||
rtos_free(ptr);
|
||||
}
|
||||
|
||||
void operator delete[](void *ptr)
|
||||
{
|
||||
rtos_free(ptr);
|
||||
}
|
||||
@@ -5,49 +5,47 @@
|
||||
|
||||
enum { r0, r1, r2, r3, r12, lr, pc, psr };
|
||||
|
||||
// we can't use the regular DEBUG_MSG for these crash dumps because it depends on threading still being running. Instead use the
|
||||
// segger in memory tool
|
||||
#define FAULT_MSG(...) SEGGER_MSG(__VA_ARGS__)
|
||||
|
||||
// Per http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0552a/Cihcfefj.html
|
||||
static void printUsageErrorMsg(uint32_t cfsr)
|
||||
{
|
||||
FAULT_MSG("Usage fault: ");
|
||||
DEBUG_MSG("Usage fault: ");
|
||||
cfsr >>= SCB_CFSR_USGFAULTSR_Pos; // right shift to lsb
|
||||
if ((cfsr & (1 << 9)) != 0)
|
||||
FAULT_MSG("Divide by zero\n");
|
||||
DEBUG_MSG("Divide by zero\n");
|
||||
if ((cfsr & (1 << 8)) != 0)
|
||||
FAULT_MSG("Unaligned\n");
|
||||
DEBUG_MSG("Unaligned\n");
|
||||
}
|
||||
|
||||
static void printBusErrorMsg(uint32_t cfsr)
|
||||
{
|
||||
FAULT_MSG("Bus fault: ");
|
||||
DEBUG_MSG("Usage fault: ");
|
||||
cfsr >>= SCB_CFSR_BUSFAULTSR_Pos; // right shift to lsb
|
||||
if ((cfsr & (1 << 0)) != 0)
|
||||
FAULT_MSG("Instruction bus error\n");
|
||||
DEBUG_MSG("Instruction bus error\n");
|
||||
if ((cfsr & (1 << 1)) != 0)
|
||||
FAULT_MSG("Precise data bus error\n");
|
||||
DEBUG_MSG("Precise data bus error\n");
|
||||
if ((cfsr & (1 << 2)) != 0)
|
||||
FAULT_MSG("Imprecise data bus error\n");
|
||||
DEBUG_MSG("Imprecise data bus error\n");
|
||||
}
|
||||
|
||||
static void printMemErrorMsg(uint32_t cfsr)
|
||||
{
|
||||
FAULT_MSG("Memory fault: ");
|
||||
DEBUG_MSG("Usage fault: ");
|
||||
cfsr >>= SCB_CFSR_MEMFAULTSR_Pos; // right shift to lsb
|
||||
if ((cfsr & (1 << 0)) != 0)
|
||||
FAULT_MSG("Instruction access violation\n");
|
||||
DEBUG_MSG("Instruction access violation\n");
|
||||
if ((cfsr & (1 << 1)) != 0)
|
||||
FAULT_MSG("Data access violation\n");
|
||||
DEBUG_MSG("Data access violation\n");
|
||||
}
|
||||
|
||||
extern "C" void HardFault_Impl(uint32_t stack[])
|
||||
static void HardFault_Impl(uint32_t stack[])
|
||||
{
|
||||
FAULT_MSG("Hard Fault occurred! SCB->HFSR = 0x%08lx\n", SCB->HFSR);
|
||||
DEBUG_MSG("In Hard Fault Handler\n");
|
||||
DEBUG_MSG("SCB->HFSR = 0x%08lx\n", SCB->HFSR);
|
||||
|
||||
if ((SCB->HFSR & SCB_HFSR_FORCED_Msk) != 0) {
|
||||
FAULT_MSG("Forced Hard Fault: SCB->CFSR = 0x%08lx\n", SCB->CFSR);
|
||||
DEBUG_MSG("Forced Hard Fault\n");
|
||||
DEBUG_MSG("SCB->CFSR = 0x%08lx\n", SCB->CFSR);
|
||||
|
||||
if ((SCB->CFSR & SCB_CFSR_USGFAULTSR_Msk) != 0) {
|
||||
printUsageErrorMsg(SCB->CFSR);
|
||||
@@ -59,23 +57,21 @@ extern "C" void HardFault_Impl(uint32_t stack[])
|
||||
printMemErrorMsg(SCB->CFSR);
|
||||
}
|
||||
|
||||
FAULT_MSG("r0 = 0x%08lx\n", stack[r0]);
|
||||
FAULT_MSG("r1 = 0x%08lx\n", stack[r1]);
|
||||
FAULT_MSG("r2 = 0x%08lx\n", stack[r2]);
|
||||
FAULT_MSG("r3 = 0x%08lx\n", stack[r3]);
|
||||
FAULT_MSG("r12 = 0x%08lx\n", stack[r12]);
|
||||
FAULT_MSG("lr = 0x%08lx\n", stack[lr]);
|
||||
FAULT_MSG("pc = 0x%08lx\n", stack[pc]);
|
||||
FAULT_MSG("psr = 0x%08lx\n", stack[psr]);
|
||||
DEBUG_MSG("r0 = 0x%08lx\n", stack[r0]);
|
||||
DEBUG_MSG("r1 = 0x%08lx\n", stack[r1]);
|
||||
DEBUG_MSG("r2 = 0x%08lx\n", stack[r2]);
|
||||
DEBUG_MSG("r3 = 0x%08lx\n", stack[r3]);
|
||||
DEBUG_MSG("r12 = 0x%08lx\n", stack[r12]);
|
||||
DEBUG_MSG("lr = 0x%08lx\n", stack[lr]);
|
||||
DEBUG_MSG("pc = 0x%08lx\n", stack[pc]);
|
||||
DEBUG_MSG("psr = 0x%08lx\n", stack[psr]);
|
||||
asm volatile("bkpt #01");
|
||||
while (1)
|
||||
;
|
||||
}
|
||||
|
||||
FAULT_MSG("Done with fault report - Waiting to reboot\n");
|
||||
asm volatile("bkpt #01"); // Enter the debugger if one is connected
|
||||
while (1)
|
||||
;
|
||||
}
|
||||
|
||||
extern "C" void HardFault_Handler(void)
|
||||
void HardFault_Handler(void)
|
||||
{
|
||||
asm volatile(" mrs r0,msp\n"
|
||||
" b HardFault_Impl \n");
|
||||
|
||||
@@ -3,11 +3,7 @@
|
||||
#include <assert.h>
|
||||
#include <ble_gap.h>
|
||||
#include <memory.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef NRF52840_XXAA
|
||||
// #include <nrf52840.h>
|
||||
#endif
|
||||
#include <nrf52840.h>
|
||||
|
||||
// #define USE_SOFTDEVICE
|
||||
|
||||
@@ -53,7 +49,6 @@ void setBluetoothEnable(bool on)
|
||||
if (on != bleOn) {
|
||||
if (on) {
|
||||
if (!nrf52Bluetooth) {
|
||||
// DEBUG_MSG("DISABLING NRF52 BLUETOOTH WHILE DEBUGGING\n");
|
||||
nrf52Bluetooth = new NRF52Bluetooth();
|
||||
nrf52Bluetooth->setup();
|
||||
}
|
||||
@@ -64,18 +59,6 @@ void setBluetoothEnable(bool on)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Override printf to use the SEGGER output library
|
||||
*/
|
||||
int printf(const char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
auto res = SEGGER_RTT_vprintf(0, fmt, &args);
|
||||
va_end(args);
|
||||
return res;
|
||||
}
|
||||
|
||||
void nrf52Setup()
|
||||
{
|
||||
|
||||
@@ -97,5 +80,4 @@ void nrf52Setup()
|
||||
// ble_controller_rand_vector_get_blocking(&r, sizeof(r));
|
||||
// randomSeed(r);
|
||||
DEBUG_MSG("FIXME, call randomSeed\n");
|
||||
// ::printf("TESTING PRINTF\n");
|
||||
}
|
||||
@@ -128,7 +128,25 @@ static const uint8_t SCK = PIN_SPI_SCK;
|
||||
#define PIN_WIRE_SDA (32 + 2)
|
||||
#define PIN_WIRE_SCL (32)
|
||||
|
||||
#define GPS_I2C_ADDR FIXME
|
||||
// CUSTOM GPIOs the SX1262
|
||||
#define SX1262_CS (10)
|
||||
#define SX1262_DIO1 (20)
|
||||
#define SX1262_DIO2 (26)
|
||||
#define SX1262_BUSY (31) // Supposed to be P0.18 but because of reworks, now on P0.31 (18)
|
||||
#define SX1262_RESET (17)
|
||||
// #define SX1262_ANT_SW (32 + 10)
|
||||
#define SX1262_RXEN (22)
|
||||
#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
|
||||
#define ERC12864_CS (32 + 4)
|
||||
#define ERC12864_RESET (32 + 6)
|
||||
#define ERC12864_CD (32 + 9)
|
||||
|
||||
// L80 GPS
|
||||
#define L80_PPS (28)
|
||||
#define L80_RESET (29)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user