use crate::Error;
use bitvec::prelude::*;
pub type Result<T> = core::result::Result<T, Error>;
struct Preamble(BitArr!(for 14, in u8, Msb0));
pub type SerialiseBuffer = BitArr!(for 43, in u8, Msb0);
impl Default for Preamble {
fn default() -> Self {
Self(BitArray::from([0xff, 0xff]))
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "use-defmt", derive(defmt::Format))]
pub enum Direction {
Forward,
Backward,
}
impl Default for Direction {
fn default() -> Self {
Self::Forward
}
}
impl Direction {
pub fn toggle(&mut self) {
use Direction::*;
*self = match *self {
Forward => Backward,
Backward => Forward,
}
}
}
pub struct SpeedAndDirection {
address: u8,
instruction: u8,
ecc: u8,
}
impl SpeedAndDirection {
pub fn builder() -> SpeedAndDirectionBuilder {
SpeedAndDirectionBuilder::default()
}
pub fn serialise(&self, buf: &mut SerialiseBuffer) -> Result<usize> {
buf[0..16].copy_from_bitslice([0xff, 0xfe].view_bits::<Msb0>()); buf.set(15, false); buf[16..24].copy_from_bitslice([self.address].view_bits::<Msb0>());
buf.set(24, false); buf[25..33].copy_from_bitslice([self.instruction].view_bits::<Msb0>());
buf.set(33, false); buf[34..42].copy_from_bitslice([self.ecc].view_bits::<Msb0>());
buf.set(42, true);
Ok(43)
}
}
#[derive(Default)]
pub struct SpeedAndDirectionBuilder {
address: Option<u8>,
speed: Option<u8>,
e_stop: bool,
direction: Option<Direction>,
}
impl SpeedAndDirectionBuilder {
pub fn address(&mut self, address: u8) -> Result<&mut Self> {
if address == 0 || address > 0x7f {
Err(Error::InvalidAddress)
} else {
self.address = Some(address);
Ok(self)
}
}
pub fn speed(&mut self, speed: u8) -> Result<&mut Self> {
if speed > 28 {
Err(Error::InvalidSpeed)
} else {
self.speed = Some(speed);
Ok(self)
}
}
pub fn direction(&mut self, direction: Direction) -> &mut Self {
self.direction = Some(direction);
self
}
pub fn e_stop(&mut self, e_stop: bool) -> &mut Self {
self.e_stop = e_stop;
self
}
pub fn build(&mut self) -> SpeedAndDirection {
let address = self.address.unwrap_or(3);
let speed = match self.speed {
Some(0) | None => 0,
Some(speed) => speed + 3,
};
#[cfg(test)]
eprintln!("Speed is {speed} = {speed:08b}");
let mut instruction = 0b0100_0000; if let Direction::Forward = self.direction.unwrap_or_default() {
instruction |= 0b0010_0000;
}
if self.e_stop {
instruction |= 0x01;
} else {
instruction |= (speed >> 1) & 0x0f;
instruction |= (speed & 0x01) << 4;
}
let ecc = address ^ instruction;
SpeedAndDirection {
address,
instruction,
ecc,
}
}
}
pub struct Reset;
impl Reset {
pub fn serialise(&self, buf: &mut SerialiseBuffer) -> Result<usize> {
buf[0..16].copy_from_bitslice([0xff, 0xfe].view_bits::<Msb0>()); buf.set(15, false); buf[16..24].copy_from_bitslice([0x00].view_bits::<Msb0>());
buf.set(24, false); buf[25..33].copy_from_bitslice([0x00].view_bits::<Msb0>());
buf.set(33, false); buf[34..42].copy_from_bitslice([0x00].view_bits::<Msb0>());
buf.set(42, true);
Ok(43)
}
}
pub struct Idle;
impl Idle {
pub fn serialise(&self, buf: &mut SerialiseBuffer) -> Result<usize> {
buf[0..16].copy_from_bitslice([0xff, 0xfe].view_bits::<Msb0>()); buf.set(15, false); buf[16..24].copy_from_bitslice([0xff].view_bits::<Msb0>());
buf.set(24, false); buf[25..33].copy_from_bitslice([0x00].view_bits::<Msb0>());
buf.set(33, false); buf[34..42].copy_from_bitslice([0xff].view_bits::<Msb0>());
buf.set(42, true);
Ok(43)
}
}
pub struct BroadcastStop {
float: bool,
}
impl BroadcastStop {
pub fn immediate() -> Self {
Self { float: false }
}
pub fn float() -> Self {
Self { float: true }
}
pub fn serialise(&self, buf: &mut SerialiseBuffer) -> Result<usize> {
let instr = if self.float { 0b0101_0000 } else { 0b0100_0000 };
buf[0..16].copy_from_bitslice([0xff, 0xfe].view_bits::<Msb0>()); buf.set(15, false); buf[16..24].copy_from_bitslice([0x00].view_bits::<Msb0>());
buf.set(24, false); buf[25..33].copy_from_bitslice([instr].view_bits::<Msb0>());
buf.set(33, false); buf[34..42].copy_from_bitslice([instr].view_bits::<Msb0>());
buf.set(42, true);
Ok(43)
}
}
#[cfg(test)]
mod test {
use super::*;
fn display_serialise_buffer(buf: &SerialiseBuffer) {
println!("{buf:?}");
println!("ppppppppppppppp s aaaaaaaa s 01dvvvvv s cccccccc s");
println!(
"{} {} {} {} {} {} {} {}",
buf[..15]
.iter()
.map(|b| if *b { "1" } else { "0" })
.collect::<Vec<_>>()
.join(""),
if *buf.get(15).unwrap() { "1" } else { "0" },
buf[16..24]
.iter()
.map(|b| if *b { "1" } else { "0" })
.collect::<Vec<_>>()
.join(""),
if *buf.get(24).unwrap() { "1" } else { "0" },
buf[25..33]
.iter()
.map(|b| if *b { "1" } else { "0" })
.collect::<Vec<_>>()
.join(""),
if *buf.get(33).unwrap() { "1" } else { "0" },
buf[34..42]
.iter()
.map(|b| if *b { "1" } else { "0" })
.collect::<Vec<_>>()
.join(""),
if *buf.get(42).unwrap() { "1" } else { "0" },
);
}
#[test]
fn make_speed_and_direction() -> Result<()> {
let pkt = SpeedAndDirection::builder()
.address(35)?
.speed(14)?
.direction(Direction::Forward)
.build();
assert_eq!(pkt.address, 35);
let expected = 0b0111_1000;
eprintln!("Got instruction: {:08b}", pkt.instruction);
eprintln!("Expected: {expected:08b}");
assert_eq!(pkt.instruction, expected);
assert_eq!(pkt.ecc, 0x5b);
Ok(())
}
#[test]
fn serialise_speed_and_direction() -> Result<()> {
let pkt = SpeedAndDirection::builder()
.address(35)?
.speed(14)?
.direction(Direction::Forward)
.build();
let mut buf = SerialiseBuffer::default();
let len = pkt.serialise(&mut buf)?;
#[allow(clippy::unusual_byte_groupings)]
let expected_arr = [
0xff_u8, 0b1111_1110, 35, 0b0_0111_100, 0b0_0_010110, 0b11_1_00000, ];
let mut expected = SerialiseBuffer::default();
expected[..43]
.copy_from_bitslice(&expected_arr.view_bits::<Msb0>()[..43]);
println!("got:");
display_serialise_buffer(&buf);
println!("expected:");
display_serialise_buffer(&expected);
assert_eq!(len, 43);
assert_eq!(buf[..len], expected[..43]);
Ok(())
}
#[test]
fn serialise_reset_packet() -> Result<()> {
let pkt = Reset;
let mut buf = SerialiseBuffer::default();
let len = pkt.serialise(&mut buf)?;
#[allow(clippy::unusual_byte_groupings)]
let expected_arr = [
0xff_u8, 0b1111_1110, 0x00, 0b0_0000_000, 0b0_0_000000, 0b00_1_00000, ];
let mut expected = SerialiseBuffer::default();
expected[..43]
.copy_from_bitslice(&expected_arr.view_bits::<Msb0>()[..43]);
println!("got:");
display_serialise_buffer(&buf);
println!("expected:");
display_serialise_buffer(&expected);
assert_eq!(len, 43);
assert_eq!(buf[..len], expected[..43]);
Ok(())
}
#[test]
fn serialise_idle_packet() -> Result<()> {
let pkt = Idle;
let mut buf = SerialiseBuffer::default();
let len = pkt.serialise(&mut buf)?;
#[allow(clippy::unusual_byte_groupings)]
let expected_arr = [
0xff_u8, 0b1111_1110, 0xff, 0b0_0000_000, 0b0_0_111111, 0b11_1_00000, ];
let mut expected = SerialiseBuffer::default();
expected[..43]
.copy_from_bitslice(&expected_arr.view_bits::<Msb0>()[..43]);
println!("got:");
display_serialise_buffer(&buf);
println!("expected:");
display_serialise_buffer(&expected);
assert_eq!(len, 43);
assert_eq!(buf[..len], expected[..43]);
Ok(())
}
#[test]
fn serialise_broadcast_stop_packet() -> Result<()> {
let pkt = BroadcastStop::float();
let mut buf = SerialiseBuffer::default();
let len = pkt.serialise(&mut buf)?;
#[allow(clippy::unusual_byte_groupings)]
let expected_arr = [
0xff_u8, 0b1111_1110, 0x00, 0b0_0101_000, 0b0_0_010100, 0b00_1_00000, ];
let mut expected = SerialiseBuffer::default();
expected[..43]
.copy_from_bitslice(&expected_arr.view_bits::<Msb0>()[..43]);
println!("got:");
display_serialise_buffer(&buf);
println!("expected:");
display_serialise_buffer(&expected);
assert_eq!(len, 43);
assert_eq!(buf[..len], expected[..43]);
Ok(())
}
}