On 2021-09-20 10:58 a.m., [email protected] wrote:
Marcus,
Thanks for your quick answer. I wrote this small script to show you
what I try to do :
|# -*- coding: utf-8 -*- """ Author : Christophe Grimault Date :
Version : Copyright (c) NovaGrid SAS 2021 This software is proprietary
software; you can not redistribute it and/or modify it without
permission of the author or of the above named company. You should
have received a license along with this software. """ #
----------------------------------------------------- # IMPORT SECTION
# ----------------------------------------------------- import numpy
as np import time import uhd from uhd.libpyuhd.types import
tune_request, tune_request_policy UHD_INIT_DELAY = 0.05 from math
import ceil from threading import (Thread, Event, Lock) class
VultureSampler(object): """ This is the server side, in Client/Server
mode, used by the VultureChannelizer, which is the client. The
VultureSampler can create and maintain 1 or 2 streams from a single
USRP. """ def __init__(self, usrp_addr='10.0.0.2', Fs=1562.5e3,
fc0=3000.0e3, fc1=None, accumulator_max_size_mbytes=200): # Configure
USRP N210 with LFRX Dboard to get single or dual stream from same
unique LFRX self.Fs = Fs self.fc0 = fc0 self.fc1 = fc1 self.duration =
0.1 self.accumulator_max_size_mbytes = accumulator_max_size_mbytes
self.accumulator_max_size_MSCx = int(accumulator_max_size_mbytes / 8)
# 8 bytes / Cx sample self.accumulator_max_duration =
self.accumulator_max_size_MSCx / self.Fs * 1e6 # Instantiate a single
MultiUSRP... self.usrp = uhd.usrp.MultiUSRP("addr=%s,
type=usrp2"%usrp_addr) self.usrp.set_clock_source("internal") if
self.fc1 is None: # For 1 stream (0) self.spec =
uhd.usrp.SubdevSpec("A:B") else: # For 2 streams (0 and 1) self.spec =
uhd.usrp.SubdevSpec("A:B A:B") self.usrp.set_rx_subdev_spec(self.spec)
self.usrp.set_rx_antenna('RX1', 0) self.usrp.set_rx_rate(self.Fs, 0)
if self.fc1 is not None: self.usrp.set_rx_antenna('RX1', 1)
self.usrp.set_rx_rate(self.Fs, 1) # self.rx_tune_request0 =
tune_request(.0e6) # self.rx_tune_request0.rf_freq_policy =
tune_request_policy.manual # self.rx_tune_request0.dsp_freq_policy =
tune_request_policy.manual # self.rx_tune_request0.rf_freq = 0.0 #
self.rx_tune_request0.dsp_freq = -self.fc0 #
self.usrp.set_rx_freq(tune_request=self.rx_tune_request0, chan=0) # #
if self.fc1 is not None: # self.rx_tune_request1 = tune_request(.0e6)
# self.rx_tune_request1.rf_freq_policy = tune_request_policy.manual #
self.rx_tune_request1.dsp_freq_policy = tune_request_policy.manual #
self.rx_tune_request1.rf_freq = 0.0 # self.rx_tune_request1.dsp_freq =
-self.fc1 # self.usrp.set_rx_freq(tune_request=self.rx_tune_request1,
chan=1) self.streamer_args0 = uhd.usrp.StreamArgs('fc32', 'sc16')
self.streamer_args0.channels.append(0) self.rx_streamer0 =
self.usrp.get_rx_stream(self.streamer_args0) max_samps_per_packet =
self.rx_streamer0.get_max_num_samps() self.rx_rate =
self.usrp.get_rx_rate() self.packet_duration =
max_samps_per_packet/self.rx_rate self.nb_packets =
int(ceil(self.duration / self.packet_duration)) self.recv_buffer0 =
np.zeros(max_samps_per_packet*self.nb_packets, dtype=np.complex64)
self.metadata0 = uhd.types.RXMetadata() if self.fc1 is not None:
self.streamer_args1 = uhd.usrp.StreamArgs('fc32', 'sc16')
self.streamer_args1.channels.append(1) self.rx_streamer1 =
self.usrp.get_rx_stream(self.streamer_args1) self.recv_buffer1 =
np.zeros(max_samps_per_packet*self.nb_packets, dtype=np.complex64)
self.metadata1 = uhd.types.RXMetadata() # Craft and send the Stream
Commands self.stream_cmd =
uhd.types.StreamCMD(uhd.types.StreamMode.start_cont)
self.stream_cmd.stream_now = False self.stream_cmd.time_spec =
uhd.types.TimeSpec(self.usrp.get_time_now().get_real_secs() +
UHD_INIT_DELAY) self.rx_streamer0.issue_stream_cmd(self.stream_cmd) if
self.fc1 is not None:
self.rx_streamer1.issue_stream_cmd(self.stream_cmd) print("CONF :")
print(" > MBoard name : %s" % (self.usrp.get_mboard_name())) print(" >
Nb of channels : %d" % (self.usrp.get_rx_num_channels())) print(" >
Max sps/packet : %d" % (max_samps_per_packet)) print(" > Rx rate :
%1.3f kSCx/s (specified : %1.3f)" % (self.rx_rate, self.Fs)) print(" >
Duration = %1.3f s => nb_packets = %d, L = %d" % ( self.duration,
self.nb_packets, len(self.recv_buffer0))) print(' > accumulator max
size = %1.2f MSCx'%(self.accumulator_max_size_MSCx)) print(' >
accumulator max duration = %1.3f s'%(self.accumulator_max_duration)) #
Launch the accumulator threads thd0 = Thread(target=self.accumulate0,
args=(), name='VultureSampler.accumulate0') thd0.daemon = False
thd0.start() if self.fc1 is not None: thd1 =
Thread(target=self.accumulate1, args=(),
name='VultureSampler.accumulate1') thd1.daemon = False thd1.start()
def accumulate0(self): """ This function runs permanently as a thread,
to collect the samples from the USRP """ print("Launching
accumulate0()...") total_nb_rx_sps = 0 self.accumulator0 = []
self.number_of_recv0 = 0 stream_start_time = time.time() while
self.number_of_recv0 < 5: ti = time.time() nb_rx_sps =
self.rx_streamer0.recv(self.recv_buffer0, self.metadata0, 0.5)
print("Acc0 : ", self.recv_buffer0[500:510])
self.accumulator0.append(self.recv_buffer0.copy()) T = time.time() -
ti acc0_size_MSCx = sum([len(a) for a in self.accumulator0]) / 1e6
acc0_load_pct = acc0_size_MSCx / self.accumulator_max_size_MSCx *
100.0 total_nb_rx_sps += nb_rx_sps overall_stream_speed_kSCxs =
total_nb_rx_sps/1000.0 / (time.time() - stream_start_time) print("ACC0
# %d > Data buffer [%d / %d] received in %1.3f ms at %1.3f MScx/s =>
%d sub_arrays (%.1f MSCx, load = %1.3f%%, %1.3f kSCx/s)"%(
self.number_of_recv0, nb_rx_sps, len(self.recv_buffer0), T*1000,
len(self.recv_buffer0)/1.0e6/T, len(self.accumulator0),
acc0_size_MSCx, acc0_load_pct, overall_stream_speed_kSCxs))
time.sleep(self.duration/10) self.number_of_recv0 += 1 print("Exiting
accumulate0()...") def accumulate1(self): """ This function runs
permanently as a thread, to collect the samples from the USRP. It is
the same as the one above, but for channel 1... """ # time.sleep(5)
print("Launching accumulate1()...") total_nb_rx_sps = 0
self.accumulator1 = [] self.number_of_recv1 = 0 stream_start_time =
time.time() while self.number_of_recv1 < 5: ti = time.time() nb_rx_sps
= self.rx_streamer1.recv(self.recv_buffer1, self.metadata1, 0.5)
print("Acc1 : ", self.recv_buffer1[500:510])
self.accumulator1.append(self.recv_buffer1.copy()) T = time.time() -
ti acc1_size_MSCx = sum([len(a) for a in self.accumulator1]) / 1e6
acc1_load_pct = acc1_size_MSCx / self.accumulator_max_size_MSCx *
100.0 total_nb_rx_sps += nb_rx_sps overall_stream_speed_kSCxs =
total_nb_rx_sps/1000.0 / (time.time() - stream_start_time) print("ACC1
# %d > Data buffer [%d / %d] received in %1.3f ms at %1.3f MScx/s =>
%d sub_arrays (%.1f MSCx, load = %1.3f%%, %1.3f kSCx/s)"%(
self.number_of_recv1, nb_rx_sps, len(self.recv_buffer1), T*1000,
len(self.recv_buffer1)/1.0e6/T, len(self.accumulator1),
acc1_size_MSCx, acc1_load_pct, overall_stream_speed_kSCxs))
time.sleep(self.duration/10) self.number_of_recv1 += 1 print("Exiting
accumulate1()...") if __name__ == '__main__': # Version with one
stream # vulture_sampler = VultureSampler(Fs=1562500.0, fc0=2000.0e3)
# Produces the output below : """ python -i
/media/realcrypt1/workspace2/CSA-HF/sampler_bistream_test.py [INFO]
[UHD] linux; GNU C++ version 10.3.1 20210422 (Red Hat 10.3.1-1);
Boost_106900; UHD_4.1.0.HEAD-0-g96032d06 [INFO] [USRP2] Opening a
USRP2/N-Series device... [INFO] [USRP2] Current recv frame size: 1472
bytes [INFO] [USRP2] Current send frame size: 1472 bytes CONF : >
MBoard name : N210r4 > Nb of channels : 1 > Max sps/packet : 363 > Rx
rate : 1562500.000 kSCx/s (specified : 1562500.000) > Duration = 0.100
s => nb_packets = 431, L = 156453 > accumulator max size = 25.00 MSCx
> accumulator max duration = 16.000 s Launching accumulate0()... >>>
Acc0 : [6.1036691e-05+0.j 9.1555034e-05+0.j 6.1036691e-05+0.j
1.2207338e-04+0.j 1.8311007e-04+0.j 1.2207338e-04+0.j
1.5259173e-04+0.j 0.0000000e+00+0.j 9.1555034e-05+0.j
1.5259173e-04+0.j] ACC0 # 0 > Data buffer [156453 / 156453] received
in 149.756 ms at 1.045 MScx/s => 1 sub_arrays (0.2 MSCx, load =
0.626%, 1044.668 kSCx/s) Acc0 : [ 3.0518346e-05+0.j -3.0518346e-05+0.j
-3.0518346e-05+0.j -3.0518346e-05+0.j -6.1036691e-05+0.j
-6.1036691e-05+0.j -3.0518346e-05+0.j 3.0518346e-05+0.j
-6.1036691e-05+0.j -1.2207338e-04+0.j] ACC0 # 1 > Data buffer [156453
/ 156453] received in 89.977 ms at 1.739 MScx/s => 2 sub_arrays (0.3
MSCx, load = 1.252%, 1252.571 kSCx/s) Acc0 : [ 3.0518346e-05+0.j
-9.1555034e-05+0.j 3.0518346e-05+0.j 0.0000000e+00+0.j
0.0000000e+00+0.j 0.0000000e+00+0.j 6.1036691e-05+0.j
6.1036691e-05+0.j 1.2207338e-04+0.j 3.0518346e-05+0.j] ACC0 # 2 > Data
buffer [156453 / 156453] received in 90.028 ms at 1.738 MScx/s => 3
sub_arrays (0.5 MSCx, load = 1.877%, 1341.370 kSCx/s) Acc0 : [
3.0518346e-05+0.j 0.0000000e+00+0.j 6.1036691e-05+0.j
6.1036691e-05+0.j 3.0518346e-05+0.j 0.0000000e+00+0.j
0.0000000e+00+0.j -3.0518346e-05+0.j 6.1036691e-05+0.j
3.0518346e-05+0.j] ACC0 # 3 > Data buffer [156453 / 156453] received
in 90.301 ms at 1.733 MScx/s => 4 sub_arrays (0.6 MSCx, load = 2.503%,
1389.821 kSCx/s) Acc0 : [1.2207338e-04+0.j 3.0518346e-05+0.j
3.0518346e-05+0.j 6.1036691e-05+0.j 3.0518346e-05+0.j
6.1036691e-05+0.j 0.0000000e+00+0.j 0.0000000e+00+0.j
3.0518346e-05+0.j 0.0000000e+00+0.j] ACC0 # 4 > Data buffer [156453 /
156453] received in 89.789 ms at 1.742 MScx/s => 5 sub_arrays (0.8
MSCx, load = 3.129%, 1421.752 kSCx/s) Exiting accumulate0()... """ #
Version with two streams vulture_sampler =
VultureSampler(Fs=1562500.0, fc0=2000.0e3, fc1=3000.0e3) # Produces
the output below : """ python -i
/media/realcrypt1/workspace2/CSA-HF/sampler_bistream_test.py [INFO]
[UHD] linux; GNU C++ version 10.3.1 20210422 (Red Hat 10.3.1-1);
Boost_106900; UHD_4.1.0.HEAD-0-g96032d06 [INFO] [USRP2] Opening a
USRP2/N-Series device... [INFO] [USRP2] Current recv frame size: 1472
bytes [INFO] [USRP2] Current send frame size: 1472 bytes CONF : >
MBoard name : N210r4 > Nb of channels : 2 > Max sps/packet : 363 > Rx
rate : 1562500.000 kSCx/s (specified : 1562500.000) > Duration = 0.100
s => nb_packets = 431, L = 156453 > accumulator max size = 25.00 MSCx
> accumulator max duration = 16.000 s Launching accumulate0()...
Launching accumulate1()... >>> DDAcc1 : [0.+0.j 0.+0.j 0.+0.j 0.+0.j
0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j] Acc0 : [0.+0.j 0.+0.j
0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j] ACC1 # 0 >
Data buffer [0 / 156453] received in 50.670 ms at 3.088 MScx/s => 1
sub_arrays (0.2 MSCx, load = 0.626%, 0.000 kSCx/s) ACC0 # 0 > Data
buffer [363 / 156453] received in 51.076 ms at 3.063 MScx/s => 1
sub_arrays (0.2 MSCx, load = 0.626%, 7.106 kSCx/s) DAcc1 : [0.+0.j
0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j] Acc0 :
[0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j
0.+0.j] ACC1 # 1 > Data buffer [363 / 156453] received in 0.558 ms at
280.193 MScx/s => 2 sub_arrays (0.3 MSCx, load = 1.252%, 5.918 kSCx/s)
ACC0 # 1 > Data buffer [0 / 156453] received in 0.587 ms at 266.320
MScx/s => 2 sub_arrays (0.3 MSCx, load = 1.252%, 5.876 kSCx/s) Acc1 :
[0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j
0.+0.j] DAcc0 : [0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j
0.+0.j 0.+0.j 0.+0.j] ACC1 # 2 > Data buffer [0 / 156453] received in
0.571 ms at 273.764 MScx/s => 3 sub_arrays (0.5 MSCx, load = 1.877%,
5.042 kSCx/s) ACC0 # 2 > Data buffer [363 / 156453] received in 0.570
ms at 274.680 MScx/s => 3 sub_arrays (0.5 MSCx, load = 1.877%, 10.022
kSCx/s) DAcc1 : [0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j
0.+0.j 0.+0.j 0.+0.j] Acc0 : [0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j
0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j] ACC1 # 3 > Data buffer [363 /
156453] received in 0.540 ms at 289.846 MScx/s => 4 sub_arrays (0.6
MSCx, load = 2.503%, 8.786 kSCx/s) ACC0 # 3 > Data buffer [0 / 156453]
received in 0.544 ms at 287.434 MScx/s => 4 sub_arrays (0.6 MSCx, load
= 2.503%, 8.739 kSCx/s) Acc1 : [0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j
0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j] DAcc0 : [0.+0.j 0.+0.j 0.+0.j
0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j] ACC1 # 4 > Data
buffer [0 / 156453] received in 0.572 ms at 273.308 MScx/s => 5
sub_arrays (0.8 MSCx, load = 3.129%, 7.782 kSCx/s) ACC0 # 4 > Data
buffer [363 / 156453] received in 0.822 ms at 190.261 MScx/s => 5
sub_arrays (0.8 MSCx, load = 3.129%, 11.585 kSCx/s) Exiting
accumulate1()... Exiting accumulate0()... """|
FOr one, you're asking to create two streams off the same SUBDEV, which
I'm near-certain is not supported, pretty sure the DDCs will get confused.
_______________________________________________
USRP-users mailing list -- [email protected]
To unsubscribe send an email to [email protected]