opentitanlib/transport/dediprog/
gpio.rs1use std::cell::RefCell;
6use std::collections::HashMap;
7use std::rc::Rc;
8use std::sync::LazyLock;
9
10use anyhow::{Result, ensure};
11
12use crate::collection;
13use crate::io::gpio::{GpioError, GpioPin, PinMode, PullMode};
14use crate::transport::dediprog::Inner;
15use crate::util::parse_int::ParseInt;
16
17pub struct DediprogPin {
18 inner: Rc<RefCell<Inner>>,
19 index: u8,
20}
21
22impl DediprogPin {
23 const LAST_PIN_NUM: u8 = 15;
24
25 pub fn open(inner: Rc<RefCell<Inner>>, pinname: &str) -> Result<Self> {
26 Ok(Self {
27 inner,
28 index: Self::pin_name_to_number(pinname)?,
29 })
30 }
31
32 pub fn pin_name_to_number(pinname: &str) -> Result<u8> {
34 if let Ok(pinnum) = u8::from_str(pinname) {
37 ensure!(
38 pinnum <= Self::LAST_PIN_NUM,
39 GpioError::InvalidPinNumber(pinnum)
40 );
41 return Ok(pinnum);
42 }
43 let pinname = pinname.to_uppercase();
44 let pn = pinname.as_str();
45 PIN_NAMES
46 .get(pn)
47 .copied()
48 .ok_or_else(|| GpioError::InvalidPinName(pinname).into())
49 }
50}
51
52impl GpioPin for DediprogPin {
53 fn read(&self) -> Result<bool> {
54 Ok(self.inner.borrow().gpio_levels & (1 << self.index) != 0)
55 }
56
57 fn write(&self, value: bool) -> Result<()> {
58 let mut inner = self.inner.borrow_mut();
59 if value {
60 inner.gpio_levels |= 1u16 << self.index
61 } else {
62 inner.gpio_levels &= !(1u16 << self.index)
63 }
64 inner.set_gpio_levels()
65 }
66
67 fn set_mode(&self, mode: PinMode) -> Result<()> {
68 match mode {
69 PinMode::PushPull => Ok(()),
70 _ => Err(GpioError::UnsupportedPinMode(mode).into()),
71 }
72 }
73
74 fn set_pull_mode(&self, mode: PullMode) -> Result<()> {
75 match mode {
76 PullMode::None => Ok(()),
77 _ => Err(GpioError::UnsupportedPullMode(mode).into()),
78 }
79 }
80}
81
82static PIN_NAMES: LazyLock<HashMap<&'static str, u8>> = LazyLock::new(|| {
83 collection! {
84 "IO2" => 0,
85 "IO1" => 1,
86 "IO3" => 2,
87 "IO4" => 3,
88 "PASS_LED" => 8,
89 "BUSY_LED" => 9,
90 "ERROR_LED" => 10,
91 }
92});