├── AS07-M1101S.pdf ├── Arduino-NANO-Pinout.png ├── E07-M1101D-SMA_Usermanual_EN_v1.30.pdf ├── ESP8266-cpu-speed-selection-for-WIFI.png ├── ESP8266_Pinout_Diagrams.pdf ├── Esp8266_CC1101.png ├── README.md ├── SmartRC-CC1101-Driver-Lib-master.zip ├── TXS0108E_CC1101.png ├── Wiring_CC1101.png ├── arduino-esp32-en-latest-doc.pdf ├── arduino-esp8266-readthedocs-io-en-latest.pdf ├── arduino-pro-micro-pinout.png ├── cc1101-arduino-pro-micro-tool.png ├── cc1101-tool-arduino-nano.ino ├── cc1101-tool-arduino-pro-micro-E7-M1101D.png ├── cc1101-tool-esp32-wroom.ino ├── cc1101-tool-esp32.ino ├── cc1101-tool-esp8266-wifi-ap.ino ├── cc1101-tool-esp8266-wifi.ino ├── cc1101-tool-esp8266.ino ├── cc1101-tool-rp2040.ino ├── cc1101-tool.ino ├── cc1101.pdf ├── esp32-pinout.png ├── esp32c3-pinout.jpg ├── in-action.jpg └── wemos-d1-mini-cc1101-E07-M1101D.png /AS07-M1101S.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcore1976/cc1101-tool/0322f973d4c2d871154a308abb1e669cecd98cba/AS07-M1101S.pdf -------------------------------------------------------------------------------- /Arduino-NANO-Pinout.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcore1976/cc1101-tool/0322f973d4c2d871154a308abb1e669cecd98cba/Arduino-NANO-Pinout.png -------------------------------------------------------------------------------- /E07-M1101D-SMA_Usermanual_EN_v1.30.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcore1976/cc1101-tool/0322f973d4c2d871154a308abb1e669cecd98cba/E07-M1101D-SMA_Usermanual_EN_v1.30.pdf -------------------------------------------------------------------------------- /ESP8266-cpu-speed-selection-for-WIFI.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcore1976/cc1101-tool/0322f973d4c2d871154a308abb1e669cecd98cba/ESP8266-cpu-speed-selection-for-WIFI.png -------------------------------------------------------------------------------- /ESP8266_Pinout_Diagrams.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcore1976/cc1101-tool/0322f973d4c2d871154a308abb1e669cecd98cba/ESP8266_Pinout_Diagrams.pdf -------------------------------------------------------------------------------- /Esp8266_CC1101.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcore1976/cc1101-tool/0322f973d4c2d871154a308abb1e669cecd98cba/Esp8266_CC1101.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # cc1101-tool 2 | RF tool based on CC1101 module and Arduino Pro Micro 8VMHz/3.3V. Allows using CLI to control CC1101 board over USB interface. Putty or any other serial terminal can be used. It has similar functionality to YardStick One but is cheaper and does not need specialized software. Allows for RF jamming and replay attacks as well. It has RAW recording/replaying function which works exactly the same as in the Flipper Zero. Additional function is Radio Chat communicator 3 | 4 | You simply connect your Arduino Pro Micro (Arduino Leonardo clone from Sparkfun) to USB port of your PC and launch Putty terminal to communicate with CC1101 module over USB Serial port ( /dev/ttyACM0 port in Linux, COMxx in Windows). 5 | 6 | Also you may connect this device to Android OTG USB port in your smartphone for portable hacking and use USB Serial Terminal application with option CDC driver set to communicate with the device ( app : https://play.google.com/store/apps/details?id=de.kai_morich.serial_usb_terminal ). When using Serial Terminal app on Android first go to the Settings in the app on your smartphone then upper side of the screen select "Send" and then set "Newline" as CR only. It is sending to many characters to the device and extra character of Newline sometimes stops some of commands like "rxraw" for example. 7 | 8 | Following commands are available : 9 | 10 | setmodulation // set modulation mode. 0 = 2-FSK, 1 = GFSK, 2 = ASK/OOK, 3 = 4-FSK, 4 = MSK. 11 | 12 | setmhz // Here you can set your basic frequency. default = 433.92).The cc1101 can: 300-348 MHZ, 387-464MHZ and 779-928MHZ. 13 | 14 | setdeviation // Set the Frequency deviation in kHz. Value from 1.58 to 380.85. Default is 47.60 kHz. 15 | 16 | setchannel // Set the Channelnumber from 0 to 255. Default is cahnnel 0. 17 | 18 | setchsp // The channel spacing is multiplied by the channel number CHAN and added to the base frequency in kHz. Value from 25.39 to 405.45. Default is 199.95 kHz. 19 | 20 | setrxbw // Set the Receive Bandwidth in kHz. Value from 58.03 to 812.50. Default is 812.50 kHz. 21 | 22 | setdrate // Set the Data Rate in kBaud. Value from 0.02 to 1621.83. Default is 99.97 kBaud! 23 | 24 | setpa // Set TxPower. The following settings are possible depending on the frequency band. (-30 -20 -15 -10 -6 0 5 7 10 11 12) Default is max! 25 | 26 | setsyncmode // Combined sync-word qualifier mode. 0 = No preamble/sync. 1 = 16 sync word bits detected. 2 = 16/16 sync word bits detected. 3 = 30/32 sync word bits detected. 4 = No preamble/sync, carrier-sense above threshold. 5 = 15/16 + carrier-sense above threshold. 6 = 16/16 + carrier-sense above threshold. 7 = 30/32 + carrier-sense above threshold. 27 | 28 | setsyncword // Set sync word. Must be the same for the transmitter and receiver. (Syncword high, Syncword low) 29 | 30 | setadrchk
// Controls address check configuration of received packages. 0 = No address check. 1 = Address check, no broadcast. 2 = Address check and 0 (0x00) broadcast. 3 = Address check and 0 (0x00) and 255 (0xFF) broadcast. 31 | 32 | setaddr
// Address used for packet filtration. Optional broadcast addresses are 0 (0x00) and 255 (0xFF). 33 | 34 | setwhitedata // Turn data whitening on / off. 0 = Whitening off. 1 = Whitening on. 35 | 36 | setpktformat // Format of RX and TX data. 0 = Normal mode, use FIFOs for RX and TX. 1 = Synchronous serial mode, Data in on GDO0 and data out on either of the GDOx pins. 2 = Random TX mode; sends random data using PN9 generator. Used for test. Works as normal mode, setting 0 (00), in RX. 3 = Asynchronous serial mode, Data in on GDO0 and data out on either of the GDOx pins. 37 | 38 | setlengthconfig // 0 = Fixed packet length mode. 1 = Variable packet length mode. 2 = Infinite packet length mode. 3 = Reserved 39 | 40 | setpacketlength // Indicates the packet length when fixed packet length mode is enabled. If variable packet length mode is used, this value indicates the maximum packet length allowed. 41 | 42 | setcrc // 1 = CRC calculation in TX and CRC check in RX enabled. 0 = CRC disabled for TX and RX. 43 | 44 | setcrcaf // Enable automatic flush of RX FIFO when CRC is not OK. This requires that only one packet is in the RXIFIFO and that packet length is limited to the RX FIFO size. 45 | 46 | setdcfilteroff // Disable digital DC blocking filter before demodulator. Only for data rates ≤ 250 kBaud The recommended IF frequency changes when the DC blocking is disabled. 1 = Disable (current optimized). 0 = Enable (better sensitivity). 47 | 48 | setmanchester // Enables Manchester encoding/decoding. 0 = Disable. 1 = Enable. 49 | 50 | setfec // Enable Forward Error Correction (FEC) with interleaving for packet payload (Only supported for fixed packet length mode. 0 = Disable. 1 = Enable. 51 | 52 | setpre // Sets the minimum number of preamble bytes to be transmitted. Values: 0 : 2, 1 : 3, 2 : 4, 3 : 6, 4 : 8, 5 : 12, 6 : 16, 7 : 24 53 | 54 | setpqt // Preamble quality estimator threshold. The preamble quality estimator increases an internal counter by one each time a bit is received that is different from the previous bit, and decreases the counter by 8 each time a bit is received that is the same as the last bit. A threshold of 4∙PQT for this counter is used to gate sync word detection. When PQT=0 a sync word is always accepted. 55 | 56 | setappendstatus // When enabled, two status bytes will be appended to the payload of the packet. The status bytes contain RSSI and LQI values, as well as CRC OK. 57 | 58 | getrssi // Shows radio quality information about last received RF data frame. 59 | 60 | scan // Scan frequency range for the highest signal and display results 61 | 62 | rx // Enable or disable printing of received RF packets on serial terminal. 63 | 64 | tx // Send the packet of max 60 bytes < hex values > hex values over RF 65 | 66 | jam // Enable or disable continous jamming on selected band with selected modulation etc... 67 | 68 | brute // Brute force garage gate with keyword where symbol length is 69 | 70 | rec // Enable or disable recording frames in the buffer. 71 | 72 | show // Show content of recording buffer 73 | 74 | add // Manually add single frame payload (max 60 hex values) to the buffer so it can be replayed 75 | 76 | flush // Clear the recording buffer 77 | 78 | play // Replay 0 = all frames or N-th recorded frame 79 | 80 | rxraw // Sniffs radio by sampling with interval and prints received bytes in hex 81 | 82 | addraw // Manually add chunks (max 60 hex values) to the buffer so they can be further replayed. 83 | 84 | recraw // Recording RAW RF data with sampling interval 85 | 86 | showraw // Showing content of recording buffer in RAW format 87 | 88 | showbit // Showing content of recording buffer in RAW format as a stream of bits. 89 | 90 | playraw // Replaying previously recorded RAW RF data with sampling interval 91 | 92 | save // Store recording buffer content in non-volatile memory 93 | 94 | load // Load the content from non-volatile memory to the recording buffer 95 | 96 | echo // Enable or disable Echo on serial terminal. 1 = enabled, 0 = disabled 97 | 98 | chat // switching device into chat mode 99 | 100 | x // Stops activities like jamming/receiving/recording packets 101 | 102 | init // Restarts CC1101 board with default parameters 103 | 104 | The code uses SmartRC library (modified Electrohouse library by Little_S@tan) which allows to customize ALL transmission parameters in human readable format without using SmartRF studio from TI (CC1101 parameter customization tool). To use it please download following ZIP library from following github link https://github.com/LSatan/SmartRC-CC1101-Driver-Lib and attach it to the script in Arduino IDE. 105 | 106 | Arduino Pro Micro board ( ATMEGA32U4 chip ) must support 3.3Volt VCC and 3.3V TTL logic because this is required by CC1101 board, otherwise you will fry CC1101 chip. Please follow this guide to setup your Arduino environment for Arduino Pro Micro board : https://learn.sparkfun.com/tutorials/pro-micro--fio-v3-hookup-guide/all 107 | 108 | If you are having issues with uploading the code from Arduino IDE to the board, after pressing "Upload" in Arduino you have to immediatelly short GND+RST pins two times in few seconds. Then bootloader in Arduino Pro Micro will start (common issue) and upload will begin. 109 | 110 | Connections to be made for ARDUINO PRO MICRO : 111 | 112 | ARDUINO PRO MICRO 3.3V / 8MHz <-> CC1101 BOARD 113 | 114 | DIGITAL PIN 3 ( PD0 / INT0 ) <-> CC1101 GDO0 115 | 116 | DIGITAL PIN 9 ( PB5 ) <-> CC1101 GDO2 117 | 118 | DIGITAL PIN 10 ( PB6 ) <-> CC1101 CSN / CS / SS 119 | 120 | DIGITAL PIN 16 ( PB2 / MOSI ) <-> CC1101 MOSI / SI 121 | 122 | DIGITAL PIN 14 ( PB3 / MISO ) <-> CC1101 MISO / SO 123 | 124 | DIGITAL PIN 15 ( PB1 / SCK ) <-> CC1101 SCLK / CLK 125 | 126 | VCC 3.3V <-> CC1101 VCC 127 | 128 | GND <-> CC1101 GND 129 | 130 | 131 | ---- 132 | 133 | If you want to use different Arduino Board, please change pin assignment in the beginning of the source code and adjust size of EEPROM/FLASH for storing recorded data and size of SRAM memory 134 | 135 | ---- 136 | 137 | Example for ESP32 board : 138 | 139 | #define RECORDINGBUFFERSIZE 4096 // Buffer for recording the frames 140 | 141 | #define EPROMSIZE 512 // Size of EEPROM in your Arduino chip. For ESP32 it is Flash simulated 512 bytes only 142 | 143 | // defining PINs set for ESP32 module 144 | 145 | byte sck = 18; // GPIO 18 146 | 147 | byte miso = 19; // GPIO 19 148 | 149 | byte mosi = 23; // GPIO 150 | 151 | byte ss = 5; // GPIO 5 152 | 153 | int gdo0 = 2; // GPIO 2 154 | 155 | int gdo2 = 4; // GPIO 4 156 | 157 | ---- 158 | 159 | Example for XIAO ESP32 C3 - ATTENTION ! This board may require some shielding of cables connected to GDO0 pin when using some cheapest CC1101 boards (green D-SUN f.ex.) to properly work with RXRAW/RECRAW commands. It catches noise like "FF" in RXRAW/RECRAW. 160 | 161 | #define RECORDINGBUFFERSIZE 4096 // Buffer for recording the frames 162 | 163 | #define EPROMSIZE 512 // Size of EEPROM in your Arduino chip. For ESP32 it is Flash simulated 512 bytes only 164 | 165 | // defining PINs set for XIAO ESP32 C3 166 | 167 | byte sck = 8; // GPIO 8 168 | 169 | byte miso = 4; // GPIO 4 170 | 171 | byte mosi = 10; // GPIO 10 172 | 173 | byte ss = 20; // GPIO 20 174 | 175 | int gdo0 = 21; // GPIO 21 176 | 177 | int gdo2 = 7; // GPIO 7 178 | 179 | ---- 180 | 181 | Example for WEMOS D1 MINI module 182 | 183 | #define RECORDINGBUFFERSIZE 4096 // Buffer for recording the frames 184 | 185 | #define EPROMSIZE 4096 // Size of EEPROM in your Arduino chip. For ESP8266 size is 4096 186 | 187 | // defining PINs set for ESP8266 - WEMOS D1 MINI module 188 | 189 | byte sck = 14; // GPIO 14 190 | 191 | byte miso = 12; // GPIO 12 192 | 193 | byte mosi = 13; // GPIO 13 194 | 195 | byte ss = 15; // GPIO 15 196 | 197 | int gdo0 = 5; // GPIO 5 198 | 199 | int gdo2 = 4; // GPIO 4 200 | 201 | ---- 202 | 203 | Example for Arduino Nano board - ATTENTION ! I HAVE TESTED THIS BOARD AND IT REQUIRES TTL LOGIC COVERTER 5V<->3.3V TXS0108E ESPECIALLY FOR BOARD CC1101 : E07-M1101D, otherwise it does not work 204 | 205 | #define RECORDINGBUFFERSIZE 1024 // Buffer for recording the frames 206 | 207 | #define EPROMSIZE 1024 // Size of EEPROM in your Arduino chip. 208 | 209 | // defining PINs for Arduino NANO 210 | 211 | byte sck = 16; // D13 212 | 213 | byte miso = 15; // D12 214 | 215 | byte mosi = 14; // D11 216 | 217 | byte ss = 13; // D10 218 | 219 | int gdo0 = 9; // D6 220 | 221 | int gdo2 = 5; // D2 222 | 223 | ---- 224 | 225 | Example for Raspberry Pi Pico / RP2040 board - ATTENTION ! I HAVE TESTED THIS BOARD AND IT USES 3.3V LOGIC 226 | 227 | #define RECORDINGBUFFERSIZE 4096 // Buffer for recording the frames 228 | 229 | #define EPROMSIZE 512 // Size of EEPROM in your Arduino chip. 230 | 231 | // defining PINs for Raspberry Pi Pico 232 | 233 | // see pinout: https://cdn-learn.adafruit.com/assets/assets/000/099/339/original/raspberry_pi_Pico-R3-Pinout-narrow.png 234 | 235 | byte sck = 2; 236 | 237 | byte miso = 4; 238 | 239 | byte mosi = 3; 240 | 241 | byte ss = 5; 242 | 243 | int gdo0 = 7; 244 | 245 | int gdo2 = 6; 246 | 247 | 248 | Attention ! There may be different SPI pins set for your Pico board : 249 | 250 | byte miso = 16; 251 | 252 | byte ss = 17; 253 | 254 | byte mosi = 19; 255 | 256 | byte sck = 18; 257 | 258 | 259 | 260 | 261 | -------------------------------------------------------------------------------------- 262 | First version of this project was presented in this video : https://youtu.be/iPVckkTjsd0 263 | Using Universal Radio Hacker and my CC1101-tool is presented in following video : https://youtu.be/mdkEK_wmWJA 264 | -------------------------------------------------------------------------------------- 265 | 266 | 267 | Change log : 268 | 269 | 08.06.2023 : optimized CLI 270 | - removed unnecessary parameters for commands RX, TX, JAM. 271 | - changed command JAMM to JAM. 272 | - optimized output of RX command - now will print directly hex values with no description when sniffer enabled. 273 | - corrected reaction for CR/LF when using with "Serial Terminal" application on USB OTG port on Android phones 274 | - Added CHAT mode, if you have couple of these devices you may use it as and IRC like communicator on selected band/modulation/frequency/channel... 275 | 276 | 277 | 09.06.2023 : added RAW mode as in Flipper Zero 278 | - rxraw "interval microseconds", 279 | - recraw "interval usec", 280 | - playraw "interval usec", 281 | - showraw - for record & replay attacking. 282 | - buffer of 1536 bytes is used to store recording (in ATMEGA32U4, 1024 for Atmega Mega/Uno/Nano, 4096 or more for ESP32 boards). 283 | - after playing with RAW mode please always enter "init" command to restart CC1101 chip. Don't worry about Low Memory warning during Arduino compilation it will work JUST FINE.. Enjoy :-) 284 | 285 | 286 | 287 | 10.06.2023 : 288 | - added Arduino Mega/Nano/Uno version which requires TTL logic converter for 3.3V - TXS0108E. 289 | - added ESP32 version. 290 | - changed RECRAW command to start recording RAW signal once something appears over the radio. 291 | - added command ADDRAW to enable manual composition of the signal in the buffer (by copying hex number chunks from Universal Radio Hacker tool for example). 292 | - added option SCAN to find a peak frequency for recording/jamming.. 293 | 294 | 17.06.2023 : 295 | - added SAVE function to store recorded frames buffer into non-volatile EEPROM memory of the Arduino chip 296 | - added LOAD function to restore recorded frames from non-volatile memory and put them into recording buffer for replaying. 297 | - added SHOWBIT command to display RAW data from the buffer as stream of bits. 298 | - corrected ESP32 version which has problem with changing (char *) type to (byte *) due to different C++ compiler for ESP32 boards 299 | 300 | 18.06.2023 : 301 | - updated bit storage order in PLAYRAW, RXRAW, RECRAW commands to match the type used in Universal Radio Hacker tool : https://github.com/jopohl/urh 302 | 303 | 30.06.2023 304 | - added debug message during CC1101 startup 305 | - corrected EEPROM usage for ESP32 chip based Arduino - ESP32 has 512 bytes, ESP8266 has 4096 bytes 306 | - added ESP32-WROOM version ( I have tested it succesfully with my own board ) 307 | - added ESP8266 - WEMOS D1 Mini version 308 | 309 | 08.07.2023 310 | - corrected ESP8266 version, WDT watchdog restarts MOSTLY solved (this single core chip is heavy loaded with internal WiFI procedures and TCP IP stack). Code was successfuly tested on WEMOS D1 MINI clone and D-SUN CC1101 board. The advantage of using WEMOS D1 MINI biggest size of FLASH simulated EEPROM for RF sequences storage. ESP32 chips are dual core and my code runs better. 311 | 312 | 13.07.2023 313 | - changed default data rate for Packet Mode from 1.2Kbaud to 9.6Kbaud which removes problems with Watchdog Restart on ESP8266 board and improves stability 314 | 315 | 27.07.2023: 316 | - rp2040 board added 317 | 318 | 18.08.2023: 319 | - added command BRUTE for brute force attack on some DIP switches based garage gates. Sometimes the code hangs after executing full brute force cycle. Trying to find the root cause... Another bad news is that I have reached full FLASH capacity of ATMEGA32U4 so no more extensions are possible to the code for this chip. 320 | 321 | 02.09.2023 322 | - WIFI client mode for ESP8266 board added - there is a separate source code version wifi in the name. Before uploading the code you need to assign an IP address to the module , put correct default gateway as well as configure SSID of your WIFI router and the WIFI password in the code like below (defaults are for Android tethering access point). Wifi client mode can be used to extend widely the range between CC1101 device and you PC/smartphone which is used to control this board. Beetween them you have external Access Point that will be "man in the middle" to extend the WIFI range... 323 | - The ESP8266 board connects to your WIFI router/access point (you need 2nd mobile phone which will serve as an accesspoint for your own phone and ESP8266 board) and you do a TELNET to its IP address 192.168.43.100 from the other smartphone : 324 | 325 | IPAddress ip(192, 168, 43, 100); // Local Static IP address 326 | 327 | IPAddress gateway(192, 168, 43, 1); // Gateway IP address 328 | 329 | IPAddress subnet(255, 255, 255, 0); // Subnet Mask 330 | 331 | const char ssid[] = "AndroidAP"; // Change to your Router SSID 332 | 333 | const char password[] = "password"; // Change to your Router Password 334 | 335 | Example scenario for WIFI / telnet connection when ESP8266 is WIFI client : 336 | ESP8266 + CC1101 WIFI client at 192.168.43.100 <-> Smartphone #1 wifi tethering / wifi access point at 192.168.43.1 <-> Smartphone #2 WIFI client / Connectbot - telnet to 192.168.43.100. 337 | ATTENTION ! When using WIFI versions I recommend to set ESP8266 CPU speed to 160 MHz : in arduino IDE - go to Tools, in dropdown list select "CPU Frequency 160MHz" instead of "CPU Frequency 80MHz". 338 | 339 | 340 | 341 | 08.09.2023 342 | - WIFI Access Point mode to ESP8266 board added - there is a separate source code version with wifi-ap in the name. Before uploading the code you can change an IP address to the module and SSID for your ESP8266 board. Default is SSID "cc1101" and IP address for telnet "192.168.1.100". This is the simplest scenario, use Connectbot and Telnet protocol to connect to CC1101 board over TCP port 23. ATTENTION ! When using WIFI versions I recommend to set ESP8266 CPU speed to 160 MHz : in arduino IDE - go to Tools, in dropdown list select "CPU Frequency 160MHz" instead of "CPU Frequency 80MHz". 343 | 344 | 345 | 22.11.2023 346 | Corrected bug in showbit() function, all the thanks go to jps1x2. 347 | 348 | 349 | 08.02.2024 350 | Corrected bug in scan() function (not accepting MHz fractions in frequency range), all the thanks go to chris4soft 351 | 352 | 353 | 354 | Known Bugs : sometimes RX command does not work correctly after many big frames have been received (in packet mode, not in async mode). This may be due to some memory leak in SmartRC library. Still checking what is the reason. Keep attention to putting an argument to rxraw, playraw command - otherwise ESP8266 are restarting themselves when wifi in use (stack overflow). 355 | 356 | 357 | -------------------------------------------------------------------------------- /SmartRC-CC1101-Driver-Lib-master.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcore1976/cc1101-tool/0322f973d4c2d871154a308abb1e669cecd98cba/SmartRC-CC1101-Driver-Lib-master.zip -------------------------------------------------------------------------------- /TXS0108E_CC1101.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcore1976/cc1101-tool/0322f973d4c2d871154a308abb1e669cecd98cba/TXS0108E_CC1101.png -------------------------------------------------------------------------------- /Wiring_CC1101.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcore1976/cc1101-tool/0322f973d4c2d871154a308abb1e669cecd98cba/Wiring_CC1101.png -------------------------------------------------------------------------------- /arduino-esp32-en-latest-doc.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcore1976/cc1101-tool/0322f973d4c2d871154a308abb1e669cecd98cba/arduino-esp32-en-latest-doc.pdf -------------------------------------------------------------------------------- /arduino-esp8266-readthedocs-io-en-latest.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcore1976/cc1101-tool/0322f973d4c2d871154a308abb1e669cecd98cba/arduino-esp8266-readthedocs-io-en-latest.pdf -------------------------------------------------------------------------------- /arduino-pro-micro-pinout.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcore1976/cc1101-tool/0322f973d4c2d871154a308abb1e669cecd98cba/arduino-pro-micro-pinout.png -------------------------------------------------------------------------------- /cc1101-arduino-pro-micro-tool.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcore1976/cc1101-tool/0322f973d4c2d871154a308abb1e669cecd98cba/cc1101-arduino-pro-micro-tool.png -------------------------------------------------------------------------------- /cc1101-tool-arduino-nano.ino: -------------------------------------------------------------------------------- 1 | // 2 | // CC1101 interactive terminal tool 3 | // allows for sending / receiving data over serial port 4 | // on selected radio channel, modulation, .. 5 | // 6 | // (C) Adam Loboda '2023 , adam.loboda@wp.pl 7 | // 8 | // based on great SmartRC library by Little_S@tan 9 | // Please download ZIP from 10 | // https://github.com/LSatan/SmartRC-CC1101-Driver-Lib 11 | // and attach it as ZIP library for Arduino 12 | // 13 | // Also uses Arduino Command Line interpreter by Edgar Bonet 14 | // from https://gist.github.com/edgar-bonet/607b387260388be77e96 15 | // 16 | // This code will ONLY work with Arduino Nano board 17 | // 18 | 19 | #include 20 | #include 21 | #include 22 | 23 | #define CCBUFFERSIZE 64 24 | #define RECORDINGBUFFERSIZE 1024 // Buffer for recording the frames. ATMEGA328 has only 2048 SRAM storage 25 | #define EPROMSIZE 1024 // Size of EEPROM in your Arduino chip. ATMEGA328 has 1024 26 | #define BUF_LENGTH 128 // Buffer for the incoming command. 27 | 28 | // defining PINs for Arduino NANO 29 | byte sck = 16; // D13 30 | byte miso = 15; // D12 31 | byte mosi = 14; // D11 32 | byte ss = 13; // D10 33 | byte gdo0 = 9; // D6 34 | byte gdo2 = 5; // D2 35 | 36 | // position in big recording buffer 37 | int bigrecordingbufferpos = 0; 38 | 39 | // number of frames in big recording buffer 40 | int framesinbigrecordingbuffer = 0; 41 | 42 | // check if CLI receiving mode enabled 43 | int receivingmode = 0; 44 | 45 | // check if CLI jamming mode enabled 46 | int jammingmode = 0; 47 | 48 | // check if CLI recording mode enabled 49 | int recordingmode = 0; 50 | 51 | // check if CLI chat mode enabled 52 | int chatmode = 0; 53 | 54 | static bool do_echo = true; 55 | 56 | // buffer for receiving CC1101 57 | byte ccreceivingbuffer[CCBUFFERSIZE] = {0}; 58 | 59 | // buffer for sending CC1101 60 | byte ccsendingbuffer[CCBUFFERSIZE] = {0}; 61 | 62 | // buffer for recording and replaying of many frames 63 | byte bigrecordingbuffer[RECORDINGBUFFERSIZE] = {0}; 64 | 65 | // buffer for hex to ascii conversions 66 | byte textbuffer[BUF_LENGTH]; 67 | 68 | 69 | 70 | // convert char table to string with hex numbers 71 | void asciitohex(byte *ascii_ptr, byte *hex_ptr,int len) 72 | { 73 | byte i,j,k; 74 | for(i = 0; i < len; i++) 75 | { 76 | // high byte first 77 | j = ascii_ptr[i] / 16; 78 | if (j>9) 79 | { k = j - 10 + 65; } 80 | else 81 | { k = j + 48; } 82 | hex_ptr[2*i] = k ; 83 | // low byte second 84 | j = ascii_ptr[i] % 16; 85 | if (j>9) 86 | { k = j - 10 + 65; } 87 | else 88 | { k = j + 48; } 89 | hex_ptr[(2*i)+1] = k ; 90 | }; 91 | hex_ptr[(2*i)+2] = '\0' ; 92 | } 93 | 94 | 95 | // convert string with hex numbers to array of bytes 96 | void hextoascii(byte *ascii_ptr, byte *hex_ptr,int len) 97 | { 98 | byte i,j; 99 | for(i = 0; i < (len/2); i++) 100 | { 101 | j = hex_ptr[i*2]; 102 | if ((j>47) && (j<58)) ascii_ptr[i] = (j - 48) * 16; 103 | if ((j>64) && (j<71)) ascii_ptr[i] = (j - 55) * 16; 104 | if ((j>96) && (j<103)) ascii_ptr[i] = (j - 87) * 16; 105 | j = hex_ptr[i*2+1]; 106 | if ((j>47) && (j<58)) ascii_ptr[i] = ascii_ptr[i] + (j - 48); 107 | if ((j>64) && (j<71)) ascii_ptr[i] = ascii_ptr[i] + (j - 55); 108 | if ((j>96) && (j<103)) ascii_ptr[i] = ascii_ptr[i] + (j - 87); 109 | }; 110 | ascii_ptr[i++] = '\0' ; 111 | } 112 | 113 | // Initialize CC1101 board with default settings, you may change your preferences here 114 | static void cc1101initialize(void) 115 | { 116 | // initializing library with custom pins selected 117 | ELECHOUSE_cc1101.setSpiPin(sck, miso, mosi, ss); 118 | ELECHOUSE_cc1101.setGDO(gdo0, gdo2); 119 | 120 | // Main part to tune CC1101 with proper frequency, modulation and encoding 121 | ELECHOUSE_cc1101.Init(); // must be set to initialize the cc1101! 122 | ELECHOUSE_cc1101.setGDO0(gdo0); // set lib internal gdo pin (gdo0). Gdo2 not use for this example. 123 | ELECHOUSE_cc1101.setCCMode(1); // set config for internal transmission mode. value 0 is for RAW recording/replaying 124 | ELECHOUSE_cc1101.setModulation(2); // set modulation mode. 0 = 2-FSK, 1 = GFSK, 2 = ASK/OOK, 3 = 4-FSK, 4 = MSK. 125 | ELECHOUSE_cc1101.setMHZ(433.92); // Here you can set your basic frequency. The lib calculates the frequency automatically (default = 433.92).The cc1101 can: 300-348 MHZ, 387-464MHZ and 779-928MHZ. Read More info from datasheet. 126 | ELECHOUSE_cc1101.setDeviation(47.60); // Set the Frequency deviation in kHz. Value from 1.58 to 380.85. Default is 47.60 kHz. 127 | ELECHOUSE_cc1101.setChannel(0); // Set the Channelnumber from 0 to 255. Default is cahnnel 0. 128 | ELECHOUSE_cc1101.setChsp(199.95); // The channel spacing is multiplied by the channel number CHAN and added to the base frequency in kHz. Value from 25.39 to 405.45. Default is 199.95 kHz. 129 | ELECHOUSE_cc1101.setRxBW(812.50); // Set the Receive Bandwidth in kHz. Value from 58.03 to 812.50. Default is 812.50 kHz. 130 | ELECHOUSE_cc1101.setDRate(9.6); // Set the Data Rate in kBaud. Value from 0.02 to 1621.83. Default is 99.97 kBaud! 131 | ELECHOUSE_cc1101.setPA(10); // Set TxPower. The following settings are possible depending on the frequency band. (-30 -20 -15 -10 -6 0 5 7 10 11 12) Default is max! 132 | ELECHOUSE_cc1101.setSyncMode(2); // Combined sync-word qualifier mode. 0 = No preamble/sync. 1 = 16 sync word bits detected. 2 = 16/16 sync word bits detected. 3 = 30/32 sync word bits detected. 4 = No preamble/sync, carrier-sense above threshold. 5 = 15/16 + carrier-sense above threshold. 6 = 16/16 + carrier-sense above threshold. 7 = 30/32 + carrier-sense above threshold. 133 | ELECHOUSE_cc1101.setSyncWord(211, 145); // Set sync word. Must be the same for the transmitter and receiver. Default is 211,145 (Syncword high, Syncword low) 134 | ELECHOUSE_cc1101.setAdrChk(0); // Controls address check configuration of received packages. 0 = No address check. 1 = Address check, no broadcast. 2 = Address check and 0 (0x00) broadcast. 3 = Address check and 0 (0x00) and 255 (0xFF) broadcast. 135 | ELECHOUSE_cc1101.setAddr(0); // Address used for packet filtration. Optional broadcast addresses are 0 (0x00) and 255 (0xFF). 136 | ELECHOUSE_cc1101.setWhiteData(0); // Turn data whitening on / off. 0 = Whitening off. 1 = Whitening on. 137 | ELECHOUSE_cc1101.setPktFormat(0); // Format of RX and TX data. 0 = Normal mode, use FIFOs for RX and TX. 1 = Synchronous serial mode, Data in on GDO0 and data out on either of the GDOx pins. 2 = Random TX mode; sends random data using PN9 generator. Used for test. Works as normal mode, setting 0 (00), in RX. 3 = Asynchronous serial mode, Data in on GDO0 and data out on either of the GDOx pins. 138 | ELECHOUSE_cc1101.setLengthConfig(1); // 0 = Fixed packet length mode. 1 = Variable packet length mode. 2 = Infinite packet length mode. 3 = Reserved 139 | ELECHOUSE_cc1101.setPacketLength(0); // Indicates the packet length when fixed packet length mode is enabled. If variable packet length mode is used, this value indicates the maximum packet length allowed. 140 | ELECHOUSE_cc1101.setCrc(0); // 1 = CRC calculation in TX and CRC check in RX enabled. 0 = CRC disabled for TX and RX. 141 | ELECHOUSE_cc1101.setCRC_AF(0); // Enable automatic flush of RX FIFO when CRC is not OK. This requires that only one packet is in the RXIFIFO and that packet length is limited to the RX FIFO size. 142 | ELECHOUSE_cc1101.setDcFilterOff(0); // Disable digital DC blocking filter before demodulator. Only for data rates ≤ 250 kBaud The recommended IF frequency changes when the DC blocking is disabled. 1 = Disable (current optimized). 0 = Enable (better sensitivity). 143 | ELECHOUSE_cc1101.setManchester(0); // Enables Manchester encoding/decoding. 0 = Disable. 1 = Enable. 144 | ELECHOUSE_cc1101.setFEC(0); // Enable Forward Error Correction (FEC) with interleaving for packet payload (Only supported for fixed packet length mode. 0 = Disable. 1 = Enable. 145 | ELECHOUSE_cc1101.setPRE(0); // Sets the minimum number of preamble bytes to be transmitted. Values: 0 : 2, 1 : 3, 2 : 4, 3 : 6, 4 : 8, 5 : 12, 6 : 16, 7 : 24 146 | ELECHOUSE_cc1101.setPQT(0); // Preamble quality estimator threshold. The preamble quality estimator increases an internal counter by one each time a bit is received that is different from the previous bit, and decreases the counter by 8 each time a bit is received that is the same as the last bit. A threshold of 4∙PQT for this counter is used to gate sync word detection. When PQT=0 a sync word is always accepted. 147 | ELECHOUSE_cc1101.setAppendStatus(0); // When enabled, two status bytes will be appended to the payload of the packet. The status bytes contain RSSI and LQI values, as well as CRC OK. 148 | } 149 | 150 | 151 | // Execute a complete CC1101 command. 152 | 153 | static void exec(char *cmdline) 154 | { 155 | 156 | char *command = strsep(&cmdline, " "); 157 | int setting, setting2, len; 158 | uint16_t brute, poweroftwo; 159 | byte j, k; 160 | float settingf1; 161 | float settingf2; 162 | // variables for frequency scanner 163 | float freq; 164 | long compare_freq; 165 | float mark_freq; 166 | int rssi; 167 | int mark_rssi=-100; 168 | 169 | // identification of the command & actions 170 | 171 | if (strcmp_P(command, PSTR("help")) == 0) { 172 | Serial.println(F( 173 | "setmodulation : Set modulation mode. 0 = 2-FSK, 1 = GFSK, 2 = ASK/OOK, 3 = 4-FSK, 4 = MSK.\r\n\r\n" 174 | "setmhz : Here you can set your basic frequency. default = 433.92).The cc1101 can: 300-348 MHZ, 387-464MHZ and 779-928MHZ.\r\n\r\n" 175 | "setdeviation : Set the Frequency deviation in kHz. Value from 1.58 to 380.85. Default is 47.60 kHz.\r\n\r\n" 176 | "setchannel : Set the Channelnumber from 0 to 255. Default is cahnnel 0.\r\n\r\n" 177 | "setchsp : The channel spacing is multiplied by the channel number CHAN and added to the base frequency in kHz. Value from 25.39 to 405.45. Default is 199.95 kHz. \r\n\r\n" 178 | "setrxbw : Set the Receive Bandwidth in kHz. Value from 58.03 to 812.50. Default is 812.50 kHz.\r\n" 179 | "setdrate : Set the Data Rate in kBaud. Value from 0.02 to 1621.83. Default is 99.97 kBaud!\r\n\r\n" 180 | "setpa : Set RF transmission power. The following settings are possible depending on the frequency band. (-30 -20 -15 -10 -6 0 5 7 10 11 12) Default is max!\r\n\r\n" 181 | "setsyncmode : Combined sync-word qualifier mode. 0 = No preamble/sync. 1 = 16 sync word bits detected. 2 = 16/16 sync word bits detected. 3 = 30/32 sync word bits detected. 4 = No preamble/sync, carrier-sense above threshold. 5 = 15/16 + carrier-sense above threshold. 6 = 16/16 + carrier-sense above threshold. 7 = 30/32 + carrier-sense above threshold.\r\n" 182 | )); 183 | Serial.println(F( 184 | "setsyncword : Set sync word. Must be the same for the transmitter and receiver. (Syncword high, Syncword low) Default is 211,145\r\n\r\n" 185 | "setadrchk
: Controls address check configuration of received packages. 0 = No address check. 1 = Address check, no broadcast. 2 = Address check and 0 (0x00) broadcast. 3 = Address check and 0 (0x00) and 255 (0xFF) broadcast.\r\n\r\n" 186 | "setaddr
: Address used for packet filtration. Optional broadcast addresses are 0 (0x00) and 255 (0xFF).\r\n\r\n" 187 | "setwhitedata : Turn data whitening on / off. 0 = Whitening off. 1 = Whitening on.\r\n\r\n" 188 | "setpktformat : Format of RX and TX data. 0 = Normal mode, use FIFOs for RX and TX. 1 = Synchronous serial mode, Data in on GDO0 and data out on either of the GDOx pins. 2 = Random TX mode; sends random data using PN9 generator. 3 = Asynchronous serial mode\r\n\r\n" 189 | "setlengthconfig : Set packet Length mode : 0 = Fixed packet length mode. 1 = Variable packet length mode. 2 = Infinite packet length mode. 3 = Reserved \r\n\r\n" 190 | "setpacketlength : Indicates the packet length when fixed packet length mode is enabled. If variable packet length mode is used, this value indicates the maximum packet length allowed.\r\n\r\n" 191 | "setcrc : Switches on/of CRC calculation and check. 1 = CRC calculation in TX and CRC check in RX enabled. 0 = CRC disabled for TX and RX.\r\n\r\n" 192 | "setcrcaf : Enable automatic flush of RX FIFO when CRC is not OK. This requires that only one packet is in the RXIFIFO and that packet length is limited to the RX FIFO size.\r\n" 193 | )); 194 | Serial.println(F( 195 | "setdcfilteroff : Disable digital DC blocking filter before demodulator. Only for data rates ≤ 250 kBaud The recommended IF frequency changes when the DC blocking is disabled. 1 = Disable (current optimized). 0 = Enable (better sensitivity).\r\n\r\n" 196 | "setmanchester : Enables Manchester encoding/decoding. 0 = Disable. 1 = Enable.\r\n\r\n" 197 | "setfec : Enable Forward Error Correction (FEC) with interleaving for packet payload (Only supported for fixed packet length mode. 0 = Disable. 1 = Enable.\r\n\r\n" 198 | "setpre : Sets the minimum number of preamble bytes to be transmitted. Values: 0 : 2, 1 : 3, 2 : 4, 3 : 6, 4 : 8, 5 : 12, 6 : 16, 7 : 24\r\n\r\n" 199 | "setpqt : Preamble quality estimator threshold. \r\n\r\n" 200 | "setappendstatus : When enabled, two status bytes will be appended to the payload of the packet. The status bytes contain RSSI and LQI values, as well as CRC OK.\r\n\r\n" 201 | "getrssi : Display quality information about last received frames over RF\r\n\r\n" 202 | "scan : Scan frequency range for the highest signal.\r\n\r\n" 203 | "chat : Enable chat mode between many devices. No exit available, disconnect device to quit\r\n" 204 | )); 205 | Serial.println(F( 206 | "rx : Sniffer. Enable or disable printing of received RF packets on serial terminal.\r\n\r\n" 207 | "tx : Send packet of max 60 bytes over RF\r\n" 208 | "jam : Enable or disable continous jamming on selected band.\r\n\r\n" 209 | "brute : Brute force garage gate with keyword where symbol time is .\r\n\r\n" 210 | "rec : Enable or disable recording frames in the buffer.\r\n\r\n" 211 | "add : Manually add single frame payload (max 64 hex values) to the buffer so it can be replayed\r\n\r\n" 212 | "show : Show content of recording buffer\r\n\r\n" 213 | "flush : Clear the recording buffer\r\n\r\n" 214 | "play : Replay 0 = all frames or N-th recorded frame previously stored in the buffer.\r\n\r\n" 215 | "rxraw : Sniffs radio by sampling with interval and prints received bytes in hex.\r\n\r\n" 216 | "recraw : Recording RAW RF data with sampling interval.\r\n" 217 | )); 218 | Serial.println(F( 219 | "addraw : Manually add chunks (max 60 hex values) to the buffer so they can be further replayed.\r\n\r\n" 220 | "showraw : Showing content of recording buffer in RAW format.\r\n\r\n" 221 | "playraw : Replaying previously recorded RAW RF data with sampling interval.\r\n\r\n" 222 | "showbit : Showing content of recording buffer in RAW format as a stream of bits.\r\n\r\n" 223 | "save : Store recording buffer content in non-volatile memory\r\n\r\n" 224 | "load : Load the content from non-volatile memory to the recording buffer\r\n\r\n" 225 | "echo : Enable or disable Echo on serial terminal. 1 = enabled, 0 = disabled\r\n\r\n" 226 | "x : Stops jamming/receiving/recording packets.\r\n\r\n" 227 | "init : Restarts CC1101 board with default parameters\r\n\r\n" 228 | )); 229 | 230 | // Handling SETMODULATION command 231 | } else if (strcmp_P(command, PSTR("setmodulation")) == 0) { 232 | setting = atoi(cmdline); 233 | ELECHOUSE_cc1101.setModulation(setting); 234 | Serial.print(F("\r\nModulation: ")); 235 | if (setting == 0) { Serial.print(F("2-FSK")); } 236 | else if (setting == 1) { Serial.print(F("GFSK")); } 237 | else if (setting == 2) { Serial.print(F("ASK/OOK")); } 238 | else if (setting == 3) { Serial.print(F("4-FSK")); } 239 | else if (setting == 4) { Serial.print(F("MSK")); }; 240 | Serial.print(F(" \r\n")); 241 | 242 | // Handling SETMHZ command 243 | } else if (strcmp_P(command, PSTR("setmhz")) == 0) { 244 | settingf1 = atof(cmdline); 245 | ELECHOUSE_cc1101.setMHZ(settingf1); 246 | Serial.print(F("\r\nFrequency: ")); 247 | Serial.print(settingf1); 248 | Serial.print(F(" MHz\r\n")); 249 | 250 | // Handling SETDEVIATION command 251 | } else if (strcmp_P(command, PSTR("setdeviation")) == 0) { 252 | settingf1 = atof(cmdline); 253 | ELECHOUSE_cc1101.setDeviation(settingf1); 254 | Serial.print(F("\r\nDeviation: ")); 255 | Serial.print(settingf1); 256 | Serial.print(F(" KHz\r\n")); 257 | 258 | // Handling SETCHANNEL command 259 | } else if (strcmp_P(command, PSTR("setchannel")) == 0) { 260 | setting = atoi(cmdline); 261 | ELECHOUSE_cc1101.setChannel(setting); 262 | Serial.print(F("\r\nChannel:")); 263 | Serial.print(setting); 264 | Serial.print(F("\r\n")); 265 | 266 | // Handling SETCHSP command 267 | } else if (strcmp_P(command, PSTR("setchsp")) == 0) { 268 | settingf1 = atof(cmdline); 269 | ELECHOUSE_cc1101.setChsp(settingf1); 270 | Serial.print(F("\r\nChann spacing: ")); 271 | Serial.print(settingf1); 272 | Serial.print(F(" kHz\r\n")); 273 | 274 | // Handling SETRXBW command 275 | } else if (strcmp_P(command, PSTR("setrxbw")) == 0) { 276 | settingf1 = atof(cmdline); 277 | ELECHOUSE_cc1101.setRxBW(settingf1); 278 | Serial.print(F("\r\nRX bandwidth: ")); 279 | Serial.print(settingf1); 280 | Serial.print(F(" kHz \r\n")); 281 | 282 | // Handling SETDRATE command 283 | } else if (strcmp_P(command, PSTR("setdrate")) == 0) { 284 | settingf1 = atof(cmdline); 285 | ELECHOUSE_cc1101.setDRate(settingf1); 286 | Serial.print(F("\r\nDatarate: ")); 287 | Serial.print(settingf1); 288 | Serial.print(F(" kbaud\r\n")); 289 | 290 | // Handling SETPA command 291 | } else if (strcmp_P(command, PSTR("setpa")) == 0) { 292 | setting = atoi(cmdline); 293 | ELECHOUSE_cc1101.setPA(setting); 294 | Serial.print(F("\r\nTX PWR: ")); 295 | Serial.print(setting); 296 | Serial.print(F(" dBm\r\n")); 297 | 298 | // Handling SETSYNCMODE command 299 | } else if (strcmp_P(command, PSTR("setsyncmode")) == 0) { 300 | int setting = atoi(cmdline); 301 | ELECHOUSE_cc1101.setSyncMode(setting); 302 | Serial.print(F("\r\nSynchronization: ")); 303 | if (setting == 0) { Serial.print(F("No preamble")); } 304 | else if (setting == 1) { Serial.print(F("16 sync bits")); } 305 | else if (setting == 2) { Serial.print(F("16/16 sync bits")); } 306 | else if (setting == 3) { Serial.print(F("30/32 sync bits")); } 307 | else if (setting == 4) { Serial.print(F("No preamble/sync, carrier-sense")); } 308 | else if (setting == 5) { Serial.print(F("15/16 + carrier-sense")); } 309 | else if (setting == 6) { Serial.print(F("16/16 + carrier-sense")); } 310 | else if (setting == 7) { Serial.print(F("30/32 + carrier-sense")); }; 311 | Serial.print(F("\r\n")); 312 | 313 | // Handling SETSYNCWORD command 314 | } else if (strcmp_P(command, PSTR("setsyncword")) == 0) { 315 | setting = atoi(strsep(&cmdline, " ")); 316 | setting2 = atoi(cmdline); 317 | ELECHOUSE_cc1101.setSyncWord(setting2, setting); 318 | Serial.print(F("\r\nSynchronization:\r\n")); 319 | Serial.print(F("high = ")); 320 | Serial.print(setting); 321 | Serial.print(F("\r\nlow = ")); 322 | Serial.print(setting2); 323 | Serial.print(F("\r\n")); 324 | 325 | 326 | // Handling SETADRCHK command 327 | } else if (strcmp_P(command, PSTR("setadrchk")) == 0) { 328 | setting = atoi(cmdline); 329 | ELECHOUSE_cc1101.setAdrChk(setting); 330 | Serial.print(F("\r\nAddress checking:")); 331 | if (setting == 0) { Serial.print(F("No adr chk")); } 332 | else if (setting == 1) { Serial.print(F("Adr chk, no bcast")); } 333 | else if (setting == 2) { Serial.print(F("Adr chk and 0 bcast")); } 334 | else if (setting == 3) { Serial.print(F("Adr chk and 0 and FF bcast")); }; 335 | Serial.print(F("\r\n")); 336 | 337 | // Handling SETADDR command 338 | } else if (strcmp_P(command, PSTR("setaddr")) == 0) { 339 | setting = atoi(cmdline); 340 | ELECHOUSE_cc1101.setAddr(setting); 341 | Serial.print(F("\r\nAddress: ")); 342 | Serial.print(setting); 343 | Serial.print(F("\r\n")); 344 | 345 | // Handling SETWHITEDATA command 346 | } else if (strcmp_P(command, PSTR("setwhitedata")) == 0) { 347 | setting = atoi(cmdline); 348 | ELECHOUSE_cc1101.setWhiteData(setting); 349 | Serial.print(F("\r\nWhitening ")); 350 | if (setting == 0) { Serial.print(F("OFF")); } 351 | else if (setting == 1) { Serial.print(F("ON")); } 352 | Serial.print(F("\r\n")); 353 | 354 | // Handling SETPKTFORMAT command 355 | } else if (strcmp_P(command, PSTR("setpktformat")) == 0) { 356 | setting = atoi(cmdline); 357 | ELECHOUSE_cc1101.setPktFormat(setting); 358 | Serial.print(F("\r\nPacket format: ")); 359 | if (setting == 0) { Serial.print(F("Normal mode")); } 360 | else if (setting == 1) { Serial.print(F("Synchronous serial mode")); } 361 | else if (setting == 2) { Serial.print(F("Random TX mode")); } 362 | else if (setting == 3) { Serial.print(F("Asynchronous serial mode")); }; 363 | Serial.print(F("\r\n")); 364 | 365 | // Handling SETLENGTHCONFIG command 366 | } else if (strcmp_P(command, PSTR("setlengthconfig")) == 0) { 367 | setting = atoi(cmdline); 368 | ELECHOUSE_cc1101.setLengthConfig(setting); 369 | Serial.print(F("\r\nPkt length mode: ")); 370 | if (setting == 0) { Serial.print(F("Fixed")); } 371 | else if (setting == 1) { Serial.print(F("Variable")); } 372 | else if (setting == 2) { Serial.print(F("Infinite")); } 373 | else if (setting == 3) { Serial.print(F("Reserved")); }; 374 | Serial.print(F("\r\n")); 375 | 376 | // Handling SETPACKETLENGTH command 377 | } else if (strcmp_P(command, PSTR("setpacketlength")) == 0) { 378 | setting = atoi(cmdline); 379 | ELECHOUSE_cc1101.setPacketLength(setting); 380 | Serial.print(F("\r\nPkt length: ")); 381 | Serial.print(setting); 382 | Serial.print(F(" bytes\r\n")); 383 | 384 | // Handling SETCRC command 385 | } else if (strcmp_P(command, PSTR("setcrc")) == 0) { 386 | setting = atoi(cmdline); 387 | ELECHOUSE_cc1101.setCrc(setting); 388 | Serial.print(F("\r\nCRC checking: ")); 389 | if (setting == 0) { Serial.print(F("Disabled")); } 390 | else if (setting == 1) { Serial.print(F("Enabled")); }; 391 | Serial.print(F("\r\n")); 392 | 393 | // Handling SETCRCAF command 394 | } else if (strcmp_P(command, PSTR("setcrcaf")) == 0) { 395 | setting = atoi(cmdline); 396 | ELECHOUSE_cc1101.setCRC_AF(setting); 397 | Serial.print(F("\r\nCRC Autoflush: ")); 398 | if (setting == 0) { Serial.print(F("Disabled")); } 399 | else if (setting == 1) { Serial.print(F("Enabled")); }; 400 | Serial.print(F("\r\n")); 401 | 402 | // Handling SETDCFILTEROFF command 403 | } else if (strcmp_P(command, PSTR("setdcfilteroff")) == 0) { 404 | setting = atoi(cmdline); 405 | ELECHOUSE_cc1101.setDcFilterOff(setting); 406 | Serial.print(F("\r\nDC filter: ")); 407 | if (setting == 0) { Serial.print(F("Enabled")); } 408 | else if (setting == 1) { Serial.print(F("Disabled")); }; 409 | Serial.print(F("\r\n")); 410 | 411 | // Handling SETMANCHESTER command 412 | } else if (strcmp_P(command, PSTR("setmanchester")) == 0) { 413 | setting = atoi(cmdline); 414 | ELECHOUSE_cc1101.setManchester(setting); 415 | Serial.print(F("\r\nManchester coding: ")); 416 | if (setting == 0) { Serial.print(F("Disabled")); } 417 | else if (setting == 1) { Serial.print(F("Enabled")); }; 418 | Serial.print(F("\r\n")); 419 | 420 | // Handling SETFEC command 421 | } else if (strcmp_P(command, PSTR("setfec")) == 0) { 422 | setting = atoi(cmdline); 423 | ELECHOUSE_cc1101.setFEC(setting); 424 | Serial.print(F("\r\nForward Error Correction: ")); 425 | if (setting == 0) { Serial.print(F("Disabled")); } 426 | else if (setting == 1) { Serial.print(F("Enabled")); }; 427 | Serial.print(F("\r\n")); 428 | 429 | // Handling SETPRE command 430 | } else if (strcmp_P(command, PSTR("setpre")) == 0) { 431 | setting = atoi(cmdline); 432 | ELECHOUSE_cc1101.setPRE(setting); 433 | Serial.print(F("\r\nMinimum preamble bytes:")); 434 | Serial.print(setting); 435 | Serial.print(F(" means 0 = 2 bytes, 1 = 3b, 2 = 4b, 3 = 6b, 4 = 8b, 5 = 12b, 6 = 16b, 7 = 24 bytes\r\n")); 436 | Serial.print(F("\r\n")); 437 | 438 | 439 | // Handling SETPQT command 440 | } else if (strcmp_P(command, PSTR("setpqt")) == 0) { 441 | setting = atoi(cmdline); 442 | ELECHOUSE_cc1101.setPQT(setting); 443 | Serial.print(F("\r\nPQT: ")); 444 | Serial.print(setting); 445 | Serial.print(F("\r\n")); 446 | 447 | // Handling SETAPPENDSTATUS command 448 | } else if (strcmp_P(command, PSTR("setappendstatus")) == 0) { 449 | setting = atoi(cmdline); 450 | ELECHOUSE_cc1101.setAppendStatus(setting); 451 | Serial.print(F("\r\nStatus bytes appending: ")); 452 | if (setting == 0) { Serial.print(F("Enabled")); } 453 | else if (setting == 1) { Serial.print(F("Disabled")); }; 454 | Serial.print(F("\r\n")); 455 | 456 | // Handling GETRSSI command 457 | } else if (strcmp_P(command, PSTR("getrssi")) == 0) { 458 | //Rssi Level in dBm 459 | Serial.print(F("Rssi: ")); 460 | Serial.println(ELECHOUSE_cc1101.getRssi()); 461 | //Link Quality Indicator 462 | Serial.print(F(" LQI: ")); 463 | Serial.println(ELECHOUSE_cc1101.getLqi()); 464 | Serial.print(F("\r\n")); 465 | 466 | // Handling RX command 467 | } else if (strcmp_P(command, PSTR("rx")) == 0) { 468 | Serial.print(F("\r\nReceiving and printing RF packet changed to ")); 469 | if (receivingmode == 1) { 470 | receivingmode = 0; 471 | Serial.print(F("Disabled")); } 472 | else if (receivingmode == 0) 473 | { ELECHOUSE_cc1101.SetRx(); 474 | Serial.print(F("Enabled")); 475 | receivingmode = 1; 476 | jammingmode = 0; 477 | recordingmode = 0; 478 | }; 479 | Serial.print(F("\r\n")); 480 | 481 | 482 | // Handling CHAT command 483 | } else if (strcmp_P(command, PSTR("chat")) == 0) { 484 | Serial.print(F("\r\nEntering chat mode:\r\n\r\n")); 485 | if (chatmode == 0) 486 | { 487 | chatmode = 1; 488 | jammingmode = 0; 489 | receivingmode = 0; 490 | recordingmode = 0; 491 | }; 492 | 493 | 494 | // Handling JAM command 495 | } else if (strcmp_P(command, PSTR("jam")) == 0) { 496 | Serial.print(F("\r\nJamming changed to ")); 497 | if (jammingmode == 1) 498 | { Serial.print(F("Disabled")); 499 | jammingmode = 0; 500 | } 501 | else if (jammingmode == 0) 502 | { 503 | Serial.print(F("Enabled")); 504 | jammingmode = 1; 505 | receivingmode = 0; }; 506 | Serial.print(F("\r\n")); 507 | 508 | 509 | // handling BRUTE command 510 | } else if (strcmp_P(command, PSTR("brute")) == 0) { 511 | 512 | // take interval period for sampling 513 | setting = atoi(strsep(&cmdline, " ")); 514 | // take number of bits for brute forcing 515 | setting2 = atoi(cmdline); 516 | // calculate power of 2 upon setting 517 | poweroftwo = 1 << setting2; 518 | 519 | if (setting>0) 520 | { 521 | // setup async mode on CC1101 and go into TX mode 522 | // with GDO0 pin processing 523 | ELECHOUSE_cc1101.setCCMode(0); 524 | ELECHOUSE_cc1101.setPktFormat(3); 525 | ELECHOUSE_cc1101.SetTx(); 526 | 527 | //start playing RF with setting GDO0 bit state with bitbanging 528 | Serial.print(F("\r\nStarting Brute Forcing press any key to stop...\r\n")); 529 | pinMode(gdo0, OUTPUT); 530 | 531 | for (brute = 0; brute < poweroftwo ; brute++) 532 | { 533 | for(int k = 0; k < 5; k++) // sending 5 times each code 534 | { 535 | for(int j = (setting2 - 1); j > -1; j--) // j bits in a value brute 536 | { 537 | digitalWrite(gdo0, bitRead(brute, j)); // Set GDO0 according to actual brute force value 538 | delayMicroseconds(setting); // delay for selected sampling interval 539 | }; // end of J loop 540 | }; // end of K loop 541 | // checking if key pressed 542 | if (Serial.available()) break; 543 | }; 544 | 545 | 546 | Serial.print(F("\r\nBrute forcing complete.\r\n\r\n")); 547 | 548 | // setting normal pkt format again 549 | ELECHOUSE_cc1101.setCCMode(1); 550 | ELECHOUSE_cc1101.setPktFormat(0); 551 | ELECHOUSE_cc1101.SetTx(); 552 | // pinMode(gdo0pin, INPUT); 553 | } // end of IF 554 | else { Serial.print(F("Wrong parameters.\r\n")); }; 555 | 556 | 557 | // Handling TX command 558 | } else if (strcmp_P(command, PSTR("tx")) == 0) { 559 | // convert hex array to set of bytes 560 | if ((strlen(cmdline)<=120) && (strlen(cmdline)>0) ) 561 | { 562 | hextoascii((byte *)textbuffer, cmdline, strlen(cmdline)); 563 | memcpy(ccsendingbuffer, textbuffer, strlen(cmdline)/2 ); 564 | ccsendingbuffer[strlen(cmdline)/2] = 0x00; 565 | Serial.print("\r\nTransmitting RF packets.\r\n"); 566 | // send these data to radio over CC1101 567 | ELECHOUSE_cc1101.SendData(ccsendingbuffer, (byte)(strlen(cmdline)/2)); 568 | // for DEBUG only 569 | asciitohex((byte *)ccsendingbuffer, (byte *)textbuffer, strlen(cmdline)/2 ); 570 | Serial.print(F("Sent frame: ")); 571 | Serial.print((char *)textbuffer); 572 | Serial.print(F("\r\n")); } 573 | else { Serial.print(F("Wrong parameters.\r\n")); }; 574 | 575 | 576 | 577 | // handling RECRAW command 578 | } else if (strcmp_P(command, PSTR("recraw")) == 0) { 579 | // take interval period for samplink 580 | setting = atoi(cmdline); 581 | if (setting>0) 582 | { 583 | // setup async mode on CC1101 with GDO0 pin processing 584 | ELECHOUSE_cc1101.setCCMode(0); 585 | ELECHOUSE_cc1101.setPktFormat(3); 586 | ELECHOUSE_cc1101.SetRx(); 587 | 588 | //start recording to the buffer with bitbanging of GDO0 pin state 589 | Serial.print(F("\r\nWaiting for radio signal to start RAW recording...\r\n")); 590 | pinMode(gdo0, INPUT); 591 | 592 | // waiting for some data first or serial port signal 593 | // while (!Serial.available() || (digitalRead(gdo0) == LOW) ); 594 | while ( digitalRead(gdo0) == LOW ); 595 | 596 | // start capturing 597 | for (int i=0; i -1; j--) // 8 bits in a byte 601 | { 602 | bitWrite(receivedbyte, j, digitalRead(gdo0)); // Capture GDO0 state into the byte 603 | delayMicroseconds(setting); // delay for selected sampling interval 604 | }; 605 | // store the output into recording buffer 606 | bigrecordingbuffer[i] = receivedbyte; 607 | } 608 | Serial.print(F("\r\nRecording RAW data complete.\r\n\r\n")); 609 | // setting normal pkt format again 610 | ELECHOUSE_cc1101.setCCMode(1); 611 | ELECHOUSE_cc1101.setPktFormat(0); 612 | ELECHOUSE_cc1101.SetRx(); 613 | } 614 | else { Serial.print(F("Wrong parameters.\r\n")); }; 615 | 616 | // handling RXRAW command - sniffer 617 | } else if (strcmp_P(command, PSTR("rxraw")) == 0) { 618 | // take interval period for samplink 619 | setting = atoi(cmdline); 620 | if (setting>0) 621 | { 622 | // setup async mode on CC1101 with GDO0 pin processing 623 | ELECHOUSE_cc1101.setCCMode(0); 624 | ELECHOUSE_cc1101.setPktFormat(3); 625 | ELECHOUSE_cc1101.SetRx(); 626 | //start recording to the buffer with bitbanging of GDO0 pin state 627 | Serial.print(F("\r\nSniffer enabled...\r\n")); 628 | pinMode(gdo0, INPUT); 629 | 630 | 631 | 632 | // Any received char over Serial port stops printing RF received bytes 633 | while (!Serial.available()) 634 | { 635 | 636 | // we have to use the buffer not to introduce delays 637 | for (int i=0; i -1; j--) // 8 bits in a byte 641 | { 642 | bitWrite(receivedbyte, j, digitalRead(gdo0)); // Capture GDO0 state into the byte 643 | delayMicroseconds(setting); // delay for selected sampling interval 644 | }; 645 | // store the output into recording buffer 646 | bigrecordingbuffer[i] = receivedbyte; 647 | }; 648 | // when buffer full print the ouptput to serial port 649 | for (int i = 0; i < RECORDINGBUFFERSIZE ; i = i + 32) 650 | { 651 | asciitohex((byte *)&bigrecordingbuffer[i], (byte *)textbuffer, 32); 652 | Serial.print((char *)textbuffer); 653 | }; 654 | 655 | 656 | }; // end of While loop 657 | 658 | Serial.print(F("\r\nStopping the sniffer.\n\r\n")); 659 | 660 | // setting normal pkt format again 661 | ELECHOUSE_cc1101.setCCMode(1); 662 | ELECHOUSE_cc1101.setPktFormat(0); 663 | ELECHOUSE_cc1101.SetRx(); 664 | } 665 | else { Serial.print(F("Wrong parameters.\r\n")); }; 666 | 667 | 668 | // handling PLAYRAW command 669 | } else if (strcmp_P(command, PSTR("playraw")) == 0) { 670 | // take interval period for sampling 671 | setting = atoi(cmdline); 672 | if (setting>0) 673 | { 674 | // setup async mode on CC1101 and go into TX mode 675 | // with GDO0 pin processing 676 | ELECHOUSE_cc1101.setCCMode(0); 677 | ELECHOUSE_cc1101.setPktFormat(3); 678 | ELECHOUSE_cc1101.SetTx(); 679 | //start replaying GDO0 bit state from data in the buffer with bitbanging 680 | Serial.print(F("\r\nReplaying RAW data from the buffer...\r\n")); 681 | pinMode(gdo0, OUTPUT); 682 | 683 | 684 | for (int i=1; i -1; j--) // 8 bits in a byte 688 | { 689 | digitalWrite(gdo0, bitRead(receivedbyte, j)); // Set GDO0 according to recorded byte 690 | delayMicroseconds(setting); // delay for selected sampling interval 691 | }; 692 | } 693 | 694 | 695 | Serial.print(F("\r\nReplaying RAW data complete.\r\n\r\n")); 696 | // setting normal pkt format again 697 | ELECHOUSE_cc1101.setCCMode(1); 698 | ELECHOUSE_cc1101.setPktFormat(0); 699 | ELECHOUSE_cc1101.SetTx(); 700 | // pinMode(gdo0pin, INPUT); 701 | } 702 | else { Serial.print(F("Wrong parameters.\r\n")); }; 703 | 704 | // handling SHOWRAW command 705 | } else if (strcmp_P(command, PSTR("showraw")) == 0) { 706 | // show the content of recorded RAW signal as hex numbers 707 | Serial.print(F("\r\nRecorded RAW data:\r\n")); 708 | for (int i = 0; i < RECORDINGBUFFERSIZE ; i = i + 32) 709 | { 710 | asciitohex((byte *)&bigrecordingbuffer[i], (byte *)textbuffer, 32); 711 | Serial.print((char *)textbuffer); 712 | } 713 | Serial.print(F("\r\n\r\n")); 714 | 715 | 716 | // handling SHOWBIT command 717 | } else if (strcmp_P(command, PSTR("showbit")) == 0) { 718 | // show the content of recorded RAW signal as hex numbers 719 | Serial.print(F("\r\nRecorded RAW data as bit stream:\r\n")); 720 | for (int i = 0; i < RECORDINGBUFFERSIZE ; i = i + 32) 721 | { // first convert to hex numbers 722 | asciitohex((byte *)&bigrecordingbuffer[i], (byte *)textbuffer, 32); 723 | // now decode as binary and print 724 | for (setting = 0; setting < 64 ; setting++) 725 | { 726 | setting2 = textbuffer[setting]; 727 | switch( setting2 ) 728 | { 729 | case '0': 730 | Serial.print(F("____")); 731 | break; 732 | 733 | case '1': 734 | Serial.print(F("___-")); 735 | break; 736 | 737 | case '2': 738 | Serial.print(F("__-_")); 739 | break; 740 | 741 | case '3': 742 | Serial.print(F("__--")); 743 | break; 744 | 745 | case '4': 746 | Serial.print(F("_-__")); 747 | break; 748 | 749 | case '5': 750 | Serial.print(F("_-_-")); 751 | break; 752 | 753 | case '6': 754 | Serial.print(F("_--_")); 755 | break; 756 | 757 | case '7': 758 | Serial.print(F("_---")); 759 | break; 760 | 761 | case '8': 762 | Serial.print(F("-___")); 763 | break; 764 | 765 | case '9': 766 | Serial.print(F("-__-")); 767 | break; 768 | 769 | case 'A': 770 | Serial.print(F("-_-_")); 771 | break; 772 | 773 | case 'B': 774 | Serial.print(F("-_--")); 775 | break; 776 | 777 | case 'C': 778 | Serial.print(F("--__")); 779 | break; 780 | 781 | case 'D': 782 | Serial.print(F("--_-")); 783 | break; 784 | 785 | case 'E': 786 | Serial.print(F("---_")); 787 | break; 788 | 789 | case 'F': 790 | Serial.print(F("----")); 791 | break; 792 | 793 | }; // end of switch 794 | 795 | }; // end of for 796 | 797 | } // end of for 798 | Serial.print(F("\r\n\r\n")); 799 | 800 | 801 | 802 | // Handling ADDRAW command 803 | } else if (strcmp_P(command, PSTR("addraw")) == 0) { 804 | // getting hex numbers - the content of the frame 805 | len = strlen(cmdline); 806 | // convert hex array to set of bytes 807 | if ((len<=120) && (len>0) ) 808 | { 809 | // convert the hex content to array of bytes 810 | hextoascii((byte *)textbuffer, cmdline, len); 811 | len = len /2; 812 | // check if the frame fits into the buffer and store it 813 | if (( bigrecordingbufferpos + len) < RECORDINGBUFFERSIZE) 814 | { // copy current frame and increase pointer for next frames 815 | memcpy(&bigrecordingbuffer[bigrecordingbufferpos], &textbuffer, len ); 816 | // increase position in big recording buffer for next frame 817 | bigrecordingbufferpos = bigrecordingbufferpos + len; 818 | Serial.print(F("\r\nChunk added to recording buffer\r\n\r\n")); 819 | } 820 | else 821 | { 822 | Serial.print(F("\r\nBuffer is full. The frame does not fit.\r\n ")); 823 | }; 824 | } 825 | else { Serial.print(F("Wrong parameters.\r\n")); }; 826 | 827 | 828 | 829 | // Handling REC command 830 | } else if (strcmp_P(command, PSTR("rec")) == 0) { 831 | Serial.print(F("\r\nRecording mode set to ")); 832 | if (recordingmode == 1) 833 | { 834 | Serial.print(F("Disabled")); 835 | bigrecordingbufferpos = 0; 836 | recordingmode = 0; 837 | } 838 | else if (recordingmode == 0) 839 | { ELECHOUSE_cc1101.SetRx(); 840 | Serial.print(F("Enabled")); 841 | bigrecordingbufferpos = 0; 842 | // flush buffer for recording 843 | for (int i = 0; i < RECORDINGBUFFERSIZE; i++) 844 | { bigrecordingbuffer[RECORDINGBUFFERSIZE] = 0; }; 845 | recordingmode = 1; 846 | jammingmode = 0; 847 | receivingmode = 0; 848 | // start counting frames in the buffer 849 | framesinbigrecordingbuffer = 0; 850 | }; 851 | Serial.print(F("\r\n")); 852 | 853 | 854 | // Handling PLAY command 855 | } else if (strcmp_P(command, PSTR("play")) == 0) { 856 | setting = atoi(strsep(&cmdline, " ")); 857 | // if number of played frames is 0 it means play all frames 858 | if (setting <= framesinbigrecordingbuffer) 859 | { 860 | Serial.print(F("\r\nReplaying recorded frames.\r\n ")); 861 | // rewind recording buffer position to the beginning 862 | bigrecordingbufferpos = 0; 863 | if (framesinbigrecordingbuffer >0) 864 | { 865 | 866 | // start reading and sending frames from the buffer : FIFO 867 | for (int i=1; i<=framesinbigrecordingbuffer ; i++) 868 | { 869 | // read length of the recorded frame first from the buffer 870 | len = bigrecordingbuffer[bigrecordingbufferpos]; 871 | if ( ((len<=60) and (len>0)) and ((i == setting) or (setting == 0)) ) 872 | { 873 | // take next frame from the buffer for replay 874 | memcpy(ccsendingbuffer, &bigrecordingbuffer[bigrecordingbufferpos + 1], len ); 875 | // send these data to radio over CC1101 876 | ELECHOUSE_cc1101.SendData(ccsendingbuffer, (byte)len); 877 | }; 878 | // increase position to the buffer and check exception 879 | bigrecordingbufferpos = bigrecordingbufferpos + 1 + len; 880 | if ( bigrecordingbufferpos > RECORDINGBUFFERSIZE) break; 881 | // 882 | }; 883 | }; // end of IF framesinrecordingbuffer 884 | 885 | // rewind buffer position 886 | bigrecordingbufferpos = 0; 887 | Serial.print(F("Done.\r\n")); 888 | } 889 | else { Serial.print(F("Wrong parameters.\r\n")); }; 890 | 891 | 892 | // Handling ADD command 893 | } else if (strcmp_P(command, PSTR("add")) == 0) { 894 | // getting hex numbers - the content of the frame 895 | len = strlen(cmdline); 896 | // convert hex array to set of bytes 897 | if ((len<=120) && (len>0) ) 898 | { 899 | // convert the hex content to array of bytes 900 | hextoascii((byte *)textbuffer, cmdline, len); 901 | len = len /2; 902 | // check if the frame fits into the buffer and store it 903 | if (( bigrecordingbufferpos + len + 1) < RECORDINGBUFFERSIZE) 904 | { // put info about number of bytes 905 | bigrecordingbuffer[bigrecordingbufferpos] = len; 906 | bigrecordingbufferpos++; 907 | // next - copy current frame and increase 908 | memcpy(&bigrecordingbuffer[bigrecordingbufferpos], &textbuffer, len ); 909 | // increase position in big recording buffer for next frame 910 | bigrecordingbufferpos = bigrecordingbufferpos + len; 911 | // increase counter of frames stored 912 | framesinbigrecordingbuffer++; 913 | Serial.print(F("\r\nAdded frame number ")); 914 | Serial.print(framesinbigrecordingbuffer); 915 | Serial.print(F("\r\n")); 916 | } 917 | else 918 | { 919 | Serial.print(F("\r\nBuffer is full. The frame does not fit.\r\n ")); 920 | }; 921 | } 922 | else { Serial.print(F("Wrong parameters.\r\n")); }; 923 | 924 | 925 | 926 | // Handling SHOW command 927 | } else if (strcmp_P(command, PSTR("show")) == 0) { 928 | if (framesinbigrecordingbuffer>0) 929 | { 930 | Serial.print(F("\r\nFrames stored in the recording buffer:\r\n ")); 931 | // rewind recording buffer position to the beginning 932 | bigrecordingbufferpos = 0; 933 | // start reading and sending frames from the buffer : FIFO 934 | for (setting=1; setting<=framesinbigrecordingbuffer; setting++) 935 | { 936 | // read length of the recorded frame first from the buffer 937 | len = bigrecordingbuffer[bigrecordingbufferpos]; 938 | if ((len<=60) and (len>0)) 939 | { 940 | // take next frame from the buffer for replay 941 | // flush textbuffer 942 | for (setting2 = 0; setting2 < BUF_LENGTH; setting2++) 943 | { textbuffer[setting2] = 0; }; 944 | asciitohex((byte *)&bigrecordingbuffer[bigrecordingbufferpos + 1], (byte *)textbuffer, len); 945 | Serial.print(F("\r\nFrame ")); 946 | Serial.print(setting); 947 | Serial.print(F(" : ")); 948 | Serial.print((char *)textbuffer); 949 | Serial.print(F("\r\n")); 950 | }; 951 | // increase position to the buffer and check exception 952 | bigrecordingbufferpos = bigrecordingbufferpos + 1 + len; 953 | if ( bigrecordingbufferpos > RECORDINGBUFFERSIZE) break; 954 | // 955 | }; 956 | // rewind buffer position 957 | // bigrecordingbufferpos = 0; 958 | Serial.print(F("\r\n")); 959 | } 960 | else { Serial.print(F("Wrong parameters.\r\n")); }; 961 | 962 | 963 | // Handling FLUSH command 964 | } else if (strcmp_P(command, PSTR("flush")) == 0) { 965 | // flushing bigrecordingbuffer with zeros and rewinding all the pointers 966 | for (setting = 0; setting-75) 993 | { 994 | if (rssi > mark_rssi) 995 | { 996 | mark_rssi = rssi; 997 | mark_freq = freq; 998 | }; 999 | }; 1000 | 1001 | freq+=0.01; 1002 | 1003 | if (freq > settingf2) 1004 | { 1005 | freq = settingf1; 1006 | 1007 | if (mark_rssi>-75) 1008 | { 1009 | long fr = mark_freq*100; 1010 | if (fr == compare_freq) 1011 | { 1012 | Serial.print(F("Signal found at ")); 1013 | Serial.print(F("Freq: ")); 1014 | Serial.print(mark_freq); 1015 | Serial.print(F(" Rssi: ")); 1016 | Serial.println(mark_rssi); 1017 | mark_rssi=-100; 1018 | compare_freq = 0; 1019 | mark_freq = 0; 1020 | } 1021 | else 1022 | { 1023 | compare_freq = mark_freq*100; 1024 | freq = mark_freq -0.10; 1025 | mark_freq=0; 1026 | mark_rssi=-100; 1027 | }; 1028 | }; 1029 | 1030 | }; // end of IF freq>stop frequency 1031 | 1032 | }; // End of While 1033 | 1034 | 1035 | 1036 | 1037 | // handling SAVE command 1038 | } else if (strcmp_P(command, PSTR("save")) == 0) { 1039 | //start saving recording buffer content into EEPROM non-volatile memory 1040 | Serial.print(F("\r\nSaving recording buffer content into the non-volatile memory...\r\n")); 1041 | 1042 | for (setting=0; setting 20 | #include 21 | 22 | #define CCBUFFERSIZE 64 23 | #define RECORDINGBUFFERSIZE 4096 // Buffer for recording the frames 24 | #define EPROMSIZE 512 // Size of EEPROM in your Arduino chip. For ESP32 it is Flash simulated so very slow 25 | #define BUF_LENGTH 128 // Buffer for the incoming command. 26 | 27 | // defining PINs set for ESP32 module 28 | // Example for XIAO ESP32 C3 29 | /* byte sck = 8; 30 | byte miso = 4; 31 | byte mosi = 10; 32 | byte ss = 20; 33 | int gdo0 = 21; 34 | int gdo2 = 7; */ 35 | 36 | // defining PINs set for ESP32 WROOM module 37 | 38 | byte sck = 18; // GPIO 18 39 | byte miso = 19; // GPIO 19 40 | byte mosi = 23; // GPIO 23 41 | byte ss = 5; // GPIO 5 42 | int gdo0 = 2; // GPIO 2 43 | int gdo2 = 4; // GPIO 4 44 | 45 | 46 | // position in big recording buffer 47 | int bigrecordingbufferpos = 0; 48 | 49 | // number of frames in big recording buffer 50 | int framesinbigrecordingbuffer = 0; 51 | 52 | // check if CLI receiving mode enabled 53 | int receivingmode = 0; 54 | 55 | // check if CLI jamming mode enabled 56 | int jammingmode = 0; 57 | 58 | // check if CLI recording mode enabled 59 | int recordingmode = 0; 60 | 61 | // check if CLI chat mode enabled 62 | int chatmode = 0; 63 | 64 | static bool do_echo = true; 65 | 66 | // buffer for receiving CC1101 67 | byte ccreceivingbuffer[CCBUFFERSIZE] = {0}; 68 | 69 | // buffer for sending CC1101 70 | byte ccsendingbuffer[CCBUFFERSIZE] = {0}; 71 | //char ccsendingbuffer[CCBUFFERSIZE] = {0}; 72 | 73 | // buffer for recording and replaying of many frames 74 | byte bigrecordingbuffer[RECORDINGBUFFERSIZE] = {0}; 75 | 76 | // buffer for hex to ascii conversions 77 | byte textbuffer[BUF_LENGTH]; 78 | //char textbuffer[BUF_LENGTH]; 79 | 80 | 81 | 82 | // convert bytes in table to string with hex numbers 83 | void asciitohex(byte *ascii_ptr, byte *hex_ptr,int len) 84 | { 85 | byte i,j,k; 86 | for(i = 0; i < len; i++) 87 | { 88 | // high byte first 89 | j = ascii_ptr[i] / 16; 90 | if (j>9) 91 | { k = j - 10 + 65; } 92 | else 93 | { k = j + 48; } 94 | hex_ptr[2*i] = k ; 95 | // low byte second 96 | j = ascii_ptr[i] % 16; 97 | if (j>9) 98 | { k = j - 10 + 65; } 99 | else 100 | { k = j + 48; } 101 | hex_ptr[(2*i)+1] = k ; 102 | }; 103 | hex_ptr[(2*i)+2] = '\0' ; 104 | } 105 | 106 | 107 | // convert string with hex numbers to array of bytes 108 | void hextoascii(byte *ascii_ptr, byte *hex_ptr,int len) 109 | { 110 | byte i,j; 111 | for(i = 0; i < (len/2); i++) 112 | { 113 | j = hex_ptr[i*2]; 114 | if ((j>47) && (j<58)) ascii_ptr[i] = (j - 48) * 16; 115 | if ((j>64) && (j<71)) ascii_ptr[i] = (j - 55) * 16; 116 | if ((j>96) && (j<103)) ascii_ptr[i] = (j - 87) * 16; 117 | j = hex_ptr[i*2+1]; 118 | if ((j>47) && (j<58)) ascii_ptr[i] = ascii_ptr[i] + (j - 48); 119 | if ((j>64) && (j<71)) ascii_ptr[i] = ascii_ptr[i] + (j - 55); 120 | if ((j>96) && (j<103)) ascii_ptr[i] = ascii_ptr[i] + (j - 87); 121 | }; 122 | ascii_ptr[i++] = '\0' ; 123 | } 124 | 125 | // Initialize CC1101 board with default settings, you may change your preferences here 126 | static void cc1101initialize(void) 127 | { 128 | // initializing library with custom pins selected 129 | ELECHOUSE_cc1101.setSpiPin(sck, miso, mosi, ss); 130 | ELECHOUSE_cc1101.setGDO(gdo0, gdo2); 131 | 132 | // Main part to tune CC1101 with proper frequency, modulation and encoding 133 | ELECHOUSE_cc1101.Init(); // must be set to initialize the cc1101! 134 | ELECHOUSE_cc1101.setGDO0(gdo0); // set lib internal gdo pin (gdo0). Gdo2 not use for this example. 135 | ELECHOUSE_cc1101.setCCMode(1); // set config for internal transmission mode. value 0 is for RAW recording/replaying 136 | ELECHOUSE_cc1101.setModulation(2); // set modulation mode. 0 = 2-FSK, 1 = GFSK, 2 = ASK/OOK, 3 = 4-FSK, 4 = MSK. 137 | ELECHOUSE_cc1101.setMHZ(433.92); // Here you can set your basic frequency. The lib calculates the frequency automatically (default = 433.92).The cc1101 can: 300-348 MHZ, 387-464MHZ and 779-928MHZ. Read More info from datasheet. 138 | ELECHOUSE_cc1101.setDeviation(47.60); // Set the Frequency deviation in kHz. Value from 1.58 to 380.85. Default is 47.60 kHz. 139 | ELECHOUSE_cc1101.setChannel(0); // Set the Channelnumber from 0 to 255. Default is cahnnel 0. 140 | ELECHOUSE_cc1101.setChsp(199.95); // The channel spacing is multiplied by the channel number CHAN and added to the base frequency in kHz. Value from 25.39 to 405.45. Default is 199.95 kHz. 141 | ELECHOUSE_cc1101.setRxBW(812.50); // Set the Receive Bandwidth in kHz. Value from 58.03 to 812.50. Default is 812.50 kHz. 142 | ELECHOUSE_cc1101.setDRate(9.6); // Set the Data Rate in kBaud. Value from 0.02 to 1621.83. Default is 99.97 kBaud! 143 | ELECHOUSE_cc1101.setPA(10); // Set TxPower. The following settings are possible depending on the frequency band. (-30 -20 -15 -10 -6 0 5 7 10 11 12) Default is max! 144 | ELECHOUSE_cc1101.setSyncMode(2); // Combined sync-word qualifier mode. 0 = No preamble/sync. 1 = 16 sync word bits detected. 2 = 16/16 sync word bits detected. 3 = 30/32 sync word bits detected. 4 = No preamble/sync, carrier-sense above threshold. 5 = 15/16 + carrier-sense above threshold. 6 = 16/16 + carrier-sense above threshold. 7 = 30/32 + carrier-sense above threshold. 145 | ELECHOUSE_cc1101.setSyncWord(211, 145); // Set sync word. Must be the same for the transmitter and receiver. Default is 211,145 (Syncword high, Syncword low) 146 | ELECHOUSE_cc1101.setAdrChk(0); // Controls address check configuration of received packages. 0 = No address check. 1 = Address check, no broadcast. 2 = Address check and 0 (0x00) broadcast. 3 = Address check and 0 (0x00) and 255 (0xFF) broadcast. 147 | ELECHOUSE_cc1101.setAddr(0); // Address used for packet filtration. Optional broadcast addresses are 0 (0x00) and 255 (0xFF). 148 | ELECHOUSE_cc1101.setWhiteData(0); // Turn data whitening on / off. 0 = Whitening off. 1 = Whitening on. 149 | ELECHOUSE_cc1101.setPktFormat(0); // Format of RX and TX data. 0 = Normal mode, use FIFOs for RX and TX. 1 = Synchronous serial mode, Data in on GDO0 and data out on either of the GDOx pins. 2 = Random TX mode; sends random data using PN9 generator. Used for test. Works as normal mode, setting 0 (00), in RX. 3 = Asynchronous serial mode, Data in on GDO0 and data out on either of the GDOx pins. 150 | ELECHOUSE_cc1101.setLengthConfig(1); // 0 = Fixed packet length mode. 1 = Variable packet length mode. 2 = Infinite packet length mode. 3 = Reserved 151 | ELECHOUSE_cc1101.setPacketLength(0); // Indicates the packet length when fixed packet length mode is enabled. If variable packet length mode is used, this value indicates the maximum packet length allowed. 152 | ELECHOUSE_cc1101.setCrc(0); // 1 = CRC calculation in TX and CRC check in RX enabled. 0 = CRC disabled for TX and RX. 153 | ELECHOUSE_cc1101.setCRC_AF(0); // Enable automatic flush of RX FIFO when CRC is not OK. This requires that only one packet is in the RXIFIFO and that packet length is limited to the RX FIFO size. 154 | ELECHOUSE_cc1101.setDcFilterOff(0); // Disable digital DC blocking filter before demodulator. Only for data rates ≤ 250 kBaud The recommended IF frequency changes when the DC blocking is disabled. 1 = Disable (current optimized). 0 = Enable (better sensitivity). 155 | ELECHOUSE_cc1101.setManchester(0); // Enables Manchester encoding/decoding. 0 = Disable. 1 = Enable. 156 | ELECHOUSE_cc1101.setFEC(0); // Enable Forward Error Correction (FEC) with interleaving for packet payload (Only supported for fixed packet length mode. 0 = Disable. 1 = Enable. 157 | ELECHOUSE_cc1101.setPRE(0); // Sets the minimum number of preamble bytes to be transmitted. Values: 0 : 2, 1 : 3, 2 : 4, 3 : 6, 4 : 8, 5 : 12, 6 : 16, 7 : 24 158 | ELECHOUSE_cc1101.setPQT(0); // Preamble quality estimator threshold. The preamble quality estimator increases an internal counter by one each time a bit is received that is different from the previous bit, and decreases the counter by 8 each time a bit is received that is the same as the last bit. A threshold of 4∙PQT for this counter is used to gate sync word detection. When PQT=0 a sync word is always accepted. 159 | ELECHOUSE_cc1101.setAppendStatus(0); // When enabled, two status bytes will be appended to the payload of the packet. The status bytes contain RSSI and LQI values, as well as CRC OK. 160 | } 161 | 162 | 163 | // Execute a complete CC1101 command. 164 | 165 | static void exec(char *cmdline) 166 | { 167 | 168 | char *command = strsep(&cmdline, " "); 169 | int setting, setting2, len; 170 | uint16_t brute, poweroftwo; 171 | byte j, k; 172 | float settingf1; 173 | float settingf2; 174 | // variables for frequency scanner 175 | float freq; 176 | long compare_freq; 177 | float mark_freq; 178 | int rssi; 179 | int mark_rssi=-100; 180 | 181 | // identification of the command & actions 182 | 183 | if (strcmp_P(command, PSTR("help")) == 0) { 184 | Serial.println(F( 185 | "setmodulation : Set modulation mode. 0 = 2-FSK, 1 = GFSK, 2 = ASK/OOK, 3 = 4-FSK, 4 = MSK.\r\n\r\n" 186 | "setmhz : Here you can set your basic frequency. default = 433.92).The cc1101 can: 300-348 MHZ, 387-464MHZ and 779-928MHZ.\r\n\r\n" 187 | "setdeviation : Set the Frequency deviation in kHz. Value from 1.58 to 380.85.\r\n\r\n" 188 | "setchannel : Set the Channelnumber from 0 to 255. Default is cahnnel 0.\r\n\r\n" 189 | "setchsp : The channel spacing is multiplied by the channel number CHAN and added to the base frequency in kHz. Value from 25.39 to 405.45. \r\n\r\n" 190 | "setrxbw : Set the Receive Bandwidth in kHz. Value from 58.03 to 812.50. \r\n\r\n" 191 | "setdrate : Set the Data Rate in kBaud. Value from 0.02 to 1621.83.\r\n\r\n" 192 | "setpa : Set RF transmission power. The following settings are possible depending on the frequency band. (-30 -20 -15 -10 -6 0 5 7 10 11 12) Default is max!\r\n\r\n" 193 | "setsyncmode : Combined sync-word qualifier mode. 0 = No preamble/sync. 1 = 16 sync word bits detected. 2 = 16/16 sync word bits detected. 3 = 30/32 sync word bits detected. 4 = No preamble/sync, carrier-sense above threshold. 5 = 15/16 + carrier-sense above threshold. 6 = 16/16 + carrier-sense above threshold. 7 = 30/32 + carrier-sense above threshold.\r\n" 194 | )); 195 | Serial.println(F( 196 | "setsyncword : Set sync word. Must be the same for the transmitter and receiver. (Syncword high, Syncword low) Default is 211,145\r\n\r\n" 197 | "setadrchk
: Controls address check configuration of received packages. 0 = No address check. 1 = Address check, no broadcast. 2 = Address check and 0 (0x00) broadcast. 3 = Address check and 0 (0x00) and 255 (0xFF) broadcast.\r\n\r\n" 198 | "setaddr
: Address used for packet filtration. Optional broadcast addresses are 0 (0x00) and 255 (0xFF).\r\n\r\n" 199 | "setwhitedata : Turn data whitening on / off. 0 = Whitening off. 1 = Whitening on.\r\n\r\n" 200 | "setpktformat : Format of RX and TX data. 0 = Normal mode, use FIFOs for RX and TX. 1 = Synchronous serial mode, Data in on GDO0 and data out on either of the GDOx pins. 2 = Random TX mode; sends random data using PN9 generator. 3 = Asynchronous serial mode\r\n\r\n" 201 | "setlengthconfig : Set packet Length mode : 0 = Fixed packet length mode. 1 = Variable packet length mode. 2 = Infinite packet length mode. 3 = Reserved \r\n\r\n" 202 | "setpacketlength : Indicates the packet length when fixed packet length mode is enabled. If variable packet length mode is used, this value indicates the maximum packet length allowed.\r\n\r\n" 203 | "setcrc : Switches on/of CRC calculation and check. 1 = CRC calculation in TX and CRC check in RX enabled. 0 = CRC disabled for TX and RX.\r\n\r\n" 204 | "setcrcaf : Enable automatic flush of RX FIFO when CRC is not OK. This requires that only one packet is in the RXIFIFO and that packet length is limited to the RX FIFO size.\r\n" 205 | )); 206 | Serial.println(F( 207 | "setdcfilteroff : Disable digital DC blocking filter before demodulator. Only for data rates ≤ 250 kBaud The recommended IF frequency changes when the DC blocking is disabled. 1 = Disable (current optimized). 0 = Enable (better sensitivity).\r\n\r\n" 208 | "setmanchester : Enables Manchester encoding/decoding. 0 = Disable. 1 = Enable.\r\n\r\n" 209 | "setfec : Enable Forward Error Correction (FEC) with interleaving for packet payload (Only supported for fixed packet length mode. 0 = Disable. 1 = Enable.\r\n\r\n" 210 | "setpre : Sets the minimum number of preamble bytes to be transmitted. Values: 0 : 2, 1 : 3, 2 : 4, 3 : 6, 4 : 8, 5 : 12, 6 : 16, 7 : 24\r\n\r\n" 211 | "setpqt : Preamble quality estimator threshold. \r\n\r\n" 212 | "setappendstatus : When enabled, two status bytes will be appended to the payload of the packet. The status bytes contain RSSI and LQI values, as well as CRC OK.\r\n\r\n" 213 | "getrssi : Display quality information about last received frames over RF\r\n\r\n" 214 | "scan : Scan frequency range for the highest signal.\r\n\r\n" 215 | "chat : Enable chat mode between many devices. No exit available, disconnect device to quit\r\n" 216 | )); 217 | Serial.println(F( 218 | "rx : Sniffer. Enable or disable printing of received RF packets on serial terminal.\r\n\r\n" 219 | "tx : Send packet of max 60 bytes over RF\r\n\r\n" 220 | "jam : Enable or disable continous jamming on selected band.\r\n\r\n" 221 | "brute : Brute force garage gate with keyword where symbol time is .\r\n\r\n" 222 | "rec : Enable or disable recording frames in the buffer.\r\n\r\n" 223 | "add : Manually add single frame payload (max 64 hex values) to the buffer so it can be replayed\r\n\r\n" 224 | "show : Show content of recording buffer\r\n\r\n" 225 | "flush : Clear the recording buffer\r\n\r\n" 226 | "play : Replay 0 = all frames or N-th recorded frame previously stored in the buffer.\r\n\r\n" 227 | "rxraw : Sniffs radio by sampling with interval and prints received bytes in hex.\r\n\r\n" 228 | "recraw : Recording RAW RF data with sampling interval.\r\n" 229 | )); 230 | Serial.println(F( 231 | "addraw : Manually add chunks (max 60 hex values) to the buffer so they can be further replayed.\r\n\r\n" 232 | "showraw : Showing content of recording buffer in RAW format.\r\n\r\n" 233 | "playraw : Replaying previously recorded RAW RF data with sampling interval.\r\n\r\n" 234 | "showbit : Showing content of recording buffer in RAW format as a stream of bits.\r\n\r\n" 235 | "save : Store recording buffer content in non-volatile memory\r\n\r\n" 236 | "load : Load the content from non-volatile memory to the recording buffer\r\n\r\n" 237 | "echo : Enable or disable Echo on serial terminal. 1 = enabled, 0 = disabled\r\n\r\n" 238 | "x : Stops jamming/receiving/recording packets.\r\n\r\n" 239 | "init : Restarts CC1101 board with default parameters\r\n\r\n" 240 | )); 241 | 242 | // Handling SETMODULATION command 243 | } else if (strcmp_P(command, PSTR("setmodulation")) == 0) { 244 | setting = atoi(cmdline); 245 | ELECHOUSE_cc1101.setModulation(setting); 246 | Serial.print(F("\r\nModulation: ")); 247 | if (setting == 0) { Serial.print(F("2-FSK")); } 248 | else if (setting == 1) { Serial.print(F("GFSK")); } 249 | else if (setting == 2) { Serial.print(F("ASK/OOK")); } 250 | else if (setting == 3) { Serial.print(F("4-FSK")); } 251 | else if (setting == 4) { Serial.print(F("MSK")); }; 252 | Serial.print(F(" \r\n")); 253 | 254 | // Handling SETMHZ command 255 | } else if (strcmp_P(command, PSTR("setmhz")) == 0) { 256 | settingf1 = atof(cmdline); 257 | ELECHOUSE_cc1101.setMHZ(settingf1); 258 | Serial.print(F("\r\nFrequency: ")); 259 | Serial.print(settingf1); 260 | Serial.print(F(" MHz\r\n")); 261 | 262 | // Handling SETDEVIATION command 263 | } else if (strcmp_P(command, PSTR("setdeviation")) == 0) { 264 | settingf1 = atof(cmdline); 265 | ELECHOUSE_cc1101.setDeviation(settingf1); 266 | Serial.print(F("\r\nDeviation: ")); 267 | Serial.print(settingf1); 268 | Serial.print(F(" KHz\r\n")); 269 | 270 | // Handling SETCHANNEL command 271 | } else if (strcmp_P(command, PSTR("setchannel")) == 0) { 272 | setting = atoi(cmdline); 273 | ELECHOUSE_cc1101.setChannel(setting); 274 | Serial.print(F("\r\nChannel:")); 275 | Serial.print(setting); 276 | Serial.print(F("\r\n")); 277 | 278 | // Handling SETCHSP command 279 | } else if (strcmp_P(command, PSTR("setchsp")) == 0) { 280 | settingf1 = atof(cmdline); 281 | ELECHOUSE_cc1101.setChsp(settingf1); 282 | Serial.print(F("\r\nChann spacing: ")); 283 | Serial.print(settingf1); 284 | Serial.print(F(" kHz\r\n")); 285 | 286 | // Handling SETRXBW command 287 | } else if (strcmp_P(command, PSTR("setrxbw")) == 0) { 288 | settingf1 = atof(cmdline); 289 | ELECHOUSE_cc1101.setRxBW(settingf1); 290 | Serial.print(F("\r\nRX bandwidth: ")); 291 | Serial.print(settingf1); 292 | Serial.print(F(" kHz \r\n")); 293 | 294 | // Handling SETDRATE command 295 | } else if (strcmp_P(command, PSTR("setdrate")) == 0) { 296 | settingf1 = atof(cmdline); 297 | ELECHOUSE_cc1101.setDRate(settingf1); 298 | Serial.print(F("\r\nDatarate: ")); 299 | Serial.print(settingf1); 300 | Serial.print(F(" kbaud\r\n")); 301 | 302 | // Handling SETPA command 303 | } else if (strcmp_P(command, PSTR("setpa")) == 0) { 304 | setting = atoi(cmdline); 305 | ELECHOUSE_cc1101.setPA(setting); 306 | Serial.print(F("\r\nTX PWR: ")); 307 | Serial.print(setting); 308 | Serial.print(F(" dBm\r\n")); 309 | 310 | // Handling SETSYNCMODE command 311 | } else if (strcmp_P(command, PSTR("setsyncmode")) == 0) { 312 | int setting = atoi(cmdline); 313 | ELECHOUSE_cc1101.setSyncMode(setting); 314 | Serial.print(F("\r\nSynchronization: ")); 315 | if (setting == 0) { Serial.print(F("No preamble")); } 316 | else if (setting == 1) { Serial.print(F("16 sync bits")); } 317 | else if (setting == 2) { Serial.print(F("16/16 sync bits")); } 318 | else if (setting == 3) { Serial.print(F("30/32 sync bits")); } 319 | else if (setting == 4) { Serial.print(F("No preamble/sync, carrier-sense")); } 320 | else if (setting == 5) { Serial.print(F("15/16 + carrier-sense")); } 321 | else if (setting == 6) { Serial.print(F("16/16 + carrier-sense")); } 322 | else if (setting == 7) { Serial.print(F("30/32 + carrier-sense")); }; 323 | Serial.print(F("\r\n")); 324 | 325 | // Handling SETSYNCWORD command 326 | } else if (strcmp_P(command, PSTR("setsyncword")) == 0) { 327 | setting = atoi(strsep(&cmdline, " ")); 328 | setting2 = atoi(cmdline); 329 | ELECHOUSE_cc1101.setSyncWord(setting2, setting); 330 | Serial.print(F("\r\nSynchronization:\r\n")); 331 | Serial.print(F("high = ")); 332 | Serial.print(setting); 333 | Serial.print(F("\r\nlow = ")); 334 | Serial.print(setting2); 335 | Serial.print(F("\r\n")); 336 | 337 | 338 | // Handling SETADRCHK command 339 | } else if (strcmp_P(command, PSTR("setadrchk")) == 0) { 340 | setting = atoi(cmdline); 341 | ELECHOUSE_cc1101.setAdrChk(setting); 342 | Serial.print(F("\r\nAddress checking:")); 343 | if (setting == 0) { Serial.print(F("No adr chk")); } 344 | else if (setting == 1) { Serial.print(F("Adr chk, no bcast")); } 345 | else if (setting == 2) { Serial.print(F("Adr chk and 0 bcast")); } 346 | else if (setting == 3) { Serial.print(F("Adr chk and 0 and FF bcast")); }; 347 | Serial.print(F("\r\n")); 348 | 349 | // Handling SETADDR command 350 | } else if (strcmp_P(command, PSTR("setaddr")) == 0) { 351 | setting = atoi(cmdline); 352 | ELECHOUSE_cc1101.setAddr(setting); 353 | Serial.print(F("\r\nAddress: ")); 354 | Serial.print(setting); 355 | Serial.print(F("\r\n")); 356 | 357 | // Handling SETWHITEDATA command 358 | } else if (strcmp_P(command, PSTR("setwhitedata")) == 0) { 359 | setting = atoi(cmdline); 360 | ELECHOUSE_cc1101.setWhiteData(setting); 361 | Serial.print(F("\r\nWhitening ")); 362 | if (setting == 0) { Serial.print(F("OFF")); } 363 | else if (setting == 1) { Serial.print(F("ON")); } 364 | Serial.print(F("\r\n")); 365 | 366 | // Handling SETPKTFORMAT command 367 | } else if (strcmp_P(command, PSTR("setpktformat")) == 0) { 368 | setting = atoi(cmdline); 369 | ELECHOUSE_cc1101.setPktFormat(setting); 370 | Serial.print(F("\r\nPacket format: ")); 371 | if (setting == 0) { Serial.print(F("Normal mode")); } 372 | else if (setting == 1) { Serial.print(F("Synchronous serial mode")); } 373 | else if (setting == 2) { Serial.print(F("Random TX mode")); } 374 | else if (setting == 3) { Serial.print(F("Asynchronous serial mode")); }; 375 | Serial.print(F("\r\n")); 376 | 377 | // Handling SETLENGTHCONFIG command 378 | } else if (strcmp_P(command, PSTR("setlengthconfig")) == 0) { 379 | setting = atoi(cmdline); 380 | ELECHOUSE_cc1101.setLengthConfig(setting); 381 | Serial.print(F("\r\nPkt length mode: ")); 382 | if (setting == 0) { Serial.print(F("Fixed")); } 383 | else if (setting == 1) { Serial.print(F("Variable")); } 384 | else if (setting == 2) { Serial.print(F("Infinite")); } 385 | else if (setting == 3) { Serial.print(F("Reserved")); }; 386 | Serial.print(F("\r\n")); 387 | 388 | // Handling SETPACKETLENGTH command 389 | } else if (strcmp_P(command, PSTR("setpacketlength")) == 0) { 390 | setting = atoi(cmdline); 391 | ELECHOUSE_cc1101.setPacketLength(setting); 392 | Serial.print(F("\r\nPkt length: ")); 393 | Serial.print(setting); 394 | Serial.print(F(" bytes\r\n")); 395 | 396 | // Handling SETCRC command 397 | } else if (strcmp_P(command, PSTR("setcrc")) == 0) { 398 | setting = atoi(cmdline); 399 | ELECHOUSE_cc1101.setCrc(setting); 400 | Serial.print(F("\r\nCRC checking: ")); 401 | if (setting == 0) { Serial.print(F("Disabled")); } 402 | else if (setting == 1) { Serial.print(F("Enabled")); }; 403 | Serial.print(F("\r\n")); 404 | 405 | // Handling SETCRCAF command 406 | } else if (strcmp_P(command, PSTR("setcrcaf")) == 0) { 407 | setting = atoi(cmdline); 408 | ELECHOUSE_cc1101.setCRC_AF(setting); 409 | Serial.print(F("\r\nCRC Autoflush: ")); 410 | if (setting == 0) { Serial.print(F("Disabled")); } 411 | else if (setting == 1) { Serial.print(F("Enabled")); }; 412 | Serial.print(F("\r\n")); 413 | 414 | // Handling SETDCFILTEROFF command 415 | } else if (strcmp_P(command, PSTR("setdcfilteroff")) == 0) { 416 | setting = atoi(cmdline); 417 | ELECHOUSE_cc1101.setDcFilterOff(setting); 418 | Serial.print(F("\r\nDC filter: ")); 419 | if (setting == 0) { Serial.print(F("Enabled")); } 420 | else if (setting == 1) { Serial.print(F("Disabled")); }; 421 | Serial.print(F("\r\n")); 422 | 423 | // Handling SETMANCHESTER command 424 | } else if (strcmp_P(command, PSTR("setmanchester")) == 0) { 425 | setting = atoi(cmdline); 426 | ELECHOUSE_cc1101.setManchester(setting); 427 | Serial.print(F("\r\nManchester coding: ")); 428 | if (setting == 0) { Serial.print(F("Disabled")); } 429 | else if (setting == 1) { Serial.print(F("Enabled")); }; 430 | Serial.print(F("\r\n")); 431 | 432 | // Handling SETFEC command 433 | } else if (strcmp_P(command, PSTR("setfec")) == 0) { 434 | setting = atoi(cmdline); 435 | ELECHOUSE_cc1101.setFEC(setting); 436 | Serial.print(F("\r\nForward Error Correction: ")); 437 | if (setting == 0) { Serial.print(F("Disabled")); } 438 | else if (setting == 1) { Serial.print(F("Enabled")); }; 439 | Serial.print(F("\r\n")); 440 | 441 | // Handling SETPRE command 442 | } else if (strcmp_P(command, PSTR("setpre")) == 0) { 443 | setting = atoi(cmdline); 444 | ELECHOUSE_cc1101.setPRE(setting); 445 | Serial.print(F("\r\nMinimum preamble bytes:")); 446 | Serial.print(setting); 447 | Serial.print(F(" means 0 = 2 bytes, 1 = 3b, 2 = 4b, 3 = 6b, 4 = 8b, 5 = 12b, 6 = 16b, 7 = 24 bytes\r\n")); 448 | Serial.print(F("\r\n")); 449 | 450 | 451 | // Handling SETPQT command 452 | } else if (strcmp_P(command, PSTR("setpqt")) == 0) { 453 | setting = atoi(cmdline); 454 | ELECHOUSE_cc1101.setPQT(setting); 455 | Serial.print(F("\r\nPQT: ")); 456 | Serial.print(setting); 457 | Serial.print(F("\r\n")); 458 | 459 | // Handling SETAPPENDSTATUS command 460 | } else if (strcmp_P(command, PSTR("setappendstatus")) == 0) { 461 | setting = atoi(cmdline); 462 | ELECHOUSE_cc1101.setAppendStatus(setting); 463 | Serial.print(F("\r\nStatus bytes appending: ")); 464 | if (setting == 0) { Serial.print(F("Enabled")); } 465 | else if (setting == 1) { Serial.print(F("Disabled")); }; 466 | Serial.print(F("\r\n")); 467 | 468 | // Handling GETRSSI command 469 | } else if (strcmp_P(command, PSTR("getrssi")) == 0) { 470 | //Rssi Level in dBm 471 | Serial.print(F("Rssi: ")); 472 | Serial.println(ELECHOUSE_cc1101.getRssi()); 473 | //Link Quality Indicator 474 | Serial.print(F(" LQI: ")); 475 | Serial.println(ELECHOUSE_cc1101.getLqi()); 476 | Serial.print(F("\r\n")); 477 | 478 | 479 | // Handling SCAN command - frequency scanner by Little S@tan ! 480 | } else if (strcmp_P(command, PSTR("scan")) == 0) { 481 | settingf1 = atof(strsep(&cmdline, " ")); 482 | settingf2 = atof(cmdline); 483 | Serial.print(F("\r\nScanning frequency range from : ")); 484 | Serial.print(settingf1); 485 | Serial.print(F(" MHz to ")); 486 | Serial.print(settingf2); 487 | Serial.print(F(" MHz, press any key for stop or wait...\r\n")); 488 | // initialize parameters for scanning 489 | ELECHOUSE_cc1101.Init(); 490 | ELECHOUSE_cc1101.setRxBW(58); 491 | ELECHOUSE_cc1101.SetRx(); 492 | // Do scanning until some key pressed 493 | freq = settingf1; // start frequency for scanning 494 | mark_rssi=-100; 495 | while (!Serial.available()) 496 | { 497 | ELECHOUSE_cc1101.setMHZ(freq); 498 | rssi = ELECHOUSE_cc1101.getRssi(); 499 | if (rssi>-75) 500 | { 501 | if (rssi > mark_rssi) 502 | { 503 | mark_rssi = rssi; 504 | mark_freq = freq; 505 | }; 506 | }; 507 | 508 | freq+=0.01; 509 | 510 | if (freq > settingf2) 511 | { 512 | freq = settingf1; 513 | 514 | if (mark_rssi>-75) 515 | { 516 | long fr = mark_freq*100; 517 | if (fr == compare_freq) 518 | { 519 | Serial.print(F("\r\nSignal found at ")); 520 | Serial.print(F("Freq: ")); 521 | Serial.print(mark_freq); 522 | Serial.print(F(" Rssi: ")); 523 | Serial.println(mark_rssi); 524 | mark_rssi=-100; 525 | compare_freq = 0; 526 | mark_freq = 0; 527 | } 528 | else 529 | { 530 | compare_freq = mark_freq*100; 531 | freq = mark_freq -0.10; 532 | mark_freq=0; 533 | mark_rssi=-100; 534 | }; 535 | }; 536 | 537 | }; // end of IF freq>stop frequency 538 | 539 | }; // End of While 540 | 541 | 542 | // handling SAVE command 543 | } else if (strcmp_P(command, PSTR("save")) == 0) { 544 | //start saving recording buffer content into EEPROM non-volatile memory 545 | Serial.print(F("\r\nSaving recording buffer content into the non-volatile memory...\r\n")); 546 | 547 | for (setting=0; setting0) 627 | { 628 | // setup async mode on CC1101 and go into TX mode 629 | // with GDO0 pin processing 630 | ELECHOUSE_cc1101.setCCMode(0); 631 | ELECHOUSE_cc1101.setPktFormat(3); 632 | ELECHOUSE_cc1101.SetTx(); 633 | 634 | //start playing RF with setting GDO0 bit state with bitbanging 635 | Serial.print(F("\r\nStarting Brute Forcing press any key to stop...\r\n")); 636 | pinMode(gdo0, OUTPUT); 637 | 638 | for (brute = 0; brute < poweroftwo ; brute++) 639 | { 640 | for(int k = 0; k < 5; k++) // sending 5 times each code 641 | { 642 | for(int j = (setting2 - 1); j > -1; j--) // j bits in a value brute 643 | { 644 | digitalWrite(gdo0, bitRead(brute, j)); // Set GDO0 according to actual brute force value 645 | delayMicroseconds(setting); // delay for selected sampling interval 646 | }; // end of J loop 647 | }; // end of K loop 648 | // checking if key pressed 649 | if (Serial.available()) break; 650 | }; 651 | Serial.print(F("\r\nBrute forcing complete.\r\n\r\n")); 652 | 653 | // setting normal pkt format again 654 | ELECHOUSE_cc1101.setCCMode(1); 655 | ELECHOUSE_cc1101.setPktFormat(0); 656 | ELECHOUSE_cc1101.SetTx(); 657 | // pinMode(gdo0pin, INPUT); 658 | } // end of IF 659 | else { Serial.print(F("Wrong parameters.\r\n")); }; 660 | 661 | 662 | // Handling TX command 663 | } else if (strcmp_P(command, PSTR("tx")) == 0) { 664 | // convert hex array to set of bytes 665 | if ((strlen(cmdline)<=120) && (strlen(cmdline)>0) ) 666 | { 667 | hextoascii(textbuffer,(byte *)cmdline, strlen(cmdline)); 668 | memcpy(ccsendingbuffer, textbuffer, strlen(cmdline)/2 ); 669 | ccsendingbuffer[strlen(cmdline)/2] = 0x00; 670 | Serial.print("\r\nTransmitting RF packets.\r\n"); 671 | // send these data to radio over CC1101 672 | ELECHOUSE_cc1101.SendData(ccsendingbuffer, (byte)(strlen(cmdline)/2)); 673 | // for DEBUG only 674 | asciitohex(ccsendingbuffer, textbuffer, strlen(cmdline)/2 ); 675 | Serial.print(F("Sent frame: ")); 676 | Serial.print((char *)textbuffer); 677 | Serial.print(F("\r\n")); } 678 | else { Serial.print(F("Wrong parameters.\r\n")); }; 679 | 680 | 681 | 682 | // handling RECRAW command 683 | } else if (strcmp_P(command, PSTR("recraw")) == 0) { 684 | // take interval period for samplink 685 | setting = atoi(cmdline); 686 | if (setting>0) 687 | { 688 | // setup async mode on CC1101 with GDO0 pin processing 689 | ELECHOUSE_cc1101.setCCMode(0); 690 | ELECHOUSE_cc1101.setPktFormat(3); 691 | ELECHOUSE_cc1101.SetRx(); 692 | 693 | 694 | //start recording to the buffer with bitbanging of GDO0 pin state 695 | Serial.print(F("\r\nWaiting for radio signal to start RAW recording...\r\n")); 696 | pinMode(gdo0, INPUT); 697 | 698 | // this is only for ESP32 boards because they are getting some noise on the beginning 699 | setting2 = digitalRead(gdo0); 700 | delayMicroseconds(1000); 701 | 702 | 703 | // waiting for some data first or serial port signal 704 | //while (!Serial.available() || (digitalRead(gdo0) == LOW) ); 705 | while ( digitalRead(gdo0) == LOW ); 706 | 707 | 708 | //start recording to the buffer with bitbanging of GDO0 pin state 709 | Serial.print(F("\r\nStarting RAW recording to the buffer...\r\n")); 710 | 711 | for (int i=0; i -1; j--) // 8 bits in a byte 715 | { 716 | bitWrite(receivedbyte, j, digitalRead(gdo0)); // Capture GDO0 state into the byte 717 | delayMicroseconds(setting); // delay for selected sampling interval 718 | }; 719 | // store the output into recording buffer 720 | bigrecordingbuffer[i] = receivedbyte; 721 | } 722 | Serial.print(F("\r\nRecording RAW data complete.\r\n\r\n")); 723 | // setting normal pkt format again 724 | ELECHOUSE_cc1101.setCCMode(1); 725 | ELECHOUSE_cc1101.setPktFormat(0); 726 | ELECHOUSE_cc1101.SetRx(); 727 | } 728 | else { Serial.print(F("Wrong parameters.\r\n")); }; 729 | 730 | // handling RXRAW command - sniffer 731 | } else if (strcmp_P(command, PSTR("rxraw")) == 0) { 732 | // take interval period for samplink 733 | setting = atoi(cmdline); 734 | if (setting>0) 735 | { 736 | // setup async mode on CC1101 with GDO0 pin processing 737 | ELECHOUSE_cc1101.setCCMode(0); 738 | ELECHOUSE_cc1101.setPktFormat(3); 739 | ELECHOUSE_cc1101.SetRx(); 740 | //start recording to the buffer with bitbanging of GDO0 pin state 741 | Serial.print(F("\r\nSniffer enabled...\r\n")); 742 | pinMode(gdo0, INPUT); 743 | 744 | 745 | 746 | // Any received char over Serial port stops printing RF received bytes 747 | while (!Serial.available()) 748 | { 749 | 750 | // we have to use the buffer not to introduce delays 751 | for (int i=0; i -1; j--) // 8 bits in a byte 755 | { 756 | bitWrite(receivedbyte, j, digitalRead(gdo0)); // Capture GDO0 state into the byte 757 | delayMicroseconds(setting); // delay for selected sampling interval 758 | }; 759 | // store the output into recording buffer 760 | bigrecordingbuffer[i] = receivedbyte; 761 | }; 762 | // when buffer full print the ouptput to serial port 763 | for (int i = 0; i < RECORDINGBUFFERSIZE ; i = i + 32) 764 | { 765 | asciitohex(&bigrecordingbuffer[i], textbuffer, 32); 766 | Serial.print((char *)textbuffer); 767 | }; 768 | 769 | 770 | }; // end of While loop 771 | 772 | Serial.print(F("\r\nStopping the sniffer.\n\r\n")); 773 | 774 | // setting normal pkt format again 775 | ELECHOUSE_cc1101.setCCMode(1); 776 | ELECHOUSE_cc1101.setPktFormat(0); 777 | ELECHOUSE_cc1101.SetRx(); 778 | } 779 | else { Serial.print(F("Wrong parameters.\r\n")); }; 780 | 781 | 782 | // handling PLAYRAW command 783 | } else if (strcmp_P(command, PSTR("playraw")) == 0) { 784 | // take interval period for sampling 785 | setting = atoi(cmdline); 786 | if (setting>0) 787 | { 788 | // setup async mode on CC1101 and go into TX mode 789 | // with GDO0 pin processing 790 | ELECHOUSE_cc1101.setCCMode(0); 791 | ELECHOUSE_cc1101.setPktFormat(3); 792 | ELECHOUSE_cc1101.SetTx(); 793 | //start replaying GDO0 bit state from data in the buffer with bitbanging 794 | Serial.print(F("\r\nReplaying RAW data from the buffer...\r\n")); 795 | pinMode(gdo0, OUTPUT); 796 | 797 | 798 | for (int i=1; i -1; j--) // 8 bits in a byte 802 | { 803 | digitalWrite(gdo0, bitRead(receivedbyte, j)); // Set GDO0 according to recorded byte 804 | delayMicroseconds(setting); // delay for selected sampling interval 805 | }; 806 | } 807 | 808 | 809 | Serial.print(F("\r\nReplaying RAW data complete.\r\n\r\n")); 810 | // setting normal pkt format again 811 | ELECHOUSE_cc1101.setCCMode(1); 812 | ELECHOUSE_cc1101.setPktFormat(0); 813 | ELECHOUSE_cc1101.SetTx(); 814 | // pinMode(gdo0pin, INPUT); 815 | } 816 | else { Serial.print(F("Wrong parameters.\r\n")); }; 817 | 818 | // handling SHOWRAW command 819 | } else if (strcmp_P(command, PSTR("showraw")) == 0) { 820 | // show the content of recorded RAW signal as hex numbers 821 | Serial.print(F("\r\nRecorded RAW data:\r\n")); 822 | for (int i = 0; i < RECORDINGBUFFERSIZE ; i = i + 32) 823 | { 824 | asciitohex(&bigrecordingbuffer[i], textbuffer, 32); 825 | Serial.print((char *)textbuffer); 826 | } 827 | Serial.print(F("\r\n\r\n")); 828 | 829 | 830 | // handling SHOWBIT command 831 | } else if (strcmp_P(command, PSTR("showbit")) == 0) { 832 | // show the content of recorded RAW signal as hex numbers 833 | Serial.print(F("\r\nRecorded RAW data as bit stream:\r\n")); 834 | for (int i = 0; i < RECORDINGBUFFERSIZE ; i = i + 32) 835 | { // first convert to hex numbers 836 | asciitohex((byte *)&bigrecordingbuffer[i], (byte *)textbuffer, 32); 837 | // now decode as binary and print 838 | for (setting = 0; setting < 64 ; setting++) 839 | { 840 | setting2 = textbuffer[setting]; 841 | switch( setting2 ) 842 | { 843 | case '0': 844 | Serial.print(F("____")); 845 | break; 846 | 847 | case '1': 848 | Serial.print(F("___-")); 849 | break; 850 | 851 | case '2': 852 | Serial.print(F("__-_")); 853 | break; 854 | 855 | case '3': 856 | Serial.print(F("__--")); 857 | break; 858 | 859 | case '4': 860 | Serial.print(F("_-__")); 861 | break; 862 | 863 | case '5': 864 | Serial.print(F("_-_-")); 865 | break; 866 | 867 | case '6': 868 | Serial.print(F("_--_")); 869 | break; 870 | 871 | case '7': 872 | Serial.print(F("_---")); 873 | break; 874 | 875 | case '8': 876 | Serial.print(F("-___")); 877 | break; 878 | 879 | case '9': 880 | Serial.print(F("-__-")); 881 | break; 882 | 883 | case 'A': 884 | Serial.print(F("-_-_")); 885 | break; 886 | 887 | case 'B': 888 | Serial.print(F("-_--")); 889 | break; 890 | 891 | case 'C': 892 | Serial.print(F("--__")); 893 | break; 894 | 895 | case 'D': 896 | Serial.print(F("--_-")); 897 | break; 898 | 899 | case 'E': 900 | Serial.print(F("---_")); 901 | break; 902 | 903 | case 'F': 904 | Serial.print(F("----")); 905 | break; 906 | 907 | }; // end of switch 908 | 909 | }; // end of for 910 | 911 | } // end of for 912 | Serial.print(F("\r\n\r\n")); 913 | 914 | 915 | 916 | // Handling ADDRAW command 917 | } else if (strcmp_P(command, PSTR("addraw")) == 0) { 918 | // getting hex numbers - the content of the frame 919 | len = strlen(cmdline); 920 | // convert hex array to set of bytes 921 | if ((len<=120) && (len>0) ) 922 | { 923 | // convert the hex content to array of bytes 924 | hextoascii(textbuffer, (byte *)cmdline, len); 925 | len = len /2; 926 | // check if the frame fits into the buffer and store it 927 | if (( bigrecordingbufferpos + len) < RECORDINGBUFFERSIZE) 928 | { // copy current frame and increase pointer for next frames 929 | memcpy(&bigrecordingbuffer[bigrecordingbufferpos], &textbuffer, len ); 930 | // increase position in big recording buffer for next frame 931 | bigrecordingbufferpos = bigrecordingbufferpos + len; 932 | Serial.print(F("\r\nChunk added to recording buffer\r\n\r\n")); 933 | } 934 | else 935 | { 936 | Serial.print(F("\r\nBuffer is full. The frame does not fit.\r\n ")); 937 | }; 938 | } 939 | else { Serial.print(F("Wrong parameters.\r\n")); }; 940 | 941 | 942 | 943 | // Handling REC command 944 | } else if (strcmp_P(command, PSTR("rec")) == 0) { 945 | Serial.print(F("\r\nRecording mode set to ")); 946 | if (recordingmode == 1) 947 | { 948 | Serial.print(F("Disabled")); 949 | bigrecordingbufferpos = 0; 950 | recordingmode = 0; 951 | } 952 | else if (recordingmode == 0) 953 | { ELECHOUSE_cc1101.SetRx(); 954 | Serial.print(F("Enabled")); 955 | bigrecordingbufferpos = 0; 956 | // flush buffer for recording 957 | for (int i = 0; i < RECORDINGBUFFERSIZE; i++) 958 | { bigrecordingbuffer[RECORDINGBUFFERSIZE] = 0; }; 959 | recordingmode = 1; 960 | jammingmode = 0; 961 | receivingmode = 0; 962 | // start counting frames in the buffer 963 | framesinbigrecordingbuffer = 0; 964 | }; 965 | Serial.print(F("\r\n")); 966 | 967 | 968 | // Handling PLAY command 969 | } else if (strcmp_P(command, PSTR("play")) == 0) { 970 | setting = atoi(strsep(&cmdline, " ")); 971 | // if number of played frames is 0 it means play all frames 972 | if (setting <= framesinbigrecordingbuffer) 973 | { 974 | Serial.print(F("\r\nReplaying recorded frames.\r\n ")); 975 | // rewind recording buffer position to the beginning 976 | bigrecordingbufferpos = 0; 977 | if (framesinbigrecordingbuffer >0) 978 | { 979 | 980 | // start reading and sending frames from the buffer : FIFO 981 | for (int i=1; i<=framesinbigrecordingbuffer ; i++) 982 | { 983 | // read length of the recorded frame first from the buffer 984 | len = bigrecordingbuffer[bigrecordingbufferpos]; 985 | if ( ((len<=60) and (len>0)) and ((i == setting) or (setting == 0)) ) 986 | { 987 | // take next frame from the buffer for replay 988 | memcpy(ccsendingbuffer, &bigrecordingbuffer[bigrecordingbufferpos + 1], len ); 989 | // send these data to radio over CC1101 990 | ELECHOUSE_cc1101.SendData(ccsendingbuffer, (byte)len); 991 | }; 992 | // increase position to the buffer and check exception 993 | bigrecordingbufferpos = bigrecordingbufferpos + 1 + len; 994 | if ( bigrecordingbufferpos > RECORDINGBUFFERSIZE) break; 995 | // 996 | }; 997 | }; // end of IF framesinrecordingbuffer 998 | 999 | // rewind buffer position 1000 | bigrecordingbufferpos = 0; 1001 | Serial.print(F("Done.\r\n")); 1002 | } 1003 | else { Serial.print(F("Wrong parameters.\r\n")); }; 1004 | 1005 | 1006 | // Handling ADD command 1007 | } else if (strcmp_P(command, PSTR("add")) == 0) { 1008 | // getting hex numbers - the content of the frame 1009 | len = strlen(cmdline); 1010 | // convert hex array to set of bytes 1011 | if ((len<=120) && (len>0) ) 1012 | { 1013 | // convert the hex content to array of bytes 1014 | hextoascii(textbuffer,(byte *)cmdline, len); 1015 | len = len /2; 1016 | // check if the frame fits into the buffer and store it 1017 | if (( bigrecordingbufferpos + len + 1) < RECORDINGBUFFERSIZE) 1018 | { // put info about number of bytes 1019 | bigrecordingbuffer[bigrecordingbufferpos] = len; 1020 | bigrecordingbufferpos++; 1021 | // next - copy current frame and increase 1022 | memcpy(&bigrecordingbuffer[bigrecordingbufferpos], &textbuffer, len ); 1023 | // increase position in big recording buffer for next frame 1024 | bigrecordingbufferpos = bigrecordingbufferpos + len; 1025 | // increase counter of frames stored 1026 | framesinbigrecordingbuffer++; 1027 | Serial.print(F("\r\nAdded frame number ")); 1028 | Serial.print(framesinbigrecordingbuffer); 1029 | Serial.print(F("\r\n")); 1030 | } 1031 | else 1032 | { 1033 | Serial.print(F("\r\nBuffer is full. The frame does not fit.\r\n ")); 1034 | }; 1035 | } 1036 | else { Serial.print(F("Wrong parameters.\r\n")); }; 1037 | 1038 | 1039 | 1040 | // Handling SHOW command 1041 | } else if (strcmp_P(command, PSTR("show")) == 0) { 1042 | if (framesinbigrecordingbuffer>0) 1043 | { 1044 | Serial.print(F("\r\nFrames stored in the recording buffer:\r\n ")); 1045 | // rewind recording buffer position to the beginning 1046 | bigrecordingbufferpos = 0; 1047 | // start reading and sending frames from the buffer : FIFO 1048 | for (setting=1; setting<=framesinbigrecordingbuffer; setting++) 1049 | { 1050 | // read length of the recorded frame first from the buffer 1051 | len = bigrecordingbuffer[bigrecordingbufferpos]; 1052 | if ((len<=60) and (len>0)) 1053 | { 1054 | // take next frame from the buffer for replay 1055 | // flush textbuffer 1056 | for (setting2 = 0; setting2 < BUF_LENGTH; setting2++) 1057 | { textbuffer[setting2] = 0; }; 1058 | asciitohex(&bigrecordingbuffer[bigrecordingbufferpos + 1], textbuffer, len); 1059 | Serial.print(F("\r\nFrame ")); 1060 | Serial.print(setting); 1061 | Serial.print(F(" : ")); 1062 | Serial.print((char *)textbuffer); 1063 | Serial.print(F("\r\n")); 1064 | }; 1065 | // increase position to the buffer and check exception 1066 | bigrecordingbufferpos = bigrecordingbufferpos + 1 + len; 1067 | if ( bigrecordingbufferpos > RECORDINGBUFFERSIZE) break; 1068 | // 1069 | }; 1070 | // rewind buffer position 1071 | // bigrecordingbufferpos = 0; 1072 | Serial.print(F("\r\n")); 1073 | } 1074 | else { Serial.print(F("Wrong parameters.\r\n")); }; 1075 | 1076 | 1077 | // Handling FLUSH command 1078 | } else if (strcmp_P(command, PSTR("flush")) == 0) { 1079 | // flushing bigrecordingbuffer with zeros and rewinding all the pointers 1080 | for (setting = 0; setting 20 | #include 21 | 22 | #define CCBUFFERSIZE 64 23 | #define RECORDINGBUFFERSIZE 4096 // Buffer for recording the frames 24 | #define EPROMSIZE 512 // Size of EEPROM in your Arduino chip. For ESP32 it is Flash simulated only 512 bytes, ESP8266 is 4096 25 | #define BUF_LENGTH 128 // Buffer for the incoming command. 26 | 27 | // defining PINs set for ESP32 module 28 | // Example for XIAO ESP32 C3 29 | byte sck = 8; // GPIO 8 30 | byte miso = 4; // GPIO 4 31 | byte mosi = 10; // GPIO 10 32 | byte ss = 20; // GPIO 20 33 | int gdo0 = 21; // GPIO 21 34 | int gdo2 = 7; // GPIO 7 35 | 36 | // defining PINs set for ESP32 WROOM module 37 | /* 38 | byte sck = 18; // GPIO 18 39 | byte miso = 19; // GPIO 19 40 | byte mosi = 23; // GPIO 41 | byte ss = 5; // GPIO 5 42 | int gdo0 = 2; // GPIO 2 43 | int gdo2 = 4; // GPIO 4 44 | */ 45 | 46 | // position in big recording buffer 47 | int bigrecordingbufferpos = 0; 48 | 49 | // number of frames in big recording buffer 50 | int framesinbigrecordingbuffer = 0; 51 | 52 | // check if CLI receiving mode enabled 53 | int receivingmode = 0; 54 | 55 | // check if CLI jamming mode enabled 56 | int jammingmode = 0; 57 | 58 | // check if CLI recording mode enabled 59 | int recordingmode = 0; 60 | 61 | // check if CLI chat mode enabled 62 | int chatmode = 0; 63 | 64 | static bool do_echo = true; 65 | 66 | // buffer for receiving CC1101 67 | byte ccreceivingbuffer[CCBUFFERSIZE] = {0}; 68 | 69 | // buffer for sending CC1101 70 | byte ccsendingbuffer[CCBUFFERSIZE] = {0}; 71 | //char ccsendingbuffer[CCBUFFERSIZE] = {0}; 72 | 73 | // buffer for recording and replaying of many frames 74 | byte bigrecordingbuffer[RECORDINGBUFFERSIZE] = {0}; 75 | 76 | // buffer for hex to ascii conversions 77 | byte textbuffer[BUF_LENGTH]; 78 | //char textbuffer[BUF_LENGTH]; 79 | 80 | 81 | 82 | // convert bytes in table to string with hex numbers 83 | void asciitohex(byte *ascii_ptr, byte *hex_ptr,int len) 84 | { 85 | byte i,j,k; 86 | for(i = 0; i < len; i++) 87 | { 88 | // high byte first 89 | j = ascii_ptr[i] / 16; 90 | if (j>9) 91 | { k = j - 10 + 65; } 92 | else 93 | { k = j + 48; } 94 | hex_ptr[2*i] = k ; 95 | // low byte second 96 | j = ascii_ptr[i] % 16; 97 | if (j>9) 98 | { k = j - 10 + 65; } 99 | else 100 | { k = j + 48; } 101 | hex_ptr[(2*i)+1] = k ; 102 | }; 103 | hex_ptr[(2*i)+2] = '\0' ; 104 | } 105 | 106 | 107 | // convert string with hex numbers to array of bytes 108 | void hextoascii(byte *ascii_ptr, byte *hex_ptr,int len) 109 | { 110 | byte i,j; 111 | for(i = 0; i < (len/2); i++) 112 | { 113 | j = hex_ptr[i*2]; 114 | if ((j>47) && (j<58)) ascii_ptr[i] = (j - 48) * 16; 115 | if ((j>64) && (j<71)) ascii_ptr[i] = (j - 55) * 16; 116 | if ((j>96) && (j<103)) ascii_ptr[i] = (j - 87) * 16; 117 | j = hex_ptr[i*2+1]; 118 | if ((j>47) && (j<58)) ascii_ptr[i] = ascii_ptr[i] + (j - 48); 119 | if ((j>64) && (j<71)) ascii_ptr[i] = ascii_ptr[i] + (j - 55); 120 | if ((j>96) && (j<103)) ascii_ptr[i] = ascii_ptr[i] + (j - 87); 121 | }; 122 | ascii_ptr[i++] = '\0' ; 123 | } 124 | 125 | // Initialize CC1101 board with default settings, you may change your preferences here 126 | static void cc1101initialize(void) 127 | { 128 | // initializing library with custom pins selected 129 | ELECHOUSE_cc1101.setSpiPin(sck, miso, mosi, ss); 130 | ELECHOUSE_cc1101.setGDO(gdo0, gdo2); 131 | 132 | // Main part to tune CC1101 with proper frequency, modulation and encoding 133 | ELECHOUSE_cc1101.Init(); // must be set to initialize the cc1101! 134 | ELECHOUSE_cc1101.setGDO0(gdo0); // set lib internal gdo pin (gdo0). Gdo2 not use for this example. 135 | ELECHOUSE_cc1101.setCCMode(1); // set config for internal transmission mode. value 0 is for RAW recording/replaying 136 | ELECHOUSE_cc1101.setModulation(2); // set modulation mode. 0 = 2-FSK, 1 = GFSK, 2 = ASK/OOK, 3 = 4-FSK, 4 = MSK. 137 | ELECHOUSE_cc1101.setMHZ(433.92); // Here you can set your basic frequency. The lib calculates the frequency automatically (default = 433.92).The cc1101 can: 300-348 MHZ, 387-464MHZ and 779-928MHZ. Read More info from datasheet. 138 | ELECHOUSE_cc1101.setDeviation(47.60); // Set the Frequency deviation in kHz. Value from 1.58 to 380.85. Default is 47.60 kHz. 139 | ELECHOUSE_cc1101.setChannel(0); // Set the Channelnumber from 0 to 255. Default is cahnnel 0. 140 | ELECHOUSE_cc1101.setChsp(199.95); // The channel spacing is multiplied by the channel number CHAN and added to the base frequency in kHz. Value from 25.39 to 405.45. Default is 199.95 kHz. 141 | ELECHOUSE_cc1101.setRxBW(812.50); // Set the Receive Bandwidth in kHz. Value from 58.03 to 812.50. Default is 812.50 kHz. 142 | ELECHOUSE_cc1101.setDRate(9.6); // Set the Data Rate in kBaud. Value from 0.02 to 1621.83. Default is 99.97 kBaud! 143 | ELECHOUSE_cc1101.setPA(10); // Set TxPower. The following settings are possible depending on the frequency band. (-30 -20 -15 -10 -6 0 5 7 10 11 12) Default is max! 144 | ELECHOUSE_cc1101.setSyncMode(2); // Combined sync-word qualifier mode. 0 = No preamble/sync. 1 = 16 sync word bits detected. 2 = 16/16 sync word bits detected. 3 = 30/32 sync word bits detected. 4 = No preamble/sync, carrier-sense above threshold. 5 = 15/16 + carrier-sense above threshold. 6 = 16/16 + carrier-sense above threshold. 7 = 30/32 + carrier-sense above threshold. 145 | ELECHOUSE_cc1101.setSyncWord(211, 145); // Set sync word. Must be the same for the transmitter and receiver. Default is 211,145 (Syncword high, Syncword low) 146 | ELECHOUSE_cc1101.setAdrChk(0); // Controls address check configuration of received packages. 0 = No address check. 1 = Address check, no broadcast. 2 = Address check and 0 (0x00) broadcast. 3 = Address check and 0 (0x00) and 255 (0xFF) broadcast. 147 | ELECHOUSE_cc1101.setAddr(0); // Address used for packet filtration. Optional broadcast addresses are 0 (0x00) and 255 (0xFF). 148 | ELECHOUSE_cc1101.setWhiteData(0); // Turn data whitening on / off. 0 = Whitening off. 1 = Whitening on. 149 | ELECHOUSE_cc1101.setPktFormat(0); // Format of RX and TX data. 0 = Normal mode, use FIFOs for RX and TX. 1 = Synchronous serial mode, Data in on GDO0 and data out on either of the GDOx pins. 2 = Random TX mode; sends random data using PN9 generator. Used for test. Works as normal mode, setting 0 (00), in RX. 3 = Asynchronous serial mode, Data in on GDO0 and data out on either of the GDOx pins. 150 | ELECHOUSE_cc1101.setLengthConfig(1); // 0 = Fixed packet length mode. 1 = Variable packet length mode. 2 = Infinite packet length mode. 3 = Reserved 151 | ELECHOUSE_cc1101.setPacketLength(0); // Indicates the packet length when fixed packet length mode is enabled. If variable packet length mode is used, this value indicates the maximum packet length allowed. 152 | ELECHOUSE_cc1101.setCrc(0); // 1 = CRC calculation in TX and CRC check in RX enabled. 0 = CRC disabled for TX and RX. 153 | ELECHOUSE_cc1101.setCRC_AF(0); // Enable automatic flush of RX FIFO when CRC is not OK. This requires that only one packet is in the RXIFIFO and that packet length is limited to the RX FIFO size. 154 | ELECHOUSE_cc1101.setDcFilterOff(0); // Disable digital DC blocking filter before demodulator. Only for data rates ≤ 250 kBaud The recommended IF frequency changes when the DC blocking is disabled. 1 = Disable (current optimized). 0 = Enable (better sensitivity). 155 | ELECHOUSE_cc1101.setManchester(0); // Enables Manchester encoding/decoding. 0 = Disable. 1 = Enable. 156 | ELECHOUSE_cc1101.setFEC(0); // Enable Forward Error Correction (FEC) with interleaving for packet payload (Only supported for fixed packet length mode. 0 = Disable. 1 = Enable. 157 | ELECHOUSE_cc1101.setPRE(0); // Sets the minimum number of preamble bytes to be transmitted. Values: 0 : 2, 1 : 3, 2 : 4, 3 : 6, 4 : 8, 5 : 12, 6 : 16, 7 : 24 158 | ELECHOUSE_cc1101.setPQT(0); // Preamble quality estimator threshold. The preamble quality estimator increases an internal counter by one each time a bit is received that is different from the previous bit, and decreases the counter by 8 each time a bit is received that is the same as the last bit. A threshold of 4∙PQT for this counter is used to gate sync word detection. When PQT=0 a sync word is always accepted. 159 | ELECHOUSE_cc1101.setAppendStatus(0); // When enabled, two status bytes will be appended to the payload of the packet. The status bytes contain RSSI and LQI values, as well as CRC OK. 160 | } 161 | 162 | 163 | // Execute a complete CC1101 command. 164 | 165 | static void exec(char *cmdline) 166 | { 167 | 168 | char *command = strsep(&cmdline, " "); 169 | int setting, setting2, len; 170 | uint16_t brute, poweroftwo; 171 | byte j, k; 172 | float settingf1; 173 | float settingf2; 174 | // variables for frequency scanner 175 | float freq; 176 | long compare_freq; 177 | float mark_freq; 178 | int rssi; 179 | int mark_rssi=-100; 180 | 181 | // identification of the command & actions 182 | 183 | if (strcmp_P(command, PSTR("help")) == 0) { 184 | Serial.println(F( 185 | "setmodulation : Set modulation mode. 0 = 2-FSK, 1 = GFSK, 2 = ASK/OOK, 3 = 4-FSK, 4 = MSK.\r\n\r\n" 186 | "setmhz : Here you can set your basic frequency. default = 433.92).The cc1101 can: 300-348 MHZ, 387-464MHZ and 779-928MHZ.\r\n\r\n" 187 | "setdeviation : Set the Frequency deviation in kHz. Value from 1.58 to 380.85.\r\n\r\n" 188 | "setchannel : Set the Channelnumber from 0 to 255. Default is cahnnel 0.\r\n\r\n" 189 | "setchsp : The channel spacing is multiplied by the channel number CHAN and added to the base frequency in kHz. Value from 25.39 to 405.45. \r\n\r\n" 190 | "setrxbw : Set the Receive Bandwidth in kHz. Value from 58.03 to 812.50. \r\n\r\n" 191 | "setdrate : Set the Data Rate in kBaud. Value from 0.02 to 1621.83.\r\n\r\n" 192 | "setpa : Set RF transmission power. The following settings are possible depending on the frequency band. (-30 -20 -15 -10 -6 0 5 7 10 11 12) Default is max!\r\n\r\n" 193 | "setsyncmode : Combined sync-word qualifier mode. 0 = No preamble/sync. 1 = 16 sync word bits detected. 2 = 16/16 sync word bits detected. 3 = 30/32 sync word bits detected. 4 = No preamble/sync, carrier-sense above threshold. 5 = 15/16 + carrier-sense above threshold. 6 = 16/16 + carrier-sense above threshold. 7 = 30/32 + carrier-sense above threshold.\r\n" 194 | )); 195 | Serial.println(F( 196 | "setsyncword : Set sync word. Must be the same for the transmitter and receiver. (Syncword high, Syncword low) Default is 211,145\r\n\r\n" 197 | "setadrchk
: Controls address check configuration of received packages. 0 = No address check. 1 = Address check, no broadcast. 2 = Address check and 0 (0x00) broadcast. 3 = Address check and 0 (0x00) and 255 (0xFF) broadcast.\r\n\r\n" 198 | "setaddr
: Address used for packet filtration. Optional broadcast addresses are 0 (0x00) and 255 (0xFF).\r\n\r\n" 199 | "setwhitedata : Turn data whitening on / off. 0 = Whitening off. 1 = Whitening on.\r\n\r\n" 200 | "setpktformat : Format of RX and TX data. 0 = Normal mode, use FIFOs for RX and TX. 1 = Synchronous serial mode, Data in on GDO0 and data out on either of the GDOx pins. 2 = Random TX mode; sends random data using PN9 generator. 3 = Asynchronous serial mode\r\n\r\n" 201 | "setlengthconfig : Set packet Length mode : 0 = Fixed packet length mode. 1 = Variable packet length mode. 2 = Infinite packet length mode. 3 = Reserved \r\n\r\n" 202 | "setpacketlength : Indicates the packet length when fixed packet length mode is enabled. If variable packet length mode is used, this value indicates the maximum packet length allowed.\r\n\r\n" 203 | "setcrc : Switches on/of CRC calculation and check. 1 = CRC calculation in TX and CRC check in RX enabled. 0 = CRC disabled for TX and RX.\r\n\r\n" 204 | "setcrcaf : Enable automatic flush of RX FIFO when CRC is not OK. This requires that only one packet is in the RXIFIFO and that packet length is limited to the RX FIFO size.\r\n" 205 | )); 206 | Serial.println(F( 207 | "setdcfilteroff : Disable digital DC blocking filter before demodulator. Only for data rates ≤ 250 kBaud The recommended IF frequency changes when the DC blocking is disabled. 1 = Disable (current optimized). 0 = Enable (better sensitivity).\r\n\r\n" 208 | "setmanchester : Enables Manchester encoding/decoding. 0 = Disable. 1 = Enable.\r\n\r\n" 209 | "setfec : Enable Forward Error Correction (FEC) with interleaving for packet payload (Only supported for fixed packet length mode. 0 = Disable. 1 = Enable.\r\n\r\n" 210 | "setpre : Sets the minimum number of preamble bytes to be transmitted. Values: 0 : 2, 1 : 3, 2 : 4, 3 : 6, 4 : 8, 5 : 12, 6 : 16, 7 : 24\r\n\r\n" 211 | "setpqt : Preamble quality estimator threshold. \r\n\r\n" 212 | "setappendstatus : When enabled, two status bytes will be appended to the payload of the packet. The status bytes contain RSSI and LQI values, as well as CRC OK.\r\n\r\n" 213 | "getrssi : Display quality information about last received frames over RF\r\n\r\n" 214 | "scan : Scan frequency range for the highest signal.\r\n\r\n" 215 | "chat : Enable chat mode between many devices. No exit available, disconnect device to quit\r\n" 216 | )); 217 | Serial.println(F( 218 | "rx : Sniffer. Enable or disable printing of received RF packets on serial terminal.\r\n\r\n" 219 | "tx : Send packet of max 60 bytes over RF\r\n\r\n" 220 | "jam : Enable or disable continous jamming on selected band.\r\n\r\n" 221 | "brute : Brute force garage gate with keyword where symbol time is .\r\n\r\n" 222 | "rec : Enable or disable recording frames in the buffer.\r\n\r\n" 223 | "add : Manually add single frame payload (max 64 hex values) to the buffer so it can be replayed\r\n\r\n" 224 | "show : Show content of recording buffer\r\n\r\n" 225 | "flush : Clear the recording buffer\r\n\r\n" 226 | "play : Replay 0 = all frames or N-th recorded frame previously stored in the buffer.\r\n\r\n" 227 | "rxraw : Sniffs radio by sampling with interval and prints received bytes in hex.\r\n\r\n" 228 | "recraw : Recording RAW RF data with sampling interval.\r\n" 229 | )); 230 | Serial.println(F( 231 | "addraw : Manually add chunks (max 60 hex values) to the buffer so they can be further replayed.\r\n\r\n" 232 | "showraw : Showing content of recording buffer in RAW format.\r\n\r\n" 233 | "playraw : Replaying previously recorded RAW RF data with sampling interval.\r\n\r\n" 234 | "showbit : Showing content of recording buffer in RAW format as a stream of bits.\r\n\r\n" 235 | "save : Store recording buffer content in non-volatile memory\r\n\r\n" 236 | "load : Load the content from non-volatile memory to the recording buffer\r\n\r\n" 237 | "echo : Enable or disable Echo on serial terminal. 1 = enabled, 0 = disabled\r\n\r\n" 238 | "x : Stops jamming/receiving/recording packets.\r\n\r\n" 239 | "init : Restarts CC1101 board with default parameters\r\n\r\n" 240 | )); 241 | 242 | // Handling SETMODULATION command 243 | } else if (strcmp_P(command, PSTR("setmodulation")) == 0) { 244 | setting = atoi(cmdline); 245 | ELECHOUSE_cc1101.setModulation(setting); 246 | Serial.print(F("\r\nModulation: ")); 247 | if (setting == 0) { Serial.print(F("2-FSK")); } 248 | else if (setting == 1) { Serial.print(F("GFSK")); } 249 | else if (setting == 2) { Serial.print(F("ASK/OOK")); } 250 | else if (setting == 3) { Serial.print(F("4-FSK")); } 251 | else if (setting == 4) { Serial.print(F("MSK")); }; 252 | Serial.print(F(" \r\n")); 253 | 254 | // Handling SETMHZ command 255 | } else if (strcmp_P(command, PSTR("setmhz")) == 0) { 256 | settingf1 = atof(cmdline); 257 | ELECHOUSE_cc1101.setMHZ(settingf1); 258 | Serial.print(F("\r\nFrequency: ")); 259 | Serial.print(settingf1); 260 | Serial.print(F(" MHz\r\n")); 261 | 262 | // Handling SETDEVIATION command 263 | } else if (strcmp_P(command, PSTR("setdeviation")) == 0) { 264 | settingf1 = atof(cmdline); 265 | ELECHOUSE_cc1101.setDeviation(settingf1); 266 | Serial.print(F("\r\nDeviation: ")); 267 | Serial.print(settingf1); 268 | Serial.print(F(" KHz\r\n")); 269 | 270 | // Handling SETCHANNEL command 271 | } else if (strcmp_P(command, PSTR("setchannel")) == 0) { 272 | setting = atoi(cmdline); 273 | ELECHOUSE_cc1101.setChannel(setting); 274 | Serial.print(F("\r\nChannel:")); 275 | Serial.print(setting); 276 | Serial.print(F("\r\n")); 277 | 278 | // Handling SETCHSP command 279 | } else if (strcmp_P(command, PSTR("setchsp")) == 0) { 280 | settingf1 = atof(cmdline); 281 | ELECHOUSE_cc1101.setChsp(settingf1); 282 | Serial.print(F("\r\nChann spacing: ")); 283 | Serial.print(settingf1); 284 | Serial.print(F(" kHz\r\n")); 285 | 286 | // Handling SETRXBW command 287 | } else if (strcmp_P(command, PSTR("setrxbw")) == 0) { 288 | settingf1 = atof(cmdline); 289 | ELECHOUSE_cc1101.setRxBW(settingf1); 290 | Serial.print(F("\r\nRX bandwidth: ")); 291 | Serial.print(settingf1); 292 | Serial.print(F(" kHz \r\n")); 293 | 294 | // Handling SETDRATE command 295 | } else if (strcmp_P(command, PSTR("setdrate")) == 0) { 296 | settingf1 = atof(cmdline); 297 | ELECHOUSE_cc1101.setDRate(settingf1); 298 | Serial.print(F("\r\nDatarate: ")); 299 | Serial.print(settingf1); 300 | Serial.print(F(" kbaud\r\n")); 301 | 302 | // Handling SETPA command 303 | } else if (strcmp_P(command, PSTR("setpa")) == 0) { 304 | setting = atoi(cmdline); 305 | ELECHOUSE_cc1101.setPA(setting); 306 | Serial.print(F("\r\nTX PWR: ")); 307 | Serial.print(setting); 308 | Serial.print(F(" dBm\r\n")); 309 | 310 | // Handling SETSYNCMODE command 311 | } else if (strcmp_P(command, PSTR("setsyncmode")) == 0) { 312 | int setting = atoi(cmdline); 313 | ELECHOUSE_cc1101.setSyncMode(setting); 314 | Serial.print(F("\r\nSynchronization: ")); 315 | if (setting == 0) { Serial.print(F("No preamble")); } 316 | else if (setting == 1) { Serial.print(F("16 sync bits")); } 317 | else if (setting == 2) { Serial.print(F("16/16 sync bits")); } 318 | else if (setting == 3) { Serial.print(F("30/32 sync bits")); } 319 | else if (setting == 4) { Serial.print(F("No preamble/sync, carrier-sense")); } 320 | else if (setting == 5) { Serial.print(F("15/16 + carrier-sense")); } 321 | else if (setting == 6) { Serial.print(F("16/16 + carrier-sense")); } 322 | else if (setting == 7) { Serial.print(F("30/32 + carrier-sense")); }; 323 | Serial.print(F("\r\n")); 324 | 325 | // Handling SETSYNCWORD command 326 | } else if (strcmp_P(command, PSTR("setsyncword")) == 0) { 327 | setting = atoi(strsep(&cmdline, " ")); 328 | setting2 = atoi(cmdline); 329 | ELECHOUSE_cc1101.setSyncWord(setting2, setting); 330 | Serial.print(F("\r\nSynchronization:\r\n")); 331 | Serial.print(F("high = ")); 332 | Serial.print(setting); 333 | Serial.print(F("\r\nlow = ")); 334 | Serial.print(setting2); 335 | Serial.print(F("\r\n")); 336 | 337 | 338 | // Handling SETADRCHK command 339 | } else if (strcmp_P(command, PSTR("setadrchk")) == 0) { 340 | setting = atoi(cmdline); 341 | ELECHOUSE_cc1101.setAdrChk(setting); 342 | Serial.print(F("\r\nAddress checking:")); 343 | if (setting == 0) { Serial.print(F("No adr chk")); } 344 | else if (setting == 1) { Serial.print(F("Adr chk, no bcast")); } 345 | else if (setting == 2) { Serial.print(F("Adr chk and 0 bcast")); } 346 | else if (setting == 3) { Serial.print(F("Adr chk and 0 and FF bcast")); }; 347 | Serial.print(F("\r\n")); 348 | 349 | // Handling SETADDR command 350 | } else if (strcmp_P(command, PSTR("setaddr")) == 0) { 351 | setting = atoi(cmdline); 352 | ELECHOUSE_cc1101.setAddr(setting); 353 | Serial.print(F("\r\nAddress: ")); 354 | Serial.print(setting); 355 | Serial.print(F("\r\n")); 356 | 357 | // Handling SETWHITEDATA command 358 | } else if (strcmp_P(command, PSTR("setwhitedata")) == 0) { 359 | setting = atoi(cmdline); 360 | ELECHOUSE_cc1101.setWhiteData(setting); 361 | Serial.print(F("\r\nWhitening ")); 362 | if (setting == 0) { Serial.print(F("OFF")); } 363 | else if (setting == 1) { Serial.print(F("ON")); } 364 | Serial.print(F("\r\n")); 365 | 366 | // Handling SETPKTFORMAT command 367 | } else if (strcmp_P(command, PSTR("setpktformat")) == 0) { 368 | setting = atoi(cmdline); 369 | ELECHOUSE_cc1101.setPktFormat(setting); 370 | Serial.print(F("\r\nPacket format: ")); 371 | if (setting == 0) { Serial.print(F("Normal mode")); } 372 | else if (setting == 1) { Serial.print(F("Synchronous serial mode")); } 373 | else if (setting == 2) { Serial.print(F("Random TX mode")); } 374 | else if (setting == 3) { Serial.print(F("Asynchronous serial mode")); }; 375 | Serial.print(F("\r\n")); 376 | 377 | // Handling SETLENGTHCONFIG command 378 | } else if (strcmp_P(command, PSTR("setlengthconfig")) == 0) { 379 | setting = atoi(cmdline); 380 | ELECHOUSE_cc1101.setLengthConfig(setting); 381 | Serial.print(F("\r\nPkt length mode: ")); 382 | if (setting == 0) { Serial.print(F("Fixed")); } 383 | else if (setting == 1) { Serial.print(F("Variable")); } 384 | else if (setting == 2) { Serial.print(F("Infinite")); } 385 | else if (setting == 3) { Serial.print(F("Reserved")); }; 386 | Serial.print(F("\r\n")); 387 | 388 | // Handling SETPACKETLENGTH command 389 | } else if (strcmp_P(command, PSTR("setpacketlength")) == 0) { 390 | setting = atoi(cmdline); 391 | ELECHOUSE_cc1101.setPacketLength(setting); 392 | Serial.print(F("\r\nPkt length: ")); 393 | Serial.print(setting); 394 | Serial.print(F(" bytes\r\n")); 395 | 396 | // Handling SETCRC command 397 | } else if (strcmp_P(command, PSTR("setcrc")) == 0) { 398 | setting = atoi(cmdline); 399 | ELECHOUSE_cc1101.setCrc(setting); 400 | Serial.print(F("\r\nCRC checking: ")); 401 | if (setting == 0) { Serial.print(F("Disabled")); } 402 | else if (setting == 1) { Serial.print(F("Enabled")); }; 403 | Serial.print(F("\r\n")); 404 | 405 | // Handling SETCRCAF command 406 | } else if (strcmp_P(command, PSTR("setcrcaf")) == 0) { 407 | setting = atoi(cmdline); 408 | ELECHOUSE_cc1101.setCRC_AF(setting); 409 | Serial.print(F("\r\nCRC Autoflush: ")); 410 | if (setting == 0) { Serial.print(F("Disabled")); } 411 | else if (setting == 1) { Serial.print(F("Enabled")); }; 412 | Serial.print(F("\r\n")); 413 | 414 | // Handling SETDCFILTEROFF command 415 | } else if (strcmp_P(command, PSTR("setdcfilteroff")) == 0) { 416 | setting = atoi(cmdline); 417 | ELECHOUSE_cc1101.setDcFilterOff(setting); 418 | Serial.print(F("\r\nDC filter: ")); 419 | if (setting == 0) { Serial.print(F("Enabled")); } 420 | else if (setting == 1) { Serial.print(F("Disabled")); }; 421 | Serial.print(F("\r\n")); 422 | 423 | // Handling SETMANCHESTER command 424 | } else if (strcmp_P(command, PSTR("setmanchester")) == 0) { 425 | setting = atoi(cmdline); 426 | ELECHOUSE_cc1101.setManchester(setting); 427 | Serial.print(F("\r\nManchester coding: ")); 428 | if (setting == 0) { Serial.print(F("Disabled")); } 429 | else if (setting == 1) { Serial.print(F("Enabled")); }; 430 | Serial.print(F("\r\n")); 431 | 432 | // Handling SETFEC command 433 | } else if (strcmp_P(command, PSTR("setfec")) == 0) { 434 | setting = atoi(cmdline); 435 | ELECHOUSE_cc1101.setFEC(setting); 436 | Serial.print(F("\r\nForward Error Correction: ")); 437 | if (setting == 0) { Serial.print(F("Disabled")); } 438 | else if (setting == 1) { Serial.print(F("Enabled")); }; 439 | Serial.print(F("\r\n")); 440 | 441 | // Handling SETPRE command 442 | } else if (strcmp_P(command, PSTR("setpre")) == 0) { 443 | setting = atoi(cmdline); 444 | ELECHOUSE_cc1101.setPRE(setting); 445 | Serial.print(F("\r\nMinimum preamble bytes:")); 446 | Serial.print(setting); 447 | Serial.print(F(" means 0 = 2 bytes, 1 = 3b, 2 = 4b, 3 = 6b, 4 = 8b, 5 = 12b, 6 = 16b, 7 = 24 bytes\r\n")); 448 | Serial.print(F("\r\n")); 449 | 450 | 451 | // Handling SETPQT command 452 | } else if (strcmp_P(command, PSTR("setpqt")) == 0) { 453 | setting = atoi(cmdline); 454 | ELECHOUSE_cc1101.setPQT(setting); 455 | Serial.print(F("\r\nPQT: ")); 456 | Serial.print(setting); 457 | Serial.print(F("\r\n")); 458 | 459 | // Handling SETAPPENDSTATUS command 460 | } else if (strcmp_P(command, PSTR("setappendstatus")) == 0) { 461 | setting = atoi(cmdline); 462 | ELECHOUSE_cc1101.setAppendStatus(setting); 463 | Serial.print(F("\r\nStatus bytes appending: ")); 464 | if (setting == 0) { Serial.print(F("Enabled")); } 465 | else if (setting == 1) { Serial.print(F("Disabled")); }; 466 | Serial.print(F("\r\n")); 467 | 468 | // Handling GETRSSI command 469 | } else if (strcmp_P(command, PSTR("getrssi")) == 0) { 470 | //Rssi Level in dBm 471 | Serial.print(F("Rssi: ")); 472 | Serial.println(ELECHOUSE_cc1101.getRssi()); 473 | //Link Quality Indicator 474 | Serial.print(F(" LQI: ")); 475 | Serial.println(ELECHOUSE_cc1101.getLqi()); 476 | Serial.print(F("\r\n")); 477 | 478 | 479 | // Handling SCAN command - frequency scanner by Little S@tan ! 480 | } else if (strcmp_P(command, PSTR("scan")) == 0) { 481 | settingf1 = atof(strsep(&cmdline, " ")); 482 | settingf2 = atof(cmdline); 483 | Serial.print(F("\r\nScanning frequency range from : ")); 484 | Serial.print(settingf1); 485 | Serial.print(F(" MHz to ")); 486 | Serial.print(settingf2); 487 | Serial.print(F(" MHz, press any key for stop or wait...\r\n")); 488 | // initialize parameters for scanning 489 | ELECHOUSE_cc1101.Init(); 490 | ELECHOUSE_cc1101.setRxBW(58); 491 | ELECHOUSE_cc1101.SetRx(); 492 | // Do scanning until some key pressed 493 | freq = settingf1; // start frequency for scanning 494 | mark_rssi=-100; 495 | while (!Serial.available()) 496 | { 497 | ELECHOUSE_cc1101.setMHZ(freq); 498 | rssi = ELECHOUSE_cc1101.getRssi(); 499 | if (rssi>-75) 500 | { 501 | if (rssi > mark_rssi) 502 | { 503 | mark_rssi = rssi; 504 | mark_freq = freq; 505 | }; 506 | }; 507 | 508 | freq+=0.01; 509 | 510 | if (freq > settingf2) 511 | { 512 | freq = settingf1; 513 | 514 | if (mark_rssi>-75) 515 | { 516 | long fr = mark_freq*100; 517 | if (fr == compare_freq) 518 | { 519 | Serial.print(F("\r\nSignal found at ")); 520 | Serial.print(F("Freq: ")); 521 | Serial.print(mark_freq); 522 | Serial.print(F(" Rssi: ")); 523 | Serial.println(mark_rssi); 524 | mark_rssi=-100; 525 | compare_freq = 0; 526 | mark_freq = 0; 527 | } 528 | else 529 | { 530 | compare_freq = mark_freq*100; 531 | freq = mark_freq -0.10; 532 | mark_freq=0; 533 | mark_rssi=-100; 534 | }; 535 | }; 536 | 537 | }; // end of IF freq>stop frequency 538 | 539 | }; // End of While 540 | 541 | 542 | // handling SAVE command 543 | } else if (strcmp_P(command, PSTR("save")) == 0) { 544 | //start saving recording buffer content into EEPROM non-volatile memory 545 | Serial.print(F("\r\nSaving recording buffer content into the non-volatile memory...\r\n")); 546 | 547 | for (setting=0; setting0) 628 | { 629 | // setup async mode on CC1101 and go into TX mode 630 | // with GDO0 pin processing 631 | ELECHOUSE_cc1101.setCCMode(0); 632 | ELECHOUSE_cc1101.setPktFormat(3); 633 | ELECHOUSE_cc1101.SetTx(); 634 | 635 | //start playing RF with setting GDO0 bit state with bitbanging 636 | Serial.print(F("\r\nStarting Brute Forcing press any key to stop...\r\n")); 637 | pinMode(gdo0, OUTPUT); 638 | 639 | for (brute = 0; brute < poweroftwo ; brute++) 640 | { 641 | for(int k = 0; k < 5; k++) // sending 5 times each code 642 | { 643 | for(int j = (setting2 - 1); j > -1; j--) // j bits in a value brute 644 | { 645 | digitalWrite(gdo0, bitRead(brute, j)); // Set GDO0 according to actual brute force value 646 | delayMicroseconds(setting); // delay for selected sampling interval 647 | }; // end of J loop 648 | }; // end of K loop 649 | // checking if key pressed 650 | if (Serial.available()) break; 651 | }; 652 | Serial.print(F("\r\nBrute forcing complete.\r\n\r\n")); 653 | 654 | // setting normal pkt format again 655 | ELECHOUSE_cc1101.setCCMode(1); 656 | ELECHOUSE_cc1101.setPktFormat(0); 657 | ELECHOUSE_cc1101.SetTx(); 658 | // pinMode(gdo0pin, INPUT); 659 | } // end of IF 660 | else { Serial.print(F("Wrong parameters.\r\n")); }; 661 | 662 | 663 | // Handling TX command 664 | } else if (strcmp_P(command, PSTR("tx")) == 0) { 665 | // convert hex array to set of bytes 666 | if ((strlen(cmdline)<=120) && (strlen(cmdline)>0) ) 667 | { 668 | hextoascii(textbuffer,(byte *)cmdline, strlen(cmdline)); 669 | memcpy(ccsendingbuffer, textbuffer, strlen(cmdline)/2 ); 670 | ccsendingbuffer[strlen(cmdline)/2] = 0x00; 671 | Serial.print("\r\nTransmitting RF packets.\r\n"); 672 | // send these data to radio over CC1101 673 | ELECHOUSE_cc1101.SendData(ccsendingbuffer, (byte)(strlen(cmdline)/2)); 674 | // for DEBUG only 675 | asciitohex(ccsendingbuffer, textbuffer, strlen(cmdline)/2 ); 676 | Serial.print(F("Sent frame: ")); 677 | Serial.print((char *)textbuffer); 678 | Serial.print(F("\r\n")); } 679 | else { Serial.print(F("Wrong parameters.\r\n")); }; 680 | 681 | 682 | 683 | // handling RECRAW command 684 | } else if (strcmp_P(command, PSTR("recraw")) == 0) { 685 | // take interval period for samplink 686 | setting = atoi(cmdline); 687 | if (setting>0) 688 | { 689 | // setup async mode on CC1101 with GDO0 pin processing 690 | ELECHOUSE_cc1101.setCCMode(0); 691 | ELECHOUSE_cc1101.setPktFormat(3); 692 | ELECHOUSE_cc1101.SetRx(); 693 | 694 | //start recording to the buffer with bitbanging of GDO0 pin state 695 | Serial.print(F("\r\nWaiting for radio signal to start RAW recording...\r\n")); 696 | pinMode(gdo0, INPUT); 697 | 698 | // this is only for ESP32 boards because they are getting some noise on the beginning 699 | setting2 = digitalRead(gdo0); 700 | delayMicroseconds(1000); 701 | 702 | 703 | // waiting for some data first or serial port signal 704 | // while (!Serial.available() || (digitalRead(gdo0) == LOW) ); 705 | while ( digitalRead(gdo0) == LOW ); 706 | 707 | //start recording to the buffer with bitbanging of GDO0 pin state 708 | Serial.print(F("\r\nStarting RAW recording to the buffer...\r\n")); 709 | pinMode(gdo0, INPUT); 710 | 711 | for (int i=0; i -1; j--) // 8 bits in a byte 715 | { 716 | bitWrite(receivedbyte, j, digitalRead(gdo0)); // Capture GDO0 state into the byte 717 | delayMicroseconds(setting); // delay for selected sampling interval 718 | }; 719 | // store the output into recording buffer 720 | bigrecordingbuffer[i] = receivedbyte; 721 | } 722 | Serial.print(F("\r\nRecording RAW data complete.\r\n\r\n")); 723 | // setting normal pkt format again 724 | ELECHOUSE_cc1101.setCCMode(1); 725 | ELECHOUSE_cc1101.setPktFormat(0); 726 | ELECHOUSE_cc1101.SetRx(); 727 | } 728 | else { Serial.print(F("Wrong parameters.\r\n")); }; 729 | 730 | // handling RXRAW command - sniffer 731 | } else if (strcmp_P(command, PSTR("rxraw")) == 0) { 732 | // take interval period for samplink 733 | setting = atoi(cmdline); 734 | if (setting>0) 735 | { 736 | // setup async mode on CC1101 with GDO0 pin processing 737 | ELECHOUSE_cc1101.setCCMode(0); 738 | ELECHOUSE_cc1101.setPktFormat(3); 739 | ELECHOUSE_cc1101.SetRx(); 740 | //start recording to the buffer with bitbanging of GDO0 pin state 741 | Serial.print(F("\r\nSniffer enabled...\r\n")); 742 | pinMode(gdo0, INPUT); 743 | 744 | 745 | 746 | // Any received char over Serial port stops printing RF received bytes 747 | while (!Serial.available()) 748 | { 749 | 750 | // we have to use the buffer not to introduce delays 751 | for (int i=0; i -1; j--) // 8 bits in a byte 755 | { 756 | bitWrite(receivedbyte, j, digitalRead(gdo0)); // Capture GDO0 state into the byte 757 | delayMicroseconds(setting); // delay for selected sampling interval 758 | }; 759 | // store the output into recording buffer 760 | bigrecordingbuffer[i] = receivedbyte; 761 | }; 762 | // when buffer full print the ouptput to serial port 763 | for (int i = 0; i < RECORDINGBUFFERSIZE ; i = i + 32) 764 | { 765 | asciitohex(&bigrecordingbuffer[i], textbuffer, 32); 766 | Serial.print((char *)textbuffer); 767 | }; 768 | 769 | 770 | }; // end of While loop 771 | 772 | Serial.print(F("\r\nStopping the sniffer.\n\r\n")); 773 | 774 | // setting normal pkt format again 775 | ELECHOUSE_cc1101.setCCMode(1); 776 | ELECHOUSE_cc1101.setPktFormat(0); 777 | ELECHOUSE_cc1101.SetRx(); 778 | } 779 | else { Serial.print(F("Wrong parameters.\r\n")); }; 780 | 781 | 782 | // handling PLAYRAW command 783 | } else if (strcmp_P(command, PSTR("playraw")) == 0) { 784 | // take interval period for sampling 785 | setting = atoi(cmdline); 786 | if (setting>0) 787 | { 788 | // setup async mode on CC1101 and go into TX mode 789 | // with GDO0 pin processing 790 | ELECHOUSE_cc1101.setCCMode(0); 791 | ELECHOUSE_cc1101.setPktFormat(3); 792 | ELECHOUSE_cc1101.SetTx(); 793 | //start replaying GDO0 bit state from data in the buffer with bitbanging 794 | Serial.print(F("\r\nReplaying RAW data from the buffer...\r\n")); 795 | pinMode(gdo0, OUTPUT); 796 | 797 | 798 | for (int i=1; i -1; j--) // 8 bits in a byte 802 | { 803 | digitalWrite(gdo0, bitRead(receivedbyte, j)); // Set GDO0 according to recorded byte 804 | delayMicroseconds(setting); // delay for selected sampling interval 805 | }; 806 | } 807 | 808 | 809 | Serial.print(F("\r\nReplaying RAW data complete.\r\n\r\n")); 810 | // setting normal pkt format again 811 | ELECHOUSE_cc1101.setCCMode(1); 812 | ELECHOUSE_cc1101.setPktFormat(0); 813 | ELECHOUSE_cc1101.SetTx(); 814 | // pinMode(gdo0pin, INPUT); 815 | } 816 | else { Serial.print(F("Wrong parameters.\r\n")); }; 817 | 818 | // handling SHOWRAW command 819 | } else if (strcmp_P(command, PSTR("showraw")) == 0) { 820 | // show the content of recorded RAW signal as hex numbers 821 | Serial.print(F("\r\nRecorded RAW data:\r\n")); 822 | for (int i = 0; i < RECORDINGBUFFERSIZE ; i = i + 32) 823 | { 824 | asciitohex(&bigrecordingbuffer[i], textbuffer, 32); 825 | Serial.print((char *)textbuffer); 826 | } 827 | Serial.print(F("\r\n\r\n")); 828 | 829 | 830 | // handling SHOWBIT command 831 | } else if (strcmp_P(command, PSTR("showbit")) == 0) { 832 | // show the content of recorded RAW signal as hex numbers 833 | Serial.print(F("\r\nRecorded RAW data as bit stream:\r\n")); 834 | for (int i = 0; i < RECORDINGBUFFERSIZE ; i = i + 32) 835 | { // first convert to hex numbers 836 | asciitohex((byte *)&bigrecordingbuffer[i], (byte *)textbuffer, 32); 837 | // now decode as binary and print 838 | for (setting = 0; setting < 64 ; setting++) 839 | { 840 | setting2 = textbuffer[setting]; 841 | switch( setting2 ) 842 | { 843 | case '0': 844 | Serial.print(F("____")); 845 | break; 846 | 847 | case '1': 848 | Serial.print(F("___-")); 849 | break; 850 | 851 | case '2': 852 | Serial.print(F("__-_")); 853 | break; 854 | 855 | case '3': 856 | Serial.print(F("__--")); 857 | break; 858 | 859 | case '4': 860 | Serial.print(F("_-__")); 861 | break; 862 | 863 | case '5': 864 | Serial.print(F("_-_-")); 865 | break; 866 | 867 | case '6': 868 | Serial.print(F("_--_")); 869 | break; 870 | 871 | case '7': 872 | Serial.print(F("_---")); 873 | break; 874 | 875 | case '8': 876 | Serial.print(F("-___")); 877 | break; 878 | 879 | case '9': 880 | Serial.print(F("-__-")); 881 | break; 882 | 883 | case 'A': 884 | Serial.print(F("-_-_")); 885 | break; 886 | 887 | case 'B': 888 | Serial.print(F("-_--")); 889 | break; 890 | 891 | case 'C': 892 | Serial.print(F("--__")); 893 | break; 894 | 895 | case 'D': 896 | Serial.print(F("--_-")); 897 | break; 898 | 899 | case 'E': 900 | Serial.print(F("---_")); 901 | break; 902 | 903 | case 'F': 904 | Serial.print(F("----")); 905 | break; 906 | 907 | }; // end of switch 908 | 909 | }; // end of for 910 | 911 | } // end of for 912 | Serial.print(F("\r\n\r\n")); 913 | 914 | 915 | // Handling ADDRAW command 916 | } else if (strcmp_P(command, PSTR("addraw")) == 0) { 917 | // getting hex numbers - the content of the frame 918 | len = strlen(cmdline); 919 | // convert hex array to set of bytes 920 | if ((len<=120) && (len>0) ) 921 | { 922 | // convert the hex content to array of bytes 923 | hextoascii(textbuffer, (byte *)cmdline, len); 924 | len = len /2; 925 | // check if the frame fits into the buffer and store it 926 | if (( bigrecordingbufferpos + len) < RECORDINGBUFFERSIZE) 927 | { // copy current frame and increase pointer for next frames 928 | memcpy(&bigrecordingbuffer[bigrecordingbufferpos], &textbuffer, len ); 929 | // increase position in big recording buffer for next frame 930 | bigrecordingbufferpos = bigrecordingbufferpos + len; 931 | Serial.print(F("\r\nChunk added to recording buffer\r\n\r\n")); 932 | } 933 | else 934 | { 935 | Serial.print(F("\r\nBuffer is full. The frame does not fit.\r\n ")); 936 | }; 937 | } 938 | else { Serial.print(F("Wrong parameters.\r\n")); }; 939 | 940 | 941 | 942 | // Handling REC command 943 | } else if (strcmp_P(command, PSTR("rec")) == 0) { 944 | Serial.print(F("\r\nRecording mode set to ")); 945 | if (recordingmode == 1) 946 | { 947 | Serial.print(F("Disabled")); 948 | bigrecordingbufferpos = 0; 949 | recordingmode = 0; 950 | } 951 | else if (recordingmode == 0) 952 | { ELECHOUSE_cc1101.SetRx(); 953 | Serial.print(F("Enabled")); 954 | bigrecordingbufferpos = 0; 955 | // flush buffer for recording 956 | for (int i = 0; i < RECORDINGBUFFERSIZE; i++) 957 | { bigrecordingbuffer[RECORDINGBUFFERSIZE] = 0; }; 958 | recordingmode = 1; 959 | jammingmode = 0; 960 | receivingmode = 0; 961 | // start counting frames in the buffer 962 | framesinbigrecordingbuffer = 0; 963 | }; 964 | Serial.print(F("\r\n")); 965 | 966 | 967 | // Handling PLAY command 968 | } else if (strcmp_P(command, PSTR("play")) == 0) { 969 | setting = atoi(strsep(&cmdline, " ")); 970 | // if number of played frames is 0 it means play all frames 971 | if (setting <= framesinbigrecordingbuffer) 972 | { 973 | Serial.print(F("\r\nReplaying recorded frames.\r\n ")); 974 | // rewind recording buffer position to the beginning 975 | bigrecordingbufferpos = 0; 976 | if (framesinbigrecordingbuffer >0) 977 | { 978 | 979 | // start reading and sending frames from the buffer : FIFO 980 | for (int i=1; i<=framesinbigrecordingbuffer ; i++) 981 | { 982 | // read length of the recorded frame first from the buffer 983 | len = bigrecordingbuffer[bigrecordingbufferpos]; 984 | if ( ((len<=60) and (len>0)) and ((i == setting) or (setting == 0)) ) 985 | { 986 | // take next frame from the buffer for replay 987 | memcpy(ccsendingbuffer, &bigrecordingbuffer[bigrecordingbufferpos + 1], len ); 988 | // send these data to radio over CC1101 989 | ELECHOUSE_cc1101.SendData(ccsendingbuffer, (byte)len); 990 | }; 991 | // increase position to the buffer and check exception 992 | bigrecordingbufferpos = bigrecordingbufferpos + 1 + len; 993 | if ( bigrecordingbufferpos > RECORDINGBUFFERSIZE) break; 994 | // 995 | }; 996 | }; // end of IF framesinrecordingbuffer 997 | 998 | // rewind buffer position 999 | bigrecordingbufferpos = 0; 1000 | Serial.print(F("Done.\r\n")); 1001 | } 1002 | else { Serial.print(F("Wrong parameters.\r\n")); }; 1003 | 1004 | 1005 | // Handling ADD command 1006 | } else if (strcmp_P(command, PSTR("add")) == 0) { 1007 | // getting hex numbers - the content of the frame 1008 | len = strlen(cmdline); 1009 | // convert hex array to set of bytes 1010 | if ((len<=120) && (len>0) ) 1011 | { 1012 | // convert the hex content to array of bytes 1013 | hextoascii(textbuffer,(byte *)cmdline, len); 1014 | len = len /2; 1015 | // check if the frame fits into the buffer and store it 1016 | if (( bigrecordingbufferpos + len + 1) < RECORDINGBUFFERSIZE) 1017 | { // put info about number of bytes 1018 | bigrecordingbuffer[bigrecordingbufferpos] = len; 1019 | bigrecordingbufferpos++; 1020 | // next - copy current frame and increase 1021 | memcpy(&bigrecordingbuffer[bigrecordingbufferpos], &textbuffer, len ); 1022 | // increase position in big recording buffer for next frame 1023 | bigrecordingbufferpos = bigrecordingbufferpos + len; 1024 | // increase counter of frames stored 1025 | framesinbigrecordingbuffer++; 1026 | Serial.print(F("\r\nAdded frame number ")); 1027 | Serial.print(framesinbigrecordingbuffer); 1028 | Serial.print(F("\r\n")); 1029 | } 1030 | else 1031 | { 1032 | Serial.print(F("\r\nBuffer is full. The frame does not fit.\r\n ")); 1033 | }; 1034 | } 1035 | else { Serial.print(F("Wrong parameters.\r\n")); }; 1036 | 1037 | 1038 | 1039 | // Handling SHOW command 1040 | } else if (strcmp_P(command, PSTR("show")) == 0) { 1041 | if (framesinbigrecordingbuffer>0) 1042 | { 1043 | Serial.print(F("\r\nFrames stored in the recording buffer:\r\n ")); 1044 | // rewind recording buffer position to the beginning 1045 | bigrecordingbufferpos = 0; 1046 | // start reading and sending frames from the buffer : FIFO 1047 | for (setting=1; setting<=framesinbigrecordingbuffer; setting++) 1048 | { 1049 | // read length of the recorded frame first from the buffer 1050 | len = bigrecordingbuffer[bigrecordingbufferpos]; 1051 | if ((len<=60) and (len>0)) 1052 | { 1053 | // take next frame from the buffer for replay 1054 | // flush textbuffer 1055 | for (setting2 = 0; setting2 < BUF_LENGTH; setting2++) 1056 | { textbuffer[setting2] = 0; }; 1057 | asciitohex(&bigrecordingbuffer[bigrecordingbufferpos + 1], textbuffer, len); 1058 | Serial.print(F("\r\nFrame ")); 1059 | Serial.print(setting); 1060 | Serial.print(F(" : ")); 1061 | Serial.print((char *)textbuffer); 1062 | Serial.print(F("\r\n")); 1063 | }; 1064 | // increase position to the buffer and check exception 1065 | bigrecordingbufferpos = bigrecordingbufferpos + 1 + len; 1066 | if ( bigrecordingbufferpos > RECORDINGBUFFERSIZE) break; 1067 | // 1068 | }; 1069 | // rewind buffer position 1070 | // bigrecordingbufferpos = 0; 1071 | Serial.print(F("\r\n")); 1072 | } 1073 | else { Serial.print(F("Wrong parameters.\r\n")); }; 1074 | 1075 | 1076 | // Handling FLUSH command 1077 | } else if (strcmp_P(command, PSTR("flush")) == 0) { 1078 | // flushing bigrecordingbuffer with zeros and rewinding all the pointers 1079 | for (setting = 0; setting