1use endbasic_std::gpio::{Pin, PinMode, Pins};
19use rppal::gpio;
20use std::collections::HashMap;
21use std::io;
22
23#[derive(Default)]
25pub struct RppalPins {
26 chip: Option<gpio::Gpio>,
27 inputs: HashMap<Pin, gpio::InputPin>,
28 outputs: HashMap<Pin, gpio::OutputPin>,
29}
30
31pub(crate) fn gpio_error_to_io_error(e: gpio::Error) -> io::Error {
33 match e {
34 gpio::Error::Io(e) => e,
35 gpio::Error::PermissionDenied(path) => io::Error::new(
36 io::ErrorKind::PermissionDenied,
37 format!("Cannot open {}: permission denied", path),
38 ),
39 gpio::Error::PinNotAvailable(pin) => {
40 io::Error::new(io::ErrorKind::InvalidInput, format!("Unknown pin number {}", pin))
41 }
42 e => io::Error::new(io::ErrorKind::Other, e.to_string()),
43 }
44}
45
46impl RppalPins {
47 fn get_chip(&mut self) -> io::Result<&mut gpio::Gpio> {
49 if self.chip.is_none() {
50 self.chip = Some(gpio::Gpio::new().map_err(gpio_error_to_io_error)?);
51 }
52 Ok(self.chip.as_mut().unwrap())
53 }
54}
55
56impl Pins for RppalPins {
57 fn setup(&mut self, pin: Pin, mode: PinMode) -> io::Result<()> {
58 self.clear(pin)?;
59 let chip = self.get_chip()?;
60 let gpio_pin = chip.get(pin.0).map_err(gpio_error_to_io_error)?;
61 match mode {
62 PinMode::In => {
63 self.inputs.insert(pin, gpio_pin.into_input());
64 }
65 PinMode::InPullDown => {
66 self.inputs.insert(pin, gpio_pin.into_input_pulldown());
67 }
68 PinMode::InPullUp => {
69 self.inputs.insert(pin, gpio_pin.into_input_pullup());
70 }
71 PinMode::Out => {
72 self.outputs.insert(pin, gpio_pin.into_output());
73 }
74 };
75 Ok(())
76 }
77
78 fn clear(&mut self, pin: Pin) -> io::Result<()> {
79 self.inputs.remove(&pin);
80 self.outputs.remove(&pin);
81 Ok(())
82 }
83
84 fn clear_all(&mut self) -> io::Result<()> {
85 self.inputs.clear();
86 self.outputs.clear();
87 Ok(())
88 }
89
90 fn read(&mut self, pin: Pin) -> io::Result<bool> {
91 if !self.inputs.contains_key(&pin) || self.outputs.contains_key(&pin) {
92 return Err(io::Error::new(
93 io::ErrorKind::AlreadyExists,
94 "Pin not configured for read; use GPIO_SETUP first",
95 ));
96 }
97 let pin = self.inputs.get(&pin).unwrap();
98 match pin.read() {
99 gpio::Level::High => Ok(true),
100 gpio::Level::Low => Ok(false),
101 }
102 }
103
104 fn write(&mut self, pin: Pin, v: bool) -> io::Result<()> {
105 if self.inputs.contains_key(&pin) || !self.outputs.contains_key(&pin) {
106 return Err(io::Error::new(
107 io::ErrorKind::AlreadyExists,
108 "Pin not configured for write; use GPIO_SETUP first",
109 ));
110 }
111 let pin = self.outputs.get_mut(&pin).unwrap();
112 if v {
113 pin.write(gpio::Level::High);
114 } else {
115 pin.write(gpio::Level::Low);
116 }
117 Ok(())
118 }
119}