@@ -60,12 +60,76 @@ pub struct Vbat;
6060/// Core temperature internal signal
6161pub struct Temperature ;
6262impl Temperature {
63+ /// Precompute the inverse of `VTEMP_CAL_VREFANALOG`, in volts,
64+ /// for floating point calculations
65+ const INV_VREFANALOG_VOLTS : f32 = 1000. / VDDA_CALIB as f32 ;
66+ /// Temperature at which temperature sensor has been calibrated in production
67+ /// for data into [`VtempCal30`] (tolerance: +-5 DegC) (unit: DegC).
68+ const VTEMP_CAL_T30 : u16 = 30 ;
69+ /// Temperature at which temperature sensor has been calibrated in production
70+ /// for data into [`VtempCal130`] (tolerance: +-5 DegC) (unit: DegC).
71+ const VTEMP_CAL_T130 : u16 = 130 ;
72+
73+ /// Convert a sample to 12 bits. Reference voltages were captured at 12 bits.
74+ const fn to_12b ( sample : u16 , resolution : config:: Resolution ) -> u16 {
75+ match resolution {
76+ config:: Resolution :: Six => sample << 6 ,
77+ config:: Resolution :: Eight => sample << 4 ,
78+ config:: Resolution :: Ten => sample << 2 ,
79+ config:: Resolution :: Twelve => sample,
80+ }
81+ }
82+
83+ /// Convert a raw sample from `Temperature` to deg C.
84+ ///
85+ /// ## Arguments
86+ /// * `sample`: ADC sample taken on the [`Temperature`] channel.
87+ /// * `vdda`: Analog reference voltage (vref+) when the temperature
88+ /// sample was taken, in volts.
89+ /// * `resolution`: Configured ADC resolution.
90+ #[ inline( always) ]
91+ pub fn temperature_to_degrees_centigrade (
92+ sample : u16 ,
93+ vdda : f32 ,
94+ resolution : config:: Resolution ,
95+ ) -> f32 {
96+ // Reference measurements were taken at 12 bits
97+ let sample_12b = Self :: to_12b ( sample, resolution) ;
98+
99+ // Normalize for the difference in VDDA
100+ let sample_normalized = sample_12b as f32 * ( vdda * Self :: INV_VREFANALOG_VOLTS ) ;
101+
102+ ( ( sample_normalized - VtempCal30 :: get ( ) . read ( ) as f32 )
103+ * ( ( Self :: VTEMP_CAL_T130 - Self :: VTEMP_CAL_T30 ) as f32 ) )
104+ / ( ( VtempCal130 :: get ( ) . read ( ) - VtempCal30 :: get ( ) . read ( ) ) as f32 )
105+ + Self :: VTEMP_CAL_T30 as f32
106+ }
107+
63108 /// Convert a raw sample from `Temperature` to deg C
109+ ///
110+ /// ## Arguments
111+ /// * `sample`: ADC sample taken on the [`Temperature`] channel.
112+ /// * `vdda`: Analog reference voltage (vref+) when the temperature
113+ /// sample was taken, in millivolts.
114+ /// * `resolution`: Configured ADC resolution.
64115 #[ inline( always) ]
65- pub fn temperature_to_degrees_centigrade ( sample : u16 ) -> f32 {
66- ( ( 130.0 - 30.0 ) / ( VtempCal130 :: get ( ) . read ( ) as f32 - VtempCal30 :: get ( ) . read ( ) as f32 )
67- * ( sample as f32 - VtempCal30 :: get ( ) . read ( ) as f32 ) )
68- + 30.0
116+ pub fn temperature_to_degrees_centigrade_coarse (
117+ sample : u16 ,
118+ vdda : u32 ,
119+ resolution : config:: Resolution ,
120+ ) -> i16 {
121+ // Reference measurements were taken at 12 bits
122+ let sample_12b = Self :: to_12b ( sample, resolution) ;
123+
124+ // Normalize for the difference in VDDA
125+ let sample_normalized = ( ( sample_12b as u32 * vdda) / VDDA_CALIB ) as u16 ;
126+
127+ let t = ( ( sample_normalized as i32 - VtempCal30 :: get ( ) . read ( ) as i32 )
128+ * ( ( Self :: VTEMP_CAL_T130 - Self :: VTEMP_CAL_T30 ) as i32 ) )
129+ / ( ( VtempCal130 :: get ( ) . read ( ) - VtempCal30 :: get ( ) . read ( ) ) as i32 )
130+ + Self :: VTEMP_CAL_T30 as i32 ;
131+
132+ t as i16
69133 }
70134}
71135
0 commit comments