Compare commits
2 Commits
5718e109b5
...
8f39c4d855
| Author | SHA1 | Date | |
|---|---|---|---|
| 8f39c4d855 | |||
| 195db4a27d |
2
poetry.toml
Normal file
2
poetry.toml
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
[virtualenvs.options]
|
||||
system-site-packages = true
|
||||
|
|
@ -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.
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user