1use crate::{
2 BitFlags, Error, ErrorWithPin, OperationState, Register, SeekDirection, SeekFmImpulseThreshold,
3 SeekMode, SeekSnrThreshold, Si4703,
4};
5use embedded_hal::{blocking::i2c, digital::v2::InputPin};
6
7impl<I2C, E, IC> Si4703<I2C, IC>
8where
9 I2C: i2c::Write<Error = E> + i2c::Read<Error = E>,
10{
11 fn get_powercfg_for_seek_config(
12 powercfg: u16,
13 mode: SeekMode,
14 direction: SeekDirection,
15 ) -> u16 {
16 let powercfg = match mode {
17 SeekMode::Wrap => powercfg | BitFlags::SKMODE,
18 SeekMode::NoWrap => powercfg & !BitFlags::SKMODE,
19 };
20 match direction {
21 SeekDirection::Up => powercfg | BitFlags::SEEKUP,
22 SeekDirection::Down => powercfg & !BitFlags::SEEKUP,
23 }
24 }
25
26 pub fn configure_seek(
28 &mut self,
29 rssi_threshold: u8,
30 snr_threshold: SeekSnrThreshold,
31 fm_impulse_threshold: SeekFmImpulseThreshold,
32 ) -> Result<(), Error<E>> {
33 let snr_mask = match snr_threshold {
34 SeekSnrThreshold::Disabled => 0,
35 SeekSnrThreshold::Enabled(v) if v > 7 || v == 0 => return Err(Error::InvalidInputData),
36 SeekSnrThreshold::Enabled(v) => v << 4,
37 };
38 let cnt_mask = match fm_impulse_threshold {
39 SeekFmImpulseThreshold::Disabled => 0,
40 SeekFmImpulseThreshold::Enabled(v) if v > 15 || v == 0 => {
41 return Err(Error::InvalidInputData)
42 }
43 SeekFmImpulseThreshold::Enabled(v) => v,
44 };
45 let mut regs = self.read_registers()?;
46 regs[Register::SYSCONFIG2] &= 0xFF00;
47 regs[Register::SYSCONFIG2] |= u16::from(rssi_threshold) << 8;
48 regs[Register::SYSCONFIG3] &= 0xFF00;
49 regs[Register::SYSCONFIG3] |= u16::from(snr_mask | cnt_mask);
50 self.write_registers(®s[..=Register::SYSCONFIG3])
51 }
52
53 pub fn seek(&mut self, mode: SeekMode, direction: SeekDirection) -> nb::Result<(), Error<E>> {
58 let set_initial_value = |regs: &mut [u16; 16]| {
59 let powercfg = regs[Register::POWERCFG] | BitFlags::SEEK;
60 regs[Register::POWERCFG] =
61 Self::get_powercfg_for_seek_config(powercfg, mode, direction);
62 Ok(Register::POWERCFG)
63 };
64 let mut state = self.seeking_state;
65 let result = self.tune_seek(
66 Register::POWERCFG,
67 BitFlags::SEEK,
68 &mut state,
69 &set_initial_value,
70 );
71 self.seeking_state = state;
72 result
73 }
74
75 pub fn seek_with_stc_int_pin<PinE, P: InputPin<Error = PinE>>(
80 &mut self,
81 mode: SeekMode,
82 direction: SeekDirection,
83 stc_int_pin: &P,
84 ) -> nb::Result<(), ErrorWithPin<E, PinE>> {
85 if self.seeking_state == OperationState::Busy
86 && stc_int_pin
87 .is_high()
88 .map_err(ErrorWithPin::Pin)
89 .map_err(nb::Error::Other)?
90 {
91 Err(nb::Error::WouldBlock)
92 } else {
93 let set_initial_value = |regs: &mut [u16; 16]| {
94 let powercfg = regs[Register::POWERCFG] | BitFlags::SEEK;
95 regs[Register::POWERCFG] =
96 Self::get_powercfg_for_seek_config(powercfg, mode, direction);
97 let previous_sysconfig1 = regs[Register::SYSCONFIG1];
98 regs[Register::SYSCONFIG1] &= 0xFFF3;
99 regs[Register::SYSCONFIG1] |= 1 << 2;
100 regs[Register::SYSCONFIG1] |= BitFlags::STCIEN;
101 if previous_sysconfig1 != regs[Register::SYSCONFIG1] {
102 Ok(Register::SYSCONFIG1)
103 } else {
104 Ok(Register::POWERCFG)
105 }
106 };
107 let mut state = self.seeking_state;
108 let result = self.tune_seek(
109 Register::POWERCFG,
110 BitFlags::SEEK,
111 &mut state,
112 &set_initial_value,
113 );
114 self.seeking_state = state;
115 result.map_err(|e| match e {
116 nb::Error::Other(e) => nb::Error::Other(e.into()),
117 nb::Error::WouldBlock => nb::Error::WouldBlock,
118 })
119 }
120 }
121
122 pub(crate) fn tune_seek(
123 &mut self,
124 register: usize,
125 bitflag: u16,
126 state: &mut OperationState,
127 set_start_value: &dyn Fn(&mut [u16; 16]) -> Result<usize, Error<E>>,
128 ) -> nb::Result<(), Error<E>> {
129 let mut regs = self.read_registers()?;
130 let flag = (regs[register] & bitflag) != 0;
131 let stc = (regs[Register::STATUSRSSI] & BitFlags::STC) != 0;
132 let failed = (regs[Register::STATUSRSSI] & BitFlags::SF_BL) != 0;
133 let afcrl = (regs[Register::STATUSRSSI] & BitFlags::AFCRL) != 0;
134
135 match (*state, flag, stc) {
136 (OperationState::Idle, false, false) => {
137 let register = set_start_value(&mut regs)?;
138 self.write_registers(®s[..=register])?;
139 *state = OperationState::Busy;
140 Err(nb::Error::WouldBlock)
141 }
142 (OperationState::Busy, true, true) => {
143 regs[register] &= !bitflag;
144 self.write_registers(®s[..=register])?;
145 *state = OperationState::WaitingForStcToClear(!failed && !afcrl);
146 Err(nb::Error::WouldBlock)
147 }
148 (OperationState::WaitingForStcToClear(success), false, false) => {
149 *state = OperationState::Idle;
150 if success {
151 Ok(())
152 } else {
153 Err(nb::Error::Other(Error::SeekFailed))
154 }
155 }
156 (_, _, _) => Err(nb::Error::WouldBlock),
157 }
158 }
159}