usrp-users@lists.ettus.com

Discussion and technical support related to USRP, UHD, RFNoC

View all threads

B210 LO phase behavior

BC
Beaudoin, Christopher J
Tue, Oct 18, 2016 7:38 PM

Hi,

  I’m developing an absolute phase detector with the B210 and establishing a consistent phase measurement (relative to the internal sampler clock) from acquisition-to-acquisition has proven difficult. I’m wondering if I have not configured the radio properly or if the device does not function in exactly the way that I am anticipating. In my setup, I have locked together the 10 MHz reference of the B210 and my external signal generator - the generator is providing a constant -30 dBm, 3 GHz tone. The B210 is configured to lock in the integer-N mode, I command the frontend LO frequency to 2999950000 Hz (i.e. 50 kHz offset from my 3 GHz tone), and I do not reset the clock nor do I re-tune any frequency/sample-rate parameters in between acquisitions. Configured in this way, I am anticipating that the absolute phase of the IQ samples at every integer second boundary to repeat precisely between acquisitions since there are an integer number of signal cycles in each second but the measured results indicate otherwise.

To investigate lack of phase repeatability on the second’s boundary further, I pulse modulated the 3 GHz tone with a 1 kHz square wave derived from the same 10 MHz reference that the B210 and signal generator are locked to. What I observed from measurements of this modulated tone is that that edges of the 1 KHz modulation appear at precisely the same sample indices relative to the integer-second boundary from acquisition-to-acquistion, however, the absolute phase of the 50 KHz tone relative to the edge of this 1KHz modulation varies significantly (>> 90 degs) from one acquisition to the next.  Just in case you are wondering, I independently confirmed that the 1 kHz modulation is phase locked to 3 GHz tone with a separate/independent setup. What this is telling me is that the time samples are true and aligned between acquisitions and that an embedded LO phase term appears to change between acquisitions. I’m not sure if such a term is arising from the analog AD9361 frontend, some known shift that results in the FPGA signal processing, or perhaps elsewhere.

Does anyone know if the behavior I’ve described here to be expected?  Any insight that you can offer would be greatly appreciated.

Best regards,
Chris

Hi, I’m developing an absolute phase detector with the B210 and establishing a consistent phase measurement (relative to the internal sampler clock) from acquisition-to-acquisition has proven difficult. I’m wondering if I have not configured the radio properly or if the device does not function in exactly the way that I am anticipating. In my setup, I have locked together the 10 MHz reference of the B210 and my external signal generator - the generator is providing a constant -30 dBm, 3 GHz tone. The B210 is configured to lock in the integer-N mode, I command the frontend LO frequency to 2999950000 Hz (i.e. 50 kHz offset from my 3 GHz tone), and I do not reset the clock nor do I re-tune any frequency/sample-rate parameters in between acquisitions. Configured in this way, I am anticipating that the absolute phase of the IQ samples at every integer second boundary to repeat precisely between acquisitions since there are an integer number of signal cycles in each second but the measured results indicate otherwise. To investigate lack of phase repeatability on the second’s boundary further, I pulse modulated the 3 GHz tone with a 1 kHz square wave derived from the same 10 MHz reference that the B210 and signal generator are locked to. What I observed from measurements of this modulated tone is that that edges of the 1 KHz modulation appear at precisely the same sample indices relative to the integer-second boundary from acquisition-to-acquistion, however, the absolute phase of the 50 KHz tone relative to the edge of this 1KHz modulation varies significantly (>> 90 degs) from one acquisition to the next. Just in case you are wondering, I independently confirmed that the 1 kHz modulation is phase locked to 3 GHz tone with a separate/independent setup. What this is telling me is that the time samples are true and aligned between acquisitions and that an embedded LO phase term appears to change between acquisitions. I’m not sure if such a term is arising from the analog AD9361 frontend, some known shift that results in the FPGA signal processing, or perhaps elsewhere. Does anyone know if the behavior I’ve described here to be expected? Any insight that you can offer would be greatly appreciated. Best regards, Chris
MD
Marcus D. Leech
Tue, Oct 18, 2016 7:44 PM

On 10/18/2016 03:38 PM, Beaudoin, Christopher J via USRP-users wrote:

