summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Rondeau2012-02-20 10:12:57 -0500
committerTom Rondeau2012-02-27 22:00:33 -0500
commitdd4cc588d7a34f82a63c6b23ca7a1fab736bfc10 (patch)
treeab65436af4949ba75b46bfa538534a308c448676
parentfed443d1ae6bb78b24de54be5daa9647c5368faa (diff)
downloadgnuradio-dd4cc588d7a34f82a63c6b23ca7a1fab736bfc10.tar.gz
gnuradio-dd4cc588d7a34f82a63c6b23ca7a1fab736bfc10.tar.bz2
gnuradio-dd4cc588d7a34f82a63c6b23ca7a1fab736bfc10.zip
core: wip on pfb synthesis. It works, but is a bit hacked together.
Need to determine the best way to handle the two filter cases, with and without oversampling.
-rw-r--r--gnuradio-core/src/lib/filter/gr_pfb_synthesis_filterbank_ccf.cc98
-rw-r--r--gnuradio-core/src/lib/filter/gr_pfb_synthesis_filterbank_ccf.h3
-rw-r--r--gnuradio-core/src/lib/filter/gr_pfb_synthesis_filterbank_ccf.i1
3 files changed, 74 insertions, 28 deletions
diff --git a/gnuradio-core/src/lib/filter/gr_pfb_synthesis_filterbank_ccf.cc b/gnuradio-core/src/lib/filter/gr_pfb_synthesis_filterbank_ccf.cc
index 9fad1bd0d..25a5f500e 100644
--- a/gnuradio-core/src/lib/filter/gr_pfb_synthesis_filterbank_ccf.cc
+++ b/gnuradio-core/src/lib/filter/gr_pfb_synthesis_filterbank_ccf.cc
@@ -44,21 +44,24 @@ gr_pfb_synthesis_filterbank_ccf::gr_pfb_synthesis_filterbank_ccf
gr_make_io_signature (1, numchans, sizeof(gr_complex)),
gr_make_io_signature (1, 1, sizeof(gr_complex)),
numchans),
- d_updated (false), d_numchans(numchans)
+ d_updated (false), d_numchans(numchans), d_state(0)
{
- d_filters = std::vector<gri_fir_filter_with_buffer_ccf*>(d_numchans);
+ d_filters = std::vector<gri_fir_filter_with_buffer_ccf*>(2*d_numchans);
// Create an FIR filter for each channel and zero out the taps
- std::vector<float> vtaps(0, d_numchans);
- for(unsigned int i = 0; i < d_numchans; i++) {
+ std::vector<float> vtaps(0, 2*d_numchans);
+ for(unsigned int i = 0; i < 2*d_numchans; i++) {
d_filters[i] = new gri_fir_filter_with_buffer_ccf(vtaps);
}
// Now, actually set the filters' taps
- set_taps(taps);
+ set_taps2(taps);
// Create the IFFT to handle the input channel rotations
- d_fft = new gri_fft_complex (d_numchans, true);
+ d_fft = new gri_fft_complex (2*d_numchans, false);
+ memset(d_fft->get_inbuf(), 0, 2*d_numchans*sizeof(gr_complex));
+
+ set_output_multiple(d_numchans);
}
gr_pfb_synthesis_filterbank_ccf::~gr_pfb_synthesis_filterbank_ccf ()
@@ -106,10 +109,62 @@ gr_pfb_synthesis_filterbank_ccf::set_taps (const std::vector<float> &taps)
}
void
+gr_pfb_synthesis_filterbank_ccf::set_taps2 (const std::vector<float> &taps)
+{
+ unsigned int i,j;
+ int state = 0;
+
+ unsigned int ntaps = taps.size();
+ d_taps_per_filter = (unsigned int)ceil((double)ntaps/(double)d_numchans);
+
+ // Create d_numchan vectors to store each channel's taps
+ d_taps.resize(2*d_numchans);
+
+ // Make a vector of the taps plus fill it out with 0's to fill
+ // each polyphase filter with exactly d_taps_per_filter
+ std::vector<float> tmp_taps;
+ tmp_taps = taps;
+ while((float)(tmp_taps.size()) < d_numchans*d_taps_per_filter) {
+ tmp_taps.push_back(0.0);
+ }
+
+ // Partition the filter
+ for(i = 0; i < d_numchans; i++) {
+ // Each channel uses all d_taps_per_filter with 0's if not enough taps to fill out
+ d_taps[i] = std::vector<float>(d_taps_per_filter, 0);
+ d_taps[d_numchans+i] = std::vector<float>(d_taps_per_filter, 0);
+ state = 0;
+ for(j = 0; j < d_taps_per_filter; j++) {
+ // add taps to channels in reverse order
+ // Zero out every other tap
+ if(state == 0) {
+ d_taps[i][j] = tmp_taps[i + j*d_numchans];
+ d_taps[d_numchans + i][j] = 0;
+ state = 1;
+ }
+ else {
+ d_taps[i][j] = 0;
+ d_taps[d_numchans + i][j] = tmp_taps[i + j*d_numchans];
+ state = 0;
+ }
+ }
+
+ // Build a filter for each channel and add it's taps to it
+ d_filters[i]->set_taps(d_taps[i]);
+ d_filters[d_numchans + i]->set_taps(d_taps[d_numchans + i]);
+ }
+
+ // Set the history to ensure enough input items for each filter
+ set_history (d_taps_per_filter+1);
+
+ d_updated = true;
+}
+
+void
gr_pfb_synthesis_filterbank_ccf::print_taps()
{
unsigned int i, j;
- for(i = 0; i < d_numchans; i++) {
+ for(i = 0; i < 2*d_numchans; i++) {
printf("filter[%d]: [", i);
for(j = 0; j < d_taps_per_filter; j++) {
printf(" %.4e", d_taps[i][j]);
@@ -126,9 +181,6 @@ gr_pfb_synthesis_filterbank_ccf::work (int noutput_items,
{
gr_complex *in = (gr_complex*) input_items[0];
gr_complex *out = (gr_complex *) output_items[0];
- int numsigs = input_items.size();
- int ndiff = d_numchans - numsigs;
- unsigned int nhalf = (unsigned int)ceil((float)numsigs/2.0f);
if (d_updated) {
d_updated = false;
@@ -137,30 +189,22 @@ gr_pfb_synthesis_filterbank_ccf::work (int noutput_items,
unsigned int n, i;
for(n = 0; n < noutput_items/d_numchans; n++) {
- // fill up the populated channels based on the
- // number of real input streams
- for(i = 0; i < nhalf; i++) {
+ for(i = 0; i < d_numchans; i++) {
in = (gr_complex*)input_items[i];
- d_fft->get_inbuf()[i] = (in+i)[n];
+ d_fft->get_inbuf()[i] = in[n];
}
-
- // Make the ndiff channels around N/2 0
- for(; i < nhalf+ndiff; i++) {
- d_fft->get_inbuf()[i] = gr_complex(0,0);
- }
-
- // Finish off channels with data
- for(; i < d_numchans; i++) {
- in = (gr_complex*)input_items[i-ndiff];
- d_fft->get_inbuf()[i] = (in+i)[n];
- }
-
+
// spin through IFFT
d_fft->execute();
+ // Output is sum of two filters, but the input buffer to the filters must be circularly
+ // shifted by numchans every time through, done by using d_state to determine which IFFT
+ // buffer position to pull from.
for(i = 0; i < d_numchans; i++) {
- out[d_numchans-i-1] = d_filters[d_numchans-i-1]->filter(d_fft->get_outbuf()[i]);
+ out[i] = d_filters[i]->filter(d_fft->get_outbuf()[d_state*d_numchans+i]);
+ out[i] += d_filters[d_numchans+i]->filter(d_fft->get_outbuf()[(d_state^1)*d_numchans+i]);
}
+ d_state ^= 1;
out += d_numchans;
}
diff --git a/gnuradio-core/src/lib/filter/gr_pfb_synthesis_filterbank_ccf.h b/gnuradio-core/src/lib/filter/gr_pfb_synthesis_filterbank_ccf.h
index 1f772b1dd..06e5462c7 100644
--- a/gnuradio-core/src/lib/filter/gr_pfb_synthesis_filterbank_ccf.h
+++ b/gnuradio-core/src/lib/filter/gr_pfb_synthesis_filterbank_ccf.h
@@ -65,7 +65,7 @@ class GR_CORE_API gr_pfb_synthesis_filterbank_ccf : public gr_sync_interpolator
gri_fft_complex *d_fft;
std::vector< gri_fir_filter_with_buffer_ccf*> d_filters;
std::vector< std::vector<float> > d_taps;
-
+ int d_state;
/*!
* Build the polyphase synthesis filterbank.
@@ -86,6 +86,7 @@ public:
populate the filterbank.
*/
void set_taps (const std::vector<float> &taps);
+ void set_taps2(const std::vector<float> &taps);
/*!
* Print all of the filterbank taps to screen.
diff --git a/gnuradio-core/src/lib/filter/gr_pfb_synthesis_filterbank_ccf.i b/gnuradio-core/src/lib/filter/gr_pfb_synthesis_filterbank_ccf.i
index 02a9f0255..0a75269cb 100644
--- a/gnuradio-core/src/lib/filter/gr_pfb_synthesis_filterbank_ccf.i
+++ b/gnuradio-core/src/lib/filter/gr_pfb_synthesis_filterbank_ccf.i
@@ -35,4 +35,5 @@ class gr_pfb_synthesis_filterbank_ccf : public gr_sync_interpolator
~gr_pfb_synthesis_filterbank_ccf ();
void set_taps (const std::vector<float> &taps);
+ void print_taps();
};