Discussion and technical support related to USRP, UHD, RFNoC
View all threadsHi,
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
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.
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
Chris,
Some suggestions for you to try:
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
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