This repository was archived by the owner on Jul 14, 2025. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 28
Add GPIO capability #406
Open
Quantaly
wants to merge
30
commits into
deislabs:main
Choose a base branch
from
mines-370-wasm-squad:gpio
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Add GPIO capability #406
Changes from all commits
Commits
Show all changes
30 commits
Select commit
Hold shift + click to select a range
a540a1d
Basic GPIO WIT
Quantaly a54cc53
Starting work on GPIO
Quantaly bc18e21
GPIO: Raspberry Pi pin construction
Quantaly f4ef59b
Remove the RaspberryPiImplementorInner struct
Quantaly f64c422
Implement Raspberry Pi GPIO methods
Quantaly 5f424d4
Actually call the pin destructor
Quantaly ab486e3
Applications reference GPIO pins by name
Quantaly f5b0f31
GPIO configuration
Quantaly 659a9e5
Add pullup/pulldown and initial output state
Quantaly 87c201d
Unit tests for pin configuration parsing
Quantaly 4445bf4
Made initial demo of input(pushdown) and output
joeyvong 33adb2e
Added cargo dependencies
joeyvong ddd56a7
added flicker to gpiodemo
BrendanBurm 400e0c5
Added additional documentation onto gpio demo. Added more test cases …
joeyvong f328c0e
Added documentation to tests.rs and lib.rs in gpio crate
BrendanBurm b77b6e7
Write documentation for GPIO capability stuff
Quantaly 5067c6c
Merge my GPIO documentation with Brandon's
Quantaly 424a3fc
Merge pull request #1 from mines-370-wasm-squad/gpio-dev
BrendanBurm f0f022e
Merge remote-tracking branch 'upstream/main' into gpio
Quantaly 031a844
Add PWM output pin to GPIO
Quantaly 3ad4258
Update GPIO demo with PWM
Quantaly 76fbde2
Fix bug in GPIO demo
Quantaly 1935c41
Fix other bug in GPIO demo
Quantaly 4f786fe
Specify type with annotation instead of cast
Quantaly cd18c2b
Revised documentation of gpio demo
joeyvong d7287c6
Update GPIO documentation
Quantaly c588203
Merge documentation updates
Quantaly cccea05
Use crate doc comment syntax
Quantaly e53a187
Emit warnings instead of errors for PWM
Quantaly 210aa31
Merge pull request #2 from mines-370-wasm-squad/gpio-pwm
BrendanBurm File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
[package] | ||
name = "slight-gpio" | ||
version = "0.1.0" | ||
edition = { workspace = true } | ||
authors = { workspace = true } | ||
license = { workspace = true } | ||
repository = { workspace = true } | ||
|
||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html | ||
|
||
[dependencies] | ||
anyhow = { workspace = true } | ||
rppal = { version = "0.14.1", optional = true } | ||
slight-common = { workspace = true } | ||
slight-file = { workspace = true } | ||
tracing = { workspace = true } | ||
wit-bindgen-wasmtime = { workspace = true } | ||
wit-error-rs = { workspace = true } | ||
|
||
[features] | ||
default = ["raspberry_pi"] | ||
raspberry_pi = ["dep:rppal"] |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
# GPIO support | ||
|
||
This crate provides the ability for SpiderLighting applications to interact with GPIO pins. | ||
|
||
Pins are named in the slightfile and passed a configuration string with the following slash-separated parameters: | ||
|
||
- Pin number | ||
- Pin mode | ||
- `input` | ||
- `output` | ||
- `pwm_output` | ||
- Optional mode-specific configuration | ||
- For input: `pullup` or `pulldown` | ||
- For output: initially set to `low` or `high` | ||
- For PWM output: the PWM period in microseconds, if supported by the implementation | ||
|
||
See the [example application](../../examples/gpio-demo/). | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's definitely not required to close this PR, but it might be helpful to add some comments to aid someone getting started w/ this capability – I have a Raspberry Pi at home like the one in your video, and would love to try using this (: |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,154 @@ | ||
use std::fmt::{self, Debug, Formatter}; | ||
use std::str::FromStr; | ||
use std::sync::Arc; | ||
|
||
use crate::{gpio, Pin, Pull}; | ||
|
||
#[cfg(feature = "raspberry_pi")] | ||
pub mod raspberry_pi; | ||
|
||
/// A GPIO implementation. | ||
/// | ||
/// This trait is not referred to directly by the linked capability, but is used to construct pin resources implementing the other traits in this module. | ||
pub(crate) trait GpioImplementor { | ||
/// Constructs an input pin resource. | ||
fn new_input_pin( | ||
&mut self, | ||
pin: u8, | ||
pull: Option<Pull>, | ||
) -> Result<Arc<dyn InputPinImplementor>, gpio::GpioError>; | ||
/// Constructs an output pin resource. | ||
fn new_output_pin( | ||
&mut self, | ||
pin: u8, | ||
init_level: Option<gpio::LogicLevel>, | ||
) -> Result<Arc<dyn OutputPinImplementor>, gpio::GpioError>; | ||
/// Constructs a PWM output pin resource. | ||
fn new_pwm_output_pin( | ||
&mut self, | ||
pin: u8, | ||
period_microseconds: Option<u32>, | ||
) -> Result<Arc<dyn PwmOutputPinImplementor>, gpio::GpioError>; | ||
} | ||
|
||
impl dyn GpioImplementor { | ||
/// Parse the provided configuration string and construct the appropriate pin resource. | ||
pub(crate) fn parse_pin_config(&mut self, config: &str) -> Result<Pin, gpio::GpioError> { | ||
let mut config_iter = config.split('/'); | ||
|
||
let pin_number = config_iter | ||
.next() | ||
.ok_or_else(|| gpio::GpioError::ConfigurationError(String::from("no pin number")))?; | ||
let pin_number = u8::from_str(pin_number).map_err(|e| { | ||
gpio::GpioError::ConfigurationError(format!("invalid pin number '{pin_number}': {e}")) | ||
})?; | ||
|
||
match config_iter.next() { | ||
Some("input") => { | ||
let pull = if let Some(pull) = config_iter.next() { | ||
Some(match pull { | ||
"pullup" => Pull::Up, | ||
"pulldown" => Pull::Down, | ||
_ => Err(gpio::GpioError::ConfigurationError(format!( | ||
"unknown pull setting '{pull}'" | ||
)))?, | ||
}) | ||
} else { | ||
None | ||
}; | ||
if config_iter.next().is_some() { | ||
return Err(gpio::GpioError::ConfigurationError(String::from( | ||
"too many fields for input pin", | ||
))); | ||
} | ||
self.new_input_pin(pin_number, pull).map(Pin::Input) | ||
} | ||
Some("output") => { | ||
let init_level = if let Some(init_level) = config_iter.next() { | ||
Some(match init_level { | ||
"low" => gpio::LogicLevel::Low, | ||
"high" => gpio::LogicLevel::High, | ||
_ => Err(gpio::GpioError::ConfigurationError(format!( | ||
"unknown initial level '{init_level}'" | ||
)))?, | ||
}) | ||
} else { | ||
None | ||
}; | ||
if config_iter.next().is_some() { | ||
return Err(gpio::GpioError::ConfigurationError(String::from( | ||
"too many fields for output pin", | ||
))); | ||
} | ||
self.new_output_pin(pin_number, init_level).map(Pin::Output) | ||
} | ||
Some("pwm_output") => { | ||
let period_microseconds = if let Some(period_microseconds) = config_iter.next() { | ||
u32::from_str(period_microseconds).map(Some).map_err(|e| { | ||
gpio::GpioError::ConfigurationError(format!( | ||
"invalid period length '{period_microseconds}': {e}" | ||
)) | ||
})? | ||
} else { | ||
None | ||
}; | ||
if config_iter.next().is_some() { | ||
return Err(gpio::GpioError::ConfigurationError(String::from( | ||
"too many fields for PWM output pin", | ||
))); | ||
} | ||
self.new_pwm_output_pin(pin_number, period_microseconds) | ||
.map(Pin::PwmOutput) | ||
} | ||
Some(unknown_type) => Err(gpio::GpioError::ConfigurationError(format!( | ||
"unknown pin type '{unknown_type}'" | ||
))), | ||
None => Err(gpio::GpioError::ConfigurationError(String::from( | ||
"no pin type", | ||
))), | ||
} | ||
} | ||
} | ||
|
||
/// An implementation of an input pin resource. | ||
pub trait InputPinImplementor: Send + Sync { | ||
/// Read the current logic level to the pin. | ||
fn read(&self) -> gpio::LogicLevel; | ||
} | ||
|
||
impl Debug for dyn InputPinImplementor { | ||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { | ||
f.debug_struct("InputPinImplementor") | ||
.finish_non_exhaustive() | ||
} | ||
} | ||
|
||
/// An implementation of an output pin resource. | ||
pub trait OutputPinImplementor: Send + Sync { | ||
/// Write the given logic level to the pin. | ||
fn write(&self, level: gpio::LogicLevel); | ||
} | ||
|
||
impl Debug for dyn OutputPinImplementor { | ||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { | ||
f.debug_struct("OutputPinImplementor") | ||
.finish_non_exhaustive() | ||
} | ||
} | ||
|
||
/// An implementation of a PWM output pin resource. | ||
pub trait PwmOutputPinImplementor: Send + Sync { | ||
/// Configure the pin with the given parameters. This does not enable it if it is disabled. | ||
fn set_duty_cycle(&self, duty_cycle: f32); | ||
/// Enable the pin's output. | ||
fn enable(&self); | ||
/// Disable the pin's output. | ||
fn disable(&self); | ||
} | ||
|
||
impl Debug for dyn PwmOutputPinImplementor { | ||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { | ||
f.debug_struct("PwmOutputPinImplementor") | ||
.finish_non_exhaustive() | ||
} | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please add your names to the authors of this crate