diff --git a/.github/workflows/main_matrix.yml b/.github/workflows/main_matrix.yml
index 8d76cfdac..18ecb22ed 100644
--- a/.github/workflows/main_matrix.yml
+++ b/.github/workflows/main_matrix.yml
@@ -34,9 +34,8 @@ jobs:
- board: heltec-v2.1
- board: tbeam0.7
- board: meshtastic-diy-v1
- - board: rak4631_5005
- - board: rak4631_19003
- - board: rak4631_5005_eink
+ - board: rak4631
+ - board: rak4631_eink
- board: t-echo
runs-on: ubuntu-latest
@@ -117,7 +116,8 @@ jobs:
- name: Upgrade python tools
run: |
python -m pip install --upgrade pip
- pip install -U platformio meshtastic adafruit-nrfutil littlefs-python
+ pip install -U platformio adafruit-nrfutil littlefs-python
+ pip install -U --pre meshtastic
- name: Upgrade platformio
run: |
@@ -158,9 +158,8 @@ jobs:
max-parallel: 2
matrix:
include:
- - board: rak4631_5005
- - board: rak4631_19003
- - board: rak4631_5005_eink
+ - board: rak4631
+ - board: rak4631_eink
- board: t-echo
- board: pca10059_diy_eink
@@ -188,7 +187,8 @@ jobs:
- name: Upgrade python tools
run: |
python -m pip install --upgrade pip
- pip install -U platformio meshtastic adafruit-nrfutil
+ pip install -U platformio adafruit-nrfutil
+ pip install -U --pre meshtastic
- name: Upgrade platformio
run: |
@@ -235,7 +235,8 @@ jobs:
- name: Upgrade python tools
run: |
python -m pip install --upgrade pip
- pip install -U platformio meshtastic adafruit-nrfutil
+ pip install -U platformio adafruit-nrfutil
+ pip install -U --pre meshtastic
- name: Upgrade platformio
run: |
diff --git a/.gitmodules b/.gitmodules
index 4f9bb6b77..59efcedd3 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -1,9 +1,6 @@
[submodule "proto"]
path = proto
url = https://github.com/meshtastic/Meshtastic-protobufs.git
-[submodule "sdk-nrfxlib"]
- path = sdk-nrfxlib
- url = https://github.com/nrfconnect/sdk-nrfxlib.git
[submodule "design"]
path = design
url = https://github.com/meshtastic/meshtastic-design.git
diff --git a/README.md b/README.md
index 43b357fd3..4876607e4 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
# Meshtastic-device
[![Open in Visual Studio Code](https://open.vscode.dev/badges/open-in-vscode.svg)](https://open.vscode.dev/meshtastic/Meshtastic-device)
-[![Continuous Integration](https://github.com/meshtastic/Meshtastic-device/actions/workflows/main.yml/badge.svg)](https://github.com/meshtastic/Meshtastic-device/actions/workflows/main.yml)
+[![Continuous Integration](https://github.com/meshtastic/Meshtastic-device/actions/workflows/main_matrix.yml/badge.svg)](https://github.com/meshtastic/Meshtastic-device/actions/workflows/main_matrix.yml)
![GitHub all releases](https://img.shields.io/github/downloads/meshtastic/meshtastic-device/total)
[![CLA assistant](https://cla-assistant.io/readme/badge/meshtastic/Meshtastic-device)](https://cla-assistant.io/meshtastic/Meshtastic-device)
[![Fiscal Contributors](https://opencollective.com/meshtastic/tiers/badge.svg)](https://opencollective.com/meshtastic/)
diff --git a/bin/build-all.sh b/bin/build-all.sh
index a92a04745..6ab69d3ef 100755
--- a/bin/build-all.sh
+++ b/bin/build-all.sh
@@ -9,7 +9,7 @@ BOARDS_ESP32="rak11200 tlora-v2 tlora-v1 tlora_v1_3 tlora-v2-1-1.6 tbeam heltec-
#BOARDS_ESP32=tbeam
# FIXME note nrf52840dk build is for some reason only generating a BIN file but not a HEX file nrf52840dk-geeksville is fine
-BOARDS_NRF52="rak4631_5005 rak4631_5005_eink rak4631_19003 t-echo pca10059_diy_eink"
+BOARDS_NRF52="rak4631 rak4631_eink t-echo pca10059_diy_eink"
#BOARDS_NRF52=""
OUTDIR=release/latest
diff --git a/bin/check-all.sh b/bin/check-all.sh
index f18f87f15..e6db5b959 100755
--- a/bin/check-all.sh
+++ b/bin/check-all.sh
@@ -13,7 +13,7 @@ if [[ $# -gt 0 ]]; then
# can override which environment by passing arg
BOARDS="$@"
else
- BOARDS="tlora-v2 tlora-v1 tlora_v1_3 tlora-v2-1-1.6 tbeam heltec-v1 heltec-v2.0 heltec-v2.1 tbeam0.7 meshtastic-diy-v1 rak4631_5005 rak4631_19003 rak11200 t-echo pca10059_diy_eink"
+ BOARDS="tlora-v2 tlora-v1 tlora_v1_3 tlora-v2-1-1.6 tbeam heltec-v1 heltec-v2.0 heltec-v2.1 tbeam0.7 meshtastic-diy-v1 rak4631 rak4631_eink rak11200 t-echo pca10059_diy_eink"
fi
echo "BOARDS:${BOARDS}"
diff --git a/boards/rak815.json b/boards/rak815.json
deleted file mode 100644
index 5411362af..000000000
--- a/boards/rak815.json
+++ /dev/null
@@ -1,55 +0,0 @@
-{
- "build": {
- "arduino":{
- "ldscript": "nrf52832_s132_v6.ld"
- },
- "core": "nRF5",
- "cpu": "cortex-m4",
- "extra_flags": "-DNRF52832_XXAA -DNRF52",
- "f_cpu": "64000000L",
- "hwids": [
- [
- "0x10c4",
- "0xea60"
- ]
- ],
- "usb_product": "RAK815",
- "mcu": "nrf52832",
- "variant": "rak815",
- "bsp": {
- "name": "adafruit"
- },
- "softdevice": {
- "sd_flags": "-DS132",
- "sd_name": "s132",
- "sd_version": "6.1.1",
- "sd_fwid": "0x00B7"
- }
- },
- "connectivity": [
- "bluetooth"
- ],
- "debug": {
- "jlink_device": "nRF52832_xxAA",
- "svd_path": "nrf52.svd"
- },
- "frameworks": [
- "arduino"
- ],
- "name": "RAK RAK815",
- "upload": {
- "maximum_ram_size": 65536,
- "maximum_size": 524288,
- "require_upload_port": true,
- "speed": 115200,
- "protocol": "nrfutil",
- "protocols": [
- "jlink",
- "nrfjprog",
- "nrfutil",
- "stlink"
- ]
- },
- "url": "https://store.rakwireless.com/products/rak815-hybrid-location-tracker",
- "vendor": "RAK"
-}
diff --git a/platformio.ini b/platformio.ini
index 67c6ae9b3..bb051e5e2 100644
--- a/platformio.ini
+++ b/platformio.ini
@@ -16,9 +16,6 @@ default_envs = tbeam
;default_envs = t-echo
;default_envs = nrf52840dk-geeksville
;default_envs = native # lora-relay-v1 # nrf52840dk-geeksville # linux # or if you'd like to change the default to something like lora-relay-v1 put that here
-;default_envs = rak4631_5005
-;default_envs = rak4631_5005_eink
-;default_envs = rak4631_19003
;default_envs = nano-g1
;default_envs = pca10059_diy_eink
;default_envs = meshtastic-diy-v1
@@ -84,7 +81,7 @@ lib_deps =
; Common settings for ESP targes, mixin with extends = esp32_base
[esp32_base]
extends = arduino_base
-platform = espressif32
+platform = espressif32@3.5.0
src_filter =
${arduino_base.src_filter} -
upload_speed = 921600
@@ -132,8 +129,7 @@ build_type = debug ; I'm debugging with ICE a lot now
; note: liboberon provides the AES256 implementation for NRF52 (though not using the hardware acceleration of the NRF52840 - FIXME)
build_flags =
${arduino_base.build_flags} -Wno-unused-variable
- -Isrc/nrf52
- -Isdk-nrfxlib/crypto/nrf_oberon/include -Lsdk-nrfxlib/crypto/nrf_oberon/lib/cortex-m4/hard-float/ -lliboberon_3.0.7
+ -Isrc/nrf52
src_filter =
${arduino_base.src_filter} - - - - - -
lib_ignore =
@@ -145,7 +141,7 @@ build_flags = ${nrf52_base.build_flags}
lib_deps =
${arduino_base.lib_deps}
${environmental.lib_deps}
- Adafruit nRFCrypto
+ https://github.com/Kongduino/Adafruit_nRFCrypto.git
; Note: By default no lora device is created for this build - it uses a simulated interface
[env:nrf52840dk]
@@ -156,10 +152,3 @@ board = nrf52840_dk
[env:feather_nrf52832]
extends = nrf52_base
board = adafruit_feather_nrf52832
-
-[env:rak815]
-extends = nrf52_base
-board = rak815
-debug_tool = jlink
-upload_protocol = jlink
-monitor_speed = 115200
diff --git a/sdk-nrfxlib b/sdk-nrfxlib
deleted file mode 160000
index e6e02cb83..000000000
--- a/sdk-nrfxlib
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit e6e02cb83d238fae2f54f084858bd5e49a31afa1
diff --git a/src/debug/einkScan.h b/src/debug/einkScan.h
new file mode 100644
index 000000000..a2509a45a
--- /dev/null
+++ b/src/debug/einkScan.h
@@ -0,0 +1,60 @@
+#include "../configuration.h"
+
+#ifdef RAK4630
+#include "../main.h"
+#include
+
+void d_writeCommand(uint8_t c)
+{
+ SPI1.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);
+ if (PIN_EINK_CS >= 0) digitalWrite(PIN_EINK_CS, HIGH);
+ if (PIN_EINK_DC >= 0) digitalWrite(PIN_EINK_DC, HIGH);
+ SPI1.endTransaction();
+}
+
+void d_writeData(uint8_t d)
+{
+ SPI1.beginTransaction(SPISettings(4000000, MSBFIRST, SPI_MODE0));
+ if (PIN_EINK_CS >= 0) digitalWrite(PIN_EINK_CS, LOW);
+ SPI1.transfer(d);
+ if (PIN_EINK_CS >= 0) digitalWrite(PIN_EINK_CS, HIGH);
+ SPI1.endTransaction();
+}
+
+unsigned long d_waitWhileBusy(uint16_t busy_time)
+{
+ if (PIN_EINK_BUSY >= 0)
+ {
+ delay(1); // add some margin to become active
+ unsigned long start = micros();
+ while (1)
+ {
+ if (digitalRead(PIN_EINK_BUSY) != HIGH) break;
+ delay(1);
+ if (digitalRead(PIN_EINK_BUSY) != HIGH) break;
+ if (micros() - start > 10000000) break;
+ }
+ unsigned long elapsed = micros() - start;
+ (void) start;
+ return elapsed;
+ }
+ else return busy_time;
+}
+
+void scanEInkDevice(void)
+{
+ SPI1.begin();
+ d_writeCommand(0x22);
+ d_writeData(0x83);
+ d_writeCommand(0x20);
+ eink_found = (d_waitWhileBusy(150) > 0) ? true : false;
+ if(eink_found)
+ DEBUG_MSG("EInk display found\n");
+ else
+ DEBUG_MSG("EInk display not found\n");
+ SPI1.end();
+}
+#endif
diff --git a/src/debug/i2cScan.h b/src/debug/i2cScan.h
index 9e7a49a62..4279a5122 100644
--- a/src/debug/i2cScan.h
+++ b/src/debug/i2cScan.h
@@ -54,6 +54,7 @@ void scanI2Cdevice(void)
DEBUG_MSG("unknown display found\n");
}
}
+
if (addr == CARDKB_ADDR) {
cardkb_found = addr;
DEBUG_MSG("m5 cardKB found\n");
diff --git a/src/gps/GPS.cpp b/src/gps/GPS.cpp
index aa92d96c8..57647472c 100644
--- a/src/gps/GPS.cpp
+++ b/src/gps/GPS.cpp
@@ -16,12 +16,6 @@ HardwareSerial *GPS::_serial_gps = &Serial1;
HardwareSerial *GPS::_serial_gps = NULL;
#endif
-#ifdef GPS_I2C_ADDRESS
-uint8_t GPS::i2cAddress = GPS_I2C_ADDRESS;
-#else
-uint8_t GPS::i2cAddress = 0;
-#endif
-
GPS *gps;
/// Multiple GPS instances might use the same serial port (in sequence), but we can
@@ -325,10 +319,6 @@ int GPS::prepareDeepSleep(void *unused)
return 0;
}
-#ifdef GPS_TX_PIN
-#include "UBloxGPS.h"
-#endif
-
#ifndef NO_GPS
#include "NMEAGPS.h"
#endif
@@ -345,25 +335,9 @@ GPS *createGps()
#else
DEBUG_MSG("Using MSL altitude model\n");
#endif
-// If we don't have bidirectional comms, we can't even try talking to UBLOX
-#ifdef GPS_TX_PIN
- // Init GPS - first try ublox
- UBloxGPS *ublox = new UBloxGPS();
-
- if (!ublox->setup()) {
- DEBUG_MSG("ERROR: No UBLOX GPS found\n");
- delete ublox;
- ublox = NULL;
- } else {
- DEBUG_MSG("Using UBLOX Mode\n");
- return ublox;
- }
-#endif
-
if (GPS::_serial_gps) {
// Some boards might have only the TX line from the GPS connected, in that case, we can't configure it at all. Just
// assume NMEA at 9600 baud.
- DEBUG_MSG("Using NMEA Mode\n");
GPS *new_gps = new NMEAGPS();
new_gps->setup();
return new_gps;
diff --git a/src/gps/GPS.h b/src/gps/GPS.h
index 8d4833590..999f88bfa 100644
--- a/src/gps/GPS.h
+++ b/src/gps/GPS.h
@@ -40,9 +40,6 @@ class GPS : private concurrency::OSThread
/** If !NULL we will use this serial port to construct our GPS */
static HardwareSerial *_serial_gps;
- /** If !0 we will attempt to connect to the GPS over I2C */
- static uint8_t i2cAddress;
-
Position p = Position_init_default;
GPS() : concurrency::OSThread("GPS") {}
diff --git a/src/gps/NMEAGPS.cpp b/src/gps/NMEAGPS.cpp
index 5c1ebafa0..73031139a 100644
--- a/src/gps/NMEAGPS.cpp
+++ b/src/gps/NMEAGPS.cpp
@@ -64,11 +64,12 @@ The Unix epoch (or Unix time or POSIX time or Unix timestamp) is the number of s
t.tm_mon = d.month() - 1;
t.tm_year = d.year() - 1900;
t.tm_isdst = false;
- DEBUG_MSG("NMEA GPS time %d-%d-%d %d:%d:%d\n", d.year(), d.month(), t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec);
-
- perhapsSetRTC(RTCQualityGPS, t);
-
- return true;
+ if (t.tm_mon > -1){
+ DEBUG_MSG("NMEA GPS time %d-%d-%d %d:%d:%d\n", d.year(), d.month(), t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec);
+ perhapsSetRTC(RTCQualityGPS, t);
+ return true;
+ } else
+ return false;
} else
return false;
}
@@ -128,8 +129,10 @@ bool NMEAGPS::lookForLocation()
auto loc = reader.location.value();
// Bail out EARLY to avoid overwriting previous good data (like #857)
- if(toDegInt(loc.lat) == 0) {
- DEBUG_MSG("Ignoring bogus NMEA position\n");
+ if((toDegInt(loc.lat) == 0) || (toDegInt(loc.lat) > 90)) {
+ return false;
+ }
+ if((toDegInt(loc.lng) == 0) || (toDegInt(loc.lng) > 180)) {
return false;
}
diff --git a/src/gps/UBloxGPS.cpp b/src/gps/UBloxGPS.cpp
deleted file mode 100644
index 70fc91ecd..000000000
--- a/src/gps/UBloxGPS.cpp
+++ /dev/null
@@ -1,328 +0,0 @@
-#include "configuration.h"
-#include "UBloxGPS.h"
-#include "RTC.h"
-#include "error.h"
-#include "sleep.h"
-#include
-
-// if gps_update_interval below this value, do not powercycle the GPS
-#define UBLOX_POWEROFF_THRESHOLD 90
-
-#define PDOP_INVALID 9999
-
-// #define UBX_MODE_NMEA
-
-extern RadioConfig radioConfig;
-
-UBloxGPS::UBloxGPS() {}
-
-bool UBloxGPS::tryConnect()
-{
- bool c = false;
-
- if (_serial_gps)
- c = ublox.begin(*_serial_gps);
-
- if (!c && i2cAddress) {
- extern bool neo6M; // Super skanky - if we are talking to the device i2c we assume it is a neo7 on a RAK815, which
- // supports the newer API
- neo6M = true;
-
- c = ublox.begin(Wire, i2cAddress);
- }
-
- if (c)
- setConnected();
-
- return c;
-}
-
-bool UBloxGPS::setupGPS()
-{
- GPS::setupGPS();
-
- // uncomment to see debug info
- // ublox.enableDebugging(Serial);
-
- // try a second time, the ublox lib serial parsing is buggy?
- // see https://github.com/meshtastic/Meshtastic-device/issues/376
- for (int i = 0; (i < 3) && !tryConnect(); i++)
- delay(500);
-
- if (isConnected()) {
-#ifdef UBX_MODE_NMEA
- DEBUG_MSG("Connected to UBLOX GPS, downgrading to NMEA mode\n");
- DEBUG_MSG("- GPS errors below are related and safe to ignore\n");
-#else
- DEBUG_MSG("Connected to UBLOX GPS successfully\n");
-#endif
-
- if (!setUBXMode())
- RECORD_CRITICALERROR(CriticalErrorCode_UBloxInitFailed); // Don't halt the boot if saving the config fails, but do report the bug
-
-#ifdef UBX_MODE_NMEA
- return false;
-#else
- return true;
-#endif
-
- } else {
- return false;
- }
-}
-
-bool UBloxGPS::setUBXMode()
-{
-#ifdef UBX_MODE_NMEA
- if (_serial_gps) {
- ublox.setUART1Output(COM_TYPE_NMEA, 1000);
- }
- if (i2cAddress) {
- ublox.setI2COutput(COM_TYPE_NMEA, 1000);
- }
-
- return false; // pretend initialization failed to force NMEA mode
-#endif
-
- if (_serial_gps) {
- if (!ublox.setUART1Output(COM_TYPE_UBX, 1000)) // Use native API
- return false;
- }
- if (i2cAddress) {
- if (!ublox.setI2COutput(COM_TYPE_UBX, 1000))
- return false;
- }
-
- if (!ublox.setNavigationFrequency(1, 1000)) // Produce 4x/sec to keep the amount of time we stall in getPVT low
- return false;
-
- // ok = ublox.setAutoPVT(false); // Not implemented on NEO-6M
- // assert(ok);
- // ok = ublox.setDynamicModel(DYN_MODEL_BIKE); // probably PEDESTRIAN but just in case assume bike speeds
- // assert(ok);
-
- // per https://github.com/meshtastic/Meshtastic-device/issues/376 powerSaveMode might not work with the marginal
- // TTGO antennas
- // if (!ublox.powerSaveMode(true, 2000)) // use power save mode, the default timeout (1100ms seems a bit too tight)
- // return false;
-
- if (!ublox.saveConfiguration(3000))
- return false;
-
- return true;
-}
-
-/**
- * Reset our GPS back to factory settings
- *
- * @return true for success
- */
-bool UBloxGPS::factoryReset()
-{
- bool ok = false;
-
- // It is useful to force back into factory defaults (9600baud, NMEA to test the behavior of boards that don't have
- // GPS_TX connected)
- ublox.factoryReset();
- delay(5000);
- tryConnect(); // sets isConnected
-
- // try a second time, the ublox lib serial parsing is buggy?
- for (int i = 0; (i < 3) && !tryConnect(); i++)
- delay(500);
-
- DEBUG_MSG("GPS Factory reset success=%d\n", isConnected());
- if (isConnected())
- ok = setUBXMode();
-
- return ok;
-}
-
-/** Idle processing while GPS is looking for lock */
-void UBloxGPS::whileActive()
-{
- ublox.flushPVT(); // reset ALL freshness flags first
- ublox.getT(maxWait()); // ask for new time data - hopefully ready when we come back
-
- // Ask for a new position fix - hopefully it will have results ready by next time
- // the order here is important, because we only check for has latitude when reading
-
- //ublox.getSIV(maxWait()); // redundant with getPDOP below
- ublox.getPDOP(maxWait()); // will trigger getSOL on NEO6, getP on others
- ublox.getP(maxWait()); // will trigger getPosLLH on NEO6, getP on others
-
- // the fixType flag will be checked and updated in lookForLocation()
-}
-
-/**
- * Perform any processing that should be done only while the GPS is awake and looking for a fix.
- * Override this method to check for new locations
- *
- * @return true if we've acquired a new location
- */
-bool UBloxGPS::lookForTime()
-{
- if (ublox.moduleQueried.gpsSecond) {
- /* Convert to unix time
- The Unix epoch (or Unix time or POSIX time or Unix timestamp) is the number of seconds that have elapsed since January
- 1, 1970 (midnight UTC/GMT), not counting leap seconds (in ISO 8601: 1970-01-01T00:00:00Z).
- */
- struct tm t;
- t.tm_sec = ublox.getSecond(0);
- t.tm_min = ublox.getMinute(0);
- t.tm_hour = ublox.getHour(0);
- t.tm_mday = ublox.getDay(0);
- t.tm_mon = ublox.getMonth(0) - 1;
- t.tm_year = ublox.getYear(0) - 1900;
- t.tm_isdst = false;
- perhapsSetRTC(RTCQualityGPS, t);
- return true;
- }
-
- return false;
-}
-
-/**
- * Perform any processing that should be done only while the GPS is awake and looking for a fix.
- * Override this method to check for new locations
- *
- * @return true if we've acquired a new location
- */
-bool UBloxGPS::lookForLocation()
-{
- bool foundLocation = false;
-
- // check if a complete GPS solution set is available for reading
- // (some of these, like lat/lon are redundant and can be removed)
- if ( ! (ublox.moduleQueried.fixType &&
- ublox.moduleQueried.latitude &&
- ublox.moduleQueried.longitude &&
- ublox.moduleQueried.altitude &&
- ublox.moduleQueried.pDOP &&
- ublox.moduleQueried.SIV &&
- ublox.moduleQueried.gpsDay))
- {
- // Not ready? No problem! We'll try again later.
- return false;
- }
-
- fixType = ublox.getFixType();
-#ifdef UBLOX_EXTRAVERBOSE
- DEBUG_MSG("FixType=%d\n", fixType);
-#endif
-
-
- // check if GPS has an acceptable lock
- if (! hasLock()) {
- ublox.flushPVT(); // reset ALL freshness flags
- return false;
- }
-
- // read lat/lon/alt/dop data into temporary variables to avoid
- // overwriting global variables with potentially invalid data
- int32_t tmp_dop = ublox.getPDOP(0); // PDOP (an accuracy metric) is reported in 10^2 units so we have to scale down when we use it
- int32_t tmp_lat = ublox.getLatitude(0);
- int32_t tmp_lon = ublox.getLongitude(0);
- int32_t tmp_alt_msl = ublox.getAltitudeMSL(0);
- int32_t tmp_alt_hae = ublox.getAltitude(0);
- int32_t max_dop = PDOP_INVALID;
- if (radioConfig.preferences.gps_max_dop)
- max_dop = radioConfig.preferences.gps_max_dop * 100; // scaling
-
- // Note: heading is only currently implmented in the ublox for the 8m chipset - therefore
- // don't read it here - it will generate an ignored getPVT command on the 6ms
- // heading = ublox.getHeading(0);
-
- // read positional timestamp
- struct tm t;
- t.tm_sec = ublox.getSecond(0);
- t.tm_min = ublox.getMinute(0);
- t.tm_hour = ublox.getHour(0);
- t.tm_mday = ublox.getDay(0);
- t.tm_mon = ublox.getMonth(0) - 1;
- t.tm_year = ublox.getYear(0) - 1900;
- t.tm_isdst = false;
-
- time_t tmp_ts = mktime(&t);
-
- // FIXME - can opportunistically attempt to set RTC from GPS timestamp?
-
- // bogus lat lon is reported as 0 or 0 (can be bogus just for one)
- // Also: apparently when the GPS is initially reporting lock it can output a bogus latitude > 90 deg!
- // FIXME - NULL ISLAND is a real location on Earth!
- foundLocation = (tmp_lat != 0) && (tmp_lon != 0) &&
- (tmp_lat <= 900000000) && (tmp_lat >= -900000000) &&
- (tmp_dop < max_dop);
-
- // only if entire dataset is valid, update globals from temp vars
- if (foundLocation) {
- p.location_source = Position_LocSource_LOCSRC_GPS_INTERNAL;
- p.longitude_i = tmp_lon;
- p.latitude_i = tmp_lat;
- if (fixType > 2) {
- // if fix is 2d, ignore altitude data
- p.altitude = tmp_alt_msl / 1000;
- p.altitude_hae = tmp_alt_hae / 1000;
- p.alt_geoid_sep = (tmp_alt_hae - tmp_alt_msl) / 1000;
- } else {
-#ifdef GPS_EXTRAVERBOSE
- DEBUG_MSG("no altitude data (fixType=%d)\n", fixType);
-#endif
- // clean up old values in case it's a 3d-2d fix transition
- p.altitude = p.altitude_hae = p.alt_geoid_sep = 0;
- }
- p.pos_timestamp = tmp_ts;
- p.PDOP = tmp_dop;
- p.fix_type = fixType;
- p.sats_in_view = ublox.getSIV(0);
- // In debug logs, identify position by @timestamp:stage (stage 1 = birth)
- DEBUG_MSG("lookForLocation() new pos@%x:1\n", tmp_ts);
- } else {
- // INVALID solution - should never happen
- DEBUG_MSG("Invalid location lat/lon/hae/dop %d/%d/%d/%d - discarded\n",
- tmp_lat, tmp_lon, tmp_alt_hae, tmp_dop);
- }
-
- ublox.flushPVT(); // reset ALL freshness flags at the end
-
- return foundLocation;
-}
-
-bool UBloxGPS::hasLock()
-{
- if (radioConfig.preferences.gps_accept_2d)
- return (fixType >= 2 && fixType <= 4);
- else
- return (fixType >= 3 && fixType <= 4);
-}
-
-bool UBloxGPS::whileIdle()
-{
- // if using i2c or serial look too see if any chars are ready
- return ublox.checkUblox(); // See if new data is available. Process bytes as they come in.
-}
-
-/// If possible force the GPS into sleep/low power mode
-/// Note: ublox doesn't need a wake method, because as soon as we send chars to the GPS it will wake up
-void UBloxGPS::sleep()
-{
- if (radioConfig.preferences.gps_update_interval > UBLOX_POWEROFF_THRESHOLD) {
- // Tell GPS to power down until we send it characters on serial port (we leave vcc connected)
- ublox.powerOff();
- // setGPSPower(false);
- }
-}
-
-void UBloxGPS::wake()
-{
- if (radioConfig.preferences.gps_update_interval > UBLOX_POWEROFF_THRESHOLD) {
- fixType = 0; // assume we have no fix yet
- }
-
- // this is idempotent
- setGPSPower(true);
-
- // Note: no delay needed because now we leave gps power on always and instead use ublox.powerOff()
- // Give time for the GPS to boot
- // delay(200);
-}
\ No newline at end of file
diff --git a/src/gps/UBloxGPS.h b/src/gps/UBloxGPS.h
deleted file mode 100644
index 3d940832f..000000000
--- a/src/gps/UBloxGPS.h
+++ /dev/null
@@ -1,72 +0,0 @@
-#pragma once
-
-#include "GPS.h"
-#include "Observer.h"
-#include "SparkFun_Ublox_Arduino_Library.h"
-
-/**
- * A gps class that only reads from the GPS periodically (and FIXME - eventually keeps the gps powered down except when reading)
- *
- * When new data is available it will notify observers.
- */
-class UBloxGPS : public GPS
-{
- SFE_UBLOX_GPS ublox;
- uint8_t fixType = 0;
-
- public:
- UBloxGPS();
-
- /**
- * Reset our GPS back to factory settings
- *
- * @return true for success
- */
- bool factoryReset() override;
-
- protected:
- /**
- * Returns true if we succeeded
- */
- virtual bool setupGPS() override;
-
- /** Subclasses should look for serial rx characters here and feed it to their GPS parser
- *
- * Return true if we received a valid message from the GPS
- */
- virtual bool whileIdle() override;
-
- /** Idle processing while GPS is looking for lock */
- virtual void whileActive() override;
-
- /**
- * Perform any processing that should be done only while the GPS is awake and looking for a fix.
- * Override this method to check for new locations
- *
- * @return true if we've acquired a time
- */
- virtual bool lookForTime() override;
-
- /**
- * Perform any processing that should be done only while the GPS is awake and looking for a fix.
- * Override this method to check for new locations
- *
- * @return true if we've acquired a new location
- */
- virtual bool lookForLocation() override;
- virtual bool hasLock() override;
-
- /// If possible force the GPS into sleep/low power mode
- virtual void sleep() override;
- virtual void wake() override;
-
- private:
- /// Attempt to connect to our GPS, returns false if no gps is present
- bool tryConnect();
-
- /// Switch to our desired operating mode and save the settings to flash
- /// returns true for success
- bool setUBXMode();
-
- uint16_t maxWait() const { return i2cAddress ? 300 : 0; /*If using i2c we must poll with wait */ }
-};
diff --git a/src/graphics/EInkDisplay2.cpp b/src/graphics/EInkDisplay2.cpp
index 47ced53c6..073b313cd 100644
--- a/src/graphics/EInkDisplay2.cpp
+++ b/src/graphics/EInkDisplay2.cpp
@@ -1,6 +1,7 @@
#include "configuration.h"
#ifdef HAS_EINK
+#include "main.h"
#include "EInkDisplay2.h"
#include "SPILock.h"
#include
@@ -171,18 +172,46 @@ bool EInkDisplay::connect()
}
#elif defined(RAK4630)
{
- auto lowLevel = new TECHO_DISPLAY_MODEL(PIN_EINK_CS, PIN_EINK_DC, PIN_EINK_RES, PIN_EINK_BUSY);
+ if (eink_found) {
+ auto lowLevel = new TECHO_DISPLAY_MODEL(PIN_EINK_CS, PIN_EINK_DC, PIN_EINK_RES, PIN_EINK_BUSY);
- adafruitDisplay = new GxEPD2_BW(*lowLevel);
-
- adafruitDisplay->init(115200, true, 10, false, SPI1, SPISettings(4000000, MSBFIRST, SPI_MODE0));
+ adafruitDisplay = new GxEPD2_BW(*lowLevel);
+
+ adafruitDisplay->init(115200, true, 10, false, SPI1, SPISettings(4000000, MSBFIRST, SPI_MODE0));
+ //RAK14000 2.13 inch b/w 250x122 does not support partial updates
//RAK14000 2.13 inch b/w 250x122 does not support partial updates
- adafruitDisplay->setRotation(3);
- //For 1.54, 2.9 and 4.2
- //adafruitDisplay->setRotation(1);
+ //RAK14000 2.13 inch b/w 250x122 does not support partial updates
+ //RAK14000 2.13 inch b/w 250x122 does not support partial updates
+ //RAK14000 2.13 inch b/w 250x122 does not support partial updates
+ //RAK14000 2.13 inch b/w 250x122 does not support partial updates
+ //RAK14000 2.13 inch b/w 250x122 does not support partial updates
+ //RAK14000 2.13 inch b/w 250x122 does not support partial updates
+ //RAK14000 2.13 inch b/w 250x122 does not support partial updates
+ //RAK14000 2.13 inch b/w 250x122 does not support partial updates
+ //RAK14000 2.13 inch b/w 250x122 does not support partial updates
+ //RAK14000 2.13 inch b/w 250x122 does not support partial updates
+ //RAK14000 2.13 inch b/w 250x122 does not support partial updates
+ adafruitDisplay->setRotation(3);
+ //For 1.54, 2.9 and 4.2
+ //adafruitDisplay->setRotation(1);
+ adafruitDisplay->setPartialWindow(0, 0, displayWidth, displayHeight);
adafruitDisplay->setPartialWindow(0, 0, displayWidth, displayHeight);
+ adafruitDisplay->setPartialWindow(0, 0, displayWidth, displayHeight);
+ adafruitDisplay->setPartialWindow(0, 0, displayWidth, displayHeight);
+ adafruitDisplay->setPartialWindow(0, 0, displayWidth, displayHeight);
+ adafruitDisplay->setPartialWindow(0, 0, displayWidth, displayHeight);
+ adafruitDisplay->setPartialWindow(0, 0, displayWidth, displayHeight);
+ adafruitDisplay->setPartialWindow(0, 0, displayWidth, displayHeight);
+ adafruitDisplay->setPartialWindow(0, 0, displayWidth, displayHeight);
+ adafruitDisplay->setPartialWindow(0, 0, displayWidth, displayHeight);
+ adafruitDisplay->setPartialWindow(0, 0, displayWidth, displayHeight);
+ adafruitDisplay->setPartialWindow(0, 0, displayWidth, displayHeight);
+ adafruitDisplay->setPartialWindow(0, 0, displayWidth, displayHeight);
+ } else {
+ (void)adafruitDisplay;
+ }
}
#elif defined(PCA10059)
{
diff --git a/src/graphics/Screen.cpp b/src/graphics/Screen.cpp
index a4bddaf17..edb3ebc45 100644
--- a/src/graphics/Screen.cpp
+++ b/src/graphics/Screen.cpp
@@ -815,12 +815,25 @@ void _screen_header()
}
#endif
+// #ifdef RAK4630
+// Screen::Screen(uint8_t address, int sda, int scl) : OSThread("Screen"), cmdQueue(32), dispdev(address, sda, scl), dispdev_oled(address, sda, scl), ui(&dispdev)
+// {
+// address_found = address;
+// cmdQueue.setReader(this);
+// if (screen_found) {
+// (void)dispdev;
+// AutoOLEDWire dispdev = dispdev_oled;
+// (void)ui;
+// OLEDDisplayUi ui(&dispdev);
+// }
+// }
+// #else
Screen::Screen(uint8_t address, int sda, int scl) : OSThread("Screen"), cmdQueue(32), dispdev(address, sda, scl), ui(&dispdev)
{
address_found = address;
cmdQueue.setReader(this);
}
-
+// #endif
/**
* Prepare the display for the unit going to the lowest power mode possible. Most screens will just
* poweroff, but eink screens will show a "I'm sleeping" graphic, possibly with a QR code
diff --git a/src/graphics/Screen.h b/src/graphics/Screen.h
index 59d68c902..259598b80 100644
--- a/src/graphics/Screen.h
+++ b/src/graphics/Screen.h
@@ -27,6 +27,10 @@ class Screen
#ifdef USE_ST7567
#include
+#elif defined(USE_SH1106)
+#include
+#elif defined(USE_SSD1306)
+#include
#else
// the SH1106/SSD1306 variant is auto-detected
#include
@@ -297,9 +301,16 @@ class Screen : public concurrency::OSThread
/// Holds state for debug information
DebugInfo debugInfo;
- /// Display device
- /** FIXME cleanup display abstraction */
-#ifdef ST7735_CS
+ /// Display device
+
+// #ifdef RAK4630
+// EInkDisplay dispdev;
+// AutoOLEDWire dispdev_oled;
+#ifdef USE_SH1106
+ SH1106Wire dispdev;
+#elif defined(USE_SSD1306)
+ SSD1306Wire dispdev;
+#elif defined(ST7735_CS)
TFTDisplay dispdev;
#elif defined(HAS_EINK)
EInkDisplay dispdev;
diff --git a/src/main.cpp b/src/main.cpp
index 5a7887608..afb162cee 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -24,6 +24,7 @@
#include "shutdown.h"
#include "target_specific.h"
#include "debug/i2cScan.h"
+#include "debug/einkScan.h"
#include "debug/axpDebug.h"
#include
// #include
@@ -78,6 +79,8 @@ uint8_t cardkb_found;
// The I2C address of the Faces Keyboard (if found)
uint8_t faceskb_found;
+bool eink_found = true;
+
uint32_t serialSinceMsec;
bool axp192_found;
@@ -208,6 +211,9 @@ void setup()
#endif
scanI2Cdevice();
+#ifdef RAK4630
+ // scanEInkDevice();
+#endif
// Buttons & LED
buttonThread = new ButtonThread();
diff --git a/src/main.h b/src/main.h
index 21138d3f0..fc91f396a 100644
--- a/src/main.h
+++ b/src/main.h
@@ -10,6 +10,7 @@ extern uint8_t screen_model;
extern uint8_t cardkb_found;
extern uint8_t faceskb_found;
+extern bool eink_found;
extern bool axp192_found;
extern bool isCharging;
extern bool isUSBPowered;
diff --git a/src/mesh/MeshPacketQueue.cpp b/src/mesh/MeshPacketQueue.cpp
index 87347f309..51af89df8 100644
--- a/src/mesh/MeshPacketQueue.cpp
+++ b/src/mesh/MeshPacketQueue.cpp
@@ -72,6 +72,16 @@ MeshPacket *MeshPacketQueue::dequeue()
return p;
}
+MeshPacket *MeshPacketQueue::getFront()
+{
+ if (empty()) {
+ return NULL;
+ }
+
+ auto *p = queue.front();
+ return p;
+}
+
/** Attempt to find and remove a packet from this queue. Returns a pointer to the removed packet, or NULL if not found */
MeshPacket *MeshPacketQueue::remove(NodeNum from, PacketId id)
{
diff --git a/src/mesh/MeshPacketQueue.h b/src/mesh/MeshPacketQueue.h
index c74addf4e..8c93b452e 100644
--- a/src/mesh/MeshPacketQueue.h
+++ b/src/mesh/MeshPacketQueue.h
@@ -28,6 +28,8 @@ class MeshPacketQueue
MeshPacket *dequeue();
+ MeshPacket *getFront();
+
/** Attempt to find and remove a packet from this queue. Returns the packet which was removed from the queue */
MeshPacket *remove(NodeNum from, PacketId id);
};
diff --git a/src/mesh/NodeDB.cpp b/src/mesh/NodeDB.cpp
index ad113e8ab..660280fcb 100644
--- a/src/mesh/NodeDB.cpp
+++ b/src/mesh/NodeDB.cpp
@@ -95,14 +95,16 @@ bool NodeDB::resetRadioConfig()
nvs_flash_erase();
#endif
#ifdef NRF52_SERIES
+ // first, remove the "/prefs" (this removes most prefs)
FSCom.rmdir_r("/prefs");
-
+ // second, install default state (this will deal with the duplicate mac address issue)
+ installDefaultDeviceState();
+ // third, write to disk
+ saveToDisk();
Bluefruit.begin();
-
DEBUG_MSG("Clearing bluetooth bonds!\n");
bond_print_list(BLE_GAP_ROLE_PERIPH);
bond_print_list(BLE_GAP_ROLE_CENTRAL);
-
Bluefruit.Periph.clearBonds();
Bluefruit.Central.clearBonds();
#endif
@@ -215,7 +217,7 @@ void NodeDB::init()
myNodeInfo.error_address = 0;
// likewise - we always want the app requirements to come from the running appload
- myNodeInfo.min_app_version = 20200; // format is Mmmss (where M is 1+the numeric major number. i.e. 20120 means 1.1.20
+ myNodeInfo.min_app_version = 20300; // format is Mmmss (where M is 1+the numeric major number. i.e. 20120 means 1.1.20
// Note! We do this after loading saved settings, so that if somehow an invalid nodenum was stored in preferences we won't
// keep using that nodenum forever. Crummy guess at our nodenum (but we will check against the nodedb to avoid conflicts)
diff --git a/src/mesh/ProtobufModule.h b/src/mesh/ProtobufModule.h
index dad0eade3..4e411c2a4 100644
--- a/src/mesh/ProtobufModule.h
+++ b/src/mesh/ProtobufModule.h
@@ -48,6 +48,17 @@ template class ProtobufModule : protected SinglePortModule
return p;
}
+ /**
+ * Gets the short name from the sender of the mesh packet
+ * Returns "???" if unknown sender
+ */
+ const char *getSenderShortName(const MeshPacket &mp)
+ {
+ auto node = nodeDB.getNode(getFrom(&mp));
+ const char *sender = (node) ? node->user.short_name : "???";
+ return sender;
+ }
+
private:
/** Called to handle a particular incoming message
diff --git a/src/mesh/RF95Interface.cpp b/src/mesh/RF95Interface.cpp
index adaeead46..a96b95100 100644
--- a/src/mesh/RF95Interface.cpp
+++ b/src/mesh/RF95Interface.cpp
@@ -176,6 +176,25 @@ void RF95Interface::startReceive()
enableInterrupt(isrRxLevel0);
}
+bool RF95Interface::isChannelActive()
+{
+ // check if we can detect a LoRa preamble on the current channel
+ int16_t result;
+ setTransmitEnable(false);
+ setStandby(); // needed for smooth transition
+ result = lora->scanChannel();
+
+ if (result == PREAMBLE_DETECTED) {
+ // DEBUG_MSG("Channel is busy!\n");
+ return true;
+ }
+
+ assert(result != ERR_WRONG_MODEM);
+
+ // DEBUG_MSG("Channel is free!\n");
+ return false;
+}
+
/** Could we send right now (i.e. either not actively receving or transmitting)? */
bool RF95Interface::isActivelyReceiving()
{
diff --git a/src/mesh/RF95Interface.h b/src/mesh/RF95Interface.h
index f62195a26..5e666ae8b 100644
--- a/src/mesh/RF95Interface.h
+++ b/src/mesh/RF95Interface.h
@@ -40,6 +40,9 @@ class RF95Interface : public RadioLibInterface
*/
virtual void enableInterrupt(void (*callback)()) { lora->setDio0Action(callback); }
+ /** can we detect a LoRa preamble on the current channel? */
+ virtual bool isChannelActive() override;
+
/** are we actively receiving a packet (only called during receiving state) */
virtual bool isActivelyReceiving() override;
diff --git a/src/mesh/RadioLibInterface.cpp b/src/mesh/RadioLibInterface.cpp
index 5f0e57210..a0058893a 100644
--- a/src/mesh/RadioLibInterface.cpp
+++ b/src/mesh/RadioLibInterface.cpp
@@ -118,20 +118,10 @@ ErrorCode RadioLibInterface::send(MeshPacket *p)
return res;
}
- // We want all sending/receiving to be done by our daemon thread, We use a delay here because this packet might have been sent
- // in response to a packet we just received. So we want to make sure the other side has had a chance to reconfigure its radio
-
- /* We assume if rx_snr = 0 and rx_rssi = 0, the packet was not generated locally.
- * This assumption is valid because of the offset generated by the radio to account for the noise
- * floor.
- */
- if (p->rx_snr == 0 && p->rx_rssi == 0) {
- startTransmitTimer(true);
- } else {
- // If there is a SNR, start a timer scaled based on that SNR.
- DEBUG_MSG("rx_snr found. hop_limit:%d rx_snr:%f\n", p->hop_limit, p->rx_snr);
- startTransmitTimerSNR(p->rx_snr);
- }
+ // set (random) transmit delay to let others reconfigure their radio,
+ // to avoid collisions and implement timing-based flooding
+ // DEBUG_MSG("Set random delay before transmitting.\n");
+ setTransmitDelay();
return res;
#else
@@ -164,8 +154,8 @@ bool RadioLibInterface::cancelSending(NodeNum from, PacketId id)
/** radio helper thread callback.
We never immediately transmit after any operation (either rx or tx). Instead we should start receiving and
-wait a random delay of 50 to 200 ms to make sure we are not stomping on someone else. The 50ms delay at the beginning ensures all
-possible listeners have had time to finish processing the previous packet and now have their radio in RX state. The up to 200ms
+wait a random delay of 100ms to 100ms+shortPacketMsec to make sure we are not stomping on someone else. The 100ms delay at the beginning ensures all
+possible listeners have had time to finish processing the previous packet and now have their radio in RX state. The up to 100ms+shortPacketMsec
random delay gives a chance for all possible senders to have high odds of detecting that someone else started transmitting first
and then they will wait until that packet finishes.
@@ -192,20 +182,26 @@ void RadioLibInterface::onNotify(uint32_t notification)
case TRANSMIT_DELAY_COMPLETED:
// DEBUG_MSG("delay done\n");
- // If we are not currently in receive mode, then restart the timer and try again later (this can happen if the main thread
+ // If we are not currently in receive mode, then restart the random delay (this can happen if the main thread
// has placed the unit into standby) FIXME, how will this work if the chipset is in sleep mode?
if (!txQueue.empty()) {
if (!canSendImmediately()) {
- startTransmitTimer(); // try again in a little while
+ // DEBUG_MSG("Currently Rx/Tx-ing: set random delay\n");
+ setTransmitDelay(); // currently Rx/Tx-ing: reset random delay
} else {
- // Send any outgoing packets we have ready
- MeshPacket *txp = txQueue.dequeue();
- assert(txp);
- startSend(txp);
+ if (isChannelActive()) { // check if there is currently a LoRa packet on the channel
+ // DEBUG_MSG("Channel is active: set random delay\n");
+ setTransmitDelay(); // reset random delay
+ } else {
+ // Send any outgoing packets we have ready
+ MeshPacket *txp = txQueue.dequeue();
+ assert(txp);
+ startSend(txp);
- // Packet has been sent, count it toward our TX airtime utilization.
- uint32_t xmitMsec = getPacketTime(txp);
- airTime->logAirtime(TX_LOG, xmitMsec);
+ // Packet has been sent, count it toward our TX airtime utilization.
+ uint32_t xmitMsec = getPacketTime(txp);
+ airTime->logAirtime(TX_LOG, xmitMsec);
+ }
}
} else {
// DEBUG_MSG("done with txqueue\n");
@@ -216,6 +212,26 @@ void RadioLibInterface::onNotify(uint32_t notification)
}
}
+void RadioLibInterface::setTransmitDelay()
+{
+ MeshPacket *p = txQueue.getFront();
+ // We want all sending/receiving to be done by our daemon thread.
+ // We use a delay here because this packet might have been sent in response to a packet we just received.
+ // So we want to make sure the other side has had a chance to reconfigure its radio.
+
+ /* We assume if rx_snr = 0 and rx_rssi = 0, the packet was generated locally.
+ * This assumption is valid because of the offset generated by the radio to account for the noise
+ * floor.
+ */
+ if (p->rx_snr == 0 && p->rx_rssi == 0) {
+ startTransmitTimer(true);
+ } else {
+ // If there is a SNR, start a timer scaled based on that SNR.
+ DEBUG_MSG("rx_snr found. hop_limit:%d rx_snr:%f\n", p->hop_limit, p->rx_snr);
+ startTransmitTimerSNR(p->rx_snr);
+ }
+}
+
void RadioLibInterface::startTransmitTimer(bool withDelay)
{
// If we have work to do and the timer wasn't already scheduled, schedule it now
diff --git a/src/mesh/RadioLibInterface.h b/src/mesh/RadioLibInterface.h
index 68dfe96d0..0f59c1fab 100644
--- a/src/mesh/RadioLibInterface.h
+++ b/src/mesh/RadioLibInterface.h
@@ -132,6 +132,9 @@ class RadioLibInterface : public RadioInterface, protected concurrency::Notified
*/
virtual void startReceive() = 0;
+ /** can we detect a LoRa preamble on the current channel? */
+ virtual bool isChannelActive() = 0;
+
/** are we actively receiving a packet (only called during receiving state)
* This method is only public to facilitate debugging. Do not call.
*/
@@ -141,18 +144,14 @@ class RadioLibInterface : public RadioInterface, protected concurrency::Notified
virtual bool cancelSending(NodeNum from, PacketId id) override;
private:
- /** if we have something waiting to send, start a short random timer so we can come check for collision before actually doing
- * the transmit
- *
- * If the timer was already running, we just wait for that one to occur.
- * */
+ /** if we have something waiting to send, start a short (random) timer so we can come check for collision before actually doing
+ * the transmit */
+ void setTransmitDelay();
+
+ /** random timer with certain min. and max. settings */
void startTransmitTimer(bool withDelay = true);
- /** if we have something waiting to send, start a short scaled timer based on SNR so we can come check for collision before actually doing
- * the transmit
- *
- * If the timer was already running, we just wait for that one to occur.
- * */
+ /** timer scaled to SNR of to be flooded packet */
void startTransmitTimerSNR(float snr);
void handleTransmitInterrupt();
diff --git a/src/mesh/SX126xInterface.cpp b/src/mesh/SX126xInterface.cpp
index b0c48d55a..ac96aa70b 100644
--- a/src/mesh/SX126xInterface.cpp
+++ b/src/mesh/SX126xInterface.cpp
@@ -226,6 +226,23 @@ void SX126xInterface::startReceive()
#endif
}
+/** Could we send right now (i.e. either not actively receving or transmitting)? */
+template
+bool SX126xInterface::isChannelActive()
+{
+ // check if we can detect a LoRa preamble on the current channel
+ int16_t result;
+
+ setStandby();
+ result = lora.scanChannel();
+ if (result == PREAMBLE_DETECTED)
+ return true;
+
+ assert(result != ERR_WRONG_MODEM);
+
+ return false;
+}
+
/** Could we send right now (i.e. either not actively receving or transmitting)? */
template
bool SX126xInterface::isActivelyReceiving()
diff --git a/src/mesh/SX126xInterface.h b/src/mesh/SX126xInterface.h
index 5168313e2..b0e5d9a32 100644
--- a/src/mesh/SX126xInterface.h
+++ b/src/mesh/SX126xInterface.h
@@ -46,6 +46,9 @@ class SX126xInterface : public RadioLibInterface
*/
virtual void enableInterrupt(void (*callback)()) { lora.setDio1Action(callback); }
+ /** can we detect a LoRa preamble on the current channel? */
+ virtual bool isChannelActive() override;
+
/** are we actively receiving a packet (only called during receiving state) */
virtual bool isActivelyReceiving() override;
diff --git a/src/modules/Telemetry/DeviceTelemetry.cpp b/src/modules/Telemetry/DeviceTelemetry.cpp
index 23c8a42a9..4568521c3 100644
--- a/src/modules/Telemetry/DeviceTelemetry.cpp
+++ b/src/modules/Telemetry/DeviceTelemetry.cpp
@@ -27,7 +27,7 @@ int32_t DeviceTelemetryModule::runOnce()
bool DeviceTelemetryModule::handleReceivedProtobuf(const MeshPacket &mp, Telemetry *t)
{
if (t->which_variant == Telemetry_device_metrics_tag) {
- String sender = getSenderName(mp);
+ const char *sender = getSenderShortName(mp);
DEBUG_MSG("-----------------------------------------\n");
DEBUG_MSG("Device Telemetry: Received data from %s\n", sender);
@@ -44,19 +44,6 @@ bool DeviceTelemetryModule::handleReceivedProtobuf(const MeshPacket &mp, Telemet
return false; // Let others look at this message also if they want
}
-String DeviceTelemetryModule::getSenderName(const MeshPacket &mp)
-{
- String sender;
-
- auto node = nodeDB.getNode(getFrom(&mp));
- if (node) {
- sender = node->user.short_name;
- } else {
- sender = "UNK";
- }
- return sender;
-}
-
bool DeviceTelemetryModule::sendOurTelemetry(NodeNum dest, bool wantReplies)
{
Telemetry t;
diff --git a/src/modules/Telemetry/DeviceTelemetry.h b/src/modules/Telemetry/DeviceTelemetry.h
index 67c7ac305..c224a2c1d 100644
--- a/src/modules/Telemetry/DeviceTelemetry.h
+++ b/src/modules/Telemetry/DeviceTelemetry.h
@@ -27,7 +27,6 @@ class DeviceTelemetryModule : private concurrency::OSThread, public ProtobufModu
bool sendOurTelemetry(NodeNum dest = NODENUM_BROADCAST, bool wantReplies = false);
private:
- String getSenderName(const MeshPacket &mp);
bool firstTime = 1;
const MeshPacket *lastMeasurementPacket;
};
diff --git a/src/modules/Telemetry/EnvironmentTelemetry.cpp b/src/modules/Telemetry/EnvironmentTelemetry.cpp
index 675969fd7..0257fe311 100644
--- a/src/modules/Telemetry/EnvironmentTelemetry.cpp
+++ b/src/modules/Telemetry/EnvironmentTelemetry.cpp
@@ -149,19 +149,6 @@ int32_t EnvironmentTelemetryModule::runOnce()
#endif
}
-String GetSenderName(const MeshPacket &mp)
-{
- String sender;
-
- auto node = nodeDB.getNode(getFrom(&mp));
- if (node) {
- sender = node->user.short_name;
- } else {
- sender = "UNK";
- }
- return sender;
-}
-
uint32_t GetTimeSinceMeshPacket(const MeshPacket *mp)
{
uint32_t now = getTime();
@@ -198,7 +185,7 @@ void EnvironmentTelemetryModule::drawFrame(OLEDDisplay *display, OLEDDisplayUiSt
Telemetry lastMeasurement;
uint32_t agoSecs = GetTimeSinceMeshPacket(lastMeasurementPacket);
- String lastSender = GetSenderName(*lastMeasurementPacket);
+ const char *lastSender = getSenderShortName(*lastMeasurementPacket);
auto &p = lastMeasurementPacket->decoded;
if (!pb_decode_from_bytes(p.payload.bytes, p.payload.size, Telemetry_fields, &lastMeasurement)) {
@@ -213,16 +200,16 @@ void EnvironmentTelemetryModule::drawFrame(OLEDDisplay *display, OLEDDisplayUiSt
if (radioConfig.preferences.telemetry_module_environment_display_fahrenheit) {
last_temp = String(CelsiusToFahrenheit(lastMeasurement.variant.environment_metrics.temperature), 0) + "°F";
}
- display->drawString(x, y += fontHeight(FONT_MEDIUM) - 2, "From: " + lastSender + "(" + String(agoSecs) + "s)");
- display->drawString(x, y += fontHeight(FONT_SMALL) - 2,"Temp/Hum: " + last_temp + " / " + String(lastMeasurement.variant.environment_metrics.relative_humidity, 0) + "%");
+ display->drawString(x, y += fontHeight(FONT_MEDIUM) - 2, "From: " + String(lastSender) + "(" + String(agoSecs) + "s)");
+ display->drawString(x, y += fontHeight(FONT_SMALL) - 2, "Temp/Hum: " + last_temp + " / " + String(lastMeasurement.variant.environment_metrics.relative_humidity, 0) + "%");
if (lastMeasurement.variant.environment_metrics.barometric_pressure != 0)
- display->drawString(x, y += fontHeight(FONT_SMALL),"Press: " + String(lastMeasurement.variant.environment_metrics.barometric_pressure, 0) + "hPA");
+ display->drawString(x, y += fontHeight(FONT_SMALL), "Press: " + String(lastMeasurement.variant.environment_metrics.barometric_pressure, 0) + "hPA");
}
bool EnvironmentTelemetryModule::handleReceivedProtobuf(const MeshPacket &mp, Telemetry *t)
{
if (t->which_variant == Telemetry_environment_metrics_tag) {
- String sender = GetSenderName(mp);
+ const char *sender = getSenderShortName(mp);
DEBUG_MSG("-----------------------------------------\n");
DEBUG_MSG("Environment Telemetry: Received data from %s\n", sender);
diff --git a/src/nrf52/NRF52CryptoEngine.cpp b/src/nrf52/NRF52CryptoEngine.cpp
index 1018b94fd..49f85a857 100644
--- a/src/nrf52/NRF52CryptoEngine.cpp
+++ b/src/nrf52/NRF52CryptoEngine.cpp
@@ -1,12 +1,9 @@
#include "configuration.h"
#include "CryptoEngine.h"
-#include "ocrypto_aes_ctr.h"
+#include
class NRF52CryptoEngine : public CryptoEngine
{
-
-
-
public:
NRF52CryptoEngine() {}
@@ -19,29 +16,37 @@ class NRF52CryptoEngine : public CryptoEngine
*/
virtual void encrypt(uint32_t fromNode, uint64_t packetId, size_t numBytes, uint8_t *bytes) override
{
- // DEBUG_MSG("NRF52 encrypt!\n");
+// DEBUG_MSG("NRF52 encrypt!\n");
if (key.length > 0) {
- ocrypto_aes_ctr_ctx ctx;
-
+ nRFCrypto.begin();
+ nRFCrypto_AES ctx;
+ uint8_t myLen = ctx.blockLen(numBytes);
+ char encBuf[myLen] = {0};
+ memcpy(encBuf, bytes, numBytes);
initNonce(fromNode, packetId);
- ocrypto_aes_ctr_init(&ctx, key.bytes, key.length, nonce);
-
- ocrypto_aes_ctr_encrypt(&ctx, bytes, bytes, numBytes);
+ ctx.begin();
+ ctx.Process(encBuf, numBytes, nonce, key.bytes, key.length, (char*)bytes, ctx.encryptFlag, ctx.ctrMode);
+ ctx.end();
+ nRFCrypto.end();
}
}
virtual void decrypt(uint32_t fromNode, uint64_t packetId, size_t numBytes, uint8_t *bytes) override
{
- // DEBUG_MSG("NRF52 decrypt!\n");
+// DEBUG_MSG("NRF52 decrypt!\n");
if (key.length > 0) {
- ocrypto_aes_ctr_ctx ctx;
-
+ nRFCrypto.begin();
+ nRFCrypto_AES ctx;
+ uint8_t myLen = ctx.blockLen(numBytes);
+ char decBuf[myLen] = {0};
+ memcpy(decBuf, bytes, numBytes);
initNonce(fromNode, packetId);
- ocrypto_aes_ctr_init(&ctx, key.bytes, key.length, nonce);
-
- ocrypto_aes_ctr_decrypt(&ctx, bytes, bytes, numBytes);
+ ctx.begin();
+ ctx.Process(decBuf, numBytes, nonce, key.bytes, key.length, (char*)bytes, ctx.decryptFlag, ctx.ctrMode);
+ ctx.end();
+ nRFCrypto.end();
}
}
diff --git a/src/nrf52/main-nrf52.cpp b/src/nrf52/main-nrf52.cpp
index bcf354024..655170c36 100644
--- a/src/nrf52/main-nrf52.cpp
+++ b/src/nrf52/main-nrf52.cpp
@@ -5,6 +5,7 @@
#include
#include
#include
+#include
// #include
#include "NRF52Bluetooth.h"
@@ -145,13 +146,15 @@ void nrf52Setup()
#endif
// Init random seed
- // FIXME - use this to get random numbers
- // #include "nrf_rng.h"
- // uint32_t r;
- // ble_controller_rand_vector_get_blocking(&r, sizeof(r));
- // randomSeed(r);
- DEBUG_MSG("FIXME, call randomSeed\n");
- // ::printf("TESTING PRINTF\n");
+ union seedParts {
+ uint32_t seed32;
+ uint8_t seed8[4];
+ } seed;
+ nRFCrypto.begin();
+ nRFCrypto.Random.generate(seed.seed8, sizeof(seed.seed8));
+ DEBUG_MSG("Setting random seed %u\n", seed.seed32);
+ randomSeed(seed.seed32);
+ nRFCrypto.end();
}
void cpuDeepSleep(uint64_t msecToWake)
diff --git a/variants/WisCore_RAK4631_Board/platformio.ini b/variants/WisCore_RAK4631_Board/platformio.ini
deleted file mode 100644
index cfd9297e0..000000000
--- a/variants/WisCore_RAK4631_Board/platformio.ini
+++ /dev/null
@@ -1,20 +0,0 @@
-; The very slick RAK wireless RAK 4631 / 4630 board
-[env:rak4631_5005]
-extends = nrf52840_base
-board = wiscore_rak4631
-# add our variants files to the include and src paths
-# define build flags for the TFT_eSPI library
-build_flags = ${nrf52840_base.build_flags} -Ivariants/WisCore_RAK4631_Board -D RAK_BASE_5005
-src_filter = ${nrf52_base.src_filter} +<../variants/WisCore_RAK4631_Board>
-debug_tool = jlink
-
-[env:rak4631_19003]
-extends = nrf52840_base
-board = wiscore_rak4631
-# add our variants files to the include and src paths
-# define build flags for the TFT_eSPI library
-build_flags = ${nrf52840_base.build_flags} -Ivariants/WisCore_RAK4631_Board -D RAK_BASE_19003
-src_filter = ${nrf52_base.src_filter} +<../variants/WisCore_RAK4631_Board>
-debug_tool = jlink
-; If not set we will default to uploading over serial (first it forces bootloader entry by talking 1200bps to cdcacm)
-;upload_protocol = jlink
\ No newline at end of file
diff --git a/variants/WisCore_RAK4631_E-Paper_Board/platformio.ini b/variants/WisCore_RAK4631_E-Paper_Board/platformio.ini
deleted file mode 100644
index 19855006b..000000000
--- a/variants/WisCore_RAK4631_E-Paper_Board/platformio.ini
+++ /dev/null
@@ -1,9 +0,0 @@
-[env:rak4631_5005_eink]
-extends = nrf52840_base
-board = wiscore_rak4631
-build_flags = ${nrf52840_base.build_flags} -Ivariants/WisCore_RAK4631_E-Paper_Board -D RAK_BASE_5005
-src_filter = ${nrf52_base.src_filter} +<../variants/WisCore_RAK4631_E-Paper_Board>
-lib_deps =
- ${nrf52840_base.lib_deps}
- https://github.com/ZinggJM/GxEPD2.git
-debug_tool = jlink
diff --git a/variants/rak4631/platformio.ini b/variants/rak4631/platformio.ini
new file mode 100644
index 000000000..6e0563598
--- /dev/null
+++ b/variants/rak4631/platformio.ini
@@ -0,0 +1,11 @@
+; The very slick RAK wireless RAK 4631 / 4630 board - Unified firmare for 5005/19003, with or without OLED RAK 1921
+[env:rak4631]
+extends = nrf52840_base
+board = wiscore_rak4631
+build_flags = ${nrf52840_base.build_flags} -Ivariants/rak4631 -D RAK_4631
+src_filter = ${nrf52_base.src_filter} +<../variants/rak4631>
+lib_deps =
+ ${nrf52840_base.lib_deps}
+debug_tool = jlink
+; If not set we will default to uploading over serial (first it forces bootloader entry by talking 1200bps to cdcacm)
+;upload_protocol = jlink
\ No newline at end of file
diff --git a/variants/WisCore_RAK4631_Board/variant.cpp b/variants/rak4631/variant.cpp
similarity index 100%
rename from variants/WisCore_RAK4631_Board/variant.cpp
rename to variants/rak4631/variant.cpp
diff --git a/variants/WisCore_RAK4631_Board/variant.h b/variants/rak4631/variant.h
similarity index 89%
rename from variants/WisCore_RAK4631_Board/variant.h
rename to variants/rak4631/variant.h
index 3058068c8..c211ec4a1 100644
--- a/variants/WisCore_RAK4631_Board/variant.h
+++ b/variants/rak4631/variant.h
@@ -59,10 +59,8 @@ extern "C" {
* Buttons
*/
-#ifdef RAK_BASE_5005
#define PIN_BUTTON1 9 // Pin for button on E-ink button module or IO expansion
#define BUTTON_NEED_PULLUP
-#endif
#define PIN_BUTTON2 12
#define PIN_BUTTON3 24
#define PIN_BUTTON4 25
@@ -110,17 +108,39 @@ static const uint8_t AREF = PIN_AREF;
/*
* SPI Interfaces
*/
-#define SPI_INTERFACES_COUNT 1
+#define SPI_INTERFACES_COUNT 2
#define PIN_SPI_MISO (45)
#define PIN_SPI_MOSI (44)
#define PIN_SPI_SCK (43)
+#define PIN_SPI1_MISO (29) // (0 + 29)
+#define PIN_SPI1_MOSI (30) // (0 + 30)
+#define PIN_SPI1_SCK (3) // (0 + 3)
+
static const uint8_t SS = 42;
static const uint8_t MOSI = PIN_SPI_MOSI;
static const uint8_t MISO = PIN_SPI_MISO;
static const uint8_t SCK = PIN_SPI_SCK;
+ /*
+ * eink display pins
+ */
+
+#define PIN_EINK_EN (0 + 2) // (0 + 2) Note: this is really just backlight power
+#define PIN_EINK_CS (0 + 26)
+#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
+
+// Controls power for the eink display - Board power is enabled either by VBUS from USB or the CPU asserting PWR_ON
+// FIXME - I think this is actually just the board power enable - it enables power to the CPU also
+//#define PIN_EINK_PWR_ON (-1)
+
+// #define HAS_EINK
+
/*
* Wire Interfaces
*/
@@ -175,10 +195,8 @@ static const uint8_t SCK = PIN_SPI_SCK;
#define PIN_GPS_EN (34)
#define PIN_GPS_PPS (17) // Pulse per second input from the GPS
-#ifdef RAK_BASE_5005
#define GPS_RX_PIN PIN_SERIAL1_RX
#define GPS_TX_PIN PIN_SERIAL1_TX
-#endif
// Battery
// The battery sense is hooked to pin A0 (5)
diff --git a/variants/rak4631_epaper/platformio.ini b/variants/rak4631_epaper/platformio.ini
new file mode 100644
index 000000000..fc65ac2c8
--- /dev/null
+++ b/variants/rak4631_epaper/platformio.ini
@@ -0,0 +1,12 @@
+; The very slick RAK wireless RAK 4631 / 4630 board - Firmware for 5005 with the RAK 14000 ePaper
+[env:rak4631_eink]
+extends = nrf52840_base
+board = wiscore_rak4631
+build_flags = ${nrf52840_base.build_flags} -Ivariants/rak4631_epaper -D RAK_4631
+src_filter = ${nrf52_base.src_filter} +<../variants/rak4631_epaper>
+lib_deps =
+ ${nrf52840_base.lib_deps}
+ https://github.com/ZinggJM/GxEPD2.git
+debug_tool = jlink
+; If not set we will default to uploading over serial (first it forces bootloader entry by talking 1200bps to cdcacm)
+;upload_protocol = jlink
\ No newline at end of file
diff --git a/variants/WisCore_RAK4631_E-Paper_Board/variant.cpp b/variants/rak4631_epaper/variant.cpp
similarity index 99%
rename from variants/WisCore_RAK4631_E-Paper_Board/variant.cpp
rename to variants/rak4631_epaper/variant.cpp
index 5b9288319..b96f6f1cd 100644
--- a/variants/WisCore_RAK4631_E-Paper_Board/variant.cpp
+++ b/variants/rak4631_epaper/variant.cpp
@@ -2,14 +2,17 @@
Copyright (c) 2014-2015 Arduino LLC. All right reserved.
Copyright (c) 2016 Sandeep Mistry All right reserved.
Copyright (c) 2018, Adafruit Industries (adafruit.com)
+
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
+
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU Lesser General Public License for more details.
+
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
diff --git a/variants/WisCore_RAK4631_E-Paper_Board/variant.h b/variants/rak4631_epaper/variant.h
similarity index 99%
rename from variants/WisCore_RAK4631_E-Paper_Board/variant.h
rename to variants/rak4631_epaper/variant.h
index 4b5d21add..071c659e1 100644
--- a/variants/WisCore_RAK4631_E-Paper_Board/variant.h
+++ b/variants/rak4631_epaper/variant.h
@@ -2,6 +2,7 @@
Copyright (c) 2014-2015 Arduino LLC. All right reserved.
Copyright (c) 2016 Sandeep Mistry All right reserved.
Copyright (c) 2018, Adafruit Industries (adafruit.com)
+
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
@@ -58,10 +59,8 @@ extern "C" {
* Buttons
*/
-#ifdef RAK_BASE_5005
#define PIN_BUTTON1 9 // Pin for button on E-ink button module or IO expansion
#define BUTTON_NEED_PULLUP
-#endif
#define PIN_BUTTON2 12
#define PIN_BUTTON3 24
#define PIN_BUTTON4 25
@@ -196,10 +195,8 @@ static const uint8_t SCK = PIN_SPI_SCK;
#define PIN_GPS_EN (34)
#define PIN_GPS_PPS (17) // Pulse per second input from the GPS
-#ifdef RAK_BASE_5005
#define GPS_RX_PIN PIN_SERIAL1_RX
#define GPS_TX_PIN PIN_SERIAL1_TX
-#endif
// Battery
// The battery sense is hooked to pin A0 (5)