Compare commits

..

1 Commits

Author SHA1 Message Date
Thomas Göttgens
2b56e25a01 ThinkNode G3, ETH support WIP 2026-01-08 08:33:27 +01:00
16 changed files with 121 additions and 86 deletions

View File

@@ -13,6 +13,11 @@ extern MemGet memGet;
#define LED_STATE_ON 1
#endif
// WIFI LED
#ifndef WIFI_STATE_ON
#define WIFI_STATE_ON 1
#endif
// -----------------------------------------------------------------------------
// DEBUG
// -----------------------------------------------------------------------------
@@ -147,7 +152,9 @@ extern "C" void logLegacy(const char *level, const char *fmt, ...);
// Default Bluetooth PIN
#define defaultBLEPin 123456
#if HAS_ETHERNET && !defined(USE_WS5500)
#if HAS_ETHERNET && defined(USE_CH390D)
#include <ESP32_CH390.h>
#elif HAS_ETHERNET && !defined(USE_WS5500)
#include <RAK13800_W5100S.h>
#endif // HAS_ETHERNET

View File

@@ -22,19 +22,15 @@ int BuzzerFeedbackThread::handleInputEvent(const InputEvent *event)
// Handle different input events with appropriate buzzer feedback
switch (event->inputEvent) {
#ifdef INPUTDRIVER_ENCODER_TYPE
case INPUT_BROKER_SELECT:
case INPUT_BROKER_SELECT_LONG:
playClick();
break;
#else
case INPUT_BROKER_USER_PRESS:
case INPUT_BROKER_ALT_PRESS:
playClick(); // Low delay feedback
break;
case INPUT_BROKER_SELECT:
case INPUT_BROKER_SELECT_LONG:
playBeep();
playBeep(); // Confirmation feedback
break;
#endif
case INPUT_BROKER_UP:
case INPUT_BROKER_UP_LONG:

View File

@@ -65,7 +65,7 @@ void playTones(const ToneDuration *tone_durations, int size)
void playBeep()
{
ToneDuration melody[] = {{NOTE_B3, DURATION_1_16}};
ToneDuration melody[] = {{NOTE_B3, DURATION_1_8}};
playTones(melody, sizeof(melody) / sizeof(ToneDuration));
}

View File

@@ -330,7 +330,7 @@ void setup()
#ifdef WIFI_LED
pinMode(WIFI_LED, OUTPUT);
digitalWrite(WIFI_LED, LOW);
digitalWrite(WIFI_LED, HIGH ^ WIFI_STATE_ON);
#endif
#ifdef BLE_LED

View File

@@ -25,7 +25,7 @@ template class LR11x0Interface<LR1121>;
template class SX126xInterface<STM32WLx>;
#endif
#if HAS_ETHERNET && !defined(USE_WS5500)
#if HAS_ETHERNET && !defined(USE_WS5500) && !defined(USE_CH390D)
#include "api/ethServerAPI.h"
template class ServerAPI<EthernetClient>;
template class APIServerPort<ethServerAPI, EthernetServer>;

View File

@@ -53,21 +53,13 @@ template <typename T> bool SX126xInterface<T>::init()
#endif
#if defined(USE_GC1109_PA)
// GC1109 FEM chip initialization
// See variant.h for full pin mapping and control logic documentation
// VFEM_Ctrl (LORA_PA_POWER): Power enable for GC1109 LDO (always on)
pinMode(LORA_PA_POWER, OUTPUT);
digitalWrite(LORA_PA_POWER, HIGH);
// CSD (LORA_PA_EN): Chip enable - must be HIGH to enable GC1109 for both RX and TX
pinMode(LORA_PA_EN, OUTPUT);
digitalWrite(LORA_PA_EN, HIGH);
// CPS (LORA_PA_TX_EN): PA mode select - HIGH enables full PA during TX, LOW for RX (don't care)
// Note: TX/RX path switching (CTX) is handled by DIO2 via SX126X_DIO2_AS_RF_SWITCH
digitalWrite(LORA_PA_EN, LOW);
pinMode(LORA_PA_TX_EN, OUTPUT);
digitalWrite(LORA_PA_TX_EN, LOW); // Start in RX-ready state
digitalWrite(LORA_PA_TX_EN, LOW);
#endif
#ifdef RF95_FAN_EN
@@ -385,13 +377,13 @@ template <typename T> bool SX126xInterface<T>::sleep()
return true;
}
/** Control PA mode for GC1109 FEM - CPS pin selects full PA (txon=true) or bypass mode (txon=false) */
/** Some boards require GPIO control of tx vs rx paths */
template <typename T> void SX126xInterface<T>::setTransmitEnable(bool txon)
{
#if defined(USE_GC1109_PA)
digitalWrite(LORA_PA_POWER, HIGH); // Ensure LDO is on
digitalWrite(LORA_PA_EN, HIGH); // CSD=1: Chip enabled
digitalWrite(LORA_PA_TX_EN, txon ? 1 : 0); // CPS: 1=full PA, 0=bypass (for RX, CPS is don't care)
digitalWrite(LORA_PA_POWER, HIGH);
digitalWrite(LORA_PA_EN, HIGH);
digitalWrite(LORA_PA_TX_EN, txon ? 1 : 0);
#endif
}

