pa_spl/
lib.rs

1#![doc = include_str!("../README.md")]
2#![cfg_attr(not(test), no_std)]
3
4use bitfield_struct::bitfield;
5use defmt::Format;
6use embedded_hal::blocking::i2c;
7
8/// PCB Artists SPL Module I2C default address.
9const DEVICE_ADDR_DEFAULT: u8 = 0x48;
10
11/// CONTROL register address.
12const REG_CONTROL: u8 = 0x06;
13/// CONTROL register default value.
14pub const REG_CONTROL_DEFAULT: u8 = 0x02;
15
16#[cfg(not(feature = "external_mic"))]
17#[bitfield(u8)]
18#[derive(PartialEq, Eq, Format)]
19pub struct ControlRegister {
20    /// Set to power down the sensor
21    power_down: bool,
22    /// Filter selection
23    #[bits(2)]
24    filter_setting: FilterSetting,
25    /// Set to enable interrupt pin operation
26    interrupt_enable: bool,
27    /// Set to enable min/max level interrupts
28    interrupt_type: bool,
29    /// Padding
30    #[bits(3)]
31    __: u8,
32}
33
34#[cfg(feature = "external_mic")]
35#[bitfield(u8)]
36#[derive(PartialEq, Eq, Format)]
37pub struct ControlRegister {
38    /// Set to power down the sensor
39    power_down: bool,
40    /// Filter selection
41    #[bits(2)]
42    filter_setting: FilterSetting,
43    /// Set to enable interrupt pin operation
44    interrupt_enable: bool,
45    /// Set to enable min/max level interrupts
46    interrupt_type: bool,
47    /// Set to enable line output (only for modules with external microphone)
48    enable_line_out: bool,
49    /// Padding for reserved bits
50    #[bits(2)]
51    __: u8,
52}
53
54#[derive(Debug, Clone, Copy, PartialEq, Eq)]
55pub enum FilterSetting {
56    /// No filter
57    None = 0b00,
58    /// A-weighting
59    AWeighting = 0b01,
60    /// C-weighting
61    CWeighting = 0b10,
62}
63
64impl FilterSetting {
65    const fn from_bits(bits: u8) -> Self {
66        match bits {
67            0b00 => Self::None,
68            0b01 => Self::AWeighting,
69            _ => Self::CWeighting,
70        }
71    }
72
73    const fn into_bits(self) -> u8 {
74        self as _
75    }
76}
77
78impl ControlRegister {
79    /// Sets the filter setting
80    ///
81    /// Sets the filter setting bits in ControlRegister for a filter defined in FilterSetting.
82    ///
83    pub fn set_filter(&mut self, filter_setting: FilterSetting) {
84        self.set_filter_setting(filter_setting);
85    }
86}
87
88/// RESET register address.
89const REG_RESET: u8 = 0x09;
90/// RESET register default value.
91pub const REG_RESET_DEFAULT: u8 = 0x00;
92
93#[bitfield(u8)]
94#[derive(PartialEq, Eq, Format)]
95pub struct ResetRegister {
96    /// Set this bit to clear interrupt signal and set INT pin to high-Z; this bit is self-clearing
97    clear_interrupt: bool,
98    /// Set this bit to clear the max and min dB values stored in MAX and MIN registers; t his bit is self-clearing
99    clear_min_max: bool,
100    /// Set this bit to clear the most recent 100 decibel values stored in history registers; this bit is self-clearing.
101    clear_history: bool,
102    /// Set this bit to perform a soft system reset and restore settings to defaults; this bit is self-clearing.
103    /// NOTE: This bit must be set to wake up the device from sleep mode.
104    system_reset: bool,
105    /// Padding for reserved bits
106    #[bits(4)]
107    __: u8,
108}
109
110/// VESION register address.
111const REG_VERSION: u8 = 0x00;
112/// DECIBEL register address.
113const REG_DECIBEL: u8 = 0x0a;
114/// Device ID registers, ID3, ID2, ID1, ID0
115const REGS_DEVICE_ID: [u8; 4] = [0x01, 0x02, 0x03, 0x04];
116/// MAX register.
117const REG_MAX: u8 = 0x0c;
118/// MIN register.
119const REG_MIN: u8 = 0x0d;
120/// SCRATCH register address.
121const REG_SCRATCH: u8 = 0x05;
122/// TAVG register high byte address.
123const REG_TAVG_HIGH: u8 = 0x07;
124/// Default value for averaging time in ms.
125pub const REG_AVERAGING_TIME_DEFAULT_MS: u16 = 1000;
126
127/// GAIN register.
128#[cfg(feature = "external_mic")]
129const REG_GAIN: u8 = 0x0f;
130
131/// A PA SPL Module on the I2C bus `I2C`.
132pub struct PaSpl<I2C>
133where
134    I2C: i2c::Read + i2c::Write + i2c::WriteRead,
135{
136    i2c: Option<I2C>,
137    device_addr: u8,
138}
139
140/// A driver error.
141#[derive(Debug, PartialEq, Eq)]
142pub enum Error<E> {
143    /// I2C bus error.
144    I2c(E),
145    /// No I2C instance available.
146    NoI2cInstance,
147    /// Buffer overflow.
148    BufferOverflow,
149}
150
151impl<E, I2C> PaSpl<I2C>
152where
153    I2C: i2c::Read<Error = E> + i2c::Write<Error = E> + i2c::WriteRead<Error = E>,
154{
155    /// Initializes the PCB Artists SPL Module driver.
156    ///
157    /// # Errors
158    ///
159    /// Returns [`Error::NoI2cInstance`] if the I2C instance is empty.
160    ///
161    pub fn new(i2c: I2C) -> Self {
162        Self {
163            i2c: Some(i2c),
164            device_addr: DEVICE_ADDR_DEFAULT,
165        }
166    }
167
168    /// Sets a new I2C device address.
169    ///
170    /// The published device address is the default but the vendor's website
171    /// states that it is possible to order a device with a custom address.
172    ///
173    pub fn set_device_addr(&mut self, addr: u8) {
174        self.device_addr = addr;
175    }
176
177    /// Gets the 16-bit averaging time in ms from registers TAVG high and TAVG low (0x07 and 0x08).
178    ///
179    /// # Errors
180    ///
181    /// Returns [`Error::NoI2cInstance`] if the I2C instance is empty.
182    ///
183    /// Returns [`Error::I2c`] if I2C returns an error.
184    ///
185    pub fn get_avg_time(&mut self) -> Result<u16, Error<E>> {
186        let mut buffer: [u8; 2] = [0; 2];
187        self.read_bytes(REG_TAVG_HIGH, &mut buffer)?;
188
189        // Combine the bytes into a u16.
190        let avg_time_ms = ((buffer[0] as u16) << 8) | (buffer[1] as u16);
191
192        Ok(avg_time_ms)
193    }
194
195    /// Gets the CONTROL register.
196    ///
197    /// # Errors
198    ///
199    /// Returns [`Error::NoI2cInstance`] if the I2C instance is empty.
200    ///
201    /// Returns [`Error::I2c`] if I2C returns an error.
202    ///
203    pub fn get_control_register(&mut self) -> Result<ControlRegister, Error<E>> {
204        let control_reg_raw = self.read_byte(REG_CONTROL)?;
205        Ok(ControlRegister::from_bits(control_reg_raw))
206    }
207
208    /// Gets the 32-bit device ID from registers ID3-ID0.
209    ///
210    /// # Errors
211    ///
212    /// Returns [`Error::NoI2cInstance`] if the I2C instance is empty.
213    ///
214    /// Returns [`Error::I2c`] if I2C returns an error.
215    ///
216    pub fn get_device_id(&mut self) -> Result<u32, Error<E>> {
217        let mut buffer: [u8; 4] = [0; 4];
218        self.read_bytes(REGS_DEVICE_ID[0], &mut buffer)?;
219
220        // Combine the bytes into a u32.
221        let device_id: u32 = ((buffer[0] as u32) << 24)
222            | ((buffer[1] as u32) << 16)
223            | ((buffer[2] as u32) << 8)
224            | (buffer[3] as u32);
225
226        Ok(device_id)
227    }
228
229    /// Gets the firmware version from the VERSION register.
230    ///
231    /// # Errors
232    ///
233    /// Returns [`Error::NoI2cInstance`] if the I2C instance is empty.
234    ///
235    /// Returns [`Error::I2c`] if I2C returns an error.
236    ///
237    pub fn get_firmware_version(&mut self) -> Result<u8, Error<E>> {
238        self.read_byte(REG_VERSION)
239    }
240
241    /// Gets the gain value in 0.5 decibel steps from the GAIN register.
242    ///
243    /// This value only needs to be modified if you are using your own
244    /// microphone. The default value will work with the default microphone
245    /// supplied with the module.
246    ///
247    /// Acceptable values are 0 to 95 to set the gain in 0.5 dB steps (+0.0 dB
248    /// to +47.5 dB).
249    ///
250    /// # Errors
251    ///
252    /// Returns [`Error::NoI2cInstance`] if the I2C instance is empty.
253    ///
254    /// Returns [`Error::I2c`] if I2C returns an error.
255    ///
256    #[cfg(feature = "external_mic")]
257    pub fn get_gain(&mut self) -> Result<u8, Error<E>> {
258        self.read_byte(REG_GAIN)
259    }
260
261    /// Gets the latest SPL value in decibels from the DECIBEL register.
262    ///
263    /// The SPL value is averaged over the last Tavg time period that is stored
264    /// in the TAVG high byte register (0x07) and the TAVG low register (x08).
265    ///
266    /// # Errors
267    ///
268    /// Returns [`Error::NoI2cInstance`] if the I2C instance is empty.
269    ///
270    /// Returns [`Error::I2c`] if I2C returns an error.
271    ///
272    pub fn get_latest_decibel(&mut self) -> Result<u8, Error<E>> {
273        self.read_byte(REG_DECIBEL)
274    }
275
276    /// Gets the max SPL value in decibels from the MAX register.
277    ///
278    /// Maximum value of decibel reading captured since power-up or manual reset of MIN/MAX registers.
279    ///
280    /// # Errors
281    ///
282    /// Returns [`Error::NoI2cInstance`] if the I2C instance is empty.
283    ///
284    /// Returns [`Error::I2c`] if I2C returns an error.
285    ///
286    pub fn get_max_decibel(&mut self) -> Result<u8, Error<E>> {
287        self.read_byte(REG_MAX)
288    }
289
290    /// Gets the min SPL value in decibels from the MIN register.
291    ///
292    /// Minimum value of decibel reading captured since power-up or manual reset of MIN/MAX registers.
293    ///
294    /// # Errors
295    ///
296    /// Returns [`Error::NoI2cInstance`] if the I2C instance is empty.
297    ///
298    /// Returns [`Error::I2c`] if I2C returns an error.
299    ///
300    pub fn get_min_decibel(&mut self) -> Result<u8, Error<E>> {
301        self.read_byte(REG_MIN)
302    }
303
304    /// Gets the value stored in the SCRATCH register.
305    ///
306    /// # Errors
307    ///
308    /// Returns [`Error::NoI2cInstance`] if the I2C instance is empty.
309    ///
310    /// Returns [`Error::I2c`] if I2C returns an error.
311    ///
312    pub fn get_scratch(&mut self) -> Result<u8, Error<E>> {
313        self.read_byte(REG_SCRATCH)
314    }
315
316    /// Soft resets the sensor.
317    ///
318    /// The sensor is soft reset by setting the System Reset bit in the RESET register.
319    ///
320    /// # Errors
321    ///
322    /// Returns [`Error::NoI2cInstance`] if the I2C instance is empty.
323    ///
324    /// Returns [`Error::I2c`] if I2C returns an error.
325    ///
326    pub fn reset(&mut self) -> Result<(), Error<E>> {
327        let reg_reset = ResetRegister::new().with_system_reset(true);
328        self.write_byte(REG_RESET, reg_reset.into_bits())
329    }
330
331    /// Sets the average time in ms for calculating SPL.
332    ///
333    /// # Errors
334    ///
335    /// Returns [`Error::NoI2cInstance`] if the I2C instance is empty.
336    ///
337    /// Returns [`Error::I2c`] if I2C returns an error.
338    ///
339    pub fn set_avg_time(&mut self, ms: u16) -> Result<(), Error<E>> {
340        // Convert the average time in ms to high and low bytes.
341        let tavg_high_byte: u8 = (ms >> 8) as u8;
342        let tavg_low_byte: u8 = (ms & 0xFF) as u8;
343        let buffer = [tavg_high_byte, tavg_low_byte];
344
345        self.write_two_bytes(REG_TAVG_HIGH, &buffer)
346    }
347
348    /// Sets the CONTROL register.
349    ///
350    /// # Errors
351    ///
352    /// Returns [`Error::NoI2cInstance`] if the I2C instance is empty.
353    ///
354    /// Returns [`Error::I2c`] if I2C returns an error.
355    ///
356    pub fn set_control_register(&mut self, reg: ControlRegister) -> Result<(), Error<E>> {
357        self.write_byte(REG_CONTROL, reg.into_bits())
358    }
359
360    /// Sets the gain in the GAIN register.
361    ///
362    /// # Errors
363    ///
364    /// Returns [`Error::NoI2cInstance`] if the I2C instance is empty.
365    ///
366    /// Returns [`Error::I2c`] if I2C returns an error.
367    /// ```
368    #[cfg(feature = "external_mic")]
369    pub fn set_gain(&mut self, value: u8) -> Result<(), Error<E>> {
370        self.write_byte(REG_GAIN, value)
371    }
372
373    /// Sets the value stored in the SCRATCH register.
374    ///
375    /// # Errors
376    ///
377    /// Returns [`Error::NoI2cInstance`] if the I2C instance is empty.
378    ///
379    /// Returns [`Error::I2c`] if I2C returns an error.
380    ///
381    pub fn set_scratch(&mut self, value: u8) -> Result<(), Error<E>> {
382        self.write_byte(REG_SCRATCH, value)
383    }
384
385    /// Destroys this driver and releases the I2C bus.
386    ///
387    pub fn destroy(&mut self) -> I2C {
388        self.i2c
389            .take()
390            .expect("I2C instance has already been taken")
391    }
392
393    /// Reads a single byte from an I2C register of the device.
394    ///
395    fn read_byte(&mut self, reg: u8) -> Result<u8, Error<E>> {
396        let mut buffer = [0; 1];
397        self.i2c
398            .as_mut()
399            .ok_or(Error::NoI2cInstance)?
400            .write_read(self.device_addr, &[reg], &mut buffer)
401            .map_err(Error::I2c)?;
402        Ok(buffer[0])
403    }
404
405    /// Read multiple bytes from a starting register.
406    ///
407    fn read_bytes(&mut self, start_reg: u8, buffer: &mut [u8]) -> Result<(), Error<E>> {
408        self.i2c
409            .as_mut()
410            .ok_or(Error::NoI2cInstance)?
411            .write_read(self.device_addr, &[start_reg], buffer)
412            .map_err(Error::I2c)?;
413        Ok(())
414    }
415
416    /// Writes a single byte to an I2C register of the device.
417    ///
418    fn write_byte(&mut self, reg: u8, value: u8) -> Result<(), Error<E>> {
419        self.i2c
420            .as_mut()
421            .ok_or(Error::NoI2cInstance)?
422            .write(self.device_addr, &[reg, value])
423            .map_err(Error::I2c)
424    }
425
426    /// Writes two bytes from a starting register.
427    ///
428    fn write_two_bytes(&mut self, reg: u8, buffer: &[u8]) -> Result<(), Error<E>> {
429        if buffer.len() > 2 {
430            return Err(Error::BufferOverflow);
431        }
432
433        self.i2c
434            .as_mut()
435            .ok_or(Error::NoI2cInstance)?
436            .write(self.device_addr, &[reg, buffer[0], buffer[1]])
437            .map_err(Error::I2c)
438    }
439}
440
441#[cfg(test)]
442mod tests {
443    use crate::{
444        ControlRegister, FilterSetting, REG_AVERAGING_TIME_DEFAULT_MS, REG_CONTROL,
445        REG_CONTROL_DEFAULT, REG_RESET, REG_TAVG_HIGH,
446    };
447
448    use super::*;
449    use embedded_hal_mock::eh0::i2c::{Mock as I2cMock, Transaction as I2cTransaction};
450
451    /// DEVICE_VER_MEMS_LTS: Published version for base features + audio spectrum analyzer.
452    const DEVICE_VER_MEMS_LTS_ASA: u8 = 0x32;
453    /// TAVG register high byte default value.
454    const REG_TAVG_HIGH_DEFAULT_BYTE: u8 = 0x03;
455    /// TAVG register low byte default value.
456    const REG_TAVG_LOW_DEFAULT_BYTE: u8 = 0xE8;
457
458    #[test]
459    fn confirm_set_device_addr() {
460        let expectations = vec![];
461        let i2c_mock = I2cMock::new(&expectations);
462
463        let mut pa_spl = PaSpl::new(i2c_mock);
464        let new_device_addr: u8 = 0x99;
465        pa_spl.set_device_addr(new_device_addr);
466        assert_eq!(new_device_addr, pa_spl.device_addr);
467
468        let mut mock = pa_spl.destroy();
469        mock.done();
470    }
471
472    #[test]
473    fn confirm_device_id() {
474        let expectations = vec![I2cTransaction::write_read(
475            DEVICE_ADDR_DEFAULT,
476            vec![REGS_DEVICE_ID[0]],
477            vec![0x01, 0x02, 0x03, 0x04],
478        )];
479        let i2c_mock = I2cMock::new(&expectations);
480
481        let mut pa_spl = PaSpl::new(i2c_mock);
482        let device_id = pa_spl.get_device_id().unwrap();
483        assert_eq!(0x01020304, device_id);
484
485        let mut mock = pa_spl.destroy();
486        mock.done();
487    }
488
489    #[test]
490    fn confirm_firmware_version() {
491        let expectations = vec![I2cTransaction::write_read(
492            DEVICE_ADDR_DEFAULT,
493            vec![REG_VERSION],
494            vec![DEVICE_VER_MEMS_LTS_ASA],
495        )];
496        let i2c_mock = I2cMock::new(&expectations);
497        let mut pa_spl = PaSpl::new(i2c_mock);
498
499        let version = pa_spl.get_firmware_version().unwrap();
500        assert_eq!(DEVICE_VER_MEMS_LTS_ASA, version);
501
502        let mut mock = pa_spl.destroy();
503        mock.done();
504    }
505
506    #[test]
507    fn confirm_get_avg_time() {
508        let expectations = vec![I2cTransaction::write_read(
509            DEVICE_ADDR_DEFAULT,
510            vec![REG_TAVG_HIGH],
511            vec![REG_TAVG_HIGH_DEFAULT_BYTE, REG_TAVG_LOW_DEFAULT_BYTE],
512        )];
513        let i2c_mock = I2cMock::new(&expectations);
514        let mut pa_spl = PaSpl::new(i2c_mock);
515
516        let averaging_time_ms = pa_spl.get_avg_time().unwrap();
517        assert_eq!(REG_AVERAGING_TIME_DEFAULT_MS, averaging_time_ms);
518
519        let mut mock = pa_spl.destroy();
520        mock.done();
521    }
522
523    #[test]
524    fn confirm_get_control_register() {
525        let expectations = vec![I2cTransaction::write_read(
526            DEVICE_ADDR_DEFAULT,
527            vec![REG_CONTROL],
528            vec![REG_CONTROL_DEFAULT], // 0b0000_0010
529        )];
530        let i2c_mock = I2cMock::new(&expectations);
531        let mut pa_spl = PaSpl::new(i2c_mock);
532
533        let reg_control = pa_spl.get_control_register().unwrap();
534        let control_register_default_bits = ControlRegister::from_bits(REG_CONTROL_DEFAULT);
535        assert_eq!(control_register_default_bits, reg_control);
536
537        let mut mock = pa_spl.destroy();
538        mock.done();
539    }
540
541    #[cfg(feature = "external_mic")]
542    #[test]
543    fn confirm_get_gain() {
544        let expectations = vec![I2cTransaction::write_read(
545            DEVICE_ADDR_DEFAULT,
546            vec![REG_GAIN],
547            vec![18],
548        )];
549        let i2c_mock = I2cMock::new(&expectations);
550        let mut pa_spl = PaSpl::new(i2c_mock);
551
552        let expected_gain: u8 = 18;
553        let gain_val = pa_spl.get_gain().unwrap();
554        assert_eq!(expected_gain, gain_val);
555
556        let mut mock = pa_spl.destroy();
557        mock.done();
558    }
559
560    #[test]
561    fn confirm_get_latest_decibel() {
562        let expectations = vec![I2cTransaction::write_read(
563            DEVICE_ADDR_DEFAULT,
564            vec![REG_DECIBEL],
565            vec![0x12],
566        )];
567        let i2c_mock = I2cMock::new(&expectations);
568        let mut pa_spl = PaSpl::new(i2c_mock);
569
570        let latest_decibel_val = pa_spl.get_latest_decibel().unwrap();
571        assert_eq!(0x12, latest_decibel_val);
572
573        let mut mock = pa_spl.destroy();
574        mock.done();
575    }
576
577    #[test]
578    fn confirm_get_max_decibel() {
579        let expectations = vec![I2cTransaction::write_read(
580            DEVICE_ADDR_DEFAULT,
581            vec![REG_MAX],
582            vec![0x12],
583        )];
584        let i2c_mock = I2cMock::new(&expectations);
585        let mut pa_spl = PaSpl::new(i2c_mock);
586
587        let result = pa_spl.get_max_decibel();
588        assert!(result.is_ok());
589
590        let mut mock = pa_spl.destroy();
591        mock.done();
592    }
593
594    #[test]
595    fn confirm_get_min_decibel() {
596        let expectations = vec![I2cTransaction::write_read(
597            DEVICE_ADDR_DEFAULT,
598            vec![REG_MIN],
599            vec![0x12],
600        )];
601        let i2c_mock = I2cMock::new(&expectations);
602        let mut pa_spl = PaSpl::new(i2c_mock);
603
604        let result = pa_spl.get_min_decibel();
605        assert!(result.is_ok());
606
607        let mut mock = pa_spl.destroy();
608        mock.done();
609    }
610
611    #[test]
612    fn confirm_get_scratch() {
613        let expectations = vec![I2cTransaction::write_read(
614            DEVICE_ADDR_DEFAULT,
615            vec![REG_SCRATCH],
616            vec![0x99],
617        )];
618        let i2c_mock = I2cMock::new(&expectations);
619        let mut pa_spl = PaSpl::new(i2c_mock);
620
621        let scratch_write_val: u8 = 0x99;
622        let scratch_read_val = pa_spl.get_scratch().unwrap();
623        assert_eq!(scratch_write_val, scratch_read_val);
624
625        let mut mock = pa_spl.destroy();
626        mock.done();
627    }
628
629    #[test]
630    fn confirm_reset() {
631        let expectations = vec![I2cTransaction::write(
632            DEVICE_ADDR_DEFAULT,
633            vec![REG_RESET, 0b0000_1000],
634        )];
635        let i2c_mock = I2cMock::new(&expectations);
636        let mut pa_spl = PaSpl::new(i2c_mock);
637
638        let result = pa_spl.reset();
639        assert!(result.is_ok());
640
641        let mut mock = pa_spl.destroy();
642        mock.done();
643    }
644
645    #[test]
646    fn confirm_set_avg_time() {
647        let new_avg_time_ms: u16 = 125;
648        let tavg_high_expected_byte: u8 = 0x00;
649        let tavg_low_expected_byte: u8 = 0x7D;
650        let expectations = vec![I2cTransaction::write(
651            DEVICE_ADDR_DEFAULT,
652            vec![
653                REG_TAVG_HIGH,
654                tavg_high_expected_byte,
655                tavg_low_expected_byte,
656            ],
657        )];
658        let i2c_mock = I2cMock::new(&expectations);
659        let mut pa_spl = PaSpl::new(i2c_mock);
660
661        let result = pa_spl.set_avg_time(new_avg_time_ms);
662        assert!(result.is_ok());
663
664        let mut mock = pa_spl.destroy();
665        mock.done();
666    }
667
668    #[test]
669    fn confirm_set_control_register() {
670        let expectations = vec![
671            I2cTransaction::write_read(
672                DEVICE_ADDR_DEFAULT,
673                vec![REG_CONTROL],
674                vec![REG_CONTROL_DEFAULT], // 0b0000_0010
675            ),
676            I2cTransaction::write(
677                DEVICE_ADDR_DEFAULT,
678                vec![REG_CONTROL, 0b0000_0100], // 0b0000_0100
679            ),
680        ];
681        let i2c_mock = I2cMock::new(&expectations);
682        let mut pa_spl = PaSpl::new(i2c_mock);
683
684        // Read-modify-write register.
685        let mut reg_control = pa_spl.get_control_register().unwrap();
686        reg_control.set_filter_setting(FilterSetting::CWeighting);
687        let result = pa_spl.set_control_register(reg_control);
688        assert!(result.is_ok());
689
690        let mut mock = pa_spl.destroy();
691        mock.done();
692    }
693
694    #[cfg(feature = "external_mic")]
695    #[test]
696    fn confirm_set_gain() {
697        let new_gain_val: u8 = 43;
698        let expectations = vec![I2cTransaction::write(
699            DEVICE_ADDR_DEFAULT,
700            vec![REG_GAIN, new_gain_val],
701        )];
702        let i2c_mock = I2cMock::new(&expectations);
703        let mut pa_spl = PaSpl::new(i2c_mock);
704
705        let result = pa_spl.set_gain(new_gain_val);
706        assert!(result.is_ok());
707
708        let mut mock = pa_spl.destroy();
709        mock.done();
710    }
711
712    #[test]
713    fn confirm_set_scratch() {
714        let scratch_write_val: u8 = 0x99;
715        let expectations = vec![I2cTransaction::write(
716            DEVICE_ADDR_DEFAULT,
717            vec![REG_SCRATCH, scratch_write_val],
718        )];
719        let i2c_mock = I2cMock::new(&expectations);
720        let mut pa_spl = PaSpl::new(i2c_mock);
721
722        let result = pa_spl.set_scratch(scratch_write_val);
723        assert!(result.is_ok());
724
725        let mut mock = pa_spl.destroy();
726        mock.done();
727    }
728}