capsules_extra/
temperature_stm.rs1use core::cell::Cell;
8use kernel::hil::adc;
9use kernel::hil::sensors;
10use kernel::utilities::cells::OptionalCell;
11use kernel::ErrorCode;
12
13use capsules_core::driver;
14pub const DRIVER_NUM: usize = driver::NUM::Temperature as usize;
15
16#[derive(Copy, Clone, PartialEq)]
17pub enum Status {
18 Read,
19 Idle,
20}
21
22pub struct TemperatureSTM<'a, A: adc::AdcChannel<'a>> {
23 adc: &'a A,
24 slope: f32,
25 v_25: f32,
26 temperature_client: OptionalCell<&'a dyn sensors::TemperatureClient>,
27 status: Cell<Status>,
28}
29
30impl<'a, A: adc::AdcChannel<'a>> TemperatureSTM<'a, A> {
31 pub fn new(adc: &'a A, slope: f32, v_25: f32) -> TemperatureSTM<'a, A> {
34 TemperatureSTM {
35 adc,
36 slope,
37 v_25,
38 temperature_client: OptionalCell::empty(),
39 status: Cell::new(Status::Idle),
40 }
41 }
42}
43
44impl<'a, A: adc::AdcChannel<'a>> adc::Client for TemperatureSTM<'a, A> {
45 fn sample_ready(&self, sample: u16) {
46 self.status.set(Status::Idle);
47 self.temperature_client.map(|client| {
48 client.callback(Ok(
49 ((((self.v_25 - (sample as f32 * 3.3 / 65535.0)) * 1000.0 / self.slope) + 25.0)
50 * 100.0) as i32,
51 ));
52 });
53 }
54}
55
56impl<'a, A: adc::AdcChannel<'a>> sensors::TemperatureDriver<'a> for TemperatureSTM<'a, A> {
57 fn set_client(&self, temperature_client: &'a dyn sensors::TemperatureClient) {
58 self.temperature_client.replace(temperature_client);
59 }
60
61 fn read_temperature(&self) -> Result<(), ErrorCode> {
62 if self.status.get() == Status::Idle {
63 self.status.set(Status::Read);
64 let _ = self.adc.sample();
65 Ok(())
66 } else {
67 Err(ErrorCode::BUSY)
68 }
69 }
70}