adi_adxl355/
lib.rs

1// Copyright © 2023 Analog Devices, Inc. All Rights Reserved. This software is
2// proprietary to Analog Devices, Inc. and its licensors.
3//
4// SPDX-License-Identifier: Apache-2.0
5//
6// Licensed under the Apache License, Version 2.0 (the "License");
7// you may not use this file except in compliance with the License.
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#![cfg_attr(not(feature = "std"), no_std)]
16#![doc = include_str!("../README.md")]
17
18pub mod config;
19pub mod interrupt;
20pub mod modes;
21pub mod register;
22pub mod status;
23
24pub use config::*;
25pub use interrupt::*;
26pub use modes::*;
27pub use register::*;
28pub use status::*;
29
30use embedded_hal::i2c::I2c;
31use embedded_hal::spi;
32use embedded_hal::spi::SpiDevice;
33use micromath::vector::{F32x3, I32x3};
34
35/// Device identification value for the ADXL355.
36pub const DEVICE_ID: u8 = 0xED;
37
38#[derive(Copy, Clone, Debug, Eq, PartialEq, Default)]
39#[cfg_attr(feature = "defmt", derive(defmt::Format))]
40#[repr(u8)]
41/// Device address when using I2C protocol depending on the state of the ASEL pin.
42pub enum DeviceI2cAddress {
43    #[default]
44    /// Device address with ASEL pin low
45    AselPinLow = 0x1D,
46    /// Device address with ASEL pin high
47    AselPinHigh = 0x53,
48}
49
50/// ADXL355 driver.
51pub struct Adxl355<PROTOCOL: Protocol> {
52    pub protocol: PROTOCOL,
53    shadow_values: [u8; 5],
54    range_scale_factor: f32,
55}
56
57impl<SPI> Adxl355<SpiProtocol<SPI>>
58where
59    SPI: SpiDevice,
60{
61    /// Create a new ADXL355 driver from given SPI peripheral in unknown state.
62    pub fn new_spi(spi: SPI) -> Result<Self, Error<SPI::Error>> {
63        let mut adxl355 = Adxl355 {
64            protocol: SpiProtocol { spi },
65            shadow_values: [0; 5],
66            range_scale_factor: 0.0,
67        };
68        let dev_id = adxl355.get_device_id()?;
69        if dev_id != DEVICE_ID {
70            return Err(Error::BadDeviceId(dev_id));
71        }
72        adxl355.init_shadow_values()?;
73        adxl355.range_scale_factor = adxl355.get_range()?.scale_factor();
74        Ok(adxl355)
75    }
76
77    /// Create a new ADXL355 driver from given SPI peripheral in the given config.
78    /// The ADXL355 is reset before the config is applied to make sure it is in standby mode.
79    pub fn new_spi_with_config(spi: SPI, config: Config) -> Result<Self, Error<SPI::Error>> {
80        let mut adxl355 = Self::new_spi(spi)?;
81        adxl355.configure(config)?;
82        Ok(adxl355)
83    }
84}
85
86impl<I2C> Adxl355<I2cProtocol<I2C>>
87where
88    I2C: I2c,
89{
90    /// Create a new ADXL355 driver from given I2C peripheral in unknown state.
91    pub fn new_i2c(i2c: I2C, address: DeviceI2cAddress) -> Result<Self, Error<I2C::Error>> {
92        let mut adxl355 = Adxl355 {
93            protocol: I2cProtocol {
94                i2c,
95                address: address as u8,
96            },
97            shadow_values: [0; 5],
98            range_scale_factor: 0.0,
99        };
100        let dev_id = adxl355.get_device_id()?;
101        if dev_id != DEVICE_ID {
102            return Err(Error::BadDeviceId(dev_id));
103        }
104        adxl355.init_shadow_values()?;
105        adxl355.range_scale_factor = adxl355.get_range()?.scale_factor();
106        Ok(adxl355)
107    }
108
109    /// Create a new ADXL355 driver from given I2C peripheral in the given config.
110    /// The ADXL355 is reset before the config is applied to make sure it is in standby mode.
111    pub fn new_i2c_with_config(
112        i2c: I2C,
113        address: DeviceI2cAddress,
114        config: Config,
115    ) -> Result<Self, Error<I2C::Error>> {
116        let mut adxl355 = Self::new_i2c(i2c, address)?;
117        adxl355.configure(config)?;
118        Ok(adxl355)
119    }
120}
121
122impl<PROTOCOL> Adxl355<PROTOCOL>
123where
124    PROTOCOL: Protocol,
125{
126    /// Configure the ADXL355.
127    /// The ADXL355 is reset before the config is applied to make sure it is in standby mode.
128    pub fn configure(&mut self, config: Config) -> Result<(), Error<PROTOCOL::ProtocolError>> {
129        self.reset()?;
130
131        let mode = self.get_mode()?;
132
133        if !mode.is_in_standby() {
134            return Err(Error::DeviceRunning);
135        }
136
137        self.protocol
138            .write_register(Register::FILTER, (config.hpf.val() << 4) | config.odr.val())?;
139        let mut range_register_value = self.protocol.read_register(Register::RANGE)?;
140        range_register_value |= config.range.val();
141        self.protocol
142            .write_register(Register::RANGE, range_register_value)?;
143        self.range_scale_factor = config.range.scale_factor();
144
145        Ok(())
146    }
147
148    /// Get device [`Status`]
149    pub fn get_status(&mut self) -> Result<Status, Error<PROTOCOL::ProtocolError>> {
150        let status_val = self.protocol.read_register(Register::STATUS)?;
151        Ok(Status(status_val))
152    }
153
154    /// Get the device ID, `0xED` is expected.
155    pub fn get_device_id(&mut self) -> Result<u8, Error<PROTOCOL::ProtocolError>> {
156        self.protocol.read_register(Register::PARTID)
157    }
158
159    /// Get the product revision ID.
160    pub fn get_revision_id(&mut self) -> Result<u8, Error<PROTOCOL::ProtocolError>> {
161        self.protocol.read_register(Register::REVID)
162    }
163
164    /// Reset the device and make sure the NVM is loaded correctly.
165    pub fn reset(&mut self) -> Result<(), Error<PROTOCOL::ProtocolError>> {
166        self.protocol.write_register(Register::RESET, 0x52)?;
167
168        let mut nb_of_retries = 255;
169        let mut nvm_busy = self.get_status()?.is_nvm_busy();
170
171        while nvm_busy && nb_of_retries > 0 {
172            nvm_busy = self.get_status()?.is_nvm_busy();
173            nb_of_retries -= 1;
174        }
175
176        if nb_of_retries == 0 || nvm_busy {
177            return Err(Error::SoftResetFailed);
178        }
179
180        let shadow_values = self.get_shadow_values()?;
181
182        if self.shadow_values == shadow_values {
183            Ok(())
184        } else {
185            Err(Error::SoftResetFailed)
186        }
187    }
188
189    /// Get the current [`Mode`] of the device.
190    pub fn get_mode(&mut self) -> Result<Mode, Error<PROTOCOL::ProtocolError>> {
191        self.protocol.read_register(Register::POWER_CTL).map(Mode)
192    }
193
194    /// Set the [`Mode`] of the device.
195    pub fn set_mode(&mut self, mode: Mode) -> Result<(), Error<PROTOCOL::ProtocolError>> {
196        self.protocol.write_register(Register::POWER_CTL, mode.0)
197    }
198
199    /// Get the current [`Range`] of the device.
200    pub fn get_range(&mut self) -> Result<Range, Error<PROTOCOL::ProtocolError>> {
201        self.protocol
202            .read_register(Register::RANGE)
203            .map(Range::from)
204    }
205
206    /// Get the current [`Odr`] of the device.
207    pub fn get_odr_lpf(&mut self) -> Result<Odr, Error<PROTOCOL::ProtocolError>> {
208        self.protocol.read_register(Register::FILTER).map(Odr::from)
209    }
210
211    /// Get the current [`HpfCorner`] of the device.
212    pub fn get_hpf_corner(&mut self) -> Result<HpfCorner, Error<PROTOCOL::ProtocolError>> {
213        self.protocol
214            .read_register(Register::FILTER)
215            .map(HpfCorner::from)
216    }
217
218    /// Get the current [`Config`] of the device.
219    pub fn get_config(&mut self) -> Result<Config, Error<PROTOCOL::ProtocolError>> {
220        let range = self.get_range()?;
221
222        let filter_val = self.protocol.read_register(Register::FILTER)?;
223        let odr = Odr::from(filter_val);
224        let hpf = HpfCorner::from(filter_val);
225
226        Ok(Config { range, odr, hpf })
227    }
228
229    /// Set device in measurement mode.
230    pub fn set_measurement_mode(&mut self) -> Result<(), Error<PROTOCOL::ProtocolError>> {
231        let mode = self.protocol.read_register(Register::POWER_CTL)?;
232        self.protocol
233            .write_register(Register::POWER_CTL, mode & !Mode::STANDBY_BIT)
234    }
235
236    /// Set device in standby mode.
237    pub fn set_standby_mode(&mut self) -> Result<(), Error<PROTOCOL::ProtocolError>> {
238        let mode = self.protocol.read_register(Register::POWER_CTL)?;
239        self.protocol
240            .write_register(Register::POWER_CTL, mode | Mode::STANDBY_BIT)
241    }
242
243    /// Get raw temperature value.
244    pub fn get_temperature_raw(&mut self) -> Result<u16, Error<PROTOCOL::ProtocolError>> {
245        let mut buf: [u8; 2] = [0; 2];
246
247        self.protocol
248            .read_multiple_registers(Register::TEMP2, &mut buf)?;
249
250        Ok((((buf[0] & 0x0F) as u16) << 8) | ((buf[1] as u16) & 0xFF))
251    }
252
253    // Get temperature in Celsius.
254    pub fn get_temparature(&mut self) -> Result<f32, Error<PROTOCOL::ProtocolError>> {
255        let raw_temp = self.get_temperature_raw()?;
256        Ok(((((raw_temp as i32) - 1885i32) as f32) / (-9.05f32)) + 25.0f32)
257    }
258
259    /// Get raw acceleration values.
260    pub fn get_raw_accel_sample(&mut self) -> Result<I32x3, Error<PROTOCOL::ProtocolError>> {
261        let mut buf: [u8; 9] = [0; 9];
262        self.protocol
263            .read_multiple_registers(Register::XDATA3, &mut buf)?;
264
265        let mut sample = I32x3 { x: 0, y: 0, z: 0 };
266
267        Self::acc_buf_to_raw_sample(&buf, &mut sample);
268
269        Ok(sample)
270    }
271
272    /// Get acceleration values in g.
273    pub fn get_accel_sample(&mut self) -> Result<F32x3, Error<PROTOCOL::ProtocolError>> {
274        let mut buf: [u8; 9] = [0; 9];
275        self.protocol
276            .read_multiple_registers(Register::XDATA3, &mut buf)?;
277
278        let mut sample = F32x3 {
279            x: 0.0,
280            y: 0.0,
281            z: 0.0,
282        };
283
284        Self::acc_buf_to_sample(&buf, &mut sample, self.range_scale_factor);
285
286        Ok(sample)
287    }
288
289    /// Enable device self test feature.
290    pub fn start_self_test(&mut self) -> Result<(), Error<PROTOCOL::ProtocolError>> {
291        self.protocol.write_register(Register::SELF_TEST, 0x03)
292    }
293
294    /// Disable device self test feature.
295    pub fn stop_self_test(&mut self) -> Result<(), Error<PROTOCOL::ProtocolError>> {
296        self.protocol.write_register(Register::SELF_TEST, 0x00)
297    }
298
299    /// Apply offset trims for raw axis data after all other signal processing.
300    /// The offset trim value is removed from the axis data bits\[19:4\].
301    pub fn set_offset_trims(
302        &mut self,
303        offset_x: i16,
304        offset_y: i16,
305        offset_z: i16,
306    ) -> Result<(), Error<PROTOCOL::ProtocolError>> {
307        let mut buf = [
308            Register::OFFSET_X_H.addr(),
309            ((offset_x >> 8) & 0xFF) as u8,
310            ((offset_x) & 0xFF) as u8,
311            ((offset_y >> 8) & 0xFF) as u8,
312            ((offset_y) & 0xFF) as u8,
313            ((offset_z >> 8) & 0xFF) as u8,
314            ((offset_z) & 0xFF) as u8,
315        ];
316        self.protocol.write_multiple_registers(&mut buf)
317    }
318
319    /// Get the number of data samples stored in the FIFO
320    pub fn get_nb_samples_in_fifo(&mut self) -> Result<u8, Error<PROTOCOL::ProtocolError>> {
321        let nb_samples = self.protocol.read_register(Register::FIFO_ENTRIES)? & 0x7F;
322        Ok(nb_samples)
323    }
324
325    /// Set the maximum number of samples the fifo will store.
326    /// Value must range from 1 to 96.
327    pub fn set_nb_max_samples_in_fifo(
328        &mut self,
329        fifo_samples: u8,
330    ) -> Result<(), Error<PROTOCOL::ProtocolError>> {
331        if !(1..=96).contains(&fifo_samples) {
332            return Err(Error::InvalidMaxNbFifoSamples);
333        }
334
335        self.protocol
336            .write_register(Register::FIFO_SAMPLES, fifo_samples)
337    }
338
339    /// Get data from the fifo into provided array of raw accelerometer samples.
340    /// The return value indicates how many samples were retrieved.
341    pub fn get_fifo_raw_data(
342        &mut self,
343        data: &mut [I32x3],
344    ) -> Result<usize, Error<PROTOCOL::ProtocolError>> {
345        let mut nb_available_samples = self.get_nb_samples_in_fifo()?;
346        if nb_available_samples < 3 {
347            return Err(Error::NotEnoughData);
348        }
349        let data_len = data.len();
350        let mut nb_samples_retrieved: usize = 0;
351
352        let mut buf = [0u8; 9];
353        self.protocol
354            .read_multiple_registers(Register::FIFO_DATA, &mut buf[..3])?;
355        nb_available_samples -= 1;
356
357        // Make sure first value is from X axis
358        while buf[2] & 0x01 == 0 {
359            if nb_available_samples < 3 {
360                return Err(Error::NotEnoughData);
361            }
362
363            self.protocol
364                .read_multiple_registers(Register::FIFO_DATA, &mut buf[..3])?;
365            nb_available_samples -= 1;
366        }
367
368        self.protocol
369            .read_multiple_registers(Register::FIFO_DATA, &mut buf[3..])?;
370        nb_available_samples -= 2;
371
372        Self::acc_buf_to_raw_sample(&buf, &mut data[0]);
373        nb_samples_retrieved += 1;
374
375        while nb_available_samples >= 3 && data_len > nb_samples_retrieved {
376            self.protocol
377                .read_multiple_registers(Register::FIFO_DATA, &mut buf)?;
378            nb_available_samples -= 3;
379
380            Self::acc_buf_to_raw_sample(&buf, &mut data[nb_samples_retrieved]);
381            nb_samples_retrieved += 1;
382        }
383
384        Ok(nb_samples_retrieved)
385    }
386
387    /// Get data from the fifo into provided array of accelerometer samples in g.
388    /// The return value indicates how many samples were retrieved.
389    pub fn get_fifo_data(
390        &mut self,
391        data: &mut [F32x3],
392    ) -> Result<usize, Error<PROTOCOL::ProtocolError>> {
393        let mut nb_available_samples = self.get_nb_samples_in_fifo()?;
394        if nb_available_samples < 3 {
395            return Err(Error::NotEnoughData);
396        }
397        let data_len = data.len();
398        let mut nb_samples_retrieved: usize = 0;
399
400        let mut buf = [0u8; 9];
401        self.protocol
402            .read_multiple_registers(Register::FIFO_DATA, &mut buf[..3])?;
403        nb_available_samples -= 1;
404
405        // Make sure first value is from X axis
406        while buf[2] & 0x01 == 0 {
407            if nb_available_samples < 3 {
408                return Err(Error::NotEnoughData);
409            }
410
411            self.protocol
412                .read_multiple_registers(Register::FIFO_DATA, &mut buf[..3])?;
413            nb_available_samples -= 1;
414        }
415
416        self.protocol
417            .read_multiple_registers(Register::FIFO_DATA, &mut buf[3..])?;
418        nb_available_samples -= 2;
419
420        Self::acc_buf_to_sample(&buf, &mut data[0], self.range_scale_factor);
421        nb_samples_retrieved += 1;
422
423        while nb_available_samples >= 3 && data_len > nb_samples_retrieved {
424            self.protocol
425                .read_multiple_registers(Register::FIFO_DATA, &mut buf)?;
426            nb_available_samples -= 3;
427
428            Self::acc_buf_to_sample(
429                &buf,
430                &mut data[nb_samples_retrieved],
431                self.range_scale_factor,
432            );
433            nb_samples_retrieved += 1;
434        }
435
436        Ok(nb_samples_retrieved)
437    }
438
439    /// Enable activity detection for selected axes
440    pub fn enable_activity_detection(
441        &mut self,
442        x: bool,
443        y: bool,
444        z: bool,
445    ) -> Result<(), Error<PROTOCOL::ProtocolError>> {
446        let mut act_en = 0;
447        if x {
448            act_en += 0x01;
449        }
450        if y {
451            act_en += 0x02;
452        }
453        if z {
454            act_en += 0x04;
455        }
456
457        self.protocol.write_register(Register::ACT_EN, act_en)
458    }
459
460    /// Set threshold for activity detection. The acceleration magnitude must be greater
461    /// than the value in ACT_THRESH to trigger the activity counter.
462    /// The significance of the threshold matches the significance of Bits\[18:3\]
463    /// of the accelerometer's axes data.
464    pub fn set_activity_threshold(
465        &mut self,
466        threshold: u16,
467    ) -> Result<(), Error<PROTOCOL::ProtocolError>> {
468        self.protocol.write_multiple_registers(&mut [
469            Register::ACT_THRESH_H.addr(),
470            ((threshold >> 8) & 0xFF) as u8,
471            (threshold & 0xFF) as u8,
472        ])
473    }
474
475    /// Set number of consecutive events above threshold required to detect activity.
476    pub fn set_activity_count(&mut self, count: u8) -> Result<(), Error<PROTOCOL::ProtocolError>> {
477        self.protocol.write_register(Register::ACT_COUNT, count)
478    }
479
480    /// Configure interrupt pins INT1 and INT2.
481    pub fn configure_interrupt_pins(
482        &mut self,
483        conf: InterruptConfig,
484    ) -> Result<(), Error<PROTOCOL::ProtocolError>> {
485        self.protocol.write_register(Register::INT_MAP, conf.0)
486    }
487
488    /// Set interrupt pins polarity.
489    pub fn set_interrupt_polarity(
490        &mut self,
491        polarity: InterruptPolarity,
492    ) -> Result<(), Error<PROTOCOL::ProtocolError>> {
493        let mut buf = self.protocol.read_register(Register::RANGE)?;
494
495        match polarity {
496            InterruptPolarity::ActiveHigh => {
497                buf |= 0x40;
498            }
499            InterruptPolarity::ActiveLow => {
500                buf &= !0x40;
501            }
502        }
503
504        self.protocol.write_register(Register::RANGE, buf)
505    }
506
507    /// Set I2C speed mode.
508    pub fn set_i2c_speed(
509        &mut self,
510        mode: I2cSpeedMode,
511    ) -> Result<(), Error<PROTOCOL::ProtocolError>> {
512        let mut buf = self.protocol.read_register(Register::RANGE)?;
513
514        match mode {
515            I2cSpeedMode::HighSpeed => {
516                buf |= 0x80;
517            }
518            I2cSpeedMode::Fast => {
519                buf &= !0x80;
520            }
521        }
522
523        self.protocol.write_register(Register::RANGE, buf)
524    }
525
526    /// Set the synchronization mode the device will operate in. See options in [`ExternalSyncMode`].
527    pub fn set_synchronization_mode(
528        &mut self,
529        mode: ExternalSyncMode,
530    ) -> Result<(), Error<PROTOCOL::ProtocolError>> {
531        self.protocol.write_register(Register::SYNC, mode as u8)
532    }
533
534    /// Converts 9 bytes to raw acceleration sample.
535    fn acc_buf_to_raw_sample(buf: &[u8; 9], sample: &mut I32x3) {
536        sample.x =
537            (((buf[0] as i32) << 24) | ((buf[1] as i32) << 16) | ((buf[2] & 0xF0) as i32) << 8)
538                >> 12;
539        sample.y =
540            (((buf[3] as i32) << 24) | ((buf[4] as i32) << 16) | ((buf[5] & 0xF0) as i32) << 8)
541                >> 12;
542        sample.z =
543            (((buf[6] as i32) << 24) | ((buf[7] as i32) << 16) | ((buf[8] & 0xF0) as i32) << 8)
544                >> 12;
545    }
546
547    /// Converts 9 bytes to acceleration sample in g using the scale factor provided.
548    fn acc_buf_to_sample(buf: &[u8; 9], sample: &mut F32x3, scale_factor: f32) {
549        sample.x =
550            ((((buf[0] as i32) << 24) | ((buf[1] as i32) << 16) | ((buf[2] & 0xF0) as i32) << 8)
551                >> 12) as f32
552                * scale_factor;
553        sample.y =
554            ((((buf[3] as i32) << 24) | ((buf[4] as i32) << 16) | ((buf[5] & 0xF0) as i32) << 8)
555                >> 12) as f32
556                * scale_factor;
557        sample.z =
558            ((((buf[6] as i32) << 24) | ((buf[7] as i32) << 16) | ((buf[8] & 0xF0) as i32) << 8)
559                >> 12) as f32
560                * scale_factor;
561    }
562
563    /// Read the shadow registers initial values.
564    fn init_shadow_values(&mut self) -> Result<(), Error<PROTOCOL::ProtocolError>> {
565        self.protocol
566            .read_multiple_registers(Register::SHADOW_REG1, &mut self.shadow_values)?;
567        Ok(())
568    }
569
570    /// Get the shdow registers' values.
571    fn get_shadow_values(&mut self) -> Result<[u8; 5], Error<PROTOCOL::ProtocolError>> {
572        let mut shadow_values = [0u8; 5];
573        self.protocol
574            .read_multiple_registers(Register::SHADOW_REG1, &mut shadow_values)?;
575        Ok(shadow_values)
576    }
577}
578
579pub trait Protocol {
580    type ProtocolError: core::fmt::Debug;
581
582    /// Read a single register.
583    fn read_register(&mut self, register: Register) -> Result<u8, Error<Self::ProtocolError>>;
584
585    /// Read `buf.len()` registers from the `start_register` address included.
586    fn read_multiple_registers(
587        &mut self,
588        start_register: Register,
589        buf: &mut [u8],
590    ) -> Result<(), Error<Self::ProtocolError>>;
591
592    /// Write a single register.
593    fn write_register(
594        &mut self,
595        register: Register,
596        buf: u8,
597    ) -> Result<(), Error<Self::ProtocolError>>;
598
599    /// Write `buf.len() - 1` registers, the first byte must be the address of the start register.
600    fn write_multiple_registers(
601        &mut self,
602        buf: &mut [u8],
603    ) -> Result<(), Error<Self::ProtocolError>>;
604}
605
606pub struct SpiProtocol<SPI> {
607    spi: SPI,
608}
609
610impl<SPI> Protocol for SpiProtocol<SPI>
611where
612    SPI: SpiDevice,
613{
614    type ProtocolError = SPI::Error;
615
616    /// Read a single register.
617    fn read_register(&mut self, register: Register) -> Result<u8, Error<Self::ProtocolError>> {
618        let mut buf = [0u8; 1];
619        self.spi
620            .transaction(&mut [
621                spi::Operation::Write(&[register.addr() << 1 | 0x01]),
622                spi::Operation::Read(&mut buf),
623            ])
624            .map_err(Error::Protocol)?;
625        Ok(buf[0])
626    }
627
628    /// Read `buf.len()` registers from the `start_register` address included.
629    fn read_multiple_registers(
630        &mut self,
631        start_register: Register,
632        buf: &mut [u8],
633    ) -> Result<(), Error<Self::ProtocolError>> {
634        self.spi
635            .transaction(&mut [
636                spi::Operation::Write(&[(start_register.addr() << 1) | 0x01]),
637                spi::Operation::Read(buf),
638            ])
639            .map_err(Error::Protocol)?;
640        Ok(())
641    }
642
643    /// Write a single register.
644    fn write_register(
645        &mut self,
646        register: Register,
647        buf: u8,
648    ) -> Result<(), Error<Self::ProtocolError>> {
649        self.spi
650            .write(&[register.addr() << 1, buf])
651            .map_err(Error::Protocol)?;
652        Ok(())
653    }
654
655    /// Write `buf.len() - 1` registers, the first byte must be the address of the register.
656    fn write_multiple_registers(
657        &mut self,
658        buf: &mut [u8],
659    ) -> Result<(), Error<Self::ProtocolError>> {
660        buf[0] <<= 1;
661        self.spi.write(buf).map_err(Error::Protocol)?;
662        Ok(())
663    }
664}
665
666pub struct I2cProtocol<I2C> {
667    i2c: I2C,
668    address: u8,
669}
670
671impl<I2C> Protocol for I2cProtocol<I2C>
672where
673    I2C: I2c,
674{
675    type ProtocolError = I2C::Error;
676
677    /// Read a single register.
678    fn read_register(&mut self, register: Register) -> Result<u8, Error<Self::ProtocolError>> {
679        let mut buf = [0u8; 1];
680        self.i2c
681            .write_read(self.address, &[register.addr()], &mut buf)
682            .map_err(Error::Protocol)?;
683        Ok(buf[0])
684    }
685
686    /// Read `buf.len()` registers from the `start_register` address included.
687    fn read_multiple_registers(
688        &mut self,
689        start_register: Register,
690        buf: &mut [u8],
691    ) -> Result<(), Error<Self::ProtocolError>> {
692        self.i2c
693            .write_read(self.address, &[start_register.addr()], buf)
694            .map_err(Error::Protocol)?;
695        Ok(())
696    }
697
698    /// Write a single register.
699    fn write_register(
700        &mut self,
701        register: Register,
702        buf: u8,
703    ) -> Result<(), Error<Self::ProtocolError>> {
704        self.i2c
705            .write(self.address, &[register.addr(), buf])
706            .map_err(Error::Protocol)?;
707        Ok(())
708    }
709
710    /// Write `buf.len() - 1` registers, the first byte must be the address of the register.
711    fn write_multiple_registers(
712        &mut self,
713        buf: &mut [u8],
714    ) -> Result<(), Error<Self::ProtocolError>> {
715        self.i2c.write(self.address, buf).map_err(Error::Protocol)?;
716        Ok(())
717    }
718}
719
720#[derive(Copy, Clone, Debug)]
721#[cfg_attr(feature = "defmt", derive(defmt::Format))]
722#[cfg_attr(feature = "std", derive(thiserror::Error))]
723/// Driver errors
724pub enum Error<ProtocolError: core::fmt::Debug> {
725    /// Protocol error.
726    #[cfg_attr(feature = "std", error("protocol error: {0:?}"))]
727    Protocol(ProtocolError),
728
729    /// Device ID is not 0xED.
730    #[cfg_attr(feature = "std", error("unexpected device ID: {0}"))]
731    BadDeviceId(u8),
732
733    /// Device is in measure mode and cannot be configured.
734    #[cfg_attr(
735        feature = "std",
736        error("device is in measure mode and cannot be configured")
737    )]
738    DeviceRunning,
739
740    /// Software reset failed to reset device properly.
741    #[cfg_attr(feature = "std", error("device software reset failed"))]
742    SoftResetFailed,
743
744    /// The max number of samples to store in the fifo is invalid. Must range from 1 to 96.
745    #[cfg_attr(
746        feature = "std",
747        error("max number of fifo samples must range from 1 to 96")
748    )]
749    InvalidMaxNbFifoSamples,
750
751    /// The fifo does not contain enough data to get one sample with the 3-axis values.
752    #[cfg_attr(feature = "std", error("not enough data in the fifo"))]
753    NotEnoughData,
754}