1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
// Copyright (c) 2026 G & R Associates LLC
// SPDX-License-Identifier: MIT OR Apache-2.0
// CRC-14 for FT8/FT4, polynomial 0x2757.
//
// Algorithm: straight-line bit-by-bit shift register, MSB first.
// Ported from ft8_lib (kgoba, MIT licence).
//
// ── Polynomial note ────────────────────────────────────────────────────────
// Several secondary sources quote 0x6757 — that is wrong. The correct value
// from the ft8_lib reference implementation (constants.h) is 0x2757.
//
// ── CRC domain ─────────────────────────────────────────────────────────────
// The CRC is computed over the 77-bit payload zero-extended to 82 bits (i.e.
// 5 zero bits appended), NOT over the full 91-bit a91 block. In other words
// the 14-bit CRC field itself is never fed back into the CRC calculation.
// Concretely: call ft8_crc14(buf, 82) where buf has the 77 payload bits in
// positions 0-76 and zeros in positions 77-81. The CRC result occupies
// positions 77-90 of the a91 layout.
//
// ── Byte 9 slack bits ──────────────────────────────────────────────────────
// The 77-bit payload is packed MSB-first into 10 bytes. Bit 76 (last payload
// bit) lands at byte 9 bit 3 (counting from MSB = bit 7). Bits 77-79 (byte 9
// bits 2-0) are unused slack and must be zero. Mask: payload[9] &= 0xF8.
// For a "77 bits all-ones" payload, byte 9 = 0xF8 (not 0xFF or 0xFE).
//
// ── a91 layout (12 bytes = 96 bits) ────────────────────────────────────────
// bits 0-76: 77-bit payload
// bits 77-90: 14-bit CRC (stored as: a91[9] bits 2-0, a91[10], a91[11] bits 7-5)
// bits 91-95: unused (zero)
const POLY: u16 = 0x2757;
const WIDTH: u32 = 14;
const TOPBIT: u16 = 1 << ;
/// Compute CRC-14 over the first `num_bits` bits of `message` (MSB first).
/// Append a 14-bit CRC to 77 bits of payload, producing a 91-bit `a91` block.
///
/// Layout: bits 0–76 = payload, bits 77–90 = CRC (MSB first).
/// The CRC is computed over the 77-bit payload zero-padded to 82 bits
/// (i.e., 96 - 14 = 82 bits processed).
/// Extract the 14-bit CRC from bits 77..90 of a packed 91-bit `a91` block.
// ── Generic frame CRCs ─────────────────────────────────────────────────────
//
// General-purpose CRCs over arbitrary byte slices, used by the OFDM frame
// layer (header/payload integrity). Distinct from `ft8_crc14` above, which is
// tailored to FT8's 77-bit-payload / 91-bit-block layout.
/// CRC-16/CCITT-FALSE over `bytes`.
///
/// Parameters: polynomial `0x1021`, initial value `0xFFFF`, non-reflected
/// input/output, no final XOR (the "CCITT-FALSE" variant). Known-answer:
/// `crc16(b"123456789") == 0x29B1`.
/// CRC-32/ISO-HDLC over `bytes` — the ubiquitous CRC used by Ethernet, zlib,
/// gzip, and PNG.
///
/// Parameters: polynomial `0x04C11DB7` (reflected form `0xEDB88320`), reflected
/// input/output, initial value `0xFFFFFFFF`, final XOR `0xFFFFFFFF`.
/// Known-answer: `crc32(b"123456789") == 0xCBF43926`.