Skip to content

ENDOH-R/RSPdx-R2-python-wrapper

Repository files navigation

RSPdx-R2 Python Control Plan

This repository is for building a Python interface to SDRplay RSPdx-R2 hardware. The actual implementation will be generated with opencode/Qwen3, using the SDRplay API already installed on the target machine.

References

Hardware and API Assumptions

  • Target hardware: SDRplay RSPdx-R2.
  • Required SDRplay API version: 3.15 or later.
  • The SDRplay API service/daemon and shared library are already installed.
  • The Python code should call the native SDRplay API through ctypes.
  • Initial implementation targets one RSPdx-R2 device and single-tuner operation.

Architecture

RSPdx-R2 hardware
↓
SDRplay API 3.15
↓
rspdx_r2 ctypes wrapper
↓
capture_iq()
iter_iq_chunks()
↓
capture.json / capture.npy / capture.raw / SigMF
↓
AI-CW-Decoder

Current Capabilities

  • device discovery
  • configure()
  • capture_iq()
  • realtime iter_iq_chunks()
  • npy export
  • raw export
  • metadata export
  • SigMF metadata export
  • inspect_capture.py
  • analyze_capture.py

Installation

Prerequisite: install SDRplay API separately.

macOS downloads:

https://www.sdrplay.com/downloads/

Install this Python wrapper in editable mode:

pip install -e .

This project does NOT redistribute:

  • SDRplay API binaries
  • SDRplay API headers
  • SDK packages
  • installers

SDRplay API Dependency

This project uses SDRplay API as an external runtime dependency.

  • This is a Python ctypes wrapper project.
  • SDRplay API runtime is required.
  • SDRplay hardware is required.
  • SDRplay API must be installed separately.

Official SDRplay website:

https://www.sdrplay.com/

Downloads:

https://www.sdrplay.com/downloads/

API Documentation:

https://www.sdrplay.com/docs/

Dependency relationship:

RSPdx-R2 hardware
↓
SDRplay API runtime
↓
rspdx_r2 Python wrapper
↓
capture / realtime streaming / export

This repository contains original Python code only.

The following are NOT redistributed:

  • SDRplay API binaries
  • SDRplay API headers
  • SDRplay SDK packages
  • SDRplay installers
  • SDRplay trademarks

Users must obtain SDRplay API directly from SDRplay Ltd.

macOS example:

  1. Install SDRplay API from:

    https://www.sdrplay.com/downloads/

  2. Verify installation:

    find /Library/SDRplayAPI \
      -iname "*license*" \
      -o -iname "*readme*"
  3. Verify API runtime:

    python examples/api_version.py
  4. Verify hardware detection:

    python examples/list_devices.py

Scope

The first implementation should provide a small, safe, testable Python package that can:

  1. Load the SDRplay native API library.
  2. Open and close the API.
  3. Check the installed API version.
  4. Enumerate attached SDRplay devices.
  5. Select an RSPdx-R2 device.
  6. Read device parameters.
  7. Configure basic tuner settings.
  8. Start a short IQ stream capture.
  9. Stop streaming and release all API resources reliably.

Initial CLI Examples

The first generated version should include these example scripts:

  • examples/api_version.py
    • Prints the loaded SDRplay API version.
  • examples/list_devices.py
    • Lists visible SDRplay devices and identifies RSPdx-R2 if present.
  • examples/capture_iq.py
    • Captures a short IQ sample file with explicit frequency, sample rate, and duration.

Example target usage:

python examples/api_version.py
python examples/list_devices.py
python examples/capture_iq.py --center-hz 100000000 --sample-rate 2000000 --duration-sec 1 --out capture.npy

Safety Defaults

  • Do not perform OS-level configuration changes.
  • Do not install, update, remove, start, stop, or restart system services.
  • Do not use sudo in generated code or examples.
  • Bias-T must default to disabled.
  • HDR mode must default to disabled unless explicitly requested.
  • Device resources must be released on normal exit, exceptions, and Ctrl-C.
  • Streaming callbacks must avoid heavy work and should only move samples into a queue or ring buffer.

Expected Package Layout

rspdx_r2/
  __init__.py
  loader.py
  errors.py
  constants.py
  structs.py
  config.py
  device.py
  stream.py
examples/
  api_version.py
  list_devices.py
  capture_iq.py
tests/
  test_config_validation.py
  test_error_mapping.py

See SPEC.md for the detailed implementation specification.

AI-CW-Decoder Export Format