View File

@@ -1,7 +1,7 @@
#include "configuration.h"
#include <Arduino.h>
#if HAS_ETHERNET && !defined(USE_WS5500)
#if HAS_ETHERNET && !defined(USE_WS5500) && !defined(USE_CH390D)
#include "ethServerAPI.h"

View File

@@ -1,7 +1,7 @@
#pragma once
#include "ServerAPI.h"
#ifndef USE_WS5500
#if !defined(USE_WS5500) && !defined(USE_CH390D)
#include <RAK13800_W5100S.h>
/**

View File

@@ -384,13 +384,13 @@ static void WiFiEvent(WiFiEvent_t event)
#endif
}
#ifdef WIFI_LED
digitalWrite(WIFI_LED, HIGH);
digitalWrite(WIFI_LED, LOW ^ WIFI_STATE_ON);
#endif
break;
case ARDUINO_EVENT_WIFI_STA_DISCONNECTED:
LOG_INFO("Disconnected from WiFi access point");
#ifdef WIFI_LED
digitalWrite(WIFI_LED, LOW);
digitalWrite(WIFI_LED, HIGH ^ WIFI_STATE_ON);
#endif
if (!isReconnecting) {
WiFi.disconnect(false, true);
@@ -442,13 +442,13 @@ static void WiFiEvent(WiFiEvent_t event)
case ARDUINO_EVENT_WIFI_AP_START:
LOG_INFO("WiFi access point started");
#ifdef WIFI_LED
digitalWrite(WIFI_LED, HIGH);
digitalWrite(WIFI_LED, LOW ^ WIFI_STATE_ON);
#endif
break;
case ARDUINO_EVENT_WIFI_AP_STOP:
LOG_INFO("WiFi access point stopped");
#ifdef WIFI_LED
digitalWrite(WIFI_LED, LOW);
digitalWrite(WIFI_LED, HIGH ^ WIFI_STATE_ON);
#endif
break;
case ARDUINO_EVENT_WIFI_AP_STACONNECTED:

View File

@@ -1230,7 +1230,7 @@ void AdminModule::handleGetDeviceConnectionStatus(const meshtastic_MeshPacket &r
}
#endif
#if HAS_ETHERNET && !defined(USE_WS5500)
#if HAS_ETHERNET && !defined(USE_WS5500) && !defined(USE_CH390D)
conn.has_ethernet = true;
conn.ethernet.has_status = true;
if (Ethernet.linkStatus() == LinkON) {

View File

@@ -15,7 +15,7 @@
#include <WiFiClientSecure.h>
#endif
#endif
#if HAS_ETHERNET && !defined(USE_WS5500)
#if HAS_ETHERNET && !defined(USE_WS5500) && !defined(USE_CH390D)
#include <EthernetClient.h>
#endif

View File

@@ -0,0 +1,26 @@
#ifndef Pins_Arduino_h
#define Pins_Arduino_h
#include <stdint.h>
#define USB_VID 0x303a
#define USB_PID 0x1001
// The default Wire will be mapped to PMU and RTC
static const uint8_t SDA = 17;
static const uint8_t SCL = 18;
// Default SPI will be mapped to Radio
static const uint8_t SS = 39;
static const uint8_t MOSI = 40;
static const uint8_t MISO = 41;
static const uint8_t SCK = 42;
// #define SPI_MOSI (11)
// #define SPI_SCK (10)
// #define SPI_MISO (9)
// #define SPI_CS (12)
// #define SDCARD_CS SPI_CS
#endif /* Pins_Arduino_h */

