Skip to content

Commit 92b95d5

Browse files
author
Connor Truono
committed
Implement multi-byte I2C read/write functions and optimize driver functions
1 parent 22106b8 commit 92b95d5

File tree

1 file changed

+47
-25
lines changed

1 file changed

+47
-25
lines changed

src/lib.rs

Lines changed: 47 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,18 @@ impl<I2C: embedded_hal_async::i2c::I2c> Lis2dw12<I2C> {
7979
self.i2c.write(self.addr, data).await
8080
}
8181

82+
/// Read multiple bytes from LIS2DW12 registers
83+
pub async fn read_regs(&mut self, reg: Register, read_buf: &mut [u8]) -> Result<(), I2C::Error> {
84+
self.i2c.write_read(self.addr, &[reg as u8], read_buf).await?;
85+
Ok(())
86+
}
87+
88+
/// Write multiple bytes to LIS2DW12 registers
89+
/// NOTE: The first byte of the write data must be the starting register address to write
90+
pub async fn write_regs(&mut self, data: &[u8]) -> Result<(), I2C::Error> {
91+
self.i2c.write(self.addr, data).await
92+
}
93+
8294
/// Modifies the specified register by first reading then setting or resetting specified bits
8395
/// If a bit is marked in both set and reset masks, then that bit will not be updated
8496
pub async fn modify_reg_bits(
@@ -117,10 +129,9 @@ impl<I2C: embedded_hal_async::i2c::I2c> Lis2dw12<I2C> {
117129
/// Offset: 0 LSB = 25 deg C
118130
/// Scale: 16 LSB / deg C (Note: LSB bits 3..0 are unused 0, so the LSB is at bit 4)
119131
pub async fn temp_12bit(&mut self) -> Result<i16, I2C::Error> {
120-
let mut temp: i16 = 0;
121-
temp += ((self.read_reg(Register::TempOutHigh).await?) as i16) << 8;
122-
temp += (self.read_reg(Register::TempOutLow).await?) as i16;
123-
Ok(temp)
132+
let mut temp_bytes: [u8; 2] = [0; 2];
133+
self.read_regs(Register::TempOutLow, &mut temp_bytes).await?;
134+
Ok(i16::from_le_bytes(temp_bytes))
124135
}
125136

126137
/// Reads the device temperature with 8 bit precision
@@ -137,31 +148,34 @@ impl<I2C: embedded_hal_async::i2c::I2c> Lis2dw12<I2C> {
137148

138149
/// Reads the device acceleration register in the X axis
139150
pub async fn acc_x(&mut self) -> Result<i16, I2C::Error> {
140-
let mut accx: i16 = 0;
141-
accx += ((self.read_reg(Register::XOutHigh).await?) as i16) << 8;
142-
accx += (self.read_reg(Register::XOutLow).await?) as i16;
143-
Ok(accx)
151+
let mut accx_bytes: [u8; 2] = [0; 2];
152+
self.read_regs(Register::XOutLow, &mut accx_bytes).await?;
153+
Ok(i16::from_le_bytes(accx_bytes))
144154
}
145155

146156
/// Reads the device acceleration register in the Y axis
147157
pub async fn acc_y(&mut self) -> Result<i16, I2C::Error> {
148-
let mut accy: i16 = 0;
149-
accy += ((self.read_reg(Register::YOutHigh).await?) as i16) << 8;
150-
accy += (self.read_reg(Register::YOutLow).await?) as i16;
151-
Ok(accy)
158+
let mut accy_bytes: [u8; 2] = [0; 2];
159+
self.read_regs(Register::YOutLow, &mut accy_bytes).await?;
160+
Ok(i16::from_le_bytes(accy_bytes))
152161
}
153162

154163
/// Reads the device acceleration register in the Z axis
155164
pub async fn acc_z(&mut self) -> Result<i16, I2C::Error> {
156-
let mut accz: i16 = 0;
157-
accz += ((self.read_reg(Register::ZOutHigh).await?) as i16) << 8;
158-
accz += (self.read_reg(Register::ZOutLow).await?) as i16;
159-
Ok(accz)
165+
let mut accz_bytes: [u8; 2] = [0; 2];
166+
self.read_regs(Register::ZOutLow, &mut accz_bytes).await?;
167+
Ok(i16::from_le_bytes(accz_bytes))
160168
}
161169

162170
/// Reads the 3D device acceleration from registers
163171
pub async fn acc(&mut self) -> Result<(i16, i16, i16), I2C::Error> {
164-
Ok((self.acc_x().await?, self.acc_y().await?, self.acc_z().await?))
172+
let mut acc_bytes: [u8; 6] = [0; 6];
173+
self.read_regs(Register::XOutLow, &mut acc_bytes).await?;
174+
Ok((
175+
i16::from_le_bytes(acc_bytes[0..2].try_into().unwrap()),
176+
i16::from_le_bytes(acc_bytes[2..4].try_into().unwrap()),
177+
i16::from_le_bytes(acc_bytes[4..6].try_into().unwrap()),
178+
))
165179
}
166180

167181
/// Returns the 3D device acceleration in Gs
@@ -251,8 +265,15 @@ impl<I2C: embedded_hal_async::i2c::I2c> Lis2dw12<I2C> {
251265

252266
/// Returns free fall duration by stitching FF_DUR5 from WAKE_UP_DUR register onto FF register output
253267
pub async fn free_fall_duration(&mut self) -> Result<u8, I2C::Error> {
254-
let ff_reg: FreeFallReg = self.read_reg(Register::FreeFall).await?.into();
255-
let wu_reg: WakeUpDurationReg = self.read_reg(Register::WakeUpDuration).await?.into();
268+
let mut regs: [u8; 2] = [0; 2];
269+
self.read_regs(Register::WakeUpDuration, &mut regs).await?;
270+
271+
// WakeUpDuration = 0x35
272+
let wu_reg: WakeUpDurationReg = regs[0].into();
273+
274+
// FreeFall = 0x36
275+
let ff_reg: FreeFallReg = regs[1].into();
276+
256277
let ff_dur: u8 = u8::from(ff_reg.ff_dur()) + (u8::from(wu_reg.ff_dur5()) << 5);
257278
Ok(ff_dur)
258279
}
@@ -320,12 +341,13 @@ mod tests {
320341
#[tokio::test]
321342
async fn test_ff_dur() {
322343
let ff_dur_expected: u8 = 0b010100;
323-
let ff_reg: [u8; 1] = [0b10100101];
324-
let wud_reg: [u8; 1] = [0b01011010];
325-
let expectations = vec![
326-
Transaction::write_read(SA0_GND_ADDR, vec![Register::FreeFall as u8], vec![ff_reg[0]]),
327-
Transaction::write_read(SA0_GND_ADDR, vec![Register::WakeUpDuration as u8], vec![wud_reg[0]]),
328-
];
344+
let wud_reg: u8 = 0b01011010; // Wake Up Duration: 0x35
345+
let ff_reg: u8 = 0b10100101; // Free Fall: 0x36
346+
let expectations = vec![Transaction::write_read(
347+
SA0_GND_ADDR,
348+
vec![Register::WakeUpDuration as u8],
349+
vec![wud_reg, ff_reg],
350+
)];
329351
let i2c = Mock::new(&expectations);
330352
let mut accel = Lis2dw12::new_with_sa0_gnd(i2c);
331353
let ff_dur: u8 = accel.free_fall_duration().await.unwrap();

0 commit comments

Comments
 (0)