Skip to content
HN On Hacker News ↗

CC1101 on an FT232H: a 433 MHz scanner in the terminal

▲ 36 points • 16 comments • by xx__yy • 3d ago • HN discussion ↗

Pangram verdict · v3.3

We believe that this text is a mix of AI and human-written content.

62 %

AI likelihood · overall

Mixed
38% human-written 62% AI-generated
SEGMENTS · HUMAN 20 of 58
SEGMENTS · AI 38 of 58
WORD COUNT 1,740
PEAK AI % 100% · §1
Analyzed
Nov 3
backend: pangram/v3.3
Segments scanned
58 windows
avg 30 words each
Distribution
38 / 62%
human / AI fraction
Verdict
Mixed
Pangram v3.3

Article text · 1,740 words · 58 segments analyzed

Human AI-generated
§1 AI · 100%

Our gate remotes send on 433 MHz, and I wanted to see what those signals looked like. A cheap AliExpress copy remote couldn’t learn them. So I put a CC1101 radio module on a CJMCU-232H, an FT232H board that plugs straight into the laptop. Six jumper wires and a Python script: no microcontroller to flash, nothing to solder.

§2 Human · 0%

This setup and test was just to prove that the FTDI board could be connected to the 433 MHz board (bought from AliExpress), and that together they could scan and visualise simple signals from a bootleg remote.

§3 Human · 0%

The rig, drawn: the FT232H board, six wires, the CC1101 and its antenna.

§4 Human · 0%

A CC1101 433 MHz module and its antenna.

§5 Human · 0%

Mine is an E07-M1101D (Ebyte’s board layout, with an SMA socket), about AU$3.40 on AliExpress.

§6 Human · 0%

A CJMCU-232H: a purple board with an FTDI FT232H chip and a USB-A plug.

§7 AI · 100%

A breadboard, 4 male-female jumper wires and 2 female-female ones. Linux with Python 3.

§8 AI · 100%

The script uses pyftdi.

§9 AI · 100%

Something that sends on 433 MHz to test with.

§10 AI · 100%

I used the copy remote.

§11 AI · 100%

The CC1101 talks SPI. A plain USB-serial stick (CP2102, CH340) only does serial, so it can’t drive it. The FT232H does SPI from USB, so Python on the laptop talks to the radio directly. The usual way is an ESP32 running ESPHome, which means building and flashing firmware every time you change something.

§12 Human · 0%

Step 1: Download the filesSection titled “Step 1: Download the files” rf-scan-ft232h.py: the scanner keeloq-capture-ft232h.py: sets up the CC1101 and samples its data.

§13 AI · 100%

The scanner uses it, and on its own it captures KeeLoq remote presses keeloq-check.py: the KeeLoq decoder both of them use 70-ftdi-ft232h.rules: a udev rule so your user can open the board All four are MIT licensed.

§14 AI · 100%

Keep the three scripts in one folder.

§15 AI · 100%

mkdir -p ~/cc1101 && cd ~/cc1101curl -O https://blog.jacq.cc/cc1101-scanner/rf-scan-ft232h.py \ -O https://blog.jacq.cc/cc1101-scanner/keeloq-capture-ft232h.py \ -O https://blog.jacq.cc/cc1101-scanner/keeloq-check.py \ -O https://blog.jacq.cc/cc1101-scanner/70-ftdi-ft232h.rules Step 2: Install pyftdi and the udev ruleSection titled “Step 2: Install pyftdi and the udev rule” python3 -m venv .venv.venv/bin/pip install pyftdisudo install -m 644 70-ftdi-ft232h.rules /etc/udev/rules.d/sudo udevadm control --reload.venv/bin/python rf-scan-ft232h.py --self-test The rule tags the FT232H (USB ID 0403:6014) with uaccess, so the logged-in user can open it: no sudo to run the scanner. Plug the board in after reloading the rules, or unplug it and plug it in again. --self-test needs no hardware: it decodes synthetic noisy presses, and a real frame from my copy remote. The CC1101’s header prints only pins 1, 2, 7 and 8.

§16 AI · 100%

