File frame_meter_core.h¶
FileList > frame_meter > frame_meter_core.h
Go to the source code of this file
Frame outcomes accumulated across a record: FER, and sync detection. More...
#include "ber/ber_core.h"#include "dp_state.h"#include <stddef.h>#include <stdint.h>#include "detection/detection_core.h"#include "ber_meter/ber_meter_core.h"
Classes¶
| Type | Name |
|---|---|
| struct | frame_meter_state_t Frame-outcome accumulator. Allocate with frame_meter_create() . |
Public Functions¶
| Type | Name |
|---|---|
| void | frame_meter_add (frame_meter_state_t * state, int sync_ok, int crc) Record one frame's outcome. |
| frame_meter_state_t * | frame_meter_create (size_t target_errors, double conf) Create an accumulator. |
| void | frame_meter_destroy (frame_meter_state_t * state) Release the meter. |
| ber_interval_t | frame_meter_fer (const frame_meter_state_t * state) Frame error rate with its exact interval. |
| size_t | frame_meter_get_crc_passed (const frame_meter_state_t * state) Frames whose CRC checked. |
| int | frame_meter_get_enough (const frame_meter_state_t * state) Non-zero once target_errors frame errors have accumulated. |
| size_t | frame_meter_get_errors (const frame_meter_state_t * state) Frames not delivered: no sync, or a failed CRC. |
| size_t | frame_meter_get_frames (const frame_meter_state_t * state) Frames attempted. |
| void | frame_meter_get_state (const frame_meter_state_t * state, void * blob) Serialize the running counters into blob . |
| size_t | frame_meter_get_sync_detected (const frame_meter_state_t * state) Frames whose sync word was detected. |
| void | frame_meter_reset (frame_meter_state_t * state) Clear every counter; the configuration is untouched. |
| int | frame_meter_set_state (frame_meter_state_t * state, const void * blob) Restore; DP_OK, or DP_ERR_INVALID if the blob is rejected. |
| size_t | frame_meter_state_bytes (const frame_meter_state_t * state) Serialized-state byte size. |
| ber_interval_t | frame_meter_sync_miss (const frame_meter_state_t * state) Sync MISS rate with its exact interval. |
Macros¶
| Type | Name |
|---|---|
| define | FRAME_METER_STATE_MAGIC [**DP\_FOURCC**](dp__state_8h.md#define-dp_fourcc) ('F', 'R', 'M', 'M') |
| define | FRAME_METER_STATE_VERSION 1u |
Detailed Description¶
The fourth metric, and the only one that needs NO TRUTH and still catches a false lock. ber_evm_db and snr_m2m4_db need no truth either, and a stationary-but-wrong constellation reads clean on both — measured across orders in test_mpsk_receiver_performance.py, with the penalty SHRINKING as M rises. BER sees it but needs truth and a trustworthy alignment. A CRC-checked frame needs no payload truth at all: it either checks or it does not, and a false lock fails it. That makes a frame error rate the one metric usable on a real capture that still detects the failure this receiver family is most prone to.
What a frame outcome is¶
Two independent things can go wrong, and collapsing them loses the diagnosis: the sync word may not be FOUND, or the frame may be found and fail its CRC. Both are frame errors — a frame you did not detect is a frame you did not deliver — but "the sync is too short at this Es/N0" and "the demodulator is making bit errors" are different repairs, so both counts come back separately.
A frame carrying no CRC (crc = -1, which is exactly what wfm_frame_crc_ok() returns for one) counts as delivered when its sync was detected. Counting it as an error instead would make every unprotected frame fail, which is a measurement of the frame format rather than the receiver.
The stopping rule is the ERROR count, and that is not decoration¶
ber_confidence() is the exact Gamma/chi-square interval for INVERSE BINOMIAL sampling — fix the errors, let the trial count fall out. Its relative standard error is 1/sqrt(r), a function of the error count ALONE, which is why a run stopped on errors gives a consistent measurement and one stopped on a fixed count does not. This meter therefore uses the same rule as ber_meter, exposes the same enough read-back, and hands the same interval back. Reusing that interval under a fixed-frame-count stopping rule would be the wrong sampling model (that is binomial, and its exact interval is Clopper-Pearson), so the convention is stated here rather than left for a caller to assume.
See also: docs/design/rx-test.md section 2.5
Public Functions Documentation¶
function frame_meter_add¶
Record one frame's outcome.
Parameters:
statethe meter.sync_oknon-zero when the frame's sync word was detected. Pass the detector's own decision —ber_align_t::ok, orburst_demod's frame_offset validity — never a threshold applied afterwards to a statistic.crcwfm_frame_crc_ok()'s return, passed straight through: 1 pass, 0 fail, -1 the frame carries no CRC.
A frame counts as an error when its sync was not detected, or when it was and the CRC failed. With crc = -1 a detected frame counts as delivered, because nothing about it can be checked.
>>> from doppler.ber import FrameMeter
>>> met = FrameMeter(target_errors=10)
>>> met.add(1, 1) # found, and it checked
>>> met.add(1, 0) # found, and the CRC failed
>>> met.add(0, 0) # never found: still a frame you did not deliver
>>> met.add(1, -1) # found, no CRC: delivered but not CHECKED
>>> met.frames, met.sync_detected, met.crc_passed, met.errors
(4, 3, 1, 2)
function frame_meter_create¶
Create an accumulator.
Parameters:
target_errorsframe errors to accumulate beforeenough; 0 is taken as BER_TARGET_ERRORS.confconfidence level in (0, 1); 0 is taken as BER_CONF.
Returns:
the meter, or NULL if conf is outside (0, 1).
function frame_meter_destroy¶
Release the meter.
function frame_meter_fer¶
Frame error rate with its exact interval.
ber_confidence(errors, frames, conf) — the same interval ber_meter reports, which is generic over trials and therefore applies to frames unchanged. Assert on lo, never on p_hat.
Parameters:
statethe meter.
Returns:
the rate with its exact interval.
>>> from doppler.ber import FrameMeter
>>> met = FrameMeter(target_errors=4)
>>> for i in range(20):
... met.add(1, 0 if i % 5 == 0 else 1)
>>> met.enough
1
>>> fer = met.fer()
>>> round(fer.p_hat, 3), fer.lo < fer.p_hat < fer.hi
(0.158, True)
function frame_meter_get_crc_passed¶
Frames whose CRC checked.
function frame_meter_get_enough¶
Non-zero once target_errors frame errors have accumulated.
The stopping condition, so a caller loops records until the measurement has the precision it asked for rather than until a frame count someone guessed.
function frame_meter_get_errors¶
Frames not delivered: no sync, or a failed CRC.
function frame_meter_get_frames¶
Frames attempted.
function frame_meter_get_state¶
Serialize the running counters into blob .
function frame_meter_get_sync_detected¶
Frames whose sync word was detected.
function frame_meter_reset¶
Clear every counter; the configuration is untouched.
The target and the confidence level are what the caller asked for, so resetting the accumulation must not silently re-negotiate them. Use it between records, or to discard a run that turned out to be measuring the wrong thing.
Parameters:
statethe meter.
function frame_meter_set_state¶
Restore; DP_OK, or DP_ERR_INVALID if the blob is rejected.
function frame_meter_state_bytes¶
Serialized-state byte size.
function frame_meter_sync_miss¶
Sync MISS rate with its exact interval.
Reported as a miss rate rather than a detection rate so it is an ERROR rate like every other number here, and so the same interval applies without reinterpretation. This is what turns "is this sync word long
enough at this Es/N0" into a measurement — ber_align_detect() already returns margin_db and runner_db per attempt, and accumulating the decisions is what answers the question with a number.
Parameters:
statethe meter.
Returns:
the miss rate with its exact interval.
>>> from doppler.ber import FrameMeter
>>> met = FrameMeter()
>>> for i in range(50):
... met.add(0 if i % 10 == 0 else 1, 1)
>>> met.frames, met.sync_detected
(50, 45)
>>> miss = met.sync_miss()
>>> round(miss.p_hat, 3), miss.hi > miss.p_hat
(0.082, True)
Macro Definition Documentation¶
define FRAME_METER_STATE_MAGIC¶
define FRAME_METER_STATE_VERSION¶
The documentation for this class was generated from the following file native/inc/frame_meter/frame_meter_core.h