File conv_enc_core.h¶
FileList > conv_enc > conv_enc_core.h
Go to the source code of this file
The convolutional encoder, as a stateful object over conv .More...
#include "clib_common.h"#include "conv/conv_core.h"#include "dp_state.h"#include "jm_perf.h"
Classes¶
| Type | Name |
|---|---|
| struct | conv_enc_state_t A code and the register encoding it, together. |
Public Functions¶
| Type | Name |
|---|---|
| const conv_code_t * | conv_enc_code (const conv_enc_state_t * s) The code this encoder was built for. |
| conv_enc_state_t * | conv_enc_create (const uint32_t * poly, size_t poly_len, uint32_t k, uint32_t invert) Build an encoder for the code the polynomials describe. |
| conv_enc_state_t * | conv_enc_create_code (const conv_code_t * c) Build an encoder from a code already assembled. |
| void | conv_enc_destroy (conv_enc_state_t * state) Free an encoder. NULL is a no-op. |
| size_t | conv_enc_encode (conv_enc_state_t * state, const uint8_t * in, size_t n_in, uint8_t * out, size_t max_out) Encode information bits into channel symbols. |
| size_t | conv_enc_encode_max_out (const conv_enc_state_t * state, size_t n_in) Symbols conv_enc_encode writes for n_in input bits. |
| void | conv_enc_get_state (const conv_enc_state_t * s, void * blob) Serialize the register into blob . |
| void | conv_enc_reset (conv_enc_state_t * state) Return the register to all-zero, keeping the code. |
| int | conv_enc_set_state (conv_enc_state_t * s, const void * blob) Restore a register from blob . |
| size_t | conv_enc_state_bytes (const conv_enc_state_t * s) Bytes conv_enc_get_state writes: envelope, code identity and the register. |
Macros¶
| Type | Name |
|---|---|
| define | CONV_ENC_STATE_MAGIC [**DP\_FOURCC**](dp__state_8h.md#define-dp_fourcc) ('C', 'V', 'E', 'N')Blob type tag: "CVEN". |
| define | CONV_ENC_STATE_VERSION 1uBlob format version. |
Detailed Description¶
conv owns the CODE — the description, the trellis arithmetic, and the conv_encode kernel that turns bits into symbols. This owns the ENCODER built over one: a code and the shift register that must survive between calls, bound together so a caller cannot pair the wrong two.
It is not a second implementation. conv_enc_encode calls conv_encode, exactly as viterbi_decode's object calls its own kernel. Two encoders for one code family is how a rounding rule or an inversion comes to differ between them.
Why this exists at all¶
Viterbi accepts any rate-1/n code, and until this the library could produce symbols for exactly one of them — CCSDS's, and only inside a wfm_frame_desc_t, whose stage kinds bind to ccsds_tm_frame_ops and carry a depth rather than a polynomial. Nothing in doppler exposed an encode() at all (doppler#900). A decoder whose matching encoder cannot be reached is a decoder that can only be tested against itself, which is the failure conv's own tests are built to refuse.
The register is the whole state, and it is load-bearing¶
3.3.2's shape, in the general case: the output is one uninterrupted symbol sequence, so encoding a long record in chunks must carry the k-1 previous inputs across every boundary. An encoder that restarted per chunk emits k-1 wrong symbols at each one — self-consistent, decodable by a receiver of one's own construction, and not what any standard says. That is why the register lives here rather than being passed in, and why this object serializes.
Bit convention follows conv and the rest of the coding chain: unpacked bits, one per byte in the LSB, in and out.
See also: conv/conv_core.h for the code description and the kernel.
See also: viterbi/viterbi_core.h for the other direction.
const uint32_t poly[2] = { 0171u, 0133u };
conv_enc_state_t *e = conv_enc_create (poly, 2, 7u, 0x2u); // CCSDS
uint8_t sym[2 * N];
const size_t n = conv_enc_encode (e, bits, N, sym, sizeof sym);
conv_enc_destroy (e);
Public Functions Documentation¶
function conv_enc_code¶
The code this encoder was built for.
function conv_enc_create¶
Build an encoder for the code the polynomials describe.
conv_enc_state_t * conv_enc_create (
const uint32_t * poly,
size_t poly_len,
uint32_t k,
uint32_t invert
)
The array IS the code: its length gives the number of outputs per input bit, so [0o171, 0o133] is a rate-1/2 code and a three-element array is rate 1/3. k is the constraint length, which fixes the register width at k - 1.
invert is a mask over the outputs, and it is not decoration: CCSDS complements G2 and most codes complement nothing. An encoder built without it round-trips perfectly against a decoder built without it, and interoperates with nothing — which is why it is a parameter here rather than a property of any one standard's configuration.
>>> import numpy as np
>>> from doppler.coding import ConvEncoder
>>> e = ConvEncoder([0o171, 0o133], k=7, invert=0x2)
>>> e.encode(np.zeros(8, dtype=np.uint8)).size
16
Parameters:
polyGenerator polynomials, one per output. The array IS the code;poly_lengivesn.poly_lenNumber of polynomials, 1 toCONV_N_MAX.kConstraint length, 2 toCONV_K_MAX.invertBitjcomplements outputj.
Returns:
Heap-allocated state, or NULL if the code is unusable.
Note:
Caller must call conv_enc_destroy() when done.
function conv_enc_create_code¶
Build an encoder from a code already assembled.
The declared conv_enc_create takes the polynomials directly, because a struct pointer is not expressible in a manifest. Callers that already hold a conv_code_t — the CCSDS configuration, the validators — use this.
Parameters:
cThe code. Copied, so the caller's may be temporary.
Returns:
The encoder, or NULL if c is invalid.
function conv_enc_destroy¶
Free an encoder. NULL is a no-op.
Parameters:
stateMay be NULL.
function conv_enc_encode¶
Encode information bits into channel symbols.
size_t conv_enc_encode (
conv_enc_state_t * state,
const uint8_t * in,
size_t n_in,
uint8_t * out,
size_t max_out
)
The register carries across calls, so a long record may be fed in blocks and the symbol sequence is identical to one call — which is the property a standard fixes and a chunked encoder silently breaks.
Outputs are emitted in polynomial order per input bit: for [G1, G2], out[2i] is G1's symbol for input bit i and out[2i+1] is G2's.
Parameters:
stateThe encoder.inn_inunpacked input bits, one per byte.n_inNumber of input bits.outReceivesn_in * nunpacked symbols, one per byte.max_outCapacity ofout. Short is a refusal, not a truncation: half a codeword is not a shorter codeword.
Returns:
Symbols written, or 0 if max_out is too small — in which case out is untouched.
>>> import numpy as np
>>> from doppler.coding import ConvEncoder, Viterbi
>>> bits = np.array([1, 0, 1, 1, 0, 0, 1, 0] * 40, dtype=np.uint8)
>>> sym = ConvEncoder([0o171, 0o133], k=7).encode(bits)
>>> llr = np.where(sym, -8.0, 8.0).astype(np.float32)
>>> out = Viterbi([0o171, 0o133], k=7, depth=35).decode(llr)
>>> bool(np.array_equal(out, bits[: out.size]))
True
function conv_enc_encode_max_out¶
Symbols conv_enc_encode writes forn_in input bits.
Exactly n_in * n — a convolutional code has no fill and no latency on the encode side, which is the asymmetry with viterbi_decode_max_out, where the traceback still owes bits at the start of a stream.
Parameters:
stateThe encoder.n_inNumber of input bits.
Returns:
Symbols that call will write.
function conv_enc_get_state¶
Serialize the register into blob .
Parameters:
sThe encoder.blobAt least conv_enc_state_bytes bytes.
function conv_enc_reset¶
Return the register to all-zero, keeping the code.
The boundary between two independent records, not a reconfiguration. The next encode starts from the same state a freshly created encoder is in, which is what makes a reset stream byte-identical to a fresh one.
Parameters:
stateMust be non-NULL.
>>> import numpy as np
>>> from doppler.coding import ConvEncoder
>>> e = ConvEncoder([0o171, 0o133], k=7)
>>> e.reset()
function conv_enc_set_state¶
Restore a register from blob .
The code identity travels in the blob and is CHECKED rather than restored: create() already fixed the code, and a blob from a different one describes a register that means something else. Refusing is the only answer that cannot silently produce a stream no decoder matches.
Parameters:
sThe encoder.blobA blob from conv_enc_get_state.
Returns:
DP_OK, or DP_ERR_INVALID for a blob that is not this encoder's.
function conv_enc_state_bytes¶
Bytes conv_enc_get_state writes: envelope, code identity and the register.
A constant for this object, unlike the decoder's, whose ring is sized from the configuration.
Macro Definition Documentation¶
define CONV_ENC_STATE_MAGIC¶
Blob type tag: "CVEN".
define CONV_ENC_STATE_VERSION¶
Blob format version.
The documentation for this class was generated from the following file native/inc/conv_enc/conv_enc_core.h