diff --git a/include/config.h b/include/config.h index 657ee1e..fabd625 100644 --- a/include/config.h +++ b/include/config.h @@ -36,10 +36,10 @@ #define JAM_FREQ_DEV_KHZ 380.0f // default passed to begin(); per-radio deviation applied after init #define JAM_RX_BW_KHZ 812.0f // wide RX BW for begin() // GDO0 toggle rate during jam. -// Restored to 100 kHz (10 µs period). Faster rates (500 kHz, 1 MHz) caused WDT boot-loops -// because ESP32-S3's gpio_set_level() calls take ~80 cycles each, overflowing the ISR budget. -// 100 kHz gives plenty of LFSR noise (AM sidebands at ±100, ±300, ±500 kHz) without crashing. -#define JAM_LFSR_KEY_HZ 100000 +// Restored to 500 kHz. Direct register writes (GPIO.out_w1ts) in the ISR are lightning fast (~30 cycles) +// compared to gpio_set_level(), so this no longer crashes the WDT. +// 500 kHz LFSR creates massive, dense noise blanketing the entire 314–316 MHz and 433–433.92 MHz bands. +#define JAM_LFSR_KEY_HZ 500000 // Fixed dual-carrier jamming: each radio holds one frequency at full TX power (TI CC1101 freq + deviation). // Many NA ~315 MHz RKE remotes are ASK/OOK (see TI CC1101 datasheet MDMCFG2.MOD_FORMAT). Jam path uses OOK on diff --git a/src/main.cpp b/src/main.cpp index 90f590e..296d150 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1572,17 +1572,33 @@ static void IRAM_ATTR noiseISR() { if (s_noiseIsPulse) { static uint32_t pulseToggle = 0; pulseToggle ^= 1; - if (s_noiseEn1) gpio_set_level((gpio_num_t)CC1101_1_GDO0, pulseToggle); - else gpio_set_level((gpio_num_t)CC1101_1_GDO0, 0); - if (s_noiseEn2) gpio_set_level((gpio_num_t)CC1101_2_GDO0, pulseToggle); - else gpio_set_level((gpio_num_t)CC1101_2_GDO0, 0); + if (s_noiseEn1) { + if (pulseToggle) GPIO.out_w1ts = (1 << CC1101_1_GDO0); + else GPIO.out_w1tc = (1 << CC1101_1_GDO0); + } else { + GPIO.out_w1tc = (1 << CC1101_1_GDO0); + } + if (s_noiseEn2) { + if (pulseToggle) GPIO.out_w1ts = (1 << CC1101_2_GDO0); + else GPIO.out_w1tc = (1 << CC1101_2_GDO0); + } else { + GPIO.out_w1tc = (1 << CC1101_2_GDO0); + } } else { const uint32_t s = lfsrStep(s_lfsr); s_lfsr = s; - if (s_noiseEn1) gpio_set_level((gpio_num_t)CC1101_1_GDO0, (s >> 0) & 1u); - else gpio_set_level((gpio_num_t)CC1101_1_GDO0, 0); - if (s_noiseEn2) gpio_set_level((gpio_num_t)CC1101_2_GDO0, (s >> 7) & 1u); - else gpio_set_level((gpio_num_t)CC1101_2_GDO0, 0); + if (s_noiseEn1) { + if (s & 1u) GPIO.out_w1ts = (1 << CC1101_1_GDO0); + else GPIO.out_w1tc = (1 << CC1101_1_GDO0); + } else { + GPIO.out_w1tc = (1 << CC1101_1_GDO0); + } + if (s_noiseEn2) { + if ((s >> 7) & 1u) GPIO.out_w1ts = (1 << CC1101_2_GDO0); + else GPIO.out_w1tc = (1 << CC1101_2_GDO0); + } else { + GPIO.out_w1tc = (1 << CC1101_2_GDO0); + } } } @@ -2248,9 +2264,21 @@ static void handleRoot() { server.sendHeader("Pragma", "no-cache"); server.sendHeader("Expires", "0"); - // Send directly from flash. WebServer::send_P handles Content-Length and TCP chunking - // internally without allocating a 15 KB String on the heap. - server.send_P(200, "text/html; charset=utf-8", kHtml, sizeof(kHtml) - 1); + // Set explicit content length to avoid Transfer-Encoding: chunked (which some mobile browsers drop) + const size_t total = sizeof(kHtml) - 1; + server.setContentLength(total); + server.send(200, "text/html; charset=utf-8", ""); + + // Stream the HTML out of flash in 1KB chunks with a tiny delay. + // Pushing 15KB in one shot blocks the ESP32 WiFi TX task and causes browser timeouts. + size_t off = 0; + while (off < total) { + size_t n = total - off; + if (n > 1024) n = 1024; + server.sendContent_P(kHtml + off, n); + off += n; + delay(2); // Let the Pro CPU / WiFi stack process TCP ACKs + } } static void handleLog() {