Better integration in meshtastic TX windows
Using SNR related calculation of TX wait time
This commit is contained in:
parent
895d385f21
commit
585ae45c86
287
src/main.cpp
287
src/main.cpp
|
@ -15,7 +15,7 @@ void setup() {
|
||||||
initRegion(); // create regions[] and load myRegion
|
initRegion(); // create regions[] and load myRegion
|
||||||
applyModemConfig(); // apply lora settings
|
applyModemConfig(); // apply lora settings
|
||||||
radio.setDio1Action(ISR_dio1Action);
|
radio.setDio1Action(ISR_dio1Action);
|
||||||
MSG("[INF][SX1262]Starting to listen ...\n");
|
MSG("[INF][SX1262]Starting to listen ...\n\r");
|
||||||
startReceive();
|
startReceive();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,93 +28,125 @@ void loop() {
|
||||||
PacketReceived = true;
|
PacketReceived = true;
|
||||||
}
|
}
|
||||||
if (irqStatus & RADIOLIB_SX126X_IRQ_TX_DONE) {
|
if (irqStatus & RADIOLIB_SX126X_IRQ_TX_DONE) {
|
||||||
PacketSent = true;
|
p = NULL;
|
||||||
|
PacketSent = false;
|
||||||
|
startReceive();
|
||||||
}
|
}
|
||||||
|
// other dio1 event
|
||||||
|
/*
|
||||||
|
if (!(p == NULL)) {
|
||||||
|
// drop packet, if we could not send it in 1 minute
|
||||||
|
if ( (p->packetTime + 60*1000) < millis() ) p = NULL;
|
||||||
|
MSG("[INF] TX aborted, could not send packet in 1 minute\n\r");
|
||||||
|
startReceive();
|
||||||
|
|
||||||
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
if (PacketReceived) {
|
if (PacketReceived) {
|
||||||
PacketReceived = false;
|
PacketReceived = false;
|
||||||
const size_t length = radio.getPacketLength();
|
Packet_t pck;
|
||||||
state = radio.readData(radiobuf, length);
|
pck.packetTime = millis();
|
||||||
PacketHeader* h = (PacketHeader *)radiobuf;
|
pck.size = radio.getPacketLength();
|
||||||
|
if (pck.size == 0) {
|
||||||
if (state == RADIOLIB_ERR_NONE) {
|
MSG("[ERR]Received packet length = 0!\n\r");
|
||||||
const int32_t payloadLen = length - sizeof(PacketHeader);
|
return; // we are still in receive mode
|
||||||
|
}
|
||||||
|
err = radio.readData(pck.buf, pck.size);
|
||||||
|
PacketHeader* h = (PacketHeader *)pck.buf;
|
||||||
|
snr = radio.getRSSI();
|
||||||
|
if (err == RADIOLIB_ERR_NONE) {
|
||||||
|
const int32_t payloadLen = pck.size - sizeof(PacketHeader);
|
||||||
if (payloadLen < 0) {
|
if (payloadLen < 0) {
|
||||||
MSG("[WARN]Not a Meshtastic packet, too short!\n");
|
MSG("[WARN]Not a Meshtastic packet, too short!\n\r");
|
||||||
return; // will not repeat
|
return; // will not repeat, continue receiving
|
||||||
}
|
}
|
||||||
const uint8_t hop_limit = h->flags & PACKET_FLAGS_HOP_MASK;
|
const uint8_t hop_limit = h->flags & PACKET_FLAGS_HOP_MASK;
|
||||||
// do not repeat if id is known or hop limit is zero
|
MSG("\n\r[NEW](id=0x%08X) (HopLim %d) ", h->id, hop_limit);
|
||||||
repeatPacket = msgID.add(h->id);
|
repeatPacket = msgID.add(h->id);
|
||||||
|
// print new packets only not repeated due to HopLim 0
|
||||||
|
if ((repeatPacket) && (hop_limit==0)) {
|
||||||
|
MSG("\n\r");
|
||||||
|
perhapsDecode(&pck);
|
||||||
|
}
|
||||||
if (hop_limit == 0) repeatPacket = false;
|
if (hop_limit == 0) repeatPacket = false;
|
||||||
MSG("\n[NEW](id=0x%08X) (HopLim %d) ", h->id, hop_limit);
|
// do not repeat if id is known or hop limit is zero
|
||||||
if ( !repeatPacket ){
|
if ( !repeatPacket ){
|
||||||
MSG("no repeat!\n");
|
MSG(" !!! no repeat !!!\n\r");
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
h->flags -= 1; // decrease hop limit by 1
|
h->flags -= 1; // decrease hop limit by 1
|
||||||
txQueue.add(radiobuf, length);
|
txQueue.add(&pck);
|
||||||
}
|
}
|
||||||
} else if (state == RADIOLIB_ERR_CRC_MISMATCH) {
|
} else if (err == RADIOLIB_ERR_CRC_MISMATCH) {
|
||||||
MSG(" [ERROR]CRC error!\n");
|
MSG(" [ERROR]CRC error!\n\r");
|
||||||
} else {
|
} else {
|
||||||
MSG(" [ERROR]Receive failed, code: %i!\n", state);
|
MSG(" [ERROR]Receive failed, code: %i!\n\r", err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
while (txQueue.hasPackets) {
|
if ( (txQueue.Count > 0) || !(p==NULL) ) {
|
||||||
p = txQueue.pop();
|
uint32_t now = millis();
|
||||||
// if we pop a Nullpointer (empty queue), hasPackets will be false now
|
if (p == NULL) {
|
||||||
if (txQueue.hasPackets) {
|
if ( txQueue.pop() ) {
|
||||||
TimerTime_t now = systime; //RtcGetTimerValue();
|
p = &PacketToSend;
|
||||||
//try to decode the packet and print it
|
}
|
||||||
uint32_t wait = maxPacketTimeMsec + abs( radio.getRSSI() * radio.getSNR() ) + random(0, 3*slotTimeMsec);
|
}
|
||||||
MSG("[INF]wait %i ms before TX\n", wait);
|
// resume recieving in case we popped an empty packet
|
||||||
while ( (now + wait) > systime ) {
|
if (p == NULL) {
|
||||||
|
PacketSent = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p->size > 0) {
|
||||||
|
uint32_t wait = getTxDelayMsecWeighted(snr);
|
||||||
|
|
||||||
|
MSG("[INF]wait %i ms before TX\n\r", wait);
|
||||||
|
activeReceiveStart = 0;
|
||||||
|
while ( ((now + wait) > millis() ) || ( isActivelyReceiving() ) ) {
|
||||||
// while waiting, we still are in receive mode
|
// while waiting, we still are in receive mode
|
||||||
if (dio1) {
|
if (dio1) {
|
||||||
MSG("[INF]New packet, no TX\n");
|
MSG("[INF]New packet, no TX\n\r");
|
||||||
return; // new packet arrived, return to handle it
|
return; // new packet arrived, return to handle it
|
||||||
}
|
}
|
||||||
delay(5);
|
delay(5);
|
||||||
}
|
}
|
||||||
// last check before actually sending the packet
|
// drop packet if we could not send it in 1 minute
|
||||||
radio.startChannelScan(); // RadioLib 6.5 overrides all user params
|
if ( (p->packetTime + 60*1000) < millis() ) {
|
||||||
// CAD will activate dio1 at activity or timeout
|
p = NULL;
|
||||||
MCU_deepsleep();
|
PacketSent = true;
|
||||||
if (radio.getChannelScanResult() == RADIOLIB_LORA_DETECTED) {
|
MSG("[INF] TX aborted, could not send packet in 1 minute\n\r");
|
||||||
dio1 = false;
|
|
||||||
startReceive();
|
|
||||||
MSG("[INF]Lora activity, no TX\n");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
dio1 = false;
|
if (perhapsSend(p) ) {
|
||||||
if (perhapsSend(&p->buf[0], p->size) ) {
|
// packet successfully sent
|
||||||
perhapsDecode(&p->buf[0], p->size);
|
// try to decode the packet and print it
|
||||||
|
perhapsDecode(p);
|
||||||
PacketSent = true;
|
PacketSent = true;
|
||||||
// mark packet as "deleted"
|
p = NULL;
|
||||||
p->size = 0;
|
|
||||||
} else {
|
} else {
|
||||||
// Could not send, resume receiving
|
// resume receiving if we could not send
|
||||||
PacketSent = true;
|
PacketSent = true;
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
|
MSG("[ERR]Tried to send empty package! TxQueue count=%i\n\r", txQueue.Count);
|
||||||
if (PacketSent) {
|
PacketSent = true;
|
||||||
PacketSent = false;
|
|
||||||
radio.finishTransmit();
|
|
||||||
dio1 = false;
|
|
||||||
startReceive();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef SILENT
|
if (PacketSent) {
|
||||||
// wait for serial output to conplete
|
PacketSent = false;
|
||||||
delay(10);
|
startReceive();
|
||||||
#endif
|
}
|
||||||
|
|
||||||
MCU_deepsleep();
|
if (txQueue.Count == 0) {
|
||||||
|
#ifndef SILENT
|
||||||
|
// wait for serial output to conplete
|
||||||
|
delay(10);
|
||||||
|
#endif
|
||||||
|
MCU_deepsleep(); // sleep until IRQ
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -135,38 +167,51 @@ void MCU_deepsleep(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void startReceive(){
|
void startReceive(){
|
||||||
MSG("[RX]Start receiving ...\n");
|
// clear irq status, standby()
|
||||||
while (RADIOLIB_ERR_NONE != radio.startReceive(RADIOLIB_SX126X_RX_TIMEOUT_INF, RADIOLIB_SX126X_IRQ_RX_DEFAULT , RADIOLIB_SX126X_IRQ_RX_DONE, 0) )
|
radio.finishTransmit();
|
||||||
{
|
dio1 = false;
|
||||||
MSG("\n[ERROR][SX1262] startReceive() failed, code: %i\n", state);
|
err = radio.startReceiveDutyCycleAuto(preambleLength, 8,
|
||||||
delay(1000);
|
RADIOLIB_SX126X_IRQ_RX_DEFAULT | RADIOLIB_SX126X_IRQ_PREAMBLE_DETECTED | RADIOLIB_SX126X_IRQ_HEADER_VALID);
|
||||||
}
|
if (err != RADIOLIB_ERR_NONE) MSG("[ERROR]Radiolib error %d when attempting SX126X startReceiveDutyCycleAuto!\n\r", err);
|
||||||
|
assert(err == RADIOLIB_ERR_NONE);
|
||||||
|
//radio.setDio1Action(ISR_dio1Action);
|
||||||
|
isReceiving = true;
|
||||||
|
MSG("[RX] ... \n\r");
|
||||||
}
|
}
|
||||||
|
|
||||||
bool perhapsSend(uint8_t* buf, size_t size) {
|
bool perhapsSend(Packet_t* p) {
|
||||||
PacketHeader* h = (PacketHeader *)buf;
|
if (p->size > RADIOLIB_SX126X_MAX_PACKET_LENGTH) {
|
||||||
MSG("\n[TX](id=0x%08X) HopLim=%i ", h->id, (h->flags & PACKET_FLAGS_HOP_MASK));
|
MSG("\n\r[INF]Packet size is %i! Reducing to %i. Sending ...", p->size, RADIOLIB_SX126X_MAX_PACKET_LENGTH);
|
||||||
state=radio.startTransmit(buf, size);
|
p->size = RADIOLIB_SX126X_MAX_PACKET_LENGTH;
|
||||||
if (state == RADIOLIB_ERR_NONE) {
|
|
||||||
MSG("starting ... ");
|
|
||||||
}
|
}
|
||||||
else {
|
// clear irq status, standby()
|
||||||
MSG("failed, ERR = %i - resume RX\n", state);
|
radio.finishTransmit();
|
||||||
|
dio1 = false;
|
||||||
|
PacketHeader* h = (PacketHeader *)p->buf;
|
||||||
|
MSG("\n\r[TX](id=0x%08X) HopLim=%i ", h->id, (h->flags & PACKET_FLAGS_HOP_MASK));
|
||||||
|
err=radio.startTransmit(p->buf, p->size);
|
||||||
|
isReceiving = false;
|
||||||
|
if (err == RADIOLIB_ERR_NONE) {
|
||||||
|
MSG("starting ... ");
|
||||||
|
} else {
|
||||||
|
MSG("failed, ERR = %i - resume RX\n\r", err);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
delay(10);
|
delay(10);
|
||||||
MCU_deepsleep(); // wait for TX to complete, will wake on any DIO1
|
MCU_deepsleep(); // wait for TX to complete, will wake on any DIO1
|
||||||
state = radio.getIrqStatus();
|
err = radio.getIrqStatus();
|
||||||
(state & RADIOLIB_SX126X_IRQ_TX_DONE) ? MSG("done!\n") : MSG("failed. Returned IRQ=%i\n", state);
|
(err & RADIOLIB_SX126X_IRQ_TX_DONE) ? MSG("done!\n\r") : MSG("failed. Returned IRQ=%i\n\r", err);
|
||||||
dio1 = false;
|
dio1 = false;
|
||||||
return ( state & RADIOLIB_SX126X_IRQ_TX_DONE );
|
radio.finishTransmit();
|
||||||
|
return ( err & RADIOLIB_SX126X_IRQ_TX_DONE );
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool perhapsDecode(uint8_t* buf, size_t size) {
|
bool perhapsDecode(Packet_t* p) {
|
||||||
// modified code, (c) Meshtastic https://github.com/meshtastic/firmware
|
// modified code, (c) Meshtastic https://github.com/meshtastic/firmware
|
||||||
PacketHeader* h = (PacketHeader *)buf;
|
PacketHeader* h = (PacketHeader *)p->buf;
|
||||||
const int32_t len = size - sizeof(PacketHeader);
|
const int32_t len = p->size - sizeof(PacketHeader);
|
||||||
const uint8_t *payload = radiobuf + sizeof(PacketHeader);
|
const uint8_t *payload = p->buf + sizeof(PacketHeader);
|
||||||
mp.from = h->from;
|
mp.from = h->from;
|
||||||
mp.to = h->to;
|
mp.to = h->to;
|
||||||
mp.id = h->id;
|
mp.id = h->id;
|
||||||
|
@ -176,19 +221,19 @@ bool perhapsDecode(uint8_t* buf, size_t size) {
|
||||||
mp.want_ack = h->flags & PACKET_FLAGS_WANT_ACK_MASK;
|
mp.want_ack = h->flags & PACKET_FLAGS_WANT_ACK_MASK;
|
||||||
mp.via_mqtt = h->flags & PACKET_FLAGS_VIA_MQTT_MASK;
|
mp.via_mqtt = h->flags & PACKET_FLAGS_VIA_MQTT_MASK;
|
||||||
mp.rx_snr = radio.getSNR();
|
mp.rx_snr = radio.getSNR();
|
||||||
mp.rx_rssi = lround(radio.getRSSI());
|
mp.rx_rssi = lround(snr);
|
||||||
mp.which_payload_variant = meshtastic_MeshPacket_encrypted_tag;
|
mp.which_payload_variant = meshtastic_MeshPacket_encrypted_tag;
|
||||||
mp.encrypted.size = 0;
|
mp.encrypted.size = 0;
|
||||||
static uint8_t scratchbuf[MAX_RHPACKETLEN];
|
static uint8_t scratchbuf[MAX_RHPACKETLEN];
|
||||||
assert(len <= sizeof(scratchbuf));
|
assert(len <= sizeof(scratchbuf));
|
||||||
// we have to copy into a scratch buffer, because mp.encrypted is a union with the decoded protobuf
|
// we have to copy into a scratch buffer, because mp.encrypted is a union with the decoded protobuf
|
||||||
memcpy(scratchbuf, buf + sizeof(PacketHeader), len);
|
memcpy(scratchbuf, p->buf + sizeof(PacketHeader), len);
|
||||||
crypto->decrypt(mp.from, mp.id, len, scratchbuf);
|
crypto->decrypt(mp.from, mp.id, len, scratchbuf);
|
||||||
memset(&mp.decoded, 0, sizeof(mp.decoded));
|
memset(&mp.decoded, 0, sizeof(mp.decoded));
|
||||||
if (!pb_decode_from_bytes((const uint8_t*)scratchbuf, len, &meshtastic_Data_msg, &mp.decoded)) {
|
if (!pb_decode_from_bytes((const uint8_t*)scratchbuf, len, &meshtastic_Data_msg, &mp.decoded)) {
|
||||||
MSG("[ERROR]Invalid protobufs in received mesh packet (bad psk?)!\n");
|
MSG("[ERROR]Invalid protobufs in received mesh packet (bad psk?)!\n\r");
|
||||||
} else if (mp.decoded.portnum == meshtastic_PortNum_UNKNOWN_APP) {
|
} else if (mp.decoded.portnum == meshtastic_PortNum_UNKNOWN_APP) {
|
||||||
MSG("[ERROR]Invalid portnum (bad psk?)!\n");
|
MSG("[ERROR]Invalid portnum (bad psk?)!\n\r");
|
||||||
} else {
|
} else {
|
||||||
mp.which_payload_variant = meshtastic_MeshPacket_decoded_tag;
|
mp.which_payload_variant = meshtastic_MeshPacket_decoded_tag;
|
||||||
mp.channel = generateHash(0);
|
mp.channel = generateHash(0);
|
||||||
|
@ -206,7 +251,7 @@ bool perhapsDecode(uint8_t* buf, size_t size) {
|
||||||
printPacket();
|
printPacket();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
MSG("[ERROR]No suitable channel found for decoding, hash was 0x%x!\n", mp.channel);
|
MSG("[ERROR]No suitable channel found for decoding, hash was 0x%x!\n\r", mp.channel);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -225,10 +270,10 @@ void printPacket(void) {
|
||||||
if (mp.rx_rssi != 0) MSG(" rxRSSI=%i", mp.rx_rssi);
|
if (mp.rx_rssi != 0) MSG(" rxRSSI=%i", mp.rx_rssi);
|
||||||
if (mp.via_mqtt != 0) MSG(" via MQTT");
|
if (mp.via_mqtt != 0) MSG(" via MQTT");
|
||||||
if (mp.priority != 0) MSG(" priority=%d", mp.priority);
|
if (mp.priority != 0) MSG(" priority=%d", mp.priority);
|
||||||
MSG("\nPayload: ");
|
MSG("\n\rPayload: ");
|
||||||
printVariants();
|
printVariants();
|
||||||
} else {
|
} else {
|
||||||
MSG(" encrypted!\n");
|
MSG(" encrypted!\n\r");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -242,7 +287,7 @@ void printVariants(void){
|
||||||
// /modules/TextMessageModule.cpp
|
// /modules/TextMessageModule.cpp
|
||||||
if (d.portnum == meshtastic_PortNum_TEXT_MESSAGE_APP){
|
if (d.portnum == meshtastic_PortNum_TEXT_MESSAGE_APP){
|
||||||
MSG("TEXT ");
|
MSG("TEXT ");
|
||||||
MSG("\"%.*s\"\n", d.payload.size, d.payload.bytes);
|
MSG("\"%.*s\"\n\r", d.payload.size, d.payload.bytes);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -252,7 +297,7 @@ void printVariants(void){
|
||||||
MSG("GPIO ");
|
MSG("GPIO ");
|
||||||
meshtastic_NodeRemoteHardwarePin pin;
|
meshtastic_NodeRemoteHardwarePin pin;
|
||||||
if (!pb_decode_from_bytes(d.payload.bytes, d.payload.size, &meshtastic_NodeRemoteHardwarePin_msg, &pin)) {
|
if (!pb_decode_from_bytes(d.payload.bytes, d.payload.size, &meshtastic_NodeRemoteHardwarePin_msg, &pin)) {
|
||||||
MSG("*** Error ***\n");
|
MSG("*** Error ***\n\r");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -265,12 +310,12 @@ void printVariants(void){
|
||||||
MSG("POSITION ");
|
MSG("POSITION ");
|
||||||
meshtastic_Position pos;
|
meshtastic_Position pos;
|
||||||
if (!pb_decode_from_bytes(d.payload.bytes, d.payload.size, &meshtastic_Position_msg, &pos)) {
|
if (!pb_decode_from_bytes(d.payload.bytes, d.payload.size, &meshtastic_Position_msg, &pos)) {
|
||||||
MSG("*** Error ***\n");
|
MSG("*** Error ***\n\r");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Log packet size and data fields
|
// Log packet size and data fields
|
||||||
MSG("Node=%08X l=%d latI=%d lonI=%d msl=%d hae=%d geo=%d pdop=%d hdop=%d vdop=%d siv=%d fxq=%d fxt=%d pts=%d "
|
MSG("Node=%08X l=%d latI=%d lonI=%d msl=%d hae=%d geo=%d pdop=%d hdop=%d vdop=%d siv=%d fxq=%d fxt=%d pts=%d "
|
||||||
"time=%d\n",
|
"time=%d\n\r",
|
||||||
mp.from, d.payload.size, pos.latitude_i, pos.longitude_i, pos.altitude, pos.altitude_hae,
|
mp.from, d.payload.size, pos.latitude_i, pos.longitude_i, pos.altitude, pos.altitude_hae,
|
||||||
pos.altitude_geoidal_separation, pos.PDOP, pos.HDOP, pos.VDOP, pos.sats_in_view, pos.fix_quality, pos.fix_type, pos.timestamp,
|
pos.altitude_geoidal_separation, pos.PDOP, pos.HDOP, pos.VDOP, pos.sats_in_view, pos.fix_quality, pos.fix_type, pos.timestamp,
|
||||||
pos.time);
|
pos.time);
|
||||||
|
@ -283,7 +328,7 @@ void printVariants(void){
|
||||||
MSG("NODE INFO ");
|
MSG("NODE INFO ");
|
||||||
meshtastic_User user;
|
meshtastic_User user;
|
||||||
if (!pb_decode_from_bytes(d.payload.bytes, d.payload.size, &meshtastic_User_msg, &user)) {
|
if (!pb_decode_from_bytes(d.payload.bytes, d.payload.size, &meshtastic_User_msg, &user)) {
|
||||||
MSG("*** Error ***\n");
|
MSG("*** Error ***\n\r");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
MSG("id:%s short: %s long: %s licensed: %s ",user.id, user.short_name, user.long_name, (user.is_licensed)?"YES":"NO");
|
MSG("id:%s short: %s long: %s licensed: %s ",user.id, user.short_name, user.long_name, (user.is_licensed)?"YES":"NO");
|
||||||
|
@ -291,29 +336,29 @@ void printVariants(void){
|
||||||
for (uint8_t i=0; i<sizeof(user.macaddr); i++) {
|
for (uint8_t i=0; i<sizeof(user.macaddr); i++) {
|
||||||
MSG("%0X",user.macaddr[i]);
|
MSG("%0X",user.macaddr[i]);
|
||||||
}
|
}
|
||||||
MSG(" HW model: %i role: %i\n", (uint8_t)user.hw_model, (uint8_t)user.role);
|
MSG(" HW model: %i role: %i\n\r", (uint8_t)user.hw_model, (uint8_t)user.role);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ROUTING MESSAGE
|
// ROUTING MESSAGE
|
||||||
// /modules/RoutingModule.cpp
|
// /modules/RoutingModule.cpp
|
||||||
if (d.portnum == meshtastic_PortNum_ROUTING_APP){
|
if (d.portnum == meshtastic_PortNum_ROUTING_APP){
|
||||||
MSG("ROUTING \n");
|
MSG("ROUTING \n\r");
|
||||||
/*
|
/*
|
||||||
meshtastic_Routing r;
|
meshtastic_Routing r;
|
||||||
if (!pb_decode_from_bytes(d.payload.bytes, d.payload.size, &meshtastic_Routing_msg, &r)) {
|
if (!pb_decode_from_bytes(d.payload.bytes, d.payload.size, &meshtastic_Routing_msg, &r)) {
|
||||||
MSG("*** Error ***\n");
|
MSG("*** Error ***\n\r");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (r.which_variant == sizeof(meshtastic_Routing_Error) ) {
|
if (r.which_variant == sizeof(meshtastic_Routing_Error) ) {
|
||||||
MSG("RoutingError=%i\n", r.error_reason);
|
MSG("RoutingError=%i\n\r", r.error_reason);
|
||||||
} else {
|
} else {
|
||||||
MSG("RouteRequest [");
|
MSG("RouteRequest [");
|
||||||
for (uint8_t i=0; i < r.route_request.route_count; i++) MSG("0x%X ", r.route_request.route[i]);
|
for (uint8_t i=0; i < r.route_request.route_count; i++) MSG("0x%X ", r.route_request.route[i]);
|
||||||
MSG("] ");
|
MSG("] ");
|
||||||
MSG("RouteReply [");
|
MSG("RouteReply [");
|
||||||
for (uint8_t i=0; i < r.route_reply.route_count; i++) MSG("0x%X ", r.route_reply.route[i]);
|
for (uint8_t i=0; i < r.route_reply.route_count; i++) MSG("0x%X ", r.route_reply.route[i]);
|
||||||
MSG("]\n");
|
MSG("]\n\r");
|
||||||
|
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
@ -326,7 +371,7 @@ void printVariants(void){
|
||||||
meshtastic_Telemetry telemetry;
|
meshtastic_Telemetry telemetry;
|
||||||
meshtastic_Telemetry *t = &telemetry;
|
meshtastic_Telemetry *t = &telemetry;
|
||||||
if (!pb_decode_from_bytes(d.payload.bytes, d.payload.size, &meshtastic_Telemetry_msg, &telemetry)) {
|
if (!pb_decode_from_bytes(d.payload.bytes, d.payload.size, &meshtastic_Telemetry_msg, &telemetry)) {
|
||||||
MSG("*** Error ***\n");
|
MSG("*** Error ***\n\r");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// /modules/Telemetry/PowerTelemetry.cpp
|
// /modules/Telemetry/PowerTelemetry.cpp
|
||||||
|
@ -338,7 +383,7 @@ void printVariants(void){
|
||||||
MSGFLOAT(", ch2_current=", t->variant.power_metrics.ch2_current);
|
MSGFLOAT(", ch2_current=", t->variant.power_metrics.ch2_current);
|
||||||
MSGFLOAT(", ch3_voltage=", t->variant.power_metrics.ch3_voltage);
|
MSGFLOAT(", ch3_voltage=", t->variant.power_metrics.ch3_voltage);
|
||||||
MSGFLOAT(", ch3_current=", t->variant.power_metrics.ch3_current);
|
MSGFLOAT(", ch3_current=", t->variant.power_metrics.ch3_current);
|
||||||
MSG("\n" );
|
MSG("\n\r" );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// /modules/Telemetry/DeviceTelemetry.cpp
|
// /modules/Telemetry/DeviceTelemetry.cpp
|
||||||
|
@ -348,7 +393,7 @@ void printVariants(void){
|
||||||
MSGFLOAT(", channel_utilization=", t->variant.device_metrics.channel_utilization);
|
MSGFLOAT(", channel_utilization=", t->variant.device_metrics.channel_utilization);
|
||||||
MSGFLOAT(", battery_level=", t->variant.device_metrics.battery_level);
|
MSGFLOAT(", battery_level=", t->variant.device_metrics.battery_level);
|
||||||
MSGFLOAT(", voltage=", t->variant.device_metrics.voltage);
|
MSGFLOAT(", voltage=", t->variant.device_metrics.voltage);
|
||||||
MSG("\n" );
|
MSG("\n\r" );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// /modules/Telemetry/EnvironmentTelemetry.cpp
|
// /modules/Telemetry/EnvironmentTelemetry.cpp
|
||||||
|
@ -360,16 +405,16 @@ void printVariants(void){
|
||||||
MSGFLOAT(", rel_humidity=",t->variant.environment_metrics.relative_humidity);
|
MSGFLOAT(", rel_humidity=",t->variant.environment_metrics.relative_humidity);
|
||||||
MSGFLOAT(", temp=", t->variant.environment_metrics.temperature);
|
MSGFLOAT(", temp=", t->variant.environment_metrics.temperature);
|
||||||
MSGFLOAT(", volt=", t->variant.environment_metrics.voltage);
|
MSGFLOAT(", volt=", t->variant.environment_metrics.voltage);
|
||||||
MSG("\n");
|
MSG("\n\r");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// /modules/Telemetry/AirQualityTelemetry.cpp
|
// /modules/Telemetry/AirQualityTelemetry.cpp
|
||||||
if (t->which_variant == meshtastic_Telemetry_air_quality_metrics_tag) {
|
if (t->which_variant == meshtastic_Telemetry_air_quality_metrics_tag) {
|
||||||
MSG("Air Quality Metrics:\n");
|
MSG("Air Quality Metrics:\n\r");
|
||||||
MSG( "pm10_standard=%i, pm25_standard=%i, pm100_standard=%i\n",
|
MSG( "pm10_standard=%i, pm25_standard=%i, pm100_standard=%i\n\r",
|
||||||
t->variant.air_quality_metrics.pm10_standard, t->variant.air_quality_metrics.pm25_standard,
|
t->variant.air_quality_metrics.pm10_standard, t->variant.air_quality_metrics.pm25_standard,
|
||||||
t->variant.air_quality_metrics.pm100_standard);
|
t->variant.air_quality_metrics.pm100_standard);
|
||||||
MSG("PM1.0(Environmental)=%i, PM2.5(Environmental)=%i, PM10.0(Environmental)=%i\n",
|
MSG("PM1.0(Environmental)=%i, PM2.5(Environmental)=%i, PM10.0(Environmental)=%i\n\r",
|
||||||
t->variant.air_quality_metrics.pm10_environmental, t->variant.air_quality_metrics.pm25_environmental,
|
t->variant.air_quality_metrics.pm10_environmental, t->variant.air_quality_metrics.pm25_environmental,
|
||||||
t->variant.air_quality_metrics.pm100_environmental);
|
t->variant.air_quality_metrics.pm100_environmental);
|
||||||
return;
|
return;
|
||||||
|
@ -382,7 +427,7 @@ void printVariants(void){
|
||||||
MSG("TRACEROUTE");
|
MSG("TRACEROUTE");
|
||||||
meshtastic_RouteDiscovery route;
|
meshtastic_RouteDiscovery route;
|
||||||
if (!pb_decode_from_bytes(d.payload.bytes, d.payload.size, &meshtastic_RouteDiscovery_msg, &route)) {
|
if (!pb_decode_from_bytes(d.payload.bytes, d.payload.size, &meshtastic_RouteDiscovery_msg, &route)) {
|
||||||
MSG("*** Error ***\n");
|
MSG("*** Error ***\n\r");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
MSG("(seen by %i Nodes", route.route_count);
|
MSG("(seen by %i Nodes", route.route_count);
|
||||||
|
@ -391,7 +436,7 @@ void printVariants(void){
|
||||||
MSG(" %08X", route.route[i]);
|
MSG(" %08X", route.route[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
MSG(")\n");
|
MSG(")\n\r");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -401,13 +446,13 @@ void printVariants(void){
|
||||||
MSG("NEIGHBORINFO ");
|
MSG("NEIGHBORINFO ");
|
||||||
meshtastic_NeighborInfo np;
|
meshtastic_NeighborInfo np;
|
||||||
if (!pb_decode_from_bytes(d.payload.bytes, d.payload.size, &meshtastic_NeighborInfo_msg, &np)) {
|
if (!pb_decode_from_bytes(d.payload.bytes, d.payload.size, &meshtastic_NeighborInfo_msg, &np)) {
|
||||||
MSG("*** Error ***\n");
|
MSG("*** Error ***\n\r");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
MSG("(last sent by 0x%x) Number of neighbors=%d\n", np.last_sent_by_id, np.neighbors_count);
|
MSG("(last sent by 0x%x) Number of neighbors=%d\n\r", np.last_sent_by_id, np.neighbors_count);
|
||||||
for (uint8_t i = 0; i < np.neighbors_count; i++) {
|
for (uint8_t i = 0; i < np.neighbors_count; i++) {
|
||||||
MSG("[0x%X, ", np.neighbors[i].node_id);
|
MSG("[0x%X, ", np.neighbors[i].node_id);
|
||||||
MSGFLOAT("snr=%.2f]\n", np.neighbors[i].snr);
|
MSGFLOAT("snr=%.2f]\n\r", np.neighbors[i].snr);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -415,22 +460,22 @@ void printVariants(void){
|
||||||
// ATAK PLUGIN MESSAGE
|
// ATAK PLUGIN MESSAGE
|
||||||
// /modules/AtakPluginModule.cpp
|
// /modules/AtakPluginModule.cpp
|
||||||
if (d.portnum == meshtastic_PortNum_ATAK_PLUGIN){
|
if (d.portnum == meshtastic_PortNum_ATAK_PLUGIN){
|
||||||
MSG("ATAK \n");
|
MSG("ATAK \n\r");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// No known PortNum:
|
// No known PortNum:
|
||||||
MSG("\"");
|
MSG("UNKNOWN #%i \"", d.portnum);
|
||||||
for (uint32_t i=0; i < d.payload.size; i++){
|
for (uint32_t i=0; i < d.payload.size; i++){
|
||||||
MSG("%X", d.payload.bytes[i]);
|
MSG("%X", d.payload.bytes[i]);
|
||||||
}
|
}
|
||||||
MSG("\"\n");
|
MSG("\"\n\r");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// PacketQueueClass Definitions
|
// PacketQueueClass Definitions
|
||||||
|
|
||||||
void PacketQueueClass::add(uint8_t* buf, size_t size) {
|
void PacketQueueClass::add(Packet_t* p) {
|
||||||
uint8_t idx = MAX_TX_QUEUE;
|
uint8_t idx = MAX_TX_QUEUE;
|
||||||
for (uint8_t i=0; i<(MAX_TX_QUEUE -1); i++) {
|
for (uint8_t i=0; i<(MAX_TX_QUEUE -1); i++) {
|
||||||
if (Queue[i].size == 0) { // search for a free slot
|
if (Queue[i].size == 0) { // search for a free slot
|
||||||
|
@ -443,14 +488,15 @@ void PacketQueueClass::add(uint8_t* buf, size_t size) {
|
||||||
if (Queue[idx].packetTime < Queue[i].packetTime) idx = i;
|
if (Queue[idx].packetTime < Queue[i].packetTime) idx = i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Queue[idx].size = size;
|
Queue[idx].size = p->size;
|
||||||
Queue[idx].packetTime = (uint32_t)RtcGetTimerValue();
|
Queue[idx].packetTime = p->packetTime;
|
||||||
MSG("enQueue Index=%i Size=%i\n", idx, Queue[idx].size);
|
MSG("enQueue Index=%i Size=%i\n\r", idx, Queue[idx].size);
|
||||||
memcpy(Queue[idx].buf, buf, size);
|
memcpy(Queue[idx].buf, p->buf, p->size);
|
||||||
hasPackets = true;
|
this->Count += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
Packet_t* PacketQueueClass::pop(void) {
|
bool PacketQueueClass::pop(void) {
|
||||||
|
if (this->Count == 0) return false;
|
||||||
uint8_t idx = MAX_TX_QUEUE;
|
uint8_t idx = MAX_TX_QUEUE;
|
||||||
for (uint8_t i=0 ;i < (MAX_TX_QUEUE -1); i++ ){
|
for (uint8_t i=0 ;i < (MAX_TX_QUEUE -1); i++ ){
|
||||||
if (Queue[i].size != 0) { // first not empty entry
|
if (Queue[i].size != 0) { // first not empty entry
|
||||||
|
@ -459,18 +505,23 @@ Packet_t* PacketQueueClass::pop(void) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (idx == MAX_TX_QUEUE) { // empty Queue
|
if (idx == MAX_TX_QUEUE) { // empty Queue
|
||||||
hasPackets = false;
|
this->Count = 0;
|
||||||
return (Packet_t*)NULL;
|
return false;
|
||||||
}
|
}
|
||||||
for (uint8_t i=idx; i<(MAX_TX_QUEUE -1); i++) {
|
for (uint8_t i=idx; i<(MAX_TX_QUEUE -1); i++) {
|
||||||
if ( (Queue[i].size != 0) && (Queue[idx].packetTime < Queue[i].packetTime) ) idx = i; // find oldest packet
|
if ( (Queue[i].size != 0) && (Queue[idx].packetTime < Queue[i].packetTime) ) idx = i; // find oldest packet
|
||||||
}
|
}
|
||||||
return &Queue[idx];
|
PacketToSend.packetTime = millis(); // start timer. after 1 minute, drop packet
|
||||||
|
PacketToSend.size = Queue[idx].size;
|
||||||
|
memcpy(PacketToSend.buf, Queue[idx].buf, Queue[idx].size);
|
||||||
|
this->Count -= 1;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PacketQueueClass::clear(void) {
|
void PacketQueueClass::clear(void) {
|
||||||
for (uint8_t i = 0; i<(MAX_TX_QUEUE - 1); i++) {
|
for (uint8_t i = 0; i<(MAX_TX_QUEUE - 1); i++) {
|
||||||
Queue[i].size = 0; // mark as "deleted"
|
this->Queue[i].size = 0; // mark as "deleted"
|
||||||
|
this->Count = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
127
src/main.h
127
src/main.h
|
@ -44,6 +44,7 @@ static const uint8_t mypsk[] = {0xd4, 0xf1, 0xbb, 0x3a, 0x20, 0x29, 0x07, 0x59,
|
||||||
using std::min;
|
using std::min;
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
|
|
||||||
#include <RadioLib.h>
|
#include <RadioLib.h>
|
||||||
|
|
||||||
#ifdef CUBECELL
|
#ifdef CUBECELL
|
||||||
|
@ -64,9 +65,10 @@ extern "C"
|
||||||
#include <mesh/compression/unishox2.h>
|
#include <mesh/compression/unishox2.h>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// struct to store the raw packet data (buf, size) and the time of receiving
|
||||||
typedef struct {
|
typedef struct {
|
||||||
size_t size;
|
size_t size;
|
||||||
uint8_t buf[MAX_RHPACKETLEN -1];
|
uint8_t buf[MAX_RHPACKETLEN];
|
||||||
uint32_t packetTime;
|
uint32_t packetTime;
|
||||||
} Packet_t;
|
} Packet_t;
|
||||||
|
|
||||||
|
@ -84,9 +86,9 @@ private:
|
||||||
Packet_t Queue[MAX_TX_QUEUE - 1];
|
Packet_t Queue[MAX_TX_QUEUE - 1];
|
||||||
public:
|
public:
|
||||||
void clear(void);
|
void clear(void);
|
||||||
bool hasPackets = false;
|
uint8_t Count = 0;
|
||||||
void add(uint8_t* buf, size_t size);
|
void add(Packet_t* p);
|
||||||
Packet_t* pop(void);
|
bool pop(void);
|
||||||
};
|
};
|
||||||
PacketQueueClass txQueue;
|
PacketQueueClass txQueue;
|
||||||
|
|
||||||
|
@ -102,29 +104,44 @@ idStoreClass msgID;
|
||||||
|
|
||||||
CryptoKey psk;
|
CryptoKey psk;
|
||||||
meshtastic_MeshPacket mp;
|
meshtastic_MeshPacket mp;
|
||||||
uint8_t radiobuf[MAX_RHPACKETLEN];
|
|
||||||
bool repeatPacket = false;
|
bool repeatPacket = false;
|
||||||
int state = RADIOLIB_ERR_NONE;
|
int err = RADIOLIB_ERR_NONE;
|
||||||
Packet_t* p = NULL;
|
|
||||||
|
|
||||||
void MCU_deepsleep(void);
|
|
||||||
void startReceive(void);
|
|
||||||
bool perhapsSend(uint8_t* buf, size_t size);
|
|
||||||
bool perhapsDecode(uint8_t* buf, size_t size);
|
|
||||||
void printPacket(void);
|
|
||||||
void printVariants(void);
|
|
||||||
|
|
||||||
bool PacketReceived = false;
|
bool PacketReceived = false;
|
||||||
bool PacketSent = false;
|
bool PacketSent = false;
|
||||||
|
bool isReceiving = false;
|
||||||
|
|
||||||
|
/* Packet we are trying to send.
|
||||||
|
* .packetTime is the time we started trying to send it.
|
||||||
|
* packet will be dropped after a minute of trying.
|
||||||
|
*/
|
||||||
|
Packet_t PacketToSend;
|
||||||
|
Packet_t* p = NULL;
|
||||||
|
|
||||||
|
// global dio1 flag - will be set to true, when dio1 is active
|
||||||
volatile bool dio1 = false;
|
volatile bool dio1 = false;
|
||||||
|
|
||||||
|
// interrupt service routine for setting the dio1 flag
|
||||||
void ISR_dio1Action(void) {
|
void ISR_dio1Action(void) {
|
||||||
dio1 = true;
|
dio1 = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MCU_deepsleep(void);
|
||||||
|
void startReceive(void);
|
||||||
|
bool perhapsSend(Packet_t* p);
|
||||||
|
bool perhapsDecode(Packet_t* p);
|
||||||
|
void printPacket(void);
|
||||||
|
void printVariants(void);
|
||||||
|
|
||||||
/**************
|
/**************
|
||||||
* Meshtastic * https://github.com/meshtastic/firmware
|
* Meshtastic * https://github.com/meshtastic/firmware
|
||||||
**************/
|
**************/
|
||||||
|
float bw = 0;
|
||||||
|
uint8_t sf = 0;
|
||||||
|
uint8_t cr = 0;
|
||||||
|
int8_t power = CC_MY_LORA_POWER; // 0 = max legal power for region
|
||||||
|
float freq = 0;
|
||||||
|
float snr = 5.0;
|
||||||
|
uint32_t activeReceiveStart = 0;
|
||||||
|
|
||||||
/** Slottime is the minimum time to wait, consisting of:
|
/** Slottime is the minimum time to wait, consisting of:
|
||||||
- CAD duration (maximum of SX126x and SX127x);
|
- CAD duration (maximum of SX126x and SX127x);
|
||||||
|
@ -363,21 +380,30 @@ int16_t generateHash(ChannelIndex channelNum)
|
||||||
else {
|
else {
|
||||||
const char *name = CC_CHANNEL_NAME; //getName(channelNum);
|
const char *name = CC_CHANNEL_NAME; //getName(channelNum);
|
||||||
uint8_t h = xorHash((const uint8_t *)name, strlen(name));
|
uint8_t h = xorHash((const uint8_t *)name, strlen(name));
|
||||||
|
|
||||||
h ^= xorHash(k.bytes, k.length);
|
h ^= xorHash(k.bytes, k.length);
|
||||||
|
|
||||||
return h;
|
return h;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t getPacketTime(uint32_t pl)
|
||||||
|
{
|
||||||
|
float bandwidthHz = bw * 1000.0f;
|
||||||
|
bool headDisable = false; // we currently always use the header
|
||||||
|
float tSym = (1 << sf) / bandwidthHz;
|
||||||
|
|
||||||
|
bool lowDataOptEn = tSym > 16e-3 ? true : false; // Needed if symbol time is >16ms
|
||||||
|
|
||||||
|
float tPreamble = (preambleLength + 4.25f) * tSym;
|
||||||
|
float numPayloadSym =
|
||||||
|
8 + max(ceilf(((8.0f * pl - 4 * sf + 28 + 16 - 20 * headDisable) / (4 * (sf - 2 * lowDataOptEn))) * cr), 0.0f);
|
||||||
|
float tPayload = numPayloadSym * tSym;
|
||||||
|
float tPacket = tPreamble + tPayload;
|
||||||
|
|
||||||
|
return (uint32_t)(tPacket * 1000);
|
||||||
|
}
|
||||||
|
|
||||||
void applyModemConfig()
|
void applyModemConfig()
|
||||||
{
|
{
|
||||||
float bw = 0;
|
|
||||||
uint8_t sf = 0;
|
|
||||||
uint8_t cr = 0;
|
|
||||||
int8_t power = CC_MY_LORA_POWER; // 0 = max legal power for region
|
|
||||||
float freq = 0;
|
|
||||||
|
|
||||||
if (CC_LORA_USE_PRESET) {
|
if (CC_LORA_USE_PRESET) {
|
||||||
|
|
||||||
switch (CC_MY_LORA_PRESET) {
|
switch (CC_MY_LORA_PRESET) {
|
||||||
|
@ -473,15 +499,64 @@ void applyModemConfig()
|
||||||
// Syncword is 0x2b, see RadioLibInterface.h
|
// Syncword is 0x2b, see RadioLibInterface.h
|
||||||
// preamble length is 16, see RadioInterface.h
|
// preamble length is 16, see RadioInterface.h
|
||||||
|
|
||||||
state = radio.begin(freq, bw, sf, cr, 0x2b, power, 16);
|
err = radio.begin(freq, bw, sf, cr, 0x2b, power, 16);
|
||||||
|
|
||||||
if (state == RADIOLIB_ERR_NONE) {
|
if (err == RADIOLIB_ERR_NONE) {
|
||||||
MSG("success!\n");
|
MSG("success!\n");
|
||||||
} else {
|
} else {
|
||||||
MSG("\n[ERROR] [SX1262} Init failed, code: %i\n\n ** Full Stop **", state);
|
MSG("\n[ERROR] [SX1262} Init failed, code: %i\n\n ** Full Stop **", err);
|
||||||
while (true);
|
while (true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// used to calculate wait time before repeating a packet
|
// used to calculate wait time before repeating a packet
|
||||||
slotTimeMsec = 8.5 * pow(2, sf) / bw + 0.2 + 0.4 + 7;
|
slotTimeMsec = 8.5 * pow(2, sf) / bw + 0.2 + 0.4 + 7;
|
||||||
|
preambleTimeMsec = getPacketTime((uint32_t)0);
|
||||||
|
maxPacketTimeMsec = getPacketTime(meshtastic_Constants_DATA_PAYLOAD_LEN + sizeof(PacketHeader));
|
||||||
|
MSG("[INF]SlotTime=%ims PreambleTime=%ims maxPacketTime=%ims\n", slotTimeMsec, preambleTimeMsec, maxPacketTimeMsec);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** The delay to use when we want to flood a message */
|
||||||
|
uint32_t getTxDelayMsecWeighted(float snr) // RadioInterface.cpp
|
||||||
|
{
|
||||||
|
// The minimum value for a LoRa SNR
|
||||||
|
const uint32_t SNR_MIN = -20;
|
||||||
|
|
||||||
|
// The maximum value for a LoRa SNR
|
||||||
|
const uint32_t SNR_MAX = 15;
|
||||||
|
|
||||||
|
// high SNR = large CW size (Long Delay)
|
||||||
|
// low SNR = small CW size (Short Delay)
|
||||||
|
uint32_t delay = 0;
|
||||||
|
uint8_t CWsize = map(snr, SNR_MIN, SNR_MAX, CWmin, CWmax);
|
||||||
|
|
||||||
|
// our role is meshtastic_Config_DeviceConfig_Role_REPEATER
|
||||||
|
delay = random(0, 2 * CWsize) * slotTimeMsec;
|
||||||
|
return delay;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isActivelyReceiving()
|
||||||
|
{
|
||||||
|
// The IRQ status will be cleared when we start our read operation. Check if we've started a header, but haven't yet
|
||||||
|
// received and handled the interrupt for reading the packet/handling errors.
|
||||||
|
|
||||||
|
uint16_t irq = radio.getIrqStatus();
|
||||||
|
bool detected = (irq & (RADIOLIB_SX126X_IRQ_HEADER_VALID | RADIOLIB_SX126X_IRQ_PREAMBLE_DETECTED));
|
||||||
|
// Handle false detections
|
||||||
|
if (detected) {
|
||||||
|
uint32_t now = millis();
|
||||||
|
if (!activeReceiveStart) {
|
||||||
|
activeReceiveStart = now;
|
||||||
|
} else if ((now - activeReceiveStart > 2 * preambleTimeMsec) && !(irq & RADIOLIB_SX126X_IRQ_HEADER_VALID)) {
|
||||||
|
// The HEADER_VALID flag should be set by now if it was really a packet, so ignore PREAMBLE_DETECTED flag
|
||||||
|
activeReceiveStart = 0;
|
||||||
|
MSG("Ignore false preamble detection.\n");
|
||||||
|
return false;
|
||||||
|
} else if (now - activeReceiveStart > maxPacketTimeMsec) {
|
||||||
|
// We should have gotten an RX_DONE IRQ by now if it was really a packet, so ignore HEADER_VALID flag
|
||||||
|
activeReceiveStart = 0;
|
||||||
|
MSG("Ignore false header detection.\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return detected;
|
||||||
}
|
}
|
Loading…
Reference in New Issue