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 #include #include #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 ================================================
logo

RF-Clown

A fully open-source BLE and Bluetooth jammer

cifertech - RF-Clown stars - RF-Clown forks - RF-Clown

TWITTER · INSTAGRAM · YOUTUBE · WEBSITE


## 📖 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!
 
## :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.
screenshot
 
### 🎯 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.
 
## :eyes: RF-Clown Versions:
RF-Clown v1

RF-Clown v1

RF-Clown v2

RF-Clown v2

 
## 🔗 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.   ### 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
 
## :warning: License Distributed under the MIT License. See LICENSE.txt for more information.
 
## :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)
 
================================================ 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 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((current_Mode == 0) ? 7 : (current_Mode - 1)); } else if (ChangeRequested1) { ChangeRequested1 = false; current_Mode = static_cast((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 #include #include #include #include #include #include #include #include #include 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 #include #include // nRF24-specific dependencies #include #include // WiFi-specific dependencies #include #include #include #include #include #include #include // ESP-specific configurations #include #include // 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& 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 #include #include #include #include #include #include #include void neopixelSetup(); void neopixelLoop(); void setNeoPixelColour(const std::string& colour); void flash(int numberOfFlashes, const std::vector& 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