locodrive/args.rs
1#![allow(clippy::too_many_arguments)]
2
3use crate::error::MessageParseError;
4use crate::protocol::Message;
5use std::fmt::{Debug, Display, Formatter};
6
7/// Represents a trains address of 14 byte length.
8#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
9pub struct AddressArg(u16);
10
11impl AddressArg {
12 /// Creates a new address.
13 ///
14 /// Please consider keeping in range between 0 and 16383.
15 /// Higher values may not be supported by this address implementation.
16 pub fn new(adr: u16) -> Self {
17 Self(adr)
18 }
19
20 /// Parses the message bytes from a model railroads message into an `AddressArg`
21 ///
22 /// # Parameters
23 ///
24 /// - `adr`: seven least significant loco address bits
25 /// - `adr2`: seven most significant loco address bits
26 pub(crate) fn parse(adr2: u8, adr: u8) -> Self {
27 let mut address = adr as u16;
28 address |= (adr2 as u16) << 7;
29 Self(address)
30 }
31
32 /// # Returns
33 ///
34 /// The address hold by this arg
35 pub fn address(&self) -> u16 {
36 self.0
37 }
38
39 /// Sets the address hold by this [`AddressArg`]
40 ///
41 /// Please consider keeping in range between 0 and 16383.
42 /// Higher values may not be supported by this address implementation.
43 pub fn set_address(&mut self, address: u16) {
44 self.0 = address;
45 }
46
47 /// # Returns
48 ///
49 /// seven least significant loco address bits
50 pub(crate) fn adr1(&self) -> u8 {
51 (self.0 & 0x007F) as u8
52 }
53
54 /// # Returns
55 ///
56 /// seven most significant loco address bits
57 pub(crate) fn adr2(&self) -> u8 {
58 ((self.0 >> 7) & 0x007F) as u8
59 }
60}
61
62/// Which direction state a switch is orientated to
63#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
64pub enum SwitchDirection {
65 Straight,
66 Curved,
67}
68
69impl std::ops::Not for SwitchDirection {
70 type Output = SwitchDirection;
71
72 fn not(self) -> Self::Output {
73 match self {
74 SwitchDirection::Straight => SwitchDirection::Curved,
75 SwitchDirection::Curved => SwitchDirection::Straight,
76 }
77 }
78}
79
80/// Holds switch state information to be read or write
81#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
82pub struct SwitchArg {
83 /// The address of the switch (0 - 2047)
84 address: u16,
85 /// The switches direction state, which direction the switch points
86 direction: SwitchDirection,
87 /// If the switch is not in the requested direction.
88 /// Use true if you want the switch to go to the direction.
89 state: bool,
90}
91
92impl SwitchArg {
93 /// Creates a new switch information block that can be send to update a switch in a
94 /// model railroad system using the corresponding [`crate::protocol::Message::SwReq`] message.
95 ///
96 /// # Parameters
97 ///
98 /// - `address`: The address of the switch you want to change state (0 to 2047)
99 /// - `direction`: The direction the switch should switch to
100 /// - `state`: The activation state of the switch (If the switch is in the requested state)
101 pub fn new(address: u16, direction: SwitchDirection, state: bool) -> Self {
102 Self {
103 address,
104 direction,
105 state,
106 }
107 }
108
109 /// Parses the arguments of an incoming model railroads message to a [`SwitchArg`].
110 ///
111 /// # Parameters
112 ///
113 /// - `sw1`: Seven least significant switch address bits
114 /// - `sw2`: four most significant switch address bits,
115 /// - 1 bit for direction and
116 /// - 1 bit for activation state
117 pub(crate) fn parse(sw1: u8, sw2: u8) -> Self {
118 let mut address = sw1 as u16;
119 address |= (sw2 as u16 & 0x0F) << 7;
120
121 let direction = if sw2 & 0x20 == 0 {
122 SwitchDirection::Curved
123 } else {
124 SwitchDirection::Straight
125 };
126
127 let state = (sw2 & 0x10) != 0;
128 Self {
129 address,
130 direction,
131 state,
132 }
133 }
134
135 /// # Returns
136 ///
137 /// The address of the switch
138 pub fn address(&self) -> u16 {
139 self.address
140 }
141 /// # Returns
142 ///
143 /// The switches direction state
144 pub fn direction(&self) -> SwitchDirection {
145 self.direction
146 }
147 /// # Returns
148 ///
149 /// The switches activation status. False if the switch has switched to the requested state.
150 pub fn state(&self) -> bool {
151 self.state
152 }
153
154 /// Sets the address of the switch to use.
155 ///
156 /// # Parameters
157 ///
158 /// - `address`: The switches address (0 - 2047)
159 pub fn set_address(&mut self, address: u16) {
160 self.address = address;
161 }
162 /// Sets the direction to switch to.
163 ///
164 /// # Parameters
165 ///
166 /// - `direction`: The switches direction
167 pub fn set_direction(&mut self, direction: SwitchDirection) {
168 self.direction = direction;
169 }
170 /// Sets the activation state of the switch.
171 ///
172 /// # Parameters
173 ///
174 /// - `state`: The switches activation state to set (`true = ON, false = OFF`)
175 pub fn set_state(&mut self, state: bool) {
176 self.state = state;
177 }
178
179 /// # Returns
180 ///
181 /// The seven least significant address bits.
182 pub(crate) fn sw1(&self) -> u8 {
183 (self.address & 0x007F) as u8
184 }
185
186 /// # Returns
187 ///
188 /// The four most significant address bits combined with a direction state and activation state.
189 pub(crate) fn sw2(&self) -> u8 {
190 let mut sw2 = ((self.address >> 7) & 0x000F) as u8;
191
192 sw2 |= match self.direction {
193 SwitchDirection::Curved => 0x00,
194 SwitchDirection::Straight => 0x20,
195 };
196
197 if self.state {
198 sw2 |= 0x10;
199 }
200
201 sw2
202 }
203}
204
205/// Represents one slots address between 0 to 127.
206///
207/// Note that some slots are special handled slots and therefore can not be used (read/write) as normal slots.
208///
209/// # Slots
210///
211/// | Nr. | Function |
212/// |---------|------------------------------------|
213/// | 0 | dispatch |
214/// | 1-119 | active locs (normal slots) |
215/// | 120-127 | reserved (system / master control) |
216/// | - 123 | fast clock |
217/// | - 124 | programming track |
218/// | - 127 | command station options |
219#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
220pub struct SlotArg(u8);
221
222impl SlotArg {
223 /// Creates a new slots address in range of 0 to 127.
224 ///
225 /// Please consider that the special slots (0, 120 - 127) may not work
226 /// as you expect other slots to do.
227 ///
228 /// # Parameter
229 ///
230 /// - `slot`: The slots address to set
231 pub fn new(slot: u8) -> Self {
232 Self(slot & 0x7F)
233 }
234
235 /// Parses an incoming slot message from a model railroads message.
236 ///
237 /// # Parameter
238 ///
239 /// - `slot`: The slots address to set
240 pub(crate) fn parse(slot: u8) -> Self {
241 Self(slot & 0x7F)
242 }
243
244 /// # Returns
245 ///
246 /// The slot hold by the struct
247 pub fn slot(&self) -> u8 {
248 self.0
249 }
250}
251
252/// Represents the speed set to a [`SlotArg`].
253#[derive(Debug, Copy, Clone, Eq, Hash, PartialEq)]
254pub enum SpeedArg {
255 /// Performs a normal stop. Trains may stop smoothly when they receive a message force them to stop.
256 Stop,
257 /// Performs an immediate stop action. Trains do stop immediately.
258 EmergencyStop,
259 /// Sets the slots speed to a given value. If you want a slot speed to set to 0
260 /// use [`SpeedArg::Stop`] or create your [`SpeedArg`] using [`SpeedArg::new()`].
261 ///
262 /// The maximum speed is 126. Higher values may create unexpected behaviour.
263 Drive(u8),
264}
265
266impl SpeedArg {
267 /// Creates a new [`SpeedArg`] from the given value.
268 /// This means returning [`SpeedArg::Stop`] if the given `spd` is set to 0 and
269 /// returning [`SpeedArg::Drive`] with the given `spd` set as speed otherwise.
270 ///
271 /// # Parameters
272 ///
273 /// - `spd`: The speed to create the `SpeedArg` for.
274 /// The maximum speed is 126. Higher values may create unexpected behaviour.
275 pub fn new(spd: u8) -> Self {
276 match spd {
277 0x00 => Self::Stop,
278 _ => Self::Drive(spd),
279 }
280 }
281
282 /// Parses the speed from a model railroads send speed.
283 ///
284 /// # Parameters
285 ///
286 /// - `spd`: The model railroad messages speed
287 pub(crate) fn parse(spd: u8) -> Self {
288 match spd {
289 0x00 => Self::Stop,
290 0x01 => Self::EmergencyStop,
291 _ => Self::Drive(spd - 1),
292 }
293 }
294
295 /// # Returns
296 ///
297 /// The model railroad interpreted speed of this arg.
298 pub(crate) fn spd(&self) -> u8 {
299 match *self {
300 SpeedArg::Stop => 0x00,
301 SpeedArg::EmergencyStop => 0x01,
302 SpeedArg::Drive(spd) => (spd + 1) & 0x7F,
303 }
304 }
305
306 /// # Returns
307 ///
308 /// A `u8` interpreted value of the given [`SpeedArg`].
309 ///
310 /// Please note that [`SpeedArg::Stop`] and [`SpeedArg::EmergencyStop`] are both cast to 0
311 /// as they both indicates that the slots speed is 0 and only differ in how
312 /// immediate this state is reached by the connected device.
313 pub fn get_spd(&self) -> u8 {
314 match *self {
315 SpeedArg::Stop => 0x00,
316 SpeedArg::EmergencyStop => 0x00,
317 SpeedArg::Drive(spd) => spd,
318 }
319 }
320}
321
322/// Represents the direction and first five function bits of a slot.
323///
324/// Function bit 0 may control a trains light
325#[derive(Copy, Clone, Eq, Hash, PartialEq)]
326pub struct DirfArg(u8);
327
328impl DirfArg {
329 /// Creates a new dirf arg with all possible functions set
330 ///
331 /// # Parameter
332 ///
333 /// - `dir`: The direction to set (`true` = forwards, `false` = backwards)
334 /// - `f0`: Function bit 0 (train light control)
335 /// - `f1`: Function bit 1
336 /// - `f2`: Function bit 2
337 /// - `f3`: Function bit 3
338 /// - `f4`: Function bit 4
339 pub fn new(dir: bool, f0: bool, f1: bool, f2: bool, f3: bool, f4: bool) -> Self {
340 let mut dirf = if dir { 0x20 } else { 0x00 };
341 if f0 {
342 dirf |= 0x10
343 }
344 if f1 {
345 dirf |= 0x01
346 }
347 if f2 {
348 dirf |= 0x02
349 }
350 if f3 {
351 dirf |= 0x04
352 }
353 if f4 {
354 dirf |= 0x08
355 }
356 Self(dirf)
357 }
358
359 /// Parses the direction from a model railroad message.
360 pub(crate) fn parse(dirf: u8) -> Self {
361 Self(dirf & 0x3F)
362 }
363
364 /// # Returns
365 ///
366 /// The direction represented by this [`DirfArg`].
367 /// `true` means forward, `false` means backwards.
368 pub fn dir(&self) -> bool {
369 self.0 & 0x20 != 0
370 }
371
372 /// # Returns
373 ///
374 /// The value of the requested f-flag.
375 /// As there are only for f-flags are hold by one [`DirfArg`] only values from
376 /// 0 to 4 are calculated other inputs may ever return `false`.
377 pub fn f(&self, f_num: u8) -> bool {
378 if f_num <= 4 {
379 self.0 >> (if f_num == 0 { 4 } else { f_num - 1 }) & 1 != 0
380 } else {
381 false
382 }
383 }
384
385 /// Sets the direction hold by this arg to the requested value
386 ///
387 /// # Parameters
388 ///
389 /// - `value`: The direction to set (`true` = forward, `false` = backward)
390 pub fn set_dir(&mut self, value: bool) {
391 if value {
392 self.0 |= 0x20;
393 } else {
394 self.0 &= !0x20
395 }
396 }
397
398 /// Sets the value of the requested f-flag.
399 ///
400 /// # Parameters
401 ///
402 /// - `f_num`: The f-flag to set. (Only values in range of 0 to 4 may create an effect).
403 /// Other inputs will be ignored.
404 /// - `value`: The value to set the requested flag to.
405 pub fn set_f(&mut self, f_num: u8, value: bool) {
406 if f_num <= 4 {
407 let mask = 1 << if f_num == 0 { 4 } else { f_num - 1 };
408 if value {
409 self.0 |= mask;
410 } else {
411 self.0 &= !mask;
412 }
413 }
414 }
415
416 /// Parses this [`DirfArg`] in the corresponding model railroad message format.
417 ///
418 /// # Returns
419 ///
420 /// The to this arg corresponding model railroad message value.
421 pub(crate) fn dirf(&self) -> u8 {
422 self.0
423 }
424}
425
426/// Overriding the [`Debug`] trait, to show only the corresponding arg states
427impl Debug for DirfArg {
428 /// Prints the direction and all f-flags from 0 to 4 to the formatter
429 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
430 write!(
431 f,
432 "dirf: (dir: {}, f0: {}, f1: {}, f2: {}, f3: {}, f4: {})",
433 self.dir(),
434 self.f(0),
435 self.f(1),
436 self.f(2),
437 self.f(3),
438 self.f(4)
439 )
440 }
441}
442
443/// Holds the track information
444#[derive(Debug, Copy, Clone, Eq, Hash, PartialEq)]
445pub struct TrkArg {
446 /// The tracks power state (`ON`/`OFF`).
447 power: bool,
448 /// The tracks idle state.
449 idle: bool,
450 /// `true`: This master implements this protocol capability.
451 /// `false`: This master is `DT200`.
452 mlok1: bool,
453 /// Indicates that masters programming track is busy.
454 prog_busy: bool,
455}
456
457impl TrkArg {
458 /// Creates a new arg representing the tracks status
459 ///
460 /// # Parameters
461 ///
462 /// - `power`: The tracks power state (`On`/`OFF`)
463 /// - `idle`: The tracks idle state
464 /// - `mlok1`: The protocol Version to use. 0 = `DT200`, 1 = this protocol
465 /// - `prog_busy`: Busy status for programming track (Slot 124)
466 pub fn new(power: bool, idle: bool, mlok1: bool, prog_busy: bool) -> Self {
467 TrkArg {
468 power,
469 idle,
470 mlok1,
471 prog_busy,
472 }
473 }
474
475 /// Parses a model railroad messages trk arg to this struct by extracting the required values.
476 ///
477 /// # Parameters
478 ///
479 /// - `trk_arg`: The track message to parse
480 pub(crate) fn parse(trk_arg: u8) -> Self {
481 let power = trk_arg & 0x01 == 0x01;
482 let idle = trk_arg & 0x02 == 0x00;
483 let mlok1 = trk_arg & 0x04 == 0x04;
484 let prog_busy = trk_arg & 0x08 == 0x08;
485 TrkArg {
486 power,
487 idle,
488 mlok1,
489 prog_busy,
490 }
491 }
492
493 /// # Returns
494 ///
495 /// The power state of the track.
496 pub fn power_on(&self) -> bool {
497 self.power
498 }
499
500 /// # Returns
501 ///
502 /// The tracks master idle status.
503 pub fn track_idle(&self) -> bool {
504 self.idle
505 }
506
507 /// # Returns
508 ///
509 /// The available protocol version by the master.
510 ///
511 /// - `true` = this protocol is fully supported
512 /// - `false` = `DT200`
513 pub fn mlok1(&self) -> bool {
514 self.mlok1
515 }
516
517 /// # Returns
518 ///
519 /// The programing tracks busy status.
520 pub fn prog_busy(&self) -> bool {
521 self.prog_busy
522 }
523
524 /// Parses this arg to a valid model railroad track message byte.
525 ///
526 /// # Returns
527 ///
528 /// The model railroad trk message byte matching this [`TrkArg`].
529 pub(crate) fn trk_arg(&self) -> u8 {
530 let mut trk_arg = if self.power { 0x01 } else { 0x00 };
531 if !self.idle {
532 trk_arg |= 0x02;
533 }
534 if self.mlok1 {
535 trk_arg |= 0x04;
536 }
537 if self.prog_busy {
538 trk_arg |= 0x08;
539 }
540 trk_arg
541 }
542}
543
544/// Holds the function flags 5 to 8.
545///
546/// This function flags may be used for train sound management if available.
547#[derive(Copy, Clone, Eq, Hash, PartialEq)]
548pub struct SndArg(u8);
549
550impl SndArg {
551 /// Creates a new [`SndArg`] with the function flags set.
552 ///
553 /// # Parameters
554 ///
555 /// - `f5`: Function flag 5
556 /// - `f6`: Function flag 6
557 /// - `f7`: Function flag 7
558 /// - `f8`: Function flag 8
559 pub fn new(f5: bool, f6: bool, f7: bool, f8: bool) -> Self {
560 let mut snd = if f5 { 0x01 } else { 0x00 } as u8;
561 if f6 {
562 snd |= 0x02
563 }
564 if f7 {
565 snd |= 0x04
566 }
567 if f8 {
568 snd |= 0x08
569 }
570 Self(snd)
571 }
572
573 /// Parses a model railroad based function message byte to this arg.
574 ///
575 /// # Parameters
576 ///
577 /// - `snd`: A model railroad formatted snd byte
578 pub(crate) fn parse(snd: u8) -> Self {
579 Self(snd & 0x0F)
580 }
581
582 /// # Parameters
583 ///
584 /// - `f_num`: Which flag to look up
585 ///
586 /// # Returns
587 ///
588 /// The value of the `f_num`s function flag. Only values between 5 and 8 are allowed.
589 pub fn f(&self, f_num: u8) -> bool {
590 if (5..=8).contains(&f_num) {
591 self.0 & 1 << (f_num - 5) != 0
592 } else {
593 false
594 }
595 }
596
597 /// Sets the value of the `f_num`s function flag to `value`.
598 ///
599 /// # Parameters
600 ///
601 /// - `f_num`: The function flags index
602 /// - `value`: Which value to set the function bit to
603 pub fn set_f(&mut self, f_num: u8, value: bool) {
604 if (5..=8).contains(&f_num) {
605 let mask = 1 << (f_num - 5);
606 if value {
607 self.0 |= mask;
608 } else {
609 self.0 &= !mask;
610 }
611 }
612 }
613
614 /// Parses this [`SndArg`] to a model railroad snd message byte
615 pub(crate) fn snd(&self) -> u8 {
616 self.0
617 }
618}
619
620/// Overrides the [`Debug`] trait to show only the corresponding function bits
621impl Debug for SndArg {
622 /// Prints the f flags from 5 to 8 to the formatter
623 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
624 write!(
625 f,
626 "snd: (f5: {}, f6: {}, f7: {}, f8: {})",
627 self.f(5),
628 self.f(6),
629 self.f(7),
630 self.f(8)
631 )
632 }
633}
634
635/// Represents the link status of a slot
636#[derive(Debug, Copy, Clone, Eq, Hash, PartialEq)]
637pub enum Consist {
638 /// Slot is linked up and down
639 LogicalMid,
640 /// Slot is only linked down
641 LogicalTop,
642 /// Slot is only linked up
643 LogicalSubMember,
644 /// Slot is not linked
645 Free,
646}
647
648/// Represents the usage status of a slot
649#[derive(Debug, Copy, Clone, Eq, Hash, PartialEq)]
650pub enum State {
651 /// Indicates that this slot is in use by some device. The slot holds a loc address and is refreshed.
652 ///
653 /// If you want to mark your slot as [`State::InUse`] simply perform a `NULL`-Move on this slot. (Move message with eq, Hashual source and destination)
654 InUse,
655 /// A loco adr is in the slot but the slot was not refreshed.
656 Idle,
657 /// This slot holds some loc address and is refreshed.
658 Common,
659 /// No valid data in this slot, this slot is not refreshed.
660 Free,
661}
662
663/// Represents the decoders speed control message format used
664#[derive(Debug, Copy, Clone, Eq, Hash, PartialEq)]
665pub enum DecoderType {
666 /// 28 step decoder with advanced DCC allowed
667 Dcc28,
668 /// 128 step decoder with advanced DVV allowed
669 Dcc128,
670 /// 28 step mode in 3 byte PKT regular mode
671 Regular28,
672 /// 28 step mode. Generates trinary packets for mobile address.
673 AdrMobile28,
674 /// 14 step speed mode (Speed will match values from 0 to 14)
675 Step14,
676 /// 128 speed mode packets
677 Speed128,
678}
679
680/// Holds general slot status information.
681#[derive(Debug, Copy, Clone, Eq, Hash, PartialEq)]
682pub struct Stat1Arg {
683 /// The slots purge status.
684 s_purge: bool,
685 /// The slots link status.
686 consist: Consist,
687 /// The slots usage status.
688 state: State,
689 /// The decoder type used by the slot.
690 decoder_type: DecoderType,
691}
692
693impl Stat1Arg {
694 /// Creates new slot status information
695 ///
696 /// # Parameters
697 ///
698 /// - `s_purge`: The slots purge status
699 /// - `consist`: The slots link status
700 /// - `state`: The slots usage status
701 /// - `decoder_type`: The decoder type used to generate loc messages for this slot
702 pub fn new(s_purge: bool, consist: Consist, state: State, decoder_type: DecoderType) -> Self {
703 Stat1Arg {
704 s_purge,
705 consist,
706 state,
707 decoder_type,
708 }
709 }
710
711 /// Parses a model railroad formatted `stat1` byte into this arg
712 ///
713 /// # Parameters
714 ///
715 /// - `stat1`: The status byte to parse
716 pub(crate) fn parse(stat1: u8) -> Self {
717 let s_purge = stat1 & 0x80 != 0;
718
719 let consist = match stat1 & 0x48 {
720 0x48 => Consist::LogicalMid,
721 0x08 => Consist::LogicalTop,
722 0x40 => Consist::LogicalSubMember,
723 0x00 => Consist::Free,
724 _ => Consist::Free,
725 };
726
727 let state = match stat1 & 0x30 {
728 0x30 => State::InUse,
729 0x20 => State::Idle,
730 0x10 => State::Common,
731 0x00 => State::Free,
732 _ => State::Free,
733 };
734
735 let decoder_type = match stat1 & 0x07 {
736 0x02 => DecoderType::Step14,
737 0x01 => DecoderType::AdrMobile28,
738 0x00 => DecoderType::Regular28,
739 0x03 => DecoderType::Speed128,
740 0x07 => DecoderType::Dcc128,
741 0x04 => DecoderType::Dcc28,
742 _ => panic!("The given decoder type was invalid!"),
743 };
744
745 Stat1Arg {
746 s_purge,
747 consist,
748 state,
749 decoder_type,
750 }
751 }
752
753 /// # Returns
754 ///
755 /// The slots purge status
756 pub fn s_purge(&self) -> bool {
757 self.s_purge
758 }
759
760 /// # Returns
761 ///
762 /// The slots linking state
763 pub fn consist(&self) -> Consist {
764 self.consist
765 }
766
767 /// # Returns
768 ///
769 /// The usage state of the slot
770 pub fn state(&self) -> State {
771 self.state
772 }
773
774 /// # Returns
775 ///
776 /// The decoder type to use for this slot
777 pub fn decoder_type(&self) -> DecoderType {
778 self.decoder_type
779 }
780
781 /// Parses this arg to a model railroad defined stat1 message byte
782 pub(crate) fn stat1(&self) -> u8 {
783 let mut stat1: u8 = if self.s_purge { 0x80 } else { 0x00 };
784
785 stat1 |= match self.consist {
786 Consist::LogicalMid => 0x48,
787 Consist::LogicalTop => 0x08,
788 Consist::LogicalSubMember => 0x40,
789 Consist::Free => 0x00,
790 };
791
792 stat1 |= match self.state {
793 State::InUse => 0x30,
794 State::Idle => 0x20,
795 State::Common => 0x10,
796 State::Free => 0x00,
797 };
798
799 stat1 |= match self.decoder_type {
800 DecoderType::Dcc28 => 0x04,
801 DecoderType::Dcc128 => 0x07,
802 DecoderType::Regular28 => 0x00,
803 DecoderType::AdrMobile28 => 0x01,
804 DecoderType::Step14 => 0x02,
805 DecoderType::Speed128 => 0x03,
806 };
807
808 stat1
809 }
810}
811
812/// Extension part for the slot status holding some additional slot information
813#[derive(Debug, Copy, Clone, Eq, Hash, PartialEq)]
814pub struct Stat2Arg {
815 /// If slots ADV consist is suppressed
816 has_adv: bool,
817 /// ID1/2 is not used for ID
818 no_id_usage: bool,
819 /// If this ID is no encoded alias
820 id_encoded_alias: bool,
821}
822
823impl Stat2Arg {
824 /// Creates a new status argument
825 ///
826 /// # Parameters
827 ///
828 /// - `has_adv`: If this slot has suppressed ADV consist
829 /// - `no_id_usage`: If this slots ID1/2 values are not used to represent the ID
830 /// - `id_encoded_alias`: If this ID is no encoded alias
831 pub fn new(has_adv: bool, no_id_usage: bool, id_encoded_alias: bool) -> Self {
832 Stat2Arg {
833 has_adv,
834 no_id_usage,
835 id_encoded_alias,
836 }
837 }
838
839 /// Parses a received `stat2` byte by the model railroad to this struct
840 pub(crate) fn parse(stat2: u8) -> Self {
841 let has_adv = stat2 & 0x01 != 0;
842
843 let no_id_usage = stat2 & 0x04 != 0;
844
845 let id_encoded_alias = stat2 & 0x08 != 0;
846
847 Stat2Arg {
848 has_adv,
849 no_id_usage,
850 id_encoded_alias,
851 }
852 }
853
854 /// # Returns
855 ///
856 /// If this slot has suppressed advanced control v
857 pub fn has_adv(&self) -> bool {
858 self.has_adv
859 }
860
861 /// # Returns
862 ///
863 /// If this slot has suppressed adv
864 pub fn no_id_usage(&self) -> bool {
865 self.no_id_usage
866 }
867
868 /// # Returns
869 ///
870 /// If this messages id is no encoded alias
871 pub fn id_encoded_alias(&self) -> bool {
872 self.id_encoded_alias
873 }
874
875 /// # Returns
876 ///
877 /// The values hold by this argument as one byte
878 pub(crate) fn stat2(&self) -> u8 {
879 let mut stat2 = if self.has_adv { 0x01 } else { 0x00 };
880 if self.no_id_usage {
881 stat2 |= 0x04;
882 }
883 if self.id_encoded_alias {
884 stat2 |= 0x08;
885 }
886 stat2
887 }
888}
889
890/// Represents a copy of the operation code with the highest bit erased
891#[derive(Debug, Copy, Clone, Eq, Hash, PartialEq)]
892pub struct LopcArg(u8);
893
894impl LopcArg {
895 /// Creates a new operation code copy with the highest bit erased from the given op code byte.
896 ///
897 /// To get a messages operation code you can use: [Message::opc()]
898 pub fn new(opc: u8) -> Self {
899 LopcArg::parse(opc & 0x7F)
900 }
901
902 /// Parses a new operation code copy from an incoming byte
903 pub(crate) fn parse(lopc: u8) -> Self {
904 Self(lopc & 0x7F)
905 }
906
907 /// # Returns
908 ///
909 /// The operation code copy argument
910 pub(crate) fn lopc(&self) -> u8 {
911 self.0
912 }
913
914 /// Checks whether an messages operation code matches the operation code held by this argument
915 ///
916 /// # Parameter
917 ///
918 /// - `message`: The message to check operation code matching for
919 ///
920 /// # Returns
921 ///
922 /// If the messages operation code matches the operation code hold by this argument
923 pub fn check_opc(&self, message: &Message) -> bool {
924 message.opc() & 0x7F == self.0
925 }
926}
927
928/// Holds a response code for a before received message
929#[derive(Debug, Copy, Clone, Eq, Hash, PartialEq)]
930pub struct Ack1Arg(u8);
931
932impl Ack1Arg {
933 /// Creates a new acknowledgment answer
934 ///
935 /// # Parameter
936 ///
937 /// - `success`: If this acknowledgment indicates that the request was successfully
938 pub fn new(success: bool) -> Self {
939 Self(if success { 0x7F } else { 0x00 })
940 }
941
942 /// This creates a new acknowledgment answer with only the `code` to send as answer.
943 ///
944 /// `0x7F` means the request succeeded and `0x00` means the request was denied.
945 ///
946 /// If you want to mark that you accepted the message use `0x01` and when you want to indicate a blind acceptance use `0x40`
947 pub fn new_advanced(code: u8) -> Self {
948 Self(code & 0x7F)
949 }
950
951 /// Parses the acknowledgment type from a byte
952 pub(crate) fn parse(ack1: u8) -> Self {
953 Self(ack1)
954 }
955
956 /// # Returns
957 ///
958 /// The acknowledgment parsed to a byte
959 pub fn ack1(&self) -> u8 {
960 self.0
961 }
962
963 /// # Returns
964 ///
965 /// If this message indicates the operation succeeded
966 pub fn success(&self) -> bool {
967 self.0 == 0x7F
968 }
969
970 /// # Returns
971 ///
972 /// If the message has not failed
973 pub fn limited_success(&self) -> bool {
974 self.0 != 0x00
975 }
976
977 /// # Returns
978 ///
979 /// If this message indicates the operation failure
980 pub fn failed(&self) -> bool {
981 self.0 == 0x00
982 }
983
984 /// # Returns
985 ///
986 /// If this message indicates the operation was accepted but not succeeded yet
987 pub fn accepted(&self) -> bool {
988 self.0 == 0x01
989 }
990
991 /// # Returns
992 ///
993 /// If this message indicates the operation was accepted without checks, but not succeeded yet
994 pub fn accepted_blind(&self) -> bool {
995 self.0 == 0x40
996 }
997}
998
999impl Display for Ack1Arg {
1000 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
1001 if self.failed() {
1002 write!(f, "ack1: (failed)")
1003 } else if self.accepted() {
1004 write!(f, "ack1: (accepted)")
1005 } else if self.accepted_blind() {
1006 write!(f, "ack1: (accepted_blind)")
1007 } else {
1008 write!(f, "ack1: (success, ack: {})", self.0,)
1009 }
1010 }
1011}
1012
1013/// Indicates which source type the input came from
1014#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
1015pub enum SourceType {
1016 /// Switch is connected over a DS54 port
1017 Ds54Aux,
1018 /// Switch is directly accessible
1019 Switch,
1020}
1021
1022/// A sensors detection state
1023#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
1024pub enum SensorLevel {
1025 /// The sensor detects some energy flow (sensor on)
1026 High,
1027 /// The sensor detects no energy flow (sensor off)
1028 Low,
1029}
1030
1031impl std::ops::Not for SensorLevel {
1032 type Output = SensorLevel;
1033
1034 fn not(self) -> Self::Output {
1035 match self {
1036 SensorLevel::High => SensorLevel::Low,
1037 SensorLevel::Low => SensorLevel::High,
1038 }
1039 }
1040}
1041
1042/// Represents an sensor input argument
1043#[derive(Debug, Copy, Clone, Eq, Hash, PartialEq)]
1044pub struct InArg {
1045 /// The sensors argument
1046 address: u16,
1047 /// The sensors source type
1048 input_source: SourceType,
1049 /// The sensors detection state
1050 sensor_level: SensorLevel,
1051 /// The sensors control bit that is reserved to future use
1052 control_bit: bool,
1053}
1054
1055impl InArg {
1056 /// Creates a new sensors input argument
1057 ///
1058 /// # Parameters
1059 ///
1060 /// - `address`: The sensors address (0 - 2047)
1061 /// - `input_source`: The sensors input source type
1062 /// - `sensor_level`: The sensors state (High = On, Low = Off)
1063 /// - `control_bit`: Control bit that is reserved for future use.
1064 pub fn new(
1065 address: u16,
1066 input_source: SourceType,
1067 sensor_level: SensorLevel,
1068 control_bit: bool,
1069 ) -> Self {
1070 InArg {
1071 address: address & 0x07FF,
1072 input_source,
1073 sensor_level,
1074 control_bit,
1075 }
1076 }
1077
1078 /// Parses the sensors information from two bytes `in1` and `in2`
1079 pub(crate) fn parse(in1: u8, in2: u8) -> Self {
1080 let mut address = in1 as u16;
1081 address |= (in2 as u16 & 0x0F) << 7;
1082
1083 let input_source = if in2 & 0x20 == 0 {
1084 SourceType::Ds54Aux
1085 } else {
1086 SourceType::Switch
1087 };
1088
1089 let sensor_level = if (in2 & 0x10) != 0 {
1090 SensorLevel::High
1091 } else {
1092 SensorLevel::Low
1093 };
1094 let control_bit = (in2 & 0x40) != 0;
1095 Self {
1096 address,
1097 input_source,
1098 sensor_level,
1099 control_bit,
1100 }
1101 }
1102
1103 /// # Returns
1104 ///
1105 /// The address of this sensor
1106 pub fn address(&self) -> u16 {
1107 self.address
1108 }
1109
1110 /// # Returns
1111 ///
1112 /// The address with the sensors source type set as least significant bit
1113 pub fn address_ds54(&self) -> u16 {
1114 (self.address << 1)
1115 | match self.input_source {
1116 SourceType::Switch => 1,
1117 SourceType::Ds54Aux => 0,
1118 }
1119 }
1120
1121 /// # Returns
1122 ///
1123 /// The sensors source type
1124 pub fn input_source(&self) -> SourceType {
1125 self.input_source
1126 }
1127
1128 /// # Returns
1129 ///
1130 /// The sensors state (High = On, Low = Off)
1131 pub fn sensor_level(&self) -> SensorLevel {
1132 self.sensor_level
1133 }
1134
1135 /// # Returns
1136 ///
1137 /// The sensors control bit
1138 pub fn control_bit(&self) -> bool {
1139 self.control_bit
1140 }
1141
1142 /// Sets the address of this sensor argument
1143 ///
1144 /// # Parameters
1145 ///
1146 /// - `address`: The address to set (0 - 2047)
1147 pub fn set_address(&mut self, address: u16) {
1148 if address <= 0x07FF {
1149 self.address = address;
1150 }
1151 }
1152
1153 /// Sets the address with the sensors source type as least significant bit
1154 ///
1155 /// # Parameters
1156 ///
1157 /// - `address_ds54`: The address and as least significant the source type
1158 pub fn set_address_ds54(&mut self, address_ds54: u16) {
1159 if address_ds54 <= 0x0FFF {
1160 self.input_source = if address_ds54 & 1 == 0 {
1161 SourceType::Ds54Aux
1162 } else {
1163 SourceType::Switch
1164 };
1165 self.set_address(address_ds54 >> 1);
1166 }
1167 }
1168
1169 /// Sets the sensors input source type
1170 ///
1171 /// # Parameters
1172 ///
1173 /// - `input_source`: The input source the sensor used
1174 pub fn set_input_source(&mut self, input_source: SourceType) {
1175 self.input_source = input_source;
1176 }
1177
1178 /// Sets the sensors activation state
1179 ///
1180 /// # Parameters
1181 ///
1182 /// - `sensor_level`: The activation state to use (High = ON, Low = OFF)
1183 pub fn set_sensor_level(&mut self, sensor_level: SensorLevel) {
1184 self.sensor_level = sensor_level;
1185 }
1186
1187 /// Sets the control bit of this sensor arg to the given value.
1188 ///
1189 /// # Parameters
1190 ///
1191 /// - `control_bit`: The bit to set
1192 pub fn set_control_bit(&mut self, control_bit: bool) {
1193 self.control_bit = control_bit;
1194 }
1195
1196 /// Parses this sensors least significant address bit in one byte
1197 pub(crate) fn in1(&self) -> u8 {
1198 self.address as u8 & 0x7F
1199 }
1200
1201 /// Parses this sensors most significant address bit and its input source type
1202 /// as well as the sensor activation state and control bit in one byte,
1203 pub(crate) fn in2(&self) -> u8 {
1204 let mut in2 = ((self.address >> 7) as u8) & 0x0F;
1205 in2 |= match self.input_source {
1206 SourceType::Ds54Aux => 0x00,
1207 SourceType::Switch => 0x20,
1208 };
1209 in2 |= match self.sensor_level {
1210 SensorLevel::High => 0x10,
1211 SensorLevel::Low => 0x00,
1212 };
1213 if self.control_bit {
1214 in2 |= 0x40;
1215 }
1216 in2
1217 }
1218}
1219
1220/// Metainformation for a device
1221#[derive(Copy, Clone, Eq, Hash, PartialEq, Debug)]
1222pub enum SnArg {
1223 /// The devices meta information by device type
1224 /// - 0: Device address
1225 /// - 1: If this device is a switch
1226 /// - 2: If this device is active
1227 SwitchType(u16, bool, bool),
1228 /// The devices meta information by output
1229 /// - 0: Device address
1230 /// - 1: The activation state of the straight switch part
1231 /// - 2: The activation state of the curved switch part
1232 SwitchDirectionStatus(u16, SensorLevel, SensorLevel),
1233}
1234
1235impl SnArg {
1236 /// Parses the sensors information from two bytes `sn1` and `sn2`
1237 pub(crate) fn parse(sn1: u8, sn2: u8) -> Self {
1238 let mut address = sn1 as u16;
1239 address |= (sn2 as u16 & 0x0F) << 7;
1240
1241 let format = sn2 & 0x40 == 0x40;
1242
1243 let t = sn2 & 0x10 == 0x10;
1244 let c = sn2 & 0x20 == 0x20;
1245
1246 if format {
1247 SnArg::SwitchType(address, c, t)
1248 } else {
1249 SnArg::SwitchDirectionStatus(
1250 address,
1251 if c {
1252 SensorLevel::High
1253 } else {
1254 SensorLevel::Low
1255 },
1256 if t {
1257 SensorLevel::High
1258 } else {
1259 SensorLevel::Low
1260 },
1261 )
1262 }
1263 }
1264
1265 /// # Returns
1266 ///
1267 /// The device address
1268 pub fn address(&self) -> u16 {
1269 match *self {
1270 SnArg::SwitchType(address, ..) => address,
1271 SnArg::SwitchDirectionStatus(address, ..) => address,
1272 }
1273 }
1274
1275 /// # Returns
1276 ///
1277 /// Parses this low address bits in a writeable byte
1278 pub(crate) fn sn1(&self) -> u8 {
1279 (match *self {
1280 SnArg::SwitchDirectionStatus(address, ..) => address,
1281 SnArg::SwitchType(address, ..) => address,
1282 } as u8)
1283 & 0x7F
1284 }
1285
1286 /// # Returns
1287 ///
1288 /// Parses the status information and the high address bits into a writeable byte
1289 pub(crate) fn sn2(&self) -> u8 {
1290 match *self {
1291 SnArg::SwitchType(address, is_switch, state) => {
1292 let mut sn2 = ((address >> 7) as u8 & 0x0F) | 0x40;
1293
1294 sn2 |= if is_switch { 0x20 } else { 0x00 };
1295 sn2 | if state { 0x10 } else { 0x00 }
1296 }
1297 SnArg::SwitchDirectionStatus(address, straight_status, curved_status) => {
1298 let mut sn2 = (address >> 7) as u8 & 0x0F;
1299
1300 sn2 |= match straight_status {
1301 SensorLevel::High => 0x20,
1302 SensorLevel::Low => 0x00,
1303 };
1304 sn2 | match curved_status {
1305 SensorLevel::High => 0x10,
1306 SensorLevel::Low => 0x00,
1307 }
1308 }
1309 }
1310 }
1311}
1312
1313/// Id of the slot controlling device
1314///
1315/// - 0: No ID being used
1316/// - 00/80 - 3F/81: ID shows PC usage
1317/// - 00/02 - 3F/83: System reserved
1318/// - 00/04 - 3F/FE: normal throttle range
1319#[derive(Debug, Copy, Clone, Eq, Hash, PartialEq)]
1320pub struct IdArg(u16);
1321
1322impl IdArg {
1323 /// Creates a new device id
1324 ///
1325 /// # Parameters
1326 ///
1327 /// - `id`: A fourteen bit device address
1328 pub fn new(id: u16) -> Self {
1329 IdArg(id & 0x3FFF)
1330 }
1331
1332 /// Parses the device id from two bytes `id1` and `id2`
1333 pub(crate) fn parse(id1: u8, id2: u8) -> Self {
1334 IdArg((((id2 & 0x7F) as u16) << 7) | ((id1 & 0x7F) as u16))
1335 }
1336
1337 /// # Returns
1338 ///
1339 /// The device `id`
1340 pub fn id(&self) -> u16 {
1341 self.0
1342 }
1343
1344 /// # Returns
1345 ///
1346 /// The seven least significant address bits
1347 pub(crate) fn id1(&self) -> u8 {
1348 self.0 as u8 & 0x7F
1349 }
1350
1351 /// # Returns
1352 ///
1353 /// The seven most significant address bits
1354 pub(crate) fn id2(&self) -> u8 {
1355 (self.0 >> 7) as u8 & 0x7F
1356 }
1357}
1358
1359/// Represents power information for a specific railway sector
1360#[derive(Debug, Copy, Clone, Eq, Hash, PartialEq)]
1361pub struct MultiSenseArg {
1362 /// This messages three bit represented type
1363 m_type: u8,
1364 /// The present state
1365 present: bool,
1366 /// The board address corresponding to this message
1367 board_address: u8,
1368 /// The zone corresponding to this message
1369 zone: u8,
1370}
1371
1372impl MultiSenseArg {
1373 /// Creates new power information for a specified railway sector
1374 ///
1375 /// # Parameters
1376 ///
1377 /// - `m_type`: The messages type
1378 /// - `present`: The present state of the sender
1379 /// - `board_address`: The board address
1380 /// - `zone`: The zone address
1381 pub fn new(m_type: u8, present: bool, board_address: u8, zone: u8) -> Self {
1382 Self {
1383 m_type: m_type & 0x07,
1384 present,
1385 board_address,
1386 zone,
1387 }
1388 }
1389
1390 /// Parses the power information id from two bytes `m_high` and `zas`
1391 pub(crate) fn parse(m_high: u8, zas: u8) -> Self {
1392 let m_type = (0xE0 & m_high) >> 5;
1393 let present = 0x10 & m_high == 0x10;
1394 let board_address = ((0x0F & m_high) << 4) | ((zas & 0xF0) >> 4);
1395 let zone = 0x0F & zas;
1396
1397 MultiSenseArg {
1398 m_type,
1399 present,
1400 board_address,
1401 zone,
1402 }
1403 }
1404
1405 /// # Returns
1406 ///
1407 /// The three bit message type
1408 pub fn m_type(&self) -> u8 {
1409 self.m_type
1410 }
1411
1412 /// # Returns
1413 ///
1414 /// The senders present status
1415 pub fn present(&self) -> bool {
1416 self.present
1417 }
1418
1419 /// # Returns
1420 ///
1421 /// The sections board address
1422 pub fn board_address(&self) -> u8 {
1423 self.board_address
1424 }
1425
1426 /// # Returns
1427 ///
1428 /// The sections zone
1429 pub fn zone(&self) -> u8 {
1430 self.zone
1431 }
1432
1433 /// # Returns
1434 ///
1435 /// One byte holding the least significant board address and zone bits
1436 pub(crate) fn zas(&self) -> u8 {
1437 self.zone | ((self.board_address & 0x0F) << 4)
1438 }
1439
1440 /// # Returns
1441 ///
1442 /// The low address bits as well as the messages type and present status as one byte
1443 pub(crate) fn m_high(&self) -> u8 {
1444 ((self.board_address & 0xF0) >> 4)
1445 | ((self.m_type & 0x07) << 5)
1446 | if self.present { 0x10 } else { 0x00 }
1447 }
1448}
1449
1450/// The functions group
1451#[derive(Debug, Copy, Clone, Eq, Hash, PartialEq)]
1452pub enum FunctionGroup {
1453 /// Function bits 9, 10 and 11 are available
1454 F9TO11,
1455 /// Function bits 13 to 19 are available
1456 F13TO19,
1457 /// Function bits 12, 20 and 28 are available
1458 F12F20F28,
1459 /// Function bit 21 to 27 are available
1460 F21TO27,
1461}
1462
1463/// Represents the function bits of one function group.
1464///
1465/// - 0: The functions group type
1466/// - 1: The functions bits set
1467#[derive(Copy, Clone, Eq, Hash, PartialEq)]
1468pub struct FunctionArg(u8, u8);
1469
1470impl FunctionArg {
1471 /// Creates a new function arg for a given group.
1472 ///
1473 /// # Parameters
1474 ///
1475 /// - `group`: The functions group to set the values to.
1476 pub fn new(group: FunctionGroup) -> Self {
1477 FunctionArg(
1478 match group {
1479 FunctionGroup::F9TO11 => 0x07,
1480 FunctionGroup::F13TO19 => 0x08,
1481 FunctionGroup::F12F20F28 => 0x05,
1482 FunctionGroup::F21TO27 => 0x09,
1483 },
1484 0,
1485 )
1486 }
1487
1488 /// Parses the group and function bits from two bits.
1489 pub(crate) fn parse(group: u8, function: u8) -> Self {
1490 FunctionArg(group, function)
1491 }
1492
1493 /// # Returns
1494 ///
1495 /// The value of the `f_num`s function bit value if this bit is contained in
1496 /// this args function group.
1497 pub fn f(&self, f_num: u8) -> bool {
1498 if f_num > 8 && f_num < 12 && self.0 == 0x07 {
1499 (self.1 >> (f_num - 5)) & 1 != 0
1500 } else if (f_num == 12 || f_num == 20 || f_num == 28) && self.0 == 0x05 {
1501 (self.1
1502 >> (if f_num == 12 {
1503 4
1504 } else if f_num == 20 {
1505 5
1506 } else {
1507 6
1508 }))
1509 & 1
1510 != 0
1511 } else if f_num > 12 && f_num < 20 && self.0 == 0x08 {
1512 (self.1 >> (f_num - 13)) & 1 != 0
1513 } else if f_num > 20 && f_num < 28 && self.0 == 0x09 {
1514 (self.1 >> (f_num - 21)) & 1 != 0
1515 } else {
1516 false
1517 }
1518 }
1519
1520 /// Sets the `f_num` function bits value, if it is present in this args function group.
1521 ///
1522 /// # Parameters
1523 ///
1524 /// - `f_num`: The bit to set
1525 /// - `value`: The bits value
1526 ///
1527 /// # Returns
1528 ///
1529 /// A mutable reference of this struct instance.
1530 pub fn set_f(&mut self, f_num: u8, value: bool) -> &mut Self {
1531 let mask = if f_num > 8 && f_num < 12 && self.0 == 0x07 {
1532 1 << (f_num - 5)
1533 } else if (f_num == 12 || f_num == 20 || f_num == 28) && self.0 == 0x05 {
1534 1 << (if f_num == 12 {
1535 0
1536 } else if f_num == 20 {
1537 1
1538 } else {
1539 2
1540 })
1541 } else if f_num > 12 && f_num < 20 && self.0 == 0x08 {
1542 1 << (f_num - 13)
1543 } else if f_num > 20 && f_num < 28 && self.0 == 0x09 {
1544 1 << (f_num - 21)
1545 } else {
1546 0x00
1547 };
1548
1549 if value {
1550 self.1 |= mask;
1551 } else {
1552 self.1 &= !mask;
1553 }
1554
1555 self
1556 }
1557
1558 /// # Returns
1559 ///
1560 /// The function group specifying which function values may be set.
1561 pub fn function_group(&self) -> FunctionGroup {
1562 match self.0 {
1563 0x07 => FunctionGroup::F9TO11,
1564 0x05 => FunctionGroup::F12F20F28,
1565 0x08 => FunctionGroup::F13TO19,
1566 0x09 => FunctionGroup::F21TO27,
1567 _ => FunctionGroup::F9TO11,
1568 }
1569 }
1570
1571 /// # Returns
1572 ///
1573 /// The functions group represented as one byte.
1574 pub(crate) fn group(&self) -> u8 {
1575 self.0
1576 }
1577
1578 /// # Returns
1579 ///
1580 /// The function bits represented as one byte.
1581 pub(crate) fn function(&self) -> u8 {
1582 self.1
1583 }
1584}
1585
1586/// Overriding debug to only display the relevant function bits.
1587impl Debug for FunctionArg {
1588 /// Prints the group corresponding function bit values.
1589 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
1590 match self.function_group() {
1591 FunctionGroup::F9TO11 => {
1592 write!(
1593 f,
1594 "function_arg: (group: {:?}, f9: {}, f10: {}, f11: {})",
1595 FunctionGroup::F9TO11,
1596 self.f(9),
1597 self.f(10),
1598 self.f(11)
1599 )
1600 }
1601 FunctionGroup::F13TO19 => {
1602 write!(f,
1603 "function_arg: (group: {:?}, f13: {}, f14: {}, f15: {}, f16: {}, f17: {}, f18: {}, f19: {})",
1604 FunctionGroup::F13TO19,
1605 self.f(13),
1606 self.f(14),
1607 self.f(15),
1608 self.f(16),
1609 self.f(17),
1610 self.f(18),
1611 self.f(19),
1612 )
1613 }
1614 FunctionGroup::F12F20F28 => {
1615 write!(
1616 f,
1617 "function_arg: (group: {:?}, f12: {}, f20: {}, f28: {})",
1618 FunctionGroup::F12F20F28,
1619 self.f(12),
1620 self.f(20),
1621 self.f(28)
1622 )
1623 }
1624 FunctionGroup::F21TO27 => {
1625 write!(f,
1626 "function_arg: (group: {:?}, f21: {}, f22: {}, f23: {}, f24: {}, f25: {}, f26: {}, f27: {})",
1627 FunctionGroup::F21TO27,
1628 self.f(21),
1629 self.f(22),
1630 self.f(23),
1631 self.f(24),
1632 self.f(25),
1633 self.f(26),
1634 self.f(27)
1635 )
1636 }
1637 }
1638 }
1639}
1640
1641/// Representing the command mode used to write to the programming track
1642///
1643/// # Type Codes Table
1644///
1645/// | [Pcmd::byte_mode] | [Pcmd::ops_mode] | [Pcmd::ty0] | [Pcmd::ty1] | Mode |
1646/// |-------------------|------------------|-------------|-------------|---------------------------------|
1647/// | 0 | 0 | 0 | 0 | Abort operation |
1648/// | 1 | 0 | 0 | 0 | Paged mode |
1649/// | x | 0 | 0 | 1 | Direct mode |
1650/// | x | 0 | 1 | 0 | Physical register |
1651/// | x | 0 | 1 | 1 | service track reserved function |
1652/// | x | 1 | 0 | 0 | no feedback |
1653/// | x | 1 | 0 | 0 | feedback |
1654#[derive(Debug, Copy, Clone, Eq, Hash, PartialEq)]
1655pub struct Pcmd {
1656 /// Whether to write or if `false` read
1657 write: bool,
1658 /// Whether to use byte or bitwise operation mode
1659 byte_mode: bool,
1660 /// Whether to use the main track or the programming track
1661 ops_mode: bool,
1662 /// First programing type select bit
1663 ty0: bool,
1664 /// Second programming type select bit
1665 ty1: bool,
1666}
1667
1668impl Pcmd {
1669 /// Creates a new programm control argument
1670 ///
1671 /// For near information on `ty0` and `ty1` see [Pcmd].
1672 ///
1673 /// # Parameters
1674 ///
1675 /// - `write`: Whether to write or read
1676 /// - `byte_mode`: Whether to use bytewise or bitwise mode
1677 /// - `ops_mode`: Whether to use the main track or the programming track
1678 /// - `ty0`: See [Pcmd]
1679 /// - `ty1`: See [Pcmd]
1680 pub fn new(write: bool, byte_mode: bool, ops_mode: bool, ty0: bool, ty1: bool) -> Self {
1681 Pcmd {
1682 write,
1683 byte_mode,
1684 ops_mode,
1685 ty0,
1686 ty1,
1687 }
1688 }
1689
1690 /// Reads the programming control information from one byte
1691 pub(crate) fn parse(pcmd: u8) -> Self {
1692 let write = pcmd & 0x20 == 0x20;
1693 let byte_mode = pcmd & 0x40 == 0x40;
1694 let ops_mode = pcmd & 0x02 == 0x02;
1695 let ty0 = pcmd & 0x80 == 0x80;
1696 let ty1 = pcmd & 0x01 == 0x01;
1697
1698 Pcmd {
1699 write,
1700 byte_mode,
1701 ops_mode,
1702 ty0,
1703 ty1,
1704 }
1705 }
1706
1707 /// # Returns
1708 ///
1709 /// Whether to write or read
1710 pub fn write(&self) -> bool {
1711 self.write
1712 }
1713
1714 /// # Returns
1715 ///
1716 /// Whether to use byte or bit mode
1717 pub fn byte_mode(&self) -> bool {
1718 self.byte_mode
1719 }
1720
1721 /// # Returns
1722 ///
1723 /// Whether to use the main or programming track
1724 pub fn ops_mode(&self) -> bool {
1725 self.ops_mode
1726 }
1727
1728 /// See [Pcmd]
1729 pub fn ty0(&self) -> bool {
1730 self.ty0
1731 }
1732
1733 /// See [Pcmd]
1734 pub fn ty1(&self) -> bool {
1735 self.ty1
1736 }
1737
1738 /// Sets the write argument
1739 ///
1740 /// # Parameters
1741 ///
1742 /// - `write`: Whether to write or read
1743 pub fn set_write(&mut self, write: bool) {
1744 self.write = write
1745 }
1746
1747 /// Sets the byte_mode argument
1748 ///
1749 /// # Parameters
1750 ///
1751 /// - `byte_mode`: Whether to use byte or bit mode
1752 pub fn set_byte_mode(&mut self, byte_mode: bool) {
1753 self.byte_mode = byte_mode
1754 }
1755
1756 /// Sets the ops_mode argument
1757 ///
1758 /// # Parameters
1759 ///
1760 /// - `ops_mode`: Whether to use the main or programming track
1761 pub fn set_ops_mode(&mut self, ops_mode: bool) {
1762 self.ops_mode = ops_mode
1763 }
1764
1765 /// See [Pcmd]
1766 pub fn set_ty0(&mut self, ty0: bool) {
1767 self.ty0 = ty0
1768 }
1769
1770 /// See [Pcmd]
1771 pub fn set_ty1(&mut self, ty1: bool) {
1772 self.ty1 = ty1
1773 }
1774
1775 /// # Returns
1776 ///
1777 /// Parses the programming information data into one representing byte
1778 pub(crate) fn pcmd(&self) -> u8 {
1779 let mut pcmd = if self.write { 0x20 } else { 0x00 };
1780 if self.byte_mode {
1781 pcmd |= 0x40;
1782 }
1783 if self.ops_mode {
1784 pcmd |= 0x02;
1785 }
1786 if self.ty0 {
1787 pcmd |= 0x80;
1788 }
1789 if self.ty1 {
1790 pcmd |= 0x01;
1791 }
1792 pcmd
1793 }
1794}
1795
1796/// Holding programming error flags
1797#[derive(Debug, Copy, Clone, Eq, Hash, PartialEq)]
1798pub struct PStat {
1799 /// User canceled operation
1800 user_aborted: bool,
1801 /// No read acknowledgment
1802 no_read_ack: bool,
1803 /// No write acknowledgment
1804 no_write_ack: bool,
1805 /// No train on the programming track to programm
1806 programming_track_empty: bool,
1807}
1808
1809impl PStat {
1810 /// Creates new programming error information
1811 ///
1812 /// # Parameters
1813 ///
1814 /// - `user_aborted`: If an user canceled the programming operation
1815 /// - `no_read_ack`: No read acknowledgment received
1816 /// - `no_write_ack`: No write acknowledgment received
1817 /// - `programming_track_empty`: No train is on the programming track
1818 pub fn new(
1819 user_aborted: bool,
1820 no_read_ack: bool,
1821 no_write_ack: bool,
1822 programming_track_empty: bool,
1823 ) -> Self {
1824 PStat {
1825 user_aborted,
1826 no_read_ack,
1827 no_write_ack,
1828 programming_track_empty,
1829 }
1830 }
1831
1832 /// Parses the error flags from one byte
1833 pub(crate) fn parse(stat: u8) -> Self {
1834 let user_aborted = stat & 0x01 == 0x01;
1835 let no_read_ack = stat & 0x02 == 0x02;
1836 let no_write_ack = stat & 0x04 == 0x04;
1837 let programming_track_empty = stat & 0x08 == 0x08;
1838
1839 PStat {
1840 user_aborted,
1841 no_read_ack,
1842 no_write_ack,
1843 programming_track_empty,
1844 }
1845 }
1846
1847 /// # Returns
1848 ///
1849 /// If the operation was aborted by a user
1850 pub fn user_aborted(&self) -> bool {
1851 self.user_aborted
1852 }
1853
1854 /// # Returns
1855 ///
1856 /// If the operation was canceled by a missing read acknowledgment
1857 pub fn no_read_ack(&self) -> bool {
1858 self.no_read_ack
1859 }
1860
1861 /// # Returns
1862 ///
1863 /// If the operation was canceled by a missing write acknowledgment
1864 pub fn no_write_ack(&self) -> bool {
1865 self.no_write_ack
1866 }
1867
1868 /// # Returns
1869 ///
1870 /// If no train was found to programm
1871 pub fn programming_track_empty(&self) -> bool {
1872 self.programming_track_empty
1873 }
1874
1875 /// # Returns
1876 ///
1877 /// A byte representing all found error states
1878 pub(crate) fn stat(&self) -> u8 {
1879 let mut stat = if self.user_aborted { 0x01 } else { 0x00 };
1880 if self.no_read_ack {
1881 stat |= 0x02;
1882 }
1883 if self.no_write_ack {
1884 stat |= 0x04;
1885 }
1886 if self.programming_track_empty {
1887 stat |= 0x08;
1888 }
1889 stat
1890 }
1891}
1892
1893/// Holds control variables and data arguments.
1894#[derive(Copy, Clone, Eq, Hash, PartialEq, Default)]
1895pub struct CvDataArg(u16, u8);
1896
1897impl CvDataArg {
1898 /// Creates a new empty arg.
1899 pub fn new() -> CvDataArg {
1900 CvDataArg(0, 0)
1901 }
1902
1903 /// Parses cv and data from three byte
1904 pub(crate) fn parse(cvh: u8, cvl: u8, data7: u8) -> Self {
1905 let mut cv_arg = cvl as u16;
1906 let data = ((cvh & 0x02) << 6) | data7;
1907
1908 let mut high_cv_arg = cvh & 0x01;
1909 high_cv_arg |= (cvh & 0x30) >> 3;
1910
1911 cv_arg |= (high_cv_arg as u16) << 7;
1912
1913 CvDataArg(cv_arg, data)
1914 }
1915
1916 /// # Parameters
1917 ///
1918 /// - `d_num`: Wich data bit to return (Value must be between 0 and 7 (inclusive))
1919 ///
1920 /// # Returns
1921 ///
1922 /// The data bit specified by `d_num`
1923 pub fn data(&self, d_num: u8) -> bool {
1924 (self.1 >> d_num) & 0x01 != 0
1925 }
1926
1927 /// # Parameters
1928 ///
1929 /// - `cv_num`: Wich cv bit to return (Value must be between 0 and 9 (inclusive))
1930 ///
1931 /// # Returns
1932 ///
1933 /// The cv bit specified by `cv_num`
1934 pub fn cv(&self, cv_num: u8) -> bool {
1935 self.0 >> cv_num & 1 != 0
1936 }
1937
1938 /// Sets the specified data bit to the given state
1939 ///
1940 /// # Parameters
1941 ///
1942 /// - `d_num`: Wich data bit to set
1943 /// - `value`: The value to set the data bit to
1944 pub fn set_data(&mut self, d_num: u8, value: bool) -> &mut Self {
1945 let mask = 1 << d_num;
1946
1947 if value {
1948 self.1 |= mask;
1949 } else {
1950 self.1 &= !mask;
1951 }
1952
1953 self
1954 }
1955
1956 /// Sets the specified cv bit to the given state
1957 ///
1958 /// # Parameters
1959 ///
1960 /// - `cv_num`: Wich cv bit to set
1961 /// - `value`: The value to set the cv bit to
1962 pub fn set_cv(&mut self, cv_num: u8, value: bool) -> &mut Self {
1963 let mask = (1 << cv_num) & 0x03FF;
1964
1965 if value {
1966 self.0 |= mask;
1967 } else {
1968 self.0 &= !mask;
1969 }
1970
1971 self
1972 }
1973
1974 /// # Returns
1975 ///
1976 /// The high part of the cv values and the seventh data bit as one byte
1977 pub(crate) fn cvh(&self) -> u8 {
1978 let mut cvh = (self.0 >> 7) as u8;
1979 let high_cv = cvh & 0x06 << 3;
1980 cvh &= 0x01;
1981 cvh |= high_cv;
1982 if self.data(7) {
1983 cvh |= 0x02;
1984 }
1985 cvh
1986 }
1987
1988 /// # Returns
1989 ///
1990 /// The low part of the cv values as one byte
1991 pub(crate) fn cvl(&self) -> u8 {
1992 self.0 as u8 & 0x7F
1993 }
1994
1995 /// # Returns
1996 ///
1997 /// The data bits from 0 to 6 (inclusive) as one byte
1998 pub(crate) fn data7(&self) -> u8 {
1999 self.1 & 0x7F
2000 }
2001}
2002
2003/// Overridden for precise value orientated output
2004impl Debug for CvDataArg {
2005 /// Writes all args and cv values to the formatter
2006 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
2007 write!(
2008 f,
2009 "cv_data_arg: (data: (d0: {}, d1: {}, d2: {}, d3: {}, d4: {}, d5: {}, d6: {}, d7: {}), cv: (cv0: {}, cv1: {}, cv2: {}, cv3: {}, cv4: {}, cv5: {}, cv6: {}, cv7: {}, cv8: {}, cv9: {}))",
2010 self.data(0),
2011 self.data(1),
2012 self.data(2),
2013 self.data(3),
2014 self.data(4),
2015 self.data(5),
2016 self.data(6),
2017 self.data(7),
2018 self.cv(0),
2019 self.cv(1),
2020 self.cv(2),
2021 self.cv(3),
2022 self.cv(4),
2023 self.cv(5),
2024 self.cv(6),
2025 self.cv(7),
2026 self.cv(8),
2027 self.cv(9)
2028 )
2029 }
2030}
2031
2032/// Holding the clocks information
2033#[derive(Debug, Copy, Clone, Eq, Hash, PartialEq)]
2034pub struct FastClock {
2035 /// The clocks tick rate. (0 = Frozen), (x = x to 1 rate),
2036 clk_rate: u8,
2037 /// Intern subminute counter
2038 frac_mins: u16,
2039 /// The clocks minutes
2040 mins: u8,
2041 /// The clocks set hours
2042 hours: u8,
2043 /// The clocks set days
2044 days: u8,
2045 /// The clock control
2046 clk_cntrl: u8,
2047}
2048
2049impl FastClock {
2050 /// Creates a new clock synchronise information
2051 ///
2052 /// # Parameters
2053 ///
2054 /// - `clock_rate`: The clocks tick rate. (0 = Frozen), (x = x to 1 rate)
2055 /// - `frac_mins`: The internal subminute counter
2056 /// - `mins`: The clock mins calculated by 256-MINS%60
2057 /// - `hours`: The clocks hours calculated by 256-HRS%24
2058 /// - `days`: The number of 24 hour cycles passed
2059 /// - `clk_cntrl`: Clock control information. third bit must be true to mark this clock data valid.
2060 pub fn new(clk_rate: u8, frac_mins: u16, mins: u8, hours: u8, days: u8, clk_cntrl: u8) -> Self {
2061 FastClock {
2062 clk_rate,
2063 frac_mins,
2064 mins,
2065 hours,
2066 days,
2067 clk_cntrl,
2068 }
2069 }
2070
2071 /// Calculates the clock information from 7 bytes
2072 ///
2073 /// # Parameters
2074 ///
2075 /// - `clock_rate`: The clocks tick rate. (0 = Frozen), (x = x to 1 rate)
2076 /// - `frac_minsl`: The least significant part of the internal subminute counter
2077 /// - `frac_minsh`: The most significant part of the internal subminute counter
2078 /// - `mins`: The clock mins calculated by 256-MINS%60
2079 /// - `hours`: The clocks hours calculated by 256-HRS%24
2080 /// - `days`: The number of 24 hour cycles passed
2081 /// - `clk_cntrl`: Clock control information. third bit must be true to mark this clock data valid.
2082 fn parse(
2083 clk_rate: u8,
2084 frac_minsl: u8,
2085 frac_minsh: u8,
2086 mins: u8,
2087 hours: u8,
2088 days: u8,
2089 clk_cntrl: u8,
2090 ) -> Self {
2091 FastClock {
2092 clk_rate: clk_rate & 0x7F,
2093 frac_mins: (frac_minsl as u16) | ((frac_minsh as u16) << 8),
2094 mins,
2095 hours,
2096 days,
2097 clk_cntrl,
2098 }
2099 }
2100
2101 /// # Returns
2102 ///
2103 /// The clocks rate
2104 pub fn clk_rate(&self) -> u8 {
2105 self.clk_rate
2106 }
2107
2108 /// # Returns
2109 ///
2110 /// The clocks least significant internal counter part
2111 fn frac_minsl(&self) -> u8 {
2112 self.frac_mins as u8
2113 }
2114
2115 /// # Returns
2116 ///
2117 /// The clocks most significant internal counter part
2118 fn frac_minsh(&self) -> u8 {
2119 (self.frac_mins >> 8) as u8
2120 }
2121
2122 /// # Returns
2123 ///
2124 /// The internal clock counter
2125 pub fn frac_mins(&self) -> u16 {
2126 self.frac_mins
2127 }
2128
2129 /// # Returns
2130 ///
2131 /// The clocks minutes. Represented by (256-MINS%60)
2132 pub fn mins(&self) -> u8 {
2133 self.mins
2134 }
2135
2136 /// # Returns
2137 ///
2138 /// The clocks hours. Represented by (256-HRS%24)
2139 pub fn hours(&self) -> u8 {
2140 self.hours
2141 }
2142
2143 /// # Retuns
2144 ///
2145 /// The count of 24 hour cycles passed
2146 pub fn days(&self) -> u8 {
2147 self.days
2148 }
2149
2150 /// # Returns
2151 ///
2152 /// General clock control information.
2153 ///
2154 /// The third bit represents the valid state of this message (0 = invalid)
2155 pub fn clk_cntrl(&self) -> u8 {
2156 self.clk_cntrl
2157 }
2158}
2159
2160/// The function bits accessible by the corresponding [ImArg]
2161#[derive(Debug, Copy, Clone, Eq, Hash, PartialEq)]
2162pub enum ImFunctionType {
2163 /// Functions 9 to 12 (inclusive) are accessible
2164 F9to12,
2165 /// Functions 13 to 20 (inclusive) are accessible
2166 F13to20,
2167 /// Functions 21 to 28 (inclusive) are accessible
2168 F21to28,
2169}
2170
2171/// The address in the right format used by the corresponding [ImArg]
2172#[derive(Debug, Copy, Clone, Eq, Hash, PartialEq)]
2173pub enum ImAddress {
2174 /// A short 8 bit address
2175 Short(u8),
2176 /// A long 16 bit address
2177 Long(u16),
2178}
2179
2180/// This arg hold function bit information
2181#[derive(Debug, Copy, Clone, Eq, Hash, PartialEq)]
2182pub struct ImArg {
2183 /// I don't get the concrete meaning and functionality of this arg
2184 dhi: u8,
2185 /// This is the address to set the function bits to
2186 address: ImAddress,
2187 /// This is the functions settable by this arg
2188 function_type: ImFunctionType,
2189 /// This holds the function bits
2190 function_bits: u8,
2191 /// Unused for now, do what you want
2192 im5: u8,
2193}
2194
2195impl ImArg {
2196 /// Creates a new function arg
2197 ///
2198 /// # Parameters
2199 ///
2200 /// - `dhi`: I don't get the concrete meaning and functionality of this arg
2201 /// - `address`: The address to set the function bits for
2202 /// - `function_type`: Wich functions should be settable
2203 /// - `im5`: Unused parameter
2204 pub fn new(dhi: u8, address: ImAddress, function_type: ImFunctionType, im5: u8) -> Self {
2205 ImArg {
2206 dhi,
2207 address,
2208 function_type,
2209 function_bits: 0x00,
2210 im5,
2211 }
2212 }
2213
2214 /// Calculates the information of one im arg from eight bytes
2215 ///
2216 /// # Parameters
2217 ///
2218 /// - `_`: Not used, as it was always the same value
2219 /// - `reps`: The function bits range type
2220 /// - `dhi`: Not understood by me
2221 /// - `im1-5`: The address and function bits
2222 pub(crate) fn parse(
2223 _: u8,
2224 reps: u8,
2225 dhi: u8,
2226 im1: u8,
2227 im2: u8,
2228 im3: u8,
2229 im4: u8,
2230 im5: u8,
2231 ) -> ImArg {
2232 if reps == 0x44 || (reps == 0x34 && (im3 & 0x20) == 0x20) {
2233 let address = ImAddress::Long(((im2 as u16) << 8) | im1 as u16);
2234
2235 let function_type = if im3 == 0x5E {
2236 ImFunctionType::F13to20
2237 } else if im3 == 0x5F {
2238 ImFunctionType::F21to28
2239 } else {
2240 ImFunctionType::F9to12
2241 };
2242 let mut function_bits = match function_type {
2243 ImFunctionType::F21to28 => im4,
2244 ImFunctionType::F13to20 => im4,
2245 ImFunctionType::F9to12 => im3 & !0x20,
2246 };
2247
2248 function_bits &= 0x7F;
2249
2250 Self {
2251 dhi,
2252 address,
2253 function_type,
2254 function_bits,
2255 im5,
2256 }
2257 } else {
2258 let address = ImAddress::Short(im1);
2259
2260 let function_type = if im2 == 0x5E {
2261 ImFunctionType::F13to20
2262 } else if im2 == 0x5F {
2263 ImFunctionType::F21to28
2264 } else {
2265 ImFunctionType::F9to12
2266 };
2267 let mut function_bits = match function_type {
2268 ImFunctionType::F13to20 => im3,
2269 ImFunctionType::F21to28 => im3,
2270 ImFunctionType::F9to12 => im2 & !0x2F,
2271 };
2272
2273 function_bits &= 0x7F;
2274
2275 Self {
2276 dhi,
2277 address,
2278 function_type,
2279 function_bits,
2280 im5,
2281 }
2282 }
2283 }
2284
2285 /// # Returns
2286 ///
2287 /// The type of this function arg as one byte
2288 pub(crate) fn reps(&self) -> u8 {
2289 match self.address {
2290 ImAddress::Short(_) => match self.function_type {
2291 ImFunctionType::F9to12 => 0x24,
2292 ImFunctionType::F13to20 => 0x34,
2293 ImFunctionType::F21to28 => 0x34,
2294 },
2295 ImAddress::Long(_) => match self.function_type {
2296 ImFunctionType::F9to12 => 0x34,
2297 ImFunctionType::F13to20 => 0x44,
2298 ImFunctionType::F21to28 => 0x44,
2299 },
2300 }
2301 }
2302
2303 /// # Returns
2304 ///
2305 /// The dhi byte, holding special address and bit information.
2306 pub fn dhi(&self) -> u8 {
2307 self.dhi
2308 }
2309
2310 /// # Returns
2311 ///
2312 /// The address in long or short format
2313 pub fn address(&self) -> ImAddress {
2314 self.address
2315 }
2316
2317 /// # Returns
2318 ///
2319 /// The type specifying wich function bits are settable
2320 pub fn function_type(&self) -> ImFunctionType {
2321 self.function_type
2322 }
2323
2324 /// Calculates the `f_num`s function bit
2325 ///
2326 /// # Parameters
2327 ///
2328 /// - `f_num`: The function bits number to get
2329 ///
2330 /// # Returns
2331 ///
2332 /// The value of the `f_num`s function bit
2333 pub fn f(&self, f_num: u8) -> bool {
2334 let dist = match self.function_type {
2335 ImFunctionType::F13to20 => 21,
2336 ImFunctionType::F21to28 => 13,
2337 ImFunctionType::F9to12 => 9,
2338 };
2339
2340 (self.function_bits >> (f_num - dist)) & 0x01 == 0x01
2341 }
2342
2343 /// Sets the `f_num`s function bit to the given value `f`.
2344 ///
2345 /// # Parameters
2346 ///
2347 /// - `f_num`: The function bit to set
2348 /// - `f`: The value to set the function bit to
2349 pub fn set_f(&mut self, f_num: u8, f: bool) {
2350 let dist = match self.function_type {
2351 ImFunctionType::F13to20 => 21,
2352 ImFunctionType::F21to28 => 13,
2353 ImFunctionType::F9to12 => 9,
2354 };
2355
2356 let mask = 0x01 << (f_num - dist);
2357
2358 if f {
2359 self.function_bits |= mask;
2360 } else {
2361 self.function_bits &= !mask;
2362 }
2363 }
2364
2365 /// # Returns
2366 ///
2367 /// The first function arg
2368 pub(crate) fn im1(&self) -> u8 {
2369 match self.address {
2370 ImAddress::Short(adr) => adr,
2371 ImAddress::Long(adr) => adr as u8,
2372 }
2373 }
2374
2375 /// # Returns
2376 ///
2377 /// The second function arg
2378 pub(crate) fn im2(&self) -> u8 {
2379 match self.address {
2380 ImAddress::Short(_) => match self.function_type {
2381 ImFunctionType::F9to12 => (self.function_bits & 0x7F) | 0x20,
2382 ImFunctionType::F13to20 => 0x5E,
2383 ImFunctionType::F21to28 => 0x5F,
2384 },
2385 ImAddress::Long(adr) => (adr >> 8) as u8,
2386 }
2387 }
2388
2389 /// # Returns
2390 ///
2391 /// The third function arg
2392 pub(crate) fn im3(&self) -> u8 {
2393 match self.address {
2394 ImAddress::Short(_) => {
2395 if self.function_type == ImFunctionType::F9to12 {
2396 0x00
2397 } else {
2398 self.function_bits
2399 }
2400 }
2401 ImAddress::Long(_) => match self.function_type {
2402 ImFunctionType::F9to12 => (self.function_bits & 0x7F) | 0x20,
2403 ImFunctionType::F13to20 => 0x5E,
2404 ImFunctionType::F21to28 => 0x5F,
2405 },
2406 }
2407 }
2408
2409 /// # Returns
2410 ///
2411 /// The fourth function arg
2412 pub(crate) fn im4(&self) -> u8 {
2413 if self.reps() == 0x34 && self.function_type != ImFunctionType::F9to12 {
2414 return self.function_bits;
2415 }
2416 0x00
2417 }
2418
2419 /// # Returns
2420 ///
2421 /// The fifth function arg
2422 pub(crate) fn im5(&self) -> u8 {
2423 self.im5
2424 }
2425}
2426
2427/// Holds messages for writing data to slots
2428#[derive(Debug, Copy, Clone, Eq, Hash, PartialEq)]
2429pub enum WrSlDataStructure {
2430 /// Represents clock sync information
2431 ///
2432 /// # Parameters
2433 ///
2434 /// - `FastClock`: The clock information
2435 /// - `TrkArg`: The track
2436 /// - `IdArg`: The ID of the slots user
2437 DataTime(FastClock, TrkArg, IdArg),
2438 /// Creates new data to write to the programming track
2439 ///
2440 /// # Parameters
2441 ///
2442 /// - `Pcmd`: The programming command to use
2443 /// - `AddressArg`: Operation mode programming bits as address
2444 /// - `TrkArg`: The current track information to set
2445 /// - `CvDataArg`: The command value and data bits to programm
2446 DataPt(Pcmd, AddressArg, TrkArg, CvDataArg),
2447 /// Represents a general message to write data to one specified slot
2448 ///
2449 /// # Parameters
2450 ///
2451 /// - `SlotArg`: The slot to write to
2452 /// - `Stat1Arg`: The slots general status information
2453 /// - `Stat2Arg`: Additional slot status information
2454 /// - `AddressArg`: The slots corresponding address
2455 /// - `SpeedArg`: The slots set speed
2456 /// - `DirfArg`: The direction and low function bits
2457 /// - `TrkArg`: The general track information
2458 /// - `SndArg`: Additional function bits
2459 /// - `IdArg`: The ID of the slots user
2460 DataGeneral(
2461 SlotArg,
2462 Stat1Arg,
2463 Stat2Arg,
2464 AddressArg,
2465 SpeedArg,
2466 DirfArg,
2467 TrkArg,
2468 SndArg,
2469 IdArg,
2470 ),
2471}
2472
2473impl WrSlDataStructure {
2474 /// Parses eleven incoming bytes to one write slot data message
2475 pub(crate) fn parse(
2476 arg1: u8,
2477 arg2: u8,
2478 arg3: u8,
2479 arg4: u8,
2480 arg5: u8,
2481 arg6: u8,
2482 arg7: u8,
2483 arg8: u8,
2484 arg9: u8,
2485 arg10: u8,
2486 arg11: u8,
2487 ) -> Self {
2488 if arg1 == 0x7C {
2489 WrSlDataStructure::DataPt(
2490 Pcmd::parse(arg2),
2491 AddressArg::parse(arg4, arg5),
2492 TrkArg::parse(arg6),
2493 CvDataArg::parse(arg7, arg8, arg9),
2494 )
2495 } else if arg1 == 0x7B {
2496 WrSlDataStructure::DataTime(
2497 FastClock::parse(arg2, arg3, arg4, arg5, arg7, arg8, arg9),
2498 TrkArg::parse(arg6),
2499 IdArg::parse(arg10, arg11),
2500 )
2501 } else {
2502 WrSlDataStructure::DataGeneral(
2503 SlotArg::parse(arg1),
2504 Stat1Arg::parse(arg2),
2505 Stat2Arg::parse(arg7),
2506 AddressArg::parse(arg8, arg3),
2507 SpeedArg::parse(arg4),
2508 DirfArg::parse(arg5),
2509 TrkArg::parse(arg6),
2510 SndArg::parse(arg9),
2511 IdArg::parse(arg10, arg11),
2512 )
2513 }
2514 }
2515
2516 /// # Returns
2517 ///
2518 /// The slot this message is written to
2519 pub fn slot_type(&self) -> u8 {
2520 match self {
2521 WrSlDataStructure::DataPt(..) => 0x7C,
2522 WrSlDataStructure::DataTime(..) => 0x7B,
2523 WrSlDataStructure::DataGeneral(slot, ..) => slot.slot(),
2524 }
2525 }
2526
2527 /// # Returns
2528 ///
2529 /// This message as a sequence of 13 bytes
2530 pub(crate) fn to_message(self) -> Vec<u8> {
2531 match self {
2532 WrSlDataStructure::DataPt(pcmd, adr, trk, cv_data) => {
2533 vec![
2534 0xEF,
2535 0x0E,
2536 0x7C,
2537 pcmd.pcmd(),
2538 0x00,
2539 adr.adr2(),
2540 adr.adr1(),
2541 trk.trk_arg(),
2542 cv_data.cvh(),
2543 cv_data.cvl(),
2544 cv_data.data7(),
2545 0x00,
2546 0x00,
2547 ]
2548 }
2549 WrSlDataStructure::DataTime(fast_clock, trk, id) => {
2550 vec![
2551 0xEF,
2552 0x0E,
2553 0x7B,
2554 fast_clock.clk_rate(),
2555 fast_clock.frac_minsl(),
2556 fast_clock.frac_minsh(),
2557 fast_clock.mins(),
2558 trk.trk_arg(),
2559 fast_clock.hours(),
2560 fast_clock.days(),
2561 fast_clock.clk_cntrl(),
2562 id.id1(),
2563 id.id2(),
2564 ]
2565 }
2566 WrSlDataStructure::DataGeneral(
2567 slot,
2568 stat1,
2569 stat2,
2570 adr,
2571 speed,
2572 dirf,
2573 trk,
2574 sound,
2575 id,
2576 ) => {
2577 vec![
2578 0xEF,
2579 0x0E,
2580 slot.slot(),
2581 stat1.stat1(),
2582 adr.adr1(),
2583 speed.spd(),
2584 dirf.dirf(),
2585 trk.trk_arg(),
2586 stat2.stat2(),
2587 adr.adr2(),
2588 sound.snd(),
2589 id.id1(),
2590 id.id2(),
2591 ]
2592 }
2593 }
2594 }
2595}
2596
2597/// Lissy IR reports status information
2598#[derive(Debug, Copy, Clone, Eq, Hash, PartialEq)]
2599pub struct LissyIrReport {
2600 arg1: u8,
2601 dir: bool,
2602 unit: u16,
2603 address: u16,
2604}
2605
2606impl LissyIrReport {
2607 /// Creates a new report
2608 ///
2609 /// # Parameters
2610 ///
2611 /// - `dir`: The direction
2612 /// - `unit`: The reports unit
2613 /// - `address`: The reports address
2614 pub fn new(dir: bool, unit: u16, address: u16) -> Self {
2615 LissyIrReport {
2616 arg1: 0x00,
2617 dir,
2618 unit,
2619 address,
2620 }
2621 }
2622
2623 /// Parses the report information from five bytes
2624 ///
2625 /// # Parameters
2626 ///
2627 /// - `arg1`: Specifies the report type
2628 /// - `high_unit`: The most significant unit bits and the direction
2629 /// - `low_unit`: The least significant unit bits
2630 /// - `high_adr`: The most significant address bits
2631 /// - `low_adr`: The least significant address bits
2632 pub(crate) fn parse(arg1: u8, high_unit: u8, low_unit: u8, high_adr: u8, low_adr: u8) -> Self {
2633 let dir = high_unit & 0x40 == 0x40;
2634 let unit = (((high_unit & 0x3F) as u16) << 7) | (low_unit as u16);
2635 let address = (((high_adr & 0x7F) as u16) << 7) | (low_adr as u16);
2636
2637 LissyIrReport {
2638 arg1,
2639 dir,
2640 unit,
2641 address,
2642 }
2643 }
2644
2645 /// # Returns
2646 ///
2647 /// This message represented by a vector of seven bytes
2648 pub(crate) fn to_message(self) -> Vec<u8> {
2649 let mut high_unit = ((self.unit >> 7) as u8) & 0x3F;
2650 if self.dir {
2651 high_unit |= 0x40;
2652 }
2653 let low_unit = self.unit as u8 & 0x7F;
2654 let high_adr = ((self.address >> 7) as u8) & 0x7F;
2655 let low_adr = self.address as u8 & 0x7F;
2656 vec![
2657 0xE4, 0x08, self.arg1, high_unit, low_unit, high_adr, low_adr,
2658 ]
2659 }
2660
2661 /// # Returns
2662 ///
2663 /// The messages type byte
2664 pub fn arg1(&self) -> u8 {
2665 self.arg1
2666 }
2667
2668 /// # Returns
2669 ///
2670 /// The direction
2671 pub fn dir(&self) -> bool {
2672 self.dir
2673 }
2674
2675 /// # Returns
2676 ///
2677 /// The unit of this message
2678 pub fn unit(&self) -> u16 {
2679 self.unit
2680 }
2681
2682 /// # Returns
2683 ///
2684 /// The messages address
2685 pub fn address(&self) -> u16 {
2686 self.address
2687 }
2688}
2689
2690/// Holds report information of a rfid5 report message
2691#[derive(Debug, Copy, Clone, Eq, Hash, PartialEq)]
2692pub struct RFID5Report {
2693 arg1: u8,
2694 address: u16,
2695 rfid0: u8,
2696 rfid1: u8,
2697 rfid2: u8,
2698 rfid3: u8,
2699 rfid4: u8,
2700 rfid_hi: u8,
2701}
2702
2703impl RFID5Report {
2704 /// Creates new report information
2705 ///
2706 /// # Parameters
2707 ///
2708 /// - `address`: The reporters address
2709 /// - `rfid0` - `rfid4` and `rfid_hi`: The reported rfid values
2710 pub fn new(
2711 address: u16,
2712 rfid0: u8,
2713 rfid1: u8,
2714 rfid2: u8,
2715 rfid3: u8,
2716 rfid4: u8,
2717 rfid_hi: u8,
2718 ) -> Self {
2719 RFID5Report {
2720 arg1: 0x41,
2721 address,
2722 rfid0,
2723 rfid1,
2724 rfid2,
2725 rfid3,
2726 rfid4,
2727 rfid_hi,
2728 }
2729 }
2730
2731 /// Parses this message from nine bytes
2732 ///
2733 /// # Parameters
2734 ///
2735 /// - `arg1`: This reports type byte
2736 /// - `high_adr`: This most significant address part
2737 /// - `low_adr`: This least significant address part
2738 /// - `rfid0` - `rfid4` and `rfid_hi`: The reported rfid values
2739 pub(crate) fn parse(
2740 arg1: u8,
2741 high_adr: u8,
2742 low_adr: u8,
2743 rfid0: u8,
2744 rfid1: u8,
2745 rfid2: u8,
2746 rfid3: u8,
2747 rfid4: u8,
2748 rfid_hi: u8,
2749 ) -> Self {
2750 let address = (((high_adr & 0x7F) as u16) << 7) | (low_adr as u16);
2751 RFID5Report {
2752 arg1,
2753 address,
2754 rfid0,
2755 rfid1,
2756 rfid2,
2757 rfid3,
2758 rfid4,
2759 rfid_hi,
2760 }
2761 }
2762
2763 /// # Returns
2764 ///
2765 /// This message parsed represented by 11 bytes
2766 pub(crate) fn to_message(self) -> Vec<u8> {
2767 let high_adr = ((self.address >> 7) as u8) & 0x7F;
2768 let low_adr = (self.address as u8) & 0x7F;
2769 vec![
2770 0xE4,
2771 0x0C,
2772 self.arg1,
2773 high_adr,
2774 low_adr,
2775 self.rfid0,
2776 self.rfid1,
2777 self.rfid2,
2778 self.rfid3,
2779 self.rfid4,
2780 self.rfid_hi,
2781 ]
2782 }
2783
2784 /// # Returns
2785 ///
2786 /// The messages type byte
2787 pub fn arg1(&self) -> u8 {
2788 self.arg1
2789 }
2790
2791 /// # Returns
2792 ///
2793 /// The reporters address
2794 pub fn address(&self) -> u16 {
2795 self.address
2796 }
2797
2798 /// # Returns
2799 ///
2800 /// The first reported rfid byte
2801 pub fn rfid0(&self) -> u8 {
2802 self.rfid0
2803 }
2804
2805 /// # Returns
2806 ///
2807 /// The second reported rfid byte
2808 pub fn rfid1(&self) -> u8 {
2809 self.rfid1
2810 }
2811
2812 /// # Returns
2813 ///
2814 /// The third reported rfid byte
2815 pub fn rfid2(&self) -> u8 {
2816 self.rfid2
2817 }
2818
2819 /// # Returns
2820 ///
2821 /// The fourth reported rfid byte
2822 pub fn rfid3(&self) -> u8 {
2823 self.rfid3
2824 }
2825
2826 /// # Returns
2827 ///
2828 /// The fifth reported rfid byte
2829 pub fn rfid4(&self) -> u8 {
2830 self.rfid4
2831 }
2832
2833 /// # Returns
2834 ///
2835 /// The last reported rfid byte
2836 pub fn rfid_hi(&self) -> u8 {
2837 self.rfid_hi
2838 }
2839}
2840
2841/// Holds report information of a rfid7 report message
2842#[derive(Debug, Copy, Clone, Eq, Hash, PartialEq)]
2843pub struct RFID7Report {
2844 arg1: u8,
2845 address: u16,
2846 rfid0: u8,
2847 rfid1: u8,
2848 rfid2: u8,
2849 rfid3: u8,
2850 rfid4: u8,
2851 rfid5: u8,
2852 rfid6: u8,
2853 rfid_hi: u8,
2854}
2855
2856impl RFID7Report {
2857 /// Creates new report information
2858 ///
2859 /// # Parameters
2860 ///
2861 /// - `address`: The reporters address
2862 /// - `rfid0` - `rfid6` and `rfid_hi`: The reported rfid values
2863 pub fn new(
2864 address: u16,
2865 rfid0: u8,
2866 rfid1: u8,
2867 rfid2: u8,
2868 rfid3: u8,
2869 rfid4: u8,
2870 rfid5: u8,
2871 rfid6: u8,
2872 rfid_hi: u8,
2873 ) -> Self {
2874 RFID7Report {
2875 arg1: 0x41,
2876 address,
2877 rfid0,
2878 rfid1,
2879 rfid2,
2880 rfid3,
2881 rfid4,
2882 rfid5,
2883 rfid6,
2884 rfid_hi,
2885 }
2886 }
2887
2888 /// Parses this message from eleven bytes
2889 ///
2890 /// # Parameters
2891 ///
2892 /// - `arg1`: This reports type byte
2893 /// - `high_adr`: This most significant address part
2894 /// - `low_adr`: This least significant address part
2895 /// - `rfid0` - `rfid6` and `rfid_hi`: The reported rfid values
2896 pub(crate) fn parse(
2897 arg1: u8,
2898 high_adr: u8,
2899 low_adr: u8,
2900 rfid0: u8,
2901 rfid1: u8,
2902 rfid2: u8,
2903 rfid3: u8,
2904 rfid4: u8,
2905 rfid5: u8,
2906 rfid6: u8,
2907 rfid_hi: u8,
2908 ) -> Self {
2909 let address = (((high_adr & 0x7F) as u16) << 7) | (low_adr as u16);
2910 RFID7Report {
2911 arg1,
2912 address,
2913 rfid0,
2914 rfid1,
2915 rfid2,
2916 rfid3,
2917 rfid4,
2918 rfid5,
2919 rfid6,
2920 rfid_hi,
2921 }
2922 }
2923
2924 /// # Returns
2925 ///
2926 /// This message represented by 13 bytes
2927 pub(crate) fn to_message(self) -> Vec<u8> {
2928 let high_adr = ((self.address >> 7) as u8) & 0x7F;
2929 let low_adr = (self.address as u8) & 0x7F;
2930 vec![
2931 0xE4,
2932 0x0E,
2933 self.arg1,
2934 high_adr,
2935 low_adr,
2936 self.rfid0,
2937 self.rfid1,
2938 self.rfid2,
2939 self.rfid3,
2940 self.rfid4,
2941 self.rfid5,
2942 self.rfid6,
2943 self.rfid_hi,
2944 ]
2945 }
2946
2947 /// # Returns
2948 ///
2949 /// The messages type byte
2950 pub fn arg1(&self) -> u8 {
2951 self.arg1
2952 }
2953
2954 /// # Returns
2955 ///
2956 /// The reporters address
2957 pub fn address(&self) -> u16 {
2958 self.address
2959 }
2960
2961 /// # Returns
2962 ///
2963 /// The first reported rfid byte
2964 pub fn rfid0(&self) -> u8 {
2965 self.rfid0
2966 }
2967
2968 /// # Returns
2969 ///
2970 /// The second reported rfid byte
2971 pub fn rfid1(&self) -> u8 {
2972 self.rfid1
2973 }
2974
2975 /// # Returns
2976 ///
2977 /// The third reported rfid byte
2978 pub fn rfid2(&self) -> u8 {
2979 self.rfid2
2980 }
2981
2982 /// # Returns
2983 ///
2984 /// The fourth reported rfid byte
2985 pub fn rfid3(&self) -> u8 {
2986 self.rfid3
2987 }
2988
2989 /// # Returns
2990 ///
2991 /// The fifth reported rfid byte
2992 pub fn rfid4(&self) -> u8 {
2993 self.rfid4
2994 }
2995
2996 /// # Returns
2997 ///
2998 /// The sixth reported rfid byte
2999 pub fn rfid5(&self) -> u8 {
3000 self.rfid5
3001 }
3002
3003 /// # Returns
3004 ///
3005 /// The seventh reported rfid byte
3006 pub fn rfid6(&self) -> u8 {
3007 self.rfid6
3008 }
3009
3010 /// # Returns
3011 ///
3012 /// The last reported rfid byte
3013 pub fn rfid_hi(&self) -> u8 {
3014 self.rfid_hi
3015 }
3016}
3017
3018/// Holds wheel counter report information
3019#[derive(Debug, Copy, Clone, Eq, Hash, PartialEq)]
3020pub struct WheelcntReport {
3021 arg1: u8,
3022 unit: u16,
3023 direction: bool,
3024 count: u16,
3025}
3026
3027impl WheelcntReport {
3028 /// Creates new wheel counter report information
3029 ///
3030 /// # Parameters
3031 ///
3032 /// - `unit`: The reports unit
3033 /// - `direction`: The reports direction
3034 /// - `count`: The reports wheel count
3035 pub fn new(unit: u16, direction: bool, count: u16) -> Self {
3036 WheelcntReport {
3037 arg1: 0x40,
3038 unit,
3039 direction,
3040 count,
3041 }
3042 }
3043
3044 /// Parses the wheel count information from five bytes
3045 ///
3046 /// # Parameters
3047 ///
3048 /// - `arg1`: The reports type byte
3049 /// - `high_unit`: The most significant unit bits and the direction
3050 /// - `low_unit`: The least significant unit bits
3051 /// - `high_count`: The most significant count bits
3052 /// - `low_count`: The least significant count bits
3053 pub(crate) fn parse(
3054 arg1: u8,
3055 high_unit: u8,
3056 low_unit: u8,
3057 high_count: u8,
3058 low_count: u8,
3059 ) -> Self {
3060 let count = ((high_count as u16) << 7) | (low_count as u16);
3061 let direction = high_unit & 0x40 == 0x40;
3062 let unit = (((high_unit & 0x3F) as u16) << 7) | (low_unit as u16);
3063 WheelcntReport {
3064 arg1,
3065 unit,
3066 direction,
3067 count,
3068 }
3069 }
3070
3071 /// # Returns
3072 ///
3073 /// This message represented by seven bytes
3074 pub(crate) fn to_message(self) -> Vec<u8> {
3075 let mut high_unit = ((self.unit >> 7) as u8) & 0x3F;
3076 if self.direction {
3077 high_unit |= 0x40;
3078 }
3079 let low_unit = self.unit as u8 & 0x7F;
3080 let high_count = ((self.count >> 7) as u8) & 0x7F;
3081 let low_count = self.count as u8 & 0x7F;
3082 vec![
3083 0xE4, 0x08, self.arg1, high_unit, low_unit, high_count, low_count,
3084 ]
3085 }
3086
3087 /// # Returns
3088 ///
3089 /// This reports type byte
3090 pub fn arg1(&self) -> u8 {
3091 self.arg1
3092 }
3093
3094 /// # Returns
3095 ///
3096 /// The unit of this report
3097 pub fn unit(&self) -> u16 {
3098 self.unit
3099 }
3100
3101 /// # Returns
3102 ///
3103 /// The count hold by this message
3104 pub fn count(&self) -> u16 {
3105 self.count
3106 }
3107
3108 /// # Returns
3109 ///
3110 /// This messages direction
3111 pub fn direction(&self) -> bool {
3112 self.direction
3113 }
3114}
3115
3116/// Represents a report message
3117#[derive(Debug, Copy, Clone, Eq, Hash, PartialEq)]
3118pub enum RepStructure {
3119 /// A Lissy IR report
3120 LissyIrReport(LissyIrReport),
3121 /// A rfid5 report
3122 RFID5Report(RFID5Report),
3123 /// A rfid7 report
3124 RFID7Report(RFID7Report),
3125 /// A wheel count report
3126 WheelcntReport(WheelcntReport),
3127}
3128
3129impl RepStructure {
3130 /// Parses a report message from the given bytes
3131 ///
3132 /// # Parameters
3133 ///
3134 /// - `count`: The messages length
3135 /// - `args`: The messages arguments to parse
3136 pub(crate) fn parse(count: u8, args: &[u8]) -> Result<Self, MessageParseError> {
3137 if args[0] == 0x00 {
3138 if count != 0x08 {
3139 Err(MessageParseError::UnexpectedEnd(0xE4))
3140 } else {
3141 Ok(Self::LissyIrReport(LissyIrReport::parse(
3142 args[0], args[1], args[2], args[3], args[4],
3143 )))
3144 }
3145 } else if args[0] == 0x40 {
3146 if count != 0x08 {
3147 Err(MessageParseError::UnexpectedEnd(0xE4))
3148 } else {
3149 Ok(Self::WheelcntReport(WheelcntReport::parse(
3150 args[0], args[1], args[2], args[3], args[4],
3151 )))
3152 }
3153 } else if args[0] == 0x41 && count == 0x0C {
3154 Ok(Self::RFID5Report(RFID5Report::parse(
3155 args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8],
3156 )))
3157 } else if args[0] == 0x41 && count == 0x0E {
3158 Ok(Self::RFID7Report(RFID7Report::parse(
3159 args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8],
3160 args[9], args[10],
3161 )))
3162 } else {
3163 Err(MessageParseError::InvalidFormat(
3164 "The report message (opcode: 0xE4) was in invalid format!".into(),
3165 ))
3166 }
3167 }
3168}
3169
3170/// The destination slot to move data to
3171#[derive(Debug, Copy, Clone, Eq, Hash, PartialEq)]
3172pub struct DstArg(u16);
3173
3174impl DstArg {
3175 /// Creates a new destination slot
3176 ///
3177 /// # Parameters
3178 ///
3179 /// - `dst`: The destination
3180 pub fn new(dst: u16) -> Self {
3181 DstArg(dst)
3182 }
3183
3184 /// Parses the destination from two bytes
3185 ///
3186 /// # Parameters
3187 ///
3188 /// - `dst_low`: The seven least significant destination address bytes
3189 /// - `dst_high`: The seven most significant destination address bytes
3190 pub(crate) fn parse(dst_low: u8, dst_high: u8) -> Self {
3191 let dst = ((dst_high as u16) << 7) | (dst_low as u16);
3192 DstArg(dst)
3193 }
3194
3195 /// # Returns
3196 ///
3197 /// The destination address of the slot move
3198 pub fn dst(&self) -> u16 {
3199 self.0
3200 }
3201
3202 /// # Returns
3203 ///
3204 /// The seven least significant destination address bits
3205 pub(crate) fn dst_low(&self) -> u8 {
3206 self.0 as u8 & 0x7F
3207 }
3208
3209 /// # Returns
3210 ///
3211 /// The seven most significant destination address bits
3212 pub(crate) fn dst_high(&self) -> u8 {
3213 (self.0 >> 7) as u8 & 0x7F
3214 }
3215}
3216
3217/// Holds eight movable bytes and peer data
3218#[derive(Debug, Copy, Clone, Eq, Hash, PartialEq)]
3219pub struct PxctData {
3220 pxc: u8,
3221 d1: u8,
3222 d2: u8,
3223 d3: u8,
3224 d4: u8,
3225 d5: u8,
3226 d6: u8,
3227 d7: u8,
3228 d8: u8,
3229}
3230
3231impl PxctData {
3232 /// Creates new peer data
3233 ///
3234 /// # Parameters
3235 ///
3236 /// - `pxc`: The peer data
3237 /// - `d1` - `d8`: The data
3238 pub fn new(pxc: u8, d1: u8, d2: u8, d3: u8, d4: u8, d5: u8, d6: u8, d7: u8, d8: u8) -> Self {
3239 PxctData {
3240 pxc,
3241 d1,
3242 d2,
3243 d3,
3244 d4,
3245 d5,
3246 d6,
3247 d7,
3248 d8,
3249 }
3250 }
3251
3252 /// Parses the data from 10 bytes
3253 ///
3254 /// # Parameters
3255 ///
3256 /// - `pxct1`, `pxct2`: The peer data
3257 /// - `d1` - `d8`: The data
3258 pub(crate) fn parse(
3259 pxct1: u8,
3260 d1: u8,
3261 d2: u8,
3262 d3: u8,
3263 d4: u8,
3264 pxct2: u8,
3265 d5: u8,
3266 d6: u8,
3267 d7: u8,
3268 d8: u8,
3269 ) -> Self {
3270 let pxc = ((pxct1 & 0x70) >> 4) | ((pxct2 & 0x70) >> 1);
3271
3272 PxctData {
3273 pxc,
3274 d1: d1 | ((pxct1 & 0x01) << 6),
3275 d2: d2 | ((pxct1 & 0x02) << 5),
3276 d3: d3 | ((pxct1 & 0x04) << 4),
3277 d4: d4 | ((pxct1 & 0x08) << 3),
3278 d5: d5 | ((pxct2 & 0x01) << 6),
3279 d6: d6 | ((pxct2 & 0x02) << 5),
3280 d7: d7 | ((pxct2 & 0x04) << 4),
3281 d8: d8 | ((pxct2 & 0x08) << 3),
3282 }
3283 }
3284
3285 /// # Returns
3286 ///
3287 /// The peer data
3288 pub fn pxc(&self) -> u8 {
3289 self.pxc
3290 }
3291
3292 /// # Returns
3293 ///
3294 /// The low part of the peer data and one data bit of the first four the data bits
3295 pub(crate) fn pxct1(&self) -> u8 {
3296 let mut pxct1 = (self.pxc & 0x07) << 4;
3297
3298 if self.d1 & 0x40 == 0x40 {
3299 pxct1 |= 0x01;
3300 }
3301 if self.d2 & 0x40 == 0x40 {
3302 pxct1 |= 0x02;
3303 }
3304 if self.d3 & 0x40 == 0x40 {
3305 pxct1 |= 0x04;
3306 }
3307 if self.d4 & 0x40 == 0x40 {
3308 pxct1 |= 0x08;
3309 }
3310
3311 pxct1
3312 }
3313
3314 /// # Returns
3315 ///
3316 /// The high part of the peer data and one data bit of the last four the data bits
3317 pub(crate) fn pxct2(&self) -> u8 {
3318 let mut pxct2 = (self.pxc & 0x78) << 1;
3319
3320 if self.d5 & 0x40 == 0x40 {
3321 pxct2 |= 0x01;
3322 }
3323 if self.d6 & 0x40 == 0x40 {
3324 pxct2 |= 0x02;
3325 }
3326 if self.d7 & 0x40 == 0x40 {
3327 pxct2 |= 0x04;
3328 }
3329 if self.d8 & 0x40 == 0x40 {
3330 pxct2 |= 0x08;
3331 }
3332
3333 pxct2
3334 }
3335
3336 /// # Returns
3337 ///
3338 /// The first data byte to move
3339 pub fn d1(&self) -> u8 {
3340 self.d1 & 0x3F
3341 }
3342
3343 /// # Returns
3344 ///
3345 /// The second data byte to move
3346 pub fn d2(&self) -> u8 {
3347 self.d2 & 0x3F
3348 }
3349
3350 /// # Returns
3351 ///
3352 /// The third data byte to move
3353 pub fn d3(&self) -> u8 {
3354 self.d3 & 0x3F
3355 }
3356
3357 /// # Returns
3358 ///
3359 /// The fourth data byte to move
3360 pub fn d4(&self) -> u8 {
3361 self.d4 & 0x3F
3362 }
3363
3364 /// # Returns
3365 ///
3366 /// The fifth data byte to move
3367 pub fn d5(&self) -> u8 {
3368 self.d5 & 0x3F
3369 }
3370
3371 /// # Returns
3372 ///
3373 /// The sixth data byte to move
3374 pub fn d6(&self) -> u8 {
3375 self.d6 & 0x3F
3376 }
3377
3378 /// # Returns
3379 ///
3380 /// The seventh data byte to move
3381 pub fn d7(&self) -> u8 {
3382 self.d7 & 0x3F
3383 }
3384
3385 /// # Returns
3386 ///
3387 /// The eighth data byte to move
3388 pub fn d8(&self) -> u8 {
3389 self.d8 & 0x3F
3390 }
3391}
3392
3393/// Send when service mode is aborted
3394///
3395/// As I do not now how this message is structured this message bytes is for now open to use.
3396/// Please feel free to contribute to provide a more powerful version of this arg
3397#[derive(Debug, Copy, Clone, Eq, Hash, PartialEq)]
3398pub struct ProgrammingAbortedArg {
3399 /// The count of args to write to the message 0x10 or 0x15
3400 pub arg_len: u8,
3401 /// The first argument
3402 pub arg01: u8,
3403 /// The second argument
3404 pub arg02: u8,
3405 /// The third argument
3406 pub arg03: u8,
3407 /// The fourth argument
3408 pub arg04: u8,
3409 /// The fifth argument
3410 pub arg05: u8,
3411 /// The sixth argument
3412 pub arg06: u8,
3413 /// The seventh argument
3414 pub arg07: u8,
3415 /// The eighth argument
3416 pub arg08: u8,
3417 /// The ninth argument
3418 pub arg09: u8,
3419 /// The tenth argument
3420 pub arg10: u8,
3421 /// The eleventh argument
3422 pub arg11: u8,
3423 /// The twelfth argument
3424 pub arg12: u8,
3425 /// The thirteenth argument
3426 pub arg13: u8,
3427 /// The fourteenth argument
3428 pub arg14: u8,
3429 /// The fifteenth argument
3430 pub arg15: u8,
3431 /// The sixteenth argument
3432 pub arg16: u8,
3433 /// The seventeenth argument
3434 pub arg17: u8,
3435 /// The eighteenth argument
3436 pub arg18: u8,
3437}
3438
3439impl ProgrammingAbortedArg {
3440 /// Creates a new service mode aborted message.
3441 ///
3442 /// # Parameters
3443 ///
3444 /// - `len`: The messages length (0x10 or 0x15)
3445 /// - `args`: The argument values. 0x10 = 0 - 12 filled, 0x15 = 0 - 17 filled
3446 pub fn new(len: u8, args: &[u8]) -> Self {
3447 ProgrammingAbortedArg::parse(len, args)
3448 }
3449
3450 /// Parses a new service mode aborted message.
3451 ///
3452 /// # Parameters
3453 ///
3454 /// - `len`: The messages length (0x10 or 0x15)
3455 /// - `args`: The argument values. 0x10 = 0 - 12 filled, 0x15 = 0 - 17 filled
3456 pub(crate) fn parse(len: u8, args: &[u8]) -> Self {
3457 match len {
3458 0x10 => ProgrammingAbortedArg {
3459 arg_len: len,
3460 arg01: args[0],
3461 arg02: args[1],
3462 arg03: args[2],
3463 arg04: args[3],
3464 arg05: args[4],
3465 arg06: args[5],
3466 arg07: args[6],
3467 arg08: args[7],
3468 arg09: args[8],
3469 arg10: args[9],
3470 arg11: args[10],
3471 arg12: args[11],
3472 arg13: args[12],
3473 arg14: 0,
3474 arg15: 0,
3475 arg16: 0,
3476 arg17: 0,
3477 arg18: 0,
3478 },
3479
3480 0x15 => ProgrammingAbortedArg {
3481 arg_len: len,
3482 arg01: args[0],
3483 arg02: args[1],
3484 arg03: args[2],
3485 arg04: args[3],
3486 arg05: args[4],
3487 arg06: args[5],
3488 arg07: args[6],
3489 arg08: args[7],
3490 arg09: args[8],
3491 arg10: args[9],
3492 arg11: args[10],
3493 arg12: args[11],
3494 arg13: args[12],
3495 arg14: args[13],
3496 arg15: args[14],
3497 arg16: args[15],
3498 arg17: args[16],
3499 arg18: args[17],
3500 },
3501 _ => ProgrammingAbortedArg {
3502 arg_len: len,
3503 arg01: *args.first().unwrap_or(&0u8),
3504 arg02: *args.get(1).unwrap_or(&0u8),
3505 arg03: *args.get(2).unwrap_or(&0u8),
3506 arg04: *args.get(3).unwrap_or(&0u8),
3507 arg05: *args.get(4).unwrap_or(&0u8),
3508 arg06: *args.get(5).unwrap_or(&0u8),
3509 arg07: *args.get(6).unwrap_or(&0u8),
3510 arg08: *args.get(7).unwrap_or(&0u8),
3511 arg09: *args.get(8).unwrap_or(&0u8),
3512 arg10: *args.get(9).unwrap_or(&0u8),
3513 arg11: *args.get(10).unwrap_or(&0u8),
3514 arg12: *args.get(11).unwrap_or(&0u8),
3515 arg13: *args.get(12).unwrap_or(&0u8),
3516 arg14: *args.get(13).unwrap_or(&0u8),
3517 arg15: *args.get(14).unwrap_or(&0u8),
3518 arg16: *args.get(15).unwrap_or(&0u8),
3519 arg17: *args.get(16).unwrap_or(&0u8),
3520 arg18: *args.get(17).unwrap_or(&0u8),
3521 },
3522 }
3523 }
3524
3525 /// # Returns
3526 ///
3527 /// This message as a count of bytes
3528 pub(crate) fn to_message(self) -> Vec<u8> {
3529 match self.arg_len {
3530 0x10 => vec![
3531 0xE6, 0x10, self.arg01, self.arg02, self.arg03, self.arg04, self.arg05, self.arg06,
3532 self.arg07, self.arg08, self.arg09, self.arg10, self.arg11, self.arg12, self.arg13,
3533 ],
3534 _ => vec![
3535 0xE6, 0x15, self.arg01, self.arg02, self.arg03, self.arg04, self.arg05, self.arg06,
3536 self.arg07, self.arg08, self.arg09, self.arg10, self.arg11, self.arg12, self.arg13,
3537 self.arg14, self.arg15, self.arg16, self.arg17, self.arg18,
3538 ],
3539 }
3540 }
3541}