dvb_bbframe/crc.rs
1//! CRC-8 encoder per EN 302 755 Annex F / EN 302 307-1 §5.1.4.
2//!
3//! Polynomial: g(X) = (X⁵+X⁴+X³+X²+1)·(X²+X+1)·(X+1)
4//! = X⁸+X⁷+X⁶+X⁴+X²+1 = 0xD5
5
6/// CRC-8 polynomial (0xD5), MSB-first, no reflection.
7pub const CRC8_POLY: u8 = 0xD5;
8
9/// Standard CRC-8 initial register value (0x00).
10pub const CRC8_INIT: u8 = 0x00;
11
12/// Compute CRC-8 with the standard initial value (0x00).
13///
14/// There is no separate "HEM init": EN 302 755 §5.1.7 puts
15/// `crc8(header) XOR MODE` on the wire, so HEM (MODE=1) is the init-0 CRC
16/// XOR 1. (A previous revision modelled HEM as init=0xB5 — that value is
17/// init-0 propagated through exactly 9 zero bytes and only coincided for
18/// 9-byte inputs; do not reintroduce it.)
19#[inline]
20pub fn crc8(bytes: &[u8]) -> u8 {
21 let mut crc = CRC8_INIT;
22 for &byte in bytes {
23 crc ^= byte;
24 for _ in 0..8 {
25 if crc & 0x80 != 0 {
26 crc = (crc << 1) ^ CRC8_POLY;
27 } else {
28 crc <<= 1;
29 }
30 }
31 }
32 crc
33}
34
35#[cfg(test)]
36mod tests {
37 use super::*;
38
39 #[test]
40 fn crc8_of_all_zeros_is_init_value() {
41 assert_eq!(crc8(&[0x00; 9]), CRC8_INIT);
42 }
43
44 #[test]
45 fn crc8_known_dvb_t2_vector() {
46 // Rai T2-MI (12606V, ISI 5, PLP 0). Live capture: wire byte is 0x1F.
47 let hdr = [0xf8u8, 0x00, 0xa4, 0x28, 0xbc, 0xc8, 0xe2, 0x03, 0x50];
48 assert_eq!(crc8(&hdr), 0x1E);
49 // §5.1.7: wire byte = crc8 XOR MODE → 0x1E ^ 1 = 0x1F (HEM).
50 assert_eq!(crc8(&hdr) ^ 0x01, 0x1F);
51 }
52}