summaryrefslogtreecommitdiff
path: root/gr-digital/lib
diff options
context:
space:
mode:
authorBen Reynwar2011-06-13 13:30:19 -0700
committerBen Reynwar2011-06-13 13:30:19 -0700
commitf73984a6b43af4c4795af4b91657cc7b1ff49dae (patch)
treef7ed1390445a1a3e8905dba741163a3876ad40f2 /gr-digital/lib
parent2c8b1d999e7388c4513149615b5c7ebedb854d35 (diff)
parent5ce630cbce6460b739b175257ce0d717095a55f4 (diff)
downloadgnuradio-f73984a6b43af4c4795af4b91657cc7b1ff49dae.tar.gz
gnuradio-f73984a6b43af4c4795af4b91657cc7b1ff49dae.tar.bz2
gnuradio-f73984a6b43af4c4795af4b91657cc7b1ff49dae.zip
Merge branch '8psk' of https://github.com/trondeau/gnuradio into 8psk
Diffstat (limited to 'gr-digital/lib')
-rw-r--r--gr-digital/lib/Makefile.am2
-rw-r--r--gr-digital/lib/digital_cma_equalizer_cc.cc13
-rw-r--r--gr-digital/lib/digital_cma_equalizer_cc.h22
-rw-r--r--gr-digital/lib/digital_constellation.cc26
-rw-r--r--gr-digital/lib/digital_lms_dd_equalizer_cc.cc85
-rw-r--r--gr-digital/lib/digital_lms_dd_equalizer_cc.h116
6 files changed, 241 insertions, 23 deletions
diff --git a/gr-digital/lib/Makefile.am b/gr-digital/lib/Makefile.am
index 6f641b745..25a2b6f7f 100644
--- a/gr-digital/lib/Makefile.am
+++ b/gr-digital/lib/Makefile.am
@@ -28,6 +28,7 @@ grinclude_HEADERS = \
digital_constellation.h \
digital_costas_loop_cc.h \
digital_cma_equalizer_cc.h \
+ digital_lms_dd_equalizer_cc.h \
digital_kurtotic_equalizer_cc.h
lib_LTLIBRARIES = libgnuradio-digital.la
@@ -36,6 +37,7 @@ libgnuradio_digital_la_SOURCES = \
digital_constellation.cc \
digital_costas_loop_cc.cc \
digital_cma_equalizer_cc.cc \
+ digital_lms_dd_equalizer_cc.cc \
digital_kurtotic_equalizer_cc.cc
libgnuradio_digital_la_LIBADD = \
diff --git a/gr-digital/lib/digital_cma_equalizer_cc.cc b/gr-digital/lib/digital_cma_equalizer_cc.cc
index 89f56c16f..c6c46c2d8 100644
--- a/gr-digital/lib/digital_cma_equalizer_cc.cc
+++ b/gr-digital/lib/digital_cma_equalizer_cc.cc
@@ -25,19 +25,22 @@
#endif
#include <digital_cma_equalizer_cc.h>
+#include <cstdio>
digital_cma_equalizer_cc_sptr
-digital_make_cma_equalizer_cc(int num_taps, float modulus, float mu)
+digital_make_cma_equalizer_cc(int num_taps, float modulus, float mu, int sps)
{
- return gnuradio::get_initial_sptr(new digital_cma_equalizer_cc(num_taps, modulus, mu));
+ return gnuradio::get_initial_sptr(new digital_cma_equalizer_cc(num_taps, modulus,
+ mu, sps));
}
-digital_cma_equalizer_cc::digital_cma_equalizer_cc(int num_taps, float modulus, float mu)
- : gr_adaptive_fir_ccc("cma_equalizer_cc", 1, std::vector<gr_complex>(num_taps))
+digital_cma_equalizer_cc::digital_cma_equalizer_cc(int num_taps, float modulus,
+ float mu, int sps)
+ : gr_adaptive_fir_ccc("cma_equalizer_cc", sps,
+ std::vector<gr_complex>(num_taps, gr_complex(0,0)))
{
set_modulus(modulus);
set_gain(mu);
if (num_taps > 0)
d_taps[0] = 1.0;
}
-
diff --git a/gr-digital/lib/digital_cma_equalizer_cc.h b/gr-digital/lib/digital_cma_equalizer_cc.h
index 54cba319c..0dd99debd 100644
--- a/gr-digital/lib/digital_cma_equalizer_cc.h
+++ b/gr-digital/lib/digital_cma_equalizer_cc.h
@@ -31,7 +31,7 @@ class digital_cma_equalizer_cc;
typedef boost::shared_ptr<digital_cma_equalizer_cc> digital_cma_equalizer_cc_sptr;
digital_cma_equalizer_cc_sptr
-digital_make_cma_equalizer_cc(int num_taps, float modulus, float mu);
+digital_make_cma_equalizer_cc(int num_taps, float modulus, float mu, int sps);
/*!
* \brief Implements constant modulus adaptive filter on complex stream
@@ -51,8 +51,9 @@ private:
friend digital_cma_equalizer_cc_sptr digital_make_cma_equalizer_cc(int num_taps,
float modulus,
- float mu);
- digital_cma_equalizer_cc(int num_taps, float modulus, float mu);
+ float mu,
+ int sps);
+ digital_cma_equalizer_cc(int num_taps, float modulus, float mu, int sps);
protected:
@@ -71,12 +72,23 @@ protected:
}
public:
+ float get_gain()
+ {
+ return d_mu;
+ }
+
void set_gain(float mu)
{
- if(mu < 0)
- throw std::out_of_range("digital_cma_equalizer::set_gain: Gain value must be >= 0");
+ if(mu < 0.0f || mu > 1.0f) {
+ throw std::out_of_range("digital_cma_equalizer::set_gain: Gain value must be in [0,1]");
+ }
d_mu = mu;
}
+
+ float get_modulus()
+ {
+ return d_modulus;
+ }
void set_modulus(float mod)
{
diff --git a/gr-digital/lib/digital_constellation.cc b/gr-digital/lib/digital_constellation.cc
index bfed84320..edf0bda22 100644
--- a/gr-digital/lib/digital_constellation.cc
+++ b/gr-digital/lib/digital_constellation.cc
@@ -433,7 +433,7 @@ digital_constellation_8psk::digital_constellation_8psk ()
d_constellation.resize(8);
// Gray-coded
d_constellation[0] = gr_complex(cos( 1*angle), sin( 1*angle));
- d_constellation[1] = gr_complex(cos( 7*angle), sin( 3*angle));
+ d_constellation[1] = gr_complex(cos( 7*angle), sin( 7*angle));
d_constellation[2] = gr_complex(cos(15*angle), sin(15*angle));
d_constellation[3] = gr_complex(cos( 9*angle), sin( 9*angle));
d_constellation[4] = gr_complex(cos( 3*angle), sin( 3*angle));
@@ -448,17 +448,17 @@ digital_constellation_8psk::digital_constellation_8psk ()
unsigned int
digital_constellation_8psk::decision_maker(const gr_complex *sample)
{
- // Real component determines small bit.
- // Imag component determines big bit.
- return 2*(imag(*sample)>0) + (real(*sample)>0);
+ unsigned int ret = 0;
- unsigned int real, imag;
- imag = 2*(sample->imag()<=0);
- real = (sample->real()<=0);
- if(abs(sample->real()) >= abs(sample->imag())) {
- return 0 + imag + real;
- }
- else {
- return 4 + imag + real;
- }
+ float re = sample->real();
+ float im = sample->imag();
+
+ if(fabsf(re) <= fabsf(im))
+ ret = 4;
+ if(re <= 0)
+ ret |= 1;
+ if(im <= 0)
+ ret |= 2;
+
+ return ret;
}
diff --git a/gr-digital/lib/digital_lms_dd_equalizer_cc.cc b/gr-digital/lib/digital_lms_dd_equalizer_cc.cc
new file mode 100644
index 000000000..e2c2f16f2
--- /dev/null
+++ b/gr-digital/lib/digital_lms_dd_equalizer_cc.cc
@@ -0,0 +1,85 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2011 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <digital_lms_dd_equalizer_cc.h>
+#include <gr_io_signature.h>
+#include <gr_misc.h>
+#include <iostream>
+
+digital_lms_dd_equalizer_cc_sptr
+digital_make_lms_dd_equalizer_cc(int num_taps, float mu, int sps,
+ digital_constellation_sptr cnst)
+{
+ return gnuradio::get_initial_sptr(new digital_lms_dd_equalizer_cc(num_taps, mu,
+ sps, cnst));
+}
+
+digital_lms_dd_equalizer_cc::digital_lms_dd_equalizer_cc(int num_taps, float mu,
+ int sps,
+ digital_constellation_sptr cnst)
+ : gr_adaptive_fir_ccc("lms_dd_equalizer_cc", sps,
+ std::vector<gr_complex>(num_taps, gr_complex(0,0))),
+ d_taps(num_taps), d_cnst(cnst)
+{
+ set_gain(mu);
+ if (num_taps > 0)
+ d_taps[num_taps/2] = 1.0;
+}
+
+
+
+
+/*
+int
+digital_lms_dd_equalizer_cc::work (int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+{
+ const gr_complex *in = (const gr_complex *) input_items[0];
+ gr_complex *out = (gr_complex *) output_items[0];
+
+ gr_complex acc, decision, error;
+
+ for(int i = 0; i < noutput_items; i++) {
+ acc = 0;
+
+ // Compute output
+ for (size_t j=0; j < d_taps.size(); j++)
+ acc += in[i+j] * conj(d_taps[j]);
+
+ d_cnst->map_to_points(d_cnst->decision_maker(&acc), &decision);
+ error = decision - acc;
+
+ // Update taps
+ for (size_t j=0; j < d_taps.size(); j++)
+ d_taps[j] += d_mu * conj(error) * in[i+j];
+
+ out[i] = acc;
+ }
+
+ return noutput_items;
+}
+*/
diff --git a/gr-digital/lib/digital_lms_dd_equalizer_cc.h b/gr-digital/lib/digital_lms_dd_equalizer_cc.h
new file mode 100644
index 000000000..e3ad4bf4a
--- /dev/null
+++ b/gr-digital/lib/digital_lms_dd_equalizer_cc.h
@@ -0,0 +1,116 @@
+/* -*- 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.
+ */
+
+#ifndef INCLUDED_DIGITAL_LMS_DD_EQUALIZER_CC_H
+#define INCLUDED_DIGITAL_LMS_DD_EQUALIZER_CC_H
+
+#include <gr_adaptive_fir_ccc.h>
+#include <digital_constellation.h>
+
+class digital_lms_dd_equalizer_cc;
+typedef boost::shared_ptr<digital_lms_dd_equalizer_cc> digital_lms_dd_equalizer_cc_sptr;
+
+digital_lms_dd_equalizer_cc_sptr digital_make_lms_dd_equalizer_cc (int num_taps,
+ float mu, int sps,
+ digital_constellation_sptr cnst);
+
+/*!
+ * \brief Least-Mean-Square Decision Directed Equalizer (complex in/out)
+ * \ingroup eq_blk
+ *
+ * This block implements an LMS-based decision-directed equalizer.
+ * It uses a set of weights, w, to correlate against the inputs, u,
+ * and a decisions is then made from this output. The error
+ * in the decision is used to update teh weight vector.
+ *
+ * y[n] = conj(w[n]) u[n]
+ * d[n] = decision(y[n])
+ * e[n] = d[n] - y[n]
+ * w[n+1] = w[n] + mu u[n] conj(e[n])
+ *
+ * Where mu is a gain value (between 0 and 1 and usualy small,
+ * around 0.001 - 0.01.
+ *
+ * This block uses the digital_constellation object for making
+ * the decision from y[n]. Create the constellation object for
+ * whatever constellation is to be used and pass in the object.
+ * In Python, you can use something like:
+ * self.constellation = digital.constellation_qpsk()
+ * To create a QPSK constellation (see the digital_constellation
+ * block for more details as to what constellations are available
+ * or how to create your own). You then pass the object to this
+ * block as an sptr, or using "self.constellation.base()".
+ *
+ * The theory for this algorithm can be found in Chapter 9 of:
+ * S. Haykin, Adaptive Filter Theory, Upper Saddle River, NJ:
+ * Prentice Hall, 1996.
+ *
+ */
+class digital_lms_dd_equalizer_cc : public gr_adaptive_fir_ccc
+{
+private:
+ friend digital_lms_dd_equalizer_cc_sptr digital_make_lms_dd_equalizer_cc (int num_taps,
+ float mu, int sps,
+ digital_constellation_sptr cnst);
+
+ float d_mu;
+ std::vector<gr_complex> d_taps;
+ digital_constellation_sptr d_cnst;
+
+ digital_lms_dd_equalizer_cc (int num_taps,
+ float mu, int sps,
+ digital_constellation_sptr cnst);
+
+protected:
+
+ virtual gr_complex error(const gr_complex &out)
+ {
+ gr_complex decision, error;
+ d_cnst->map_to_points(d_cnst->decision_maker(&out), &decision);
+ error = decision - out;
+ return error;
+ }
+
+ virtual void update_tap(gr_complex &tap, const gr_complex &in)
+ {
+ tap += d_mu*conj(in)*d_error;
+ }
+
+public:
+ float get_gain()
+ {
+ return d_mu;
+ }
+
+ void set_gain(float mu)
+ {
+ if(mu < 0.0f || mu > 1.0f) {
+ throw std::out_of_range("digital_lms_dd_equalizer::set_mu: Gain value must in [0, 1]");
+ }
+ else {
+ d_mu = mu;
+ }
+ }
+
+};
+
+#endif