In this second part I will explain how I made the stereo receiver.
Receiver graph
Following figure shows the finished receiver. I've cleaned it up (e.g. removed some unnecessary waveform displays) to have a clearer view of what is going on. I also added borders and numbers to denote different sections.Finished stereo FM broadcast receiver |
1. FM demodulation
The first section is the FM demodulator. I use the rtl-sdr block to interface with the radio module, then low pass filter the raw data and apply the FM demodulator. This block is the same as with mono receiver, except the demodulator low pass filter must be > 80 kHz and there must be no de-emphasis in this stage. The signal is then resampled to 384 kHz for faster calculations in later stages.The waveform sources are shown as disabled. If this was used with the ramp waveforms generated with the python script, the raw waveform should look like following.
Raw baseband signal |
2. Delay block
I found out that I need to delay the signal for clock reconstruction by 3 samples. Most likely this is due to the phase shift of the low-pass filters. If the delay was something else than 3 samples, the reconstructed audio signals were completely wrong.Here is how the clock signals look in the python script:
Clock signals in python script |
Clock signals in GRC |
3. 19 kHz pilot signal
The 19 kHz pilot signal is first bandpass filtered, to remove all other content from the signal. My understanding is that band pass filter should not cause phase shift at the center frequency, but I'm not completely sure. If it did cause delay, it could be compensated with the delay discussed previously.The filtered pilot signal is then fed into a PLL to regenerate a clean clock signal with amplitude of 1.0. The minimum and maxium frequencies are given as radians per sample and are calculated with the variables. I gave something like +-50 Hz range for the PLL.
The bandwidth of the PLL is set to a very small value, by trial and error. I noticed that large bandwidth changed the output from sinusoidal to square wave and also I think the PLL should not respond to fast changes but rather gradually correct any phase or frequency errors. 200e-6 seemed to work fine.
4. 38 kHz carrier
The 38 kHz carrier signal is generated by squaring the PLL output. The resulting waveform contains multiple harmonics and only the 2nd harmonic is bandpass filtered. This results in clean output in the same phase as the PLL output.I added gain of 2 here, but it could also be added later. The difference signal needs to be doubled in amplitude to give correct output.
5. Difference signal demodulation
The difference (L-R, "stereo") signal is obtained by demodulating the AM signal with the 38 kHz carrier, i.e. multiplying the raw baseband signal with the carrier and then low pass filtering with 15 kHz filter.6. Sum (mono) signal
The mono signal (sum, L+R) is got simply be low-pass filtering with 15 kHz the raw baseband signal, in the same way as with the mono receiver.Now that we have both mono and "stereo" signals, we can compare them to the output of the python script.
Sum and difference signals from python |
Sum and difference signals from GRC |
7. Channel reconstruction
Now that we seem to have correct data, we can reconstruct the audio signals. Left channel is the sum of the two streams 0.5*(L+R)+0.5*(L-R) =L and right channel is the difference 0.5*(L+R)-0.5*(L+R)=R.After addition or subtraction, the de-emphasis filter is applied for both channels and they are resampled to 48 kHz and fed to an audio sink. We can still compare the original waveforms from python to what was received.
Original left and right channel data from python |
"Received" left and right waveforms in GRC |
Conclusion
I uploaded two versions of the receiver to my GitHub.- 1st version is the cleand up version without additional waveform displays
- 2nd version contains the waveform displays that can be used to compare the python script output to GRC.
I also added a checkbox to enable stereo decoding (which changes the "stereo" channel low pass filter gain from 1.0 to 0.0 if stereo is disabled) so that it is easy to compare the audio quality.
Ei kommentteja:
Lähetä kommentti