Install
$ agentstack add skill-wang200935-security-agent-skills-rf-multi-protocol-jammer ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
RF Jammer Style Multi-Protocol 2.4GHz Jammer
🎯 Trigger Conditions
- Building OLED-menu multi-protocol 2.4GHz jammer (WiFi/BLE/BT/VideoTX/RC/Zigbee/USB/nRF24)
- Based on cifertech/rf-jammer or architecture
- ESP32 + 3×nRF24L01+PA+LNA on shared SPI bus
- Breadboard/high-R connections requiring bit-bang SPI with verified writes
- Need ShockBurst for WiFi/BLE, fast sweep for BT Classic, channel hopping for others
📂 Reference Architecture: cifertech/rf-jammer
Hardware
- MCU: ESP32-D0WDQ6 (or S3/C3/C6/H2)
- Radios: 3× nRF24L01+PA+LNA
- SPI: Shared SCK=18, MISO=19, MOSI=23
- CE/CSN: Radio A: CE=5, CSN=17 | Radio B: CE=16, CSN=4 | Radio C: CE=14, CSN=13
- OLED: SSD1306 I2C (SDA/SCL per board)
- Buttons: 3× input-only GPIO (34/36/39) with 10kΩ pullups
- NeoPixel: GPIO 33 (moved from 14 to avoid CE_C conflict)
Firmware Modes (8 protocols)
| Mode | Constant | Target | Method | Channels | |------|----------|--------|--------|----------| | WiFi | WiFi_MODULE | 802.11 b/g/n | constCarrier static 100% duty | ch 12, 37, 62 (WiFi 1/6/11) | | BLE | BLE_MODULE | BLE advertising | constCarrier static 100% duty | ch 2, 26, 80 (adv 37/38/39) | | BT Classic | Bluetooth_MODULE | BR/EDR 79ch | constCarrier + fast segmented sweep | A:2-27, B:28-53, C:54-80 | | Video TX | VIDEO_TX_MODULE | Analog FPV | constCarrier + 3ms hop, ch+2/+4 offset | videoTransmitterchannels[] | | RC | RC_MODULE | 2.4GHz RC | constCarrier + 3ms hop, ch+2/+4 offset | rcchannels[] | | Zigbee | ZIGBEE_MODULE | 802.15.4 | constCarrier + 3ms hop, ch+2/+4 offset | zigbeechannels[] | | USB Wireless | USB_WIRELESS_MODULE | Logitech/etc | constCarrier + 3ms hop, ch+2/+4 offset | usbWirelesschannels[] | | nRF24 | NRF24_MODULE | nRF24 links | constCarrier + 3ms hop, ch+2/+4 offset | nrf24_channels[] |
⚡ Core Technical Patterns
1. SoftNRF Bit-Bang Driver (Shared SPI)
All 3 radios share SCK/MOSI/MISO. Each has independent CE/CSN. Bit-bang delay per radio:
- Radio A/B (healthy): 10µs
- Radio C (high-R): 150µs
SoftNRF::busInit(); // Once at boot
RadioA.beginPins(); RadioB.beginPins(); RadioC.beginPins();
2. startConstCarrier — The ONLY Working TX Method (ALL Modes)
CRITICAL: Pure ShockBurst TX fires ONE packet then stops (FIFO empties, TXDS set, radio idle). Pure CW carrier (CONTWAVE alone, no payload) does NOT trigger WiFi CCA backoff. The ONLY configuration that produces continuous effective interference is the RF24 library's startConstCarrier() pattern: CONTWAVE + PLLLOCK + WTXPAYLOADNOACK + REUSETX_PL used together.
See references/nrf24-tx-mode-truth.md for the full empirical analysis and verification data.
void SoftNRF::startConstCarrier() {
// 1) CONT_WAVE + PLL_LOCK in RF_SETUP (carrier stays on)
writeRegChecked(RF_SETUP, 0x0F | 0x90); // 2Mbps + PA max + LNA + CONT_WAVE + PLL_LOCK
// 2) No auto-ack, no retries
writeRegChecked(EN_AA, 0x00);
writeRegChecked(SETUP_RETR, 0x00);
// 3) TX_ADDR + RX_ADDR_P0 = 5 bytes 0xFF (spectrum-rich)
// 4) PWR_UP=1, PRIM_RX=0, CRC off → CONFIG=0x02
writeRegChecked(CONFIG, 0x02);
delay(2); // Tpd2stby >= 1.5ms
// 5) FLUSH_TX → W_TX_PAYLOAD_NOACK (0xB0) with 32 bytes 0xFF
// 6) CE HIGH → delay 1ms
// 7) sendReuseTXPL(): CE LOW → clear MAX_RT → transfer(0xE3) → CE HIGH
}
Expected register state after start: RFSETUP=0x9F, CONFIG=0x02, STATUS=0x0e. To verify TX is running: FIFOSTATUS should show TXFULL=1, TXEMPTY=0 (FIFO has data, carrier active). If TXEMPTY=1 and TXDS=1, the radio fired one packet and stopped — startConstCarrier was not called or REUSETXPL failed.
ALL 8 modes now use startConstCarrier — WiFi, BLE, BT, VideoTX, RC, Zigbee, nRF24, USB. The mode only changes which channels the radios sit on or sweep through. The TX mechanism is always constCarrier.
// In initAllRadios() — same for ALL modes
RadioA.setChannelChecked(chA);
RadioB.setChannelChecked(chB);
RadioC.setChannelChecked(chC);
RadioA.startConstCarrier();
RadioB.startConstCarrier();
RadioC.startConstCarrier();
// Verify: RF_SETUP must be 0x9F on all 3 radios
3. Bluetooth Classic: Fast Segmented Sweep (constCarrier stays ON)
BT Classic hops 1600×/s over 79 channels with AFH. Slow 3ms hopping lets AFH map and avoid us. Solution: parallel segmented sweep at ~350µs/hop. CONTWAVE carrier stays ON — only RFCH changes (PLL re-locks ~130µs).
// In jamLoop() - ONLY for Bluetooth_MODULE
static uint8_t swA = 2, swB = 28, swC = 54, cDiv = 0;
RadioA.setChannel(swA); // A: 2-27 (every loop)
RadioB.setChannel(swB); // B: 28-53 (every loop)
if (++cDiv >= 4) { // C: 54-80 (1/4 rate due to 150µs delay)
RadioC.setChannel(swC);
swC = (swC >= 80) ? 54 : swC + 1;
cDiv = 0;
}
swA = (swA >= 27) ? 2 : swA + 1;
swB = (swB >= 53) ? 28 : swB + 1;
Coverage: Full 2-80 sweep in ~9ms (vs BT's 625µs hop). AFH cannot adapt fast enough.
4. Other Sweep Modes: 3ms Channel Hop with Offsets
VideoTX/RC/Zigbee/nRF24/USB all sweep their channel tables at 3ms/hop with +2/+4 offsets. Carrier stays ON (CONTWAVE) — only RFCH changes.
byte ch = channels[hopIndex % chCount];
hopIndex++;
RadioA.setChannel(ch);
RadioB.setChannel((ch + 2 readReg(0x06) != 0x9F) { // expected: CONT_WAVE+PLL_LOCK+2Mbps+PA max
r->reloadP(); // flush + reload payload + re-arm REUSE_TX_PL
}
}
📡 nRF24 Channel ↔ Protocol Frequency Mapping
| Protocol | Freq (MHz) | nRF24 Channel | |----------|------------|---------------| | WiFi ch 1 | 2412 | 12 | | WiFi ch 6 | 2437 | 37 | | WiFi ch 11 | 2462 | 62 | | BLE adv 37 | 2402 | 2 | | BLE adv 38 | 2426 | 26 | | BLE adv 39 | 2480 | 80 | | BT Classic | 2402-2480 | 2-80 | | Zigbee ch 11 | 2405 | 5 | | Zigbee ch 26 | 2480 | 80 |
Formula: nRF24_ch = freq_MHz - 2400
🔧 Configuration Constants (config.h)
// Pin definitions
#define NRF_CE_PIN_A 5
#define NRF_CSN_PIN_A 17
#define NRF_CE_PIN_B 16
#define NRF_CSN_PIN_B 4
#define NRF_CE_PIN_C 14
#define NRF_CSN_PIN_C 13
// SoftNRF delays (µs per bit)
#define NRF_DELAY_A 10
#define NRF_DELAY_B 10
#define NRF_DELAY_C 150
// NeoPixel (moved from GPIO 14 to avoid CE_C conflict)
#define NEOPIXEL_PIN 33
// Buttons (input-only GPIOs with 10kΩ pullups)
#define PIN_BTN_L 34
#define PIN_BTN_R 36
#define PIN_BTN_S 39
📋 Channel Tables (config.h)
// WiFi: nRF24 channels for 1, 6, 11
const byte WiFi_channels[] = {12, 37, 62};
// BLE: advertising channels 37, 38, 39
const byte ble_channels[] = {2, 26, 80};
// Bluetooth Classic: all 79 channels (2-80)
const byte bluetooth_channels[] = {2,3,4,...,80}; // 79 entries
// Video TX (analog FPV bands)
const byte videoTransmitter_channels[] = {...};
// RC (FlySky, FrSky, etc.)
const byte rc_channels[] = {...};
// Zigbee (15.4 channels 11-26)
const byte zigbee_channels[] = {5,6,7,...,80};
// nRF24 native
const byte nrf24_channels[] = {2,3,...,80};
// USB Wireless (Logitech Unifying, etc.)
const byte usbWireless_channels[] = {...};
🚀 Boot Sequence
void setup() {
Serial.begin(115200);
// 1. Park ALL radio pins FIRST (CSN HIGH, CE LOW)
pinMode(NRF_CE_PIN_A, OUTPUT); digitalWrite(NRF_CE_PIN_A, LOW);
pinMode(NRF_CSN_PIN_A, OUTPUT); digitalWrite(NRF_CSN_PIN_A, HIGH);
// ... same for B, C
// 2. Init shared SPI bus (bit-bang)
SoftNRF::busInit();
RadioA.beginPins(); RadioB.beginPins(); RadioC.beginPins();
// 3. Verify all 3 radios present
// 4. OLED init, button ISRs
// 5. Disable ESP32 WiFi/BT (we use nRF24 for everything)
esp_bt_controller_deinit();
esp_wifi_stop(); esp_wifi_deinit(); esp_wifi_disconnect();
// 6. Auto-activate after 3s (for remote testing)
delay(3000);
current = ACTIVE_MODE;
initAllRadios(); // Calls startConstCarrier() on all 3 radios — starts jamming immediately
// Verify: Serial.printf("A: RF_SETUP=0x%02x", RadioA.readReg(0x06)); // expect 0x9F
}
🎮 Button Controls
- Left/Right: Cycle through 8 modes
- Select (OK): Toggle ACTIVE/STANDBY
- Auto-activate: 3s after boot (diagnostic mode)
🔄 jamLoop() Dispatch Logic
void jamLoop() {
// WiFi/BLE: static constCarrier - no hopping needed (set in initAllRadios)
if (current_Mode == WiFi_MODULE || current_Mode == BLE_MODULE) return;
// Bluetooth Classic: fast segmented sweep (constCarrier stays ON, only RF_CH changes)
if (current_Mode == Bluetooth_MODULE) {
// ... sweep A:2-27, B:28-53, C:54-80 at ~350µs/hop
return;
}
// All other modes: 3ms hop with +2/+4 offsets (constCarrier stays ON)
if (millis() - lastHop < 3) return;
lastHop = millis();
byte ch = channels[hopIndex++ % chCount];
RadioA.setChannel(ch);
RadioB.setChannel(min(ch + 2, 80));
RadioC.setChannel(min(ch + 4, 80));
}
⚠️ Critical Pitfalls Learned
- GPIO 2 = CSNC kills Radio C — GPIO 2 has onboard LED + strapping function. Move CSNC to GPIO 13, CE_C to GPIO 14.
- NeoPixel on GPIO 14 conflicts with CE_C — Move NeoPixel to GPIO 33.
- Hardware SPI fails on high-R breadboard — Nanosecond edges ring. Must use bit-bang with µs delays.
- Radio C needs 150µs delay — 100µs still shows occasional register corruption during long FIFO loads.
- FIFO load (33 bytes) corrupts previous register writes — CSN glitches during long transaction. Solution: verified writes (
writeRegChecked) + periodicreloadP()if RF_SETUP drifts from 0x9F.
- BT Classic AFH defeats slow hopping — Must sweep full band faster than AFH adaptation (~9ms full sweep).
- ShockBurst TX fires ONE packet then stops ( empirically verified: STATUS TXDS=1, FIFO TXEMPTY=1, radio idle for 5s). DO NOT use
startShockBurst()for interference — it looks like it works on a scope during the first 10ms but is actually a single shot. UsestartConstCarrier()(CONTWAVE + PLLLOCK + WTXPAYLOADNOACK + REUSETX_PL) instead. Seereferences/nrf24-tx-mode-truth.md.
- Pure CW carrier (CONTWAVE without payload) does NOT trigger WiFi CCA — CCA energy detect alone is insufficient; receivers also need preamble-like correlation. The RF24 library's
startConstCarrier()combines CONTWAVE with a loaded payload + REUSETXPL, producing carrier modulated with packet data that triggers both CCA energy detect AND preamble correlation.
- CONTWAVE + REUSETXPL cannot be stopped by CE LOW — Datasheet warns both set together makes CE unresponsive. Must
powerDown()(PWRUP=0) to release, then clear CONTWAVE/PLLLOCK bits + FLUSH_TX. This is whystopConstCarrier()callspowerDown()first.
- initAllRadios() must be called on mode switch — checkMode() calls it when ACTIVE_MODE changes. setRadiosNeutralState() now calls
stopConstCarrier()notpowerDown()alone.
- REUSETXPL (0xE3) is an SPI command, not a register write — Must use
transfer(0xE3)notwriteReg(0x1D, 0x04). The sequence is: CE LOW → clear MAX_RT (write STATUS 0x30) → transfer(0xE3) → CE HIGH.
📁 Project Structure
rf-jammer_fw/
├── src/
│ ├── main.cpp # OLED, buttons, jamLoop, mode switching
│ ├── setting.cpp # initAllRadios, SoftNRF instances, mode configs
│ ├── setting.h # Radio declarations, mode enum
│ ├── softnrf.h # Bit-bang driver class
│ ├── softnrf.cpp # Implementation with verified writes
│ ├── config.h # Pins, delays, channel tables
│ └── neopixel.cpp # Status LED animations
├── test_radioC/ # Isolated Radio C diagnostics
└── platformio.ini
🛡️ Legal Notice
Taiwan Telecommunications Act Art 66/67: 2.4GHz jammer manufacture/possession/use illegal (fines 100-700萬 / 3-30萬). For authorized research in Faraday cage only.
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: Wang200935
- Source: Wang200935/security-agent-skills
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.