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

eldruin / lsm303agr-rs / 9613401698

21 Jun 2024 12:12PM UTC coverage: 82.582% (-3.6%) from 86.196%
9613401698

Pull #31

github

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

104 of 138 new or added lines in 5 files covered. (75.36%)

7 existing lines in 3 files now uncovered.

531 of 643 relevant lines covered (82.58%)

2.58 hits per line

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

74.7
/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(cfg(not(feature = "async")), keep_self,),
34
    async(cfg(feature = "async"), keep_self,)
35
)]
36
pub trait WriteData: private::Sealed {
37
    /// Error type
38
    type Error;
39

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

43
    /// Write to an u8 magnetometer register
44
    async fn write_mag_register<R: RegWrite>(&mut self, reg: R) -> Result<(), Self::Error>;
45
}
46

47
#[maybe(
48
    sync(cfg(not(feature = "async")), keep_self,),
49
    async(cfg(feature = "async"), keep_self,)
50
)]
51
impl<I2C, E> WriteData for I2cInterface<I2C>
52
where
53
    I2C: i2c::I2c<Error = E>,
54
{
55
    type Error = Error<E>;
56

57
    async fn write_accel_register<R: RegWrite>(&mut self, reg: R) -> Result<(), Self::Error> {
11✔
58
        let payload: [u8; 2] = [R::ADDR, reg.data()];
22✔
59
        self.i2c
11✔
NEW
60
            .write(ACCEL_ADDR, &payload)
×
NEW
61
            .await
×
NEW
62
            .map_err(Error::Comm)
×
63
    }
64

65
    async fn write_mag_register<R: RegWrite>(&mut self, reg: R) -> Result<(), Self::Error> {
4✔
66
        let payload: [u8; 2] = [R::ADDR, reg.data()];
8✔
67
        self.i2c
4✔
NEW
68
            .write(MAG_ADDR, &payload)
×
NEW
69
            .await
×
NEW
70
            .map_err(Error::Comm)
×
71
    }
72
}
73

74
#[maybe(
75
    sync(cfg(not(feature = "async")), keep_self,),
76
    async(cfg(feature = "async"), keep_self,)
77
)]
78
impl<SPIXL, SPIMAG, CommE> WriteData for SpiInterface<SPIXL, SPIMAG>
79
where
80
    SPIXL: spi::SpiDevice<u8, Error = CommE>,
81
    SPIMAG: spi::SpiDevice<u8, Error = CommE>,
82
{
83
    type Error = Error<CommE>;
84

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

91
    async fn write_mag_register<R: RegWrite>(&mut self, reg: R) -> Result<(), Self::Error> {
2✔
92
        // note that multiple byte writing needs to set the MS bit
93
        let payload: [u8; 2] = [R::ADDR, reg.data()];
4✔
94
        self.spi_mag.write(&payload).await.map_err(Error::Comm)
2✔
95
    }
96
}
97

98
/// Read data
99
#[maybe(
100
    sync(cfg(not(feature = "async")), keep_self,),
101
    async(cfg(feature = "async"), keep_self,)
102
)]
103
pub trait ReadData: private::Sealed {
104
    /// Error type
105
    type Error;
106

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

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

113
    /// Read an u16 accelerometer register
114
    async fn read_accel_double_register<R: RegRead<u16>>(
115
        &mut self,
116
    ) -> Result<R::Output, Self::Error>;
117

118
    /// Read 3 u16 accelerometer registers
119
    async fn read_accel_3_double_registers<R: RegRead<(u16, u16, u16)>>(
120
        &mut self,
121
    ) -> Result<R::Output, Self::Error>;
122

123
    /// Read 3 u16 magnetometer registers
124
    async fn read_mag_3_double_registers<R: RegRead<(u16, u16, u16)>>(
125
        &mut self,
126
    ) -> Result<R::Output, Self::Error>;
127
}
128

129
#[maybe(
130
    sync(cfg(not(feature = "async")), keep_self,),
131
    async(cfg(feature = "async"), keep_self,)
