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}