Some usrp_spectrum_sense.py code Explanation

Hi Everybody,

and Merry Christmas

I received many emails requesting some explanation for
usrp_spectrum_sense.py gnuradio example program. The following link
contains
the code with some explanation and one bug fix (in self.max_center_freq
equation):

http://rapidshare.com/files/177960860/usrp_spectrum_sense.py

usrp_spectrum_sense.py Explanation :

Introduction:

  1. This program can be used as a basic code for implementing wideband
    spectrum analyzer.
  2. As we know, the USRP cannot examine more than 8 MHz of RF spectrum
    due to
    USB bus limitations.
  3. So, to scan across a wide RF spectrum band (bigger than 8 MHz) we
    have to
    tune USRP RF front end in suitable steps so that we can examine a lot of
    spectrum, although not all at the same instant.
  4. The usrp_spectrum_sense shows the way how it can be done.It steps
    across
    the spectrum and make the RF measurements. This application can
    sense a large bandwidth, but not in real time, and it can do the
    frequency
    sweep over the required frequency range,

Theory:

  1. To use N points complex FFT X(W) analysis, we have to get N time
    samples
    x(t) which are sampled at Fs.
  2. These N time samples must be time windowed using a known window
    function
    to reduce spectral leakage.
  3. Performing N points complex FFT analysis.
  4. The output of the complex FFT will represent the frequency spectrum
    contents as follows:

a) The first value of the FFT output (bin 0 == X[0]) is the passband
center
frequency.
b) The first half of the FFT (X[1] to X[N/2-1] contains the positive
baseband frequencies,which corresponds to the passband spectrum from the
center frequency out to the maximum passband frequency (from center
frequency to +Fs/2).
c) The second half of the FFT (X[N/2] to X[N-1]) contains the negative
baseband frequencies,which correspond to the lowest passband frequency
up to
the passband center frequency (from -Fs/2 to center frequency).

Example

Let us assume that we have 1024 (I and Q) samples gathered using a tuner
centered at 20MHz. And let us assume that the sampling frequency was
8MHz.
Doing 1024 points complex FFT means:

  1. FFT Frequency resolution is : 8MHz / 1024 = 7812.5 KHz
  2. The output of the FFT X[0] represents the spectrum at 20MHz.
  3. The output of the FFT X[1] to X[511] represents the frequencies from
    20.0078125 MHz to 23.9921875 MHz (about 4MHz above center frequency).
  4. The output of the FFT X[512] to X[1023] represents the frequencies
    from
    16.0078125 MHz to 19.9921875 MHz (about 4MHz bellow center frequency).

RF Frequency Sweeping

  1. Let us suppose that we want to scan RF spectrum band from 10MHz to 52
    MHz.
  2. Let us remember that USRP can analyze 8MHz of frequency at a time.
  3. So theoretically we have to step our RF center frequency as follows:

First step is 14MHz (it will cover frequency band from 10MHz to 18MHz),
Second step is 22MHz (it will cover frequency band from 18MHz to 26MHz),
Third step is 30MHz (it will cover frequency band from 26MHz to 34MHz),
Fourth step is 38MHz (it will cover frequency band from 34MHz to 42MHz),
Fifth step is 46MHz (it will cover frequency band from 42MHz to 50MHz),
and finally the Sixth step is 54MHz (it will cover frequency band from
50MHz
to 58MHz). Remember that we want the frequencies up to 52MHz only, so we
have to discard some FFT points from the Sixth analysis.

  1. Paralytically we have to use FFT overlapping to reduce the non
    linearity
    response of the Digital Down Converter (the DDC frequency response is
    not
    Flat from -Fs/2 to + Fs/2) and to fill the frequency holes that will be
    present at the FFT analysis edges (10MHz, 18MHz, 26MHz, 34MHz, 42MHz, 50
    MHz).

So if we choose to use an overlap of 25%, this means that our step size
will
be 6MHz (8MHz*(1-.25)), thus practically we have to step our RF center
frequency as follows:

First step is 13MHz (it will cover frequency band from 9MHz to 17MHz),
Second step is 19MHz (it will cover frequency band from 15MHz to 23MHz),
Third step is 25MHz (it will cover frequency band from 21MHz to 29MHz),
Fourth step is 31MHz (it will cover frequency band from 27MHz to 35MHz),
Fifth step is 37MHz (it will cover frequency band from 33MHz to 41MHz),
Sixth step is 43MHz (it will cover frequency band from 39MHz to 47MHz),
and Finally the Seventh step is 49MHz (it will cover frequency band from
45MHz to 53MHz),

Changing RF center Frequency

  1. To change USRP RF center frequency we have to send a tunning command
    to
    the USRP every time we complete the analysis of the current frequency
    chunk.
  2. Before gnuradio revision [10165], all USRP RF daughterboards tunning
    were
    done using Python functions and classes. After that revision, tunning
    the
    USRP daughterboards from withen C++ code is possible.
  3. In usrp_spectrum_sense.py, the DSP C++ written code is allowed to
    transparently invoke Python code USRP tune function. This tunning
    control is
    done in gr_bin_statistics_f sink function.

Tunning Delay Problem:

When we command the usrp RF daughterboard to change its center
frequency, we
have to wait until (right) ADC samples arrive to our FFT engine and we
have
to insure that it belongs to the wanted center frequency. This
represents a
problem since there are many delays along the digitization path (RF
synthesizer settling time, and pipeline propagation delay [FPGA FIFO
filling
time, USB transferring time…etc]). To overcome this problem we have to
use
enough tune delay time in order to be sure that the samples entering
our
FFT block are belong to the requested center frequency. This is done
simply
by dropping the incoming received samples over a specified tunning delay
time.

usrp_spectrum_sense Implementation

  1. The engine of the usrp_spectrum_sense depends mainly on
    bin_statistics
    sink function.

  2. bin_statistics function combines statistics gathering with a state
    machine for controlling the USRP RF tuning (frequency sweeping). It
    determines max values (keeps track of the maximum power in each FFT bin)
    of
    vectors (with length vlen) over a time period determined by dwell_delay
    (after converting it to a number of FFT vectors). This operation is
    performed after discarding tune_delay samples.

  3. After processing N = dwell_delay samples, bin_statistics composes a
    message and inserts it in a message queue.

  4. Each message from bin_statistics consists of a vector of max values,
    prefixed by the center frequency corresponding to the associated
    samples,
    i.e., it is the center frequency value of the delivered input samples to
    bin_statistics.

Choosing Tune and Dwell delay times

  1. We have to play with the --tune-delay and --dwell-delay command line
    options to determine appropriate timming values. The most important one
    is
    the tune delay time.

  2. The choose of tune-delay should include time for the front end PLL to
    settle, plus time for the new samples to propagate through the pipeline.
    The default value is 1ms, which is probably in the ballpark on the RFX**
    boards. The TV RX board is much slower. The tuner data sheets says it
    could take 100ms to settle.

  3. The tune delay timing parameter passed to bin_statistics is
    calculated in
    FFT frames which depends on USRP rate and FFT length as in :

tune_delay_passed_to_bin_statistics =
int(round(required_tune_delay_in_sec*usrp_rate/fft_size))

if this calculated value is less than “1”, then we should make it at
least
“1” FFT frame.

For example:

If the :

required_tune_delay_in_sec = 10e-3
and usrp_rate = 8000000 (decimation =8)
and FFT size is 1024

Then :

tune_delay_passed_to_bin_stats = 78 (FFT Frames)

This means we have to skip 78 incoming vectors (FFT frames) before we
actually use the acquired samples in our spectrum statistics.

  1. Beside tunning time depends on the hardware (RF synthesizer
    speed),one
    should remember that the time needed to collect 1024 samples
    with decimation rate=8 (minimum USRP decimation) is 128 usec, while the
    time
    needed to collect 1024 samples with decimation rate=256 (maximum USRP
    decimation) is 4.096 msec.
    This means that the tune delay in the case of decimation rate =256
    should be
    larger than that used for decimation = 8.

  2. A working tune delay value (which gives accurate results) can be
    known by
    experiments (for given decimation rate and FFT length).

