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
rowsconsecutive OUTPUT units touches each codeword AT MOST ONCE; - two originally adjacent INPUT units land
rowsapart 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:
inrows * cols * unitfloats of interleaved input.outWhere to write them; must not overlapin.rowsInterleaving depth, as given to the forward transform.colsBlock span, as given to the forward transform.unitFloats per interleaved unit.
function dp_deinterleave_index¶
Where output unit o came from — the inverse permutation.
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:
oOutput unit index, belowrows * cols.rowsInterleaving depth, as given to the forward transform.colsBlock 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:
inrows * cols * unitbytes of interleaved input.outWhere to write them; must not overlapin.rowsInterleaving depth, as given to the forward transform.colsBlock span, as given to the forward transform.unitBytes per interleaved unit.
function dp_interleave_block_units¶
Units in one block — rows * cols .
The length every call below consumes and produces, in UNITS. Multiply by the unit size for elements.
Parameters:
rowsInterleaving depth.colsBlock 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:
inrows * cols * unitfloats of input.outWhere to write them; must not overlapin.rowsInterleaving depth.colsBlock span.unitFloats per interleaved unit.
function dp_interleave_index¶
Where input unit i lands in the interleaved output.
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:
iInput unit index, belowrows * cols.rowsInterleaving depth.colsBlock 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:
inrows * cols * unit_bytesbytes of input.outWhere to write the same number of bytes.rowsInterleaving depth.colsBlock span.unit_bytesBytes 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:
inrows * cols * unitbytes of input.outWhere to write them; must not overlapin.rowsInterleaving depth.colsBlock span.unitBytes per interleaved unit.
The documentation for this class was generated from the following file native/inc/dp_interleave.h