Skip to content

File dp_interleave.h

FileList > inc > dp_interleave.h

Go to the source code of this file

Block interleaving — the permutation, and nothing else. More...

  • #include <stddef.h>
  • #include <stdint.h>
  • #include <string.h>

Public Static Functions

Type Name
void dp_deinterleave_f32 (const float * in, float * out, size_t rows, size_t cols, size_t unit)
Undo dp_interleave_f32 — the soft-decision receive path.
size_t dp_deinterleave_index (size_t o, size_t rows, size_t cols)
Where output unit o came from — the inverse permutation.
void dp_deinterleave_u8 (const uint8_t * in, uint8_t * out, size_t rows, size_t cols, size_t unit)
Undo dp_interleave_u8 over a block of the same geometry.
size_t dp_interleave_block_units (size_t rows, size_t cols)
Units in one block — rows * cols .
void dp_interleave_f32 (const float * in, float * out, size_t rows, size_t cols, size_t unit)
Interleave one block of soft values.
size_t dp_interleave_index (size_t i, size_t rows, size_t cols)
Where input unit i lands in the interleaved output.
void dp_interleave_raw (const void * in, void * out, size_t rows, size_t cols, size_t unit_bytes)
Interleave one block of opaque fixed-size units.
void dp_interleave_u8 (const uint8_t * in, uint8_t * out, size_t rows, size_t cols, size_t unit)
Interleave one block of unpacked bits or octets.

Detailed Description

A block interleaver writes its input by ROWS into a rows x cols matrix and reads it back by COLUMNS. That is the whole transform. It carries no state, adds no redundancy and detects nothing; what it buys is that a burst of errors on the wire arrives at the decoder spread out.

The two numbers are a link budget, not a tuning pair. Write one CODEWORD per row, cols units long, rows of them:

  • a burst of up to rows consecutive OUTPUT units touches each codeword AT MOST ONCE;
  • two originally adjacent INPUT units land rows apart on the wire.

So rows is the longest burst fully spread and cols is the codeword length. An outer code correcting t units per codeword survives a burst of t * rows.

The invariant is one-per-CODEWORD, not a minimum index separation. Two burst positions either side of a column boundary can land as close as cols - 1 apart while still being in different codewords, which is what matters; a first draft of this header claimed the separation instead and test_dp_interleave.c refused it.

The UNIT is a parameter and not a detail. Interleaving octets is what spreads a burst across the codewords of a symbol-oriented code such as Reed-Solomon over GF(256); interleaving bits inside such a code spreads a burst WITHIN a symbol, which buys nothing, because the symbol is already wrong. Match the unit to the code the interleaver protects.

Not the CCSDS interleaver. ccsds_tm/rs.c also interleaves, and it is a different transform sharing a name: depth-I interleaving is intrinsic to the Reed-Solomon codeblock layout (131.0-B-6 4.4.1) and is fused into encode and decode, not a permutation applied afterwards. Neither can be written in terms of the other.

Not a convolutional (Forney) interleaver. That is a different structure with different latency and memory, and it is deliberately absent rather than pending — see doppler#1031.

Header-only, like dp_crc16.h and for the same reason: the frame stage kernel and the Interleaver object both need it, and neither should grow a link-line dependency for arithmetic.

Public Static Functions Documentation

function dp_deinterleave_f32

Undo dp_interleave_f32 — the soft-decision receive path.

static inline void dp_deinterleave_f32 (
    const float * in,
    float * out,
    size_t rows,
    size_t cols,
    size_t unit
) 

This is the one a receiver actually needs. dsss_burst_receiver's llrs span the whole frame, and an outer decoder wants them de-interleaved BEFORE it runs; hard-decision de-interleaving would throw away the confidence the soft output exists to carry.

Parameters:

  • in rows * cols * unit floats of interleaved input.
  • out Where to write them; must not overlap in.
  • rows Interleaving depth, as given to the forward transform.
  • cols Block span, as given to the forward transform.
  • unit Floats per interleaved unit.

function dp_deinterleave_index

Where output unit o came from — the inverse permutation.

static inline size_t dp_deinterleave_index (
    size_t o,
    size_t rows,
    size_t cols
) 

Identical to dp_interleave_index with rows and cols exchanged, which is a fact about the transform rather than a coincidence: reading a rows x cols matrix by columns is writing a cols x rows one by rows. It is why every function below undoes itself by swapping two arguments, and why a SQUARE block is its own inverse.

Parameters:

  • o Output unit index, below rows * cols.
  • rows Interleaving depth, as given to the forward transform.
  • cols Block span, as given to the forward transform.

Returns:

The input unit index it came from.


function dp_deinterleave_u8

Undo dp_interleave_u8 over a block of the same geometry.

static inline void dp_deinterleave_u8 (
    const uint8_t * in,
    uint8_t * out,
    size_t rows,
    size_t cols,
    size_t unit
) 

Parameters:

  • in rows * cols * unit bytes of interleaved input.
  • out Where to write them; must not overlap in.
  • rows Interleaving depth, as given to the forward transform.
  • cols Block span, as given to the forward transform.
  • unit Bytes per interleaved unit.

function dp_interleave_block_units

Units in one block — rows * cols .

static inline size_t dp_interleave_block_units (
    size_t rows,
    size_t cols
) 

The length every call below consumes and produces, in UNITS. Multiply by the unit size for elements.

Parameters:

  • rows Interleaving depth.
  • cols Block span.

Returns:

The block size in units.


function dp_interleave_f32

Interleave one block of soft values.

static inline void dp_interleave_f32 (
    const float * in,
    float * out,
    size_t rows,
    size_t cols,
    size_t unit
) 

Parameters:

  • in rows * cols * unit floats of input.
  • out Where to write them; must not overlap in.
  • rows Interleaving depth.
  • cols Block span.
  • unit Floats per interleaved unit.

function dp_interleave_index

Where input unit i lands in the interleaved output.

static inline size_t dp_interleave_index (
    size_t i,
    size_t rows,
    size_t cols
) 

Unit i sits at row i / cols, column i % cols of the write-by-rows matrix; reading by columns puts it at (i % cols) * rows + (i / cols).

Parameters:

  • i Input unit index, below rows * cols.
  • rows Interleaving depth.
  • cols Block span.

Returns:

The output unit index.


function dp_interleave_raw

Interleave one block of opaque fixed-size units.

static inline void dp_interleave_raw (
    const void * in,
    void * out,
    size_t rows,
    size_t cols,
    size_t unit_bytes
) 

The generic kernel the typed wrappers below call. in and out must not overlap: a block interleave is a transpose, so doing it in place needs cycle-following and is a different algorithm, not an option here.

Parameters:

  • in rows * cols * unit_bytes bytes of input.
  • out Where to write the same number of bytes.
  • rows Interleaving depth.
  • cols Block span.
  • unit_bytes Bytes per interleaved unit; 0 writes nothing.

function dp_interleave_u8

Interleave one block of unpacked bits or octets.

static inline void dp_interleave_u8 (
    const uint8_t * in,
    uint8_t * out,
    size_t rows,
    size_t cols,
    size_t unit
) 

The array form doppler's frame paths use: one bit per byte. unit is in BYTES of that array, so unit == 1 interleaves bits and unit == 8 interleaves octets of a bit-per-byte stream.

Parameters:

  • in rows * cols * unit bytes of input.
  • out Where to write them; must not overlap in.
  • rows Interleaving depth.
  • cols Block span.
  • unit Bytes per interleaved unit.


The documentation for this class was generated from the following file native/inc/dp_interleave.h