Pin 1 is the square pad, the odd pins run along the board’s edge, and the even pins sit on the inside.

§17 Human · 0%

CC1101 pin Name CJMCU-232H 1 GND GND on the 4-pin header 2 VCC +3.3V on the 4-pin header. Never +5V, and not VCORE 4 CSN AD3 5 SCK AD0 6 MOSI AD1 7 MISO / GDO1 AD2 3, 8 GDO0, GDO2 not connected Six wires.

§18 AI · 100%

The CJMCU-232H prints its pin names only on the back, so they’re drawn in here.

§19 AI · 100%

The CJMCU-232H goes on the breadboard.

§20 AI · 100%

The CC1101 stays off it: its 2 × 4 header would short its pins in pairs along the breadboard’s rows. So the signal wires go male end into the breadboard beside the AD pins, female end onto the CC1101. The power pair goes female to female, straight onto the 4-pin header. My layout: the board’s AD row in rows 21 to 30, the jumpers in column j beside it.

§21 AI · 100%

Screw the antenna onto the CC1101.

§22 AI · 100%

Power first, with female-female wires: CC1101 pin 1 to GND and pin 2 to +3.3V on the 4-pin header.

§23 AI · 100%

Signals, with male-female wires: pin 4 to AD3, pin 7 to AD2, pin 6 to AD1, pin 5 to AD0.

§24 AI · 100%

Leave +5V and CC1101 pins 3 and 8 empty. Power first: red from pin 2 to +3.3V, brown from pin 1 to GND.

§25 AI · 100%

All six wired. The loose black and orange jumpers aren’t part of it. The USB plug hangs off the end of the breadboard. A short USB extension cable helps.

§26 AI · 100%

.venv/bin/python rf-scan-ft232h.py Use a terminal window at least 60 × 20.

§27 AI · 100%

Before the screen starts, the script checks the radio: it reads the chip’s version (mine says 0x14), writes its settings and reads them back, and checks it’s receiving. If something fails, it names the wires to check. “No CC1101 answers” means power, SCK, MISO or CSN. Settings that read back wrong mean MOSI.

§28 AI · 100%

It only receives. It never transmits.

§29 AI · 100%

There are two screens, and Tab switches between them. Key Sweep Listen Tab listen at the marker (Enter too) back to the sweep ← → move the marker one column tune ±10 kHz [ ] move the marker 10 columns tune ±100 kHz p marker to the strongest signal z x zoom in or out around the marker b next band c clear clear q quit and print a summary quit and print a summary Other options: --band 315 starts on another band: 433 (the default, 432 to 436 MHz), 315, 300-348, 387-464, 779-928, all, or any START-STOP in MHz.

§30 AI · 100%

--listen 433.92 starts on the listen screen.

§31 AI · 100%

--text prints plain lines instead of the screen, and --seconds 30 stops it by itself. --replay /tmp/rf-listen.log decodes a saved log instead of the radio. The CC1101 only tunes 300 to 348, 387 to 464 and 779 to 928 MHz. A 433 MHz module and antenna hear only strong signals in the other bands. The sweep steps across the band and reads the signal strength (RSSI) at each step. It shows bars with peak hold (yellow dots), a waterfall of past sweeps underneath (newest at the top), and the strongest signals seen along the bottom.

§32 Human · 0%

Zoomed out to 402 to 466 MHz, with a remote pressed near 434 MHz. The 433 band sweeps in 0.16 s.

§33 Human · 0%

All three bands take 0.6 s. The noise floor here is about −90 dBm.

§34 Human · 3%

Steady signals sit near 408, 416, 418 to 420, 442 and 456 MHz, pressed or not.

§35 AI · 99%

The one near 416 MHz is the strongest, at about −65 dBm.

§36 AI · 100%

A press near 434 MHz reads up to −22 dBm.

§37 AI · 100%

Close to the antenna, it spills into the steps around it, from 431.7 to 436.5 MHz.

§38 AI · 100%

On all bands, two more peaks show up at 782 and 883 MHz. Both are in mobile phone tower bands.

