1use crate::error::Error;
2use crate::{FtInner, PinUse};
3use ftdi_mpsse::{ClockData, ClockDataOut, MpsseCmdBuilder, MpsseCmdExecutor};
4use std::sync::{Arc, Mutex, MutexGuard};
5
6#[derive(Debug, Clone, Copy, PartialEq, Eq)]
10pub struct Polarity {
11 clk: ClockData,
15 clk_out: ClockDataOut,
19}
20
21impl From<eh0::spi::Polarity> for Polarity {
22 fn from(cpol: eh0::spi::Polarity) -> Self {
23 match cpol {
24 eh0::spi::Polarity::IdleLow => Polarity {
25 clk: ClockData::MsbPosIn,
26 clk_out: ClockDataOut::MsbNeg,
27 },
28 eh0::spi::Polarity::IdleHigh => Polarity {
29 clk: ClockData::MsbNegIn,
30 clk_out: ClockDataOut::MsbPos,
31 },
32 }
33 }
34}
35
36impl From<eh1::spi::Polarity> for Polarity {
37 fn from(cpol: eh1::spi::Polarity) -> Self {
38 match cpol {
39 eh1::spi::Polarity::IdleLow => Polarity {
40 clk: ClockData::MsbPosIn,
41 clk_out: ClockDataOut::MsbNeg,
42 },
43 eh1::spi::Polarity::IdleHigh => Polarity {
44 clk: ClockData::MsbNegIn,
45 clk_out: ClockDataOut::MsbPos,
46 },
47 }
48 }
49}
50
51impl Default for Polarity {
52 fn default() -> Self {
53 Self {
54 clk: ClockData::MsbPosIn,
55 clk_out: ClockDataOut::MsbNeg,
56 }
57 }
58}
59
60#[derive(Debug)]
68pub struct Spi<Device: MpsseCmdExecutor> {
69 mtx: Arc<Mutex<FtInner<Device>>>,
71 pol: Polarity,
73}
74
75impl<Device, E> Spi<Device>
76where
77 Device: MpsseCmdExecutor<Error = E>,
78 E: std::error::Error,
79 Error<E>: From<E>,
80{
81 pub(crate) fn new(mtx: Arc<Mutex<FtInner<Device>>>) -> Result<Spi<Device>, Error<E>> {
82 {
83 let mut lock = mtx.lock().expect("Failed to aquire FTDI mutex");
84 lock.allocate_pin(0, PinUse::Spi);
85 lock.allocate_pin(1, PinUse::Spi);
86 lock.allocate_pin(2, PinUse::Spi);
87
88 lock.direction &= !0x07;
90 lock.direction |= 0x03;
92
93 let cmd: MpsseCmdBuilder = MpsseCmdBuilder::new()
95 .set_gpio_lower(lock.value, lock.direction)
96 .send_immediate();
97 lock.ft.send(cmd.as_slice())?;
98 }
99
100 Ok(Spi {
101 mtx,
102 pol: Default::default(),
103 })
104 }
105
106 pub fn set_clock_polarity<P: Into<Polarity>>(&mut self, cpol: P) {
128 self.pol = cpol.into()
129 }
130}
131
132impl<Device, E> eh0::blocking::spi::Write<u8> for Spi<Device>
133where
134 Device: MpsseCmdExecutor<Error = E>,
135 E: std::error::Error,
136 Error<E>: From<E>,
137{
138 type Error = Error<E>;
139
140 fn write(&mut self, words: &[u8]) -> Result<(), Error<E>> {
141 let cmd: MpsseCmdBuilder = MpsseCmdBuilder::new()
142 .clock_data_out(self.pol.clk_out, words)
143 .send_immediate();
144
145 let mut lock = self.mtx.lock().expect("Failed to aquire FTDI mutex");
146 lock.ft.send(cmd.as_slice())?;
147
148 Ok(())
149 }
150}
151
152impl<Device, E> eh0::blocking::spi::Transfer<u8> for Spi<Device>
153where
154 Device: MpsseCmdExecutor<Error = E>,
155 E: std::error::Error,
156 Error<E>: From<E>,
157{
158 type Error = Error<E>;
159
160 fn transfer<'w>(&mut self, words: &'w mut [u8]) -> Result<&'w [u8], Error<E>> {
161 let cmd: MpsseCmdBuilder = MpsseCmdBuilder::new()
162 .clock_data(self.pol.clk, words)
163 .send_immediate();
164
165 let mut lock = self.mtx.lock().expect("Failed to aquire FTDI mutex");
166 lock.ft.send(cmd.as_slice())?;
167 lock.ft.recv(words)?;
168
169 Ok(words)
170 }
171}
172
173impl<Device, E> eh0::spi::FullDuplex<u8> for Spi<Device>
174where
175 Device: MpsseCmdExecutor<Error = E>,
176 E: std::error::Error,
177 Error<E>: From<E>,
178{
179 type Error = Error<E>;
180
181 fn read(&mut self) -> nb::Result<u8, Error<E>> {
182 let mut buf: [u8; 1] = [0];
183 let cmd: MpsseCmdBuilder = MpsseCmdBuilder::new()
184 .clock_data(self.pol.clk, &buf)
185 .send_immediate();
186
187 let mut lock = self.mtx.lock().expect("Failed to aquire FTDI mutex");
188 match lock.ft.xfer(cmd.as_slice(), &mut buf) {
189 Ok(()) => Ok(buf[0]),
190 Err(e) => Err(nb::Error::Other(Error::from(e))),
191 }
192 }
193
194 fn send(&mut self, byte: u8) -> nb::Result<(), Error<E>> {
195 let cmd: MpsseCmdBuilder = MpsseCmdBuilder::new()
196 .clock_data_out(self.pol.clk_out, &[byte])
197 .send_immediate();
198
199 let mut lock = self.mtx.lock().expect("Failed to aquire FTDI mutex");
200 match lock.ft.send(cmd.as_slice()) {
201 Ok(()) => Ok(()),
202 Err(e) => Err(nb::Error::Other(Error::from(e))),
203 }
204 }
205}
206
207impl<E> eh1::spi::Error for Error<E>
208where
209 E: std::error::Error,
210 Error<E>: From<E>,
211{
212 fn kind(&self) -> eh1::spi::ErrorKind {
213 eh1::spi::ErrorKind::Other
214 }
215}
216
217impl<Device, E> eh1::spi::ErrorType for Spi<Device>
218where
219 Device: MpsseCmdExecutor<Error = E>,
220 E: std::error::Error,
221 Error<E>: From<E>,
222{
223 type Error = Error<E>;
224}
225
226impl<Device, E> eh1::spi::SpiBus<u8> for Spi<Device>
227where
228 Device: MpsseCmdExecutor<Error = E>,
229 E: std::error::Error,
230 Error<E>: From<E>,
231{
232 fn read(&mut self, words: &mut [u8]) -> Result<(), Self::Error> {
233 let data_out: Vec<u8> = vec![0; words.len()];
234 let cmd: MpsseCmdBuilder = MpsseCmdBuilder::new()
235 .clock_data(self.pol.clk, &data_out)
236 .send_immediate();
237
238 let mut lock = self.mtx.lock().expect("Failed to aquire FTDI mutex");
239 lock.ft.send(cmd.as_slice())?;
240 lock.ft.recv(words)?;
241
242 Ok(())
243 }
244
245 fn write(&mut self, words: &[u8]) -> Result<(), Error<E>> {
246 let cmd: MpsseCmdBuilder = MpsseCmdBuilder::new()
247 .clock_data_out(self.pol.clk_out, words)
248 .send_immediate();
249
250 let mut lock = self.mtx.lock().expect("Failed to aquire FTDI mutex");
251 lock.ft.send(cmd.as_slice())?;
252
253 Ok(())
254 }
255
256 fn flush(&mut self) -> Result<(), Self::Error> {
257 Ok(())
258 }
259
260 fn transfer_in_place(&mut self, words: &mut [u8]) -> Result<(), Error<E>> {
261 let cmd: MpsseCmdBuilder = MpsseCmdBuilder::new()
262 .clock_data(self.pol.clk, words)
263 .send_immediate();
264
265 let mut lock = self.mtx.lock().expect("Failed to aquire FTDI mutex");
266
267 lock.ft.send(cmd.as_slice())?;
268 lock.ft.recv(words)?;
269
270 Ok(())
271 }
272
273 fn transfer(&mut self, read: &mut [u8], write: &[u8]) -> Result<(), Error<E>> {
274 let cmd: MpsseCmdBuilder = MpsseCmdBuilder::new()
275 .clock_data(self.pol.clk, write)
276 .send_immediate();
277
278 let mut lock = self.mtx.lock().expect("Failed to aquire FTDI mutex");
279 lock.ft.send(cmd.as_slice())?;
280 lock.ft.recv(read)?;
281
282 let remain: usize = write.len().saturating_sub(read.len());
283 if remain != 0 {
284 let mut remain_buf: Vec<u8> = vec![0; remain];
285 lock.ft.recv(&mut remain_buf)?;
286 }
287
288 Ok(())
289 }
290}
291
292impl<Device, E> ehnb1::spi::FullDuplex<u8> for Spi<Device>
293where
294 Device: MpsseCmdExecutor<Error = E>,
295 E: std::error::Error,
296 Error<E>: From<E>,
297{
298 fn read(&mut self) -> nb::Result<u8, Error<E>> {
299 let mut buf: [u8; 1] = [0];
300 let cmd: MpsseCmdBuilder = MpsseCmdBuilder::new()
301 .clock_data(self.pol.clk, &buf)
302 .send_immediate();
303
304 let mut lock = self.mtx.lock().expect("Failed to aquire FTDI mutex");
305 match lock.ft.xfer(cmd.as_slice(), &mut buf) {
306 Ok(()) => Ok(buf[0]),
307 Err(e) => Err(nb::Error::Other(Error::from(e))),
308 }
309 }
310
311 fn write(&mut self, byte: u8) -> nb::Result<(), Error<E>> {
312 let cmd: MpsseCmdBuilder = MpsseCmdBuilder::new()
313 .clock_data_out(self.pol.clk_out, &[byte])
314 .send_immediate();
315
316 let mut lock = self.mtx.lock().expect("Failed to aquire FTDI mutex");
317 match lock.ft.send(cmd.as_slice()) {
318 Ok(()) => Ok(()),
319 Err(e) => Err(nb::Error::Other(Error::from(e))),
320 }
321 }
322}
323
324pub struct SpiDeviceBus<'a, Device: MpsseCmdExecutor> {
325 lock: MutexGuard<'a, FtInner<Device>>,
326 pol: Polarity,
327}
328
329impl<Device, E> eh1::spi::ErrorType for SpiDeviceBus<'_, Device>
330where
331 Device: MpsseCmdExecutor<Error = E>,
332 E: std::error::Error,
333 Error<E>: From<E>,
334{
335 type Error = Error<E>;
336}
337
338impl<Device, E> eh1::spi::SpiBus<u8> for SpiDeviceBus<'_, Device>
339where
340 Device: MpsseCmdExecutor<Error = E>,
341 E: std::error::Error,
342 Error<E>: From<E>,
343{
344 fn read(&mut self, words: &mut [u8]) -> Result<(), Self::Error> {
345 self.lock.ft.xfer(
346 MpsseCmdBuilder::new()
347 .clock_data(self.pol.clk, words)
348 .send_immediate()
349 .as_slice(),
350 words,
351 )?;
352 Ok(())
353 }
354
355 fn write(&mut self, words: &[u8]) -> Result<(), Self::Error> {
356 self.lock.ft.send(
357 MpsseCmdBuilder::new()
358 .clock_data_out(self.pol.clk_out, words)
359 .send_immediate()
360 .as_slice(),
361 )?;
362 Ok(())
363 }
364
365 fn flush(&mut self) -> Result<(), Self::Error> {
366 Ok(())
367 }
368
369 fn transfer(&mut self, read: &mut [u8], write: &[u8]) -> Result<(), Self::Error> {
370 self.lock.ft.xfer(
371 MpsseCmdBuilder::new()
372 .clock_data(self.pol.clk, write)
373 .send_immediate()
374 .as_slice(),
375 read,
376 )?;
377 Ok(())
378 }
379
380 fn transfer_in_place(&mut self, words: &mut [u8]) -> Result<(), Self::Error> {
381 self.lock.ft.xfer(
382 MpsseCmdBuilder::new()
383 .clock_data(self.pol.clk, words)
384 .send_immediate()
385 .as_slice(),
386 words,
387 )?;
388 Ok(())
389 }
390}
391
392#[derive(Debug)]
400pub struct SpiDevice<Device: MpsseCmdExecutor> {
401 mtx: Arc<Mutex<FtInner<Device>>>,
403 pol: Polarity,
405 cs_idx: u8,
407}
408
409impl<Device, E> SpiDevice<Device>
410where
411 Device: MpsseCmdExecutor<Error = E>,
412 E: std::error::Error,
413 Error<E>: From<E>,
414{
415 pub(crate) fn new(
416 mtx: Arc<Mutex<FtInner<Device>>>,
417 cs_idx: u8,
418 ) -> Result<SpiDevice<Device>, Error<E>> {
419 {
420 let mut lock = mtx.lock().expect("Failed to aquire FTDI mutex");
421 lock.allocate_pin(0, PinUse::Spi);
422 lock.allocate_pin(1, PinUse::Spi);
423 lock.allocate_pin(2, PinUse::Spi);
424 lock.allocate_pin(cs_idx, PinUse::Output);
425
426 let cs_mask: u8 = 1 << cs_idx;
427
428 lock.direction &= !(0x07 | cs_mask);
430 lock.direction |= 0x03 | cs_mask;
432
433 let cmd: MpsseCmdBuilder = MpsseCmdBuilder::new()
435 .set_gpio_lower(lock.value, lock.direction)
436 .send_immediate();
437 lock.ft.send(cmd.as_slice())?;
438 }
439
440 Ok(Self {
441 mtx,
442 pol: Default::default(),
443 cs_idx,
444 })
445 }
446
447 pub(crate) fn cs_mask(&self) -> u8 {
448 1 << self.cs_idx
449 }
450
451 pub fn set_clock_polarity<P: Into<Polarity>>(&mut self, cpol: P) {
473 self.pol = cpol.into()
474 }
475}
476
477impl<Device, E> eh1::spi::ErrorType for SpiDevice<Device>
478where
479 Device: MpsseCmdExecutor<Error = E>,
480 E: std::error::Error,
481 Error<E>: From<E>,
482{
483 type Error = Error<E>;
484}
485
486impl<Device, E> eh1::spi::SpiDevice for SpiDevice<Device>
487where
488 Device: MpsseCmdExecutor<Error = E>,
489 E: std::error::Error,
490 Error<E>: From<E>,
491{
492 fn transaction(
493 &mut self,
494 operations: &mut [eh1::spi::Operation<'_, u8>],
495 ) -> Result<(), Self::Error> {
496 let mut lock: MutexGuard<FtInner<Device>> =
498 self.mtx.lock().expect("Failed to aquire FTDI mutex");
499 let direction: u8 = lock.direction;
500
501 let mut value_cs_asserted: u8 = lock.value & !self.cs_mask();
503
504 match self.pol.clk {
507 ClockData::MsbNegIn | ClockData::LsbNegIn => {
508 value_cs_asserted |= 1;
509 }
510 ClockData::MsbPosIn | ClockData::LsbPosIn => {
511 value_cs_asserted &= !1;
512 }
513 }
514
515 lock.ft.send(
516 MpsseCmdBuilder::new()
517 .set_gpio_lower(value_cs_asserted, direction)
518 .send_immediate()
519 .as_slice(),
520 )?;
521
522 let mut bus: SpiDeviceBus<Device> = SpiDeviceBus {
523 lock,
524 pol: self.pol,
525 };
526
527 for op in operations {
528 match op {
529 eh1::spi::Operation::Read(buffer) => {
530 eh1::spi::SpiBus::read(&mut bus, buffer)?;
531 }
532 eh1::spi::Operation::Write(buffer) => {
533 eh1::spi::SpiBus::write(&mut bus, buffer)?;
534 }
535 eh1::spi::Operation::Transfer(read, write) => {
536 eh1::spi::SpiBus::transfer(&mut bus, read, write)?;
537 }
538 eh1::spi::Operation::TransferInPlace(buffer) => {
539 eh1::spi::SpiBus::transfer_in_place(&mut bus, buffer)?;
540 }
541 eh1::spi::Operation::DelayNs(micros) => {
542 std::thread::sleep(std::time::Duration::from_nanos((*micros).into()));
543 }
544 }
545 }
546
547 {
549 use eh1::spi::SpiBus;
550 bus.flush()?;
551 }
552
553 let mut lock: MutexGuard<FtInner<Device>> = bus.lock;
554
555 let mut value_cs_deasserted: u8 = lock.value | self.cs_mask();
557
558 match self.pol.clk {
561 ClockData::MsbNegIn | ClockData::LsbNegIn => {
562 value_cs_deasserted |= 1;
563 }
564 ClockData::MsbPosIn | ClockData::LsbPosIn => {
565 value_cs_deasserted &= !1;
566 }
567 }
568
569 lock.ft.send(
570 MpsseCmdBuilder::new()
571 .set_gpio_lower(value_cs_deasserted, direction)
572 .send_immediate()
573 .as_slice(),
574 )?;
575
576 Ok(())
578 }
579}