-
Notifications
You must be signed in to change notification settings - Fork 30
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add GPIO capability #406
base: main
Are you sure you want to change the base?
Add GPIO capability #406
Conversation
Signed-off-by: Kai Page <kai@quantaly.net>
Signed-off-by: Kai Page <kai@quantaly.net>
Signed-off-by: Kai Page <kai@quantaly.net>
Signed-off-by: Kai Page <kai@quantaly.net>
Signed-off-by: Kai Page <kai@quantaly.net>
Signed-off-by: Kai Page <kai@quantaly.net>
Signed-off-by: Kai Page <kai@quantaly.net>
Signed-off-by: Kai Page <kai@quantaly.net>
Signed-off-by: Kai Page <kai@quantaly.net>
Signed-off-by: Kai Page <kai@quantaly.net>
Signed-off-by: joeyvongphasouk <joey.vongpha@gmail.com>
Signed-off-by: joeyvongphasouk <joey.vongpha@gmail.com>
Signed-off-by: brendan burmeister <brendanburmeister@mines.edu>
…for gpio unit tests. Signed-off-by: joeyvongphasouk <joey.vongpha@gmail.com>
Signed-off-by: Kai Page <kai@quantaly.net>
Signed-off-by: Kai Page <kai@quantaly.net>
Stage current GPIO work
Signed-off-by: Kai Page <kai@quantaly.net>
Signed-off-by: Kai Page <kai@quantaly.net>
Signed-off-by: Kai Page <kai@quantaly.net>
Signed-off-by: Kai Page <kai@quantaly.net>
Signed-off-by: Kai Page <kai@quantaly.net>
Signed-off-by: joeyvongphasouk <joey.vongpha@gmail.com>
Signed-off-by: Kai Page <kai@quantaly.net>
Signed-off-by: Kai Page <kai@quantaly.net>
Signed-off-by: Kai Page <kai@quantaly.net>
Signed-off-by: Kai Page <kai@quantaly.net>
PWM output for GPIO
Hey @Quantaly ! Thanks for your contribution! This looks pretty awesome 💙 I will admit that I am not familiar with GPIO capability, but I noted that it will only be able to run on a Raspberry Pi. This is quiet a different capability than the ones we already have, which are mostly centered on the theme of wasi-cloud-core World proposal. On the other hand, this PR does add a optional compilation feature like all other capabilities so it won't affect any downstream projects that use only a subset of SpiderLightning's capabilities. With that being said, I am happy to merge this to the main branch, but this does not indicate that it will be part of the Since this is a pretty big PR, I will do a quick pass of review today and then let's iterate through it. I noticed that the CI is failing, could you please help to fix it? |
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.
Mostly look good to me but admitted I didn't run this locally yet.
I left some comments and once they are ready, I am happy to do a round 2 review!
@@ -0,0 +1,38 @@ | |||
variant gpio-error { |
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.
Could you please add some docs on this new WIT file? What are each resources represent, much like the pwm-output-pin
resource.
let gpio: &mut dyn GpioImplementor = &mut gpio; | ||
for config in [ | ||
"", | ||
"some", |
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.
Love this!
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.
🤣
@@ -330,6 +335,16 @@ async fn build_store_instance( | |||
linked_capabilities.insert("http-client".to_string()); | |||
} | |||
} | |||
#[cfg(feature = "gpio")] |
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.
Could you please add at least one intergration test to this new capability so that it will be automatically tested in our CI/CD pipelines?
name = "slight-gpio" | ||
version = "0.1.0" | ||
edition = { workspace = true } | ||
authors = { workspace = true } |
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
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.
This is looking really solid – Thank you so much for the PR, folks! Awesome work!
I've just added some comments here and there, but nothing major.
Also, to fix our CI, you might want to run:
cargo clippy --fix --all
cargo fmt --all
- 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 comment
The 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 (:
Some(Ok(_)) => Err(gpio::GpioError::PinUsageError(format!( | ||
"'{name}' is not an input pin" | ||
))), | ||
Some(Err(e)) => Err(e.clone()), | ||
None => Err(gpio::GpioError::PinUsageError(format!( | ||
"'{name}' is not a named pin" | ||
))), |
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.
This ties to my comment above about storing errors in the HashMap
. I feel like a better look for this would only handle Some(<my_pin>)
, or None
.
Some(Ok(Pin::Output(pin))) => Ok(pin.clone()), | ||
Some(Ok(_)) => Err(gpio::GpioError::PinUsageError(format!( | ||
"'{name}' is not an output pin" | ||
))), | ||
Some(Err(e)) => Err(e.clone()), | ||
None => Err(gpio::GpioError::PinUsageError(format!( | ||
"'{name}' is not a named pin" | ||
))), |
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.
~same as above.
match self.pins.get(name) { | ||
Some(Ok(Pin::PwmOutput(pin))) => Ok(pin.clone()), | ||
Some(Ok(_)) => Err(gpio::GpioError::PinUsageError(format!( | ||
"'{name}' is not a PWM output pin" | ||
))), | ||
Some(Err(e)) => Err(e.clone()), | ||
None => Err(gpio::GpioError::PinUsageError(format!( | ||
"'{name}' is not a named pin" | ||
))), |
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.
~same as above.
let gpio: &mut dyn GpioImplementor = &mut gpio; | ||
for config in [ | ||
"", | ||
"some", |
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.
🤣
enable: func() -> unit | ||
/// Disable the output signal. | ||
disable: func() -> unit | ||
} |
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.
Usually, we'd first get a proposal for an interface, and then later move on to the implementation to allow for agreement over the interface prior to any work being done – That said, I think this is looking very solid. It'd be cool to be able to add some sort of pin event handling to be able to register callbacks or smt based on specific GPIO pin events, but callback support in WIT is very restricted.
push_down_button = "17/input/pulldown" | ||
led = "5/output" | ||
pwm_control_button = "18/input/pullup" | ||
pwm_led = "6/pwm_output" |
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.
I see that you're defining pin config. (i.e., pull-up/pull-down) directly in the string vars here. Have you considered baking this into some sort of structure within the interface?
let pins = state | ||
.configs_map | ||
.map(|configs| { | ||
configs | ||
.iter() | ||
.map(|(name, config)| (name.clone(), implementor.parse_pin_config(config))) | ||
.collect() | ||
}) | ||
.unwrap_or_else(HashMap::new); |
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.
Currently, all pin usage is registered via the slightfile – Is there any usage to registering pins are runtime?
/// It must be [Send], [Sync], and [Clone]. | ||
#[derive(Clone)] | ||
pub struct Gpio { | ||
pins: HashMap<String, Result<Pin, gpio::GpioError>>, |
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.
Are we sure we want to store possible errors in the HashMap
? As a user, I'd rather fail at compile-time instead of trying to get my pin and failing at runtime.
@Quantaly , @joeyvongphasouk , and @BrendanBurm ~ Is this something you are still interested in merging? |
I think this should be a proposal upstream for wasi! or, resubmit to the spin project? |
I think having a wasi-gpio interface upstream would be awesome. Spin could then implement it! |
This work was completed for our Advanced Software Engineering course at Colorado School of Mines.
We've added a GPIO capability with an implementation for Raspberry Pi based on rppal. The interface supports basic digital input and output as well as PWM output. A video demonstrating this functionality is attached.
demo.webm