Hi,

    I’m developing an absolute phase detector with the B210 and establishing a consistent phase measurement (relative to the internal sampler clock) from acquisition-to-acquisition has proven difficult. I’m wondering if I have not configured the radio properly or if the device does not function in exactly the way that I am anticipating. In my setup, I have locked together the 10 MHz reference of the B210 and my external signal generator - the generator is providing a constant -30 dBm, 3 GHz tone. The B210 is configured to lock in the integer-N mode, I command the frontend LO frequency to 2999950000 Hz (i.e. 50 kHz offset from my 3 GHz tone), and I do not reset the clock nor do I re-tune any frequency/sample-rate parameters in between acquisitions. Configured in this way, I am anticipating that the absolute phase of the IQ samples at every integer second boundary to repeat precisely between acquisitions since there are an integer number of signal cycles in each second but the measured results indicate otherwise.

To investigate lack of phase repeatability on the second’s boundary further, I pulse modulated the 3 GHz tone with a 1 kHz square wave derived from the same 10 MHz reference that the B210 and signal generator are locked to. What I observed from measurements of this modulated tone is that that edges of the 1 KHz modulation appear at precisely the same sample indices relative to the integer-second boundary from acquisition-to-acquistion, however, the absolute phase of the 50 KHz tone relative to the edge of this 1KHz modulation varies significantly (>> 90 degs) from one acquisition to the next.  Just in case you are wondering, I independently confirmed that the 1 kHz modulation is phase locked to 3 GHz tone with a separate/independent setup. What this is telling me is that the time samples are true and aligned between acquisitions and that an embedded LO phase term appears to change between acquisitions. I’m not sure if such a term is arising from the analog AD9361 frontend, some known shift that results in the FPGA signal processing, or perhaps elsewhere.

Does anyone know if the behavior I’ve described here to be expected?  Any insight that you can offer would be greatly appreciated.

Best regards,
Chris


When you say you do "multiple acquisitions", how exactly are you doing
that?    Unless you're continuously streaming, various bits and
pieces get "idled" and brought back up between runs.

On 10/18/2016 03:38 PM, Beaudoin, Christopher J via USRP-users wrote: > Hi, > > I’m developing an absolute phase detector with the B210 and establishing a consistent phase measurement (relative to the internal sampler clock) from acquisition-to-acquisition has proven difficult. I’m wondering if I have not configured the radio properly or if the device does not function in exactly the way that I am anticipating. In my setup, I have locked together the 10 MHz reference of the B210 and my external signal generator - the generator is providing a constant -30 dBm, 3 GHz tone. The B210 is configured to lock in the integer-N mode, I command the frontend LO frequency to 2999950000 Hz (i.e. 50 kHz offset from my 3 GHz tone), and I do not reset the clock nor do I re-tune any frequency/sample-rate parameters in between acquisitions. Configured in this way, I am anticipating that the absolute phase of the IQ samples at every integer second boundary to repeat precisely between acquisitions since there are an integer number of signal cycles in each second but the measured results indicate otherwise. > > To investigate lack of phase repeatability on the second’s boundary further, I pulse modulated the 3 GHz tone with a 1 kHz square wave derived from the same 10 MHz reference that the B210 and signal generator are locked to. What I observed from measurements of this modulated tone is that that edges of the 1 KHz modulation appear at precisely the same sample indices relative to the integer-second boundary from acquisition-to-acquistion, however, the absolute phase of the 50 KHz tone relative to the edge of this 1KHz modulation varies significantly (>> 90 degs) from one acquisition to the next. Just in case you are wondering, I independently confirmed that the 1 kHz modulation is phase locked to 3 GHz tone with a separate/independent setup. What this is telling me is that the time samples are true and aligned between acquisitions and that an embedded LO phase term appears to change between acquisitions. I’m not sure if such a term is arising from the analog AD9361 frontend, some known shift that results in the FPGA signal processing, or perhaps elsewhere. > > Does anyone know if the behavior I’ve described here to be expected? Any insight that you can offer would be greatly appreciated. > > Best regards, > Chris > _______________________________________________ When you say you do "multiple acquisitions", how exactly are you doing that? Unless you're continuously streaming, various bits and pieces get "idled" and brought back up between runs.
BC
Beaudoin, Christopher J
Wed, Oct 19, 2016 6:39 PM

Hi Marcus,

 In response to your message,

When you say you do "multiple acquisitions", how exactly are you doing
that?    Unless you're continuously streaming, various bits and
pieces get "idled" and brought back up between runs.

I’ve included a snippet of the code below that I use to perform the collections. I am not streaming samples continuously as you can see below. Rather, an external client makes a requests to collects the specified number of samples asynchronously but, since I am not reseting the clock or retuning any parameters between these acquisitions (at least that I am aware of), I thought the phase of the samples would remain continuous across async requests - perhaps this is not the case?

Thanks,
Chris

//----------Setup the USRP:          START ------------------//

//create a receive streamer
uhd::stream_args_t stream_args("sc16", wire); //complex floats
stream_args.channels = channel_nums;
uhd::rx_streamer::sptr rx_stream = usrp->get_rx_stream(stream_args);

