Skip to content

Bind sdr::Constellation — QAM/PSK mapper and demapper #119

Description

@Ravenwater

Bind sw::dsp::sdr::Constellation and its free helpers — the symbol mapper
and demapper at the head of the SDR chain.

Upstream source: include/sw/dsp/sdr/constellation.hpp (closes upstream #95).
Upstream tests: tests/test_sdr_constellation.cpp.

Surface

enum class Modulation { bpsk, qpsk, psk8, qam16, qam64, qam256 } plus
to_string.

Free functions:

  • bits_per_symbol(Modulation) -> 1, 2, 3, 4, 6, 8
  • modulation_order(Modulation) -> 2^bits
  • is_square_qam(Modulation)
  • binary_to_gray(std::size_t), gray_to_binary(std::size_t, nbits)

Constellation<T>:

  • symbol(index), index_of(bits), bits_of(index, out)
  • map(std::span<const std::uint8_t> bits) -> symbol
  • demap_hard(symbol) -> index, demap_hard_bits(symbol, out)
  • demap_llr(symbol, noise_variance, out) — exact
  • demap_llr_maxlog(symbol, noise_variance, out) — max-log approximation
  • average_power(), order()

Binding notes

  • Modulation should be a proper nb::enum_, not a string key — it is a
    signal-structure parameter, not an arithmetic config, and it recurs in
    metrics.hpp (theoretical_ber_awgn) and analysis/sdr_precision.hpp
    (SdrLinkConfig). Bind it once here and reuse.
  • std::span<const std::uint8_t> bit vectors map to uint8 ndarrays. This is
    the first non-float64 array type at the boundary in this repo — the
    np_f64_ro typedefs in src/_binding_helpers.hpp need a uint8
    counterpart with the same c_contig copy-on-noncontiguous behaviour.
  • The LLR outputs are written into caller-provided std::span<T>. Bindings
    should allocate and return instead, via make_f64_array — and per
    src/BINDING_PATTERNS.md, any property returning a capsule-owned ndarray
    needs explicit nb::rv_policy::take_ownership.
  • Add block-level convenience wrappers (map/demap a whole symbol vector) rather
    than forcing per-symbol Python loops. A 2000-symbol link at one Python call
    per symbol is not usable.
  • Constellation<T> is single-scalar, so it dispatches on plain dtype=. It
    does not need the scalar-pair scheme.

Depends on

Foundations issue (complex marshalling — symbol_type is complex).

Deliverables

  • src/sdr_bindings.cpp created; forward-decl + call in src/bindings.cpp;
    source listed in nanobind_add_module(_core ...) in CMakeLists.txt.
  • Names exported by explicit name in python/mpdsp/__init__.py.
  • tests/test_sdr_constellation.py, mirroring the binding file 1:1.
  • Entries added to scripts/build_api_ref.py CATEGORIES/CLASSES and
    docs/api_reference.md regenerated (never hand-edited).

Part of the SDR binding epic #130.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions