From d70a9392affb9ace3c3c32af9acc8129ab6976b7 Mon Sep 17 00:00:00 2001 From: ChangYanChu Date: Sat, 8 Feb 2025 20:03:44 +0800 Subject: [PATCH 01/21] improve UTF-8 string handling in JSONValue (#6011) ```text feat(json): improve UTF-8 string handling in JSONValue - Add proper UTF-8 multi-byte character sequence handling - Add boundary checks for UTF-8 sequences - Keep original code structure and flow - Add detailed comments for UTF-8 processing logic This change improves the robustness of JSON string handling while maintaining compatibility with existing code. --- src/serialization/JSONValue.cpp | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/src/serialization/JSONValue.cpp b/src/serialization/JSONValue.cpp index 64dc10abe..20cd90373 100644 --- a/src/serialization/JSONValue.cpp +++ b/src/serialization/JSONValue.cpp @@ -850,18 +850,26 @@ std::string JSONValue::StringifyString(const std::string &str) str_out += "\\r"; } else if (chr == '\t') { str_out += "\\t"; - } else if (chr < ' ' || chr > 126) { - str_out += "\\u"; - for (int i = 0; i < 4; i++) { - int value = (chr >> 12) & 0xf; - if (value >= 0 && value <= 9) - str_out += (char)('0' + value); - else if (value >= 10 && value <= 15) - str_out += (char)('A' + (value - 10)); - chr <<= 4; - } + } else if (chr < 0x20 || chr == 0x7F) { + char buf[7]; + snprintf(buf, sizeof(buf), "\\u%04x", chr); + str_out += buf; + } else if (chr < 0x80) { + str_out += chr; } else { str_out += chr; + size_t remain = str.end() - iter - 1; + if ((chr & 0xE0) == 0xC0 && remain >= 1) { + ++iter; + str_out += *iter; + } else if ((chr & 0xF0) == 0xE0 && remain >= 2) { + str_out += *(++iter); + str_out += *(++iter); + } else if ((chr & 0xF8) == 0xF0 && remain >= 3) { + str_out += *(++iter); + str_out += *(++iter); + str_out += *(++iter); + } } ++iter; From 39e45d90e16db0352660a912247e27620515ab91 Mon Sep 17 00:00:00 2001 From: Mark Trevor Birss Date: Mon, 10 Feb 2025 09:59:13 +0200 Subject: [PATCH 02/21] Create display-x11.yaml (#6021) --- bin/config.d/display-x11.yaml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 bin/config.d/display-x11.yaml diff --git a/bin/config.d/display-x11.yaml b/bin/config.d/display-x11.yaml new file mode 100644 index 000000000..b22df1cb0 --- /dev/null +++ b/bin/config.d/display-x11.yaml @@ -0,0 +1,4 @@ +Display: + Panel: X11 + Width: 480 + Height: 480 From 96262b106c579cccf1fde24a4e8aa771e5f34ae1 Mon Sep 17 00:00:00 2001 From: Mark Trevor Birss Date: Mon, 10 Feb 2025 11:53:58 +0200 Subject: [PATCH 03/21] Revert "Create display-x11.yaml (#6021)" (#6022) This reverts commit 39e45d90e16db0352660a912247e27620515ab91. --- bin/config.d/display-x11.yaml | 4 ---- 1 file changed, 4 deletions(-) delete mode 100644 bin/config.d/display-x11.yaml diff --git a/bin/config.d/display-x11.yaml b/bin/config.d/display-x11.yaml deleted file mode 100644 index b22df1cb0..000000000 --- a/bin/config.d/display-x11.yaml +++ /dev/null @@ -1,4 +0,0 @@ -Display: - Panel: X11 - Width: 480 - Height: 480 From 7c4bf38647691aa04aaea88f22b1b96d018b3ca2 Mon Sep 17 00:00:00 2001 From: Austin Date: Mon, 10 Feb 2025 15:29:16 -0500 Subject: [PATCH 04/21] meshtasticd flatpak: Include pio deps with release (#6025) --- .github/workflows/main_matrix.yml | 27 +++++++++-- .github/workflows/package_pio_deps.yml | 64 ++++++++++++++++++++++++++ 2 files changed, 87 insertions(+), 4 deletions(-) create mode 100644 .github/workflows/package_pio_deps.yml diff --git a/.github/workflows/main_matrix.yml b/.github/workflows/main_matrix.yml index b13866435..1dc177cc6 100644 --- a/.github/workflows/main_matrix.yml +++ b/.github/workflows/main_matrix.yml @@ -135,6 +135,12 @@ jobs: build_location: local secrets: inherit + package-pio-deps-native: + uses: ./.github/workflows/package_pio_deps.yml + with: + pio_env: native + secrets: inherit + test-native: uses: ./.github/workflows/test_native.yml @@ -279,7 +285,10 @@ jobs: if: ${{ github.event_name == 'workflow_dispatch' }} outputs: upload_url: ${{ steps.create_release.outputs.upload_url }} - needs: [gather-artifacts, build-debian-src] + needs: + - gather-artifacts + - build-debian-src + - package-pio-deps-native steps: - name: Checkout uses: actions/checkout@v4 @@ -315,17 +324,27 @@ jobs: merge-multiple: true path: ./output/debian-src - - name: Zip source deb + - name: Download native pio deps + uses: actions/download-artifact@v4 + with: + pattern: platformio-deps-native-${{ steps.version.outputs.long }} + merge-multiple: true + path: ./output/pio-deps-native + + - name: Zip linux sources working-directory: output - run: zip -j -9 -r ./meshtasticd-${{ steps.version.outputs.deb }}-src.zip ./debian-src + run: | + zip -j -9 -r ./meshtasticd-${{ steps.version.outputs.deb }}-src.zip ./debian-src + zip -j -9 -r ./platformio-deps-native-${{ steps.version.outputs.long }}.zip ./pio-deps-native # For diagnostics - name: Display structure of downloaded files run: ls -lR - - name: Add source deb to release + - name: Add linux sources to release run: | gh release upload v${{ steps.version.outputs.long }} ./output/meshtasticd-${{ steps.version.outputs.deb }}-src.zip + gh release upload v${{ steps.version.outputs.long }} ./output/platformio-deps-native-${{ steps.version.outputs.long }}.zip env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/package_pio_deps.yml b/.github/workflows/package_pio_deps.yml new file mode 100644 index 000000000..38c0e8104 --- /dev/null +++ b/.github/workflows/package_pio_deps.yml @@ -0,0 +1,64 @@ +name: Package PlatformIO Library Dependencies +# trunk-ignore-all(checkov/CKV_GHA_7): Allow workflow_dispatch inputs for testing + +on: + workflow_call: + inputs: + pio_env: + description: PlatformIO environment to target + required: true + type: string + workflow_dispatch: + inputs: + pio_env: + description: PlatformIO environment to target + required: true + type: string + +permissions: + contents: write + packages: write + +jobs: + pkg-pio-libdeps: + runs-on: ubuntu-24.04 + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + submodules: recursive + ref: ${{github.event.pull_request.head.ref}} + repository: ${{github.event.pull_request.head.repo.full_name}} + + - name: Setup Python + uses: actions/setup-python@v5 + with: + python-version: 3.x + + - name: Install deps + shell: bash + run: | + pip install platformio + + - name: Get release version string + run: | + echo "long=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT + id: version + + - name: Fetch libdeps + shell: bash + run: |- + platformio pkg install -e ${{ inputs.pio_env }} + platformio pkg install -e ${{ inputs.pio_env }} -t platformio/tool-scons@4.40502.0 + env: + PLATFORMIO_LIBDEPS_DIR: pio/libdeps + PLATFORMIO_PACKAGES_DIR: pio/packages + PLATFORMIO_CORE_DIR: pio/core + + - name: Store binaries as an artifact + uses: actions/upload-artifact@v4 + with: + name: platformio-deps-${{ inputs.pio_env }}-${{ steps.version.outputs.long }} + overwrite: true + path: | + pio/* From da1d78c8822a084e9473ff03091fccb3b5ea5228 Mon Sep 17 00:00:00 2001 From: Jason P Date: Mon, 10 Feb 2025 14:30:43 -0600 Subject: [PATCH 05/21] Add support for 12- and 24-hour clock, Minor Settings Frame Adjustment (#5988) * 12- or 24-hour clock work in progress * 12- and 24-hour added to Settings Frame. Also some adjustments to screen layout. * Updated Uptime wording to be "Up" to fit within screen real estate * Removed label from uptime to conserve additional space --------- Co-authored-by: Ben Meadors --- src/graphics/Screen.cpp | 48 +++++++++++++++++++++++++++++------------ 1 file changed, 34 insertions(+), 14 deletions(-) diff --git a/src/graphics/Screen.cpp b/src/graphics/Screen.cpp index 4ee49e3c0..0c18f3287 100644 --- a/src/graphics/Screen.cpp +++ b/src/graphics/Screen.cpp @@ -1489,22 +1489,21 @@ static void drawNodeInfo(OLEDDisplay *display, OLEDDisplayUiState *state, int16_ bearingToOther -= myHeading; screen->drawNodeHeading(display, compassX, compassY, compassDiam, bearingToOther); - float bearingToOtherDegrees = (bearingToOther < 0) ? bearingToOther + 2*PI : bearingToOther; + float bearingToOtherDegrees = (bearingToOther < 0) ? bearingToOther + 2 * PI : bearingToOther; bearingToOtherDegrees = bearingToOtherDegrees * 180 / PI; if (config.display.units == meshtastic_Config_DisplayConfig_DisplayUnits_IMPERIAL) { if (d < (2 * MILES_TO_FEET)) snprintf(distStr, sizeof(distStr), "%.0fft %.0f°", d * METERS_TO_FEET, bearingToOtherDegrees); else - snprintf(distStr, sizeof(distStr), "%.1fmi %.0f°", d * METERS_TO_FEET / MILES_TO_FEET, bearingToOtherDegrees); + snprintf(distStr, sizeof(distStr), "%.1fmi %.0f°", d * METERS_TO_FEET / MILES_TO_FEET, + bearingToOtherDegrees); } else { if (d < 2000) snprintf(distStr, sizeof(distStr), "%.0fm %.0f°", d, bearingToOtherDegrees); else snprintf(distStr, sizeof(distStr), "%.1fkm %.0f°", d / 1000, bearingToOtherDegrees); } - - } } if (!hasNodeHeading) { @@ -2649,13 +2648,12 @@ void DebugInfo::drawFrameSettings(OLEDDisplay *display, OLEDDisplayUiState *stat display->drawString(x + 1, y, String("USB")); } - auto mode = DisplayFormatters::getModemPresetDisplayName(config.lora.modem_preset, true); + // auto mode = DisplayFormatters::getModemPresetDisplayName(config.lora.modem_preset, true); - display->drawString(x + SCREEN_WIDTH - display->getStringWidth(mode), y, mode); - if (config.display.heading_bold) - display->drawString(x + SCREEN_WIDTH - display->getStringWidth(mode) - 1, y, mode); + // display->drawString(x + SCREEN_WIDTH - display->getStringWidth(mode), y, mode); + // if (config.display.heading_bold) + // display->drawString(x + SCREEN_WIDTH - display->getStringWidth(mode) - 1, y, mode); - // Line 2 uint32_t currentMillis = millis(); uint32_t seconds = currentMillis / 1000; uint32_t minutes = seconds / 60; @@ -2668,6 +2666,9 @@ void DebugInfo::drawFrameSettings(OLEDDisplay *display, OLEDDisplayUiState *stat display->setColor(WHITE); + // Setup string to assemble analogClock string + std::string analogClock = ""; + // Show uptime as days, hours, minutes OR seconds std::string uptime = screen->drawTimeDelta(days, hours, minutes, seconds); @@ -2684,17 +2685,36 @@ void DebugInfo::drawFrameSettings(OLEDDisplay *display, OLEDDisplayUiState *stat int min = (hms % SEC_PER_HOUR) / SEC_PER_MIN; int sec = (hms % SEC_PER_HOUR) % SEC_PER_MIN; // or hms % SEC_PER_MIN - char timebuf[10]; - snprintf(timebuf, sizeof(timebuf), " %02d:%02d:%02d", hour, min, sec); - uptime += timebuf; + char timebuf[12]; + + if (config.display.use_12h_clock) { + std::string meridiem = "am"; + if (hour >= 12) { + if (hour > 12) + hour -= 12; + meridiem = "pm"; + } + if (hour == 00) { + hour = 12; + } + snprintf(timebuf, sizeof(timebuf), "%d:%02d:%02d%s", hour, min, sec, meridiem.c_str()); + } else { + snprintf(timebuf, sizeof(timebuf), "%02d:%02d:%02d", hour, min, sec); + } + analogClock += timebuf; } - display->drawString(x, y + FONT_HEIGHT_SMALL * 1, uptime.c_str()); + // Line 1 + display->drawString(x + SCREEN_WIDTH - display->getStringWidth(uptime.c_str()), y, uptime.c_str()); + + // Line 2 + display->drawString(x, y + FONT_HEIGHT_SMALL * 1, analogClock.c_str()); // Display Channel Utilization char chUtil[13]; snprintf(chUtil, sizeof(chUtil), "ChUtil %2.0f%%", airTime->channelUtilizationPercent()); display->drawString(x + SCREEN_WIDTH - display->getStringWidth(chUtil), y + FONT_HEIGHT_SMALL * 1, chUtil); + #if HAS_GPS if (config.position.gps_mode == meshtastic_Config_PositionConfig_GpsMode_ENABLED) { // Line 3 @@ -2827,4 +2847,4 @@ int Screen::handleAdminMessage(const meshtastic_AdminMessage *arg) } // namespace graphics #else graphics::Screen::Screen(ScanI2C::DeviceAddress, meshtastic_Config_DisplayConfig_OledType, OLEDDISPLAY_GEOMETRY) {} -#endif // HAS_SCREEN +#endif // HAS_SCREEN \ No newline at end of file From 4e2b47cc67d33d399350a2947c4fe61329801cb5 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 10 Feb 2025 15:02:42 -0600 Subject: [PATCH 06/21] [create-pull-request] automated change (#6027) Co-authored-by: thebentern <9000580+thebentern@users.noreply.github.com> --- protobufs | 2 +- src/mesh/generated/meshtastic/module_config.pb.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/protobufs b/protobufs index b80785b16..068646653 160000 --- a/protobufs +++ b/protobufs @@ -1 +1 @@ -Subproject commit b80785b16bc0d243b97917998706e7bf209cd9d0 +Subproject commit 068646653e8375fc145988026ad242a3cf70f7ab diff --git a/src/mesh/generated/meshtastic/module_config.pb.h b/src/mesh/generated/meshtastic/module_config.pb.h index 697b965c5..848b010d3 100644 --- a/src/mesh/generated/meshtastic/module_config.pb.h +++ b/src/mesh/generated/meshtastic/module_config.pb.h @@ -347,7 +347,7 @@ typedef struct _meshtastic_ModuleConfig_TelemetryConfig { bool health_screen_enabled; } meshtastic_ModuleConfig_TelemetryConfig; -/* TODO: REPLACE */ +/* Canned Messages Module Config */ typedef struct _meshtastic_ModuleConfig_CannedMessageConfig { /* Enable the rotary encoder #1. This is a 'dumb' encoder sending pulses on both A and B pins while rotating. */ bool rotary1_enabled; From 8427072d791b5547ec029534e615da1e45b740f3 Mon Sep 17 00:00:00 2001 From: Austin Date: Mon, 10 Feb 2025 18:58:02 -0500 Subject: [PATCH 07/21] meshtasticd: include `.hidden` (.git) dirs in pio-deps (#6028) --- .github/workflows/package_pio_deps.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/package_pio_deps.yml b/.github/workflows/package_pio_deps.yml index 38c0e8104..9f535b7b1 100644 --- a/.github/workflows/package_pio_deps.yml +++ b/.github/workflows/package_pio_deps.yml @@ -60,5 +60,6 @@ jobs: with: name: platformio-deps-${{ inputs.pio_env }}-${{ steps.version.outputs.long }} overwrite: true + include-hidden-files: true path: | pio/* From d1fa27d3537d5b78d0af96fdbcbec580dee36b6a Mon Sep 17 00:00:00 2001 From: Austin Date: Mon, 10 Feb 2025 21:35:06 -0500 Subject: [PATCH 08/21] small fix: don't junk the zip for pio-deps (#6029) --- .github/workflows/main_matrix.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main_matrix.yml b/.github/workflows/main_matrix.yml index 1dc177cc6..7062ef525 100644 --- a/.github/workflows/main_matrix.yml +++ b/.github/workflows/main_matrix.yml @@ -335,7 +335,7 @@ jobs: working-directory: output run: | zip -j -9 -r ./meshtasticd-${{ steps.version.outputs.deb }}-src.zip ./debian-src - zip -j -9 -r ./platformio-deps-native-${{ steps.version.outputs.long }}.zip ./pio-deps-native + zip -9 -r ./platformio-deps-native-${{ steps.version.outputs.long }}.zip ./pio-deps-native # For diagnostics - name: Display structure of downloaded files From 7fdd262d55bd694fe9a347ab8c946bd080bb5bce Mon Sep 17 00:00:00 2001 From: nwilde1590 Date: Tue, 11 Feb 2025 00:02:21 -0600 Subject: [PATCH 09/21] Added custom OCV array values for T1000-E (#6031) --- src/power.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/power.h b/src/power.h index 176e16ee5..e9c0deb7c 100644 --- a/src/power.h +++ b/src/power.h @@ -24,6 +24,8 @@ #define OCV_ARRAY 1400, 1300, 1280, 1270, 1260, 1250, 1240, 1230, 1210, 1150, 1000 #elif defined(CELL_TYPE_LTO) #define OCV_ARRAY 2700, 2560, 2540, 2520, 2500, 2460, 2420, 2400, 2380, 2320, 1500 +#elif defined(TRACKER_T1000_E) +#define OCV_ARRAY 4190, 4078, 4017, 3969, 3887, 3818, 3798, 3791, 3766, 3712, 3100 #else // LiIon #define OCV_ARRAY 4190, 4050, 3990, 3890, 3800, 3720, 3630, 3530, 3420, 3300, 3100 #endif From eb650a6adbc4a83ca1df909cec80dd6a56dfd2a9 Mon Sep 17 00:00:00 2001 From: Manuel <71137295+mverch67@users.noreply.github.com> Date: Tue, 11 Feb 2025 17:34:37 +0100 Subject: [PATCH 10/21] set TCXO to 2.4V (#6036) --- variants/seeed-sensecap-indicator/variant.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/variants/seeed-sensecap-indicator/variant.h b/variants/seeed-sensecap-indicator/variant.h index c5fc685cd..58eed7d96 100644 --- a/variants/seeed-sensecap-indicator/variant.h +++ b/variants/seeed-sensecap-indicator/variant.h @@ -71,7 +71,7 @@ #define SX126X_DIO2_AS_RF_SWITCH #define TCXO_OPTIONAL // handle Indicator V1 and V2 -#define SX126X_DIO3_TCXO_VOLTAGE 1.8 +#define SX126X_DIO3_TCXO_VOLTAGE 2.4 #define USE_VIRTUAL_KEYBOARD 1 #define DISPLAY_CLOCK_FRAME 1 From 495f69cf907d03619289e8f6b8563a91fcc9a5e7 Mon Sep 17 00:00:00 2001 From: Austin Date: Tue, 11 Feb 2025 19:57:23 -0500 Subject: [PATCH 11/21] Trunk: Trailing commas begone! (#6038) --- .trunk/configs/.prettierrc | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 .trunk/configs/.prettierrc diff --git a/.trunk/configs/.prettierrc b/.trunk/configs/.prettierrc new file mode 100644 index 000000000..edf9dbc9c --- /dev/null +++ b/.trunk/configs/.prettierrc @@ -0,0 +1,10 @@ +{ + "overrides": [ + { + "files": "userPrefs.jsonc", + "options": { + "trailingComma": "none" + } + } + ] +} From 01935ea35e1c2c1bcdb51757e63751e06a5d1899 Mon Sep 17 00:00:00 2001 From: porkcube Date: Fri, 14 Feb 2025 07:50:28 -0500 Subject: [PATCH 12/21] Add XIAO nRF52840 + Wio SX1262 DIY Variant (#5976) * added xiao nRF52840 + xiao wio sx1262 DIY variant * fix path / make buildy buildy * pcf cruft from personal hw --------- Co-authored-by: Ben Meadors --- variants/diy/platformio.ini | 16 +- .../seeed-xiao-nrf52840-wio-sx1262/README.md | 43 ++++ .../variant.cpp | 55 +++++ .../seeed-xiao-nrf52840-wio-sx1262/variant.h | 188 ++++++++++++++++++ 4 files changed, 301 insertions(+), 1 deletion(-) create mode 100644 variants/diy/seeed-xiao-nrf52840-wio-sx1262/README.md create mode 100644 variants/diy/seeed-xiao-nrf52840-wio-sx1262/variant.cpp create mode 100644 variants/diy/seeed-xiao-nrf52840-wio-sx1262/variant.h diff --git a/variants/diy/platformio.ini b/variants/diy/platformio.ini index b7f3f6a92..229f48bbf 100644 --- a/variants/diy/platformio.ini +++ b/variants/diy/platformio.ini @@ -70,6 +70,20 @@ lib_deps = ${nrf52840_base.lib_deps} debug_tool = jlink +; Seeed XIAO nRF52840 + XIAO Wio SX1262 DIY +[env:seeed-xiao-nrf52840-wio-sx1262] +board = xiao_ble_sense +extends = nrf52840_base +board_level = extra +build_flags = ${nrf52840_base.build_flags} -Ivariants/diy/seeed-xiao-nrf52840-wio-sx1262 -D PRIVATE_HW + -Isrc/platform/nrf52/softdevice -Isrc/platform/nrf52/softdevice/nrf52 + -L "${platformio.libdeps_dir}/${this.__env__}/bsec2/src/cortex-m4/fpv4-sp-d16-hard" +board_build.ldscript = src/platform/nrf52/nrf52840_s140_v7.ld +build_src_filter = ${nrf52_base.build_src_filter} +<../variants/diy/seeed-xiao-nrf52840-wio-sx1262> +lib_deps = + ${nrf52840_base.lib_deps} +debug_tool = jlink + ; NanoVHF T-Energy-S3 + E22(0)-xxxM - DIY [env:t-energy-s3_e22] extends = esp32s3_base @@ -86,4 +100,4 @@ build_flags = -D BOARD_HAS_PSRAM -D ARDUINO_USB_MODE=0 -D ARDUINO_USB_CDC_ON_BOOT=1 - -I variants/diy/t-energy-s3_e22 + -I variants/diy/t-energy-s3_e22 \ No newline at end of file diff --git a/variants/diy/seeed-xiao-nrf52840-wio-sx1262/README.md b/variants/diy/seeed-xiao-nrf52840-wio-sx1262/README.md new file mode 100644 index 000000000..194c53434 --- /dev/null +++ b/variants/diy/seeed-xiao-nrf52840-wio-sx1262/README.md @@ -0,0 +1,43 @@ +# XIAO nRF52840 + XIAO Wio SX1262 + +For a mere doubling in price you too can swap out the XIAO ESP32C3 for a XIAO nRF52840, stack the Wio SX1262 radio board either above or underneath the nRF52840, solder the pins, and achieve a massive improvement in battery life! + +I'm not really sure why else you would want to as the ESP32C3 is perfectly cromulent, easily connects to the Wio SX1262 via the B2B connector and has an onboard IPEX connector for the included Bluetooth antenna. So you'll also lose BT range, but you will also have working ADC for the battery in Meshtastic and also have an ESP32C3 to use for something else! + +If you're still reading you are clearly gonna do it anyway, so...mount the Wio SX1262 either on top or underneath depending on your preference. The `variant.h` will work with either configuration though it does map the Wio SX1262's button to nRF52840 Pin `D5` as it can still be used as a user button and it's nice to be able to gracefully shutdown a node by holding it down for 5 seconds. + +If you do decide to wire up the button, orient it so looking straight-down at the Wio SX1262 the radio chip is at the bottom, button in the middle and the hole is at the top - the **left** side of the button should be soldered to `GND` (e.g. the 2nd pin down the top on the **right** row of pins) and the **right** side of the button should be soldered to `D5` (e.g. the 2nd pin up from the button on the **left** row of pins.). This mirrors the original wiring and wiring it in reverse could end up connecting GND to voltage and that's no beuno. + +Serial Pins remain available on `D6` (TX) and `D7` (RX) should you want to use them, The same pins could be repurposed for `i2c` if you would like to have that instead of serial, in `variant.h` you would just need to change: + +```c++ +// RX and TX pins +#define PIN_SERIAL1_RX (6) +#define PIN_SERIAL1_TX (7) +``` + +to + +```c++ +// RX and TX pins +#define PIN_SERIAL1_RX (-1) +#define PIN_SERIAL1_TX (-1) +``` + +and + +```c++ +#define PIN_WIRE_SDA (-1) +#define PIN_WIRE_SCL (-1) +// #define PIN_WIRE_SDA (6) +// #define PIN_WIRE_SCL (7) +``` + +to + +```c++ +#define PIN_WIRE_SDA (6) +#define PIN_WIRE_SCL (7) +``` + +If you wanted both serial and i2c you could even go so far as to use the pads for the PDM mic which is missing on the non-sense board (`P1.00` / `P0.16`)... or move up to the nRF52840 Plus which has even more pins available but hasn't been checked/confirmed if it follows the same pin mapping as the non-plus. diff --git a/variants/diy/seeed-xiao-nrf52840-wio-sx1262/variant.cpp b/variants/diy/seeed-xiao-nrf52840-wio-sx1262/variant.cpp new file mode 100644 index 000000000..2c6c3e539 --- /dev/null +++ b/variants/diy/seeed-xiao-nrf52840-wio-sx1262/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/diy/seeed-xiao-nrf52840-wio-sx1262/variant.h b/variants/diy/seeed-xiao-nrf52840-wio-sx1262/variant.h new file mode 100644 index 000000000..d5dfc3fab --- /dev/null +++ b/variants/diy/seeed-xiao-nrf52840-wio-sx1262/variant.h @@ -0,0 +1,188 @@ +// basically xiao_ble with pins remapped for: +// Seeed XIAO nRF52840 : https://www.seeedstudio.com/Seeed-XIAO-BLE-nRF52840-p-5201.html +// Seeed Wio SX1626 : https://www.seeedstudio.com/Wio-SX1262-with-XIAO-ESP32S3-p-5982.html + +#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 + +/*---------------------------------------------------------------------------- + * 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 + +// XIAO Wio-SX1262 Shield User button +#define PIN_BUTTON1 5 +#define BUTTON_NEED_PULLUP + +// 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) + +// RX and TX pins +#define PIN_SERIAL1_RX (6) +#define PIN_SERIAL1_TX (7) +// complains if not defined +#define PIN_SERIAL2_RX (-1) +#define PIN_SERIAL2_TX (-1) + +// 4 is used as RF_SW and 5 for USR button so... +#define PIN_WIRE_SDA (-1) +#define PIN_WIRE_SCL (-1) +// #define PIN_WIRE_SDA (6) +// #define PIN_WIRE_SCL (7) + +static const uint8_t SDA = PIN_WIRE_SDA; +static const uint8_t SCL = PIN_WIRE_SCL; + +// SPI SX1262 +// ---------- +#define SPI_SX1262 +#ifdef SPI_SX1262 +#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 = D3; +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 D3 +#define SX126X_DIO1 D0 +#define SX126X_BUSY D1 +#define SX126X_RESET D2 + +// DIO2 controlls an antenna switch and the TCXO voltage is controlled by DIO3 +#define SX126X_DIO2_AS_RF_SWITCH +#define SX126X_RXEN 38 +#define SX126X_TXEN RADIOLIB_NC +#define SX126X_DIO3_TCXO_VOLTAGE 1.8 +#define SX126X_DIO3_TCXO_VOLTAGE 1.8 +#endif + +// Wire Interfaces +// ------------------- +#define WIRE_INTERFACES_COUNT 1 // 2 + +// Sense version has IMU and PDM Mic +// #define XIAO_SENSE +#ifndef XIAO_SENSE +// 6 DoF IMU +#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) +#endif + +// 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 +// ------- +// 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 BAT_READ 14 +#define BATTERY_SENSE_RESOLUTION_BITS 10 +#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 From 9b46cb4ef08688a2f424c76d8425561e4f5db844 Mon Sep 17 00:00:00 2001 From: Woutvstk <119763111+Woutvstk@users.noreply.github.com> Date: Fri, 14 Feb 2025 19:53:22 +0100 Subject: [PATCH 13/21] Rak4631 remove spi1 (#6042) * Removed non-existant SPI1 interface on rak4631 * trunk fmt --- src/detect/einkScan.h | 16 ++++++++-------- variants/rak4631/variant.h | 18 +++++++----------- 2 files changed, 15 insertions(+), 19 deletions(-) diff --git a/src/detect/einkScan.h b/src/detect/einkScan.h index d20c7b6e5..5bc218d00 100644 --- a/src/detect/einkScan.h +++ b/src/detect/einkScan.h @@ -6,28 +6,28 @@ void d_writeCommand(uint8_t c) { - SPI1.beginTransaction(SPISettings(4000000, MSBFIRST, SPI_MODE0)); + SPI.beginTransaction(SPISettings(4000000, MSBFIRST, SPI_MODE0)); if (PIN_EINK_DC >= 0) digitalWrite(PIN_EINK_DC, LOW); if (PIN_EINK_CS >= 0) digitalWrite(PIN_EINK_CS, LOW); - SPI1.transfer(c); + SPI.transfer(c); if (PIN_EINK_CS >= 0) digitalWrite(PIN_EINK_CS, HIGH); if (PIN_EINK_DC >= 0) digitalWrite(PIN_EINK_DC, HIGH); - SPI1.endTransaction(); + SPI.endTransaction(); } void d_writeData(uint8_t d) { - SPI1.beginTransaction(SPISettings(4000000, MSBFIRST, SPI_MODE0)); + SPI.beginTransaction(SPISettings(4000000, MSBFIRST, SPI_MODE0)); if (PIN_EINK_CS >= 0) digitalWrite(PIN_EINK_CS, LOW); - SPI1.transfer(d); + SPI.transfer(d); if (PIN_EINK_CS >= 0) digitalWrite(PIN_EINK_CS, HIGH); - SPI1.endTransaction(); + SPI.endTransaction(); } unsigned long d_waitWhileBusy(uint16_t busy_time) @@ -53,7 +53,7 @@ unsigned long d_waitWhileBusy(uint16_t busy_time) void scanEInkDevice(void) { - SPI1.begin(); + SPI.begin(); d_writeCommand(0x22); d_writeData(0x83); d_writeCommand(0x20); @@ -62,6 +62,6 @@ void scanEInkDevice(void) LOG_DEBUG("EInk display found"); else LOG_DEBUG("EInk display not found"); - SPI1.end(); + SPI.end(); } #endif \ No newline at end of file diff --git a/variants/rak4631/variant.h b/variants/rak4631/variant.h index bc5541336..f50f3b880 100644 --- a/variants/rak4631/variant.h +++ b/variants/rak4631/variant.h @@ -107,15 +107,11 @@ static const uint8_t AREF = PIN_AREF; /* * SPI Interfaces */ -#define SPI_INTERFACES_COUNT 2 +#define SPI_INTERFACES_COUNT 1 -#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) +#define PIN_SPI_MISO (29) +#define PIN_SPI_MOSI (30) +#define PIN_SPI_SCK (3) static const uint8_t SS = 42; static const uint8_t MOSI = PIN_SPI_MOSI; @@ -130,8 +126,8 @@ static const uint8_t SCK = PIN_SPI_SCK; #define PIN_EINK_BUSY (0 + 4) #define PIN_EINK_DC (0 + 17) #define PIN_EINK_RES (-1) -#define PIN_EINK_SCLK (0 + 3) -#define PIN_EINK_MOSI (0 + 30) // also called SDI +#define PIN_EINK_SCLK PIN_SPI_SCK +#define PIN_EINK_MOSI PIN_SPI_MOSI // also called SDI // #define USE_EINK @@ -259,7 +255,7 @@ SO GPIO 39/TXEN MAY NOT BE DEFINED FOR SUCCESSFUL OPERATION OF THE SX1262 - TG #define PIN_ETHERNET_RESET 21 #define PIN_ETHERNET_SS PIN_EINK_CS -#define ETH_SPI_PORT SPI1 +#define ETH_SPI_PORT SPI #define AQ_SET_PIN 10 #ifdef __cplusplus From c83ffd4911f1edb8cb437db97346c40ac630e245 Mon Sep 17 00:00:00 2001 From: Eric Severance Date: Fri, 14 Feb 2025 17:19:50 -0800 Subject: [PATCH 14/21] Consider the MQTT TLS remote IP when enabled. (#6058) --- src/mqtt/MQTT.cpp | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/src/mqtt/MQTT.cpp b/src/mqtt/MQTT.cpp index f808a66ef..6043daa34 100644 --- a/src/mqtt/MQTT.cpp +++ b/src/mqtt/MQTT.cpp @@ -412,36 +412,28 @@ void MQTT::reconnect() const char *serverAddr = default_mqtt_address; const char *mqttUsername = default_mqtt_username; const char *mqttPassword = default_mqtt_password; + MQTTClient *clientConnection = mqttClient.get(); if (*moduleConfig.mqtt.address) { serverAddr = moduleConfig.mqtt.address; mqttUsername = moduleConfig.mqtt.username; mqttPassword = moduleConfig.mqtt.password; } -#if HAS_WIFI && !defined(ARCH_PORTDUINO) -#if !defined(CONFIG_IDF_TARGET_ESP32C6) +#if HAS_WIFI && !defined(ARCH_PORTDUINO) && !defined(CONFIG_IDF_TARGET_ESP32C6) if (moduleConfig.mqtt.tls_enabled) { // change default for encrypted to 8883 try { serverPort = 8883; wifiSecureClient.setInsecure(); - - pubSub.setClient(wifiSecureClient); LOG_INFO("Use TLS-encrypted session"); + clientConnection = &wifiSecureClient; } catch (const std::exception &e) { LOG_ERROR("MQTT ERROR: %s", e.what()); } } else { LOG_INFO("Use non-TLS-encrypted session"); - pubSub.setClient(*mqttClient); } -#else - pubSub.setClient(*mqttClient); #endif -#elif HAS_NETWORKING - pubSub.setClient(*mqttClient); -#endif - std::pair hostAndPort = parseHostAndPort(serverAddr, serverPort); serverAddr = hostAndPort.first.c_str(); serverPort = hostAndPort.second; @@ -451,13 +443,14 @@ void MQTT::reconnect() LOG_INFO("Connect directly to MQTT server %s, port: %d, username: %s, password: %s", serverAddr, serverPort, mqttUsername, mqttPassword); + pubSub.setClient(*clientConnection); bool connected = pubSub.connect(owner.id, mqttUsername, mqttPassword); if (connected) { LOG_INFO("MQTT connected"); enabled = true; // Start running background process again runASAP = true; reconnectCount = 0; - isMqttServerAddressPrivate = isPrivateIpAddress(mqttClient->remoteIP()); + isMqttServerAddressPrivate = isPrivateIpAddress(clientConnection->remoteIP()); publishNodeInfo(); sendSubscriptions(); From 50b7d6a0f7e7bac8766a8c467a9a5afad332b072 Mon Sep 17 00:00:00 2001 From: Eric Severance Date: Fri, 14 Feb 2025 18:32:41 -0800 Subject: [PATCH 15/21] Establish MQTT connection only from MQTT::runOnce (#6057) Co-authored-by: Ben Meadors --- src/mesh/eth/ethClient.cpp | 9 --------- src/mesh/wifi/WiFiAPClient.cpp | 9 --------- src/mqtt/MQTT.h | 8 ++++---- test/test_mqtt/MQTT.cpp | 3 ++- 4 files changed, 6 insertions(+), 23 deletions(-) diff --git a/src/mesh/eth/ethClient.cpp b/src/mesh/eth/ethClient.cpp index 24c4f0db1..70c6e3fe4 100644 --- a/src/mesh/eth/ethClient.cpp +++ b/src/mesh/eth/ethClient.cpp @@ -5,9 +5,6 @@ #include "configuration.h" #include "main.h" #include "mesh/api/ethServerAPI.h" -#if !MESHTASTIC_EXCLUDE_MQTT -#include "mqtt/MQTT.h" -#endif #include "target_specific.h" #include #include @@ -72,12 +69,6 @@ static int32_t reconnectETH() ethStartupComplete = true; } -#if !MESHTASTIC_EXCLUDE_MQTT - // FIXME this is kinda yucky, instead we should just have an observable for 'wifireconnected' - if (mqtt && !moduleConfig.mqtt.proxy_to_client_enabled && !mqtt->isConnectedDirectly()) { - mqtt->reconnect(); - } -#endif } #ifndef DISABLE_NTP diff --git a/src/mesh/wifi/WiFiAPClient.cpp b/src/mesh/wifi/WiFiAPClient.cpp index 41de89794..d4a5dbf94 100644 --- a/src/mesh/wifi/WiFiAPClient.cpp +++ b/src/mesh/wifi/WiFiAPClient.cpp @@ -7,9 +7,6 @@ #include "main.h" #include "mesh/api/WiFiServerAPI.h" -#if !MESHTASTIC_EXCLUDE_MQTT -#include "mqtt/MQTT.h" -#endif #include "target_specific.h" #include #include @@ -111,12 +108,6 @@ static void onNetworkConnected() #endif APStartupComplete = true; } - - // FIXME this is kinda yucky, instead we should just have an observable for 'wifireconnected' -#ifndef MESHTASTIC_EXCLUDE_MQTT - if (mqtt) - mqtt->reconnect(); -#endif } static int32_t reconnectWiFi() diff --git a/src/mqtt/MQTT.h b/src/mqtt/MQTT.h index cf52ad877..42157fda9 100644 --- a/src/mqtt/MQTT.h +++ b/src/mqtt/MQTT.h @@ -47,10 +47,6 @@ class MQTT : private concurrency::OSThread */ void onSend(const meshtastic_MeshPacket &mp_encrypted, const meshtastic_MeshPacket &mp_decoded, ChannelIndex chIndex); - /** Attempt to connect to server if necessary - */ - void reconnect(); - bool isConnectedDirectly(); bool publish(const char *topic, const char *payload, bool retained); @@ -115,6 +111,10 @@ class MQTT : private concurrency::OSThread */ bool wantsLink() const; + /** Attempt to connect to server if necessary + */ + void reconnect(); + /** Tell the server what subscriptions we want (based on channels.downlink_enabled) */ void sendSubscriptions(); diff --git a/test/test_mqtt/MQTT.cpp b/test/test_mqtt/MQTT.cpp index 55ba479e2..3a4625aed 100644 --- a/test/test_mqtt/MQTT.cpp +++ b/test/test_mqtt/MQTT.cpp @@ -242,6 +242,7 @@ class MQTTUnitTest : public MQTT mqttClient.release(); delete pubsub; } + using MQTT::reconnect; int queueSize() { return mqttQueue.numUsed(); } void reportToMap(std::optional precision = std::nullopt) { @@ -488,7 +489,7 @@ void test_reconnectProxyDoesNotReconnectMqtt(void) moduleConfig.mqtt.proxy_to_client_enabled = true; MQTTUnitTest::restart(); - mqtt->reconnect(); + unitTest->reconnect(); TEST_ASSERT_FALSE(pubsub->connected_); } From 8c9947b05c00e8137200a2b9093cbb19edd2aaa9 Mon Sep 17 00:00:00 2001 From: GUVWAF <78759985+GUVWAF@users.noreply.github.com> Date: Sat, 15 Feb 2025 14:55:51 +0100 Subject: [PATCH 16/21] Allow NeighborInfo on non-default frequency slot (#6061) --- src/modules/NeighborInfoModule.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/modules/NeighborInfoModule.cpp b/src/modules/NeighborInfoModule.cpp index fb658421d..eebf428a4 100644 --- a/src/modules/NeighborInfoModule.cpp +++ b/src/modules/NeighborInfoModule.cpp @@ -121,7 +121,8 @@ Will be used for broadcast. */ int32_t NeighborInfoModule::runOnce() { - if (moduleConfig.neighbor_info.transmit_over_lora && !channels.isDefaultChannel(channels.getPrimaryIndex()) && + if (moduleConfig.neighbor_info.transmit_over_lora && + (!channels.isDefaultChannel(channels.getPrimaryIndex()) || !RadioInterface::uses_default_frequency_slot) && airTime->isTxAllowedChannelUtil(true) && airTime->isTxAllowedAirUtil()) { sendNeighborInfo(NODENUM_BROADCAST, false); } else { From 2f6cd021115d0e63975cf8248bb550c76a7497a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20Gjels=C3=B8?= <36234524+gjelsoe@users.noreply.github.com> Date: Sat, 15 Feb 2025 15:06:41 +0100 Subject: [PATCH 17/21] Typo for Bandit button LEDs (#6053) Changed Button 2 LED index define from BUTTON1_COLOR_INDEX to correct BUTTON2_COLOR_INDEX --- src/AmbientLightingThread.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/AmbientLightingThread.h b/src/AmbientLightingThread.h index 600583348..c487f9d53 100644 --- a/src/AmbientLightingThread.h +++ b/src/AmbientLightingThread.h @@ -153,7 +153,7 @@ class AmbientLightingThread : public concurrency::OSThread pixels.fill(BUTTON1_COLOR, BUTTON1_COLOR_INDEX, 1); #endif #if defined(BUTTON2_COLOR) && defined(BUTTON2_COLOR_INDEX) - pixels.fill(BUTTON2_COLOR, BUTTON1_COLOR_INDEX, 1); + pixels.fill(BUTTON2_COLOR, BUTTON2_COLOR_INDEX, 1); #endif #endif pixels.show(); From 27fea5fc0724bbd1d6142f684b529807a91211d2 Mon Sep 17 00:00:00 2001 From: GUVWAF <78759985+GUVWAF@users.noreply.github.com> Date: Sat, 15 Feb 2025 16:06:10 +0100 Subject: [PATCH 18/21] Fix STM32WL TCXO setting; enable logs and modules (#6063) Co-authored-by: Ben Meadors --- arch/stm32/stm32.ini | 10 ++++++++-- src/mesh/STM32WLE5JCInterface.cpp | 5 ++++- src/mesh/STM32WLE5JCInterface.h | 3 --- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/arch/stm32/stm32.ini b/arch/stm32/stm32.ini index 7e211496d..46f41db3a 100644 --- a/arch/stm32/stm32.ini +++ b/arch/stm32/stm32.ini @@ -11,9 +11,15 @@ build_flags = ${arduino_base.build_flags} -flto -Isrc/platform/stm32wl -g - -DMESHTASTIC_MINIMIZE_BUILD + -DMESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR + -DMESHTASTIC_EXCLUDE_INPUTBROKER + -DMESHTASTIC_EXCLUDE_I2C + -DMESHTASTIC_EXCLUDE_POWERMON + -DMESHTASTIC_EXCLUDE_SCREEN + -DMESHTASTIC_EXCLUDE_MQTT + -DMESHTASTIC_EXCLUDE_BLUETOOTH + -DMESHTASTIC_EXCLUDE_PKI -DMESHTASTIC_EXCLUDE_GPS - -DDEBUG_MUTE ; -DVECT_TAB_OFFSET=0x08000000 -DconfigUSE_CMSIS_RTOS_V2=1 ; -DSPI_MODE_0=SPI_MODE0 diff --git a/src/mesh/STM32WLE5JCInterface.cpp b/src/mesh/STM32WLE5JCInterface.cpp index 499db9176..ad1f675b6 100644 --- a/src/mesh/STM32WLE5JCInterface.cpp +++ b/src/mesh/STM32WLE5JCInterface.cpp @@ -18,6 +18,9 @@ bool STM32WLE5JCInterface::init() { RadioLibInterface::init(); + // https://github.com/Seeed-Studio/LoRaWan-E5-Node/blob/main/Middlewares/Third_Party/SubGHz_Phy/stm32_radio_driver/radio_driver.c + setTCXOVoltage(1.7); + lora.setRfSwitchTable(rfswitch_pins, rfswitch_table); if (power > STM32WLx_MAX_POWER) // This chip has lower power limits than some @@ -39,4 +42,4 @@ bool STM32WLE5JCInterface::init() return res == RADIOLIB_ERR_NONE; } -#endif // ARCH_STM32WL +#endif // ARCH_STM32WL \ No newline at end of file diff --git a/src/mesh/STM32WLE5JCInterface.h b/src/mesh/STM32WLE5JCInterface.h index fad793332..0c8140290 100644 --- a/src/mesh/STM32WLE5JCInterface.h +++ b/src/mesh/STM32WLE5JCInterface.h @@ -16,9 +16,6 @@ class STM32WLE5JCInterface : public SX126xInterface virtual bool init() override; }; -// https://github.com/Seeed-Studio/LoRaWan-E5-Node/blob/main/Middlewares/Third_Party/SubGHz_Phy/stm32_radio_driver/radio_driver.c -static const float tcxoVoltage = 1.7; - /* https://wiki.seeedstudio.com/LoRa-E5_STM32WLE5JC_Module/ * Wio-E5 module ONLY transmits through RFO_HP * Receive: PA4=1, PA5=0 From 4407d9e04023a693205aefa36c754d11002c1f0e Mon Sep 17 00:00:00 2001 From: porkcube Date: Sun, 16 Feb 2025 07:39:48 -0500 Subject: [PATCH 19/21] assigning SDA/SCL so it actually works 8| (#6065) --- variants/diy/seeed-xiao-nrf52840-wio-sx1262/variant.h | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/variants/diy/seeed-xiao-nrf52840-wio-sx1262/variant.h b/variants/diy/seeed-xiao-nrf52840-wio-sx1262/variant.h index d5dfc3fab..7a76727f2 100644 --- a/variants/diy/seeed-xiao-nrf52840-wio-sx1262/variant.h +++ b/variants/diy/seeed-xiao-nrf52840-wio-sx1262/variant.h @@ -84,17 +84,15 @@ static const uint8_t A5 = PIN_A5; #define PIN_NFC2 (31) // RX and TX pins -#define PIN_SERIAL1_RX (6) -#define PIN_SERIAL1_TX (7) +#define PIN_SERIAL1_RX (-1) +#define PIN_SERIAL1_TX (-1) // complains if not defined #define PIN_SERIAL2_RX (-1) #define PIN_SERIAL2_TX (-1) // 4 is used as RF_SW and 5 for USR button so... -#define PIN_WIRE_SDA (-1) -#define PIN_WIRE_SCL (-1) -// #define PIN_WIRE_SDA (6) -// #define PIN_WIRE_SCL (7) +#define PIN_WIRE_SDA (6) +#define PIN_WIRE_SCL (7) static const uint8_t SDA = PIN_WIRE_SDA; static const uint8_t SCL = PIN_WIRE_SCL; From 7648391f91f2b84e367ae2b38220b30936fb45b1 Mon Sep 17 00:00:00 2001 From: Eric Severance Date: Sun, 16 Feb 2025 05:15:30 -0800 Subject: [PATCH 20/21] Reject invalid configuration for the default MQTT server (#6066) * Sanity check configuration for the default MQTT server * Skip for MESHTASTIC_EXCLUDE_MQTT --------- Co-authored-by: Ben Meadors --- src/modules/AdminModule.cpp | 17 ++++++++++++++--- src/modules/AdminModule.h | 2 +- src/mqtt/MQTT.cpp | 27 +++++++++++++++++++++++++-- src/mqtt/MQTT.h | 2 ++ test/test_mqtt/MQTT.cpp | 36 ++++++++++++++++++++++++++++++++++++ 5 files changed, 78 insertions(+), 6 deletions(-) diff --git a/src/modules/AdminModule.cpp b/src/modules/AdminModule.cpp index 7906b410b..530d0b82e 100644 --- a/src/modules/AdminModule.cpp +++ b/src/modules/AdminModule.cpp @@ -162,7 +162,9 @@ bool AdminModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshta case meshtastic_AdminMessage_set_module_config_tag: LOG_INFO("Client set module config"); - handleSetModuleConfig(r->set_module_config); + if (!handleSetModuleConfig(r->set_module_config)) { + myReply = allocErrorResponse(meshtastic_Routing_Error_BAD_REQUEST, &mp); + } break; case meshtastic_AdminMessage_set_channel_tag: @@ -648,15 +650,23 @@ void AdminModule::handleSetConfig(const meshtastic_Config &c) saveChanges(changes, requiresReboot); } -void AdminModule::handleSetModuleConfig(const meshtastic_ModuleConfig &c) +bool AdminModule::handleSetModuleConfig(const meshtastic_ModuleConfig &c) { if (!hasOpenEditTransaction) disableBluetooth(); switch (c.which_payload_variant) { case meshtastic_ModuleConfig_mqtt_tag: +#if MESHTASTIC_EXCLUDE_MQTT + LOG_WARN("Set module config: MESHTASTIC_EXCLUDE_MQTT is defined. Not setting MQTT config"); + return false; +#else LOG_INFO("Set module config: MQTT"); + if (!MQTT::isValidConfig(c.payload_variant.mqtt)) { + return false; + } moduleConfig.has_mqtt = true; moduleConfig.mqtt = c.payload_variant.mqtt; +#endif break; case meshtastic_ModuleConfig_serial_tag: LOG_INFO("Set module config: Serial"); @@ -724,6 +734,7 @@ void AdminModule::handleSetModuleConfig(const meshtastic_ModuleConfig &c) break; } saveChanges(SEGMENT_MODULECONFIG); + return true; } void AdminModule::handleSetChannel(const meshtastic_Channel &cc) @@ -1160,4 +1171,4 @@ void disableBluetooth() nrf52Bluetooth->shutdown(); #endif #endif -} +} \ No newline at end of file diff --git a/src/modules/AdminModule.h b/src/modules/AdminModule.h index ee2ebfd96..12c857e04 100644 --- a/src/modules/AdminModule.h +++ b/src/modules/AdminModule.h @@ -50,7 +50,7 @@ class AdminModule : public ProtobufModule, public Obser void handleSetOwner(const meshtastic_User &o); void handleSetChannel(const meshtastic_Channel &cc); void handleSetConfig(const meshtastic_Config &c); - void handleSetModuleConfig(const meshtastic_ModuleConfig &c); + bool handleSetModuleConfig(const meshtastic_ModuleConfig &c); void handleSetChannel(); void handleSetHamMode(const meshtastic_HamParameters &req); void handleStoreDeviceUIConfig(const meshtastic_DeviceUIConfig &uicfg); diff --git a/src/mqtt/MQTT.cpp b/src/mqtt/MQTT.cpp index 6043daa34..67eba82a6 100644 --- a/src/mqtt/MQTT.cpp +++ b/src/mqtt/MQTT.cpp @@ -41,6 +41,7 @@ MQTT *mqtt; namespace { constexpr int reconnectMax = 5; +constexpr uint16_t mqttPort = 1883; // FIXME - this size calculation is super sloppy, but it will go away once we dynamically alloc meshpackets static uint8_t bytes[meshtastic_MqttClientProxyMessage_size + 30]; // 12 for channel name and 16 for nodeid @@ -245,6 +246,11 @@ std::pair parseHostAndPort(String server, uint16_t port = 0) } return std::make_pair(std::move(server), port); } + +bool isDefaultServer(const String &host) +{ + return host.length() == 0 || host == default_mqtt_address; +} } // namespace void MQTT::mqttCallback(char *topic, byte *payload, unsigned int length) @@ -324,7 +330,7 @@ MQTT::MQTT() : concurrency::OSThread("mqtt"), mqttQueue(MAX_MQTT_QUEUE) } String host = parseHostAndPort(moduleConfig.mqtt.address).first; - isConfiguredForDefaultServer = host.length() == 0 || host == default_mqtt_address; + isConfiguredForDefaultServer = isDefaultServer(host); IPAddress ip; isMqttServerAddressPrivate = ip.fromString(host.c_str()) && isPrivateIpAddress(ip); @@ -408,7 +414,7 @@ void MQTT::reconnect() } #if HAS_NETWORKING // Defaults - int serverPort = 1883; + int serverPort = mqttPort; const char *serverAddr = default_mqtt_address; const char *mqttUsername = default_mqtt_username; const char *mqttPassword = default_mqtt_password; @@ -561,6 +567,23 @@ int32_t MQTT::runOnce() return 30000; } +bool MQTT::isValidConfig(const meshtastic_ModuleConfig_MQTTConfig &config) +{ + String host; + uint16_t port; + std::tie(host, port) = parseHostAndPort(config.address, mqttPort); + const bool defaultServer = isDefaultServer(host); + if (defaultServer && config.tls_enabled) { + LOG_ERROR("Invalid MQTT config: TLS was enabled, but the default server does not support TLS"); + return false; + } + if (defaultServer && port != mqttPort) { + LOG_ERROR("Invalid MQTT config: Unsupported port '%d' for the default MQTT server", port); + return false; + } + return true; +} + void MQTT::publishNodeInfo() { // TODO: NodeInfo broadcast over MQTT only (NODENUM_BROADCAST_NO_LORA) diff --git a/src/mqtt/MQTT.h b/src/mqtt/MQTT.h index 42157fda9..f7e3864f8 100644 --- a/src/mqtt/MQTT.h +++ b/src/mqtt/MQTT.h @@ -61,6 +61,8 @@ class MQTT : private concurrency::OSThread bool isUsingDefaultServer() { return isConfiguredForDefaultServer; } + static bool isValidConfig(const meshtastic_ModuleConfig_MQTTConfig &config); + protected: struct QueueEntry { std::string topic; diff --git a/test/test_mqtt/MQTT.cpp b/test/test_mqtt/MQTT.cpp index 3a4625aed..c00922548 100644 --- a/test/test_mqtt/MQTT.cpp +++ b/test/test_mqtt/MQTT.cpp @@ -800,6 +800,38 @@ void test_customMqttRoot(void) [] { return pubsub->subscriptions_.count("custom/2/e/test/+") && pubsub->subscriptions_.count("custom/2/e/PKI/+"); })); } +// Empty configuration is valid. +void test_configurationEmptyIsValid(void) +{ + meshtastic_ModuleConfig_MQTTConfig config; + + TEST_ASSERT_TRUE(MQTT::isValidConfig(config)); +} + +// Configuration with the default server is valid. +void test_configWithDefaultServer(void) +{ + meshtastic_ModuleConfig_MQTTConfig config = {.address = default_mqtt_address}; + + TEST_ASSERT_TRUE(MQTT::isValidConfig(config)); +} + +// Configuration with the default server and port 8888 is invalid. +void test_configWithDefaultServerAndInvalidPort(void) +{ + meshtastic_ModuleConfig_MQTTConfig config = {.address = default_mqtt_address ":8888"}; + + TEST_ASSERT_FALSE(MQTT::isValidConfig(config)); +} + +// Configuration with the default server and tls_enabled = true is invalid. +void test_configWithDefaultServerAndInvalidTLSEnabled(void) +{ + meshtastic_ModuleConfig_MQTTConfig config = {.tls_enabled = true}; + + TEST_ASSERT_FALSE(MQTT::isValidConfig(config)); +} + void setup() { initializeTestEnvironment(); @@ -843,6 +875,10 @@ void setup() RUN_TEST(test_enabled); RUN_TEST(test_disabled); RUN_TEST(test_customMqttRoot); + RUN_TEST(test_configurationEmptyIsValid); + RUN_TEST(test_configWithDefaultServer); + RUN_TEST(test_configWithDefaultServerAndInvalidPort); + RUN_TEST(test_configWithDefaultServerAndInvalidTLSEnabled); exit(UNITY_END()); } #else From 7eb77276cdeca95b4a04360333b357921a6ca141 Mon Sep 17 00:00:00 2001 From: A_Ponzano Date: Mon, 17 Feb 2025 02:49:17 +0100 Subject: [PATCH 21/21] Add support for new NRF52 board, MeshLink (#5736) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add support for MeshLink * Updated, enabled watchdog and added button definition * added eink variant and removed some compile errors * Small board json file edit * Finally got trunk working (somehow?), this is just cleanup with trunk fmt * Various improvements and cleanup. Removed the use of PIN_3V3_En and defined a specific WD_EN pin instead for better clarity. Will do a bit more testing asap to make sure everything still works as intended :) * Enable on-board QSPI Flash * run trunk fmt with clang-format --------- Co-authored-by: Ben Meadors Co-authored-by: Thomas Göttgens Co-authored-by: Austin --- boards/meshlink.json | 52 ++++++++ src/graphics/EInkDisplay2.cpp | 9 ++ src/mesh/generated/meshtastic/mesh.pb.h | 2 +- src/modules/SerialModule.cpp | 8 +- src/platform/nrf52/architecture.h | 2 +- src/platform/nrf52/main-nrf52.cpp | 5 + src/sleep.cpp | 5 +- variants/meshlink/platformio.ini | 30 +++++ variants/meshlink/variant.cpp | 23 ++++ variants/meshlink/variant.h | 153 ++++++++++++++++++++++++ variants/meshlink_eink/platformio.ini | 30 +++++ variants/meshlink_eink/variant.cpp | 23 ++++ variants/meshlink_eink/variant.h | 153 ++++++++++++++++++++++++ 13 files changed, 488 insertions(+), 7 deletions(-) create mode 100644 boards/meshlink.json create mode 100644 variants/meshlink/platformio.ini create mode 100644 variants/meshlink/variant.cpp create mode 100644 variants/meshlink/variant.h create mode 100644 variants/meshlink_eink/platformio.ini create mode 100644 variants/meshlink_eink/variant.cpp create mode 100644 variants/meshlink_eink/variant.h diff --git a/boards/meshlink.json b/boards/meshlink.json new file mode 100644 index 000000000..a608de88a --- /dev/null +++ b/boards/meshlink.json @@ -0,0 +1,52 @@ +{ + "build": { + "arduino": { + "ldscript": "nrf52840_s140_v6.ld" + }, + "core": "nRF5", + "cpu": "cortex-m4", + "extra_flags": "-DMESHLINK -DNRF52840_XXAA", + "f_cpu": "64000000L", + "hwids": [ + ["0x239A", "0x00B3"], + ["0x239A", "0x8029"], + ["0x239A", "0x0029"], + ["0x239A", "0x002A"], + ["0x239A", "0x802A"] + ], + "usb_product": "MeshLink", + "mcu": "nrf52840", + "variant": "meshlink", + "bsp": { + "name": "adafruit" + }, + "softdevice": { + "sd_flags": "-DS140", + "sd_name": "s140", + "sd_version": "6.1.1", + "sd_fwid": "0x00B6" + }, + "bootloader": { + "settings_addr": "0xFF000" + } + }, + "connectivity": ["bluetooth"], + "debug": { + "jlink_device": "nRF52840_xxAA", + "svd_path": "nrf52840.svd" + }, + "frameworks": ["arduino"], + "name": "MeshLink", + "upload": { + "maximum_ram_size": 248832, + "maximum_size": 815104, + "speed": 115200, + "protocol": "nrfutil", + "protocols": ["nrfutil", "jlink", "nrfjprog", "stlink"], + "use_1200bps_touch": true, + "require_upload_port": true, + "wait_for_upload_port": true + }, + "url": "https://www.loraitalia.it", + "vendor": "LoraItalia" +} diff --git a/src/graphics/EInkDisplay2.cpp b/src/graphics/EInkDisplay2.cpp index 6c85582c0..9702b0086 100644 --- a/src/graphics/EInkDisplay2.cpp +++ b/src/graphics/EInkDisplay2.cpp @@ -140,6 +140,15 @@ bool EInkDisplay::connect() adafruitDisplay->setRotation(3); adafruitDisplay->setPartialWindow(0, 0, displayWidth, displayHeight); } +#elif defined(MESHLINK) + { + auto lowLevel = new EINK_DISPLAY_MODEL(PIN_EINK_CS, PIN_EINK_DC, PIN_EINK_RES, PIN_EINK_BUSY, SPI1); + + adafruitDisplay = new GxEPD2_BW(*lowLevel); + adafruitDisplay->init(); + adafruitDisplay->setRotation(3); + adafruitDisplay->setPartialWindow(0, 0, displayWidth, displayHeight); + } #elif defined(RAK4630) || defined(MAKERPYTHON) { if (eink_found) { diff --git a/src/mesh/generated/meshtastic/mesh.pb.h b/src/mesh/generated/meshtastic/mesh.pb.h index 3353a020f..de8a1a353 100644 --- a/src/mesh/generated/meshtastic/mesh.pb.h +++ b/src/mesh/generated/meshtastic/mesh.pb.h @@ -1775,4 +1775,4 @@ extern const pb_msgdesc_t meshtastic_ChunkedPayloadResponse_msg; } /* extern "C" */ #endif -#endif +#endif \ No newline at end of file diff --git a/src/modules/SerialModule.cpp b/src/modules/SerialModule.cpp index bf53b1748..c6a95912b 100644 --- a/src/modules/SerialModule.cpp +++ b/src/modules/SerialModule.cpp @@ -60,7 +60,7 @@ SerialModule *serialModule; SerialModuleRadio *serialModuleRadio; -#if defined(TTGO_T_ECHO) || defined(CANARYONE) +#if defined(TTGO_T_ECHO) || defined(CANARYONE) || defined(MESHLINK) SerialModule::SerialModule() : StreamAPI(&Serial), concurrency::OSThread("Serial") {} static Print *serialPrint = &Serial; #elif defined(CONFIG_IDF_TARGET_ESP32C6) @@ -158,7 +158,7 @@ int32_t SerialModule::runOnce() Serial.begin(baud); Serial.setTimeout(moduleConfig.serial.timeout > 0 ? moduleConfig.serial.timeout : TIMEOUT); } -#elif !defined(TTGO_T_ECHO) && !defined(CANARYONE) +#elif !defined(TTGO_T_ECHO) && !defined(CANARYONE) && !defined(MESHLINK) if (moduleConfig.serial.rxd && moduleConfig.serial.txd) { #ifdef ARCH_RP2040 Serial2.setFIFOSize(RX_BUFFER); @@ -214,7 +214,7 @@ int32_t SerialModule::runOnce() } } -#if !defined(TTGO_T_ECHO) && !defined(CANARYONE) +#if !defined(TTGO_T_ECHO) && !defined(CANARYONE) && !defined(MESHLINK) else if ((moduleConfig.serial.mode == meshtastic_ModuleConfig_SerialConfig_Serial_Mode_WS85)) { processWXSerial(); @@ -416,7 +416,7 @@ uint32_t SerialModule::getBaudRate() */ void SerialModule::processWXSerial() { -#if !defined(TTGO_T_ECHO) && !defined(CANARYONE) && !defined(CONFIG_IDF_TARGET_ESP32C6) +#if !defined(TTGO_T_ECHO) && !defined(CANARYONE) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(MESHLINK) static unsigned int lastAveraged = 0; static unsigned int averageIntervalMillis = 300000; // 5 minutes hard coded. static double dir_sum_sin = 0; diff --git a/src/platform/nrf52/architecture.h b/src/platform/nrf52/architecture.h index ce99244ba..3e4397686 100644 --- a/src/platform/nrf52/architecture.h +++ b/src/platform/nrf52/architecture.h @@ -127,4 +127,4 @@ #if !defined(PIN_SERIAL_RX) && !defined(NRF52840_XXAA) // No serial ports on this board - ONLY use segger in memory console #define USE_SEGGER -#endif +#endif \ No newline at end of file diff --git a/src/platform/nrf52/main-nrf52.cpp b/src/platform/nrf52/main-nrf52.cpp index ad4d7a881..8483d21c6 100644 --- a/src/platform/nrf52/main-nrf52.cpp +++ b/src/platform/nrf52/main-nrf52.cpp @@ -304,6 +304,11 @@ void cpuDeepSleep(uint32_t msecToWake) nrf_gpio_cfg_default(WB_I2C1_SDA); #endif #endif +#ifdef MESHLINK +#ifdef PIN_WD_EN + digitalWrite(PIN_WD_EN, LOW); +#endif +#endif #ifdef HELTEC_MESH_NODE_T114 nrf_gpio_cfg_default(PIN_GPS_PPS); diff --git a/src/sleep.cpp b/src/sleep.cpp index 161b6e107..437d7b88b 100644 --- a/src/sleep.cpp +++ b/src/sleep.cpp @@ -245,6 +245,9 @@ void doDeepSleep(uint32_t msecToWake, bool skipPreflight = false, bool skipSaveN #ifdef PIN_3V3_EN digitalWrite(PIN_3V3_EN, LOW); #endif +#ifdef PIN_WD_EN + digitalWrite(PIN_WD_EN, LOW); +#endif #endif ledBlink.set(false); @@ -530,4 +533,4 @@ void enableLoraInterrupt() } #endif } -#endif +#endif \ No newline at end of file diff --git a/variants/meshlink/platformio.ini b/variants/meshlink/platformio.ini new file mode 100644 index 000000000..180dddd49 --- /dev/null +++ b/variants/meshlink/platformio.ini @@ -0,0 +1,30 @@ +; MeshLink board developed by LoraItalia. NRF52840, eByte E22900M22S (Will also come with other frequencies), 25w MPPT solar charger (5v,12v,18v selectable), support for gps, buzzer, oled or e-ink display, 10 gpios, hardware watchdog +; https://www.loraitalia.it +; firmware for boards with or without oled display +[env:meshlink] +extends = nrf52840_base +board = meshlink +;board_check = true +build_flags = ${nrf52840_base.build_flags} -I variants/meshlink -D MESHLINK + -L "${platformio.libdeps_dir}/${this.__env__}/bsec2/src/cortex-m4/fpv4-sp-d16-hard" + -D GPS_POWER_TOGGLE ; comment this line to disable triple press function on the user button to turn off gps entirely. + -D EINK_DISPLAY_MODEL=GxEPD2_213_B74 + -D EINK_WIDTH=250 + -D EINK_HEIGHT=122 + -D USE_EINK_DYNAMICDISPLAY ; Enable Dynamic EInk + -D EINK_LIMIT_FASTREFRESH=5 ; How many consecutive fast-refreshes are permitted + -D EINK_LIMIT_RATE_BACKGROUND_SEC=30 ; Minimum interval between BACKGROUND updates + -D EINK_LIMIT_RATE_RESPONSIVE_SEC=1 ; Minimum interval between RESPONSIVE updates + -D EINK_LIMIT_GHOSTING_PX=2000 ; (Optional) How much image ghosting is tolerated + -D EINK_BACKGROUND_USES_FAST ; (Optional) Use FAST refresh for both BACKGROUND and RESPONSIVE, until a limit is reached. + -D EINK_HASQUIRK_VICIOUSFASTREFRESH ; Identify that pixels drawn by fast-refresh are harder to clear + + +build_src_filter = ${nrf52_base.build_src_filter} +<../variants/meshlink> +lib_deps = + ${nrf52840_base.lib_deps} + https://github.com/meshtastic/GxEPD2#55f618961db45a23eff0233546430f1e5a80f63a +debug_tool = jlink +; If not set we will default to uploading over serial (first it forces bootloader entry by talking 1200bps to cdcacm) +; Note: as of 6/2013 the serial/bootloader based programming takes approximately 30 seconds +;upload_protocol = jlink \ No newline at end of file diff --git a/variants/meshlink/variant.cpp b/variants/meshlink/variant.cpp new file mode 100644 index 000000000..81a5097c4 --- /dev/null +++ b/variants/meshlink/variant.cpp @@ -0,0 +1,23 @@ +#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() +{ + pinMode(PIN_LED1, OUTPUT); + digitalWrite(PIN_LED1, HIGH); // turn off the white led while booting + // otherwise it will stay lit for several seconds (could be annoying) + +#ifdef PIN_WD_EN + pinMode(PIN_WD_EN, OUTPUT); + digitalWrite(PIN_WD_EN, HIGH); // Enable the Watchdog at boot +#endif +} \ No newline at end of file diff --git a/variants/meshlink/variant.h b/variants/meshlink/variant.h new file mode 100644 index 000000000..54df03691 --- /dev/null +++ b/variants/meshlink/variant.h @@ -0,0 +1,153 @@ +#ifndef _VARIANT_MESHLINK_ +#define _VARIANT_MESHLINK_ +#ifndef MESHLINK +#define MESHLINK +#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 (2) +#define NUM_ANALOG_OUTPUTS (0) + +#define BUTTON_PIN (-1) // If defined, this will be used for user button presses, +#define BUTTON_NEED_PULLUP + +// LEDs +#define PIN_LED1 (24) // Built in white led for status +#define LED_BLUE PIN_LED1 +#define LED_BUILTIN PIN_LED1 + +#define LED_STATE_ON 0 // State when LED is litted +#define LED_INVERTED 1 + +// Testing USB detection +// #define NRF_APM + +/* + * Analog pins + */ +#define PIN_A1 (3) // P0.03/AIN1 +#define ADC_RESOLUTION 14 + +// Other pins +// #define PIN_AREF (2) +// static const uint8_t AREF = PIN_AREF; + +/* + * Serial interfaces + */ +#define PIN_SERIAL1_RX (32 + 8) +#define PIN_SERIAL1_TX (7) + +/* + * SPI Interfaces + */ +#define SPI_INTERFACES_COUNT 2 + +#define PIN_SPI_MISO (8) +#define PIN_SPI_MOSI (32 + 9) +#define PIN_SPI_SCK (11) + +#define PIN_SPI1_MISO (23) +#define PIN_SPI1_MOSI (21) +#define PIN_SPI1_SCK (19) + +static const uint8_t SS = 12; +static const uint8_t MOSI = PIN_SPI_MOSI; +static const uint8_t MISO = PIN_SPI_MISO; +static const uint8_t SCK = PIN_SPI_SCK; + +/* + * eink display pins + */ +// #define USE_EINK + +#define PIN_EINK_CS (15) +#define PIN_EINK_BUSY (16) +#define PIN_EINK_DC (14) +#define PIN_EINK_RES (17) +#define PIN_EINK_SCLK (19) +#define PIN_EINK_MOSI (21) // also called SDI + +/* + * Wire Interfaces + */ +#define WIRE_INTERFACES_COUNT 1 + +#define PIN_WIRE_SDA (1) +#define PIN_WIRE_SCL (27) + +// QSPI Pins +#define PIN_QSPI_SCK 19 +#define PIN_QSPI_CS 22 +#define PIN_QSPI_IO0 21 +#define PIN_QSPI_IO1 23 +#define PIN_QSPI_IO2 32 +#define PIN_QSPI_IO3 20 + +// On-board QSPI Flash +#define EXTERNAL_FLASH_DEVICES W25Q16JVUXIQ +#define EXTERNAL_FLASH_USE_QSPI + +#define USE_SX1262 +#define SX126X_CS (12) +#define SX126X_DIO1 (32 + 1) +#define SX126X_BUSY (32 + 3) +#define SX126X_RESET (6) +// #define SX126X_RXEN (13) +// DIO2 controlls an antenna switch and the TCXO voltage is controlled by DIO3 +#define SX126X_DIO2_AS_RF_SWITCH +#define SX126X_DIO3_TCXO_VOLTAGE 1.8 + +// pin 25 is used to enable or disable the watchdog. This pin has to be disabled when cpu is put to sleep +// otherwise the timer will expire and wd will reboot the cpu +#define PIN_WD_EN (25) + +#define PIN_GPS_PPS (26) // Pulse per second input from the GPS + +#define GPS_TX_PIN PIN_SERIAL1_RX // This is for bits going TOWARDS the CPU +#define GPS_RX_PIN PIN_SERIAL1_TX // This is for bits going TOWARDS the GPS + +// #define GPS_THREAD_INTERVAL 50 + +// Define pin to enable GPS toggle (set GPIO to LOW) via user button triple press +#define PIN_GPS_EN (0) +#define GPS_EN_ACTIVE LOW + +#define PIN_BUZZER (31) // P0.31/AIN7 + +// Battery +// The battery sense is hooked to pin A0 (2) +#define BATTERY_PIN (2) +// and has 12 bit resolution +#define BATTERY_SENSE_RESOLUTION_BITS 12 +#define BATTERY_SENSE_RESOLUTION 4096.0 +#undef AREF_VOLTAGE +#define AREF_VOLTAGE 3.0 +#define VBAT_AR_INTERNAL AR_INTERNAL_3_0 +#define ADC_MULTIPLIER 1.42 // fine tuning of voltage + +#ifdef __cplusplus +} +#endif + +/*---------------------------------------------------------------------------- + * Arduino objects - C++ only + *----------------------------------------------------------------------------*/ +#endif \ No newline at end of file diff --git a/variants/meshlink_eink/platformio.ini b/variants/meshlink_eink/platformio.ini new file mode 100644 index 000000000..db3647e73 --- /dev/null +++ b/variants/meshlink_eink/platformio.ini @@ -0,0 +1,30 @@ +; MeshLink board developed by LoraItalia. NRF52840, eByte E22900M22S (Will also come with other frequencies), 25w MPPT solar charger (5v,12v,18v selectable), support for gps, buzzer, oled or e-ink display, 10 gpios, hardware watchdog +; https://www.loraitalia.it +; firmware for boards with a 250x122 e-ink display +[env:meshlink_eink] +extends = nrf52840_base +board = meshlink +;board_check = true +build_flags = ${nrf52840_base.build_flags} -I variants/meshlink_eink -D MESHLINK + -L "${platformio.libdeps_dir}/${this.__env__}/bsec2/src/cortex-m4/fpv4-sp-d16-hard" + -D GPS_POWER_TOGGLE ; comment this line to disable triple press function on the user button to turn off gps entirely. + -D EINK_DISPLAY_MODEL=GxEPD2_213_B74 + -D EINK_WIDTH=250 + -D EINK_HEIGHT=122 + -D USE_EINK_DYNAMICDISPLAY ; Enable Dynamic EInk + -D EINK_LIMIT_FASTREFRESH=5 ; How many consecutive fast-refreshes are permitted + -D EINK_LIMIT_RATE_BACKGROUND_SEC=30 ; Minimum interval between BACKGROUND updates + -D EINK_LIMIT_RATE_RESPONSIVE_SEC=1 ; Minimum interval between RESPONSIVE updates + -D EINK_LIMIT_GHOSTING_PX=2000 ; (Optional) How much image ghosting is tolerated + -D EINK_BACKGROUND_USES_FAST ; (Optional) Use FAST refresh for both BACKGROUND and RESPONSIVE, until a limit is reached. + -D EINK_HASQUIRK_VICIOUSFASTREFRESH ; Identify that pixels drawn by fast-refresh are harder to clear + + +build_src_filter = ${nrf52_base.build_src_filter} +<../variants/meshlink_eink> +lib_deps = + ${nrf52840_base.lib_deps} + https://github.com/meshtastic/GxEPD2#55f618961db45a23eff0233546430f1e5a80f63a +debug_tool = jlink +; If not set we will default to uploading over serial (first it forces bootloader entry by talking 1200bps to cdcacm) +; Note: as of 6/2013 the serial/bootloader based programming takes approximately 30 seconds +;upload_protocol = jlink \ No newline at end of file diff --git a/variants/meshlink_eink/variant.cpp b/variants/meshlink_eink/variant.cpp new file mode 100644 index 000000000..81a5097c4 --- /dev/null +++ b/variants/meshlink_eink/variant.cpp @@ -0,0 +1,23 @@ +#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() +{ + pinMode(PIN_LED1, OUTPUT); + digitalWrite(PIN_LED1, HIGH); // turn off the white led while booting + // otherwise it will stay lit for several seconds (could be annoying) + +#ifdef PIN_WD_EN + pinMode(PIN_WD_EN, OUTPUT); + digitalWrite(PIN_WD_EN, HIGH); // Enable the Watchdog at boot +#endif +} \ No newline at end of file diff --git a/variants/meshlink_eink/variant.h b/variants/meshlink_eink/variant.h new file mode 100644 index 000000000..b605d7082 --- /dev/null +++ b/variants/meshlink_eink/variant.h @@ -0,0 +1,153 @@ +#ifndef _VARIANT_MESHLINK_ +#define _VARIANT_MESHLINK_ +#ifndef MESHLINK +#define MESHLINK +#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 (2) +#define NUM_ANALOG_OUTPUTS (0) + +#define BUTTON_PIN (-1) // If defined, this will be used for user button presses, +#define BUTTON_NEED_PULLUP + +// LEDs +#define PIN_LED1 (24) // Built in white led for status +#define LED_BLUE PIN_LED1 +#define LED_BUILTIN PIN_LED1 + +#define LED_STATE_ON 0 // State when LED is litted +#define LED_INVERTED 1 + +// Testing USB detection +// #define NRF_APM + +/* + * Analog pins + */ +#define PIN_A1 (3) // P0.03/AIN1 +#define ADC_RESOLUTION 14 + +// Other pins +// #define PIN_AREF (2) +// static const uint8_t AREF = PIN_AREF; + +/* + * Serial interfaces + */ +#define PIN_SERIAL1_RX (32 + 8) +#define PIN_SERIAL1_TX (7) + +/* + * SPI Interfaces + */ +#define SPI_INTERFACES_COUNT 2 + +#define PIN_SPI_MISO (8) +#define PIN_SPI_MOSI (32 + 9) +#define PIN_SPI_SCK (11) + +#define PIN_SPI1_MISO (23) +#define PIN_SPI1_MOSI (21) +#define PIN_SPI1_SCK (19) + +static const uint8_t SS = 12; +static const uint8_t MOSI = PIN_SPI_MOSI; +static const uint8_t MISO = PIN_SPI_MISO; +static const uint8_t SCK = PIN_SPI_SCK; + +/* + * eink display pins + */ +#define USE_EINK + +#define PIN_EINK_CS (15) +#define PIN_EINK_BUSY (16) +#define PIN_EINK_DC (14) +#define PIN_EINK_RES (17) +#define PIN_EINK_SCLK (19) +#define PIN_EINK_MOSI (21) // also called SDI + +/* + * Wire Interfaces + */ +#define WIRE_INTERFACES_COUNT 1 + +#define PIN_WIRE_SDA (1) +#define PIN_WIRE_SCL (27) + +// QSPI Pins +#define PIN_QSPI_SCK 19 +#define PIN_QSPI_CS 22 +#define PIN_QSPI_IO0 21 +#define PIN_QSPI_IO1 23 +#define PIN_QSPI_IO2 32 +#define PIN_QSPI_IO3 20 + +// On-board QSPI Flash +#define EXTERNAL_FLASH_DEVICES W25Q16JVUXIQ +#define EXTERNAL_FLASH_USE_QSPI + +#define USE_SX1262 +#define SX126X_CS (12) +#define SX126X_DIO1 (32 + 1) +#define SX126X_BUSY (32 + 3) +#define SX126X_RESET (6) +// #define SX126X_RXEN (13) +// DIO2 controlls an antenna switch and the TCXO voltage is controlled by DIO3 +#define SX126X_DIO2_AS_RF_SWITCH +#define SX126X_DIO3_TCXO_VOLTAGE 1.8 + +// pin 25 is used to enable or disable the watchdog. This pin has to be disabled when cpu is put to sleep +// otherwise the timer will expire and wd will reboot the cpu +#define PIN_WD_EN (25) + +#define PIN_GPS_PPS (26) // Pulse per second input from the GPS + +#define GPS_TX_PIN PIN_SERIAL1_RX // This is for bits going TOWARDS the CPU +#define GPS_RX_PIN PIN_SERIAL1_TX // This is for bits going TOWARDS the GPS + +// #define GPS_THREAD_INTERVAL 50 + +// Define pin to enable GPS toggle (set GPIO to LOW) via user button triple press +#define PIN_GPS_EN (0) +#define GPS_EN_ACTIVE LOW + +#define PIN_BUZZER (31) // P0.31/AIN7 + +// Battery +// The battery sense is hooked to pin A0 (2) +#define BATTERY_PIN (2) +// and has 12 bit resolution +#define BATTERY_SENSE_RESOLUTION_BITS 12 +#define BATTERY_SENSE_RESOLUTION 4096.0 +#undef AREF_VOLTAGE +#define AREF_VOLTAGE 3.0 +#define VBAT_AR_INTERNAL AR_INTERNAL_3_0 +#define ADC_MULTIPLIER 1.42 // fine tuning of voltage + +#ifdef __cplusplus +} +#endif + +/*---------------------------------------------------------------------------- + * Arduino objects - C++ only + *----------------------------------------------------------------------------*/ +#endif \ No newline at end of file