Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 39 additions & 0 deletions boards/station-g1.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
{
"build": {
"arduino": {
"ldscript": "esp32.ld"
},
"core": "esp32",
"extra_flags": [
"-D RADIOLIB_DEBUG=1"
],
"f_cpu": "240000000L",
"f_flash": "40000000L",
"flash_mode": "dio",
"mcu": "esp32",
"variant": "esp32"
},
"connectivity": [
"wifi"
],
"debug": {
"default_tool": "esp-builtin",
"onboard_tools": [
"esp-builtin"
],
"openocd_target": "esp32.cfg"
},
"frameworks": [
"arduino"
],
"name": "BQ Station G1",
"upload": {
"flash_size": "4MB",
"maximum_ram_size": 327680,
"maximum_size": 4194304,
"require_upload_port": true,
"speed": 460800
},
"url": "https://www.uniteng.com/wiki/doku.php?id=meshtastic:station",
"vendor": "BQ Consulting"
}
89 changes: 89 additions & 0 deletions variants/station_g1/StationG1Board.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
#pragma once

#include <Arduino.h>
#include <helpers/ESP32Board.h>
#include <driver/rtc_io.h>

// From Meshtastic Station G1 variant.h
#ifndef BATTERY_PIN
#define BATTERY_PIN 35
#endif

#ifndef BATTERY_SENSE_SAMPLES
#define BATTERY_SENSE_SAMPLES 30
#endif

#ifndef ADC_MULTIPLIER
#define ADC_MULTIPLIER 6.45f
#endif

class StationG1Board : public ESP32Board {
public:
void begin() {
ESP32Board::begin();

Serial.begin(115200);
delay(1000);
Serial.println("booting station g1 meshcore");

// Battery ADC setup
analogReadResolution(12);
analogSetPinAttenuation((uint8_t)BATTERY_PIN, ADC_11db);

esp_reset_reason_t reason = esp_reset_reason();
if (reason == ESP_RST_DEEPSLEEP) {
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)
startup_reason = BD_STARTUP_RX_PACKET;
}

rtc_gpio_hold_dis((gpio_num_t)P_LORA_NSS);
rtc_gpio_deinit((gpio_num_t)P_LORA_DIO_1);
}
}

void enterDeepSleep(uint32_t secs, int pin_wake_btn = -1) {
esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON);

rtc_gpio_set_direction((gpio_num_t)P_LORA_DIO_1, RTC_GPIO_MODE_INPUT_ONLY);
rtc_gpio_pulldown_en((gpio_num_t)P_LORA_DIO_1);

rtc_gpio_hold_en((gpio_num_t)P_LORA_NSS);

if (pin_wake_btn < 0) {
esp_sleep_enable_ext1_wakeup((1L << P_LORA_DIO_1), ESP_EXT1_WAKEUP_ANY_HIGH);
} else {
esp_sleep_enable_ext1_wakeup((1L << P_LORA_DIO_1) | (1L << pin_wake_btn), ESP_EXT1_WAKEUP_ANY_HIGH);
}

if (secs > 0) {
esp_sleep_enable_timer_wakeup(secs * 1000000);
}

esp_deep_sleep_start();
}

uint16_t getBattMilliVolts() override {
uint32_t acc_mv = 0;
for (int i = 0; i < BATTERY_SENSE_SAMPLES; i++) {
acc_mv += (uint32_t)analogReadMilliVolts((uint8_t)BATTERY_PIN);
delay(2);
}

const float pin_mv = (float)acc_mv / (float)BATTERY_SENSE_SAMPLES;
const float batt_mv = pin_mv * ADC_MULTIPLIER;

if (batt_mv < 0.0f) {
return 0;
}
if (batt_mv > 65535.0f) {
return 65535;
}
return (uint16_t)(batt_mv + 0.5f);
}

const char* getManufacturerName() const override {
return "Station G1";
}
};

254 changes: 254 additions & 0 deletions variants/station_g1/platformio.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,254 @@
[Station_G1]
extends = esp32_base
board = station-g1

build_flags =
${esp32_base.build_flags}
${sensor_base.build_flags}
-I variants/station_g1
-I src/helpers/ui
-D STATION_G1
-D RADIO_CLASS=CustomSX1262
-D WRAPPER_CLASS=CustomSX1262Wrapper

; ---- LoRa (SX1262) ----
-D P_LORA_DIO_1=33
-D P_LORA_BUSY=32
-D P_LORA_RESET=23

; TODO: confirm these 4 from Station G1 schematic/PCB
-D P_LORA_NSS=18
-D P_LORA_SCLK=5
-D P_LORA_MISO=19
-D P_LORA_MOSI=27

