SkillAgentSearch skills...

PhaseLatchMini

High-rate continuous streaming of interleaved dual ADC (I/Q) samples over USB Full‑Speed (FS) using only the built‑in CDC class on an STM32F103C8 ("Blue Pill" style) board. Companion Python host tools provide live visualization, FIFO bridging, raw capture, diagnostics, and throughput benchmarking.

Install / Use

/learn @AndersBNielsen/PhaseLatchMini
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

PhaseLatch Mini – STM32F103 Dual-ADC IQ USB Streamer

Combined hardware + firmware + host tooling for a compact dual‑ADC I/Q capture platform.

Overview

High-rate continuous streaming of interleaved dual ADC (I/Q) samples over USB Full‑Speed (FS) using only the built‑in CDC class on an STM32F103C8 ("Blue Pill" style) board. Companion Python host tools provide live visualization, FIFO bridging, raw capture, diagnostics, and throughput benchmarking.

Status: Actively optimized. Current configured complex sample rate target: 210.5 k I/Q samples/sec (IQ_SAMPLE_RATE_HZ = 210526) with sustained USB payload throughput >500 KiB/s. Timer PSC/ARR are selected at runtime by a search routine for the closest achievable rate; observed effective rate can be within a small delta of the target. ADC sampling time was reduced (now ADC_SAMPLETIME_28CYCLES_5) to reach this rate while maintaining conversion stability.

Origin / Intended Use: Initially developed as a lightweight streaming engine for the PhaseLoom project, but fully usable with any dual (I/Q) analog front end producing baseband signals on two STM32F1 ADC channels. Note: Phaseloom should be modified for best performance. Replace 22kOhm feedback caps with matched 47kOhm resistors and replace the output stage 50 ohms with 0 ohm.

https://www.youtube.com/watch?v=UEAtSE1PV44


Hardware: PhaseLatch Mini

A 4‑layer purple PCB (Blue Pill footprint inspired) integrating two SMA input ports and on‑board ~100 kHz low‑pass filtering (~210 kHz complex baseband bandwidth). Designed around the STM32F103C8 in dual regular simultaneous ADC mode (ADC1 + ADC2) to stream interleaved I/Q samples over USB Full-Speed.

<img src="https://www.imania.dk/product_thumb.php?img=mediafiles/images/produkter/phaselatchmini-frontview.jpeg&w=360&h=360" alt="PhaseLatch Mini" style="width: 220px;">

Key Features

  • MCU: STM32F103C8 (72 MHz) LQFP‑48
  • Dual simultaneous ADC (12‑bit each) packed into 32‑bit words (I lower 12 bits, Q upper 12 bits)
  • 2 × edge‑mount SMA (J20 = I_IN, J21 = Q_IN)
  • Integrated passive input filtering (inductor + capacitor network targeting ~100 kHz LPF per channel)
  • USB‑C connector (USB2.0 FS, CDC class currently; raw/bulk class option planned)
  • On‑board 8 MHz + 32.768 kHz crystals for stable system and RTC timing
  • Ferrite bead + local bulk/decoupling for cleaner ADC rails
  • Unused GPIOs forced to analog mode early for noise reduction (see Quiet_Unused_Pins in main.c)
  • Headers for expansion / SWD / boot configuration

Production Assets

All fabrication outputs live in hardware/PhaseLatchMini/production:

  • PhaseLatchMini.zip – Gerber/drill bundle ready for PCB fab
  • bom.csv – Bill of Materials (with LCSC part numbers for quick JLCPCB sourcing)
  • designators.csv – Component reference list
  • positions.csv – Pick‑and‑place XY + rotation for SMT assembly
  • netlist.ipc – IPC netlist export

Direct link (relative): hardware/PhaseLatchMini/production/PhaseLatchMini.zip

BOM Highlights

Representative components (from bom.csv):

  • Decoupling: multiple 100 nF 0402 caps (C307331) near MCU and filter sections
  • Filter / bulk caps: 22 nF, 220 nF, 470 nF mix shaping input response
  • Inductors: six 10 µH (0805) parts forming LC sections for each channel’s low‑pass filtering / supply isolation
  • USB-C receptacle: 16‑pin (HCTL HC-TYPE-C-16P-01A) with 5k1 CC resistors for proper orientation detection
  • Ferrite bead (FB1) for USB / supply noise suppression
  • Voltage regulator: MIC5504-3.3 (SOT‑23‑5) providing clean 3V3
  • Crystals: 8 MHz main, 32.768 kHz low‑speed (RTC / optional precise timing)
  • SMA edge connectors: matched pair for I and Q inputs

Assembly Notes

  • Clean flux residues near high‑impedance analog nodes (C1/C8 cluster) to keep leakage low.
  • If performing hand assembly, solder the SMA edge connectors first to anchor board alignment, then USB, then fine‑pitch MCU.

Filter Tuning

Current passive network targets ~100 kHz corner. For alternative bandwidths:

  • Raise corner: decrease shunt capacitance (e.g., swap 470 nF → 220 nF or 22 nF depending on desired slope) or reduce inductance value.
  • Lower corner: increase shunt capacitance or employ higher inductance (space permitting). Recalculate fc ≈ 1/(2π√(L·C_eq)).
  • Mitigate source‑resistor induced tilt: include its resistance in design equations; keep initial shunt capacitors modest (≤10 nF) if a 50 Ω series is retained upstream.