//setup streaming
uhd::stream_cmd_t stream_cmd(uhd::stream_cmd_t::STREAM_MODE_NUM_SAMPS_AND_DONE);
stream_cmd.num_samps = total_num_samps;
stream_cmd.stream_now = false;

ts = usrp->get_time_now();
stream_cmd.time_spec = uhd::time_spec_t( (double) ts.get_full_secs() +  seconds_in_future);
//stream_cmd.time_spec = uhd::time_spec_t(seconds_in_future);
rx_stream->issue_stream_cmd(stream_cmd);

//allocate buffer to receive with samples
std::vector<std::complex<short> > buff_RFa(rx_stream->get_max_num_samps());
std::vector<std::complex<short> > buff_RFb(rx_stream->get_max_num_samps());
std::vector<void *> buffs;
buffs.push_back(&buff_RFa.front()); //same buffer for each channel
buffs.push_back(&buff_RFb.front()); //same buffer for each channel

//allocate memory for arrays of samples for each channel
samples_RFa = (char *) malloc(total_num_samps * sizeof(std::complex<short>));
samples_RFb = (char *) malloc(total_num_samps * sizeof(std::complex<short>));

for(m = 0;m < (total_num_samps * sizeof(std::complex<short>));m++){
samples_RFa[m] = 32;
samples_RFb[m] = 32;
}

//----------Setup the USRP:          STOP  ------------------//

//----------Data Acquisition:        START ------------------//

//the first call to recv() will block this many seconds before receiving

double timeout = seconds_in_future + 0.1; //timeout (delay before receive + padding)

size_t m,num_acc_samps = 0; //number of accumulated samples
int fcount=0,pkt_cnt = 0;
int ftot=3000;
short int tt_n, tt_o=1;

while( (num_acc_samps < total_num_samps) ){
//receive a single packet
size_t num_rx_samps = rx_stream->recv(buffs, buff_RFa.size(), md, timeout, true);

if ( num_acc_samps == 0 ){ //get frac seconds offset for first frame
t0_d = md.time_spec.get_frac_secs();
t0_d_a[0] = t0_d ;
t0 = (char *) t0_d_a;
}

//use a small timeout for subsequent packets
timeout = 0.1;

//handle the error code
if (md.error_code == uhd::rx_metadata_t::ERROR_CODE_TIMEOUT) break;
if (md.error_code != uhd::rx_metadata_t::ERROR_CODE_NONE){
throw std::runtime_error(str(boost::format(
"Receiver error %s") % md.strerror()));
}

if(verbose) std::cout << boost::format(
"Received packet: %u tot samples, %u rx samples, %u full secs, %f frac secs"
) % num_acc_samps % num_rx_samps % md.time_spec.get_full_secs() % md.time_spec.get_frac_secs() << std::endl;

memcpy(samples_RFa + 4 * num_acc_samps,
(const char*) &buff_RFa[0],
num_rx_samps * sizeof(std::complex<short>));

memcpy(samples_RFb + num_acc_samps sizeof(std::complex<short>),
(const char
) &buff_RFb[0],
num_rx_samps * sizeof(std::complex<short>));

num_acc_samps += num_rx_samps;
}
stream_cmd.stream_mode = uhd::stream_cmd_t::STREAM_MODE_STOP_CONTINUOUS;
rx_stream->issue_stream_cmd(stream_cmd);

if (num_acc_samps < total_num_samps) std::cerr << "Receive timeout before all samples received..." << std::endl;

//----------Data Acquisition:        STOP  ------------------//

On Oct 18, 2016, at 3:38 PM, Beaudoin, Christopher J <Christopher_Beaudoin@uml.edumailto:Christopher_Beaudoin@uml.edu> wrote:

Hi,

 I’m developing an absolute phase detector with the B210 and establishing a consistent phase measurement (relative to the internal sampler clock) from acquisition-to-acquisition has proven difficult. I’m wondering if I have not configured the radio properly or if the device does not function in exactly the way that I am anticipating. In my setup, I have locked together the 10 MHz reference of the B210 and my external signal generator - the generator is providing a constant -30 dBm, 3 GHz tone. The B210 is configured to lock in the integer-N mode, I command the frontend LO frequency to 2999950000 Hz (i.e. 50 kHz offset from my 3 GHz tone), and I do not reset the clock nor do I re-tune any frequency/sample-rate parameters in between acquisitions. Configured in this way, I am anticipating that the absolute phase of the IQ samples at every integer second boundary to repeat precisely between acquisitions since there are an integer number of signal cycles in each second but the measured results indicate otherwise.