; Station G1 uses DIO2 as RF switch internally (per your Meshtastic snippet)
-D SX126X_DIO2_AS_RF_SWITCH=true

; This is the Meshtastic Station G1 "do not exceed PA saturation" constraint
-D MAX_LORA_TX_POWER=16

; Optional defaults (tune for your deployment)
-D LORA_TX_POWER=8

; ---- I2C ----
-D PIN_BOARD_SDA=21
-D PIN_BOARD_SCL=22

; ---- Button ----
-D PIN_USER_BTN=36

; ---- GPS header (optional) ----
-D PIN_GPS_RX=34
-D PIN_GPS_TX=12

; ---- Display ----
-D DISPLAY_CLASS=SH1106Display

build_src_filter = ${esp32_base.build_src_filter}
+<../variants/station_g1>
+<helpers/sensors>
+<helpers/ui/SH1106Display.cpp>
+<helpers/ui/MomentaryButton.cpp>
lib_deps =
${esp32_base.lib_deps}
${sensor_base.lib_deps}
adafruit/Adafruit SH110X @ ~2.1.13
adafruit/Adafruit GFX Library @ ^1.12.1

[env:Station_G1_repeater]
extends = Station_G1
build_flags =
${Station_G1.build_flags}
-D ADVERT_NAME='"Station G1 Repeater"'
-D ADVERT_LAT=0.0
-D ADVERT_LON=0.0
-D ADMIN_PASSWORD='"password"'
-D MAX_NEIGHBOURS=50
; -D MESH_PACKET_LOGGING=1
; -D MESH_DEBUG=1
build_src_filter = ${Station_G1.build_src_filter}
+<../examples/simple_repeater>
lib_deps =
${Station_G1.lib_deps}
${esp32_ota.lib_deps}

; [env:Station_G1_repeater_bridge_rs232]
; extends = Station_G1
; build_flags =
; ${Station_G1.build_flags}
; -D ADVERT_NAME='"RS232 Bridge"'
; -D ADVERT_LAT=0.0
; -D ADVERT_LON=0.0
; -D ADMIN_PASSWORD='"password"'
; -D MAX_NEIGHBOURS=50
; -D WITH_RS232_BRIDGE=Serial2
; -D WITH_RS232_BRIDGE_RX=5
; -D WITH_RS232_BRIDGE_TX=6
; -D BRIDGE_DEBUG=1
; ; -D MESH_PACKET_LOGGING=1
; ; -D MESH_DEBUG=1
; build_src_filter = ${Station_G1.build_src_filter}
; +<helpers/bridges/RS232Bridge.cpp>
; +<../examples/simple_repeater>
; lib_deps =
; ${Station_G1.lib_deps}
; ${esp32_ota.lib_deps}

[env:Station_G1_repeater_bridge_espnow]
extends = Station_G1
build_flags =
${Station_G1.build_flags}
-D ADVERT_NAME='"ESPNow Bridge"'
-D ADVERT_LAT=0.0
-D ADVERT_LON=0.0
-D ADMIN_PASSWORD='"password"'
-D MAX_NEIGHBOURS=50
-D WITH_ESPNOW_BRIDGE=1
; -D BRIDGE_DEBUG=1
; -D MESH_PACKET_LOGGING=1
; -D MESH_DEBUG=1
build_src_filter = ${Station_G1.build_src_filter}
+<helpers/bridges/ESPNowBridge.cpp>
+<../examples/simple_repeater>
lib_deps =
${Station_G1.lib_deps}
${esp32_ota.lib_deps}

[env:Station_G1_logging_repeater]
extends = Station_G1
build_flags =
${Station_G1.build_flags}
-D ADVERT_NAME='"Station G1 Logging Repeater"'
-D ADVERT_LAT=0.0
-D ADVERT_LON=0.0
-D ADMIN_PASSWORD='"password"'
-D MAX_NEIGHBOURS=50
-D MESH_PACKET_LOGGING=1
-D SX126X_RX_BOOSTED_GAIN=1
; https://wiki.uniteng.com/en/meshtastic/station-g2#impact-of-lora-node-dense-areashigh-noise-environments-on-rf-performance
; -D MESH_DEBUG=1
build_src_filter = ${Station_G1.build_src_filter}
+<../examples/simple_repeater>
lib_deps =
${Station_G1.lib_deps}
${esp32_ota.lib_deps}

