Compare commits

..

11 Commits

Author SHA1 Message Date
Matthias Wientapper
0fbd92b4b5 rak4631: set lockout voltage to 0V 2026-03-06 19:45:59 +01:00
Matthias Wientapper
11852ca08c set default: disable flood adverts 2026-03-06 19:45:59 +01:00
Matthias Wientapper
660b19ab4c Integration of upstrem PR #1810 2026-03-06 19:45:59 +01:00
Matthias Wientapper
a4d38f902f Integration of upstrem PR #1338 2026-03-06 19:45:57 +01:00
Matthias Wientapper
c0cf31ffe2 Integration of upstrem PR #1297 2026-03-06 19:45:55 +01:00
mattzzw
853ee62eb0 Update examples/simple_room_server/MyMesh.cpp
Fix pow() and rand() are calculated for every forwarded packet, but we only need it for flood advert. Also fixes 'paket' typo.

Co-authored-by: Wessel <wessel@weebl.me>
2026-03-05 11:32:47 +01:00
mattzzw
7af6941220 Update examples/simple_repeater/MyMesh.cpp
Fix pow() and rand() are calculated for every forwarded packet, but we only need it for flood advert. Also fixes 'paket' typo.

Co-authored-by: Wessel <wessel@weebl.me>
2026-03-05 11:32:47 +01:00
mattzzw
a678c4a9e6 Update src/helpers/CommonCLI.cpp
Co-authored-by: Wessel <wessel@weebl.me>
2026-03-05 11:32:47 +01:00
Matthias Wientapper
e24b5ff263 Add cli config flood.advert.base
0 = forwarding flood adverts off
1 = forwarding flood adverts on (unrestricted)
0.308 (default) = prob. forwarding according to #1338
2026-03-05 11:32:47 +01:00
Matthias Wientapper
6209ad12ce Limit flood advert packet forwarding for roomservers as well 2026-03-05 11:32:47 +01:00
Matthias Wientapper
971b3f414f Limit flood advert packet forwarding, implements #1223 2026-03-05 11:31:43 +01:00
224 changed files with 362 additions and 2151 deletions

View File

