Radio

Struct Radio 

Source
pub struct Radio<T: Transport> { /* private fields */ }
Expand description

High-level async API for controlling a Kenwood TH-D75.

Generic over the transport layer — works with USB serial, Bluetooth SPP, or mock transport for testing.

The Radio struct tracks the VFO/Memory mode of each band when VM commands are sent through it, enabling mode-compatibility warnings. Use the safe tuning methods (tune_frequency, tune_channel) for automatic mode management.

Implementations§

Source§

impl<T: Transport> Radio<T>

Source

pub async fn get_tnc_baud(&mut self) -> Result<TncBaud, Error>

Get the TNC baud rate (AS read).

Returns 0 = 1200 baud, 1 = 9600 baud.

§Errors

Returns an error if the command fails or the response is unexpected.

Source

pub async fn get_beacon_type(&mut self) -> Result<BeaconMode, Error>

Get the beacon TX control mode (PT read).

Returns the current beacon transmission mode:

  • 0 = Off (no automatic beaconing)
  • 1 = Manual (beacon sent only when explicitly triggered)
  • 2 = PTT (beacon sent after each PTT release)
  • 3 = Auto (beacon sent at fixed intervals set by the beacon interval timer)
  • 4 = SmartBeaconing (adaptive beaconing based on speed and direction changes)
§Errors

Returns an error if the command fails or the response is unexpected.

Source

pub async fn get_position_source(&mut self) -> Result<u8, Error>

Get the APRS position source (MS read).

§Errors

Returns an error if the command fails or the response is unexpected.

Source

pub async fn set_tnc_baud(&mut self, rate: TncBaud) -> Result<(), Error>

Set the TNC baud rate (AS write).

Values: 0 = 1200 baud, 1 = 9600 baud.

§Errors

Returns an error if the command fails or the response is unexpected.

Source

pub async fn set_beacon_type(&mut self, mode: BeaconMode) -> Result<(), Error>

Set the beacon TX control mode (PT write).

See get_beacon_type for valid mode values and their meanings.

§Errors

Returns an error if the command fails or the response is unexpected.

Source

pub async fn send_message(&mut self, text: &str) -> Result<(), Error>

Send a message via the APRS/TNC interface (MS write).

§RF emission warning

This command causes the radio to transmit on the air. The TNC will key the transmitter and send an AX.25 packet containing the message on the currently configured APRS frequency. Ensure you are authorized to transmit on the current frequency before calling this method.

The transmission is a single packet burst (not continuous like transmit), but it still constitutes an RF emission that must comply with radio regulations.

§Errors

Returns an error if the command fails or the response is unexpected.

Source

pub async fn get_serial_info(&mut self) -> Result<(String, String), Error>

Get the radio’s serial number and model code (AE read).

Despite the AE mnemonic, this returns serial info, not APRS data. Returns (serial, model_code).

§Errors

Returns an error if the command fails or the response is unexpected.

Source§

impl<T: Transport> Radio<T>

Source

pub async fn get_af_gain(&mut self) -> Result<AfGainLevel, Error>

Get the AF gain level (AG read).

D75 RE: bare AG\r returns global gain level. Band-indexed read returns ?, so this is a global query.

§Errors

Returns an error if the command fails or the response is unexpected.

Source

pub async fn set_af_gain( &mut self, band: Band, level: AfGainLevel, ) -> Result<(), Error>

Set the AF gain level (AG write).

§Get/set asymmetry

The get and set commands have different wire formats on the D75:

  • Read (AG\r): bare command, returns a global gain level. Band-indexed read (AG 0\r) returns ?.
  • Write (AG NNN\r): bare 3-digit zero-padded value (e.g., AG 015\r). Despite the band parameter in this method’s signature, the wire format is bare (no band index) — the value applies globally.
§Valid range

level must be 0 through 99. The wire format zero-pads to 3 digits (e.g., AG 005\r). Values outside 0-99 may be rejected or cause unexpected behavior.

§Errors

Returns an error if the command fails or the response is unexpected.

Source

pub async fn get_tnc_mode(&mut self) -> Result<(TncMode, TncBaud), Error>

Get the TNC mode (TN bare read).

Hardware-verified: bare TN\r returns TN mode,setting. Returns (mode, setting).

Valid mode values per firmware validation: 0, 1, 2, 3. Mode 3 may correspond to MMDVM or Reflector Terminal mode.

§Errors

Returns an error if the command fails or the response is unexpected.

Source

pub async fn set_tnc_mode( &mut self, mode: TncMode, setting: TncBaud, ) -> Result<(), Error>

Set the TNC mode (TN write).

Valid mode values per firmware validation: 0, 1, 2, 3. Mode 3 may correspond to MMDVM or Reflector Terminal mode.

§Wire format

TN mode,setting\r.

§Errors

Returns an error if the command fails or the response is unexpected.

Source

pub async fn get_dstar_callsign( &mut self, slot: DstarSlot, ) -> Result<(String, String), Error>

Get D-STAR callsign data for a slot (DC read).

Hardware-verified: DC slot\r where slot is 1-6. Returns (callsign, suffix).

Note: This method lives in audio.rs rather than dstar.rs because it was discovered during audio subsystem hardware probing. The DC mnemonic is overloaded on the D75 (DCS code, not D-STAR callsign as on D74).

§Errors

Returns an error if the command fails or the response is unexpected.

Source

pub async fn set_dstar_callsign( &mut self, slot: DstarSlot, callsign: &str, suffix: &str, ) -> Result<(), Error>

Set D-STAR callsign data for a slot (DC write).

Writes callsign and suffix data to one of the 6 D-STAR callsign slots.

§Wire format

DC slot,callsign,suffix\r where slot is 1-6, callsign is 8 characters (space-padded), and suffix is up to 4 characters.

§Parameters
  • slot: Callsign slot number (1-6).
  • callsign: Callsign string (8 characters, space-padded to length).
  • suffix: Callsign suffix (up to 4 characters, e.g., “D75A”).
§Errors

Returns an error if the command fails or the response is unexpected.

Source

pub async fn get_real_time_clock(&mut self) -> Result<String, Error>

Get the real-time clock (RT bare read).

Note: This method lives in audio.rs rather than system.rs because RT is overloaded on the D75 (repeater tone vs real-time clock on D74). It was discovered during audio subsystem probing.

Hardware-verified: bare RT\r returns RT YYMMDDHHmmss.

§Errors

Returns an error if the command fails or the response is unexpected.

Source

pub async fn get_vox(&mut self) -> Result<bool, Error>

Get the VOX (Voice-Operated Exchange/Transmit) enabled state (VX read).

VOX allows hands-free transmit operation. When enabled, the radio automatically keys the transmitter when it detects audio input from the microphone, and returns to receive after a configurable delay when audio stops.

VOX must be enabled before get_vox_gain or get_vox_delay will succeed — those commands return N (not available) when VOX is disabled.

§Errors

Returns an error if the command fails or the response is unexpected.

Source

pub async fn set_vox(&mut self, enabled: bool) -> Result<(), Error>

Set the VOX (Voice-Operated Exchange/Transmit) enabled state (VX write).

See get_vox for a description of VOX operation. Enabling VOX (true) unlocks the set_vox_gain and set_vox_delay commands. Disabling VOX (false) causes those commands to return N (not available).

§Errors

Returns an error if the command fails or the response is unexpected.

Source

pub async fn get_vox_gain(&mut self) -> Result<VoxGain, Error>

Get the VOX gain level (VG read).

§Mode requirement

VOX must be enabled (VX 1) for VG read to succeed. Returns N (not available) when VOX is off.

§Errors

Returns an error if the command fails or the response is unexpected.

Source

pub async fn set_vox_gain(&mut self, gain: VoxGain) -> Result<(), Error>

Set the VOX gain level (VG write).

§Mode requirement

VOX must be enabled (VX 1) for VG write to succeed. Returns N (not available) when VOX is off.

§Errors

Returns an error if the command fails or the response is unexpected.

Source

pub async fn get_vox_delay(&mut self) -> Result<VoxDelay, Error>

Get the VOX delay value (VD read).

§Mode requirement

VOX must be enabled (VX 1) for VD read to succeed. Returns N (not available) when VOX is off.

§Errors

Returns an error if the command fails or the response is unexpected.

Source

pub async fn set_vox_delay(&mut self, delay: VoxDelay) -> Result<(), Error>

Set the VOX delay value (VD write).

§Mode requirement

VOX must be enabled (VX 1) for VD write to succeed. Returns N (not available) when VOX is off.

§Errors

