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