mirror of
https://github.com/EttusResearch/uhd.git
synced 2026-10-25 17:36:10 +00:00
python: Update pyuhd wrapper functions to make freq tuning use timedcmds
This commit is contained in:
parent
5de584251c
commit
52467d3261
@ -7,7 +7,10 @@
|
||||
Python UHD module containing the MultiUSRP and other objects
|
||||
"""
|
||||
|
||||
import time
|
||||
|
||||
import numpy as np
|
||||
|
||||
from .. import libpyuhd as lib
|
||||
|
||||
|
||||
@ -17,14 +20,17 @@ def _get_mpm_client(token, mb_args):
|
||||
MultiUSRP.
|
||||
"""
|
||||
from uhd.utils import mpmtools
|
||||
rpc_addr = mb_args.get('mgmt_addr')
|
||||
rpc_port = mb_args.get('rpc_port', mpmtools.MPM_RPC_PORT)
|
||||
|
||||
rpc_addr = mb_args.get("mgmt_addr")
|
||||
rpc_port = mb_args.get("rpc_port", mpmtools.MPM_RPC_PORT)
|
||||
return mpmtools.MPMClient(mpmtools.InitMode.Hijack, rpc_addr, rpc_port, token)
|
||||
|
||||
|
||||
class MultiUSRP(lib.usrp.multi_usrp):
|
||||
"""
|
||||
MultiUSRP object for controlling devices
|
||||
"""
|
||||
|
||||
def __init__(self, args=""):
|
||||
"""MultiUSRP constructor"""
|
||||
super(MultiUSRP, self).__init__(args)
|
||||
@ -32,18 +38,12 @@ class MultiUSRP(lib.usrp.multi_usrp):
|
||||
# MPM client
|
||||
if self.get_tree().exists("/mboards/0/token"):
|
||||
token = self.get_tree().access_str("/mboards/0/token").get()
|
||||
mb_args = \
|
||||
self.get_tree().access_device_addr("/mboards/0/args").get().to_dict()
|
||||
setattr(self, 'get_mpm_client', lambda: _get_mpm_client(token, mb_args))
|
||||
mb_args = self.get_tree().access_device_addr("/mboards/0/args").get().to_dict()
|
||||
setattr(self, "get_mpm_client", lambda: _get_mpm_client(token, mb_args))
|
||||
|
||||
def recv_num_samps(self,
|
||||
num_samps,
|
||||
freq,
|
||||
rate=1e6,
|
||||
channels=(0,),
|
||||
gain=10,
|
||||
start_time=None,
|
||||
streamer=None):
|
||||
def recv_num_samps(
|
||||
self, num_samps, freq, rate=1e6, channels=(0,), gain=10, start_time=None, streamer=None
|
||||
):
|
||||
"""
|
||||
RX a finite number of samples from the USRP
|
||||
|
||||
@ -63,6 +63,7 @@ class MultiUSRP(lib.usrp.multi_usrp):
|
||||
one locally and attempt to destroy it afterwards.
|
||||
:return: numpy array of complex floating-point samples (fc32)
|
||||
"""
|
||||
|
||||
def _config_streamer(streamer):
|
||||
"""
|
||||
Set up the correct streamer
|
||||
@ -72,6 +73,7 @@ class MultiUSRP(lib.usrp.multi_usrp):
|
||||
st_args.channels = channels
|
||||
streamer = super(MultiUSRP, self).get_rx_stream(st_args)
|
||||
return streamer
|
||||
|
||||
def _start_stream(streamer):
|
||||
"""
|
||||
Issue the start-stream command.
|
||||
@ -83,8 +85,10 @@ class MultiUSRP(lib.usrp.multi_usrp):
|
||||
stream_cmd.time_spec = start_time
|
||||
else:
|
||||
stream_cmd.time_spec = lib.types.time_spec(
|
||||
super(MultiUSRP, self).get_time_now().get_real_secs() + 0.05)
|
||||
super(MultiUSRP, self).get_time_now().get_real_secs() + 0.05
|
||||
)
|
||||
streamer.issue_stream_cmd(stream_cmd)
|
||||
|
||||
def _stop_stream(streamer):
|
||||
"""
|
||||
Issue the stop-stream command and flush the queue.
|
||||
@ -94,6 +98,7 @@ class MultiUSRP(lib.usrp.multi_usrp):
|
||||
streamer.issue_stream_cmd(stream_cmd)
|
||||
while streamer.recv(recv_buffer, metadata):
|
||||
pass
|
||||
|
||||
## And go!
|
||||
# Configure USRP
|
||||
for chan in channels:
|
||||
@ -105,8 +110,7 @@ class MultiUSRP(lib.usrp.multi_usrp):
|
||||
metadata = lib.types.rx_metadata()
|
||||
# Set up buffers and counters
|
||||
result = np.empty((len(channels), num_samps), dtype=np.complex64)
|
||||
recv_buffer = np.zeros(
|
||||
(len(channels), streamer.get_max_num_samps()), dtype=np.complex64)
|
||||
recv_buffer = np.zeros((len(channels), streamer.get_max_num_samps()), dtype=np.complex64)
|
||||
recv_samps = 0
|
||||
samps = 0
|
||||
# Now stream
|
||||
@ -117,8 +121,7 @@ class MultiUSRP(lib.usrp.multi_usrp):
|
||||
print(metadata.strerror())
|
||||
if samps:
|
||||
real_samps = min(num_samps - recv_samps, samps)
|
||||
result[:, recv_samps:recv_samps + real_samps] = \
|
||||
recv_buffer[:, 0:real_samps]
|
||||
result[:, recv_samps : recv_samps + real_samps] = recv_buffer[:, 0:real_samps]
|
||||
recv_samps += real_samps
|
||||
# Stop and clean up
|
||||
_stop_stream(streamer)
|
||||
@ -126,15 +129,17 @@ class MultiUSRP(lib.usrp.multi_usrp):
|
||||
streamer = None
|
||||
return result
|
||||
|
||||
def send_waveform(self,
|
||||
waveform_proto,
|
||||
duration,
|
||||
freq,
|
||||
rate=1e6,
|
||||
channels=(0,),
|
||||
gain=10,
|
||||
start_time=None,
|
||||
streamer=None):
|
||||
def send_waveform(
|
||||
self,
|
||||
waveform_proto,
|
||||
duration,
|
||||
freq,
|
||||
rate=1e6,
|
||||
channels=(0,),
|
||||
gain=10,
|
||||
start_time=None,
|
||||
streamer=None,
|
||||
):
|
||||
"""
|
||||
TX a finite number of samples from the USRP
|
||||
:param waveform_proto: numpy array of samples to TX
|
||||
@ -149,6 +154,7 @@ class MultiUSRP(lib.usrp.multi_usrp):
|
||||
one locally and attempt to destroy it afterwards.
|
||||
:return: the number of transmitted samples
|
||||
"""
|
||||
|
||||
def _config_streamer(streamer):
|
||||
"""
|
||||
Set up the correct streamer
|
||||
@ -158,20 +164,38 @@ class MultiUSRP(lib.usrp.multi_usrp):
|
||||
st_args.channels = channels
|
||||
streamer = super(MultiUSRP, self).get_tx_stream(st_args)
|
||||
return streamer
|
||||
|
||||
## And go!
|
||||
for chan in channels:
|
||||
super(MultiUSRP, self).set_tx_rate(rate, chan)
|
||||
super(MultiUSRP, self).set_tx_freq(lib.types.tune_request(freq), chan)
|
||||
if start_time is None:
|
||||
super(MultiUSRP, self).set_tx_freq(lib.types.tune_request(freq), chan)
|
||||
super(MultiUSRP, self).set_tx_gain(gain, chan)
|
||||
|
||||
if start_time is not None:
|
||||
# Use timed commands to set frequency to minimize phase differences
|
||||
# between channels. Picking a command time in the middle between
|
||||
# now and start time.
|
||||
cmd_time_offset = max(
|
||||
0, (start_time - super(MultiUSRP, self).get_time_now()).get_real_secs() / 2
|
||||
)
|
||||
cmd_time = super(MultiUSRP, self).get_time_now() + cmd_time_offset
|
||||
super(MultiUSRP, self).set_command_time(cmd_time)
|
||||
for chan in channels:
|
||||
super(MultiUSRP, self).set_tx_freq(lib.types.tune_request(freq), chan)
|
||||
super(MultiUSRP, self).clear_command_time()
|
||||
# Enough time for tune time to expire
|
||||
time.sleep(cmd_time_offset)
|
||||
|
||||
# Configure streamer
|
||||
streamer = _config_streamer(streamer)
|
||||
# Set up buffers and counters
|
||||
buffer_samps = streamer.get_max_num_samps()
|
||||
proto_len = waveform_proto.shape[-1]
|
||||
if proto_len < buffer_samps:
|
||||
waveform_proto = np.tile(waveform_proto,
|
||||
(1, int(np.ceil(float(buffer_samps)/proto_len))))
|
||||
waveform_proto = np.tile(
|
||||
waveform_proto, (1, int(np.ceil(float(buffer_samps) / proto_len)))
|
||||
)
|
||||
proto_len = waveform_proto.shape[-1]
|
||||
send_samps = 0
|
||||
max_samps = int(np.floor(duration * rate))
|
||||
@ -185,7 +209,7 @@ class MultiUSRP(lib.usrp.multi_usrp):
|
||||
metadata.time_spec = start_time
|
||||
metadata.has_time_spec = True
|
||||
while send_samps < max_samps:
|
||||
real_samps = min(proto_len, max_samps-send_samps)
|
||||
real_samps = min(proto_len, max_samps - send_samps)
|
||||
if real_samps < proto_len:
|
||||
samples = streamer.send(waveform_proto[:, :real_samps], metadata)
|
||||
else:
|
||||
|
||||
Loading…
Reference in New Issue
Block a user