Returns an error if the command fails or the response is unexpected.

Source§

impl<T: Transport> Radio<T>

Source

pub async fn get_dstar_slot(&mut self) -> Result<DstarSlot, Error>

Get the active D-STAR callsign slot (DS read).

§Errors

Returns an error if the command fails or the response is unexpected.

Source

pub async fn get_active_callsign_slot(&mut self) -> Result<CallsignSlot, Error>

Get the active callsign slot number (CS bare read).

CS returns a slot number (0-10), NOT the callsign text itself. The actual callsign text is accessible via the CS callsign slots.

§Errors

Returns an error if the command fails or the response is unexpected.

Source

pub async fn set_active_callsign_slot( &mut self, slot: CallsignSlot, ) -> Result<(), Error>

Set the active callsign slot (CS write).

Selects which callsign slot is active. The callsign text itself is read via DC (D-STAR callsign) slots 1-6.

§Errors

Returns an error if the command fails or the response is unexpected.

Source

pub async fn set_dstar_slot(&mut self, slot: DstarSlot) -> Result<(), Error>

Set the active D-STAR callsign slot (DS write).

§Errors

Returns an error if the command fails or the response is unexpected.

Source

pub async fn get_gateway(&mut self) -> Result<DvGatewayMode, Error>

Get the gateway value (GW read).

§Errors

Returns an error if the command fails or the response is unexpected.

Source

pub async fn set_gateway(&mut self, value: DvGatewayMode) -> Result<(), Error>

Set the gateway value (GW write).

§Errors

Returns an error if the command fails or the response is unexpected.

Source

pub async fn get_urcall(&mut self) -> Result<(String, String), Error>

Read the current URCALL (destination) callsign from slot 1.

In D-STAR, the URCALL field determines the routing behaviour of your transmission (per User Manual Chapter 16):

  • "CQCQCQ " — general CQ call (local or via gateway)
  • A specific callsign — callsign routing through the D-STAR network
  • A reflector command — link/unlink/info/echo operations

Returns (callsign, suffix) where both are as stored on the radio (8-char callsign, up to 4-char suffix).

§Errors

Returns an error if the command fails or the response is unexpected.

Source

pub async fn set_urcall( &mut self, callsign: &str, suffix: &str, ) -> Result<(), Error>

Set the URCALL (destination) callsign in slot 1.

The URCALL field controls D-STAR routing behaviour. Common values:

  • CQ call: set_urcall("CQCQCQ", "") — general call
  • Callsign routing: set_urcall("KQ4NIT", "") — route to a station
  • Reflector link: set_urcall("REF030", "CL") — connect module C, link
  • Reflector unlink: set_urcall(" U", "") — 7 spaces + U

The callsign is space-padded to 8 characters and the suffix to 4 characters before writing to the radio.

§Errors

Returns an error if the callsign exceeds 8 characters, the suffix exceeds 4 characters, or the command fails.

Source

pub async fn get_rpt1(&mut self) -> Result<(String, String), Error>

Read the RPT1 (access repeater) callsign from slot 2.

RPT1 is the local repeater that your radio transmits to. In the D-STAR routing model, RPT1 receives your signal over RF and either plays it locally or forwards it to RPT2 for gateway routing.

Returns (callsign, suffix).

§Errors

Returns an error if the command fails or the response is unexpected.

Source

pub async fn set_rpt1( &mut self, callsign: &str, suffix: &str, ) -> Result<(), Error>

Set the RPT1 (access repeater) callsign in slot 2.

RPT1 should be set to the callsign of your local D-STAR repeater’s RF module (e.g. "W4BFB C" for a 2m module). The module letter is part of the 8-character callsign field, not the suffix.

The callsign is space-padded to 8 characters and the suffix to 4 characters before writing.

§Errors

Returns an error if the callsign exceeds 8 characters, the suffix exceeds 4 characters, or the command fails.

Source

pub async fn get_rpt2(&mut self) -> Result<(String, String), Error>

Read the RPT2 (gateway repeater) callsign from slot 3.

RPT2 is the gateway repeater that forwards your signal to the D-STAR network. For gateway-linked calls, RPT2 is typically the repeater’s gateway callsign (module G). For local-only calls, RPT2 can be left blank or set to the same repeater.

Returns (callsign, suffix).

§Errors

Returns an error if the command fails or the response is unexpected.

Source

pub async fn set_rpt2( &mut self, callsign: &str, suffix: &str, ) -> Result<(), Error>

Set the RPT2 (gateway repeater) callsign in slot 3.

For gateway-linked operation, set RPT2 to the repeater’s gateway module (e.g. "W4BFB G"). For local-only simplex or repeater use, RPT2 can be blank.

The callsign is space-padded to 8 characters and the suffix to 4 characters before writing.

§Errors

Returns an error if the callsign exceeds 8 characters, the suffix exceeds 4 characters, or the command fails.

Source

pub async fn connect_reflector( &mut self, reflector: &str, module: char, ) -> Result<(), Error>

Connect to a D-STAR reflector.

Sets the URCALL field to the reflector callsign with a link suffix, which instructs the gateway to link to the specified reflector module. The operator must then key up (transmit briefly) to trigger the link command.

§Parameters
  • reflector: Reflector callsign, e.g. "REF030", "XLX390", "DCS006". Padded to 8 characters.
  • module: The reflector module letter, e.g. 'C' for module C.
§Wire encoding

URCALL is set to the reflector callsign (8 chars) and the suffix is set to "{module}L " (module letter + ‘L’ for link, space-padded to 4 chars). For example, connect_reflector("REF030", 'C') sets URCALL to "REF030 " with suffix "CL ".

§Errors

Returns an error if the reflector callsign exceeds 8 characters, or the command fails.

Source

pub async fn disconnect_reflector(&mut self) -> Result<(), Error>

Disconnect from the current D-STAR reflector.

Sets URCALL to the unlink command (" U" — 7 spaces followed by ‘U’) with a blank suffix. The operator must then key up to trigger the unlink.

§Errors

Returns an error if the command fails.

Source

pub async fn set_cq(&mut self) -> Result<(), Error>

Set URCALL to CQCQCQ for a general CQ call.

This configures the radio for a local or gateway CQ call. Whether the call goes through the gateway depends on the RPT2 setting: if RPT2 is set to the gateway module (G), the call is relayed to all linked stations/reflectors.

§Errors

Returns an error if the command fails.

Source

pub async fn route_to_callsign(&mut self, callsign: &str) -> Result<(), Error>

Set URCALL for callsign routing (individual call).

Routes your transmission to a specific station through the D-STAR network. The gateway will look up the destination callsign in the D-STAR registration database and forward your audio to the last repeater the target station was heard on.

RPT2 must be set to the gateway module for routing to work.

§Errors

Returns an error if the callsign exceeds 8 characters or the command fails.

Source§

impl<T: Transport> Radio<T>

Source

pub async fn get_frequency( &mut self, band: Band, ) -> Result<ChannelMemory, Error>

Read the current frequency data for the given band (FQ read).

§Errors

Returns an error if the command fails or the response is unexpected.

Source

pub async fn get_frequency_full( &mut self, band: Band, ) -> Result<ChannelMemory, Error>

Read the full frequency and settings for the given band (FO read).

§Errors

Returns an error if the command fails or the response is unexpected.

Source

pub async fn set_frequency_full( &mut self, band: Band, channel: &ChannelMemory, ) -> Result<(), Error>

Write full frequency and settings for the given band (FO write).

Sends the full channel configuration (frequency, offset, tone mode, CTCSS/DCS codes, shift direction, and other fields) to the radio for the specified band.

§VFO mode requirement

The target band must be in VFO mode (VM band,0). If the band is in Memory, Call, or WX mode, the radio returns ? and the write is silently rejected. Use set_vfo_memory_mode to switch to VFO first, or prefer tune_frequency() which handles mode management safely.

§Wire format

FO band,freq,step,shift,reverse,tone_status,ctcss_status,dcs_status,tone_freq,ctcss_freq,dcs_code,offset,...\r

The full FO command encodes all 21 fields of the ChannelMemory struct as comma-separated values.

§Errors

Returns an error if the command fails or the response is unexpected.

Source

pub async fn get_mode(&mut self, band: Band) -> Result<Mode, Error>

Get the operating mode for the given band (MD read).

§Errors

Returns an error if the command fails or the response is unexpected.

Source

pub async fn set_mode(&mut self, band: Band, mode: Mode) -> Result<(), Error>

Set the operating mode for the given band (MD write).

§Band restrictions