View File

@@ -0,0 +1,22 @@
[env:thinknode_g3]
extends = esp32s3_base
board = ESP32-S3-WROOM-1-N4
board_build.psram_type = opi
build_flags =
${esp32s3_base.build_flags}
-D ELECROW_ThinkNode_G3
-D HAS_UDP_MULTICAST=1
-D BOARD_HAS_PSRAM
-D PRIVATE_HW
# -D CONFIG_ETH_ENABLED=1
# -D CONFIG_ETH_USE_ESP32_EMAC=1
-I variants/esp32s3/ELECROW-ThinkNode-G3
-mfix-esp32-psram-cache-issue
lib_ignore =
Ethernet
lib_deps =
${esp32s3_base.lib_deps}
# file://../ESP32-CH390/ESP32-CH390-1.0.1.tar.gz

View File

@@ -0,0 +1,36 @@
#define HAS_GPS 0
#define HAS_WIRE 0
#define I2C_NO_RESCAN
#define WIFI_LED 5
#define WIFI_STATE_ON 0
#define LED_PIN 6 // The blue LORA LED
#define LED_STATE_ON 0
#define BUTTON_PIN 4 // the external user button of the device, BOOT and RESET are not accessible without opening it up.
#define USE_SX1262
#define LORA_SCK 42
#define LORA_MISO 41
#define LORA_MOSI 40
#define LORA_CS 39
#define LORA_RESET 21
#define SX126X_CS LORA_CS
#define SX126X_DIO1 15
#define SX126X_BUSY 47
#define SX126X_RESET LORA_RESET
#define SX126X_DIO2_AS_RF_SWITCH
#define SX126X_DIO3_TCXO_VOLTAGE 1.8
#define PIN_POWER_EN 45
// #define HAS_ETHERNET 1
// #define USE_CH390D 1 // this driver uses the same stack as the ESP32 Wifi driver
// #define ETH_MISO_PIN 47
// #define ETH_MOSI_PIN 21
// #define ETH_SCLK_PIN 48
// #define ETH_CS_PIN 45
// #define ETH_INT_PIN 14
// #define ETH_RST_PIN -1
// #define ETH_ADDR 1

View File