132
)]
133
impl<I2C, E> ReadData for I2cInterface<I2C>
134
where
135
    I2C: i2c::I2c<Error = E>,
136
{
137
    type Error = Error<E>;
138

139
    async fn read_accel_register<R: RegRead>(&mut self) -> Result<R::Output, Self::Error> {
3✔
140
        self.read_register::<R>(ACCEL_ADDR).await
3✔
141
    }
142

143
    async fn read_mag_register<R: RegRead>(&mut self) -> Result<R::Output, Self::Error> {
4✔
144
        self.read_register::<R>(MAG_ADDR).await
4✔
145
    }
146

147
    async fn read_accel_double_register<R: RegRead<u16>>(
1✔
148
        &mut self,
149
    ) -> Result<R::Output, Self::Error> {
150
        self.read_double_register::<R>(ACCEL_ADDR).await
1✔
151
    }
152

153
    async fn read_accel_3_double_registers<R: RegRead<(u16, u16, u16)>>(
1✔
154
        &mut self,
155
    ) -> Result<R::Output, Self::Error> {
156
        self.read_3_double_registers::<R>(ACCEL_ADDR).await
1✔
157
    }
158

159
    async fn read_mag_3_double_registers<R: RegRead<(u16, u16, u16)>>(
1✔
160
        &mut self,
161
    ) -> Result<R::Output, Self::Error> {
162
        self.read_3_double_registers::<R>(MAG_ADDR).await
1✔
163
    }
164
}
165

166
#[maybe(
167
    sync(cfg(not(feature = "async")), keep_self,),
168
    async(cfg(feature = "async"), keep_self,)
169
)]
170
impl<I2C, E> I2cInterface<I2C>
171
where
172
    I2C: i2c::I2c<Error = E>,
173
{
174
    async fn read_register<R: RegRead>(&mut self, address: u8) -> Result<R::Output, Error<E>> {
7✔
175
        let mut data = [0];
7✔
176
        self.i2c
14✔
177
            .write_read(address, &[R::ADDR], &mut data)
×
NEW
178
            .await
×
UNCOV
179
            .map_err(Error::Comm)?;
×
180

181
        Ok(R::from_data(data[0]))
7✔
182
    }
183

184
    async fn read_double_register<R: RegRead<u16>>(
1✔
185
        &mut self,
186
        address: u8,
187
    ) -> Result<R::Output, Error<E>> {
188
        let mut data = [0; 2];
1✔
189
        self.i2c
2✔
190
            .write_read(address, &[R::ADDR | 0x80], &mut data)
×
NEW
191
            .await
×
UNCOV
192
            .map_err(Error::Comm)?;
×
193

194
        Ok(R::from_data(u16::from_le_bytes(data)))
1✔
195
    }
196

197
    async fn read_3_double_registers<R: RegRead<(u16, u16, u16)>>(
2✔
198
        &mut self,
199
        address: u8,
200
    ) -> Result<R::Output, Error<E>> {
201
        let mut data = [0; 6];
2✔
202
        self.i2c
4✔
203
            .write_read(address, &[R::ADDR | 0x80], &mut data)
×
NEW
204
            .await
×
UNCOV
205
            .map_err(Error::Comm)?;
×
206

207
        Ok(R::from_data((
4✔
208
            u16::from_le_bytes([data[0], data[1]]),
2✔
209
            u16::from_le_bytes([data[2], data[3]]),
2✔
210
            u16::from_le_bytes([data[4], data[5]]),
2✔
211
        )))
212
    }
213
}
214

215
#[maybe(
216
    sync(cfg(not(feature = "async")), keep_self,),
217
    async(cfg(feature = "async"), keep_self,)
218
)]
219
impl<SPIXL, SPIMAG, CommE> ReadData for SpiInterface<SPIXL, SPIMAG>
220
where
221
    SPIXL: spi::SpiDevice<u8, Error = CommE>,
222
    SPIMAG: spi::SpiDevice<u8, Error = CommE>,