; [env:Station_G1_logging_repeater_bridge_rs232]
; extends = Station_G1
; build_flags =
; ${Station_G1.build_flags}
; -D ADVERT_NAME='"RS232 Bridge"'
; -D ADVERT_LAT=0.0
; -D ADVERT_LON=0.0
; -D ADMIN_PASSWORD='"password"'
; -D MAX_NEIGHBOURS=50
; -D MESH_PACKET_LOGGING=1
; -D SX126X_RX_BOOSTED_GAIN=1
; -D WITH_RS232_BRIDGE=Serial2
; -D WITH_RS232_BRIDGE_RX=5
; -D WITH_RS232_BRIDGE_TX=6
; -D BRIDGE_DEBUG=1
; ; -D MESH_DEBUG=1
; build_src_filter = ${Station_G1.build_src_filter}
; +<helpers/bridges/RS232Bridge.cpp>
; +<../examples/simple_repeater>
; lib_deps =
; ${Station_G1.lib_deps}
; ${esp32_ota.lib_deps}

[env:Station_G1_logging_repeater_bridge_espnow]
extends = Station_G1
build_flags =
${Station_G1.build_flags}
-D ADVERT_NAME='"ESPNow Bridge"'
-D ADVERT_LAT=0.0
-D ADVERT_LON=0.0
-D ADMIN_PASSWORD='"password"'
-D MAX_NEIGHBOURS=50
-D MESH_PACKET_LOGGING=1
-D SX126X_RX_BOOSTED_GAIN=1
-D WITH_ESPNOW_BRIDGE=1
; -D BRIDGE_DEBUG=1
; -D MESH_DEBUG=1
build_src_filter = ${Station_G1.build_src_filter}
+<helpers/bridges/ESPNowBridge.cpp>
+<../examples/simple_repeater>
lib_deps =
${Station_G1.lib_deps}
${esp32_ota.lib_deps}

[env:Station_G1_room_server]
extends = Station_G1
build_src_filter = ${Station_G1.build_src_filter}
+<../examples/simple_room_server>
build_flags =
${Station_G1.build_flags}
-D ADVERT_NAME='"Station G1 Room"'
-D ADVERT_LAT=0.0
-D ADVERT_LON=0.0
-D ADMIN_PASSWORD='"password"'
-D ROOM_PASSWORD='"hello"'
; -D MESH_PACKET_LOGGING=1
; -D MESH_DEBUG=1
lib_deps =
${Station_G1.lib_deps}
${esp32_ota.lib_deps}

[env:Station_G1_companion_radio_usb]
extends = Station_G1
build_flags =
${Station_G1.build_flags}
-I examples/companion_radio/ui-new
-D MAX_CONTACTS=350
-D MAX_GROUP_CHANNELS=40
; NOTE: DO NOT ENABLE --> -D MESH_PACKET_LOGGING=1
; NOTE: DO NOT ENABLE --> -D MESH_DEBUG=1
build_src_filter = ${Station_G1.build_src_filter}
+<helpers/esp32/*.cpp>
+<../examples/companion_radio/*.cpp>
+<../examples/companion_radio/ui-new/*.cpp>
lib_deps =
${Station_G1.lib_deps}
densaugeo/base64 @ ~1.4.0

[env:Station_G1_companion_radio_ble]
extends = Station_G1
build_flags =
${Station_G1.build_flags}
-I examples/companion_radio/ui-new
-D MAX_CONTACTS=350
-D MAX_GROUP_CHANNELS=40
-D BLE_PIN_CODE=022288
-D BLE_DEBUG_LOGGING=1
-D OFFLINE_QUEUE_SIZE=256
; -D MESH_PACKET_LOGGING=1
; -D MESH_DEBUG=1
build_src_filter = ${Station_G1.build_src_filter}
+<helpers/esp32/*.cpp>
+<../examples/companion_radio/*.cpp>
+<../examples/companion_radio/ui-new/*.cpp>
lib_deps =
${Station_G1.lib_deps}
densaugeo/base64 @ ~1.4.0

[env:Station_G1_companion_radio_wifi]
extends = Station_G1
build_flags =
${Station_G1.build_flags}
-I examples/companion_radio/ui-new
-D MAX_CONTACTS=350
-D MAX_GROUP_CHANNELS=40
-D WIFI_DEBUG_LOGGING=1
-D WIFI_SSID='"myssid"'
-D WIFI_PWD='"mypwd"'
-D OFFLINE_QUEUE_SIZE=256
; -D MESH_PACKET_LOGGING=1
; -D MESH_DEBUG=1
build_src_filter = ${Station_G1.build_src_filter}
+<helpers/esp32/*.cpp>
+<../examples/companion_radio/*.cpp>
+<../examples/companion_radio/ui-new/*.cpp>
lib_deps =
${Station_G1.lib_deps}
densaugeo/base64 @ ~1.4.0
Loading