code_rs/coding/
cyclic.rs

1//! Encoding and decoding of the (16, 8, 5) shortened cyclic code described by P25.
2//!
3//! The key information that this code is shortened from a (17, 8, 5) code came from
4//! "Standard APCO25 Physical Layer of the Radio Transmission Chain", Simon, 2014.
5
6use cai_cyclic;
7
8/// Encode the given 8 data bits into a 16-bit codeword.
9pub fn encode(data: u8) -> u16 {
10    cai_cyclic::encode(data as u16) as u16
11}
12
13/// Try to decode the given 16-bit word to the nearest codeword, correcting up to 2
14/// errors.
15///
16/// If decoding was successful, return `Some((data, err))`, where `data` is the 8 data
17/// bits and `err` is the number of corrected bits. Otherwise, return `None` to indicate
18/// an unrecoverable error.
19pub fn decode(word: u16) -> Option<(u8, usize)> {
20    cai_cyclic::decode(word as u32).and_then(|(word, err)| {
21        if word >> 8 == 0 {
22            Some((word as u8, err))
23        } else {
24            None
25        }
26    })
27}
28
29#[cfg(test)]
30mod test {
31    use super::*;
32
33    #[test]
34    fn test_decode() {
35        let w = 0b10101011;
36        let e = encode(w);
37        assert_eq!(e, 0b1010_1011_0111_1011);
38
39        assert_eq!(Some((w, 0)), decode(e ^ 0b0000000000000000));
40        assert_eq!(Some((w, 2)), decode(e ^ 0b1000000000000001));
41        assert_eq!(Some((w, 1)), decode(e ^ 0b0001000000000000));
42        assert_eq!(Some((w, 2)), decode(e ^ 0b0011000000000000));
43
44        assert_eq!(Some((w, 1)), decode(e ^ 0b1000000000000000));
45        assert_eq!(Some((w, 1)), decode(e ^ 0b0100000000000000));
46        assert_eq!(Some((w, 2)), decode(e ^ 0b0010000000000001));
47        assert_eq!(Some((w, 2)), decode(e ^ 0b0001000000000010));
48        assert_eq!(Some((w, 2)), decode(e ^ 0b0000100000000100));
49        assert_eq!(Some((w, 2)), decode(e ^ 0b0000010000001000));
50        assert_eq!(Some((w, 2)), decode(e ^ 0b0000001000010000));
51        assert_eq!(Some((w, 2)), decode(e ^ 0b0000000100100000));
52        assert_eq!(Some((w, 2)), decode(e ^ 0b0000000011000000));
53        assert_eq!(Some((w, 2)), decode(e ^ 0b0000000001010000));
54        assert_eq!(Some((w, 2)), decode(e ^ 0b0000000010001000));
55        assert_eq!(Some((w, 2)), decode(e ^ 0b0000000100000100));
56        assert_eq!(Some((w, 2)), decode(e ^ 0b0000001000000010));
57        assert_eq!(Some((w, 2)), decode(e ^ 0b0000010000000001));
58        assert_eq!(Some((w, 1)), decode(e ^ 0b0000100000000000));
59        assert_eq!(Some((w, 1)), decode(e ^ 0b0001000000000000));
60        assert_eq!(Some((w, 2)), decode(e ^ 0b0010000000000001));
61        assert_eq!(Some((w, 2)), decode(e ^ 0b0100000000000100));
62        assert_eq!(Some((w, 2)), decode(e ^ 0b1000000000001000));
63
64        for w in 0..=(!0u8) {
65            assert_eq!(decode(encode(w as u8)), Some((w, 0)));
66        }
67    }
68}