Full Code of cifertech/RF-Clown for AI

main 7866869ca73b cached
10 files
44.3 KB
17.7k tokens
14 symbols
1 requests
Download .txt
Repository: cifertech/RF-Clown
Branch: main
Commit: 7866869ca73b
Files: 10
Total size: 44.3 KB

Directory structure:
gitextract_ubnffn7d/

├── LICENSE
├── PCB/
│   ├── Pick Place for RfClownV2-pcb.csv
│   └── RfClownV2-BOM.xlsx
├── Previous Versions/
│   └── RF-Clown/
│       └── RF-Clown.ino
├── README.md
└── RfClown/
    ├── RfClown.ino
    ├── config.h
    ├── neopixel.cpp
    ├── setting.cpp
    └── setting.h

================================================
FILE CONTENTS
================================================

================================================
FILE: LICENSE
================================================
MIT License

Copyright (c) 2022 CiferTech

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.


================================================
FILE: PCB/Pick Place for RfClownV2-pcb.csv
================================================
Altium Designer Pick and Place Locations
C:\Users\Public\Documents\Altium\Projects\RfClownV2\Project Outputs for RfClownV2\Pick Place for RfClownV2-pcb.csv

========================================================================================================================
File Design Information:

Date:       25/10/25
Time:       20:36
Revision:   Not in VersionControl
Variant:    No variations
Units used: mm

"Designator","Comment","Layer","Footprint","Center-X(mm)","Center-Y(mm)","Rotation","Description"
"U?4","SW-SMD_L6.0-W6.0-P6.00-LS6.6","TopLayer","SW-SMD_L6.0-W6.0-P6.00-LS6.6","107.8230","73.6600","180",""
"U?3","SW-SMD_L6.0-W6.0-P6.00-LS6.6","TopLayer","SW-SMD_L6.0-W6.0-P6.00-LS6.6","118.3560","73.6600","180",""
"U?2","SW-SMD_L6.0-W6.0-P6.00-LS6.6","TopLayer","SW-SMD_L6.0-W6.0-P6.00-LS6.6","128.5240","73.6600","180",""
"R13","1k","TopLayer","RES_0805_(2012X06L)","96.3930","87.8210","90","RESISTOR"
"J5","SMA","BottomLayer","SAMTEC_SMA-J-P-H-ST-EM1","82.4340","110.6440","0","SMA Connector Jack, Female Socket 50Ohm Board Edge, End Launch Solder"
"J4","SMA","BottomLayer","SAMTEC_SMA-J-P-H-ST-EM1","105.8866","110.6440","0","SMA Connector Jack, Female Socket 50Ohm Board Edge, End Launch Solder"
"J3","SMA","BottomLayer","SAMTEC_SMA-J-P-H-ST-EM1","129.3393","110.6440","0","SMA Connector Jack, Female Socket 50Ohm Board Edge, End Launch Solder"
"J2","SMA","BottomLayer","SAMTEC_SMA-J-P-H-ST-EM1","152.7920","110.6440","0","SMA Connector Jack, Female Socket 50Ohm Board Edge, End Launch Solder"
"D1","LED RGB WS2812","TopLayer","LED_5050_WS2812B","100.0760","87.8840","90","LED"
"ANT4","ANT U.FL","BottomLayer","U.FL_SMD","82.4322","106.0069","360","Antenna"
"ANT3","ANT U.FL","BottomLayer","U.FL_SMD","105.8848","106.0069","360","Antenna"
"ANT2","ANT U.FL","BottomLayer","U.FL_SMD","129.3375","106.0069","360","Antenna"
"ANT1","ANT U.FL","BottomLayer","U.FL_SMD","152.7902","106.0069","360","Antenna"
"U8","NRF24L01","TopLayer","NRF24L01_GT24MINI_MS","148.5420","63.9780","360","2.4GHz Transceiver MODULE, SMD"
"U7","NRF24L01","TopLayer","NRF24L01_GT24MINI_MS","148.5420","80.8690","360","2.4GHz Transceiver MODULE, SMD"
"U6","NRF24L01","TopLayer","NRF24L01_GT24MINI_MS","148.5420","97.7600","360","2.4GHz Transceiver MODULE, SMD"
"C21","Capacitor Tantalum SMD","TopLayer","Tan_1206_(3216X18L)_Size_A","144.1450","94.6898","90","Capacitor Tantalum SMD"
"C20","Capacitor Tantalum SMD","TopLayer","Tan_1206_(3216X18L)_Size_A","144.1450","77.7988","90","Capacitor Tantalum SMD"
"C19","Capacitor Tantalum SMD","TopLayer","Tan_1206_(3216X18L)_Size_A","144.1450","60.9078","90","Capacitor Tantalum SMD"
"U4","LF33","BottomLayer","D-PACK","139.8500","82.5750","180","3.3V VOLTAGE REGULATOR"
"SW1","SlideSwitch","BottomLayer","SWSLIDT_SPDT_MSS3","69.3610","60.4520","270","SWITCH, SLIDE, SPDT, SMD"
"STD","LED","TopLayer","L0805","102.1560","52.0090","90","LED"
"R12","1k","BottomLayer","RES_0805","86.0450","73.0250","270","RESISTOR"
"R11","1k","BottomLayer","RES_0805","98.8670","75.3110","90","RESISTOR"
"R10","1k","BottomLayer","RES_0805","98.8670","73.0250","90","RESISTOR"
"IC1","TP4056","BottomLayer","SOP-8","92.4530","74.2850","0","Complete single cell Li-Ion battery with a constant current / constant voltage linear charger"
"CHG","LED","TopLayer","L0805","104.5690","52.0090","90","LED"
"C12","100nf","BottomLayer","CAP0805","92.4560","77.9780","0","Capacitor"
"C11","10uf","BottomLayer","CAP_1206_(3216X15L)","136.2400","76.4540","0","Capacitor"
"C10","10uf","BottomLayer","CAP_1206_(3216X15L)","143.4599","76.4540","180","Capacitor"
"C9","Capacitor Tantalum SMD","BottomLayer","Tan_1206_(3216X18L)_Size_A","136.1652","73.6600","0","Capacitor Tantalum SMD"
"C8","Capacitor Tantalum SMD","BottomLayer","Tan_1206_(3216X18L)_Size_A","143.5347","73.6600","180","Capacitor Tantalum SMD"
"C7","100nf","BottomLayer","CAP0805","86.0450","75.3110","0","Capacitor"
"BT1","1042","BottomLayer","BAT_1042","117.9830","59.4360","180",""
"U5","OLED_0.96IN_WHITE","TopLayer","OLED_0.96IN_WHITE_SSD1306","118.2060","84.9630","360","OLED, 0.96", Monochrome white, SSD1306"
"R15","390k","TopLayer","RES_0805_(2012X06L)","121.7043","89.8194","90","RESISTOR"
"R14","10k","TopLayer","RES_0805_(2012X06L)","116.8400","89.4710","90","RESISTOR"
"C23","1uf","TopLayer","CAP0805","107.3150","89.5960","90","Capacitor"
"C22","2.2uf","TopLayer","CAP0805","114.5963","89.5960","90","Capacitor"
"C18","1uf","TopLayer","CAP0805","109.7421","89.5960","90","Capacitor"
"C17","2.2uf","TopLayer","CAP0805","124.3048","89.5960","90","Capacitor"
"C16","100nf","TopLayer","CAP0805","126.7319","89.5960","270","Capacitor"
"C15","100nf","TopLayer","CAP0805","112.1692","89.5960","90","Capacitor"
"C14","10uf","TopLayer","CAP0805","129.1590","89.5960","270","Capacitor"
"C13","10uf","TopLayer","CAP0805","119.4506","89.5960","270","Capacitor"
"U2","CP2102","TopLayer","QFN28G_0.5-5X5MM","117.3560","63.1690","90","USB Bridge, USB to UART USB 2.0 UART Interface 28-QFN _5x5_"
"R8","5.1k","TopLayer","RES_0805","123.9520","53.9090","0","RESISTOR"
"R7","5.1k","TopLayer","RES_0805","110.8710","53.9090","0","RESISTOR"
"R5","12k","TopLayer","RES_0805","104.3940","62.7240","180","RESISTOR"
"R4","12k","TopLayer","RES_0805","102.3620","62.7190","360","RESISTOR"
"R2","470","TopLayer","RES_0805","110.4900","63.6190","180","RESISTOR"
"Q2","S8050","TopLayer","SOT-23","103.3780","58.4670","180","Bipolar (BJT) Transistor NPN 25 V 500 mA 150MHz 300 mW Surface Mount SOT-23"
"Q1","S8050","TopLayer","SOT-23","103.3780","67.1030","360","Bipolar (BJT) Transistor NPN 25 V 500 mA 150MHz 300 mW Surface Mount SOT-23"
"J1","TYPE-C-31-M-12","TopLayer","HRO_TYPE-C-31-M-12","117.6020","54.0640","360","USB Connectors 24 Receptacle 1 8.94*7.3mm RoHS"
"C5","100nf","TopLayer","CAP0805","125.5560","59.6290","90","Capacitor"
"C4","10uf","TopLayer","CAP0805","127.5880","59.6340","90","Capacitor"
"C3","100nf","TopLayer","CAP0805","125.5560","63.5290","270","Capacitor"
"C2","10uf","TopLayer","CAP0805","127.5880","63.5290","270","Capacitor"
"U1","ESP32-WROOM-32U","TopLayer","XCVR_ESP32-WROOM-32U","78.1190","87.3490","90","Bluetooth, WiFi 802.11b/g/n, Bluetooth v4.2 +EDR, Class 1, 2 and 3 Transceiver Module 2.4GHz ~ 2.5GHz Antenna Not Included, U.FL Surface Mount"
"R1","4.7k","BottomLayer","RES_0805","74.4220","70.5100","180","RESISTOR"
"R3","4.7k","BottomLayer","RES_0805","74.4820","104.0740","180","RESISTOR"
"C6","100nf","BottomLayer","CAP0805","76.9620","70.5100","270","Capacitor"
"C1","100nf","BottomLayer","CAP0805","76.8650","104.0740","90","Capacitor"
"B2","BUTTON","BottomLayer","PUSH_BUTTON_SMD","69.8000","102.5850","180","PUSH BUTTON"
"B1","BUTTON","BottomLayer","PUSH_BUTTON_SMD","69.7800","71.6600","180","PUSH BUTTON"


