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]

Reply via email to