Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions examples/simple_repeater/MyMesh.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include "MyMesh.h"
#include <algorithm>
#include <climits>

/* ------------------------------ Config -------------------------------- */

Expand Down Expand Up @@ -87,6 +88,42 @@ void MyMesh::putNeighbour(const mesh::Identity &id, uint32_t timestamp, float sn
#endif
}

int8_t MyMesh::findNeighbourSNR(const uint8_t* hash, uint8_t hash_size) {
#if MAX_NEIGHBOURS
for (int i = 0; i < MAX_NEIGHBOURS; i++) {
if (neighbours[i].heard_timestamp != 0 && neighbours[i].id.isHashMatch(hash, hash_size)) {
return neighbours[i].snr;
}
}
#endif
return INT8_MAX;
}

// Approximate SNR demod floor per SF (same as RadioLibWrappers.cpp)
static const float cr_snr_thresholds[] = {
-7.5f, // SF7
-10.0f, // SF8
-12.5f, // SF9
-15.0f, // SF10
-17.5f, // SF11
-20.0f // SF12
};

uint8_t MyMesh::selectCodingRateForPeer(const uint8_t* hash, uint8_t hash_size) {
int8_t snr4 = findNeighbourSNR(hash, hash_size);
if (snr4 == INT8_MAX) return 0; // unknown neighbor, use default

float snr = snr4 / 4.0f;
float threshold = (_prefs.sf >= 7 && _prefs.sf <= 12)
? cr_snr_thresholds[_prefs.sf - 7] : -15.0f;
float margin = snr - threshold;

if (margin < 3.0f) return 8;
if (margin < 6.0f) return 7;
if (margin < 10.0f) return 6;
return 5; // good margin, use lightest CR
}