SSB (LSB/USB), CW, and AM modes are only available on Band B. Attempting to set these modes on Band A will return ?. FM, NFM, DV, and DR modes are available on both bands.

See the Mode type for valid values. Note that the MD command uses a different encoding than FO/ME commands — the Mode type handles this mapping internally.

§Errors

Returns an error if the command fails or the response is unexpected.

Source

pub async fn get_power_level(&mut self, band: Band) -> Result<PowerLevel, Error>

Get the power level for the given band (PC read).

§Errors

Returns an error if the command fails or the response is unexpected.

Source

pub async fn set_power_level( &mut self, band: Band, level: PowerLevel, ) -> Result<(), Error>

Set the power level for the given band (PC write).

§Errors

Returns an error if the command fails or the response is unexpected.

Source

pub async fn get_squelch(&mut self, band: Band) -> Result<SquelchLevel, Error>

Get the squelch level for the given band (SQ read).

§Errors

Returns an error if the command fails or the response is unexpected.

Source

pub async fn set_squelch( &mut self, band: Band, level: SquelchLevel, ) -> Result<(), Error>

Set the squelch level for the given band (SQ write).

§Valid range

level must be 0 through 6 on the TH-D75. Values outside this range cause the radio to return ? and the write is rejected. Level 0 means squelch is fully open (all signals pass); level 6 is the tightest squelch setting.

§Wire format

SQ band,level\r where band is 0 (A) or 1 (B) and level is a single digit 0-6.

§Errors

Returns an error if the command fails or the response is unexpected.

Source

pub async fn get_smeter(&mut self, band: Band) -> Result<SMeterReading, Error>

Get the S-meter reading for the given band (SM read).

Returns an instantaneous signal strength measurement as a raw value 0-5. This is a read-only, point-in-time snapshot — the value changes continuously as signal conditions vary.

§Value mapping

The raw values map to approximate S-meter readings:

RawS-meter
0S0 (no signal)
1S1
2S3
3S5
4S7
5S9 (full scale)
§Polling warning

Do not poll SM continuously — the firmware returns spurious spikes on Band B. Instead, use AI mode (set_auto_info) with the BY (busy) signal as a gate: read SM once when squelch opens, and treat it as zero when squelch is closed.

§Wire format

SM band\r returns SM band,level\r.

§Errors

Returns an error if the command fails or the response is unexpected.

Source

pub async fn get_busy(&mut self, band: Band) -> Result<bool, Error>

Get the busy state for the given band (BY read).

“Busy” means the squelch is open — a signal strong enough to exceed the current squelch threshold is present on the channel. Returns true when the squelch is open (signal present), false when closed (no signal or signal below threshold).

§Wire format

BY band\r returns BY band,state\r where state is 0 (not busy / squelch closed) or 1 (busy / squelch open).

§Errors

Returns an error if the command fails or the response is unexpected.

Source

pub async fn transmit(&mut self, band: Band) -> Result<(), Error>

Switch the given band to transmit mode (TX action).

§RF emission warning

This keys the transmitter and causes RF emission on the currently tuned frequency. The radio will transmit continuously until receive is called. Ensure you are authorized to transmit on the current frequency before calling this method. Unauthorized transmission is a violation of radio regulations (e.g., FCC Part 97 in the US).

Always call receive when done to return to receive mode. If your program panics or is interrupted while transmitting, the radio will continue to transmit until manually stopped or the timeout (if any) expires.

§Wire format

TX band\r where band is 0 (A) or 1 (B). Returns OK\r on success.

§Errors

Returns an error if the command fails or the response is unexpected.

Source

pub async fn receive(&mut self, band: Band) -> Result<(), Error>

Switch the given band to receive mode (RX action).

Stops transmitting and returns the radio to receive mode. This is the counterpart to transmit and must be called after transmitting to stop RF emission.

§Wire format

RX band\r where band is 0 (A) or 1 (B). Returns OK\r on success.

§Errors

Returns an error if the command fails or the response is unexpected.

Source

pub async fn get_firmware_version(&mut self) -> Result<String, Error>

Get the firmware version string (FV read).

§Errors

Returns an error if the command fails or the response is unexpected.

Source

pub async fn get_power_status(&mut self) -> Result<bool, Error>

Get the power on/off status (PS read).

§Errors

Returns an error if the command fails or the response is unexpected.

Source

pub async fn get_radio_id(&mut self) -> Result<String, Error>

Get the radio model identification string (ID read).

§Errors

Returns an error if the command fails or the response is unexpected.

Source

pub async fn get_band(&mut self) -> Result<Band, Error>

Get the current active band (BC read).

§Errors

Returns an error if the command fails or the response is unexpected.

Source

pub async fn set_band(&mut self, band: Band) -> Result<(), Error>

Set the active band (BC write).

§Warning

This is an ACTION command that switches the radio’s active band.

§Errors

Returns an error if the command fails or the response is unexpected.

Source

pub async fn get_vfo_memory_mode( &mut self, band: Band, ) -> Result<VfoMemoryMode, Error>

Get the VFO/Memory mode for a band (VM read).

Returns a mode index: 0 = VFO, 1 = Memory, 2 = Call, 3 = WX.

§Errors

Returns an error if the command fails or the response is unexpected.

Source

pub async fn set_vfo_memory_mode( &mut self, band: Band, mode: VfoMemoryMode, ) -> Result<(), Error>

Set the VFO/Memory mode for a band (VM write).

Mode values: 0 = VFO, 1 = Memory, 2 = Call, 3 = WX.

§Errors

Returns an error if the command fails or the response is unexpected.

Source

pub async fn get_current_channel(&mut self, band: Band) -> Result<u16, Error>

Get the current memory channel number for a band (MR read).

Hardware-verified: MR band\r returns MR bandCCC where CCC is the channel number. This is a read that queries which channel is active, not an action that changes the channel.

§Errors

Returns an error if the command fails or the response is unexpected.

Source

pub async fn recall_channel( &mut self, band: Band, channel: u16, ) -> Result<(), Error>

Recall a memory channel on the given band (MR action).

This is an ACTION command that switches the radio’s active channel. The previous channel selection is not preserved.

§Errors

Returns an error if the command fails or the response is unexpected.

Source

pub async fn frequency_up(&mut self, band: Band) -> Result<(), Error>

Step the frequency up by one increment on the given band (UP action).

This is an ACTION command that changes the radio’s active frequency. There is no undo — the previous frequency is not preserved.

§Errors

Returns an error if the command fails or the response is unexpected.

Source

pub async fn get_fm_radio(&mut self) -> Result<bool, Error>

Get the FM broadcast radio on/off state (FR read).

§Errors

Returns an error if the command fails or the response is unexpected.

Source

pub async fn set_fm_radio(&mut self, enabled: bool) -> Result<(), Error>

Set the FM broadcast radio on/off state (FR write).

This controls the broadcast FM receiver (76-108 MHz), not amateur FM mode. This is the same as the “FM Radio” menu item on the radio — it tunes to commercial broadcast stations.

§Side effects

Enabling the FM broadcast receiver takes over the display and audio output. The radio’s normal amateur band display is replaced with the broadcast FM frequency. Normal band receive audio is muted while the FM broadcast receiver is active. Disable it to return to normal amateur radio operation.

§Errors

Returns an error if the command fails or the response is unexpected.

Source

pub async fn get_fine_step(&mut self) -> Result<FineStep, Error>

Get the fine step setting (FS bare read).

Firmware-verified: FS = Fine Step. Bare FS\r returns a single value (0-3). No band parameter — the radio returns a global fine step setting.

§Errors

Returns an error if the command fails or the response is unexpected.

Source

pub async fn set_fine_step( &mut self, band: Band, step: FineStep, ) -> Result<(), Error>

Set the fine step for a band (FS write).

Firmware-verified: FS band,step\r (band 0-1, step 0-3).

§Firmware bug (v1.03)

FS write is broken on firmware 1.03 — the radio returns N (not available) for all write attempts.

§Errors

Returns an error if the command fails or the response is unexpected.

Source

pub async fn get_function_type(&mut self) -> Result<bool, Error>

Get the function type value (FT read).

§Errors

Returns an error if the command fails or the response is unexpected.

Source

pub async fn set_function_type(&mut self, enabled: bool) -> Result<(), Error>

Set fine tune on/off (FT write).

Per Operating Tips section 5.10.6: Fine Tune only works with AM modulation and Band B.

§Wire format

FT value\r where value is 0 (off) or 1 (on). This is a global toggle (no band parameter). Confirmed by ARFC-D75 decompilation and firmware handler analysis (accepts only 5-byte commands: FT N\r).

