From 5c9e50fa48da6f0496df72753e7750fd7327770a Mon Sep 17 00:00:00 2001 From: ash Date: Mon, 6 Oct 2025 00:06:33 -0400 Subject: [PATCH] mcr error for usb devices in uhd, and type mismatch error in blade --- src/ria_toolkit_oss/sdr/blade.py | 16 ++++++++------ src/ria_toolkit_oss/sdr/usrp.py | 36 ++++++++++++++++++++------------ 2 files changed, 33 insertions(+), 19 deletions(-) diff --git a/src/ria_toolkit_oss/sdr/blade.py b/src/ria_toolkit_oss/sdr/blade.py index e2ebef6..7fa6231 100644 --- a/src/ria_toolkit_oss/sdr/blade.py +++ b/src/ria_toolkit_oss/sdr/blade.py @@ -375,14 +375,18 @@ class Blade(SDR): return samples def _convert_tx_samples(self, samples): - tx_samples = np.empty(samples.size * 2, dtype=np.float32) - tx_samples[::2] = np.real(samples) # Real part - tx_samples[1::2] = np.imag(samples) # Imaginary part + # Normalize to maximum amplitude to prevent overflow + max_val = np.max(np.abs(samples)) + if max_val > 0: + samples = samples / max_val # Normalize to [-1, 1] + + # Scale to Q11 format (use 2047 instead of 2048 to avoid overflow) + # and interleave I/Q samples + tx_samples = np.zeros(len(samples) * 2, dtype=np.int16) + tx_samples[0::2] = (np.real(samples) * 2047).astype(np.int16) # I samples + tx_samples[1::2] = (np.imag(samples) * 2047).astype(np.int16) # Q samples - tx_samples *= 2048 - tx_samples = tx_samples.astype(np.int16) byte_array = tx_samples.tobytes() - return byte_array def _set_rx_channel(self, channel): diff --git a/src/ria_toolkit_oss/sdr/usrp.py b/src/ria_toolkit_oss/sdr/usrp.py index 29fa94a..4169c0a 100644 --- a/src/ria_toolkit_oss/sdr/usrp.py +++ b/src/ria_toolkit_oss/sdr/usrp.py @@ -100,13 +100,18 @@ class USRP(SDR): self.usrp.set_rx_gain(abs_gain, channel) # check if sample rate arg is valid - sample_rate_range = self.usrp.get_rx_rates() - if sample_rate < sample_rate_range.start() or sample_rate > sample_rate_range.stop(): - raise IOError( - f"Sample rate {sample_rate} not valid for this USRP.\nValid\ - range is {sample_rate_range.start()}\ - to {sample_rate_range.stop()}." - ) + # Note: B200/B210 devices auto-adjust master clock rate, so get_rx_rates() returns + # the range for the CURRENT master clock, not the maximum possible range. + # Skip validation for B-series devices and let UHD handle it. + device_type = self.device_dict.get("type", "").lower() + if device_type not in ["b200", "b210"]: + sample_rate_range = self.usrp.get_rx_rates() + if sample_rate < sample_rate_range.start() or sample_rate > sample_rate_range.stop(): + raise IOError( + f"Sample rate {sample_rate} not valid for this USRP.\nValid\ + range is {sample_rate_range.start()}\ + to {sample_rate_range.stop()}." + ) self.usrp.set_rx_rate(sample_rate, channel) center_frequency_range = self.usrp.get_rx_freq_range() @@ -317,12 +322,17 @@ class USRP(SDR): self.usrp.set_tx_gain(abs_gain, channel) # check if sample rate arg is valid - sample_rate_range = self.usrp.get_tx_rates() - if sample_rate < sample_rate_range.start() or sample_rate > sample_rate_range.stop(): - raise IOError( - f"Sample rate {sample_rate} not valid for this USRP.\nValid\ - range is {sample_rate_range.start()} to {sample_rate_range.stop()}." - ) + # Note: B200/B210 devices auto-adjust master clock rate, so get_tx_rates() returns + # the range for the CURRENT master clock, not the maximum possible range. + # Skip validation for B-series devices and let UHD handle it. + device_type = self.device_dict.get("type", "").lower() + if device_type not in ["b200", "b210"]: + sample_rate_range = self.usrp.get_tx_rates() + if sample_rate < sample_rate_range.start() or sample_rate > sample_rate_range.stop(): + raise IOError( + f"Sample rate {sample_rate} not valid for this USRP.\nValid\ + range is {sample_rate_range.start()} to {sample_rate_range.stop()}." + ) self.usrp.set_tx_rate(sample_rate, channel) center_frequency_range = self.usrp.get_tx_freq_range()