examples/capture_iq.py exports RSPdx-R2 IQ captures as a small file set:

  • capture.npy: NumPy complex64 IQ samples.
  • capture.raw: raw interleaved signed 16-bit IQ samples.
  • capture.json: metadata and file references for the capture.

capture.json is the integration entry point. AI-CW-Decoder should receive the metadata JSON path, validate it, and then load the referenced IQ data.

AI-CW-Decoder should prefer npy_path when it is present and the metadata declares complex64_npy in export_format. Only read raw_path when npy_path is missing or not exported.

Metadata Schema

Required keys:

  • schema_version: must be "rspdx-r2-capture-v1".
  • source: must be "rspdx-r2".
  • export_format: list of exported data formats, for example ["complex64_npy", "interleaved_int16_iq"].
  • center_hz: RF center frequency in Hz.
  • sample_rate_hz: sample rate in Hz.
  • duration_sec: requested capture duration in seconds.
  • antenna: selected antenna, normally "A", "B", or "C".
  • sample_count: number of complex IQ samples.
  • dtype: expected NumPy dtype for the preferred .npy export.
  • npy_path: path to the .npy export, or null.
  • raw_path: path to the .raw export, or null.
  • raw_format: raw export format, currently "interleaved_int16_iq".
  • iq_order: raw IQ order, currently "I,Q".
  • created_by: producer identifier.

Relative npy_path and raw_path values are resolved relative to the parent directory of capture.json.

Format Details

complex64_npy:

  • Read with np.load(path).
  • dtype must be complex64.
  • shape must be (sample_count,).

interleaved_int16_iq:

  • Read with np.fromfile(path, dtype=np.int16).
  • Layout is I0,Q0,I1,Q1,....
  • Element count must be sample_count * 2.
  • Restore to complex64 with:
    • real = raw[0::2]
    • imag = raw[1::2]

AI-CW-Decoder Loading Pseudocode

metadata = json.load(open(metadata_json))

base_dir = Path(metadata_json).resolve().parent
npy_path = base_dir / metadata["npy_path"] if metadata["npy_path"] else None
raw_path = base_dir / metadata["raw_path"] if metadata["raw_path"] else None

if "complex64_npy" in metadata["export_format"] and npy_path:
    iq = np.load(npy_path).astype(np.complex64)
else:
    raw = np.fromfile(raw_path, dtype=np.int16)
    iq = raw[0::2].astype(np.float32) + 1j * raw[1::2].astype(np.float32)
    iq = iq.astype(np.complex64)

AI-CW-Decoder Integration

AI-CW-Decoder should read capture.json as the canonical entry point.

AI-CW-Decoder users must install SDRplay API separately. This repository does not vendor the SDRplay SDK. capture.json remains the canonical integration point for saved IQ exports.

Recommended loading order:

  1. Load capture.json.
  2. If "complex64_npy" is in export_format, use npy_path.
  3. Otherwise, reconstruct IQ from raw_path.
  4. Validate:
    • schema_version
    • source
    • sample_count
    • raw_format
    • iq_order
  5. Feed the resulting IQ ndarray into the decoder.

Realtime API Example

AI-CW-Decoder realtime integration can consume iter_iq_chunks() instead of reading saved capture files.

with RspDxR2Device() as dev:
    dev.open()
    dev.select_rspdx_r2()
    dev.configure(config)

    for chunk in dev.iter_iq_chunks(
        duration_sec=3,
        chunk_samples=8192,
    ):
        process(chunk)

Licensing Notes

  • Repository code is licensed under the MIT License.
  • The SDRplay SDK/API is a separate proprietary dependency.
  • Users must install SDRplay API independently from SDRplay Ltd.
  • This repository contains original Python wrapper code only.
  • SDRplay API binaries, libraries, headers, installers, SDK packages, and trademarks belong to SDRplay Ltd and are not redistributed here.

Publishing Self-Check

Before publishing or cutting a release, verify generated captures are ignored:

git check-ignore -v \
capture.raw \
capture.sigmf-meta \
capture.json

Verify proprietary SDRplay artifacts are not tracked:

git ls-files | grep -Ei \
"sdrplay|\.dylib$|\.so$|sdk|installer|header"

Expected result: no SDRplay API binary, header, SDK archive, or installer file is tracked in this repository.

About

Python ctypes wrapper for SDRplay RSPdx-R2 with IQ capture, realtime streaming, SigMF export, and AI-CW-Decoder integration support.

Topics

Resources

License

Contributing

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages