-
Notifications
You must be signed in to change notification settings - Fork 9
Humidity API #22
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
base: master
Are you sure you want to change the base?
Humidity API #22
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| [package] | ||
| name = "libtock_humidity" | ||
| version = "0.1.0" | ||
| edition = "2021" | ||
|
|
||
| # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html | ||
|
|
||
| [dependencies] | ||
| libtock_platform = { path = "../../platform" } | ||
|
|
||
| [dev-dependencies] | ||
| libtock_unittest = { path = "../../unittest" } | ||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,81 @@ | ||||||
| #![no_std] | ||||||
|
|
||||||
| use core::cell::Cell; | ||||||
| use libtock_platform::{ | ||||||
| share, subscribe::OneId, DefaultConfig, ErrorCode, Subscribe, Syscalls, Upcall, | ||||||
| }; | ||||||
|
|
||||||
| pub struct Humidity<S: Syscalls>(S); | ||||||
|
|
||||||
| impl<S: Syscalls> Humidity<S> { | ||||||
| /// Returns Ok() if the driver was present.This does not necessarily mean | ||||||
| /// that the driver is working. | ||||||
| pub fn exists() -> Result<(), ErrorCode> { | ||||||
| S::command(DRIVER_NUM, EXISTS, 0, 0).to_result() | ||||||
| } | ||||||
|
|
||||||
| /// Initiate a humidity measurement. | ||||||
| /// | ||||||
| /// This function is used both for synchronous and asynchronous readings | ||||||
| pub fn read_humidity() -> Result<(), ErrorCode> { | ||||||
|
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.
Suggested change
|
||||||
| S::command(DRIVER_NUM, READ_HUM, 0, 0).to_result() | ||||||
| } | ||||||
|
|
||||||
| /// Register an events listener | ||||||
| pub fn register_listener<'share, F: Fn(i32)>( | ||||||
|
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. I think this should be |
||||||
| listener: &'share HumidityListener<F>, | ||||||
| subscribe: share::Handle<Subscribe<'share, S, DRIVER_NUM, 0>>, | ||||||
| ) -> Result<(), ErrorCode> { | ||||||
| S::subscribe::<_, _, DefaultConfig, DRIVER_NUM, 0>(subscribe, listener) | ||||||
| } | ||||||
|
|
||||||
| /// Unregister the events listener | ||||||
| pub fn unregister_listener() { | ||||||
| S::unsubscribe(DRIVER_NUM, 0) | ||||||
| } | ||||||
|
|
||||||
| /// Initiate a synchronous humidity measurement. | ||||||
| /// Returns Ok(humidity_value) if the operation was successful | ||||||
| /// humidity_value is returned in hundreds of centigrades | ||||||
| pub fn read_humidity_sync() -> Result<i32, ErrorCode> { | ||||||
| let humidity_cell: Cell<Option<i32>> = Cell::new(None); | ||||||
| let listener = HumidityListener(|hum_val| { | ||||||
| humidity_cell.set(Some(hum_val)); | ||||||
| }); | ||||||
| share::scope(|subscribe| { | ||||||
| if let Ok(()) = Self::register_listener(&listener, subscribe) { | ||||||
| if let Ok(()) = Self::read_humidity() { | ||||||
| while humidity_cell.get() == None { | ||||||
| S::yield_wait(); | ||||||
| } | ||||||
| } | ||||||
| } | ||||||
| }); | ||||||
|
|
||||||
| match humidity_cell.get() { | ||||||
| None => Err(ErrorCode::Busy), | ||||||
| Some(hum_val) => Ok(hum_val), | ||||||
| } | ||||||
| } | ||||||
| } | ||||||
|
|
||||||
| pub struct HumidityListener<F: Fn(i32)>(pub F); | ||||||
| impl<F: Fn(i32)> Upcall<OneId<DRIVER_NUM, 0>> for HumidityListener<F> { | ||||||
| fn upcall(&self, hum_val: u32, _arg1: u32, _arg2: u32) { | ||||||
| self.0(hum_val as i32) | ||||||
| } | ||||||
| } | ||||||
|
|
||||||
| #[cfg(test)] | ||||||
| mod tests; | ||||||
|
|
||||||
| // ----------------------------------------------------------------------------- | ||||||
| // Driver number and command IDs | ||||||
| // ----------------------------------------------------------------------------- | ||||||
|
|
||||||
| const DRIVER_NUM: u32 = 0x60001; | ||||||
|
|
||||||
| // Command IDs | ||||||
|
|
||||||
| const EXISTS: u32 = 0; | ||||||
| const READ_HUM: u32 = 1; | ||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,81 @@ | ||
| use core::cell::Cell; | ||
| use libtock_platform::{share, ErrorCode, Syscalls, YieldNoWaitReturn}; | ||
| use libtock_unittest::fake; | ||
|
|
||
| type Humidity = super::Humidity<fake::Syscalls>; | ||
|
|
||
| #[test] | ||
| fn no_driver() { | ||
| let _kernel = fake::Kernel::new(); | ||
| assert_eq!(Humidity::exists(), Err(ErrorCode::NoDevice)); | ||
| } | ||
|
|
||
| #[test] | ||
| fn driver_check() { | ||
| let kernel = fake::Kernel::new(); | ||
| let driver = fake::Humidity::new(); | ||
| kernel.add_driver(&driver); | ||
|
|
||
| assert_eq!(Humidity::exists(), Ok(())); | ||
| } | ||
|
|
||
| #[test] | ||
| fn read_humidity() { | ||
| let kernel = fake::Kernel::new(); | ||
| let driver = fake::Humidity::new(); | ||
| kernel.add_driver(&driver); | ||
|
|
||
| assert_eq!(Humidity::read_humidity(), Ok(())); | ||
| assert!(driver.is_busy()); | ||
|
|
||
| assert_eq!(Humidity::read_humidity(), Err(ErrorCode::Busy)); | ||
| assert_eq!(Humidity::read_humidity_sync(), Err(ErrorCode::Busy)); | ||
| } | ||
|
|
||
| #[test] | ||
| fn register_unregister_listener() { | ||
| let kernel = fake::Kernel::new(); | ||
| let driver = fake::Humidity::new(); | ||
| kernel.add_driver(&driver); | ||
|
|
||
| let humidity_cell: Cell<Option<i32>> = Cell::new(None); | ||
| let listener = crate::HumidityListener(|hum_val| { | ||
| humidity_cell.set(Some(hum_val)); | ||
| }); | ||
| share::scope(|subscribe| { | ||
| assert_eq!(Humidity::read_humidity(), Ok(())); | ||
| driver.set_value(100); | ||
| assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::NoUpcall); | ||
|
|
||
| assert_eq!(Humidity::register_listener(&listener, subscribe), Ok(())); | ||
| assert_eq!(Humidity::read_humidity(), Ok(())); | ||
| driver.set_value(100); | ||
| assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::Upcall); | ||
| assert_eq!(humidity_cell.get(), Some(100)); | ||
|
|
||
| Humidity::unregister_listener(); | ||
| assert_eq!(Humidity::read_humidity(), Ok(())); | ||
| driver.set_value(100); | ||
| assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::NoUpcall); | ||
| }); | ||
| } | ||
|
|
||
| #[test] | ||
| fn read_humidity_sync() { | ||
| let kernel = fake::Kernel::new(); | ||
| let driver = fake::Humidity::new(); | ||
| kernel.add_driver(&driver); | ||
|
|
||
| driver.set_value_sync(1000); | ||
| assert_eq!(Humidity::read_humidity_sync(), Ok(1000)); | ||
| } | ||
|
|
||
| #[test] | ||
| fn negative_value() { | ||
| let kernel = fake::Kernel::new(); | ||
| let driver = fake::Humidity::new(); | ||
| kernel.add_driver(&driver); | ||
|
|
||
| driver.set_value_sync(-1000); | ||
| assert_eq!(Humidity::read_humidity_sync(), Ok(-1000)); | ||
| } |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,41 @@ | ||||||||||||||||||||||||
| //! A simple libtock-rs example. Checks for humidity driver | ||||||||||||||||||||||||
| //! and samples the sensor every 2 seconds. | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| #![no_main] | ||||||||||||||||||||||||
| #![no_std] | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| use core::fmt::Write; | ||||||||||||||||||||||||
| use libtock::console::Console; | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| use libtock::alarm::{Alarm, Milliseconds}; | ||||||||||||||||||||||||
| use libtock::humidity::Humidity; | ||||||||||||||||||||||||
| use libtock::runtime::{set_main, stack_size}; | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| set_main! {main} | ||||||||||||||||||||||||
| stack_size! {0x200} | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| fn main() { | ||||||||||||||||||||||||
| match Humidity::exists() { | ||||||||||||||||||||||||
| Ok(()) => writeln!(Console::writer(), "humidity driver available").unwrap(), | ||||||||||||||||||||||||
| Err(_) => { | ||||||||||||||||||||||||
| writeln!(Console::writer(), "humidity driver unavailable").unwrap(); | ||||||||||||||||||||||||
| return; | ||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
|
Comment on lines
+18
to
+24
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.
Suggested change
|
||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| loop { | ||||||||||||||||||||||||
| match Humidity::read_humidity_sync() { | ||||||||||||||||||||||||
| Ok(hum_val) => writeln!( | ||||||||||||||||||||||||
| Console::writer(), | ||||||||||||||||||||||||
| "Humidity: {}{}.{}*C\n", | ||||||||||||||||||||||||
| if hum_val > 0 { "" } else { "-" }, | ||||||||||||||||||||||||
| i32::abs(hum_val) / 100, | ||||||||||||||||||||||||
| i32::abs(hum_val) % 100 | ||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||
| .unwrap(), | ||||||||||||||||||||||||
| Err(_) => writeln!(Console::writer(), "error while reading humidity",).unwrap(), | ||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| Alarm::sleep_for(Milliseconds(2000)).unwrap(); | ||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
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.
Add newline