@@ -2,7 +2,6 @@
"name": "MeshCore",
"image": "mcr.microsoft.com/devcontainers/python:3-bookworm",
"features": {
"ghcr.io/devcontainers-extra/features/bun:1": {},
"ghcr.io/rocker-org/devcontainer-features/apt-packages:1": {
"packages": [
"sudo"
@@ -12,15 +11,14 @@
"runArgs": [
"--privileged",
"--network=host",
"--device=/dev/bus/usb",
// arch linux tty* is owned by uucp (986)
"--group-add=986",
"--volume=/dev/bus/usb:/dev/bus/usb:ro",
// arch tty* is owned by uucp (986)
// debian tty* is owned by dialout (20)
"--group-add=20"
"--group-add=20",
"--group-add=986"
],
"postCreateCommand": {
"platformio": "pipx install platformio",
"opencode": "curl -fsSL https://opencode.ai/install | bash"
"platformio": "pipx install platformio"
},
"customizations": {
"vscode": {

View File

@@ -9,14 +9,6 @@ on:
- 'variants/**'
- 'platformio.ini'
- '.github/workflows/pr-build-check.yml'
push:
branches: [main, dev]
paths:
- 'src/**'
- 'examples/**'
- 'variants/**'
- 'platformio.ini'
- '.github/workflows/pr-build-check.yml'
jobs:
build:

View File

@@ -39,7 +39,7 @@
"frameworks": ["arduino"],
"name": "Heltec nrf (Adafruit BSP)",
"upload": {
"maximum_ram_size": 235520,
"maximum_ram_size": 248832,
"maximum_size": 815104,
"speed": 115200,
"protocol": "nrfutil",

View File

@@ -42,7 +42,7 @@
],
"name": "Heltec Mesh Solar Board",
"upload": {
"maximum_ram_size": 235520,
"maximum_ram_size": 248832,
"maximum_size": 815104,
"speed": 115200,
"protocol": "nrfutil",

View File

@@ -42,7 +42,7 @@
],
"name": "Heltec T114 Board",
"upload": {
"maximum_ram_size": 235520,
"maximum_ram_size": 248832,
"maximum_size": 815104,
"speed": 115200,
"protocol": "nrfutil",

View File

@@ -60,7 +60,7 @@
],
"name": "Keepteen LT1",
"upload": {
"maximum_ram_size": 235520,
"maximum_ram_size": 248832,
"maximum_size": 815104,
"speed": 115200,
"protocol": "nrfutil",

View File

@@ -55,7 +55,7 @@
],
"name": "Meshtiny",
"upload": {
"maximum_ram_size": 235520,
"maximum_ram_size": 248832,
"maximum_size": 815104,
"speed": 115200,
"protocol": "nrfutil",

View File

@@ -38,8 +38,8 @@
"frameworks": ["arduino"],
"name": "Minewsemi ME25LS01",
"upload": {
"maximum_ram_size": 235520,
"maximum_size": 811008,
"maximum_ram_size": 248832,
"maximum_size": 815104,
"speed": 115200,
"protocol": "nrfutil",
"protocols": [

View File

@@ -54,7 +54,7 @@
],
"name": "BQ nRF52840",
"upload": {
"maximum_ram_size": 235520,
"maximum_ram_size": 248832,
"maximum_size": 815104,
"speed": 115200,
"protocol": "nrfutil",

View File

@@ -60,7 +60,7 @@
],
"name": "ProMicro NRF52840",
"upload": {
"maximum_ram_size": 235520,
"maximum_ram_size": 248832,
"maximum_size": 815104,
"speed": 115200,
"protocol": "nrfutil",

View File

@@ -46,15 +46,14 @@
],
"debug": {
"jlink_device": "nRF52840_xxAA",
"svd_path": "nrf52840.svd",
"openocd_target": "nrf52.cfg"
"svd_path": "nrf52840.svd"
},
"frameworks": [
"arduino"
],
"name": "WisCore RAK3401 Board",
"upload": {
"maximum_ram_size": 235520,
"maximum_ram_size": 248832,
"maximum_size": 815104,
"speed": 115200,
"protocol": "nrfutil",

View File

@@ -46,15 +46,14 @@
],
"debug": {
"jlink_device": "nRF52840_xxAA",
"svd_path": "nrf52840.svd",
"openocd_target": "nrf52.cfg"
"svd_path": "nrf52840.svd"
},
"frameworks": [
"arduino"
],
"name": "WisCore RAK4631 Board",
"upload": {
"maximum_ram_size": 235520,
"maximum_ram_size": 248832,
"maximum_size": 815104,
"speed": 115200,
"protocol": "nrfutil",

View File

@@ -40,7 +40,7 @@
],
"name": "Seeed Wio Tracker L1",
"upload": {
"maximum_ram_size": 235520,
"maximum_ram_size": 237568,
"maximum_size": 811008,
"protocol": "nrfutil",
"speed": 115200,

View File

@@ -40,7 +40,7 @@
],
"name": "Seeed Studio XIAO nRF52840",
"upload": {
"maximum_ram_size": 235520,
"maximum_ram_size": 237568,
"maximum_size": 811008,
"protocol": "nrfutil",
"speed": 115200,

View File

@@ -39,8 +39,8 @@
],
"name": "Seeed Studio XIAO nRF52840",
"upload": {
"maximum_ram_size": 235520,
"maximum_size": 811008,
"maximum_ram_size": 248832,
"maximum_size": 815104,
"protocol": "nrfutil",
"speed": 115200,
"protocols": [

View File

@@ -45,7 +45,7 @@
],
"name": "LilyGo T-ECHO",
"upload": {
"maximum_ram_size": 235520,
"maximum_ram_size": 248832,
"maximum_size": 815104,
"require_upload_port": true,
"speed": 115200,

View File

@@ -53,7 +53,7 @@
],
"name": "elecrow eink",
"upload": {
"maximum_ram_size": 235520,
"maximum_ram_size": 248832,
"maximum_size": 815104,
"speed": 115200,
"use_1200bps_touch": true,

View File

@@ -53,7 +53,7 @@
],
"name": "elecrow nrf",
"upload": {
"maximum_ram_size": 235520,
"maximum_ram_size": 248832,
"maximum_size": 815104,
"speed": 115200,
"use_1200bps_touch": true,

View File

@@ -53,7 +53,7 @@
],
"name": "elecrow solar",
"upload": {
"maximum_ram_size": 235520,
"maximum_ram_size": 248832,
"maximum_size": 815104,
"speed": 115200,
"use_1200bps_touch": true,

View File

@@ -38,8 +38,8 @@
"frameworks": ["arduino"],
"name": "Seeed T1000-E",
"upload": {
"maximum_ram_size": 235520,
"maximum_size": 811008,
"maximum_ram_size": 248832,
"maximum_size": 815104,
"speed": 115200,
"protocol": "nrfutil",
"protocols": [

View File

@@ -63,12 +63,6 @@ This document provides an overview of CLI commands that can be sent to MeshCore
---
### Send a zero-hop advert
**Usage:**
- `advert.zerohop`
---
### Start an Over-The-Air (OTA) firmware update
**Usage:**
- `start ota`
@@ -361,25 +355,13 @@ This document provides an overview of CLI commands that can be sent to MeshCore
---
#### View this node's public key
**Usage:** `get public.key`
---
#### View this node's configured role
**Usage:** `get role`
---
#### View or change this node's power saving flag (Repeater Only)
**Usage:**
- `powersaving <state>`
- `powersaving`
- `powersaving on`
- `powersaving off`
**Parameters:**
- `on`: enable power saving
- `off`: disable power saving
- `state`: `on`|`off`
**Default:** `on`
@@ -401,46 +383,6 @@ This document provides an overview of CLI commands that can be sent to MeshCore
---
#### View or change this node's advert path hash size
**Usage:**
- `get path.hash.mode`
- `set path.hash.mode <value>`
**Parameters:**
- `value`: Path hash size (0-2)
- `0`: 1 Byte hash size (256 unique ids)[64 max flood]
- `1`: 2 Byte hash size (65,536 unique ids)[32 max flood]
- `2`: 3 Byte hash size (16,777,216 unique ids)[21 max flood]
- `3`: DO NOT USE (Reserved)
**Default:** `0`
**Note:** the 'path.hash.mode' sets the low-level ID/hash encoding size used when the repeater adverts. This setting has no impact on what packet ID/hash size this repeater forwards, all sizes should be forwarded on firmware >= 1.14. This feature was added in firmware 1.14
**Temporary Note:** adverts with ID/hash sizes of 2 or 3 bytes may have limited flood propogation in your network while this feature is new as v1.13.0 firmware and older will drop packets with multibyte path ID/hashes as only 1-byte hashes are suppored. Consider your install base of firmware >=1.14 has reached a criticality for effective network flooding before implementing higher ID/hash sizes.
---
#### View or change this node's loop detection
**Usage:**
- `get loop.detect`
- `set loop.detect <state>`
**Parameters:**
- `state`:
- `off`: no loop detection is performed
- `minimal`: packets are dropped if repeater's ID/hash appears 4 or more times (1-byte), 2 or more (2-byte), 1 or more (3-byte)
- `moderate`: packets are dropped if repeater's ID/hash appears 2 or more times (1-byte), 1 or more (2-byte), 1 or more (3-byte)
- `strict`: packets are dropped if repeater's ID/hash appears 1 or more times (1-byte), 1 or more (2-byte), 1 or more (3-byte)
**Default:** `off`
**Note:** When it is enabled, repeaters will now reject flood packets which look like they are in a loop. This has been happening recently in some meshes when there is just a single 'bad' repeater firmware out there (prob some forked or custom firmware). If the payload is messed with, then forwarded, the same packet ends up causing a packet storm, repeated up to the max 64 hops. This feature was added in firmware 1.14
**Example:** If preference is `loop.detect minimal`, and a 1-byte path size packet is received, the repeater will see if its own ID/hash is already in the path. If it's already encoded 4 times, it will reject the packet. If the packet uses 2-byte path size, and repeater's own ID/hash is already encoded 2 times, it rejects. If the packet uses 3-byte path size, and the repeater's own ID/hash is already encoded 1 time, it rejects.
---
#### View or change the retransmit delay factor for flood traffic
**Usage:**
- `get txdelay`
@@ -862,11 +804,6 @@ region save
### Bridge (When bridge support is compiled in)
#### View the compiled bridge type
**Usage:** `get bridge.type`
---
#### View or change the bridge enabled flag
**Usage:**
- `get bridge.enabled`
@@ -879,6 +816,12 @@ region save
---
#### View the bridge source
**Usage:**
- `get bridge.source`
---
#### Add a delay to packets routed through this bridge
**Usage:**
- `get bridge.delay`
@@ -898,10 +841,10 @@ region save
**Parameters:**
- `source`:
- `logRx`: bridges received packets
- `logTx`: bridges transmitted packets
- `rx`: bridges received packets
- `tx`: bridges transmitted packets
**Default:** `logTx`
**Default:** `tx`
---
@@ -933,39 +876,8 @@ region save
- `set bridge.secret <secret>`
**Parameters:**
- `secret`: ESP-NOW bridge secret, up to 15 characters
- `secret`: 16-character encryption secret
**Default:** Varies by board
---
#### View the bootloader version (nRF52 only)
**Usage:** `get bootloader.ver`
---
#### View power management support
**Usage:** `get pwrmgt.support`
---
#### View the current power source
**Usage:** `get pwrmgt.source`
**Note:** Returns an error on boards without power management support.
---
#### View the boot reset and shutdown reasons
**Usage:** `get pwrmgt.bootreason`
**Note:** Returns an error on boards without power management support.
---
#### View the boot voltage
**Usage:** `get pwrmgt.bootmv`
**Note:** Returns an error on boards without power management support.
---

View File

@@ -1,6 +1,6 @@
# Companion Protocol
- **Last Updated**: 2026-03-08
- **Last Updated**: 2026-01-03
- **Protocol Version**: Companion Firmware v1.12.0+
> NOTE: This document is still in development. Some information may be inaccurate.
@@ -100,7 +100,7 @@ When writing commands to the RX characteristic, specify the write type:
### MTU (Maximum Transmission Unit)
The default BLE MTU is 23 bytes (20 bytes payload). For larger commands like `SET_CHANNEL` (50 bytes), you may need to:
The default BLE MTU is 23 bytes (20 bytes payload). For larger commands like `SET_CHANNEL` (66 bytes), you may need to:
1. **Request Larger MTU**: Request MTU of 512 bytes if supported
- Android: `gatt.requestMtu(512)`
@@ -167,16 +167,16 @@ The first byte indicates the packet type (see [Response Parsing](#response-parsi
**Command Format**:
```
Byte 0: 0x01
Bytes 1-7: Reserved (currently ignored by firmware)
Bytes 8+: Application name (UTF-8, optional)
Byte 1: 0x03
Bytes 2-10: "mccli" (ASCII, null-padded to 9 bytes)
```
**Example** (hex):
```
01 00 00 00 00 00 00 00 6d 63 63 6c 69
01 03 6d 63 63 6c 69 00 00 00 00
```
**Response**: `PACKET_SELF_INFO` (0x05)
**Response**: `PACKET_OK` (0x00)
---
@@ -216,6 +216,8 @@ Byte 1: Channel Index (0-7)
**Response**: `PACKET_CHANNEL_INFO` (0x12) with channel details
**Note**: The device does not return channel secrets for security reasons. Store secrets locally when creating channels.
---
### 4. Set Channel
@@ -227,10 +229,10 @@ Byte 1: Channel Index (0-7)
Byte 0: 0x20
Byte 1: Channel Index (0-7)
Bytes 2-33: Channel Name (32 bytes, UTF-8, null-padded)
Bytes 34-49: Secret (16 bytes)
Bytes 34-65: Secret (32 bytes)
```
**Total Length**: 50 bytes
**Total Length**: 66 bytes
**Channel Index**:
- Index 0: Reserved for public channels (no secret)
@@ -241,18 +243,16 @@ Bytes 34-49: Secret (16 bytes)
- Maximum 32 bytes
- Padded with null bytes (0x00) if shorter
**Secret Field** (16 bytes):
- For **private channels**: 16-byte secret
**Secret Field** (32 bytes):
- For **private channels**: 32-byte secret
- For **public channels**: All zeros (0x00)
**Example** (create channel "YourChannelName" at index 1 with secret):
```
20 01 53 4D 53 00 00 ... (name padded to 32 bytes)
[16 bytes of secret]
[32 bytes of secret]
```
**Note**: The 32-byte secret variant is unsupported and returns `PACKET_ERROR`.
**Response**: `PACKET_OK` (0x00) on success, `PACKET_ERROR` (0x01) on failure
---
@@ -304,9 +304,9 @@ Byte 0: 0x0A
---
### 7. Get Battery and Storage
### 7. Get Battery
**Purpose**: Query device battery voltage and storage usage.
**Purpose**: Query device battery level.
**Command Format**:
```
@@ -318,7 +318,7 @@ Byte 0: 0x14
14
```
**Response**: `PACKET_BATTERY` (0x0C) with battery millivolts and storage information
**Response**: `PACKET_BATTERY` (0x0C) with battery percentage
---
@@ -346,7 +346,7 @@ Byte 0: 0x14
1. **Set Channel**:
- Fetch all channel slots, and find one with empty name and all-zero secret
- Generate or provide a 16-byte secret
- Send `CMD_SET_CHANNEL` with name and a 16-byte secret
- Send `CMD_SET_CHANNEL` with name and secret
2. **Get Channel**:
- Send `CMD_GET_CHANNEL` with channel index
- Parse `RESP_CODE_CHANNEL_INFO` response
@@ -360,7 +360,7 @@ Byte 0: 0x14
### Receiving Messages
Messages are received via the TX characteristic (notifications). The device sends:
Messages are received via the RX characteristic (notifications). The device sends:
1. **Channel Messages**:
- `PACKET_CHANNEL_MSG_RECV` (0x08) - Standard format
@@ -544,10 +544,10 @@ Byte 1: Error code (optional)
Byte 0: 0x12
Byte 1: Channel Index
Bytes 2-33: Channel Name (32 bytes, null-terminated)
Bytes 34-49: Secret (16 bytes)
Bytes 34-65: Secret (32 bytes, but device typically only returns 20 bytes total)
```
**Note**: The device returns the 16-byte channel secret in this response.
**Note**: The device may not return the full 66-byte packet. Parse what is available. The secret field is typically not returned for security reasons.
**PACKET_DEVICE_INFO** (0x0D):
```
@@ -562,8 +562,6 @@ Bytes 4-7: BLE PIN (32-bit little-endian)
Bytes 8-19: Firmware Build (12 bytes, UTF-8, null-padded)
Bytes 20-59: Model (40 bytes, UTF-8, null-padded)
Bytes 60-79: Version (20 bytes, UTF-8, null-padded)
Byte 80: Client repeat enabled/preferred (firmware v9+)
Byte 81: Path hash mode (firmware v10+)
```
**Parsing Pseudocode**:
@@ -589,7 +587,9 @@ def parse_device_info(data):
**PACKET_BATTERY** (0x0C):
```
Byte 0: 0x0C
Bytes 1-2: Battery Voltage (16-bit little-endian, millivolts)
Bytes 1-2: Battery Level (16-bit little-endian, percentage 0-100)
Optional (if data size > 3):
Bytes 3-6: Used Storage (32-bit little-endian, KB)
Bytes 7-10: Total Storage (32-bit little-endian, KB)
```
@@ -600,12 +600,14 @@ def parse_battery(data):
if len(data) < 3:
return None
mv = int.from_bytes(data[1:3], 'little')
info = {'battery_mv': mv}
level = int.from_bytes(data[1:3], 'little')
info = {'level': level}
if len(data) >= 11:
info['used_kb'] = int.from_bytes(data[3:7], 'little')
info['total_kb'] = int.from_bytes(data[7:11], 'little')
if len(data) > 3:
used_kb = int.from_bytes(data[3:7], 'little')
total_kb = int.from_bytes(data[7:11], 'little')
info['used_kb'] = used_kb
info['total_kb'] = total_kb
return info
```
@@ -627,7 +629,7 @@ Bytes 48-51: Radio Frequency (32-bit little-endian, divided by 1000.0)
Bytes 52-55: Radio Bandwidth (32-bit little-endian, divided by 1000.0)
Byte 56: Radio Spreading Factor
Byte 57: Radio Coding Rate
Bytes 58+: Device Name (UTF-8, variable length, no null terminator required)
Bytes 58+: Device Name (UTF-8, variable length, null-terminated)
```
**Parsing Pseudocode**:
@@ -678,9 +680,9 @@ def parse_self_info(data):
**PACKET_MSG_SENT** (0x06):
```
Byte 0: 0x06
Byte 1: Route Flag (0 = direct, 1 = flood)
Bytes 2-5: Tag / Expected ACK (4 bytes, little-endian)
Bytes 6-9: Suggested Timeout (32-bit little-endian, milliseconds)
Byte 1: Message Type
Bytes 2-5: Expected ACK (4 bytes, hex)
Bytes 6-9: Suggested Timeout (32-bit little-endian, seconds)
```
**PACKET_ACK** (0x82):
@@ -708,32 +710,89 @@ Bytes 1-6: ACK Code (6 bytes, hex)
**Note**: Error codes may vary by firmware version. Always check byte 1 of `PACKET_ERROR` response.
### Frame Handling
### Partial Packet Handling
BLE implementations enqueue and deliver one protocol frame per BLE write/notification at the firmware layer.
BLE notifications may arrive in chunks, especially for larger packets. Implement buffering:
- Apps should treat each characteristic write/notification as exactly one companion protocol frame
- Apps should still validate frame lengths before parsing
- Future transports or firmware revisions may differ, so avoid assuming fixed payload sizes for variable-length responses
**Implementation**:
```python
class PacketBuffer:
def __init__(self):
self.buffer = bytearray()
self.expected_length = None
def add_data(self, data):
self.buffer.extend(data)
# Check if we have a complete packet
if len(self.buffer) >= 1:
packet_type = self.buffer[0]
# Determine expected length based on packet type
expected = self.get_expected_length(packet_type)
if expected is not None and len(self.buffer) >= expected:
# Complete packet
packet = bytes(self.buffer[:expected])
self.buffer = self.buffer[expected:]
return packet
elif expected is None:
# Variable length packet - try to parse what we have
# Some packets have minimum length requirements
if self.can_parse_partial(packet_type):
return self.try_parse_partial()
return None # Incomplete packet
def get_expected_length(self, packet_type):
# Fixed-length packets
fixed_lengths = {
0x00: 5, # PACKET_OK (minimum)
0x01: 2, # PACKET_ERROR (minimum)
0x0A: 1, # PACKET_NO_MORE_MSGS
0x14: 3, # PACKET_BATTERY (minimum)
}
return fixed_lengths.get(packet_type)
def can_parse_partial(self, packet_type):
# Some packets can be parsed partially
return packet_type in [0x12, 0x08, 0x11, 0x07, 0x10, 0x05, 0x0D]
def try_parse_partial(self):
# Try to parse with available data
# Return packet if successfully parsed, None otherwise
# This is packet-type specific
pass
```
**Usage**:
```python
buffer = PacketBuffer()
def on_notification_received(data):
packet = buffer.add_data(data)
if packet:
parse_and_handle_packet(packet)
```
### Response Handling
1. **Command-Response Pattern**:
- Send command via RX characteristic
- Wait for response via TX characteristic (notification)
- Send command via TX characteristic
- Wait for response via RX characteristic (notification)
- Match response to command using sequence numbers or command type
- Handle timeout (typically 5 seconds)
- Use command queue to prevent concurrent commands
2. **Asynchronous Messages**:
- Device may send messages at any time via TX characteristic
- Device may send messages at any time via RX characteristic
- Handle `PACKET_MESSAGES_WAITING` (0x83) by polling `GET_MESSAGE` command
- Parse incoming messages and route to appropriate handlers
- Validate frame length before decoding
- Buffer partial packets until complete
3. **Response Matching**:
- Match responses to commands by expected packet type:
- `APP_START``PACKET_SELF_INFO`
- `APP_START``PACKET_OK`
- `DEVICE_QUERY``PACKET_DEVICE_INFO`
- `GET_CHANNEL``PACKET_CHANNEL_INFO`
- `SET_CHANNEL``PACKET_OK` or `PACKET_ERROR`
@@ -766,16 +825,16 @@ device = scan_for_device("MeshCore")
gatt = connect_to_device(device)
# 3. Discover services and characteristics
service = discover_service(gatt, "6E400001-B5A3-F393-E0A9-E50E24DCCA9E")
rx_char = discover_characteristic(service, "6E400002-B5A3-F393-E0A9-E50E24DCCA9E")
tx_char = discover_characteristic(service, "6E400003-B5A3-F393-E0A9-E50E24DCCA9E")
service = discover_service(gatt, "0000ff00-0000-1000-8000-00805f9b34fb")
rx_char = discover_characteristic(service, "0000ff01-0000-1000-8000-00805f9b34fb")
tx_char = discover_characteristic(service, "0000ff02-0000-1000-8000-00805f9b34fb")
# 4. Enable notifications on TX characteristic
enable_notifications(tx_char, on_notification_received)
# 4. Enable notifications on RX characteristic
enable_notifications(rx_char, on_notification_received)
# 5. Send AppStart command
send_command(rx_char, build_app_start())
wait_for_response(PACKET_SELF_INFO)
send_command(tx_char, build_app_start())
wait_for_response(PACKET_OK)
```
### Creating a Private Channel
@@ -785,16 +844,21 @@ wait_for_response(PACKET_SELF_INFO)
secret_16_bytes = generate_secret(16) # Use CSPRNG
secret_hex = secret_16_bytes.hex()
# 2. Build SET_CHANNEL command
# 2. Expand secret to 32 bytes using SHA-512
import hashlib
sha512_hash = hashlib.sha512(secret_16_bytes).digest()
secret_32_bytes = sha512_hash[:32]
# 3. Build SET_CHANNEL command
channel_name = "YourChannelName"
channel_index = 1 # Use 1-7 for private channels
command = build_set_channel(channel_index, channel_name, secret_16_bytes)
command = build_set_channel(channel_index, channel_name, secret_32_bytes)
# 3. Send command
send_command(rx_char, command)
# 4. Send command
send_command(tx_char, command)
response = wait_for_response(PACKET_OK)
# 4. Store secret locally
# 5. Store secret locally (device won't return it)
store_channel_secret(channel_index, secret_hex)
```
@@ -808,7 +872,7 @@ timestamp = int(time.time())
command = build_channel_message(channel_index, message, timestamp)
# 2. Send command
send_command(rx_char, command)
send_command(tx_char, command)
response = wait_for_response(PACKET_MSG_SENT)
```
@@ -823,7 +887,7 @@ def on_notification_received(data):
handle_channel_message(message)
elif packet_type == PACKET_MESSAGES_WAITING:
# Poll for messages
send_command(rx_char, build_get_message())
send_command(tx_char, build_get_message())
```
---

View File

@@ -221,11 +221,11 @@ MeshCore allows you to manually broadcast your name, position and public encrypt
* Zero hop means your advert is broadcasted out to anyone that can hear it, and that's it.
* Flooded means it's broadcasted out and then repeated by all the repeaters that hear it.
MeshCore clients only advertise themselves when the user initiates it. A repeater sends a flood advert once every 12 hours by default. This interval can be configured using the following command:
MeshCore clients only advertise themselves when the user initiates it. A repeater sends a flood advert once every 3 hours by default. This interval can be configured using the following command:
`set flood.advert.interval {hours}`
`set advert.interval {minutes}`
The separate `set advert.interval {minutes}` command controls the local zero-hop advert timer.
As of Aug 20 2025, a pending PR on github will change the flood advert to 12 hours to minimize airtime utilization caused by repeaters' flood adverts.
### 2.5. Q: Is there a hop limit?
@@ -260,9 +260,7 @@ Repeater or room server can be administered with one of the options below:
### 3.2. Q: Do I need to set the location for a repeater?
**A:** While not required, with location set for a repeater it will show up on the MeshCore map in the future. Set location with the following command:
`set lat <GPS Lat>`
`set lon <GPS Lon>`
`set lat <GPS Lat> set long <GPS Lon>`
You can get the latitude and longitude from Google Maps by right-clicking the location you are at on the map.

View File

@@ -190,7 +190,7 @@ All values little-endian.
| Field | Size | Description |
|-------|------|-------------|
| MAC | 2 bytes | HMAC-SHA256 truncated to 2 bytes |
| Ciphertext | variable | AES-128 block-encrypted data with zero padding |
| Ciphertext | variable | AES-128-CBC encrypted data |
### Airtime (Airtime response)
@@ -268,7 +268,7 @@ Data returned in CayenneLPP format. See [CayenneLPP documentation](https://docs.
|-----------|-----------|
| Identity / Signing / Verification | Ed25519 |
| Key Exchange | X25519 (ECDH) |
| Encryption | AES-128 block encryption with zero padding + HMAC-SHA256 (MAC truncated to 2 bytes) |
| Encryption | AES-128-CBC + HMAC-SHA256 (MAC truncated to 2 bytes) |
| Hashing | SHA-256 |
## Notes
@@ -279,4 +279,4 @@ Data returned in CayenneLPP format. See [CayenneLPP documentation](https://docs.
- SNR values in RxMeta are multiplied by 4 for 0.25 dB precision
- TxDone is sent as a SetHardware event after each transmission
- Standard KISS clients receive only type 0x00 data frames and can safely ignore all SetHardware (0x06) frames
- See [packet_format.md](./packet_format.md) for packet format
- See [packet_structure.md](./packet_structure.md) for packet format

View File

@@ -42,7 +42,7 @@ Shutdown reason codes (stored in GPREGRET2):
| RAK WisMesh Tag | No | No | No |
| Heltec Mesh Solar | No | No | No |
| LilyGo T-Echo / T-Echo Lite | No | No | No |
| SenseCAP Solar | Yes | Yes | Yes |
| SenseCAP Solar | No | No | No |
| WIO Tracker L1 / L1 E-Ink | No | No | No |
| WIO WM1110 | No | No | No |
| Mesh Pocket | No | No | No |

View File

@@ -90,17 +90,23 @@ Returned path messages provide a description of the route a packet took from the
## Request
| Field | Size (bytes) | Description |
|--------------|-----------------|------------------------------------------|
| timestamp | 4 | sender time (unix timestamp) |
| request data | rest of payload | application-defined request payload body |
| Field | Size (bytes) | Description |
|--------------|-----------------|----------------------------|
| timestamp | 4 | send time (unix timestamp) |
| request type | 1 | see below |
| request data | rest of payload | depends on request type |
For the common chat/server helpers in `BaseChatMesh`, the current request type values are:
Request type
| Value | Name | Description |
|--------|----------------------|---------------------------------------|
| `0x01` | get stats | get stats of repeater or room server |
| `0x02` | keepalive | keep-alive request used for maintained connections |
| `0x02` | keepalive | (deprecated) |
| `0x03` | get telemetry data | TODO |
| `0x04` | get min,max,avg data | sensor nodes - get min, max, average for given time span |
| `0x05` | get access list | get node's approved access list |
| `0x06` | get neighbors | get repeater node's neighbors |
| `0x07` | get owner info | get repeater firmware-ver/name/owner info |
### Get stats
@@ -127,36 +133,35 @@ Gets information about the node, possibly including the following:
### Get telemetry data
Not defined in `BaseChatMesh`. Sensor- and application-specific request payloads may be implemented by higher-level firmware.
Request data about sensors on the node, including battery level.
### Get Telemetry
Not defined in `BaseChatMesh`.
TODO
### Get Min/Max/Ave (Sensor nodes)
Not defined in `BaseChatMesh`.
TODO
### Get Access List
Not defined in `BaseChatMesh`.
TODO
### Get Neighors
Not defined in `BaseChatMesh`.
TODO
### Get Owner Info
Not defined in `BaseChatMesh`.
TODO
## Response
| Field | Size (bytes) | Description |
|---------|-----------------|-------------|
| content | rest of payload | application-defined response body |
Response contents are opaque application data. There is no single generic response envelope beyond the encrypted payload wrapper shown above.
| tag | 4 | TODO |
| content | rest of payload | TODO |
## Plain text message

View File

@@ -230,7 +230,6 @@ void DataStore::loadPrefsInt(const char *filename, NodePrefs& _prefs, double& no
file.read((uint8_t *)&_prefs.gps_interval, sizeof(_prefs.gps_interval)); // 86
file.read((uint8_t *)&_prefs.autoadd_config, sizeof(_prefs.autoadd_config)); // 87
file.read((uint8_t *)&_prefs.autoadd_max_hops, sizeof(_prefs.autoadd_max_hops)); // 88
file.read((uint8_t *)&_prefs.rx_boosted_gain, sizeof(_prefs.rx_boosted_gain)); // 89
file.close();
}
@@ -267,8 +266,7 @@ void DataStore::savePrefs(const NodePrefs& _prefs, double node_lat, double node_
file.write((uint8_t *)&_prefs.gps_enabled, sizeof(_prefs.gps_enabled)); // 85
file.write((uint8_t *)&_prefs.gps_interval, sizeof(_prefs.gps_interval)); // 86
file.write((uint8_t *)&_prefs.autoadd_config, sizeof(_prefs.autoadd_config)); // 87
file.write((uint8_t *)&_prefs.autoadd_max_hops, sizeof(_prefs.autoadd_max_hops)); // 88
file.write((uint8_t *)&_prefs.rx_boosted_gain, sizeof(_prefs.rx_boosted_gain)); // 89
file.write((uint8_t *)&_prefs.autoadd_max_hops, sizeof(_prefs.autoadd_max_hops)); // 88
file.close();
}

View File

@@ -821,13 +821,6 @@ MyMesh::MyMesh(mesh::Radio &radio, mesh::RNG &rng, mesh::RTCClock &rtc, SimpleMe
_prefs.gps_enabled = 0; // GPS disabled by default
_prefs.gps_interval = 0; // No automatic GPS updates by default
//_prefs.rx_delay_base = 10.0f; enable once new algo fixed
#if defined(USE_SX1262) || defined(USE_SX1268)
#ifdef SX126X_RX_BOOSTED_GAIN
_prefs.rx_boosted_gain = SX126X_RX_BOOSTED_GAIN;
#else
_prefs.rx_boosted_gain = 1; // enabled by default
#endif
#endif
}
void MyMesh::begin(bool has_display) {
@@ -894,9 +887,6 @@ void MyMesh::begin(bool has_display) {
radio_set_params(_prefs.freq, _prefs.bw, _prefs.sf, _prefs.cr);
radio_set_tx_power(_prefs.tx_power_dbm);
radio_driver.setRxBoostedGainMode(_prefs.rx_boosted_gain);
MESH_DEBUG_PRINTLN("RX Boosted Gain Mode: %s",
radio_driver.getRxBoostedGainMode() ? "Enabled" : "Disabled");
}
const char *MyMesh::getNodeName() {
@@ -1726,7 +1716,7 @@ void MyMesh::handleCmdFrame(size_t len) {
out_frame[i++] = STATS_TYPE_CORE;
uint16_t battery_mv = board.getBattMilliVolts();
uint32_t uptime_secs = _ms->getMillis() / 1000;
uint8_t queue_len = (uint8_t)_mgr->getOutboundTotal();
uint8_t queue_len = (uint8_t)_mgr->getOutboundCount(0xFFFFFFFF);
memcpy(&out_frame[i], &battery_mv, 2); i += 2;
memcpy(&out_frame[i], &uptime_secs, 4); i += 4;
memcpy(&out_frame[i], &_err_flags, 2); i += 2;

View File

@@ -28,7 +28,6 @@ struct NodePrefs { // persisted to file
uint8_t gps_enabled; // GPS enabled flag (0=disabled, 1=enabled)
uint32_t gps_interval; // GPS read interval in seconds
uint8_t autoadd_config; // bitmask for auto-add contacts config
uint8_t rx_boosted_gain; // SX126x RX boosted gain mode (0=power saving, 1=boosted)
uint8_t client_repeat;
uint8_t path_hash_mode; // which path mode to use when sending
uint8_t autoadd_max_hops; // 0 = no limit, 1 = direct (0 hops), N = up to N-1 hops (max 64)

View File

@@ -219,7 +219,7 @@ int MyMesh::handleRequest(ClientInfo *sender, uint32_t sender_timestamp, uint8_t
if (payload[0] == REQ_TYPE_GET_STATUS) { // guests can also access this now
RepeaterStats stats;
stats.batt_milli_volts = board.getBattMilliVolts();
stats.curr_tx_queue_len = _mgr->getOutboundTotal();
stats.curr_tx_queue_len = _mgr->getOutboundCount(0xFFFFFFFF);
stats.noise_floor = (int16_t)_radio->getNoiseFloor();
stats.last_rssi = (int16_t)radio_driver.getLastRSSI();
stats.n_packets_recv = radio_driver.getPacketsRecv();
@@ -902,14 +902,6 @@ MyMesh::MyMesh(mesh::MainBoard &board, mesh::Radio &radio, mesh::MillisecondCloc
_prefs.adc_multiplier = 0.0f; // 0.0f means use default board multiplier
#if defined(USE_SX1262) || defined(USE_SX1268)
#ifdef SX126X_RX_BOOSTED_GAIN
_prefs.rx_boosted_gain = SX126X_RX_BOOSTED_GAIN;
#else
_prefs.rx_boosted_gain = 1; // enabled by default;
#endif
#endif
pending_discover_tag = 0;
pending_discover_until = 0;
}
@@ -932,10 +924,6 @@ void MyMesh::begin(FILESYSTEM *fs) {
radio_set_params(_prefs.freq, _prefs.bw, _prefs.sf, _prefs.cr);
radio_set_tx_power(_prefs.tx_power_dbm);
radio_driver.setRxBoostedGainMode(_prefs.rx_boosted_gain);
MESH_DEBUG_PRINTLN("RX Boosted Gain Mode: %s",
radio_driver.getRxBoostedGainMode() ? "Enabled" : "Disabled");
updateAdvertTimer();
updateFloodAdvertTimer();
@@ -1018,12 +1006,6 @@ void MyMesh::setTxPower(int8_t power_dbm) {
radio_set_tx_power(power_dbm);
}
#if defined(USE_SX1262) || defined(USE_SX1268)
void MyMesh::setRxBoostedGain(bool enable) {
radio_driver.setRxBoostedGainMode(enable);
}
#endif
void MyMesh::formatNeighborsReply(char *reply) {
char *dp = reply;
@@ -1312,8 +1294,7 @@ void MyMesh::loop() {
if (next_flood_advert && millisHasNowPassed(next_flood_advert)) {
mesh::Packet *pkt = createSelfAdvert();
uint32_t delay_millis = 0;
if (pkt) sendFlood(pkt, delay_millis, _prefs.path_hash_mode + 1);
if (pkt) sendFlood(pkt);
updateFloodAdvertTimer(); // schedule next flood advert
updateAdvertTimer(); // also schedule local advert (so they don't overlap)
@@ -1353,5 +1334,5 @@ bool MyMesh::hasPendingWork() const {
#if defined(WITH_BRIDGE)
if (bridge.isRunning()) return true; // bridge needs WiFi radio, can't sleep
#endif
return _mgr->getOutboundTotal() > 0;
return _mgr->getOutboundCount(0xFFFFFFFF) > 0;
}

View File

@@ -239,8 +239,4 @@ public:
// To check if there is pending work
bool hasPendingWork() const;
#if defined(USE_SX1262) || defined(USE_SX1268)
void setRxBoostedGain(bool enable) override;
#endif
};

View File

@@ -23,11 +23,6 @@ static char command[160];
unsigned long lastActive = 0; // mark last active time
unsigned long nextSleepinSecs = 120; // next sleep in seconds. The first sleep (if enabled) is after 2 minutes from boot
#if defined(PIN_USER_BTN) && defined(_SEEED_SENSECAP_SOLAR_H_)
static unsigned long userBtnDownAt = 0;
#define USER_BTN_HOLD_OFF_MILLIS 1500
#endif
void setup() {
Serial.begin(115200);
delay(1000);
@@ -132,21 +127,6 @@ void loop() {
command[0] = 0; // reset command buffer
}
#if defined(PIN_USER_BTN) && defined(_SEEED_SENSECAP_SOLAR_H_)
// Hold the user button to power off the SenseCAP Solar repeater.
int btnState = digitalRead(PIN_USER_BTN);
if (btnState == LOW) {
if (userBtnDownAt == 0) {
userBtnDownAt = millis();
} else if ((unsigned long)(millis() - userBtnDownAt) >= USER_BTN_HOLD_OFF_MILLIS) {
Serial.println("Powering off...");
board.powerOff(); // does not return
}
} else {
userBtnDownAt = 0;
}
#endif
the_mesh.loop();
sensors.loop();
#ifdef DISPLAY_CLASS

View File

@@ -140,7 +140,7 @@ int MyMesh::handleRequest(ClientInfo *sender, uint32_t sender_timestamp, uint8_t
if (payload[0] == REQ_TYPE_GET_STATUS) {
ServerStats stats;
stats.batt_milli_volts = board.getBattMilliVolts();
stats.curr_tx_queue_len = _mgr->getOutboundTotal();
stats.curr_tx_queue_len = _mgr->getOutboundCount(0xFFFFFFFF);
stats.noise_floor = (int16_t)_radio->getNoiseFloor();
stats.last_rssi = (int16_t)radio_driver.getLastRSSI();
stats.n_packets_recv = radio_driver.getPacketsRecv();
@@ -172,12 +172,6 @@ int MyMesh::handleRequest(ClientInfo *sender, uint32_t sender_timestamp, uint8_t
}
sensors.querySensors(perm_mask, telemetry);
// This default temperature will be overridden by external sensors (if any)
float temperature = board.getMCUTemperature();
if(!isnan(temperature)) { // Supported boards with built-in temperature sensor. ESP32-C3 may return NAN
telemetry.addTemperature(TELEM_CHANNEL_SELF, temperature); // Built-in MCU Temperature
}
uint8_t tlen = telemetry.getSize();
memcpy(&reply_data[4], telemetry.getBuffer(), tlen);
return 4 + tlen; // reply_len
@@ -875,8 +869,7 @@ void MyMesh::loop() {
if (next_flood_advert && millisHasNowPassed(next_flood_advert)) {
mesh::Packet *pkt = createSelfAdvert();
uint32_t delay_millis = 0;
if (pkt) sendFlood(pkt, delay_millis, _prefs.path_hash_mode + 1);
if (pkt) sendFlood(pkt);
updateFloodAdvertTimer(); // schedule next flood advert
updateAdvertTimer(); // also schedule local advert (so they don't overlap)

View File

@@ -90,7 +90,6 @@ public:
virtual void queueOutbound(Packet* packet, uint8_t priority, uint32_t scheduled_for) = 0;
virtual Packet* getNextOutbound(uint32_t now) = 0; // by priority
virtual int getOutboundCount(uint32_t now) const = 0;
virtual int getOutboundTotal() const = 0;
virtual int getFreeCount() const = 0;
virtual Packet* getOutboundByIdx(int i) = 0;
virtual Packet* removeOutboundByIdx(int i) = 0;
@@ -141,7 +140,7 @@ protected:
{
outbound = NULL;
total_air_time = rx_air_time = 0;
next_tx_time = ms.getMillis();
next_tx_time = 0;
cad_busy_start = 0;
next_floor_calib_time = next_agc_reset_time = 0;
_err_flags = 0;

View File

@@ -4,10 +4,6 @@
#include "AdvertDataHelpers.h"
#include <RTClib.h>
#ifndef BRIDGE_MAX_BAUD
#define BRIDGE_MAX_BAUD 115200
#endif
// Believe it or not, this std C function is busted on some platforms!
static uint32_t _atoi(const char* sp) {
uint32_t n = 0;
@@ -55,12 +51,12 @@ void CommonCLI::loadPrefsInt(FILESYSTEM* fs, const char* filename) {
file.read((uint8_t *)&_prefs->tx_power_dbm, sizeof(_prefs->tx_power_dbm)); // 76
file.read((uint8_t *)&_prefs->disable_fwd, sizeof(_prefs->disable_fwd)); // 77
file.read((uint8_t *)&_prefs->advert_interval, sizeof(_prefs->advert_interval)); // 78
file.read((uint8_t *)&_prefs->rx_boosted_gain, sizeof(_prefs->rx_boosted_gain)); // 79
file.read((uint8_t *)pad, 1); // 79 was 'unused'
file.read((uint8_t *)&_prefs->rx_delay_base, sizeof(_prefs->rx_delay_base)); // 80
file.read((uint8_t *)&_prefs->tx_delay_factor, sizeof(_prefs->tx_delay_factor)); // 84
file.read((uint8_t *)&_prefs->guest_password[0], sizeof(_prefs->guest_password)); // 88
file.read((uint8_t *)&_prefs->direct_tx_delay_factor, sizeof(_prefs->direct_tx_delay_factor)); // 104
file.read(pad, 4); // 108 : 4 bytes unused
file.read(pad, 4); // 108
file.read((uint8_t *)&_prefs->sf, sizeof(_prefs->sf)); // 112
file.read((uint8_t *)&_prefs->cr, sizeof(_prefs->cr)); // 113
file.read((uint8_t *)&_prefs->allow_read_only, sizeof(_prefs->allow_read_only)); // 114
@@ -109,7 +105,7 @@ void CommonCLI::loadPrefsInt(FILESYSTEM* fs, const char* filename) {
_prefs->bridge_enabled = constrain(_prefs->bridge_enabled, 0, 1);
_prefs->bridge_delay = constrain(_prefs->bridge_delay, 0, 10000);
_prefs->bridge_pkt_src = constrain(_prefs->bridge_pkt_src, 0, 1);
_prefs->bridge_baud = constrain(_prefs->bridge_baud, 9600, BRIDGE_MAX_BAUD);
_prefs->bridge_baud = constrain(_prefs->bridge_baud, 9600, 115200);
_prefs->bridge_channel = constrain(_prefs->bridge_channel, 0, 14);
_prefs->powersaving_enabled = constrain(_prefs->powersaving_enabled, 0, 1);
@@ -117,9 +113,6 @@ void CommonCLI::loadPrefsInt(FILESYSTEM* fs, const char* filename) {
_prefs->gps_enabled = constrain(_prefs->gps_enabled, 0, 1);
_prefs->advert_loc_policy = constrain(_prefs->advert_loc_policy, 0, 2);
// sanitise settings
_prefs->rx_boosted_gain = constrain(_prefs->rx_boosted_gain, 0, 1); // boolean
_prefs->flood_advert_base = constrain(_prefs->flood_advert_base, 0, 1);
file.close();
@@ -149,12 +142,12 @@ void CommonCLI::savePrefs(FILESYSTEM* fs) {
file.write((uint8_t *)&_prefs->tx_power_dbm, sizeof(_prefs->tx_power_dbm)); // 76
file.write((uint8_t *)&_prefs->disable_fwd, sizeof(_prefs->disable_fwd)); // 77
file.write((uint8_t *)&_prefs->advert_interval, sizeof(_prefs->advert_interval)); // 78
file.write((uint8_t *)&_prefs->rx_boosted_gain, sizeof(_prefs->rx_boosted_gain)); // 79
file.write((uint8_t *)pad, 1); // 79 was 'unused'
file.write((uint8_t *)&_prefs->rx_delay_base, sizeof(_prefs->rx_delay_base)); // 80
file.write((uint8_t *)&_prefs->tx_delay_factor, sizeof(_prefs->tx_delay_factor)); // 84
file.write((uint8_t *)&_prefs->guest_password[0], sizeof(_prefs->guest_password)); // 88
file.write((uint8_t *)&_prefs->direct_tx_delay_factor, sizeof(_prefs->direct_tx_delay_factor)); // 104
file.write(pad, 4); // 108 : 4 byte unused
file.write(pad, 4); // 108
file.write((uint8_t *)&_prefs->sf, sizeof(_prefs->sf)); // 112
file.write((uint8_t *)&_prefs->cr, sizeof(_prefs->cr)); // 113
file.write((uint8_t *)&_prefs->allow_read_only, sizeof(_prefs->allow_read_only)); // 114
@@ -180,8 +173,8 @@ void CommonCLI::savePrefs(FILESYSTEM* fs) {
file.write((uint8_t *)&_prefs->advert_loc_policy, sizeof(_prefs->advert_loc_policy)); // 161
file.write((uint8_t *)&_prefs->discovery_mod_timestamp, sizeof(_prefs->discovery_mod_timestamp)); // 162
file.write((uint8_t *)&_prefs->adc_multiplier, sizeof(_prefs->adc_multiplier)); // 166
file.write((uint8_t *)_prefs->owner_info, sizeof(_prefs->owner_info)); // 170
file.write((uint8_t *)&_prefs->flood_advert_base, sizeof(_prefs->flood_advert_base)); // next: 290
file.write((uint8_t *)_prefs->owner_info, sizeof(_prefs->owner_info)); // 170
file.write((uint8_t *)&_prefs->flood_advert_base, sizeof(_prefs->flood_advert_base)); // 290
// 294
@@ -212,9 +205,7 @@ uint8_t CommonCLI::buildAdvertData(uint8_t node_type, uint8_t* app_data) {
}
void CommonCLI::handleCommand(uint32_t sender_timestamp, const char* command, char* reply) {
if (memcmp(command, "poweroff", 8) == 0 || memcmp(command, "shutdown", 8) == 0) {
_board->powerOff(); // doesn't return
} else if (memcmp(command, "reboot", 6) == 0) {
if (memcmp(command, "reboot", 6) == 0) {
_board->reboot(); // doesn't return
} else if (memcmp(command, "clkreboot", 9) == 0) {
// Reset clock
@@ -327,10 +318,6 @@ void CommonCLI::handleCommand(uint32_t sender_timestamp, const char* command, ch
sprintf(reply, "> %s", StrHelper::ftoa(_prefs->node_lat));
} else if (memcmp(config, "lon", 3) == 0) {
sprintf(reply, "> %s", StrHelper::ftoa(_prefs->node_lon));
#if defined(USE_SX1262) || defined(USE_SX1268)
} else if (memcmp(config, "radio.rxgain", 12) == 0) {
sprintf(reply, "> %s", _prefs->rx_boosted_gain ? "on" : "off");
#endif
} else if (memcmp(config, "radio", 5) == 0) {
char freq[16], bw[16];
strcpy(freq, StrHelper::ftoa(_prefs->freq));
@@ -526,13 +513,6 @@ void CommonCLI::handleCommand(uint32_t sender_timestamp, const char* command, ch
_prefs->disable_fwd = memcmp(&config[7], "off", 3) == 0;
savePrefs();
strcpy(reply, _prefs->disable_fwd ? "OK - repeat is now OFF" : "OK - repeat is now ON");
#if defined(USE_SX1262) || defined(USE_SX1268)
} else if (memcmp(config, "radio.rxgain ", 13) == 0) {
_prefs->rx_boosted_gain = memcmp(&config[13], "on", 2) == 0;
strcpy(reply, "OK");
savePrefs();
_callbacks->setRxBoostedGain(_prefs->rx_boosted_gain);
#endif
} else if (memcmp(config, "radio ", 6) == 0) {
strcpy(tmp, &config[6]);
const char *parts[4];
@@ -667,13 +647,13 @@ void CommonCLI::handleCommand(uint32_t sender_timestamp, const char* command, ch
#ifdef WITH_RS232_BRIDGE
} else if (memcmp(config, "bridge.baud ", 12) == 0) {
uint32_t baud = atoi(&config[12]);
if (baud >= 9600 && baud <= BRIDGE_MAX_BAUD) {
if (baud >= 9600 && baud <= 115200) {
_prefs->bridge_baud = (uint32_t)baud;
_callbacks->restartBridge();
savePrefs();
strcpy(reply, "OK");
} else {
sprintf(reply, "Error: baud rate must be between 9600-%d",BRIDGE_MAX_BAUD);
strcpy(reply, "Error: baud rate must be between 9600-115200");
}
#endif
#ifdef WITH_ESPNOW_BRIDGE

View File

@@ -58,7 +58,6 @@ struct NodePrefs { // persisted to file
uint32_t discovery_mod_timestamp;
float adc_multiplier;
char owner_info[120];
uint8_t rx_boosted_gain; // power settings
uint8_t path_hash_mode; // which path mode to use when sending
uint8_t loop_detect;
};
@@ -96,10 +95,6 @@ public:
virtual void restartBridge() {
// no op by default
};
virtual void setRxBoostedGain(bool enable) {
// no op by default
};
};
class CommonCLI {

View File

@@ -9,8 +9,6 @@ PacketQueue::PacketQueue(int max_entries) {
}
int PacketQueue::countBefore(uint32_t now) const {
if (now == 0xFFFFFFFF) return _num; // sentinel: count all entries regardless of schedule
int n = 0;
for (int j = 0; j < _num; j++) {
if ((int32_t)(_schedule_table[j] - now) > 0) continue; // scheduled for future... ignore for now
@@ -99,10 +97,6 @@ int StaticPoolPacketManager::getOutboundCount(uint32_t now) const {
return send_queue.countBefore(now);
}
int StaticPoolPacketManager::getOutboundTotal() const {
return send_queue.count();
}
int StaticPoolPacketManager::getFreeCount() const {
return unused.count();
}

View File

@@ -29,7 +29,6 @@ public:
void queueOutbound(mesh::Packet* packet, uint8_t priority, uint32_t scheduled_for) override;
mesh::Packet* getNextOutbound(uint32_t now) override;
int getOutboundCount(uint32_t now) const override;
int getOutboundTotal() const override;
int getFreeCount() const override;
mesh::Packet* getOutboundByIdx(int i) override;
mesh::Packet* removeOutboundByIdx(int i) override;

View File

@@ -14,7 +14,7 @@ public:
board.getBattMilliVolts(),
ms.getMillis() / 1000,
err_flags,
mgr->getOutboundTotal()
mgr->getOutboundCount(0xFFFFFFFF)
);
}

View File

@@ -246,7 +246,6 @@ void SerialBLEInterface::enable() {
clearBuffers();
_last_health_check = millis();
Bluefruit.Advertising.restartOnDisconnect(true);
Bluefruit.Advertising.start(0);
}
@@ -260,9 +259,8 @@ void SerialBLEInterface::disable() {
_isEnabled = false;
BLE_DEBUG_PRINTLN("SerialBLEInterface: disable");
Bluefruit.Advertising.restartOnDisconnect(false);
Bluefruit.Advertising.stop();
disconnect();
Bluefruit.Advertising.stop();
_last_health_check = 0;
}

View File

@@ -45,7 +45,8 @@ class CustomLLCC68 : public LLCC68 {
int status = begin(LORA_FREQ, LORA_BW, LORA_SF, cr, RADIOLIB_SX126X_SYNC_WORD_PRIVATE, LORA_TX_POWER, 16, tcxo);
// if radio init fails with -707/-706, try again with tcxo voltage set to 0.0f
if (status == RADIOLIB_ERR_SPI_CMD_FAILED || status == RADIOLIB_ERR_SPI_CMD_INVALID) {
tcxo = 0.0f;
#define SX126X_DIO3_TCXO_VOLTAGE (0.0f);
tcxo = SX126X_DIO3_TCXO_VOLTAGE;
status = begin(LORA_FREQ, LORA_BW, LORA_SF, cr, RADIOLIB_SX126X_SYNC_WORD_PRIVATE, LORA_TX_POWER, 16, tcxo);
}
if (status != RADIOLIB_ERR_NONE) {
@@ -83,10 +84,4 @@ class CustomLLCC68 : public LLCC68 {
bool detected = (irq & SX126X_IRQ_HEADER_VALID) || (irq & SX126X_IRQ_PREAMBLE_DETECTED);
return detected;
}
bool getRxBoostedGainMode() {
uint8_t rxGain = 0;
readRegister(RADIOLIB_SX126X_REG_RX_GAIN, &rxGain, 1);
return (rxGain == RADIOLIB_SX126X_RX_GAIN_BOOSTED);
}
};

View File

@@ -22,11 +22,4 @@ public:
}
void doResetAGC() override { sx126xResetAGC((SX126x *)_radio); }
void setRxBoostedGainMode(bool en) override {
((CustomLLCC68 *)_radio)->setRxBoostedGainMode(en);
}
bool getRxBoostedGainMode() const override {
return ((CustomLLCC68 *)_radio)->getRxBoostedGainMode();
}
};

View File

@@ -4,8 +4,6 @@
#include "MeshCore.h"
class CustomLR1110 : public LR1110 {
bool _rx_boosted = false;
public:
CustomLR1110(Module *mod) : LR1110(mod) { }
@@ -24,13 +22,6 @@ class CustomLR1110 : public LR1110 {
float getFreqMHz() const { return freqMHz; }
int16_t setRxBoostedGainMode(bool en) {
_rx_boosted = en;
return LR1110::setRxBoostedGainMode(en);
}
bool getRxBoostedGainMode() const { return _rx_boosted; }
bool isReceiving() {
uint16_t irq = getIrqStatus();
bool detected = ((irq & RADIOLIB_LR11X0_IRQ_SYNC_WORD_HEADER_VALID) || (irq & RADIOLIB_LR11X0_IRQ_PREAMBLE_DETECTED));

View File

@@ -24,11 +24,5 @@ public:
float getLastRSSI() const override { return ((CustomLR1110 *)_radio)->getRSSI(); }
float getLastSNR() const override { return ((CustomLR1110 *)_radio)->getSNR(); }
void setRxBoostedGainMode(bool en) override {
((CustomLR1110 *)_radio)->setRxBoostedGainMode(en);
}
bool getRxBoostedGainMode() const override {
return ((CustomLR1110 *)_radio)->getRxBoostedGainMode();
}
int16_t setRxBoostedGainMode(bool en) { return ((CustomLR1110 *)_radio)->setRxBoostedGainMode(en); };
};

View File

@@ -2,7 +2,7 @@
#include <RadioLib.h>
#define SX126X_IRQ_HEADER_VALID 0b0000010000 // 4 4 valid LoRa header received
#define SX126X_IRQ_HEADER_VALID 0b0000010000 // 4 4 valid LoRa header received
#define SX126X_IRQ_PREAMBLE_DETECTED 0x04
class CustomSX1262 : public SX1262 {
@@ -45,7 +45,8 @@ class CustomSX1262 : public SX1262 {
int status = begin(LORA_FREQ, LORA_BW, LORA_SF, cr, RADIOLIB_SX126X_SYNC_WORD_PRIVATE, LORA_TX_POWER, 16, tcxo);
// if radio init fails with -707/-706, try again with tcxo voltage set to 0.0f
if (status == RADIOLIB_ERR_SPI_CMD_FAILED || status == RADIOLIB_ERR_SPI_CMD_INVALID) {
tcxo = 0.0f;
#define SX126X_DIO3_TCXO_VOLTAGE (0.0f);
tcxo = SX126X_DIO3_TCXO_VOLTAGE;
status = begin(LORA_FREQ, LORA_BW, LORA_SF, cr, RADIOLIB_SX126X_SYNC_WORD_PRIVATE, LORA_TX_POWER, 16, tcxo);
}
if (status != RADIOLIB_ERR_NONE) {
@@ -91,10 +92,4 @@ class CustomSX1262 : public SX1262 {
bool detected = (irq & SX126X_IRQ_HEADER_VALID) || (irq & SX126X_IRQ_PREAMBLE_DETECTED);
return detected;
}
bool getRxBoostedGainMode() {
uint8_t rxGain = 0;
readRegister(RADIOLIB_SX126X_REG_RX_GAIN, &rxGain, 1);
return (rxGain == RADIOLIB_SX126X_RX_GAIN_BOOSTED);
}
};

View File

@@ -4,10 +4,6 @@
#include "RadioLibWrappers.h"
#include "SX126xReset.h"
#ifndef USE_SX1262
#define USE_SX1262
#endif
class CustomSX1262Wrapper : public RadioLibWrapper {
public:
CustomSX1262Wrapper(CustomSX1262& radio, mesh::MainBoard& board) : RadioLibWrapper(radio, board) { }
@@ -29,11 +25,4 @@ public:
}
void doResetAGC() override { sx126xResetAGC((SX126x *)_radio); }
void setRxBoostedGainMode(bool en) override {
((CustomSX1262 *)_radio)->setRxBoostedGainMode(en);
}
bool getRxBoostedGainMode() const override {
return ((CustomSX1262 *)_radio)->getRxBoostedGainMode();
}
};

View File

@@ -2,7 +2,7 @@
#include <RadioLib.h>
#define SX126X_IRQ_HEADER_VALID 0b0000010000 // 4 4 valid LoRa header received
#define SX126X_IRQ_HEADER_VALID 0b0000010000 // 4 4 valid LoRa header received
#define SX126X_IRQ_PREAMBLE_DETECTED 0x04
class CustomSX1268 : public SX1268 {
@@ -45,7 +45,8 @@ class CustomSX1268 : public SX1268 {
int status = begin(LORA_FREQ, LORA_BW, LORA_SF, cr, RADIOLIB_SX126X_SYNC_WORD_PRIVATE, LORA_TX_POWER, 16, tcxo);
// if radio init fails with -707/-706, try again with tcxo voltage set to 0.0f
if (status == RADIOLIB_ERR_SPI_CMD_FAILED || status == RADIOLIB_ERR_SPI_CMD_INVALID) {
tcxo = 0.0f;
#define SX126X_DIO3_TCXO_VOLTAGE (0.0f);
tcxo = SX126X_DIO3_TCXO_VOLTAGE;
status = begin(LORA_FREQ, LORA_BW, LORA_SF, cr, RADIOLIB_SX126X_SYNC_WORD_PRIVATE, LORA_TX_POWER, 16, tcxo);
}
if (status != RADIOLIB_ERR_NONE) {
@@ -83,10 +84,4 @@ class CustomSX1268 : public SX1268 {
bool detected = (irq & SX126X_IRQ_HEADER_VALID) || (irq & SX126X_IRQ_PREAMBLE_DETECTED);
return detected;
}
bool getRxBoostedGainMode() {
uint8_t rxGain = 0;
readRegister(RADIOLIB_SX126X_REG_RX_GAIN, &rxGain, 1);
return (rxGain == RADIOLIB_SX126X_RX_GAIN_BOOSTED);
}
};

View File

@@ -4,10 +4,6 @@
#include "RadioLibWrappers.h"
#include "SX126xReset.h"
#ifndef USE_SX1268
#define USE_SX1268
#endif
class CustomSX1268Wrapper : public RadioLibWrapper {
public:
CustomSX1268Wrapper(CustomSX1268& radio, mesh::MainBoard& board) : RadioLibWrapper(radio, board) { }
@@ -26,11 +22,4 @@ public:
}
void doResetAGC() override { sx126xResetAGC((SX126x *)_radio); }
void setRxBoostedGainMode(bool en) override {
((CustomSX1268 *)_radio)->setRxBoostedGainMode(en);
}
bool getRxBoostedGainMode() const override {
return ((CustomSX1268 *)_radio)->getRxBoostedGainMode();
}
};

View File

@@ -3,10 +3,6 @@
#include "CustomSX1276.h"
#include "RadioLibWrappers.h"
#ifndef USE_SX1276
#define USE_SX1276
#endif
class CustomSX1276Wrapper : public RadioLibWrapper {
public:
CustomSX1276Wrapper(CustomSX1276& radio, mesh::MainBoard& board) : RadioLibWrapper(radio, board) { }

View File

@@ -54,9 +54,6 @@ public:
virtual float getLastSNR() const override;
float packetScore(float snr, int packet_len) override { return packetScoreInt(snr, 10, packet_len); } // assume sf=10
virtual void setRxBoostedGainMode(bool) { }
virtual bool getRxBoostedGainMode() const { return false; }
};
/**

View File

@@ -39,13 +39,10 @@ class MicroNMEALocationProvider : public LocationProvider {
mesh::RTCClock* _clock;
Stream* _gps_serial;
RefCountedDigitalPin* _peripher_power;
int8_t _claims = 0;
int _pin_reset;
int _pin_en;
long next_check = 0;
long time_valid = 0;
unsigned long _last_time_sync = 0;
static const unsigned long TIME_SYNC_INTERVAL = 1800000; // Re-sync every 30 minutes
public :
MicroNMEALocationProvider(Stream& ser, mesh::RTCClock* clock = NULL, int pin_reset = GPS_RESET, int pin_en = GPS_EN,RefCountedDigitalPin* peripher_power=NULL) :
@@ -60,21 +57,8 @@ public :
}
}
void claim() {
_claims++;
if (_claims > 0) {
if (_peripher_power) _peripher_power->claim();
}
}
void release() {
if (_claims == 0) return; // avoid negative _claims
_claims--;
if (_peripher_power) _peripher_power->release();
}
void begin() override {
claim();
if (_peripher_power) _peripher_power->claim();
if (_pin_en != -1) {
digitalWrite(_pin_en, PIN_GPS_EN_ACTIVE);
}
@@ -98,7 +82,7 @@ public :
if (_pin_reset != -1) {
digitalWrite(_pin_reset, GPS_RESET_FORCE);
}
release();
if (_peripher_power) _peripher_power->release();
}
bool isEnabled() override {
@@ -145,15 +129,10 @@ public :
if (millis() > next_check) {
next_check = millis() + 1000;
// Re-enable time sync periodically when GPS has valid fix
if (!_time_sync_needed && _clock != NULL && (millis() - _last_time_sync) > TIME_SYNC_INTERVAL) {
_time_sync_needed = true;
}
if (_time_sync_needed && time_valid > 2) {
if (_clock != NULL) {
_clock->setCurrentTime(getTimestamp());
_time_sync_needed = false;
_last_time_sync = millis();
}
}
if (isValid()) {

View File

@@ -59,58 +59,44 @@ bool E213Display::begin() {
}
void E213Display::powerOn() {
if (_periph_power) {
_periph_power->claim();
} else {
#ifdef PIN_VEXT_EN
pinMode(PIN_VEXT_EN, OUTPUT);
pinMode(PIN_VEXT_EN, OUTPUT);
#ifdef PIN_VEXT_EN_ACTIVE
digitalWrite(PIN_VEXT_EN, PIN_VEXT_EN_ACTIVE);
digitalWrite(PIN_VEXT_EN, PIN_VEXT_EN_ACTIVE);
#else
digitalWrite(PIN_VEXT_EN, LOW); // Active low
digitalWrite(PIN_VEXT_EN, LOW); // Active low
#endif
#endif
}
delay(50); // Allow power to stabilize
#endif
}
void E213Display::powerOff() {
if (_periph_power) {
_periph_power->release();
} else {
#ifdef PIN_VEXT_EN
#ifdef PIN_VEXT_EN_ACTIVE
digitalWrite(PIN_VEXT_EN, !PIN_VEXT_EN_ACTIVE);
digitalWrite(PIN_VEXT_EN, !PIN_VEXT_EN_ACTIVE);
#else
digitalWrite(PIN_VEXT_EN, HIGH); // Turn off power
digitalWrite(PIN_VEXT_EN, HIGH); // Turn off power
#endif
#endif
}
}
void E213Display::turnOn() {
if (!_init) begin();
else if (!_isOn) {
powerOn();
display->fastmodeOn(); // Reinitialize display controller after power was cut
}
powerOn();
_isOn = true;
}
void E213Display::turnOff() {
if (_isOn) {
powerOff();
_isOn = false;
}
powerOff();
_isOn = false;
}
void E213Display::clear() {
display->clear();
}
void E213Display::startFrame(Color bkg) {
display_crc.reset();
// Fill screen with white first to ensure clean background
display->fillRect(0, 0, width(), height(), WHITE);
@@ -121,50 +107,31 @@ void E213Display::startFrame(Color bkg) {
}
void E213Display::setTextSize(int sz) {
display_crc.update<int>(sz);
// The library handles text size internally
display->setTextSize(sz);
}
void E213Display::setColor(Color c) {
display_crc.update<Color>(c);
// implemented in individual display methods
}
void E213Display::setCursor(int x, int y) {
display_crc.update<int>(x);
display_crc.update<int>(y);
display->setCursor(x, y);
}
void E213Display::print(const char *str) {
display_crc.update<char>(str, strlen(str));
display->print(str);
}
void E213Display::fillRect(int x, int y, int w, int h) {
display_crc.update<int>(x);
display_crc.update<int>(y);
display_crc.update<int>(w);
display_crc.update<int>(h);
display->fillRect(x, y, w, h, BLACK);
}
void E213Display::drawRect(int x, int y, int w, int h) {
display_crc.update<int>(x);
display_crc.update<int>(y);
display_crc.update<int>(w);
display_crc.update<int>(h);
display->drawRect(x, y, w, h, BLACK);
}
void E213Display::drawXbm(int x, int y, const uint8_t *bits, int w, int h) {
display_crc.update<int>(x);
display_crc.update<int>(y);
display_crc.update<int>(w);
display_crc.update<int>(h);
display_crc.update<uint8_t>(bits, w * h / 8);
// Width in bytes for bitmap processing
uint16_t widthInBytes = (w + 7) / 8;
@@ -193,9 +160,5 @@ uint16_t E213Display::getTextWidth(const char *str) {
}
void E213Display::endFrame() {
uint32_t crc = display_crc.finalize();
if (crc != last_display_crc_value) {
display->update();
last_display_crc_value = crc;
}
}

View File

@@ -5,20 +5,15 @@
#include <SPI.h>
#include <Wire.h>
#include <heltec-eink-modules.h>
#include <CRC32.h>
#include <helpers/RefCountedDigitalPin.h>
// Display driver for E213 e-ink display
class E213Display : public DisplayDriver {
BaseDisplay* display=NULL;
bool _init = false;
bool _isOn = false;
RefCountedDigitalPin* _periph_power;
CRC32 display_crc;
uint32_t last_display_crc_value = 0;
public:
E213Display(RefCountedDigitalPin* periph_power = NULL) : DisplayDriver(250, 122), _periph_power(periph_power) {}
E213Display() : DisplayDriver(250, 122) {}
~E213Display(){
if(display!=NULL) {
delete display;
@@ -44,4 +39,4 @@ private:
BaseDisplay* detectEInk();
void powerOn();
void powerOff();
};
};

View File

@@ -21,41 +21,28 @@ bool E290Display::begin() {
}
void E290Display::powerOn() {
if (_periph_power) {
_periph_power->claim();
} else {
#ifdef PIN_VEXT_EN
pinMode(PIN_VEXT_EN, OUTPUT);
digitalWrite(PIN_VEXT_EN, PIN_VEXT_EN_ACTIVE);
#endif
}
pinMode(PIN_VEXT_EN, OUTPUT);
digitalWrite(PIN_VEXT_EN, PIN_VEXT_EN_ACTIVE);
delay(50); // Allow power to stabilize
#endif
}
void E290Display::powerOff() {
if (_periph_power) {
_periph_power->release();
} else {
#ifdef PIN_VEXT_EN
digitalWrite(PIN_VEXT_EN, !PIN_VEXT_EN_ACTIVE); // Turn off power
digitalWrite(PIN_VEXT_EN, !PIN_VEXT_EN_ACTIVE); // Turn off power
#endif
}
}
void E290Display::turnOn() {
if (!_init) begin();
else if (!_isOn) {
powerOn();
display.fastmodeOn(); // Reinitialize display controller after power was cut
}
powerOn();
_isOn = true;
}
void E290Display::turnOff() {
if (_isOn) {
powerOff();
_isOn = false;
}
powerOff();
_isOn = false;
}
void E290Display::clear() {
@@ -63,8 +50,6 @@ void E290Display::clear() {
}
void E290Display::startFrame(Color bkg) {
display_crc.reset();
// Fill screen with white first to ensure clean background
display.fillRect(0, 0, width(), height(), WHITE);
if (bkg == LIGHT) {
@@ -74,50 +59,31 @@ void E290Display::startFrame(Color bkg) {
}
void E290Display::setTextSize(int sz) {
display_crc.update<int>(sz);
// The library handles text size internally
display.setTextSize(sz);
}
void E290Display::setColor(Color c) {
display_crc.update<Color>(c);
// implemented in individual display methods
}
void E290Display::setCursor(int x, int y) {
display_crc.update<int>(x);
display_crc.update<int>(y);
display.setCursor(x, y);
}
void E290Display::print(const char *str) {
display_crc.update<char>(str, strlen(str));
display.print(str);
}
void E290Display::fillRect(int x, int y, int w, int h) {
display_crc.update<int>(x);
display_crc.update<int>(y);
display_crc.update<int>(w);
display_crc.update<int>(h);
display.fillRect(x, y, w, h, BLACK);
}
void E290Display::drawRect(int x, int y, int w, int h) {
display_crc.update<int>(x);
display_crc.update<int>(y);
display_crc.update<int>(w);
display_crc.update<int>(h);
display.drawRect(x, y, w, h, BLACK);
}
void E290Display::drawXbm(int x, int y, const uint8_t *bits, int w, int h) {
display_crc.update<int>(x);
display_crc.update<int>(y);
display_crc.update<int>(w);
display_crc.update<int>(h);
display_crc.update<uint8_t>(bits, w * h / 8);
// Width in bytes for bitmap processing
uint16_t widthInBytes = (w + 7) / 8;
@@ -146,9 +112,5 @@ uint16_t E290Display::getTextWidth(const char *str) {
}
void E290Display::endFrame() {
uint32_t crc = display_crc.finalize();
if (crc != last_display_crc_value) {
display.update();
last_display_crc_value = crc;
}
display.update();
}

View File

@@ -5,20 +5,15 @@
#include <SPI.h>
#include <Wire.h>
#include <heltec-eink-modules.h>
#include <CRC32.h>
#include <helpers/RefCountedDigitalPin.h>
// Display driver for E290 e-ink display
class E290Display : public DisplayDriver {
EInkDisplay_VisionMasterE290 display;
bool _init = false;
bool _isOn = false;
RefCountedDigitalPin* _periph_power;
CRC32 display_crc;
uint32_t last_display_crc_value = 0;
public:
E290Display(RefCountedDigitalPin* periph_power = NULL) : DisplayDriver(296, 128), _periph_power(periph_power) {}
E290Display() : DisplayDriver(296, 128) {}
bool begin();
bool isOn() override { return _isOn; }
@@ -39,4 +34,4 @@ public:
private:
void powerOn();
void powerOff();
};
};

View File

@@ -30,7 +30,6 @@ build_flags =
-D SX126X_DIO2_AS_RF_SWITCH=true
-D SX126X_DIO3_TCXO_VOLTAGE=1.8
-D SX126X_CURRENT_LIMIT=140
-D USE_SX1262
-D RADIO_CLASS=CustomSX1262
-D WRAPPER_CLASS=CustomSX1262Wrapper
-D LORA_TX_POWER=22

View File

@@ -1,57 +0,0 @@
#include <Arduino.h>
#include <Wire.h>
#include "GAT56230SMeshKitBoard.h"
#ifdef NRF52_POWER_MANAGEMENT
// Static configuration for power management
// Values set in variant.h defines
const PowerMgtConfig power_config = {
.lpcomp_ain_channel = PWRMGT_LPCOMP_AIN,
.lpcomp_refsel = PWRMGT_LPCOMP_REFSEL,
.voltage_bootlock = PWRMGT_VOLTAGE_BOOTLOCK
};
void GAT56230SMeshKitBoard::initiateShutdown(uint8_t reason) {
// Disable LoRa module power before shutdown
digitalWrite(SX126X_POWER_EN, LOW);
if (reason == SHUTDOWN_REASON_LOW_VOLTAGE ||
reason == SHUTDOWN_REASON_BOOT_PROTECT) {
configureVoltageWake(power_config.lpcomp_ain_channel, power_config.lpcomp_refsel);
}
enterSystemOff(reason);
}
#endif // NRF52_POWER_MANAGEMENT
void GAT56230SMeshKitBoard::begin() {
NRF52BoardDCDC::begin();
pinMode(PIN_VBAT_READ, INPUT);
// Set all button pins to INPUT_PULLUP
pinMode(PIN_BUTTON1, INPUT_PULLUP);
pinMode(PIN_BUTTON2, INPUT_PULLUP);
pinMode(PIN_BUTTON3, INPUT_PULLUP);
pinMode(PIN_BUTTON4, INPUT_PULLUP);
pinMode(PIN_BUTTON5, INPUT_PULLUP);
pinMode(PIN_BUTTON6, INPUT_PULLUP);
#if defined(PIN_BOARD_SDA) && defined(PIN_BOARD_SCL)
Wire.setPins(PIN_BOARD_SDA, PIN_BOARD_SCL);
#endif
Wire.begin();
pinMode(SX126X_POWER_EN, OUTPUT);
#ifdef NRF52_POWER_MANAGEMENT
// Boot voltage protection check (may not return if voltage too low)
// We need to call this after we configure SX126X_POWER_EN as output but before we pull high
checkBootVoltage(&power_config);
#endif
digitalWrite(SX126X_POWER_EN, HIGH);
delay(10); // give sx1262 some time to power up
}

View File

@@ -1,53 +0,0 @@
#pragma once
#include <MeshCore.h>
#include <Arduino.h>
#include <helpers/NRF52Board.h>
class GAT56230SMeshKitBoard : public NRF52BoardDCDC {
protected:
#ifdef NRF52_POWER_MANAGEMENT
void initiateShutdown(uint8_t reason) override;
#endif
public:
GAT56230SMeshKitBoard() : NRF52Board("GAT562_OTA") {}
void begin();
#define BATTERY_SAMPLES 8
uint16_t getBattMilliVolts() override {
analogReadResolution(12);
uint32_t raw = 0;
for (int i = 0; i < BATTERY_SAMPLES; i++) {
raw += analogRead(PIN_VBAT_READ);
}
raw = raw / BATTERY_SAMPLES;
return (ADC_MULTIPLIER * raw) / 4096;
}
const char* getManufacturerName() const override {
return "GAT562 30S Mesh Kit";
}
#if defined(P_LORA_TX_LED)
void onBeforeTransmit() override {
digitalWrite(P_LORA_TX_LED, HIGH); // turn TX LED on
}
void onAfterTransmit() override {
digitalWrite(P_LORA_TX_LED, LOW); // turn TX LED off
}
#endif
void powerOff() override {
uint32_t button_pin = PIN_BUTTON1;
nrf_gpio_cfg_input(button_pin, NRF_GPIO_PIN_PULLUP);
nrf_gpio_cfg_sense_set(button_pin, NRF_GPIO_PIN_SENSE_LOW);
sd_power_system_off();
}
};

View File

@@ -1,114 +0,0 @@
[GAT562_30S_Mesh_Kit]
extends = nrf52_base
board = rak4631
board_check = true
build_flags = ${nrf52_base.build_flags}
${sensor_base.build_flags}
-I variants/gat562_30s_mesh_kit
-D RAK_4631
-D RAK_BOARD
-D NRF52_POWER_MANAGEMENT
-D PIN_BOARD_SCL=14
-D PIN_BOARD_SDA=13
-D PIN_OLED_RESET=-1
-D UI_HAS_JOYSTICK=1
-D RADIO_CLASS=CustomSX1262
-D WRAPPER_CLASS=CustomSX1262Wrapper
-D LORA_TX_POWER=22
-D SX126X_CURRENT_LIMIT=140
-D PIN_BUZZER=33
-D SX126X_RX_BOOSTED_GAIN=1
-D SX126X_DIO2_AS_RF_SWITCH=true
build_src_filter = ${nrf52_base.build_src_filter}
+<../variants/gat562_30s_mesh_kit>
+<helpers/ui/SSD1306Display.cpp>
+<helpers/ui/MomentaryButton.cpp>
+<helpers/sensors>
lib_deps =
${nrf52_base.lib_deps}
${sensor_base.lib_deps}
adafruit/Adafruit SSD1306 @ ^2.5.13
sparkfun/SparkFun u-blox GNSS Arduino Library@^2.2.27
[env:GAT562_30S_Mesh_Kit_repeater]
extends = GAT562_30S_Mesh_Kit
build_flags =
${GAT562_30S_Mesh_Kit.build_flags}
-D DISPLAY_CLASS=SSD1306Display
-D ADVERT_NAME='"GAT562 Repeater"'
-D ADVERT_LAT=0.0
-D ADVERT_LON=0.0
-D ADMIN_PASSWORD='"password"'
-D MAX_NEIGHBOURS=50
; -D MESH_PACKET_LOGGING=1
; -D MESH_DEBUG=1
build_src_filter = ${GAT562_30S_Mesh_Kit.build_src_filter}
+<helpers/ui/SSD1306Display.cpp>
+<../examples/simple_repeater>
[env:GAT562_30S_Mesh_Kit_room_server]
extends = GAT562_30S_Mesh_Kit
build_flags =
${GAT562_30S_Mesh_Kit.build_flags}
-D DISPLAY_CLASS=SSD1306Display
-D ADVERT_NAME='"GAT562 Room"'
-D ADVERT_LAT=0.0
-D ADVERT_LON=0.0
-D ADMIN_PASSWORD='"password"'
-D ROOM_PASSWORD='"hello"'
; -D MESH_PACKET_LOGGING=1
; -D MESH_DEBUG=1
build_src_filter = ${GAT562_30S_Mesh_Kit.build_src_filter}
+<helpers/ui/SSD1306Display.cpp>
+<../examples/simple_room_server>
[env:GAT562_30S_Mesh_Kit_companion_radio_usb]
extends = GAT562_30S_Mesh_Kit
board_build.ldscript = boards/nrf52840_s140_v6_extrafs.ld
board_upload.maximum_size = 712704
build_flags =
${GAT562_30S_Mesh_Kit.build_flags}
-I examples/companion_radio/ui-new
-D DISPLAY_CLASS=SSD1306Display
-D MAX_CONTACTS=350
-D MAX_GROUP_CHANNELS=40
; NOTE: DO NOT ENABLE --> -D MESH_PACKET_LOGGING=1
; NOTE: DO NOT ENABLE --> -D MESH_DEBUG=1
build_src_filter = ${GAT562_30S_Mesh_Kit.build_src_filter}
+<../examples/companion_radio/*.cpp>
+<../examples/companion_radio/ui-new/*.cpp>
+<helpers/ui/buzzer.cpp>
lib_deps =
${GAT562_30S_Mesh_Kit.lib_deps}
densaugeo/base64 @ ~1.4.0
end2endzone/NonBlockingRTTTL@^1.3.0
[env:GAT562_30S_Mesh_Kit_companion_radio_ble]
extends = GAT562_30S_Mesh_Kit
board_build.ldscript = boards/nrf52840_s140_v6_extrafs.ld
board_upload.maximum_size = 712704
build_flags =
${GAT562_30S_Mesh_Kit.build_flags}
-I examples/companion_radio/ui-new
-D DISPLAY_CLASS=SSD1306Display
-D MAX_CONTACTS=350
-D MAX_GROUP_CHANNELS=40
-D BLE_PIN_CODE=123456
-D BLE_DEBUG_LOGGING=1
-D OFFLINE_QUEUE_SIZE=256
; -D MESH_PACKET_LOGGING=1
; -D MESH_DEBUG=1
build_src_filter = ${GAT562_30S_Mesh_Kit.build_src_filter}
+<helpers/nrf52/SerialBLEInterface.cpp>
+<helpers/ui/buzzer.cpp>
+<../examples/companion_radio/*.cpp>
+<../examples/companion_radio/ui-new/*.cpp>
lib_deps =
${GAT562_30S_Mesh_Kit.lib_deps}
densaugeo/base64 @ ~1.4.0
end2endzone/NonBlockingRTTTL@^1.3.0

View File

@@ -1,59 +0,0 @@
#include <Arduino.h>
#include "target.h"
#include <helpers/ArduinoHelpers.h>
GAT56230SMeshKitBoard board;
#ifndef PIN_USER_BTN
#define PIN_USER_BTN (-1)
#endif
#ifdef DISPLAY_CLASS
DISPLAY_CLASS display;
MomentaryButton user_btn(PIN_USER_BTN, 1000, true, false, false);
MomentaryButton joystick_left(JOYSTICK_LEFT, 1000, true, false, false);
MomentaryButton joystick_right(JOYSTICK_RIGHT, 1000, true, false, false);
MomentaryButton back_btn(PIN_BACK_BTN, 1000, true, false, true);
#endif
RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY, SPI);
WRAPPER_CLASS radio_driver(radio, board);
VolatileRTCClock fallback_clock;
AutoDiscoverRTCClock rtc_clock(fallback_clock);
#if ENV_INCLUDE_GPS
#include <helpers/sensors/MicroNMEALocationProvider.h>
MicroNMEALocationProvider nmea = MicroNMEALocationProvider(Serial1, &rtc_clock);
EnvironmentSensorManager sensors = EnvironmentSensorManager(nmea);
#else
EnvironmentSensorManager sensors;
#endif
bool radio_init() {
rtc_clock.begin(Wire);
return radio.std_init(&SPI);
}
uint32_t radio_get_rng_seed() {
return radio.random(0x7FFFFFFF);
}
void radio_set_params(float freq, float bw, uint8_t sf, uint8_t cr) {
radio.setFrequency(freq);
radio.setSpreadingFactor(sf);
radio.setBandwidth(bw);
radio.setCodingRate(cr);
}
void radio_set_tx_power(int8_t dbm) {
radio.setOutputPower(dbm);
}
mesh::LocalIdentity radio_new_identity() {
RadioNoiseListener rng(radio);
return mesh::LocalIdentity(&rng); // create new random identity
}

View File

@@ -1,30 +0,0 @@
#pragma once
#define RADIOLIB_STATIC_ONLY 1
#include <RadioLib.h>
#include <helpers/radiolib/RadioLibWrappers.h>
#include <GAT56230SMeshKitBoard.h>
#include <helpers/radiolib/CustomSX1262Wrapper.h>
#include <helpers/AutoDiscoverRTCClock.h>
#include <helpers/sensors/EnvironmentSensorManager.h>
#ifdef DISPLAY_CLASS
#include <helpers/ui/SSD1306Display.h>
extern DISPLAY_CLASS display;
#include <helpers/ui/MomentaryButton.h>
extern MomentaryButton user_btn;
extern MomentaryButton joystick_left;
extern MomentaryButton joystick_right;
extern MomentaryButton back_btn;
#endif
extern GAT56230SMeshKitBoard board;
extern WRAPPER_CLASS radio_driver;
extern AutoDiscoverRTCClock rtc_clock;
extern EnvironmentSensorManager sensors;
bool radio_init();
uint32_t radio_get_rng_seed();
void radio_set_params(float freq, float bw, uint8_t sf, uint8_t cr);
void radio_set_tx_power(int8_t dbm);
mesh::LocalIdentity radio_new_identity();

View File

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

View File

@@ -1,230 +0,0 @@
/*
Copyright (c) 2014-2015 Arduino LLC. All right reserved.
Copyright (c) 2016 Sandeep Mistry All right reserved.
Copyright (c) 2018, Adafruit Industries (adafruit.com)
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _VARIANT_RAK4630_
#define _VARIANT_RAK4630_
#define RAK4630
/** Master clock frequency */
#define VARIANT_MCK (64000000ul)
#define USE_LFXO // Board uses 32khz crystal for LF
// define USE_LFRC // Board uses RC for LF
/*----------------------------------------------------------------------------
* Headers
*----------------------------------------------------------------------------*/
#include "WVariant.h"
#ifdef __cplusplus
extern "C"
{
#endif // __cplusplus
/*
* WisBlock Base GPIO definitions
*/
static const uint8_t WB_IO1 = 17; // SLOT_A SLOT_B
static const uint8_t WB_IO2 = 34; // SLOT_A SLOT_B
static const uint8_t WB_IO3 = 21; // SLOT_C
static const uint8_t WB_IO4 = 4; // SLOT_C
static const uint8_t WB_IO5 = 9; // SLOT_D
static const uint8_t WB_IO6 = 10; // SLOT_D
static const uint8_t WB_SW1 = 33; // IO_SLOT
static const uint8_t WB_A0 = 5; // IO_SLOT
static const uint8_t WB_A1 = 31; // IO_SLOT
static const uint8_t WB_I2C1_SDA = 13; // SENSOR_SLOT IO_SLOT
static const uint8_t WB_I2C1_SCL = 14; // SENSOR_SLOT IO_SLOT
static const uint8_t WB_I2C2_SDA = 24; // IO_SLOT
static const uint8_t WB_I2C2_SCL = 25; // IO_SLOT
static const uint8_t WB_SPI_CS = 26; // IO_SLOT
static const uint8_t WB_SPI_CLK = 3; // IO_SLOT
static const uint8_t WB_SPI_MISO = 29; // IO_SLOT
static const uint8_t WB_SPI_MOSI = 30; // IO_SLOT
// Number of pins defined in PinDescription array
#define PINS_COUNT (48)
#define NUM_DIGITAL_PINS (48)
#define NUM_ANALOG_INPUTS (6)
#define NUM_ANALOG_OUTPUTS (0)
// LEDs
#define PIN_LED1 (35)
#define PIN_LED2 (36)
#define PIN_LED3 (29)
#define LED_BUILTIN PIN_LED1
#define LED_CONN PIN_LED2
#define WS2812_PIN PIN_LED3
#define LED_GREEN PIN_LED1
#define LED_BLUE PIN_LED2
#define LED_STATE_ON 1 // State when LED is litted
#define P_LORA_TX_LED LED_GREEN
/*
* Buttons
*/
#define PIN_BUTTON1 (9) // Menu / User Button
#define PIN_BUTTON2 (28) // Joystick Up
#define PIN_BUTTON3 (4) // Joystick Down
#define PIN_BUTTON4 (30) // Joystick Left
#define PIN_BUTTON5 (31) // Joystick Right
#define PIN_BUTTON6 (26) // Joystick Press
#define PIN_BACK_BTN PIN_BUTTON1
#define JOYSTICK_UP PIN_BUTTON2
#define JOYSTICK_DOWN PIN_BUTTON3
#define JOYSTICK_LEFT PIN_BUTTON4
#define JOYSTICK_RIGHT PIN_BUTTON5
#define JOYSTICK_PRESS PIN_BUTTON6
#define PIN_USER_BTN PIN_BUTTON6
/*
* Bat pins
*/
#define PIN_VBAT_READ (5)
#define ADC_MULTIPLIER (3 * 1.75 * 1.187 * 1000)
/*
* Analog pins
*/
#define PIN_A0 (5) //(3)
#define PIN_A1 (31) //(4)
#define PIN_A2 (28)
#define PIN_A3 (29)
#define PIN_A4 (30)
#define PIN_A5 (31)
#define PIN_A6 (0xff)
#define PIN_A7 (0xff)
static const uint8_t A0 = PIN_A0;
static const uint8_t A1 = PIN_A1;
static const uint8_t A2 = PIN_A2;
static const uint8_t A3 = PIN_A3;
static const uint8_t A4 = PIN_A4;
static const uint8_t A5 = PIN_A5;
static const uint8_t A6 = PIN_A6;
static const uint8_t A7 = PIN_A7;
#define ADC_RESOLUTION 14
// Power management boot protection threshold (millivolts)
// Set to 0 to disable boot protection
#define PWRMGT_VOLTAGE_BOOTLOCK 3300 // Won't boot below this voltage (mV)
// LPCOMP wake configuration (voltage recovery from SYSTEMOFF)
// AIN3 = P0.05 = PIN_A0 / PIN_VBAT_READ
#define PWRMGT_LPCOMP_AIN 3
#define PWRMGT_LPCOMP_REFSEL 4 // 5/8 VDD (~3.13-3.44V)
// Other pins
#define PIN_AREF (2)
#define PIN_NFC1 (9)
#define PIN_NFC2 (10)
static const uint8_t AREF = PIN_AREF;
/*
* Serial interfaces
*/
// TXD1 RXD1 on Base Board
#define PIN_SERIAL1_RX (15)
#define PIN_SERIAL1_TX (16)
// TXD0 RXD0 on Base Board
#define PIN_SERIAL2_RX (19)
#define PIN_SERIAL2_TX (20)
/*
* SPI Interfaces
*/
#define SPI_INTERFACES_COUNT 1
#define PIN_SPI_MISO (29)
#define PIN_SPI_MOSI (30)
#define PIN_SPI_SCK (3)
static const uint8_t SS = 26;
static const uint8_t MOSI = PIN_SPI_MOSI;
static const uint8_t MISO = PIN_SPI_MISO;
static const uint8_t SCK = PIN_SPI_SCK;
// LoRa radio module pins for RAK4631
#define SX126X_POWER_EN (37)
#define P_LORA_RESET (38)
#define P_LORA_NSS (42)
#define P_LORA_SCLK (43)
#define P_LORA_MOSI (44)
#define P_LORA_MISO (45)
#define P_LORA_BUSY (46)
#define P_LORA_DIO_1 (47)
#define SX126X_DIO2_AS_RF_SWITCH true
#define SX126X_DIO3_TCXO_VOLTAGE 1.8
/*
* Wire Interfaces
*/
#define WIRE_INTERFACES_COUNT 2
#define PIN_WIRE_SDA (13)
#define PIN_WIRE_SCL (14)
#define PIN_WIRE1_SDA (24)
#define PIN_WIRE1_SCL (25)
// QSPI Pins
// QSPI occupied by GPIO's
#define PIN_QSPI_SCK 3 // 19
#define PIN_QSPI_CS 26 // 17
#define PIN_QSPI_IO0 30 // 20
#define PIN_QSPI_IO1 29 // 21
#define PIN_QSPI_IO2 28 // 22
#define PIN_QSPI_IO3 2 // 23
// On-board QSPI Flash
// No onboard flash
#define EXTERNAL_FLASH_DEVICES IS25LP080D
#define EXTERNAL_FLASH_USE_QSPI
#define GPS_ADDRESS 0x42 //i2c address for GPS
// GPS L76KB
#define GPS_BAUD_RATE 9600
#define GPS_THREAD_INTERVAL 50
#define PIN_GPS_TX PIN_SERIAL1_RX
#define PIN_GPS_RX PIN_SERIAL1_TX
#define PIN_GPS_EN (33)
#define PIN_GPS_PPS (17)
#ifdef __cplusplus
}
#endif
/*----------------------------------------------------------------------------
* Arduino objects - C++ only
*----------------------------------------------------------------------------*/
#endif

View File

@@ -1,57 +0,0 @@
#include <Arduino.h>
#include <Wire.h>
#include "GAT562MeshTrackerProBoard.h"
#ifdef NRF52_POWER_MANAGEMENT
// Static configuration for power management
// Values set in variant.h defines
const PowerMgtConfig power_config = {
.lpcomp_ain_channel = PWRMGT_LPCOMP_AIN,
.lpcomp_refsel = PWRMGT_LPCOMP_REFSEL,
.voltage_bootlock = PWRMGT_VOLTAGE_BOOTLOCK
};
void GAT562MeshTrackerProBoard::initiateShutdown(uint8_t reason) {
// Disable LoRa module power before shutdown
digitalWrite(SX126X_POWER_EN, LOW);
if (reason == SHUTDOWN_REASON_LOW_VOLTAGE ||
reason == SHUTDOWN_REASON_BOOT_PROTECT) {
configureVoltageWake(power_config.lpcomp_ain_channel, power_config.lpcomp_refsel);
}
enterSystemOff(reason);
}
#endif // NRF52_POWER_MANAGEMENT
void GAT562MeshTrackerProBoard::begin() {
NRF52BoardDCDC::begin();
pinMode(PIN_VBAT_READ, INPUT);
// Set all button pins to INPUT_PULLUP
pinMode(PIN_BUTTON1, INPUT_PULLUP);
pinMode(PIN_BUTTON2, INPUT_PULLUP);
pinMode(PIN_BUTTON3, INPUT_PULLUP);
pinMode(PIN_BUTTON4, INPUT_PULLUP);
pinMode(PIN_BUTTON5, INPUT_PULLUP);
pinMode(PIN_BUTTON6, INPUT_PULLUP);
#if defined(PIN_BOARD_SDA) && defined(PIN_BOARD_SCL)
Wire.setPins(PIN_BOARD_SDA, PIN_BOARD_SCL);
#endif
Wire.begin();
pinMode(SX126X_POWER_EN, OUTPUT);
#ifdef NRF52_POWER_MANAGEMENT
// Boot voltage protection check (may not return if voltage too low)
// We need to call this after we configure SX126X_POWER_EN as output but before we pull high
checkBootVoltage(&power_config);
#endif
digitalWrite(SX126X_POWER_EN, HIGH);
delay(10); // give sx1262 some time to power up
}

View File

@@ -1,53 +0,0 @@
#pragma once
#include <MeshCore.h>
#include <Arduino.h>
#include <helpers/NRF52Board.h>
class GAT562MeshTrackerProBoard : public NRF52BoardDCDC {
protected:
#ifdef NRF52_POWER_MANAGEMENT
void initiateShutdown(uint8_t reason) override;
#endif
public:
GAT562MeshTrackerProBoard() : NRF52Board("GAT562_OTA") {}
void begin();
#define BATTERY_SAMPLES 8
uint16_t getBattMilliVolts() override {
analogReadResolution(12);
uint32_t raw = 0;
for (int i = 0; i < BATTERY_SAMPLES; i++) {
raw += analogRead(PIN_VBAT_READ);
}
raw = raw / BATTERY_SAMPLES;
return (ADC_MULTIPLIER * raw) / 4096;
}
const char* getManufacturerName() const override {
return "GAT562 Mesh Tracker Pro";
}
#if defined(P_LORA_TX_LED)
void onBeforeTransmit() override {
digitalWrite(P_LORA_TX_LED, HIGH); // turn TX LED on
}
void onAfterTransmit() override {
digitalWrite(P_LORA_TX_LED, LOW); // turn TX LED off
}
#endif
void powerOff() override {
uint32_t button_pin = PIN_BUTTON1;
nrf_gpio_cfg_input(button_pin, NRF_GPIO_PIN_PULLUP);
nrf_gpio_cfg_sense_set(button_pin, NRF_GPIO_PIN_SENSE_LOW);
sd_power_system_off();
}
};

View File

@@ -1,110 +0,0 @@
[GAT562_Mesh_Tracker_Pro]
extends = nrf52_base
board = rak4631
board_check = true
build_flags = ${nrf52_base.build_flags}
${sensor_base.build_flags}
-I variants/gat562_mesh_tracker_pro
-D RAK_4631
-D RAK_BOARD
-D NRF52_POWER_MANAGEMENT
-D PIN_BOARD_SCL=14
-D PIN_BOARD_SDA=13
-D PIN_OLED_RESET=-1
-D UI_HAS_JOYSTICK=1
-D RADIO_CLASS=CustomSX1262
-D WRAPPER_CLASS=CustomSX1262Wrapper
-D LORA_TX_POWER=22
-D SX126X_CURRENT_LIMIT=140
-D SX126X_RX_BOOSTED_GAIN=1
build_src_filter = ${nrf52_base.build_src_filter}
+<../variants/gat562_mesh_tracker_pro>
+<helpers/ui/SSD1306Display.cpp>
+<helpers/ui/MomentaryButton.cpp>
+<helpers/sensors>
lib_deps =
${nrf52_base.lib_deps}
${sensor_base.lib_deps}
adafruit/Adafruit SSD1306 @ ^2.5.13
sparkfun/SparkFun u-blox GNSS Arduino Library@^2.2.27
[env:GAT562_Mesh_Tracker_Pro_repeater]
extends = GAT562_Mesh_Tracker_Pro
build_flags =
${GAT562_Mesh_Tracker_Pro.build_flags}
-D DISPLAY_CLASS=SSD1306Display
-D ADVERT_NAME='"GAT562 Repeater"'
-D ADVERT_LAT=0.0
-D ADVERT_LON=0.0
-D ADMIN_PASSWORD='"password"'
-D MAX_NEIGHBOURS=50
; -D MESH_PACKET_LOGGING=1
; -D MESH_DEBUG=1
build_src_filter = ${GAT562_Mesh_Tracker_Pro.build_src_filter}
+<helpers/ui/SSD1306Display.cpp>
+<../examples/simple_repeater>
[env:GAT562_Mesh_Tracker_Pro_room_server]
extends = GAT562_Mesh_Tracker_Pro
build_flags =
${GAT562_Mesh_Tracker_Pro.build_flags}
-D DISPLAY_CLASS=SSD1306Display
-D ADVERT_NAME='"GAT562 Room"'
-D ADVERT_LAT=0.0
-D ADVERT_LON=0.0
-D ADMIN_PASSWORD='"password"'
-D ROOM_PASSWORD='"hello"'
; -D MESH_PACKET_LOGGING=1
; -D MESH_DEBUG=1
build_src_filter = ${GAT562_Mesh_Tracker_Pro.build_src_filter}
+<helpers/ui/SSD1306Display.cpp>
+<../examples/simple_room_server>
[env:GAT562_Mesh_Tracker_Pro_companion_radio_usb]
extends = GAT562_Mesh_Tracker_Pro
board_build.ldscript = boards/nrf52840_s140_v6_extrafs.ld
board_upload.maximum_size = 712704
build_flags =
${GAT562_Mesh_Tracker_Pro.build_flags}
-I examples/companion_radio/ui-new
-D DISPLAY_CLASS=SSD1306Display
-D MAX_CONTACTS=350
-D MAX_GROUP_CHANNELS=40
; NOTE: DO NOT ENABLE --> -D MESH_PACKET_LOGGING=1
; NOTE: DO NOT ENABLE --> -D MESH_DEBUG=1
build_src_filter = ${GAT562_Mesh_Tracker_Pro.build_src_filter}
+<../examples/companion_radio/*.cpp>
+<../examples/companion_radio/ui-new/*.cpp>
lib_deps =
${GAT562_Mesh_Tracker_Pro.lib_deps}
densaugeo/base64 @ ~1.4.0
[env:GAT562_Mesh_Tracker_Pro_companion_radio_ble]
extends = GAT562_Mesh_Tracker_Pro
board_build.ldscript = boards/nrf52840_s140_v6_extrafs.ld
board_upload.maximum_size = 712704
build_flags =
${GAT562_Mesh_Tracker_Pro.build_flags}
-I examples/companion_radio/ui-new
-D DISPLAY_CLASS=SSD1306Display
-D MAX_CONTACTS=350
-D MAX_GROUP_CHANNELS=40
-D BLE_PIN_CODE=123456
-D BLE_DEBUG_LOGGING=1
-D OFFLINE_QUEUE_SIZE=256
; -D MESH_PACKET_LOGGING=1
; -D MESH_DEBUG=1
build_src_filter = ${GAT562_Mesh_Tracker_Pro.build_src_filter}
+<helpers/nrf52/SerialBLEInterface.cpp>
+<helpers/ui/MomentaryButton.cpp>
+<../examples/companion_radio/*.cpp>
+<../examples/companion_radio/ui-new/*.cpp>
lib_deps =
${GAT562_Mesh_Tracker_Pro.lib_deps}
densaugeo/base64 @ ~1.4.0

View File

@@ -1,59 +0,0 @@
#include <Arduino.h>
#include "target.h"
#include <helpers/ArduinoHelpers.h>
GAT562MeshTrackerProBoard board;
#ifndef PIN_USER_BTN
#define PIN_USER_BTN (-1)
#endif
#ifdef DISPLAY_CLASS
DISPLAY_CLASS display;
MomentaryButton user_btn(PIN_USER_BTN, 1000, true, false, false);
MomentaryButton joystick_left(JOYSTICK_LEFT, 1000, true, false, false);
MomentaryButton joystick_right(JOYSTICK_RIGHT, 1000, true, false, false);
MomentaryButton back_btn(PIN_BACK_BTN, 1000, true, false, true);
#endif
RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY, SPI);
WRAPPER_CLASS radio_driver(radio, board);
VolatileRTCClock fallback_clock;
AutoDiscoverRTCClock rtc_clock(fallback_clock);
#if ENV_INCLUDE_GPS
#include <helpers/sensors/MicroNMEALocationProvider.h>
MicroNMEALocationProvider nmea = MicroNMEALocationProvider(Serial1, &rtc_clock);
EnvironmentSensorManager sensors = EnvironmentSensorManager(nmea);
#else
EnvironmentSensorManager sensors;
#endif
bool radio_init() {
rtc_clock.begin(Wire);
return radio.std_init(&SPI);
}
uint32_t radio_get_rng_seed() {
return radio.random(0x7FFFFFFF);
}
void radio_set_params(float freq, float bw, uint8_t sf, uint8_t cr) {
radio.setFrequency(freq);
radio.setSpreadingFactor(sf);
radio.setBandwidth(bw);
radio.setCodingRate(cr);
}
void radio_set_tx_power(int8_t dbm) {
radio.setOutputPower(dbm);
}
mesh::LocalIdentity radio_new_identity() {
RadioNoiseListener rng(radio);
return mesh::LocalIdentity(&rng); // create new random identity
}

View File

@@ -1,30 +0,0 @@
#pragma once
#define RADIOLIB_STATIC_ONLY 1
#include <RadioLib.h>
#include <helpers/radiolib/RadioLibWrappers.h>
#include <GAT562MeshTrackerProBoard.h>
#include <helpers/radiolib/CustomSX1262Wrapper.h>
#include <helpers/AutoDiscoverRTCClock.h>
#include <helpers/sensors/EnvironmentSensorManager.h>
#ifdef DISPLAY_CLASS
#include <helpers/ui/SSD1306Display.h>
extern DISPLAY_CLASS display;
#include <helpers/ui/MomentaryButton.h>
extern MomentaryButton user_btn;
extern MomentaryButton joystick_left;
extern MomentaryButton joystick_right;
extern MomentaryButton back_btn;
#endif
extern GAT562MeshTrackerProBoard board;
extern WRAPPER_CLASS radio_driver;
extern AutoDiscoverRTCClock rtc_clock;
extern EnvironmentSensorManager sensors;
bool radio_init();
uint32_t radio_get_rng_seed();
void radio_set_params(float freq, float bw, uint8_t sf, uint8_t cr);
void radio_set_tx_power(int8_t dbm);
mesh::LocalIdentity radio_new_identity();

View File

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

View File

@@ -1,226 +0,0 @@
/*
Copyright (c) 2014-2015 Arduino LLC. All right reserved.
Copyright (c) 2016 Sandeep Mistry All right reserved.
Copyright (c) 2018, Adafruit Industries (adafruit.com)
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _VARIANT_RAK4630_
#define _VARIANT_RAK4630_
#define RAK4630
/** Master clock frequency */
#define VARIANT_MCK (64000000ul)
#define USE_LFXO // Board uses 32khz crystal for LF
// define USE_LFRC // Board uses RC for LF
/*----------------------------------------------------------------------------
* Headers
*----------------------------------------------------------------------------*/
#include "WVariant.h"
#ifdef __cplusplus
extern "C"
{
#endif // __cplusplus
/*
* WisBlock Base GPIO definitions
*/
static const uint8_t WB_IO1 = 17; // SLOT_A SLOT_B
static const uint8_t WB_IO2 = 34; // SLOT_A SLOT_B
static const uint8_t WB_IO3 = 21; // SLOT_C
static const uint8_t WB_IO4 = 4; // SLOT_C
static const uint8_t WB_IO5 = 9; // SLOT_D
static const uint8_t WB_IO6 = 10; // SLOT_D
static const uint8_t WB_SW1 = 33; // IO_SLOT
static const uint8_t WB_A0 = 5; // IO_SLOT
static const uint8_t WB_A1 = 31; // IO_SLOT
static const uint8_t WB_I2C1_SDA = 13; // SENSOR_SLOT IO_SLOT
static const uint8_t WB_I2C1_SCL = 14; // SENSOR_SLOT IO_SLOT
static const uint8_t WB_I2C2_SDA = 24; // IO_SLOT
static const uint8_t WB_I2C2_SCL = 25; // IO_SLOT
static const uint8_t WB_SPI_CS = 26; // IO_SLOT
static const uint8_t WB_SPI_CLK = 3; // IO_SLOT
static const uint8_t WB_SPI_MISO = 29; // IO_SLOT
static const uint8_t WB_SPI_MOSI = 30; // IO_SLOT
// Number of pins defined in PinDescription array
#define PINS_COUNT (48)
#define NUM_DIGITAL_PINS (48)
#define NUM_ANALOG_INPUTS (6)
#define NUM_ANALOG_OUTPUTS (0)
// LEDs
#define PIN_LED1 (35)
#define PIN_LED2 (36)
#define LED_BUILTIN PIN_LED1
#define LED_CONN PIN_LED2
#define LED_GREEN PIN_LED1
#define LED_BLUE PIN_LED2
#define LED_STATE_ON 1 // State when LED is litted
// #define P_LORA_TX_LED LED_GREEN
/*
* Buttons
*/
#define PIN_BUTTON1 (9) // Menu / User Button
#define PIN_BUTTON2 (28) // Joystick Up
#define PIN_BUTTON3 (4) // Joystick Down
#define PIN_BUTTON4 (30) // Joystick Left
#define PIN_BUTTON5 (31) // Joystick Right
#define PIN_BUTTON6 (26) // Joystick Press
#define PIN_BACK_BTN PIN_BUTTON1
#define JOYSTICK_UP PIN_BUTTON2
#define JOYSTICK_DOWN PIN_BUTTON3
#define JOYSTICK_LEFT PIN_BUTTON4
#define JOYSTICK_RIGHT PIN_BUTTON5
#define JOYSTICK_PRESS PIN_BUTTON6
#define PIN_USER_BTN PIN_BUTTON6
// Analog pins
#define PIN_VBAT_READ (5)
#define ADC_MULTIPLIER (3 * 1.75 * 1.187 * 1000)
/*
* Analog pins
*/
#define PIN_A0 (5) //(3)
#define PIN_A1 (31) //(4)
#define PIN_A2 (28)
#define PIN_A3 (29)
#define PIN_A4 (30)
#define PIN_A5 (31)
#define PIN_A6 (0xff)
#define PIN_A7 (0xff)
static const uint8_t A0 = PIN_A0;
static const uint8_t A1 = PIN_A1;
static const uint8_t A2 = PIN_A2;
static const uint8_t A3 = PIN_A3;
static const uint8_t A4 = PIN_A4;
static const uint8_t A5 = PIN_A5;
static const uint8_t A6 = PIN_A6;
static const uint8_t A7 = PIN_A7;
#define ADC_RESOLUTION 14
// Power management boot protection threshold (millivolts)
// Set to 0 to disable boot protection
#define PWRMGT_VOLTAGE_BOOTLOCK 3300 // Won't boot below this voltage (mV)
// LPCOMP wake configuration (voltage recovery from SYSTEMOFF)
// AIN3 = P0.05 = PIN_A0 / PIN_VBAT_READ
#define PWRMGT_LPCOMP_AIN 3
#define PWRMGT_LPCOMP_REFSEL 4 // 5/8 VDD (~3.13-3.44V)
// Other pins
#define PIN_AREF (2)
#define PIN_NFC1 (9)
#define PIN_NFC2 (10)
static const uint8_t AREF = PIN_AREF;
/*
* Serial interfaces
*/
// TXD1 RXD1 on Base Board
#define PIN_SERIAL1_RX (15)
#define PIN_SERIAL1_TX (16)
// TXD0 RXD0 on Base Board
#define PIN_SERIAL2_RX (19)
#define PIN_SERIAL2_TX (20)
/*
* SPI Interfaces
*/
#define SPI_INTERFACES_COUNT 1
#define PIN_SPI_MISO (29)
#define PIN_SPI_MOSI (30)
#define PIN_SPI_SCK (3)
static const uint8_t SS = 26;
static const uint8_t MOSI = PIN_SPI_MOSI;
static const uint8_t MISO = PIN_SPI_MISO;
static const uint8_t SCK = PIN_SPI_SCK;
// LoRa radio module pins for RAK4631
#define SX126X_POWER_EN (37)
#define P_LORA_RESET (38)
#define P_LORA_NSS (42)
#define P_LORA_SCLK (43)
#define P_LORA_MOSI (44)
#define P_LORA_MISO (45)
#define P_LORA_BUSY (46)
#define P_LORA_DIO_1 (47)
#define SX126X_DIO2_AS_RF_SWITCH true
#define SX126X_DIO3_TCXO_VOLTAGE 1.8
/*
* Wire Interfaces
*/
#define WIRE_INTERFACES_COUNT 2
#define PIN_WIRE_SDA (13)
#define PIN_WIRE_SCL (14)
#define PIN_WIRE1_SDA (24)
#define PIN_WIRE1_SCL (25)
// QSPI Pins
// QSPI occupied by GPIO's
#define PIN_QSPI_SCK 3 // 19
#define PIN_QSPI_CS 26 // 17
#define PIN_QSPI_IO0 30 // 20
#define PIN_QSPI_IO1 29 // 21
#define PIN_QSPI_IO2 28 // 22
#define PIN_QSPI_IO3 2 // 23
// On-board QSPI Flash
// No onboard flash
#define EXTERNAL_FLASH_DEVICES IS25LP080D
#define EXTERNAL_FLASH_USE_QSPI
#define GPS_ADDRESS 0x42 //i2c address for GPS
// GPS L76KB
#define GPS_BAUD_RATE 9600
#define GPS_THREAD_INTERVAL 50
#define PIN_GPS_TX PIN_SERIAL1_RX
#define PIN_GPS_RX PIN_SERIAL1_TX
#define PIN_GPS_EN (33)
#define PIN_GPS_PPS (17)
#ifdef __cplusplus
}
#endif
/*----------------------------------------------------------------------------
* Arduino objects - C++ only
*----------------------------------------------------------------------------*/
#endif

View File

@@ -46,4 +46,3 @@ mesh::LocalIdentity radio_new_identity() {
RadioNoiseListener rng(radio);
return mesh::LocalIdentity(&rng); // create new random identity
}

View File

@@ -19,4 +19,3 @@ uint32_t radio_get_rng_seed();
void radio_set_params(float freq, float bw, uint8_t sf, uint8_t cr);
void radio_set_tx_power(int8_t dbm);
mesh::LocalIdentity radio_new_identity();

View File

@@ -5,7 +5,6 @@ build_flags =
${esp32_base.build_flags}
-I variants/heltec_ct62
-D HELTEC_HT_CT62=1
-D USE_SX1262
-D RADIO_CLASS=CustomSX1262
-D WRAPPER_CLASS=CustomSX1262Wrapper
-D ESP32_CPU_FREQ=80

View File

@@ -34,4 +34,4 @@ void radio_set_tx_power(int8_t dbm) {
mesh::LocalIdentity radio_new_identity() {
RadioNoiseListener rng(radio);
return mesh::LocalIdentity(&rng); // create new random identity
}
}

View File

@@ -17,4 +17,4 @@ bool radio_init();
uint32_t radio_get_rng_seed();
void radio_set_params(float freq, float bw, uint8_t sf, uint8_t cr);
void radio_set_tx_power(int8_t dbm);
mesh::LocalIdentity radio_new_identity();
mesh::LocalIdentity radio_new_identity();

View File

@@ -6,7 +6,6 @@ build_flags =
-I variants/heltec_e213
-D Vision_Master_E213
-D ARDUINO_USB_CDC_ON_BOOT=1
-D USE_SX1262
-D RADIO_CLASS=CustomSX1262
-D WRAPPER_CLASS=CustomSX1262Wrapper
-D P_LORA_DIO_1=14
@@ -41,7 +40,7 @@ lib_deps =
${esp32_base.lib_deps}
https://github.com/Quency-D/heltec-eink-modules/archive/563dd41fd850a1bc3039b8723da4f3a20fe1c800.zip
[env:Heltec_E213_companion_radio_ble]
[env:Heltec_E213_companion_radio_ble_]
extends = Heltec_E213_base
build_flags =
${Heltec_E213_base.build_flags}
@@ -49,7 +48,6 @@ build_flags =
-D MAX_CONTACTS=350
-D MAX_GROUP_CHANNELS=40
-D DISPLAY_CLASS=E213Display
-D AUTO_OFF_MILLIS=0
-D BLE_PIN_CODE=123456 ; dynamic, random PIN
-D BLE_DEBUG_LOGGING=1
-D OFFLINE_QUEUE_SIZE=256
@@ -61,9 +59,8 @@ build_src_filter = ${Heltec_E213_base.build_src_filter}
lib_deps =
${Heltec_E213_base.lib_deps}
densaugeo/base64 @ ~1.4.0
bakercp/CRC32 @ ^2.0.0
[env:Heltec_E213_companion_radio_usb]
[env:Heltec_E213_companion_radio_usb_]
extends = Heltec_E213_base
build_flags =
${Heltec_E213_base.build_flags}
@@ -71,7 +68,6 @@ build_flags =
-D MAX_CONTACTS=350
-D MAX_GROUP_CHANNELS=40
-D DISPLAY_CLASS=E213Display
-D AUTO_OFF_MILLIS=0
-D OFFLINE_QUEUE_SIZE=256
build_src_filter = ${Heltec_E213_base.build_src_filter}
+<helpers/ui/E213Display.cpp>
@@ -81,9 +77,8 @@ build_src_filter = ${Heltec_E213_base.build_src_filter}
lib_deps =
${Heltec_E213_base.lib_deps}
densaugeo/base64 @ ~1.4.0
bakercp/CRC32 @ ^2.0.0
[env:Heltec_E213_repeater]
[env:Heltec_E213_repeater_]
extends = Heltec_E213_base
build_flags =
${Heltec_E213_base.build_flags}
@@ -99,9 +94,8 @@ build_src_filter = ${Heltec_E213_base.build_src_filter}
lib_deps =
${Heltec_E213_base.lib_deps}
${esp32_ota.lib_deps}
bakercp/CRC32 @ ^2.0.0
; [env:Heltec_E213_repeater_bridge_rs232]
; [env:Heltec_E213_repeater_bridge_rs232_]
; extends = Heltec_E213_base
; build_flags =
; ${Heltec_E213_base.build_flags}
@@ -124,9 +118,8 @@ lib_deps =
; lib_deps =
; ${Heltec_E213_base.lib_deps}
; ${esp32_ota.lib_deps}
; bakercp/CRC32 @ ^2.0.0
[env:Heltec_E213_repeater_bridge_espnow]
[env:Heltec_E213_repeater_bridge_espnow_]
extends = Heltec_E213_base
build_flags =
${Heltec_E213_base.build_flags}
@@ -147,9 +140,8 @@ build_src_filter = ${Heltec_E213_base.build_src_filter}
lib_deps =
${Heltec_E213_base.lib_deps}
${esp32_ota.lib_deps}
bakercp/CRC32 @ ^2.0.0
[env:Heltec_E213_room_server]
[env:Heltec_E213_room_server_]
extends = Heltec_E213_base
build_flags =
${Heltec_E213_base.build_flags}
@@ -165,4 +157,3 @@ build_src_filter = ${Heltec_E213_base.build_src_filter}
lib_deps =
${Heltec_E213_base.lib_deps}
${esp32_ota.lib_deps}
bakercp/CRC32 @ ^2.0.0

View File

@@ -18,7 +18,7 @@ AutoDiscoverRTCClock rtc_clock(fallback_clock);
SensorManager sensors;
#ifdef DISPLAY_CLASS
DISPLAY_CLASS display(&board.periph_power);
DISPLAY_CLASS display;
MomentaryButton user_btn(PIN_USER_BTN, 1000, true);
#endif

View File

@@ -26,4 +26,4 @@ bool radio_init();
uint32_t radio_get_rng_seed();
void radio_set_params(float freq, float bw, uint8_t sf, uint8_t cr);
void radio_set_tx_power(int8_t dbm);
mesh::LocalIdentity radio_new_identity();
mesh::LocalIdentity radio_new_identity();

View File

@@ -10,7 +10,7 @@ class HeltecE290Board : public ESP32Board {
public:
RefCountedDigitalPin periph_power;
HeltecE290Board() : periph_power(PIN_VEXT_EN, PIN_VEXT_EN_ACTIVE) { }
HeltecE290Board() : periph_power(PIN_VEXT_EN) { }
void begin();
void enterDeepSleep(uint32_t secs, int pin_wake_btn = -1);

View File

@@ -6,7 +6,6 @@ build_flags =
-I variants/heltec_e290
-D Vision_Master_E290
-D ARDUINO_USB_CDC_ON_BOOT=1
-D USE_SX1262
-D RADIO_CLASS=CustomSX1262
-D WRAPPER_CLASS=CustomSX1262Wrapper
-D LORA_TX_POWER=22
@@ -35,7 +34,7 @@ lib_deps =
${esp32_base.lib_deps}
https://github.com/Quency-D/heltec-eink-modules/archive/563dd41fd850a1bc3039b8723da4f3a20fe1c800.zip
[env:Heltec_E290_companion_ble]
[env:Heltec_E290_companion_ble_]
extends = Heltec_E290_base
build_flags =
${Heltec_E290_base.build_flags}
@@ -43,7 +42,6 @@ build_flags =
-D MAX_CONTACTS=350
-D MAX_GROUP_CHANNELS=40
-D DISPLAY_CLASS=E290Display
-D AUTO_OFF_MILLIS=0
-D BLE_PIN_CODE=123456 ; dynamic, random PIN
-D BLE_DEBUG_LOGGING=1
-D OFFLINE_QUEUE_SIZE=256
@@ -55,9 +53,8 @@ build_src_filter = ${Heltec_E290_base.build_src_filter}
lib_deps =
${Heltec_E290_base.lib_deps}
densaugeo/base64 @ ~1.4.0
bakercp/CRC32 @ ^2.0.0
[env:Heltec_E290_companion_usb]
[env:Heltec_E290_companion_usb_]
extends = Heltec_E290_base
build_flags =
${Heltec_E290_base.build_flags}
@@ -65,7 +62,6 @@ build_flags =
-D MAX_CONTACTS=350
-D MAX_GROUP_CHANNELS=40
-D DISPLAY_CLASS=E290Display
-D AUTO_OFF_MILLIS=0
-D BLE_PIN_CODE=123456 ; dynamic, random PIN
-D BLE_DEBUG_LOGGING=1
-D OFFLINE_QUEUE_SIZE=256
@@ -77,9 +73,8 @@ build_src_filter = ${Heltec_E290_base.build_src_filter}
lib_deps =
${Heltec_E290_base.lib_deps}
densaugeo/base64 @ ~1.4.0
bakercp/CRC32 @ ^2.0.0
[env:Heltec_E290_repeater]
[env:Heltec_E290_repeater_]
extends = Heltec_E290_base
build_flags =
${Heltec_E290_base.build_flags}
@@ -95,9 +90,8 @@ build_src_filter = ${Heltec_E290_base.build_src_filter}
lib_deps =
${Heltec_E290_base.lib_deps}
${esp32_ota.lib_deps}
bakercp/CRC32 @ ^2.0.0
; [env:Heltec_E290_repeater_bridge_rs232]
; [env:Heltec_E290_repeater_bridge_rs232_]
; extends = Heltec_E290_base
; build_flags =
; ${Heltec_E290_base.build_flags}
@@ -120,9 +114,8 @@ lib_deps =
; lib_deps =
; ${Heltec_E290_base.lib_deps}
; ${esp32_ota.lib_deps}
; bakercp/CRC32 @ ^2.0.0
[env:Heltec_E290_repeater_bridge_espnow]
[env:Heltec_E290_repeater_bridge_espnow_]
extends = Heltec_E290_base
build_flags =
${Heltec_E290_base.build_flags}
@@ -143,9 +136,8 @@ build_src_filter = ${Heltec_E290_base.build_src_filter}
lib_deps =
${Heltec_E290_base.lib_deps}
${esp32_ota.lib_deps}
bakercp/CRC32 @ ^2.0.0
[env:Heltec_E290_room_server]
[env:Heltec_E290_room_server_]
extends = Heltec_E290_base
build_flags =
${Heltec_E290_base.build_flags}
@@ -161,4 +153,3 @@ build_src_filter = ${Heltec_E290_base.build_src_filter}
lib_deps =
${Heltec_E290_base.lib_deps}
${esp32_ota.lib_deps}
bakercp/CRC32 @ ^2.0.0

View File

@@ -18,7 +18,7 @@ AutoDiscoverRTCClock rtc_clock(fallback_clock);
SensorManager sensors;
#ifdef DISPLAY_CLASS
DISPLAY_CLASS display(&board.periph_power);
DISPLAY_CLASS display;
MomentaryButton user_btn(PIN_USER_BTN, 1000, true);
#endif

View File

@@ -26,4 +26,4 @@ bool radio_init();
uint32_t radio_get_rng_seed();
void radio_set_params(float freq, float bw, uint8_t sf, uint8_t cr);
void radio_set_tx_power(int8_t dbm);
mesh::LocalIdentity radio_new_identity();
mesh::LocalIdentity radio_new_identity();

View File

@@ -11,7 +11,7 @@ WRAPPER_CLASS radio_driver(radio, board);
VolatileRTCClock fallback_clock;
AutoDiscoverRTCClock rtc_clock(fallback_clock);
MicroNMEALocationProvider nmea = MicroNMEALocationProvider(Serial1, &rtc_clock);
MicroNMEALocationProvider nmea = MicroNMEALocationProvider(Serial1);
SolarSensorManager sensors = SolarSensorManager(nmea);
#ifdef DISPLAY_CLASS

View File

@@ -32,7 +32,7 @@
// Power management boot protection threshold (millivolts)
// Set to 0 to disable boot protection
#define PWRMGT_VOLTAGE_BOOTLOCK 0 // Won't boot below this voltage (mV)
#define PWRMGT_VOLTAGE_BOOTLOCK 3300 // Won't boot below this voltage (mV)
// LPCOMP wake configuration (voltage recovery from SYSTEMOFF)
// AIN2 = P0.04 = BATTERY_PIN / PIN_VBAT_READ
#define PWRMGT_LPCOMP_AIN 2

View File

@@ -6,7 +6,6 @@ build_flags =
-I variants/heltec_t190
-I src/helpers/ui
-D HELTEC_VISION_MASTER_T190
-D USE_SX1262
-D RADIO_CLASS=CustomSX1262
-D WRAPPER_CLASS=CustomSX1262Wrapper
-D P_LORA_DIO_1=14

View File

@@ -26,4 +26,4 @@ bool radio_init();
uint32_t radio_get_rng_seed();
void radio_set_params(float freq, float bw, uint8_t sf, uint8_t cr);
void radio_set_tx_power(int8_t dbm);
mesh::LocalIdentity radio_new_identity();
mesh::LocalIdentity radio_new_identity();

View File

@@ -14,7 +14,6 @@ build_flags =
-D P_LORA_SCLK=9
-D P_LORA_MISO=11
-D P_LORA_MOSI=10
-D USE_SX1262
-D RADIO_CLASS=CustomSX1262
-D WRAPPER_CLASS=CustomSX1262Wrapper
-D LORA_TX_POWER=22

View File

@@ -6,7 +6,19 @@ void HeltecTrackerV2Board::begin() {
pinMode(PIN_ADC_CTRL, OUTPUT);
digitalWrite(PIN_ADC_CTRL, LOW); // Initially inactive
loRaFEMControl.init();
// Set up digital GPIO registers before releasing RTC hold. The hold latches
// the pad state including function select, so register writes accumulate
// without affecting the pad. On hold release, all changes apply atomically
// (IO MUX switches to digital GPIO with output already HIGH — no glitch).
pinMode(P_LORA_PA_POWER, OUTPUT);
digitalWrite(P_LORA_PA_POWER,HIGH);
rtc_gpio_hold_dis((gpio_num_t)P_LORA_PA_POWER);
pinMode(P_LORA_PA_EN, OUTPUT);
digitalWrite(P_LORA_PA_EN,HIGH);
rtc_gpio_hold_dis((gpio_num_t)P_LORA_PA_EN);
pinMode(P_LORA_PA_TX_EN, OUTPUT);
digitalWrite(P_LORA_PA_TX_EN,LOW);
esp_reset_reason_t reason = esp_reset_reason();
if (reason != ESP_RST_DEEPSLEEP) {
@@ -27,12 +39,12 @@ void HeltecTrackerV2Board::begin() {
void HeltecTrackerV2Board::onBeforeTransmit(void) {
digitalWrite(P_LORA_TX_LED, HIGH); // turn TX LED on
loRaFEMControl.setTxModeEnable();
digitalWrite(P_LORA_PA_TX_EN,HIGH);
}
void HeltecTrackerV2Board::onAfterTransmit(void) {
digitalWrite(P_LORA_TX_LED, LOW); // turn TX LED off
loRaFEMControl.setRxModeEnable();
digitalWrite(P_LORA_PA_TX_EN,LOW);
}
void HeltecTrackerV2Board::enterDeepSleep(uint32_t secs, int pin_wake_btn) {
@@ -44,7 +56,9 @@ void HeltecTrackerV2Board::begin() {
rtc_gpio_hold_en((gpio_num_t)P_LORA_NSS);
loRaFEMControl.setRxModeEnableWhenMCUSleep();//It also needs to be enabled in receive mode
// Hold GC1109 FEM pins during sleep to keep LNA active for RX wake
rtc_gpio_hold_en((gpio_num_t)P_LORA_PA_POWER);
rtc_gpio_hold_en((gpio_num_t)P_LORA_PA_EN);
if (pin_wake_btn < 0) {
esp_sleep_enable_ext1_wakeup( (1L << P_LORA_DIO_1), ESP_EXT1_WAKEUP_ANY_HIGH); // wake up on: recv LoRa packet

View File

@@ -4,13 +4,11 @@
#include <helpers/RefCountedDigitalPin.h>
#include <helpers/ESP32Board.h>
#include <driver/rtc_io.h>
#include "LoRaFEMControl.h"
class HeltecTrackerV2Board : public ESP32Board {
public:
RefCountedDigitalPin periph_power;
LoRaFEMControl loRaFEMControl;
HeltecTrackerV2Board() : periph_power(PIN_VEXT_EN,PIN_VEXT_EN_ACTIVE) { }

View File

@@ -1,58 +0,0 @@
#include "LoRaFEMControl.h"
#include <driver/rtc_io.h>
#include <esp_sleep.h>
#include <Arduino.h>
void LoRaFEMControl::init(void)
{
pinMode(P_LORA_PA_POWER, OUTPUT);
digitalWrite(P_LORA_PA_POWER, HIGH);
rtc_gpio_hold_dis((gpio_num_t)P_LORA_PA_POWER);
rtc_gpio_hold_dis((gpio_num_t)P_LORA_KCT8103L_PA_CSD);
rtc_gpio_hold_dis((gpio_num_t)P_LORA_KCT8103L_PA_CTX);
delay(1);
pinMode(P_LORA_KCT8103L_PA_CSD, OUTPUT);
digitalWrite(P_LORA_KCT8103L_PA_CSD, HIGH);
pinMode(P_LORA_KCT8103L_PA_CTX, OUTPUT);
digitalWrite(P_LORA_KCT8103L_PA_CTX, HIGH);
setLnaCanControl(true);
}
void LoRaFEMControl::setSleepModeEnable(void)
{
// shutdown the PA
digitalWrite(P_LORA_KCT8103L_PA_CSD, LOW);
}
void LoRaFEMControl::setTxModeEnable(void)
{
digitalWrite(P_LORA_KCT8103L_PA_CSD, HIGH);
digitalWrite(P_LORA_KCT8103L_PA_CTX, HIGH);
}
void LoRaFEMControl::setRxModeEnable(void)
{
digitalWrite(P_LORA_KCT8103L_PA_CSD, HIGH);
if (lna_enabled) {
digitalWrite(P_LORA_KCT8103L_PA_CTX, LOW);
} else {
digitalWrite(P_LORA_KCT8103L_PA_CTX, HIGH);
}
}
void LoRaFEMControl::setRxModeEnableWhenMCUSleep(void)
{
digitalWrite(P_LORA_KCT8103L_PA_CSD, HIGH);
rtc_gpio_hold_en((gpio_num_t)P_LORA_KCT8103L_PA_CSD);
if (lna_enabled) {
digitalWrite(P_LORA_KCT8103L_PA_CTX, LOW);
} else {
digitalWrite(P_LORA_KCT8103L_PA_CTX, HIGH);
}
rtc_gpio_hold_en((gpio_num_t)P_LORA_KCT8103L_PA_CTX);
}
void LoRaFEMControl::setLNAEnable(bool enabled)
{
lna_enabled = enabled;
}

View File

@@ -1,21 +0,0 @@
#pragma once
#include <stdint.h>
class LoRaFEMControl
{
public:
LoRaFEMControl() {}
virtual ~LoRaFEMControl() {}
void init(void);
void setSleepModeEnable(void);
void setTxModeEnable(void);
void setRxModeEnable(void);
void setRxModeEnableWhenMCUSleep(void);
void setLNAEnable(bool enabled);
bool isLnaCanControl(void) { return lna_can_control; }
void setLnaCanControl(bool can_control) { lna_can_control = can_control; }
private:
bool lna_enabled = false;
bool lna_can_control = false;
};

View File

@@ -7,7 +7,6 @@ build_flags =
-I variants/heltec_tracker_v2
-D HELTEC_TRACKER_V2
-D ESP32_CPU_FREQ=160
-D USE_SX1262
-D RADIO_CLASS=CustomSX1262
-D WRAPPER_CLASS=CustomSX1262Wrapper
-D P_LORA_TX_LED=18
@@ -18,18 +17,18 @@ build_flags =
-D P_LORA_SCLK=9
-D P_LORA_MISO=11
-D P_LORA_MOSI=10
-D P_LORA_PA_POWER=7 ;VFEM_Ctrl -LDO power enable
-D P_LORA_KCT8103L_PA_CSD=4
-D P_LORA_KCT8103L_PA_CTX=5
-D LORA_TX_POWER=9 ; 9dBm + ~13dB KCT8103L gain = ~22dBm output
-D P_LORA_PA_POWER=7 ; VFEM_Ctrl - GC1109 LDO power enable
-D P_LORA_PA_EN=4 ; CSD - GC1109 chip enable (HIGH=on)
-D P_LORA_PA_TX_EN=46 ; CPS - GC1109 PA mode (HIGH=full PA, LOW=bypass)
-D LORA_TX_POWER=10 ; 10dBm + ~11dB GC1109 gain = ~21dBm output
-D MAX_LORA_TX_POWER=22 ; Max SX1262 output -> ~28dBm at antenna
-D SX126X_DIO2_AS_RF_SWITCH=true
-D SX126X_DIO3_TCXO_VOLTAGE=1.8
-D SX126X_CURRENT_LIMIT=140
-D SX126X_RX_BOOSTED_GAIN=1
-D SX126X_REGISTER_PATCH=1
-D PIN_BOARD_SDA=6
-D PIN_BOARD_SCL=17
-D PIN_BOARD_SDA=5
-D PIN_BOARD_SCL=6
-D PIN_USER_BTN=0
-D PIN_TFT_SDA=42 ; SDIN
-D PIN_TFT_SCL=41 ; SCLK
@@ -208,6 +207,8 @@ build_flags =
-D ADVERT_LAT=0.0
-D ADVERT_LON=0.0
-D ADMIN_PASSWORD='"password"'
-D ENV_PIN_SDA=3
-D ENV_PIN_SCL=4
-D DISPLAY_CLASS=ST7735Display
; -D MESH_PACKET_LOGGING=1
; -D MESH_DEBUG=1

View File

@@ -17,7 +17,7 @@ AutoDiscoverRTCClock rtc_clock(fallback_clock);
#if ENV_INCLUDE_GPS
#include <helpers/sensors/MicroNMEALocationProvider.h>
MicroNMEALocationProvider nmea = MicroNMEALocationProvider(Serial1, &rtc_clock, GPS_RESET, GPS_EN, &board.periph_power);
MicroNMEALocationProvider nmea = MicroNMEALocationProvider(Serial1, NULL, GPS_RESET, GPS_EN, &board.periph_power);
EnvironmentSensorManager sensors = EnvironmentSensorManager(nmea);
#else
EnvironmentSensorManager sensors;
@@ -58,4 +58,3 @@ mesh::LocalIdentity radio_new_identity() {
RadioNoiseListener rng(radio);
return mesh::LocalIdentity(&rng); // create new random identity
}

View File

@@ -28,4 +28,3 @@ uint32_t radio_get_rng_seed();
void radio_set_params(float freq, float bw, uint8_t sf, uint8_t cr);
void radio_set_tx_power(int8_t dbm);
mesh::LocalIdentity radio_new_identity();

View File

@@ -50,4 +50,4 @@ void radio_set_tx_power(int8_t dbm) {
mesh::LocalIdentity radio_new_identity() {
RadioNoiseListener rng(radio);
return mesh::LocalIdentity(&rng); // create new random identity
}
}

View File

@@ -14,7 +14,6 @@ build_flags =
-D P_LORA_SCLK=9
-D P_LORA_MISO=11
-D P_LORA_MOSI=10
-D USE_SX1262
-D RADIO_CLASS=CustomSX1262
-D WRAPPER_CLASS=CustomSX1262Wrapper
-D LORA_TX_POWER=22

View File

@@ -17,7 +17,7 @@ AutoDiscoverRTCClock rtc_clock(fallback_clock);
#if ENV_INCLUDE_GPS
#include <helpers/sensors/MicroNMEALocationProvider.h>
MicroNMEALocationProvider nmea = MicroNMEALocationProvider(Serial1, &rtc_clock);
MicroNMEALocationProvider nmea = MicroNMEALocationProvider(Serial1);
EnvironmentSensorManager sensors = EnvironmentSensorManager(nmea);
#else
EnvironmentSensorManager sensors;
@@ -58,4 +58,3 @@ mesh::LocalIdentity radio_new_identity() {
RadioNoiseListener rng(radio);
return mesh::LocalIdentity(&rng); // create new random identity
}

View File

@@ -6,7 +6,6 @@ build_flags =
${sensor_base.build_flags}
-I variants/heltec_v4
-D HELTEC_LORA_V4
-D USE_SX1262
-D ESP32_CPU_FREQ=80
-D RADIO_CLASS=CustomSX1262
-D WRAPPER_CLASS=CustomSX1262Wrapper

View File

@@ -17,7 +17,7 @@ AutoDiscoverRTCClock rtc_clock(fallback_clock);
#if ENV_INCLUDE_GPS
#include <helpers/sensors/MicroNMEALocationProvider.h>
MicroNMEALocationProvider nmea = MicroNMEALocationProvider(Serial1, &rtc_clock);
MicroNMEALocationProvider nmea = MicroNMEALocationProvider(Serial1);
EnvironmentSensorManager sensors = EnvironmentSensorManager(nmea);
#else
EnvironmentSensorManager sensors;
@@ -58,4 +58,3 @@ mesh::LocalIdentity radio_new_identity() {
RadioNoiseListener rng(radio);
return mesh::LocalIdentity(&rng); // create new random identity
}

View File

@@ -32,4 +32,3 @@ uint32_t radio_get_rng_seed();
void radio_set_params(float freq, float bw, uint8_t sf, uint8_t cr);
void radio_set_tx_power(int8_t dbm);
mesh::LocalIdentity radio_new_identity();

Some files were not shown because too many files have changed in this diff Show More