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 {
67 bus,
68 cs,
69 _word: core::marker::PhantomData,
70 }
71 }
72}
73
74impl<'a, M: RawMutex + 'a, BUS: SpiBus<Word>, CS: OutputPin + 'a, Word: Copy + 'static>
75 ExtendedSpi<Word> for EmbassySpiDevice<'a, M, BUS, CS, Word>
76{
77 type Error = <SpiDevice<'a, M, BUS, CS> as ErrorType>::Error;
78
79 async fn transaction(
80 &mut self,
81 operations: &mut [Operation<'_, Word>],
82 ) -> Result<(), Self::Error> {
83 let mut spi = SpiDevice::new(self.bus, &mut self.cs);
84 SpiDeviceTrait::transaction(&mut spi, operations).await
85 }
86
87 fn transaction_iter_supported(&self) -> bool {
88 true
89 }
90
91 async fn transaction_iter(
92 &mut self,
93 operations: impl Iterator<Item = IterOperation<Word>>,
94 ) -> Result<(), Self::Error> {
95 self.cs.set_low().map_err(Self::Error::Cs)?;
96 {
97 let mut bus = self.bus.lock().await;
98 for op in operations {
99 match op {
100 IterOperation::Write(item) => {
101 bus.write(&[item]).await.map_err(Self::Error::Spi)?
102 }
103 IterOperation::DelayNs(n) => embassy_time::Timer::after_nanos(n.into()).await,
104 }
105 }
106 }
107 self.cs.set_high().map_err(Self::Error::Cs)?;
108
109 Ok(())
110 }
111}
112
113impl<T: SpiDeviceTrait<Word>, Word: Copy + 'static> ExtendedSpi<Word> for T {
114 type Error = T::Error;
115
116 async fn transaction(
117 &mut self,
118 operations: &mut [Operation<'_, Word>],
119 ) -> Result<(), Self::Error> {
120 SpiDeviceTrait::transaction(self, operations).await
121 }
122}