To investigate lack of phase repeatability on the second’s boundary further, I pulse modulated the 3 GHz tone with a 1 kHz square wave derived from the same 10 MHz reference that the B210 and signal generator are locked to. What I observed from measurements of this modulated tone is that that edges of the 1 KHz modulation appear at precisely the same sample indices relative to the integer-second boundary from acquisition-to-acquistion, however, the absolute phase of the 50 KHz tone relative to the edge of this 1KHz modulation varies significantly (>> 90 degs) from one acquisition to the next.  Just in case you are wondering, I independently confirmed that the 1 kHz modulation is phase locked to 3 GHz tone with a separate/independent setup. What this is telling me is that the time samples are true and aligned between acquisitions and that an embedded LO phase term appears to change between acquisitions. I’m not sure if such a term is arising from the analog AD9361 frontend, some known shift that results in the FPGA signal processing, or perhaps elsewhere.

Does anyone know if the behavior I’ve described here to be expected?  Any insight that you can offer would be greatly appreciated.

Best regards,
Chris

Hi Marcus, In response to your message, When you say you do "multiple acquisitions", how exactly are you doing that? Unless you're continuously streaming, various bits and pieces get "idled" and brought back up between runs. I’ve included a snippet of the code below that I use to perform the collections. I am not streaming samples continuously as you can see below. Rather, an external client makes a requests to collects the specified number of samples asynchronously but, since I am not reseting the clock or retuning any parameters between these acquisitions (at least that I am aware of), I thought the phase of the samples would remain continuous across async requests - perhaps this is not the case? Thanks, Chris //----------Setup the USRP: START ------------------// //create a receive streamer uhd::stream_args_t stream_args("sc16", wire); //complex floats stream_args.channels = channel_nums; uhd::rx_streamer::sptr rx_stream = usrp->get_rx_stream(stream_args); //setup streaming uhd::stream_cmd_t stream_cmd(uhd::stream_cmd_t::STREAM_MODE_NUM_SAMPS_AND_DONE); stream_cmd.num_samps = total_num_samps; stream_cmd.stream_now = false; ts = usrp->get_time_now(); stream_cmd.time_spec = uhd::time_spec_t( (double) ts.get_full_secs() + seconds_in_future); //stream_cmd.time_spec = uhd::time_spec_t(seconds_in_future); rx_stream->issue_stream_cmd(stream_cmd); //allocate buffer to receive with samples std::vector<std::complex<short> > buff_RFa(rx_stream->get_max_num_samps()); std::vector<std::complex<short> > buff_RFb(rx_stream->get_max_num_samps()); std::vector<void *> buffs; buffs.push_back(&buff_RFa.front()); //same buffer for each channel buffs.push_back(&buff_RFb.front()); //same buffer for each channel //allocate memory for arrays of samples for each channel samples_RFa = (char *) malloc(total_num_samps * sizeof(std::complex<short>)); samples_RFb = (char *) malloc(total_num_samps * sizeof(std::complex<short>)); for(m = 0;m < (total_num_samps * sizeof(std::complex<short>));m++){ samples_RFa[m] = 32; samples_RFb[m] = 32; } //----------Setup the USRP: STOP ------------------// //----------Data Acquisition: START ------------------// //the first call to recv() will block this many seconds before receiving double timeout = seconds_in_future + 0.1; //timeout (delay before receive + padding) size_t m,num_acc_samps = 0; //number of accumulated samples int fcount=0,pkt_cnt = 0; int ftot=3000; short int tt_n, tt_o=1; while( (num_acc_samps < total_num_samps) ){ //receive a single packet size_t num_rx_samps = rx_stream->recv(buffs, buff_RFa.size(), md, timeout, true); if ( num_acc_samps == 0 ){ //get frac seconds offset for first frame t0_d = md.time_spec.get_frac_secs(); t0_d_a[0] = t0_d ; t0 = (char *) t0_d_a; } //use a small timeout for subsequent packets timeout = 0.1; //handle the error code if (md.error_code == uhd::rx_metadata_t::ERROR_CODE_TIMEOUT) break; if (md.error_code != uhd::rx_metadata_t::ERROR_CODE_NONE){ throw std::runtime_error(str(boost::format( "Receiver error %s") % md.strerror())); } if(verbose) std::cout << boost::format( "Received packet: %u tot samples, %u rx samples, %u full secs, %f frac secs" ) % num_acc_samps % num_rx_samps % md.time_spec.get_full_secs() % md.time_spec.get_frac_secs() << std::endl; memcpy(samples_RFa + 4 * num_acc_samps, (const char*) &buff_RFa[0], num_rx_samps * sizeof(std::complex<short>)); memcpy(samples_RFb + num_acc_samps *sizeof(std::complex<short>), (const char*) &buff_RFb[0], num_rx_samps * sizeof(std::complex<short>)); num_acc_samps += num_rx_samps; } stream_cmd.stream_mode = uhd::stream_cmd_t::STREAM_MODE_STOP_CONTINUOUS; rx_stream->issue_stream_cmd(stream_cmd); if (num_acc_samps < total_num_samps) std::cerr << "Receive timeout before all samples received..." << std::endl; //----------Data Acquisition: STOP ------------------// On Oct 18, 2016, at 3:38 PM, Beaudoin, Christopher J <Christopher_Beaudoin@uml.edu<mailto:Christopher_Beaudoin@uml.edu>> wrote: Hi, I’m developing an absolute phase detector with the B210 and establishing a consistent phase measurement (relative to the internal sampler clock) from acquisition-to-acquisition has proven difficult. I’m wondering if I have not configured the radio properly or if the device does not function in exactly the way that I am anticipating. In my setup, I have locked together the 10 MHz reference of the B210 and my external signal generator - the generator is providing a constant -30 dBm, 3 GHz tone. The B210 is configured to lock in the integer-N mode, I command the frontend LO frequency to 2999950000 Hz (i.e. 50 kHz offset from my 3 GHz tone), and I do not reset the clock nor do I re-tune any frequency/sample-rate parameters in between acquisitions. Configured in this way, I am anticipating that the absolute phase of the IQ samples at every integer second boundary to repeat precisely between acquisitions since there are an integer number of signal cycles in each second but the measured results indicate otherwise. To investigate lack of phase repeatability on the second’s boundary further, I pulse modulated the 3 GHz tone with a 1 kHz square wave derived from the same 10 MHz reference that the B210 and signal generator are locked to. What I observed from measurements of this modulated tone is that that edges of the 1 KHz modulation appear at precisely the same sample indices relative to the integer-second boundary from acquisition-to-acquistion, however, the absolute phase of the 50 KHz tone relative to the edge of this 1KHz modulation varies significantly (>> 90 degs) from one acquisition to the next. Just in case you are wondering, I independently confirmed that the 1 kHz modulation is phase locked to 3 GHz tone with a separate/independent setup. What this is telling me is that the time samples are true and aligned between acquisitions and that an embedded LO phase term appears to change between acquisitions. I’m not sure if such a term is arising from the analog AD9361 frontend, some known shift that results in the FPGA signal processing, or perhaps elsewhere. Does anyone know if the behavior I’ve described here to be expected? Any insight that you can offer would be greatly appreciated. Best regards, Chris
JH
Jeremy Hershberger
Wed, Oct 19, 2016 9:09 PM

