• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

eldruin / lsm303agr-rs / 9599194769

20 Jun 2024 02:21PM UTC coverage: 86.275% (+0.08%) from 86.196%
9599194769

Pull #31

github

web-flow
Merge c444d3f43 into 322cb031a
Pull Request #31: implement embedded-hal-async traits using maybe-async-cfg

102 of 111 new or added lines in 5 files covered. (91.89%)

4 existing lines in 2 files now uncovered.

528 of 612 relevant lines covered (86.27%)

2.7 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

91.18
/src/interface.rs
1
//! I2C/SPI interfaces
2

3
#[cfg(not(feature = "async"))]
4
use embedded_hal::{i2c, spi};
5
#[cfg(feature = "async")]
6
use embedded_hal_async::{i2c, spi};
7
use maybe_async_cfg::maybe;
8

9
use crate::{
10
    private,
11
    register_address::{RegRead, RegWrite},
12
    Error,
13
};
14

15
pub(crate) const ACCEL_ADDR: u8 = 0b001_1001;
16
pub(crate) const MAG_ADDR: u8 = 0b001_1110;
17

18
/// I2C interface
19
#[derive(Debug)]
20
pub struct I2cInterface<I2C> {
21
    pub(crate) i2c: I2C,
22
}
23

24
/// SPI interface
25
#[derive(Debug)]
26
pub struct SpiInterface<SPIXL, SPIMAG> {
27
    pub(crate) spi_xl: SPIXL,
28
    pub(crate) spi_mag: SPIMAG,
29
}
30

31
/// Write data
32
#[maybe(
33
    sync(
34
        cfg(not(feature = "async")),
35
        keep_self,
36
    ),
37
    async (
38
        cfg(feature = "async"),
39
        keep_self,
40
    )
41
)]
42
pub trait WriteData: private::Sealed {
43
    /// Error type
44
    type Error;
45

46
    /// Write to an u8 accelerometer register
47
    async fn write_accel_register<R: RegWrite>(&mut self, reg: R) -> Result<(), Self::Error>;
48

49
    /// Write to an u8 magnetometer register
50
    async fn write_mag_register<R: RegWrite>(&mut self, reg: R) -> Result<(), Self::Error>;
51
}
52

53
#[maybe(
54
    sync(
55
        cfg(not(feature = "async")),
56
        keep_self,
57
    ),
58
    async (
59
        cfg(feature = "async"),
60
        keep_self,
61
    )
62
)]
63
impl<I2C, E> WriteData for I2cInterface<I2C>
64
where
65
    I2C: i2c::I2c<Error = E>,
66
{
67
    type Error = Error<E>;
68

69
    async fn write_accel_register<R: RegWrite>(&mut self, reg: R) -> Result<(), Self::Error> {
11✔
70
        let payload: [u8; 2] = [R::ADDR, reg.data()];
22✔
71
        self.i2c.write(ACCEL_ADDR, &payload).await.map_err(Error::Comm)
11✔
72
    }
73

74
    async fn write_mag_register<R: RegWrite>(&mut self, reg: R) -> Result<(), Self::Error> {
4✔
75
        let payload: [u8; 2] = [R::ADDR, reg.data()];
8✔
76
        self.i2c.write(MAG_ADDR, &payload).await.map_err(Error::Comm)
4✔
77
    }
78
}
79

80
#[maybe(
81
    sync(
82
        cfg(not(feature = "async")),
83
        keep_self,
84
    ),
85
    async (
86
        cfg(feature = "async"),
87
        keep_self,
88
    )
89
)]
90
impl<SPIXL, SPIMAG, CommE> WriteData for SpiInterface<SPIXL, SPIMAG>
91
where
92
    SPIXL: spi::SpiDevice<u8, Error = CommE>,
93
    SPIMAG: spi::SpiDevice<u8, Error = CommE>,
94
{
95
    type Error = Error<CommE>;
96

97
    async fn write_accel_register<R: RegWrite>(&mut self, reg: R) -> Result<(), Self::Error> {
6✔
98
        // note that multiple byte writing needs to set the MS bit
99
        let payload: [u8; 2] = [R::ADDR, reg.data()];
12✔
100
        self.spi_xl.write(&payload).await.map_err(Error::Comm)
6✔
101
    }
102

103
    async fn write_mag_register<R: RegWrite>(&mut self, reg: R) -> Result<(), Self::Error> {
2✔
104
        // note that multiple byte writing needs to set the MS bit
105
        let payload: [u8; 2] = [R::ADDR, reg.data()];
4✔
106
        self.spi_mag.write(&payload).await.map_err(Error::Comm)
2✔
107
    }
108
}
109

110
/// Read data
111
#[maybe(
112
    sync(
113
        cfg(not(feature = "async")),
114
        keep_self,
115
    ),
