C4FM-VB is a C++ project for experimenting with wide C4FM-style file transfer. It is intentionally structured like the working 4GFSK project, but the modem layer is refocused around 4-level FM / C4FM dibits instead of the earlier 4GFSK interpretation.
This first pass provides:
- packetization, CRC protection, and file reassembly
- a self-contained C4FM-style dibit modulator and FM discriminator decoder
- simulation with AWGN, timing offset, and frequency offset
- optional SoapySDR over-the-air testing
- full-duplex self-loopback transport
- a first-pass half-duplex runtime option
It is meant as a clean sandbox for building a wideband C4FM transmitter/decoder without depending on dsd-neo.
This project is wide C4FM-style, not a strict P25 implementation.
- The symbol mapping follows the usual C4FM-style 4-level dibit idea.
- The framing, file transfer, and OTA workflow are custom and project-local.
SiteSimwas used as a reference for C4FM transmit conventions, but this project keeps its own decoder and does not reuse thedsd-neoreceive engine.
Requirements:
- CMake 3.20+
- a C++20 compiler
pkg-configSoapySDRdevelopment files for OTA mode
Build:
cmake -S . -B build
cmake --build buildRun tests:
ctest --test-dir build --output-on-failureIf SoapySDR is available, OTA support is compiled in automatically. Otherwise, the simulation path still builds and runs.
Show help:
./build/c4fm_vb --helpImportant options:
--mode <simulate|ota>selects simulation or OTA--input <path>uses a real file as payload--generate-bytes <n>generates a synthetic test payload--payload-bytes <n>controls file chunk size--symrate <Hz>sets symbol rate--sps <count>sets samples per symbol--deviation-step <Hz>sets the C4FM deviation step for the+/-1and+/-3levels--duplex <full|half>selects OTA duplex mode--stream-mode <continuous|burst>selects continuous whole-file streaming or per-packet bursts--packet-repetitions <n>retransmits each OTA packet payloadntimes
General waveform defaults:
--symrate 480000--sps 4--deviation-step 60000
That corresponds to:
- sample rate:
1.92 Msps - maximum symbol deviation:
180 kHz
OTA defaults are intentionally more conservative when you do not explicitly override them:
--symrate 120000--sps 4--deviation-step 15000
That gives a safer 480 ksps OTA sample path for bring-up and experimentation on hardware such as a B210.
The default OTA center frequency is set to 433.5 MHz as a reasonable 70cm amateur-band default. Override it with --freq whenever you want a different channel.
The default OTA stream mode is continuous, which keeps the signal on-air across the whole file transfer rather than keying separate packet bursts.
Default simulation:
./build/c4fm_vb --mode simulateLarger multi-packet simulation:
./build/c4fm_vb --mode simulate --generate-bytes 4096Simulation with channel impairments:
./build/c4fm_vb --mode simulate \
--generate-bytes 4096 \
--snr-db 30 \
--freq-offset 1200 \
--timing-offset 3Full-duplex continuous self-test at the default 70cm frequency (433.5 MHz):
./build/c4fm_vb --mode ota \
--duplex full \
--stream-mode continuous \
--device driver=uhd \
--tx-gain 35 \
--rx-gain 35 \
--packet-repetitions 2 \
--generate-bytes 4096Half-duplex runtime example:
./build/c4fm_vb --mode ota \
--duplex half \
--stream-mode burst \
--device driver=uhd \
--tx-gain 35 \
--rx-gain 35 \
--generate-bytes 4096 \
--turnaround-delay-ms 10Use --input yourfile.bin instead of --generate-bytes when you want to transfer a real file.
Full duplex is the current validation path for same-radio self-test, because transmit and receive happen at the same time and the receive window is aligned to each burst.
Half duplex is exposed so the transport architecture is not locked to one operating style. It is better suited to future remote or turn-taking workflows than same-radio self-loopback.
- This is a wide C4FM-style modem, not a standards-accurate P25 physical layer.
- The decoder currently uses a straightforward FM discriminator plus symbol slicing.
- Burst acquisition is still simple and can miss packets under real RF conditions.
- Continuous OTA mode keeps RF data flowing across the whole file, but receive-side packet recovery still works by finding packet prefixes and validating CRCs inside the decoded symbol stream.
- B210 over USB 2 can still be throughput-limited.
- This is an experimental transfer tool, not a hardened production modem.
include/c4fmvb/public headerssrc/modem, framing, simulation, OTA, and CLI implementationtests/regression tests