1#![no_std]
2#![deny(rust_2018_idioms)]
3#![cfg_attr(docsrs, feature(doc_cfg))]
4
5#![doc = document_features::document_features!(feature_label = r#"<span class="stab portability"><code>{feature}</code></span>"#)]
7
8pub(crate) mod fmt;
9use embedded_hal::{digital::OutputPin, i2c};
10use embedded_hal::delay::DelayNs;
11
12const CS43L22_ADDR: u8 = 74;
13
14const CS43L22_REG_ID: u8 = 0x01;
16const CS43L22_REG_POWER_CTL1: u8 = 0x02;
17const CS43L22_REG_POWER_CTL2: u8 = 0x04;
18const CS43L22_REG_CLOCKING_CTL: u8 = 0x05;
19const CS43L22_REG_INTERFACE_CTL1: u8 = 0x06;
20const CS43L22_REG_ANALOG_ZC_SR_SETT: u8 = 0x0A;
24const CS43L22_REG_MISC_CTL: u8 = 0x0E;
27const CS43L22_REG_PCMA_VOL: u8 = 0x1A;
31const CS43L22_REG_PCMB_VOL: u8 = 0x1B;
32const CS43L22_REG_BEEP_FREQ_ONTIME: u8 = 0x1C;
33const CS43L22_REG_BEEP_VOL_OFFTIME: u8 = 0x1D;
34const CS43L22_REG_BEEP_TONE_CFG: u8 = 0x1E;
35const CS43L22_REG_TONE_CTL: u8 = 0x1F;
36const CS43L22_REG_MASTER_A_VOL: u8 = 0x20;
37const CS43L22_REG_MASTER_B_VOL: u8 = 0x21;
38const CS43L22_REG_HP_A_VOL: u8 = 0x22;
39const CS43L22_REG_HP_B_VOL: u8 = 0x23;
40const CS43L22_REG_PCM_CH_SWAP: u8 = 0x26;
43const CS43L22_REG_LIMIT_CTL1: u8 = 0x27;
44#[derive(Debug)]
53pub enum Error<I2CError> {
55 I2C(I2CError),
57 InvalidChipID,
60}
61pub type Result<T, I2CError> = core::result::Result<T, Error<I2CError>>;
63
64impl<I2CError> From<I2CError> for Error<I2CError> {
65 fn from(value: I2CError) -> Self {
66 Self::I2C(value)
67 }
68}
69
70#[derive(Debug)]
74#[cfg_attr(feature = "defmt", derive(defmt::Format))]
75pub struct Config {
76 output_device: OutputDevice,
77 interface_format: InterfaceFormat,
78 word_length: WordLength,
79 treble_cutoff: TrebleCutoff,
80 treble_gain: ToneGain,
81 bass_cutoff: BassCutoff,
82 bass_gain: ToneGain,
83 tone_control: bool,
84 volume_a: u16,
85 volume_b: u16,
86}
87impl Config {
88 pub fn new() -> Self {
90 Self {
91 output_device: OutputDevice::Auto,
92 interface_format: InterfaceFormat::I2S,
93 word_length: WordLength::W32,
94 treble_cutoff: TrebleCutoff::_5kHz,
95 treble_gain: ToneGain::_0dB,
96 bass_cutoff: BassCutoff::_50Hz,
97 bass_gain: ToneGain::_0dB,
98 tone_control: false,
99 volume_a: 70,
100 volume_b: 70,
101 }
102 }
103
104 pub fn output_device(mut self, output_device: OutputDevice) -> Self {
106 self.output_device = output_device;
107 self
108 }
109
110 pub fn interface_format(mut self, interface_format: InterfaceFormat) -> Self {
112 self.interface_format = interface_format;
113 self
114 }
115
116 pub fn word_length(mut self, word_length: WordLength) -> Self {
118 self.word_length = word_length;
119 self
120 }
121
122 pub fn volume_a(mut self, volume: u16) -> Self {
124 self.volume_a = volume;
125 self
126 }
127
128 pub fn volume_b(mut self, volume: u16) -> Self {
130 self.volume_b = volume;
131 self
132 }
133
134 pub fn treble_cutoff(mut self, treble_cutoff: TrebleCutoff) -> Self {
136 self.treble_cutoff = treble_cutoff;
137 self
138 }
139
140 pub fn treble_gain(mut self, treble_gain: ToneGain) -> Self {
142 self.treble_gain = treble_gain;
143 self
144 }
145
146 pub fn bass_cutoff(mut self, bass_cutoff: BassCutoff) -> Self {
148 self.bass_cutoff = bass_cutoff;
149 self
150 }
151
152 pub fn bass_gain(mut self, bass_gain: ToneGain) -> Self {
154 self.bass_gain = bass_gain;
155 self
156 }
157
158 pub fn with_tone_control(mut self, tone_control: bool) -> Self {
160 self.tone_control = tone_control;
161 self
162 }
163}
164
165impl Default for Config {
166 fn default() -> Self {
167 Self::new()
168 }
169}
170
171pub struct Cs43l22<I2C, RST, DL> {
180 pub i2c: I2C,
182 pub reset: RST,
184 pub delay: DL,
186 pub config: Config,
188 pub beep_config: BeepConfig,
190 running: bool,
191}
192impl<I2C, I2CError, RST, DL> Cs43l22<I2C, RST, DL>
195where
196 I2C: i2c::I2c<u8, Error = I2CError>,
197 I2CError: i2c::Error,
198 RST: OutputPin,
199 DL: DelayNs,
200{
201 pub fn new(
204 i2c: I2C,
205 reset: RST,
206 delay: DL,
207 config: Config,
208 beep_config: BeepConfig,
209 dsp_mode: bool,
210 ) -> Result<Self, I2CError> {
211 let mut cs43l22 = Self {
212 i2c,
213 reset,
214 delay,
215 config,
216 beep_config,
217 running: false,
218 };
219
220 cs43l22.reset()?;
222
223 let mut chip_id = [0u8; 1];
225 cs43l22.i2c.write(CS43L22_ADDR, &[CS43L22_REG_ID])?;
226 cs43l22.i2c.read(CS43L22_ADDR, &mut chip_id)?;
227
228 if chip_id[0] & 0xF8 != 0xE0 {
229 return Err(Error::InvalidChipID);
230 }
231 trace!("Chip ID: {}", chip_id[0] & 0xF8);
232
233 cs43l22
235 .i2c
236 .write(CS43L22_ADDR, &[CS43L22_REG_POWER_CTL1, 0x01])?;
237 cs43l22.i2c.write(
239 CS43L22_ADDR,
240 &[CS43L22_REG_POWER_CTL2, cs43l22.config.output_device.into()],
241 )?;
242 cs43l22
244 .i2c
245 .write(CS43L22_ADDR, &[CS43L22_REG_CLOCKING_CTL, 0x81])?;
246 let interface_ctl1 = cs43l22.config.word_length.value()
249 + (cs43l22.config.interface_format.value() << 2)
250 + ((dsp_mode as u8) << 3);
251
252 cs43l22
253 .i2c
254 .write(CS43L22_ADDR, &[CS43L22_REG_INTERFACE_CTL1, interface_ctl1])?;
255
256 cs43l22
258 .i2c
259 .write(CS43L22_ADDR, &[CS43L22_REG_ANALOG_ZC_SR_SETT, 0x00])?;
260 cs43l22
262 .i2c
263 .write(CS43L22_ADDR, &[CS43L22_REG_MISC_CTL, 0x04])?;
264 cs43l22
266 .i2c
267 .write(CS43L22_ADDR, &[CS43L22_REG_LIMIT_CTL1, 0x00])?;
268
269 let tone_cfg = cs43l22.config.tone_control as u8
271 | (cs43l22.config.treble_cutoff.value() << 3)
272 | (cs43l22.config.bass_cutoff.value() << 1);
273 cs43l22
274 .i2c
275 .write(CS43L22_ADDR, &[CS43L22_REG_TONE_CTL, tone_cfg])?;
276
277 let tone_ctl = cs43l22.config.bass_gain.value() | (cs43l22.config.treble_gain.value() << 4);
279 cs43l22
280 .i2c
281 .write(CS43L22_ADDR, &[CS43L22_REG_TONE_CTL, tone_ctl])?;
282
283 Ok(cs43l22)
284 }
285
286 pub fn play(&mut self) -> Result<(), I2CError> {
288 if !self.running {
289 self.i2c
291 .write(CS43L22_ADDR, &[CS43L22_REG_MISC_CTL, 0x06])?;
292
293 self.i2c
296 .write(CS43L22_ADDR, &[CS43L22_REG_POWER_CTL1, 0x9E])?;
297
298 self.running = true;
299 }
300 Ok(())
301 }
302
303 pub fn reset(&mut self) -> Result<(), I2CError> {
305 self.reset.set_low().ok();
306 self.delay.delay_ms(100);
307 self.reset.set_high().ok();
308 self.delay.delay_ms(100);
309 Ok(())
310 }
311
312 pub fn stop(&mut self) -> Result<(), I2CError> {
314 if self.running {
315 self.mute()?;
316 self.i2c
318 .write(CS43L22_ADDR, &[CS43L22_REG_MISC_CTL, 0x04])?;
319 self.i2c
321 .write(CS43L22_ADDR, &[CS43L22_REG_POWER_CTL1, 0x9F])?;
322 self.running = false;
323 }
324 Ok(())
325 }
326
327 pub fn pause(&mut self) -> Result<(), I2CError> {
329 if self.running {
330 self.mute()?;
331 self.i2c
333 .write(CS43L22_ADDR, &[CS43L22_REG_POWER_CTL1, 0x01])?;
334 self.running = false;
335 }
336 Ok(())
337 }
338
339 pub fn resume(&mut self) -> Result<(), I2CError> {
341 if !self.running {
342 self.unmute()?;
344 self.i2c
346 .write(CS43L22_ADDR, &[CS43L22_REG_POWER_CTL1, 0x9E])?;
347 self.running = true;
348 }
349 Ok(())
350 }
351
352 pub fn mute(&mut self) -> Result<(), I2CError> {
354 self.i2c
355 .write(CS43L22_ADDR, &[CS43L22_REG_POWER_CTL2, 0xFF])?;
356 self.i2c
357 .write(CS43L22_ADDR, &[CS43L22_REG_HP_A_VOL, 0x01])?;
358 self.i2c
359 .write(CS43L22_ADDR, &[CS43L22_REG_HP_B_VOL, 0x01])?;
360
361 Ok(())
362 }
363
364 pub fn unmute(&mut self) -> Result<(), I2CError> {
366 self.i2c
367 .write(CS43L22_ADDR, &[CS43L22_REG_HP_A_VOL, 0x00])?;
368 self.i2c
369 .write(CS43L22_ADDR, &[CS43L22_REG_HP_B_VOL, 0x00])?;
370 self.i2c.write(
371 CS43L22_ADDR,
372 &[CS43L22_REG_POWER_CTL2, self.config.output_device.into()],
373 )?;
374 Ok(())
375 }
376
377 pub fn set_volume_a(&mut self, volume: u16) -> Result<(), I2CError> {
379 self.config.volume_a = volume;
380 self.i2c.write(
381 CS43L22_ADDR,
382 &[
383 CS43L22_REG_MASTER_A_VOL,
384 self.convert_volume(self.config.volume_a),
385 ],
386 )?;
387 Ok(())
388 }
389
390 pub fn set_volume_b(&mut self, volume: u16) -> Result<(), I2CError> {
392 self.config.volume_b = volume;
393 self.i2c.write(
394 CS43L22_ADDR,
395 &[
396 CS43L22_REG_MASTER_B_VOL,
397 self.convert_volume(self.config.volume_b),
398 ],
399 )?;
400 Ok(())
401 }
402
403 pub fn get_volume_a(&mut self) -> Result<u16, I2CError> {
405 Ok(self.config.volume_a)
406 }
407
408 pub fn get_volume_b(&mut self) -> Result<u16, I2CError> {
410 Ok(self.config.volume_b)
411 }
412
413 pub fn set_pcm_volume_a(&mut self, volume: u16) -> Result<(), I2CError> {
415 self.i2c.write(
416 CS43L22_ADDR,
417 &[CS43L22_REG_PCMA_VOL, self.convert_pcm_volume(volume)],
418 )?;
419 Ok(())
420 }
421
422 pub fn set_pcm_volume_b(&mut self, volume: u16) -> Result<(), I2CError> {
424 self.i2c.write(
425 CS43L22_ADDR,
426 &[CS43L22_REG_PCMB_VOL, self.convert_pcm_volume(volume)],
427 )?;
428 Ok(())
429 }
430
431 pub fn pcm_mute(&mut self) -> Result<(), I2CError> {
433 let mut current_volume_a = [0u8; 1];
434 let mut current_volume_b = [0u8; 1];
435 self.i2c
436 .write_read(CS43L22_ADDR, &[CS43L22_REG_PCMA_VOL], &mut current_volume_a)?;
437 self.i2c
438 .write_read(CS43L22_ADDR, &[CS43L22_REG_PCMB_VOL], &mut current_volume_b)?;
439 self.i2c.write(
440 CS43L22_ADDR,
441 &[CS43L22_REG_PCMA_VOL, current_volume_a[0] | 0x80],
442 )?;
443 self.i2c.write(
444 CS43L22_ADDR,
445 &[CS43L22_REG_PCMB_VOL, current_volume_b[0] | 0x80],
446 )?;
447 Ok(())
448 }
449
450 pub fn pcm_unmute(&mut self) -> Result<(), I2CError> {
452 let mut current_volume_a = [0u8; 1];
453 let mut current_volume_b = [0u8; 1];
454 self.i2c
455 .write_read(CS43L22_ADDR, &[CS43L22_REG_PCMA_VOL], &mut current_volume_a)?;
456 self.i2c
457 .write_read(CS43L22_ADDR, &[CS43L22_REG_PCMB_VOL], &mut current_volume_b)?;
458 self.i2c.write(
459 CS43L22_ADDR,
460 &[CS43L22_REG_PCMA_VOL, current_volume_a[0] & 0x7F],
461 )?;
462 self.i2c.write(
463 CS43L22_ADDR,
464 &[CS43L22_REG_PCMB_VOL, current_volume_b[0] & 0x7F],
465 )?;
466 Ok(())
467 }
468
469 pub fn setup_beep(&mut self) -> Result<(), I2CError> {
471 let mut tone_cfg = [0u8; 1];
473 self.i2c
474 .write_read(CS43L22_ADDR, &[CS43L22_REG_BEEP_TONE_CFG], &mut tone_cfg)?;
475
476 tone_cfg[0] = tone_cfg[0] & 0x0F;
477
478 let frec_ontime_value =
479 self.beep_config.on_time.value() | (self.beep_config.pitch.value() << 4) + tone_cfg[0];
480 self.i2c.write(
481 CS43L22_ADDR,
482 &[CS43L22_REG_BEEP_FREQ_ONTIME, frec_ontime_value],
483 )?;
484 let vol_offtime_value = self.convert_beep_volume(self.beep_config.volume)
485 | (self.beep_config.off_time.value() << 5);
486 self.i2c.write(
487 CS43L22_ADDR,
488 &[CS43L22_REG_BEEP_VOL_OFFTIME, vol_offtime_value],
489 )?;
490
491 let tone_cfg_value =
493 (self.beep_config.mode.value() << 6) | ((!self.beep_config.mix as u8) << 5);
494 self.i2c
495 .write(CS43L22_ADDR, &[CS43L22_REG_BEEP_TONE_CFG, tone_cfg_value])?;
496
497 Ok(())
498 }
499
500 pub fn change_beep_settings(&mut self, beep_config: BeepConfig) -> Result<(), I2CError> {
502 self.beep_config = beep_config;
503 self.setup_beep()
504 }
505
506 pub fn set_pcm_mix(&mut self, mix: PCMmix) -> Result<(), I2CError> {
508 let pcm_channel_swap_val = mix.value() << 4;
509 self.i2c.write(
510 CS43L22_ADDR,
511 &[CS43L22_REG_PCM_CH_SWAP, pcm_channel_swap_val],
512 )?;
513 Ok(())
514 }
515
516 fn convert_volume(&self, volume: u16) -> u8 {
518 let mut volume = (volume * 255 / 100) as u8;
519 if volume > 0xE6 {
520 volume = volume - 0xE7;
521 } else {
522 volume = volume + 0x19;
523 }
524 volume
525 }
526 fn convert_pcm_volume(&self, volume: u16) -> u8 {
527 let mut volume = (volume * 114 / 100) as u8;
528 if volume > 0x67 {
529 volume = volume - 0x68;
530 } else {
531 volume = volume + 0x19;
532 }
533 volume
534 }
535 fn convert_beep_volume(&self, volume: u16) -> u8 {
536 let mut volume = (volume * 62 / 100) as u8;
537 if volume > 0x36 {
538 volume = volume - 0x37;
539 } else {
540 volume = volume + 0x07;
541 }
542 volume
543 }
544}
545
546#[derive(Debug, Clone, Copy, PartialEq)]
547#[cfg_attr(feature = "defmt", derive(defmt::Format))]
548pub enum OutputDevice {
552 Speaker,
554 Headphone,
556 Both,
558 Auto,
560}
561
562impl OutputDevice {
563 fn value(self) -> u8 {
564 match self {
565 Self::Speaker => 0xFA,
566 Self::Headphone => 0xAF,
567 Self::Both => 0xAA,
568 Self::Auto => 0x05,
569 }
570 }
571}
572
573impl From<OutputDevice> for u8 {
574 fn from(device: OutputDevice) -> Self {
575 device.value()
576 }
577}
578
579#[derive(Debug, Clone, Copy, PartialEq)]
581#[cfg_attr(feature = "defmt", derive(defmt::Format))]
582pub enum InterfaceFormat {
583 LeftJustified,
585 I2S,
587 RightJustified,
589}
590impl InterfaceFormat {
591 fn value(self) -> u8 {
592 match self {
593 Self::LeftJustified => 0x00,
594 Self::I2S => 0x01,
595 Self::RightJustified => 0x02,
596 }
597 }
598}
599impl From<InterfaceFormat> for u8 {
600 fn from(interface_format: InterfaceFormat) -> Self {
601 interface_format.value()
602 }
603}
604
605#[derive(Debug, Clone, Copy, PartialEq)]
607#[cfg_attr(feature = "defmt", derive(defmt::Format))]
608pub enum WordLength {
609 W16,
611 W20,
613 W24,
615 W32,
617}
618impl WordLength {
619 fn value(self) -> u8 {
620 match self {
621 Self::W16 => 0x03,
622 Self::W20 => 0x02,
623 Self::W24 => 0x01,
624 Self::W32 => 0x00,
625 }
626 }
627}
628impl From<WordLength> for u8 {
629 fn from(word_length: WordLength) -> Self {
630 word_length.value()
631 }
632}
633
634#[derive(Debug, Clone, Copy, PartialEq)]
635#[cfg_attr(feature = "defmt", derive(defmt::Format))]
636pub enum BeepPitch {
640 C4,
642 C5,
644 D5,
646 E5,
648 F5,
650 G5,
652 A5,
654 B5,
656 C6,
658 D6,
660 E6,
662 F6,
664 G6,
666 A6,
668 B6,
670 C7,
672}
673
674impl BeepPitch {
675 fn value(self) -> u8 {
676 match self {
677 Self::C4 => 0b0000,
678 Self::C5 => 0b0001,
679 Self::D5 => 0b0010,
680 Self::E5 => 0b0011,
681 Self::F5 => 0b0100,
682 Self::G5 => 0b0101,
683 Self::A5 => 0b0110,
684 Self::B5 => 0b0111,
685 Self::C6 => 0b1000,
686 Self::D6 => 0b1001,
687 Self::E6 => 0b1010,
688 Self::F6 => 0b1011,
689 Self::G6 => 0b1100,
690 Self::A6 => 0b1101,
691 Self::B6 => 0b1110,
692 Self::C7 => 0b1111,
693 }
694 }
695}
696
697impl From<BeepPitch> for u8 {
698 fn from(pitch: BeepPitch) -> Self {
699 pitch.value()
700 }
701}
702
703#[derive(Debug, Clone, Copy, PartialEq)]
705#[cfg_attr(feature = "defmt", derive(defmt::Format))]
706pub enum BeepOnTime {
707 _86ms,
709 _430ms,
711 _780ms,
713 _1200ms,
715 _1500ms,
717 _1800ms,
719 _2200ms,
721 _2500ms,
723 _2800ms,
725 _3200ms,
727 _3500ms,
729 _3800ms,
731 _4200ms,
733 _4500ms,
735 _4800ms,
737 _5200ms,
739}
740
741impl BeepOnTime {
742 fn value(self) -> u8 {
743 match self {
744 Self::_86ms => 0b0000,
745 Self::_430ms => 0b0001,
746 Self::_780ms => 0b0010,
747 Self::_1200ms => 0b0011,
748 Self::_1500ms => 0b0100,
749 Self::_1800ms => 0b0101,
750 Self::_2200ms => 0b0110,
751 Self::_2500ms => 0b0111,
752 Self::_2800ms => 0b1000,
753 Self::_3200ms => 0b1001,
754 Self::_3500ms => 0b1010,
755 Self::_3800ms => 0b1011,
756 Self::_4200ms => 0b1100,
757 Self::_4500ms => 0b1101,
758 Self::_4800ms => 0b1110,
759 Self::_5200ms => 0b1111,
760 }
761 }
762}
763
764impl From<BeepOnTime> for u8 {
765 fn from(time: BeepOnTime) -> Self {
766 time.value()
767 }
768}
769
770#[derive(Debug, Clone, Copy, PartialEq)]
772#[cfg_attr(feature = "defmt", derive(defmt::Format))]
773pub enum BeepOffTime {
774 _1230ms,
776 _2580ms,
778 _3900ms,
780 _5220ms,
782 _6600ms,
784 _8050ms,
786 _9350ms,
788 _10800ms,
790}
791
792impl BeepOffTime {
793 fn value(self) -> u8 {
794 match self {
795 Self::_1230ms => 0b000,
796 Self::_2580ms => 0b001,
797 Self::_3900ms => 0b010,
798 Self::_5220ms => 0b011,
799 Self::_6600ms => 0b100,
800 Self::_8050ms => 0b101,
801 Self::_9350ms => 0b110,
802 Self::_10800ms => 0b111,
803 }
804 }
805}
806
807impl From<BeepOffTime> for u8 {
808 fn from(time: BeepOffTime) -> Self {
809 time.value()
810 }
811}
812
813#[derive(Debug, Clone, Copy, PartialEq)]
815#[cfg_attr(feature = "defmt", derive(defmt::Format))]
816pub enum BeepMode {
817 Off,
819 Single,
821 Multiple,
823 Continuous,
825}
826impl BeepMode {
827 fn value(self) -> u8 {
828 match self {
829 Self::Off => 0b00,
830 Self::Single => 0b01,
831 Self::Multiple => 0b10,
832 Self::Continuous => 0b11,
833 }
834 }
835}
836
837impl From<BeepMode> for u8 {
838 fn from(mode: BeepMode) -> Self {
839 mode.value()
840 }
841}
842
843#[derive(Debug, Clone, Copy, PartialEq)]
847#[cfg_attr(feature = "defmt", derive(defmt::Format))]
848pub struct BeepConfig {
849 pitch: BeepPitch,
850 on_time: BeepOnTime,
851 off_time: BeepOffTime,
852 mode: BeepMode,
853 mix: bool,
854 volume: u16,
855}
856
857impl BeepConfig {
858 pub fn new() -> Self {
860 Self {
861 pitch: BeepPitch::C4,
862 on_time: BeepOnTime::_86ms,
863 off_time: BeepOffTime::_1230ms,
864 mode: BeepMode::Off,
865 mix: false,
866 volume: 70,
867 }
868 }
869
870 pub fn pitch(mut self, pitch: BeepPitch) -> Self {
872 self.pitch = pitch;
873 self
874 }
875
876 pub fn on_time(mut self, on_time: BeepOnTime) -> Self {
878 self.on_time = on_time;
879 self
880 }
881
882 pub fn off_time(mut self, off_time: BeepOffTime) -> Self {
884 self.off_time = off_time;
885 self
886 }
887
888 pub fn volume(mut self, volume: u16) -> Self {
890 self.volume = volume;
891 self
892 }
893
894 pub fn mode(mut self, mode: BeepMode) -> Self {
896 self.mode = mode;
897 self
898 }
899
900 pub fn mix(mut self, mix: bool) -> Self {
902 self.mix = mix;
903 self
904 }
905}
906
907impl Default for BeepConfig {
908 fn default() -> Self {
909 Self::new()
910 }
911}
912
913#[derive(Debug, Clone, Copy, PartialEq)]
916#[cfg_attr(feature = "defmt", derive(defmt::Format))]
917pub enum TrebleCutoff {
918 _5kHz,
920 _7kHz,
922 _10kHz,
924 _15kHz,
926}
927
928impl TrebleCutoff {
929 fn value(self) -> u8 {
930 match self {
931 Self::_5kHz => 0b00,
932 Self::_7kHz => 0b01,
933 Self::_10kHz => 0b10,
934 Self::_15kHz => 0b11,
935 }
936 }
937}
938
939impl From<TrebleCutoff> for u8 {
940 fn from(cutoff: TrebleCutoff) -> Self {
941 cutoff.value()
942 }
943}
944
945#[derive(Debug, Clone, Copy, PartialEq)]
948#[cfg_attr(feature = "defmt", derive(defmt::Format))]
949pub enum BassCutoff {
950 _50Hz,
952 _100Hz,
954 _200Hz,
956 _250Hz,
958}
959
960impl BassCutoff {
961 fn value(self) -> u8 {
962 match self {
963 Self::_50Hz => 0b00,
964 Self::_100Hz => 0b01,
965 Self::_200Hz => 0b10,
966 Self::_250Hz => 0b11,
967 }
968 }
969}
970
971impl From<BassCutoff> for u8 {
972 fn from(cutoff: BassCutoff) -> Self {
973 cutoff.value()
974 }
975}
976
977#[derive(Debug, Clone, Copy, PartialEq)]
980#[cfg_attr(feature = "defmt", derive(defmt::Format))]
981pub enum ToneGain {
982 _12dB,
984 _10_5dB,
986 _9dB,
988 _7_5dB,
990 _6dB,
992 _4_5dB,
994 _3dB,
996 _1_5dB,
998 _0dB,
1000 Min1_5dB,
1002 Min3dB,
1004 Min4_5dB,
1006 Min6dB,
1008 Min7_5dB,
1010 Min9dB,
1012 Min10_5dB,
1014}
1015
1016impl ToneGain {
1017 fn value(self) -> u8 {
1018 match self {
1019 Self::_12dB => 0b0000,
1020 Self::_10_5dB => 0b0001,
1021 Self::_9dB => 0b0010,
1022 Self::_7_5dB => 0b0011,
1023 Self::_6dB => 0b0100,
1024 Self::_4_5dB => 0b0101,
1025 Self::_3dB => 0b0110,
1026 Self::_1_5dB => 0b0111,
1027 Self::_0dB => 0b1000,
1028 Self::Min1_5dB => 0b1001,
1029 Self::Min3dB => 0b1010,
1030 Self::Min4_5dB => 0b1011,
1031 Self::Min6dB => 0b1100,
1032 Self::Min7_5dB => 0b1101,
1033 Self::Min9dB => 0b1110,
1034 Self::Min10_5dB => 0b1111,
1035 }
1036 }
1037}
1038
1039impl From<ToneGain> for u8 {
1040 fn from(gain: ToneGain) -> Self {
1041 gain.value()
1042 }
1043}
1044
1045#[derive(Debug, Clone, Copy, PartialEq)]
1050#[cfg_attr(feature = "defmt", derive(defmt::Format))]
1051pub enum PCMmix {
1052 Left,
1054 Half,
1056 Right,
1058}
1059
1060impl PCMmix {
1061 fn value(self) -> u8 {
1062 match self {
1063 Self::Left => 0b00,
1064 Self::Half => 0b01,
1065 Self::Right => 0b11,
1066 }
1067 }
1068}
1069
1070impl From<PCMmix> for u8 {
1071 fn from(mix: PCMmix) -> Self {
1072 mix.value()
1073 }
1074}