diff --git a/.github/workflows/build_raspbian.yml b/.github/workflows/build_raspbian.yml
new file mode 100644
index 000000000..103f43a71
--- /dev/null
+++ b/.github/workflows/build_raspbian.yml
@@ -0,0 +1,45 @@
+name: Build Raspbian
+
+on: workflow_call
+
+permissions:
+ contents: write
+ packages: write
+
+jobs:
+ build-raspbian:
+ runs-on: [self-hosted, linux, ARM64]
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v3
+ with:
+ submodules: recursive
+ ref: ${{github.event.pull_request.head.ref}}
+ repository: ${{github.event.pull_request.head.repo.full_name}}
+
+ - name: Upgrade python tools
+ shell: bash
+ run: |
+ python -m pip install --upgrade pip
+ pip install -U platformio adafruit-nrfutil
+ pip install -U meshtastic --pre
+
+ - name: Upgrade platformio
+ shell: bash
+ run: |
+ pio upgrade
+
+ - name: Build Raspbian
+ run: bin/build-native.sh
+
+ - name: Get release version string
+ run: echo "version=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
+ id: version
+
+ - name: Store binaries as an artifact
+ uses: actions/upload-artifact@v3
+ with:
+ name: firmware-raspbian-${{ steps.version.outputs.version }}.zip
+ path: |
+ release/meshtasticd_linux_arm64
+ bin/config-dist.yaml
diff --git a/.github/workflows/main_matrix.yml b/.github/workflows/main_matrix.yml
index 145a75c2d..6b6ff1ad7 100644
--- a/.github/workflows/main_matrix.yml
+++ b/.github/workflows/main_matrix.yml
@@ -103,7 +103,6 @@ jobs:
build-nrf52:
strategy:
fail-fast: false
- max-parallel: 2
matrix:
include:
- board: rak4631
@@ -129,6 +128,15 @@ jobs:
with:
board: ${{ matrix.board }}
+ build-raspbian:
+ strategy:
+ fail-fast: false
+ max-parallel: 1
+ uses: ./.github/workflows/build_raspbian.yml
+
+ package-raspbian:
+ uses: ./.github/workflows/package_raspbian.yml
+
build-native:
runs-on: ubuntu-latest
steps:
@@ -204,7 +212,15 @@ jobs:
gather-artifacts:
runs-on: ubuntu-latest
needs:
- [build-esp32, build-esp32-s3, build-nrf52, build-native, build-rpi2040]
+ [
+ build-esp32,
+ build-esp32-s3,
+ build-nrf52,
+ build-raspbian,
+ build-native,
+ build-rpi2040,
+ package-raspbian,
+ ]
steps:
- name: Checkout code
uses: actions/checkout@v3
@@ -216,12 +232,15 @@ jobs:
with:
path: ./
+ - name: Display structure of downloaded files
+ run: ls -R
+
- name: Get release version string
run: echo "version=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
id: version
- name: Move files up
- run: mv -b -t ./ ./*tbeam-2*/littlefs*.bin ./*tbeam-2*/bleota.bin ./*tbeam-s3*/bleota-s3.bin ./**/firmware*.bin ./*t-echo*/Meshtastic_nRF52_factory_erase.uf2 ./**/firmware-*.uf2 ./**/firmware-*-ota.zip ./**/*.elf ./*native*/*device-*.sh ./*native*/*device-*.bat
+ run: mv -b -t ./ ./*tbeam-2*/littlefs*.bin ./*tbeam-2*/bleota.bin ./*tbeam-s3*/bleota-s3.bin ./**/firmware*.bin ./*t-echo*/Meshtastic_nRF52_factory_erase.uf2 ./**/firmware-*.uf2 ./**/firmware-*-ota.zip ./**/*.elf ./*native*/*device-*.sh ./*native*/*device-*.bat ./firmware-raspbian-*/release/meshtasticd_linux_arm64 ./firmware-raspbian-*/bin/config-dist.yaml
- name: Repackage in single firmware zip
uses: actions/upload-artifact@v3
@@ -233,6 +252,8 @@ jobs:
./firmware-*-ota.zip
./device-*.sh
./device-*.bat
+ ./meshtasticd_linux_arm64
+ ./config-dist.yaml
retention-days: 90
- uses: actions/download-artifact@v3
@@ -294,6 +315,13 @@ jobs:
name: firmware-${{ steps.version.outputs.version }}
path: ./output
+ - uses: actions/download-artifact@v3
+ with:
+ name: artifact-deb
+
+ - name: Display structure of downloaded files
+ run: ls -R
+
- name: Device scripts permissions
run: |
chmod +x ./output/device-install.sh
@@ -347,6 +375,16 @@ jobs:
asset_name: debug-elfs-${{ steps.version.outputs.version }}.zip
asset_content_type: application/zip
+ - name: Add raspbian .deb
+ uses: actions/upload-release-asset@v1
+ env:
+ GITHUB_TOKEN: ${{ github.token }}
+ with:
+ upload_url: ${{ steps.create_release.outputs.upload_url }}
+ asset_path: ./meshtasticd_${{ steps.version.outputs.version }}_arm64.deb
+ asset_name: meshtasticd_${{ steps.version.outputs.version }}_arm64.deb
+ asset_content_type: application/vnd.debian.binary-package
+
- name: Bump version.properties
run: >-
bin/bump_version.py
diff --git a/.github/workflows/package_raspbian.yml b/.github/workflows/package_raspbian.yml
new file mode 100644
index 000000000..61f82e9d7
--- /dev/null
+++ b/.github/workflows/package_raspbian.yml
@@ -0,0 +1,62 @@
+name: Package Raspbian
+
+on:
+ workflow_call:
+ workflow_dispatch:
+
+permissions:
+ contents: write
+ packages: write
+
+jobs:
+ build-raspbian:
+ uses: ./.github/workflows/build_raspbian.yml
+
+ package-raspbian:
+ runs-on: ubuntu-latest
+ needs: build-raspbian
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v3
+ with:
+ submodules: recursive
+ ref: ${{github.event.pull_request.head.ref}}
+ repository: ${{github.event.pull_request.head.repo.full_name}}
+
+ - name: Get release version string
+ run: echo "version=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
+ id: version
+
+ - name: Download artifacts
+ uses: actions/download-artifact@v3
+ with:
+ name: firmware-raspbian-${{ steps.version.outputs.version }}.zip
+
+ - name: Display structure of downloaded files
+ run: ls -R
+
+ - name: build .debpkg
+ run: |
+ mkdir -p .debpkg/usr/sbin
+ mkdir -p .debpkg/etc/meshtasticd
+ mkdir -p .debpkg/usr/lib/systemd/system/
+ cp release/meshtasticd_linux_arm64 .debpkg/usr/sbin/meshtasticd
+ cp bin/config-dist.yaml .debpkg/etc/meshtasticd/config.yaml
+ chmod +x .debpkg/usr/sbin/meshtasticd
+ cp bin/meshtasticd.service .debpkg/usr/lib/systemd/system/meshtasticd.service
+
+ - uses: jiro4989/build-deb-action@v3
+ with:
+ package: meshtasticd
+ package_root: .debpkg
+ maintainer: Jonathan Bennett
+ version: ${{ steps.version.outputs.version }} # refs/tags/v*.*.*
+ arch: arm64
+ depends: libyaml-cpp0.7
+ desc: Native Linux Meshtastic binary.
+
+ - uses: actions/upload-artifact@v3
+ with:
+ name: artifact-deb
+ path: |
+ ./*.deb
diff --git a/.trunk/configs/.shellcheckrc b/.trunk/configs/.shellcheckrc
index 8c7b1ada8..b2e8a14cc 100644
--- a/.trunk/configs/.shellcheckrc
+++ b/.trunk/configs/.shellcheckrc
@@ -1,7 +1,10 @@
enable=all
source-path=SCRIPTDIR
disable=SC2154
+disable=SC2248
+disable=SC2250
# If you're having issues with shellcheck following source, disable the errors via:
# disable=SC1090
# disable=SC1091
+#
\ No newline at end of file
diff --git a/.trunk/configs/.yamllint.yaml b/.trunk/configs/.yamllint.yaml
index 4d444662d..790846156 100644
--- a/.trunk/configs/.yamllint.yaml
+++ b/.trunk/configs/.yamllint.yaml
@@ -3,7 +3,7 @@ rules:
required: only-when-needed
extra-allowed: ["{|}"]
empty-values:
- forbid-in-block-mappings: true
+ forbid-in-block-mappings: false
forbid-in-flow-mappings: true
key-duplicates: {}
octal-values:
diff --git a/arch/esp32/esp32.ini b/arch/esp32/esp32.ini
index a26b8ab58..60cdee1cd 100644
--- a/arch/esp32/esp32.ini
+++ b/arch/esp32/esp32.ini
@@ -39,7 +39,7 @@ lib_deps =
${environmental_base.lib_deps}
https://github.com/meshtastic/esp32_https_server.git#23665b3adc080a311dcbb586ed5941b5f94d6ea2
h2zero/NimBLE-Arduino@^1.4.1
- jgromes/RadioLib@^6.1.0
+ jgromes/RadioLib@^6.2.0
https://github.com/lewisxhe/XPowersLib.git#84b7373faea3118b6c37954d52f98b8a337148d6
https://github.com/meshtastic/ESP32_Codec2.git#633326c78ac251c059ab3a8c430fcdf25b41672f
@@ -57,4 +57,4 @@ lib_ignore =
; customize the partition table
; http://docs.platformio.org/en/latest/platforms/espressif32.html#partition-tables
-board_build.partitions = partition-table.csv
+board_build.partitions = partition-table.csv
\ No newline at end of file
diff --git a/arch/nrf52/nrf52.ini b/arch/nrf52/nrf52.ini
index 046c8ac62..0326c87f0 100644
--- a/arch/nrf52/nrf52.ini
+++ b/arch/nrf52/nrf52.ini
@@ -15,7 +15,7 @@ build_src_filter =
lib_deps=
${arduino_base.lib_deps}
- jgromes/RadioLib@^6.1.0
+ jgromes/RadioLib@^6.2.0
lib_ignore =
BluetoothOTA
\ No newline at end of file
diff --git a/arch/portduino/portduino.ini b/arch/portduino/portduino.ini
index 8c000519a..0d1151a3b 100644
--- a/arch/portduino/portduino.ini
+++ b/arch/portduino/portduino.ini
@@ -1,6 +1,6 @@
; The Portduino based sim environment on top of any host OS, all hardware will be simulated
[portduino_base]
-platform = https://github.com/meshtastic/platform-native.git#489ff929dca0bb768256ba2de45f95815111490f
+platform = https://github.com/meshtastic/platform-native.git#05255283879a0c65a7d3eba6c468b9186438bb14
framework = arduino
build_src_filter =
@@ -23,9 +23,11 @@ lib_deps =
${env.lib_deps}
${networking_base.lib_deps}
rweather/Crypto@^0.4.0
- jgromes/RadioLib@6.1.0
+ jgromes/RadioLib@^6.1.0
build_flags =
${arduino_base.build_flags}
-fPIC
- -Isrc/platform/portduino
\ No newline at end of file
+ -Isrc/platform/portduino
+ -DRADIOLIB_EEPROM_UNSUPPORTED
+
diff --git a/arch/rp2040/rp2040.ini b/arch/rp2040/rp2040.ini
index d72f719c6..457961a12 100644
--- a/arch/rp2040/rp2040.ini
+++ b/arch/rp2040/rp2040.ini
@@ -20,5 +20,5 @@ lib_ignore =
lib_deps =
${arduino_base.lib_deps}
${environmental_base.lib_deps}
- jgromes/RadioLib@^6.1.0
- https://github.com/kokke/tiny-AES-c.git#f06ac37fc31dfdaca2e0d9bec83f90d5663c319b
\ No newline at end of file
+ jgromes/RadioLib@^6.2.0
+ rweather/Crypto
\ No newline at end of file
diff --git a/arch/stm32/stm32wl5e.ini b/arch/stm32/stm32wl5e.ini
index ab06bdc50..4c4792777 100644
--- a/arch/stm32/stm32wl5e.ini
+++ b/arch/stm32/stm32wl5e.ini
@@ -20,7 +20,7 @@ upload_protocol = stlink
lib_deps =
${env.lib_deps}
- jgromes/RadioLib@^6.1.0
+ jgromes/RadioLib@^6.2.0
https://github.com/kokke/tiny-AES-c.git#f06ac37fc31dfdaca2e0d9bec83f90d5663c319b
https://github.com/littlefs-project/littlefs.git#v2.5.1
https://github.com/stm32duino/STM32FreeRTOS.git#10.3.1
diff --git a/bin/build-native.sh b/bin/build-native.sh
index 8bc262860..64c5adb50 100755
--- a/bin/build-native.sh
+++ b/bin/build-native.sh
@@ -2,8 +2,8 @@
set -e
-VERSION=`bin/buildinfo.py long`
-SHORT_VERSION=`bin/buildinfo.py short`
+VERSION=$(bin/buildinfo.py long)
+SHORT_VERSION=$(bin/buildinfo.py short)
OUTDIR=release/
@@ -13,11 +13,15 @@ mkdir -p $OUTDIR/
rm -r $OUTDIR/* || true
# Important to pull latest version of libs into all device flavors, otherwise some devices might be stale
-platformio pkg update
+platformio pkg update
-pio run --environment native
-cp .pio/build/native/program $OUTDIR/meshtasticd_linux_amd64
+if command -v raspi-config &>/dev/null; then
+ pio run --environment raspbian
+ cp .pio/build/raspbian/program $OUTDIR/meshtasticd_linux_arm64
+else
+ pio run --environment native
+ cp .pio/build/native/program $OUTDIR/meshtasticd_linux_amd64
+fi
cp bin/device-install.* $OUTDIR
cp bin/device-update.* $OUTDIR
-
diff --git a/bin/config-dist.yaml b/bin/config-dist.yaml
new file mode 100644
index 000000000..cde45d1f8
--- /dev/null
+++ b/bin/config-dist.yaml
@@ -0,0 +1,40 @@
+# Define your devices here using Broadcom pin numbering
+# Uncomment the block that corresponds to your hardware
+---
+Lora:
+# Module: sx1262 # Waveshare SX126X XXXM
+# DIO2_AS_RF_SWITCH: true
+# CS: 21
+# IRQ: 16
+# Busy: 20
+# Reset: 18
+
+# Module: sx1262 # Waveshare SX1302 LISTEN ONLY AT THIS TIME!
+# CS: 7
+# IRQ: 17
+# Reset: 22
+
+# Module: RF95 # Adafruit RFM9x
+# Reset: 25
+# CS: 7
+# IRQ: 22
+# Busy: 23
+
+# Module: RF95 # Elecrow Lora RFM95 IOT https://www.elecrow.com/lora-rfm95-iot-board-for-rpi.html
+# Reset: 22
+# CS: 7
+# IRQ: 25
+
+# Set gpio chip to use in /dev/. Defaults to 0.
+# Notably the Raspberry Pi 5 puts the GPIO header on gpiochip4
+# gpiochip: 4
+
+# Define GPIO buttons here:
+
+GPIO:
+# User: 6
+
+# Define GPS
+
+GPS:
+# SerialPath: /dev/ttyS0
diff --git a/bin/meshtasticd.service b/bin/meshtasticd.service
new file mode 100644
index 000000000..4ed1bfd8f
--- /dev/null
+++ b/bin/meshtasticd.service
@@ -0,0 +1,9 @@
+[unit]
+description=Meshtastic Native Daemon
+
+[Service]
+Type=simple
+ExecStart=/usr/sbin/meshtasticd
+
+[Install]
+WantedBy=multi-user.target
diff --git a/bin/native-install.sh b/bin/native-install.sh
new file mode 100755
index 000000000..d1d0c8707
--- /dev/null
+++ b/bin/native-install.sh
@@ -0,0 +1,10 @@
+#!/usr/bin/env bash
+
+cp release/meshtasticd_linux_arm64 /usr/sbin/meshtasticd
+mkdir /etc/meshtasticd
+if [[ -f "/etc/meshtasticd/config.yaml" ]]; then
+ cp bin/config-dist.yaml /etc/meshtasticd/config-upgrade.yaml
+else
+ cp bin/config-dist.yaml /etc/meshtasticd/config.yaml
+fi
+cp bin/meshtasticd.service /usr/lib/systemd/system/meshtasticd.service
diff --git a/platformio.ini b/platformio.ini
index cb79565f1..451fe3f1a 100644
--- a/platformio.ini
+++ b/platformio.ini
@@ -93,7 +93,7 @@ lib_deps =
end2endzone/NonBlockingRTTTL@^1.3.0
https://github.com/meshtastic/SparkFun_ATECCX08a_Arduino_Library.git#5cf62b36c6f30bc72a07bdb2c11fc9a22d1e31da
-build_flags = ${env.build_flags} -Os -DRADIOLIB_SPI_PARANOID=0
+build_flags = ${env.build_flags} -Os
build_src_filter = ${env.build_src_filter} -
; Common libs for communicating over TCP/IP networks such as MQTT
@@ -123,4 +123,4 @@ lib_deps =
adafruit/Adafruit PM25 AQI Sensor@^1.0.6
adafruit/Adafruit MPU6050@^2.2.4
adafruit/Adafruit LIS3DH@^1.2.4
- https://github.com/lewisxhe/BMA423_Library@^0.0.1
\ No newline at end of file
+ https://github.com/lewisxhe/BMA423_Library@^0.0.1
diff --git a/protobufs b/protobufs
index c845b7848..9148427a3 160000
--- a/protobufs
+++ b/protobufs
@@ -1 +1 @@
-Subproject commit c845b7848eebb11150ca0427773303bf8758e533
+Subproject commit 9148427a3be535c9e3f17e846ecbb64ce04b6521
diff --git a/src/ButtonThread.h b/src/ButtonThread.h
index a8a89e82e..a60b7730a 100644
--- a/src/ButtonThread.h
+++ b/src/ButtonThread.h
@@ -36,6 +36,9 @@ class ButtonThread : public concurrency::OSThread
#endif
#ifdef BUTTON_PIN_TOUCH
OneButton userButtonTouch;
+#endif
+#if defined(ARCH_RASPBERRY_PI)
+ OneButton userButton;
#endif
static bool shutdown_on_long_stop;
@@ -45,8 +48,14 @@ class ButtonThread : public concurrency::OSThread
// callback returns the period for the next callback invocation (or 0 if we should no longer be called)
ButtonThread() : OSThread("Button")
{
-#ifdef BUTTON_PIN
+#if defined(ARCH_RASPBERRY_PI) || defined(BUTTON_PIN)
+#if defined(ARCH_RASPBERRY_PI)
+ if (settingsMap.count(user) != 0 && settingsMap[user] != RADIOLIB_NC)
+ userButton = OneButton(settingsMap[user], true, true);
+#elif defined(BUTTON_PIN)
+
userButton = OneButton(config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN, true, true);
+#endif
#ifdef INPUT_PULLUP_SENSE
// Some platforms (nrf52) have a SENSE variant which allows wake from sleep - override what OneButton did
pinMode(config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN, INPUT_PULLUP_SENSE);
@@ -58,8 +67,13 @@ class ButtonThread : public concurrency::OSThread
userButton.attachMultiClick(userButtonMultiPressed);
userButton.attachLongPressStart(userButtonPressedLongStart);
userButton.attachLongPressStop(userButtonPressedLongStop);
+#if defined(ARCH_RASPBERRY_PI)
+ if (settingsMap.count(user) != 0 && settingsMap[user] != RADIOLIB_NC)
+ wakeOnIrq(settingsMap[user], FALLING);
+#else
wakeOnIrq(config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN, FALLING);
#endif
+#endif
#ifdef BUTTON_PIN_ALT
userButtonAlt = OneButton(BUTTON_PIN_ALT, true, true);
#ifdef INPUT_PULLUP_SENSE
@@ -87,9 +101,14 @@ class ButtonThread : public concurrency::OSThread
{
canSleep = true; // Assume we should not keep the board awake
-#ifdef BUTTON_PIN
+#if defined(BUTTON_PIN)
userButton.tick();
canSleep &= userButton.isIdle();
+#elif defined(ARCH_RASPBERRY_PI)
+ if (settingsMap.count(user) != 0 && settingsMap[user] != RADIOLIB_NC) {
+ userButton.tick();
+ canSleep &= userButton.isIdle();
+ }
#endif
#ifdef BUTTON_PIN_ALT
userButtonAlt.tick();
@@ -121,6 +140,13 @@ class ButtonThread : public concurrency::OSThread
!moduleConfig.canned_message.enabled) {
powerFSM.trigger(EVENT_PRESS);
}
+#endif
+#if defined(ARCH_RASPBERRY_PI)
+ if ((settingsMap.count(user) != 0 && settingsMap[user] != RADIOLIB_NC) &&
+ (settingsMap[user] != moduleConfig.canned_message.inputbroker_pin_press) ||
+ !moduleConfig.canned_message.enabled) {
+ powerFSM.trigger(EVENT_PRESS);
+ }
#endif
}
static void userButtonPressedLong()
@@ -199,4 +225,4 @@ class ButtonThread : public concurrency::OSThread
}
};
-} // namespace concurrency
\ No newline at end of file
+} // namespace concurrency
diff --git a/src/Power.cpp b/src/Power.cpp
index e6f7ac990..6f0d2cbdd 100644
--- a/src/Power.cpp
+++ b/src/Power.cpp
@@ -19,6 +19,11 @@
#include "meshUtils.h"
#include "sleep.h"
+// Working USB detection for powered/charging states on the RAK platform
+#ifdef NRF_APM
+#include "nrfx_power.h"
+#endif
+
#ifdef DEBUG_HEAP_MQTT
#include "mqtt/MQTT.h"
#include "target_specific.h"
@@ -52,6 +57,7 @@ static const adc_atten_t atten = ADC_ATTENUATION;
#if HAS_TELEMETRY && !defined(ARCH_PORTDUINO)
INA260Sensor ina260Sensor;
INA219Sensor ina219Sensor;
+INA3221Sensor ina3221Sensor;
#endif
#ifdef HAS_PMU
@@ -286,6 +292,9 @@ class AnalogBatteryLevel : public HasBatteryLevel
} else if (nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_INA260].first ==
config.power.device_battery_ina_address) {
return ina260Sensor.getBusVoltageMv();
+ } else if (nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_INA3221].first ==
+ config.power.device_battery_ina_address) {
+ return ina3221Sensor.getBusVoltageMv();
}
return 0;
}
@@ -456,10 +465,25 @@ void Power::readPowerStatus()
}
}
+ OptionalBool NRF_USB = OptFalse;
+
+#ifdef NRF_APM // Section of code detects USB power on the RAK4631 and updates the power states. Takes 20 seconds or so to detect
+ // changes.
+
+ nrfx_power_usb_state_t nrf_usb_state = nrfx_power_usbstatus_get();
+
+ if (nrf_usb_state == NRFX_POWER_USB_STATE_DISCONNECTED) {
+ powerFSM.trigger(EVENT_POWER_DISCONNECTED);
+ NRF_USB = OptFalse;
+ } else {
+ powerFSM.trigger(EVENT_POWER_CONNECTED);
+ NRF_USB = OptTrue;
+ }
+#endif
// Notify any status instances that are observing us
- const PowerStatus powerStatus2 =
- PowerStatus(hasBattery ? OptTrue : OptFalse, batteryLevel->isVbusIn() ? OptTrue : OptFalse,
- batteryLevel->isCharging() ? OptTrue : OptFalse, batteryVoltageMv, batteryChargePercent);
+ const PowerStatus powerStatus2 = PowerStatus(
+ hasBattery ? OptTrue : OptFalse, batteryLevel->isVbusIn() || NRF_USB == OptTrue ? OptTrue : OptFalse,
+ batteryLevel->isCharging() || NRF_USB == OptTrue ? OptTrue : OptFalse, batteryVoltageMv, batteryChargePercent);
LOG_DEBUG("Battery: usbPower=%d, isCharging=%d, batMv=%d, batPct=%d\n", powerStatus2.getHasUSB(),
powerStatus2.getIsCharging(), powerStatus2.getBatteryVoltageMv(), powerStatus2.getBatteryChargePercent());
newStatus.notifyObservers(&powerStatus2);
diff --git a/src/configuration.h b/src/configuration.h
index 199880c6b..cb7ee218b 100644
--- a/src/configuration.h
+++ b/src/configuration.h
@@ -57,8 +57,8 @@ along with this program. If not, see .
#define REQUIRE_RADIO true // If true, we will fail to start if the radio is not found
/// Convert a preprocessor name into a quoted string
-#define xstr(s) str(s)
-#define str(s) #s
+#define xstr(s) ystr(s)
+#define ystr(s) #s
/// Convert a preprocessor name into a quoted string and if that string is empty use "unset"
#define optstr(s) (xstr(s)[0] ? xstr(s) : "unset")
@@ -209,4 +209,4 @@ along with this program. If not, see .
#ifndef HW_VENDOR
#error HW_VENDOR must be defined
-#endif
+#endif
\ No newline at end of file
diff --git a/src/detect/ScanI2CTwoWire.cpp b/src/detect/ScanI2CTwoWire.cpp
index 8c58333dd..763112fa3 100644
--- a/src/detect/ScanI2CTwoWire.cpp
+++ b/src/detect/ScanI2CTwoWire.cpp
@@ -2,7 +2,9 @@
#include "concurrency/LockGuard.h"
#include "configuration.h"
-
+#if defined(ARCH_RASPBERRY_PI)
+#include "linux/LinuxHardwareI2C.h"
+#endif
#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL)
#include "main.h" // atecc
#endif
@@ -162,7 +164,14 @@ void ScanI2CTwoWire::scanPort(I2CPort port)
for (addr.address = 1; addr.address < 127; addr.address++) {
i2cBus->beginTransmission(addr.address);
+#ifdef ARCH_PORTDUINO
+ if (i2cBus->read() != -1)
+ err = 0;
+ else
+ err = 2;
+#else
err = i2cBus->endTransmission();
+#endif
type = NONE;
if (err == 0) {
LOG_DEBUG("I2C device found at address 0x%x\n", addr.address);
diff --git a/src/gps/GPS.cpp b/src/gps/GPS.cpp
index 47ba067d2..7ea36c860 100644
--- a/src/gps/GPS.cpp
+++ b/src/gps/GPS.cpp
@@ -7,6 +7,7 @@
#include "ubx.h"
#ifdef ARCH_PORTDUINO
+#include "PortduinoGlue.h"
#include "meshUtils.h"
#include
#endif
@@ -15,7 +16,7 @@
#define GPS_RESET_MODE HIGH
#endif
-#if defined(NRF52840_XXAA) || defined(NRF52833_XXAA) || defined(ARCH_ESP32)
+#if defined(NRF52840_XXAA) || defined(NRF52833_XXAA) || defined(ARCH_ESP32) || defined(ARCH_RASPBERRY_PI)
HardwareSerial *GPS::_serial_gps = &Serial1;
#else
HardwareSerial *GPS::_serial_gps = NULL;
@@ -261,6 +262,20 @@ bool GPS::setup()
isProblematicGPS = true;
}
#endif
+
+#if defined(RAK4630) && defined(PIN_3V3_EN)
+ // If we are using the RAK4630 and we have no other peripherals on the I2C bus or module interest in 3V3_S,
+ // then we can safely set en_gpio turn off power to 3V3 (IO2) to hard sleep the GPS
+ if (rtc_found.port == ScanI2C::DeviceType::NONE && rgb_found.type == ScanI2C::DeviceType::NONE &&
+ accelerometer_found.port == ScanI2C::DeviceType::NONE && !moduleConfig.detection_sensor.enabled &&
+ !moduleConfig.telemetry.air_quality_enabled && !moduleConfig.telemetry.environment_measurement_enabled &&
+ config.power.device_battery_ina_address == 0 && en_gpio == 0) {
+ LOG_DEBUG("Since no problematic peripherals or interested modules were found, setting power save GPS_EN to pin %i\n",
+ PIN_3V3_EN);
+ en_gpio = PIN_3V3_EN;
+ }
+#endif
+
if (tx_gpio && gnssModel == GNSS_MODEL_UNKNOWN) {
LOG_DEBUG("Probing for GPS at %d \n", serialSpeeds[speedSelect]);
gnssModel = probe(serialSpeeds[speedSelect]);
@@ -433,6 +448,7 @@ bool GPS::setup()
notifyDeepSleepObserver.observe(¬ifyDeepSleep);
notifyGPSSleepObserver.observe(¬ifyGPSSleep);
+
return true;
}
@@ -889,6 +905,10 @@ GPS *GPS::createGps()
#if defined(PIN_GPS_EN)
if (!_en_gpio)
_en_gpio = PIN_GPS_EN;
+#endif
+#ifdef ARCH_RASPBERRY_PI
+ if (!settingsMap[has_gps])
+ return nullptr;
#endif
if (!_rx_gpio || !_serial_gps) // Configured to have no GPS at all
return nullptr;
diff --git a/src/graphics/Screen.cpp b/src/graphics/Screen.cpp
index b626e393a..2e144e41a 100644
--- a/src/graphics/Screen.cpp
+++ b/src/graphics/Screen.cpp
@@ -1564,7 +1564,7 @@ void DebugInfo::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16
// Jm
void DebugInfo::drawFrameWiFi(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
{
-#if HAS_WIFI
+#if HAS_WIFI && !defined(ARCH_RASPBERRY_PI)
const char *wifiName = config.network.wifi_ssid;
display->setFont(FONT_SMALL);
diff --git a/src/main.cpp b/src/main.cpp
index c9f5646f5..8ce029361 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -68,13 +68,14 @@ NRF52Bluetooth *nrf52Bluetooth;
#endif
#ifdef ARCH_RASPBERRY_PI
-#include "platform/portduino/PiHal.h"
+#include "linux/LinuxHardwareI2C.h"
+#include "platform/portduino/PortduinoGlue.h"
#include
#include
#include
#endif
-#if HAS_BUTTON
+#if HAS_BUTTON || defined(ARCH_RASPBERRY_PI)
#include "ButtonThread.h"
#endif
#include "PowerFSMThread.h"
@@ -205,13 +206,13 @@ static int32_t ledBlinker()
uint32_t timeLastPowered = 0;
-#if HAS_BUTTON
+#if HAS_BUTTON || defined(ARCH_RASPBERRY_PI)
bool ButtonThread::shutdown_on_long_stop = false;
#endif
static Periodic *ledPeriodic;
static OSThread *powerFSMthread;
-#if HAS_BUTTON
+#if HAS_BUTTON || defined(ARCH_RASPBERRY_PI)
static OSThread *buttonThread;
uint32_t ButtonThread::longPressTime = 0;
#endif
@@ -582,7 +583,7 @@ void setup()
else
router = new ReliableRouter();
-#if HAS_BUTTON
+#if HAS_BUTTON || defined(ARCH_RASPBERRY_PI)
// Buttons. Moved here cause we need NodeDB to be initialized
buttonThread = new ButtonThread();
#endif
@@ -627,16 +628,16 @@ void setup()
initSPI();
#ifdef ARCH_RP2040
#ifdef HW_SPI1_DEVICE
- SPI1.setSCK(RF95_SCK);
- SPI1.setTX(RF95_MOSI);
- SPI1.setRX(RF95_MISO);
- pinMode(RF95_NSS, OUTPUT);
- digitalWrite(RF95_NSS, HIGH);
+ SPI1.setSCK(LORA_SCK);
+ SPI1.setTX(LORA_MOSI);
+ SPI1.setRX(LORA_MISO);
+ pinMode(LORA_CS, OUTPUT);
+ digitalWrite(LORA_CS, HIGH);
SPI1.begin(false);
-#else // HW_SPI1_DEVICE
- SPI.setSCK(RF95_SCK);
- SPI.setTX(RF95_MOSI);
- SPI.setRX(RF95_MISO);
+#else // HW_SPI1_DEVICE
+ SPI.setSCK(LORA_SCK);
+ SPI.setTX(LORA_MOSI);
+ SPI.setRX(LORA_MISO);
SPI.begin(false);
#endif // HW_SPI1_DEVICE
#elif defined(ARCH_APOLLO3)
@@ -646,8 +647,8 @@ void setup()
SPI.begin();
#else
// ESP32
- SPI.begin(RF95_SCK, RF95_MISO, RF95_MOSI, RF95_NSS);
- LOG_WARN("SPI.begin(SCK=%d, MISO=%d, MOSI=%d, NSS=%d)\n", RF95_SCK, RF95_MISO, RF95_MOSI, RF95_NSS);
+ SPI.begin(LORA_SCK, LORA_MISO, LORA_MOSI, LORA_CS);
+ LOG_WARN("SPI.begin(SCK=%d, MISO=%d, MOSI=%d, NSS=%d)\n", LORA_SCK, LORA_MISO, LORA_MOSI, LORA_CS);
SPI.setFrequency(4000000);
#endif
@@ -693,15 +694,32 @@ void setup()
#endif
#ifdef ARCH_RASPBERRY_PI
- PiHal *RadioLibHAL = new PiHal(1);
- if (!rIf) {
- rIf = new SX1262Interface((LockingArduinoHal *)RadioLibHAL, 21, 16, 18, 20);
- if (!rIf->init()) {
- LOG_WARN("Failed to find SX1262 radio\n");
- delete rIf;
- rIf = NULL;
- } else {
- LOG_INFO("SX1262 Radio init succeeded, using SX1262 radio\n");
+ if (settingsMap[use_sx1262]) {
+ if (!rIf) {
+ LockingArduinoHal *RadioLibHAL = new LockingArduinoHal(SPI, spiSettings);
+ rIf = new SX1262Interface((LockingArduinoHal *)RadioLibHAL, settingsMap[cs], settingsMap[irq], settingsMap[reset],
+ settingsMap[busy]);
+ if (!rIf->init()) {
+ LOG_ERROR("Failed to find SX1262 radio\n");
+ delete rIf;
+ exit(EXIT_FAILURE);
+ } else {
+ LOG_INFO("SX1262 Radio init succeeded, using SX1262 radio\n");
+ }
+ }
+ } else if (settingsMap[use_rf95]) {
+ if (!rIf) {
+ LockingArduinoHal *RadioLibHAL = new LockingArduinoHal(SPI, spiSettings);
+ rIf = new RF95Interface((LockingArduinoHal *)RadioLibHAL, settingsMap[cs], settingsMap[irq], settingsMap[reset],
+ settingsMap[busy]);
+ if (!rIf->init()) {
+ LOG_ERROR("Failed to find RF95 radio\n");
+ delete rIf;
+ rIf = NULL;
+ exit(EXIT_FAILURE);
+ } else {
+ LOG_INFO("RF95 Radio init succeeded, using RF95 radio\n");
+ }
}
}
@@ -740,7 +758,7 @@ void setup()
#if defined(RF95_IRQ)
if (!rIf) {
- rIf = new RF95Interface(RadioLibHAL, RF95_NSS, RF95_IRQ, RF95_RESET, RF95_DIO1);
+ rIf = new RF95Interface(RadioLibHAL, LORA_CS, RF95_IRQ, RF95_RESET, RF95_DIO1);
if (!rIf->init()) {
LOG_WARN("Failed to find RF95 radio\n");
delete rIf;
diff --git a/src/mesh/NodeDB.cpp b/src/mesh/NodeDB.cpp
index 0580113d1..afc09309d 100644
--- a/src/mesh/NodeDB.cpp
+++ b/src/mesh/NodeDB.cpp
@@ -200,7 +200,7 @@ void NodeDB::installDefaultConfig()
config.position.position_flags =
(meshtastic_Config_PositionConfig_PositionFlags_ALTITUDE | meshtastic_Config_PositionConfig_PositionFlags_ALTITUDE_MSL |
meshtastic_Config_PositionConfig_PositionFlags_SPEED | meshtastic_Config_PositionConfig_PositionFlags_HEADING |
- meshtastic_Config_PositionConfig_PositionFlags_DOP);
+ meshtastic_Config_PositionConfig_PositionFlags_DOP | meshtastic_Config_PositionConfig_PositionFlags_SATINVIEW);
#ifdef T_WATCH_S3
config.display.screen_on_secs = 30;
@@ -316,8 +316,8 @@ void NodeDB::installDefaultChannels()
void NodeDB::resetNodes()
{
- devicestate.node_db_lite_count = 0;
- memset(devicestate.node_db_lite, 0, sizeof(devicestate.node_db_lite));
+ devicestate.node_db_lite_count = 1;
+ std::fill(&devicestate.node_db_lite[1], &devicestate.node_db_lite[MAX_NUM_NODES - 1], meshtastic_NodeInfoLite());
saveDeviceStateToDisk();
if (neighborInfoModule && moduleConfig.neighbor_info.enabled)
neighborInfoModule->resetNeighbors();
@@ -370,7 +370,6 @@ void NodeDB::installDefaultDeviceState()
pickNewNodeNum(); // based on macaddr now
snprintf(owner.long_name, sizeof(owner.long_name), "Meshtastic %02x%02x", ourMacAddr[4], ourMacAddr[5]);
snprintf(owner.short_name, sizeof(owner.short_name), "%02x%02x", ourMacAddr[4], ourMacAddr[5]);
-
snprintf(owner.id, sizeof(owner.id), "!%08x", getNodeNum()); // Default node ID now based on nodenum
memcpy(owner.macaddr, ourMacAddr, sizeof(owner.macaddr));
}
@@ -395,6 +394,8 @@ void NodeDB::init()
// Set our board type so we can share it with others
owner.hw_model = HW_VENDOR;
+ // Ensure user (nodeinfo) role is set to whatever we're configured to
+ owner.role = config.device.role;
// Include our owner in the node db under our nodenum
meshtastic_NodeInfoLite *info = getOrCreateMeshNode(getNodeNum());
diff --git a/src/mesh/RadioLibRF95.cpp b/src/mesh/RadioLibRF95.cpp
index 0fa6c7fe8..f84ec28b7 100644
--- a/src/mesh/RadioLibRF95.cpp
+++ b/src/mesh/RadioLibRF95.cpp
@@ -1,9 +1,6 @@
#include "RadioLibRF95.h"
#include "configuration.h"
-#define RF95_CHIP_VERSION 0x12
-#define RF95_ALT_VERSION 0x11 // Supposedly some versions of the chip have id 0x11
-
// From datasheet but radiolib doesn't know anything about this
#define SX127X_REG_TCXO 0x4B
@@ -13,9 +10,8 @@ int16_t RadioLibRF95::begin(float freq, float bw, uint8_t sf, uint8_t cr, uint8_
uint8_t gain)
{
// execute common part
- int16_t state = SX127x::begin(RF95_CHIP_VERSION, syncWord, preambleLength);
- if (state != RADIOLIB_ERR_NONE)
- state = SX127x::begin(RF95_ALT_VERSION, syncWord, preambleLength);
+ uint8_t rf95versions[2] = {0x12, 0x11};
+ int16_t state = SX127x::begin(rf95versions, sizeof(rf95versions), syncWord, preambleLength);
RADIOLIB_ASSERT(state);
// current limit was removed from module' ctor
@@ -80,4 +76,4 @@ bool RadioLibRF95::isReceiving()
uint8_t RadioLibRF95::readReg(uint8_t addr)
{
return mod->SPIreadRegister(addr);
-}
\ No newline at end of file
+}
diff --git a/src/mesh/SX126xInterface.cpp b/src/mesh/SX126xInterface.cpp
index 980107917..30951cd16 100644
--- a/src/mesh/SX126xInterface.cpp
+++ b/src/mesh/SX126xInterface.cpp
@@ -2,6 +2,9 @@
#include "configuration.h"
#include "error.h"
#include "mesh/NodeDB.h"
+#ifdef ARCH_RASPBERRY_PI
+#include "PortduinoGlue.h"
+#endif
// Particular boards might define a different max power based on what their hardware can do, default to max power output if not
// specified (may be dangerous if using external PA and SX126x power config forgotten)
@@ -74,6 +77,12 @@ template bool SX126xInterface::init()
#ifdef SX126X_DIO2_AS_RF_SWITCH
LOG_DEBUG("Setting DIO2 as RF switch\n");
bool dio2AsRfSwitch = true;
+#elif defined(ARCH_RASPBERRY_PI)
+ bool dio2AsRfSwitch = false;
+ if (settingsMap[dio2_as_rf_switch]) {
+ LOG_DEBUG("Setting DIO2 as RF switch\n");
+ dio2AsRfSwitch = true;
+ }
#else
LOG_DEBUG("Setting DIO2 as not RF switch\n");
bool dio2AsRfSwitch = false;
@@ -241,7 +250,7 @@ template void SX126xInterface::startReceive()
// We use a 16 bit preamble so this should save some power by letting radio sit in standby mostly.
// Furthermore, we need the PREAMBLE_DETECTED and HEADER_VALID IRQ flag to detect whether we are actively receiving
int err = lora.startReceiveDutyCycleAuto(preambleLength, 8,
- RADIOLIB_SX126X_IRQ_RX_DEFAULT | RADIOLIB_SX126X_IRQ_RADIOLIB_PREAMBLE_DETECTED |
+ RADIOLIB_SX126X_IRQ_RX_DEFAULT | RADIOLIB_SX126X_IRQ_PREAMBLE_DETECTED |
RADIOLIB_SX126X_IRQ_HEADER_VALID);
assert(err == RADIOLIB_ERR_NONE);
@@ -275,7 +284,7 @@ template bool SX126xInterface::isActivelyReceiving()
// received and handled the interrupt for reading the packet/handling errors.
uint16_t irq = lora.getIrqStatus();
- bool detected = (irq & (RADIOLIB_SX126X_IRQ_HEADER_VALID | RADIOLIB_SX126X_IRQ_RADIOLIB_PREAMBLE_DETECTED));
+ bool detected = (irq & (RADIOLIB_SX126X_IRQ_HEADER_VALID | RADIOLIB_SX126X_IRQ_PREAMBLE_DETECTED));
// Handle false detections
if (detected) {
uint32_t now = millis();
@@ -318,4 +327,4 @@ template bool SX126xInterface::sleep()
#endif
return true;
-}
+}
\ No newline at end of file
diff --git a/src/mesh/generated/meshtastic/deviceonly.pb.h b/src/mesh/generated/meshtastic/deviceonly.pb.h
index ace142773..b099a3eab 100644
--- a/src/mesh/generated/meshtastic/deviceonly.pb.h
+++ b/src/mesh/generated/meshtastic/deviceonly.pb.h
@@ -313,8 +313,8 @@ extern const pb_msgdesc_t meshtastic_NodeRemoteHardwarePin_msg;
/* Maximum encoded size of messages (where known) */
#define meshtastic_ChannelFile_size 638
-#define meshtastic_DeviceState_size 16854
-#define meshtastic_NodeInfoLite_size 151
+#define meshtastic_DeviceState_size 17056
+#define meshtastic_NodeInfoLite_size 153
#define meshtastic_NodeRemoteHardwarePin_size 29
#define meshtastic_OEMStore_size 3231
#define meshtastic_PositionLite_size 28
diff --git a/src/mesh/generated/meshtastic/mesh.pb.h b/src/mesh/generated/meshtastic/mesh.pb.h
index dfaf693fc..59005db48 100644
--- a/src/mesh/generated/meshtastic/mesh.pb.h
+++ b/src/mesh/generated/meshtastic/mesh.pb.h
@@ -402,6 +402,8 @@ typedef struct _meshtastic_User {
If this user is a licensed operator, set this flag.
Also, "long_name" should be their licence number. */
bool is_licensed;
+ /* Indicates that the user's role in the mesh */
+ meshtastic_Config_DeviceConfig_Role role;
} meshtastic_User;
/* A message used in our Dynamic Source Routing protocol (RFC 4728 based) */
@@ -826,6 +828,7 @@ extern "C" {
#define meshtastic_Position_altitude_source_ENUMTYPE meshtastic_Position_AltSource
#define meshtastic_User_hw_model_ENUMTYPE meshtastic_HardwareModel
+#define meshtastic_User_role_ENUMTYPE meshtastic_Config_DeviceConfig_Role
#define meshtastic_Routing_variant_error_reason_ENUMTYPE meshtastic_Routing_Error
@@ -854,7 +857,7 @@ extern "C" {
/* Initializer values for message structs */
#define meshtastic_Position_init_default {0, 0, 0, 0, _meshtastic_Position_LocSource_MIN, _meshtastic_Position_AltSource_MIN, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
-#define meshtastic_User_init_default {"", "", "", {0}, _meshtastic_HardwareModel_MIN, 0}
+#define meshtastic_User_init_default {"", "", "", {0}, _meshtastic_HardwareModel_MIN, 0, _meshtastic_Config_DeviceConfig_Role_MIN}
#define meshtastic_RouteDiscovery_init_default {0, {0, 0, 0, 0, 0, 0, 0, 0}}
#define meshtastic_Routing_init_default {0, {meshtastic_RouteDiscovery_init_default}}
#define meshtastic_Data_init_default {_meshtastic_PortNum_MIN, {0, {0}}, 0, 0, 0, 0, 0, 0}
@@ -872,7 +875,7 @@ extern "C" {
#define meshtastic_Neighbor_init_default {0, 0, 0, 0}
#define meshtastic_DeviceMetadata_init_default {"", 0, 0, 0, 0, 0, _meshtastic_Config_DeviceConfig_Role_MIN, 0, _meshtastic_HardwareModel_MIN, 0}
#define meshtastic_Position_init_zero {0, 0, 0, 0, _meshtastic_Position_LocSource_MIN, _meshtastic_Position_AltSource_MIN, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
-#define meshtastic_User_init_zero {"", "", "", {0}, _meshtastic_HardwareModel_MIN, 0}
+#define meshtastic_User_init_zero {"", "", "", {0}, _meshtastic_HardwareModel_MIN, 0, _meshtastic_Config_DeviceConfig_Role_MIN}
#define meshtastic_RouteDiscovery_init_zero {0, {0, 0, 0, 0, 0, 0, 0, 0}}
#define meshtastic_Routing_init_zero {0, {meshtastic_RouteDiscovery_init_zero}}
#define meshtastic_Data_init_zero {_meshtastic_PortNum_MIN, {0, {0}}, 0, 0, 0, 0, 0, 0}
@@ -919,6 +922,7 @@ extern "C" {
#define meshtastic_User_macaddr_tag 4
#define meshtastic_User_hw_model_tag 5
#define meshtastic_User_is_licensed_tag 6
+#define meshtastic_User_role_tag 7
#define meshtastic_RouteDiscovery_route_tag 1
#define meshtastic_Routing_route_request_tag 1
#define meshtastic_Routing_route_reply_tag 2
@@ -1047,7 +1051,8 @@ X(a, STATIC, SINGULAR, STRING, long_name, 2) \
X(a, STATIC, SINGULAR, STRING, short_name, 3) \
X(a, STATIC, SINGULAR, FIXED_LENGTH_BYTES, macaddr, 4) \
X(a, STATIC, SINGULAR, UENUM, hw_model, 5) \
-X(a, STATIC, SINGULAR, BOOL, is_licensed, 6)
+X(a, STATIC, SINGULAR, BOOL, is_licensed, 6) \
+X(a, STATIC, SINGULAR, UENUM, role, 7)
#define meshtastic_User_CALLBACK NULL
#define meshtastic_User_DEFAULT NULL
@@ -1280,13 +1285,13 @@ extern const pb_msgdesc_t meshtastic_DeviceMetadata_msg;
#define meshtastic_MyNodeInfo_size 18
#define meshtastic_NeighborInfo_size 258
#define meshtastic_Neighbor_size 22
-#define meshtastic_NodeInfo_size 261
+#define meshtastic_NodeInfo_size 263
#define meshtastic_Position_size 137
#define meshtastic_QueueStatus_size 23
#define meshtastic_RouteDiscovery_size 40
#define meshtastic_Routing_size 42
#define meshtastic_ToRadio_size 504
-#define meshtastic_User_size 77
+#define meshtastic_User_size 79
#define meshtastic_Waypoint_size 165
#ifdef __cplusplus
diff --git a/src/modules/Telemetry/PowerTelemetry.cpp b/src/modules/Telemetry/PowerTelemetry.cpp
index 53e26ee6a..032d7fc27 100644
--- a/src/modules/Telemetry/PowerTelemetry.cpp
+++ b/src/modules/Telemetry/PowerTelemetry.cpp
@@ -11,11 +11,6 @@
#include "sleep.h"
#include "target_specific.h"
-#if HAS_TELEMETRY && !defined(ARCH_PORTDUINO)
-#include "Sensor/INA3221Sensor.h"
-INA3221Sensor ina3221Sensor;
-#endif
-
#define FAILED_STATE_SENSOR_READ_MULTIPLIER 10
#define DISPLAY_RECEIVEID_MEASUREMENTS_ON_SCREEN true
diff --git a/src/modules/Telemetry/Sensor/INA3221Sensor.cpp b/src/modules/Telemetry/Sensor/INA3221Sensor.cpp
index 634f5a5c9..3269ba47a 100644
--- a/src/modules/Telemetry/Sensor/INA3221Sensor.cpp
+++ b/src/modules/Telemetry/Sensor/INA3221Sensor.cpp
@@ -13,8 +13,9 @@ int32_t INA3221Sensor::runOnce()
return DEFAULT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS;
}
if (!status) {
- ina3221.setAddr(INA3221_ADDR42_SDA);
+ ina3221.setAddr(INA3221_ADDR42_SDA); // i2c address 0x42
ina3221.begin();
+ ina3221.setShuntRes(100, 100, 100); // 0.1 Ohm shunt resistors
status = true;
} else {
status = true;
diff --git a/src/modules/Telemetry/Sensor/INA3221Sensor.h b/src/modules/Telemetry/Sensor/INA3221Sensor.h
index a1c0fb2a7..4c82fc34d 100644
--- a/src/modules/Telemetry/Sensor/INA3221Sensor.h
+++ b/src/modules/Telemetry/Sensor/INA3221Sensor.h
@@ -1,16 +1,19 @@
#include "../mesh/generated/meshtastic/telemetry.pb.h"
#include "TelemetrySensor.h"
+#include "VoltageSensor.h"
#include
-class INA3221Sensor : public TelemetrySensor
+class INA3221Sensor : public TelemetrySensor, VoltageSensor
{
+ private:
+ INA3221 ina3221 = INA3221(INA3221_ADDR42_SDA);
+
+ protected:
+ void setup() override;
+
public:
INA3221Sensor();
int32_t runOnce() override;
- void setup() override;
bool getMetrics(meshtastic_Telemetry *measurement) override;
- virtual uint16_t getBusVoltageMv();
-
- private:
- INA3221 ina3221 = INA3221(INA3221_ADDR42_SDA);
+ virtual uint16_t getBusVoltageMv() override;
};
\ No newline at end of file
diff --git a/src/nimble/NimbleBluetooth.cpp b/src/nimble/NimbleBluetooth.cpp
index 1f06b25f2..3175e0f09 100644
--- a/src/nimble/NimbleBluetooth.cpp
+++ b/src/nimble/NimbleBluetooth.cpp
@@ -9,6 +9,7 @@
#include
NimBLECharacteristic *fromNumCharacteristic;
+NimBLECharacteristic *BatteryCharacteristic;
NimBLEServer *bleServer;
static bool passkeyShowing;
@@ -181,6 +182,18 @@ void NimbleBluetooth::setupService()
FromRadioCharacteristic->setCallbacks(fromRadioCallbacks);
bleService->start();
+
+ // Setup the battery service
+ NimBLEService *batteryService = bleServer->createService(NimBLEUUID((uint16_t)0x180f)); // 0x180F is the Battery Service
+ BatteryCharacteristic = batteryService->createCharacteristic( // 0x2A19 is the Battery Level characteristic)
+ (uint16_t)0x2a19, NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::NOTIFY);
+
+ NimBLE2904 *batteryLevelDescriptor = (NimBLE2904 *)BatteryCharacteristic->createDescriptor((uint16_t)0x2904);
+ batteryLevelDescriptor->setFormat(NimBLE2904::FORMAT_UINT8);
+ batteryLevelDescriptor->setNamespace(1);
+ batteryLevelDescriptor->setUnit(0x27ad);
+
+ batteryService->start();
}
void NimbleBluetooth::startAdvertising()
@@ -188,13 +201,15 @@ void NimbleBluetooth::startAdvertising()
NimBLEAdvertising *pAdvertising = NimBLEDevice::getAdvertising();
pAdvertising->reset();
pAdvertising->addServiceUUID(MESH_SERVICE_UUID);
+ pAdvertising->addServiceUUID(NimBLEUUID((uint16_t)0x180f)); // 0x180F is the Battery Service
pAdvertising->start(0);
}
/// Given a level between 0-100, update the BLE attribute
void updateBatteryLevel(uint8_t level)
{
- // blebas.write(level);
+ BatteryCharacteristic->setValue(&level, 1);
+ BatteryCharacteristic->notify();
}
void NimbleBluetooth::clearBonds()
diff --git a/src/platform/esp32/architecture.h b/src/platform/esp32/architecture.h
index 163cc8b84..0686aa59f 100644
--- a/src/platform/esp32/architecture.h
+++ b/src/platform/esp32/architecture.h
@@ -127,12 +127,20 @@
// LoRa SPI
// -----------------------------------------------------------------------------
-// NRF52 boards will define this in variant.h
-#ifndef RF95_SCK
-#define RF95_SCK 5
-#define RF95_MISO 19
-#define RF95_MOSI 27
-#define RF95_NSS 18
+// If an SPI-related pin used by the LoRa module isn't defined, use the conventional pin number for it.
+// FIXME: these pins should really be defined in each variant.h file to prevent breakages if the defaults change, currently many
+// ESP32 variants don't define these pins in their variant.h file.
+#ifndef LORA_SCK
+#define LORA_SCK 5
+#endif
+#ifndef LORA_MISO
+#define LORA_MISO 19
+#endif
+#ifndef LORA_MOSI
+#define LORA_MOSI 27
+#endif
+#ifndef LORA_CS
+#define LORA_CS 18
#endif
-#define SERIAL0_RX_GPIO 3 // Always GPIO3 on ESP32
\ No newline at end of file
+#define SERIAL0_RX_GPIO 3 // Always GPIO3 on ESP32 // FIXME: may be different on ESP32-S3, etc.
\ No newline at end of file
diff --git a/src/platform/portduino/PiHal.h b/src/platform/portduino/PiHal.h
deleted file mode 100644
index f10040583..000000000
--- a/src/platform/portduino/PiHal.h
+++ /dev/null
@@ -1,155 +0,0 @@
-#ifndef PI_HAL_H
-#define PI_HAL_H
-
-// include RadioLib
-#include
-
-// include the library for Raspberry GPIO pins
-#include "pigpio.h"
-
-// create a new Raspberry Pi hardware abstraction layer
-// using the pigpio library
-// the HAL must inherit from the base RadioLibHal class
-// and implement all of its virtual methods
-class PiHal : public RadioLibHal
-{
- public:
- // default constructor - initializes the base HAL and any needed private members
- PiHal(uint8_t spiChannel, uint32_t spiSpeed = 2000000)
- : RadioLibHal(PI_INPUT, PI_OUTPUT, PI_LOW, PI_HIGH, RISING_EDGE, FALLING_EDGE), _spiChannel(spiChannel),
- _spiSpeed(spiSpeed)
- {
- }
-
- void init() override
- {
- // first initialise pigpio library
- gpioInitialise();
-
- // now the SPI
- spiBegin();
-
- // Waveshare LoRaWAN Hat also needs pin 18 to be pulled high to enable the radio
- // gpioSetMode(18, PI_OUTPUT);
- // gpioWrite(18, PI_HIGH);
- }
-
- void term() override
- {
- // stop the SPI
- spiEnd();
-
- // pull the enable pin low
- // gpioSetMode(18, PI_OUTPUT);
- // gpioWrite(18, PI_LOW);
-
- // finally, stop the pigpio library
- gpioTerminate();
- }
-
- // GPIO-related methods (pinMode, digitalWrite etc.) should check
- // RADIOLIB_NC as an alias for non-connected pins
- void pinMode(uint32_t pin, uint32_t mode) override
- {
- if (pin == RADIOLIB_NC) {
- return;
- }
-
- gpioSetMode(pin, mode);
- }
-
- void digitalWrite(uint32_t pin, uint32_t value) override
- {
- if (pin == RADIOLIB_NC) {
- return;
- }
-
- gpioWrite(pin, value);
- }
-
- uint32_t digitalRead(uint32_t pin) override
- {
- if (pin == RADIOLIB_NC) {
- return (0);
- }
-
- return (gpioRead(pin));
- }
-
- void attachInterrupt(uint32_t interruptNum, void (*interruptCb)(void), uint32_t mode) override
- {
- if (interruptNum == RADIOLIB_NC) {
- return;
- }
- if (gpioRead(interruptNum) == 1) {
- interruptCb();
- } else {
- gpioSetAlertFunc(interruptNum, (gpioISRFunc_t)interruptCb);
- }
- }
-
- void detachInterrupt(uint32_t interruptNum) override
- {
- if (interruptNum == RADIOLIB_NC) {
- return;
- }
-
- gpioSetAlertFunc(interruptNum, NULL);
- }
-
- void delay(unsigned long ms) override { gpioDelay(ms * 1000); }
-
- void delayMicroseconds(unsigned long us) override { gpioDelay(us); }
-
- unsigned long millis() override { return (gpioTick() / 1000); }
-
- unsigned long micros() override { return (gpioTick()); }
-
- long pulseIn(uint32_t pin, uint32_t state, unsigned long timeout) override
- {
- if (pin == RADIOLIB_NC) {
- return (0);
- }
-
- this->pinMode(pin, PI_INPUT);
- uint32_t start = this->micros();
- uint32_t curtick = this->micros();
-
- while (this->digitalRead(pin) == state) {
- if ((this->micros() - curtick) > timeout) {
- return (0);
- }
- }
-
- return (this->micros() - start);
- }
-
- void spiBegin()
- {
- if (_spiHandle < 0) {
- _spiHandle = spiOpen(_spiChannel, _spiSpeed, 0);
- }
- }
-
- void spiBeginTransaction() {}
-
- void spiTransfer(uint8_t *out, size_t len, uint8_t *in) { spiXfer(_spiHandle, (char *)out, (char *)in, len); }
-
- void spiEndTransaction() {}
-
- void spiEnd()
- {
- if (_spiHandle >= 0) {
- spiClose(_spiHandle);
- _spiHandle = -1;
- }
- }
-
- private:
- // the HAL can contain any additional private members
- const unsigned int _spiSpeed;
- const uint8_t _spiChannel;
- int _spiHandle = -1;
-};
-
-#endif
\ No newline at end of file
diff --git a/src/platform/portduino/PortduinoGlue.cpp b/src/platform/portduino/PortduinoGlue.cpp
index fb71a429b..06e18eb91 100644
--- a/src/platform/portduino/PortduinoGlue.cpp
+++ b/src/platform/portduino/PortduinoGlue.cpp
@@ -9,7 +9,15 @@
#include
#ifdef ARCH_RASPBERRY_PI
+#include "PortduinoGlue.h"
+#include "linux/gpio/LinuxGPIOPin.h"
#include "pigpio.h"
+#include "yaml-cpp/yaml.h"
+#include
+#include