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
8const DEVICE_ADDR_DEFAULT: u8 = 0x48;
10
11const REG_CONTROL: u8 = 0x06;
13pub 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 power_down: bool,
22 #[bits(2)]
24 filter_setting: FilterSetting,
25 interrupt_enable: bool,
27 interrupt_type: bool,
29 #[bits(3)]
31 __: u8,
32}
33
34#[cfg(feature = "external_mic")]
35#[bitfield(u8)]
36#[derive(PartialEq, Eq, Format)]
37pub struct ControlRegister {
38 power_down: bool,
40 #[bits(2)]
42 filter_setting: FilterSetting,
43 interrupt_enable: bool,
45 interrupt_type: bool,
47 enable_line_out: bool,
49 #[bits(2)]
51 __: u8,
52}
53
54#[derive(Debug, Clone, Copy, PartialEq, Eq)]
55pub enum FilterSetting {
56 None = 0b00,
58 AWeighting = 0b01,
60 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 pub fn set_filter(&mut self, filter_setting: FilterSetting) {
84 self.set_filter_setting(filter_setting);
85 }
86}
87
88const REG_RESET: u8 = 0x09;
90pub const REG_RESET_DEFAULT: u8 = 0x00;
92
93#[bitfield(u8)]
94#[derive(PartialEq, Eq, Format)]
95pub struct ResetRegister {
96 clear_interrupt: bool,
98 clear_min_max: bool,
100 clear_history: bool,
102 system_reset: bool,
105 #[bits(4)]
107 __: u8,
108}
109
110const REG_VERSION: u8 = 0x00;
112const REG_DECIBEL: u8 = 0x0a;
114const REGS_DEVICE_ID: [u8; 4] = [0x01, 0x02, 0x03, 0x04];
116const REG_MAX: u8 = 0x0c;
118const REG_MIN: u8 = 0x0d;
120const REG_SCRATCH: u8 = 0x05;
122const REG_TAVG_HIGH: u8 = 0x07;
124pub const REG_AVERAGING_TIME_DEFAULT_MS: u16 = 1000;
126
127#[cfg(feature = "external_mic")]
129const REG_GAIN: u8 = 0x0f;
130
131pub struct PaSpl<I2C>
133where
134 I2C: i2c::Read + i2c::Write + i2c::WriteRead,
135{
136 i2c: Option<I2C>,
137 device_addr: u8,
138}
139
140#[derive(Debug, PartialEq, Eq)]
142pub enum Error<E> {
143 I2c(E),
145 NoI2cInstance,
147 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 pub fn new(i2c: I2C) -> Self {
162 Self {
163 i2c: Some(i2c),
164 device_addr: DEVICE_ADDR_DEFAULT,
165 }
166 }
167
168 pub fn set_device_addr(&mut self, addr: u8) {
174 self.device_addr = addr;
175 }
176
177 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 let avg_time_ms = ((buffer[0] as u16) << 8) | (buffer[1] as u16);
191
192 Ok(avg_time_ms)
193 }
194
195 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 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 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 pub fn get_firmware_version(&mut self) -> Result<u8, Error<E>> {
238 self.read_byte(REG_VERSION)
239 }
240
241 #[cfg(feature = "external_mic")]
257 pub fn get_gain(&mut self) -> Result<u8, Error<E>> {
258 self.read_byte(REG_GAIN)
259 }
260
261 pub fn get_latest_decibel(&mut self) -> Result<u8, Error<E>> {
273 self.read_byte(REG_DECIBEL)
274 }
275
276 pub fn get_max_decibel(&mut self) -> Result<u8, Error<E>> {
287 self.read_byte(REG_MAX)
288 }
289
290 pub fn get_min_decibel(&mut self) -> Result<u8, Error<E>> {
301 self.read_byte(REG_MIN)
302 }
303
304 pub fn get_scratch(&mut self) -> Result<u8, Error<E>> {
313 self.read_byte(REG_SCRATCH)
314 }
315
316 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 pub fn set_avg_time(&mut self, ms: u16) -> Result<(), Error<E>> {
340 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 pub fn set_control_register(&mut self, reg: ControlRegister) -> Result<(), Error<E>> {
357 self.write_byte(REG_CONTROL, reg.into_bits())
358 }
359
360 #[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 pub fn set_scratch(&mut self, value: u8) -> Result<(), Error<E>> {
382 self.write_byte(REG_SCRATCH, value)
383 }
384
385 pub fn destroy(&mut self) -> I2C {
388 self.i2c
389 .take()
390 .expect("I2C instance has already been taken")
391 }
392
393 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 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 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 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 const DEVICE_VER_MEMS_LTS_ASA: u8 = 0x32;
453 const REG_TAVG_HIGH_DEFAULT_BYTE: u8 = 0x03;
455 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], )];
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], ),
676 I2cTransaction::write(
677 DEVICE_ADDR_DEFAULT,
678 vec![REG_CONTROL, 0b0000_0100], ),
680 ];
681 let i2c_mock = I2cMock::new(&expectations);
682 let mut pa_spl = PaSpl::new(i2c_mock);
683
684 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}