embedded_hal_bus/spi/
exclusive.rs1use embedded_hal::delay::DelayNs;
4use embedded_hal::digital::OutputPin;
5use embedded_hal::spi::{ErrorType, Operation, SpiBus, SpiDevice};
6#[cfg(feature = "async")]
7use embedded_hal_async::{
8 delay::DelayNs as AsyncDelayNs,
9 spi::{SpiBus as AsyncSpiBus, SpiDevice as AsyncSpiDevice},
10};
11
12use super::shared::transaction;
13use super::DeviceError;
14
15pub struct ExclusiveDevice<BUS, CS, D> {
20 bus: BUS,
21 cs: CS,
22 delay: D,
23}
24
25impl<BUS, CS, D> ExclusiveDevice<BUS, CS, D> {
26 #[inline]
31 pub fn new(bus: BUS, mut cs: CS, delay: D) -> Result<Self, CS::Error>
32 where
33 CS: OutputPin,
34 {
35 cs.set_high()?;
36 Ok(Self { bus, cs, delay })
37 }
38
39 #[inline]
41 pub fn bus(&self) -> &BUS {
42 &self.bus
43 }
44
45 #[inline]
47 pub fn bus_mut(&mut self) -> &mut BUS {
48 &mut self.bus
49 }
50}
51
52impl<BUS, CS> ExclusiveDevice<BUS, CS, super::NoDelay> {
53 #[inline]
73 pub fn new_no_delay(bus: BUS, mut cs: CS) -> Result<Self, CS::Error>
74 where
75 CS: OutputPin,
76 {
77 cs.set_high()?;
78 Ok(Self {
79 bus,
80 cs,
81 delay: super::NoDelay,
82 })
83 }
84}
85
86impl<BUS, CS, D> ErrorType for ExclusiveDevice<BUS, CS, D>
87where
88 BUS: ErrorType,
89 CS: OutputPin,
90{
91 type Error = DeviceError<BUS::Error, CS::Error>;
92}
93
94impl<Word: Copy + 'static, BUS, CS, D> SpiDevice<Word> for ExclusiveDevice<BUS, CS, D>
95where
96 BUS: SpiBus<Word>,
97 CS: OutputPin,
98 D: DelayNs,
99{
100 #[inline]
101 fn transaction(&mut self, operations: &mut [Operation<'_, Word>]) -> Result<(), Self::Error> {
102 transaction(operations, &mut self.bus, &mut self.delay, &mut self.cs)
103 }
104}
105
106#[cfg(feature = "async")]
107#[cfg_attr(docsrs, doc(cfg(feature = "async")))]
108impl<Word: Copy + 'static, BUS, CS, D> AsyncSpiDevice<Word> for ExclusiveDevice<BUS, CS, D>
109where
110 BUS: AsyncSpiBus<Word>,
111 CS: OutputPin,
112 D: AsyncDelayNs,
113{
114 #[inline]
115 async fn transaction(
116 &mut self,
117 operations: &mut [Operation<'_, Word>],
118 ) -> Result<(), Self::Error> {
119 self.cs.set_low().map_err(DeviceError::Cs)?;
120
121 let op_res = 'ops: {
122 for op in operations {
123 let res = match op {
124 Operation::Read(buf) => self.bus.read(buf).await,
125 Operation::Write(buf) => self.bus.write(buf).await,
126 Operation::Transfer(read, write) => self.bus.transfer(read, write).await,
127 Operation::TransferInPlace(buf) => self.bus.transfer_in_place(buf).await,
128 Operation::DelayNs(ns) => match self.bus.flush().await {
129 Err(e) => Err(e),
130 Ok(()) => {
131 self.delay.delay_ns(*ns).await;
132 Ok(())
133 }
134 },
135 };
136 if let Err(e) = res {
137 break 'ops Err(e);
138 }
139 }
140 Ok(())
141 };
142
143 let flush_res = self.bus.flush().await;
145 let cs_res = self.cs.set_high();
146
147 op_res.map_err(DeviceError::Spi)?;
148 flush_res.map_err(DeviceError::Spi)?;
149 cs_res.map_err(DeviceError::Cs)?;
150
151 Ok(())
152 }
153}