Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

240 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

WSPR Transmitter

WSPR-Transmitter is a C++20 component for generating WSPR (Weak Signal Propagation Reporter) RF transmissions with precise symbol timing.

The current production-proven path is a Raspberry Pi backend that uses Broadcom mailbox, DMA, PWM, and clock hardware to emit RF. The codebase has been refactored so transmission control and scheduling live in a generic controller, while platform-specific hardware work lives behind a backend interface.

What The Project Does

The component can:

  • Configure a WSPR transmission from RF frequency, power level, PPM correction, and optional callsign/grid/power message fields
  • Run either continuous-tone output or full WSPR symbol transmissions
  • Schedule WSPR transmissions on proper window boundaries
  • Stop, reconfigure, and restart safely
  • Monitor backend-specific hardware faults and recover through backend-owned recovery logic

The public facade is WsprTransmitter. Higher-level code uses that class and does not need to manipulate DMA, PWM, mailbox, or watchdog details directly.

High-Level Architecture

The architecture is split into three layers:

1. Controller / Facade

WsprTransmitter owns:

  • Public API
  • Transmission configuration state
  • Scheduler and worker-thread orchestration
  • High-level transmission state machine
  • Symbol timing decisions
  • Callback delivery

The controller decides when a transmission starts and when each symbol should be emitted. It does not own backend-private hardware sequencing state.

2. Generic Backend Interface

WsprTransmitBackend defines the hardware-facing contract used by the controller. The interface is intentionally expressed in generic transmission operations rather than Raspberry Pi DMA concepts.

Shared backend-neutral data types live in wspr_transmit_types.hpp:

  • WsprTransmissionPlan Snapshot of transmission intent and configuration passed from controller to backend. It currently includes:
    • RF center frequency in hertz (Hz)
    • Tone spacing in hertz (Hz)
    • Logical output power level
    • Symbol count
  • WsprTransmissionConfigureResult Small result returned by backend configuration. It currently reports the applied RF center frequency in hertz (Hz) after backend quantization or hardware adjustment.

3. Raspberry Pi Backend

WsprRpiBackend owns all Raspberry Pi-specific implementation details, including:

  • Mailbox allocation and peripheral mapping
  • DMA control-block setup and ring management
  • PWM / GPCLK programming
  • GPIO drive-strength based output control
  • DMA watchdog monitoring
  • Watchdog recovery and hardware reset behavior

Those details are intentionally kept out of the generic controller/backend boundary.

Backend Model

The backend model is designed so additional hardware implementations can be added without changing the controller's scheduling and transmission logic.

Current backend responsibilities:

  • Prepare hardware resources for a configured transmission
  • Apply the transmission plan to hardware
  • Report the applied configuration back to the controller
  • Enable and disable RF output
  • Emit controller-scheduled symbols
  • Handle backend-private fault monitoring and recovery

Current controller responsibilities:

  • Build the transmission plan
  • Determine symbol timing
  • Drive lifecycle sequencing
  • Maintain high-level state
  • Coordinate stop and restart behavior

Transmission Lifecycle

At a high level, the lifecycle is:

  1. configure(...) The controller stores user configuration, derives WSPR symbol data when message mode is selected, and builds the backend-neutral transmission plan.
  2. prepareTransmission() The backend allocates or initializes hardware-specific resources.
  3. configureTransmission(plan) -> result The backend applies hardware configuration and returns the actual RF center frequency in hertz (Hz) that will be used.
  4. startAsync() The controller starts either immediate tone transmission or the WSPR scheduler, depending on mode.
  5. beginTransmissionOutput(plan) The backend enables RF output.
  6. emitSymbol(plan, sym_num, tsym, symbol_index) The controller calls this once per scheduled symbol. tsym is expressed in seconds. In continuous-tone mode, tsym is 0.0.
  7. endTransmissionOutput() The backend disables RF output.
  8. cleanupTransmission() Backend resources are released during shutdown or reconfiguration.

This split keeps timing control in the controller while leaving hardware sequencing private to the backend.

Repository Layout

src/
  main.cpp                    Demo / test harness
  Makefile                    Standalone build rules
  wspr_transmit.hpp           Controller / facade public API
  wspr_transmit.cpp           Controller implementation
  wspr_transmit_backend.hpp   Generic backend interface
  wspr_transmit_backend_rpi.hpp
  wspr_transmit_backend_rpi.cpp
                              Raspberry Pi backend
  wspr_transmit_types.hpp     Shared state, plan, and result types

Dependencies

This project expects sibling modules that provide:

  • WSPR message encoding
  • Broadcom mailbox access and DMA-safe memory allocation

The current standalone Makefile includes those submodule paths when present.

Building

cd src
make debug

Common targets:

  • debug builds the debug test binary
  • release builds an optimized binary
  • clean removes build artifacts

The Raspberry Pi runtime path requires appropriate privileges for low-level hardware access.

Debian Contract CI

The Debian backend contracts workflow runs the simulator and transmission controller contract tests in an isolated Debian Trixie checkout. Those tests are standalone and require no hardware or elevated privileges.

Si5351 transition, startup-quiescence, full debug-build, and physical-backend regressions still require the dependency topology recorded by the parent WsprryPi repository. The parent non-hardware workflow runs those tests against the exact pinned sibling submodules. Neither workflow performs installation, service management, transmitter device access, live transmission, or RF qualification.

Runtime Notes

  • RF frequency values are expressed in hertz (Hz)
  • Symbol duration values are expressed in seconds
  • Power reporting helpers return estimated milliwatts (mW)
  • The Raspberry Pi backend is the only production-verified backend at present

Current Status

  • Controller/backend refactor complete
  • Generic backend interface in place
  • Raspberry Pi RF path re-verified after refactor
  • WsprTransmissionPlan and WsprTransmissionConfigureResult are part of the stable shared interface

License

See source file headers for license terms.

About

A C++17 class for transmitting WSPR messages or continuous test tones using DMA and PWM on Raspberry Pi. Runs in a dedicated real-time thread with controllable scheduling policy and priority.

Resources

Stars

2 stars

Watchers

2 watching

Forks

Releases

Packages

Contributors

Languages