blob: 4b163b96a9fa65923e87a1bbde63bbff3e918d76 [file] [log] [blame]
Tom Tsou35222292016-06-22 16:16:30 -07001/*
2 * Polyphase channelizer
3 *
4 * Copyright (C) 2012-2014 Tom Tsou <tom@tsou.cc>
5 * Copyright (C) 2015 Ettus Research LLC
6 *
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU Affero General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * This program 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 Affero General Public License for more details.
16 *
17 * You should have received a copy of the GNU Affero General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 * See the COPYING file in the main directory for details.
20 */
21
22#include <stdlib.h>
23#include <math.h>
24#include <assert.h>
25#include <string.h>
26#include <cstdio>
27
28#include "Logger.h"
29#include "Channelizer.h"
30
31extern "C" {
32#include "common/fft.h"
33#include "common/convolve.h"
34}
35
36static void deinterleave(const float *in, size_t ilen,
37 float **out, size_t olen, size_t m)
38{
39 size_t i, n;
40
41 for (i = 0; i < olen; i++) {
42 for (n = 0; n < m; n++) {
43 out[m - 1 - n][2 * i + 0] = in[2 * (i * m + n) + 0];
44 out[m - 1 - n][2 * i + 1] = in[2 * (i * m + n) + 1];
45 }
46 }
47}
48
49size_t Channelizer::inputLen() const
50{
51 return blockLen * m;
52}
53
54size_t Channelizer::outputLen() const
55{
56 return blockLen;
57}
58
59float *Channelizer::outputBuffer(size_t chan) const
60{
61 if (chan >= m)
62 return NULL;
63
64 return hInputs[chan];
65}
66
67/*
68 * Implementation based on material found in:
69 *
70 * "harris, fred, Multirate Signal Processing, Upper Saddle River, NJ,
71 * Prentice Hall, 2006."
72 */
73bool Channelizer::rotate(const float *in, size_t len)
74{
75 size_t hSize = 2 * hLen * sizeof(float);
76
77 if (!checkLen(blockLen, len))
78 return false;
79
80 deinterleave(in, len, hInputs, blockLen, m);
81
82 /*
83 * Convolve through filterbank while applying and saving sample history
84 */
85 for (size_t i = 0; i < m; i++) {
86 memcpy(&hInputs[i][2 * -hLen], hist[i], hSize);
87 memcpy(hist[i], &hInputs[i][2 * (blockLen - hLen)], hSize);
88
89 convolve_real(hInputs[i], blockLen,
90 subFilters[i], hLen,
91 hOutputs[i], blockLen,
92 0, blockLen, 1, 0);
93 }
94
95 cxvec_fft(fftHandle);
96
97 return true;
98}
99
100/* Setup channelizer paramaters */
101Channelizer::Channelizer(size_t m, size_t blockLen, size_t hLen)
102 : ChannelizerBase(m, blockLen, hLen)
103{
104}
105
106Channelizer::~Channelizer()
107{
108}