diff --git a/variants/heltec_tracker_v2/HeltecTrackerV2Board.cpp b/variants/heltec_tracker_v2/HeltecTrackerV2Board.cpp index 4975d5cde..159e87625 100644 --- a/variants/heltec_tracker_v2/HeltecTrackerV2Board.cpp +++ b/variants/heltec_tracker_v2/HeltecTrackerV2Board.cpp @@ -6,17 +6,7 @@ void HeltecTrackerV2Board::begin() { pinMode(PIN_ADC_CTRL, OUTPUT); digitalWrite(PIN_ADC_CTRL, LOW); // Initially inactive - pinMode(P_LORA_PA_POWER, OUTPUT); - digitalWrite(P_LORA_PA_POWER,HIGH); - - rtc_gpio_hold_dis((gpio_num_t)P_LORA_PA_EN); - pinMode(P_LORA_PA_EN, OUTPUT); - digitalWrite(P_LORA_PA_EN,HIGH); - pinMode(P_LORA_PA_TX_EN, OUTPUT); - digitalWrite(P_LORA_PA_TX_EN,LOW); - - periph_power.begin(); - + // Check if waking from deep sleep esp_reset_reason_t reason = esp_reset_reason(); if (reason == ESP_RST_DEEPSLEEP) { long wakeup_source = esp_sleep_get_ext1_wakeup_status(); @@ -24,19 +14,44 @@ void HeltecTrackerV2Board::begin() { startup_reason = BD_STARTUP_RX_PACKET; } + // Release RTC holds - pins retain their state, no need to reconfigure rtc_gpio_hold_dis((gpio_num_t)P_LORA_NSS); + rtc_gpio_hold_dis((gpio_num_t)P_LORA_PA_POWER); + rtc_gpio_hold_dis((gpio_num_t)P_LORA_PA_EN); rtc_gpio_deinit((gpio_num_t)P_LORA_DIO_1); + } else { + // Cold boot: Configure GC1109 FEM pins + // Control logic (from GC1109 datasheet): + // Receive LNA: CSD=1, CTX=0, CPS=X (17dB gain, 2dB NF) + // Transmit PA: CSD=1, CTX=1, CPS=1 (full PA enabled) + // Pin mapping: CTX->DIO2 (auto), CSD->GPIO4, CPS->GPIO46, VFEM->GPIO7 + + // VFEM_Ctrl (GPIO7): Power enable for GC1109 LDO + pinMode(P_LORA_PA_POWER, OUTPUT); + digitalWrite(P_LORA_PA_POWER, HIGH); + + // CSD (GPIO4): Chip enable - must be HIGH for GC1109 to work + pinMode(P_LORA_PA_EN, OUTPUT); + digitalWrite(P_LORA_PA_EN, HIGH); } + + periph_power.begin(); + + // Note: GPIO46 (CPS) is a strapping pin - do NOT configure it here. + // TX handlers are fully responsible for GPIO46 (see onBeforeTransmit/onAfterTransmit) } void HeltecTrackerV2Board::onBeforeTransmit(void) { - digitalWrite(P_LORA_TX_LED, HIGH); // turn TX LED on - digitalWrite(P_LORA_PA_TX_EN,HIGH); + // GPIO46 is a strapping pin - only drive it when actively transmitting + pinMode(P_LORA_PA_TX_EN, OUTPUT); + digitalWrite(P_LORA_PA_TX_EN, HIGH); // CPS=1: Enable full PA mode + digitalWrite(P_LORA_TX_LED, HIGH); } void HeltecTrackerV2Board::onAfterTransmit(void) { - digitalWrite(P_LORA_TX_LED, LOW); // turn TX LED off - digitalWrite(P_LORA_PA_TX_EN,LOW); + digitalWrite(P_LORA_PA_TX_EN, LOW); + pinMode(P_LORA_PA_TX_EN, INPUT); // Release strapping pin + digitalWrite(P_LORA_TX_LED, LOW); } void HeltecTrackerV2Board::enterDeepSleep(uint32_t secs, int pin_wake_btn) { @@ -48,7 +63,11 @@ void HeltecTrackerV2Board::begin() { rtc_gpio_hold_en((gpio_num_t)P_LORA_NSS); - rtc_gpio_hold_en((gpio_num_t)P_LORA_PA_EN); //It also needs to be enabled in receive mode + // Hold GC1109 FEM pins during sleep for RX wake capability + // State: CSD=1, CTX=0 (DIO2), CPS=X -> Receive LNA mode + rtc_gpio_hold_en((gpio_num_t)P_LORA_PA_POWER); // VFEM_Ctrl - keep LDO powered + rtc_gpio_hold_en((gpio_num_t)P_LORA_PA_EN); // CSD=1 - chip enabled + // Note: GPIO46 (CPS) is NOT an RTC GPIO, cannot hold - but CPS is don't care for RX 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 diff --git a/variants/heltec_tracker_v2/platformio.ini b/variants/heltec_tracker_v2/platformio.ini index 61ccd4f4b..21fe2325a 100644 --- a/variants/heltec_tracker_v2/platformio.ini +++ b/variants/heltec_tracker_v2/platformio.ini @@ -17,15 +17,17 @@ build_flags = -D P_LORA_SCLK=9 -D P_LORA_MISO=11 -D P_LORA_MOSI=10 - -D P_LORA_PA_POWER=7 ;power en - -D P_LORA_PA_EN=4 - -D P_LORA_PA_TX_EN=46 ;enable tx - -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 + -D P_LORA_PA_POWER=7 ; VFEM_Ctrl - GC1109 LDO power enable + -D P_LORA_PA_EN=4 ; CSD - GC1109 chip enable (HIGH=on) + -D P_LORA_PA_TX_EN=46 ; CPS - GC1109 PA mode (HIGH=full PA, LOW=bypass) + -D LORA_TX_POWER=10 ; 10dBm + 11dB gain = ~21dBm output (see gain curve above) + -D MAX_LORA_TX_POWER=22 ; Max SX1262 output -> ~28dBm at antenna -D SX126X_DIO2_AS_RF_SWITCH=true -D SX126X_DIO3_TCXO_VOLTAGE=1.8 -D SX126X_CURRENT_LIMIT=140 -D SX126X_RX_BOOSTED_GAIN=1 + ; GC1109 FEM: TX/RX switching is handled by DIO2 -> CTX pin (via SX126X_DIO2_AS_RF_SWITCH) + ; GPIO46 is CPS (PA mode), not TX control - do not use for RF switching -D PIN_BOARD_SDA=5 -D PIN_BOARD_SCL=6 -D PIN_USER_BTN=0 diff --git a/variants/heltec_v4/HeltecV4Board.cpp b/variants/heltec_v4/HeltecV4Board.cpp index f143db36f..18caeca15 100644 --- a/variants/heltec_v4/HeltecV4Board.cpp +++ b/variants/heltec_v4/HeltecV4Board.cpp @@ -3,22 +3,10 @@ void HeltecV4Board::begin() { ESP32Board::begin(); - pinMode(PIN_ADC_CTRL, OUTPUT); digitalWrite(PIN_ADC_CTRL, LOW); // Initially inactive - pinMode(P_LORA_PA_POWER, OUTPUT); - digitalWrite(P_LORA_PA_POWER,HIGH); - - rtc_gpio_hold_dis((gpio_num_t)P_LORA_PA_EN); - pinMode(P_LORA_PA_EN, OUTPUT); - digitalWrite(P_LORA_PA_EN,HIGH); - pinMode(P_LORA_PA_TX_EN, OUTPUT); - digitalWrite(P_LORA_PA_TX_EN,LOW); - - - periph_power.begin(); - + // Check if waking from deep sleep esp_reset_reason_t reason = esp_reset_reason(); if (reason == ESP_RST_DEEPSLEEP) { long wakeup_source = esp_sleep_get_ext1_wakeup_status(); @@ -26,19 +14,44 @@ void HeltecV4Board::begin() { startup_reason = BD_STARTUP_RX_PACKET; } + // Release RTC holds - pins retain their state, no need to reconfigure rtc_gpio_hold_dis((gpio_num_t)P_LORA_NSS); + rtc_gpio_hold_dis((gpio_num_t)P_LORA_PA_POWER); + rtc_gpio_hold_dis((gpio_num_t)P_LORA_PA_EN); rtc_gpio_deinit((gpio_num_t)P_LORA_DIO_1); + } else { + // Cold boot: Configure GC1109 FEM pins + // Control logic (from GC1109 datasheet): + // Receive LNA: CSD=1, CTX=0, CPS=X (17dB gain, 2dB NF) + // Transmit PA: CSD=1, CTX=1, CPS=1 (full PA enabled) + // Pin mapping: CTX->DIO2 (auto), CSD->GPIO2, CPS->GPIO46, VFEM->GPIO7 + + // VFEM_Ctrl (GPIO7): Power enable for GC1109 LDO + pinMode(P_LORA_PA_POWER, OUTPUT); + digitalWrite(P_LORA_PA_POWER, HIGH); + + // CSD (GPIO2): Chip enable - must be HIGH for GC1109 to work + pinMode(P_LORA_PA_EN, OUTPUT); + digitalWrite(P_LORA_PA_EN, HIGH); } + + periph_power.begin(); + + // Note: GPIO46 (CPS) is a strapping pin - do NOT configure it here. + // TX handlers are fully responsible for GPIO46 (see onBeforeTransmit/onAfterTransmit) } void HeltecV4Board::onBeforeTransmit(void) { - digitalWrite(P_LORA_TX_LED, HIGH); // turn TX LED on - digitalWrite(P_LORA_PA_TX_EN,HIGH); + // GPIO46 is a strapping pin - only drive it when actively transmitting + pinMode(P_LORA_PA_TX_EN, OUTPUT); + digitalWrite(P_LORA_PA_TX_EN, HIGH); // CPS=1: Enable full PA mode + digitalWrite(P_LORA_TX_LED, HIGH); } void HeltecV4Board::onAfterTransmit(void) { - digitalWrite(P_LORA_TX_LED, LOW); // turn TX LED off - digitalWrite(P_LORA_PA_TX_EN,LOW); + digitalWrite(P_LORA_PA_TX_EN, LOW); + pinMode(P_LORA_PA_TX_EN, INPUT); // Release strapping pin + digitalWrite(P_LORA_TX_LED, LOW); } void HeltecV4Board::enterDeepSleep(uint32_t secs, int pin_wake_btn) { @@ -50,7 +63,11 @@ void HeltecV4Board::begin() { rtc_gpio_hold_en((gpio_num_t)P_LORA_NSS); - rtc_gpio_hold_en((gpio_num_t)P_LORA_PA_EN); //It also needs to be enabled in receive mode + // Hold GC1109 FEM pins during sleep for RX wake capability + // State: CSD=1, CTX=0 (DIO2), CPS=X -> Receive LNA mode + rtc_gpio_hold_en((gpio_num_t)P_LORA_PA_POWER); // VFEM_Ctrl - keep LDO powered + rtc_gpio_hold_en((gpio_num_t)P_LORA_PA_EN); // CSD=1 - chip enabled + // Note: GPIO46 (CPS) is NOT an RTC GPIO, cannot hold - but CPS is don't care for RX 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 diff --git a/variants/heltec_v4/platformio.ini b/variants/heltec_v4/platformio.ini index c26a5bc69..44c4f00a1 100644 --- a/variants/heltec_v4/platformio.ini +++ b/variants/heltec_v4/platformio.ini @@ -17,9 +17,9 @@ build_flags = -D P_LORA_SCLK=9 -D P_LORA_MISO=11 -D P_LORA_MOSI=10 - -D P_LORA_PA_POWER=7 ;power en - -D P_LORA_PA_EN=2 - -D P_LORA_PA_TX_EN=46 ;enable tx + -D P_LORA_PA_POWER=7 ; VFEM_Ctrl - GC1109 LDO power enable + -D P_LORA_PA_EN=2 ; CSD - GC1109 chip enable (HIGH=on) + -D P_LORA_PA_TX_EN=46 ; CPS - GC1109 PA mode (HIGH=full PA, LOW=bypass) -D PIN_BOARD_SDA=17 -D PIN_BOARD_SCL=18 -D PIN_USER_BTN=0 @@ -31,6 +31,8 @@ build_flags = -D SX126X_DIO3_TCXO_VOLTAGE=1.8 -D SX126X_CURRENT_LIMIT=140 -D SX126X_RX_BOOSTED_GAIN=1 + ; GC1109 FEM: TX/RX switching is handled by DIO2 -> CTX pin (via SX126X_DIO2_AS_RF_SWITCH) + ; GPIO46 is CPS (power save), not TX control - do not use for RF switching -D PIN_GPS_RX=38 -D PIN_GPS_TX=39 -D PIN_GPS_RESET=42