dcc_rs/packets/
mod.rs

1// This Source Code Form is subject to the terms of the Mozilla Public
2// License, v. 2.0. If a copy of the MPL was not distributed with this
3// file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
5//! Modules containing packet definitions
6
7pub mod baseline;
8pub mod extended;
9pub mod service_mode;
10
11pub use baseline::*;
12pub use extended::*;
13pub use service_mode::*;
14
15use crate::Error;
16use bitvec::prelude::*;
17
18/// Convenient Result wrapper
19pub type Result<T> = core::result::Result<T, Error>;
20
21struct Preamble(BitArr!(for 14, in u8, Msb0));
22
23const MAX_BITS: usize = 15 + 4 * 9 + 1;
24/// Buffer long enough to serialise any common DCC packet into
25pub type SerialiseBuffer = BitArr!(for MAX_BITS, in u8, Msb0);
26
27/// Method used to perform serialisations. Should be less error-prone
28/// than all of the manual bit offsets we implemented in baseline.
29fn serialise(data: &[u8], buf: &mut SerialiseBuffer) -> Result<usize> {
30    // check that the provided data will fit into the buffer
31    let required_bits = 15 + data.len() * 9 + 1;
32    if required_bits > MAX_BITS {
33        return Err(Error::TooLong);
34    }
35
36    buf[0..16].copy_from_bitslice([0xff, 0xfe].view_bits::<Msb0>()); // preamble
37
38    let mut pos: usize = 15;
39    for byte in data {
40        buf.set(pos, false); // start bit
41        pos += 1;
42        buf[pos..pos + 8].copy_from_bitslice([*byte].view_bits::<Msb0>());
43        pos += 8;
44    }
45
46    buf.set(pos, true); // stop bit
47    pos += 1;
48
49    Ok(pos)
50}
51
52#[cfg(test)]
53mod test {
54    use super::*;
55
56    pub fn print_chunks(buf: &SerialiseBuffer, limit: usize) {
57        println!("Preamble: {}", &buf[..15]);
58
59        let mut offset = 15;
60        while offset < limit - 1 {
61            println!(
62                "[{}] Chunk: {}-{:08b}",
63                offset,
64                buf[offset] as u8,
65                &buf[offset + 1..offset + 9]
66            );
67            offset += 9;
68        }
69        println!("Stop bit: {}", buf[offset] as u8);
70    }
71}