Skip to content

Commit 5f56b5c

Browse files
committed
add Rust GPIO support
1 parent 242c49b commit 5f56b5c

File tree

3 files changed

+110
-0
lines changed

3 files changed

+110
-0
lines changed

clients/jabi-rs/src/lib.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ mod error;
33
mod interfaces;
44
mod peripherals {
55
pub mod can;
6+
pub mod gpio;
67
pub mod i2c;
78
pub mod metadata;
89
}
@@ -16,6 +17,8 @@ pub use crate::interfaces::usb;
1617
pub use crate::peripherals::can::CANMessage;
1718
pub use crate::peripherals::can::CANMode;
1819
pub use crate::peripherals::can::CANState;
20+
pub use crate::peripherals::gpio::GPIODir;
21+
pub use crate::peripherals::gpio::GPIOPull;
1922
pub use crate::peripherals::i2c::I2CFreq;
2023
pub use crate::peripherals::metadata::InstID;
2124

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
use crate::interfaces::InterfaceRequest;
2+
use crate::Error;
3+
use deku::{DekuContainerRead, DekuContainerWrite, DekuRead, DekuUpdate, DekuWrite};
4+
5+
pub enum GPIODir {
6+
Input = 0,
7+
Output = 1,
8+
OpenDrain = 2,
9+
OpenSource = 3,
10+
}
11+
12+
pub enum GPIOPull {
13+
None = 0,
14+
Up = 1,
15+
Down = 2,
16+
Both = 3,
17+
}
18+
19+
enum Func {
20+
SetMode = 0,
21+
Write = 1,
22+
Read = 2,
23+
}
24+
25+
fn gen_req(f: Func, idx: usize, payload: Vec<u8>) -> Result<InterfaceRequest, Error> {
26+
let mut r = InterfaceRequest {
27+
periph_id: crate::InstID::GPIO as u16,
28+
periph_idx: idx as u16,
29+
periph_fn: f as u16,
30+
payload_len: 0,
31+
payload: payload,
32+
};
33+
r.update().map_or(Err(Error::PacketFormat), |_| Ok(r))
34+
}
35+
36+
impl crate::Device {
37+
pub fn gpio_set_mode(
38+
&self,
39+
idx: usize,
40+
dir: GPIODir,
41+
pull: GPIOPull,
42+
init_val: bool,
43+
) -> Result<(), Error> {
44+
#[derive(DekuWrite)]
45+
#[deku(endian = "little")]
46+
struct SetModeRequest {
47+
direction: u8,
48+
pull: u8,
49+
init_val: u8,
50+
}
51+
let req = SetModeRequest {
52+
direction: dir as u8,
53+
pull: pull as u8,
54+
init_val: init_val as u8,
55+
};
56+
let resp = self.send(&gen_req(Func::SetMode, idx, req.to_bytes().unwrap())?)?;
57+
if resp.len() == 0 {
58+
Ok(())
59+
} else {
60+
Err(Error::PacketFormat)
61+
}
62+
}
63+
64+
pub fn gpio_write(&self, idx: usize, val: bool) -> Result<(), Error> {
65+
#[derive(DekuWrite)]
66+
#[deku(endian = "little")]
67+
struct WriteRequest {
68+
val: u8,
69+
}
70+
let req = WriteRequest { val: val as u8 };
71+
let resp = self.send(&gen_req(Func::Write, idx, req.to_bytes().unwrap())?)?;
72+
if resp.len() == 0 {
73+
Ok(())
74+
} else {
75+
Err(Error::PacketFormat)
76+
}
77+
}
78+
79+
pub fn gpio_read(&self, idx: usize) -> Result<bool, Error> {
80+
#[derive(DekuRead)]
81+
#[deku(endian = "little")]
82+
struct ReadResponse {
83+
val: u8,
84+
}
85+
let resp = self.send(&gen_req(Func::Read, idx, vec![])?)?;
86+
match ReadResponse::from_bytes((&resp, 0)) {
87+
Ok(((s, _), ret)) if s.len() == 0 => Ok(ret.val != 0),
88+
_ => Err(Error::PacketFormat),
89+
}
90+
}
91+
}

examples/jabi-rs/src/main.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,22 @@ fn test_device(d: &jabi::Device) -> Result<(), jabi::Error> {
4141
}
4242
println!();
4343

44+
// GPIO
45+
for i in 0..d.num_inst(jabi::InstID::GPIO)? {
46+
println!("\tFlashing GPIO {i}");
47+
d.gpio_set_mode(i, jabi::GPIODir::Output, jabi::GPIOPull::None, false)?;
48+
for _ in 0..6 {
49+
d.gpio_write(i, false)?;
50+
std::thread::sleep(std::time::Duration::from_millis(25));
51+
d.gpio_write(i, true)?;
52+
std::thread::sleep(std::time::Duration::from_millis(25));
53+
}
54+
}
55+
for i in 0..d.num_inst(jabi::InstID::GPIO)? {
56+
d.gpio_set_mode(i, jabi::GPIODir::Input, jabi::GPIOPull::Up, false)?;
57+
println!("\tRead GPIO {i} w/ pullups: {}", d.gpio_read(i)?);
58+
}
59+
4460
Ok(())
4561
}
4662

0 commit comments

Comments
 (0)