arinc_429/
lib.rs

1//!
2//! Common types for ARINC 429 communication
3//!
4//! # Serialization/Deserialization
5//!
6//! When compiled with the `serde` feature, all types support serialization and deserialization.
7//!
8
9#![doc(html_root_url = "https://docs.rs/arinc_429/0.1.5")]
10#![cfg_attr(not(feature = "std"), no_std)]
11
12pub mod constants;
13
14#[cfg(feature = "serde")]
15#[macro_use]
16extern crate serde;
17
18#[cfg(feature = "std")]
19use std as base;
20#[cfg(not(feature = "std"))]
21use core as base;
22
23mod parity_error;
24pub use self::parity_error::ParityError;
25
26/// An ARINC 429 message
27///
28/// The bits of a message are represented exactly as transmitted on the wires, with the least
29/// significant bit transmitted first.
30///
31/// The label field is in the 8 least significant bits. Because the most significant digit of the
32/// label is transmitted first, the label field is in the reverse of the usual bit order.
33///
34/// The parity bit is the most significant bit.
35///
36/// # Conversions
37///
38/// The `u32::from(Message)` and `Message::from(u32)` `From` implementations copy bits with no
39/// changes.
40///
41/// Some ARINC 429 adapters use a different representation, where the bits of the label field are
42/// reversed from their on-wire representation. The methods `Message::from_bits_label_swapped()` and
43/// `Message::bits_label_swapped()` implement this conversion.
44///
45/// Conversions never panic.
46///
47/// # Examples
48///
49/// Create a message
50///
51/// ```
52/// # use arinc_429::Message;
53/// let message = Message::from(0x10000056);
54/// assert_eq!(0x10000056, u32::from(message));
55/// ```
56///
57/// Label bit swapping
58///
59/// ```
60/// # use arinc_429::Message;
61/// let message = Message::from_bits_label_swapped(0x10000056);
62/// assert_eq!(0x1000006a, u32::from(message));
63/// ```
64///
65#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
66#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
67pub struct Message(u32);
68
69impl Message {
70    /// Returns the bits that represent this message
71    pub fn bits(&self) -> u32 {
72        self.0
73    }
74
75    /// Returns the bits of this message, but
76    /// with the order of the 8 label bits reversed.
77    pub fn bits_label_swapped(&self) -> u32 {
78        let bits = self.bits();
79        Self::swap_label_bits(bits)
80    }
81
82    /// Creates a message from a message representation with the 8 label bits
83    /// reversed. The returned Message will be represented as transmitted on the wires.
84    pub fn from_bits_label_swapped(bits: u32) -> Self {
85        let bits = Self::swap_label_bits(bits);
86        Message(bits)
87    }
88
89    /// Checks the parity of this message, and returns an error if the parity is not odd
90    ///
91    /// # Examples
92    ///
93    /// ```
94    /// # use arinc_429::Message;
95    /// assert!(Message::from(0x0).check_parity().is_err());
96    /// assert!(Message::from(0xf03ccccc).check_parity().is_err());
97    /// assert!(Message::from(0x1).check_parity().is_ok());
98    /// assert!(Message::from(0xf13ccccc).check_parity().is_ok());
99    /// ```
100    ///
101    pub fn check_parity(&self) -> Result<(), ParityError> {
102        // Should have an odd number of ones
103        if self.0.count_ones() % 2 == 1 {
104            Ok(())
105        } else {
106            let parity = (self.0 >> 31) as u8;
107            let expected = parity ^ 1;
108            Err(ParityError::new(expected, parity))
109        }
110    }
111
112    /// Calculates the parity of this message and returns a new message with the parity bit (31) to
113    /// the correct value
114    ///
115    /// # Examples
116    ///
117    /// ```
118    /// # use arinc_429::Message;
119    /// // Create a message with incorrect (even) parity
120    /// let message = Message::from(0x22443300);
121    /// assert_eq!(message.update_parity().bits(), 0xa2443300);
122    /// ```
123    ///
124    /// ```
125    /// # use arinc_429::Message;
126    /// // Create a message with correct (odd) parity
127    /// let message = Message::from(0x22443301);
128    /// // Message should not change
129    /// assert_eq!(message.update_parity(), message);
130    /// ```
131    ///
132    pub fn update_parity(&self) -> Message {
133        match self.check_parity() {
134            Ok(_) => self.clone(),
135            Err(_) => {
136                // Flip parity bit
137                Message(self.0 ^ 1 << 31)
138            }
139        }
140    }
141
142    /// Returns the label of this message. This can be used to show the label as an octal number.
143    ///
144    /// # Examples
145    ///
146    /// ```
147    /// # use arinc_429::Message;
148    /// let message = Message::from(0x84000109);
149    /// let label = message.label();
150    /// assert_eq!(format!("{:?}", label), "Label(0o220)");
151    /// ```
152    ///
153    /// ```
154    /// # use arinc_429::Message;
155    /// let message = Message::from(0x84000180);
156    /// let label = message.label();
157    /// assert_eq!(format!("{:?}", label), "Label(0o001)");
158    /// ```
159    ///
160    pub fn label(&self) -> Label {
161        let swapped = Self::swap_label_bits(self.0);
162        Label(swapped as u8)
163    }
164
165    /// Reverses the order of the 8 least significant bits of a value.
166    /// Returns bits 32-9 unmodified, but with bits 1-8 reversed.
167    fn swap_label_bits(bits: u32) -> u32 {
168        let label = bits & 0xff;
169        let new_label = ((label & 0x1) << 7) | ((label & 0x2) << 5) | ((label & 0x4) << 3) |
170            ((label & 0x8) << 1) |
171            ((label & 0x10) >> 1) | ((label & 0x20) >> 3) |
172            ((label & 0x40) >> 5) | ((label & 0x80) >> 7);
173        (bits & 0xffffff00) | new_label
174    }
175}
176
177/// A label from a message, displayed in normal bit ordering as an octal number
178// Implementation detail: The enclosed label is stored in normal bit ordering
179pub struct Label(u8);
180
181impl From<u32> for Message {
182    /// Creates a message from bits as transmitted, with no modifications
183    fn from(bits: u32) -> Self {
184        Message(bits)
185    }
186}
187impl From<Message> for u32 {
188    /// Converts a message into bits, with no modifications
189    fn from(Message(bits): Message) -> u32 {
190        bits
191    }
192}
193
194mod msg_fmt {
195    use super::{Message, Label};
196
197    use base::fmt::{Debug, Formatter, Result};
198
199    impl Debug for Message {
200        fn fmt(&self, f: &mut Formatter) -> Result {
201            write!(f, "Message({:#010x})", self.0)
202        }
203    }
204
205    impl Debug for Label {
206        fn fmt(&self, f: &mut Formatter) -> Result {
207            write!(f, "Label({:#05o})", self.0)
208        }
209    }
210
211    #[cfg(all(test, feature = "std"))]
212    mod message_test {
213        use super::super::Message;
214
215        #[test]
216        fn test_zero() {
217            let message = Message::from(0x0);
218            check_debug(&message, "Message(0x00000000)");
219        }
220
221        #[test]
222        fn test_all_ones() {
223            let message = Message::from(0xffffffff);
224            check_debug(&message, "Message(0xffffffff)");
225        }
226
227        fn check_debug(message: &Message, expected: &str) {
228            let actual = format!("{:?}", message);
229            assert_eq!(actual, expected, "Incorrect debug representation");
230        }
231    }
232
233    #[cfg(all(test, feature = "std"))]
234    mod label_test {
235        use super::super::Label;
236
237        #[test]
238        fn test_zero() {
239            let label = Label(0x0);
240            check_debug(&label, "Label(0o000)");
241        }
242
243        #[test]
244        fn test_all_ones() {
245            let label = Label(0xff);
246            check_debug(&label, "Label(0o377)");
247        }
248
249        fn check_debug(label: &Label, expected: &str) {
250            let actual = format!("{:?}", label);
251            assert_eq!(actual, expected, "Incorrect debug representation");
252        }
253    }
254}
255
256/// ARINC 429 communication speeds
257#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
258#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
259#[cfg_attr(feature = "serde", serde(rename = "speed"))]
260#[cfg_attr(feature = "serde", serde(rename_all = "lowercase"))]
261pub enum Speed {
262    /// High speed, 100 kbps
263    High,
264    /// Low speed, 12.5 kbps
265    Low,
266}