updates_and_fixes #12

Merged
madrigal merged 9 commits from updates_and_fixes into main 2025-11-18 15:01:25 -05:00
Showing only changes of commit a0d0899eab - Show all commits

View File

@ -36,7 +36,7 @@ except SyntaxError as exc: # pragma: no cover - Python 2/3 compatibility issue
print("Manual fix: Run `python scripts/fix_pyrf_python3.py` from ria-toolkit-oss directory")
raise exc
from ria_toolkit_oss.sdr.sdr import SDR
from ria_toolkit_oss.sdr.sdr import SDR, SDRParameterError
class ThinkRF(SDR):
@ -51,7 +51,7 @@ class ThinkRF(SDR):
super().__init__()
if identifier is None:
raise ValueError("ThinkRF requires an IP address or hostname identifier")
raise SDRParameterError("ThinkRF requires an IP address or hostname identifier")
self.identifier = identifier
try:
@ -90,7 +90,7 @@ class ThinkRF(SDR):
mode = capture_mode.lower()
if mode not in {"block", "stream"}:
raise ValueError("capture_mode must be either 'block' or 'stream'")
raise SDRParameterError("capture_mode must be either 'block' or 'stream'")
self._rfe_mode = rfe_mode
self._attenuation = int(max(0, min(attenuation, 30)))
@ -113,10 +113,12 @@ class ThinkRF(SDR):
decimation: Optional[int] = None,
):
if channel not in (0, None):
raise ValueError("ThinkRF devices expose a single receive channel")
raise SDRParameterError("ThinkRF supports only channel 0 for RX.")
stream_mode = getattr(self, "_capture_mode", "block") == "stream"
actual_decimation, actual_sample_rate = self.set_rx_sample_rate(sample_rate=sample_rate, decimation=decimation)
actual_decimation, _ = self.set_rx_sample_rate(
sample_rate=sample_rate, decimation=decimation, stream_mode=stream_mode
)
self.radio.reset()
self.radio.scpiset(":SYSTEM:FLUSH")
@ -127,15 +129,7 @@ class ThinkRF(SDR):
self.radio.rfe_mode(self._rfe_mode)
self.set_rx_center_frequency(center_frequency=center_frequency)
attenuation = self._attenuation if gain is None else int(gain) # gain
attenuation = max(0, min(attenuation, 30))
self.radio.attenuator(attenuation)
gain_profile = self._gain_profile
if gain_mode and isinstance(gain_mode, str) and gain_mode.upper() in {"LOW", "MEDIUM", "HIGH", "VLOW"}:
gain_profile = gain_mode.upper()
self.radio.gain(gain_profile.lower()) # WSA.gain() expects lowercase
self.set_rx_gain(gain=gain, gain_mode=gain_mode, actual_decimation=actual_decimation)
self.radio.decimation(actual_decimation)
if stream_mode:
@ -153,14 +147,6 @@ class ThinkRF(SDR):
self.radio.scpiset(f":TRACE:BLOCK:PACKETS {self._packets_per_block}")
self.radio.scpiset(":TRACE:BLOCK:DATA?")
self.rx_gain = {
"attenuation_dB": attenuation,
"profile": gain_profile,
"decimation": actual_decimation,
"rfe_mode": self._rfe_mode,
"spp": self._samples_per_packet,
"ppb": self._packets_per_block,
}
self.rx_buffer_size = self._samples_per_packet
self.rx_channel = 0
@ -168,6 +154,10 @@ class ThinkRF(SDR):
self._tx_initialized = False
def set_rx_sample_rate(self, sample_rate, decimation, stream_mode):
"""
Set the sample rate of the receiver.
Not callable during recording; ThinkRF requires stream stop/restart to change sample rate.
"""
# Enforce sample rate / decimation
# Note: decimation parameter takes precedence if provided
actual_decimation, actual_sample_rate = self.enforce_sample_rate(sample_rate, decimation)
@ -188,9 +178,32 @@ class ThinkRF(SDR):
return actual_decimation, actual_sample_rate
def set_rx_center_frequency(self, center_frequency):
self.radio.freq(int(center_frequency))
self.rx_center_frequency = self.radio.freq
print(f"ThinkRF RX Center Frequency = {self.radio.freq}")
"""
Set the center frequency of the receiver. Callable during streaming.
"""
with self._param_lock:
self.radio.freq(int(center_frequency))
self.rx_center_frequency = self.radio.freq
print(f"ThinkRF RX Center Frequency = {self.radio.freq}")
def set_rx_gain(self, gain, gain_mode, actual_decimation):
attenuation = self._attenuation if gain is None else int(gain) # gain
attenuation = max(0, min(attenuation, 30))
self.radio.attenuator(attenuation)
gain_profile = self._gain_profile
if gain_mode and isinstance(gain_mode, str) and gain_mode.upper() in {"LOW", "MEDIUM", "HIGH", "VLOW"}:
gain_profile = gain_mode.upper()
self.radio.gain(gain_profile.lower()) # WSA.gain() expects lowercase
self.rx_gain = {
"attenuation_dB": attenuation,
"profile": gain_profile,
"decimation": actual_decimation,
"rfe_mode": self._rfe_mode,
"spp": self._samples_per_packet,
"ppb": self._packets_per_block,
}
def _stream_rx(self, callback):
if not self._rx_initialized:
@ -431,7 +444,7 @@ class ThinkRF(SDR):
For decimation 1 or 2, block captures are limited by onboard RAM.
"""
if decimation <= 2 and num_samples > self.MAX_ONBOARD_SAMPLES:
raise ValueError(
raise SDRParameterError(
f"ThinkRF: Cannot capture {num_samples} samples at decimation {decimation}. "
f"Onboard RAM limit is ~{self.MAX_ONBOARD_SAMPLES} samples for dec 1/2. "
f"Either reduce num_samples or use stream mode (increase decimation to >=4)."
@ -446,3 +459,6 @@ class ThinkRF(SDR):
"fstop": int(center_frequency) + half,
"amplitude": -100,
}
def supports_dynamic_updates(self) -> dict:
return {"center_frequency": True, "sample_rate": False, "gain": False}