From 730e550d4ec5f429170d97383e3826193a893ac8 Mon Sep 17 00:00:00 2001 From: Martin Braun Date: Wed, 8 Dec 2010 17:51:43 +0100 Subject: first version of CPM code --- gnuradio-core/src/lib/hier/Makefile.am | 26 +++- gnuradio-core/src/lib/hier/gr_cpm.cc | 210 +++++++++++++++++++++++++++++ gnuradio-core/src/lib/hier/gr_cpm.h | 75 +++++++++++ gnuradio-core/src/lib/hier/gr_cpm.i | 40 ++++++ gnuradio-core/src/lib/hier/gr_cpmmod_bc.cc | 74 ++++++++++ gnuradio-core/src/lib/hier/gr_cpmmod_bc.h | 62 +++++++++ gnuradio-core/src/lib/hier/gr_cpmmod_bc.i | 36 +++++ gnuradio-core/src/lib/hier/hier.i | 3 + gnuradio-core/src/lib/hier/qa_gr_cpm.cc | 108 +++++++++++++++ gnuradio-core/src/lib/hier/qa_gr_cpm.h | 51 +++++++ 10 files changed, 680 insertions(+), 5 deletions(-) create mode 100644 gnuradio-core/src/lib/hier/gr_cpm.cc create mode 100644 gnuradio-core/src/lib/hier/gr_cpm.h create mode 100644 gnuradio-core/src/lib/hier/gr_cpm.i create mode 100644 gnuradio-core/src/lib/hier/gr_cpmmod_bc.cc create mode 100644 gnuradio-core/src/lib/hier/gr_cpmmod_bc.h create mode 100644 gnuradio-core/src/lib/hier/gr_cpmmod_bc.i create mode 100644 gnuradio-core/src/lib/hier/qa_gr_cpm.cc create mode 100644 gnuradio-core/src/lib/hier/qa_gr_cpm.h diff --git a/gnuradio-core/src/lib/hier/Makefile.am b/gnuradio-core/src/lib/hier/Makefile.am index e2e7fe886..3a7c9f592 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 # @@ -24,16 +24,32 @@ include $(top_srcdir)/Makefile.common AM_CPPFLAGS = $(STD_DEFINES_AND_INCLUDES) $(WITH_INCLUDES) -noinst_LTLIBRARIES = libhier.la +noinst_LTLIBRARIES = libhier.la libhier-qa.la libhier_la_SOURCES = \ - gr_channel_model.cc + gr_channel_model.cc \ + gr_cpm.cc \ + gr_cpmmod_bc.cc grinclude_HEADERS = \ - gr_channel_model.h + gr_channel_model.h \ + gr_cpm.h \ + gr_cpmmod_bc.h + if PYTHON swiginclude_HEADERS = \ hier.i \ - gr_channel_model.i + gr_channel_model.i \ + gr_cpmmod_bc.i \ + gr_cpm.i endif + + +libhier_qa_la_SOURCES = \ + qa_gr_cpm.cc + +noinst_HEADERS = \ + qa_gr_cpm.h + + diff --git a/gnuradio-core/src/lib/hier/gr_cpm.cc b/gnuradio-core/src/lib/hier/gr_cpm.cc new file mode 100644 index 000000000..5eda182b2 --- /dev/null +++ b/gnuradio-core/src/lib/hier/gr_cpm.cc @@ -0,0 +1,210 @@ +/* -*- 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 +#include +#include + + +//! 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 +generate_cpm_lrc_taps(unsigned samples_per_sym, unsigned L) +{ + std::vector taps(samples_per_sym * L, 1.0/L/samples_per_sym); + for (int 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 +generate_cpm_lsrc_taps(unsigned samples_per_sym, unsigned L, double beta) +{ + double Ls = (double) L * samples_per_sym; + std::vector taps_d(Ls, 0.0); + std::vector taps(Ls, 0.0); + + for (int 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(abs(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 (int 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 +generate_cpm_lrec_taps(unsigned samples_per_sym, unsigned L) +{ + return std::vector(samples_per_sym * L, 1.0/L/samples_per_sym); +} + + +//! Helper function for TFM +double tfm_g0(double k, double sps) +{ + if (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 +generate_cpm_tfm_taps(unsigned sps, unsigned L) +{ + double causal_shift = (double) L * sps / 2; + std::vector taps_d(Ls, 0.0); + std::vector taps(Ls, 0.0); + + double sum = 0; + for (int i = 0; i < sps * L; i++) { + double k = (double)i - 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 (int i = 0; i < samples_per_sym * 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 +generate_cpm_gaussian_taps(unsigned samples_per_sym, unsigned L, double bt) +{ + double Ls = (double) L * samples_per_sym; + std::vector taps_d(Ls, 0.0); + std::vector taps(Ls, 0.0); + + // alpha = sqrt(2/ln(2)) * pi * BT + double alpha = 5.336446256636997 * bt; + for (int 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 +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/hier/gr_cpm.h b/gnuradio-core/src/lib/hier/gr_cpm.h new file mode 100644 index 000000000..f32fa44fd --- /dev/null +++ b/gnuradio-core/src/lib/hier/gr_cpm.h @@ -0,0 +1,75 @@ +/* -*- 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 + +#define M_TWOPI (2*M_PI) + +class gr_cpm +{ + public: + enum cpm_type { + LRC, + LSRC, + LREC, + TFM, + GAUSSIAN, + GENERIC = 999 + }; + + //! Return the taps for an interpolating FIR filter (gr_fir_filter_fff). + // + // These taps represent the phase response for use in a CPM modulator. + // + // Parameters: + // \p type: The CPM type (Rectangular, Raised Cosine, Spectral Raised Cosine, + // Tamed FM or Gaussian). + // \p samples_per_sym: Samples per symbol. + // \p L: The length of the phase response in symbols. + // \p 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 \p L * \p samples_per_sym. 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 taps are normalised s.t. \sum taps = 1; this causes a maximum phase change + // of h*pi between two symbols, where 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. + // + static std::vector + 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/hier/gr_cpm.i b/gnuradio-core/src/lib/hier/gr_cpm.i new file mode 100644 index 000000000..7145f5edd --- /dev/null +++ b/gnuradio-core/src/lib/hier/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 + }; + + std::vector + phase_response(cpm_type type, unsigned samples_per_sym, unsigned L, double beta=0.3); +}; + diff --git a/gnuradio-core/src/lib/hier/gr_cpmmod_bc.cc b/gnuradio-core/src/lib/hier/gr_cpmmod_bc.cc new file mode 100644 index 000000000..8f9d30cda --- /dev/null +++ b/gnuradio-core/src/lib/hier/gr_cpmmod_bc.cc @@ -0,0 +1,74 @@ +/* -*- 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 +#include +#include + + +// Shared pointer constructor +gr_cpmmod_bc_sptr +gr_make_cpmmod_bc(int type, float h, unsigned samples_per_sym, unsigned L, double beta) +{ + return gnuradio::get_initial_sptr(new gr_cpmmod_bc((cpm_type)type, h, samples_per_sym, L, beta)); +} + + +// Parameters: +// - type (raised cosine, spectral raised cosine, rectangular, tamed fm, gmsk. +// - h (modulation index) +// - L (length of filter in symbols) +// - samples per symbol +// - beta (for gmsk: BT product, for the RC's: rolloff) +gr_cpmmod_bc::gr_cpmmod_bc(cpm_type type, double h, unsigned samples_per_sym, + unsigned L, double beta) + : gr_hier_block2("gr_cpmmod_bc", + gr_make_io_signature(1, 1, sizeof(char)), + gr_make_io_signature2(1, 2, sizeof(gr_complex), sizeof(float))), + d_char_to_float(gr_make_char_to_float()), + d_fm(gr_make_frequency_modulator_fc(M_TWOPI * h / samples_per_sym)), + d_taps(generate_cpm_taps(type, samples_per_sym, L, beta)), + d_pulse_shaper(gr_make_interp_fir_filter_fff(samples_per_sym, d_taps)) +{ + switch (type) { + case CPM_LRC: + case CPM_LSRC: + case CPM_LREC: + case CPM_TFM: + case CPM_GMSK: + 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); + + // FIXME is this valid? multiple outputs? + connect(d_pulse_shaper, 0, self(), 1); +} + diff --git a/gnuradio-core/src/lib/hier/gr_cpmmod_bc.h b/gnuradio-core/src/lib/hier/gr_cpmmod_bc.h new file mode 100644 index 000000000..ac96a2d85 --- /dev/null +++ b/gnuradio-core/src/lib/hier/gr_cpmmod_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. + */ + +#include +#include +#include +#include + + +class gr_cpmmod_bc; +typedef boost::shared_ptr gr_cpmmod_bc_sptr; + +enum gr_cpmmod_bc::cpm_type; + +gr_cpmmod_bc_sptr +gr_make_cpmmod_bc(int type, float h, unsigned samples_per_sym, unsigned L, double beta=0.3); + +/*! + * \brief Generic CPM modulator + * + * \ingroup modulation_blk + * + * The input of this block are symbols from an M-ary alphabet + * \pm1, \pm3, ..., \pm(M-1). Usually, M = 2 and therefore, the + * valid inputs are \pm1. + * The output is the phase-modulated signal. + */ +class gr_cpmmod_bc : public gr_hier_block2 +{ + friend gr_cpmmod_bc_sptr gr_make_cpmmod_bc(int type, float h, unsigned samples_per_sym, unsigned L, double beta); + gr_cpmmod_bc(int type, float h, unsigned samples_per_sym, unsigned L, double beta); + + 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; + + std::vector d_taps; + + public: + //! Return the phase response FIR taps + std::vector get_taps() { return d_taps; }; +}; + diff --git a/gnuradio-core/src/lib/hier/gr_cpmmod_bc.i b/gnuradio-core/src/lib/hier/gr_cpmmod_bc.i new file mode 100644 index 000000000..a474aa4d9 --- /dev/null +++ b/gnuradio-core/src/lib/hier/gr_cpmmod_bc.i @@ -0,0 +1,36 @@ +/* -*- 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(gr, cpmmod_bc) + +gr_cpmmod_bc_sptr +gr_make_cpmmod_bc(int type, float h, unsigned samples_per_sym, unsigned L, double beta); + +class gr_cpmmod_bc : public gr_hier_block2 +{ + private: + gr_cpmmod_bc(int type, float h, unsigned samples_per_sym, unsigned L, double beta); + + public: + std::vector get_taps(); +}; + diff --git a/gnuradio-core/src/lib/hier/hier.i b/gnuradio-core/src/lib/hier/hier.i index dbcc8e915..6ac2903fa 100644 --- a/gnuradio-core/src/lib/hier/hier.i +++ b/gnuradio-core/src/lib/hier/hier.i @@ -26,6 +26,9 @@ #endif #include +#include %} %include "gr_channel_model.i" +%include "gr_cpmmod_bc.i" + diff --git a/gnuradio-core/src/lib/hier/qa_gr_cpm.cc b/gnuradio-core/src/lib/hier/qa_gr_cpm.cc new file mode 100644 index 000000000..835ff4b28 --- /dev/null +++ b/gnuradio-core/src/lib/hier/qa_gr_cpm.cc @@ -0,0 +1,108 @@ +/* -*- 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 +#include +#include + +// Check LREC phase response +void +qa_gr_cpm::t1 () +{ + int L = 5; + int samples_per_sym = 4; + std::vector 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); + } +} + + +// Check LRC phase response +void +qa_gr_cpm::t2 () +{ + int L = 5; + int samples_per_sym = 4; + std::vector 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++) { + sum += taps[i]; + } + + CPPUNIT_ASSERT_DOUBLES_EQUAL(sum, 1.0); + CPPUNIT_ASSERT_DOUBLES_EQUAL(taps[L*samples_per_sym/2], 0.05); +} + + +// Check LSRC phase response +void +qa_gr_cpm::t3 () +{ + int L = 5; + int samples_per_sym = 4; + std::vector 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++) { + sum += taps[i]; + } + + CPPUNIT_ASSERT_DOUBLES_EQUAL(sum, 1.0); +} + + +// Check the TFM phase response +void +qa_gr_cpm::t4 () +{ + int L = 5; + int samples_per_sym = 4; + std::vector 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++) { + sum += taps[i]; + } + + CPPUNIT_ASSERT_DOUBLES_EQUAL(sum, 1.0); +} + + +// Check the Gaussian phase response +void +qa_gr_cpm::t5 () +{ + int L = 5; + int samples_per_sym = 4; + std::vector 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++) { + sum += taps[i]; + } + + CPPUNIT_ASSERT_DOUBLES_EQUAL(sum, 1.0, 1e-4); +} + diff --git a/gnuradio-core/src/lib/hier/qa_gr_cpm.h b/gnuradio-core/src/lib/hier/qa_gr_cpm.h new file mode 100644 index 000000000..16965593a --- /dev/null +++ b/gnuradio-core/src/lib/hier/qa_gr_cpm.h @@ -0,0 +1,51 @@ +/* -*- 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_GRI_CPM_H +#define _QA_GRI_CPM_H + +#include +#include + +class qa_gri_cpm : public CppUnit::TestCase { + + CPPUNIT_TEST_SUITE (qa_gri_cpm); + CPPUNIT_TEST (t1); + CPPUNIT_TEST (t2); + CPPUNIT_TEST (t3); + CPPUNIT_TEST (t4); + CPPUNIT_TEST (t5); + CPPUNIT_TEST (t6); + CPPUNIT_TEST_SUITE_END (); + + private: + void t1 (); + void t2 (); + void t3 (); + void t4 (); + void t5 (); + void t6 (); + +}; + + +#endif /* _QA_GRI_CPM_H */ + -- cgit From 5155713e970946e2ce213c4f68ccc44e6737ead0 Mon Sep 17 00:00:00 2001 From: Martin Braun Date: Wed, 8 Dec 2010 19:32:06 +0100 Subject: CPM make checks --- gnuradio-core/src/lib/general/Makefile.am | 5 + gnuradio-core/src/lib/general/gr_cpm.cc | 211 ++++++++++++++++++++++++++++ gnuradio-core/src/lib/general/gr_cpm.h | 81 +++++++++++ gnuradio-core/src/lib/general/gr_cpm.i | 40 ++++++ gnuradio-core/src/lib/general/qa_general.cc | 2 + gnuradio-core/src/lib/general/qa_gr_cpm.cc | 110 +++++++++++++++ gnuradio-core/src/lib/general/qa_gr_cpm.h | 49 +++++++ gnuradio-core/src/lib/hier/Makefile.am | 15 +- gnuradio-core/src/lib/hier/gr_cpm.cc | 210 --------------------------- gnuradio-core/src/lib/hier/gr_cpm.h | 75 ---------- gnuradio-core/src/lib/hier/gr_cpm.i | 40 ------ gnuradio-core/src/lib/hier/gr_cpmmod_bc.cc | 30 ++-- gnuradio-core/src/lib/hier/gr_cpmmod_bc.h | 25 +++- gnuradio-core/src/lib/hier/qa_gr_cpm.cc | 108 -------------- gnuradio-core/src/lib/hier/qa_gr_cpm.h | 51 ------- 15 files changed, 532 insertions(+), 520 deletions(-) create mode 100644 gnuradio-core/src/lib/general/gr_cpm.cc create mode 100644 gnuradio-core/src/lib/general/gr_cpm.h create mode 100644 gnuradio-core/src/lib/general/gr_cpm.i create mode 100644 gnuradio-core/src/lib/general/qa_gr_cpm.cc create mode 100644 gnuradio-core/src/lib/general/qa_gr_cpm.h delete mode 100644 gnuradio-core/src/lib/hier/gr_cpm.cc delete mode 100644 gnuradio-core/src/lib/hier/gr_cpm.h delete mode 100644 gnuradio-core/src/lib/hier/gr_cpm.i delete mode 100644 gnuradio-core/src/lib/hier/qa_gr_cpm.cc delete mode 100644 gnuradio-core/src/lib/hier/qa_gr_cpm.h diff --git a/gnuradio-core/src/lib/general/Makefile.am b/gnuradio-core/src/lib/general/Makefile.am index 3d8a42805..de1df9ffc 100644 --- a/gnuradio-core/src/lib/general/Makefile.am +++ b/gnuradio-core/src/lib/general/Makefile.am @@ -58,6 +58,7 @@ libgeneral_la_SOURCES = \ gr_costas_loop_cc.cc \ gr_count_bits.cc \ gr_cpfsk_bc.cc \ + gr_cpm.cc \ gr_crc32.cc \ gr_ctcss_squelch_ff.cc \ gr_decode_ccsds_27_fb.cc \ @@ -180,6 +181,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 \ @@ -212,6 +214,7 @@ grinclude_HEADERS = \ gr_costas_loop_cc.h \ gr_count_bits.h \ gr_cpfsk_bc.h \ + gr_cpm.h \ gr_crc32.h \ gr_ctcss_squelch_ff.h \ gr_decode_ccsds_27_fb.h \ @@ -349,6 +352,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 \ @@ -382,6 +386,7 @@ swiginclude_HEADERS = \ gr_correlate_access_code_bb.i \ gr_costas_loop_cc.i \ gr_cpfsk_bc.i \ + gr_cpm.i \ gr_crc32.i \ gr_ctcss_squelch_ff.i \ gr_decode_ccsds_27_fb.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..a5d328edf --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_cpm.cc @@ -0,0 +1,211 @@ +/* -*- 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 +#include +#include + + +//! 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 +generate_cpm_lrc_taps(unsigned samples_per_sym, unsigned L) +{ + std::vector 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 +generate_cpm_lsrc_taps(unsigned samples_per_sym, unsigned L, double beta) +{ + double Ls = (double) L * samples_per_sym; + std::vector taps_d(L * samples_per_sym, 0.0); + std::vector 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 +generate_cpm_lrec_taps(unsigned samples_per_sym, unsigned L) +{ + return std::vector(samples_per_sym * L, 1.0/L/samples_per_sym); +} + + +//! Helper function for TFM +double tfm_g0(double k, double sps) +{ + if (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 +generate_cpm_tfm_taps(unsigned sps, unsigned L) +{ + double causal_shift = (double) L * sps / 2; + std::vector taps_d(sps * L, 0.0); + std::vector taps(sps * L, 0.0); + + double sum = 0; + for (unsigned i = 0; i < sps * L; i++) { + double k = (double)i - 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 +generate_cpm_gaussian_taps(unsigned samples_per_sym, unsigned L, double bt) +{ + double Ls = (double) L * samples_per_sym; + std::vector taps_d(L * samples_per_sym, 0.0); + std::vector 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 +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..f9b97f7ea --- /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 + +#define M_TWOPI (2*M_PI) + +class gr_cpm +{ + public: + enum cpm_type { + LRC, + LSRC, + LREC, + TFM, + GAUSSIAN, + GENERIC = 999 + }; + + //! Return the taps for an interpolating FIR filter (gr_fir_filter_fff). + // + // These taps represent the phase response for use in a CPM modulator. + // + // Parameters: + // \p type: The CPM type (Rectangular, Raised Cosine, Spectral Raised Cosine, + // Tamed FM or Gaussian). + // \p samples_per_sym: Samples per symbol. + // \p L: The length of the phase response in symbols. + // \p 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 \p L * \p samples_per_sym. 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 taps are normalised s.t. \sum taps = 1; this causes a maximum phase change + // of h*pi between two symbols, where 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 + 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..7145f5edd --- /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 + }; + + std::vector + phase_response(cpm_type type, unsigned samples_per_sym, unsigned L, double beta=0.3); +}; + 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 #include #include +#include #include #include #include @@ -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..20d72968a --- /dev/null +++ b/gnuradio-core/src/lib/general/qa_gr_cpm.cc @@ -0,0 +1,110 @@ +/* -*- 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 +#include +#include + +const double DELTA = 1e-5; + +// Check LREC phase response +void +qa_gr_cpm::t1 () +{ + int L = 5; + int samples_per_sym = 4; + std::vector 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 () +{ + int L = 5; + int samples_per_sym = 4; + std::vector 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++) { + sum += taps[i]; + } + + CPPUNIT_ASSERT_DOUBLES_EQUAL(sum, 1.0, DELTA); + CPPUNIT_ASSERT_DOUBLES_EQUAL(taps[L*samples_per_sym/2], 0.1, DELTA); +} + + +// Check LSRC phase response +void +qa_gr_cpm::t3 () +{ + int L = 5; + int samples_per_sym = 4; + std::vector 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++) { + sum += taps[i]; + } + + CPPUNIT_ASSERT_DOUBLES_EQUAL(sum, 1.0, DELTA); +} + + +// Check the TFM phase response +void +qa_gr_cpm::t4 () +{ + int L = 5; + int samples_per_sym = 4; + std::vector 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++) { + sum += taps[i]; + } + + CPPUNIT_ASSERT_DOUBLES_EQUAL(sum, 1.0, DELTA); +} + + +// Check the Gaussian phase response +void +qa_gr_cpm::t5 () +{ + int L = 5; + int samples_per_sym = 4; + std::vector 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++) { + sum += taps[i]; + } + + CPPUNIT_ASSERT_DOUBLES_EQUAL(sum, 1.0, 1e-4); +} + 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 +#include + +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 3a7c9f592..a4b634139 100644 --- a/gnuradio-core/src/lib/hier/Makefile.am +++ b/gnuradio-core/src/lib/hier/Makefile.am @@ -24,16 +24,14 @@ include $(top_srcdir)/Makefile.common AM_CPPFLAGS = $(STD_DEFINES_AND_INCLUDES) $(WITH_INCLUDES) -noinst_LTLIBRARIES = libhier.la libhier-qa.la +noinst_LTLIBRARIES = libhier.la libhier_la_SOURCES = \ gr_channel_model.cc \ - gr_cpm.cc \ gr_cpmmod_bc.cc grinclude_HEADERS = \ gr_channel_model.h \ - gr_cpm.h \ gr_cpmmod_bc.h @@ -41,15 +39,6 @@ if PYTHON swiginclude_HEADERS = \ hier.i \ gr_channel_model.i \ - gr_cpmmod_bc.i \ - gr_cpm.i + gr_cpmmod_bc.i endif - -libhier_qa_la_SOURCES = \ - qa_gr_cpm.cc - -noinst_HEADERS = \ - qa_gr_cpm.h - - diff --git a/gnuradio-core/src/lib/hier/gr_cpm.cc b/gnuradio-core/src/lib/hier/gr_cpm.cc deleted file mode 100644 index 5eda182b2..000000000 --- a/gnuradio-core/src/lib/hier/gr_cpm.cc +++ /dev/null @@ -1,210 +0,0 @@ -/* -*- 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 -#include -#include - - -//! 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 -generate_cpm_lrc_taps(unsigned samples_per_sym, unsigned L) -{ - std::vector taps(samples_per_sym * L, 1.0/L/samples_per_sym); - for (int 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 -generate_cpm_lsrc_taps(unsigned samples_per_sym, unsigned L, double beta) -{ - double Ls = (double) L * samples_per_sym; - std::vector taps_d(Ls, 0.0); - std::vector taps(Ls, 0.0); - - for (int 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(abs(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 (int 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 -generate_cpm_lrec_taps(unsigned samples_per_sym, unsigned L) -{ - return std::vector(samples_per_sym * L, 1.0/L/samples_per_sym); -} - - -//! Helper function for TFM -double tfm_g0(double k, double sps) -{ - if (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 -generate_cpm_tfm_taps(unsigned sps, unsigned L) -{ - double causal_shift = (double) L * sps / 2; - std::vector taps_d(Ls, 0.0); - std::vector taps(Ls, 0.0); - - double sum = 0; - for (int i = 0; i < sps * L; i++) { - double k = (double)i - 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 (int i = 0; i < samples_per_sym * 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 -generate_cpm_gaussian_taps(unsigned samples_per_sym, unsigned L, double bt) -{ - double Ls = (double) L * samples_per_sym; - std::vector taps_d(Ls, 0.0); - std::vector taps(Ls, 0.0); - - // alpha = sqrt(2/ln(2)) * pi * BT - double alpha = 5.336446256636997 * bt; - for (int 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 -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/hier/gr_cpm.h b/gnuradio-core/src/lib/hier/gr_cpm.h deleted file mode 100644 index f32fa44fd..000000000 --- a/gnuradio-core/src/lib/hier/gr_cpm.h +++ /dev/null @@ -1,75 +0,0 @@ -/* -*- 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 - -#define M_TWOPI (2*M_PI) - -class gr_cpm -{ - public: - enum cpm_type { - LRC, - LSRC, - LREC, - TFM, - GAUSSIAN, - GENERIC = 999 - }; - - //! Return the taps for an interpolating FIR filter (gr_fir_filter_fff). - // - // These taps represent the phase response for use in a CPM modulator. - // - // Parameters: - // \p type: The CPM type (Rectangular, Raised Cosine, Spectral Raised Cosine, - // Tamed FM or Gaussian). - // \p samples_per_sym: Samples per symbol. - // \p L: The length of the phase response in symbols. - // \p 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 \p L * \p samples_per_sym. 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 taps are normalised s.t. \sum taps = 1; this causes a maximum phase change - // of h*pi between two symbols, where 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. - // - static std::vector - 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/hier/gr_cpm.i b/gnuradio-core/src/lib/hier/gr_cpm.i deleted file mode 100644 index 7145f5edd..000000000 --- a/gnuradio-core/src/lib/hier/gr_cpm.i +++ /dev/null @@ -1,40 +0,0 @@ -/* -*- 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 - }; - - std::vector - phase_response(cpm_type type, unsigned samples_per_sym, unsigned L, double beta=0.3); -}; - diff --git a/gnuradio-core/src/lib/hier/gr_cpmmod_bc.cc b/gnuradio-core/src/lib/hier/gr_cpmmod_bc.cc index 8f9d30cda..a145aaeec 100644 --- a/gnuradio-core/src/lib/hier/gr_cpmmod_bc.cc +++ b/gnuradio-core/src/lib/hier/gr_cpmmod_bc.cc @@ -22,7 +22,6 @@ #include "config.h" #endif -#include #include #include @@ -31,32 +30,26 @@ gr_cpmmod_bc_sptr gr_make_cpmmod_bc(int type, float h, unsigned samples_per_sym, unsigned L, double beta) { - return gnuradio::get_initial_sptr(new gr_cpmmod_bc((cpm_type)type, h, samples_per_sym, L, beta)); + return gnuradio::get_initial_sptr(new gr_cpmmod_bc((gr_cpm::cpm_type)type, h, samples_per_sym, L, beta)); } -// Parameters: -// - type (raised cosine, spectral raised cosine, rectangular, tamed fm, gmsk. -// - h (modulation index) -// - L (length of filter in symbols) -// - samples per symbol -// - beta (for gmsk: BT product, for the RC's: rolloff) -gr_cpmmod_bc::gr_cpmmod_bc(cpm_type type, double h, unsigned samples_per_sym, +gr_cpmmod_bc::gr_cpmmod_bc(gr_cpm::cpm_type type, float h, unsigned samples_per_sym, unsigned L, double beta) : gr_hier_block2("gr_cpmmod_bc", gr_make_io_signature(1, 1, sizeof(char)), gr_make_io_signature2(1, 2, 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_fm(gr_make_frequency_modulator_fc(M_TWOPI * h / samples_per_sym)), - d_taps(generate_cpm_taps(type, samples_per_sym, L, beta)), - d_pulse_shaper(gr_make_interp_fir_filter_fff(samples_per_sym, d_taps)) + d_pulse_shaper(gr_make_interp_fir_filter_fff(samples_per_sym, d_taps)), + d_fm(gr_make_frequency_modulator_fc(M_TWOPI * h / samples_per_sym)) { switch (type) { - case CPM_LRC: - case CPM_LSRC: - case CPM_LREC: - case CPM_TFM: - case CPM_GMSK: + case gr_cpm::LRC: + case gr_cpm::LSRC: + case gr_cpm::LREC: + case gr_cpm::TFM: + case gr_cpm::GAUSSIAN: break; default: @@ -67,8 +60,5 @@ gr_cpmmod_bc::gr_cpmmod_bc(cpm_type type, double h, unsigned samples_per_sym, connect(d_char_to_float, 0, d_pulse_shaper, 0); connect(d_pulse_shaper, 0, d_fm, 0); connect(d_fm, 0, self(), 0); - - // FIXME is this valid? multiple outputs? - connect(d_pulse_shaper, 0, self(), 1); } diff --git a/gnuradio-core/src/lib/hier/gr_cpmmod_bc.h b/gnuradio-core/src/lib/hier/gr_cpmmod_bc.h index ac96a2d85..77512d8d3 100644 --- a/gnuradio-core/src/lib/hier/gr_cpmmod_bc.h +++ b/gnuradio-core/src/lib/hier/gr_cpmmod_bc.h @@ -24,12 +24,12 @@ #include #include #include +#include class gr_cpmmod_bc; typedef boost::shared_ptr gr_cpmmod_bc_sptr; -enum gr_cpmmod_bc::cpm_type; gr_cpmmod_bc_sptr gr_make_cpmmod_bc(int type, float h, unsigned samples_per_sym, unsigned L, double beta=0.3); @@ -39,21 +39,40 @@ gr_make_cpmmod_bc(int type, float h, unsigned samples_per_sym, unsigned L, doubl * * \ingroup modulation_blk * + * Parameters: + * * \p type: The modulation type. Can be one of LREC, LRC, LSRC, TFM or GAUSSIAN. See + * gr_cpm::phase_response() for a detailed description. + * * \p h: The modulation index. h*PI is the maximum phase change that can occur + * between two symbols, i.e., if you only send ones, the phase will increase + * by h*PI every \p samples_per_sym samples. Set this to 0.5 for Minimum Shift + * Keying variants. + * * \p samples_per_sym: Samples per symbol. + * * \p L: The length of the phase duration in symbols. For L=1, this yields full- + * response CPM symbols, for L > 1, it yields partial-response. + * * \p 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 * \pm1, \pm3, ..., \pm(M-1). Usually, M = 2 and therefore, the * valid inputs are \pm1. + * The modulator will silently accept any other inputs, though. * The output is the phase-modulated signal. */ class gr_cpmmod_bc : public gr_hier_block2 { friend gr_cpmmod_bc_sptr gr_make_cpmmod_bc(int type, float h, unsigned samples_per_sym, unsigned L, double beta); - gr_cpmmod_bc(int type, float h, unsigned samples_per_sym, unsigned L, double beta); + gr_cpmmod_bc(gr_cpm::cpm_type type, float h, unsigned samples_per_sym, unsigned L, double beta); + + std::vector 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; - std::vector d_taps; public: //! Return the phase response FIR taps diff --git a/gnuradio-core/src/lib/hier/qa_gr_cpm.cc b/gnuradio-core/src/lib/hier/qa_gr_cpm.cc deleted file mode 100644 index 835ff4b28..000000000 --- a/gnuradio-core/src/lib/hier/qa_gr_cpm.cc +++ /dev/null @@ -1,108 +0,0 @@ -/* -*- 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 -#include -#include - -// Check LREC phase response -void -qa_gr_cpm::t1 () -{ - int L = 5; - int samples_per_sym = 4; - std::vector 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); - } -} - - -// Check LRC phase response -void -qa_gr_cpm::t2 () -{ - int L = 5; - int samples_per_sym = 4; - std::vector 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++) { - sum += taps[i]; - } - - CPPUNIT_ASSERT_DOUBLES_EQUAL(sum, 1.0); - CPPUNIT_ASSERT_DOUBLES_EQUAL(taps[L*samples_per_sym/2], 0.05); -} - - -// Check LSRC phase response -void -qa_gr_cpm::t3 () -{ - int L = 5; - int samples_per_sym = 4; - std::vector 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++) { - sum += taps[i]; - } - - CPPUNIT_ASSERT_DOUBLES_EQUAL(sum, 1.0); -} - - -// Check the TFM phase response -void -qa_gr_cpm::t4 () -{ - int L = 5; - int samples_per_sym = 4; - std::vector 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++) { - sum += taps[i]; - } - - CPPUNIT_ASSERT_DOUBLES_EQUAL(sum, 1.0); -} - - -// Check the Gaussian phase response -void -qa_gr_cpm::t5 () -{ - int L = 5; - int samples_per_sym = 4; - std::vector 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++) { - sum += taps[i]; - } - - CPPUNIT_ASSERT_DOUBLES_EQUAL(sum, 1.0, 1e-4); -} - diff --git a/gnuradio-core/src/lib/hier/qa_gr_cpm.h b/gnuradio-core/src/lib/hier/qa_gr_cpm.h deleted file mode 100644 index 16965593a..000000000 --- a/gnuradio-core/src/lib/hier/qa_gr_cpm.h +++ /dev/null @@ -1,51 +0,0 @@ -/* -*- 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_GRI_CPM_H -#define _QA_GRI_CPM_H - -#include -#include - -class qa_gri_cpm : public CppUnit::TestCase { - - CPPUNIT_TEST_SUITE (qa_gri_cpm); - CPPUNIT_TEST (t1); - CPPUNIT_TEST (t2); - CPPUNIT_TEST (t3); - CPPUNIT_TEST (t4); - CPPUNIT_TEST (t5); - CPPUNIT_TEST (t6); - CPPUNIT_TEST_SUITE_END (); - - private: - void t1 (); - void t2 (); - void t3 (); - void t4 (); - void t5 (); - void t6 (); - -}; - - -#endif /* _QA_GRI_CPM_H */ - -- cgit From dd35f129cc0ecbbf092a25a60414fef133e6dc04 Mon Sep 17 00:00:00 2001 From: Martin Braun Date: Thu, 9 Dec 2010 09:54:42 +0100 Subject: more elaborate checks, they also work now --- gnuradio-core/src/lib/general/gr_cpm.cc | 6 +-- gnuradio-core/src/lib/general/qa_gr_cpm.cc | 62 ++++++++++++++++++++++++------ 2 files changed, 53 insertions(+), 15 deletions(-) diff --git a/gnuradio-core/src/lib/general/gr_cpm.cc b/gnuradio-core/src/lib/general/gr_cpm.cc index a5d328edf..f2d032a22 100644 --- a/gnuradio-core/src/lib/general/gr_cpm.cc +++ b/gnuradio-core/src/lib/general/gr_cpm.cc @@ -113,7 +113,7 @@ generate_cpm_lrec_taps(unsigned samples_per_sym, unsigned L) //! Helper function for TFM double tfm_g0(double k, double sps) { - if (k < 2 * DBL_EPSILON) { + if (fabs(k) < 2 * DBL_EPSILON) { return 1.145393004159143; // 1 + pi^2/48 / sqrt(2) } @@ -131,13 +131,13 @@ double tfm_g0(double k, double sps) std::vector generate_cpm_tfm_taps(unsigned sps, unsigned L) { - double causal_shift = (double) L * sps / 2; + unsigned causal_shift = sps * L / 2; std::vector taps_d(sps * L, 0.0); std::vector taps(sps * L, 0.0); double sum = 0; for (unsigned i = 0; i < sps * L; i++) { - double k = (double)i - causal_shift; // Causal to acausal + double k = (double)(((int)i) - ((int)causal_shift)); // Causal to acausal taps_d[i] = tfm_g0(k - sps, sps) + 2 * tfm_g0(k, sps) + diff --git a/gnuradio-core/src/lib/general/qa_gr_cpm.cc b/gnuradio-core/src/lib/general/qa_gr_cpm.cc index 20d72968a..fe76feadd 100644 --- a/gnuradio-core/src/lib/general/qa_gr_cpm.cc +++ b/gnuradio-core/src/lib/general/qa_gr_cpm.cc @@ -24,14 +24,53 @@ #include #include +#include +using std::cout; +using std::endl; + 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 () { - int L = 5; - int samples_per_sym = 4; std::vector taps(gr_cpm::phase_response(gr_cpm::LREC, samples_per_sym, L)); for (int i = 0; i < L * samples_per_sym; i++) { @@ -44,17 +83,15 @@ qa_gr_cpm::t1 () void qa_gr_cpm::t2 () { - int L = 5; - int samples_per_sym = 4; std::vector 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); - CPPUNIT_ASSERT_DOUBLES_EQUAL(taps[L*samples_per_sym/2], 0.1, DELTA); } @@ -62,12 +99,11 @@ qa_gr_cpm::t2 () void qa_gr_cpm::t3 () { - int L = 5; - int samples_per_sym = 4; std::vector 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]; } @@ -79,12 +115,13 @@ qa_gr_cpm::t3 () void qa_gr_cpm::t4 () { - int L = 5; - int samples_per_sym = 4; std::vector taps(gr_cpm::phase_response(gr_cpm::TFM, samples_per_sym, L)); float sum = 0; + cout << "TFM" << endl; for (int i = 0; i < L * samples_per_sym; i++) { + cout << "i=" << i << " " << taps[i] << "?=" << taps_tfm[i] << endl; + CPPUNIT_ASSERT_DOUBLES_EQUAL(taps[i], taps_tfm[i], DELTA); sum += taps[i]; } @@ -96,15 +133,16 @@ qa_gr_cpm::t4 () void qa_gr_cpm::t5 () { - int L = 5; - int samples_per_sym = 4; std::vector 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, 1e-4); + // Need to cut this guy some slack; in theory, sum only equals one for + // L => infinity + CPPUNIT_ASSERT_DOUBLES_EQUAL(sum, 1.0, DELTA); } -- cgit From 144ef2dbe12de3f1f784fb2e76771b1e174deb41 Mon Sep 17 00:00:00 2001 From: Martin Braun Date: Thu, 9 Dec 2010 13:54:22 +0100 Subject: All CPM stuff included (C++/GRC/Python), tests pass --- gnuradio-core/src/lib/general/general.i | 4 +- gnuradio-core/src/lib/general/qa_gr_cpm.cc | 6 -- gnuradio-core/src/lib/hier/Makefile.am | 3 + gnuradio-core/src/lib/hier/gr_cpmmod_bc.cc | 2 +- gnuradio-core/src/lib/hier/gr_cpmmod_bc.h | 18 ++++-- gnuradio-core/src/lib/hier/gr_cpmmod_bc.i | 2 +- gnuradio-core/src/lib/hier/gr_gmskmod_bc.cc | 41 +++++++++++++ gnuradio-core/src/lib/hier/gr_gmskmod_bc.h | 65 ++++++++++++++++++++ gnuradio-core/src/lib/hier/gr_gmskmod_bc.i | 36 +++++++++++ gnuradio-core/src/lib/hier/hier.i | 2 + gnuradio-core/src/python/gnuradio/gr/qa_cpm.py | 85 ++++++++++++++++++++++++++ grc/blocks/gr_cpmmod_bc.xml | 69 +++++++++++++++++++++ grc/blocks/gr_gmskmod_bc.xml | 38 ++++++++++++ 13 files changed, 356 insertions(+), 15 deletions(-) create mode 100644 gnuradio-core/src/lib/hier/gr_gmskmod_bc.cc create mode 100644 gnuradio-core/src/lib/hier/gr_gmskmod_bc.h create mode 100644 gnuradio-core/src/lib/hier/gr_gmskmod_bc.i create mode 100755 gnuradio-core/src/python/gnuradio/gr/qa_cpm.py create mode 100644 grc/blocks/gr_cpmmod_bc.xml create mode 100644 grc/blocks/gr_gmskmod_bc.xml diff --git a/gnuradio-core/src/lib/general/general.i b/gnuradio-core/src/lib/general/general.i index 68cafce2e..8c7f31c62 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 * @@ -141,6 +141,7 @@ #include #include #include +#include %} %include "gr_nop.i" @@ -262,3 +263,4 @@ %include "gr_copy.i" %include "gr_fll_band_edge_cc.i" %include "gr_additive_scrambler_bb.i" +%include "gr_cpm.i" diff --git a/gnuradio-core/src/lib/general/qa_gr_cpm.cc b/gnuradio-core/src/lib/general/qa_gr_cpm.cc index fe76feadd..ae391c48c 100644 --- a/gnuradio-core/src/lib/general/qa_gr_cpm.cc +++ b/gnuradio-core/src/lib/general/qa_gr_cpm.cc @@ -24,10 +24,6 @@ #include #include -#include -using std::cout; -using std::endl; - const double DELTA = 1e-5; const int L = 5; const int samples_per_sym = 4; @@ -118,9 +114,7 @@ qa_gr_cpm::t4 () std::vector taps(gr_cpm::phase_response(gr_cpm::TFM, samples_per_sym, L)); float sum = 0; - cout << "TFM" << endl; for (int i = 0; i < L * samples_per_sym; i++) { - cout << "i=" << i << " " << taps[i] << "?=" << taps_tfm[i] << endl; CPPUNIT_ASSERT_DOUBLES_EQUAL(taps[i], taps_tfm[i], DELTA); sum += taps[i]; } diff --git a/gnuradio-core/src/lib/hier/Makefile.am b/gnuradio-core/src/lib/hier/Makefile.am index a4b634139..d46fb8fd9 100644 --- a/gnuradio-core/src/lib/hier/Makefile.am +++ b/gnuradio-core/src/lib/hier/Makefile.am @@ -28,10 +28,12 @@ noinst_LTLIBRARIES = libhier.la libhier_la_SOURCES = \ gr_channel_model.cc \ + gr_gmskmod_bc.cc \ gr_cpmmod_bc.cc grinclude_HEADERS = \ gr_channel_model.h \ + gr_gmskmod_bc.h \ gr_cpmmod_bc.h @@ -39,6 +41,7 @@ if PYTHON swiginclude_HEADERS = \ hier.i \ gr_channel_model.i \ + gr_gmskmod_bc.i \ gr_cpmmod_bc.i endif diff --git a/gnuradio-core/src/lib/hier/gr_cpmmod_bc.cc b/gnuradio-core/src/lib/hier/gr_cpmmod_bc.cc index a145aaeec..d14deee34 100644 --- a/gnuradio-core/src/lib/hier/gr_cpmmod_bc.cc +++ b/gnuradio-core/src/lib/hier/gr_cpmmod_bc.cc @@ -38,7 +38,7 @@ gr_cpmmod_bc::gr_cpmmod_bc(gr_cpm::cpm_type type, float h, unsigned samples_per_ unsigned L, double beta) : gr_hier_block2("gr_cpmmod_bc", gr_make_io_signature(1, 1, sizeof(char)), - gr_make_io_signature2(1, 2, sizeof(gr_complex), sizeof(float))), + 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)), diff --git a/gnuradio-core/src/lib/hier/gr_cpmmod_bc.h b/gnuradio-core/src/lib/hier/gr_cpmmod_bc.h index 77512d8d3..f32d0fdca 100644 --- a/gnuradio-core/src/lib/hier/gr_cpmmod_bc.h +++ b/gnuradio-core/src/lib/hier/gr_cpmmod_bc.h @@ -20,7 +20,10 @@ * Boston, MA 02110-1301, USA. */ -#include +#ifndef INCLUDED_GR_CPMMOD_BC_H +#define INCLUDED_GR_CPMMOD_BC_H + +#include #include #include #include @@ -34,6 +37,7 @@ typedef boost::shared_ptr gr_cpmmod_bc_sptr; gr_cpmmod_bc_sptr gr_make_cpmmod_bc(int type, float h, unsigned samples_per_sym, unsigned L, double beta=0.3); + /*! * \brief Generic CPM modulator * @@ -48,7 +52,7 @@ gr_make_cpmmod_bc(int type, float h, unsigned samples_per_sym, unsigned L, doubl * Keying variants. * * \p samples_per_sym: Samples per symbol. * * \p L: The length of the phase duration in symbols. For L=1, this yields full- - * response CPM symbols, for L > 1, it yields partial-response. + * response CPM symbols, for L > 1, partial-response. * * \p beta: For LSRC, this is the rolloff factor. For Gaussian pulses, this is the 3 dB * time-bandwidth product. * @@ -57,25 +61,27 @@ gr_make_cpmmod_bc(int type, float h, unsigned samples_per_sym, unsigned L, doubl * * 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 - * \pm1, \pm3, ..., \pm(M-1). Usually, M = 2 and therefore, the - * valid inputs are \pm1. + * +/-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 gr_cpmmod_bc : public gr_hier_block2 { friend gr_cpmmod_bc_sptr gr_make_cpmmod_bc(int type, float h, unsigned samples_per_sym, unsigned L, double beta); - gr_cpmmod_bc(gr_cpm::cpm_type type, float h, unsigned samples_per_sym, unsigned L, double beta); std::vector 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: + gr_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 get_taps() { return d_taps; }; }; +#endif /* INCLUDED_GR_CPMMOD_BC_H */ + diff --git a/gnuradio-core/src/lib/hier/gr_cpmmod_bc.i b/gnuradio-core/src/lib/hier/gr_cpmmod_bc.i index a474aa4d9..55116cda7 100644 --- a/gnuradio-core/src/lib/hier/gr_cpmmod_bc.i +++ b/gnuradio-core/src/lib/hier/gr_cpmmod_bc.i @@ -23,7 +23,7 @@ GR_SWIG_BLOCK_MAGIC(gr, cpmmod_bc) gr_cpmmod_bc_sptr -gr_make_cpmmod_bc(int type, float h, unsigned samples_per_sym, unsigned L, double beta); +gr_make_cpmmod_bc(int type, float h, unsigned samples_per_sym, unsigned L, double beta=0.3); class gr_cpmmod_bc : public gr_hier_block2 { diff --git a/gnuradio-core/src/lib/hier/gr_gmskmod_bc.cc b/gnuradio-core/src/lib/hier/gr_gmskmod_bc.cc new file mode 100644 index 000000000..9324edc96 --- /dev/null +++ b/gnuradio-core/src/lib/hier/gr_gmskmod_bc.cc @@ -0,0 +1,41 @@ +/* -*- 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 +#include + + +// Shared pointer constructor +gr_gmskmod_bc_sptr +gr_make_gmskmod_bc(unsigned samples_per_sym, unsigned L, double bt) +{ + return gnuradio::get_initial_sptr(new gr_gmskmod_bc(samples_per_sym, L, bt)); +} + + +gr_gmskmod_bc::gr_gmskmod_bc(unsigned samples_per_sym, unsigned L, double bt) + : gr_cpmmod_bc(gr_cpm::GAUSSIAN, 0.5, samples_per_sym, L, bt) +{ +} + diff --git a/gnuradio-core/src/lib/hier/gr_gmskmod_bc.h b/gnuradio-core/src/lib/hier/gr_gmskmod_bc.h new file mode 100644 index 000000000..bfe0513e1 --- /dev/null +++ b/gnuradio-core/src/lib/hier/gr_gmskmod_bc.h @@ -0,0 +1,65 @@ +/* -*- 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_GR_GMSKMOD_BC_H +#define INCLUDED_GR_GMSKMOD_BC_H + +#include + +class gr_gmskmod_bc; +typedef boost::shared_ptr gr_gmskmod_bc_sptr; + + +gr_gmskmod_bc_sptr +gr_make_gmskmod_bc(unsigned samples_per_sym=2, unsigned L=4, double bt=0.3); + + +/*! + * \brief GMSK modulator + * + * \ingroup modulation_blk + * + * Parameters: + * * \p samples_per_sym: Samples per symbol. + * * \p L: The length of the phase duration in symbols. The Gaussian pulse is truncated + * after L symbols. + * * \p bt: 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 gr_gmskmod_bc : public gr_cpmmod_bc +{ + friend gr_gmskmod_bc_sptr gr_make_gmskmod_bc(unsigned samples_per_sym, unsigned L, double bt); + gr_gmskmod_bc(unsigned samples_per_sym, unsigned L, double bt); +}; + +#endif /* INCLUDED_GR_GMSKMOD_BC_H */ + diff --git a/gnuradio-core/src/lib/hier/gr_gmskmod_bc.i b/gnuradio-core/src/lib/hier/gr_gmskmod_bc.i new file mode 100644 index 000000000..7fb16839b --- /dev/null +++ b/gnuradio-core/src/lib/hier/gr_gmskmod_bc.i @@ -0,0 +1,36 @@ +/* -*- 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(gr, gmskmod_bc) + +gr_gmskmod_bc_sptr +gr_make_gmskmod_bc(unsigned samples_per_sym=2, unsigned L=4, double bt=0.3); + +class gr_gmskmod_bc : public gr_hier_block2 +{ + private: + gr_cpmmod_bc(int type, float h, unsigned samples_per_sym, unsigned L, double beta); + + public: + std::vector get_taps(); +}; + diff --git a/gnuradio-core/src/lib/hier/hier.i b/gnuradio-core/src/lib/hier/hier.i index 6ac2903fa..b8915e15b 100644 --- a/gnuradio-core/src/lib/hier/hier.i +++ b/gnuradio-core/src/lib/hier/hier.i @@ -27,8 +27,10 @@ #include #include +#include %} %include "gr_channel_model.i" %include "gr_cpmmod_bc.i" +%include "gr_gmskmod_bc.i" diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_cpm.py b/gnuradio-core/src/python/gnuradio/gr/qa_cpm.py new file mode 100755 index 000000000..9cc22c257 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_cpm.py @@ -0,0 +1,85 @@ +#!/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 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 = 5 + in_bits = (1,) * 20 + src = gr.vector_source_b(in_bits, False) + cpm = gr.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 + in_bits = (1,) * 20 + src = gr.vector_source_b(in_bits, False) + gmsk = gr.gmskmod_bc(sps, 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") + + +if __name__ == '__main__': + gr_unittest.run(test_cpm, "test_cpm.xml") + diff --git a/grc/blocks/gr_cpmmod_bc.xml b/grc/blocks/gr_cpmmod_bc.xml new file mode 100644 index 000000000..7ebb7e179 --- /dev/null +++ b/grc/blocks/gr_cpmmod_bc.xml @@ -0,0 +1,69 @@ + + + + Continuous Phase Modulation + gr_cpmmod_bc + from gnuradio import gr + gr.cpmmod_bc($type, $mod_index, $samples_per_symbol, $L, $beta) + + CPM Type + type + enum + + + + + + + + Modulation Index + mod_index + real + 0.5 + + + Samples/Symbol + samples_per_symbol + 4 + int + + + Pulse Duration (Symbols) + L + 5 + int + + + Phase Response Parameter (BT or Beta) + beta + real + 0.3 + + + in + byte + + + out + complex + + diff --git a/grc/blocks/gr_gmskmod_bc.xml b/grc/blocks/gr_gmskmod_bc.xml new file mode 100644 index 000000000..00195a12f --- /dev/null +++ b/grc/blocks/gr_gmskmod_bc.xml @@ -0,0 +1,38 @@ + + + + GMSK + gr_gmskmod_bc + from gnuradio import gr + gr.gmskmod_bc($samples_per_symbol, $L, $bt) + + Samples/Symbol + samples_per_symbol + 4 + int + + + Pulse Duration (Symbols) + L + 5 + int + + + 3 dB Time-Bandwith Product + bt + real + 0.3 + + + in + byte + + + out + complex + + -- cgit From c96ea6723a3e7ce6dc5bbccb4386647a088186aa Mon Sep 17 00:00:00 2001 From: Martin Braun Date: Fri, 10 Dec 2010 10:44:08 +0100 Subject: updated doxygen blocks, changed param order for gmsk --- gnuradio-core/src/lib/general/gr_cpm.h | 81 +++++++++++++------------- gnuradio-core/src/lib/hier/gr_cpmmod_bc.h | 27 +++++---- gnuradio-core/src/lib/hier/gr_gmskmod_bc.cc | 6 +- gnuradio-core/src/lib/hier/gr_gmskmod_bc.h | 28 ++++----- gnuradio-core/src/lib/hier/gr_gmskmod_bc.i | 4 +- gnuradio-core/src/python/gnuradio/gr/qa_cpm.py | 3 +- 6 files changed, 73 insertions(+), 76 deletions(-) diff --git a/gnuradio-core/src/lib/general/gr_cpm.h b/gnuradio-core/src/lib/general/gr_cpm.h index f9b97f7ea..09598024a 100644 --- a/gnuradio-core/src/lib/general/gr_cpm.h +++ b/gnuradio-core/src/lib/general/gr_cpm.h @@ -1,17 +1,17 @@ /* -*- 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, @@ -24,7 +24,9 @@ #include -#define M_TWOPI (2*M_PI) +#ifndef M_TWOPI +# define M_TWOPI (2*M_PI) +#endif class gr_cpm { @@ -38,41 +40,42 @@ class gr_cpm GENERIC = 999 }; - //! Return the taps for an interpolating FIR filter (gr_fir_filter_fff). - // - // These taps represent the phase response for use in a CPM modulator. - // - // Parameters: - // \p type: The CPM type (Rectangular, Raised Cosine, Spectral Raised Cosine, - // Tamed FM or Gaussian). - // \p samples_per_sym: Samples per symbol. - // \p L: The length of the phase response in symbols. - // \p 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 \p L * \p samples_per_sym. 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 taps are normalised s.t. \sum taps = 1; this causes a maximum phase change - // of h*pi between two symbols, where 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 + /*! \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 phase_response(cpm_type type, unsigned samples_per_sym, unsigned L, double beta=0.3); }; diff --git a/gnuradio-core/src/lib/hier/gr_cpmmod_bc.h b/gnuradio-core/src/lib/hier/gr_cpmmod_bc.h index f32d0fdca..210b30612 100644 --- a/gnuradio-core/src/lib/hier/gr_cpmmod_bc.h +++ b/gnuradio-core/src/lib/hier/gr_cpmmod_bc.h @@ -43,22 +43,21 @@ gr_make_cpmmod_bc(int type, float h, unsigned samples_per_sym, unsigned L, doubl * * \ingroup modulation_blk * - * Parameters: - * * \p type: The modulation type. Can be one of LREC, LRC, LSRC, TFM or GAUSSIAN. See - * gr_cpm::phase_response() for a detailed description. - * * \p h: The modulation index. h*PI is the maximum phase change that can occur - * between two symbols, i.e., if you only send ones, the phase will increase - * by h*PI every \p samples_per_sym samples. Set this to 0.5 for Minimum Shift - * Keying variants. - * * \p samples_per_sym: Samples per symbol. - * * \p L: The length of the phase duration in symbols. For L=1, this yields full- - * response CPM symbols, for L > 1, partial-response. - * * \p beta: For LSRC, this is the rolloff factor. For Gaussian pulses, this is the 3 dB - * time-bandwidth product. + * \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. + * - 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 diff --git a/gnuradio-core/src/lib/hier/gr_gmskmod_bc.cc b/gnuradio-core/src/lib/hier/gr_gmskmod_bc.cc index 9324edc96..37128d99c 100644 --- a/gnuradio-core/src/lib/hier/gr_gmskmod_bc.cc +++ b/gnuradio-core/src/lib/hier/gr_gmskmod_bc.cc @@ -28,13 +28,13 @@ // Shared pointer constructor gr_gmskmod_bc_sptr -gr_make_gmskmod_bc(unsigned samples_per_sym, unsigned L, double bt) +gr_make_gmskmod_bc(unsigned samples_per_sym, double bt, unsigned L) { - return gnuradio::get_initial_sptr(new gr_gmskmod_bc(samples_per_sym, L, bt)); + return gnuradio::get_initial_sptr(new gr_gmskmod_bc(samples_per_sym, bt, L)); } -gr_gmskmod_bc::gr_gmskmod_bc(unsigned samples_per_sym, unsigned L, double bt) +gr_gmskmod_bc::gr_gmskmod_bc(unsigned samples_per_sym, double bt, unsigned L) : gr_cpmmod_bc(gr_cpm::GAUSSIAN, 0.5, samples_per_sym, L, bt) { } diff --git a/gnuradio-core/src/lib/hier/gr_gmskmod_bc.h b/gnuradio-core/src/lib/hier/gr_gmskmod_bc.h index bfe0513e1..39bd576e2 100644 --- a/gnuradio-core/src/lib/hier/gr_gmskmod_bc.h +++ b/gnuradio-core/src/lib/hier/gr_gmskmod_bc.h @@ -1,19 +1,19 @@ /* -*- 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, @@ -30,7 +30,7 @@ typedef boost::shared_ptr gr_gmskmod_bc_sptr; gr_gmskmod_bc_sptr -gr_make_gmskmod_bc(unsigned samples_per_sym=2, unsigned L=4, double bt=0.3); +gr_make_gmskmod_bc(unsigned samples_per_sym=2, double bt=0.3, unsigned L=4); /*! @@ -38,16 +38,10 @@ gr_make_gmskmod_bc(unsigned samples_per_sym=2, unsigned L=4, double bt=0.3); * * \ingroup modulation_blk * - * Parameters: - * * \p samples_per_sym: Samples per symbol. - * * \p L: The length of the phase duration in symbols. The Gaussian pulse is truncated - * after L symbols. - * * \p bt: 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. + * \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 @@ -57,8 +51,8 @@ gr_make_gmskmod_bc(unsigned samples_per_sym=2, unsigned L=4, double bt=0.3); */ class gr_gmskmod_bc : public gr_cpmmod_bc { - friend gr_gmskmod_bc_sptr gr_make_gmskmod_bc(unsigned samples_per_sym, unsigned L, double bt); - gr_gmskmod_bc(unsigned samples_per_sym, unsigned L, double bt); + friend gr_gmskmod_bc_sptr gr_make_gmskmod_bc(unsigned samples_per_sym, double bt, unsigned L); + gr_gmskmod_bc(unsigned samples_per_sym, double bt, unsigned L); }; #endif /* INCLUDED_GR_GMSKMOD_BC_H */ diff --git a/gnuradio-core/src/lib/hier/gr_gmskmod_bc.i b/gnuradio-core/src/lib/hier/gr_gmskmod_bc.i index 7fb16839b..dadf3be62 100644 --- a/gnuradio-core/src/lib/hier/gr_gmskmod_bc.i +++ b/gnuradio-core/src/lib/hier/gr_gmskmod_bc.i @@ -23,12 +23,12 @@ GR_SWIG_BLOCK_MAGIC(gr, gmskmod_bc) gr_gmskmod_bc_sptr -gr_make_gmskmod_bc(unsigned samples_per_sym=2, unsigned L=4, double bt=0.3); +gr_make_gmskmod_bc(unsigned samples_per_sym=2, double bt=0.3, unsigned L=4); class gr_gmskmod_bc : public gr_hier_block2 { private: - gr_cpmmod_bc(int type, float h, unsigned samples_per_sym, unsigned L, double beta); + gr_cpmmod_bc(int type, float h, unsigned samples_per_sym, double beta, unsigned L); public: std::vector get_taps(); diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_cpm.py b/gnuradio-core/src/python/gnuradio/gr/qa_cpm.py index 9cc22c257..b28decce2 100755 --- a/gnuradio-core/src/python/gnuradio/gr/qa_cpm.py +++ b/gnuradio-core/src/python/gnuradio/gr/qa_cpm.py @@ -64,9 +64,10 @@ class test_cpm(gr_unittest.TestCase): 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 = gr.gmskmod_bc(sps, L) + gmsk = gr.gmskmod_bc(sps, bt, L) arg = gr.complex_to_arg() sink = gr.vector_sink_f() -- cgit From 3f9a95ae3e8b91faae6b59870429b84ccdfaa3db Mon Sep 17 00:00:00 2001 From: Martin Braun Date: Fri, 10 Dec 2010 13:48:37 +0100 Subject: Added GRC blocks to Makefile --- grc/blocks/Makefile.am | 2 ++ grc/blocks/gr_gmskmod_bc.xml | 16 ++++++++-------- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/grc/blocks/Makefile.am b/grc/blocks/Makefile.am index 18420a013..af849cd1b 100644 --- a/grc/blocks/Makefile.am +++ b/grc/blocks/Makefile.am @@ -92,6 +92,7 @@ dist_ourdata_DATA = \ gr_correlate_access_code_bb.xml \ gr_costas_loop_cc.xml \ gr_cpfsk_bc.xml \ + gr_cpmmod_bc.xml \ gr_decode_ccsds_27_fb.xml \ gr_deinterleave.xml \ gr_delay.xml \ @@ -118,6 +119,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 \ diff --git a/grc/blocks/gr_gmskmod_bc.xml b/grc/blocks/gr_gmskmod_bc.xml index 00195a12f..de730fbc2 100644 --- a/grc/blocks/gr_gmskmod_bc.xml +++ b/grc/blocks/gr_gmskmod_bc.xml @@ -8,17 +8,11 @@ GMSK gr_gmskmod_bc from gnuradio import gr - gr.gmskmod_bc($samples_per_symbol, $L, $bt) + gr.gmskmod_bc($samples_per_symbol, $bt, $L) Samples/Symbol samples_per_symbol - 4 - int - - - Pulse Duration (Symbols) - L - 5 + 2 int @@ -27,6 +21,12 @@ real 0.3 + + Pulse Duration (Symbols) + L + 4 + int + in byte -- cgit From ee5ac10dcec81570be475877b41be6219784d4c6 Mon Sep 17 00:00:00 2001 From: Martin Braun Date: Fri, 10 Dec 2010 14:03:50 +0100 Subject: Forgot to add GRC blocks to block_tree, fixed --- grc/blocks/block_tree.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/grc/blocks/block_tree.xml b/grc/blocks/block_tree.xml index 610a88102..dda5742ec 100644 --- a/grc/blocks/block_tree.xml +++ b/grc/blocks/block_tree.xml @@ -205,6 +205,8 @@ gr_phase_modulator_fc gr_quadrature_demod_cf gr_cpfsk_bc + gr_cpmmod_bc + gr_gmskmod_bc gr_diff_phasor_cc gr_constellation_decoder_cb -- cgit From 67e6c7e9a9420f2fc5ee14cee862412aad24b89f Mon Sep 17 00:00:00 2001 From: Martin Braun Date: Fri, 10 Dec 2010 14:31:00 +0100 Subject: fixed some XML glitches --- grc/blocks/gr_cpmmod_bc.xml | 6 +++--- grc/blocks/gr_gmskmod_bc.xml | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/grc/blocks/gr_cpmmod_bc.xml b/grc/blocks/gr_cpmmod_bc.xml index 7ebb7e179..da405534e 100644 --- a/grc/blocks/gr_cpmmod_bc.xml +++ b/grc/blocks/gr_cpmmod_bc.xml @@ -37,8 +37,8 @@ Modulation Index mod_index - real 0.5 + real Samples/Symbol @@ -49,14 +49,14 @@ Pulse Duration (Symbols) L - 5 + 4 int Phase Response Parameter (BT or Beta) beta - real 0.3 + real in diff --git a/grc/blocks/gr_gmskmod_bc.xml b/grc/blocks/gr_gmskmod_bc.xml index de730fbc2..82e47452b 100644 --- a/grc/blocks/gr_gmskmod_bc.xml +++ b/grc/blocks/gr_gmskmod_bc.xml @@ -5,7 +5,7 @@ ################################################### --> - GMSK + GMSK Modulator gr_gmskmod_bc from gnuradio import gr gr.gmskmod_bc($samples_per_symbol, $bt, $L) @@ -18,8 +18,8 @@ 3 dB Time-Bandwith Product bt - real 0.3 + real Pulse Duration (Symbols) -- cgit From b12498643aa5c11a35a484925c565a7a9e746f75 Mon Sep 17 00:00:00 2001 From: Martin Braun Date: Fri, 10 Dec 2010 17:30:01 +0100 Subject: fixed: FM sensitivity and calling gr_cpm::phase_response() through SWIG --- gnuradio-core/src/lib/general/gr_cpm.cc | 3 +++ gnuradio-core/src/lib/general/gr_cpm.h | 4 ---- gnuradio-core/src/lib/general/gr_cpm.i | 2 +- gnuradio-core/src/lib/general/qa_gr_cpm.cc | 2 -- gnuradio-core/src/lib/hier/gr_cpmmod_bc.cc | 2 +- gnuradio-core/src/python/gnuradio/gr/qa_cpm.py | 6 +++++- 6 files changed, 10 insertions(+), 9 deletions(-) diff --git a/gnuradio-core/src/lib/general/gr_cpm.cc b/gnuradio-core/src/lib/general/gr_cpm.cc index f2d032a22..a00526b52 100644 --- a/gnuradio-core/src/lib/general/gr_cpm.cc +++ b/gnuradio-core/src/lib/general/gr_cpm.cc @@ -28,6 +28,9 @@ #include #include +#ifndef M_TWOPI +# define M_TWOPI (2*M_PI) +#endif //! Normalised sinc function, sinc(x)=sin(pi*x)/pi*x inline double diff --git a/gnuradio-core/src/lib/general/gr_cpm.h b/gnuradio-core/src/lib/general/gr_cpm.h index 09598024a..cae6fe313 100644 --- a/gnuradio-core/src/lib/general/gr_cpm.h +++ b/gnuradio-core/src/lib/general/gr_cpm.h @@ -24,10 +24,6 @@ #include -#ifndef M_TWOPI -# define M_TWOPI (2*M_PI) -#endif - class gr_cpm { public: diff --git a/gnuradio-core/src/lib/general/gr_cpm.i b/gnuradio-core/src/lib/general/gr_cpm.i index 7145f5edd..f01aba34e 100644 --- a/gnuradio-core/src/lib/general/gr_cpm.i +++ b/gnuradio-core/src/lib/general/gr_cpm.i @@ -34,7 +34,7 @@ class gr_cpm GENERIC = 999 }; - std::vector + static std::vector phase_response(cpm_type type, unsigned samples_per_sym, unsigned L, double beta=0.3); }; diff --git a/gnuradio-core/src/lib/general/qa_gr_cpm.cc b/gnuradio-core/src/lib/general/qa_gr_cpm.cc index ae391c48c..cc32d1117 100644 --- a/gnuradio-core/src/lib/general/qa_gr_cpm.cc +++ b/gnuradio-core/src/lib/general/qa_gr_cpm.cc @@ -135,8 +135,6 @@ qa_gr_cpm::t5 () sum += taps[i]; } - // Need to cut this guy some slack; in theory, sum only equals one for - // L => infinity CPPUNIT_ASSERT_DOUBLES_EQUAL(sum, 1.0, DELTA); } diff --git a/gnuradio-core/src/lib/hier/gr_cpmmod_bc.cc b/gnuradio-core/src/lib/hier/gr_cpmmod_bc.cc index d14deee34..24c25e22f 100644 --- a/gnuradio-core/src/lib/hier/gr_cpmmod_bc.cc +++ b/gnuradio-core/src/lib/hier/gr_cpmmod_bc.cc @@ -42,7 +42,7 @@ gr_cpmmod_bc::gr_cpmmod_bc(gr_cpm::cpm_type type, float h, unsigned samples_per_ 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_TWOPI * h / samples_per_sym)) + d_fm(gr_make_frequency_modulator_fc(M_PI * h)) { switch (type) { case gr_cpm::LRC: diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_cpm.py b/gnuradio-core/src/python/gnuradio/gr/qa_cpm.py index b28decce2..776173466 100755 --- a/gnuradio-core/src/python/gnuradio/gr/qa_cpm.py +++ b/gnuradio-core/src/python/gnuradio/gr/qa_cpm.py @@ -33,7 +33,7 @@ class test_cpm(gr_unittest.TestCase): def do_check_phase_shift(self, type, name): sps = 2 - L = 5 + L = 1 in_bits = (1,) * 20 src = gr.vector_source_b(in_bits, False) cpm = gr.cpmmod_bc(type, 0.5, sps, L) @@ -80,6 +80,10 @@ class test_cpm(gr_unittest.TestCase): 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") -- cgit From 8af791009ad280f8830dada145a78292a19dde81 Mon Sep 17 00:00:00 2001 From: Tom Rondeau Date: Mon, 22 Aug 2011 20:13:13 -0400 Subject: utils: fixed typo --- gr-utils/src/python/gr_plot_const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 -- cgit From 35fd5072f4a1eba6d02e3c4615dfde33783f876f Mon Sep 17 00:00:00 2001 From: Tom Rondeau Date: Sat, 27 Aug 2011 16:30:56 -0400 Subject: digital: made digital constellation receiver a child of the second order control loop class and cleaned up the interface. --- .../lib/digital_constellation_receiver_cb.cc | 145 +-------------------- gr-digital/lib/digital_constellation_receiver_cb.h | 132 +------------------ 2 files changed, 9 insertions(+), 268 deletions(-) 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 ea55c6243..3885b301e 100644 --- a/gr-digital/lib/digital_constellation_receiver_cb.h +++ b/gr-digital/lib/digital_constellation_receiver_cb.h @@ -25,6 +25,7 @@ #include #include +#include #include #include #include @@ -63,7 +64,7 @@ digital_make_constellation_receiver_cb (digital_constellation_sptr constellation * */ -class digital_constellation_receiver_cb : public gr_block +class digital_constellation_receiver_cb : public gr_block, public gri_control_loop { public: int general_work (int noutput_items, @@ -71,126 +72,6 @@ class digital_constellation_receiver_cb : public gr_block 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: /*! @@ -213,15 +94,6 @@ protected: 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; -- cgit From 56500df87ed591e645d57bbaa67a8e49942de909 Mon Sep 17 00:00:00 2001 From: Tom Rondeau Date: Sat, 27 Aug 2011 16:32:29 -0400 Subject: digital: updating constellation receiver's QA code. --- gr-digital/python/qa_constellation_receiver.py | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) 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) -- cgit From d2a856cf1d85eb2f36101874cad16905c7442377 Mon Sep 17 00:00:00 2001 From: Tom Rondeau Date: Sat, 27 Aug 2011 16:33:23 -0400 Subject: digital: working on adding a dqpsk modulation block. --- gr-digital/python/qpsk.py | 69 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/gr-digital/python/qpsk.py b/gr-digital/python/qpsk.py index 76e5df270..d4daa868b 100644 --- a/gr-digital/python/qpsk.py +++ b/gr-digital/python/qpsk.py @@ -100,10 +100,79 @@ 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_qpsk() + if constellation_points != 4: + raise ValueError('Number of constellation points must be 4 for DQPSK.') + if not gray_coded: + raise ValueError("This DQPSK mod/demod works only for gray-coded constellations.") + 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_qpsk() + 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) -- cgit From b29d77324666696d10397a379cce394e8e43156b Mon Sep 17 00:00:00 2001 From: Tom Rondeau Date: Sat, 27 Aug 2011 16:33:49 -0400 Subject: digital: wip: dqpsk needs work. --- gr-digital/python/generic_mod_demod.py | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/gr-digital/python/generic_mod_demod.py b/gr-digital/python/generic_mod_demod.py index da8e2cfd9..9378e2d61 100644 --- a/gr-digital/python/generic_mod_demod.py +++ b/gr-digital/python/generic_mod_demod.py @@ -265,8 +265,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, @@ -275,6 +276,9 @@ class generic_demod(gr.hier_block2): self._timing_bw, taps, nfilts, nfilts//2, self._timing_max_dev) + # Perform phase / fine frequency correction + self.phase_recov = digital_swig.costas_loop_cc(self._phase_bw, arity) + fmin = -0.25 fmax = 0.25 self.receiver = digital_swig.constellation_receiver_cb( @@ -283,7 +287,8 @@ class generic_demod(gr.hier_block2): # Do differential decoding based on phase change of symbols if differential: - self.diffdec = gr.diff_decoder_bb(arity) + #self.diffdec = gr.diff_decoder_bb(arity) + self.diffdec = gr.diff_phasor_cc() if self._constellation.apply_pre_diff_code(): self.symbol_mapper = gr.map_bb( @@ -292,16 +297,23 @@ class generic_demod(gr.hier_block2): # unpack the k bit vector into a stream of bits self.unpack = gr.unpack_k_bits_bb(self.bits_per_symbol()) + p = 1*math.pi/4.0 + c = complex(math.sin(p), math.cos(p)) + self.rotate = gr.multiply_const_cc(c) + if verbose: self._print_verbage() 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] if differential: blocks.append(self.diffdec) + blocks.append(self.rotate) + blocks.append(self.receiver) + if self._constellation.apply_pre_diff_code(): blocks.append(self.symbol_mapper) blocks += [self.unpack, self] @@ -351,7 +363,8 @@ class generic_demod(gr.hier_block2): gr.file_sink(gr.sizeof_float, "rx_receiver_freq.32f")) if self._differential: self.connect(self.diffdec, - gr.file_sink(gr.sizeof_char, "rx_diffdec.8b")) + gr.file_sink(gr.sizeof_gr_complex, "rx_diffdec.8b")) + #gr.file_sink(gr.sizeof_char, "rx_diffdec.8b")) if self._constellation.apply_pre_diff_code(): self.connect(self.symbol_mapper, gr.file_sink(gr.sizeof_char, "rx_symbol_mapper.8b")) -- cgit From 41cf2b306a210c3600c1c35a8e952679a94c00a6 Mon Sep 17 00:00:00 2001 From: Tom Rondeau Date: Mon, 29 Aug 2011 17:37:38 -0400 Subject: digital: created a separate DQPSK constellation that does not gray code inside the block. This forces a slower decision making routine but allows differential encoding. Gray coding is done using pre_diff_code. --- gr-digital/lib/digital_constellation.cc | 80 ++++++++++++++++++++++++++++++ gr-digital/lib/digital_constellation.h | 87 ++++++++++++++++++++++++--------- gr-digital/swig/digital_constellation.i | 18 +++++++ 3 files changed, 162 insertions(+), 23 deletions(-) diff --git a/gr-digital/lib/digital_constellation.cc b/gr-digital/lib/digital_constellation.cc index 2263bba0b..ed6d32bcb 100644 --- a/gr-digital/lib/digital_constellation.cc +++ b/gr-digital/lib/digital_constellation.cc @@ -407,6 +407,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(); @@ -418,8 +432,74 @@ 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 () +{ + 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); + + 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(); +} + +#include +unsigned int +digital_constellation_dqpsk::decision_maker(const gr_complex *sample) +{ + 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 4119b5803..fd773a907 100644 --- a/gr-digital/lib/digital_constellation.h +++ b/gr-digital/lib/digital_constellation.h @@ -41,8 +41,10 @@ typedef boost::shared_ptr digital_constellation_sptr; class digital_constellation : public boost::enable_shared_from_this { public: - digital_constellation (std::vector constellation, std::vector pre_diff_code, - unsigned int rotational_symmetry, unsigned int dimensionality); + digital_constellation (std::vector constellation, + std::vector pre_diff_code, + unsigned int rotational_symmetry, + unsigned int dimensionality); digital_constellation (); //! Returns the constellation points for a symbol value @@ -73,6 +75,8 @@ public: std::vector > 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 pre_diff_code() { return d_pre_diff_code;} //! Returns the order of rotational symmetry. @@ -119,17 +123,19 @@ typedef boost::shared_ptr digital_constellation_ // public constructor digital_constellation_calcdist_sptr -digital_make_constellation_calcdist (std::vector constellation, std::vector pre_diff_code, - unsigned int rotational_symmetry, unsigned int dimensionality); +digital_make_constellation_calcdist (std::vector constellation, + std::vector pre_diff_code, + unsigned int rotational_symmetry, + unsigned int dimensionality); class digital_constellation_calcdist : public digital_constellation { public: digital_constellation_calcdist (std::vector constellation, - std::vector pre_diff_code, - unsigned int rotational_symmetry, - unsigned int dimensionality); + std::vector 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); @@ -154,10 +160,10 @@ class digital_constellation_sector : public digital_constellation public: digital_constellation_sector (std::vector constellation, - std::vector pre_diff_code, - unsigned int rotational_symmetry, - unsigned int dimensionality, - unsigned int n_sectors); + std::vector pre_diff_code, + unsigned int rotational_symmetry, + unsigned int dimensionality, + unsigned int n_sectors); unsigned int decision_maker (const gr_complex *sample); @@ -193,19 +199,25 @@ typedef boost::shared_ptr digital_constellation_rect // public constructor digital_constellation_rect_sptr -digital_make_constellation_rect (std::vector constellation, std::vector 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 constellation, + std::vector 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_constellation_rect : public digital_constellation_sector { public: - digital_constellation_rect (std::vector constellation, std::vector 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 constellation, + std::vector pre_diff_code, + unsigned int rotational_symmetry, + unsigned int real_sectors, + unsigned int imag_sectors, + float width_real_sectors, + float width_imag_sectors); protected: @@ -221,10 +233,13 @@ class digital_constellation_rect : public digital_constellation_sector float d_width_imag_sectors; friend digital_constellation_rect_sptr - digital_make_constellation_rect (std::vector constellation, std::vector 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 constellation, + std::vector pre_diff_code, + unsigned int rotational_symmetry, + unsigned int real_sectors, + unsigned int imag_sectors, + float width_real_sectors, + float width_imag_sectors); }; @@ -322,6 +337,32 @@ class digital_constellation_qpsk : public digital_constellation }; +/************************************************************/ +/* digital_constellation_dqpsk */ +/* */ +/* Works with differential encoding; slower decisions. */ +/* */ +/************************************************************/ + +class digital_constellation_dqpsk; +typedef boost::shared_ptr digital_constellation_dqpsk_sptr; + +// public constructor +digital_constellation_dqpsk_sptr +digital_make_constellation_dqpsk (); + +class digital_constellation_dqpsk : public digital_constellation +{ + public: + + digital_constellation_dqpsk (); + unsigned int decision_maker (const gr_complex *sample); + + friend digital_constellation_dqpsk_sptr + digital_make_constellation_dqpsk (); + +}; + /************************************************************/ /* digital_constellation_8psk */ 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 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_sptr; +%template(digital_constellation_dqpsk_sptr) boost::shared_ptr; +%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 -- cgit From f94ceff1f608bd5d1c67e3ff662fb2c659e61aa8 Mon Sep 17 00:00:00 2001 From: Tom Rondeau Date: Mon, 29 Aug 2011 17:39:40 -0400 Subject: digital: fixed qpsk modulators to enable dqpsk. --- gr-digital/python/generic_mod_demod.py | 30 +++++++++++------------------- gr-digital/python/qpsk.py | 6 ++---- 2 files changed, 13 insertions(+), 23 deletions(-) diff --git a/gr-digital/python/generic_mod_demod.py b/gr-digital/python/generic_mod_demod.py index 9378e2d61..47026ef85 100644 --- a/gr-digital/python/generic_mod_demod.py +++ b/gr-digital/python/generic_mod_demod.py @@ -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,6 +229,8 @@ 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 @@ -276,31 +279,23 @@ class generic_demod(gr.hier_block2): self._timing_bw, taps, nfilts, nfilts//2, self._timing_max_dev) - # Perform phase / fine frequency correction - self.phase_recov = digital_swig.costas_loop_cc(self._phase_bw, arity) - fmin = -0.25 fmax = 0.25 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) - self.diffdec = gr.diff_phasor_cc() + 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())) # unpack the k bit vector into a stream of bits self.unpack = gr.unpack_k_bits_bb(self.bits_per_symbol()) - p = 1*math.pi/4.0 - c = complex(math.sin(p), math.cos(p)) - self.rotate = gr.multiply_const_cc(c) - if verbose: self._print_verbage() @@ -308,12 +303,10 @@ class generic_demod(gr.hier_block2): self._setup_logging() # Connect and Initialize base class - blocks = [self, self.agc, self.freq_recov, self.time_recov] + blocks = [self, self.agc, self.freq_recov, + self.time_recov, self.receiver] if differential: blocks.append(self.diffdec) - blocks.append(self.rotate) - blocks.append(self.receiver) - if self._constellation.apply_pre_diff_code(): blocks.append(self.symbol_mapper) blocks += [self.unpack, self] @@ -363,8 +356,7 @@ class generic_demod(gr.hier_block2): gr.file_sink(gr.sizeof_float, "rx_receiver_freq.32f")) if self._differential: self.connect(self.diffdec, - gr.file_sink(gr.sizeof_gr_complex, "rx_diffdec.8b")) - #gr.file_sink(gr.sizeof_char, "rx_diffdec.8b")) + gr.file_sink(gr.sizeof_char, "rx_diffdec.8b")) if self._constellation.apply_pre_diff_code(): self.connect(self.symbol_mapper, gr.file_sink(gr.sizeof_char, "rx_symbol_mapper.8b")) diff --git a/gr-digital/python/qpsk.py b/gr-digital/python/qpsk.py index d4daa868b..481b7cb5b 100644 --- a/gr-digital/python/qpsk.py +++ b/gr-digital/python/qpsk.py @@ -130,11 +130,9 @@ class dqpsk_mod(generic_mod): """ constellation_points = _def_constellation_points - constellation = digital_swig.constellation_qpsk() + constellation = digital_swig.constellation_dqpsk() if constellation_points != 4: raise ValueError('Number of constellation points must be 4 for DQPSK.') - if not gray_coded: - raise ValueError("This DQPSK mod/demod works only for gray-coded constellations.") super(dqpsk_mod, self).__init__(constellation=constellation, gray_coded=gray_coded, differential=True, @@ -159,7 +157,7 @@ class dqpsk_demod(generic_demod): See generic_demod block for list of parameters. """ constellation_points = _def_constellation_points - constellation = digital_swig.constellation_qpsk() + 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, -- cgit From 5784b0c53c6d19b7a74f82e57c816beecd8b5edb Mon Sep 17 00:00:00 2001 From: Tom Rondeau Date: Mon, 29 Aug 2011 17:58:25 -0400 Subject: digital: fixing qa code to test new dqpsk; a few minor formatting changes. --- gr-digital/lib/digital_constellation.cc | 8 +++++++- gr-digital/lib/digital_constellation.h | 1 + gr-digital/python/qa_constellation.py | 11 +++++------ 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/gr-digital/lib/digital_constellation.cc b/gr-digital/lib/digital_constellation.cc index ed6d32bcb..3dfc70273 100644 --- a/gr-digital/lib/digital_constellation.cc +++ b/gr-digital/lib/digital_constellation.cc @@ -463,12 +463,16 @@ digital_make_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; @@ -481,10 +485,12 @@ digital_constellation_dqpsk::digital_constellation_dqpsk () calc_arity(); } -#include 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) { diff --git a/gr-digital/lib/digital_constellation.h b/gr-digital/lib/digital_constellation.h index fd773a907..3e54e7d96 100644 --- a/gr-digital/lib/digital_constellation.h +++ b/gr-digital/lib/digital_constellation.h @@ -344,6 +344,7 @@ class digital_constellation_qpsk : public digital_constellation /* */ /************************************************************/ +//! \brief DQPSK-specific constellation and decision maker class digital_constellation_dqpsk; typedef boost::shared_ptr digital_constellation_dqpsk_sptr; 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: -- cgit From 9dc241fc48ac4e286cfd51c3bddde0b9f0f40988 Mon Sep 17 00:00:00 2001 From: Tom Rondeau Date: Mon, 29 Aug 2011 21:42:15 -0400 Subject: Updating all three PLL blocks to use new control_loop parent class. --- .../src/lib/general/gr_pll_carriertracking_cc.cc | 43 +++++++++++----------- .../src/lib/general/gr_pll_carriertracking_cc.h | 23 +++++++----- .../src/lib/general/gr_pll_carriertracking_cc.i | 11 +++--- gnuradio-core/src/lib/general/gr_pll_freqdet_cf.cc | 33 +++++++---------- gnuradio-core/src/lib/general/gr_pll_freqdet_cf.h | 24 ++++++------ gnuradio-core/src/lib/general/gr_pll_freqdet_cf.i | 11 +++--- gnuradio-core/src/lib/general/gr_pll_refout_cc.cc | 4 +- gnuradio-core/src/lib/general/gr_pll_refout_cc.h | 4 +- gnuradio-core/src/lib/general/gri_control_loop.cc | 4 +- 9 files changed, 81 insertions(+), 76 deletions(-) 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 #include -#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 195f06016..bcdf543a4 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 * @@ -24,12 +24,14 @@ #define INCLUDED_GR_PLL_CARRIERTRACKING_CC_H #include +#include class gr_pll_carriertracking_cc; typedef boost::shared_ptr gr_pll_carriertracking_cc_sptr; -gr_pll_carriertracking_cc_sptr gr_make_pll_carriertracking_cc (float alpha, float beta, - float max_freq, float min_freq); +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. @@ -41,19 +43,20 @@ gr_pll_carriertracking_cc_sptr gr_make_pll_carriertracking_cc (float alpha, floa * 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_pll_carriertracking_cc : public gr_sync_block +class gr_pll_carriertracking_cc : public gr_sync_block, public gri_control_loop { - friend gr_pll_carriertracking_cc_sptr gr_make_pll_carriertracking_cc (float alpha, float beta, - float max_freq, float min_freq); + friend 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 #include -#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 0581c8724..0da9fc5c7 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 * @@ -24,12 +24,14 @@ #define INCLUDED_GR_PLL_FREQDET_CF_H #include +#include class gr_pll_freqdet_cf; typedef boost::shared_ptr gr_pll_freqdet_cf_sptr; -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); /*! * \brief Implements a PLL which locks to the input frequency and outputs * an estimate of that frequency. Useful for FM Demod. @@ -40,24 +42,24 @@ gr_pll_freqdet_cf_sptr gr_make_pll_freqdet_cf (float alpha, float beta, * 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_pll_freqdet_cf : public gr_sync_block +class gr_pll_freqdet_cf : public gr_sync_block, public gri_control_loop { - friend gr_pll_freqdet_cf_sptr gr_make_pll_freqdet_cf (float alpha, float beta, - float max_freq, float min_freq); + friend 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 #include -#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 226ca8f9e..d3e45882b 100644 --- a/gnuradio-core/src/lib/general/gr_pll_refout_cc.h +++ b/gnuradio-core/src/lib/general/gr_pll_refout_cc.h @@ -42,8 +42,8 @@ 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_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 d84b47493..affdeefc9 100644 --- a/gnuradio-core/src/lib/general/gri_control_loop.cc +++ b/gnuradio-core/src/lib/general/gri_control_loop.cc @@ -70,9 +70,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; } /******************************************************************* -- cgit From e8f68c3db6b4391ba88d36c42f2ce077a02c0c7b Mon Sep 17 00:00:00 2001 From: Tom Rondeau Date: Mon, 29 Aug 2011 21:42:42 -0400 Subject: Updating QA code for PLL blocks. Setting gains using new loop bw concept changes the behavior slightly so new values were necessary. By explicitly setting alpha and beta to the previous values still worked, though. --- gnuradio-core/src/guile/tests/general_ctors.test | 6 +- .../python/gnuradio/gr/qa_pll_carriertracking.py | 207 ++++++++++---------- .../src/python/gnuradio/gr/qa_pll_freqdet.py | 207 ++++++++++---------- .../src/python/gnuradio/gr/qa_pll_refout.py | 208 ++++++++++----------- 4 files changed, 312 insertions(+), 316 deletions(-) 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/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") -- cgit From 38ee7ad424f470826db6e0a31b85442a12464e15 Mon Sep 17 00:00:00 2001 From: Tom Rondeau Date: Tue, 30 Aug 2011 10:29:04 -0400 Subject: digital: reformatting documentation for line length. --- gr-digital/lib/digital_fll_band_edge_cc.h | 115 +++++++++++++++++------------- 1 file changed, 65 insertions(+), 50 deletions(-) diff --git a/gr-digital/lib/digital_fll_band_edge_cc.h b/gr-digital/lib/digital_fll_band_edge_cc.h index 496289d90..fbd59881b 100644 --- a/gr-digital/lib/digital_fll_band_edge_cc.h +++ b/gr-digital/lib/digital_fll_band_edge_cc.h @@ -39,35 +39,47 @@ digital_fll_band_edge_cc_sptr digital_make_fll_band_edge_cc (float samps_per_sym * * \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. * */ @@ -155,12 +167,12 @@ public: * \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. + * 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(). + * 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 * @@ -172,8 +184,8 @@ public: * * Set's the loop filter's alpha gain parameter. * - * This value should really only be set by adjusting the loop bandwidth - * and damping factor. + * This value should really only be set by adjusting the loop + * bandwidth and damping factor. * * \param alpha (float) new alpha gain * @@ -185,8 +197,8 @@ public: * * Set's the loop filter's beta gain parameter. * - * This value should really only be set by adjusting the loop bandwidth - * and damping factor. + * This value should really only be set by adjusting the loop + * bandwidth and damping factor. * * \param beta (float) new beta gain * @@ -196,8 +208,9 @@ public: /*! * \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 * @@ -207,13 +220,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] * @@ -223,13 +237,14 @@ 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 * @@ -240,8 +255,8 @@ public: * \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. + * inner loop of the algorithm, it could be useful to manually + * initialize, set, or reset this under certain circumstances. * * \param freq (float) new frequency * @@ -252,8 +267,8 @@ public: * \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. + * inner loop of the algorithm, it could be useful to manually + * initialize, set, or reset this under certain circumstances. * * \param phase (float) new phase * -- cgit From db2cfb25b719511c3ca01bcbadf5ef35a43f4319 Mon Sep 17 00:00:00 2001 From: Tom Rondeau Date: Tue, 30 Aug 2011 10:36:10 -0400 Subject: digital: converted FLL block to use gri_control_loop parent class. --- gr-digital/lib/digital_fll_band_edge_cc.cc | 139 +---------------------------- gr-digital/lib/digital_fll_band_edge_cc.h | 127 +------------------------- gr-digital/swig/digital_fll_band_edge_cc.i | 2 +- 3 files changed, 7 insertions(+), 261 deletions(-) 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 fbd59881b..5b7732906 100644 --- a/gr-digital/lib/digital_fll_band_edge_cc.h +++ b/gr-digital/lib/digital_fll_band_edge_cc.h @@ -25,6 +25,7 @@ #define INCLUDED_DIGITAL_FLL_BAND_EDGE_CC_H #include +#include class digital_fll_band_edge_cc; typedef boost::shared_ptr digital_fll_band_edge_cc_sptr; @@ -83,7 +84,7 @@ digital_fll_band_edge_cc_sptr digital_make_fll_band_edge_cc (float samps_per_sym * */ -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: /*! @@ -104,18 +105,10 @@ class digital_fll_band_edge_cc : public gr_sync_block float d_max_freq; float d_min_freq; - float d_loop_bw; - float d_damping; - float d_alpha; - float d_beta; - std::vector d_taps_lower; std::vector 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 @@ -126,11 +119,6 @@ class digital_fll_band_edge_cc : public gr_sync_block digital_fll_band_edge_cc(float samps_per_sym, float rolloff, 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 @@ -148,63 +136,6 @@ public: 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 number of samples per symbol * @@ -251,54 +182,10 @@ public: */ 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 */ @@ -314,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. */ 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, -- cgit From 6b774f7fd055650628d4e6679e0e32b31b3af5c6 Mon Sep 17 00:00:00 2001 From: Tom Rondeau Date: Tue, 30 Aug 2011 10:36:50 -0400 Subject: digital: made other QA codes executable --- gr-digital/python/qa_crc32.py | 0 gr-digital/python/qa_fll_band_edge.py | 0 gr-digital/python/qa_lms_equalizer.py | 0 gr-digital/python/qa_mpsk_receiver.py | 0 4 files changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 gr-digital/python/qa_crc32.py mode change 100644 => 100755 gr-digital/python/qa_fll_band_edge.py mode change 100644 => 100755 gr-digital/python/qa_lms_equalizer.py mode change 100644 => 100755 gr-digital/python/qa_mpsk_receiver.py diff --git a/gr-digital/python/qa_crc32.py b/gr-digital/python/qa_crc32.py old mode 100644 new mode 100755 diff --git a/gr-digital/python/qa_fll_band_edge.py b/gr-digital/python/qa_fll_band_edge.py old mode 100644 new mode 100755 diff --git a/gr-digital/python/qa_lms_equalizer.py b/gr-digital/python/qa_lms_equalizer.py old mode 100644 new mode 100755 diff --git a/gr-digital/python/qa_mpsk_receiver.py b/gr-digital/python/qa_mpsk_receiver.py old mode 100644 new mode 100755 -- cgit From c63d077ba9fe98eb6b963b0d91ffa2c61048288d Mon Sep 17 00:00:00 2001 From: Tom Rondeau Date: Tue, 30 Aug 2011 10:40:16 -0400 Subject: digital: formatting comments for line length. --- gr-digital/lib/digital_mpsk_receiver_cc.h | 121 +++++++++++++++++------------- 1 file changed, 70 insertions(+), 51 deletions(-) diff --git a/gr-digital/lib/digital_mpsk_receiver_cc.h b/gr-digital/lib/digital_mpsk_receiver_cc.h index bcb06e17c..d27967ad5 100644 --- a/gr-digital/lib/digital_mpsk_receiver_cc.h +++ b/gr-digital/lib/digital_mpsk_receiver_cc.h @@ -42,31 +42,38 @@ digital_make_mpsk_receiver_cc (unsigned int M, float theta, 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. * */ @@ -140,8 +147,8 @@ class digital_mpsk_receiver_cc : public gr_block protected: - - /*! + + /*! * \brief Constructor to synchronize incoming M-PSK symbols * * \param M modulation order of the M-PSK modulation @@ -171,54 +178,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/ */ @@ -230,24 +244,27 @@ 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: @@ -260,16 +277,17 @@ protected: 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 @@ -282,14 +300,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; -- cgit From ba3a3158456cfc866204071183ccdd773f0ab5a2 Mon Sep 17 00:00:00 2001 From: Tom Rondeau Date: Tue, 30 Aug 2011 11:08:13 -0400 Subject: digital: converted mpsk_receiver to use gri_control_loop parent class. Updated QA code for this, too. Again, had to change the expected data since the loop converges at a different rate; tested by setting alpha and beta to old values and it worked with old data still. --- gr-digital/lib/digital_mpsk_receiver_cc.cc | 36 ++++++++++------------- gr-digital/lib/digital_mpsk_receiver_cc.h | 46 ++++-------------------------- gr-digital/python/qa_mpsk_receiver.py | 26 ++++++++--------- gr-digital/swig/digital_mpsk_receiver_cc.i | 14 ++------- 4 files changed, 36 insertions(+), 86 deletions(-) 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 d27967ad5..91cd4a14d 100644 --- a/gr-digital/lib/digital_mpsk_receiver_cc.h +++ b/gr-digital/lib/digital_mpsk_receiver_cc.h @@ -24,6 +24,7 @@ #define INCLUDED_DIGITAL_MPSK_RECEIVER_CC_H #include +#include #include #include #include @@ -36,7 +37,7 @@ typedef boost::shared_ptr digital_mpsk_receiver_cc_spt // public constructor 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); @@ -77,7 +78,7 @@ digital_make_mpsk_receiver_cc (unsigned int M, float theta, * */ -class digital_mpsk_receiver_cc : public gr_block +class digital_mpsk_receiver_cc : public gr_block, public gri_control_loop { public: ~digital_mpsk_receiver_cc (); @@ -118,34 +119,6 @@ class 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: /*! @@ -153,8 +126,7 @@ protected: * * \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] @@ -167,7 +139,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); @@ -271,12 +243,6 @@ protected: 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 * @@ -326,7 +292,7 @@ protected: friend 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/qa_mpsk_receiver.py b/gr-digital/python/qa_mpsk_receiver.py index 7e9a76e1f..6531e59f7 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/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; } }; -- cgit From 317e8321472cb9e921757636b561897b12199195 Mon Sep 17 00:00:00 2001 From: Tom Rondeau Date: Tue, 30 Aug 2011 16:35:30 -0400 Subject: digital: adding a script to add channel conditions to a saved file and output to another file. --- gr-digital/examples/benchmark_add_channel.py | 101 +++++++++++++++++++++++++++ 1 file changed, 101 insertions(+) create mode 100755 gr-digital/examples/benchmark_add_channel.py 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] " + 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 -- cgit From b827a9b538a6df1e74af02041624b77e71dc38ae Mon Sep 17 00:00:00 2001 From: Tom Rondeau Date: Tue, 30 Aug 2011 17:03:54 -0400 Subject: digital: fixing a few things left out in conversion to gri_control_loop children. --- gr-digital/lib/digital_constellation_receiver_cb.h | 13 ++----------- gr-digital/lib/digital_fll_band_edge_cc.h | 2 -- gr-digital/lib/digital_mpsk_receiver_cc.h | 2 +- gr-digital/swig/digital_constellation_receiver_cb.i | 16 +--------------- 4 files changed, 4 insertions(+), 29 deletions(-) diff --git a/gr-digital/lib/digital_constellation_receiver_cb.h b/gr-digital/lib/digital_constellation_receiver_cb.h index 3885b301e..0ac80450f 100644 --- a/gr-digital/lib/digital_constellation_receiver_cb.h +++ b/gr-digital/lib/digital_constellation_receiver_cb.h @@ -66,7 +66,7 @@ digital_make_constellation_receiver_cb (digital_constellation_sptr constellation class 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, @@ -91,7 +91,7 @@ protected: void phase_error_tracking(float phase_error); - private: +private: unsigned int d_M; digital_constellation_sptr d_constellation; @@ -106,15 +106,6 @@ protected: //! 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_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.h b/gr-digital/lib/digital_fll_band_edge_cc.h index 5b7732906..4fa7b3a3e 100644 --- a/gr-digital/lib/digital_fll_band_edge_cc.h +++ b/gr-digital/lib/digital_fll_band_edge_cc.h @@ -102,8 +102,6 @@ class digital_fll_band_edge_cc : public gr_sync_block, public gri_control_loop float d_sps; float d_rolloff; int d_filter_size; - float d_max_freq; - float d_min_freq; std::vector d_taps_lower; std::vector d_taps_upper; diff --git a/gr-digital/lib/digital_mpsk_receiver_cc.h b/gr-digital/lib/digital_mpsk_receiver_cc.h index 91cd4a14d..f8aa4e341 100644 --- a/gr-digital/lib/digital_mpsk_receiver_cc.h +++ b/gr-digital/lib/digital_mpsk_receiver_cc.h @@ -239,7 +239,7 @@ protected: */ unsigned int decision_qpsk(gr_complex sample) const; - private: +private: unsigned int d_M; float d_theta; 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; }; -- cgit From 9b89276c58516cc9d3be817a96d68483c60a26f7 Mon Sep 17 00:00:00 2001 From: Tom Rondeau Date: Tue, 30 Aug 2011 17:40:31 -0400 Subject: digital: minor formatting fixes. --- gr-digital/python/generic_mod_demod.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gr-digital/python/generic_mod_demod.py b/gr-digital/python/generic_mod_demod.py index 47026ef85..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]") @@ -233,7 +233,7 @@ class generic_demod(gr.hier_block2): @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 -- cgit From 245ef56d20f1c947e3c0f42e2edf15515e00db10 Mon Sep 17 00:00:00 2001 From: Tom Rondeau Date: Tue, 30 Aug 2011 17:40:42 -0400 Subject: digital: adding GMSK as a modulation type. Updated to use PFB-based clock recovery alg instead of M&M. --- gr-digital/python/__init__.py | 1 + gr-digital/python/gmsk.py | 106 +++++++++++++++++------------------------- 2 files changed, 43 insertions(+), 64 deletions(-) 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/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) -- cgit From ff8ce00c0457c213dcad0b1b460a5d0db1b7d155 Mon Sep 17 00:00:00 2001 From: Tom Rondeau Date: Tue, 30 Aug 2011 22:11:56 -0400 Subject: digital: moved newly added CPM and GMSK hier blocks to gr-digital. --- gnuradio-core/src/lib/hier/gr_cpmmod_bc.cc | 64 ------------------- gnuradio-core/src/lib/hier/gr_cpmmod_bc.h | 86 -------------------------- gnuradio-core/src/lib/hier/gr_cpmmod_bc.i | 36 ----------- gnuradio-core/src/lib/hier/gr_gmskmod_bc.cc | 41 ------------- gnuradio-core/src/lib/hier/gr_gmskmod_bc.h | 59 ------------------ gnuradio-core/src/lib/hier/gr_gmskmod_bc.i | 36 ----------- gnuradio-core/src/lib/hier/hier.i | 4 -- gr-digital/Makefile.am | 2 +- gr-digital/hier/gr_cpmmod_bc.cc | 69 +++++++++++++++++++++ gr-digital/hier/gr_cpmmod_bc.h | 95 +++++++++++++++++++++++++++++ gr-digital/hier/gr_cpmmod_bc.i | 40 ++++++++++++ gr-digital/hier/gr_gmskmod_bc.cc | 42 +++++++++++++ gr-digital/hier/gr_gmskmod_bc.h | 60 ++++++++++++++++++ gr-digital/hier/gr_gmskmod_bc.i | 39 ++++++++++++ 14 files changed, 346 insertions(+), 327 deletions(-) delete mode 100644 gnuradio-core/src/lib/hier/gr_cpmmod_bc.cc delete mode 100644 gnuradio-core/src/lib/hier/gr_cpmmod_bc.h delete mode 100644 gnuradio-core/src/lib/hier/gr_cpmmod_bc.i delete mode 100644 gnuradio-core/src/lib/hier/gr_gmskmod_bc.cc delete mode 100644 gnuradio-core/src/lib/hier/gr_gmskmod_bc.h delete mode 100644 gnuradio-core/src/lib/hier/gr_gmskmod_bc.i create mode 100644 gr-digital/hier/gr_cpmmod_bc.cc create mode 100644 gr-digital/hier/gr_cpmmod_bc.h create mode 100644 gr-digital/hier/gr_cpmmod_bc.i create mode 100644 gr-digital/hier/gr_gmskmod_bc.cc create mode 100644 gr-digital/hier/gr_gmskmod_bc.h create mode 100644 gr-digital/hier/gr_gmskmod_bc.i diff --git a/gnuradio-core/src/lib/hier/gr_cpmmod_bc.cc b/gnuradio-core/src/lib/hier/gr_cpmmod_bc.cc deleted file mode 100644 index 24c25e22f..000000000 --- a/gnuradio-core/src/lib/hier/gr_cpmmod_bc.cc +++ /dev/null @@ -1,64 +0,0 @@ -/* -*- 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 -#include - - -// Shared pointer constructor -gr_cpmmod_bc_sptr -gr_make_cpmmod_bc(int type, float h, unsigned samples_per_sym, unsigned L, double beta) -{ - return gnuradio::get_initial_sptr(new gr_cpmmod_bc((gr_cpm::cpm_type)type, h, samples_per_sym, L, beta)); -} - - -gr_cpmmod_bc::gr_cpmmod_bc(gr_cpm::cpm_type type, float h, unsigned samples_per_sym, - unsigned L, double beta) - : gr_hier_block2("gr_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/gnuradio-core/src/lib/hier/gr_cpmmod_bc.h b/gnuradio-core/src/lib/hier/gr_cpmmod_bc.h deleted file mode 100644 index 210b30612..000000000 --- a/gnuradio-core/src/lib/hier/gr_cpmmod_bc.h +++ /dev/null @@ -1,86 +0,0 @@ -/* -*- 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_GR_CPMMOD_BC_H -#define INCLUDED_GR_CPMMOD_BC_H - -#include -#include -#include -#include -#include - - -class gr_cpmmod_bc; -typedef boost::shared_ptr gr_cpmmod_bc_sptr; - - -gr_cpmmod_bc_sptr -gr_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 gr_cpmmod_bc : public gr_hier_block2 -{ - friend gr_cpmmod_bc_sptr gr_make_cpmmod_bc(int type, float h, unsigned samples_per_sym, unsigned L, double beta); - - std::vector 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: - gr_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 get_taps() { return d_taps; }; -}; - -#endif /* INCLUDED_GR_CPMMOD_BC_H */ - diff --git a/gnuradio-core/src/lib/hier/gr_cpmmod_bc.i b/gnuradio-core/src/lib/hier/gr_cpmmod_bc.i deleted file mode 100644 index 55116cda7..000000000 --- a/gnuradio-core/src/lib/hier/gr_cpmmod_bc.i +++ /dev/null @@ -1,36 +0,0 @@ -/* -*- 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(gr, cpmmod_bc) - -gr_cpmmod_bc_sptr -gr_make_cpmmod_bc(int type, float h, unsigned samples_per_sym, unsigned L, double beta=0.3); - -class gr_cpmmod_bc : public gr_hier_block2 -{ - private: - gr_cpmmod_bc(int type, float h, unsigned samples_per_sym, unsigned L, double beta); - - public: - std::vector get_taps(); -}; - diff --git a/gnuradio-core/src/lib/hier/gr_gmskmod_bc.cc b/gnuradio-core/src/lib/hier/gr_gmskmod_bc.cc deleted file mode 100644 index 37128d99c..000000000 --- a/gnuradio-core/src/lib/hier/gr_gmskmod_bc.cc +++ /dev/null @@ -1,41 +0,0 @@ -/* -*- 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 -#include - - -// Shared pointer constructor -gr_gmskmod_bc_sptr -gr_make_gmskmod_bc(unsigned samples_per_sym, double bt, unsigned L) -{ - return gnuradio::get_initial_sptr(new gr_gmskmod_bc(samples_per_sym, bt, L)); -} - - -gr_gmskmod_bc::gr_gmskmod_bc(unsigned samples_per_sym, double bt, unsigned L) - : gr_cpmmod_bc(gr_cpm::GAUSSIAN, 0.5, samples_per_sym, L, bt) -{ -} - diff --git a/gnuradio-core/src/lib/hier/gr_gmskmod_bc.h b/gnuradio-core/src/lib/hier/gr_gmskmod_bc.h deleted file mode 100644 index 39bd576e2..000000000 --- a/gnuradio-core/src/lib/hier/gr_gmskmod_bc.h +++ /dev/null @@ -1,59 +0,0 @@ -/* -*- 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_GR_GMSKMOD_BC_H -#define INCLUDED_GR_GMSKMOD_BC_H - -#include - -class gr_gmskmod_bc; -typedef boost::shared_ptr gr_gmskmod_bc_sptr; - - -gr_gmskmod_bc_sptr -gr_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 gr_gmskmod_bc : public gr_cpmmod_bc -{ - friend gr_gmskmod_bc_sptr gr_make_gmskmod_bc(unsigned samples_per_sym, double bt, unsigned L); - gr_gmskmod_bc(unsigned samples_per_sym, double bt, unsigned L); -}; - -#endif /* INCLUDED_GR_GMSKMOD_BC_H */ - diff --git a/gnuradio-core/src/lib/hier/gr_gmskmod_bc.i b/gnuradio-core/src/lib/hier/gr_gmskmod_bc.i deleted file mode 100644 index dadf3be62..000000000 --- a/gnuradio-core/src/lib/hier/gr_gmskmod_bc.i +++ /dev/null @@ -1,36 +0,0 @@ -/* -*- 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(gr, gmskmod_bc) - -gr_gmskmod_bc_sptr -gr_make_gmskmod_bc(unsigned samples_per_sym=2, double bt=0.3, unsigned L=4); - -class gr_gmskmod_bc : public gr_hier_block2 -{ - private: - gr_cpmmod_bc(int type, float h, unsigned samples_per_sym, double beta, unsigned L); - - public: - std::vector get_taps(); -}; - diff --git a/gnuradio-core/src/lib/hier/hier.i b/gnuradio-core/src/lib/hier/hier.i index b8915e15b..bec3de7ed 100644 --- a/gnuradio-core/src/lib/hier/hier.i +++ b/gnuradio-core/src/lib/hier/hier.i @@ -26,11 +26,7 @@ #endif #include -#include -#include %} %include "gr_channel_model.i" -%include "gr_cpmmod_bc.i" -%include "gr_gmskmod_bc.i" diff --git a/gr-digital/Makefile.am b/gr-digital/Makefile.am index f1409793f..57bfb1e0d 100644 --- a/gr-digital/Makefile.am +++ b/gr-digital/Makefile.am @@ -21,7 +21,7 @@ include $(top_srcdir)/Makefile.common -SUBDIRS = lib +SUBDIRS = lib hier if PYTHON SUBDIRS += swig python apps grc examples diff --git a/gr-digital/hier/gr_cpmmod_bc.cc b/gr-digital/hier/gr_cpmmod_bc.cc new file mode 100644 index 000000000..e0e39f0dc --- /dev/null +++ b/gr-digital/hier/gr_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 +#include + + +// Shared pointer constructor +gr_cpmmod_bc_sptr +gr_make_cpmmod_bc(int type, float h, + unsigned samples_per_sym, + unsigned L, double beta) +{ + return gnuradio::get_initial_sptr(new gr_cpmmod_bc((gr_cpm::cpm_type)type, + h, samples_per_sym, + L, beta)); +} + + +gr_cpmmod_bc::gr_cpmmod_bc(gr_cpm::cpm_type type, float h, + unsigned samples_per_sym, + unsigned L, double beta) + : gr_hier_block2("gr_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/gr_cpmmod_bc.h b/gr-digital/hier/gr_cpmmod_bc.h new file mode 100644 index 000000000..55ea6edd1 --- /dev/null +++ b/gr-digital/hier/gr_cpmmod_bc.h @@ -0,0 +1,95 @@ +/* -*- 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_GR_CPMMOD_BC_H +#define INCLUDED_GR_CPMMOD_BC_H + +#include +#include +#include +#include +#include + + +class gr_cpmmod_bc; +typedef boost::shared_ptr gr_cpmmod_bc_sptr; + + +gr_cpmmod_bc_sptr +gr_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 gr_cpmmod_bc : public gr_hier_block2 +{ + friend gr_cpmmod_bc_sptr gr_make_cpmmod_bc(int type, float h, + unsigned samples_per_sym, + unsigned L, double beta); + + std::vector 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: + gr_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 get_taps() { return d_taps; }; +}; + +#endif /* INCLUDED_GR_CPMMOD_BC_H */ + diff --git a/gr-digital/hier/gr_cpmmod_bc.i b/gr-digital/hier/gr_cpmmod_bc.i new file mode 100644 index 000000000..dc38fea17 --- /dev/null +++ b/gr-digital/hier/gr_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(gr, cpmmod_bc) + +gr_cpmmod_bc_sptr +gr_make_cpmmod_bc(int type, float h, + unsigned samples_per_sym, + unsigned L, double beta=0.3); + +class gr_cpmmod_bc : public gr_hier_block2 +{ + private: + gr_cpmmod_bc(int type, float h, + unsigned samples_per_sym, + unsigned L, double beta); + + public: + std::vector get_taps(); +}; + diff --git a/gr-digital/hier/gr_gmskmod_bc.cc b/gr-digital/hier/gr_gmskmod_bc.cc new file mode 100644 index 000000000..22287d014 --- /dev/null +++ b/gr-digital/hier/gr_gmskmod_bc.cc @@ -0,0 +1,42 @@ +/* -*- 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 +#include + +// Shared pointer constructor +gr_gmskmod_bc_sptr +gr_make_gmskmod_bc(unsigned samples_per_sym, double bt, unsigned L) +{ + return gnuradio::get_initial_sptr(new gr_gmskmod_bc(samples_per_sym, bt, L)); +} + + +gr_gmskmod_bc::gr_gmskmod_bc(unsigned samples_per_sym, double bt, unsigned L) + : gr_cpmmod_bc(gr_cpm::GAUSSIAN, 0.5, samples_per_sym, L, bt) +{ +} + diff --git a/gr-digital/hier/gr_gmskmod_bc.h b/gr-digital/hier/gr_gmskmod_bc.h new file mode 100644 index 000000000..c3d2c8194 --- /dev/null +++ b/gr-digital/hier/gr_gmskmod_bc.h @@ -0,0 +1,60 @@ +/* -*- 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_GR_GMSKMOD_BC_H +#define INCLUDED_GR_GMSKMOD_BC_H + +#include + +class gr_gmskmod_bc; +typedef boost::shared_ptr gr_gmskmod_bc_sptr; + + +gr_gmskmod_bc_sptr +gr_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 gr_gmskmod_bc : public gr_cpmmod_bc +{ + friend gr_gmskmod_bc_sptr gr_make_gmskmod_bc(unsigned samples_per_sym, + double bt, unsigned L); + gr_gmskmod_bc(unsigned samples_per_sym, double bt, unsigned L); +}; + +#endif /* INCLUDED_GR_GMSKMOD_BC_H */ + diff --git a/gr-digital/hier/gr_gmskmod_bc.i b/gr-digital/hier/gr_gmskmod_bc.i new file mode 100644 index 000000000..9e59b279b --- /dev/null +++ b/gr-digital/hier/gr_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(gr, gmskmod_bc) + +gr_gmskmod_bc_sptr +gr_make_gmskmod_bc(unsigned samples_per_sym=2, + double bt=0.3, unsigned L=4); + +class gr_gmskmod_bc : public gr_hier_block2 +{ + private: + gr_cpmmod_bc(int type, float h, + unsigned samples_per_sym, + double beta, unsigned L); + + public: + std::vector get_taps(); +}; + -- cgit From da5b87db20a34c84b3d03f87a668632997d58457 Mon Sep 17 00:00:00 2001 From: Tom Rondeau Date: Tue, 30 Aug 2011 22:51:15 -0400 Subject: digital: fixed up build to make libdigital_hier.la; does not swig or get built into full library yet. Passes distcheck. --- config/grc_gr_digital.m4 | 1 + gnuradio-core/src/lib/hier/Makefile.am | 12 ++-------- gr-digital/hier/Makefile.am | 40 ++++++++++++++++++++++++++++++++++ gr-digital/hier/digital_hier.i | 33 ++++++++++++++++++++++++++++ 4 files changed, 76 insertions(+), 10 deletions(-) create mode 100644 gr-digital/hier/Makefile.am create mode 100644 gr-digital/hier/digital_hier.i diff --git a/config/grc_gr_digital.m4 b/config/grc_gr_digital.m4 index 83c3f03a4..bde4a3087 100644 --- a/config/grc_gr_digital.m4 +++ b/config/grc_gr_digital.m4 @@ -29,6 +29,7 @@ AC_DEFUN([GRC_GR_DIGITAL],[ 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/lib/hier/Makefile.am b/gnuradio-core/src/lib/hier/Makefile.am index 8d56be7a3..369feef75 100644 --- a/gnuradio-core/src/lib/hier/Makefile.am +++ b/gnuradio-core/src/lib/hier/Makefile.am @@ -27,19 +27,11 @@ AM_CPPFLAGS = $(STD_DEFINES_AND_INCLUDES) $(WITH_INCLUDES) noinst_LTLIBRARIES = libhier.la libhier_la_SOURCES = \ - gr_channel_model.cc \ - gr_gmskmod_bc.cc \ - gr_cpmmod_bc.cc + gr_channel_model.cc grinclude_HEADERS = \ - gr_channel_model.h \ - gr_gmskmod_bc.h \ - gr_cpmmod_bc.h - + gr_channel_model.h swiginclude_HEADERS = \ hier.i \ gr_channel_model.i - gr_channel_model.i \ - gr_gmskmod_bc.i \ - gr_cpmmod_bc.i diff --git a/gr-digital/hier/Makefile.am b/gr-digital/hier/Makefile.am new file mode 100644 index 000000000..a51689ed6 --- /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 = \ + gr_gmskmod_bc.cc \ + gr_cpmmod_bc.cc + +grinclude_HEADERS = \ + gr_gmskmod_bc.h \ + gr_cpmmod_bc.h + + +swiginclude_HEADERS = \ + digital_hier.i \ + gr_gmskmod_bc.i \ + gr_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..c24d0f777 --- /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 +#include +%} + +%include "gr_cpmmod_bc.i" +%include "gr_gmskmod_bc.i" -- cgit From e17dbbcda50bdb851227c67e68c9d3e2e7732468 Mon Sep 17 00:00:00 2001 From: Tom Rondeau Date: Tue, 30 Aug 2011 22:52:44 -0400 Subject: digital: added gitignore file to hier dir. --- gr-digital/hier/.gitignore | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 gr-digital/hier/.gitignore 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 -- cgit From 0e962fd8e859f313c9483d6c3444200977a70022 Mon Sep 17 00:00:00 2001 From: Tom Rondeau Date: Thu, 1 Sep 2011 12:11:07 -0400 Subject: digital: adding CPM C++ hier block, which adds a hier directory to gr-digital. Reworked build system to include this in the libraries and modules built. --- Makefile.common | 4 + config/grc_gr_digital.m4 | 16 +++ gnuradio-core/src/python/gnuradio/gr/qa_cpm.py | 90 --------------- gr-digital/Makefile.am | 2 +- gr-digital/hier/Makefile.am | 14 +-- gr-digital/hier/_digital_hier.i | 33 ++++++ gr-digital/hier/digital_cpmmod_bc.cc | 69 ++++++++++++ gr-digital/hier/digital_cpmmod_bc.h | 95 ++++++++++++++++ gr-digital/hier/digital_cpmmod_bc.i | 40 +++++++ gr-digital/hier/digital_gmskmod_bc.cc | 44 ++++++++ gr-digital/hier/digital_gmskmod_bc.h | 61 ++++++++++ gr-digital/hier/digital_gmskmod_bc.i | 39 +++++++ gr-digital/hier/digital_hier.i | 33 ------ gr-digital/hier/gr_cpmmod_bc.cc | 69 ------------ gr-digital/hier/gr_cpmmod_bc.h | 95 ---------------- gr-digital/hier/gr_cpmmod_bc.i | 40 ------- gr-digital/hier/gr_gmskmod_bc.cc | 42 ------- gr-digital/hier/gr_gmskmod_bc.h | 60 ---------- gr-digital/hier/gr_gmskmod_bc.i | 39 ------- gr-digital/lib/Makefile.am | 3 +- gr-digital/python/Makefile.am | 1 + gr-digital/python/qa_cpm.py | 91 +++++++++++++++ gr-digital/swig/Makefile.am | 10 +- gr-digital/swig/Makefile.swig.gen | 148 ++++++++++++++++++++++++- gr-digital/swig/digital_hier.i | 40 +++++++ gr-digital/swig/digital_swig.i | 1 + 26 files changed, 696 insertions(+), 483 deletions(-) delete mode 100755 gnuradio-core/src/python/gnuradio/gr/qa_cpm.py create mode 100644 gr-digital/hier/_digital_hier.i create mode 100644 gr-digital/hier/digital_cpmmod_bc.cc create mode 100644 gr-digital/hier/digital_cpmmod_bc.h create mode 100644 gr-digital/hier/digital_cpmmod_bc.i create mode 100644 gr-digital/hier/digital_gmskmod_bc.cc create mode 100644 gr-digital/hier/digital_gmskmod_bc.h create mode 100644 gr-digital/hier/digital_gmskmod_bc.i delete mode 100644 gr-digital/hier/digital_hier.i delete mode 100644 gr-digital/hier/gr_cpmmod_bc.cc delete mode 100644 gr-digital/hier/gr_cpmmod_bc.h delete mode 100644 gr-digital/hier/gr_cpmmod_bc.i delete mode 100644 gr-digital/hier/gr_gmskmod_bc.cc delete mode 100644 gr-digital/hier/gr_gmskmod_bc.h delete mode 100644 gr-digital/hier/gr_gmskmod_bc.i create mode 100755 gr-digital/python/qa_cpm.py create mode 100644 gr-digital/swig/digital_hier.i 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 bde4a3087..d7c1d605f 100644 --- a/config/grc_gr_digital.m4 +++ b/config/grc_gr_digital.m4 @@ -23,6 +23,22 @@ 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 \ diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_cpm.py b/gnuradio-core/src/python/gnuradio/gr/qa_cpm.py deleted file mode 100755 index 776173466..000000000 --- a/gnuradio-core/src/python/gnuradio/gr/qa_cpm.py +++ /dev/null @@ -1,90 +0,0 @@ -#!/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 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 = gr.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 = gr.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/Makefile.am b/gr-digital/Makefile.am index 57bfb1e0d..346db120f 100644 --- a/gr-digital/Makefile.am +++ b/gr-digital/Makefile.am @@ -21,7 +21,7 @@ include $(top_srcdir)/Makefile.common -SUBDIRS = lib hier +SUBDIRS = hier lib if PYTHON SUBDIRS += swig python apps grc examples diff --git a/gr-digital/hier/Makefile.am b/gr-digital/hier/Makefile.am index a51689ed6..b11b85f77 100644 --- a/gr-digital/hier/Makefile.am +++ b/gr-digital/hier/Makefile.am @@ -26,15 +26,15 @@ AM_CPPFLAGS = $(STD_DEFINES_AND_INCLUDES) $(WITH_INCLUDES) noinst_LTLIBRARIES = libdigital_hier.la libdigital_hier_la_SOURCES = \ - gr_gmskmod_bc.cc \ - gr_cpmmod_bc.cc + digital_gmskmod_bc.cc \ + digital_cpmmod_bc.cc grinclude_HEADERS = \ - gr_gmskmod_bc.h \ - gr_cpmmod_bc.h + digital_gmskmod_bc.h \ + digital_cpmmod_bc.h swiginclude_HEADERS = \ - digital_hier.i \ - gr_gmskmod_bc.i \ - gr_cpmmod_bc.i + _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 +#include +%} + +%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 +#include + + +// 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..6212fc777 --- /dev/null +++ b/gr-digital/hier/digital_cpmmod_bc.h @@ -0,0 +1,95 @@ +/* -*- 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 +#include +#include +#include +#include + + +class digital_cpmmod_bc; +typedef boost::shared_ptr digital_cpmmod_bc_sptr; + + +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_cpmmod_bc : public gr_hier_block2 +{ + friend digital_cpmmod_bc_sptr digital_make_cpmmod_bc(int type, float h, + unsigned samples_per_sym, + unsigned L, double beta); + + std::vector 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 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 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 +#include + +// 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..92b53cd4b --- /dev/null +++ b/gr-digital/hier/digital_gmskmod_bc.h @@ -0,0 +1,61 @@ +/* -*- 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 + +class digital_gmskmod_bc; +typedef boost::shared_ptr digital_gmskmod_bc_sptr; + + +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_gmskmod_bc : public digital_cpmmod_bc +{ + friend 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 get_taps(); +}; + diff --git a/gr-digital/hier/digital_hier.i b/gr-digital/hier/digital_hier.i deleted file mode 100644 index c24d0f777..000000000 --- a/gr-digital/hier/digital_hier.i +++ /dev/null @@ -1,33 +0,0 @@ -/* -*- 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 -#include -%} - -%include "gr_cpmmod_bc.i" -%include "gr_gmskmod_bc.i" diff --git a/gr-digital/hier/gr_cpmmod_bc.cc b/gr-digital/hier/gr_cpmmod_bc.cc deleted file mode 100644 index e0e39f0dc..000000000 --- a/gr-digital/hier/gr_cpmmod_bc.cc +++ /dev/null @@ -1,69 +0,0 @@ -/* -*- 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 -#include - - -// Shared pointer constructor -gr_cpmmod_bc_sptr -gr_make_cpmmod_bc(int type, float h, - unsigned samples_per_sym, - unsigned L, double beta) -{ - return gnuradio::get_initial_sptr(new gr_cpmmod_bc((gr_cpm::cpm_type)type, - h, samples_per_sym, - L, beta)); -} - - -gr_cpmmod_bc::gr_cpmmod_bc(gr_cpm::cpm_type type, float h, - unsigned samples_per_sym, - unsigned L, double beta) - : gr_hier_block2("gr_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/gr_cpmmod_bc.h b/gr-digital/hier/gr_cpmmod_bc.h deleted file mode 100644 index 55ea6edd1..000000000 --- a/gr-digital/hier/gr_cpmmod_bc.h +++ /dev/null @@ -1,95 +0,0 @@ -/* -*- 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_GR_CPMMOD_BC_H -#define INCLUDED_GR_CPMMOD_BC_H - -#include -#include -#include -#include -#include - - -class gr_cpmmod_bc; -typedef boost::shared_ptr gr_cpmmod_bc_sptr; - - -gr_cpmmod_bc_sptr -gr_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 gr_cpmmod_bc : public gr_hier_block2 -{ - friend gr_cpmmod_bc_sptr gr_make_cpmmod_bc(int type, float h, - unsigned samples_per_sym, - unsigned L, double beta); - - std::vector 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: - gr_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 get_taps() { return d_taps; }; -}; - -#endif /* INCLUDED_GR_CPMMOD_BC_H */ - diff --git a/gr-digital/hier/gr_cpmmod_bc.i b/gr-digital/hier/gr_cpmmod_bc.i deleted file mode 100644 index dc38fea17..000000000 --- a/gr-digital/hier/gr_cpmmod_bc.i +++ /dev/null @@ -1,40 +0,0 @@ -/* -*- 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(gr, cpmmod_bc) - -gr_cpmmod_bc_sptr -gr_make_cpmmod_bc(int type, float h, - unsigned samples_per_sym, - unsigned L, double beta=0.3); - -class gr_cpmmod_bc : public gr_hier_block2 -{ - private: - gr_cpmmod_bc(int type, float h, - unsigned samples_per_sym, - unsigned L, double beta); - - public: - std::vector get_taps(); -}; - diff --git a/gr-digital/hier/gr_gmskmod_bc.cc b/gr-digital/hier/gr_gmskmod_bc.cc deleted file mode 100644 index 22287d014..000000000 --- a/gr-digital/hier/gr_gmskmod_bc.cc +++ /dev/null @@ -1,42 +0,0 @@ -/* -*- 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 -#include - -// Shared pointer constructor -gr_gmskmod_bc_sptr -gr_make_gmskmod_bc(unsigned samples_per_sym, double bt, unsigned L) -{ - return gnuradio::get_initial_sptr(new gr_gmskmod_bc(samples_per_sym, bt, L)); -} - - -gr_gmskmod_bc::gr_gmskmod_bc(unsigned samples_per_sym, double bt, unsigned L) - : gr_cpmmod_bc(gr_cpm::GAUSSIAN, 0.5, samples_per_sym, L, bt) -{ -} - diff --git a/gr-digital/hier/gr_gmskmod_bc.h b/gr-digital/hier/gr_gmskmod_bc.h deleted file mode 100644 index c3d2c8194..000000000 --- a/gr-digital/hier/gr_gmskmod_bc.h +++ /dev/null @@ -1,60 +0,0 @@ -/* -*- 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_GR_GMSKMOD_BC_H -#define INCLUDED_GR_GMSKMOD_BC_H - -#include - -class gr_gmskmod_bc; -typedef boost::shared_ptr gr_gmskmod_bc_sptr; - - -gr_gmskmod_bc_sptr -gr_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 gr_gmskmod_bc : public gr_cpmmod_bc -{ - friend gr_gmskmod_bc_sptr gr_make_gmskmod_bc(unsigned samples_per_sym, - double bt, unsigned L); - gr_gmskmod_bc(unsigned samples_per_sym, double bt, unsigned L); -}; - -#endif /* INCLUDED_GR_GMSKMOD_BC_H */ - diff --git a/gr-digital/hier/gr_gmskmod_bc.i b/gr-digital/hier/gr_gmskmod_bc.i deleted file mode 100644 index 9e59b279b..000000000 --- a/gr-digital/hier/gr_gmskmod_bc.i +++ /dev/null @@ -1,39 +0,0 @@ -/* -*- 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(gr, gmskmod_bc) - -gr_gmskmod_bc_sptr -gr_make_gmskmod_bc(unsigned samples_per_sym=2, - double bt=0.3, unsigned L=4); - -class gr_gmskmod_bc : public gr_hier_block2 -{ - private: - gr_cpmmod_bc(int type, float h, - unsigned samples_per_sym, - double beta, unsigned L); - - public: - std::vector get_taps(); -}; - diff --git a/gr-digital/lib/Makefile.am b/gr-digital/lib/Makefile.am index 34988d9a2..60db19821 100644 --- a/gr-digital/lib/Makefile.am +++ b/gr-digital/lib/Makefile.am @@ -60,6 +60,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/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/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/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_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_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" -- cgit From 194cb7f405858fdcd76f8e7595d4970f4a2da984 Mon Sep 17 00:00:00 2001 From: Tom Rondeau Date: Thu, 1 Sep 2011 15:35:12 -0400 Subject: Fixing GRC files for new API to loop blocks. --- gr-digital/grc/digital_costas_loop_cc.xml | 12 +++--------- grc/blocks/gr_pll_carriertracking_cc.xml | 12 ++++-------- grc/blocks/gr_pll_freqdet_cf.xml | 12 ++++-------- grc/blocks/gr_pll_refout_cc.xml | 12 ++++-------- 4 files changed, 15 insertions(+), 33 deletions(-) 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 @@ Costas Loop digital_costas_loop_cc from gnuradio import digital - digital.costas_loop_cc($eta, $w, $order) - set_damping_factor($eta) - set_natural_freq($w) + digital.costas_loop_cc($w, $order) + set_loop_bandwidth($w) - Damping Factor - eta - real - - - Natural Frequency + Loop Bandwidth w real 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 @@ PLL Carrier Tracking gr_pll_carriertracking_cc from gnuradio import gr - gr.pll_carriertracking_cc($alpha, $beta, $max_freq, $min_freq) + gr.pll_carriertracking_cc($w, $max_freq, $min_freq) + set_loop_bandwidth($w) - Alpha - alpha - real - - - Beta - beta + Loop Bandwidth + w real 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 @@ PLL Freq Det gr_pll_freqdet_cf from gnuradio import gr - gr.pll_freqdet_cf($alpha, $beta, $max_freq, $min_freq) + gr.pll_freqdet_cf($w, $max_freq, $min_freq) + set_loop_bandwidth($w) - Alpha - alpha - real - - - Beta - beta + Loop Bandwidth + w real 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 @@ PLL Ref Out gr_pll_refout_cc from gnuradio import gr - gr.pll_refout_cc($alpha, $beta, $max_freq, $min_freq) + gr.pll_refout_cc($w, $max_freq, $min_freq) + set_loop_bandwidth($w) - Alpha - alpha - real - - - Beta - beta + Loop Bandwidth + w real -- cgit From 4f6e8d801bc6f4e43e956bd9b21d2904451a1233 Mon Sep 17 00:00:00 2001 From: Tom Rondeau Date: Thu, 1 Sep 2011 16:06:07 -0400 Subject: Fixed the PFB clock sync block when asking for multiple samples per symbol out. --- .../src/lib/filter/gr_pfb_clock_sync_ccf.cc | 64 +++++++++++----------- .../src/lib/filter/gr_pfb_clock_sync_ccf.h | 1 + 2 files changed, 33 insertions(+), 32 deletions(-) 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 0909220e0..4718171a7 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 @@ -154,6 +154,7 @@ class 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. -- cgit From 65fbbb8f752ebf522ac2628f850445e66a278e2f Mon Sep 17 00:00:00 2001 From: Tom Rondeau Date: Thu, 1 Sep 2011 16:06:44 -0400 Subject: grc: moved GRC blocks that were put into gr-digital into gr-digital/grc and refactored for new API. --- gr-digital/grc/Makefile.am | 4 +- gr-digital/grc/digital_block_tree.xml | 2 + gr-digital/grc/digital_fll_band_edge_cc.xml | 70 +++++++++++++++++++++++++ gr-digital/grc/digital_mpsk_receiver_cc.xml | 75 ++++++++++++++++++++++++++ grc/blocks/Makefile.am | 2 - grc/blocks/block_tree.xml | 3 -- grc/blocks/gr_fll_band_edge_cc.xml | 76 --------------------------- grc/blocks/gr_mpsk_receiver_cc.xml | 81 ----------------------------- 8 files changed, 150 insertions(+), 163 deletions(-) create mode 100644 gr-digital/grc/digital_fll_band_edge_cc.xml create mode 100644 gr-digital/grc/digital_mpsk_receiver_cc.xml delete mode 100644 grc/blocks/gr_fll_band_edge_cc.xml delete mode 100644 grc/blocks/gr_mpsk_receiver_cc.xml 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 @@ digital_cma_equalizer_cc digital_lms_dd_equalizer_cc digital_kurtotic_equalizer_cc + digital_fll_band_edge_cc + digital_mpsk_receiver_cc Digital Modulators diff --git a/gr-digital/grc/digital_fll_band_edge_cc.xml b/gr-digital/grc/digital_fll_band_edge_cc.xml new file mode 100644 index 000000000..1c5a34e54 --- /dev/null +++ b/gr-digital/grc/digital_fll_band_edge_cc.xml @@ -0,0 +1,70 @@ + + + + FLL Band-Edge + gr_fll_band_edge_cc + from gnuradio import gr + gr.fll_band_edge_cc($samps_per_sym, $rolloff, $filter_size, $w) + set_loop_bandwidth($w) + + Type + type + enum + + + + + Samples Per Symbol + samps_per_sym + real + + + Filter Rolloff Factor + rolloff + real + + + Prototype Filter Size + filter_size + int + + + + Loop Bandwidth + w + real + + + + in + $type.input + + + out + $type.output + + + freq + float + 1 + + + phase + float + 1 + + + error + float + 1 + + diff --git a/gr-digital/grc/digital_mpsk_receiver_cc.xml b/gr-digital/grc/digital_mpsk_receiver_cc.xml new file mode 100644 index 000000000..948f18b6e --- /dev/null +++ b/gr-digital/grc/digital_mpsk_receiver_cc.xml @@ -0,0 +1,75 @@ + + + + MPSK Receiver + gr_mpsk_receiver_cc + from gnuradio import gr + gr.mpsk_receiver_cc($M, $theta, $w, $fmin, $fmax, $mu, $gain_mu, $omega, $gain_omega, $omega_relative_limit) + set_loop_bandwidth($w) + set_mu($mu) + set_gain_mu($gain_mu) + set_omega($omega) + set_gain_omega($gain_omega) + + M + M + int + + + Theta + theta + real + + + Loop Bandwidth + w + real + + + Min Freq + fmin + real + + + Max Freq + fmax + real + + + Mu + mu + real + + + Gain Mu + gain_mu + real + + + Omega + omega + real + + + Gain Omega + gain_omega + real + + + Omega Relative Limit + omega_relative_limit + real + + + in + complex + + + out + complex + + diff --git a/grc/blocks/Makefile.am b/grc/blocks/Makefile.am index 0360ebc80..6f72fe399 100644 --- a/grc/blocks/Makefile.am +++ b/grc/blocks/Makefile.am @@ -109,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 \ @@ -136,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 3dc247aec..f5365dcb5 100644 --- a/grc/blocks/block_tree.xml +++ b/grc/blocks/block_tree.xml @@ -121,14 +121,11 @@ gr_costas_loop_cc gr_mpsk_sync_cc - gr_mpsk_receiver_cc gr_pll_carriertracking_cc gr_pll_freqdet_cf gr_pll_refout_cc - gr_fll_band_edge_cc - gr_correlate_access_code_bb gr_pn_correlator_cc gr_simple_correlator diff --git a/grc/blocks/gr_fll_band_edge_cc.xml b/grc/blocks/gr_fll_band_edge_cc.xml deleted file mode 100644 index 5a13ac49b..000000000 --- a/grc/blocks/gr_fll_band_edge_cc.xml +++ /dev/null @@ -1,76 +0,0 @@ - - - - FLL Band-Edge - gr_fll_band_edge_cc - from gnuradio import gr - gr.fll_band_edge_cc($samps_per_sym, $rolloff, $filter_size, $alpha, $beta) - set_alpha($alpha) - set_beta($beta) - - - Type - type - enum - - - - - Samples Per Symbol - samps_per_sym - real - - - Filter Rolloff Factor - rolloff - real - - - Prototype Filter Size - filter_size - int - - - - Alpha - alpha - real - - - Beta - beta - real - - - in - $type.input - - - out - $type.output - - - freq - float - 1 - - - phase - float - 1 - - - error - float - 1 - - diff --git a/grc/blocks/gr_mpsk_receiver_cc.xml b/grc/blocks/gr_mpsk_receiver_cc.xml deleted file mode 100644 index 843c3a4c1..000000000 --- a/grc/blocks/gr_mpsk_receiver_cc.xml +++ /dev/null @@ -1,81 +0,0 @@ - - - - MPSK Receiver - gr_mpsk_receiver_cc - from gnuradio import gr - gr.mpsk_receiver_cc($M, $theta, $alpha, $beta, $fmin, $fmax, $mu, $gain_mu, $omega, $gain_omega, $omega_relative_limit) - set_alpha($alpha) - set_beta($beta) - set_mu($mu) - set_gain_mu($gain_mu) - set_omega($omega) - set_gain_omega($gain_omega) - - M - M - int - - - Theta - theta - real - - - Alpha - alpha - real - - - Beta - beta - real - - - Min Freq - fmin - real - - - Max Freq - fmax - real - - - Mu - mu - real - - - Gain Mu - gain_mu - real - - - Omega - omega - real - - - Gain Omega - gain_omega - real - - - Omega Relative Limit - omega_relative_limit - real - - - in - complex - - - out - complex - - -- cgit