Merge remote-tracking branch 'upstream/dev' into keymindCascade
# Conflicts: # examples/companion_radio/MyMesh.cpp # examples/companion_radio/NodePrefs.h # examples/simple_repeater/MyMesh.cpp # examples/simple_room_server/MyMesh.cpp # examples/simple_room_server/MyMesh.h # examples/simple_sensor/SensorMesh.cpp # src/Identity.cpp # src/MeshCore.h # src/Utils.cpp # src/helpers/CommonCLI.cpp # src/helpers/CommonCLI.h # src/helpers/radiolib/CustomLR2021Wrapper.h # src/helpers/radiolib/CustomSX1262Wrapper.h # src/helpers/radiolib/CustomSX1268Wrapper.h # src/helpers/radiolib/RadioLibWrappers.cpp # src/helpers/radiolib/RadioLibWrappers.h # src/helpers/ui/SH1106Display.cpp # variants/minewsemi_me25ls01/target.cpp # variants/minewsemi_me25ls01/target.h # variants/muziworks_r1_neo/target.cpp
This commit is contained in:
commit
c2e64da695
28 files changed
+704
-286
No files matched your search
@@ -15,6 +15,10 @@
|
||||
#include <Adafruit_TinyUSB.h>
|
||||
#endif
|
||||
|
||||
#ifdef USE_CC310_HW_CRYPTO
|
||||
#include <Adafruit_nRFCrypto.h>
|
||||
#endif
|
||||
|
||||
static BLEDfu bledfu;
|
||||
static uint16_t ota_conn_handle = BLE_CONN_HANDLE_INVALID;
|
||||
static bool ota_active = false;
|
||||
@@ -108,6 +112,11 @@ static void disconnect_callback(uint16_t conn_handle, uint8_t reason) {
|
||||
|
||||
void NRF52Board::begin() {
|
||||
startup_reason = BD_STARTUP_NORMAL;
|
||||
|
||||
#ifdef USE_CC310_HW_CRYPTO
|
||||
// CC310 TRNG is higher quality and environment-independent vs radio RSSI noise.
|
||||
nRFCrypto.begin();
|
||||
#endif
|
||||
}
|
||||
|
||||
#if NRF52_WATCHDOG_TIMEOUT_SECONDS > 0
|
||||
@@ -541,6 +550,10 @@ void NRF52Board::shutdownPeripherals() {
|
||||
sensors.getLocationProvider()->stop();
|
||||
}
|
||||
|
||||
#ifdef USE_CC310_HW_CRYPTO
|
||||
nRFCrypto.end();
|
||||
#endif
|
||||
|
||||
// Flush serial buffers
|
||||
Serial.flush();
|
||||
delay(100);
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
#pragma once
|
||||
|
||||
#include <Packet.h>
|
||||
|
||||
namespace mesh {
|
||||
|
||||
/**
|
||||
* \brief Test a flood packet against the configured hop limits.
|
||||
* \param packet inbound flood packet (caller has already checked isRouteFlood())
|
||||
* \param flood_max max hops for any flood packet
|
||||
* \param flood_max_unscoped max hops for ROUTE_TYPE_FLOOD (ie. un-scoped) packets
|
||||
* \param flood_max_advert max hops for ADVERT packets
|
||||
* \returns true if the packet has exceeded a limit, and must not be forwarded
|
||||
*/
|
||||
inline bool isFloodHopLimitExceeded(const Packet* packet, uint8_t flood_max,
|
||||
uint8_t flood_max_unscoped, uint8_t flood_max_advert) {
|
||||
uint8_t hops = packet->getPathHashCount();
|
||||
if (hops >= flood_max) return true;
|
||||
if (packet->getRouteType() == ROUTE_TYPE_FLOOD && hops >= flood_max_unscoped) return true;
|
||||
if (packet->getPayloadType() == PAYLOAD_TYPE_ADVERT && hops >= flood_max_advert) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief How a server routes a reply back to the requesting client.
|
||||
*/
|
||||
enum ReplyRoute : uint8_t {
|
||||
REPLY_ROUTE_PATH_RETURN, // request arrived by flood: reply with a PATH return, flooded back
|
||||
REPLY_ROUTE_DIRECT_SUPPLIED, // reply DIRECT, along the return path supplied in the request
|
||||
REPLY_ROUTE_DIRECT_OUT_PATH, // reply DIRECT, along the out_path already stored for this client
|
||||
REPLY_ROUTE_FLOOD, // no return path known: flood the reply
|
||||
};
|
||||
|
||||
/**
|
||||
* \param inbound_is_flood the request arrived as a flood packet
|
||||
* \param have_supplied_path the request payload carried an explicit reply path
|
||||
* \param have_out_path this server already has a stored out_path for the client
|
||||
*/
|
||||
inline ReplyRoute chooseReplyRoute(bool inbound_is_flood, bool have_supplied_path, bool have_out_path) {
|
||||
if (inbound_is_flood) return REPLY_ROUTE_PATH_RETURN;
|
||||
if (have_supplied_path) return REPLY_ROUTE_DIRECT_SUPPLIED;
|
||||
if (have_out_path) return REPLY_ROUTE_DIRECT_OUT_PATH;
|
||||
return REPLY_ROUTE_FLOOD;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Which transport scope a flooded reply should be sent with.
|
||||
*/
|
||||
enum ReplyScope : uint8_t {
|
||||
REPLY_SCOPE_REQUEST, // re-use the scope the request arrived on
|
||||
REPLY_SCOPE_DEFAULT, // fall back to this node's default region scope
|
||||
REPLY_SCOPE_NONE, // send un-scoped (ROUTE_TYPE_FLOOD)
|
||||
};
|
||||
|
||||
/**
|
||||
* \param request_scope_known request arrived scoped, and we resolved its Region's key
|
||||
* \param request_was_unscoped_flood request arrived as an un-scoped flood
|
||||
* \param default_scope_known this node has a default Region with a usable transport key
|
||||
*/
|
||||
inline ReplyScope chooseReplyScope(bool request_scope_known, bool request_was_unscoped_flood,
|
||||
bool default_scope_known) {
|
||||
if (request_scope_known) return REPLY_SCOPE_REQUEST;
|
||||
if (request_was_unscoped_flood) return REPLY_SCOPE_NONE; // requester chose un-scoped, so mirror it
|
||||
if (default_scope_known) return REPLY_SCOPE_DEFAULT; // scope unknowable: DIRECT, or unresolved Region
|
||||
return REPLY_SCOPE_NONE;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -4,6 +4,10 @@
|
||||
#include "MeshCore.h"
|
||||
|
||||
class CustomLR2021 : public LR2021 {
|
||||
uint32_t _preambleMillis = 66;
|
||||
uint32_t _maxPayloadMillis = 3934;
|
||||
uint32_t _activityAt = 0;
|
||||
bool _headerSeen = false;
|
||||
bool _rx_boosted = false;
|
||||
uint32_t _rf_switch_pins[Module::RFSWITCH_MAX_PINS] = {};
|
||||
const Module::RfSwitchMode_t* _rf_switch_table = nullptr;
|
||||
@@ -109,12 +113,63 @@ class CustomLR2021 : public LR2021 {
|
||||
return busy != RADIOLIB_NC && this->mod->hal->digitalRead(busy);
|
||||
}
|
||||
|
||||
int16_t startReceive() override {
|
||||
// include the PREAMBLE_DETECTED irq bit in reported flags
|
||||
return LR2021::startReceive(RADIOLIB_LR2021_RX_TIMEOUT_INF, RADIOLIB_IRQ_RX_DEFAULT_FLAGS | (1UL << RADIOLIB_LR2021_IRQ_PREAMBLE_DETECTED), RADIOLIB_IRQ_RX_DEFAULT_MASK, 0);
|
||||
}
|
||||
|
||||
bool isReceiving() {
|
||||
if (isChipBusy()) return false;
|
||||
uint32_t irq = getIrqStatus();
|
||||
bool detected = ((irq & RADIOLIB_LR2021_IRQ_SYNCWORD_VALID) || (irq & RADIOLIB_LR2021_IRQ_PREAMBLE_DETECTED));
|
||||
return detected;
|
||||
bool preamble = irq & RADIOLIB_LR2021_IRQ_PREAMBLE_DETECTED; // bit 5
|
||||
bool header = irq & RADIOLIB_LR2021_IRQ_LORA_HEADER_VALID; // bit 6
|
||||
bool hdrErr = irq & RADIOLIB_LR2021_IRQ_LORA_HDR_CRC_ERROR; // bit 9
|
||||
uint32_t now = millis();
|
||||
if (hdrErr) {
|
||||
clearIrqFlags(RADIOLIB_LR2021_IRQ_PREAMBLE_DETECTED | RADIOLIB_LR2021_IRQ_LORA_HEADER_VALID | RADIOLIB_LR2021_IRQ_LORA_HDR_CRC_ERROR);
|
||||
_activityAt = 0;
|
||||
_headerSeen = false;
|
||||
return false;
|
||||
}
|
||||
if (!header && _headerSeen) {
|
||||
// something cleared the header flag, reset our state.
|
||||
_activityAt = 0; _headerSeen = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (header) {
|
||||
if (!_headerSeen) { _headerSeen = true; _activityAt = now; };
|
||||
if (now - _activityAt > _maxPayloadMillis) {
|
||||
MESH_DEBUG_PRINTLN("Clearing header IRQ after %ums", _maxPayloadMillis);
|
||||
clearIrqFlags(RADIOLIB_LR2021_IRQ_PREAMBLE_DETECTED | RADIOLIB_LR2021_IRQ_LORA_HEADER_VALID | RADIOLIB_LR2021_IRQ_LORA_HDR_CRC_ERROR);
|
||||
_activityAt = 0; _headerSeen = false;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (preamble) {
|
||||
if (_activityAt == 0) _activityAt = now;
|
||||
if (now - _activityAt > _preambleMillis) {
|
||||
clearIrqFlags(RADIOLIB_LR2021_IRQ_PREAMBLE_DETECTED);
|
||||
_activityAt = 0;
|
||||
MESH_DEBUG_PRINTLN("Clearing preamble IRQ after %ums", _preambleMillis);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
_activityAt = 0; _headerSeen = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
void setPreambleMillis(uint32_t preambleMillis) {
|
||||
_preambleMillis = preambleMillis;
|
||||
MESH_DEBUG_PRINTLN("Set _preambleMillis=%u", _preambleMillis);
|
||||
}
|
||||
void setMaxPayloadMillis(uint32_t payloadMillis) {
|
||||
_maxPayloadMillis = payloadMillis;
|
||||
MESH_DEBUG_PRINTLN("Set _maxPayloadMillis=%u", _maxPayloadMillis);
|
||||
}
|
||||
|
||||
|
||||
uint8_t getSpreadingFactor() const { return spreadingFactor; }
|
||||
};
|
||||
@@ -20,12 +20,18 @@ public:
|
||||
|
||||
protected:
|
||||
bool applyParams(float freq, float bw, uint8_t sf, uint8_t cr) override {
|
||||
return ((CustomLR2021 *)_radio)->setFrequency(freq) == RADIOLIB_ERR_NONE
|
||||
bool success = ((CustomLR2021 *)_radio)->setFrequency(freq) == RADIOLIB_ERR_NONE
|
||||
&& ((CustomLR2021 *)_radio)->setSpreadingFactor(sf) == RADIOLIB_ERR_NONE
|
||||
&& ((CustomLR2021 *)_radio)->setBandwidth(bw) == RADIOLIB_ERR_NONE
|
||||
&& ((CustomLR2021 *)_radio)->setCodingRate(cr) == RADIOLIB_ERR_NONE
|
||||
&& updatePreamble(sf)
|
||||
&& applySideDetectorConfig(sf, bw);
|
||||
if (!success) return false;
|
||||
|
||||
PacketMillis pm = calcMaxPacketMillis(sf, bw, cr, preambleLengthForSF(sf));
|
||||
((CustomLR2021 *)_radio)->setPreambleMillis(pm.preambleMillis);
|
||||
((CustomLR2021 *)_radio)->setMaxPayloadMillis(pm.payloadMillis);
|
||||
return true;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
@@ -22,7 +22,7 @@ static volatile uint8_t state = STATE_IDLE;
|
||||
|
||||
// this function is called when a complete packet
|
||||
// is transmitted by the module
|
||||
static
|
||||
static
|
||||
#if defined(ESP8266) || defined(ESP32)
|
||||
ICACHE_RAM_ATTR
|
||||
#endif
|
||||
|
||||
@@ -24,20 +24,26 @@ bool SH1106Display::begin()
|
||||
{
|
||||
// Wire must already be initialised by board.begin() before this is called.
|
||||
// Boards with non-standard SH1106 addresses should define DISPLAY_ADDRESS
|
||||
// in their variant/platformio configuration. Some board revisions may have
|
||||
// different solder-bridge address configurations, so variants can also
|
||||
// provide DISPLAY_ADDRESS_ALT as a fallback.
|
||||
if (i2c_probe(Wire, DISPLAY_ADDRESS) && display.begin(DISPLAY_ADDRESS, true)) {
|
||||
return true;
|
||||
// in their variant/platformio configuration. The SA0 strap selects 0x3C or
|
||||
// 0x3D and differs between revisions of the same board. Variants may name a
|
||||
// preferred alternate explicitly; otherwise try the other address in the
|
||||
// pair. Always run the Adafruit init so its buffer and device objects exist,
|
||||
// even when no panel answers the probe.
|
||||
uint8_t addr = 0;
|
||||
if (i2c_probe(Wire, DISPLAY_ADDRESS)) {
|
||||
addr = DISPLAY_ADDRESS;
|
||||
}
|
||||
#ifdef DISPLAY_ADDRESS_ALT
|
||||
if (DISPLAY_ADDRESS_ALT != DISPLAY_ADDRESS &&
|
||||
i2c_probe(Wire, DISPLAY_ADDRESS_ALT) &&
|
||||
display.begin(DISPLAY_ADDRESS_ALT, true)) {
|
||||
return true;
|
||||
if (addr == 0 && DISPLAY_ADDRESS_ALT != DISPLAY_ADDRESS &&
|
||||
i2c_probe(Wire, DISPLAY_ADDRESS_ALT)) {
|
||||
addr = DISPLAY_ADDRESS_ALT;
|
||||
}
|
||||
#endif
|
||||
return false;
|
||||
if (addr == 0 && i2c_probe(Wire, DISPLAY_ADDRESS ^ 1)) {
|
||||
addr = DISPLAY_ADDRESS ^ 1;
|
||||
}
|
||||
bool ok = display.begin(addr ? addr : DISPLAY_ADDRESS, true);
|
||||
return addr != 0 && ok;
|
||||
}
|
||||
|
||||
void SH1106Display::turnOn()
|
||||
|
||||
Reference in new issue
Block a user