summaryrefslogtreecommitdiff
path: root/gr-blocks
diff options
context:
space:
mode:
Diffstat (limited to 'gr-blocks')
-rw-r--r--gr-blocks/examples/ctrlport/simple_copy.grc50
-rw-r--r--gr-blocks/grc/blocks_moving_average_xx.xml11
-rw-r--r--gr-blocks/include/gnuradio/blocks/moving_average_XX.h.t6
-rw-r--r--gr-blocks/lib/moving_average_XX_impl.cc.t61
-rw-r--r--gr-blocks/lib/moving_average_XX_impl.h.t11
-rw-r--r--gr-blocks/python/blocks/qa_moving_average.py68
6 files changed, 135 insertions, 72 deletions
diff --git a/gr-blocks/examples/ctrlport/simple_copy.grc b/gr-blocks/examples/ctrlport/simple_copy.grc
index a52c350ded..f61c6cd18a 100644
--- a/gr-blocks/examples/ctrlport/simple_copy.grc
+++ b/gr-blocks/examples/ctrlport/simple_copy.grc
@@ -1,5 +1,5 @@
<?xml version='1.0' encoding='utf-8'?>
-<?grc format='1' created='3.7.11'?>
+<?grc format='1' created='3.7.12'?>
<flow_graph>
<timestamp>Sat Mar 16 22:03:14 2013</timestamp>
<block>
@@ -393,48 +393,6 @@ to enable/disablethis block</value>
</param>
</block>
<block>
- <key>epy_block</key>
- <param>
- <key>alias</key>
- <value></value>
- </param>
- <param>
- <key>_io_cache</key>
- <value>('Null Msg Source', 'blk', [], [], [('fake_output', 'message', 1)], '', [])</value>
- </param>
- <param>
- <key>_source_code</key>
- <value># Block that doesn't do anything, just used to get a msg input port on another block exposed to ControlPort
-from gnuradio import gr
-import pmt
-class blk(gr.basic_block):
- def __init__(self):
- gr.basic_block.__init__(self,name='Null Msg Source',in_sig=[],out_sig=[])
- self.message_port_register_out(pmt.intern("fake_output"))
-</value>
- </param>
- <param>
- <key>comment</key>
- <value></value>
- </param>
- <param>
- <key>_enabled</key>
- <value>True</value>
- </param>
- <param>
- <key>_coordinate</key>
- <value>(357, 218)</value>
- </param>
- <param>
- <key>_rotation</key>
- <value>0</value>
- </param>
- <param>
- <key>id</key>
- <value>epy_block_0</value>
- </param>
- </block>
- <block>
<key>note</key>
<param>
<key>alias</key>
@@ -861,10 +819,4 @@ python simple_copy_controller.py 127.0.0.1 &lt;PORT&gt; true</value>
<source_key>0</source_key>
<sink_key>0</sink_key>
</connection>
- <connection>
- <source_block_id>epy_block_0</source_block_id>
- <sink_block_id>blocks_copy_0</sink_block_id>
- <source_key>fake_output</source_key>
- <sink_key>en</sink_key>
- </connection>
</flow_graph>
diff --git a/gr-blocks/grc/blocks_moving_average_xx.xml b/gr-blocks/grc/blocks_moving_average_xx.xml
index e90903ad85..00c5e1d486 100644
--- a/gr-blocks/grc/blocks_moving_average_xx.xml
+++ b/gr-blocks/grc/blocks_moving_average_xx.xml
@@ -8,7 +8,7 @@
<name>Moving Average</name>
<key>blocks_moving_average_xx</key>
<import>from gnuradio import blocks</import>
- <make>blocks.moving_average_$(type.fcn)($length, $scale, $max_iter)</make>
+ <make>blocks.moving_average_$(type.fcn)($length, $scale, $max_iter, $vlen)</make>
<callback>set_length_and_scale($length, $scale)</callback>
<param>
<name>Type</name>
@@ -57,12 +57,21 @@
<value>4000</value>
<type>int</type>
</param>
+ <param>
+ <name>Length of Vectors</name>
+ <key>vlen</key>
+ <value>1</value>
+ <type>int</type>
+ </param>
+ <check>$vlen &gt; 0</check>
<sink>
<name>in</name>
<type>$type</type>
+ <vlen>$vlen</vlen>
</sink>
<source>
<name>out</name>
<type>$type</type>
+ <vlen>$vlen</vlen>
</source>
</block>
diff --git a/gr-blocks/include/gnuradio/blocks/moving_average_XX.h.t b/gr-blocks/include/gnuradio/blocks/moving_average_XX.h.t
index da5968240c..deabf31832 100644
--- a/gr-blocks/include/gnuradio/blocks/moving_average_XX.h.t
+++ b/gr-blocks/include/gnuradio/blocks/moving_average_XX.h.t
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/*
- * Copyright 2008,2013 Free Software Foundation, Inc.
+ * Copyright 2008,2013,2017 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
@@ -48,9 +48,11 @@ namespace gr {
* \param scale scale factor for the result.
* \param max_iter limits how long we go without flushing the accumulator
* This is necessary to avoid numerical instability for float and complex.
+ * \param vlen When > 1, do a per-vector-element moving average
*/
static sptr make(int length, @O_TYPE@ scale,
- int max_iter = 4096);
+ int max_iter = 4096,
+ unsigned int vlen = 1);
/*!
* Get the length used in the avaraging calculation.
diff --git a/gr-blocks/lib/moving_average_XX_impl.cc.t b/gr-blocks/lib/moving_average_XX_impl.cc.t
index 089166971f..fe0a2bdebd 100644
--- a/gr-blocks/lib/moving_average_XX_impl.cc.t
+++ b/gr-blocks/lib/moving_average_XX_impl.cc.t
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/*
- * Copyright 2008,2010,2013 Free Software Foundation, Inc.
+ * Copyright 2008,2010,2013,2017 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
@@ -33,24 +33,30 @@ namespace gr {
namespace blocks {
@NAME@::sptr
- @NAME@::make(int length, @O_TYPE@ scale, int max_iter)
+ @NAME@::make(int length, @O_TYPE@ scale, int max_iter, unsigned int vlen)
{
return gnuradio::get_initial_sptr
- (new @NAME_IMPL@(length, scale, max_iter));
+ (new @NAME_IMPL@(length, scale, max_iter, vlen));
}
- @NAME_IMPL@::@NAME_IMPL@(int length, @O_TYPE@ scale, int max_iter)
+ @NAME_IMPL@::@NAME_IMPL@(int length, @O_TYPE@ scale, int max_iter, unsigned int vlen)
: sync_block("@NAME@",
- io_signature::make(1, 1, sizeof(@I_TYPE@)),
- io_signature::make(1, 1, sizeof(@O_TYPE@))),
+ io_signature::make(1, 1, sizeof(@I_TYPE@)*vlen),
+ io_signature::make(1, 1, sizeof(@O_TYPE@)*vlen)),
d_length(length),
d_scale(scale),
d_max_iter(max_iter),
+ d_vlen(vlen),
d_new_length(length),
d_new_scale(scale),
d_updated(false)
{
set_history(length);
+ //we don't have C++11's <array>, so initialize the stored vector instead
+ //we store this vector so that work() doesn't spend its time allocating and freeing vector storage
+ if(d_vlen > 1) {
+ d_sum = std::vector<@I_TYPE@>(d_vlen);
+ }
}
@NAME_IMPL@::~@NAME_IMPL@()
@@ -95,18 +101,39 @@ namespace gr {
const @I_TYPE@ *in = (const @I_TYPE@ *)input_items[0];
@O_TYPE@ *out = (@O_TYPE@ *)output_items[0];
- @I_TYPE@ sum = 0;
- int num_iter = (noutput_items>d_max_iter) ? d_max_iter : noutput_items;
- for(int i = 0; i < d_length-1; i++) {
- sum += in[i];
- }
-
- for(int i = 0; i < num_iter; i++) {
- sum += in[i+d_length-1];
- out[i] = sum * d_scale;
- sum -= in[i];
+ unsigned int num_iter = (unsigned int)((noutput_items>d_max_iter) ? d_max_iter : noutput_items);
+ if(d_vlen == 1) {
+ @I_TYPE@ sum = in[0];
+ for(int i = 1; i < d_length-1; i++) {
+ sum += in[i];
+ }
+
+ for(unsigned int i = 0; i < num_iter; i++) {
+ sum += in[i+d_length-1];
+ out[i] = sum * d_scale;
+ sum -= in[i];
+ }
+
+ } else { // d_vlen > 1
+ //gets automatically optimized well
+ for(unsigned int elem = 0; elem < d_vlen; elem++) {
+ d_sum[elem] = in[elem];
+ }
+
+ for(int i = 1; i < d_length - 1; i++) {
+ for(unsigned int elem = 0; elem < d_vlen; elem++) {
+ d_sum[elem] += in[i*d_vlen + elem];
+ }
+ }
+
+ for(unsigned int i = 0; i < num_iter; i++) {
+ for(unsigned int elem = 0; elem < d_vlen; elem++) {
+ d_sum[elem] += in[(i+d_length-1)*d_vlen + elem];
+ out[i*d_vlen + elem] = d_sum[elem] * d_scale;
+ d_sum[elem] -= in[i*d_vlen + elem];
+ }
+ }
}
-
return num_iter;
}
diff --git a/gr-blocks/lib/moving_average_XX_impl.h.t b/gr-blocks/lib/moving_average_XX_impl.h.t
index 17e8ef5da9..f90a666bbf 100644
--- a/gr-blocks/lib/moving_average_XX_impl.h.t
+++ b/gr-blocks/lib/moving_average_XX_impl.h.t
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/*
- * Copyright 2008,2013 Free Software Foundation, Inc.
+ * Copyright 2008,2013,2017 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
@@ -26,6 +26,8 @@
#define @GUARD_NAME_IMPL@
#include <gnuradio/blocks/@NAME@.h>
+#include <vector>
+#include <algorithm>
namespace gr {
namespace blocks {
@@ -36,6 +38,9 @@ namespace gr {
int d_length;
@O_TYPE@ d_scale;
int d_max_iter;
+ unsigned int d_vlen;
+ std::vector<@I_TYPE@> d_sum;
+
int d_new_length;
@O_TYPE@ d_new_scale;
@@ -43,11 +48,13 @@ namespace gr {
public:
@NAME_IMPL@(int length, @O_TYPE@ scale,
- int max_iter = 4096);
+ int max_iter = 4096,
+ unsigned int vlen = 1);
~@NAME_IMPL@();
int length() const { return d_new_length; }
@O_TYPE@ scale() const { return d_new_scale; }
+ unsigned int vlen() const { return d_vlen; }
void set_length_and_scale(int length, @O_TYPE@ scale);
void set_length(int length);
diff --git a/gr-blocks/python/blocks/qa_moving_average.py b/gr-blocks/python/blocks/qa_moving_average.py
index 2c58805925..b76f81392d 100644
--- a/gr-blocks/python/blocks/qa_moving_average.py
+++ b/gr-blocks/python/blocks/qa_moving_average.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python
#
-# Copyright 2013 Free Software Foundation, Inc.
+# Copyright 2013,2017 Free Software Foundation, Inc.
#
# This file is part of GNU Radio
#
@@ -45,6 +45,10 @@ class test_moving_average(gr_unittest.TestCase):
def tearDown(self):
self.tb = None
+ # These tests will always pass and are therefore useless. 100 random numbers [-1,1) are
+ # getting summed up and scaled with 0.001. Then, an assertion verifies a result near 0,
+ # which is the case even if the block is malfunctioning.
+
def test_01(self):
tb = self.tb
@@ -87,5 +91,67 @@ class test_moving_average(gr_unittest.TestCase):
# make sure result is close to zero
self.assertComplexTuplesAlmostEqual(expected_result, dst_data, 1)
+ # This tests implement own moving average to verify correct behaviour of the block
+
+ def test_03(self):
+ tb = self.tb
+
+ vlen = 5
+ N = 10*vlen
+ seed = 0
+ data = make_random_float_tuple(N, 2**10)
+ data = [int(d*1000) for d in data]
+ src = blocks.vector_source_i(data, False)
+ one_to_many = blocks.stream_to_streams(gr.sizeof_int, vlen)
+ one_to_vector = blocks.stream_to_vector(gr.sizeof_int, vlen)
+ many_to_vector = blocks.streams_to_vector(gr.sizeof_int, vlen)
+ isolated = [ blocks.moving_average_ii(100, 1) for i in range(vlen)]
+ dut = blocks.moving_average_ii(100, 1, vlen=vlen)
+ dut_dst = blocks.vector_sink_i(vlen=vlen)
+ ref_dst = blocks.vector_sink_i(vlen=vlen)
+
+ tb.connect(src, one_to_many)
+ tb.connect(src, one_to_vector, dut, dut_dst)
+ tb.connect(many_to_vector, ref_dst)
+ for idx, single in enumerate(isolated):
+ tb.connect((one_to_many,idx), single, (many_to_vector,idx))
+
+ tb.run()
+
+ dut_data = dut_dst.data()
+ ref_data = ref_dst.data()
+
+ # make sure result is close to zero
+ self.assertTupleEqual(dut_data, ref_data)
+
+ def test_04(self):
+ tb = self.tb
+
+ N = 10000 # number of samples
+ history = 100 # num of samples to average
+ data = make_random_complex_tuple(N, 1) # generate random data
+
+ # pythonic MA filter
+ data_padded = (history-1)*[0.0+1j*0.0]+list(data) # history
+ expected_result = []
+ moving_sum = sum(data_padded[:history-1])
+ for i in range(N):
+ moving_sum += data_padded[i+history-1]
+ expected_result.append(moving_sum)
+ moving_sum -= data_padded[i]
+
+ src = blocks.vector_source_c(data, False)
+ op = blocks.moving_average_cc(history, 1)
+ dst = blocks.vector_sink_c()
+
+ tb.connect(src, op)
+ tb.connect(op, dst)
+ tb.run()
+
+ dst_data = dst.data()
+
+ # make sure result is close to zero
+ self.assertComplexTuplesAlmostEqual(expected_result, dst_data, 4)
+
if __name__ == '__main__':
gr_unittest.run(test_moving_average, "test_moving_average.xml")