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}