diff --git a/data/igate_conf.json b/data/igate_conf.json
index 69602fb..4d03837 100644
--- a/data/igate_conf.json
+++ b/data/igate_conf.json
@@ -28,9 +28,9 @@
"messagesToRF": false,
"objectsToRF": false,
"server": "rotate.aprs2.net",
- "passcode": "XYZVW",
+ "passcode": "XYZVW",
"port": 14580,
- "filter": "m/10"
+ "filter": "m/10"
},
"personalNote": "",
"blacklist": "",
@@ -40,6 +40,7 @@
"backupDigiMode": false
},
"lora": {
+ "cadActive": true,
"rxActive": true,
"rxFreq": 433775000,
"rxSpreadingFactor": 12,
diff --git a/include/configuration.h b/include/configuration.h
index f03bfb6..f87498e 100644
--- a/include/configuration.h
+++ b/include/configuration.h
@@ -75,6 +75,7 @@ public:
class LoraModule {
public:
+ bool cadActive;
bool rxActive;
long rxFreq;
int rxSpreadingFactor;
diff --git a/src/LoRa_APRS_iGate.cpp b/src/LoRa_APRS_iGate.cpp
index 429f1c4..55b484f 100644
--- a/src/LoRa_APRS_iGate.cpp
+++ b/src/LoRa_APRS_iGate.cpp
@@ -68,8 +68,8 @@ ___________________________________________________________________*/
#endif
-String versionDate = "2026-04-21";
-String versionNumber = "3.2.4";
+String versionDate = "2026-06-09";
+String versionNumber = "3.3.0";
Configuration Config;
WiFiClient aprsIsClient;
WiFiClient mqttClient;
diff --git a/src/aprs_is_utils.cpp b/src/aprs_is_utils.cpp
index 97be61b..6bee2dc 100644
--- a/src/aprs_is_utils.cpp
+++ b/src/aprs_is_utils.cpp
@@ -16,7 +16,7 @@
* along with LoRa APRS iGate. If not, see .
*/
-#include
+#include
#include
#include "configuration.h"
#include "network_manager.h"
@@ -47,7 +47,6 @@ extern bool modemLoggedToAPRSIS;
extern bool backupDigiMode;
extern String versionNumber;
-uint32_t lastRxTime = millis();
bool passcodeValid = false;
uint32_t lastServerCheck = 0;
@@ -403,7 +402,6 @@ namespace APRS_IS_Utils {
String aprsisPacket = aprsIsClient.readStringUntil('\r');
aprsisPacket.trim(); // Serial.println(aprsisPacket);
processAPRSISPacket(aprsisPacket);
- lastRxTime = millis();
}
}
#endif
diff --git a/src/configuration.cpp b/src/configuration.cpp
index 1e62f72..27e9bd8 100644
--- a/src/configuration.cpp
+++ b/src/configuration.cpp
@@ -97,6 +97,7 @@ bool Configuration::writeFile() {
#endif
data["digi"]["backupDigiMode"] = digi.backupDigiMode;
+ data["lora"]["cadActive"] = loramodule.cadActive;
data["lora"]["rxActive"] = loramodule.rxActive;
data["lora"]["rxFreq"] = loramodule.rxFreq;
data["lora"]["rxCodingRate4"] = loramodule.rxCodingRate4;
@@ -291,7 +292,8 @@ bool Configuration::readFile() {
digi.backupDigiMode = data["digi"]["backupDigiMode"] | false;
- if (data["lora"]["rxActive"].isNull() ||
+ if (data["lora"]["cadActive"].isNull() ||
+ data["lora"]["rxActive"].isNull() ||
data["lora"]["rxFreq"].isNull() ||
data["lora"]["rxSpreadingFactor"].isNull() ||
data["lora"]["rxCodingRate4"].isNull() ||
@@ -302,6 +304,7 @@ bool Configuration::readFile() {
data["lora"]["txCodingRate4"].isNull() ||
data["lora"]["txSignalBandwidth"].isNull() ||
data["lora"]["power"].isNull()) needsRewrite = true;
+ loramodule.cadActive = data["lora"]["cadActive"] | true;
loramodule.rxActive = data["lora"]["rxActive"] | true;
loramodule.rxFreq = data["lora"]["rxFreq"] | 433775000;
loramodule.rxSpreadingFactor = data["lora"]["rxSpreadingFactor"] | 12;
@@ -492,6 +495,7 @@ void Configuration::setDefaultValues() {
digi.ecoMode = 0;
digi.backupDigiMode = false;
+ loramodule.cadActive = true;
loramodule.rxActive = true;
loramodule.rxFreq = 433775000;
loramodule.rxSpreadingFactor = 12;
diff --git a/src/lora_utils.cpp b/src/lora_utils.cpp
index d9653f7..2ecd128 100644
--- a/src/lora_utils.cpp
+++ b/src/lora_utils.cpp
@@ -27,10 +27,13 @@
#include "display.h"
#include "utils.h"
+//
+#define DIFS_SLOTS 2 // Number of secuential CAD slots to consider a free channel to Tx
+int BO_MAX = 4; // Max Backoff
+//
extern Configuration Config;
extern NetworkManager *networkManager;
-extern uint32_t lastRxTime;
extern bool packetIsBeacon;
extern std::vector receivedPackets;
@@ -167,6 +170,34 @@ namespace LoRa_Utils {
radio.setBandwidth(signalBandwidth);
}
+ //
+ bool doCAD() { // Checks for CAD (Channel Activity Detection)
+ int state = radio.scanChannel();
+ if (state == RADIOLIB_LORA_DETECTED) {
+ return true;
+ } else if (state == RADIOLIB_CHANNEL_FREE) {
+ return false;
+ } else { // CAD failed, return true for safety
+ return true;
+ }
+ }
+
+ bool doDIFS() { // DIFS (Distributed Inter-Frame Space) Return True = channel free
+ for (uint8_t i = DIFS_SLOTS; i > 0; i--) {
+ if (doCAD()) return false;
+ }
+ return true;
+ }
+
+ void waitForDIFS() {
+ while (!doDIFS()) {
+ //
+ Serial.println("DIFS failed, retry");
+ //
+ }
+ }
+ //
+
void sendNewPacket(const String& newPacket) {
if (!Config.loramodule.txActive) return;
@@ -179,6 +210,19 @@ namespace LoRa_Utils {
#ifdef INTERNAL_LED_PIN
if (Config.digi.ecoMode != 1) digitalWrite(INTERNAL_LED_PIN, HIGH); // disabled in Ultra Eco Mode
#endif
+
+ //
+ #ifdef HAS_SX1262
+ if (Config.loramodule.cadActive) {
+ //
+ Serial.println("checking for DIFS");
+ //
+ waitForDIFS();
+ //
+ }
+ #endif
+ //
+
int state = radio.transmit("\x3c\xff\x01" + newPacket);
transmitFlag = true;
if (state == RADIOLIB_ERR_NONE) {
@@ -250,7 +294,6 @@ namespace LoRa_Utils {
} else {
packet = "";
}
- lastRxTime = millis();
return packet;
}
} else if (state == RADIOLIB_ERR_CRC_MISMATCH) {
diff --git a/src/station_utils.cpp b/src/station_utils.cpp
index be21b67..34fbccb 100644
--- a/src/station_utils.cpp
+++ b/src/station_utils.cpp
@@ -25,15 +25,11 @@
#include "utils.h"
#include
-#define SECS_TO_WAIT 3 // soon to be deleted...
-
extern Configuration Config;
-extern uint32_t lastRxTime;
extern String fourthLine;
extern bool shouldSleepLowVoltage;
-uint32_t lastTxTime = millis();
std::vector lastHeardStations;
std::vector blacklist;
std::vector managers;
@@ -214,15 +210,11 @@ namespace STATION_Utils {
}
void processOutputPacketBuffer() {
- int timeToWait = SECS_TO_WAIT * 1000; // 3 segs between packet Tx and also Rx ???
- uint32_t lastRx = millis() - lastRxTime;
- uint32_t lastTx = millis() - lastTxTime;
- if (outputPacketBuffer.size() > 0 && lastTx > timeToWait && lastRx > timeToWait) {
+ if (outputPacketBuffer.size() > 0) {
if (outputPacketBuffer[0].isBeacon) packetIsBeacon = true;
LoRa_Utils::sendNewPacket(outputPacketBuffer[0].packet);
if (outputPacketBuffer[0].isBeacon) packetIsBeacon = false;
outputPacketBuffer.erase(outputPacketBuffer.begin());
- lastTxTime = millis();
}
if (shouldSleepLowVoltage) {
while (outputPacketBuffer.size() > 0) {