223
{
224
    type Error = Error<CommE>;
225

226
    async fn read_accel_register<R: RegRead>(&mut self) -> Result<R::Output, Self::Error> {
1✔
227
        spi_read_register::<R, _, _>(&mut self.spi_xl).await
1✔
228
    }
229

230
    async fn read_mag_register<R: RegRead>(&mut self) -> Result<R::Output, Self::Error> {
1✔
231
        spi_read_register::<R, _, _>(&mut self.spi_mag).await
1✔
232
    }
233

234
    async fn read_accel_double_register<R: RegRead<u16>>(
1✔
235
        &mut self,
236
    ) -> Result<R::Output, Self::Error> {
237
        spi_read_double_register::<R, _, _>(&mut self.spi_xl).await
1✔
238
    }
239

240
    async fn read_accel_3_double_registers<R: RegRead<(u16, u16, u16)>>(
1✔
241
        &mut self,
242
    ) -> Result<R::Output, Self::Error> {
243
        spi_read_3_double_registers::<R, _, _>(&mut self.spi_xl).await
1✔
244
    }
245

246
    async fn read_mag_3_double_registers<R: RegRead<(u16, u16, u16)>>(
1✔
247
        &mut self,
248
    ) -> Result<R::Output, Self::Error> {
249
        spi_read_3_double_registers::<R, _, _>(&mut self.spi_mag).await
1✔
250
    }
251
}
252

253
const SPI_RW: u8 = 1 << 7;
254
const SPI_MS: u8 = 1 << 6;
255

256
#[maybe(
257
    sync(cfg(not(feature = "async")), keep_self,),
258
    async(cfg(feature = "async"), keep_self,)
259
)]
260
async fn spi_read_register<R: RegRead, SPI: spi::SpiDevice<u8, Error = CommE>, CommE>(
2✔
261
    spi: &mut SPI,
262
) -> Result<R::Output, Error<CommE>> {
263
    let mut data = [SPI_RW | R::ADDR, 0];
2✔
264
    spi.transfer_in_place(&mut data)
4✔
NEW
265
        .await
×
NEW
266
        .map_err(Error::Comm)?;
×
267

268
    Ok(R::from_data(data[1]))
2✔
269
}
270

271
#[maybe(
272
    sync(cfg(not(feature = "async")), keep_self,),
273
    async(cfg(feature = "async"), keep_self,)
274
)]
275
async fn spi_read_double_register<
1✔
276
    R: RegRead<u16>,
277
    SPI: spi::SpiDevice<u8, Error = CommE>,
278
    CommE,
279
>(
280
    spi: &mut SPI,
281
) -> Result<R::Output, Error<CommE>> {
282
    let mut data = [SPI_RW | SPI_MS | R::ADDR, 0, 0];
1✔
283
    spi.transfer_in_place(&mut data)
2✔
NEW
284
        .await
×
NEW
285
        .map_err(Error::Comm)?;
×
286

287
    Ok(R::from_data(u16::from_le_bytes([data[1], data[2]])))
1✔
288
}
289

290
#[maybe(
291
    sync(cfg(not(feature = "async")), keep_self,),
292
    async(cfg(feature = "async"), keep_self,)
293
)]
294
async fn spi_read_3_double_registers<
2✔
295
    R: RegRead<(u16, u16, u16)>,
296
    SPI: spi::SpiDevice<u8, Error = CommE>,
297
    CommE,
298
>(
299
    spi: &mut SPI,
300
) -> Result<R::Output, Error<CommE>> {
301
    let mut data = [SPI_RW | SPI_MS | R::ADDR, 0, 0, 0, 0, 0, 0];
2✔
302
    spi.transfer_in_place(&mut data)
4✔
NEW
303
        .await
×
NEW
304
        .map_err(Error::Comm)?;
×
305

306
    Ok(R::from_data((
4✔
307
        u16::from_le_bytes([data[1], data[2]]),
2✔
308
        u16::from_le_bytes([data[3], data[4]]),
2✔
309
        u16::from_le_bytes([data[5], data[6]]),
2✔
310
    )))
311
}
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