summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gnuradio-core/src/lib/general/Makefile.am5
-rw-r--r--gnuradio-core/src/lib/general/gr_cpm.cc (renamed from gnuradio-core/src/lib/hier/gr_cpm.cc)27
-rw-r--r--gnuradio-core/src/lib/general/gr_cpm.h (renamed from gnuradio-core/src/lib/hier/gr_cpm.h)6
-rw-r--r--gnuradio-core/src/lib/general/gr_cpm.i (renamed from gnuradio-core/src/lib/hier/gr_cpm.i)0
-rw-r--r--gnuradio-core/src/lib/general/qa_general.cc2
-rw-r--r--gnuradio-core/src/lib/general/qa_gr_cpm.cc (renamed from gnuradio-core/src/lib/hier/qa_gr_cpm.cc)12
-rw-r--r--gnuradio-core/src/lib/general/qa_gr_cpm.h (renamed from gnuradio-core/src/lib/hier/qa_gr_cpm.h)12
-rw-r--r--gnuradio-core/src/lib/hier/Makefile.am15
-rw-r--r--gnuradio-core/src/lib/hier/gr_cpmmod_bc.cc30
-rw-r--r--gnuradio-core/src/lib/hier/gr_cpmmod_bc.h25
10 files changed, 73 insertions, 61 deletions
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/hier/gr_cpm.cc b/gnuradio-core/src/lib/general/gr_cpm.cc
index 5eda182b2..a5d328edf 100644
--- a/gnuradio-core/src/lib/hier/gr_cpm.cc
+++ b/gnuradio-core/src/lib/general/gr_cpm.cc
@@ -46,7 +46,7 @@ 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++) {
+ for (unsigned i = 0; i < samples_per_sym * L; i++) {
taps[i] *= 1 - cos(M_TWOPI * i / L / samples_per_sym);
}
@@ -74,10 +74,11 @@ 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);
+ std::vector<double> taps_d(L * samples_per_sym, 0.0);
+ std::vector<float> taps(L * samples_per_sym, 0.0);
- for (int i = 0; i < samples_per_sym * L; i++) {
+ 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);
@@ -85,7 +86,7 @@ generate_cpm_lsrc_taps(unsigned samples_per_sym, unsigned L, double beta)
// 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) {
+ if (fabs(fabs(k) - Ls/4/beta) < 2*DBL_EPSILON) {
taps_d[i] *= M_PI_4;
} else {
double tmp = 4.0 * beta * k / Ls;
@@ -93,7 +94,7 @@ generate_cpm_lsrc_taps(unsigned samples_per_sym, unsigned L, double beta)
}
sum += taps_d[i];
}
- for (int i = 0; i < samples_per_sym * L; i++) {
+ for (unsigned i = 0; i < samples_per_sym * L; i++) {
taps[i] = (float) taps_d[i] / sum;
}
@@ -131,11 +132,11 @@ 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);
+ std::vector<double> taps_d(sps * L, 0.0);
+ std::vector<float> taps(sps * L, 0.0);
double sum = 0;
- for (int i = 0; i < sps * L; i++) {
+ 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) +
@@ -143,7 +144,7 @@ generate_cpm_tfm_taps(unsigned sps, unsigned L)
tfm_g0(k + sps, sps);
sum += taps_d[i];
}
- for (int i = 0; i < samples_per_sym * L; i++) {
+ for (unsigned i = 0; i < sps * L; i++) {
taps[i] = (float) taps_d[i] / sum;
}
@@ -167,12 +168,12 @@ 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);
+ std::vector<double> taps_d(L * samples_per_sym, 0.0);
+ std::vector<float> taps(L * samples_per_sym, 0.0);
// alpha = sqrt(2/ln(2)) * pi * BT
double alpha = 5.336446256636997 * bt;
- for (int i = 0; i < samples_per_sym * L; i++) {
+ 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)))
diff --git a/gnuradio-core/src/lib/hier/gr_cpm.h b/gnuradio-core/src/lib/general/gr_cpm.h
index f32fa44fd..f9b97f7ea 100644
--- a/gnuradio-core/src/lib/hier/gr_cpm.h
+++ b/gnuradio-core/src/lib/general/gr_cpm.h
@@ -22,6 +22,8 @@
#ifndef INCLUDED_GR_CPM_H
#define INCLUDED_GR_CPM_H
+#include <vector>
+
#define M_TWOPI (2*M_PI)
class gr_cpm
@@ -67,6 +69,10 @@ class gr_cpm
// * GAUSSIAN: A Gaussian phase response. For a modulation index h = 1/2, this
// results in GMSK.
//
+ // A short description of all these phase responses can be found in [1].
+ //
+ //
+ // [1]: Anderson, Aulin and Sundberg; Digital Phase Modulation
static std::vector<float>
phase_response(cpm_type type, unsigned samples_per_sym, unsigned L, double beta=0.3);
};
diff --git a/gnuradio-core/src/lib/hier/gr_cpm.i b/gnuradio-core/src/lib/general/gr_cpm.i
index 7145f5edd..7145f5edd 100644
--- a/gnuradio-core/src/lib/hier/gr_cpm.i
+++ b/gnuradio-core/src/lib/general/gr_cpm.i
diff --git a/gnuradio-core/src/lib/general/qa_general.cc b/gnuradio-core/src/lib/general/qa_general.cc
index 6984d798c..b9080f362 100644
--- a/gnuradio-core/src/lib/general/qa_general.cc
+++ b/gnuradio-core/src/lib/general/qa_general.cc
@@ -28,6 +28,7 @@
#include <qa_general.h>
#include <qa_gr_firdes.h>
#include <qa_gr_circular_file.h>
+#include <qa_gr_cpm.h>
#include <qa_gr_fxpt.h>
#include <qa_gr_fxpt_nco.h>
#include <qa_gr_fxpt_vco.h>
@@ -41,6 +42,7 @@ qa_general::suite ()
s->addTest (qa_gr_firdes::suite ());
s->addTest (qa_gr_circular_file::suite ());
+ s->addTest (qa_gr_cpm::suite ());
s->addTest (qa_gr_fxpt::suite ());
s->addTest (qa_gr_fxpt_nco::suite ());
s->addTest (qa_gr_fxpt_vco::suite ());
diff --git a/gnuradio-core/src/lib/hier/qa_gr_cpm.cc b/gnuradio-core/src/lib/general/qa_gr_cpm.cc
index 835ff4b28..20d72968a 100644
--- a/gnuradio-core/src/lib/hier/qa_gr_cpm.cc
+++ b/gnuradio-core/src/lib/general/qa_gr_cpm.cc
@@ -24,6 +24,8 @@
#include <gr_cpm.h>
#include <cppunit/TestAssert.h>
+const double DELTA = 1e-5;
+
// Check LREC phase response
void
qa_gr_cpm::t1 ()
@@ -33,7 +35,7 @@ qa_gr_cpm::t1 ()
std::vector<float> taps(gr_cpm::phase_response(gr_cpm::LREC, samples_per_sym, L));
for (int i = 0; i < L * samples_per_sym; i++) {
- CPPUNIT_ASSERT_DOUBLES_EQUAL(taps[i], 0.05);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(taps[i], 0.05, DELTA);
}
}
@@ -51,8 +53,8 @@ qa_gr_cpm::t2 ()
sum += taps[i];
}
- CPPUNIT_ASSERT_DOUBLES_EQUAL(sum, 1.0);
- CPPUNIT_ASSERT_DOUBLES_EQUAL(taps[L*samples_per_sym/2], 0.05);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(sum, 1.0, DELTA);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(taps[L*samples_per_sym/2], 0.1, DELTA);
}
@@ -69,7 +71,7 @@ qa_gr_cpm::t3 ()
sum += taps[i];
}
- CPPUNIT_ASSERT_DOUBLES_EQUAL(sum, 1.0);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(sum, 1.0, DELTA);
}
@@ -86,7 +88,7 @@ qa_gr_cpm::t4 ()
sum += taps[i];
}
- CPPUNIT_ASSERT_DOUBLES_EQUAL(sum, 1.0);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(sum, 1.0, DELTA);
}
diff --git a/gnuradio-core/src/lib/hier/qa_gr_cpm.h b/gnuradio-core/src/lib/general/qa_gr_cpm.h
index 16965593a..741cb2860 100644
--- a/gnuradio-core/src/lib/hier/qa_gr_cpm.h
+++ b/gnuradio-core/src/lib/general/qa_gr_cpm.h
@@ -19,21 +19,20 @@
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
-#ifndef _QA_GRI_CPM_H
-#define _QA_GRI_CPM_H
+#ifndef _QA_GR_CPM_H
+#define _QA_GR_CPM_H
#include <cppunit/extensions/HelperMacros.h>
#include <cppunit/TestCase.h>
-class qa_gri_cpm : public CppUnit::TestCase {
+class qa_gr_cpm : public CppUnit::TestCase {
- CPPUNIT_TEST_SUITE (qa_gri_cpm);
+ CPPUNIT_TEST_SUITE (qa_gr_cpm);
CPPUNIT_TEST (t1);
CPPUNIT_TEST (t2);
CPPUNIT_TEST (t3);
CPPUNIT_TEST (t4);
CPPUNIT_TEST (t5);
- CPPUNIT_TEST (t6);
CPPUNIT_TEST_SUITE_END ();
private:
@@ -42,10 +41,9 @@ class qa_gri_cpm : public CppUnit::TestCase {
void t3 ();
void t4 ();
void t5 ();
- void t6 ();
};
-#endif /* _QA_GRI_CPM_H */
+#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_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 <gri_cpm.h>
#include <gr_cpmmod_bc.h>
#include <gr_io_signature.h>
@@ -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 <gr_char_to_float.h>
#include <gr_interp_fir_filter_fff.h>
#include <gr_frequency_modulator_fc.h>
+#include <gr_cpm.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);
@@ -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<float> d_taps;
gr_char_to_float_sptr d_char_to_float;
gr_interp_fir_filter_fff_sptr d_pulse_shaper;
gr_frequency_modulator_fc_sptr d_fm;
- std::vector<float> d_taps;
public:
//! Return the phase response FIR taps