Skip to main content

Crate viterbi

Crate viterbi 

Source
Expand description

§viterbi — CCSDS convolutional encoder + block Viterbi (MLSE) decoder.

This crate is the inner code of the classic CCSDS concatenated coding scheme, designed to pair with an outer Reed–Solomon code via an interleaver:

TX:  data → [RS(255,223)] → [interleaver] → [conv. K=7] → CHANNEL
RX:  CHANNEL → [Viterbi] → [de-interleaver] → [RS decode] → data
               └── this crate

§Feature set (v0.2.x)

  • Hard-decision block encode/decode (HardHamming, CcsdsViterbiDecoder::decode_block) — the first-class CCSDS K = 7, R = 1/2 path.
  • Soft-decision decoding over quantized i8 LLRs (SoftLlr, CcsdsSoftDecoder) for the ≈ 2 dB coding gain, validated by a BER-vs-Eb/N0 sweep (see examples/ber_curve).
  • Rate-1/3 mother code (d_free = 14) via CodeParams::ccsds_r1_3 and the n-generic trellis.
  • Puncturing to rates 2/3, 3/4, 5/6, 7/8 as a separable wrapping layer over both mother codes (Puncturer / DePuncturer, puncture matrix as runtime data).
  • Generic constraint length K ≤ 9 via the const-generic state count (K = 7 stays first-class); preconfigured codes are discoverable through CodeProfile.

All new capability is additive: the released hard-decision R = 1/2, K = 7 public API and behaviour are unchanged. Streaming, concatenation, no_std/MCU, and SOVA remain for later minors.

§Design invariants

  • Pure Rust, no unsafe (forbided crate-wide via Cargo.toml lints and here).
  • Deterministic: same input ⇒ same output, bit-for-bit, on every platform.
  • No panic in the decode hot path; Result only at configuration boundaries.

§Examples

Encode a payload, then recover it with the Viterbi decoder (clean channel):

use viterbi::{CcsdsViterbiDecoder, CodeParams, ViterbiEncoder};

// Build the encoder and decoder from the first-class CCSDS profile.
let encoder = ViterbiEncoder::new(CodeParams::ccsds_r1_2()).unwrap();
let mut decoder = CcsdsViterbiDecoder::new(CodeParams::ccsds_r1_2(), 4096).unwrap();

let payload = b"hello, viterbi";
let coded = encoder.encode(payload).unwrap();
let decoded = decoder.decode_block(&coded).unwrap();

assert_eq!(&decoded.bytes, payload);

Re-exports§

pub use decoder::CcsdsSoftDecoder;
pub use decoder::CcsdsViterbiDecoder;
pub use decoder::ConfigError;
pub use decoder::DecodeError;
pub use decoder::ViterbiDecoder;
pub use encoder::EncodeError;
pub use encoder::ViterbiEncoder;
pub use metric::BranchMetric;
pub use metric::HardHamming;
pub use metric::SoftLlr;
pub use metric::HARD_ERASURE;
pub use metric::SOFT_MAX_SPREAD;
pub use packing::CodedBlock;
pub use packing::DecodedBlock;
pub use params::CodeParams;
pub use params::CodeProfile;
pub use params::ParamError;
pub use puncture::DePuncturer;
pub use puncture::PunctureError;
pub use puncture::PunctureMatrix;
pub use puncture::PunctureOrder;
pub use puncture::PuncturedRate;
pub use puncture::Puncturer;

Modules§

decoder
Hard-decision block Viterbi decoder (ACS + traceback).
encoder
Convolutional encoder with zero-tail termination (R1, R2).
metric
Branch-metric abstraction: hard-decision Hamming now, soft/erasure-ready (R7).
packing
MSB-first bit <-> byte packing and the block wrappers (R16). Sole owner of this conversion.
params
Convolutional code parameters and their validation (R8, R19).
puncture
Puncturing support: the puncture matrix as runtime data (RP1) plus its structural validation.

Constants§

K
Constraint length.
M
Memory (shift-register length) = K - 1.
MAX_SUPPORTED_INFO_BITS
Hard upper bound on max_info_bits (R18).
N
Output bits per input bit (rate 1/2).
STATES
Trellis states for the CCSDS profile = 2^M.