Compare commits

..

13 Commits

Author SHA1 Message Date
Matthias Wientapper
e22e63c9f8 Disable flood adverts 2026-02-28 15:55:34 +01:00
Matthias Wientapper
81406cdb25 Set RAK boot lock voltage to 0V 2026-02-28 15:55:34 +01:00
Matthias Wientapper
baa17d204b Integration of upstrem PR #1810 2026-02-28 15:55:34 +01:00
Matthias Wientapper
cf5c268cfd Integration of upstrem PR #1743 2026-02-28 15:55:34 +01:00
Matthias Wientapper
1ae9b18e10 Integration of upstrem PR #1338 2026-02-28 15:55:34 +01:00
Matthias Wientapper
291eb6d305 Integration of upstrem PR #1297 2026-02-28 15:55:34 +01:00
Wessel Nieboer
87717610f5 fix comment, we know the band now after checking LR1110 user manual 2026-02-26 23:16:02 +01:00
Wessel Nieboer
dcfc83fb3d Calibrate configured frequency for AGC reset 2026-02-26 23:16:02 +01:00
Wessel Nieboer
b90da8e1c0 Also implement LR11x10 AGC reset
Similar to SX126x but simpler.
2026-02-26 23:16:01 +01:00
Wessel Nieboer
cb2ebbf2f8 make it more dry 2026-02-26 23:16:01 +01:00
Wessel Nieboer
34c1f13d55 reset noise_floor sampling after agc reset 2026-02-26 23:16:01 +01:00
Wessel Nieboer
bb5bdcf9e5 when doing AGC reset, call Calibrate(0x7F)
1. warm sleep
2. wake to stdby
3. Calibrate(0x7F) to reset all internal blocks
4. re-apply DIO2 RF / boosted gain & register patch to make sure
everything is as it was
2026-02-26 23:16:00 +01:00
Wessel Nieboer
de9100785e fix agc reset 2026-02-26 23:16:00 +01:00
19 changed files with 41 additions and 108 deletions

View File

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

View File

