Clockwork PicoCalc · Volume 11
PicoCalc Volume 11 — Use-Case Playbooks: Hacking & Ham Radio
Sub-GHz, LoRa, BLE/WiFi tools, APRS, CW, WSPR, hamlib
Contents
| Section | Topic |
|---|---|
| 1 | About this Volume |
| 2 | Use-Case Playbooks: Hacking and Ham Radio |
| · 2.3 | PicoCalc as a hacking tool |
| · · 2.3.1 | What’s actually feasible |
| · · 2.3.2 | Setup — sub-GHz with CC1101 |
| · · 2.3.3 | Setup — LoRa sniffing |
| · · 2.3.4 | Setup — I²C bus probe |
| · · 2.3.5 | Legal — read this |
| · 2.4 | PicoCalc as a ham-radio companion |
| · · 2.4.1 | APRS — packet radio terminal |
| · · 2.4.2 | LoRa-APRS |
| · · 2.4.3 | CW keyer and Morse decoder |
| · · 2.4.4 | WSPR (Weak Signal Propagation Reporter) |
1. About this Volume
This volume covers the PicoCalc as a hardware-hacking instrument and as a ham-radio companion.
The hacking section covers what’s actually feasible (sub-GHz with CC1101, LoRa with RFM95, BLE on Pico 2 W, PIO-based bus probing, JTAG, and limited WiFi monitor mode), where the PicoCalc wins versus other tools in the Hack Tools hub (it’s a credible CC1101 / RFM95 platform but the Cardputer is the better tool for serious WiFi attacks; HackRF is a wideband companion not a replacement), and the legal envelope around RF transmit (FCC Part 15 / ETSI compliance for the 433/915 MHz bands, plus the ham-license requirement for amateur-band TX).
The ham-radio section covers APRS over AFSK with a full audio-interface schematic to a real rig, LoRa-APRS via RFM95 modules, CW keyer + decoder (pure-software practice mode, plus rig-keying via PTT line), WSPR controller for an external transmitter (QCX-mini, Etherkit Si5351), and hamlib bridges to a CAT-controllable desk rig.
The companion add-on hardware (CC1101, RFM95, audio interfaces) and their schematic theory are covered in Volume 7. Legal/ethics references in _shared/legal_ethics.md.
2. Use-Case Playbooks: Hacking and Ham Radio

Figure 2.0 — VHF handheld radio. File:Amateur radio VHF handheld transceiver on yacht.jpg by Nigel Jones. License: CC BY-SA 4.0. Via Wikimedia Commons.
2.3 PicoCalc as a hacking tool
The PicoCalc is a credible hardware-hacking instrument when paired with the right add-on radios. Compared to other tools in the Hack Tools hub:
- vs. Cardputer: PicoCalc has a better screen and more RAM but no built-in WiFi attack stack. Cardputer wins for WiFi attacks; PicoCalc wins for sub-GHz / LoRa / I²C protocol work where the larger screen helps.
- vs. HackRF One: PicoCalc is a handheld supplement to a wideband SDR, not a replacement. Pair them: PicoCalc as a controller with the LCD; HackRF as the radio over USB-host or a separate machine.
- vs. Flipper Zero: similar ambition, but PicoCalc gives you a real keyboard and more screen, while Flipper has an integrated sub-GHz radio. PicoCalc + CC1101 covers the same sub-GHz ground at lower cost; Flipper has way more polished apps.
2.3.1 What’s actually feasible
| Workload | PicoCalc capability |
|---|---|
| 433/868/915 MHz sniff/replay | CC1101 add-on; works well |
| LoRa sniffing | RFM95 add-on; works well |
| WiFi monitor mode | Pico 2 W has limited monitor capability |
| WiFi deauth / handshake capture | Possible on Pico 2 W but ESP32 (Cardputer) is better |
| BLE scanning | Pico 2 W; works |
| RFID/NFC | No built-in; add a PN532 over I²C |
| I²C / SPI / 1-wire bus probing | Pico’s PIO is excellent at this |
| JTAG bus probing | Yes via PIO |
| Side-channel (power analysis) | No (no shunt amp built in) |
| Glitching | RP2350’s PIO is good for glitch generators |
2.3.2 Setup — sub-GHz with CC1101
- Wire CC1101 to side header (SPI; see §10.3).
- Flash Picoware (with CC1101 driver) or build a custom C app.
- Picoware’s UI: Apps → Sub-GHz → Read.
- Hold the PicoCalc near a transmitting device (garage opener, weather station, etc.). Picoware shows the captured frame; you can replay it.
2.3.3 Setup — LoRa sniffing
- Wire RFM95 (§10.2).
- Flash a small MicroPython script using
micropython-loralib:
from machine import SPI, Pin
import lora
spi = SPI(0, baudrate=10000000, sck=Pin(18), mosi=Pin(19), miso=Pin(16))
radio = lora.SX127x(spi, cs=Pin(17), reset=Pin(15), dio0=Pin(14))
radio.set_freq_mhz(915)
radio.set_spread_factor(7)
radio.set_bandwidth(125000)
radio.recv_continuous(lambda payload, rssi: print(f"{rssi}dBm: {payload}"))
This dumps every LoRa frame in range to the REPL.
2.3.4 Setup — I²C bus probe
- Connect target’s SDA / SCL / GND to side header.
- Use a PIO-based I²C analyzer (community code; search “pico i2c sniffer”):
// Pseudo-code: PIO state machine watches SDA / SCL transitions
// Decoded byte stream printed to USB CDC
The 200×200 region of the LCD becomes a real-time byte/timing display.
2.3.5 Legal — read this
The legal/ethics doc at ../_shared/legal_ethics.md of this project applies: you transmit only on hardware you own or have written authorization to test. Receiving / monitoring is broader (passive RX is generally OK in most jurisdictions for unencrypted hobby bands), but sub-GHz transmit (433/915 MHz) requires an FCC Part 15 power-budget compliance check in the US (and ETSI equivalents in Europe).
2.4 PicoCalc as a ham-radio companion
PicoCalc isn’t an HF transceiver — it has no transmitter or receiver of its own. It can, however, serve as:
- A digital-mode encoder/decoder when paired with a real rig over audio or USB.
- A portable APRS terminal when paired with a 1200 baud AFSK modem or LoRa-APRS radio.
- A CW keyer and Morse decoder on its own (no rig needed for practice, paired with a rig via PTT line for real CW).
- A WSPR beacon controller when paired with an external transmitter.

Figure 2.4 — Ham-radio interface schematic. Hand-authored for this volume.
2.4.1 APRS — packet radio terminal
APRS (Automatic Packet Reporting System) is a 1200-baud AX.25-over-AFSK protocol used by hams for position reporting and short messages. The PicoCalc can encode/decode APRS in software:
- Audio interface: PCM5102A I²S DAC (§10.1) for transmit audio out; ADC pin GP28 for receive audio in. Wire to your rig’s mic/speaker jacks (with isolation transformers — see references).
- Software: a community PicoMite library implements 1200 AFSK on Pico’s PIO. Source: https://github.com/topics/aprs — search forks tagged
picomite. - What you do with it: connect to your VHF rig, your callsign and grid go on the APRS network. Receive packets on screen, display incoming messages, transmit short packets.
2.4.2 LoRa-APRS
LoRa-APRS routes APRS over LoRa instead of AFSK — much longer range at lower power, no audio modulation. The hardware path:
- RFM95 module wired to side header (§10.2).
- Antenna for the 433.775 MHz LoRa-APRS band (in EU; US uses 915 MHz subbands).
- Software: https://github.com/lora-aprs for reference implementations. The
LoRa_APRS_iGateandLoRa_APRS_Trackerprojects port to Pico with minor changes. - Configure your callsign in the source, build, flash, transmit position.
This is a working portable LoRa-APRS station. Range is typically 5-15 km with stock antennas; better with elevated antennas. See https://how.aprs.works/lora-aprs-bringing-aprs-into-the-21st-century/ for the full background.

