blob: 4420791bd1801f8059acb046f1aa704c873fd48e [file] [log] [blame]
use crate::futures;
use crate::result::TockError;
use crate::syscalls;
use core::cell::Cell;
use core::fmt;
use core::fmt::Display;
use core::mem;
const DRIVER_NUMBER: usize = 0x60000;
mod command_nr {
pub const START_MEASUREMENT: usize = 1;
}
mod subscribe_nr {
pub const SUBSCRIBE_CALLBACK: usize = 0;
}
#[non_exhaustive]
pub struct TemperatureDriver;
impl TemperatureDriver {
pub async fn measure_temperature(&mut self) -> Result<Temperature, TockError> {
let temperature = Cell::<Option<isize>>::new(None);
let mut callback = |arg1, _, _| temperature.set(Some(arg1 as isize));
let subscription = syscalls::subscribe(
DRIVER_NUMBER,
subscribe_nr::SUBSCRIBE_CALLBACK,
&mut callback,
)?;
syscalls::command(DRIVER_NUMBER, command_nr::START_MEASUREMENT, 0, 0)?;
let temperatur = Temperature {
centi_celsius: futures::wait_for_value(|| temperature.get()).await,
};
mem::drop(subscription);
Ok(temperatur)
}
}
#[derive(Copy, Clone)]
pub struct Temperature {
centi_celsius: isize,
}
impl Temperature {
pub fn in_celsius(self) -> isize {
self.centi_celsius / 100
}
pub fn in_centi_celsius(self) -> isize {
self.centi_celsius
}
}
impl Display for Temperature {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"{}.{:02}°C",
self.centi_celsius / 100,
self.centi_celsius.abs() % 100
)
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn render_temperature() {
assert_eq!(render_temperature_for(0), "0.00°C");
assert_eq!(render_temperature_for(5), "0.05°C");
assert_eq!(render_temperature_for(105), "1.05°C");
assert_eq!(render_temperature_for(125), "1.25°C");
assert_eq!(render_temperature_for(1025), "10.25°C");
assert_eq!(render_temperature_for(-1025), "-10.25°C");
}
fn render_temperature_for(centi_celsius: isize) -> String {
Temperature { centi_celsius }.to_string()
}
}