1use super::{Error, Result, SerialiseBuffer};
11
12#[derive(Copy, Clone)]
13#[allow(missing_docs)]
14pub enum Operation {
15 Verify,
16 Write,
17}
18
19pub struct PagePreset;
21
22impl PagePreset {
23 pub fn serialise(&self, buf: &mut SerialiseBuffer) -> Result<usize> {
27 super::serialise(&[0b01111101, 0b00000001, 0b01111100], buf)
28 }
29}
30
31#[derive(Copy, Clone)]
41#[allow(missing_docs)]
42pub enum InstructionType {
43 WriteCvBit { offset: u8, value: bool },
44 VerifyCvBit { offset: u8, value: bool },
45 WriteCvByte { value: u8 },
46 VerifyCvByte { value: u8 },
47}
48
49pub struct Instruction {
52 typ: InstructionType,
53 cv_address: u16,
54}
55
56impl Instruction {
57 pub fn builder() -> InstructionBuilder {
59 InstructionBuilder::default()
60 }
61
62 pub fn serialise(&self, buf: &mut SerialiseBuffer) -> Result<usize> {
66 let mut type_and_start_of_address = 0x70;
69 type_and_start_of_address |= (self.cv_address >> 8) as u8;
70
71 let rest_of_address = (self.cv_address & 0x00ff) as u8;
73
74 #[allow(clippy::unusual_byte_groupings)]
78 let data = match self.typ {
79 InstructionType::WriteCvBit { offset, value } => {
80 type_and_start_of_address |= 0b0000_10_00;
81 let mut data = 0b111_1_0000;
83 data |= offset;
84 data |= (value as u8) << 3;
85 data
86 }
87 InstructionType::VerifyCvBit { offset, value } => {
88 type_and_start_of_address |= 0b0000_10_00;
89 #[allow(clippy::unusual_byte_groupings)]
91 let mut data = 0b111_0_0000;
92 data |= offset;
93 data |= (value as u8) << 3;
94 data
95 }
96 InstructionType::WriteCvByte { value } => {
97 type_and_start_of_address |= 0b0000_11_00;
98 value
99 }
100 InstructionType::VerifyCvByte { value } => {
101 type_and_start_of_address |= 0b0000_01_00;
102 value
103 }
104 };
105
106 super::serialise(
107 &[
108 type_and_start_of_address,
109 rest_of_address,
110 data,
111 type_and_start_of_address ^ rest_of_address ^ data,
112 ],
113 buf,
114 )
115 }
116}
117
118#[derive(Default)]
121pub struct InstructionBuilder {
122 cv_address: Option<u16>,
123 typ: Option<InstructionType>,
124}
125
126impl InstructionBuilder {
127 pub fn cv_address(&mut self, cv_address: u16) -> Result<&mut Self> {
134 if 0 < cv_address && cv_address < 0x0400 {
135 self.cv_address = Some(cv_address - 1);
136 Ok(self)
137 } else {
138 Err(Error::InvalidAddress)
139 }
140 }
141
142 pub fn write_byte(&mut self, value: u8) -> &mut Self {
144 self.typ = Some(InstructionType::WriteCvByte { value });
145 self
146 }
147
148 pub fn verify_byte(&mut self, value: u8) -> &mut Self {
150 self.typ = Some(InstructionType::VerifyCvByte { value });
151 self
152 }
153
154 pub fn write_bit(&mut self, offset: u8, value: bool) -> Result<&mut Self> {
156 if offset < 0x08 {
157 self.typ = Some(InstructionType::WriteCvBit { offset, value });
158 Ok(self)
159 } else {
160 Err(Error::InvalidOffset)
161 }
162 }
163
164 pub fn verify_bit(&mut self, offset: u8, value: bool) -> Result<&mut Self> {
166 if offset < 0x08 {
167 self.typ = Some(InstructionType::VerifyCvBit { offset, value });
168 Ok(self)
169 } else {
170 Err(Error::InvalidOffset)
171 }
172 }
173
174 pub fn build(&mut self) -> Result<Instruction> {
176 Ok(Instruction {
177 typ: self.typ.ok_or(Error::MissingField)?,
178 cv_address: self.cv_address.ok_or(Error::MissingField)?,
179 })
180 }
181}
182
183#[allow(missing_docs)]
186pub enum AddressOnly {
187 Write { address: u8 },
188 Verify { address: u8 },
189}
190
191impl AddressOnly {
192 pub fn write(address: u8) -> Result<AddressOnly> {
195 if address < 0x7f {
196 Ok(AddressOnly::Write { address })
197 } else {
198 Err(Error::InvalidAddress)
199 }
200 }
201
202 pub fn verify(address: u8) -> Result<AddressOnly> {
205 if address < 0x7f {
206 Ok(AddressOnly::Verify { address })
207 } else {
208 Err(Error::InvalidAddress)
209 }
210 }
211
212 pub fn serialise(&self, buf: &mut SerialiseBuffer) -> Result<usize> {
216 let mut instr = 0b0111_0000;
217 let address = match self {
218 AddressOnly::Write { address } => {
219 instr |= 0b0000_1000;
220 *address
221 }
222 AddressOnly::Verify { address } => *address,
223 };
224 super::serialise(&[instr, address, instr ^ address], buf)
225 }
226}
227
228pub struct PhysicalRegister {
233 operation: Operation,
234 register: u8,
235 value: u8,
236}
237
238impl PhysicalRegister {
239 pub const ADDRESS: u8 = 1;
241 pub const START_VOLTAGE: u8 = 2;
243 pub const ACCELERATION: u8 = 3;
245 pub const DECELERATION: u8 = 4;
247 pub const BASIC_CONFIGURATION_REGISTER: u8 = 5;
249 pub const RESERVED_FOR_PAGE_REGISTER: u8 = 6;
251 pub const VERSION_NUMBER: u8 = 7;
253 pub const MANUFACTURER_ID: u8 = 8;
255
256 pub fn builder() -> PhysicalRegisterBuilder {
258 PhysicalRegisterBuilder::default()
259 }
260
261 pub fn serialise(&self, buf: &mut SerialiseBuffer) -> Result<usize> {
265 let mut instr = 0b0111_0000;
266
267 if let Operation::Write = self.operation {
268 instr |= 0b0000_1000;
269 }
270
271 instr |= self.register;
272
273 super::serialise(&[instr, self.value, instr ^ self.value], buf)
274 }
275}
276
277#[derive(Default)]
279pub struct PhysicalRegisterBuilder {
280 operation: Option<Operation>,
281 register: Option<u8>,
282 value: Option<u8>,
283}
284
285impl PhysicalRegisterBuilder {
286 pub fn operation(&mut self, operation: Operation) -> &mut Self {
288 self.operation = Some(operation);
289 self
290 }
291
292 pub fn register(&mut self, register: u8) -> Result<&mut Self> {
296 if 1 < register && register <= 8 {
297 self.register = Some(register - 1);
298 Ok(self)
299 } else {
300 Err(Error::InvalidAddress)
301 }
302 }
303
304 pub fn value(&mut self, value: u8) -> &mut Self {
306 self.value = Some(value);
307 self
308 }
309
310 pub fn build(&mut self) -> Result<PhysicalRegister> {
313 Ok(PhysicalRegister {
314 operation: self.operation.ok_or(Error::MissingField)?,
315 register: self.register.ok_or(Error::MissingField)?,
316 value: self.value.ok_or(Error::MissingField)?,
317 })
318 }
319}
320
321pub struct FactoryReset;
323
324impl FactoryReset {
325 pub fn serialise(&self, buf: &mut SerialiseBuffer) -> Result<usize> {
329 super::serialise(&[0b01111111, 0b00001000, 0b01110111], buf)
330 }
331}
332
333pub struct AddressQuery {
335 address: u8,
336}
337
338impl AddressQuery {
339 pub fn address(address: u8) -> AddressQuery {
341 AddressQuery { address }
342 }
343
344 pub fn serialise(&self, buf: &mut SerialiseBuffer) -> Result<usize> {
348 let instr = 0b11111001;
349 super::serialise(&[self.address, instr, self.address ^ instr], buf)
350 }
351}
352
353pub struct DecoderLock {
356 address: u8,
357}
358
359impl DecoderLock {
360 pub fn builder() -> DecoderLockBuilder {
362 DecoderLockBuilder::default()
363 }
364
365 pub fn serialise(&self, buf: &mut SerialiseBuffer) -> Result<usize> {
369 let instr = 0b11111001;
370 super::serialise(&[0, instr, self.address, self.address ^ instr], buf)
371 }
372}
373
374#[derive(Default)]
376pub struct DecoderLockBuilder {
377 address: Option<u8>,
378}
379
380impl DecoderLockBuilder {
381 pub fn address(&mut self, address: u8) -> Result<&mut Self> {
385 if address < 0x7f {
386 self.address = Some(address);
387 Ok(self)
388 } else {
389 Err(Error::InvalidAddress)
390 }
391 }
392
393 pub fn build(&mut self) -> Result<DecoderLock> {
396 Ok(DecoderLock {
397 address: self.address.ok_or(Error::MissingField)?,
398 })
399 }
400}
401
402#[cfg(test)]
403mod test {
404 use super::*;
405 use crate::packets::test::print_chunks;
406 use bitvec::prelude::*;
407
408 #[test]
409 fn serialise_instruction_packet_write_byte() {
410 let pkt = Instruction::builder()
413 .cv_address(48)
414 .unwrap()
415 .write_byte(0xaa)
416 .build()
417 .unwrap();
418
419 let mut buf = SerialiseBuffer::default();
420 let len = pkt.serialise(&mut buf).unwrap();
421 assert_eq!(len, 52);
422
423 #[allow(clippy::unusual_byte_groupings)]
424 let expected_arr = &[
425 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, ]
433 .view_bits::<Msb0>()[..len];
434 let mut expected = SerialiseBuffer::default();
435 expected[..52].copy_from_bitslice(expected_arr);
436
437 println!("Got:");
438 print_chunks(&buf, 52);
439 println!("Expected:");
440 print_chunks(&expected, 52);
441 assert_eq!(buf[..len], expected[..52]);
442 }
443
444 #[test]
445 fn serialise_instruction_packet_verify_bit() {
446 let pkt = Instruction::builder()
449 .cv_address(298)
450 .unwrap()
451 .verify_bit(5, true)
452 .unwrap()
453 .build()
454 .unwrap();
455
456 let mut buf = SerialiseBuffer::default();
457 let len = pkt.serialise(&mut buf).unwrap();
458 assert_eq!(len, 52);
459
460 #[allow(clippy::unusual_byte_groupings)]
461 let expected_arr = &[
462 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, ]
470 .view_bits::<Msb0>()[..len];
471 let mut expected = SerialiseBuffer::default();
472 expected[..52].copy_from_bitslice(expected_arr);
473
474 println!("Got:");
475 print_chunks(&buf, 52);
476 println!("Expected:");
477 print_chunks(&expected, 52);
478 assert_eq!(buf[..len], expected[..52]);
479 }
480
481 #[test]
482 fn serialise_address_only_packet() {
483 let pkt = AddressOnly::write(59).unwrap();
486
487 let mut buf = SerialiseBuffer::default();
488 let len = pkt.serialise(&mut buf).unwrap();
489 assert_eq!(len, 43);
490
491 #[allow(clippy::unusual_byte_groupings)]
492 let expected_arr = &[
493 0b1111_1111_u8, 0b1111_111_0, 0b0111_1000, 0b0_0011_101, 0b1_0_01_0000, 0b11_1_0_0000, ]
500 .view_bits::<Msb0>()[..len];
501 let mut expected = SerialiseBuffer::default();
502 expected[..43].copy_from_bitslice(expected_arr);
503
504 println!("Got:");
505 print_chunks(&buf, 43);
506 println!("Expected:");
507 print_chunks(&expected, 43);
508 assert_eq!(buf[..len], expected[..43]);
509 }
510
511 #[test]
512 fn serialise_physical_register_packet() {
513 let pkt = PhysicalRegister::builder()
516 .operation(Operation::Write)
517 .register(6)
518 .unwrap()
519 .value(0xaa)
520 .build()
521 .unwrap();
522
523 let mut buf = SerialiseBuffer::default();
524 let len = pkt.serialise(&mut buf).unwrap();
525 assert_eq!(len, 43);
526
527 #[allow(clippy::unusual_byte_groupings)]
528 let expected_arr = &[
529 0b1111_1111_u8, 0b1111_111_0, 0b0111_1_101, 0b0_1010_101, 0b0_0_11_0101, 0b11_1_0_0000, ]
536 .view_bits::<Msb0>()[..len];
537 let mut expected = SerialiseBuffer::default();
538 expected[..43].copy_from_bitslice(expected_arr);
539
540 println!("Got:");
541 print_chunks(&buf, 43);
542 println!("Expected:");
543 print_chunks(&expected, 43);
544 assert_eq!(buf[..len], expected[..43]);
545 }
546}