diff --git a/arch/portduino/portduino.ini b/arch/portduino/portduino.ini
index 07151c4a3..53f06c9f3 100644
--- a/arch/portduino/portduino.ini
+++ b/arch/portduino/portduino.ini
@@ -1,6 +1,6 @@
; The Portduino based sim environment on top of any host OS, all hardware will be simulated
[portduino_base]
-platform = https://github.com/meshtastic/platform-native.git#c95616208ffff4c8a36d48df810a3f072cce3521
+platform = https://github.com/meshtastic/platform-native.git#6fb39b6f94ece9c042141edb4afb91aca94dcaab
framework = arduino
build_src_filter =
diff --git a/bin/config-dist.yaml b/bin/config-dist.yaml
index 5a8e658cb..f729f1ac7 100644
--- a/bin/config-dist.yaml
+++ b/bin/config-dist.yaml
@@ -101,18 +101,20 @@ Display:
# Height: 240
Touchscreen:
+### Note, at least for now, the touchscreen must have a CS pin defined, even if you let Linux manage the CS switching.
+
# Module: STMPE610
# CS: 7
# IRQ: 24
-# Module: XPT2046
+# Module: XPT2046 # Waveshare 2.8inch
# CS: 7
# IRQ: 17
### Configure device for direct keyboard input
Input:
-# KeyboardDevice: /dev/input/event0
+# KeyboardDevice: /dev/input/by-id/usb-_Raspberry_Pi_Internal_Keyboard-event-kbd
###
diff --git a/boards/CDEBYTE_EoRa-S3.json b/boards/CDEBYTE_EoRa-S3.json
new file mode 100644
index 000000000..9ecee3c9f
--- /dev/null
+++ b/boards/CDEBYTE_EoRa-S3.json
@@ -0,0 +1,38 @@
+{
+ "build": {
+ "arduino": {
+ "ldscript": "esp32s3_out.ld"
+ },
+ "core": "esp32",
+ "extra_flags": [
+ "-D CDEBYTE_EORA_S3",
+ "-D ARDUINO_USB_CDC_ON_BOOT=1",
+ "-D ARDUINO_USB_MODE=0",
+ "-D ARDUINO_RUNNING_CORE=1",
+ "-D ARDUINO_EVENT_RUNNING_CORE=1",
+ "-D BOARD_HAS_PSRAM"
+ ],
+ "f_cpu": "240000000L",
+ "f_flash": "80000000L",
+ "flash_mode": "dio",
+ "hwids": [["0x303A", "0x1001"]],
+ "mcu": "esp32s3",
+ "variant": "CDEBYTE_EoRa-S3"
+ },
+ "connectivity": ["wifi"],
+ "debug": {
+ "openocd_target": "esp32s3.cfg"
+ },
+ "frameworks": ["arduino", "espidf"],
+ "name": "CDEBYTE EoRa-S3",
+ "upload": {
+ "flash_size": "4MB",
+ "maximum_ram_size": 327680,
+ "maximum_size": 4194304,
+ "wait_for_upload_port": true,
+ "require_upload_port": true,
+ "speed": 921600
+ },
+ "url": "https://www.cdebyte.com/Module-Testkits-EoRaPI",
+ "vendor": "CDEBYTE"
+}
diff --git a/boards/tbeam-s3-core.json b/boards/tbeam-s3-core.json
index 8d2c3eed6..4c82a2789 100644
--- a/boards/tbeam-s3-core.json
+++ b/boards/tbeam-s3-core.json
@@ -7,7 +7,6 @@
"extra_flags": [
"-DBOARD_HAS_PSRAM",
"-DLILYGO_TBEAM_S3_CORE",
- "-DARDUINO_USB_CDC_ON_BOOT=1",
"-DARDUINO_USB_MODE=1",
"-DARDUINO_RUNNING_CORE=1",
"-DARDUINO_EVENT_RUNNING_CORE=1"
diff --git a/protobufs b/protobufs
index f92900c5f..ecf105f66 160000
--- a/protobufs
+++ b/protobufs
@@ -1 +1 @@
-Subproject commit f92900c5f884b04388fb7abf61d4df66783015e4
+Subproject commit ecf105f66d182531423b73f4408c53701313c4eb
diff --git a/src/PowerFSM.cpp b/src/PowerFSM.cpp
index ac48e664c..4f42b36b5 100644
--- a/src/PowerFSM.cpp
+++ b/src/PowerFSM.cpp
@@ -185,10 +185,12 @@ static void powerEnter()
screen->setOn(true);
setBluetoothEnable(true);
// within enter() the function getState() returns the state we came from
- if (strcmp(powerFSM.getState()->name, "BOOT") != 0 && strcmp(powerFSM.getState()->name, "POWER") != 0 &&
+
+ // Mothballed: print change of power-state to device screen
+ /* if (strcmp(powerFSM.getState()->name, "BOOT") != 0 && strcmp(powerFSM.getState()->name, "POWER") != 0 &&
strcmp(powerFSM.getState()->name, "DARK") != 0) {
screen->print("Powered...\n");
- }
+ }*/
}
}
@@ -205,8 +207,10 @@ static void powerExit()
{
screen->setOn(true);
setBluetoothEnable(true);
- if (!isPowered())
- screen->print("Unpowered...\n");
+
+ // Mothballed: print change of power-state to device screen
+ /*if (!isPowered())
+ screen->print("Unpowered...\n");*/
}
static void onEnter()
diff --git a/src/RedirectablePrint.cpp b/src/RedirectablePrint.cpp
index 16906e2e0..e09e5fe30 100644
--- a/src/RedirectablePrint.cpp
+++ b/src/RedirectablePrint.cpp
@@ -182,11 +182,11 @@ size_t RedirectablePrint::log(const char *logLevel, const char *format, ...)
void RedirectablePrint::hexDump(const char *logLevel, unsigned char *buf, uint16_t len)
{
const char alphabet[17] = "0123456789abcdef";
- log(logLevel, " +------------------------------------------------+ +----------------+\n");
- log(logLevel, " |.0 .1 .2 .3 .4 .5 .6 .7 .8 .9 .a .b .c .d .e .f | | ASCII |\n");
+ log(logLevel, " +------------------------------------------------+ +----------------+\n");
+ log(logLevel, " |.0 .1 .2 .3 .4 .5 .6 .7 .8 .9 .a .b .c .d .e .f | | ASCII |\n");
for (uint16_t i = 0; i < len; i += 16) {
if (i % 128 == 0)
- log(logLevel, " +------------------------------------------------+ +----------------+\n");
+ log(logLevel, " +------------------------------------------------+ +----------------+\n");
char s[] = "| | | |\n";
uint8_t ix = 1, iy = 52;
for (uint8_t j = 0; j < 16; j++) {
@@ -208,7 +208,7 @@ void RedirectablePrint::hexDump(const char *logLevel, unsigned char *buf, uint16
log(logLevel, ".");
log(logLevel, s);
}
- log(logLevel, " +------------------------------------------------+ +----------------+\n");
+ log(logLevel, " +------------------------------------------------+ +----------------+\n");
}
std::string RedirectablePrint::mt_sprintf(const std::string fmt_str, ...)
diff --git a/src/configuration.h b/src/configuration.h
index 37b67f666..701e07a32 100644
--- a/src/configuration.h
+++ b/src/configuration.h
@@ -74,6 +74,13 @@ along with this program. If not, see .
#define RTC_DATA_ATTR
#endif
+// -----------------------------------------------------------------------------
+// Regulatory overrides for producing regional builds
+// -----------------------------------------------------------------------------
+
+// Define if region should override user saved region
+// #define LORA_REGIONCODE meshtastic_Config_LoRaConfig_RegionCode_SG_923
+
// -----------------------------------------------------------------------------
// Feature toggles
// -----------------------------------------------------------------------------
diff --git a/src/gps/GPS.cpp b/src/gps/GPS.cpp
index 6a0e3e44a..0d0bfd9a2 100644
--- a/src/gps/GPS.cpp
+++ b/src/gps/GPS.cpp
@@ -7,6 +7,8 @@
#include "main.h" // pmu_found
#include "sleep.h"
+
+#include "cas.h"
#include "ubx.h"
#ifdef ARCH_PORTDUINO
@@ -51,6 +53,28 @@ void GPS::UBXChecksum(uint8_t *message, size_t length)
message[length - 1] = CK_B;
}
+// Calculate the checksum for a CAS packet
+void GPS::CASChecksum(uint8_t *message, size_t length)
+{
+ uint32_t cksum = ((uint32_t)message[5] << 24); // Message ID
+ cksum += ((uint32_t)message[4]) << 16; // Class
+ cksum += message[2]; // Payload Len
+
+ // Iterate over the payload as a series of uint32_t's and
+ // accumulate the cksum
+ uint32_t *payload = (uint32_t *)(message + 6);
+ for (size_t i = 0; i < (length - 10) / 4; i++) {
+ uint32_t p = payload[i];
+ cksum += p;
+ }
+
+ // Place the checksum values in the message
+ message[length - 4] = (cksum & 0xFF);
+ message[length - 3] = (cksum & (0xFF << 8)) >> 8;
+ message[length - 2] = (cksum & (0xFF << 16)) >> 16;
+ message[length - 1] = (cksum & (0xFF << 24)) >> 24;
+}
+
// Function to create a ublox packet for editing in memory
uint8_t GPS::makeUBXPacket(uint8_t class_id, uint8_t msg_id, uint8_t payload_size, const uint8_t *msg)
{
@@ -72,6 +96,41 @@ uint8_t GPS::makeUBXPacket(uint8_t class_id, uint8_t msg_id, uint8_t payload_siz
return (payload_size + 8);
}
+// Function to create a CAS packet for editing in memory
+uint8_t GPS::makeCASPacket(uint8_t class_id, uint8_t msg_id, uint8_t payload_size, const uint8_t *msg)
+{
+ // General CAS structure
+ // | H1 | H2 | payload_len | cls | msg | Payload ... | Checksum |
+ // Size: | 1 | 1 | 2 | 1 | 1 | payload_len | 4 |
+ // Pos: | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 ... | 6 + payload_len ... |
+ // |------|------|-------------|------|------|------|--------------|---------------------------|
+ // | 0xBA | 0xCE | 0xXX | 0xXX | 0xXX | 0xXX | 0xXX | 0xXX ... | 0xXX | 0xXX | 0xXX | 0xXX |
+
+ // Construct the CAS packet
+ UBXscratch[0] = 0xBA; // header 1 (0xBA)
+ UBXscratch[1] = 0xCE; // header 2 (0xCE)
+ UBXscratch[2] = payload_size; // length 1
+ UBXscratch[3] = 0; // length 2
+ UBXscratch[4] = class_id; // class
+ UBXscratch[5] = msg_id; // id
+
+ UBXscratch[6 + payload_size] = 0x00; // Checksum
+ UBXscratch[7 + payload_size] = 0x00;
+ UBXscratch[8 + payload_size] = 0x00;
+ UBXscratch[9 + payload_size] = 0x00;
+
+ for (int i = 0; i < payload_size; i++) {
+ UBXscratch[6 + i] = pgm_read_byte(&msg[i]);
+ }
+ CASChecksum(UBXscratch, (payload_size + 10));
+
+#if defined(GPS_DEBUG) && defined(DEBUG_PORT)
+ LOG_DEBUG("Constructed CAS packet: \n");
+ DEBUG_PORT.hexDump(MESHTASTIC_LOG_LEVEL_DEBUG, UBXscratch, payload_size + 10);
+#endif
+ return (payload_size + 10);
+}
+
GPS_RESPONSE GPS::getACK(const char *message, uint32_t waitMillis)
{
uint8_t buffer[768] = {0};
@@ -81,6 +140,7 @@ GPS_RESPONSE GPS::getACK(const char *message, uint32_t waitMillis)
while (millis() < startTimeout) {
if (_serial_gps->available()) {
b = _serial_gps->read();
+
#ifdef GPS_DEBUG
LOG_DEBUG("%02X", (char *)buffer);
#endif
@@ -104,6 +164,67 @@ GPS_RESPONSE GPS::getACK(const char *message, uint32_t waitMillis)
return GNSS_RESPONSE_NONE;
}
+GPS_RESPONSE GPS::getACKCas(uint8_t class_id, uint8_t msg_id, uint32_t waitMillis)
+{
+ uint32_t startTime = millis();
+ uint8_t buffer[CAS_ACK_NACK_MSG_SIZE] = {0};
+ uint8_t bufferPos = 0;
+
+ // CAS-ACK-(N)ACK structure
+ // | H1 | H2 | Payload Len | cls | msg | Payload | Checksum (4) |
+ // | | | | | | Cls | Msg | Reserved | |
+ // |------|------|-------------|------|------|------|------|-------------|---------------------------|
+ // ACK-NACK| 0xBA | 0xCE | 0x04 | 0x00 | 0x05 | 0x00 | 0xXX | 0xXX | 0x00 | 0x00 | 0xXX | 0xXX | 0xXX | 0xXX |
+ // ACK-ACK | 0xBA | 0xCE | 0x04 | 0x00 | 0x05 | 0x01 | 0xXX | 0xXX | 0x00 | 0x00 | 0xXX | 0xXX | 0xXX | 0xXX |
+
+ while (millis() - startTime < waitMillis) {
+ if (_serial_gps->available()) {
+ buffer[bufferPos++] = _serial_gps->read();
+
+ // keep looking at the first two bytes of buffer until
+ // we have found the CAS frame header (0xBA, 0xCE), if not
+ // keep reading bytes until we find a frame header or we run
+ // out of time.
+ if ((bufferPos == 2) && !(buffer[0] == 0xBA && buffer[1] == 0xCE)) {
+ buffer[0] = buffer[1];
+ buffer[1] = 0;
+ bufferPos = 1;
+ }
+ }
+
+ // we have read all the bytes required for the Ack/Nack (14-bytes)
+ // and we must have found a frame to get this far
+ if (bufferPos == sizeof(buffer) - 1) {
+ uint8_t msg_cls = buffer[4]; // message class should be 0x05
+ uint8_t msg_msg_id = buffer[5]; // message id should be 0x00 or 0x01
+ uint8_t payload_cls = buffer[6]; // payload class id
+ uint8_t payload_msg = buffer[7]; // payload message id
+
+ // Check for an ACK-ACK for the specified class and message id
+ if ((msg_cls == 0x05) && (msg_msg_id == 0x01) && payload_cls == class_id && payload_msg == msg_id) {
+#ifdef GPS_DEBUG
+ LOG_INFO("Got ACK for class %02X message %02X in %d millis.\n", class_id, msg_id, millis() - startTime);
+#endif
+ return GNSS_RESPONSE_OK;
+ }
+
+ // Check for an ACK-NACK for the specified class and message id
+ if ((msg_cls == 0x05) && (msg_msg_id == 0x00) && payload_cls == class_id && payload_msg == msg_id) {
+#ifdef GPS_DEBUG
+ LOG_WARN("Got NACK for class %02X message %02X in %d millis.\n", class_id, msg_id, millis() - startTime);
+#endif
+ return GNSS_RESPONSE_NAK;
+ }
+
+ // This isn't the frame we are looking for, clear the buffer
+ // and try again until we run out of time.
+ memset(buffer, 0x0, sizeof(buffer));
+ bufferPos = 0;
+ }
+ }
+ return GNSS_RESPONSE_NONE;
+}
+
GPS_RESPONSE GPS::getACK(uint8_t class_id, uint8_t msg_id, uint32_t waitMillis)
{
uint8_t b;
@@ -313,6 +434,33 @@ bool GPS::setup()
// Switch to Fitness Mode, for running and walking purpose with low speed (<5 m/s)
_serial_gps->write("$PMTK886,1*29\r\n");
delay(250);
+ } else if (gnssModel == GNSS_MODEL_ATGM336H) {
+ // Set the intial configuration of the device - these _should_ work for most AT6558 devices
+ msglen = makeCASPacket(0x06, 0x07, sizeof(_message_CAS_CFG_NAVX_CONF), _message_CAS_CFG_NAVX_CONF);
+ _serial_gps->write(UBXscratch, msglen);
+ if (getACKCas(0x06, 0x07, 250) != GNSS_RESPONSE_OK) {
+ LOG_WARN("ATGM336H - Could not set Configuration");
+ }
+
+ // Set the update frequence to 1Hz
+ msglen = makeCASPacket(0x06, 0x04, sizeof(_message_CAS_CFG_RATE_1HZ), _message_CAS_CFG_RATE_1HZ);
+ _serial_gps->write(UBXscratch, msglen);
+ if (getACKCas(0x06, 0x04, 250) != GNSS_RESPONSE_OK) {
+ LOG_WARN("ATGM336H - Could not set Update Frequency");
+ }
+
+ // Set the NEMA output messages
+ // Ask for only RMC and GGA
+ uint8_t fields[] = {CAS_NEMA_RMC, CAS_NEMA_GGA};
+ for (int i = 0; i < sizeof(fields); i++) {
+ // Construct a CAS-CFG-MSG packet
+ uint8_t cas_cfg_msg_packet[] = {0x4e, fields[i], 0x01, 0x00};
+ msglen = makeCASPacket(0x06, 0x01, sizeof(cas_cfg_msg_packet), cas_cfg_msg_packet);
+ _serial_gps->write(UBXscratch, msglen);
+ if (getACKCas(0x06, 0x01, 250) != GNSS_RESPONSE_OK) {
+ LOG_WARN("ATGM336H - Could not enable NMEA MSG: %d\n", fields[i]);
+ }
+ }
} else if (gnssModel == GNSS_MODEL_UC6580) {
// The Unicore UC6580 can use a lot of sat systems, enable it to
// use GPS L1 & L5 + BDS B1I & B2a + GLONASS L1 + GALILEO E1 & E5a + SBAS
@@ -948,10 +1096,18 @@ GnssModel_t GPS::probe(int serialSpeed)
uint8_t buffer[768] = {0};
delay(100);
- // Close all NMEA sentences , Only valid for L76K MTK platform
+ // Close all NMEA sentences, valid for L76K, ATGM336H (and likely other AT6558 devices)
_serial_gps->write("$PCAS03,0,0,0,0,0,0,0,0,0,0,,,0,0*02\r\n");
delay(20);
+ // Get version information
+ clearBuffer();
+ _serial_gps->write("$PCAS06,1*1A\r\n");
+ if (getACK("$GPTXT,01,01,02,HW=ATGM336H", 500) == GNSS_RESPONSE_OK) {
+ LOG_INFO("ATGM336H GNSS init succeeded, using ATGM336H Module\n");
+ return GNSS_MODEL_ATGM336H;
+ }
+
// Get version information
clearBuffer();
_serial_gps->write("$PCAS06,0*1B\r\n");
@@ -1216,6 +1372,11 @@ bool GPS::factoryReset()
LOG_INFO("GNSS Factory Reset via PCAS10,3\n");
_serial_gps->write("$PCAS10,3*1F\r\n");
delay(100);
+ } else if (gnssModel == GNSS_MODEL_ATGM336H) {
+ LOG_INFO("Factory Reset via CAS-CFG-RST\n");
+ uint8_t msglen = makeCASPacket(0x06, 0x02, sizeof(_message_CAS_CFG_RST_FACTORY), _message_CAS_CFG_RST_FACTORY);
+ _serial_gps->write(UBXscratch, msglen);
+ delay(100);
} else {
// fire this for good measure, if we have an L76B - won't harm other devices.
_serial_gps->write("$PMTK104*37\r\n");
diff --git a/src/gps/GPS.h b/src/gps/GPS.h
index 49f27e29f..77c6c0269 100644
--- a/src/gps/GPS.h
+++ b/src/gps/GPS.h
@@ -22,7 +22,14 @@ struct uBloxGnssModelInfo {
char extension[10][30];
};
-typedef enum { GNSS_MODEL_MTK, GNSS_MODEL_UBLOX, GNSS_MODEL_UC6580, GNSS_MODEL_UNKNOWN, GNSS_MODEL_MTK_L76B } GnssModel_t;
+typedef enum {
+ GNSS_MODEL_ATGM336H,
+ GNSS_MODEL_MTK,
+ GNSS_MODEL_UBLOX,
+ GNSS_MODEL_UC6580,
+ GNSS_MODEL_UNKNOWN,
+ GNSS_MODEL_MTK_L76B
+} GnssModel_t;
typedef enum {
GNSS_RESPONSE_NONE,
@@ -133,6 +140,11 @@ class GPS : private concurrency::OSThread
static const uint8_t _message_VALSET_DISABLE_SBAS_RAM[];
static const uint8_t _message_VALSET_DISABLE_SBAS_BBR[];
+ // CASIC commands for ATGM336H
+ static const uint8_t _message_CAS_CFG_RST_FACTORY[];
+ static const uint8_t _message_CAS_CFG_NAVX_CONF[];
+ static const uint8_t _message_CAS_CFG_RATE_1HZ[];
+
meshtastic_Position p = meshtastic_Position_init_default;
GPS() : concurrency::OSThread("GPS") {}
@@ -174,6 +186,7 @@ class GPS : private concurrency::OSThread
// Create a ublox packet for editing in memory
uint8_t makeUBXPacket(uint8_t class_id, uint8_t msg_id, uint8_t payload_size, const uint8_t *msg);
+ uint8_t makeCASPacket(uint8_t class_id, uint8_t msg_id, uint8_t payload_size, const uint8_t *msg);
// scratch space for creating ublox packets
uint8_t UBXscratch[250] = {0};
@@ -184,6 +197,8 @@ class GPS : private concurrency::OSThread
GPS_RESPONSE getACK(uint8_t c, uint8_t i, uint32_t waitMillis);
GPS_RESPONSE getACK(const char *message, uint32_t waitMillis);
+ GPS_RESPONSE getACKCas(uint8_t class_id, uint8_t msg_id, uint32_t waitMillis);
+
/**
* Switch the GPS into a mode where we are actively looking for a lock, or alternatively switch GPS into a low power mode
*
@@ -243,6 +258,7 @@ class GPS : private concurrency::OSThread
// Calculate checksum
void UBXChecksum(uint8_t *message, size_t length);
+ void CASChecksum(uint8_t *message, size_t length);
/** Get how long we should stay looking for each aquisition
*/
diff --git a/src/gps/cas.h b/src/gps/cas.h
new file mode 100644
index 000000000..53d75cda9
--- /dev/null
+++ b/src/gps/cas.h
@@ -0,0 +1,63 @@
+#pragma once
+
+// CASIC binary message definitions
+// Reference: https://www.icofchina.com/d/file/xiazai/2020-09-22/20f1b42b3a11ac52089caf3603b43fb5.pdf
+// ATGM33H-5N: https://www.icofchina.com/pro/mokuai/2016-08-01/4.html
+// (https://www.icofchina.com/d/file/xiazai/2016-12-05/b5c57074f4b1fcc62ba8c7868548d18a.pdf)
+
+// NEMA (Class ID - 0x4e) message IDs
+#define CAS_NEMA_GGA 0x00
+#define CAS_NEMA_GLL 0x01
+#define CAS_NEMA_GSA 0x02
+#define CAS_NEMA_GSV 0x03
+#define CAS_NEMA_RMC 0x04
+#define CAS_NEMA_VTG 0x05
+#define CAS_NEMA_GST 0x07
+#define CAS_NEMA_ZDA 0x08
+#define CAS_NEMA_DHV 0x0D
+
+// Size of a CAS-ACK-(N)ACK message (14 bytes)
+#define CAS_ACK_NACK_MSG_SIZE 0x0E
+
+// CFG-RST (0x06, 0x02)
+// Factory reset
+const uint8_t GPS::_message_CAS_CFG_RST_FACTORY[] = {
+ 0xFF, 0x03, // Fields to clear
+ 0x01, // Reset Mode: Controlled Software reset
+ 0x03 // Startup Mode: Factory
+};
+
+// CFG_RATE (0x06, 0x01)
+// 1HZ update rate, this should always be the case after
+// factory reset but update it regardless
+const uint8_t GPS::_message_CAS_CFG_RATE_1HZ[] = {
+ 0xE8, 0x03, // Update Rate: 0x03E8 = 1000ms
+ 0x00, 0x00 // Reserved
+};
+
+// CFG-NAVX (0x06, 0x07)
+// Initial ATGM33H-5N configuration, Updates for Dynamic Mode, Fix Mode, and SV system
+// Qwirk: The ATGM33H-5N-31 should only support GPS+BDS, however it will happily enable
+// and use GPS+BDS+GLONASS iff the correct CFG_NAVX command is used.
+const uint8_t GPS::_message_CAS_CFG_NAVX_CONF[] = {
+ 0x03, 0x01, 0x00, 0x00, // Update Mask: Dynamic Mode, Fix Mode, Nav Settings
+ 0x03, // Dynamic Mode: Automotive
+ 0x03, // Fix Mode: Auto 2D/3D
+ 0x00, // Min SV
+ 0x00, // Max SVs
+ 0x00, // Min CNO
+ 0x00, // Reserved1
+ 0x00, // Init 3D fix
+ 0x00, // Min Elevation
+ 0x00, // Dr Limit
+ 0x07, // Nav System: 2^0 = GPS, 2^1 = BDS 2^2 = GLONASS: 2^3
+ // 3=GPS+BDS, 7=GPS+BDS+GLONASS
+ 0x00, 0x00, // Rollover Week
+ 0x00, 0x00, 0x00, 0x00, // Fix Altitude
+ 0x00, 0x00, 0x00, 0x00, // Fix Height Error
+ 0x00, 0x00, 0x00, 0x00, // PDOP Maximum
+ 0x00, 0x00, 0x00, 0x00, // TDOP Maximum
+ 0x00, 0x00, 0x00, 0x00, // Position Accuracy Max
+ 0x00, 0x00, 0x00, 0x00, // Time Accuracy Max
+ 0x00, 0x00, 0x00, 0x00 // Static Hold Threshold
+};
\ No newline at end of file
diff --git a/src/graphics/TFTDisplay.cpp b/src/graphics/TFTDisplay.cpp
index fb64553ef..12e549424 100644
--- a/src/graphics/TFTDisplay.cpp
+++ b/src/graphics/TFTDisplay.cpp
@@ -1,6 +1,7 @@
#include "configuration.h"
#include "main.h"
#if ARCH_PORTDUINO
+#include "mesh_bus_spi.h"
#include "platform/portduino/PortduinoGlue.h"
#endif
@@ -339,7 +340,7 @@ static TFT_eSPI *tft = nullptr; // Invoke library, pins defined in User_Setup.h
class LGFX : public lgfx::LGFX_Device
{
lgfx::Panel_LCD *_panel_instance;
- lgfx::Bus_SPI _bus_instance;
+ lgfx::Mesh_Bus_SPI _bus_instance;
lgfx::ITouch *_touch_instance;
@@ -356,6 +357,7 @@ class LGFX : public lgfx::LGFX_Device
_panel_instance = new lgfx::Panel_ILI9341;
auto buscfg = _bus_instance.config();
buscfg.spi_mode = 0;
+ _bus_instance.spi_device(DisplaySPI, settingsStrings[displayspidev]);
buscfg.pin_dc = settingsMap[displayDC]; // Set SPI DC pin number (-1 = disable)
@@ -411,8 +413,7 @@ class LGFX : public lgfx::LGFX_Device
lgfx::Panel_HX8357D _panel_instance;
lgfx::Bus_SPI _bus_instance;
#if defined(USE_XPT2046)
- lgfx::ITouch *_touch_instance;
-// lgfx::Touch_XPT2046 _touch_instance;
+ lgfx::Touch_XPT2046 _touch_instance;
#endif
public:
@@ -466,8 +467,7 @@ class LGFX : public lgfx::LGFX_Device
#if defined(USE_XPT2046)
{
// Configure settings for touch control.
- _touch_instance = new lgfx::Touch_XPT2046;
- auto touch_cfg = _touch_instance->config();
+ auto touch_cfg = _touch_instance.config();
touch_cfg.pin_cs = TOUCH_CS;
touch_cfg.x_min = 0;
@@ -478,8 +478,8 @@ class LGFX : public lgfx::LGFX_Device
touch_cfg.bus_shared = true;
touch_cfg.offset_rotation = 1;
- _touch_instance->config(touch_cfg);
- //_panel_instance->setTouch(_touch_instance);
+ _touch_instance.config(touch_cfg);
+ _panel_instance.setTouch(&_touch_instance);
}
#endif
setPanel(&_panel_instance);
@@ -496,6 +496,11 @@ static LGFX *tft = nullptr;
#include "TFTDisplay.h"
#include
+#ifdef UNPHONE
+#include "unPhone.h"
+extern unPhone unphone;
+#endif
+
TFTDisplay::TFTDisplay(uint8_t address, int sda, int scl, OLEDDISPLAY_GEOMETRY geometry, HW_I2C i2cBus)
{
LOG_DEBUG("TFTDisplay!\n");
@@ -576,11 +581,7 @@ void TFTDisplay::sendCommand(uint8_t com)
digitalWrite(VTFT_CTRL, LOW);
#endif
#ifdef UNPHONE
- Wire.beginTransmission(0x26);
- Wire.write(0x02);
- Wire.write(0x04); // Backlight on
- Wire.write(0x22); // G&B LEDs off
- Wire.endTransmission();
+ unphone.backlight(true); // using unPhone library
#endif
#ifdef RAK14014
#elif !defined(M5STACK)
@@ -612,11 +613,7 @@ void TFTDisplay::sendCommand(uint8_t com)
digitalWrite(VTFT_CTRL, HIGH);
#endif
#ifdef UNPHONE
- Wire.beginTransmission(0x26);
- Wire.write(0x02);
- Wire.write(0x00); // Backlight off
- Wire.write(0x22); // G&B LEDs off
- Wire.endTransmission();
+ unphone.backlight(false); // using unPhone library
#endif
#ifdef RAK14014
#elif !defined(M5STACK)
@@ -690,11 +687,7 @@ bool TFTDisplay::connect()
digitalWrite(ST7735_BL_V05, TFT_BACKLIGHT_ON);
#endif
#ifdef UNPHONE
- Wire.beginTransmission(0x26);
- Wire.write(0x02);
- Wire.write(0x04); // Backlight on
- Wire.write(0x22); // G&B LEDs off
- Wire.endTransmission();
+ unphone.backlight(true); // using unPhone library
LOG_INFO("Power to TFT Backlight\n");
#endif
diff --git a/src/graphics/mesh_bus_spi.cpp b/src/graphics/mesh_bus_spi.cpp
new file mode 100644
index 000000000..a9536d490
--- /dev/null
+++ b/src/graphics/mesh_bus_spi.cpp
@@ -0,0 +1,188 @@
+// This code has been copied from LovyanGFX to make the SPI device selectable for touchscreens.
+// Ideally this could eventually be an inherited class from BUS_SPI,
+// but currently too many internal objects are set private.
+
+#include "configuration.h"
+#if ARCH_PORTDUINO
+#include "lgfx/v1/misc/pixelcopy.hpp"
+#include "main.h"
+#include "mesh_bus_spi.h"
+#include
+#include
+
+namespace lgfx
+{
+inline namespace v1
+{
+//----------------------------------------------------------------------------
+
+void Mesh_Bus_SPI::config(const config_t &config)
+{
+ _cfg = config;
+
+ if (_cfg.pin_dc >= 0) {
+ pinMode(_cfg.pin_dc, pin_mode_t::output);
+ gpio_hi(_cfg.pin_dc);
+ }
+}
+
+bool Mesh_Bus_SPI::init(void)
+{
+ dc_h();
+ pinMode(_cfg.pin_dc, pin_mode_t::output);
+ if (SPIName != "")
+ PrivateSPI->begin(SPIName.c_str());
+ else
+ PrivateSPI->begin();
+ return true;
+}
+
+void Mesh_Bus_SPI::release(void)
+{
+ PrivateSPI->end();
+}
+
+void Mesh_Bus_SPI::spi_device(HardwareSPI *newSPI, std::string newSPIName)
+{
+ PrivateSPI = newSPI;
+ SPIName = newSPIName;
+}
+void Mesh_Bus_SPI::beginTransaction(void)
+{
+ dc_h();
+ SPISettings setting(_cfg.freq_write, MSBFIRST, _cfg.spi_mode);
+ PrivateSPI->beginTransaction(setting);
+}
+
+void Mesh_Bus_SPI::endTransaction(void)
+{
+ PrivateSPI->endTransaction();
+ dc_h();
+}
+
+void Mesh_Bus_SPI::beginRead(void)
+{
+ PrivateSPI->endTransaction();
+ // SPISettings setting(_cfg.freq_read, BitOrder::MSBFIRST, _cfg.spi_mode, false);
+ SPISettings setting(_cfg.freq_read, MSBFIRST, _cfg.spi_mode);
+ PrivateSPI->beginTransaction(setting);
+}
+
+void Mesh_Bus_SPI::endRead(void)
+{
+ PrivateSPI->endTransaction();
+ beginTransaction();
+}
+
+void Mesh_Bus_SPI::wait(void) {}
+
+bool Mesh_Bus_SPI::busy(void) const
+{
+ return false;
+}
+
+bool Mesh_Bus_SPI::writeCommand(uint32_t data, uint_fast8_t bit_length)
+{
+ dc_l();
+ PrivateSPI->transfer((uint8_t *)&data, bit_length >> 3);
+ dc_h();
+ return true;
+}
+
+void Mesh_Bus_SPI::writeData(uint32_t data, uint_fast8_t bit_length)
+{
+ PrivateSPI->transfer((uint8_t *)&data, bit_length >> 3);
+}
+
+void Mesh_Bus_SPI::writeDataRepeat(uint32_t data, uint_fast8_t bit_length, uint32_t length)
+{
+ const uint8_t dst_bytes = bit_length >> 3;
+ uint32_t limit = (dst_bytes == 3) ? 12 : 16;
+ auto buf = _flip_buffer.getBuffer(512);
+ size_t fillpos = 0;
+ reinterpret_cast(buf)[0] = data;
+ fillpos += dst_bytes;
+ uint32_t len;
+ do {
+ len = ((length - 1) % limit) + 1;
+ if (limit <= 64)
+ limit <<= 1;
+
+ while (fillpos < len * dst_bytes) {
+ memcpy(&buf[fillpos], buf, fillpos);
+ fillpos += fillpos;
+ }
+
+ PrivateSPI->transfer(buf, len * dst_bytes);
+ } while (length -= len);
+}
+
+void Mesh_Bus_SPI::writePixels(pixelcopy_t *param, uint32_t length)
+{
+ const uint8_t dst_bytes = param->dst_bits >> 3;
+ uint32_t limit = (dst_bytes == 3) ? 12 : 16;
+ uint32_t len;
+ do {
+ len = ((length - 1) % limit) + 1;
+ if (limit <= 32)
+ limit <<= 1;
+ auto buf = _flip_buffer.getBuffer(len * dst_bytes);
+ param->fp_copy(buf, 0, len, param);
+ PrivateSPI->transfer(buf, len * dst_bytes);
+ } while (length -= len);
+}
+
+void Mesh_Bus_SPI::writeBytes(const uint8_t *data, uint32_t length, bool dc, bool use_dma)
+{
+ if (dc)
+ dc_h();
+ else
+ dc_l();
+ PrivateSPI->transfer(const_cast(data), length);
+ if (!dc)
+ dc_h();
+}
+
+uint32_t Mesh_Bus_SPI::readData(uint_fast8_t bit_length)
+{
+ uint32_t res = 0;
+ bit_length >>= 3;
+ if (!bit_length)
+ return res;
+ int idx = 0;
+ do {
+ res |= PrivateSPI->transfer(0) << idx;
+ idx += 8;
+ } while (--bit_length);
+ return res;
+}
+
+bool Mesh_Bus_SPI::readBytes(uint8_t *dst, uint32_t length, bool use_dma)
+{
+ do {
+ dst[0] = PrivateSPI->transfer(0);
+ ++dst;
+ } while (--length);
+ return true;
+}
+
+void Mesh_Bus_SPI::readPixels(void *dst, pixelcopy_t *param, uint32_t length)
+{
+ uint32_t bytes = param->src_bits >> 3;
+ uint32_t dstindex = 0;
+ uint32_t len = 4;
+ uint8_t buf[24];
+ param->src_data = buf;
+ do {
+ if (len > length)
+ len = length;
+ readBytes((uint8_t *)buf, len * bytes, true);
+ param->src_x = 0;
+ dstindex = param->fp_copy(dst, dstindex, dstindex + len, param);
+ length -= len;
+ } while (length);
+}
+
+} // namespace v1
+} // namespace lgfx
+#endif
\ No newline at end of file
diff --git a/src/graphics/mesh_bus_spi.h b/src/graphics/mesh_bus_spi.h
new file mode 100644
index 000000000..903f7ad9d
--- /dev/null
+++ b/src/graphics/mesh_bus_spi.h
@@ -0,0 +1,100 @@
+#if ARCH_PORTDUINO
+/*----------------------------------------------------------------------------/
+ Lovyan GFX - Graphics library for embedded devices.
+
+Original Source:
+ https://github.com/lovyan03/LovyanGFX/
+
+Licence:
+ [FreeBSD](https://github.com/lovyan03/LovyanGFX/blob/master/license.txt)
+
+Author:
+ [lovyan03](https://twitter.com/lovyan03)
+
+Contributors:
+ [ciniml](https://github.com/ciniml)
+ [mongonta0716](https://github.com/mongonta0716)
+ [tobozo](https://github.com/tobozo)
+/----------------------------------------------------------------------------*/
+#pragma once
+
+#include
+
+#include "lgfx/v1/Bus.hpp"
+#include "lgfx/v1/platforms/common.hpp"
+
+namespace lgfx
+{
+inline namespace v1
+{
+//----------------------------------------------------------------------------
+
+class Mesh_Bus_SPI : public IBus
+{
+ public:
+ struct config_t {
+ uint32_t freq_write = 16000000;
+ uint32_t freq_read = 8000000;
+ // bool spi_3wire = true;
+ // bool use_lock = true;
+ int16_t pin_sclk = -1;
+ int16_t pin_miso = -1;
+ int16_t pin_mosi = -1;
+ int16_t pin_dc = -1;
+ uint8_t spi_mode = 0;
+ };
+
+ const config_t &config(void) const { return _cfg; }
+
+ void config(const config_t &config);
+
+ bus_type_t busType(void) const override { return bus_type_t::bus_spi; }
+
+ bool init(void) override;
+ void release(void) override;
+ void spi_device(HardwareSPI *newSPI, std::string newSPIName);
+
+ void beginTransaction(void) override;
+ void endTransaction(void) override;
+ void wait(void) override;
+ bool busy(void) const override;
+
+ bool writeCommand(uint32_t data, uint_fast8_t bit_length) override;
+ void writeData(uint32_t data, uint_fast8_t bit_length) override;
+ void writeDataRepeat(uint32_t data, uint_fast8_t bit_length, uint32_t count) override;
+ void writePixels(pixelcopy_t *param, uint32_t length) override;
+ void writeBytes(const uint8_t *data, uint32_t length, bool dc, bool use_dma) override;
+
+ void initDMA(void) {}
+ void flush(void) {}
+ void addDMAQueue(const uint8_t *data, uint32_t length) override { writeBytes(data, length, true, true); }
+ void execDMAQueue(void) {}
+ uint8_t *getDMABuffer(uint32_t length) override { return _flip_buffer.getBuffer(length); }
+
+ void beginRead(void) override;
+ void endRead(void) override;
+ uint32_t readData(uint_fast8_t bit_length) override;
+ bool readBytes(uint8_t *dst, uint32_t length, bool use_dma) override;
+ void readPixels(void *dst, pixelcopy_t *param, uint32_t length) override;
+
+ private:
+ HardwareSPI *PrivateSPI;
+ std::string SPIName;
+ __attribute__((always_inline)) inline void dc_h(void) { gpio_hi(_cfg.pin_dc); }
+ __attribute__((always_inline)) inline void dc_l(void) { gpio_lo(_cfg.pin_dc); }
+
+ config_t _cfg;
+ FlipBuffer _flip_buffer;
+ bool _need_wait;
+ uint32_t _mask_reg_dc;
+ uint32_t _last_apb_freq = -1;
+ uint32_t _clkdiv_write;
+ uint32_t _clkdiv_read;
+ volatile uint32_t *_gpio_reg_dc_h;
+ volatile uint32_t *_gpio_reg_dc_l;
+};
+
+//----------------------------------------------------------------------------
+} // namespace v1
+} // namespace lgfx
+#endif
\ No newline at end of file
diff --git a/src/input/TouchScreenImpl1.cpp b/src/input/TouchScreenImpl1.cpp
index 3e4ed4163..c863ead69 100644
--- a/src/input/TouchScreenImpl1.cpp
+++ b/src/input/TouchScreenImpl1.cpp
@@ -4,7 +4,7 @@
#include "configuration.h"
#include "modules/ExternalNotificationModule.h"
-#ifdef ARCH_PORTDUINO
+#if ARCH_PORTDUINO
#include "platform/portduino/PortduinoGlue.h"
#endif
diff --git a/src/main.cpp b/src/main.cpp
index 587bcb56e..b1a15634f 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -590,20 +590,6 @@ void setup()
if (config.display.oled != meshtastic_Config_DisplayConfig_OledType_OLED_AUTO)
screen_model = config.display.oled;
-#ifdef UNPHONE
- // initialise IO expander with pinmodes
- Wire.beginTransmission(0x26);
- Wire.write(0x06);
- Wire.write(0x7A);
- Wire.write(0xDD);
- Wire.endTransmission();
- Wire.beginTransmission(0x26);
- Wire.write(0x02);
- Wire.write(0x04); // Backlight on
- Wire.write(0x22); // G&B LEDs off
- Wire.endTransmission();
-#endif
-
#if defined(USE_SH1107)
screen_model = meshtastic_Config_DisplayConfig_OledType_OLED_SH1107; // set dimension of 128x128
display_geometry = GEOMETRY_128_128;
@@ -644,14 +630,12 @@ void setup()
pinMode(LORA_CS, OUTPUT);
digitalWrite(LORA_CS, HIGH);
SPI1.begin(false);
-#else // HW_SPI1_DEVICE
+#else // HW_SPI1_DEVICE
SPI.setSCK(LORA_SCK);
SPI.setTX(LORA_MOSI);
SPI.setRX(LORA_MISO);
SPI.begin(false);
-#endif // HW_SPI1_DEVICE
-#elif ARCH_PORTDUINO
- SPI.begin(settingsStrings[spidev].c_str());
+#endif // HW_SPI1_DEVICE
#elif !defined(ARCH_ESP32) // ARCH_RP2040
SPI.begin();
#else
@@ -738,7 +722,7 @@ void setup()
if (settingsMap[use_sx1262]) {
if (!rIf) {
LOG_DEBUG("Attempting to activate sx1262 radio on SPI port %s\n", settingsStrings[spidev].c_str());
- LockingArduinoHal *RadioLibHAL = new LockingArduinoHal(SPI, spiSettings);
+ LockingArduinoHal *RadioLibHAL = new LockingArduinoHal(*LoraSPI, spiSettings);
rIf = new SX1262Interface((LockingArduinoHal *)RadioLibHAL, settingsMap[cs], settingsMap[irq], settingsMap[reset],
settingsMap[busy]);
if (!rIf->init()) {
@@ -752,7 +736,7 @@ void setup()
} else if (settingsMap[use_rf95]) {
if (!rIf) {
LOG_DEBUG("Attempting to activate rf95 radio on SPI port %s\n", settingsStrings[spidev].c_str());
- LockingArduinoHal *RadioLibHAL = new LockingArduinoHal(SPI, spiSettings);
+ LockingArduinoHal *RadioLibHAL = new LockingArduinoHal(*LoraSPI, spiSettings);
rIf = new RF95Interface((LockingArduinoHal *)RadioLibHAL, settingsMap[cs], settingsMap[irq], settingsMap[reset],
settingsMap[busy]);
if (!rIf->init()) {
@@ -767,7 +751,7 @@ void setup()
} else if (settingsMap[use_sx1280]) {
if (!rIf) {
LOG_DEBUG("Attempting to activate sx1280 radio on SPI port %s\n", settingsStrings[spidev].c_str());
- LockingArduinoHal *RadioLibHAL = new LockingArduinoHal(SPI, spiSettings);
+ LockingArduinoHal *RadioLibHAL = new LockingArduinoHal(*LoraSPI, spiSettings);
rIf = new SX1280Interface((LockingArduinoHal *)RadioLibHAL, settingsMap[cs], settingsMap[irq], settingsMap[reset],
settingsMap[busy]);
if (!rIf->init()) {
@@ -1017,4 +1001,4 @@ void loop()
mainDelay.delay(delayMsec);
}
// if (didWake) LOG_DEBUG("wake!\n");
-}
+}
\ No newline at end of file
diff --git a/src/main.h b/src/main.h
index 132fd190b..bb812b7b6 100644
--- a/src/main.h
+++ b/src/main.h
@@ -22,6 +22,11 @@ extern NimbleBluetooth *nimbleBluetooth;
extern NRF52Bluetooth *nrf52Bluetooth;
#endif
+#if ARCH_PORTDUINO
+extern HardwareSPI *DisplaySPI;
+extern HardwareSPI *LoraSPI;
+
+#endif
extern ScanI2C::DeviceAddress screen_found;
extern ScanI2C::DeviceAddress cardkb_found;
extern uint8_t kb_model;
diff --git a/src/mesh/MeshModule.cpp b/src/mesh/MeshModule.cpp
index c8dd7f3d1..2ef46e4db 100644
--- a/src/mesh/MeshModule.cpp
+++ b/src/mesh/MeshModule.cpp
@@ -12,7 +12,7 @@ const meshtastic_MeshPacket *MeshModule::currentRequest;
/**
* If any of the current chain of modules has already sent a reply, it will be here. This is useful to allow
- * the RoutingPlugin to avoid sending redundant acks
+ * the RoutingModule to avoid sending redundant acks
*/
meshtastic_MeshPacket *MeshModule::currentReply;
@@ -40,7 +40,7 @@ meshtastic_MeshPacket *MeshModule::allocAckNak(meshtastic_Routing_Error err, Nod
c.error_reason = err;
c.which_variant = meshtastic_Routing_error_reason_tag;
- // Now that we have moded sendAckNak up one level into the class hierarchy we can no longer assume we are a RoutingPlugin
+ // Now that we have moded sendAckNak up one level into the class hierarchy we can no longer assume we are a RoutingModule
// So we manually call pb_encode_to_bytes and specify routing port number
// auto p = allocDataProtobuf(c);
meshtastic_MeshPacket *p = router->allocForSending();
@@ -54,7 +54,8 @@ meshtastic_MeshPacket *MeshModule::allocAckNak(meshtastic_Routing_Error err, Nod
p->to = to;
p->decoded.request_id = idFrom;
p->channel = chIndex;
- LOG_ERROR("Alloc an err=%d,to=0x%x,idFrom=0x%x,id=0x%x\n", err, to, idFrom, p->id);
+ if (err != meshtastic_Routing_Error_NONE)
+ LOG_ERROR("Alloc an err=%d,to=0x%x,idFrom=0x%x,id=0x%x\n", err, to, idFrom, p->id);
return p;
}
@@ -68,7 +69,7 @@ meshtastic_MeshPacket *MeshModule::allocErrorResponse(meshtastic_Routing_Error e
return r;
}
-void MeshModule::callPlugins(meshtastic_MeshPacket &mp, RxSource src)
+void MeshModule::callModules(meshtastic_MeshPacket &mp, RxSource src)
{
// LOG_DEBUG("In call modules\n");
bool moduleFound = false;
@@ -258,7 +259,7 @@ void MeshModule::observeUIEvents(Observer *observer)
}
}
-AdminMessageHandleResult MeshModule::handleAdminMessageForAllPlugins(const meshtastic_MeshPacket &mp,
+AdminMessageHandleResult MeshModule::handleAdminMessageForAllModules(const meshtastic_MeshPacket &mp,
meshtastic_AdminMessage *request,
meshtastic_AdminMessage *response)
{
diff --git a/src/mesh/MeshModule.h b/src/mesh/MeshModule.h
index 6c431adb4..2e2af33e0 100644
--- a/src/mesh/MeshModule.h
+++ b/src/mesh/MeshModule.h
@@ -64,11 +64,11 @@ class MeshModule
/** For use only by MeshService
*/
- static void callPlugins(meshtastic_MeshPacket &mp, RxSource src = RX_SRC_RADIO);
+ static void callModules(meshtastic_MeshPacket &mp, RxSource src = RX_SRC_RADIO);
static std::vector GetMeshModulesWithUIFrames();
static void observeUIEvents(Observer *observer);
- static AdminMessageHandleResult handleAdminMessageForAllPlugins(const meshtastic_MeshPacket &mp,
+ static AdminMessageHandleResult handleAdminMessageForAllModules(const meshtastic_MeshPacket &mp,
meshtastic_AdminMessage *request,
meshtastic_AdminMessage *response);
#if HAS_SCREEN
@@ -195,4 +195,4 @@ class MeshModule
/** set the destination and packet parameters of packet p intended as a reply to a particular "to" packet
* This ensures that if the request packet was sent reliably, the reply is sent that way as well.
*/
-void setReplyTo(meshtastic_MeshPacket *p, const meshtastic_MeshPacket &to);
+void setReplyTo(meshtastic_MeshPacket *p, const meshtastic_MeshPacket &to);
\ No newline at end of file
diff --git a/src/mesh/NodeDB.cpp b/src/mesh/NodeDB.cpp
index 73aa29bbf..710b21593 100644
--- a/src/mesh/NodeDB.cpp
+++ b/src/mesh/NodeDB.cpp
@@ -527,8 +527,8 @@ void NodeDB::installDefaultDeviceState()
void NodeDB::pickNewNodeNum()
{
NodeNum nodeNum = myNodeInfo.my_node_num;
+ getMacAddr(ourMacAddr); // Make sure ourMacAddr is set
if (nodeNum == 0) {
- getMacAddr(ourMacAddr); // Make sure ourMacAddr is set
// Pick an initial nodenum based on the macaddr
nodeNum = (ourMacAddr[2] << 24) | (ourMacAddr[3] << 16) | (ourMacAddr[4] << 8) | ourMacAddr[5];
}
diff --git a/src/mesh/RF95Interface.cpp b/src/mesh/RF95Interface.cpp
index b658a8ff6..8c6c349fd 100644
--- a/src/mesh/RF95Interface.cpp
+++ b/src/mesh/RF95Interface.cpp
@@ -215,7 +215,7 @@ bool RF95Interface::isChannelActive()
// LOG_DEBUG("Channel is busy!\n");
return true;
}
- if (result != RADIOLIB_ERR_WRONG_MODEM)
+ if (result != RADIOLIB_CHANNEL_FREE)
LOG_ERROR("Radiolib error %d when attempting RF95 isChannelActive!\n", result);
assert(result != RADIOLIB_ERR_WRONG_MODEM);
diff --git a/src/mesh/RadioInterface.cpp b/src/mesh/RadioInterface.cpp
index 3aac9dfce..63912a03e 100644
--- a/src/mesh/RadioInterface.cpp
+++ b/src/mesh/RadioInterface.cpp
@@ -151,10 +151,16 @@ static uint8_t bytes[MAX_RHPACKETLEN];
void initRegion()
{
const RegionInfo *r = regions;
+#ifdef LORA_REGIONCODE
+ for (; r->code != meshtastic_Config_LoRaConfig_RegionCode_UNSET && r->code != LORA_REGIONCODE; r++)
+ ;
+ LOG_INFO("Wanted region %d, regulatory override to %s\n", config.lora.region, r->name);
+#else
for (; r->code != meshtastic_Config_LoRaConfig_RegionCode_UNSET && r->code != config.lora.region; r++)
;
- myRegion = r;
LOG_INFO("Wanted region %d, using %s\n", config.lora.region, r->name);
+#endif
+ myRegion = r;
}
/**
diff --git a/src/mesh/Router.cpp b/src/mesh/Router.cpp
index 3fa933bb1..e4d67f019 100644
--- a/src/mesh/Router.cpp
+++ b/src/mesh/Router.cpp
@@ -479,7 +479,7 @@ void Router::handleReceived(meshtastic_MeshPacket *p, RxSource src)
// call modules here
if (!skipHandle)
- MeshModule::callPlugins(*p, src);
+ MeshModule::callModules(*p, src);
}
void Router::perhapsHandleReceived(meshtastic_MeshPacket *p)
@@ -499,4 +499,4 @@ void Router::perhapsHandleReceived(meshtastic_MeshPacket *p)
handleReceived(p);
packetPool.release(p);
-}
+}
\ No newline at end of file
diff --git a/src/mesh/SX128xInterface.cpp b/src/mesh/SX128xInterface.cpp
index 564b80494..9e4fbfa77 100644
--- a/src/mesh/SX128xInterface.cpp
+++ b/src/mesh/SX128xInterface.cpp
@@ -280,7 +280,7 @@ template bool SX128xInterface::isChannelActive()
result = lora.scanChannel();
if (result == RADIOLIB_LORA_DETECTED)
return true;
- if (result != RADIOLIB_ERR_WRONG_MODEM)
+ if (result != RADIOLIB_CHANNEL_FREE)
LOG_ERROR("Radiolib error %d when attempting SX128X scanChannel!\n", result);
assert(result != RADIOLIB_ERR_WRONG_MODEM);
diff --git a/src/mesh/generated/meshtastic/mesh.pb.h b/src/mesh/generated/meshtastic/mesh.pb.h
index e674e28bb..67b2edd15 100644
--- a/src/mesh/generated/meshtastic/mesh.pb.h
+++ b/src/mesh/generated/meshtastic/mesh.pb.h
@@ -146,6 +146,8 @@ typedef enum _meshtastic_HardwareModel {
/* Teledatics TD-LORAC NRF52840 based M.2 LoRA module
Compatible with the TD-WRLS development board */
meshtastic_HardwareModel_TD_LORAC = 60,
+ /* CDEBYTE EoRa-S3 board using their own MM modules, clone of LILYGO T3S3 */
+ meshtastic_HardwareModel_CDEBYTE_EORA_S3 = 61,
/* ------------------------------------------------------------------------------------------------------------------------------------------
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.
------------------------------------------------------------------------------------------------------------------------------------------ */
diff --git a/src/modules/AdminModule.cpp b/src/modules/AdminModule.cpp
index b40633af0..54eb577f7 100644
--- a/src/modules/AdminModule.cpp
+++ b/src/modules/AdminModule.cpp
@@ -256,7 +256,7 @@ bool AdminModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshta
default:
meshtastic_AdminMessage res = meshtastic_AdminMessage_init_default;
- AdminMessageHandleResult handleResult = MeshModule::handleAdminMessageForAllPlugins(mp, r, &res);
+ AdminMessageHandleResult handleResult = MeshModule::handleAdminMessageForAllModules(mp, r, &res);
if (handleResult == AdminMessageHandleResult::HANDLED_WITH_RESPONSE) {
myReply = allocDataProtobuf(res);
diff --git a/src/mqtt/MQTT.cpp b/src/mqtt/MQTT.cpp
index 05d5486b2..da1c204b8 100644
--- a/src/mqtt/MQTT.cpp
+++ b/src/mqtt/MQTT.cpp
@@ -656,6 +656,7 @@ std::string MQTT::meshPacketToJson(meshtastic_MeshPacket *mp)
msgPayload["voltage"] = new JSONValue(decoded->variant.device_metrics.voltage);
msgPayload["channel_utilization"] = new JSONValue(decoded->variant.device_metrics.channel_utilization);
msgPayload["air_util_tx"] = new JSONValue(decoded->variant.device_metrics.air_util_tx);
+ msgPayload["uptime_seconds"] = new JSONValue((uint)decoded->variant.device_metrics.uptime_seconds);
} else if (decoded->which_variant == meshtastic_Telemetry_environment_metrics_tag) {
msgPayload["temperature"] = new JSONValue(decoded->variant.environment_metrics.temperature);
msgPayload["relative_humidity"] = new JSONValue(decoded->variant.environment_metrics.relative_humidity);
diff --git a/src/platform/esp32/architecture.h b/src/platform/esp32/architecture.h
index 6855265ac..15e437bb5 100644
--- a/src/platform/esp32/architecture.h
+++ b/src/platform/esp32/architecture.h
@@ -117,6 +117,8 @@
#define HW_VENDOR meshtastic_HardwareModel_HELTEC_WIRELESS_PAPER
#elif defined(TLORA_T3S3_V1)
#define HW_VENDOR meshtastic_HardwareModel_TLORA_T3_S3
+#elif defined(CDEBYTE_ELORA_S3)
+#define HW_VENDOR meshtastic_HardwareModel_CDEBYTE_ELORA_S3
#elif defined(BETAFPV_2400_TX)
#define HW_VENDOR meshtastic_HardwareModel_BETAFPV_2400_TX
#elif defined(NANO_G1_EXPLORER)
diff --git a/src/platform/portduino/PortduinoGlue.cpp b/src/platform/portduino/PortduinoGlue.cpp
index f686ef3dc..f3415aaee 100644
--- a/src/platform/portduino/PortduinoGlue.cpp
+++ b/src/platform/portduino/PortduinoGlue.cpp
@@ -15,6 +15,8 @@
#include