[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Discuss-gnuradio] DDC and Polyphase Channelizer
From: |
Tom Rondeau |
Subject: |
Re: [Discuss-gnuradio] DDC and Polyphase Channelizer |
Date: |
Tue, 28 Dec 2010 11:58:59 -0500 |
On Mon, Dec 27, 2010 at 3:48 AM, Jimmy Richardson <address@hidden> wrote:
> Hi,:
>
> I'm learning about polyphase channelizer, and I have been reading fred
> harris' paper "Digital Receivers and Transmitters Using Polyphase Filter
> Banks for Wireless Communications". I have also played with the Matlab
> programs at the end of the paper. What I'm trying to do next is to use
> GNURadio to do the channelization. I made two attempts, one uses
> freq_xlating_fir_filter_ccf to implement a DDC channelizer, another uses
> pfb_channelizer_ccf, running against the data in appendix III of harris'
> paper. I'm hoping the channelizer result from GNURadio code would match the
> result from Matlab, but I failed on both, I wonder if someone could help me
> spot the problem.
>
> 1. DDC Channelizer:
Using the frequency xlating filters here is not recommended. You'll
need to use much longer filters than when using the channelizer. That
said, I'm not sure what would cause the problem you identified below.
In my opinion, it's not worth doing it this way.
> 1.1 Code: The following is the core part of the code (input parsing and
> various other stuff are omitted), the value for the variables can be found
> in 1.2
> self._filter_taps = gr.firdes.low_pass(1, self._input_rate,
> self._cutoff_freq, self._trans_width,
>
> window=gr.firdes.WIN_BLACKMAN_hARRIS)
> print "Number of taps: _filter_taps = ", len(self._filter_taps)
>
> # Blocks
> self.ddc_filter = list()
> # i = 0 to M-1
> for i in xrange(self._M):
> offset = self._channel_bandwidth * (float(self._M)/2 - i)
> print "Channel ", i, "'s offset (Hz): ", offset
>
> self.ddc_filter.append(gr.freq_xlating_fir_filter_ccf(self._resampling_ratio,
>
> self._filter_taps, offset, self._input_rate))
> self.connect(self.head, self.ddc_filter[i], self.output_files[i])
>
> 1.2 Variable values:
> Input sampling freq (Hz): _input_rate = 1120000000.0
> Resampling ratio: _resampling_ratio = 28
> Output sampling freq (Hz): _output_rate = 40000000.0
> Transition width (Hz): _trans_width = 2000000.0
> Number of channels: _M = 40
> Number of samples: _N = 11200
> Oversample rate: _oversample_rate = 1.42857142857
> Channel bandwidth (HZ): _channel_bandwidth = 28000000.0
> Cutoff freq (HZ): _cutoff_freq = 13000000.0
> Number of taps: _filter_taps = 561
> Channel 0 's offset (Hz): 560000000.0
> Channel 1 's offset (Hz): 532000000.0
> ...
> 1.3 Result: The result from GNURadio code is saved to output files, one for
> each channel. Then the results time-domain are plotted in Matlab (-10 to
> +10, time 1 to 200), and compared to the result plot from harris' code, they
> are similar, but not the same. Channel 0 to 5, 17, 18, 34 to 39 do not have
> any strong signal, this is reflected in both plots, channel 20's signal is
> exactly the same, but all other channels' plot are different.
>
> 2. Polyphase Channelizer:
> 2.1 Code:
> self._filter_taps = gr.firdes.low_pass(1, self._input_rate,
> self._cutoff_freq, self._trans_width,
>
> window=gr.firdes.WIN_BLACKMAN_hARRIS)
> # Calculate the number of taps per channel for our own information
> self._taps_per_channel = scipy.ceil(float(len(self._filter_taps)) /
> float(self._M))
> print "Number of taps: _filter_taps = ", len(self._filter_taps)
> print "Taps per channel: _taps_per_channel = ",
> self._taps_per_channel
>
> # Construct the channelizer filter
> self.pfb = blks2.pfb_channelizer_ccf(self._M, self._filter_taps,
> self._oversample_rate)
>
> # Connect the blocks
> self.connect(self.head, self.pfb)
> # i = 0 to M-1
> for i in xrange(self._M):
> self.connect((self.pfb, i), self.output_files[i])
>
> 2.2 Variable values:
> Input sampling freq (Hz): _input_rate = 1120000000.0
> Resampling ratio: _resampling_ratio = 28
> Output sampling freq (Hz): _output_rate = 40000000.0
> Transition width (Hz): _trans_width = 2000000.0
> Number of channels: _M = 40
> Number of samples: _N = 11200
> Oversample rate: _oversample_rate = 1.42857142857
> Channel bandwidth (HZ): _channel_bandwidth = 28000000.0
> Cutoff freq (HZ): _cutoff_freq = 13000000.0
> Number of taps: _filter_taps = 561
> Taps per channel: _taps_per_channel = 15.0
>
> 2.3 Result: The GNURadio program failed with:
> "terminate called after throwing an instance of 'std::invalid_argument'
> what(): gr_pfb_channelizer: oversample rate must be N/i for i in [1, N]
>
> This application has requested the Runtime to terminate it in an unusual
> way.
> Please contact the application's support team for more information."
>
> This doesn't seem to make sense, since in this case N = 40, oversample rate
> =1.42857142857, i = 28
>
> Thanks
The "oversample_rate" is not exactly what you are specifying here. The
default behavior of this PFB channelizer implementation is to be
critically sampled; that is, the sample rate equals the bandwidth. For
many applications, you want to have the output sample rate be some
other rate, most notably, 2x the bandwidth. The oversample_rate allows
you to specify a number real number, but this cannot be an arbitrary
number in this case. Because of the way the samples are fed to the
filters, the oversample rate, O, has to be set such that the number of
filters, N, can be evenly divided by an integer to to get O; that is,
N/i = O for i in [1,N]. Take the example in in fred's paper where he
has 64 channels and a 1/48 resampling rate. So he's using a 48-to-1
downsampling in 64 channels, so his rate is 4/3, which means that the
output sampling rate is (4/3)*bw, where bw is the channel bandwidth.
If you specified that the rate was 2.0, you would feed 32 of the 64
channels and have a sample rate that is twice the bandwidth. I notice
in the remarks in fred's paper that he's outputting the channels at 2
samples/symbol, so the oversample_rate here should be 2.
I hope that makes sense and you can figure out from there what you
need to do to get it to work. I've worked with fred for a while now,
but I find his Matlab to be almost unreadable (I've told him this
before), so I can't quite tell you from a quick look over the code he
has in this paper what's really going on.
Also, keep in mind that fred always develops he own filters straight
from the remez algorithm. If you are using gr.firdes.low_pass, you're
not going to get the same output filters. Closer would be to use the
blcks2.optfir.low_pass, which uses the PM algorithm (which in turn
uses Remez), but I couldn't give you the specs you need to build the
same _exact_ filter as in fred's paper. But you'll get close enough
that the basic shapes of the signals will be the same, if not every
point.
Tom