Chris,

Some suggestions for you to try:

  1. Are you destroying the streamer object after stopping the streamer?
    It is not apparent from your code snippet whether or not the rx_streamer
    object persists from streaming run to streaming run.  I would recommend not
    destroying the streamer object between streaming runs.
  2. Rather than using get_time_now(), perhaps switch to using the
    internal PPS timekeeping.  get_time_last_pps() would align your captures to
    1 sec boundaries, might help with any timing variances.  No idea if your
    application can accept the max possible delay of 1sec on an async request.
    However, this might be worth trying just to see if it helps
  3. You mentioned a single-channel application, are you using the second
    rx channel?  This might be used in some fashion to help estimate the phase
    as both rx channels share the same LO.
  4. As a last ditch effort, you could just burn up the usb link by rx'ing
    continuously and only keeping the samples if requested by your system.
    This would require some testing as USB performance can vary over time, and
    might crash randomly.  Again it depends on what your application can
    tolerate.

Cheers,

-Jeremy

On Wed, Oct 19, 2016 at 2:39 PM, Beaudoin, Christopher J via USRP-users <
usrp-users@lists.ettus.com> wrote:

Hi Marcus,

  In response to your message,

When you say you do "multiple acquisitions", how exactly are you doing
that?    Unless you're continuously streaming, various bits and
pieces get "idled" and brought back up between runs.

I’ve included a snippet of the code below that I use to perform the
collections. I am not streaming samples continuously as you can see below.
Rather, an external client makes a requests to collects the specified
number of samples asynchronously but, since I am not reseting the clock or
retuning any parameters between these acquisitions (at least that I am
aware of), I thought the phase of the samples would remain continuous
across async requests - perhaps this is not the case?

Thanks,
Chris

//----------Setup the USRP:          START ------------------//

