[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Discuss-gnuradio] Modified wfm_rcv_pll, usrp_wfm_rcv_pll blocks, and gr

From: Robert McGwier
Subject: [Discuss-gnuradio] Modified wfm_rcv_pll, usrp_wfm_rcv_pll blocks, and gr_filter blocks
Date: Mon, 06 Feb 2006 22:35:02 -0500
User-agent: Thunderbird 1.5 (Windows/20051201)

Today Eric showed me how to use gr_kludge_copy to finish the modifications to wfm_rcv_pll and we now have stereo receive on FM. These modification are a testimonial to the GnuRadio code and the ease with which it can be used to glue things together. I wrote the lines down, Eric put in gr.kludge and it just worked the first time. This

Matt Ettus caught a stupid bug in the pll receiver. It is a second order PLL. Effectively the phase gain was too small by 1/3 and it was hugely overdamped. We can now do a complex FIR band pass filter gr.firdes.complex_band_pass designs the bandpass. Then you can use gr_fir_filter_?cc to filter the input signal with the filter in the usual overlap add manner

After this was done, stereo was a hop-skip-jump. Let me attempt to describe it.

Tuner -> A/D -> USRP ->  ///software in PC///

Tuner -> A/D -> FPGA

is the TV tuner and the A/D's on the USRP and the FPGA is doing numerically controlled oscillator and half band filtering to downconvert and downsample the signal.

///Software in PC///

Before today's code, the base FM station signal was being sent to the sound system and it was monoaural. The PLL is doing a fine job of demodulating the FM signal (with Matt's fix) and now it is easy to see the stereo carrier, multiplex, and the RDS signal if they are present. We definitely have some work to do on the de-emphasis but that can wait. it appears to me that the de-emphasis is too strongly tapered.

So we have this signal coming from the USRP and we run it through a PLL detector for FM that takes the 150 kHz signal in and spits detector audio out. This is run into the de-emphasis filter.

We ran a filter on the audio:

self.audio_filter = gr.fir_filter_fff (audio_decimation, audio_coeffs)

where the wider band signal with all of the extra content had the base audio signal filtered off. The filter was run and the (now lowpass) signal is decimated down to a rate for sending to the sound card.

This used to be done in a statement that looked like this:

fg.connect (self.fm_demod, self.deemph, self.audio_filter)

This takes the fm demod output, does deemphasis,  and then filters.

There are at least three other signals that might be in an FM broadcast.

If the broadcast is stereo, there are two more minimum. If you had a stereo signal and you could not decode the stereo, what would you want to send out the monoaural sink? You would lose the separation but acceptable audio would be present if you send Left + Right down the monoaural pipe. Then it is clear what you want transmit in any extra channel, you need L-R or R-L.

FM carrier transmit a carrier signal at 19 kHz and double side band suppressed carrier (DSBSC) centered at 38 kHz. If you square the FM carrier signal at 19 kHz, you get the exact carrier needed to perfectly baseband the DSBSC. By perfect what do I mean? DSBSC means the analytic is real. If perfectly basebanded (the center frequency at zero and the phase set correctly), the imaginary channel has zero in it and all of the relevant signal is in the real part.
So,  we build a complex filter for the carrier at -19000 Hz:

stereo_carrier_filter_coeffs = gr.firdes.complex_band_pass(10.0*volume*fm_demod_gain, demod_rate,
width_of_transition_band, gr.firdes.WIN_HAMMING)

Notice that the audio transmitted by the FM is real. That means it has negative and positive frequency content. Also recall from the previous paragraph that we need to base band the DSBSC "perfectly", so we will save some operations and pick off the "negative frequency" component of the carrier. This will be explained further in a moment along with gain.

The DSBSC signal contain Left minus Right (L-R) is centered at 38 kHz and is audio_rate wide. Lets build a filter for the DSBSC.

stereo_dsbsc_filter_coeffs = gr.firdes.complex_band_pass(10.0*volume*fm_demod_gain, demod_rate, 38000-audio_rate/2, 38000+audio_rate/2, width_of_transition_band, gr.firdes.WIN_HAMMING)