§Errors

Returns an error if the command fails or the response is unexpected.

Source

pub async fn set_smeter( &mut self, band: Band, level: SMeterReading, ) -> Result<(), Error>

Set the S-meter value for a band (SM write) – calibration/test interface.

§Warning

This is likely a calibration or test/debug interface. Setting the S-meter value directly may interfere with normal signal strength readings. The exact behavior and persistence of written values is undocumented.

§Wire format

SM band,level\r where band is 0 (A) or 1 (B) and level is a hex nibble value.

§Errors

Returns an error if the command fails or the response is unexpected.

Source

pub async fn set_busy(&mut self, band: Band, busy: bool) -> Result<(), Error>

Set the busy/squelch state for a band (BY write) – test/debug interface.

§Warning

This is likely a test or debug interface. Setting the busy state directly may interfere with normal squelch operation. Use with caution.

§Wire format

BY band,state\r where band is 0 (A) or 1 (B) and state is 0 (not busy) or 1 (busy).

§Errors

Returns an error if the command fails or the response is unexpected.

Source

pub async fn set_firmware_version(&mut self, version: &str) -> Result<(), Error>

Set the firmware version string (FV write) – factory programming command.

§Safety

DANGEROUS FACTORY COMMAND. This is intended for factory programming only. Writing an incorrect firmware version string may brick the radio, cause firmware validation failures, or void your warranty. Do not use unless you fully understand the consequences.

§Wire format

FV version\r.

§Errors

Returns an error if the command fails or the response is unexpected.

Source

pub async fn set_radio_id(&mut self, model: &str) -> Result<(), Error>

Set the radio model identification string (ID write) – factory programming command.

§Safety

DANGEROUS FACTORY COMMAND. This is intended for factory programming only. Writing an incorrect model ID may cause the radio to behave as a different model, disable features, or brick the device. Do not use unless you fully understand the consequences.

§Wire format

ID model\r.

§Errors

Returns an error if the command fails or the response is unexpected.

Source

pub async fn get_filter_width( &mut self, mode: FilterMode, ) -> Result<FilterWidthIndex, Error>

Get the filter width for a given mode index (SH read).

mode_index: 0 = SSB, 1 = CW, 2 = AM.

§Errors

Returns an error if the command fails or the response is unexpected.

Source

pub async fn set_filter_width( &mut self, mode: FilterMode, width: FilterWidthIndex, ) -> Result<(), Error>

Set the filter width for a given mode index (SH write).

mode_index: 0 = SSB, 1 = CW, 2 = AM. The width value selects from the available filter options for that mode (per Operating Tips §5.10.1–§5.10.3).

§Errors

Returns an error if the command fails or the response is unexpected.

Source§

impl<T: Transport> Radio<T>

Source

pub async fn get_gps_config(&mut self) -> Result<(bool, bool), Error>

Get GPS configuration (GP read).

Returns (gps_enabled, pc_output).

§Errors

Returns an error if the command fails or the response is unexpected.

Source

pub async fn get_gps_sentences( &mut self, ) -> Result<(bool, bool, bool, bool, bool, bool), Error>

Get GPS NMEA sentence enable flags (GS read).

Returns (gga, gll, gsa, gsv, rmc, vtg) — six booleans indicating which NMEA 0183 sentence types are enabled for output when pc_output is active.

§Sentence types
  • GGA (Global Positioning System Fix Data): time, position, fix quality, number of satellites, HDOP, altitude. The primary fix sentence.
  • GLL (Geographic Position - Latitude/Longitude): position and time, simpler than GGA.
  • GSA (GNSS DOP and Active Satellites): fix type (2D/3D), satellite IDs in use, PDOP/HDOP/VDOP dilution of precision values.
  • GSV (GNSS Satellites in View): satellite count, PRN numbers, elevation, azimuth, and SNR for each satellite. Multiple sentences for all visible satellites.
  • RMC (Recommended Minimum Navigation Information): time, position, speed over ground, course, date, magnetic variation. The most commonly used sentence.
  • VTG (Course Over Ground and Ground Speed): track (true and magnetic) and speed (knots and km/h).
§Errors

Returns an error if the command fails or the response is unexpected.

Source

pub async fn set_gps_config( &mut self, gps_enabled: bool, pc_output: bool, ) -> Result<(), Error>

Set GPS configuration (GP write).

  • gps_enabled: turns the GPS receiver on or off. When off, no position fix is available for APRS beaconing or display.
  • pc_output: when true, the radio outputs raw NMEA sentences over the serial connection (USB or Bluetooth SPP). This competes with CAT command I/O — NMEA data will be interleaved with CAT responses on the same serial channel, which can confuse the protocol parser. Only enable this if you are prepared to handle mixed NMEA/CAT traffic, or if you are using the serial port exclusively for GPS data.
§Errors

Returns an error if the command fails or the response is unexpected.

Source

pub async fn set_gps_sentences( &mut self, gga: bool, gll: bool, gsa: bool, gsv: bool, rmc: bool, vtg: bool, ) -> Result<(), Error>

Set GPS NMEA sentence enable flags (GS write).

Sets 6 boolean flags controlling which NMEA sentences are output: GGA, GLL, GSA, GSV, RMC, VTG.

§Errors

Returns an error if the command fails or the response is unexpected.

Source

pub async fn get_gps_mode(&mut self) -> Result<GpsRadioMode, Error>

Get GPS/Radio mode status (GM bare read).

Returns the current GPS/Radio operating mode. Normal (0) means standard transceiver operation. GpsReceiver (1) means GPS-only mode.

§Warning

Only the bare GM\r read is safe. Sending GM 1\r would reboot the radio into GPS-only mode. This method only sends the bare read.

§Errors

Returns an error if the command fails or the response is unexpected.

Source§

impl<T: Transport> Radio<T>

Source

pub async fn enter_kiss( self, baud: TncBaud, ) -> Result<KissSession<T>, (Self, Error)>

Enter KISS mode, consuming this Radio and returning a KissSession.

Sends the TN 2,x CAT command to switch the TNC to KISS mode at the specified baud rate. After this call, the serial port speaks KISS binary framing. Use KissSession::exit to return to CAT mode.

§Errors

On failure, returns the Radio alongside the error so the caller can continue using CAT mode. The radio is NOT consumed on error.

Source§

impl<T: Transport> Radio<T>

Source

pub async fn read_channel( &mut self, channel: u16, ) -> Result<ChannelMemory, Error>

Read a memory channel by number (ME read).

§Errors

Returns an error if the command fails or the response is unexpected.

Source

pub async fn read_channels( &mut self, range: Range<u16>, ) -> Result<Vec<(u16, ChannelMemory)>, Error>

Read multiple memory channels efficiently.

Reads channels in the given range and returns only occupied channels (skips channels that return N/not available).

§Errors

Returns an error if a transport or protocol error occurs (other than the radio returning N for an empty channel).

Source

pub async fn write_channel( &mut self, channel: u16, data: &ChannelMemory, ) -> Result<(), Error>

Write a memory channel by number (ME write).

§Errors

Returns an error if the command fails or the response is unexpected.

Source§

impl<T: Transport + Unpin + 'static> Radio<T>

Source

pub fn into_mmdvm_session(self) -> MmdvmSession<T>

Wrap this Radio as an MmdvmSession without sending any commands.

Use this when the radio is already in MMDVM mode (e.g. after enabling DV Gateway / Reflector Terminal Mode via MCP write to offset 0x1CA0). The transport is assumed to already speak MMDVM binary framing.

Source

pub async fn enter_mmdvm( self, baud: TncBaud, ) -> Result<MmdvmSession<T>, (Self, Error)>

Enter MMDVM mode, consuming this Radio and returning an MmdvmSession.

Sends the TN 3,x CAT command to switch the TNC to MMDVM mode at the specified baud rate. After this call, the serial port speaks MMDVM binary framing. Use MmdvmSession::exit to return to CAT mode.

§Errors

On failure, returns the Radio alongside the error so the caller can continue using CAT mode. The radio is NOT consumed on error.

Source§

impl<T: Transport> Radio<T>

Source

pub async fn read_memory_image(&mut self) -> Result<Vec<u8>, Error>

Read the entire radio memory image (500,480 bytes).

Enters programming mode, reads all 1,955 pages, and exits. This takes approximately 55 seconds at 9600 baud.

§Errors

Returns an error if entry, any page read, or exit fails. Programming mode is always exited, even on error.

Source

pub async fn read_memory_image_with_progress<F>( &mut self, on_progress: F, ) -> Result<Vec<u8>, Error>
where F: FnMut(u16, u16),

