• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

eldruin / xca9548a-rs / 10244505709

03 Aug 2024 07:25AM UTC coverage: 95.531% (-0.07%) from 95.604%
10244505709

push

github

eldruin
Reorganize code

126 of 131 new or added lines in 2 files covered. (96.18%)

171 of 179 relevant lines covered (95.53%)

9.18 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

94.95
/src/device_impl.rs
1
use crate::{
2
    parts::{Parts, Parts2, Parts4},
3
    private, Error, SlaveAddr, Xca9543a, Xca9545a, Xca9548a, DEVICE_BASE_ADDRESS,
4
};
5
use core::cell;
6
use embedded_hal::i2c as ehal;
7

8
#[doc(hidden)]
9
#[derive(Debug)]
10
pub struct Xca954xaData<I2C> {
11
    /// The concrete I²C device implementation.
12
    pub(crate) i2c: I2C,
13
    /// The I²C device address.
14
    pub(crate) address: u8,
15
    pub(crate) selected_channel_mask: u8,
16
}
17

18
impl<I2C, E> SelectChannels for Xca954xaData<I2C>
19
where
20
    I2C: ehal::I2c<Error = E>,
21
    E: core::fmt::Debug,
22
{
23
    type Error = Error<E>;
24
    fn select_channels(&mut self, channels: u8) -> Result<(), Self::Error> {
29✔
25
        self.i2c
29✔
26
            .write(self.address, &[channels])
29✔
27
            .map_err(Error::I2C)?;
29✔
28
        self.selected_channel_mask = channels;
29✔
29
        Ok(())
29✔
30
    }
29✔
31
}
32

33
#[doc(hidden)]
34
pub trait DoOnAcquired<I2C>: private::Sealed {
35
    fn do_on_acquired<R, E: ehal::Error>(
36
        &self,
37
        f: impl FnOnce(cell::RefMut<Xca954xaData<I2C>>) -> Result<R, Error<E>>,
38
    ) -> Result<R, Error<E>>;
39
}
40

41
#[doc(hidden)]
42
pub trait SelectChannels: private::Sealed {
43
    type Error;
44
    fn select_channels(&mut self, mask: u8) -> Result<(), Self::Error>;
45
}
46

47
impl<E> ehal::Error for Error<E>
48
where
49
    E: ehal::Error,
50
{
NEW
51
    fn kind(&self) -> ehal::ErrorKind {
×
NEW
52
        match self {
×
NEW
53
            Error::I2C(e) => e.kind(),
×
NEW
54
            Error::CouldNotAcquireDevice => ehal::ErrorKind::Other,
×
55
        }
NEW
56
    }
×
57
}
58

