Skip to main content

automation_hat/
digital_output.rs

1//! Digital output control for Automation HAT boards.
2//!
3//! This module provides control for the digital output pins on Automation HAT boards.
4//! Digital outputs provide 5V signals for controlling external devices and have indicator
5//! LEDs to show their current state.
6
7use crate::lights::LED;
8
9use embedded_hal::digital::{OutputPin, PinState};
10use linux_embedded_hal::{
11    CdevPin,
12    gpio_cdev::{Line, LineRequestFlags},
13};
14
15/// Controls a digital output on the Automation HAT.
16///
17/// Digital outputs provide 5V signals for controlling external devices.
18/// When an output is set high, it outputs 5V. Each output can have an associated
19/// LED that automatically indicates the output state.
20pub struct DigitalOutput {
21    /// GPIO pin for the digital output
22    pin: CdevPin,
23    /// Optional LED indicator for this output
24    led: Option<LED>,
25    /// Whether the LED should automatically reflect output state
26    _auto_light: bool,
27    /// Current state of the output (true = high/on, false = low/off)
28    pub value: bool,
29}
30
31impl DigitalOutput {
32    /// Creates a new digital output with automatic LED indication enabled.
33    ///
34    /// # Arguments
35    ///
36    /// * `line` - GPIO line connected to the digital output
37    /// * `led` - Optional LED indicator for this output
38    ///
39    /// # Returns
40    ///
41    /// A new `DigitalOutput` instance with automatic LED indication enabled
42    pub fn new(line: Line, led: Option<LED>) -> Self {
43        let line = line
44            .request(LineRequestFlags::OUTPUT, 0, "AutomationHAT Rust SDK")
45            .unwrap();
46        let pin = CdevPin::new(line).unwrap();
47        DigitalOutput {
48            pin,
49            led,
50            _auto_light: true,
51            value: false,
52        }
53    }
54
55    /// Creates a new digital output with configurable LED indication.
56    ///
57    /// # Arguments
58    ///
59    /// * `line` - GPIO line connected to the digital output
60    /// * `led` - Optional LED indicator for this output
61    /// * `auto_light` - Whether the LED should automatically reflect the output state
62    ///
63    /// # Returns
64    ///
65    /// A new `DigitalOutput` instance with the specified LED behavior
66    pub fn new_with_auto_light(line: Line, led: Option<LED>, auto_light: bool) -> Self {
67        let line = line
68            .request(LineRequestFlags::OUTPUT, 0, "AutomationHAT Rust SDK")
69            .unwrap();
70        let pin = CdevPin::new(line).unwrap();
71        DigitalOutput {
72            pin,
73            led,
74            _auto_light: auto_light,
75            value: false,
76        }
77    }
78
79    /// Sets the state of the digital output.
80    ///
81    /// When `on` is true, the output is set high (5V).
82    /// When `on` is false, the output is set low (0V).
83    /// If auto_light is enabled and an LED is attached, this method will
84    /// also update the LED to reflect the current output state.
85    ///
86    /// # Arguments
87    ///
88    /// * `on` - The desired state of the output (true = high/on, false = low/off)
89    ///
90    /// # Returns
91    ///
92    /// * `Ok(())` - If the output was successfully set
93    /// * `Err(String)` - If setting the output or LED failed, with an error message
94    pub fn write(&mut self, on: bool) -> Result<(), String> {
95        if self._auto_light {
96            if let Some(led) = &mut self.led {
97                match led.set(match on {
98                    true => 1.0,
99                    false => 0.0,
100                }) {
101                    Ok(_) => {}
102                    Err(e) => return Err(format!("Unable to set LED state: {}", e)),
103                }
104            }
105        }
106        return match self.pin.set_state(match on {
107            true => PinState::High,
108            false => PinState::Low,
109        }) {
110            Ok(_) => {
111                self.value = on;
112                Ok(())
113            }
114            Err(e) => Err(format!("Unable to set pin state: {}", e)),
115        };
116    }
117}