summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Rondeau <trondeau@vt.edu>2013-03-08 08:57:46 -0500
committerTom Rondeau <trondeau@vt.edu>2013-03-08 09:23:44 -0500
commit4389b769891283face9aa397bd4d736f478e97e4 (patch)
tree255aaaabba7075dfe2595170682ef2596fd93367
parent42f8854f6d13de7e3f142f3f80233066a032d627 (diff)
blocks: moving vco/nco bases to gr-blocks.
-rw-r--r--gr-blocks/CMakeLists.txt3
-rw-r--r--gr-blocks/grc/blocks_block_tree.xml1
-rw-r--r--gr-blocks/grc/blocks_vco_f.xml35
-rw-r--r--gr-blocks/include/blocks/CMakeLists.txt3
-rw-r--r--gr-blocks/include/blocks/fxpt_nco.h1
-rw-r--r--gr-blocks/include/blocks/nco.h210
-rw-r--r--gr-blocks/include/blocks/vco.h113
-rw-r--r--gr-blocks/include/blocks/vco_f.h57
-rw-r--r--gr-blocks/lib/CMakeLists.txt1
-rw-r--r--gr-blocks/lib/qa_fxpt_nco.cc6
-rw-r--r--gr-blocks/lib/qa_fxpt_vco.cc6
-rw-r--r--gr-blocks/lib/vco_f_impl.cc68
-rw-r--r--gr-blocks/lib/vco_f_impl.h53
-rw-r--r--gr-blocks/python/qa_vco.py59
-rw-r--r--gr-blocks/swig/blocks_swig.i3
-rw-r--r--gr-blocks/tests/CMakeLists.txt56
-rw-r--r--gr-blocks/tests/benchmark_nco.cc225
-rw-r--r--gr-blocks/tests/benchmark_vco.cc172
-rw-r--r--gr-blocks/tests/nco_results48
19 files changed, 1114 insertions, 6 deletions
diff --git a/gr-blocks/CMakeLists.txt b/gr-blocks/CMakeLists.txt
index 7e2f43562f..e92e4c2808 100644
--- a/gr-blocks/CMakeLists.txt
+++ b/gr-blocks/CMakeLists.txt
@@ -80,6 +80,9 @@ CPACK_COMPONENT("blocks_swig"
########################################################################
add_subdirectory(include/blocks)
add_subdirectory(lib)
+#if(ENABLE_TESTING)
+# add_subdirectory(tests)
+#endif(ENABLE_TESTING)
if(ENABLE_PYTHON)
add_subdirectory(python)
add_subdirectory(swig)
diff --git a/gr-blocks/grc/blocks_block_tree.xml b/gr-blocks/grc/blocks_block_tree.xml
index 40061dd663..dc5fb6606d 100644
--- a/gr-blocks/grc/blocks_block_tree.xml
+++ b/gr-blocks/grc/blocks_block_tree.xml
@@ -59,6 +59,7 @@
<block>blocks_transcendental</block>
<block>blocks_argmax_xx</block>
<block>blocks_max_xx</block>
+ <block>blocks_vco_f</block>
</cat>
<cat>
<name>Boolean Operations (New) </name>
diff --git a/gr-blocks/grc/blocks_vco_f.xml b/gr-blocks/grc/blocks_vco_f.xml
new file mode 100644
index 0000000000..77a3ba0bd4
--- /dev/null
+++ b/gr-blocks/grc/blocks_vco_f.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##VCO
+###################################################
+ -->
+<block>
+ <name>VCO</name>
+ <key>blocks_vco_f</key>
+ <import>from gnuradio import blocks</import>
+ <make>blocks.vco_f($samp_rate, $sensitivity, $amplitude)</make>
+ <param>
+ <name>Sample Rate</name>
+ <key>samp_rate</key>
+ <type>real</type>
+ </param>
+ <param>
+ <name>Sensitivity</name>
+ <key>sensitivity</key>
+ <type>real</type>
+ </param>
+ <param>
+ <name>Amplitude</name>
+ <key>amplitude</key>
+ <type>real</type>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>float</type>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>float</type>
+ </source>
+</block>
diff --git a/gr-blocks/include/blocks/CMakeLists.txt b/gr-blocks/include/blocks/CMakeLists.txt
index 91d1ee4289..8ffbdf0b19 100644
--- a/gr-blocks/include/blocks/CMakeLists.txt
+++ b/gr-blocks/include/blocks/CMakeLists.txt
@@ -104,6 +104,8 @@ install(FILES
fxpt_nco.h
fxpt_vco.h
log2_const.h
+ nco.h
+ vco.h
add_ff.h
bin_statistics_f.h
burst_tagger.h
@@ -169,6 +171,7 @@ install(FILES
tuntap_pdu.h
uchar_to_float.h
unpack_k_bits_bb.h
+ vco_f.h
vector_to_stream.h
vector_to_streams.h
DESTINATION ${GR_INCLUDE_DIR}/gnuradio/blocks
diff --git a/gr-blocks/include/blocks/fxpt_nco.h b/gr-blocks/include/blocks/fxpt_nco.h
index ea266552b3..0faa731763 100644
--- a/gr-blocks/include/blocks/fxpt_nco.h
+++ b/gr-blocks/include/blocks/fxpt_nco.h
@@ -77,6 +77,7 @@ namespace gr {
d_phase += d_phase_inc;
}
+ //! increment current phase angle n times
void step(int n) {
d_phase += d_phase_inc * n;
}
diff --git a/gr-blocks/include/blocks/nco.h b/gr-blocks/include/blocks/nco.h
new file mode 100644
index 0000000000..e6658a3572
--- /dev/null
+++ b/gr-blocks/include/blocks/nco.h
@@ -0,0 +1,210 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2002,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 GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef _GR_NCO_H_
+#define _GR_NCO_H_
+
+#include <vector>
+#include <gr_sincos.h>
+#include <cmath>
+#include <gr_complex.h>
+
+namespace gr {
+ namespace blocks {
+
+ /*!
+ * \brief base class template for Numerically Controlled Oscillator (NCO)
+ * \ingroup misc
+ *
+ * Calculate sine and cosine based on the current phase. This
+ * class has multiple ways to calculate sin/cos and when
+ * requensting a range will increment the phase based on a
+ * frequency, which can be set using set_freq. Similar interfaces
+ * to the fxpt_vco can also be used to set or adjust the current
+ * phase.
+ *
+ * \sa fxpt_nco.h for fixed-point implementation.
+ */
+ template<class o_type, class i_type>
+ class nco
+ {
+ public:
+ nco() : phase(0), phase_inc(0) {}
+
+ virtual ~nco() {}
+
+ //! Set the current phase \p angle in radians
+ void set_phase(double angle) {
+ phase = angle;
+ }
+
+ //! Update the current phase in radians by \p delta_phase
+ void adjust_phase(double delta_phase) {
+ phase += delta_phase;
+ }
+
+ //! angle_rate is in radians / step
+ void set_freq(double angle_rate) {
+ phase_inc = angle_rate;
+ }
+
+ //! angle_rate is a delta in radians / step
+ void adjust_freq(double delta_angle_rate) {
+ phase_inc += delta_angle_rate;
+ }
+
+ //! increment current phase angle
+ void step()
+ {
+ phase += phase_inc;
+ if(fabs (phase) > M_PI) {
+
+ while(phase > M_PI)
+ phase -= 2*M_PI;
+
+ while(phase < -M_PI)
+ phase += 2*M_PI;
+ }
+ }
+
+ //! increment current phase angle n times
+ void step(int n)
+ {
+ phase += phase_inc * n;
+ if(fabs (phase) > M_PI) {
+
+ while(phase > M_PI)
+ phase -= 2*M_PI;
+
+ while(phase < -M_PI)
+ phase += 2*M_PI;
+ }
+ }
+
+ //! units are radians / step
+ double get_phase() const { return phase; }
+ double get_freq() const { return phase_inc; }
+
+ //! compute sin and cos for current phase angle
+ void sincos(float *sinx, float *cosx) const;
+
+ //! compute cos or sin for current phase angle
+ float cos() const { return std::cos (phase); }
+ float sin() const { return std::sin (phase); }
+
+ //! compute a block at a time
+ void sin(float *output, int noutput_items, double ampl = 1.0);
+ void cos(float *output, int noutput_items, double ampl = 1.0);
+ void sincos(gr_complex *output, int noutput_items, double ampl = 1.0);
+ void sin(short *output, int noutput_items, double ampl = 1.0);
+ void cos(short *output, int noutput_items, double ampl = 1.0);
+ void sin(int *output, int noutput_items, double ampl = 1.0);
+ void cos(int *output, int noutput_items, double ampl = 1.0);
+
+ protected:
+ double phase;
+ double phase_inc;
+ };
+
+ template<class o_type, class i_type>
+ void
+ nco<o_type,i_type>::sincos(float *sinx, float *cosx) const
+ {
+ gr_sincosf(phase, sinx, cosx);
+ }
+
+ template<class o_type, class i_type>
+ void
+ nco<o_type,i_type>::sin(float *output, int noutput_items, double ampl)
+ {
+ for(int i = 0; i < noutput_items; i++) {
+ output[i] = (float)(sin() * ampl);
+ step();
+ }
+ }
+
+ template<class o_type, class i_type>
+ void
+ nco<o_type,i_type>::cos(float *output, int noutput_items, double ampl)
+ {
+ for(int i = 0; i < noutput_items; i++){
+ output[i] = (float)(cos() * ampl);
+ step();
+ }
+ }
+
+ template<class o_type, class i_type>
+ void
+ nco<o_type,i_type>::sin(short *output, int noutput_items, double ampl)
+ {
+ for(int i = 0; i < noutput_items; i++) {
+ output[i] = (short)(sin() * ampl);
+ step();
+ }
+ }
+
+ template<class o_type, class i_type>
+ void
+ nco<o_type,i_type>::cos(short *output, int noutput_items, double ampl)
+ {
+ for(int i = 0; i < noutput_items; i++) {
+ output[i] = (short)(cos() * ampl);
+ step();
+ }
+ }
+
+ template<class o_type, class i_type>
+ void
+ nco<o_type,i_type>::sin(int *output, int noutput_items, double ampl)
+ {
+ for(int i = 0; i < noutput_items; i++) {
+ output[i] = (int)(sin() * ampl);
+ step();
+ }
+ }
+
+ template<class o_type, class i_type>
+ void
+ nco<o_type,i_type>::cos(int *output, int noutput_items, double ampl)
+ {
+ for(int i = 0; i < noutput_items; i++) {
+ output[i] = (int)(cos() * ampl);
+ step();
+ }
+ }
+
+ template<class o_type, class i_type>
+ void
+ nco<o_type,i_type>::sincos(gr_complex *output, int noutput_items, double ampl)
+ {
+ for(int i = 0; i < noutput_items; i++) {
+ float cosx, sinx;
+ sincos(&sinx, &cosx);
+ output[i] = gr_complex(cosx * ampl, sinx * ampl);
+ step();
+ }
+ }
+
+ } /* namespace blocks */
+} /* namespace gr */
+
+#endif /* _NCO_H_ */
diff --git a/gr-blocks/include/blocks/vco.h b/gr-blocks/include/blocks/vco.h
new file mode 100644
index 0000000000..4417d588ae
--- /dev/null
+++ b/gr-blocks/include/blocks/vco.h
@@ -0,0 +1,113 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2005,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 GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef _GR_VCO_H_
+#define _GR_VCO_H_
+
+#include <vector>
+#include <gr_sincos.h>
+#include <cmath>
+#include <gr_complex.h>
+
+namespace gr {
+ namespace blocks {
+
+ /*!
+ * \brief base class template for Voltage Controlled Oscillator (VCO)
+ * \ingroup misc
+ *
+ * Simple calculations of sine and cosine. Set the phase using
+ * set_phase or adjust it by some delta using adjust_phase. Sine
+ * and cosine can be retrieved together with sincos(sinx, cosx)
+ * where sinx and cosx are the returned values at the current
+ * phase. They can be retrieved individually using either sin() or
+ * cos().
+ *
+ * \sa fxpt_nco.h for fixed-point implementation.
+ */
+
+ template<class o_type, class i_type>
+ class vco
+ {
+ public:
+ vco() : d_phase(0) {}
+
+ virtual ~vco() {}
+
+ //! Set the current phase \p angle in radians
+ void set_phase(double angle) {
+ d_phase = angle;
+ }
+
+ //! Update the current phase in radians by \p delta_phase
+ void adjust_phase(double delta_phase) {
+ d_phase += delta_phase;
+ if(fabs(d_phase) > M_PI) {
+
+ while(d_phase > M_PI)
+ d_phase -= 2*M_PI;
+
+ while(d_phase < -M_PI)
+ d_phase += 2*M_PI;
+ }
+ }
+
+ //! Get the current phase in radians
+ double get_phase() const { return d_phase; }
+
+ //! compute sin and cos for current phase angle
+ void sincos(float *sinx, float *cosx) const;
+
+ //! compute cos or sin for current phase angle
+ float cos() const { return std::cos(d_phase); }
+ float sin() const { return std::sin(d_phase); }
+
+ //! compute a block at a time
+ void cos(float *output, const float *input, int noutput_items,
+ double k, double ampl = 1.0);
+
+ protected:
+ double d_phase;
+ };
+
+ template<class o_type, class i_type>
+ void
+ vco<o_type,i_type>::sincos(float *sinx, float *cosx) const
+ {
+ gr_sincosf(d_phase, sinx, cosx);
+ }
+
+ template<class o_type, class i_type>
+ void
+ vco<o_type,i_type>::cos(float *output, const float *input, int noutput_items,
+ double k, double ampl)
+ {
+ for(int i = 0; i < noutput_items; i++) {
+ output[i] = cos() * ampl;
+ adjust_phase(input[i] * k);
+ }
+ }
+
+ } /* namespace blocks */
+} /* namespace gr */
+
+#endif /* _VCO_H_ */
diff --git a/gr-blocks/include/blocks/vco_f.h b/gr-blocks/include/blocks/vco_f.h
new file mode 100644
index 0000000000..0a5bf97d1f
--- /dev/null
+++ b/gr-blocks/include/blocks/vco_f.h
@@ -0,0 +1,57 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2005,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 GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_GR_VCO_F_H
+#define INCLUDED_GR_VCO_F_H
+
+#include <blocks/api.h>
+#include <gr_sync_block.h>
+
+namespace gr {
+ namespace blocks {
+
+ /*!
+ * \brief VCO - Voltage controlled oscillator
+ * \ingroup misc
+ *
+ * input: float stream of control voltages; output: float oscillator output
+ */
+ class BLOCKS_API vco_f : virtual public gr_sync_block
+ {
+ public:
+ // gr::blocks::vco_f::sptr
+ typedef boost::shared_ptr<vco_f> sptr;
+
+ /*!
+ * \brief VCO - Voltage controlled oscillator
+ *
+ * \param sampling_rate sampling rate (Hz)
+ * \param sensitivity units are radians/sec/volt
+ * \param amplitude output amplitude
+ */
+ static sptr make(double sampling_rate, double sensitivity, double amplitude);
+ };
+
+ } /* namespace blocks */
+} /* namespace gr */
+
+#endif /* INCLUDED_GR_VCO_F_H */
diff --git a/gr-blocks/lib/CMakeLists.txt b/gr-blocks/lib/CMakeLists.txt
index ad0af831f4..4506eaca39 100644
--- a/gr-blocks/lib/CMakeLists.txt
+++ b/gr-blocks/lib/CMakeLists.txt
@@ -209,6 +209,7 @@ list(APPEND gr_blocks_sources
uchar_array_to_float.cc
uchar_to_float_impl.cc
unpack_k_bits_bb_impl.cc
+ vco_f_impl.cc
vector_to_stream_impl.cc
vector_to_streams_impl.cc
)
diff --git a/gr-blocks/lib/qa_fxpt_nco.cc b/gr-blocks/lib/qa_fxpt_nco.cc
index 12135dcf91..63c0a92902 100644
--- a/gr-blocks/lib/qa_fxpt_nco.cc
+++ b/gr-blocks/lib/qa_fxpt_nco.cc
@@ -26,7 +26,7 @@
#include <qa_fxpt_nco.h>
#include <blocks/fxpt_nco.h>
-#include <gr_nco.h>
+#include <blocks/nco.h>
#include <cppunit/TestAssert.h>
#include <iostream>
#include <stdio.h>
@@ -50,7 +50,7 @@ static double max_d(double a, double b)
void
qa_fxpt_nco::t0()
{
- gr_nco<float,float> ref_nco;
+ nco<float,float> ref_nco;
fxpt_nco new_nco;
double max_error = 0, max_phase_error = 0;
@@ -86,7 +86,7 @@ qa_fxpt_nco::t0()
void
qa_fxpt_nco::t1()
{
- gr_nco<float,float> ref_nco;
+ nco<float,float> ref_nco;
fxpt_nco new_nco;
gr_complex ref_block[SIN_COS_BLOCK_SIZE];
gr_complex new_block[SIN_COS_BLOCK_SIZE];
diff --git a/gr-blocks/lib/qa_fxpt_vco.cc b/gr-blocks/lib/qa_fxpt_vco.cc
index ff26e0129e..2efce0506b 100644
--- a/gr-blocks/lib/qa_fxpt_vco.cc
+++ b/gr-blocks/lib/qa_fxpt_vco.cc
@@ -26,7 +26,7 @@
#include <qa_fxpt_vco.h>
#include <blocks/fxpt_vco.h>
-#include <gr_vco.h>
+#include <blocks/vco.h>
#include <cppunit/TestAssert.h>
#include <iostream>
#include <stdio.h>
@@ -50,7 +50,7 @@ static double max_d(double a, double b)
void
qa_fxpt_vco::t0()
{
- gr_vco<float,float> ref_vco;
+ vco<float,float> ref_vco;
fxpt_vco new_vco;
double max_error = 0, max_phase_error = 0;
float input[SIN_COS_BLOCK_SIZE];
@@ -79,7 +79,7 @@ qa_fxpt_vco::t0()
void
qa_fxpt_vco::t1()
{
- gr_vco<float,float> ref_vco;
+ vco<float,float> ref_vco;
fxpt_vco new_vco;
float ref_block[SIN_COS_BLOCK_SIZE];
float new_block[SIN_COS_BLOCK_SIZE];
diff --git a/gr-blocks/lib/vco_f_impl.cc b/gr-blocks/lib/vco_f_impl.cc
new file mode 100644
index 0000000000..21e7d0a0f2
--- /dev/null
+++ b/gr-blocks/lib/vco_f_impl.cc
@@ -0,0 +1,68 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2005,2010,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 GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "vco_f_impl.h"
+#include <gr_io_signature.h>
+#include <math.h>
+
+namespace gr {
+ namespace blocks {
+
+ vco_f::sptr
+ vco_f::make(double sampling_rate, double sensitivity, double amplitude)
+ {
+ return gnuradio::get_initial_sptr
+ (new vco_f_impl(sampling_rate, sensitivity, amplitude));
+ }
+
+ vco_f_impl::vco_f_impl(double sampling_rate, double sensitivity, double amplitude)
+ : gr_sync_block("vco_f",
+ gr_make_io_signature(1, 1, sizeof(float)),
+ gr_make_io_signature(1, 1, sizeof(float))),
+ d_sampling_rate(sampling_rate), d_sensitivity(sensitivity),
+ d_amplitude(amplitude), d_k(d_sensitivity/d_sampling_rate)
+ {
+ }
+
+ vco_f_impl::~vco_f_impl()
+ {
+ }
+
+ int
+ vco_f_impl::work(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+ {
+ const float *input = (const float*)input_items[0];
+ float *output = (float*)output_items[0];
+
+ d_vco.cos(output, input, noutput_items, d_k, d_amplitude);
+
+ return noutput_items;
+ }
+
+ } /* namespace blocks */
+} /* namespace gr */
diff --git a/gr-blocks/lib/vco_f_impl.h b/gr-blocks/lib/vco_f_impl.h
new file mode 100644
index 0000000000..cecf72441f
--- /dev/null
+++ b/gr-blocks/lib/vco_f_impl.h
@@ -0,0 +1,53 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2005,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 GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_GR_VCO_F_IMPL_H
+#define INCLUDED_GR_VCO_F_IMPL_H
+
+#include <blocks/vco_f.h>
+#include <blocks/fxpt_vco.h>
+
+namespace gr {
+ namespace blocks {
+
+ class vco_f_impl : public vco_f
+ {
+ private:
+ double d_sampling_rate;
+ double d_sensitivity;
+ double d_amplitude;
+ double d_k;
+ fxpt_vco d_vco;
+
+ public:
+ vco_f_impl(double sampling_rate, double sensitivity, double amplitude);
+ ~vco_f_impl();
+
+ int work(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+ };
+
+ } /* namespace blocks */
+} /* namespace gr */
+
+#endif /* INCLUDED_GR_VCO_F_H */
diff --git a/gr-blocks/python/qa_vco.py b/gr-blocks/python/qa_vco.py
new file mode 100644
index 0000000000..721eb9471b
--- /dev/null
+++ b/gr-blocks/python/qa_vco.py
@@ -0,0 +1,59 @@
+#!/usr/bin/env python
+#
+# Copyright 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 GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+
+from gnuradio import gr, gr_unittest
+import blocks_swig
+import math
+
+def sig_source_f(samp_rate, freq, amp, N):
+ t = map(lambda x: float(x)/samp_rate, xrange(N))
+ y = map(lambda x: amp*math.cos(2.*math.pi*freq*x), t)
+ return y
+
+class test_vco(gr_unittest.TestCase):
+
+ def setUp (self):
+ self.tb = gr.top_block ()
+
+ def tearDown (self):
+ self.tb = None
+
+ def test_001(self):
+ src_data = 200*[0,] + 200*[0.5,] + 200*[1,]
+ expected_result = 200*[1,] + \
+ sig_source_f(1, 0.125, 1, 200) + \
+ sig_source_f(1, 0.25, 1, 200)
+
+ src = gr.vector_source_f(src_data)
+ op = blocks_swig.vco_f(1, math.pi/2.0, 1)
+ dst = gr.vector_sink_f()
+
+ self.tb.connect(src, op, dst)
+ self.tb.run()
+
+ result_data = dst.data()
+ self.assertFloatTuplesAlmostEqual(expected_result, result_data, 5)
+
+
+if __name__ == '__main__':
+ gr_unittest.run(test_vco, "test_vco.xml")
+
diff --git a/gr-blocks/swig/blocks_swig.i b/gr-blocks/swig/blocks_swig.i
index 1c0f49dfeb..19f1c949ca 100644
--- a/gr-blocks/swig/blocks_swig.i
+++ b/gr-blocks/swig/blocks_swig.i
@@ -175,6 +175,7 @@
#include "blocks/unpacked_to_packed_bb.h"
#include "blocks/unpacked_to_packed_ss.h"
#include "blocks/unpacked_to_packed_ii.h"
+#include "blocks/vco_f.h"
#include "blocks/vector_to_stream.h"
#include "blocks/vector_to_streams.h"
#include "blocks/xor_bb.h"
@@ -326,6 +327,7 @@
%include "blocks/unpacked_to_packed_bb.h"
%include "blocks/unpacked_to_packed_ss.h"
%include "blocks/unpacked_to_packed_ii.h"
+%include "blocks/vco_f.h"
%include "blocks/vector_to_stream.h"
%include "blocks/vector_to_streams.h"
%include "blocks/xor_bb.h"
@@ -476,6 +478,7 @@ GR_SWIG_BLOCK_MAGIC2(blocks, unpack_k_bits_bb);
GR_SWIG_BLOCK_MAGIC2(blocks, unpacked_to_packed_bb);
GR_SWIG_BLOCK_MAGIC2(blocks, unpacked_to_packed_ss);
GR_SWIG_BLOCK_MAGIC2(blocks, unpacked_to_packed_ii);
+GR_SWIG_BLOCK_MAGIC2(blocks, vco_f);
GR_SWIG_BLOCK_MAGIC2(blocks, vector_to_stream);
GR_SWIG_BLOCK_MAGIC2(blocks, vector_to_streams);
GR_SWIG_BLOCK_MAGIC2(blocks, xor_bb);
diff --git a/gr-blocks/tests/CMakeLists.txt b/gr-blocks/tests/CMakeLists.txt
new file mode 100644
index 0000000000..8f7ba2f64f
--- /dev/null
+++ b/gr-blocks/tests/CMakeLists.txt
@@ -0,0 +1,56 @@
+# Copyright 2010-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 GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+
+########################################################################
+include(GrMiscUtils) #check n def
+GR_CHECK_HDR_N_DEF(sys/resource.h HAVE_SYS_RESOURCE_H)
+
+########################################################################
+# Setup the include and linker paths
+########################################################################
+include_directories(
+ ${GR_BLOCKS_INCLUDE_DIRS}
+ ${GNURADIO_CORE_INCLUDE_DIRS}
+ ${GRUEL_INCLUDE_DIRS}
+ ${Boost_INCLUDE_DIRS}
+ ${CPPUNIT_INCLUDE_DIRS}
+)
+
+link_directories(
+ ${Boost_LIBRARY_DIRS}
+ ${CPPUNIT_LIBRARY_DIRS}
+)
+
+include_directories(${LOG4CXX_INCLUDE_DIRS})
+link_directories(${LOG4CXX_LIBRARY_DIRS})
+
+########################################################################
+# Build benchmarks and non-registered tests
+########################################################################
+set(tests_not_run #single source per test
+ benchmark_nco.cc
+ benchmark_vco.cc
+)
+
+foreach(test_not_run_src ${tests_not_run})
+ get_filename_component(name ${test_not_run_src} NAME_WE)
+ add_executable(${name} ${test_not_run_src})
+ target_link_libraries(${name} test-gnuradio-core gnuradio-blocks)
+endforeach(test_not_run_src)
+
diff --git a/gr-blocks/tests/benchmark_nco.cc b/gr-blocks/tests/benchmark_nco.cc
new file mode 100644
index 0000000000..4c2ed120db
--- /dev/null
+++ b/gr-blocks/tests/benchmark_nco.cc
@@ -0,0 +1,225 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2002,2004,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 GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/time.h>
+
+#ifdef HAVE_SYS_RESOURCE_H
+#include <sys/resource.h>
+#endif
+
+#include <unistd.h>
+#include <blocks/nco.h>
+#include <blocks/fxpt_nco.h>
+#include <string.h>
+
+#define ITERATIONS 20000000
+#define BLOCK_SIZE (10 * 1000) // fits in cache
+
+#define FREQ 5003.123
+
+static double
+timeval_to_double(const struct timeval *tv)
+{
+ return (double)tv->tv_sec + (double)tv->tv_usec * 1e-6;
+}
+
+
+static void
+benchmark(void test (float *x, float *y), const char *implementation_name)
+{
+#ifdef HAVE_SYS_RESOURCE_H
+ struct rusage rusage_start;
+ struct rusage rusage_stop;
+#else
+ double clock_start;
+ double clock_end;
+#endif
+ float output[2*BLOCK_SIZE];
+ float *x = &output[0], *y = &output[BLOCK_SIZE];
+
+ // touch memory
+ memset(output, 0, 2*BLOCK_SIZE*sizeof(float));
+
+ // get starting CPU usage
+#ifdef HAVE_SYS_RESOURCE_H
+ if(getrusage(RUSAGE_SELF, &rusage_start) < 0) {
+ perror("getrusage");
+ exit(1);
+ }
+#else
+ clock_start = (double)clock() * (1000000. / CLOCKS_PER_SEC);
+#endif
+ // do the actual work
+
+ test(x, y);
+
+ // get ending CPU usage
+
+#ifdef HAVE_SYS_RESOURCE_H
+ if(getrusage(RUSAGE_SELF, &rusage_stop) < 0) {
+ perror("getrusage");
+ exit(1);
+ }
+
+ // compute results
+
+ double user =
+ timeval_to_double(&rusage_stop.ru_utime)
+ - timeval_to_double(&rusage_start.ru_utime);
+
+ double sys =
+ timeval_to_double(&rusage_stop.ru_stime)
+ - timeval_to_double(&rusage_start.ru_stime);
+
+ double total = user + sys;
+#else
+ clock_end = (double)clock() * (1000000. / CLOCKS_PER_SEC);
+ double total = clock_end - clock_start;
+#endif
+
+ printf("%18s: cpu: %6.3f steps/sec: %10.3e\n",
+ implementation_name, total, ITERATIONS / total);
+}
+
+// ----------------------------------------------------------------
+// Don't compare the _vec with other functions since memory store's
+// are involved.
+
+void basic_sincos_vec(float *x, float *y)
+{
+ gr::blocks::nco<float,float> nco;
+
+ nco.set_freq(2 * M_PI / FREQ);
+
+ for(int i = 0; i < ITERATIONS/BLOCK_SIZE; i++) {
+ for(int j = 0; j < BLOCK_SIZE; j++) {
+ nco.sincos(&x[2*j+1], &x[2*j]);
+ nco.step();
+ }
+ }
+}
+
+void native_sincos_vec(float *x, float *y)
+{
+ gr::blocks::nco<float,float> nco;
+
+ nco.set_freq(2 * M_PI / FREQ);
+
+ for(int i = 0; i < ITERATIONS/BLOCK_SIZE; i++) {
+ nco.sincos((gr_complex*)x, BLOCK_SIZE);
+ }
+}
+
+void fxpt_sincos_vec(float *x, float *y)
+{
+ gr::blocks::fxpt_nco nco;
+
+ nco.set_freq (2 * M_PI / FREQ);
+
+ for(int i = 0; i < ITERATIONS/BLOCK_SIZE; i++) {
+ nco.sincos((gr_complex*)x, BLOCK_SIZE);
+ }
+}
+
+// ----------------------------------------------------------------
+
+void native_sincos(float *x, float *y)
+{
+ gr::blocks::nco<float,float> nco;
+
+ nco.set_freq(2 * M_PI / FREQ);
+
+ for(int i = 0; i < ITERATIONS; i++) {
+ nco.sincos(x, y);
+ nco.step();
+ }
+}
+
+void fxpt_sincos(float *x, float *y)
+{
+ gr::blocks::fxpt_nco nco;
+
+ nco.set_freq(2 * M_PI / FREQ);
+
+ for(int i = 0; i < ITERATIONS; i++) {
+ nco.sincos(x, y);
+ nco.step();
+ }
+}
+
+// ----------------------------------------------------------------
+
+void native_sin(float *x, float *y)
+{
+ gr::blocks::nco<float,float> nco;
+
+ nco.set_freq(2 * M_PI / FREQ);
+
+ for(int i = 0; i < ITERATIONS; i++) {
+ *x = nco.sin();
+ nco.step();
+ }
+}
+
+void fxpt_sin(float *x, float *y)
+{
+ gr::blocks::fxpt_nco nco;
+
+ nco.set_freq(2 * M_PI / FREQ);
+
+ for(int i = 0; i < ITERATIONS; i++) {
+ *x = nco.sin();
+ nco.step();
+ }
+}
+
+// ----------------------------------------------------------------
+
+void nop_fct(float *x, float *y)
+{
+}
+
+void nop_loop(float *x, float *y)
+{
+ for(int i = 0; i < ITERATIONS; i++) {
+ nop_fct(x, y);
+ }
+}
+
+int
+main(int argc, char **argv)
+{
+ benchmark(nop_loop, "nop loop");
+ benchmark(native_sin, "native sine");
+ benchmark(fxpt_sin, "fxpt sine");
+ benchmark(native_sincos, "native sin/cos");
+ benchmark(fxpt_sincos, "fxpt sin/cos");
+ benchmark(basic_sincos_vec, "basic sin/cos vec");
+ benchmark(native_sincos_vec, "native sin/cos vec");
+ benchmark(fxpt_sincos_vec, "fxpt sin/cos vec");
+}
diff --git a/gr-blocks/tests/benchmark_vco.cc b/gr-blocks/tests/benchmark_vco.cc
new file mode 100644
index 0000000000..955dc08051
--- /dev/null
+++ b/gr-blocks/tests/benchmark_vco.cc
@@ -0,0 +1,172 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2002,2004,2005,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 GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/time.h>
+
+#ifdef HAVE_SYS_RESOURCE_H
+#include <sys/resource.h>
+#endif
+
+#include <unistd.h>
+#include <blocks/vco.h>
+#include <blocks/fxpt_vco.h>
+#include <string.h>
+
+#define ITERATIONS 5000000
+#define BLOCK_SIZE (10 * 1000) // fits in cache
+
+#define FREQ 5003.123
+#define K 4.9999999
+#define AMPLITUDE 2.444444444
+
+
+static double
+timeval_to_double(const struct timeval *tv)
+{
+ return (double) tv->tv_sec + (double) tv->tv_usec * 1e-6;
+}
+
+
+static void
+benchmark(void test (float *x, const float *y), const char *implementation_name)
+{
+#ifdef HAVE_SYS_RESOURCE_H
+ struct rusage rusage_start;
+ struct rusage rusage_stop;
+#else
+ double clock_start;
+ double clock_end;
+#endif
+ float output[BLOCK_SIZE];
+ float input[BLOCK_SIZE];
+
+ // touch memory
+ memset(output, 0, BLOCK_SIZE*sizeof(float));
+ for(int i = 0; i<BLOCK_SIZE; i++)
+ input[i] = sin(double(i));
+
+ // get starting CPU usage
+#ifdef HAVE_SYS_RESOURCE_H
+ if(getrusage (RUSAGE_SELF, &rusage_start) < 0) {
+ perror("getrusage");
+ exit(1);
+ }
+#else
+ clock_start = (double)clock() * (1000000. / CLOCKS_PER_SEC);
+#endif
+ // do the actual work
+
+ test(output, input);
+
+ // get ending CPU usage
+
+#ifdef HAVE_SYS_RESOURCE_H
+ if(getrusage (RUSAGE_SELF, &rusage_stop) < 0) {
+ perror("getrusage");
+ exit(1);
+ }
+
+ // compute results
+
+ double user =
+ timeval_to_double(&rusage_stop.ru_utime)
+ - timeval_to_double(&rusage_start.ru_utime);
+
+ double sys =
+ timeval_to_double(&rusage_stop.ru_stime)
+ - timeval_to_double(&rusage_start.ru_stime);
+
+ double total = user + sys;
+#else
+ clock_end = (double)clock() * (1000000. / CLOCKS_PER_SEC);
+ double total = clock_end - clock_start;
+#endif
+
+ printf("%18s: cpu: %6.3f steps/sec: %10.3e\n",
+ implementation_name, total, ITERATIONS / total);
+}
+
+// ----------------------------------------------------------------
+
+void basic_vco(float *output, const float *input)
+{
+ double phase = 0;
+
+ for(int j = 0; j < ITERATIONS/BLOCK_SIZE; j++) {
+ for(int i = 0; i < BLOCK_SIZE; i++) {
+ output[i] = cos(phase) * AMPLITUDE;
+ phase += input[i] * K;
+
+ while(phase > 2 * M_PI)
+ phase -= 2 * M_PI;
+
+ while(phase < -2 * M_PI)
+ phase += 2 * M_PI;
+ }
+ }
+}
+
+void native_vco(float *output, const float *input)
+{
+ gr::blocks::vco<float,float> vco;
+
+ for(int j = 0; j < ITERATIONS/BLOCK_SIZE; j++) {
+ vco.cos(output, input, BLOCK_SIZE, K, AMPLITUDE);
+ }
+}
+
+void fxpt_vco(float *output, const float *input)
+{
+ gr::blocks::fxpt_vco vco;
+
+ for(int j = 0; j < ITERATIONS/BLOCK_SIZE; j++) {
+ vco.cos(output, input, BLOCK_SIZE, K, AMPLITUDE);
+ }
+}
+
+// ----------------------------------------------------------------
+
+void nop_fct(float *x, const float *y)
+{
+}
+
+void nop_loop(float *x, const float *y)
+{
+ for(int i = 0; i < ITERATIONS; i++) {
+ nop_fct(x, y);
+ }
+}
+
+int
+main(int argc, char **argv)
+{
+ benchmark(nop_loop, "nop loop");
+ benchmark(basic_vco, "basic vco");
+ benchmark(native_vco, "native vco");
+ benchmark(fxpt_vco, "fxpt vco");
+}
diff --git a/gr-blocks/tests/nco_results b/gr-blocks/tests/nco_results
new file mode 100644
index 0000000000..5bdf5dd1cb
--- /dev/null
+++ b/gr-blocks/tests/nco_results
@@ -0,0 +1,48 @@
+================================================================
+These are on a 1.4 GHz Pentium M using g++ 3.4.1
+================================================================
+
+Default compiler options -O2
+
+ nop loop: cpu: 0.015 steps/sec: 6.668e+08
+ native sine: cpu: 0.900 steps/sec: 1.111e+07
+ fxpt sine: cpu: 0.281 steps/sec: 3.559e+07
+ native sin/cos: cpu: 1.138 steps/sec: 8.789e+06
+ fxpt sin/cos: cpu: 0.550 steps/sec: 1.818e+07
+
+-O2 -march=pentium-m -fomit-frame-pointer
+
+ nop loop: cpu: 0.015 steps/sec: 6.668e+08
+ native sine: cpu: 0.903 steps/sec: 1.108e+07
+ fxpt sine: cpu: 0.271 steps/sec: 3.691e+07
+ native sin/cos: cpu: 1.092 steps/sec: 9.159e+06
+ fxpt sin/cos: cpu: 0.542 steps/sec: 1.845e+07
+
+Inlined fxpt::sin & cos
+-O2 -march=pentium-m -fomit-frame-pointer
+
+ nop loop: cpu: 0.015 steps/sec: 6.668e+08
+ native sine: cpu: 0.904 steps/sec: 1.106e+07
+ fxpt sine: cpu: 0.187 steps/sec: 5.348e+07
+ native sin/cos: cpu: 1.091 steps/sec: 9.167e+06
+ fxpt sin/cos: cpu: 0.373 steps/sec: 2.681e+07
+
+================================================================
+These are on a 1.5 GHz Athon MP 1800+
+================================================================
+
+Default compiler options: -O2
+
+ nop loop: cpu: 0.013 steps/sec: 7.693e+08
+ native sine: cpu: 0.733 steps/sec: 1.364e+07
+ fxpt sine: cpu: 0.210 steps/sec: 4.763e+07
+ native sin/cos: cpu: 1.183 steps/sec: 8.454e+06
+ fxpt sin/cos: cpu: 0.420 steps/sec: 2.381e+07
+
+-O2 -fomit-frame-pointer -march=athlon-mp
+
+ nop loop: cpu: 0.013 steps/sec: 7.693e+08
+ native sine: cpu: 0.679 steps/sec: 1.473e+07
+ fxpt sine: cpu: 0.200 steps/sec: 5.001e+07
+ native sin/cos: cpu: 1.147 steps/sec: 8.720e+06
+ fxpt sin/cos: cpu: 0.444 steps/sec: 2.253e+07