1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
//!
//! Common types for ARINC 429 communication
//!
//! # Serialization/Deserialization
//!
//! When compiled with the `serde` feature, all types support serialization and deserialization.
//!

#![doc(html_root_url = "https://docs.rs/arinc_429/0.1.1")]
#![no_std]

#[cfg(feature = "serde")]
#[macro_use]
extern crate serde;

/// An ARINC 429 message
///
/// The bits of a message are represented exactly as transmitted on the wires, with the least
/// significant bit transmitted first.
///
/// The label field is in the 8 least significant bits. Because the most significant digit of the
/// label is transmitted first, the label field is in the reverse of the usual bit order.
///
/// The parity bit is the most significant bit.
///
/// # Conversions
///
/// The `u32::from(Message)` and `Message::from(u32)` `From` implementations copy bits with no
/// changes.
///
/// Some ARINC 429 adapters use a different representation, where the bits of the label field are
/// reversed from their on-wire representation. The methods `Message::from_bits_label_swapped()` and
/// `Message::bits_label_swapped()` implement this conversion.
///
/// Conversions never panic.
///
/// # Examples
///
/// Create a message
///
/// ```
/// use arinc_429::Message;
/// let message = Message::from(0x10000056);
/// assert_eq!(0x10000056, u32::from(message));
/// ```
///
/// Label bit swapping
///
/// ```
/// use arinc_429::Message;
/// let message = Message::from_bits_label_swapped(0x10000056);
/// assert_eq!(0x1000006a, u32::from(message));
/// ```
///
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct Message(u32);

impl Message {
    /// Returns the bits that represent this message
    pub fn bits(&self) -> u32 {
        self.0
    }

    /// Returns the bits of this message, but
    /// with the order of the 8 label bits reversed.
    pub fn bits_label_swapped(&self) -> u32 {
        let bits = self.bits();
        Self::swap_label_bits(bits)
    }

    /// Creates a message from a message representation with the 8 label bits
    /// reversed. The returned Msg429 will be represented as transmitted on the wires.
    pub fn from_bits_label_swapped(bits: u32) -> Self {
        let bits = Self::swap_label_bits(bits);
        Message(bits)
    }

    /// Reverses the order of the 8 least significant bits of a value.
    /// Returns bits 32-9 unmodified, but with bits 1-8 reversed.
    fn swap_label_bits(bits: u32) -> u32 {
        let label = bits & 0xff;
        let new_label = ((label & 0x1) << 7) | ((label & 0x2) << 5) | ((label & 0x4) << 3) |
            ((label & 0x8) << 1) |
            ((label & 0x10) >> 1) | ((label & 0x20) >> 3) |
            ((label & 0x40) >> 5) | ((label & 0x80) >> 7);
        (bits & 0xffffff00) | new_label
    }
}

impl From<u32> for Message {
    /// Creates a message from bits as transmitted, with no modifications
    fn from(bits: u32) -> Self {
        Message(bits)
    }
}
impl From<Message> for u32 {
    /// Converts a message into bits, with no modifications
    fn from(Message(bits): Message) -> u32 {
        bits
    }
}

mod msg_fmt {
    use super::Message;

    use core::fmt::{Debug, Formatter, Result};

    impl Debug for Message {
        fn fmt(&self, f: &mut Formatter) -> Result {
            write!(f, "Msg429({:#x})", self.0)
        }
    }
}

/// ARINC 429 communication speeds
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "serde", serde(rename = "speed"))]
#[cfg_attr(feature = "serde", serde(rename_all = "lowercase"))]
pub enum Speed {
    /// High speed, 100 kbps
    High,
    /// Low speed, 12.5 kbps
    Low,
}