From d783f3584a2f503499d4424264aeab2e9c05d07a Mon Sep 17 00:00:00 2001 From: CosminPerRam Date: Mon, 7 Oct 2024 18:50:26 +0300 Subject: [PATCH] feat: add shared state button example --- examples/README.md | 2 ++ examples/gpio_shared_button_state.rs | 52 ++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+) create mode 100644 examples/gpio_shared_button_state.rs diff --git a/examples/README.md b/examples/README.md index f6c449d8..6adf62f8 100644 --- a/examples/README.md +++ b/examples/README.md @@ -14,6 +14,8 @@ Before running any examples that interface with external components, read throug `gpio_status.rs` - Retrieves the mode and logic level for each of the pins on the 26-pin or 40-pin GPIO header, and displays the results in an ASCII table. +`gpio_shared_button_state.rs` - Shares a state with an input interrupt, stops the program until N event changes. + `i2c_ds3231.rs` - Sets and retrieves the time on a Maxim Integrated DS3231 RTC using I2C. `pwm_blinkled.rs` - Blinks an LED using hardware PWM. diff --git a/examples/gpio_shared_button_state.rs b/examples/gpio_shared_button_state.rs new file mode 100644 index 00000000..a86bbb88 --- /dev/null +++ b/examples/gpio_shared_button_state.rs @@ -0,0 +1,52 @@ +// gpio_shared_button_state.rs - Stops the program until a certain amount of event input changes via +// a non-global shared variable (that can be done using OnceCell for example), this requires a Mutex +// as it goes across threads and Arc to make sure we have the same entry everywhere. + +use std::error::Error; +use std::sync::{Arc, Mutex}; +use std::time::Duration; +use rppal::gpio::{Gpio, Event, Trigger}; + +const INPUT_PIN_GPIO: u8 = 27; +const STOP_AFTER_N_CHANGES: u8 = 5; + +// The function we will run upon a Trigger +fn input_callback(event: Event, my_data: Arc>) { + println!("Event: {:?}", event); + *my_data.lock().unwrap() += 1; +} + +fn main() -> Result<(), Box> { + // Initialize our data, in this case it's just a number. + let shared_state = Arc::new(Mutex::new(0)); + + // Configure the input pin. + let mut input_pin = Gpio::new()?.get(INPUT_PIN_GPIO)?.into_input_pullup(); + + // We need to clone this as set_async_interrupt will move it and cant be used afterward if so + let shared_state_hold = shared_state.clone(); + input_pin.set_async_interrupt( + Trigger::FallingEdge, + Some(Duration::from_millis(50)), + move |event| { + // Note: you can also add more parameters here! + input_callback(event, shared_state_hold.clone()); + }, + )?; + + // We check constantly if we have reached our number of changes. + loop { + if *shared_state.lock().unwrap() >= STOP_AFTER_N_CHANGES { + // Reached it, exiting the program. + println!("Reached {STOP_AFTER_N_CHANGES} events, exiting..."); + break; + } + + // Suppose we do some work here that takes a second, the shorter the work takes, the quicker + // we will quit upon reaching our condition. + println!("Still waiting..."); + std::thread::sleep(Duration::from_secs(1)); + } + + Ok(()) +}