use crate::ral;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct PowerDownError(());
pub struct TempMon {
base: ral::tempmon::TEMPMON,
scaler: i32,
hot_count: i32,
hot_temp: i32,
}
impl core::fmt::Debug for TempMon {
fn fmt(&self, fmt: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
fmt.debug_struct("TempMon")
.field("scaler", &format_args!("{}", self.scaler))
.field("hot_count", &format_args!("{}", self.hot_count))
.field("hot_temp", &format_args!("{}", self.hot_temp))
.finish()
}
}
impl TempMon {
pub fn new(tempmon: ral::tempmon::TEMPMON) -> Self {
let calibration = unsafe { ral::read_reg!(ral::ocotp, OCOTP, ANA1) };
let n1_room_count = (calibration >> 20) as i32;
let t1_room_temp = 25_000_i32;
let n2_hot_count = ((calibration >> 8) & 0xFFF) as i32;
let t2_hot_temp = (calibration & 0xFF) as i32 * 1_000;
let scaler = (t2_hot_temp - t1_room_temp) / (n1_room_count - n2_hot_count);
let t = Self {
base: tempmon,
scaler,
hot_count: n2_hot_count,
hot_temp: t2_hot_temp,
};
t.power_up();
t
}
pub fn with_measure_freq(tempmon: ral::tempmon::TEMPMON, measure_freq: u16) -> Self {
let mut t = Self::new(tempmon);
t.set_measure_frequency(measure_freq);
t
}
fn convert(&self, temp_cnt: i32) -> i32 {
let n_meas = temp_cnt - self.hot_count;
self.hot_temp - n_meas * self.scaler
}
fn decode(&self, temp_value_mc: i32) -> u32 {
let v = (temp_value_mc - self.hot_temp) / self.scaler;
(self.hot_count - v) as u32
}
pub fn measure_temp(&mut self) -> nb::Result<i32, PowerDownError> {
if !self.is_powered_up() {
Err(nb::Error::from(PowerDownError(())))
} else {
let active = ral::read_reg!(ral::tempmon, self.base, TEMPSENSE0, MEASURE_TEMP == START);
if !active {
ral::write_reg!(ral::tempmon, self.base, TEMPSENSE0_SET, MEASURE_TEMP: START);
}
if ral::read_reg!(ral::tempmon, self.base, TEMPSENSE0, FINISHED == INVALID) {
Err(nb::Error::WouldBlock)
} else {
ral::write_reg!(ral::tempmon, self.base, TEMPSENSE0_CLR, MEASURE_TEMP: START);
let temp_cnt = ral::read_reg!(ral::tempmon, self.base, TEMPSENSE0, TEMP_CNT) as i32;
Ok(self.convert(temp_cnt))
}
}
}
pub fn get_temp(&self) -> nb::Result<i32, PowerDownError> {
if self.is_powered_up() {
let temp_cnt = ral::read_reg!(ral::tempmon, self.base, TEMPSENSE0, TEMP_CNT) as i32;
Ok(self.convert(temp_cnt))
} else {
Err(nb::Error::from(PowerDownError(())))
}
}
pub fn start(&mut self) -> nb::Result<(), PowerDownError> {
if self.is_powered_up() {
ral::write_reg!(ral::tempmon, self.base, TEMPSENSE0_SET, MEASURE_TEMP: START);
Ok(())
} else {
Err(nb::Error::from(PowerDownError(())))
}
}
pub fn stop(&self) {
ral::write_reg!(ral::tempmon, self.base, TEMPSENSE0_CLR, MEASURE_TEMP: START);
}
pub fn is_powered_up(&self) -> bool {
ral::read_reg!(ral::tempmon, self.base, TEMPSENSE0, POWER_DOWN == POWER_UP)
}
pub fn power_down(&self) {
ral::write_reg!(
ral::tempmon,
self.base,
TEMPSENSE0_SET,
POWER_DOWN: POWER_DOWN
);
}
pub fn power_up(&self) {
ral::write_reg!(
ral::tempmon,
self.base,
TEMPSENSE0_CLR,
POWER_DOWN: POWER_DOWN
);
}
pub fn set_alarm_values(&mut self, low_alarm_mc: i32, high_alarm_mc: i32, panic_alarm_mc: i32) {
let low_alarm = self.decode(low_alarm_mc);
let high_alarm = self.decode(high_alarm_mc);
let panic_alarm = self.decode(panic_alarm_mc);
ral::modify_reg!(ral::tempmon, self.base, TEMPSENSE0, ALARM_VALUE: high_alarm);
ral::write_reg!(
ral::tempmon,
self.base,
TEMPSENSE2,
LOW_ALARM_VALUE: low_alarm,
PANIC_ALARM_VALUE: panic_alarm
);
}
pub fn alarm_values(&self) -> (i32, i32, i32) {
let high_alarm = ral::read_reg!(ral::tempmon, self.base, TEMPSENSE0, ALARM_VALUE);
let (low_alarm, panic_alarm) = ral::read_reg!(
ral::tempmon,
self.base,
TEMPSENSE2,
LOW_ALARM_VALUE,
PANIC_ALARM_VALUE
);
(
self.convert(low_alarm as i32),
self.convert(high_alarm as i32),
self.convert(panic_alarm as i32),
)
}
pub fn set_measure_frequency(&mut self, measure_freq: u16) {
ral::modify_reg!(
ral::tempmon,
self.base,
TEMPSENSE1,
MEASURE_FREQ: measure_freq as u32
);
}
}