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()...

    """
```
_______________________________________________
USRP-users mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to