commit-gnuradio
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Commit-gnuradio] [gnuradio] 06/14: gr-filter: Add a convenience freq_xl


From: git
Subject: [Commit-gnuradio] [gnuradio] 06/14: gr-filter: Add a convenience freq_xlating_fft_filter block
Date: Fri, 9 May 2014 22:28:43 +0000 (UTC)

This is an automated email from the git hooks/post-receive script.

jcorgan pushed a commit to branch master
in repository gnuradio.

commit 78d7d59f28e8fb1c792bbb1a80dd989c60a7214b
Author: Sylvain Munaut <address@hidden>
Date:   Thu May 8 15:15:29 2014 +0200

    gr-filter: Add a convenience freq_xlating_fft_filter block
    
    It's meant as a GRC convenience mainly. It's in python only and implemented
    as a hier block encapsulating a FFT filter + rotator
    
    Signed-off-by: Sylvain Munaut <address@hidden>
---
 gr-filter/grc/CMakeLists.txt                       |   1 +
 gr-filter/grc/filter_block_tree.xml                |   1 +
 .../grc/filter_freq_xlating_fft_filter_ccc.xml     |  62 +++++++++
 gr-filter/python/filter/CMakeLists.txt             |   1 +
 gr-filter/python/filter/__init__.py                |   1 +
 gr-filter/python/filter/freq_xlating_fft_filter.py |  80 +++++++++++
 .../python/filter/qa_freq_xlating_fft_filter.py    | 147 +++++++++++++++++++++
 7 files changed, 293 insertions(+)

