Skip to main content

esp_idf_hal/
temp_sensor.rs

1use esp_idf_sys::{
2    esp, soc_periph_temperature_sensor_clk_src_t_TEMPERATURE_SENSOR_CLK_SRC_DEFAULT,
3    temperature_sensor_clk_src_t, temperature_sensor_config_t, temperature_sensor_disable,
4    temperature_sensor_enable, temperature_sensor_get_celsius, temperature_sensor_handle_t,
5    temperature_sensor_install, temperature_sensor_uninstall, EspError,
6};
7
8#[cfg(esp32p4)]
9use esp_idf_sys::soc_periph_temperature_sensor_clk_src_t_TEMPERATURE_SENSOR_CLK_SRC_LP_PERI;
10#[cfg(any(
11    esp32c2, esp32c3, esp32c5, esp32c6, esp32c61, esp32h2, esp32s2, esp32s3
12))]
13use esp_idf_sys::soc_periph_temperature_sensor_clk_src_t_TEMPERATURE_SENSOR_CLK_SRC_RC_FAST;
14#[cfg(any(esp32c2, esp32c3, esp32c5, esp32c6, esp32c61, esp32h2))]
15use esp_idf_sys::soc_periph_temperature_sensor_clk_src_t_TEMPERATURE_SENSOR_CLK_SRC_XTAL;
16
17use core::marker::PhantomData;
18
19// -- TempSensorClockSource --
20
21#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
22/// Rust translation of `temperature_sensor_clk_src_t`
23pub enum TempSensorClockSource {
24    Default,
25    #[cfg(any(
26        esp32c2, esp32c3, esp32c5, esp32c6, esp32c61, esp32h2, esp32s2, esp32s3
27    ))]
28    RcFast,
29    #[cfg(any(esp32c2, esp32c3, esp32c5, esp32c6, esp32c61, esp32h2))]
30    XTAL,
31    #[cfg(esp32p4)]
32    LpPeri,
33}
34
35impl From<TempSensorClockSource> for temperature_sensor_clk_src_t {
36    fn from(value: TempSensorClockSource) -> Self {
37        match value {
38            #[cfg(any(
39                esp32c2, esp32c3, esp32c5, esp32c6, esp32c61, esp32h2, esp32s2, esp32s3
40            ))]
41            TempSensorClockSource::RcFast => {
42                soc_periph_temperature_sensor_clk_src_t_TEMPERATURE_SENSOR_CLK_SRC_RC_FAST
43            }
44            #[cfg(any(esp32c2, esp32c3, esp32c5, esp32c6, esp32c61, esp32h2))]
45            TempSensorClockSource::XTAL => {
46                soc_periph_temperature_sensor_clk_src_t_TEMPERATURE_SENSOR_CLK_SRC_XTAL
47            }
48            #[cfg(esp32p4)]
49            TempSensorClockSource::LpPeri => {
50                soc_periph_temperature_sensor_clk_src_t_TEMPERATURE_SENSOR_CLK_SRC_LP_PERI
51            }
52            TempSensorClockSource::Default => {
53                soc_periph_temperature_sensor_clk_src_t_TEMPERATURE_SENSOR_CLK_SRC_DEFAULT
54            }
55        }
56    }
57}
58
59impl From<temperature_sensor_clk_src_t> for TempSensorClockSource {
60    fn from(value: temperature_sensor_clk_src_t) -> Self {
61        match value {
62            #[cfg(any(
63                esp32c2, esp32c3, esp32c5, esp32c6, esp32c61, esp32h2, esp32s2, esp32s3
64            ))]
65            #[allow(non_upper_case_globals)]
66            soc_periph_temperature_sensor_clk_src_t_TEMPERATURE_SENSOR_CLK_SRC_RC_FAST => {
67                Self::RcFast
68            }
69            #[cfg(any(esp32c2, esp32c3, esp32c5, esp32c6, esp32c61, esp32h2))]
70            #[allow(non_upper_case_globals)]
71            soc_periph_temperature_sensor_clk_src_t_TEMPERATURE_SENSOR_CLK_SRC_XTAL => Self::XTAL,
72            #[cfg(esp32p4)]
73            #[allow(non_upper_case_globals)]
74            soc_periph_temperature_sensor_clk_src_t_TEMPERATURE_SENSOR_CLK_SRC_LP_PERI => {
75                Self::LpPeri
76            }
77            // TODO: Perhaps the default value should be mapped explicitly
78            // and all other (u32) values should cause a failure
79            _ => Self::Default,
80        }
81    }
82}
83
84// -- TempSensorConfig --
85pub type TempSensorConfig = config::Config;
86pub mod config {
87    use super::*;
88    #[derive(Debug, Clone, PartialEq, Eq, Hash)]
89    #[non_exhaustive]
90    /// Rust wrapper for `temperature_sensor_config_t`
91    pub struct Config {
92        // TODO: check int size
93        pub range_min: i32,
94        pub range_max: i32,
95        pub clk_src: TempSensorClockSource,
96    }
97
98    impl From<temperature_sensor_config_t> for Config {
99        fn from(value: temperature_sensor_config_t) -> Self {
100            Config {
101                range_min: value.range_min,
102                range_max: value.range_max,
103                clk_src: value.clk_src.into(),
104            }
105        }
106    }
107
108    #[allow(clippy::needless_update)]
109    impl From<&Config> for temperature_sensor_config_t {
110        fn from(value: &Config) -> Self {
111            temperature_sensor_config_t {
112                clk_src: value.clk_src.into(),
113                range_max: value.range_max,
114                range_min: value.range_min,
115                ..Default::default()
116            }
117        }
118    }
119
120    impl Default for Config {
121        fn default() -> Self {
122            Config::new()
123        }
124    }
125
126    impl Config {
127        pub const fn new() -> Self {
128            Self {
129                range_min: -10,
130                range_max: 80,
131                clk_src: TempSensorClockSource::Default,
132            }
133        }
134    }
135}
136
137// -- TempSensorDriver --
138
139pub struct TempSensorDriver<'d> {
140    ptr: temperature_sensor_handle_t,
141    _p: PhantomData<&'d mut ()>,
142}
143
144impl<'d> TempSensorDriver<'d> {
145    pub fn new(config: &TempSensorConfig, _sensor: TempSensor<'d>) -> Result<Self, EspError> {
146        let mut sensor = core::ptr::null_mut();
147        esp!(unsafe { temperature_sensor_install(&config.into(), &mut sensor) })?;
148        Ok(TempSensorDriver {
149            ptr: sensor,
150            _p: PhantomData,
151        })
152    }
153
154    pub fn enable(&mut self) -> Result<(), EspError> {
155        esp!(unsafe { temperature_sensor_enable(self.ptr) })
156    }
157
158    pub fn disable(&mut self) -> Result<(), EspError> {
159        esp!(unsafe { temperature_sensor_disable(self.ptr) })
160    }
161
162    pub fn get_celsius(&self) -> Result<f32, EspError> {
163        let mut val = 0.0;
164        esp!(unsafe { temperature_sensor_get_celsius(self.ptr, &mut val) })?;
165        Ok(val)
166    }
167
168    pub fn get_fahrenheit(&self) -> Result<f32, EspError> {
169        let celsius = self.get_celsius()?;
170        Ok((celsius * 1.8) + 32.0)
171    }
172
173    pub fn get_kelvin(&self) -> Result<f32, EspError> {
174        let celsius = self.get_celsius()?;
175        Ok(celsius + 273.15)
176    }
177}
178
179impl Drop for TempSensorDriver<'_> {
180    fn drop(&mut self) {
181        let _ = self.disable();
182        esp!(unsafe { temperature_sensor_uninstall(self.ptr) }).unwrap();
183    }
184}
185
186unsafe impl Send for TempSensorDriver<'_> {}
187
188crate::impl_peripheral!(TempSensor);