Interrupting Output Spectrum

The actual mapping from the levels at the daughterboard antenna input
port
to the output analysis values depends on a lot of factors including the
used
daughterboard RF gain and decimation specific gain in the digital down
converter. You’ll need to calibrate the system if you need something
that
maps to dBm.Currently, the output of usrp_spectrum_sense is the
magnitude
squared of the FFT output. That is, for each FFT bin[i], the output is
Y[i]
= re[X[i]]*re[X[i]] + im[X[i]]*im[X[i]]. If you want power, take the
square
root of the output.

========================================================================================

Best Regards,

Firas

View this message in context:
http://www.nabble.com/Some-usrp_spectrum_sense.py-code-Explanation-tp21209623p21209623.html
Sent from the GnuRadio mailing list archive at Nabble.com.

Interrupting Output Spectrum

The actual mapping from the levels at the daughterboard antenna input
port
to the output analysis values depends on a lot of factors including the
used
daughterboard RF gain and decimation specific gain in the digital down
converter. You’ll need to calibrate the system if you need something
that
maps to dBm.Currently, the output of usrp_spectrum_sense is the
magnitude
squared of the FFT output. That is, for each FFT bin[i], the output is
Y[i]
= re[X[i]]*re[X[i]] + im[X[i]]*im[X[i]]. If you want power, take the
square
root of the output.

========================================================================================
Hi, Firas
In my opinion the ouput Y[i] has the same dimension with the power. If
we
square root the output, and divide it with the fft bin numbers, then we
get
the voltage magnitude.
Am I right?

Best Regards,
Ling


View this message in context:
http://www.nabble.com/Some-usrp_spectrum_sense.py-code-Explanation-tp21209623p21214158.html
Sent from the GnuRadio mailing list archive at Nabble.com.

Hi,

— On Tue, 12/30/08, Ling H. [email protected] wrote:
Hi, Firas
In my opinion the ouput Y[i] has the same dimension with
the power. If we square root the output, and divide it with the fft bin
numbers, then we get the voltage magnitude. Am I right?

Best Regards,
Ling

Yes, If we square root the output, and divide it with the fft size, then
we will get the voltage magnitude.
Calculating 20 Log10 this value will give us the power.

Best Regards,

Firas

Example

Let us assume that we have 1024 (I and Q) samples gathered using a tuner
centered at 20MHz. And let us assume that the sampling frequency was
8MHz.
Doing 1024 points complex FFT means:

  1. FFT Frequency resolution is : 8MHz / 1024 = 7812.5 KHz

Shouldn’t this read 7.8 KHz ?

Hello

I am trying to use the usrp_spectrum_sense.py as an energy detector, and
I have appreciated your explanation of it. But I was wondering if you
have any code examples where you actually look at the data that is in
m.data? When I plot them they do not appear to be 10*log10(|fft
coeffcicients|^2) which was my understanding. Any help would be
appreciated.

Thanks

Scott Johnston

Firas A. wrote in post #764376:

Hi,

— On Tue, 12/30/08, Ling H. [email protected] wrote:
Hi, Firas
In my opinion the ouput Y[i] has the same dimension with
the power. If we square root the output, and divide it with the fft bin
numbers, then we get the voltage magnitude. Am I right?

Best Regards,
Ling

Yes, If we square root the output, and divide it with the fft size, then
we will get the voltage magnitude.
Calculating 20 Log10 this value will give us the power.

Best Regards,

Firas

Dear Firas,
I’m confused with such a question listed following:
To calculate the energy in certain bandwidth, we need to sum the bins in
m.data and then divide it by fft-size.We get the db power by 10 log10
this value.
However, in another way,we square root the output and divide it by the
fft-size and after that calculate 20log 10 this value to get the
power.Last, average the power of fft-size bins to get the average power
in certain
bandwidth.
It seems that two ways work differently and wonder where am I wrong?Hope
I’ve clarified my question clearly and appreciate your reply!Thx!
Jun