59
macro_rules! i2c_traits {
60
    ( $name:ident ) => {
61
        impl<I2C> DoOnAcquired<I2C> for $name<I2C> {
62
            fn do_on_acquired<R, E: ehal::Error>(
52✔
63
                &self,
52✔
64
                f: impl FnOnce(cell::RefMut<Xca954xaData<I2C>>) -> Result<R, Error<E>>,
52✔
65
            ) -> Result<R, Error<E>> {
52✔
66
                let dev = self
52✔
67
                    .data
52✔
68
                    .try_borrow_mut()
52✔
69
                    .map_err(|_| Error::CouldNotAcquireDevice)?;
52✔
70
                f(dev)
52✔
71
            }
52✔
72
        }
73

74
        impl<I2C, E> ehal::ErrorType for $name<I2C>
75
        where
76
            I2C: ehal::I2c<Error = E>,
77
            E: ehal::Error,
78
        {
79
            type Error = Error<E>;
80
        }
81

82
        impl<I2C, E> ehal::I2c for $name<I2C>
83
        where
84
            I2C: ehal::I2c<Error = E>,
85
            E: ehal::Error,
86
        {
87
            fn transaction(
3✔
88
                &mut self,
3✔
89
                address: u8,
3✔
90
                operations: &mut [ehal::Operation<'_>],
3✔
91
            ) -> Result<(), Error<E>> {
3✔
92
                self.do_on_acquired(|mut dev| {
3✔
93
                    dev.i2c.transaction(address, operations).map_err(Error::I2C)
3✔
94
                })
3✔
95
            }
3✔
96

97
            fn read(&mut self, address: u8, read: &mut [u8]) -> Result<(), Self::Error> {
3✔
98
                self.do_on_acquired(|mut dev| dev.i2c.read(address, read).map_err(Error::I2C))
3✔
99
            }
3✔
100

101
            fn write(&mut self, address: u8, write: &[u8]) -> Result<(), Self::Error> {
3✔
102
                self.do_on_acquired(|mut dev| dev.i2c.write(address, write).map_err(Error::I2C))
3✔
103
            }
3✔
104

105
            fn write_read(
3✔
106
                &mut self,
3✔
107
                address: u8,
3✔
108
                write: &[u8],
3✔
109
                read: &mut [u8],
3✔
110
            ) -> Result<(), Self::Error> {
3✔
111
                self.do_on_acquired(|mut dev| {
3✔
112
                    dev.i2c.write_read(address, write, read).map_err(Error::I2C)
3✔
113
                })
3✔
114
            }
3✔
115
        }
116
    };
117
}
118

119
macro_rules! impl_device {
120
    ( $name:ident, $parts:ident ) => {
121
        impl<I2C> $name<I2C> {
122
            /// Create new instance of the device
123
            pub fn new(i2c: I2C, address: SlaveAddr) -> Self {
28✔
124
                let data = Xca954xaData {
28✔
125
                    i2c,
28✔
126
                    address: address.addr(DEVICE_BASE_ADDRESS),
28✔
127
                    selected_channel_mask: 0,
28✔
128
                };
28✔
129
                $name {
28✔
130
                    data: cell::RefCell::new(data),
28✔
131
                }
28✔
132
            }
28✔
133

134
            /// Destroy driver instance, return I²C bus instance.
135
            pub fn destroy(self) -> I2C {
28✔
136
                self.data.into_inner().i2c
28✔
137
            }
28✔
138

139
            /// Split device into individual I2C devices
140
            ///
141
            /// It is not possible to know the compatibilities between channels
142
            /// so when talking to a split I2C device, only its channel
143
            /// will be selected.
144
            pub fn split(&self) -> $parts<$name<I2C>, I2C> {
6✔
145
                $parts::new(&self)
6✔
146
            }
6✔
147
        }
148
    };
149
    ( $name:ident, $parts:ident, no_interrupts ) => {
150
        impl_device!($name, $parts);
151

152
        impl<I2C, E> $name<I2C>
153
        where
154
            I2C: ehal::I2c<Error = E>,
155
            E: ehal::Error,
156
        {
157
            /// Get status of channels.
158
            ///
159
            /// Each bit corresponds to a channel.
160
            /// Bit 0 corresponds to channel 0 and so on up to bit 7 which
161
            /// corresponds to channel 7.
162
            /// A `0` means the channel is disabled and a `1` that the channel is enabled.
163
            pub fn get_channel_status(&mut self) -> Result<u8, Error<E>> {
1✔
164
                let mut data = [0];
1✔
165
                self.do_on_acquired(|mut dev| {
1✔
166
                    let address = dev.address;
1✔
167
                    dev.i2c
1✔
168
                        .read(address, &mut data)
1✔
169
                        .map_err(Error::I2C)
1✔
170
                        .and(Ok(data[0]))
1✔
171
                })
1✔
172
            }
1✔
173
        }
174

175
        impl<I2C, E> $name<I2C>
176
        where
177
            I2C: ehal::I2c<Error = E>,
178
            E: ehal::Error,
179
        {
180
            /// Select which channels are enabled.
181
            ///
182
            /// Each bit corresponds to a channel.
183
            /// Bit 0 corresponds to channel 0 and so on up to bit 7 which
184
            /// corresponds to channel 7.
185
            /// A `0` disables the channel and a `1` enables it.
186
            /// Several channels can be enabled at the same time
187
            pub fn select_channels(&mut self, channels: u8) -> Result<(), Error<E>> {
5✔
188
                self.do_on_acquired(|mut dev| dev.select_channels(channels))
5✔
189
            }
5✔
190
        }
191
    };
192
    ( $name:ident, $parts:ident, $mask:expr, interrupts ) => {
193
        impl_device!($name, $parts);
194

195
        impl<I2C, E> $name<I2C>
196
        where
197
            I2C: ehal::I2c<Error = E>,
198
            E: ehal::Error,
199
        {
200
            /// Get status of channels.
201
            ///
202
            /// Each bit corresponds to a channel.
203
            /// Bit 0 corresponds to channel 0, bit 1 to channel 1 and so on.
204
            /// A `0` means the channel is disabled and a `1` that the channel is enabled.
205
            pub fn get_channel_status(&mut self) -> Result<u8, Error<E>> {
2✔
206
                let mut data = [0];
2✔
207
                self.do_on_acquired(|mut dev| {
2✔
208
                    let address = dev.address;
2✔
209
                    dev.i2c
2✔
210
                        .read(address, &mut data)
2✔
211
                        .map_err(Error::I2C)
2✔
212
                        .and(Ok(data[0] & $mask))
2✔
213
                })
2✔
214
            }
2✔
215

216
            /// Get status of channel interrupts.
217
            ///
218
            /// Each bit corresponds to a channel.
219
            /// Bit 0 corresponds to channel 0, bit 1 to channel 1 and so on.
220
            /// A `1` means the channel's interrupt is high and a `0` that the channel's interrupt is low.
221
            /// Note: I2C interrupts are usually active LOW!
222
            pub fn get_interrupt_status(&mut self) -> Result<u8, Error<E>> {
2✔
223
                let mut data = [0];
2✔
224
                self.do_on_acquired(|mut dev| {
2✔
225
                    let address = dev.address;
2✔
226
                    dev.i2c
2✔
227
                        .read(address, &mut data)
2✔
228
                        .map_err(Error::I2C)
2✔
229
                        .and(Ok((data[0] >> 4) & $mask))
2✔
230
                })
2✔
231
            }
2✔
232
        }
233

234
        impl<I2C, E> $name<I2C>
235
        where
236
            I2C: ehal::I2c<Error = E>,
237
            E: ehal::Error,
238
        {
239
            /// Select which channels are enabled.
240
            ///
241
            /// Each bit corresponds to a channel.
242
            /// Bit 0 corresponds to channel 0, bit 1 to channel 1 and so on.
243
            /// A `0` disables the channel and a `1` enables it.
244
            /// Several channels can be enabled at the same time.
245
            ///
246
            /// Channels/bits that does not exist for the specific device are ignored.
247
            pub fn select_channels(&mut self, channels: u8) -> Result<(), Error<E>> {
12✔
248
                self.do_on_acquired(|mut dev| dev.select_channels(channels & $mask))
12✔
249
            }
12✔
250
        }
251
    };
252
}
253

254
impl_device!(Xca9548a, Parts, no_interrupts);
255
i2c_traits!(Xca9548a);
256

257
impl_device!(Xca9543a, Parts2, 0x03, interrupts);
258
i2c_traits!(Xca9543a);
259

260
impl_device!(Xca9545a, Parts4, 0x0f, interrupts);
261
i2c_traits!(Xca9545a);
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc