mirror of
https://github.com/MarekZegare4/MeshCore-Solo.git
synced 2026-11-02 10:51:57 +00:00
Merge upstream companion-v1.18.0
Fixes and features from upstream: MACThenDecrypt / command buffer overflow fixes, ACK forwarding delay, transport code 0 as unscoped, hidden nodes don't answer DISCOVER, LR2021/LR1121 fixes, GPS cold-start detection and waitFor()/drain(), NMEA fix-age counters, ESP32 RTC after a crash, remote CLI by text message (TXT_TYPE_CLI_COMMAND), PUSH_CODE_BINARY_RESPONSE, board.loop(), new boards (Wio Tracker L1 1W, ThinkNode M4/M8, Muzi Base, Waveshare LR1121, Pico W). Kept ours: NodePrefs, main.cpp, every UI, GxEPDDisplay. The companion CLI stays MyMeshCli.h's handleCliCommand(); upstream's handleCommand() calls it. The board's FEM gains go through attachDynamicPrefs() with an adapter over our NodePrefs fields. Upstream's JSON prefs and MultiSerialInterface come as their own stages. Also: the display defaults were inside RADIO_FEM_TXGAIN's #else (a missing #endif). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -7,7 +7,6 @@ build_flags = ${nrf52_base.build_flags}
|
||||
-I variants/gat562_30s_mesh_kit
|
||||
-D RAK_4631
|
||||
-D RAK_BOARD
|
||||
-D NRF52_POWER_MANAGEMENT
|
||||
-D PIN_BOARD_SCL=14
|
||||
-D PIN_BOARD_SDA=13
|
||||
-D PIN_OLED_RESET=-1
|
||||
|
||||
@@ -5,7 +5,6 @@ board_check = true
|
||||
build_flags = ${nrf52_base.build_flags}
|
||||
${sensor_base.build_flags}
|
||||
-I variants/gat562_mesh_evb_pro
|
||||
-D NRF52_POWER_MANAGEMENT
|
||||
-D PIN_BOARD_SCL=14
|
||||
-D PIN_BOARD_SDA=13
|
||||
-D RADIO_CLASS=CustomSX1262
|
||||
|
||||
@@ -5,7 +5,6 @@ board_check = true
|
||||
build_flags = ${nrf52_base.build_flags}
|
||||
${sensor_base.build_flags}
|
||||
-I variants/gat562_mesh_tracker_pro
|
||||
-D NRF52_POWER_MANAGEMENT
|
||||
-D PIN_BOARD_SCL=14
|
||||
-D PIN_BOARD_SDA=13
|
||||
-D PIN_OLED_RESET=-1
|
||||
|
||||
@@ -8,7 +8,6 @@ build_flags = ${nrf52_base.build_flags}
|
||||
-I variants/gat562_mesh_watch13
|
||||
-D RAK_4631
|
||||
-D RAK_BOARD
|
||||
-D NRF52_POWER_MANAGEMENT
|
||||
-D PIN_BOARD_SCL=14
|
||||
-D PIN_BOARD_SDA=13
|
||||
-D PIN_OLED_RESET=-1
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
[Heltec_ct62]
|
||||
extends = esp32_base
|
||||
board = esp32-c3-devkitm-1
|
||||
board_build.partitions = min_spiffs.csv ; get around 4mb flash limit
|
||||
build_flags =
|
||||
${esp32_base.build_flags}
|
||||
-I variants/heltec_ct62
|
||||
|
||||
@@ -173,6 +173,7 @@ extends = Heltec_RC32
|
||||
build_flags =
|
||||
${Heltec_RC32.build_flags}
|
||||
-I examples/companion_radio/ui-new
|
||||
-D ENABLE_WIFI_INTERFACE
|
||||
-D DISPLAY_CLASS=NullDisplayDriver
|
||||
-D MAX_CONTACTS=350
|
||||
-D MAX_GROUP_CHANNELS=40
|
||||
@@ -185,6 +186,7 @@ build_src_filter = ${Heltec_RC32.build_src_filter}
|
||||
+<helpers/ui/buzzer.cpp>
|
||||
+<helpers/ui/NullDisplayDriver.cpp>
|
||||
+<helpers/esp32/*.cpp>
|
||||
+<helpers/wifi/*.cpp>
|
||||
+<../examples/companion_radio/*.cpp>
|
||||
+<../examples/companion_radio/ui-new/*.cpp>
|
||||
lib_deps =
|
||||
@@ -314,6 +316,7 @@ extends = Heltec_RC32_with_display
|
||||
build_flags =
|
||||
${Heltec_RC32_with_display.build_flags}
|
||||
-I examples/companion_radio/ui-new
|
||||
-D ENABLE_WIFI_INTERFACE
|
||||
-D UI_HAS_ROTARY_INPUT
|
||||
-D MAX_CONTACTS=350
|
||||
-D MAX_GROUP_CHANNELS=40
|
||||
@@ -324,6 +327,7 @@ build_flags =
|
||||
build_src_filter = ${Heltec_RC32_with_display.build_src_filter}
|
||||
+<helpers/ui/buzzer.cpp>
|
||||
+<helpers/esp32/*.cpp>
|
||||
+<helpers/wifi/*.cpp>
|
||||
+<../examples/companion_radio/*.cpp>
|
||||
+<../examples/companion_radio/ui-new/*.cpp>
|
||||
lib_deps =
|
||||
|
||||
@@ -131,10 +131,50 @@ bool T096Board::setLoRaFemLnaEnabled(bool enable) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool T096Board::canControlLoRaFemLna() const {
|
||||
return loRaFEMControl.isLnaCanControl();
|
||||
}
|
||||
|
||||
bool T096Board::isLoRaFemLnaEnabled() const {
|
||||
return loRaFEMControl.isLNAEnabled();
|
||||
}
|
||||
|
||||
void T096Board::attachDynamicPrefs(KeyValueStore* prefs) {
|
||||
_prefs = prefs;
|
||||
|
||||
char radio_fem_rxgain[8] = { 0 };
|
||||
_prefs->getByKey("fem_rxgain", radio_fem_rxgain, 7); // get initial values
|
||||
|
||||
setLoRaFemLnaEnabled(strcmp(radio_fem_rxgain, "1") == 0);
|
||||
}
|
||||
|
||||
bool T096Board::handleCommand(const char* command, uint32_t sender_timestamp, char* reply) {
|
||||
if (strcmp(command, "get radio.fem.rxgain") == 0) {
|
||||
if (!loRaFEMControl.isLnaCanControl()) {
|
||||
strcpy(reply, "Error: unsupported");
|
||||
} else {
|
||||
sprintf(reply, "> %s", isLoRaFemLnaEnabled() ? "on" : "off");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (memcmp(command, "set radio.fem.rxgain ", 21) == 0) {
|
||||
if (!loRaFEMControl.isLnaCanControl()) {
|
||||
strcpy(reply, "Error: unsupported");
|
||||
} else if (memcmp(&command[21], "on", 2) == 0) {
|
||||
if (setLoRaFemLnaEnabled(true)) {
|
||||
_prefs->setByKey("fem_rxgain", "1");
|
||||
strcpy(reply, "OK - LoRa FEM RX gain on");
|
||||
} else {
|
||||
strcpy(reply, "Error: failed to apply LoRa FEM RX gain");
|
||||
}
|
||||
} else if (memcmp(&command[21], "off", 3) == 0) {
|
||||
if (setLoRaFemLnaEnabled(false)) {
|
||||
_prefs->setByKey("fem_rxgain", "0");
|
||||
strcpy(reply, "OK - LoRa FEM RX gain off");
|
||||
} else {
|
||||
strcpy(reply, "Error: failed to apply LoRa FEM RX gain");
|
||||
}
|
||||
} else {
|
||||
strcpy(reply, "Error: state must be on or off");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return false; // not handled
|
||||
}
|
||||
|
||||
@@ -4,28 +4,33 @@
|
||||
#include <Arduino.h>
|
||||
#include <helpers/NRF52Board.h>
|
||||
#include <helpers/RefCountedDigitalPin.h>
|
||||
#include <helpers/KeyValueStore.h>
|
||||
#include "LoRaFEMControl.h"
|
||||
|
||||
class T096Board : public NRF52BoardDCDC {
|
||||
KeyValueStore* _prefs = NULL;
|
||||
|
||||
protected:
|
||||
#ifdef NRF52_POWER_MANAGEMENT
|
||||
void initiateShutdown(uint8_t reason) override;
|
||||
#endif
|
||||
void variant_shutdown();
|
||||
|
||||
bool setLoRaFemLnaEnabled(bool enable);
|
||||
bool isLoRaFemLnaEnabled() const;
|
||||
|
||||
public:
|
||||
RefCountedDigitalPin periph_power;
|
||||
LoRaFEMControl loRaFEMControl;
|
||||
|
||||
T096Board() :periph_power(PIN_VEXT_EN,PIN_VEXT_EN_ACTIVE), NRF52Board("T096_OTA") {}
|
||||
void begin();
|
||||
void attachDynamicPrefs(KeyValueStore* prefs);
|
||||
bool handleCommand(const char* command, uint32_t sender_timestamp, char* reply) override;
|
||||
|
||||
void onBeforeTransmit(void) override;
|
||||
void onAfterTransmit(void) override;
|
||||
uint16_t getBattMilliVolts() override;
|
||||
const char* getManufacturerName() const override ;
|
||||
void powerOff() override;
|
||||
bool setLoRaFemLnaEnabled(bool enable) override;
|
||||
bool canControlLoRaFemLna() const override;
|
||||
bool isLoRaFemLnaEnabled() const override;
|
||||
};
|
||||
|
||||
@@ -9,7 +9,6 @@ build_flags = ${nrf52_base.build_flags}
|
||||
-I variants/heltec_t096
|
||||
-I src/helpers/ui
|
||||
-D HELTEC_T096
|
||||
-D NRF52_POWER_MANAGEMENT
|
||||
-D P_LORA_DIO_1=21
|
||||
-D P_LORA_NSS=5
|
||||
-D P_LORA_RESET=16
|
||||
|
||||
@@ -9,6 +9,12 @@
|
||||
#define USE_LFXO
|
||||
#define VARIANT_MCK (64000000ul)
|
||||
|
||||
// This board has no external RTC chip -- the ICM-42607-P IMU sits at 0x68,
|
||||
// the same I2C address DS3231 probing checks, so without this the IMU gets
|
||||
// misidentified as a DS3231 and its unrelated registers get read/written
|
||||
// as if they were time/status registers, producing a bogus, unfixable clock.
|
||||
#define DISABLE_DS3231_PROBE
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Number of pins
|
||||
|
||||
|
||||
@@ -12,7 +12,6 @@ build_flags = ${nrf52_base.build_flags}
|
||||
-I variants/heltec_t114
|
||||
-I src/helpers/ui
|
||||
-D HELTEC_T114
|
||||
-D NRF52_POWER_MANAGEMENT
|
||||
-D P_LORA_DIO_1=20
|
||||
-D P_LORA_NSS=24
|
||||
-D P_LORA_RESET=25
|
||||
|
||||
@@ -72,10 +72,50 @@ void HeltecTrackerV2Board::begin() {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool HeltecTrackerV2Board::canControlLoRaFemLna() const {
|
||||
return loRaFEMControl.isLnaCanControl();
|
||||
}
|
||||
|
||||
bool HeltecTrackerV2Board::isLoRaFemLnaEnabled() const {
|
||||
return loRaFEMControl.isLNAEnabled();
|
||||
}
|
||||
|
||||
void HeltecTrackerV2Board::attachDynamicPrefs(KeyValueStore* prefs) {
|
||||
_prefs = prefs;
|
||||
|
||||
char radio_fem_rxgain[8] = { 0 };
|
||||
_prefs->getByKey("fem_rxgain", radio_fem_rxgain, 7); // get initial values
|
||||
|
||||
setLoRaFemLnaEnabled(strcmp(radio_fem_rxgain, "1") == 0);
|
||||
}
|
||||
|
||||
bool HeltecTrackerV2Board::handleCommand(const char* command, uint32_t sender_timestamp, char* reply) {
|
||||
if (strcmp(command, "get radio.fem.rxgain") == 0) {
|
||||
if (!loRaFEMControl.isLnaCanControl()) {
|
||||
strcpy(reply, "Error: unsupported");
|
||||
} else {
|
||||
sprintf(reply, "> %s", isLoRaFemLnaEnabled() ? "on" : "off");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (memcmp(command, "set radio.fem.rxgain ", 21) == 0) {
|
||||
if (!loRaFEMControl.isLnaCanControl()) {
|
||||
strcpy(reply, "Error: unsupported");
|
||||
} else if (memcmp(&command[21], "on", 2) == 0) {
|
||||
if (setLoRaFemLnaEnabled(true)) {
|
||||
_prefs->setByKey("fem_rxgain", "1");
|
||||
strcpy(reply, "OK - LoRa FEM RX gain on");
|
||||
} else {
|
||||
strcpy(reply, "Error: failed to apply LoRa FEM RX gain");
|
||||
}
|
||||
} else if (memcmp(&command[21], "off", 3) == 0) {
|
||||
if (setLoRaFemLnaEnabled(false)) {
|
||||
_prefs->setByKey("fem_rxgain", "0");
|
||||
strcpy(reply, "OK - LoRa FEM RX gain off");
|
||||
} else {
|
||||
strcpy(reply, "Error: failed to apply LoRa FEM RX gain");
|
||||
}
|
||||
} else {
|
||||
strcpy(reply, "Error: state must be on or off");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return false; // not handled
|
||||
}
|
||||
|
||||
@@ -6,6 +6,10 @@
|
||||
#include "LoRaFEMControl.h"
|
||||
|
||||
class HeltecTrackerV2Board : public ESP32Board {
|
||||
KeyValueStore* _prefs = NULL;
|
||||
|
||||
bool setLoRaFemLnaEnabled(bool enable);
|
||||
bool isLoRaFemLnaEnabled() const;
|
||||
|
||||
public:
|
||||
RefCountedDigitalPin periph_power;
|
||||
@@ -14,13 +18,13 @@ public:
|
||||
HeltecTrackerV2Board() : periph_power(PIN_VEXT_EN,PIN_VEXT_EN_ACTIVE) { }
|
||||
|
||||
void begin();
|
||||
void attachDynamicPrefs(KeyValueStore* prefs);
|
||||
bool handleCommand(const char* command, uint32_t sender_timestamp, char* reply) override;
|
||||
|
||||
void onBeforeTransmit(void) override;
|
||||
void onAfterTransmit(void) override;
|
||||
void powerOff() override;
|
||||
uint16_t getBattMilliVolts() override;
|
||||
const char* getManufacturerName() const override ;
|
||||
bool setLoRaFemLnaEnabled(bool enable) override;
|
||||
bool canControlLoRaFemLna() const override;
|
||||
bool isLoRaFemLnaEnabled() const override;
|
||||
|
||||
};
|
||||
|
||||
@@ -183,6 +183,7 @@ extends = Heltec_tracker_v2
|
||||
build_flags =
|
||||
${Heltec_tracker_v2.build_flags}
|
||||
-I examples/companion_radio/ui-new
|
||||
-D ENABLE_WIFI_INTERFACE
|
||||
-D MAX_CONTACTS=350
|
||||
-D MAX_GROUP_CHANNELS=40
|
||||
-D DISPLAY_CLASS=ST7735Display
|
||||
@@ -196,6 +197,7 @@ build_src_filter = ${Heltec_tracker_v2.build_src_filter}
|
||||
+<helpers/ui/ST7735Display.cpp>
|
||||
+<helpers/ui/MomentaryButton.cpp>
|
||||
+<helpers/esp32/*.cpp>
|
||||
+<helpers/wifi/*.cpp>
|
||||
+<../examples/companion_radio/*.cpp>
|
||||
+<../examples/companion_radio/ui-new/*.cpp>
|
||||
lib_deps =
|
||||
|
||||
@@ -178,6 +178,7 @@ extends = Heltec_lora32_v2
|
||||
build_flags =
|
||||
${Heltec_lora32_v2.build_flags}
|
||||
-I examples/companion_radio/ui-new
|
||||
-D ENABLE_WIFI_INTERFACE
|
||||
-D DISPLAY_CLASS=SSD1306Display
|
||||
-D MAX_CONTACTS=160
|
||||
-D MAX_GROUP_CHANNELS=8
|
||||
@@ -189,6 +190,7 @@ build_flags =
|
||||
; -D MESH_DEBUG=1
|
||||
build_src_filter = ${Heltec_lora32_v2.build_src_filter}
|
||||
+<helpers/esp32/*.cpp>
|
||||
+<helpers/wifi/*.cpp>
|
||||
+<helpers/ui/SSD1306Display.cpp>
|
||||
+<helpers/ui/MomentaryButton.cpp>
|
||||
+<../examples/companion_radio/*.cpp>
|
||||
|
||||
@@ -168,12 +168,14 @@ build_flags =
|
||||
-D AUTO_SHUTDOWN_MILLIVOLTS=3400
|
||||
-D BLE_DEBUG_LOGGING=1
|
||||
-D OFFLINE_QUEUE_SIZE=256
|
||||
-D ENABLE_WIFI_INTERFACE
|
||||
; -D MESH_PACKET_LOGGING=1
|
||||
; -D MESH_DEBUG=1
|
||||
build_src_filter = ${Heltec_lora32_v3.build_src_filter}
|
||||
+<helpers/ui/SSD1306Display.cpp>
|
||||
+<helpers/ui/MomentaryButton.cpp>
|
||||
+<helpers/esp32/*.cpp>
|
||||
+<helpers/wifi/*.cpp>
|
||||
+<../examples/companion_radio/*.cpp>
|
||||
+<../examples/companion_radio/ui-new/*.cpp>
|
||||
lib_deps =
|
||||
@@ -185,6 +187,7 @@ extends = Heltec_lora32_v3
|
||||
build_flags =
|
||||
${Heltec_lora32_v3.build_flags}
|
||||
-I examples/companion_radio/ui-new
|
||||
-D ENABLE_WIFI_INTERFACE
|
||||
-D MAX_CONTACTS=350
|
||||
-D MAX_GROUP_CHANNELS=40
|
||||
-D DISPLAY_CLASS=SSD1306Display
|
||||
@@ -198,6 +201,7 @@ build_src_filter = ${Heltec_lora32_v3.build_src_filter}
|
||||
+<helpers/ui/SSD1306Display.cpp>
|
||||
+<helpers/ui/MomentaryButton.cpp>
|
||||
+<helpers/esp32/*.cpp>
|
||||
+<helpers/wifi/*.cpp>
|
||||
+<../examples/companion_radio/*.cpp>
|
||||
+<../examples/companion_radio/ui-new/*.cpp>
|
||||
lib_deps =
|
||||
@@ -310,12 +314,14 @@ build_flags =
|
||||
-D MAX_CONTACTS=350
|
||||
-D MAX_GROUP_CHANNELS=40
|
||||
-D BLE_PIN_CODE=123456
|
||||
-D BLE_DEBUG_LOGGING=1
|
||||
-D OFFLINE_QUEUE_SIZE=256
|
||||
-D ENABLE_WIFI_INTERFACE
|
||||
; -D BLE_DEBUG_LOGGING=1
|
||||
; -D MESH_PACKET_LOGGING=1
|
||||
; -D MESH_DEBUG=1
|
||||
build_src_filter = ${Heltec_lora32_v3.build_src_filter}
|
||||
+<helpers/esp32/*.cpp>
|
||||
+<helpers/wifi/*.cpp>
|
||||
+<../examples/companion_radio/*.cpp>
|
||||
lib_deps =
|
||||
${Heltec_lora32_v3.lib_deps}
|
||||
@@ -340,6 +346,7 @@ lib_deps =
|
||||
extends = Heltec_lora32_v3
|
||||
build_flags =
|
||||
${Heltec_lora32_v3.build_flags}
|
||||
-D ENABLE_WIFI_INTERFACE
|
||||
-D MAX_CONTACTS=350
|
||||
-D MAX_GROUP_CHANNELS=40
|
||||
-D WIFI_DEBUG_LOGGING=1
|
||||
@@ -350,6 +357,7 @@ build_flags =
|
||||
; -D MESH_DEBUG=1
|
||||
build_src_filter = ${Heltec_lora32_v3.build_src_filter}
|
||||
+<helpers/esp32/*.cpp>
|
||||
+<helpers/wifi/*.cpp>
|
||||
+<../examples/companion_radio/*.cpp>
|
||||
lib_deps =
|
||||
${Heltec_lora32_v3.lib_deps}
|
||||
|
||||
@@ -73,10 +73,50 @@ void HeltecV4Board::begin() {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool HeltecV4Board::canControlLoRaFemLna() const {
|
||||
return loRaFEMControl.isLnaCanControl();
|
||||
}
|
||||
|
||||
bool HeltecV4Board::isLoRaFemLnaEnabled() const {
|
||||
return loRaFEMControl.isLNAEnabled();
|
||||
}
|
||||
|
||||
void HeltecV4Board::attachDynamicPrefs(KeyValueStore* prefs) {
|
||||
_prefs = prefs;
|
||||
|
||||
char radio_fem_rxgain[8] = { 0 };
|
||||
_prefs->getByKey("fem_rxgain", radio_fem_rxgain, 7); // get initial values
|
||||
|
||||
setLoRaFemLnaEnabled(strcmp(radio_fem_rxgain, "1") == 0);
|
||||
}
|
||||
|
||||
bool HeltecV4Board::handleCommand(const char* command, uint32_t sender_timestamp, char* reply) {
|
||||
if (strcmp(command, "get radio.fem.rxgain") == 0) {
|
||||
if (!loRaFEMControl.isLnaCanControl()) {
|
||||
strcpy(reply, "Error: unsupported");
|
||||
} else {
|
||||
sprintf(reply, "> %s", isLoRaFemLnaEnabled() ? "on" : "off");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (memcmp(command, "set radio.fem.rxgain ", 21) == 0) {
|
||||
if (!loRaFEMControl.isLnaCanControl()) {
|
||||
strcpy(reply, "Error: unsupported");
|
||||
} else if (memcmp(&command[21], "on", 2) == 0) {
|
||||
if (setLoRaFemLnaEnabled(true)) {
|
||||
_prefs->setByKey("fem_rxgain", "1");
|
||||
strcpy(reply, "OK - LoRa FEM RX gain on");
|
||||
} else {
|
||||
strcpy(reply, "Error: failed to apply LoRa FEM RX gain");
|
||||
}
|
||||
} else if (memcmp(&command[21], "off", 3) == 0) {
|
||||
if (setLoRaFemLnaEnabled(false)) {
|
||||
_prefs->setByKey("fem_rxgain", "0");
|
||||
strcpy(reply, "OK - LoRa FEM RX gain off");
|
||||
} else {
|
||||
strcpy(reply, "Error: failed to apply LoRa FEM RX gain");
|
||||
}
|
||||
} else {
|
||||
strcpy(reply, "Error: state must be on or off");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return false; // not handled
|
||||
}
|
||||
|
||||
@@ -10,6 +10,10 @@
|
||||
#endif
|
||||
|
||||
class HeltecV4Board : public ESP32Board {
|
||||
KeyValueStore* _prefs = NULL;
|
||||
|
||||
bool setLoRaFemLnaEnabled(bool enable);
|
||||
bool isLoRaFemLnaEnabled() const;
|
||||
|
||||
protected:
|
||||
float adc_mult = ADC_MULTIPLIER;
|
||||
@@ -20,12 +24,12 @@ public:
|
||||
HeltecV4Board() : periph_power(PIN_VEXT_EN,PIN_VEXT_EN_ACTIVE) { }
|
||||
|
||||
void begin();
|
||||
void attachDynamicPrefs(KeyValueStore* prefs);
|
||||
bool handleCommand(const char* command, uint32_t sender_timestamp, char* reply) override;
|
||||
|
||||
void onBeforeTransmit(void) override;
|
||||
void onAfterTransmit(void) override;
|
||||
void powerOff() override;
|
||||
bool setLoRaFemLnaEnabled(bool enable) override;
|
||||
bool canControlLoRaFemLna() const override;
|
||||
bool isLoRaFemLnaEnabled() const override;
|
||||
uint16_t getBattMilliVolts() override;
|
||||
bool setAdcMultiplier(float multiplier) override {
|
||||
if (multiplier == 0.0f) {
|
||||
|
||||
@@ -211,12 +211,14 @@ build_flags =
|
||||
-D AUTO_SHUTDOWN_MILLIVOLTS=3400
|
||||
-D BLE_DEBUG_LOGGING=1
|
||||
-D OFFLINE_QUEUE_SIZE=256
|
||||
-D ENABLE_WIFI_INTERFACE
|
||||
; -D MESH_PACKET_LOGGING=1
|
||||
; -D MESH_DEBUG=1
|
||||
build_src_filter = ${heltec_v4_oled.build_src_filter}
|
||||
+<helpers/ui/SSD1306Display.cpp>
|
||||
+<helpers/ui/MomentaryButton.cpp>
|
||||
+<helpers/esp32/*.cpp>
|
||||
+<helpers/wifi/*.cpp>
|
||||
+<../examples/companion_radio/*.cpp>
|
||||
+<../examples/companion_radio/ui-new/*.cpp>
|
||||
lib_deps =
|
||||
@@ -228,6 +230,7 @@ extends = heltec_v4_oled
|
||||
build_flags =
|
||||
${heltec_v4_oled.build_flags}
|
||||
-I examples/companion_radio/ui-new
|
||||
-D ENABLE_WIFI_INTERFACE
|
||||
-D MAX_CONTACTS=350
|
||||
-D MAX_GROUP_CHANNELS=40
|
||||
-D OFFLINE_QUEUE_SIZE=256
|
||||
@@ -241,6 +244,7 @@ build_src_filter = ${heltec_v4_oled.build_src_filter}
|
||||
+<helpers/ui/SSD1306Display.cpp>
|
||||
+<helpers/ui/MomentaryButton.cpp>
|
||||
+<helpers/esp32/*.cpp>
|
||||
+<helpers/wifi/*.cpp>
|
||||
+<../examples/companion_radio/*.cpp>
|
||||
+<../examples/companion_radio/ui-new/*.cpp>
|
||||
lib_deps =
|
||||
@@ -393,6 +397,7 @@ extends = heltec_v4_tft
|
||||
build_flags =
|
||||
${heltec_v4_tft.build_flags}
|
||||
-I examples/companion_radio/ui-new
|
||||
-D ENABLE_WIFI_INTERFACE
|
||||
-D MAX_CONTACTS=350
|
||||
-D MAX_GROUP_CHANNELS=40
|
||||
-D OFFLINE_QUEUE_SIZE=256
|
||||
@@ -406,6 +411,7 @@ build_src_filter = ${heltec_v4_tft.build_src_filter}
|
||||
+<helpers/ui/ST7789LCDDisplay.cpp>
|
||||
+<helpers/ui/MomentaryButton.cpp>
|
||||
+<helpers/esp32/*.cpp>
|
||||
+<helpers/wifi/*.cpp>
|
||||
+<../examples/companion_radio/*.cpp>
|
||||
+<../examples/companion_radio/ui-new/*.cpp>
|
||||
lib_deps =
|
||||
|
||||
@@ -84,3 +84,61 @@ const char* HeltecV4R8Board::getManufacturerName() const {
|
||||
return "Heltec V4 R8 OLED";
|
||||
#endif
|
||||
}
|
||||
|
||||
bool HeltecV4R8Board::setLoRaFemLnaEnabled(bool enable) {
|
||||
if (!loRaFEMControl.isLnaCanControl()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
loRaFEMControl.setLNAEnable(enable);
|
||||
loRaFEMControl.setRxModeEnable();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool HeltecV4R8Board::isLoRaFemLnaEnabled() const {
|
||||
return loRaFEMControl.isLNAEnabled();
|
||||
}
|
||||
|
||||
void HeltecV4R8Board::attachDynamicPrefs(KeyValueStore* prefs) {
|
||||
_prefs = prefs;
|
||||
|
||||
char radio_fem_rxgain[8] = { 0 };
|
||||
_prefs->getByKey("fem_rxgain", radio_fem_rxgain, 7); // get initial values
|
||||
|
||||
setLoRaFemLnaEnabled(strcmp(radio_fem_rxgain, "1") == 0);
|
||||
}
|
||||
|
||||
bool HeltecV4R8Board::handleCommand(const char* command, uint32_t sender_timestamp, char* reply) {
|
||||
if (strcmp(command, "get radio.fem.rxgain") == 0) {
|
||||
if (!loRaFEMControl.isLnaCanControl()) {
|
||||
strcpy(reply, "Error: unsupported");
|
||||
} else {
|
||||
sprintf(reply, "> %s", isLoRaFemLnaEnabled() ? "on" : "off");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (memcmp(command, "set radio.fem.rxgain ", 21) == 0) {
|
||||
if (!loRaFEMControl.isLnaCanControl()) {
|
||||
strcpy(reply, "Error: unsupported");
|
||||
} else if (memcmp(&command[21], "on", 2) == 0) {
|
||||
if (setLoRaFemLnaEnabled(true)) {
|
||||
_prefs->setByKey("fem_rxgain", "1");
|
||||
strcpy(reply, "OK - LoRa FEM RX gain on");
|
||||
} else {
|
||||
strcpy(reply, "Error: failed to apply LoRa FEM RX gain");
|
||||
}
|
||||
} else if (memcmp(&command[21], "off", 3) == 0) {
|
||||
if (setLoRaFemLnaEnabled(false)) {
|
||||
_prefs->setByKey("fem_rxgain", "0");
|
||||
strcpy(reply, "OK - LoRa FEM RX gain off");
|
||||
} else {
|
||||
strcpy(reply, "Error: failed to apply LoRa FEM RX gain");
|
||||
}
|
||||
} else {
|
||||
strcpy(reply, "Error: state must be on or off");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return false; // not handled
|
||||
}
|
||||
|
||||
@@ -11,6 +11,10 @@
|
||||
#endif
|
||||
|
||||
class HeltecV4R8Board : public ESP32Board {
|
||||
KeyValueStore* _prefs = NULL;
|
||||
|
||||
bool setLoRaFemLnaEnabled(bool enable);
|
||||
bool isLoRaFemLnaEnabled() const;
|
||||
protected:
|
||||
float adc_mult = ADC_MULTIPLIER;
|
||||
|
||||
@@ -21,6 +25,9 @@ public:
|
||||
HeltecV4R8Board() : periph_power(PIN_VEXT_EN, PIN_VEXT_EN_ACTIVE) { }
|
||||
|
||||
void begin();
|
||||
void attachDynamicPrefs(KeyValueStore* prefs);
|
||||
bool handleCommand(const char* command, uint32_t sender_timestamp, char* reply) override;
|
||||
|
||||
void onBeforeTransmit(void) override;
|
||||
void onAfterTransmit(void) override;
|
||||
void enterDeepSleep(uint32_t secs, int pin_wake_btn = -1);
|
||||
|
||||
@@ -17,6 +17,7 @@ public:
|
||||
void setLNAEnable(bool enabled);
|
||||
bool isLnaCanControl(void) { return true; }
|
||||
void setLnaCanControl(bool can_control) { }
|
||||
bool isLNAEnabled(void) const { return lna_enabled; }
|
||||
LoRaFEMType getFEMType(void) const { return KCT8103L_PA; }
|
||||
|
||||
private:
|
||||
|
||||
@@ -160,10 +160,12 @@ build_flags =
|
||||
-D AUTO_SHUTDOWN_MILLIVOLTS=3400
|
||||
-D BLE_DEBUG_LOGGING=1
|
||||
-D OFFLINE_QUEUE_SIZE=256
|
||||
-D ENABLE_WIFI_INTERFACE
|
||||
build_src_filter = ${heltec_v4_r8_oled.build_src_filter}
|
||||
+<helpers/ui/SSD1306Display.cpp>
|
||||
+<helpers/ui/MomentaryButton.cpp>
|
||||
+<helpers/esp32/*.cpp>
|
||||
+<helpers/wifi/*.cpp>
|
||||
+<../examples/companion_radio/*.cpp>
|
||||
+<../examples/companion_radio/ui-new/*.cpp>
|
||||
lib_deps =
|
||||
@@ -175,6 +177,7 @@ extends = heltec_v4_r8_oled
|
||||
build_flags =
|
||||
${heltec_v4_r8_oled.build_flags}
|
||||
-I examples/companion_radio/ui-new
|
||||
-D ENABLE_WIFI_INTERFACE
|
||||
-D MAX_CONTACTS=350
|
||||
-D MAX_GROUP_CHANNELS=40
|
||||
-D OFFLINE_QUEUE_SIZE=256
|
||||
@@ -186,6 +189,7 @@ build_src_filter = ${heltec_v4_r8_oled.build_src_filter}
|
||||
+<helpers/ui/SSD1306Display.cpp>
|
||||
+<helpers/ui/MomentaryButton.cpp>
|
||||
+<helpers/esp32/*.cpp>
|
||||
+<helpers/wifi/*.cpp>
|
||||
+<../examples/companion_radio/*.cpp>
|
||||
+<../examples/companion_radio/ui-new/*.cpp>
|
||||
lib_deps =
|
||||
@@ -300,6 +304,7 @@ extends = heltec_v4_r8_tft
|
||||
build_flags =
|
||||
${heltec_v4_r8_tft.build_flags}
|
||||
-I examples/companion_radio/ui-new
|
||||
-D ENABLE_WIFI_INTERFACE
|
||||
-D MAX_CONTACTS=350
|
||||
-D MAX_GROUP_CHANNELS=40
|
||||
-D OFFLINE_QUEUE_SIZE=256
|
||||
@@ -311,6 +316,7 @@ build_src_filter = ${heltec_v4_r8_tft.build_src_filter}
|
||||
+<helpers/ui/ST7789LCDDisplay.cpp>
|
||||
+<helpers/ui/MomentaryButton.cpp>
|
||||
+<helpers/esp32/*.cpp>
|
||||
+<helpers/wifi/*.cpp>
|
||||
+<../examples/companion_radio/*.cpp>
|
||||
+<../examples/companion_radio/ui-new/*.cpp>
|
||||
lib_deps =
|
||||
|
||||
@@ -52,11 +52,13 @@ build_flags =
|
||||
-D MAX_GROUP_CHANNELS=40
|
||||
-D DISPLAY_CLASS=E213Display
|
||||
-D BLE_PIN_CODE=123456 ; dynamic, random PIN
|
||||
-D BLE_DEBUG_LOGGING=1
|
||||
-D OFFLINE_QUEUE_SIZE=256
|
||||
-D ENABLE_WIFI_INTERFACE
|
||||
; -D BLE_DEBUG_LOGGING=1
|
||||
build_src_filter = ${Heltec_Wireless_Paper_base.build_src_filter}
|
||||
+<helpers/ui/E213Display.cpp>
|
||||
+<helpers/esp32/*.cpp>
|
||||
+<helpers/wifi/*.cpp>
|
||||
+<../examples/companion_radio/*.cpp>
|
||||
+<../examples/companion_radio/ui-new/*.cpp>
|
||||
lib_deps =
|
||||
|
||||
@@ -9,7 +9,7 @@ protected:
|
||||
uint8_t btn_prev_state;
|
||||
|
||||
public:
|
||||
TImpulsePlusBoard() : NRF52Board("T-Impulse-Plus OTA") {}
|
||||
TImpulsePlusBoard() : NRF52Board("T-Impulse-Plus_OTA") {}
|
||||
void begin();
|
||||
|
||||
#if defined(P_LORA_TX_LED)
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
#include "TBeam1WBoard.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
void TBeam1WBoard::begin() {
|
||||
ESP32Board::begin();
|
||||
|
||||
@@ -15,31 +20,61 @@ void TBeam1WBoard::begin() {
|
||||
pinMode(LED_PIN, OUTPUT);
|
||||
digitalWrite(LED_PIN, LOW);
|
||||
|
||||
// Initialize fan control (on by default - 1W PA can overheat)
|
||||
// NTC ADC (PA-adjacent thermistor)
|
||||
pinMode(NTC_PIN, INPUT);
|
||||
analogSetPinAttenuation(NTC_PIN, ADC_11db);
|
||||
analogReadResolution(12);
|
||||
|
||||
// Fan: auto/onoff. Thermal on at 36C / off below 30C; TX still forces a cooldown.
|
||||
pinMode(FAN_CTRL_PIN, OUTPUT);
|
||||
digitalWrite(FAN_CTRL_PIN, HIGH);
|
||||
_fan_on = true;
|
||||
_temp_c = readNtcTempC();
|
||||
startFanTask();
|
||||
}
|
||||
|
||||
void TBeam1WBoard::startFanTask() {
|
||||
if (_fan_task) return;
|
||||
xTaskCreate(fanTaskThunk, "tbeam1w_fan", 4096, this, 1, &_fan_task);
|
||||
}
|
||||
|
||||
void TBeam1WBoard::fanTaskThunk(void* arg) {
|
||||
auto* self = static_cast<TBeam1WBoard*>(arg);
|
||||
for (;;) {
|
||||
self->updateFan();
|
||||
vTaskDelay(pdMS_TO_TICKS(1000));
|
||||
}
|
||||
}
|
||||
|
||||
void TBeam1WBoard::onBeforeTransmit() {
|
||||
// RF switching handled by RadioLib via SX126X_DIO2_AS_RF_SWITCH and setRfSwitchPins()
|
||||
digitalWrite(LED_PIN, HIGH); // TX LED on
|
||||
portENTER_CRITICAL(&_fan_mux);
|
||||
_tx_active = true;
|
||||
if (_mode == FAN_AUTO && !_stopped) {
|
||||
setFanOutputLocked(true);
|
||||
}
|
||||
portEXIT_CRITICAL(&_fan_mux);
|
||||
}
|
||||
|
||||
void TBeam1WBoard::onAfterTransmit() {
|
||||
digitalWrite(LED_PIN, LOW); // TX LED off
|
||||
portENTER_CRITICAL(&_fan_mux);
|
||||
if (!_stopped) {
|
||||
_tx_until_ms = millis() + FAN_TX_COOLDOWN_MS;
|
||||
_tx_cooldown_active = true;
|
||||
}
|
||||
_tx_active = false;
|
||||
portEXIT_CRITICAL(&_fan_mux);
|
||||
}
|
||||
|
||||
uint16_t TBeam1WBoard::getBattMilliVolts() {
|
||||
// T-Beam 1W uses 7.4V battery with voltage divider
|
||||
// ADC reads through divider - adjust multiplier based on actual divider ratio
|
||||
analogReadResolution(12);
|
||||
uint32_t raw = 0;
|
||||
for (int i = 0; i < 8; i++) {
|
||||
raw += analogRead(BATTERY_PIN);
|
||||
}
|
||||
raw = raw / 8;
|
||||
// Assuming voltage divider ratio from ADC_MULTIPLIER
|
||||
// 3.3V reference, 12-bit ADC (4095 max)
|
||||
return static_cast<uint16_t>((raw * 3300 * ADC_MULTIPLIER) / 4095);
|
||||
}
|
||||
|
||||
@@ -48,6 +83,13 @@ const char* TBeam1WBoard::getManufacturerName() const {
|
||||
}
|
||||
|
||||
void TBeam1WBoard::powerOff() {
|
||||
portENTER_CRITICAL(&_fan_mux);
|
||||
_stopped = true;
|
||||
_tx_active = false;
|
||||
_tx_cooldown_active = false;
|
||||
setFanOutputLocked(false);
|
||||
portEXIT_CRITICAL(&_fan_mux);
|
||||
|
||||
// Turn off radio LNA (CTRL pin must be LOW when not receiving)
|
||||
digitalWrite(SX126X_RXEN, LOW);
|
||||
|
||||
@@ -55,17 +97,254 @@ void TBeam1WBoard::powerOff() {
|
||||
digitalWrite(SX126X_POWER_EN, LOW);
|
||||
radio_powered = false;
|
||||
|
||||
// Turn off LED and fan
|
||||
digitalWrite(LED_PIN, LOW);
|
||||
digitalWrite(FAN_CTRL_PIN, LOW);
|
||||
|
||||
ESP32Board::powerOff();
|
||||
}
|
||||
|
||||
void TBeam1WBoard::setFanEnabled(bool enabled) {
|
||||
digitalWrite(FAN_CTRL_PIN, enabled ? HIGH : LOW);
|
||||
portENTER_CRITICAL(&_fan_mux);
|
||||
setFanOutputLocked(enabled && !_stopped);
|
||||
portEXIT_CRITICAL(&_fan_mux);
|
||||
}
|
||||
|
||||
bool TBeam1WBoard::isFanEnabled() const {
|
||||
return digitalRead(FAN_CTRL_PIN) == HIGH;
|
||||
portENTER_CRITICAL(&_fan_mux);
|
||||
bool enabled = _fan_on;
|
||||
portEXIT_CRITICAL(&_fan_mux);
|
||||
return enabled;
|
||||
}
|
||||
|
||||
float TBeam1WBoard::readNtcTempC() {
|
||||
analogReadMilliVolts(NTC_PIN); // settle
|
||||
uint32_t sum = 0;
|
||||
for (int i = 0; i < 8; i++) {
|
||||
uint32_t sample_mv = analogReadMilliVolts(NTC_PIN);
|
||||
// GPIO14 is ADC2 on ESP32-S3. Wi-Fi/ESP-NOW arbitration failures are
|
||||
// reported by Arduino as 0 mV; never average a failed sample into a
|
||||
// plausible-but-low temperature.
|
||||
if (sample_mv == 0 || sample_mv >= NTC_VCC_MV) return NAN;
|
||||
sum += sample_mv;
|
||||
}
|
||||
float mv = sum / 8.0f;
|
||||
|
||||
// R_ntc = R_fixed * (Vcc - V) / V for 3.3V-NTC-ADC-10k-GND
|
||||
float r_ntc = NTC_R_FIXED * (NTC_VCC_MV - mv) / mv;
|
||||
if (r_ntc <= 0.0f) return NAN;
|
||||
|
||||
float temp_k = 1.0f / (1.0f / 298.15f + (1.0f / NTC_B) * logf(r_ntc / NTC_R25));
|
||||
return temp_k - 273.15f;
|
||||
}
|
||||
|
||||
bool TBeam1WBoard::ntcImplausible(float temp_c) const {
|
||||
return isnan(temp_c) || temp_c < -20.0f || temp_c > 120.0f;
|
||||
}
|
||||
|
||||
bool TBeam1WBoard::isTxCoolingLocked(uint32_t now) {
|
||||
if (_tx_active) return true;
|
||||
if (!_tx_cooldown_active) return false;
|
||||
if ((int32_t)(now - _tx_until_ms) >= 0) {
|
||||
_tx_cooldown_active = false;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
int TBeam1WBoard::cooldownSecsLocked() {
|
||||
if (_tx_active) return (FAN_TX_COOLDOWN_MS + 999) / 1000;
|
||||
if (!_tx_cooldown_active) return 0;
|
||||
int32_t remain_ms = (int32_t)(_tx_until_ms - millis());
|
||||
if (remain_ms <= 0) {
|
||||
_tx_cooldown_active = false;
|
||||
return 0;
|
||||
}
|
||||
return (remain_ms + 999) / 1000;
|
||||
}
|
||||
|
||||
void TBeam1WBoard::setFanOutputLocked(bool enabled) {
|
||||
_fan_on = enabled;
|
||||
digitalWrite(FAN_CTRL_PIN, enabled ? HIGH : LOW);
|
||||
}
|
||||
|
||||
void TBeam1WBoard::updateFan() {
|
||||
float t = readNtcTempC();
|
||||
uint32_t now = millis();
|
||||
|
||||
portENTER_CRITICAL(&_fan_mux);
|
||||
if (_stopped) {
|
||||
portEXIT_CRITICAL(&_fan_mux);
|
||||
return;
|
||||
}
|
||||
|
||||
_temp_c = t;
|
||||
bool tx_cooling = isTxCoolingLocked(now);
|
||||
|
||||
bool enabled;
|
||||
if (_mode == FAN_ON) {
|
||||
enabled = true;
|
||||
} else if (_mode == FAN_OFF) {
|
||||
enabled = false;
|
||||
} else if (ntcImplausible(t)) {
|
||||
enabled = true; // fail-safe: treat bad NTC as hot
|
||||
} else {
|
||||
// TX cooldown must not latch _thermal_on, or a TX at 30C keeps the fan
|
||||
// running until the temperature dips under lo.
|
||||
if (t >= (float)_hi_c) _thermal_on = true;
|
||||
else if (t < (float)_lo_c) _thermal_on = false;
|
||||
enabled = _thermal_on || tx_cooling;
|
||||
}
|
||||
|
||||
setFanOutputLocked(enabled);
|
||||
portEXIT_CRITICAL(&_fan_mux);
|
||||
}
|
||||
|
||||
bool TBeam1WBoard::persistKey(const char* key, const char* value) {
|
||||
return _prefs && _prefs->setByKey(key, value);
|
||||
}
|
||||
|
||||
bool TBeam1WBoard::parseIntArg(const char* text, int& value) {
|
||||
if (!text || !*text) return false;
|
||||
errno = 0;
|
||||
char* end = nullptr;
|
||||
long parsed = strtol(text, &end, 10);
|
||||
if (errno == ERANGE || end == text || *end != '\0' || parsed < INT_MIN || parsed > INT_MAX) {
|
||||
return false;
|
||||
}
|
||||
value = (int)parsed;
|
||||
return true;
|
||||
}
|
||||
|
||||
void TBeam1WBoard::loadFanPrefs() {
|
||||
if (!_prefs) return;
|
||||
|
||||
FanMode mode = FAN_AUTO;
|
||||
char buf[12];
|
||||
buf[0] = 0;
|
||||
if (_prefs->getByKey("fan", buf, 11)) {
|
||||
if (strcmp(buf, "off") == 0) mode = FAN_OFF;
|
||||
else if (strcmp(buf, "on") == 0) mode = FAN_ON;
|
||||
}
|
||||
|
||||
int lo = FAN_DEFAULT_LO_C;
|
||||
int hi = FAN_DEFAULT_HI_C;
|
||||
buf[0] = 0;
|
||||
if (_prefs->getByKey("fan_lo", buf, 11)) lo = atoi(buf);
|
||||
buf[0] = 0;
|
||||
if (_prefs->getByKey("fan_hi", buf, 11)) hi = atoi(buf);
|
||||
|
||||
portENTER_CRITICAL(&_fan_mux);
|
||||
_mode = mode;
|
||||
if (lo >= 0 && hi <= 120 && lo < hi) {
|
||||
_lo_c = lo;
|
||||
_hi_c = hi;
|
||||
}
|
||||
portEXIT_CRITICAL(&_fan_mux);
|
||||
}
|
||||
|
||||
void TBeam1WBoard::attachDynamicPrefs(KeyValueStore* prefs) {
|
||||
_prefs = prefs;
|
||||
loadFanPrefs();
|
||||
updateFan();
|
||||
}
|
||||
|
||||
const char* TBeam1WBoard::modeNameLocked() const {
|
||||
if (_mode == FAN_AUTO) return "auto";
|
||||
if (_mode == FAN_OFF) return "off";
|
||||
return "on";
|
||||
}
|
||||
|
||||
bool TBeam1WBoard::handleCommand(const char* command, uint32_t sender_timestamp, char* reply) {
|
||||
(void)sender_timestamp;
|
||||
|
||||
if (strcmp(command, "get fan") == 0) {
|
||||
portENTER_CRITICAL(&_fan_mux);
|
||||
int cd = cooldownSecsLocked();
|
||||
float temp_c = _temp_c;
|
||||
bool enabled = _fan_on;
|
||||
const char* mode = modeNameLocked();
|
||||
portEXIT_CRITICAL(&_fan_mux);
|
||||
if (ntcImplausible(temp_c)) {
|
||||
sprintf(reply, "> %s n/a fan=%s cd=%ds", mode, enabled ? "on" : "off", cd);
|
||||
} else {
|
||||
sprintf(reply, "> %s %.1fC fan=%s cd=%ds",
|
||||
mode, (double)temp_c, enabled ? "on" : "off", cd);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if (strncmp(command, "set fan.lo ", 11) == 0) {
|
||||
int lo;
|
||||
portENTER_CRITICAL(&_fan_mux);
|
||||
int hi_limit = _hi_c;
|
||||
portEXIT_CRITICAL(&_fan_mux);
|
||||
if (!parseIntArg(&command[11], lo) || lo < 0 || lo >= hi_limit || lo > 100) {
|
||||
strcpy(reply, "Error: fan.lo must be 0..100 and < fan.hi");
|
||||
} else if (!persistKey("fan_lo", &command[11])) {
|
||||
strcpy(reply, "Error: failed to save fan.lo");
|
||||
} else {
|
||||
portENTER_CRITICAL(&_fan_mux);
|
||||
_lo_c = lo;
|
||||
portEXIT_CRITICAL(&_fan_mux);
|
||||
sprintf(reply, "OK - fan.lo %d", lo);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if (strncmp(command, "set fan.hi ", 11) == 0) {
|
||||
int hi;
|
||||
portENTER_CRITICAL(&_fan_mux);
|
||||
int lo_limit = _lo_c;
|
||||
portEXIT_CRITICAL(&_fan_mux);
|
||||
if (!parseIntArg(&command[11], hi) || hi <= lo_limit || hi > 120) {
|
||||
strcpy(reply, "Error: fan.hi must be > fan.lo and <= 120");
|
||||
} else if (!persistKey("fan_hi", &command[11])) {
|
||||
strcpy(reply, "Error: failed to save fan.hi");
|
||||
} else {
|
||||
portENTER_CRITICAL(&_fan_mux);
|
||||
_hi_c = hi;
|
||||
portEXIT_CRITICAL(&_fan_mux);
|
||||
sprintf(reply, "OK - fan.hi %d", hi);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if (strncmp(command, "set fan ", 8) == 0) {
|
||||
const char* arg = &command[8];
|
||||
if (strcmp(arg, "on") == 0) {
|
||||
if (!persistKey("fan", "on")) {
|
||||
strcpy(reply, "Error: failed to save fan mode");
|
||||
} else {
|
||||
portENTER_CRITICAL(&_fan_mux);
|
||||
_mode = FAN_ON;
|
||||
if (!_stopped) setFanOutputLocked(true);
|
||||
portEXIT_CRITICAL(&_fan_mux);
|
||||
strcpy(reply, "OK - fan on");
|
||||
}
|
||||
} else if (strcmp(arg, "off") == 0) {
|
||||
if (!persistKey("fan", "off")) {
|
||||
strcpy(reply, "Error: failed to save fan mode");
|
||||
} else {
|
||||
portENTER_CRITICAL(&_fan_mux);
|
||||
_mode = FAN_OFF;
|
||||
setFanOutputLocked(false);
|
||||
portEXIT_CRITICAL(&_fan_mux);
|
||||
strcpy(reply, "OK - fan off");
|
||||
}
|
||||
} else if (strcmp(arg, "auto") == 0) {
|
||||
if (!persistKey("fan", "auto")) {
|
||||
strcpy(reply, "Error: failed to save fan mode");
|
||||
} else {
|
||||
portENTER_CRITICAL(&_fan_mux);
|
||||
_mode = FAN_AUTO;
|
||||
portEXIT_CRITICAL(&_fan_mux);
|
||||
updateFan();
|
||||
strcpy(reply, "OK - fan auto");
|
||||
}
|
||||
} else {
|
||||
strcpy(reply, "Error: fan must be on, off, or auto");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <freertos/FreeRTOS.h>
|
||||
#include <freertos/task.h>
|
||||
#include <helpers/ESP32Board.h>
|
||||
#include "variant.h"
|
||||
|
||||
@@ -28,18 +30,48 @@
|
||||
// - Battery must support 2A+ discharge for high-power TX
|
||||
|
||||
class TBeam1WBoard : public ESP32Board {
|
||||
public:
|
||||
enum FanMode { FAN_ON, FAN_OFF, FAN_AUTO };
|
||||
|
||||
private:
|
||||
bool radio_powered = false;
|
||||
bool _stopped = false;
|
||||
KeyValueStore* _prefs = nullptr;
|
||||
FanMode _mode = FAN_AUTO;
|
||||
int _lo_c = FAN_DEFAULT_LO_C;
|
||||
int _hi_c = FAN_DEFAULT_HI_C;
|
||||
bool _thermal_on = false; // onoff hysteresis; TX boost must not latch this
|
||||
bool _fan_on = true;
|
||||
float _temp_c = NAN;
|
||||
bool _tx_active = false;
|
||||
bool _tx_cooldown_active = false;
|
||||
uint32_t _tx_until_ms = 0;
|
||||
TaskHandle_t _fan_task = nullptr;
|
||||
mutable portMUX_TYPE _fan_mux = portMUX_INITIALIZER_UNLOCKED;
|
||||
|
||||
void startFanTask();
|
||||
void updateFan();
|
||||
void setFanOutputLocked(bool enabled);
|
||||
float readNtcTempC();
|
||||
int cooldownSecsLocked();
|
||||
bool isTxCoolingLocked(uint32_t now);
|
||||
bool ntcImplausible(float temp_c) const;
|
||||
bool persistKey(const char* key, const char* value);
|
||||
static bool parseIntArg(const char* text, int& value);
|
||||
void loadFanPrefs();
|
||||
const char* modeNameLocked() const;
|
||||
static void fanTaskThunk(void* arg);
|
||||
|
||||
public:
|
||||
void begin();
|
||||
void attachDynamicPrefs(KeyValueStore* prefs);
|
||||
bool handleCommand(const char* command, uint32_t sender_timestamp, char* reply) override;
|
||||
void onBeforeTransmit() override;
|
||||
void onAfterTransmit() override;
|
||||
uint16_t getBattMilliVolts() override;
|
||||
const char* getManufacturerName() const override;
|
||||
void powerOff() override;
|
||||
|
||||
// Fan control methods
|
||||
void setFanEnabled(bool enabled);
|
||||
bool isFanEnabled() const;
|
||||
};
|
||||
|
||||
@@ -153,6 +153,7 @@ extends = LilyGo_TBeam_1W
|
||||
build_flags =
|
||||
${LilyGo_TBeam_1W.build_flags}
|
||||
-I examples/companion_radio/ui-new
|
||||
-D ENABLE_WIFI_INTERFACE
|
||||
-D MAX_CONTACTS=350
|
||||
-D MAX_GROUP_CHANNELS=40
|
||||
-D OFFLINE_QUEUE_SIZE=256
|
||||
@@ -165,6 +166,7 @@ build_flags =
|
||||
; -D MESH_DEBUG=1
|
||||
build_src_filter = ${LilyGo_TBeam_1W.build_src_filter}
|
||||
+<helpers/esp32/*.cpp>
|
||||
+<helpers/wifi/*.cpp>
|
||||
+<../examples/companion_radio/*.cpp>
|
||||
+<../examples/companion_radio/ui-new/*.cpp>
|
||||
lib_deps =
|
||||
|
||||
@@ -77,11 +77,21 @@
|
||||
#define BATTERY_SENSE_SAMPLES 30
|
||||
#define ADC_MULTIPLIER 3.0
|
||||
|
||||
// NTC temperature sensor
|
||||
// NTC thermistor (Murata NCP18XH103F03RB, 10k, B25/50=3380K)
|
||||
// Divider: 3.3V -> NTC -> GPIO14 -> 10k pull-down -> GND (Vadc rises with temp)
|
||||
#define NTC_PIN 14
|
||||
#define NTC_B 3380.0f
|
||||
#define NTC_R25 10000.0f
|
||||
#define NTC_R_FIXED 10000.0f
|
||||
#define NTC_VCC_MV 3300.0f
|
||||
|
||||
// Fan control
|
||||
// Fan control (GPIO41). NTC is PA-adjacent PCB temp, not die temp, so trip
|
||||
// well below the SX1262/ESP32 85C operating limit. Hardware testing confirmed
|
||||
// that this fan/MOSFET path is on/off; PWM below 100% does not spin the fan.
|
||||
#define FAN_CTRL_PIN 41
|
||||
#define FAN_TX_COOLDOWN_MS 15000
|
||||
#define FAN_DEFAULT_LO_C 30 // off below typical indoor idle (~86F)
|
||||
#define FAN_DEFAULT_HI_C 36 // on at ~97F PCB; still far below 85C chip ratings
|
||||
|
||||
// PA Ramp Time - T-Beam 1W requires >800us stabilization (default is 200us)
|
||||
// Value 0x05 = RADIOLIB_SX126X_PA_RAMP_800U
|
||||
|
||||
@@ -148,6 +148,7 @@ extends = T_Beam_S3_Supreme_SX1262
|
||||
build_flags =
|
||||
${T_Beam_S3_Supreme_SX1262.build_flags}
|
||||
-I examples/companion_radio/ui-new
|
||||
-D ENABLE_WIFI_INTERFACE
|
||||
-D MAX_CONTACTS=350
|
||||
-D MAX_GROUP_CHANNELS=40
|
||||
-D OFFLINE_QUEUE_SIZE=256
|
||||
@@ -160,6 +161,7 @@ build_flags =
|
||||
; -D CORE_DEBUG_LEVEL=4
|
||||
build_src_filter = ${T_Beam_S3_Supreme_SX1262.build_src_filter}
|
||||
+<helpers/esp32/*.cpp>
|
||||
+<helpers/wifi/*.cpp>
|
||||
+<helpers/ui/MomentaryButton.cpp>
|
||||
+<../examples/companion_radio/*.cpp>
|
||||
+<../examples/companion_radio/ui-new/*.cpp>
|
||||
|
||||
@@ -101,6 +101,32 @@ lib_deps =
|
||||
${LilyGo_T-Echo-Lite.lib_deps}
|
||||
densaugeo/base64 @ ~1.4.0
|
||||
|
||||
[env:LilyGo_T-Echo-Lite_kiss_modem]
|
||||
extends = LilyGo_T-Echo-Lite
|
||||
build_src_filter = ${LilyGo_T-Echo-Lite.build_src_filter}
|
||||
+<../examples/kiss_modem/>
|
||||
[env:LilyGo_T-Echo-Lite_companion_radio_usb]
|
||||
extends = LilyGo_T-Echo-Lite
|
||||
board_build.ldscript = boards/nrf52840_s140_v6_extrafs.ld
|
||||
board_upload.maximum_size = 712704
|
||||
build_flags =
|
||||
${LilyGo_T-Echo-Lite.build_flags}
|
||||
-I src/helpers/ui
|
||||
-I examples/companion_radio/ui-new
|
||||
-D MAX_CONTACTS=350
|
||||
-D MAX_GROUP_CHANNELS=40
|
||||
-D OFFLINE_QUEUE_SIZE=256
|
||||
-D UI_RECENT_LIST_SIZE=9
|
||||
-D UI_SENSORS_PAGE=1
|
||||
-D AUTO_SHUTDOWN_MILLIVOLTS=3300
|
||||
; -D QSPIFLASH=1
|
||||
build_src_filter = ${LilyGo_T-Echo-Lite.build_src_filter}
|
||||
+<../examples/companion_radio/*.cpp>
|
||||
+<../examples/companion_radio/ui-new/*.cpp>
|
||||
lib_deps =
|
||||
${LilyGo_T-Echo-Lite.lib_deps}
|
||||
densaugeo/base64 @ ~1.4.0
|
||||
|
||||
[env:LilyGo_T-Echo-Lite_non_shell_companion_radio_ble]
|
||||
extends = LilyGo_T-Echo-Lite
|
||||
upload_protocol = nrfutil
|
||||
@@ -190,8 +216,3 @@ build_src_filter = ${nrf52_base.build_src_filter}
|
||||
lib_deps =
|
||||
${LilyGo_T-Echo-Lite.lib_deps}
|
||||
densaugeo/base64 @ ~1.4.0
|
||||
|
||||
[env:LilyGo_T-Echo-Lite_kiss_modem]
|
||||
extends = LilyGo_T-Echo-Lite
|
||||
build_src_filter = ${LilyGo_T-Echo-Lite.build_src_filter}
|
||||
+<../examples/kiss_modem/>
|
||||
|
||||
@@ -70,9 +70,6 @@
|
||||
#define PIN_QSPI_IO2 _PINNUM(1, 9)
|
||||
#define PIN_QSPI_IO3 _PINNUM(0, 26)
|
||||
|
||||
#define EXTERNAL_FLASH_DEVICES ZD25WQ32CEIGR
|
||||
#define EXTERNAL_FLASH_USE_QSPI
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Builtin LEDs
|
||||
|
||||
@@ -95,9 +92,6 @@
|
||||
#define PIN_BUTTON2 _PINNUM(0, 18)
|
||||
#define BUTTON_PIN2 PIN_BUTTON2
|
||||
|
||||
#define EXTERNAL_FLASH_DEVICES MX25R1635F
|
||||
#define EXTERNAL_FLASH_USE_QSPI
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Lora
|
||||
|
||||
@@ -154,10 +148,8 @@ extern const int SCK;
|
||||
// GPS — per LilyGo t_echo_lite_config.h
|
||||
// PIN_GPS_TX/RX named from GPS module's perspective
|
||||
|
||||
//#define PIN_GPS_TX _PINNUM(0, 29) // GPS UART TX → MCU RX
|
||||
//#define PIN_GPS_RX _PINNUM(1, 10) // GPS UART RX ← MCU TX
|
||||
#define PIN_GPS_RX _PINNUM(0, 29) // GPS UART TX → MCU RX
|
||||
#define PIN_GPS_TX _PINNUM(1, 10) // GPS UART RX ← MCU TX
|
||||
#define GPS_EN _PINNUM(1, 11) // GPS RT9080 power enable
|
||||
#define PIN_GPS_STANDBY _PINNUM(1, 13) // GPS wake-up
|
||||
#define PIN_GPS_PPS _PINNUM(1, 15) // GPS 1PPS
|
||||
#define PIN_GPS_PPS _PINNUM(1, 15) // GPS 1PPS
|
||||
|
||||
@@ -132,6 +132,7 @@ extends = LilyGo_TLora_V2_1_1_6
|
||||
build_flags =
|
||||
${LilyGo_TLora_V2_1_1_6.build_flags}
|
||||
-I examples/companion_radio/ui-new
|
||||
-D ENABLE_WIFI_INTERFACE
|
||||
-D MAX_CONTACTS=160
|
||||
-D MAX_GROUP_CHANNELS=8
|
||||
-D WIFI_SSID='"ssid"'
|
||||
@@ -140,6 +141,7 @@ build_flags =
|
||||
-D OFFLINE_QUEUE_SIZE=128
|
||||
build_src_filter = ${LilyGo_TLora_V2_1_1_6.build_src_filter}
|
||||
+<helpers/esp32/*.cpp>
|
||||
+<helpers/wifi/*.cpp>
|
||||
+<helpers/ui/MomentaryButton.cpp>
|
||||
+<../examples/companion_radio/*.cpp>
|
||||
+<../examples/companion_radio/ui-new/*.cpp>
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
#pragma once
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
// LoRa radio module pins for Meshadventurer
|
||||
#define P_LORA_DIO_1 33
|
||||
#define P_LORA_NSS 18
|
||||
#define P_LORA_RESET 23
|
||||
#define P_LORA_BUSY 32
|
||||
#define P_LORA_SCLK 5
|
||||
#define P_LORA_MISO 19
|
||||
#define P_LORA_MOSI 27
|
||||
|
||||
#define PIN_VBAT_READ 35
|
||||
|
||||
#include "helpers/ESP32Board.h"
|
||||
|
||||
class MeshadventurerBoard : public ESP32Board {
|
||||
|
||||
public:
|
||||
void begin() {
|
||||
ESP32Board::begin();
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t getBattMilliVolts() override {
|
||||
analogReadResolution(12);
|
||||
|
||||
uint32_t raw = 0;
|
||||
for (int i = 0; i < 4; i++) {
|
||||
raw += analogReadMilliVolts(PIN_VBAT_READ);
|
||||
}
|
||||
raw = raw / 4;
|
||||
|
||||
return (2 * raw);
|
||||
}
|
||||
|
||||
const char* getManufacturerName() const override {
|
||||
return "Meshadventurer";
|
||||
}
|
||||
};
|
||||
@@ -3,7 +3,7 @@
|
||||
#define RADIOLIB_STATIC_ONLY 1
|
||||
#include <RadioLib.h>
|
||||
#include <helpers/radiolib/RadioLibWrappers.h>
|
||||
#include <helpers/MeshadventurerBoard.h>
|
||||
#include <MeshadventurerBoard.h>
|
||||
#include <helpers/radiolib/CustomSX1262Wrapper.h>
|
||||
#include <helpers/radiolib/CustomSX1268Wrapper.h>
|
||||
#include <helpers/AutoDiscoverRTCClock.h>
|
||||
@@ -44,4 +44,3 @@ extern MASensorManager sensors;
|
||||
|
||||
bool radio_init();
|
||||
mesh::LocalIdentity radio_new_identity();
|
||||
|
||||
|
||||
@@ -27,8 +27,8 @@ build_flags =
|
||||
-D PIN_USER_BTN=0
|
||||
-D PIN_VEXT_EN=45
|
||||
-D PIN_VEXT_EN_ACTIVE=HIGH
|
||||
-D LORA_TX_POWER=4
|
||||
-D MAX_LORA_TX_POWER=4 ; GC1109 datasheet says max input at TX port is +5dbm, confirmed full saturation seems to occur at around 3-4dbm
|
||||
-D LORA_TX_POWER=5 ; default to 5, which gives ~22dbm
|
||||
-D MAX_LORA_TX_POWER=13 ; tested with tinySA, 13 gives ~28dbm
|
||||
-D PIN_GPS_RX=38
|
||||
-D PIN_GPS_TX=39
|
||||
-D PIN_GPS_RESET=42
|
||||
@@ -171,6 +171,7 @@ extends = meshnology_w12
|
||||
build_flags =
|
||||
${meshnology_w12.build_flags}
|
||||
-I examples/companion_radio/ui-new
|
||||
-D ENABLE_WIFI_INTERFACE
|
||||
-D MAX_CONTACTS=350
|
||||
-D MAX_GROUP_CHANNELS=40
|
||||
-D OFFLINE_QUEUE_SIZE=256
|
||||
@@ -184,6 +185,7 @@ build_src_filter = ${meshnology_w12.build_src_filter}
|
||||
+<helpers/ui/SSD1306Display.cpp>
|
||||
+<helpers/ui/MomentaryButton.cpp>
|
||||
+<helpers/esp32/*.cpp>
|
||||
+<helpers/wifi/*.cpp>
|
||||
+<../examples/companion_radio/*.cpp>
|
||||
+<../examples/companion_radio/ui-new/*.cpp>
|
||||
lib_deps =
|
||||
|
||||
@@ -9,7 +9,7 @@ protected:
|
||||
uint8_t btn_prev_state;
|
||||
|
||||
public:
|
||||
MeshtinyBoard() : NRF52Board("Meshtiny OTA") {}
|
||||
MeshtinyBoard() : NRF52Board("Meshtiny_OTA") {}
|
||||
void begin();
|
||||
|
||||
#if defined(P_LORA_TX_LED)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include <Arduino.h>
|
||||
#include "target.h"
|
||||
#include <helpers/sensors/MicroNMEALocationProvider.h>
|
||||
#include <helpers/sensors/AirohaSleep.h>
|
||||
|
||||
MeshTrackerX1Board board;
|
||||
|
||||
@@ -27,46 +28,27 @@ mesh::LocalIdentity radio_new_identity() {
|
||||
|
||||
void MeshTrackerX1SensorManager::start_gps() {
|
||||
gps_active = true;
|
||||
// this init sequence comes from seeed examples and deals with all gps pins
|
||||
pinMode(GPS_EN, OUTPUT);
|
||||
digitalWrite(GPS_EN, HIGH);
|
||||
delay(10);
|
||||
pinMode(GPS_VRTC_EN, OUTPUT);
|
||||
digitalWrite(GPS_VRTC_EN, HIGH);
|
||||
delay(10);
|
||||
|
||||
pinMode(GPS_RESET, OUTPUT);
|
||||
digitalWrite(GPS_RESET, HIGH);
|
||||
delay(10);
|
||||
digitalWrite(GPS_RESET, LOW);
|
||||
|
||||
pinMode(GPS_SLEEP_INT, OUTPUT);
|
||||
digitalWrite(GPS_SLEEP_INT, HIGH);
|
||||
pinMode(GPS_RTC_INT, OUTPUT);
|
||||
digitalWrite(GPS_RTC_INT, LOW);
|
||||
}
|
||||
|
||||
void MeshTrackerX1SensorManager::sleep_gps() {
|
||||
gps_active = false;
|
||||
digitalWrite(GPS_VRTC_EN, HIGH); // keep RTC alive for faster fix on wake
|
||||
digitalWrite(GPS_EN, LOW);
|
||||
digitalWrite(GPS_RESET, LOW);
|
||||
digitalWrite(GPS_SLEEP_INT, HIGH);
|
||||
digitalWrite(GPS_RTC_INT, HIGH);
|
||||
delay(5);
|
||||
digitalWrite(GPS_RTC_INT, LOW);
|
||||
}
|
||||
|
||||
void MeshTrackerX1SensorManager::stop_gps() {
|
||||
gps_active = false;
|
||||
digitalWrite(GPS_VRTC_EN, LOW);
|
||||
digitalWrite(GPS_VRTC_EN, HIGH); // keep GPS RTC alive for faster fix on wake
|
||||
digitalWrite(GPS_RTC_INT, LOW); // make sure this is LOW so we can pulse it to wake
|
||||
airohaEnterSleep(_nmea);
|
||||
digitalWrite(GPS_EN, LOW);
|
||||
digitalWrite(GPS_RESET, LOW);
|
||||
digitalWrite(GPS_SLEEP_INT, HIGH);
|
||||
digitalWrite(GPS_RTC_INT, LOW);
|
||||
}
|
||||
|
||||
bool MeshTrackerX1SensorManager::begin() {
|
||||
// init GPS
|
||||
Serial1.begin(GPS_BAUD_RATE);
|
||||
digitalWrite(GPS_RESET, HIGH);
|
||||
delay(10);
|
||||
digitalWrite(GPS_RESET, LOW);
|
||||
|
||||
// init SPA06-003 barometer
|
||||
baro_ok = spa06.begin(SPA06_003_DEFAULT_ADDR, &Wire) || spa06.begin(0x76, &Wire);
|
||||
@@ -122,7 +104,7 @@ const char* MeshTrackerX1SensorManager::getSettingValue(int i) const {
|
||||
bool MeshTrackerX1SensorManager::setSettingValue(const char* name, const char* value) {
|
||||
if (strcmp(name, "gps") == 0) {
|
||||
if (strcmp(value, "0") == 0) {
|
||||
sleep_gps(); // sleep for faster fix !
|
||||
stop_gps();
|
||||
} else {
|
||||
start_gps();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
#include <Arduino.h>
|
||||
#include <Wire.h>
|
||||
|
||||
#include "MuziBaseBoard.h"
|
||||
|
||||
#ifdef NRF52_POWER_MANAGEMENT
|
||||
const PowerMgtConfig power_config = {
|
||||
.lpcomp_ain_channel = PWRMGT_LPCOMP_AIN,
|
||||
.lpcomp_refsel = PWRMGT_LPCOMP_REFSEL,
|
||||
.voltage_bootlock = PWRMGT_VOLTAGE_BOOTLOCK
|
||||
};
|
||||
|
||||
void MuziBaseBoard::initiateShutdown(uint8_t reason) {
|
||||
// Disable LoRa module power before shutdown
|
||||
if (reason == SHUTDOWN_REASON_LOW_VOLTAGE ||
|
||||
reason == SHUTDOWN_REASON_BOOT_PROTECT) {
|
||||
configureVoltageWake(power_config.lpcomp_ain_channel, power_config.lpcomp_refsel);
|
||||
}
|
||||
|
||||
enterSystemOff(reason);
|
||||
}
|
||||
#endif // NRF52_POWER_MANAGEMENT
|
||||
|
||||
void MuziBaseBoard::begin() {
|
||||
NRF52BoardDCDC::begin();
|
||||
pinMode(PIN_VBAT_READ, INPUT);
|
||||
pinMode(PIN_BATTERY_CHARGING, INPUT);
|
||||
pinMode(PIN_CHARGER_FAULT, INPUT);
|
||||
pinMode(LED_PIN, OUTPUT);
|
||||
digitalWrite(LED_PIN, LOW);
|
||||
// output latches default to HIGH, so pull these low right after enabling
|
||||
pinMode(BUZZER_PIN, OUTPUT);
|
||||
digitalWrite(BUZZER_PIN, LOW);
|
||||
// gps power is driven by the sensor manager (mode switch). off to start.
|
||||
pinMode(PIN_GPS_EN, OUTPUT);
|
||||
digitalWrite(PIN_GPS_EN, LOW);
|
||||
// 12V rail is only needed for the superIO display
|
||||
pinMode(SCREEN_12V_ENABLE, OUTPUT);
|
||||
#ifdef MUZI_BASE_SUPERIO
|
||||
digitalWrite(SCREEN_12V_ENABLE, HIGH); // Enable 12V power for SH1107 display
|
||||
delay(250);
|
||||
#else
|
||||
digitalWrite(SCREEN_12V_ENABLE, LOW);
|
||||
#endif
|
||||
Wire.begin();
|
||||
// delay(1000); // wait for display to initialize. otherwise it doesn't come up on boot.
|
||||
|
||||
#ifdef PIN_USER_BTN
|
||||
pinMode(PIN_USER_BTN, INPUT_PULLUP);
|
||||
#endif
|
||||
pinMode(PIN_BUTTON1, INPUT_PULLUP);
|
||||
pinMode(PIN_BUTTON2, INPUT_PULLUP);
|
||||
pinMode(PIN_BUTTON3, INPUT_PULLUP);
|
||||
pinMode(PIN_BUTTON4, INPUT_PULLUP);
|
||||
pinMode(PIN_BUTTON5, INPUT_PULLUP);
|
||||
pinMode(PIN_BUTTON6, INPUT_PULLUP);
|
||||
|
||||
// #if defined(PIN_BOARD_SDA) && defined(PIN_BOARD_SCL)
|
||||
// Wire.setPins(PIN_BOARD_SDA, PIN_BOARD_SCL);
|
||||
// #endif
|
||||
#ifdef NRF52_POWER_MANAGEMENT
|
||||
checkBootVoltage(&power_config);
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
#pragma once
|
||||
|
||||
#include <MeshCore.h>
|
||||
#include <Arduino.h>
|
||||
#include <helpers/NRF52Board.h>
|
||||
|
||||
// The Muzi Base PCB ships in two radio flavors. Keep the user-facing identity
|
||||
// (OTA/DFU name and reported manufacturer) distinct per radio even though the
|
||||
// board logic is shared.
|
||||
#if defined(USE_SX1262)
|
||||
#define MUZI_BASE_OTA_NAME "MUZI_BASE_UNO_OTA"
|
||||
#define MUZI_BASE_MFR_NAME "Muzi Base Uno"
|
||||
#else
|
||||
#define MUZI_BASE_OTA_NAME "MUZI_BASE_DUO_OTA"
|
||||
#define MUZI_BASE_MFR_NAME "Muzi Base Duo"
|
||||
#endif
|
||||
|
||||
class MuziBaseBoard : public NRF52BoardDCDC {
|
||||
protected:
|
||||
#ifdef NRF52_POWER_MANAGEMENT
|
||||
void initiateShutdown(uint8_t reason) override;
|
||||
#endif
|
||||
|
||||
public:
|
||||
MuziBaseBoard() : NRF52Board(MUZI_BASE_OTA_NAME) {}
|
||||
void begin();
|
||||
|
||||
#define BATTERY_SAMPLES 8
|
||||
|
||||
uint16_t getBattMilliVolts() override {
|
||||
analogReadResolution(12);
|
||||
analogReference(AR_INTERNAL_3_0);
|
||||
delay(1);
|
||||
|
||||
uint32_t raw = 0;
|
||||
for (int i = 0; i < BATTERY_SAMPLES; i++) {
|
||||
raw += analogRead(PIN_VBAT_READ);
|
||||
}
|
||||
raw = raw / BATTERY_SAMPLES;
|
||||
|
||||
// ADC_MULTIPLIER is the voltage divider ratio
|
||||
return (raw * ADC_MULTIPLIER * AREF_VOLTAGE) / 4.096;
|
||||
}
|
||||
|
||||
const char* getManufacturerName() const override {
|
||||
return MUZI_BASE_MFR_NAME;
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,322 @@
|
||||
; ============================================================================
|
||||
; Muzi Base (MuziWorks)
|
||||
;
|
||||
; One nRF52840 board, shipped in two radio flavors. The radio is selected per
|
||||
; environment; all board logic lives in variants/muzi_base and is shared:
|
||||
; muzi_base_duo_* -> LR1121 (USE_LR1121)
|
||||
; muzi_base_uno_* -> SX1262 (USE_SX1262)
|
||||
; ============================================================================
|
||||
|
||||
[muzi_base_common]
|
||||
extends = nrf52_base
|
||||
board = muzi_base
|
||||
board_build.ldscript = boards/nrf52840_s140_v6.ld
|
||||
build_flags = ${nrf52_base.build_flags}
|
||||
-I src/helpers/nrf52
|
||||
-I lib/nrf52/s140_nrf52_6.1.1_API/include
|
||||
-I lib/nrf52/s140_nrf52_6.1.1_API/include/nrf52
|
||||
-I variants/muzi_base
|
||||
-I src/helpers/ui
|
||||
-D MUZI_BASE
|
||||
-D NRF52_POWER_MANAGEMENT
|
||||
-D PIN_USER_BTN=PIN_BUTTON1
|
||||
-D USER_BTN_PRESSED=LOW
|
||||
-D PIN_STATUS_LED=35
|
||||
-D LORA_TX_POWER=22
|
||||
-D P_LORA_BUSY=LORA_BUSY
|
||||
-D P_LORA_SCLK=LORA_SCLK
|
||||
-D P_LORA_NSS=LORA_NSS
|
||||
-D P_LORA_DIO_1=LORA_DIO_1
|
||||
-D P_LORA_MISO=LORA_MISO
|
||||
-D P_LORA_MOSI=LORA_MOSI
|
||||
-D P_LORA_RESET=LORA_RESET
|
||||
-D QSPIFLASH=1
|
||||
build_src_filter = ${nrf52_base.build_src_filter}
|
||||
+<helpers/*.cpp>
|
||||
+<helpers/sensors>
|
||||
+<../variants/muzi_base>
|
||||
debug_tool = jlink
|
||||
upload_protocol = nrfutil
|
||||
lib_deps =
|
||||
${nrf52_base.lib_deps}
|
||||
${sensor_base.lib_deps}
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; Radio selection (Duo = LR1121, Uno = SX1262). The matching radio pins / TCXO
|
||||
; / RF-switch defines are picked up in variant.h via USE_LR1121 / USE_SX1262.
|
||||
; ---------------------------------------------------------------------------
|
||||
[muzi_base_duo]
|
||||
extends = muzi_base_common
|
||||
build_flags = ${muzi_base_common.build_flags}
|
||||
-D USE_LR1121
|
||||
-D RADIO_CLASS=CustomLR1121
|
||||
-D WRAPPER_CLASS=CustomLR1121Wrapper
|
||||
-D RF_SWITCH_TABLE
|
||||
-D RX_BOOSTED_GAIN=true
|
||||
-D LR11X0_DIO_AS_RF_SWITCH=true
|
||||
-D LR11X0_DIO3_TCXO_VOLTAGE=3.0
|
||||
|
||||
[muzi_base_uno]
|
||||
extends = muzi_base_common
|
||||
build_flags = ${muzi_base_common.build_flags}
|
||||
-D USE_SX1262
|
||||
-D RADIO_CLASS=CustomSX1262
|
||||
-D WRAPPER_CLASS=CustomSX1262Wrapper
|
||||
-D SX126X_RX_BOOSTED_GAIN=1
|
||||
-D SX126X_CURRENT_LIMIT=140
|
||||
-D SX126X_DIO2_AS_RF_SWITCH=1
|
||||
-D SX126X_DIO3_TCXO_VOLTAGE=3.3
|
||||
|
||||
; ===========================================================================
|
||||
; Duo (LR1121) environments
|
||||
; ===========================================================================
|
||||
[env:muzi_base_duo_repeater]
|
||||
extends = muzi_base_duo
|
||||
build_flags = ${muzi_base_duo.build_flags}
|
||||
-I examples/companion_radio/ui-new
|
||||
-D ADVERT_NAME='"Muzi Base 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 = ${muzi_base_duo.build_src_filter}
|
||||
+<../examples/simple_repeater>
|
||||
lib_deps = ${muzi_base_duo.lib_deps}
|
||||
|
||||
[env:muzi_base_duo_room_server]
|
||||
extends = muzi_base_duo
|
||||
build_flags = ${muzi_base_duo.build_flags}
|
||||
-I examples/companion_radio/ui-new
|
||||
-D ADVERT_NAME='"Muzi Base 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
|
||||
build_src_filter = ${muzi_base_duo.build_src_filter}
|
||||
+<../examples/simple_room_server>
|
||||
lib_deps = ${muzi_base_duo.lib_deps}
|
||||
|
||||
[env:muzi_base_duo_companion_radio_usb]
|
||||
extends = muzi_base_duo
|
||||
board_build.ldscript = boards/nrf52840_s140_v6_extrafs.ld
|
||||
board_upload.maximum_size = 708608
|
||||
build_flags = ${muzi_base_duo.build_flags}
|
||||
-I examples/companion_radio/ui-new
|
||||
-D MAX_CONTACTS=350
|
||||
-D MAX_GROUP_CHANNELS=40
|
||||
; -D MESH_PACKET_LOGGING=1
|
||||
; -D MESH_DEBUG=1
|
||||
-D OFFLINE_QUEUE_SIZE=256
|
||||
-D DISPLAY_CLASS=NullDisplayDriver
|
||||
build_src_filter = ${muzi_base_duo.build_src_filter}
|
||||
+<helpers/ui/NullDisplayDriver.cpp>
|
||||
+<../examples/companion_radio/*.cpp>
|
||||
+<../examples/companion_radio/ui-new/*.cpp>
|
||||
lib_deps = ${muzi_base_duo.lib_deps}
|
||||
densaugeo/base64 @ ~1.4.0
|
||||
|
||||
[env:muzi_base_duo_companion_radio_ble]
|
||||
extends = muzi_base_duo
|
||||
board_build.ldscript = boards/nrf52840_s140_v6_extrafs.ld
|
||||
board_upload.maximum_size = 708608
|
||||
build_flags = ${muzi_base_duo.build_flags}
|
||||
-I examples/companion_radio/ui-new
|
||||
-D MAX_CONTACTS=350
|
||||
-D MAX_GROUP_CHANNELS=40
|
||||
-D BLE_PIN_CODE=123456
|
||||
-D QSPIFLASH=1
|
||||
; -D BLE_DEBUG_LOGGING=1
|
||||
; -D MESH_PACKET_LOGGING=1
|
||||
; -D MESH_DEBUG=1
|
||||
-D OFFLINE_QUEUE_SIZE=256
|
||||
-D DISPLAY_CLASS=NullDisplayDriver
|
||||
; -D ADVERT_NAME='"@@MAC"'
|
||||
build_src_filter = ${muzi_base_duo.build_src_filter}
|
||||
+<helpers/nrf52/SerialBLEInterface.cpp>
|
||||
+<helpers/sensors>
|
||||
+<helpers/ui/NullDisplayDriver.cpp>
|
||||
+<../examples/companion_radio/*.cpp>
|
||||
+<../examples/companion_radio/ui-new/*.cpp>
|
||||
lib_deps = ${muzi_base_duo.lib_deps}
|
||||
densaugeo/base64 @ ~1.4.0
|
||||
|
||||
[muzi_base_duo_superIO]
|
||||
extends = muzi_base_duo
|
||||
board_build.ldscript = boards/nrf52840_s140_v6_extrafs.ld
|
||||
board_upload.maximum_size = 708608
|
||||
build_flags = ${muzi_base_duo.build_flags}
|
||||
-D MUZI_BASE_SUPERIO
|
||||
-D UI_HAS_JOYSTICK=1
|
||||
-D OFFLINE_QUEUE_SIZE=256
|
||||
-D DISPLAY_CLASS=SH1107Display
|
||||
-D DISPLAY_ROTATION=2
|
||||
-D ENV_INCLUDE_GPS=1
|
||||
-D ENV_SKIP_GPS_DETECT
|
||||
-D PIN_BUZZER=22
|
||||
build_src_filter = ${muzi_base_duo.build_src_filter}
|
||||
+<helpers/nrf52/SerialBLEInterface.cpp>
|
||||
+<helpers/sensors>
|
||||
+<helpers/ui/SH1107Display.cpp>
|
||||
+<helpers/ui/buzzer.cpp>
|
||||
+<helpers/ui/MomentaryButton.cpp>
|
||||
lib_deps = ${muzi_base_duo.lib_deps}
|
||||
densaugeo/base64 @ ~1.4.0
|
||||
stevemarple/MicroNMEA @ ^2.0.6
|
||||
end2endzone/NonBlockingRTTTL@^1.3.0
|
||||
adafruit/Adafruit SH110X@^2.1.14
|
||||
artronshop/ArtronShop_RX8130CE@1.0.0
|
||||
adafruit/Adafruit GFX Library @ ^1.12.1
|
||||
debug_tool = jlink
|
||||
upload_protocol = nrfutil
|
||||
|
||||
[env:muzi_base_duo_superIO_companion_radio_ble]
|
||||
extends = muzi_base_duo_superIO
|
||||
board_build.ldscript = boards/nrf52840_s140_v6_extrafs.ld
|
||||
board_upload.maximum_size = 708608
|
||||
build_flags = ${muzi_base_duo_superIO.build_flags}
|
||||
-D MAX_CONTACTS=350
|
||||
-D MAX_GROUP_CHANNELS=40
|
||||
-I examples/companion_radio/ui-new
|
||||
-D BLE_PIN_CODE=123456
|
||||
-D QSPIFLASH=1
|
||||
; -D BLE_DEBUG_LOGGING=1
|
||||
; -D MESH_PACKET_LOGGING=1
|
||||
; -D MESH_DEBUG=1
|
||||
-D OFFLINE_QUEUE_SIZE=256
|
||||
build_src_filter = ${muzi_base_duo_superIO.build_src_filter}
|
||||
+<helpers/nrf52/SerialBLEInterface.cpp>
|
||||
+<../examples/companion_radio/*.cpp>
|
||||
+<../examples/companion_radio/ui-new/*.cpp>
|
||||
lib_deps =
|
||||
${muzi_base_duo_superIO.lib_deps}
|
||||
|
||||
; ===========================================================================
|
||||
; Uno (SX1262) environments
|
||||
; ===========================================================================
|
||||
[env:muzi_base_uno_repeater]
|
||||
extends = muzi_base_uno
|
||||
build_flags = ${muzi_base_uno.build_flags}
|
||||
-I examples/companion_radio/ui-new
|
||||
-D ADVERT_NAME='"Muzi Base 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 = ${muzi_base_uno.build_src_filter}
|
||||
+<../examples/simple_repeater>
|
||||
lib_deps = ${muzi_base_uno.lib_deps}
|
||||
|
||||
[env:muzi_base_uno_room_server]
|
||||
extends = muzi_base_uno
|
||||
build_flags = ${muzi_base_uno.build_flags}
|
||||
-I examples/companion_radio/ui-new
|
||||
-D ADVERT_NAME='"Muzi Base 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
|
||||
build_src_filter = ${muzi_base_uno.build_src_filter}
|
||||
+<../examples/simple_room_server>
|
||||
lib_deps = ${muzi_base_uno.lib_deps}
|
||||
|
||||
[env:muzi_base_uno_companion_radio_usb]
|
||||
extends = muzi_base_uno
|
||||
board_build.ldscript = boards/nrf52840_s140_v6_extrafs.ld
|
||||
board_upload.maximum_size = 708608
|
||||
build_flags = ${muzi_base_uno.build_flags}
|
||||
-I examples/companion_radio/ui-new
|
||||
-D MAX_CONTACTS=350
|
||||
-D MAX_GROUP_CHANNELS=40
|
||||
; -D MESH_PACKET_LOGGING=1
|
||||
; -D MESH_DEBUG=1
|
||||
-D OFFLINE_QUEUE_SIZE=256
|
||||
-D DISPLAY_CLASS=NullDisplayDriver
|
||||
build_src_filter = ${muzi_base_uno.build_src_filter}
|
||||
+<helpers/ui/NullDisplayDriver.cpp>
|
||||
+<../examples/companion_radio/*.cpp>
|
||||
+<../examples/companion_radio/ui-new/*.cpp>
|
||||
lib_deps = ${muzi_base_uno.lib_deps}
|
||||
densaugeo/base64 @ ~1.4.0
|
||||
|
||||
[env:muzi_base_uno_companion_radio_ble]
|
||||
extends = muzi_base_uno
|
||||
board_build.ldscript = boards/nrf52840_s140_v6_extrafs.ld
|
||||
board_upload.maximum_size = 708608
|
||||
build_flags = ${muzi_base_uno.build_flags}
|
||||
-I examples/companion_radio/ui-new
|
||||
-D MAX_CONTACTS=350
|
||||
-D MAX_GROUP_CHANNELS=40
|
||||
-D BLE_PIN_CODE=123456
|
||||
-D QSPIFLASH=1
|
||||
; -D BLE_DEBUG_LOGGING=1
|
||||
; -D MESH_PACKET_LOGGING=1
|
||||
; -D MESH_DEBUG=1
|
||||
-D OFFLINE_QUEUE_SIZE=256
|
||||
-D DISPLAY_CLASS=NullDisplayDriver
|
||||
; -D ADVERT_NAME='"@@MAC"'
|
||||
build_src_filter = ${muzi_base_uno.build_src_filter}
|
||||
+<helpers/nrf52/SerialBLEInterface.cpp>
|
||||
+<helpers/sensors>
|
||||
+<helpers/ui/NullDisplayDriver.cpp>
|
||||
+<../examples/companion_radio/*.cpp>
|
||||
+<../examples/companion_radio/ui-new/*.cpp>
|
||||
lib_deps = ${muzi_base_uno.lib_deps}
|
||||
densaugeo/base64 @ ~1.4.0
|
||||
|
||||
[muzi_base_uno_superIO]
|
||||
extends = muzi_base_uno
|
||||
board_build.ldscript = boards/nrf52840_s140_v6_extrafs.ld
|
||||
board_upload.maximum_size = 708608
|
||||
build_flags = ${muzi_base_uno.build_flags}
|
||||
-D MUZI_BASE_SUPERIO
|
||||
-D UI_HAS_JOYSTICK=1
|
||||
-D OFFLINE_QUEUE_SIZE=256
|
||||
-D DISPLAY_CLASS=SH1107Display
|
||||
-D DISPLAY_ROTATION=2
|
||||
-D ENV_INCLUDE_GPS=1
|
||||
-D ENV_SKIP_GPS_DETECT
|
||||
-D PIN_BUZZER=22
|
||||
build_src_filter = ${muzi_base_uno.build_src_filter}
|
||||
+<helpers/nrf52/SerialBLEInterface.cpp>
|
||||
+<helpers/sensors>
|
||||
+<helpers/ui/SH1107Display.cpp>
|
||||
+<helpers/ui/buzzer.cpp>
|
||||
+<helpers/ui/MomentaryButton.cpp>
|
||||
lib_deps = ${muzi_base_uno.lib_deps}
|
||||
densaugeo/base64 @ ~1.4.0
|
||||
stevemarple/MicroNMEA @ ^2.0.6
|
||||
end2endzone/NonBlockingRTTTL@^1.3.0
|
||||
adafruit/Adafruit SH110X@^2.1.14
|
||||
artronshop/ArtronShop_RX8130CE@1.0.0
|
||||
adafruit/Adafruit GFX Library @ ^1.12.1
|
||||
debug_tool = jlink
|
||||
upload_protocol = nrfutil
|
||||
|
||||
[env:muzi_base_uno_superIO_companion_radio_ble]
|
||||
extends = muzi_base_uno_superIO
|
||||
board_build.ldscript = boards/nrf52840_s140_v6_extrafs.ld
|
||||
board_upload.maximum_size = 708608
|
||||
build_flags = ${muzi_base_uno_superIO.build_flags}
|
||||
-D MAX_CONTACTS=350
|
||||
-D MAX_GROUP_CHANNELS=40
|
||||
-I examples/companion_radio/ui-new
|
||||
-D BLE_PIN_CODE=123456
|
||||
-D QSPIFLASH=1
|
||||
; -D BLE_DEBUG_LOGGING=1
|
||||
; -D MESH_PACKET_LOGGING=1
|
||||
; -D MESH_DEBUG=1
|
||||
-D OFFLINE_QUEUE_SIZE=256
|
||||
build_src_filter = ${muzi_base_uno_superIO.build_src_filter}
|
||||
+<helpers/nrf52/SerialBLEInterface.cpp>
|
||||
+<../examples/companion_radio/*.cpp>
|
||||
+<../examples/companion_radio/ui-new/*.cpp>
|
||||
lib_deps =
|
||||
${muzi_base_uno_superIO.lib_deps}
|
||||
@@ -0,0 +1,162 @@
|
||||
#include <Arduino.h>
|
||||
#include <nrf_gpio.h>
|
||||
#include "target.h"
|
||||
#include "variant.h"
|
||||
|
||||
MuziBaseBoard board;
|
||||
|
||||
RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY, SPI);
|
||||
|
||||
WRAPPER_CLASS radio_driver(radio, board);
|
||||
|
||||
VolatileRTCClock fallback_clock;
|
||||
AutoDiscoverRTCClock rtc_clock(fallback_clock);
|
||||
#if ENV_INCLUDE_GPS
|
||||
#include <helpers/sensors/MicroNMEALocationProvider.h>
|
||||
MicroNMEALocationProvider nmea = MicroNMEALocationProvider(Serial1, &rtc_clock);
|
||||
MuziBaseSensorManager sensors = MuziBaseSensorManager(nmea);
|
||||
#else
|
||||
MuziBaseSensorManager sensors;
|
||||
#endif
|
||||
|
||||
// user button for the N-click power-off. single-click mode (multiclick off) so
|
||||
// each press is its own CLICK; we count them ourselves. reliable across the
|
||||
// idle-sleep loop because it's the same MomentaryButton the UI navigates with.
|
||||
static MomentaryButton pwr_btn(PIN_USER_BTN, 0, true, true, false);
|
||||
|
||||
// power off, arming the user button as a wake source first so a later press
|
||||
// turns it back on. wait for the button to release (the 5th click already fires
|
||||
// on release, so this returns quickly), then set nRF52 GPIO SENSE (press = LOW);
|
||||
// it survives into SYSTEMOFF because shutdownPeripherals() doesn't touch this pin.
|
||||
static void muziPowerOff() {
|
||||
uint32_t t0 = millis();
|
||||
while (digitalRead(PIN_USER_BTN) == USER_BTN_PRESSED && (millis() - t0) < 3000) { delay(5); }
|
||||
delay(50); // settle
|
||||
nrf_gpio_cfg_sense_input(g_ADigitalPinMap[PIN_USER_BTN], NRF_GPIO_PIN_PULLUP, NRF_GPIO_PIN_SENSE_LOW);
|
||||
board.powerOff(); // shutdownPeripherals() + SYSTEMOFF
|
||||
}
|
||||
|
||||
bool MuziBaseSensorManager::begin() {
|
||||
pwr_btn.begin();
|
||||
bool ok = EnvironmentSensorManager::begin();
|
||||
#if ENV_INCLUDE_GPS
|
||||
pinMode(PIN_GPS_SWITCH, INPUT);
|
||||
_last_gps_sw = digitalRead(PIN_GPS_SWITCH); // initial gps state from the switch
|
||||
if (_last_gps_sw == HIGH) start_gps(); else stop_gps();
|
||||
#endif
|
||||
return ok;
|
||||
}
|
||||
|
||||
void MuziBaseSensorManager::loop() {
|
||||
// user button: USER_BTN_POWER_OFF_CLICKS quick clicks -> power off
|
||||
if (pwr_btn.check() == BUTTON_EVENT_CLICK) {
|
||||
unsigned long t = millis();
|
||||
if (t - _pwr_last_click > 2000) _pwr_clicks = 0; // restart if too slow
|
||||
_pwr_last_click = t;
|
||||
if (++_pwr_clicks >= USER_BTN_POWER_OFF_CLICKS) muziPowerOff();
|
||||
}
|
||||
#if ENV_INCLUDE_GPS
|
||||
unsigned long now = millis();
|
||||
if (now > _next_sw_check) { // check the mode switch ~once a sec
|
||||
_next_sw_check = now + 1000;
|
||||
int sw = digitalRead(PIN_GPS_SWITCH);
|
||||
if (sw != _last_gps_sw) {
|
||||
_last_gps_sw = sw;
|
||||
if (sw == HIGH) start_gps(); else stop_gps();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
EnvironmentSensorManager::loop();
|
||||
}
|
||||
|
||||
#ifdef DISPLAY_CLASS
|
||||
DISPLAY_CLASS display;
|
||||
MomentaryButton user_btn(PIN_USER_BTN, 1000, true, false, false);
|
||||
MomentaryButton joystick_left(JOYSTICK_LEFT, 1000, true, false, false);
|
||||
MomentaryButton joystick_right(JOYSTICK_RIGHT, 1000, true, false, false);
|
||||
MomentaryButton back_btn(PIN_BACK_BTN, 1000, true, false, true);
|
||||
#endif
|
||||
|
||||
#if defined(USE_LR1121)
|
||||
#ifndef LORA_CR
|
||||
#define LORA_CR 5
|
||||
#endif
|
||||
|
||||
#ifdef RF_SWITCH_TABLE
|
||||
static const uint32_t rfswitch_dios[Module::RFSWITCH_MAX_PINS] = {
|
||||
RADIOLIB_LR11X0_DIO5,
|
||||
RADIOLIB_LR11X0_DIO6,
|
||||
RADIOLIB_NC
|
||||
};
|
||||
|
||||
static const Module::RfSwitchMode_t rfswitch_table[] = {
|
||||
// mode DIO5 DIO6
|
||||
{ LR11x0::MODE_STBY, {LOW, LOW}},
|
||||
{ LR11x0::MODE_RX, {HIGH, LOW}},
|
||||
{ LR11x0::MODE_TX, {LOW, HIGH}},
|
||||
{ LR11x0::MODE_TX_HP, {LOW, HIGH}},
|
||||
{ LR11x0::MODE_TX_HF, {LOW, LOW}},
|
||||
{ LR11x0::MODE_GNSS, {LOW, LOW}},
|
||||
{ LR11x0::MODE_WIFI, {LOW, LOW}},
|
||||
END_OF_MODE_TABLE,
|
||||
};
|
||||
#endif
|
||||
#endif // USE_LR1121
|
||||
|
||||
bool radio_init() {
|
||||
//rtc_clock.begin(Wire);
|
||||
|
||||
#if defined(USE_LR1121)
|
||||
#ifdef LR11X0_DIO3_TCXO_VOLTAGE
|
||||
float tcxo = LR11X0_DIO3_TCXO_VOLTAGE;
|
||||
#else
|
||||
float tcxo = 1.6f;
|
||||
#endif
|
||||
|
||||
SPI.setPins(P_LORA_MISO, P_LORA_SCLK, P_LORA_MOSI);
|
||||
SPI.begin();
|
||||
int status = radio.begin(LORA_FREQ, LORA_BW, LORA_SF, LORA_CR, RADIOLIB_LR11X0_LORA_SYNC_WORD_PRIVATE, LORA_TX_POWER, 16, tcxo);
|
||||
if (status != RADIOLIB_ERR_NONE) {
|
||||
Serial.print("ERROR: radio init failed: ");
|
||||
Serial.println(status);
|
||||
return false; // fail
|
||||
}
|
||||
|
||||
radio.setCRC(2);
|
||||
radio.explicitHeader();
|
||||
|
||||
#ifdef RF_SWITCH_TABLE
|
||||
radio.setRfSwitchTable(rfswitch_dios, rfswitch_table);
|
||||
#endif
|
||||
#ifdef RX_BOOSTED_GAIN
|
||||
radio.setRxBoostedGainMode(RX_BOOSTED_GAIN);
|
||||
#endif
|
||||
|
||||
return true; // success
|
||||
#else // USE_SX1262
|
||||
// CustomSX1262::std_init() configures the SPI pins, runs begin() with the
|
||||
// TCXO-voltage fallback, sets CRC, current limit, the DIO2 RF switch, and
|
||||
// RX boosted gain from the SX126X_* build flags.
|
||||
return radio.std_init(&SPI);
|
||||
#endif
|
||||
}
|
||||
|
||||
uint32_t radio_get_rng_seed() {
|
||||
return radio.random(0x7FFFFFFF);
|
||||
}
|
||||
|
||||
void radio_set_params(float freq, float bw, uint8_t sf, uint8_t cr) {
|
||||
radio.setFrequency(freq);
|
||||
radio.setSpreadingFactor(sf);
|
||||
radio.setBandwidth(bw);
|
||||
radio.setCodingRate(cr);
|
||||
}
|
||||
|
||||
void radio_set_tx_power(int8_t dbm) {
|
||||
radio.setOutputPower(dbm);
|
||||
}
|
||||
|
||||
mesh::LocalIdentity radio_new_identity() {
|
||||
RadioNoiseListener rng(radio);
|
||||
return mesh::LocalIdentity(&rng); // create new random identity
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
#pragma once
|
||||
|
||||
#define RADIOLIB_STATIC_ONLY 1
|
||||
#include <RadioLib.h>
|
||||
#include <helpers/radiolib/RadioLibWrappers.h>
|
||||
#include "MuziBaseBoard.h"
|
||||
#if defined(USE_LR1121)
|
||||
#include <helpers/radiolib/CustomLR1121Wrapper.h>
|
||||
#elif defined(USE_SX1262)
|
||||
#include <helpers/radiolib/CustomSX1262Wrapper.h>
|
||||
#else
|
||||
#error "muzi_base: no radio selected (define USE_LR1121 or USE_SX1262)"
|
||||
#endif
|
||||
#include <helpers/ArduinoHelpers.h>
|
||||
#include <helpers/SensorManager.h>
|
||||
#include <helpers/sensors/LocationProvider.h>
|
||||
#include <helpers/AutoDiscoverRTCClock.h>
|
||||
#include <helpers/sensors/EnvironmentSensorManager.h> // Added: Include for EnvironmentSensorManager
|
||||
#include <helpers/ui/MomentaryButton.h>
|
||||
|
||||
|
||||
#ifdef MUZI_BASE_SUPERIO
|
||||
#include <helpers/ui/SH1107Display.h>
|
||||
extern DISPLAY_CLASS display;
|
||||
extern MomentaryButton user_btn;
|
||||
extern MomentaryButton joystick_left;
|
||||
extern MomentaryButton joystick_right;
|
||||
extern MomentaryButton back_btn;
|
||||
#elif defined(DISPLAY_CLASS)
|
||||
#include "helpers/ui/NullDisplayDriver.h"
|
||||
extern DISPLAY_CLASS display;
|
||||
extern MomentaryButton user_btn;
|
||||
#endif
|
||||
|
||||
extern MuziBaseBoard board;
|
||||
extern WRAPPER_CLASS radio_driver;
|
||||
extern AutoDiscoverRTCClock rtc_clock;
|
||||
|
||||
// muzi sensor manager, polled from main loop via sensors.loop():
|
||||
// - user button: USER_BTN_POWER_OFF_CLICKS quick presses -> power off (all builds)
|
||||
// - gps mode switch on/off (superIO only, see thinknode_m1)
|
||||
class MuziBaseSensorManager : public EnvironmentSensorManager {
|
||||
unsigned long _pwr_last_click = 0;
|
||||
uint8_t _pwr_clicks = 0;
|
||||
#if ENV_INCLUDE_GPS
|
||||
int _last_gps_sw = -1;
|
||||
unsigned long _next_sw_check = 0;
|
||||
#endif
|
||||
public:
|
||||
#if ENV_INCLUDE_GPS
|
||||
MuziBaseSensorManager(LocationProvider& location) : EnvironmentSensorManager(location) {}
|
||||
#else
|
||||
MuziBaseSensorManager() {}
|
||||
#endif
|
||||
bool begin() override;
|
||||
void loop() override;
|
||||
};
|
||||
extern MuziBaseSensorManager sensors;
|
||||
|
||||
bool radio_init();
|
||||
uint32_t radio_get_rng_seed();
|
||||
void radio_set_params(float freq, float bw, uint8_t sf, uint8_t cr);
|
||||
void radio_set_tx_power(int8_t dbm);
|
||||
mesh::LocalIdentity radio_new_identity();
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* variant.cpp
|
||||
* Copyright (C) 2023 Seeed K.K.
|
||||
* MIT License
|
||||
*/
|
||||
|
||||
#include "variant.h"
|
||||
#include "wiring_constants.h"
|
||||
#include "wiring_digital.h"
|
||||
|
||||
const uint32_t g_ADigitalPinMap[PINS_COUNT + 1] =
|
||||
{
|
||||
0,
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
4,
|
||||
5,
|
||||
6,
|
||||
7,
|
||||
8,
|
||||
9,
|
||||
10,
|
||||
11,
|
||||
12,
|
||||
13,
|
||||
14,
|
||||
15,
|
||||
16,
|
||||
17,
|
||||
18,
|
||||
19,
|
||||
20,
|
||||
21,
|
||||
22,
|
||||
23,
|
||||
24,
|
||||
25,
|
||||
26,
|
||||
27,
|
||||
28,
|
||||
29,
|
||||
30,
|
||||
31,
|
||||
// P1 pins.
|
||||
32,
|
||||
33,
|
||||
34,
|
||||
35,
|
||||
36,
|
||||
37,
|
||||
38,
|
||||
39,
|
||||
40,
|
||||
41,
|
||||
42,
|
||||
43,
|
||||
44,
|
||||
45,
|
||||
46,
|
||||
47,
|
||||
};
|
||||
@@ -0,0 +1,169 @@
|
||||
/*
|
||||
* variant.h
|
||||
* Copyright (C) 2023 Seeed K.K.
|
||||
* MIT License
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "WVariant.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Low frequency clock source
|
||||
|
||||
#define USE_LFXO // 32.768 kHz crystal oscillator
|
||||
#define VARIANT_MCK (64000000ul)
|
||||
// #define USE_LFRC // 32.768 kHz RC oscillator
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Power
|
||||
|
||||
#define PIN_VBAT_READ (31) // P0.31
|
||||
#define BATTERY_SENSE_RESOLUTION_BITS 12
|
||||
#define BATTERY_SENSE_RESOLUTION 4096.0
|
||||
#define AREF_VOLTAGE 3.0
|
||||
#define VBAT_AR_INTERNAL AR_INTERNAL_3_0
|
||||
#define ADC_MULTIPLIER 1.537
|
||||
#define ADC_RESOLUTION 14
|
||||
#define PIN_BATTERY_CHARGING (32+2) // P1.02 STAT2
|
||||
#define PIN_CHARGER_FAULT (27) // P0.27 STAT1 this pin is disabled on meshtastic.
|
||||
// BQ25185 has 2 status pins: STAT1 and STAT2. Both are high when not charging. STAT1 high, STAT2 low: charging. Recoverable fault: STAT1 low, STAT2 high. Unrecoverable fault: both low.
|
||||
// We only need to detect charging vs not charging, but someone else can use the fault pin to log when the battery gets too hot or cold.
|
||||
|
||||
// Power management boot protection threshold (millivolts)
|
||||
#define PWRMGT_VOLTAGE_BOOTLOCK 3100 // Won't boot below this voltage (mV). BB15 battery min voltage is 3v, 3100mV is minimum batt in meshtastic code.
|
||||
|
||||
// LPCOMP wake configuration (voltage recovery from SYSTEMOFF)
|
||||
#define PWRMGT_LPCOMP_AIN 7 // AIN7 = P0.31 = PIN_VBAT_READ
|
||||
#define PWRMGT_LPCOMP_REFSEL 4 // 5/8 VDD (~3.13-3.44V) was the default on RAK4631. should still apply here.
|
||||
|
||||
// Other pins
|
||||
#define PIN_AREF (-1)
|
||||
#define SCREEN_12V_ENABLE (23) // SH1107 OLED controller has a pin that needs to be enabled to turn on the screen.
|
||||
|
||||
static const uint8_t AREF = (PIN_AREF); // not used
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Number of pins
|
||||
|
||||
#define PINS_COUNT (48)
|
||||
#define NUM_DIGITAL_PINS (48)
|
||||
#define NUM_ANALOG_INPUTS (6)
|
||||
#define NUM_ANALOG_OUTPUTS (0)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// UART pin definition
|
||||
|
||||
#define PIN_SERIAL1_RX (19) // P0.19 used for GPS RX
|
||||
#define PIN_SERIAL1_TX (20) // P0.20 used for GPS TX
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// I2C pin definition
|
||||
|
||||
#define HAS_WIRE (1)
|
||||
#define WIRE_INTERFACES_COUNT (2)
|
||||
|
||||
#define PIN_WIRE1_SDA (4) // P0.4
|
||||
#define PIN_WIRE1_SCL (6) // P0.6
|
||||
#define PIN_WIRE_SDA (24) // P0.24 OLED I2C
|
||||
#define PIN_WIRE_SCL (25) // P0.25 OLED I2C
|
||||
#define I2C_NO_RESCAN
|
||||
// #define I2C_NO_RESCAN
|
||||
// #define HAS_QMA6100P
|
||||
// #define QMA_6100P_INT_PIN (34) // P1.2
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// SPI pin definition
|
||||
|
||||
#define SPI_INTERFACES_COUNT (1)
|
||||
|
||||
#define PIN_SPI_MISO (32+15) // internally connected to p1.15
|
||||
#define PIN_SPI_MOSI (32+14) // internally connected to p1.14
|
||||
#define PIN_SPI_SCK (32+13) // internally connected to p1.13
|
||||
#define PIN_SPI_NSS (32+12) // internally connected to p1.12
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Builtin LEDs
|
||||
|
||||
#define LED_BUILTIN (35)
|
||||
#define LED_BLUE (-1) // P1.04 turned off, because the blue LED was annoying.
|
||||
// #define LED_GREEN (35) // P1.03
|
||||
#define LED_PIN LED_BUILTIN
|
||||
|
||||
#define LED_STATE_ON LOW
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Builtin buttons
|
||||
#define PIN_BUTTON1 (10) // P0.10 Menu / User Button | on superIO, this is in the center of the "D-Pad", but it's also the button on the Uno/Duo.
|
||||
#define PIN_BUTTON2 (21) // Joystick Up
|
||||
#define PIN_BUTTON3 (17) // Joystick Down
|
||||
#define PIN_BUTTON4 (37) // Joystick Left
|
||||
#define PIN_BUTTON5 (16) // Joystick Right
|
||||
#define PIN_BUTTON6 (15) // Back / Cancel Button.
|
||||
#define JOYSTICK_PRESS PIN_BUTTON1
|
||||
#define JOYSTICK_UP PIN_BUTTON2
|
||||
#define JOYSTICK_DOWN PIN_BUTTON3
|
||||
#define JOYSTICK_LEFT PIN_BUTTON4
|
||||
#define JOYSTICK_RIGHT PIN_BUTTON5
|
||||
#define PIN_BACK_BTN PIN_BUTTON6
|
||||
|
||||
// quick user-button presses that power the device off (per Muzi's docs)
|
||||
#ifndef USER_BTN_POWER_OFF_CLICKS
|
||||
#define USER_BTN_POWER_OFF_CLICKS 5
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// LoRa radio
|
||||
//
|
||||
// The Muzi Base PCB is populated with one of two radios:
|
||||
// * Base Uno -> SX1262 (USE_SX1262)
|
||||
// * Base Duo -> LR1121 (USE_LR1121)
|
||||
// Both share NSS/SCLK/MISO/MOSI/RESET/BUSY. The only pin difference is the
|
||||
// radio IRQ (DIO1): the SX1262 routes it to P1.06, the LR1121 to P1.08.
|
||||
// (see Meshtastic muzi_base variant, which defines both radios on this board)
|
||||
|
||||
#define LORA_NSS (PIN_SPI_NSS) // P1.12
|
||||
#define LORA_RESET (32+10) // P1.10
|
||||
#define LORA_BUSY (32+11) // P1.11
|
||||
#define LORA_SCLK (PIN_SPI_SCK) // P1.13
|
||||
#define LORA_MISO (PIN_SPI_MISO) // P1.15
|
||||
#define LORA_MOSI (PIN_SPI_MOSI) // P1.14
|
||||
|
||||
// only the IRQ pin differs per radio. rf-switch/tcxo defines are in platformio.ini
|
||||
#if defined(USE_LR1121)
|
||||
#define LORA_DIO_1 (32+8) // P1.08 LR1121 IRQ/DIO1
|
||||
#elif defined(USE_SX1262)
|
||||
#define LORA_DIO_1 (32+6) // P1.06 SX1262 IRQ/DIO1
|
||||
#else
|
||||
#error "muzi_base: no radio selected (define USE_LR1121 or USE_SX1262)"
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// QSPI Flash
|
||||
#define PIN_QSPI_SCK (0 + 3)
|
||||
#define PIN_QSPI_CS (0 + 26)
|
||||
#define PIN_QSPI_IO0 (0 + 30)
|
||||
#define PIN_QSPI_IO1 (0 + 29)
|
||||
#define PIN_QSPI_IO2 (0 + 28)
|
||||
#define PIN_QSPI_IO3 (0 + 2)
|
||||
|
||||
#define EXTERNAL_FLASH_DEVICES W25Q128JVPQ
|
||||
#define EXTERNAL_FLASH_USE_QSPI
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// GPS
|
||||
#define HAS_GPS 1
|
||||
#define PIN_GPS_RX PIN_SERIAL1_RX
|
||||
#define PIN_GPS_TX PIN_SERIAL1_TX
|
||||
#define PIN_GPS_EN (32+1) // P1.01 PWR_IO2 on schematic. gps power, driven by the sensor manager.
|
||||
|
||||
// superIO 3-position mode switch (pins from the meshtastic muzi_base variant).
|
||||
// "Mode 2" reads HIGH on PIN_GPS_SWITCH and turns the gps on.
|
||||
#define SWITCH_MODE1 (32+9) // P1.09
|
||||
#define SWITCH_MODE2 (12) // P0.12
|
||||
#define PIN_GPS_SWITCH SWITCH_MODE2
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Buzzer
|
||||
|
||||
#define BUZZER_PIN (22) // P0.22 same load switch design as GPS_EN.
|
||||
@@ -7,7 +7,6 @@ build_flags = ${nrf52_base.build_flags}
|
||||
-I variants/muziworks_r1_neo
|
||||
-I src/helpers/ui
|
||||
-D R1Neo
|
||||
-D NRF52_POWER_MANAGEMENT
|
||||
-D RADIO_CLASS=CustomSX1262
|
||||
-D WRAPPER_CLASS=CustomSX1262Wrapper
|
||||
-D DISPLAY_CLASS=NullDisplayDriver
|
||||
|
||||
@@ -143,6 +143,7 @@ extends = nibble_screen_connect_base
|
||||
build_flags =
|
||||
${nibble_screen_connect_base.build_flags}
|
||||
-I examples/companion_radio/ui-new
|
||||
-D ENABLE_WIFI_INTERFACE
|
||||
-D DISPLAY_CLASS=SSD1306Display
|
||||
-D MAX_CONTACTS=300
|
||||
-D MAX_GROUP_CHANNELS=8
|
||||
@@ -154,6 +155,7 @@ build_src_filter = ${nibble_screen_connect_base.build_src_filter}
|
||||
+<helpers/ui/SSD1306Display.cpp>
|
||||
+<helpers/ui/MomentaryButton.cpp>
|
||||
+<helpers/esp32/*.cpp>
|
||||
+<helpers/wifi/*.cpp>
|
||||
+<../examples/companion_radio/*.cpp>
|
||||
+<../examples/companion_radio/ui-new/*.cpp>
|
||||
lib_deps =
|
||||
|
||||
@@ -140,6 +140,7 @@ extends = nibble_zero_connect_base
|
||||
build_flags =
|
||||
${nibble_zero_connect_base.build_flags}
|
||||
-I examples/companion_radio/ui-new
|
||||
-D ENABLE_WIFI_INTERFACE
|
||||
-D DISPLAY_CLASS=SSD1306Display
|
||||
-D MAX_CONTACTS=300
|
||||
-D MAX_GROUP_CHANNELS=8
|
||||
@@ -150,6 +151,7 @@ build_src_filter = ${nibble_zero_connect_base.build_src_filter}
|
||||
+<helpers/ui/SSD1306Display.cpp>
|
||||
+<helpers/ui/MomentaryButton.cpp>
|
||||
+<helpers/esp32/*.cpp>
|
||||
+<helpers/wifi/*.cpp>
|
||||
+<../examples/companion_radio/*.cpp>
|
||||
+<../examples/companion_radio/ui-new/*.cpp>
|
||||
lib_deps =
|
||||
|
||||
@@ -23,6 +23,7 @@ build_flags = ${nrf52_base.build_flags}
|
||||
-D ENV_INCLUDE_BMP280=1
|
||||
-D ENV_INCLUDE_INA3221=1
|
||||
-D ENV_INCLUDE_INA219=1
|
||||
-D ENV_INCLUDE_INA226=1
|
||||
build_src_filter = ${nrf52_base.build_src_filter}
|
||||
+<helpers/sensors>
|
||||
+<../variants/promicro>
|
||||
@@ -34,6 +35,7 @@ lib_deps= ${nrf52_base.lib_deps}
|
||||
adafruit/Adafruit BME280 Library @ ^2.3.0
|
||||
adafruit/Adafruit BMP280 Library@^2.6.8
|
||||
stevemarple/MicroNMEA @ ^2.0.6
|
||||
robtillaart/INA226@^0.6.6
|
||||
|
||||
[env:ProMicro_repeater]
|
||||
extends = Promicro
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <MeshCore.h>
|
||||
#include <helpers/KeyValueStore.h>
|
||||
|
||||
// from https://github.com/RAKWireless/RAK11300-AT-Command-Firmware/blob/9c48409a43620a828d653501d536473200aa33af/RAK11300-AT-Arduino/batt.cpp#L17-L19
|
||||
#define VBAT_MV_PER_LSB (0.806F) // 3.0V ADC range and 12 - bit ADC resolution = 3300mV / 4096
|
||||
@@ -46,4 +47,6 @@ public:
|
||||
void reboot() override { rp2040.reboot(); }
|
||||
|
||||
bool startOTAUpdate(const char *id, char reply[]) override;
|
||||
|
||||
void attachDynamicPrefs(KeyValueStore* prefs) { } // no-op
|
||||
};
|
||||
|
||||
@@ -155,12 +155,14 @@ build_flags =
|
||||
-D MAX_GROUP_CHANNELS=40
|
||||
-D BLE_PIN_CODE=123456 ; dynamic, random PIN
|
||||
-D AUTO_SHUTDOWN_MILLIVOLTS=3400
|
||||
-D BLE_DEBUG_LOGGING=1
|
||||
-D OFFLINE_QUEUE_SIZE=256
|
||||
-D ENABLE_WIFI_INTERFACE
|
||||
; -D BLE_DEBUG_LOGGING=1
|
||||
; -D MESH_PACKET_LOGGING=1
|
||||
; -D MESH_DEBUG=1
|
||||
build_src_filter = ${rak3112.build_src_filter}
|
||||
+<helpers/esp32/*.cpp>
|
||||
+<helpers/wifi/*.cpp>
|
||||
+<../examples/companion_radio/*.cpp>
|
||||
+<../examples/companion_radio/ui-orig/*.cpp>
|
||||
lib_deps =
|
||||
@@ -172,6 +174,7 @@ extends = rak3112
|
||||
build_flags =
|
||||
${rak3112.build_flags}
|
||||
-I examples/companion_radio/ui-orig
|
||||
-D ENABLE_WIFI_INTERFACE
|
||||
-D MAX_CONTACTS=350
|
||||
-D MAX_GROUP_CHANNELS=40
|
||||
-D WIFI_DEBUG_LOGGING=1
|
||||
@@ -182,6 +185,7 @@ build_flags =
|
||||
; -D MESH_DEBUG=1
|
||||
build_src_filter = ${rak3112.build_src_filter}
|
||||
+<helpers/esp32/*.cpp>
|
||||
+<helpers/wifi/*.cpp>
|
||||
+<../examples/companion_radio/*.cpp>
|
||||
+<../examples/companion_radio/ui-orig/*.cpp>
|
||||
lib_deps =
|
||||
|
||||
@@ -6,7 +6,7 @@ build_flags = ${nrf52_base.build_flags}
|
||||
${sensor_base.build_flags}
|
||||
-I variants/rak3401
|
||||
-D RAK_3401
|
||||
-D NRF52_POWER_MANAGEMENT
|
||||
-D RAK_BOARD
|
||||
-D RADIO_CLASS=CustomSX1262
|
||||
-D WRAPPER_CLASS=CustomSX1262Wrapper
|
||||
-D LORA_TX_POWER=22
|
||||
|
||||
@@ -188,8 +188,8 @@ static const uint8_t AREF = PIN_AREF;
|
||||
// Power is on the controllable 3V3_S rail
|
||||
#define PIN_GPS_PPS (17) // Pulse per second input from the GPS
|
||||
|
||||
#define PIN_GPS_RX PIN_SERIAL1_RX
|
||||
#define PIN_GPS_TX PIN_SERIAL1_TX
|
||||
#define PIN_GPS_TX PIN_SERIAL1_RX
|
||||
#define PIN_GPS_RX PIN_SERIAL1_TX
|
||||
|
||||
#define PIN_GPS_1PPS PIN_GPS_PPS
|
||||
#define GPS_BAUD_RATE 9600
|
||||
|
||||
@@ -9,7 +9,6 @@ build_flags = ${nrf52_base.build_flags}
|
||||
-I variants/rak4631
|
||||
-D RAK_4631
|
||||
-D RAK_BOARD
|
||||
-D NRF52_POWER_MANAGEMENT
|
||||
-D PIN_BOARD_SCL=14
|
||||
-D PIN_BOARD_SDA=13
|
||||
-D PIN_GPS_TX=PIN_SERIAL1_RX
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include <MeshCore.h>
|
||||
#include <Arduino.h>
|
||||
#include <helpers/KeyValueStore.h>
|
||||
|
||||
// built-ins
|
||||
#define PIN_VBAT_READ 26
|
||||
@@ -16,6 +17,8 @@ public:
|
||||
void begin();
|
||||
uint8_t getStartupReason() const override { return startup_reason; }
|
||||
|
||||
void attachDynamicPrefs(KeyValueStore* prefs) { } // no-op
|
||||
|
||||
void onBeforeTransmit() override {
|
||||
digitalWrite(LED_BUILTIN, HIGH); // turn TX LED on
|
||||
}
|
||||
|
||||
@@ -67,34 +67,60 @@ lib_deps = ${rpi_picow.lib_deps}
|
||||
densaugeo/base64 @ ~1.4.0
|
||||
lib_ignore = BLE
|
||||
|
||||
; [env:PicoW_companion_radio_ble]
|
||||
; extends = rpi_picow
|
||||
; build_flags = ${rpi_picow.build_flags}
|
||||
; -D MAX_CONTACTS=100
|
||||
; -D MAX_GROUP_CHANNELS=8
|
||||
; -D BLE_PIN_CODE=123456
|
||||
; -D BLE_DEBUG_LOGGING=1
|
||||
; ; -D MESH_PACKET_LOGGING=1
|
||||
; ; -D MESH_DEBUG=1
|
||||
; build_src_filter = ${rpi_picow.build_src_filter}
|
||||
; +<../examples/companion_radio/*.cpp>
|
||||
; lib_deps = ${rpi_picow.lib_deps}
|
||||
; densaugeo/base64 @ ~1.4.0
|
||||
[env:PicoW_companion_radio_ble]
|
||||
extends = rpi_picow
|
||||
build_flags = ${rpi_picow.build_flags}
|
||||
-D MAX_CONTACTS=100
|
||||
-D MAX_GROUP_CHANNELS=8
|
||||
-D PIO_FRAMEWORK_ARDUINO_ENABLE_BLUETOOTH
|
||||
-D BLE_PIN_CODE=123456
|
||||
-D BLE_DEBUG_LOGGING=1
|
||||
; -D MESH_PACKET_LOGGING=1
|
||||
; -D MESH_DEBUG=1
|
||||
build_src_filter = ${rpi_picow.build_src_filter}
|
||||
+<helpers/rp2040/SerialBLEInterface.cpp>
|
||||
+<../examples/companion_radio/*.cpp>
|
||||
lib_deps = ${rpi_picow.lib_deps}
|
||||
densaugeo/base64 @ ~1.4.0
|
||||
|
||||
; [env:PicoW_companion_radio_wifi]
|
||||
; extends = rpi_picow
|
||||
; build_flags = ${rpi_picow.build_flags}
|
||||
; -D MAX_CONTACTS=100
|
||||
; -D MAX_GROUP_CHANNELS=8
|
||||
; -D WIFI_DEBUG_LOGGING=1
|
||||
; -D WIFI_SSID='"myssid"'
|
||||
; -D WIFI_PWD='"mypwd"'
|
||||
; ; -D MESH_PACKET_LOGGING=1
|
||||
; ; -D MESH_DEBUG=1
|
||||
; build_src_filter = ${rpi_picow.build_src_filter}
|
||||
; +<../examples/companion_radio/*.cpp>
|
||||
; lib_deps = ${rpi_picow.lib_deps}
|
||||
; densaugeo/base64 @ ~1.4.0
|
||||
; USB + WiFi + BLE together; the interface manager fans frames out to all of them
|
||||
[env:PicoW_companion_radio]
|
||||
extends = rpi_picow
|
||||
build_flags = ${rpi_picow.build_flags}
|
||||
-D MAX_CONTACTS=100
|
||||
-D MAX_GROUP_CHANNELS=8
|
||||
-D ENABLE_USB_INTERFACE
|
||||
-D ENABLE_WIFI_INTERFACE
|
||||
-D PIO_FRAMEWORK_ARDUINO_ENABLE_BLUETOOTH
|
||||
-D BLE_PIN_CODE=123456
|
||||
; NOTE: DO NOT ENABLE --> -D BLE_DEBUG_LOGGING=1 (shares Serial with the USB interface)
|
||||
; NOTE: DO NOT ENABLE --> -D WIFI_DEBUG_LOGGING=1
|
||||
; -D MESH_PACKET_LOGGING=1
|
||||
; -D MESH_DEBUG=1
|
||||
build_src_filter = ${rpi_picow.build_src_filter}
|
||||
+<helpers/rp2040/SerialBLEInterface.cpp>
|
||||
+<helpers/wifi/*.cpp>
|
||||
+<../examples/companion_radio/*.cpp>
|
||||
lib_deps = ${rpi_picow.lib_deps}
|
||||
densaugeo/base64 @ ~1.4.0
|
||||
|
||||
[env:PicoW_companion_radio_wifi]
|
||||
extends = rpi_picow
|
||||
build_flags = ${rpi_picow.build_flags}
|
||||
-D ENABLE_WIFI_INTERFACE
|
||||
-D MAX_CONTACTS=100
|
||||
-D MAX_GROUP_CHANNELS=8
|
||||
-D WIFI_DEBUG_LOGGING=1
|
||||
-D WIFI_SSID='""' ; no default network, configure with 'set wifi.ssid' / 'set wifi.pwd'
|
||||
-D WIFI_PWD='""'
|
||||
; -D MESH_PACKET_LOGGING=1
|
||||
; -D MESH_DEBUG=1
|
||||
build_src_filter = ${rpi_picow.build_src_filter}
|
||||
+<helpers/wifi/*.cpp>
|
||||
+<../examples/companion_radio/*.cpp>
|
||||
lib_deps = ${rpi_picow.lib_deps}
|
||||
densaugeo/base64 @ ~1.4.0
|
||||
lib_ignore = BLE
|
||||
|
||||
[env:PicoW_terminal_chat]
|
||||
extends = rpi_picow
|
||||
|
||||
@@ -10,7 +10,6 @@ build_flags = ${nrf52_base.build_flags}
|
||||
-I src/helpers/nrf52
|
||||
-D NRF52_PLATFORM=1
|
||||
-D USE_SX1262
|
||||
-D NRF52_POWER_MANAGEMENT
|
||||
-D RADIO_CLASS=CustomSX1262
|
||||
-D WRAPPER_CLASS=CustomSX1262Wrapper
|
||||
-D P_LORA_TX_LED=12
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <MeshCore.h>
|
||||
#include <helpers/KeyValueStore.h>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
|
||||
@@ -20,6 +21,7 @@ class SimMainBoard : public mesh::MainBoard {
|
||||
|
||||
public:
|
||||
void begin() { }
|
||||
void attachDynamicPrefs(KeyValueStore* prefs) { } // no-op, as the real boards without their own settings
|
||||
|
||||
bool isExternalPowered() override { return externalPowerRef(); }
|
||||
static void setExternalPower(bool on) { externalPowerRef() = on; }
|
||||
|
||||
@@ -224,6 +224,7 @@ extends = Station_G2
|
||||
build_flags =
|
||||
${Station_G2.build_flags}
|
||||
-I examples/companion_radio/ui-new
|
||||
-D ENABLE_WIFI_INTERFACE
|
||||
-D MAX_CONTACTS=350
|
||||
-D MAX_GROUP_CHANNELS=40
|
||||
-D WIFI_DEBUG_LOGGING=1
|
||||
@@ -234,6 +235,7 @@ build_flags =
|
||||
; -D MESH_DEBUG=1
|
||||
build_src_filter = ${Station_G2.build_src_filter}
|
||||
+<helpers/esp32/*.cpp>
|
||||
+<helpers/wifi/*.cpp>
|
||||
+<../examples/companion_radio/*.cpp>
|
||||
+<../examples/companion_radio/ui-new/*.cpp>
|
||||
lib_deps =
|
||||
|
||||
@@ -21,10 +21,6 @@ bool StationG3Board::setLoRaFemLnaEnabled(bool enable) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool StationG3Board::canControlLoRaFemLna() const {
|
||||
return loRaFEMControl.canControlLNA();
|
||||
}
|
||||
|
||||
bool StationG3Board::isLoRaFemLnaEnabled() const {
|
||||
return loRaFEMControl.isLNAEnabled();
|
||||
}
|
||||
@@ -37,10 +33,86 @@ bool StationG3Board::setLoRaFemPaGainEnabled(bool enable) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool StationG3Board::canControlLoRaFemPaGain() const {
|
||||
return loRaFEMControl.canControlPAGain();
|
||||
}
|
||||
|
||||
bool StationG3Board::isLoRaFemPaGainEnabled() const {
|
||||
return loRaFEMControl.isPAGainEnabled();
|
||||
}
|
||||
|
||||
void StationG3Board::attachDynamicPrefs(KeyValueStore* prefs) {
|
||||
_prefs = prefs;
|
||||
|
||||
char gain[8];
|
||||
|
||||
gain[0] = 0;
|
||||
_prefs->getByKey("fem_rxgain", gain, 7); // get initial values
|
||||
setLoRaFemLnaEnabled(strcmp(gain, "1") == 0);
|
||||
|
||||
gain[0] = 0;
|
||||
_prefs->getByKey("fem_txgain", gain, 7); // get initial values
|
||||
setLoRaFemPaGainEnabled(strcmp(gain, "1") == 0);
|
||||
}
|
||||
|
||||
bool StationG3Board::handleCommand(const char* command, uint32_t sender_timestamp, char* reply) {
|
||||
if (strcmp(command, "get radio.fem.rxgain") == 0) {
|
||||
if (!loRaFEMControl.canControlLNA()) {
|
||||
strcpy(reply, "Error: unsupported");
|
||||
} else {
|
||||
sprintf(reply, "> %s", isLoRaFemLnaEnabled() ? "on" : "off");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (memcmp(command, "set radio.fem.rxgain ", 21) == 0) {
|
||||
if (!loRaFEMControl.canControlLNA()) {
|
||||
strcpy(reply, "Error: unsupported");
|
||||
} else if (memcmp(&command[21], "on", 2) == 0) {
|
||||
if (setLoRaFemLnaEnabled(true)) {
|
||||
_prefs->setByKey("fem_rxgain", "1");
|
||||
strcpy(reply, "OK - LoRa FEM RX gain on");
|
||||
} else {
|
||||
strcpy(reply, "Error: failed to apply LoRa FEM RX gain");
|
||||
}
|
||||
} else if (memcmp(&command[21], "off", 3) == 0) {
|
||||
if (setLoRaFemLnaEnabled(false)) {
|
||||
_prefs->setByKey("fem_rxgain", "0");
|
||||
strcpy(reply, "OK - LoRa FEM RX gain off");
|
||||
} else {
|
||||
strcpy(reply, "Error: failed to apply LoRa FEM RX gain");
|
||||
}
|
||||
} else {
|
||||
strcpy(reply, "Error: state must be on or off");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if (strcmp(command, "get radio.fem.txgain") == 0) {
|
||||
if (!loRaFEMControl.canControlPAGain()) {
|
||||
strcpy(reply, "Error: unsupported");
|
||||
} else {
|
||||
sprintf(reply, "> %s", isLoRaFemPaGainEnabled() ? "on" : "off");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (memcmp(command, "set radio.fem.txgain ", 21) == 0) {
|
||||
if (!loRaFEMControl.canControlPAGain()) {
|
||||
strcpy(reply, "Error: unsupported");
|
||||
} else if (memcmp(&command[21], "on", 2) == 0) {
|
||||
if (setLoRaFemPaGainEnabled(true)) {
|
||||
_prefs->setByKey("fem_txgain", "1");
|
||||
strcpy(reply, "OK - LoRa FEM TX gain on");
|
||||
} else {
|
||||
strcpy(reply, "Error: failed to apply LoRa FEM TX gain");
|
||||
}
|
||||
} else if (memcmp(&command[21], "off", 3) == 0) {
|
||||
if (setLoRaFemPaGainEnabled(false)) {
|
||||
_prefs->setByKey("fem_txgain", "0");
|
||||
strcpy(reply, "OK - LoRa FEM TX gain off");
|
||||
} else {
|
||||
strcpy(reply, "Error: failed to apply LoRa FEM TX gain");
|
||||
}
|
||||
} else {
|
||||
strcpy(reply, "Error: state must be on or off");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return false; // not handled
|
||||
}
|
||||
|
||||
@@ -6,6 +6,12 @@
|
||||
#include "LoRaFEMControl.h"
|
||||
|
||||
class StationG3Board : public ESP32Board {
|
||||
KeyValueStore* _prefs = NULL;
|
||||
|
||||
bool setLoRaFemLnaEnabled(bool enable);
|
||||
bool isLoRaFemLnaEnabled() const;
|
||||
bool setLoRaFemPaGainEnabled(bool enable);
|
||||
bool isLoRaFemPaGainEnabled() const;
|
||||
public:
|
||||
LoRaFEMControl loRaFEMControl;
|
||||
|
||||
@@ -25,6 +31,10 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
void attachDynamicPrefs(KeyValueStore* prefs);
|
||||
|
||||
bool handleCommand(const char* command, uint32_t sender_timestamp, char* reply) override;
|
||||
|
||||
void setPrimaryLNAEnable(bool enabled) {
|
||||
loRaFEMControl.setLNAEnable(enabled);
|
||||
}
|
||||
@@ -43,13 +53,6 @@ public:
|
||||
loRaFEMControl.setRxModeEnable();
|
||||
}
|
||||
|
||||
bool setLoRaFemLnaEnabled(bool enable) override;
|
||||
bool canControlLoRaFemLna() const override;
|
||||
bool isLoRaFemLnaEnabled() const override;
|
||||
bool setLoRaFemPaGainEnabled(bool enable) override;
|
||||
bool canControlLoRaFemPaGain() const override;
|
||||
bool isLoRaFemPaGainEnabled() const override;
|
||||
|
||||
void powerOff() override;
|
||||
|
||||
uint16_t getBattMilliVolts() override {
|
||||
|
||||
@@ -139,6 +139,7 @@ extends = Station_G3_ESP32
|
||||
build_flags =
|
||||
${Station_G3_ESP32.build_flags}
|
||||
-I examples/companion_radio/ui-new
|
||||
-D ENABLE_WIFI_INTERFACE
|
||||
-D MAX_CONTACTS=350
|
||||
-D MAX_GROUP_CHANNELS=40
|
||||
-D WIFI_DEBUG_LOGGING=1
|
||||
@@ -149,6 +150,7 @@ build_flags =
|
||||
; -D MESH_DEBUG=1
|
||||
build_src_filter = ${Station_G3_ESP32.build_src_filter}
|
||||
+<helpers/esp32/*.cpp>
|
||||
+<helpers/wifi/*.cpp>
|
||||
+<../examples/companion_radio/*.cpp>
|
||||
+<../examples/companion_radio/ui-new/*.cpp>
|
||||
lib_deps =
|
||||
|
||||
@@ -69,10 +69,6 @@ public:
|
||||
#ifdef PIN_3V3_ACC_EN
|
||||
digitalWrite(PIN_3V3_ACC_EN, LOW);
|
||||
#endif
|
||||
#ifdef SENSOR_EN
|
||||
digitalWrite(SENSOR_EN, LOW);
|
||||
#endif
|
||||
|
||||
// set led on and wait for button release before poweroff
|
||||
#ifdef LED_PIN
|
||||
digitalWrite(LED_PIN, HIGH);
|
||||
|
||||
@@ -72,7 +72,6 @@ float t1000e_get_temperature(void) {
|
||||
unsigned int ntc_v, vcc_v;
|
||||
|
||||
digitalWrite(PIN_3V3_EN, HIGH);
|
||||
digitalWrite(SENSOR_EN, HIGH);
|
||||
analogReference(AR_INTERNAL_3_0);
|
||||
analogReadResolution(12);
|
||||
delay(10);
|
||||
@@ -80,7 +79,6 @@ float t1000e_get_temperature(void) {
|
||||
vcc_v = (rail_v > NTC_REF_VCC) ? NTC_REF_VCC : rail_v;
|
||||
ntc_v = (1000.0 * AREF_VOLTAGE * analogRead(TEMP_SENSOR)) / 4096;
|
||||
digitalWrite(PIN_3V3_EN, LOW);
|
||||
digitalWrite(SENSOR_EN, LOW);
|
||||
|
||||
return get_heater_temperature(vcc_v, ntc_v);
|
||||
}
|
||||
@@ -90,13 +88,11 @@ uint32_t t1000e_get_light(void) {
|
||||
unsigned int lux_v = 0;
|
||||
|
||||
digitalWrite(PIN_3V3_EN, HIGH);
|
||||
digitalWrite(SENSOR_EN, HIGH);
|
||||
analogReference(AR_INTERNAL_3_0);
|
||||
analogReadResolution(12);
|
||||
delay(10);
|
||||
lux_v = 1000 * analogRead(LUX_SENSOR) * AREF_VOLTAGE / 4096;
|
||||
lux = get_light_lv(lux_v);
|
||||
digitalWrite(SENSOR_EN, LOW);
|
||||
digitalWrite(PIN_3V3_EN, LOW);
|
||||
|
||||
return lux;
|
||||
|
||||
+10
-38
@@ -2,6 +2,7 @@
|
||||
#include "t1000e_sensors.h"
|
||||
#include "target.h"
|
||||
#include <helpers/sensors/MicroNMEALocationProvider.h>
|
||||
#include <helpers/sensors/AirohaSleep.h>
|
||||
|
||||
T1000eBoard board;
|
||||
|
||||
@@ -81,56 +82,28 @@ mesh::LocalIdentity radio_new_identity() {
|
||||
|
||||
void T1000SensorManager::start_gps() {
|
||||
gps_active = true;
|
||||
//_nmea->begin();
|
||||
// this init sequence should be better
|
||||
// comes from seeed examples and deals with all gps pins
|
||||
pinMode(GPS_EN, OUTPUT);
|
||||
digitalWrite(GPS_EN, HIGH);
|
||||
delay(10);
|
||||
pinMode(GPS_VRTC_EN, OUTPUT);
|
||||
digitalWrite(GPS_VRTC_EN, HIGH);
|
||||
delay(10);
|
||||
|
||||
pinMode(GPS_RESET, OUTPUT);
|
||||
digitalWrite(GPS_RESET, HIGH);
|
||||
delay(10);
|
||||
digitalWrite(GPS_RESET, LOW);
|
||||
|
||||
pinMode(GPS_SLEEP_INT, OUTPUT);
|
||||
digitalWrite(GPS_SLEEP_INT, HIGH);
|
||||
pinMode(GPS_RTC_INT, OUTPUT);
|
||||
digitalWrite(GPS_RTC_INT, HIGH);
|
||||
delay(5);
|
||||
digitalWrite(GPS_RTC_INT, LOW);
|
||||
pinMode(GPS_RESETB, INPUT_PULLUP);
|
||||
}
|
||||
|
||||
void T1000SensorManager::sleep_gps() {
|
||||
gps_active = false;
|
||||
digitalWrite(GPS_VRTC_EN, HIGH);
|
||||
digitalWrite(GPS_EN, LOW);
|
||||
digitalWrite(GPS_RESET, HIGH);
|
||||
digitalWrite(GPS_SLEEP_INT, HIGH);
|
||||
digitalWrite(GPS_RTC_INT, LOW);
|
||||
pinMode(GPS_RESETB, OUTPUT);
|
||||
digitalWrite(GPS_RESETB, LOW);
|
||||
//_nmea->stop();
|
||||
}
|
||||
|
||||
void T1000SensorManager::stop_gps() {
|
||||
gps_active = false;
|
||||
digitalWrite(GPS_VRTC_EN, LOW);
|
||||
digitalWrite(GPS_VRTC_EN, HIGH); // keep GPS RTC alive for faster fix on wake
|
||||
digitalWrite(GPS_RTC_INT, LOW); // make sure this is LOW so we can pulse it to wake
|
||||
airohaEnterSleep(_nmea); // send command to put the GPS into RTC backup sleep
|
||||
digitalWrite(GPS_EN, LOW);
|
||||
digitalWrite(GPS_RESET, HIGH);
|
||||
digitalWrite(GPS_SLEEP_INT, HIGH);
|
||||
digitalWrite(GPS_RTC_INT, LOW);
|
||||
pinMode(GPS_RESETB, OUTPUT);
|
||||
digitalWrite(GPS_RESETB, LOW);
|
||||
//_nmea->stop();
|
||||
}
|
||||
|
||||
|
||||
bool T1000SensorManager::begin() {
|
||||
// init GPS
|
||||
Serial1.begin(115200);
|
||||
digitalWrite(GPS_RESET, HIGH);
|
||||
delay(10);
|
||||
digitalWrite(GPS_RESET, LOW);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -156,7 +129,6 @@ void T1000SensorManager::loop() {
|
||||
node_lat = ((double)_nmea->getLatitude())/1000000.;
|
||||
node_lon = ((double)_nmea->getLongitude())/1000000.;
|
||||
node_altitude = ((double)_nmea->getAltitude()) / 1000.0;
|
||||
//Serial.printf("lat %f lon %f\r\n", _lat, _lon);
|
||||
}
|
||||
next_gps_update = millis() + 1000;
|
||||
}
|
||||
@@ -176,7 +148,7 @@ const char* T1000SensorManager::getSettingValue(int i) const {
|
||||
bool T1000SensorManager::setSettingValue(const char* name, const char* value) {
|
||||
if (strcmp(name, "gps") == 0) {
|
||||
if (strcmp(value, "0") == 0) {
|
||||
sleep_gps(); // sleep for faster fix !
|
||||
stop_gps();
|
||||
} else {
|
||||
start_gps();
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ const uint32_t g_ADigitalPinMap[PINS_COUNT + 1] =
|
||||
1, // P0.01
|
||||
2, // P0.02, AIN0 BATTERY_PIN
|
||||
3, // P0.03
|
||||
4, // P0.04, SENSOR_EN
|
||||
4, // P0.04
|
||||
5, // P0.05, EXT_PWR_DETEC
|
||||
6, // P0.06, PIN_BUTTON1
|
||||
7, // P0.07, LORA_BUSY
|
||||
@@ -71,13 +71,12 @@ void initVariant()
|
||||
pinMode(LUX_SENSOR, INPUT);
|
||||
pinMode(EXT_CHRG_DETECT, INPUT);
|
||||
pinMode(EXT_PWR_DETECT, INPUT);
|
||||
pinMode(GPS_RESETB, INPUT);
|
||||
pinMode(GPS_RESETB, INPUT_PULLUP);
|
||||
pinMode(PIN_BUTTON1, INPUT);
|
||||
|
||||
pinMode(PIN_3V3_EN, OUTPUT);
|
||||
pinMode(PIN_3V3_ACC_EN, OUTPUT);
|
||||
pinMode(BUZZER_EN, OUTPUT);
|
||||
pinMode(SENSOR_EN, OUTPUT);
|
||||
pinMode(GPS_EN, OUTPUT);
|
||||
pinMode(GPS_RESET, OUTPUT);
|
||||
pinMode(GPS_VRTC_EN, OUTPUT);
|
||||
@@ -88,11 +87,10 @@ void initVariant()
|
||||
digitalWrite(PIN_3V3_EN, LOW);
|
||||
digitalWrite(PIN_3V3_ACC_EN, LOW);
|
||||
digitalWrite(BUZZER_EN, LOW);
|
||||
digitalWrite(SENSOR_EN, LOW);
|
||||
digitalWrite(GPS_EN, LOW);
|
||||
digitalWrite(GPS_RESET, LOW);
|
||||
digitalWrite(GPS_VRTC_EN, LOW);
|
||||
digitalWrite(GPS_SLEEP_INT, HIGH);
|
||||
digitalWrite(GPS_VRTC_EN, HIGH);
|
||||
digitalWrite(GPS_SLEEP_INT, LOW);
|
||||
digitalWrite(GPS_RTC_INT, LOW);
|
||||
digitalWrite(LED_PIN, LOW);
|
||||
}
|
||||
|
||||
@@ -120,7 +120,6 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Temp+Lux Sensor
|
||||
|
||||
#define SENSOR_EN (4) // P0.4
|
||||
#define TEMP_SENSOR (31) // P0.31/AIN7
|
||||
#define LUX_SENSOR (29) // P0.29/AIN5
|
||||
|
||||
|
||||
@@ -176,6 +176,7 @@ extends = ThinkNode_M2
|
||||
build_flags =
|
||||
${ThinkNode_M2.build_flags}
|
||||
-I examples/companion_radio/ui-new
|
||||
-D ENABLE_WIFI_INTERFACE
|
||||
-D MAX_CONTACTS=350
|
||||
-D MAX_GROUP_CHANNELS=40
|
||||
-D OFFLINE_QUEUE_SIZE=256
|
||||
@@ -184,6 +185,7 @@ build_flags =
|
||||
-D WIFI_PWD='"mypwd"'
|
||||
build_src_filter = ${ThinkNode_M2.build_src_filter}
|
||||
+<helpers/esp32/*.cpp>
|
||||
+<helpers/wifi/*.cpp>
|
||||
+<helpers/ui/MomentaryButton.cpp>
|
||||
+<helpers/ui/buzzer.cpp>
|
||||
+<../examples/companion_radio/*.cpp>
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
#include <Arduino.h>
|
||||
#include "ThinkNodeM4Board.h"
|
||||
#include <Wire.h>
|
||||
|
||||
#include <bluefruit.h>
|
||||
|
||||
void ThinkNodeM4Board::begin() {
|
||||
NRF52Board::begin();
|
||||
btn_prev_state = HIGH;
|
||||
|
||||
Wire.begin();
|
||||
battery_serial->begin(4800);
|
||||
|
||||
delay(10); // give sx1262 some time to power up
|
||||
}
|
||||
|
||||
uint16_t ThinkNodeM4Board::getBattMilliVolts() {
|
||||
int tentatives = 10;
|
||||
uint8_t data[5];
|
||||
uint8_t b;
|
||||
|
||||
if (battery_serial->available() < 10)
|
||||
return bat_level_mv;
|
||||
|
||||
// discard old data
|
||||
while (battery_serial->available() > 10)
|
||||
battery_serial->read();
|
||||
|
||||
// synchronize
|
||||
while((b = battery_serial->read()) != 0xFE) {
|
||||
if (tentatives-- == 0) {
|
||||
MESH_DEBUG_PRINTLN("Could not find battery frame start %x", b);
|
||||
return bat_level_mv;
|
||||
}
|
||||
}
|
||||
battery_serial->readBytes(data, 5);
|
||||
|
||||
if (data[4] != 0xFD) {
|
||||
MESH_DEBUG_PRINTLN("Invalid battery frame end %x", data[4]);
|
||||
return bat_level_mv;
|
||||
}
|
||||
bat_level_percent = data[0];
|
||||
//MESH_DEBUG_PRINTLN("Battery level %d\%", bat_level_percent);
|
||||
bat_level_mv = 2 * (data[1]*1000. + data[2]*10. + data[3]/10.);
|
||||
return bat_level_mv;
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
#pragma once
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <MeshCore.h>
|
||||
#include <helpers/NRF52Board.h>
|
||||
|
||||
class ThinkNodeM4Board : public NRF52BoardDCDC {
|
||||
protected:
|
||||
#if NRF52_POWER_MANAGEMENT
|
||||
void initiateShutdown(uint8_t reason) override;
|
||||
#endif
|
||||
uint8_t btn_prev_state;
|
||||
HardwareSerial * battery_serial;
|
||||
uint16_t bat_level_mv = 0;
|
||||
uint8_t bat_level_percent =0;
|
||||
|
||||
public:
|
||||
ThinkNodeM4Board() : NRF52Board("THINKNODE_M4_OTA"), battery_serial(&Serial2) {}
|
||||
void begin();
|
||||
uint16_t getBattMilliVolts() override;
|
||||
|
||||
#ifdef P_LORA_TX_LED
|
||||
void onBeforeTransmit() override {
|
||||
digitalWrite(P_LORA_TX_LED, LED_STATE_ON); // turn TX LED on
|
||||
}
|
||||
void onAfterTransmit() override {
|
||||
digitalWrite(P_LORA_TX_LED, !LED_STATE_ON); // turn TX LED off
|
||||
}
|
||||
#endif
|
||||
|
||||
const char* getManufacturerName() const override {
|
||||
return "Elecrow ThinkNode M4";
|
||||
}
|
||||
|
||||
int buttonStateChanged() {
|
||||
#ifdef BUTTON_PIN
|
||||
uint8_t v = digitalRead(BUTTON_PIN);
|
||||
if (v != btn_prev_state) {
|
||||
btn_prev_state = v;
|
||||
return (v == USER_BTN_PRESSED) ? 1 : -1;
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
void shutdownPeripherals() override {
|
||||
// shutdown common peripherals
|
||||
NRF52Board::shutdownPeripherals();
|
||||
|
||||
#ifdef LED_STATUS
|
||||
digitalWrite(LED_STATUS, HIGH);
|
||||
#endif
|
||||
#ifdef BUTTON_PIN
|
||||
while(!digitalRead(BUTTON_PIN));
|
||||
#endif
|
||||
#ifdef LED_STATUS
|
||||
digitalWrite(LED_STATUS, LOW);
|
||||
#endif
|
||||
|
||||
digitalWrite(LED_BAT1, LOW);
|
||||
digitalWrite(LED_BAT2, LOW);
|
||||
digitalWrite(LED_BAT3, LOW);
|
||||
digitalWrite(LED_BAT4, LOW);
|
||||
digitalWrite(LED_STATUS, LOW);
|
||||
digitalWrite(LED_PIN, LOW);
|
||||
|
||||
digitalWrite(PIN_PWR_EN, LOW);
|
||||
digitalWrite(I2C_POWER, !I2C_POWER_ACTIVE);
|
||||
digitalWrite(PIN_GPS_POWER, !GPS_POWER_ACTIVE);
|
||||
|
||||
#ifdef BUTTON_PIN
|
||||
nrf_gpio_cfg_sense_input(BUTTON_PIN, NRF_GPIO_PIN_NOPULL, NRF_GPIO_PIN_SENSE_LOW);
|
||||
#endif
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,130 @@
|
||||
[ThinkNode_M4]
|
||||
extends = nrf52_base
|
||||
board = thinknode_m4
|
||||
board_build.ldscript = boards/nrf52840_s140_v6.ld
|
||||
build_flags = ${nrf52_base.build_flags}
|
||||
-I src/helpers/nrf52
|
||||
-I lib/nrf52/s140_nrf52_6.1.1_API/include
|
||||
-I lib/nrf52/s140_nrf52_6.1.1_API/include/nrf52
|
||||
-I variants/thinknode_m4
|
||||
-I src/helpers/ui
|
||||
-D THINKNODE_M4
|
||||
-D PIN_USER_BTN=4
|
||||
-D PIN_STATUS_LED=LED_STATUS
|
||||
-D RADIO_CLASS=CustomLR1110
|
||||
-D WRAPPER_CLASS=CustomLR1110Wrapper
|
||||
-D LORA_TX_POWER=22
|
||||
-D RF_SWITCH_TABLE
|
||||
-D RX_BOOSTED_GAIN=true
|
||||
-D P_LORA_BUSY=26
|
||||
-D P_LORA_SCLK=6
|
||||
-D P_LORA_NSS=27
|
||||
-D P_LORA_DIO_1=12
|
||||
-D P_LORA_MISO=8
|
||||
-D P_LORA_MOSI=7
|
||||
-D P_LORA_RESET=40
|
||||
-D P_LORA_TX_LED=LED_TX
|
||||
-D LR11X0_DIO_AS_RF_SWITCH=true
|
||||
-D LR11X0_DIO3_TCXO_VOLTAGE=1.6
|
||||
-D ENV_INCLUDE_GPS=1
|
||||
; -D MESH_DEBUG=1
|
||||
; -D GPS_NMEA_DEBUG=1
|
||||
build_src_filter = ${nrf52_base.build_src_filter}
|
||||
+<helpers/*.cpp>
|
||||
+<../variants/thinknode_m4>
|
||||
+<helpers/sensors>
|
||||
debug_tool = stlink
|
||||
upload_protocol = nrfutil
|
||||
lib_deps= ${nrf52_base.lib_deps}
|
||||
|
||||
[env:ThinkNode_M4_repeater]
|
||||
extends = ThinkNode_M4
|
||||
build_flags = ${ThinkNode_M4.build_flags}
|
||||
-I examples/companion_radio/ui-orig
|
||||
-D ADVERT_NAME='"ThinkNode_M4 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 = ${ThinkNode_M4.build_src_filter}
|
||||
+<../examples/simple_repeater>
|
||||
lib_deps = ${ThinkNode_M4.lib_deps}
|
||||
stevemarple/MicroNMEA @ ^2.0.6
|
||||
|
||||
[env:ThinkNode_M4_room_server]
|
||||
extends = ThinkNode_M4
|
||||
build_flags = ${ThinkNode_M4.build_flags}
|
||||
-I examples/companion_radio/ui-orig
|
||||
-D ADVERT_NAME='"ThinkNode_M4 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
|
||||
-D RF_SWITCH_TABLE
|
||||
build_src_filter = ${ThinkNode_M4.build_src_filter}
|
||||
+<../examples/simple_room_server>
|
||||
lib_deps = ${ThinkNode_M4.lib_deps}
|
||||
stevemarple/MicroNMEA @ ^2.0.6
|
||||
|
||||
[env:ThinkNode_M4_companion_radio_usb]
|
||||
extends = ThinkNode_M4
|
||||
board_build.ldscript = boards/nrf52840_s140_v6_extrafs.ld
|
||||
board_upload.maximum_size = 708608
|
||||
build_flags = ${ThinkNode_M4.build_flags}
|
||||
-I examples/companion_radio/ui-orig
|
||||
-D MAX_CONTACTS=350
|
||||
-D MAX_GROUP_CHANNELS=40
|
||||
; -D MESH_PACKET_LOGGING=1
|
||||
; -D MESH_DEBUG=1
|
||||
-D OFFLINE_QUEUE_SIZE=256
|
||||
-D DISPLAY_CLASS=NullDisplayDriver
|
||||
-D PIN_BUZZER=23
|
||||
-D PIN_BUZZER_EN=36
|
||||
-D ENABLE_USB_INTERFACE
|
||||
build_src_filter = ${ThinkNode_M4.build_src_filter}
|
||||
+<helpers/ui/buzzer.cpp>
|
||||
+<helpers/ui/NullDisplayDriver.cpp>
|
||||
+<../examples/companion_radio/*.cpp>
|
||||
+<../examples/companion_radio/ui-orig/*.cpp>
|
||||
lib_deps = ${ThinkNode_M4.lib_deps}
|
||||
densaugeo/base64 @ ~1.4.0
|
||||
stevemarple/MicroNMEA @ ^2.0.6
|
||||
end2endzone/NonBlockingRTTTL@^1.3.0
|
||||
|
||||
[env:ThinkNode_M4_companion_radio_ble]
|
||||
extends = ThinkNode_M4
|
||||
board_build.ldscript = boards/nrf52840_s140_v6_extrafs.ld
|
||||
board_upload.maximum_size = 708608
|
||||
build_flags = ${ThinkNode_M4.build_flags}
|
||||
-I examples/companion_radio/ui-orig
|
||||
-D MAX_CONTACTS=350
|
||||
-D MAX_GROUP_CHANNELS=40
|
||||
-D BLE_PIN_CODE=123456
|
||||
-D BLE_TX_POWER=0
|
||||
; -D BLE_DEBUG_LOGGING=1
|
||||
; -D MESH_PACKET_LOGGING=1
|
||||
-D OFFLINE_QUEUE_SIZE=256
|
||||
-D DISPLAY_CLASS=NullDisplayDriver
|
||||
-D PIN_BUZZER=23
|
||||
-D PIN_BUZZER_EN=36
|
||||
build_src_filter = ${ThinkNode_M4.build_src_filter}
|
||||
+<helpers/nrf52/SerialBLEInterface.cpp>
|
||||
+<helpers/ui/buzzer.cpp>
|
||||
+<helpers/ui/NullDisplayDriver.cpp>
|
||||
+<../examples/companion_radio/*.cpp>
|
||||
+<../examples/companion_radio/ui-orig/*.cpp>
|
||||
lib_deps = ${ThinkNode_M4.lib_deps}
|
||||
densaugeo/base64 @ ~1.4.0
|
||||
stevemarple/MicroNMEA @ ^2.0.6
|
||||
end2endzone/NonBlockingRTTTL@^1.3.0
|
||||
|
||||
[env:ThinkNode_M4_kiss_modem]
|
||||
extends = ThinkNode_M4
|
||||
build_src_filter = ${ThinkNode_M4.build_src_filter}
|
||||
+<../examples/kiss_modem/>
|
||||
lib_deps = ${ThinkNode_M4.lib_deps}
|
||||
stevemarple/MicroNMEA @ ^2.0.6
|
||||
@@ -0,0 +1,84 @@
|
||||
#include <Arduino.h>
|
||||
#include "target.h"
|
||||
#include <helpers/sensors/MicroNMEALocationProvider.h>
|
||||
|
||||
ThinkNodeM4Board board;
|
||||
|
||||
RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY, SPI);
|
||||
|
||||
WRAPPER_CLASS radio_driver(radio, board);
|
||||
|
||||
VolatileRTCClock fallback_clock;
|
||||
AutoDiscoverRTCClock rtc_clock(fallback_clock);
|
||||
#ifdef ENV_INCLUDE_GPS
|
||||
MicroNMEALocationProvider nmea = MicroNMEALocationProvider(Serial1, &rtc_clock);
|
||||
EnvironmentSensorManager sensors = EnvironmentSensorManager(nmea);
|
||||
#else
|
||||
EnvironmentSensorManager sensors = EnvironmentSensorManager();
|
||||
#endif
|
||||
|
||||
#ifdef DISPLAY_CLASS
|
||||
NullDisplayDriver display;
|
||||
#endif
|
||||
|
||||
#ifndef LORA_CR
|
||||
#define LORA_CR 5
|
||||
#endif
|
||||
|
||||
#ifdef RF_SWITCH_TABLE
|
||||
static const uint32_t rfswitch_dios[Module::RFSWITCH_MAX_PINS] = {
|
||||
RADIOLIB_LR11X0_DIO5,
|
||||
RADIOLIB_LR11X0_DIO6,
|
||||
RADIOLIB_NC,
|
||||
RADIOLIB_NC,
|
||||
RADIOLIB_NC
|
||||
};
|
||||
|
||||
static const Module::RfSwitchMode_t rfswitch_table[] = {
|
||||
// mode DIO5 DIO6
|
||||
{ LR11x0::MODE_STBY, {LOW , LOW }},
|
||||
{ LR11x0::MODE_RX, {HIGH, LOW }},
|
||||
{ LR11x0::MODE_TX, {HIGH, HIGH }},
|
||||
{ LR11x0::MODE_TX_HP, {LOW , HIGH }},
|
||||
{ LR11x0::MODE_TX_HF, {LOW , LOW }},
|
||||
{ LR11x0::MODE_GNSS, {LOW , LOW }},
|
||||
{ LR11x0::MODE_WIFI, {LOW , LOW }},
|
||||
END_OF_MODE_TABLE,
|
||||
};
|
||||
#endif
|
||||
|
||||
bool radio_init() {
|
||||
rtc_clock.begin(Wire);
|
||||
|
||||
#ifdef LR11X0_DIO3_TCXO_VOLTAGE
|
||||
float tcxo = LR11X0_DIO3_TCXO_VOLTAGE;
|
||||
#else
|
||||
float tcxo = 1.6f;
|
||||
#endif
|
||||
|
||||
SPI.setPins(P_LORA_MISO, P_LORA_SCLK, P_LORA_MOSI);
|
||||
SPI.begin();
|
||||
int status = radio.begin(LORA_FREQ, LORA_BW, LORA_SF, LORA_CR, RADIOLIB_LR11X0_LORA_SYNC_WORD_PRIVATE, LORA_TX_POWER, 16, tcxo);
|
||||
if (status != RADIOLIB_ERR_NONE) {
|
||||
Serial.print("ERROR: radio init failed: ");
|
||||
Serial.println(status);
|
||||
return false; // fail
|
||||
}
|
||||
|
||||
radio.setCRC(2);
|
||||
radio.explicitHeader();
|
||||
|
||||
#ifdef RF_SWITCH_TABLE
|
||||
radio.setRfSwitchTable(rfswitch_dios, rfswitch_table);
|
||||
#endif
|
||||
#ifdef RX_BOOSTED_GAIN
|
||||
radio.setRxBoostedGainMode(RX_BOOSTED_GAIN);
|
||||
#endif
|
||||
|
||||
return true; // success
|
||||
}
|
||||
|
||||
mesh::LocalIdentity radio_new_identity() {
|
||||
RadioNoiseListener rng(radio);
|
||||
return mesh::LocalIdentity(&rng); // create new random identity
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
#pragma once
|
||||
|
||||
#define RADIOLIB_STATIC_ONLY 1
|
||||
#include <RadioLib.h>
|
||||
#include <helpers/radiolib/RadioLibWrappers.h>
|
||||
#include "ThinkNodeM4Board.h"
|
||||
#include <helpers/radiolib/CustomLR1110Wrapper.h>
|
||||
#include <helpers/ArduinoHelpers.h>
|
||||
#include <helpers/sensors/EnvironmentSensorManager.h>
|
||||
#include <helpers/sensors/LocationProvider.h>
|
||||
#include <helpers/AutoDiscoverRTCClock.h>
|
||||
#ifdef DISPLAY_CLASS
|
||||
#include "NullDisplayDriver.h"
|
||||
#endif
|
||||
|
||||
#ifdef DISPLAY_CLASS
|
||||
extern NullDisplayDriver display;
|
||||
#endif
|
||||
|
||||
extern ThinkNodeM4Board board;
|
||||
extern WRAPPER_CLASS radio_driver;
|
||||
extern AutoDiscoverRTCClock rtc_clock;
|
||||
extern EnvironmentSensorManager sensors;
|
||||
|
||||
bool radio_init();
|
||||
mesh::LocalIdentity radio_new_identity();
|
||||
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* variant.cpp
|
||||
* Copyright (C) 2023 Seeed K.K.
|
||||
* MIT License
|
||||
*/
|
||||
|
||||
#include "variant.h"
|
||||
#include "wiring_constants.h"
|
||||
#include "wiring_digital.h"
|
||||
|
||||
const uint32_t g_ADigitalPinMap[] =
|
||||
{
|
||||
0xff, // P0.00 - LFXO (do not use)
|
||||
0xff, // P0.01 - LFXO (do not use)
|
||||
2, // P0.02
|
||||
3, // P0.03
|
||||
4, // P0.04
|
||||
5, // P0.05
|
||||
6, // P0.06
|
||||
7, // P0.07
|
||||
8, // P0.08
|
||||
9, // P0.09
|
||||
10, // P0.10
|
||||
11, // P0.11
|
||||
12, // P0.12
|
||||
13, // P0.13
|
||||
14, // P0.14
|
||||
15, // P0.15
|
||||
16, // P0.16
|
||||
17, // P0.17
|
||||
18, // P0.18
|
||||
19, // P0.19
|
||||
20, // P0.20
|
||||
21, // P0.21
|
||||
22, // P0.22
|
||||
23, // P0.23
|
||||
24, // P0.24
|
||||
25, // P0.25
|
||||
26, // P0.26
|
||||
27, // P0.27
|
||||
28, // P0.28
|
||||
29, // P0.29
|
||||
30, // P0.30
|
||||
31, // P0.31
|
||||
32, // P1.00
|
||||
33, // P1.01
|
||||
34, // P1.02
|
||||
35, // P1.03
|
||||
36, // P1.04
|
||||
37, // P1.05
|
||||
38, // P1.06
|
||||
39, // P1.07
|
||||
40, // P1.08
|
||||
41, // P1.09
|
||||
42, // P1.10
|
||||
43, // P1.11
|
||||
44, // P1.12
|
||||
45, // P1.13
|
||||
46, // P1.14
|
||||
47, // P1.15
|
||||
};
|
||||
|
||||
void initVariant()
|
||||
{
|
||||
/* TODO */
|
||||
pinMode(PIN_PWR_EN, OUTPUT);
|
||||
pinMode(I2C_POWER, OUTPUT);
|
||||
|
||||
digitalWrite(PIN_PWR_EN, HIGH);
|
||||
digitalWrite(I2C_POWER, I2C_POWER_ACTIVE);
|
||||
|
||||
pinMode(LED_STATUS, OUTPUT);
|
||||
pinMode(LED_PIN, OUTPUT);
|
||||
pinMode(LED_BAT1, OUTPUT);
|
||||
pinMode(LED_BAT2, OUTPUT);
|
||||
pinMode(LED_BAT3, OUTPUT);
|
||||
pinMode(LED_BAT4, OUTPUT);
|
||||
|
||||
digitalWrite(LED_BAT1, LOW);
|
||||
digitalWrite(LED_BAT2, LOW);
|
||||
digitalWrite(LED_BAT3, LOW);
|
||||
digitalWrite(LED_BAT4, LOW);
|
||||
digitalWrite(LED_STATUS, LOW);
|
||||
digitalWrite(LED_PIN, LOW);
|
||||
|
||||
pinMode(BUTTON_PIN, INPUT_PULLUP);
|
||||
|
||||
pinMode(PIN_GPS_POWER, OUTPUT);
|
||||
pinMode(PIN_GPS_EN, OUTPUT);
|
||||
|
||||
// Power on gps but in standby
|
||||
digitalWrite(PIN_GPS_EN, !GPS_EN_ACTIVE);
|
||||
digitalWrite(PIN_GPS_POWER, GPS_POWER_ACTIVE);
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
* variant.h
|
||||
* Copyright (C) 2023 Seeed K.K.
|
||||
* MIT License
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "WVariant.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Low frequency clock source
|
||||
|
||||
#define USE_LFXO // 32.768 kHz crystal oscillator
|
||||
#define VARIANT_MCK (64000000ul)
|
||||
// #define USE_LFRC // 32.768 kHz RC oscillator
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Number of pins
|
||||
|
||||
#define PINS_COUNT (48)
|
||||
#define NUM_DIGITAL_PINS (48)
|
||||
#define NUM_ANALOG_INPUTS (1)
|
||||
#define NUM_ANALOG_OUTPUTS (0)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Power
|
||||
|
||||
#define NRF_APM // detect usb power
|
||||
|
||||
#define EXT_CHRG_DETECT (38)
|
||||
// Power to radio
|
||||
#define PIN_PWR_EN (11)
|
||||
|
||||
// I2C bus power
|
||||
#define I2C_POWER (32)
|
||||
#define I2C_POWER_ACTIVE LOW
|
||||
|
||||
#define PIN_BAT_RX (5)
|
||||
#define PIN_BAT_TX (30)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// UART pin definition
|
||||
|
||||
#define PIN_SERIAL1_RX PIN_GPS_TX
|
||||
#define PIN_SERIAL1_TX PIN_GPS_RX
|
||||
|
||||
#define PIN_SERIAL2_RX PIN_BAT_TX
|
||||
#define PIN_SERIAL2_TX PIN_BAT_RX
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// I2C pin definition
|
||||
|
||||
#define HAS_WIRE (1)
|
||||
#define WIRE_INTERFACES_COUNT (1)
|
||||
|
||||
#define PIN_WIRE_SDA (23)
|
||||
#define PIN_WIRE_SCL (25)
|
||||
#define I2C_NO_RESCAN
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// SPI pin definition
|
||||
|
||||
#define SPI_INTERFACES_COUNT (1)
|
||||
|
||||
#define PIN_SPI_MISO (8)
|
||||
#define PIN_SPI_MOSI (7)
|
||||
#define PIN_SPI_SCK (6)
|
||||
#define PIN_SPI_NSS (27)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Builtin LEDs
|
||||
|
||||
#define LED_BLUE (-1) // disable blue led
|
||||
#define LED_STATUS (13) // blue
|
||||
#define LED_PIN (41) // red
|
||||
#define LED_TX LED_PIN
|
||||
#define LED_BUILTIN LED_BLUE
|
||||
#define LED_STATE_ON HIGH
|
||||
|
||||
#define LED_BAT1 (15)
|
||||
#define LED_BAT2 (17)
|
||||
#define LED_BAT3 (34)
|
||||
#define LED_BAT4 (36)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Builtin buttons
|
||||
|
||||
#define PIN_BUTTON1 (4)
|
||||
#define BUTTON_PIN PIN_BUTTON1
|
||||
#define USER_BTN_PRESSED LOW
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// GPS
|
||||
|
||||
#define HAS_GPS 1
|
||||
#define GPS_BAUDRATE 9600
|
||||
#define PIN_GPS_RX (44)
|
||||
#define PIN_GPS_TX (46)
|
||||
|
||||
#define PIN_GPS_POWER (14)
|
||||
#define GPS_POWER_ACTIVE LOW
|
||||
#define PIN_GPS_EN (43)
|
||||
#define GPS_EN_ACTIVE LOW
|
||||
#define PIN_GPS_RESET (3)
|
||||
#define GPS_RESET_ACTIVE HIGH
|
||||
@@ -190,6 +190,7 @@ extends = ThinkNode_M5
|
||||
build_flags =
|
||||
${ThinkNode_M5.build_flags}
|
||||
-I examples/companion_radio/ui-new
|
||||
-D ENABLE_WIFI_INTERFACE
|
||||
-D MAX_CONTACTS=350
|
||||
-D MAX_GROUP_CHANNELS=40
|
||||
-D OFFLINE_QUEUE_SIZE=256
|
||||
@@ -198,6 +199,7 @@ build_flags =
|
||||
-D WIFI_PWD='"mypwd"'
|
||||
build_src_filter = ${ThinkNode_M5.build_src_filter}
|
||||
+<helpers/esp32/*.cpp>
|
||||
+<helpers/wifi/*.cpp>
|
||||
+<helpers/ui/MomentaryButton.cpp>
|
||||
+<../examples/companion_radio/*.cpp>
|
||||
+<../examples/companion_radio/ui-new/*.cpp>
|
||||
|
||||
@@ -15,6 +15,9 @@ void ThinkNodeM6Board::begin() {
|
||||
digitalWrite(P_LORA_TX_LED, LOW);
|
||||
#endif
|
||||
|
||||
pinMode(EXT_PWR_DETECT, INPUT);
|
||||
pinMode(EXT_CHRG_DETECT, INPUT);
|
||||
|
||||
delay(10); // give sx1262 some time to power up
|
||||
}
|
||||
|
||||
|
||||
@@ -36,6 +36,35 @@ public:
|
||||
return "Elecrow ThinkNode M6";
|
||||
}
|
||||
|
||||
bool hasUsbPowerDetect() const override { return true; }
|
||||
|
||||
bool isUsbPowered() override {
|
||||
// P0.13 is the dedicated USB / external power-detect line on the M6 PCB
|
||||
// (same pin the Meshtastic M6 variant uses for USB detection).
|
||||
return digitalRead(EXT_PWR_DETECT) == EXT_PWR_DETECT_VALUE;
|
||||
}
|
||||
|
||||
bool hasSolarChargerDetect() const override { return true; }
|
||||
|
||||
bool isSolarChargerActive() override {
|
||||
// P0.15 is the active-low solar-charger status line. It reports the
|
||||
// charger's state, not photovoltaic voltage or current.
|
||||
return digitalRead(EXT_CHRG_DETECT) == EXT_CHRG_DETECT_VALUE;
|
||||
}
|
||||
|
||||
bool isExternalPowered() override {
|
||||
if (isUsbPowered() || isSolarChargerActive()) {
|
||||
return true;
|
||||
}
|
||||
return NRF52Board::isExternalPowered();
|
||||
}
|
||||
|
||||
bool isChargerActive() override {
|
||||
// Preserve a generic charging indication while also exposing both
|
||||
// source-specific states (USB / solar) separately through the CLI.
|
||||
return isSolarChargerActive() || isUsbPowered();
|
||||
}
|
||||
|
||||
void powerOff() override {
|
||||
|
||||
// turn off all leds, sd_power_system_off will not do this for us
|
||||
|
||||
@@ -29,6 +29,12 @@
|
||||
|
||||
#define AREF_VOLTAGE (3.0)
|
||||
|
||||
// External power and charger status lines.
|
||||
#define EXT_PWR_DETECT (13)
|
||||
#define EXT_PWR_DETECT_VALUE HIGH
|
||||
#define EXT_CHRG_DETECT (15)
|
||||
#define EXT_CHRG_DETECT_VALUE LOW
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Number of pins
|
||||
|
||||
|
||||
@@ -98,11 +98,13 @@ build_flags =
|
||||
-D MAX_GROUP_CHANNELS=40
|
||||
-D BLE_PIN_CODE=123456
|
||||
-D OFFLINE_QUEUE_SIZE=256
|
||||
-D ENABLE_WIFI_INTERFACE
|
||||
; -D BLE_DEBUG_LOGGING=1
|
||||
; -D MESH_PACKET_LOGGING=1
|
||||
build_src_filter = ${ThinkNode_M7.build_src_filter}
|
||||
${ThinkNode_M7_ethernet.build_src_filter}
|
||||
+<helpers/esp32/*.cpp>
|
||||
+<helpers/wifi/*.cpp>
|
||||
+<helpers/ui/MomentaryButton.cpp>
|
||||
+<helpers/ui/NullDisplayDriver.cpp>
|
||||
+<../examples/companion_radio/*.cpp>
|
||||
@@ -135,6 +137,7 @@ extends = ThinkNode_M7
|
||||
build_flags =
|
||||
${ThinkNode_M7.build_flags}
|
||||
-I examples/companion_radio/ui-orig
|
||||
-D ENABLE_WIFI_INTERFACE
|
||||
-D MAX_CONTACTS=350
|
||||
-D MAX_GROUP_CHANNELS=40
|
||||
-D DISPLAY_CLASS=NullDisplayDriver
|
||||
@@ -145,6 +148,7 @@ build_flags =
|
||||
; -D MESH_PACKET_LOGGING=1
|
||||
build_src_filter = ${ThinkNode_M7.build_src_filter}
|
||||
+<helpers/esp32/*.cpp>
|
||||
+<helpers/wifi/*.cpp>
|
||||
+<helpers/ui/MomentaryButton.cpp>
|
||||
+<helpers/ui/NullDisplayDriver.cpp>
|
||||
+<../examples/companion_radio/*.cpp>
|
||||
@@ -167,6 +171,7 @@ build_src_filter = ${ThinkNode_M7.build_src_filter}
|
||||
${ThinkNode_M7_ethernet.build_src_filter}
|
||||
+<helpers/esp32/*.cpp>
|
||||
+<helpers/ui/MomentaryButton.cpp>
|
||||
+<helpers/ui/NullDisplayDriver.cpp>
|
||||
+<../examples/companion_radio/*.cpp>
|
||||
+<../examples/companion_radio/ui-orig/*.cpp>
|
||||
lib_deps = ${ThinkNode_M7.lib_deps}
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
#include <Arduino.h>
|
||||
#include <Wire.h>
|
||||
|
||||
#include "ThinkNodeM8Board.h"
|
||||
|
||||
#ifdef THINKNODE_M8
|
||||
|
||||
void ThinkNodeM8Board::begin() {
|
||||
NRF52Board::begin();
|
||||
|
||||
Wire.begin();
|
||||
|
||||
#ifdef P_LORA_TX_LED
|
||||
pinMode(P_LORA_TX_LED, OUTPUT);
|
||||
digitalWrite(P_LORA_TX_LED, LOW);
|
||||
#endif
|
||||
|
||||
pinMode(SX126X_POWER_EN, OUTPUT);
|
||||
digitalWrite(SX126X_POWER_EN, HIGH);
|
||||
delay(10); // give sx1262 some time to power up
|
||||
}
|
||||
|
||||
uint16_t ThinkNodeM8Board::getBattMilliVolts() {
|
||||
int adcvalue = 0;
|
||||
|
||||
digitalWrite(ADC_EN, HIGH);
|
||||
analogReference(AR_INTERNAL_2_4);
|
||||
analogReadResolution(12);
|
||||
delay(10);
|
||||
|
||||
// ADC range is 0..3000mV and resolution is 12-bit (0..4095)
|
||||
adcvalue = analogRead(PIN_VBAT_READ);
|
||||
// Convert the raw value to compensated mv, taking the resistor-
|
||||
// divider into account (providing the actual LIPO voltage)
|
||||
digitalWrite(ADC_EN, LOW);
|
||||
return (uint16_t)((float)adcvalue * REAL_VBAT_MV_PER_LSB);
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,50 @@
|
||||
#pragma once
|
||||
|
||||
#include <MeshCore.h>
|
||||
#include <Arduino.h>
|
||||
#include <helpers/NRF52Board.h>
|
||||
|
||||
// built-ins
|
||||
#define VBAT_MV_PER_LSB (0.5859375F) // 2.4V ADC range and 12-bit ADC resolution = 2400mV/4096
|
||||
|
||||
#define VBAT_DIVIDER (0.57F) // 150K + 150K voltage divider on VBAT
|
||||
#define VBAT_DIVIDER_COMP (1.75F) // Compensation factor for the VBAT divider
|
||||
|
||||
#define PIN_VBAT_READ (4)
|
||||
#define REAL_VBAT_MV_PER_LSB (VBAT_DIVIDER_COMP * VBAT_MV_PER_LSB)
|
||||
|
||||
class ThinkNodeM8Board : public NRF52Board {
|
||||
public:
|
||||
ThinkNodeM8Board() : NRF52Board("THINKNODE_M8_OTA") {}
|
||||
void begin();
|
||||
uint16_t getBattMilliVolts() override;
|
||||
|
||||
#if defined(P_LORA_TX_LED)
|
||||
void onBeforeTransmit() override {
|
||||
digitalWrite(P_LORA_TX_LED, HIGH); // turn TX LED on
|
||||
}
|
||||
void onAfterTransmit() override {
|
||||
digitalWrite(P_LORA_TX_LED, LOW); // turn TX LED off
|
||||
}
|
||||
#endif
|
||||
|
||||
const char* getManufacturerName() const override {
|
||||
return "Elecrow ThinkNode-M8";
|
||||
}
|
||||
|
||||
void shutdownPeripherals() override {
|
||||
// power off board
|
||||
NRF52Board::shutdownPeripherals();
|
||||
|
||||
// make sure every gate is closed
|
||||
digitalWrite(DISP_EN, LOW);
|
||||
digitalWrite(PIN_PWR_EN, LOW);
|
||||
digitalWrite(PIN_GPS_EN, LOW);
|
||||
digitalWrite(SX126X_ANT_SW, LOW);
|
||||
digitalWrite(ADC_EN, LOW);
|
||||
|
||||
#ifdef PIN_BUTTON1 // Use BTN to go out of sleep
|
||||
nrf_gpio_cfg_sense_input(PIN_BUTTON1, NRF_GPIO_PIN_PULLUP, NRF_GPIO_PIN_SENSE_LOW);
|
||||
#endif
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,160 @@
|
||||
[ThinkNode_M8]
|
||||
extends = nrf52_base
|
||||
board = thinknode_m8
|
||||
board_build.ldscript = boards/nrf52840_s140_v6.ld
|
||||
build_flags = ${nrf52_base.build_flags}
|
||||
-I src/helpers/nrf52
|
||||
-I lib/nrf52/s140_nrf52_6.1.1_API/include
|
||||
-I lib/nrf52/s140_nrf52_6.1.1_API/include/nrf52
|
||||
-I variants/thinknode_m8
|
||||
-D THINKNODE_M8=1
|
||||
-D RADIO_CLASS=CustomSX1262
|
||||
-D WRAPPER_CLASS=CustomSX1262Wrapper
|
||||
-D P_LORA_DIO_1=25
|
||||
-D P_LORA_DIO_2=32
|
||||
-D P_LORA_NSS=21
|
||||
-D P_LORA_RESET=24
|
||||
-D P_LORA_BUSY=32 # DIO2
|
||||
-D P_LORA_SCLK=19
|
||||
-D P_LORA_MISO=22
|
||||
-D P_LORA_MOSI=20
|
||||
-D UI_SHOW_CLOCK=1
|
||||
-D UI_HAS_ROTARY_INPUT=1
|
||||
-D UI_HAS_NAV_INPUT=1
|
||||
-D UI_RECENT_LIST_SIZE=9
|
||||
-D UI_MSG_PREVIEW_SIZE=165
|
||||
-D EINK_MAX_PARTIAL_REFRESH=60
|
||||
-D EINK_DISPLAY_MODEL=GxEPD2_154_D67
|
||||
; -D EINK_DISPLAY_MODEL=GxEPD2_154_GDEY0154D67
|
||||
; -D EINK_DISPLAY_MODEL=GxEPD2_150_BN
|
||||
-D EINK_SCALE_X=1.5625f
|
||||
-D EINK_SCALE_Y=1.5625f
|
||||
-D EINK_X_OFFSET=0
|
||||
-D EINK_Y_OFFSET=10
|
||||
-D DISABLE_DIAGNOSTIC_OUTPUT
|
||||
-D SX126X_POWER_EN=37
|
||||
-D SX126X_DIO2_AS_RF_SWITCH=true
|
||||
-D SX126X_DIO3_TCXO_VOLTAGE=3.3
|
||||
-D SX126X_CURRENT_LIMIT=140
|
||||
-D SX126X_RX_BOOSTED_GAIN=1
|
||||
-D LORA_TX_POWER=22
|
||||
build_src_filter = ${nrf52_base.build_src_filter}
|
||||
+<helpers/*.cpp>
|
||||
+<ThinkNodeM8Board.cpp>
|
||||
+<../variants/thinknode_m8>
|
||||
lib_deps =
|
||||
${nrf52_base.lib_deps}
|
||||
stevemarple/MicroNMEA @ ^2.0.6
|
||||
debug_tool = jlink
|
||||
upload_protocol = nrfutil
|
||||
|
||||
[env:ThinkNode_M8_repeater]
|
||||
extends = ThinkNode_M8
|
||||
build_flags =
|
||||
${ThinkNode_M8.build_flags}
|
||||
-D ADVERT_NAME='"ThinkNode 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 = ${ThinkNode_M8.build_src_filter}
|
||||
+<../examples/simple_repeater/*.cpp>
|
||||
lib_deps =
|
||||
${ThinkNode_M8.lib_deps}
|
||||
|
||||
[env:ThinkNode_M8_room_server]
|
||||
extends = ThinkNode_M8
|
||||
build_flags =
|
||||
${ThinkNode_M8.build_flags}
|
||||
-D ADVERT_NAME='"ThinkNode 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
|
||||
build_src_filter = ${ThinkNode_M8.build_src_filter}
|
||||
+<../examples/simple_room_server/*.cpp>
|
||||
lib_deps =
|
||||
${ThinkNode_M8.lib_deps}
|
||||
|
||||
[env:ThinkNode_M8_companion_radio_ble]
|
||||
extends = ThinkNode_M8
|
||||
board_build.ldscript = boards/nrf52840_s140_v6_extrafs.ld
|
||||
board_upload.maximum_size = 712704
|
||||
build_flags =
|
||||
${ThinkNode_M8.build_flags}
|
||||
-I src/helpers/ui
|
||||
-I examples/companion_radio/ui-new
|
||||
-D MAX_CONTACTS=350
|
||||
-D MAX_GROUP_CHANNELS=40
|
||||
-D BLE_PIN_CODE=123456
|
||||
# -D BLE_DEBUG_LOGGING=1
|
||||
-D DISPLAY_ROTATION=4
|
||||
-D DISPLAY_CLASS=GxEPDDisplay
|
||||
-D BACKLIGHT_BTN=PIN_BUTTON2
|
||||
-D AUTO_OFF_MILLIS=0
|
||||
-D OFFLINE_QUEUE_SIZE=256
|
||||
-D PIN_BUZZER=33
|
||||
-D AUTO_SHUTDOWN_MILLIVOLTS=3300
|
||||
-D QSPIFLASH=1
|
||||
-D ENV_INCLUDE_GPS=1
|
||||
; -D GPS_NMEA_DEBUG=1
|
||||
; -D MESH_PACKET_LOGGING=1
|
||||
-D MESH_DEBUG=1
|
||||
build_src_filter = ${ThinkNode_M8.build_src_filter}
|
||||
+<helpers/nrf52/SerialBLEInterface.cpp>
|
||||
+<helpers/ui/GxEPDDisplay.cpp>
|
||||
+<helpers/ui/buzzer.cpp>
|
||||
+<helpers/ui/MomentaryButton.cpp>
|
||||
+<helpers/ui/RotaryInputGPIO.cpp>
|
||||
+<helpers/sensors/EnvironmentSensorManager.cpp>
|
||||
+<../examples/companion_radio/*.cpp>
|
||||
+<../examples/companion_radio/ui-new/*.cpp>
|
||||
lib_deps =
|
||||
${ThinkNode_M8.lib_deps}
|
||||
densaugeo/base64 @ ~1.4.0
|
||||
zinggjm/GxEPD2 @ 1.6.9
|
||||
bakercp/CRC32 @ ^2.0.0
|
||||
end2endzone/NonBlockingRTTTL@^1.3.0
|
||||
|
||||
[env:ThinkNode_M8_companion_radio_usb]
|
||||
extends = ThinkNode_M8
|
||||
board_build.ldscript = boards/nrf52840_s140_v6_extrafs.ld
|
||||
board_upload.maximum_size = 712704
|
||||
build_flags =
|
||||
${ThinkNode_M8.build_flags}
|
||||
-I src/helpers/ui
|
||||
-I examples/companion_radio/ui-new
|
||||
-D MAX_CONTACTS=350
|
||||
-D MAX_GROUP_CHANNELS=40
|
||||
-D DISPLAY_ROTATION=4
|
||||
-D QSPIFLASH=1
|
||||
-D DISPLAY_CLASS=GxEPDDisplay
|
||||
-D BACKLIGHT_BTN=PIN_BUTTON2
|
||||
-D AUTO_OFF_MILLIS=0
|
||||
-D OFFLINE_QUEUE_SIZE=256
|
||||
-D PIN_BUZZER=6
|
||||
-D AUTO_SHUTDOWN_MILLIVOLTS=3300
|
||||
-D ENABLE_USB_INTERFACE
|
||||
build_src_filter = ${ThinkNode_M8.build_src_filter}
|
||||
+<helpers/ui/GxEPDDisplay.cpp>
|
||||
+<helpers/ui/buzzer.cpp>
|
||||
+<helpers/ui/MomentaryButton.cpp>
|
||||
+<helpers/ui/RotaryInputGPIO.cpp>
|
||||
+<helpers/sensors/EnvironmentSensorManager.cpp>
|
||||
+<../examples/companion_radio/*.cpp>
|
||||
+<../examples/companion_radio/ui-new/*.cpp>
|
||||
lib_deps =
|
||||
${ThinkNode_M8.lib_deps}
|
||||
densaugeo/base64 @ ~1.4.0
|
||||
zinggjm/GxEPD2 @ 1.6.2
|
||||
bakercp/CRC32 @ ^2.0.0
|
||||
end2endzone/NonBlockingRTTTL@^1.3.0
|
||||
|
||||
[env:ThinkNode_M8_kiss_modem]
|
||||
extends = ThinkNode_M8
|
||||
build_src_filter = ${ThinkNode_M8.build_src_filter}
|
||||
+<../examples/kiss_modem/>
|
||||
@@ -0,0 +1,36 @@
|
||||
#include <Arduino.h>
|
||||
#include "target.h"
|
||||
#include <helpers/ArduinoHelpers.h>
|
||||
#include <helpers/sensors/MicroNMEALocationProvider.h>
|
||||
#include <Wire.h>
|
||||
|
||||
ThinkNodeM8Board board;
|
||||
|
||||
RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY, SPI);
|
||||
|
||||
WRAPPER_CLASS radio_driver(radio, board);
|
||||
|
||||
VolatileRTCClock fallback_clock;
|
||||
AutoDiscoverRTCClock rtc_clock(fallback_clock);
|
||||
#ifdef ENV_INCLUDE_GPS
|
||||
MicroNMEALocationProvider nmea = MicroNMEALocationProvider(Serial1, &rtc_clock);
|
||||
EnvironmentSensorManager sensors = EnvironmentSensorManager(nmea);
|
||||
#else
|
||||
EnvironmentSensorManager sensors = EnvironmentSensorManager();
|
||||
#endif
|
||||
|
||||
#ifdef DISPLAY_CLASS
|
||||
DISPLAY_CLASS display;
|
||||
MomentaryButton user_btn(PIN_USER_BTN, 1000, true);
|
||||
RotaryInputGPIO rotary_input(PIN_BUTTON1_A, PIN_BUTTON1_B);
|
||||
#endif
|
||||
|
||||
bool radio_init() {
|
||||
rtc_clock.begin(Wire);
|
||||
return radio.std_init(&SPI);
|
||||
}
|
||||
|
||||
mesh::LocalIdentity radio_new_identity() {
|
||||
RadioNoiseListener rng(radio);
|
||||
return mesh::LocalIdentity(&rng); // create new random identity
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
#pragma once
|
||||
|
||||
#define RADIOLIB_STATIC_ONLY 1
|
||||
#include <RadioLib.h>
|
||||
#include <helpers/radiolib/RadioLibWrappers.h>
|
||||
#include <ThinkNodeM8Board.h>
|
||||
#include <helpers/radiolib/CustomSX1262Wrapper.h>
|
||||
#include <helpers/AutoDiscoverRTCClock.h>
|
||||
#include <helpers/SensorManager.h>
|
||||
#include <helpers/sensors/LocationProvider.h>
|
||||
#include <helpers/sensors/EnvironmentSensorManager.h>
|
||||
#ifdef DISPLAY_CLASS
|
||||
#include <helpers/ui/GxEPDDisplay.h>
|
||||
#include <helpers/ui/RotaryInputGPIO.h>
|
||||
#include <helpers/ui/MomentaryButton.h>
|
||||
#endif
|
||||
|
||||
extern ThinkNodeM8Board board;
|
||||
extern WRAPPER_CLASS radio_driver;
|
||||
extern AutoDiscoverRTCClock rtc_clock;
|
||||
extern EnvironmentSensorManager sensors;
|
||||
|
||||
#ifdef DISPLAY_CLASS
|
||||
extern DISPLAY_CLASS display;
|
||||
extern MomentaryButton user_btn;
|
||||
extern RotaryInputGPIO rotary_input;
|
||||
#endif
|
||||
|
||||
bool radio_init();
|
||||
mesh::LocalIdentity radio_new_identity();
|
||||
@@ -0,0 +1,39 @@
|
||||
#include "variant.h"
|
||||
#include "wiring_constants.h"
|
||||
#include "wiring_digital.h"
|
||||
|
||||
const int MISO = PIN_SPI1_MISO;
|
||||
const int MOSI = PIN_SPI1_MOSI;
|
||||
const int SCK = PIN_SPI1_SCK;
|
||||
|
||||
const uint32_t g_ADigitalPinMap[] = {
|
||||
0xff, 0xff, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
|
||||
14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
|
||||
27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
|
||||
40, 41, 42, 43, 44, 45, 46, 47
|
||||
};
|
||||
|
||||
void initVariant() {
|
||||
pinMode(PIN_PWR_EN, OUTPUT);
|
||||
digitalWrite(PIN_PWR_EN, HIGH);
|
||||
pinMode(DISP_EN, OUTPUT);
|
||||
digitalWrite(DISP_EN, HIGH);
|
||||
|
||||
pinMode(PIN_BUTTON1, INPUT_PULLDOWN);
|
||||
pinMode(PIN_BUTTON1_A, INPUT_PULLDOWN);
|
||||
pinMode(PIN_BUTTON1_B, INPUT_PULLDOWN);
|
||||
pinMode(PIN_BUTTON2, INPUT_PULLUP);
|
||||
|
||||
// shutdown gps
|
||||
pinMode(PIN_GPS_STANDBY, OUTPUT);
|
||||
digitalWrite(PIN_GPS_STANDBY, HIGH);
|
||||
pinMode(PIN_GPS_EN, OUTPUT);
|
||||
digitalWrite(PIN_GPS_EN, LOW); // disable at startup
|
||||
|
||||
pinMode(SX126X_ANT_SW, OUTPUT); // ANT_SW
|
||||
digitalWrite(SX126X_ANT_SW, HIGH);
|
||||
|
||||
pinMode(ADC_EN, OUTPUT);
|
||||
digitalWrite(ADC_EN, LOW);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,141 @@
|
||||
/*
|
||||
* variant.h
|
||||
* Copyright (C) 2023 Seeed K.K.
|
||||
* MIT License
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "WVariant.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Low frequency clock source
|
||||
|
||||
#define USE_LFXO // 32.768 kHz crystal oscillator
|
||||
#define VARIANT_MCK (64000000ul)
|
||||
|
||||
#define WIRE_INTERFACES_COUNT (1)
|
||||
#define PIN_TXCO (21)
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Power
|
||||
|
||||
#define PIN_PWR_EN (13) // I2C
|
||||
|
||||
#define BATTERY_PIN (4)
|
||||
#define ADC_MULTIPLIER (1.75F)
|
||||
|
||||
#define ADC_RESOLUTION (14)
|
||||
#define BATTERY_SENSE_RES (12)
|
||||
|
||||
#define AREF_VOLTAGE (2.4)
|
||||
|
||||
#define ADC_EN (40)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Number of pins
|
||||
|
||||
#define PINS_COUNT (48)
|
||||
#define NUM_DIGITAL_PINS (48)
|
||||
#define NUM_ANALOG_INPUTS (1)
|
||||
#define NUM_ANALOG_OUTPUTS (0)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// UART pin definition
|
||||
|
||||
#define PIN_SERIAL1_RX PIN_GPS_TX
|
||||
#define PIN_SERIAL1_TX PIN_GPS_RX
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// I2C pin definition
|
||||
|
||||
#define PIN_WIRE_SDA (26) // P0.26
|
||||
#define PIN_WIRE_SCL (27) // P0.27
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// SPI pin definition
|
||||
|
||||
#define SPI_INTERFACES_COUNT (2)
|
||||
|
||||
#define PIN_SPI_MISO (22)
|
||||
#define PIN_SPI_MOSI (20)
|
||||
#define PIN_SPI_SCK (19)
|
||||
#define PIN_SPI_NSS (21)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Builtin LEDs
|
||||
#define LED_BLUE (-1)
|
||||
|
||||
#define LED_BUILTIN LED_BLUE
|
||||
#define LED_PIN LED_BUILTIN
|
||||
#define LED_STATE_ON HIGH
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Builtin buttons
|
||||
|
||||
#define PIN_BUTTON1 (6)
|
||||
#define PIN_BUTTON1_A (8) // Rotary button/Encoder
|
||||
#define PIN_BUTTON1_B (41)
|
||||
#define BUTTON_PIN PIN_BUTTON1
|
||||
|
||||
#define PIN_BUTTON2 (12)
|
||||
#define BUTTON_PIN2 PIN_BUTTON2
|
||||
|
||||
#define PIN_USER_BTN PIN_BUTTON1
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Lora
|
||||
|
||||
#define USE_SX1262
|
||||
#define LORA_CS (24)
|
||||
#define SX126X_DIO1 (20)
|
||||
#define SX126X_BUSY (17)
|
||||
#define SX126X_RESET (25)
|
||||
#define SX126X_ANT_SW (23)
|
||||
#define SX126X_DIO2_AS_RF_SWITCH
|
||||
#define SX126X_DIO3_TCXO_VOLTAGE 1.8
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// SPI1
|
||||
#define PIN_SPI1_NSS (30)
|
||||
#define PIN_SPI1_SCK (31)
|
||||
#define PIN_SPI1_MOSI (29)
|
||||
#define PIN_SPI1_MISO (-1)
|
||||
|
||||
// GxEPD2 needs that for a panel that is not even used !
|
||||
extern const int MISO;
|
||||
extern const int MOSI;
|
||||
extern const int SCK;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// QSPI
|
||||
#define EXTERNAL_FLASH_DEVICES MX25R1635F
|
||||
#define EXTERNAL_FLASH_USE_QSPI
|
||||
#define PIN_QSPI_SCK (46)
|
||||
#define PIN_QSPI_CS (47)
|
||||
#define PIN_QSPI_IO0 (44) // MOSI if using two bit interface
|
||||
#define PIN_QSPI_IO1 (45) // MISO if using two bit interface
|
||||
#define PIN_QSPI_IO2 (7) // WP if using two bit interface (i.e. not used)
|
||||
#define PIN_QSPI_IO3 (5) // HOLD if using two bit interface (i.e. not used)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Display
|
||||
|
||||
#define DISP_MISO PIN_SPI1_MISO
|
||||
#define DISP_MOSI PIN_SPI1_MOSI
|
||||
#define DISP_SCLK PIN_SPI1_SCK
|
||||
#define PIN_DISPLAY_CS PIN_SPI1_NSS
|
||||
#define PIN_DISPLAY_DC (28)
|
||||
#define PIN_DISPLAY_RST (2)
|
||||
#define PIN_DISPLAY_BUSY (3)
|
||||
#define DISP_BACKLIGHT (43)
|
||||
#define DISP_EN (42)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// GPS
|
||||
|
||||
#define PIN_GPS_RX (36)
|
||||
#define PIN_GPS_TX (34)
|
||||
#define PIN_GPS_EN (16)
|
||||
#define PIN_GPS_RESET (-1)
|
||||
#define PIN_GPS_PPS (14)
|
||||
#define PIN_GPS_STANDBY (15) // Low = sleep
|
||||
#define GPS_BAUD_RATE 115200
|
||||
@@ -137,6 +137,7 @@ extends = ThinkNode_M9
|
||||
build_flags =
|
||||
${ThinkNode_M9.build_flags}
|
||||
-I examples/companion_radio/ui-new
|
||||
-D ENABLE_WIFI_INTERFACE
|
||||
-D MAX_CONTACTS=350
|
||||
-D MAX_GROUP_CHANNELS=40
|
||||
-D WIFI_DEBUG_LOGGING=1
|
||||
@@ -146,6 +147,7 @@ build_flags =
|
||||
; -D MESH_PACKET_LOGGING=1
|
||||
build_src_filter = ${ThinkNode_M9.build_src_filter}
|
||||
+<helpers/esp32/*.cpp>
|
||||
+<helpers/wifi/*.cpp>
|
||||
+<helpers/ui/buzzer.cpp>
|
||||
+<helpers/ui/MomentaryButton.cpp>
|
||||
+<../examples/companion_radio/*.cpp>
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <helpers/ESP32Board.h>
|
||||
|
||||
class WaveshareS3LR1121Board : public ESP32Board {
|
||||
public:
|
||||
const char* getManufacturerName() const override {
|
||||
return "Waveshare ESP32-S3-LR1121";
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,102 @@
|
||||
; Waveshare ESP32-S3-LR1121 (HF: 850-930 MHz + 2.4 GHz)
|
||||
; ESP32-S3FH4R2 (4MB flash, 2MB PSRAM), native USB-CDC via the Tiny-Adapter FPC.
|
||||
; No user LED, battery sense or user button (BOOT is GPIO0).
|
||||
[Waveshare_S3_LR1121]
|
||||
extends = esp32_base
|
||||
board = esp32-s3-zero
|
||||
; min_spiffs: 1.9MB OTA app slots; one layout for every role so switching roles keeps the filesystem
|
||||
board_build.partitions = min_spiffs.csv
|
||||
build_flags = ${esp32_base.build_flags}
|
||||
-I variants/waveshare_esp32s3_lr1121
|
||||
-D BOARD_HAS_PSRAM
|
||||
-D P_LORA_DIO_1=38
|
||||
-D P_LORA_NSS=42
|
||||
-D P_LORA_RESET=39
|
||||
-D P_LORA_BUSY=41
|
||||
-D P_LORA_SCLK=40
|
||||
-D P_LORA_MISO=46
|
||||
-D P_LORA_MOSI=45
|
||||
-D RADIO_CLASS=CustomLR1121
|
||||
-D WRAPPER_CLASS=CustomLR1121Wrapper
|
||||
-D LR11X0_DIO3_TCXO_VOLTAGE=1.8
|
||||
-D LR1121_FORCE_HP_PA ; RFO_LP_LF is not fitted (R4 NC)
|
||||
-D RX_BOOSTED_GAIN=true
|
||||
-D LORA_TX_POWER=22
|
||||
build_src_filter = ${esp32_base.build_src_filter}
|
||||
+<../variants/waveshare_esp32s3_lr1121>
|
||||
lib_deps =
|
||||
${esp32_base.lib_deps}
|
||||
|
||||
[env:Waveshare_S3_LR1121_repeater]
|
||||
extends = Waveshare_S3_LR1121
|
||||
build_flags =
|
||||
${Waveshare_S3_LR1121.build_flags}
|
||||
-D ADVERT_NAME='"Waveshare LR1121 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 = ${Waveshare_S3_LR1121.build_src_filter}
|
||||
+<../examples/simple_repeater/*.cpp>
|
||||
lib_deps =
|
||||
${Waveshare_S3_LR1121.lib_deps}
|
||||
${esp32_ota.lib_deps}
|
||||
|
||||
[env:Waveshare_S3_LR1121_room_server]
|
||||
extends = Waveshare_S3_LR1121
|
||||
build_flags =
|
||||
${Waveshare_S3_LR1121.build_flags}
|
||||
-D ADVERT_NAME='"Waveshare LR1121 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
|
||||
build_src_filter = ${Waveshare_S3_LR1121.build_src_filter}
|
||||
+<../examples/simple_room_server>
|
||||
lib_deps =
|
||||
${Waveshare_S3_LR1121.lib_deps}
|
||||
${esp32_ota.lib_deps}
|
||||
|
||||
[env:Waveshare_S3_LR1121_companion_radio_usb]
|
||||
extends = Waveshare_S3_LR1121
|
||||
build_flags =
|
||||
${Waveshare_S3_LR1121.build_flags}
|
||||
-D MAX_CONTACTS=350
|
||||
-D MAX_GROUP_CHANNELS=40
|
||||
-D OFFLINE_QUEUE_SIZE=256
|
||||
-D ENABLE_USB_INTERFACE
|
||||
; -D MESH_PACKET_LOGGING=1
|
||||
; -D MESH_DEBUG=1
|
||||
build_src_filter = ${Waveshare_S3_LR1121.build_src_filter}
|
||||
+<helpers/esp32/*.cpp>
|
||||
+<../examples/companion_radio/*.cpp>
|
||||
lib_deps =
|
||||
${Waveshare_S3_LR1121.lib_deps}
|
||||
densaugeo/base64 @ ~1.4.0
|
||||
|
||||
[env:Waveshare_S3_LR1121_companion_radio_ble]
|
||||
extends = Waveshare_S3_LR1121
|
||||
build_flags =
|
||||
${Waveshare_S3_LR1121.build_flags}
|
||||
-D MAX_CONTACTS=350
|
||||
-D MAX_GROUP_CHANNELS=40
|
||||
-D OFFLINE_QUEUE_SIZE=256
|
||||
-D BLE_PIN_CODE=123456
|
||||
; -D BLE_DEBUG_LOGGING=1
|
||||
; -D MESH_PACKET_LOGGING=1
|
||||
; -D MESH_DEBUG=1
|
||||
build_src_filter = ${Waveshare_S3_LR1121.build_src_filter}
|
||||
+<helpers/esp32/*.cpp>
|
||||
+<../examples/companion_radio/*.cpp>
|
||||
lib_deps =
|
||||
${Waveshare_S3_LR1121.lib_deps}
|
||||
densaugeo/base64 @ ~1.4.0
|
||||
|
||||
[env:Waveshare_S3_LR1121_kiss_modem]
|
||||
extends = Waveshare_S3_LR1121
|
||||
build_src_filter = ${Waveshare_S3_LR1121.build_src_filter}
|
||||
+<../examples/kiss_modem/>
|
||||
@@ -0,0 +1,63 @@
|
||||
#include <Arduino.h>
|
||||
#include "target.h"
|
||||
|
||||
WaveshareS3LR1121Board board;
|
||||
|
||||
static SPIClass spi;
|
||||
RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY, spi);
|
||||
WRAPPER_CLASS radio_driver(radio, board);
|
||||
|
||||
ESP32RTCClock fallback_clock;
|
||||
AutoDiscoverRTCClock rtc_clock(fallback_clock);
|
||||
SensorManager sensors;
|
||||
|
||||
#ifndef LORA_CR
|
||||
#define LORA_CR 5
|
||||
#endif
|
||||
|
||||
// DIO5/DIO6 drive the RTC6603SP sub-GHz T/R switch; the 2.4 GHz port (RFIO_HF) is unswitched
|
||||
static const uint32_t rfswitch_dios[Module::RFSWITCH_MAX_PINS] = {
|
||||
RADIOLIB_LR11X0_DIO5,
|
||||
RADIOLIB_LR11X0_DIO6,
|
||||
RADIOLIB_NC
|
||||
};
|
||||
|
||||
static const Module::RfSwitchMode_t rfswitch_table[] = {
|
||||
// mode DIO5 DIO6
|
||||
{ LR11x0::MODE_STBY, {LOW, LOW}},
|
||||
{ LR11x0::MODE_RX, {HIGH, LOW}},
|
||||
{ LR11x0::MODE_TX, {LOW, HIGH}},
|
||||
{ LR11x0::MODE_TX_HP, {LOW, HIGH}},
|
||||
{ LR11x0::MODE_TX_HF, {LOW, LOW}},
|
||||
{ LR11x0::MODE_GNSS, {LOW, LOW}},
|
||||
{ LR11x0::MODE_WIFI, {LOW, LOW}},
|
||||
END_OF_MODE_TABLE,
|
||||
};
|
||||
|
||||
bool radio_init() {
|
||||
fallback_clock.begin();
|
||||
rtc_clock.begin(Wire);
|
||||
|
||||
spi.begin(P_LORA_SCLK, P_LORA_MISO, P_LORA_MOSI);
|
||||
int status = radio.begin(LORA_FREQ, LORA_BW, LORA_SF, LORA_CR, RADIOLIB_LR11X0_LORA_SYNC_WORD_PRIVATE,
|
||||
LORA_TX_POWER, 16, LR11X0_DIO3_TCXO_VOLTAGE);
|
||||
if (status != RADIOLIB_ERR_NONE) {
|
||||
Serial.print("ERROR: radio init failed: ");
|
||||
Serial.println(status);
|
||||
return false;
|
||||
}
|
||||
|
||||
radio.setCRC(2);
|
||||
radio.explicitHeader();
|
||||
radio.setRfSwitchTable(rfswitch_dios, rfswitch_table);
|
||||
#ifdef RX_BOOSTED_GAIN
|
||||
radio.setRxBoostedGainMode(RX_BOOSTED_GAIN);
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
mesh::LocalIdentity radio_new_identity() {
|
||||
RadioNoiseListener rng(radio);
|
||||
return mesh::LocalIdentity(&rng);
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
#pragma once
|
||||
|
||||
#define RADIOLIB_STATIC_ONLY 1
|
||||
#include <RadioLib.h>
|
||||
#include <helpers/radiolib/RadioLibWrappers.h>
|
||||
#include <helpers/radiolib/CustomLR1121Wrapper.h>
|
||||
#include <helpers/AutoDiscoverRTCClock.h>
|
||||
#include <helpers/SensorManager.h>
|
||||
#include "WaveshareS3LR1121Board.h"
|
||||
|
||||
extern WaveshareS3LR1121Board board;
|
||||
extern WRAPPER_CLASS radio_driver;
|
||||
extern AutoDiscoverRTCClock rtc_clock;
|
||||
extern SensorManager sensors;
|
||||
|
||||
bool radio_init();
|
||||
mesh::LocalIdentity radio_new_identity();
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <MeshCore.h>
|
||||
#include <helpers/KeyValueStore.h>
|
||||
|
||||
// LoRa radio module pins for Waveshare RP2040-LoRa-HF/LF
|
||||
// https://files.waveshare.com/wiki/RP2040-LoRa/Rp2040-lora-sch.pdf
|
||||
@@ -32,6 +33,8 @@ public:
|
||||
void begin();
|
||||
uint8_t getStartupReason() const override { return startup_reason; }
|
||||
|
||||
void attachDynamicPrefs(KeyValueStore* prefs) { } // no-op
|
||||
|
||||
#ifdef P_LORA_TX_LED
|
||||
void onBeforeTransmit() override { digitalWrite(P_LORA_TX_LED, HIGH); }
|
||||
void onAfterTransmit() override { digitalWrite(P_LORA_TX_LED, LOW); }
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
#include <Arduino.h>
|
||||
#include <Wire.h>
|
||||
|
||||
#include "WioTrackerL1Board.h"
|
||||
|
||||
void WioTrackerL1Board::begin() {
|
||||
NRF52BoardDCDC::begin();
|
||||
btn_prev_state = HIGH;
|
||||
|
||||
pinMode(PIN_VBAT_READ, INPUT); // VBAT ADC input
|
||||
// Set all button pins to INPUT_PULLUP
|
||||
pinMode(PIN_BUTTON1, INPUT_PULLUP);
|
||||
pinMode(PIN_BUTTON2, INPUT_PULLUP);
|
||||
pinMode(PIN_BUTTON3, INPUT_PULLUP);
|
||||
pinMode(PIN_BUTTON4, INPUT_PULLUP);
|
||||
pinMode(PIN_BUTTON5, INPUT_PULLUP);
|
||||
pinMode(PIN_BUTTON6, INPUT_PULLUP);
|
||||
|
||||
#if defined(PIN_WIRE_SDA) && defined(PIN_WIRE_SCL)
|
||||
Wire.setPins(PIN_WIRE_SDA, PIN_WIRE_SCL);
|
||||
#endif
|
||||
|
||||
Wire.begin();
|
||||
|
||||
pinMode(SX126X_POWER_EN, OUTPUT);
|
||||
|
||||
#ifdef P_LORA_TX_LED
|
||||
pinMode(P_LORA_TX_LED, OUTPUT);
|
||||
digitalWrite(P_LORA_TX_LED, LOW);
|
||||
#endif
|
||||
|
||||
delay(10); // give sx1262 some time to power up
|
||||
}
|
||||
|
||||
bool WioTrackerL1Board::setLoRaFemPaGainEnabled(bool enable) {
|
||||
_is_pa_enabled = enable;
|
||||
digitalWrite(SX126X_POWER_EN, enable ? HIGH : LOW); // enable/disable the 1W PA
|
||||
return true;
|
||||
}
|
||||
|
||||
void WioTrackerL1Board::attachDynamicPrefs(KeyValueStore* prefs) {
|
||||
_prefs = prefs;
|
||||
|
||||
char gain[8];
|
||||
|
||||
gain[0] = 0;
|
||||
_prefs->getByKey("fem_txgain", gain, 7); // get initial values
|
||||
setLoRaFemPaGainEnabled(strcmp(gain, "1") == 0);
|
||||
}
|
||||
|
||||
bool WioTrackerL1Board::handleCommand(const char* command, uint32_t sender_timestamp, char* reply) {
|
||||
if (strcmp(command, "get radio.fem.rxgain") == 0) {
|
||||
strcpy(reply, "Error: unsupported");
|
||||
return true;
|
||||
}
|
||||
if (memcmp(command, "set radio.fem.rxgain ", 21) == 0) {
|
||||
strcpy(reply, "Error: unsupported");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (strcmp(command, "get radio.fem.txgain") == 0) {
|
||||
sprintf(reply, "> %s", isLoRaFemPaGainEnabled() ? "on" : "off");
|
||||
return true;
|
||||
}
|
||||
if (memcmp(command, "set radio.fem.txgain ", 21) == 0) {
|
||||
if (memcmp(&command[21], "on", 2) == 0) {
|
||||
if (setLoRaFemPaGainEnabled(true)) {
|
||||
_prefs->setByKey("fem_txgain", "1");
|
||||
strcpy(reply, "OK - LoRa FEM TX gain on");
|
||||
} else {
|
||||
strcpy(reply, "Error: failed to apply LoRa FEM TX gain");
|
||||
}
|
||||
} else if (memcmp(&command[21], "off", 3) == 0) {
|
||||
if (setLoRaFemPaGainEnabled(false)) {
|
||||
_prefs->setByKey("fem_txgain", "0");
|
||||
strcpy(reply, "OK - LoRa FEM TX gain off");
|
||||
} else {
|
||||
strcpy(reply, "Error: failed to apply LoRa FEM TX gain");
|
||||
}
|
||||
} else {
|
||||
strcpy(reply, "Error: state must be on or off");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return false; // not handled
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
#pragma once
|
||||
|
||||
#include <MeshCore.h>
|
||||
#include <Arduino.h>
|
||||
#include <helpers/NRF52Board.h>
|
||||
|
||||
class WioTrackerL1Board : public NRF52BoardDCDC {
|
||||
protected:
|
||||
uint8_t btn_prev_state;
|
||||
bool _is_pa_enabled = false;
|
||||
KeyValueStore* _prefs = NULL;
|
||||
|
||||
bool setLoRaFemPaGainEnabled(bool enable);
|
||||
bool isLoRaFemPaGainEnabled() const { return _is_pa_enabled; }
|
||||
|
||||
public:
|
||||
WioTrackerL1Board() : NRF52Board("WioTrackerL1_OTA") {}
|
||||
void begin();
|
||||
void attachDynamicPrefs(KeyValueStore* prefs);
|
||||
bool handleCommand(const char* command, uint32_t sender_timestamp, char* reply) override;
|
||||
|
||||
#if defined(P_LORA_TX_LED)
|
||||
void onBeforeTransmit() override {
|
||||
digitalWrite(P_LORA_TX_LED, HIGH); // turn TX LED on
|
||||
}
|
||||
void onAfterTransmit() override {
|
||||
digitalWrite(P_LORA_TX_LED, LOW); // turn TX LED off
|
||||
}
|
||||
#endif
|
||||
|
||||
uint16_t getBattMilliVolts() override {
|
||||
int adcvalue = 0;
|
||||
analogReadResolution(12);
|
||||
analogReference(AR_INTERNAL);
|
||||
delay(10);
|
||||
adcvalue = analogRead(PIN_VBAT_READ);
|
||||
return (adcvalue * ADC_MULTIPLIER * AREF_VOLTAGE) / 4.096;
|
||||
}
|
||||
|
||||
const char* getManufacturerName() const override {
|
||||
return "Seeed Wio Tracker L1";
|
||||
}
|
||||
|
||||
void powerOff() override {
|
||||
setLoRaFemPaGainEnabled(false); // turn Off PA
|
||||
NRF52Board::powerOff();
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,123 @@
|
||||
[WioTrackerL1-1W]
|
||||
extends = nrf52_base
|
||||
board = seeed-wio-tracker-l1
|
||||
board_build.ldscript = boards/nrf52840_s140_v7.ld
|
||||
build_flags = ${nrf52_base.build_flags}
|
||||
${sensor_base.build_flags}
|
||||
-I lib/nrf52/s140_nrf52_7.3.0_API/include
|
||||
-I lib/nrf52/s140_nrf52_7.3.0_API/include/nrf52
|
||||
-I variants/wio-tracker-l1-1w
|
||||
-D WIO_TRACKER_L1
|
||||
-D USE_SX1262
|
||||
-D RADIO_CLASS=CustomSX1262
|
||||
-D WRAPPER_CLASS=CustomSX1262Wrapper
|
||||
-D LORA_TX_POWER=22
|
||||
-D SX126X_CURRENT_LIMIT=140
|
||||
-D SX126X_RX_BOOSTED_GAIN=1
|
||||
-D PIN_OLED_RESET=-1
|
||||
-D GPS_BAUD_RATE=9600
|
||||
build_src_filter = ${nrf52_base.build_src_filter}
|
||||
+<WioTrackerL1Board.cpp>
|
||||
+<../variants/wio-tracker-l1-1w>
|
||||
+<helpers/ui/SH1106Display.cpp>
|
||||
+<helpers/sensors>
|
||||
lib_deps= ${nrf52_base.lib_deps}
|
||||
${sensor_base.lib_deps}
|
||||
adafruit/Adafruit SH110X @ ^2.1.13
|
||||
adafruit/Adafruit GFX Library @ ^1.12.1
|
||||
|
||||
[env:WioTrackerL1-1W_repeater]
|
||||
extends = WioTrackerL1-1W
|
||||
build_src_filter = ${WioTrackerL1-1W.build_src_filter}
|
||||
+<../examples/simple_repeater>
|
||||
build_flags =
|
||||
${WioTrackerL1-1W.build_flags}
|
||||
-D ADVERT_NAME='"WioTrackerL1 Repeater"'
|
||||
-D ADMIN_PASSWORD='"password"'
|
||||
-D MAX_NEIGHBOURS=50
|
||||
-D DISPLAY_CLASS=SH1106Display
|
||||
; -D MESH_PACKET_LOGGING=1
|
||||
; -D MESH_DEBUG=1
|
||||
lib_deps = ${WioTrackerL1-1W.lib_deps}
|
||||
adafruit/RTClib @ ^2.1.3
|
||||
|
||||
[env:WioTrackerL1-1W_room_server]
|
||||
extends = WioTrackerL1-1W
|
||||
build_src_filter = ${WioTrackerL1-1W.build_src_filter}
|
||||
+<../examples/simple_room_server>
|
||||
build_flags = ${WioTrackerL1-1W.build_flags}
|
||||
-D ADVERT_NAME='"WioTrackerL1 Room"'
|
||||
-D ADMIN_PASSWORD='"password"'
|
||||
-D ROOM_PASSWORD='"hello"'
|
||||
-D DISPLAY_CLASS=SH1106Display
|
||||
; -D MESH_PACKET_LOGGING=1
|
||||
; -D MESH_DEBUG=1
|
||||
lib_deps = ${WioTrackerL1-1W.lib_deps}
|
||||
adafruit/RTClib @ ^2.1.3
|
||||
|
||||
[env:WioTrackerL1-1W_companion_radio_usb]
|
||||
extends = WioTrackerL1-1W
|
||||
board_build.ldscript = boards/nrf52840_s140_v7_extrafs.ld
|
||||
board_upload.maximum_size = 708608
|
||||
build_flags = ${WioTrackerL1-1W.build_flags}
|
||||
-I examples/companion_radio/ui-new
|
||||
-D MAX_CONTACTS=350
|
||||
-D MAX_GROUP_CHANNELS=40
|
||||
-D DISPLAY_CLASS=SH1106Display
|
||||
-D UI_HAS_JOYSTICK=1
|
||||
-D UI_NO_HIBERNATE
|
||||
-D OFFLINE_QUEUE_SIZE=256
|
||||
-D PIN_BUZZER=12
|
||||
-D QSPIFLASH=1
|
||||
-D RADIO_FEM_TXGAIN=1
|
||||
-D ENABLE_USB_INTERFACE
|
||||
; NOTE: DO NOT ENABLE --> -D MESH_PACKET_LOGGING=1
|
||||
; NOTE: DO NOT ENABLE --> -D MESH_DEBUG=1
|
||||
build_src_filter = ${WioTrackerL1-1W.build_src_filter}
|
||||
+<helpers/ui/MomentaryButton.cpp>
|
||||
+<../examples/companion_radio/*.cpp>
|
||||
+<../examples/companion_radio/ui-new/*.cpp>
|
||||
+<helpers/ui/SH1106Display.cpp>
|
||||
+<helpers/ui/buzzer.cpp>
|
||||
lib_deps = ${WioTrackerL1-1W.lib_deps}
|
||||
adafruit/RTClib @ ^2.1.3
|
||||
densaugeo/base64 @ ~1.4.0
|
||||
end2endzone/NonBlockingRTTTL@^1.3.0
|
||||
|
||||
[env:WioTrackerL1-1W_companion_radio_ble]
|
||||
extends = WioTrackerL1-1W
|
||||
board_build.ldscript = boards/nrf52840_s140_v7_extrafs.ld
|
||||
board_upload.maximum_size = 708608
|
||||
build_flags = ${WioTrackerL1-1W.build_flags}
|
||||
-I examples/companion_radio/ui-new
|
||||
-D MAX_CONTACTS=350
|
||||
-D MAX_GROUP_CHANNELS=40
|
||||
-D BLE_PIN_CODE=123456
|
||||
-D BLE_DEBUG_LOGGING=1
|
||||
-D OFFLINE_QUEUE_SIZE=256
|
||||
-D DISPLAY_CLASS=SH1106Display
|
||||
-D UI_HAS_JOYSTICK=1
|
||||
-D UI_NO_HIBERNATE
|
||||
-D PIN_BUZZER=12
|
||||
-D QSPIFLASH=1
|
||||
-D RADIO_FEM_TXGAIN=1
|
||||
-D ADVERT_NAME='"@@MAC"'
|
||||
-D ENV_PIN_SDA=PIN_WIRE1_SDA
|
||||
-D ENV_PIN_SCL=PIN_WIRE1_SCL
|
||||
; -D MESH_PACKET_LOGGING=1
|
||||
; -D MESH_DEBUG=1
|
||||
build_src_filter = ${WioTrackerL1-1W.build_src_filter}
|
||||
+<helpers/nrf52/SerialBLEInterface.cpp>
|
||||
+<helpers/ui/MomentaryButton.cpp>
|
||||
+<helpers/ui/buzzer.cpp>
|
||||
+<../examples/companion_radio/*.cpp>
|
||||
+<../examples/companion_radio/ui-new/*.cpp>
|
||||
lib_deps = ${WioTrackerL1-1W.lib_deps}
|
||||
adafruit/RTClib @ ^2.1.3
|
||||
densaugeo/base64 @ ~1.4.0
|
||||
end2endzone/NonBlockingRTTTL@^1.3.0
|
||||
|
||||
[env:WioTrackerL1-1W_kiss_modem]
|
||||
extends = WioTrackerL1-1W
|
||||
build_src_filter = ${WioTrackerL1-1W.build_src_filter}
|
||||
+<../examples/kiss_modem/>
|
||||
@@ -0,0 +1,40 @@
|
||||
#include <Arduino.h>
|
||||
#include "target.h"
|
||||
#include <helpers/ArduinoHelpers.h>
|
||||
#include <helpers/sensors/MicroNMEALocationProvider.h>
|
||||
|
||||
WioTrackerL1Board board;
|
||||
|
||||
RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY, SPI);
|
||||
|
||||
WRAPPER_CLASS radio_driver(radio, board);
|
||||
|
||||
VolatileRTCClock fallback_clock;
|
||||
AutoDiscoverRTCClock rtc_clock(fallback_clock);
|
||||
|
||||
#ifdef ENV_INCLUDE_GPS
|
||||
MicroNMEALocationProvider nmea = MicroNMEALocationProvider(Serial1, &rtc_clock);
|
||||
EnvironmentSensorManager sensors = EnvironmentSensorManager(nmea);
|
||||
#else
|
||||
EnvironmentSensorManager sensors = EnvironmentSensorManager();
|
||||
#endif
|
||||
|
||||
#ifdef DISPLAY_CLASS
|
||||
DISPLAY_CLASS display;
|
||||
MomentaryButton user_btn(PIN_USER_BTN, 1000, true, false, false);
|
||||
MomentaryButton joystick_left(JOYSTICK_LEFT, 1000, true, false, false);
|
||||
MomentaryButton joystick_right(JOYSTICK_RIGHT, 1000, true, false, false);
|
||||
MomentaryButton back_btn(PIN_BACK_BTN, 1000, true, false, true);
|
||||
#endif
|
||||
|
||||
bool radio_init() {
|
||||
rtc_clock.begin(Wire);
|
||||
|
||||
return radio.std_init(&SPI);
|
||||
}
|
||||
|
||||
mesh::LocalIdentity radio_new_identity() {
|
||||
RadioNoiseListener rng(radio);
|
||||
return mesh::LocalIdentity(&rng); // create new random identity
|
||||
}
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
#pragma once
|
||||
|
||||
#define RADIOLIB_STATIC_ONLY 1
|
||||
#include <RadioLib.h>
|
||||
#include <helpers/radiolib/RadioLibWrappers.h>
|
||||
#include <WioTrackerL1Board.h>
|
||||
#include <helpers/radiolib/CustomSX1262Wrapper.h>
|
||||
#include <helpers/AutoDiscoverRTCClock.h>
|
||||
#include <helpers/ArduinoHelpers.h>
|
||||
#include <helpers/sensors/EnvironmentSensorManager.h>
|
||||
#ifdef DISPLAY_CLASS
|
||||
#if defined(WIO_TRACKER_L1_EINK)
|
||||
#include <helpers/ui/GxEPDDisplay.h>
|
||||
#else
|
||||
#include <helpers/ui/SH1106Display.h>
|
||||
#endif
|
||||
#include <helpers/ui/MomentaryButton.h>
|
||||
#endif
|
||||
#include <helpers/sensors/EnvironmentSensorManager.h>
|
||||
|
||||
extern WioTrackerL1Board board;
|
||||
extern WRAPPER_CLASS radio_driver;
|
||||
extern AutoDiscoverRTCClock rtc_clock;
|
||||
extern EnvironmentSensorManager sensors;
|
||||
#ifdef DISPLAY_CLASS
|
||||
extern DISPLAY_CLASS display;
|
||||
extern MomentaryButton user_btn;
|
||||
extern MomentaryButton joystick_left;
|
||||
extern MomentaryButton joystick_right;
|
||||
extern MomentaryButton back_btn;
|
||||
#endif
|
||||
|
||||
bool radio_init();
|
||||
mesh::LocalIdentity radio_new_identity();
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
#include "variant.h"
|
||||
#include "wiring_constants.h"
|
||||
#include "wiring_digital.h"
|
||||
#include "nrf.h"
|
||||
|
||||
const uint32_t g_ADigitalPinMap[] = {
|
||||
// D0 .. D10 - Peripheral control pins
|
||||
41, // D0 P1.09 GNSS_WAKEUP
|
||||
7, // D1 P0.07 LORA_DIO1
|
||||
39, // D2 P1,07 LORA_RESET
|
||||
42, // D3 P1.10 LORA_BUSY
|
||||
46, // D4 P1.14 (A4/SDA) LORA_CS
|
||||
29, // D5 P0.29 (AIN5) LORA_VDET 鈥?Pro 1W: P0.29 (not P1.08)
|
||||
27, // D6 P0.27 (UART_TX) GNSS_TX
|
||||
26, // D7 P0.26 (UART_RX) GNSS_RX
|
||||
30, // D8 P0.30 (SPI_SCK) LORA_SCK
|
||||
3, // D9 P0.3 (SPI_MISO) LORA_MISO
|
||||
28, // D10 P0.28 (SPI_MOSI) LORA_MOSI
|
||||
|
||||
// D11-D12 - LED outputs
|
||||
33, // D11 P1.01 Mesh_LED (orange) 鈥?Pro 1W: P1.01 (not P1.15)
|
||||
// Buzzzer
|
||||
32, // D12 P1.0 Buzzer
|
||||
|
||||
// D13 - User input
|
||||
8, // D13 P0.08 User Button
|
||||
|
||||
// D14-D15 - OLED
|
||||
6, // D14 P0.06 OLED SDA
|
||||
5, // D15 P0.05 OLED SCL
|
||||
|
||||
// D16 - Battery voltage ADC input
|
||||
31, // D16 P0.31 VBAT_ADC
|
||||
// GROVE
|
||||
43, // D17 P0.00 GROVE SDA
|
||||
44, // D18 P0.01 GROVE SCL
|
||||
|
||||
// FLASH
|
||||
21, // D19 P0.21 (QSPI_SCK)
|
||||
25, // D20 P0.25 (QSPI_CSN)
|
||||
20, // D21 P0.20 (QSPI_SIO_0 DI)
|
||||
24, // D22 P0.24 (QSPI_SIO_1 DO)
|
||||
22, // D23 P0.22 (QSPI_SIO_2 WP)
|
||||
23, // D24 P0.23 (QSPI_SIO_3 HOLD)
|
||||
|
||||
// JOYSTICK
|
||||
36, // D25 TB_UP
|
||||
12, // D26 TB_DOWN
|
||||
11, // D27 TB_LEFT
|
||||
35, // D28 TB_RIGHT
|
||||
37, // D29 TB_PRESS
|
||||
|
||||
// VBAT ENABLE
|
||||
4, // D30 BAT_CTL
|
||||
|
||||
// D31-D33 - Pro 1W only
|
||||
13, // D31 P0.13 BOOST_EN (Grove 5V Boost)
|
||||
47, // D32 P1.15 nRF_Sig_Charge_State (BQ25616 STAT)
|
||||
14, // D33 P0.14 LORA_PWR_EN (SX1262 + 1 W PA LDO)
|
||||
};
|
||||
|
||||
void initVariant() {
|
||||
pinMode(PIN_QSPI_CS, OUTPUT);
|
||||
digitalWrite(PIN_QSPI_CS, HIGH);
|
||||
|
||||
// VBAT_ENABLE
|
||||
pinMode(VBAT_ENABLE, OUTPUT);
|
||||
digitalWrite(VBAT_ENABLE, HIGH);
|
||||
|
||||
// set LED pin as output and set it low
|
||||
pinMode(PIN_LED, OUTPUT);
|
||||
digitalWrite(PIN_LED, LOW);
|
||||
|
||||
// set buzzer pin as output and set it low
|
||||
pinMode(12, OUTPUT);
|
||||
digitalWrite(12, LOW);
|
||||
pinMode(12, OUTPUT);
|
||||
}
|
||||
@@ -0,0 +1,130 @@
|
||||
#ifndef _SEEED_WIO_TRACKER_L1_H_
|
||||
#define _SEEED_WIO_TRACKER_L1_H_
|
||||
|
||||
/** Master clock frequency */
|
||||
#define VARIANT_MCK (64000000ul)
|
||||
|
||||
#define USE_LFXO // Board uses 32khz crystal for LF
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Headers
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
#include "WVariant.h"
|
||||
|
||||
#define PINS_COUNT (34)
|
||||
#define NUM_DIGITAL_PINS (34)
|
||||
#define NUM_ANALOG_INPUTS (8)
|
||||
#define NUM_ANALOG_OUTPUTS (0)
|
||||
|
||||
// LEDs
|
||||
#define PIN_LED (11)
|
||||
#define LED_BLUE (-1) // Disable annoying flashing caused by Bluefruit
|
||||
#define LED_BUILTIN PIN_LED
|
||||
#define P_LORA_TX_LED PIN_LED
|
||||
#define LED_STATE_ON 1
|
||||
|
||||
// Buttons
|
||||
#define PIN_BUTTON1 (13) // Menu / User Button
|
||||
#define PIN_BUTTON2 (25) // Joystick Up
|
||||
#define PIN_BUTTON3 (26) // Joystick Down
|
||||
#define PIN_BUTTON4 (27) // Joystick Left
|
||||
#define PIN_BUTTON5 (28) // Joystick Right
|
||||
#define PIN_BUTTON6 (29) // Joystick Press
|
||||
#define PIN_BACK_BTN PIN_BUTTON1
|
||||
#define JOYSTICK_UP PIN_BUTTON2
|
||||
#define JOYSTICK_DOWN PIN_BUTTON3
|
||||
#define JOYSTICK_LEFT PIN_BUTTON4
|
||||
#define JOYSTICK_RIGHT PIN_BUTTON5
|
||||
#define JOYSTICK_PRESS PIN_BUTTON6
|
||||
#define PIN_USER_BTN PIN_BUTTON6
|
||||
|
||||
// Buzzer
|
||||
// #define PIN_BUZZER (12) // Buzzer pin (defined per firmware type)
|
||||
|
||||
#define VBAT_ENABLE (30)
|
||||
|
||||
// Analog pins
|
||||
#define PIN_VBAT_READ (16)
|
||||
#define AREF_VOLTAGE (3.6F)
|
||||
#define ADC_MULTIPLIER (2.0F)
|
||||
#define ADC_RESOLUTION (12)
|
||||
|
||||
// Serial interfaces
|
||||
#define PIN_SERIAL1_RX (7)
|
||||
#define PIN_SERIAL1_TX (6)
|
||||
|
||||
// SPI Interfaces
|
||||
#define SPI_INTERFACES_COUNT (2)
|
||||
|
||||
#define PIN_SPI_MISO (9)
|
||||
#define PIN_SPI_MOSI (10)
|
||||
#define PIN_SPI_SCK (8)
|
||||
|
||||
// BQ25616 single-wire charge status (Pro 1W)
|
||||
#define PIN_BOOST_EN (31) // D31 / P0.13 鈥?Grove 5V Boost enable
|
||||
#define EXT_CHRG_DETECT (32) // D32 / P1.15 鈥?BQ25616 STAT
|
||||
#define EXT_CHRG_DETECT_VALUE LOW // 0 = charging, 1 = full / charger sleep
|
||||
#define BOOST_EN_ACTIVE HIGH // HIGH enables Grove 5V Boost
|
||||
|
||||
// Lora Pins
|
||||
#define P_LORA_SCLK PIN_SPI_SCK
|
||||
#define P_LORA_MISO PIN_SPI_MISO
|
||||
#define P_LORA_MOSI PIN_SPI_MOSI
|
||||
#define P_LORA_DIO_1 (1)
|
||||
#define P_LORA_RESET (2)
|
||||
#define P_LORA_BUSY (3)
|
||||
#define P_LORA_NSS (4)
|
||||
#define SX126X_RXEN (5)
|
||||
#define SX126X_TXEN RADIOLIB_NC
|
||||
#define SX126X_DIO2_AS_RF_SWITCH true
|
||||
#define SX126X_DIO3_TCXO_VOLTAGE (1.8f)
|
||||
|
||||
// LORA_PWR_EN (P0.14): external LDO enable for the SX1262 + 1 W PA on the Pro 1W board.
|
||||
#define LORA_PWR_EN (33)
|
||||
#define SX126X_POWER_EN LORA_PWR_EN
|
||||
|
||||
// Wire Interfaces
|
||||
#define WIRE_INTERFACES_COUNT (2)
|
||||
|
||||
#define PIN_WIRE_SDA (14)
|
||||
#define PIN_WIRE_SCL (15)
|
||||
#define PIN_WIRE1_SDA (18)
|
||||
#define PIN_WIRE1_SCL (17)
|
||||
#define I2C_NO_RESCAN
|
||||
#define DISPLAY_ADDRESS 0x3D // SH1106 OLED I2C address
|
||||
|
||||
// GPS L76KB
|
||||
#define GPS_BAUDRATE 9600
|
||||
#define PIN_GPS_TX PIN_SERIAL1_RX
|
||||
#define PIN_GPS_RX PIN_SERIAL1_TX
|
||||
#define PIN_GPS_STANDBY (0)
|
||||
#define PIN_GPS_EN (PIN_GPS_STANDBY)
|
||||
|
||||
// QSPI Pins
|
||||
#define PIN_QSPI_SCK (19)
|
||||
#define PIN_QSPI_CS (20)
|
||||
#define PIN_QSPI_IO0 (21)
|
||||
#define PIN_QSPI_IO1 (22)
|
||||
#define PIN_QSPI_IO2 (23)
|
||||
#define PIN_QSPI_IO3 (24)
|
||||
|
||||
#define EXTERNAL_FLASH_DEVICES P25Q16H
|
||||
#define EXTERNAL_FLASH_USE_QSPI
|
||||
|
||||
// // EInk on SPI1
|
||||
// #define PIN_DISPLAY_CS (36)
|
||||
// #define PIN_DISPLAY_BUSY (35)
|
||||
// #define PIN_DISPLAY_DC (34)
|
||||
// #define PIN_DISPLAY_RST (32)
|
||||
|
||||
#define PIN_SPI1_MISO (37)
|
||||
#define PIN_SPI1_MOSI (33)
|
||||
#define PIN_SPI1_SCK (31)
|
||||
|
||||
// GxEPD2 needs that for a panel that is not even used !
|
||||
extern const int MISO;
|
||||
extern const int MOSI;
|
||||
extern const int SCK;
|
||||
|
||||
#endif
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user