Add ITU regions for this device and make GPS work.

This commit is contained in:
Thomas Göttgens
2026-04-21 15:13:43 +02:00
parent 0d08680104
commit b365c94981
6 changed files with 104 additions and 5 deletions
+16
View File
@@ -1239,6 +1239,22 @@ bool Power::axpChipInit()
PMU->disablePowerOutput(XPOWERS_DLDO1); // Invalid power channel, it does not exist
PMU->disablePowerOutput(XPOWERS_DLDO2); // Invalid power channel, it does not exist
PMU->disablePowerOutput(XPOWERS_VBACKUP);
} else if (HW_VENDOR == meshtastic_HardwareModel_TBEAM_BPF) {
// T-Beam BPF rail map (per schematic LilyGo_TBeam_BPF r2025-05-08):
// DCDC1 -> ESP32 + OLED 3V3 (always on, protected)
// ALDO2 -> MicroSD 3V3 (OFF at reset, must enable)
// ALDO4 -> L76K GNSS 3V3 (OFF at reset, must enable)
// ALDO1/3, BLDO1/2, DLDO1 -> user headers / unused at boot, leave at reset defaults.
// LoRa power is outside the PMU (external P-MOSFET switched by RF95_POWER_EN / IO16).
PMU->setPowerChannelVoltage(XPOWERS_ALDO4, 3300);
PMU->enablePowerOutput(XPOWERS_ALDO4);
PMU->setPowerChannelVoltage(XPOWERS_ALDO2, 3300);
PMU->enablePowerOutput(XPOWERS_ALDO2);
// Make sure nothing's driving into an unused rail
PMU->disablePowerOutput(XPOWERS_DCDC5);
PMU->disablePowerOutput(XPOWERS_DLDO1);
}
// disable all axp chip interrupt
+9
View File
@@ -112,6 +112,14 @@ void menuHandler::OnboardMessage()
void menuHandler::LoraRegionPicker(uint32_t duration)
{
#ifdef HAS_HAM_2M_ONLY
// Hardware is restricted to the amateur 2m band — offer only the two 2m regions
// so the user cannot pick a sub-GHz region the RF path cannot emit or receive.
static const LoraRegionOption regionOptions[] = {
{"ITU1_2M (144-146)", OptionsAction::Select, meshtastic_Config_LoRaConfig_RegionCode_ITU1_2M},
{"ITU2/3_2M (144-148)", OptionsAction::Select, meshtastic_Config_LoRaConfig_RegionCode_ITU23_2M},
};
#else
static const LoraRegionOption regionOptions[] = {
{"Back", OptionsAction::Back},
{"US", OptionsAction::Select, meshtastic_Config_LoRaConfig_RegionCode_US},
@@ -141,6 +149,7 @@ void menuHandler::LoraRegionPicker(uint32_t duration)
{"NP_865", OptionsAction::Select, meshtastic_Config_LoRaConfig_RegionCode_NP_865},
{"BR_902", OptionsAction::Select, meshtastic_Config_LoRaConfig_RegionCode_BR_902},
};
#endif
constexpr size_t regionCount = sizeof(regionOptions) / sizeof(regionOptions[0]);
static std::array<const char *, regionCount> regionLabels{};
+1 -1
View File
@@ -26,9 +26,9 @@ struct RegionProfile {
extern const RegionProfile PROFILE_STD;
extern const RegionProfile PROFILE_EU868;
extern const RegionProfile PROFILE_UNDEF;
extern const RegionProfile PROFILE_HAM;
// extern const RegionProfile PROFILE_LITE;
// extern const RegionProfile PROFILE_NARROW;
// extern const RegionProfile PROFILE_HAM;
// Map from old region names to new region enums
struct RegionInfo {
+7
View File
@@ -1124,6 +1124,13 @@ void NodeDB::installDefaultDeviceState()
memcpy(owner.macaddr, ourMacAddr, sizeof(owner.macaddr));
owner.has_is_unmessagable = true;
owner.is_unmessagable = false;
#ifdef HAS_HAM_2M_ONLY
// Ham-band-only hardware defaults to licensed operation. The user can still flip this off later
// (e.g. a commercial operator on an adjacent allocation who wants to keep encryption on) — we
// only set the default here, not on every boot.
owner.is_licensed = true;
#endif
}
// We reserve a few nodenums for future use
+67 -1
View File
@@ -54,6 +54,7 @@ static const meshtastic_Config_LoRaConfig_ModemPreset PRESETS_UNDEF[] = {meshtas
const RegionProfile PROFILE_STD = {PRESETS_STD, 0, 0, true, false, 0, 0, 0, 0};
const RegionProfile PROFILE_EU868 = {PRESETS_EU_868, 0, 0, false, false, 0, 0, 0, 0};
const RegionProfile PROFILE_UNDEF = {PRESETS_UNDEF, 0, 0, true, false, 0, 0, 0, 0};
const RegionProfile PROFILE_HAM = {PRESETS_STD, 0, 0, false, true, 0, 0, 0, 0};
#define RDEF(name, freq_start, freq_end, duty_cycle, power_limit, frequency_switching, wide_lora, profile_ptr) \
{ \
@@ -223,6 +224,19 @@ const RegionInfo regions[] = {
*/
RDEF(BR_902, 902.0f, 907.5f, 100, 30, false, false, PROFILE_STD),
/*
ITU Region 1 (Europe, Africa, Middle East, former USSR) amateur 2m allocation: 144.000 - 146.000 MHz.
Power limit is the regulatory ceiling (1 W / 30 dBm) — individual hardware will cap below this
via its own PA curve; the field here is just the legal upper bound.
*/
RDEF(ITU1_2M, 144.0f, 146.0f, 100, 30, false, false, PROFILE_HAM),
/*
ITU Region 2 (Americas) and Region 3 (Asia/Pacific) amateur 2m allocation: 144.000 - 148.000 MHz.
Typical admin rules (e.g. US FCC Part 97) allow well above 30 dBm for licensed operators.
*/
RDEF(ITU23_2M, 144.0f, 148.0f, 100, 30, false, false, PROFILE_HAM),
/*
2.4 GHZ WLAN Band equivalent. Only for SX128x chips.
*/
@@ -505,6 +519,23 @@ std::unique_ptr<RadioInterface> initLoRa()
rebootAtMsec = millis() + 5000;
}
}
// Hardware/region crosscheck for the amateur 2m band: ham-only boards must run a 2m region,
// and boards without 2m support must not run one. In either mismatch, drop to UNSET so the
// first-start picker runs and the user re-selects a legal region for the hardware.
const bool is2mRegion = config.lora.region == meshtastic_Config_LoRaConfig_RegionCode_ITU1_2M ||
config.lora.region == meshtastic_Config_LoRaConfig_RegionCode_ITU23_2M;
#ifdef HAS_HAM_2M_ONLY
const bool mismatch = !is2mRegion && config.lora.region != meshtastic_Config_LoRaConfig_RegionCode_UNSET;
#else
const bool mismatch = is2mRegion;
#endif
if (mismatch) {
LOG_WARN("Saved region incompatible with this hardware's RF path. Revert to unset");
config.lora.region = meshtastic_Config_LoRaConfig_RegionCode_UNSET;
nodeDB->saveToDisk(SEGMENT_CONFIG);
}
return rIf;
}
@@ -787,7 +818,14 @@ bool RadioInterface::validateConfigRegion(const meshtastic_Config_LoRaConfig &lo
const RegionInfo *newRegion = getRegion(loraConfig.region);
// If you are not licensed, you can't use ham regions.
if (newRegion->profile->licensedOnly && !devicestate.owner.is_licensed) {
// Exception: on hardware that can *only* operate on a ham band (e.g. T-Beam BPF), the user has
// no other region to choose, so allow unlicensed selection — a commercial operator on adjacent
// frequencies can still use the band plan and keep encryption enabled.
bool allowUnlicensedHam = false;
#ifdef HAS_HAM_2M_ONLY
allowUnlicensedHam = true;
#endif
if (newRegion->profile->licensedOnly && !devicestate.owner.is_licensed && !allowUnlicensedHam) {
char err_string[160];
snprintf(err_string, sizeof(err_string), "Region %s requires licensed mode", newRegion->name);
LOG_ERROR("%s", err_string);
@@ -796,6 +834,34 @@ bool RadioInterface::validateConfigRegion(const meshtastic_Config_LoRaConfig &lo
return false;
}
const bool is2mRegion = loraConfig.region == meshtastic_Config_LoRaConfig_RegionCode_ITU1_2M ||
loraConfig.region == meshtastic_Config_LoRaConfig_RegionCode_ITU23_2M;
#ifdef HAS_HAM_2M_ONLY
// This hardware's front-end / band-pass filter only passes 144-148 MHz. Any other region
// selection would key the radio on a frequency the RF path cannot emit or receive.
if (!is2mRegion && loraConfig.region != meshtastic_Config_LoRaConfig_RegionCode_UNSET) {
char err_string[160];
snprintf(err_string, sizeof(err_string), "Region %s not supported: this hardware is 2m-only", newRegion->name);
LOG_ERROR("%s", err_string);
RECORD_CRITICALERROR(meshtastic_CriticalErrorCode_INVALID_RADIO_SETTING);
sendErrorNotification(err_string);
return false;
}
#else
// Conversely, the 2m ham regions are illegal RF output for hardware not designed for that band
// (e.g. selecting ITU23_2M on a 915 MHz node would transmit at ~3x the expected frequency with
// an untuned antenna and filter). Refuse the selection entirely.
if (is2mRegion) {
char err_string[160];
snprintf(err_string, sizeof(err_string), "Region %s requires 2m-band hardware", newRegion->name);
LOG_ERROR("%s", err_string);
RECORD_CRITICALERROR(meshtastic_CriticalErrorCode_INVALID_RADIO_SETTING);
sendErrorNotification(err_string);
return false;
}
#endif
return true;
}
+4 -3
View File
@@ -1,14 +1,15 @@
// LilyGo T-Beam-BPF variant.h
// Configuration based on LilyGO utilities.h and RF documentation
// TODO Lock to 2M (144mhz) ham "region"
// #define REGULATORY_LORA_REGIONCODE meshtastic_Config_LoRaConfig_RegionCode_HAM_2M
// Hardware is restricted to the amateur 2m band (144-148 MHz).
#define HAS_HAM_2M_ONLY 1
// I2C for OLED display (SH1106 at 0x3C)
#define I2C_SDA 8
#define I2C_SCL 9
// GPS - Quectel L76K
// GPS - Quectel L76K. Per schematic sheet 7:
#define GPS_RX_PIN 5
#define GPS_TX_PIN 6
#define GPS_1PPS_PIN 7