1
2
3use linux_embedded_hal::SpidevBus;
4pub use linux_embedded_hal::{
5 spidev, spidev::SpiModeFlags, Delay, SpidevDevice, SysfsPin as Pindev,
6 sysfs_gpio::{Direction, Error as PinError},
7};
8use embedded_hal_bus::spi::{ExclusiveDevice, NoDelay};
9
10use super::*;
11
12pub struct LinuxDriver;
13
14pub type LinuxSpiDevice = ExclusiveDevice<SpidevBus, Pindev, NoDelay>;
15
16impl LinuxDriver {
17 pub fn new(path: &str, spi: &SpiConfig, pins: &PinConfig) -> Result<HalInst, HalError> {
19 let mut flags = match spi.mode {
20 0 => SpiModeFlags::SPI_MODE_0,
21 1 => SpiModeFlags::SPI_MODE_1,
22 2 => SpiModeFlags::SPI_MODE_2,
23 3 => SpiModeFlags::SPI_MODE_3,
24 _ => return Err(HalError::InvalidSpiMode),
25 };
26
27 flags |= SpiModeFlags::SPI_NO_CS;
28
29 debug!(
30 "Conecting to spi: {} at {} baud with mode: {:?}",
31 path, spi.baud, flags
32 );
33
34 let spi_bus = load_spi(path, spi.baud, flags)?;
35 let spi_cs = load_pin(pins.chip_select, Direction::Out)?;
36 let spi = ExclusiveDevice::new_no_delay(spi_bus, spi_cs);
37
38 let pins = Self::load_pins(pins)?;
39
40 Ok(HalInst {
41 base: HalBase::None,
42 spi: HalSpi::Linux(spi),
43 pins,
44 })
45 }
46
47 fn load_pins(pins: &PinConfig) -> Result<HalPins, HalError> {
49 let reset = load_pin(pins.reset, Direction::Out)?;
50
51 let busy = match pins.busy {
52 Some(p) => HalInputPin::Linux(load_pin(p, Direction::In)?),
53 None => HalInputPin::None,
54 };
55
56 let ready = match pins.ready {
57 Some(p) => HalInputPin::Linux(load_pin(p, Direction::In)?),
58 None => HalInputPin::None,
59 };
60
61 let led0 = match pins.led0 {
62 Some(p) => HalOutputPin::Linux(load_pin(p, Direction::Out)?),
63 None => HalOutputPin::None,
64 };
65
66 let led1 = match pins.led1 {
67 Some(p) => HalOutputPin::Linux(load_pin(p, Direction::Out)?),
68 None => HalOutputPin::None,
69 };
70
71 let pins = HalPins {
72 reset: HalOutputPin::Linux(reset),
73 busy,
74 ready,
75 led0,
76 led1,
77 };
78
79 Ok(pins)
80 }
81}
82
83fn load_spi(path: &str, baud: u32, mode: spidev::SpiModeFlags) -> Result<SpidevBus, HalError> {
85 debug!(
86 "Conecting to spi: {} at {} baud with mode: {:?}",
87 path, baud, mode
88 );
89
90 let mut spi = SpidevBus::open(path)?;
91
92 let mut config = spidev::SpidevOptions::new();
93 config.mode(SpiModeFlags::SPI_MODE_0 | SpiModeFlags::SPI_NO_CS);
94 config.max_speed_hz(baud);
95 spi.configure(&config)?;
96
97 Ok(spi)
98}
99
100fn load_pin(index: u64, direction: Direction) -> Result<Pindev, HalError> {
102 debug!(
103 "Connecting to pin: {} with direction: {:?}",
104 index, direction
105 );
106
107 let p = Pindev::new(index);
108 p.export()?;
109 p.set_direction(direction)?;
110
111 Ok(p)
112}