const DOT15D4_FCS_POLY_REFLECTED: u16 = 0x8408;
pub(crate) fn dot15d4_fcs(bytes: &[u8]) -> u16 {
let mut crc: u16 = 0x0000;
for &byte in bytes {
crc ^= u16::from(byte);
for _ in 0..8 {
if crc & 1 != 0 {
crc = (crc >> 1) ^ DOT15D4_FCS_POLY_REFLECTED;
} else {
crc >>= 1;
}
}
}
crc
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn dot15d4_fcs_ack_frame_matches_reference() {
let mhr_and_payload = [0x02u8, 0x00, 0x53];
assert_eq!(dot15d4_fcs(&mhr_and_payload), 0xD5A6);
}
#[test]
fn dot15d4_fcs_data_header_matches_reference() {
let mhr = [0x41u8, 0x88, 0x01, 0xFF, 0xFF, 0xFF, 0xFF];
assert_eq!(dot15d4_fcs(&mhr), 0x84F4);
}
#[test]
fn dot15d4_fcs_empty_input_is_zero() {
assert_eq!(dot15d4_fcs(&[]), 0x0000);
}
#[test]
fn dot15d4_fcs_appended_fcs_self_checks() {
let mhr_and_payload = [0x02u8, 0x00, 0x53];
let fcs = dot15d4_fcs(&mhr_and_payload);
let mut full = mhr_and_payload.to_vec();
full.extend_from_slice(&fcs.to_le_bytes());
assert_eq!(dot15d4_fcs(&full), 0x0000);
}
}