embedded_c_sdk_bind_hal/
spi.rs1pub use crate::ll_api::{SpiBusBitOrder, SpiBusDataSize, SpiBusId, SpiBusMode};
2use crate::{ll_api::ll_cmd::*, tick::Delay};
3use core::{cmp::min, ptr};
4use embedded_hal::{delay::DelayNs, digital::OutputPin, spi::Operation};
5
6#[derive(Debug, PartialEq, Eq, Clone, Copy)]
7pub enum Error {
8 Code(i32),
9}
10
11pub struct Config {
21 pub baudrate: u32,
22 pub mode: SpiBusMode,
23 pub size: SpiBusDataSize,
24 pub order: SpiBusBitOrder,
25}
26
27impl Default for Config {
28 fn default() -> Self {
29 Self {
30 baudrate: 8_000_000,
31 mode: SpiBusMode::Mode0,
32 size: SpiBusDataSize::DataSize8,
33 order: SpiBusBitOrder::MsbFirst,
34 }
35 }
36}
37
38#[derive(Clone, Debug)]
39pub struct SpiBus {
40 bus: SpiBusId,
41}
42
43impl SpiBus {
44 pub fn new(bus: SpiBusId, config: &Config) -> Self {
53 let flags = config.size as u32 | config.order as u32;
54 ll_invoke_inner!(INVOKE_ID_SPI_INIT, bus, config.mode, flags, config.baudrate);
55 SpiBus { bus }
56 }
57
58 pub fn to_device<NSS: OutputPin>(self, nss: NSS) -> SpiDevice<NSS> {
66 SpiDevice { bus: self, nss }
67 }
68
69 fn blocking_read(&mut self, words: &mut [u8]) -> i32 {
77 ll_invoke_inner!(
78 INVOKE_ID_SPI_BLOCKING_RW,
79 self.bus,
80 ptr::null::<u8>(),
81 words.as_mut_ptr(),
82 words.len()
83 )
84 }
85
86 fn blocking_write(&mut self, words: &[u8]) -> i32 {
94 ll_invoke_inner!(
95 INVOKE_ID_SPI_BLOCKING_RW,
96 self.bus,
97 words.as_ptr(),
98 ptr::null::<u8>(),
99 words.len()
100 )
101 }
102
103 fn blocking_transfer(&mut self, read: &mut [u8], write: &[u8]) -> i32 {
112 let size = min(read.len(), write.len());
113 ll_invoke_inner!(
114 INVOKE_ID_SPI_BLOCKING_RW,
115 self.bus,
116 write.as_ptr(),
117 read.as_ptr(),
118 size
119 )
120 }
121
122 fn blocking_transfer_in_place(&mut self, words: &mut [u8]) -> i32 {
130 let rw_ptr = words.as_ptr();
131 ll_invoke_inner!(
132 INVOKE_ID_SPI_BLOCKING_RW,
133 self.bus,
134 rw_ptr,
135 rw_ptr,
136 words.len()
137 )
138 }
139}
140
141impl Drop for SpiBus {
142 fn drop(&mut self) {
143 ll_invoke_inner!(INVOKE_ID_SPI_DEINIT, self.bus);
144 }
145}
146
147impl embedded_hal::spi::ErrorType for SpiBus {
148 type Error = Error;
149}
150
151impl embedded_hal::spi::SpiBus for SpiBus {
152 fn flush(&mut self) -> Result<(), Self::Error> {
153 Ok(())
154 }
155
156 fn read(&mut self, words: &mut [u8]) -> Result<(), Self::Error> {
157 let result = self.blocking_read(words);
158 if result == 0 {
159 return Ok(());
160 }
161 return Err(Error::Code(result));
162 }
163
164 fn write(&mut self, words: &[u8]) -> Result<(), Self::Error> {
165 let result = self.blocking_write(words);
166 if result == 0 {
167 return Ok(());
168 }
169 return Err(Error::Code(result));
170 }
171
172 fn transfer(&mut self, read: &mut [u8], write: &[u8]) -> Result<(), Self::Error> {
173 let result = self.blocking_transfer(read, write);
174 if result == 0 {
175 return Ok(());
176 }
177 return Err(Error::Code(result));
178 }
179
180 fn transfer_in_place(&mut self, words: &mut [u8]) -> Result<(), Self::Error> {
181 let result = self.blocking_transfer_in_place(words);
182 if result == 0 {
183 return Ok(());
184 }
185 return Err(Error::Code(result));
186 }
187}
188
189impl embedded_hal::spi::Error for Error {
190 fn kind(&self) -> embedded_hal::spi::ErrorKind {
191 match *self {
192 Self::Code(_) => embedded_hal::spi::ErrorKind::Other,
193 }
194 }
195}
196
197pub struct SpiDevice<NSS> {
198 bus: SpiBus,
199 nss: NSS,
200}
201
202impl<NSS: OutputPin> SpiDevice<NSS> {
203 pub fn new(bus: SpiBus, nss: NSS) -> Self {
212 SpiDevice { bus, nss }
213 }
214}
215
216impl<NSS: OutputPin> embedded_hal::spi::ErrorType for SpiDevice<NSS> {
217 type Error = Error;
218}
219
220impl<NSS: OutputPin> embedded_hal::spi::SpiDevice for SpiDevice<NSS> {
221 fn transaction(&mut self, operations: &mut [Operation<'_, u8>]) -> Result<(), Self::Error> {
222 let mut result = Ok(());
223
224 self.nss.set_low().ok();
225 for op in operations {
226 match op {
227 Operation::Read(words) => {
228 let ret = self.bus.blocking_read(words);
229 if ret != 0 {
230 result = Err(Error::Code(ret));
231 }
232 }
233 Operation::Write(words) => {
234 let ret = self.bus.blocking_write(words);
235 if ret != 0 {
236 result = Err(Error::Code(ret));
237 }
238 }
239 Operation::Transfer(rd_words, wr_words) => {
240 let ret = self.bus.blocking_transfer(rd_words, wr_words);
241 if ret != 0 {
242 result = Err(Error::Code(ret));
243 }
244 }
245 Operation::TransferInPlace(words) => {
246 let ret = self.bus.blocking_transfer_in_place(words);
247 if ret != 0 {
248 result = Err(Error::Code(ret));
249 }
250 }
251 Operation::DelayNs(ns) => {
252 let mut delay = Delay::new();
253 delay.delay_ns(*ns);
254 }
255 }
256 }
257 self.nss.set_high().ok();
258
259 result
260 }
261}