Read the entire radio memory image with a progress callback.

The callback receives (current_page, total_pages) after each page is read, allowing progress display for the ~55-second dump.

§Errors

Returns an error if entry, any page read, or exit fails. Programming mode is always exited, even on error.

Source

pub async fn write_memory_image(&mut self, image: &[u8]) -> Result<(), Error>

Write a complete memory image back to the radio.

WARNING: This overwrites ALL radio settings except factory calibration (last 2 pages). The image must be exactly 500,480 bytes.

§Errors

Returns Error::InvalidImageSize if the image is the wrong size. Returns an error if entry, any page write, or exit fails. Programming mode is always exited, even on error.

Source

pub async fn write_memory_image_with_progress<F>( &mut self, image: &[u8], on_progress: F, ) -> Result<(), Error>
where F: FnMut(u16, u16),

Write a complete memory image with a progress callback.

The callback receives (current_page, total_pages) after each page is written.

§Errors

Returns Error::InvalidImageSize if the image is the wrong size. Returns an error if entry, any page write, or exit fails. Programming mode is always exited, even on error.

Source

pub async fn read_memory_pages( &mut self, start_page: u16, count: u16, ) -> Result<Vec<u8>, Error>

Read a range of pages from radio memory.

Enters programming mode, reads count pages starting at start_page, and exits. Returns the raw bytes.

§Errors

Returns an error if entry, any page read, or exit fails. Programming mode is always exited, even on error.

Source

pub async fn write_memory_pages( &mut self, start_page: u16, data: &[u8], ) -> Result<(), Error>

Write a range of pages to radio memory.

Enters programming mode, writes pages starting at start_page with the provided data, and exits. The data length must be a multiple of 256 (one or more full pages).

§Errors

Returns Error::MemoryWriteProtected if any target page falls within the factory calibration region. Returns an error if entry, any page write, or exit fails. Programming mode is always exited, even on error.

Source

pub async fn read_page(&mut self, page: u16) -> Result<[u8; 256], Error>

Read a single memory page (256 bytes).

Enters programming mode, reads the page, and exits.

§Errors

Returns an error if entry, the page read, or exit fails. Programming mode is always exited, even on error.

Source

pub async fn write_page( &mut self, page: u16, data: &[u8; 256], ) -> Result<(), Error>

Write a single memory page (256 bytes).

Enters programming mode, writes the page, and exits.

§Errors

Returns Error::MemoryWriteProtected if the page is in the factory calibration region. Returns an error if entry, the page write, or exit fails. Programming mode is always exited, even on error.

Source

pub async fn modify_memory_page<F>( &mut self, page: u16, modify: F, ) -> Result<(), Error>
where F: FnOnce(&mut [u8; 256]),

Read a memory page, apply in-place modifications, and write it back in a single MCP programming session.

This is the key primitive for changing individual settings via MCP without reading or writing the entire 500 KB image. The three steps (read, modify, write) happen inside one programming mode session so the radio only enters and exits MCP mode once.

§Connection lifetime

The USB connection does not survive the programming mode transition. After this method returns, the Radio instance should be dropped and a fresh connection established for subsequent CAT commands.

§Errors

Returns Error::MemoryWriteProtected if the page is in the factory calibration region. Returns an error if entry, the page read, the page write, or exit fails. Programming mode is always exited, even on error.

Source

pub async fn read_channel_names(&mut self) -> Result<Vec<String>, Error>

Read all channel display names from the radio.

This enters programming mode, reads the channel name memory pages, and exits programming mode. The radio will briefly show “PROG MCP” on its display during this operation.

Returns a Vec of up to 1,000 channel names indexed by channel number. Channels without a user-assigned name are returned as empty strings.

§Errors

Returns an error if the radio fails to enter programming mode, if a page read fails, or if the connection is lost. On error, an attempt is still made to exit programming mode before returning.

Source

pub async fn read_all_channel_names(&mut self) -> Result<Vec<String>, Error>

Read all 1,200 channel display names from the radio, including extended entries (scan edges, WX, and call channels).

This reads 75 pages (0x0100-0x014A) instead of the 63 pages read by read_channel_names, which only returns the first 1,000 standard channel names.

§Connection lifetime

This enters MCP programming mode. The USB connection drops after exit. The Radio instance should be dropped and a fresh connection established for subsequent CAT commands.

§Errors

Returns an error if the radio fails to enter programming mode, if a page read fails, or if the connection is lost. On error, an attempt is still made to exit programming mode before returning.

Source

pub async fn write_channel_name( &mut self, channel: u16, name: &str, ) -> Result<(), Error>

Write a single channel display name via MCP programming mode.

Enters programming mode, reads the containing name page, modifies the 16-byte slot for the given channel, writes the page back, and exits. The name is truncated to 15 bytes (leaving room for a null terminator) and null-padded to fill the 16-byte slot.

§Connection lifetime

This enters MCP programming mode. The USB connection drops after exit. The Radio instance should be dropped and a fresh connection established for subsequent CAT commands.

§Errors

Returns Error::Validation if the channel number is 1200 or greater. Returns an error if entering programming mode, reading the page, writing the page, or exiting programming mode fails.

Source

pub async fn read_channel_flags(&mut self) -> Result<Vec<ChannelFlag>, Error>

Read channel flags for all 1,200 channel entries.

Each flag indicates whether a channel slot is used (and which band), whether it is locked out from scanning, and its group assignment.

§Errors

Returns an error if entry, any page read, or exit fails. Programming mode is always exited, even on error.

Source

pub async fn read_all_channels(&mut self) -> Result<Vec<FlashChannel>, Error>

Read all channel memory data (frequencies, modes, tones, etc.) for all 1,200 channel entries.

Channels whose flag indicates empty (0xFF) will still be returned with whatever data is in the slot (typically zeroed). Check the corresponding ChannelFlag to determine which slots are in use.

§Errors

Returns an error if entry, any page read, or exit fails. Programming mode is always exited, even on error.

Source

pub async fn read_configuration(&mut self) -> Result<MemoryImage, Error>

Read and parse the full radio configuration.

Reads the entire 500,480-byte memory image and returns a crate::memory::MemoryImage with typed access to all settings, channels, and subsystem configurations.

This takes approximately 55 seconds at 9600 baud.

§Errors

Returns an error if the read fails. Programming mode is always exited, even on error.

Source

pub async fn read_configuration_with_progress<F>( &mut self, on_progress: F, ) -> Result<MemoryImage, Error>
where F: FnMut(u16, u16),

Read and parse the full radio configuration with progress.

The callback receives (current_page, total_pages) after each page is read.

§Errors

Returns an error if the read fails. Programming mode is always exited, even on error.

Source

pub async fn write_configuration( &mut self, image: &MemoryImage, ) -> Result<(), Error>

Write a full radio configuration back to the radio.

Takes a crate::memory::MemoryImage (possibly modified via its typed accessors) and writes it to the radio’s flash memory.

§Errors

Returns an error if the write fails. Programming mode is always exited, even on error.

Source

pub async fn write_configuration_with_progress<F>( &mut self, image: &MemoryImage, on_progress: F, ) -> Result<(), Error>
where F: FnMut(u16, u16),

Write a full radio configuration with progress.

The callback receives (current_page, total_pages) after each page is written.

§Errors

Returns an error if the write fails. Programming mode is always exited, even on error.

Source§

impl<T: Transport> Radio<T>

Source

pub async fn set_scan_resume( &mut self, mode: ScanResumeMethod, ) -> Result<(), Error>

Set the scan resume mode (SR write).

Hardware-verified: bare SR\r returns ? (no read form). Sets the scan resume method (SR write).

Firmware-verified: SR reads/writes scan resume configuration via hardware registers, NOT a radio reset (previous documentation was wrong).

§Errors

Returns an error if the command fails or the response is unexpected.

Source

pub async fn get_step_size( &mut self, band: Band, ) -> Result<(Band, StepSize), Error>

Get the step size for a band (SF read).

Firmware-verified: SF = Step Size. SF band\r returns SF band,step.

§Errors

Returns an error if the command fails or the response is unexpected.

Source

pub async fn set_step_size( &mut self, band: Band, step: StepSize, ) -> Result<(), Error>

Set the step size for a band (SF write).

Firmware-verified: SF = Step Size. SF band,step\r (band 0-1, step 0-11).

§Errors

Returns an error if the command fails or the response is unexpected.

Source

pub async fn get_band_scope(&mut self, band: Band) -> Result<Band, Error>

