embedded_hal_bus/i2c/
refcell.rs

1use core::cell::RefCell;
2use embedded_hal::i2c::{ErrorType, I2c};
3
4/// `RefCell`-based shared bus [`I2c`] implementation.
5///
6/// Sharing is implemented with a `RefCell`. This means it has low overhead, but `RefCellDevice` instances are not `Send`,
7/// so it only allows sharing within a single thread (interrupt priority level). If you need to share a bus across several
8/// threads, use [`CriticalSectionDevice`](super::CriticalSectionDevice) instead.
9///
10/// # Examples
11///
12/// Assuming there is a pressure sensor with address `0x42` on the same bus as a temperature sensor
13/// with address `0x20`; [`RefCellDevice`] can be used to give access to both of these sensors
14/// from a single `i2c` instance.
15///
16/// ```
17/// use embedded_hal_bus::i2c;
18/// use core::cell::RefCell;
19/// # use embedded_hal::i2c::{self as hali2c, SevenBitAddress, TenBitAddress, I2c, Operation, ErrorKind};
20/// # pub struct Sensor<I2C> {
21/// #     i2c: I2C,
22/// #     address: u8,
23/// # }
24/// # impl<I2C: I2c> Sensor<I2C> {
25/// #     pub fn new(i2c: I2C, address: u8) -> Self {
26/// #         Self { i2c, address }
27/// #     }
28/// # }
29/// # type PressureSensor<I2C> = Sensor<I2C>;
30/// # type TemperatureSensor<I2C> = Sensor<I2C>;
31/// # pub struct I2c0;
32/// # #[derive(Debug, Copy, Clone, Eq, PartialEq)]
33/// # pub enum Error { }
34/// # impl hali2c::Error for Error {
35/// #     fn kind(&self) -> hali2c::ErrorKind {
36/// #         ErrorKind::Other
37/// #     }
38/// # }
39/// # impl hali2c::ErrorType for I2c0 {
40/// #     type Error = Error;
41/// # }
42/// # impl I2c<SevenBitAddress> for I2c0 {
43/// #     fn transaction(&mut self, address: u8, operations: &mut [Operation<'_>]) -> Result<(), Self::Error> {
44/// #       Ok(())
45/// #     }
46/// # }
47/// # struct Hal;
48/// # impl Hal {
49/// #   fn i2c(&self) -> I2c0 {
50/// #     I2c0
51/// #   }
52/// # }
53/// # let hal = Hal;
54///
55/// let i2c = hal.i2c();
56/// let i2c_ref_cell = RefCell::new(i2c);
57/// let mut temperature_sensor = TemperatureSensor::new(
58///   i2c::RefCellDevice::new(&i2c_ref_cell),
59///   0x20,
60/// );
61/// let mut pressure_sensor = PressureSensor::new(
62///   i2c::RefCellDevice::new(&i2c_ref_cell),
63///   0x42,
64/// );
65/// ```
66pub struct RefCellDevice<'a, T> {
67    bus: &'a RefCell<T>,
68}
69
70impl<'a, T> RefCellDevice<'a, T> {
71    /// Create a new `RefCellDevice`.
72    #[inline]
73    pub fn new(bus: &'a RefCell<T>) -> Self {
74        Self { bus }
75    }
76}
77
78impl<'a, T> ErrorType for RefCellDevice<'a, T>
79where
80    T: I2c,
81{
82    type Error = T::Error;
83}
84
85impl<'a, T> I2c for RefCellDevice<'a, T>
86where
87    T: I2c,
88{
89    #[inline]
90    fn read(&mut self, address: u8, read: &mut [u8]) -> Result<(), Self::Error> {
91        let bus = &mut *self.bus.borrow_mut();
92        bus.read(address, read)
93    }
94
95    #[inline]
96    fn write(&mut self, address: u8, write: &[u8]) -> Result<(), Self::Error> {
97        let bus = &mut *self.bus.borrow_mut();
98        bus.write(address, write)
99    }
100
101    #[inline]
102    fn write_read(
103        &mut self,
104        address: u8,
105        write: &[u8],
106        read: &mut [u8],
107    ) -> Result<(), Self::Error> {
108        let bus = &mut *self.bus.borrow_mut();
109        bus.write_read(address, write, read)
110    }
111
112    #[inline]
113    fn transaction(
114        &mut self,
115        address: u8,
116        operations: &mut [embedded_hal::i2c::Operation<'_>],
117    ) -> Result<(), Self::Error> {
118        let bus = &mut *self.bus.borrow_mut();
119        bus.transaction(address, operations)
120    }
121}