Firmware

  • Dual ADC synchronous sampling packed as 32-bit little-endian words (I 12-bit + Q 12-bit inside two 16-bit lanes)
  • Target sample rate IQ_SAMPLE_RATE_HZ (currently 210526) with dynamic TIM3 prescaler/period search (see timer_trigger_init() in iq_adc.c)
  • ADC sampling time set to ADC_SAMPLETIME_28CYCLES_5 for higher throughput (previous higher value limited rate)
  • Circular DMA with half / full transfer interrupts
  • Lock-free ring queue feeding USB transmit path
  • ISR burst chaining (current chain limit 16 packets per IN completion) to minimize USB idle gaps
  • Immediate DMA IRQ packet scheduling ("kick") to prime first packet of each half-buffer
  • Optional diagnostic/stat packets suppressed in throughput builds
  • Host tools for diagnostics, throughput, raw capture, FIFO bridging, live view

Changing the Sample Rate

  1. Edit Inc/iq_adc.h and set #define IQ_SAMPLE_RATE_HZ <desired_rate> (I/Q pairs per second).
  2. Ensure the new rate is feasible: TIM3 must be able to realize it given 16-bit ARR and prescaler; the search code picks the closest achievable value.
  3. If pushing higher rates:
    • Consider reducing ADC sampling time (ADC_SAMPLETIME_x) further, but watch noise/performance.
    • Monitor USB throughput counters (FEED command) for increased busy skips.
  4. Rebuild and flash. Optionally measure actual achieved rate by counting iq_dma_half_count + iq_dma_full_count over a timed host interval.

Verifying Achieved Rate

  • After START, issue the A command periodically; note increments of half/full counts.
  • Effective samples/sec ≈ ((delta_half + delta_full) * half_buffer_samples) / time_interval.
  • Or capture a known duration with host_test.py and compute rows * rate.

Repository Layout

platformio.ini              # Build environments & macro flags
src/                        # Firmware sources (USB, ADC, main logic)
Inc/ / include/             # Public headers
host_*.py                   # Python host utilities
lib/ test/                  # (Placeholders / future use)

Key firmware files:

  • src/main.c – System init, main loop USB feeder (fallback scheduling & instrumentation)
  • src/iq_adc.c / Inc/iq_adc.h – ADC+DMA+Timer configuration, DMA IRQ scheduling kick
  • src/usbd_conf.c – Low-level USB callbacks, DataIn burst chaining logic
  • src/usbd_cdc_if.c – CDC interface, command parser (A/F/STATS) & data write API
  • src/usbd_raw.c (future / optional) – Raw class scaffolding (if transitioning from CDC for additional margin)

Host scripts (root directory):

  • host_diagnostics.py – Passive capture, STATS delta decode, periodic monitor, USB descriptor info
  • host_throughput.py – PyUSB bulk endpoint benchmark (raw vendor class / future); shows packet stats
  • host_raw_capture.py – Robust raw USB (PyUSB or CDC) capture with quiet mode & BrokenPipe safety
  • host_iq_fifo.py – Serial CDC → named FIFO adapter (u8 or cf32) for GQRX / GNU Radio
  • host_iq_live.py – Terminal live IQ stats + sparklines / averages
  • host_test.py – Simple START/STOP based capture, optional float32 output & basic stats
  • host_probe.py – (Currently empty placeholder for future probing utilities)

Build & Flash (PlatformIO)

Prerequisites:

  • VS Code + PlatformIO extension (or pio CLI)

Clone & open project, then build one of the defined environments:

PlatformIO Quickstart (Basics)

If you're new to PlatformIO, these are the minimal steps to get a firmware onto the board.

Option A: VS Code GUI

  1. Install the "PlatformIO IDE" extension in VS Code.
  2. Open this project folder (where platformio.ini resides).
  3. Bottom status bar: pick the desired environment (e.g. adc).
  4. Click the checkmark (Build). Wait for success.
  5. Connect the board via USB (ensure it enumerates) and press the right arrow (Upload). If first flash fails, press/hold BOOT (if available) or use a serial/USB boot jumper sequence depending on your Blue Pill variant.
  6. Use the plug icon (Monitor) or run a host script to interact.

Option B: CLI

Install PlatformIO Core (Python 3.11+ recommended):

pip install --upgrade platformio

From the project root:

# List environments defined in platformio.ini
pio run --list-targets

# Build the adc environment
pio run -e adc

# Upload (adjust -e if choosing another env)
pio run -e adc -t upload

# Open a serial monitor (Ctrl+C to exit)
pio device monitor -b 115200

If you see permission errors on macOS/Linux, you may need to adjust USB device permissions or add your user to the appropriate group (e.g. dialout on some Linux distros).

Common Upload Notes

  • Some Blue Pill clones require setting/removing BOOT0 jumpers for the built-in ROM bootloader; after initial flash with a USB‑TTL adapter or ST-Link, subsequent USB CDC updates normally proceed automatically.
  • For ST-Link users, ensure drivers and udev rules (Linux) are installed.
  • If the device does not reset into the new firmware, press the hardware RESET button.

Serial Device Identification

On macOS you'll typically see /dev/tty.usbmodem*. On Linux, it may appear as /dev/ttyACM0. Use pio device list to enumerate.

Environments (see platformio.ini):

  • env:baseline – Minimal USB baseline with reduced diagnostics (throughput focus pattern)
  • env:diag – Heavier diagnostics enabled (ASCII stat chatter)
  • env:adc – Active dual-ADC streaming (ENABLE_IQ + throughput suppressions)
  • env:adc_smoke – Lower-intensity validation (ext

Related Skills

View on GitHub
GitHub Stars68
CategoryDevelopment
Updated2d ago
Forks13

Languages

Python

Security Score

85/100

Audited on Mar 24, 2026

No findings