Bind the SDR link-quality metrics — the measurement layer the whole
mixed-precision SDR study reports against.
Upstream source: include/sw/dsp/sdr/metrics.hpp (closes upstream #97).
Upstream tests: tests/test_sdr_metrics.cpp.
Surface
Result structs: EvmResult, BerResult, IqImbalance.
Free functions:
evm(reference, measured) -> EvmResult
mer_db(reference, measured) -> double
ber(transmitted, received) -> BerResult
theoretical_ber_awgn(Modulation, ebn0_db) -> double
iq_imbalance(reference, measured) -> IqImbalance
q_function(x) -> double
Binding notes
- The templated ones are on
typename Complex, not DspField — they are
measurement code and run in double. No dtype= on these. That is the
same reasoning that makes signal generators reference-precision: a metric
that quantized itself would confound the thing it is measuring.
evm, mer_db and iq_imbalance take pairs of complex spans. This is the
heaviest consumer of the inbound complex-array convention — whatever the
foundations issue decides, these four signatures are where it shows.
ber takes std::span<const std::uint8_t> bit vectors; same uint8 ndarray
typedef needed by the constellation issue.
theoretical_ber_awgn needs the Modulation enum bound by the constellation
issue. If metrics lands first, bind the enum here instead — but bind it
exactly once.
- Result structs get
def_ro properties. They are plain scalar aggregates, so
the take_ownership rule does not bite here.
require_paired throws on length mismatch upstream; confirm the exception
surfaces as a Python ValueError and test it.
Depends on
Foundations issue (complex array marshalling); Modulation from the
constellation issue.
Deliverables
Part of the SDR binding epic #130.
Bind the SDR link-quality metrics — the measurement layer the whole
mixed-precision SDR study reports against.
Upstream source:
include/sw/dsp/sdr/metrics.hpp(closes upstream #97).Upstream tests:
tests/test_sdr_metrics.cpp.Surface
Result structs:
EvmResult,BerResult,IqImbalance.Free functions:
evm(reference, measured)->EvmResultmer_db(reference, measured)->doubleber(transmitted, received)->BerResulttheoretical_ber_awgn(Modulation, ebn0_db)->doubleiq_imbalance(reference, measured)->IqImbalanceq_function(x)->doubleBinding notes
typename Complex, notDspField— they aremeasurement code and run in double. No
dtype=on these. That is thesame reasoning that makes signal generators reference-precision: a metric
that quantized itself would confound the thing it is measuring.
evm,mer_dbandiq_imbalancetake pairs of complex spans. This is theheaviest consumer of the inbound complex-array convention — whatever the
foundations issue decides, these four signatures are where it shows.
bertakesstd::span<const std::uint8_t>bit vectors; sameuint8ndarraytypedef needed by the constellation issue.
theoretical_ber_awgnneeds theModulationenum bound by the constellationissue. If metrics lands first, bind the enum here instead — but bind it
exactly once.
def_roproperties. They are plain scalar aggregates, sothe
take_ownershiprule does not bite here.require_pairedthrows on length mismatch upstream; confirm the exceptionsurfaces as a Python
ValueErrorand test it.Depends on
Foundations issue (complex array marshalling);
Modulationfrom theconstellation issue.
Deliverables
src/sdr_bindings.cpp.python/mpdsp/__init__.py.tests/test_sdr_metrics.py, including a check that measured BER trackstheoretical_ber_awgnwithin a tolerance that scales with the errorcount (upstream hit exactly this flake — see
787cc37).scripts/build_api_ref.pytables updated,docs/api_reference.mdregenerated.
Part of the SDR binding epic #130.