diff options
| author | krolyxon <me@krolyxon.com> | 2026-06-20 00:24:34 +0530 |
|---|---|---|
| committer | krolyxon <me@krolyxon.com> | 2026-06-20 00:24:34 +0530 |
| commit | 7e4cfad53699fabbecb6696508e5addcffc1b095 (patch) | |
| tree | ebff581b0989df578c312247e1dad514c956572b /src-arduino/rf | |
| parent | 1f800b74329d4f8b1511b4cf2a0d031439e1038d (diff) | |
restructure to use rust source tree primarily
Diffstat (limited to 'src-arduino/rf')
| -rw-r--r-- | src-arduino/rf/cc1101.cpp | 357 | ||||
| -rw-r--r-- | src-arduino/rf/cc1101.h | 12 | ||||
| -rw-r--r-- | src-arduino/rf/nrf24.cpp | 217 | ||||
| -rw-r--r-- | src-arduino/rf/nrf24.h | 13 |
4 files changed, 599 insertions, 0 deletions
diff --git a/src-arduino/rf/cc1101.cpp b/src-arduino/rf/cc1101.cpp new file mode 100644 index 0000000..7e11d0b --- /dev/null +++ b/src-arduino/rf/cc1101.cpp @@ -0,0 +1,357 @@ +#include "cc1101.h" +#include "config.h" +#include "ELECHOUSE_CC1101_SRC_DRV.h" +#include "ui/display.h" +#include "utils/buttons.h" +#include "SPI.h" +#include <Arduino.h> + +// ===== CONFIG ===== +#define RAW_BUF_MAX 512 + +// ===== STATE ===== +static bool cc1101Inited = false; + +// ===== CAPTURE STATE ===== +volatile unsigned long captureBuffer[RAW_BUF_MAX]; +volatile int pulseIndex = 0; +volatile unsigned long lastEdgeTime = 0; +volatile bool capturing = false; + +// ===== RF SETTINGS ===== +float currentFreq = 433.92; +float dataRate = 3.79372; +float deviation = 0.0; +float rxBW = 325.0; +int powerLevel = 10; + +// ===== ISR ===== +void IRAM_ATTR pulseISR() { + unsigned long now = micros(); + + if (!capturing) + return; + if (pulseIndex >= RAW_BUF_MAX) + return; + + unsigned long duration = now - lastEdgeTime; + + if (duration < 150) + return; + + captureBuffer[pulseIndex++] = duration; + lastEdgeTime = now; +} + +// ===== OOK SETUP ===== +void setupOOKMode() { + ELECHOUSE_cc1101.SetRx(); + ELECHOUSE_cc1101.setMHZ(currentFreq); + + ELECHOUSE_cc1101.setModulation(2); // ASK/OOK + ELECHOUSE_cc1101.setDRate(dataRate); + ELECHOUSE_cc1101.setDeviation(0); + ELECHOUSE_cc1101.setRxBW(rxBW); + ELECHOUSE_cc1101.setSyncMode(0); + ELECHOUSE_cc1101.setPA(powerLevel); +} + +// ===== INIT (LAZY, SAFE) ===== +// ================= CC1101 INIT ================= +bool initCC1101() { + Serial.println(); + Serial.println("===== CC1101 INIT ====="); + + // ===== SPI ===== + SPI.begin(cc1101_SCK, cc1101_MISO, cc1101_MOSI, CC1101_CS); + + pinMode(CC1101_CS, OUTPUT); + digitalWrite(CC1101_CS, HIGH); + + delay(100); + + // ===== GDO ===== + ELECHOUSE_cc1101.setGDO(CC1101_GDO0, -1); + + ELECHOUSE_cc1101.setSpiPin(cc1101_SCK, cc1101_MISO, cc1101_MOSI, CC1101_CS); + + // ===== DETECT ===== + Serial.println("Checking chip..."); + + if (!ELECHOUSE_cc1101.getCC1101()) { + Serial.println("❌ CC1101 NOT FOUND"); + return false; + } + + Serial.println("✅ CC1101 FOUND"); + + // ===== IMPORTANT ===== + // DO NOT CALL Init() + // it freezes on some ESP32-S3 setups + + // ===== MANUAL CONFIG ===== + ELECHOUSE_cc1101.setMHZ(currentFreq); + + // 2 = ASK/OOK + ELECHOUSE_cc1101.setModulation(2); + + ELECHOUSE_cc1101.setDRate(dataRate); + + ELECHOUSE_cc1101.setRxBW(rxBW); + + ELECHOUSE_cc1101.setDeviation(0); + + // disable sync requirement + ELECHOUSE_cc1101.setSyncMode(0); + + ELECHOUSE_cc1101.setPA(powerLevel); + + // async serial mode + ELECHOUSE_cc1101.setCCMode(0); + + // enter RX + ELECHOUSE_cc1101.SetRx(); + + pinMode(CC1101_GDO0, INPUT); + + Serial.println("✅ RX MODE READY"); + + cc1101Inited = true; + return true; +} +// ===== CAPTURE CONTROL ===== +void startCapture() { + pulseIndex = 0; + capturing = true; + lastEdgeTime = micros(); + + attachInterrupt(digitalPinToInterrupt(CC1101_GDO0), pulseISR, CHANGE); + + Serial.println("Looking for RF... "); +} + +bool isCC1101Ready() { return cc1101Inited; } + +void stopCapture() { + capturing = false; + + detachInterrupt(digitalPinToInterrupt(CC1101_GDO0)); + + Serial.println("Capture stopped"); +} + +// ===== DEBUG PRINT ===== +void printCapture() { + Serial.println("Captured pulses:"); + + for (int i = 0; i < pulseIndex; i++) { + Serial.println(captureBuffer[i]); + } +} + +// ================= REPLAY ================= +void replaySignal() { + Serial.println(); + Serial.println("Replaying signal..."); + + stopCapture(); + + ELECHOUSE_cc1101.SetTx(); + + pinMode(CC1101_GDO0, OUTPUT); + + for (int i = 0; i < pulseIndex; i++) { + digitalWrite(CC1101_GDO0, (i % 2 == 0) ? HIGH : LOW); + + delayMicroseconds(captureBuffer[i]); + } + + digitalWrite(CC1101_GDO0, LOW); + + ELECHOUSE_cc1101.SetRx(); + + pinMode(CC1101_GDO0, INPUT); + + Serial.println("Replay complete"); +} + +void captureAndDisplay() { + if (!cc1101Inited) { + if (!initCC1101()) { + u8g2.clearBuffer(); + u8g2.setFont(u8g2_font_6x10_tr); + u8g2.drawStr(0, 20, "CC1101 Failed"); + u8g2.sendBuffer(); + return; + } + } + + startCapture(); + + u8g2.clearBuffer(); + u8g2.setFont(u8g2_font_6x10_tr); + u8g2.drawStr(0, 12, "CC1101 Capture"); + u8g2.drawStr(0, 28, "Waiting RF..."); + u8g2.drawStr(0, 60, "BACK = Exit"); + u8g2.sendBuffer(); + + unsigned long lastSignal = millis(); + int lastPulseCount = 0; + + while (true) { + // signal detected + if (pulseIndex > lastPulseCount) { + lastPulseCount = pulseIndex; + lastSignal = millis(); + } + + // update OLED + u8g2.clearBuffer(); + u8g2.setFont(u8g2_font_6x10_tr); + + u8g2.drawStr(0, 12, "CC1101 Capture"); + + u8g2.setCursor(0, 28); + u8g2.print("Pulses: "); + u8g2.print(pulseIndex); + + u8g2.setCursor(0, 42); + u8g2.print("Freq: "); + u8g2.print(currentFreq); + u8g2.print(" MHz"); + + if (pulseIndex > 0) { + u8g2.drawStr(0, 54, "Signal Detected"); + } else { + u8g2.drawStr(0, 54, "Waiting..."); + } + + u8g2.sendBuffer(); + + // auto print once capture stabilizes + if (pulseIndex > 20 && (millis() - lastSignal > 1500)) { + stopCapture(); + + Serial.println(); + Serial.println("===== RF CAPTURE ====="); + + for (int i = 0; i < pulseIndex; i++) { + Serial.print(captureBuffer[i]); + Serial.print(", "); + } + + Serial.println(); + + u8g2.clearBuffer(); + u8g2.setFont(u8g2_font_6x10_tr); + u8g2.drawStr(0, 15, "Capture Complete"); + + u8g2.setCursor(0, 35); + } + } +} + +void handleMenu() { + if (!isCC1101Ready()) { + if (!initCC1101()) { + u8g2.clearBuffer(); + u8g2.setFont(u8g2_font_6x10_tr); + u8g2.drawStr(0, 20, "CC1101 Failed"); + u8g2.sendBuffer(); + delay(1500); + return; + } + } + + pulseIndex = 0; + + startCapture(); + + // ===== CAPTURE FOR 5 SEC ===== + unsigned long start = millis(); + + while (millis() - start < 5000) { + noInterrupts(); + int count = pulseIndex; + interrupts(); + + u8g2.clearBuffer(); + u8g2.setFont(u8g2_font_6x10_tr); + + u8g2.drawStr(0, 12, "RF Capturing..."); + + u8g2.setCursor(0, 30); + u8g2.print("Pulses: "); + u8g2.print(count); + + u8g2.sendBuffer(); + + delay(50); + } + + stopCapture(); + + // ===== DISPLAY CAPTURE BUFFER ===== + int scroll = 0; + + while (1) { + noInterrupts(); + int count = pulseIndex; + interrupts(); + + u8g2.clearBuffer(); + u8g2.setFont(u8g2_font_5x8_tr); + + u8g2.drawStr(0, 8, "Captured Buffer"); + + // display 6 lines + for (int i = 0; i < 6; i++) { + int idx = scroll + i; + + if (idx >= count) + break; + + noInterrupts(); + unsigned long val = captureBuffer[idx]; + interrupts(); + + char buf[32]; + + snprintf(buf, sizeof(buf), "%03d: %lu", idx, val); + + u8g2.drawStr(0, 20 + (i * 8), buf); + } + + u8g2.sendBuffer(); + + // scroll down + if (btnDown()) { + if (scroll < count - 1) + scroll++; + + delay(120); + } + + // scroll up + if (btnUp()) { + if (scroll > 0) + scroll--; + + delay(120); + } + + // replay + if (btnSelect()) { + replaySignal(); + delay(300); + } + + // exit + if (btnBack()) { + delay(150); + return; + } + + delay(20); + } +} diff --git a/src-arduino/rf/cc1101.h b/src-arduino/rf/cc1101.h new file mode 100644 index 0000000..def6a2e --- /dev/null +++ b/src-arduino/rf/cc1101.h @@ -0,0 +1,12 @@ +#pragma once + +bool initCC1101(); +bool isCC1101Ready(); + +void captureAndDisplay(); + +void handleMenu(); +void startCapture(); +void stopCapture(); +void printCapture(); +void replaySignal(); diff --git a/src-arduino/rf/nrf24.cpp b/src-arduino/rf/nrf24.cpp new file mode 100644 index 0000000..0b0ed90 --- /dev/null +++ b/src-arduino/rf/nrf24.cpp @@ -0,0 +1,217 @@ +#include "nrf24.h" +#include "ui/display.h" +#include "utils/buttons.h" +#include <Arduino.h> +#include <RF24.h> +#define JAM_DURATION 500 + +extern SPIClass *RADIO_SPI; +extern RF24 radio1; +extern RF24 radio2; + +// ============ CHANNELS ============= +const byte bleChannels[] = {2, 26, 80}; +const byte bluetoothChannels[] = {32, 34, 46, 48, 50, 52, 0, 1, 2, 4, 6, + 8, 22, 24, 26, 28, 30, 74, 76, 78, 80}; +const byte wifiChannels[] = {12, 17, 22, 27, 32, 37, 42, + 47, 52, 57, 62, 67, 72}; +const byte usbWireless_channels[] = {40, 50, 60}; +const byte videoTransmitter_channels[] = {70, 75, 80}; +const byte zigbee_channels[] = {11, 15, 20, 25}; +const byte rc_channels[] = {1, 3, 5, 7}; + +void initNRF(RF24 &radio) { + if (!radio.begin(RADIO_SPI)) { + Serial.println("NRF not found"); + return; + } + + radio.setAutoAck(false); + radio.stopListening(); + radio.setRetries(0, 0); + radio.setPALevel(RF24_PA_MAX, true); + radio.setDataRate(RF24_2MBPS); + radio.openWritingPipe(0xE7E7E7E7E7LL); + radio.setCRCLength(RF24_CRC_DISABLED); + Serial.println("NRF Initialized"); +} + +// void startBleJammer() { +// initNRF(radio1); +// initNRF(radio2); +// +// Serial.println("NRF JAMMER STARTED"); +// +// const char payload[] = "xxxxxxxxxxxxxxxx"; +// +// u8g2.clearBuffer(); +// u8g2.drawStr(0, 10, "Jamming:"); +// u8g2.setCursor(60, 10); +// u8g2.print("Bluetooth"); +// u8g2.sendBuffer(); +// +// while(true) { +// +// // Channels (you can change this set) +// const byte channels[] = {2, 26, 80}; +// +// +// for (int i = 0; i < sizeof(channels); i++) { +// radio1.setChannel(channels[i]); +// radio1.write(&payload, sizeof(payload)); +// //radio2.setChannel(channels[i]); +// //radio2.write(&payload, sizeof(payload)); +// } +// +// if (btnBack()) +// { +// Serial.println("Jammer stopped"); +// return; +// } +// } +// +// } +// +// void startBluetoothJammer() +//{ +// initNRF(radio1); +// initNRF(radio2); +// +// Serial.println("NRF JAMMER STARTED"); +// +// const char payload[] = "xxxxxxxxxxxxxxxx"; +// +// u8g2.clearBuffer(); +// u8g2.drawStr(0, 10, "Jamming:"); +// u8g2.setCursor(60, 10); +// u8g2.print("Bluetooth"); +// u8g2.sendBuffer(); +// +// while(true) { +// +// // Channels (you can change this set) +// const byte channels[] = {32, 34, 46, 48, 50, 52, 0, 1, 2, 4, 6, 8, 22, +// 24, 26, 28, 30, 74, 76, 78, 80}; +// +// +// for (int i = 0; i < sizeof(channels); i++) { +// radio1.setChannel(channels[i]); +// radio1.write(&payload, sizeof(payload)); +// //radio2.setChannel(channels[i]); +// //radio2.write(&payload, sizeof(payload)); +// } +// +// if (btnBack()) +// { +// Serial.println("Jammer stopped"); +// return; +// } +// } +// } + +void startJammer(const char *name, const byte *channels, size_t channelCount) { + initNRF(radio1); + initNRF(radio2); + + Serial.println("NRF JAMMER STARTED"); + + const char payload[] = "xxxxxxxxxxxxxxxx"; + + u8g2.clearBuffer(); + u8g2.setFont(u8g2_font_6x10_tr); + u8g2.drawStr(0, 15, "NRF24 Jammer"); + u8g2.drawStr(0, 35, name); + u8g2.drawStr(0, 55, "BACK = Exit"); + u8g2.sendBuffer(); + + while (true) { + for (size_t i = 0; i < channelCount; i++) { + // radio1.setChannel(channels[i]); + // radio1.write(&payload, sizeof(payload)); + + // Optional second NRF + // radio2.setChannel(channels[i]); + // radio2.write(&payload, sizeof(payload)); + + radio1.setChannel(channels[i]); + radio2.setChannel(channels[(i + 1) % channelCount]); + + radio1.writeFast(&payload, sizeof(payload)); + radio2.writeFast(&payload, sizeof(payload)); + } + + if (btnBack()) { + Serial.println("Jammer stopped"); + radio1.powerDown(); + radio2.powerDown(); + return; + } + } + + // while (true) { + // for (size_t i = 0; i < channelCount; i++) + //{ + // radio1.setChannel(channels[i]); + // radio2.setChannel(channels[(i + 1) % channelCount]); + + // radio1.writeFast(&payload, sizeof(payload)); + // radio2.writeFast(&payload, sizeof(payload)); + + // radio1.txStandBy(1); + // radio2.txStandBy(1); + + // delayMicroseconds(200); + //} + + // if (btnBack()) + //{ + // Serial.println("Jammer stopped"); + + // radio1.powerDown(); + // radio2.powerDown(); + + // return; + //} + //} +} + +void NRFToolsMenu(int index) { + switch (index) { + case 0: + // startBleJammer(); + // BLE + startJammer("BLE", bleChannels, + sizeof(bleChannels) / sizeof(bleChannels[0])); + + break; + case 1: + // startBluetoothJammer(); + // Bluetooth + startJammer("Bluetooth", bluetoothChannels, + sizeof(bluetoothChannels) / sizeof(bluetoothChannels[0])); + break; + + case 2: + startJammer("WiFi", wifiChannels, + sizeof(wifiChannels) / sizeof(wifiChannels[0])); + break; + case 3: + startJammer("USB Wireless", usbWireless_channels, + sizeof(usbWireless_channels) / + sizeof(usbWireless_channels[0])); + break; + case 4: + startJammer("Video TX", videoTransmitter_channels, + sizeof(videoTransmitter_channels) / + sizeof(videoTransmitter_channels[0])); + break; + case 5: + break; + startJammer("RC", rc_channels, + sizeof(rc_channels) / sizeof(rc_channels[0])); + break; + case 6: + + break; + } +} diff --git a/src-arduino/rf/nrf24.h b/src-arduino/rf/nrf24.h new file mode 100644 index 0000000..6d7f7d8 --- /dev/null +++ b/src-arduino/rf/nrf24.h @@ -0,0 +1,13 @@ +#pragma once + +#include <RF24.h> + +// Initialization +void initNRF(RF24 &radio); + +void startBluetoothJammer(); +void startBleJammer(); + +void startJammer(const char *name, const byte *channels, size_t channelCount); + +void NRFToolsMenu(int index); |
