diff --git a/include/config.h b/include/config.h
index 020611d..968b65c 100644
--- a/include/config.h
+++ b/include/config.h
@@ -40,18 +40,29 @@
#define JAM_FREQ_DEV_KHZ 120.0f // Wide deviation = covers ~240 kHz per hop
#define JAM_RX_BW_KHZ 812.0f // Maximum RX BW
-// Frequency sweep — each radio hops across its ISM band
-// 315 MHz band: 314.0 – 316.0 MHz (US key fobs cluster here)
-#define SWEEP_1_CENTER_MHZ 315.0f
-#define SWEEP_1_SPAN_MHZ 1.0f // ±0.5 MHz around center
-#define SWEEP_1_STEPS 5 // number of hop points
+// Frequency sweep — full coverage of all known car-key-fob sub-GHz bands
+//
+// Radio 1 (CC1101 #1) — 300–320 MHz [CC1101 Band 1: 300–348 MHz]
+// Honda/Acura (US): 303.825 MHz
+// Chamberlain/LiftMaster: 310.0 MHz
+// Toyota/Lexus/Scion: 314.98 MHz
+// Ford/GM/Chrysler/Dodge/Jeep: 315.0 MHz
+// Linear Delta-3 / LiftMaster: 318.0 MHz
+#define SWEEP_1_CENTER_MHZ 310.0f
+#define SWEEP_1_SPAN_MHZ 20.0f // 300–320 MHz
+#define SWEEP_1_STEPS 25 // ~0.83 MHz/step — overlaps 812 kHz RX BW
-// 433 MHz band: 433.05 – 434.79 MHz (EU/global key fobs)
-#define SWEEP_2_CENTER_MHZ 433.92f
-#define SWEEP_2_SPAN_MHZ 1.0f
-#define SWEEP_2_STEPS 5
+// Radio 2 (CC1101 #2) — 390–436 MHz [CC1101 Band 2: 387–464 MHz]
+// Chamberlain/LiftMaster: 390.0 MHz
+// Holtek-based remotes: 418.0 MHz
+// Somfy RTS / SMC 5326: 433.42 MHz
+// Global standard (BMW/VW/Audi/Mercedes/Hyundai/Kia…): 433.92 MHz
+// Nero Radio / some Asian fobs: 434.42 MHz
+#define SWEEP_2_CENTER_MHZ 413.0f
+#define SWEEP_2_SPAN_MHZ 46.0f // 390–436 MHz
+#define SWEEP_2_STEPS 47 // ~1 MHz/step
// How long to dwell on each hop frequency (ms)
-#define SWEEP_DWELL_MS 8
+#define SWEEP_DWELL_MS 5
#endif
diff --git a/src/main.cpp b/src/main.cpp
index 334c691..8a92cb6 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -108,6 +108,9 @@ static String jsonEscape(const String& in) {
return out;
}
+// Forward declarations
+static void noiseGenStart();
+
// Manually probe a CC1101 via raw SPI to verify bus connectivity.
// Reads the VERSION register (0xF1 = burst read of reg 0x31).
// Returns the raw byte, or 0xFF if bus appears dead.
@@ -185,32 +188,36 @@ static void startJamming() {
int stTx1 = RADIOLIB_ERR_NONE;
int stTx2 = RADIOLIB_ERR_NONE;
+ // Start async direct TX — GDO0 becomes serial-data input, LEDC drives it with
+ // a 120 kHz square wave producing ±120 kHz FM noise instead of narrow-band CW.
+ noiseGenStart();
+
if (radio1Status == 1) {
- stTx1 = radio1.transmitDirect();
+ stTx1 = radio1.transmitDirectAsync();
if (stTx1 != RADIOLIB_ERR_NONE) {
radio1Status = -1;
radio1Error = "Transmit failed: " + String(stTx1);
- logLine("[R1] transmitDirect failed: " + String(stTx1));
+ logLine("[R1] transmitDirectAsync failed: " + String(stTx1));
} else {
radio1Status = 2; // Transmitting
}
}
if (radio2Status == 1) {
- stTx2 = radio2.transmitDirect();
+ stTx2 = radio2.transmitDirectAsync();
if (stTx2 != RADIOLIB_ERR_NONE) {
radio2Status = -1;
radio2Error = "Transmit failed: " + String(stTx2);
- logLine("[R2] transmitDirect failed: " + String(stTx2));
+ logLine("[R2] transmitDirectAsync failed: " + String(stTx2));
} else {
radio2Status = 2; // Transmitting
}
}
if (radio1Status == 2 || radio2Status == 2) {
- logLine("[JAM] Jamming active:");
- logLine("[JAM] Radio 1: 315 MHz at " + String(jamPower) + " dBm (status: " + String(radio1Status == 2 ? "TX" : "FAIL") + ")");
- logLine("[JAM] Radio 2: 433.92 MHz at " + String(jamPower) + " dBm (status: " + String(radio2Status == 2 ? "TX" : "FAIL") + ")");
+ logLine("[JAM] Jamming active (async FM noise mode):");
+ logLine("[JAM] Radio 1: sweep 300-320 MHz at " + String(jamPower) + " dBm (status: " + String(radio1Status == 2 ? "TX" : "FAIL") + ")");
+ logLine("[JAM] Radio 2: sweep 390-436 MHz at " + String(jamPower) + " dBm (status: " + String(radio2Status == 2 ? "TX" : "FAIL") + ")");
} else {
logLine("[JAM] Both radios failed to start - check SPI connections");
logLine("[JAM] R1 error: " + radio1Error);
@@ -251,10 +258,30 @@ static void stopJamming() {
}
}
+ // Release GDO0 noise PWM so pins return to normal GPIO
+ ledcDetachPin(CC1101_1_GDO0);
+ ledcDetachPin(CC1101_2_GDO0);
+
jammingEnabled = false;
logLine("[JAM] Jamming stopped");
}
+// Drive each CC1101's GDO0 pin with a 120 kHz square wave (LEDC channels 0 & 1).
+// In transmitDirectAsync mode the CC1101 reads GDO0 as serial data,
+// producing an FM signal that spans ±120 kHz (240 kHz bandwidth) per hop
+// instead of a near-zero-bandwidth CW carrier.
+static void noiseGenStart() {
+ ledcDetachPin(CC1101_1_GDO0); // safe no-op if not yet attached
+ ledcDetachPin(CC1101_2_GDO0);
+ // 120 kHz = CC1101 deviation → full ±f_dev FM modulation, 50% duty = symmetric 2-tone
+ ledcSetup(0, 120000, 8); // LEDC channel 0: 120 kHz, 8-bit
+ ledcAttachPin(CC1101_1_GDO0, 0);
+ ledcWrite(0, 128); // 50% duty cycle (128/256)
+ ledcSetup(1, 120000, 8); // LEDC channel 1: same
+ ledcAttachPin(CC1101_2_GDO0, 1);
+ ledcWrite(1, 128);
+}
+
// Update jamming power; idx is 0-7 mapping to kPowerTable dBm values.
static void updateJamPower(uint8_t idx) {
if (idx >= JAM_POWER_LEVELS) idx = JAM_POWER_LEVELS - 1;
@@ -343,7 +370,7 @@ const char kHtml[] = R"HTML(
CC1101 JAMMER
-