//create a receive streamer
uhd::stream_args_t stream_args("sc16", wire); //complex floats
stream_args.channels = channel_nums;
uhd::rx_streamer::sptr rx_stream = usrp->get_rx_stream(stream_args);

//setup streaming
uhd::stream_cmd_t stream_cmd(uhd::stream_cmd_t::STREAM_MODE_NUM_SAMPS_AND_
DONE);
stream_cmd.num_samps = total_num_samps;
stream_cmd.stream_now = false;

ts = usrp->get_time_now();
stream_cmd.time_spec = uhd::time_spec_t( (double) ts.get_full_secs() +
seconds_in_future);
//stream_cmd.time_spec = uhd::time_spec_t(seconds_in_future);
rx_stream->issue_stream_cmd(stream_cmd);

//allocate buffer to receive with samples
std::vector<std::complex<short> > buff_RFa(rx_stream->get_max_
num_samps());
std::vector<std::complex<short> > buff_RFb(rx_stream->get_max_
num_samps());
std::vector<void *> buffs;
buffs.push_back(&buff_RFa.front()); //same buffer for each channel
buffs.push_back(&buff_RFb.front()); //same buffer for each channel

//allocate memory for arrays of samples for each channel
samples_RFa = (char *) malloc(total_num_samps *
sizeof(std::complex<short>));
samples_RFb = (char *) malloc(total_num_samps *
sizeof(std::complex<short>));

for(m = 0;m < (total_num_samps * sizeof(std::complex<short>));m++){
samples_RFa[m] = 32;
samples_RFb[m] = 32;
}

//----------Setup the USRP:          STOP  ------------------//

//----------Data Acquisition:        START ------------------//

//the first call to recv() will block this many seconds before receiving

double timeout = seconds_in_future + 0.1; //timeout (delay before receive

  • padding)

size_t m,num_acc_samps = 0; //number of accumulated samples
int fcount=0,pkt_cnt = 0;
int ftot=3000;
short int tt_n, tt_o=1;

while( (num_acc_samps < total_num_samps) ){
//receive a single packet
size_t num_rx_samps = rx_stream->recv(buffs, buff_RFa.size(), md, timeout,
true);

if ( num_acc_samps == 0 ){ //get frac seconds offset for first frame
t0_d = md.time_spec.get_frac_secs();
t0_d_a[0] = t0_d ;
t0 = (char *) t0_d_a;
}

//use a small timeout for subsequent packets
timeout = 0.1;

//handle the error code
if (md.error_code == uhd::rx_metadata_t::ERROR_CODE_TIMEOUT) break;
if (md.error_code != uhd::rx_metadata_t::ERROR_CODE_NONE){
throw std::runtime_error(str(boost::format(
"Receiver error %s") % md.strerror()));
}

if(verbose) std::cout << boost::format(
"Received packet: %u tot samples, %u rx samples, %u full secs, %f frac
secs"
) % num_acc_samps % num_rx_samps % md.time_spec.get_full_secs() %
md.time_spec.get_frac_secs() << std::endl;

memcpy(samples_RFa + 4 * num_acc_samps,
(const char*) &buff_RFa[0],
num_rx_samps * sizeof(std::complex<short>));

memcpy(samples_RFb + num_acc_samps sizeof(std::complex<short>),
(const char
) &buff_RFb[0],
num_rx_samps * sizeof(std::complex<short>));

num_acc_samps += num_rx_samps;
}
stream_cmd.stream_mode = uhd::stream_cmd_t::STREAM_MODE_STOP_CONTINUOUS;
rx_stream->issue_stream_cmd(stream_cmd);

if (num_acc_samps < total_num_samps) std::cerr << "Receive timeout before
all samples received..." << std::endl;

//----------Data Acquisition:        STOP  ------------------//

On Oct 18, 2016, at 3:38 PM, Beaudoin, Christopher J <
Christopher_Beaudoin@uml.edu> wrote:

Hi,

  I’m developing an absolute phase detector with the B210 and

establishing a consistent phase measurement (relative to the internal
sampler clock) from acquisition-to-acquisition has proven difficult. I’m
wondering if I have not configured the radio properly or if the device does
not function in exactly the way that I am anticipating. In my setup, I have
locked together the 10 MHz reference of the B210 and my external signal
generator - the generator is providing a constant -30 dBm, 3 GHz tone. The
B210 is configured to lock in the integer-N mode, I command the frontend LO
frequency to 2999950000 Hz (i.e. 50 kHz offset from my 3 GHz tone), and I
do not reset the clock nor do I re-tune any frequency/sample-rate
parameters in between acquisitions. Configured in this way, I am
anticipating that the absolute phase of the IQ samples at every integer
second boundary to repeat precisely between acquisitions since there are an
integer number of signal cycles in each second but the measured results
indicate otherwise.

