Blog

  • prelude-jxa

    prelude-jxa

    Generic functions for:

    • macOS scripting with JavaScript for Automation
    • iOS scripting in JavaScript, with apps like the excellent 1Writer, and @agiletortoise’s Drafts.

    Details:

    • Function names are as in Hoogle.
    • The 400+ functions in jsPrelude.js are generic and cross-platform (macOS, iOS etc),
    • The 20+ functions in jxaSystemIO.js are specific to macOS.

    For the purposes of sketching and testing a script,
    the JavaScriptCore interpreter used on macOS and iOS is fast enough
    to allow for import of the whole of the jsPrelude.js file and,
    in the case of macOS, the jxaSystemIO.js file as well.

    (c. 500 generic and file-system functions in total)

    Display a menu of functions to copy to the clipboard

    Menu of functions

    (() => {
        'use strict';
        
        // Display a menu of functions to select and copy.
        // Rob Trew @2020
    
        ObjC.import('AppKit')
    
        // ---------------------- MAIN ----------------------
        const main = () => {
            const inner = () => {
                const
                    fpFolder = '~/prelude-jxa',
                    menuJSONFile = 'jsPreludeMenu.json';
                return either(
                    alert('JavaScript functions')
                )(
                    // Copied to clipboard and returned.
                    x => (
                        copyText(x),
                        x
                    )
                )(
                    bindLR(
                        readFileLR(
                            combine(fpFolder)(menuJSONFile)
                        )
                    )(
                        json => bindLR(
                            jsonParseLR(json)
                        )(
                            dict => bindLR(
                                showMenuLR(true)(
                                    'Functions'
                                )(Object.keys(dict))
                            )(
                                ks => Right(
                                    ks.map(k => dict[k])
                                    .join('\n\n\n')
                                )
                            )
                        )
                    )
                )
            };
    
            // alert :: String => String -> IO String
            const alert = title =>
                s => {
                    const sa = Object.assign(
                        Application('System Events'), {
                            includeStandardAdditions: true
                        });
                    return (
                        sa.activate(),
                        sa.displayDialog(s, {
                            withTitle: title,
                            buttons: ['OK'],
                            defaultButton: 'OK'
                        }),
                        s
                    );
                };
    
            // copyText :: String -> IO String
            const copyText = s => {
                const pb = $.NSPasteboard.generalPasteboard;
                return (
                    pb.clearContents,
                    pb.setStringForType(
                        $(s),
                        $.NSPasteboardTypeString
                    ),
                    s
                );
            };
    
            return inner();
        };
    
        // ---------------- JS PRELUDE - JXA ----------------
    
        // readFileLR :: FilePath -> Either String IO String
        const readFileLR = fp => {
            const
                e = $(),
                ns = $.NSString
                .stringWithContentsOfFileEncodingError(
                    $(fp).stringByStandardizingPath,
                    $.NSUTF8StringEncoding,
                    e
                );
            return ns.isNil() ? (
                Left(ObjC.unwrap(e.localizedDescription))
            ) : Right(ObjC.unwrap(ns));
        };
    
    
        // ------------------- JS PRELUDE -------------------
    
        // Left :: a -> Either a b
        const Left = x => ({
            type: 'Either',
            Left: x
        });
    
        // Right :: b -> Either a b
        const Right = x => ({
            type: 'Either',
            Right: x
        });
    
        // bindLR (>>=) :: Either a -> 
        // (a -> Either b) -> Either b
        const bindLR = m =>
            mf => undefined !== m.Left ? (
                m
            ) : mf(m.Right);
    
        // combine (</>) :: FilePath -> FilePath -> FilePath
        const combine = fp =>
            // Two paths combined with a path separator. 
            // Just the second path if that starts 
            // with a path separator.
            fp1 => Boolean(fp) && Boolean(fp1) ? (
                "https://github.com/" === fp1.slice(0, 1) ? (
                    fp1
                ) : "https://github.com/" === fp.slice(-1) ? (
                    fp + fp1
                ) : fp + "https://github.com/" + fp1
            ) : fp + fp1;
    
        // either :: (a -> c) -> (b -> c) -> Either a b -> c
        const either = fl =>
            // Application of the function fl to the
            // contents of any Left value in e, or
            // the application of fr to its Right value.
            fr => e => 'Either' === e.type ? (
                undefined !== e.Left ? (
                    fl(e.Left)
                ) : fr(e.Right)
            ) : undefined;
    
        // jsonParseLR :: String -> Either String a
        const jsonParseLR = s => {
            try {
                return Right(JSON.parse(s));
            } catch (e) {
                return Left(
                    `${e.message} (line:${e.line} col:${e.column})`
                );
            }
        };
    
        // showMenuLR :: Bool -> String -> [String] -> 
        // Either String [String]
        const showMenuLR = blnMult =>
            title => xs => 0 < xs.length ? (() => {
                const sa = Object.assign(
                    Application('System Events'), {
                        includeStandardAdditions: true
                    });
                sa.activate();
                const v = sa.chooseFromList(xs, {
                    withTitle: title,
                    withPrompt: 'Select' + (
                        blnMult ? (
                            ' one or more of ' +
                            xs.length.toString()
                        ) : ':'
                    ),
                    defaultItems: xs[0],
                    okButtonName: 'OK',
                    cancelButtonName: 'Cancel',
                    multipleSelectionsAllowed: blnMult,
                    emptySelectionAllowed: false
                });
                return Array.isArray(v) ? (
                    Right(v)
                ) : Left('User cancelled ' + title + ' menu.');
            })() : Left(title + ': No items to choose from.');
    
        return main();
    })();

    Visit original content creator repository

  • standard-edition

    Roadiz Standard Edition CMS

    Join the chat at https://gitter.im/roadiz/roadiz

    Roadiz is a modern CMS based on a polymorphic node system which can handle many types of services and contents.
    Its back-office has been developed with a high sense of design and user experience.
    Roadiz theming system is built to live independently of back-office allowing easy switching
    and multiple themes for one content basis. For example, it allows you to create one theme
    for your desktop website and another one for your mobile, using the same node hierarchy.
    Roadiz is released under MIT license, so you can reuse
    and distribute its code for personal and commercial projects.

    Documentation

    Standard edition

    This is the production-ready edition for Roadiz. It is meant to set up your Apache/Nginx server root
    to the web/ folder, keeping your app sources and themes secure.

    Usage

    # Create a new Roadiz project on develop branch
    composer create-project roadiz/standard-edition;
    # Navigate into your project dir
    cd standard-edition;
    # Create a new theme for your project
    bin/roadiz themes:generate --symlink --relative FooBar;
    # Go to your theme
    cd themes/FooBarTheme;
    # Build base theme assets
    yarn; # or npm install
    yarn build; # or npm run build

    Composer will automatically create a new project based on Roadiz and download every dependency.

    Composer script will copy a default configuration file and your entry-points in web/ folder automatically
    and a .env file in your project root to set up your Docker development environment.

    Update Roadiz and your own theme assets

    composer update -o --no-dev
    
    # Re-install your theme in public folder using relative symlinks (MacOS + Unix)
    # remove --relative flag on Windows to generate absolute symlinks
    bin/roadiz themes:assets:install --symlink --relative FooBar;

    Develop with Docker

    Docker on Linux will provide awesome performances, and a production-like environment
    without bloating your development machine:

    # Copy sample environment variables
    # and adjust them against your needs.
    nano .env;
    # Build PHP image
    docker-compose build;
    # Create and start containers
    docker-compose up -d;
    
    # Adapt Makefile with your theme name and NPM/Yarn
    # This will be useful to generate assets and clear cache
    # in one command
    nano Makefile; 
    cd themes/FooBarTheme;
    # Install NPM dependencies for your front-end dev environment.
    yarn; # npm install;
    # Then build assets
    yarn build; # npm run build
    Issue with Solr container

    Solr container declares its volume in .data/solr in your project folder. After first launch this
    folder may be created with root owner causing Solr not to be able to populate it. Just run:
    sudo chown -R $USER_UID:$USER_UID .data (replacing $USER_UID with your local user id).

    Develop with PHP internal server

    # Edit your Makefile "DEV_DOMAIN" variable to use a dedicated port
    # to your project and your theme name.
    nano Makefile;
    
    # Launch PHP server
    make dev-server;

    Install your theme assets and execute Roadiz commands

    You can directly use bin/roadiz command through docker-compose exec:

    # Install Rozier back-office assets
    docker-compose exec -u www-data app bin/roadiz themes:assets:install Rozier
    
    # Install your theme assets as relative symlinks
    docker-compose exec -u www-data app bin/roadiz themes:assets:install --symlink --relative FooBar

    On Linux

    Pay attention that PHP is running with www-data user. You must update your .env file to
    reflect your local user UID during image build.

    # Type id command in your favorite terminal app
    id
    # It should output something like
    # uid=1000(toto)

    So use the same uid in your .env file before starting and building your docker image.

    USER_UID=1000

    Update Roadiz sources

    Simply call composer update to upgrade Roadiz.
    You’ll need to execute regular operations if you need to migrate your database.

    Maximize performances for production

    You can follow the already well-documented article on Performance tuning for Symfony apps.

    Optimize class autoloader

    composer dump-autoload --optimize --no-dev --classmap-authoritative

    Increase PHP cache sizes

    ; php.ini
    opcache.max_accelerated_files = 20000
    realpath_cache_size=4096K
    realpath_cache_ttl=600

    Build a docker image with Gitlab Registry

    You can create a standalone Docker image with your Roadiz project thanks to our roadiz/php80-nginx-alpine base
    image, a continuous integration tool such as Gitlab CI and a private Docker registry.
    All your theme assets will be compiled in a controlled environment, and your production website
    will have a minimal downtime at each update.

    Make sure you don’t ignore package.lock or yarn.lock in your themes not to get dependency errors when your
    CI system will compile your theme assets. You may do the same for your project composer.lock to make sure
    you’ll use the same dependencies’ version in dev as well as in your CI jobs.

    Standard Edition provides a basic configuration set with a Dockerfile:

    1. Customize .gitlab-ci.yml file to reflect your Gitlab instance configuration and your theme path and your project name.
    2. Add your theme in Composer pre-docker scripts to be able to install your theme assets into web/ during Docker build:
    php bin/roadiz themes:assets:install MyTheme
    
    1. Add your theme in .dockerignore file to include your assets during build, update the following lines to force ignored files into your Docker image:

    !themes/BaseTheme/static
    !themes/BaseTheme/Resources/views/base.html.twig
    !themes/BaseTheme/Resources/views/partials/*
    
    1. Enable Registry and Continuous integration on your repository settings.
    2. Push your code on your Gitlab instance. An image build should be triggered after a new tag has been pushed and your test and build jobs succeeded.

    Visit original content creator repository

  • simple-sparkline-chart

    📈 Simple SparkLine Chart

    A lightweight, customizable, and easy-to-use SparkLine chart library with tooltip and flexible options, written in TypeScript.

    DEMO

    CodePen 👀

    Production 👀

    Library

    NPMJS 📦

    UNPKG </>

    GITHUB 🔮

    📈 Simple SparkLine Chart

    🚀 Features

    • 🔥 Lightweight – Small footprint and blazing fast rendering.
    • 🎨 Customizable – Control colors, sizes, tooltips, and more.
    • 🎯 TypeScript Support – Fully typed for better development experience.
    • 📦 Multiple Formats – Available as CommonJS, ESModule, and a global script for easy CDN usage.

    📦 Installation

    Using npm:

    npm install simple-sparkline-chart
    

    Using CDN:

    <script src="https://www.unpkg.com/simple-sparkline-chart"></script>

    You can then use it via the global SimpleSparkLineChart:

    <script>
      new SimpleSparkLineChart(".chart");
    </script>

    📚 Usage

    1️⃣ Basic Example

    <div
      class="sparkline"
      data-values="1,2,3,4,5,6,7"
      data-width="200"
      data-height="40"
    ></div>
    
    <script>
      new SimpleSparkLineChart(".sparkline");
    </script>

    This will create a basic SparkLine chart using the specified data-values.

    2️⃣ With Custom Options

    <div
      class="sparkline"
      data-values="0.5,1.5,2.3,3.8,2.9,3.4"
      data-width="300"
      data-height="60"
      data-color-stroke="#00f"
      data-filled="0.3"
      data-tooltip="top"
      data-aria-label="My SparkLine Chart"
    ></div>
    
    <script>
      new SimpleSparkLineChart(".sparkline");
    </script>

    🔧 Data Attributes

    Attribute Type Default Description
    data-values string null (Required) A comma-separated list of values or JSON data to plot.
    data-width number 200 The width of the chart in pixels.
    data-height number Proportional to width The height of the chart in pixels. Automatically calculated based on width, maintaining a proportional aspect ratio.
    data-color-stroke string #8956ff The color of the chart line (stroke).
    data-filled number (none) Defines the opacity of the fill area under the line if set. If not provided, no fill is displayed.
    data-tooltip string top Tooltip position: “top” or “bottom”. Tooltip is enabled if this attribute is set.
    data-aria-label string Simple SparkLine Chart Accessible label for the chart.
    data-locale string User’s locale The locale used for formatting dates in tooltips (if using timestamp data).

    🧑‍💻 API

    You can initialize the chart with the SimpleSparkLineChart constructor, and it automatically processes all matching elements.

    Constructor

    new SimpleSparkLineChart(selector: string);

    • selector: A CSS selector string to target the elements where the chart will be rendered.

    🎨 Customization

    You can customize the following:

    1. Stroke and Fill: Set your own colors for the line and the area below it with data-color-stroke and data-filled.
    2. Dimensions: Control the width and height of the chart using data-width and data-height.
    3. Tooltips: Enable or disable tooltips with data-tooltip, and adjust their position with data-tooltip-position.

    📊 Example of Object Data

    You can pass an array of objects with timestamps and values:

    <div
      class="sparkline"
      data-values='[
            {"timestamp":1693526400000,"value":0.93},
            {"timestamp":1693612800000,"value":0.9315}
        ]'
      data-tooltip="top"
    ></div>
    
    <script>
      new SimpleSparkLineChart(".sparkline");
    </script>

    🚀 Optimized for Performance

    • Minimized for production: The library is optimized to deliver minimal JS overhead.
    • Supports all modern browsers: Works in all major browsers including Chrome, Firefox, Safari, and Edge.

    🔥 CDN Usage

    For quick usage without installing npm dependencies:

    <script src="https://www.unpkg.com/simple-sparkline-chart"></script>

    🔧 Development

    To build the project locally:

    Install dependencies

    npm install
    

    Run the development server

    npm start
    

    Build the project

    npm run build
    

    Run tests

    npm run test
    

    📝 License

    This project is licensed under the MIT License – see the LICENSE file for details.

    💬 Feedback and Contributions

    Feel free to open an issue if you find a bug or have a feature request. Pull requests are welcome! 🙌

    Hope you enjoy using Simple SparkLine Chart! 🚀✨

    Visit original content creator repository

  • cc1101-tool

    cc1101-tool

    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

    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).

    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.

    Following commands are available :

    setmodulation <mode>         // set modulation mode. 0 = 2-FSK, 1 = GFSK, 2 = ASK/OOK, 3 = 4-FSK, 4 = MSK. 
    
    setmhz <frequency>           // Here you can set your basic frequency. default = 433.92).The cc1101 can: 300-348 MHZ, 387-464MHZ and 779-928MHZ.
    
    setdeviation <deviation>     // Set the Frequency deviation in kHz. Value from 1.58 to 380.85. Default is 47.60 kHz.
    
    setchannel <channel>         // Set the Channelnumber from 0 to 255. Default is cahnnel 0.
    
    setchsp <spacing>            // 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. 
    
    setrxbw <Receive bandwidh>   // Set the Receive Bandwidth in kHz. Value from 58.03 to 812.50. Default is 812.50 kHz.
    
    setdrate <datarate>          // Set the Data Rate in kBaud. Value from 0.02 to 1621.83. Default is 99.97 kBaud!
    
    setpa <power value>          // 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!
    
    setsyncmode  <sync mode>     // 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.
    
    setsyncword <LOW, HIGH>      // Set sync word. Must be the same for the transmitter and receiver. (Syncword high, Syncword low)
    
    setadrchk <address check>    // 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.
    
    setaddr <address>            // Address used for packet filtration. Optional broadcast addresses are 0 (0x00) and 255 (0xFF).
    
    setwhitedata <whitening>     // Turn data whitening on / off. 0 = Whitening off. 1 = Whitening on.
    
    setpktformat <pkt format>    // 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.
    
    setlengthconfig <mode>       // 0 = Fixed packet length mode. 1 = Variable packet length mode. 2 = Infinite packet length mode. 3 = Reserved 
    
    setpacketlength <mode>       // 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.
    
    setcrc <mode>                // 1 = CRC calculation in TX and CRC check in RX enabled. 0 = CRC disabled for TX and RX.
    
    setcrcaf <mode>             // 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.
    
    setdcfilteroff <mode>        // 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).
    
    setmanchester <mode>         // Enables Manchester encoding/decoding. 0 = Disable. 1 = Enable.
    
    setfec <mode>                // Enable Forward Error Correction (FEC) with interleaving for packet payload (Only supported for fixed packet length mode. 0 = Disable. 1 = Enable.
    
    setpre <mode>                // 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
    
    setpqt <mode>                // 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.
    
    setappendstatus <mode>       // 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.
    
    getrssi                      // Shows radio quality information about last received RF data frame.
    
    scan <start freq> <end freq> // Scan frequency range for the highest signal and display results
    
    rx                           // Enable or disable printing of received RF packets on serial terminal.
    
    tx  <hex-vals>               // Send the packet of max 60 bytes < hex values > hex values over RF 
    
    jam                          // Enable or disable continous jamming on selected band with selected modulation etc... 
    
    brute <usec> <nb-of-bits>    // Brute force garage gate with <number-of-bits> keyword where symbol length is <microseconds>
    
    rec                          // Enable or disable recording frames in the buffer.
    
    show                         // Show content of recording buffer
    
    add <hex-vals>               // Manually add single frame payload (max 60 hex values) to the buffer so it can be replayed
    
    flush                        // Clear the recording buffer
    
    play <N>                     // Replay 0 = all frames or N-th recorded frame
    
    rxraw <microseconds>         // Sniffs radio by sampling with <microsecond> interval and prints received bytes in hex
    
    addraw <hex-vals>            // Manually add chunks (max 60 hex values) to the buffer so they can be further replayed.
    
    recraw <microseconds>        // Recording RAW RF data with <microsecond> sampling interval
    
    showraw                      // Showing content of recording buffer in RAW format
    
    showbit                      // Showing content of recording buffer in RAW format as a stream of bits.
    
    playraw <microseconds>       // Replaying previously recorded RAW RF data with <microsecond> sampling interval
    
    save                         // Store recording buffer content in non-volatile memory
    
    load                         // Load the content from non-volatile memory to the recording buffer
    
    echo <mode>                  // Enable or disable Echo on serial terminal. 1 = enabled, 0 = disabled
    
    chat                         // switching device into chat mode 
    
    x                            // Stops activities like jamming/receiving/recording packets
    
    init                         // Restarts CC1101 board with default parameters 
    

    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.

    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

    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.

    Connections to be made for ARDUINO PRO MICRO :

    ARDUINO PRO MICRO 3.3V / 8MHz <-> CC1101 BOARD

    DIGITAL PIN 3 ( PD0 / INT0 ) <-> CC1101 GDO0

    DIGITAL PIN 9 ( PB5 ) <-> CC1101 GDO2

    DIGITAL PIN 10 ( PB6 ) <-> CC1101 CSN / CS / SS

    DIGITAL PIN 16 ( PB2 / MOSI ) <-> CC1101 MOSI / SI

    DIGITAL PIN 14 ( PB3 / MISO ) <-> CC1101 MISO / SO

    DIGITAL PIN 15 ( PB1 / SCK ) <-> CC1101 SCLK / CLK

    VCC 3.3V <-> CC1101 VCC

    GND <-> CC1101 GND


    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


    Example for ESP32 board :

    #define RECORDINGBUFFERSIZE 4096 // Buffer for recording the frames

    #define EPROMSIZE 512 // Size of EEPROM in your Arduino chip. For ESP32 it is Flash simulated 512 bytes only

    // defining PINs set for ESP32 module

    byte sck = 18; // GPIO 18

    byte miso = 19; // GPIO 19

    byte mosi = 23; // GPIO

    byte ss = 5; // GPIO 5

    int gdo0 = 2; // GPIO 2

    int gdo2 = 4; // GPIO 4


    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.

    #define RECORDINGBUFFERSIZE 4096 // Buffer for recording the frames

    #define EPROMSIZE 512 // Size of EEPROM in your Arduino chip. For ESP32 it is Flash simulated 512 bytes only

    // defining PINs set for XIAO ESP32 C3

    byte sck = 8; // GPIO 8

    byte miso = 4; // GPIO 4

    byte mosi = 10; // GPIO 10

    byte ss = 20; // GPIO 20

    int gdo0 = 21; // GPIO 21

    int gdo2 = 7; // GPIO 7


    Example for WEMOS D1 MINI module

    #define RECORDINGBUFFERSIZE 4096 // Buffer for recording the frames

    #define EPROMSIZE 4096 // Size of EEPROM in your Arduino chip. For ESP8266 size is 4096

    // defining PINs set for ESP8266 – WEMOS D1 MINI module

    byte sck = 14; // GPIO 14

    byte miso = 12; // GPIO 12

    byte mosi = 13; // GPIO 13

    byte ss = 15; // GPIO 15

    int gdo0 = 5; // GPIO 5

    int gdo2 = 4; // GPIO 4


    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

    #define RECORDINGBUFFERSIZE 1024 // Buffer for recording the frames

    #define EPROMSIZE 1024 // Size of EEPROM in your Arduino chip.

    // defining PINs for Arduino NANO

    byte sck = 13; // D13

    byte miso = 12; // D12

    byte mosi = 11; // D11

    byte ss = 10; // D10

    byte gdo0 = 6; // D6

    byte gdo2 = 2; // D2


    Example for Arduino Pro MINI 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

    #define RECORDINGBUFFERSIZE 1024 // Buffer for recording the frames

    #define EPROMSIZE 1024 // Size of EEPROM in your Arduino chip.

    // defining PINs for Arduino PRO MINI

    byte sck = 16; // D13

    byte miso = 15; // D12

    byte mosi = 14; // D11

    byte ss = 13; // D10

    byte gdo0 = 9; // D6

    byte gdo2 = 5; // D2


    Example for Raspberry Pi Pico / RP2040 board – ATTENTION ! I HAVE TESTED THIS BOARD AND IT USES 3.3V LOGIC

    #define RECORDINGBUFFERSIZE 4096 // Buffer for recording the frames

    #define EPROMSIZE 512 // Size of EEPROM in your Arduino chip.

    // defining PINs for Raspberry Pi Pico

    // see pinout: https://cdn-learn.adafruit.com/assets/assets/000/099/339/original/raspberry_pi_Pico-R3-Pinout-narrow.png

    byte sck = 2;

    byte miso = 4;

    byte mosi = 3;

    byte ss = 5;

    int gdo0 = 7;

    int gdo2 = 6;

    Attention ! There may be different SPI pins set for your Pico board :

    byte miso = 16;

    byte ss = 17;

    byte mosi = 19;

    byte sck = 18;


    First version of this project was presented in this video : https://youtu.be/iPVckkTjsd0
    Using Universal Radio Hacker and my CC1101-tool is presented in following video : https://youtu.be/mdkEK_wmWJA

    Change log :

    08.06.2023 : optimized CLI

    • removed unnecessary parameters for commands RX, TX, JAM.
    • changed command JAMM to JAM.
    • optimized output of RX command – now will print directly hex values with no description when sniffer enabled.
    • corrected reaction for CR/LF when using with “Serial Terminal” application on USB OTG port on Android phones
    • 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…

    09.06.2023 : added RAW mode as in Flipper Zero

    • rxraw “interval microseconds”,
    • recraw “interval usec”,
    • playraw “interval usec”,
    • showraw – for record & replay attacking.
    • buffer of 1536 bytes is used to store recording (in ATMEGA32U4, 1024 for Atmega Mega/Uno/Nano, 4096 or more for ESP32 boards).
    • 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 🙂

    10.06.2023 :

    • added Arduino Mega/Nano/Uno version which requires TTL logic converter for 3.3V – TXS0108E.
    • added ESP32 version.
    • changed RECRAW command to start recording RAW signal once something appears over the radio.
    • 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).
    • added option SCAN to find a peak frequency for recording/jamming..

    17.06.2023 :

    • added SAVE function to store recorded frames buffer into non-volatile EEPROM memory of the Arduino chip
    • added LOAD function to restore recorded frames from non-volatile memory and put them into recording buffer for replaying.
    • added SHOWBIT command to display RAW data from the buffer as stream of bits.
    • corrected ESP32 version which has problem with changing (char *) type to (byte *) due to different C++ compiler for ESP32 boards

    18.06.2023 :

    • updated bit storage order in PLAYRAW, RXRAW, RECRAW commands to match the type used in Universal Radio Hacker tool : https://github.com/jopohl/urh

    30.06.2023

    • added debug message during CC1101 startup
    • corrected EEPROM usage for ESP32 chip based Arduino – ESP32 has 512 bytes, ESP8266 has 4096 bytes
    • added ESP32-WROOM version ( I have tested it succesfully with my own board )
    • added ESP8266 – WEMOS D1 Mini version

    08.07.2023

    • 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.

    13.07.2023

    • 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

    27.07.2023:

    • rp2040 board added

    18.08.2023:

    • 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.

    02.09.2023

    • 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…

    • 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 :

      IPAddress ip(192, 168, 43, 100); // Local Static IP address

      IPAddress gateway(192, 168, 43, 1); // Gateway IP address

      IPAddress subnet(255, 255, 255, 0); // Subnet Mask

      const char ssid[] = “AndroidAP”; // Change to your Router SSID

      const char password[] = “password”; // Change to your Router Password

    Example scenario for WIFI / telnet connection when ESP8266 is WIFI client :
    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.
    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”.

    08.09.2023

    • 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”.

    22.11.2023
    Corrected bug in showbit() function, all the thanks go to jps1x2.

    08.02.2024
    Corrected bug in scan() function (not accepting MHz fractions in frequency range), all the thanks go to chris4soft

    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).

    Visit original content creator repository