pub fn reverse_bits(buf: &mut [u8]) {
for byte in buf {
*byte = byte.reverse_bits();
}
}
pub fn whiten(buf: &mut [u8], coefficient: u8) {
let mut coefficient = coefficient;
for byte in buf {
let mut result = *byte;
let mut mask = 1u8;
for _ in 0u8..8 {
if (coefficient & 1) == 1 {
coefficient ^= 0x88;
result ^= mask;
}
mask <<= 1;
coefficient >>= 1;
}
*byte = result;
}
}
pub fn crc24_ble(data: &[u8]) -> [u8; 3] {
let degree_polynomial: u32 = 0x65B;
let mut crc: u32 = 0x555555;
for byte in data {
let copy = *byte;
crc ^= (copy.reverse_bits() as u32) << 16;
for _ in 0u8..8 {
if (crc & 0x800000) > 0 {
crc = (crc << 1) ^ degree_polynomial;
} else {
crc <<= 1;
}
}
crc &= 0xFFFFFF;
}
let mut checksum = crc.to_be_bytes();
reverse_bits(&mut checksum);
let mut result = [0u8; 3];
result.copy_from_slice(&checksum[1..4]);
result
}
#[cfg(test)]
mod test {
use super::{crc24_ble, reverse_bits, whiten};
#[test]
fn reverse() {
let mut buf = [0u8; 11];
buf.copy_from_slice(b"Hello World");
reverse_bits(&mut buf);
let mut expected = [
0x12, 0xA6, 0x36, 0x36, 0xF6, 0x04, 0xEA, 0xF6, 0x4E, 0x36, 0x26,
];
assert_eq!(buf, expected);
reverse_bits(&mut buf);
expected.copy_from_slice(b"Hello World");
assert_eq!(buf, expected);
}
#[test]
fn whitening() {
let coefficient = (2 + 37) | 0x40;
let mut buf = [0u8; 11];
buf.copy_from_slice(b"Hello World");
whiten(&mut buf, coefficient);
let expected: [u8; 11] = [
0x57, 0x52, 0x26, 0x33, 0xEA, 0xD6, 0xCB, 0xF5, 0xB3, 0xBA, 0xA1,
];
assert_eq!(buf, expected);
whiten(&mut buf, coefficient);
let mut expected = [0u8; 11];
expected.copy_from_slice(b"Hello World");
assert_eq!(buf, expected);
}
#[test]
fn crc() {
let buffer = b"Hello World";
let checksum = crc24_ble(buffer);
assert_eq!(buffer, b"Hello World");
let expected = [0xB6u8, 0x8C, 0xB0];
assert_eq!(expected, checksum);
}
}