================================================
FILE: Previous Versions/RF-Clown/RF-Clown.ino
================================================
#include "RF24.h"
#include <SPI.h>
#include <ezButton.h>
#include <Adafruit_NeoPixel.h>
#include "esp_bt.h"
#include "esp_wifi.h"

constexpr int BUTTON_PIN = 34;
constexpr int NEOPIXEL_PIN = 4;
constexpr int NUM_PIXELS = 1;
constexpr int SPI_SPEED = 16000000;

SPIClass *spiVSPI = nullptr;
SPIClass *spiHSPI = nullptr;
RF24 radioVSPI(15, 5, SPI_SPEED);
RF24 radioHSPI(22, 21, SPI_SPEED);

Adafruit_NeoPixel pixels(NUM_PIXELS, NEOPIXEL_PIN, NEO_GRB + NEO_KHZ800);

int bluetooth_channels[] = {32, 34, 46, 48, 50, 52, 0, 1, 2, 4, 6, 8, 22, 24, 26, 28, 30, 74, 76, 78, 80};
int ble_channels[] = {2, 26, 80};

int currentMode = 0;

ezButton modeButton(BUTTON_PIN);

void configureRadio(RF24 &radio, int channel, SPIClass *spi);
void handleModeChange();
void executeMode();
void updateNeoPixel();
void jamBLE();
void jamBluetooth();
void jamAll();

void setup() {
    Serial.begin(115200);
    
    esp_bt_controller_deinit();
    esp_wifi_stop();
    esp_wifi_deinit();
    esp_wifi_disconnect();
    
    modeButton.setDebounceTime(100);
    pixels.begin();
    pixels.clear();
    pixels.show();
    
    spiVSPI = new SPIClass(VSPI);
    spiVSPI->begin();
    configureRadio(radioVSPI, ble_channels[0], spiVSPI);
    
    spiHSPI = new SPIClass(HSPI);
    spiHSPI->begin();
    configureRadio(radioHSPI, bluetooth_channels[0], spiHSPI);
}

void configureRadio(RF24 &radio, int channel, SPIClass *spi) {
    if (radio.begin(spi)) {
        radio.setAutoAck(false);
        radio.stopListening();
        radio.setRetries(0, 0);
        radio.setPALevel(RF24_PA_MAX, true);
        radio.setDataRate(RF24_2MBPS);
        radio.setCRCLength(RF24_CRC_DISABLED);
        radio.startConstCarrier(RF24_PA_HIGH, channel);
    }
}

void loop() {

    modeButton.loop();
    if (modeButton.isPressed()) {
        handleModeChange();
    }
    executeMode();
}

void handleModeChange() {
    currentMode = (currentMode + 1) % 4;
    Serial.print("Mode changed to: ");
    Serial.println(currentMode);
    updateNeoPixel();
}

void updateNeoPixel() {
    switch (currentMode) {
        case 0:
            pixels.clear();
            pixels.show();
            break;
        case 1:
            pixels.setPixelColor(0, pixels.Color(0, 0, 25));
            pixels.show();
            break;
        case 2:
            pixels.setPixelColor(0, pixels.Color(0, 25, 0));
            pixels.show();
            break;
        case 3:
            pixels.setPixelColor(0, pixels.Color(25, 0, 0));
            pixels.show();
            break;
    }
}

void executeMode() {
    switch (currentMode) {
        case 0:
            //radioVSPI.powerDown();
            //radioHSPI.powerDown();
            delay(100);
            break;
        case 1:
            jamBLE();
            break;
        case 2:
            jamBluetooth();
            break;
        case 3:
            jamAll();
            break;
    }
}

