Skip to content

Commit 47df22c

Browse files
bors[bot]Dirbaio
andauthored
Merge #373
373: async/spi: add helper methods to SpiDevice. r=eldruin a=Dirbaio It's not possible to add them as default methods to `SpiDevice` itself, but it's possible to do via an extension trait! With this, you can avoid interacting with the horrible async closure hack in most cases. You can now do `my_device.write(&buf).await`, just like with bare buses. Co-authored-by: Dario Nieuwenhuis <[email protected]>
2 parents b5c29b3 + bdc20d8 commit 47df22c

File tree

1 file changed

+158
-0
lines changed

1 file changed

+158
-0
lines changed

embedded-hal-async/src/spi.rs

Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,164 @@ pub trait SpiDevice: ErrorType {
5353
> + 'a;
5454
}
5555

56+
/// Helper methods for SpiDevice.
57+
///
58+
/// This is automatically implemented for all `T: SpiDevice`, you can directly
59+
/// use the methods on any `SpiDevice`.
60+
pub trait SpiDeviceExt: SpiDevice {
61+
/// Future returned by the `read` method.
62+
type ReadFuture<'a, Word>: Future<Output = Result<(), Self::Error>> + 'a
63+
where
64+
Self: 'a,
65+
Self::Bus: SpiBusRead<Word>,
66+
Word: Copy + 'static;
67+
68+
/// Do a read within a transaction.
69+
///
70+
/// This is a convenience method equivalent to `device.transaction(|bus| bus.read(buf))`.
71+
///
72+
/// See also: [`SpiDevice::transaction`], [`SpiBusRead::read`]
73+
fn read<'a, Word>(&'a mut self, buf: &'a mut [Word]) -> Self::ReadFuture<'a, Word>
74+
where
75+
Self::Bus: SpiBusRead<Word>,
76+
Word: Copy + 'static;
77+
78+
/// Future returned by the `write` method.
79+
type WriteFuture<'a, Word>: Future<Output = Result<(), Self::Error>> + 'a
80+
where
81+
Self: 'a,
82+
Self::Bus: SpiBusWrite<Word>,
83+
Word: Copy + 'static;
84+
85+
/// Do a write within a transaction.
86+
///
87+
/// This is a convenience method equivalent to `device.transaction(|bus| bus.write(buf))`.
88+
///
89+
/// See also: [`SpiDevice::transaction`], [`SpiBusWrite::write`]
90+
fn write<'a, Word>(&'a mut self, buf: &'a [Word]) -> Self::WriteFuture<'a, Word>
91+
where
92+
Self::Bus: SpiBusWrite<Word>,
93+
Word: Copy + 'static;
94+
95+
/// Future returned by the `transfer` method.
96+
type TransferFuture<'a, Word>: Future<Output = Result<(), Self::Error>> + 'a
97+
where
98+
Self: 'a,
99+
Self::Bus: SpiBus<Word>,
100+
Word: Copy + 'static;
101+
102+
/// Do a transfer within a transaction.
103+
///
104+
/// This is a convenience method equivalent to `device.transaction(|bus| bus.transfer(read, write))`.
105+
///
106+
/// See also: [`SpiDevice::transaction`], [`SpiBus::transfer`]
107+
fn transfer<'a, Word>(
108+
&'a mut self,
109+
read: &'a mut [Word],
110+
write: &'a [Word],
111+
) -> Self::TransferFuture<'a, Word>
112+
where
113+
Self::Bus: SpiBus<Word>,
114+
Word: Copy + 'static;
115+
116+
/// Future returned by the `transfer_in_place` method.
117+
type TransferInPlaceFuture<'a, Word>: Future<Output = Result<(), Self::Error>> + 'a
118+
where
119+
Self: 'a,
120+
Self::Bus: SpiBus<Word>,
121+
Word: Copy + 'static;
122+
123+
/// Do an in-place transfer within a transaction.
124+
///
125+
/// This is a convenience method equivalent to `device.transaction(|bus| bus.transfer_in_place(buf))`.
126+
///
127+
/// See also: [`SpiDevice::transaction`], [`SpiBus::transfer_in_place`]
128+
fn transfer_in_place<'a, Word>(
129+
&'a mut self,
130+
buf: &'a mut [Word],
131+
) -> Self::TransferInPlaceFuture<'a, Word>
132+
where
133+
Self::Bus: SpiBus<Word>,
134+
Word: Copy + 'static;
135+
}
136+
137+
impl<T: SpiDevice> SpiDeviceExt for T {
138+
type ReadFuture<'a, Word> = impl Future<Output = Result<(), Self::Error>> + 'a
139+
where
140+
Self: 'a,
141+
Self::Bus: SpiBusRead<Word>,
142+
Word: Copy + 'static;
143+
144+
fn read<'a, Word>(&'a mut self, buf: &'a mut [Word]) -> Self::ReadFuture<'a, Word>
145+
where
146+
Self::Bus: SpiBusRead<Word>,
147+
Word: Copy + 'static,
148+
{
149+
self.transaction(move |bus| async move {
150+
let res = bus.read(buf).await;
151+
(bus, res)
152+
})
153+
}
154+
155+
type WriteFuture<'a, Word> = impl Future<Output = Result<(), Self::Error>> + 'a
156+
where
157+
Self: 'a,
158+
Self::Bus: SpiBusWrite<Word>,
159+
Word: Copy + 'static;
160+
161+
fn write<'a, Word>(&'a mut self, buf: &'a [Word]) -> Self::WriteFuture<'a, Word>
162+
where
163+
Self::Bus: SpiBusWrite<Word>,
164+
Word: Copy + 'static,
165+
{
166+
self.transaction(move |bus| async move {
167+
let res = bus.write(buf).await;
168+
(bus, res)
169+
})
170+
}
171+
172+
type TransferFuture<'a, Word> = impl Future<Output = Result<(), Self::Error>> + 'a
173+
where
174+
Self: 'a,
175+
Self::Bus: SpiBus<Word>,
176+
Word: Copy + 'static;
177+
178+
fn transfer<'a, Word>(
179+
&'a mut self,
180+
read: &'a mut [Word],
181+
write: &'a [Word],
182+
) -> Self::TransferFuture<'a, Word>
183+
where
184+
Self::Bus: SpiBus<Word>,
185+
Word: Copy + 'static,
186+
{
187+
self.transaction(move |bus| async move {
188+
let res = bus.transfer(read, write).await;
189+
(bus, res)
190+
})
191+
}
192+
193+
type TransferInPlaceFuture<'a, Word> = impl Future<Output = Result<(), Self::Error>> + 'a
194+
where
195+
Self: 'a,
196+
Self::Bus: SpiBus<Word>,
197+
Word: Copy + 'static;
198+
199+
fn transfer_in_place<'a, Word>(
200+
&'a mut self,
201+
buf: &'a mut [Word],
202+
) -> Self::TransferInPlaceFuture<'a, Word>
203+
where
204+
Self::Bus: SpiBus<Word>,
205+
Word: Copy + 'static,
206+
{
207+
self.transaction(move |bus| async move {
208+
let res = bus.transfer_in_place(buf).await;
209+
(bus, res)
210+
})
211+
}
212+
}
213+
56214
impl<T: SpiDevice> SpiDevice for &mut T {
57215
type Bus = T::Bus;
58216

0 commit comments

Comments
 (0)