Again we have made a complex filter but this one is centered at +38000 Hz and is audio_rate wide. Both of these filters have a transition bandwith that attenuates the nearby signals to keep them from interfering. Both of these filters are done with 10 dB of gain. In my reading, several articles say the carrier and DSBSC signal are added to the main audio attenuated by 10 dB. THIS APPEARS TO BE RIGHT FROM THE RESULTS but if someone knows better, let us know.

We need to square the carrier freq so we will use a complex multiply:

           self.stereo_carrier_generator = gr.multiply_cc();

We will also need a mixer to use the carrier to baseband the DSBSC audio. A mixer for us is a complex multiply

           self.stereo_basebander = gr.multiply_cc();

Now some utilties:

           self.LmR_real = gr.complex_to_real();
           self.Make_Left = gr.add_ff();
           self.Make_Right = gr.sub_ff();

We are going to produce a complex signal at baseband with the DSBSC signal in it. The imaginary component in an ideal world is zero so we will pick off the real part and this will be L-R audio.

The carrier will be filtered with the standard overlap add:

self.stereo_carrier_filter = gr.fir_filter_fcc(audio_decimation, stereo_carrier_filter_coeffs)

and so will the DSBSC:

self.stereo_dsbsc_filter = gr.fir_filter_fcc(audio_decimation, stereo_dsbsc_filter_coeffs)

Now that we have everything set up, lets explain the new stereo decoder:

fg.connect (self.fm_demod, self.deemph)

this demods the signal and sends it to the de-emphasis filter.

       if 1:

# send the real signal to complex filter to pick off the carrier and then to one side of a multiplier fg.connect (self.deemph,self.stereo_carrier_filter, (self.stereo_carrier_generator,0)) # send the already filtered carrier to the otherside of the carrier fg.connect (self.stereo_carrier_filter, (self.stereo_carrier_generator,1)) # the resulting signal from this multiplier is the carrier with correct phase but at -38000 Hz.

           # send the new carrier to one side of the mixer (multiplier)
fg.connect (self.stereo_carrier_generator, (self.stereo_basebander,0)) # send the demphasized audio to the DSBSC pick off filter, the complex # DSBSC signal at +38000 Hz is sent to the other side of the mixer/multiplier fg.connect (self.deemph,self.stereo_dsbsc_filter, (self.stereo_basebander,1))
           # the result is BASEBANDED DSBSC with phase zero!

# Pick off the real part since the imaginary is theoretically zero and then to one side of a summer fg.connect (self.stereo_basebander,self.LmR_real,(self.Make_Left,0)) #take the same real part of the DSBSC baseband signal and send it to negative side of a subtracter
           fg.connect (self.LmR_real,(self.Make_Right,1))

       if 1:
# pick off the audio, L+R that is what we used to have and send it to the summer
           fg.connect(self.deemph, self.audio_filter, (self.Make_Left, 1))
# take the picked off L+R audio and send it to the PLUS side of the subtractor
           fg.connect(self.audio_filter, (self.Make_Right, 0))
# The result of Make_Left gets (L+R) + (L-R) and results in 2*L # The result of Make_Right gets (L+R) - (L-R) and results in 2*R

           # kludge the signals into a stereo channel
           kludge = gr.kludge_copy(gr.sizeof_float)
           fg.connect(self.Make_Left , (kludge, 0))
           fg.connect(self.Make_Right, (kludge, 1))

          #send it to the audio system
self.fm_demod, # head of the pipeline kludge) # tail of the pipeline

This is not perfect yet but it does work. We need to work on the pre-emphasis and possibly on the gains for the carrier and DSBSC filters but the stereo separation is apparent. It appears to me that the result L-R signal is down a few dB from where it should be. This will be revisited until we are all happy.

Next after this is to decode the RDS signal at 57 kHz in the demphasized audio. It has 1200 bps of data. This is usually the radio station and/or the current song or show on the channel.

Happy FM'ing

AMSAT VP Engineering. Member: ARRL, AMSAT-DL, TAPR, Packrats,
Laziness is the number one inspiration for ingenuity.  Guilty as charged!

reply via email to

[Prev in Thread] Current Thread [Next in Thread]