Get band scope data for a band (BS read).

The radio echoes back the band number when queried.

§Errors

Returns an error if the command fails or the response is unexpected.

Source

pub async fn set_band_scope( &mut self, band: Band, value: u8, ) -> Result<(), Error>

Set band scope configuration for a band (BS write).

§Wire format

BS band,value\r where band is 0 (A) or 1 (B). The exact meaning of the value parameter is unknown.

§Errors

Returns an error if the command fails or the response is unexpected.

Source§

impl<T: Transport> Radio<T>

Source

pub async fn enter_service_mode(&mut self) -> Result<(), Error>

Enter factory service mode (0G KENWOOD).

Switches the radio from the standard 53-command CAT table to the 34-entry service mode table. Normal CAT commands will not work until service mode is exited with exit_service_mode.

§Errors

Returns an error if the command fails or the response is unexpected.

Source

pub async fn exit_service_mode(&mut self) -> Result<(), Error>

Exit factory service mode (0G bare).

Restores the standard CAT command table. Normal CAT commands will work again after this call.

§Errors

Returns an error if the command fails or the response is unexpected.

Source

pub async fn read_calibration_data(&mut self) -> Result<String, Error>

Read factory calibration data (0S).

Returns 200 bytes of hex-encoded factory calibration data (118 bytes from flash 0x4E000 + 82 bytes from a second address).

Requires service mode. Call enter_service_mode first.

§Errors

Returns an error if the command fails or the response is unexpected.

Source

pub async fn write_calibration_data(&mut self, data: &str) -> Result<(), Error>

Write factory calibration data (0R).

Writes 200 bytes of calibration data. The data parameter must be exactly 400 hex characters encoding 200 bytes.

§Safety

CRITICAL: Can corrupt factory calibration. Always read calibration first with read_calibration_data and keep a backup before writing.

Requires service mode. Call enter_service_mode first.

§Errors

Returns an error if the command fails or the response is unexpected.

Source

pub async fn get_service_status(&mut self) -> Result<String, Error>

Get service/MCP status (0E in service mode).

Reads 3 bytes from hardware status register at address 0x110. In normal mode, 0E returns N (not available). In service mode, it returns actual status data.

Requires service mode. Call enter_service_mode first.

§Errors

Returns an error if the command fails or the response is unexpected.

Source

pub async fn service_calibrate_1a(&mut self) -> Result<String, Error>

Read/write calibration parameter 1A.

Delegates to the firmware’s command executor for calibration access.

Requires service mode. Call enter_service_mode first.

§Errors

Returns an error if the command fails or the response is unexpected.

Source

pub async fn service_calibrate_1d(&mut self) -> Result<String, Error>

Read/write calibration parameter 1D.

Same executor-based pattern as 1A.

Requires service mode. Call enter_service_mode first.

§Errors

Returns an error if the command fails or the response is unexpected.

Source

pub async fn service_calibrate_1e( &mut self, value: Option<&str>, ) -> Result<String, Error>

Read calibration parameter 1E, or write with a 3-character value.

When value is None, sends a bare read (1E\r). When value is Some, sends 1E XXX\r (write form).

Requires service mode. Call enter_service_mode first.

§Errors

Returns an error if the command fails or the response is unexpected.

Source

pub async fn service_calibrate_1n(&mut self) -> Result<String, Error>

Read/write calibration parameter 1N.

Same executor-based pattern as 1A.

Requires service mode. Call enter_service_mode first.

§Errors

Returns an error if the command fails or the response is unexpected.

Source

pub async fn service_calibrate_1v( &mut self, value: Option<&str>, ) -> Result<String, Error>

Read calibration parameter 1V, or write with a 3-character value.

Same dual-mode pattern as 1E.

Requires service mode. Call enter_service_mode first.

§Errors

Returns an error if the command fails or the response is unexpected.

Source

pub async fn service_calibrate_1w( &mut self, value: &str, ) -> Result<String, Error>

Write calibration parameter 1W (write only).

Single-character parameter, likely a mode or flag toggle.

Requires service mode. Call enter_service_mode first.

§Errors

Returns an error if the command fails or the response is unexpected.

Source

pub async fn service_write_id( &mut self, id: &str, code: &str, ) -> Result<(), Error>

Write factory callsign/serial number (1I).

The id parameter must be exactly 8 alphanumeric characters and code must be exactly 3 alphanumeric characters.

§Safety

HIGH RISK: Changes the radio’s factory serial number / callsign. This may void the warranty and could cause regulatory issues.

Requires service mode. Call enter_service_mode first.

§Errors

Returns an error if the command fails or the response is unexpected.

Source

pub async fn service_flash_read(&mut self) -> Result<String, Error>

Read flash memory (1F bare read).

The read behavior depends on the firmware executor’s internal state.

§Safety

While reading is generally safe, this accesses raw flash memory.

Requires service mode. Call enter_service_mode first.

§Errors

Returns an error if the command fails or the response is unexpected.

Source

pub async fn service_flash_write( &mut self, address: &str, data: &str, ) -> Result<(), Error>

Write raw flash memory (1F write).

The address must be a 6-digit hex string (max 0x04FFFF) and data must be hex-encoded bytes. Address + data length must not exceed 0x50000.

§Safety

CRITICAL: Can brick the radio. Raw flash writes can overwrite boot code, calibration data, or firmware. There is no recovery mechanism short of JTAG or factory repair.

Requires service mode. Call enter_service_mode first.

§Errors

Returns an error if the command fails or the response is unexpected.

Source

pub async fn service_write_config(&mut self) -> Result<String, Error>

Generic write via executor (0W).

The exact operation depends on the firmware executor’s internal state.

Requires service mode. Call enter_service_mode first.

§Errors

Returns an error if the command fails or the response is unexpected.

Source

pub async fn service_band_select(&mut self, band: u8) -> Result<(), Error>

Select service mode band (0Y).

Band 0 and band 1 activate different receiver chain code paths in the firmware.

Requires service mode. Call enter_service_mode first.

§Errors

Returns an error if the command fails or the response is unexpected.

Source

pub async fn service_read_eeprom( &mut self, address: &str, length: &str, ) -> Result<String, Error>

Read bulk EEPROM/calibration data (9E).

Reads up to 256 bytes from the specified address. The address parameter is a 6-digit hex string and length is a 2-digit hex string (00 = 256 bytes). Address + length must not exceed 0x50000.

Requires service mode. Call enter_service_mode first.

§Errors

Returns an error if the command fails or the response is unexpected.

Source

pub async fn service_read_eeprom_addr(&mut self) -> Result<String, Error>

Read calibration data at current offset (9R).

Returns 4 bytes of formatted calibration data. The offset is determined by firmware internal state.

Requires service mode. Call enter_service_mode first.

§Errors

Returns an error if the command fails or the response is unexpected.

Source

pub async fn service_get_version( &mut self, param1: &str, param2: &str, ) -> Result<String, Error>

Get internal version/variant information (2V).

Returns model code (e.g., EX-5210), build date, hardware revision, and calibration date. The param1 is a 2-digit hex parameter and param2 is a 3-digit hex parameter.

Requires service mode. Call enter_service_mode first.

§Errors

Returns an error if the command fails or the response is unexpected.

Source

pub async fn service_get_hardware(&mut self) -> Result<String, Error>

Get hardware register / GPIO status (1G).

Returns hex-encoded hardware register values. Used for factory testing of GPIO and peripheral status.

Requires service mode. Call enter_service_mode first.

§Errors

Returns an error if the command fails or the response is unexpected.

Source

pub async fn service_calibrate_new(&mut self, value: &str) -> Result<(), Error>

Write new D75-specific calibration parameter (1C).

The value must be a 3-digit hex string (max 0xFF). This command is new in the D75 (not present in D74) and may be related to the 220 MHz band or enhanced DSP.

Requires service mode. Call enter_service_mode first.

§Errors

Returns an error if the command fails or the response is unexpected.

Source

pub async fn service_dynamic_param( &mut self, data: Option<&str>, ) -> Result<String, Error>

Read or write dynamic-length hardware configuration (1U).

When data is None, sends a bare read. When data is Some, sends a write with the provided data. The expected wire length is determined dynamically by the firmware reading a hardware register.

Requires service mode. Call enter_service_mode first.

§Errors

Returns an error if the command fails or the response is unexpected.

Source§

impl<T: Transport> Radio<T>

Source

pub async fn get_beep(&mut self) -> Result<bool, Error>

Get beep setting (BE read).

D75 RE: BE x (x: 0=off, 1=on).

§Errors

