kenwood_thd75/radio/
scan.rs

1//! Scan-related radio methods: scan resume (SR write-only), step size (SF), band scope (BS).
2//!
3//! # Single Band Display (per Operating Tips ยง5.10.4)
4//!
5//! Menu No. 904 controls the Single Band Display information line:
6//! Off, GPS (Altitude), GPS (Ground Speed), Date, or Demodulation Mode.
7
8use crate::error::{Error, ProtocolError};
9use crate::protocol::{Command, Response};
10use crate::transport::Transport;
11use crate::types::{Band, ScanResumeMethod, StepSize};
12
13use super::Radio;
14
15impl<T: Transport> Radio<T> {
16    /// Set the scan resume mode (SR write).
17    ///
18    /// Hardware-verified: bare `SR\r` returns `?` (no read form).
19    /// Sets the scan resume method (SR write).
20    ///
21    /// Firmware-verified: SR reads/writes scan resume configuration via
22    /// hardware registers, NOT a radio reset (previous documentation was wrong).
23    ///
24    /// # Errors
25    ///
26    /// Returns an error if the command fails or the response is unexpected.
27    pub async fn set_scan_resume(&mut self, mode: ScanResumeMethod) -> Result<(), Error> {
28        tracing::info!(?mode, "setting scan resume mode (SR)");
29        let response = self.execute(Command::SetScanResume { mode }).await?;
30        match response {
31            Response::Ok => Ok(()),
32            other => Err(Error::Protocol(ProtocolError::UnexpectedResponse {
33                expected: "Ok".into(),
34                actual: format!("{other:?}").into_bytes(),
35            })),
36        }
37    }
38
39    /// Get the step size for a band (SF read).
40    ///
41    /// Firmware-verified: SF = Step Size. `SF band\r` returns `SF band,step`.
42    ///
43    /// # Errors
44    ///
45    /// Returns an error if the command fails or the response is unexpected.
46    pub async fn get_step_size(&mut self, band: Band) -> Result<(Band, StepSize), Error> {
47        tracing::debug!(?band, "reading step size");
48        let response = self.execute(Command::GetStepSize { band }).await?;
49        match response {
50            Response::StepSize {
51                band: resp_band,
52                step,
53            } => Ok((resp_band, step)),
54            other => Err(Error::Protocol(ProtocolError::UnexpectedResponse {
55                expected: "StepSize".into(),
56                actual: format!("{other:?}").into_bytes(),
57            })),
58        }
59    }
60
61    /// Set the step size for a band (SF write).
62    ///
63    /// Firmware-verified: SF = Step Size. `SF band,step\r` (band 0-1, step 0-11).
64    ///
65    /// # Errors
66    ///
67    /// Returns an error if the command fails or the response is unexpected.
68    pub async fn set_step_size(&mut self, band: Band, step: StepSize) -> Result<(), Error> {
69        tracing::info!(?band, ?step, "setting step size");
70        let response = self.execute(Command::SetStepSize { band, step }).await?;
71        match response {
72            Response::StepSize { .. } => Ok(()),
73            other => Err(Error::Protocol(ProtocolError::UnexpectedResponse {
74                expected: "StepSize".into(),
75                actual: format!("{other:?}").into_bytes(),
76            })),
77        }
78    }
79
80    /// Get band scope data for a band (BS read).
81    ///
82    /// The radio echoes back the band number when queried.
83    ///
84    /// # Errors
85    ///
86    /// Returns an error if the command fails or the response is unexpected.
87    pub async fn get_band_scope(&mut self, band: Band) -> Result<Band, Error> {
88        tracing::debug!(?band, "reading band scope");
89        let response = self.execute(Command::GetBandScope { band }).await?;
90        match response {
91            Response::BandScope { band: scope_band } => Ok(scope_band),
92            other => Err(Error::Protocol(ProtocolError::UnexpectedResponse {
93                expected: "BandScope".into(),
94                actual: format!("{other:?}").into_bytes(),
95            })),
96        }
97    }
98
99    /// Set band scope configuration for a band (BS write).
100    ///
101    /// # Wire format
102    ///
103    /// `BS band,value\r` where band is 0 (A) or 1 (B). The exact meaning
104    /// of the value parameter is unknown.
105    ///
106    /// # Errors
107    ///
108    /// Returns an error if the command fails or the response is unexpected.
109    pub async fn set_band_scope(&mut self, band: Band, value: u8) -> Result<(), Error> {
110        tracing::info!(?band, value, "setting band scope configuration");
111        let response = self.execute(Command::SetBandScope { band, value }).await?;
112        match response {
113            Response::BandScope { .. } => Ok(()),
114            other => Err(Error::Protocol(ProtocolError::UnexpectedResponse {
115                expected: "BandScope".into(),
116                actual: format!("{other:?}").into_bytes(),
117            })),
118        }
119    }
120}