uint8_t MyMesh::handleLoginReq(const mesh::Identity& sender, const uint8_t* secret, uint32_t sender_timestamp, const uint8_t* data, bool is_flood) {
ClientInfo* client = NULL;
if (data[0] == 0) { // blank password, just check if sender is in ACL
Expand Down Expand Up @@ -910,6 +947,7 @@ void MyMesh::begin(FILESYSTEM *fs) {

radio_set_params(_prefs.freq, _prefs.bw, _prefs.sf, _prefs.cr);
radio_set_tx_power(_prefs.tx_power_dbm);
setDefaultCR(_prefs.cr);

updateAdvertTimer();
updateFloodAdvertTimer();
Expand Down
2 changes: 2 additions & 0 deletions examples/simple_repeater/MyMesh.h
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ class MyMesh : public mesh::Mesh, public CommonCLICallbacks {
#endif

void putNeighbour(const mesh::Identity& id, uint32_t timestamp, float snr);
int8_t findNeighbourSNR(const uint8_t* hash, uint8_t hash_size);
void sendNodeDiscoverReq();
uint8_t handleLoginReq(const mesh::Identity& sender, const uint8_t* secret, uint32_t sender_timestamp, const uint8_t* data, bool is_flood);
uint8_t handleAnonRegionsReq(const mesh::Identity& sender, uint32_t sender_timestamp, const uint8_t* data);
Expand Down Expand Up @@ -156,6 +157,7 @@ class MyMesh : public mesh::Mesh, public CommonCLICallbacks {
uint8_t getExtraAckTransmitCount() const override {
return _prefs.multi_acks;
}
uint8_t selectCodingRateForPeer(const uint8_t* hash, uint8_t hash_size) override;

#if ENV_INCLUDE_GPS == 1
void applyGpsPrefs() {
Expand Down
16 changes: 15 additions & 1 deletion src/Dispatcher.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,9 @@ void Dispatcher::loop() {
}

_radio->onSendFinished();
if (outbound->_tx_cr != 0 && outbound->_tx_cr != _default_cr) {
_radio->setCodingRate(_default_cr);
}
logTx(outbound, 2 + outbound->getPathByteLen() + outbound->payload_len);
if (outbound->isRouteFlood()) {
n_sent_flood++;
Expand All @@ -117,6 +120,9 @@ void Dispatcher::loop() {
MESH_DEBUG_PRINTLN("%s Dispatcher::loop(): WARNING: outbound packed send timed out!", getLogDateTime());

_radio->onSendFinished();
if (outbound->_tx_cr != 0 && outbound->_tx_cr != _default_cr) {
_radio->setCodingRate(_default_cr);
}
logTxFail(outbound, 2 + outbound->getPathByteLen() + outbound->payload_len);

releasePacket(outbound); // return to pool
Expand Down Expand Up @@ -323,14 +329,21 @@ void Dispatcher::checkSend() {
} else {
memcpy(&raw[len], outbound->payload, outbound->payload_len); len += outbound->payload_len;

if (outbound->_tx_cr != 0 && outbound->_tx_cr != _default_cr) {
_radio->setCodingRate(outbound->_tx_cr);
}

uint32_t max_airtime = _radio->getEstAirtimeFor(len)*3/2;
outbound_start = _ms->getMillis();
bool success = _radio->startSendRaw(raw, len);
if (!success) {
MESH_DEBUG_PRINTLN("%s Dispatcher::loop(): ERROR: send start failed!", getLogDateTime());
if (outbound->_tx_cr != 0 && outbound->_tx_cr != _default_cr) {
_radio->setCodingRate(_default_cr);
}

logTxFail(outbound, outbound->getRawLength());

releasePacket(outbound); // return to pool
outbound = NULL;
return;
Expand Down Expand Up @@ -359,6 +372,7 @@ Packet* Dispatcher::obtainNewPacket() {
} else {
pkt->payload_len = pkt->path_len = 0;
pkt->_snr = 0;
pkt->_tx_cr = 0;
}
return pkt;
}
Expand Down
7 changes: 7 additions & 0 deletions src/Dispatcher.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,8 @@ class Radio {
*/
virtual bool isReceiving() { return false; }

virtual void setCodingRate(uint8_t cr) { }

virtual float getLastRSSI() const { return 0; }
virtual float getLastSNR() const { return 0; }
};
Expand Down Expand Up @@ -136,6 +138,8 @@ class Dispatcher {
MillisecondClock* _ms;
uint16_t _err_flags;

uint8_t _default_cr;

Dispatcher(Radio& radio, MillisecondClock& ms, PacketManager& mgr)
: _radio(&radio), _ms(&ms), _mgr(&mgr)
{
Expand All @@ -150,6 +154,7 @@ class Dispatcher {
tx_budget_ms = 0;
last_budget_update = 0;
duty_cycle_window_ms = 3600000;
_default_cr = 5;
}

virtual DispatcherAction onRecvPacket(Packet* pkt) = 0;
Expand Down Expand Up @@ -184,6 +189,8 @@ class Dispatcher {
uint32_t getNumSentDirect() const { return n_sent_direct; }
uint32_t getNumRecvFlood() const { return n_recv_flood; }
uint32_t getNumRecvDirect() const { return n_recv_direct; }
void setDefaultCR(uint8_t cr) { _default_cr = cr; }

void resetStats() {
n_sent_flood = n_sent_direct = n_recv_flood = n_recv_direct = 0;
_err_flags = 0;
Expand Down
3 changes: 2 additions & 1 deletion src/Mesh.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -96,9 +96,10 @@ DispatcherAction Mesh::onRecvPacket(Packet* pkt) {

if (!_tables->hasSeen(pkt)) {
removeSelfFromPath(pkt);
pkt->_tx_cr = selectCodingRateForPeer(pkt->path, pkt->getPathHashSize());

uint32_t d = getDirectRetransmitDelay(pkt);
return ACTION_RETRANSMIT_DELAYED(0, d); // Routed traffic is HIGHEST priority
return ACTION_RETRANSMIT_DELAYED(0, d); // Routed traffic is HIGHEST priority
}
}
return ACTION_RELEASE; // this node is NOT the next hop (OR this packet has already been forwarded), so discard.
Expand Down
8 changes: 8 additions & 0 deletions src/Mesh.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,14 @@ class Mesh : public Dispatcher {
*/
virtual uint8_t getExtraAckTransmitCount() const;

/**
* \brief Select a coding rate for the next-hop peer based on link quality.
* \param hash the hash of the next-hop peer (from path[0..hash_size-1])
* \param hash_size bytes per hash entry
* \returns 0 = use node default CR, 5-8 = override CR for this packet
*/
virtual uint8_t selectCodingRateForPeer(const uint8_t* hash, uint8_t hash_size) { return 0; }

/**
* \brief Perform search of local DB of peers/contacts.
* \returns Number of peers with matching hash
Expand Down
2 changes: 2 additions & 0 deletions src/Packet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ Packet::Packet() {
header = 0;
path_len = 0;
payload_len = 0;
_snr = 0;
_tx_cr = 0;
}

bool Packet::isValidPathLen(uint8_t path_len) {
Expand Down
1 change: 1 addition & 0 deletions src/Packet.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ class Packet {
uint8_t path[MAX_PATH_SIZE];
uint8_t payload[MAX_PACKET_PAYLOAD];
int8_t _snr;
uint8_t _tx_cr; // 0 = use node default, 5-8 = override CR for this TX (not serialized to wire)

/**
* \brief calculate the hash of payload + type
Expand Down
2 changes: 2 additions & 0 deletions src/helpers/radiolib/CustomLLCC68Wrapper.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ class CustomLLCC68Wrapper : public RadioLibWrapper {
float getLastRSSI() const override { return ((CustomLLCC68 *)_radio)->getRSSI(); }
float getLastSNR() const override { return ((CustomLLCC68 *)_radio)->getSNR(); }

void setCodingRate(uint8_t cr) override { ((CustomLLCC68 *)_radio)->setCodingRate(cr); }

float packetScore(float snr, int packet_len) override {
int sf = ((CustomLLCC68 *)_radio)->spreadingFactor;
return packetScoreInt(snr, sf, packet_len);
Expand Down
2 changes: 2 additions & 0 deletions src/helpers/radiolib/CustomLR1110Wrapper.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ class CustomLR1110Wrapper : public RadioLibWrapper {
_radio->setPreambleLength(16); // overcomes weird issues with small and big pkts
}

void setCodingRate(uint8_t cr) override { ((CustomLR1110 *)_radio)->setCodingRate(cr); }

float getLastRSSI() const override { return ((CustomLR1110 *)_radio)->getRSSI(); }
float getLastSNR() const override { return ((CustomLR1110 *)_radio)->getSNR(); }
int16_t setRxBoostedGainMode(bool en) { return ((CustomLR1110 *)_radio)->setRxBoostedGainMode(en); };
Expand Down
2 changes: 2 additions & 0 deletions src/helpers/radiolib/CustomSTM32WLxWrapper.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ class CustomSTM32WLxWrapper : public RadioLibWrapper {
float getLastRSSI() const override { return ((CustomSTM32WLx *)_radio)->getRSSI(); }
float getLastSNR() const override { return ((CustomSTM32WLx *)_radio)->getSNR(); }

void setCodingRate(uint8_t cr) override { ((CustomSTM32WLx *)_radio)->setCodingRate(cr); }

float packetScore(float snr, int packet_len) override {
int sf = ((CustomSTM32WLx *)_radio)->spreadingFactor;
return packetScoreInt(snr, sf, packet_len);
Expand Down
2 changes: 2 additions & 0 deletions src/helpers/radiolib/CustomSX1262Wrapper.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ class CustomSX1262Wrapper : public RadioLibWrapper {
float getLastRSSI() const override { return ((CustomSX1262 *)_radio)->getRSSI(); }
float getLastSNR() const override { return ((CustomSX1262 *)_radio)->getSNR(); }

void setCodingRate(uint8_t cr) override { ((CustomSX1262 *)_radio)->setCodingRate(cr); }

float packetScore(float snr, int packet_len) override {
int sf = ((CustomSX1262 *)_radio)->spreadingFactor;
return packetScoreInt(snr, sf, packet_len);
Expand Down
2 changes: 2 additions & 0 deletions src/helpers/radiolib/CustomSX1268Wrapper.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ class CustomSX1268Wrapper : public RadioLibWrapper {
float getLastRSSI() const override { return ((CustomSX1268 *)_radio)->getRSSI(); }
float getLastSNR() const override { return ((CustomSX1268 *)_radio)->getSNR(); }

void setCodingRate(uint8_t cr) override { ((CustomSX1268 *)_radio)->setCodingRate(cr); }

float packetScore(float snr, int packet_len) override {
int sf = ((CustomSX1268 *)_radio)->spreadingFactor;
return packetScoreInt(snr, sf, packet_len);
Expand Down
2 changes: 2 additions & 0 deletions src/helpers/radiolib/CustomSX1276Wrapper.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ class CustomSX1276Wrapper : public RadioLibWrapper {
float getLastRSSI() const override { return ((CustomSX1276 *)_radio)->getRSSI(); }
float getLastSNR() const override { return ((CustomSX1276 *)_radio)->getSNR(); }

void setCodingRate(uint8_t cr) override { ((CustomSX1276 *)_radio)->setCodingRate(cr); }

float packetScore(float snr, int packet_len) override {
int sf = ((CustomSX1276 *)_radio)->spreadingFactor;
return packetScoreInt(snr, sf, packet_len);
Expand Down