umsh_radio_loraphy/
temperature.rs1use lora_phy::{
4 lr1110::{Lr1110, Lr1110Variant},
5 mod_traits::{InterfaceVariant, RadioKind},
6};
7
8pub trait TemperatureSensor<RK: RadioKind> {
11 const SUPPORTED: bool;
12 async fn sample(&mut self, radio: &mut RK) -> Option<u16>;
15}
16
17pub struct NoTemperature;
18impl<RK: RadioKind> TemperatureSensor<RK> for NoTemperature {
19 const SUPPORTED: bool = false;
20 async fn sample(&mut self, _: &mut RK) -> Option<u16> {
21 None
22 }
23}
24
25pub struct Lr1110Temperature;
26impl<SPI, IV, C> TemperatureSensor<Lr1110<SPI, IV, C>> for Lr1110Temperature
27where
28 SPI: embedded_hal_async::spi::SpiDevice<u8>,
29 IV: InterfaceVariant,
30 C: Lr1110Variant,
31{
32 const SUPPORTED: bool = true;
33 async fn sample(&mut self, radio: &mut Lr1110<SPI, IV, C>) -> Option<u16> {
34 from_lr1110_raw(radio.get_temp().await.ok()?)
35 }
36}
37
38pub fn from_lr1110_raw(raw: u16) -> Option<u16> {
43 let raw = i64::from(raw & 0x07ff);
44 let denominator = 2 * 2047 * 170;
45 let numerator = 5963 * 2047 * 170 + 2 * (729500 * 2047 - raw * 1350000);
46 if numerator < 0 {
47 return None;
48 }
49 u16::try_from((numerator + denominator / 2) / denominator)
50 .ok()
51 .filter(|&value| value != u16::MAX)
52}
53
54#[cfg(test)]
55mod tests {
56 use super::*;
57 #[test]
58 fn temperature_raw_codes_convert_to_tenths_kelvin() {
59 assert_eq!(from_lr1110_raw(1106), Some(2982));
60 assert_eq!(from_lr1110_raw(1200), Some(2617));
61 assert_eq!(from_lr1110_raw(0), Some(7273));
62 assert_eq!(from_lr1110_raw(2047), None); assert_eq!(from_lr1110_raw(1106 | 0xf800), Some(2982));
64 }
65}