mirror of
https://github.com/meshtastic/firmware.git
synced 2026-06-06 15:55:36 -04:00
Merge branch 'develop' into thinknode-g3
This commit is contained in:
191
.github/copilot-instructions.md
vendored
191
.github/copilot-instructions.md
vendored
@@ -4,11 +4,11 @@ This document provides context and guidelines for AI assistants working with the
|
||||
|
||||
## Project Overview
|
||||
|
||||
Meshtastic is an open-source LoRa mesh networking project for long-range, low-power communication without relying on internet or cellular infrastructure. The firmware enables text messaging, location sharing, and telemetry over a decentralized mesh network.
|
||||
Meshtastic is an open-source LoRa mesh networking project for long-range, low-power communication without relying on internet or cellular infrastructure. The firmware enables text messaging, location sharing, and telemetry over a decentralized mesh network. The project uses **C++17** as its language standard across all platforms.
|
||||
|
||||
### Supported Hardware Platforms
|
||||
|
||||
- **ESP32** (ESP32, ESP32-S3, ESP32-C3) - Most common platform
|
||||
- **ESP32** (ESP32, ESP32-S3, ESP32-C3, ESP32-C6) - Most common platform
|
||||
- **nRF52** (nRF52840, nRF52833) - Low power Nordic chips
|
||||
- **RP2040/RP2350** - Raspberry Pi Pico variants
|
||||
- **STM32WL** - STM32 with integrated LoRa
|
||||
@@ -80,21 +80,46 @@ firmware/
|
||||
│ │ ├── NodeDB.* # Node database management
|
||||
│ │ ├── Router.* # Packet routing
|
||||
│ │ ├── Channels.* # Channel management
|
||||
│ │ ├── CryptoEngine.* # AES-CCM encryption
|
||||
│ │ ├── *Interface.* # Radio interface implementations
|
||||
│ │ ├── api/ # WiFi/Ethernet server APIs (ServerAPI, PacketAPI)
|
||||
│ │ ├── http/ # HTTP server (WebServer, ContentHandler)
|
||||
│ │ ├── wifi/ # WiFi support (WiFiAPClient)
|
||||
│ │ ├── eth/ # Ethernet support (ethClient)
|
||||
│ │ ├── udp/ # UDP multicast
|
||||
│ │ ├── compression/ # Message compression (unishox2)
|
||||
│ │ └── generated/ # Protobuf generated code
|
||||
│ ├── modules/ # Feature modules (Position, Telemetry, etc.)
|
||||
│ │ └── Telemetry/ # Telemetry subsystem
|
||||
│ │ └── Sensor/ # 50+ I2C sensor drivers
|
||||
│ ├── gps/ # GPS handling
|
||||
│ ├── graphics/ # Display drivers and UI
|
||||
│ ├── platform/ # Platform-specific code
|
||||
│ ├── input/ # Input device handling
|
||||
│ └── concurrency/ # Threading utilities
|
||||
│ │ └── niche/ # Specialized UIs (InkHUD e-ink framework)
|
||||
│ ├── platform/ # Platform-specific code (esp32, nrf52, rp2xx0, stm32wl, portduino)
|
||||
│ ├── input/ # Input device handling (InputBroker, keyboards, buttons)
|
||||
│ ├── detect/ # I2C hardware auto-detection (80+ device types)
|
||||
│ ├── motion/ # Accelerometer drivers (BMA423, BMI270, MPU6050, etc.)
|
||||
│ ├── mqtt/ # MQTT bridge client
|
||||
│ ├── power/ # Power HAL
|
||||
│ ├── nimble/ # BLE via NimBLE
|
||||
│ ├── buzz/ # Audio/notification (buzzer, RTTTL)
|
||||
│ ├── serialization/ # JSON serialization, COBS encoding
|
||||
│ ├── watchdog/ # Hardware watchdog thread
|
||||
│ ├── concurrency/ # Threading utilities (OSThread, Lock)
|
||||
│ ├── PowerFSM.* # Power finite state machine
|
||||
│ └── Observer.h # Observer/Observable event pattern
|
||||
├── variants/ # Hardware variant definitions
|
||||
│ ├── esp32/ # ESP32 variants
|
||||
│ ├── esp32s3/ # ESP32-S3 variants
|
||||
│ ├── nrf52/ # nRF52 variants
|
||||
│ └── rp2xxx/ # RP2040/RP2350 variants
|
||||
│ ├── esp32c3/ # ESP32-C3 variants
|
||||
│ ├── esp32c6/ # ESP32-C6 variants
|
||||
│ ├── nrf52840/ # nRF52 variants
|
||||
│ ├── rp2040/ # RP2040/RP2350 variants
|
||||
│ ├── stm32/ # STM32WL variants
|
||||
│ └── native/ # Linux/Portduino variants
|
||||
├── protobufs/ # Protocol buffer definitions
|
||||
├── boards/ # Custom PlatformIO board definitions
|
||||
├── test/ # Unit tests (12 test suites)
|
||||
└── bin/ # Build and utility scripts
|
||||
```
|
||||
|
||||
@@ -105,6 +130,7 @@ firmware/
|
||||
- Follow existing code style - run `trunk fmt` before commits
|
||||
- Prefer `LOG_DEBUG`, `LOG_INFO`, `LOG_WARN`, `LOG_ERROR` for logging
|
||||
- Use `assert()` for invariants that should never fail
|
||||
- C++17 features are available (`std::optional`, structured bindings, `if constexpr`, etc.)
|
||||
|
||||
### Naming Conventions
|
||||
|
||||
@@ -118,70 +144,151 @@ firmware/
|
||||
|
||||
#### Module System
|
||||
|
||||
Modules inherit from `MeshModule` or `ProtobufModule<T>` and implement:
|
||||
Modules use a three-tier class hierarchy:
|
||||
|
||||
- `handleReceivedProtobuf()` - Process incoming packets
|
||||
- `allocReply()` - Generate response packets
|
||||
- `runOnce()` - Periodic task execution (returns next run interval in ms)
|
||||
1. **`MeshModule`** - Base class. Implement `wantPacket()` and `handleReceived()`. Returns `ProcessMessage::STOP` or `ProcessMessage::CONTINUE`.
|
||||
2. **`SinglePortModule`** - Handles a single portnum. Simplified `wantPacket()` that checks `decoded.portnum`.
|
||||
3. **`ProtobufModule<T>`** - Template for protobuf-based modules. Handles encoding/decoding automatically.
|
||||
|
||||
Most modules also inherit from **`OSThread`** for periodic tasks (the "mixin" pattern):
|
||||
|
||||
```cpp
|
||||
class MyModule : public ProtobufModule<meshtastic_MyMessage>
|
||||
class MyModule : public ProtobufModule<meshtastic_MyMessage>, private concurrency::OSThread
|
||||
{
|
||||
public:
|
||||
MyModule();
|
||||
|
||||
protected:
|
||||
virtual bool handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshtastic_MyMessage *msg) override;
|
||||
virtual int32_t runOnce() override;
|
||||
virtual meshtastic_MeshPacket *allocReply() override; // Generate response packets
|
||||
virtual int32_t runOnce() override; // Periodic task (returns next interval in ms)
|
||||
virtual bool alterReceivedProtobuf(meshtastic_MeshPacket &mp, meshtastic_MyMessage *msg); // Modify in-flight
|
||||
virtual bool wantUIFrame(); // Request a UI display frame
|
||||
};
|
||||
```
|
||||
|
||||
Modules are registered in `src/modules/Modules.cpp` guarded by `MESHTASTIC_EXCLUDE_*` flags.
|
||||
|
||||
#### Observer/Observable Pattern
|
||||
|
||||
Event-driven communication between subsystems uses `src/Observer.h`:
|
||||
|
||||
```cpp
|
||||
// Observable emits events
|
||||
Observable<const meshtastic::Status *> newStatus;
|
||||
newStatus.notifyObservers(&status);
|
||||
|
||||
// Observer receives events via callback
|
||||
CallbackObserver<MyClass, const meshtastic::Status *> statusObserver =
|
||||
CallbackObserver<MyClass, const meshtastic::Status *>(this, &MyClass::handleStatusUpdate);
|
||||
```
|
||||
|
||||
#### Configuration Access
|
||||
|
||||
- `config.*` - Device configuration (LoRa, position, power, etc.)
|
||||
- `moduleConfig.*` - Module-specific configuration
|
||||
- `channels.*` - Channel configuration and management
|
||||
- `owner` - Device owner info
|
||||
- `myNodeInfo` - Local node info
|
||||
|
||||
#### Default Values
|
||||
|
||||
Use the `Default` class helpers in `src/mesh/Default.h`:
|
||||
|
||||
- `Default::getConfiguredOrDefaultMs(configured, default)` - Returns ms, using default if configured is 0
|
||||
- `Default::getConfiguredOrDefault(configured, default)` - Generic configured/default getter
|
||||
- `Default::getConfiguredOrMinimumValue(configured, min)` - Enforces minimum values
|
||||
- `Default::getConfiguredOrDefaultMsScaled(configured, default, numNodes)` - Scales based on network size
|
||||
|
||||
#### Thread Safety
|
||||
|
||||
- Use `concurrency::Lock` for mutex protection
|
||||
- Use `concurrency::Lock` and `concurrency::LockGuard` for mutex protection
|
||||
- Radio SPI access uses `SPILock`
|
||||
- Prefer `OSThread` for background tasks
|
||||
|
||||
### Hardware Detection
|
||||
|
||||
`src/detect/ScanI2C` automatically enumerates 80+ I2C device types at boot including displays, sensors, RTCs, keyboards, PMUs, and touch controllers. This drives automatic initialization of the correct drivers.
|
||||
|
||||
### Graphics/UI System
|
||||
|
||||
Multiple display driver families in `src/graphics/`:
|
||||
|
||||
- **OLED**: SSD1306, SH1106, ST7567
|
||||
- **TFT**: TFTDisplay (LovyanGFX-based)
|
||||
- **E-Ink**: EInkDisplay2, EInkDynamicDisplay, EInkParallelDisplay
|
||||
|
||||
**InkHUD** (`src/graphics/niche/InkHUD/`) is an event-driven e-ink UI framework:
|
||||
|
||||
- Applet-based architecture — modular display tiles
|
||||
- Read-only, static display optimized for minimal refreshes and low power
|
||||
- Configured per-variant via `nicheGraphics.h`
|
||||
- Separate PlatformIO config: `src/graphics/niche/InkHUD/PlatformioConfig.ini`
|
||||
|
||||
### Input System
|
||||
|
||||
`src/input/InputBroker` is the centralized input event dispatcher. Supports multiple input sources: buttons, keyboards (BBQ10, Cardputer, TCA8418), touch screens, rotary encoders, and matrix keyboards.
|
||||
|
||||
### Power Management
|
||||
|
||||
`src/PowerFSM.*` implements a finite state machine with states: `stateON`, `statePOWER`, `stateSERIAL`, `stateDARK`. Key events: `EVENT_PRESS`, `EVENT_WAKE_TIMER`, `EVENT_LOW_BATTERY`, `EVENT_RECEIVED_MSG`, `EVENT_SHUTDOWN`. Conditionally excluded with `MESHTASTIC_EXCLUDE_POWER_FSM` (falls back to `FakeFsm`).
|
||||
|
||||
### Motion Sensors
|
||||
|
||||
`src/motion/AccelerometerThread` provides background motion monitoring with automatic screen wake and double-tap button press detection. Supports 10+ accelerometer/gyroscope chips (BMA423, BMI270, MPU6050, LIS3DH, LSM6DS3, STK8XXX, QMA6100P, ICM20948, BMX160).
|
||||
|
||||
### Telemetry Sensor Library
|
||||
|
||||
`src/modules/Telemetry/Sensor/` contains 50+ I2C sensor drivers organized by category:
|
||||
|
||||
- **Power monitoring**: INA219/226/260/3221, MAX17048
|
||||
- **Environmental**: BME280/680, SCD4X (CO₂), SEN5X (particulate)
|
||||
- **Humidity/Temperature**: SHT3X/4X, AHT10, MCP9808, MLX90614
|
||||
- **Light**: BH1750, TSL2561/2591, VEML7700, LTR390UV, OPT3001
|
||||
- **Air quality**: PMSA003I, SFA30
|
||||
- **Specialized**: CGRadSens (radiation), NAU7802 (weight scale)
|
||||
|
||||
### API/Networking
|
||||
|
||||
`src/mesh/api/` provides a template-based `ServerAPI` for client communication over WiFi (`WiFiServerAPI`) and Ethernet (`ethServerAPI`). Default port: **4403**. HTTP server in `src/mesh/http/`. JSON serialization in `src/serialization/MeshPacketSerializer`.
|
||||
|
||||
### Hardware Variants
|
||||
|
||||
Each hardware variant has:
|
||||
|
||||
- `variant.h` - Pin definitions and hardware capabilities
|
||||
- `platformio.ini` - Build configuration
|
||||
- Optional: `pins_arduino.h`, `rfswitch.h`
|
||||
- Optional: `pins_arduino.h`, `rfswitch.h`, `nicheGraphics.h` (for InkHUD variants)
|
||||
|
||||
Key defines in variant.h:
|
||||
|
||||
```cpp
|
||||
#define USE_SX1262 // Radio chip selection
|
||||
#define HAS_GPS 1 // Hardware capabilities
|
||||
#define HAS_SCREEN 1 // Display present
|
||||
#define LORA_CS 36 // Pin assignments
|
||||
#define SX126X_DIO1 14 // Radio-specific pins
|
||||
```
|
||||
|
||||
### Protobuf Messages
|
||||
|
||||
- Defined in `protobufs/meshtastic/*.proto`
|
||||
- Generated code in `src/mesh/generated/`
|
||||
- Defined in `protobufs/meshtastic/*.proto` (~32 proto files)
|
||||
- Generated code in `src/mesh/generated/meshtastic/`
|
||||
- Regenerate with `bin/regen-protos.sh`
|
||||
- Message types prefixed with `meshtastic_`
|
||||
- Nanopb `.options` files control field sizes and encoding
|
||||
|
||||
### Conditional Compilation
|
||||
|
||||
```cpp
|
||||
#if !MESHTASTIC_EXCLUDE_GPS // Feature exclusion
|
||||
#if !MESHTASTIC_EXCLUDE_WIFI // Network feature exclusion
|
||||
#if !MESHTASTIC_EXCLUDE_BLUETOOTH // BLE exclusion
|
||||
#if !MESHTASTIC_EXCLUDE_POWER_FSM // Power FSM exclusion
|
||||
#ifdef ARCH_ESP32 // Architecture-specific
|
||||
#ifdef ARCH_NRF52 // Nordic platform
|
||||
#ifdef ARCH_RP2040 // Raspberry Pi Pico
|
||||
#ifdef ARCH_PORTDUINO // Linux native
|
||||
#if defined(USE_SX1262) // Radio-specific
|
||||
#ifdef HAS_SCREEN // Hardware capability
|
||||
#if USERPREFS_EVENT_MODE // User preferences
|
||||
@@ -192,7 +299,7 @@ Key defines in variant.h:
|
||||
Uses **PlatformIO** with custom scripts:
|
||||
|
||||
- `bin/platformio-pre.py` - Pre-build script
|
||||
- `bin/platformio-custom.py` - Custom build logic
|
||||
- `bin/platformio-custom.py` - Custom build logic, manifest generation
|
||||
|
||||
Build commands:
|
||||
|
||||
@@ -202,21 +309,38 @@ pio run -e tbeam -t upload # Build and upload
|
||||
pio run -e native # Build native/Linux version
|
||||
```
|
||||
|
||||
### Build Manifest
|
||||
|
||||
`bin/platformio-custom.py` emits a build manifest with metadata:
|
||||
|
||||
- `hasMui`, `hasInkHud` - UI capability flags (overridable via `custom_meshtastic_has_mui`, `custom_meshtastic_has_ink_hud`)
|
||||
- Architecture normalization (e.g., `esp32s3` → `esp32-s3` for API compatibility)
|
||||
|
||||
## Common Tasks
|
||||
|
||||
### Adding a New Module
|
||||
|
||||
1. Create `src/modules/MyModule.cpp` and `.h`
|
||||
2. Inherit from appropriate base class
|
||||
3. Register in `src/modules/Modules.cpp`
|
||||
4. Add protobuf messages if needed in `protobufs/`
|
||||
2. Inherit from appropriate base class (`MeshModule`, `SinglePortModule`, or `ProtobufModule<T>`)
|
||||
3. Mix in `concurrency::OSThread` if periodic work is needed
|
||||
4. Register in `src/modules/Modules.cpp` guarded by `#if !MESHTASTIC_EXCLUDE_MYMODULE`
|
||||
5. Add protobuf messages if needed in `protobufs/meshtastic/`
|
||||
6. Add test suite in `test/test_mymodule/` if applicable
|
||||
|
||||
### Adding a New Hardware Variant
|
||||
|
||||
1. Create directory under `variants/<arch>/<name>/`
|
||||
2. Add `variant.h` with pin definitions
|
||||
3. Add `platformio.ini` with build config
|
||||
4. Reference common configs with `extends`
|
||||
2. Add `variant.h` with pin definitions and hardware capability defines
|
||||
3. Add `platformio.ini` with build config — use `extends` to reference common base (e.g., `esp32s3_base`)
|
||||
4. Set `custom_meshtastic_support_level = 1` (PR builds) or `2` (merge builds)
|
||||
5. For e-ink displays, add `nicheGraphics.h` for InkHUD configuration
|
||||
|
||||
### Adding a New Telemetry Sensor
|
||||
|
||||
1. Create driver in `src/modules/Telemetry/Sensor/` following existing sensor pattern
|
||||
2. Register I2C address in `src/detect/ScanI2C` for auto-detection
|
||||
3. Integrate with the appropriate telemetry module (Environment, Health, Power, AirQuality)
|
||||
4. Add proto fields in `protobufs/meshtastic/telemetry.proto` if new data types are needed
|
||||
|
||||
### Modifying Configuration Defaults
|
||||
|
||||
@@ -305,9 +429,22 @@ Most workflows can be triggered manually via `workflow_dispatch` for testing.
|
||||
|
||||
## Testing
|
||||
|
||||
- Unit tests in `test/` directory
|
||||
- Run with `pio test -e native`
|
||||
- Use `bin/test-simulator.sh` for simulation testing
|
||||
Unit tests in `test/` directory with 12 test suites:
|
||||
|
||||
- `test_crypto/` - Cryptography
|
||||
- `test_mqtt/` - MQTT integration
|
||||
- `test_radio/` - Radio interface
|
||||
- `test_mesh_module/` - Module framework
|
||||
- `test_meshpacket_serializer/` - Packet serialization
|
||||
- `test_transmit_history/` - Retransmission tracking
|
||||
- `test_atak/` - ATAK integration
|
||||
- `test_default/` - Default configuration
|
||||
- `test_http_content_handler/` - HTTP handling
|
||||
- `test_serial/` - Serial communication
|
||||
|
||||
Run with: `pio test -e native`
|
||||
|
||||
Simulation testing: `bin/test-simulator.sh`
|
||||
|
||||
## Resources
|
||||
|
||||
|
||||
138
.github/prompts/new-module.prompt.md
vendored
Normal file
138
.github/prompts/new-module.prompt.md
vendored
Normal file
@@ -0,0 +1,138 @@
|
||||
# New Meshtastic Module
|
||||
|
||||
Guide for developing a new Meshtastic firmware module.
|
||||
|
||||
## Module Hierarchy
|
||||
|
||||
Choose the appropriate base class:
|
||||
|
||||
1. **`MeshModule`** — Raw base class. Override `wantPacket()` and `handleReceived()`. Returns `ProcessMessage::STOP` or `ProcessMessage::CONTINUE`.
|
||||
2. **`SinglePortModule`** — Handles a single `meshtastic_PortNum`. Constructor takes `(name, portNum)`. Simplified `wantPacket()` checking `decoded.portnum`. Use `allocDataPacket()` to create outgoing packets.
|
||||
3. **`ProtobufModule<T>`** — Template for protobuf-encoded modules. Constructor takes `(name, portNum, fields)`. Override `handleReceivedProtobuf()`. Use `allocDataProtobuf(payload)` to create outgoing packets.
|
||||
|
||||
Most modules also mix in `concurrency::OSThread` for periodic background tasks.
|
||||
|
||||
## Implementation Pattern
|
||||
|
||||
```cpp
|
||||
// src/modules/MyModule.h
|
||||
#pragma once
|
||||
#include "ProtobufModule.h"
|
||||
#include "concurrency/OSThread.h"
|
||||
|
||||
class MyModule : public ProtobufModule<meshtastic_MyMessage>, private concurrency::OSThread
|
||||
{
|
||||
public:
|
||||
MyModule();
|
||||
|
||||
protected:
|
||||
// Process incoming protobuf packet. Return true to stop further processing.
|
||||
virtual bool handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshtastic_MyMessage *msg) override;
|
||||
|
||||
// Generate response packet (optional)
|
||||
virtual meshtastic_MeshPacket *allocReply() override;
|
||||
|
||||
// Periodic task — return next run interval in ms, or disable()
|
||||
virtual int32_t runOnce() override;
|
||||
|
||||
// Modify packet in-flight before delivery (optional)
|
||||
virtual bool alterReceivedProtobuf(meshtastic_MeshPacket &mp, meshtastic_MyMessage *msg);
|
||||
|
||||
// Request a UI display frame (optional)
|
||||
virtual bool wantUIFrame();
|
||||
};
|
||||
```
|
||||
|
||||
## Registration
|
||||
|
||||
Register in `src/modules/Modules.cpp` inside `setupModules()`:
|
||||
|
||||
```cpp
|
||||
#if !MESHTASTIC_EXCLUDE_MYMODULE
|
||||
new MyModule();
|
||||
#endif
|
||||
```
|
||||
|
||||
If other code needs to reference the module instance:
|
||||
|
||||
```cpp
|
||||
#if !MESHTASTIC_EXCLUDE_MYMODULE
|
||||
myModule = new MyModule();
|
||||
#endif
|
||||
```
|
||||
|
||||
And declare the global in the header:
|
||||
|
||||
```cpp
|
||||
extern MyModule *myModule;
|
||||
```
|
||||
|
||||
Some modules also conditionally instantiate based on `moduleConfig`:
|
||||
|
||||
```cpp
|
||||
#if !MESHTASTIC_EXCLUDE_MYMODULE
|
||||
if (moduleConfig.has_my_module && moduleConfig.my_module.enabled) {
|
||||
new MyModule();
|
||||
}
|
||||
#endif
|
||||
```
|
||||
|
||||
## Conditional Compilation
|
||||
|
||||
Add a `MESHTASTIC_EXCLUDE_MYMODULE` guard. This allows the module to be excluded from constrained builds. The flag name must follow the pattern: `MESHTASTIC_EXCLUDE_` + uppercase module name.
|
||||
|
||||
## Protobuf Messages (if needed)
|
||||
|
||||
1. Define messages in `protobufs/meshtastic/` (e.g., `mymodule.proto`)
|
||||
2. Add a `.options` file for nanopb field size constraints
|
||||
3. Regenerate with `bin/regen-protos.sh`
|
||||
4. Generated code appears in `src/mesh/generated/meshtastic/`
|
||||
5. Assign a `meshtastic_PortNum` if the module uses a new port number
|
||||
|
||||
## Timing and Defaults
|
||||
|
||||
Use `Default` class helpers for configurable intervals:
|
||||
|
||||
```cpp
|
||||
int32_t MyModule::runOnce()
|
||||
{
|
||||
uint32_t interval = Default::getConfiguredOrDefaultMs(moduleConfig.my_module.update_interval,
|
||||
default_my_module_interval);
|
||||
// ... do work ...
|
||||
return interval;
|
||||
}
|
||||
```
|
||||
|
||||
On public/default channels, enforce minimums with `Default::getConfiguredOrMinimumValue()`.
|
||||
|
||||
## Observer Pattern
|
||||
|
||||
Subscribe to system events:
|
||||
|
||||
```cpp
|
||||
CallbackObserver<MyModule, const meshtastic::Status *> statusObserver =
|
||||
CallbackObserver<MyModule, const meshtastic::Status *>(this, &MyModule::handleStatusUpdate);
|
||||
```
|
||||
|
||||
## Testing
|
||||
|
||||
Add test suite in `test/test_mymodule/`:
|
||||
|
||||
```
|
||||
test/
|
||||
└── test_mymodule/
|
||||
└── test_main.cpp
|
||||
```
|
||||
|
||||
Run with: `pio test -e native`
|
||||
|
||||
## Checklist
|
||||
|
||||
- [ ] Header and implementation files in `src/modules/`
|
||||
- [ ] Inherit from appropriate base class (MeshModule / SinglePortModule / ProtobufModule)
|
||||
- [ ] Mix in OSThread if periodic work is needed
|
||||
- [ ] Register in `src/modules/Modules.cpp` with `MESHTASTIC_EXCLUDE_` guard
|
||||
- [ ] Add protobuf definitions if needed (`protobufs/meshtastic/`)
|
||||
- [ ] Use `Default::getConfiguredOrDefaultMs()` for timing
|
||||
- [ ] Respect bandwidth limits on public channels
|
||||
- [ ] Add test suite in `test/`
|
||||
149
.github/prompts/new-sensor.prompt.md
vendored
Normal file
149
.github/prompts/new-sensor.prompt.md
vendored
Normal file
@@ -0,0 +1,149 @@
|
||||
# New Telemetry Sensor
|
||||
|
||||
Guide for adding a new I2C telemetry sensor driver to Meshtastic firmware.
|
||||
|
||||
## Overview
|
||||
|
||||
Telemetry sensors live in `src/modules/Telemetry/Sensor/`. There are 50+ existing drivers organized by measurement type. Each sensor integrates with one of the telemetry modules:
|
||||
|
||||
- **EnvironmentTelemetryModule** — Temperature, humidity, pressure, gas, light
|
||||
- **AirQualityTelemetryModule** — Particulate matter, VOCs
|
||||
- **PowerTelemetryModule** — Voltage, current, power monitoring
|
||||
- **HealthTelemetryModule** — Heart rate, SpO2, body temperature
|
||||
|
||||
## Sensor Driver Pattern
|
||||
|
||||
Each sensor has a `.h` and `.cpp` file pair following this pattern:
|
||||
|
||||
```cpp
|
||||
// src/modules/Telemetry/Sensor/MySensor.h
|
||||
#pragma once
|
||||
#include "TelemetrySensor.h"
|
||||
#include <MySensorLibrary.h> // Arduino/PlatformIO library
|
||||
|
||||
class MySensor : virtual public TelemetrySensor
|
||||
{
|
||||
private:
|
||||
MySensorLibrary sensor;
|
||||
|
||||
public:
|
||||
MySensor() : TelemetrySensor(meshtastic_TelemetrySensorType_MY_SENSOR, "MySensor") {}
|
||||
|
||||
// Initialize sensor hardware. Return true on success.
|
||||
virtual void setup() override;
|
||||
|
||||
// Read sensor data into the telemetry protobuf. Return true on success.
|
||||
virtual bool getMetrics(meshtastic_Telemetry *measurement) override;
|
||||
};
|
||||
```
|
||||
|
||||
```cpp
|
||||
// src/modules/Telemetry/Sensor/MySensor.cpp
|
||||
#include "MySensor.h"
|
||||
#include "TelemetrySensor.h"
|
||||
|
||||
void MySensor::setup()
|
||||
{
|
||||
sensor.begin();
|
||||
// Configure sensor parameters...
|
||||
}
|
||||
|
||||
bool MySensor::getMetrics(meshtastic_Telemetry *measurement)
|
||||
{
|
||||
// Read from hardware
|
||||
float value = sensor.readValue();
|
||||
|
||||
// Populate the appropriate protobuf variant
|
||||
measurement->variant.environment_metrics.temperature = value;
|
||||
// ... other fields ...
|
||||
|
||||
return true;
|
||||
}
|
||||
```
|
||||
|
||||
## I2C Address Registration
|
||||
|
||||
Register the sensor's I2C address(es) in `src/detect/ScanI2C` so it's auto-detected at boot:
|
||||
|
||||
1. Add a `DeviceType` enum entry in `src/detect/ScanI2C.h`
|
||||
2. Add the I2C address mapping in `src/detect/ScanI2CTwoWire.cpp`
|
||||
|
||||
The scan runs at boot and populates a device map that telemetry modules use to decide which sensors to initialize.
|
||||
|
||||
## Protobuf Fields
|
||||
|
||||
If the sensor provides data not covered by existing telemetry fields:
|
||||
|
||||
1. Add fields to the appropriate message in `protobufs/meshtastic/telemetry.proto`:
|
||||
- `EnvironmentMetrics` — Environmental measurements
|
||||
- `AirQualityMetrics` — Air quality data
|
||||
- `PowerMetrics` — Power/energy data
|
||||
- `HealthMetrics` — Health/biometric data
|
||||
2. Add a `.options` constraint if needed (field sizes for nanopb)
|
||||
3. Regenerate: `bin/regen-protos.sh`
|
||||
|
||||
## Sensor Type Enum
|
||||
|
||||
Add the sensor to `meshtastic_TelemetrySensorType` enum in `protobufs/meshtastic/telemetry.proto`:
|
||||
|
||||
```protobuf
|
||||
enum TelemetrySensorType {
|
||||
// ... existing entries ...
|
||||
MY_SENSOR = XX;
|
||||
}
|
||||
```
|
||||
|
||||
## Integration with Telemetry Module
|
||||
|
||||
Wire the sensor into the appropriate telemetry module. For environment sensors, this is typically in `src/modules/Telemetry/EnvironmentTelemetry.cpp`:
|
||||
|
||||
1. Include the sensor header
|
||||
2. Add initialization in `setupSensor()` guarded by detection results
|
||||
3. Call `getMetrics()` in the measurement collection path
|
||||
|
||||
Example pattern from existing sensors:
|
||||
|
||||
```cpp
|
||||
#include "Sensor/MySensor.h"
|
||||
|
||||
MySensor mySensor;
|
||||
|
||||
// In setup:
|
||||
if (nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_MY_SENSOR].first > 0) {
|
||||
mySensor.setup();
|
||||
}
|
||||
|
||||
// In measurement collection:
|
||||
if (nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_MY_SENSOR].first > 0) {
|
||||
mySensor.getMetrics(&measurement);
|
||||
}
|
||||
```
|
||||
|
||||
## Library Dependencies
|
||||
|
||||
If the sensor needs an external library, add it to the `lib_deps` in the relevant base platformio.ini configs:
|
||||
|
||||
```ini
|
||||
lib_deps =
|
||||
${env.lib_deps}
|
||||
mysensorlibrary@^1.0.0
|
||||
```
|
||||
|
||||
Or use a conditional dependency if it's platform-specific.
|
||||
|
||||
## Unit Conversions
|
||||
|
||||
If the sensor reports values in non-standard units, use `src/modules/Telemetry/UnitConversions.h` for conversion helpers (e.g., Celsius ↔ Fahrenheit, hPa ↔ inHg).
|
||||
|
||||
## Checklist
|
||||
|
||||
- [ ] Create `src/modules/Telemetry/Sensor/MySensor.h` and `.cpp`
|
||||
- [ ] Inherit from `TelemetrySensor` base class
|
||||
- [ ] Implement `setup()` and `getMetrics()` methods
|
||||
- [ ] Add `meshtastic_TelemetrySensorType` enum entry in `telemetry.proto`
|
||||
- [ ] Add I2C address to `src/detect/ScanI2C` for auto-detection
|
||||
- [ ] Add protobuf fields in `telemetry.proto` if new data types needed
|
||||
- [ ] Regenerate protos: `bin/regen-protos.sh`
|
||||
- [ ] Wire into the appropriate telemetry module (Environment/AirQuality/Power/Health)
|
||||
- [ ] Add library dependency if external library required
|
||||
- [ ] Test on hardware or native build
|
||||
178
.github/prompts/new-variant.prompt.md
vendored
Normal file
178
.github/prompts/new-variant.prompt.md
vendored
Normal file
@@ -0,0 +1,178 @@
|
||||
# New Hardware Variant
|
||||
|
||||
Guide for adding a new Meshtastic hardware variant to the firmware.
|
||||
|
||||
## Directory Structure
|
||||
|
||||
Create under `variants/<arch>/<name>/`:
|
||||
|
||||
```
|
||||
variants/
|
||||
├── esp32/ # ESP32
|
||||
├── esp32s3/ # ESP32-S3
|
||||
├── esp32c3/ # ESP32-C3
|
||||
├── esp32c6/ # ESP32-C6
|
||||
├── nrf52840/ # nRF52840
|
||||
├── rp2040/ # RP2040/RP2350
|
||||
├── stm32/ # STM32WL
|
||||
└── native/ # Linux/Portduino
|
||||
```
|
||||
|
||||
Each variant needs at minimum:
|
||||
|
||||
- `variant.h` — Pin definitions and hardware capabilities
|
||||
- `platformio.ini` — Build configuration
|
||||
|
||||
Optional files:
|
||||
|
||||
- `pins_arduino.h` — Arduino pin mapping overrides
|
||||
- `rfswitch.h` — RF switch control for multi-band radios
|
||||
- `nicheGraphics.h` — InkHUD e-ink configuration
|
||||
|
||||
## variant.h Template
|
||||
|
||||
```cpp
|
||||
// Pin definitions
|
||||
#define I2C_SDA 21
|
||||
#define I2C_SCL 22
|
||||
|
||||
// LoRa radio
|
||||
#define USE_SX1262 // Radio chip: USE_SX1262, USE_SX1268, USE_SX1280, USE_RF95, USE_LLCC68, USE_LR1110, USE_LR1120, USE_LR1121
|
||||
#define LORA_CS 18
|
||||
#define LORA_SCK 5
|
||||
#define LORA_MOSI 27
|
||||
#define LORA_MISO 19
|
||||
#define LORA_DIO1 33 // SX126x: DIO1, SX128x: DIO1, RF95: IRQ
|
||||
#define LORA_RESET 23
|
||||
#define LORA_BUSY 32 // SX126x/SX128x only
|
||||
#define SX126X_DIO2_AS_RF_SWITCH // Common for SX1262 boards
|
||||
|
||||
// GPS
|
||||
#define HAS_GPS 1
|
||||
#define GPS_RX_PIN 34
|
||||
#define GPS_TX_PIN 12
|
||||
// #define PIN_GPS_EN 47 // Optional GPS enable pin
|
||||
// #define GPS_BAUDRATE 9600 // Override default 9600
|
||||
|
||||
// Display
|
||||
#define HAS_SCREEN 1
|
||||
// #define USE_SSD1306 // OLED type
|
||||
// #define USE_SH1106 // Alternative OLED
|
||||
// #define USE_ST7789 // TFT type
|
||||
// #define SCREEN_WIDTH 128
|
||||
// #define SCREEN_HEIGHT 64
|
||||
|
||||
// LEDs
|
||||
#define LED_PIN 2 // Status LED (optional)
|
||||
// #define HAS_NEOPIXEL 1 // WS2812 support
|
||||
|
||||
// Buttons
|
||||
#define BUTTON_PIN 38
|
||||
// #define BUTTON_PIN_ALT 0 // Secondary button
|
||||
|
||||
// Power management
|
||||
// #define HAS_AXP192 1 // AXP192 PMU (T-Beam v1.0)
|
||||
// #define HAS_AXP2101 1 // AXP2101 PMU (T-Beam v1.2+)
|
||||
// #define BATTERY_PIN 35 // ADC battery voltage pin
|
||||
// #define ADC_MULTIPLIER 2.0 // Voltage divider ratio
|
||||
|
||||
// Optional I2C devices
|
||||
// #define HAS_RTC 1 // Real-time clock
|
||||
// #define HAS_TELEMETRY 1 // Enable telemetry sensor support
|
||||
// #define HAS_SENSOR 1 // I2C sensors present
|
||||
```
|
||||
|
||||
## platformio.ini Template
|
||||
|
||||
```ini
|
||||
[env:my_variant]
|
||||
extends = esp32s3_base ; Use architecture-specific base
|
||||
board = esp32-s3-devkitc-1 ; PlatformIO board definition (or custom in boards/)
|
||||
board_level = extra ; Build level: extra, or omit for default
|
||||
custom_meshtastic_support_level = 1 ; 1 = PR builds, 2 = merge builds only
|
||||
|
||||
build_flags =
|
||||
${esp32s3_base.build_flags}
|
||||
-D MY_VARIANT_SPECIFIC_FLAG=1
|
||||
-I variants/esp32s3/my_variant ; Include path for variant.h
|
||||
|
||||
upload_speed = 921600
|
||||
```
|
||||
|
||||
### Common Base Configs
|
||||
|
||||
- `esp32_base` / `esp32-common.ini` — ESP32
|
||||
- `esp32s3_base` — ESP32-S3
|
||||
- `esp32c3_base` — ESP32-C3
|
||||
- `esp32c6_base` — ESP32-C6
|
||||
- `nrf52840_base` / `nrf52.ini` — nRF52840
|
||||
- `rp2040_base` — RP2040/RP2350
|
||||
|
||||
### Support Levels
|
||||
|
||||
- `custom_meshtastic_support_level = 1` — Built on every PR (actively supported)
|
||||
- `custom_meshtastic_support_level = 2` — Built only on merge to main branches
|
||||
- `board_level = extra` — Only built on full releases
|
||||
|
||||
## Build Manifest Metadata
|
||||
|
||||
`bin/platformio-custom.py` emits UI capability flags in the build manifest:
|
||||
|
||||
- `custom_meshtastic_has_mui = true/false` — Override MUI detection
|
||||
- `custom_meshtastic_has_ink_hud = true/false` — Override InkHUD detection
|
||||
- Architecture names are normalized (e.g., `esp32s3` → `esp32-s3`)
|
||||
|
||||
## InkHUD E-Ink Variants
|
||||
|
||||
For e-ink display variants using the InkHUD framework, add `nicheGraphics.h`:
|
||||
|
||||
```cpp
|
||||
// nicheGraphics.h — InkHUD configuration for this variant
|
||||
#define INKHUD // Enable InkHUD
|
||||
// Configure display, applets, and refresh behavior per device
|
||||
```
|
||||
|
||||
InkHUD has its own PlatformIO config: `src/graphics/niche/InkHUD/PlatformioConfig.ini`
|
||||
|
||||
## I2C Device Detection
|
||||
|
||||
If the variant has I2C devices, ensure `src/detect/ScanI2C` will detect them. The auto-detection system handles 80+ device types including displays, sensors, RTCs, keyboards, PMUs, and touch controllers at boot.
|
||||
|
||||
## Custom Board Definitions
|
||||
|
||||
If the PlatformIO board doesn't exist, create a custom board JSON in `boards/`:
|
||||
|
||||
```json
|
||||
{
|
||||
"build": {
|
||||
"arduino": { "ldscript": "esp32s3_out.ld" },
|
||||
"core": "esp32",
|
||||
"f_cpu": "240000000L",
|
||||
"f_flash": "80000000L",
|
||||
"flash_mode": "qio",
|
||||
"mcu": "esp32s3",
|
||||
"variant": "esp32s3"
|
||||
},
|
||||
"connectivity": ["wifi", "bluetooth"],
|
||||
"frameworks": ["arduino", "espidf"],
|
||||
"name": "My Custom Board",
|
||||
"upload": {
|
||||
"flash_size": "8MB",
|
||||
"maximum_ram_size": 327680,
|
||||
"maximum_size": 8388608
|
||||
},
|
||||
"url": "https://example.com",
|
||||
"vendor": "MyVendor"
|
||||
}
|
||||
```
|
||||
|
||||
## Checklist
|
||||
|
||||
- [ ] Create `variants/<arch>/<name>/variant.h` with pin definitions
|
||||
- [ ] Create `variants/<arch>/<name>/platformio.ini` extending correct base
|
||||
- [ ] Set `custom_meshtastic_support_level` (1 or 2)
|
||||
- [ ] Verify radio chip define matches hardware (`USE_SX1262`, etc.)
|
||||
- [ ] Set hardware capability flags (`HAS_GPS`, `HAS_SCREEN`, etc.)
|
||||
- [ ] Add custom board JSON in `boards/` if needed
|
||||
- [ ] Test build: `pio run -e my_variant`
|
||||
- [ ] For e-ink: add `nicheGraphics.h` with InkHUD config
|
||||
6
.github/workflows/main_matrix.yml
vendored
6
.github/workflows/main_matrix.yml
vendored
@@ -301,10 +301,12 @@ jobs:
|
||||
id: release_notes
|
||||
run: |
|
||||
chmod +x ./bin/generate_release_notes.py
|
||||
NOTES=$(./bin/generate_release_notes.py ${{ needs.version.outputs.long }})
|
||||
NOTES=$(./bin/generate_release_notes.py ${{ needs.version.outputs.long }} --compare-ref HEAD 2>release_notes.log)
|
||||
echo "notes<<EOF" >> $GITHUB_OUTPUT
|
||||
echo "$NOTES" >> $GITHUB_OUTPUT
|
||||
echo "EOF" >> $GITHUB_OUTPUT
|
||||
echo "### Release note range" >> $GITHUB_STEP_SUMMARY
|
||||
cat release_notes.log >> $GITHUB_STEP_SUMMARY
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
@@ -466,7 +468,7 @@ jobs:
|
||||
- name: Generate release notes
|
||||
run: |
|
||||
chmod +x ./bin/generate_release_notes.py
|
||||
./bin/generate_release_notes.py ${{ needs.version.outputs.long }} > ./publish/release_notes.md
|
||||
./bin/generate_release_notes.py ${{ needs.version.outputs.long }} --compare-ref HEAD > ./publish/release_notes.md
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
# For use with Armbian luckfox-pico-max
|
||||
# Waveshare LoRa HAT for Raspberry Pi Pico
|
||||
# https://www.waveshare.com/wiki/Pico-LoRa-SX1262
|
||||
|
||||
Meta:
|
||||
name: luckfox-pico-max-ws-raspberry-pi-pico-hat
|
||||
support: community
|
||||
compatible:
|
||||
- luckfox-pico-max # Armbian
|
||||
|
||||
Lora:
|
||||
Module: sx1262
|
||||
DIO2_AS_RF_SWITCH: true
|
||||
DIO3_TCXO_VOLTAGE: true
|
||||
spidev: spidev0.0
|
||||
Busy: # GPIO1_C7 / GP2
|
||||
pin: 55
|
||||
gpiochip: 1
|
||||
line: 23
|
||||
CS: # GPIO1_C6 / GP3
|
||||
pin: 54
|
||||
gpiochip: 1
|
||||
line: 22
|
||||
Reset: # GPIO1_D1 / GP15
|
||||
pin: 57
|
||||
gpiochip: 1
|
||||
line: 25
|
||||
IRQ: # GPIO2_A2 / GP20
|
||||
pin: 66
|
||||
gpiochip: 2
|
||||
line: 2
|
||||
@@ -1,25 +1,31 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Generate release notes from merged PRs on develop and master branches.
|
||||
Categorizes PRs into Enhancements and Bug Fixes/Maintenance sections.
|
||||
"""
|
||||
"""Generate release notes from the actual release commit range."""
|
||||
|
||||
import subprocess
|
||||
import re
|
||||
import argparse
|
||||
import json
|
||||
import re
|
||||
import subprocess
|
||||
import sys
|
||||
from datetime import datetime
|
||||
|
||||
|
||||
def get_last_release_tag():
|
||||
"""Get the most recent release tag."""
|
||||
def get_last_release_tag(compare_ref, exclude_tag=None):
|
||||
"""Get the most recent version tag merged into compare_ref."""
|
||||
result = subprocess.run(
|
||||
["git", "describe", "--tags", "--abbrev=0"],
|
||||
["git", "tag", "--merged", compare_ref, "--sort=-version:refname", "v*"],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
check=True,
|
||||
)
|
||||
return result.stdout.strip()
|
||||
|
||||
for line in result.stdout.splitlines():
|
||||
candidate = line.strip()
|
||||
if not candidate:
|
||||
continue
|
||||
if exclude_tag and candidate == exclude_tag:
|
||||
continue
|
||||
return candidate
|
||||
|
||||
raise subprocess.CalledProcessError(result.returncode, result.args, output=result.stdout, stderr=result.stderr)
|
||||
|
||||
|
||||
def get_tag_date(tag):
|
||||
@@ -33,18 +39,18 @@ def get_tag_date(tag):
|
||||
return result.stdout.strip()
|
||||
|
||||
|
||||
def get_merged_prs_since_tag(tag, branch):
|
||||
"""Get all merged PRs since the given tag on the specified branch."""
|
||||
# Get commits since tag on the branch - look for PR numbers in parentheses
|
||||
def get_merged_prs_in_range(tag, compare_ref):
|
||||
"""Get all merged PRs in the git range between tag and compare_ref."""
|
||||
result = subprocess.run(
|
||||
[
|
||||
"git",
|
||||
"log",
|
||||
f"{tag}..origin/{branch}",
|
||||
f"{tag}..{compare_ref}",
|
||||
"--oneline",
|
||||
],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
check=True,
|
||||
)
|
||||
|
||||
prs = []
|
||||
@@ -65,6 +71,25 @@ def get_merged_prs_since_tag(tag, branch):
|
||||
return prs
|
||||
|
||||
|
||||
def parse_args():
|
||||
"""Parse CLI arguments."""
|
||||
parser = argparse.ArgumentParser(
|
||||
description="Generate release notes from the actual release commit range."
|
||||
)
|
||||
parser.add_argument("new_version", help="Version that will be tagged for this release")
|
||||
parser.add_argument(
|
||||
"--base-tag",
|
||||
dest="base_tag",
|
||||
help="Existing version tag to diff from. Defaults to the latest version tag merged into the compare ref.",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--compare-ref",
|
||||
default="HEAD",
|
||||
help="Git ref to diff to. Defaults to HEAD.",
|
||||
)
|
||||
return parser.parse_args()
|
||||
|
||||
|
||||
def get_pr_details(pr_number):
|
||||
"""Get PR details from GitHub API via gh CLI."""
|
||||
try:
|
||||
@@ -268,28 +293,28 @@ def get_new_contributors(pr_details_list, tag, repo="meshtastic/firmware"):
|
||||
|
||||
|
||||
def main():
|
||||
if len(sys.argv) < 2:
|
||||
print("Usage: generate_release_notes.py <new_version>", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
new_version = sys.argv[1]
|
||||
args = parse_args()
|
||||
new_version = args.new_version
|
||||
compare_ref = args.compare_ref
|
||||
current_tag = f"v{new_version}"
|
||||
|
||||
# Get last release tag
|
||||
try:
|
||||
last_tag = get_last_release_tag()
|
||||
last_tag = args.base_tag or get_last_release_tag(compare_ref, exclude_tag=current_tag)
|
||||
except subprocess.CalledProcessError:
|
||||
print("Error: Could not find last release tag", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
# Collect PRs from both branches
|
||||
all_pr_numbers = set()
|
||||
print(
|
||||
f"Resolved release note range: {last_tag}..{compare_ref}",
|
||||
file=sys.stderr,
|
||||
)
|
||||
|
||||
for branch in ["develop", "master"]:
|
||||
try:
|
||||
prs = get_merged_prs_since_tag(last_tag, branch)
|
||||
all_pr_numbers.update(prs)
|
||||
except Exception as e:
|
||||
print(f"Warning: Could not get PRs from {branch}: {e}", file=sys.stderr)
|
||||
try:
|
||||
all_pr_numbers = set(get_merged_prs_in_range(last_tag, compare_ref))
|
||||
except subprocess.CalledProcessError as e:
|
||||
print(f"Error: Could not get PRs for range {last_tag}..{compare_ref}: {e}", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
# Get details for all PRs
|
||||
enhancements = []
|
||||
|
||||
@@ -87,6 +87,9 @@
|
||||
</screenshots>
|
||||
|
||||
<releases>
|
||||
<release version="2.7.23" date="2026-04-14">
|
||||
<url type="details">https://github.com/meshtastic/firmware/releases?q=tag%3Av2.7.23</url>
|
||||
</release>
|
||||
<release version="2.7.22" date="2026-04-06">
|
||||
<url type="details">https://github.com/meshtastic/firmware/releases?q=tag%3Av2.7.22</url>
|
||||
</release>
|
||||
|
||||
6
debian/changelog
vendored
6
debian/changelog
vendored
@@ -1,3 +1,9 @@
|
||||
meshtasticd (2.7.23.0) unstable; urgency=medium
|
||||
|
||||
* Version 2.7.23
|
||||
|
||||
-- GitHub Actions <github-actions[bot]@users.noreply.github.com> Tue, 14 Apr 2026 12:29:48 +0000
|
||||
|
||||
meshtasticd (2.7.22.0) unstable; urgency=medium
|
||||
|
||||
* Version 2.7.22
|
||||
|
||||
@@ -56,9 +56,7 @@ build_flags = -Wno-missing-field-initializers
|
||||
-DMESHTASTIC_EXCLUDE_POWERSTRESS=1 ; exclude power stress test module from main firmware
|
||||
-DMESHTASTIC_EXCLUDE_GENERIC_THREAD_MODULE=1
|
||||
-DMESHTASTIC_EXCLUDE_POWERMON=1
|
||||
-DMESHTASTIC_EXCLUDE_STATUS=1
|
||||
-D MAX_THREADS=40 ; As we've split modules, we have more threads to manage
|
||||
-DLED_BUILTIN=-1
|
||||
#-DBUILD_EPOCH=$UNIX_TIME ; set in platformio-custom.py now
|
||||
#-D OLED_PL=1
|
||||
#-D DEBUG_HEAP=1 ; uncomment to add free heap space / memory leak debugging logs
|
||||
@@ -126,7 +124,7 @@ lib_deps =
|
||||
[device-ui_base]
|
||||
lib_deps =
|
||||
# renovate: datasource=git-refs depName=meshtastic/device-ui packageName=https://github.com/meshtastic/device-ui gitBranch=master
|
||||
https://github.com/meshtastic/device-ui/archive/1897dd17fceb1f101bb1a3245680aa3439edcfdd.zip
|
||||
https://github.com/meshtastic/device-ui/archive/5305670b68eb5b92d14e62b5b536969ca4bb441f.zip
|
||||
|
||||
; Common libs for environmental measurements in telemetry module
|
||||
[environmental_base]
|
||||
|
||||
Submodule protobufs updated: 940ac382a7...e30092e616
@@ -21,8 +21,15 @@
|
||||
// How many messages are stored (RAM + flash).
|
||||
// Define -DMESSAGE_HISTORY_LIMIT=N in build_flags to control memory usage.
|
||||
#ifndef MESSAGE_HISTORY_LIMIT
|
||||
#if defined(ARCH_ESP32) && \
|
||||
!(defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32S3) || defined(CONFIG_IDF_TARGET_ESP32S2))
|
||||
// Baseline ESP32 (non-PSRAM variants) has limited heap; reduce message history on resource-constrained builds.
|
||||
// Override with -DMESSAGE_HISTORY_LIMIT=N if needed.
|
||||
#define MESSAGE_HISTORY_LIMIT 10
|
||||
#else
|
||||
#define MESSAGE_HISTORY_LIMIT 20
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Internal alias used everywhere in code – do NOT redefine elsewhere.
|
||||
#define MAX_MESSAGES_SAVED MESSAGE_HISTORY_LIMIT
|
||||
|
||||
@@ -40,6 +40,22 @@
|
||||
#include "concurrency/LockGuard.h"
|
||||
#endif
|
||||
|
||||
#if defined(ARCH_STM32WL) && defined(BATTERY_PIN)
|
||||
#include "stm32yyxx_ll_adc.h"
|
||||
|
||||
/* Analog read resolution */
|
||||
#if defined(LL_ADC_RESOLUTION_12B)
|
||||
#define LL_ADC_RESOLUTION LL_ADC_RESOLUTION_12B
|
||||
#define BATTERY_SENSE_RESOLUTION_BITS 12
|
||||
#elif defined(LL_ADC_DS_DATA_WIDTH_12_BIT)
|
||||
#define LL_ADC_RESOLUTION LL_ADC_DS_DATA_WIDTH_12_BIT
|
||||
#define BATTERY_SENSE_RESOLUTION_BITS 12
|
||||
#else
|
||||
#error "ADC resolution could not be defined!"
|
||||
#endif
|
||||
#define ADC_RANGE (1 << BATTERY_SENSE_RESOLUTION_BITS)
|
||||
#endif
|
||||
|
||||
#if defined(DEBUG_HEAP_MQTT) && !MESHTASTIC_EXCLUDE_MQTT
|
||||
#include "mqtt/MQTT.h"
|
||||
#include "target_specific.h"
|
||||
@@ -328,11 +344,17 @@ class AnalogBatteryLevel : public HasBatteryLevel
|
||||
float scaled = 0;
|
||||
|
||||
battery_adcEnable();
|
||||
#ifdef ARCH_ESP32 // ADC block for espressif platforms
|
||||
#ifdef ARCH_STM32WL
|
||||
// STM32 ADC with VREFINT runtime calibration
|
||||
Vref = __LL_ADC_CALC_VREFANALOG_VOLTAGE(analogRead(AVREF), LL_ADC_RESOLUTION);
|
||||
raw = analogRead(BATTERY_PIN);
|
||||
scaled = __LL_ADC_CALC_DATA_TO_VOLTAGE(Vref, raw, LL_ADC_RESOLUTION);
|
||||
scaled *= operativeAdcMultiplier;
|
||||
#elif defined(ARCH_ESP32) // ADC block for espressif platforms
|
||||
raw = espAdcRead();
|
||||
scaled = esp_adc_cal_raw_to_voltage(raw, adc_characs);
|
||||
scaled *= operativeAdcMultiplier;
|
||||
#else // block for all other platforms
|
||||
#else // block for all other platforms
|
||||
#ifdef ARCH_NRF52
|
||||
concurrency::LockGuard saadcGuard(concurrency::nrf52SaadcLock);
|
||||
#endif
|
||||
@@ -530,6 +552,11 @@ class AnalogBatteryLevel : public HasBatteryLevel
|
||||
bool initial_read_done = false;
|
||||
float last_read_value = (OCV[NUM_OCV_POINTS - 1] * NUM_CELLS);
|
||||
uint32_t last_read_time_ms = 0;
|
||||
#ifdef ARCH_STM32WL
|
||||
// 3300mV placeholder for STM32 errata where VREFINT factory calibration may be missing
|
||||
// (e.g. STM32U0, see DS14756 Rev 3 §2.4.1 "VREFINT offset")
|
||||
uint32_t Vref = 3300;
|
||||
#endif
|
||||
|
||||
#if HAS_TELEMETRY && !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && defined(HAS_RAKPROT)
|
||||
|
||||
@@ -639,7 +666,9 @@ bool Power::analogInit()
|
||||
#define BATTERY_SENSE_RESOLUTION_BITS 10
|
||||
#endif
|
||||
|
||||
#ifdef ARCH_ESP32 // ESP32 needs special analog stuff
|
||||
#ifdef ARCH_STM32WL
|
||||
analogReadResolution(BATTERY_SENSE_RESOLUTION_BITS);
|
||||
#elif defined(ARCH_ESP32) // ESP32 needs special analog stuff
|
||||
|
||||
#ifndef ADC_WIDTH // max resolution by default
|
||||
static const adc_bits_width_t width = ADC_WIDTH_BIT_12;
|
||||
@@ -649,7 +678,7 @@ bool Power::analogInit()
|
||||
#ifndef BAT_MEASURE_ADC_UNIT // ADC1
|
||||
adc1_config_width(width);
|
||||
adc1_config_channel_atten(adc_channel, atten);
|
||||
#else // ADC2
|
||||
#else // ADC2
|
||||
adc2_config_channel_atten(adc_channel, atten);
|
||||
#ifndef CONFIG_IDF_TARGET_ESP32S3
|
||||
// ADC2 wifi bug workaround
|
||||
@@ -679,7 +708,7 @@ bool Power::analogInit()
|
||||
|
||||
// NRF52 ADC init moved to powerHAL_init in nrf52 platform
|
||||
|
||||
#ifndef ARCH_ESP32
|
||||
#if !defined(ARCH_ESP32) && !defined(ARCH_STM32WL)
|
||||
analogReadResolution(BATTERY_SENSE_RESOLUTION_BITS);
|
||||
#endif
|
||||
|
||||
|
||||
@@ -1197,7 +1197,7 @@ void Screen::setFrames(FrameFocus focus)
|
||||
for (size_t i = 0; i < nodeDB->getNumMeshNodes(); i++) {
|
||||
const meshtastic_NodeInfoLite *n = nodeDB->getMeshNodeByIndex(i);
|
||||
if (n && n->num != nodeDB->getNodeNum() && n->is_favorite) {
|
||||
favoriteFrames.push_back(graphics::UIRenderer::drawNodeInfo);
|
||||
favoriteFrames.push_back(graphics::UIRenderer::drawFavoriteNode);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1226,7 +1226,7 @@ void Screen::setFrames(FrameFocus focus)
|
||||
static OverlayCallback overlays[] = {graphics::UIRenderer::drawNavigationBar, NotificationRenderer::drawBannercallback};
|
||||
ui->setOverlays(overlays, sizeof(overlays) / sizeof(overlays[0]));
|
||||
|
||||
prevFrame = -1; // Force drawNodeInfo to pick a new node (because our list just changed)
|
||||
prevFrame = -1; // Force drawFavoriteNode to pick a new node (because our list just changed)
|
||||
|
||||
// Focus on a specific frame, in the frame set we just created
|
||||
switch (focus) {
|
||||
|
||||
@@ -422,6 +422,17 @@ void drawTextMessageFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16
|
||||
std::vector<bool> isMine; // track alignment
|
||||
std::vector<bool> isHeader; // track header lines
|
||||
std::vector<AckStatus> ackForLine;
|
||||
// Hard limit on total cached lines to prevent unbounded growth from a single long message.
|
||||
// Reserve to the actual cache cap up front, because a single message can expand to many more
|
||||
// wrapped display lines than a small per-message estimate would predict. For a display
|
||||
// rendering only ~5-30 lines at a time, caching more than this limit wastes heap. Stop
|
||||
// appending once we reach MAX_CACHED_LINES to prevent a single message from blowing out the
|
||||
// heap.
|
||||
constexpr size_t MAX_CACHED_LINES = 100U; // ~5-6KB for std::string overhead on 32-bit (if each ~50-60 bytes avg)
|
||||
allLines.reserve(MAX_CACHED_LINES);
|
||||
isMine.reserve(MAX_CACHED_LINES);
|
||||
isHeader.reserve(MAX_CACHED_LINES);
|
||||
ackForLine.reserve(MAX_CACHED_LINES);
|
||||
|
||||
for (auto it = filtered.rbegin(); it != filtered.rend(); ++it) {
|
||||
const auto &m = *it;
|
||||
@@ -565,16 +576,23 @@ void drawTextMessageFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16
|
||||
|
||||
int wrapWidth = mine ? rightTextWidth : leftTextWidth;
|
||||
std::vector<std::string> wrapped = generateLines(display, "", msgText, wrapWidth);
|
||||
// Per-message wrap-line limit: even if wrapping produces many lines, cap them to prevent
|
||||
// a single long message from consuming most or all of the cache.
|
||||
constexpr size_t MAX_WRAPPED_LINES_PER_MSG = 20U;
|
||||
size_t wrappedCount = 0;
|
||||
for (auto &ln : wrapped) {
|
||||
allLines.push_back(ln);
|
||||
if (allLines.size() >= MAX_CACHED_LINES || wrappedCount >= MAX_WRAPPED_LINES_PER_MSG)
|
||||
break; // Cache limit or per-message limit reached; stop adding lines from this message
|
||||
allLines.emplace_back(std::move(ln));
|
||||
isMine.push_back(mine);
|
||||
isHeader.push_back(false);
|
||||
ackForLine.push_back(AckStatus::NONE);
|
||||
++wrappedCount;
|
||||
}
|
||||
}
|
||||
|
||||
// Cache lines and heights
|
||||
cachedLines = allLines;
|
||||
cachedLines.swap(allLines);
|
||||
cachedHeights = calculateLineHeights(cachedLines, emotes, isHeader);
|
||||
|
||||
std::vector<MessageBlock> blocks = buildMessageBlocks(isHeader, isMine);
|
||||
|
||||
@@ -3,6 +3,9 @@
|
||||
#include "CompassRenderer.h"
|
||||
#include "NodeDB.h"
|
||||
#include "NodeListRenderer.h"
|
||||
#if !MESHTASTIC_EXCLUDE_STATUS
|
||||
#include "modules/StatusMessageModule.h"
|
||||
#endif
|
||||
#include "UIRenderer.h"
|
||||
#include "gps/GeoCoord.h"
|
||||
#include "gps/RTC.h" // for getTime() function
|
||||
@@ -92,8 +95,41 @@ std::string getSafeNodeName(OLEDDisplay *display, meshtastic_NodeInfoLite *node,
|
||||
|
||||
// 1) Choose target candidate (long vs short) only if present
|
||||
const char *raw = nullptr;
|
||||
if (node && node->has_user) {
|
||||
raw = config.display.use_long_node_name ? node->user.long_name : node->user.short_name;
|
||||
|
||||
#if !MESHTASTIC_EXCLUDE_STATUS
|
||||
// If long-name mode is enabled, and we have a recent status for this node,
|
||||
// prefer "(short_name) statusText" as the raw candidate.
|
||||
std::string composedFromStatus;
|
||||
if (config.display.use_long_node_name && node && node->has_user && statusMessageModule) {
|
||||
const auto &recent = statusMessageModule->getRecentReceived();
|
||||
const StatusMessageModule::RecentStatus *found = nullptr;
|
||||
for (auto it = recent.rbegin(); it != recent.rend(); ++it) {
|
||||
if (it->fromNodeId == node->num && !it->statusText.empty()) {
|
||||
found = &(*it);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (found) {
|
||||
const char *shortName = node->user.short_name;
|
||||
composedFromStatus.reserve(4 + (shortName ? std::strlen(shortName) : 0) + 1 + found->statusText.size());
|
||||
composedFromStatus += "(";
|
||||
if (shortName && *shortName) {
|
||||
composedFromStatus += shortName;
|
||||
}
|
||||
composedFromStatus += ") ";
|
||||
composedFromStatus += found->statusText;
|
||||
|
||||
raw = composedFromStatus.c_str(); // safe for now; we'll sanitize immediately into std::string
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// If we didn't compose from status, use normal long/short selection
|
||||
if (!raw) {
|
||||
if (node && node->has_user) {
|
||||
raw = config.display.use_long_node_name ? node->user.long_name : node->user.short_name;
|
||||
}
|
||||
}
|
||||
|
||||
// 2) Preserve UTF-8 names so emotes can be detected and rendered.
|
||||
|
||||
@@ -5,6 +5,9 @@
|
||||
#include "MeshService.h"
|
||||
#include "NodeDB.h"
|
||||
#include "NodeListRenderer.h"
|
||||
#if !MESHTASTIC_EXCLUDE_STATUS
|
||||
#include "modules/StatusMessageModule.h"
|
||||
#endif
|
||||
#include "UIRenderer.h"
|
||||
#include "airtime.h"
|
||||
#include "gps/GeoCoord.h"
|
||||
@@ -290,7 +293,7 @@ void UIRenderer::drawNodes(OLEDDisplay *display, int16_t x, int16_t y, const mes
|
||||
// * Favorite Node Info *
|
||||
// **********************
|
||||
// cppcheck-suppress constParameterPointer; signature must match FrameCallback typedef from OLEDDisplayUi library
|
||||
void UIRenderer::drawNodeInfo(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
|
||||
void UIRenderer::drawFavoriteNode(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
|
||||
{
|
||||
if (favoritedNodes.empty())
|
||||
return;
|
||||
@@ -342,6 +345,57 @@ void UIRenderer::drawNodeInfo(OLEDDisplay *display, OLEDDisplayUiState *state, i
|
||||
UIRenderer::drawStringWithEmotes(display, x, getTextPositions(display)[line++], username, FONT_HEIGHT_SMALL, 1, false);
|
||||
}
|
||||
|
||||
#if !MESHTASTIC_EXCLUDE_STATUS
|
||||
// === Optional: Last received StatusMessage line for this node ===
|
||||
// Display it directly under the username line (if we have one).
|
||||
if (statusMessageModule) {
|
||||
const auto &recent = statusMessageModule->getRecentReceived();
|
||||
const StatusMessageModule::RecentStatus *found = nullptr;
|
||||
|
||||
// Search newest-to-oldest
|
||||
for (auto it = recent.rbegin(); it != recent.rend(); ++it) {
|
||||
if (it->fromNodeId == node->num && !it->statusText.empty()) {
|
||||
found = &(*it);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (found) {
|
||||
std::string statusLine = std::string(" Status: ") + found->statusText;
|
||||
{
|
||||
const int screenW = display->getWidth();
|
||||
const int ellipseW = display->getStringWidth("...");
|
||||
int w = display->getStringWidth(statusLine.c_str());
|
||||
|
||||
// Only do work if it overflows
|
||||
if (w > screenW) {
|
||||
bool truncated = false;
|
||||
if (ellipseW > screenW) {
|
||||
statusLine.clear();
|
||||
} else {
|
||||
while (!statusLine.empty()) {
|
||||
// remove one char (byte) at a time
|
||||
statusLine.pop_back();
|
||||
truncated = true;
|
||||
|
||||
// Measure candidate with ellipsis appended
|
||||
std::string candidate = statusLine + "...";
|
||||
if (display->getStringWidth(candidate.c_str()) <= screenW) {
|
||||
statusLine = std::move(candidate);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (statusLine.empty() && ellipseW <= screenW) {
|
||||
statusLine = "...";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
display->drawString(x, getTextPositions(display)[line++], statusLine.c_str());
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// === 2. Signal and Hops (combined on one line, if available) ===
|
||||
char signalHopsStr[32] = "";
|
||||
bool haveSignal = false;
|
||||
|
||||
@@ -50,7 +50,7 @@ class UIRenderer
|
||||
// Navigation bar overlay
|
||||
static void drawNavigationBar(OLEDDisplay *display, OLEDDisplayUiState *state);
|
||||
|
||||
static void drawNodeInfo(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y);
|
||||
static void drawFavoriteNode(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y);
|
||||
|
||||
static void drawDeviceFocused(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y);
|
||||
|
||||
|
||||
@@ -121,7 +121,6 @@ void CardputerKeyboard::pressed(uint8_t key)
|
||||
modifierFlag = 0;
|
||||
}
|
||||
|
||||
uint8_t next_key = 0;
|
||||
int row = (key - 1) / 10;
|
||||
int col = (key - 1) % 10;
|
||||
|
||||
|
||||
@@ -10,8 +10,26 @@
|
||||
#include "memGet.h"
|
||||
#include "configuration.h"
|
||||
|
||||
#ifdef ARCH_STM32WL
|
||||
#if defined(MESHTASTIC_DYNAMIC_SBRK_HEAP)
|
||||
#include <malloc.h>
|
||||
#include <unistd.h> // sbrk
|
||||
|
||||
#ifdef ARCH_STM32WL
|
||||
// Returns the uncommitted sbrk headroom: addressable space between the current heap
|
||||
// break and the stack pointer that has not yet been committed to the arena.
|
||||
static uint32_t sbrkHeadroom()
|
||||
{
|
||||
// defined in STM32 linker script
|
||||
extern char _estack;
|
||||
extern char _Min_Stack_Size;
|
||||
|
||||
uint32_t max_sp = (uint32_t)(&_estack - &_Min_Stack_Size);
|
||||
uint32_t heap_end = (uint32_t)sbrk(0);
|
||||
return (max_sp > heap_end) ? (max_sp - heap_end) : 0;
|
||||
}
|
||||
#else
|
||||
#error Unsupported architecture!
|
||||
#endif
|
||||
#endif
|
||||
|
||||
MemGet memGet;
|
||||
@@ -28,9 +46,9 @@ uint32_t MemGet::getFreeHeap()
|
||||
return dbgHeapFree();
|
||||
#elif defined(ARCH_RP2040)
|
||||
return rp2040.getFreeHeap();
|
||||
#elif defined(ARCH_STM32WL)
|
||||
#elif defined(MESHTASTIC_DYNAMIC_SBRK_HEAP) // Currently: ARCH_STM32WL
|
||||
struct mallinfo m = mallinfo();
|
||||
return m.fordblks; // Total free space (bytes)
|
||||
return m.fordblks + sbrkHeadroom(); // Free space within arena + uncommitted sbrk headroom
|
||||
#else
|
||||
// this platform does not have heap management function implemented
|
||||
return UINT32_MAX;
|
||||
@@ -49,9 +67,9 @@ uint32_t MemGet::getHeapSize()
|
||||
return dbgHeapTotal();
|
||||
#elif defined(ARCH_RP2040)
|
||||
return rp2040.getTotalHeap();
|
||||
#elif defined(ARCH_STM32WL)
|
||||
#elif defined(MESHTASTIC_DYNAMIC_SBRK_HEAP) // Currently: ARCH_STM32WL
|
||||
struct mallinfo m = mallinfo();
|
||||
return m.arena; // Non-mmapped space allocated (bytes)
|
||||
return m.arena + sbrkHeadroom(); // Non-mmapped space allocated + uncommitted sbrk headroom
|
||||
#else
|
||||
// this platform does not have heap management function implemented
|
||||
return UINT32_MAX;
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include "MeshTypes.h"
|
||||
#include "PointerQueue.h"
|
||||
#include "configuration.h"
|
||||
#include "detect/LoRaRadioType.h"
|
||||
|
||||
// Sentinel marking the end of a modem preset array
|
||||
static constexpr meshtastic_Config_LoRaConfig_ModemPreset MODEM_PRESET_END =
|
||||
@@ -59,7 +60,7 @@ extern const RegionInfo *myRegion;
|
||||
extern void initRegion();
|
||||
|
||||
// Valid LoRa spread factor range and defaults
|
||||
constexpr uint8_t LORA_SF_MIN = 7;
|
||||
constexpr uint8_t LORA_SF_MIN = 5;
|
||||
constexpr uint8_t LORA_SF_MAX = 12;
|
||||
constexpr uint8_t LORA_SF_DEFAULT = 11; // LONG_FAST default
|
||||
|
||||
@@ -71,10 +72,14 @@ constexpr uint8_t LORA_CR_DEFAULT = 5; // LONG_FAST default
|
||||
// Default bandwidth in kHz (LONG_FAST)
|
||||
constexpr float LORA_BW_DEFAULT_KHZ = 250.0f;
|
||||
|
||||
/// Clamp spread factor to the valid LoRa range [7, 12].
|
||||
/// Clamp spread factor to the valid LoRa range [5, 12].
|
||||
/// Out-of-range values (including 0 from unset preset mode) return LORA_SF_DEFAULT.
|
||||
static inline uint8_t clampSpreadFactor(uint8_t sf)
|
||||
{
|
||||
// We check for RF95 radios that are incompatible with Spreading Factors 5 and 6.
|
||||
if (radioType == RF95_RADIO && (sf == 5 || sf == 6))
|
||||
return LORA_SF_DEFAULT;
|
||||
|
||||
if (sf < LORA_SF_MIN || sf > LORA_SF_MAX)
|
||||
return LORA_SF_DEFAULT;
|
||||
return sf;
|
||||
|
||||
@@ -45,7 +45,10 @@ PB_BIND(meshtastic_Route, meshtastic_Route, 2)
|
||||
PB_BIND(meshtastic_Route_Link, meshtastic_Route_Link, AUTO)
|
||||
|
||||
|
||||
PB_BIND(meshtastic_CasevacReport, meshtastic_CasevacReport, AUTO)
|
||||
PB_BIND(meshtastic_CasevacReport, meshtastic_CasevacReport, 2)
|
||||
|
||||
|
||||
PB_BIND(meshtastic_ZMistEntry, meshtastic_ZMistEntry, AUTO)
|
||||
|
||||
|
||||
PB_BIND(meshtastic_EmergencyAlert, meshtastic_EmergencyAlert, AUTO)
|
||||
@@ -54,6 +57,12 @@ PB_BIND(meshtastic_EmergencyAlert, meshtastic_EmergencyAlert, AUTO)
|
||||
PB_BIND(meshtastic_TaskRequest, meshtastic_TaskRequest, AUTO)
|
||||
|
||||
|
||||
PB_BIND(meshtastic_TAKEnvironment, meshtastic_TAKEnvironment, AUTO)
|
||||
|
||||
|
||||
PB_BIND(meshtastic_SensorFov, meshtastic_SensorFov, AUTO)
|
||||
|
||||
|
||||
PB_BIND(meshtastic_TAKPacketV2, meshtastic_TAKPacketV2, 2)
|
||||
|
||||
|
||||
@@ -89,6 +98,8 @@ PB_BIND(meshtastic_TAKPacketV2, meshtastic_TAKPacketV2, 2)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -521,6 +521,19 @@ typedef enum _meshtastic_TaskRequest_Status {
|
||||
meshtastic_TaskRequest_Status_Status_Cancelled = 5 /* cancelled before completion */
|
||||
} meshtastic_TaskRequest_Status;
|
||||
|
||||
/* Coarse sensor category, inferred from `model` on parse when the source
|
||||
XML doesn't label it. Receivers that render differently per sensor
|
||||
class (thermal overlay vs daylight cone) use this. */
|
||||
typedef enum _meshtastic_SensorFov_SensorType {
|
||||
meshtastic_SensorFov_SensorType_SensorType_Unspecified = 0,
|
||||
meshtastic_SensorFov_SensorType_SensorType_Camera = 1, /* daylight / general optical */
|
||||
meshtastic_SensorFov_SensorType_SensorType_Thermal = 2, /* FLIR, thermal imager */
|
||||
meshtastic_SensorFov_SensorType_SensorType_Laser = 3, /* rangefinder, LRF, designator */
|
||||
meshtastic_SensorFov_SensorType_SensorType_Nvg = 4, /* night vision goggles */
|
||||
meshtastic_SensorFov_SensorType_SensorType_Rf = 5, /* radio/radar direction-finding */
|
||||
meshtastic_SensorFov_SensorType_SensorType_Other = 6
|
||||
} meshtastic_SensorFov_SensorType;
|
||||
|
||||
/* Struct definitions */
|
||||
/* ATAK GeoChat message */
|
||||
typedef struct _meshtastic_GeoChat {
|
||||
@@ -865,8 +878,82 @@ typedef struct _meshtastic_CasevacReport {
|
||||
/* Line 2: radio frequency / callsign metadata (e.g. "38.90 Mhz" or
|
||||
"Victor 6"). Capped tight in options. */
|
||||
char frequency[16];
|
||||
/* Short title / MEDEVAC identifier (e.g. "EAGLE.15.181230"). Usually the
|
||||
same as the envelope callsign but ATAK sometimes carries a distinct
|
||||
ops-number here. */
|
||||
pb_callback_t title;
|
||||
/* Primary medline free-text — the single most clinically important line
|
||||
on a MEDLINE form (e.g. "2 urgent litter patients, smoke on approach").
|
||||
MUST be preserved under MTU pressure as long as any casevac is sent. */
|
||||
pb_callback_t medline_remarks;
|
||||
/* Line 3 (newer ATAK format): patient counts by precedence level.
|
||||
Coexists with the enum-style `precedence` field (tag 1) — older ATAK
|
||||
emits a single enum, newer ATAK emits these counts, and both can be
|
||||
set simultaneously. Senders populate whichever style(s) the source
|
||||
XML had; receivers prefer counts when non-zero. */
|
||||
uint32_t urgent_count;
|
||||
uint32_t urgent_surgical_count;
|
||||
uint32_t priority_count;
|
||||
uint32_t routine_count;
|
||||
uint32_t convenience_count;
|
||||
/* Line 4 supplementary: free-text description of non-standard equipment
|
||||
(e.g. "Blood warmer"). Pairs with the `equipment_flags` bitfield. */
|
||||
pb_callback_t equipment_detail;
|
||||
/* Line 1 override: MGRS grid when distinct from the event anchor point
|
||||
(e.g. "34T CQ 12345 67890"). Event lat/lon/hae still carries the
|
||||
numeric location; this field preserves the exact MGRS string the
|
||||
medic entered. */
|
||||
pb_callback_t zone_protected_coord;
|
||||
/* Line 9 supplementary: slope direction (e.g. "N", "NE", "SSW") when
|
||||
`terrain_flags` bit 0 (slope) is set. */
|
||||
pb_callback_t terrain_slope_dir;
|
||||
/* Line 9 supplementary: free-text description of "other" terrain hazards
|
||||
(e.g. "Loose debris on west edge") when `terrain_flags` bit 5 (other)
|
||||
is set. Tier-2 strippable under MTU pressure. */
|
||||
pb_callback_t terrain_other_detail;
|
||||
/* Line 7 supplementary: how the zone is being marked right now
|
||||
(e.g. "Orange smoke", "VS-17 panel"). Complements the structured
|
||||
`hlz_marking` enum with a specific human-readable description. */
|
||||
pb_callback_t marked_by;
|
||||
/* Nearby obstacles on the approach (e.g. "Power lines north of HLZ"). */
|
||||
pb_callback_t obstacles;
|
||||
/* Wind direction and speed (e.g. "270 at 12 kts"). */
|
||||
pb_callback_t winds_are_from;
|
||||
/* Friendly forces posture near the pickup zone
|
||||
(e.g. "Squad east of HLZ"). */
|
||||
pb_callback_t friendlies;
|
||||
/* Known or suspected enemy positions near the pickup zone
|
||||
(e.g. "Possible enemy on south ridge"). */
|
||||
pb_callback_t enemy;
|
||||
/* Free-text description of the HLZ itself
|
||||
(e.g. "Primary HLZ is soccer field"). */
|
||||
pb_callback_t hlz_remarks;
|
||||
/* Per-patient clinical records. Each entry is one patient's ZMIST card
|
||||
(Zap number / Mechanism / Injuries / Signs / Treatment). Repeatable —
|
||||
a mass-casualty event can carry 1-6 entries in practice, limited by
|
||||
the 237 B LoRa MTU. */
|
||||
pb_callback_t zmist;
|
||||
} meshtastic_CasevacReport;
|
||||
|
||||
/* Per-patient clinical summary record — one entry per patient in a CASEVAC.
|
||||
Maps directly to ATAK's <zMist> child element inside <zMistsMap>.
|
||||
All fields are optional free-text; senders populate what they have. */
|
||||
typedef struct _meshtastic_ZMistEntry {
|
||||
/* Patient identifier / sequence label (e.g. "ZMIST-1", "ZMIST-2"). */
|
||||
pb_callback_t title;
|
||||
/* Zap number — unique patient tracking ID (often a terse code like
|
||||
"Gunshot" or a serial). */
|
||||
pb_callback_t z;
|
||||
/* Mechanism of injury (e.g. "Penetrating trauma", "Blast injury"). */
|
||||
pb_callback_t m;
|
||||
/* Injuries observed (e.g. "Left thigh", "Concussion"). */
|
||||
pb_callback_t i;
|
||||
/* Signs / vital stats (e.g. "Stable", "Priority", "BP 110/70"). */
|
||||
pb_callback_t s;
|
||||
/* Treatment given (e.g. "Tourniquet 1810Z", "O2 administered"). */
|
||||
pb_callback_t t;
|
||||
} meshtastic_ZMistEntry;
|
||||
|
||||
/* Emergency alert / 911 beacon (CoT types b-a-o-tbl, b-a-o-pan, b-a-o-opn,
|
||||
b-a-o-can, b-a-o-c, b-a-g).
|
||||
|
||||
@@ -911,6 +998,76 @@ typedef struct _meshtastic_TaskRequest {
|
||||
char note[48];
|
||||
} meshtastic_TaskRequest;
|
||||
|
||||
/* Weather annotation from <environment> CoT detail element.
|
||||
|
||||
Attaches to any TAKPacketV2 regardless of payload_variant — an Aircraft,
|
||||
PLI, or Marker can all carry observed conditions at the emitting station.
|
||||
ATAK-CIV ships an XSD for <environment> but no dedicated handler, so the
|
||||
element round-trips through the generic detail pipeline; this message
|
||||
promotes it to a first-class structured field.
|
||||
|
||||
Target wire cost: ~6-8 bytes compressed with a fully populated instance.
|
||||
|
||||
Named `TAKEnvironment` (not just `Environment`) because the bare name
|
||||
collides with `SwiftUI.Environment` — every SwiftUI view in a consuming
|
||||
iOS app uses the `@Environment` property wrapper, and importing the
|
||||
generated proto module would make `Environment` ambiguous in every one
|
||||
of those files. The `TAK` prefix matches the convention used by the
|
||||
outer `TAKPacketV2` wrapper and is unambiguous across all target
|
||||
languages (Swift, Kotlin, Python, TypeScript, C#). */
|
||||
typedef struct _meshtastic_TAKEnvironment {
|
||||
/* Temperature in deci-degrees Celsius. 225 = 22.5°C.
|
||||
Range covers -50°C to +50°C (-500 to +500) which spans every realistic
|
||||
outdoor TAK deployment. sint32 because negative temps are common in
|
||||
cold-weather ops. */
|
||||
int32_t temperature_c_x10;
|
||||
/* Wind direction in whole degrees, 0-359. "Direction FROM" per
|
||||
meteorological convention (matches CoT / ATAK). */
|
||||
uint32_t wind_direction_deg;
|
||||
/* Wind speed in cm/s. Matches the unit of TAKPacketV2.speed for
|
||||
consistency. 1200 = 12.00 m/s = ~27 mph. */
|
||||
uint32_t wind_speed_cm_s;
|
||||
} meshtastic_TAKEnvironment;
|
||||
|
||||
/* Sensor field-of-view cone from <sensor> CoT detail element.
|
||||
|
||||
Encodes the 8 geometry attributes that ATAK-CIV's SensorDetailHandler
|
||||
reads from the wire; drops the 9 visual-styling attributes that are
|
||||
receiver-side render hints (fovAlpha, fovRed/Green/Blue, strokeColor,
|
||||
strokeWeight, displayMagneticReference, hideFov, fovLabels, rangeLines).
|
||||
The receiving ATAK client restores those from its own defaults, same as
|
||||
every other CoT carried over Meshtastic today.
|
||||
|
||||
Attaches to any TAKPacketV2 — a PLI with a sensor on the operator's head,
|
||||
an Aircraft with a FLIR turret, a Marker dropped on a UAV.
|
||||
Target wire cost: ~7-14 bytes compressed (dominated by model string). */
|
||||
typedef struct _meshtastic_SensorFov {
|
||||
meshtastic_SensorFov_SensorType type;
|
||||
/* Azimuth in whole degrees, 0-359. "Pointing direction" of the cone axis,
|
||||
measured clockwise from true north. Whole degrees match ATAK-CIV's
|
||||
SensorDetailHandler default (270°) and save varint bytes over centi-deg. */
|
||||
uint32_t azimuth_deg;
|
||||
/* Maximum range of the cone in meters.
|
||||
Optional — if unset, receivers should use the ATAK-CIV default of 100m. */
|
||||
bool has_range_m;
|
||||
uint32_t range_m;
|
||||
/* Horizontal field of view in whole degrees (cone's angular width).
|
||||
ATAK-CIV default is 45°. */
|
||||
uint32_t fov_horizontal_deg;
|
||||
/* Vertical field of view in whole degrees. ATAK-CIV default is 45°.
|
||||
Optional — a value of 0 means "not set / use horizontal FOV". */
|
||||
uint32_t fov_vertical_deg;
|
||||
/* Elevation angle in whole degrees. Positive = up, negative = down.
|
||||
Range -90 to +90. sint32 for varint efficiency on small negatives. */
|
||||
int32_t elevation_deg;
|
||||
/* Roll (camera tilt) in whole degrees, -180 to +180.
|
||||
Optional — use 0 if the sensor doesn't track roll. */
|
||||
int32_t roll_deg;
|
||||
/* Free-form device model identifier, e.g. "FLIR-Boson-640", "SEEK".
|
||||
Optional — empty string means "unknown model" (ATAK-CIV default). */
|
||||
pb_callback_t model;
|
||||
} meshtastic_SensorFov;
|
||||
|
||||
typedef PB_BYTES_ARRAY_T(220) meshtastic_TAKPacketV2_raw_detail_t;
|
||||
/* ATAK v2 packet with expanded CoT field support and zstd dictionary compression.
|
||||
Sent on ATAK_PLUGIN_V2 port. The wire payload is:
|
||||
@@ -970,6 +1127,14 @@ typedef struct _meshtastic_TAKPacketV2 {
|
||||
GeoChat messages carry their text in GeoChat.message instead.
|
||||
Empty string (proto3 default) means no remarks were present. */
|
||||
pb_callback_t remarks;
|
||||
/* Observed weather conditions (temperature, wind). From <environment>.
|
||||
Type is `TAKEnvironment`, not `Environment`, to avoid colliding with
|
||||
SwiftUI's `@Environment` property wrapper in iOS consumers. */
|
||||
bool has_environment;
|
||||
meshtastic_TAKEnvironment environment;
|
||||
/* Sensor field-of-view cone (camera, FLIR, laser, etc.). From <sensor>. */
|
||||
bool has_sensor_fov;
|
||||
meshtastic_SensorFov sensor_fov;
|
||||
pb_size_t which_payload_variant;
|
||||
union {
|
||||
/* Position report (true = PLI, no extra fields beyond the common ones above) */
|
||||
@@ -1075,6 +1240,10 @@ extern "C" {
|
||||
#define _meshtastic_TaskRequest_Status_MAX meshtastic_TaskRequest_Status_Status_Cancelled
|
||||
#define _meshtastic_TaskRequest_Status_ARRAYSIZE ((meshtastic_TaskRequest_Status)(meshtastic_TaskRequest_Status_Status_Cancelled+1))
|
||||
|
||||
#define _meshtastic_SensorFov_SensorType_MIN meshtastic_SensorFov_SensorType_SensorType_Unspecified
|
||||
#define _meshtastic_SensorFov_SensorType_MAX meshtastic_SensorFov_SensorType_SensorType_Other
|
||||
#define _meshtastic_SensorFov_SensorType_ARRAYSIZE ((meshtastic_SensorFov_SensorType)(meshtastic_SensorFov_SensorType_SensorType_Other+1))
|
||||
|
||||
|
||||
#define meshtastic_GeoChat_receipt_type_ENUMTYPE meshtastic_GeoChat_ReceiptType
|
||||
|
||||
@@ -1104,11 +1273,15 @@ extern "C" {
|
||||
#define meshtastic_CasevacReport_security_ENUMTYPE meshtastic_CasevacReport_Security
|
||||
#define meshtastic_CasevacReport_hlz_marking_ENUMTYPE meshtastic_CasevacReport_HlzMarking
|
||||
|
||||
|
||||
#define meshtastic_EmergencyAlert_type_ENUMTYPE meshtastic_EmergencyAlert_Type
|
||||
|
||||
#define meshtastic_TaskRequest_priority_ENUMTYPE meshtastic_TaskRequest_Priority
|
||||
#define meshtastic_TaskRequest_status_ENUMTYPE meshtastic_TaskRequest_Status
|
||||
|
||||
|
||||
#define meshtastic_SensorFov_type_ENUMTYPE meshtastic_SensorFov_SensorType
|
||||
|
||||
#define meshtastic_TAKPacketV2_cot_type_id_ENUMTYPE meshtastic_CotType
|
||||
#define meshtastic_TAKPacketV2_how_ENUMTYPE meshtastic_CotHow
|
||||
#define meshtastic_TAKPacketV2_team_ENUMTYPE meshtastic_Team
|
||||
@@ -1131,10 +1304,13 @@ extern "C" {
|
||||
#define meshtastic_RangeAndBearing_init_default {false, meshtastic_CotGeoPoint_init_default, "", 0, 0, _meshtastic_Team_MIN, 0, 0}
|
||||
#define meshtastic_Route_init_default {_meshtastic_Route_Method_MIN, _meshtastic_Route_Direction_MIN, "", 0, 0, {meshtastic_Route_Link_init_default, meshtastic_Route_Link_init_default, meshtastic_Route_Link_init_default, meshtastic_Route_Link_init_default, meshtastic_Route_Link_init_default, meshtastic_Route_Link_init_default, meshtastic_Route_Link_init_default, meshtastic_Route_Link_init_default, meshtastic_Route_Link_init_default, meshtastic_Route_Link_init_default, meshtastic_Route_Link_init_default, meshtastic_Route_Link_init_default, meshtastic_Route_Link_init_default, meshtastic_Route_Link_init_default, meshtastic_Route_Link_init_default, meshtastic_Route_Link_init_default}, 0}
|
||||
#define meshtastic_Route_Link_init_default {false, meshtastic_CotGeoPoint_init_default, "", "", 0}
|
||||
#define meshtastic_CasevacReport_init_default {_meshtastic_CasevacReport_Precedence_MIN, 0, 0, 0, _meshtastic_CasevacReport_Security_MIN, _meshtastic_CasevacReport_HlzMarking_MIN, "", 0, 0, 0, 0, 0, 0, 0, ""}
|
||||
#define meshtastic_CasevacReport_init_default {_meshtastic_CasevacReport_Precedence_MIN, 0, 0, 0, _meshtastic_CasevacReport_Security_MIN, _meshtastic_CasevacReport_HlzMarking_MIN, "", 0, 0, 0, 0, 0, 0, 0, "", {{NULL}, NULL}, {{NULL}, NULL}, 0, 0, 0, 0, 0, {{NULL}, NULL}, {{NULL}, NULL}, {{NULL}, NULL}, {{NULL}, NULL}, {{NULL}, NULL}, {{NULL}, NULL}, {{NULL}, NULL}, {{NULL}, NULL}, {{NULL}, NULL}, {{NULL}, NULL}, {{NULL}, NULL}}
|
||||
#define meshtastic_ZMistEntry_init_default {{{NULL}, NULL}, {{NULL}, NULL}, {{NULL}, NULL}, {{NULL}, NULL}, {{NULL}, NULL}, {{NULL}, NULL}}
|
||||
#define meshtastic_EmergencyAlert_init_default {_meshtastic_EmergencyAlert_Type_MIN, "", ""}
|
||||
#define meshtastic_TaskRequest_init_default {"", "", "", _meshtastic_TaskRequest_Priority_MIN, _meshtastic_TaskRequest_Status_MIN, ""}
|
||||
#define meshtastic_TAKPacketV2_init_default {_meshtastic_CotType_MIN, _meshtastic_CotHow_MIN, "", _meshtastic_Team_MIN, _meshtastic_MemberRole_MIN, 0, 0, 0, 0, 0, 0, _meshtastic_GeoPointSource_MIN, _meshtastic_GeoPointSource_MIN, "", "", 0, "", "", "", "", "", "", "", {{NULL}, NULL}, 0, {0}}
|
||||
#define meshtastic_TAKEnvironment_init_default {0, 0, 0}
|
||||
#define meshtastic_SensorFov_init_default {_meshtastic_SensorFov_SensorType_MIN, 0, false, 0, 0, 0, 0, 0, {{NULL}, NULL}}
|
||||
#define meshtastic_TAKPacketV2_init_default {_meshtastic_CotType_MIN, _meshtastic_CotHow_MIN, "", _meshtastic_Team_MIN, _meshtastic_MemberRole_MIN, 0, 0, 0, 0, 0, 0, _meshtastic_GeoPointSource_MIN, _meshtastic_GeoPointSource_MIN, "", "", 0, "", "", "", "", "", "", "", {{NULL}, NULL}, false, meshtastic_TAKEnvironment_init_default, false, meshtastic_SensorFov_init_default, 0, {0}}
|
||||
#define meshtastic_TAKPacket_init_zero {0, false, meshtastic_Contact_init_zero, false, meshtastic_Group_init_zero, false, meshtastic_Status_init_zero, 0, {meshtastic_PLI_init_zero}}
|
||||
#define meshtastic_GeoChat_init_zero {"", false, "", false, "", "", _meshtastic_GeoChat_ReceiptType_MIN}
|
||||
#define meshtastic_Group_init_zero {_meshtastic_MemberRole_MIN, _meshtastic_Team_MIN}
|
||||
@@ -1148,10 +1324,13 @@ extern "C" {
|
||||
#define meshtastic_RangeAndBearing_init_zero {false, meshtastic_CotGeoPoint_init_zero, "", 0, 0, _meshtastic_Team_MIN, 0, 0}
|
||||
#define meshtastic_Route_init_zero {_meshtastic_Route_Method_MIN, _meshtastic_Route_Direction_MIN, "", 0, 0, {meshtastic_Route_Link_init_zero, meshtastic_Route_Link_init_zero, meshtastic_Route_Link_init_zero, meshtastic_Route_Link_init_zero, meshtastic_Route_Link_init_zero, meshtastic_Route_Link_init_zero, meshtastic_Route_Link_init_zero, meshtastic_Route_Link_init_zero, meshtastic_Route_Link_init_zero, meshtastic_Route_Link_init_zero, meshtastic_Route_Link_init_zero, meshtastic_Route_Link_init_zero, meshtastic_Route_Link_init_zero, meshtastic_Route_Link_init_zero, meshtastic_Route_Link_init_zero, meshtastic_Route_Link_init_zero}, 0}
|
||||
#define meshtastic_Route_Link_init_zero {false, meshtastic_CotGeoPoint_init_zero, "", "", 0}
|
||||
#define meshtastic_CasevacReport_init_zero {_meshtastic_CasevacReport_Precedence_MIN, 0, 0, 0, _meshtastic_CasevacReport_Security_MIN, _meshtastic_CasevacReport_HlzMarking_MIN, "", 0, 0, 0, 0, 0, 0, 0, ""}
|
||||
#define meshtastic_CasevacReport_init_zero {_meshtastic_CasevacReport_Precedence_MIN, 0, 0, 0, _meshtastic_CasevacReport_Security_MIN, _meshtastic_CasevacReport_HlzMarking_MIN, "", 0, 0, 0, 0, 0, 0, 0, "", {{NULL}, NULL}, {{NULL}, NULL}, 0, 0, 0, 0, 0, {{NULL}, NULL}, {{NULL}, NULL}, {{NULL}, NULL}, {{NULL}, NULL}, {{NULL}, NULL}, {{NULL}, NULL}, {{NULL}, NULL}, {{NULL}, NULL}, {{NULL}, NULL}, {{NULL}, NULL}, {{NULL}, NULL}}
|
||||
#define meshtastic_ZMistEntry_init_zero {{{NULL}, NULL}, {{NULL}, NULL}, {{NULL}, NULL}, {{NULL}, NULL}, {{NULL}, NULL}, {{NULL}, NULL}}
|
||||
#define meshtastic_EmergencyAlert_init_zero {_meshtastic_EmergencyAlert_Type_MIN, "", ""}
|
||||
#define meshtastic_TaskRequest_init_zero {"", "", "", _meshtastic_TaskRequest_Priority_MIN, _meshtastic_TaskRequest_Status_MIN, ""}
|
||||
#define meshtastic_TAKPacketV2_init_zero {_meshtastic_CotType_MIN, _meshtastic_CotHow_MIN, "", _meshtastic_Team_MIN, _meshtastic_MemberRole_MIN, 0, 0, 0, 0, 0, 0, _meshtastic_GeoPointSource_MIN, _meshtastic_GeoPointSource_MIN, "", "", 0, "", "", "", "", "", "", "", {{NULL}, NULL}, 0, {0}}
|
||||
#define meshtastic_TAKEnvironment_init_zero {0, 0, 0}
|
||||
#define meshtastic_SensorFov_init_zero {_meshtastic_SensorFov_SensorType_MIN, 0, false, 0, 0, 0, 0, 0, {{NULL}, NULL}}
|
||||
#define meshtastic_TAKPacketV2_init_zero {_meshtastic_CotType_MIN, _meshtastic_CotHow_MIN, "", _meshtastic_Team_MIN, _meshtastic_MemberRole_MIN, 0, 0, 0, 0, 0, 0, _meshtastic_GeoPointSource_MIN, _meshtastic_GeoPointSource_MIN, "", "", 0, "", "", "", "", "", "", "", {{NULL}, NULL}, false, meshtastic_TAKEnvironment_init_zero, false, meshtastic_SensorFov_init_zero, 0, {0}}
|
||||
|
||||
/* Field tags (for use in manual encoding/decoding) */
|
||||
#define meshtastic_GeoChat_message_tag 1
|
||||
@@ -1244,6 +1423,30 @@ extern "C" {
|
||||
#define meshtastic_CasevacReport_child_tag 13
|
||||
#define meshtastic_CasevacReport_terrain_flags_tag 14
|
||||
#define meshtastic_CasevacReport_frequency_tag 15
|
||||
#define meshtastic_CasevacReport_title_tag 16
|
||||
#define meshtastic_CasevacReport_medline_remarks_tag 17
|
||||
#define meshtastic_CasevacReport_urgent_count_tag 18
|
||||
#define meshtastic_CasevacReport_urgent_surgical_count_tag 19
|
||||
#define meshtastic_CasevacReport_priority_count_tag 20
|
||||
#define meshtastic_CasevacReport_routine_count_tag 21
|
||||
#define meshtastic_CasevacReport_convenience_count_tag 22
|
||||
#define meshtastic_CasevacReport_equipment_detail_tag 23
|
||||
#define meshtastic_CasevacReport_zone_protected_coord_tag 24
|
||||
#define meshtastic_CasevacReport_terrain_slope_dir_tag 25
|
||||
#define meshtastic_CasevacReport_terrain_other_detail_tag 26
|
||||
#define meshtastic_CasevacReport_marked_by_tag 27
|
||||
#define meshtastic_CasevacReport_obstacles_tag 28
|
||||
#define meshtastic_CasevacReport_winds_are_from_tag 29
|
||||
#define meshtastic_CasevacReport_friendlies_tag 30
|
||||
#define meshtastic_CasevacReport_enemy_tag 31
|
||||
#define meshtastic_CasevacReport_hlz_remarks_tag 32
|
||||
#define meshtastic_CasevacReport_zmist_tag 33
|
||||
#define meshtastic_ZMistEntry_title_tag 1
|
||||
#define meshtastic_ZMistEntry_z_tag 2
|
||||
#define meshtastic_ZMistEntry_m_tag 3
|
||||
#define meshtastic_ZMistEntry_i_tag 4
|
||||
#define meshtastic_ZMistEntry_s_tag 5
|
||||
#define meshtastic_ZMistEntry_t_tag 6
|
||||
#define meshtastic_EmergencyAlert_type_tag 1
|
||||
#define meshtastic_EmergencyAlert_authoring_uid_tag 2
|
||||
#define meshtastic_EmergencyAlert_cancel_reference_uid_tag 3
|
||||
@@ -1253,6 +1456,17 @@ extern "C" {
|
||||
#define meshtastic_TaskRequest_priority_tag 4
|
||||
#define meshtastic_TaskRequest_status_tag 5
|
||||
#define meshtastic_TaskRequest_note_tag 6
|
||||
#define meshtastic_TAKEnvironment_temperature_c_x10_tag 1
|
||||
#define meshtastic_TAKEnvironment_wind_direction_deg_tag 2
|
||||
#define meshtastic_TAKEnvironment_wind_speed_cm_s_tag 3
|
||||
#define meshtastic_SensorFov_type_tag 1
|
||||
#define meshtastic_SensorFov_azimuth_deg_tag 2
|
||||
#define meshtastic_SensorFov_range_m_tag 3
|
||||
#define meshtastic_SensorFov_fov_horizontal_deg_tag 4
|
||||
#define meshtastic_SensorFov_fov_vertical_deg_tag 5
|
||||
#define meshtastic_SensorFov_elevation_deg_tag 6
|
||||
#define meshtastic_SensorFov_roll_deg_tag 7
|
||||
#define meshtastic_SensorFov_model_tag 8
|
||||
#define meshtastic_TAKPacketV2_cot_type_id_tag 1
|
||||
#define meshtastic_TAKPacketV2_how_tag 2
|
||||
#define meshtastic_TAKPacketV2_callsign_tag 3
|
||||
@@ -1277,6 +1491,8 @@ extern "C" {
|
||||
#define meshtastic_TAKPacketV2_phone_tag 22
|
||||
#define meshtastic_TAKPacketV2_cot_type_str_tag 23
|
||||
#define meshtastic_TAKPacketV2_remarks_tag 24
|
||||
#define meshtastic_TAKPacketV2_environment_tag 25
|
||||
#define meshtastic_TAKPacketV2_sensor_fov_tag 26
|
||||
#define meshtastic_TAKPacketV2_pli_tag 30
|
||||
#define meshtastic_TAKPacketV2_chat_tag 31
|
||||
#define meshtastic_TAKPacketV2_aircraft_tag 32
|
||||
@@ -1441,9 +1657,38 @@ X(a, STATIC, SINGULAR, UINT32, non_us_civilian, 11) \
|
||||
X(a, STATIC, SINGULAR, UINT32, epw, 12) \
|
||||
X(a, STATIC, SINGULAR, UINT32, child, 13) \
|
||||
X(a, STATIC, SINGULAR, UINT32, terrain_flags, 14) \
|
||||
X(a, STATIC, SINGULAR, STRING, frequency, 15)
|
||||
#define meshtastic_CasevacReport_CALLBACK NULL
|
||||
X(a, STATIC, SINGULAR, STRING, frequency, 15) \
|
||||
X(a, CALLBACK, SINGULAR, STRING, title, 16) \
|
||||
X(a, CALLBACK, SINGULAR, STRING, medline_remarks, 17) \
|
||||
X(a, STATIC, SINGULAR, UINT32, urgent_count, 18) \
|
||||
X(a, STATIC, SINGULAR, UINT32, urgent_surgical_count, 19) \
|
||||
X(a, STATIC, SINGULAR, UINT32, priority_count, 20) \
|
||||
X(a, STATIC, SINGULAR, UINT32, routine_count, 21) \
|
||||
X(a, STATIC, SINGULAR, UINT32, convenience_count, 22) \
|
||||
X(a, CALLBACK, SINGULAR, STRING, equipment_detail, 23) \
|
||||
X(a, CALLBACK, SINGULAR, STRING, zone_protected_coord, 24) \
|
||||
X(a, CALLBACK, SINGULAR, STRING, terrain_slope_dir, 25) \
|
||||
X(a, CALLBACK, SINGULAR, STRING, terrain_other_detail, 26) \
|
||||
X(a, CALLBACK, SINGULAR, STRING, marked_by, 27) \
|
||||
X(a, CALLBACK, SINGULAR, STRING, obstacles, 28) \
|
||||
X(a, CALLBACK, SINGULAR, STRING, winds_are_from, 29) \
|
||||
X(a, CALLBACK, SINGULAR, STRING, friendlies, 30) \
|
||||
X(a, CALLBACK, SINGULAR, STRING, enemy, 31) \
|
||||
X(a, CALLBACK, SINGULAR, STRING, hlz_remarks, 32) \
|
||||
X(a, CALLBACK, REPEATED, MESSAGE, zmist, 33)
|
||||
#define meshtastic_CasevacReport_CALLBACK pb_default_field_callback
|
||||
#define meshtastic_CasevacReport_DEFAULT NULL
|
||||
#define meshtastic_CasevacReport_zmist_MSGTYPE meshtastic_ZMistEntry
|
||||
|
||||
#define meshtastic_ZMistEntry_FIELDLIST(X, a) \
|
||||
X(a, CALLBACK, SINGULAR, STRING, title, 1) \
|
||||
X(a, CALLBACK, SINGULAR, STRING, z, 2) \
|
||||
X(a, CALLBACK, SINGULAR, STRING, m, 3) \
|
||||
X(a, CALLBACK, SINGULAR, STRING, i, 4) \
|
||||
X(a, CALLBACK, SINGULAR, STRING, s, 5) \
|
||||
X(a, CALLBACK, SINGULAR, STRING, t, 6)
|
||||
#define meshtastic_ZMistEntry_CALLBACK pb_default_field_callback
|
||||
#define meshtastic_ZMistEntry_DEFAULT NULL
|
||||
|
||||
#define meshtastic_EmergencyAlert_FIELDLIST(X, a) \
|
||||
X(a, STATIC, SINGULAR, UENUM, type, 1) \
|
||||
@@ -1462,6 +1707,25 @@ X(a, STATIC, SINGULAR, STRING, note, 6)
|
||||
#define meshtastic_TaskRequest_CALLBACK NULL
|
||||
#define meshtastic_TaskRequest_DEFAULT NULL
|
||||
|
||||
#define meshtastic_TAKEnvironment_FIELDLIST(X, a) \
|
||||
X(a, STATIC, SINGULAR, SINT32, temperature_c_x10, 1) \
|
||||
X(a, STATIC, SINGULAR, UINT32, wind_direction_deg, 2) \
|
||||
X(a, STATIC, SINGULAR, UINT32, wind_speed_cm_s, 3)
|
||||
#define meshtastic_TAKEnvironment_CALLBACK NULL
|
||||
#define meshtastic_TAKEnvironment_DEFAULT NULL
|
||||
|
||||
#define meshtastic_SensorFov_FIELDLIST(X, a) \
|
||||
X(a, STATIC, SINGULAR, UENUM, type, 1) \
|
||||
X(a, STATIC, SINGULAR, UINT32, azimuth_deg, 2) \
|
||||
X(a, STATIC, OPTIONAL, UINT32, range_m, 3) \
|
||||
X(a, STATIC, SINGULAR, UINT32, fov_horizontal_deg, 4) \
|
||||
X(a, STATIC, SINGULAR, UINT32, fov_vertical_deg, 5) \
|
||||
X(a, STATIC, SINGULAR, SINT32, elevation_deg, 6) \
|
||||
X(a, STATIC, SINGULAR, SINT32, roll_deg, 7) \
|
||||
X(a, CALLBACK, SINGULAR, STRING, model, 8)
|
||||
#define meshtastic_SensorFov_CALLBACK pb_default_field_callback
|
||||
#define meshtastic_SensorFov_DEFAULT NULL
|
||||
|
||||
#define meshtastic_TAKPacketV2_FIELDLIST(X, a) \
|
||||
X(a, STATIC, SINGULAR, UENUM, cot_type_id, 1) \
|
||||
X(a, STATIC, SINGULAR, UENUM, how, 2) \
|
||||
@@ -1487,6 +1751,8 @@ X(a, STATIC, SINGULAR, STRING, endpoint, 21) \
|
||||
X(a, STATIC, SINGULAR, STRING, phone, 22) \
|
||||
X(a, STATIC, SINGULAR, STRING, cot_type_str, 23) \
|
||||
X(a, CALLBACK, SINGULAR, STRING, remarks, 24) \
|
||||
X(a, STATIC, OPTIONAL, MESSAGE, environment, 25) \
|
||||
X(a, STATIC, OPTIONAL, MESSAGE, sensor_fov, 26) \
|
||||
X(a, STATIC, ONEOF, BOOL, (payload_variant,pli,payload_variant.pli), 30) \
|
||||
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,chat,payload_variant.chat), 31) \
|
||||
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,aircraft,payload_variant.aircraft), 32) \
|
||||
@@ -1500,6 +1766,8 @@ X(a, STATIC, ONEOF, MESSAGE, (payload_variant,emergency,payload_variant.em
|
||||
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,task,payload_variant.task), 40)
|
||||
#define meshtastic_TAKPacketV2_CALLBACK pb_default_field_callback
|
||||
#define meshtastic_TAKPacketV2_DEFAULT NULL
|
||||
#define meshtastic_TAKPacketV2_environment_MSGTYPE meshtastic_TAKEnvironment
|
||||
#define meshtastic_TAKPacketV2_sensor_fov_MSGTYPE meshtastic_SensorFov
|
||||
#define meshtastic_TAKPacketV2_payload_variant_chat_MSGTYPE meshtastic_GeoChat
|
||||
#define meshtastic_TAKPacketV2_payload_variant_aircraft_MSGTYPE meshtastic_AircraftTrack
|
||||
#define meshtastic_TAKPacketV2_payload_variant_shape_MSGTYPE meshtastic_DrawnShape
|
||||
@@ -1524,8 +1792,11 @@ extern const pb_msgdesc_t meshtastic_RangeAndBearing_msg;
|
||||
extern const pb_msgdesc_t meshtastic_Route_msg;
|
||||
extern const pb_msgdesc_t meshtastic_Route_Link_msg;
|
||||
extern const pb_msgdesc_t meshtastic_CasevacReport_msg;
|
||||
extern const pb_msgdesc_t meshtastic_ZMistEntry_msg;
|
||||
extern const pb_msgdesc_t meshtastic_EmergencyAlert_msg;
|
||||
extern const pb_msgdesc_t meshtastic_TaskRequest_msg;
|
||||
extern const pb_msgdesc_t meshtastic_TAKEnvironment_msg;
|
||||
extern const pb_msgdesc_t meshtastic_SensorFov_msg;
|
||||
extern const pb_msgdesc_t meshtastic_TAKPacketV2_msg;
|
||||
|
||||
/* Defines for backwards compatibility with code written before nanopb-0.4.0 */
|
||||
@@ -1543,15 +1814,20 @@ extern const pb_msgdesc_t meshtastic_TAKPacketV2_msg;
|
||||
#define meshtastic_Route_fields &meshtastic_Route_msg
|
||||
#define meshtastic_Route_Link_fields &meshtastic_Route_Link_msg
|
||||
#define meshtastic_CasevacReport_fields &meshtastic_CasevacReport_msg
|
||||
#define meshtastic_ZMistEntry_fields &meshtastic_ZMistEntry_msg
|
||||
#define meshtastic_EmergencyAlert_fields &meshtastic_EmergencyAlert_msg
|
||||
#define meshtastic_TaskRequest_fields &meshtastic_TaskRequest_msg
|
||||
#define meshtastic_TAKEnvironment_fields &meshtastic_TAKEnvironment_msg
|
||||
#define meshtastic_SensorFov_fields &meshtastic_SensorFov_msg
|
||||
#define meshtastic_TAKPacketV2_fields &meshtastic_TAKPacketV2_msg
|
||||
|
||||
/* Maximum encoded size of messages (where known) */
|
||||
/* meshtastic_CasevacReport_size depends on runtime parameters */
|
||||
/* meshtastic_ZMistEntry_size depends on runtime parameters */
|
||||
/* meshtastic_SensorFov_size depends on runtime parameters */
|
||||
/* meshtastic_TAKPacketV2_size depends on runtime parameters */
|
||||
#define MESHTASTIC_MESHTASTIC_ATAK_PB_H_MAX_SIZE meshtastic_Route_size
|
||||
#define meshtastic_AircraftTrack_size 134
|
||||
#define meshtastic_CasevacReport_size 70
|
||||
#define meshtastic_Contact_size 242
|
||||
#define meshtastic_CotGeoPoint_size 12
|
||||
#define meshtastic_DrawnShape_size 553
|
||||
@@ -1564,6 +1840,7 @@ extern const pb_msgdesc_t meshtastic_TAKPacketV2_msg;
|
||||
#define meshtastic_Route_Link_size 83
|
||||
#define meshtastic_Route_size 1379
|
||||
#define meshtastic_Status_size 3
|
||||
#define meshtastic_TAKEnvironment_size 18
|
||||
#define meshtastic_TAKPacket_size 756
|
||||
#define meshtastic_TaskRequest_size 132
|
||||
|
||||
|
||||
@@ -890,6 +890,10 @@ typedef struct _meshtastic_RemoteShell {
|
||||
uint32_t rows;
|
||||
/* Bit flags for protocol extensions. */
|
||||
uint32_t flags;
|
||||
/* The last sequence number TX'd. */
|
||||
uint32_t last_tx_seq;
|
||||
/* The last sequence number RX'd. */
|
||||
uint32_t last_rx_seq;
|
||||
} meshtastic_RemoteShell;
|
||||
|
||||
/* Waypoint message, used to share arbitrary locations across the mesh */
|
||||
@@ -1512,7 +1516,7 @@ extern "C" {
|
||||
#define meshtastic_Data_init_default {_meshtastic_PortNum_MIN, {0, {0}}, 0, 0, 0, 0, 0, 0, false, 0}
|
||||
#define meshtastic_KeyVerification_init_default {0, {0, {0}}, {0, {0}}}
|
||||
#define meshtastic_StoreForwardPlusPlus_init_default {_meshtastic_StoreForwardPlusPlus_SFPP_message_type_MIN, {0, {0}}, {0, {0}}, {0, {0}}, {0, {0}}, 0, 0, 0, 0, 0}
|
||||
#define meshtastic_RemoteShell_init_default {_meshtastic_RemoteShell_OpCode_MIN, 0, 0, 0, {0, {0}}, 0, 0, 0}
|
||||
#define meshtastic_RemoteShell_init_default {_meshtastic_RemoteShell_OpCode_MIN, 0, 0, 0, {0, {0}}, 0, 0, 0, 0, 0}
|
||||
#define meshtastic_Waypoint_init_default {0, false, 0, false, 0, 0, 0, "", "", 0}
|
||||
#define meshtastic_StatusMessage_init_default {""}
|
||||
#define meshtastic_MqttClientProxyMessage_init_default {"", 0, {{0, {0}}}, 0}
|
||||
@@ -1546,7 +1550,7 @@ extern "C" {
|
||||
#define meshtastic_Data_init_zero {_meshtastic_PortNum_MIN, {0, {0}}, 0, 0, 0, 0, 0, 0, false, 0}
|
||||
#define meshtastic_KeyVerification_init_zero {0, {0, {0}}, {0, {0}}}
|
||||
#define meshtastic_StoreForwardPlusPlus_init_zero {_meshtastic_StoreForwardPlusPlus_SFPP_message_type_MIN, {0, {0}}, {0, {0}}, {0, {0}}, {0, {0}}, 0, 0, 0, 0, 0}
|
||||
#define meshtastic_RemoteShell_init_zero {_meshtastic_RemoteShell_OpCode_MIN, 0, 0, 0, {0, {0}}, 0, 0, 0}
|
||||
#define meshtastic_RemoteShell_init_zero {_meshtastic_RemoteShell_OpCode_MIN, 0, 0, 0, {0, {0}}, 0, 0, 0, 0, 0}
|
||||
#define meshtastic_Waypoint_init_zero {0, false, 0, false, 0, 0, 0, "", "", 0}
|
||||
#define meshtastic_StatusMessage_init_zero {""}
|
||||
#define meshtastic_MqttClientProxyMessage_init_zero {"", 0, {{0, {0}}}, 0}
|
||||
@@ -1644,6 +1648,8 @@ extern "C" {
|
||||
#define meshtastic_RemoteShell_cols_tag 6
|
||||
#define meshtastic_RemoteShell_rows_tag 7
|
||||
#define meshtastic_RemoteShell_flags_tag 8
|
||||
#define meshtastic_RemoteShell_last_tx_seq_tag 9
|
||||
#define meshtastic_RemoteShell_last_rx_seq_tag 10
|
||||
#define meshtastic_Waypoint_id_tag 1
|
||||
#define meshtastic_Waypoint_latitude_i_tag 2
|
||||
#define meshtastic_Waypoint_longitude_i_tag 3
|
||||
@@ -1884,7 +1890,9 @@ X(a, STATIC, SINGULAR, UINT32, ack_seq, 4) \
|
||||
X(a, STATIC, SINGULAR, BYTES, payload, 5) \
|
||||
X(a, STATIC, SINGULAR, UINT32, cols, 6) \
|
||||
X(a, STATIC, SINGULAR, UINT32, rows, 7) \
|
||||
X(a, STATIC, SINGULAR, UINT32, flags, 8)
|
||||
X(a, STATIC, SINGULAR, UINT32, flags, 8) \
|
||||
X(a, STATIC, SINGULAR, UINT32, last_tx_seq, 9) \
|
||||
X(a, STATIC, SINGULAR, UINT32, last_rx_seq, 10)
|
||||
#define meshtastic_RemoteShell_CALLBACK NULL
|
||||
#define meshtastic_RemoteShell_DEFAULT NULL
|
||||
|
||||
@@ -2262,7 +2270,7 @@ extern const pb_msgdesc_t meshtastic_ChunkedPayloadResponse_msg;
|
||||
#define meshtastic_NodeRemoteHardwarePin_size 29
|
||||
#define meshtastic_Position_size 144
|
||||
#define meshtastic_QueueStatus_size 23
|
||||
#define meshtastic_RemoteShell_size 241
|
||||
#define meshtastic_RemoteShell_size 253
|
||||
#define meshtastic_RouteDiscovery_size 256
|
||||
#define meshtastic_Routing_size 259
|
||||
#define meshtastic_StatusMessage_size 81
|
||||
|
||||
@@ -29,10 +29,23 @@ int32_t StatusMessageModule::runOnce()
|
||||
ProcessMessage StatusMessageModule::handleReceived(const meshtastic_MeshPacket &mp)
|
||||
{
|
||||
if (mp.which_payload_variant == meshtastic_MeshPacket_decoded_tag) {
|
||||
meshtastic_StatusMessage incomingMessage;
|
||||
meshtastic_StatusMessage incomingMessage = meshtastic_StatusMessage_init_zero;
|
||||
|
||||
if (pb_decode_from_bytes(mp.decoded.payload.bytes, mp.decoded.payload.size, meshtastic_StatusMessage_fields,
|
||||
&incomingMessage)) {
|
||||
|
||||
LOG_INFO("Received a NodeStatus message %s", incomingMessage.status);
|
||||
|
||||
RecentStatus entry;
|
||||
entry.fromNodeId = mp.from;
|
||||
entry.statusText = incomingMessage.status;
|
||||
|
||||
recentReceived.push_back(std::move(entry));
|
||||
|
||||
// Keep only last MAX_RECENT_STATUSMESSAGES
|
||||
if (recentReceived.size() > MAX_RECENT_STATUSMESSAGES) {
|
||||
recentReceived.erase(recentReceived.begin()); // drop oldest
|
||||
}
|
||||
}
|
||||
}
|
||||
return ProcessMessage::CONTINUE;
|
||||
|
||||
@@ -2,10 +2,11 @@
|
||||
#if !MESHTASTIC_EXCLUDE_STATUS
|
||||
#include "SinglePortModule.h"
|
||||
#include "configuration.h"
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
class StatusMessageModule : public SinglePortModule, private concurrency::OSThread
|
||||
{
|
||||
|
||||
public:
|
||||
/** Constructor
|
||||
* name is for debugging output
|
||||
@@ -19,16 +20,28 @@ class StatusMessageModule : public SinglePortModule, private concurrency::OSThre
|
||||
this->setInterval(1000 * 12 * 60 * 60);
|
||||
}
|
||||
// TODO: If we have a string, set the initial delay (15 minutes maybe)
|
||||
|
||||
// Keep vector from reallocating as we fill up to MAX_RECENT_STATUSMESSAGES
|
||||
recentReceived.reserve(MAX_RECENT_STATUSMESSAGES);
|
||||
}
|
||||
|
||||
virtual int32_t runOnce() override;
|
||||
|
||||
struct RecentStatus {
|
||||
uint32_t fromNodeId; // mp.from
|
||||
std::string statusText; // incomingMessage.status
|
||||
};
|
||||
|
||||
const std::vector<RecentStatus> &getRecentReceived() const { return recentReceived; }
|
||||
|
||||
protected:
|
||||
/** Called to handle a particular incoming message
|
||||
*/
|
||||
virtual ProcessMessage handleReceived(const meshtastic_MeshPacket &mp) override;
|
||||
|
||||
private:
|
||||
static constexpr size_t MAX_RECENT_STATUSMESSAGES = 5;
|
||||
std::vector<RecentStatus> recentReceived;
|
||||
};
|
||||
|
||||
extern StatusMessageModule *statusMessageModule;
|
||||
|
||||
@@ -654,7 +654,9 @@ void portduinoSetup()
|
||||
if (verboseEnabled && portduino_config.logoutputlevel != level_trace) {
|
||||
portduino_config.logoutputlevel = level_debug;
|
||||
}
|
||||
|
||||
if (portduino_config.lora_spi_dev != "") {
|
||||
portduinoSetOptions({.realHardware = true});
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -15,8 +15,13 @@
|
||||
|
||||
// Device specific curves go in variant.h
|
||||
#ifndef OCV_ARRAY
|
||||
#if defined(ARCH_STM32WL) && BATTERY_PIN == AVBAT
|
||||
// STM32 VDD/VBAT absolute maximum is 4V so use an LFP curve
|
||||
#define OCV_ARRAY 3650, 3400, 3340, 3320, 3300, 3280, 3270, 3260, 3240, 3200, 2500
|
||||
#else
|
||||
#define OCV_ARRAY 4190, 4050, 3990, 3890, 3800, 3720, 3630, 3530, 3420, 3300, 3100
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*Note: 12V lead acid is 6 cells, most board accept only 1 cell LiIon/LiPo*/
|
||||
#ifndef NUM_CELLS
|
||||
|
||||
@@ -8,7 +8,6 @@ build_flags =
|
||||
-I variants/esp32/chatter2
|
||||
-DMESHTASTIC_EXCLUDE_WEBSERVER=1
|
||||
-DMESHTASTIC_EXCLUDE_PAXCOUNTER=1
|
||||
-ULED_BUILTIN
|
||||
|
||||
lib_deps =
|
||||
${esp32_base.lib_deps}
|
||||
|
||||
@@ -10,7 +10,6 @@ build_flags =
|
||||
-D EBYTE_E22
|
||||
-D EBYTE_E22_900M30S ; Assume Tx power curve is identical to 900M30S as there is no documentation
|
||||
-I variants/esp32/diy/9m2ibr_aprs_lora_tracker
|
||||
-ULED_BUILTIN
|
||||
build_src_filter =
|
||||
${esp32_base.build_src_filter}
|
||||
+<../variants/esp32/diy/9m2ibr_aprs_lora_tracker>
|
||||
@@ -14,4 +14,3 @@ build_flags =
|
||||
${esp32_base.build_flags}
|
||||
-D DIY_V1
|
||||
-I variants/esp32/diy/hydra
|
||||
-ULED_BUILTIN
|
||||
|
||||
@@ -17,4 +17,3 @@ build_flags =
|
||||
-D DIY_V1
|
||||
-D EBYTE_E22
|
||||
-I variants/esp32/diy/v1
|
||||
-ULED_BUILTIN
|
||||
|
||||
@@ -14,4 +14,3 @@ build_flags =
|
||||
${esp32_base.build_flags}
|
||||
-D HELTEC_V2_1
|
||||
-I variants/esp32/heltec_v2.1
|
||||
-ULED_BUILTIN
|
||||
|
||||
@@ -14,4 +14,3 @@ build_flags =
|
||||
${esp32_base.build_flags}
|
||||
-D HELTEC_V2_0
|
||||
-I variants/esp32/heltec_v2
|
||||
-ULED_BUILTIN
|
||||
|
||||
@@ -10,6 +10,7 @@ build_flags =
|
||||
-D BOARD_HAS_PSRAM
|
||||
-D RADIOLIB_EXCLUDE_LR11X0=1
|
||||
-D RADIOLIB_EXCLUDE_SX128X=1
|
||||
-D RADIOLIB_EXCLUDE_LR2021=1
|
||||
-D MESHTASTIC_EXCLUDE_CANNEDMESSAGES=1
|
||||
-D MESHTASTIC_EXCLUDE_DETECTIONSENSOR=1
|
||||
-D MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR=1
|
||||
|
||||
@@ -14,4 +14,3 @@ build_flags =
|
||||
${esp32_base.build_flags}
|
||||
-D NANO_G1_EXPLORER
|
||||
-I variants/esp32/nano-g1-explorer
|
||||
-ULED_BUILTIN
|
||||
|
||||
@@ -14,4 +14,3 @@ build_flags =
|
||||
${esp32_base.build_flags}
|
||||
-D NANO_G1
|
||||
-I variants/esp32/nano-g1
|
||||
-ULED_BUILTIN
|
||||
|
||||
@@ -9,7 +9,6 @@ build_flags =
|
||||
-DHAS_STK8XXX=1
|
||||
-O2
|
||||
-I variants/esp32/radiomaster_900_bandit
|
||||
-ULED_BUILTIN
|
||||
board_build.f_cpu = 240000000L
|
||||
upload_protocol = esptool
|
||||
lib_deps =
|
||||
|
||||
@@ -13,6 +13,5 @@ build_flags =
|
||||
-DCONFIG_DISABLE_HAL_LOCKS=1
|
||||
-O2
|
||||
-I variants/esp32/radiomaster_900_bandit_nano
|
||||
-ULED_BUILTIN
|
||||
board_build.f_cpu = 240000000L
|
||||
upload_protocol = esptool
|
||||
|
||||
@@ -16,6 +16,5 @@ build_flags =
|
||||
-DCONFIG_DISABLE_HAL_LOCKS=1
|
||||
-O2
|
||||
-I variants/esp32/radiomaster_900_bandit_nano
|
||||
-ULED_BUILTIN
|
||||
board_build.f_cpu = 240000000L
|
||||
upload_protocol = esptool
|
||||
|
||||
@@ -14,4 +14,3 @@ build_flags =
|
||||
${esp32_base.build_flags}
|
||||
-D STATION_G1
|
||||
-I variants/esp32/station-g1
|
||||
-ULED_BUILTIN
|
||||
|
||||
@@ -16,7 +16,6 @@ board_check = true
|
||||
build_flags = ${esp32_base.build_flags}
|
||||
-D TBEAM_V10
|
||||
-I variants/esp32/tbeam
|
||||
-ULED_BUILTIN
|
||||
upload_speed = 921600
|
||||
|
||||
[env:tbeam-displayshield]
|
||||
|
||||
@@ -13,5 +13,4 @@ build_flags =
|
||||
${esp32_base.build_flags}
|
||||
-D TLORA_V1
|
||||
-I variants/esp32/tlora_v1
|
||||
-ULED_BUILTIN
|
||||
upload_speed = 115200
|
||||
|
||||
@@ -12,7 +12,7 @@ extends = esp32_base
|
||||
board = ttgo-lora32-v21
|
||||
board_check = true
|
||||
build_flags =
|
||||
${esp32_base.build_flags} -D TLORA_V2_1_16 -I variants/esp32/tlora_v2_1_16 -ULED_BUILTIN
|
||||
${esp32_base.build_flags} -D TLORA_V2_1_16 -I variants/esp32/tlora_v2_1_16
|
||||
upload_speed = 115200
|
||||
|
||||
[env:sugarcube]
|
||||
|
||||
@@ -7,5 +7,4 @@ build_flags =
|
||||
-D TLORA_V2_1_16
|
||||
-I variants/esp32/tlora_v2_1_16
|
||||
-D LORA_TCXO_GPIO=33
|
||||
-ULED_BUILTIN
|
||||
upload_speed = 115200
|
||||
|
||||
@@ -7,4 +7,3 @@ build_flags =
|
||||
-I variants/esp32/tlora_v2_1_16
|
||||
-D LORA_TCXO_GPIO=12
|
||||
-D BUTTON_PIN=0
|
||||
-ULED_BUILTIN
|
||||
@@ -8,4 +8,3 @@ build_flags =
|
||||
-I variants/esp32c6/tlora_c6
|
||||
-DARDUINO_USB_CDC_ON_BOOT=1
|
||||
-DARDUINO_USB_MODE=1
|
||||
-ULED_BUILTIN
|
||||
|
||||
@@ -6,5 +6,4 @@ board_build.partitions = default_8MB.csv
|
||||
build_flags =
|
||||
${esp32s3_base.build_flags} -I variants/esp32s3/heltec_capsule_sensor_v3
|
||||
-D HELTEC_CAPSULE_SENSOR_V3
|
||||
-ULED_BUILTIN
|
||||
;-D DEBUG_DISABLED ; uncomment this line to disable DEBUG output
|
||||
|
||||
@@ -7,4 +7,3 @@ build_flags =
|
||||
${esp32s3_base.build_flags}
|
||||
-I variants/esp32s3/heltec_sensor_hub
|
||||
-D HELTEC_SENSOR_HUB
|
||||
-ULED_BUILTIN
|
||||
|
||||
@@ -18,4 +18,3 @@ build_flags =
|
||||
${esp32s3_base.build_flags}
|
||||
-D HELTEC_V3
|
||||
-I variants/esp32s3/heltec_v3
|
||||
-ULED_BUILTIN
|
||||
|
||||
@@ -8,7 +8,6 @@ build_flags =
|
||||
-D HELTEC_V4
|
||||
-D HAS_LORA_FEM=1
|
||||
-I variants/esp32s3/heltec_v4
|
||||
-ULED_BUILTIN
|
||||
|
||||
|
||||
[env:heltec-v4]
|
||||
|
||||
@@ -20,5 +20,5 @@ build_flags =
|
||||
lib_deps =
|
||||
${esp32s3_base.lib_deps}
|
||||
# renovate: datasource=git-refs depName=meshtastic-st7789 packageName=https://github.com/meshtastic/st7789 gitBranch=main
|
||||
https://github.com/meshtastic/st7789/archive/a787beea5c6c8f864ba6787eb432bbefc575e6ad.zip
|
||||
https://github.com/meshtastic/st7789/archive/92bae2e4a307afb430c3b0bc3d661c55ee1565f0.zip
|
||||
upload_speed = 921600
|
||||
|
||||
@@ -17,4 +17,3 @@ build_flags =
|
||||
${esp32s3_base.build_flags}
|
||||
-D HELTEC_WSL_V3
|
||||
-I variants/esp32s3/heltec_wsl_v3
|
||||
-ULED_BUILTIN
|
||||
|
||||
@@ -11,3 +11,4 @@ build_flags =
|
||||
-DRADIOLIB_EXCLUDE_SX128X=1
|
||||
-DRADIOLIB_EXCLUDE_SX127X=1
|
||||
-DRADIOLIB_EXCLUDE_LR11X0=1
|
||||
-DRADIOLIB_EXCLUDE_LR2021=1
|
||||
|
||||
@@ -16,7 +16,7 @@ build_src_filter =
|
||||
lib_deps =
|
||||
${esp32s3_base.lib_deps}
|
||||
# renovate: datasource=git-refs depName=meshtastic-st7789 packageName=https://github.com/meshtastic/st7789 gitBranch=main
|
||||
https://github.com/meshtastic/st7789/archive/a787beea5c6c8f864ba6787eb432bbefc575e6ad.zip
|
||||
https://github.com/meshtastic/st7789/archive/92bae2e4a307afb430c3b0bc3d661c55ee1565f0.zip
|
||||
# renovate: datasource=github-tags depName=pschatzmann_arduino-audio-driver packageName=pschatzmann/arduino-audio-driver
|
||||
https://github.com/pschatzmann/arduino-audio-driver/archive/v0.2.1.zip
|
||||
# renovate: datasource=git-refs depName=ESP8266Audio packageName=https://github.com/meshtastic/ESP8266Audio gitBranch=meshtastic-2.0.0-dacfix
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
[portduino_base]
|
||||
platform =
|
||||
# renovate: datasource=git-refs depName=platform-native packageName=https://github.com/meshtastic/platform-native gitBranch=develop
|
||||
https://github.com/meshtastic/platform-native/archive/f566d364204416cdbf298e349213f7d551f793d9.zip
|
||||
https://github.com/meshtastic/platform-native/archive/71ed55bb95feb3c43ebde1ec1e2e17643a424c04.zip
|
||||
framework = arduino
|
||||
|
||||
build_src_filter =
|
||||
|
||||
@@ -11,4 +11,5 @@ build_flags = ${nrf52840_base.build_flags}
|
||||
-DRADIOLIB_EXCLUDE_SX128X=1
|
||||
-DRADIOLIB_EXCLUDE_SX127X=1
|
||||
-DRADIOLIB_EXCLUDE_LR11X0=1
|
||||
-DRADIOLIB_EXCLUDE_LR2021=1
|
||||
build_src_filter = ${nrf52_base.build_src_filter} +<../variants/nrf52840/gat562_mesh_trial_tracker>
|
||||
|
||||
@@ -23,4 +23,4 @@ build_src_filter = ${nrf52_base.build_src_filter} +<../variants/nrf52840/heltec_
|
||||
lib_deps =
|
||||
${nrf52840_base.lib_deps}
|
||||
# renovate: datasource=git-refs depName=meshtastic-st7789 packageName=https://github.com/meshtastic/st7789 gitBranch=main
|
||||
https://github.com/meshtastic/st7789/archive/a787beea5c6c8f864ba6787eb432bbefc575e6ad.zip
|
||||
https://github.com/meshtastic/st7789/archive/92bae2e4a307afb430c3b0bc3d661c55ee1565f0.zip
|
||||
|
||||
@@ -132,4 +132,4 @@ build_flags = ${heltec_mesh_solar_base.build_flags}
|
||||
lib_deps =
|
||||
${heltec_mesh_solar_base.lib_deps}
|
||||
# renovate: datasource=git-refs depName=meshtastic-st7789 packageName=https://github.com/meshtastic/st7789 gitBranch=main
|
||||
https://github.com/meshtastic/st7789/archive/a787beea5c6c8f864ba6787eb432bbefc575e6ad.zip
|
||||
https://github.com/meshtastic/st7789/archive/92bae2e4a307afb430c3b0bc3d661c55ee1565f0.zip
|
||||
|
||||
@@ -12,6 +12,7 @@ build_flags = ${nrf52840_base.build_flags}
|
||||
-DRADIOLIB_EXCLUDE_SX128X=1
|
||||
-DRADIOLIB_EXCLUDE_SX127X=1
|
||||
-DRADIOLIB_EXCLUDE_LR11X0=1
|
||||
-DRADIOLIB_EXCLUDE_LR2021=1
|
||||
|
||||
build_src_filter = ${nrf52_base.build_src_filter} +<../variants/nrf52840/meshlink>
|
||||
debug_tool = jlink
|
||||
@@ -30,6 +31,7 @@ build_flags = ${nrf52840_base.build_flags}
|
||||
-DRADIOLIB_EXCLUDE_SX128X=1
|
||||
-DRADIOLIB_EXCLUDE_SX127X=1
|
||||
-DRADIOLIB_EXCLUDE_LR11X0=1
|
||||
-DRADIOLIB_EXCLUDE_LR2021=1
|
||||
-D USE_EINK
|
||||
-D EINK_DISPLAY_MODEL=GxEPD2_213_B74
|
||||
-D EINK_WIDTH=250
|
||||
@@ -51,4 +53,4 @@ lib_deps =
|
||||
debug_tool = jlink
|
||||
; If not set we will default to uploading over serial (first it forces bootloader entry by talking 1200bps to cdcacm)
|
||||
; Note: as of 6/2013 the serial/bootloader based programming takes approximately 30 seconds
|
||||
;upload_protocol = jlink
|
||||
;upload_protocol = jlink
|
||||
|
||||
@@ -4,6 +4,7 @@ extends = nrf52_base
|
||||
build_flags =
|
||||
${nrf52_base.build_flags}
|
||||
-DSERIAL_BUFFER_SIZE=4096
|
||||
-DLED_BUILTIN=-1
|
||||
|
||||
lib_deps =
|
||||
${nrf52_base.lib_deps}
|
||||
@@ -79,4 +80,4 @@ debug_speed = 4000
|
||||
|
||||
; The following is not needed because it automatically tries do this
|
||||
;debug_server_ready_pattern = -.*GDB server started on port \d+.*
|
||||
;debug_port = localhost:3333
|
||||
;debug_port = localhost:3333
|
||||
|
||||
@@ -18,6 +18,7 @@ build_flags = ${nrf52840_base.build_flags}
|
||||
-DRADIOLIB_EXCLUDE_SX128X=1
|
||||
-DRADIOLIB_EXCLUDE_SX127X=1
|
||||
-DRADIOLIB_EXCLUDE_LR11X0=1
|
||||
-DRADIOLIB_EXCLUDE_LR2021=1
|
||||
build_src_filter = ${nrf52_base.build_src_filter} +<../variants/nrf52840/r1-neo> +<mesh/api/> +<mqtt/>
|
||||
lib_deps =
|
||||
${nrf52840_base.lib_deps}
|
||||
|
||||
@@ -18,6 +18,7 @@ build_flags = ${nrf52840_base.build_flags}
|
||||
-DRADIOLIB_EXCLUDE_SX128X=1
|
||||
-DRADIOLIB_EXCLUDE_SX127X=1
|
||||
-DRADIOLIB_EXCLUDE_LR11X0=1
|
||||
-DRADIOLIB_EXCLUDE_LR2021=1
|
||||
-DHAS_RAKPROT=1 ; Define if RAk OneWireSerial is used (disables GPS)
|
||||
build_src_filter = ${nrf52_base.build_src_filter} +<../variants/nrf52840/rak2560> +<mesh/api/> +<mqtt/> +<serialization/>
|
||||
lib_deps =
|
||||
|
||||
@@ -22,6 +22,7 @@ build_flags = ${nrf52840_base.build_flags}
|
||||
-DRADIOLIB_EXCLUDE_SX128X=1
|
||||
-DRADIOLIB_EXCLUDE_SX127X=1
|
||||
-DRADIOLIB_EXCLUDE_LR11X0=1
|
||||
-DRADIOLIB_EXCLUDE_LR2021=1
|
||||
build_src_filter = ${nrf52_base.build_src_filter} +<../variants/nrf52840/rak3401_1watt> +<mesh/api/>
|
||||
lib_deps =
|
||||
${nrf52840_base.lib_deps}
|
||||
|
||||
@@ -21,6 +21,7 @@ build_flags = ${nrf52840_base.build_flags}
|
||||
-DRADIOLIB_EXCLUDE_SX128X=1
|
||||
-DRADIOLIB_EXCLUDE_SX127X=1
|
||||
-DRADIOLIB_EXCLUDE_LR11X0=1
|
||||
-DRADIOLIB_EXCLUDE_LR2021=1
|
||||
build_src_filter = ${nrf52_base.build_src_filter} \
|
||||
+<../variants/nrf52840/rak4631> \
|
||||
+<mesh/eth/> \
|
||||
|
||||
@@ -11,6 +11,7 @@ build_flags = ${nrf52840_base.build_flags}
|
||||
-DRADIOLIB_EXCLUDE_SX128X=1
|
||||
-DRADIOLIB_EXCLUDE_SX127X=1
|
||||
-DRADIOLIB_EXCLUDE_LR11X0=1
|
||||
-DRADIOLIB_EXCLUDE_LR2021=1
|
||||
build_src_filter = ${nrf52_base.build_src_filter} +<../variants/nrf52840/rak4631_epaper>
|
||||
lib_deps =
|
||||
${nrf52840_base.lib_deps}
|
||||
|
||||
@@ -13,6 +13,7 @@ build_flags = ${nrf52840_base.build_flags}
|
||||
-D RADIOLIB_EXCLUDE_SX128X=1
|
||||
-D RADIOLIB_EXCLUDE_SX127X=1
|
||||
-D RADIOLIB_EXCLUDE_LR11X0=1
|
||||
-D RADIOLIB_EXCLUDE_LR2021=1
|
||||
build_src_filter = ${nrf52_base.build_src_filter} +<../variants/nrf52840/rak4631_epaper_onrxtx>
|
||||
lib_deps =
|
||||
${nrf52840_base.lib_deps}
|
||||
|
||||
@@ -21,6 +21,7 @@ build_flags = ${nrf52840_base.build_flags}
|
||||
-DRADIOLIB_EXCLUDE_SX128X=1
|
||||
-DRADIOLIB_EXCLUDE_SX127X=1
|
||||
-DRADIOLIB_EXCLUDE_LR11X0=1
|
||||
-DRADIOLIB_EXCLUDE_LR2021=1
|
||||
build_src_filter = ${nrf52_base.build_src_filter} +<../variants/nrf52840/rak4631_nomadstar_meteor_pro> +<mesh/api/> +<mqtt/>
|
||||
lib_deps =
|
||||
${nrf52840_base.lib_deps}
|
||||
|
||||
@@ -19,5 +19,6 @@ build_flags = ${nrf52840_base.build_flags}
|
||||
-DRADIOLIB_EXCLUDE_SX128X=1
|
||||
-DRADIOLIB_EXCLUDE_SX127X=1
|
||||
-DRADIOLIB_EXCLUDE_LR11X0=1
|
||||
-DRADIOLIB_EXCLUDE_LR2021=1
|
||||
-DMESHTASTIC_EXCLUDE_WIFI=1
|
||||
build_src_filter = ${nrf52_base.build_src_filter} +<../variants/nrf52840/rak_wismeshtag>
|
||||
|
||||
@@ -22,7 +22,6 @@ build_flags =
|
||||
-D HW_SPI1_DEVICE
|
||||
-D HAS_UDP_MULTICAST=1
|
||||
-fexceptions # for exception handling in MQTT
|
||||
-ULED_BUILTIN
|
||||
build_src_filter = ${rp2040_base.build_src_filter} +<mesh/wifi/>
|
||||
lib_deps =
|
||||
${rp2040_base.lib_deps}
|
||||
|
||||
@@ -16,6 +16,11 @@ Do not expect a working Meshtastic device with this target.
|
||||
#define LED_POWER PA0 // Green LED
|
||||
#define LED_STATE_ON 1
|
||||
|
||||
#define BATTERY_PIN AVBAT
|
||||
// ADC_MULTIPLIER: 3.0 = internal 1:3 bridge divider (DS13105§3.18.3)
|
||||
// Margin: 1.10 = AVBAT divider tolerance ±10% (Table 82)
|
||||
#define ADC_MULTIPLIER (1.01f * 3)
|
||||
|
||||
#define RAK3172
|
||||
#define SERIAL_PRINT_PORT 1
|
||||
|
||||
|
||||
@@ -13,9 +13,19 @@ build_flags =
|
||||
${stm32_base.build_flags}
|
||||
-Ivariants/stm32/russell
|
||||
-DPRIVATE_HW
|
||||
-DMESHTASTIC_EXCLUDE_AIR_QUALITY_SENSOR=1
|
||||
-DMESHTASTIC_EXCLUDE_RANGETEST=1
|
||||
-DMESHTASTIC_EXCLUDE_DETECTIONSENSOR=1
|
||||
-DMESHTASTIC_EXCLUDE_EXTERNALNOTIFICATION=1
|
||||
-DMESHTASTIC_EXCLUDE_POWERSTRESS=1
|
||||
-DMESHTASTIC_EXCLUDE_NEIGHBORINFO=1
|
||||
-DMESHTASTIC_EXCLUDE_TRACEROUTE=1
|
||||
-DMESHTASTIC_EXCLUDE_WAYPOINT=1
|
||||
lib_deps =
|
||||
${stm32_base.lib_deps}
|
||||
# renovate: datasource=custom.pio depName=Adafruit BME280 packageName=adafruit/library/Adafruit BME280 Library
|
||||
adafruit/Adafruit BME280 Library@2.3.0
|
||||
# renovate: datasource=custom.pio depName=Adafruit_BME680 packageName=adafruit/library/Adafruit BME680 Library
|
||||
adafruit/Adafruit BME680 Library@2.0.6
|
||||
|
||||
upload_port = stlink
|
||||
|
||||
@@ -13,6 +13,16 @@
|
||||
// #define EXT_CHRG_DETECT PA5
|
||||
// #define EXT_PWR_DETECT PA4
|
||||
|
||||
#define BATTERY_PIN AVBAT
|
||||
// ADC_MULTIPLIER: 3.0 = internal 1:3 bridge divider (DS13105§3.18.3)
|
||||
// Margin: 1.10 = AVBAT divider tolerance ±10% (Table 82)
|
||||
#define ADC_MULTIPLIER (1.01f * 3)
|
||||
/*
|
||||
Sample OCV curve for Li-SOCl2 primary lithium cells (e.g. Saft cells have fresh OCV of 3.67V)
|
||||
#define NUM_OCV_POINTS 11
|
||||
#define OCV_ARRAY 3670, 3650, 3630, 3610, 3590, 3560, 3530, 3480, 3400, 3200, 2500
|
||||
*/
|
||||
|
||||
// Bosch Sensortec BME280
|
||||
#define HAS_SENSOR 1
|
||||
|
||||
@@ -20,6 +30,11 @@
|
||||
#define ENABLE_HWSERIAL1
|
||||
#define PIN_SERIAL1_RX PB7
|
||||
#define PIN_SERIAL1_TX PB6
|
||||
|
||||
// Debug serial (USART2)
|
||||
#define ENABLE_HWSERIAL2
|
||||
#define PIN_SERIAL2_TX PA2
|
||||
#define PIN_SERIAL2_RX PA3
|
||||
#define HAS_GPS 1
|
||||
#define PIN_GPS_STANDBY PA15
|
||||
#define GPS_RX_PIN PB7
|
||||
|
||||
@@ -35,6 +35,8 @@ build_flags =
|
||||
-DRADIOLIB_EXCLUDE_SX128X=1
|
||||
-DRADIOLIB_EXCLUDE_SX127X=1
|
||||
-DRADIOLIB_EXCLUDE_LR11X0=1
|
||||
-DRADIOLIB_EXCLUDE_LR2021=1
|
||||
-DMESHTASTIC_DYNAMIC_SBRK_HEAP
|
||||
-DHAL_DAC_MODULE_ONLY
|
||||
-DHAL_RNG_MODULE_ENABLED
|
||||
-Wl,--wrap=__assert_func
|
||||
@@ -56,3 +58,6 @@ lib_deps =
|
||||
|
||||
lib_ignore =
|
||||
OneButton
|
||||
|
||||
; Set a custom linker script with a higher MinStackSize value, to match NRF52.
|
||||
board_build.ldscript = $PROJECT_DIR/variants/stm32/stm32wle5xx.ld
|
||||
204
variants/stm32/stm32wle5xx.ld
Normal file
204
variants/stm32/stm32wle5xx.ld
Normal file
@@ -0,0 +1,204 @@
|
||||
/*
|
||||
******************************************************************************
|
||||
**
|
||||
** File : LinkerScript.ld
|
||||
**
|
||||
** Author : STM32CubeIDE
|
||||
**
|
||||
** Abstract : Linker script for STM32WL55xC Device
|
||||
** 256Kbytes FLASH
|
||||
** 64Kbytes RAM
|
||||
**
|
||||
** Set heap size, stack size and stack location according
|
||||
** to application requirements.
|
||||
**
|
||||
** Set memory bank area and size if external memory is used.
|
||||
**
|
||||
** Target : STMicroelectronics STM32
|
||||
**
|
||||
** Distribution: The file is distributed as is without any warranty
|
||||
** of any kind.
|
||||
**
|
||||
*****************************************************************************
|
||||
** @attention
|
||||
**
|
||||
** <h2><center>© Copyright (c) 2020 STMicroelectronics.
|
||||
** All rights reserved.</center></h2>
|
||||
**
|
||||
** This software component is licensed by ST under BSD 3-Clause license,
|
||||
** the "License"; You may not use this file except in compliance with the
|
||||
** License. You may obtain a copy of the License at:
|
||||
** opensource.org/licenses/BSD-3-Clause
|
||||
**
|
||||
*****************************************************************************
|
||||
*/
|
||||
|
||||
/* Entry Point */
|
||||
ENTRY(Reset_Handler)
|
||||
|
||||
/* Highest address of the user mode stack */
|
||||
_estack = ORIGIN(RAM) + LENGTH(RAM); /* end of "RAM" Ram type memory */
|
||||
|
||||
_Min_Heap_Size = 0x200 ; /* required amount of heap */
|
||||
/* Modified from original to 2KB, to match NRF52 */
|
||||
_Min_Stack_Size = 2048 ; /* required amount of stack */
|
||||
|
||||
/* Memories definition */
|
||||
MEMORY
|
||||
{
|
||||
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = LD_MAX_DATA_SIZE
|
||||
FLASH (rx) : ORIGIN = 0x08000000 + LD_FLASH_OFFSET, LENGTH = LD_MAX_SIZE - LD_FLASH_OFFSET
|
||||
}
|
||||
|
||||
/* Sections */
|
||||
SECTIONS
|
||||
{
|
||||
/* The startup code into "FLASH" Rom type memory */
|
||||
.isr_vector :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
KEEP(*(.isr_vector)) /* Startup code */
|
||||
. = ALIGN(4);
|
||||
} >FLASH
|
||||
|
||||
/* The program code and other data into "FLASH" Rom type memory */
|
||||
.text :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
*(.text) /* .text sections (code) */
|
||||
*(.text*) /* .text* sections (code) */
|
||||
*(.glue_7) /* glue arm to thumb code */
|
||||
*(.glue_7t) /* glue thumb to arm code */
|
||||
*(.eh_frame)
|
||||
|
||||
KEEP (*(.init))
|
||||
KEEP (*(.fini))
|
||||
|
||||
. = ALIGN(4);
|
||||
_etext = .; /* define a global symbols at end of code */
|
||||
} >FLASH
|
||||
|
||||
/* Constant data into "FLASH" Rom type memory */
|
||||
.rodata :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
*(.rodata) /* .rodata sections (constants, strings, etc.) */
|
||||
*(.rodata*) /* .rodata* sections (constants, strings, etc.) */
|
||||
. = ALIGN(4);
|
||||
} >FLASH
|
||||
|
||||
.ARM.extab (READONLY) : {
|
||||
. = ALIGN(4);
|
||||
*(.ARM.extab* .gnu.linkonce.armextab.*)
|
||||
. = ALIGN(4);
|
||||
} >FLASH
|
||||
|
||||
.ARM (READONLY) : {
|
||||
. = ALIGN(4);
|
||||
__exidx_start = .;
|
||||
*(.ARM.exidx*)
|
||||
__exidx_end = .;
|
||||
. = ALIGN(4);
|
||||
} >FLASH
|
||||
|
||||
.preinit_array (READONLY) :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
PROVIDE_HIDDEN (__preinit_array_start = .);
|
||||
KEEP (*(.preinit_array*))
|
||||
PROVIDE_HIDDEN (__preinit_array_end = .);
|
||||
. = ALIGN(4);
|
||||
} >FLASH
|
||||
|
||||
.init_array (READONLY) :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
PROVIDE_HIDDEN (__init_array_start = .);
|
||||
KEEP (*(SORT(.init_array.*)))
|
||||
KEEP (*(.init_array*))
|
||||
PROVIDE_HIDDEN (__init_array_end = .);
|
||||
. = ALIGN(4);
|
||||
} >FLASH
|
||||
|
||||
.fini_array (READONLY) :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
PROVIDE_HIDDEN (__fini_array_start = .);
|
||||
KEEP (*(SORT(.fini_array.*)))
|
||||
KEEP (*(.fini_array*))
|
||||
PROVIDE_HIDDEN (__fini_array_end = .);
|
||||
. = ALIGN(4);
|
||||
} >FLASH
|
||||
|
||||
/* Used by the startup to initialize data */
|
||||
_sidata = LOADADDR(.data);
|
||||
|
||||
/* Initialized data sections into "RAM" Ram type memory */
|
||||
.data :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
_sdata = .; /* create a global symbol at data start */
|
||||
*(.data) /* .data sections */
|
||||
*(.data*) /* .data* sections */
|
||||
*(.RamFunc) /* .RamFunc sections */
|
||||
*(.RamFunc*) /* .RamFunc* sections */
|
||||
|
||||
. = ALIGN(4);
|
||||
_edata = .; /* define a global symbol at data end */
|
||||
|
||||
} >RAM AT> FLASH
|
||||
|
||||
/* Uninitialized data section into "RAM" Ram type memory */
|
||||
. = ALIGN(4);
|
||||
.bss :
|
||||
{
|
||||
/* This is used by the startup in order to initialize the .bss section */
|
||||
_sbss = .; /* define a global symbol at bss start */
|
||||
__bss_start__ = _sbss;
|
||||
*(.bss)
|
||||
*(.bss*)
|
||||
*(COMMON)
|
||||
|
||||
. = ALIGN(4);
|
||||
_ebss = .; /* define a global symbol at bss end */
|
||||
__bss_end__ = _ebss;
|
||||
} >RAM
|
||||
|
||||
/* Define a noinit output section and mark it as NOLOAD to prevent
|
||||
* putting its contents into the resulting .bin file (which is the
|
||||
* default). */
|
||||
.noinit (NOLOAD) :
|
||||
{
|
||||
/* Ensure output is aligned */
|
||||
. = ALIGN(4);
|
||||
/* Define a global _snoinit (and _enoinit below) symbol just in case
|
||||
* code wants to iterate over all noinit variables for some reason */
|
||||
_snoinit = .;
|
||||
/* Actually import the .noinit and .noinit* import sections */
|
||||
*(.noinit)
|
||||
*(.noinit*)
|
||||
. = ALIGN(4);
|
||||
_enoinit = .;
|
||||
} >RAM
|
||||
|
||||
/* User_heap_stack section, used to check that there is enough "RAM" Ram type memory left */
|
||||
._user_heap_stack :
|
||||
{
|
||||
. = ALIGN(8);
|
||||
PROVIDE ( end = . );
|
||||
PROVIDE ( _end = . );
|
||||
. = . + _Min_Heap_Size;
|
||||
. = . + _Min_Stack_Size;
|
||||
. = ALIGN(8);
|
||||
} >RAM
|
||||
|
||||
/* Remove information from the compiler libraries */
|
||||
/DISCARD/ :
|
||||
{
|
||||
libc.a ( * )
|
||||
libm.a ( * )
|
||||
libgcc.a ( * )
|
||||
}
|
||||
|
||||
.ARM.attributes 0 : { *(.ARM.attributes) }
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
[VERSION]
|
||||
major = 2
|
||||
minor = 7
|
||||
build = 22
|
||||
build = 23
|
||||
|
||||
Reference in New Issue
Block a user