Skip to main content

hardware_registers/i2c/
device_address.rs

1use core::ops::Deref;
2
3/// A device address.
4pub trait DeviceAddress {
5    /// The number of bits of the address.
6    const ADDR_BITS: usize;
7
8    /// Returns the number of bits in the address.
9    #[must_use]
10    fn addr_bits(&self) -> usize {
11        Self::ADDR_BITS
12    }
13}
14
15/// An 7-bit device address.
16#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
17#[allow(clippy::module_name_repetitions)]
18pub struct DeviceAddress7(u8);
19
20impl DeviceAddress7 {
21    /// Constructs a new [`DeviceAddress7`] from a specified value.
22    ///
23    /// To ensure the provided value is a valid 7-bit address, the value is masked
24    /// with `0b0111_1111`.
25    #[must_use]
26    pub const fn new(address: u8) -> Self {
27        Self(address & 0b0111_1111_u8)
28    }
29
30    /// Consumes self and returns the inner value.
31    #[must_use]
32    pub const fn into_inner(self) -> u8 {
33        self.0
34    }
35}
36
37impl DeviceAddress for DeviceAddress7 {
38    const ADDR_BITS: usize = 7;
39}
40
41impl From<u8> for DeviceAddress7 {
42    fn from(value: u8) -> Self {
43        Self::new(value)
44    }
45}
46
47/// A 10-bit device address.
48#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
49#[allow(clippy::module_name_repetitions)]
50pub struct DeviceAddress10(u16);
51
52impl DeviceAddress10 {
53    /// Constructs a new [`DeviceAddress10`] from a specified value.
54    ///
55    /// To ensure the provided value is a valid 10-bit address, the value is masked
56    /// with `0b1111111111`.
57    #[must_use]
58    pub const fn new(address: u16) -> Self {
59        Self(address & 0b0000_0011_1111_1111_u16)
60    }
61
62    /// Consumes self and returns the inner value.
63    #[must_use]
64    pub const fn into_inner(self) -> u16 {
65        self.0
66    }
67}
68
69impl DeviceAddress for DeviceAddress10 {
70    const ADDR_BITS: usize = 10;
71}
72
73impl From<u8> for DeviceAddress10 {
74    fn from(value: u8) -> Self {
75        Self(value.into())
76    }
77}
78
79impl From<u16> for DeviceAddress10 {
80    fn from(value: u16) -> Self {
81        Self::new(value)
82    }
83}
84
85impl From<DeviceAddress7> for DeviceAddress10 {
86    fn from(value: DeviceAddress7) -> Self {
87        Self(value.into_inner().into())
88    }
89}
90
91impl TryFrom<DeviceAddress10> for DeviceAddress7 {
92    type Error = <u16 as TryInto<u8>>::Error;
93
94    fn try_from(value: DeviceAddress10) -> Result<Self, Self::Error> {
95        let value = value.into_inner();
96        let addr_8: u8 = value.try_into()?;
97        Ok(Self(addr_8))
98    }
99}
100
101impl Deref for DeviceAddress7 {
102    type Target = u8;
103
104    fn deref(&self) -> &Self::Target {
105        &self.0
106    }
107}
108
109impl Deref for DeviceAddress10 {
110    type Target = u16;
111
112    fn deref(&self) -> &Self::Target {
113        &self.0
114    }
115}
116
117impl core::fmt::Debug for DeviceAddress7 {
118    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
119        write!(f, "0x{:02X}", self.0)?;
120        f.write_str(" (")?;
121        write!(f, "{:07b}", self.0)?;
122        f.write_str(")")
123    }
124}
125
126impl core::fmt::Debug for DeviceAddress10 {
127    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
128        write!(f, "0x{:03X}", self.0)?;
129        f.write_str(" (")?;
130        write!(f, "{:010b}", self.0)?;
131        f.write_str(")")
132    }
133}
134
135impl core::fmt::Display for DeviceAddress7 {
136    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
137        write!(f, "{self:?}")
138    }
139}
140
141impl core::fmt::Display for DeviceAddress10 {
142    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
143        write!(f, "{self:?}")
144    }
145}
146
147#[cfg(test)]
148mod tests {
149    use super::*;
150
151    #[test]
152    fn dev7_from_u8() {
153        let addr = DeviceAddress7::from(0b111_0000);
154        assert_eq!(addr.into_inner(), 0b111_0000);
155        assert_eq!(addr.addr_bits(), 7);
156    }
157
158    #[test]
159    fn dev10_from_u8() {
160        let addr = DeviceAddress10::from(0b0111_0000_u8);
161        assert_eq!(addr.into_inner(), 0b111_0000);
162        assert_eq!(addr.addr_bits(), 10);
163    }
164
165    #[test]
166    fn dev7_from_u8_masked() {
167        let addr = DeviceAddress7::from(0b1111_0000_u8);
168        assert_eq!(addr.into_inner(), 0b111_0000);
169    }
170
171    #[test]
172    fn dev10_from_u16() {
173        let addr = DeviceAddress10::from(0b11_1111_0000_u16);
174        assert_eq!(addr.into_inner(), 0b11_1111_0000);
175    }
176
177    #[test]
178    fn dev10_from_u16_masked() {
179        let addr = DeviceAddress10::from(0b1111_1111_1111_0000_u16);
180        assert_eq!(addr.into_inner(), 0b0000_0011_1111_0000);
181    }
182
183    #[test]
184    fn dev10_from_dev7() {
185        let addr = DeviceAddress7::from(0b1111_0000_u8);
186        let addr: DeviceAddress10 = addr.into();
187        assert_eq!(addr.into_inner(), 0b0000_0000_0111_0000);
188    }
189
190    #[test]
191    fn dev7_debug() {
192        let addr = DeviceAddress7::new(0b111_0000);
193        test_format::assert_debug_fmt!(addr, "0x70 (1110000)");
194    }
195
196    #[test]
197    #[cfg(feature = "std")]
198    fn dev7_display() {
199        let addr = DeviceAddress7::new(0b111_0000);
200        test_format::assert_display_fmt!(addr, "0x70 (1110000)");
201    }
202
203    #[test]
204    fn dev10_debug() {
205        let addr = DeviceAddress10::new(0b01_1111_0100);
206        test_format::assert_debug_fmt!(addr, "0x1F4 (0111110100)");
207    }
208
209    #[test]
210    #[cfg(feature = "std")]
211    fn dev10_display() {
212        let addr = DeviceAddress10::new(0b01_1111_0100);
213        test_format::assert_display_fmt!(addr, "0x1F4 (0111110100)");
214    }
215}