diff --git a/boards/bpi_picow_esp32_s3.json b/boards/bpi_picow_esp32_s3.json
new file mode 100644
index 000000000..75983d845
--- /dev/null
+++ b/boards/bpi_picow_esp32_s3.json
@@ -0,0 +1,38 @@
+{
+ "build": {
+ "arduino": {
+ "ldscript": "esp32s3_out.ld"
+ },
+ "core": "esp32",
+ "extra_flags": [
+ "-DARDUINO_USB_CDC_ON_BOOT=1",
+ "-DARDUINO_USB_MODE=0",
+ "-DARDUINO_RUNNING_CORE=1",
+ "-DARDUINO_EVENT_RUNNING_CORE=1",
+ "-DBOARD_HAS_PSRAM"
+ ],
+ "f_cpu": "240000000L",
+ "f_flash": "80000000L",
+ "flash_mode": "dio",
+ "hwids": [["0x303A", "0x1001"]],
+ "mcu": "esp32s3",
+ "variant": "bpi_picow_esp32_s3"
+ },
+ "connectivity": ["wifi"],
+ "debug": {
+ "openocd_target": "esp32s3.cfg"
+ },
+ "frameworks": ["arduino", "espidf"],
+ "name": "BPI-PicoW-S3 (8 MB FLASH, 2 MB PSRAM)",
+ "upload": {
+ "flash_size": "8MB",
+ "maximum_ram_size": 327680,
+ "maximum_size": 8388608,
+ "use_1200bps_touch": true,
+ "wait_for_upload_port": true,
+ "require_upload_port": true,
+ "speed": 921600
+ },
+ "url": "https://wiki.banana-pi.org/BPI-PicoW-S3",
+ "vendor": "BPI"
+}
diff --git a/protobufs b/protobufs
index ef2bc66bb..e84f0cc7c 160000
--- a/protobufs
+++ b/protobufs
@@ -1 +1 @@
-Subproject commit ef2bc66bba41e8ef98ea893e46eb36a2da40cb5e
+Subproject commit e84f0cc7cab2879b00085000589b9fd6527d0d68
diff --git a/src/PowerFSM.cpp b/src/PowerFSM.cpp
index 7babc2067..6804242c2 100644
--- a/src/PowerFSM.cpp
+++ b/src/PowerFSM.cpp
@@ -295,10 +295,10 @@ void PowerFSM_setup()
powerFSM.add_transition(&stateON, &stateON, EVENT_NODEDB_UPDATED, NULL, "NodeDB update");
// Show the received text message
- powerFSM.add_transition(&stateLS, &stateON, EVENT_RECEIVED_TEXT_MSG, NULL, "Received text");
- powerFSM.add_transition(&stateNB, &stateON, EVENT_RECEIVED_TEXT_MSG, NULL, "Received text");
- powerFSM.add_transition(&stateDARK, &stateON, EVENT_RECEIVED_TEXT_MSG, NULL, "Received text");
- powerFSM.add_transition(&stateON, &stateON, EVENT_RECEIVED_TEXT_MSG, NULL, "Received text"); // restarts the sleep timer
+ powerFSM.add_transition(&stateLS, &stateON, EVENT_RECEIVED_MSG, NULL, "Received text");
+ powerFSM.add_transition(&stateNB, &stateON, EVENT_RECEIVED_MSG, NULL, "Received text");
+ powerFSM.add_transition(&stateDARK, &stateON, EVENT_RECEIVED_MSG, NULL, "Received text");
+ powerFSM.add_transition(&stateON, &stateON, EVENT_RECEIVED_MSG, NULL, "Received text"); // restarts the sleep timer
}
// If we are not in statePOWER but get a serial connection, suppress sleep (and keep the screen on) while connected
diff --git a/src/PowerFSM.h b/src/PowerFSM.h
index 116468121..752a9f7dd 100644
--- a/src/PowerFSM.h
+++ b/src/PowerFSM.h
@@ -8,7 +8,7 @@
#define EVENT_WAKE_TIMER 2
// #define EVENT_RECEIVED_PACKET 3
#define EVENT_PACKET_FOR_PHONE 4
-#define EVENT_RECEIVED_TEXT_MSG 5
+#define EVENT_RECEIVED_MSG 5
// #define EVENT_BOOT 6 // now done with a timed transition
#define EVENT_BLUETOOTH_PAIR 7
#define EVENT_NODEDB_UPDATED 8 // NodeDB has a big enough change that we think you should turn on the screen
diff --git a/src/configuration.h b/src/configuration.h
index 58e41877d..e1420c8db 100644
--- a/src/configuration.h
+++ b/src/configuration.h
@@ -124,6 +124,11 @@ along with this program. If not, see .
#define MPU6050_ADDR 0x68
#define LIS3DH_ADR 0x18
+// -----------------------------------------------------------------------------
+// LED
+// -----------------------------------------------------------------------------
+#define NCP5623_ADDR 0x38
+
// -----------------------------------------------------------------------------
// Security
// -----------------------------------------------------------------------------
diff --git a/src/detect/ScanI2C.h b/src/detect/ScanI2C.h
index 01b300c10..a56ce86fe 100644
--- a/src/detect/ScanI2C.h
+++ b/src/detect/ScanI2C.h
@@ -33,6 +33,7 @@ class ScanI2C
PMSA0031,
MPU6050,
LIS3DH,
+ NCP5623,
} DeviceType;
// typedef uint8_t DeviceAddress;
diff --git a/src/detect/ScanI2CTwoWire.cpp b/src/detect/ScanI2CTwoWire.cpp
index fb568b552..b7f16734f 100644
--- a/src/detect/ScanI2CTwoWire.cpp
+++ b/src/detect/ScanI2CTwoWire.cpp
@@ -213,6 +213,7 @@ void ScanI2CTwoWire::scanPort(I2CPort port)
break;
SCAN_SIMPLE_CASE(ST7567_ADDRESS, SCREEN_ST7567, "st7567 display found\n")
+ SCAN_SIMPLE_CASE(NCP5623_ADDR, NCP5623, "NCP5623 RGB LED found\n");
#ifdef HAS_PMU
SCAN_SIMPLE_CASE(XPOWERS_AXP192_AXP2101_ADDRESS, PMU_AXP192_AXP2101, "axp192/axp2101 PMU found\n")
diff --git a/src/gps/NMEAWPL.cpp b/src/gps/NMEAWPL.cpp
index 6ab2c85bf..ac11d78f8 100644
--- a/src/gps/NMEAWPL.cpp
+++ b/src/gps/NMEAWPL.cpp
@@ -1,5 +1,7 @@
#include "NMEAWPL.h"
#include "GeoCoord.h"
+#include "RTC.h"
+#include
/* -------------------------------------------
* 1 2 3 4 5 6
@@ -56,12 +58,18 @@ uint32_t printWPL(char *buf, size_t bufsz, const meshtastic_Position &pos, const
uint32_t printGGA(char *buf, size_t bufsz, const meshtastic_Position &pos)
{
GeoCoord geoCoord(pos.latitude_i, pos.longitude_i, pos.altitude);
- uint32_t len =
- snprintf(buf, bufsz, "$GNGGA,%06u.%03u,%02d%07.4f,%c,%03d%07.4f,%c,%u,%02u,%04u,%04d,%c,%04d,%c,%d,%04d", pos.time / 1000,
- pos.time % 1000, geoCoord.getDMSLatDeg(), (abs(geoCoord.getLatitude()) - geoCoord.getDMSLatDeg() * 1e+7) * 6e-6,
- geoCoord.getDMSLatCP(), geoCoord.getDMSLonDeg(),
- (abs(geoCoord.getLongitude()) - geoCoord.getDMSLonDeg() * 1e+7) * 6e-6, geoCoord.getDMSLonCP(), pos.fix_type,
- pos.sats_in_view, pos.HDOP, geoCoord.getAltitude(), 'M', pos.altitude_geoidal_separation, 'M', 0, 0);
+ tm *t = localtime((time_t *)&pos.timestamp);
+ if (getRTCQuality() > 0) { // use the device clock if we got time from somewhere. If not, use the GPS timestamp.
+ uint32_t rtc_sec = getValidTime(RTCQuality::RTCQualityDevice);
+ t = localtime((time_t *)&rtc_sec);
+ }
+
+ uint32_t len = snprintf(
+ buf, bufsz, "$GNGGA,%02d%02d%02d.%02d,%02d%07.4f,%c,%03d%07.4f,%c,%u,%02u,%04u,%04d,%c,%04d,%c,%d,%04d", t->tm_hour,
+ t->tm_min, t->tm_sec, pos.timestamp_millis_adjust, geoCoord.getDMSLatDeg(),
+ (abs(geoCoord.getLatitude()) - geoCoord.getDMSLatDeg() * 1e+7) * 6e-6, geoCoord.getDMSLatCP(), geoCoord.getDMSLonDeg(),
+ (abs(geoCoord.getLongitude()) - geoCoord.getDMSLonDeg() * 1e+7) * 6e-6, geoCoord.getDMSLonCP(), pos.fix_quality,
+ pos.sats_in_view, pos.HDOP, geoCoord.getAltitude(), 'M', pos.altitude_geoidal_separation, 'M', 0, 0);
uint32_t chk = 0;
for (uint32_t i = 1; i < len; i++) {
diff --git a/src/graphics/Screen.cpp b/src/graphics/Screen.cpp
index 482e76450..219214091 100644
--- a/src/graphics/Screen.cpp
+++ b/src/graphics/Screen.cpp
@@ -404,6 +404,43 @@ static void drawTextMessageFrame(OLEDDisplay *display, OLEDDisplayUiState *state
display->drawStringMaxWidth(0 + x, 0 + y + FONT_HEIGHT_SMALL, x + display->getWidth(), tempBuf);
}
+/// Draw the last waypoint we received
+static void drawWaypointFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
+{
+ static char tempBuf[237];
+
+ meshtastic_MeshPacket &mp = devicestate.rx_waypoint;
+ meshtastic_NodeInfo *node = nodeDB.getNode(getFrom(&mp));
+
+ display->setTextAlignment(TEXT_ALIGN_LEFT);
+ display->setFont(FONT_SMALL);
+ if (config.display.displaymode == meshtastic_Config_DisplayConfig_DisplayMode_INVERTED) {
+ display->fillRect(0 + x, 0 + y, x + display->getWidth(), y + FONT_HEIGHT_SMALL);
+ display->setColor(BLACK);
+ }
+
+ uint32_t seconds = sinceReceived(&mp);
+ uint32_t minutes = seconds / 60;
+ uint32_t hours = minutes / 60;
+ uint32_t days = hours / 24;
+
+ if (config.display.heading_bold) {
+ display->drawStringf(1 + x, 0 + y, tempBuf, "%s ago from %s",
+ screen->drawTimeDelta(days, hours, minutes, seconds).c_str(),
+ (node && node->has_user) ? node->user.short_name : "???");
+ }
+ display->drawStringf(0 + x, 0 + y, tempBuf, "%s ago from %s", screen->drawTimeDelta(days, hours, minutes, seconds).c_str(),
+ (node && node->has_user) ? node->user.short_name : "???");
+
+ display->setColor(WHITE);
+ meshtastic_Waypoint scratch;
+ memset(&scratch, 0, sizeof(scratch));
+ if (pb_decode_from_bytes(mp.decoded.payload.bytes, mp.decoded.payload.size, &meshtastic_Waypoint_msg, &scratch)) {
+ snprintf(tempBuf, sizeof(tempBuf), "Received waypoint: %s", scratch.name);
+ display->drawStringMaxWidth(0 + x, 0 + y + FONT_HEIGHT_SMALL, x + display->getWidth(), tempBuf);
+ }
+}
+
/// Draw a series of fields in a column, wrapping to multiple colums if needed
static void drawColumns(OLEDDisplay *display, int16_t x, int16_t y, const char **fields)
{
@@ -1232,6 +1269,10 @@ void Screen::setFrames()
if (devicestate.has_rx_text_message && shouldDrawMessage(&devicestate.rx_text_message)) {
normalFrames[numframes++] = drawTextMessageFrame;
}
+ // If we have a waypoint - show it next, unless it's a phone message and we aren't using any special modules
+ if (devicestate.has_rx_waypoint && shouldDrawMessage(&devicestate.rx_waypoint)) {
+ normalFrames[numframes++] = drawWaypointFrame;
+ }
// then all the nodes
// We only show a few nodes in our scrolling list - because meshes with many nodes would have too many screens
diff --git a/src/main.cpp b/src/main.cpp
index 7af41116c..b1a21e942 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -100,6 +100,8 @@ uint8_t kb_model;
ScanI2C::DeviceAddress rtc_found = ScanI2C::ADDRESS_NONE;
// The I2C address of the Accelerometer (if found)
ScanI2C::DeviceAddress accelerometer_found = ScanI2C::ADDRESS_NONE;
+// The I2C address of the RGB LED (if found)
+ScanI2C::FoundDevice rgb_found = ScanI2C::FoundDevice(ScanI2C::DeviceType::NONE, ScanI2C::ADDRESS_NONE);
#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL)
ATECCX08A atecc;
@@ -234,8 +236,6 @@ void setup()
fsInit();
- router = new ReliableRouter();
-
#ifdef I2C_SDA1
Wire1.begin(I2C_SDA1, I2C_SCL1);
#endif
@@ -346,6 +346,8 @@ void setup()
* nodeTelemetrySensorsMap singleton. This wraps that logic in a temporary scope to declare the temporary field
* "found".
*/
+ // Only one supported RGB LED currently
+ rgb_found = i2cScanner->find(ScanI2C::DeviceType::NCP5623);
#if !defined(ARCH_PORTDUINO)
auto acc_info = i2cScanner->firstAccelerometer();
@@ -413,6 +415,8 @@ void setup()
// If we're taking on the repeater role, use flood router
if (config.device.role == meshtastic_Config_DeviceConfig_Role_REPEATER)
router = new FloodingRouter();
+ else
+ router = new ReliableRouter();
#if HAS_BUTTON
// Buttons. Moved here cause we need NodeDB to be initialized
diff --git a/src/main.h b/src/main.h
index 645ba2ee2..5707e3bc5 100644
--- a/src/main.h
+++ b/src/main.h
@@ -26,6 +26,7 @@ extern ScanI2C::DeviceAddress cardkb_found;
extern uint8_t kb_model;
extern ScanI2C::DeviceAddress rtc_found;
extern ScanI2C::DeviceAddress accelerometer_found;
+extern ScanI2C::FoundDevice rgb_found;
extern bool eink_found;
extern bool pmu_found;
diff --git a/src/mesh/generated/meshtastic/deviceonly.pb.h b/src/mesh/generated/meshtastic/deviceonly.pb.h
index 56beee95e..d08c18ba9 100644
--- a/src/mesh/generated/meshtastic/deviceonly.pb.h
+++ b/src/mesh/generated/meshtastic/deviceonly.pb.h
@@ -56,6 +56,11 @@ typedef struct _meshtastic_DeviceState {
bool no_save;
/* Some GPS receivers seem to have bogus settings from the factory, so we always do one factory reset. */
bool did_gps_reset;
+ /* We keep the last received waypoint stored in the device flash,
+ so we can show it on the screen.
+ Might be null */
+ bool has_rx_waypoint;
+ meshtastic_MeshPacket rx_waypoint;
} meshtastic_DeviceState;
/* The on-disk saved channels */
@@ -110,10 +115,10 @@ extern "C" {
/* Initializer values for message structs */
-#define meshtastic_DeviceState_init_default {false, meshtastic_MyNodeInfo_init_default, false, meshtastic_User_init_default, 0, {meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default}, 0, {meshtastic_MeshPacket_init_default}, false, meshtastic_MeshPacket_init_default, 0, 0, 0}
+#define meshtastic_DeviceState_init_default {false, meshtastic_MyNodeInfo_init_default, false, meshtastic_User_init_default, 0, {meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default}, 0, {meshtastic_MeshPacket_init_default}, false, meshtastic_MeshPacket_init_default, 0, 0, 0, false, meshtastic_MeshPacket_init_default}
#define meshtastic_ChannelFile_init_default {0, {meshtastic_Channel_init_default, meshtastic_Channel_init_default, meshtastic_Channel_init_default, meshtastic_Channel_init_default, meshtastic_Channel_init_default, meshtastic_Channel_init_default, meshtastic_Channel_init_default, meshtastic_Channel_init_default}, 0}
#define meshtastic_OEMStore_init_default {0, 0, {0, {0}}, _meshtastic_ScreenFonts_MIN, "", {0, {0}}, false, meshtastic_LocalConfig_init_default, false, meshtastic_LocalModuleConfig_init_default}
-#define meshtastic_DeviceState_init_zero {false, meshtastic_MyNodeInfo_init_zero, false, meshtastic_User_init_zero, 0, {meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero}, 0, {meshtastic_MeshPacket_init_zero}, false, meshtastic_MeshPacket_init_zero, 0, 0, 0}
+#define meshtastic_DeviceState_init_zero {false, meshtastic_MyNodeInfo_init_zero, false, meshtastic_User_init_zero, 0, {meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero}, 0, {meshtastic_MeshPacket_init_zero}, false, meshtastic_MeshPacket_init_zero, 0, 0, 0, false, meshtastic_MeshPacket_init_zero}
#define meshtastic_ChannelFile_init_zero {0, {meshtastic_Channel_init_zero, meshtastic_Channel_init_zero, meshtastic_Channel_init_zero, meshtastic_Channel_init_zero, meshtastic_Channel_init_zero, meshtastic_Channel_init_zero, meshtastic_Channel_init_zero, meshtastic_Channel_init_zero}, 0}
#define meshtastic_OEMStore_init_zero {0, 0, {0, {0}}, _meshtastic_ScreenFonts_MIN, "", {0, {0}}, false, meshtastic_LocalConfig_init_zero, false, meshtastic_LocalModuleConfig_init_zero}
@@ -126,6 +131,7 @@ extern "C" {
#define meshtastic_DeviceState_version_tag 8
#define meshtastic_DeviceState_no_save_tag 9
#define meshtastic_DeviceState_did_gps_reset_tag 11
+#define meshtastic_DeviceState_rx_waypoint_tag 12
#define meshtastic_ChannelFile_channels_tag 1
#define meshtastic_ChannelFile_version_tag 2
#define meshtastic_OEMStore_oem_icon_width_tag 1
@@ -146,7 +152,8 @@ X(a, STATIC, REPEATED, MESSAGE, receive_queue, 5) \
X(a, STATIC, OPTIONAL, MESSAGE, rx_text_message, 7) \
X(a, STATIC, SINGULAR, UINT32, version, 8) \
X(a, STATIC, SINGULAR, BOOL, no_save, 9) \
-X(a, STATIC, SINGULAR, BOOL, did_gps_reset, 11)
+X(a, STATIC, SINGULAR, BOOL, did_gps_reset, 11) \
+X(a, STATIC, OPTIONAL, MESSAGE, rx_waypoint, 12)
#define meshtastic_DeviceState_CALLBACK NULL
#define meshtastic_DeviceState_DEFAULT NULL
#define meshtastic_DeviceState_my_node_MSGTYPE meshtastic_MyNodeInfo
@@ -154,6 +161,7 @@ X(a, STATIC, SINGULAR, BOOL, did_gps_reset, 11)
#define meshtastic_DeviceState_node_db_MSGTYPE meshtastic_NodeInfo
#define meshtastic_DeviceState_receive_queue_MSGTYPE meshtastic_MeshPacket
#define meshtastic_DeviceState_rx_text_message_MSGTYPE meshtastic_MeshPacket
+#define meshtastic_DeviceState_rx_waypoint_MSGTYPE meshtastic_MeshPacket
#define meshtastic_ChannelFile_FIELDLIST(X, a) \
X(a, STATIC, REPEATED, MESSAGE, channels, 1) \
@@ -187,7 +195,7 @@ extern const pb_msgdesc_t meshtastic_OEMStore_msg;
/* Maximum encoded size of messages (where known) */
#define meshtastic_ChannelFile_size 638
-#define meshtastic_DeviceState_size 22040
+#define meshtastic_DeviceState_size 22364
#define meshtastic_OEMStore_size 3041
#ifdef __cplusplus
diff --git a/src/modules/AdminModule.cpp b/src/modules/AdminModule.cpp
index 106aaeafc..d5f887734 100644
--- a/src/modules/AdminModule.cpp
+++ b/src/modules/AdminModule.cpp
@@ -39,9 +39,9 @@ static void writeSecret(char *buf, size_t bufsz, const char *currentVal)
}
/**
- * @brief Handle recieved protobuf message
+ * @brief Handle received protobuf message
*
- * @param mp Recieved MeshPacket
+ * @param mp Received MeshPacket
* @param r Decoded AdminMessage
* @return bool
*/
diff --git a/src/modules/ExternalNotificationModule.cpp b/src/modules/ExternalNotificationModule.cpp
index 3c931f3e2..7dbf78a08 100644
--- a/src/modules/ExternalNotificationModule.cpp
+++ b/src/modules/ExternalNotificationModule.cpp
@@ -8,6 +8,17 @@
#include "mesh/generated/meshtastic/rtttl.pb.h"
#include
+#include "main.h"
+
+#ifdef RAK4630
+#include
+NCP5623 rgb;
+
+uint8_t red = 0;
+uint8_t green = 0;
+uint8_t blue = 0;
+#endif
+
#ifndef PIN_BUZZER
#define PIN_BUZZER false
#endif
@@ -73,6 +84,15 @@ int32_t ExternalNotificationModule::runOnce()
millis()) {
getExternal(2) ? setExternalOff(2) : setExternalOn(2);
}
+#ifdef RAK4630
+ if (rgb_found.type == ScanI2C::NCP5623) {
+ green = (green + 50) % 255;
+ red = abs(red - green) % 255;
+ blue = abs(blue / red) % 255;
+
+ rgb.setColor(red, green, blue);
+ }
+#endif
}
// now let the PWM buzzer play
@@ -84,6 +104,7 @@ int32_t ExternalNotificationModule::runOnce()
rtttl::begin(config.device.buzzer_gpio, rtttlConfig.ringtone);
}
}
+
return 25;
}
}
@@ -106,6 +127,11 @@ void ExternalNotificationModule::setExternalOn(uint8_t index)
digitalWrite(output, (moduleConfig.external_notification.active ? true : false));
break;
}
+#ifdef RAK4630
+ if (rgb_found.type == ScanI2C::NCP5623) {
+ rgb.setColor(red, green, blue);
+ }
+#endif
}
void ExternalNotificationModule::setExternalOff(uint8_t index)
@@ -126,6 +152,15 @@ void ExternalNotificationModule::setExternalOff(uint8_t index)
digitalWrite(output, (moduleConfig.external_notification.active ? false : true));
break;
}
+
+#ifdef RAK4630
+ if (rgb_found.type == ScanI2C::NCP5623) {
+ red = 0;
+ green = 0;
+ blue = 0;
+ rgb.setColor(red, green, blue);
+ }
+#endif
}
bool ExternalNotificationModule::getExternal(uint8_t index)
@@ -200,6 +235,12 @@ ExternalNotificationModule::ExternalNotificationModule()
LOG_INFO("Using Pin %i in PWM mode\n", config.device.buzzer_gpio);
}
}
+#ifdef RAK4630
+ if (rgb_found.type == ScanI2C::NCP5623) {
+ rgb.begin();
+ rgb.setCurrent(10);
+ }
+#endif
} else {
LOG_INFO("External Notification Module Disabled\n");
disable();
@@ -300,7 +341,6 @@ ProcessMessage ExternalNotificationModule::handleReceived(const meshtastic_MeshP
nagCycleCutoff = millis() + moduleConfig.external_notification.output_ms;
}
}
-
setIntervalFromNow(0); // run once so we know if we should do something
}
diff --git a/src/modules/RemoteHardwareModule.cpp b/src/modules/RemoteHardwareModule.cpp
index fb455af44..c3232d266 100644
--- a/src/modules/RemoteHardwareModule.cpp
+++ b/src/modules/RemoteHardwareModule.cpp
@@ -18,7 +18,7 @@
static void pinModes(uint64_t mask, uint8_t mode)
{
for (uint64_t i = 0; i < NUM_GPIOS; i++) {
- if (mask & (1 << i)) {
+ if (mask & (1ULL << i)) {
pinMode(i, mode);
}
}
@@ -29,13 +29,10 @@ static uint64_t digitalReads(uint64_t mask)
{
uint64_t res = 0;
- // The Arduino docs show to run pinMode(). But, when testing, found it is best not to.
- // If the line below is uncommented, read will flip the pin to the default of the second
- // argument in pinModes(), which will make the read turn the PIN "on".
- // pinModes(mask, INPUT_PULLUP);
+ pinModes(mask, INPUT_PULLUP);
for (uint64_t i = 0; i < NUM_GPIOS; i++) {
- uint64_t m = 1 << i;
+ uint64_t m = 1ULL << i;
if (mask & m) {
if (digitalRead(i)) {
res |= m;
@@ -64,7 +61,7 @@ bool RemoteHardwareModule::handleReceivedProtobuf(const meshtastic_MeshPacket &r
screen->print("Write GPIOs\n");
for (uint8_t i = 0; i < NUM_GPIOS; i++) {
- uint64_t mask = 1 << i;
+ uint64_t mask = 1ULL << i;
if (p.gpio_mask & mask) {
digitalWrite(i, (p.gpio_value & mask) ? 1 : 0);
}
diff --git a/src/modules/TextMessageModule.cpp b/src/modules/TextMessageModule.cpp
index bab5decda..0fa175a14 100644
--- a/src/modules/TextMessageModule.cpp
+++ b/src/modules/TextMessageModule.cpp
@@ -15,7 +15,7 @@ ProcessMessage TextMessageModule::handleReceived(const meshtastic_MeshPacket &mp
devicestate.rx_text_message = mp;
devicestate.has_rx_text_message = true;
- powerFSM.trigger(EVENT_RECEIVED_TEXT_MSG);
+ powerFSM.trigger(EVENT_RECEIVED_MSG);
notifyObservers(&mp);
return ProcessMessage::CONTINUE; // Let others look at this message also if they want
diff --git a/src/modules/WaypointModule.cpp b/src/modules/WaypointModule.cpp
index 079be604e..f95bdec34 100644
--- a/src/modules/WaypointModule.cpp
+++ b/src/modules/WaypointModule.cpp
@@ -10,6 +10,12 @@ ProcessMessage WaypointModule::handleReceived(const meshtastic_MeshPacket &mp)
auto &p = mp.decoded;
LOG_INFO("Received waypoint msg from=0x%0x, id=0x%x, msg=%.*s\n", mp.from, mp.id, p.payload.size, p.payload.bytes);
+ // We only store/display messages destined for us.
+ // Keep a copy of the most recent text message.
+ devicestate.rx_waypoint = mp;
+ devicestate.has_rx_waypoint = true;
+
+ powerFSM.trigger(EVENT_RECEIVED_MSG);
notifyObservers(&mp);
return ProcessMessage::CONTINUE; // Let others look at this message also if they want
diff --git a/src/sleep.cpp b/src/sleep.cpp
index c25e3473e..e612b0032 100644
--- a/src/sleep.cpp
+++ b/src/sleep.cpp
@@ -309,8 +309,13 @@ esp_sleep_wakeup_cause_t doLightSleep(uint64_t sleepMsec) // FIXME, use a more r
// assert(esp_sleep_enable_uart_wakeup(0) == ESP_OK);
#endif
#ifdef BUTTON_PIN
+#if SOC_PM_SUPPORT_EXT_WAKEUP
esp_sleep_enable_ext0_wakeup((gpio_num_t)(config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN),
LOW); // when user presses, this button goes low
+#else
+ esp_sleep_enable_gpio_wakeup();
+ gpio_wakeup_enable((gpio_num_t)BUTTON_PIN, GPIO_INTR_LOW_LEVEL);
+#endif
#endif
#if defined(LORA_DIO1) && (LORA_DIO1 != RADIOLIB_NC)
gpio_wakeup_enable((gpio_num_t)LORA_DIO1, GPIO_INTR_HIGH_LEVEL); // SX126x/SX128x interrupt, active high
diff --git a/variants/ai-c3/platformio.ini b/variants/ai-c3/platformio.ini
index 76ecd9f0f..fbc6b51fa 100644
--- a/variants/ai-c3/platformio.ini
+++ b/variants/ai-c3/platformio.ini
@@ -2,7 +2,13 @@
extends = esp32c3_base
board = esp32-c3-devkitm-1
board_level = extra
-build_flags =
- ${esp32_base.build_flags}
+build_flags = ${esp32c3_base.build_flags}
-D PRIVATE_HW
-I variants/ai-c3
+; as long as BSEC2 Software Library is not supported remove Sensors from build
+build_src_filter = ${esp32c3_base.build_src_filter}
+ -
+ -
+ -
+lib_ignore = ${esp32c3_base.lib_ignore}
+ BSEC Software Library
diff --git a/variants/ai-c3/variant.h b/variants/ai-c3/variant.h
index 05f0abb51..2db91ccab 100644
--- a/variants/ai-c3/variant.h
+++ b/variants/ai-c3/variant.h
@@ -1,26 +1,33 @@
-// #define BUTTON_NEED_PULLUP // if set we need to turn on the internal CPU pullup during sleep
+#define HAS_TELEMETRY 0 // as long as BSEC2 is not supported
+#define HAS_SENSOR 0 // as long as BSEC2 is not supported
-#define I2C_SDA 8
-#define I2C_SCL 9
+#define SDA 0
+#define SCL 1
+#define I2C_SDA SDA
+#define I2C_SCL SCL
-#define BUTTON_PIN 0
+#define BUTTON_PIN 9 // BOOT button
+#define LED_PIN 30 // RGB LED
#define USE_RF95
-#undef RF95_SCK
#define RF95_SCK 4
-#undef RF95_MISO
#define RF95_MISO 5
-#undef RF95_MOSI
#define RF95_MOSI 6
-#undef RF95_NSS
#define RF95_NSS 7
-#define LORA_DIO0 10 // a No connect on the SX1262 module
-#define LORA_DIO1 3 // a No connect on the SX1262 module
+#define LORA_DIO0 10
+#define LORA_DIO1 3
#define LORA_RESET 2
+// WaveShare Core1262-868M
+// https://www.waveshare.com/wiki/Core1262-868M
+#define USE_SX1262
+#define SX126X_CS RF95_NSS
+#define SX126X_DIO1 LORA_DIO1
+#define SX126X_BUSY 10
+#define SX126X_RESET LORA_RESET
+#define SX126X_E22 // use DIO2 as RF switch
+
+#define HAS_GPS 0
#undef GPS_RX_PIN
#undef GPS_TX_PIN
-
-#define HAS_SCREEN 0
-#define HAS_GPS 0
diff --git a/variants/bpi_picow_esp32_s3/pins_arduino.h b/variants/bpi_picow_esp32_s3/pins_arduino.h
new file mode 100644
index 000000000..ee0e34ebf
--- /dev/null
+++ b/variants/bpi_picow_esp32_s3/pins_arduino.h
@@ -0,0 +1,37 @@
+#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) < 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;
+
+// The default Wire will be mapped to PMU and RTC
+static const uint8_t SDA = 12;
+static const uint8_t SCL = 14;
+
+// Default SPI will be mapped to Radio
+static const uint8_t MISO = 39;
+static const uint8_t SCK = 21;
+static const uint8_t MOSI = 38;
+static const uint8_t SS = 17;
+
+//#define SPI_MOSI (11)
+//#define SPI_SCK (14)
+//#define SPI_MISO (2)
+//#define SPI_CS (13)
+
+//#define SDCARD_CS SPI_CS
+
+#endif /* Pins_Arduino_h */
\ No newline at end of file
diff --git a/variants/bpi_picow_esp32_s3/platformio.ini b/variants/bpi_picow_esp32_s3/platformio.ini
new file mode 100644
index 000000000..27c420df5
--- /dev/null
+++ b/variants/bpi_picow_esp32_s3/platformio.ini
@@ -0,0 +1,14 @@
+[env:bpi_picow_esp32_s3]
+extends = esp32s3_base
+board = bpi_picow_esp32_s3
+board_level = extra
+;OpenOCD flash method
+;upload_protocol = esp-builtin
+;Normal method
+upload_protocol = esptool
+upload_port = /dev/ttyACM2
+lib_deps =
+ ${esp32_base.lib_deps}
+ caveman99/ESP32 Codec2@^1.0.1
+build_flags =
+ ${esp32_base.build_flags} -D PRIVATE_HW -I variants/bpi_picow_esp32_s3
\ No newline at end of file
diff --git a/variants/bpi_picow_esp32_s3/variant.h b/variants/bpi_picow_esp32_s3/variant.h
new file mode 100644
index 000000000..78eae1dad
--- /dev/null
+++ b/variants/bpi_picow_esp32_s3/variant.h
@@ -0,0 +1,73 @@
+#define HAS_GPS 0
+#undef GPS_RX_PIN
+#undef GPS_TX_PIN
+
+//#define HAS_SCREEN 0
+
+//#define HAS_SDCARD
+//#define SDCARD_USE_SPI1
+
+#define USE_SSD1306
+#define I2C_SDA 12
+#define I2C_SCL 14
+
+#define LED_PIN 46
+#define LED_STATE_ON 0 // State when LED is litted
+
+//#define BUTTON_PIN 15 // Pico OLED 1.3 User key 0 - removed User key 1 (17)
+
+#define BUTTON_PIN 40
+//#define BUTTON_PIN 0 // This is the BOOT button pad at the moment
+//#define BUTTON_NEED_PULLUP
+
+//#define USE_RF95 // RFM95/SX127x
+
+#undef RF95_SCK
+#undef RF95_MISO
+#undef RF95_MOSI
+#undef RF95_NSS
+
+// WaveShare Core1262-868M OK
+// https://www.waveshare.com/wiki/Core1262-868M
+#define USE_SX1262
+
+#ifdef USE_SX1262
+#define RF95_MISO 39
+#define RF95_SCK 21
+#define RF95_MOSI 38
+#define RF95_NSS 17
+#define LORA_RESET 42
+#define LORA_DIO1 5
+#define LORA_BUSY 47
+#define SX126X_CS RF95_NSS
+#define SX126X_DIO1 LORA_DIO1
+#define SX126X_BUSY LORA_BUSY
+#define SX126X_RESET LORA_RESET
+#define SX126X_E22
+#endif
+
+//#define USE_SX1280
+#ifdef USE_SX1280
+#define RF95_MISO 1
+#define RF95_SCK 3
+#define RF95_MOSI 4
+#define RF95_NSS 2
+#define LORA_RESET 17
+#define LORA_DIO1 12
+#define LORA_BUSY 47
+#define SX128X_CS RF95_NSS
+#define SX128X_DIO1 LORA_DIO1
+#define SX128X_BUSY LORA_BUSY
+#define SX128X_RESET LORA_RESET
+#endif
+
+//#define USE_EINK
+/*
+ * eink display pins
+ */
+//#define PIN_EINK_CS
+//#define PIN_EINK_BUSY
+//#define PIN_EINK_DC
+//#define PIN_EINK_RES (-1)
+//#define PIN_EINK_SCLK 3
+//#define PIN_EINK_MOSI 4
\ No newline at end of file
diff --git a/variants/diy/v1/variant.h b/variants/diy/v1/variant.h
index 541edfa91..da9e41553 100644
--- a/variants/diy/v1/variant.h
+++ b/variants/diy/v1/variant.h
@@ -38,8 +38,9 @@
#define SX126X_DIO1 LORA_DIO1
#define SX126X_BUSY LORA_DIO2
#define SX126X_RESET LORA_RESET
-#define SX126X_RXEN 14
-#define SX126X_TXEN 13
+//#define SX126X_RXEN 14
+//#define SX126X_TXEN 13
+#define SX126X_POWER_EN (13)
// RX/TX for RFM95/SX127x
#define RF95_RXEN 14
diff --git a/variants/rak4631/platformio.ini b/variants/rak4631/platformio.ini
index a0928605f..0d1f17d91 100644
--- a/variants/rak4631/platformio.ini
+++ b/variants/rak4631/platformio.ini
@@ -9,6 +9,7 @@ lib_deps =
${networking_base.lib_deps}
melopero/Melopero RV3028@^1.1.0
https://github.com/RAKWireless/RAK13800-W5100S.git#1.0.2
+ rakwireless/RAKwireless NCP5623 RGB LED library@^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/rak4631_epaper/platformio.ini b/variants/rak4631_epaper/platformio.ini
index fd266c07f..e9c3e8723 100644
--- a/variants/rak4631_epaper/platformio.ini
+++ b/variants/rak4631_epaper/platformio.ini
@@ -8,6 +8,7 @@ lib_deps =
${nrf52840_base.lib_deps}
zinggjm/GxEPD2@^1.4.9
melopero/Melopero RV3028@^1.1.0
+ rakwireless/RAKwireless NCP5623 RGB LED library@^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/rak4631_epaper_onrxtx/platformio.ini b/variants/rak4631_epaper_onrxtx/platformio.ini
index 920380011..6e922b841 100644
--- a/variants/rak4631_epaper_onrxtx/platformio.ini
+++ b/variants/rak4631_epaper_onrxtx/platformio.ini
@@ -10,6 +10,7 @@ lib_deps =
${nrf52840_base.lib_deps}
zinggjm/GxEPD2@^1.5.1
melopero/Melopero RV3028@^1.1.0
+ rakwireless/RAKwireless NCP5623 RGB LED library@^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
diff --git a/version.properties b/version.properties
index 253a4d545..0e33ac38b 100644
--- a/version.properties
+++ b/version.properties
@@ -1,4 +1,4 @@
[VERSION]
major = 2
minor = 1
-build = 10
+build = 12