116
    async (
117
        cfg(feature = "async"),
118
        keep_self,
119
    )
120
)]
121
pub trait ReadData: private::Sealed {
122
    /// Error type
123
    type Error;
124

125
    /// Read an u8 accelerometer register
126
    async fn read_accel_register<R: RegRead>(&mut self) -> Result<R::Output, Self::Error>;
127

128
    /// Read an u8 magnetometer register
129
    async fn read_mag_register<R: RegRead>(&mut self) -> Result<R::Output, Self::Error>;
130

131
    /// Read an u16 accelerometer register
132
    async fn read_accel_double_register<R: RegRead<u16>>(&mut self) -> Result<R::Output, Self::Error>;
133

134
    /// Read 3 u16 accelerometer registers
135
    async fn read_accel_3_double_registers<R: RegRead<(u16, u16, u16)>>(
136
        &mut self,
137
    ) -> Result<R::Output, Self::Error>;
138

139
    /// Read 3 u16 magnetometer registers
140
    async fn read_mag_3_double_registers<R: RegRead<(u16, u16, u16)>>(
141
        &mut self,
142
    ) -> Result<R::Output, Self::Error>;
143
}
144

145
#[maybe(
146
    sync(
147
        cfg(not(feature = "async")),
148
        keep_self,
149
    ),
150
    async (
151
        cfg(feature = "async"),
152
        keep_self,
153
    )
154
)]
155
impl<I2C, E> ReadData for I2cInterface<I2C>
156
where
157
    I2C: i2c::I2c<Error = E>,
158
{
159
    type Error = Error<E>;
160

161
    async fn read_accel_register<R: RegRead>(&mut self) -> Result<R::Output, Self::Error> {
3✔
162
        self.read_register::<R>(ACCEL_ADDR).await
3✔
163
    }
164

165
    async fn read_mag_register<R: RegRead>(&mut self) -> Result<R::Output, Self::Error> {
4✔
166
        self.read_register::<R>(MAG_ADDR).await
4✔
167
    }
168

169
    async fn read_accel_double_register<R: RegRead<u16>>(&mut self) -> Result<R::Output, Self::Error> {
1✔
170
        self.read_double_register::<R>(ACCEL_ADDR).await
1✔
171
    }
172

173
    async fn read_accel_3_double_registers<R: RegRead<(u16, u16, u16)>>(
1✔
174
        &mut self,
175
    ) -> Result<R::Output, Self::Error> {
176
        self.read_3_double_registers::<R>(ACCEL_ADDR).await
1✔
177
    }
178

179
    async fn read_mag_3_double_registers<R: RegRead<(u16, u16, u16)>>(
1✔
180
        &mut self,
181
    ) -> Result<R::Output, Self::Error> {
182
        self.read_3_double_registers::<R>(MAG_ADDR).await
1✔
183
    }
184
}
185

186
#[maybe(
187
    sync(
188
        cfg(not(feature = "async")),
189
        keep_self,
190
    ),
191
    async (
192
        cfg(feature = "async"),
193
        keep_self,
194
    )
195
)]
196
impl<I2C, E> I2cInterface<I2C>
197
where
198
    I2C: i2c::I2c<Error = E>,
199
{
200
    async fn read_register<R: RegRead>(&mut self, address: u8) -> Result<R::Output, Error<E>> {
7✔
201
        let mut data = [0];
7✔
202
        self.i2c
14✔
NEW
203
            .write_read(address, &[R::ADDR], &mut data).await
×
204
            .map_err(Error::Comm)?;
×
205

206
        Ok(R::from_data(data[0]))
7✔
207
    }
208

209
    async fn read_double_register<R: RegRead<u16>>(
1✔
210
        &mut self,
211
        address: u8,
212
    ) -> Result<R::Output, Error<E>> {
213
        let mut data = [0; 2];
1✔
214
        self.i2c
2✔
NEW
215
            .write_read(address, &[R::ADDR | 0x80], &mut data).await
×
216
            .map_err(Error::Comm)?;
×
217

218
        Ok(R::from_data(u16::from_le_bytes(data)))
1✔
219
    }
220

221
    async fn read_3_double_registers<R: RegRead<(u16, u16, u16)>>(
2✔
222
        &mut self,
223
        address: u8,
224
    ) -> Result<R::Output, Error<E>> {
225
        let mut data = [0; 6];
2✔
226
        self.i2c
4✔
NEW
227
            .write_read(address, &[R::ADDR | 0x80], &mut data).await
×
228
            .map_err(Error::Comm)?;
×
229

230
        Ok(R::from_data((
4✔
231
            u16::from_le_bytes([data[0], data[1]]),
2✔
232
            u16::from_le_bytes([data[2], data[3]]),
2✔
233
            u16::from_le_bytes([data[4], data[5]]),
2✔
234
        )))
235
    }
236
}
237

