Expand Number of samples #22
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.tx_gain = None
|
||||||
self._param_lock = threading.RLock() # Reentrant lock
|
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:
|
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.
|
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
|
self._num_buffers_processed = 0
|
||||||
return recording
|
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):
|
def stream_to_zmq(self, zmq_address, n_samples: int, buffer_size: Optional[int] = 10000):
|
||||||
"""
|
"""
|
||||||
Stream iq samples as interleaved bytes via zmq.
|
Stream iq samples as interleaved bytes via zmq.
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user