@@ -81,7 +81,12 @@ impl<I2C: embedded_hal_async::i2c::I2c> Lis2dw12<I2C> {
8181
8282 /// Modifies the specified register by first reading then setting or resetting specified bits
8383 /// If a bit is marked in both set and reset masks, then that bit will not be updated
84- pub async fn modify_reg ( & mut self , reg : Register , bits_to_reset : u8 , bits_to_set : u8 ) -> Result < ( ) , I2C :: Error > {
84+ pub async fn modify_reg_bits (
85+ & mut self ,
86+ reg : Register ,
87+ bits_to_reset : u8 ,
88+ bits_to_set : u8 ,
89+ ) -> Result < ( ) , I2C :: Error > {
8590 // Filter masks to clear overlap bits
8691 let both_mask: u8 = bits_to_reset & bits_to_set;
8792 let reset_mask: u8 = bits_to_reset & !both_mask;
@@ -97,94 +102,211 @@ impl<I2C: embedded_hal_async::i2c::I2c> Lis2dw12<I2C> {
97102 self . write_reg ( reg, current) . await
98103 }
99104
100- /// Reads the device temperature with 12 bit precision
105+ /// Modifies the specified register by first reading then replacing the masked bits with the value's bits
106+ pub async fn modify_reg_field ( & mut self , reg : Register , val : u8 , mask : u8 ) -> Result < ( ) , I2C :: Error > {
107+ // Read current value of that register
108+ let mut current: u8 = self . read_reg ( reg) . await ?;
109+
110+ // Update the register value with the new masked bits
111+ current = ( current & !mask) | ( val & mask) ;
112+
113+ self . write_reg ( reg, current) . await
114+ }
115+
116+ /// Reads the device temperature with 12 bit precision. The LSB bits 3..0 are unused 0
117+ /// Offset: 0 LSB = 25 deg C
118+ /// Scale: 16 LSB / deg C (Note: LSB bits 3..0 are unused 0, so the LSB is at bit 4)
101119 pub async fn temp_12bit ( & mut self ) -> Result < i16 , I2C :: Error > {
102120 let mut temp: i16 = 0 ;
103121 temp += ( ( self . read_reg ( Register :: TempOutHigh ) . await ?) as i16 ) << 8 ;
104122 temp += ( self . read_reg ( Register :: TempOutLow ) . await ?) as i16 ;
105- temp >>= 4 ;
106123 Ok ( temp)
107124 }
108125
109126 /// Reads the device temperature with 8 bit precision
127+ /// Offset: 0 LSB = 25 deg C
128+ /// Scale: 1 deg C / LSB
110129 pub async fn temp_8bit ( & mut self ) -> Result < i8 , I2C :: Error > {
111130 Ok ( self . read_reg ( Register :: TempOut ) . await ? as i8 )
112131 }
113132
114- /// Reads the device acceleration in the X axis
133+ /// Reads the current temperature and returns the value in degrees Celcius
134+ pub async fn temp_celcius ( & mut self ) -> Result < f32 , I2C :: Error > {
135+ Ok ( Lis2dw12 :: < I2C > :: convert_temp_reg_to_celcius ( self . temp_12bit ( ) . await ?) )
136+ }
137+
138+ /// Reads the device acceleration register in the X axis
115139 pub async fn acc_x ( & mut self ) -> Result < i16 , I2C :: Error > {
116140 let mut accx: i16 = 0 ;
117141 accx += ( ( self . read_reg ( Register :: XOutHigh ) . await ?) as i16 ) << 8 ;
118142 accx += ( self . read_reg ( Register :: XOutLow ) . await ?) as i16 ;
119143 Ok ( accx)
120144 }
121145
122- /// Reads the device acceleration in the Y axis
146+ /// Reads the device acceleration register in the Y axis
123147 pub async fn acc_y ( & mut self ) -> Result < i16 , I2C :: Error > {
124148 let mut accy: i16 = 0 ;
125149 accy += ( ( self . read_reg ( Register :: YOutHigh ) . await ?) as i16 ) << 8 ;
126150 accy += ( self . read_reg ( Register :: YOutLow ) . await ?) as i16 ;
127151 Ok ( accy)
128152 }
129153
130- /// Reads the device acceleration in the Z axis
154+ /// Reads the device acceleration register in the Z axis
131155 pub async fn acc_z ( & mut self ) -> Result < i16 , I2C :: Error > {
132156 let mut accz: i16 = 0 ;
133157 accz += ( ( self . read_reg ( Register :: ZOutHigh ) . await ?) as i16 ) << 8 ;
134158 accz += ( self . read_reg ( Register :: ZOutLow ) . await ?) as i16 ;
135159 Ok ( accz)
136160 }
137161
138- /// Reads the 3D device acceleration
162+ /// Reads the 3D device acceleration from registers
139163 pub async fn acc ( & mut self ) -> Result < ( i16 , i16 , i16 ) , I2C :: Error > {
140164 Ok ( ( self . acc_x ( ) . await ?, self . acc_y ( ) . await ?, self . acc_z ( ) . await ?) )
141165 }
142166
167+ /// Returns the 3D device acceleration in Gs
168+ pub async fn acc_gs ( & mut self ) -> Result < ( f32 , f32 , f32 ) , I2C :: Error > {
169+ let full_scale = self . full_scale_range ( ) . await ?;
170+ let ( accx, accy, accz) = self . acc ( ) . await ?;
171+ Ok ( (
172+ Lis2dw12 :: < I2C > :: convert_acc_to_gs ( accx, full_scale) ,
173+ Lis2dw12 :: < I2C > :: convert_acc_to_gs ( accy, full_scale) ,
174+ Lis2dw12 :: < I2C > :: convert_acc_to_gs ( accz, full_scale) ,
175+ ) )
176+ }
177+
178+ /// Returns the 3D device acceleration in milli-Gs
179+ pub async fn acc_mgs ( & mut self ) -> Result < ( f32 , f32 , f32 ) , I2C :: Error > {
180+ let full_scale = self . full_scale_range ( ) . await ?;
181+ let ( accx, accy, accz) = self . acc ( ) . await ?;
182+ Ok ( (
183+ Lis2dw12 :: < I2C > :: convert_acc_to_mgs ( accx, full_scale) ,
184+ Lis2dw12 :: < I2C > :: convert_acc_to_mgs ( accy, full_scale) ,
185+ Lis2dw12 :: < I2C > :: convert_acc_to_mgs ( accz, full_scale) ,
186+ ) )
187+ }
188+
189+ /// Returns the 3D device acceleration in micro-Gs
190+ pub async fn acc_ugs ( & mut self ) -> Result < ( f32 , f32 , f32 ) , I2C :: Error > {
191+ let full_scale = self . full_scale_range ( ) . await ?;
192+ let ( accx, accy, accz) = self . acc ( ) . await ?;
193+ Ok ( (
194+ Lis2dw12 :: < I2C > :: convert_acc_to_ugs ( accx, full_scale) ,
195+ Lis2dw12 :: < I2C > :: convert_acc_to_ugs ( accy, full_scale) ,
196+ Lis2dw12 :: < I2C > :: convert_acc_to_ugs ( accz, full_scale) ,
197+ ) )
198+ }
199+
200+ /// Reads the tap threshold value in the X axis from its register fields
143201 pub async fn tap_threshold_x ( & mut self ) -> Result < u8 , I2C :: Error > {
144- self . read_reg ( Register :: TapThresholdX ) . await
202+ Ok ( self . read_reg ( Register :: TapThresholdX ) . await ? & 0x1F )
145203 }
146204
205+ /// Reads the tap threshold value in the Y axis from its register fields
147206 pub async fn tap_threshold_y ( & mut self ) -> Result < u8 , I2C :: Error > {
148- self . read_reg ( Register :: TapThresholdY ) . await
207+ Ok ( self . read_reg ( Register :: TapThresholdY ) . await ? & 0x1F )
149208 }
150209
210+ /// Reads the tap threshold value in the Z axis from its register fields
151211 pub async fn tap_threshold_z ( & mut self ) -> Result < u8 , I2C :: Error > {
152- self . read_reg ( Register :: TapThresholdZ ) . await
212+ Ok ( self . read_reg ( Register :: TapThresholdZ ) . await ? & 0x1F )
153213 }
154214
215+ /// Sets the tap threshold value in the X axis
216+ /// Does not update the rest of the register
155217 pub async fn set_tap_threshold_x ( & mut self , ths : u8 ) -> Result < ( ) , I2C :: Error > {
156- self . write_reg ( Register :: TapThresholdX , ths) . await
218+ self . modify_reg_field ( Register :: TapThresholdX , ths, 0x1F ) . await
157219 }
158220
221+ /// Sets the tap threshold value in the Y axis
222+ /// Does not update the rest of the register
159223 pub async fn set_tap_threshold_y ( & mut self , ths : u8 ) -> Result < ( ) , I2C :: Error > {
160- self . write_reg ( Register :: TapThresholdY , ths) . await
224+ self . modify_reg_field ( Register :: TapThresholdY , ths, 0x1F ) . await
161225 }
162226
227+ /// Sets the tap threshold value in the Z axis
228+ /// Does not update the rest of the register
163229 pub async fn set_tap_threshold_z ( & mut self , ths : u8 ) -> Result < ( ) , I2C :: Error > {
164- self . write_reg ( Register :: TapThresholdZ , ths) . await
230+ self . modify_reg_field ( Register :: TapThresholdZ , ths, 0x1F ) . await
165231 }
166232
233+ /// Reads the Status register
167234 pub async fn status ( & mut self ) -> Result < StatusReg , I2C :: Error > {
168235 let reg: u8 = self . read_reg ( Register :: Status ) . await ?;
169236 Ok ( reg. into ( ) )
170237 }
171238
239+ /// Reads the full scale range from Control Register 6
172240 pub async fn full_scale_range ( & mut self ) -> Result < Control6FullScale , I2C :: Error > {
173241 let ctrl6: ControlReg6 = self . read_reg ( Register :: Control6 ) . await ?. into ( ) ;
174242 Ok ( ctrl6. fs ( ) )
175243 }
176244
245+ /// Sets the full scale range in Control Register 6
177246 pub async fn set_full_scale_range ( & mut self , new_fs : Control6FullScale ) -> Result < ( ) , I2C :: Error > {
178247 let mut ctrl6: ControlReg6 = self . read_reg ( Register :: Control6 ) . await ?. into ( ) ;
179248 ctrl6. set_fs ( new_fs) ;
180249 self . write_reg ( Register :: Control6 , ctrl6. into ( ) ) . await
181250 }
182251
252+ /// Returns free fall duration by stitching FF_DUR5 from WAKE_UP_DUR register onto FF register output
183253 pub async fn free_fall_duration ( & mut self ) -> Result < u8 , I2C :: Error > {
184- // Get full free fall duration by stitching FF_DUR5 from WAKE_UP_DUR register onto FF register output
185254 let ff_reg: FreeFallReg = self . read_reg ( Register :: FreeFall ) . await ?. into ( ) ;
186255 let wu_reg: WakeUpDurationReg = self . read_reg ( Register :: WakeUpDuration ) . await ?. into ( ) ;
187256 let ff_dur: u8 = u8:: from ( ff_reg. ff_dur ( ) ) + ( u8:: from ( wu_reg. ff_dur5 ( ) ) << 5 ) ;
188257 Ok ( ff_dur)
189258 }
259+
260+ // -------------------------- Helper Functions --------------------------
261+
262+ /// Converts i16 temperature representation to degrees Celcius
263+ /// For use with 8bit temp register, convert to i16 and shift data to upper (MSB) byte for input
264+ pub fn convert_temp_reg_to_celcius ( temp_in : i16 ) -> f32 {
265+ // Convert temp int to float
266+ let mut temp: f32 = temp_in as f32 ;
267+
268+ // Divide out temp offset: bit 8 (LSB of upper byte) = 1 deg C
269+ temp /= 256f32 ;
270+
271+ // Add offset of 25 deg C at 0
272+ temp += 25f32 ;
273+
274+ temp
275+ }
276+
277+ /// Converts the acceleration register data to acceleration in Gs
278+ pub fn convert_acc_to_gs ( acc_in : i16 , full_scale : Control6FullScale ) -> f32 {
279+ let acc: f32 = acc_in as f32 ;
280+ let factor: f32 = match full_scale {
281+ Control6FullScale :: Scale2g => 1f32 / 16384f32 ,
282+ Control6FullScale :: Scale4g => 1f32 / 8192f32 ,
283+ Control6FullScale :: Scale8g => 1f32 / 4096f32 ,
284+ Control6FullScale :: Scale16g => 1f32 / 2048f32 ,
285+ } ;
286+ acc * factor
287+ }
288+
289+ /// Converts the acceleration register data to acceleration in milli-Gs
290+ pub fn convert_acc_to_mgs ( acc_in : i16 , full_scale : Control6FullScale ) -> f32 {
291+ let acc: f32 = acc_in as f32 ;
292+ let factor: f32 = match full_scale {
293+ Control6FullScale :: Scale2g => 1000f32 / 16384f32 ,
294+ Control6FullScale :: Scale4g => 1000f32 / 8192f32 ,
295+ Control6FullScale :: Scale8g => 1000f32 / 4096f32 ,
296+ Control6FullScale :: Scale16g => 1000f32 / 2048f32 ,
297+ } ;
298+ acc * factor
299+ }
300+
301+ /// Converts the acceleration register data to acceleration in micro-Gs
302+ pub fn convert_acc_to_ugs ( acc_in : i16 , full_scale : Control6FullScale ) -> f32 {
303+ let acc: f32 = acc_in as f32 ;
304+ let factor: f32 = match full_scale {
305+ Control6FullScale :: Scale2g => 1_000_000f32 / 16384f32 ,
306+ Control6FullScale :: Scale4g => 1_000_000f32 / 8192f32 ,
307+ Control6FullScale :: Scale8g => 1_000_000f32 / 4096f32 ,
308+ Control6FullScale :: Scale16g => 1_000_000f32 / 2048f32 ,
309+ } ;
310+ acc * factor
311+ }
190312}
0 commit comments