rktk_drivers_common/
spi.rs1use embassy_embedded_hal::shared_bus::asynch::spi::SpiDevice;
2use embassy_sync::{blocking_mutex::raw::RawMutex, mutex::Mutex};
3use embedded_hal::{
4 digital::OutputPin,
5 spi::{ErrorType, Operation},
6};
7use embedded_hal_async::spi::{SpiBus, SpiDevice as SpiDeviceTrait};
8
9#[derive(Debug, PartialEq, Eq)]
10#[cfg_attr(feature = "defmt", derive(defmt::Format))]
11pub enum IterOperation<Word: 'static> {
12 Write(Word),
13 DelayNs(u32),
14}
15
16#[allow(async_fn_in_trait)]
30pub trait ExtendedSpi<Word: Copy + 'static = u8> {
31 type Error: core::fmt::Debug;
32
33 async fn transaction(
34 &mut self,
35 operations: &mut [Operation<'_, Word>],
36 ) -> Result<(), Self::Error>;
37
38 fn transaction_iter_supported(&self) -> bool {
39 false
40 }
41
42 async fn transaction_iter(
43 &mut self,
44 _operations: impl Iterator<Item = IterOperation<Word>>,
45 ) -> Result<(), Self::Error> {
46 Ok(())
47 }
48}
49
50pub struct EmbassySpiDevice<
51 'a,
52 M: RawMutex,
53 BUS: SpiBus<Word>,
54 CS: OutputPin,
55 Word: Copy + 'static = u8,
56> {
57 bus: &'a Mutex<M, BUS>,
58 cs: CS,
59 _word: core::marker::PhantomData<Word>,
60}
61
62impl<'a, M: RawMutex, BUS: SpiBus<Word>, CS: OutputPin, Word: Copy + 'static>
63 EmbassySpiDevice<'a, M, BUS, CS, Word>
64{
65 pub fn new(bus: &'a Mutex<M, BUS>, cs: CS) -> Self {
66 Self { bus, cs, _word: core::marker::PhantomData }
67 }
68}
69
70impl<'a, M: RawMutex + 'a, BUS: SpiBus<Word>, CS: OutputPin + 'a, Word: Copy + 'static>
71 ExtendedSpi<Word> for EmbassySpiDevice<'a, M, BUS, CS, Word>
72{
73 type Error = <SpiDevice<'a, M, BUS, CS> as ErrorType>::Error;
74
75 async fn transaction(
76 &mut self,
77 operations: &mut [Operation<'_, Word>],
78 ) -> Result<(), Self::Error> {
79 let mut spi = SpiDevice::new(self.bus, &mut self.cs);
80 SpiDeviceTrait::transaction(&mut spi, operations).await
81 }
82
83 fn transaction_iter_supported(&self) -> bool {
84 true
85 }
86
87 async fn transaction_iter(
88 &mut self,
89 operations: impl Iterator<Item = IterOperation<Word>>,
90 ) -> Result<(), Self::Error> {
91 self.cs.set_low().map_err(Self::Error::Cs)?;
92 {
93 let mut bus = self.bus.lock().await;
94 for op in operations {
95 match op {
96 IterOperation::Write(item) => {
97 bus.write(&[item]).await.map_err(Self::Error::Spi)?
98 }
99 IterOperation::DelayNs(n) => embassy_time::Timer::after_nanos(n.into()).await,
100 }
101 }
102 }
103 self.cs.set_high().map_err(Self::Error::Cs)?;
104
105 Ok(())
106 }
107}
108
109impl<T: SpiDeviceTrait<Word>, Word: Copy + 'static> ExtendedSpi<Word> for T {
110 type Error = T::Error;
111
112 async fn transaction(
113 &mut self,
114 operations: &mut [Operation<'_, Word>],
115 ) -> Result<(), Self::Error> {
116 SpiDeviceTrait::transaction(self, operations).await
117 }
118}