::isActivelyReceiving()
{
uint16_t irq = lora.getIrqStatus();
diff --git a/src/mesh/SinglePortModule.h b/src/mesh/SinglePortModule.h
index 6fa69d964..a5aaa2582 100644
--- a/src/mesh/SinglePortModule.h
+++ b/src/mesh/SinglePortModule.h
@@ -3,7 +3,7 @@
#include "Router.h"
/**
- * Most modules are only interested in sending/receving one particular portnum. This baseclass simplifies that common
+ * Most modules are only interested in sending/receiving one particular portnum. This baseclass simplifies that common
* case.
*/
class SinglePortModule : public MeshModule
diff --git a/src/mesh/compression/unishox2.c b/src/mesh/compression/unishox2.c
index 1632f970a..99c62f659 100644
--- a/src/mesh/compression/unishox2.c
+++ b/src/mesh/compression/unishox2.c
@@ -57,7 +57,7 @@ uint8_t usx_code_94[94];
uint8_t usx_vcodes[] = {0x00, 0x40, 0x60, 0x80, 0x90, 0xA0, 0xB0, 0xC0, 0xD0, 0xD8, 0xE0, 0xE4, 0xE8, 0xEC,
0xEE, 0xF0, 0xF2, 0xF4, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF};
-/// Length of each veritical code
+/// Length of each vertical code
uint8_t usx_vcode_lens[] = {2, 3, 3, 4, 4, 4, 4, 4, 5, 5, 6, 6, 6, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8};
/// Vertical Codes and Set number for frequent sequences in sets USX_SYM and USX_NUM. First 3 bits indicate set (USX_SYM/USX_NUM)
@@ -188,7 +188,7 @@ int append_switch_code(char *out, int olen, int ol, uint8_t state)
return ol;
}
-/// Appends given horizontal and veritical code bits to out
+/// Appends given horizontal and vertical code bits to out
int append_code(char *out, int olen, int ol, uint8_t code, uint8_t *state, const uint8_t usx_hcodes[],
const uint8_t usx_hcode_lens[])
{
@@ -888,7 +888,7 @@ int read8bitCode(const char *in, int len, int bit_no)
return code;
}
-/// The list of veritical codes is split into 5 sections. Used by readVCodeIdx()
+/// The list of vertical codes is split into 5 sections. Used by readVCodeIdx()
#define SECTION_COUNT 5
/// Used by readVCodeIdx() for finding the section under which the code read using read8bitCode() falls
uint8_t usx_vsections[] = {0x7F, 0xBF, 0xDF, 0xEF, 0xFF};
@@ -915,7 +915,7 @@ uint8_t usx_vcode_lookup[36] = {(1 << 5) + 0, (1 << 5) + 0, (2 << 5) + 1, (2
/// compared to using a 256 uint8_t buffer to decode the next 8 bits read by read8bitCode() \n
/// by splitting the list of vertical codes. \n
/// Decoder is designed for using less memory, not speed. \n
-/// Returns the veritical code index or 99 if match could not be found. \n
+/// Returns the vertical code index or 99 if match could not be found. \n
/// Also updates bit_no_p with how many ever bits used by the vertical code.
int readVCodeIdx(const char *in, int len, int *bit_no_p)
{
diff --git a/src/mesh/compression/unishox2.h b/src/mesh/compression/unishox2.h
index e3674fb7c..a5117a5de 100644
--- a/src/mesh/compression/unishox2.h
+++ b/src/mesh/compression/unishox2.h
@@ -198,45 +198,45 @@
2, 2, 2, 2, 0 \
}
-/// Default frequently occuring sequences. When composition of text is know beforehand, the other sequences in this section can be
-/// used to achieve more compression.
+/// Default frequently occurring sequences. When composition of text is know beforehand, the other sequences in this section can
+/// be used to achieve more compression.
#define USX_FREQ_SEQ_DFLT \
(const char *[]) \
{ \
"\": \"", "\": ", "", "=\"", "\":\"", "://" \
}
-/// Frequently occuring sequences in text content
+/// Frequently occurring sequences in text content
#define USX_FREQ_SEQ_TXT \
(const char *[]) \
{ \
" the ", " and ", "tion", " with", "ing", "ment" \
}
-/// Frequently occuring sequences in URL content
+/// Frequently occurring sequences in URL content
#define USX_FREQ_SEQ_URL \
(const char *[]) \
{ \
"https://", "www.", ".com", "http://", ".org", ".net" \
}
-/// Frequently occuring sequences in JSON content
+/// Frequently occurring sequences in JSON content
#define USX_FREQ_SEQ_JSON \
(const char *[]) \
{ \
"\": \"", "\": ", "\",", "}}}", "\":\"", "}}" \
}
-/// Frequently occuring sequences in HTML content
+/// Frequently occurring sequences in HTML content
#define USX_FREQ_SEQ_HTML \
(const char *[]) \
{ \
"", "=\"", "div", "href", "class", "" \
}
-/// Frequently occuring sequences in XML content
+/// Frequently occurring sequences in XML content
#define USX_FREQ_SEQ_XML \
(const char *[]) \
{ \
"", "=\"", "\">", "connected()) {
+ if (mqtt && !moduleConfig.mqtt.proxy_to_client_enabled && !mqtt->isConnectedDirectly()) {
mqtt->reconnect();
}
}
@@ -87,7 +87,6 @@ static int32_t reconnectETH()
perhapsSetRTC(RTCQualityNTP, &tv);
ntp_renew = millis() + 43200 * 1000; // success, refresh every 12 hours
-
} else {
LOG_ERROR("NTP Update failed\n");
ntp_renew = millis() + 300 * 1000; // failure, retry every 5 minutes
@@ -170,7 +169,6 @@ bool initEthernet()
ethEvent = new Periodic("ethConnect", reconnectETH);
return true;
-
} else {
LOG_INFO("Not using Ethernet\n");
return false;
diff --git a/src/mesh/generated/meshtastic/deviceonly.pb.h b/src/mesh/generated/meshtastic/deviceonly.pb.h
index d0c3b7bd8..a093c9fe2 100644
--- a/src/mesh/generated/meshtastic/deviceonly.pb.h
+++ b/src/mesh/generated/meshtastic/deviceonly.pb.h
@@ -323,7 +323,7 @@ extern const pb_msgdesc_t meshtastic_NodeRemoteHardwarePin_msg;
#define meshtastic_DeviceState_size 35056
#define meshtastic_NodeInfoLite_size 151
#define meshtastic_NodeRemoteHardwarePin_size 29
-#define meshtastic_OEMStore_size 3152
+#define meshtastic_OEMStore_size 3154
#define meshtastic_PositionLite_size 28
#ifdef __cplusplus
diff --git a/src/mesh/generated/meshtastic/localonly.pb.h b/src/mesh/generated/meshtastic/localonly.pb.h
index d70acc7fc..b7199a001 100644
--- a/src/mesh/generated/meshtastic/localonly.pb.h
+++ b/src/mesh/generated/meshtastic/localonly.pb.h
@@ -163,7 +163,7 @@ extern const pb_msgdesc_t meshtastic_LocalModuleConfig_msg;
/* Maximum encoded size of messages (where known) */
#define meshtastic_LocalConfig_size 461
-#define meshtastic_LocalModuleConfig_size 545
+#define meshtastic_LocalModuleConfig_size 547
#ifdef __cplusplus
} /* extern "C" */
diff --git a/src/mesh/generated/meshtastic/mesh.pb.c b/src/mesh/generated/meshtastic/mesh.pb.c
index ce7d48b14..790f8be2d 100644
--- a/src/mesh/generated/meshtastic/mesh.pb.c
+++ b/src/mesh/generated/meshtastic/mesh.pb.c
@@ -24,6 +24,9 @@ PB_BIND(meshtastic_Data, meshtastic_Data, 2)
PB_BIND(meshtastic_Waypoint, meshtastic_Waypoint, AUTO)
+PB_BIND(meshtastic_MqttClientProxyMessage, meshtastic_MqttClientProxyMessage, 2)
+
+
PB_BIND(meshtastic_MeshPacket, meshtastic_MeshPacket, 2)
diff --git a/src/mesh/generated/meshtastic/mesh.pb.h b/src/mesh/generated/meshtastic/mesh.pb.h
index 0ed2f8e68..6007265d5 100644
--- a/src/mesh/generated/meshtastic/mesh.pb.h
+++ b/src/mesh/generated/meshtastic/mesh.pb.h
@@ -97,6 +97,14 @@ typedef enum _meshtastic_HardwareModel {
meshtastic_HardwareModel_BETAFPV_900_NANO_TX = 46,
/* Raspberry Pi Pico (W) with Waveshare SX1262 LoRa Node Module */
meshtastic_HardwareModel_RPI_PICO = 47,
+ /* Heltec Wireless Tracker with ESP32-S3 CPU, built-in GPS, and TFT */
+ meshtastic_HardwareModel_HELTEC_WIRELESS_TRACKER = 48,
+ /* Heltec Wireless Paper with ESP32-S3 CPU and E-Ink display */
+ meshtastic_HardwareModel_HELTEC_WIRELESS_PAPER = 49,
+ /* LilyGo T-Deck with ESP32-S3 CPU, Keyboard, and IPS display */
+ meshtastic_HardwareModel_T_DECK = 50,
+ /* LilyGo T-Watch S3 with ESP32-S3 CPU and IPS display */
+ meshtastic_HardwareModel_T_WATCH_S3 = 51,
/* ------------------------------------------------------------------------------------------------------------------------------------------
Reserved ID For developing private Ports. These will show up in live traffic sparsely, so we can use a high number. Keep it within 8 bits.
------------------------------------------------------------------------------------------------------------------------------------------ */
@@ -462,6 +470,22 @@ typedef struct _meshtastic_Waypoint {
uint32_t icon;
} meshtastic_Waypoint;
+typedef PB_BYTES_ARRAY_T(435) meshtastic_MqttClientProxyMessage_data_t;
+/* This message will be proxied over the PhoneAPI for the client to deliver to the MQTT server */
+typedef struct _meshtastic_MqttClientProxyMessage {
+ /* The MQTT topic this message will be sent /received on */
+ char topic[60];
+ pb_size_t which_payload_variant;
+ union {
+ /* Bytes */
+ meshtastic_MqttClientProxyMessage_data_t data;
+ /* Text */
+ char text[435];
+ } payload_variant;
+ /* Whether the message should be retained (or not) */
+ bool retained;
+} meshtastic_MqttClientProxyMessage;
+
typedef PB_BYTES_ARRAY_T(256) meshtastic_MeshPacket_encrypted_t;
/* A packet envelope sent/received over the mesh
only payload_variant is sent in the payload portion of the LORA packet.
@@ -683,6 +707,8 @@ typedef struct _meshtastic_ToRadio {
(Sending this message is optional for clients) */
bool disconnect;
meshtastic_XModem xmodemPacket;
+ /* MQTT Client Proxy Message (for client / phone subscribed to MQTT sending to device) */
+ meshtastic_MqttClientProxyMessage mqttClientProxyMessage;
};
} meshtastic_ToRadio;
@@ -780,6 +806,8 @@ typedef struct _meshtastic_FromRadio {
meshtastic_XModem xmodemPacket;
/* Device metadata message */
meshtastic_DeviceMetadata metadata;
+ /* MQTT Client Proxy Message (device sending to client / phone for publishing to MQTT) */
+ meshtastic_MqttClientProxyMessage mqttClientProxyMessage;
};
} meshtastic_FromRadio;
@@ -836,6 +864,7 @@ extern "C" {
#define meshtastic_Data_portnum_ENUMTYPE meshtastic_PortNum
+
#define meshtastic_MeshPacket_priority_ENUMTYPE meshtastic_MeshPacket_Priority
#define meshtastic_MeshPacket_delayed_ENUMTYPE meshtastic_MeshPacket_Delayed
@@ -862,6 +891,7 @@ extern "C" {
#define meshtastic_Routing_init_default {0, {meshtastic_RouteDiscovery_init_default}}
#define meshtastic_Data_init_default {_meshtastic_PortNum_MIN, {0, {0}}, 0, 0, 0, 0, 0, 0}
#define meshtastic_Waypoint_init_default {0, 0, 0, 0, 0, "", "", 0}
+#define meshtastic_MqttClientProxyMessage_init_default {"", 0, {{0, {0}}}, 0}
#define meshtastic_MeshPacket_init_default {0, 0, 0, 0, {meshtastic_Data_init_default}, 0, 0, 0, 0, 0, _meshtastic_MeshPacket_Priority_MIN, 0, _meshtastic_MeshPacket_Delayed_MIN}
#define meshtastic_NodeInfo_init_default {0, false, meshtastic_User_init_default, false, meshtastic_Position_init_default, 0, 0, false, meshtastic_DeviceMetrics_init_default, 0}
#define meshtastic_MyNodeInfo_init_default {0, 0, 0, "", _meshtastic_CriticalErrorCode_MIN, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0}, 0, {0, 0, 0, 0, 0, 0, 0, 0}, 0, 0, 0}
@@ -879,6 +909,7 @@ extern "C" {
#define meshtastic_Routing_init_zero {0, {meshtastic_RouteDiscovery_init_zero}}
#define meshtastic_Data_init_zero {_meshtastic_PortNum_MIN, {0, {0}}, 0, 0, 0, 0, 0, 0}
#define meshtastic_Waypoint_init_zero {0, 0, 0, 0, 0, "", "", 0}
+#define meshtastic_MqttClientProxyMessage_init_zero {"", 0, {{0, {0}}}, 0}
#define meshtastic_MeshPacket_init_zero {0, 0, 0, 0, {meshtastic_Data_init_zero}, 0, 0, 0, 0, 0, _meshtastic_MeshPacket_Priority_MIN, 0, _meshtastic_MeshPacket_Delayed_MIN}
#define meshtastic_NodeInfo_init_zero {0, false, meshtastic_User_init_zero, false, meshtastic_Position_init_zero, 0, 0, false, meshtastic_DeviceMetrics_init_zero, 0}
#define meshtastic_MyNodeInfo_init_zero {0, 0, 0, "", _meshtastic_CriticalErrorCode_MIN, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0}, 0, {0, 0, 0, 0, 0, 0, 0, 0}, 0, 0, 0}
@@ -940,6 +971,10 @@ extern "C" {
#define meshtastic_Waypoint_name_tag 6
#define meshtastic_Waypoint_description_tag 7
#define meshtastic_Waypoint_icon_tag 8
+#define meshtastic_MqttClientProxyMessage_topic_tag 1
+#define meshtastic_MqttClientProxyMessage_data_tag 2
+#define meshtastic_MqttClientProxyMessage_text_tag 3
+#define meshtastic_MqttClientProxyMessage_retained_tag 4
#define meshtastic_MeshPacket_from_tag 1
#define meshtastic_MeshPacket_to_tag 2
#define meshtastic_MeshPacket_channel_tag 3
@@ -988,6 +1023,7 @@ extern "C" {
#define meshtastic_ToRadio_want_config_id_tag 3
#define meshtastic_ToRadio_disconnect_tag 4
#define meshtastic_ToRadio_xmodemPacket_tag 5
+#define meshtastic_ToRadio_mqttClientProxyMessage_tag 6
#define meshtastic_Compressed_portnum_tag 1
#define meshtastic_Compressed_data_tag 2
#define meshtastic_Neighbor_node_id_tag 1
@@ -1018,6 +1054,7 @@ extern "C" {
#define meshtastic_FromRadio_queueStatus_tag 11
#define meshtastic_FromRadio_xmodemPacket_tag 12
#define meshtastic_FromRadio_metadata_tag 13
+#define meshtastic_FromRadio_mqttClientProxyMessage_tag 14
/* Struct field encoding specification for nanopb */
#define meshtastic_Position_FIELDLIST(X, a) \
@@ -1094,6 +1131,14 @@ X(a, STATIC, SINGULAR, FIXED32, icon, 8)
#define meshtastic_Waypoint_CALLBACK NULL
#define meshtastic_Waypoint_DEFAULT NULL
+#define meshtastic_MqttClientProxyMessage_FIELDLIST(X, a) \
+X(a, STATIC, SINGULAR, STRING, topic, 1) \
+X(a, STATIC, ONEOF, BYTES, (payload_variant,data,payload_variant.data), 2) \
+X(a, STATIC, ONEOF, STRING, (payload_variant,text,payload_variant.text), 3) \
+X(a, STATIC, SINGULAR, BOOL, retained, 4)
+#define meshtastic_MqttClientProxyMessage_CALLBACK NULL
+#define meshtastic_MqttClientProxyMessage_DEFAULT NULL
+
#define meshtastic_MeshPacket_FIELDLIST(X, a) \
X(a, STATIC, SINGULAR, FIXED32, from, 1) \
X(a, STATIC, SINGULAR, FIXED32, to, 2) \
@@ -1175,7 +1220,8 @@ X(a, STATIC, ONEOF, MESSAGE, (payload_variant,moduleConfig,moduleConfig),
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,channel,channel), 10) \
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,queueStatus,queueStatus), 11) \
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,xmodemPacket,xmodemPacket), 12) \
-X(a, STATIC, ONEOF, MESSAGE, (payload_variant,metadata,metadata), 13)
+X(a, STATIC, ONEOF, MESSAGE, (payload_variant,metadata,metadata), 13) \
+X(a, STATIC, ONEOF, MESSAGE, (payload_variant,mqttClientProxyMessage,mqttClientProxyMessage), 14)
#define meshtastic_FromRadio_CALLBACK NULL
#define meshtastic_FromRadio_DEFAULT NULL
#define meshtastic_FromRadio_payload_variant_packet_MSGTYPE meshtastic_MeshPacket
@@ -1188,16 +1234,19 @@ X(a, STATIC, ONEOF, MESSAGE, (payload_variant,metadata,metadata), 13)
#define meshtastic_FromRadio_payload_variant_queueStatus_MSGTYPE meshtastic_QueueStatus
#define meshtastic_FromRadio_payload_variant_xmodemPacket_MSGTYPE meshtastic_XModem
#define meshtastic_FromRadio_payload_variant_metadata_MSGTYPE meshtastic_DeviceMetadata
+#define meshtastic_FromRadio_payload_variant_mqttClientProxyMessage_MSGTYPE meshtastic_MqttClientProxyMessage
#define meshtastic_ToRadio_FIELDLIST(X, a) \
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,packet,packet), 1) \
X(a, STATIC, ONEOF, UINT32, (payload_variant,want_config_id,want_config_id), 3) \
X(a, STATIC, ONEOF, BOOL, (payload_variant,disconnect,disconnect), 4) \
-X(a, STATIC, ONEOF, MESSAGE, (payload_variant,xmodemPacket,xmodemPacket), 5)
+X(a, STATIC, ONEOF, MESSAGE, (payload_variant,xmodemPacket,xmodemPacket), 5) \
+X(a, STATIC, ONEOF, MESSAGE, (payload_variant,mqttClientProxyMessage,mqttClientProxyMessage), 6)
#define meshtastic_ToRadio_CALLBACK NULL
#define meshtastic_ToRadio_DEFAULT NULL
#define meshtastic_ToRadio_payload_variant_packet_MSGTYPE meshtastic_MeshPacket
#define meshtastic_ToRadio_payload_variant_xmodemPacket_MSGTYPE meshtastic_XModem
+#define meshtastic_ToRadio_payload_variant_mqttClientProxyMessage_MSGTYPE meshtastic_MqttClientProxyMessage
#define meshtastic_Compressed_FIELDLIST(X, a) \
X(a, STATIC, SINGULAR, UENUM, portnum, 1) \
@@ -1239,6 +1288,7 @@ extern const pb_msgdesc_t meshtastic_RouteDiscovery_msg;
extern const pb_msgdesc_t meshtastic_Routing_msg;
extern const pb_msgdesc_t meshtastic_Data_msg;
extern const pb_msgdesc_t meshtastic_Waypoint_msg;
+extern const pb_msgdesc_t meshtastic_MqttClientProxyMessage_msg;
extern const pb_msgdesc_t meshtastic_MeshPacket_msg;
extern const pb_msgdesc_t meshtastic_NodeInfo_msg;
extern const pb_msgdesc_t meshtastic_MyNodeInfo_msg;
@@ -1258,6 +1308,7 @@ extern const pb_msgdesc_t meshtastic_DeviceMetadata_msg;
#define meshtastic_Routing_fields &meshtastic_Routing_msg
#define meshtastic_Data_fields &meshtastic_Data_msg
#define meshtastic_Waypoint_fields &meshtastic_Waypoint_msg
+#define meshtastic_MqttClientProxyMessage_fields &meshtastic_MqttClientProxyMessage_msg
#define meshtastic_MeshPacket_fields &meshtastic_MeshPacket_msg
#define meshtastic_NodeInfo_fields &meshtastic_NodeInfo_msg
#define meshtastic_MyNodeInfo_fields &meshtastic_MyNodeInfo_msg
@@ -1274,9 +1325,10 @@ extern const pb_msgdesc_t meshtastic_DeviceMetadata_msg;
#define meshtastic_Compressed_size 243
#define meshtastic_Data_size 270
#define meshtastic_DeviceMetadata_size 46
-#define meshtastic_FromRadio_size 330
+#define meshtastic_FromRadio_size 510
#define meshtastic_LogRecord_size 81
#define meshtastic_MeshPacket_size 321
+#define meshtastic_MqttClientProxyMessage_size 501
#define meshtastic_MyNodeInfo_size 179
#define meshtastic_NeighborInfo_size 142
#define meshtastic_Neighbor_size 11
@@ -1285,7 +1337,7 @@ extern const pb_msgdesc_t meshtastic_DeviceMetadata_msg;
#define meshtastic_QueueStatus_size 23
#define meshtastic_RouteDiscovery_size 40
#define meshtastic_Routing_size 42
-#define meshtastic_ToRadio_size 324
+#define meshtastic_ToRadio_size 504
#define meshtastic_User_size 77
#define meshtastic_Waypoint_size 165
diff --git a/src/mesh/generated/meshtastic/module_config.pb.c b/src/mesh/generated/meshtastic/module_config.pb.c
index 9352feb17..86614d18c 100644
--- a/src/mesh/generated/meshtastic/module_config.pb.c
+++ b/src/mesh/generated/meshtastic/module_config.pb.c
@@ -39,6 +39,9 @@ PB_BIND(meshtastic_ModuleConfig_TelemetryConfig, meshtastic_ModuleConfig_Telemet
PB_BIND(meshtastic_ModuleConfig_CannedMessageConfig, meshtastic_ModuleConfig_CannedMessageConfig, AUTO)
+PB_BIND(meshtastic_ModuleConfig_AmbientLightingConfig, meshtastic_ModuleConfig_AmbientLightingConfig, AUTO)
+
+
PB_BIND(meshtastic_RemoteHardwarePin, meshtastic_RemoteHardwarePin, AUTO)
diff --git a/src/mesh/generated/meshtastic/module_config.pb.h b/src/mesh/generated/meshtastic/module_config.pb.h
index 6273a89ae..43b330b04 100644
--- a/src/mesh/generated/meshtastic/module_config.pb.h
+++ b/src/mesh/generated/meshtastic/module_config.pb.h
@@ -112,6 +112,8 @@ typedef struct _meshtastic_ModuleConfig_MQTTConfig {
/* The root topic to use for MQTT messages. Default is "msh".
This is useful if you want to use a single MQTT server for multiple meshtastic networks and separate them via ACLs */
char root[16];
+ /* If true, we can use the connected phone / client to proxy messages to MQTT instead of a direct connection */
+ bool proxy_to_client_enabled;
} meshtastic_ModuleConfig_MQTTConfig;
/* NeighborInfoModule Config */
@@ -279,6 +281,20 @@ typedef struct _meshtastic_ModuleConfig_CannedMessageConfig {
bool send_bell;
} meshtastic_ModuleConfig_CannedMessageConfig;
+/* Ambient Lighting Module - Settings for control of onboard LEDs to allow users to adjust the brightness levels and respective color levels.
+Initially created for the RAK14001 RGB LED module. */
+typedef struct _meshtastic_ModuleConfig_AmbientLightingConfig {
+ /* Sets LED to on or off. */
+ bool led_state;
+ /* Sets the overall current for the LED, firmware side range for the RAK14001 is 1-31, but users should be given a range of 0-100% */
+ uint8_t current;
+ uint8_t red; /* Red level */
+ /* Sets the green level of the LED, firmware side values are 0-255, but users should be given a range of 0-100% */
+ uint8_t green; /* Green level */
+ /* Sets the blue level of the LED, firmware side values are 0-255, but users should be given a range of 0-100% */
+ uint8_t blue; /* Blue level */
+} meshtastic_ModuleConfig_AmbientLightingConfig;
+
/* A GPIO pin definition for remote hardware module */
typedef struct _meshtastic_RemoteHardwarePin {
/* GPIO Pin number (must match Arduino) */
@@ -324,6 +340,8 @@ typedef struct _meshtastic_ModuleConfig {
meshtastic_ModuleConfig_RemoteHardwareConfig remote_hardware;
/* TODO: REPLACE */
meshtastic_ModuleConfig_NeighborInfoConfig neighbor_info;
+ /* TODO: REPLACE */
+ meshtastic_ModuleConfig_AmbientLightingConfig ambient_lighting;
} payload_variant;
} meshtastic_ModuleConfig;
@@ -370,12 +388,13 @@ extern "C" {
#define meshtastic_ModuleConfig_CannedMessageConfig_inputbroker_event_ccw_ENUMTYPE meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar
#define meshtastic_ModuleConfig_CannedMessageConfig_inputbroker_event_press_ENUMTYPE meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar
+
#define meshtastic_RemoteHardwarePin_type_ENUMTYPE meshtastic_RemoteHardwarePinType
/* Initializer values for message structs */
#define meshtastic_ModuleConfig_init_default {0, {meshtastic_ModuleConfig_MQTTConfig_init_default}}
-#define meshtastic_ModuleConfig_MQTTConfig_init_default {0, "", "", "", 0, 0, 0, ""}
+#define meshtastic_ModuleConfig_MQTTConfig_init_default {0, "", "", "", 0, 0, 0, "", 0}
#define meshtastic_ModuleConfig_RemoteHardwareConfig_init_default {0, 0, 0, {meshtastic_RemoteHardwarePin_init_default, meshtastic_RemoteHardwarePin_init_default, meshtastic_RemoteHardwarePin_init_default, meshtastic_RemoteHardwarePin_init_default}}
#define meshtastic_ModuleConfig_NeighborInfoConfig_init_default {0, 0}
#define meshtastic_ModuleConfig_AudioConfig_init_default {0, 0, _meshtastic_ModuleConfig_AudioConfig_Audio_Baud_MIN, 0, 0, 0, 0}
@@ -385,9 +404,10 @@ extern "C" {
#define meshtastic_ModuleConfig_RangeTestConfig_init_default {0, 0, 0}
#define meshtastic_ModuleConfig_TelemetryConfig_init_default {0, 0, 0, 0, 0, 0, 0}
#define meshtastic_ModuleConfig_CannedMessageConfig_init_default {0, 0, 0, 0, _meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_MIN, _meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_MIN, _meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_MIN, 0, 0, "", 0}
+#define meshtastic_ModuleConfig_AmbientLightingConfig_init_default {0, 0, 0, 0, 0}
#define meshtastic_RemoteHardwarePin_init_default {0, "", _meshtastic_RemoteHardwarePinType_MIN}
#define meshtastic_ModuleConfig_init_zero {0, {meshtastic_ModuleConfig_MQTTConfig_init_zero}}
-#define meshtastic_ModuleConfig_MQTTConfig_init_zero {0, "", "", "", 0, 0, 0, ""}
+#define meshtastic_ModuleConfig_MQTTConfig_init_zero {0, "", "", "", 0, 0, 0, "", 0}
#define meshtastic_ModuleConfig_RemoteHardwareConfig_init_zero {0, 0, 0, {meshtastic_RemoteHardwarePin_init_zero, meshtastic_RemoteHardwarePin_init_zero, meshtastic_RemoteHardwarePin_init_zero, meshtastic_RemoteHardwarePin_init_zero}}
#define meshtastic_ModuleConfig_NeighborInfoConfig_init_zero {0, 0}
#define meshtastic_ModuleConfig_AudioConfig_init_zero {0, 0, _meshtastic_ModuleConfig_AudioConfig_Audio_Baud_MIN, 0, 0, 0, 0}
@@ -397,6 +417,7 @@ extern "C" {
#define meshtastic_ModuleConfig_RangeTestConfig_init_zero {0, 0, 0}
#define meshtastic_ModuleConfig_TelemetryConfig_init_zero {0, 0, 0, 0, 0, 0, 0}
#define meshtastic_ModuleConfig_CannedMessageConfig_init_zero {0, 0, 0, 0, _meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_MIN, _meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_MIN, _meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_MIN, 0, 0, "", 0}
+#define meshtastic_ModuleConfig_AmbientLightingConfig_init_zero {0, 0, 0, 0, 0}
#define meshtastic_RemoteHardwarePin_init_zero {0, "", _meshtastic_RemoteHardwarePinType_MIN}
/* Field tags (for use in manual encoding/decoding) */
@@ -408,6 +429,7 @@ extern "C" {
#define meshtastic_ModuleConfig_MQTTConfig_json_enabled_tag 6
#define meshtastic_ModuleConfig_MQTTConfig_tls_enabled_tag 7
#define meshtastic_ModuleConfig_MQTTConfig_root_tag 8
+#define meshtastic_ModuleConfig_MQTTConfig_proxy_to_client_enabled_tag 9
#define meshtastic_ModuleConfig_NeighborInfoConfig_enabled_tag 1
#define meshtastic_ModuleConfig_NeighborInfoConfig_update_interval_tag 2
#define meshtastic_ModuleConfig_AudioConfig_codec2_enabled_tag 1
@@ -465,6 +487,11 @@ extern "C" {
#define meshtastic_ModuleConfig_CannedMessageConfig_enabled_tag 9
#define meshtastic_ModuleConfig_CannedMessageConfig_allow_input_source_tag 10
#define meshtastic_ModuleConfig_CannedMessageConfig_send_bell_tag 11
+#define meshtastic_ModuleConfig_AmbientLightingConfig_led_state_tag 1
+#define meshtastic_ModuleConfig_AmbientLightingConfig_current_tag 2
+#define meshtastic_ModuleConfig_AmbientLightingConfig_red_tag 3
+#define meshtastic_ModuleConfig_AmbientLightingConfig_green_tag 4
+#define meshtastic_ModuleConfig_AmbientLightingConfig_blue_tag 5
#define meshtastic_RemoteHardwarePin_gpio_pin_tag 1
#define meshtastic_RemoteHardwarePin_name_tag 2
#define meshtastic_RemoteHardwarePin_type_tag 3
@@ -481,6 +508,7 @@ extern "C" {
#define meshtastic_ModuleConfig_audio_tag 8
#define meshtastic_ModuleConfig_remote_hardware_tag 9
#define meshtastic_ModuleConfig_neighbor_info_tag 10
+#define meshtastic_ModuleConfig_ambient_lighting_tag 11
/* Struct field encoding specification for nanopb */
#define meshtastic_ModuleConfig_FIELDLIST(X, a) \
@@ -493,7 +521,8 @@ X(a, STATIC, ONEOF, MESSAGE, (payload_variant,telemetry,payload_variant.te
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,canned_message,payload_variant.canned_message), 7) \
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,audio,payload_variant.audio), 8) \
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,remote_hardware,payload_variant.remote_hardware), 9) \
-X(a, STATIC, ONEOF, MESSAGE, (payload_variant,neighbor_info,payload_variant.neighbor_info), 10)
+X(a, STATIC, ONEOF, MESSAGE, (payload_variant,neighbor_info,payload_variant.neighbor_info), 10) \
+X(a, STATIC, ONEOF, MESSAGE, (payload_variant,ambient_lighting,payload_variant.ambient_lighting), 11)
#define meshtastic_ModuleConfig_CALLBACK NULL
#define meshtastic_ModuleConfig_DEFAULT NULL
#define meshtastic_ModuleConfig_payload_variant_mqtt_MSGTYPE meshtastic_ModuleConfig_MQTTConfig
@@ -506,6 +535,7 @@ X(a, STATIC, ONEOF, MESSAGE, (payload_variant,neighbor_info,payload_varian
#define meshtastic_ModuleConfig_payload_variant_audio_MSGTYPE meshtastic_ModuleConfig_AudioConfig
#define meshtastic_ModuleConfig_payload_variant_remote_hardware_MSGTYPE meshtastic_ModuleConfig_RemoteHardwareConfig
#define meshtastic_ModuleConfig_payload_variant_neighbor_info_MSGTYPE meshtastic_ModuleConfig_NeighborInfoConfig
+#define meshtastic_ModuleConfig_payload_variant_ambient_lighting_MSGTYPE meshtastic_ModuleConfig_AmbientLightingConfig
#define meshtastic_ModuleConfig_MQTTConfig_FIELDLIST(X, a) \
X(a, STATIC, SINGULAR, BOOL, enabled, 1) \
@@ -515,7 +545,8 @@ X(a, STATIC, SINGULAR, STRING, password, 4) \
X(a, STATIC, SINGULAR, BOOL, encryption_enabled, 5) \
X(a, STATIC, SINGULAR, BOOL, json_enabled, 6) \
X(a, STATIC, SINGULAR, BOOL, tls_enabled, 7) \
-X(a, STATIC, SINGULAR, STRING, root, 8)
+X(a, STATIC, SINGULAR, STRING, root, 8) \
+X(a, STATIC, SINGULAR, BOOL, proxy_to_client_enabled, 9)
#define meshtastic_ModuleConfig_MQTTConfig_CALLBACK NULL
#define meshtastic_ModuleConfig_MQTTConfig_DEFAULT NULL
@@ -616,6 +647,15 @@ X(a, STATIC, SINGULAR, BOOL, send_bell, 11)
#define meshtastic_ModuleConfig_CannedMessageConfig_CALLBACK NULL
#define meshtastic_ModuleConfig_CannedMessageConfig_DEFAULT NULL
+#define meshtastic_ModuleConfig_AmbientLightingConfig_FIELDLIST(X, a) \
+X(a, STATIC, SINGULAR, BOOL, led_state, 1) \
+X(a, STATIC, SINGULAR, UINT32, current, 2) \
+X(a, STATIC, SINGULAR, UINT32, red, 3) \
+X(a, STATIC, SINGULAR, UINT32, green, 4) \
+X(a, STATIC, SINGULAR, UINT32, blue, 5)
+#define meshtastic_ModuleConfig_AmbientLightingConfig_CALLBACK NULL
+#define meshtastic_ModuleConfig_AmbientLightingConfig_DEFAULT NULL
+
#define meshtastic_RemoteHardwarePin_FIELDLIST(X, a) \
X(a, STATIC, SINGULAR, UINT32, gpio_pin, 1) \
X(a, STATIC, SINGULAR, STRING, name, 2) \
@@ -634,6 +674,7 @@ extern const pb_msgdesc_t meshtastic_ModuleConfig_StoreForwardConfig_msg;
extern const pb_msgdesc_t meshtastic_ModuleConfig_RangeTestConfig_msg;
extern const pb_msgdesc_t meshtastic_ModuleConfig_TelemetryConfig_msg;
extern const pb_msgdesc_t meshtastic_ModuleConfig_CannedMessageConfig_msg;
+extern const pb_msgdesc_t meshtastic_ModuleConfig_AmbientLightingConfig_msg;
extern const pb_msgdesc_t meshtastic_RemoteHardwarePin_msg;
/* Defines for backwards compatibility with code written before nanopb-0.4.0 */
@@ -648,20 +689,22 @@ extern const pb_msgdesc_t meshtastic_RemoteHardwarePin_msg;
#define meshtastic_ModuleConfig_RangeTestConfig_fields &meshtastic_ModuleConfig_RangeTestConfig_msg
#define meshtastic_ModuleConfig_TelemetryConfig_fields &meshtastic_ModuleConfig_TelemetryConfig_msg
#define meshtastic_ModuleConfig_CannedMessageConfig_fields &meshtastic_ModuleConfig_CannedMessageConfig_msg
+#define meshtastic_ModuleConfig_AmbientLightingConfig_fields &meshtastic_ModuleConfig_AmbientLightingConfig_msg
#define meshtastic_RemoteHardwarePin_fields &meshtastic_RemoteHardwarePin_msg
/* Maximum encoded size of messages (where known) */
+#define meshtastic_ModuleConfig_AmbientLightingConfig_size 14
#define meshtastic_ModuleConfig_AudioConfig_size 19
#define meshtastic_ModuleConfig_CannedMessageConfig_size 49
#define meshtastic_ModuleConfig_ExternalNotificationConfig_size 40
-#define meshtastic_ModuleConfig_MQTTConfig_size 220
+#define meshtastic_ModuleConfig_MQTTConfig_size 222
#define meshtastic_ModuleConfig_NeighborInfoConfig_size 8
#define meshtastic_ModuleConfig_RangeTestConfig_size 10
#define meshtastic_ModuleConfig_RemoteHardwareConfig_size 96
#define meshtastic_ModuleConfig_SerialConfig_size 28
#define meshtastic_ModuleConfig_StoreForwardConfig_size 22
#define meshtastic_ModuleConfig_TelemetryConfig_size 26
-#define meshtastic_ModuleConfig_size 223
+#define meshtastic_ModuleConfig_size 225
#define meshtastic_RemoteHardwarePin_size 21
#ifdef __cplusplus
diff --git a/src/mesh/generated/meshtastic/portnums.pb.h b/src/mesh/generated/meshtastic/portnums.pb.h
index 089d7b59f..e4aaeeb96 100644
--- a/src/mesh/generated/meshtastic/portnums.pb.h
+++ b/src/mesh/generated/meshtastic/portnums.pb.h
@@ -54,6 +54,8 @@ typedef enum _meshtastic_PortNum {
/* Audio Payloads.
Encapsulated codec2 packets. On 2.4 GHZ Bandwidths only for now */
meshtastic_PortNum_AUDIO_APP = 9,
+ /* Payloads for clients with a network connection proxying MQTT pub/sub to the device */
+ meshtastic_PortNum_MQTT_CLIENT_PROXY_APP = 10,
/* Provides a 'ping' service that replies to any packet it receives.
Also serves as a small example module. */
meshtastic_PortNum_REPLY_APP = 32,
diff --git a/src/mesh/generated/meshtastic/telemetry.pb.h b/src/mesh/generated/meshtastic/telemetry.pb.h
index 31646693e..4a9efc337 100644
--- a/src/mesh/generated/meshtastic/telemetry.pb.h
+++ b/src/mesh/generated/meshtastic/telemetry.pb.h
@@ -63,7 +63,7 @@ typedef struct _meshtastic_EnvironmentMetrics {
float relative_humidity;
/* Barometric pressure in hPA measured */
float barometric_pressure;
- /* Gas resistance in mOhm measured */
+ /* Gas resistance in MOhm measured */
float gas_resistance;
/* Voltage measured */
float voltage;
diff --git a/src/mesh/http/ContentHandler.cpp b/src/mesh/http/ContentHandler.cpp
index 9ddb5ca3a..acee9be0d 100644
--- a/src/mesh/http/ContentHandler.cpp
+++ b/src/mesh/http/ContentHandler.cpp
@@ -165,7 +165,7 @@ void handleAPIv1FromRadio(HTTPRequest *req, HTTPResponse *res)
if (params->getQueryParameter("all", valueAll)) {
- // If all is ture, return all the buffers we have available
+ // If all is true, return all the buffers we have available
// to us at this point in time.
if (valueAll == "true") {
while (len) {
@@ -179,7 +179,7 @@ void handleAPIv1FromRadio(HTTPRequest *req, HTTPResponse *res)
res->write(txBuf, len);
}
- // the param "all" was not spcified. Return just one protobuf
+ // the param "all" was not specified. Return just one protobuf
} else {
len = webAPI.getFromRadio(txBuf);
res->write(txBuf, len);
@@ -460,7 +460,7 @@ void handleFormUpload(HTTPRequest *req, HTTPResponse *res)
HTTPBodyParser *parser;
std::string contentType = req->getHeader("Content-Type");
- // The content type may have additional properties after a semicolon, for exampel:
+ // The content type may have additional properties after a semicolon, for example:
// Content-Type: text/html;charset=utf-8
// Content-Type: multipart/form-data;boundary=------s0m3w31rdch4r4c73rs
// As we're interested only in the actual mime _type_, we strip everything after the
diff --git a/src/mesh/http/WebServer.cpp b/src/mesh/http/WebServer.cpp
index 289f1429b..2b045c0be 100644
--- a/src/mesh/http/WebServer.cpp
+++ b/src/mesh/http/WebServer.cpp
@@ -15,7 +15,7 @@
#include "esp_task_wdt.h"
#endif
-// Persistant Data Storage
+// Persistent Data Storage
#include
Preferences prefs;
diff --git a/src/mesh/mesh-pb-constants.cpp b/src/mesh/mesh-pb-constants.cpp
index f9fa02251..994fab61f 100644
--- a/src/mesh/mesh-pb-constants.cpp
+++ b/src/mesh/mesh-pb-constants.cpp
@@ -14,7 +14,7 @@ size_t pb_encode_to_bytes(uint8_t *destbuf, size_t destbufsize, const pb_msgdesc
if (!pb_encode(&stream, fields, src_struct)) {
LOG_ERROR("Panic: can't encode protobuf reason='%s'\n", PB_GET_ERROR(&stream));
assert(
- 0); // If this asser fails it probably means you made a field too large for the max limits specified in mesh.options
+ 0); // If this assert fails it probably means you made a field too large for the max limits specified in mesh.options
} else {
return stream.bytes_written;
}
diff --git a/src/modules/AdminModule.cpp b/src/modules/AdminModule.cpp
index ae254e7f7..be76f62a5 100644
--- a/src/modules/AdminModule.cpp
+++ b/src/modules/AdminModule.cpp
@@ -16,9 +16,7 @@
#include "unistd.h"
#endif
-#if HAS_WIFI || HAS_ETHERNET
#include "mqtt/MQTT.h"
-#endif
#define DEFAULT_REBOOT_SECONDS 7
@@ -567,7 +565,7 @@ void AdminModule::handleGetDeviceConnectionStatus(const meshtastic_MeshPacket &r
if (conn.wifi.status.is_connected) {
conn.wifi.rssi = WiFi.RSSI();
conn.wifi.status.ip_address = WiFi.localIP();
- conn.wifi.status.is_mqtt_connected = mqtt && mqtt->connected();
+ conn.wifi.status.is_mqtt_connected = mqtt && mqtt->isConnectedDirectly();
conn.wifi.status.is_syslog_connected = false; // FIXME wire this up
}
#endif
@@ -578,7 +576,7 @@ void AdminModule::handleGetDeviceConnectionStatus(const meshtastic_MeshPacket &r
if (Ethernet.linkStatus() == LinkON) {
conn.ethernet.status.is_connected = true;
conn.ethernet.status.ip_address = Ethernet.localIP();
- conn.ethernet.status.is_mqtt_connected = mqtt && mqtt->connected();
+ conn.ethernet.status.is_mqtt_connected = mqtt && mqtt->isConnectedDirectly();
conn.ethernet.status.is_syslog_connected = false; // FIXME wire this up
} else {
conn.ethernet.status.is_connected = false;
diff --git a/src/modules/CannedMessageModule.cpp b/src/modules/CannedMessageModule.cpp
index bbd39f696..d3a450371 100644
--- a/src/modules/CannedMessageModule.cpp
+++ b/src/modules/CannedMessageModule.cpp
@@ -4,7 +4,7 @@
#include "FSCommon.h"
#include "MeshService.h"
#include "NodeDB.h"
-#include "PowerFSM.h" // neede for button bypass
+#include "PowerFSM.h" // needed for button bypass
#include "detect/ScanI2C.h"
#include "mesh/generated/meshtastic/cannedmessages.pb.h"
@@ -18,7 +18,7 @@
#include "graphics/fonts/OLEDDisplayFontsUA.h"
#endif
-#if defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7735_CS)
+#if defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7735_CS) || defined(ST7789_CS)
// The screen is bigger so use bigger fonts
#define FONT_SMALL ArialMT_Plain_16
#define FONT_MEDIUM ArialMT_Plain_24
@@ -123,8 +123,8 @@ int CannedMessageModule::splitConfiguredMessages()
int CannedMessageModule::handleInputEvent(const InputEvent *event)
{
if ((strlen(moduleConfig.canned_message.allow_input_source) > 0) &&
- (strcmp(moduleConfig.canned_message.allow_input_source, event->source) != 0) &&
- (strcmp(moduleConfig.canned_message.allow_input_source, "_any") != 0)) {
+ (strcasecmp(moduleConfig.canned_message.allow_input_source, event->source) != 0) &&
+ (strcasecmp(moduleConfig.canned_message.allow_input_source, "_any") != 0)) {
// Event source is not accepted.
// Event only accepted if source matches the configured one, or
// the configured one is "_any" (or if there is no configured
diff --git a/src/modules/ExternalNotificationModule.cpp b/src/modules/ExternalNotificationModule.cpp
index 82701cdc0..7dd6dd1ce 100644
--- a/src/modules/ExternalNotificationModule.cpp
+++ b/src/modules/ExternalNotificationModule.cpp
@@ -10,7 +10,7 @@
#include "main.h"
-#ifdef RAK4630
+#ifdef HAS_NCP5623
#include
NCP5623 rgb;
@@ -84,7 +84,7 @@ int32_t ExternalNotificationModule::runOnce()
millis()) {
getExternal(2) ? setExternalOff(2) : setExternalOn(2);
}
-#ifdef RAK4630
+#ifdef HAS_NCP5623
if (rgb_found.type == ScanI2C::NCP5623) {
green = (green + 50) % 255;
red = abs(red - green) % 255;
@@ -93,6 +93,10 @@ int32_t ExternalNotificationModule::runOnce()
rgb.setColor(red, green, blue);
}
#endif
+
+#ifdef T_WATCH_S3
+ drv.go();
+#endif
}
// now let the PWM buzzer play
@@ -124,14 +128,18 @@ void ExternalNotificationModule::setExternalOn(uint8_t index)
digitalWrite(moduleConfig.external_notification.output_buzzer, true);
break;
default:
- digitalWrite(output, (moduleConfig.external_notification.active ? true : false));
+ if (output > 0)
+ digitalWrite(output, (moduleConfig.external_notification.active ? true : false));
break;
}
-#ifdef RAK4630
+#ifdef HAS_NCP5623
if (rgb_found.type == ScanI2C::NCP5623) {
rgb.setColor(red, green, blue);
}
#endif
+#ifdef T_WATCH_S3
+ drv.go();
+#endif
}
void ExternalNotificationModule::setExternalOff(uint8_t index)
@@ -149,11 +157,12 @@ void ExternalNotificationModule::setExternalOff(uint8_t index)
digitalWrite(moduleConfig.external_notification.output_buzzer, false);
break;
default:
- digitalWrite(output, (moduleConfig.external_notification.active ? false : true));
+ if (output > 0)
+ digitalWrite(output, (moduleConfig.external_notification.active ? false : true));
break;
}
-#ifdef RAK4630
+#ifdef HAS_NCP5623
if (rgb_found.type == ScanI2C::NCP5623) {
red = 0;
green = 0;
@@ -161,6 +170,9 @@ void ExternalNotificationModule::setExternalOff(uint8_t index)
rgb.setColor(red, green, blue);
}
#endif
+#ifdef T_WATCH_S3
+ drv.stop();
+#endif
}
bool ExternalNotificationModule::getExternal(uint8_t index)
@@ -174,6 +186,9 @@ void ExternalNotificationModule::stopNow()
nagCycleCutoff = 1; // small value
isNagging = false;
setIntervalFromNow(0);
+#ifdef T_WATCH_S3
+ drv.stop();
+#endif
}
ExternalNotificationModule::ExternalNotificationModule()
@@ -185,7 +200,6 @@ ExternalNotificationModule::ExternalNotificationModule()
without having to configure it from the PythonAPI or WebUI.
*/
- // moduleConfig.external_notification.enabled = true;
// moduleConfig.external_notification.alert_message = true;
// moduleConfig.external_notification.alert_message_buzzer = true;
// moduleConfig.external_notification.alert_message_vibra = true;
@@ -213,8 +227,10 @@ ExternalNotificationModule::ExternalNotificationModule()
: EXT_NOTIFICATION_MODULE_OUTPUT;
// Set the direction of a pin
- LOG_INFO("Using Pin %i in digital mode\n", output);
- pinMode(output, OUTPUT);
+ if (output > 0) {
+ LOG_INFO("Using Pin %i in digital mode\n", output);
+ pinMode(output, OUTPUT);
+ }
setExternalOff(0);
externalTurnedOn[0] = 0;
if (moduleConfig.external_notification.output_vibra) {
@@ -235,7 +251,7 @@ ExternalNotificationModule::ExternalNotificationModule()
LOG_INFO("Using Pin %i in PWM mode\n", config.device.buzzer_gpio);
}
}
-#ifdef RAK4630
+#ifdef HAS_NCP5623
if (rgb_found.type == ScanI2C::NCP5623) {
rgb.begin();
rgb.setCurrent(10);
@@ -250,7 +266,12 @@ ExternalNotificationModule::ExternalNotificationModule()
ProcessMessage ExternalNotificationModule::handleReceived(const meshtastic_MeshPacket &mp)
{
if (moduleConfig.external_notification.enabled) {
-
+#if T_WATCH_S3
+ drv.setWaveform(0, 75);
+ drv.setWaveform(1, 56);
+ drv.setWaveform(2, 0);
+ drv.go();
+#endif
if (getFrom(&mp) != nodeDB.getNodeNum()) {
// Check if the message contains a bell character. Don't do this loop for every pin, just once.
@@ -343,7 +364,6 @@ ProcessMessage ExternalNotificationModule::handleReceived(const meshtastic_MeshP
}
setIntervalFromNow(0); // run once so we know if we should do something
}
-
} else {
LOG_INFO("External Notification Module Disabled\n");
}
diff --git a/src/modules/RangeTestModule.cpp b/src/modules/RangeTestModule.cpp
index 783fbd758..28835406d 100644
--- a/src/modules/RangeTestModule.cpp
+++ b/src/modules/RangeTestModule.cpp
@@ -54,7 +54,7 @@ int32_t RangeTestModule::runOnce()
if (moduleConfig.range_test.sender) {
LOG_INFO("Initializing Range Test Module -- Sender\n");
started = millis(); // make a note of when we started
- return (5000); // Sending first message 5 seconds after initilization.
+ return (5000); // Sending first message 5 seconds after initialization.
} else {
LOG_INFO("Initializing Range Test Module -- Receiver\n");
return disable();
@@ -147,8 +147,8 @@ ProcessMessage RangeTestModuleRadio::handleReceived(const meshtastic_MeshPacket
LOG_DEBUG("mp.from %d\n", mp.from);
LOG_DEBUG("mp.rx_snr %f\n", mp.rx_snr);
LOG_DEBUG("mp.hop_limit %d\n", mp.hop_limit);
- // LOG_DEBUG("mp.decoded.position.latitude_i %d\n", mp.decoded.position.latitude_i); // Depricated
- // LOG_DEBUG("mp.decoded.position.longitude_i %d\n", mp.decoded.position.longitude_i); // Depricated
+ // LOG_DEBUG("mp.decoded.position.latitude_i %d\n", mp.decoded.position.latitude_i); // Deprecated
+ // LOG_DEBUG("mp.decoded.position.longitude_i %d\n", mp.decoded.position.longitude_i); // Deprecated
LOG_DEBUG("---- Node Information of Received Packet (mp.from):\n");
LOG_DEBUG("n->user.long_name %s\n", n->user.long_name);
LOG_DEBUG("n->user.short_name %s\n", n->user.short_name);
@@ -186,8 +186,8 @@ bool RangeTestModuleRadio::appendFile(const meshtastic_MeshPacket &mp)
LOG_DEBUG("mp.from %d\n", mp.from);
LOG_DEBUG("mp.rx_snr %f\n", mp.rx_snr);
LOG_DEBUG("mp.hop_limit %d\n", mp.hop_limit);
- // LOG_DEBUG("mp.decoded.position.latitude_i %d\n", mp.decoded.position.latitude_i); // Depricated
- // LOG_DEBUG("mp.decoded.position.longitude_i %d\n", mp.decoded.position.longitude_i); // Depricated
+ // LOG_DEBUG("mp.decoded.position.latitude_i %d\n", mp.decoded.position.latitude_i); // Deprecated
+ // LOG_DEBUG("mp.decoded.position.longitude_i %d\n", mp.decoded.position.longitude_i); // Deprecated
LOG_DEBUG("---- Node Information of Received Packet (mp.from):\n");
LOG_DEBUG("n->user.long_name %s\n", n->user.long_name);
LOG_DEBUG("n->user.short_name %s\n", n->user.short_name);
diff --git a/src/modules/SerialModule.cpp b/src/modules/SerialModule.cpp
index af7ba1381..a3cac53b1 100644
--- a/src/modules/SerialModule.cpp
+++ b/src/modules/SerialModule.cpp
@@ -33,11 +33,11 @@
to your device.
TODO (in this order):
- * Define a verbose RX mode to report on mesh and packet infomration.
+ * Define a verbose RX mode to report on mesh and packet information.
- This won't happen any time soon.
KNOWN PROBLEMS
- * Until the module is initilized by the startup sequence, the TX pin is in a floating
+ * Until the module is initialized by the startup sequence, the TX pin is in a floating
state. Device connected to that pin may see this as "noise".
* Will not work on Linux device targets.
diff --git a/src/modules/Telemetry/EnvironmentTelemetry.cpp b/src/modules/Telemetry/EnvironmentTelemetry.cpp
index 5cdc4bf4d..8a4747114 100644
--- a/src/modules/Telemetry/EnvironmentTelemetry.cpp
+++ b/src/modules/Telemetry/EnvironmentTelemetry.cpp
@@ -86,6 +86,10 @@ int32_t EnvironmentTelemetryModule::runOnce()
result = lps22hbSensor.runOnce();
if (sht31Sensor.hasSensor())
result = sht31Sensor.runOnce();
+ if (ina219Sensor.hasSensor() && !ina219Sensor.isInitialized())
+ result = ina219Sensor.runOnce();
+ if (ina260Sensor.hasSensor() && !ina260Sensor.isInitialized())
+ result = ina260Sensor.runOnce();
}
return result;
} else {
diff --git a/src/modules/esp32/StoreForwardModule.cpp b/src/modules/esp32/StoreForwardModule.cpp
index 767e1fb2b..fccbd7199 100644
--- a/src/modules/esp32/StoreForwardModule.cpp
+++ b/src/modules/esp32/StoreForwardModule.cpp
@@ -62,7 +62,7 @@ void StoreForwardModule::populatePSRAM()
https://learn.upesy.com/en/programmation/psram.html#psram-tab
*/
- LOG_DEBUG("*** Before PSRAM initilization: heap %d/%d PSRAM %d/%d\n", memGet.getFreeHeap(), memGet.getHeapSize(),
+ LOG_DEBUG("*** Before PSRAM initialization: heap %d/%d PSRAM %d/%d\n", memGet.getFreeHeap(), memGet.getHeapSize(),
memGet.getFreePsram(), memGet.getPsramSize());
this->packetHistoryTXQueue =
@@ -77,7 +77,7 @@ void StoreForwardModule::populatePSRAM()
this->packetHistory = static_cast(ps_calloc(numberOfPackets, sizeof(PacketHistoryStruct)));
- LOG_DEBUG("*** After PSRAM initilization: heap %d/%d PSRAM %d/%d\n", memGet.getFreeHeap(), memGet.getHeapSize(),
+ LOG_DEBUG("*** After PSRAM initialization: heap %d/%d PSRAM %d/%d\n", memGet.getFreeHeap(), memGet.getHeapSize(),
memGet.getFreePsram(), memGet.getPsramSize());
LOG_DEBUG("*** numberOfPackets for packetHistory - %u\n", numberOfPackets);
}
diff --git a/src/mqtt/JSONValue.cpp b/src/mqtt/JSONValue.cpp
index 10d79a4df..1990a13b6 100644
--- a/src/mqtt/JSONValue.cpp
+++ b/src/mqtt/JSONValue.cpp
@@ -282,7 +282,7 @@ JSONValue *JSONValue::Parse(const char **data)
return NULL;
}
- // Ran out of possibilites, it's bad!
+ // Ran out of possibilities, it's bad!
else {
return NULL;
}
diff --git a/src/mqtt/MQTT.cpp b/src/mqtt/MQTT.cpp
index 532a2d125..50198efca 100644
--- a/src/mqtt/MQTT.cpp
+++ b/src/mqtt/MQTT.cpp
@@ -25,12 +25,16 @@ Allocator &mqttPool = staticMqttPool;
void MQTT::mqttCallback(char *topic, byte *payload, unsigned int length)
{
- mqtt->onPublish(topic, payload, length);
+ mqtt->onReceive(topic, payload, length);
}
-void MQTT::onPublish(char *topic, byte *payload, unsigned int length)
+void MQTT::onClientProxyReceive(meshtastic_MqttClientProxyMessage msg)
+{
+ onReceive(msg.topic, msg.payload_variant.data.bytes, msg.payload_variant.data.size);
+}
+
+void MQTT::onReceive(char *topic, byte *payload, size_t length)
{
- // parsing ServiceEnvelope
meshtastic_ServiceEnvelope e = meshtastic_ServiceEnvelope_init_default;
if (moduleConfig.mqtt.json_enabled && (strncmp(topic, jsonTopic.c_str(), jsonTopic.length()) == 0)) {
@@ -153,10 +157,13 @@ void mqttInit()
new MQTT();
}
+#ifdef HAS_NETWORKING
MQTT::MQTT() : concurrency::OSThread("mqtt"), pubSub(mqttClient), mqttQueue(MAX_MQTT_QUEUE)
+#else
+MQTT::MQTT() : concurrency::OSThread("mqtt"), mqttQueue(MAX_MQTT_QUEUE)
+#endif
{
if (moduleConfig.mqtt.enabled) {
-
assert(!mqtt);
mqtt = this;
@@ -170,22 +177,77 @@ MQTT::MQTT() : concurrency::OSThread("mqtt"), pubSub(mqttClient), mqttQueue(MAX_
jsonTopic = "msh" + jsonTopic;
}
- pubSub.setCallback(mqttCallback);
-
+#ifdef HAS_NETWORKING
+ if (!moduleConfig.mqtt.proxy_to_client_enabled)
+ pubSub.setCallback(mqttCallback);
+#endif
// preflightSleepObserver.observe(&preflightSleep);
} else {
disable();
}
}
-bool MQTT::connected()
+bool MQTT::isConnectedDirectly()
{
+#ifdef HAS_NETWORKING
return pubSub.connected();
+#else
+ return false;
+#endif
+}
+
+bool MQTT::publish(const char *topic, const char *payload, bool retained)
+{
+ if (moduleConfig.mqtt.proxy_to_client_enabled) {
+ meshtastic_MqttClientProxyMessage *msg = mqttClientProxyMessagePool.allocZeroed();
+ msg->which_payload_variant = meshtastic_MqttClientProxyMessage_text_tag;
+ strcpy(msg->topic, topic);
+ strcpy(msg->payload_variant.text, payload);
+ msg->retained = retained;
+ service.sendMqttMessageToClientProxy(msg);
+ return true;
+ }
+#ifdef HAS_NETWORKING
+ else if (isConnectedDirectly()) {
+ return pubSub.publish(topic, payload, retained);
+ }
+#endif
+ return false;
+}
+
+bool MQTT::publish(const char *topic, const uint8_t *payload, size_t length, bool retained)
+{
+ if (moduleConfig.mqtt.proxy_to_client_enabled) {
+ meshtastic_MqttClientProxyMessage *msg = mqttClientProxyMessagePool.allocZeroed();
+ msg->which_payload_variant = meshtastic_MqttClientProxyMessage_data_tag;
+ strcpy(msg->topic, topic);
+ msg->payload_variant.data.size = length;
+ memcpy(msg->payload_variant.data.bytes, payload, length);
+ msg->retained = retained;
+ service.sendMqttMessageToClientProxy(msg);
+ return true;
+ }
+#ifdef HAS_NETWORKING
+ else if (isConnectedDirectly()) {
+ return pubSub.publish(topic, payload, length, retained);
+ }
+#endif
+ return false;
}
void MQTT::reconnect()
{
if (wantsLink()) {
+ if (moduleConfig.mqtt.proxy_to_client_enabled) {
+ LOG_INFO("MQTT connecting via client proxy instead...\n");
+ enabled = true;
+ runASAP = true;
+ reconnectCount = 0;
+
+ publishStatus();
+ return; // Don't try to connect directly to the server
+ }
+#ifdef HAS_NETWORKING
// Defaults
int serverPort = 1883;
const char *serverAddr = default_mqtt_address;
@@ -197,7 +259,6 @@ void MQTT::reconnect()
mqttUsername = moduleConfig.mqtt.username;
mqttPassword = moduleConfig.mqtt.password;
}
-
#if HAS_WIFI && !defined(ARCH_PORTDUINO)
if (moduleConfig.mqtt.tls_enabled) {
// change default for encrypted to 8883
@@ -214,7 +275,7 @@ void MQTT::reconnect()
LOG_INFO("Using non-TLS-encrypted session\n");
pubSub.setClient(mqttClient);
}
-#else
+#elif HAS_NETWORKING
pubSub.setClient(mqttClient);
#endif
@@ -229,8 +290,9 @@ void MQTT::reconnect()
pubSub.setServer(serverAddr, serverPort);
pubSub.setBufferSize(512);
- LOG_INFO("Connecting to MQTT server %s, port: %d, username: %s, password: %s\n", serverAddr, serverPort, mqttUsername,
- mqttPassword);
+ LOG_INFO("Attempting to connect directly to MQTT server %s, port: %d, username: %s, password: %s\n", serverAddr,
+ serverPort, mqttUsername, mqttPassword);
+
auto myStatus = (statusTopic + owner.id);
bool connected = pubSub.connect(owner.id, mqttUsername, mqttPassword, myStatus.c_str(), 1, true, "offline");
if (connected) {
@@ -239,15 +301,12 @@ void MQTT::reconnect()
runASAP = true;
reconnectCount = 0;
- /// FIXME, include more information in the status text
- bool ok = pubSub.publish(myStatus.c_str(), "online", true);
- LOG_INFO("published %d\n", ok);
-
+ publishStatus();
sendSubscriptions();
} else {
#if HAS_WIFI && !defined(ARCH_PORTDUINO)
reconnectCount++;
- LOG_ERROR("Failed to contact MQTT server (%d/%d)...\n", reconnectCount, reconnectMax);
+ LOG_ERROR("Failed to contact MQTT server directly (%d/%d)...\n", reconnectCount, reconnectMax);
if (reconnectCount >= reconnectMax) {
needReconnect = true;
wifiReconnect->setIntervalFromNow(0);
@@ -255,11 +314,13 @@ void MQTT::reconnect()
}
#endif
}
+#endif
}
}
void MQTT::sendSubscriptions()
{
+#ifdef HAS_NETWORKING
size_t numChan = channels.getNumChannels();
for (size_t i = 0; i < numChan; i++) {
auto &ch = channels.getByIndex(i);
@@ -274,6 +335,7 @@ void MQTT::sendSubscriptions()
}
}
}
+#endif
}
bool MQTT::wantsLink() const
@@ -291,60 +353,44 @@ bool MQTT::wantsLink() const
}
}
}
+ if (hasChannel && moduleConfig.mqtt.proxy_to_client_enabled)
+ return true;
#if HAS_WIFI
return hasChannel && WiFi.isConnected();
#endif
#if HAS_ETHERNET
- return hasChannel && (Ethernet.linkStatus() == LinkON);
+ return hasChannel && Ethernet.linkStatus() == LinkON;
#endif
return false;
}
int32_t MQTT::runOnce()
{
- if (!moduleConfig.mqtt.enabled) {
+ if (!moduleConfig.mqtt.enabled)
return disable();
- }
+
bool wantConnection = wantsLink();
// If connected poll rapidly, otherwise only occasionally check for a wifi connection change and ability to contact server
- if (!pubSub.loop()) {
- if (wantConnection) {
+ if (moduleConfig.mqtt.proxy_to_client_enabled) {
+ publishQueuedMessages();
+ return 200;
+ }
+#ifdef HAS_NETWORKING
+ else if (!pubSub.loop()) {
+ if (!wantConnection)
+ return 5000; // If we don't want connection now, check again in 5 secs
+ else {
reconnect();
-
// If we succeeded, empty the queue one by one and start reading rapidly, else try again in 30 seconds (TCP
// connections are EXPENSIVE so try rarely)
- if (pubSub.connected()) {
- if (!mqttQueue.isEmpty()) {
- // FIXME - this size calculation is super sloppy, but it will go away once we dynamically alloc meshpackets
- meshtastic_ServiceEnvelope *env = mqttQueue.dequeuePtr(0);
- static uint8_t bytes[meshtastic_MeshPacket_size + 64];
- size_t numBytes = pb_encode_to_bytes(bytes, sizeof(bytes), &meshtastic_ServiceEnvelope_msg, env);
-
- std::string topic = cryptTopic + env->channel_id + "/" + owner.id;
- LOG_INFO("publish %s, %u bytes from queue\n", topic.c_str(), numBytes);
-
- pubSub.publish(topic.c_str(), bytes, numBytes, false);
-
- if (moduleConfig.mqtt.json_enabled) {
- // handle json topic
- auto jsonString = this->downstreamPacketToJson(env->packet);
- if (jsonString.length() != 0) {
- std::string topicJson = jsonTopic + env->channel_id + "/" + owner.id;
- LOG_INFO("JSON publish message to %s, %u bytes: %s\n", topicJson.c_str(), jsonString.length(),
- jsonString.c_str());
- pubSub.publish(topicJson.c_str(), jsonString.c_str(), false);
- }
- }
- mqttPool.release(env);
- }
+ if (isConnectedDirectly()) {
+ publishQueuedMessages();
return 200;
- } else {
+ } else
return 30000;
- }
- } else
- return 5000; // If we don't want connection now, check again in 5 secs
+ }
} else {
// we are connected to server, check often for new requests on the TCP port
if (!wantConnection) {
@@ -355,6 +401,44 @@ int32_t MQTT::runOnce()
powerFSM.trigger(EVENT_CONTACT_FROM_PHONE); // Suppress entering light sleep (because that would turn off bluetooth)
return 20;
}
+#endif
+ return 30000;
+}
+
+/// FIXME, include more information in the status text
+void MQTT::publishStatus()
+{
+ auto myStatus = (statusTopic + owner.id);
+ bool ok = publish(myStatus.c_str(), "online", true);
+ LOG_INFO("published online=%d\n", ok);
+}
+
+void MQTT::publishQueuedMessages()
+{
+ if (!mqttQueue.isEmpty()) {
+ LOG_DEBUG("Publishing enqueued MQTT message\n");
+ // FIXME - this size calculation is super sloppy, but it will go away once we dynamically alloc meshpackets
+ meshtastic_ServiceEnvelope *env = mqttQueue.dequeuePtr(0);
+ static uint8_t bytes[meshtastic_MeshPacket_size + 64];
+ size_t numBytes = pb_encode_to_bytes(bytes, sizeof(bytes), &meshtastic_ServiceEnvelope_msg, env);
+
+ std::string topic = cryptTopic + env->channel_id + "/" + owner.id;
+ LOG_INFO("publish %s, %u bytes from queue\n", topic.c_str(), numBytes);
+
+ publish(topic.c_str(), bytes, numBytes, false);
+
+ if (moduleConfig.mqtt.json_enabled) {
+ // handle json topic
+ auto jsonString = this->meshPacketToJson(env->packet);
+ if (jsonString.length() != 0) {
+ std::string topicJson = jsonTopic + env->channel_id + "/" + owner.id;
+ LOG_INFO("JSON publish message to %s, %u bytes: %s\n", topicJson.c_str(), jsonString.length(),
+ jsonString.c_str());
+ publish(topicJson.c_str(), jsonString.c_str(), false);
+ }
+ }
+ mqttPool.release(env);
+ }
}
void MQTT::onSend(const meshtastic_MeshPacket &mp, ChannelIndex chIndex)
@@ -368,27 +452,26 @@ void MQTT::onSend(const meshtastic_MeshPacket &mp, ChannelIndex chIndex)
env->channel_id = (char *)channelId;
env->gateway_id = owner.id;
env->packet = (meshtastic_MeshPacket *)∓
+ LOG_DEBUG("MQTT onSend - Publishing portnum %i message\n", env->packet->decoded.portnum);
- // don't bother sending if not connected...
- if (pubSub.connected()) {
-
+ if (moduleConfig.mqtt.proxy_to_client_enabled || this->isConnectedDirectly()) {
// FIXME - this size calculation is super sloppy, but it will go away once we dynamically alloc meshpackets
static uint8_t bytes[meshtastic_MeshPacket_size + 64];
size_t numBytes = pb_encode_to_bytes(bytes, sizeof(bytes), &meshtastic_ServiceEnvelope_msg, env);
std::string topic = cryptTopic + channelId + "/" + owner.id;
- LOG_DEBUG("publish %s, %u bytes\n", topic.c_str(), numBytes);
+ LOG_DEBUG("MQTT Publish %s, %u bytes\n", topic.c_str(), numBytes);
- pubSub.publish(topic.c_str(), bytes, numBytes, false);
+ publish(topic.c_str(), bytes, numBytes, false);
if (moduleConfig.mqtt.json_enabled) {
// handle json topic
- auto jsonString = this->downstreamPacketToJson((meshtastic_MeshPacket *)&mp);
+ auto jsonString = this->meshPacketToJson((meshtastic_MeshPacket *)&mp);
if (jsonString.length() != 0) {
std::string topicJson = jsonTopic + channelId + "/" + owner.id;
LOG_INFO("JSON publish message to %s, %u bytes: %s\n", topicJson.c_str(), jsonString.length(),
jsonString.c_str());
- pubSub.publish(topicJson.c_str(), jsonString.c_str(), false);
+ publish(topicJson.c_str(), jsonString.c_str(), false);
}
}
} else {
@@ -408,7 +491,7 @@ void MQTT::onSend(const meshtastic_MeshPacket &mp, ChannelIndex chIndex)
}
// converts a downstream packet into a json message
-std::string MQTT::downstreamPacketToJson(meshtastic_MeshPacket *mp)
+std::string MQTT::meshPacketToJson(meshtastic_MeshPacket *mp)
{
// the created jsonObj is immutable after creation, so
// we need to do the heavy lifting before assembling it.
diff --git a/src/mqtt/MQTT.h b/src/mqtt/MQTT.h
index 1e626c3e0..565f46ecf 100644
--- a/src/mqtt/MQTT.h
+++ b/src/mqtt/MQTT.h
@@ -5,15 +5,20 @@
#include "concurrency/OSThread.h"
#include "mesh/Channels.h"
#include "mesh/generated/meshtastic/mqtt.pb.h"
-#include
#if HAS_WIFI
#include
+#define HAS_NETWORKING 1
#if !defined(ARCH_PORTDUINO)
#include
#endif
#endif
#if HAS_ETHERNET
#include
+#define HAS_NETWORKING 1
+#endif
+
+#ifdef HAS_NETWORKING
+#include
#endif
#define MAX_MQTT_QUEUE 16
@@ -35,12 +40,9 @@ class MQTT : private concurrency::OSThread
#if HAS_ETHERNET
EthernetClient mqttClient;
#endif
-#if !defined(DEBUG_HEAP_MQTT)
- PubSubClient pubSub;
public:
-#else
- public:
+#ifdef HAS_NETWORKING
PubSubClient pubSub;
#endif
MQTT();
@@ -51,7 +53,7 @@ class MQTT : private concurrency::OSThread
* @param chIndex the index of the channel for this message
*
* Note: for messages we are forwarding on the mesh that we can't find the channel for (because we don't have the keys), we
- * can not forward those messages to the cloud - becuase no way to find a global channel ID.
+ * can not forward those messages to the cloud - because no way to find a global channel ID.
*/
void onSend(const meshtastic_MeshPacket &mp, ChannelIndex chIndex);
@@ -59,7 +61,13 @@ class MQTT : private concurrency::OSThread
*/
void reconnect();
- bool connected();
+ bool isConnectedDirectly();
+
+ bool publish(const char *topic, const char *payload, bool retained);
+
+ bool publish(const char *topic, const uint8_t *payload, size_t length, const bool retained);
+
+ void onClientProxyReceive(meshtastic_MqttClientProxyMessage msg);
protected:
PointerQueue mqttQueue;
@@ -80,14 +88,17 @@ class MQTT : private concurrency::OSThread
*/
void sendSubscriptions();
- /// Just C glue to call onPublish
+ /// Callback for direct mqtt subscription messages
static void mqttCallback(char *topic, byte *payload, unsigned int length);
/// Called when a new publish arrives from the MQTT server
- void onPublish(char *topic, byte *payload, unsigned int length);
+ void onReceive(char *topic, byte *payload, size_t length);
/// Called when a new publish arrives from the MQTT server
- std::string downstreamPacketToJson(meshtastic_MeshPacket *mp);
+ std::string meshPacketToJson(meshtastic_MeshPacket *mp);
+
+ void publishStatus();
+ void publishQueuedMessages();
/// Return 0 if sleep is okay, veto sleep if we are connected to pubsub server
// int preflightSleepCb(void *unused = NULL) { return pubSub.connected() ? 1 : 0; }
diff --git a/src/platform/esp32/CallbackCharacteristic.h b/src/platform/esp32/CallbackCharacteristic.h
index 9c4f59a05..cd3bc6f51 100644
--- a/src/platform/esp32/CallbackCharacteristic.h
+++ b/src/platform/esp32/CallbackCharacteristic.h
@@ -3,7 +3,7 @@
#include "PowerFSM.h" // FIXME - someday I want to make this OTA thing a separate lb at at that point it can't touch this
/**
- * A characterstic with a set of overridable callbacks
+ * A characteristic with a set of overridable callbacks
*/
class CallbackCharacteristic : public BLECharacteristic, public BLECharacteristicCallbacks
{
diff --git a/src/platform/esp32/architecture.h b/src/platform/esp32/architecture.h
index 7a1e9ba49..6e80b50e6 100644
--- a/src/platform/esp32/architecture.h
+++ b/src/platform/esp32/architecture.h
@@ -46,6 +46,10 @@
#if defined(HAS_AXP192) || defined(HAS_AXP2101)
#define HAS_PMU
#endif
+
+#ifdef PIN_BUTTON_TOUCH
+#define BUTTON_PIN_TOUCH PIN_BUTTON_TOUCH
+#endif
//
// set HW_VENDOR
//
@@ -81,6 +85,10 @@
#define HW_VENDOR meshtastic_HardwareModel_TLORA_V2_1_1P6
#elif defined(TLORA_V2_1_18)
#define HW_VENDOR meshtastic_HardwareModel_TLORA_V2_1_1P8
+#elif defined(T_DECK)
+#define HW_VENDOR meshtastic_HardwareModel_T_DECK
+#elif defined(T_WATCH_S3)
+#define HW_VENDOR meshtastic_HardwareModel_T_WATCH_S3
#elif defined(GENIEBLOCKS)
#define HW_VENDOR meshtastic_HardwareModel_GENIEBLOCKS
#elif defined(PRIVATE_HW)
@@ -97,6 +105,10 @@
#define HW_VENDOR meshtastic_HardwareModel_HELTEC_V3
#elif defined(HELTEC_WSL_V3)
#define HW_VENDOR meshtastic_HardwareModel_HELTEC_WSL_V3
+#elif defined(HELTEC_WIRELESS_TRACKER)
+#define HW_VENDOR meshtastic_HardwareModel_HELTEC_WIRELESS_TRACKER
+#elif defined(HELTEC_WIRELESS_PAPER)
+#define HW_VENDOR meshtastic_HardwareModel_HELTEC_WIRELESS_PAPER
#elif defined(TLORA_T3S3_V1)
#define HW_VENDOR meshtastic_HardwareModel_TLORA_T3_S3
#elif defined(BETAFPV_2400_TX)
diff --git a/src/platform/esp32/main-esp32.cpp b/src/platform/esp32/main-esp32.cpp
index 4cb7f4443..8abe6d56d 100644
--- a/src/platform/esp32/main-esp32.cpp
+++ b/src/platform/esp32/main-esp32.cpp
@@ -99,7 +99,7 @@ void esp32Setup()
LOG_DEBUG("Setup Preferences in Flash Storage\n");
- // Create object to store our persistant data
+ // Create object to store our persistent data
Preferences preferences;
preferences.begin("meshtastic", false);
diff --git a/src/platform/nrf52/JLINK_MONITOR_ISR_SES.S b/src/platform/nrf52/JLINK_MONITOR_ISR_SES.S
index b513ea07d..cda4b1a50 100644
--- a/src/platform/nrf52/JLINK_MONITOR_ISR_SES.S
+++ b/src/platform/nrf52/JLINK_MONITOR_ISR_SES.S
@@ -136,7 +136,7 @@ Purpose : Implementation of debug monitor for J-Link monitor mode
* This handler is also responsible for handling commands that are sent by the debugger.
*
* Notes
-* This is actually the ISR for the debug inerrupt (exception no. 12)
+* This is actually the ISR for the debug interrupt (exception no. 12)
*/
.thumb_func
diff --git a/src/platform/nrf52/NRF52Bluetooth.cpp b/src/platform/nrf52/NRF52Bluetooth.cpp
index 044b57ae6..c29739542 100644
--- a/src/platform/nrf52/NRF52Bluetooth.cpp
+++ b/src/platform/nrf52/NRF52Bluetooth.cpp
@@ -17,7 +17,7 @@ static BLEBas blebas; // BAS (Battery Service) helper class instance
static BLEDfu bledfu; // DFU software update helper service
// This scratch buffer is used for various bluetooth reads/writes - but it is safe because only one bt operation can be in
-// proccess at once
+// process at once
// static uint8_t trBytes[_max(_max(_max(_max(ToRadio_size, RadioConfig_size), User_size), MyNodeInfo_size), FromRadio_size)];
static uint8_t fromRadioBytes[meshtastic_FromRadio_size];
static uint8_t toRadioBytes[meshtastic_ToRadio_size];
diff --git a/src/platform/nrf52/architecture.h b/src/platform/nrf52/architecture.h
index 037e884cb..904ab908d 100644
--- a/src/platform/nrf52/architecture.h
+++ b/src/platform/nrf52/architecture.h
@@ -66,6 +66,14 @@
#endif
+#ifdef _SEEED_XIAO_NRF52840_SENSE_H_
+
+// This board uses 0 to be mean LED on
+#undef LED_INVERTED
+#define LED_INVERTED 1
+
+#endif
+
#ifndef TTGO_T_ECHO
#define GPS_UBLOX
#endif
diff --git a/src/platform/nrf52/main-nrf52.cpp b/src/platform/nrf52/main-nrf52.cpp
index c630aa13b..fd6fe2cc2 100644
--- a/src/platform/nrf52/main-nrf52.cpp
+++ b/src/platform/nrf52/main-nrf52.cpp
@@ -170,8 +170,11 @@ void cpuDeepSleep(uint32_t msecToWake)
Serial1.end();
#endif
setBluetoothEnable(false);
+
#ifdef RAK4630
+#ifdef PIN_3V3_EN
digitalWrite(PIN_3V3_EN, LOW);
+#endif
#ifndef USE_EINK
// RAK-12039 set pin for Air quality sensor
digitalWrite(AQ_SET_PIN, LOW);
diff --git a/src/platform/portduino/SimRadio.cpp b/src/platform/portduino/SimRadio.cpp
index f71113ab4..e3d56554a 100644
--- a/src/platform/portduino/SimRadio.cpp
+++ b/src/platform/portduino/SimRadio.cpp
@@ -92,7 +92,7 @@ void SimRadio::completeSending()
}
}
-/** Could we send right now (i.e. either not actively receving or transmitting)? */
+/** Could we send right now (i.e. either not actively receiving or transmitting)? */
bool SimRadio::canSendImmediately()
{
// We wait _if_ we are partially though receiving a packet (rather than just merely waiting for one).
diff --git a/src/platform/rp2040/architecture.h b/src/platform/rp2040/architecture.h
index 772e4b1af..762a2dc83 100644
--- a/src/platform/rp2040/architecture.h
+++ b/src/platform/rp2040/architecture.h
@@ -2,9 +2,18 @@
#define ARCH_RP2040
+#ifndef HAS_BUTTON
+#define HAS_BUTTON 1
+#endif
#ifndef HAS_TELEMETRY
#define HAS_TELEMETRY 1
#endif
+#ifndef HAS_SCREEN
+#define HAS_SCREEN 1
+#endif
+#ifndef HAS_WIRE
+#define HAS_WIRE 1
+#endif
#ifndef HAS_SENSOR
#define HAS_SENSOR 1
#endif
diff --git a/src/platform/stm32wl/InternalFileSystem.cpp b/src/platform/stm32wl/InternalFileSystem.cpp
index 950ceb0cd..d42a646a5 100644
--- a/src/platform/stm32wl/InternalFileSystem.cpp
+++ b/src/platform/stm32wl/InternalFileSystem.cpp
@@ -49,7 +49,7 @@ static int _internal_flash_read(const struct lfs_config *c, lfs_block_t block, l
}
// Program a region in a block. The block must have previously
-// been erased. Negative error codes are propogated to the user.
+// been erased. Negative error codes are propagated to the user.
// May return LFS_ERR_CORRUPT if the block should be considered bad.
static int _internal_flash_prog(const struct lfs_config *c, lfs_block_t block, lfs_off_t off, const void *buffer, lfs_size_t size)
{
@@ -67,7 +67,7 @@ static int _internal_flash_prog(const struct lfs_config *c, lfs_block_t block, l
// Erase a block. A block must be erased before being programmed.
// The state of an erased block is undefined. Negative error codes
-// are propogated to the user.
+// are propagated to the user.
// May return LFS_ERR_CORRUPT if the block should be considered bad.
static int _internal_flash_erase(const struct lfs_config *c, lfs_block_t block)
{
@@ -84,7 +84,7 @@ static int _internal_flash_erase(const struct lfs_config *c, lfs_block_t block)
}
// Sync the state of the underlying block device. Negative error codes
-// are propogated to the user.
+// are propagated to the user.
static int _internal_flash_sync(const struct lfs_config *c)
{
// we don't use a ram cache, this is a noop
diff --git a/src/shutdown.h b/src/shutdown.h
index ee63422dd..d9077151c 100644
--- a/src/shutdown.h
+++ b/src/shutdown.h
@@ -12,6 +12,8 @@ void powerCommandsCheck()
ESP.restart();
#elif defined(ARCH_NRF52)
NVIC_SystemReset();
+#elif defined(ARCH_RP2040)
+ rp2040.reboot();
#else
rebootAtMsec = -1;
LOG_WARN("FIXME implement reboot for this platform. Skipping for now.\n");
@@ -33,4 +35,4 @@ void powerCommandsCheck()
LOG_WARN("FIXME implement shutdown for this platform");
#endif
}
-}
+}
\ No newline at end of file
diff --git a/src/sleep.cpp b/src/sleep.cpp
index 5331eaf75..3d6da7feb 100644
--- a/src/sleep.cpp
+++ b/src/sleep.cpp
@@ -23,11 +23,6 @@ esp_sleep_source_t wakeCause; // the reason we booted this time
#define INCLUDE_vTaskSuspend 0
#endif
-#ifdef HAS_PMU
-#include "XPowersLibInterface.hpp"
-extern XPowersLibInterface *PMU;
-#endif
-
/// Called to ask any observers if they want to veto sleep. Return 1 to veto or 0 to allow sleep to happen
Observable preflightSleep;
@@ -99,6 +94,10 @@ void setGPSPower(bool on)
{
LOG_INFO("Setting GPS power=%d\n", on);
+#ifdef PIN_GPS_EN
+ digitalWrite(PIN_GPS_EN, on ? 1 : 0);
+#endif
+
#ifdef HAS_PMU
if (pmu_found && PMU) {
uint8_t model = PMU->getChipModel();
@@ -185,7 +184,7 @@ static void waitEnterSleep()
void doGPSpowersave(bool on)
{
-#ifdef HAS_PMU
+#if defined(HAS_PMU) || defined(PIN_GPS_EN)
if (on) {
LOG_INFO("Turning GPS back on\n");
gps->forceWake(1);
@@ -246,7 +245,7 @@ void doDeepSleep(uint32_t msecToWake)
//
// No need to turn this off if the power draw in sleep mode really is just 0.2uA and turning it off would
// leave floating input for the IRQ line
- // If we want to leave the radio receving in would be 11.5mA current draw, but most of the time it is just waiting
+ // If we want to leave the radio receiving in would be 11.5mA current draw, but most of the time it is just waiting
// in its sequencer (true?) so the average power draw should be much lower even if we were listinging for packets
// all the time.
@@ -255,7 +254,8 @@ void doDeepSleep(uint32_t msecToWake)
if (HW_VENDOR == meshtastic_HardwareModel_TBEAM) {
// t-beam v1.2 radio power channel
PMU->disablePowerOutput(XPOWERS_ALDO2); // lora radio power channel
- } else if (HW_VENDOR == meshtastic_HardwareModel_LILYGO_TBEAM_S3_CORE) {
+ } else if (HW_VENDOR == meshtastic_HardwareModel_LILYGO_TBEAM_S3_CORE ||
+ HW_VENDOR == meshtastic_HardwareModel_T_WATCH_S3) {
PMU->disablePowerOutput(XPOWERS_ALDO3); // lora radio power channel
}
} else if (model == XPOWERS_AXP192) {
@@ -384,4 +384,4 @@ void enableModemSleep()
int rv = esp_pm_configure(&esp32_config);
LOG_DEBUG("Sleep request result %x\n", rv);
}
-#endif
+#endif
\ No newline at end of file
diff --git a/src/sleep.h b/src/sleep.h
index a4b8f37b5..856d8d6b1 100644
--- a/src/sleep.h
+++ b/src/sleep.h
@@ -12,6 +12,12 @@ esp_sleep_wakeup_cause_t doLightSleep(uint64_t msecToWake);
extern esp_sleep_source_t wakeCause;
#endif
+
+#ifdef HAS_PMU
+#include "XPowersLibInterface.hpp"
+extern XPowersLibInterface *PMU;
+#endif
+
void setGPSPower(bool on);
void doGPSpowersave(bool on);
// Perform power on init that we do on each wake from deep sleep
diff --git a/variants/diy/hydra/variant.h b/variants/diy/hydra/variant.h
new file mode 100644
index 000000000..65bf839fd
--- /dev/null
+++ b/variants/diy/hydra/variant.h
@@ -0,0 +1,44 @@
+// For OLED LCD
+#define I2C_SDA 21
+#define I2C_SCL 22
+
+// GPS
+#undef GPS_RX_PIN
+#undef GPS_TX_PIN
+#define GPS_RX_PIN 12
+#define GPS_TX_PIN 15
+#define GPS_UBLOX
+#define PIN_GPS_EN 4
+
+#define BUTTON_PIN 39 // The middle button GPIO on the T-Beam
+#define BATTERY_PIN 35 // A battery voltage measurement pin, voltage divider connected here to measure battery voltage
+#define ADC_CHANNEL ADC1_GPIO35_CHANNEL
+#define ADC_MULTIPLIER 1.85 // (R1 = 470k, R2 = 680k)
+#define EXT_PWR_DETECT 4 // Pin to detect connected external power source for LILYGO® TTGO T-Energy T18 and other DIY boards
+#define EXT_NOTIFY_OUT 12 // Overridden default pin to use for Ext Notify Module (#975).
+#define LED_PIN 2 // add status LED (compatible with core-pcb and DIY targets)
+
+#define LORA_DIO0 26 // a No connect on the SX1262/SX1268 module
+#define LORA_RESET 23 // RST for SX1276, and for SX1262/SX1268
+#define LORA_DIO1 33 // IRQ for SX1262/SX1268
+#define LORA_DIO2 32 // BUSY for SX1262/SX1268
+#define LORA_DIO3 // Not connected on PCB, but internally on the TTGO SX1262/SX1268, if DIO3 is high the TXCO is enabled
+
+#define RF95_SCK 5
+#define RF95_MISO 19
+#define RF95_MOSI 27
+#define RF95_NSS 18
+
+#define USE_SX1262
+
+#define SX126X_CS 18 // NSS for SX126X
+#define SX126X_DIO1 LORA_DIO1
+#define SX126X_BUSY LORA_DIO2
+#define SX126X_RESET LORA_RESET
+#define SX126X_RXEN 14
+#define SX126X_TXEN RADIOLIB_NC
+#define E22_TXEN_CONNECTED_TO_DIO2 1
+
+// Set lora.tx_power to 13 for Hydra or other E22 900M30S target due to PA
+#define SX126X_MAX_POWER 13
+#define SX126X_E22
diff --git a/variants/diy/platformio.ini b/variants/diy/platformio.ini
index 612035717..cb031f266 100644
--- a/variants/diy/platformio.ini
+++ b/variants/diy/platformio.ini
@@ -34,3 +34,15 @@ build_flags =
-D DR_DEV
-D EBYTE_E22
-I variants/diy/dr-dev
+
+; Hydra - Meshtastic DIY v1 hardware with some specific changes
+[env:hydra]
+extends = esp32_base
+board = esp32doit-devkit-v1
+board_level = extra
+build_flags =
+ ${esp32_base.build_flags}
+ -D DIY_V1
+ -D EBYTE_E22
+ -D GPS_POWER_TOGGLE
+ -I variants/diy/hydra
diff --git a/variants/heltec_v2.1/platformio.ini b/variants/heltec_v2.1/platformio.ini
index 29f544f7a..7d4daecc9 100644
--- a/variants/heltec_v2.1/platformio.ini
+++ b/variants/heltec_v2.1/platformio.ini
@@ -4,4 +4,5 @@ extends = esp32_base
board = heltec_wifi_lora_32_V2
board_level = extra
build_flags =
- ${esp32_base.build_flags} -D HELTEC_V2_1 -I variants/heltec_v2.1
\ No newline at end of file
+ ${esp32_base.build_flags} -D HELTEC_V2_1 -I variants/heltec_v2.1
+ -DGPS_POWER_TOGGLE ; comment this line to disable triple press function on the user button to turn off gps entirely.
\ No newline at end of file
diff --git a/variants/heltec_v2.1/variant.h b/variants/heltec_v2.1/variant.h
index e7cfd5b34..ed123efec 100644
--- a/variants/heltec_v2.1/variant.h
+++ b/variants/heltec_v2.1/variant.h
@@ -8,6 +8,8 @@
#define GPS_RX_PIN 36
#define GPS_TX_PIN 33
+#define PIN_GPS_EN 37 // GPS power enable pin
+
#ifndef USE_JTAG // gpio15 is TDO for JTAG, so no I2C on this board while doing jtag
#define I2C_SDA 4 // I2C pins for this board
#define I2C_SCL 15
diff --git a/variants/heltec_v3/platformio.ini b/variants/heltec_v3/platformio.ini
index 3e0ace39c..58ee0b5ba 100644
--- a/variants/heltec_v3/platformio.ini
+++ b/variants/heltec_v3/platformio.ini
@@ -4,3 +4,4 @@ board = heltec_wifi_lora_32_V3
# Temporary until espressif creates a release with this new target
build_flags =
${esp32s3_base.build_flags} -D HELTEC_V3 -I variants/heltec_v3
+ -DGPS_POWER_TOGGLE ; comment this line to disable triple press function on the user button to turn off gps entirely.
\ No newline at end of file
diff --git a/variants/heltec_v3/variant.h b/variants/heltec_v3/variant.h
index d9fc0b4c2..aedfbe677 100644
--- a/variants/heltec_v3/variant.h
+++ b/variants/heltec_v3/variant.h
@@ -7,6 +7,8 @@
#define VEXT_ENABLE Vext // active low, powers the oled display and the lora antenna boost
#define BUTTON_PIN 0
+#define PIN_GPS_EN 46 // GPS power enable pin
+
#define BATTERY_PIN 1 // A battery voltage measurement pin, voltage divider connected here to measure battery voltage
#define ADC_CHANNEL ADC1_GPIO1_CHANNEL
#define ADC_ATTENUATION ADC_ATTEN_DB_2_5 // lower dB for high resistance voltage divider
@@ -29,4 +31,4 @@
#define SX126X_DIO1 LORA_DIO1
#define SX126X_BUSY LORA_DIO2
#define SX126X_RESET LORA_RESET
-#define SX126X_E22
\ No newline at end of file
+#define SX126X_E22
diff --git a/variants/heltec_wireless_paper/platformio.ini b/variants/heltec_wireless_paper/platformio.ini
new file mode 100644
index 000000000..0bc7f14d1
--- /dev/null
+++ b/variants/heltec_wireless_paper/platformio.ini
@@ -0,0 +1,8 @@
+[env:heltec-wireless-paper]
+extends = esp32s3_base
+board = heltec_wifi_lora_32_V3
+build_flags =
+ ${esp32s3_base.build_flags} -D HELTEC_WIRELESS_PAPER -I variants/heltec_wireless_paper
+lib_deps =
+ ${esp32s3_base.lib_deps}
+ zinggjm/GxEPD2@^1.5.2
diff --git a/variants/heltec_wireless_paper/variant.h b/variants/heltec_wireless_paper/variant.h
new file mode 100644
index 000000000..84c16c884
--- /dev/null
+++ b/variants/heltec_wireless_paper/variant.h
@@ -0,0 +1,39 @@
+#define LED_PIN 18
+
+#define USE_EINK
+/*
+ * eink display pins
+ */
+#define PIN_EINK_CS 4
+#define PIN_EINK_BUSY 7
+#define PIN_EINK_DC 5
+#define PIN_EINK_RES 6
+#define PIN_EINK_SCLK 3
+#define PIN_EINK_MOSI 2
+
+#define VEXT_ENABLE Vext // active low, powers the oled display and the lora antenna boost
+#define BUTTON_PIN 0
+
+#define BATTERY_PIN 1 // A battery voltage measurement pin, voltage divider connected here to measure battery voltage
+#define ADC_CHANNEL ADC1_GPIO1_CHANNEL
+#define ADC_ATTENUATION ADC_ATTEN_DB_2_5 // lower dB for high resistance voltage divider
+#define ADC_MULTIPLIER 4.9
+
+#define USE_SX1262
+
+#define LORA_DIO0 -1 // a No connect on the SX1262 module
+#define LORA_RESET 12
+#define LORA_DIO1 14 // SX1262 IRQ
+#define LORA_DIO2 13 // SX1262 BUSY
+#define LORA_DIO3 // Not connected on PCB, but internally on the TTGO SX1262, if DIO3 is high the TXCO is enabled
+
+#define RF95_SCK 9
+#define RF95_MISO 11
+#define RF95_MOSI 10
+#define RF95_NSS 8
+
+#define SX126X_CS RF95_NSS
+#define SX126X_DIO1 LORA_DIO1
+#define SX126X_BUSY LORA_DIO2
+#define SX126X_RESET LORA_RESET
+#define SX126X_E22
\ No newline at end of file
diff --git a/variants/heltec_wireless_tracker/pins_arduino.h b/variants/heltec_wireless_tracker/pins_arduino.h
new file mode 100644
index 000000000..e4d2631e7
--- /dev/null
+++ b/variants/heltec_wireless_tracker/pins_arduino.h
@@ -0,0 +1,80 @@
+#ifndef Pins_Arduino_h
+#define Pins_Arduino_h
+
+#include "soc/soc_caps.h"
+#include
+
+#define WIFI_LoRa_32_V3 true
+#define DISPLAY_HEIGHT 64
+#define DISPLAY_WIDTH 128
+
+#define USB_VID 0x303a
+#define USB_PID 0x1001
+
+#define EXTERNAL_NUM_INTERRUPTS 46
+#define NUM_DIGITAL_PINS 48
+#define NUM_ANALOG_INPUTS 20
+
+static const uint8_t LED_BUILTIN = 18;
+#define BUILTIN_LED LED_BUILTIN // backward compatibility
+#define LED_BUILTIN LED_BUILTIN
+
+#define analogInputToDigitalPin(p) (((p) < 20) ? (analogChannelToDigitalPin(p)) : -1)
+#define digitalPinToInterrupt(p) (((p) < 48) ? (p) : -1)
+#define digitalPinHasPWM(p) (p < 46)
+
+static const uint8_t TX = 43;
+static const uint8_t RX = 44;
+
+static const uint8_t SDA = 41;
+static const uint8_t SCL = 42;
+
+static const uint8_t SS = 8;
+static const uint8_t MOSI = 10;
+static const uint8_t MISO = 11;
+static const uint8_t SCK = 9;
+
+static const uint8_t A0 = 1;
+static const uint8_t A1 = 2;
+static const uint8_t A2 = 3;
+static const uint8_t A3 = 4;
+static const uint8_t A4 = 5;
+static const uint8_t A5 = 6;
+static const uint8_t A6 = 7;
+static const uint8_t A7 = 8;
+static const uint8_t A8 = 9;
+static const uint8_t A9 = 10;
+static const uint8_t A10 = 11;
+static const uint8_t A11 = 12;
+static const uint8_t A12 = 13;
+static const uint8_t A13 = 14;
+static const uint8_t A14 = 15;
+static const uint8_t A15 = 16;
+static const uint8_t A16 = 17;
+static const uint8_t A17 = 18;
+static const uint8_t A18 = 19;
+static const uint8_t A19 = 20;
+
+static const uint8_t T1 = 1;
+static const uint8_t T2 = 2;
+static const uint8_t T3 = 3;
+static const uint8_t T4 = 4;
+static const uint8_t T5 = 5;
+static const uint8_t T6 = 6;
+static const uint8_t T7 = 7;
+static const uint8_t T8 = 8;
+static const uint8_t T9 = 9;
+static const uint8_t T10 = 10;
+static const uint8_t T11 = 11;
+static const uint8_t T12 = 12;
+static const uint8_t T13 = 13;
+static const uint8_t T14 = 14;
+
+static const uint8_t Vext = 36;
+static const uint8_t LED = 18;
+
+static const uint8_t RST_LoRa = 12;
+static const uint8_t BUSY_LoRa = 13;
+static const uint8_t DIO0 = 14;
+
+#endif /* Pins_Arduino_h */
diff --git a/variants/heltec_wireless_tracker/platformio.ini b/variants/heltec_wireless_tracker/platformio.ini
new file mode 100644
index 000000000..92e76a981
--- /dev/null
+++ b/variants/heltec_wireless_tracker/platformio.ini
@@ -0,0 +1,11 @@
+[env:heltec-wireless-tracker]
+extends = esp32s3_base
+board = heltec_wireless_tracker
+upload_protocol = esp-builtin
+
+build_flags =
+ ${esp32s3_base.build_flags} -I variants/heltec_wireless_tracker
+
+lib_deps =
+ ${esp32s3_base.lib_deps}
+ lovyan03/LovyanGFX@^1.1.7
\ No newline at end of file
diff --git a/variants/heltec_wireless_tracker/variant.h b/variants/heltec_wireless_tracker/variant.h
new file mode 100644
index 000000000..318454522
--- /dev/null
+++ b/variants/heltec_wireless_tracker/variant.h
@@ -0,0 +1,59 @@
+#define LED_PIN 18
+
+// ST7735S TFT LCD
+#define ST7735S 1 // there are different (sub-)versions of ST7735
+#define ST7735_CS 38
+#define ST7735_RS 40 // DC
+#define ST7735_SDA 42 // MOSI
+#define ST7735_SCK 41
+#define ST7735_RESET 39
+#define ST7735_MISO -1
+#define ST7735_BUSY -1
+#define ST7735_BL 45
+#define ST7735_SPI_HOST SPI3_HOST
+#define ST7735_BACKLIGHT_EN 45
+#define SPI_FREQUENCY 40000000
+#define SPI_READ_FREQUENCY 16000000
+#define SCREEN_ROTATE
+#define TFT_HEIGHT 160
+#define TFT_WIDTH 80
+#define TFT_OFFSET_X 26
+#define TFT_OFFSET_Y 0
+#define VTFT_CTRL 46 // Heltec Tracker needs this pulled low for TFT
+#define SCREEN_TRANSITION_FRAMERATE 1 // fps
+
+#define VEXT_ENABLE Vext // active low, powers the oled display and the lora antenna boost
+#define BUTTON_PIN 0
+
+#define BATTERY_PIN 1 // A battery voltage measurement pin, voltage divider connected here to measure battery voltage
+#define ADC_CHANNEL ADC1_GPIO1_CHANNEL
+#define ADC_ATTENUATION ADC_ATTEN_DB_2_5 // lower dB for high resistance voltage divider
+#define ADC_MULTIPLIER 4.9
+
+#undef GPS_RX_PIN
+#undef GPS_TX_PIN
+#define GPS_RX_PIN 33
+#define GPS_TX_PIN 34
+#define PIN_GPS_RESET 35
+#define PIN_GPS_PPS 36
+#define VGNSS_CTRL 37 // Heltec Tracker needs this pulled low for GPS
+#define GPS_RESET_MODE LOW
+#define GPS_UC6580
+
+#define USE_SX1262
+#define LORA_DIO0 -1 // a No connect on the SX1262 module
+#define LORA_RESET 12
+#define LORA_DIO1 14 // SX1262 IRQ
+#define LORA_DIO2 13 // SX1262 BUSY
+#define LORA_DIO3 // Not connected on PCB, but internally on the TTGO SX1262, if DIO3 is high the TXCO is enabled
+
+#define RF95_SCK 9
+#define RF95_MISO 11
+#define RF95_MOSI 10
+#define RF95_NSS 8
+
+#define SX126X_CS RF95_NSS
+#define SX126X_DIO1 LORA_DIO1
+#define SX126X_BUSY LORA_DIO2
+#define SX126X_RESET LORA_RESET
+#define SX126X_E22
\ No newline at end of file
diff --git a/variants/heltec_wsl_v3/platformio.ini b/variants/heltec_wsl_v3/platformio.ini
index 5f89a7466..c95659156 100644
--- a/variants/heltec_wsl_v3/platformio.ini
+++ b/variants/heltec_wsl_v3/platformio.ini
@@ -4,3 +4,4 @@ board = heltec_wifi_lora_32_V3
# Temporary until espressif creates a release with this new target
build_flags =
${esp32s3_base.build_flags} -D HELTEC_WSL_V3 -I variants/heltec_wsl_v3
+ -DGPS_POWER_TOGGLE ; comment this line to disable triple press function on the user button to turn off gps entirely.
\ No newline at end of file
diff --git a/variants/heltec_wsl_v3/variant.h b/variants/heltec_wsl_v3/variant.h
index 0ecc5bea7..ec5796313 100644
--- a/variants/heltec_wsl_v3/variant.h
+++ b/variants/heltec_wsl_v3/variant.h
@@ -8,6 +8,8 @@
#define VEXT_ENABLE Vext // active low, powers the oled display and the lora antenna boost
#define BUTTON_PIN 0
+#define PIN_GPS_EN 46 // GPS power enable pin
+
#define BATTERY_PIN 1 // A battery voltage measurement pin, voltage divider connected here to measure battery voltage
#define ADC_CHANNEL ADC1_GPIO1_CHANNEL
#define ADC_ATTENUATION ADC_ATTEN_DB_2_5 // lower dB for high resistance voltage divider
@@ -30,4 +32,4 @@
#define SX126X_DIO1 LORA_DIO1
#define SX126X_BUSY LORA_DIO2
#define SX126X_RESET LORA_RESET
-#define SX126X_E22
\ No newline at end of file
+#define SX126X_E22
diff --git a/variants/m5stack_coreink/variant.h b/variants/m5stack_coreink/variant.h
index 37131caca..3abf16be7 100644
--- a/variants/m5stack_coreink/variant.h
+++ b/variants/m5stack_coreink/variant.h
@@ -1,7 +1,19 @@
+// Primary I2C Bus includes PCF8563 RTC Module
#define I2C_SDA 21
#define I2C_SCL 22
-// LED?
+// 7-07-2023 Or enable Secondary I2C Bus
+//#define I2C_SDA1 32
+//#define I2C_SCL1 33
+
+#define HAS_GPS 1
+#undef GPS_RX_PIN
+#undef GPS_TX_PIN
+// Use Secondary I2C Bus as GPS Serial
+#define GPS_RX_PIN 33
+#define GPS_TX_PIN 32
+
+// Green LED
#define LED_INVERTED 0
#define LED_PIN 10
@@ -37,10 +49,6 @@
#define LORA_DIO1 RADIOLIB_NC
#define LORA_DIO2 RADIOLIB_NC
-// This board has no GPS for now
-#undef GPS_RX_PIN
-#undef GPS_TX_PIN
-
#define USE_EINK
// https://docs.m5stack.com/en/core/coreink
// https://m5stack.oss-cn-shenzhen.aliyuncs.com/resource/docs/schematic/Core/coreink/coreink_sch.pdf
diff --git a/variants/monteops_hw1/platformio.ini b/variants/monteops_hw1/platformio.ini
new file mode 100644
index 000000000..f9d260e74
--- /dev/null
+++ b/variants/monteops_hw1/platformio.ini
@@ -0,0 +1,14 @@
+; MonteOps M.Node/M.Backbone/M.Eagle hardware based on hardware variant #1 (RAK4630 based)
+[env:monteops_hw1]
+extends = nrf52840_base
+board = wiscore_rak4631
+build_flags = ${nrf52840_base.build_flags} -Ivariants/monteops_hw1 -D MONTEOPS_HW1
+ -L "${platformio.libdeps_dir}/${this.__env__}/BSEC2 Software Library/src/cortex-m4/fpv4-sp-d16-hard"
+build_src_filter = ${nrf52_base.build_src_filter} +<../variants/monteops_hw1> + + +
+lib_deps =
+ ${nrf52840_base.lib_deps}
+ ${networking_base.lib_deps}
+ https://github.com/RAKWireless/RAK13800-W5100S.git#1.0.2
+debug_tool = jlink
+; If not set we will default to uploading over serial (first it forces bootloader entry by talking 1200bps to cdcacm)
+;upload_protocol = jlink
\ No newline at end of file
diff --git a/variants/monteops_hw1/variant.cpp b/variants/monteops_hw1/variant.cpp
new file mode 100644
index 000000000..75cca1dc3
--- /dev/null
+++ b/variants/monteops_hw1/variant.cpp
@@ -0,0 +1,41 @@
+/*
+ Copyright (c) 2014-2015 Arduino LLC. All right reserved.
+ Copyright (c) 2016 Sandeep Mistry All right reserved.
+ Copyright (c) 2018, Adafruit Industries (adafruit.com)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ See the GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#include "variant.h"
+#include "nrf.h"
+#include "wiring_constants.h"
+#include "wiring_digital.h"
+
+const uint32_t g_ADigitalPinMap[] = {
+ // P0
+ 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
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47};
+
+void initVariant()
+{
+ // LED1 & LED2
+ pinMode(PIN_LED1, OUTPUT);
+ ledOff(PIN_LED1);
+
+ pinMode(PIN_LED2, OUTPUT);
+ ledOff(PIN_LED2);
+}
diff --git a/variants/monteops_hw1/variant.h b/variants/monteops_hw1/variant.h
new file mode 100644
index 000000000..866ddf471
--- /dev/null
+++ b/variants/monteops_hw1/variant.h
@@ -0,0 +1,240 @@
+/*
+ Copyright (c) 2014-2015 Arduino LLC. All right reserved.
+ Copyright (c) 2016 Sandeep Mistry All right reserved.
+ Copyright (c) 2018, Adafruit Industries (adafruit.com)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ See the GNU Lesser General Public License for more details.
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#ifndef _VARIANT_MOPS_HW1_
+#define _VARIANT_MOPS_HW1_
+
+#define RAK4630
+
+// MonteOps hardware design variant
+#ifndef MONTEOPS_HW1
+#define MONTEOPS_HW1
+#endif
+
+/** Master clock frequency */
+#define VARIANT_MCK (64000000ul)
+
+#define USE_LFXO // Board uses 32khz crystal for LF
+// define USE_LFRC // Board uses RC for LF
+
+/*----------------------------------------------------------------------------
+ * Headers
+ *----------------------------------------------------------------------------*/
+
+#include "WVariant.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+// Number of pins defined in PinDescription array
+#define PINS_COUNT (48)
+#define NUM_DIGITAL_PINS (48)
+#define NUM_ANALOG_INPUTS (6)
+#define NUM_ANALOG_OUTPUTS (0)
+
+// LEDs
+#define PIN_LED1 (35)
+#define PIN_LED2 (36) // Connected to WWAN host LED (if present)
+
+#define LED_BUILTIN PIN_LED1
+#define LED_CONN PIN_LED2
+
+#define LED_GREEN PIN_LED1
+#define LED_BLUE PIN_LED2
+
+#define LED_STATE_ON 1 // State when LED is litted
+
+/*
+ * Buttons
+ */
+
+//#define PIN_BUTTON1 9 // Pin for button on E-ink button module or IO expansion
+#define BUTTON_NEED_PULLUP
+#define PIN_BUTTON2 12
+#define PIN_BUTTON3 24
+#define PIN_BUTTON4 25
+
+/*
+ * Analog pins
+ */
+#define PIN_A0 (5)
+#define PIN_A1 (31)
+#define PIN_A2 (28)
+#define PIN_A3 (29)
+#define PIN_A4 (30)
+#define PIN_A5 (31)
+#define PIN_A6 (0xff)
+#define PIN_A7 (0xff)
+
+static const uint8_t A0 = PIN_A0;
+static const uint8_t A1 = PIN_A1;
+static const uint8_t A2 = PIN_A2;
+static const uint8_t A3 = PIN_A3;
+static const uint8_t A4 = PIN_A4;
+static const uint8_t A5 = PIN_A5;
+static const uint8_t A6 = PIN_A6;
+static const uint8_t A7 = PIN_A7;
+#define ADC_RESOLUTION 14
+
+// Other pins
+#define PIN_AREF (2)
+#define PIN_NFC1 (9)
+#define PIN_NFC2 (10)
+
+static const uint8_t AREF = PIN_AREF;
+
+/*
+ * Serial interfaces
+ */
+#define PIN_SERIAL1_RX (15)
+#define PIN_SERIAL1_TX (16)
+
+// Connected to Jlink CDC
+#define PIN_SERIAL2_RX (8)
+#define PIN_SERIAL2_TX (6)
+
+/*
+ * SPI Interfaces
+ */
+#define SPI_INTERFACES_COUNT 2
+
+#define PIN_SPI_MISO (45)
+#define PIN_SPI_MOSI (44)
+#define PIN_SPI_SCK (43)
+
+#define PIN_SPI1_MISO (29) // (0 + 29)
+#define PIN_SPI1_MOSI (30) // (0 + 30)
+#define PIN_SPI1_SCK (3) // (0 + 3)
+
+static const uint8_t SS = 42;
+static const uint8_t MOSI = PIN_SPI_MOSI;
+static const uint8_t MISO = PIN_SPI_MISO;
+static const uint8_t SCK = PIN_SPI_SCK;
+
+#define WIRE_INTERFACES_COUNT 1
+
+#define PIN_WIRE_SDA (13)
+#define PIN_WIRE_SCL (14)
+
+// QSPI Pins
+#define PIN_QSPI_SCK 3
+#define PIN_QSPI_CS 26
+#define PIN_QSPI_IO0 30
+#define PIN_QSPI_IO1 29
+#define PIN_QSPI_IO2 28
+#define PIN_QSPI_IO3 2
+
+// On-board QSPI Flash
+#define EXTERNAL_FLASH_DEVICES IS25LP080D
+#define EXTERNAL_FLASH_USE_QSPI
+
+/* @note RAK5005-O GPIO mapping to RAK4631 GPIO ports
+ RAK5005-O <-> nRF52840
+ IO1 <-> P0.17 (Arduino GPIO number 17)
+ IO2 <-> P1.02 (Arduino GPIO number 34)
+ IO3 <-> P0.21 (Arduino GPIO number 21)
+ IO4 <-> P0.04 (Arduino GPIO number 4)
+ IO5 <-> P0.09 (Arduino GPIO number 9)
+ IO6 <-> P0.10 (Arduino GPIO number 10)
+ IO7 <-> P0.28 (Arduino GPIO number 28)
+ SW1 <-> P0.01 (Arduino GPIO number 1)
+ A0 <-> P0.04/AIN2 (Arduino Analog A2)
+ A1 <-> P0.31/AIN7 (Arduino Analog A7)
+ SPI_CS <-> P0.26 (Arduino GPIO number 26)
+ */
+
+// RAK4630 LoRa module
+
+/* Setup of the SX1262 LoRa module ( https://docs.rakwireless.com/Product-Categories/WisBlock/RAK4631/Datasheet/ )
+
+P1.10 NSS SPI NSS (Arduino GPIO number 42)
+P1.11 SCK SPI CLK (Arduino GPIO number 43)
+P1.12 MOSI SPI MOSI (Arduino GPIO number 44)
+P1.13 MISO SPI MISO (Arduino GPIO number 45)
+P1.14 BUSY BUSY signal (Arduino GPIO number 46)
+P1.15 DIO1 DIO1 event interrupt (Arduino GPIO number 47)
+P1.06 NRESET NRESET manual reset of the SX1262 (Arduino GPIO number 38)
+
+Important for successful SX1262 initialization:
+
+* Setup DIO2 to control the antenna switch
+* Setup DIO3 to control the TCXO power supply
+* Setup the SX1262 to use it's DCDC regulator and not the LDO
+* RAK4630 schematics show GPIO P1.07 connected to the antenna switch, but it should not be initialized, as DIO2 will do the
+control of the antenna switch
+
+SO GPIO 39/TXEN MAY NOT BE DEFINED FOR SUCCESSFUL OPERATION OF THE SX1262 - TG
+
+*/
+
+#define USE_SX1262
+#define SX126X_CS (42)
+#define SX126X_DIO1 (47)
+#define SX126X_BUSY (46)
+#define SX126X_RESET (38)
+// #define SX126X_TXEN (39)
+// #define SX126X_RXEN (37)
+#define SX126X_POWER_EN (37)
+#define SX126X_E22 // DIO2 controlls an antenna switch and the TCXO voltage is controlled by DIO3
+
+#define PIN_GPS_RESET (34) // Must be P1.02
+// #define PIN_GPS_EN
+// #define PIN_GPS_PPS (17) // Pulse per second input from the GPS
+
+#define GPS_RX_PIN PIN_SERIAL1_RX
+#define GPS_TX_PIN PIN_SERIAL1_TX
+
+// Battery
+// The battery sense is hooked to pin A0 (5)
+#define BATTERY_PIN PIN_A0
+// and has 12 bit resolution
+#define BATTERY_SENSE_RESOLUTION_BITS 12
+#define BATTERY_SENSE_RESOLUTION 4096.0
+// Definition of milliVolt per LSB => 3.0V ADC range and 12-bit ADC resolution = 3000mV/4096
+#define VBAT_MV_PER_LSB (0.73242188F)
+// Voltage divider value => 1.5M + 1M voltage divider on VBAT = (1.5M / (1M + 1.5M))
+#define VBAT_DIVIDER (0.4F)
+// Compensation factor for the VBAT divider
+#define VBAT_DIVIDER_COMP (1.73)
+// Fixed calculation of milliVolt from compensation value
+#define REAL_VBAT_MV_PER_LSB (VBAT_DIVIDER_COMP * VBAT_MV_PER_LSB)
+#undef AREF_VOLTAGE
+#define AREF_VOLTAGE 3.0
+#define VBAT_AR_INTERNAL AR_INTERNAL_3_0
+#define ADC_MULTIPLIER VBAT_DIVIDER_COMP // REAL_VBAT_MV_PER_LSB
+#define VBAT_RAW_TO_SCALED(x) (REAL_VBAT_MV_PER_LSB * x)
+
+//#define HAS_RTC 1
+
+#define HAS_ETHERNET 1
+
+#define PIN_ETHERNET_RESET 21
+#define PIN_ETHERNET_SS 26 // P0.26 QSPI_CS
+#define ETH_SPI_PORT SPI1
+#define AQ_SET_PIN 10
+
+#ifdef __cplusplus
+}
+#endif
+
+/*----------------------------------------------------------------------------
+ * Arduino objects - C++ only
+ *----------------------------------------------------------------------------*/
+
+#endif
\ No newline at end of file
diff --git a/variants/rak4631/variant.h b/variants/rak4631/variant.h
index fe9f062c8..258e4eb3c 100644
--- a/variants/rak4631/variant.h
+++ b/variants/rak4631/variant.h
@@ -139,6 +139,9 @@ static const uint8_t SCK = PIN_SPI_SCK;
// #define USE_EINK
+// RAKRGB
+#define HAS_NCP5623
+
/*
* Wire Interfaces
*/
@@ -255,6 +258,8 @@ SO GPIO 39/TXEN MAY NOT BE DEFINED FOR SUCCESSFUL OPERATION OF THE SX1262 - TG
#define HAS_ETHERNET 1
+#define RAK_4631 1
+
#define PIN_ETHERNET_RESET 21
#define PIN_ETHERNET_SS PIN_EINK_CS
#define ETH_SPI_PORT SPI1
diff --git a/variants/rak4631_epaper/variant.h b/variants/rak4631_epaper/variant.h
index a43229088..ad3e4b87f 100644
--- a/variants/rak4631_epaper/variant.h
+++ b/variants/rak4631_epaper/variant.h
@@ -139,6 +139,9 @@ static const uint8_t SCK = PIN_SPI_SCK;
#define USE_EINK
+// RAKRGB
+#define HAS_NCP5623
+
/*
* Wire Interfaces
*/
@@ -226,6 +229,8 @@ static const uint8_t SCK = PIN_SPI_SCK;
#define HAS_RTC 1
+#define RAK_4631 1
+
#ifdef __cplusplus
}
#endif
@@ -234,4 +239,4 @@ static const uint8_t SCK = PIN_SPI_SCK;
* Arduino objects - C++ only
*----------------------------------------------------------------------------*/
-#endif
+#endif
\ No newline at end of file
diff --git a/variants/rak4631_epaper_onrxtx/variant.h b/variants/rak4631_epaper_onrxtx/variant.h
index 44db0b7f0..e4d7c7d45 100644
--- a/variants/rak4631_epaper_onrxtx/variant.h
+++ b/variants/rak4631_epaper_onrxtx/variant.h
@@ -120,6 +120,9 @@ static const uint8_t SCK = PIN_SPI_SCK;
// FIXME - I think this is actually just the board power enable - it enables power to the CPU also
// #define PIN_EINK_PWR_ON (-1)
+// RAKRGB
+#define HAS_NCP5623
+
/*
* Wire Interfaces
*/
@@ -207,4 +210,4 @@ static const uint8_t SCK = PIN_SPI_SCK;
* Arduino objects - C++ only
*----------------------------------------------------------------------------*/
-#endif
+#endif
\ No newline at end of file
diff --git a/variants/rpipico/variant.h b/variants/rpipico/variant.h
index 7e2660aa6..fb4b9bd75 100644
--- a/variants/rpipico/variant.h
+++ b/variants/rpipico/variant.h
@@ -15,11 +15,11 @@
#define USE_SH1106 1
#undef GPS_SERIAL_NUM
-// #define I2C_SDA 6
-// #define I2C_SCL 7
+// default I2C pins:
+// SDA = 4
+// SCL = 5
#define BUTTON_PIN 17
-#define EXT_NOTIFY_OUT 4
#define LED_PIN PIN_LED
diff --git a/variants/rpipicow/variant.h b/variants/rpipicow/variant.h
index 4741fd130..59f8d2ec2 100644
--- a/variants/rpipicow/variant.h
+++ b/variants/rpipicow/variant.h
@@ -15,11 +15,11 @@
#define USE_SH1106 1
#undef GPS_SERIAL_NUM
-// #define I2C_SDA 6
-// #define I2C_SCL 7
+// default I2C pins:
+// SDA = 4
+// SCL = 5
#define BUTTON_PIN 17
-#define EXT_NOTIFY_OUT 4
#define BATTERY_PIN 26
// ratio of voltage divider = 3.0 (R17=200k, R18=100k)
diff --git a/variants/t-deck/pins_arduino.h b/variants/t-deck/pins_arduino.h
new file mode 100644
index 000000000..0150935ed
--- /dev/null
+++ b/variants/t-deck/pins_arduino.h
@@ -0,0 +1,69 @@
+#ifndef Pins_Arduino_h
+#define Pins_Arduino_h
+
+#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) < NUM_ANALOG_INPUTS) ? (analogChannelToDigitalPin(p)) : -1)
+#define digitalPinToInterrupt(p) (((p) < NUM_DIGITAL_PINS) ? (p) : -1)
+#define digitalPinHasPWM(p) (p < EXTERNAL_NUM_INTERRUPTS)
+
+// static const uint8_t LED_BUILTIN = -1;
+
+static const uint8_t TX = 43;
+static const uint8_t RX = 44;
+
+static const uint8_t SDA = 18;
+static const uint8_t SCL = 8;
+
+// Default SPI will be mapped to Radio
+static const uint8_t SS = 9;
+static const uint8_t MOSI = 41;
+static const uint8_t MISO = 38;
+static const uint8_t SCK = 40;
+
+static const uint8_t A0 = 1;
+static const uint8_t A1 = 2;
+static const uint8_t A2 = 3;
+static const uint8_t A3 = 4;
+static const uint8_t A4 = 5;
+static const uint8_t A5 = 6;
+static const uint8_t A6 = 7;
+static const uint8_t A7 = 8;
+static const uint8_t A8 = 9;
+static const uint8_t A9 = 10;
+static const uint8_t A10 = 11;
+static const uint8_t A11 = 12;
+static const uint8_t A12 = 13;
+static const uint8_t A13 = 14;
+static const uint8_t A14 = 15;
+static const uint8_t A15 = 16;
+static const uint8_t A16 = 17;
+static const uint8_t A17 = 18;
+static const uint8_t A18 = 19;
+static const uint8_t A19 = 20;
+
+static const uint8_t T1 = 1;
+static const uint8_t T2 = 2;
+static const uint8_t T3 = 3;
+static const uint8_t T4 = 4;
+static const uint8_t T5 = 5;
+static const uint8_t T6 = 6;
+static const uint8_t T7 = 7;
+static const uint8_t T8 = 8;
+static const uint8_t T9 = 9;
+static const uint8_t T10 = 10;
+static const uint8_t T11 = 11;
+static const uint8_t T12 = 12;
+static const uint8_t T13 = 13;
+static const uint8_t T14 = 14;
+
+static const uint8_t BAT_ADC_PIN = 4;
+
+#endif /* Pins_Arduino_h */
diff --git a/variants/t-deck/platformio.ini b/variants/t-deck/platformio.ini
new file mode 100644
index 000000000..8344fb990
--- /dev/null
+++ b/variants/t-deck/platformio.ini
@@ -0,0 +1,14 @@
+; LilyGo T-Deck
+[env:t-deck]
+extends = esp32s3_base
+board = t-deck
+upload_protocol = esp-builtin
+debug_tool = esp-builtin
+
+build_flags = ${esp32_base.build_flags}
+ -DT_DECK
+ -DBOARD_HAS_PSRAM
+ -Ivariants/t-deck
+
+lib_deps = ${esp32s3_base.lib_deps}
+ lovyan03/LovyanGFX@^1.1.7
\ No newline at end of file
diff --git a/variants/t-deck/variant.h b/variants/t-deck/variant.h
new file mode 100644
index 000000000..e434cd35d
--- /dev/null
+++ b/variants/t-deck/variant.h
@@ -0,0 +1,74 @@
+// ST7789 TFT LCD
+#define ST7789_CS 12
+#define ST7789_RS 11 // DC
+#define ST7789_SDA 41 // MOSI
+#define ST7789_SCK 40
+#define ST7789_RESET -1
+#define ST7789_MISO 38
+#define ST7789_BUSY -1
+#define ST7789_BL 42
+#define ST7789_SPI_HOST SPI2_HOST
+#define ST7789_BACKLIGHT_EN 42
+#define SPI_FREQUENCY 40000000
+#define SPI_READ_FREQUENCY 16000000
+#define TFT_HEIGHT 320
+#define TFT_WIDTH 240
+#define TFT_OFFSET_X 0
+#define TFT_OFFSET_Y 0
+#define SCREEN_ROTATE
+#define SCREEN_TRANSITION_FRAMERATE 1 // fps
+#define SCREEN_TOUCH_INT 16
+#define TOUCH_SLAVE_ADDRESS 0x5D // GT911
+
+#define BUTTON_PIN 0
+// #define BUTTON_NEED_PULLUP
+
+#define HAS_GPS 0
+#undef GPS_RX_PIN
+#undef GPS_TX_PIN
+
+// Have SPI interface SD card slot
+#define HAS_SDCARD 1
+#define SPI_MOSI (41)
+#define SPI_SCK (40)
+#define SPI_MISO (38)
+#define SPI_CS (39)
+#define SDCARD_CS SPI_CS
+
+#define BATTERY_PIN 4 // A battery voltage measurement pin, voltage divider connected here to measure battery voltage
+// ratio of voltage divider = 2.0 (RD2=100k, RD3=100k)
+#define ADC_MULTIPLIER 2.11 // 2.0 + 10% for correction of display undervoltage.
+#define ADC_CHANNEL ADC1_GPIO1_CHANNEL
+
+// keyboard
+#define I2C_SDA 18 // I2C pins for this board
+#define I2C_SCL 8
+#define BOARD_POWERON 10 // must be set to HIGH
+#define KB_SLAVE_ADDRESS 0x55
+#define KB_BL_PIN 46 // INT, set to INPUT
+#define KB_UP 2
+#define KB_DOWN 3
+#define KB_LEFT 1
+#define KB_RIGHT 15
+
+#define USE_SX1262
+#define USE_SX1268
+
+#define RF95_SCK 40
+#define RF95_MISO 38
+#define RF95_MOSI 41
+#define RF95_NSS 9
+
+#define LORA_DIO0 -1 // a No connect on the SX1262 module
+#define LORA_RESET 17
+#define LORA_DIO1 45 // SX1262 IRQ
+#define LORA_DIO2 13 // SX1262 BUSY
+#define LORA_DIO3 // Not connected on PCB, but internally on the TTGO SX1262, if DIO3 is high the TXCO is enabled
+
+#define SX126X_CS RF95_NSS // FIXME - we really should define LORA_CS instead
+#define SX126X_DIO1 LORA_DIO1
+#define SX126X_BUSY LORA_DIO2
+#define SX126X_RESET LORA_RESET
+#define SX126X_E22 // Not really an E22 but TTGO seems to be trying to clone that
+// Internally the TTGO module hooks the SX1262-DIO2 in to control the TX/RX switch (which is the default for the sx1262interface
+// code)
diff --git a/variants/t-watch-s3/pins_arduino.h b/variants/t-watch-s3/pins_arduino.h
new file mode 100644
index 000000000..d3dde6856
--- /dev/null
+++ b/variants/t-watch-s3/pins_arduino.h
@@ -0,0 +1,64 @@
+#ifndef Pins_Arduino_h
+#define Pins_Arduino_h
+
+#include
+
+#define EXTERNAL_NUM_INTERRUPTS 46
+#define NUM_DIGITAL_PINS 48
+#define NUM_ANALOG_INPUTS 20
+
+#define analogInputToDigitalPin(p) (((p) < NUM_ANALOG_INPUTS) ? (analogChannelToDigitalPin(p)) : -1)
+#define digitalPinToInterrupt(p) (((p) < NUM_DIGITAL_PINS) ? (p) : -1)
+#define digitalPinHasPWM(p) (p < EXTERNAL_NUM_INTERRUPTS)
+
+// static const uint8_t LED_BUILTIN = -1;
+
+// static const uint8_t TX = 43;
+// static const uint8_t RX = 44;
+
+static const uint8_t SDA = 10;
+static const uint8_t SCL = 11;
+
+// Default SPI will be mapped to Radio
+static const uint8_t SS = 5;
+static const uint8_t MOSI = 1;
+static const uint8_t MISO = 4;
+static const uint8_t SCK = 3;
+
+static const uint8_t A0 = 1;
+static const uint8_t A1 = 2;
+static const uint8_t A2 = 3;
+static const uint8_t A3 = 4;
+static const uint8_t A4 = 5;
+static const uint8_t A5 = 6;
+static const uint8_t A6 = 7;
+static const uint8_t A7 = 8;
+static const uint8_t A8 = 9;
+static const uint8_t A9 = 10;
+static const uint8_t A10 = 11;
+static const uint8_t A11 = 12;
+static const uint8_t A12 = 13;
+static const uint8_t A13 = 14;
+static const uint8_t A14 = 15;
+static const uint8_t A15 = 16;
+static const uint8_t A16 = 17;
+static const uint8_t A17 = 18;
+static const uint8_t A18 = 19;
+static const uint8_t A19 = 20;
+
+static const uint8_t T1 = 1;
+static const uint8_t T2 = 2;
+static const uint8_t T3 = 3;
+static const uint8_t T4 = 4;
+static const uint8_t T5 = 5;
+static const uint8_t T6 = 6;
+static const uint8_t T7 = 7;
+static const uint8_t T8 = 8;
+static const uint8_t T9 = 9;
+static const uint8_t T10 = 10;
+static const uint8_t T11 = 11;
+static const uint8_t T12 = 12;
+static const uint8_t T13 = 13;
+static const uint8_t T14 = 14;
+
+#endif /* Pins_Arduino_h */
\ No newline at end of file
diff --git a/variants/t-watch-s3/platformio.ini b/variants/t-watch-s3/platformio.ini
new file mode 100644
index 000000000..709ea89ee
--- /dev/null
+++ b/variants/t-watch-s3/platformio.ini
@@ -0,0 +1,17 @@
+; LilyGo T-Watch S3
+[env:t-watch-s3]
+extends = esp32s3_base
+board = t-watch-s3
+upload_protocol = esptool
+upload_speed = 115200
+#upload_port = /dev/tty.usbmodem3485188D636C1
+
+build_flags = ${esp32_base.build_flags}
+ -DT_WATCH_S3
+ -Ivariants/t-watch-s3
+ -DPCF8563_RTC=0x51
+
+lib_deps = ${esp32s3_base.lib_deps}
+ lovyan03/LovyanGFX@^1.1.7
+ lewisxhe/PCF8563_Library@1.0.1
+ adafruit/Adafruit DRV2605 Library@^1.2.2
\ No newline at end of file
diff --git a/variants/t-watch-s3/variant.h b/variants/t-watch-s3/variant.h
new file mode 100644
index 000000000..652696c3f
--- /dev/null
+++ b/variants/t-watch-s3/variant.h
@@ -0,0 +1,64 @@
+// ST7789 TFT LCD
+#define ST7789_CS 12
+#define ST7789_RS 38 // DC
+#define ST7789_SDA 13 // MOSI
+#define ST7789_SCK 18
+#define ST7789_RESET -1
+#define ST7789_MISO -1
+#define ST7789_BUSY -1
+#define ST7789_BL 45
+#define ST7789_SPI_HOST SPI3_HOST
+#define ST7789_BACKLIGHT_EN 45
+#define SPI_FREQUENCY 40000000
+#define SPI_READ_FREQUENCY 16000000
+#define TFT_HEIGHT 240
+#define TFT_WIDTH 240
+#define TFT_OFFSET_X 0
+#define TFT_OFFSET_Y 0
+#define SCREEN_ROTATE
+#define SCREEN_TRANSITION_FRAMERATE 1 // fps
+#define SCREEN_TOUCH_INT 16
+#define SCREEN_TOUCH_USE_I2C1 1
+#define TOUCH_SLAVE_ADDRESS 0x38 // GT911
+
+#define I2C_SDA1 39 // Used for capacitive touch
+#define I2C_SCL1 40 // Used for capacitive touch
+
+#define TFT_BL ST7789_BACKLIGHT_EN
+
+#define HAS_AXP2101
+
+#define HAS_RTC 1
+
+#define I2C_SDA 10 // For QMC6310 sensors and screens
+#define I2C_SCL 11 // For QMC6310 sensors and screens
+
+#define BUTTON_PIN 0
+
+#define BMA4XX_INT 14 // Interrupt for BMA_423 axis sensor
+
+#define HAS_GPS 0
+#undef GPS_RX_PIN
+#undef GPS_TX_PIN
+
+#define USE_SX1262
+#define USE_SX1268
+
+#define RF95_SCK 3
+#define RF95_MISO 4
+#define RF95_MOSI 1
+#define RF95_NSS 5
+
+#define LORA_DIO0 -1 // a No connect on the SX1262 module
+#define LORA_RESET 8
+#define LORA_DIO1 9 // SX1262 IRQ
+#define LORA_DIO2 7 // SX1262 BUSY
+#define LORA_DIO3 // Not connected on PCB, but internally on the TTGO SX1262, if DIO3 is high the TXCO is enabled
+
+#define SX126X_CS RF95_NSS // FIXME - we really should define LORA_CS instead
+#define SX126X_DIO1 LORA_DIO1
+#define SX126X_BUSY LORA_DIO2
+#define SX126X_RESET LORA_RESET
+#define SX126X_E22 // Not really an E22 but TTGO seems to be trying to clone that
+ // Internally the TTGO module hooks the SX1262-DIO2 in to control the TX/RX switch (which is the default for
+ // the sx1262interface code)
\ No newline at end of file
diff --git a/variants/tbeam-s3-core/variant.h b/variants/tbeam-s3-core/variant.h
index 69f639de8..532b5b85c 100644
--- a/variants/tbeam-s3-core/variant.h
+++ b/variants/tbeam-s3-core/variant.h
@@ -39,6 +39,8 @@
// #define PMU_IRQ 40
#define HAS_AXP2101
+#define HAS_RTC 1
+
// Specify the PMU as Wire1. In the t-beam-s3 core, PCF8563 and PMU share the bus
#define PMU_USE_WIRE1
#define RTC_USE_WIRE1
@@ -59,8 +61,6 @@
// PCF8563 RTC Module
// #define PCF8563_RTC 0x51 //Putting definitions in variant. h does not compile correctly
-#define HAS_RTC 1
-
// has 32768 Hz crystal
#define HAS_32768HZ
diff --git a/variants/tlora_t3s3_v1/platformio.ini b/variants/tlora_t3s3_v1/platformio.ini
index bef57c3b4..fd3d393d9 100644
--- a/variants/tlora_t3s3_v1/platformio.ini
+++ b/variants/tlora_t3s3_v1/platformio.ini
@@ -4,4 +4,5 @@ board = tlora-t3s3-v1
upload_protocol = esp-builtin
build_flags =
- ${esp32_base.build_flags} -D TLORA_T3S3_V1 -I variants/tlora_t3s3_v1
\ No newline at end of file
+ ${esp32_base.build_flags} -D TLORA_T3S3_V1 -I variants/tlora_t3s3_v1
+ -DGPS_POWER_TOGGLE ; comment this line to disable triple press function on the user button to turn off gps entirely.
\ No newline at end of file
diff --git a/variants/tlora_t3s3_v1/variant.h b/variants/tlora_t3s3_v1/variant.h
index 313b08e6d..7f914c055 100644
--- a/variants/tlora_t3s3_v1/variant.h
+++ b/variants/tlora_t3s3_v1/variant.h
@@ -1,6 +1,8 @@
#undef GPS_RX_PIN
#undef GPS_TX_PIN
+#define PIN_GPS_EN 42 // GPS power enable pin
+
#define HAS_SDCARD
#define SDCARD_USE_SPI1
diff --git a/variants/tlora_v2_1_16/platformio.ini b/variants/tlora_v2_1_16/platformio.ini
index da2a32ce4..167f6c37c 100644
--- a/variants/tlora_v2_1_16/platformio.ini
+++ b/variants/tlora_v2_1_16/platformio.ini
@@ -2,4 +2,5 @@
extends = esp32_base
board = ttgo-lora32-v21
build_flags =
- ${esp32_base.build_flags} -D TLORA_V2_1_16 -I variants/tlora_v2_1_16
\ No newline at end of file
+ ${esp32_base.build_flags} -D TLORA_V2_1_16 -I variants/tlora_v2_1_16
+ -DGPS_POWER_TOGGLE ; comment this line to disable triple press function on the user button to turn off gps entirely.
\ No newline at end of file
diff --git a/variants/tlora_v2_1_16/variant.h b/variants/tlora_v2_1_16/variant.h
index adb5af898..30a176e4c 100644
--- a/variants/tlora_v2_1_16/variant.h
+++ b/variants/tlora_v2_1_16/variant.h
@@ -3,6 +3,8 @@
#define GPS_RX_PIN 15 // per @der_bear on the forum, 36 is incorrect for this board type and 15 is a better pick
#define GPS_TX_PIN 13
+#define PIN_GPS_EN 19 // GPS power enable pin
+
#define BATTERY_PIN 35
#define ADC_CHANNEL ADC1_GPIO35_CHANNEL
#define BATTERY_SENSE_SAMPLES 30
diff --git a/variants/xiao_ble/README.md b/variants/xiao_ble/README.md
new file mode 100644
index 000000000..6fff9cd22
--- /dev/null
+++ b/variants/xiao_ble/README.md
@@ -0,0 +1,261 @@
+#
+
+
+ Xiao BLE/BLE Sense + Ebyte E22-900M30S
+
+
+
+ A step-by-step guide for macOS and Linux
+
+
+## Introduction
+
+This guide will walk you through everything needed to get the Xiao BLE (or BLE Sense) running Meshtastic using an Ebyte E22-900M30S LoRa module. The combination of the E22 with an nRF52840 MCU is desirable because it allows for both very low idle (Rx) power draw and high transmit power. The Xiao BLE is a small but surprisingly well-appointed nRF52840 board, with enough GPIO for most Meshtastic applications and a built-in LiPo charger. The E22, on the other hand, is a famously inscrutable and mysterious beast. It is one of the more readily available LoRa modules capable of transmitting at 30 dBm, and includes an LNA to boost its Rx sensitivity a few dB beyond that of the SX1262. However, its documentation is relatively sparse overall, and seems to merely hint at (or completely omit) several key details regarding its functionality. Thus, much of what follows is a synthesis of my observations and inferences over the course of many hours of trial and error.
+
+Acknowledgement and friendly disclaimer
+
+Huge thanks to those in the community who have forged the way with the E22, without whose hard work none of this would have been possible! (thebentern, riddick, rainer_vie, beegee-tokyo, geeksville, caveman99, Der_Bear, PlumRugOfDoom, BigCorvus, and many others.)
+
+
+
+Please take the conclusions here as a tentative work in progress, representing my current (and fairly limited) understanding of the E22 when paired with this particular MCU. It is my hope that this guide will be helpful to others who are interested in trying a DIY Meshtastic build, and also be subject to revision by folks with more experience and better test equipment.
+
+### Obligatory liability disclaimer
+
+This guide and all associated content is for informational purposes only. The information presented is intended for consumption only by persons having appropriate technical skill and judgement, to be used entirely at their own discretion and risk. The authors of this guide in no way provide any warranty, express or implied, toward the content herein, nor its correctness, safety, or suitability to any particular purpose. By following the instructions in this guide in part or in full, you assume all responsibility for all potential risks, including but not limited to fire, property damage, bodily injury, and death.
+
+### Note
+
+These instructions assume you are running macOS or Linux, but it should be relatively easy to translate each command for Windows. (In this case, in step 2 below, each line of `xiao_ble.sh` would also need to be converted to the equivalent Windows CLI command and run individually.)
+
+## 1. Update Bootloader
+
+The first thing you will need to do is update the Xiao BLE's bootloader. The stock bootloader is functionally very similar to the Adafruit nRF52 UF2 bootloader, but apparently not quite enough so to work with Meshtastic out of the box.
+
+1. Connect the Xiao BLE to your computer via USB-C.
+
+2. Install `adafruit-nrfutil` by following the instructions here.
+
+3. Open a terminal window and navigate to `firmware/variants/xiao_ble` (where `firmware` is the directory into which you have cloned the Meshtastic firmware repo).
+
+4. Run the following command, replacing `/dev/cu.usbmodem2101` with the serial port your Xiao BLE is connected to:
+
+ ```bash
+ adafruit-nrfutil --verbose dfu serial --package xiao_nrf52840_ble_bootloader-0.7.0-22-g277a0c8_s140_7.3.0.zip --port /dev/cu.usbmodem2101 -b 115200 --singlebank --touch 1200
+ ```
+
+5. If all goes well, the Xiao BLE's red LED should start to pulse slowly, and you should see a new USB storage device called `XIAO-BOOT` appear under `Locations` in Finder.
+
+
+
+## 2. PlatformIO Environment Preparation
+
+Before building Meshtastic for the Xiao BLE + E22, it is necessary to pull in SoftDevice 7.3.0 and its associated linker script (nrf52840_s140_v7.ld) from Seeed Studio's Arduino core. The `xiao_ble.sh` script does this.
+
+1. In your terminal window, run the following command:
+
+ ```bash
+ sudo ./xiao_ble.sh
+ ```
+
+
+
+## 3. Build Meshtastic
+
+At this point, you should be able to build the firmware successfully.
+
+1. In VS Code, press `Command Shift P` to bring up the command palette.
+
+2. Search for and run the `Developer: Reload Window` command.
+
+3. Bring up the command palette again with `Command Shift P`. Search for and run the `PlatformIO: Pick Project Environment` command.
+
+4. In the list of environments, select `env:xiao_ble`. PlatformIO may update itself for a minute or two, and should let you know once done.
+
+5. Return to the command palette once again (`Command Shift P`). Search for and run the `PlatformIO: Build` command.
+
+6. PlatformIO will build the project. After a few minutes you should see a green `SUCCESS` message.
+
+
+
+## 4. Wire the board
+
+Connecting the E22 to the Xiao BLE is straightforward, but there are a few gotchas to be mindful of.
+
+- On the Xiao BLE:
+
+ - Pins D4 and D5 are currently mapped to `PIN_WIRE_SDA` and `PIN_WIRE_SCL`, respectively. If you are not using I²C and would like to free up pins D4 and D5 for use as GPIO, `PIN_WIRE_SDA` and `PIN_WIRE_SCL` can be reassigned to any two other unused pin numbers.
+
+ - Pins D6 and D7 were originally mapped to the TX and RX pins for serial interface 1 (`PIN_SERIAL1_RX` and `PIN_SERIAL1_TX`) but are currently set to -1 in `variant.h`. If you need to expose a serial interface, you can restore these pins and move e.g. `SX126X_RXEN` to pin 4 or 5 (the opposite should work too).
+
+- On the E22:
+
+ - There are two options for the E22's `TXEN` pin:
+
+ 1. It can be connected to the MCU on the pin defined as `SX126X_TXEN` in `variant.h`. In this configuration, the MCU will control Tx/Rx switching "manually". As long as `SX126X_TXEN` and `SX126X_RXEN` are both defined in `variant.h` (and neither is set to `RADIOLIB_NC`), `SX126xInterface.cpp` will initialize the E22 correctly for this mode.
+
+ 2. Alternately, it can be connected to the E22's `DIO2` pin only, with neither `TXEN` nor `DIO2` being connected to the MCU. In this configuration, the E22 will control Tx/Rx switching automatically. In `variant.h`, as long as `SX126X_TXEN` is defined as `RADIOLIB_NC`, and `SX126X_RXEN` is defined and connected to the E22's `RXEN` pin, and `E22_TXEN_CONNECTED_TO_DIO2` is defined, `SX126xInterface.cpp` will initialize the E22 correctly for this mode. This configuration frees up a GPIO, and presents no drawbacks that I have found.
+
+ - Note that any combination other than the two described above will likely result in unexpected behavior. In my testing, some of these other configurations appeared to "work" at first glance, but every one I tried had at least one of the following flaws: weak Tx power, extremely poor Rx sensitivity, or the E22 overheating because TXEN was never pulled low, causing its PA to stay on indefinitely.
+
+ - Along the same lines, it is a good idea to check the E22's temperature frequently by lightly touching the shield. If you feel the shield getting hot (i.e. approaching uncomfortable to touch) near pins 1, 2, and 3, something is probably misconfigured; disconnect both the Xiao BLE and E22 from power and double check wiring and pin mapping.
+
+ - Whether you opt to let the E22 control Rx and Tx or handle this manually, the E22's `RXEN` pin must always be connected to the MCU on the pin defined as `SX126X_RXEN` in `variant.h`.
+
+Note
+
+The default pin mapping in `variant.h` uses 'automatic Tx/Rx switching' mode. If you wire your board for manual Rx/Tx switching, make sure to update `variant.h` accordingly by commenting/uncommenting the necessary lines in the 'E22 Tx/Rx control options' section.
+
+
+
+---
+
+
+
+Example wiring for "E22 automatic Tx/Rx switching" mode:
+
+
+MCU -> E22 connections
+| Xiao BLE pin | variant.h definition | E22 pin | Notes |
+| :------------ | :---------------------------- | :-----------------| :------------------------------------------------------------------------------------------------------------------- |
+| D0 | SX126X_CS | 19 (NSS) | |
+| D1 | SX126X_DIO1 | 13 (DIO1) | |
+| D2 | SX126X_BUSY | 14 (BUSY) | |
+| D3 | SX126X_RESET | 15 (NRST) | |
+| D7 | SX126X_RXEN | 6 (RXEN) | These pins must still be connected, and `SX126X_RXEN` defined in `variant.h`, otherwise Rx sensitivity will be poor. |
+| D8 | PIN_SPI_SCK | 18 (SCK) | |
+| D9 | PIN_SPI_MISO | 16 (MISO) | |
+| D10 | PIN_SPI_MOSI | 17 (MOSI) | |
+
+
+
+
+E22 -> E22 connections:
+| E22 pin | E22 pin | Notes |
+| :------------ | :---------------------------- | :------------------------------------------------------------------------ |
+| TXEN | DIO2 | These must be physically connected for automatic Tx/Rx switching to work. |
+
+Note
+
+The schematic (`xiao-ble-e22-schematic.png`) in the `eagle-project` directory uses this wiring.
+
+
+
+---
+
+
+
+Example wiring for "Manual Tx/Rx switching" mode:
+
+MCU -> E22 connections
+| Xiao BLE pin | variant.h definition | E22 pin | Notes |
+| :------------ | :---------------------------- | :-----------------| :--------------------------- |
+| D0 | SX126X_CS | 19 (NSS) | |
+| D1 | SX126X_DIO1 | 13 (DIO1) | |
+| D2 | SX126X_BUSY | 14 (BUSY) | |
+| D3 | SX126X_RESET | 15 (NRST) | |
+| D6 | SX126X_TXEN | 7 (TXEN) | |
+| D7 | SX126X_RXEN | 6 (RXEN) | |
+| D8 | PIN_SPI_SCK | 18 (SCK) | |
+| D9 | PIN_SPI_MISO | 16 (MISO) | |
+| D10 | PIN_SPI_MOSI | 17 (MOSI) | |
+
+E22 -> E22 connections: (none)
+
+
+
+## 5. Flash the firmware to the Xiao BLE
+
+1. Double press the Xiao's `reset` button to put it in bootloader mode.
+2. In a terminal window, navigate to the Meshtastic firmware repo's root directory, and from there to `.pio/build/xiao_ble`.
+3. Convert the generated `.hex` file into a `.uf2` file:
+
+ ```bash
+ ../../../bin/uf2conv.py firmware.hex -c -o firmware.uf2 -f 0xADA52840
+ ```
+
+4. Copy the new `.uf2` file to the Xiao's mass storage volume:
+
+ ```bash
+ cp firmware.uf2 /Volumes/XIAO-BOOT
+ ```
+
+5. The Xiao's red LED will flash for several seconds as the firmware is copied.
+6. Once the firmware is copied, to verify it is running, run the following command:
+
+ ```bash
+ meshtastic --noproto
+ ```
+
+7. Then, press the Xiao's `reset` button again. You should see a lot of debug output logged in the terminal window.
+
+
+
+## 6. Troubleshooting
+
+- If after flashing Meshtastic, the Xiao is bootlooped, look at the serial output (you can see this by running `meshtastic --noproto` with the device connected to your computer via USB).
+
+ - If you see that the SX1262 init result was -2, this likely indicates a wiring problem; double check your wiring and pin mapping in `variant.h`.
+
+ - If you see an error mentioning tinyFS, this may mean you need to reformat the Xiao's storage:
+
+ 1. Double press the `reset` button to put the Xiao in bootloader mode.
+
+ 2. In a terminal window, navigate to the Meshtastic firmware repo's root directory, and from there to `variants/xiao_ble`.
+
+ 3. Run the following command: `cp xiao-ble-internal-format.uf2 /Volumes/XIAO-BOOT`
+
+ 4. The Xiao's red LED will flash briefly as the filesystem format firmware is copied.
+
+ 5. Run the following command: `meshtastic --noproto`
+
+ 6. In the output of the above command, you should see a message saying "Formatting...done".
+
+ 7. To flash Meshtastic again, repeat the steps in section 5 above.
+
+ - If you don't see any specific error message, but the boot process is stuck or not proceeding as expected, this might also mean there is a conflict in `variant.h`. If you have made any changes to the pin mapping, ensure they do not result in a conflict. If all else fails, try reverting your changes and using the known-good configuration included here.
+
+ - The above might also mean something is wired incorrectly. Try reverting to one of the known-good example wirings in section 4.
+
+- If the E22 gets hot to the touch:
+ - The power amplifier is likely running continually. Disconnect it and the Xiao from power immediately, and double check wiring and pin mapping. In my experimentation this occurred in cases where TXEN was inadvertenly high (usually due to a pin mapping conflict).
+
+
+
+## 7. Notes
+
+- There are several anecdotal recommendations regarding the Tx power the E22's internal SX1262 should be set to in order to achieve the advertised output of 30 dBm, ranging from 4 (per this article in the RadioLib github repo) to 22 (per this conversation from the Meshtastic Discord). When paired with the Xiao BLE in the configurations described above, I observed that the output is at its maximum when Tx power is set to 22.
+
+- To achieve its full output, the E22 should have a bypass capacitor from its 5V supply to ground. 100 µF works well.
+
+- The E22 will happily run on voltages lower than 5V, but the full output power will not be realized. For example, with a fully charged LiPo at 4.2V, Tx power appears to max out around 26-27 dBm.
+
+
+
+## 8. Testing Methodology
+
+During what became a fairly long trial-and-error process, I did a lot of careful testing of Tx power and Rx sensitivity. My methodology in these tests was as follows:
+
+- All tests were conducted between two nodes:
+
+ 1. The Xiao BLE + E22 coupled with an Abracon ARRKP4065-S915A ceramic patch antenna
+
+ 2. A RAK 5005/4631 coupled with a Laird MA9-5N antenna via a 4" U.FL to Type N pigtail.
+
+ - No other nodes were powered up onsite or nearby.
+
+
+
+- Each node and its antenna was kept in exactly the same position and orientation throughout testing.
+
+- Other environmental factors (e.g. the location and resting position of my body in the room while testing) were controlled as carefully as possible.
+
+- Each test comprised at least five (and often ten) runs, after which the results were averaged.
+
+- All testing was done by sending single-character messages between nodes and observing the received RSSI reported in the message acknowledgement. Messages were sent one by one, waiting for each to be acknowledged or time out before sending the next.
+
+- The E22's Tx power was observed by sending messages from the RAK to the Xiao BLE + E22 and recording the received RSSI.
+
+- The opposite was done to observe the E22's Rx sensitivity: messages were sent from the Xiao BLE + E22 to the RAK, and the received RSSI was recorded.
+
+While this cannot match the level of accuracy achievable with actual test equipment in a lab setting, it was nonetheless sufficient to demonstrate the (sometimes very large) differences in Tx power and Rx sensitivity between various configurations.
diff --git a/variants/xiao_ble/platformio.ini b/variants/xiao_ble/platformio.ini
new file mode 100644
index 000000000..c52e2c644
--- /dev/null
+++ b/variants/xiao_ble/platformio.ini
@@ -0,0 +1,13 @@
+; Seeed Xiao BLE: https://www.digikey.com/en/products/detail/seeed-technology-co-ltd/102010448/16652893
+[env:xiao_ble]
+extends = nrf52840_base
+board = xiao_ble_sense
+board_level = extra
+build_flags = ${nrf52840_base.build_flags} -Ivariants/xiao_ble -Dxiao_ble -D EBYTE_E22
+ -L "${platformio.libdeps_dir}/${this.__env__}/BSEC2 Software Library/src/cortex-m4/fpv4-sp-d16-hard"
+build_src_filter = ${nrf52_base.build_src_filter} +<../variants/xiao_ble>
+lib_deps =
+ ${nrf52840_base.lib_deps}
+debug_tool = jlink
+; If not set we will default to uploading over serial (first it forces bootloader entry by talking 1200bps to cdcacm)
+;upload_protocol = jlink
\ No newline at end of file
diff --git a/variants/xiao_ble/variant.cpp b/variants/xiao_ble/variant.cpp
new file mode 100644
index 000000000..2c6c3e539
--- /dev/null
+++ b/variants/xiao_ble/variant.cpp
@@ -0,0 +1,55 @@
+#include "variant.h"
+#include "nrf.h"
+#include "wiring_constants.h"
+#include "wiring_digital.h"
+
+const uint32_t g_ADigitalPinMap[] = {
+ // D0 .. D13
+ 2, // D0 is P0.02 (A0)
+ 3, // D1 is P0.03 (A1)
+ 28, // D2 is P0.28 (A2)
+ 29, // D3 is P0.29 (A3)
+ 4, // D4 is P0.04 (A4,SDA)
+ 5, // D5 is P0.05 (A5,SCL)
+ 43, // D6 is P1.11 (TX)
+ 44, // D7 is P1.12 (RX)
+ 45, // D8 is P1.13 (SCK)
+ 46, // D9 is P1.14 (MISO)
+ 47, // D10 is P1.15 (MOSI)
+
+ // LEDs
+ 26, // D11 is P0.26 (LED RED)
+ 6, // D12 is P0.06 (LED BLUE)
+ 30, // D13 is P0.30 (LED GREEN)
+ 14, // D14 is P0.14 (READ_BAT)
+
+ // LSM6DS3TR
+ 40, // D15 is P1.08 (6D_PWR)
+ 27, // D16 is P0.27 (6D_I2C_SCL)
+ 7, // D17 is P0.07 (6D_I2C_SDA)
+ 11, // D18 is P0.11 (6D_INT1)
+
+ // MIC
+ 42, // 17,//42, // D19 is P1.10 (MIC_PWR)
+ 32, // 26,//32, // D20 is P1.00 (PDM_CLK)
+ 16, // 25,//16, // D21 is P0.16 (PDM_DATA)
+
+ // BQ25100
+ 13, // D22 is P0.13 (HICHG)
+ 17, // D23 is P0.17 (~CHG)
+
+ //
+ 21, // D24 is P0.21 (QSPI_SCK)
+ 25, // D25 is P0.25 (QSPI_CSN)
+ 20, // D26 is P0.20 (QSPI_SIO_0 DI)
+ 24, // D27 is P0.24 (QSPI_SIO_1 DO)
+ 22, // D28 is P0.22 (QSPI_SIO_2 WP)
+ 23, // D29 is P0.23 (QSPI_SIO_3 HOLD)
+
+ // NFC
+ 9, // D30 is P0.09 (NFC1)
+ 10, // D31 is P0.10 (NFC2)
+
+ // VBAT
+ 31, // D32 is P0.10 (VBAT)
+};
\ No newline at end of file
diff --git a/variants/xiao_ble/variant.h b/variants/xiao_ble/variant.h
new file mode 100644
index 000000000..ae7d37458
--- /dev/null
+++ b/variants/xiao_ble/variant.h
@@ -0,0 +1,201 @@
+#ifndef _SEEED_XIAO_NRF52840_SENSE_H_
+#define _SEEED_XIAO_NRF52840_SENSE_H_
+
+/** Master clock frequency */
+#define VARIANT_MCK (64000000ul)
+
+#define USE_LFXO // Board uses 32khz crystal for LF
+//#define USE_LFRC // Board uses RC for LF
+
+/*----------------------------------------------------------------------------
+ * Headers
+ *----------------------------------------------------------------------------*/
+
+#include "WVariant.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+#define PINS_COUNT (33)
+#define NUM_DIGITAL_PINS (33)
+#define NUM_ANALOG_INPUTS (8) // A6 is used for battery, A7 is analog reference
+#define NUM_ANALOG_OUTPUTS (0)
+
+// LEDs
+
+#define LED_RED 11
+#define LED_BLUE 12
+#define LED_GREEN 13
+
+#define PIN_LED1 LED_GREEN
+#define PIN_LED2 LED_BLUE
+#define PIN_LED3 LED_RED
+
+#define PIN_LED PIN_LED1
+#define LED_PWR (PINS_COUNT)
+
+#define LED_BUILTIN PIN_LED
+
+#define LED_STATE_ON 1 // State when LED is lit
+
+/*
+ * Buttons
+ */
+#define PIN_BUTTON1 (PINS_COUNT)
+
+// Digital PINs
+#define D0 (0ul)
+#define D1 (1ul)
+#define D2 (2ul)
+#define D3 (3ul)
+#define D4 (4ul)
+#define D5 (5ul)
+#define D6 (6ul)
+#define D7 (7ul)
+#define D8 (8ul)
+#define D9 (9ul)
+#define D10 (10ul)
+
+/*
+ * Analog pins
+ */
+#define PIN_A0 (0)
+#define PIN_A1 (1)
+#define PIN_A2 (2)
+#define PIN_A3 (3)
+#define PIN_A4 (4)
+#define PIN_A5 (5)
+#define PIN_VBAT (32)
+#define VBAT_ENABLE (14)
+
+static const uint8_t A0 = PIN_A0;
+static const uint8_t A1 = PIN_A1;
+static const uint8_t A2 = PIN_A2;
+static const uint8_t A3 = PIN_A3;
+static const uint8_t A4 = PIN_A4;
+static const uint8_t A5 = PIN_A5;
+#define ADC_RESOLUTION 12
+
+// Other pins
+#define PIN_NFC1 (30)
+#define PIN_NFC2 (31)
+
+/*
+ * Serial interfaces
+ */
+#define PIN_SERIAL1_RX (-1) // (7)
+#define PIN_SERIAL1_TX (-1) // (6)
+
+#define PIN_SERIAL2_RX (-1)
+#define PIN_SERIAL2_TX (-1)
+
+/*
+ * SPI Interfaces
+ */
+#define SPI_INTERFACES_COUNT 1
+
+#define PIN_SPI_MISO (9)
+#define PIN_SPI_MOSI (10)
+#define PIN_SPI_SCK (8)
+
+static const uint8_t SS = D0;
+static const uint8_t MOSI = PIN_SPI_MOSI;
+static const uint8_t MISO = PIN_SPI_MISO;
+static const uint8_t SCK = PIN_SPI_SCK;
+
+// supported modules list
+#define USE_SX1262
+
+// common pinouts for SX126X modules
+#define SX126X_CS D0
+#define SX126X_DIO1 D1
+#define SX126X_BUSY D2
+#define SX126X_RESET D3
+
+// ----------------------------------------------------------------
+
+// E22 Tx/Rx control options:
+
+// 1. Let the E22 control Tx and Rx automagically via DIO2.
+
+// * The E22's TXEN and DIO2 pins are connected to each other, but not to the MCU.
+// * The E22's RXEN pin *is* connected to the MCU.
+// * E22_TXEN_CONNECTED_TO_DIO2 is defined so the logic in SX126XInterface.cpp handles this configuration correctly.
+
+#define SX126X_TXEN RADIOLIB_NC
+#define SX126X_RXEN D7
+#define E22_TXEN_CONNECTED_TO_DIO2
+
+// ------------------------------ OR ------------------------------
+
+// 2. Control Tx and Rx manually.
+
+// * The E22's TXEN and RXEN pins are both connected to the MCU.
+
+// #define SX126X_TXEN D6
+// #define SX126X_RXEN D7
+
+// ----------------------------------------------------------------
+
+#ifdef EBYTE_E22
+// Internally the TTGO module hooks the SX126x-DIO2 in to control the TX/RX switch
+// (which is the default for the sx1262interface code)
+#define SX126X_E22
+#endif
+
+/*
+ * Wire Interfaces
+ */
+#define WIRE_INTERFACES_COUNT 1 // 2
+
+#define PIN_WIRE_SDA (4)
+#define PIN_WIRE_SCL (5)
+
+static const uint8_t SDA = PIN_WIRE_SDA;
+static const uint8_t SCL = PIN_WIRE_SCL;
+
+#define PIN_LSM6DS3TR_C_POWER (15)
+#define PIN_LSM6DS3TR_C_INT1 (18)
+
+// PDM Interfaces
+// ---------------
+#define PIN_PDM_PWR (19)
+#define PIN_PDM_CLK (20)
+#define PIN_PDM_DIN (21)
+
+// QSPI Pins
+#define PIN_QSPI_SCK (24)
+#define PIN_QSPI_CS (25)
+#define PIN_QSPI_IO0 (26)
+#define PIN_QSPI_IO1 (27)
+#define PIN_QSPI_IO2 (28)
+#define PIN_QSPI_IO3 (29)
+
+// On-board QSPI Flash
+#define EXTERNAL_FLASH_DEVICES P25Q16H
+#define EXTERNAL_FLASH_USE_QSPI
+
+// Battery
+
+#define BAT_READ \
+ 14 // P0_14 = 14 Reads battery voltage from divider on signal board. (PIN_VBAT is reading voltage divider on XIAO and is
+ // program pin 32 / or P0.31)
+#define CHARGE_LED 23 // P0_17 = 17 D23 YELLOW CHARGE LED
+#define HICHG 22 // P0_13 = 13 D22 Charge-select pin for Lipo for 100 mA instead of default 50mA charge
+
+// The battery sense is hooked to pin A0 (5)
+#define BATTERY_PIN PIN_VBAT // PIN_A0
+
+// ratio of voltage divider = 3.0 (R17=1M, R18=510k)
+#define ADC_MULTIPLIER 3 // 3.0 + a bit for being optimistic
+
+#ifdef __cplusplus
+}
+#endif
+
+/*----------------------------------------------------------------------------
+ * Arduino objects - C++ only
+ *----------------------------------------------------------------------------*/
+
+#endif
\ No newline at end of file
diff --git a/variants/xiao_ble/xiao-ble-internal-format.uf2 b/variants/xiao_ble/xiao-ble-internal-format.uf2
new file mode 100644
index 000000000..59de2c68a
Binary files /dev/null and b/variants/xiao_ble/xiao-ble-internal-format.uf2 differ
diff --git a/variants/xiao_ble/xiao_ble.sh b/variants/xiao_ble/xiao_ble.sh
new file mode 100755
index 000000000..2f3cc5390
--- /dev/null
+++ b/variants/xiao_ble/xiao_ble.sh
@@ -0,0 +1,15 @@
+#!/bin/bash
+# adapted from the script linked in this very helpful article: https://enzolombardi.net/low-power-bluetooth-advertising-with-xiao-ble-and-platformio-e8e7d0da80d2
+
+# source: https://gist.githubusercontent.com/turing-complete-labs/b3105ee653782183c54b4fdbe18f411f/raw/d86779ba7702775d3b79781da63d85442acd9de6/xiao_ble.sh
+# download the core for arduino from seeedstudio. Softdevice 7.3.0, linker and variants folder are what we need
+curl https://files.seeedstudio.com/arduino/core/nRF52840/Arduino_core_nRF52840.tar.bz2 -o arduino.core.1.0.0.tar.bz2
+tar -xjf arduino.core.1.0.0.tar.bz2
+rm arduino.core.1.0.0.tar.bz2
+
+# copy the needed files
+cp 1.0.0/cores/nRF5/linker/nrf52840_s140_v7.ld ~/.platformio/packages/framework-arduinoadafruitnrf52/cores/nRF5/linker
+cp -r 1.0.0/cores/nRF5/nordic/softdevice/s140_nrf52_7.3.0_API ~/.platformio/packages/framework-arduinoadafruitnrf52/cores/nRF5/nordic/softdevice
+
+rm -rf 1.0.0
+echo done!
diff --git a/variants/xiao_ble/xiao_nrf52840_ble_bootloader-0.7.0-22-g277a0c8_s140_7.3.0.zip b/variants/xiao_ble/xiao_nrf52840_ble_bootloader-0.7.0-22-g277a0c8_s140_7.3.0.zip
new file mode 100644
index 000000000..40b966baf
Binary files /dev/null and b/variants/xiao_ble/xiao_nrf52840_ble_bootloader-0.7.0-22-g277a0c8_s140_7.3.0.zip differ
diff --git a/version.properties b/version.properties
index 5cc440cdd..76538d46b 100644
--- a/version.properties
+++ b/version.properties
@@ -1,4 +1,4 @@
[VERSION]
major = 2
minor = 1
-build = 18
+build = 20