diff options
-rw-r--r-- | gnuradio-core/src/lib/hier/Makefile.am | 26 | ||||
-rw-r--r-- | gnuradio-core/src/lib/hier/gr_cpm.cc | 210 | ||||
-rw-r--r-- | gnuradio-core/src/lib/hier/gr_cpm.h | 75 | ||||
-rw-r--r-- | gnuradio-core/src/lib/hier/gr_cpm.i | 40 | ||||
-rw-r--r-- | gnuradio-core/src/lib/hier/gr_cpmmod_bc.cc | 74 | ||||
-rw-r--r-- | gnuradio-core/src/lib/hier/gr_cpmmod_bc.h | 62 | ||||
-rw-r--r-- | gnuradio-core/src/lib/hier/gr_cpmmod_bc.i | 36 | ||||
-rw-r--r-- | gnuradio-core/src/lib/hier/hier.i | 3 | ||||
-rw-r--r-- | gnuradio-core/src/lib/hier/qa_gr_cpm.cc | 108 | ||||
-rw-r--r-- | gnuradio-core/src/lib/hier/qa_gr_cpm.h | 51 |
10 files changed, 680 insertions, 5 deletions
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 <cmath> +#include <cfloat> +#include <gr_cpm.h> + + +//! Normalised sinc function, sinc(x)=sin(pi*x)/pi*x +inline double +sinc(double x) +{ + if (x == 0) { + return 1.0; + } + + return sin(M_PI * x) / (M_PI * x); +} + + +//! Taps for L-RC CPM (Raised cosine of length L symbols) +std::vector<float> +generate_cpm_lrc_taps(unsigned samples_per_sym, unsigned L) +{ + std::vector<float> taps(samples_per_sym * L, 1.0/L/samples_per_sym); + for (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<float> +generate_cpm_lsrc_taps(unsigned samples_per_sym, unsigned L, double beta) +{ + double Ls = (double) L * samples_per_sym; + std::vector<double> taps_d(Ls, 0.0); + std::vector<float> 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<float> +generate_cpm_lrec_taps(unsigned samples_per_sym, unsigned L) +{ + return std::vector<float>(samples_per_sym * L, 1.0/L/samples_per_sym); +} + + +//! Helper function for TFM +double tfm_g0(double k, double sps) +{ + if (k < 2 * DBL_EPSILON) { + return 1.145393004159143; // 1 + pi^2/48 / sqrt(2) + } + + const double pi2_24 = 0.411233516712057; // pi^2/24 + double f = M_PI * k / sps; + return sinc(k/sps) - pi2_24 * (2 * sin(f) - 2*f*cos(f) - f*f*sin(f)) / (f*f*f); +} + + +//! Taps for TFM CPM (Tamed frequency modulation) +// +// See [2, Chapter 2.7.2]. +// +// [2]: Anderson, Aulin and Sundberg; Digital Phase Modulation +std::vector<float> +generate_cpm_tfm_taps(unsigned sps, unsigned L) +{ + double causal_shift = (double) L * sps / 2; + std::vector<double> taps_d(Ls, 0.0); + std::vector<float> 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<float> +generate_cpm_gaussian_taps(unsigned samples_per_sym, unsigned L, double bt) +{ + double Ls = (double) L * samples_per_sym; + std::vector<double> taps_d(Ls, 0.0); + std::vector<float> 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<float> +gr_cpm::phase_response(cpm_type type, unsigned samples_per_sym, unsigned L, double beta) +{ + switch (type) { + case LRC: + return generate_cpm_lrc_taps(samples_per_sym, L); + + case LSRC: + return generate_cpm_lsrc_taps(samples_per_sym, L, beta); + + case LREC: + return generate_cpm_lrec_taps(samples_per_sym, L); + + case TFM: + return generate_cpm_tfm_taps(samples_per_sym, L); + + case GAUSSIAN: + return generate_cpm_gaussian_taps(samples_per_sym, L, beta); + + default: + return generate_cpm_lrec_taps(samples_per_sym, 1); + } +} + diff --git a/gnuradio-core/src/lib/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<float> + phase_response(cpm_type type, unsigned samples_per_sym, unsigned L, double beta=0.3); +}; + +#endif /* INCLUDED_GR_CPM_H */ + diff --git a/gnuradio-core/src/lib/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<float> + 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 <gri_cpm.h> +#include <gr_cpmmod_bc.h> +#include <gr_io_signature.h> + + +// 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 <gr_top_block.h> +#include <gr_char_to_float.h> +#include <gr_interp_fir_filter_fff.h> +#include <gr_frequency_modulator_fc.h> + + +class gr_cpmmod_bc; +typedef boost::shared_ptr<gr_cpmmod_bc> 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<float> d_taps; + + public: + //! Return the phase response FIR taps + std::vector<float> 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<float> 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 <gr_channel_model.h> +#include <gr_cpmmod_bc.h> %} %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 <qa_gr_cpm.h> +#include <gr_cpm.h> +#include <cppunit/TestAssert.h> + +// Check LREC phase response +void +qa_gr_cpm::t1 () +{ + int L = 5; + int samples_per_sym = 4; + std::vector<float> taps(gr_cpm::phase_response(gr_cpm::LREC, samples_per_sym, L)); + + for (int i = 0; i < L * samples_per_sym; i++) { + CPPUNIT_ASSERT_DOUBLES_EQUAL(taps[i], 0.05); + } +} + + +// Check LRC phase response +void +qa_gr_cpm::t2 () +{ + int L = 5; + int samples_per_sym = 4; + std::vector<float> taps(gr_cpm::phase_response(gr_cpm::LRC, samples_per_sym, L)); + float sum = 0; + + for (int i = 0; i < L * samples_per_sym; i++) { + 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<float> taps(gr_cpm::phase_response(gr_cpm::LSRC, samples_per_sym, L, 0.2)); + float sum = 0; + + for (int i = 0; i < L * samples_per_sym; i++) { + 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<float> taps(gr_cpm::phase_response(gr_cpm::TFM, samples_per_sym, L)); + float sum = 0; + + for (int i = 0; i < L * samples_per_sym; i++) { + 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<float> taps(gr_cpm::phase_response(gr_cpm::GAUSSIAN, samples_per_sym, L, 0.3)); + float sum = 0; + + for (int i = 0; i < L * samples_per_sym; i++) { + 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 <cppunit/extensions/HelperMacros.h> +#include <cppunit/TestCase.h> + +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 */ + |