summaryrefslogtreecommitdiffstats
path: root/src/conversion.rs
blob: 142de0ec4c6c3cc87d5de2cf6def829c0d1ff209 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
use crate::{ic, private, Error};

#[doc(hidden)]
pub trait ConvertThreshold<E>: private::Sealed {
    fn convert_threshold(value: i16) -> Result<u16, Error<E>>;
}

impl<E> ConvertThreshold<E> for ic::Resolution12Bit {
    fn convert_threshold(value: i16) -> Result<u16, Error<E>> {
        if !(-2048..=2047).contains(&value) {
            return Err(Error::InvalidInputData);
        }
        Ok((value << 4) as u16)
    }
}

impl<E> ConvertThreshold<E> for ic::Resolution16Bit {
    fn convert_threshold(value: i16) -> Result<u16, Error<E>> {
        Ok(value as u16)
    }
}

#[doc(hidden)]
pub trait ConvertMeasurement: private::Sealed {
    fn convert_measurement(register_data: u16) -> i16;
}

impl ConvertMeasurement for ic::Resolution12Bit {
    fn convert_measurement(register_data: u16) -> i16 {
        let value = register_data;
        let is_negative = (value & 0b1000_0000_0000_0000) != 0;
        if is_negative {
            let value = 0b1111_0000_0000_0000 | (value >> 4);
            value as i16
        } else {
            (value >> 4) as i16
        }
    }
}

impl ConvertMeasurement for ic::Resolution16Bit {
    fn convert_measurement(register_data: u16) -> i16 {
        register_data as i16
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn convert_measurement_12_bits() {
        assert_eq!(0, ic::Resolution12Bit::convert_measurement(0));
        assert_eq!(2047, ic::Resolution12Bit::convert_measurement(0x7FFF));
        assert_eq!(-2048, ic::Resolution12Bit::convert_measurement(0x8000));
        assert_eq!(-1, ic::Resolution12Bit::convert_measurement(0xFFFF));
    }

    #[test]
    fn convert_measurement_16_bits() {
        assert_eq!(0, ic::Resolution16Bit::convert_measurement(0));
        assert_eq!(32767, ic::Resolution16Bit::convert_measurement(0x7FFF));
        assert_eq!(-32768, ic::Resolution16Bit::convert_measurement(0x8000));
        assert_eq!(-1, ic::Resolution16Bit::convert_measurement(0xFFFF));
    }

    fn assert_invalid_input_data<E>(result: Result<u16, Error<E>>) {
        match result {
            Err(Error::InvalidInputData) => (),
            _ => panic!("InvalidInputData error was not returned."),
        }
    }

    #[test]
    fn check_assert_matches() {
        assert_invalid_input_data::<()>(Err(Error::InvalidInputData));
    }

    #[test]
    #[should_panic]
    fn check_assert_fails() {
        assert_invalid_input_data::<()>(Ok(0));
    }

    fn convert_threshold<T: ConvertThreshold<()>>(value: i16) -> u16 {
        T::convert_threshold(value).unwrap()
    }

    #[test]
    fn convert_threshold_12_bits() {
        assert_invalid_input_data::<()>(ic::Resolution12Bit::convert_threshold(2048));
        assert_invalid_input_data::<()>(ic::Resolution12Bit::convert_threshold(-2049));
        assert_eq!(0, convert_threshold::<ic::Resolution12Bit>(0));
        assert_eq!(0x7FF0, convert_threshold::<ic::Resolution12Bit>(2047));
        assert_eq!(0x8000, convert_threshold::<ic::Resolution12Bit>(-2048));
        assert_eq!(0xFFF0, convert_threshold::<ic::Resolution12Bit>(-1));
    }

    #[test]
    fn convert_threshold_16_bits() {
        assert_eq!(0x7FFF, convert_threshold::<ic::Resolution16Bit>(32767));
        assert_eq!(0x8000, convert_threshold::<ic::Resolution16Bit>(-32768));
    }
}