@@ -29,32 +29,10 @@
#define SX126X_DIO2_AS_RF_SWITCH
#define SX126X_DIO3_TCXO_VOLTAGE 1.8
// ---- GC1109 RF FRONT END CONFIGURATION ----
// The Heltec V4 uses a GC1109 FEM chip with integrated PA and LNA
// RF path: SX1262 -> GC1109 PA -> Pi attenuator -> Antenna
// Measured net TX gain (non-linear due to PA compression):
// +11dB at 0-15dBm input (e.g., 10dBm in -> 21dBm out)
// +10dB at 16-17dBm input
// +9dB at 18-19dBm input
// +7dB at 21dBm input (e.g., 21dBm in -> 28dBm out max)
// Control logic (from GC1109 datasheet):
// Shutdown: CSD=0, CTX=X, CPS=X
// Receive LNA: CSD=1, CTX=0, CPS=X (17dB gain, 2dB NF)
// Transmit bypass: CSD=1, CTX=1, CPS=0 (~1dB loss, no PA)
// Transmit PA: CSD=1, CTX=1, CPS=1 (full PA enabled)
// Pin mapping:
// CTX (pin 6) -> SX1262 DIO2: TX/RX path select (automatic via SX126X_DIO2_AS_RF_SWITCH)
// CSD (pin 4) -> GPIO2: Chip enable (HIGH=on, LOW=shutdown)
// CPS (pin 5) -> GPIO46: PA mode select (HIGH=full PA, LOW=bypass)
// VCC0/VCC1 -> Vfem via U3 LDO, controlled by GPIO7
#define USE_GC1109_PA
#define LORA_PA_POWER 7 // VFEM_Ctrl - GC1109 LDO power enable
#define LORA_PA_EN 2 // CSD - GC1109 chip enable (HIGH=on)
#define LORA_PA_TX_EN 46 // CPS - GC1109 PA mode (HIGH=full PA, LOW=bypass)
// GC1109 FEM: TX/RX path switching is handled by DIO2 -> CTX pin (via SX126X_DIO2_AS_RF_SWITCH)
// GPIO46 is CPS (PA mode), not TX control - setTransmitEnable() handles it in SX126xInterface.cpp
// Do NOT use SX126X_TXEN/RXEN as that would cause double-control of GPIO46
#define USE_GC1109_PA // We have a GC1109 power amplifier+attenuator
#define LORA_PA_POWER 7 // power en
#define LORA_PA_EN 2
#define LORA_PA_TX_EN 46 // enable tx
#if HAS_TFT
#define USE_TFTDISPLAY 1

View File

@@ -73,29 +73,7 @@
#define SX126X_DIO2_AS_RF_SWITCH
#define SX126X_DIO3_TCXO_VOLTAGE 1.8
// ---- GC1109 RF FRONT END CONFIGURATION ----
// The Heltec Wireless Tracker V2 uses a GC1109 FEM chip with integrated PA and LNA
// RF path: SX1262 -> GC1109 PA -> Pi attenuator -> Antenna
// Measured net TX gain (non-linear due to PA compression):
// +11dB at 0-15dBm input (e.g., 10dBm in -> 21dBm out)
// +10dB at 16-17dBm input
// +9dB at 18-19dBm input
// +7dB at 21dBm input (e.g., 21dBm in -> 28dBm out max)
// Control logic (from GC1109 datasheet):
// Shutdown: CSD=0, CTX=X, CPS=X
// Receive LNA: CSD=1, CTX=0, CPS=X (17dB gain, 2dB NF)
// Transmit bypass: CSD=1, CTX=1, CPS=0 (~1dB loss, no PA)
// Transmit PA: CSD=1, CTX=1, CPS=1 (full PA enabled)
// Pin mapping:
// CTX (pin 6) -> SX1262 DIO2: TX/RX path select (automatic via SX126X_DIO2_AS_RF_SWITCH)
// CSD (pin 4) -> GPIO4: Chip enable (HIGH=on, LOW=shutdown)
// CPS (pin 5) -> GPIO46: PA mode select (HIGH=full PA, LOW=bypass)
// VCC0/VCC1 -> Vfem via U3 LDO, controlled by GPIO7
#define USE_GC1109_PA
#define LORA_PA_POWER 7 // VFEM_Ctrl - GC1109 LDO power enable
#define LORA_PA_EN 4 // CSD - GC1109 chip enable (HIGH=on)
#define LORA_PA_TX_EN 46 // CPS - GC1109 PA mode (HIGH=full PA, LOW=bypass)
// GC1109 FEM: TX/RX path switching is handled by DIO2 -> CTX pin (via SX126X_DIO2_AS_RF_SWITCH)
// GPIO46 is CPS (PA mode), not TX control - setTransmitEnable() handles it in SX126xInterface.cpp
// Do NOT use SX126X_TXEN/RXEN as that would cause double-control of GPIO46
#define USE_GC1109_PA // We have a GC1109 power amplifier+attenuator
#define LORA_PA_POWER 7 // power en
#define LORA_PA_EN 4
#define LORA_PA_TX_EN 46 // enable tx