§39 AI · 100%

Put the marker on a signal and press Tab. The listen screen stays on that one frequency and records what the CC1101 demodulates.

§40 Human · 5%

It shows the signal strength over the last minutes, the last frame’s pulses and bits, and every code heard more than once, with a guess at the protocol.

§41 Human · 0%

The timings go to /tmp/rf-listen.log. The copy remote.

§42 Human · 0%

It sends a fixed code: the same bits on every press.

§43 Human · 0%

Inside is a board marked 520B V2.1: four buttons (K1 to K4), a 433 MHz SAW resonator (R433) and a 12 V 27A battery.

§44 Human · 0%

The chip is an FMD FT60E021, a general-purpose 8-bit microcontroller, not a dedicated remote encoder, so the code it sends comes from its firmware. The gate remotes have a KeeLoq encoder chip instead, the HCS300.

§45 Human · 0%

The board: the chip (U2), the resonator (X1) and the four buttons. The chip: an FMD FT60E021 microcontroller.

§46 Human · 0%

The back. The antenna is a copper trace printed on the board.

§47 Human · 0%

The copy remote’s specs, its parts and its instruction sheet are on its device page: AliExpress 433 MHz copy remote. All four buttons of the copy remote, one short press each. The copy remote sends EV1527-style codes: 24 bits, a 20-bit ID (0x0B80A) and 4 button bits. Its buttons send 0x0B80A1, 0x0B80A2, 0x0B80A4 and 0x0B80A8.

§48 AI · 97%

The shortest pulse (TE) is 340 µs.

§49 AI · 100%

The presses came in at −18 to −20 dBm, against a floor of −88 dBm. A remote repeats its code while the button is down, so each short press gave 3 to 7 frames. Holding the buttons down fills the list with shorter codes too, 12 to 22 bits long, like 0x80A4 and 0x0B80. They’re pieces of the real codes that noise cut short.

§50 AI · 100%

Only the 24-bit rows are real.

§51 AI · 100%

Buttons held down: the four real codes, and pieces of them.

§52 AI · 100%

The script sets the CC1101 up as an OOK receiver on 433.92 MHz, with Flipper Zero’s AM650 settings: a 650 kHz filter and no packet handling. The chip puts the demodulated data on its GDO1 pin.

§53 AI · 100%

On this module GDO1 shares a pin with MISO: while CSN is high, nobody is talking to the chip and MISO carries the data. The FT232H is already in SPI mode to talk to the radio, and an SPI read clocks bits in at a steady rate. So the script opens a second SPI port on a chip-select pin that isn’t wired, AD4. Reading from it leaves CSN high and clocks MISO in at 50 kHz: a sample every 20 µs, about 17 of them per 340 µs pulse. A thread keeps the USB reads back to back, and the decoder turns runs of ones and zeros into pulse lengths. When the radio is idle, its output on my rig is mostly high with short dips. That noise often runs straight into the start of a frame and swallows the first bit’s high pulse.

§54 AI · 100%

Every frame of the copy remote came out 23 bits long instead of 24. The fix: read that bit from its low pulse alone. In EV1527 a 1 is a long high and a short low, and a 0 is a short high and a long low.

§55 AI · 100%

For the sweep, the script tunes to each step, waits 1.2 ms for the chip to calibrate and settle, and reads its RSSI register.

§56 AI · 100%

The filter is set as wide as the step, so a sweep leaves no gaps between steps.

§57 Human · 0%

How it turned outSection titled “How it turned out” The test was quite successful, and the TUI proved quite handy for learning and seeing what these remotes can output. Next: the gate remotesSection titled “Next: the gate remotes” The next project builds on this one: scanning the Richmond gate remotes to see what they output and what that looks like. They’re the same remotes that open our garage through a GE-RCV1. Inside each one is a Microchip HCS300, a KeeLoq rolling-code chip.

§58 Human · 0%

A rolling-code remote shouldn’t send the same thing twice. Each press is a 66-bit frame: the remote’s serial number and buttons in the clear, and a 32-bit encrypted part that holds a counter, which goes up on every press.