Usrp1 harmonic issue

Hello,

I am a beginner with USRP. Please help with my problem.

Please see the attached two pictures captured by a spectrum analyzer. In
usrp1_64MHz_harmonic.JPG, I just powered up the motherboard without any
daughterboard. I guess the harmonics comes from the fact that we have
64MHz
ADC. In rxf400_4MHz_harmonic.JPG, I transmit ofdm signal at 420MHz using
daughterboard RXF400. Beside the 64MHz harmonic coupling with the
transmit
signal, I also see the 4MHz harmonics.

Do you know why these happen and how to mitigate them? I appreciate your
answers.

Thank you,
Quoc

You are not seeing harmonics. You are seeing DC offset, which you have
not corrected for. Also, you seem to be transmitting a very low power
which results in your signal being below the DC offset level.

Matt

Matt E. <matt ettus.com> writes:

You are not seeing harmonics. You are seeing DC offset, which you have
not corrected for.
Is there any example which corrects the dc offset ?
So that we see, which commands are up to date.

Regards Markus

feldmaus <feldmann_markus gmx.de> writes:

Is there any example which corrects the dc offset ?
So that we see, which commands are up to date.

I think we have first to calculate the dc offset?
And the to adjust ?

To calculate the dc offset we can use:
usrp_cal_dc_offset:
usage: usrp_cal_dc_offset [-v] [-w which_side] [-D decim] [-c ddc_freq]
[-g gain]
[-S fusb_block_size] [-N fusb_nblocks]

And get for example this:
1715545 : 172 2597454 : 260

Which is side A and which one is side B ?
The ‘-w’ parameter doesn’t change anything, so how to use this correctly
?

To adjust the dc offset we can use:
set_dc_offset_cl_enable(self, int bits, int mask)
OR
set_adc_offset(self, int which_adc, int offset)

Can somebody please explain the different between these both functions ?
Which one should we use to adjust the offset ?

Regards Markus

On Mon, Mar 30, 2009 at 09:58:53AM +0000, feldmaus wrote:

usage: usrp_cal_dc_offset [-v] [-w which_side] [-D decim] [-c ddc_freq] [-g gain]
OR
set_adc_offset(self, int which_adc, int offset)

Can somebody please explain the different between these both functions ?
Which one should we use to adjust the offset ?

Regards Markus

A quick look at usrp_basic.h reveals:

/*!

  • \brief Enable/disable automatic DC offset removal control loop in
    FPGA
  • \param bits which control loops to enable
  • \param mask which \p bits to pay attention to
  • If the corresponding bit is set, enable the automatic DC
  • offset correction control loop.
  • 
    
  • The 4 low bits are significant:
  • ADC0 = (1 << 0)
  • ADC1 = (1 << 1)
  • ADC2 = (1 << 2)
  • ADC3 = (1 << 3)
  • By default the control loop is enabled on all ADC’s.
    */
    bool set_dc_offset_cl_enable(int bits, int mask);

/*!

  • \brief Set ADC offset correction
  • \param which which ADC[0,3]: 0 = RX_A I, 1 = RX_A Q…
  • \param offset 16-bit value to subtract from raw ADC input.
    */
    bool set_adc_offset (int which_adc, int offset);

As it says above, “By default the control loop is enabled on all ADC’s.”
You should leave it that way, with the possible exception of when
using the LF RX daughterboard.

Eric

Eric B. <eb comsec.com> writes:

  • 
    

bool set_dc_offset_cl_enable(int bits, int mask);
If i want to set no automatic ADC control loop, what do i have to do?
set_dc_offset_cl_enable(int(0), int(0))

DEC → BIN
int BITS: 0 → 0000 (for ADC_0)
int MASK: 0 → 0000
RESULT: 0000
In this case no ADC will get automatic loop ???
Is this correct ?

Regards Markus

Eric B. schrieb:

*/
bool set_adc_offset (int which_adc, int offset);

As it says above, “By default the control loop is enabled on all ADC’s.”
You should leave it that way, with the possible exception of when
using the LF RX daughterboard.

Eric
I am using the LFRX Db.

So do i have to use the bool
<set_adc_offset (int which_adc, int offset)>
manually ?
I tried that but i doesn’t seem to change anything.
Thereforwe i calculated the offset with the gnuradio tool:
<usrp_cal_dc_offset>
Where i not know about the correct using?

Regards Markus

On Tue, Mar 31, 2009 at 12:19:32PM +0000, feldmaus wrote:

  • offset correction control loop.
  • By default the control loop is enabled on all ADC’s.
    Is this correct ?

Regards Markus

To disable automatic ADC control on all ADC’s:

u.set_dc_offset_cl_enable(0x0, 0xf)

Then set the offset that you want for each ADC using:

u.set_adc_offset(0, offset0)
u.set_adc_offset(1, offset1)
u.set_adc_offset(2, offset2)
u.set_adc_offset(3, offset3)

Start with an offset of 0.

Note that the appropriate offset varies over temperature.

Eric

Eric B. <eb comsec.com> writes:

And if i only want to diable the automatic dc offset loop at
ADC_0 and ADC_1, then:
u.set_dc_offset_cl_enable(0x3, 0x3)

Is this correct ???

Regards Markus

On Wed, Apr 01, 2009 at 07:32:04AM +0000, feldmaus wrote:

u.set_adc_offset(2, offset2)
u.set_adc_offset(3, offset3)

And if i only want to diable the automatic dc offset loop at
ADC_0 and ADC_1, then:
u.set_dc_offset_cl_enable(0x3, 0x3)

Is this correct ???

No, you’d want

u.set_dc_offet_cl_enable(0x0, 0x3)

The mask specifies which of the bits will be touched. value is the
value you want for those bits. This allows us to do an atomic
read/modify/write.

If reg is a register in the FPGA, mask and value work like this:

reg = (reg & ~mask) | (value & mask);

Eric

feldmaus wrote:

Matt E. <matt ettus.com> writes:

You are not seeing harmonics. You are seeing DC offset, which you have
not corrected for.
Is there any example which corrects the dc offset ?
So that we see, which commands are up to date.

Everybody is talking about something different on this thread. The
original posting was talking about DC offset on transmit. We have code
to manually control the DC offset on transmit, but not to measure it.

Markus, you seem to be talking about DC offset on receive, which is
completely handled by the FPGA. You should have no need to change it
unless you are using the LFRX AND you care about accurate DC
measurements.

Matt

Markus F. schrieb:

u.set_adc_offset(0, offset0)
No, you’d want
u.set_adc_offset(2, offset2)
u.set_adc_offset(3, offset3)

As you wrote above, the mask is the bits you want to touch
and the bits is the value you want to store, but why do you
want to store a value of int(2) and int(3).
As i understand you, there are only 2 logically
values for the bits we store int(0) and int(1).

Is this correct ?
My mistake i mixed up the both methods. :slight_smile:

Regards Markus

Eric B. schrieb:

u.set_adc_offset(1, offset1)

u.set_dc_offet_cl_enable(0x0, 0x3)

The mask specifies which of the bits will be touched. value is the
value you want for those bits.
Hi and thanks for your answer,

but then i didn’t understand what you try with,
u.set_adc_offset(0, offset0)
u.set_adc_offset(1, offset1)
u.set_adc_offset(2, offset2)
u.set_adc_offset(3, offset3)

As you wrote above, the mask is the bits you want to touch
and the bits is the value you want to store, but why do you
want to store a value of int(2) and int(3).
As i understand you, there are only 2 logically
values for the bits we store int(0) and int(1).

Is this correct ?

Regards Markus