mirror of
https://github.com/meshcore-dev/MeshCore.git
synced 2026-04-20 22:13:47 +00:00
Add Radiomaster Bandit/Bandit Nano support
Added support for 5-Way analog joystick. Added Custom Sh1115 OLED driver. Added NeoPixels support for Radiomaster Bandit. Power output 20-30 dbm (100mW-1000mW). Changed so Analog joystick can be used in UI. Changed so NeoPixels is used for new Message. (Color can be defined). Radiomaster Bandit Micro uses the same code as Nano.
This commit is contained in:
parent
e33d93dc7f
commit
6c0da535b8
17 changed files with 1951 additions and 2 deletions
127
variants/radiomaster_900_bandit/BanditBoard.h
Normal file
127
variants/radiomaster_900_bandit/BanditBoard.h
Normal file
|
|
@ -0,0 +1,127 @@
|
|||
#pragma once
|
||||
|
||||
#include <Adafruit_NeoPixel.h>
|
||||
#include <Arduino.h>
|
||||
#include <helpers/ESP32Board.h>
|
||||
#include <helpers/ui/AnalogJoystick.h>
|
||||
|
||||
#define RADIOMASTER_900_BANDIT
|
||||
#define DISPLAY_CLASS SH1115Display
|
||||
|
||||
extern Adafruit_NeoPixel pixels;
|
||||
|
||||
// User-definable TX LED color (RGB hex format)
|
||||
// Examples: 0x00FF00 (green), 0xFF0000 (red), 0x0000FF (blue)
|
||||
#ifndef TX_LED_COLOR
|
||||
#define TX_LED_COLOR 0x009600 // Default: Green (0, 150, 0)
|
||||
#endif
|
||||
|
||||
// Extract RGB components from hex color for TX LED
|
||||
#define TX_LED_RED ((TX_LED_COLOR >> 16) & 0xFF)
|
||||
#define TX_LED_GREEN ((TX_LED_COLOR >> 8) & 0xFF)
|
||||
#define TX_LED_BLUE (TX_LED_COLOR & 0xFF)
|
||||
|
||||
/*
|
||||
6 x Neopixels, GRB
|
||||
GPIO 15
|
||||
Backgroundlight button 1 at index 0
|
||||
Backgroundlight button 2 at index 1
|
||||
|
||||
Button 1 at GPIO 34 - UNUSED
|
||||
Button 2 at GPIO 35 - UNUSED
|
||||
|
||||
STK8XXX Accelerometer I2C address 0x18 and Interrupt at GPIO 37
|
||||
*/
|
||||
|
||||
/*
|
||||
Pin connections from ESP32-D0WDQ6 to SX1276.
|
||||
*/
|
||||
#define P_LORA_DIO_0 22
|
||||
#define P_LORA_DIO_1 21
|
||||
#define P_LORA_NSS 4
|
||||
#define P_LORA_RESET 5
|
||||
#define P_LORA_SCLK 18
|
||||
#define P_LORA_MISO 19
|
||||
#define P_LORA_MOSI 23
|
||||
#define SX176X_TXEN 33
|
||||
|
||||
/*
|
||||
I2C SDA and SCL.
|
||||
*/
|
||||
#define PIN_BOARD_SDA 14
|
||||
#define PIN_BOARD_SCL 12
|
||||
|
||||
/*
|
||||
This unit has a FAN built-in.
|
||||
FAN is active at 250mW on it's ExpressLRS Firmware.
|
||||
Always ON
|
||||
*/
|
||||
#define PA_FAN_EN 2 // FAN on GPIO 2
|
||||
|
||||
/*
|
||||
This module has Skyworks SKY66122 controlled by dacWrite
|
||||
power rangeing from 100mW to 1000mW.
|
||||
|
||||
Mapping of PA_LEVEL to Power output: GPIO26/dacWrite
|
||||
168 -> 100mW -> 2.11v
|
||||
148 -> 250mW -> 1.87v
|
||||
128 -> 500mW -> 1.63v
|
||||
90 -> 1000mW -> 1.16v
|
||||
*/
|
||||
#define DAC_PA_PIN 26 // GPIO 26 enables the PA
|
||||
|
||||
// Configuration - adjust these for your hardware
|
||||
#define PA_CONSTANT_GAIN 18 // SKY66122 operates at constant 18dB gain
|
||||
#define MIN_OUTPUT_DBM 20 // 100mW minimum
|
||||
#define MAX_OUTPUT_DBM 30 // 1000mW maximum
|
||||
|
||||
// Calibration points from manufacturer
|
||||
struct PowerCalibration {
|
||||
uint8_t output_dbm;
|
||||
int8_t sx1278_dbm;
|
||||
uint8_t dac_value;
|
||||
};
|
||||
|
||||
// Values are from Radiomaster.
|
||||
const PowerCalibration calibration[] = {
|
||||
{ 20, 2, 165 }, // 100mW
|
||||
{ 24, 6, 155 }, // 250mW
|
||||
{ 27, 9, 142 }, // 500mW
|
||||
{ 30, 10, 110 } // 1000mW
|
||||
};
|
||||
|
||||
inline Adafruit_NeoPixel pixels(NEOPIXEL_NUM, PIN_NEOPIXEL, NEO_GRB + NEO_KHZ800);
|
||||
|
||||
const int NUM_CAL_POINTS = sizeof(calibration) / sizeof(calibration[0]);
|
||||
|
||||
class BanditBoard : public ESP32Board {
|
||||
private:
|
||||
public:
|
||||
void begin() {
|
||||
ESP32Board::begin();
|
||||
pixels.begin();
|
||||
pixels.clear();
|
||||
// pixels.setPixelColor(0, pixels.Color(255, 0, 0));
|
||||
// pixels.setPixelColor(1, pixels.Color(0, 255, 0));
|
||||
pixels.show();
|
||||
}
|
||||
// Return fake battery status, battery/fixed power is not monitored.
|
||||
uint16_t getBattMilliVolts() override { return 5000; }
|
||||
|
||||
const char *getManufacturerName() const override { return "RadioMaster Bandit"; }
|
||||
|
||||
void onBeforeTransmit() override {
|
||||
// Use user-defined TX LED color
|
||||
for (byte i = 2; i <= 6; i++) {
|
||||
pixels.setPixelColor(i, pixels.Color(TX_LED_RED, TX_LED_GREEN, TX_LED_BLUE));
|
||||
}
|
||||
pixels.show();
|
||||
}
|
||||
|
||||
void onAfterTransmit() override {
|
||||
for (byte i = 2; i <= 6; i++) {
|
||||
pixels.setPixelColor(i, pixels.Color(0, 0, 0));
|
||||
}
|
||||
pixels.show();
|
||||
}
|
||||
};
|
||||
276
variants/radiomaster_900_bandit/COLOR_EXAMPLES.md
Normal file
276
variants/radiomaster_900_bandit/COLOR_EXAMPLES.md
Normal file
|
|
@ -0,0 +1,276 @@
|
|||
# NeoPixel Color Examples & Recommendations
|
||||
|
||||
## 🎨 Complete Color Palette
|
||||
|
||||
### Primary Colors
|
||||
```
|
||||
Red: 0xFF0000 🔴 High urgency, attention-grabbing
|
||||
Green: 0x00FF00 🟢 Success, go, nature
|
||||
Blue: 0x0000FF 🔵 Calm, default, trust (DEFAULT)
|
||||
```
|
||||
|
||||
### Secondary Colors
|
||||
```
|
||||
Yellow: 0xFFFF00 🟡 Warning, caution, bright
|
||||
Cyan: 0x00FFFF ⚡ Cool, techy, calming
|
||||
Magenta: 0xFF00FF 💜 Unique, stands out
|
||||
```
|
||||
|
||||
### Extended Palette
|
||||
```
|
||||
Orange: 0xFF8000 🟠 Warm, friendly
|
||||
Purple: 0x8000FF 🟣 Creative, gentle
|
||||
Pink: 0xFF1493 💗 Soft, playful
|
||||
Hot Pink: 0xFF69B4 🎀 Very noticeable
|
||||
Lime: 0xBFFF00 🟢 Fresh, energetic
|
||||
Teal: 0x008080 🌊 Sophisticated
|
||||
Navy: 0x000080 🌑 Subtle, professional
|
||||
Maroon: 0x800000 🍷 Rich, subdued
|
||||
Olive: 0x808000 🫒 Natural, earthy
|
||||
Aqua: 0x00FF88 💎 Tropical, bright
|
||||
Violet: 0x8800FF 🔮 Mystical
|
||||
Coral: 0xFF7F50 🐠 Warm, inviting
|
||||
Turquoise: 0x40E0D0 🏖️ Refreshing
|
||||
Gold: 0xFFD700 ⭐ Valuable, special
|
||||
Silver: 0xC0C0C0 🤖 Modern, sleek
|
||||
```
|
||||
|
||||
### White Variants
|
||||
```
|
||||
Pure White: 0xFFFFFF ⚪ Maximum brightness
|
||||
Warm White: 0xFFCC88 🕯️ Cozy, comfortable
|
||||
Cool White: 0xCCDDFF ❄️ Clinical, clear
|
||||
Soft White: 0xFFEEDD 🌟 Gentle, easy on eyes
|
||||
```
|
||||
|
||||
## 📋 Use Case Recommendations
|
||||
|
||||
### High Priority / Urgent Messages
|
||||
**Best choices:**
|
||||
- `0xFF0000` (Red) - Classic alert color
|
||||
- `0xFF00FF` (Magenta) - Unusual, catches attention
|
||||
- `0xFFFF00` (Yellow) - Warning/caution
|
||||
- `0xFF1493` (Hot Pink) - Very noticeable
|
||||
|
||||
**Settings for urgent:**
|
||||
```ini
|
||||
build_flags =
|
||||
-DNEW_MSG_LED=0xFF0000 ; Red
|
||||
-DNEOPIXEL_MAX_BRIGHTNESS=120 ; Brighter
|
||||
-DNEOPIXEL_MSG_UPDATE_MILLIS=20 ; Faster breathing
|
||||
```
|
||||
|
||||
### Normal Priority Messages
|
||||
**Best choices:**
|
||||
- `0x0000FF` (Blue) - Default, professional
|
||||
- `0x00FFFF` (Cyan) - Visible but calm
|
||||
- `0x8000FF` (Purple) - Distinctive yet gentle
|
||||
- `0x00FF00` (Green) - Positive feeling
|
||||
|
||||
**Settings for normal:**
|
||||
```ini
|
||||
build_flags =
|
||||
-DNEW_MSG_LED=0x0000FF ; Blue
|
||||
-DNEOPIXEL_MAX_BRIGHTNESS=80 ; Standard
|
||||
-DNEOPIXEL_MSG_UPDATE_MILLIS=30 ; Normal speed
|
||||
```
|
||||
|
||||
### Low Distraction / Ambient
|
||||
**Best choices:**
|
||||
- `0x8000FF` (Purple) - Subtle
|
||||
- `0x008080` (Teal) - Sophisticated
|
||||
- `0x40E0D0` (Turquoise) - Calming
|
||||
- `0xFF7F50` (Coral) - Warm but not harsh
|
||||
|
||||
**Settings for ambient:**
|
||||
```ini
|
||||
build_flags =
|
||||
-DNEW_MSG_LED=0x8000FF ; Purple
|
||||
-DNEOPIXEL_MAX_BRIGHTNESS=40 ; Dim
|
||||
-DNEOPIXEL_MSG_UPDATE_MILLIS=50 ; Slow breathing
|
||||
```
|
||||
|
||||
### Battery Saving
|
||||
**Best choices (single LED color):**
|
||||
- `0xFF0000` (Red) - Only red LED
|
||||
- `0x00FF00` (Green) - Only green LED
|
||||
- `0x0000FF` (Blue) - Only blue LED
|
||||
|
||||
**Avoid for battery:**
|
||||
- ❌ `0xFFFFFF` (White) - All 3 LEDs at full
|
||||
- ❌ `0xFFFF00` (Yellow) - 2 LEDs at full
|
||||
- ❌ `0x00FFFF` (Cyan) - 2 LEDs at full
|
||||
- ❌ `0xFF00FF` (Magenta) - 2 LEDs at full
|
||||
|
||||
**Battery-conscious settings:**
|
||||
```ini
|
||||
build_flags =
|
||||
-DNEW_MSG_LED=0x00FF00 ; Green (single LED)
|
||||
-DNEOPIXEL_MAX_BRIGHTNESS=60 ; Moderate brightness
|
||||
-DNEOPIXEL_MIN_BRIGHTNESS=3 ; Very dim minimum
|
||||
```
|
||||
|
||||
## 🎭 Themed Configurations
|
||||
|
||||
### "Stealth Mode" - Minimal Visibility
|
||||
```ini
|
||||
build_flags =
|
||||
-DNEW_MSG_LED=0x000080 ; Navy blue
|
||||
-DNEOPIXEL_MAX_BRIGHTNESS=30
|
||||
-DNEOPIXEL_MIN_BRIGHTNESS=2
|
||||
-DNEOPIXEL_MSG_UPDATE_MILLIS=60
|
||||
```
|
||||
|
||||
### "Party Mode" - Maximum Attention
|
||||
```ini
|
||||
build_flags =
|
||||
-DNEW_MSG_LED=0xFF00FF ; Magenta
|
||||
-DNEOPIXEL_MAX_BRIGHTNESS=150
|
||||
-DNEOPIXEL_MIN_BRIGHTNESS=10
|
||||
-DNEOPIXEL_MSG_UPDATE_MILLIS=15
|
||||
```
|
||||
|
||||
### "Professional" - Subtle Business Setting
|
||||
```ini
|
||||
build_flags =
|
||||
-DNEW_MSG_LED=0x0000FF ; Blue
|
||||
-DNEOPIXEL_MAX_BRIGHTNESS=60
|
||||
-DNEOPIXEL_MSG_UPDATE_MILLIS=40
|
||||
```
|
||||
|
||||
### "Emergency Services" - High Visibility Red
|
||||
```ini
|
||||
build_flags =
|
||||
-DNEW_MSG_LED=0xFF0000 ; Red
|
||||
-DNEOPIXEL_MAX_BRIGHTNESS=120
|
||||
-DNEOPIXEL_MSG_UPDATE_MILLIS=15
|
||||
```
|
||||
|
||||
### "Nature Lover" - Earth Tones
|
||||
```ini
|
||||
build_flags =
|
||||
-DNEW_MSG_LED=0x00FF00 ; Green
|
||||
-DNEOPIXEL_MAX_BRIGHTNESS=70
|
||||
-DNEOPIXEL_MSG_UPDATE_MILLIS=35
|
||||
```
|
||||
|
||||
### "Gamer RGB" - Vibrant Cyan
|
||||
```ini
|
||||
build_flags =
|
||||
-DNEW_MSG_LED=0x00FFFF ; Cyan
|
||||
-DNEOPIXEL_MAX_BRIGHTNESS=100
|
||||
-DNEOPIXEL_MSG_UPDATE_MILLIS=25
|
||||
```
|
||||
|
||||
## 🔬 Color Mixing Guide
|
||||
|
||||
Want a custom color? Mix Red, Green, and Blue:
|
||||
|
||||
```
|
||||
Formula: 0xRRGGBB
|
||||
|
||||
RR = Red intensity (00 to FF in hex, 0 to 255 decimal)
|
||||
GG = Green intensity (00 to FF in hex, 0 to 255 decimal)
|
||||
BB = Blue intensity (00 to FF in hex, 0 to 255 decimal)
|
||||
```
|
||||
|
||||
### Quick Mix Examples:
|
||||
|
||||
**Orange** (Red + half Green):
|
||||
```
|
||||
0xFF8000 = 0xFF (255 red) + 0x80 (128 green) + 0x00 (0 blue)
|
||||
```
|
||||
|
||||
**Purple** (Red + Blue):
|
||||
```
|
||||
0x8000FF = 0x80 (128 red) + 0x00 (0 green) + 0xFF (255 blue)
|
||||
```
|
||||
|
||||
**Pink** (Red + some Green + Blue):
|
||||
```
|
||||
0xFF69B4 = 0xFF (255 red) + 0x69 (105 green) + 0xB4 (180 blue)
|
||||
```
|
||||
|
||||
### Hex to Decimal Quick Reference:
|
||||
```
|
||||
00 = 0 40 = 64 80 = 128 C0 = 192
|
||||
20 = 32 60 = 96 A0 = 160 E0 = 224
|
||||
30 = 48 70 = 112 B0 = 176 FF = 255
|
||||
```
|
||||
|
||||
## 💡 Pro Tips
|
||||
|
||||
### Visibility in Different Lighting
|
||||
- **Daylight/Bright**: Use high brightness (100-150) and saturated colors
|
||||
- **Indoor/Office**: Medium brightness (60-80) with any color
|
||||
- **Dark/Night**: Low brightness (30-50) to avoid being blinding
|
||||
- **Outdoors**: Blue/Cyan show well in daylight, red at night
|
||||
|
||||
### Color Psychology
|
||||
- **Red**: Urgency, danger, stop, important
|
||||
- **Green**: Go, success, safe, nature
|
||||
- **Blue**: Trust, calm, professional, default
|
||||
- **Yellow**: Warning, caution, attention
|
||||
- **Purple**: Creative, unique, mystical
|
||||
- **Cyan**: Tech, modern, cool
|
||||
- **Orange**: Friendly, energetic, warm
|
||||
- **White**: Clean, pure, maximum visibility
|
||||
|
||||
### Multi-User Scenarios
|
||||
If multiple people use devices, assign colors:
|
||||
- User 1: Blue `0x0000FF`
|
||||
- User 2: Green `0x00FF00`
|
||||
- User 3: Red `0xFF0000`
|
||||
- User 4: Magenta `0xFF00FF`
|
||||
- User 5: Cyan `0x00FFFF`
|
||||
|
||||
## 🧪 Testing Your Color
|
||||
|
||||
1. Choose your hex color
|
||||
2. Add to platformio.ini: `-DNEW_MSG_LED=0xYOURCOLOR`
|
||||
3. Build and flash
|
||||
4. Send yourself a test message
|
||||
5. Observe the breathing effect
|
||||
6. Adjust brightness/speed if needed
|
||||
|
||||
## 📱 Web Color Picker
|
||||
|
||||
Use any online color picker (search "RGB color picker") to find your perfect color:
|
||||
1. Pick your color visually
|
||||
2. Copy the RGB hex value (usually shown as #RRGGBB)
|
||||
3. Change # to 0x (e.g., #00FF00 becomes 0x00FF00)
|
||||
4. Use in your build configuration
|
||||
|
||||
## 🎨 Seasonal Colors
|
||||
|
||||
### Spring
|
||||
```
|
||||
Pastel Pink: 0xFFB6C1
|
||||
Mint Green: 0x98FF98
|
||||
Lavender: 0xE6E6FA
|
||||
```
|
||||
|
||||
### Summer
|
||||
```
|
||||
Tropical Blue: 0x00CED1
|
||||
Bright Yellow: 0xFFFF00
|
||||
Coral: 0xFF7F50
|
||||
```
|
||||
|
||||
### Autumn
|
||||
```
|
||||
Burnt Orange: 0xFF8C00
|
||||
Rust: 0xB7410E
|
||||
Gold: 0xFFD700
|
||||
```
|
||||
|
||||
### Winter
|
||||
```
|
||||
Ice Blue: 0xAFEEEE
|
||||
Snow White: 0xFFFAFA
|
||||
Silver: 0xC0C0C0
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
Remember: The color appears as a breathing/pulsing animation, so it will cycle between dim and bright, making it more dynamic than a static color!
|
||||
286
variants/radiomaster_900_bandit/LED_CONFIGURATION_GUIDE.md
Normal file
286
variants/radiomaster_900_bandit/LED_CONFIGURATION_GUIDE.md
Normal file
|
|
@ -0,0 +1,286 @@
|
|||
# LED Color Configuration Guide
|
||||
|
||||
## Overview
|
||||
|
||||
Your RadioMaster Bandit now has **two user-configurable LED colors**:
|
||||
|
||||
1. **TX_LED_COLOR** - Color during radio transmission (flash)
|
||||
2. **NEW_MSG_LED** - Color for new message notifications (breathing effect)
|
||||
|
||||
## Quick Setup
|
||||
|
||||
### platformio.ini Configuration
|
||||
|
||||
```ini
|
||||
[env:bandit]
|
||||
build_flags =
|
||||
-DTX_LED_COLOR=0x00FF00 ; Green transmission flash (default)
|
||||
-DNEW_MSG_LED=0x0000FF ; Blue message breathing (default)
|
||||
```
|
||||
|
||||
### Example Configurations
|
||||
|
||||
**Default (Green TX, Blue Messages):**
|
||||
```ini
|
||||
build_flags =
|
||||
-DTX_LED_COLOR=0x009600 ; Green (0, 150, 0) - slightly dimmed
|
||||
-DNEW_MSG_LED=0x0000FF ; Blue
|
||||
```
|
||||
|
||||
**All Red:**
|
||||
```ini
|
||||
build_flags =
|
||||
-DTX_LED_COLOR=0xFF0000 ; Red transmission
|
||||
-DNEW_MSG_LED=0xFF0000 ; Red messages
|
||||
```
|
||||
|
||||
**High Contrast (Red TX, Blue Messages):**
|
||||
```ini
|
||||
build_flags =
|
||||
-DTX_LED_COLOR=0xFF0000 ; Red transmission
|
||||
-DNEW_MSG_LED=0x0000FF ; Blue messages
|
||||
```
|
||||
|
||||
**Professional (Blue TX, Cyan Messages):**
|
||||
```ini
|
||||
build_flags =
|
||||
-DTX_LED_COLOR=0x0000FF ; Blue transmission
|
||||
-DNEW_MSG_LED=0x00FFFF ; Cyan messages
|
||||
```
|
||||
|
||||
**Stealth (Dim Purple for both):**
|
||||
```ini
|
||||
build_flags =
|
||||
-DTX_LED_COLOR=0x400040 ; Dim purple transmission
|
||||
-DNEW_MSG_LED=0x8000FF ; Purple messages
|
||||
```
|
||||
|
||||
**High Visibility (Yellow TX, Magenta Messages):**
|
||||
```ini
|
||||
build_flags =
|
||||
-DTX_LED_COLOR=0xFFFF00 ; Yellow transmission
|
||||
-DNEW_MSG_LED=0xFF00FF ; Magenta messages
|
||||
```
|
||||
|
||||
## Color Behavior
|
||||
|
||||
### TX_LED_COLOR (Transmission Flash)
|
||||
- **When**: During radio transmission
|
||||
- **NeoPixels**: 2-5 (indices 2, 3, 4, 5)
|
||||
- **Duration**: Brief flash while transmitting
|
||||
- **Effect**: Solid color, no animation
|
||||
- **Default**: Green (0x009600 = RGB 0, 150, 0)
|
||||
|
||||
### NEW_MSG_LED (Message Notification)
|
||||
- **When**: Unread messages exist
|
||||
- **NeoPixels**: 2-5 (indices 2, 3, 4, 5)
|
||||
- **Duration**: Continuous until messages read
|
||||
- **Effect**: Smooth breathing/pulsing
|
||||
- **Default**: Blue (0x0000FF)
|
||||
|
||||
### NeoPixel Layout
|
||||
```
|
||||
Index 0: Button 1 backlight (not controlled by these settings)
|
||||
Index 1: Button 2 backlight (not controlled by these settings)
|
||||
Index 2: TX flash / Message notification
|
||||
Index 3: TX flash / Message notification
|
||||
Index 4: TX flash / Message notification
|
||||
Index 5: TX flash / Message notification
|
||||
```
|
||||
|
||||
## Color Format
|
||||
|
||||
Both use RGB hex format: `0xRRGGBB`
|
||||
- RR = Red (00-FF hex / 0-255 decimal)
|
||||
- GG = Green (00-FF hex / 0-255 decimal)
|
||||
- BB = Blue (00-FF hex / 0-255 decimal)
|
||||
|
||||
### Common Colors
|
||||
|
||||
| Color | Hex | Decimal RGB |
|
||||
|-------|-----|-------------|
|
||||
| Red | `0xFF0000` | 255, 0, 0 |
|
||||
| Green | `0x00FF00` | 0, 255, 0 |
|
||||
| Blue | `0x0000FF` | 0, 0, 255 |
|
||||
| Yellow | `0xFFFF00` | 255, 255, 0 |
|
||||
| Cyan | `0x00FFFF` | 0, 255, 255 |
|
||||
| Magenta | `0xFF00FF` | 255, 0, 255 |
|
||||
| White | `0xFFFFFF` | 255, 255, 255 |
|
||||
| Orange | `0xFF8000` | 255, 128, 0 |
|
||||
| Purple | `0x8000FF` | 128, 0, 255 |
|
||||
|
||||
### Brightness Control
|
||||
|
||||
You can dim colors by reducing the values:
|
||||
|
||||
**Full Brightness Green:** `0x00FF00` (0, 255, 0)
|
||||
**Medium Green:** `0x008000` (0, 128, 0)
|
||||
**Dim Green:** `0x004000` (0, 64, 0)
|
||||
**Very Dim Green:** `0x002000` (0, 32, 0)
|
||||
|
||||
**Current default TX color:** `0x009600` (0, 150, 0) - medium-bright green
|
||||
|
||||
## Use Case Examples
|
||||
|
||||
### Emergency Services / High Visibility
|
||||
```ini
|
||||
build_flags =
|
||||
-DTX_LED_COLOR=0xFF0000 ; Red transmission (urgent)
|
||||
-DNEW_MSG_LED=0xFF0000 ; Red messages (urgent)
|
||||
```
|
||||
|
||||
### Professional / Office
|
||||
```ini
|
||||
build_flags =
|
||||
-DTX_LED_COLOR=0x004080 ; Dim blue transmission
|
||||
-DNEW_MSG_LED=0x0000FF ; Blue messages
|
||||
```
|
||||
|
||||
### Battery Saver (Single color LEDs)
|
||||
```ini
|
||||
build_flags =
|
||||
-DTX_LED_COLOR=0x00FF00 ; Green only (1 LED per pixel)
|
||||
-DNEW_MSG_LED=0x00FF00 ; Green only (1 LED per pixel)
|
||||
```
|
||||
|
||||
### Nighttime / Low Light
|
||||
```ini
|
||||
build_flags =
|
||||
-DTX_LED_COLOR=0x400000 ; Very dim red
|
||||
-DNEW_MSG_LED=0x400000 ; Very dim red
|
||||
```
|
||||
|
||||
### Color-Coded Operations
|
||||
```ini
|
||||
build_flags =
|
||||
-DTX_LED_COLOR=0xFFFF00 ; Yellow = transmitting
|
||||
-DNEW_MSG_LED=0x00FF00 ; Green = new message received
|
||||
```
|
||||
|
||||
### Rainbow Theme
|
||||
```ini
|
||||
build_flags =
|
||||
-DTX_LED_COLOR=0xFF00FF ; Magenta TX
|
||||
-DNEW_MSG_LED=0x00FFFF ; Cyan messages
|
||||
```
|
||||
|
||||
## Recommended Color Combinations
|
||||
|
||||
### Same Color (Unified Look)
|
||||
- Both Blue: `TX=0x0000FF, MSG=0x0000FF`
|
||||
- Both Green: `TX=0x00FF00, MSG=0x00FF00`
|
||||
- Both Red: `TX=0xFF0000, MSG=0xFF0000`
|
||||
|
||||
### Contrasting (Easy to Distinguish)
|
||||
- Red TX, Blue MSG: `TX=0xFF0000, MSG=0x0000FF`
|
||||
- Green TX, Magenta MSG: `TX=0x00FF00, MSG=0xFF00FF`
|
||||
- Yellow TX, Cyan MSG: `TX=0xFFFF00, MSG=0x00FFFF`
|
||||
|
||||
### Subtle (Professional)
|
||||
- Dim Blue TX, Blue MSG: `TX=0x000080, MSG=0x0000FF`
|
||||
- Dim Green TX, Cyan MSG: `TX=0x004000, MSG=0x00FFFF`
|
||||
- Dim Purple TX, Purple MSG: `TX=0x400040, MSG=0x8000FF`
|
||||
|
||||
## Power Consumption Notes
|
||||
|
||||
**Most Efficient (Single LED color):**
|
||||
- Red: `0xFF0000`
|
||||
- Green: `0x00FF00`
|
||||
- Blue: `0x0000FF`
|
||||
|
||||
**Medium Efficiency (Two LED colors):**
|
||||
- Yellow: `0xFFFF00` (Red + Green)
|
||||
- Cyan: `0x00FFFF` (Green + Blue)
|
||||
- Magenta: `0xFF00FF` (Red + Blue)
|
||||
|
||||
**Least Efficient (All LEDs):**
|
||||
- White: `0xFFFFFF` (Red + Green + Blue)
|
||||
|
||||
Lower brightness values also save power:
|
||||
- `0x00FF00` = 255 brightness
|
||||
- `0x008000` = 128 brightness (half power)
|
||||
- `0x004000` = 64 brightness (quarter power)
|
||||
|
||||
## Testing Your Configuration
|
||||
|
||||
1. Set your colors in `platformio.ini`
|
||||
2. Build and flash: `pio run -t upload`
|
||||
3. **Test TX LED**: Send a message - should see brief flash in TX_LED_COLOR
|
||||
4. **Test MSG LED**: Receive a message - should see breathing effect in NEW_MSG_LED
|
||||
5. Adjust brightness/colors as needed
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
**Colors look wrong:**
|
||||
- Verify hex format: `0xRRGGBB` with `0x` prefix
|
||||
- Check build flags are being applied (view compiler output)
|
||||
- NeoPixels are GRB format, but code handles conversion
|
||||
|
||||
**TX flash too bright:**
|
||||
- Reduce TX_LED_COLOR values (e.g., `0x00FF00` → `0x008000`)
|
||||
|
||||
**Message breathing too dim:**
|
||||
- Adjust `NEOPIXEL_MAX_BRIGHTNESS` in UITask.cpp (default: 80)
|
||||
|
||||
**Want different brightness for TX vs MSG:**
|
||||
- TX: Adjust the color value directly (e.g., `0x009600` is dimmer than `0x00FF00`)
|
||||
- MSG: Adjust `NEOPIXEL_MAX_BRIGHTNESS` in code
|
||||
|
||||
## Advanced: Hex to RGB Conversion
|
||||
|
||||
If you want a specific RGB value:
|
||||
|
||||
**Formula:** `0xRRGGBB`
|
||||
|
||||
**Example - RGB(255, 128, 64) = Orange:**
|
||||
1. Red = 255 = 0xFF
|
||||
2. Green = 128 = 0x80
|
||||
3. Blue = 64 = 0x40
|
||||
4. Result = `0xFF8040`
|
||||
|
||||
**Hex conversion chart:**
|
||||
```
|
||||
0 = 0x00 64 = 0x40 128 = 0x80 192 = 0xC0
|
||||
32 = 0x20 96 = 0x60 160 = 0xA0 224 = 0xE0
|
||||
48 = 0x30 112 = 0x70 176 = 0xB0 255 = 0xFF
|
||||
```
|
||||
|
||||
## Files Modified
|
||||
|
||||
1. **BanditBoard.h** - Added TX_LED_COLOR support
|
||||
2. **UITask.h** - NeoPixel message notification support
|
||||
3. **UITask.cpp** - NEW_MSG_LED color system
|
||||
|
||||
---
|
||||
|
||||
## Quick Copy-Paste Examples
|
||||
|
||||
### Default Configuration
|
||||
```ini
|
||||
-DTX_LED_COLOR=0x009600 -DNEW_MSG_LED=0x0000FF
|
||||
```
|
||||
|
||||
### All Green
|
||||
```ini
|
||||
-DTX_LED_COLOR=0x00FF00 -DNEW_MSG_LED=0x00FF00
|
||||
```
|
||||
|
||||
### All Red
|
||||
```ini
|
||||
-DTX_LED_COLOR=0xFF0000 -DNEW_MSG_LED=0xFF0000
|
||||
```
|
||||
|
||||
### Red TX, Blue Messages
|
||||
```ini
|
||||
-DTX_LED_COLOR=0xFF0000 -DNEW_MSG_LED=0x0000FF
|
||||
```
|
||||
|
||||
### Yellow TX, Magenta Messages
|
||||
```ini
|
||||
-DTX_LED_COLOR=0xFFFF00 -DNEW_MSG_LED=0xFF00FF
|
||||
```
|
||||
|
||||
### Dim Everything (Stealth)
|
||||
```ini
|
||||
-DTX_LED_COLOR=0x202020 -DNEW_MSG_LED=0x404040
|
||||
```
|
||||
190
variants/radiomaster_900_bandit/QUICK_REFERENCE.md
Normal file
190
variants/radiomaster_900_bandit/QUICK_REFERENCE.md
Normal file
|
|
@ -0,0 +1,190 @@
|
|||
# Quick Reference: NeoPixel LED Configuration
|
||||
|
||||
## 🎨 Two Configurable LED Colors
|
||||
|
||||
### TX_LED_COLOR - Radio Transmission Flash
|
||||
Color shown on NeoPixels 2-5 during transmission
|
||||
|
||||
### NEW_MSG_LED - Message Notification Breathing
|
||||
Color shown on NeoPixels 2-5 when you have unread messages
|
||||
|
||||
## ⚡ Quick Setup
|
||||
|
||||
### platformio.ini
|
||||
```ini
|
||||
build_flags =
|
||||
-DTX_LED_COLOR=0x00FF00 ; Green transmission flash
|
||||
-DNEW_MSG_LED=0x0000FF ; Blue message breathing
|
||||
```
|
||||
|
||||
### In Code
|
||||
```cpp
|
||||
#define TX_LED_COLOR 0x00FF00 // Green transmission
|
||||
#define NEW_MSG_LED 0x0000FF // Blue messages
|
||||
```
|
||||
|
||||
## 🌈 Popular Colors
|
||||
|
||||
| Color | Hex | Use For |
|
||||
|-------|-----|---------|
|
||||
| Blue | `0x0000FF` | Professional, calm |
|
||||
| Green | `0x00FF00` | Success, go, battery-friendly |
|
||||
| Red | `0xFF0000` | Urgent, stop, attention |
|
||||
| Yellow | `0xFFFF00` | Warning, caution |
|
||||
| Cyan | `0x00FFFF` | Modern, cool |
|
||||
| Magenta | `0xFF00FF` | Unique, stands out |
|
||||
| Orange | `0xFF8000` | Friendly, warm |
|
||||
| Purple | `0x8000FF` | Subtle, creative |
|
||||
| White | `0xFFFFFF` | Maximum visibility |
|
||||
|
||||
## 📋 Recommended Combinations
|
||||
|
||||
### Defaults
|
||||
```ini
|
||||
-DTX_LED_COLOR=0x009600 -DNEW_MSG_LED=0x0000FF
|
||||
```
|
||||
Green TX flash (dimmed), Blue message breathing
|
||||
|
||||
### All Green (Battery Saver)
|
||||
```ini
|
||||
-DTX_LED_COLOR=0x00FF00 -DNEW_MSG_LED=0x00FF00
|
||||
```
|
||||
|
||||
### All Red (High Urgency)
|
||||
```ini
|
||||
-DTX_LED_COLOR=0xFF0000 -DNEW_MSG_LED=0xFF0000
|
||||
```
|
||||
|
||||
### High Contrast
|
||||
```ini
|
||||
-DTX_LED_COLOR=0xFF0000 -DNEW_MSG_LED=0x0000FF
|
||||
```
|
||||
Red TX, Blue messages - easy to distinguish
|
||||
|
||||
### Professional
|
||||
```ini
|
||||
-DTX_LED_COLOR=0x0000FF -DNEW_MSG_LED=0x00FFFF
|
||||
```
|
||||
Blue TX, Cyan messages - business-friendly
|
||||
|
||||
### Stealth Mode
|
||||
```ini
|
||||
-DTX_LED_COLOR=0x202020 -DNEW_MSG_LED=0x404040
|
||||
```
|
||||
Very dim for low visibility
|
||||
|
||||
## 🔧 Files Modified
|
||||
|
||||
1. **BanditBoard.h** - TX_LED_COLOR support
|
||||
2. **UITask.h** - NEW_MSG_LED variables
|
||||
3. **UITask.cpp** - NEW_MSG_LED color system
|
||||
|
||||
## 📊 LED Behavior
|
||||
|
||||
| Event | NeoPixels 0-1 | NeoPixels 2-5 |
|
||||
|-------|---------------|---------------|
|
||||
| Radio TX | Unchanged | TX_LED_COLOR (flash) |
|
||||
| New messages | Unchanged | NEW_MSG_LED (breathing) |
|
||||
| No messages | Unchanged | OFF |
|
||||
|
||||
## 🎛️ Advanced Tweaks
|
||||
|
||||
### Dim TX Flash
|
||||
```cpp
|
||||
#define TX_LED_COLOR 0x004000 // Dim green (was 0x00FF00)
|
||||
```
|
||||
|
||||
### Brighter Messages
|
||||
```cpp
|
||||
#define NEOPIXEL_MAX_BRIGHTNESS 120 // In UITask.cpp (was 80)
|
||||
```
|
||||
|
||||
### Faster Breathing
|
||||
```cpp
|
||||
#define NEOPIXEL_MSG_UPDATE_MILLIS 20 // In UITask.cpp (was 30)
|
||||
```
|
||||
|
||||
### Smoother Breathing
|
||||
```cpp
|
||||
#define NEOPIXEL_BRIGHTNESS_STEP 1 // In UITask.cpp (was 2)
|
||||
```
|
||||
|
||||
## 🔋 Battery Considerations
|
||||
|
||||
**Most Efficient (single LED):**
|
||||
- `0xFF0000` (Red only)
|
||||
- `0x00FF00` (Green only)
|
||||
- `0x0000FF` (Blue only)
|
||||
|
||||
**Less Efficient (multiple LEDs):**
|
||||
- `0xFFFF00` (Yellow = Red + Green)
|
||||
- `0x00FFFF` (Cyan = Green + Blue)
|
||||
- `0xFF00FF` (Magenta = Red + Blue)
|
||||
- `0xFFFFFF` (White = all three)
|
||||
|
||||
**Brightness matters:**
|
||||
- `0x00FF00` = full brightness
|
||||
- `0x008000` = half brightness (50% power)
|
||||
- `0x004000` = quarter brightness (25% power)
|
||||
|
||||
## 💡 Color Format
|
||||
|
||||
`0xRRGGBB` where:
|
||||
- RR = Red (00-FF hex)
|
||||
- GG = Green (00-FF hex)
|
||||
- BB = Blue (00-FF hex)
|
||||
|
||||
Examples:
|
||||
- Orange: `0xFF8000` = RGB(255, 128, 0)
|
||||
- Pink: `0xFF69B4` = RGB(255, 105, 180)
|
||||
- Teal: `0x008080` = RGB(0, 128, 128)
|
||||
|
||||
## 🧪 Testing
|
||||
|
||||
1. Set colors in platformio.ini
|
||||
2. Build: `pio run`
|
||||
3. Flash: `pio run -t upload`
|
||||
4. Test TX: Send a message → see TX_LED_COLOR flash
|
||||
5. Test MSG: Have unread messages → see NEW_MSG_LED breathing
|
||||
6. Adjust as needed
|
||||
|
||||
## ⚠️ Troubleshooting
|
||||
|
||||
**Wrong color?**
|
||||
→ Check hex format: `0xRRGGBB` with `0x` prefix
|
||||
|
||||
**TX too bright?**
|
||||
→ Lower TX_LED_COLOR values: `0x00FF00` → `0x008000`
|
||||
|
||||
**Messages too dim?**
|
||||
→ Increase NEOPIXEL_MAX_BRIGHTNESS in UITask.cpp
|
||||
|
||||
**Colors not applying?**
|
||||
→ Check compiler output for build flags
|
||||
|
||||
## 📝 Quick Copy Examples
|
||||
|
||||
### Green TX, Blue MSG (default)
|
||||
```
|
||||
-DTX_LED_COLOR=0x009600 -DNEW_MSG_LED=0x0000FF
|
||||
```
|
||||
|
||||
### Red TX, Red MSG
|
||||
```
|
||||
-DTX_LED_COLOR=0xFF0000 -DNEW_MSG_LED=0xFF0000
|
||||
```
|
||||
|
||||
### Yellow TX, Magenta MSG
|
||||
```
|
||||
-DTX_LED_COLOR=0xFFFF00 -DNEW_MSG_LED=0xFF00FF
|
||||
```
|
||||
|
||||
### Cyan TX, Purple MSG
|
||||
```
|
||||
-DTX_LED_COLOR=0x00FFFF -DNEW_MSG_LED=0x8000FF
|
||||
```
|
||||
|
||||
### Dim White TX, Bright White MSG
|
||||
```
|
||||
-DTX_LED_COLOR=0x404040 -DNEW_MSG_LED=0xFFFFFF
|
||||
```
|
||||
94
variants/radiomaster_900_bandit/platformio.ini
Normal file
94
variants/radiomaster_900_bandit/platformio.ini
Normal file
|
|
@ -0,0 +1,94 @@
|
|||
[radiomaster_900_bandit]
|
||||
extends = esp32_base
|
||||
board = esp32dev
|
||||
#upload_flags = --before default_reset
|
||||
build_flags =
|
||||
${esp32_base.build_flags}
|
||||
-I variants/radiomaster_900_bandit
|
||||
-D RADIOMASTER_900_BANDIT
|
||||
-D SX127X_CURRENT_LIMIT=120
|
||||
-D RADIO_CLASS=CustomSX1276
|
||||
-D WRAPPER_CLASS=CustomSX1276Wrapper
|
||||
-D DISPLAY_CLASS=SH1115Display ; I've added the SH1115 driver to Adafruit_SH110x that is avaible on ny github @ https://github.com/gjelsoe/Adafruit_SH110x
|
||||
; The SH1106 will work, but there are some small pixels misplacement. Haven't testet if SH1107 will work better.
|
||||
-D NEW_MSG_LED=0x0000FF ; Blue New message notification LED color, to diable enter 0x000000.
|
||||
-D TX_LED_COLOR=0x009600 ; Green TX LED color, to diable enter 0x000000.
|
||||
-D PIN_NEOPIXEL=15 ; Data GPIO of the NEOPIXELS.
|
||||
-D NEOPIXEL_NUM=6 ; Number of NEOPIXELS.
|
||||
-D SX176X_TXEN=33
|
||||
-D MAX_LORA_TX_POWER=30
|
||||
-D LORA_TX_POWER=20
|
||||
-D PIN_BOARD_SDA=14
|
||||
-D PIN_BOARD_SCL=12
|
||||
-D PIN_USER_JOYSTICK=39
|
||||
-D ENV_INCLUDE_GPS=0
|
||||
build_src_filter = ${esp32_base.build_src_filter}
|
||||
+<../variants/radiomaster_900_bandit>
|
||||
+<helpers/ui/AnalogJoystick.cpp>
|
||||
+<helpers/ui/SH1115Display.cpp>
|
||||
+<helpers/sensors>
|
||||
|
||||
board_upload.flash_size = 8MB
|
||||
board_build.partitions = default_8MB.csv
|
||||
|
||||
lib_deps =
|
||||
${esp32_base.lib_deps}
|
||||
adafruit/Adafruit NeoPixel@^1.10.0
|
||||
https://github.com/gjelsoe/Adafruit_SH110x
|
||||
|
||||
[env:radiomaster_900_bandit_companion_radio_ble]
|
||||
extends = radiomaster_900_bandit
|
||||
board_build.upload.maximum_ram_size=2000000
|
||||
build_flags =
|
||||
${radiomaster_900_bandit.build_flags}
|
||||
-I examples/companion_radio/ui-new
|
||||
-D MAX_CONTACTS=160
|
||||
-D MAX_GROUP_CHANNELS=8
|
||||
-D BLE_PIN_CODE=123456
|
||||
; -D BLE_DEBUG_LOGGING=1
|
||||
-D OFFLINE_QUEUE_SIZE=256
|
||||
; -D RADIOLIB_DEBUG_BASIC=1
|
||||
; -D MESH_PACKET_LOGGING=1
|
||||
; -D MESH_DEBUG=1
|
||||
build_src_filter = ${radiomaster_900_bandit.build_src_filter}
|
||||
+<helpers/esp32/*.cpp>
|
||||
+<helpers/ui/MomentaryButton.cpp>
|
||||
+<../examples/companion_radio/*.cpp>
|
||||
+<../examples/companion_radio/ui-new/*.cpp>
|
||||
lib_deps =
|
||||
${radiomaster_900_bandit.lib_deps}
|
||||
densaugeo/base64 @ ~1.4.0
|
||||
|
||||
[env:radiomaster_900_bandit_repeater]
|
||||
extends = radiomaster_900_bandit
|
||||
build_flags =
|
||||
${radiomaster_900_bandit.build_flags}
|
||||
-D ADVERT_NAME='"Radiomaster Repeater"'
|
||||
-D ADVERT_LAT=0.0
|
||||
-D ADVERT_LON=0.0
|
||||
-D ADMIN_PASSWORD='"password"'
|
||||
-D MAX_NEIGHBOURS=50
|
||||
-D PERSISTANT_GPS=1
|
||||
; -D MESH_PACKET_LOGGING=1
|
||||
; -D MESH_DEBUG=1
|
||||
build_src_filter = ${radiomaster_900_bandit.build_src_filter}
|
||||
+<../examples/simple_repeater>
|
||||
lib_deps =
|
||||
${radiomaster_900_bandit.lib_deps}
|
||||
${esp32_ota.lib_deps}
|
||||
|
||||
[env:radiomaster_900_bandit_room_server]
|
||||
extends = radiomaster_900_bandit
|
||||
build_flags =
|
||||
${radiomaster_900_bandit.build_flags}
|
||||
-D ADVERT_NAME='"Radiomaster Room"'
|
||||
-D ADVERT_LAT=0.0
|
||||
-D ADVERT_LON=0.0
|
||||
-D ADMIN_PASSWORD='"password"'
|
||||
; -D MESH_PACKET_LOGGING=1
|
||||
; -D MESH_DEBUG=1
|
||||
build_src_filter = ${radiomaster_900_bandit.build_src_filter}
|
||||
+<../examples/simple_room_server>
|
||||
lib_deps =
|
||||
${radiomaster_900_bandit.lib_deps}
|
||||
${esp32_ota.lib_deps}
|
||||
160
variants/radiomaster_900_bandit/target.cpp
Normal file
160
variants/radiomaster_900_bandit/target.cpp
Normal file
|
|
@ -0,0 +1,160 @@
|
|||
#include "target.h"
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <helpers/ui/UIScreen.h>
|
||||
|
||||
BanditBoard board;
|
||||
|
||||
#if defined(P_LORA_SCLK)
|
||||
static SPIClass spi;
|
||||
RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_0, P_LORA_RESET, P_LORA_DIO_1, spi);
|
||||
#else
|
||||
RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_0, P_LORA_RESET, P_LORA_DIO_1);
|
||||
#endif
|
||||
|
||||
WRAPPER_CLASS radio_driver(radio, board);
|
||||
|
||||
ESP32RTCClock fallback_clock;
|
||||
AutoDiscoverRTCClock rtc_clock(fallback_clock);
|
||||
SensorManager sensors;
|
||||
|
||||
#ifndef PIN_USER_BTN
|
||||
#define PIN_USER_BTN (-1)
|
||||
#endif
|
||||
|
||||
#ifdef DISPLAY_CLASS
|
||||
DISPLAY_CLASS display;
|
||||
// MomentaryButton user_btn(PIN_USER_BTN, 1000, true);
|
||||
#if defined(PIN_USER_JOYSTICK)
|
||||
static AnalogJoystick::JoyADCMapping joystick_mappings[] = {
|
||||
{ 0, KEY_DOWN }, { 1290, KEY_SELECT }, { 1961, KEY_LEFT },
|
||||
{ 2668, KEY_RIGHT }, { 3227, KEY_UP }, { 4095, 0 } // IDLE
|
||||
};
|
||||
|
||||
AnalogJoystick analog_joystick(PIN_USER_JOYSTICK, joystick_mappings, 6, KEY_SELECT);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
bool radio_init() {
|
||||
|
||||
#ifdef PA_FAN_EN
|
||||
pinMode(PA_FAN_EN, OUTPUT);
|
||||
digitalWrite(PA_FAN_EN, 1);
|
||||
#endif
|
||||
|
||||
fallback_clock.begin();
|
||||
rtc_clock.begin(Wire);
|
||||
|
||||
#if defined(P_LORA_SCLK)
|
||||
return radio.std_init(&spi);
|
||||
#else
|
||||
return radio.std_init();
|
||||
#endif
|
||||
}
|
||||
|
||||
uint32_t radio_get_rng_seed() {
|
||||
return radio.random(0x7FFFFFFF);
|
||||
}
|
||||
|
||||
void radio_set_params(float freq, float bw, uint8_t sf, uint8_t cr) {
|
||||
radio.setFrequency(freq);
|
||||
radio.setSpreadingFactor(sf);
|
||||
radio.setBandwidth(bw);
|
||||
radio.setCodingRate(cr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Linear interpolation helper for integers
|
||||
*/
|
||||
int16_t lerp_int(uint8_t x, uint8_t x0, uint8_t x1, int16_t y0, int16_t y1) {
|
||||
if (x1 == x0) return y0;
|
||||
return y0 + ((int16_t)(x - x0) * (y1 - y0)) / (x1 - x0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set PA output power with automatic SX1276 and DAC calculation
|
||||
*
|
||||
* @param target_output_dbm Desired PA output power in dBm (20-30 dBm for 100-1000mW)
|
||||
* @param clamp_to_range If true, clamp out-of-range values to min/max instead of failing
|
||||
* @return true if successful, false if out of range and clamp_to_range is false
|
||||
*/
|
||||
bool setPAOutputPower(uint8_t target_output_dbm, bool clamp_to_range = true) {
|
||||
// Validate and clamp range
|
||||
if (target_output_dbm < MIN_OUTPUT_DBM) {
|
||||
if (clamp_to_range) {
|
||||
MESH_DEBUG_PRINT("Warning: Target %u dBm too low, clamping to min %u dBm\n", target_output_dbm,
|
||||
MIN_OUTPUT_DBM);
|
||||
target_output_dbm = MIN_OUTPUT_DBM;
|
||||
} else {
|
||||
MESH_DEBUG_PRINT("Error: Target %u dBm below minimum %u dBm\n", target_output_dbm, MIN_OUTPUT_DBM);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (target_output_dbm > MAX_OUTPUT_DBM) {
|
||||
if (clamp_to_range) {
|
||||
MESH_DEBUG_PRINT("Warning: Target %u dBm too high, clamping to max %u dBm\n", target_output_dbm,
|
||||
MAX_OUTPUT_DBM);
|
||||
target_output_dbm = MAX_OUTPUT_DBM;
|
||||
} else {
|
||||
MESH_DEBUG_PRINT("Error: Target %u dBm above maximum %u dBm\n", target_output_dbm, MAX_OUTPUT_DBM);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Find the calibration points to interpolate between
|
||||
int lower_idx = 0;
|
||||
int upper_idx = NUM_CAL_POINTS - 1;
|
||||
|
||||
for (int i = 0; i < NUM_CAL_POINTS - 1; i++) {
|
||||
if (target_output_dbm >= calibration[i].output_dbm &&
|
||||
target_output_dbm <= calibration[i + 1].output_dbm) {
|
||||
lower_idx = i;
|
||||
upper_idx = i + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Handle exact matches
|
||||
if (target_output_dbm == calibration[lower_idx].output_dbm) {
|
||||
int8_t sx1278_power = calibration[lower_idx].sx1278_dbm;
|
||||
uint8_t dac_value = calibration[lower_idx].dac_value;
|
||||
|
||||
radio.setOutputPower(sx1278_power, true); // RFO output
|
||||
dacWrite(DAC_PA_PIN, dac_value);
|
||||
|
||||
MESH_DEBUG_PRINT("Set power: %u dBm (SX1278: %d dBm, DAC: %u)\n", target_output_dbm, sx1278_power,
|
||||
dac_value);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Linear interpolation between calibration points
|
||||
uint8_t lower_out = calibration[lower_idx].output_dbm;
|
||||
uint8_t upper_out = calibration[upper_idx].output_dbm;
|
||||
|
||||
// Interpolate SX1278 power (maintaining 18dB gain relationship)
|
||||
int16_t sx1278_power = lerp_int(target_output_dbm, lower_out, upper_out, calibration[lower_idx].sx1278_dbm,
|
||||
calibration[upper_idx].sx1278_dbm);
|
||||
|
||||
// Interpolate DAC value
|
||||
int16_t dac_value = lerp_int(target_output_dbm, lower_out, upper_out, calibration[lower_idx].dac_value,
|
||||
calibration[upper_idx].dac_value);
|
||||
|
||||
// Set the calculated values
|
||||
radio.setOutputPower((int8_t)sx1278_power, true); // RFO output
|
||||
dacWrite(DAC_PA_PIN, (uint8_t)dac_value);
|
||||
|
||||
MESH_DEBUG_PRINT("Set power: %u dBm (SX1278: %d dBm, DAC: %u)\n", target_output_dbm, sx1278_power,
|
||||
dac_value);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void radio_set_tx_power(uint8_t dbm) {
|
||||
setPAOutputPower(dbm);
|
||||
}
|
||||
|
||||
mesh::LocalIdentity radio_new_identity() {
|
||||
RadioNoiseListener rng(radio);
|
||||
return mesh::LocalIdentity(&rng); // create new random identity
|
||||
}
|
||||
33
variants/radiomaster_900_bandit/target.h
Normal file
33
variants/radiomaster_900_bandit/target.h
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
#pragma once
|
||||
|
||||
#define RADIOLIB_STATIC_ONLY 1
|
||||
// #include <RadioLib.h>
|
||||
#include <BanditBoard.h>
|
||||
#include <helpers/AutoDiscoverRTCClock.h>
|
||||
#include <helpers/SensorManager.h>
|
||||
#include <helpers/radiolib/CustomSX1276Wrapper.h>
|
||||
#include <helpers/radiolib/RadioLibWrappers.h>
|
||||
|
||||
#ifdef DISPLAY_CLASS
|
||||
#include <helpers/ui/AnalogJoystick.h>
|
||||
#include <helpers/ui/SH1115Display.h>
|
||||
#endif
|
||||
|
||||
extern BanditBoard board;
|
||||
|
||||
extern WRAPPER_CLASS radio_driver;
|
||||
extern SensorManager sensors;
|
||||
extern AutoDiscoverRTCClock rtc_clock;
|
||||
|
||||
#ifdef DISPLAY_CLASS
|
||||
extern DISPLAY_CLASS display;
|
||||
#if defined(PIN_USER_JOYSTICK)
|
||||
extern AnalogJoystick analog_joystick;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
bool radio_init();
|
||||
uint32_t radio_get_rng_seed();
|
||||
void radio_set_params(float freq, float bw, uint8_t sf, uint8_t cr);
|
||||
void radio_set_tx_power(uint8_t dbm);
|
||||
mesh::LocalIdentity radio_new_identity();
|
||||
74
variants/radiomaster_900_bandit_nano/BanditNanoBoard.h
Normal file
74
variants/radiomaster_900_bandit_nano/BanditNanoBoard.h
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
#pragma once
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <helpers/ESP32Board.h>
|
||||
#include <helpers/ui/AnalogJoystick.h>
|
||||
|
||||
#define RADIOMASTER_900_BANDIT_NANO
|
||||
/*
|
||||
Pin connections from ESP32-D0WDQ6 to SX1276.
|
||||
*/
|
||||
#define P_LORA_DIO_0 22
|
||||
#define P_LORA_DIO_1 21
|
||||
#define P_LORA_NSS 4
|
||||
#define P_LORA_RESET 5
|
||||
#define P_LORA_SCLK 18
|
||||
#define P_LORA_MISO 19
|
||||
#define P_LORA_MOSI 23
|
||||
#define SX176X_TXEN 33
|
||||
|
||||
/*
|
||||
I2C SDA and SCL.
|
||||
*/
|
||||
#define PIN_BOARD_SDA 14
|
||||
#define PIN_BOARD_SCL 12
|
||||
|
||||
/*
|
||||
This unit has a FAN built-in.
|
||||
FAN is active at 250mW on it's ExpressLRS Firmware.
|
||||
Always ON
|
||||
*/
|
||||
#define PA_FAN_EN 2 // FAN on GPIO 2
|
||||
|
||||
/*
|
||||
This module has Skyworks SKY66122 controlled by dacWrite
|
||||
power rangeing from 100mW to 1000mW.
|
||||
|
||||
Mapping of PA_LEVEL to Power output: GPIO26/dacWrite
|
||||
168 -> 100mW -> 2.11v
|
||||
148 -> 250mW -> 1.87v
|
||||
128 -> 500mW -> 1.63v
|
||||
90 -> 1000mW -> 1.16v
|
||||
*/
|
||||
#define DAC_PA_PIN 26 // GPIO 26 controls the PA gain.
|
||||
|
||||
// Configuration - adjust these for your hardware
|
||||
#define PA_CONSTANT_GAIN 18 // SKY66122 operates at constant 18dB gain
|
||||
#define MIN_OUTPUT_DBM 20 // 100mW minimum
|
||||
#define MAX_OUTPUT_DBM 30 // 1000mW maximum
|
||||
|
||||
// Calibration points from manufacturer
|
||||
struct PowerCalibration {
|
||||
uint8_t output_dbm;
|
||||
int8_t sx1278_dbm;
|
||||
uint8_t dac_value;
|
||||
};
|
||||
|
||||
// Values are from Radiomaster.
|
||||
const PowerCalibration calibration[] = {
|
||||
{ 20, 2, 168 }, // 100mW
|
||||
{ 24, 6, 148 }, // 250mW
|
||||
{ 27, 9, 128 }, // 500mW
|
||||
{ 30, 12, 90 } // 1000mW
|
||||
};
|
||||
|
||||
const int NUM_CAL_POINTS = sizeof(calibration) / sizeof(calibration[0]);
|
||||
|
||||
class BanditNanoBoard : public ESP32Board {
|
||||
private:
|
||||
public:
|
||||
// Return fake battery status, battery/fixed power is not monitored.
|
||||
uint16_t getBattMilliVolts() override { return 5000; }
|
||||
|
||||
const char *getManufacturerName() const override { return "RadioMaster Bandit Nano"; }
|
||||
};
|
||||
99
variants/radiomaster_900_bandit_nano/platformio.ini
Normal file
99
variants/radiomaster_900_bandit_nano/platformio.ini
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
[radiomaster_900_bandit_nano]
|
||||
extends = esp32_base
|
||||
board = esp32dev
|
||||
build_flags =
|
||||
${esp32_base.build_flags}
|
||||
-I variants/radiomaster_900_bandit_nano
|
||||
-D RADIOMASTER_900_BANDIT_NANO
|
||||
-D SX127X_CURRENT_LIMIT=120
|
||||
-D RADIO_CLASS=CustomSX1276
|
||||
-D WRAPPER_CLASS=CustomSX1276Wrapper
|
||||
-D DISPLAY_CLASS=SSD1306Display
|
||||
; -D P_LORA_DIO_1=21
|
||||
; -D P_LORA_DIO_0=22
|
||||
; -D P_LORA_NSS=4
|
||||
; -D P_LORA_RESET=5
|
||||
; -D P_LORA_SCLK=18
|
||||
; -D P_LORA_MISO=19
|
||||
; -D P_LORA_MOSI=23
|
||||
-D SX176X_TXEN=33
|
||||
-D MAX_LORA_TX_POWER=30
|
||||
-D LORA_TX_POWER=20
|
||||
-D P_LORA_TX_LED=15
|
||||
-D PIN_BOARD_SDA=14
|
||||
-D PIN_BOARD_SCL=12
|
||||
-D PIN_USER_JOYSTICK=39
|
||||
; -D PA_FAN_EN=2
|
||||
; -D PIN_PA_EN=26
|
||||
-D DISPLAY_ROTATION=2 ; Display is flipped
|
||||
-D ENV_INCLUDE_GPS=0
|
||||
|
||||
build_src_filter = ${esp32_base.build_src_filter}
|
||||
+<../variants/radiomaster_900_bandit_nano>
|
||||
+<helpers/ui/AnalogJoystick.cpp>
|
||||
+<helpers/ui/SSD1306Display.cpp>
|
||||
+<helpers/sensors>
|
||||
|
||||
board_upload.flash_size = 8MB
|
||||
board_build.partitions = default_8MB.csv
|
||||
|
||||
lib_deps =
|
||||
${esp32_base.lib_deps}
|
||||
adafruit/Adafruit SSD1306 @ ^2.5.13
|
||||
|
||||
[env:radiomaster_900_bandit_nano_companion_radio_ble]
|
||||
extends = radiomaster_900_bandit_nano
|
||||
;board_build.upload.maximum_ram_size=2000000
|
||||
build_flags =
|
||||
${radiomaster_900_bandit_nano.build_flags}
|
||||
-I examples/companion_radio/ui-new
|
||||
-D MAX_CONTACTS=160
|
||||
-D MAX_GROUP_CHANNELS=8
|
||||
-D BLE_PIN_CODE=123456
|
||||
; -D BLE_DEBUG_LOGGING=1
|
||||
-D OFFLINE_QUEUE_SIZE=256
|
||||
; -D RADIOLIB_DEBUG_BASIC=1
|
||||
; -D MESH_PACKET_LOGGING=1
|
||||
; -D MESH_DEBUG=1
|
||||
build_src_filter = ${radiomaster_900_bandit_nano.build_src_filter}
|
||||
+<helpers/esp32/*.cpp>
|
||||
+<helpers/ui/MomentaryButton.cpp>
|
||||
+<../examples/companion_radio/*.cpp>
|
||||
+<../examples/companion_radio/ui-new/*.cpp>
|
||||
lib_deps =
|
||||
${radiomaster_900_bandit_nano.lib_deps}
|
||||
densaugeo/base64 @ ~1.4.0
|
||||
|
||||
[env:radiomaster_900_bandit_nano_repeater]
|
||||
extends = radiomaster_900_bandit_nano
|
||||
build_flags =
|
||||
${radiomaster_900_bandit_nano.build_flags}
|
||||
-D ADVERT_NAME='"Radiomaster Repeater"'
|
||||
-D ADVERT_LAT=0.0
|
||||
-D ADVERT_LON=0.0
|
||||
-D ADMIN_PASSWORD='"password"'
|
||||
-D MAX_NEIGHBOURS=50
|
||||
-D PERSISTANT_GPS=1
|
||||
; -D MESH_PACKET_LOGGING=1
|
||||
; -D MESH_DEBUG=1
|
||||
build_src_filter = ${radiomaster_900_bandit_nano.build_src_filter}
|
||||
+<../examples/simple_repeater>
|
||||
lib_deps =
|
||||
${radiomaster_900_bandit_nano.lib_deps}
|
||||
${esp32_ota.lib_deps}
|
||||
|
||||
[env:radiomaster_900_bandit_nano_room_server]
|
||||
extends = radiomaster_900_bandit_nano
|
||||
build_flags =
|
||||
${radiomaster_900_bandit_nano.build_flags}
|
||||
-D ADVERT_NAME='"Radiomaster Room"'
|
||||
-D ADVERT_LAT=0.0
|
||||
-D ADVERT_LON=0.0
|
||||
-D ADMIN_PASSWORD='"password"'
|
||||
; -D MESH_PACKET_LOGGING=1
|
||||
; -D MESH_DEBUG=1
|
||||
build_src_filter = ${radiomaster_900_bandit_nano.build_src_filter}
|
||||
+<../examples/simple_room_server>
|
||||
lib_deps =
|
||||
${radiomaster_900_bandit_nano.lib_deps}
|
||||
${esp32_ota.lib_deps}
|
||||
160
variants/radiomaster_900_bandit_nano/target.cpp
Normal file
160
variants/radiomaster_900_bandit_nano/target.cpp
Normal file
|
|
@ -0,0 +1,160 @@
|
|||
#include "target.h"
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <helpers/ui/UIScreen.h>
|
||||
|
||||
BanditNanoBoard board;
|
||||
|
||||
#if defined(P_LORA_SCLK)
|
||||
static SPIClass spi;
|
||||
RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_0, P_LORA_RESET, P_LORA_DIO_1, spi);
|
||||
#else
|
||||
RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_0, P_LORA_RESET, P_LORA_DIO_1);
|
||||
#endif
|
||||
|
||||
WRAPPER_CLASS radio_driver(radio, board);
|
||||
|
||||
ESP32RTCClock fallback_clock;
|
||||
AutoDiscoverRTCClock rtc_clock(fallback_clock);
|
||||
SensorManager sensors;
|
||||
|
||||
#ifndef PIN_USER_BTN
|
||||
#define PIN_USER_BTN (-1)
|
||||
#endif
|
||||
|
||||
#ifdef DISPLAY_CLASS
|
||||
DISPLAY_CLASS display;
|
||||
// MomentaryButton user_btn(PIN_USER_BTN, 1000, true);
|
||||
#if defined(PIN_USER_JOYSTICK)
|
||||
static AnalogJoystick::JoyADCMapping joystick_mappings[] = {
|
||||
{ 0, KEY_DOWN }, { 1290, KEY_SELECT }, { 1961, KEY_LEFT },
|
||||
{ 2668, KEY_RIGHT }, { 3227, KEY_UP }, { 4095, 0 } // IDLE
|
||||
};
|
||||
|
||||
AnalogJoystick analog_joystick(PIN_USER_JOYSTICK, joystick_mappings, 6, KEY_SELECT);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
bool radio_init() {
|
||||
|
||||
#ifdef PA_FAN_EN
|
||||
pinMode(PA_FAN_EN, OUTPUT);
|
||||
digitalWrite(PA_FAN_EN, 1);
|
||||
#endif
|
||||
|
||||
fallback_clock.begin();
|
||||
rtc_clock.begin(Wire);
|
||||
|
||||
#if defined(P_LORA_SCLK)
|
||||
return radio.std_init(&spi);
|
||||
#else
|
||||
return radio.std_init();
|
||||
#endif
|
||||
}
|
||||
|
||||
uint32_t radio_get_rng_seed() {
|
||||
return radio.random(0x7FFFFFFF);
|
||||
}
|
||||
|
||||
void radio_set_params(float freq, float bw, uint8_t sf, uint8_t cr) {
|
||||
radio.setFrequency(freq);
|
||||
radio.setSpreadingFactor(sf);
|
||||
radio.setBandwidth(bw);
|
||||
radio.setCodingRate(cr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Linear interpolation helper for integers
|
||||
*/
|
||||
int16_t lerp_int(uint8_t x, uint8_t x0, uint8_t x1, int16_t y0, int16_t y1) {
|
||||
if (x1 == x0) return y0;
|
||||
return y0 + ((int16_t)(x - x0) * (y1 - y0)) / (x1 - x0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set PA output power with automatic SX1276 and DAC calculation
|
||||
*
|
||||
* @param target_output_dbm Desired PA output power in dBm (20-30 dBm for 100-1000mW)
|
||||
* @param clamp_to_range If true, clamp out-of-range values to min/max instead of failing
|
||||
* @return true if successful, false if out of range and clamp_to_range is false
|
||||
*/
|
||||
bool setPAOutputPower(uint8_t target_output_dbm, bool clamp_to_range = true) {
|
||||
// Validate and clamp range
|
||||
if (target_output_dbm < MIN_OUTPUT_DBM) {
|
||||
if (clamp_to_range) {
|
||||
MESH_DEBUG_PRINT("Warning: Target %u dBm too low, clamping to min %u dBm\n", target_output_dbm,
|
||||
MIN_OUTPUT_DBM);
|
||||
target_output_dbm = MIN_OUTPUT_DBM;
|
||||
} else {
|
||||
MESH_DEBUG_PRINT("Error: Target %u dBm below minimum %u dBm\n", target_output_dbm, MIN_OUTPUT_DBM);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (target_output_dbm > MAX_OUTPUT_DBM) {
|
||||
if (clamp_to_range) {
|
||||
MESH_DEBUG_PRINT("Warning: Target %u dBm too high, clamping to max %u dBm\n", target_output_dbm,
|
||||
MAX_OUTPUT_DBM);
|
||||
target_output_dbm = MAX_OUTPUT_DBM;
|
||||
} else {
|
||||
MESH_DEBUG_PRINT("Error: Target %u dBm above maximum %u dBm\n", target_output_dbm, MAX_OUTPUT_DBM);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Find the calibration points to interpolate between
|
||||
int lower_idx = 0;
|
||||
int upper_idx = NUM_CAL_POINTS - 1;
|
||||
|
||||
for (int i = 0; i < NUM_CAL_POINTS - 1; i++) {
|
||||
if (target_output_dbm >= calibration[i].output_dbm &&
|
||||
target_output_dbm <= calibration[i + 1].output_dbm) {
|
||||
lower_idx = i;
|
||||
upper_idx = i + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Handle exact matches
|
||||
if (target_output_dbm == calibration[lower_idx].output_dbm) {
|
||||
int8_t sx1278_power = calibration[lower_idx].sx1278_dbm;
|
||||
uint8_t dac_value = calibration[lower_idx].dac_value;
|
||||
|
||||
radio.setOutputPower(sx1278_power, true); // RFO output
|
||||
dacWrite(DAC_PA_PIN, dac_value);
|
||||
|
||||
MESH_DEBUG_PRINT("Set power: %u dBm (SX1278: %d dBm, DAC: %u)\n", target_output_dbm, sx1278_power,
|
||||
dac_value);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Linear interpolation between calibration points
|
||||
uint8_t lower_out = calibration[lower_idx].output_dbm;
|
||||
uint8_t upper_out = calibration[upper_idx].output_dbm;
|
||||
|
||||
// Interpolate SX1278 power (maintaining 18dB gain relationship)
|
||||
int16_t sx1278_power = lerp_int(target_output_dbm, lower_out, upper_out, calibration[lower_idx].sx1278_dbm,
|
||||
calibration[upper_idx].sx1278_dbm);
|
||||
|
||||
// Interpolate DAC value
|
||||
int16_t dac_value = lerp_int(target_output_dbm, lower_out, upper_out, calibration[lower_idx].dac_value,
|
||||
calibration[upper_idx].dac_value);
|
||||
|
||||
// Set the calculated values
|
||||
radio.setOutputPower((int8_t)sx1278_power, true); // RFO output
|
||||
dacWrite(DAC_PA_PIN, (uint8_t)dac_value);
|
||||
|
||||
MESH_DEBUG_PRINT("Set power: %u dBm (SX1278: %d dBm, DAC: %u)\n", target_output_dbm, sx1278_power,
|
||||
dac_value);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void radio_set_tx_power(uint8_t dbm) {
|
||||
setPAOutputPower(dbm);
|
||||
}
|
||||
|
||||
mesh::LocalIdentity radio_new_identity() {
|
||||
RadioNoiseListener rng(radio);
|
||||
return mesh::LocalIdentity(&rng); // create new random identity
|
||||
}
|
||||
35
variants/radiomaster_900_bandit_nano/target.h
Normal file
35
variants/radiomaster_900_bandit_nano/target.h
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
#pragma once
|
||||
|
||||
#define RADIOLIB_STATIC_ONLY 1
|
||||
// #include <RadioLib.h>
|
||||
#include <BanditNanoBoard.h>
|
||||
#include <helpers/AutoDiscoverRTCClock.h>
|
||||
#include <helpers/SensorManager.h>
|
||||
#include <helpers/radiolib/CustomSX1276Wrapper.h>
|
||||
#include <helpers/radiolib/RadioLibWrappers.h>
|
||||
|
||||
#ifdef DISPLAY_CLASS
|
||||
#include <helpers/ui/AnalogJoystick.h>
|
||||
// #include <helpers/ui/MomentaryButton.h>
|
||||
#include <helpers/ui/SSD1306Display.h>
|
||||
#endif
|
||||
|
||||
extern BanditNanoBoard board;
|
||||
|
||||
extern WRAPPER_CLASS radio_driver;
|
||||
extern SensorManager sensors;
|
||||
extern AutoDiscoverRTCClock rtc_clock;
|
||||
|
||||
#ifdef DISPLAY_CLASS
|
||||
extern DISPLAY_CLASS display;
|
||||
// extern MomentaryButton user_btn;
|
||||
#if defined(PIN_USER_JOYSTICK)
|
||||
extern AnalogJoystick analog_joystick;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
bool radio_init();
|
||||
uint32_t radio_get_rng_seed();
|
||||
void radio_set_params(float freq, float bw, uint8_t sf, uint8_t cr);
|
||||
void radio_set_tx_power(uint8_t dbm);
|
||||
mesh::LocalIdentity radio_new_identity();
|
||||
Loading…
Add table
Add a link
Reference in a new issue