As a test, I am sending a GMSK signal (created by a signal generator,
very low noise) at low symbol rates into the USRP and plotting the
complex
baseband that reaches the PC. One would expect to see a nice tight unit
circle, and at low decimation rates (-d 16, etc) this is indeed the
case.
However, when I increase the decimation rate, the unit circle grows
“thicker”, which seems to indicate amplitude distortion. At -d 256 the
distortion is quite bad. Any idea what could be going on here? This
shows up
whether using either the TVRX daughtercard or the BasicRX. Something
going
on with the DDC in the FPGA? Filter ripple?
I am considering making a modified version of gr_quadrature_demod
that
would better handle residual carrier frequency error. The output of
gr_quadrature_demod_cf::work should average to 0 over the long term if
there’s no residual carrier, but will be nonzero otherwise. So the basic
idea is to average the “d_gain * gr_fast_atan2f(imag(product),
real(product));” values and subtract them out. Is this a reasonable
approach? A lot of this depends on how many samples the work function
receives to operate on. Who calls the work function of the various
blocks in
the flow graph, and what determines the size of noutput_items? Is there
a
way to set bounds on noutput_items? How do I insure that I’m averaging
over
a sufficient window?
On Wed, Mar 14, 2007 at 03:45:32PM -0400, Steven C. wrote:
Hi all-
Two very different questions for you:
As a test, I am sending a GMSK signal (created by a signal generator,
very low noise) at low symbol rates into the USRP and plotting the complex
baseband that reaches the PC. One would expect to see a nice tight unit
circle, and at low decimation rates (-d 16, etc) this is indeed the case.
However, when I increase the decimation rate, the unit circle grows
“thicker”, which seems to indicate amplitude distortion. At -d 256 the
distortion is quite bad.
Are you plotting points or drawing lines between points?
Any idea what could be going on here? This shows up
whether using either the TVRX daughtercard or the BasicRX. Something going
on with the DDC in the FPGA? Filter ripple?
Where in the processing pipeline are you grabbing the data that you’re
plotting? Before or after the clock recovery block?
I am considering making a modified version of gr_quadrature_demod that
would better handle residual carrier frequency error. The output of
gr_quadrature_demod_cf::work should average to 0 over the long term if
there’s no residual carrier, but will be nonzero otherwise. So the basic
idea is to average the “d_gain * gr_fast_atan2f(imag(product),
real(product));” values and subtract them out. Is this a reasonable
approach?
You could do this downstream of the block with an IIR filter and a
subtractor.
A lot of this depends on how many samples the work function
receives to operate on.
I don’t see how this matters…
Who calls the work function of the various blocks in
the flow graph, and what determines the size of noutput_items? Is there a
way to set bounds on noutput_items? How do I insure that I’m averaging over
a sufficient window?
Instead of trying to second guess how the scheduler works, you’d be
better advised to carry around any state that you need to do the
work. As pointed out above, an IIR should do a fine job of
estimating the DC offset, which can then be subtracted.
[There are ways to bound noutput_items, but I wouldn’t recommend them
for this application. They tend to have unintended consequences.]
However, when I increase the decimation rate, the unit circle grows
“thicker”, which seems to indicate amplitude distortion. At -d 256 the
distortion is quite bad.
Are you plotting points or drawing lines between points?
Plotting just points. They are definitely at different amplitudes. I can
link plot images if that would help.
Any idea what could be going on here? This shows up
whether using either the TVRX daughtercard or the BasicRX. Something
going
on with the DDC in the FPGA? Filter ripple?
Where in the processing pipeline are you grabbing the data that you’re
plotting? Before or after the clock recovery block?
I’m using usrp_rx_cfile.py. So hopefully I’m just looking at the raw
complex
baseband coming across USB. (incidentally, when you’re using sending a
complex stream to a file sink, is the first sample always real? I assume
so…)
I am considering making a modified version of gr_quadrature_demod that
would better handle residual carrier frequency error. The output of
gr_quadrature_demod_cf::work should average to 0 over the long term if
there’s no residual carrier, but will be nonzero otherwise. So the basic
idea is to average the “d_gain * gr_fast_atan2f(imag(product),
real(product));” values and subtract them out. Is this a reasonable
approach?
You could do this downstream of the block with an IIR filter and a
subtractor.
Thanks for the tip. I will have to think about this some more.
A lot of this depends on how many samples the work function
receives to operate on.
I don’t see how this matters…
I just meant that if I’m averaging, it’s better if the averaging window
is
larger so that I get a good sampling of points.
estimating the DC offset, which can then be subtracted.
[There are ways to bound noutput_items, but I wouldn’t recommend them
for this application. They tend to have unintended consequences.]
Sorry for the delayed response, I’ve been away for a bit. Regarding
losing
more of the sidebands due to the tighter filters @ higher decimation: I
was
matching the symbol rate of my transmitted signal to the decimation
rate.
I.e. at d=256 I set sym rate=31.25ksym/sec, at d=8 I used 250ksym/sec.
So it
should be chopping the same amount of sideband in either case. I’m going
to
continue looking into this, will let you guys know if I discover
anything
interesting.
Regarding improved carrier tracking for GMSK rx: Eric, your IIR filter
idea
seems to be working like a charm. Below is the relevant modification to
gmsk.py:
It seems to be working well… the only question is what to use for the
alpha value in the filter constructor. 0.0001 seems like a good
compromise
between converging to the correct value quickly and being relatively
stable.
Am I taking a reasonable approach with this design?
I just joined the gnuradio discussion but I found your question about
the
GMSK amplitude distortion interesting. My guess is that it’s aliasing.
GMSK
has good spectral efficiency but it still has spectral sidelobes that
get
folding into your desired passband when you decimate. I would suggest
filtering before decimating. Even better, since your decimating by
factors
of 2, you can use a half band filter that reduces the sample rate by 2
each
time. Or you could consider downsampling via a polyphase filter. I’d be
interesting in seeing the phase distortion too. Phase distortion is more
of
a concern for GMSK demodulation since it’s a phase modulation. Take the
phase of the input signal and the phase of the output signal and
difference
the two to get the phase error. You should see higher phase distortion
as
you decimate more especially if you don’t filter.
signal is going in to RX at -10dBm, default gain setting.
On 3/14/07, Eric B. [email protected] wrote:
On Wed, Mar 14, 2007 at 09:47:20PM -0400, Steven C. wrote:
Steve, what’s the real amplitude of the received baseband signal?
I suspect that you are normalizing to 1. Can you regenerate the plots
without normalizing so that we’ve got an idea of the values coming
across the USB.
Steve, what’s the real amplitude of the received baseband signal?
I suspect that you are normalizing to 1. Can you regenerate the plots
without normalizing so that we’ve got an idea of the values coming
across the USB.
GMSK is a constant amplitude modulation. So unless I am misunderstanding
something (which is entirely possible), if you plot the complex baseband
signal with real for X and imag for Y, the result should be a
constant-amplitude circle regardless of where in the symbol you are
sampling, and regardless of any carrier freq discrepancy between the tx and
rx. A carrier freq offset will make the phasor spin faster or slower, but it
should still have constant magnitude.
I’d be interested if you could point me to some of your plots. It
sounds interesting.
essentially high-pass filter the output of the FM demod to get rid of the DC
offset. Were you recommending low-pass filtering the FM demod output to
estimate the DC bias and then subtracting that off from the original signal?
Why an IIR filter rather than a FIR? Which IIR block would you choose?
You said before you were looking at using just a little bit of the
bandwidth, so why not sample such that you have an image of your
signal at some higher frequency, and use a DDC in the PC to get it
down to baseband - shifting your DC offset by that higher frequency
and then apply the LPF?
Plots of USRP decimation woes:
input is GMSK waveform @ ~30ksym/sec, BT = 0.35, no noise added
using decimation rate of 16: http://img339.imageshack.us/img339/4467/d16cz9.jpg
top plot is complex baseband, bottom plot is amplitude of top plot
some amplitude variations noticeable, but fairly minor.
Plots showing effects of carrier discrepancy between tx and rx on GMSK
demodulation:
These are plots of the output of the fmdemod block (and of the input to
the
M&M clock recovery block).
Residual carrier manifests as DC offset after fmdemod (look at y-axis): http://img89.imageshack.us/img89/1116/fmdemoduntunedri8.jpg
sending input like this into the clock recovery block → lots of bit
errors,
especially when noise is added.
So, that’s the motivation for wanting carrier tracking. I think Eric’s
right
that there’s a solution involving filters that doesn’t require me to
leave
python-land, but I’m still a bit confused as to how to leverage the IIR
block.
There is always an unknown phase between the transmitter and receiver.
In addition, the clocks between the transmitter and receiver are never
running at exactly the same frequency. FWIW, the oscillator on the
USRP is spec’d to 50ppm.
Eric
GMSK is a constant amplitude modulation. So unless I am misunderstanding
something (which is entirely possible), if you plot the complex baseband
signal with real for X and imag for Y, the result should be a
constant-amplitude circle regardless of where in the symbol you are
sampling, and regardless of any carrier freq discrepancy between the tx
and
rx. A carrier freq offset will make the phasor spin faster or slower,
but it
should still have constant magnitude.
I’d seen the 50ppm number before, and that’s part of the reason I asked
the
second question about adding improved carrier recovery. I was noticing a
freq difference of ~5 kHz @ somewhere in the 200-300MHz range (that’s
about
20ppm, so in line with our expectations), and it was really making the
M&M
clock recovery block in gmsk.py struggle. I’m guessing that M&M depends
on
zero crossings for clock recovery, so when it’s input (which is normally
in
the [-1, 1] range) gets a DC offset such that it’s now [-0.5, 1.5] for
example, it has problems.
I’m interested in your IIR suggestion. It seems like what we want to do
is
essentially high-pass filter the output of the FM demod to get rid of
the DC
offset. Were you recommending low-pass filtering the FM demod output to
estimate the DC bias and then subtracting that off from the original
signal?
Why an IIR filter rather than a FIR? Which IIR block would you choose?
On Wed, Mar 14, 2007 at 05:54:03PM -0400, Steven C. wrote:
I’m using usrp_rx_cfile.py. So hopefully I’m just looking at the raw
complex
baseband coming across USB.
No surprise, you’re not sampling at the center of the symbols.
Eh? I’m using the -f command line argument to tune the USRP to the center of
my signal.
There is always an unknown phase between the transmitter and receiver.
In addition, the clocks between the transmitter and receiver are never
running at exactly the same frequency. FWIW, the oscillator on the
USRP is spec’d to 50ppm.
I’m waiting on hearing the results of low pass filtering the “perfect
samples” without decimation, and seeing if the problem still exists.
I was driving home from work and was remembering that GMSK has a good
amount of ISI built in. When looking at a very low 1 sps or 2 sps,
that interference will be very apparent - won’t it?
signal is going in to RX at -10dBm, default gain setting.
Steve,
Can you try this experiment?
Using your perfect samples (the ones you get with decim=8), can you
try low pass filtering them (without decimating) to the equivalent
width that you’d get with the decim=256 setting, and then plotting
them?
Maybe it’s not perfectly round because with the narrower filter, we’re
losing more of the sidebands. IIRC it’s only constant envelope with
infinite sidebands.
Or for a different experiment: feed in a complex sinusoid with no
modulation, and see what happens with the decim=8 and decim=256 cases.
On Sat, Mar 17, 2007 at 08:00:59AM -0700, Mike Garcia wrote:
Thanks Eric. That makes sense. I’m still learning about gnuradio so excuse
my naivete. Could the distortion be cause by the CIC filters? I understand a
CIC filter needs some amount of bit growth. If the LSBs are truncated
instead, then that amounts to adding noise to the system. This may be
unavoidable but might explain the distortion you’re seeing.
Mike
I don’t think it’s a problem in the CIC. They have enough width to
accomodate the maximum decimation (usrp/fpga/sdr_lib/cic_decim.v)
I’m waiting on hearing the results of low pass filtering the “perfect
samples” without decimation, and seeing if the problem still exists.
Thanks Eric. That makes sense. I’m still learning about gnuradio so
excuse
my naivete. Could the distortion be cause by the CIC filters? I
understand a
CIC filter needs some amount of bit growth. If the LSBs are truncated
instead, then that amounts to adding noise to the system. This may be
unavoidable but might explain the distortion you’re seeing.
On Fri, Mar 16, 2007 at 08:07:33PM -0700, Mike Garcia wrote:
a concern for GMSK demodulation since it’s a phase modulation. Take the
phase of the input signal and the phase of the output signal and difference
the two to get the phase error. You should see higher phase distortion as
you decimate more especially if you don’t filter.
Mike
Hi Mike, thanks for your comments.
We do filter when decimating, otherwise nothing would work. The first
N/2 decimation is handled with a 4th-order CIC, the final decimation
by two is done with a halfband.
The Cylone doesn’t have any h/w multipliers, so using a halfband at
each stage is not feasible.
Eric
This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.