1- const RAD_PER_DEG : f32 = 2. * core:: f32:: consts:: PI / 360 .;
1+ const RAD_PER_DEG : f32 = core:: f32:: consts:: PI / 180 .;
22const DEG_PER_RAD : f32 = 1. / RAD_PER_DEG ;
3+ const ACCEL_PER_G : f32 = 9.81 ;
4+ const G_PER_ACCEL : f32 = 1. / ACCEL_PER_G ;
35
46// TODO: This whole module needs unit tests
57
@@ -13,6 +15,7 @@ pub enum GyroFsr {
1315 D250 ,
1416 D125 ,
1517}
18+
1619#[ allow( dead_code) ]
1720impl GyroFsr {
1821 /// The default FSR when the IMU is reset
@@ -85,16 +88,102 @@ impl GyroFsr {
8588 pub const fn rad_per_lsb ( self ) -> f32 {
8689 self . dps_per_lsb ( ) * RAD_PER_DEG
8790 }
91+
92+ /// The bmi160 returns the data from the gyro as an `i16`, we must use the Full
93+ /// Scale Range to convert to a float rad/s
94+ pub const fn discrete_to_velocity ( self , discrete : i16 ) -> f32 {
95+ discrete as f32 * self . rad_per_lsb ( )
96+ }
97+ }
98+
99+ /// The Full Scale Range of the accelerometer. For example, G2 means +/- 19.6 meters/sec^2
100+ #[ derive( Eq , PartialEq , Copy , Clone , Debug ) ]
101+ #[ allow( dead_code) ]
102+ pub enum AccelFsr {
103+ G2 ,
104+ G4 ,
105+ G8 ,
106+ G16 ,
107+ }
108+
109+ #[ allow( dead_code) ]
110+ impl AccelFsr {
111+ /// The default FSR when the IMU is reset
112+ pub const DEFAULT : Self = Self :: G2 ;
113+ pub const fn from_reg ( v : u8 ) -> Result < Self , InvalidBitPattern > {
114+ Ok ( match v {
115+ 0b0011 => Self :: G2 ,
116+ 0b0101 => Self :: G4 ,
117+ 0b1000 => Self :: G8 ,
118+ 0b1100 => Self :: G16 ,
119+ _ => return Err ( InvalidBitPattern ) ,
120+ } )
121+ }
122+
123+ pub const fn to_reg ( self ) -> u8 {
124+ match self {
125+ Self :: G2 => 0b0011 ,
126+ Self :: G4 => 0b0101 ,
127+ Self :: G8 => 0b1000 ,
128+ Self :: G16 => 0b1100 ,
129+ }
130+ }
131+
132+ pub const fn as_u16 ( self ) -> u16 {
133+ match self {
134+ Self :: G2 => 2 ,
135+ Self :: G4 => 4 ,
136+ Self :: G8 => 8 ,
137+ Self :: G16 => 16 ,
138+ }
139+ }
140+
141+ pub const fn from_u16 ( v : u16 ) -> Result < Self , InvalidNum > {
142+ // TODO: I'm not confident this is performant
143+ Ok ( match v {
144+ v if v == Self :: G2 . as_u16 ( ) => Self :: G2 ,
145+ v if v == Self :: G4 . as_u16 ( ) => Self :: G4 ,
146+ v if v == Self :: G8 . as_u16 ( ) => Self :: G8 ,
147+ v if v == Self :: G16 . as_u16 ( ) => Self :: G16 ,
148+ _ => return Err ( InvalidNum ) ,
149+ } )
150+ }
151+
152+ /// least signficant bits per g
153+ pub const fn lsb_per_g ( self ) -> f32 {
154+ let range: f32 = self . as_u16 ( ) as _ ;
155+ // Add 1 because there is MAX+1 numbers due to `0`
156+ const TMP : f32 = i16:: MAX as f32 + 1. ;
157+ TMP / range
158+ }
159+
160+ /// g per least significant bit
161+ pub const fn g_per_lsb ( self ) -> f32 {
162+ let range: f32 = self . as_u16 ( ) as _ ;
163+ // Add 1 because there is MAX+1 numbers due to `0`
164+ const TMP : f32 = 1. / ( i16:: MAX as f32 + 1. ) ;
165+ range * TMP
166+ }
167+
168+ /// least significant bits per accel
169+ pub const fn lsb_per_accel ( self ) -> f32 {
170+ self . lsb_per_g ( ) * ACCEL_PER_G
171+ }
172+
173+ /// g per least significant bit
174+ pub const fn accel_per_lsb ( self ) -> f32 {
175+ self . g_per_lsb ( ) * G_PER_ACCEL
176+ }
177+
178+ /// The bmi160 returns the data from the accel as an `i16`, we must use the Full
179+ /// Scale Range to convert to a float m/s^2
180+ pub const fn discrete_to_accel ( self , discrete : i16 ) -> f32 {
181+ discrete as f32 * self . accel_per_lsb ( )
182+ }
88183}
89184
90185#[ derive( Debug ) ]
91186pub struct InvalidBitPattern ;
92187
93188#[ derive( Debug ) ]
94189pub struct InvalidNum ;
95-
96- /// The bmi160 returns the data from the gyro as an `i16`, we must use the Full Scale Range to
97- /// convert to a float.
98- pub const fn discrete_to_radians ( fsr : GyroFsr , discrete : i16 ) -> f32 {
99- discrete as f32 * fsr. rad_per_lsb ( )
100- }
0 commit comments