use super::{Error, Result, SerialiseBuffer};
#[derive(Copy, Clone)]
#[allow(missing_docs)]
pub enum Operation {
Verify,
Write,
}
pub struct PagePreset;
impl PagePreset {
pub fn serialise(&self, buf: &mut SerialiseBuffer) -> Result<usize> {
super::serialise(&[0b01111101, 0b00000001, 0b01111100], buf)
}
}
#[derive(Copy, Clone)]
#[allow(missing_docs)]
pub enum InstructionType {
WriteCvBit { offset: u8, value: bool },
VerifyCvBit { offset: u8, value: bool },
WriteCvByte { value: u8 },
VerifyCvByte { value: u8 },
}
pub struct Instruction {
typ: InstructionType,
cv_address: u16,
}
impl Instruction {
pub fn builder() -> InstructionBuilder {
InstructionBuilder::default()
}
pub fn serialise(&self, buf: &mut SerialiseBuffer) -> Result<usize> {
let mut type_and_start_of_address = 0x70;
type_and_start_of_address |= (self.cv_address >> 8) as u8;
let rest_of_address = (self.cv_address & 0x00ff) as u8;
#[allow(clippy::unusual_byte_groupings)]
let data = match self.typ {
InstructionType::WriteCvBit { offset, value } => {
type_and_start_of_address |= 0b0000_10_00;
let mut data = 0b111_1_0000;
data |= offset;
data |= (value as u8) << 3;
data
}
InstructionType::VerifyCvBit { offset, value } => {
type_and_start_of_address |= 0b0000_10_00;
#[allow(clippy::unusual_byte_groupings)]
let mut data = 0b111_0_0000;
data |= offset;
data |= (value as u8) << 3;
data
}
InstructionType::WriteCvByte { value } => {
type_and_start_of_address |= 0b0000_11_00;
value
}
InstructionType::VerifyCvByte { value } => {
type_and_start_of_address |= 0b0000_01_00;
value
}
};
super::serialise(
&[
type_and_start_of_address,
rest_of_address,
data,
type_and_start_of_address ^ rest_of_address ^ data,
],
buf,
)
}
}
#[derive(Default)]
pub struct InstructionBuilder {
cv_address: Option<u16>,
typ: Option<InstructionType>,
}
impl InstructionBuilder {
pub fn cv_address(&mut self, cv_address: u16) -> Result<&mut Self> {
if 0 < cv_address && cv_address < 0x0400 {
self.cv_address = Some(cv_address - 1);
Ok(self)
} else {
Err(Error::InvalidAddress)
}
}
pub fn write_byte(&mut self, value: u8) -> &mut Self {
self.typ = Some(InstructionType::WriteCvByte { value });
self
}
pub fn verify_byte(&mut self, value: u8) -> &mut Self {
self.typ = Some(InstructionType::VerifyCvByte { value });
self
}
pub fn write_bit(&mut self, offset: u8, value: bool) -> Result<&mut Self> {
if offset < 0x08 {
self.typ = Some(InstructionType::WriteCvBit { offset, value });
Ok(self)
} else {
Err(Error::InvalidOffset)
}
}
pub fn verify_bit(&mut self, offset: u8, value: bool) -> Result<&mut Self> {
if offset < 0x08 {
self.typ = Some(InstructionType::VerifyCvBit { offset, value });
Ok(self)
} else {
Err(Error::InvalidOffset)
}
}
pub fn build(&mut self) -> Result<Instruction> {
Ok(Instruction {
typ: self.typ.ok_or(Error::MissingField)?,
cv_address: self.cv_address.ok_or(Error::MissingField)?,
})
}
}
#[allow(missing_docs)]
pub enum AddressOnly {
Write { address: u8 },
Verify { address: u8 },
}
impl AddressOnly {
pub fn write(address: u8) -> Result<AddressOnly> {
if address < 0x7f {
Ok(AddressOnly::Write { address })
} else {
Err(Error::InvalidAddress)
}
}
pub fn verify(address: u8) -> Result<AddressOnly> {
if address < 0x7f {
Ok(AddressOnly::Verify { address })
} else {
Err(Error::InvalidAddress)
}
}
pub fn serialise(&self, buf: &mut SerialiseBuffer) -> Result<usize> {
let mut instr = 0b0111_0000;
let address = match self {
AddressOnly::Write { address } => {
instr |= 0b0000_1000;
*address
}
AddressOnly::Verify { address } => *address,
};
super::serialise(&[instr, address, instr ^ address], buf)
}
}
pub struct PhysicalRegister {
operation: Operation,
register: u8,
value: u8,
}
impl PhysicalRegister {
pub const ADDRESS: u8 = 1;
pub const START_VOLTAGE: u8 = 2;
pub const ACCELERATION: u8 = 3;
pub const DECELERATION: u8 = 4;
pub const BASIC_CONFIGURATION_REGISTER: u8 = 5;
pub const RESERVED_FOR_PAGE_REGISTER: u8 = 6;
pub const VERSION_NUMBER: u8 = 7;
pub const MANUFACTURER_ID: u8 = 8;
pub fn builder() -> PhysicalRegisterBuilder {
PhysicalRegisterBuilder::default()
}
pub fn serialise(&self, buf: &mut SerialiseBuffer) -> Result<usize> {
let mut instr = 0b0111_0000;
if let Operation::Write = self.operation {
instr |= 0b0000_1000;
}
instr |= self.register;
super::serialise(&[instr, self.value, instr ^ self.value], buf)
}
}
#[derive(Default)]
pub struct PhysicalRegisterBuilder {
operation: Option<Operation>,
register: Option<u8>,
value: Option<u8>,
}
impl PhysicalRegisterBuilder {
pub fn operation(&mut self, operation: Operation) -> &mut Self {
self.operation = Some(operation);
self
}
pub fn register(&mut self, register: u8) -> Result<&mut Self> {
if 1 < register && register <= 8 {
self.register = Some(register - 1);
Ok(self)
} else {
Err(Error::InvalidAddress)
}
}
pub fn value(&mut self, value: u8) -> &mut Self {
self.value = Some(value);
self
}
pub fn build(&mut self) -> Result<PhysicalRegister> {
Ok(PhysicalRegister {
operation: self.operation.ok_or(Error::MissingField)?,
register: self.register.ok_or(Error::MissingField)?,
value: self.value.ok_or(Error::MissingField)?,
})
}
}
pub struct FactoryReset;
impl FactoryReset {
pub fn serialise(&self, buf: &mut SerialiseBuffer) -> Result<usize> {
super::serialise(&[0b01111111, 0b00001000, 0b01110111], buf)
}
}
pub struct AddressQuery {
address: u8,
}
impl AddressQuery {
pub fn address(address: u8) -> AddressQuery {
AddressQuery { address }
}
pub fn serialise(&self, buf: &mut SerialiseBuffer) -> Result<usize> {
let instr = 0b11111001;
super::serialise(&[self.address, instr, self.address ^ instr], buf)
}
}
pub struct DecoderLock {
address: u8,
}
impl DecoderLock {
pub fn builder() -> DecoderLockBuilder {
DecoderLockBuilder::default()
}
pub fn serialise(&self, buf: &mut SerialiseBuffer) -> Result<usize> {
let instr = 0b11111001;
super::serialise(&[0, instr, self.address, self.address ^ instr], buf)
}
}
#[derive(Default)]
pub struct DecoderLockBuilder {
address: Option<u8>,
}
impl DecoderLockBuilder {
pub fn address(&mut self, address: u8) -> Result<&mut Self> {
if address < 0x7f {
self.address = Some(address);
Ok(self)
} else {
Err(Error::InvalidAddress)
}
}
pub fn build(&mut self) -> Result<DecoderLock> {
Ok(DecoderLock {
address: self.address.ok_or(Error::MissingField)?,
})
}
}
#[cfg(test)]
mod test {
use super::*;
use crate::packets::test::print_chunks;
use bitvec::prelude::*;
#[test]
fn serialise_instruction_packet_write_byte() {
let pkt = Instruction::builder()
.cv_address(48)
.unwrap()
.write_byte(0xaa)
.build()
.unwrap();
let mut buf = SerialiseBuffer::default();
let len = pkt.serialise(&mut buf).unwrap();
assert_eq!(len, 52);
#[allow(clippy::unusual_byte_groupings)]
let expected_arr = &[
0b1111_1111_u8, 0b1111_111_0, 0b0111_11_00, 0b0001_0_111, 0b1_0_10_10_10, 0b10_0_1_111_1, 0b001_1_0000, ]
.view_bits::<Msb0>()[..len];
let mut expected = SerialiseBuffer::default();
expected[..52].copy_from_bitslice(expected_arr);
println!("Got:");
print_chunks(&buf, 52);
println!("Expected:");
print_chunks(&expected, 52);
assert_eq!(buf[..len], expected[..52]);
}
#[test]
fn serialise_instruction_packet_verify_bit() {
let pkt = Instruction::builder()
.cv_address(298)
.unwrap()
.verify_bit(5, true)
.unwrap()
.build()
.unwrap();
let mut buf = SerialiseBuffer::default();
let len = pkt.serialise(&mut buf).unwrap();
assert_eq!(len, 52);
#[allow(clippy::unusual_byte_groupings)]
let expected_arr = &[
0b1111_1111_u8, 0b1111_111_0, 0b0111_10_01, 0b0001_0_100, 0b1_0_11_10_11, 0b01_0_1_011_1, 0b101_1_0000, ]
.view_bits::<Msb0>()[..len];
let mut expected = SerialiseBuffer::default();
expected[..52].copy_from_bitslice(expected_arr);
println!("Got:");
print_chunks(&buf, 52);
println!("Expected:");
print_chunks(&expected, 52);
assert_eq!(buf[..len], expected[..52]);
}
#[test]
fn serialise_address_only_packet() {
let pkt = AddressOnly::write(59).unwrap();
let mut buf = SerialiseBuffer::default();
let len = pkt.serialise(&mut buf).unwrap();
assert_eq!(len, 43);
#[allow(clippy::unusual_byte_groupings)]
let expected_arr = &[
0b1111_1111_u8, 0b1111_111_0, 0b0111_1000, 0b0_0011_101, 0b1_0_01_0000, 0b11_1_0_0000, ]
.view_bits::<Msb0>()[..len];
let mut expected = SerialiseBuffer::default();
expected[..43].copy_from_bitslice(expected_arr);
println!("Got:");
print_chunks(&buf, 43);
println!("Expected:");
print_chunks(&expected, 43);
assert_eq!(buf[..len], expected[..43]);
}
#[test]
fn serialise_physical_register_packet() {
let pkt = PhysicalRegister::builder()
.operation(Operation::Write)
.register(6)
.unwrap()
.value(0xaa)
.build()
.unwrap();
let mut buf = SerialiseBuffer::default();
let len = pkt.serialise(&mut buf).unwrap();
assert_eq!(len, 43);
#[allow(clippy::unusual_byte_groupings)]
let expected_arr = &[
0b1111_1111_u8, 0b1111_111_0, 0b0111_1_101, 0b0_1010_101, 0b0_0_11_0101, 0b11_1_0_0000, ]
.view_bits::<Msb0>()[..len];
let mut expected = SerialiseBuffer::default();
expected[..43].copy_from_bitslice(expected_arr);
println!("Got:");
print_chunks(&buf, 43);
println!("Expected:");
print_chunks(&expected, 43);
assert_eq!(buf[..len], expected[..43]);
}
}