mirror of
https://github.com/mikecarper/MeshCore.git
synced 2026-09-16 07:42:37 +00:00
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:
@@ -8,11 +8,11 @@
|
||||
#define FIRMWARE_VER_CODE 13
|
||||
|
||||
#ifndef FIRMWARE_BUILD_DATE
|
||||
#define FIRMWARE_BUILD_DATE "9 Aug 2026"
|
||||
#define FIRMWARE_BUILD_DATE "14 Aug 2026"
|
||||
#endif
|
||||
|
||||
#ifndef FIRMWARE_VERSION
|
||||
#define FIRMWARE_VERSION "v1.17.0"
|
||||
#define FIRMWARE_VERSION "v1.17.1"
|
||||
#endif
|
||||
|
||||
#if defined(NRF52_PLATFORM) || defined(STM32_PLATFORM)
|
||||
|
||||
@@ -853,15 +853,23 @@ bool MyMesh::isLooped(const mesh::Packet* packet, const uint8_t max_counters[])
|
||||
}
|
||||
|
||||
void MyMesh::sendFloodReply(mesh::Packet* packet, unsigned long delay_millis, uint8_t path_hash_size) {
|
||||
if (recv_pkt_region && !recv_pkt_region->isWildcard()) { // if _request_ packet scope is known, send reply with same scope
|
||||
TransportKey scope;
|
||||
if (region_map.getTransportKeysFor(*recv_pkt_region, &scope, 1) > 0) {
|
||||
sendFloodScoped(scope, packet, delay_millis, path_hash_size);
|
||||
} else {
|
||||
TransportKey req_scope;
|
||||
bool is_wildcard = recv_pkt_region != NULL && recv_pkt_region->isWildcard();
|
||||
bool req_scope_known = recv_pkt_region != NULL && !is_wildcard
|
||||
&& region_map.getTransportKeysFor(*recv_pkt_region, &req_scope, 1) > 0;
|
||||
|
||||
switch (mesh::chooseReplyScope(req_scope_known, is_wildcard, !default_scope.isNull())) {
|
||||
case mesh::REPLY_SCOPE_REQUEST:
|
||||
sendFloodScoped(req_scope, packet, delay_millis, path_hash_size); // reply with same scope as request
|
||||
break;
|
||||
case mesh::REPLY_SCOPE_DEFAULT:
|
||||
// requester's scope is unknown: DIRECT request (no transport codes), or code matched no Region.
|
||||
// un-scoped would be dropped at hop 0 by repeaters running flood.max.unscoped=0
|
||||
sendFloodScoped(default_scope, packet, delay_millis, path_hash_size);
|
||||
break;
|
||||
case mesh::REPLY_SCOPE_NONE:
|
||||
sendFlood(packet, delay_millis, path_hash_size); // send un-scoped
|
||||
}
|
||||
} else {
|
||||
sendFlood(packet, delay_millis, path_hash_size); // send un-scoped
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -932,10 +940,11 @@ bool MyMesh::floodChannelDataHopApplies(const mesh::Packet* packet) const {
|
||||
bool MyMesh::allowPacketForward(const mesh::Packet *packet) {
|
||||
if (_prefs.disable_fwd) return false;
|
||||
if (packet->isRouteFlood()) {
|
||||
if (packet->getPathHashCount() >= _prefs.flood_max) return false;
|
||||
if (packet->getRouteType() == ROUTE_TYPE_FLOOD
|
||||
&& packet->getPathHashCount() >= _prefs.flood_max_unscoped) return false;
|
||||
if (packet->getPayloadType() == PAYLOAD_TYPE_ADVERT && packet->getPathHashCount() >= _prefs.flood_max_advert) return false;
|
||||
if (mesh::isFloodHopLimitExceeded(packet, _prefs.flood_max,
|
||||
_prefs.flood_max_unscoped,
|
||||
_prefs.flood_max_advert)) {
|
||||
return false;
|
||||
}
|
||||
#if !defined(PORTABLE_MQTT_OBSERVER) && !MESH_ENABLE_FLOOD_RULE_ENGINE
|
||||
if (!_prefs.flood_channel_data_enabled
|
||||
&& packet->getPayloadType() == PAYLOAD_TYPE_GRP_DATA
|
||||
@@ -2428,17 +2437,29 @@ void MyMesh::onAnonDataRecv(mesh::Packet *packet, const uint8_t *secret, const m
|
||||
|
||||
if (reply_len == 0) return; // invalid request
|
||||
|
||||
if (packet->isRouteFlood()) {
|
||||
// a DIRECT login can reply via the stored out_path, as onPeerDataRecv() does for REQ
|
||||
ClientInfo* client = acl.getClient(sender.pub_key, PUB_KEY_SIZE);
|
||||
bool have_out_path = client != NULL && client->out_path_len != OUT_PATH_UNKNOWN;
|
||||
|
||||
auto route = mesh::chooseReplyRoute(packet->isRouteFlood(), reply_path_len != 0xFF, have_out_path);
|
||||
|
||||
if (route == mesh::REPLY_ROUTE_PATH_RETURN) {
|
||||
// let this sender know path TO here, so they can use sendDirect(), and ALSO encode the response
|
||||
mesh::Packet* path = createPathReturn(sender, secret, packet->path, packet->path_len,
|
||||
PAYLOAD_TYPE_RESPONSE, reply_data, reply_len);
|
||||
if (path) sendFloodReply(path, SERVER_RESPONSE_DELAY, packet->getPathHashSize());
|
||||
} else if (reply_path_len == 0xFF) {
|
||||
mesh::Packet* reply = createDatagram(PAYLOAD_TYPE_RESPONSE, sender, secret, reply_data, reply_len);
|
||||
if (reply) sendFloodReply(reply, SERVER_RESPONSE_DELAY, packet->getPathHashSize());
|
||||
return;
|
||||
}
|
||||
|
||||
mesh::Packet* reply = createDatagram(PAYLOAD_TYPE_RESPONSE, sender, secret, reply_data, reply_len);
|
||||
if (reply == NULL) return;
|
||||
|
||||
if (route == mesh::REPLY_ROUTE_DIRECT_SUPPLIED) {
|
||||
sendDirect(reply, reply_path, reply_path_len, SERVER_RESPONSE_DELAY);
|
||||
} else if (route == mesh::REPLY_ROUTE_DIRECT_OUT_PATH) {
|
||||
sendDirect(reply, client->out_path, client->out_path_len, SERVER_RESPONSE_DELAY);
|
||||
} else {
|
||||
mesh::Packet* reply = createDatagram(PAYLOAD_TYPE_RESPONSE, sender, secret, reply_data, reply_len);
|
||||
if (reply) sendDirect(reply, reply_path, reply_path_len, SERVER_RESPONSE_DELAY);
|
||||
sendFloodReply(reply, SERVER_RESPONSE_DELAY, packet->getPathHashSize());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -97,6 +97,7 @@
|
||||
#endif
|
||||
#include <helpers/TxtDataHelpers.h>
|
||||
#include <helpers/RegionMap.h>
|
||||
#include <helpers/RoutingPolicy.h>
|
||||
#include "RateLimiter.h"
|
||||
|
||||
|
||||
@@ -130,14 +131,14 @@ struct NeighbourInfo {
|
||||
};
|
||||
|
||||
#ifndef FIRMWARE_BUILD_DATE
|
||||
#define FIRMWARE_BUILD_DATE "9 Aug 2026"
|
||||
#define FIRMWARE_BUILD_DATE "14 Aug 2026"
|
||||
#endif
|
||||
#ifndef FIRMWARE_BUILD_EPOCH
|
||||
#define FIRMWARE_BUILD_EPOCH 0UL
|
||||
#endif
|
||||
|
||||
#ifndef FIRMWARE_VERSION
|
||||
#define FIRMWARE_VERSION "v1.17.0"
|
||||
#define FIRMWARE_VERSION "v1.17.1"
|
||||
#endif
|
||||
|
||||
#define FIRMWARE_ROLE "repeater"
|
||||
|
||||
@@ -494,9 +494,11 @@ void MyMesh::onRetryConfigChanged() {
|
||||
bool MyMesh::allowPacketForward(const mesh::Packet *packet) {
|
||||
if (_prefs.disable_fwd) return false;
|
||||
if (packet->isRouteFlood()) {
|
||||
if (packet->getPathHashCount() >= _prefs.flood_max) return false;
|
||||
if (packet->getRouteType() == ROUTE_TYPE_FLOOD && packet->getPathHashCount() >= _prefs.flood_max_unscoped) return false;
|
||||
if (packet->getPayloadType() == PAYLOAD_TYPE_ADVERT && packet->getPathHashCount() >= _prefs.flood_max_advert) return false;
|
||||
if (mesh::isFloodHopLimitExceeded(packet, _prefs.flood_max,
|
||||
_prefs.flood_max_unscoped,
|
||||
_prefs.flood_max_advert)) {
|
||||
return false;
|
||||
}
|
||||
#if defined(MESHCORE_ESP32_FULL_PROFILE)
|
||||
if (flood_rules.shouldBlock(packet, recv_pkt_rule_match_mask,
|
||||
_ms->getMillis())) {
|
||||
@@ -1171,7 +1173,6 @@ MyMesh::MyMesh(mesh::MainBoard &board, mesh::Radio &radio, mesh::MillisecondCloc
|
||||
#endif
|
||||
_prefs.radio_fem_rxgain = 1;
|
||||
_prefs.radio_fem_txgain = 0;
|
||||
|
||||
// Observer defaults (alert.*, etc.) moved to applyMQTTDefaults() - they live
|
||||
// in /mqtt_prefs now, not NodePrefs.
|
||||
|
||||
@@ -1366,15 +1367,23 @@ bool MyMesh::resolveAlertScope(TransportKey& dest) {
|
||||
}
|
||||
|
||||
void MyMesh::sendFloodReply(mesh::Packet* packet, unsigned long delay_millis, uint8_t path_hash_size) {
|
||||
if (recv_pkt_region && !recv_pkt_region->isWildcard()) { // if _request_ packet scope is known, send reply with same scope
|
||||
TransportKey scope;
|
||||
if (region_map.getTransportKeysFor(*recv_pkt_region, &scope, 1) > 0) {
|
||||
sendFloodScoped(scope, packet, delay_millis, path_hash_size);
|
||||
} else {
|
||||
TransportKey req_scope;
|
||||
bool is_wildcard = recv_pkt_region != NULL && recv_pkt_region->isWildcard();
|
||||
bool req_scope_known = recv_pkt_region != NULL && !is_wildcard
|
||||
&& region_map.getTransportKeysFor(*recv_pkt_region, &req_scope, 1) > 0;
|
||||
|
||||
switch (mesh::chooseReplyScope(req_scope_known, is_wildcard, !default_scope.isNull())) {
|
||||
case mesh::REPLY_SCOPE_REQUEST:
|
||||
sendFloodScoped(req_scope, packet, delay_millis, path_hash_size); // reply with same scope as request
|
||||
break;
|
||||
case mesh::REPLY_SCOPE_DEFAULT:
|
||||
// requester's scope is unknown: DIRECT request (no transport codes), or code matched no Region.
|
||||
// un-scoped would be dropped at hop 0 by repeaters running flood.max.unscoped=0
|
||||
sendFloodScoped(default_scope, packet, delay_millis, path_hash_size);
|
||||
break;
|
||||
case mesh::REPLY_SCOPE_NONE:
|
||||
sendFlood(packet, delay_millis, path_hash_size); // send un-scoped
|
||||
}
|
||||
} else {
|
||||
sendFlood(packet, delay_millis, path_hash_size); // send un-scoped
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#include <helpers/RemoteCliRequest.h>
|
||||
#include <helpers/RegionMap.h>
|
||||
#include "FloodRuleEngine.h"
|
||||
#include <helpers/RoutingPolicy.h>
|
||||
#include <RTClib.h>
|
||||
#include <target.h>
|
||||
|
||||
@@ -51,11 +52,11 @@
|
||||
/* ------------------------------ Config -------------------------------- */
|
||||
|
||||
#ifndef FIRMWARE_BUILD_DATE
|
||||
#define FIRMWARE_BUILD_DATE "9 Aug 2026"
|
||||
#define FIRMWARE_BUILD_DATE "14 Aug 2026"
|
||||
#endif
|
||||
|
||||
#ifndef FIRMWARE_VERSION
|
||||
#define FIRMWARE_VERSION "v1.17.0"
|
||||
#define FIRMWARE_VERSION "v1.17.1"
|
||||
#endif
|
||||
|
||||
#ifndef LORA_FREQ
|
||||
|
||||
@@ -38,11 +38,11 @@
|
||||
#define PERM_RECV_ALERTS_HI (1 << 7) // high priority alerts
|
||||
|
||||
#ifndef FIRMWARE_BUILD_DATE
|
||||
#define FIRMWARE_BUILD_DATE "9 Aug 2026"
|
||||
#define FIRMWARE_BUILD_DATE "14 Aug 2026"
|
||||
#endif
|
||||
|
||||
#ifndef FIRMWARE_VERSION
|
||||
#define FIRMWARE_VERSION "v1.17.0"
|
||||
#define FIRMWARE_VERSION "v1.17.1"
|
||||
#endif
|
||||
|
||||
#define FIRMWARE_ROLE "sensor"
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
|
||||
#include "../../examples/companion_radio/NodePrefs.h"
|
||||
|
||||
class ReplayStream : public Stream {
|
||||
const char* _text;
|
||||
int _pos = 0;
|
||||
int _len;
|
||||
|
||||
public:
|
||||
explicit ReplayStream(const char* text) : _text(text), _len(strlen(text)) { }
|
||||
|
||||
int available() override { return _len - _pos; }
|
||||
int read() override { return _pos < _len ? _text[_pos++] : -1; }
|
||||
int peek() override { return _pos < _len ? _text[_pos] : -1; }
|
||||
};
|
||||
|
||||
class CaptureStream : public Stream {
|
||||
std::string _text;
|
||||
|
||||
size_t emit(long long value) {
|
||||
char text[24];
|
||||
int length = snprintf(text, sizeof(text), "%lld", value);
|
||||
return write(reinterpret_cast<const uint8_t*>(text), length);
|
||||
}
|
||||
|
||||
public:
|
||||
size_t write(uint8_t value) override {
|
||||
_text.push_back(static_cast<char>(value));
|
||||
return 1;
|
||||
}
|
||||
|
||||
size_t write(const uint8_t* buffer, size_t size) override {
|
||||
_text.append(reinterpret_cast<const char*>(buffer), size);
|
||||
return size;
|
||||
}
|
||||
|
||||
size_t print(unsigned char value, int = DEC) override { return emit(value); }
|
||||
size_t print(int value, int = DEC) override { return emit(value); }
|
||||
size_t print(unsigned int value, int = DEC) override { return emit(value); }
|
||||
size_t print(long value, int = DEC) override { return emit(value); }
|
||||
size_t print(unsigned long value, int = DEC) override { return emit(value); }
|
||||
size_t print(long long value, int = DEC) override { return emit(value); }
|
||||
size_t print(unsigned long long value, int = DEC) override { return emit(value); }
|
||||
|
||||
const std::string& text() const { return _text; }
|
||||
};
|
||||
|
||||
#if 0
|
||||
// Re-enable test once we can SET fem_ values in companion
|
||||
TEST(CompanionNodePrefs, RxGainSettingsRoundTripIndependently) {
|
||||
NodePrefs saved;
|
||||
saved.rx_boosted_gain = 0;
|
||||
saved.radio_fem_rxgain = 1;
|
||||
saved.radio_fem_txgain = 0;
|
||||
|
||||
CaptureStream output;
|
||||
ASSERT_TRUE(saved.saveSerial(output));
|
||||
EXPECT_NE(std::string::npos, output.text().find("rxgain:0"));
|
||||
EXPECT_NE(std::string::npos, output.text().find("fem_rxgain:1"));
|
||||
EXPECT_NE(std::string::npos, output.text().find("fem_txgain:0"));
|
||||
|
||||
ReplayStream input("{radio:{rxgain:1,fem_rxgain:0,fem_txgain:1}}");
|
||||
NodePrefs loaded;
|
||||
loaded.rx_boosted_gain = 0;
|
||||
loaded.radio_fem_rxgain = 1;
|
||||
loaded.radio_fem_txgain = 0;
|
||||
|
||||
ASSERT_TRUE(loaded.loadSerial(input));
|
||||
EXPECT_EQ(1, loaded.rx_boosted_gain);
|
||||
EXPECT_EQ(0, loaded.radio_fem_rxgain);
|
||||
EXPECT_EQ(1, loaded.radio_fem_txgain);
|
||||
}
|
||||
#endif
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
::testing::InitGoogleTest(&argc, argv);
|
||||
return RUN_ALL_TESTS();
|
||||
}
|
||||
@@ -1,6 +1,14 @@
|
||||
#include <gtest/gtest.h>
|
||||
#include "helpers/ConfigSerializer.h"
|
||||
|
||||
class NativeFileSystem {
|
||||
public:
|
||||
void mkdir(const char*) { }
|
||||
};
|
||||
#define FILESYSTEM NativeFileSystem
|
||||
#include "helpers/CommonCLI.h"
|
||||
#undef FILESYSTEM
|
||||
|
||||
#define TEST_INT_S "56"
|
||||
#define TEST_INT 56
|
||||
#define TEST_FLOAT_S "-6.123"
|
||||
@@ -21,6 +29,19 @@ public:
|
||||
class MockPrintStream : public Stream {
|
||||
int len = 0;
|
||||
uint8_t _buf[1024];
|
||||
|
||||
size_t printSigned(long long value) {
|
||||
char text[24];
|
||||
snprintf(text, sizeof(text), "%lld", value);
|
||||
return Print::print(text);
|
||||
}
|
||||
|
||||
size_t printUnsigned(unsigned long long value) {
|
||||
char text[24];
|
||||
snprintf(text, sizeof(text), "%llu", value);
|
||||
return Print::print(text);
|
||||
}
|
||||
|
||||
public:
|
||||
size_t write(uint8_t b) override {
|
||||
if (len < sizeof(_buf)) {
|
||||
@@ -30,17 +51,17 @@ public:
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t print(unsigned char b, int r) override { if (b == TEST_INT) return Print::print(TEST_INT_S); return 0; }
|
||||
size_t print(int v, int r) override { if (v == TEST_INT) return Print::print(TEST_INT_S); return 0; }
|
||||
size_t print(unsigned int v, int r) override { if (v == TEST_INT) return Print::print(TEST_INT_S); return 0; }
|
||||
size_t print(long v, int r) override { if (v == TEST_INT) return Print::print(TEST_INT_S); return 0; }
|
||||
size_t print(unsigned long v, int r) override { if (v == TEST_INT) return Print::print(TEST_INT_S); return 0; }
|
||||
size_t print(long long v, int r) override { if (v == TEST_INT) return Print::print(TEST_INT_S); return 0; }
|
||||
size_t print(unsigned long long v, int r) override { if (v == TEST_INT) return Print::print(TEST_INT_S); return 0; }
|
||||
size_t print(double v, int p = 2) override {
|
||||
if (p == 6) return Print::print(TEST_DOUBLE_S);
|
||||
if (p == 4) return Print::print(TEST_FLOAT_S);
|
||||
return 0;
|
||||
size_t print(unsigned char v, int r) override { return printUnsigned(v); }
|
||||
size_t print(int v, int r) override { return printSigned(v); }
|
||||
size_t print(unsigned int v, int r) override { return printUnsigned(v); }
|
||||
size_t print(long v, int r) override { return printSigned(v); }
|
||||
size_t print(unsigned long v, int r) override { return printUnsigned(v); }
|
||||
size_t print(long long v, int r) override { return printSigned(v); }
|
||||
size_t print(unsigned long long v, int r) override { return printUnsigned(v); }
|
||||
size_t print(double v, int p = 2) override {
|
||||
char text[32];
|
||||
snprintf(text, sizeof(text), "%.*f", p, v);
|
||||
return Print::print(text);
|
||||
}
|
||||
|
||||
int getLength() const { return len; }
|
||||
@@ -171,6 +192,28 @@ TEST(ConfigSerializer, LoadSerial_IgnoreUnknowns) {
|
||||
EXPECT_TRUE(match);
|
||||
}
|
||||
|
||||
TEST(NodePrefs, FemGainSettingsRoundTrip) {
|
||||
NodePrefs saved;
|
||||
saved.radio_fem_rxgain = 0;
|
||||
saved.radio_fem_txgain = 1;
|
||||
|
||||
MockPrintStream output;
|
||||
ASSERT_TRUE(saved.saveSerial(output));
|
||||
|
||||
std::string serialised(reinterpret_cast<const char*>(output.getBytes()), output.getLength());
|
||||
EXPECT_NE(std::string::npos, serialised.find("fem_rxgain:0"));
|
||||
EXPECT_NE(std::string::npos, serialised.find("fem_txgain:1"));
|
||||
|
||||
MockInputStream input(serialised.c_str());
|
||||
NodePrefs loaded;
|
||||
loaded.radio_fem_rxgain = 1;
|
||||
loaded.radio_fem_txgain = 0;
|
||||
|
||||
ASSERT_TRUE(loaded.loadSerial(input));
|
||||
EXPECT_EQ(0, loaded.radio_fem_rxgain);
|
||||
EXPECT_EQ(1, loaded.radio_fem_txgain);
|
||||
}
|
||||
|
||||
|
||||
// ── main ───────────────────────────────────────────────────────
|
||||
|
||||
|
||||
@@ -0,0 +1,110 @@
|
||||
#include <gtest/gtest.h>
|
||||
#include "helpers/RoutingPolicy.h"
|
||||
|
||||
using namespace mesh;
|
||||
|
||||
static Packet makeFlood(uint8_t route_type, uint8_t payload_type, uint8_t hops) {
|
||||
Packet p;
|
||||
p.header = route_type | (payload_type << PH_TYPE_SHIFT);
|
||||
p.setPathHashSizeAndCount(1, hops);
|
||||
p.payload_len = 1;
|
||||
return p;
|
||||
}
|
||||
|
||||
TEST(FloodHopLimit, UnscopedFloodIsDroppedAtFirstHopWhenMaxUnscopedIsZero) {
|
||||
auto pkt = makeFlood(ROUTE_TYPE_FLOOD, PAYLOAD_TYPE_RESPONSE, 0);
|
||||
EXPECT_TRUE(isFloodHopLimitExceeded(&pkt, 64, 0, 8));
|
||||
}
|
||||
|
||||
TEST(FloodHopLimit, ScopedFloodIsForwardedWhenMaxUnscopedIsZero) {
|
||||
for (uint8_t hops = 0; hops < 4; hops++) {
|
||||
auto pkt = makeFlood(ROUTE_TYPE_TRANSPORT_FLOOD, PAYLOAD_TYPE_RESPONSE, hops);
|
||||
EXPECT_FALSE(isFloodHopLimitExceeded(&pkt, 64, 0, 8)) << "hops=" << (int)hops;
|
||||
}
|
||||
}
|
||||
|
||||
TEST(FloodHopLimit, UnscopedFloodSurvivesUpToMaxUnscopedHops) {
|
||||
// matches the reported workaround: raising flood.max.unscoped to the expected hop count
|
||||
auto ok = makeFlood(ROUTE_TYPE_FLOOD, PAYLOAD_TYPE_RESPONSE, 2);
|
||||
EXPECT_FALSE(isFloodHopLimitExceeded(&ok, 64, 3, 8));
|
||||
|
||||
auto too_far = makeFlood(ROUTE_TYPE_FLOOD, PAYLOAD_TYPE_RESPONSE, 3);
|
||||
EXPECT_TRUE(isFloodHopLimitExceeded(&too_far, 64, 3, 8));
|
||||
}
|
||||
|
||||
TEST(FloodHopLimit, ScopedFloodStillHonoursFloodMaxAndAdvertMax) {
|
||||
auto beyond_max = makeFlood(ROUTE_TYPE_TRANSPORT_FLOOD, PAYLOAD_TYPE_RESPONSE, 5);
|
||||
EXPECT_TRUE(isFloodHopLimitExceeded(&beyond_max, 5, 64, 8));
|
||||
|
||||
auto advert = makeFlood(ROUTE_TYPE_TRANSPORT_FLOOD, PAYLOAD_TYPE_ADVERT, 8);
|
||||
EXPECT_TRUE(isFloodHopLimitExceeded(&advert, 64, 64, 8));
|
||||
}
|
||||
|
||||
// flood.max.unscoped=0 hits adverts too, well before flood_max_advert applies: a node
|
||||
// still advertising un-scoped is invisible past its immediate neighbours
|
||||
TEST(FloodHopLimit, UnscopedAdvertIsAlsoDroppedAtHopZero) {
|
||||
auto advert = makeFlood(ROUTE_TYPE_FLOOD, PAYLOAD_TYPE_ADVERT, 0);
|
||||
EXPECT_TRUE(isFloodHopLimitExceeded(&advert, 64, 0, 8));
|
||||
|
||||
auto scoped = makeFlood(ROUTE_TYPE_TRANSPORT_FLOOD, PAYLOAD_TYPE_ADVERT, 0);
|
||||
EXPECT_FALSE(isFloodHopLimitExceeded(&scoped, 64, 0, 8));
|
||||
}
|
||||
|
||||
TEST(ReplyRoute, FloodRequestGetsAPathReturn) {
|
||||
EXPECT_EQ(REPLY_ROUTE_PATH_RETURN,
|
||||
chooseReplyRoute(true, false, false));
|
||||
EXPECT_EQ(REPLY_ROUTE_PATH_RETURN,
|
||||
chooseReplyRoute(true, false, true));
|
||||
}
|
||||
|
||||
TEST(ReplyRoute, DirectRequestWithSuppliedPathRepliesDirect) {
|
||||
EXPECT_EQ(REPLY_ROUTE_DIRECT_SUPPLIED, chooseReplyRoute(false, true, false));
|
||||
}
|
||||
|
||||
// the reported bug: a DIRECT login (app already has a path) was answered by flooding, even
|
||||
// with an out_path stored. Under flood.max.unscoped=0 that reply never arrives.
|
||||
TEST(ReplyRoute, DirectRequestWithKnownOutPathRepliesDirect) {
|
||||
EXPECT_EQ(REPLY_ROUTE_DIRECT_OUT_PATH,
|
||||
chooseReplyRoute(false, false, true));
|
||||
}
|
||||
|
||||
TEST(ReplyRoute, SuppliedPathWinsOverStoredOutPath) {
|
||||
EXPECT_EQ(REPLY_ROUTE_DIRECT_SUPPLIED, chooseReplyRoute(false, true, true));
|
||||
}
|
||||
|
||||
TEST(ReplyRoute, DirectRequestWithNoReturnPathFallsBackToFlood) {
|
||||
EXPECT_EQ(REPLY_ROUTE_FLOOD, chooseReplyRoute(false, false, false));
|
||||
}
|
||||
|
||||
TEST(ReplyScope, MirrorsTheRequestScopeWhenKnown) {
|
||||
EXPECT_EQ(REPLY_SCOPE_REQUEST, chooseReplyScope(true,
|
||||
false,
|
||||
false));
|
||||
EXPECT_EQ(REPLY_SCOPE_REQUEST, chooseReplyScope(true, false, true));
|
||||
}
|
||||
|
||||
// un-scoped is itself a known scope, so mirror it. Replying scoped would change a path that
|
||||
// works today, and repeaters not holding our default Region would drop it anyway.
|
||||
TEST(ReplyScope, RepliesUnscopedToAnUnscopedFloodEvenWhenADefaultScopeExists) {
|
||||
EXPECT_EQ(REPLY_SCOPE_NONE, chooseReplyScope(false,
|
||||
true,
|
||||
true));
|
||||
}
|
||||
|
||||
// second half of the bug: a DIRECT request carries no transport codes, so recv_pkt_region is
|
||||
// always NULL. Un-scoped is dropped under flood.max.unscoped=0, and floods the mesh otherwise.
|
||||
TEST(ReplyScope, FallsBackToDefaultScopeWhenRequestScopeUnknown) {
|
||||
EXPECT_EQ(REPLY_SCOPE_DEFAULT, chooseReplyScope(false,
|
||||
false,
|
||||
true));
|
||||
}
|
||||
|
||||
TEST(ReplyScope, SendsUnscopedOnlyWhenNoScopeIsAvailableAtAll) {
|
||||
EXPECT_EQ(REPLY_SCOPE_NONE, chooseReplyScope(false, false, false));
|
||||
EXPECT_EQ(REPLY_SCOPE_NONE, chooseReplyScope(false, true, false));
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
::testing::InitGoogleTest(&argc, argv);
|
||||
return RUN_ALL_TESTS();
|
||||
}
|
||||
@@ -104,7 +104,7 @@
|
||||
#define PIN_SPI_SCK (32 + 8)
|
||||
#define PIN_SPI_NSS LORA_CS
|
||||
|
||||
#define PIN_SPI1_MISO (-1)
|
||||
#define PIN_SPI1_MISO (0)
|
||||
#define PIN_SPI1_MOSI (0+17)
|
||||
#define PIN_SPI1_SCK (0+20)
|
||||
|
||||
|
||||
@@ -25,8 +25,8 @@
|
||||
#define ST7735_SDA (0 + 24)
|
||||
#define ST7735_SCK (32 + 0)
|
||||
#define ST7735_RESET (0 + 20)
|
||||
#define ST7735_MISO (-1)
|
||||
#define ST7735_BUSY (-1)
|
||||
#define ST7735_MISO (0) // 0 maps to 0xff on this device which is NRFX_SPIM_PIN_NOT_USED
|
||||
#define ST7735_BUSY (0) // 0 maps to 0xff on this device which is NRFX_SPIM_PIN_NOT_USED
|
||||
#define ST7735_BL (0 + 15)
|
||||
#define VTFT_CTRL (0 + 13)
|
||||
|
||||
@@ -66,8 +66,7 @@
|
||||
// UART
|
||||
|
||||
// No longer populated on PCB.
|
||||
#define PIN_SERIAL2_RX (-1)
|
||||
#define PIN_SERIAL2_TX (-1)
|
||||
// Removed the pin definitions to avoid potential issues with Uart.
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// I2C
|
||||
|
||||
@@ -107,7 +107,7 @@
|
||||
#define P_LORA_NSS (11) // P0.11
|
||||
#define SX126X_RXEN (33) // P1.01
|
||||
#define SX126X_TXEN (27) // P0.27
|
||||
#define SX126X_DIO3_TCXO_VOLTAGE (1.8f)
|
||||
#define SX126X_DIO3_TCXO_VOLTAGE (3.0f)
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -58,7 +58,7 @@
|
||||
#define PIN_SPI_MISO _PINNUM(0, 17) // (MISO)
|
||||
#define PIN_SPI_MOSI _PINNUM(0, 15) // (MOSI)
|
||||
#define PIN_SPI_SCK _PINNUM(0, 13) // (SCK)
|
||||
#define PIN_SPI_NSS (-1)
|
||||
#define PIN_SPI_NSS (0)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// QSPI FLASH
|
||||
@@ -123,7 +123,7 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// SPI1
|
||||
|
||||
#define PIN_SPI1_MISO (-1) // Not used for Display
|
||||
#define PIN_SPI1_MISO (0) // Not used for Display, 0 maps to 0xff on this device which is NRFX_SPIM_PIN_NOT_USED
|
||||
#define PIN_SPI1_MOSI _PINNUM(0, 20)
|
||||
#define PIN_SPI1_SCK _PINNUM(0, 19)
|
||||
|
||||
@@ -135,7 +135,7 @@ extern const int SCK;
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Display
|
||||
|
||||
// #define DISP_MISO (-1) // Not used for Display
|
||||
// #define DISP_MISO (0) // Not used for Display, 0 maps to 0xff on this device which is NRFX_SPIM_PIN_NOT_USED
|
||||
#define DISP_MOSI _PINNUM(0, 20)
|
||||
#define DISP_SCLK _PINNUM(0, 19)
|
||||
#define DISP_CS _PINNUM(0, 22)
|
||||
@@ -143,7 +143,7 @@ extern const int SCK;
|
||||
#define DISP_RST _PINNUM(0, 28)
|
||||
#define DISP_BUSY _PINNUM(0, 3)
|
||||
#define DISP_POWER _PINNUM(1, 12)
|
||||
// #define DISP_BACKLIGHT (-1) // Display has no backlight
|
||||
// #define DISP_BACKLIGHT (0) // Display has no backlight, 0 maps to 0xff on this device which is NRFX_SPIM_PIN_NOT_USED
|
||||
|
||||
#define PIN_DISPLAY_CS DISP_CS
|
||||
#define PIN_DISPLAY_DC DISP_DC
|
||||
|
||||
@@ -108,7 +108,7 @@
|
||||
#define PIN_DISPLAY_DC (31)
|
||||
#define PIN_DISPLAY_RST (32 + 4)
|
||||
|
||||
#define PIN_SPI1_MISO (-1)
|
||||
#define PIN_SPI1_MISO (0) // 0 maps to 0xff on this device which is NRFX_SPIM_PIN_NOT_USED
|
||||
#define PIN_SPI1_MOSI (20)
|
||||
#define PIN_SPI1_SCK (22)
|
||||
|
||||
|
||||
@@ -1,163 +1,147 @@
|
||||
[me25ls01]
|
||||
extends = nrf52_base
|
||||
board = minewsemi_me25ls01
|
||||
board_build.ldscript = boards/nrf52840_s140_v7.ld
|
||||
build_flags = ${nrf52_base.build_flags}
|
||||
-I src/helpers/nrf52
|
||||
-I lib/nrf52/s140_nrf52_7.3.0_API/include
|
||||
-I lib/nrf52/s140_nrf52_7.3.0_API/include/nrf52
|
||||
-I variants/minewsemi_me25ls01
|
||||
-D me25ls01
|
||||
-D PIN_USER_BTN=27
|
||||
-D PIN_STATUS_LED=39
|
||||
-D P_LORA_TX_LED=22
|
||||
-D RADIO_CLASS=CustomLR1110
|
||||
[me25ls01]
|
||||
extends = nrf52_base
|
||||
board = minewsemi_me25ls01
|
||||
board_build.ldscript = boards/nrf52840_s140_v7.ld
|
||||
build_flags = ${nrf52_base.build_flags}
|
||||
-I src/helpers/nrf52
|
||||
-I lib/nrf52/s140_nrf52_7.3.0_API/include
|
||||
-I lib/nrf52/s140_nrf52_7.3.0_API/include/nrf52
|
||||
-I variants/minewsemi_me25ls01
|
||||
-D me25ls01
|
||||
-D PIN_USER_BTN=27
|
||||
-D PIN_STATUS_LED=39
|
||||
-D P_LORA_TX_LED=22
|
||||
-D RADIO_CLASS=CustomLR1110
|
||||
-D USE_LR1110
|
||||
-D WRAPPER_CLASS=CustomLR1110Wrapper
|
||||
-D LORA_TX_POWER=22
|
||||
-D ENV_INCLUDE_GPS=0
|
||||
-D ENV_INCLUDE_AHTX0=1
|
||||
-D ENV_INCLUDE_BME280=1
|
||||
-D ENV_INCLUDE_INA3221=1
|
||||
-D ENV_INCLUDE_INA219=1
|
||||
build_src_filter = ${nrf52_base.build_src_filter}
|
||||
+<helpers/*.cpp>
|
||||
+<../variants/minewsemi_me25ls01>
|
||||
+<helpers/sensors>
|
||||
debug_tool = jlink
|
||||
upload_protocol = nrfutil
|
||||
lib_deps = ${nrf52_base.lib_deps}
|
||||
adafruit/RTClib @ ^2.1.3
|
||||
densaugeo/base64 @ ~1.4.0
|
||||
stevemarple/MicroNMEA @ ^2.0.6
|
||||
end2endzone/NonBlockingRTTTL@^1.3.0
|
||||
adafruit/Adafruit SSD1306 @ ^2.5.13
|
||||
adafruit/Adafruit INA3221 Library @ ^1.0.1
|
||||
adafruit/Adafruit INA219 @ ^1.2.3
|
||||
adafruit/Adafruit AHTX0 @ ^2.0.5
|
||||
adafruit/Adafruit BME280 Library @ ^2.3.0
|
||||
|
||||
[env:Minewsemi_me25ls01_companion_radio_ble]
|
||||
extends = me25ls01
|
||||
board_build.ldscript = boards/nrf52840_s140_v7_extrafs.ld
|
||||
board_upload.maximum_size = 708608
|
||||
build_flags = ${me25ls01.build_flags}
|
||||
-I examples/companion_radio/ui-orig
|
||||
-D MAX_CONTACTS=350
|
||||
-D MAX_GROUP_CHANNELS=40
|
||||
-D BLE_PIN_CODE=123456
|
||||
; -D BLE_DEBUG_LOGGING=1
|
||||
; -D MESH_PACKET_LOGGING=1
|
||||
; -D MESH_DEBUG=1
|
||||
-D OFFLINE_QUEUE_SIZE=256
|
||||
-D RX_BOOSTED_GAIN=true
|
||||
-D RF_SWITCH_TABLE
|
||||
-D DISPLAY_CLASS=NullDisplayDriver
|
||||
;-D PIN_BUZZER=25
|
||||
;-D PIN_BUZZER_EN=37
|
||||
build_src_filter = ${me25ls01.build_src_filter}
|
||||
+<helpers/ui/NullDisplayDriver.cpp>
|
||||
+<helpers/nrf52/SerialBLEInterface.cpp>
|
||||
+<../examples/companion_radio/*.cpp>
|
||||
+<../examples/companion_radio/ui-orig/*.cpp>
|
||||
|
||||
[env:Minewsemi_me25ls01_repeater]
|
||||
extends = me25ls01
|
||||
extra_scripts = ${nrf52_lora_ota.extra_scripts}
|
||||
build_flags = ${me25ls01.build_flags}
|
||||
-D MAX_CONTACTS=100
|
||||
-D MAX_GROUP_CHANNELS=8
|
||||
-D BLE_PIN_CODE=123456
|
||||
; -D BLE_DEBUG_LOGGING=1
|
||||
; -D MESH_PACKET_LOGGING=1
|
||||
; -D MESH_DEBUG=1
|
||||
-D OFFLINE_QUEUE_SIZE=256
|
||||
-D RX_BOOSTED_GAIN=true
|
||||
-D RF_SWITCH_TABLE
|
||||
-D ADVERT_NAME='"ME25LS01 Repeater"'
|
||||
-D ADVERT_LAT=0.0
|
||||
-D ADVERT_LON=0.0
|
||||
-D ADMIN_PASSWORD='"password"'
|
||||
-D MAX_NEIGHBOURS=50
|
||||
-D DISPLAY_CLASS=NullDisplayDriver
|
||||
-D ENABLE_OTA=1
|
||||
-D OTA_FLASH_STORE=1
|
||||
-D OTA_FOLDER_SERIAL
|
||||
build_src_filter = ${me25ls01.build_src_filter}
|
||||
+<helpers/ota/*.cpp>
|
||||
+<../examples/simple_repeater>
|
||||
+<helpers/ui/NullDisplayDriver.cpp>
|
||||
|
||||
[env:Minewsemi_me25ls01_room_server]
|
||||
extends = me25ls01
|
||||
build_flags = ${me25ls01.build_flags}
|
||||
-D MAX_CONTACTS=100
|
||||
-D MAX_GROUP_CHANNELS=8
|
||||
; -D BLE_PIN_CODE=123456
|
||||
; -D BLE_DEBUG_LOGGING=1
|
||||
; -D MESH_PACKET_LOGGING=1
|
||||
; -D MESH_DEBUG=1
|
||||
-D OFFLINE_QUEUE_SIZE=256
|
||||
-D RX_BOOSTED_GAIN=true
|
||||
-D RF_SWITCH_TABLE
|
||||
-D ADVERT_NAME='"ME25LS01 Room"'
|
||||
-D ADVERT_LAT=0.0
|
||||
-D ADVERT_LON=0.0
|
||||
-D ADMIN_PASSWORD='"password"'
|
||||
-D ROOM_PASSWORD='"hello"'
|
||||
-D MAX_NEIGHBOURS=50
|
||||
-D DISPLAY_CLASS=NullDisplayDriver
|
||||
build_src_filter = ${me25ls01.build_src_filter}
|
||||
+<../examples/simple_room_server>
|
||||
+<helpers/ui/NullDisplayDriver.cpp>
|
||||
|
||||
[env:Minewsemi_me25ls01_terminal_chat]
|
||||
extends = me25ls01
|
||||
build_flags = ${me25ls01.build_flags}
|
||||
-D MAX_CONTACTS=100
|
||||
-D MAX_GROUP_CHANNELS=8
|
||||
-D BLE_PIN_CODE=123456
|
||||
; -D BLE_DEBUG_LOGGING=1
|
||||
; -D MESH_PACKET_LOGGING=1
|
||||
; -D MESH_DEBUG=1
|
||||
-D OFFLINE_QUEUE_SIZE=256
|
||||
-D RX_BOOSTED_GAIN=true
|
||||
-D RF_SWITCH_TABLE
|
||||
-D ADVERT_NAME='"ME25LS01 Chat"'
|
||||
-D ADVERT_LAT=0.0
|
||||
-D ADVERT_LON=0.0
|
||||
-D ADMIN_PASSWORD='"password"'
|
||||
-D ROOM_PASSWORD='"hello"'
|
||||
-D MAX_NEIGHBOURS=50
|
||||
-D DISPLAY_CLASS=NullDisplayDriver
|
||||
build_src_filter = ${me25ls01.build_src_filter}
|
||||
+<../examples/simple_secure_chat/main.cpp>
|
||||
+<helpers/ui/NullDisplayDriver.cpp>
|
||||
|
||||
[env:Minewsemi_me25ls01_companion_radio_usb]
|
||||
extends = me25ls01
|
||||
board_build.ldscript = boards/nrf52840_s140_v7_extrafs.ld
|
||||
board_upload.maximum_size = 708608
|
||||
build_flags = ${me25ls01.build_flags}
|
||||
-I examples/companion_radio/ui-orig
|
||||
-D MAX_CONTACTS=350
|
||||
-D MAX_GROUP_CHANNELS=40
|
||||
;-D BLE_PIN_CODE=123456
|
||||
; -D BLE_DEBUG_LOGGING=1
|
||||
; -D MESH_PACKET_LOGGING=1
|
||||
; -D MESH_DEBUG=1
|
||||
-D OFFLINE_QUEUE_SIZE=256
|
||||
-D RX_BOOSTED_GAIN=true
|
||||
-D RF_SWITCH_TABLE
|
||||
-D DISPLAY_CLASS=NullDisplayDriver
|
||||
-D ENABLE_USB_INTERFACE
|
||||
build_src_filter = ${me25ls01.build_src_filter}
|
||||
+<helpers/nrf52/*.cpp>
|
||||
+<helpers/ui/NullDisplayDriver.cpp>
|
||||
+<../examples/companion_radio/*.cpp>
|
||||
+<../examples/companion_radio/ui-orig/*.cpp>
|
||||
|
||||
[env:Minewsemi_me25ls01_kiss_modem]
|
||||
extends = me25ls01
|
||||
build_src_filter = ${me25ls01.build_src_filter}
|
||||
+<../examples/kiss_modem/>
|
||||
-D WRAPPER_CLASS=CustomLR1110Wrapper
|
||||
-D LORA_TX_POWER=22
|
||||
-D ENV_INCLUDE_GPS=0
|
||||
-D ENV_INCLUDE_AHTX0=1
|
||||
-D ENV_INCLUDE_BME280=1
|
||||
-D ENV_INCLUDE_INA3221=1
|
||||
-D ENV_INCLUDE_INA219=1
|
||||
build_src_filter = ${nrf52_base.build_src_filter}
|
||||
+<helpers/*.cpp>
|
||||
+<helpers/ui/NullDisplayDriver.cpp>
|
||||
+<../variants/minewsemi_me25ls01>
|
||||
+<helpers/sensors>
|
||||
debug_tool = jlink
|
||||
upload_protocol = nrfutil
|
||||
lib_deps = ${nrf52_base.lib_deps}
|
||||
adafruit/RTClib @ ^2.1.3
|
||||
densaugeo/base64 @ ~1.4.0
|
||||
stevemarple/MicroNMEA @ ^2.0.6
|
||||
end2endzone/NonBlockingRTTTL@^1.3.0
|
||||
adafruit/Adafruit SSD1306 @ ^2.5.13
|
||||
adafruit/Adafruit INA3221 Library @ ^1.0.1
|
||||
adafruit/Adafruit INA219 @ ^1.2.3
|
||||
adafruit/Adafruit AHTX0 @ ^2.0.5
|
||||
adafruit/Adafruit BME280 Library @ ^2.3.0
|
||||
|
||||
[env:Minewsemi_me25ls01_companion_radio_ble]
|
||||
extends = me25ls01
|
||||
board_build.ldscript = boards/nrf52840_s140_v7_extrafs.ld
|
||||
board_upload.maximum_size = 708608
|
||||
build_flags = ${me25ls01.build_flags}
|
||||
-I examples/companion_radio/ui-orig
|
||||
-D MAX_CONTACTS=350
|
||||
-D MAX_GROUP_CHANNELS=40
|
||||
-D BLE_PIN_CODE=123456
|
||||
; -D BLE_DEBUG_LOGGING=1
|
||||
; -D MESH_PACKET_LOGGING=1
|
||||
; -D MESH_DEBUG=1
|
||||
-D OFFLINE_QUEUE_SIZE=256
|
||||
-D RX_BOOSTED_GAIN=true
|
||||
-D RF_SWITCH_TABLE
|
||||
-D DISPLAY_CLASS=NullDisplayDriver
|
||||
;-D PIN_BUZZER=25
|
||||
;-D PIN_BUZZER_EN=37
|
||||
build_src_filter = ${me25ls01.build_src_filter}
|
||||
+<helpers/nrf52/SerialBLEInterface.cpp>
|
||||
+<../examples/companion_radio/*.cpp>
|
||||
+<../examples/companion_radio/ui-orig/*.cpp>
|
||||
|
||||
[env:Minewsemi_me25ls01_repeater]
|
||||
extends = me25ls01
|
||||
extra_scripts = ${nrf52_lora_ota.extra_scripts}
|
||||
build_flags = ${me25ls01.build_flags}
|
||||
; -D MESH_PACKET_LOGGING=1
|
||||
; -D MESH_DEBUG=1
|
||||
-D OFFLINE_QUEUE_SIZE=256
|
||||
-D RX_BOOSTED_GAIN=true
|
||||
-D RF_SWITCH_TABLE
|
||||
-D ADVERT_NAME='"ME25LS01 Repeater"'
|
||||
-D ADVERT_LAT=0.0
|
||||
-D ADVERT_LON=0.0
|
||||
-D ADMIN_PASSWORD='"password"'
|
||||
-D MAX_NEIGHBOURS=50
|
||||
-D DISPLAY_CLASS=NullDisplayDriver
|
||||
-D ENABLE_OTA=1
|
||||
-D OTA_FLASH_STORE=1
|
||||
-D OTA_FOLDER_SERIAL
|
||||
build_src_filter = ${me25ls01.build_src_filter}
|
||||
+<helpers/ota/*.cpp>
|
||||
+<../examples/simple_repeater>
|
||||
+<helpers/ui/NullDisplayDriver.cpp>
|
||||
|
||||
[env:Minewsemi_me25ls01_room_server]
|
||||
extends = me25ls01
|
||||
build_flags = ${me25ls01.build_flags}
|
||||
; -D MESH_PACKET_LOGGING=1
|
||||
; -D MESH_DEBUG=1
|
||||
-D OFFLINE_QUEUE_SIZE=256
|
||||
-D RX_BOOSTED_GAIN=true
|
||||
-D RF_SWITCH_TABLE
|
||||
-D ADVERT_NAME='"ME25LS01 Room"'
|
||||
-D ADVERT_LAT=0.0
|
||||
-D ADVERT_LON=0.0
|
||||
-D ADMIN_PASSWORD='"password"'
|
||||
-D ROOM_PASSWORD='"hello"'
|
||||
-D MAX_NEIGHBOURS=50
|
||||
-D DISPLAY_CLASS=NullDisplayDriver
|
||||
build_src_filter = ${me25ls01.build_src_filter}
|
||||
+<../examples/simple_room_server>
|
||||
|
||||
[env:Minewsemi_me25ls01_terminal_chat]
|
||||
extends = me25ls01
|
||||
build_flags = ${me25ls01.build_flags}
|
||||
; -D MESH_PACKET_LOGGING=1
|
||||
; -D MESH_DEBUG=1
|
||||
-D OFFLINE_QUEUE_SIZE=256
|
||||
-D RX_BOOSTED_GAIN=true
|
||||
-D RF_SWITCH_TABLE
|
||||
-D ADVERT_NAME='"ME25LS01 Chat"'
|
||||
-D ADVERT_LAT=0.0
|
||||
-D ADVERT_LON=0.0
|
||||
-D ADMIN_PASSWORD='"password"'
|
||||
-D ROOM_PASSWORD='"hello"'
|
||||
-D MAX_NEIGHBOURS=50
|
||||
-D DISPLAY_CLASS=NullDisplayDriver
|
||||
build_src_filter = ${me25ls01.build_src_filter}
|
||||
+<../examples/simple_secure_chat/main.cpp>
|
||||
|
||||
[env:Minewsemi_me25ls01_companion_radio_usb]
|
||||
extends = me25ls01
|
||||
board_build.ldscript = boards/nrf52840_s140_v7_extrafs.ld
|
||||
board_upload.maximum_size = 708608
|
||||
build_flags = ${me25ls01.build_flags}
|
||||
-I examples/companion_radio/ui-orig
|
||||
-D MAX_CONTACTS=350
|
||||
-D MAX_GROUP_CHANNELS=40
|
||||
;-D BLE_PIN_CODE=123456
|
||||
; -D MESH_PACKET_LOGGING=1
|
||||
; -D MESH_DEBUG=1
|
||||
-D OFFLINE_QUEUE_SIZE=256
|
||||
-D RX_BOOSTED_GAIN=true
|
||||
-D RF_SWITCH_TABLE
|
||||
-D DISPLAY_CLASS=NullDisplayDriver
|
||||
-D ENABLE_USB_INTERFACE
|
||||
build_src_filter = ${me25ls01.build_src_filter}
|
||||
+<helpers/nrf52/*.cpp>
|
||||
+<../examples/companion_radio/*.cpp>
|
||||
+<../examples/companion_radio/ui-orig/*.cpp>
|
||||
|
||||
[env:Minewsemi_me25ls01_kiss_modem]
|
||||
extends = me25ls01
|
||||
build_src_filter = ${me25ls01.build_src_filter}
|
||||
+<../examples/kiss_modem/>
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
MinewsemiME25LS01Board board;
|
||||
|
||||
RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY, SPI);
|
||||
|
||||
WRAPPER_CLASS radio_driver(radio, board);
|
||||
|
||||
VolatileRTCClock rtc_clock;
|
||||
@@ -18,7 +17,7 @@ extern EnvironmentSensorManager sensors;
|
||||
#endif
|
||||
|
||||
#ifdef DISPLAY_CLASS
|
||||
NullDisplayDriver display;
|
||||
DISPLAY_CLASS display;
|
||||
MomentaryButton user_btn(PIN_USER_BTN, 1000, true);
|
||||
#endif
|
||||
|
||||
|
||||
@@ -1,28 +1,27 @@
|
||||
#pragma once
|
||||
|
||||
#define RADIOLIB_STATIC_ONLY 1
|
||||
#include <RadioLib.h>
|
||||
#include <helpers/radiolib/RadioLibWrappers.h>
|
||||
#include <MinewsemiME25LS01Board.h>
|
||||
#include <helpers/radiolib/CustomLR1110Wrapper.h>
|
||||
#include <helpers/ArduinoHelpers.h>
|
||||
#include <helpers/SensorManager.h>
|
||||
#include <helpers/sensors/LocationProvider.h>
|
||||
#include <helpers/sensors/EnvironmentSensorManager.h>
|
||||
#pragma once
|
||||
|
||||
#define RADIOLIB_STATIC_ONLY 1
|
||||
#include <RadioLib.h>
|
||||
#include <helpers/radiolib/RadioLibWrappers.h>
|
||||
#include <MinewsemiME25LS01Board.h>
|
||||
#include <helpers/radiolib/CustomLR1110Wrapper.h>
|
||||
#include <helpers/ArduinoHelpers.h>
|
||||
#include <helpers/SensorManager.h>
|
||||
#include <helpers/sensors/LocationProvider.h>
|
||||
#include <helpers/sensors/EnvironmentSensorManager.h>
|
||||
#ifdef DISPLAY_CLASS
|
||||
#include <helpers/ui/NullDisplayDriver.h>
|
||||
#include <helpers/ui/MomentaryButton.h>
|
||||
#endif
|
||||
|
||||
extern MinewsemiME25LS01Board board;
|
||||
extern WRAPPER_CLASS radio_driver;
|
||||
extern VolatileRTCClock rtc_clock;
|
||||
extern EnvironmentSensorManager sensors;
|
||||
#ifdef DISPLAY_CLASS
|
||||
extern NullDisplayDriver display;
|
||||
extern DISPLAY_CLASS display;
|
||||
extern MomentaryButton user_btn;
|
||||
#endif
|
||||
|
||||
extern MinewsemiME25LS01Board board;
|
||||
extern WRAPPER_CLASS radio_driver;
|
||||
extern VolatileRTCClock rtc_clock;
|
||||
extern EnvironmentSensorManager sensors;
|
||||
|
||||
bool radio_init();
|
||||
mesh::LocalIdentity radio_new_identity();
|
||||
|
||||
bool radio_init();
|
||||
mesh::LocalIdentity radio_new_identity();
|
||||
|
||||
@@ -10,6 +10,7 @@ build_flags = ${rak4631_hw.build_flags}
|
||||
-D NRF52_POWER_MANAGEMENT
|
||||
-D RADIO_CLASS=CustomSX1262
|
||||
-D WRAPPER_CLASS=CustomSX1262Wrapper
|
||||
-D DISPLAY_CLASS=NullDisplayDriver
|
||||
-D LORA_TX_POWER=22
|
||||
-D SX126X_CURRENT_LIMIT=140
|
||||
-D SX126X_RX_BOOSTED_GAIN=1
|
||||
@@ -100,7 +101,6 @@ build_src_filter = ${R1Neo.build_src_filter}
|
||||
+<../examples/companion_radio/ui-orig/*.cpp>
|
||||
lib_deps =
|
||||
${R1Neo.lib_deps}
|
||||
${rak4631.lib_deps}
|
||||
densaugeo/base64 @ ~1.4.0
|
||||
end2endzone/NonBlockingRTTTL@^1.3.0
|
||||
|
||||
|
||||
@@ -4,13 +4,17 @@
|
||||
|
||||
R1NeoBoard board;
|
||||
|
||||
DISPLAY_CLASS display;
|
||||
MomentaryButton user_btn(PIN_USER_BTN, 1000);
|
||||
|
||||
RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY, SPI);
|
||||
|
||||
WRAPPER_CLASS radio_driver(radio, board);
|
||||
|
||||
#ifdef DISPLAY_CLASS
|
||||
NullDisplayDriver display;
|
||||
#endif
|
||||
|
||||
#ifdef PIN_USER_BTN
|
||||
MomentaryButton user_btn(PIN_USER_BTN, 1000, true);
|
||||
#endif
|
||||
|
||||
VolatileRTCClock fallback_clock;
|
||||
AutoDiscoverRTCClock rtc_clock(fallback_clock);
|
||||
|
||||
|
||||
@@ -4,19 +4,6 @@
|
||||
#include <Arduino.h>
|
||||
#include <helpers/NRF52Board.h>
|
||||
|
||||
#define P_LORA_NSS 13 //P1.13 45
|
||||
#define P_LORA_DIO_1 11 //P0.10 10
|
||||
#define P_LORA_RESET 10 //P0.09 9
|
||||
#define P_LORA_BUSY 16 //P0.29 29
|
||||
#define P_LORA_MISO 15 //P0.02 2
|
||||
#define P_LORA_SCLK 12 //P1.11 43
|
||||
#define P_LORA_MOSI 14 //P1.15 47
|
||||
#define SX126X_POWER_EN 21 //P0.13 13
|
||||
#define SX126X_RXEN 2 //P0.17
|
||||
#define SX126X_TXEN RADIOLIB_NC
|
||||
#define SX126X_DIO2_AS_RF_SWITCH true
|
||||
#define SX126X_DIO3_TCXO_VOLTAGE (1.8f)
|
||||
|
||||
#define PIN_VBAT_READ 17
|
||||
#define ADC_MULTIPLIER (1.815f) // dependent on voltage divider resistors. TODO: more accurate battery tracking
|
||||
|
||||
|
||||
@@ -3,13 +3,29 @@
|
||||
#include "wiring_digital.h"
|
||||
|
||||
const uint32_t g_ADigitalPinMap[] = {
|
||||
8, 6, 17, 20, 22, 24, 32, 11, 36, 38,
|
||||
9, 10, 43, 45, 47, 2, 29, 31,
|
||||
33, 34, 37,
|
||||
13, 15
|
||||
8, // P0.08 = 0
|
||||
6, // P0.06 = 1
|
||||
17, // P0.17 = 2
|
||||
20, // P0.20 = 3
|
||||
22, // P0.22 = 4
|
||||
24, // P0.24 = 5
|
||||
32, // P1.00 = 6
|
||||
11, // P0.11 = 7
|
||||
36, // P1.04 = 8
|
||||
38, // P1.06 = 9
|
||||
9, // P0.09 = 10
|
||||
10, // P0.10 = 11
|
||||
43, // P1.11 = 12
|
||||
45, // P1.13 = 13
|
||||
47, // P1.15 = 14
|
||||
2, // P0.02 = 15
|
||||
29, // P0.29 = 16
|
||||
31, // P0.31 = 17
|
||||
33, // P1.01 = 18
|
||||
34, // P1.02 = 19
|
||||
37, // P1.05 = 20
|
||||
13, // P0.13 = 21
|
||||
15 // P0.15 = 22
|
||||
};
|
||||
|
||||
void initVariant()
|
||||
{
|
||||
}
|
||||
|
||||
void initVariant() {}
|
||||
|
||||
@@ -7,9 +7,9 @@
|
||||
#pragma once
|
||||
|
||||
#include "WVariant.h"
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Low frequency clock source
|
||||
// Low frequency clock source
|
||||
|
||||
#define VARIANT_MCK (64000000ul)
|
||||
|
||||
@@ -79,4 +79,18 @@
|
||||
#define PIN_BUTTON1 (6)
|
||||
#define BUTTON_PIN PIN_BUTTON1
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// LoRa
|
||||
|
||||
#define P_LORA_NSS (13)
|
||||
#define P_LORA_DIO_1 (11)
|
||||
#define P_LORA_RESET (10)
|
||||
#define P_LORA_BUSY (16)
|
||||
#define P_LORA_MISO (15)
|
||||
#define P_LORA_SCLK (12)
|
||||
#define P_LORA_MOSI (14)
|
||||
#define SX126X_POWER_EN (21)
|
||||
#define SX126X_RXEN (2)
|
||||
#define SX126X_TXEN (-1)
|
||||
#define SX126X_DIO2_AS_RF_SWITCH true
|
||||
#define SX126X_DIO3_TCXO_VOLTAGE (1.8f)
|
||||
|
||||
Reference in New Issue
Block a user