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}