diff --git a/gr-filter/grc/CMakeLists.txt b/gr-filter/grc/CMakeLists.txt
index 8c3dc64..575f667 100644
--- a/gr-filter/grc/CMakeLists.txt
+++ b/gr-filter/grc/CMakeLists.txt
@@ -26,6 +26,7 @@ install(FILES
     filter_filterbank_vcvcf.xml
     filter_fractional_interpolator_xx.xml
     filter_fractional_resampler_xx.xml
+    filter_freq_xlating_fft_filter_ccc.xml
     filter_freq_xlating_fir_filter_xxx.xml
     filter_hilbert_fc.xml
     filter_iir_filter_xxx.xml
diff --git a/gr-filter/grc/filter_block_tree.xml 
b/gr-filter/grc/filter_block_tree.xml
index f85f3f1..ea0ffd3 100644
--- a/gr-filter/grc/filter_block_tree.xml
+++ b/gr-filter/grc/filter_block_tree.xml
@@ -56,6 +56,7 @@
        </cat>
        <cat>
                <name>Channelizers</name>
+               <block>freq_xlating_fft_filter_ccc</block>
                <block>freq_xlating_fir_filter_xxx</block>
                <block>pfb_channelizer_ccf</block>
                <block>pfb_channelizer_hier_ccf</block>
diff --git a/gr-filter/grc/filter_freq_xlating_fft_filter_ccc.xml 
b/gr-filter/grc/filter_freq_xlating_fft_filter_ccc.xml
new file mode 100644
index 0000000..ec27a4f
--- /dev/null
+++ b/gr-filter/grc/filter_freq_xlating_fft_filter_ccc.xml
@@ -0,0 +1,62 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Frequency Xlating FFT Filter
+###################################################
+ -->
+<block>
+       <name>Frequency Xlating FFT Filter</name>
+       <key>freq_xlating_fft_filter_ccc</key>
+       <import>from gnuradio import filter</import>
+       <import>from gnuradio.filter import firdes</import>
+       <make>filter.freq_xlating_fft_filter_ccc($decim, $taps, $center_freq, 
$samp_rate)
+self.$(id).set_nthreads($nthreads)
+self.$(id).declare_sample_delay($samp_delay)</make>
+       <callback>set_taps($taps)</callback>
+       <callback>set_center_freq($center_freq)</callback>
+       <callback>set_nthreads($nthreads)</callback>
+       <param>
+               <name>Decimation</name>
+               <key>decim</key>
+               <value>1</value>
+               <type>int</type>
+       </param>
+       <param>
+               <name>Taps</name>
+               <key>taps</key>
+               <type>complex_vector</type>
+       </param>
+       <param>
+               <name>Center Frequency</name>
+               <key>center_freq</key>
+               <value>0</value>
+               <type>real</type>
+       </param>
+       <param>
+               <name>Sample Rate</name>
+               <key>samp_rate</key>
+               <value>samp_rate</value>
+               <type>real</type>
+       </param>
+       <param>
+               <name>Sample Delay</name>
+               <key>samp_delay</key>
+                <value>0</value>
+               <type>int</type>
+                <hide>part</hide>
+       </param>
+       <param>
+               <name>Num. Threads</name>
+               <key>nthreads</key>
+               <value>1</value>
+               <type>int</type>
+       </param>
+       <sink>
+               <name>in</name>
+               <type>complex</type>
+       </sink>
+       <source>
+               <name>out</name>
+               <type>complex</type>
+       </source>
+</block>
diff --git a/gr-filter/python/filter/CMakeLists.txt 
b/gr-filter/python/filter/CMakeLists.txt
index e83e6dd..c708f0a 100644
--- a/gr-filter/python/filter/CMakeLists.txt
+++ b/gr-filter/python/filter/CMakeLists.txt
@@ -24,6 +24,7 @@ GR_PYTHON_INSTALL(
     FILES
     __init__.py
     filterbank.py
+    freq_xlating_fft_filter.py
     optfir.py
     pfb.py
     rational_resampler.py
diff --git a/gr-filter/python/filter/__init__.py 
b/gr-filter/python/filter/__init__.py
index 80dc422..cbbc80f 100644
--- a/gr-filter/python/filter/__init__.py
+++ b/gr-filter/python/filter/__init__.py
@@ -31,6 +31,7 @@ except ImportError:
     __path__.append(os.path.join(dirname, "..", "..", "swig"))
     from filter_swig import *
 from filterbank import *
+from freq_xlating_fft_filter import *
 from rational_resampler import *
 import pfb
 import optfir
diff --git a/gr-filter/python/filter/freq_xlating_fft_filter.py 
b/gr-filter/python/filter/freq_xlating_fft_filter.py
new file mode 100644
index 0000000..f6ebe05
--- /dev/null
+++ b/gr-filter/python/filter/freq_xlating_fft_filter.py
@@ -0,0 +1,80 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+#
+# Copyright 2013 Sylvain Munaut <address@hidden>
+#
+# This is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# This software is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this software; see the file COPYING.  If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+
+import math
+import cmath
+
+from gnuradio import gr
+from gnuradio.blocks import rotator_cc
+
+from filter_swig import fft_filter_ccc
+
+
+__all__ = [ 'freq_xlating_fft_filter_ccc' ]
+
+
+class freq_xlating_fft_filter_ccc(gr.hier_block2):
+
+    def __init__(self, decim, taps, center_freq, samp_rate):
+        gr.hier_block2.__init__(
+            self,
+            'freq_xlating_fft_filter_ccc',
+            gr.io_signature(1, 1, gr.sizeof_gr_complex),
+            gr.io_signature(1, 1, gr.sizeof_gr_complex),
+        )
+
+        # Save args
+        self.decim       = decim
+        self.taps        = taps
+        self.center_freq = center_freq
+        self.samp_rate   = samp_rate
+
+        # Sub blocks
+        self._filter = fft_filter_ccc(decim, taps)
+        self._rotator = rotator_cc(0.0)
+
+        self.connect(self, self._filter, self._rotator, self)
+
+        # Refresh
+        self._refresh()
+
+    def _rotate_taps(self, taps, phase_inc):
+        return [ x * cmath.exp(i * phase_inc * 1j) for i,x in enumerate(taps) ]
+
+    def _refresh(self):
+        phase_inc = (2.0 * math.pi * self.center_freq) / self.samp_rate
+        rtaps = self._rotate_taps(self.taps, phase_inc)
+        self._filter.set_taps(rtaps)
+        self._rotator.set_phase_inc(- self.decim * phase_inc)
+
+    def set_taps(self, taps):
+        self.taps = taps
+        self._refresh()
+
+    def set_center_freq(self, center_freq):
+        self.center_freq = center_freq
+        self._refresh()
+
+    def set_nthreads(self, nthreads):
+        self._filter.set_nthreads(nthreads)
+
+    def declare_sample_delay(self, samp_delay):
+        self._filter.declare_sample_delay(samp_delay)
diff --git a/gr-filter/python/filter/qa_freq_xlating_fft_filter.py 
b/gr-filter/python/filter/qa_freq_xlating_fft_filter.py
new file mode 100755
index 0000000..a9adfa0
--- /dev/null
+++ b/gr-filter/python/filter/qa_freq_xlating_fft_filter.py
@@ -0,0 +1,147 @@
+#!/usr/bin/env python
+#
+# Copyright 2008,2010,2012,2013 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+
+from gnuradio import gr, gr_unittest, filter, blocks
+
+import cmath, math
+
+def fir_filter(x, taps, decim=1):
+    y = []
+    x2 = (len(taps)-1)*[0,] + x
+    for i in range(0, len(x), decim):
+        yi = 0
+        for j in range(len(taps)):
+            yi += taps[len(taps)-1-j] * x2[i+j]
+        y.append(yi)
+    return y
+
+def sig_source_s(samp_rate, freq, amp, N):
+    t = map(lambda x: float(x)/samp_rate, xrange(N))
+    y = map(lambda x: int(100*math.sin(2.*math.pi*freq*x)), t)
+    return y
+
+def sig_source_c(samp_rate, freq, amp, N):
+    t = map(lambda x: float(x)/samp_rate, xrange(N))
+    y = map(lambda x: math.cos(2.*math.pi*freq*x) + \
+                1j*math.sin(2.*math.pi*freq*x), t)
+    return y
+
+def mix(lo, data):
+    y = [lo_i*data_i for lo_i, data_i in zip(lo, data)]
+    return y
+
+class test_freq_xlating_filter(gr_unittest.TestCase):
+
+    def setUp(self):
+        self.tb = gr.top_block ()
+
+    def tearDown(self):
+        self.tb = None
+
+    def generate_ccf_source(self):
+        self.fs = fs = 1
+        self.fc = fc = 0.3
+        self.bw = bw = 0.1
+        self.taps = filter.firdes.low_pass(1, fs, bw, bw/4)
+        times = xrange(1024)
+        self.src_data = map(lambda t: cmath.exp(-2j*cmath.pi*fc/fs*(t/100.0)), 
times)
+
+    def generate_ccc_source(self):
+        self.fs = fs = 1
+        self.fc = fc = 0.3
+        self.bw = bw = 0.1
+        self.taps = filter.firdes.complex_band_pass(1, fs, -bw/2, bw/2, bw/4)
+        times = xrange(1024)
+        self.src_data = map(lambda t: cmath.exp(-2j*cmath.pi*fc/fs*(t/100.0)), 
times)
+
+    def assert_fft_ok(self, expected_result, result_data):
+        expected_result = expected_result[:len(result_data)]
+        self.assertComplexTuplesAlmostEqual2 (expected_result, result_data,
+                                              abs_eps=1e-9, rel_eps=1e-3)
+
+
+    def test_fft_filter_ccf_001(self):
+        self.generate_ccf_source()
+
+        decim = 1
+        lo = sig_source_c(self.fs, -self.fc, 1, len(self.src_data))
+        despun = mix(lo, self.src_data)
+        expected_data = fir_filter(despun, self.taps, decim)
+
+        src = blocks.vector_source_c(self.src_data)
+        op  = filter.freq_xlating_fft_filter_ccc(decim, self.taps, self.fc, 
self.fs)
+        dst = blocks.vector_sink_c()
+        self.tb.connect(src, op, dst)
+        self.tb.run()
+        result_data = dst.data()
+        self.assert_fft_ok(expected_data, result_data)
+
+    def test_fft_filter_ccf_002(self):
+        self.generate_ccf_source()
+
+        decim = 4
+        lo = sig_source_c(self.fs, -self.fc, 1, len(self.src_data))
+        despun = mix(lo, self.src_data)
+        expected_data = fir_filter(despun, self.taps, decim)
+
+        src = blocks.vector_source_c(self.src_data)
+        op  = filter.freq_xlating_fft_filter_ccc(decim, self.taps, self.fc, 
self.fs)
+        dst = blocks.vector_sink_c()
+        self.tb.connect(src, op, dst)
+        self.tb.run()
+        result_data = dst.data()
+        self.assert_fft_ok(expected_data, result_data)
+
+    def test_fft_filter_ccc_001(self):
+        self.generate_ccc_source()
+
+        decim = 1
+        lo = sig_source_c(self.fs, -self.fc, 1, len(self.src_data))
+        despun = mix(lo, self.src_data)
+        expected_data = fir_filter(despun, self.taps, decim)
+
+        src = blocks.vector_source_c(self.src_data)
+        op  = filter.freq_xlating_fft_filter_ccc(decim, self.taps, self.fc, 
self.fs)
+        dst = blocks.vector_sink_c()
+        self.tb.connect(src, op, dst)
+        self.tb.run()
+        result_data = dst.data()
+        self.assert_fft_ok(expected_data, result_data)
+
+    def test_fft_filter_ccc_002(self):
+        self.generate_ccc_source()
+
+        decim = 4
+        lo = sig_source_c(self.fs, -self.fc, 1, len(self.src_data))
+        despun = mix(lo, self.src_data)
+        expected_data = fir_filter(despun, self.taps, decim)
+
+        src = blocks.vector_source_c(self.src_data)
+        op  = filter.freq_xlating_fft_filter_ccc(decim, self.taps, self.fc, 
self.fs)
+        dst = blocks.vector_sink_c()
+        self.tb.connect(src, op, dst)
+        self.tb.run()
+        result_data = dst.data()
+        self.assert_fft_ok(expected_data, result_data)
+
+if __name__ == '__main__':
+    gr_unittest.run(test_freq_xlating_filter, "test_freq_xlating_filter.xml")
+



reply via email to

[Prev in Thread] Current Thread [Next in Thread]