Skip to main content

jtag_scanner/protocols/
pin.rs

1//! Adapters for [embedded_hal::digital]. This is the only protocol module
2//! that is not behind another feature gate; it is also the only protocol
3//! module that does not use [PinGroup](crate::PinGroup).
4
5use std::{cell::RefCell, rc::Rc};
6
7use embedded_hal::digital::{
8    OutputPin,
9    PinState::{High, Low},
10};
11
12use crate::{Error, ErrorKind::WrongPinType, PinId, PinScanner};
13
14impl embedded_hal::digital::Error for Error {
15    fn kind(&self) -> embedded_hal::digital::ErrorKind {
16        embedded_hal::digital::ErrorKind::Other
17    }
18}
19
20/// Input-only pin that implements [embedded_hal::digital::InputPin].
21pub struct In {
22    scanner: Rc<RefCell<PinScanner>>,
23    pin_id: PinId,
24}
25
26impl In {
27    /// Creates the adapter.
28    pub fn new(scanner: &Rc<RefCell<PinScanner>>, pin_id: PinId) -> Result<Self, Error> {
29        if !pin_id.is_input() {
30            return Error::result(WrongPinType, "not input pin");
31        }
32        Ok(Self {
33            scanner: scanner.clone(),
34            pin_id,
35        })
36    }
37}
38
39impl embedded_hal::digital::ErrorType for In {
40    type Error = Error;
41}
42
43impl embedded_hal::digital::InputPin for In {
44    fn is_high(&mut self) -> Result<bool, Self::Error> {
45        let mut scanner = self.scanner.try_borrow_mut()?;
46        scanner.update()?;
47        scanner
48            .get_pin_state(&self.pin_id)
49            .map(|st| st.input.unwrap())
50    }
51    fn is_low(&mut self) -> Result<bool, Self::Error> {
52        self.is_high().map(|v| !v)
53    }
54}
55
56/// Output-only pin that implements [embedded_hal::digital::OutputPin].
57pub struct Out {
58    scanner: Rc<RefCell<PinScanner>>,
59    pin_id: PinId,
60}
61
62impl Out {
63    /// Creates the adapter.
64    pub fn new(scanner: &Rc<RefCell<PinScanner>>, pin_id: PinId) -> Result<Self, Error> {
65        if !pin_id.is_output() {
66            return Error::result(WrongPinType, "not output pin");
67        }
68        Ok(Self {
69            scanner: scanner.clone(),
70            pin_id,
71        })
72    }
73}
74
75impl embedded_hal::digital::ErrorType for Out {
76    type Error = Error;
77}
78
79impl embedded_hal::digital::OutputPin for Out {
80    fn set_high(&mut self) -> Result<(), Self::Error> {
81        self.set_state(High)
82    }
83    fn set_low(&mut self) -> Result<(), Self::Error> {
84        self.set_state(Low)
85    }
86    fn set_state(&mut self, state: embedded_hal::digital::PinState) -> Result<(), Self::Error> {
87        let mut scanner = self.scanner.try_borrow_mut()?;
88        scanner.set_pin_state(&self.pin_id, Some(state == High))?;
89        scanner.write_update()
90    }
91}
92
93/// Input and output pin that implements [embedded_hal::digital::InputPin]
94/// and [embedded_hal::digital::OutputPin].
95pub struct InOut {
96    scanner: Rc<RefCell<PinScanner>>,
97    pin_id: PinId,
98
99    // false if the output should keep disabled on the next `set_state` call.
100    output_enable: bool,
101
102    // the value for output, when output is enabled; it is the value to recover
103    // when this pin is switched from disabled state to enabled state.
104    output_value: Option<bool>,
105}
106
107impl InOut {
108    /// Creates the adapter.
109    /// - `init_val`: this is used to call `PinScanner::set_pin_state` for
110    ///   making clear of the initial state. If it is `None`, the output will
111    ///   be disabled until [Self::set_output_enable] is called with `true`.
112    pub fn new(
113        scanner: &Rc<RefCell<PinScanner>>,
114        pin_id: PinId,
115        init_val: Option<bool>,
116    ) -> Result<Self, Error> {
117        if !pin_id.is_input() || !pin_id.is_output() {
118            return Error::result(WrongPinType, "not input + output pin");
119        }
120
121        let mut sc = scanner.try_borrow_mut()?;
122        sc.set_pin_state(&pin_id, init_val)?;
123        sc.write_update()?;
124
125        Ok(Self {
126            scanner: scanner.clone(),
127            pin_id,
128            output_enable: init_val.is_some(),
129            output_value: init_val,
130        })
131    }
132
133    /// If the pin is tristated, disables output immediately if `val` is false;
134    /// otherwise enables output: it is enabled immediately if there is a
135    /// previously remembered value; without a previously set value, it is
136    /// enabled on the next `set_state` call (including `set_low`, `set_high`).
137    ///
138    /// If the pin is not tristated, returns error if `val` is false, otherwise
139    /// does nothing.
140    pub fn set_output_enable(&mut self, enable: bool) -> Result<(), Error> {
141        if enable == self.output_enable {
142            return Ok(());
143        }
144        if !self.pin_id.is_tristates() {
145            if !enable {
146                return Error::result(WrongPinType, "not tristated pin");
147            }
148            return Ok(());
149        }
150        if enable {
151            self.output_enable = true;
152            if let Some(&last_output) = self.output_value.as_ref() {
153                self.set_state(if last_output { High } else { Low })?;
154            }
155        } else {
156            let mut sc = self.scanner.try_borrow_mut()?;
157            sc.set_pin_state(&self.pin_id, None)?;
158            sc.write_update()?;
159            self.output_enable = false;
160        }
161        Ok(())
162    }
163}
164
165impl embedded_hal::digital::ErrorType for InOut {
166    type Error = Error;
167}
168
169impl embedded_hal::digital::InputPin for InOut {
170    fn is_high(&mut self) -> Result<bool, Self::Error> {
171        let mut scanner = self.scanner.try_borrow_mut()?;
172        scanner.update()?;
173        scanner
174            .get_pin_state(&self.pin_id)
175            .map(|st| st.input.unwrap())
176    }
177    fn is_low(&mut self) -> Result<bool, Self::Error> {
178        self.is_high().map(|v| !v)
179    }
180}
181
182impl embedded_hal::digital::OutputPin for InOut {
183    fn set_high(&mut self) -> Result<(), Self::Error> {
184        self.set_state(High)
185    }
186    fn set_low(&mut self) -> Result<(), Self::Error> {
187        self.set_state(Low)
188    }
189    fn set_state(&mut self, state: embedded_hal::digital::PinState) -> Result<(), Self::Error> {
190        self.output_value = Some(state == High);
191        if self.output_enable {
192            let mut scanner = self.scanner.try_borrow_mut()?;
193            scanner.set_pin_state(&self.pin_id, self.output_value)?;
194            scanner.write_update()?;
195        }
196        Ok(())
197    }
198}