Returns an error if the command fails or the response is unexpected.

Source

pub async fn set_beep(&mut self, enabled: bool) -> Result<(), Error>

Set beep on/off (BE write).

D75 RE: BE x (x: 0=off, 1=on).

§D75 firmware bug

The CAT BE write command is a firmware stub on the TH-D75. It always returns ? regardless of the value sent. The read (get_beep) works, but writes are silently ignored by the firmware.

Use set_beep_via_mcp instead, which writes directly to the verified MCP memory offset (0x1071) and actually changes the setting.

§Errors

Returns an error if the command fails or the response is unexpected.

Source

pub async fn get_battery_level(&mut self) -> Result<BatteryLevel, Error>

Get the battery charge level (BL read).

Returns 0=Empty (Red), 1=1/3 (Yellow), 2=2/3 (Green), 3=Full (Green), 4=Charging (USB power connected). Read-only.

§Errors

Returns an error if the command fails or the response is unexpected.

Source

pub async fn set_battery_level( &mut self, bl_display: u8, level: u8, ) -> Result<(), Error>

Set battery level display (BL write).

§Warning

The exact purpose of this command is unclear. It may control the battery display indicator or be a calibration/test interface. The display and level parameter semantics are undocumented.

§Wire format

BL display,level\r (7 bytes with comma).

§Errors

Returns an error if the command fails or the response is unexpected.

Source

pub async fn get_lock(&mut self) -> Result<bool, Error>

Get the key lock state (LC read).

On the TH-D75, the LC wire value is inverted: LC 0 means locked, LC 1 means unlocked. This method inverts the response so that true means locked (logical meaning). The MCP offset for the lock setting is 0x1060.

§Errors

Returns an error if the command fails or the response is unexpected.

Source

pub async fn set_lock(&mut self, locked: bool) -> Result<(), Error>

Set the key lock state (LC write).

Accepts logical meaning: true = locked, false = unlocked. Inverts before sending on the wire (LC 0 = locked, LC 1 = unlocked on the D75).

§Errors

Returns an error if the command fails or the response is unexpected.

Source

pub async fn set_lock_full( &mut self, locked: bool, lock_type: KeyLockType, lock_a: bool, lock_b: bool, lock_c: bool, lock_ptt: bool, ) -> Result<(), Error>

Set all lock/control fields (LC 6-field write).

Sends the full LC a,b,c,d,e,f format to configure all lock parameters at once.

§Parameters
  • locked: master lock enable (true = locked, false = unlocked). Inverted before sending on the wire (D75: 0 = locked, 1 = unlocked).
  • lock_type: what to lock — key only, key+PTT, or key+PTT+dial.
  • lock_a: lock Band A controls (true = locked).
  • lock_b: lock Band B controls (true = locked).
  • lock_c: lock Band C controls (true = locked).
  • lock_ptt: lock the PTT button (true = locked, prevents transmission).
§Errors

Returns an error if the command fails or the response is unexpected.

Source

pub async fn get_dual_band(&mut self) -> Result<bool, Error>

Get the dual-band enabled state (DL read).

On the TH-D75, the DL wire value is inverted: DL 0 means dual band enabled, DL 1 means single band. This method inverts the response so that true means dual band is enabled (logical meaning).

§Errors

Returns an error if the command fails or the response is unexpected.

Source

pub async fn set_dual_band(&mut self, enabled: bool) -> Result<(), Error>

Set the dual-band enabled state (DL write).

Accepts logical meaning: true = dual band enabled, false = single band. Inverts before sending on the wire (DL 0 = dual band, DL 1 = single band on the D75).

§Errors

Returns an error if the command fails or the response is unexpected.

Source

pub async fn frequency_down( &mut self, band: Band, ) -> Result<ChannelMemory, Error>

Step frequency down on the given band (DW action), then read back the resulting frequency.

Sends DW to step down, then issues FQ to read back the new frequency. Returns the post-step ChannelMemory.

Per KI4LAX CAT reference: DW tunes the current band’s frequency down by the current step size. Counterpart to frequency_up.

§VFO mode requirement

The target band must be in VFO mode for this command to take effect. In Memory mode, the command may be ignored or return an error.

§Step size

The frequency moves by the band’s current step size (see get_step_size / set_step_size). The step size varies by band and mode — for example, 25 kHz for FM, 1 kHz for SSB.

§Wire format

DW band\r where band is 0 (A) or 1 (B). Despite the mnemonic suggesting “Dual Watch”, on the D75 this is strictly frequency-down.

§Errors

Returns an error if the command fails or the response is unexpected.

Source

pub async fn frequency_down_blind(&mut self, band: Band) -> Result<(), Error>

Step frequency down on the given band (DW action) without reading back the result.

This is the fire-and-forget variant of frequency_down. Use this when you do not need the resulting frequency (saves one round-trip).

§Errors

Returns an error if the command fails or the response is unexpected.

Source

pub async fn get_bluetooth(&mut self) -> Result<bool, Error>

Get the Bluetooth enabled state (BT read).

§Errors

Returns an error if the command fails or the response is unexpected.

Source

pub async fn set_bluetooth(&mut self, enabled: bool) -> Result<(), Error>

Set the Bluetooth enabled state (BT write).

§Errors

Returns an error if the command fails or the response is unexpected.

Source

pub async fn get_attenuator(&mut self, band: Band) -> Result<bool, Error>

Get the attenuator state for the given band (RA read).

§Errors

Returns an error if the command fails or the response is unexpected.

Source

pub async fn set_attenuator( &mut self, band: Band, enabled: bool, ) -> Result<(), Error>

Set the attenuator state for the given band (RA write).

§Errors

Returns an error if the command fails or the response is unexpected.

Source

pub async fn set_auto_info(&mut self, enabled: bool) -> Result<(), Error>

Set the auto-info mode (AI write). This is a write-only command.

When enabled (AI 1), the radio pushes unsolicited status updates over the serial connection whenever internal state changes. This includes frequency changes (FQ), mode changes (MD), squelch changes (SQ), and busy state transitions (BY). Without AI mode, the only way to detect changes is to poll each command individually.

Unsolicited frames pushed by the radio are delivered through the broadcast channel returned by subscribe. The execute() method routes solicited responses (matching the sent command’s mnemonic) to the caller and unsolicited frames to the broadcast channel.

This command is write-only — there is no AI read form. To check the current state, you must track it in your application after calling this method.

§Wire format

AI 0\r (disable) or AI 1\r (enable).

§Errors

Returns an error if the command fails or the response is unexpected.

Source

pub async fn get_radio_type(&mut self) -> Result<(String, u8), Error>

Get the radio type/region code (TY read).

Returns a tuple of (region code, variant number). For example, ("K", 2) indicates a US-region radio, hardware variant 2.

This command is not in the firmware’s 53-command dispatch table.

§Errors

Returns an error if the command fails or the response is unexpected.

Source

pub async fn get_io_port(&mut self) -> Result<DetectOutputMode, Error>

Get the USB Out select state (IO read).

Per KI4LAX CAT reference and Operating Tips §5.10.5: 0 = AF (audio frequency output), 1 = IF (12 kHz centered IF signal for SSB/CW/AM, 15 kHz bandwidth), 2 = Detect (pre-detection signal).

Menu 102 (USB Out Select) controls this. IF/Detect output is only available when in Single Band mode on Band B.

§Errors

Returns an error if the command fails or the response is unexpected.

Source

pub async fn set_io_port( &mut self, value: DetectOutputMode, ) -> Result<(), Error>

Set the USB Out select state (IO write).

See get_io_port for value meanings.

§Errors

Returns an error if the command fails or the response is unexpected.

Source

pub async fn get_sd_status(&mut self) -> Result<bool, Error>

Query SD card / programming interface status (SD read).

The firmware’s SD handler primarily checks for SD PROGRAM to enter MCP programming mode. The bare SD read response indicates programming interface readiness, not SD card presence.

§Errors

Returns an error if the command fails or the response is unexpected.

Source

pub async fn get_mcp_status(&mut self) -> Result<String, Error>

Get MCP status (0E read).

Returns N (not available) in normal operating mode. This mnemonic appears to be MCP-related.

§Errors

Returns an error if the command fails or the response is unexpected.

Source

pub async fn set_beep_via_mcp(&mut self, enabled: bool) -> Result<(), Error>

Set key beep on/off via MCP memory write.

The CAT BE command is a firmware stub on the TH-D75 — it always returns ? for writes. This method writes directly to the verified MCP offset (0x1071) instead.

§Connection lifetime

