diff --git a/arch/esp32/esp32s2.ini b/arch/esp32/esp32s2.ini
index 5de0fa549..df66de2ed 100644
--- a/arch/esp32/esp32s2.ini
+++ b/arch/esp32/esp32s2.ini
@@ -2,14 +2,17 @@
extends = esp32_base
build_src_filter =
- ${esp32_base.build_src_filter} - -
+ ${esp32_base.build_src_filter} - - -
monitor_speed = 115200
build_flags =
${esp32_base.build_flags}
-DHAS_BLUETOOTH=0
+ -DMESHTASTIC_EXCLUDE_PAXCOUNTER
+ -DMESHTASTIC_EXCLUDE_BLUETOOTH
lib_ignore =
${esp32_base.lib_ignore}
- NimBLE-Arduino
\ No newline at end of file
+ NimBLE-Arduino
+ libpax
\ No newline at end of file
diff --git a/boards/ESP32-S3-WROOM-1-N4.json b/boards/ESP32-S3-WROOM-1-N4.json
new file mode 100644
index 000000000..3620a711d
--- /dev/null
+++ b/boards/ESP32-S3-WROOM-1-N4.json
@@ -0,0 +1,39 @@
+{
+ "build": {
+ "arduino": {
+ "ldscript": "esp32s3_out.ld"
+ },
+ "core": "esp32",
+ "extra_flags": [
+ "-D ARDUINO_USB_CDC_ON_BOOT=0",
+ "-D ARDUINO_USB_MSC_ON_BOOT=0",
+ "-D ARDUINO_USB_DFU_ON_BOOT=0",
+ "-D ARDUINO_USB_MODE=0",
+ "-D ARDUINO_RUNNING_CORE=1",
+ "-D ARDUINO_EVENT_RUNNING_CORE=1"
+ ],
+ "f_cpu": "240000000L",
+ "f_flash": "80000000L",
+ "flash_mode": "qio",
+ "hwids": [["0x303A", "0x1001"]],
+ "mcu": "esp32s3",
+ "variant": "ESP32-S3-WROOM-1-N4"
+ },
+ "connectivity": ["wifi"],
+ "debug": {
+ "default_tool": "esp-builtin",
+ "onboard_tools": ["esp-builtin"],
+ "openocd_target": "esp32s3.cfg"
+ },
+ "frameworks": ["arduino", "espidf"],
+ "name": "ESP32-S3-WROOM-1-N4 (4 MB Flash, No PSRAM)",
+ "upload": {
+ "flash_size": "4MB",
+ "maximum_ram_size": 524288,
+ "maximum_size": 4194304,
+ "require_upload_port": true,
+ "speed": 921600
+ },
+ "url": "https://www.espressif.com/sites/default/files/documentation/esp32-s3-wroom-1_wroom-1u_datasheet_en.pdf",
+ "vendor": "Espressif"
+}
diff --git a/protobufs b/protobufs
index 0d08acd9c..eade2c6be 160000
--- a/protobufs
+++ b/protobufs
@@ -1 +1 @@
-Subproject commit 0d08acd9c51c4e5575f3ea42368834ec990b2278
+Subproject commit eade2c6befb65a9c46c5d28ae1e8e24c37a1a3d0
diff --git a/src/detect/ScanI2CTwoWire.cpp b/src/detect/ScanI2CTwoWire.cpp
index 13c2f4609..ba2820a77 100644
--- a/src/detect/ScanI2CTwoWire.cpp
+++ b/src/detect/ScanI2CTwoWire.cpp
@@ -271,8 +271,14 @@ void ScanI2CTwoWire::scanPort(I2CPort port)
}
break;
case INA3221_ADDR:
- LOG_INFO("INA3221 sensor found at address 0x%x\n", (uint8_t)addr.address);
- type = INA3221;
+ registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0xFE), 2);
+ LOG_DEBUG("Register MFG_UID: 0x%x\n", registerValue);
+ if (registerValue == 0x5449) {
+ LOG_INFO("INA3221 sensor found at address 0x%x\n", (uint8_t)addr.address);
+ type = INA3221;
+ } else { // Unknown device
+ LOG_INFO("No INA3221 found at address 0x%x\n", (uint8_t)addr.address);
+ }
break;
case MCP9808_ADDR:
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x07), 2);
diff --git a/src/gps/GPS.cpp b/src/gps/GPS.cpp
index 0d0bfd9a2..17e35a4b3 100644
--- a/src/gps/GPS.cpp
+++ b/src/gps/GPS.cpp
@@ -452,7 +452,7 @@ bool GPS::setup()
// Set the NEMA output messages
// Ask for only RMC and GGA
uint8_t fields[] = {CAS_NEMA_RMC, CAS_NEMA_GGA};
- for (int i = 0; i < sizeof(fields); i++) {
+ for (uint i = 0; i < sizeof(fields); i++) {
// Construct a CAS-CFG-MSG packet
uint8_t cas_cfg_msg_packet[] = {0x4e, fields[i], 0x01, 0x00};
msglen = makeCASPacket(0x06, 0x01, sizeof(cas_cfg_msg_packet), cas_cfg_msg_packet);
@@ -1584,7 +1584,7 @@ bool GPS::hasFlow()
bool GPS::whileIdle()
{
- int charsInBuf = 0;
+ uint charsInBuf = 0;
bool isValid = false;
if (!isAwake) {
clearBuffer();
diff --git a/src/gps/RTC.cpp b/src/gps/RTC.cpp
index 26af7cac2..85931900f 100644
--- a/src/gps/RTC.cpp
+++ b/src/gps/RTC.cpp
@@ -104,13 +104,15 @@ bool perhapsSetRTC(RTCQuality q, const struct timeval *tv)
bool shouldSet;
if (q > currentQuality) {
shouldSet = true;
- LOG_DEBUG("Upgrading time to quality %d\n", q);
- } else if (q == RTCQualityGPS && (now - lastSetMsec) > (12 * 60 * 60 * 1000UL)) {
- // Every 12 hrs we will slam in a new GPS time, to correct for local RTC clock drift
+ LOG_DEBUG("Upgrading time to quality %s\n", RtcName(q));
+ } else if (q >= RTCQualityNTP && (now - lastSetMsec) > (12 * 60 * 60 * 1000UL)) {
+ // Every 12 hrs we will slam in a new GPS or Phone GPS / NTP time, to correct for local RTC clock drift
shouldSet = true;
LOG_DEBUG("Reapplying external time to correct clock drift %ld secs\n", tv->tv_sec);
- } else
+ } else {
shouldSet = false;
+ LOG_DEBUG("Current RTC quality: %s. Ignoring time of RTC quality of %s\n", RtcName(currentQuality), RtcName(q));
+ }
if (shouldSet) {
currentQuality = q;
@@ -162,6 +164,24 @@ bool perhapsSetRTC(RTCQuality q, const struct timeval *tv)
}
}
+const char *RtcName(RTCQuality quality)
+{
+ switch (quality) {
+ case RTCQualityNone:
+ return "None";
+ case RTCQualityDevice:
+ return "Device";
+ case RTCQualityFromNet:
+ return "Net";
+ case RTCQualityNTP:
+ return "NTP";
+ case RTCQualityGPS:
+ return "GPS";
+ default:
+ return "Unknown";
+ }
+}
+
/**
* Sets the RTC time if the provided time is of higher quality than the current RTC time.
*
diff --git a/src/gps/RTC.h b/src/gps/RTC.h
index 0561819bd..1d609f136 100644
--- a/src/gps/RTC.h
+++ b/src/gps/RTC.h
@@ -28,6 +28,9 @@ RTCQuality getRTCQuality();
bool perhapsSetRTC(RTCQuality q, const struct timeval *tv);
bool perhapsSetRTC(RTCQuality q, struct tm &t);
+/// Return a string name for the quality
+const char *RtcName(RTCQuality quality);
+
/// Return time since 1970 in secs. While quality is RTCQualityNone we will be returning time based at zero
uint32_t getTime(bool local = false);
diff --git a/src/main.cpp b/src/main.cpp
index 4277e5e92..d652c1eae 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -179,6 +179,11 @@ const char *getDeviceName()
static int32_t ledBlinker()
{
+ // Still set up the blinking (heartbeat) interval but skip code path below, so LED will blink if
+ // config.device.led_heartbeat_disabled is changed
+ if (config.device.led_heartbeat_disabled)
+ return 1000;
+
static bool ledOn;
ledOn ^= 1;
@@ -1004,4 +1009,4 @@ void loop()
mainDelay.delay(delayMsec);
}
// if (didWake) LOG_DEBUG("wake!\n");
-}
\ No newline at end of file
+}
diff --git a/src/mesh/NodeDB.h b/src/mesh/NodeDB.h
index 169d91b67..4ec0853f9 100644
--- a/src/mesh/NodeDB.h
+++ b/src/mesh/NodeDB.h
@@ -153,12 +153,13 @@ class NodeDB
void setLocalPosition(meshtastic_Position position, bool timeOnly = false)
{
if (timeOnly) {
- LOG_DEBUG("Setting local position time only: time=%i\n", position.time);
+ LOG_DEBUG("Setting local position time only: time=%u timestamp=%u\n", position.time, position.timestamp);
localPosition.time = position.time;
+ localPosition.timestamp = position.timestamp > 0 ? position.timestamp : position.time;
return;
}
- LOG_DEBUG("Setting local position: latitude=%i, longitude=%i, time=%i\n", position.latitude_i, position.longitude_i,
- position.time);
+ LOG_DEBUG("Setting local position: latitude=%i, longitude=%i, time=%u, timestamp=%u\n", position.latitude_i,
+ position.longitude_i, position.time, position.timestamp);
localPosition = position;
}
diff --git a/src/mesh/RadioInterface.cpp b/src/mesh/RadioInterface.cpp
index 0f6cfde60..f07f71a83 100644
--- a/src/mesh/RadioInterface.cpp
+++ b/src/mesh/RadioInterface.cpp
@@ -492,7 +492,7 @@ void RadioInterface::applyModemConfig()
// If user has manually specified a channel num, then use that, otherwise generate one by hashing the name
const char *channelName = channels.getName(channels.getPrimaryIndex());
// channel_num is actually (channel_num - 1), since modulus (%) returns values from 0 to (numChannels - 1)
- int channel_num = (loraConfig.channel_num ? loraConfig.channel_num - 1 : hash(channelName)) % numChannels;
+ uint channel_num = (loraConfig.channel_num ? loraConfig.channel_num - 1 : hash(channelName)) % numChannels;
// Check if we use the default frequency slot
RadioInterface::uses_default_frequency_slot =
diff --git a/src/mesh/generated/meshtastic/config.pb.h b/src/mesh/generated/meshtastic/config.pb.h
index 7471d32f0..9292f33f3 100644
--- a/src/mesh/generated/meshtastic/config.pb.h
+++ b/src/mesh/generated/meshtastic/config.pb.h
@@ -283,6 +283,8 @@ typedef struct _meshtastic_Config_DeviceConfig {
bool disable_triple_click;
/* POSIX Timezone definition string from https://github.com/nayarsystems/posix_tz_db/blob/master/zones.csv. */
char tzdef[65];
+ /* If true, disable the default blinking LED (LED_PIN) behavior on the device */
+ bool led_heartbeat_disabled;
} meshtastic_Config_DeviceConfig;
/* Position Config */
@@ -582,7 +584,7 @@ extern "C" {
/* Initializer values for message structs */
#define meshtastic_Config_init_default {0, {meshtastic_Config_DeviceConfig_init_default}}
-#define meshtastic_Config_DeviceConfig_init_default {_meshtastic_Config_DeviceConfig_Role_MIN, 0, 0, 0, 0, _meshtastic_Config_DeviceConfig_RebroadcastMode_MIN, 0, 0, 0, 0, ""}
+#define meshtastic_Config_DeviceConfig_init_default {_meshtastic_Config_DeviceConfig_Role_MIN, 0, 0, 0, 0, _meshtastic_Config_DeviceConfig_RebroadcastMode_MIN, 0, 0, 0, 0, "", 0}
#define meshtastic_Config_PositionConfig_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, _meshtastic_Config_PositionConfig_GpsMode_MIN}
#define meshtastic_Config_PowerConfig_init_default {0, 0, 0, 0, 0, 0, 0, 0}
#define meshtastic_Config_NetworkConfig_init_default {0, "", "", "", 0, _meshtastic_Config_NetworkConfig_AddressMode_MIN, false, meshtastic_Config_NetworkConfig_IpV4Config_init_default, ""}
@@ -591,7 +593,7 @@ extern "C" {
#define meshtastic_Config_LoRaConfig_init_default {0, _meshtastic_Config_LoRaConfig_ModemPreset_MIN, 0, 0, 0, 0, _meshtastic_Config_LoRaConfig_RegionCode_MIN, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0}, 0}
#define meshtastic_Config_BluetoothConfig_init_default {0, _meshtastic_Config_BluetoothConfig_PairingMode_MIN, 0}
#define meshtastic_Config_init_zero {0, {meshtastic_Config_DeviceConfig_init_zero}}
-#define meshtastic_Config_DeviceConfig_init_zero {_meshtastic_Config_DeviceConfig_Role_MIN, 0, 0, 0, 0, _meshtastic_Config_DeviceConfig_RebroadcastMode_MIN, 0, 0, 0, 0, ""}
+#define meshtastic_Config_DeviceConfig_init_zero {_meshtastic_Config_DeviceConfig_Role_MIN, 0, 0, 0, 0, _meshtastic_Config_DeviceConfig_RebroadcastMode_MIN, 0, 0, 0, 0, "", 0}
#define meshtastic_Config_PositionConfig_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, _meshtastic_Config_PositionConfig_GpsMode_MIN}
#define meshtastic_Config_PowerConfig_init_zero {0, 0, 0, 0, 0, 0, 0, 0}
#define meshtastic_Config_NetworkConfig_init_zero {0, "", "", "", 0, _meshtastic_Config_NetworkConfig_AddressMode_MIN, false, meshtastic_Config_NetworkConfig_IpV4Config_init_zero, ""}
@@ -612,6 +614,7 @@ extern "C" {
#define meshtastic_Config_DeviceConfig_is_managed_tag 9
#define meshtastic_Config_DeviceConfig_disable_triple_click_tag 10
#define meshtastic_Config_DeviceConfig_tzdef_tag 11
+#define meshtastic_Config_DeviceConfig_led_heartbeat_disabled_tag 12
#define meshtastic_Config_PositionConfig_position_broadcast_secs_tag 1
#define meshtastic_Config_PositionConfig_position_broadcast_smart_enabled_tag 2
#define meshtastic_Config_PositionConfig_fixed_position_tag 3
@@ -713,7 +716,8 @@ X(a, STATIC, SINGULAR, UINT32, node_info_broadcast_secs, 7) \
X(a, STATIC, SINGULAR, BOOL, double_tap_as_button_press, 8) \
X(a, STATIC, SINGULAR, BOOL, is_managed, 9) \
X(a, STATIC, SINGULAR, BOOL, disable_triple_click, 10) \
-X(a, STATIC, SINGULAR, STRING, tzdef, 11)
+X(a, STATIC, SINGULAR, STRING, tzdef, 11) \
+X(a, STATIC, SINGULAR, BOOL, led_heartbeat_disabled, 12)
#define meshtastic_Config_DeviceConfig_CALLBACK NULL
#define meshtastic_Config_DeviceConfig_DEFAULT NULL
@@ -833,7 +837,7 @@ extern const pb_msgdesc_t meshtastic_Config_BluetoothConfig_msg;
/* Maximum encoded size of messages (where known) */
#define MESHTASTIC_MESHTASTIC_CONFIG_PB_H_MAX_SIZE meshtastic_Config_size
#define meshtastic_Config_BluetoothConfig_size 10
-#define meshtastic_Config_DeviceConfig_size 98
+#define meshtastic_Config_DeviceConfig_size 100
#define meshtastic_Config_DisplayConfig_size 28
#define meshtastic_Config_LoRaConfig_size 82
#define meshtastic_Config_NetworkConfig_IpV4Config_size 20
diff --git a/src/mesh/generated/meshtastic/telemetry.pb.h b/src/mesh/generated/meshtastic/telemetry.pb.h
index b6d3811a4..e670dd340 100644
--- a/src/mesh/generated/meshtastic/telemetry.pb.h
+++ b/src/mesh/generated/meshtastic/telemetry.pb.h
@@ -43,7 +43,9 @@ typedef enum _meshtastic_TelemetrySensorType {
/* INA3221 3 Channel Voltage / Current Sensor */
meshtastic_TelemetrySensorType_INA3221 = 14,
/* BMP085/BMP180 High accuracy temperature and pressure (older Version of BMP280) */
- meshtastic_TelemetrySensorType_BMP085 = 15
+ meshtastic_TelemetrySensorType_BMP085 = 15,
+ /* RCWL-9620 Doppler Radar Distance Sensor, used for water level detection */
+ meshtastic_TelemetrySensorType_RCWL9620 = 16
} meshtastic_TelemetrySensorType;
/* Struct definitions */
@@ -78,6 +80,8 @@ typedef struct _meshtastic_EnvironmentMetrics {
/* relative scale IAQ value as measured by Bosch BME680 . value 0-500.
Belongs to Air Quality but is not particle but VOC measurement. Other VOC values can also be put in here. */
uint16_t iaq;
+ /* RCWL9620 Doppler Radar Distance Sensor, used for water level detection. Float value in mm. */
+ float distance;
} meshtastic_EnvironmentMetrics;
/* Power Metrics (voltage / current / etc) */
@@ -148,8 +152,8 @@ extern "C" {
/* Helper constants for enums */
#define _meshtastic_TelemetrySensorType_MIN meshtastic_TelemetrySensorType_SENSOR_UNSET
-#define _meshtastic_TelemetrySensorType_MAX meshtastic_TelemetrySensorType_BMP085
-#define _meshtastic_TelemetrySensorType_ARRAYSIZE ((meshtastic_TelemetrySensorType)(meshtastic_TelemetrySensorType_BMP085+1))
+#define _meshtastic_TelemetrySensorType_MAX meshtastic_TelemetrySensorType_RCWL9620
+#define _meshtastic_TelemetrySensorType_ARRAYSIZE ((meshtastic_TelemetrySensorType)(meshtastic_TelemetrySensorType_RCWL9620+1))
@@ -159,12 +163,12 @@ extern "C" {
/* Initializer values for message structs */
#define meshtastic_DeviceMetrics_init_default {0, 0, 0, 0, 0}
-#define meshtastic_EnvironmentMetrics_init_default {0, 0, 0, 0, 0, 0, 0}
+#define meshtastic_EnvironmentMetrics_init_default {0, 0, 0, 0, 0, 0, 0, 0}
#define meshtastic_PowerMetrics_init_default {0, 0, 0, 0, 0, 0}
#define meshtastic_AirQualityMetrics_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
#define meshtastic_Telemetry_init_default {0, 0, {meshtastic_DeviceMetrics_init_default}}
#define meshtastic_DeviceMetrics_init_zero {0, 0, 0, 0, 0}
-#define meshtastic_EnvironmentMetrics_init_zero {0, 0, 0, 0, 0, 0, 0}
+#define meshtastic_EnvironmentMetrics_init_zero {0, 0, 0, 0, 0, 0, 0, 0}
#define meshtastic_PowerMetrics_init_zero {0, 0, 0, 0, 0, 0}
#define meshtastic_AirQualityMetrics_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
#define meshtastic_Telemetry_init_zero {0, 0, {meshtastic_DeviceMetrics_init_zero}}
@@ -182,6 +186,7 @@ extern "C" {
#define meshtastic_EnvironmentMetrics_voltage_tag 5
#define meshtastic_EnvironmentMetrics_current_tag 6
#define meshtastic_EnvironmentMetrics_iaq_tag 7
+#define meshtastic_EnvironmentMetrics_distance_tag 8
#define meshtastic_PowerMetrics_ch1_voltage_tag 1
#define meshtastic_PowerMetrics_ch1_current_tag 2
#define meshtastic_PowerMetrics_ch2_voltage_tag 3
@@ -223,7 +228,8 @@ X(a, STATIC, SINGULAR, FLOAT, barometric_pressure, 3) \
X(a, STATIC, SINGULAR, FLOAT, gas_resistance, 4) \
X(a, STATIC, SINGULAR, FLOAT, voltage, 5) \
X(a, STATIC, SINGULAR, FLOAT, current, 6) \
-X(a, STATIC, SINGULAR, UINT32, iaq, 7)
+X(a, STATIC, SINGULAR, UINT32, iaq, 7) \
+X(a, STATIC, SINGULAR, FLOAT, distance, 8)
#define meshtastic_EnvironmentMetrics_CALLBACK NULL
#define meshtastic_EnvironmentMetrics_DEFAULT NULL
@@ -283,7 +289,7 @@ extern const pb_msgdesc_t meshtastic_Telemetry_msg;
#define MESHTASTIC_MESHTASTIC_TELEMETRY_PB_H_MAX_SIZE meshtastic_Telemetry_size
#define meshtastic_AirQualityMetrics_size 72
#define meshtastic_DeviceMetrics_size 27
-#define meshtastic_EnvironmentMetrics_size 34
+#define meshtastic_EnvironmentMetrics_size 39
#define meshtastic_PowerMetrics_size 30
#define meshtastic_Telemetry_size 79
diff --git a/src/modules/ExternalNotificationModule.cpp b/src/modules/ExternalNotificationModule.cpp
index a38b231af..b898e72ee 100644
--- a/src/modules/ExternalNotificationModule.cpp
+++ b/src/modules/ExternalNotificationModule.cpp
@@ -244,7 +244,8 @@ void ExternalNotificationModule::stopNow()
{
rtttl::stop();
#ifdef HAS_I2S
- audioThread->stop();
+ if (audioThread->isPlaying())
+ audioThread->stop();
#endif
nagCycleCutoff = 1; // small value
isNagging = false;
diff --git a/src/modules/PositionModule.cpp b/src/modules/PositionModule.cpp
index dcfe03f7f..658b8b5a7 100644
--- a/src/modules/PositionModule.cpp
+++ b/src/modules/PositionModule.cpp
@@ -17,6 +17,7 @@
extern "C" {
#include "mesh/compression/unishox2.h"
+#include
}
PositionModule *positionModule;
@@ -63,21 +64,15 @@ bool PositionModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, mes
}
// Log packet size and data fields
- LOG_INFO("POSITION node=%08x l=%d latI=%d lonI=%d msl=%d hae=%d geo=%d pdop=%d hdop=%d vdop=%d siv=%d fxq=%d fxt=%d pts=%d "
- "time=%d\n",
- getFrom(&mp), mp.decoded.payload.size, p.latitude_i, p.longitude_i, p.altitude, p.altitude_hae,
- p.altitude_geoidal_separation, p.PDOP, p.HDOP, p.VDOP, p.sats_in_view, p.fix_quality, p.fix_type, p.timestamp,
- p.time);
+ LOG_DEBUG("POSITION node=%08x l=%d latI=%d lonI=%d msl=%d hae=%d geo=%d pdop=%d hdop=%d vdop=%d siv=%d fxq=%d fxt=%d pts=%d "
+ "time=%d\n",
+ getFrom(&mp), mp.decoded.payload.size, p.latitude_i, p.longitude_i, p.altitude, p.altitude_hae,
+ p.altitude_geoidal_separation, p.PDOP, p.HDOP, p.VDOP, p.sats_in_view, p.fix_quality, p.fix_type, p.timestamp,
+ p.time);
if (p.time && channels.getByIndex(mp.channel).role == meshtastic_Channel_Role_PRIMARY) {
- struct timeval tv;
- uint32_t secs = p.time;
-
- tv.tv_sec = secs;
- tv.tv_usec = 0;
-
// Set from phone RTC Quality to RTCQualityNTP since it should be approximately so
- perhapsSetRTC(isLocal ? RTCQualityNTP : RTCQualityFromNet, &tv);
+ trySetRtc(p, isLocal);
}
nodeDB->updatePosition(getFrom(&mp), p);
@@ -92,6 +87,16 @@ bool PositionModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, mes
return false; // Let others look at this message also if they want
}
+void PositionModule::trySetRtc(meshtastic_Position p, bool isLocal)
+{
+ struct timeval tv;
+ uint32_t secs = p.time;
+
+ tv.tv_sec = secs;
+ tv.tv_usec = 0;
+ perhapsSetRTC(isLocal ? RTCQualityNTP : RTCQualityFromNet, &tv);
+}
+
meshtastic_MeshPacket *PositionModule::allocReply()
{
if (precision == 0) {
@@ -222,6 +227,16 @@ meshtastic_MeshPacket *PositionModule::allocAtakPli()
return mp;
}
+void PositionModule::sendOurPosition()
+{
+ bool requestReplies = currentGeneration != radioGeneration;
+ currentGeneration = radioGeneration;
+
+ // If we changed channels, ask everyone else for their latest info
+ LOG_INFO("Sending pos@%x:6 to mesh (wantReplies=%d)\n", localPosition.timestamp, requestReplies);
+ sendOurPosition(NODENUM_BROADCAST, requestReplies);
+}
+
void PositionModule::sendOurPosition(NodeNum dest, bool wantReplies, uint8_t channel)
{
// cancel any not yet sent (now stale) position packets
@@ -299,12 +314,7 @@ int32_t PositionModule::runOnce()
lastGpsLatitude = node->position.latitude_i;
lastGpsLongitude = node->position.longitude_i;
- // If we changed channels, ask everyone else for their latest info
- bool requestReplies = currentGeneration != radioGeneration;
- currentGeneration = radioGeneration;
-
- LOG_INFO("Sending pos@%x:6 to mesh (wantReplies=%d)\n", localPosition.timestamp, requestReplies);
- sendOurPosition(NODENUM_BROADCAST, requestReplies);
+ sendOurPosition();
if (config.device.role == meshtastic_Config_DeviceConfig_Role_LOST_AND_FOUND) {
sendLostAndFoundText();
}
@@ -314,29 +324,23 @@ int32_t PositionModule::runOnce()
if (hasValidPosition(node2)) {
// The minimum time (in seconds) that would pass before we are able to send a new position packet.
- const uint32_t minimumTimeThreshold =
- Default::getConfiguredOrDefaultMs(config.position.broadcast_smart_minimum_interval_secs, 30);
auto smartPosition = getDistanceTraveledSinceLastSend(node->position);
+ uint32_t msSinceLastSend = now - lastGpsSend;
- if (smartPosition.hasTraveledOverThreshold && msSinceLastSend >= minimumTimeThreshold) {
- bool requestReplies = currentGeneration != radioGeneration;
- currentGeneration = radioGeneration;
+ if (smartPosition.hasTraveledOverThreshold &&
+ Throttle::execute(
+ &lastGpsSend, minimumTimeThreshold, []() { positionModule->sendOurPosition(); },
+ []() { LOG_DEBUG("Skipping send smart broadcast due to time throttling\n"); })) {
- LOG_INFO("Sending smart pos@%x:6 to mesh (distanceTraveled=%fm, minDistanceThreshold=%im, timeElapsed=%ims, "
- "minTimeInterval=%ims)\n",
- localPosition.timestamp, smartPosition.distanceTraveled, smartPosition.distanceThreshold,
- msSinceLastSend, minimumTimeThreshold);
- sendOurPosition(NODENUM_BROADCAST, requestReplies);
+ LOG_DEBUG("Sent smart pos@%x:6 to mesh (distanceTraveled=%fm, minDistanceThreshold=%im, timeElapsed=%ims, "
+ "minTimeInterval=%ims)\n",
+ localPosition.timestamp, smartPosition.distanceTraveled, smartPosition.distanceThreshold,
+ msSinceLastSend, minimumTimeThreshold);
// Set the current coords as our last ones, after we've compared distance with current and decided to send
lastGpsLatitude = node->position.latitude_i;
lastGpsLongitude = node->position.longitude_i;
-
- /* Update lastGpsSend to now. This means if the device is stationary, then
- getPref_position_broadcast_secs will still apply.
- */
- lastGpsSend = now;
}
}
}
@@ -396,27 +400,21 @@ void PositionModule::handleNewPosition()
meshtastic_NodeInfoLite *node = nodeDB->getMeshNode(nodeDB->getNodeNum());
const meshtastic_NodeInfoLite *node2 = service.refreshLocalMeshNode(); // should guarantee there is now a position
// We limit our GPS broadcasts to a max rate
- uint32_t now = millis();
- uint32_t msSinceLastSend = now - lastGpsSend;
-
if (hasValidPosition(node2)) {
auto smartPosition = getDistanceTraveledSinceLastSend(node->position);
- if (smartPosition.hasTraveledOverThreshold) {
- bool requestReplies = currentGeneration != radioGeneration;
- currentGeneration = radioGeneration;
-
- LOG_INFO("Sending smart pos@%x:6 to mesh (distanceTraveled=%fm, minDistanceThreshold=%im, timeElapsed=%ims)\n",
- localPosition.timestamp, smartPosition.distanceTraveled, smartPosition.distanceThreshold, msSinceLastSend);
- sendOurPosition(NODENUM_BROADCAST, requestReplies);
+ uint32_t msSinceLastSend = millis() - lastGpsSend;
+ if (smartPosition.hasTraveledOverThreshold &&
+ Throttle::execute(
+ &lastGpsSend, minimumTimeThreshold, []() { positionModule->sendOurPosition(); },
+ []() { LOG_DEBUG("Skipping send smart broadcast due to time throttling\n"); })) {
+ LOG_DEBUG("Sent smart pos@%x:6 to mesh (distanceTraveled=%fm, minDistanceThreshold=%im, timeElapsed=%ims, "
+ "minTimeInterval=%ims)\n",
+ localPosition.timestamp, smartPosition.distanceTraveled, smartPosition.distanceThreshold, msSinceLastSend,
+ minimumTimeThreshold);
// Set the current coords as our last ones, after we've compared distance with current and decided to send
lastGpsLatitude = node->position.latitude_i;
lastGpsLongitude = node->position.longitude_i;
-
- /* Update lastGpsSend to now. This means if the device is stationary, then
- getPref_position_broadcast_secs will still apply.
- */
- lastGpsSend = now;
}
}
}
diff --git a/src/modules/PositionModule.h b/src/modules/PositionModule.h
index 68171ab0e..89ff50c64 100644
--- a/src/modules/PositionModule.h
+++ b/src/modules/PositionModule.h
@@ -1,4 +1,5 @@
#pragma once
+#include "Default.h"
#include "ProtobufModule.h"
#include "concurrency/OSThread.h"
@@ -29,7 +30,8 @@ class PositionModule : public ProtobufModule, private concu
/**
* Send our position into the mesh
*/
- void sendOurPosition(NodeNum dest = NODENUM_BROADCAST, bool wantReplies = false, uint8_t channel = 0);
+ void sendOurPosition(NodeNum dest, bool wantReplies = false, uint8_t channel = 0);
+ void sendOurPosition();
void handleNewPosition();
@@ -50,8 +52,12 @@ class PositionModule : public ProtobufModule, private concu
private:
struct SmartPosition getDistanceTraveledSinceLastSend(meshtastic_PositionLite currentPosition);
meshtastic_MeshPacket *allocAtakPli();
+ void trySetRtc(meshtastic_Position p, bool isLocal);
uint32_t precision;
void sendLostAndFoundText();
+
+ const uint32_t minimumTimeThreshold =
+ Default::getConfiguredOrDefaultMs(config.position.broadcast_smart_minimum_interval_secs, 30);
};
struct SmartPosition {
diff --git a/src/modules/RoutingModule.cpp b/src/modules/RoutingModule.cpp
index a52328ca4..fe1abab05 100644
--- a/src/modules/RoutingModule.cpp
+++ b/src/modules/RoutingModule.cpp
@@ -51,7 +51,7 @@ uint8_t RoutingModule::getHopLimitForResponse(uint8_t hopStart, uint8_t hopLimit
uint8_t hopsUsed = hopStart < hopLimit ? config.lora.hop_limit : hopStart - hopLimit;
if (hopsUsed > config.lora.hop_limit) {
return hopsUsed; // If the request used more hops than the limit, use the same amount of hops
- } else if (hopsUsed + 2 < config.lora.hop_limit) {
+ } else if ((uint8_t)(hopsUsed + 2) < config.lora.hop_limit) {
return hopsUsed + 2; // Use only the amount of hops needed with some margin as the way back may be different
}
}
diff --git a/src/modules/esp32/PaxcounterModule.cpp b/src/modules/esp32/PaxcounterModule.cpp
index aad7b5d63..b9fdfcb63 100644
--- a/src/modules/esp32/PaxcounterModule.cpp
+++ b/src/modules/esp32/PaxcounterModule.cpp
@@ -1,5 +1,5 @@
#include "configuration.h"
-#if defined(ARCH_ESP32)
+#if defined(ARCH_ESP32) && !MESHTASTIC_EXCLUDE_PAXCOUNTER
#include "Default.h"
#include "MeshService.h"
#include "PaxcounterModule.h"
diff --git a/src/platform/esp32/architecture.h b/src/platform/esp32/architecture.h
index 15e437bb5..27088f86f 100644
--- a/src/platform/esp32/architecture.h
+++ b/src/platform/esp32/architecture.h
@@ -117,8 +117,8 @@
#define HW_VENDOR meshtastic_HardwareModel_HELTEC_WIRELESS_PAPER
#elif defined(TLORA_T3S3_V1)
#define HW_VENDOR meshtastic_HardwareModel_TLORA_T3_S3
-#elif defined(CDEBYTE_ELORA_S3)
-#define HW_VENDOR meshtastic_HardwareModel_CDEBYTE_ELORA_S3
+#elif defined(CDEBYTE_EORA_S3)
+#define HW_VENDOR meshtastic_HardwareModel_CDEBYTE_EORA_S3
#elif defined(BETAFPV_2400_TX)
#define HW_VENDOR meshtastic_HardwareModel_BETAFPV_2400_TX
#elif defined(NANO_G1_EXPLORER)
@@ -127,6 +127,10 @@
#define HW_VENDOR meshtastic_HardwareModel_BETAFPV_900_NANO_TX
#elif defined(PICOMPUTER_S3)
#define HW_VENDOR meshtastic_HardwareModel_PICOMPUTER_S3
+#elif defined(HELTEC_HT62)
+#define HW_VENDOR meshtastic_HardwareModel_HELTEC_HT62
+#elif defined(EBYTE_ESP32_S3)
+#define HW_VENDOR meshtastic_HardwareModel_EBYTE_ESP32_S3
#elif defined(ESP32_S3_PICO)
#define HW_VENDOR meshtastic_HardwareModel_ESP32_S3_PICO
#elif defined(SENSELORA_S3)
diff --git a/src/sleep.cpp b/src/sleep.cpp
index a2a221d79..fe73a755c 100644
--- a/src/sleep.cpp
+++ b/src/sleep.cpp
@@ -157,6 +157,10 @@ void initDeepSleep()
for (uint8_t i = 0; i <= GPIO_NUM_MAX; i++) {
if (rtc_gpio_is_valid_gpio((gpio_num_t)i))
rtc_gpio_hold_dis((gpio_num_t)i);
+
+ // ESP32 (original)
+ else if (GPIO_IS_VALID_OUTPUT_GPIO((gpio_num_t)i))
+ gpio_hold_dis((gpio_num_t)i);
}
}
#endif
@@ -207,9 +211,10 @@ void doDeepSleep(uint32_t msecToWake, bool skipPreflight = false)
// esp_wifi_stop();
waitEnterSleep(skipPreflight);
-#ifdef ARCH_ESP32
+#if defined(ARCH_ESP32) && !MESHTASTIC_EXCLUDE_BLUETOOTH
// Full shutdown of bluetooth hardware
- nimbleBluetooth->deinit();
+ if (nimbleBluetooth)
+ nimbleBluetooth->deinit();
#endif
#ifdef ARCH_ESP32
@@ -258,14 +263,17 @@ void doDeepSleep(uint32_t msecToWake, bool skipPreflight = false)
}
#ifdef BUTTON_PIN
// Avoid leakage through button pin
- pinMode(BUTTON_PIN, INPUT);
- gpio_hold_en((gpio_num_t)BUTTON_PIN);
+ if (GPIO_IS_VALID_OUTPUT_GPIO(BUTTON_PIN)) {
+ pinMode(BUTTON_PIN, INPUT);
+ gpio_hold_en((gpio_num_t)BUTTON_PIN);
+ }
#endif
-
- // LoRa CS (RADIO_NSS) needs to stay HIGH, even during deep sleep
- pinMode(LORA_CS, OUTPUT);
- digitalWrite(LORA_CS, HIGH);
- gpio_hold_en((gpio_num_t)LORA_CS);
+ if (GPIO_IS_VALID_OUTPUT_GPIO(LORA_CS)) {
+ // LoRa CS (RADIO_NSS) needs to stay HIGH, even during deep sleep
+ pinMode(LORA_CS, OUTPUT);
+ digitalWrite(LORA_CS, HIGH);
+ gpio_hold_en((gpio_num_t)LORA_CS);
+ }
#endif
#ifdef HAS_PMU
diff --git a/variants/EBYTE_ESP32-S3/pins_arduino.h b/variants/EBYTE_ESP32-S3/pins_arduino.h
new file mode 100644
index 000000000..38a9103f0
--- /dev/null
+++ b/variants/EBYTE_ESP32-S3/pins_arduino.h
@@ -0,0 +1,37 @@
+// Need this file for ESP32-S3
+// No need to modify this file, changes to pins imported from variant.h
+// Most is similar to https://github.com/espressif/arduino-esp32/blob/master/variants/esp32s3/pins_arduino.h
+
+#ifndef Pins_Arduino_h
+#define Pins_Arduino_h
+
+#include
+#include
+
+#define USB_VID 0x303a
+#define USB_PID 0x1001
+
+#define EXTERNAL_NUM_INTERRUPTS 46
+#define NUM_DIGITAL_PINS 48
+#define NUM_ANALOG_INPUTS 20
+
+#define analogInputToDigitalPin(p) (((p) < 20) ? (analogChannelToDigitalPin(p)) : -1)
+#define digitalPinToInterrupt(p) \
+ (((p) < 48) ? (p) : -1) // Maybe it should be <= 48 but this is from a trustworthy source so it is likely correct
+#define digitalPinHasPWM(p) (p < 46)
+
+// Serial
+static const uint8_t TX = UART_TX;
+static const uint8_t RX = UART_RX;
+
+// Default SPI will be mapped to Radio
+static const uint8_t SS = LORA_CS;
+static const uint8_t SCK = LORA_SCK;
+static const uint8_t MOSI = LORA_MOSI;
+static const uint8_t MISO = LORA_MISO;
+
+// The default Wire will be mapped to PMU and RTC
+static const uint8_t SCL = I2C_SCL;
+static const uint8_t SDA = I2C_SDA;
+
+#endif /* Pins_Arduino_h */
diff --git a/variants/EBYTE_ESP32-S3/platformio.ini b/variants/EBYTE_ESP32-S3/platformio.ini
new file mode 100644
index 000000000..10de91386
--- /dev/null
+++ b/variants/EBYTE_ESP32-S3/platformio.ini
@@ -0,0 +1,9 @@
+[env:EBYTE_ESP32-S3]
+extends = esp32s3_base
+; board assumes the lowest spec WROOM module: 4 MB (Quad SPI) Flash, No PSRAM
+board = ESP32-S3-WROOM-1-N4
+board_level = extra
+build_flags =
+ ${esp32s3_base.build_flags}
+ -D EBYTE_ESP32_S3
+ -I variants/EBYTE_ESP32-S3
diff --git a/variants/EBYTE_ESP32-S3/variant.h b/variants/EBYTE_ESP32-S3/variant.h
new file mode 100644
index 000000000..10b39617b
--- /dev/null
+++ b/variants/EBYTE_ESP32-S3/variant.h
@@ -0,0 +1,193 @@
+// Supporting information: https://github.com/S5NC/EBYTE_ESP32-S3/
+
+// Originally developed for E22-900M30S with ESP32-S3-WROOM-1-N4
+// NOTE: Uses ESP32-S3-WROOM-1-N4.json in boards folder (via platformio.ini board field), assumes 4 MB (quad SPI) flash, no PSRAM
+
+// FIXME: implement SX12 module type autodetection and have setup for each case (add E32 support)
+// E32 has same pinout except having extra pins. I assume that the GND on it is connected internally to other GNDs so it is not a
+// problem to NC the extra GND pins.
+
+// For each EBYTE module pin in this section, provide the pin number of the ESP32-S3 you connected it to
+// The ESP32-S3 is great because YOU CAN USE PRACTICALLY ANY PINS for the connections, but avoid some pins (such as on the WROOM
+// modules the following): strapping pins (except 0 as a user button input as it already has a pulldown resistor in typical
+// application schematic) (0, 3, 45, 46), USB-reserved (19, 20), and pins which aren't present on the WROOM-2 module for
+// compatiblity as it uses octal SPI, or are likely connected internally in either WROOM version (26-37), and avoid pins whose
+// voltages are set by the SPI voltage (47, 48), and pins that don't exist (22-25) You can ALSO set the SPI pins (SX126X_CS,
+// SX126X_SCK, SX126X_MISO, SX126X_MOSI) to any pin with the ESP32-S3 due to \ GPIO Matrix / IO MUX / RTC IO MUX \, and also the
+// serial pins, but this isn't recommended for Serial0 as the WROOM modules have a 499 Ohm resistor on U0TXD (to reduce harmonics
+// but also acting as a sort of protection)
+
+// We have many free pins on the ESP32-S3-WROOM-X-Y module, perhaps it is best to use one of its pins to control TXEN, and use
+// DIO2 as an extra interrupt, but right now Meshtastic does not benefit from having another interrupt pin available.
+
+// Adding two 0-ohm links on your PCB design so that you can choose between the two modes for controlling the E22's TXEN would
+// enable future software to make the most of an extra available interrupt pin
+
+// Possible improvement: can add extremely low resistance MOSFET to physically toggle power to E22 module when in full sleep (not
+// waiting for interrupt)?
+
+// PA stands for Power Amplifier, used when transmitting to increase output power
+// LNA stands for Low Noise Amplifier, used when \ listening for / receiving \ data to increase sensitivity
+
+//////////////////////////////////////////////////////////////////////////////////
+// //
+// Have custom connections or functionality? Configure them in this section //
+// //
+//////////////////////////////////////////////////////////////////////////////////
+
+#define SX126X_CS 14 // EBYTE module's NSS pin // FIXME: rename to SX126X_SS
+#define LORA_SCK 21 // EBYTE module's SCK pin
+#define LORA_MOSI 38 // EBYTE module's MOSI pin
+#define LORA_MISO 39 // EBYTE module's MISO pin
+#define SX126X_RESET 40 // EBYTE module's NRST pin
+#define SX126X_BUSY 41 // EBYTE module's BUSY pin
+#define SX126X_DIO1 42 // EBYTE module's DIO1 pin
+// We don't define a pin for SX126X_DIO2 as Meshtastic doesn't use it as an interrupt output, so it is never connected to an MCU
+// pin! Also E22 module datasheets say not to connect it to an MCU pin.
+// We don't define a pin for SX126X_DIO3 as Meshtastic doesn't use it as an interrupt output, so it is never connected to an MCU
+// pin! Also E22 module datasheets say to use it as the TCXO's reference voltage.
+// E32 module (which uses SX1276) may not have ability to set TCXO voltage using a DIO pin.
+
+// The radio module needs to be told whether to enable RX mode or TX mode. Each radio module takes different actions based on
+// these values, but generally the path from the antenna to SX1262 is changed from signal output to signal input. Also, if there
+// are LNAs (Low-Noise Amplifiers) or PAs (Power Amplifiers) in the output or input paths, their power is also controlled by
+// these pins. You should never have both TXEN and RXEN set high, this can cause problems for some radio modules, and is
+// commonly referred to as 'undefined behaviour' in datasheets. For the SX1262, you shouldn't connect DIO2 to the MCU. DIO2 is
+// an output only, and can be controlled via SPI instructions, the use for this is to save an MCU pin by using the DIO2 pin to
+// control the RF switching mode.
+
+// Choose ONLY ONE option from below, comment in/out the '/*'s and '*/'s
+// SX126X_TXEN is the E22's [SX1262's] TXEN pin, SX126X_RXEN is the E22's [SX1262's] RXEN pin
+
+// Option 1: E22's TXEN pin connected to E22's DIO2 pin, E22's RXEN pin connected to NEGATED output of E22's DIO2 pin (more
+// expensive option hardware-wise, is the 'most proper' way, removes need for routing one/two traces from MCU to RF switching
+// pins), however you can't have E22 in low-power 'sleep' mode (TXEN and RXEN both low cannot be achieved this this option).
+/*
+#define SX126X_DIO2_AS_RF_SWITCH
+#define SX126X_TXEN RADIOLIB_NC
+#define SX126X_RXEN RADIOLIB_NC
+*/
+
+// Option 2: E22's TXEN pin connected to E22's DIO2 pin, E22's RXEN pin connected to MCU pin (cheaper option hardware-wise,
+// removes need for routing another trace from MCU to an RF switching pin).
+// /*
+#define SX126X_DIO2_AS_RF_SWITCH
+#define SX126X_TXEN RADIOLIB_NC
+#define SX126X_RXEN 10
+// */
+
+// Option 3: E22's TXEN pin connected to MCU pin, E22's RXEN pin connected to MCU pin (cheaper option hardware-wise, allows for
+// ramping up PA before transmission (add/expand on feature yourself in RadioLib) if PA takes a while to stabilise)
+// Don't define DIO2_AS_RF_SWITCH because we only use DIO2 or an MCU pin mutually exclusively to connect to E22's TXEN (to prevent
+// a short if they are both connected at the same time (suboptimal PCB design) and there's a slight non-neglibible delay and/or
+// voltage difference between DIO2 and TXEN). Can use DIO2 as an IRQ (but not in Meshtastic at the moment).
+/*
+#define SX126X_TXEN 9
+#define SX126X_RXEN 10
+*/
+
+// (NOT RECOMMENDED, if need to ramp up PA before transmission, better to use option 3)
+// Option 4: E22's TXEN pin connected to MCU pin, E22's RXEN pin connected to NEGATED output of E22's DIO2 pin (more expensive
+// option hardware-wise, allows for ramping up PA before transmission (add/expand on feature yourself in RadioLib) if PA takes
+// a while to stabilise, removes need for routing another trace from MCU to an RF switching pin, however may mean if in
+// RadioLib you don't tell DIO2 to go high to indicate transmission (so the negated output goes to RXEN to turn the LNA off)
+// then you may end up enabling E22's TXEN and RXEN pins at the same time whilst you ramp up the PA which is not ideal,
+// changing DIO2's switching advance in RadioLib may not even be possible, may be baked into the SX126x).
+/*
+#define SX126X_DIO2_AS_RF_SWITCH
+#define SX126X_TXEN 9
+#define SX126X_RXEN RADIOLIB_NC
+*/
+
+// Status
+#define LED_PIN 1
+#define LED_INVERTED 0
+// External notification
+// FIXME: Check if EXT_NOTIFY_OUT actualy has any effect and removes the need for setting the external notication pin in the
+// app/preferences
+#define EXT_NOTIFY_OUT 2 // The GPIO pin that acts as the external notification output (here we connect an LED to it)
+// Buzzer
+#define PIN_BUZZER 11
+// Buttons
+#define BUTTON_PIN 0 // Use the BOOT button as the user button
+// I2C
+#define I2C_SCL 18
+#define I2C_SDA 8
+// UART
+#define UART_TX 43
+#define UART_RX 44
+
+// Power
+// Outputting 22dBm from SX1262 results in ~30dBm E22-900M30S output (module only uses last stage of the YP2233W PA)
+// Respect local regulations! If your E22-900M30S outputs the advertised 30 dBm and you use a 6 dBi antenna, you are at the
+// equivalent of 36 EIRP (Effective Isotropic Radiated Power), which in this case is the limit for non-HAM users in the US (4W
+// EIRP, at SPECIFIC frequencies).
+// In the EU (and UK), as of now, you are allowed 27 dBm ERP which is 29.15 EIRP.
+// https://eur-lex.europa.eu/legal-content/EN/TXT/?uri=CELEX:32022D0180
+// https://www.legislation.gov.uk/uksi/1999/930/schedule/6/made
+// To respect the 29.15 dBm EIRP (at SPECIFIC frequencies, others are lower) EU limit with a 2.5 dBi gain antenna, consulting
+// https://github.com/S5NC/EBYTE_ESP32-S3/blob/main/power%20testing.txt, assuming 0.1 dBm insertion loss, output 20 dBm from the
+// E22-900M30S's SX1262. It is worth noting that if you are in this situation and don't have a HAM license, you may be better off
+// with a lower gain antenna, and output the difference as a higher total power input into the antenna, as your EIRP would be the
+// same, but you would get a wider angle of coverage. Also take insertion loss and possibly VSWR into account
+// (https://www.everythingrf.com/tech-resources/vswr). Please check regulations yourself and check airtime, usage (for example
+// whether you are airborne), frequency, and power laws.
+#define SX126X_MAX_POWER 22 // SX126xInterface.cpp defaults to 22 if not defined, but here we define it for good practice
+
+// Display
+// FIXME: change behavior in src to default to not having screen if is undefined
+// FIXME: remove 0/1 option for HAS_SCREEN in src, change to being defined or not
+// FIXME: check if it actually causes a crash when not specifiying that a display isn't present
+#define HAS_SCREEN 0 // Assume no screen present by default to prevent crash...
+
+// GPS
+// FIXME: unsure what to define HAS_GPS as if GPS isn't always present
+#define HAS_GPS 1 // Don't need to set this to 0 to prevent a crash as it doesn't crash if GPS not found, will probe by default
+#define PIN_GPS_EN 15
+#define GPS_EN_ACTIVE 1
+#define GPS_TX_PIN 16
+#define GPS_RX_PIN 17
+
+/////////////////////////////////////////////////////////////////////////////////
+// //
+// You should have no need to modify the code below, nor in pins_arduino.h //
+// //
+/////////////////////////////////////////////////////////////////////////////////
+
+#define USE_SX1262 // E22-900M30S, E22-900M22S, and E22-900MM22S (not E220!) use SX1262
+#define USE_SX1268 // E22-400M30S, E22-400M33S, E22-400M22S, and E22-400MM22S use SX1268
+
+// The below isn't needed as we directly define SX126X_TXEN and SX126X_RXEN instead of using proxies E22_TXEN and E22_RXEN
+/*
+// FALLBACK: If somehow E22_TXEN isn't defined or clearly isn't a valid pin number, set it to RADIOLIB_NC to avoid SX126X_TXEN
+being defined but having no value #if (!defined(E22_TXEN) || !(0 <= E22_TXEN && E22_TXEN <= 48)) #define E22_TXEN RADIOLIB_NC
+#endif
+// FALLBACK: If somehow E22_RXEN isn't defined or clearly isn't a valid pin number, set it to RADIOLIB_NC to avoid SX126X_RXEN
+being defined but having no value #if (!defined(E22_RXEN) || !(0 <= E22_RXEN && E22_RXEN <= 48)) #define E22_RXEN RADIOLIB_NC
+#endif
+#define SX126X_TXEN E22_TXEN
+#define SX126X_RXEN E22_RXEN
+*/
+
+// E22 series TCXO voltage is 1.8V per https://www.ebyte.com/en/pdf-down.aspx?id=781 (source
+// https://github.com/jgromes/RadioLib/issues/12#issuecomment-520695575), so set it as such
+#define SX126X_DIO3_TCXO_VOLTAGE 1.8
+
+#define LORA_CS SX126X_CS // FIXME: for some reason both are used in /src
+
+// Many of the below values would only be used if USE_RF95 was defined, but it's not as we aren't actually using an RF95, just
+// that the 4 pins above are named like it If they aren't used they don't need to be defined and doing so cause confusion to those
+// adapting this file LORA_RESET value is never used in src (as we are not using RF95), so no need to define LORA_DIO0 is not used
+// in src (as we are not using RF95) as SX1262 does not have it per SX1262 datasheet, so no need to define
+// FIXME: confirm that the linked lines below are actually only called when using the SX126x or SX128x and no other modules
+// then use SX126X_DIO1 and SX128X_DIO1 respectively for that purpose, removing the need for RF95-style LORA_* definitions when
+// the RF95 isn't used
+#define LORA_DIO1 \
+ SX126X_DIO1 // The old name is used in
+ // https://github.com/meshtastic/firmware/blob/7eff5e7bcb2084499b723c5e3846c15ee089e36d/src/sleep.cpp#L298, so
+ // must also define the old name
+// LORA_DIO2 value is never used in src (as we are not using RF95), so no need to define, and if DIO2_AS_RF_SWITCH is set then it
+// cannot serve any extra function even if requested to LORA_DIO3 value is never used in src (as we are not using RF95), so no
+// need to define, and DIO3_AS_TCXO_AT_1V8 is set so it cannot serve any extra function even if requested to (from 13.3.2.1
+// DioxMask in SX1262 datasheet: Note that if DIO2 or DIO3 are used to control the RF Switch or the TCXO, the IRQ will not be
+// generated even if it is mapped to the pins.)
\ No newline at end of file
diff --git a/variants/rak11310/variant.h b/variants/rak11310/variant.h
index ba3d4fed7..f9dcbd91a 100644
--- a/variants/rak11310/variant.h
+++ b/variants/rak11310/variant.h
@@ -14,7 +14,7 @@
#define BATTERY_PIN 26
#define BATTERY_SENSE_RESOLUTION_BITS ADC_RESOLUTION
// ratio of voltage divider = 3.0 (R17=200k, R18=100k)
-#define ADC_MULTIPLIER 3.1 // 3.0 + a bit for being optimistic
+#define ADC_MULTIPLIER 1.84
#define DETECTION_SENSOR_EN 28
@@ -47,4 +47,4 @@
// DIO2 controlls an antenna switch and the TCXO voltage is controlled by DIO3
#define SX126X_DIO2_AS_RF_SWITCH
#define SX126X_DIO3_TCXO_VOLTAGE 1.8
-#endif
\ No newline at end of file
+#endif