To investigate lack of phase repeatability on the second’s boundary
further, I pulse modulated the 3 GHz tone with a 1 kHz square wave derived
from the same 10 MHz reference that the B210 and signal generator are
locked to. What I observed from measurements of this modulated tone is that
that edges of the 1 KHz modulation appear at precisely the same sample
indices relative to the integer-second boundary from
acquisition-to-acquistion, however, the absolute phase of the 50 KHz tone
relative to the edge of this 1KHz modulation varies significantly (>> 90
degs) from one acquisition to the next.  Just in case you are wondering, I
independently confirmed that the 1 kHz modulation is phase locked to 3 GHz
tone with a separate/independent setup. What this is telling me is that the
time samples are true and aligned between acquisitions and that an embedded
LO phase term appears to change between acquisitions. I’m not sure if such
a term is arising from the analog AD9361 frontend, some known shift that
results in the FPGA signal processing, or perhaps elsewhere.

Does anyone know if the behavior I’ve described here to be expected?  Any
insight that you can offer would be greatly appreciated.

Best regards,
Chris


USRP-users mailing list
USRP-users@lists.ettus.com
http://lists.ettus.com/mailman/listinfo/usrp-users_lists.ettus.com

Chris, Some suggestions for you to try: 1. Are you destroying the streamer object after stopping the streamer? It is not apparent from your code snippet whether or not the rx_streamer object persists from streaming run to streaming run. I would recommend not destroying the streamer object between streaming runs. 2. Rather than using get_time_now(), perhaps switch to using the internal PPS timekeeping. get_time_last_pps() would align your captures to 1 sec boundaries, might help with any timing variances. No idea if your application can accept the max possible delay of 1sec on an async request. However, this might be worth trying just to see if it helps 3. You mentioned a single-channel application, are you using the second rx channel? This might be used in some fashion to help estimate the phase as both rx channels share the same LO. 4. As a last ditch effort, you could just burn up the usb link by rx'ing continuously and only keeping the samples if requested by your system. This would require some testing as USB performance can vary over time, and might crash randomly. Again it depends on what your application can tolerate. Cheers, -Jeremy On Wed, Oct 19, 2016 at 2:39 PM, Beaudoin, Christopher J via USRP-users < usrp-users@lists.ettus.com> wrote: > Hi Marcus, > > In response to your message, > > When you say you do "multiple acquisitions", how exactly are you doing > that? Unless you're continuously streaming, various bits and > pieces get "idled" and brought back up between runs. > > I’ve included a snippet of the code below that I use to perform the > collections. I am not streaming samples continuously as you can see below. > Rather, an external client makes a requests to collects the specified > number of samples asynchronously but, since I am not reseting the clock or > retuning any parameters between these acquisitions (at least that I am > aware of), I thought the phase of the samples would remain continuous > across async requests - perhaps this is not the case? > > Thanks, > Chris > > > > //----------Setup the USRP: START ------------------// > > //create a receive streamer > uhd::stream_args_t stream_args("sc16", wire); //complex floats > stream_args.channels = channel_nums; > uhd::rx_streamer::sptr rx_stream = usrp->get_rx_stream(stream_args); > > //setup streaming > uhd::stream_cmd_t stream_cmd(uhd::stream_cmd_t::STREAM_MODE_NUM_SAMPS_AND_ > DONE); > stream_cmd.num_samps = total_num_samps; > stream_cmd.stream_now = false; > > > ts = usrp->get_time_now(); > stream_cmd.time_spec = uhd::time_spec_t( (double) ts.get_full_secs() + > seconds_in_future); > //stream_cmd.time_spec = uhd::time_spec_t(seconds_in_future); > rx_stream->issue_stream_cmd(stream_cmd); > > //allocate buffer to receive with samples > std::vector<std::complex<short> > buff_RFa(rx_stream->get_max_ > num_samps()); > std::vector<std::complex<short> > buff_RFb(rx_stream->get_max_ > num_samps()); > std::vector<void *> buffs; > buffs.push_back(&buff_RFa.front()); //same buffer for each channel > buffs.push_back(&buff_RFb.front()); //same buffer for each channel > > //allocate memory for arrays of samples for each channel > samples_RFa = (char *) malloc(total_num_samps * > sizeof(std::complex<short>)); > samples_RFb = (char *) malloc(total_num_samps * > sizeof(std::complex<short>)); > > > for(m = 0;m < (total_num_samps * sizeof(std::complex<short>));m++){ > samples_RFa[m] = 32; > samples_RFb[m] = 32; > } > > //----------Setup the USRP: STOP ------------------// > > //----------Data Acquisition: START ------------------// > > > //the first call to recv() will block this many seconds before receiving > > > double timeout = seconds_in_future + 0.1; //timeout (delay before receive > + padding) > > size_t m,num_acc_samps = 0; //number of accumulated samples > int fcount=0,pkt_cnt = 0; > int ftot=3000; > short int tt_n, tt_o=1; > > > while( (num_acc_samps < total_num_samps) ){ > //receive a single packet > size_t num_rx_samps = rx_stream->recv(buffs, buff_RFa.size(), md, timeout, > true); > > if ( num_acc_samps == 0 ){ //get frac seconds offset for first frame > t0_d = md.time_spec.get_frac_secs(); > t0_d_a[0] = t0_d ; > t0 = (char *) t0_d_a; > } > > //use a small timeout for subsequent packets > timeout = 0.1; > > //handle the error code > if (md.error_code == uhd::rx_metadata_t::ERROR_CODE_TIMEOUT) break; > if (md.error_code != uhd::rx_metadata_t::ERROR_CODE_NONE){ > throw std::runtime_error(str(boost::format( > "Receiver error %s") % md.strerror())); > } > > if(verbose) std::cout << boost::format( > "Received packet: %u tot samples, %u rx samples, %u full secs, %f frac > secs" > ) % num_acc_samps % num_rx_samps % md.time_spec.get_full_secs() % > md.time_spec.get_frac_secs() << std::endl; > > > memcpy(samples_RFa + 4 * num_acc_samps, > (const char*) &buff_RFa[0], > num_rx_samps * sizeof(std::complex<short>)); > > memcpy(samples_RFb + num_acc_samps *sizeof(std::complex<short>), > (const char*) &buff_RFb[0], > num_rx_samps * sizeof(std::complex<short>)); > > > > > num_acc_samps += num_rx_samps; > } > stream_cmd.stream_mode = uhd::stream_cmd_t::STREAM_MODE_STOP_CONTINUOUS; > rx_stream->issue_stream_cmd(stream_cmd); > > > > if (num_acc_samps < total_num_samps) std::cerr << "Receive timeout before > all samples received..." << std::endl; > > > //----------Data Acquisition: STOP ------------------// > > On Oct 18, 2016, at 3:38 PM, Beaudoin, Christopher J < > Christopher_Beaudoin@uml.edu> wrote: > > Hi, > > I’m developing an absolute phase detector with the B210 and > establishing a consistent phase measurement (relative to the internal > sampler clock) from acquisition-to-acquisition has proven difficult. I’m > wondering if I have not configured the radio properly or if the device does > not function in exactly the way that I am anticipating. In my setup, I have > locked together the 10 MHz reference of the B210 and my external signal > generator - the generator is providing a constant -30 dBm, 3 GHz tone. The > B210 is configured to lock in the integer-N mode, I command the frontend LO > frequency to 2999950000 Hz (i.e. 50 kHz offset from my 3 GHz tone), and I > do not reset the clock nor do I re-tune any frequency/sample-rate > parameters in between acquisitions. Configured in this way, I am > anticipating that the absolute phase of the IQ samples at every integer > second boundary to repeat precisely between acquisitions since there are an > integer number of signal cycles in each second but the measured results > indicate otherwise. > > To investigate lack of phase repeatability on the second’s boundary > further, I pulse modulated the 3 GHz tone with a 1 kHz square wave derived > from the same 10 MHz reference that the B210 and signal generator are > locked to. What I observed from measurements of this modulated tone is that > that edges of the 1 KHz modulation appear at precisely the same sample > indices relative to the integer-second boundary from > acquisition-to-acquistion, however, the absolute phase of the 50 KHz tone > relative to the edge of this 1KHz modulation varies significantly (>> 90 > degs) from one acquisition to the next. Just in case you are wondering, I > independently confirmed that the 1 kHz modulation is phase locked to 3 GHz > tone with a separate/independent setup. What this is telling me is that the > time samples are true and aligned between acquisitions and that an embedded > LO phase term appears to change between acquisitions. I’m not sure if such > a term is arising from the analog AD9361 frontend, some known shift that > results in the FPGA signal processing, or perhaps elsewhere. > > Does anyone know if the behavior I’ve described here to be expected? Any > insight that you can offer would be greatly appreciated. > > Best regards, > Chris > > > > _______________________________________________ > USRP-users mailing list > USRP-users@lists.ettus.com > http://lists.ettus.com/mailman/listinfo/usrp-users_lists.ettus.com > >