Statistics
| Branch: | Tag: | Revision:

root / gnuradio-core / src / lib / filter / gr_pfb_decimator_ccf.cc @ a0d13b42

History | View | Annotate | Download (5 kB)

1
/* -*- c++ -*- */
2
/*
3
 * Copyright 2009 Free Software Foundation, Inc.
4
 * 
5
 * This file is part of GNU Radio
6
 * 
7
 * GNU Radio is free software; you can redistribute it and/or modify
8
 * it under the terms of the GNU General Public License as published by
9
 * the Free Software Foundation; either version 3, or (at your option)
10
 * any later version.
11
 * 
12
 * GNU Radio is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 * GNU General Public License for more details.
16
 * 
17
 * You should have received a copy of the GNU General Public License
18
 * along with GNU Radio; see the file COPYING.  If not, write to
19
 * the Free Software Foundation, Inc., 51 Franklin Street,
20
 * Boston, MA 02110-1301, USA.
21
 */
22
23
#ifdef HAVE_CONFIG_H
24
#include "config.h"
25
#endif
26
27
#include <gr_pfb_decimator_ccf.h>
28
#include <gr_fir_ccf.h>
29
#include <gr_fir_util.h>
30
#include <gri_fft.h>
31
#include <gr_io_signature.h>
32
#include <gr_expj.h>
33
34
gr_pfb_decimator_ccf_sptr gr_make_pfb_decimator_ccf (unsigned int decim, 
35
                                                     const std::vector<float> &taps,
36
                                                     unsigned int channel)
37
{
38
  return gr_pfb_decimator_ccf_sptr (new gr_pfb_decimator_ccf (decim, taps, channel));
39
}
40
41
42
gr_pfb_decimator_ccf::gr_pfb_decimator_ccf (unsigned int decim, 
43
                                            const std::vector<float> &taps,
44
                                            unsigned int channel)
45
  : gr_sync_block ("pfb_decimator_ccf",
46
                   gr_make_io_signature (decim, decim, sizeof(gr_complex)),
47
                   gr_make_io_signature (1, 1, sizeof(gr_complex))),
48
    d_updated (false)
49
{
50
  d_rate = decim;
51
  d_filters = std::vector<gr_fir_ccf*>(d_rate);
52
  d_chan = channel;
53
  d_rotator = new gr_complex[d_rate];
54
55
  // Create an FIR filter for each channel and zero out the taps
56
  std::vector<float> vtaps(0, d_rate);
57
  for(unsigned int i = 0; i < d_rate; i++) {
58
    d_filters[i] = gr_fir_util::create_gr_fir_ccf(vtaps);
59
    d_rotator[i] = gr_expj(i*2*M_PI*d_chan/d_rate);
60
  }
61
62
  // Now, actually set the filters' taps
63
  set_taps(taps);
64
65
  // Create the FFT to handle the output de-spinning of the channels
66
  d_fft = new gri_fft_complex (d_rate, false);
67
}
68
69
gr_pfb_decimator_ccf::~gr_pfb_decimator_ccf ()
70
{
71
  for(unsigned int i = 0; i < d_rate; i++) {
72
    delete d_filters[i];
73
  }
74
}
75
76
void
77
gr_pfb_decimator_ccf::set_taps (const std::vector<float> &taps)
78
{
79
  unsigned int i,j;
80
81
  unsigned int ntaps = taps.size();
82
  d_taps_per_filter = (unsigned int)ceil((double)ntaps/(double)d_rate);
83
84
  // Create d_numchan vectors to store each channel's taps
85
  d_taps.resize(d_rate);
86
87
  // Make a vector of the taps plus fill it out with 0's to fill
88
  // each polyphase filter with exactly d_taps_per_filter
89
  std::vector<float> tmp_taps;
90
  tmp_taps = taps;
91
  while((float)(tmp_taps.size()) < d_rate*d_taps_per_filter) {
92
    tmp_taps.push_back(0.0);
93
  }
94
  
95
  // Partition the filter
96
  for(i = 0; i < d_rate; i++) {
97
    // Each channel uses all d_taps_per_filter with 0's if not enough taps to fill out
98
    d_taps[i] = std::vector<float>(d_taps_per_filter, 0);
99
    for(j = 0; j < d_taps_per_filter; j++) {
100
      d_taps[i][j] = tmp_taps[i + j*d_rate];  // add taps to channels in reverse order
101
    }
102
    
103
    // Build a filter for each channel and add it's taps to it
104
    d_filters[i]->set_taps(d_taps[i]);
105
  }
106
107
  // Set the history to ensure enough input items for each filter
108
  set_history (d_taps_per_filter);
109
110
  d_updated = true;
111
}
112
113
void
114
gr_pfb_decimator_ccf::print_taps()
115
{
116
  unsigned int i, j;
117
  for(i = 0; i < d_rate; i++) {
118
    printf("filter[%d]: [", i);
119
    for(j = 0; j < d_taps_per_filter; j++) {
120
      printf(" %.4e", d_taps[i][j]);
121
    }
122
    printf("]\n\n");
123
  }
124
}
125
126
#define ROTATEFFT
127
128
int
129
gr_pfb_decimator_ccf::work (int noutput_items,
130
                            gr_vector_const_void_star &input_items,
131
                            gr_vector_void_star &output_items)
132
{
133
  gr_complex *in;
134
  gr_complex *out = (gr_complex *) output_items[0];
135
136
  if (d_updated) {
137
    d_updated = false;
138
    return 0;                     // history requirements may have changed.
139
  }
140
141
  int i;
142
  for(i = 0; i < noutput_items; i++) {
143
    // Move through filters from bottom to top
144
    out[i] = 0;
145
    for(int j = d_rate-1; j >= 0; j--) {
146
      // Take in the items from the first input stream to d_rate
147
      in = (gr_complex*)input_items[d_rate - 1 - j];
148
149
      // Filter current input stream from bottom filter to top
150
      // The rotate them by expj(j*k*2pi/M) where M is the number of filters
151
      // (the decimation rate) and k is the channel number to extract
152
      
153
      // This is the real math that goes on; we abuse the FFT to do this quickly
154
      // for decimation rates > N where N is a small number (~5):
155
      //       out[i] += d_filters[j]->filter(&in[i])*gr_expj(j*d_chan*2*M_PI/d_rate);
156
#ifdef ROTATEFFT
157
      d_fft->get_inbuf()[j] = d_filters[j]->filter(&in[i]);
158
#else
159
      out[i] += d_filters[j]->filter(&in[i])*d_rotator[i];
160
#endif
161
    }
162
163
#ifdef ROTATEFFT
164
    // Perform the FFT to do the complex multiply despinning for all channels
165
    d_fft->execute();
166
167
    // Select only the desired channel out
168
    out[i] = d_fft->get_outbuf()[d_chan];
169
#endif
170
    
171
  }
172
  
173
  return noutput_items;
174
}