From 195db4a27db894f14a70c5fc36afa8e007441026 Mon Sep 17 00:00:00 2001 From: ben Date: Tue, 14 Apr 2026 10:45:54 -0400 Subject: [PATCH] quick fix --- poetry.toml | 2 ++ src/ria_toolkit_oss/sdr/sdr.py | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+) create mode 100644 poetry.toml diff --git a/poetry.toml b/poetry.toml new file mode 100644 index 0000000..25758d2 --- /dev/null +++ b/poetry.toml @@ -0,0 +1,2 @@ +[virtualenvs.options] +system-site-packages = true diff --git a/src/ria_toolkit_oss/sdr/sdr.py b/src/ria_toolkit_oss/sdr/sdr.py index 36e26f7..f2ea9f4 100644 --- a/src/ria_toolkit_oss/sdr/sdr.py +++ b/src/ria_toolkit_oss/sdr/sdr.py @@ -43,6 +43,13 @@ class SDR(ABC): self.tx_gain = None self._param_lock = threading.RLock() # Reentrant lock + # Pending config consumed by rx() on first call and by _apply_sdr_config + # in the agent inference loop. Subclasses that need different defaults + # (e.g. MockSDR) can overwrite these in their own __init__. + self.center_freq: float = 2.4e9 + self.sample_rate: float = 10e6 + self.gain: float = 40.0 + def record(self, num_samples: Optional[int] = None, rx_time: Optional[int | float] = None) -> Recording: """ Create a radio recording of a given length. Either ``num_samples`` or ``rx_time`` must be provided. @@ -100,6 +107,32 @@ class SDR(ABC): self._num_buffers_processed = 0 return recording + def rx(self, num_samples: int) -> "np.ndarray": + """Return *num_samples* complex IQ samples as a 1-D complex64 array. + + This is the interface used by the agent inference loop. On first call, + ``init_rx()`` is invoked automatically using the values stored in + ``center_freq``, ``sample_rate``, and ``gain`` (set beforehand by + ``_apply_sdr_config``). Subsequent calls stream directly. + + Subclasses may override this for hardware-native capture APIs (e.g. + ``MockSDR`` uses AWGN generation; ``PlutoSDR`` could use + ``self.radio.rx()``). + """ + if not self._rx_initialized: + gain = self.gain if isinstance(self.gain, (int, float)) else 40.0 + self.init_rx( + sample_rate=self.sample_rate, + center_frequency=self.center_freq, + gain=gain, + channel=0, + ) + recording = self.record(num_samples=num_samples) + # Recording.data is either a list of 1-D arrays (one per channel) or a + # 2-D ndarray (channels × samples). Either way, index 0 is channel 0. + data = recording.data + return data[0] if hasattr(data, "__getitem__") else data + def stream_to_zmq(self, zmq_address, n_samples: int, buffer_size: Optional[int] = 10000): """ Stream iq samples as interleaved bytes via zmq. -- 2.34.1