238
#[maybe(
239
    sync(
240
        cfg(not(feature = "async")),
241
        keep_self,
242
    ),
243
    async (
244
        cfg(feature = "async"),
245
        keep_self,
246
    )
247
)]
248
impl<SPIXL, SPIMAG, CommE> ReadData for SpiInterface<SPIXL, SPIMAG>
249
where
250
    SPIXL: spi::SpiDevice<u8, Error = CommE>,
251
    SPIMAG: spi::SpiDevice<u8, Error = CommE>,
252
{
253
    type Error = Error<CommE>;
254

255
    async fn read_accel_register<R: RegRead>(&mut self) -> Result<R::Output, Self::Error> {
1✔
256
        spi_read_register::<R, _, _>(&mut self.spi_xl).await
1✔
257
    }
258

259
    async fn read_mag_register<R: RegRead>(&mut self) -> Result<R::Output, Self::Error> {
1✔
260
        spi_read_register::<R, _, _>(&mut self.spi_mag).await
1✔
261
    }
262

263
    async fn read_accel_double_register<R: RegRead<u16>>(&mut self) -> Result<R::Output, Self::Error> {
1✔
264
        spi_read_double_register::<R, _, _>(&mut self.spi_xl).await
1✔
265
    }
266

267
    async fn read_accel_3_double_registers<R: RegRead<(u16, u16, u16)>>(
1✔
268
        &mut self,
269
    ) -> Result<R::Output, Self::Error> {
270
        spi_read_3_double_registers::<R, _, _>(&mut self.spi_xl).await
1✔
271
    }
272

273
    async fn read_mag_3_double_registers<R: RegRead<(u16, u16, u16)>>(
1✔
274
        &mut self,
275
    ) -> Result<R::Output, Self::Error> {
276
        spi_read_3_double_registers::<R, _, _>(&mut self.spi_mag).await
1✔
277
    }
278
}
279

280
const SPI_RW: u8 = 1 << 7;
281
const SPI_MS: u8 = 1 << 6;
282

283
#[maybe(
284
    sync(
285
        cfg(not(feature = "async")),
286
        keep_self,
287
    ),
288
    async (
289
        cfg(feature = "async"),
290
        keep_self,
291
    )
292
)]
293
async fn spi_read_register<R: RegRead, SPI: spi::SpiDevice<u8, Error = CommE>, CommE>(
2✔
294
    spi: &mut SPI,
295
) -> Result<R::Output, Error<CommE>> {
296
    let mut data = [SPI_RW | R::ADDR, 0];
2✔
297
    spi.transfer_in_place(&mut data).await.map_err(Error::Comm)?;
4✔
298

299
    Ok(R::from_data(data[1]))
2✔
300
}
301

302
#[maybe(
303
    sync(
304
        cfg(not(feature = "async")),
305
        keep_self,
306
    ),
307
    async (
308
        cfg(feature = "async"),
309
        keep_self,
310
    )
311
)]
312
async fn spi_read_double_register<R: RegRead<u16>, SPI: spi::SpiDevice<u8, Error = CommE>, CommE>(
1✔
313
    spi: &mut SPI,
314
) -> Result<R::Output, Error<CommE>> {
315
    let mut data = [SPI_RW | SPI_MS | R::ADDR, 0, 0];
1✔
316
    spi.transfer_in_place(&mut data).await.map_err(Error::Comm)?;
2✔
317

318
    Ok(R::from_data(u16::from_le_bytes([data[1], data[2]])))
1✔
319
}
320

321
#[maybe(
322
    sync(
323
        cfg(not(feature = "async")),
324
        keep_self,
325
    ),
326
    async (
327
        cfg(feature = "async"),
328
        keep_self,
329
    )
330
)]
331
async fn spi_read_3_double_registers<
2✔
332
    R: RegRead<(u16, u16, u16)>,
333
    SPI: spi::SpiDevice<u8, Error = CommE>,
334
    CommE,
335
>(
336
    spi: &mut SPI,
337
) -> Result<R::Output, Error<CommE>> {
338
    let mut data = [SPI_RW | SPI_MS | R::ADDR, 0, 0, 0, 0, 0, 0];
2✔
339
    spi.transfer_in_place(&mut data).await.map_err(Error::Comm)?;
4✔
340

341
    Ok(R::from_data((
4✔
342
        u16::from_le_bytes([data[1], data[2]]),
2✔
343
        u16::from_le_bytes([data[3], data[4]]),
2✔
344
        u16::from_le_bytes([data[5], data[6]]),
2✔
345
    )))
346
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc