Skip to content

Commit 7fa7ac2

Browse files
authored
Merge pull request meshcore-dev#1867 from Quency-D/dev-heltec-v4.3
add heltec v4.3 board
2 parents 0b0fdb8 + 241805e commit 7fa7ac2

File tree

5 files changed

+155
-34
lines changed

5 files changed

+155
-34
lines changed

variants/heltec_v4/HeltecV4Board.cpp

Lines changed: 11 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -7,31 +7,15 @@ void HeltecV4Board::begin() {
77
pinMode(PIN_ADC_CTRL, OUTPUT);
88
digitalWrite(PIN_ADC_CTRL, LOW); // Initially inactive
99

10-
// Set up digital GPIO registers before releasing RTC hold. The hold latches
11-
// the pad state including function select, so register writes accumulate
12-
// without affecting the pad. On hold release, all changes apply atomically
13-
// (IO MUX switches to digital GPIO with output already HIGH — no glitch).
14-
pinMode(P_LORA_PA_POWER, OUTPUT);
15-
digitalWrite(P_LORA_PA_POWER,HIGH);
16-
rtc_gpio_hold_dis((gpio_num_t)P_LORA_PA_POWER);
17-
18-
pinMode(P_LORA_PA_EN, OUTPUT);
19-
digitalWrite(P_LORA_PA_EN,HIGH);
20-
rtc_gpio_hold_dis((gpio_num_t)P_LORA_PA_EN);
21-
pinMode(P_LORA_PA_TX_EN, OUTPUT);
22-
digitalWrite(P_LORA_PA_TX_EN,LOW);
23-
24-
esp_reset_reason_t reason = esp_reset_reason();
25-
if (reason != ESP_RST_DEEPSLEEP) {
26-
delay(1); // GC1109 startup time after cold power-on
27-
}
10+
loRaFEMControl.init();
2811

2912
periph_power.begin();
13+
esp_reset_reason_t reason = esp_reset_reason();
3014
if (reason == ESP_RST_DEEPSLEEP) {
3115
long wakeup_source = esp_sleep_get_ext1_wakeup_status();
3216
if (wakeup_source & (1 << P_LORA_DIO_1)) { // received a LoRa packet (while in deep sleep)
3317
startup_reason = BD_STARTUP_RX_PACKET;
34-
}
18+
}
3519

3620
rtc_gpio_hold_dis((gpio_num_t)P_LORA_NSS);
3721
rtc_gpio_deinit((gpio_num_t)P_LORA_DIO_1);
@@ -40,12 +24,12 @@ void HeltecV4Board::begin() {
4024

4125
void HeltecV4Board::onBeforeTransmit(void) {
4226
digitalWrite(P_LORA_TX_LED, HIGH); // turn TX LED on
43-
digitalWrite(P_LORA_PA_TX_EN,HIGH);
27+
loRaFEMControl.setTxModeEnable();
4428
}
4529

4630
void HeltecV4Board::onAfterTransmit(void) {
4731
digitalWrite(P_LORA_TX_LED, LOW); // turn TX LED off
48-
digitalWrite(P_LORA_PA_TX_EN,LOW);
32+
loRaFEMControl.setRxModeEnable();
4933
}
5034

5135
void HeltecV4Board::enterDeepSleep(uint32_t secs, int pin_wake_btn) {
@@ -57,9 +41,7 @@ void HeltecV4Board::begin() {
5741

5842
rtc_gpio_hold_en((gpio_num_t)P_LORA_NSS);
5943

60-
// Hold GC1109 FEM pins during sleep to keep LNA active for RX wake
61-
rtc_gpio_hold_en((gpio_num_t)P_LORA_PA_POWER);
62-
rtc_gpio_hold_en((gpio_num_t)P_LORA_PA_EN);
44+
loRaFEMControl.setRxModeEnableWhenMCUSleep();//It also needs to be enabled in receive mode
6345

6446
if (pin_wake_btn < 0) {
6547
esp_sleep_enable_ext1_wakeup( (1L << P_LORA_DIO_1), ESP_EXT1_WAKEUP_ANY_HIGH); // wake up on: recv LoRa packet
@@ -95,9 +77,9 @@ void HeltecV4Board::begin() {
9577
}
9678

9779
const char* HeltecV4Board::getManufacturerName() const {
98-
#ifdef HELTEC_LORA_V4_TFT
99-
return "Heltec V4 TFT";
100-
#else
101-
return "Heltec V4 OLED";
102-
#endif
80+
#ifdef HELTEC_LORA_V4_TFT
81+
return loRaFEMControl.getFEMType() == KCT8103L_PA ? "Heltec V4.3 TFT" : "Heltec V4 TFT";
82+
#else
83+
return loRaFEMControl.getFEMType() == KCT8103L_PA ? "Heltec V4.3 OLED" : "Heltec V4 OLED";
84+
#endif
10385
}

variants/heltec_v4/HeltecV4Board.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,12 @@
44
#include <helpers/RefCountedDigitalPin.h>
55
#include <helpers/ESP32Board.h>
66
#include <driver/rtc_io.h>
7-
7+
#include "LoRaFEMControl.h"
88
class HeltecV4Board : public ESP32Board {
99

1010
public:
1111
RefCountedDigitalPin periph_power;
12-
12+
LoRaFEMControl loRaFEMControl;
1313
HeltecV4Board() : periph_power(PIN_VEXT_EN,PIN_VEXT_EN_ACTIVE) { }
1414

1515
void begin();
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
#include "LoRaFEMControl.h"
2+
#include <driver/rtc_io.h>
3+
#include <esp_sleep.h>
4+
#include <Arduino.h>
5+
6+
void LoRaFEMControl::init(void)
7+
{
8+
// Power on FEM LDO — set registers before releasing RTC hold for
9+
// atomic transition (no glitch on deep sleep wake).
10+
pinMode(P_LORA_PA_POWER, OUTPUT);
11+
digitalWrite(P_LORA_PA_POWER, HIGH);
12+
rtc_gpio_hold_dis((gpio_num_t)P_LORA_PA_POWER);
13+
14+
esp_reset_reason_t reason = esp_reset_reason();
15+
if (reason != ESP_RST_DEEPSLEEP) {
16+
delay(1); // FEM startup time after cold power-on
17+
}
18+
19+
// Auto-detect FEM type via shared GPIO2 default pull level.
20+
// GC1109 CSD: internal pull-down → reads LOW
21+
// KCT8103L CSD: internal pull-up → reads HIGH
22+
rtc_gpio_hold_dis((gpio_num_t)P_LORA_KCT8103L_PA_CSD);
23+
pinMode(P_LORA_KCT8103L_PA_CSD, INPUT);
24+
delay(1);
25+
if(digitalRead(P_LORA_KCT8103L_PA_CSD)==HIGH) {
26+
// FEM is KCT8103L (V4.3)
27+
fem_type= KCT8103L_PA;
28+
pinMode(P_LORA_KCT8103L_PA_CSD, OUTPUT);
29+
digitalWrite(P_LORA_KCT8103L_PA_CSD, HIGH);
30+
rtc_gpio_hold_dis((gpio_num_t)P_LORA_KCT8103L_PA_CTX);
31+
pinMode(P_LORA_KCT8103L_PA_CTX, OUTPUT);
32+
digitalWrite(P_LORA_KCT8103L_PA_CTX, lna_enabled ? LOW : HIGH);
33+
setLnaCanControl(true);
34+
} else {
35+
// FEM is GC1109 (V4.2)
36+
fem_type= GC1109_PA;
37+
pinMode(P_LORA_GC1109_PA_EN, OUTPUT);
38+
digitalWrite(P_LORA_GC1109_PA_EN, HIGH);
39+
pinMode(P_LORA_GC1109_PA_TX_EN, OUTPUT);
40+
digitalWrite(P_LORA_GC1109_PA_TX_EN, LOW);
41+
}
42+
}
43+
44+
void LoRaFEMControl::setSleepModeEnable(void)
45+
{
46+
if(fem_type==GC1109_PA) {
47+
/*
48+
* Do not switch the power on and off frequently.
49+
* After turning off P_LORA_PA_EN, the power consumption has dropped to the uA level.
50+
*/
51+
digitalWrite(P_LORA_GC1109_PA_EN, LOW);
52+
digitalWrite(P_LORA_GC1109_PA_TX_EN, LOW);
53+
} else if(fem_type==KCT8103L_PA) {
54+
// shutdown the PA
55+
digitalWrite(P_LORA_KCT8103L_PA_CSD, LOW);
56+
}
57+
}
58+
59+
void LoRaFEMControl::setTxModeEnable(void)
60+
{
61+
if(fem_type==GC1109_PA) {
62+
digitalWrite(P_LORA_GC1109_PA_EN, HIGH); // CSD=1: Chip enabled
63+
digitalWrite(P_LORA_GC1109_PA_TX_EN, HIGH); // CPS: 1=full PA, 0=bypass (for RX, CPS is don't care)
64+
} else if(fem_type==KCT8103L_PA) {
65+
digitalWrite(P_LORA_KCT8103L_PA_CSD, HIGH);
66+
digitalWrite(P_LORA_KCT8103L_PA_CTX, HIGH);
67+
}
68+
}
69+
70+
void LoRaFEMControl::setRxModeEnable(void)
71+
{
72+
if(fem_type==GC1109_PA) {
73+
digitalWrite(P_LORA_GC1109_PA_EN, HIGH); // CSD=1: Chip enabled
74+
digitalWrite(P_LORA_GC1109_PA_TX_EN, LOW);
75+
} else if(fem_type==KCT8103L_PA) {
76+
digitalWrite(P_LORA_KCT8103L_PA_CSD, HIGH);
77+
if(lna_enabled) {
78+
digitalWrite(P_LORA_KCT8103L_PA_CTX, LOW); // LNA on
79+
} else {
80+
digitalWrite(P_LORA_KCT8103L_PA_CTX, HIGH); // LNA bypass
81+
}
82+
}
83+
}
84+
85+
void LoRaFEMControl::setRxModeEnableWhenMCUSleep(void)
86+
{
87+
digitalWrite(P_LORA_PA_POWER, HIGH);
88+
rtc_gpio_hold_en((gpio_num_t)P_LORA_PA_POWER);
89+
if(fem_type==GC1109_PA) {
90+
digitalWrite(P_LORA_GC1109_PA_EN, HIGH);
91+
rtc_gpio_hold_en((gpio_num_t)P_LORA_GC1109_PA_EN);
92+
gpio_pulldown_en((gpio_num_t)P_LORA_GC1109_PA_TX_EN);
93+
} else if(fem_type==KCT8103L_PA) {
94+
digitalWrite(P_LORA_KCT8103L_PA_CSD, HIGH);
95+
rtc_gpio_hold_en((gpio_num_t)P_LORA_KCT8103L_PA_CSD);
96+
if(lna_enabled) {
97+
digitalWrite(P_LORA_KCT8103L_PA_CTX, LOW); // LNA on
98+
} else {
99+
digitalWrite(P_LORA_KCT8103L_PA_CTX, HIGH); // LNA bypass
100+
}
101+
rtc_gpio_hold_en((gpio_num_t)P_LORA_KCT8103L_PA_CTX);
102+
}
103+
}
104+
105+
void LoRaFEMControl::setLNAEnable(bool enabled)
106+
{
107+
lna_enabled = enabled;
108+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
#pragma once
2+
#include <stdint.h>
3+
4+
typedef enum {
5+
GC1109_PA,
6+
KCT8103L_PA,
7+
OTHER_FEM_TYPES
8+
} LoRaFEMType;
9+
10+
class LoRaFEMControl
11+
{
12+
public:
13+
LoRaFEMControl(){ }
14+
virtual ~LoRaFEMControl(){ }
15+
void init(void);
16+
void setSleepModeEnable(void);
17+
void setTxModeEnable(void);
18+
void setRxModeEnable(void);
19+
void setRxModeEnableWhenMCUSleep(void);
20+
void setLNAEnable(bool enabled);
21+
bool isLnaCanControl(void) { return lna_can_control; }
22+
void setLnaCanControl(bool can_control) { lna_can_control = can_control; }
23+
LoRaFEMType getFEMType(void) const { return fem_type; }
24+
private:
25+
LoRaFEMType fem_type=OTHER_FEM_TYPES;
26+
bool lna_enabled=true;
27+
bool lna_can_control=false;
28+
};
29+

variants/heltec_v4/platformio.ini

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,11 @@ build_flags =
1818
-D P_LORA_SCLK=9
1919
-D P_LORA_MISO=11
2020
-D P_LORA_MOSI=10
21-
-D P_LORA_PA_POWER=7 ; VFEM_Ctrl - Power on GC1109
22-
-D P_LORA_PA_EN=2 ; PA CSD - Enable GC1109
23-
-D P_LORA_PA_TX_EN=46 ; PA CPS - GC1109 TX PA full(High) / bypass(Low)
21+
-D P_LORA_PA_POWER=7 ; // VFEM_Ctrl -LDO power enable
22+
-D P_LORA_GC1109_PA_EN=2 ; // CSD - GC1109 chip enable (HIGH=on)
23+
-D P_LORA_GC1109_PA_TX_EN=46 ;// CPS - GC1109 PA mode (HIGH=full PA, LOW=bypass)
24+
-D P_LORA_KCT8103L_PA_CSD=2
25+
-D P_LORA_KCT8103L_PA_CTX=5
2426
-D PIN_USER_BTN=0
2527
-D PIN_VEXT_EN=36
2628
-D PIN_VEXT_EN_ACTIVE=HIGH

0 commit comments

Comments
 (0)