summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile.common4
-rw-r--r--config/grc_gr_digital.m417
-rw-r--r--gnuradio-core/src/guile/tests/general_ctors.test6
-rw-r--r--gnuradio-core/src/lib/filter/gr_pfb_clock_sync_ccf.cc64
-rw-r--r--gnuradio-core/src/lib/filter/gr_pfb_clock_sync_ccf.h1
-rw-r--r--gnuradio-core/src/lib/general/CMakeLists.txt2
-rw-r--r--gnuradio-core/src/lib/general/Makefile.am5
-rw-r--r--gnuradio-core/src/lib/general/general.i4
-rw-r--r--gnuradio-core/src/lib/general/gr_cpm.cc214
-rw-r--r--gnuradio-core/src/lib/general/gr_cpm.h81
-rw-r--r--gnuradio-core/src/lib/general/gr_cpm.i40
-rw-r--r--gnuradio-core/src/lib/general/gr_pll_carriertracking_cc.cc43
-rw-r--r--gnuradio-core/src/lib/general/gr_pll_carriertracking_cc.h23
-rw-r--r--gnuradio-core/src/lib/general/gr_pll_carriertracking_cc.i11
-rw-r--r--gnuradio-core/src/lib/general/gr_pll_freqdet_cf.cc33
-rw-r--r--gnuradio-core/src/lib/general/gr_pll_freqdet_cf.h24
-rw-r--r--gnuradio-core/src/lib/general/gr_pll_freqdet_cf.i11
-rw-r--r--gnuradio-core/src/lib/general/gr_pll_refout_cc.cc4
-rw-r--r--gnuradio-core/src/lib/general/gr_pll_refout_cc.h4
-rw-r--r--gnuradio-core/src/lib/general/gri_control_loop.cc4
-rw-r--r--gnuradio-core/src/lib/general/qa_general.cc2
-rw-r--r--gnuradio-core/src/lib/general/qa_gr_cpm.cc140
-rw-r--r--gnuradio-core/src/lib/general/qa_gr_cpm.h49
-rw-r--r--gnuradio-core/src/lib/hier/Makefile.am2
-rw-r--r--gnuradio-core/src/lib/hier/hier.i1
-rwxr-xr-xgnuradio-core/src/python/gnuradio/gr/qa_pll_carriertracking.py207
-rwxr-xr-xgnuradio-core/src/python/gnuradio/gr/qa_pll_freqdet.py207
-rwxr-xr-xgnuradio-core/src/python/gnuradio/gr/qa_pll_refout.py208
-rw-r--r--gr-digital/CMakeLists.txt3
-rw-r--r--gr-digital/Makefile.am2
-rw-r--r--gr-digital/examples/CMakeLists.txt27
-rwxr-xr-xgr-digital/examples/benchmark_add_channel.py101
-rw-r--r--gr-digital/grc/Makefile.am4
-rw-r--r--gr-digital/grc/digital_block_tree.xml2
-rw-r--r--gr-digital/grc/digital_costas_loop_cc.xml12
-rw-r--r--gr-digital/grc/digital_fll_band_edge_cc.xml (renamed from grc/blocks/gr_fll_band_edge_cc.xml)16
-rw-r--r--gr-digital/grc/digital_mpsk_receiver_cc.xml (renamed from grc/blocks/gr_mpsk_receiver_cc.xml)14
-rw-r--r--gr-digital/hier/.gitignore2
-rw-r--r--gr-digital/hier/CMakeLists.txt43
-rw-r--r--gr-digital/hier/Makefile.am40
-rw-r--r--gr-digital/hier/_digital_hier.i33
-rw-r--r--gr-digital/hier/digital_cpmmod_bc.cc69
-rw-r--r--gr-digital/hier/digital_cpmmod_bc.h96
-rw-r--r--gr-digital/hier/digital_cpmmod_bc.i40
-rw-r--r--gr-digital/hier/digital_gmskmod_bc.cc44
-rw-r--r--gr-digital/hier/digital_gmskmod_bc.h62
-rw-r--r--gr-digital/hier/digital_gmskmod_bc.i39
-rw-r--r--gr-digital/lib/Makefile.am3
-rw-r--r--gr-digital/lib/digital_constellation.cc86
-rw-r--r--gr-digital/lib/digital_constellation.h90
-rw-r--r--gr-digital/lib/digital_constellation_receiver_cb.cc145
-rw-r--r--gr-digital/lib/digital_constellation_receiver_cb.h147
-rw-r--r--gr-digital/lib/digital_fll_band_edge_cc.cc139
-rw-r--r--gr-digital/lib/digital_fll_band_edge_cc.h218
-rw-r--r--gr-digital/lib/digital_mpsk_receiver_cc.cc36
-rw-r--r--gr-digital/lib/digital_mpsk_receiver_cc.h169
-rw-r--r--gr-digital/python/Makefile.am1
-rw-r--r--gr-digital/python/__init__.py1
-rw-r--r--gr-digital/python/generic_mod_demod.py23
-rw-r--r--gr-digital/python/gmsk.py106
-rwxr-xr-xgr-digital/python/qa_constellation.py11
-rwxr-xr-xgr-digital/python/qa_constellation_receiver.py12
-rwxr-xr-xgr-digital/python/qa_cpm.py91
-rwxr-xr-x[-rw-r--r--]gr-digital/python/qa_crc32.py0
-rwxr-xr-x[-rw-r--r--]gr-digital/python/qa_fll_band_edge.py0
-rwxr-xr-x[-rw-r--r--]gr-digital/python/qa_lms_equalizer.py0
-rwxr-xr-x[-rw-r--r--]gr-digital/python/qa_mpsk_receiver.py26
-rw-r--r--gr-digital/python/qpsk.py67
-rw-r--r--gr-digital/swig/CMakeLists.txt3
-rw-r--r--gr-digital/swig/Makefile.am10
-rw-r--r--gr-digital/swig/Makefile.swig.gen148
-rw-r--r--gr-digital/swig/digital_constellation.i18
-rw-r--r--gr-digital/swig/digital_constellation_receiver_cb.i16
-rw-r--r--gr-digital/swig/digital_fll_band_edge_cc.i2
-rw-r--r--gr-digital/swig/digital_hier.i40
-rw-r--r--gr-digital/swig/digital_mpsk_receiver_cc.i14
-rw-r--r--gr-digital/swig/digital_swig.i1
-rwxr-xr-xgr-utils/src/python/gr_plot_const.py2
-rw-r--r--grc/blocks/Makefile.am4
-rw-r--r--grc/blocks/block_tree.xml5
-rw-r--r--grc/blocks/gr_cpmmod_bc.xml69
-rw-r--r--grc/blocks/gr_gmskmod_bc.xml38
-rw-r--r--grc/blocks/gr_pll_carriertracking_cc.xml12
-rw-r--r--grc/blocks/gr_pll_freqdet_cf.xml12
-rw-r--r--grc/blocks/gr_pll_refout_cc.xml12
85 files changed, 2498 insertions, 1339 deletions
diff --git a/Makefile.common b/Makefile.common
index 20b8a78cf..2a5addd65 100644
--- a/Makefile.common
+++ b/Makefile.common
@@ -110,6 +110,10 @@ GCELL_SPU_LA = @gcell_spu_LA@
# libtool aware wrapper for ppu-embedspu
GCELL_EMBEDSPU_LIBTOOL = @abs_top_srcdir@/gcell/lib/runtime/gcell-embedspu-libtool
+# GR-DIGITAL includes and libraries
+GR_DIGITAL_INCLUDES = @gr_digital_INCLUDES@
+GR_DIGITAL_LA = @gr_digital_LA@
+
# Fix for BSD make not defining $(RM). We define it now in configure.ac
# using AM_PATH_PROG, but now here have to add a -f to be like GNU make
RM=$(RM_PROG) -f
diff --git a/config/grc_gr_digital.m4 b/config/grc_gr_digital.m4
index 83c3f03a4..d7c1d605f 100644
--- a/config/grc_gr_digital.m4
+++ b/config/grc_gr_digital.m4
@@ -23,12 +23,29 @@ AC_DEFUN([GRC_GR_DIGITAL],[
dnl Don't do gr-digital if gnuradio-core skipped
GRC_CHECK_DEPENDENCY(gr-digital, gnuradio-core)
+ if test $passed != with; then
+ dnl how and where to find INCLUDES and LA and such
+ gr_digital_INCLUDES="\
+-I\${abs_top_srcdir}/gr-digital/lib \
+-I\${abs_top_srcdir}/gr-digital/hier \
+-I\${abs_top_srcdir}/gr-digital/swig"
+ gr_digital_LA="\${abs_top_builddir}/gr-digital/lib/libgnuradio-core.la"
+ gr_digital_LIBDIRPATH="\${abs_top_builddir}/gr-digital/lib:\${abs_top_builddir}/gr-digital/lib/.libs"
+ gr_digital_SWIGDIRPATH="\${abs_top_builddir}/gr-digtial/lib/swig:\${abs_top_builddir}/gr-digital/swig/.libs:\${abs_top_srcdir}/gr-digital/swig"
+ gr_digital_PYDIRPATH="\${abs_top_srcdir}/gr-digital/python"
+ fi
+
+ AC_SUBST(gr_digital_I)
+ AC_SUBST(gr_digital_SWIGDIRPATH)
+ AC_SUBST(gr_digital_PYDIRPATH)
+
AC_CONFIG_FILES([\
gr-digital/Makefile \
gr-digital/gnuradio-digital.pc \
gr-digital/apps/Makefile \
gr-digital/grc/Makefile \
gr-digital/lib/Makefile \
+ gr-digital/hier/Makefile \
gr-digital/python/Makefile \
gr-digital/python/run_tests \
gr-digital/python/utils/Makefile \
diff --git a/gnuradio-core/src/guile/tests/general_ctors.test b/gnuradio-core/src/guile/tests/general_ctors.test
index 813574bca..a0e39855c 100644
--- a/gnuradio-core/src/guile/tests/general_ctors.test
+++ b/gnuradio-core/src/guile/tests/general_ctors.test
@@ -244,13 +244,13 @@
(pass-if (true? (gr:phase-modulator-fc 0)))
;;; ./general/gr_pll_carriertracking_cc.h
-(pass-if (true? (gr:pll-carriertracking-cc 0 0 0 0)))
+(pass-if (true? (gr:pll-carriertracking-cc 0 0 0)))
;;; ./general/gr_pll_freqdet_cf.h
-(pass-if (true? (gr:pll-freqdet-cf 0 0 0 0)))
+(pass-if (true? (gr:pll-freqdet-cf 0 0 0)))
;;; ./general/gr_pll_refout_cc.h
-(pass-if (true? (gr:pll-refout-cc 0 0 0 0)))
+(pass-if (true? (gr:pll-refout-cc 0 0 0)))
;;; ./general/gr_pn_correlator_cc.h
(pass-if (true? (gr:pn-correlator-cc 1 1 1)))
diff --git a/gnuradio-core/src/lib/filter/gr_pfb_clock_sync_ccf.cc b/gnuradio-core/src/lib/filter/gr_pfb_clock_sync_ccf.cc
index b5a5aed7d..a939609f3 100644
--- a/gnuradio-core/src/lib/filter/gr_pfb_clock_sync_ccf.cc
+++ b/gnuradio-core/src/lib/filter/gr_pfb_clock_sync_ccf.cc
@@ -60,7 +60,7 @@ gr_pfb_clock_sync_ccf::gr_pfb_clock_sync_ccf (double sps, float loop_bw,
gr_make_io_signaturev (1, 4, iosig)),
d_updated (false), d_nfilters(filter_size),
d_max_dev(max_rate_deviation),
- d_osps(osps)
+ d_osps(osps), d_error(0)
{
d_nfilters = filter_size;
d_sps = floor(sps);
@@ -367,51 +367,51 @@ gr_pfb_clock_sync_ccf::general_work (int noutput_items,
int nrequired = ninput_items[0] - d_taps_per_filter - d_osps;
int i = 0, count = 0;
- float error, error_r, error_i;
+ float error_r, error_i;
// produce output as long as we can and there are enough input samples
while((i < noutput_items-d_osps) && (count < nrequired)) {
- d_filtnum = (int)floor(d_k);
-
- // Keep the current filter number in [0, d_nfilters]
- // If we've run beyond the last filter, wrap around and go to next sample
- // If we've go below 0, wrap around and go to previous sample
- while(d_filtnum >= d_nfilters) {
- d_k -= d_nfilters;
- d_filtnum -= d_nfilters;
- count += 1;
- }
- while(d_filtnum < 0) {
- d_k += d_nfilters;
- d_filtnum += d_nfilters;
- count -= 1;
- }
-
for(int k = 0; k < d_osps; k++) {
+ d_filtnum = (int)floor(d_k);
+
+ // Keep the current filter number in [0, d_nfilters]
+ // If we've run beyond the last filter, wrap around and go to next sample
+ // If we've go below 0, wrap around and go to previous sample
+ while(d_filtnum >= d_nfilters) {
+ d_k -= d_nfilters;
+ d_filtnum -= d_nfilters;
+ count += 1;
+ }
+ while(d_filtnum < 0) {
+ d_k += d_nfilters;
+ d_filtnum += d_nfilters;
+ count -= 1;
+ }
+
out[i+k] = d_filters[d_filtnum]->filter(&in[count+k]);
+ d_k = d_k + d_rate_i + d_rate_f; // update phase
+
+ if(output_items.size() == 4) {
+ err[i] = d_error;
+ outrate[i] = d_rate_f;
+ outk[i] = d_k;
+ }
}
+ // Update the phase and rate estimates for this symbol
gr_complex diff = d_diff_filters[d_filtnum]->filter(&in[count]);
error_r = out[i].real() * diff.real();
error_i = out[i].imag() * diff.imag();
- error = (error_i + error_r) / 2.0; // average error from I&Q channel
-
- // Run the control loop to update the current phase (k) and tracking rate
- d_rate_f = d_rate_f + d_beta*error;
- d_k = d_k + d_alpha*error + d_rate_i + d_rate_f;
+ d_error = (error_i + error_r) / 2.0; // average error from I&Q channel
+
+ // Run the control loop to update the current phase (k) and
+ // tracking rate estimates based on the error value
+ d_rate_f = d_rate_f + d_beta*d_error;
+ d_k = d_k + d_alpha*d_error;
// Keep our rate within a good range
d_rate_f = gr_branchless_clip(d_rate_f, d_max_dev);
- if(output_items.size() == 4) {
- // FIXME: don't really know what to do about d_osps>1
- for(int k = 0; k < d_osps; k++) {
- err[i] = diff.real();
- outrate[i] = d_rate_f;
- outk[i] = d_k;
- }
- }
-
i+=d_osps;
count += (int)floor(d_sps);
}
diff --git a/gnuradio-core/src/lib/filter/gr_pfb_clock_sync_ccf.h b/gnuradio-core/src/lib/filter/gr_pfb_clock_sync_ccf.h
index 1f96b9000..2eae11807 100644
--- a/gnuradio-core/src/lib/filter/gr_pfb_clock_sync_ccf.h
+++ b/gnuradio-core/src/lib/filter/gr_pfb_clock_sync_ccf.h
@@ -155,6 +155,7 @@ class GR_CORE_API gr_pfb_clock_sync_ccf : public gr_block
float d_max_dev;
int d_filtnum;
int d_osps;
+ float d_error;
/*!
* Build the polyphase filterbank timing synchronizer.
diff --git a/gnuradio-core/src/lib/general/CMakeLists.txt b/gnuradio-core/src/lib/general/CMakeLists.txt
index 1cd9c6bd1..cb3f0da4b 100644
--- a/gnuradio-core/src/lib/general/CMakeLists.txt
+++ b/gnuradio-core/src/lib/general/CMakeLists.txt
@@ -96,6 +96,7 @@ LIST(APPEND gnuradio_core_sources
LIST(APPEND test_gnuradio_core_sources
${CMAKE_CURRENT_SOURCE_DIR}/qa_general.cc
${CMAKE_CURRENT_SOURCE_DIR}/qa_gr_circular_file.cc
+ ${CMAKE_CURRENT_SOURCE_DIR}/qa_gr_cpm.cc
${CMAKE_CURRENT_SOURCE_DIR}/qa_gr_firdes.cc
${CMAKE_CURRENT_SOURCE_DIR}/qa_gr_fxpt.cc
${CMAKE_CURRENT_SOURCE_DIR}/qa_gr_fxpt_nco.cc
@@ -189,6 +190,7 @@ SET(gr_core_general_triple_threats
gr_conjugate_cc
gr_copy
gr_cpfsk_bc
+ gr_cpm
gr_ctcss_squelch_ff
gr_decode_ccsds_27_fb
gr_diff_decoder_bb
diff --git a/gnuradio-core/src/lib/general/Makefile.am b/gnuradio-core/src/lib/general/Makefile.am
index f210cee39..fe545f98c 100644
--- a/gnuradio-core/src/lib/general/Makefile.am
+++ b/gnuradio-core/src/lib/general/Makefile.am
@@ -55,6 +55,7 @@ libgeneral_la_SOURCES = \
gr_copy.cc \
gr_count_bits.cc \
gr_cpfsk_bc.cc \
+ gr_cpm.cc \
gr_ctcss_squelch_ff.cc \
gr_decode_ccsds_27_fb.cc \
gr_deinterleave.cc \
@@ -176,6 +177,7 @@ libgeneral_la_SOURCES = \
libgeneral_qa_la_SOURCES = \
qa_general.cc \
qa_gr_circular_file.cc \
+ qa_gr_cpm.cc \
qa_gr_firdes.cc \
qa_gr_fxpt.cc \
qa_gr_fxpt_nco.cc \
@@ -203,6 +205,7 @@ grinclude_HEADERS = \
gr_copy.h \
gr_count_bits.h \
gr_cpfsk_bc.h \
+ gr_cpm.h \
gr_ctcss_squelch_ff.h \
gr_decode_ccsds_27_fb.h \
gr_diff_decoder_bb.h \
@@ -340,6 +343,7 @@ grinclude_HEADERS = \
noinst_HEADERS = \
qa_general.h \
qa_gr_circular_file.h \
+ qa_gr_cpm.h \
qa_gr_firdes.h \
qa_gr_fxpt.h \
qa_gr_fxpt_nco.h \
@@ -367,6 +371,7 @@ swiginclude_HEADERS = \
gr_conjugate_cc.i \
gr_copy.i \
gr_cpfsk_bc.i \
+ gr_cpm.i \
gr_ctcss_squelch_ff.i \
gr_decode_ccsds_27_fb.i \
gr_diff_decoder_bb.i \
diff --git a/gnuradio-core/src/lib/general/general.i b/gnuradio-core/src/lib/general/general.i
index f9adff3fa..e965eea64 100644
--- a/gnuradio-core/src/lib/general/general.i
+++ b/gnuradio-core/src/lib/general/general.i
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/*
- * Copyright 2004,2005,2006,2007,2008,2009 Free Software Foundation, Inc.
+ * Copyright 2004,2005,2006,2007,2008,2009,2010 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
@@ -137,6 +137,7 @@
#include <gr_annotator_alltoall.h>
#include <gr_annotator_1to1.h>
#include <gr_burst_tagger.h>
+#include <gr_cpm.h>
%}
%include "gri_control_loop.i"
@@ -254,3 +255,4 @@
%include "gr_annotator_alltoall.i"
%include "gr_annotator_1to1.i"
%include "gr_burst_tagger.i"
+%include "gr_cpm.i"
diff --git a/gnuradio-core/src/lib/general/gr_cpm.cc b/gnuradio-core/src/lib/general/gr_cpm.cc
new file mode 100644
index 000000000..a00526b52
--- /dev/null
+++ b/gnuradio-core/src/lib/general/gr_cpm.cc
@@ -0,0 +1,214 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2010 Free Software Foundation, Inc.
+ *
+ * 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.
+ */
+
+// Calculate the taps for the CPM phase responses
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <cmath>
+#include <cfloat>
+#include <gr_cpm.h>
+
+#ifndef M_TWOPI
+# define M_TWOPI (2*M_PI)
+#endif
+
+//! Normalised sinc function, sinc(x)=sin(pi*x)/pi*x
+inline double
+sinc(double x)
+{
+ if (x == 0) {
+ return 1.0;
+ }
+
+ return sin(M_PI * x) / (M_PI * x);
+}
+
+
+//! Taps for L-RC CPM (Raised cosine of length L symbols)
+std::vector<float>
+generate_cpm_lrc_taps(unsigned samples_per_sym, unsigned L)
+{
+ std::vector<float> taps(samples_per_sym * L, 1.0/L/samples_per_sym);
+ for (unsigned i = 0; i < samples_per_sym * L; i++) {
+ taps[i] *= 1 - cos(M_TWOPI * i / L / samples_per_sym);
+ }
+
+ return taps;
+}
+
+
+/*! Taps for L-SRC CPM (Spectral raised cosine of length L symbols).
+ *
+ * L-SRC has a time-continuous phase response function of
+ *
+ * g(t) = 1/LT * sinc(2t/LT) * cos(beta * 2pi t / LT) / (1 - (4beta / LT * t)^2)
+ *
+ * which is the Fourier transform of a cos-rolloff function with rolloff
+ * beta, and looks like a sinc-function, multiplied with a rolloff term.
+ * We return the main lobe of the sinc, i.e., everything between the
+ * zero crossings.
+ * The time-discrete IR is thus
+ *
+ * g(k) = 1/Ls * sinc(2k/Ls) * cos(beta * pi k / Ls) / (1 - (4beta / Ls * k)^2)
+ * where k = 0...Ls-1
+ * and s = samples per symbol.
+ */
+std::vector<float>
+generate_cpm_lsrc_taps(unsigned samples_per_sym, unsigned L, double beta)
+{
+ double Ls = (double) L * samples_per_sym;
+ std::vector<double> taps_d(L * samples_per_sym, 0.0);
+ std::vector<float> taps(L * samples_per_sym, 0.0);
+
+ double sum = 0;
+ for (unsigned i = 0; i < samples_per_sym * L; i++) {
+ double k = i - Ls/2; // Causal to acausal
+
+ taps_d[i] = 1.0 / Ls * sinc(2.0 * k / Ls);
+
+ // For k = +/-Ls/4*beta, the rolloff term's cos-function becomes zero
+ // and the whole thing converges to PI/4 (to prove this, use de
+ // l'hopital's rule).
+ if (fabs(fabs(k) - Ls/4/beta) < 2*DBL_EPSILON) {
+ taps_d[i] *= M_PI_4;
+ } else {
+ double tmp = 4.0 * beta * k / Ls;
+ taps_d[i] *= cos(beta * M_TWOPI * k / Ls) / (1 - tmp * tmp);
+ }
+ sum += taps_d[i];
+ }
+ for (unsigned i = 0; i < samples_per_sym * L; i++) {
+ taps[i] = (float) taps_d[i] / sum;
+ }
+
+ return taps;
+}
+
+
+//! Taps for L-REC CPM (Rectangular pulse shape of length L symbols)
+std::vector<float>
+generate_cpm_lrec_taps(unsigned samples_per_sym, unsigned L)
+{
+ return std::vector<float>(samples_per_sym * L, 1.0/L/samples_per_sym);
+}
+
+
+//! Helper function for TFM
+double tfm_g0(double k, double sps)
+{
+ if (fabs(k) < 2 * DBL_EPSILON) {
+ return 1.145393004159143; // 1 + pi^2/48 / sqrt(2)
+ }
+
+ const double pi2_24 = 0.411233516712057; // pi^2/24
+ double f = M_PI * k / sps;
+ return sinc(k/sps) - pi2_24 * (2 * sin(f) - 2*f*cos(f) - f*f*sin(f)) / (f*f*f);
+}
+
+
+//! Taps for TFM CPM (Tamed frequency modulation)
+//
+// See [2, Chapter 2.7.2].
+//
+// [2]: Anderson, Aulin and Sundberg; Digital Phase Modulation
+std::vector<float>
+generate_cpm_tfm_taps(unsigned sps, unsigned L)
+{
+ unsigned causal_shift = sps * L / 2;
+ std::vector<double> taps_d(sps * L, 0.0);
+ std::vector<float> taps(sps * L, 0.0);
+
+ double sum = 0;
+ for (unsigned i = 0; i < sps * L; i++) {
+ double k = (double)(((int)i) - ((int)causal_shift)); // Causal to acausal
+
+ taps_d[i] = tfm_g0(k - sps, sps) +
+ 2 * tfm_g0(k, sps) +
+ tfm_g0(k + sps, sps);
+ sum += taps_d[i];
+ }
+ for (unsigned i = 0; i < sps * L; i++) {
+ taps[i] = (float) taps_d[i] / sum;
+ }
+
+ return taps;
+}
+
+
+//! Taps for Gaussian CPM. Phase response is truncated after \p L symbols.
+// \p bt sets the 3dB-time-bandwidth product.
+//
+// Note: for h = 0.5, this is the phase response for GMSK.
+//
+// This C99-compatible formula for the taps is taken straight
+// from [1, Chapter 9.2.3].
+// A version in Q-notation can be found in [2, Chapter 2.7.2].
+//
+// [1]: Karl-Dirk Kammeyer; Nachrichtenübertragung, 4th Edition.
+// [2]: Anderson, Aulin and Sundberg; Digital Phase Modulation
+//
+std::vector<float>
+generate_cpm_gaussian_taps(unsigned samples_per_sym, unsigned L, double bt)
+{
+ double Ls = (double) L * samples_per_sym;
+ std::vector<double> taps_d(L * samples_per_sym, 0.0);
+ std::vector<float> taps(L * samples_per_sym, 0.0);
+
+ // alpha = sqrt(2/ln(2)) * pi * BT
+ double alpha = 5.336446256636997 * bt;
+ for (unsigned i = 0; i < samples_per_sym * L; i++) {
+ double k = i - Ls/2; // Causal to acausal
+ taps_d[i] = (erf(alpha * (k / samples_per_sym + 0.5)) -
+ erf(alpha * (k / samples_per_sym - 0.5)))
+ * 0.5 / samples_per_sym;
+ taps[i] = (float) taps_d[i];
+ }
+
+ return taps;
+}
+
+
+std::vector<float>
+gr_cpm::phase_response(cpm_type type, unsigned samples_per_sym, unsigned L, double beta)
+{
+ switch (type) {
+ case LRC:
+ return generate_cpm_lrc_taps(samples_per_sym, L);
+
+ case LSRC:
+ return generate_cpm_lsrc_taps(samples_per_sym, L, beta);
+
+ case LREC:
+ return generate_cpm_lrec_taps(samples_per_sym, L);
+
+ case TFM:
+ return generate_cpm_tfm_taps(samples_per_sym, L);
+
+ case GAUSSIAN:
+ return generate_cpm_gaussian_taps(samples_per_sym, L, beta);
+
+ default:
+ return generate_cpm_lrec_taps(samples_per_sym, 1);
+ }
+}
+
diff --git a/gnuradio-core/src/lib/general/gr_cpm.h b/gnuradio-core/src/lib/general/gr_cpm.h
new file mode 100644
index 000000000..ef2ff8414
--- /dev/null
+++ b/gnuradio-core/src/lib/general/gr_cpm.h
@@ -0,0 +1,81 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2010 Free Software Foundation, Inc.
+ *
+ * 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_CPM_H
+#define INCLUDED_GR_CPM_H
+
+#include <gr_core_api.h>
+#include <vector>
+
+class GR_CORE_API gr_cpm
+{
+ public:
+ enum cpm_type {
+ LRC,
+ LSRC,
+ LREC,
+ TFM,
+ GAUSSIAN,
+ GENERIC = 999
+ };
+
+ /*! \brief Return the taps for an interpolating FIR filter (gr_interp_fir_filter_fff).
+ *
+ * These taps represent the phase response \f$g(k)\f$ for use in a CPM modulator,
+ * see also gr_cpmmod_bc.
+ *
+ * \param type The CPM type (Rectangular, Raised Cosine, Spectral Raised Cosine,
+ * Tamed FM or Gaussian).
+ * \param samples_per_sym Samples per symbol.
+ * \param L The length of the phase response in symbols.
+ * \param beta For Spectral Raised Cosine, this is the rolloff factor. For Gaussian
+ * phase responses, this the 3dB-time-bandwidth product. For all other
+ * cases, it is ignored.
+ *
+ * Output: returns a vector of length \a K = \p samples_per_sym x \p L.
+ * This can be used directly in an interpolating FIR filter such as
+ * gr_interp_fir_filter_fff with interpolation factor \p samples_per_sym.
+ *
+ * All phase responses are normalised s.t. \f$ \sum_{k=0}^{K-1} g(k) = 1\f$; this will cause
+ * a maximum phase change of \f$ h \cdot \pi\f$ between two symbols, where \a h is the
+ * modulation index.
+ *
+ * The following phase responses can be generated:
+ * - LREC: Rectangular phase response.
+ * - LRC: Raised cosine phase response, looks like 1 - cos(x).
+ * - LSRC: Spectral raised cosine. This requires a rolloff factor beta.
+ * The phase response is the Fourier transform of raised cosine
+ * function.
+ * - TFM: Tamed frequency modulation. This scheme minimizes phase change for
+ * rapidly varying input symbols.
+ * - GAUSSIAN: A Gaussian phase response. For a modulation index h = 1/2, this
+ * results in GMSK.
+ *
+ * A short description of all these phase responses can be found in [1].
+ *
+ * [1]: Anderson, Aulin and Sundberg; Digital Phase Modulation
+ */
+ static std::vector<float>
+ phase_response(cpm_type type, unsigned samples_per_sym, unsigned L, double beta=0.3);
+};
+
+#endif /* INCLUDED_GR_CPM_H */
+
diff --git a/gnuradio-core/src/lib/general/gr_cpm.i b/gnuradio-core/src/lib/general/gr_cpm.i
new file mode 100644
index 000000000..f01aba34e
--- /dev/null
+++ b/gnuradio-core/src/lib/general/gr_cpm.i
@@ -0,0 +1,40 @@
+/* -*- C++ -*- */
+/*
+ * Copyright 2010 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.
+ */
+
+%rename(cpm) gr_cpm;
+
+class gr_cpm
+{
+ public:
+ enum cpm_type {
+ LRC,
+ LSRC,
+ LREC,
+ TFM,
+ GAUSSIAN,
+ GENERIC = 999
+ };
+
+ static std::vector<float>
+ phase_response(cpm_type type, unsigned samples_per_sym, unsigned L, double beta=0.3);
+};
+
diff --git a/gnuradio-core/src/lib/general/gr_pll_carriertracking_cc.cc b/gnuradio-core/src/lib/general/gr_pll_carriertracking_cc.cc
index 19ab316a1..583e0eb70 100644
--- a/gnuradio-core/src/lib/general/gr_pll_carriertracking_cc.cc
+++ b/gnuradio-core/src/lib/general/gr_pll_carriertracking_cc.cc
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/*
- * Copyright 2006,2010 Free Software Foundation, Inc.
+ * Copyright 2006,2010,2011 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
@@ -30,22 +30,24 @@
#include <math.h>
#include <gr_math.h>
-#define M_TWOPI (2*M_PI)
+#ifndef M_TWOPI
+#define M_TWOPI (2.0f*M_PI)
+#endif
gr_pll_carriertracking_cc_sptr
-gr_make_pll_carriertracking_cc (float alpha, float beta, float max_freq, float min_freq)
+gr_make_pll_carriertracking_cc (float loop_bw, float max_freq, float min_freq)
{
- return gnuradio::get_initial_sptr(new gr_pll_carriertracking_cc (alpha, beta, max_freq, min_freq));
+ return gnuradio::get_initial_sptr(new gr_pll_carriertracking_cc (loop_bw, max_freq, min_freq));
}
-gr_pll_carriertracking_cc::gr_pll_carriertracking_cc (float alpha, float beta, float max_freq, float min_freq)
+gr_pll_carriertracking_cc::gr_pll_carriertracking_cc (float loop_bw,
+ float max_freq,
+ float min_freq)
: gr_sync_block ("pll_carriertracking_cc",
gr_make_io_signature (1, 1, sizeof (gr_complex)),
gr_make_io_signature (1, 1, sizeof (gr_complex))),
- d_alpha(alpha), d_beta(beta),
- d_max_freq(max_freq), d_min_freq(min_freq),
- d_phase(0), d_freq((max_freq+min_freq)/2),
- d_locksig(0),d_lock_threshold(0),d_squelch_enable(false)
+ gri_control_loop(loop_bw, max_freq, min_freq),
+ d_locksig(0), d_lock_threshold(0), d_squelch_enable(false)
{
}
@@ -72,7 +74,7 @@ gr_pll_carriertracking_cc::phase_detector(gr_complex sample,float ref_phase)
bool
gr_pll_carriertracking_cc::lock_detector(void)
{
- return (fabs(d_locksig) > d_lock_threshold);
+ return (fabsf(d_locksig) > d_lock_threshold);
}
bool
@@ -100,17 +102,16 @@ gr_pll_carriertracking_cc::work (int noutput_items,
for (int i = 0; i < noutput_items; i++){
error = phase_detector(iptr[i],d_phase);
-
- d_freq = d_freq + d_beta * error;
- d_phase = mod_2pi(d_phase + d_freq + d_alpha * error);
-
- if (d_freq > d_max_freq)
- d_freq = d_max_freq;
- else if (d_freq < d_min_freq)
- d_freq = d_min_freq;
- gr_sincosf(d_phase,&t_imag,&t_real);
- optr[i] = iptr[i] * gr_complex(t_real,-t_imag);
- d_locksig = d_locksig * (1.0 - d_alpha) + d_alpha*(iptr[i].real() * t_real + iptr[i].imag() * t_imag);
+
+ advance_loop(error);
+ phase_wrap();
+ frequency_limit();
+
+ gr_sincosf(d_phase, &t_imag, &t_real);
+ optr[i] = iptr[i] * gr_complex(t_real, -t_imag);
+
+ d_locksig = d_locksig * (1.0 - d_alpha) + \
+ d_alpha*(iptr[i].real() * t_real + iptr[i].imag() * t_imag);
if ((d_squelch_enable) && !lock_detector())
optr[i] = 0;
diff --git a/gnuradio-core/src/lib/general/gr_pll_carriertracking_cc.h b/gnuradio-core/src/lib/general/gr_pll_carriertracking_cc.h
index 27e74f111..db74bb101 100644
--- a/gnuradio-core/src/lib/general/gr_pll_carriertracking_cc.h
+++ b/gnuradio-core/src/lib/general/gr_pll_carriertracking_cc.h
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/*
- * Copyright 2004,206 Free Software Foundation, Inc.
+ * Copyright 2004,2006,2011 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
@@ -25,12 +25,14 @@
#include <gr_core_api.h>
#include <gr_sync_block.h>
+#include <gri_control_loop.h>
class gr_pll_carriertracking_cc;
typedef boost::shared_ptr<gr_pll_carriertracking_cc> gr_pll_carriertracking_cc_sptr;
-GR_CORE_API gr_pll_carriertracking_cc_sptr gr_make_pll_carriertracking_cc (float alpha, float beta,
- float max_freq, float min_freq);
+GR_CORE_API gr_pll_carriertracking_cc_sptr gr_make_pll_carriertracking_cc (float loop_bw,
+ float max_freq,
+ float min_freq);
/*!
* \brief Implements a PLL which locks to the input frequency and outputs the
* input signal mixed with that carrier.
@@ -42,19 +44,20 @@ GR_CORE_API gr_pll_carriertracking_cc_sptr gr_make_pll_carriertracking_cc (float
* the input and outputs that signal, downconverted to DC
*
* All settings max_freq and min_freq are in terms of radians per sample,
- * NOT HERTZ. Alpha is the phase gain (first order, units of radians per radian)
- * and beta is the frequency gain (second order, units of radians per sample per radian)
+ * NOT HERTZ. The loop bandwidth determins the lock range and should be set
+ * around pi/200 -- 2pi/100.
* \sa gr_pll_freqdet_cf, gr_pll_carriertracking_cc
*/
-class GR_CORE_API gr_pll_carriertracking_cc : public gr_sync_block
+class GR_CORE_API gr_pll_carriertracking_cc : public gr_sync_block, public gri_control_loop
{
- friend GR_CORE_API gr_pll_carriertracking_cc_sptr gr_make_pll_carriertracking_cc (float alpha, float beta,
- float max_freq, float min_freq);
+ friend GR_CORE_API gr_pll_carriertracking_cc_sptr gr_make_pll_carriertracking_cc (float loop_bw,
+ float max_freq,
+ float min_freq);
- float d_alpha,d_beta,d_max_freq,d_min_freq,d_phase,d_freq,d_locksig,d_lock_threshold;
+ float d_locksig,d_lock_threshold;
bool d_squelch_enable;
- gr_pll_carriertracking_cc (float alpha, float beta, float max_freq, float min_freq);
+ gr_pll_carriertracking_cc (float loop_bw, float max_freq, float min_freq);
int work (int noutput_items,
gr_vector_const_void_star &input_items,
diff --git a/gnuradio-core/src/lib/general/gr_pll_carriertracking_cc.i b/gnuradio-core/src/lib/general/gr_pll_carriertracking_cc.i
index 3e84fccbe..d309111b2 100644
--- a/gnuradio-core/src/lib/general/gr_pll_carriertracking_cc.i
+++ b/gnuradio-core/src/lib/general/gr_pll_carriertracking_cc.i
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/*
- * Copyright 2005 Free Software Foundation, Inc.
+ * Copyright 2005,2011 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
@@ -23,13 +23,14 @@
GR_SWIG_BLOCK_MAGIC(gr,pll_carriertracking_cc);
gr_pll_carriertracking_cc_sptr
-gr_make_pll_carriertracking_cc (float alpha, float beta,
- float max_freq, float min_freq);
+gr_make_pll_carriertracking_cc (float loop_bw,
+ float max_freq,
+ float min_freq);
-class gr_pll_carriertracking_cc : public gr_sync_block
+class gr_pll_carriertracking_cc : public gr_sync_block, public gri_control_loop
{
private:
- gr_pll_carriertracking_cc (float alpha, float beta, float max_freq, float min_freq);
+ gr_pll_carriertracking_cc (float loop_bw, float max_freq, float min_freq);
public:
bool lock_detector(void);
bool squelch_enable(bool);
diff --git a/gnuradio-core/src/lib/general/gr_pll_freqdet_cf.cc b/gnuradio-core/src/lib/general/gr_pll_freqdet_cf.cc
index 1f17f2afc..0ae773e6e 100644
--- a/gnuradio-core/src/lib/general/gr_pll_freqdet_cf.cc
+++ b/gnuradio-core/src/lib/general/gr_pll_freqdet_cf.cc
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/*
- * Copyright 2004,2010 Free Software Foundation, Inc.
+ * Copyright 2004,2010,2011 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
@@ -20,8 +20,6 @@
* Boston, MA 02110-1301, USA.
*/
-// WARNING: this file is machine generated. Edits will be over written
-
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
@@ -31,21 +29,21 @@
#include <math.h>
#include <gr_math.h>
-#define M_TWOPI (2*M_PI)
+#ifndef M_TWOPI
+#define M_TWOPI (2.0f*M_PI)
+#endif
gr_pll_freqdet_cf_sptr
-gr_make_pll_freqdet_cf (float alpha, float beta, float max_freq, float min_freq)
+gr_make_pll_freqdet_cf (float loop_bw, float max_freq, float min_freq)
{
- return gnuradio::get_initial_sptr(new gr_pll_freqdet_cf (alpha, beta, max_freq, min_freq));
+ return gnuradio::get_initial_sptr(new gr_pll_freqdet_cf (loop_bw, max_freq, min_freq));
}
-gr_pll_freqdet_cf::gr_pll_freqdet_cf (float alpha, float beta, float max_freq, float min_freq)
+gr_pll_freqdet_cf::gr_pll_freqdet_cf (float loop_bw, float max_freq, float min_freq)
: gr_sync_block ("pll_freqdet_cf",
gr_make_io_signature (1, 1, sizeof (gr_complex)),
gr_make_io_signature (1, 1, sizeof (float))),
- d_alpha(alpha), d_beta(beta),
- d_max_freq(max_freq), d_min_freq(min_freq),
- d_phase(0), d_freq((max_freq+min_freq)/2)
+ gri_control_loop(loop_bw, max_freq, min_freq)
{
}
@@ -70,8 +68,8 @@ gr_pll_freqdet_cf::phase_detector(gr_complex sample,float ref_phase)
int
gr_pll_freqdet_cf::work (int noutput_items,
- gr_vector_const_void_star &input_items,
- gr_vector_void_star &output_items)
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
{
const gr_complex *iptr = (gr_complex *) input_items[0];
float *optr = (float *) output_items[0];
@@ -82,13 +80,10 @@ gr_pll_freqdet_cf::work (int noutput_items,
while (size-- > 0) {
error = phase_detector(*iptr++,d_phase);
- d_freq = d_freq + d_beta * error;
- d_phase = mod_2pi(d_phase + d_freq + d_alpha * error);
-
- if (d_freq > d_max_freq)
- d_freq = d_max_freq;
- else if (d_freq < d_min_freq)
- d_freq = d_min_freq;
+ advance_loop(error);
+ phase_wrap();
+ frequency_limit();
+
*optr++ = d_freq;
}
return noutput_items;
diff --git a/gnuradio-core/src/lib/general/gr_pll_freqdet_cf.h b/gnuradio-core/src/lib/general/gr_pll_freqdet_cf.h
index 6ed1f99c2..336f3fd31 100644
--- a/gnuradio-core/src/lib/general/gr_pll_freqdet_cf.h
+++ b/gnuradio-core/src/lib/general/gr_pll_freqdet_cf.h
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/*
- * Copyright 2004 Free Software Foundation, Inc.
+ * Copyright 2004,2011 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
@@ -25,12 +25,14 @@
#include <gr_core_api.h>
#include <gr_sync_block.h>
+#include <gri_control_loop.h>
class gr_pll_freqdet_cf;
typedef boost::shared_ptr<gr_pll_freqdet_cf> gr_pll_freqdet_cf_sptr;
-GR_CORE_API gr_pll_freqdet_cf_sptr gr_make_pll_freqdet_cf (float alpha, float beta,
- float max_freq, float min_freq);
+GR_CORE_API gr_pll_freqdet_cf_sptr gr_make_pll_freqdet_cf (float loop_bw,
+ float max_freq,
+ float min_freq);
/*!
* \brief Implements a PLL which locks to the input frequency and outputs
* an estimate of that frequency. Useful for FM Demod.
@@ -41,24 +43,24 @@ GR_CORE_API gr_pll_freqdet_cf_sptr gr_make_pll_freqdet_cf (float alpha, float be
* This PLL locks onto a [possibly noisy] reference carrier on
* the input and outputs an estimate of that frequency in radians per sample.
* All settings max_freq and min_freq are in terms of radians per sample,
- * NOT HERTZ. Alpha is the phase gain (first order, units of radians per radian)
- * and beta is the frequency gain (second order, units of radians per sample per radian)
+ * NOT HERTZ. The loop bandwidth determins the lock range and should be set
+ * around pi/200 -- 2pi/100.
* \sa gr_pll_refout_cc, gr_pll_carriertracking_cc
*/
-class GR_CORE_API gr_pll_freqdet_cf : public gr_sync_block
+class GR_CORE_API gr_pll_freqdet_cf : public gr_sync_block, public gri_control_loop
{
- friend GR_CORE_API gr_pll_freqdet_cf_sptr gr_make_pll_freqdet_cf (float alpha, float beta,
- float max_freq, float min_freq);
+ friend GR_CORE_API gr_pll_freqdet_cf_sptr gr_make_pll_freqdet_cf (float loop_bw,
+ float max_freq,
+ float min_freq);
- float d_alpha,d_beta,d_max_freq,d_min_freq,d_phase,d_freq;
- gr_pll_freqdet_cf (float alpha, float beta, float max_freq, float min_freq);
+ float mod_2pi (float in);
+ gr_pll_freqdet_cf (float loop_bw, float max_freq, float min_freq);
int work (int noutput_items,
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items);
private:
- float mod_2pi (float in);
float phase_detector(gr_complex sample,float ref_phase);
};
diff --git a/gnuradio-core/src/lib/general/gr_pll_freqdet_cf.i b/gnuradio-core/src/lib/general/gr_pll_freqdet_cf.i
index b730f037a..f93e6e37e 100644
--- a/gnuradio-core/src/lib/general/gr_pll_freqdet_cf.i
+++ b/gnuradio-core/src/lib/general/gr_pll_freqdet_cf.i
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/*
- * Copyright 2005 Free Software Foundation, Inc.
+ * Copyright 2005,2011 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
@@ -22,11 +22,12 @@
GR_SWIG_BLOCK_MAGIC(gr,pll_freqdet_cf)
- gr_pll_freqdet_cf_sptr gr_make_pll_freqdet_cf (float alpha, float beta,
- float max_freq, float min_freq);
+ gr_pll_freqdet_cf_sptr gr_make_pll_freqdet_cf (float loop_bw,
+ float max_freq,
+ float min_freq);
-class gr_pll_freqdet_cf : public gr_sync_block
+class gr_pll_freqdet_cf : public gr_sync_block, public gri_control_loop
{
private:
- gr_pll_freqdet_cf (float alpha, float beta, float max_freq, float min_freq);
+ gr_pll_freqdet_cf (float loop_bw, float max_freq, float min_freq);
};
diff --git a/gnuradio-core/src/lib/general/gr_pll_refout_cc.cc b/gnuradio-core/src/lib/general/gr_pll_refout_cc.cc
index 8968cd3f1..2b480fcf1 100644
--- a/gnuradio-core/src/lib/general/gr_pll_refout_cc.cc
+++ b/gnuradio-core/src/lib/general/gr_pll_refout_cc.cc
@@ -30,7 +30,9 @@
#include <math.h>
#include <gr_math.h>
-#define M_TWOPI (2*M_PI)
+#ifndef M_TWOPI
+#define M_TWOPI (2.0f*M_PI)
+#endif
gr_pll_refout_cc_sptr
gr_make_pll_refout_cc (float loop_bw, float max_freq, float min_freq)
diff --git a/gnuradio-core/src/lib/general/gr_pll_refout_cc.h b/gnuradio-core/src/lib/general/gr_pll_refout_cc.h
index 11bce5046..dcbeb1efa 100644
--- a/gnuradio-core/src/lib/general/gr_pll_refout_cc.h
+++ b/gnuradio-core/src/lib/general/gr_pll_refout_cc.h
@@ -43,8 +43,8 @@ GR_CORE_API gr_pll_refout_cc_sptr gr_make_pll_refout_cc (float loop_bw,
* aligned to it.
*
* All settings max_freq and min_freq are in terms of radians per sample,
- * NOT HERTZ. Alpha is the phase gain (first order, units of radians per radian)
- * and beta is the frequency gain (second order, units of radians per sample per radian)
+ * NOT HERTZ. The loop bandwidth determins the lock range and should be set
+ * around pi/200 -- 2pi/100.
* \sa gr_pll_freqdet_cf, gr_pll_carriertracking_cc
*/
class GR_CORE_API gr_pll_refout_cc : public gr_sync_block, public gri_control_loop
diff --git a/gnuradio-core/src/lib/general/gri_control_loop.cc b/gnuradio-core/src/lib/general/gri_control_loop.cc
index caad1f5f9..4c64bb922 100644
--- a/gnuradio-core/src/lib/general/gri_control_loop.cc
+++ b/gnuradio-core/src/lib/general/gri_control_loop.cc
@@ -74,9 +74,9 @@ void
gri_control_loop::frequency_limit()
{
if (d_freq > d_max_freq)
- d_freq = d_min_freq;
+ d_freq = d_max_freq;
else if (d_freq < d_min_freq)
- d_freq = d_max_freq;
+ d_freq = d_min_freq;
}
/*******************************************************************
diff --git a/gnuradio-core/src/lib/general/qa_general.cc b/gnuradio-core/src/lib/general/qa_general.cc
index 6984d798c..b9080f362 100644
--- a/gnuradio-core/src/lib/general/qa_general.cc
+++ b/gnuradio-core/src/lib/general/qa_general.cc
@@ -28,6 +28,7 @@
#include <qa_general.h>
#include <qa_gr_firdes.h>
#include <qa_gr_circular_file.h>
+#include <qa_gr_cpm.h>
#include <qa_gr_fxpt.h>
#include <qa_gr_fxpt_nco.h>
#include <qa_gr_fxpt_vco.h>
@@ -41,6 +42,7 @@ qa_general::suite ()
s->addTest (qa_gr_firdes::suite ());
s->addTest (qa_gr_circular_file::suite ());
+ s->addTest (qa_gr_cpm::suite ());
s->addTest (qa_gr_fxpt::suite ());
s->addTest (qa_gr_fxpt_nco::suite ());
s->addTest (qa_gr_fxpt_vco::suite ());
diff --git a/gnuradio-core/src/lib/general/qa_gr_cpm.cc b/gnuradio-core/src/lib/general/qa_gr_cpm.cc
new file mode 100644
index 000000000..cc32d1117
--- /dev/null
+++ b/gnuradio-core/src/lib/general/qa_gr_cpm.cc
@@ -0,0 +1,140 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2010 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 <qa_gr_cpm.h>
+#include <gr_cpm.h>
+#include <cppunit/TestAssert.h>
+
+const double DELTA = 1e-5;
+const int L = 5;
+const int samples_per_sym = 4;
+const float taps_lrc[20] = {
+ 0, 0.002447174185242, 0.009549150281253, 0.020610737385376,
+ 0.034549150281253, 0.050000000000000, 0.065450849718747, 0.079389262614624,
+ 0.090450849718747, 0.097552825814758, 0.100000000000000, 0.097552825814758,
+ 0.090450849718747, 0.079389262614624, 0.065450849718747, 0.050000000000000,
+ 0.034549150281253, 0.020610737385376, 0.009549150281253, 0.002447174185242
+};
+
+
+const float taps_lsrc[20] = { // beta = 0.2
+ 0.000000000000000, 0.009062686687436, 0.019517618142920, 0.030875041875917,
+ 0.042552315421249, 0.053912556756416, 0.064308860403517, 0.073130584159352,
+ 0.079847961304114, 0.084051371489937, 0.085482007518284, 0.084051371489937,
+ 0.079847961304114, 0.073130584159352, 0.064308860403517, 0.053912556756416,
+ 0.042552315421249, 0.030875041875917, 0.019517618142920, 0.009062686687436
+};
+
+
+const float taps_tfm[20] = {
+ -0.003946522220317, -0.005147757690530, -0.003171631690177, 0.003959659609805,
+ 0.017498721302356, 0.037346982678383, 0.062251889790391, 0.087364237065604,
+ 0.110049050955117, 0.125677762224511, 0.132288693729399, 0.125677762224511,
+ 0.110049050955117, 0.087364237065604, 0.062251889790391, 0.037346982678383,
+ 0.017498721302356, 0.003959659609805, -0.003171631690177, -0.005147757690530
+};
+
+
+const float taps_gaussian[20] = { // BT = 0.3
+ 0.000000743866524, 0.000009286258371, 0.000085441834550, 0.000581664421923,
+ 0.002945540765422, 0.011178079812344, 0.032117220937421, 0.070841188736816,
+ 0.122053715366673, 0.167389736919915, 0.185594670675172, 0.167389736919915,
+ 0.122053715366673, 0.070841188736816, 0.032117220937421, 0.011178079812344,
+ 0.002945540765422, 0.000581664421923, 0.000085441834550, 0.000009286258371
+};
+
+
+// Check LREC phase response
+void
+qa_gr_cpm::t1 ()
+{
+ std::vector<float> taps(gr_cpm::phase_response(gr_cpm::LREC, samples_per_sym, L));
+
+ for (int i = 0; i < L * samples_per_sym; i++) {
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(taps[i], 0.05, DELTA);
+ }
+}
+
+
+// Check LRC phase response
+void
+qa_gr_cpm::t2 ()
+{
+ std::vector<float> taps(gr_cpm::phase_response(gr_cpm::LRC, samples_per_sym, L));
+ float sum = 0;
+
+ for (int i = 0; i < L * samples_per_sym; i++) {
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(taps[i], taps_lrc[i], DELTA);
+ sum += taps[i];
+ }
+
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(sum, 1.0, DELTA);
+}
+
+
+// Check LSRC phase response
+void
+qa_gr_cpm::t3 ()
+{
+ std::vector<float> taps(gr_cpm::phase_response(gr_cpm::LSRC, samples_per_sym, L, 0.2));
+ float sum = 0;
+
+ for (int i = 0; i < L * samples_per_sym; i++) {
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(taps[i], taps_lsrc[i], DELTA);
+ sum += taps[i];
+ }
+
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(sum, 1.0, DELTA);
+}
+
+
+// Check the TFM phase response
+void
+qa_gr_cpm::t4 ()
+{
+ std::vector<float> taps(gr_cpm::phase_response(gr_cpm::TFM, samples_per_sym, L));
+ float sum = 0;
+
+ for (int i = 0; i < L * samples_per_sym; i++) {
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(taps[i], taps_tfm[i], DELTA);
+ sum += taps[i];
+ }
+
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(sum, 1.0, DELTA);
+}
+
+
+// Check the Gaussian phase response
+void
+qa_gr_cpm::t5 ()
+{
+ std::vector<float> taps(gr_cpm::phase_response(gr_cpm::GAUSSIAN, samples_per_sym, L, 0.3));
+ float sum = 0;
+
+ for (int i = 0; i < L * samples_per_sym; i++) {
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(taps[i], taps_gaussian[i], DELTA);
+ sum += taps[i];
+ }
+
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(sum, 1.0, DELTA);
+}
+
diff --git a/gnuradio-core/src/lib/general/qa_gr_cpm.h b/gnuradio-core/src/lib/general/qa_gr_cpm.h
new file mode 100644
index 000000000..741cb2860
--- /dev/null
+++ b/gnuradio-core/src/lib/general/qa_gr_cpm.h
@@ -0,0 +1,49 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2010 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 _QA_GR_CPM_H
+#define _QA_GR_CPM_H
+
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/TestCase.h>
+
+class qa_gr_cpm : public CppUnit::TestCase {
+
+ CPPUNIT_TEST_SUITE (qa_gr_cpm);
+ CPPUNIT_TEST (t1);
+ CPPUNIT_TEST (t2);
+ CPPUNIT_TEST (t3);
+ CPPUNIT_TEST (t4);
+ CPPUNIT_TEST (t5);
+ CPPUNIT_TEST_SUITE_END ();
+
+ private:
+ void t1 ();
+ void t2 ();
+ void t3 ();
+ void t4 ();
+ void t5 ();
+
+};
+
+
+#endif /* _QA_GR_CPM_H */
+
diff --git a/gnuradio-core/src/lib/hier/Makefile.am b/gnuradio-core/src/lib/hier/Makefile.am
index b525d19b4..369feef75 100644
--- a/gnuradio-core/src/lib/hier/Makefile.am
+++ b/gnuradio-core/src/lib/hier/Makefile.am
@@ -1,5 +1,5 @@
#
-# Copyright 2009 Free Software Foundation, Inc.
+# Copyright 2009,2010 Free Software Foundation, Inc.
#
# This file is part of GNU Radio
#
diff --git a/gnuradio-core/src/lib/hier/hier.i b/gnuradio-core/src/lib/hier/hier.i
index dbcc8e915..bec3de7ed 100644
--- a/gnuradio-core/src/lib/hier/hier.i
+++ b/gnuradio-core/src/lib/hier/hier.i
@@ -29,3 +29,4 @@
%}
%include "gr_channel_model.i"
+
diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_pll_carriertracking.py b/gnuradio-core/src/python/gnuradio/gr/qa_pll_carriertracking.py
index 8e4a0eefa..4c12924ec 100755
--- a/gnuradio-core/src/python/gnuradio/gr/qa_pll_carriertracking.py
+++ b/gnuradio-core/src/python/gnuradio/gr/qa_pll_carriertracking.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python
#
-# Copyright 2004,2007,2010 Free Software Foundation, Inc.
+# Copyright 2004,2007,2010,2011 Free Software Foundation, Inc.
#
# This file is part of GNU Radio
#
@@ -32,117 +32,116 @@ class test_pll_carriertracking (gr_unittest.TestCase):
self.tb = None
def test_pll_carriertracking (self):
- expected_result = ((1.00000238419+6.47922693275e-09j),
- (0.998399555683+0.0565364062786j),
- (0.994261980057+0.10695001483j),
- (0.98843306303+0.151648163795j),
- (0.981579363346+0.191063538194j),
- (0.974212288857+0.225630432367j),
- (0.966734290123+0.255773901939j),
- (0.959442555904+0.281897842884j),
- (0.952551782131+0.304379671812j),
- (0.946205317974+0.323566257954j),
- (0.940503358841+0.339778244495j),
- (0.935505151749+0.353307723999j),
- (0.931235432625+0.364419162273j),
- (0.927616357803+0.373535633087j),
- (0.924710214138+0.380666583776j),
- (0.922494113445+0.386005342007j),
- (0.92093116045+0.389725029469j),
- (0.919974088669+0.391981720924j),
- (0.919572234154+0.392916500568j),
- (0.919680893421+0.392660915852j),
- (0.920248389244+0.39133310318j),
- (0.921222627163+0.389039844275j),
- (0.922548472881+0.385877460241j),
- (0.924184799194+0.381939411163j),
- (0.926086127758+0.377309292555j),
- (0.928135097027+0.37224984169j),
- (0.930293083191+0.366814315319j),
- (0.932614028454+0.360868781805j),
- (0.935064375401+0.354473829269j),
- (0.937613248825+0.347684770823j),
- (0.940225422382+0.340550601482j),
- (0.942881464958+0.33312189579j),
- (0.945559620857+0.325443327427j),
- (0.948240220547+0.31755694747j),
- (0.950899422169+0.309499144554j),
- (0.953524827957+0.301307469606j),
- (0.956105649471+0.293015599251j),
- (0.958630502224+0.284654557705j),
- (0.96103054285+0.276443749666j),
- (0.963361799717+0.26819768548j),
- (0.965623259544+0.259936869144j),
- (0.967810571194+0.251679092646j),
- (0.969916880131+0.243440493941j),
- (0.971936583519+0.235235646367j),
- (0.97387367487+0.227080151439j),
- (0.975726902485+0.218987599015j),
- (0.977494239807+0.210969462991j),
- (0.979169845581+0.203035995364j),
- (0.980761289597+0.195199295878j),
- (0.982269346714+0.187469303608j),
- (0.983659446239+0.180052131414j),
- (0.984931468964+0.1729388237j),
- (0.986136198044+0.165923252702j),
- (0.987275123596+0.159012272954j),
- (0.988349795341+0.15221118927j),
- (0.989354014397+0.145524248481j),
- (0.990296065807+0.138957872987j),
- (0.991178870201+0.132516458631j),
- (0.992005050182+0.126204773784j),
- (0.992770493031+0.120025672019j),
- (0.993480443954+0.113984130323j),
- (0.994139909744+0.108083210886j),
- (0.994751393795+0.102326385677j),
- (0.995293080807+0.0969148278236j),
- (0.995791256428+0.091630294919j),
- (0.996252119541+0.0864710733294j),
- (0.996678769588+0.0814334899187j),
- (0.997069239616+0.0765165910125j),
- (0.997423350811+0.071716658771j),
- (0.997748315334+0.0670333206654j),
- (0.998046517372+0.0624645166099j),
- (0.998317599297+0.058009263128j),
- (0.998557567596+0.053665690124j),
- (0.998775064945+0.0494344644248j),
- (0.998971700668+0.0453144386411j),
- (0.999140620232+0.0415064357221j),
- (0.99927687645+0.0379924885929j),
- (0.999400436878+0.0345549099147j),
- (0.999511957169+0.0311931278557j),
- (0.99961233139+0.0279070306569j),
- (0.999694347382+0.0246965941042j),
- (0.999765276909+0.0215622838587j),
- (0.999826848507+0.0185046810657j),
- (0.999880313873+0.0155246723443j),
- (0.999920129776+0.0126227736473j),
- (0.999949812889+0.00980060640723j),
- (0.99997317791+0.00705910893157j),
- (0.999990820885+0.00439921114594j),
- (0.999998450279+0.00202245195396j),
- (0.999998092651-0.00029227725463j),
- (0.999994516373-0.00254815118387j),
- (0.999988794327-0.00474932929501j),
- (0.999977111816-0.00689708162099j),
- (0.999957799911-0.00899503659457j),
- (0.999936699867-0.0110441967845j),
- (0.999914228916-0.0130464555696j),
- (0.999889075756-0.0150024276227j),
- (0.999855577946-0.0169130507857j),
- (0.999821305275-0.0187777336687j),
- (0.999786794186-0.0205969288945j))
+ expected_result = ((1.00000238419+6.57831922268e-09j),
+ (0.998351693153+0.0573740489781j),
+ (0.994012773037+0.109242096543j),
+ (0.987789511681+0.155784770846j),
+ (0.980356454849+0.197242289782j),
+ (0.972262203693+0.233890414238j),
+ (0.963963091373+0.266027569771j),
+ (0.955816328526+0.293958544731j),
+ (0.948096513748+0.31798568368j),
+ (0.941002130508+0.338400006294j),
+ (0.934680581093+0.355482578278j),
+ (0.929229319096+0.369498342276j),
+ (0.924701035023+0.380694836378j),
+ (0.921043872833+0.389459967613j),
+ (0.918319702148+0.395834594965j),
+ (0.91650646925+0.400014132261j),
+ (0.915561556816+0.40217769146j),
+ (0.915425121784+0.402490824461j),
+ (0.916029334068+0.401106894016j),
+ (0.917308092117+0.39817237854j),
+ (0.919185698032+0.393822491169j),
+ (0.921583771706+0.388183712959j),
+ (0.924419641495+0.381372988224j),
+ (0.927624821663+0.373506993055j),
+ (0.93112629652+0.364693939686j),
+ (0.934793651104+0.355197936296j),
+ (0.938562095165+0.345107495785j),
+ (0.942447602749+0.33434677124j),
+ (0.946396291256+0.323003143072j),
+ (0.950359642506+0.311159342527j),
+ (0.954286515713+0.298890888691j),
+ (0.958144724369+0.286276459694j),
+ (0.961902141571+0.273387700319j),
+ (0.96553081274+0.260292351246j),
+ (0.969001471996+0.247053653002j),
+ (0.972298383713+0.233733415604j),
+ (0.975410103798+0.220389455557j),
+ (0.978325486183+0.207074314356j),
+ (0.981000483036+0.194007188082j),
+ (0.983471632004+0.181051760912j),
+ (0.985742926598+0.168245732784j),
+ (0.987816333771+0.155622571707j),
+ (0.989693164825+0.143212914467j),
+ (0.991374969482+0.131043404341j),
+ (0.992875099182+0.119139909744j),
+ (0.994201719761+0.107524067163j),
+ (0.995362222195+0.0962148010731j),
+ (0.996359944344+0.0852287560701j),
+ (0.997212648392+0.0745811164379j),
+ (0.997930467129+0.0642844736576j),
+ (0.998514950275+0.0545224510133j),
+ (0.998972594738+0.0452938191593j),
+ (0.999334216118+0.0364210158587j),
+ (0.99960911274+0.0279066264629j),
+ (0.999806642532+0.0197515785694j),
+ (0.99992787838+0.0119558870792j),
+ (0.999987542629+0.00451827049255j),
+ (0.999994814396-0.00256353616714j),
+ (0.999957740307-0.00929233431816j),
+ (0.999877095222-0.0156717002392j),
+ (0.999762177467-0.0217055380344j),
+ (0.999622702599-0.0273993015289j),
+ (0.999463677406-0.0327589809895j),
+ (0.999292552471-0.0376165211201j),
+ (0.999108791351-0.0421659946442j),
+ (0.998919844627-0.0464186370373j),
+ (0.998729586601-0.0503882467747j),
+ (0.998537421227-0.0540841519833j),
+ (0.998342692852-0.0575186908245j),
+ (0.9981533885-0.0607041418552j),
+ (0.997971534729-0.063651651144j),
+ (0.997796595097-0.0663715749979j),
+ (0.997623920441-0.0688742175698j),
+ (0.997461974621-0.0711689144373j),
+ (0.997311413288-0.0732654929161j),
+ (0.997185945511-0.0749996080995j),
+ (0.997077047825-0.0763883292675j),
+ (0.996980309486-0.0776248201728j),
+ (0.996895432472-0.0787187665701j),
+ (0.996822297573-0.0796797126532j),
+ (0.996752738953-0.0805156230927j),
+ (0.996692657471-0.0812350511551j),
+ (0.996642947197-0.0818456709385j),
+ (0.996603965759-0.0823540389538j),
+ (0.996568918228-0.0827651321888j),
+ (0.996540248394-0.0830852389336j),
+ (0.996520996094-0.0833202600479j),
+ (0.996510386467-0.0834743082523j),
+ (0.996518313885-0.0833787024021j),
+ (0.996529102325-0.083223849535j),
+ (0.996545791626-0.0830176770687j),
+ (0.99656867981-0.0827698707581j),
+ (0.996593296528-0.0824855566025j),
+ (0.99661642313-0.0821713805199j),
+ (0.996643543243-0.081834435463j),
+ (0.996674180031-0.0814796686172j),
+ (0.996706545353-0.0811114609241j),
+ (0.996734440327-0.0807323306799j),
+ (0.996764600277-0.0803465023637j),
+ (0.996797323227-0.0799564495683j))
sampling_freq = 10e3
freq = sampling_freq / 100
- alpha = 0.1
- beta = alpha * alpha / 4.0
+ loop_bw = math.pi/100.0
maxf = 1
minf = -1
src = gr.sig_source_c (sampling_freq, gr.GR_COS_WAVE, freq, 1.0)
- pll = gr.pll_carriertracking_cc(alpha, beta, maxf, minf)
+ pll = gr.pll_carriertracking_cc(loop_bw, maxf, minf)
head = gr.head (gr.sizeof_gr_complex, int (freq))
dst = gr.vector_sink_c ()
diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_pll_freqdet.py b/gnuradio-core/src/python/gnuradio/gr/qa_pll_freqdet.py
index 5225a9a3b..b84299a94 100755
--- a/gnuradio-core/src/python/gnuradio/gr/qa_pll_freqdet.py
+++ b/gnuradio-core/src/python/gnuradio/gr/qa_pll_freqdet.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python
#
-# Copyright 2004,2007,2010 Free Software Foundation, Inc.
+# Copyright 2004,2007,2010,2011 Free Software Foundation, Inc.
#
# This file is part of GNU Radio
#
@@ -32,117 +32,116 @@ class test_pll_freqdet (gr_unittest.TestCase):
self.tb = None
def test_pll_refout (self):
- expected_result = (1.1489677586e-07,
- 0.972821060568,
- 2.74556447638,
- 5.14063078448,
- 8.00965819311,
- 11.2291393027,
- 14.6967068752,
- 18.3279143967,
- 22.0534772463,
- 25.8170093072,
- 29.5729107661,
- 33.284774699,
- 36.923857393,
- 40.4367950308,
- 43.8452195091,
- 47.1363835133,
- 50.3011949468,
- 53.3336447847,
- 56.2301489564,
- 58.9891659262,
- 61.6107668417,
- 64.0962975824,
- 66.4481356707,
- 68.6694531128,
- 70.7640326003,
- 72.7048735417,
- 74.5033180826,
- 76.2012544926,
- 77.8019199967,
- 79.3088126954,
- 80.7255907715,
- 82.0560369166,
- 83.3039516093,
- 84.47312347,
- 85.5673411194,
- 86.5902864563,
- 87.5456117346,
- 88.4368565575,
- 89.2363918613,
- 89.9860999864,
- 90.688880206,
- 91.3474598523,
- 91.9644654653,
- 92.5423042123,
- 93.0832706099,
- 93.5894872344,
- 94.0629225081,
- 94.5054203452,
- 94.9186882929,
- 95.3043331057,
- 95.6326268597,
- 95.9117515522,
- 96.1801447842,
- 96.437391527,
- 96.6831953314,
- 96.9173605408,
- 97.1397982206,
- 97.3504727968,
- 97.5493842694,
- 97.7366275022,
- 97.9123092169,
- 98.0766013539,
- 98.2297054988,
- 98.3408087235,
- 98.448722155,
- 98.5534457933,
- 98.6549322065,
- 98.7531932527,
- 98.8481459259,
- 98.9397487233,
- 99.0279067813,
- 99.1125074491,
- 99.193438076,
- 99.2705800823,
- 99.3438030304,
- 99.3817663128,
- 99.3911400359,
- 99.4089388448,
- 99.4334136894,
- 99.4630408207,
- 99.4964684305,
- 99.5325166512,
- 99.5701538394,
- 99.6084432158,
- 99.6466021546,
- 99.6839073198,
- 99.7197895289,
- 99.7537270313,
- 99.7542606398,
- 99.7595848672,
- 99.7691186729,
- 99.7822928746,
- 99.7986331535,
- 99.8175940432,
- 99.838713083,
- 99.8614922382,
- 99.8854571901,
- 99.9101454781,
- 99.9351302152,
- 99.9599845147)
+ expected_result = (4.33888922882e-08,
+ 0.367369994515,
+ 1.08135249597,
+ 2.10983253908,
+ 3.42221529438,
+ 4.98940390402,
+ 6.78379190842,
+ 8.77923286024,
+ 10.9510106794,
+ 13.2758363182,
+ 15.7317829127,
+ 18.2982902299,
+ 20.9561068599,
+ 23.6755271122,
+ 26.452952094,
+ 29.2731265301,
+ 32.1219053479,
+ 34.9862418188,
+ 37.8540971414,
+ 40.7144315483,
+ 43.5571390869,
+ 46.3730179743,
+ 49.1537231663,
+ 51.8917218889,
+ 54.58026103,
+ 57.2015358514,
+ 59.7513664199,
+ 62.2380533124,
+ 64.657612252,
+ 67.006640002,
+ 69.2822432184,
+ 71.4820384499,
+ 73.6041047056,
+ 75.6469478817,
+ 77.6094829742,
+ 79.4909866472,
+ 81.2911031615,
+ 83.0097850853,
+ 84.6355598352,
+ 86.1820937186,
+ 87.6504420946,
+ 89.0418441206,
+ 90.3577286819,
+ 91.5996432431,
+ 92.7692775646,
+ 93.8684162704,
+ 94.8989269904,
+ 95.8627662892,
+ 96.7619381633,
+ 97.598505899,
+ 98.362769679,
+ 99.0579904444,
+ 99.6992633875,
+ 100.288805948,
+ 100.828805921,
+ 101.321421457,
+ 101.76878699,
+ 102.17300138,
+ 102.536116055,
+ 102.860158727,
+ 103.147085962,
+ 103.398830608,
+ 103.617254366,
+ 103.792467691,
+ 103.939387906,
+ 104.060030865,
+ 104.15631756,
+ 104.230085975,
+ 104.283067372,
+ 104.316933727,
+ 104.333238432,
+ 104.333440018,
+ 104.318914008,
+ 104.290941063,
+ 104.250742554,
+ 104.187634452,
+ 104.103822339,
+ 104.013227468,
+ 103.916810336,
+ 103.815448432,
+ 103.709936239,
+ 103.600997093,
+ 103.489283183,
+ 103.375351833,
+ 103.259712936,
+ 103.142828952,
+ 103.025091195,
+ 102.90686726,
+ 102.776726069,
+ 102.648078982,
+ 102.521459607,
+ 102.397294831,
+ 102.275999684,
+ 102.157882471,
+ 102.043215927,
+ 101.93218978,
+ 101.824958181,
+ 101.72159228,
+ 101.622151366,
+ 101.526623582)
sampling_freq = 10e3
freq = sampling_freq / 100
- alpha = 0.2
- beta = alpha * alpha / 4.0
+ loop_bw = math.pi/100.0
maxf = 1
minf = -1
src = gr.sig_source_c (sampling_freq, gr.GR_COS_WAVE, freq, 1.0)
- pll = gr.pll_freqdet_cf(alpha, beta, maxf, minf)
+ pll = gr.pll_freqdet_cf(loop_bw, maxf, minf)
head = gr.head (gr.sizeof_float, int (freq))
dst = gr.vector_sink_f ()
diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_pll_refout.py b/gnuradio-core/src/python/gnuradio/gr/qa_pll_refout.py
index c40a885a8..14f9ab877 100755
--- a/gnuradio-core/src/python/gnuradio/gr/qa_pll_refout.py
+++ b/gnuradio-core/src/python/gnuradio/gr/qa_pll_refout.py
@@ -32,117 +32,116 @@ class test_pll_refout (gr_unittest.TestCase):
self.tb = None
def test_pll_refout (self):
- expected_result = ((1+7.39965699825e-10j),
- (0.999980390072+0.00626518437639j),
- (0.999828696251+0.0185074284673j),
- (0.999342679977+0.0362518876791j),
- (0.998255133629+0.0590478181839j),
- (0.996255218983+0.0864609107375j),
- (0.993005692959+0.118066303432j),
- (0.988157629967+0.153442293406j),
- (0.981362581253+0.192165210843j),
- (0.972283244133+0.233806177974j),
- (0.960601866245+0.277928203344j),
- (0.946027755737+0.324085712433j),
- (0.928303182125+0.371824204922j),
- (0.907292485237+0.420500129461j),
- (0.882742881775+0.469856351614j),
- (0.854515135288+0.519426465034j),
- (0.822515428066+0.568742752075j),
- (0.786696314812+0.617340147495j),
- (0.747057616711+0.664759278297j),
- (0.703645646572+0.710551083088j),
- (0.656552672386+0.754280209541j),
- (0.605915129185+0.795529305935j),
- (0.551911592484+0.833902597427j),
- (0.494760006666+0.869029641151j),
- (0.43471455574+0.900568306446j),
- (0.37224894762+0.928132891655j),
- (0.30767711997+0.951490819454j),
- (0.241136431694+0.970491230488j),
- (0.172981828451+0.984925031662j),
- (0.103586450219+0.99462044239j),
- (0.0333373323083+0.999444127083j),
- (-0.0373690575361+0.999301552773j),
- (-0.108130030334+0.994136750698j),
- (-0.178540825844+0.983932495117j),
- (-0.248198583722+0.968709170818j),
- (-0.316705673933+0.948523879051j),
- (-0.383672952652+0.923469007015j),
- (-0.448723316193+0.893670737743j),
- (-0.51132196188+0.85938924551j),
- (-0.571328520775+0.820721447468j),
- (-0.628420114517+0.777874112129j),
- (-0.682293117046+0.73107868433j),
- (-0.732665538788+0.680588841438j),
- (-0.779277384281+0.626679122448j),
- (-0.821892917156+0.569642007351j),
- (-0.860301196575+0.509786069393j),
- (-0.894317150116+0.447433561087j),
- (-0.923782229424+0.382918298244j),
- (-0.948564887047+0.316582858562j),
- (-0.968560874462+0.248776733875j),
- (-0.983657121658+0.180051699281j),
- (-0.993847966194+0.110753215849j),
- (-0.999158322811+0.0410195216537j),
- (-0.999585151672-0.0288011860102j),
- (-0.995150566101-0.0983632653952j),
- (-0.985901713371-0.16732545197j),
- (-0.971909940243-0.235353127122j),
- (-0.953270018101-0.302119642496j),
- (-0.9300994277-0.367307811975j),
- (-0.902537107468-0.430612027645j),
- (-0.870742559433-0.49173912406j),
- (-0.834894418716-0.550410091877j),
- (-0.795189499855-0.606360971928j),
- (-0.751972675323-0.659194231033j),
- (-0.705345034599-0.708864152431j),
- (-0.65554022789-0.755160272121j),
- (-0.602804005146-0.79788929224j),
- (-0.547393083572-0.836875617504j),
- (-0.489574223757-0.871961653233j),
- (-0.429622590542-0.903008520603j),
- (-0.367820799351-0.929896712303j),
- (-0.30445766449-0.952525854111j),
- (-0.239826664329-0.970815718174j),
- (-0.174224823713-0.984705924988j),
- (-0.107951194048-0.994156181812j),
- (-0.0415063276887-0.999138236046j),
- (0.0248276274651-0.999691724777j),
- (0.0909758731723-0.995853126049j),
- (0.156649470329-0.987654268742j),
- (0.221562758088-0.975146114826j),
- (0.285434871912-0.958398103714j),
- (0.347990810871-0.937497973442j),
- (0.408962905407-0.912550985813j),
- (0.468091338873-0.883680105209j),
- (0.525126338005-0.851024270058j),
- (0.57982814312-0.814738810062j),
- (0.631968915462-0.77499371767j),
- (0.681333422661-0.731973171234j),
- (0.727582573891-0.68602013588j),
- (0.770699381828-0.637198925018j),
- (0.810512244701-0.585721731186j),
- (0.846863090992-0.531810998917j),
- (0.879608631134-0.475698113441j),
- (0.908620357513-0.417623132467j),
- (0.933785498142-0.357833325863j),
- (0.955007195473-0.296582698822j),
- (0.972205162048-0.234130680561j),
- (0.985315918922-0.170741200447j),
- (0.994293272495-0.106681488454j),
- (0.999108314514-0.0422209985554j))
+ expected_result = ((1+6.4087357643e-10j),
+ (0.999985277653+0.00542619498447j),
+ (0.999868750572+0.0162021834403j),
+ (0.99948567152+0.0320679470897j),
+ (0.99860727787+0.0527590736747j),
+ (0.996953129768+0.0780025869608j),
+ (0.994203746319+0.107512556016j),
+ (0.990011692047+0.140985429287j),
+ (0.984013140202+0.178095817566j),
+ (0.975838363171+0.218493551016j),
+ (0.965121984482+0.261800557375j),
+ (0.95151245594+0.307610183954j),
+ (0.934681296349+0.355486690998j),
+ (0.914401650429+0.404808044434j),
+ (0.890356600285+0.455263823271j),
+ (0.862329125404+0.506348133087j),
+ (0.830152392387+0.557536482811j),
+ (0.793714106083+0.608290970325j),
+ (0.752960026264+0.658066213131j),
+ (0.707896590233+0.706316053867j),
+ (0.658591926098+0.752500295639j),
+ (0.605175673962+0.796091973782j),
+ (0.547837555408+0.836584687233j),
+ (0.48682525754+0.873499393463j),
+ (0.42244040966+0.906390726566j),
+ (0.355197101831+0.934791445732j),
+ (0.285494059324+0.958380460739j),
+ (0.213591173291+0.976923108101j),
+ (0.139945343137+0.990159213543j),
+ (0.065038472414+0.997882783413j),
+ (-0.0106285437942+0.999943494797j),
+ (-0.0865436866879+0.996248066425j),
+ (-0.162189796567+0.986759603024j),
+ (-0.23705175519+0.971496999264j),
+ (-0.310622543097+0.950533330441j),
+ (-0.38240903616+0.923993110657j),
+ (-0.451937526464+0.89204955101j),
+ (-0.518758952618+0.854920566082j),
+ (-0.582311093807+0.812966048717j),
+ (-0.642372369766+0.76639264822j),
+ (-0.698591887951+0.715520322323j),
+ (-0.750654160976+0.660695314407j),
+ (-0.798280358315+0.602286040783j),
+ (-0.841228663921+0.540679454803j),
+ (-0.87929558754+0.476276367903j),
+ (-0.912315964699+0.409486919641j),
+ (-0.940161883831+0.340728074312j),
+ (-0.962742805481+0.270418733358j),
+ (-0.980004072189+0.198977485299j),
+ (-0.991925954819+0.126818284392j),
+ (-0.99851256609+0.0545223206282j),
+ (-0.999846458435-0.0175215266645j),
+ (-0.996021270752-0.0891158208251j),
+ (-0.987133920193-0.159895718098j),
+ (-0.973306238651-0.2295101583j),
+ (-0.954683184624-0.297624111176j),
+ (-0.931430280209-0.363919824362j),
+ (-0.903732538223-0.428097635508j),
+ (-0.871792256832-0.489875763655j),
+ (-0.835827112198-0.548992812634j),
+ (-0.796068251133-0.605206847191j),
+ (-0.752758979797-0.658296227455j),
+ (-0.706152498722-0.70805978775j),
+ (-0.656641483307-0.754202902317j),
+ (-0.604367733002-0.79670548439j),
+ (-0.549597978592-0.835429251194j),
+ (-0.492602348328-0.870254516602j),
+ (-0.433654457331-0.901079237461j),
+ (-0.373029649258-0.927819430828j),
+ (-0.31100410223-0.950408577919j),
+ (-0.247853919864-0.968797445297j),
+ (-0.183855071664-0.982953369617j),
+ (-0.119282215834-0.992860376835j),
+ (-0.0544078871608-0.998518764973j),
+ (0.0104992967099-0.999944865704j),
+ (0.0749994292855-0.997183561325j),
+ (0.138844624162-0.990314185619j),
+ (0.201967850327-0.979392170906j),
+ (0.264124274254-0.964488625526j),
+ (0.325075358152-0.945688128471j),
+ (0.3845885396-0.92308807373j),
+ (0.442438393831-0.89679890871j),
+ (0.498407125473-0.866943061352j),
+ (0.552284479141-0.833655714989j),
+ (0.603869199753-0.797083437443j),
+ (0.652970373631-0.757383465767j),
+ (0.69940674305-0.714723825455j),
+ (0.743007957935-0.66928255558j),
+ (0.78350687027-0.62138313055j),
+ (0.820889055729-0.571087777615j),
+ (0.855021059513-0.51859331131j),
+ (0.885780930519-0.46410369873j),
+ (0.913058102131-0.407829582691j),
+ (0.936754107475-0.349988251925j),
+ (0.956783294678-0.290801793337j),
+ (0.973072886467-0.230497643352j),
+ (0.985563337803-0.169307261705j),
+ (0.9942086339-0.1074674353j),
+ (0.9989772439-0.0452152714133j),
+ (0.999851942062+0.0172088555992j))
sampling_freq = 10e3
freq = sampling_freq / 100
- alpha = 0.1
- beta = alpha * alpha / 4.0
+ loop_bw = math.pi/100.0
maxf = 1
minf = -1
src = gr.sig_source_c (sampling_freq, gr.GR_COS_WAVE, freq, 1.0)
- pll = gr.pll_refout_cc(alpha, beta, maxf, minf)
+ pll = gr.pll_refout_cc(loop_bw, maxf, minf)
head = gr.head (gr.sizeof_gr_complex, int (freq))
dst = gr.vector_sink_c ()
@@ -151,8 +150,7 @@ class test_pll_refout (gr_unittest.TestCase):
self.tb.run ()
dst_data = dst.data ()
-
- self.assertComplexTuplesAlmostEqual (expected_result, dst_data, 5)
+ self.assertComplexTuplesAlmostEqual (expected_result, dst_data, 4)
if __name__ == '__main__':
gr_unittest.run(test_pll_refout, "test_pll_refout.xml")
diff --git a/gr-digital/CMakeLists.txt b/gr-digital/CMakeLists.txt
index cc00da69a..bd11be4d3 100644
--- a/gr-digital/CMakeLists.txt
+++ b/gr-digital/CMakeLists.txt
@@ -33,6 +33,7 @@ GR_REGISTER_COMPONENT("gr-digital" ENABLE_GR_DIGITAL
GR_SET_GLOBAL(GR_DIGITAL_INCLUDE_DIRS
${CMAKE_CURRENT_SOURCE_DIR}/lib
+ ${CMAKE_CURRENT_SOURCE_DIR}/hier
)
GR_SET_GLOBAL(GR_DIGITAL_SWIG_INCLUDE_DIRS
@@ -81,11 +82,13 @@ CPACK_COMPONENT("digital_swig"
########################################################################
# Add subdirectories
########################################################################
+GR_INCLUDE_SUBDIRECTORY(hier) #appends to lib sources
ADD_SUBDIRECTORY(lib)
IF(ENABLE_PYTHON)
ADD_SUBDIRECTORY(swig)
ADD_SUBDIRECTORY(python)
ADD_SUBDIRECTORY(grc)
+ ADD_SUBDIRECTORY(examples)
ENDIF(ENABLE_PYTHON)
########################################################################
diff --git a/gr-digital/Makefile.am b/gr-digital/Makefile.am
index f1409793f..346db120f 100644
--- a/gr-digital/Makefile.am
+++ b/gr-digital/Makefile.am
@@ -21,7 +21,7 @@
include $(top_srcdir)/Makefile.common
-SUBDIRS = lib
+SUBDIRS = hier lib
if PYTHON
SUBDIRS += swig python apps grc examples
diff --git a/gr-digital/examples/CMakeLists.txt b/gr-digital/examples/CMakeLists.txt
new file mode 100644
index 000000000..55a8379d9
--- /dev/null
+++ b/gr-digital/examples/CMakeLists.txt
@@ -0,0 +1,27 @@
+# Copyright 2011 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(GrPython)
+
+GR_PYTHON_INSTALL(PROGRAMS
+ transmit_path.py
+ receive_path.py
+ DESTINATION ${GR_PKG_DATA_DIR}/examples/digital
+ COMPONENT "digital_python"
+)
diff --git a/gr-digital/examples/benchmark_add_channel.py b/gr-digital/examples/benchmark_add_channel.py
new file mode 100755
index 000000000..def1f8267
--- /dev/null
+++ b/gr-digital/examples/benchmark_add_channel.py
@@ -0,0 +1,101 @@
+#!/usr/bin/env python
+#
+# Copyright 2010,2011 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
+from gnuradio import eng_notation
+from gnuradio.eng_option import eng_option
+from optparse import OptionParser
+
+import random, math, sys
+
+class my_top_block(gr.top_block):
+ def __init__(self, ifile, ofile, options):
+ gr.top_block.__init__(self)
+
+ SNR = 10.0**(options.snr/10.0)
+ frequency_offset = options.frequency_offset
+ time_offset = options.time_offset
+ phase_offset = options.phase_offset*(math.pi/180.0)
+
+ # calculate noise voltage from SNR
+ # FIXME: normalize to signal amplitude
+ power_in_signal = abs(1.0)**2
+ noise_power = power_in_signal/SNR
+ noise_voltage = math.sqrt(noise_power)
+ print noise_voltage
+
+ self.src = gr.file_source(gr.sizeof_gr_complex, ifile)
+ #self.throttle = gr.throttle(gr.sizeof_gr_complex, options.sample_rate)
+ self.channel = gr.channel_model(noise_voltage, frequency_offset,
+ time_offset, noise_seed=random.randint(0,100000))
+ self.phase = gr.multiply_const_cc(complex(math.cos(phase_offset),
+ math.sin(phase_offset)))
+ self.snk = gr.file_sink(gr.sizeof_gr_complex, ofile)
+
+ self.connect(self.src, self.channel, self.phase, self.snk)
+
+
+# /////////////////////////////////////////////////////////////////////////////
+# main
+# /////////////////////////////////////////////////////////////////////////////
+
+def main():
+ # Create Options Parser:
+ usage = "benchmack_add_channel.py [options] <input file> <output file>"
+ parser = OptionParser (usage=usage, option_class=eng_option, conflict_handler="resolve")
+ parser.add_option("-n", "--snr", type="eng_float", default=30,
+ help="set the SNR of the channel in dB [default=%default]")
+ parser.add_option("", "--seed", action="store_true", default=False,
+ help="use a random seed for AWGN noise [default=%default]")
+ parser.add_option("-f", "--frequency-offset", type="eng_float", default=0,
+ help="set frequency offset introduced by channel [default=%default]")
+ parser.add_option("-t", "--time-offset", type="eng_float", default=1.0,
+ help="set timing offset between Tx and Rx [default=%default]")
+ parser.add_option("-p", "--phase-offset", type="eng_float", default=0,
+ help="set phase offset (in degrees) between Tx and Rx [default=%default]")
+ parser.add_option("-m", "--use-multipath", action="store_true", default=False,
+ help="Use a multipath channel [default=%default]")
+
+ (options, args) = parser.parse_args ()
+
+ if len(args) != 2:
+ parser.print_help(sys.stderr)
+ sys.exit(1)
+
+ ifile = args[0]
+ ofile = args[1]
+
+ # build the graph
+ tb = my_top_block(ifile, ofile, options)
+
+ r = gr.enable_realtime_scheduling()
+ if r != gr.RT_OK:
+ print "Warning: Failed to enable realtime scheduling."
+
+ tb.start() # start flow graph
+ tb.wait() # wait for it to finish
+
+if __name__ == '__main__':
+ try:
+ main()
+ except KeyboardInterrupt:
+ pass
diff --git a/gr-digital/grc/Makefile.am b/gr-digital/grc/Makefile.am
index d271ca06a..963939f12 100644
--- a/gr-digital/grc/Makefile.am
+++ b/gr-digital/grc/Makefile.am
@@ -34,4 +34,6 @@ dist_grcblocks_DATA = \
digital_psk_mod.xml \
digital_psk_demod.xml \
digital_qam_mod.xml \
- digital_qam_demod.xml
+ digital_qam_demod.xml \
+ digital_fll_band_edge_cc.xml \
+ digital_mpsk_receiver_cc.xml
diff --git a/gr-digital/grc/digital_block_tree.xml b/gr-digital/grc/digital_block_tree.xml
index 1be4110e1..3432d876c 100644
--- a/gr-digital/grc/digital_block_tree.xml
+++ b/gr-digital/grc/digital_block_tree.xml
@@ -34,6 +34,8 @@
<block>digital_cma_equalizer_cc</block>
<block>digital_lms_dd_equalizer_cc</block>
<block>digital_kurtotic_equalizer_cc</block>
+ <block>digital_fll_band_edge_cc</block>
+ <block>digital_mpsk_receiver_cc</block>
</cat>
<cat>
<name>Digital Modulators</name>
diff --git a/gr-digital/grc/digital_costas_loop_cc.xml b/gr-digital/grc/digital_costas_loop_cc.xml
index 087535b87..668c43dec 100644
--- a/gr-digital/grc/digital_costas_loop_cc.xml
+++ b/gr-digital/grc/digital_costas_loop_cc.xml
@@ -8,16 +8,10 @@
<name>Costas Loop</name>
<key>digital_costas_loop_cc</key>
<import>from gnuradio import digital</import>
- <make>digital.costas_loop_cc($eta, $w, $order)</make>
- <callback>set_damping_factor($eta)</callback>
- <callback>set_natural_freq($w)</callback>
+ <make>digital.costas_loop_cc($w, $order)</make>
+ <callback>set_loop_bandwidth($w)</callback>
<param>
- <name>Damping Factor</name>
- <key>eta</key>
- <type>real</type>
- </param>
- <param>
- <name>Natural Frequency</name>
+ <name>Loop Bandwidth</name>
<key>w</key>
<type>real</type>
</param>
diff --git a/grc/blocks/gr_fll_band_edge_cc.xml b/gr-digital/grc/digital_fll_band_edge_cc.xml
index 5a13ac49b..1c5a34e54 100644
--- a/grc/blocks/gr_fll_band_edge_cc.xml
+++ b/gr-digital/grc/digital_fll_band_edge_cc.xml
@@ -8,10 +8,8 @@
<name>FLL Band-Edge</name>
<key>gr_fll_band_edge_cc</key>
<import>from gnuradio import gr</import>
- <make>gr.fll_band_edge_cc($samps_per_sym, $rolloff, $filter_size, $alpha, $beta)</make>
- <callback>set_alpha($alpha)</callback>
- <callback>set_beta($beta)</callback>
-
+ <make>gr.fll_band_edge_cc($samps_per_sym, $rolloff, $filter_size, $w)</make>
+ <callback>set_loop_bandwidth($w)</callback>
<param>
<name>Type</name>
<key>type</key>
@@ -41,15 +39,11 @@
</param>
<param>
- <name>Alpha</name>
- <key>alpha</key>
- <type>real</type>
- </param>
- <param>
- <name>Beta</name>
- <key>beta</key>
+ <name>Loop Bandwidth</name>
+ <key>w</key>
<type>real</type>
</param>
+
<sink>
<name>in</name>
<type>$type.input</type>
diff --git a/grc/blocks/gr_mpsk_receiver_cc.xml b/gr-digital/grc/digital_mpsk_receiver_cc.xml
index 843c3a4c1..948f18b6e 100644
--- a/grc/blocks/gr_mpsk_receiver_cc.xml
+++ b/gr-digital/grc/digital_mpsk_receiver_cc.xml
@@ -8,9 +8,8 @@
<name>MPSK Receiver</name>
<key>gr_mpsk_receiver_cc</key>
<import>from gnuradio import gr</import>
- <make>gr.mpsk_receiver_cc($M, $theta, $alpha, $beta, $fmin, $fmax, $mu, $gain_mu, $omega, $gain_omega, $omega_relative_limit)</make>
- <callback>set_alpha($alpha)</callback>
- <callback>set_beta($beta)</callback>
+ <make>gr.mpsk_receiver_cc($M, $theta, $w, $fmin, $fmax, $mu, $gain_mu, $omega, $gain_omega, $omega_relative_limit)</make>
+ <callback>set_loop_bandwidth($w)</callback>
<callback>set_mu($mu)</callback>
<callback>set_gain_mu($gain_mu)</callback>
<callback>set_omega($omega)</callback>
@@ -26,13 +25,8 @@
<type>real</type>
</param>
<param>
- <name>Alpha</name>
- <key>alpha</key>
- <type>real</type>
- </param>
- <param>
- <name>Beta</name>
- <key>beta</key>
+ <name>Loop Bandwidth</name>
+ <key>w</key>
<type>real</type>
</param>
<param>
diff --git a/gr-digital/hier/.gitignore b/gr-digital/hier/.gitignore
new file mode 100644
index 000000000..b336cc7ce
--- /dev/null
+++ b/gr-digital/hier/.gitignore
@@ -0,0 +1,2 @@
+/Makefile
+/Makefile.in
diff --git a/gr-digital/hier/CMakeLists.txt b/gr-digital/hier/CMakeLists.txt
new file mode 100644
index 000000000..f46acc81e
--- /dev/null
+++ b/gr-digital/hier/CMakeLists.txt
@@ -0,0 +1,43 @@
+# Copyright 2011 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.
+
+########################################################################
+# This file included, use CMake directory variables
+########################################################################
+
+LIST(APPEND gr_digital_sources
+ ${CMAKE_CURRENT_SOURCE_DIR}/digital_gmskmod_bc.cc
+ ${CMAKE_CURRENT_SOURCE_DIR}/digital_cpmmod_bc.cc
+)
+
+INSTALL(FILES
+ ${CMAKE_CURRENT_SOURCE_DIR}/digital_gmskmod_bc.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/digital_cpmmod_bc.h
+ DESTINATION ${GR_INCLUDE_DIR}/gnuradio
+ COMPONENT "digital_devel"
+)
+
+INSTALL(
+ FILES
+ ${CMAKE_CURRENT_SOURCE_DIR}/_digital_hier.i
+ ${CMAKE_CURRENT_SOURCE_DIR}/digital_gmskmod_bc.i
+ ${CMAKE_CURRENT_SOURCE_DIR}/digital_cpmmod_bc.i
+ DESTINATION ${GR_INCLUDE_DIR}/gnuradio/swig
+ COMPONENT "digital_swig"
+)
diff --git a/gr-digital/hier/Makefile.am b/gr-digital/hier/Makefile.am
new file mode 100644
index 000000000..b11b85f77
--- /dev/null
+++ b/gr-digital/hier/Makefile.am
@@ -0,0 +1,40 @@
+#
+# Copyright 2011 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 $(top_srcdir)/Makefile.common
+
+AM_CPPFLAGS = $(STD_DEFINES_AND_INCLUDES) $(WITH_INCLUDES)
+
+noinst_LTLIBRARIES = libdigital_hier.la
+
+libdigital_hier_la_SOURCES = \
+ digital_gmskmod_bc.cc \
+ digital_cpmmod_bc.cc
+
+grinclude_HEADERS = \
+ digital_gmskmod_bc.h \
+ digital_cpmmod_bc.h
+
+
+swiginclude_HEADERS = \
+ _digital_hier.i \
+ digital_gmskmod_bc.i \
+ digital_cpmmod_bc.i
diff --git a/gr-digital/hier/_digital_hier.i b/gr-digital/hier/_digital_hier.i
new file mode 100644
index 000000000..022e38644
--- /dev/null
+++ b/gr-digital/hier/_digital_hier.i
@@ -0,0 +1,33 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2011 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 <digital_cpmmod_bc.h>
+#include <digital_gmskmod_bc.h>
+%}
+
+%include "digital_cpmmod_bc.i"
+%include "digital_gmskmod_bc.i"
diff --git a/gr-digital/hier/digital_cpmmod_bc.cc b/gr-digital/hier/digital_cpmmod_bc.cc
new file mode 100644
index 000000000..a95b604d1
--- /dev/null
+++ b/gr-digital/hier/digital_cpmmod_bc.cc
@@ -0,0 +1,69 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2010 Free Software Foundation, Inc.
+ *
+ * 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 <digital_cpmmod_bc.h>
+#include <gr_io_signature.h>
+
+
+// Shared pointer constructor
+digital_cpmmod_bc_sptr
+digital_make_cpmmod_bc(int type, float h,
+ unsigned samples_per_sym,
+ unsigned L, double beta)
+{
+ return gnuradio::get_initial_sptr(new digital_cpmmod_bc((gr_cpm::cpm_type)type,
+ h, samples_per_sym,
+ L, beta));
+}
+
+
+digital_cpmmod_bc::digital_cpmmod_bc(gr_cpm::cpm_type type, float h,
+ unsigned samples_per_sym,
+ unsigned L, double beta)
+ : gr_hier_block2("digital_cpmmod_bc",
+ gr_make_io_signature(1, 1, sizeof(char)),
+ gr_make_io_signature2(1, 1, sizeof(gr_complex), sizeof(float))),
+ d_taps(gr_cpm::phase_response(type, samples_per_sym, L, beta)),
+ d_char_to_float(gr_make_char_to_float()),
+ d_pulse_shaper(gr_make_interp_fir_filter_fff(samples_per_sym, d_taps)),
+ d_fm(gr_make_frequency_modulator_fc(M_PI * h))
+{
+ switch (type) {
+ case gr_cpm::LRC:
+ case gr_cpm::LSRC:
+ case gr_cpm::LREC:
+ case gr_cpm::TFM:
+ case gr_cpm::GAUSSIAN:
+ break;
+
+ default:
+ throw std::invalid_argument("invalid CPM type");
+ }
+
+ connect(self(), 0, d_char_to_float, 0);
+ connect(d_char_to_float, 0, d_pulse_shaper, 0);
+ connect(d_pulse_shaper, 0, d_fm, 0);
+ connect(d_fm, 0, self(), 0);
+}
+
diff --git a/gr-digital/hier/digital_cpmmod_bc.h b/gr-digital/hier/digital_cpmmod_bc.h
new file mode 100644
index 000000000..4e9547cd6
--- /dev/null
+++ b/gr-digital/hier/digital_cpmmod_bc.h
@@ -0,0 +1,96 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2010 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_DIGITAL_CPMMOD_BC_H
+#define INCLUDED_DIGITAL_CPMMOD_BC_H
+
+#include <digital_api.h>
+#include <gr_hier_block2.h>
+#include <gr_char_to_float.h>
+#include <gr_interp_fir_filter_fff.h>
+#include <gr_frequency_modulator_fc.h>
+#include <gr_cpm.h>
+
+
+class digital_cpmmod_bc;
+typedef boost::shared_ptr<digital_cpmmod_bc> digital_cpmmod_bc_sptr;
+
+
+DIGITAL_API digital_cpmmod_bc_sptr
+digital_make_cpmmod_bc(int type, float h,
+ unsigned samples_per_sym,
+ unsigned L, double beta=0.3);
+
+/*!
+ * \brief Generic CPM modulator
+ *
+ * \ingroup modulation_blk
+ *
+ * \param type The modulation type. Can be one of LREC, LRC, LSRC, TFM
+ * or GAUSSIAN. See gr_cpm::phase_response() for a
+ * detailed description.
+ * \param h The modulation index. \f$ h \cdot \pi\f$ is the maximum
+ * phase change that can occur between two symbols, i.e., if
+ * you only send ones, the phase will increase by \f$ h \cdot
+ * \pi\f$ every \p samples_per_sym samples. Set this to 0.5
+ * for Minimum Shift Keying variants.
+ * \param samples_per_sym Samples per symbol.
+ * \param L The length of the phase duration in symbols. For L=1, this
+ * yields full- response CPM symbols, for L > 1,
+ * partial-response.
+ * \param beta For LSRC, this is the rolloff factor. For Gaussian
+ * pulses, this is the 3 dB time-bandwidth product.
+ *
+ * Examples:
+ * - Setting h = 0.5, L = 1, type = LREC yields MSK.
+ * - Setting h = 0.5, type = GAUSSIAN and beta = 0.3 yields GMSK
+ * as used in GSM.
+ *
+ * The input of this block are symbols from an M-ary alphabet
+ * +/-1, +/-3, ..., +/-(M-1). Usually, M = 2 and therefore, the
+ * valid inputs are +/-1.
+ * The modulator will silently accept any other inputs, though.
+ * The output is the phase-modulated signal.
+ */
+class DIGITAL_API digital_cpmmod_bc : public gr_hier_block2
+{
+ friend DIGITAL_API digital_cpmmod_bc_sptr digital_make_cpmmod_bc(int type, float h,
+ unsigned samples_per_sym,
+ unsigned L, double beta);
+
+ std::vector<float> d_taps;
+ gr_char_to_float_sptr d_char_to_float;
+ gr_interp_fir_filter_fff_sptr d_pulse_shaper;
+ gr_frequency_modulator_fc_sptr d_fm;
+
+protected:
+ digital_cpmmod_bc(gr_cpm::cpm_type type, float h,
+ unsigned samples_per_sym,
+ unsigned L, double beta);
+
+public:
+ //! Return the phase response FIR taps
+ std::vector<float> get_taps() { return d_taps; };
+};
+
+#endif /* INCLUDED_DIGITAL_CPMMOD_BC_H */
+
diff --git a/gr-digital/hier/digital_cpmmod_bc.i b/gr-digital/hier/digital_cpmmod_bc.i
new file mode 100644
index 000000000..fa7c50da7
--- /dev/null
+++ b/gr-digital/hier/digital_cpmmod_bc.i
@@ -0,0 +1,40 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2010 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.
+ */
+
+GR_SWIG_BLOCK_MAGIC(digital, cpmmod_bc)
+
+digital_cpmmod_bc_sptr
+digital_make_cpmmod_bc(int type, float h,
+ unsigned samples_per_sym,
+ unsigned L, double beta=0.3);
+
+class digital_cpmmod_bc : public gr_hier_block2
+{
+ private:
+ digital_cpmmod_bc(int type, float h,
+ unsigned samples_per_sym,
+ unsigned L, double beta);
+
+ public:
+ std::vector<float> get_taps();
+};
+
diff --git a/gr-digital/hier/digital_gmskmod_bc.cc b/gr-digital/hier/digital_gmskmod_bc.cc
new file mode 100644
index 000000000..e53e90037
--- /dev/null
+++ b/gr-digital/hier/digital_gmskmod_bc.cc
@@ -0,0 +1,44 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2010 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 <digital_gmskmod_bc.h>
+#include <gr_io_signature.h>
+
+// Shared pointer constructor
+digital_gmskmod_bc_sptr
+digital_make_gmskmod_bc(unsigned samples_per_sym,
+ double bt, unsigned L)
+{
+ return gnuradio::get_initial_sptr(new digital_gmskmod_bc(samples_per_sym, bt, L));
+}
+
+
+digital_gmskmod_bc::digital_gmskmod_bc(unsigned samples_per_sym,
+ double bt, unsigned L)
+ : digital_cpmmod_bc(gr_cpm::GAUSSIAN, 0.5, samples_per_sym, L, bt)
+{
+}
+
diff --git a/gr-digital/hier/digital_gmskmod_bc.h b/gr-digital/hier/digital_gmskmod_bc.h
new file mode 100644
index 000000000..33fcc6c12
--- /dev/null
+++ b/gr-digital/hier/digital_gmskmod_bc.h
@@ -0,0 +1,62 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2010 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_DIGITAL_GMSKMOD_BC_H
+#define INCLUDED_DIGITAL_GMSKMOD_BC_H
+
+#include <digital_api.h>
+#include <digital_cpmmod_bc.h>
+
+class digital_gmskmod_bc;
+typedef boost::shared_ptr<digital_gmskmod_bc> digital_gmskmod_bc_sptr;
+
+
+DIGITAL_API digital_gmskmod_bc_sptr
+digital_make_gmskmod_bc(unsigned samples_per_sym=2,
+ double bt=0.3, unsigned L=4);
+
+/*!
+ * \brief GMSK modulator
+ *
+ * \ingroup modulation_blk
+ *
+ * \param samples_per_sym Samples per symbol.
+ * \param bt The 3 dB time-bandwidth product.
+ * \param L The length of the phase duration in symbols. The Gaussian
+ * pulse is truncated after L symbols.
+ *
+ * The input of this block are symbols from an M-ary alphabet
+ * +/-1, +/-3, ..., +/-(M-1). Usually, M = 2 and therefore, the
+ * valid inputs are +/-1.
+ * The modulator will silently accept any other inputs, though.
+ * The output is the phase-modulated signal.
+ */
+class DIGITAL_API digital_gmskmod_bc : public digital_cpmmod_bc
+{
+ friend DIGITAL_API digital_gmskmod_bc_sptr digital_make_gmskmod_bc(unsigned samples_per_sym,
+ double bt, unsigned L);
+ digital_gmskmod_bc(unsigned samples_per_sym,
+ double bt, unsigned L);
+};
+
+#endif /* INCLUDED_DIGITAL_GMSKMOD_BC_H */
+
diff --git a/gr-digital/hier/digital_gmskmod_bc.i b/gr-digital/hier/digital_gmskmod_bc.i
new file mode 100644
index 000000000..ad7b82237
--- /dev/null
+++ b/gr-digital/hier/digital_gmskmod_bc.i
@@ -0,0 +1,39 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2010 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.
+ */
+
+GR_SWIG_BLOCK_MAGIC(digital, gmskmod_bc)
+
+digital_gmskmod_bc_sptr
+digital_make_gmskmod_bc(unsigned samples_per_sym=2,
+ double bt=0.3, unsigned L=4);
+
+class digital_gmskmod_bc : public gr_hier_block2
+{
+ private:
+ digital_cpmmod_bc(int type, float h,
+ unsigned samples_per_sym,
+ double beta, unsigned L);
+
+ public:
+ std::vector<float> get_taps();
+};
+
diff --git a/gr-digital/lib/Makefile.am b/gr-digital/lib/Makefile.am
index 4a9359fce..ce961ef2e 100644
--- a/gr-digital/lib/Makefile.am
+++ b/gr-digital/lib/Makefile.am
@@ -61,6 +61,7 @@ libgnuradio_digital_la_SOURCES = \
digital_mpsk_receiver_cc.cc
libgnuradio_digital_la_LIBADD = \
- $(GNURADIO_CORE_LA)
+ $(GNURADIO_CORE_LA) \
+ $(abs_top_builddir)/gr-digital/hier/libdigital_hier.la
libgnuradio_digital_la_LDFLAGS = $(NO_UNDEFINED) $(LTVERSIONFLAGS)
diff --git a/gr-digital/lib/digital_constellation.cc b/gr-digital/lib/digital_constellation.cc
index d1f218439..0c100f38e 100644
--- a/gr-digital/lib/digital_constellation.cc
+++ b/gr-digital/lib/digital_constellation.cc
@@ -411,6 +411,20 @@ digital_constellation_qpsk::digital_constellation_qpsk ()
d_constellation[1] = gr_complex(SQRT_TWO, -SQRT_TWO);
d_constellation[2] = gr_complex(-SQRT_TWO, SQRT_TWO);
d_constellation[3] = gr_complex(SQRT_TWO, SQRT_TWO);
+
+ /*
+ d_constellation[0] = gr_complex(SQRT_TWO, SQRT_TWO);
+ d_constellation[1] = gr_complex(-SQRT_TWO, SQRT_TWO);
+ d_constellation[2] = gr_complex(SQRT_TWO, -SQRT_TWO);
+ d_constellation[3] = gr_complex(SQRT_TWO, -SQRT_TWO);
+ */
+
+ d_pre_diff_code.resize(4);
+ d_pre_diff_code[0] = 0x0;
+ d_pre_diff_code[1] = 0x2;
+ d_pre_diff_code[2] = 0x3;
+ d_pre_diff_code[3] = 0x1;
+
d_rotational_symmetry = 4;
d_dimensionality = 1;
calc_arity();
@@ -422,8 +436,80 @@ digital_constellation_qpsk::decision_maker(const gr_complex *sample)
// Real component determines small bit.
// Imag component determines big bit.
return 2*(imag(*sample)>0) + (real(*sample)>0);
+
+ /*
+ bool a = real(*sample) > 0;
+ bool b = imag(*sample) > 0;
+ if(a) {
+ if(b)
+ return 0x0;
+ else
+ return 0x1;
+ }
+ else {
+ if(b)
+ return 0x2;
+ else
+ return 0x3;
+ }
+ */
+}
+
+
+/********************************************************************/
+
+
+digital_constellation_dqpsk_sptr
+digital_make_constellation_dqpsk()
+{
+ return digital_constellation_dqpsk_sptr(new digital_constellation_dqpsk ());
}
+digital_constellation_dqpsk::digital_constellation_dqpsk ()
+{
+ // This constellation is not gray coded, which allows
+ // us to use differential encodings (through gr_diff_encode and
+ // gr_diff_decode) on the symbols.
+ d_constellation.resize(4);
+ d_constellation[0] = gr_complex(+SQRT_TWO, +SQRT_TWO);
+ d_constellation[1] = gr_complex(-SQRT_TWO, +SQRT_TWO);
+ d_constellation[2] = gr_complex(-SQRT_TWO, -SQRT_TWO);
+ d_constellation[3] = gr_complex(+SQRT_TWO, -SQRT_TWO);
+
+ // Use this mapping to convert to gray code before diff enc.
+ d_pre_diff_code.resize(4);
+ d_pre_diff_code[0] = 0x0;
+ d_pre_diff_code[1] = 0x1;
+ d_pre_diff_code[2] = 0x3;
+ d_pre_diff_code[3] = 0x2;
+ d_apply_pre_diff_code = true;
+
+ d_rotational_symmetry = 4;
+ d_dimensionality = 1;
+ calc_arity();
+}
+
+unsigned int
+digital_constellation_dqpsk::decision_maker(const gr_complex *sample)
+{
+ // Slower deicison maker as we can't slice along one axis.
+ // Maybe there's a better way to do this, still.
+
+ bool a = real(*sample) > 0;
+ bool b = imag(*sample) > 0;
+ if(a) {
+ if(b)
+ return 0x0;
+ else
+ return 0x3;
+ }
+ else {
+ if(b)
+ return 0x1;
+ else
+ return 0x2;
+ }
+}
digital_constellation_8psk_sptr
digital_make_constellation_8psk()
diff --git a/gr-digital/lib/digital_constellation.h b/gr-digital/lib/digital_constellation.h
index df00f3898..9b2a58588 100644
--- a/gr-digital/lib/digital_constellation.h
+++ b/gr-digital/lib/digital_constellation.h
@@ -42,8 +42,10 @@ typedef boost::shared_ptr<digital_constellation> digital_constellation_sptr;
class DIGITAL_API digital_constellation : public boost::enable_shared_from_this<digital_constellation>
{
public:
- digital_constellation (std::vector<gr_complex> constellation, std::vector<unsigned int> pre_diff_code,
- unsigned int rotational_symmetry, unsigned int dimensionality);
+ digital_constellation (std::vector<gr_complex> constellation,
+ std::vector<unsigned int> pre_diff_code,
+ unsigned int rotational_symmetry,
+ unsigned int dimensionality);
digital_constellation ();
//! Returns the constellation points for a symbol value
@@ -74,6 +76,8 @@ public:
std::vector<std::vector<gr_complex> > v_points();
//! Whether to apply an encoding before doing differential encoding. (e.g. gray coding)
bool apply_pre_diff_code() { return d_apply_pre_diff_code;}
+ //! Whether to apply an encoding before doing differential encoding. (e.g. gray coding)
+ void set_pre_diff_code(bool a) { d_apply_pre_diff_code = a;}
//! Returns the encoding to apply before differential encoding.
std::vector<unsigned int> pre_diff_code() { return d_pre_diff_code;}
//! Returns the order of rotational symmetry.
@@ -82,7 +86,7 @@ public:
unsigned int dimensionality() {return d_dimensionality;}
unsigned int bits_per_symbol () {
- return floor(log(double(d_constellation.size()))/d_dimensionality/log(2.0));
+ return floor(log(d_constellation.size())/d_dimensionality/log(2));
}
unsigned int arity () {
@@ -120,17 +124,19 @@ typedef boost::shared_ptr<digital_constellation_calcdist> digital_constellation_
// public constructor
DIGITAL_API digital_constellation_calcdist_sptr
-digital_make_constellation_calcdist (std::vector<gr_complex> constellation, std::vector<unsigned int> pre_diff_code,
- unsigned int rotational_symmetry, unsigned int dimensionality);
+digital_make_constellation_calcdist (std::vector<gr_complex> constellation,
+ std::vector<unsigned int> pre_diff_code,
+ unsigned int rotational_symmetry,
+ unsigned int dimensionality);
class DIGITAL_API digital_constellation_calcdist : public digital_constellation
{
public:
digital_constellation_calcdist (std::vector<gr_complex> constellation,
- std::vector<unsigned int> pre_diff_code,
- unsigned int rotational_symmetry,
- unsigned int dimensionality);
+ std::vector<unsigned int> pre_diff_code,
+ unsigned int rotational_symmetry,
+ unsigned int dimensionality);
unsigned int decision_maker (const gr_complex *sample);
// void calc_metric(gr_complex *sample, float *metric, trellis_metric_type_t type);
// void calc_euclidean_metric(gr_complex *sample, float *metric);
@@ -155,10 +161,10 @@ class DIGITAL_API digital_constellation_sector : public digital_constellation
public:
digital_constellation_sector (std::vector<gr_complex> constellation,
- std::vector<unsigned int> pre_diff_code,
- unsigned int rotational_symmetry,
- unsigned int dimensionality,
- unsigned int n_sectors);
+ std::vector<unsigned int> pre_diff_code,
+ unsigned int rotational_symmetry,
+ unsigned int dimensionality,
+ unsigned int n_sectors);
unsigned int decision_maker (const gr_complex *sample);
@@ -194,19 +200,25 @@ typedef boost::shared_ptr<digital_constellation_rect> digital_constellation_rect
// public constructor
DIGITAL_API digital_constellation_rect_sptr
-digital_make_constellation_rect (std::vector<gr_complex> constellation, std::vector<unsigned int> pre_diff_code,
- unsigned int rotational_symmetry,
- unsigned int real_sectors, unsigned int imag_sectors,
- float width_real_sectors, float width_imag_sectors);
+digital_make_constellation_rect (std::vector<gr_complex> constellation,
+ std::vector<unsigned int> pre_diff_code,
+ unsigned int rotational_symmetry,
+ unsigned int real_sectors,
+ unsigned int imag_sectors,
+ float width_real_sectors,
+ float width_imag_sectors);
class DIGITAL_API digital_constellation_rect : public digital_constellation_sector
{
public:
- digital_constellation_rect (std::vector<gr_complex> constellation, std::vector<unsigned int> pre_diff_code,
- unsigned int rotational_symmetry,
- unsigned int real_sectors, unsigned int imag_sectors,
- float width_real_sectors, float width_imag_sectors);
+ digital_constellation_rect (std::vector<gr_complex> constellation,
+ std::vector<unsigned int> pre_diff_code,
+ unsigned int rotational_symmetry,
+ unsigned int real_sectors,
+ unsigned int imag_sectors,
+ float width_real_sectors,
+ float width_imag_sectors);
protected:
@@ -222,10 +234,13 @@ class DIGITAL_API digital_constellation_rect : public digital_constellation_sect
float d_width_imag_sectors;
friend DIGITAL_API digital_constellation_rect_sptr
- digital_make_constellation_rect (std::vector<gr_complex> constellation, std::vector<unsigned int> pre_diff_code,
- unsigned int rotational_symmetry,
- unsigned int real_sectors, unsigned int imag_sectors,
- float width_real_sectors, float width_imag_sectors);
+ digital_make_constellation_rect (std::vector<gr_complex> constellation,
+ std::vector<unsigned int> pre_diff_code,
+ unsigned int rotational_symmetry,
+ unsigned int real_sectors,
+ unsigned int imag_sectors,
+ float width_real_sectors,
+ float width_imag_sectors);
};
@@ -323,6 +338,33 @@ class DIGITAL_API digital_constellation_qpsk : public digital_constellation
};
+/************************************************************/
+/* digital_constellation_dqpsk */
+/* */
+/* Works with differential encoding; slower decisions. */
+/* */
+/************************************************************/
+
+//! \brief DQPSK-specific constellation and decision maker
+class digital_constellation_dqpsk;
+typedef boost::shared_ptr<digital_constellation_dqpsk> digital_constellation_dqpsk_sptr;
+
+// public constructor
+DIGITAL_API digital_constellation_dqpsk_sptr
+digital_make_constellation_dqpsk ();
+
+class DIGITAL_API digital_constellation_dqpsk : public digital_constellation
+{
+ public:
+
+ digital_constellation_dqpsk ();
+ unsigned int decision_maker (const gr_complex *sample);
+
+ friend DIGITAL_API digital_constellation_dqpsk_sptr
+ digital_make_constellation_dqpsk ();
+
+};
+
/************************************************************/
/* digital_constellation_8psk */
diff --git a/gr-digital/lib/digital_constellation_receiver_cb.cc b/gr-digital/lib/digital_constellation_receiver_cb.cc
index e2b6bf1d8..b9239962a 100644
--- a/gr-digital/lib/digital_constellation_receiver_cb.cc
+++ b/gr-digital/lib/digital_constellation_receiver_cb.cc
@@ -54,153 +54,20 @@ digital_constellation_receiver_cb::digital_constellation_receiver_cb (digital_co
: gr_block ("constellation_receiver_cb",
gr_make_io_signature (1, 1, sizeof (gr_complex)),
gr_make_io_signaturev (1, 4, iosig)),
- d_freq(0), d_max_freq(fmax), d_min_freq(fmin), d_phase(0),
+ gri_control_loop(loop_bw, fmax, fmin),
d_constellation(constellation),
d_current_const_point(0)
{
if (d_constellation->dimensionality() != 1)
throw std::runtime_error ("This receiver only works with constellations of dimension 1.");
-
- // Set the damping factor for a critically damped system
- d_damping = sqrtf(2.0f)/2.0f;
-
- // Set the bandwidth, which will then call update_gains()
- set_loop_bandwidth(loop_bw);
-}
-
-
-/*******************************************************************
- SET FUNCTIONS
-*******************************************************************/
-
-void
-digital_constellation_receiver_cb::set_loop_bandwidth(float bw)
-{
- if(bw < 0) {
- throw std::out_of_range ("digital_constellation_receiver_cb: invalid bandwidth. Must be >= 0.");
- }
-
- d_loop_bw = bw;
- update_gains();
-}
-
-void
-digital_constellation_receiver_cb::set_damping_factor(float df)
-{
- if(df < 0 || df > 1.0) {
- throw std::out_of_range ("digital_constellation_receiver_cb: invalid damping factor. Must be in [0,1].");
- }
-
- d_damping = df;
- update_gains();
-}
-
-void
-digital_constellation_receiver_cb::set_alpha(float alpha)
-{
- if(alpha < 0 || alpha > 1.0) {
- throw std::out_of_range ("digital_constellation_receiver_cb: invalid alpha. Must be in [0,1].");
- }
- d_alpha = alpha;
-}
-
-void
-digital_constellation_receiver_cb::set_beta(float beta)
-{
- if(beta < 0 || beta > 1.0) {
- throw std::out_of_range ("digital_constellation_receiver_cb: invalid beta. Must be in [0,1].");
- }
- d_beta = beta;
-}
-
-void
-digital_constellation_receiver_cb::set_frequency(float freq)
-{
- if(freq > d_max_freq)
- d_freq = d_min_freq;
- else if(freq < d_min_freq)
- d_freq = d_max_freq;
- else
- d_freq = freq;
-}
-
-void
-digital_constellation_receiver_cb::set_phase(float phase)
-{
- d_phase = phase;
- while(d_phase>M_TWOPI)
- d_phase -= M_TWOPI;
- while(d_phase<-M_TWOPI)
- d_phase += M_TWOPI;
-}
-
-
-/*******************************************************************
- GET FUNCTIONS
-*******************************************************************/
-
-
-float
-digital_constellation_receiver_cb::get_loop_bandwidth() const
-{
- return d_loop_bw;
-}
-
-float
-digital_constellation_receiver_cb::get_damping_factor() const
-{
- return d_damping;
-}
-
-float
-digital_constellation_receiver_cb::get_alpha() const
-{
- return d_alpha;
-}
-
-float
-digital_constellation_receiver_cb::get_beta() const
-{
- return d_beta;
-}
-
-float
-digital_constellation_receiver_cb::get_frequency() const
-{
- return d_freq;
-}
-
-float
-digital_constellation_receiver_cb::get_phase() const
-{
- return d_phase;
-}
-
-/*******************************************************************
-*******************************************************************/
-
-void
-digital_constellation_receiver_cb::update_gains()
-{
- float denom = (1.0 + 2.0*d_damping*d_loop_bw + d_loop_bw*d_loop_bw);
- d_alpha = (4*d_damping*d_loop_bw) / denom;
- d_beta = (4*d_loop_bw*d_loop_bw) / denom;
}
void
digital_constellation_receiver_cb::phase_error_tracking(float phase_error)
{
- d_freq += d_beta*phase_error; // adjust frequency based on error
- d_phase += d_freq + d_alpha*phase_error; // adjust phase based on error
-
- // Make sure we stay within +-2pi
- while(d_phase > M_TWOPI)
- d_phase -= M_TWOPI;
- while(d_phase < -M_TWOPI)
- d_phase += M_TWOPI;
-
- // Limit the frequency range
- d_freq = gr_branchless_clip(d_freq, d_max_freq);
+ advance_loop(phase_error);
+ phase_wrap();
+ frequency_limit();
#if VERBOSE_COSTAS
printf("cl: phase_error: %f phase: %f freq: %f sample: %f+j%f constellation: %f+j%f\n",
@@ -236,10 +103,12 @@ digital_constellation_receiver_cb::general_work (int noutput_items,
sample = in[i];
nco = gr_expj(d_phase); // get the NCO value for derotating the current sample
sample = nco*sample; // get the downconverted symbol
+
sym_value = d_constellation->decision_maker_pe(&sample, &phase_error);
- // phase_error = -arg(sample*conj(d_constellation->points()[sym_value]));
phase_error_tracking(phase_error); // corrects phase and frequency offsets
+
out[i] = sym_value;
+
if(output_items.size() == 4) {
out_err[i] = phase_error;
out_phase[i] = d_phase;
diff --git a/gr-digital/lib/digital_constellation_receiver_cb.h b/gr-digital/lib/digital_constellation_receiver_cb.h
index 5e414dfed..d33be8958 100644
--- a/gr-digital/lib/digital_constellation_receiver_cb.h
+++ b/gr-digital/lib/digital_constellation_receiver_cb.h
@@ -26,6 +26,7 @@
#include <digital_api.h>
#include <gr_block.h>
#include <digital_constellation.h>
+#include <gri_control_loop.h>
#include <gr_complex.h>
#include <math.h>
#include <fstream>
@@ -64,134 +65,14 @@ digital_make_constellation_receiver_cb (digital_constellation_sptr constellation
*
*/
-class DIGITAL_API digital_constellation_receiver_cb : public gr_block
+class DIGITAL_API digital_constellation_receiver_cb : public gr_block, public gri_control_loop
{
- public:
+public:
int general_work (int noutput_items,
gr_vector_int &ninput_items,
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items);
-
- /*******************************************************************
- SET FUNCTIONS
- *******************************************************************/
-
- /*!
- * \brief Set the loop bandwidth
- *
- * Set the loop filter's bandwidth to \p bw. This should be between
- * 2*pi/200 and 2*pi/100 (in rads/samp). It must also be a positive
- * number.
- *
- * When a new damping factor is set, the gains, alpha and beta, of the loop
- * are recalculated by a call to update_gains().
- *
- * \param bw (float) new bandwidth
- *
- */
- void set_loop_bandwidth(float bw);
-
- /*!
- * \brief Set the loop damping factor
- *
- * Set the loop filter's damping factor to \p df. The damping factor
- * should be sqrt(2)/2.0 for critically damped systems.
- * Set it to anything else only if you know what you are doing. It must
- * be a number between 0 and 1.
- *
- * When a new damping factor is set, the gains, alpha and beta, of the loop
- * are recalculated by a call to update_gains().
- *
- * \param df (float) new damping factor
- *
- */
- void set_damping_factor(float df);
-
- /*!
- * \brief Set the loop gain alpha
- *
- * Set's the loop filter's alpha gain parameter.
- *
- * This value should really only be set by adjusting the loop bandwidth
- * and damping factor.
- *
- * \param alpha (float) new alpha gain
- *
- */
- void set_alpha(float alpha);
-
- /*!
- * \brief Set the loop gain beta
- *
- * Set's the loop filter's beta gain parameter.
- *
- * This value should really only be set by adjusting the loop bandwidth
- * and damping factor.
- *
- * \param beta (float) new beta gain
- *
- */
- void set_beta(float beta);
-
- /*!
- * \brief Set the phase/freq recovery loop's frequency.
- *
- * Set's the phase/freq recovery loop's frequency. While this is normally
- * updated by the inner loop of the algorithm, it could be useful to
- * manually initialize, set, or reset this under certain circumstances.
- *
- * \param freq (float) new frequency
- *
- */
- void set_frequency(float freq);
-
- /*!
- * \brief Set the phase/freq recovery loop's phase.
- *
- * Set's the phase/freq recovery loop's phase. While this is normally
- * updated by the inner loop of the algorithm, it could be useful to
- * manually initialize, set, or reset this under certain circumstances.
- *
- * \param phase (float) new phase
- *
- */
- void set_phase(float phase);
-
- /*******************************************************************
- GET FUNCTIONS
- *******************************************************************/
-
- /*!
- * \brief Returns the loop bandwidth
- */
- float get_loop_bandwidth() const;
-
- /*!
- * \brief Returns the loop damping factor
- */
- float get_damping_factor() const;
-
- /*!
- * \brief Returns the loop gain alpha
- */
- float get_alpha() const;
-
- /*!
- * \brief Returns the loop gain beta
- */
- float get_beta() const;
-
- /*!
- * \brief Get the phase/freq recovery loop's frequency estimate
- */
- float get_frequency() const;
-
- /*!
- * \brief Get the phase/freq loop's phase estimate
- */
- float get_phase() const;
-
protected:
/*!
@@ -211,18 +92,9 @@ protected:
void phase_error_tracking(float phase_error);
- private:
+private:
unsigned int d_M;
- // Members related to carrier and phase tracking
- float d_freq, d_max_freq, d_min_freq;
- float d_phase;
-
- float d_loop_bw;
- float d_damping;
- float d_alpha;
- float d_beta;
-
digital_constellation_sptr d_constellation;
unsigned int d_current_const_point;
@@ -230,20 +102,11 @@ protected:
static const unsigned int DLLEN = 8;
//! delay line plus some length for overflow protection
- __GR_ATTR_ALIGNED(8) gr_complex d_dl[2*DLLEN];
+ gr_complex d_dl[2*DLLEN] __attribute__ ((aligned(8)));
//! index to delay line
unsigned int d_dl_idx;
- /*! \brief update the system gains from the loop bandwidth and damping factor
- *
- * This function updates the system gains based on the loop
- * bandwidth and damping factor of the system.
- * These two factors can be set separately through their own
- * set functions.
- */
- void update_gains();
-
friend DIGITAL_API digital_constellation_receiver_cb_sptr
digital_make_constellation_receiver_cb (digital_constellation_sptr constell,
float loop_bw, float fmin, float fmax);
diff --git a/gr-digital/lib/digital_fll_band_edge_cc.cc b/gr-digital/lib/digital_fll_band_edge_cc.cc
index 70cb54351..05c092622 100644
--- a/gr-digital/lib/digital_fll_band_edge_cc.cc
+++ b/gr-digital/lib/digital_fll_band_edge_cc.cc
@@ -55,6 +55,7 @@ digital_fll_band_edge_cc::digital_fll_band_edge_cc (float samps_per_sym, float r
: gr_sync_block ("fll_band_edge_cc",
gr_make_io_signature (1, 1, sizeof(gr_complex)),
gr_make_io_signaturev (1, 4, iosig)),
+ gri_control_loop(bandwidth, M_TWOPI*(2.0/samps_per_sym), -M_TWOPI*(2.0/samps_per_sym)),
d_updated (false)
{
// Initialize samples per symbol
@@ -75,22 +76,8 @@ digital_fll_band_edge_cc::digital_fll_band_edge_cc (float samps_per_sym, float r
}
d_filter_size = filter_size;
- // base this on the number of samples per symbol
- d_max_freq = M_TWOPI * (2.0/samps_per_sym);
- d_min_freq = -M_TWOPI * (2.0/samps_per_sym);
-
- // Set the damping factor for a critically damped system
- d_damping = sqrtf(2.0f)/2.0f;
-
- // Set the bandwidth, which will then call update_gains()
- set_loop_bandwidth(bandwidth);
-
// Build the band edge filters
design_filter(d_sps, d_rolloff, d_filter_size);
-
- // Initialize loop values
- d_freq = 0;
- d_phase = 0;
}
digital_fll_band_edge_cc::~digital_fll_band_edge_cc ()
@@ -102,47 +89,6 @@ digital_fll_band_edge_cc::~digital_fll_band_edge_cc ()
SET FUNCTIONS
*******************************************************************/
-
-void
-digital_fll_band_edge_cc::set_loop_bandwidth(float bw)
-{
- if(bw < 0) {
- throw std::out_of_range ("digital_fll_band_edge_cc: invalid bandwidth. Must be >= 0.");
- }
-
- d_loop_bw = bw;
- update_gains();
-}
-
-void
-digital_fll_band_edge_cc::set_damping_factor(float df)
-{
- if(df < 0 || df > 1.0) {
- throw std::out_of_range ("digital_fll_band_edge_cc: invalid damping factor. Must be in [0,1].");
- }
-
- d_damping = df;
- update_gains();
-}
-
-void
-digital_fll_band_edge_cc::set_alpha(float alpha)
-{
- if(alpha < 0 || alpha > 1.0) {
- throw std::out_of_range ("digital_fll_band_edge_cc: invalid alpha. Must be in [0,1].");
- }
- d_alpha = alpha;
-}
-
-void
-digital_fll_band_edge_cc::set_beta(float beta)
-{
- if(beta < 0 || beta > 1.0) {
- throw std::out_of_range ("digital_fll_band_edge_cc: invalid beta. Must be in [0,1].");
- }
- d_beta = beta;
-}
-
void
digital_fll_band_edge_cc::set_samples_per_symbol(float sps)
{
@@ -173,57 +119,10 @@ digital_fll_band_edge_cc::set_filter_size(int filter_size)
design_filter(d_sps, d_rolloff, d_filter_size);
}
-void
-digital_fll_band_edge_cc::set_frequency(float freq)
-{
- if(freq > d_max_freq)
- d_freq = d_min_freq;
- else if(freq < d_min_freq)
- d_freq = d_max_freq;
- else
- d_freq = freq;
-}
-
-void
-digital_fll_band_edge_cc::set_phase(float phase)
-{
- d_phase = phase;
- while(d_phase>M_TWOPI)
- d_phase -= M_TWOPI;
- while(d_phase<-M_TWOPI)
- d_phase += M_TWOPI;
-}
-
-
/*******************************************************************
GET FUNCTIONS
*******************************************************************/
-
-float
-digital_fll_band_edge_cc::get_loop_bandwidth() const
-{
- return d_loop_bw;
-}
-
-float
-digital_fll_band_edge_cc::get_damping_factor() const
-{
- return d_damping;
-}
-
-float
-digital_fll_band_edge_cc::get_alpha() const
-{
- return d_alpha;
-}
-
-float
-digital_fll_band_edge_cc::get_beta() const
-{
- return d_beta;
-}
-
float
digital_fll_band_edge_cc::get_samples_per_symbol() const
{
@@ -242,31 +141,10 @@ digital_fll_band_edge_cc:: get_filter_size() const
return d_filter_size;
}
-float
-digital_fll_band_edge_cc::get_frequency() const
-{
- return d_freq;
-}
-
-float
-digital_fll_band_edge_cc::get_phase() const
-{
- return d_phase;
-}
-
/*******************************************************************
*******************************************************************/
-
-void
-digital_fll_band_edge_cc::update_gains()
-{
- float denom = (1.0 + 2.0*d_damping*d_loop_bw + d_loop_bw*d_loop_bw);
- d_alpha = (4*d_damping*d_loop_bw) / denom;
- d_beta = (4*d_loop_bw*d_loop_bw) / denom;
-}
-
void
digital_fll_band_edge_cc::design_filter(float samps_per_sym,
float rolloff, int filter_size)
@@ -366,18 +244,9 @@ digital_fll_band_edge_cc::work (int noutput_items,
}
error = norm(out_lower) - norm(out_upper);
- d_freq = d_freq + d_beta * error;
- d_phase = d_phase + d_freq + d_alpha * error;
-
- if(d_phase > M_PI)
- d_phase -= M_TWOPI;
- else if(d_phase < -M_PI)
- d_phase += M_TWOPI;
-
- if (d_freq > d_max_freq)
- d_freq = d_max_freq;
- else if (d_freq < d_min_freq)
- d_freq = d_min_freq;
+ advance_loop(error);
+ phase_wrap();
+ frequency_limit();
if(output_items.size() == 4) {
frq[i] = d_freq;
diff --git a/gr-digital/lib/digital_fll_band_edge_cc.h b/gr-digital/lib/digital_fll_band_edge_cc.h
index c7a56a7c9..6ef8376ac 100644
--- a/gr-digital/lib/digital_fll_band_edge_cc.h
+++ b/gr-digital/lib/digital_fll_band_edge_cc.h
@@ -26,6 +26,7 @@
#include <digital_api.h>
#include <gr_sync_block.h>
+#include <gri_control_loop.h>
class digital_fll_band_edge_cc;
typedef boost::shared_ptr<digital_fll_band_edge_cc> digital_fll_band_edge_cc_sptr;
@@ -40,39 +41,51 @@ DIGITAL_API digital_fll_band_edge_cc_sptr digital_make_fll_band_edge_cc (float s
*
* \ingroup general
*
- * The frequency lock loop derives a band-edge filter that covers the upper and lower bandwidths
- * of a digitally-modulated signal. The bandwidth range is determined by the excess bandwidth
- * (e.g., rolloff factor) of the modulated signal. The placement in frequency of the band-edges
- * is determined by the oversampling ratio (number of samples per symbol) and the excess bandwidth.
- * The size of the filters should be fairly large so as to average over a number of symbols.
+ * The frequency lock loop derives a band-edge filter that covers the
+ * upper and lower bandwidths of a digitally-modulated signal. The
+ * bandwidth range is determined by the excess bandwidth (e.g.,
+ * rolloff factor) of the modulated signal. The placement in frequency
+ * of the band-edges is determined by the oversampling ratio (number
+ * of samples per symbol) and the excess bandwidth. The size of the
+ * filters should be fairly large so as to average over a number of
+ * symbols.
*
- * The FLL works by filtering the upper and lower band edges into x_u(t) and x_l(t), respectively.
- * These are combined to form cc(t) = x_u(t) + x_l(t) and ss(t) = x_u(t) - x_l(t). Combining
- * these to form the signal e(t) = Re{cc(t) \\times ss(t)^*} (where ^* is the complex conjugate)
- * provides an error signal at the DC term that is directly proportional to the carrier frequency.
- * We then make a second-order loop using the error signal that is the running average of e(t).
+ * The FLL works by filtering the upper and lower band edges into
+ * x_u(t) and x_l(t), respectively. These are combined to form cc(t)
+ * = x_u(t) + x_l(t) and ss(t) = x_u(t) - x_l(t). Combining these to
+ * form the signal e(t) = Re{cc(t) \\times ss(t)^*} (where ^* is the
+ * complex conjugate) provides an error signal at the DC term that is
+ * directly proportional to the carrier frequency. We then make a
+ * second-order loop using the error signal that is the running
+ * average of e(t).
*
- * In practice, the above equation can be simplified by just comparing the absolute value squared
- * of the output of both filters: abs(x_l(t))^2 - abs(x_u(t))^2 = norm(x_l(t)) - norm(x_u(t)).
+ * In practice, the above equation can be simplified by just comparing
+ * the absolute value squared of the output of both filters:
+ * abs(x_l(t))^2 - abs(x_u(t))^2 = norm(x_l(t)) - norm(x_u(t)).
*
- * In theory, the band-edge filter is the derivative of the matched filter in frequency,
- * (H_be(f) = \\frac{H(f)}{df}. In practice, this comes down to a quarter sine wave at the point
- * of the matched filter's rolloff (if it's a raised-cosine, the derivative of a cosine is a sine).
- * Extend this sine by another quarter wave to make a half wave around the band-edges is equivalent
- * in time to the sum of two sinc functions. The baseband filter fot the band edges is therefore
- * derived from this sum of sincs. The band edge filters are then just the baseband signal
- * modulated to the correct place in frequency. All of these calculations are done in the
+ * In theory, the band-edge filter is the derivative of the matched
+ * filter in frequency, (H_be(f) = \\frac{H(f)}{df}. In practice, this
+ * comes down to a quarter sine wave at the point of the matched
+ * filter's rolloff (if it's a raised-cosine, the derivative of a
+ * cosine is a sine). Extend this sine by another quarter wave to
+ * make a half wave around the band-edges is equivalent in time to the
+ * sum of two sinc functions. The baseband filter fot the band edges
+ * is therefore derived from this sum of sincs. The band edge filters
+ * are then just the baseband signal modulated to the correct place in
+ * frequency. All of these calculations are done in the
* 'design_filter' function.
*
- * Note: We use FIR filters here because the filters have to have a flat phase response over the
- * entire frequency range to allow their comparisons to be valid.
+ * Note: We use FIR filters here because the filters have to have a
+ * flat phase response over the entire frequency range to allow their
+ * comparisons to be valid.
*
- * It is very important that the band edge filters be the derivatives of the pulse shaping filter,
- * and that they be linear phase. Otherwise, the variance of the error will be very large.
+ * It is very important that the band edge filters be the derivatives
+ * of the pulse shaping filter, and that they be linear
+ * phase. Otherwise, the variance of the error will be very large.
*
*/
-class DIGITAL_API digital_fll_band_edge_cc : public gr_sync_block
+class DIGITAL_API digital_fll_band_edge_cc : public gr_sync_block, public gri_control_loop
{
private:
/*!
@@ -90,21 +103,11 @@ class DIGITAL_API digital_fll_band_edge_cc : public gr_sync_block
float d_sps;
float d_rolloff;
int d_filter_size;
- float d_max_freq;
- float d_min_freq;
-
- float d_loop_bw;
- float d_damping;
- float d_alpha;
- float d_beta;
std::vector<gr_complex> d_taps_lower;
std::vector<gr_complex> d_taps_upper;
bool d_updated;
- float d_freq;
- float d_phase;
-
/*!
* Build the FLL
* \param samps_per_sym (float) number of samples per symbol
@@ -116,11 +119,6 @@ class DIGITAL_API digital_fll_band_edge_cc : public gr_sync_block
int filter_size, float bandwidth);
/*!
- * \brief Update the gains, alpha and beta, of the loop filter.
- */
- void update_gains();
-
- /*!
* Design the band-edge filter based on the number of samples per symbol,
* filter rolloff factor, and the filter size
*
@@ -138,67 +136,11 @@ public:
*******************************************************************/
/*!
- * \brief Set the loop bandwidth
- *
- * Set the loop filter's bandwidth to \p bw. This should be between
- * 2*pi/200 and 2*pi/100 (in rads/samp). It must also be a positive
- * number.
- *
- * When a new damping factor is set, the gains, alpha and beta, of the loop
- * are recalculated by a call to update_gains().
- *
- * \param bw (float) new bandwidth
- *
- */
- void set_loop_bandwidth(float bw);
-
- /*!
- * \brief Set the loop damping factor
- *
- * Set the loop filter's damping factor to \p df. The damping factor
- * should be sqrt(2)/2.0 for critically damped systems.
- * Set it to anything else only if you know what you are doing. It must
- * be a number between 0 and 1.
- *
- * When a new damping factor is set, the gains, alpha and beta, of the loop
- * are recalculated by a call to update_gains().
- *
- * \param df (float) new damping factor
- *
- */
- void set_damping_factor(float df);
-
- /*!
- * \brief Set the loop gain alpha
- *
- * Set's the loop filter's alpha gain parameter.
- *
- * This value should really only be set by adjusting the loop bandwidth
- * and damping factor.
- *
- * \param alpha (float) new alpha gain
- *
- */
- void set_alpha(float alpha);
-
- /*!
- * \brief Set the loop gain beta
- *
- * Set's the loop filter's beta gain parameter.
- *
- * This value should really only be set by adjusting the loop bandwidth
- * and damping factor.
- *
- * \param beta (float) new beta gain
- *
- */
- void set_beta(float beta);
-
- /*!
* \brief Set the number of samples per symbol
*
- * Set's the number of samples per symbol the system should use. This value
- * is uesd to calculate the filter taps and will force a recalculation.
+ * Set's the number of samples per symbol the system should
+ * use. This value is uesd to calculate the filter taps and will
+ * force a recalculation.
*
* \param sps (float) new samples per symbol
*
@@ -208,13 +150,14 @@ public:
/*!
* \brief Set the rolloff factor of the shaping filter
*
- * This sets the rolloff factor that is used in the pulse shaping filter
- * and is used to calculate the filter taps. Changing this will force a
- * recalculation of the filter taps.
+ * This sets the rolloff factor that is used in the pulse shaping
+ * filter and is used to calculate the filter taps. Changing this
+ * will force a recalculation of the filter taps.
*
- * This should be the same value that is used in the transmitter's pulse
- * shaping filter. It must be between 0 and 1 and is usually between
- * 0.2 and 0.5 (where 0.22 and 0.35 are commonly used values).
+ * This should be the same value that is used in the transmitter's
+ * pulse shaping filter. It must be between 0 and 1 and is usually
+ * between 0.2 and 0.5 (where 0.22 and 0.35 are commonly used
+ * values).
*
* \param rolloff (float) new shaping filter rolloff factor [0,1]
*
@@ -224,68 +167,25 @@ public:
/*!
* \brief Set the number of taps in the filter
*
- * This sets the number of taps in the band-edge filters. Setting this will
- * force a recalculation of the filter taps.
+ * This sets the number of taps in the band-edge filters. Setting
+ * this will force a recalculation of the filter taps.
*
- * This should be about the same number of taps used in the transmitter's
- * shaping filter and also not very large. A large number of taps will
- * result in a large delay between input and frequency estimation, and
- * so will not be as accurate. Between 30 and 70 taps is usual.
+ * This should be about the same number of taps used in the
+ * transmitter's shaping filter and also not very large. A large
+ * number of taps will result in a large delay between input and
+ * frequency estimation, and so will not be as accurate. Between 30
+ * and 70 taps is usual.
*
* \param filter_size (float) number of taps in the filters
*
*/
void set_filter_size(int filter_size);
- /*!
- * \brief Set the FLL's frequency.
- *
- * Set's the FLL's frequency. While this is normally updated by the
- * inner loop of the algorithm, it could be useful to manually initialize,
- * set, or reset this under certain circumstances.
- *
- * \param freq (float) new frequency
- *
- */
- void set_frequency(float freq);
-
- /*!
- * \brief Set the FLL's phase.
- *
- * Set's the FLL's phase. While this is normally updated by the
- * inner loop of the algorithm, it could be useful to manually initialize,
- * set, or reset this under certain circumstances.
- *
- * \param phase (float) new phase
- *
- */
- void set_phase(float phase);
-
/*******************************************************************
GET FUNCTIONS
*******************************************************************/
/*!
- * \brief Returns the loop bandwidth
- */
- float get_loop_bandwidth() const;
-
- /*!
- * \brief Returns the loop damping factor
- */
- float get_damping_factor() const;
-
- /*!
- * \brief Returns the loop gain alpha
- */
- float get_alpha() const;
-
- /*!
- * \brief Returns the loop gain beta
- */
- float get_beta() const;
-
- /*!
* \brief Returns the number of sampler per symbol used for the filter
*/
float get_samples_per_symbol() const;
@@ -301,16 +201,6 @@ public:
int get_filter_size() const;
/*!
- * \brief Get the FLL's frequency estimate
- */
- float get_frequency() const;
-
- /*!
- * \brief Get the FLL's phase estimate
- */
- float get_phase() const;
-
- /*!
* Print the taps to screen.
*/
void print_taps();
diff --git a/gr-digital/lib/digital_mpsk_receiver_cc.cc b/gr-digital/lib/digital_mpsk_receiver_cc.cc
index 3b2ea9840..363b86c9f 100644
--- a/gr-digital/lib/digital_mpsk_receiver_cc.cc
+++ b/gr-digital/lib/digital_mpsk_receiver_cc.cc
@@ -41,28 +41,30 @@
digital_mpsk_receiver_cc_sptr
digital_make_mpsk_receiver_cc(unsigned int M, float theta,
- float alpha, float beta,
+ float loop_bw,
float fmin, float fmax,
float mu, float gain_mu,
float omega, float gain_omega, float omega_rel)
{
return gnuradio::get_initial_sptr(new digital_mpsk_receiver_cc (M, theta,
- alpha, beta,
- fmin, fmax,
- mu, gain_mu,
- omega, gain_omega, omega_rel));
+ loop_bw,
+ fmin, fmax,
+ mu, gain_mu,
+ omega, gain_omega,
+ omega_rel));
}
digital_mpsk_receiver_cc::digital_mpsk_receiver_cc (unsigned int M, float theta,
- float alpha, float beta,
- float fmin, float fmax,
- float mu, float gain_mu,
- float omega, float gain_omega, float omega_rel)
+ float loop_bw,
+ float fmin, float fmax,
+ float mu, float gain_mu,
+ float omega, float gain_omega,
+ float omega_rel)
: gr_block ("mpsk_receiver_cc",
gr_make_io_signature (1, 1, sizeof (gr_complex)),
gr_make_io_signature (1, 1, sizeof (gr_complex))),
+ gri_control_loop(loop_bw, fmax, fmin),
d_M(M), d_theta(theta),
- d_alpha(alpha), d_beta(beta), d_freq(0), d_max_freq(fmax), d_min_freq(fmin), d_phase(0),
d_current_const_point(0),
d_mu(mu), d_gain_mu(gain_mu), d_gain_omega(gain_omega),
d_omega_rel(omega_rel), d_max_omega(0), d_min_omega(0),
@@ -265,18 +267,10 @@ digital_mpsk_receiver_cc::phase_error_tracking(gr_complex sample)
// Make phase and frequency corrections based on sampled value
phase_error = (*this.*d_phase_error_detector)(sample);
-
- d_freq += d_beta*phase_error; // adjust frequency based on error
- d_phase += d_freq + d_alpha*phase_error; // adjust phase based on error
-
- // Make sure we stay within +-2pi
- while(d_phase > M_TWOPI)
- d_phase -= M_TWOPI;
- while(d_phase < -M_TWOPI)
- d_phase += M_TWOPI;
- // Limit the frequency range
- d_freq = gr_branchless_clip(d_freq, d_max_freq);
+ advance_loop(phase_error);
+ phase_wrap();
+ frequency_limit();
#if VERBOSE_COSTAS
printf("cl: phase_error: %f phase: %f freq: %f sample: %f+j%f constellation: %f+j%f\n",
diff --git a/gr-digital/lib/digital_mpsk_receiver_cc.h b/gr-digital/lib/digital_mpsk_receiver_cc.h
index 8a6352ec7..85cd81e99 100644
--- a/gr-digital/lib/digital_mpsk_receiver_cc.h
+++ b/gr-digital/lib/digital_mpsk_receiver_cc.h
@@ -25,6 +25,7 @@
#include <digital_api.h>
#include <gruel/attributes.h>
+#include <gri_control_loop.h>
#include <gr_block.h>
#include <gr_complex.h>
#include <fstream>
@@ -37,41 +38,48 @@ typedef boost::shared_ptr<digital_mpsk_receiver_cc> digital_mpsk_receiver_cc_spt
// public constructor
DIGITAL_API digital_mpsk_receiver_cc_sptr
digital_make_mpsk_receiver_cc (unsigned int M, float theta,
- float alpha, float beta,
+ float loop_bw,
float fmin, float fmax,
float mu, float gain_mu,
float omega, float gain_omega, float omega_rel);
/*!
- * \brief This block takes care of receiving M-PSK modulated signals through phase, frequency, and symbol
- * synchronization.
+ * \brief This block takes care of receiving M-PSK modulated signals
+ * through phase, frequency, and symbol synchronization.
* \ingroup sync_blk
* \ingroup demod_blk
*
- * This block takes care of receiving M-PSK modulated signals through phase, frequency, and symbol
- * synchronization. It performs carrier frequency and phase locking as well as symbol timing recovery.
- * It works with (D)BPSK, (D)QPSK, and (D)8PSK as tested currently. It should also work for OQPSK and
- * PI/4 DQPSK.
+ * This block takes care of receiving M-PSK modulated signals through
+ * phase, frequency, and symbol synchronization. It performs carrier
+ * frequency and phase locking as well as symbol timing recovery. It
+ * works with (D)BPSK, (D)QPSK, and (D)8PSK as tested currently. It
+ * should also work for OQPSK and PI/4 DQPSK.
*
- * The phase and frequency synchronization are based on a Costas loop that finds the error of the incoming
- * signal point compared to its nearest constellation point. The frequency and phase of the NCO are
- * updated according to this error. There are optimized phase error detectors for BPSK and QPSK, but 8PSK
- * is done using a brute-force computation of the constellation points to find the minimum.
+ * The phase and frequency synchronization are based on a Costas loop
+ * that finds the error of the incoming signal point compared to its
+ * nearest constellation point. The frequency and phase of the NCO are
+ * updated according to this error. There are optimized phase error
+ * detectors for BPSK and QPSK, but 8PSK is done using a brute-force
+ * computation of the constellation points to find the minimum.
*
- * The symbol synchronization is done using a modified Mueller and Muller circuit from the paper:
+ * The symbol synchronization is done using a modified Mueller and
+ * Muller circuit from the paper:
*
- * G. R. Danesfahani, T.G. Jeans, "Optimisation of modified Mueller and Muller
- * algorithm," Electronics Letters, Vol. 31, no. 13, 22 June 1995, pp. 1032 - 1033.
+ * G. R. Danesfahani, T.G. Jeans, "Optimisation of modified Mueller
+ * and Muller algorithm," Electronics Letters, Vol. 31, no. 13, 22
+ * June 1995, pp. 1032 - 1033.
*
- * This circuit interpolates the downconverted sample (using the NCO developed by the Costas loop)
- * every mu samples, then it finds the sampling error based on this and the past symbols and the decision
- * made on the samples. Like the phase error detector, there are optimized decision algorithms for BPSK
- * and QPKS, but 8PSK uses another brute force computation against all possible symbols. The modifications
- * to the M&M used here reduce self-noise.
+ * This circuit interpolates the downconverted sample (using the NCO
+ * developed by the Costas loop) every mu samples, then it finds the
+ * sampling error based on this and the past symbols and the decision
+ * made on the samples. Like the phase error detector, there are
+ * optimized decision algorithms for BPSK and QPKS, but 8PSK uses
+ * another brute force computation against all possible symbols. The
+ * modifications to the M&M used here reduce self-noise.
*
*/
-class DIGITAL_API digital_mpsk_receiver_cc : public gr_block
+class DIGITAL_API digital_mpsk_receiver_cc : public gr_block, public gri_control_loop
{
public:
~digital_mpsk_receiver_cc ();
@@ -112,43 +120,14 @@ class DIGITAL_API digital_mpsk_receiver_cc : public gr_block
//! (M&M) Sets value for omega gain factor
void set_gain_omega (float gain_omega) { d_gain_omega = gain_omega; }
-
-
- // Member function related to the phase/frequency tracking portion of the receiver
- //! (CL) Returns the value for alpha (the phase gain term)
- float alpha() const { return d_alpha; }
-
- //! (CL) Returns the value of beta (the frequency gain term)
- float beta() const { return d_beta; }
-
- //! (CL) Returns the current value of the frequency of the NCO in the Costas loop
- float freq() const { return d_freq; }
-
- //! (CL) Returns the current value of the phase of the NCO in the Costal loop
- float phase() const { return d_phase; }
-
- //! (CL) Sets the value for alpha (the phase gain term)
- void set_alpha(float alpha) { d_alpha = alpha; }
-
- //! (CL) Setss the value of beta (the frequency gain term)
- void set_beta(float beta) { d_beta = beta; }
-
- //! (CL) Sets the current value of the frequency of the NCO in the Costas loop
- void set_freq(float freq) { d_freq = freq; }
-
- //! (CL) Setss the current value of the phase of the NCO in the Costal loop
- void set_phase(float phase) { d_phase = phase; }
-
-
protected:
-
- /*!
+
+ /*!
* \brief Constructor to synchronize incoming M-PSK symbols
*
* \param M modulation order of the M-PSK modulation
* \param theta any constant phase rotation from the real axis of the constellation
- * \param alpha gain parameter to adjust the phase in the Costas loop (~0.01)
- * \param beta gain parameter to adjust the frequency in the Costas loop (~alpha^2/4)
+ * \param loop_bw Loop bandwidth to set gains of phase/freq tracking loop
* \param fmin minimum normalized frequency value the loop can achieve
* \param fmax maximum normalized frequency value the loop can achieve
* \param mu initial parameter for the interpolator [0,1]
@@ -161,7 +140,7 @@ protected:
* value of M.
*/
digital_mpsk_receiver_cc (unsigned int M, float theta,
- float alpha, float beta,
+ float loop_bw,
float fmin, float fmax,
float mu, float gain_mu,
float omega, float gain_omega, float omega_rel);
@@ -172,54 +151,61 @@ protected:
void phase_error_tracking(gr_complex sample);
-/*!
+ /*!
* \brief Phase error detector for MPSK modulations.
*
* \param sample the I&Q sample from which to determine the phase error
*
- * This function determines the phase error for any MPSK signal by creating a set of PSK constellation points
- * and doing a brute-force search to see which point minimizes the Euclidean distance. This point is then used
- * to derotate the sample to the real-axis and a atan (using the fast approximation function) to determine the
- * phase difference between the incoming sample and the real constellation point
+ * This function determines the phase error for any MPSK signal by
+ * creating a set of PSK constellation points and doing a
+ * brute-force search to see which point minimizes the Euclidean
+ * distance. This point is then used to derotate the sample to the
+ * real-axis and a atan (using the fast approximation function) to
+ * determine the phase difference between the incoming sample and
+ * the real constellation point
*
* This should be cleaned up and made more efficient.
*
* \returns the approximated phase error.
- */
+ */
float phase_error_detector_generic(gr_complex sample) const; // generic for M but more costly
- /*!
+ /*!
* \brief Phase error detector for BPSK modulation.
*
* \param sample the I&Q sample from which to determine the phase error
*
- * This function determines the phase error using a simple BPSK phase error detector by multiplying the real
- * and imaginary (the error signal) components together. As the imaginary part goes to 0, so does this error.
+ * This function determines the phase error using a simple BPSK
+ * phase error detector by multiplying the real and imaginary (the
+ * error signal) components together. As the imaginary part goes to
+ * 0, so does this error.
*
* \returns the approximated phase error.
- */
+ */
float phase_error_detector_bpsk(gr_complex sample) const; // optimized for BPSK
- /*!
+ /*!
* \brief Phase error detector for QPSK modulation.
*
* \param sample the I&Q sample from which to determine the phase error
*
- * This function determines the phase error using the limiter approach in a standard 4th order Costas loop
+ * This function determines the phase error using the limiter
+ * approach in a standard 4th order Costas loop
*
* \returns the approximated phase error.
- */
+ */
float phase_error_detector_qpsk(gr_complex sample) const;
- /*!
+ /*!
* \brief Decision maker for a generic MPSK constellation.
*
* \param sample the baseband I&Q sample from which to make the decision
*
- * This decision maker is a generic implementation that does a brute-force search
- * for the constellation point that minimizes the error between it and the incoming signal.
+ * This decision maker is a generic implementation that does a
+ * brute-force search for the constellation point that minimizes the
+ * error between it and the incoming signal.
*
* \returns the index to d_constellation that minimizes the error/
*/
@@ -231,46 +217,44 @@ protected:
*
* \param sample the baseband I&Q sample from which to make the decision
*
- * This decision maker is a simple slicer function that makes a decision on the symbol based on its
- * placement on the real axis of greater than 0 or less than 0; the quadrature component is always 0.
+ * This decision maker is a simple slicer function that makes a
+ * decision on the symbol based on its placement on the real axis of
+ * greater than 0 or less than 0; the quadrature component is always
+ * 0.
*
* \returns the index to d_constellation that minimizes the error/
- */
+ */
unsigned int decision_bpsk(gr_complex sample) const;
- /*!
+ /*!
* \brief Decision maker for QPSK constellation.
*
* \param sample the baseband I&Q sample from which to make the decision
*
- * This decision maker is a simple slicer function that makes a decision on the symbol based on its
- * placement versus both axes and returns which quadrant the symbol is in.
+ * This decision maker is a simple slicer function that makes a
+ * decision on the symbol based on its placement versus both axes
+ * and returns which quadrant the symbol is in.
*
* \returns the index to d_constellation that minimizes the error/
- */
+ */
unsigned int decision_qpsk(gr_complex sample) const;
- private:
+private:
unsigned int d_M;
float d_theta;
- // Members related to carrier and phase tracking
- float d_alpha;
- float d_beta;
- float d_freq, d_max_freq, d_min_freq;
- float d_phase;
-
-/*!
+ /*!
* \brief Decision maker function pointer
*
* \param sample the baseband I&Q sample from which to make the decision
*
- * This is a function pointer that is set in the constructor to point to the proper decision function
- * for the specified constellation order.
+ * This is a function pointer that is set in the constructor to
+ * point to the proper decision function for the specified
+ * constellation order.
*
* \return index into d_constellation point that is the closest to the recieved sample
- */
+ */
unsigned int (digital_mpsk_receiver_cc::*d_decision)(gr_complex sample) const; // pointer to decision function
@@ -283,14 +267,15 @@ protected:
gr_complex d_p_2T, d_p_1T, d_p_0T;
gr_complex d_c_2T, d_c_1T, d_c_0T;
- /*!
+ /*!
* \brief Phase error detector function pointer
*
* \param sample the I&Q sample from which to determine the phase error
*
- * This is a function pointer that is set in the constructor to point to the proper phase error detector
- * function for the specified constellation order.
- */
+ * This is a function pointer that is set in the constructor to
+ * point to the proper phase error detector function for the
+ * specified constellation order.
+ */
float (digital_mpsk_receiver_cc::*d_phase_error_detector)(gr_complex sample) const;
@@ -308,7 +293,7 @@ protected:
friend DIGITAL_API digital_mpsk_receiver_cc_sptr
digital_make_mpsk_receiver_cc (unsigned int M, float theta,
- float alpha, float beta,
+ float loop_bw,
float fmin, float fmax,
float mu, float gain_mu,
float omega, float gain_omega, float omega_rel);
diff --git a/gr-digital/python/Makefile.am b/gr-digital/python/Makefile.am
index 6c61002f1..a33e4963d 100644
--- a/gr-digital/python/Makefile.am
+++ b/gr-digital/python/Makefile.am
@@ -35,6 +35,7 @@ noinst_PYTHON = \
qa_binary_slicer_fb.py \
qa_clock_recovery_mm.py \
qa_cma_equalizer.py \
+ qa_cpm.py \
qa_constellation.py \
qa_constellation_receiver.py \
qa_constellation_decoder_cb.py \
diff --git a/gr-digital/python/__init__.py b/gr-digital/python/__init__.py
index 4046f7faf..7173fa09d 100644
--- a/gr-digital/python/__init__.py
+++ b/gr-digital/python/__init__.py
@@ -26,6 +26,7 @@ from psk2 import *
from bpsk import *
from qpsk import *
from qam import *
+from gmsk import *
from pkt import *
from packet_utils import *
from crc import *
diff --git a/gr-digital/python/generic_mod_demod.py b/gr-digital/python/generic_mod_demod.py
index da8e2cfd9..b1986512f 100644
--- a/gr-digital/python/generic_mod_demod.py
+++ b/gr-digital/python/generic_mod_demod.py
@@ -54,7 +54,7 @@ def add_common_options(parser):
Sets options common to both modulator and demodulator.
"""
parser.add_option("-p", "--constellation-points", type="int", default=_def_constellation_points,
- help="set the number of constellation points (must be a power of 2 (power of 4 for QAM) [default=%default]")
+ help="set the number of constellation points (must be a power of 2 for psk, power of 4 for QAM) [default=%default]")
parser.add_option("", "--non-differential", action="store_true",
dest="differential", default=False,
help="do not use differential encoding [default=%default]")
@@ -120,7 +120,7 @@ class generic_mod(gr.hier_block2):
self.bytes2chunks = \
gr.packed_to_unpacked_bb(self.bits_per_symbol(), gr.GR_MSB_FIRST)
- if self._constellation.apply_pre_diff_code():
+ if gray_coded == True:
self.symbol_mapper = gr.map_bb(self._constellation.pre_diff_code())
if differential:
@@ -142,7 +142,7 @@ class generic_mod(gr.hier_block2):
# Connect
blocks = [self, self.bytes2chunks]
- if self._constellation.apply_pre_diff_code():
+ if gray_coded == True:
blocks.append(self.symbol_mapper)
if differential:
blocks.append(self.diffenc)
@@ -211,6 +211,7 @@ class generic_demod(gr.hier_block2):
samples_per_symbol=_def_samples_per_symbol,
differential=_def_differential,
excess_bw=_def_excess_bw,
+ gray_coded=True,
freq_bw=_def_freq_bw,
timing_bw=_def_timing_bw,
phase_bw=_def_phase_bw,
@@ -228,9 +229,11 @@ class generic_demod(gr.hier_block2):
@type samples_per_symbol: float
@param excess_bw: Root-raised cosine filter excess bandwidth
@type excess_bw: float
+ @param gray_coded: turn gray coding on/off
+ @type gray_coded: bool
@param freq_bw: loop filter lock-in bandwidth
@type freq_bw: float
- @param timing_bw: timing recoery loop lock-in bandwidth
+ @param timing_bw: timing recovery loop lock-in bandwidth
@type timing_bw: float
@param phase_bw: phase recovery loop bandwidth
@type phase_bw: float
@@ -265,8 +268,9 @@ class generic_demod(gr.hier_block2):
self.agc = gr.agc2_cc(0.6e-1, 1e-3, 1, 1, 100)
# Frequency correction
+ fll_ntaps = 55
self.freq_recov = digital_swig.fll_band_edge_cc(self._samples_per_symbol, self._excess_bw,
- ntaps, self._freq_bw)
+ fll_ntaps, self._freq_bw)
# symbol timing recovery with RRC data filter
taps = gr.firdes.root_raised_cosine(nfilts, nfilts*self._samples_per_symbol,
@@ -280,12 +284,12 @@ class generic_demod(gr.hier_block2):
self.receiver = digital_swig.constellation_receiver_cb(
self._constellation, self._phase_bw,
fmin, fmax)
-
+
# Do differential decoding based on phase change of symbols
if differential:
self.diffdec = gr.diff_decoder_bb(arity)
- if self._constellation.apply_pre_diff_code():
+ if gray_coded:
self.symbol_mapper = gr.map_bb(
mod_codes.invert_code(self._constellation.pre_diff_code()))
@@ -297,9 +301,10 @@ class generic_demod(gr.hier_block2):
if log:
self._setup_logging()
-
+
# Connect and Initialize base class
- blocks = [self, self.agc, self.freq_recov, self.time_recov, self.receiver]
+ blocks = [self, self.agc, self.freq_recov,
+ self.time_recov, self.receiver]
if differential:
blocks.append(self.diffdec)
if self._constellation.apply_pre_diff_code():
diff --git a/gr-digital/python/gmsk.py b/gr-digital/python/gmsk.py
index 3b6c016a0..ba122821e 100644
--- a/gr-digital/python/gmsk.py
+++ b/gr-digital/python/gmsk.py
@@ -25,7 +25,9 @@
# See gnuradio-examples/python/digital for examples
from gnuradio import gr
-from gnuradio import modulation_utils
+import digital_swig
+import modulation_utils2
+
from math import pi
import numpy
from pprint import pprint
@@ -37,11 +39,9 @@ _def_bt = 0.35
_def_verbose = False
_def_log = False
-_def_gain_mu = None
-_def_mu = 0.5
-_def_freq_error = 0.0
-_def_omega_relative_limit = 0.005
-
+# Symbol timing recovery
+_def_timing_bw = 2*pi/100.0
+_def_timing_max_dev = 1.5
# /////////////////////////////////////////////////////////////////////////////
# GMSK modulator
@@ -79,7 +79,8 @@ class gmsk_mod(gr.hier_block2):
self._bt = bt
if not isinstance(samples_per_symbol, int) or samples_per_symbol < 2:
- raise TypeError, ("samples_per_symbol must be an integer >= 2, is %r" % (samples_per_symbol,))
+ raise TypeError, ("samples_per_symbol must be an integer >= 2, is %r" % \
+ (samples_per_symbol,))
ntaps = 4 * samples_per_symbol # up to 3 bits in filter at once
sensitivity = (pi / 2) / samples_per_symbol # phase change per bit = pi / 2
@@ -128,11 +129,11 @@ class gmsk_mod(gr.hier_block2):
def _setup_logging(self):
print "Modulation logging turned on."
self.connect(self.nrz,
- gr.file_sink(gr.sizeof_float, "nrz.dat"))
+ gr.file_sink(gr.sizeof_float, "tx_gmsk_nrz.32f"))
self.connect(self.gaussian_filter,
- gr.file_sink(gr.sizeof_float, "gaussian_filter.dat"))
+ gr.file_sink(gr.sizeof_float, "tx_gmsk_gaussian_filter.32f"))
self.connect(self.fmmod,
- gr.file_sink(gr.sizeof_gr_complex, "fmmod.dat"))
+ gr.file_sink(gr.sizeof_gr_complex, "tx_gmsk_fmmod.32fc"))
def add_options(parser):
@@ -148,7 +149,7 @@ class gmsk_mod(gr.hier_block2):
"""
Given command line options, create dictionary suitable for passing to __init__
"""
- return modulation_utils.extract_kwargs_from_options(gmsk_mod.__init__,
+ return modulation_utils2.extract_kwargs_from_options(gmsk_mod.__init__,
('self',), options)
extract_kwargs_from_options=staticmethod(extract_kwargs_from_options)
@@ -162,10 +163,8 @@ class gmsk_demod(gr.hier_block2):
def __init__(self,
samples_per_symbol=_def_samples_per_symbol,
- gain_mu=_def_gain_mu,
- mu=_def_mu,
- omega_relative_limit=_def_omega_relative_limit,
- freq_error=_def_freq_error,
+ bt=_def_bt,
+ timing_bw=_def_timing_bw,
verbose=_def_verbose,
log=_def_log):
"""
@@ -177,21 +176,12 @@ class gmsk_demod(gr.hier_block2):
@param samples_per_symbol: samples per baud
@type samples_per_symbol: integer
+ @param timing_bw: timing recovery loop lock-in bandwidth
+ @type timing_bw: float
@param verbose: Print information about modulator?
@type verbose: bool
@param log: Print modualtion data to files?
@type log: bool
-
- Clock recovery parameters. These all have reasonble defaults.
-
- @param gain_mu: controls rate of mu adjustment
- @type gain_mu: float
- @param mu: fractional delay [0.0, 1.0]
- @type mu: float
- @param omega_relative_limit: sets max variation in omega
- @type omega_relative_limit: float, typically 0.000200 (200 ppm)
- @param freq_error: bit rate error as a fraction
- @param float
"""
gr.hier_block2.__init__(self, "gmsk_demod",
@@ -199,33 +189,31 @@ class gmsk_demod(gr.hier_block2):
gr.io_signature(1, 1, gr.sizeof_char)) # Output signature
self._samples_per_symbol = samples_per_symbol
- self._gain_mu = gain_mu
- self._mu = mu
- self._omega_relative_limit = omega_relative_limit
- self._freq_error = freq_error
+ self._bt = bt
+ self._timing_bw = timing_bw
+ self._timing_max_dev= _def_timing_max_dev
if samples_per_symbol < 2:
raise TypeError, "samples_per_symbol >= 2, is %f" % samples_per_symbol
- self._omega = samples_per_symbol*(1+self._freq_error)
-
- if not self._gain_mu:
- self._gain_mu = 0.175
-
- self._gain_omega = .25 * self._gain_mu * self._gain_mu # critically damped
-
# Demodulate FM
sensitivity = (pi / 2) / samples_per_symbol
self.fmdemod = gr.quadrature_demod_cf(1.0 / sensitivity)
# the clock recovery block tracks the symbol clock and resamples as needed.
# the output of the block is a stream of soft symbols (float)
- self.clock_recovery = gr.clock_recovery_mm_ff(self._omega, self._gain_omega,
- self._mu, self._gain_mu,
- self._omega_relative_limit)
-
+ nfilts = 32
+ ntaps = 11 * int(self._samples_per_symbol*nfilts)
+ taps = gr.firdes.gaussian(nfilts,
+ nfilts*self._samples_per_symbol,
+ self._bt, ntaps)
+ self.clock_recovery = \
+ gr.pfb_clock_sync_fff(self._samples_per_symbol,
+ self._timing_bw, taps,
+ nfilts, nfilts//2, self._timing_max_dev)
+
# slice the floats at 0, outputting 1 bit (the LSB of the output byte) per sample
- self.slicer = gr.binary_slicer_fb()
+ self.slicer = digital_swig.binary_slicer_fb()
if verbose:
self._print_verbage()
@@ -245,48 +233,38 @@ class gmsk_demod(gr.hier_block2):
def _print_verbage(self):
- print "bits per symbol = %d" % self.bits_per_symbol()
- print "M&M clock recovery omega = %f" % self._omega
- print "M&M clock recovery gain mu = %f" % self._gain_mu
- print "M&M clock recovery mu = %f" % self._mu
- print "M&M clock recovery omega rel. limit = %f" % self._omega_relative_limit
- print "frequency error = %f" % self._freq_error
+ print "bits per symbol: %d" % self.bits_per_symbol()
+ print "Bandwidth-Time Prod: %f" % self._bw
+ print "Timing bandwidth: %.2e" % self._timing_bw
def _setup_logging(self):
print "Demodulation logging turned on."
self.connect(self.fmdemod,
- gr.file_sink(gr.sizeof_float, "fmdemod.dat"))
+ gr.file_sink(gr.sizeof_float, "rx_gmsk_fmdemod.32f"))
self.connect(self.clock_recovery,
- gr.file_sink(gr.sizeof_float, "clock_recovery.dat"))
+ gr.file_sink(gr.sizeof_float, "rx_gmsk_clock_recovery.32f"))
self.connect(self.slicer,
- gr.file_sink(gr.sizeof_char, "slicer.dat"))
+ gr.file_sink(gr.sizeof_char, "rx_gmsk_slicer.8b"))
def add_options(parser):
"""
Adds GMSK demodulation-specific options to the standard parser
"""
- parser.add_option("", "--gain-mu", type="float", default=_def_gain_mu,
- help="M&M clock recovery gain mu [default=%default] (GMSK/PSK)")
- parser.add_option("", "--mu", type="float", default=_def_mu,
- help="M&M clock recovery mu [default=%default] (GMSK/PSK)")
- parser.add_option("", "--omega-relative-limit", type="float", default=_def_omega_relative_limit,
- help="M&M clock recovery omega relative limit [default=%default] (GMSK/PSK)")
- parser.add_option("", "--freq-error", type="float", default=_def_freq_error,
- help="M&M clock recovery frequency error [default=%default] (GMSK)")
+ parser.add_option("", "--timing-bw", type="float", default=_def_timing_bw,
+ help="set timing symbol sync loop gain lock-in bandwidth [default=%default]")
add_options=staticmethod(add_options)
def extract_kwargs_from_options(options):
"""
Given command line options, create dictionary suitable for passing to __init__
"""
- return modulation_utils.extract_kwargs_from_options(gmsk_demod.__init__,
- ('self',), options)
+ return modulation_utils2.extract_kwargs_from_options(gmsk_demod.__init__,
+ ('self',), options)
extract_kwargs_from_options=staticmethod(extract_kwargs_from_options)
-
#
# Add these to the mod/demod registry
#
-modulation_utils.add_type_1_mod('gmsk', gmsk_mod)
-modulation_utils.add_type_1_demod('gmsk', gmsk_demod)
+modulation_utils2.add_type_1_mod('gmsk', gmsk_mod)
+modulation_utils2.add_type_1_demod('gmsk', gmsk_demod)
diff --git a/gr-digital/python/qa_constellation.py b/gr-digital/python/qa_constellation.py
index 02afb8d2d..264ff7de6 100755
--- a/gr-digital/python/qa_constellation.py
+++ b/gr-digital/python/qa_constellation.py
@@ -70,10 +70,8 @@ tested_constellation_info = (
'mod_code': tested_mod_codes, },
True, None),
(digital_swig.constellation_bpsk, {}, True, None),
- # No differential testing for qpsk because it is gray-coded.
- # This is because soft decision making is simpler if we can assume
- # gray coding.
(digital_swig.constellation_qpsk, {}, False, None),
+ (digital_swig.constellation_dqpsk, {}, True, None),
(digital_swig.constellation_8psk, {}, False, None),
(twod_constell, {}, True, None),
(threed_constell, {}, True, None),
@@ -143,8 +141,8 @@ class test_constellation (gr_unittest.TestCase):
class mod_demod(gr.hier_block2):
def __init__(self, constellation, differential, rotation):
if constellation.arity() > 256:
- # If this becomes limiting some of the blocks should be generalised so that they can work
- # with shorts and ints as well as chars.
+ # If this becomes limiting some of the blocks should be generalised so
+ # that they can work with shorts and ints as well as chars.
raise ValueError("Constellation cannot contain more than 256 points.")
gr.hier_block2.__init__(self, "mod_demod",
@@ -174,7 +172,8 @@ class mod_demod(gr.hier_block2):
if self.differential:
self.blocks.append(gr.diff_encoder_bb(arity))
# Convert to constellation symbols.
- self.blocks.append(gr.chunks_to_symbols_bc(self.constellation.points(), self.constellation.dimensionality()))
+ self.blocks.append(gr.chunks_to_symbols_bc(self.constellation.points(),
+ self.constellation.dimensionality()))
# CHANNEL
# Channel just consists of a rotation to check differential coding.
if rotation is not None:
diff --git a/gr-digital/python/qa_constellation_receiver.py b/gr-digital/python/qa_constellation_receiver.py
index 79dded8ba..25107e4a7 100755
--- a/gr-digital/python/qa_constellation_receiver.py
+++ b/gr-digital/python/qa_constellation_receiver.py
@@ -29,6 +29,7 @@ from generic_mod_demod import generic_mod, generic_demod
from qa_constellation import tested_constellations, twod_constell
+import math
# Set a seed so that if errors turn up they are reproducible.
# 1234 fails
@@ -47,11 +48,8 @@ FREQUENCY_OFFSET = 0.01
TIMING_OFFSET = 1.0
# RECEIVER PARAMETERS
-# Increased from normal default of 0.01 to speed things up.
-FREQ_ALPHA = 0.02
-# Decreased from normal default of 0.1 is required for the constellations
-# with smaller point separations.
-PHASE_ALPHA = 0.02
+FREQ_BW = 2*math.pi/100.0
+PHASE_BW = 2*math.pi/100.0
class test_constellation_receiver (gr_unittest.TestCase):
@@ -127,8 +125,8 @@ class rec_test_tb (gr.top_block):
channel = gr.channel_model(NOISE_VOLTAGE, FREQUENCY_OFFSET, TIMING_OFFSET)
# Receiver Blocks
demod = generic_demod(constellation, differential=differential,
- freq_alpha=FREQ_ALPHA,
- phase_alpha=PHASE_ALPHA)
+ freq_bw=FREQ_BW,
+ phase_bw=PHASE_BW)
self.dst = gr.vector_sink_b()
self.connect(src, packer, mod, channel, demod, self.dst)
diff --git a/gr-digital/python/qa_cpm.py b/gr-digital/python/qa_cpm.py
new file mode 100755
index 000000000..12a84c76c
--- /dev/null
+++ b/gr-digital/python/qa_cpm.py
@@ -0,0 +1,91 @@
+#!/usr/bin/env python
+#
+# Copyright 2010 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 digital_swig
+import numpy
+
+class test_cpm(gr_unittest.TestCase):
+
+ def setUp (self):
+ self.tb = gr.top_block ()
+
+ def tearDown (self):
+ self.tb = None
+
+ def do_check_phase_shift(self, type, name):
+ sps = 2
+ L = 1
+ in_bits = (1,) * 20
+ src = gr.vector_source_b(in_bits, False)
+ cpm = digital_swig.cpmmod_bc(type, 0.5, sps, L)
+ arg = gr.complex_to_arg()
+ sink = gr.vector_sink_f()
+
+ self.tb.connect(src, cpm, arg, sink)
+ self.tb.run()
+
+ symbol_phases = numpy.array(sink.data()[sps*L-1::sps])
+ phase_diff = numpy.mod(numpy.subtract(symbol_phases[1:], symbol_phases[:-1]),
+ (2*numpy.pi,) * (len(symbol_phases)-1))
+ self.assertFloatTuplesAlmostEqual(tuple(phase_diff), (0.5 * numpy.pi,) * len(phase_diff), 5,
+ msg="Phase shift was not correct for CPM method " + name)
+
+ def test_001_lrec(self):
+ self.do_check_phase_shift(gr.cpm.LRC, 'LREC')
+
+ def test_001_lrc(self):
+ self.do_check_phase_shift(gr.cpm.LRC, 'LRC')
+
+ def test_001_lsrc(self):
+ self.do_check_phase_shift(gr.cpm.LSRC, 'LSRC')
+
+ def test_001_ltfm(self):
+ self.do_check_phase_shift(gr.cpm.TFM, 'TFM')
+
+ def test_001_lgmsk(self):
+ sps = 2
+ L = 5
+ bt = 0.3
+ in_bits = (1,) * 20
+ src = gr.vector_source_b(in_bits, False)
+ gmsk = digital_swig.gmskmod_bc(sps, bt, L)
+ arg = gr.complex_to_arg()
+ sink = gr.vector_sink_f()
+
+ self.tb.connect(src, gmsk, arg, sink)
+ self.tb.run()
+
+ symbol_phases = numpy.array(sink.data()[sps*L-1::sps])
+ phase_diff = numpy.mod(numpy.subtract(symbol_phases[1:], symbol_phases[:-1]),
+ (2*numpy.pi,) * (len(symbol_phases)-1))
+ self.assertFloatTuplesAlmostEqual(tuple(phase_diff), (0.5 * numpy.pi,) * len(phase_diff), 5,
+ msg="Phase shift was not correct for GMSK")
+
+ def test_phase_response(self):
+ phase_response = gr.cpm.phase_response(gr.cpm.LREC, 2, 4)
+ self.assertAlmostEqual(numpy.sum(phase_response), 1)
+
+
+if __name__ == '__main__':
+ gr_unittest.run(test_cpm, "test_cpm.xml")
+
diff --git a/gr-digital/python/qa_crc32.py b/gr-digital/python/qa_crc32.py
index f86813f3f..f86813f3f 100644..100755
--- a/gr-digital/python/qa_crc32.py
+++ b/gr-digital/python/qa_crc32.py
diff --git a/gr-digital/python/qa_fll_band_edge.py b/gr-digital/python/qa_fll_band_edge.py
index 088eb2b68..088eb2b68 100644..100755
--- a/gr-digital/python/qa_fll_band_edge.py
+++ b/gr-digital/python/qa_fll_band_edge.py
diff --git a/gr-digital/python/qa_lms_equalizer.py b/gr-digital/python/qa_lms_equalizer.py
index 025c785aa..025c785aa 100644..100755
--- a/gr-digital/python/qa_lms_equalizer.py
+++ b/gr-digital/python/qa_lms_equalizer.py
diff --git a/gr-digital/python/qa_mpsk_receiver.py b/gr-digital/python/qa_mpsk_receiver.py
index 7e9a76e1f..6531e59f7 100644..100755
--- a/gr-digital/python/qa_mpsk_receiver.py
+++ b/gr-digital/python/qa_mpsk_receiver.py
@@ -36,8 +36,7 @@ class test_mpsk_receiver(gr_unittest.TestCase):
# Test BPSK sync
M = 2
theta = 0
- alpha = 0.1
- beta = 0.25*alpha*alpha
+ loop_bw = cmath.pi/100.0
fmin = -0.5
fmax = 0.5
mu = 0.25
@@ -46,7 +45,7 @@ class test_mpsk_receiver(gr_unittest.TestCase):
gain_omega = 0.001
omega_rel = 0.001
- self.test = digital_swig.mpsk_receiver_cc(M, theta, alpha, beta,
+ self.test = digital_swig.mpsk_receiver_cc(M, theta, loop_bw,
fmin, fmax, mu, gain_mu,
omega, gain_omega,
omega_rel)
@@ -68,8 +67,8 @@ class test_mpsk_receiver(gr_unittest.TestCase):
expected_result = expected_result[len_e - Ncmp:]
dst_data = dst_data[len_d - Ncmp:]
- #print expected_result
- #print dst_data
+ #for e,d in zip(expected_result, dst_data):
+ # print e, d
self.assertComplexTuplesAlmostEqual (expected_result, dst_data, 1)
@@ -78,8 +77,7 @@ class test_mpsk_receiver(gr_unittest.TestCase):
# Test QPSK sync
M = 4
theta = 0
- alpha = 0.1
- beta = 0.25*alpha*alpha
+ loop_bw = 2*cmath.pi/100.0
fmin = -0.5
fmax = 0.5
mu = 0.25
@@ -88,11 +86,11 @@ class test_mpsk_receiver(gr_unittest.TestCase):
gain_omega = 0.001
omega_rel = 0.001
- self.test = digital_swig.mpsk_receiver_cc(M, theta, alpha, beta,
+ self.test = digital_swig.mpsk_receiver_cc(M, theta, loop_bw,
fmin, fmax, mu, gain_mu,
omega, gain_omega,
omega_rel)
-
+
data = 1000*[complex( 0.707, 0.707), complex( 0.707, 0.707),
complex(-0.707, 0.707), complex(-0.707, 0.707),
complex(-0.707, -0.707), complex(-0.707, -0.707),
@@ -103,8 +101,8 @@ class test_mpsk_receiver(gr_unittest.TestCase):
self.tb.connect(self.src, self.test, self.snk)
self.tb.run()
- expected_result = 1000*[complex(1.2, 0), complex(0, 1.2),
- complex(-1.2, 0), complex(0, -1.2)]
+ expected_result = 1000*[complex(0, -1.0), complex(1.0, 0),
+ complex(0, 1.0), complex(-1.0, 0)]
dst_data = self.snk.data()
# Only compare last Ncmp samples
@@ -114,9 +112,9 @@ class test_mpsk_receiver(gr_unittest.TestCase):
expected_result = expected_result[len_e - Ncmp:]
dst_data = dst_data[len_d - Ncmp:]
- #print expected_result
- #print dst_data
-
+ #for e,d in zip(expected_result, dst_data):
+ # print e, d
+
self.assertComplexTuplesAlmostEqual (expected_result, dst_data, 1)
if __name__ == '__main__':
diff --git a/gr-digital/python/qpsk.py b/gr-digital/python/qpsk.py
index 76e5df270..481b7cb5b 100644
--- a/gr-digital/python/qpsk.py
+++ b/gr-digital/python/qpsk.py
@@ -100,10 +100,77 @@ class qpsk_demod(generic_demod):
super(qpsk_demod, self).__init__(constellation=constellation,
*args, **kwargs)
+
+
+# /////////////////////////////////////////////////////////////////////////////
+# DQPSK constellation
+# /////////////////////////////////////////////////////////////////////////////
+
+def dqpsk_constellation(m=_def_constellation_points):
+ if m != _def_constellation_points:
+ raise ValueError("DQPSK can only have 4 constellation points.")
+ return digital_swig.constellation_dqpsk()
+
+# /////////////////////////////////////////////////////////////////////////////
+# DQPSK modulator
+# /////////////////////////////////////////////////////////////////////////////
+
+class dqpsk_mod(generic_mod):
+
+ def __init__(self, constellation_points=_def_constellation_points,
+ gray_coded=_def_gray_coded,
+ differential=True, *args, **kwargs):
+ """
+ Hierarchical block for RRC-filtered DQPSK modulation.
+
+ The input is a byte stream (unsigned char) and the
+ output is the complex modulated signal at baseband.
+
+ See generic_mod block for list of parameters.
+ """
+
+ constellation_points = _def_constellation_points
+ constellation = digital_swig.constellation_dqpsk()
+ if constellation_points != 4:
+ raise ValueError('Number of constellation points must be 4 for DQPSK.')
+ super(dqpsk_mod, self).__init__(constellation=constellation,
+ gray_coded=gray_coded,
+ differential=True,
+ *args, **kwargs)
+
+# /////////////////////////////////////////////////////////////////////////////
+# DQPSK demodulator
+#
+# /////////////////////////////////////////////////////////////////////////////
+
+class dqpsk_demod(generic_demod):
+
+ def __init__(self, constellation_points=_def_constellation_points,
+ differential=True, *args, **kwargs):
+
+ """
+ Hierarchical block for RRC-filtered DQPSK modulation.
+
+ The input is a byte stream (unsigned char) and the
+ output is the complex modulated signal at baseband.
+
+ See generic_demod block for list of parameters.
+ """
+ constellation_points = _def_constellation_points
+ constellation = digital_swig.constellation_dqpsk()
+ if constellation_points != 4:
+ raise ValueError('Number of constellation points must be 4 for DQPSK.')
+ super(dqpsk_demod, self).__init__(constellation=constellation,
+ differential=True,
+ *args, **kwargs)
+
#
# Add these to the mod/demod registry
#
modulation_utils2.add_type_1_mod('qpsk', qpsk_mod)
modulation_utils2.add_type_1_demod('qpsk', qpsk_demod)
modulation_utils2.add_type_1_constellation('qpsk', qpsk_constellation)
+modulation_utils2.add_type_1_mod('dqpsk', dqpsk_mod)
+modulation_utils2.add_type_1_demod('dqpsk', dqpsk_demod)
+modulation_utils2.add_type_1_constellation('dqpsk', dqpsk_constellation)
diff --git a/gr-digital/swig/CMakeLists.txt b/gr-digital/swig/CMakeLists.txt
index b62c024e0..5c6477aa1 100644
--- a/gr-digital/swig/CMakeLists.txt
+++ b/gr-digital/swig/CMakeLists.txt
@@ -30,10 +30,11 @@ SET(GR_SWIG_INCLUDE_DIRS
SET(GR_SWIG_LIBRARIES gnuradio-digital)
+GR_SWIG_MAKE(digital_hier digital_hier.i)
GR_SWIG_MAKE(digital_swig digital_swig.i)
GR_SWIG_INSTALL(
- TARGETS digital_swig
+ TARGETS digital_hier digital_swig
DESTINATION ${GR_PYTHON_DIR}/gnuradio/digital
COMPONENT "digital_python"
)
diff --git a/gr-digital/swig/Makefile.am b/gr-digital/swig/Makefile.am
index c0d28c24c..6604665b0 100644
--- a/gr-digital/swig/Makefile.am
+++ b/gr-digital/swig/Makefile.am
@@ -26,8 +26,7 @@ TESTS =
EXTRA_DIST += $(nobase_guile_DATA)
AM_CPPFLAGS = \
- -I$(abs_top_srcdir)/gr-digital/lib \
- -I$(abs_top_builddir)/gr-digital/lib \
+ $(GR_DIGITAL_INCLUDES) \
$(STD_DEFINES_AND_INCLUDES) \
$(PYTHON_CPPFLAGS) \
$(WITH_INCLUDES)
@@ -43,6 +42,7 @@ noinst_GUILE = digital.test
##############################
# SWIG interface and library
TOP_SWIG_IFILES = \
+ digital_hier.i \
digital_swig.i
# Install so that they end up available as:
@@ -73,9 +73,11 @@ digital_swig_swiginclude_headers = \
digital_kurtotic_equalizer_cc.i \
digital_mpsk_receiver_cc.i
+digital_hier_swig_args = \
+ $(GR_DIGITAL_INCLUDES)
+
digital_swig_swig_args = \
- -I$(abs_top_srcdir)/gr-digital/lib \
- -I$(abs_top_builddir)/gr-digital/lib
+ $(GR_DIGITAL_INCLUDES)
if GUILE
TESTS += run_guile_tests
diff --git a/gr-digital/swig/Makefile.swig.gen b/gr-digital/swig/Makefile.swig.gen
index bd9aabcea..95d6aea89 100644
--- a/gr-digital/swig/Makefile.swig.gen
+++ b/gr-digital/swig/Makefile.swig.gen
@@ -101,8 +101,7 @@ _digital_swig_la_LDFLAGS = \
_digital_swig_la_CXXFLAGS = \
$(STD_SWIG_CXX_FLAGS) \
- -I$(top_builddir) \
- $(digital_swig_la_swig_cxxflags)
+ -I$(top_builddir)
python/digital_swig.cc: digital_swig.py
digital_swig.py: digital_swig.i
@@ -143,3 +142,148 @@ gnuradio/digital_swig-primitive.scm: gnuradio/digital_swig.scm
endif # end of GUILE
+# -*- Makefile -*-
+#
+# Copyright 2009,2011 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.
+#
+
+# Makefile.swig.gen for digital_hier.i
+
+## Default install locations for these files:
+##
+## Default location for the Python directory is:
+## ${prefix}/lib/python${python_version}/site-packages/[category]/digital_hier
+## Default location for the Python exec directory is:
+## ${exec_prefix}/lib/python${python_version}/site-packages/[category]/digital_hier
+##
+## The following can be overloaded to change the install location, but
+## this has to be done in the including Makefile.am -before-
+## Makefile.swig is included.
+
+digital_hier_pythondir_category ?= gnuradio/digital_hier
+digital_hier_pylibdir_category ?= $(digital_hier_pythondir_category)
+digital_hier_pythondir = $(pythondir)/$(digital_hier_pythondir_category)
+digital_hier_pylibdir = $(pyexecdir)/$(digital_hier_pylibdir_category)
+
+# The .so libraries for the guile modules get installed whereever guile
+# is installed, usually /usr/lib/guile/gnuradio/
+# FIXME: determince whether these should be installed with gnuradio.
+digital_hier_scmlibdir = $(libdir)
+
+# The scm files for the guile modules get installed where ever guile
+# is installed, usually /usr/share/guile/site/digital_hier
+# FIXME: determince whether these should be installed with gnuradio.
+digital_hier_scmdir = $(guiledir)
+
+## SWIG headers are always installed into the same directory.
+
+digital_hier_swigincludedir = $(swigincludedir)
+
+## This is a template file for a "generated" Makefile addition (in
+## this case, "Makefile.swig.gen"). By including the top-level
+## Makefile.swig, this file will be used to generate the SWIG
+## dependencies. Assign the variable TOP_SWIG_FILES to be the list of
+## SWIG .i files to generated wrappings for; there can be more than 1
+## so long as the names are unique (no sorting is done on the
+## TOP_SWIG_FILES list). This file explicitly assumes that a SWIG .i
+## file will generate .cc, .py, and possibly .h files -- meaning that
+## all of these files will have the same base name (that provided for
+## the SWIG .i file).
+##
+## This code is setup to ensure parallel MAKE ("-j" or "-jN") does the
+## right thing. For more info, see <
+## http://sources.redhat.com/automake/automake.html#Multiple-Outputs >
+
+## Other cleaned files: dependency files generated by SWIG or this Makefile
+
+MOSTLYCLEANFILES += $(DEPDIR)/*.S*
+
+## Various SWIG variables. These can be overloaded in the including
+## Makefile.am by setting the variable value there, then including
+## Makefile.swig .
+
+digital_hier_swiginclude_HEADERS = \
+ digital_hier.i \
+ $(digital_hier_swiginclude_headers)
+
+if PYTHON
+digital_hier_pylib_LTLIBRARIES = \
+ _digital_hier.la
+
+_digital_hier_la_SOURCES = \
+ python/digital_hier.cc \
+ $(digital_hier_la_swig_sources)
+
+digital_hier_python_PYTHON = \
+ digital_hier.py \
+ $(digital_hier_python)
+
+_digital_hier_la_LIBADD = \
+ $(STD_SWIG_LA_LIB_ADD) \
+ $(digital_hier_la_swig_libadd)
+
+_digital_hier_la_LDFLAGS = \
+ $(STD_SWIG_LA_LD_FLAGS) \
+ $(digital_hier_la_swig_ldflags)
+
+_digital_hier_la_CXXFLAGS = \
+ $(STD_SWIG_CXX_FLAGS) \
+ -I$(top_builddir) \
+ $(digital_hier_la_swig_cxxflags)
+
+python/digital_hier.cc: digital_hier.py
+digital_hier.py: digital_hier.i
+
+# Include the python dependencies for this file
+-include python/digital_hier.d
+
+endif # end of if python
+
+if GUILE
+
+digital_hier_scmlib_LTLIBRARIES = \
+ libguile-gnuradio-digital_hier.la
+libguile_gnuradio_digital_hier_la_SOURCES = \
+ guile/digital_hier.cc \
+ $(digital_hier_la_swig_sources)
+nobase_digital_hier_scm_DATA = \
+ gnuradio/digital_hier.scm \
+ gnuradio/digital_hier-primitive.scm
+libguile_gnuradio_digital_hier_la_LIBADD = \
+ $(STD_SWIG_LA_LIB_ADD) \
+ $(digital_hier_la_swig_libadd)
+libguile_gnuradio_digital_hier_la_LDFLAGS = \
+ $(STD_SWIG_LA_LD_FLAGS) \
+ $(digital_hier_la_swig_ldflags)
+libguile_gnuradio_digital_hier_la_CXXFLAGS = \
+ $(STD_SWIG_CXX_FLAGS) \
+ -I$(top_builddir) \
+ $(digital_hier_la_swig_cxxflags)
+
+guile/digital_hier.cc: gnuradio/digital_hier.scm
+gnuradio/digital_hier.scm: digital_hier.i
+gnuradio/digital_hier-primitive.scm: gnuradio/digital_hier.scm
+
+# Include the guile dependencies for this file
+-include guile/digital_hier.d
+
+endif # end of GUILE
+
+
diff --git a/gr-digital/swig/digital_constellation.i b/gr-digital/swig/digital_constellation.i
index ae31d443e..7e0ad6afe 100644
--- a/gr-digital/swig/digital_constellation.i
+++ b/gr-digital/swig/digital_constellation.i
@@ -50,6 +50,7 @@ public:
unsigned int arity ();
digital_constellation_sptr base ();
bool apply_pre_diff_code();
+ void set_pre_diff_code(bool a);
std::vector<unsigned int> pre_diff_code();
unsigned int rotational_symmetry();
unsigned int dimensionality();
@@ -152,6 +153,23 @@ public:
digital_constellation_qpsk ();
};
+/*
+ DQPSK Constellation
+*/
+
+class digital_constellation_dqpsk;
+typedef boost::shared_ptr<digital_constellation_dqpsk> digital_constellation_dqpsk_sptr;
+%template(digital_constellation_dqpsk_sptr) boost::shared_ptr<digital_constellation_dqpsk>;
+%rename(constellation_dqpsk) digital_make_constellation_dqpsk;
+digital_constellation_dqpsk_sptr digital_make_constellation_dqpsk();
+%ignore digital_constellation_dqpsk;
+
+class digital_constellation_dqpsk : public digital_constellation
+{
+public:
+ digital_constellation_dqpsk ();
+};
+
/*
8PSK Constellation
diff --git a/gr-digital/swig/digital_constellation_receiver_cb.i b/gr-digital/swig/digital_constellation_receiver_cb.i
index e4be5f39f..9c4ba645e 100644
--- a/gr-digital/swig/digital_constellation_receiver_cb.i
+++ b/gr-digital/swig/digital_constellation_receiver_cb.i
@@ -28,23 +28,9 @@ digital_constellation_receiver_cb_sptr
digital_make_constellation_receiver_cb (digital_constellation_sptr constellation,
float loop_bw, float fmin, float fmax);
-class digital_constellation_receiver_cb : public gr_block
+class digital_constellation_receiver_cb : public gr_block, public gri_control_loop
{
private:
digital_constellation_receiver_cb (digital_contellation_sptr constellation,
float loop_bw, float fmin, float fmax);
-public:
- void set_loop_bandwidth(float bw);
- void set_damping_factor(float df);
- void set_alpha(float alpha);
- void set_beta(float beta);
- void set_frequency(float freq);
- void set_phase(float phase);
-
- float get_loop_bandwidth() const;
- float get_damping_factor() const;
- float get_alpha() const;
- float get_beta() const;
- float get_frequency() const;
- float get_phase() const;
};
diff --git a/gr-digital/swig/digital_fll_band_edge_cc.i b/gr-digital/swig/digital_fll_band_edge_cc.i
index f022bc7e1..3efcb89ed 100644
--- a/gr-digital/swig/digital_fll_band_edge_cc.i
+++ b/gr-digital/swig/digital_fll_band_edge_cc.i
@@ -27,7 +27,7 @@ digital_fll_band_edge_cc_sptr digital_make_fll_band_edge_cc (float samps_per_sym
int filter_size,
float bandwidth);
-class digital_fll_band_edge_cc : public gr_sync_block
+class digital_fll_band_edge_cc : public gr_sync_block, public gri_control_loop
{
private:
digital_fll_band_edge_cc (float samps_per_sym, float rolloff,
diff --git a/gr-digital/swig/digital_hier.i b/gr-digital/swig/digital_hier.i
new file mode 100644
index 000000000..e004461d2
--- /dev/null
+++ b/gr-digital/swig/digital_hier.i
@@ -0,0 +1,40 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2009,2010 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.
+ */
+
+#ifndef SWIGIMPORTED
+%module(directors="1") digital_hier
+#endif
+
+ //%feature("autodoc", "1"); // generate python docstrings
+
+%include "gnuradio.i" // the common stuff
+
+%include "_digital_hier.i"
+
+#if SWIGGUILE
+%scheme %{
+(load-extension-global "libguile-gnuradio-digital_hier" "scm_init_gnuradio_digital_hier_module")
+%}
+
+%goops %{
+ (use-modules (gnuradio gnuradio_core_runtime))
+%}
+#endif
diff --git a/gr-digital/swig/digital_mpsk_receiver_cc.i b/gr-digital/swig/digital_mpsk_receiver_cc.i
index cdc9f661b..b51411f6f 100644
--- a/gr-digital/swig/digital_mpsk_receiver_cc.i
+++ b/gr-digital/swig/digital_mpsk_receiver_cc.i
@@ -23,16 +23,16 @@
GR_SWIG_BLOCK_MAGIC(digital,mpsk_receiver_cc);
digital_mpsk_receiver_cc_sptr digital_make_mpsk_receiver_cc (unsigned int M, float theta,
- float alpha, float beta,
+ float loop_bw,
float fmin, float fmax,
float mu, float gain_mu,
float omega, float gain_omega,
float omega_rel);
-class digital_mpsk_receiver_cc : public gr_block
+class digital_mpsk_receiver_cc : public gr_block, public gri_control_loop
{
private:
digital_mpsk_receiver_cc (unsigned int M,float theta,
- float alpha, float beta,
+ float loop_bw,
float fmin, float fmax,
float mu, float gain_mu,
float omega, float gain_omega, float omega_rel);
@@ -49,12 +49,4 @@ public:
}
void set_gain_mu (float gain_mu) { d_gain_mu = gain_mu; }
void set_gain_omega (float gain_omega) { d_gain_omega = gain_omega; }
- float alpha() const { return d_alpha; }
- float beta() const { return d_beta; }
- float freq() const { return d_freq; }
- float phase() const { return d_phase; }
- void set_alpha(float alpha) { d_alpha = alpha; }
- void set_beta(float beta) { d_beta = beta; }
- void set_freq(float freq) { d_freq = freq; }
- void set_phase(float phase) { d_phase = phase; }
};
diff --git a/gr-digital/swig/digital_swig.i b/gr-digital/swig/digital_swig.i
index 0328ca2fc..ca50f9c50 100644
--- a/gr-digital/swig/digital_swig.i
+++ b/gr-digital/swig/digital_swig.i
@@ -40,6 +40,7 @@
#include "digital_mpsk_receiver_cc.h"
%}
+%include "digital_hier.i"
%include "digital_binary_slicer_fb.i"
%include "digital_clock_recovery_mm_cc.i"
%include "digital_clock_recovery_mm_ff.i"
diff --git a/gr-utils/src/python/gr_plot_const.py b/gr-utils/src/python/gr_plot_const.py
index 0c52899b2..8873e5b7e 100755
--- a/gr-utils/src/python/gr_plot_const.py
+++ b/gr-utils/src/python/gr_plot_const.py
@@ -92,7 +92,7 @@ class draw_constellation:
self.imags = scipy.array([i.imag for i in iq])
self.time = scipy.array([i*(1/self.sample_rate) for i in range(len(self.reals))])
- return Tr
+ return True
else:
print "End of File"
return False
diff --git a/grc/blocks/Makefile.am b/grc/blocks/Makefile.am
index 14ffe8358..6f72fe399 100644
--- a/grc/blocks/Makefile.am
+++ b/grc/blocks/Makefile.am
@@ -91,6 +91,7 @@ dist_ourdata_DATA = \
gr_costas_loop_cc.xml \
gr_cpfsk_bc.xml \
gr_dc_blocker.xml \
+ gr_cpmmod_bc.xml \
gr_decode_ccsds_27_fb.xml \
gr_deinterleave.xml \
gr_delay.xml \
@@ -108,7 +109,6 @@ dist_ourdata_DATA = \
gr_file_source.xml \
gr_filter_delay_fc.xml \
gr_fir_filter_xxx.xml \
- gr_fll_band_edge_cc.xml \
gr_float_to_char.xml \
gr_float_to_complex.xml \
gr_float_to_short.xml \
@@ -117,6 +117,7 @@ dist_ourdata_DATA = \
gr_freq_xlating_fir_filter_xxx.xml \
gr_frequency_modulator_fc.xml \
gr_glfsr_source_x.xml \
+ gr_gmskmod_bc.xml \
gr_goertzel_fc.xml \
gr_head.xml \
gr_hilbert_fc.xml \
@@ -134,7 +135,6 @@ dist_ourdata_DATA = \
gr_message_sink.xml \
gr_message_source.xml \
gr_moving_average_xx.xml \
- gr_mpsk_receiver_cc.xml \
gr_mpsk_sync_cc.xml \
gr_multiply_const_vxx.xml \
gr_multiply_xx.xml \
diff --git a/grc/blocks/block_tree.xml b/grc/blocks/block_tree.xml
index 0b641d79c..f5365dcb5 100644
--- a/grc/blocks/block_tree.xml
+++ b/grc/blocks/block_tree.xml
@@ -121,14 +121,11 @@
<block>gr_costas_loop_cc</block>
<block>gr_mpsk_sync_cc</block>
- <block>gr_mpsk_receiver_cc</block>
<block>gr_pll_carriertracking_cc</block>
<block>gr_pll_freqdet_cf</block>
<block>gr_pll_refout_cc</block>
- <block>gr_fll_band_edge_cc</block>
-
<block>gr_correlate_access_code_bb</block>
<block>gr_pn_correlator_cc</block>
<block>gr_simple_correlator</block>
@@ -197,6 +194,8 @@
<block>gr_phase_modulator_fc</block>
<block>gr_quadrature_demod_cf</block>
<block>gr_cpfsk_bc</block>
+ <block>gr_cpmmod_bc</block>
+ <block>gr_gmskmod_bc</block>
<block>gr_diff_phasor_cc</block>
<block>gr_constellation_decoder_cb</block>
diff --git a/grc/blocks/gr_cpmmod_bc.xml b/grc/blocks/gr_cpmmod_bc.xml
new file mode 100644
index 000000000..da405534e
--- /dev/null
+++ b/grc/blocks/gr_cpmmod_bc.xml
@@ -0,0 +1,69 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+## Continuous Phase Modulation
+###################################################
+ -->
+<block>
+ <name>Continuous Phase Modulation</name>
+ <key>gr_cpmmod_bc</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.cpmmod_bc($type, $mod_index, $samples_per_symbol, $L, $beta)</make>
+ <param>
+ <name>CPM Type</name>
+ <key>type</key>
+ <type>enum</type>
+ <option>
+ <name>L-REC (Rectangular phase response)</name>
+ <key>gr.cpm.LREC</key>
+ </option>
+ <option>
+ <name>L-RC (Raised Cosine)</name>
+ <key>gr.cpm.LRC</key>
+ </option>
+ <option>
+ <name>L-SRC (Spectral raised cosine)</name>
+ <key>gr.cpm.LSRC</key>
+ </option>
+ <option>
+ <name>TFM (Tamed frequency modulation)</name>
+ <key>gr.cpm.TFM</key>
+ </option>
+ <option>
+ <name>Gaussian</name>
+ <key>gr.cpm.GAUSSIAN</key>
+ </option>
+ </param>
+ <param>
+ <name>Modulation Index</name>
+ <key>mod_index</key>
+ <value>0.5</value>
+ <type>real</type>
+ </param>
+ <param>
+ <name>Samples/Symbol</name>
+ <key>samples_per_symbol</key>
+ <value>4</value>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Pulse Duration (Symbols)</name>
+ <key>L</key>
+ <value>4</value>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Phase Response Parameter (BT or Beta)</name>
+ <key>beta</key>
+ <value>0.3</value>
+ <type>real</type>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>byte</type>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>complex</type>
+ </source>
+</block>
diff --git a/grc/blocks/gr_gmskmod_bc.xml b/grc/blocks/gr_gmskmod_bc.xml
new file mode 100644
index 000000000..82e47452b
--- /dev/null
+++ b/grc/blocks/gr_gmskmod_bc.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+## GMSK
+###################################################
+ -->
+<block>
+ <name>GMSK Modulator</name>
+ <key>gr_gmskmod_bc</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.gmskmod_bc($samples_per_symbol, $bt, $L)</make>
+ <param>
+ <name>Samples/Symbol</name>
+ <key>samples_per_symbol</key>
+ <value>2</value>
+ <type>int</type>
+ </param>
+ <param>
+ <name>3 dB Time-Bandwith Product</name>
+ <key>bt</key>
+ <value>0.3</value>
+ <type>real</type>
+ </param>
+ <param>
+ <name>Pulse Duration (Symbols)</name>
+ <key>L</key>
+ <value>4</value>
+ <type>int</type>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>byte</type>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>complex</type>
+ </source>
+</block>
diff --git a/grc/blocks/gr_pll_carriertracking_cc.xml b/grc/blocks/gr_pll_carriertracking_cc.xml
index 5b876b259..27e673248 100644
--- a/grc/blocks/gr_pll_carriertracking_cc.xml
+++ b/grc/blocks/gr_pll_carriertracking_cc.xml
@@ -8,15 +8,11 @@
<name>PLL Carrier Tracking</name>
<key>gr_pll_carriertracking_cc</key>
<import>from gnuradio import gr</import>
- <make>gr.pll_carriertracking_cc($alpha, $beta, $max_freq, $min_freq)</make>
+ <make>gr.pll_carriertracking_cc($w, $max_freq, $min_freq)</make>
+ <callback>set_loop_bandwidth($w)</callback>
<param>
- <name>Alpha</name>
- <key>alpha</key>
- <type>real</type>
- </param>
- <param>
- <name>Beta</name>
- <key>beta</key>
+ <name>Loop Bandwidth</name>
+ <key>w</key>
<type>real</type>
</param>
<param>
diff --git a/grc/blocks/gr_pll_freqdet_cf.xml b/grc/blocks/gr_pll_freqdet_cf.xml
index 8ec1fb3bb..d6e4694f0 100644
--- a/grc/blocks/gr_pll_freqdet_cf.xml
+++ b/grc/blocks/gr_pll_freqdet_cf.xml
@@ -8,15 +8,11 @@
<name>PLL Freq Det</name>
<key>gr_pll_freqdet_cf</key>
<import>from gnuradio import gr</import>
- <make>gr.pll_freqdet_cf($alpha, $beta, $max_freq, $min_freq)</make>
+ <make>gr.pll_freqdet_cf($w, $max_freq, $min_freq)</make>
+ <callback>set_loop_bandwidth($w)</callback>
<param>
- <name>Alpha</name>
- <key>alpha</key>
- <type>real</type>
- </param>
- <param>
- <name>Beta</name>
- <key>beta</key>
+ <name>Loop Bandwidth</name>
+ <key>w</key>
<type>real</type>
</param>
<param>
diff --git a/grc/blocks/gr_pll_refout_cc.xml b/grc/blocks/gr_pll_refout_cc.xml
index 64cf2bfb6..b231ddd19 100644
--- a/grc/blocks/gr_pll_refout_cc.xml
+++ b/grc/blocks/gr_pll_refout_cc.xml
@@ -8,15 +8,11 @@
<name>PLL Ref Out</name>
<key>gr_pll_refout_cc</key>
<import>from gnuradio import gr</import>
- <make>gr.pll_refout_cc($alpha, $beta, $max_freq, $min_freq)</make>
+ <make>gr.pll_refout_cc($w, $max_freq, $min_freq)</make>
+ <callback>set_loop_bandwidth($w)</callback>
<param>
- <name>Alpha</name>
- <key>alpha</key>
- <type>real</type>
- </param>
- <param>
- <name>Beta</name>
- <key>beta</key>
+ <name>Loop Bandwidth</name>
+ <key>w</key>
<type>real</type>
</param>
<param>