This enters MCP programming mode. The USB connection drops after exit. The Radio instance should be dropped and a fresh connection established for subsequent CAT commands.

§Errors

Returns an error if entering programming mode, reading the page, writing the page, or exiting programming mode fails.

Source

pub async fn set_beep_volume_via_mcp(&mut self, volume: u8) -> Result<(), Error>

Set beep volume level via MCP memory write.

The CAT BE command only supports on/off — volume level must be set via MCP. Writes directly to verified MCP offset (0x1072). Volume range is 0–7 (per Menu 915 in the Operating Tips §5.6.1).

§Connection lifetime

This enters MCP programming mode. The USB connection drops after exit. The Radio instance should be dropped and a fresh connection established for subsequent CAT commands.

§Errors

Returns an error if entering programming mode, reading the page, writing the page, or exiting programming mode fails.

Source

pub async fn set_vox_via_mcp(&mut self, enabled: bool) -> Result<(), Error>

Set VOX enabled on/off via MCP memory write.

Writes directly to the verified MCP offset (0x101B). This provides an alternative to CAT for modes where CAT writes are rejected.

§Connection lifetime

This enters MCP programming mode. The USB connection drops after exit. The Radio instance should be dropped and a fresh connection established for subsequent CAT commands.

§Errors

Returns an error if entering programming mode, reading the page, writing the page, or exiting programming mode fails.

Source

pub async fn set_lock_via_mcp(&mut self, locked: bool) -> Result<(), Error>

Set lock on/off via MCP memory write.

Writes directly to the verified MCP offset (0x1060). This provides an alternative to CAT for modes where CAT writes are rejected.

§Connection lifetime

This enters MCP programming mode. The USB connection drops after exit. The Radio instance should be dropped and a fresh connection established for subsequent CAT commands.

§Errors

Returns an error if entering programming mode, reading the page, writing the page, or exiting programming mode fails.

Source

pub async fn set_bluetooth_via_mcp( &mut self, enabled: bool, ) -> Result<(), Error>

Set Bluetooth on/off via MCP memory write.

Writes directly to the verified MCP offset (0x1078). This provides an alternative to CAT for modes where CAT writes are rejected.

§Connection lifetime

This enters MCP programming mode. The USB connection drops after exit. The Radio instance should be dropped and a fresh connection established for subsequent CAT commands.

§Errors

Returns an error if entering programming mode, reading the page, writing the page, or exiting programming mode fails.

Source§

impl<T: Transport> Radio<T>

Source

pub async fn tune_frequency( &mut self, band: Band, freq: Frequency, ) -> Result<(), Error>

Tune a band to a specific frequency.

Automatically switches to VFO mode if needed, sets the frequency, and verifies the change. This is the safe way to change frequencies.

§Errors

Returns an error if the mode switch, frequency set, or verification read fails.

Source

pub async fn tune_channel( &mut self, band: Band, channel: u16, ) -> Result<(), Error>

Tune a band to a memory channel by number.

Automatically switches to memory mode if needed and recalls the channel. Verifies the channel is populated by reading it first.

§Errors

Returns Error::RadioError if the channel number is out of range or the channel is empty. Returns transport/protocol errors on communication failure.

Source

pub async fn find_channel_by_name( &mut self, band: Band, name: &str, ) -> Result<u16, Error>

Find a memory channel number by its display name.

Searches all channel names for a match and returns the channel number. Does not tune the radio to that channel (the USB connection is reset by MCP programming mode before recall could happen). The caller should reconnect and use Radio::tune_channel with the returned channel number.

§Errors

Returns Error::Protocol with ProtocolError::UnexpectedResponse if no channel with the given name is found. Returns transport/protocol errors on communication failure.

§Warning

This method enters MCP programming mode to read channel names. After returning, the USB connection will have been reset by the radio. The Radio instance should be dropped and a fresh connection established.

Source

pub async fn quick_tune( &mut self, band: Band, freq_hz: u32, mode: Mode, step: StepSize, ) -> Result<(), Error>

Quick-tune: set frequency, operating mode, and step size in one call.

Switches to VFO mode if needed, then sets the frequency, operating mode, and step size. This is a convenience method that combines tune_frequency, set_mode, and set_step_size.

§Errors

Returns an error if any of the individual operations fail.

Source§

impl<T: Transport> Radio<T>

Source

pub async fn connect(transport: T) -> Result<Self, Error>

Create a new Radio instance over the given transport.

§Errors

Returns an error if the initial connection setup fails.

Source

pub async fn connect_safe(transport: T) -> Result<Self, Error>

Connect with a TNC exit preamble for robustness.

If the radio was left in KISS/TNC mode (e.g., by a crashed application), normal CAT commands will fail. This method sends the same exit sequence that Kenwood’s ARFC-D75 software uses before starting CAT communication:

  1. Two empty frames
  2. 300ms delay
  3. ETX byte (0x03)
  4. \rTC 1\r (TNC exit command)

After the preamble, the radio should be in normal CAT mode regardless of its previous state.

§Errors

Returns an error if the transport connection fails.

Source

pub fn subscribe(&self) -> Receiver<Response>

Subscribe to auto-info notifications.

When auto-info is enabled (set_auto_info(true)), the radio pushes unsolicited status updates. These are routed to all subscribers.

Source

pub async fn identify(&mut self) -> Result<RadioInfo, Error>

Verify the radio identity. Sends the ID command and checks the response.

§Errors

Returns Error::Protocol with ProtocolError::UnexpectedResponse if the radio does not return a RadioId response. Returns Error::Transport if communication fails.

Source

pub const fn set_timeout(&mut self, duration: Duration)

Set the timeout duration for command execution.

Defaults to 5 seconds. Commands that do not receive a response within this duration return Error::Timeout.

Source

pub const fn set_mcp_speed(&mut self, speed: McpSpeed)

Set the MCP transfer speed for programming mode operations.

The default is McpSpeed::Safe (9600 baud throughout, ~55 s for a full dump). Set to McpSpeed::Fast to switch the serial port to 115200 baud after the handshake (~8 s for a full dump), matching the fast MCP transfer mode.

See McpSpeed for platform compatibility caveats.

Source

pub async fn execute(&mut self, cmd: Command) -> Result<Response, Error>

Execute a raw command and return the parsed response.

Before sending, this method checks whether the command is compatible with the cached band mode. If a mismatch is detected, a tracing::warn is emitted but the command is not blocked – advanced users may have valid reasons to send raw commands in any state.

After a successful response, mode state is automatically updated when VM commands are observed.

§Errors

Returns Error::RadioError if the radio replies with ?. Returns Error::NotAvailable if the radio replies with N. Returns Error::Timeout if no response arrives within the configured timeout. Returns Error::Transport if the connection is lost or I/O fails. Returns Error::Protocol if the response cannot be parsed.

Source

pub const fn get_cached_mode(&self, band: Band) -> Option<RadioMode>

Returns the cached VFO/Memory mode for a band, if known.

Mode is only tracked for Band A and Band B (the two main VFOs). Returns None for other bands or until the first VM command for that band is observed.

Source

pub async fn disconnect(self) -> Result<(), Error>

Disconnect from the radio, consuming the Radio instance.

§Errors

Returns Error::Transport if closing the connection fails.

Source

pub async fn transport_write(&mut self, data: &[u8]) -> Result<(), Error>

Write raw bytes to the underlying transport.

Use this for protocol detection (e.g. sending MMDVM frames to check if the radio is in gateway mode). No framing or parsing is applied.

§Errors

Returns Error::Transport if the write fails.

Source

pub async fn transport_read(&mut self, buf: &mut [u8]) -> Result<usize, Error>

Read raw bytes from the underlying transport.

Use this for protocol detection. No framing or parsing is applied.

§Errors

Returns Error::Transport if the read fails.

Source

pub async fn close_transport(&mut self) -> Result<(), Error>

Close the underlying transport without consuming the Radio.

This is used before reconnecting to ensure Bluetooth RFCOMM resources are fully released before a new connection is opened. The Radio is left in a non-functional state — only reassignment or drop should follow.

§Errors

Returns Error::Transport if closing fails.

Trait Implementations§

Source§

impl<T: Transport> Debug for Radio<T>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

§

impl<T> Freeze for Radio<T>
where T: Freeze,

§

impl<T> !RefUnwindSafe for Radio<T>

§

impl<T> Send for Radio<T>

§

impl<T> Sync for Radio<T>

§

impl<T> Unpin for Radio<T>
where T: Unpin,

§

impl<T> !UnwindSafe for Radio<T>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a [WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a [WithDispatch] wrapper. Read more