1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
//! LEGO EV3 ultrasonic sensor

use std::cell::Cell;
use super::SensorPort;
use crate::{Attribute, Device, Driver, Ev3Error, Ev3Result};

/// LEGO EV3 ultrasonic sensor.
#[derive(Debug, Clone, Device)]
pub struct UltrasonicSensor {
    driver: Driver,
    cm_scale: Cell<Option<f32>>,
    in_scale: Cell<Option<f32>>,
}

impl UltrasonicSensor {

    fn new(driver: Driver) -> Self {
        Self {
            driver,
            cm_scale: Cell::new(None),
            in_scale: Cell::new(None),
        }
    }

    findable!(
        "lego-sensor",
        "lego-ev3-us",
        SensorPort,
        "UltrasonicSensor",
        "in"
    );

    /// Continuous measurement - sets LEDs on, steady.
    /// Units in centimeters. Distance (0-2550)
    pub const MODE_US_DIST_CM: &'static str = "US-DIST-CM";

    /// Continuous measurement - sets LEDs on, steady.
    /// Units in inches. Distance (0-1003)
    pub const MODE_US_DIST_IN: &'static str = "US-DIST-IN";

    /// Listen - sets LEDs on, blinking. Presence (0-1)
    pub const MODE_US_LISTEN: &'static str = "US-LISTEN";

    /// Single measurement - LEDs on momentarily when mode is set, then off.
    /// Units in centimeters. Distance (0-2550)
    pub const MODE_US_SI_CM: &'static str = "US-SI-CM";

    /// Single measurement - LEDs on momentarily when mode is set, then off.
    /// Units in inches. Distance (0-1003)
    pub const MODE_US_SI_IN: &'static str = "US-SI-IN";

    /// ??? - sets LEDs on, steady.
    /// Units in centimeters. Distance (0-2550)
    pub const MODE_US_DC_CM: &'static str = "US-DC-CM";

    /// ??? - sets LEDs on, steady.
    /// Units in inches. Distance (0-1003)
    pub const MODE_US_DC_IN: &'static str = "US-DC-IN";

    sensor!();

    /// Continuous measurement - sets LEDs on, steady. Units in centimeters. Distance (0-2550)
    pub fn set_mode_us_dist_cm(&self) -> Ev3Result<()> {
        self.set_mode(Self::MODE_US_DIST_CM)
    }

    /// Continuous measurement - sets LEDs on, steady. Units in inches. Distance (0-1003)
    pub fn set_mode_us_dist_in(&self) -> Ev3Result<()> {
        self.set_mode(Self::MODE_US_DIST_IN)
    }

    /// Listen - sets LEDs on, blinking. Presence (0-1)
    pub fn set_mode_us_listen(&self) -> Ev3Result<()> {
        self.set_mode(Self::MODE_US_LISTEN)
    }

    /// Single measurement - LEDs on momentarily when mode is set, then off. Units in centimeters. Distance (0-2550)
    pub fn set_mode_us_si_cm(&self) -> Ev3Result<()> {
        self.set_mode(Self::MODE_US_SI_CM)
    }

    /// Single measurement - LEDs on momentarily when mode is set, then off. Units in inches. Distance (0-1003)
    pub fn set_mode_us_si_in(&self) -> Ev3Result<()> {
        self.set_mode(Self::MODE_US_SI_IN)
    }

    /// ??? - sets LEDs on, steady . Units in centimeters. Distance (0-2550)
    pub fn set_mode_us_dc_cm(&self) -> Ev3Result<()> {
        self.set_mode(Self::MODE_US_DC_CM)
    }

    /// ??? - sets LEDs on, steady . Units in inches. Distance (0-1003)
    pub fn set_mode_us_dc_in(&self) -> Ev3Result<()> {
        self.set_mode(Self::MODE_US_DC_IN)
    }

    /// Measurement of the distance detected by the sensor, unscaled.
    pub fn get_distance(&self) -> Ev3Result<i32> {
        self.get_value0()
    }

    /// Measurement of the distance detected by the sensor, in centimeters.
    pub fn get_distance_centimeters(&self) -> Ev3Result<f32> {
        let scale_field = self.cm_scale.get();
        let scale = match scale_field {
            Some(s) => s,
            None => {
                let decimals = self.get_decimals()?;
                let s = 10f32.powi(-decimals);
                self.cm_scale.set(Some(s));
                s
            }
        };

        Ok((self.get_value0()? as f32) * scale)
    }

    /// Measurement of the distance detected by the sensor, in centimeters.
    pub fn get_distance_inches(&self) -> Ev3Result<f32> {
        let scale_field = self.in_scale.get();
        let scale = match scale_field {
            Some(s) => s,
            None => {
                let decimals = self.get_decimals()?;
                let s = 10f32.powi(-decimals);
                self.in_scale.set(Some(s));
                s
            }
        };

        Ok((self.get_value0()? as f32) * scale)
    }
}