void jamBLE() {
    int randomIndex = random(0, sizeof(ble_channels) / sizeof(ble_channels[0]));
    int channel = ble_channels[randomIndex];
    radioVSPI.setChannel(channel);
    radioHSPI.setChannel(channel);
}

void jamBluetooth() {
    int randomIndex = random(0, sizeof(bluetooth_channels) / sizeof(bluetooth_channels[0]));
    int channel = bluetooth_channels[randomIndex];
    radioVSPI.setChannel(channel);
    radioHSPI.setChannel(channel);
}

void jamAll() {
    if (random(0, 2)) {
        jamBluetooth();        
    } else {
        jamBLE();
    }
    //delayMicroseconds(20);
}


================================================
FILE: README.md
================================================
<div align="center">

  <img src="https://user-images.githubusercontent.com/62047147/195847997-97553030-3b79-4643-9f2c-1f04bba6b989.png" alt="logo" width="100" height="auto" />
  
  <h1> RF-Clown </h1>
  <p> A fully open-source BLE and Bluetooth jammer </p>


<!-- Badges -->
<a href="https://github.com/cifertech/nrfbox" title="Go to GitHub repo"><img src="https://img.shields.io/static/v1?label=cifertech&message=RF-Clown&color=purple&logo=github" alt="cifertech - RF-Clown"></a>
<a href="https://github.com/cifertech/nrfbox"><img src="https://img.shields.io/github/stars/cifertech/RF-Clown?style=social" alt="stars - RF-Clown"></a>
<a href="https://github.com/cifertech/nrfbox"><img src="https://img.shields.io/github/forks/cifertech/RF-Clown?style=social" alt="forks - RF-Clown"></a>

   
<h4>
    <a href="https://twitter.com/techcifer">TWITTER</a>
  <span> · </span>
    <a href="https://www.instagram.com/cifertech/">INSTAGRAM</a>
  <span> · </span>
    <a href="https://www.youtube.com/@techcifer">YOUTUBE</a>
  <span> · </span>
    <a href="https://cifertech.net/">WEBSITE</a>
  </h4>
</div>
<br/>

## 📖 Explore the Full Documentation

Ready to dive deeper into RF-Clown's details? Discover the full story, in-depth tutorials, and all the exciting features in our comprehensive [documentation](https://cifertech.net/rf-clown-your-portable-ble-bluetooth-jamming-tool/). Click the link and explore further!
  
<div>&nbsp;</div>

<!-- About the Project -->
## :star2: About the Project
RF-Clown is an open-source BLE and Bluetooth jammer inspired by similar projects in the community. Unlike many closed-source implementations, RF-Clown emphasizes transparency and education. The project is meant for testing and learning about RF technologies and communication protocols.  

**Why RF-Clown?**  
1. Promote open-source collaboration in RF research.  
2. Encourage exploration of RF vulnerabilities.   

<div align="center"> 
  <img src="https://github.com/user-attachments/assets/7be8e9b4-07ea-4f39-9cd4-d8588a95a920" alt="screenshot" width="Auto" height="Auto" />
</div>

<div>&nbsp;</div>

<!-- Features -->
### 🎯 Features

- **Triple NRF24** (GT24 Mini modules) for increased coverage and performance  
- **External antenna** setup: 4× IPEX cables + 8 dBi antennas  
- **OLED display** + **3 tactile switches** for simple on-device navigation  
- **NeoPixel Feedback**: LED indicates the current mode (BLE, Bluetooth, or combined).  
- **Portable Design**: Powered by a lithium battery with a TP4056 charger for convenience.  
- **Custom PCB**: Includes an onboard CP2102 for programming, LF33 voltage regulator, and other essential components.  
- **Open-Source Code**: Freely available for exploration and modification.  

<div>&nbsp;</div>

## :eyes: RF-Clown Versions:

<table>
  <tr>
    <td style="text-align: center;">
      <img src="https://github.com/user-attachments/assets/64df30e1-52b5-4cfb-91c8-b530d30b85e5" alt="RF-Clown v1" style="width: 600px; border: 1px solid #ccc; border-radius: 5px;">
      <p style="font-style: italic; font-size: 14px; margin-top: 5px;">RF-Clown v1</p>
    </td>    
    <td style="text-align: center;">
      <img src="https://github.com/user-attachments/assets/92f980b4-5c40-438e-ad00-413e6b39dc6d" alt="RF-Clown v2" style="width: 700px; border: 1px solid #ccc; border-radius: 5px;">
      <p style="font-style: italic; font-size: 14px; margin-top: 5px;">RF-Clown v2</p>
    </td>
  </tr>
</table>

<div>&nbsp;</div>

## 🔗 Uploading the Firmware (.bin) to ESP32

If you prefer not to upload the code manually or encounter errors during compilation, you can directly upload the precompiled `.bin` file to the ESP32. Follow these steps:

### Step 1: Download the Required Tools
1. **ESP32 Flash Download Tool**: Download the tool from Espressif's official site: [ESP32 Flash Download Tool](https://www.espressif.com/sites/default/files/tools/flash_download_tool_3.9.7_2.zip).
2. **USB Drivers**: Make sure the drivers for the ESP32 are installed on your system. You can download the drivers from [CP210x USB to UART Bridge VCP Drivers](https://www.silabs.com/developers/usb-to-uart-bridge-vcp-drivers) if you're using the CP2102 chip.

### Step 2: Prepare the `.bin` File
1. Download the precompiled `.bin` file from the repository. 

### Step 3: Upload the `.bin` File to ESP32
1. Connect your ESP32 to your computer using a USB cable.
2. Open the **ESP32 Flash Download Tool** and configure the following:
   - Select the appropriate **chip type** (ESP32) and click **OK**.
   - In the **Download Path Config** section, add the `.bin` file and set the start address to `0x1000`.
   - Select the correct **COM port** where your ESP32 is connected.
   - Choose the correct **Baud rate** (115200 is generally recommended).

3. Click on **Start** to begin uploading the `.bin` file to your ESP32.

### Step 4: Verify the Upload
Once the upload is completed, the tool will confirm a successful flash. You can now restart your ESP32 and run the firmware.

&nbsp;
### Arduino IDE Settings:
If you want to upload the sketch code to the ESP32, use the following settings in the Tools menu:
- Built using ESP32 Board Version 1.0.5


<div>&nbsp;</div>

<!-- License -->
## :warning: License

Distributed under the MIT License. See LICENSE.txt for more information.

<div>&nbsp;</div>

<!-- Contact -->
## :handshake: Contact

▶ Support me on Patreon [patreon.com/cifertech](https://www.patreon.com/cifertech)

CiferTech - [@twitter](https://twitter.com/techcifer) - CiferTech@gmali.com

Project Link: [https://github.com/cifertech/RF-Clown](https://github.com/cifertech/RF-Clown)

<div>&nbsp;</div>



================================================
FILE: RfClown/RfClown.ino
================================================
/* ____________________________
   This software is licensed under the MIT License:
   https://github.com/cifertech/rfclown
   ________________________________________ */
   
#include "setting.h"
#include "config.h"

void IRAM_ATTR handleButton() {
  unsigned long currentTime = millis();
  if (currentTime - lastPressTime > debounceDelay) {
    ChangeRequested = true;
    lastPressTime = currentTime;
  }
}

void IRAM_ATTR handleButton1() {
  unsigned long currentTime = millis();
  if (currentTime - lastPressTime > debounceDelay) {
    ChangeRequested1 = true;
    lastPressTime = currentTime;
  }
}

void IRAM_ATTR handleButton2() {
  unsigned long currentTime = millis();
  if (currentTime - lastPressTime > debounceDelay) {
    if (current == DEACTIVE_MODE) current = ACTIVE_MODE;
    else                          current = DEACTIVE_MODE;
    lastPressTime = currentTime;
  }
}

void configure_Radio(RF24 &radio, const byte *channels, size_t size) {
  configureNrf(radio);
  radio.printPrettyDetails();
  for (size_t i = 0; i < size; i++) {
    radio.setChannel(channels[i]);
    radio.startConstCarrier(RF24_PA_MAX, channels[i]);
  }
}

void initialize_MultiMode() {
  if (RadioA.begin()) {
    configure_Radio(RadioA, channelGroup_1, sizeof(channelGroup_1));
  }
  if (RadioB.begin()) {
    configure_Radio(RadioB, channelGroup_2, sizeof(channelGroup_2));
  }
  if (RadioC.begin()) {
    configure_Radio(RadioC, channelGroup_3, sizeof(channelGroup_3));
  }
}

void initialize_Radios() {
  if (current == ACTIVE_MODE) {
    initialize_MultiMode();
  } else if (current == DEACTIVE_MODE) {
    RadioA.powerDown();
    RadioB.powerDown();
    RadioC.powerDown();
    delay(100);
  }
}

static const uint8_t HEADER_H = 12;
static const uint8_t PAD      = 6;
static const uint8_t CARD_H   = 36;
static const uint8_t RADIUS   = 3;
static const uint8_t DOT_Y    = 64 - 6;

static const char* kMenuLabels[] = {
  "WiFi", "Video TX", "RC", "BLE", "Bluetooth", "USB Wireless", "Zigbee", "NRF24"
};
static const int kMenuCount = sizeof(kMenuLabels)/sizeof(kMenuLabels[0]);

static int menuIndexFromMode(OperationMode m) {
  switch (m) {
    case WiFi_MODULE:         return 0;
    case VIDEO_TX_MODULE:     return 1;
    case RC_MODULE:           return 2;
    case BLE_MODULE:          return 3;
    case Bluetooth_MODULE:    return 4;
    case USB_WIRELESS_MODULE: return 5;
    case ZIGBEE_MODULE:       return 6;
    case NRF24_MODULE:        return 7;
    default: return 0;
  }
}
static OperationMode modeFromMenuIndex(int idx) {
  switch (idx) {
    case 0: return WiFi_MODULE;
    case 1: return VIDEO_TX_MODULE;
    case 2: return RC_MODULE;
    case 3: return BLE_MODULE;
    case 4: return Bluetooth_MODULE;
    case 5: return USB_WIRELESS_MODULE;
    case 6: return ZIGBEE_MODULE;
    case 7: return NRF24_MODULE;
    default: return WiFi_MODULE;
  }
}

void spectrum() {
  const uint8_t HDR_H = 10;
  const int TOP = HDR_H + 12;
  const int BOT = SCREEN_H - 2;
  const int H   = BOT - TOP;
  const int STRIDE = 3;
  const int BINS   = SCREEN_W / STRIDE;
  const int BAR_W  = 1;
  static uint8_t h[BINS];
  static int8_t  v[BINS];
  static bool init = false;
  if (!init) {
    for (int i = 0; i < BINS; ++i) {
      h[i] = random(0, H + 1);
      v[i] = random(-2, 3);
    }
    init = true;
  }
  for (int i = 0; i < BINS; ++i) {
    int8_t a = (int8_t)random(-1, 2);
    v[i] += a;
    if (v[i] > 3) v[i] = 3;
    if (v[i] < -3) v[i] = -3;
    int16_t nh = (int16_t)h[i] + v[i];
    if (nh < 0) {
      nh = 0;
      v[i] = -(v[i] * 3) / 4;
      if (v[i] == 0) v[i] = 1;
    } else if (nh > H) {
      nh = H;
      v[i] = -(v[i] * 3) / 4;
      if (v[i] == 0) v[i] = -1;
    }
    h[i] = (uint8_t)nh;
  }
  for (int i = 0; i < BINS; ++i) {
    int x  = i * STRIDE;
    int bh = h[i];
    if (bh <= 0) continue;
    int y  = BOT - bh;
    u8g2.drawVLine(x, y, bh);
  }
  u8g2.sendBuffer();
}

static void drawHeaderBar() {
  const uint8_t W = 128;
  const uint8_t H = HEADER_H;
  const uint8_t TXT_Y = 2;
  u8g2.setDrawColor(1);
  u8g2.drawBox(0, 0, W, H);
  u8g2.setFont(FONT_SMALL);
  u8g2.setDrawColor(0);
  u8g2.drawStr(PAD, TXT_Y, "RF-Clown");
  const char* ver = "v2.0.0";
  int vw = u8g2.getStrWidth(ver);
  u8g2.drawStr(W - vw - 4, TXT_Y, ver);
  u8g2.setDrawColor(1);
  u8g2.drawHLine(0, H - 1, W);
}

static void drawPillOutline(int x,int y,int w,int h){
  if (h & 1) h--; if (y & 1) y--;
  u8g2.drawRFrame(x, y, w, h, h/2);
}
static void drawPillKnob(int x,int y,int w,int h,float pos){
  if (h & 1) h--; if (y & 1) y--;
  int r=h/2, cxL=x+r, cxR=x+w-r-1, cy=y+r;
  int cx=(int)lroundf(cxL + (cxR - cxL)*pos);
  int knob = max(2, r-3);
  u8g2.drawDisc(cx, cy, knob);
}
static void drawPillToggle(int x,int y,int w,int h,bool on){
  drawPillOutline(x,y,w,h);
  drawPillKnob(x,y,w,h, on?0.0f:1.0f);
}

static void drawPaginationDots(int active){
  int totalW = (kMenuCount * 6) - 2;
  int startX = (128 - totalW) / 2;
  for (int i=0;i<kMenuCount;i++) {
    int x = startX + i*6;
    if (i == active) u8g2.drawDisc(x, DOT_Y, 2);
    else             u8g2.drawCircle(x, DOT_Y, 2);
  }
}

static void drawCardAtCenter(int centerX, int menuIndex){
  const char* label = kMenuLabels[menuIndex];
  const int W = 128;
  const int w = W - PAD*2;
  const int x = centerX - w/2;
  const int y = HEADER_H + 4;
  u8g2.setDrawColor(0);
  u8g2.drawBox(x+1, y+1, w-2, CARD_H-2);
  u8g2.setDrawColor(1);
  u8g2.drawRFrame(x, y, w, CARD_H, RADIUS);
  u8g2.setFont(FONT_MEDIUM);
  u8g2.setCursor(x + 12, y + 4);
  u8g2.print(label);
  bool isThisFocus = (modeFromMenuIndex(menuIndex) == current_Mode);
  bool isActive    = (isThisFocus && current == ACTIVE_MODE);
  const char* status = isActive ? "ACTIVE" : "DEACTIVE";
  u8g2.setFont(FONT_SMALL);
  u8g2.setCursor(x + 12, y + 16);
  u8g2.print(status);
  bool isOn = (modeFromMenuIndex(menuIndex) == current_Mode) && (current == ACTIVE_MODE);
  const int pillW=24, pillH=14;
  const int pillY=(y + ((CARD_H-pillH)/2)) & ~1;
  drawPillToggle(x + w - pillW - 10, pillY, pillW, pillH, isOn);
}

static void renderStaticMenu(int focusIndex) {
  u8g2.clearBuffer();
  drawHeaderBar();
  drawCardAtCenter(128 / 2, focusIndex);
  drawPaginationDots(focusIndex);
  u8g2.sendBuffer();
}

static void animateToMenu(int fromIdx, int toIdx) {
  const int W = 128;
  const int STEPS = 14;
  const uint8_t DT = 10;
  const int dir = (toIdx > fromIdx) ? -1 : 1;
  for (int s = 0; s <= STEPS; s++) {
    float t = (float)s / (float)STEPS;
    float e = (t < 0.5f) ? 4.0f*t*t*t : 1.0f - powf(-2.0f*t + 2.0f, 3)/2.0f;
    int shift = (int)(e * W + 0.5f);
    int centerFrom = (W/2) + (-dir * shift);
    int centerTo   = (W/2) + ( dir * (W - shift));
    u8g2.clearBuffer();
    drawHeaderBar();
    drawCardAtCenter(centerFrom, fromIdx);
    drawCardAtCenter(centerTo,   toIdx);
    drawPaginationDots(toIdx);
    u8g2.sendBuffer();
    delay(DT);
  }
  renderStaticMenu(toIdx);
}

static void animateToggleKnobForFocus(int focusIdx, bool fromActive, bool toActive){
  float start = (fromActive ? 0.0f : 1.0f);
  float end   = (toActive   ? 0.0f : 1.0f);
  const int STEPS = 10;
  const uint8_t FRAME_MS = 12;
  for (int s=0; s<=STEPS; s++){
    float t = (float)s / (float)STEPS;
    float e = (t < 0.5f) ? 2.0f*t*t : 1.0f - powf(-2.0f*t + 2.0f, 2)/2.0f;
    float p = start + (end - start) * e;
    u8g2.clearBuffer();
    drawHeaderBar();
    const int W = 128;
    const int w = W - PAD*2;
    const int x = W/2 - w/2;
    const int y = HEADER_H + 4;
    u8g2.setDrawColor(0);
    u8g2.drawBox(x+1, y+1, w-2, CARD_H-2);
    u8g2.setDrawColor(1);
    u8g2.drawRFrame(x, y, w, CARD_H, RADIUS);
    u8g2.setFont(FONT_MEDIUM); u8g2.setCursor(x+12, y+4);  u8g2.print(kMenuLabels[focusIdx]);
    u8g2.setFont(FONT_SMALL);  u8g2.setCursor(x+12, y+16); u8g2.print("----");
    const int pillW=24, pillH=14;
    const int pillY=(y + ((CARD_H-pillH)/2)) & ~1;
    const int pillX=x + w - pillW - 10;
    drawPillOutline(pillX, pillY, pillW, pillH);
    drawPillKnob(pillX, pillY, pillW, pillH, p);
    drawPaginationDots(focusIdx);
    u8g2.sendBuffer();
    delay(FRAME_MS);
  }
  renderStaticMenu(focusIdx);
}

void update_OLED() {
  int focus = menuIndexFromMode(current_Mode);
  renderStaticMenu(focus);
}

void menuPrev() {
  int fromIdx = menuIndexFromMode(current_Mode);
  int toIdx   = (fromIdx == 0) ? (kMenuCount - 1) : (fromIdx - 1);
  current_Mode = modeFromMenuIndex(toIdx);
  animateToMenu(fromIdx, toIdx);
}
void menuNext() {
  int fromIdx = menuIndexFromMode(current_Mode);
  int toIdx   = (fromIdx == (kMenuCount - 1)) ? 0 : (fromIdx + 1);
  current_Mode = modeFromMenuIndex(toIdx);
  animateToMenu(fromIdx, toIdx);
}
void menuToggleActive() {
  int focus = menuIndexFromMode(current_Mode);
  bool wasActive = (current == ACTIVE_MODE);
  current = wasActive ? DEACTIVE_MODE : ACTIVE_MODE;
  animateToggleKnobForFocus(focus, wasActive, !wasActive);
}

void checkMode() {
  if (ChangeRequested) {
    ChangeRequested = false;
    current_Mode = static_cast<OperationMode>((current_Mode == 0) ? 7 : (current_Mode - 1));
  } else if (ChangeRequested1) {
    ChangeRequested1 = false;
    current_Mode = static_cast<OperationMode>((current_Mode + 1) % 8);
  }
}

void setup() {
  Serial.begin(115200);
  initialize_MultiMode();
  Wire.begin();
  Wire.setClock(400000);
  u8g2.begin();
  u8g2.setBusClock(400000);
  u8g2.setFont(FONT_SMALL);
  u8g2.setDrawColor(1);
  u8g2.setFontPosTop();
  esp_bt_controller_deinit();
  esp_wifi_stop();
  esp_wifi_deinit();
  esp_wifi_disconnect();
  pinMode(PIN_BTN_L,  INPUT_PULLUP);
  pinMode(PIN_BTN_R, INPUT_PULLUP);
  pinMode(PIN_BTN_S, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(PIN_BTN_L),  handleButton,  FALLING);
  attachInterrupt(digitalPinToInterrupt(PIN_BTN_R), handleButton1, FALLING);
  attachInterrupt(digitalPinToInterrupt(PIN_BTN_S), handleButton2, FALLING);
  initialize_Radios();
  conf();
  update_OLED();
}

void loop() {
  checkMode();
  static Operation     lastActivity = current;
  static OperationMode lastFocus    = current_Mode;
  if (current_Mode != lastFocus) {
    int fromIdx = menuIndexFromMode(lastFocus);
    int toIdx   = menuIndexFromMode(current_Mode);
    animateToMenu(fromIdx, toIdx);
    lastFocus = current_Mode;
    return;
  }
  if (current != lastActivity) {
    initialize_Radios();
    int  focus     = menuIndexFromMode(current_Mode);
    bool wasActive = (lastActivity == ACTIVE_MODE);
    bool nowActive = (current      == ACTIVE_MODE);
    animateToggleKnobForFocus(focus, wasActive, nowActive);
    lastActivity = current;
    return;
  }
    if (current_Mode == BLE_MODULE) {
      int randomIndex = random(0, sizeof(ble_channels) / sizeof(ble_channels[0]));
      byte channel = ble_channels[randomIndex];
      RadioA.setChannel(channel);
      RadioB.setChannel(channel);
      RadioC.setChannel(channel);
    } else if (current_Mode == Bluetooth_MODULE) {
      int randomIndex = random(0, sizeof(bluetooth_channels) / sizeof(bluetooth_channels[0]));
      byte channel = bluetooth_channels[randomIndex];
      RadioA.setChannel(channel);
      RadioB.setChannel(channel);
      RadioC.setChannel(channel);
    } else if (current_Mode == WiFi_MODULE) {
      int randomIndex = random(0, sizeof(WiFi_channels) / sizeof(WiFi_channels[0]));
      byte channel = WiFi_channels[randomIndex];
      RadioA.setChannel(channel);
      RadioB.setChannel(channel);
      RadioC.setChannel(channel);
    } else if (current_Mode == USB_WIRELESS_MODULE) {
      int randomIndex = random(0, sizeof(usbWireless_channels) / sizeof(usbWireless_channels[0]));
      byte channel = usbWireless_channels[randomIndex];
      RadioA.setChannel(channel);
      RadioB.setChannel(channel);
      RadioC.setChannel(channel);
    } else if (current_Mode == VIDEO_TX_MODULE) {
      int randomIndex = random(0, sizeof(videoTransmitter_channels) / sizeof(videoTransmitter_channels[0]));
      byte channel = videoTransmitter_channels[randomIndex];
      RadioA.setChannel(channel);
      RadioB.setChannel(channel);
      RadioC.setChannel(channel);
    } else if (current_Mode == RC_MODULE) {
      int randomIndex = random(0, sizeof(rc_channels) / sizeof(rc_channels[0]));
      byte channel = rc_channels[randomIndex];
      RadioA.setChannel(channel);
      RadioB.setChannel(channel);
      RadioC.setChannel(channel);
    } else if (current_Mode == ZIGBEE_MODULE) {
      int randomIndex = random(0, sizeof(zigbee_channels) / sizeof(zigbee_channels[0]));
      byte channel = zigbee_channels[randomIndex];
      RadioA.setChannel(channel);
      RadioB.setChannel(channel);
      RadioC.setChannel(channel);
    } else if (current_Mode == NRF24_MODULE) {
      int randomIndex = random(0, sizeof(nrf24_channels) / sizeof(nrf24_channels[0]));
      byte channel = nrf24_channels[randomIndex];
      RadioA.setChannel(channel);
      RadioB.setChannel(channel);
      RadioC.setChannel(channel);
    }
}


================================================
FILE: RfClown/config.h
================================================
/* ____________________________
   This software is licensed under the MIT License:
   https://github.com/cifertech/rfclown
   ________________________________________ */

#ifndef CONFIG_H
#define CONFIG_H

#define SCREEN_W 128
#define SCREEN_H 64

// ---------------- Pins ----------------
#define PIN_BTN_L  27
#define PIN_BTN_R  25
#define PIN_BTN_S  26

// nRF24-specific Pins
#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    15  
#define NRF_CSN_PIN_C   2  

// Common dependencies
#include "setting.h"
#include <Arduino.h>
#include <U8g2lib.h>
#include <Wire.h>
#include <SPI.h>
#include <Adafruit_NeoPixel.h>
#include <EEPROM.h>
#include <Preferences.h>
#include <vector>
#include <string>
#include <math.h>

U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE);

Adafruit_NeoPixel pixels(1, 14, NEO_GRB + NEO_KHZ800);

// BLE-specific dependencies
#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEServer.h>

// nRF24-specific dependencies
#include <nRF24L01.h>
#include <RF24.h>

// WiFi-specific dependencies
#include <WiFi.h>
#include <esp_wifi.h>
#include <esp_wifi_types.h>
#include <esp_system.h>
#include <esp_event.h>
#include <nvs_flash.h>
#include <string>

// ESP-specific configurations
#include <esp_bt.h>
#include <esp_wifi.h>

// External declarations
extern U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2;
extern Adafruit_NeoPixel pixels;

static const uint8_t* FONT_SMALL  = u8g2_font_5x8_tf;
static const uint8_t* FONT_MEDIUM = u8g2_font_6x12_tf;
static const uint8_t* FONT_ICON_FALLBACK = u8g2_font_open_iconic_thing_2x_t;

enum OperationMode {WiFi_MODULE, VIDEO_TX_MODULE, RC_MODULE, BLE_MODULE, Bluetooth_MODULE, USB_WIRELESS_MODULE, ZIGBEE_MODULE, NRF24_MODULE};
OperationMode current_Mode = WiFi_MODULE;

enum Operation {DEACTIVE_MODE, ACTIVE_MODE};
volatile Operation current = DEACTIVE_MODE;

byte channelGroup_1[] = {2, 5, 8, 11};
byte channelGroup_2[] = {26, 29, 32, 35};
byte channelGroup_3[] = {80, 83, 86, 89};

const byte bluetooth_channels[] =        {32, 34, 46, 48, 50, 52, 0, 1, 2, 4, 6, 8, 22, 24, 26, 28, 30, 74, 76, 78, 80};
const byte ble_channels[]       =        {2, 26, 80};
const byte WiFi_channels[]      =        {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
const byte usbWireless_channels[] =      {40, 50, 60};
const byte videoTransmitter_channels[] = {70, 75, 80};
const byte rc_channels[]        =        {1, 3, 5, 7};
const byte zigbee_channels[]    =        {11, 15, 20, 25};
const byte nrf24_channels[]     =        {76, 78, 79};

volatile bool ChangeRequested  = false;
volatile bool ChangeRequested1 = false;
volatile bool ChangeRequested2 = false;

unsigned long lastPressTime = 0;
const unsigned long debounceDelay = 200;

#endif // CONFIG_H


================================================
FILE: RfClown/neopixel.cpp
================================================
/* ____________________________
   This software is licensed under the MIT License:
   https://github.com/cifertech/rfclown
   ________________________________________ */
   
#include "setting.h"
#include "config.h"

extern Adafruit_NeoPixel pixels;

void neopixelSetup() {
  EEPROM.begin(512); 
  neoPixelActive = EEPROM.read(0);
  
 if (neoPixelActive) {
  pixels.begin();
  pixels.clear();
  //pixels.show();
  }
}

void neopixelLoop();

void setNeoPixelColour(const std::string& colour) {
  uint32_t colorValue = 0; 

  if (colour == "red") {
    colorValue = pixels.Color(5, 0, 0);
  } else if (colour == "green") {
    colorValue = pixels.Color(0, 5, 0);
  } else if (colour == "blue") {
    colorValue = pixels.Color(0, 0, 5);
  } else if (colour == "yellow") {
    colorValue = pixels.Color(5, 5, 0);
  } else if (colour == "purple") {
    colorValue = pixels.Color(5, 0, 5);
  } else if (colour == "cyan") {
    colorValue = pixels.Color(0, 5, 5);
  } else if (colour == "white") {
    colorValue = pixels.Color(5, 5, 5);
  } else if (colour == "null") {
    colorValue = pixels.Color(0, 0, 0);
  }

  pixels.setPixelColor(0, colorValue);
  pixels.show();
}

void flash(int numberOfFlashes, const std::vector<std::string>& colors, const std::string& finalColour) {
  if (numberOfFlashes <= 0 || colors.empty()) {
    Serial.println("Invalid parameters for flash: Check numberOfFlashes or colors vector.");
    return;
  }

  for (int i = 0; i < numberOfFlashes; ++i) {
    for (const auto& color : colors) {
      setNeoPixelColour(color);
      delay(500);
    }
  }
  setNeoPixelColour(finalColour);
}


================================================
FILE: RfClown/setting.cpp
================================================
/* ____________________________
   This software is licensed under the MIT License:
   https://github.com/cifertech/rfclown
   ________________________________________ */

#include "setting.h"
#include "config.h"

RF24 RadioA(NRF_CE_PIN_A, NRF_CSN_PIN_A);
RF24 RadioB(NRF_CE_PIN_B, NRF_CSN_PIN_B);
RF24 RadioC(NRF_CE_PIN_C, NRF_CSN_PIN_C);

void setRadiosNeutralState() {
  RadioA.stopListening();
  RadioA.setAutoAck(false);
  RadioA.setRetries(0, 0);
  RadioA.powerDown(); 
  digitalWrite(NRF_CE_PIN_A, LOW); 

  RadioB.stopListening();
  RadioB.setAutoAck(false);
  RadioB.setRetries(0, 0);
  RadioB.powerDown(); 
  digitalWrite(NRF_CE_PIN_B, LOW); 

  RadioC.stopListening();
  RadioC.setAutoAck(false);
  RadioC.setRetries(0, 0);
  RadioC.powerDown(); 
  digitalWrite(NRF_CE_PIN_C, LOW); 
}

void configureNrf(RF24 &radio) {
  radio.begin();
  radio.setAutoAck(false);
  radio.stopListening();
  radio.setRetries(0, 0);
  radio.setPALevel(RF24_PA_MAX, true);
  radio.setDataRate(RF24_2MBPS);
  radio.setCRCLength(RF24_CRC_DISABLED);
}

void setupRadioA() {
  configureNrf(RadioA);
}

void setupRadioB() {
  configureNrf(RadioB);
}

void setupRadioC() {
  configureNrf(RadioC);
}

void initAllRadios() {
  setupRadioA();
  setupRadioB();
  setupRadioC();
}

void Str(uint8_t x, uint8_t y, const uint8_t* asciiArray, size_t len) {
  char buf[64]; 
  for (size_t i = 0; i < len && i < sizeof(buf) - 1; i++) {
    buf[i] = (char)asciiArray[i];
  }
  buf[len] = '\0';

  u8g2.drawStr(x, y, buf);
}

void CenteredStr(uint8_t screenWidth, uint8_t y, const uint8_t* asciiArray, size_t len, const uint8_t* font) {
  char buf[64];
  for (size_t i = 0; i < len && i < sizeof(buf) - 1; i++) {
    buf[i] = (char)asciiArray[i];
  }
  buf[len] = '\0';

  u8g2.setFont((const uint8_t*)font);
  int16_t w = u8g2.getUTF8Width(buf);
  u8g2.setCursor((screenWidth - w) / 2, y);
  u8g2.print(buf);
}

void conf() {
  u8g2.setBitmapMode(1);
  u8g2.clearBuffer();
  CenteredStr(128, 15, txt_n, sizeof(txt_n), u8g2_font_ncenB14_tr);
  CenteredStr(120, 35, txt_c, sizeof(txt_c), u8g2_font_ncenB08_tr);
  CenteredStr(128, 50, txt_v, sizeof(txt_v), u8g2_font_6x10_tf);
  u8g2.sendBuffer();
  delay(3000);
  u8g2.clearBuffer();
  u8g2.drawXBMP(0, 0, 128, 64, cred); 
  u8g2.sendBuffer();
  delay(250);
}

 


================================================
FILE: RfClown/setting.h
================================================
/* ____________________________
   This software is licensed under the MIT License:
   https://github.com/cifertech/rfclown
   ________________________________________ */
   
#ifndef setting_H
#define setting_H

#include <BLEDevice.h>
#include <U8g2lib.h>
#include <Adafruit_NeoPixel.h>
#include <EEPROM.h>
#include <RF24.h>
#include <vector>
#include <string>
#include <SPI.h>

void neopixelSetup();
void neopixelLoop();

void setNeoPixelColour(const std::string& colour);
void flash(int numberOfFlashes, const std::vector<std::string>& colors, const std::string& finalColour);

extern U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2;
extern Adafruit_NeoPixel pixels;

//extern bool neoPixelActive;

bool neoPixelActive = false;
uint8_t oledBrightness = 100;

extern RF24 RadioA;
extern RF24 RadioB;
extern RF24 RadioC;

void configureNrf(RF24 &radio);

void setRadiosNeutralState();

void setupRadioA();
void setupRadioB();
void setupRadioC();

void initAllRadios();

void Str(uint8_t x, uint8_t y, const uint8_t* asciiArray, size_t len);
void CenteredStr(uint8_t screenWidth, uint8_t y, const uint8_t* asciiArray, size_t len, const uint8_t* font);
void conf();

const uint8_t txt_n[]   = {82, 102, 67, 108, 111, 119, 110};                  
const uint8_t txt_c[]   = {98, 121, 32, 67, 105, 102, 101, 114, 84, 101, 99, 104}; 
const uint8_t txt_v[]   = {118, 50, 46, 48, 46, 48}; 

const unsigned char cred [] PROGMEM = {
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x3f, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x07, 0xf0, 0x83, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x6f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x78, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x0c, 0x7f, 0xfe, 0x01, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0xfe, 0x03, 0xc0, 0x7f, 0xfe, 0x07, 0x80, 0xff, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0xf8, 0x07, 0xe0, 0x7f, 0xfe, 0x1f, 0xc0, 0x3f, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0xf8, 0x7f, 0xfe, 0x3f, 0xe0, 0x07, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0xc0, 0x0f, 0xfc, 0x7f, 0xfe, 0x7f, 0xe0, 0x03, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0xc0, 0x1f, 0xfe, 0x7f, 0xfe, 0xff, 0xf0, 0x03, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0xc0, 0x80, 0x7f, 0xff, 0x7f, 0xfe, 0xff, 0xf9, 0x03, 0x02, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0xc0, 0xc1, 0x3f, 0xff, 0x7f, 0xfe, 0xff, 0xfb, 0x87, 0x03, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0xc0, 0xe7, 0xbf, 0xff, 0x7f, 0xfe, 0xff, 0xf3, 0xff, 0x03, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x80, 0xff, 0xdf, 0xff, 0x7f, 0xfe, 0xff, 0xf7, 0xff, 0x03, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0xff, 0xdf, 0xff, 0x7f, 0xfe, 0xff, 0xe7, 0xff, 0x01, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0xff, 0xcf, 0xff, 0x7f, 0xfe, 0xff, 0xef, 0xff, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0xfc, 0xef, 0xff, 0x7f, 0xfe, 0xff, 0xcf, 0x3f, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0xec, 0xff, 0x7f, 0xfe, 0xff, 0x5f, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0x7f, 0xfe, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0x7f, 0xfe, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0x7f, 0xfe, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0x7f, 0xfe, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0x7f, 0x1e, 0xf0, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0x7f, 0x0e, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0x7f, 0x06, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0x7f, 0x06, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0x7f, 0x06, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0x7f, 0x0e, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0x7f, 0x0e, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0xec, 0x3f, 0x7f, 0x1e, 0x00, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x60, 0xee, 0x0f, 0x7e, 0x1e, 0x00, 0xee, 0x39, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0xfc, 0xef, 0xe7, 0x7c, 0x3e, 0x00, 0xef, 0xff, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0xfe, 0xcf, 0xf7, 0x79, 0x7e, 0x80, 0xef, 0xff, 0x01, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0xff, 0xdf, 0xf7, 0x7b, 0xfe, 0xc0, 0xe7, 0xff, 0x03, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x80, 0xff, 0x9f, 0xe7, 0x77, 0xfe, 0xf3, 0xf7, 0xff, 0x03, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x80, 0xcf, 0xbf, 0xe7, 0x6f, 0x8e, 0xff, 0xf3, 0xc7, 0x03, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x80, 0x83, 0x3f, 0xcf, 0x4f, 0x06, 0xff, 0xfb, 0x03, 0x03, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x80, 0x00, 0x3f, 0x9e, 0x1f, 0x72, 0xfe, 0xf0, 0x03, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xb0, 0x3f, 0xf8, 0x3c, 0xe0, 0x03, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x80, 0x0f, 0x60, 0x7f, 0xfe, 0x0d, 0xe0, 0x07, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0xe0, 0x0f, 0xc0, 0xfe, 0xff, 0x0c, 0xc0, 0x1f, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0xf0, 0x07, 0xc0, 0xfd, 0x7f, 0x06, 0x80, 0x7f, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0xfc, 0x03, 0x80, 0xfb, 0x3f, 0x07, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x80, 0xf3, 0x9f, 0x03, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf3, 0x9f, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x3f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x7f, 0xfc, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f, 0xf8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};

#endif
Download .txt
gitextract_ubnffn7d/

├── LICENSE
├── PCB/
│   ├── Pick Place for RfClownV2-pcb.csv
│   └── RfClownV2-BOM.xlsx
├── Previous Versions/
│   └── RF-Clown/
│       └── RF-Clown.ino
├── README.md
└── RfClown/
    ├── RfClown.ino
    ├── config.h
    ├── neopixel.cpp
    ├── setting.cpp
    └── setting.h
Download .txt
SYMBOL INDEX (14 symbols across 3 files)

FILE: RfClown/config.h
  type OperationMode (line 72) | enum OperationMode {WiFi_MODULE, VIDEO_TX_MODULE, RC_MODULE, BLE_MODULE,...
  type Operation (line 75) | enum Operation {DEACTIVE_MODE, ACTIVE_MODE}

FILE: RfClown/neopixel.cpp
  function neopixelSetup (line 11) | void neopixelSetup() {
  function setNeoPixelColour (line 24) | void setNeoPixelColour(const std::string& colour) {
  function flash (line 49) | void flash(int numberOfFlashes, const std::vector<std::string>& colors, ...

FILE: RfClown/setting.cpp
  function setRadiosNeutralState (line 13) | void setRadiosNeutralState() {
  function configureNrf (line 33) | void configureNrf(RF24 &radio) {
  function setupRadioA (line 43) | void setupRadioA() {
  function setupRadioB (line 47) | void setupRadioB() {
  function setupRadioC (line 51) | void setupRadioC() {
  function initAllRadios (line 55) | void initAllRadios() {
  function Str (line 61) | void Str(uint8_t x, uint8_t y, const uint8_t* asciiArray, size_t len) {
  function CenteredStr (line 71) | void CenteredStr(uint8_t screenWidth, uint8_t y, const uint8_t* asciiArr...
  function conf (line 84) | void conf() {
Condensed preview — 10 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (49K chars).
[
  {
    "path": "LICENSE",
    "chars": 1066,
    "preview": "MIT License\n\nCopyright (c) 2022 CiferTech\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\n"
  },
  {
    "path": "PCB/Pick Place for RfClownV2-pcb.csv",
    "chars": 6787,
    "preview": "Altium Designer Pick and Place Locations\r\nC:\\Users\\Public\\Documents\\Altium\\Projects\\RfClownV2\\Project Outputs for RfClow"
  },
  {
    "path": "Previous Versions/RF-Clown/RF-Clown.ino",
    "chars": 3640,
    "preview": "#include \"RF24.h\"\r\n#include <SPI.h>\r\n#include <ezButton.h>\r\n#include <Adafruit_NeoPixel.h>\r\n#include \"esp_bt.h\"\r\n#includ"
  },
  {
    "path": "README.md",
    "chars": 5642,
    "preview": "<div align=\"center\">\n\n  <img src=\"https://user-images.githubusercontent.com/62047147/195847997-97553030-3b79-4643-9f2c-1"
  },
  {
    "path": "RfClown/RfClown.ino",
    "chars": 13341,
    "preview": "/* ____________________________\r\n   This software is licensed under the MIT License:\r\n   https://github.com/cifertech/rf"
  },
  {
    "path": "RfClown/config.h",
    "chars": 2915,
    "preview": "/* ____________________________\r\n   This software is licensed under the MIT License:\r\n   https://github.com/cifertech/rf"
  },
  {
    "path": "RfClown/neopixel.cpp",
    "chars": 1675,
    "preview": "/* ____________________________\r\n   This software is licensed under the MIT License:\r\n   https://github.com/cifertech/rf"
  },
  {
    "path": "RfClown/setting.cpp",
    "chars": 2383,
    "preview": "/* ____________________________\r\n   This software is licensed under the MIT License:\r\n   https://github.com/cifertech/rf"
  },
  {
    "path": "RfClown/setting.h",
    "chars": 7882,
    "preview": "/* ____________________________\r\n   This software is licensed under the MIT License:\r\n   https://github.com/cifertech/rf"
  }
]

// ... and 1 more files (download for full content)

About this extraction

This page contains the full source code of the cifertech/RF-Clown GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 10 files (44.3 KB), approximately 17.7k tokens, and a symbol index with 14 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!