Figure 2.4 — Iambic paddle. File:Bencher BY-1 Iambic Paddle.JPG by camelNotation. License: CC0. Via Wikimedia Commons.
2.4.3 CW keyer and Morse decoder
Pure software on PicoCalc — no radio needed for practice mode.
Keyer (PicoMite):
' CW keyer — paddle inputs on GP12 / GP13, output on GP14
DIM speed_wpm = 20
DIM dit_ms = 1200 / speed_wpm
DO
IF PIN(12) = 0 THEN ' dit paddle
PIN(14) = 1 : PAUSE dit_ms : PIN(14) = 0 : PAUSE dit_ms
ENDIF
IF PIN(13) = 0 THEN ' dah paddle
PIN(14) = 1 : PAUSE dit_ms*3 : PIN(14) = 0 : PAUSE dit_ms
ENDIF
LOOP
The output (GP14) drives the rig’s keying line via a 2N3904 transistor.
Decoder: read audio from the rig via the ADC, run an FFT to detect the 600 Hz tone, threshold-detect dot/dash lengths, decode to ASCII. K3NG’s decoder algorithm is the canonical reference; a Pico port exists at https://github.com/k3ng/k3ng_cw_keyer.
2.4.4 WSPR (Weak Signal Propagation Reporter)
WSPR is a slow data mode that reports propagation paths globally. The PicoCalc cannot transmit on its own, but with an external WSPR-capable transmitter (QRP Labs QCX-mini, Etherkit Si5351 + amp), the PicoCalc can:
- Calculate the WSPR encoding from your callsign, grid, and dBm.
- Time the transmission window to the WSPR clock (even-minute UTC slots; WSPR uses 2-minute windows starting at 00, 02, 04, … seconds past the hour).
- Key the external transmitter’s PTT line via GPIO (same optoisolator circuit as the CW keyer above).
- Log received WSPR spots from the global database if the PicoCalc has network access (via Pi Zero compute path or a USB-tethered phone).
Hardware pairing — QCX-mini: The QRP Labs QCX-mini is a 5 W CW/WSPR transceiver kit (~$55). Connect PicoCalc → QCX-mini via a 3.5 mm key jack (GP14 through the 2N3904 keying circuit). The QCX-mini’s built-in WSPR mode handles the FSK modulation internally — the PicoCalc’s job is to calculate the symbol sequence and time the TX window. CAT control is not needed; the QCX-mini sits on a fixed WSPR frequency (e.g. 14.0956 MHz for 20 m).
Hardware pairing — Si5351 + PA: For a fully homebrew WSPR beacon, wire an Etherkit Si5351A breakout to the Pico via I²C. The Si5351 generates the RF carrier; the PicoCalc shifts its frequency in 1.46 Hz steps to encode the WSPR symbols. Add a BS170 PA stage for ~200 mW output — enough for WSPR on 20/30/40 m with a resonant antenna. Schematic and BOM in Volume 7 §10.4.
Software skeleton (MicroPython, Pico 2):
from machine import Pin, I2C, RTC
import time
# WSPR symbol table: 162 symbols, each 0-3, ~0.68 s per symbol
# Generated from callsign + grid + power using the WSPR encoding algorithm
def wspr_encode(callsign: str, grid: str, dbm: int) -> list[int]:
"""Return 162-symbol WSPR message. See Joe Taylor K1JT's algorithm."""
# Implementation: bit-interleaved convolutional code + sync vector
# Reference: https://www.physics.princeton.edu/pulsar/k1jt/wspr.html
... # ~80 lines; port from the C reference in wsprd
def wait_for_even_minute():
"""Block until the next even-minute UTC boundary."""
while True:
t = time.gmtime()
if t[4] % 2 == 0 and t[5] == 0:
return
time.sleep(0.1)
# PTT keying
ptt = Pin(14, Pin.OUT, value=0)
symbols = wspr_encode("N0CALL", "FN31", 23)
wait_for_even_minute()
ptt.on()
for sym in symbols:
# Shift Si5351 frequency by sym * 1.4648 Hz
# si5351.set_freq(base_freq + sym * 1.4648)
time.sleep(0.6827) # 256/375 seconds per symbol
ptt.off()
Clock synchronization is critical — WSPR decode fails if TX timing drifts more than ~1 s from UTC. Options: GPS module on UART (§10.5), NTP via the Pi Zero compute path, or a DS3231 RTC (§10.8 in Volume 7) set once from a known-good source.
Licensing reminder: WSPR transmits on amateur-radio bands. You need a ham license (Technician class minimum in the US; equivalent in your jurisdiction) and must identify with your own callsign. Receive-only monitoring of WSPR spots requires no license.
3. Resources
| Resource | URL |
|---|---|
| CC1101 MicroPython driver | https://github.com/peterhinch/micropython-radio |
| RFM95 / SX127x MicroPython library | https://github.com/lemariva/uPyLoRa |
| APRS protocol reference (AX.25) | http://www.aprs.org/doc/APRS101.PDF |
| LoRa-APRS project | https://github.com/lora-aprs |
| K3NG CW keyer (Arduino, portable to Pico) | https://github.com/k3ng/k3ng_cw_keyer |
| WSPR encoding algorithm (K1JT) | https://www.physics.princeton.edu/pulsar/k1jt/wspr.html |
| QRP Labs QCX-mini (WSPR/CW transceiver kit) | https://qrp-labs.com/qcxmini.html |
| Etherkit Si5351 Arduino library | https://github.com/etherkit/Si5351Arduino |
| WSPRnet spot database | https://www.wsprnet.org/ |
| PicoCalc hardware schematics | https://github.com/clockworkpi/PicoCalc |
| FCC Part 15 (ISM band limits) | https://www.ecfr.gov/current/title-47/chapter-I/subchapter-A/part-15 |
| Legal/ethics reference (this project) | ../_shared/legal_ethics.md |