use rppal::gpio::{Gpio, IoPin, Level, Mode};
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Arc;
use std::sync::Mutex;
use std::thread;
use std::thread::JoinHandle;
use std::time::Duration;
#[derive(Debug)]
pub struct OutputDevice {
pin: IoPin,
active_state: bool,
inactive_state: bool,
}
#[macro_export]
macro_rules! impl_io_device {
() => {
fn value_to_state(&self, value: bool) -> bool {
if value {
self.active_state
} else {
self.inactive_state
}
}
fn state_to_value(&self, state: bool) -> bool {
state == self.active_state
}
pub fn value(&self) -> bool {
match self.pin.read() {
Level::Low => self.state_to_value(false),
Level::High => self.state_to_value(true),
}
}
}
}
macro_rules! impl_output_device {
() => {
pub fn set_active_high(&mut self, value: bool) {
if value {
self.active_state=true;
self.inactive_state=false;
} else {
self.active_state=false;
self.inactive_state=true;
}
}
pub fn active_high(&self) -> bool {
self.active_state
}
pub fn on(&mut self) {
self.write_state(true)
}
pub fn off(&mut self) {
self.write_state(false)
}
pub fn toggle(&mut self) {
if self.is_active(){
self.off()
}else{
self.on()
}
}
fn write_state(&mut self, value: bool) {
if self.value_to_state(value) {
self.pin.set_high()
} else {
self.pin.set_low()
}
}
}
}
impl OutputDevice {
pub fn new(pin: u8) -> OutputDevice {
match Gpio::new() {
Err(e) => panic!("{:?}", e),
Ok(gpio) => match gpio.get(pin) {
Err(e) => panic!("{:?}", e),
Ok(pin) => OutputDevice {
pin: pin.into_io(Mode::Output),
active_state: true,
inactive_state: false,
},
},
}
}
impl_device!();
impl_gpio_device!();
impl_io_device!();
impl_output_device!();
}
#[derive(Debug)]
pub struct DigitalOutputDevice {
device: Arc<Mutex<OutputDevice>>,
blinking: Arc<AtomicBool>,
handle: Option<JoinHandle<()>>,
blink_count: Option<i32>,
}
macro_rules! impl_digital_output_device {
() => {
fn blinker(&mut self,
on_time: f32,
off_time: f32,
n: Option<i32>){
self.stop();
let device = Arc::clone(&self.device);
let blinking = Arc::clone(&self.blinking);
self.handle = Some(thread::spawn(move || {
blinking.store(true, Ordering::SeqCst);
match n {
Some(end) => {
for _ in 0..end {
if !blinking.load(Ordering::SeqCst) {
device.lock().unwrap().off();
break;
}
device.lock().unwrap().on();
thread::sleep(Duration::from_millis((on_time * 1000.0) as u64));
device.lock().unwrap().off();
thread::sleep(Duration::from_millis((off_time * 1000.0) as u64));
}
}
None => loop {
if !blinking.load(Ordering::SeqCst) {
device.lock().unwrap().off();
break;
}
device.lock().unwrap().on();
thread::sleep(Duration::from_millis((on_time * 1000.0) as u64));
device.lock().unwrap().off();
thread::sleep(Duration::from_millis((off_time * 1000.0) as u64));
},
}
}));
}
pub fn is_active(&self) -> bool{
Arc::clone(&self.device).lock().unwrap().is_active()
}
pub fn on(&self){
self.stop();
self.device.lock().unwrap().on()
}
pub fn off(&self){
self.stop();
self.device.lock().unwrap().off()
}
pub fn toggle(&mut self) {
self.device.lock().unwrap().toggle()
}
pub fn value(&self) -> bool {
self.device.lock().unwrap().value()
}
fn stop(&self) {
self.blinking.clone().store(false, Ordering::SeqCst);
self.device.lock().unwrap().pin.set_low();
}
pub fn active_high(&self) -> bool {
self.device.lock().unwrap().active_high()
}
pub fn set_active_high(&mut self, value: bool) {
self.device.lock().unwrap().set_active_high(value)
}
pub fn pin(&self) -> u8 {
self.device.lock().unwrap().pin.pin()
}
pub fn close(self) {
drop(self)
}
pub fn wait(&mut self){
self.handle
.take().expect("Called stop on non-running thread")
.join().expect("Could not join spawned thread");
}
}
}
impl DigitalOutputDevice {
pub fn new(pin: u8) -> DigitalOutputDevice {
DigitalOutputDevice {
device: Arc::new(Mutex::new(OutputDevice::new(pin))),
blinking: Arc::new(AtomicBool::new(false)),
handle: None,
blink_count: None,
}
}
impl_digital_output_device!();
pub fn blink(&mut self, on_time: f32, off_time: f32) {
match self.blink_count {
None => self.blinker(on_time, off_time, None),
Some(n) => self.blinker(on_time, off_time, Some(n)),
}
}
pub fn set_blink_count(&mut self, n: i32) {
self.blink_count = Some(n)
}
}
#[derive(Debug)]
pub struct LED {
device: Arc<Mutex<OutputDevice>>,
blinking: Arc<AtomicBool>,
handle: Option<JoinHandle<()>>,
blink_count: Option<i32>,
}
impl LED {
pub fn new(pin: u8) -> LED {
LED {
device: Arc::new(Mutex::new(OutputDevice::new(pin))),
blinking: Arc::new(AtomicBool::new(false)),
handle: None,
blink_count: None,
}
}
impl_digital_output_device!();
pub fn is_lit(&self) -> bool {
self.is_active()
}
pub fn blink(&mut self, on_time: f32, off_time: f32) {
match self.blink_count {
None => self.blinker(on_time, off_time, None),
Some(n) => self.blinker(on_time, off_time, Some(n)),
}
}
pub fn set_blink_count(&mut self, n: i32) {
self.blink_count = Some(n)
}
}
#[derive(Debug)]
pub struct Buzzer {
device: Arc<Mutex<OutputDevice>>,
blinking: Arc<AtomicBool>,
handle: Option<JoinHandle<()>>,
blink_count: Option<i32>,
}
impl Buzzer {
pub fn new(pin: u8) -> Buzzer {
Buzzer {
device: Arc::new(Mutex::new(OutputDevice::new(pin))),
blinking: Arc::new(AtomicBool::new(false)),
handle: None,
blink_count: None,
}
}
impl_digital_output_device!();
pub fn beep(&mut self, on_time: f32, off_time: f32) {
match self.blink_count {
None => self.blinker(on_time, off_time, None),
Some(n) => self.blinker(on_time, off_time, Some(n)),
}
}
pub fn set_beep_count(&mut self, n: i32) {
self.blink_count = Some(n)
}
}
pub struct PWMOutputDevice {
device: Arc<Mutex<OutputDevice>>,
blinking: Arc<AtomicBool>,
handle: Option<JoinHandle<()>>,
blink_count: Option<i32>,
active_state: bool,
inactive_state: bool,
}
macro_rules! impl_pwm_device {
() => {
pub fn set_value(&mut self, duty:f64){
self.write_state(duty)
}
pub fn set_blink_count(&mut self, n: i32) {
self.blink_count = Some(n)
}
fn blinker(&mut self,
on_time: f32,
off_time: f32,
fade_in_time: f32,
fade_out_time: f32,
n: Option<i32>
){
let mut sequence: Vec<(f32, f32)> = Vec::new();
let fps = 25.0;
if fade_in_time > 0.0{
for i in 0..fps as i32 * fade_in_time as i32 {
sequence.push((i as f32 * (1.0 / fps) / fade_in_time, 1.0 / fps))
}
}
sequence.push((1.0, on_time));
if fade_out_time > 0.0 {
for i in 0..fps as i32 * fade_out_time as i32 {
sequence.push((1.0 - (i as f32 * (1.0 / fps) / fade_out_time), 1.0 / fps))
}
}
sequence.push((0.0, off_time));
let device = Arc::clone(&self.device);
let blinking = Arc::clone(&self.blinking);
self.handle = Some(thread::spawn(move || {
blinking.store(true, Ordering::SeqCst);
match n {
Some(end) => {
for _ in 0..end {
for (value, delay) in &sequence {
if !blinking.load(Ordering::SeqCst) {
break;
}
device.lock().unwrap().pin.set_pwm_frequency(100.0, f64::from(*value)).unwrap();
thread::sleep(Duration::from_millis((delay * 1000 as f32) as u64));
}
}
}
None => loop {
for (value, delay) in &sequence {
if !blinking.load(Ordering::SeqCst) {
break;
}
device.lock().unwrap().pin.set_pwm_frequency(100.0, f64::from(*value)).unwrap();
thread::sleep(Duration::from_millis((delay * 1000 as f32) as u64));
}
},
}
}));
}
fn stop(&mut self) {
self.blinking.clone().store(false, Ordering::SeqCst);
if self.device.lock().unwrap().pin.clear_pwm().is_err(){
println!("Could not clear pwm for pin");
};
}
fn write_state(&mut self, value:f64){
if !(value >= 0.0 && value<=1.0) {
println!("Value must be between 0.0 and 1.0");
return;
}
self.stop();
if self.active_high() {
self.device.lock().unwrap().pin.set_pwm_frequency(100.0, value).unwrap()
}else{
self.device.lock().unwrap().pin.set_pwm_frequency(100.0, 1.0 - value).unwrap()
}
}
pub fn set_active_high(&mut self, value: bool) {
if value {
self.active_state=true;
self.inactive_state=false;
} else {
self.active_state=false;
self.inactive_state=true;
}
}
pub fn active_high(&self) -> bool {
self.active_state
}
pub fn on(&mut self) {
self.write_state(1.0)
}
pub fn off(&mut self) {
self.write_state(0.0)
}
}
}
impl PWMOutputDevice {
pub fn new(pin: u8) -> PWMOutputDevice {
PWMOutputDevice {
device: Arc::new(Mutex::new(OutputDevice::new(pin))),
blinking: Arc::new(AtomicBool::new(false)),
handle: None,
blink_count: None,
active_state: true,
inactive_state: false,
}
}
impl_pwm_device!();
pub fn blink(&mut self, on_time: f32, off_time: f32, fade_in_time: f32, fade_out_time: f32) {
match self.blink_count {
None => self.blinker(on_time, off_time, fade_in_time, fade_out_time, None),
Some(n) => self.blinker(on_time, off_time, fade_in_time, fade_out_time, Some(n)),
}
}
pub fn pulse(&mut self, fade_in_time: f32, fade_out_time: f32) {
self.blink(0.0, 0.0, fade_in_time, fade_out_time)
}
}
pub struct PWMLED(PWMOutputDevice);
impl PWMLED {
pub fn new(pin: u8) -> PWMLED {
PWMLED(PWMOutputDevice::new(pin))
}
pub fn blink(&mut self, on_time: f32, off_time: f32, fade_in_time: f32, fade_out_time: f32) {
self.0.blink(on_time, off_time, fade_in_time, fade_out_time)
}
pub fn on(&mut self) {
self.0.on();
}
pub fn off(&mut self) {
self.0.off();
}
pub fn pulse(&mut self, fade_in_time: f32, fade_out_time: f32) {
self.0.pulse(fade_in_time, fade_out_time);
}
pub fn set_value(&mut self, value: f64) {
self.0.set_value(value);
}
pub fn set_blink_count(&mut self, n: i32) {
self.0.blink_count = Some(n)
}
}
struct MotorCompositeDevice(PWMOutputDevice, PWMOutputDevice);
pub struct Motor {
devices: MotorCompositeDevice,
speed: f64,
}
impl Motor {
pub fn new(forward_pin: u8, backward_pin: u8) -> Motor {
let forward = PWMOutputDevice::new(forward_pin);
let backward = PWMOutputDevice::new(backward_pin);
Motor {
devices: MotorCompositeDevice(forward, backward),
speed: 1.0,
}
}
pub fn forward(&mut self) {
self.devices.1.off();
self.devices.0.set_value(self.speed);
}
pub fn backward(&mut self) {
self.devices.0.off();
self.devices.1.set_value(self.speed);
}
pub fn stop(&mut self) {
self.devices.0.off();
self.devices.1.off();
}
pub fn set_speed(&mut self, speed: f64) {
if !(speed >= 0.0 && speed <= 1.0) {
println!("Speed must be between 0.0 and 1.0");
return;
}
self.speed = speed
}
}
pub struct Servo {
pin: IoPin,
min_pulse_width: u64,
max_pulse_width: u64,
frame_width: u64,
}
impl Servo {
pub fn new(pin: u8) -> Servo {
match Gpio::new() {
Err(e) => panic!("{:?}", e),
Ok(gpio) => match gpio.get(pin) {
Err(e) => panic!("{:?}", e),
Ok(pin) => Servo {
pin: pin.into_io(Mode::Output),
min_pulse_width: 1000,
max_pulse_width: 2000,
frame_width: 20,
},
},
}
}
pub fn min(&mut self) {
if self
.pin
.set_pwm(
Duration::from_millis(self.frame_width),
Duration::from_micros(self.min_pulse_width),
)
.is_err()
{
println!("Failed to set servo to minimum position")
}
}
pub fn max(&mut self) {
if self
.pin
.set_pwm(
Duration::from_millis(self.frame_width),
Duration::from_micros(self.max_pulse_width),
)
.is_err()
{
println!("Failed to set servo to maximum position")
}
}
pub fn mid(&mut self) {
let mid_value = (self.min_pulse_width + self.max_pulse_width) / 2;
if self
.pin
.set_pwm(
Duration::from_millis(self.frame_width),
Duration::from_micros(mid_value),
)
.is_err()
{
println!("Failed to set servo to neutral position")
}
}
pub fn set_min_pulse_width(&mut self, value: u64) {
if value >= self.max_pulse_width {
println!("min_pulse_width must be less than max_pulse_width");
return;
} else {
self.min_pulse_width = value
}
}
pub fn set_max_pulse_width(&mut self, value: u64) {
if value >= self.frame_width {
println!("max_pulse_width must be less than frame_width");
return;
} else {
self.max_pulse_width = value
}
}
pub fn set_frame_width(&mut self, value: u64) {
self.frame_width = value;
}
pub fn get_min_pulse_width(&mut self) -> u64 {
self.min_pulse_width
}
pub fn get_max_pulse_width(&mut self) -> u64 {
self.max_pulse_width
}
pub fn get_frame_width(&mut self) -> u64 {
self.frame_width
}
}