File dp_syncword.h¶
FileList > inc > dp_syncword.h
Go to the source code of this file
Finding a known bit pattern in an unpacked bit stream — the sync word search, and the arithmetic for choosing its threshold. More...
#include <math.h>#include "clib_common.h"#include <stddef.h>#include <stdint.h>
Classes¶
| Type | Name |
|---|---|
| struct | dp_syncword_hit_t Where a marker was found, and in which polarity. |
Public Static Functions¶
| Type | Name |
|---|---|
| int | dp_syncword_find (const uint8_t * bits, size_t n_bits, const uint8_t * marker, size_t n_marker, unsigned max_errors, dp_syncword_hit_t * hit) Find the first marker in a run of unpacked bits, either polarity. |
| int | dp_syncword_max_errors (size_t n_marker, size_t window_bits, double pfa) The largest tolerance whose false-frame rate over a search window still meets pfa . |
| double | dp_syncword_pfa (size_t n_marker, unsigned max_errors) Probability that ONE random offset false-hits an n_marker -bit marker at a tolerance ofmax_errors . |
Detailed Description¶
A frame synchroniser correlates a marker it knows against the bits it is handed, in both polarities, and reports the first offset close enough to accept. That is one kernel, and every framing that has a sync word wants it: CCSDS calls its 32-bit marker an ASM and ccsds_tm_asm_find is this function configured with 0x1ACFFC1D, exactly as CCSDS_TM_CONV configures conv_code_t. The standard picks a pattern; the search is not the standard's.
Header-only (like dp_crc16.h) so no component grows a link-line dependency for a kernel this size — a receiver correlating a marker should not link a Reed-Solomon encoder to do it.
Bit convention: unpacked bits, one per byte in the LSB, which is what wfm_frame_bits, dp_crc16_ccitt, ccsds_tm_randomise and the spreader already pass around.
Choosing @p max_errors — it is not a property of the marker¶
The threshold is the whole of the trade, and the number a caller needs is a function of how much stream they search, not of how long the marker is. A 32-bit marker invites "half of 32 is 16, so 8 sounds safe", and 8 finds the marker at its true offset only 58 % of the time on a stream with no channel errors at all — because each preceding offset is an independent chance to false-hit first, and the search reports the FIRST acceptable offset rather than the best one.
So the arithmetic ships beside the search. Per offset, a random window lands within t of an n -bit marker in one polarity or the other with
P_fa(n, t) = 2 * sum_{i <= t} C(n, i) / 2^n (dp_syncword_pfa)
and over W offsets tried ahead of the true marker the chance one of them wins the race is 1 - (1 - P_fa)^W. dp_syncword_max_errors inverts that: give it the window and the false-frame rate you will accept and it returns the largest threshold that holds.
Measured for the 32-bit CCSDS marker (doppler#897, and src/doppler/tests/validation/ccsds_tm/results.md §2.2–2.3): the measured false-alarm rate tracks the closed form above to within 20 % at every threshold where the count supports a rate, t <= 1 produced zero false markers in 2000000 random bits, and polarity was never once reported wrong in 155901 detections.
Public Static Functions Documentation¶
function dp_syncword_find¶
Find the first marker in a run of unpacked bits, either polarity.
static inline int dp_syncword_find (
const uint8_t * bits,
size_t n_bits,
const uint8_t * marker,
size_t n_marker,
unsigned max_errors,
dp_syncword_hit_t * hit
)
Correlates marker against every bit offset and against its complement, and reports the first offset whose Hamming distance is at most max_errors.
First rather than best, and the difference matters: a best-match search has to see the whole stream before it can answer, which a frame synchroniser reading a live capture cannot do. First-below-threshold is what is implementable in both settings, so it is what this promises — and it is why max_errors must be chosen against the search window, as the file comment sets out.
Parameters:
bitsUnpacked bits, one per byte.n_bitsNumber of bits.markerThe pattern to find, unpacked bits, one per byte.n_markerLength ofmarkerin bits.max_errorsLargest tolerated Hamming distance, in bits.hitReceives the location; untouched when nothing matched.
Returns:
Non-zero if a marker was found.
function dp_syncword_max_errors¶
The largest tolerance whose false-frame rate over a search window still meets pfa .
The counterpart of det_threshold for this detector, and the answer to the question the signature of dp_syncword_find cannot ask: a caller knows how much stream their synchroniser reads before the marker arrives, and that — not the marker length — is what sets the threshold.
Every offset ahead of the true marker is an independent chance to win the race, so P = 1 - (1 - P_fa(n, t))^W. P rises with t, so the largest t that holds is the most tolerant threshold that keeps the false-frame rate at or under pfa.
Parameters:
n_markerMarker length in bits.window_bitsOffsets tried AHEAD of the marker — the length of stream searched, not the length of the frame.pfaTolerated probability that the window produces a false frame.
Returns:
Tolerance in bits, or -1 when even an exact match (t = 0) exceeds pfa over that window.
function dp_syncword_pfa¶
Probability that ONE random offset false-hits an n_marker -bit marker at a tolerance ofmax_errors .
P_fa = 2 * sum_{i <= max_errors} C(n, i) / 2^n — the factor of two because dp_syncword_find searches the complement too, and a random window is as likely to land near one polarity as the other. The two events are disjoint while 2 * max_errors < n_marker; at and above that every window matches in one polarity or the other, and the result is 1.
This is the per-offset number. What a synchroniser actually cares about is the whole window it searches — see dp_syncword_max_errors, which is this function inverted through 1 - (1 - P_fa)^W.
The terms are summed in log space rather than as binomial coefficients, so a long marker (C(1030, 515) overflows a double) is no different from a short one.
Parameters:
n_markerMarker length in bits; 0 gives 0.max_errorsTolerance in bits.
Returns:
Probability in [0, 1].
The documentation for this class was generated from the following file native/inc/dp_syncword.h