[
  {
    "path": "LICENSE",
    "content": "MIT License\n\nCopyright (c) 2022 CiferTech\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "PCB/Pick Place for RfClownV2-pcb.csv",
    "content": "Altium Designer Pick and Place Locations\r\nC:\\Users\\Public\\Documents\\Altium\\Projects\\RfClownV2\\Project Outputs for RfClownV2\\Pick Place for RfClownV2-pcb.csv\r\n\r\n========================================================================================================================\r\nFile Design Information:\r\n\r\nDate:       25/10/25\r\nTime:       20:36\r\nRevision:   Not in VersionControl\r\nVariant:    No variations\r\nUnits used: mm\r\n\r\n\"Designator\",\"Comment\",\"Layer\",\"Footprint\",\"Center-X(mm)\",\"Center-Y(mm)\",\"Rotation\",\"Description\"\r\n\"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\",\"\"\r\n\"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\",\"\"\r\n\"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\",\"\"\r\n\"R13\",\"1k\",\"TopLayer\",\"RES_0805_(2012X06L)\",\"96.3930\",\"87.8210\",\"90\",\"RESISTOR\"\r\n\"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\"\r\n\"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\"\r\n\"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\"\r\n\"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\"\r\n\"D1\",\"LED RGB WS2812\",\"TopLayer\",\"LED_5050_WS2812B\",\"100.0760\",\"87.8840\",\"90\",\"LED\"\r\n\"ANT4\",\"ANT U.FL\",\"BottomLayer\",\"U.FL_SMD\",\"82.4322\",\"106.0069\",\"360\",\"Antenna\"\r\n\"ANT3\",\"ANT U.FL\",\"BottomLayer\",\"U.FL_SMD\",\"105.8848\",\"106.0069\",\"360\",\"Antenna\"\r\n\"ANT2\",\"ANT U.FL\",\"BottomLayer\",\"U.FL_SMD\",\"129.3375\",\"106.0069\",\"360\",\"Antenna\"\r\n\"ANT1\",\"ANT U.FL\",\"BottomLayer\",\"U.FL_SMD\",\"152.7902\",\"106.0069\",\"360\",\"Antenna\"\r\n\"U8\",\"NRF24L01\",\"TopLayer\",\"NRF24L01_GT24MINI_MS\",\"148.5420\",\"63.9780\",\"360\",\"2.4GHz Transceiver MODULE, SMD\"\r\n\"U7\",\"NRF24L01\",\"TopLayer\",\"NRF24L01_GT24MINI_MS\",\"148.5420\",\"80.8690\",\"360\",\"2.4GHz Transceiver MODULE, SMD\"\r\n\"U6\",\"NRF24L01\",\"TopLayer\",\"NRF24L01_GT24MINI_MS\",\"148.5420\",\"97.7600\",\"360\",\"2.4GHz Transceiver MODULE, SMD\"\r\n\"C21\",\"Capacitor Tantalum SMD\",\"TopLayer\",\"Tan_1206_(3216X18L)_Size_A\",\"144.1450\",\"94.6898\",\"90\",\"Capacitor Tantalum SMD\"\r\n\"C20\",\"Capacitor Tantalum SMD\",\"TopLayer\",\"Tan_1206_(3216X18L)_Size_A\",\"144.1450\",\"77.7988\",\"90\",\"Capacitor Tantalum SMD\"\r\n\"C19\",\"Capacitor Tantalum SMD\",\"TopLayer\",\"Tan_1206_(3216X18L)_Size_A\",\"144.1450\",\"60.9078\",\"90\",\"Capacitor Tantalum SMD\"\r\n\"U4\",\"LF33\",\"BottomLayer\",\"D-PACK\",\"139.8500\",\"82.5750\",\"180\",\"3.3V VOLTAGE REGULATOR\"\r\n\"SW1\",\"SlideSwitch\",\"BottomLayer\",\"SWSLIDT_SPDT_MSS3\",\"69.3610\",\"60.4520\",\"270\",\"SWITCH, SLIDE, SPDT, SMD\"\r\n\"STD\",\"LED\",\"TopLayer\",\"L0805\",\"102.1560\",\"52.0090\",\"90\",\"LED\"\r\n\"R12\",\"1k\",\"BottomLayer\",\"RES_0805\",\"86.0450\",\"73.0250\",\"270\",\"RESISTOR\"\r\n\"R11\",\"1k\",\"BottomLayer\",\"RES_0805\",\"98.8670\",\"75.3110\",\"90\",\"RESISTOR\"\r\n\"R10\",\"1k\",\"BottomLayer\",\"RES_0805\",\"98.8670\",\"73.0250\",\"90\",\"RESISTOR\"\r\n\"IC1\",\"TP4056\",\"BottomLayer\",\"SOP-8\",\"92.4530\",\"74.2850\",\"0\",\"Complete single cell Li-Ion battery with a constant current / constant voltage linear charger\"\r\n\"CHG\",\"LED\",\"TopLayer\",\"L0805\",\"104.5690\",\"52.0090\",\"90\",\"LED\"\r\n\"C12\",\"100nf\",\"BottomLayer\",\"CAP0805\",\"92.4560\",\"77.9780\",\"0\",\"Capacitor\"\r\n\"C11\",\"10uf\",\"BottomLayer\",\"CAP_1206_(3216X15L)\",\"136.2400\",\"76.4540\",\"0\",\"Capacitor\"\r\n\"C10\",\"10uf\",\"BottomLayer\",\"CAP_1206_(3216X15L)\",\"143.4599\",\"76.4540\",\"180\",\"Capacitor\"\r\n\"C9\",\"Capacitor Tantalum SMD\",\"BottomLayer\",\"Tan_1206_(3216X18L)_Size_A\",\"136.1652\",\"73.6600\",\"0\",\"Capacitor Tantalum SMD\"\r\n\"C8\",\"Capacitor Tantalum SMD\",\"BottomLayer\",\"Tan_1206_(3216X18L)_Size_A\",\"143.5347\",\"73.6600\",\"180\",\"Capacitor Tantalum SMD\"\r\n\"C7\",\"100nf\",\"BottomLayer\",\"CAP0805\",\"86.0450\",\"75.3110\",\"0\",\"Capacitor\"\r\n\"BT1\",\"1042\",\"BottomLayer\",\"BAT_1042\",\"117.9830\",\"59.4360\",\"180\",\"\"\r\n\"U5\",\"OLED_0.96IN_WHITE\",\"TopLayer\",\"OLED_0.96IN_WHITE_SSD1306\",\"118.2060\",\"84.9630\",\"360\",\"OLED, 0.96\", Monochrome white, SSD1306\"\r\n\"R15\",\"390k\",\"TopLayer\",\"RES_0805_(2012X06L)\",\"121.7043\",\"89.8194\",\"90\",\"RESISTOR\"\r\n\"R14\",\"10k\",\"TopLayer\",\"RES_0805_(2012X06L)\",\"116.8400\",\"89.4710\",\"90\",\"RESISTOR\"\r\n\"C23\",\"1uf\",\"TopLayer\",\"CAP0805\",\"107.3150\",\"89.5960\",\"90\",\"Capacitor\"\r\n\"C22\",\"2.2uf\",\"TopLayer\",\"CAP0805\",\"114.5963\",\"89.5960\",\"90\",\"Capacitor\"\r\n\"C18\",\"1uf\",\"TopLayer\",\"CAP0805\",\"109.7421\",\"89.5960\",\"90\",\"Capacitor\"\r\n\"C17\",\"2.2uf\",\"TopLayer\",\"CAP0805\",\"124.3048\",\"89.5960\",\"90\",\"Capacitor\"\r\n\"C16\",\"100nf\",\"TopLayer\",\"CAP0805\",\"126.7319\",\"89.5960\",\"270\",\"Capacitor\"\r\n\"C15\",\"100nf\",\"TopLayer\",\"CAP0805\",\"112.1692\",\"89.5960\",\"90\",\"Capacitor\"\r\n\"C14\",\"10uf\",\"TopLayer\",\"CAP0805\",\"129.1590\",\"89.5960\",\"270\",\"Capacitor\"\r\n\"C13\",\"10uf\",\"TopLayer\",\"CAP0805\",\"119.4506\",\"89.5960\",\"270\",\"Capacitor\"\r\n\"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_\"\r\n\"R8\",\"5.1k\",\"TopLayer\",\"RES_0805\",\"123.9520\",\"53.9090\",\"0\",\"RESISTOR\"\r\n\"R7\",\"5.1k\",\"TopLayer\",\"RES_0805\",\"110.8710\",\"53.9090\",\"0\",\"RESISTOR\"\r\n\"R5\",\"12k\",\"TopLayer\",\"RES_0805\",\"104.3940\",\"62.7240\",\"180\",\"RESISTOR\"\r\n\"R4\",\"12k\",\"TopLayer\",\"RES_0805\",\"102.3620\",\"62.7190\",\"360\",\"RESISTOR\"\r\n\"R2\",\"470\",\"TopLayer\",\"RES_0805\",\"110.4900\",\"63.6190\",\"180\",\"RESISTOR\"\r\n\"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\"\r\n\"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\"\r\n\"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\"\r\n\"C5\",\"100nf\",\"TopLayer\",\"CAP0805\",\"125.5560\",\"59.6290\",\"90\",\"Capacitor\"\r\n\"C4\",\"10uf\",\"TopLayer\",\"CAP0805\",\"127.5880\",\"59.6340\",\"90\",\"Capacitor\"\r\n\"C3\",\"100nf\",\"TopLayer\",\"CAP0805\",\"125.5560\",\"63.5290\",\"270\",\"Capacitor\"\r\n\"C2\",\"10uf\",\"TopLayer\",\"CAP0805\",\"127.5880\",\"63.5290\",\"270\",\"Capacitor\"\r\n\"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\"\r\n\"R1\",\"4.7k\",\"BottomLayer\",\"RES_0805\",\"74.4220\",\"70.5100\",\"180\",\"RESISTOR\"\r\n\"R3\",\"4.7k\",\"BottomLayer\",\"RES_0805\",\"74.4820\",\"104.0740\",\"180\",\"RESISTOR\"\r\n\"C6\",\"100nf\",\"BottomLayer\",\"CAP0805\",\"76.9620\",\"70.5100\",\"270\",\"Capacitor\"\r\n\"C1\",\"100nf\",\"BottomLayer\",\"CAP0805\",\"76.8650\",\"104.0740\",\"90\",\"Capacitor\"\r\n\"B2\",\"BUTTON\",\"BottomLayer\",\"PUSH_BUTTON_SMD\",\"69.8000\",\"102.5850\",\"180\",\"PUSH BUTTON\"\r\n\"B1\",\"BUTTON\",\"BottomLayer\",\"PUSH_BUTTON_SMD\",\"69.7800\",\"71.6600\",\"180\",\"PUSH BUTTON\"\r\n"
  },
  {
    "path": "Previous Versions/RF-Clown/RF-Clown.ino",
    "content": "#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#include \"esp_wifi.h\"\r\n\r\nconstexpr int BUTTON_PIN = 34;\r\nconstexpr int NEOPIXEL_PIN = 4;\r\nconstexpr int NUM_PIXELS = 1;\r\nconstexpr int SPI_SPEED = 16000000;\r\n\r\nSPIClass *spiVSPI = nullptr;\r\nSPIClass *spiHSPI = nullptr;\r\nRF24 radioVSPI(15, 5, SPI_SPEED);\r\nRF24 radioHSPI(22, 21, SPI_SPEED);\r\n\r\nAdafruit_NeoPixel pixels(NUM_PIXELS, NEOPIXEL_PIN, NEO_GRB + NEO_KHZ800);\r\n\r\nint bluetooth_channels[] = {32, 34, 46, 48, 50, 52, 0, 1, 2, 4, 6, 8, 22, 24, 26, 28, 30, 74, 76, 78, 80};\r\nint ble_channels[] = {2, 26, 80};\r\n\r\nint currentMode = 0;\r\n\r\nezButton modeButton(BUTTON_PIN);\r\n\r\nvoid configureRadio(RF24 &radio, int channel, SPIClass *spi);\r\nvoid handleModeChange();\r\nvoid executeMode();\r\nvoid updateNeoPixel();\r\nvoid jamBLE();\r\nvoid jamBluetooth();\r\nvoid jamAll();\r\n\r\nvoid setup() {\r\n    Serial.begin(115200);\r\n    \r\n    esp_bt_controller_deinit();\r\n    esp_wifi_stop();\r\n    esp_wifi_deinit();\r\n    esp_wifi_disconnect();\r\n    \r\n    modeButton.setDebounceTime(100);\r\n    pixels.begin();\r\n    pixels.clear();\r\n    pixels.show();\r\n    \r\n    spiVSPI = new SPIClass(VSPI);\r\n    spiVSPI->begin();\r\n    configureRadio(radioVSPI, ble_channels[0], spiVSPI);\r\n    \r\n    spiHSPI = new SPIClass(HSPI);\r\n    spiHSPI->begin();\r\n    configureRadio(radioHSPI, bluetooth_channels[0], spiHSPI);\r\n}\r\n\r\nvoid configureRadio(RF24 &radio, int channel, SPIClass *spi) {\r\n    if (radio.begin(spi)) {\r\n        radio.setAutoAck(false);\r\n        radio.stopListening();\r\n        radio.setRetries(0, 0);\r\n        radio.setPALevel(RF24_PA_MAX, true);\r\n        radio.setDataRate(RF24_2MBPS);\r\n        radio.setCRCLength(RF24_CRC_DISABLED);\r\n        radio.startConstCarrier(RF24_PA_HIGH, channel);\r\n    }\r\n}\r\n\r\nvoid loop() {\r\n\r\n    modeButton.loop();\r\n    if (modeButton.isPressed()) {\r\n        handleModeChange();\r\n    }\r\n    executeMode();\r\n}\r\n\r\nvoid handleModeChange() {\r\n    currentMode = (currentMode + 1) % 4;\r\n    Serial.print(\"Mode changed to: \");\r\n    Serial.println(currentMode);\r\n    updateNeoPixel();\r\n}\r\n\r\nvoid updateNeoPixel() {\r\n    switch (currentMode) {\r\n        case 0:\r\n            pixels.clear();\r\n            pixels.show();\r\n            break;\r\n        case 1:\r\n            pixels.setPixelColor(0, pixels.Color(0, 0, 25));\r\n            pixels.show();\r\n            break;\r\n        case 2:\r\n            pixels.setPixelColor(0, pixels.Color(0, 25, 0));\r\n            pixels.show();\r\n            break;\r\n        case 3:\r\n            pixels.setPixelColor(0, pixels.Color(25, 0, 0));\r\n            pixels.show();\r\n            break;\r\n    }\r\n}\r\n\r\nvoid executeMode() {\r\n    switch (currentMode) {\r\n        case 0:\r\n            //radioVSPI.powerDown();\r\n            //radioHSPI.powerDown();\r\n            delay(100);\r\n            break;\r\n        case 1:\r\n            jamBLE();\r\n            break;\r\n        case 2:\r\n            jamBluetooth();\r\n            break;\r\n        case 3:\r\n            jamAll();\r\n            break;\r\n    }\r\n}\r\n\r\nvoid jamBLE() {\r\n    int randomIndex = random(0, sizeof(ble_channels) / sizeof(ble_channels[0]));\r\n    int channel = ble_channels[randomIndex];\r\n    radioVSPI.setChannel(channel);\r\n    radioHSPI.setChannel(channel);\r\n}\r\n\r\nvoid jamBluetooth() {\r\n    int randomIndex = random(0, sizeof(bluetooth_channels) / sizeof(bluetooth_channels[0]));\r\n    int channel = bluetooth_channels[randomIndex];\r\n    radioVSPI.setChannel(channel);\r\n    radioHSPI.setChannel(channel);\r\n}\r\n\r\nvoid jamAll() {\r\n    if (random(0, 2)) {\r\n        jamBluetooth();        \r\n    } else {\r\n        jamBLE();\r\n    }\r\n    //delayMicroseconds(20);\r\n}\r\n"
  },
  {
    "path": "README.md",
    "content": "<div align=\"center\">\n\n  <img src=\"https://user-images.githubusercontent.com/62047147/195847997-97553030-3b79-4643-9f2c-1f04bba6b989.png\" alt=\"logo\" width=\"100\" height=\"auto\" />\n  \n  <h1> RF-Clown </h1>\n  <p> A fully open-source BLE and Bluetooth jammer </p>\n\n\n<!-- Badges -->\n<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>\n<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>\n<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>\n\n   \n<h4>\n    <a href=\"https://twitter.com/techcifer\">TWITTER</a>\n  <span> · </span>\n    <a href=\"https://www.instagram.com/cifertech/\">INSTAGRAM</a>\n  <span> · </span>\n    <a href=\"https://www.youtube.com/@techcifer\">YOUTUBE</a>\n  <span> · </span>\n    <a href=\"https://cifertech.net/\">WEBSITE</a>\n  </h4>\n</div>\n<br/>\n\n## 📖 Explore the Full Documentation\n\nReady 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!\n  \n<div>&nbsp;</div>\n\n<!-- About the Project -->\n## :star2: About the Project\nRF-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.  \n\n**Why RF-Clown?**  \n1. Promote open-source collaboration in RF research.  \n2. Encourage exploration of RF vulnerabilities.   \n\n<div align=\"center\"> \n  <img src=\"https://github.com/user-attachments/assets/7be8e9b4-07ea-4f39-9cd4-d8588a95a920\" alt=\"screenshot\" width=\"Auto\" height=\"Auto\" />\n</div>\n\n<div>&nbsp;</div>\n\n<!-- Features -->\n### 🎯 Features\n\n- **Triple NRF24** (GT24 Mini modules) for increased coverage and performance  \n- **External antenna** setup: 4× IPEX cables + 8 dBi antennas  \n- **OLED display** + **3 tactile switches** for simple on-device navigation  \n- **NeoPixel Feedback**: LED indicates the current mode (BLE, Bluetooth, or combined).  \n- **Portable Design**: Powered by a lithium battery with a TP4056 charger for convenience.  \n- **Custom PCB**: Includes an onboard CP2102 for programming, LF33 voltage regulator, and other essential components.  \n- **Open-Source Code**: Freely available for exploration and modification.  \n\n<div>&nbsp;</div>\n\n## :eyes: RF-Clown Versions:\n\n<table>\n  <tr>\n    <td style=\"text-align: center;\">\n      <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;\">\n      <p style=\"font-style: italic; font-size: 14px; margin-top: 5px;\">RF-Clown v1</p>\n    </td>    \n    <td style=\"text-align: center;\">\n      <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;\">\n      <p style=\"font-style: italic; font-size: 14px; margin-top: 5px;\">RF-Clown v2</p>\n    </td>\n  </tr>\n</table>\n\n<div>&nbsp;</div>\n\n## 🔗 Uploading the Firmware (.bin) to ESP32\n\nIf 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:\n\n### Step 1: Download the Required Tools\n1. **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).\n2. **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.\n\n### Step 2: Prepare the `.bin` File\n1. Download the precompiled `.bin` file from the repository. \n\n### Step 3: Upload the `.bin` File to ESP32\n1. Connect your ESP32 to your computer using a USB cable.\n2. Open the **ESP32 Flash Download Tool** and configure the following:\n   - Select the appropriate **chip type** (ESP32) and click **OK**.\n   - In the **Download Path Config** section, add the `.bin` file and set the start address to `0x1000`.\n   - Select the correct **COM port** where your ESP32 is connected.\n   - Choose the correct **Baud rate** (115200 is generally recommended).\n\n3. Click on **Start** to begin uploading the `.bin` file to your ESP32.\n\n### Step 4: Verify the Upload\nOnce the upload is completed, the tool will confirm a successful flash. You can now restart your ESP32 and run the firmware.\n\n&nbsp;\n### Arduino IDE Settings:\nIf you want to upload the sketch code to the ESP32, use the following settings in the Tools menu:\n- Built using ESP32 Board Version 1.0.5\n\n\n<div>&nbsp;</div>\n\n<!-- License -->\n## :warning: License\n\nDistributed under the MIT License. See LICENSE.txt for more information.\n\n<div>&nbsp;</div>\n\n<!-- Contact -->\n## :handshake: Contact\n\n▶ Support me on Patreon [patreon.com/cifertech](https://www.patreon.com/cifertech)\n\nCiferTech - [@twitter](https://twitter.com/techcifer) - CiferTech@gmali.com\n\nProject Link: [https://github.com/cifertech/RF-Clown](https://github.com/cifertech/RF-Clown)\n\n<div>&nbsp;</div>\n\n"
  },
  {
    "path": "RfClown/RfClown.ino",
    "content": "/* ____________________________\r\n   This software is licensed under the MIT License:\r\n   https://github.com/cifertech/rfclown\r\n   ________________________________________ */\r\n   \r\n#include \"setting.h\"\r\n#include \"config.h\"\r\n\r\nvoid IRAM_ATTR handleButton() {\r\n  unsigned long currentTime = millis();\r\n  if (currentTime - lastPressTime > debounceDelay) {\r\n    ChangeRequested = true;\r\n    lastPressTime = currentTime;\r\n  }\r\n}\r\n\r\nvoid IRAM_ATTR handleButton1() {\r\n  unsigned long currentTime = millis();\r\n  if (currentTime - lastPressTime > debounceDelay) {\r\n    ChangeRequested1 = true;\r\n    lastPressTime = currentTime;\r\n  }\r\n}\r\n\r\nvoid IRAM_ATTR handleButton2() {\r\n  unsigned long currentTime = millis();\r\n  if (currentTime - lastPressTime > debounceDelay) {\r\n    if (current == DEACTIVE_MODE) current = ACTIVE_MODE;\r\n    else                          current = DEACTIVE_MODE;\r\n    lastPressTime = currentTime;\r\n  }\r\n}\r\n\r\nvoid configure_Radio(RF24 &radio, const byte *channels, size_t size) {\r\n  configureNrf(radio);\r\n  radio.printPrettyDetails();\r\n  for (size_t i = 0; i < size; i++) {\r\n    radio.setChannel(channels[i]);\r\n    radio.startConstCarrier(RF24_PA_MAX, channels[i]);\r\n  }\r\n}\r\n\r\nvoid initialize_MultiMode() {\r\n  if (RadioA.begin()) {\r\n    configure_Radio(RadioA, channelGroup_1, sizeof(channelGroup_1));\r\n  }\r\n  if (RadioB.begin()) {\r\n    configure_Radio(RadioB, channelGroup_2, sizeof(channelGroup_2));\r\n  }\r\n  if (RadioC.begin()) {\r\n    configure_Radio(RadioC, channelGroup_3, sizeof(channelGroup_3));\r\n  }\r\n}\r\n\r\nvoid initialize_Radios() {\r\n  if (current == ACTIVE_MODE) {\r\n    initialize_MultiMode();\r\n  } else if (current == DEACTIVE_MODE) {\r\n    RadioA.powerDown();\r\n    RadioB.powerDown();\r\n    RadioC.powerDown();\r\n    delay(100);\r\n  }\r\n}\r\n\r\nstatic const uint8_t HEADER_H = 12;\r\nstatic const uint8_t PAD      = 6;\r\nstatic const uint8_t CARD_H   = 36;\r\nstatic const uint8_t RADIUS   = 3;\r\nstatic const uint8_t DOT_Y    = 64 - 6;\r\n\r\nstatic const char* kMenuLabels[] = {\r\n  \"WiFi\", \"Video TX\", \"RC\", \"BLE\", \"Bluetooth\", \"USB Wireless\", \"Zigbee\", \"NRF24\"\r\n};\r\nstatic const int kMenuCount = sizeof(kMenuLabels)/sizeof(kMenuLabels[0]);\r\n\r\nstatic int menuIndexFromMode(OperationMode m) {\r\n  switch (m) {\r\n    case WiFi_MODULE:         return 0;\r\n    case VIDEO_TX_MODULE:     return 1;\r\n    case RC_MODULE:           return 2;\r\n    case BLE_MODULE:          return 3;\r\n    case Bluetooth_MODULE:    return 4;\r\n    case USB_WIRELESS_MODULE: return 5;\r\n    case ZIGBEE_MODULE:       return 6;\r\n    case NRF24_MODULE:        return 7;\r\n    default: return 0;\r\n  }\r\n}\r\nstatic OperationMode modeFromMenuIndex(int idx) {\r\n  switch (idx) {\r\n    case 0: return WiFi_MODULE;\r\n    case 1: return VIDEO_TX_MODULE;\r\n    case 2: return RC_MODULE;\r\n    case 3: return BLE_MODULE;\r\n    case 4: return Bluetooth_MODULE;\r\n    case 5: return USB_WIRELESS_MODULE;\r\n    case 6: return ZIGBEE_MODULE;\r\n    case 7: return NRF24_MODULE;\r\n    default: return WiFi_MODULE;\r\n  }\r\n}\r\n\r\nvoid spectrum() {\r\n  const uint8_t HDR_H = 10;\r\n  const int TOP = HDR_H + 12;\r\n  const int BOT = SCREEN_H - 2;\r\n  const int H   = BOT - TOP;\r\n  const int STRIDE = 3;\r\n  const int BINS   = SCREEN_W / STRIDE;\r\n  const int BAR_W  = 1;\r\n  static uint8_t h[BINS];\r\n  static int8_t  v[BINS];\r\n  static bool init = false;\r\n  if (!init) {\r\n    for (int i = 0; i < BINS; ++i) {\r\n      h[i] = random(0, H + 1);\r\n      v[i] = random(-2, 3);\r\n    }\r\n    init = true;\r\n  }\r\n  for (int i = 0; i < BINS; ++i) {\r\n    int8_t a = (int8_t)random(-1, 2);\r\n    v[i] += a;\r\n    if (v[i] > 3) v[i] = 3;\r\n    if (v[i] < -3) v[i] = -3;\r\n    int16_t nh = (int16_t)h[i] + v[i];\r\n    if (nh < 0) {\r\n      nh = 0;\r\n      v[i] = -(v[i] * 3) / 4;\r\n      if (v[i] == 0) v[i] = 1;\r\n    } else if (nh > H) {\r\n      nh = H;\r\n      v[i] = -(v[i] * 3) / 4;\r\n      if (v[i] == 0) v[i] = -1;\r\n    }\r\n    h[i] = (uint8_t)nh;\r\n  }\r\n  for (int i = 0; i < BINS; ++i) {\r\n    int x  = i * STRIDE;\r\n    int bh = h[i];\r\n    if (bh <= 0) continue;\r\n    int y  = BOT - bh;\r\n    u8g2.drawVLine(x, y, bh);\r\n  }\r\n  u8g2.sendBuffer();\r\n}\r\n\r\nstatic void drawHeaderBar() {\r\n  const uint8_t W = 128;\r\n  const uint8_t H = HEADER_H;\r\n  const uint8_t TXT_Y = 2;\r\n  u8g2.setDrawColor(1);\r\n  u8g2.drawBox(0, 0, W, H);\r\n  u8g2.setFont(FONT_SMALL);\r\n  u8g2.setDrawColor(0);\r\n  u8g2.drawStr(PAD, TXT_Y, \"RF-Clown\");\r\n  const char* ver = \"v2.0.0\";\r\n  int vw = u8g2.getStrWidth(ver);\r\n  u8g2.drawStr(W - vw - 4, TXT_Y, ver);\r\n  u8g2.setDrawColor(1);\r\n  u8g2.drawHLine(0, H - 1, W);\r\n}\r\n\r\nstatic void drawPillOutline(int x,int y,int w,int h){\r\n  if (h & 1) h--; if (y & 1) y--;\r\n  u8g2.drawRFrame(x, y, w, h, h/2);\r\n}\r\nstatic void drawPillKnob(int x,int y,int w,int h,float pos){\r\n  if (h & 1) h--; if (y & 1) y--;\r\n  int r=h/2, cxL=x+r, cxR=x+w-r-1, cy=y+r;\r\n  int cx=(int)lroundf(cxL + (cxR - cxL)*pos);\r\n  int knob = max(2, r-3);\r\n  u8g2.drawDisc(cx, cy, knob);\r\n}\r\nstatic void drawPillToggle(int x,int y,int w,int h,bool on){\r\n  drawPillOutline(x,y,w,h);\r\n  drawPillKnob(x,y,w,h, on?0.0f:1.0f);\r\n}\r\n\r\nstatic void drawPaginationDots(int active){\r\n  int totalW = (kMenuCount * 6) - 2;\r\n  int startX = (128 - totalW) / 2;\r\n  for (int i=0;i<kMenuCount;i++) {\r\n    int x = startX + i*6;\r\n    if (i == active) u8g2.drawDisc(x, DOT_Y, 2);\r\n    else             u8g2.drawCircle(x, DOT_Y, 2);\r\n  }\r\n}\r\n\r\nstatic void drawCardAtCenter(int centerX, int menuIndex){\r\n  const char* label = kMenuLabels[menuIndex];\r\n  const int W = 128;\r\n  const int w = W - PAD*2;\r\n  const int x = centerX - w/2;\r\n  const int y = HEADER_H + 4;\r\n  u8g2.setDrawColor(0);\r\n  u8g2.drawBox(x+1, y+1, w-2, CARD_H-2);\r\n  u8g2.setDrawColor(1);\r\n  u8g2.drawRFrame(x, y, w, CARD_H, RADIUS);\r\n  u8g2.setFont(FONT_MEDIUM);\r\n  u8g2.setCursor(x + 12, y + 4);\r\n  u8g2.print(label);\r\n  bool isThisFocus = (modeFromMenuIndex(menuIndex) == current_Mode);\r\n  bool isActive    = (isThisFocus && current == ACTIVE_MODE);\r\n  const char* status = isActive ? \"ACTIVE\" : \"DEACTIVE\";\r\n  u8g2.setFont(FONT_SMALL);\r\n  u8g2.setCursor(x + 12, y + 16);\r\n  u8g2.print(status);\r\n  bool isOn = (modeFromMenuIndex(menuIndex) == current_Mode) && (current == ACTIVE_MODE);\r\n  const int pillW=24, pillH=14;\r\n  const int pillY=(y + ((CARD_H-pillH)/2)) & ~1;\r\n  drawPillToggle(x + w - pillW - 10, pillY, pillW, pillH, isOn);\r\n}\r\n\r\nstatic void renderStaticMenu(int focusIndex) {\r\n  u8g2.clearBuffer();\r\n  drawHeaderBar();\r\n  drawCardAtCenter(128 / 2, focusIndex);\r\n  drawPaginationDots(focusIndex);\r\n  u8g2.sendBuffer();\r\n}\r\n\r\nstatic void animateToMenu(int fromIdx, int toIdx) {\r\n  const int W = 128;\r\n  const int STEPS = 14;\r\n  const uint8_t DT = 10;\r\n  const int dir = (toIdx > fromIdx) ? -1 : 1;\r\n  for (int s = 0; s <= STEPS; s++) {\r\n    float t = (float)s / (float)STEPS;\r\n    float e = (t < 0.5f) ? 4.0f*t*t*t : 1.0f - powf(-2.0f*t + 2.0f, 3)/2.0f;\r\n    int shift = (int)(e * W + 0.5f);\r\n    int centerFrom = (W/2) + (-dir * shift);\r\n    int centerTo   = (W/2) + ( dir * (W - shift));\r\n    u8g2.clearBuffer();\r\n    drawHeaderBar();\r\n    drawCardAtCenter(centerFrom, fromIdx);\r\n    drawCardAtCenter(centerTo,   toIdx);\r\n    drawPaginationDots(toIdx);\r\n    u8g2.sendBuffer();\r\n    delay(DT);\r\n  }\r\n  renderStaticMenu(toIdx);\r\n}\r\n\r\nstatic void animateToggleKnobForFocus(int focusIdx, bool fromActive, bool toActive){\r\n  float start = (fromActive ? 0.0f : 1.0f);\r\n  float end   = (toActive   ? 0.0f : 1.0f);\r\n  const int STEPS = 10;\r\n  const uint8_t FRAME_MS = 12;\r\n  for (int s=0; s<=STEPS; s++){\r\n    float t = (float)s / (float)STEPS;\r\n    float e = (t < 0.5f) ? 2.0f*t*t : 1.0f - powf(-2.0f*t + 2.0f, 2)/2.0f;\r\n    float p = start + (end - start) * e;\r\n    u8g2.clearBuffer();\r\n    drawHeaderBar();\r\n    const int W = 128;\r\n    const int w = W - PAD*2;\r\n    const int x = W/2 - w/2;\r\n    const int y = HEADER_H + 4;\r\n    u8g2.setDrawColor(0);\r\n    u8g2.drawBox(x+1, y+1, w-2, CARD_H-2);\r\n    u8g2.setDrawColor(1);\r\n    u8g2.drawRFrame(x, y, w, CARD_H, RADIUS);\r\n    u8g2.setFont(FONT_MEDIUM); u8g2.setCursor(x+12, y+4);  u8g2.print(kMenuLabels[focusIdx]);\r\n    u8g2.setFont(FONT_SMALL);  u8g2.setCursor(x+12, y+16); u8g2.print(\"----\");\r\n    const int pillW=24, pillH=14;\r\n    const int pillY=(y + ((CARD_H-pillH)/2)) & ~1;\r\n    const int pillX=x + w - pillW - 10;\r\n    drawPillOutline(pillX, pillY, pillW, pillH);\r\n    drawPillKnob(pillX, pillY, pillW, pillH, p);\r\n    drawPaginationDots(focusIdx);\r\n    u8g2.sendBuffer();\r\n    delay(FRAME_MS);\r\n  }\r\n  renderStaticMenu(focusIdx);\r\n}\r\n\r\nvoid update_OLED() {\r\n  int focus = menuIndexFromMode(current_Mode);\r\n  renderStaticMenu(focus);\r\n}\r\n\r\nvoid menuPrev() {\r\n  int fromIdx = menuIndexFromMode(current_Mode);\r\n  int toIdx   = (fromIdx == 0) ? (kMenuCount - 1) : (fromIdx - 1);\r\n  current_Mode = modeFromMenuIndex(toIdx);\r\n  animateToMenu(fromIdx, toIdx);\r\n}\r\nvoid menuNext() {\r\n  int fromIdx = menuIndexFromMode(current_Mode);\r\n  int toIdx   = (fromIdx == (kMenuCount - 1)) ? 0 : (fromIdx + 1);\r\n  current_Mode = modeFromMenuIndex(toIdx);\r\n  animateToMenu(fromIdx, toIdx);\r\n}\r\nvoid menuToggleActive() {\r\n  int focus = menuIndexFromMode(current_Mode);\r\n  bool wasActive = (current == ACTIVE_MODE);\r\n  current = wasActive ? DEACTIVE_MODE : ACTIVE_MODE;\r\n  animateToggleKnobForFocus(focus, wasActive, !wasActive);\r\n}\r\n\r\nvoid checkMode() {\r\n  if (ChangeRequested) {\r\n    ChangeRequested = false;\r\n    current_Mode = static_cast<OperationMode>((current_Mode == 0) ? 7 : (current_Mode - 1));\r\n  } else if (ChangeRequested1) {\r\n    ChangeRequested1 = false;\r\n    current_Mode = static_cast<OperationMode>((current_Mode + 1) % 8);\r\n  }\r\n}\r\n\r\nvoid setup() {\r\n  Serial.begin(115200);\r\n  initialize_MultiMode();\r\n  Wire.begin();\r\n  Wire.setClock(400000);\r\n  u8g2.begin();\r\n  u8g2.setBusClock(400000);\r\n  u8g2.setFont(FONT_SMALL);\r\n  u8g2.setDrawColor(1);\r\n  u8g2.setFontPosTop();\r\n  esp_bt_controller_deinit();\r\n  esp_wifi_stop();\r\n  esp_wifi_deinit();\r\n  esp_wifi_disconnect();\r\n  pinMode(PIN_BTN_L,  INPUT_PULLUP);\r\n  pinMode(PIN_BTN_R, INPUT_PULLUP);\r\n  pinMode(PIN_BTN_S, INPUT_PULLUP);\r\n  attachInterrupt(digitalPinToInterrupt(PIN_BTN_L),  handleButton,  FALLING);\r\n  attachInterrupt(digitalPinToInterrupt(PIN_BTN_R), handleButton1, FALLING);\r\n  attachInterrupt(digitalPinToInterrupt(PIN_BTN_S), handleButton2, FALLING);\r\n  initialize_Radios();\r\n  conf();\r\n  update_OLED();\r\n}\r\n\r\nvoid loop() {\r\n  checkMode();\r\n  static Operation     lastActivity = current;\r\n  static OperationMode lastFocus    = current_Mode;\r\n  if (current_Mode != lastFocus) {\r\n    int fromIdx = menuIndexFromMode(lastFocus);\r\n    int toIdx   = menuIndexFromMode(current_Mode);\r\n    animateToMenu(fromIdx, toIdx);\r\n    lastFocus = current_Mode;\r\n    return;\r\n  }\r\n  if (current != lastActivity) {\r\n    initialize_Radios();\r\n    int  focus     = menuIndexFromMode(current_Mode);\r\n    bool wasActive = (lastActivity == ACTIVE_MODE);\r\n    bool nowActive = (current      == ACTIVE_MODE);\r\n    animateToggleKnobForFocus(focus, wasActive, nowActive);\r\n    lastActivity = current;\r\n    return;\r\n  }\r\n    if (current_Mode == BLE_MODULE) {\r\n      int randomIndex = random(0, sizeof(ble_channels) / sizeof(ble_channels[0]));\r\n      byte channel = ble_channels[randomIndex];\r\n      RadioA.setChannel(channel);\r\n      RadioB.setChannel(channel);\r\n      RadioC.setChannel(channel);\r\n    } else if (current_Mode == Bluetooth_MODULE) {\r\n      int randomIndex = random(0, sizeof(bluetooth_channels) / sizeof(bluetooth_channels[0]));\r\n      byte channel = bluetooth_channels[randomIndex];\r\n      RadioA.setChannel(channel);\r\n      RadioB.setChannel(channel);\r\n      RadioC.setChannel(channel);\r\n    } else if (current_Mode == WiFi_MODULE) {\r\n      int randomIndex = random(0, sizeof(WiFi_channels) / sizeof(WiFi_channels[0]));\r\n      byte channel = WiFi_channels[randomIndex];\r\n      RadioA.setChannel(channel);\r\n      RadioB.setChannel(channel);\r\n      RadioC.setChannel(channel);\r\n    } else if (current_Mode == USB_WIRELESS_MODULE) {\r\n      int randomIndex = random(0, sizeof(usbWireless_channels) / sizeof(usbWireless_channels[0]));\r\n      byte channel = usbWireless_channels[randomIndex];\r\n      RadioA.setChannel(channel);\r\n      RadioB.setChannel(channel);\r\n      RadioC.setChannel(channel);\r\n    } else if (current_Mode == VIDEO_TX_MODULE) {\r\n      int randomIndex = random(0, sizeof(videoTransmitter_channels) / sizeof(videoTransmitter_channels[0]));\r\n      byte channel = videoTransmitter_channels[randomIndex];\r\n      RadioA.setChannel(channel);\r\n      RadioB.setChannel(channel);\r\n      RadioC.setChannel(channel);\r\n    } else if (current_Mode == RC_MODULE) {\r\n      int randomIndex = random(0, sizeof(rc_channels) / sizeof(rc_channels[0]));\r\n      byte channel = rc_channels[randomIndex];\r\n      RadioA.setChannel(channel);\r\n      RadioB.setChannel(channel);\r\n      RadioC.setChannel(channel);\r\n    } else if (current_Mode == ZIGBEE_MODULE) {\r\n      int randomIndex = random(0, sizeof(zigbee_channels) / sizeof(zigbee_channels[0]));\r\n      byte channel = zigbee_channels[randomIndex];\r\n      RadioA.setChannel(channel);\r\n      RadioB.setChannel(channel);\r\n      RadioC.setChannel(channel);\r\n    } else if (current_Mode == NRF24_MODULE) {\r\n      int randomIndex = random(0, sizeof(nrf24_channels) / sizeof(nrf24_channels[0]));\r\n      byte channel = nrf24_channels[randomIndex];\r\n      RadioA.setChannel(channel);\r\n      RadioB.setChannel(channel);\r\n      RadioC.setChannel(channel);\r\n    }\r\n}\r\n"
  },
  {
    "path": "RfClown/config.h",
    "content": "/* ____________________________\r\n   This software is licensed under the MIT License:\r\n   https://github.com/cifertech/rfclown\r\n   ________________________________________ */\r\n\r\n#ifndef CONFIG_H\r\n#define CONFIG_H\r\n\r\n#define SCREEN_W 128\r\n#define SCREEN_H 64\r\n\r\n// ---------------- Pins ----------------\r\n#define PIN_BTN_L  27\r\n#define PIN_BTN_R  25\r\n#define PIN_BTN_S  26\r\n\r\n// nRF24-specific Pins\r\n#define NRF_CE_PIN_A    5   \r\n#define NRF_CSN_PIN_A   17 \r\n#define NRF_CE_PIN_B    16  \r\n#define NRF_CSN_PIN_B   4  \r\n#define NRF_CE_PIN_C    15  \r\n#define NRF_CSN_PIN_C   2  \r\n\r\n// Common dependencies\r\n#include \"setting.h\"\r\n#include <Arduino.h>\r\n#include <U8g2lib.h>\r\n#include <Wire.h>\r\n#include <SPI.h>\r\n#include <Adafruit_NeoPixel.h>\r\n#include <EEPROM.h>\r\n#include <Preferences.h>\r\n#include <vector>\r\n#include <string>\r\n#include <math.h>\r\n\r\nU8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE);\r\n\r\nAdafruit_NeoPixel pixels(1, 14, NEO_GRB + NEO_KHZ800);\r\n\r\n// BLE-specific dependencies\r\n#include <BLEDevice.h>\r\n#include <BLEUtils.h>\r\n#include <BLEServer.h>\r\n\r\n// nRF24-specific dependencies\r\n#include <nRF24L01.h>\r\n#include <RF24.h>\r\n\r\n// WiFi-specific dependencies\r\n#include <WiFi.h>\r\n#include <esp_wifi.h>\r\n#include <esp_wifi_types.h>\r\n#include <esp_system.h>\r\n#include <esp_event.h>\r\n#include <nvs_flash.h>\r\n#include <string>\r\n\r\n// ESP-specific configurations\r\n#include <esp_bt.h>\r\n#include <esp_wifi.h>\r\n\r\n// External declarations\r\nextern U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2;\r\nextern Adafruit_NeoPixel pixels;\r\n\r\nstatic const uint8_t* FONT_SMALL  = u8g2_font_5x8_tf;\r\nstatic const uint8_t* FONT_MEDIUM = u8g2_font_6x12_tf;\r\nstatic const uint8_t* FONT_ICON_FALLBACK = u8g2_font_open_iconic_thing_2x_t;\r\n\r\nenum OperationMode {WiFi_MODULE, VIDEO_TX_MODULE, RC_MODULE, BLE_MODULE, Bluetooth_MODULE, USB_WIRELESS_MODULE, ZIGBEE_MODULE, NRF24_MODULE};\r\nOperationMode current_Mode = WiFi_MODULE;\r\n\r\nenum Operation {DEACTIVE_MODE, ACTIVE_MODE};\r\nvolatile Operation current = DEACTIVE_MODE;\r\n\r\nbyte channelGroup_1[] = {2, 5, 8, 11};\r\nbyte channelGroup_2[] = {26, 29, 32, 35};\r\nbyte channelGroup_3[] = {80, 83, 86, 89};\r\n\r\nconst byte bluetooth_channels[] =        {32, 34, 46, 48, 50, 52, 0, 1, 2, 4, 6, 8, 22, 24, 26, 28, 30, 74, 76, 78, 80};\r\nconst byte ble_channels[]       =        {2, 26, 80};\r\nconst byte WiFi_channels[]      =        {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};\r\nconst byte usbWireless_channels[] =      {40, 50, 60};\r\nconst byte videoTransmitter_channels[] = {70, 75, 80};\r\nconst byte rc_channels[]        =        {1, 3, 5, 7};\r\nconst byte zigbee_channels[]    =        {11, 15, 20, 25};\r\nconst byte nrf24_channels[]     =        {76, 78, 79};\r\n\r\nvolatile bool ChangeRequested  = false;\r\nvolatile bool ChangeRequested1 = false;\r\nvolatile bool ChangeRequested2 = false;\r\n\r\nunsigned long lastPressTime = 0;\r\nconst unsigned long debounceDelay = 200;\r\n\r\n#endif // CONFIG_H\r\n"
  },
  {
    "path": "RfClown/neopixel.cpp",
    "content": "/* ____________________________\r\n   This software is licensed under the MIT License:\r\n   https://github.com/cifertech/rfclown\r\n   ________________________________________ */\r\n   \r\n#include \"setting.h\"\r\n#include \"config.h\"\r\n\r\nextern Adafruit_NeoPixel pixels;\r\n\r\nvoid neopixelSetup() {\r\n  EEPROM.begin(512); \r\n  neoPixelActive = EEPROM.read(0);\r\n  \r\n if (neoPixelActive) {\r\n  pixels.begin();\r\n  pixels.clear();\r\n  //pixels.show();\r\n  }\r\n}\r\n\r\nvoid neopixelLoop();\r\n\r\nvoid setNeoPixelColour(const std::string& colour) {\r\n  uint32_t colorValue = 0; \r\n\r\n  if (colour == \"red\") {\r\n    colorValue = pixels.Color(5, 0, 0);\r\n  } else if (colour == \"green\") {\r\n    colorValue = pixels.Color(0, 5, 0);\r\n  } else if (colour == \"blue\") {\r\n    colorValue = pixels.Color(0, 0, 5);\r\n  } else if (colour == \"yellow\") {\r\n    colorValue = pixels.Color(5, 5, 0);\r\n  } else if (colour == \"purple\") {\r\n    colorValue = pixels.Color(5, 0, 5);\r\n  } else if (colour == \"cyan\") {\r\n    colorValue = pixels.Color(0, 5, 5);\r\n  } else if (colour == \"white\") {\r\n    colorValue = pixels.Color(5, 5, 5);\r\n  } else if (colour == \"null\") {\r\n    colorValue = pixels.Color(0, 0, 0);\r\n  }\r\n\r\n  pixels.setPixelColor(0, colorValue);\r\n  pixels.show();\r\n}\r\n\r\nvoid flash(int numberOfFlashes, const std::vector<std::string>& colors, const std::string& finalColour) {\r\n  if (numberOfFlashes <= 0 || colors.empty()) {\r\n    Serial.println(\"Invalid parameters for flash: Check numberOfFlashes or colors vector.\");\r\n    return;\r\n  }\r\n\r\n  for (int i = 0; i < numberOfFlashes; ++i) {\r\n    for (const auto& color : colors) {\r\n      setNeoPixelColour(color);\r\n      delay(500);\r\n    }\r\n  }\r\n  setNeoPixelColour(finalColour);\r\n}\r\n"
  },
  {
    "path": "RfClown/setting.cpp",
    "content": "/* ____________________________\r\n   This software is licensed under the MIT License:\r\n   https://github.com/cifertech/rfclown\r\n   ________________________________________ */\r\n\r\n#include \"setting.h\"\r\n#include \"config.h\"\r\n\r\nRF24 RadioA(NRF_CE_PIN_A, NRF_CSN_PIN_A);\r\nRF24 RadioB(NRF_CE_PIN_B, NRF_CSN_PIN_B);\r\nRF24 RadioC(NRF_CE_PIN_C, NRF_CSN_PIN_C);\r\n\r\nvoid setRadiosNeutralState() {\r\n  RadioA.stopListening();\r\n  RadioA.setAutoAck(false);\r\n  RadioA.setRetries(0, 0);\r\n  RadioA.powerDown(); \r\n  digitalWrite(NRF_CE_PIN_A, LOW); \r\n\r\n  RadioB.stopListening();\r\n  RadioB.setAutoAck(false);\r\n  RadioB.setRetries(0, 0);\r\n  RadioB.powerDown(); \r\n  digitalWrite(NRF_CE_PIN_B, LOW); \r\n\r\n  RadioC.stopListening();\r\n  RadioC.setAutoAck(false);\r\n  RadioC.setRetries(0, 0);\r\n  RadioC.powerDown(); \r\n  digitalWrite(NRF_CE_PIN_C, LOW); \r\n}\r\n\r\nvoid configureNrf(RF24 &radio) {\r\n  radio.begin();\r\n  radio.setAutoAck(false);\r\n  radio.stopListening();\r\n  radio.setRetries(0, 0);\r\n  radio.setPALevel(RF24_PA_MAX, true);\r\n  radio.setDataRate(RF24_2MBPS);\r\n  radio.setCRCLength(RF24_CRC_DISABLED);\r\n}\r\n\r\nvoid setupRadioA() {\r\n  configureNrf(RadioA);\r\n}\r\n\r\nvoid setupRadioB() {\r\n  configureNrf(RadioB);\r\n}\r\n\r\nvoid setupRadioC() {\r\n  configureNrf(RadioC);\r\n}\r\n\r\nvoid initAllRadios() {\r\n  setupRadioA();\r\n  setupRadioB();\r\n  setupRadioC();\r\n}\r\n\r\nvoid Str(uint8_t x, uint8_t y, const uint8_t* asciiArray, size_t len) {\r\n  char buf[64]; \r\n  for (size_t i = 0; i < len && i < sizeof(buf) - 1; i++) {\r\n    buf[i] = (char)asciiArray[i];\r\n  }\r\n  buf[len] = '\\0';\r\n\r\n  u8g2.drawStr(x, y, buf);\r\n}\r\n\r\nvoid CenteredStr(uint8_t screenWidth, uint8_t y, const uint8_t* asciiArray, size_t len, const uint8_t* font) {\r\n  char buf[64];\r\n  for (size_t i = 0; i < len && i < sizeof(buf) - 1; i++) {\r\n    buf[i] = (char)asciiArray[i];\r\n  }\r\n  buf[len] = '\\0';\r\n\r\n  u8g2.setFont((const uint8_t*)font);\r\n  int16_t w = u8g2.getUTF8Width(buf);\r\n  u8g2.setCursor((screenWidth - w) / 2, y);\r\n  u8g2.print(buf);\r\n}\r\n\r\nvoid conf() {\r\n  u8g2.setBitmapMode(1);\r\n  u8g2.clearBuffer();\r\n  CenteredStr(128, 15, txt_n, sizeof(txt_n), u8g2_font_ncenB14_tr);\r\n  CenteredStr(120, 35, txt_c, sizeof(txt_c), u8g2_font_ncenB08_tr);\r\n  CenteredStr(128, 50, txt_v, sizeof(txt_v), u8g2_font_6x10_tf);\r\n  u8g2.sendBuffer();\r\n  delay(3000);\r\n  u8g2.clearBuffer();\r\n  u8g2.drawXBMP(0, 0, 128, 64, cred); \r\n  u8g2.sendBuffer();\r\n  delay(250);\r\n}\r\n\r\n \r\n"
  },
  {
    "path": "RfClown/setting.h",
    "content": "/* ____________________________\r\n   This software is licensed under the MIT License:\r\n   https://github.com/cifertech/rfclown\r\n   ________________________________________ */\r\n   \r\n#ifndef setting_H\r\n#define setting_H\r\n\r\n#include <BLEDevice.h>\r\n#include <U8g2lib.h>\r\n#include <Adafruit_NeoPixel.h>\r\n#include <EEPROM.h>\r\n#include <RF24.h>\r\n#include <vector>\r\n#include <string>\r\n#include <SPI.h>\r\n\r\nvoid neopixelSetup();\r\nvoid neopixelLoop();\r\n\r\nvoid setNeoPixelColour(const std::string& colour);\r\nvoid flash(int numberOfFlashes, const std::vector<std::string>& colors, const std::string& finalColour);\r\n\r\nextern U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2;\r\nextern Adafruit_NeoPixel pixels;\r\n\r\n//extern bool neoPixelActive;\r\n\r\nbool neoPixelActive = false;\r\nuint8_t oledBrightness = 100;\r\n\r\nextern RF24 RadioA;\r\nextern RF24 RadioB;\r\nextern RF24 RadioC;\r\n\r\nvoid configureNrf(RF24 &radio);\r\n\r\nvoid setRadiosNeutralState();\r\n\r\nvoid setupRadioA();\r\nvoid setupRadioB();\r\nvoid setupRadioC();\r\n\r\nvoid initAllRadios();\r\n\r\nvoid Str(uint8_t x, uint8_t y, const uint8_t* asciiArray, size_t len);\r\nvoid CenteredStr(uint8_t screenWidth, uint8_t y, const uint8_t* asciiArray, size_t len, const uint8_t* font);\r\nvoid conf();\r\n\r\nconst uint8_t txt_n[]   = {82, 102, 67, 108, 111, 119, 110};                  \r\nconst uint8_t txt_c[]   = {98, 121, 32, 67, 105, 102, 101, 114, 84, 101, 99, 104}; \r\nconst uint8_t txt_v[]   = {118, 50, 46, 48, 46, 48}; \r\n\r\nconst unsigned char cred [] PROGMEM = {\r\n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \r\n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \r\n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \r\n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \r\n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \r\n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \r\n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \r\n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x3f, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \r\n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x07, 0xf0, 0x83, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, \r\n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x6f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \r\n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \r\n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x78, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \r\n  0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x0c, 0x7f, 0xfe, 0x01, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, \r\n  0x00, 0x00, 0x00, 0x00, 0xfe, 0x03, 0xc0, 0x7f, 0xfe, 0x07, 0x80, 0xff, 0x00, 0x00, 0x00, 0x00, \r\n  0x00, 0x00, 0x00, 0x00, 0xf8, 0x07, 0xe0, 0x7f, 0xfe, 0x1f, 0xc0, 0x3f, 0x00, 0x00, 0x00, 0x00, \r\n  0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0xf8, 0x7f, 0xfe, 0x3f, 0xe0, 0x07, 0x00, 0x00, 0x00, 0x00, \r\n  0x00, 0x00, 0x00, 0x00, 0xc0, 0x0f, 0xfc, 0x7f, 0xfe, 0x7f, 0xe0, 0x03, 0x00, 0x00, 0x00, 0x00, \r\n  0x00, 0x00, 0x00, 0x00, 0xc0, 0x1f, 0xfe, 0x7f, 0xfe, 0xff, 0xf0, 0x03, 0x00, 0x00, 0x00, 0x00, \r\n  0x00, 0x00, 0x00, 0xc0, 0x80, 0x7f, 0xff, 0x7f, 0xfe, 0xff, 0xf9, 0x03, 0x02, 0x00, 0x00, 0x00, \r\n  0x00, 0x00, 0x00, 0xc0, 0xc1, 0x3f, 0xff, 0x7f, 0xfe, 0xff, 0xfb, 0x87, 0x03, 0x00, 0x00, 0x00, \r\n  0x00, 0x00, 0x00, 0xc0, 0xe7, 0xbf, 0xff, 0x7f, 0xfe, 0xff, 0xf3, 0xff, 0x03, 0x00, 0x00, 0x00, \r\n  0x00, 0x00, 0x00, 0x80, 0xff, 0xdf, 0xff, 0x7f, 0xfe, 0xff, 0xf7, 0xff, 0x03, 0x00, 0x00, 0x00, \r\n  0x00, 0x00, 0x00, 0x00, 0xff, 0xdf, 0xff, 0x7f, 0xfe, 0xff, 0xe7, 0xff, 0x01, 0x00, 0x00, 0x00, \r\n  0x00, 0x00, 0x00, 0x00, 0xff, 0xcf, 0xff, 0x7f, 0xfe, 0xff, 0xef, 0xff, 0x00, 0x00, 0x00, 0x00, \r\n  0x00, 0x00, 0x00, 0x00, 0xfc, 0xef, 0xff, 0x7f, 0xfe, 0xff, 0xcf, 0x3f, 0x00, 0x00, 0x00, 0x00, \r\n  0x00, 0x00, 0x00, 0x00, 0x00, 0xec, 0xff, 0x7f, 0xfe, 0xff, 0x5f, 0x00, 0x00, 0x00, 0x00, 0x00, \r\n  0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0x7f, 0xfe, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, \r\n  0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0x7f, 0xfe, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, \r\n  0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0x7f, 0xfe, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, \r\n  0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0x7f, 0xfe, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, \r\n  0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0x7f, 0x1e, 0xf0, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, \r\n  0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0x7f, 0x0e, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, \r\n  0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0x7f, 0x06, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, \r\n  0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0x7f, 0x06, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, \r\n  0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0x7f, 0x06, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, \r\n  0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0x7f, 0x0e, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, \r\n  0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0x7f, 0x0e, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, \r\n  0x00, 0x00, 0x00, 0x00, 0x00, 0xec, 0x3f, 0x7f, 0x1e, 0x00, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x00, \r\n  0x00, 0x00, 0x00, 0x00, 0x60, 0xee, 0x0f, 0x7e, 0x1e, 0x00, 0xee, 0x39, 0x00, 0x00, 0x00, 0x00, \r\n  0x00, 0x00, 0x00, 0x00, 0xfc, 0xef, 0xe7, 0x7c, 0x3e, 0x00, 0xef, 0xff, 0x00, 0x00, 0x00, 0x00, \r\n  0x00, 0x00, 0x00, 0x00, 0xfe, 0xcf, 0xf7, 0x79, 0x7e, 0x80, 0xef, 0xff, 0x01, 0x00, 0x00, 0x00, \r\n  0x00, 0x00, 0x00, 0x00, 0xff, 0xdf, 0xf7, 0x7b, 0xfe, 0xc0, 0xe7, 0xff, 0x03, 0x00, 0x00, 0x00, \r\n  0x00, 0x00, 0x00, 0x80, 0xff, 0x9f, 0xe7, 0x77, 0xfe, 0xf3, 0xf7, 0xff, 0x03, 0x00, 0x00, 0x00, \r\n  0x00, 0x00, 0x00, 0x80, 0xcf, 0xbf, 0xe7, 0x6f, 0x8e, 0xff, 0xf3, 0xc7, 0x03, 0x00, 0x00, 0x00, \r\n  0x00, 0x00, 0x00, 0x80, 0x83, 0x3f, 0xcf, 0x4f, 0x06, 0xff, 0xfb, 0x03, 0x03, 0x00, 0x00, 0x00, \r\n  0x00, 0x00, 0x00, 0x80, 0x00, 0x3f, 0x9e, 0x1f, 0x72, 0xfe, 0xf0, 0x03, 0x00, 0x00, 0x00, 0x00, \r\n  0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xb0, 0x3f, 0xf8, 0x3c, 0xe0, 0x03, 0x00, 0x00, 0x00, 0x00, \r\n  0x00, 0x00, 0x00, 0x00, 0x80, 0x0f, 0x60, 0x7f, 0xfe, 0x0d, 0xe0, 0x07, 0x00, 0x00, 0x00, 0x00, \r\n  0x00, 0x00, 0x00, 0x00, 0xe0, 0x0f, 0xc0, 0xfe, 0xff, 0x0c, 0xc0, 0x1f, 0x00, 0x00, 0x00, 0x00, \r\n  0x00, 0x00, 0x00, 0x00, 0xf0, 0x07, 0xc0, 0xfd, 0x7f, 0x06, 0x80, 0x7f, 0x00, 0x00, 0x00, 0x00, \r\n  0x00, 0x00, 0x00, 0x00, 0xfc, 0x03, 0x80, 0xfb, 0x3f, 0x07, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, \r\n  0x00, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x80, 0xf3, 0x9f, 0x03, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, \r\n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf3, 0x9f, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \r\n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x3f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \r\n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \r\n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \r\n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x7f, 0xfc, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \r\n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f, 0xf8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \r\n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \r\n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \r\n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \r\n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \r\n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \r\n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00\r\n};\r\n\r\n#endif\r\n"
  }
]