Merge branch 'master' into nomad-gemini

This commit is contained in:
Thomas Göttgens
2024-12-29 22:50:31 +01:00
committed by GitHub
224 changed files with 16932 additions and 1755 deletions
+52 -44
View File
@@ -31,31 +31,7 @@ void LockingArduinoHal::spiEndTransaction()
#if ARCH_PORTDUINO
void LockingArduinoHal::spiTransfer(uint8_t *out, size_t len, uint8_t *in)
{
if (busy == RADIOLIB_NC) {
spi->transfer(out, in, len);
} else {
uint16_t offset = 0;
while (len) {
uint8_t block_size = (len < 20 ? len : 20);
spi->transfer((out != NULL ? out + offset : NULL), (in != NULL ? in + offset : NULL), block_size);
if (block_size == len)
return;
// ensure GPIO is low
uint32_t start = millis();
while (digitalRead(busy)) {
if (!Throttle::isWithinTimespanMs(start, 2000)) {
LOG_ERROR("GPIO mid-transfer timeout, is it connected?");
return;
}
}
offset += block_size;
len -= block_size;
}
}
spi->transfer(out, in, len);
}
#endif
@@ -259,12 +235,12 @@ void RadioLibInterface::onNotify(uint32_t notification)
case ISR_TX:
handleTransmitInterrupt();
startReceive();
startTransmitTimer();
setTransmitDelay();
break;
case ISR_RX:
handleReceiveInterrupt();
startReceive();
startTransmitTimer();
setTransmitDelay();
break;
case TRANSMIT_DELAY_COMPLETED:
@@ -274,23 +250,32 @@ void RadioLibInterface::onNotify(uint32_t notification)
if (!canSendImmediately()) {
setTransmitDelay(); // currently Rx/Tx-ing: reset random delay
} else {
if (isChannelActive()) { // check if there is currently a LoRa packet on the channel
startReceive(); // try receiving this packet, afterwards we'll be trying to transmit again
setTransmitDelay();
meshtastic_MeshPacket *txp = txQueue.getFront();
assert(txp);
long delay_remaining = txp->tx_after ? txp->tx_after - millis() : 0;
if (delay_remaining > 0) {
// There's still some delay pending on this packet, so resume waiting for it to elapse
notifyLater(delay_remaining, TRANSMIT_DELAY_COMPLETED, false);
} else {
// Send any outgoing packets we have ready as fast as possible to keep the time between channel scan and
// actual transmission as short as possible
meshtastic_MeshPacket *txp = txQueue.dequeue();
assert(txp);
bool sent = startSend(txp);
if (sent) {
// Packet has been sent, count it toward our TX airtime utilization.
uint32_t xmitMsec = getPacketTime(txp);
airTime->logAirtime(TX_LOG, xmitMsec);
if (isChannelActive()) { // check if there is currently a LoRa packet on the channel
startReceive(); // try receiving this packet, afterwards we'll be trying to transmit again
setTransmitDelay();
} else {
// Send any outgoing packets we have ready as fast as possible to keep the time between channel scan and
// actual transmission as short as possible
txp = txQueue.dequeue();
assert(txp);
bool sent = startSend(txp);
if (sent) {
// Packet has been sent, count it toward our TX airtime utilization.
uint32_t xmitMsec = getPacketTime(txp);
airTime->logAirtime(TX_LOG, xmitMsec);
}
}
}
}
} else {
// Do nothing, because the queue is empty
}
break;
default:
@@ -301,15 +286,24 @@ void RadioLibInterface::onNotify(uint32_t notification)
void RadioLibInterface::setTransmitDelay()
{
meshtastic_MeshPacket *p = txQueue.getFront();
if (!p) {
return; // noop if there's nothing in the queue
}
// We want all sending/receiving to be done by our daemon thread.
// We use a delay here because this packet might have been sent in response to a packet we just received.
// So we want to make sure the other side has had a chance to reconfigure its radio.
/* We assume if rx_snr = 0 and rx_rssi = 0, the packet was generated locally.
* This assumption is valid because of the offset generated by the radio to account for the noise
* floor.
*/
if (p->rx_snr == 0 && p->rx_rssi == 0) {
if (p->tx_after) {
unsigned long add_delay = p->rx_rssi ? getTxDelayMsecWeighted(p->rx_snr) : getTxDelayMsec();
unsigned long now = millis();
p->tx_after = max(p->tx_after + add_delay, now + add_delay);
notifyLater(now - p->tx_after, TRANSMIT_DELAY_COMPLETED, false);
} else if (p->rx_snr == 0 && p->rx_rssi == 0) {
/* We assume if rx_snr = 0 and rx_rssi = 0, the packet was generated locally.
* This assumption is valid because of the offset generated by the radio to account for the noise
* floor.
*/
startTransmitTimer(true);
} else {
// If there is a SNR, start a timer scaled based on that SNR.
@@ -336,6 +330,20 @@ void RadioLibInterface::startTransmitTimerSNR(float snr)
}
}
/**
* If the packet is not already in the late rebroadcast window, move it there
*/
void RadioLibInterface::clampToLateRebroadcastWindow(NodeNum from, PacketId id)
{
// Look for non-late packets only, so we don't do this twice!
meshtastic_MeshPacket *p = txQueue.remove(from, id, true, false);
if (p) {
p->tx_after = millis() + getTxDelayMsecWeightedWorst(p->rx_snr);
txQueue.enqueue(p);
LOG_DEBUG("Move existing queued packet to the late rebroadcast window %dms from now", p->tx_after - millis());
}
}
void RadioLibInterface::handleTransmitInterrupt()
{
// This can be null if we forced the device to enter standby mode. In that case