@@ -318,10 +318,6 @@ bool MyMesh::shouldOverwriteWhenFull() const {
return (_prefs.autoadd_config & AUTO_ADD_OVERWRITE_OLDEST) != 0; return (_prefs.autoadd_config & AUTO_ADD_OVERWRITE_OLDEST) != 0;
} }
uint8_t MyMesh::getAutoAddMaxHops() const {
return _prefs.autoadd_max_hops;
}
void MyMesh::onContactOverwrite(const uint8_t* pub_key) { void MyMesh::onContactOverwrite(const uint8_t* pub_key) {
_store->deleteBlobByKey(pub_key, PUB_KEY_SIZE); // delete from storage _store->deleteBlobByKey(pub_key, PUB_KEY_SIZE); // delete from storage
if (_serial->isConnected()) { if (_serial->isConnected()) {
@@ -1789,16 +1785,12 @@ void MyMesh::handleCmdFrame(size_t len) {
} }
} else if (cmd_frame[0] == CMD_SET_AUTOADD_CONFIG) { } else if (cmd_frame[0] == CMD_SET_AUTOADD_CONFIG) {
_prefs.autoadd_config = cmd_frame[1]; _prefs.autoadd_config = cmd_frame[1];
if (len >= 3) {
_prefs.autoadd_max_hops = min(cmd_frame[2], (uint8_t)64);
}
savePrefs(); savePrefs();
writeOKFrame(); writeOKFrame();
} else if (cmd_frame[0] == CMD_GET_AUTOADD_CONFIG) { } else if (cmd_frame[0] == CMD_GET_AUTOADD_CONFIG) {
int i = 0; int i = 0;
out_frame[i++] = RESP_CODE_AUTOADD_CONFIG; out_frame[i++] = RESP_CODE_AUTOADD_CONFIG;
out_frame[i++] = _prefs.autoadd_config; out_frame[i++] = _prefs.autoadd_config;
out_frame[i++] = _prefs.autoadd_max_hops;
_serial->writeFrame(out_frame, i); _serial->writeFrame(out_frame, i);
} else if (cmd_frame[0] == CMD_GET_ALLOWED_REPEAT_FREQ) { } else if (cmd_frame[0] == CMD_GET_ALLOWED_REPEAT_FREQ) {
int i = 0; int i = 0;

View File

@@ -119,7 +119,6 @@ protected:
bool isAutoAddEnabled() const override; bool isAutoAddEnabled() const override;
bool shouldAutoAddContactType(uint8_t type) const override; bool shouldAutoAddContactType(uint8_t type) const override;
bool shouldOverwriteWhenFull() const override; bool shouldOverwriteWhenFull() const override;
uint8_t getAutoAddMaxHops() const override;
void onContactsFull() override; void onContactsFull() override;
void onContactOverwrite(const uint8_t* pub_key) override; void onContactOverwrite(const uint8_t* pub_key) override;
bool onContactPathRecv(ContactInfo& from, uint8_t* in_path, uint8_t in_path_len, uint8_t* out_path, uint8_t out_path_len, uint8_t extra_type, uint8_t* extra, uint8_t extra_len) override; bool onContactPathRecv(ContactInfo& from, uint8_t* in_path, uint8_t in_path_len, uint8_t* out_path, uint8_t out_path_len, uint8_t extra_type, uint8_t* extra, uint8_t extra_len) override;

View File

@@ -30,5 +30,4 @@ struct NodePrefs { // persisted to file
uint8_t autoadd_config; // bitmask for auto-add contacts config uint8_t autoadd_config; // bitmask for auto-add contacts config
uint8_t client_repeat; uint8_t client_repeat;
uint8_t path_hash_mode; // which path mode to use when sending uint8_t path_hash_mode; // which path mode to use when sending
uint8_t autoadd_max_hops; // 0 = no limit, 1 = direct (0 hops), N = up to N-1 hops (max 64)
}; };

View File

@@ -141,15 +141,6 @@ void BaseChatMesh::onAdvertRecv(mesh::Packet* packet, const mesh::Identity& id,
return; return;
} }
// check hop limit for new contacts (0 = no limit, 1 = direct (0 hops), N = up to N-1 hops)
uint8_t max_hops = getAutoAddMaxHops();
if (max_hops > 0 && packet->getPathHashCount() >= max_hops) {
ContactInfo ci;
populateContactFromAdvert(ci, id, parser, timestamp);
onDiscoveredContact(ci, true, packet->path_len, packet->path); // let UI know
return;
}
from = allocateContactSlot(); from = allocateContactSlot();
if (from == NULL) { if (from == NULL) {
ContactInfo ci; ContactInfo ci;

View File

@@ -98,7 +98,6 @@ protected:
virtual bool shouldAutoAddContactType(uint8_t type) const { return true; } virtual bool shouldAutoAddContactType(uint8_t type) const { return true; }
virtual void onContactsFull() {}; virtual void onContactsFull() {};
virtual bool shouldOverwriteWhenFull() const { return false; } virtual bool shouldOverwriteWhenFull() const { return false; }
virtual uint8_t getAutoAddMaxHops() const { return 0; } // 0 = no limit, 1 = direct (0 hops), N = up to N-1 hops
virtual void onContactOverwrite(const uint8_t* pub_key) {}; virtual void onContactOverwrite(const uint8_t* pub_key) {};
virtual void onDiscoveredContact(ContactInfo& contact, bool is_new, uint8_t path_len, const uint8_t* path) = 0; virtual void onDiscoveredContact(ContactInfo& contact, bool is_new, uint8_t path_len, const uint8_t* path) = 0;
virtual ContactInfo* processAck(const uint8_t *data) = 0; virtual ContactInfo* processAck(const uint8_t *data) = 0;

View File

@@ -766,7 +766,7 @@ void CommonCLI::handleCommand(uint32_t sender_timestamp, const char* command, ch
_prefs->advert_loc_policy = ADVERT_LOC_SHARE; _prefs->advert_loc_policy = ADVERT_LOC_SHARE;
savePrefs(); savePrefs();
strcpy(reply, "ok"); strcpy(reply, "ok");
} else if (memcmp(command+11, "prefs", 5) == 0) { } else if (memcmp(command+11, "prefs", 4) == 0) {
_prefs->advert_loc_policy = ADVERT_LOC_PREFS; _prefs->advert_loc_policy = ADVERT_LOC_PREFS;
savePrefs(); savePrefs();
strcpy(reply, "ok"); strcpy(reply, "ok");

View File

@@ -707,9 +707,7 @@ void EnvironmentSensorManager::loop() {
static long next_gps_update = 0; static long next_gps_update = 0;
#if ENV_INCLUDE_GPS #if ENV_INCLUDE_GPS
if (gps_active) { _location->loop();
_location->loop();
}
if (millis() > next_gps_update) { if (millis() > next_gps_update) {
if(gps_active){ if(gps_active){

View File

@@ -79,9 +79,6 @@ public :
if (_pin_en != -1) { if (_pin_en != -1) {
digitalWrite(_pin_en, !PIN_GPS_EN_ACTIVE); digitalWrite(_pin_en, !PIN_GPS_EN_ACTIVE);
} }
if (_pin_reset != -1) {
digitalWrite(_pin_reset, GPS_RESET_FORCE);
}
if (_peripher_power) _peripher_power->release(); if (_peripher_power) _peripher_power->release();
} }

View File

@@ -32,11 +32,6 @@ build_flags =
-D PIN_TFT_LEDA_CTL=21 ; LEDK (switches on/off via mosfet to create the ground) -D PIN_TFT_LEDA_CTL=21 ; LEDK (switches on/off via mosfet to create the ground)
-D PIN_GPS_RX=33 -D PIN_GPS_RX=33
-D PIN_GPS_TX=34 -D PIN_GPS_TX=34
-D PIN_GPS_EN=35 ; N-ch MOSFET Q2 drives P-ch high-side switch → active HIGH (default)
-D PIN_GPS_RESET=36
-D PIN_GPS_RESET_ACTIVE=LOW
-D GPS_BAUD_RATE=115200
-D ENV_INCLUDE_GPS=1
-D SX126X_DIO2_AS_RF_SWITCH=true -D SX126X_DIO2_AS_RF_SWITCH=true
-D SX126X_DIO3_TCXO_VOLTAGE=1.8 -D SX126X_DIO3_TCXO_VOLTAGE=1.8
-D SX126X_CURRENT_LIMIT=140 -D SX126X_CURRENT_LIMIT=140

View File

@@ -16,8 +16,7 @@ WRAPPER_CLASS radio_driver(radio, board);
ESP32RTCClock fallback_clock; ESP32RTCClock fallback_clock;
AutoDiscoverRTCClock rtc_clock(fallback_clock); AutoDiscoverRTCClock rtc_clock(fallback_clock);
// GPS_EN (GPIO35) drives N-ch MOSFET → P-ch high-side switch; GPS_RESET (GPIO36) active LOW MicroNMEALocationProvider nmea = MicroNMEALocationProvider(Serial1);
MicroNMEALocationProvider nmea = MicroNMEALocationProvider(Serial1, &rtc_clock, GPS_RESET, GPS_EN, &board.periph_power);
HWTSensorManager sensors = HWTSensorManager(nmea); HWTSensorManager sensors = HWTSensorManager(nmea);
#ifdef DISPLAY_CLASS #ifdef DISPLAY_CLASS
@@ -59,16 +58,18 @@ mesh::LocalIdentity radio_new_identity() {
void HWTSensorManager::start_gps() { void HWTSensorManager::start_gps() {
if (!gps_active) { if (!gps_active) {
_location->begin(); // Claims periph_power via RefCountedDigitalPin board.periph_power.claim();
gps_active = true; gps_active = true;
Serial1.println("$CFGSYS,h35155*68"); // Configure GPS for all constellations Serial1.println("$CFGSYS,h35155*68");
} }
} }
void HWTSensorManager::stop_gps() { void HWTSensorManager::stop_gps() {
if (gps_active) { if (gps_active) {
gps_active = false; gps_active = false;
_location->stop(); // Releases periph_power via RefCountedDigitalPin
board.periph_power.release();
} }
} }

View File

@@ -28,7 +28,6 @@ public:
const char* getSettingName(int i) const override; const char* getSettingName(int i) const override;
const char* getSettingValue(int i) const override; const char* getSettingValue(int i) const override;
bool setSettingValue(const char* name, const char* value) override; bool setSettingValue(const char* name, const char* value) override;
LocationProvider* getLocationProvider() override { return _location; }
}; };
extern HeltecV3Board board; extern HeltecV3Board board;

View File

@@ -6,26 +6,18 @@ void HeltecTrackerV2Board::begin() {
pinMode(PIN_ADC_CTRL, OUTPUT); pinMode(PIN_ADC_CTRL, OUTPUT);
digitalWrite(PIN_ADC_CTRL, LOW); // Initially inactive digitalWrite(PIN_ADC_CTRL, LOW); // Initially inactive
// Set up digital GPIO registers before releasing RTC hold. The hold latches
// the pad state including function select, so register writes accumulate
// without affecting the pad. On hold release, all changes apply atomically
// (IO MUX switches to digital GPIO with output already HIGH — no glitch).
pinMode(P_LORA_PA_POWER, OUTPUT); pinMode(P_LORA_PA_POWER, OUTPUT);
digitalWrite(P_LORA_PA_POWER,HIGH); digitalWrite(P_LORA_PA_POWER,HIGH);
rtc_gpio_hold_dis((gpio_num_t)P_LORA_PA_POWER);
rtc_gpio_hold_dis((gpio_num_t)P_LORA_PA_EN);
pinMode(P_LORA_PA_EN, OUTPUT); pinMode(P_LORA_PA_EN, OUTPUT);
digitalWrite(P_LORA_PA_EN,HIGH); digitalWrite(P_LORA_PA_EN,HIGH);
rtc_gpio_hold_dis((gpio_num_t)P_LORA_PA_EN);
pinMode(P_LORA_PA_TX_EN, OUTPUT); pinMode(P_LORA_PA_TX_EN, OUTPUT);
digitalWrite(P_LORA_PA_TX_EN,LOW); digitalWrite(P_LORA_PA_TX_EN,LOW);
esp_reset_reason_t reason = esp_reset_reason();
if (reason != ESP_RST_DEEPSLEEP) {
delay(1); // GC1109 startup time after cold power-on
}
periph_power.begin(); periph_power.begin();
esp_reset_reason_t reason = esp_reset_reason();
if (reason == ESP_RST_DEEPSLEEP) { if (reason == ESP_RST_DEEPSLEEP) {
long wakeup_source = esp_sleep_get_ext1_wakeup_status(); long wakeup_source = esp_sleep_get_ext1_wakeup_status();
if (wakeup_source & (1 << P_LORA_DIO_1)) { // received a LoRa packet (while in deep sleep) if (wakeup_source & (1 << P_LORA_DIO_1)) { // received a LoRa packet (while in deep sleep)
@@ -56,9 +48,7 @@ void HeltecTrackerV2Board::begin() {
rtc_gpio_hold_en((gpio_num_t)P_LORA_NSS); rtc_gpio_hold_en((gpio_num_t)P_LORA_NSS);
// Hold GC1109 FEM pins during sleep to keep LNA active for RX wake rtc_gpio_hold_en((gpio_num_t)P_LORA_PA_EN); //It also needs to be enabled in receive mode
rtc_gpio_hold_en((gpio_num_t)P_LORA_PA_POWER);
rtc_gpio_hold_en((gpio_num_t)P_LORA_PA_EN);
if (pin_wake_btn < 0) { if (pin_wake_btn < 0) {
esp_sleep_enable_ext1_wakeup( (1L << P_LORA_DIO_1), ESP_EXT1_WAKEUP_ANY_HIGH); // wake up on: recv LoRa packet esp_sleep_enable_ext1_wakeup( (1L << P_LORA_DIO_1), ESP_EXT1_WAKEUP_ANY_HIGH); // wake up on: recv LoRa packet

View File

@@ -17,11 +17,11 @@ build_flags =
-D P_LORA_SCLK=9 -D P_LORA_SCLK=9
-D P_LORA_MISO=11 -D P_LORA_MISO=11
-D P_LORA_MOSI=10 -D P_LORA_MOSI=10
-D P_LORA_PA_POWER=7 ; VFEM_Ctrl - GC1109 LDO power enable -D P_LORA_PA_POWER=7 ;power en
-D P_LORA_PA_EN=4 ; CSD - GC1109 chip enable (HIGH=on) -D P_LORA_PA_EN=4
-D P_LORA_PA_TX_EN=46 ; CPS - GC1109 PA mode (HIGH=full PA, LOW=bypass) -D P_LORA_PA_TX_EN=46 ;enable tx
-D LORA_TX_POWER=10 ; 10dBm + ~11dB GC1109 gain = ~21dBm output -D LORA_TX_POWER=10 ;If it is configured as 10 here, the final output will be 22 dbm.
-D MAX_LORA_TX_POWER=22 ; Max SX1262 output -> ~28dBm at antenna -D MAX_LORA_TX_POWER=22 ;Max SX1262 output
-D SX126X_DIO2_AS_RF_SWITCH=true -D SX126X_DIO2_AS_RF_SWITCH=true
-D SX126X_DIO3_TCXO_VOLTAGE=1.8 -D SX126X_DIO3_TCXO_VOLTAGE=1.8
-D SX126X_CURRENT_LIMIT=140 -D SX126X_CURRENT_LIMIT=140

View File

@@ -7,26 +7,19 @@ void HeltecV4Board::begin() {
pinMode(PIN_ADC_CTRL, OUTPUT); pinMode(PIN_ADC_CTRL, OUTPUT);
digitalWrite(PIN_ADC_CTRL, LOW); // Initially inactive digitalWrite(PIN_ADC_CTRL, LOW); // Initially inactive
// Set up digital GPIO registers before releasing RTC hold. The hold latches
// the pad state including function select, so register writes accumulate
// without affecting the pad. On hold release, all changes apply atomically
// (IO MUX switches to digital GPIO with output already HIGH — no glitch).
pinMode(P_LORA_PA_POWER, OUTPUT); pinMode(P_LORA_PA_POWER, OUTPUT);
digitalWrite(P_LORA_PA_POWER,HIGH); digitalWrite(P_LORA_PA_POWER,HIGH);
rtc_gpio_hold_dis((gpio_num_t)P_LORA_PA_POWER);
rtc_gpio_hold_dis((gpio_num_t)P_LORA_PA_EN);
pinMode(P_LORA_PA_EN, OUTPUT); pinMode(P_LORA_PA_EN, OUTPUT);
digitalWrite(P_LORA_PA_EN,HIGH); digitalWrite(P_LORA_PA_EN,HIGH);
rtc_gpio_hold_dis((gpio_num_t)P_LORA_PA_EN);
pinMode(P_LORA_PA_TX_EN, OUTPUT); pinMode(P_LORA_PA_TX_EN, OUTPUT);
digitalWrite(P_LORA_PA_TX_EN,LOW); digitalWrite(P_LORA_PA_TX_EN,LOW);
esp_reset_reason_t reason = esp_reset_reason();
if (reason != ESP_RST_DEEPSLEEP) {
delay(1); // GC1109 startup time after cold power-on
}
periph_power.begin(); periph_power.begin();
esp_reset_reason_t reason = esp_reset_reason();
if (reason == ESP_RST_DEEPSLEEP) { if (reason == ESP_RST_DEEPSLEEP) {
long wakeup_source = esp_sleep_get_ext1_wakeup_status(); long wakeup_source = esp_sleep_get_ext1_wakeup_status();
if (wakeup_source & (1 << P_LORA_DIO_1)) { // received a LoRa packet (while in deep sleep) if (wakeup_source & (1 << P_LORA_DIO_1)) { // received a LoRa packet (while in deep sleep)
@@ -57,9 +50,7 @@ void HeltecV4Board::begin() {
rtc_gpio_hold_en((gpio_num_t)P_LORA_NSS); rtc_gpio_hold_en((gpio_num_t)P_LORA_NSS);
// Hold GC1109 FEM pins during sleep to keep LNA active for RX wake rtc_gpio_hold_en((gpio_num_t)P_LORA_PA_EN); //It also needs to be enabled in receive mode
rtc_gpio_hold_en((gpio_num_t)P_LORA_PA_POWER);
rtc_gpio_hold_en((gpio_num_t)P_LORA_PA_EN);
if (pin_wake_btn < 0) { if (pin_wake_btn < 0) {
esp_sleep_enable_ext1_wakeup( (1L << P_LORA_DIO_1), ESP_EXT1_WAKEUP_ANY_HIGH); // wake up on: recv LoRa packet esp_sleep_enable_ext1_wakeup( (1L << P_LORA_DIO_1), ESP_EXT1_WAKEUP_ANY_HIGH); // wake up on: recv LoRa packet

View File

@@ -20,29 +20,13 @@ void RAK3401Board::begin() {
Wire.begin(); Wire.begin();
// PIN_3V3_EN (WB_IO2, P0.34) controls the 3V3_S switched peripheral rail
// AND the 5V boost regulator (U5) on the RAK13302 that powers the SKY66122 PA.
// Must stay HIGH during radio operation — do not toggle for power saving.
pinMode(PIN_3V3_EN, OUTPUT); pinMode(PIN_3V3_EN, OUTPUT);
digitalWrite(PIN_3V3_EN, HIGH); digitalWrite(PIN_3V3_EN, HIGH);
// Enable SKY66122-11 FEM on the RAK13302 module. #ifdef P_LORA_PA_EN
// CSD and CPS are tied together on the RAK13302 PCB, routed to IO3 (P0.21). // Initialize RAK13302 1W LoRa transceiver module PA control pin
// HIGH = FEM active (LNA for RX, PA path available for TX). pinMode(P_LORA_PA_EN, OUTPUT);
// TX/RX switching (CTX) is handled by SX1262 DIO2 via SetDIO2AsRfSwitchCtrl. digitalWrite(P_LORA_PA_EN, LOW); // Start with PA disabled
pinMode(SX126X_POWER_EN, OUTPUT); delay(10); // Allow PA module to initialize
digitalWrite(SX126X_POWER_EN, HIGH);
delay(1); // SKY66122 turn-on settling time (tON = 3us typ)
}
#ifdef NRF52_POWER_MANAGEMENT
void RAK3401Board::initiateShutdown(uint8_t reason) {
// Disable SKY66122 FEM (CSD+CPS LOW = shutdown, <1 uA)
digitalWrite(SX126X_POWER_EN, LOW);
// Disable 3V3 switched peripherals and 5V boost
digitalWrite(PIN_3V3_EN, LOW);
enterSystemOff(reason);
}
#endif #endif
}

View File

@@ -38,6 +38,13 @@ public:
return "RAK 3401"; return "RAK 3401";
} }
// TX/RX switching is handled by SX1262 DIO2 -> SKY66122 CTX (hardware-timed). #ifdef P_LORA_PA_EN
// No onBeforeTransmit/onAfterTransmit overrides needed. void onBeforeTransmit() override {
digitalWrite(P_LORA_PA_EN, HIGH); // Enable PA before transmission
}
void onAfterTransmit() override {
digitalWrite(P_LORA_PA_EN, LOW); // Disable PA after transmission to save power
}
#endif
}; };

View File

@@ -11,7 +11,6 @@ build_flags = ${nrf52_base.build_flags}
-D LORA_TX_POWER=22 -D LORA_TX_POWER=22
-D SX126X_CURRENT_LIMIT=140 -D SX126X_CURRENT_LIMIT=140
-D SX126X_RX_BOOSTED_GAIN=1 -D SX126X_RX_BOOSTED_GAIN=1
-D SX126X_REGISTER_PATCH=1 ; Patch register 0x8B5 for improved RX with SKY66122 FEM
build_src_filter = ${nrf52_base.build_src_filter} build_src_filter = ${nrf52_base.build_src_filter}
+<../variants/rak3401> +<../variants/rak3401>
+<helpers/sensors> +<helpers/sensors>

View File

@@ -147,15 +147,8 @@ static const uint8_t AREF = PIN_AREF;
#define SX126X_BUSY (9) #define SX126X_BUSY (9)
#define SX126X_RESET (4) #define SX126X_RESET (4)
// SKY66122-11 FEM control on the RAK13302 module: #define SX126X_POWER_EN (21)
// CSD + CPS are tied together on the PCB, routed to WisBlock IO3 (P0.21). // DIO2 controlls an antenna switch and the TCXO voltage is controlled by DIO3
// Setting IO3 HIGH enables the FEM (LNA for RX, PA path for TX).
// CTX is connected to SX1262 DIO2 — the radio handles TX/RX switching
// in hardware via SetDIO2AsRfSwitchCtrl (microsecond-accurate, no GPIO needed).
// The 5V boost for the PA is enabled by WB_IO2 (P0.34 = PIN_3V3_EN).
#define SX126X_POWER_EN (21) // P0.21 = IO3 -> SKY66122 CSD+CPS (FEM enable)
// CTX is driven by SX1262 DIO2, not a GPIO
#define SX126X_DIO2_AS_RF_SWITCH #define SX126X_DIO2_AS_RF_SWITCH
#define SX126X_DIO3_TCXO_VOLTAGE 1.8 #define SX126X_DIO3_TCXO_VOLTAGE 1.8
@@ -166,6 +159,7 @@ static const uint8_t AREF = PIN_AREF;
#define P_LORA_DIO_1 SX126X_DIO1 #define P_LORA_DIO_1 SX126X_DIO1
#define P_LORA_BUSY SX126X_BUSY #define P_LORA_BUSY SX126X_BUSY
#define P_LORA_RESET SX126X_RESET #define P_LORA_RESET SX126X_RESET
#define P_LORA_PA_EN 31
// enables 3.3V periphery like GPS or IO Module // enables 3.3V periphery like GPS or IO Module
// Do not toggle this for GPS power savings // Do not toggle this for GPS power savings