summaryrefslogtreecommitdiff
path: root/gr-digital
diff options
context:
space:
mode:
Diffstat (limited to 'gr-digital')
-rw-r--r--gr-digital/CMakeLists.txt3
-rw-r--r--gr-digital/Makefile.am2
-rw-r--r--gr-digital/examples/CMakeLists.txt27
-rwxr-xr-xgr-digital/examples/benchmark_add_channel.py101
-rw-r--r--gr-digital/grc/Makefile.am4
-rw-r--r--gr-digital/grc/digital_block_tree.xml2
-rw-r--r--gr-digital/grc/digital_costas_loop_cc.xml12
-rw-r--r--gr-digital/grc/digital_fll_band_edge_cc.xml70
-rw-r--r--gr-digital/grc/digital_mpsk_receiver_cc.xml75
-rw-r--r--gr-digital/hier/.gitignore2
-rw-r--r--gr-digital/hier/CMakeLists.txt43
-rw-r--r--gr-digital/hier/Makefile.am40
-rw-r--r--gr-digital/hier/_digital_hier.i33
-rw-r--r--gr-digital/hier/digital_cpmmod_bc.cc69
-rw-r--r--gr-digital/hier/digital_cpmmod_bc.h96
-rw-r--r--gr-digital/hier/digital_cpmmod_bc.i40
-rw-r--r--gr-digital/hier/digital_gmskmod_bc.cc44
-rw-r--r--gr-digital/hier/digital_gmskmod_bc.h62
-rw-r--r--gr-digital/hier/digital_gmskmod_bc.i39
-rw-r--r--gr-digital/lib/Makefile.am3
-rw-r--r--gr-digital/lib/digital_constellation.cc86
-rw-r--r--gr-digital/lib/digital_constellation.h90
-rw-r--r--gr-digital/lib/digital_constellation_receiver_cb.cc145
-rw-r--r--gr-digital/lib/digital_constellation_receiver_cb.h147
-rw-r--r--gr-digital/lib/digital_fll_band_edge_cc.cc139
-rw-r--r--gr-digital/lib/digital_fll_band_edge_cc.h218
-rw-r--r--gr-digital/lib/digital_mpsk_receiver_cc.cc36
-rw-r--r--gr-digital/lib/digital_mpsk_receiver_cc.h169
-rw-r--r--gr-digital/python/Makefile.am1
-rw-r--r--gr-digital/python/__init__.py1
-rw-r--r--gr-digital/python/generic_mod_demod.py23
-rw-r--r--gr-digital/python/gmsk.py106
-rwxr-xr-xgr-digital/python/qa_constellation.py11
-rwxr-xr-xgr-digital/python/qa_constellation_receiver.py12
-rwxr-xr-xgr-digital/python/qa_cpm.py91
-rwxr-xr-x[-rw-r--r--]gr-digital/python/qa_crc32.py0
-rwxr-xr-x[-rw-r--r--]gr-digital/python/qa_fll_band_edge.py0
-rwxr-xr-x[-rw-r--r--]gr-digital/python/qa_lms_equalizer.py0
-rwxr-xr-x[-rw-r--r--]gr-digital/python/qa_mpsk_receiver.py26
-rw-r--r--gr-digital/python/qpsk.py67
-rw-r--r--gr-digital/swig/CMakeLists.txt3
-rw-r--r--gr-digital/swig/Makefile.am10
-rw-r--r--gr-digital/swig/Makefile.swig.gen148
-rw-r--r--gr-digital/swig/digital_constellation.i18
-rw-r--r--gr-digital/swig/digital_constellation_receiver_cb.i16
-rw-r--r--gr-digital/swig/digital_fll_band_edge_cc.i2
-rw-r--r--gr-digital/swig/digital_hier.i40
-rw-r--r--gr-digital/swig/digital_mpsk_receiver_cc.i14
-rw-r--r--gr-digital/swig/digital_swig.i1
49 files changed, 1525 insertions, 862 deletions
diff --git a/gr-digital/CMakeLists.txt b/gr-digital/CMakeLists.txt
index cc00da69a9..bd11be4d32 100644
--- a/gr-digital/CMakeLists.txt
+++ b/gr-digital/CMakeLists.txt
@@ -33,6 +33,7 @@ GR_REGISTER_COMPONENT("gr-digital" ENABLE_GR_DIGITAL
GR_SET_GLOBAL(GR_DIGITAL_INCLUDE_DIRS
${CMAKE_CURRENT_SOURCE_DIR}/lib
+ ${CMAKE_CURRENT_SOURCE_DIR}/hier
)
GR_SET_GLOBAL(GR_DIGITAL_SWIG_INCLUDE_DIRS
@@ -81,11 +82,13 @@ CPACK_COMPONENT("digital_swig"
########################################################################
# Add subdirectories
########################################################################
+GR_INCLUDE_SUBDIRECTORY(hier) #appends to lib sources
ADD_SUBDIRECTORY(lib)
IF(ENABLE_PYTHON)
ADD_SUBDIRECTORY(swig)
ADD_SUBDIRECTORY(python)
ADD_SUBDIRECTORY(grc)
+ ADD_SUBDIRECTORY(examples)
ENDIF(ENABLE_PYTHON)
########################################################################
diff --git a/gr-digital/Makefile.am b/gr-digital/Makefile.am
index f1409793ff..346db120f5 100644
--- a/gr-digital/Makefile.am
+++ b/gr-digital/Makefile.am
@@ -21,7 +21,7 @@
include $(top_srcdir)/Makefile.common
-SUBDIRS = lib
+SUBDIRS = hier lib
if PYTHON
SUBDIRS += swig python apps grc examples
diff --git a/gr-digital/examples/CMakeLists.txt b/gr-digital/examples/CMakeLists.txt
new file mode 100644
index 0000000000..55a8379d9a
--- /dev/null
+++ b/gr-digital/examples/CMakeLists.txt
@@ -0,0 +1,27 @@
+# Copyright 2011 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+
+INCLUDE(GrPython)
+
+GR_PYTHON_INSTALL(PROGRAMS
+ transmit_path.py
+ receive_path.py
+ DESTINATION ${GR_PKG_DATA_DIR}/examples/digital
+ COMPONENT "digital_python"
+)
diff --git a/gr-digital/examples/benchmark_add_channel.py b/gr-digital/examples/benchmark_add_channel.py
new file mode 100755
index 0000000000..def1f8267e
--- /dev/null
+++ b/gr-digital/examples/benchmark_add_channel.py
@@ -0,0 +1,101 @@
+#!/usr/bin/env python
+#
+# Copyright 2010,2011 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+
+from gnuradio import gr
+from gnuradio import eng_notation
+from gnuradio.eng_option import eng_option
+from optparse import OptionParser
+
+import random, math, sys
+
+class my_top_block(gr.top_block):
+ def __init__(self, ifile, ofile, options):
+ gr.top_block.__init__(self)
+
+ SNR = 10.0**(options.snr/10.0)
+ frequency_offset = options.frequency_offset
+ time_offset = options.time_offset
+ phase_offset = options.phase_offset*(math.pi/180.0)
+
+ # calculate noise voltage from SNR
+ # FIXME: normalize to signal amplitude
+ power_in_signal = abs(1.0)**2
+ noise_power = power_in_signal/SNR
+ noise_voltage = math.sqrt(noise_power)
+ print noise_voltage
+
+ self.src = gr.file_source(gr.sizeof_gr_complex, ifile)
+ #self.throttle = gr.throttle(gr.sizeof_gr_complex, options.sample_rate)
+ self.channel = gr.channel_model(noise_voltage, frequency_offset,
+ time_offset, noise_seed=random.randint(0,100000))
+ self.phase = gr.multiply_const_cc(complex(math.cos(phase_offset),
+ math.sin(phase_offset)))
+ self.snk = gr.file_sink(gr.sizeof_gr_complex, ofile)
+
+ self.connect(self.src, self.channel, self.phase, self.snk)
+
+
+# /////////////////////////////////////////////////////////////////////////////
+# main
+# /////////////////////////////////////////////////////////////////////////////
+
+def main():
+ # Create Options Parser:
+ usage = "benchmack_add_channel.py [options] <input file> <output file>"
+ parser = OptionParser (usage=usage, option_class=eng_option, conflict_handler="resolve")
+ parser.add_option("-n", "--snr", type="eng_float", default=30,
+ help="set the SNR of the channel in dB [default=%default]")
+ parser.add_option("", "--seed", action="store_true", default=False,
+ help="use a random seed for AWGN noise [default=%default]")
+ parser.add_option("-f", "--frequency-offset", type="eng_float", default=0,
+ help="set frequency offset introduced by channel [default=%default]")
+ parser.add_option("-t", "--time-offset", type="eng_float", default=1.0,
+ help="set timing offset between Tx and Rx [default=%default]")
+ parser.add_option("-p", "--phase-offset", type="eng_float", default=0,
+ help="set phase offset (in degrees) between Tx and Rx [default=%default]")
+ parser.add_option("-m", "--use-multipath", action="store_true", default=False,
+ help="Use a multipath channel [default=%default]")
+
+ (options, args) = parser.parse_args ()
+
+ if len(args) != 2:
+ parser.print_help(sys.stderr)
+ sys.exit(1)
+
+ ifile = args[0]
+ ofile = args[1]
+
+ # build the graph
+ tb = my_top_block(ifile, ofile, options)
+
+ r = gr.enable_realtime_scheduling()
+ if r != gr.RT_OK:
+ print "Warning: Failed to enable realtime scheduling."
+
+ tb.start() # start flow graph
+ tb.wait() # wait for it to finish
+
+if __name__ == '__main__':
+ try:
+ main()
+ except KeyboardInterrupt:
+ pass
diff --git a/gr-digital/grc/Makefile.am b/gr-digital/grc/Makefile.am
index d271ca06a8..963939f127 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 1be4110e17..3432d876c1 100644
--- a/gr-digital/grc/digital_block_tree.xml
+++ b/gr-digital/grc/digital_block_tree.xml
@@ -34,6 +34,8 @@
<block>digital_cma_equalizer_cc</block>
<block>digital_lms_dd_equalizer_cc</block>
<block>digital_kurtotic_equalizer_cc</block>
+ <block>digital_fll_band_edge_cc</block>
+ <block>digital_mpsk_receiver_cc</block>
</cat>
<cat>
<name>Digital Modulators</name>
diff --git a/gr-digital/grc/digital_costas_loop_cc.xml b/gr-digital/grc/digital_costas_loop_cc.xml
index 087535b879..668c43dec6 100644
--- a/gr-digital/grc/digital_costas_loop_cc.xml
+++ b/gr-digital/grc/digital_costas_loop_cc.xml
@@ -8,16 +8,10 @@
<name>Costas Loop</name>
<key>digital_costas_loop_cc</key>
<import>from gnuradio import digital</import>
- <make>digital.costas_loop_cc($eta, $w, $order)</make>
- <callback>set_damping_factor($eta)</callback>
- <callback>set_natural_freq($w)</callback>
+ <make>digital.costas_loop_cc($w, $order)</make>
+ <callback>set_loop_bandwidth($w)</callback>
<param>
- <name>Damping Factor</name>
- <key>eta</key>
- <type>real</type>
- </param>
- <param>
- <name>Natural Frequency</name>
+ <name>Loop Bandwidth</name>
<key>w</key>
<type>real</type>
</param>
diff --git a/gr-digital/grc/digital_fll_band_edge_cc.xml b/gr-digital/grc/digital_fll_band_edge_cc.xml
new file mode 100644
index 0000000000..1c5a34e540
--- /dev/null
+++ b/gr-digital/grc/digital_fll_band_edge_cc.xml
@@ -0,0 +1,70 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+## FLL using Band-Edge Filters
+###################################################
+ -->
+<block>
+ <name>FLL Band-Edge</name>
+ <key>gr_fll_band_edge_cc</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.fll_band_edge_cc($samps_per_sym, $rolloff, $filter_size, $w)</make>
+ <callback>set_loop_bandwidth($w)</callback>
+ <param>
+ <name>Type</name>
+ <key>type</key>
+ <type>enum</type>
+ <option>
+ <name>Complex->Complex</name>
+ <key>cc</key>
+ <opt>input:complex</opt>
+ <opt>output:complex</opt>
+ </option>
+ </param>
+
+ <param>
+ <name>Samples Per Symbol</name>
+ <key>samps_per_sym</key>
+ <type>real</type>
+ </param>
+ <param>
+ <name>Filter Rolloff Factor</name>
+ <key>rolloff</key>
+ <type>real</type>
+ </param>
+ <param>
+ <name>Prototype Filter Size</name>
+ <key>filter_size</key>
+ <type>int</type>
+ </param>
+
+ <param>
+ <name>Loop Bandwidth</name>
+ <key>w</key>
+ <type>real</type>
+ </param>
+
+ <sink>
+ <name>in</name>
+ <type>$type.input</type>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>$type.output</type>
+ </source>
+ <source>
+ <name>freq</name>
+ <type>float</type>
+ <optional>1</optional>
+ </source>
+ <source>
+ <name>phase</name>
+ <type>float</type>
+ <optional>1</optional>
+ </source>
+ <source>
+ <name>error</name>
+ <type>float</type>
+ <optional>1</optional>
+ </source>
+</block>
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 0000000000..948f18b6e6
--- /dev/null
+++ b/gr-digital/grc/digital_mpsk_receiver_cc.xml
@@ -0,0 +1,75 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##MPSK Receiver
+###################################################
+ -->
+<block>
+ <name>MPSK Receiver</name>
+ <key>gr_mpsk_receiver_cc</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.mpsk_receiver_cc($M, $theta, $w, $fmin, $fmax, $mu, $gain_mu, $omega, $gain_omega, $omega_relative_limit)</make>
+ <callback>set_loop_bandwidth($w)</callback>
+ <callback>set_mu($mu)</callback>
+ <callback>set_gain_mu($gain_mu)</callback>
+ <callback>set_omega($omega)</callback>
+ <callback>set_gain_omega($gain_omega)</callback>
+ <param>
+ <name>M</name>
+ <key>M</key>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Theta</name>
+ <key>theta</key>
+ <type>real</type>
+ </param>
+ <param>
+ <name>Loop Bandwidth</name>
+ <key>w</key>
+ <type>real</type>
+ </param>
+ <param>
+ <name>Min Freq</name>
+ <key>fmin</key>
+ <type>real</type>
+ </param>
+ <param>
+ <name>Max Freq</name>
+ <key>fmax</key>
+ <type>real</type>
+ </param>
+ <param>
+ <name>Mu</name>
+ <key>mu</key>
+ <type>real</type>
+ </param>
+ <param>
+ <name>Gain Mu</name>
+ <key>gain_mu</key>
+ <type>real</type>
+ </param>
+ <param>
+ <name>Omega</name>
+ <key>omega</key>
+ <type>real</type>
+ </param>
+ <param>
+ <name>Gain Omega</name>
+ <key>gain_omega</key>
+ <type>real</type>
+ </param>
+ <param>
+ <name>Omega Relative Limit</name>
+ <key>omega_relative_limit</key>
+ <type>real</type>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>complex</type>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>complex</type>
+ </source>
+</block>
diff --git a/gr-digital/hier/.gitignore b/gr-digital/hier/.gitignore
new file mode 100644
index 0000000000..b336cc7cec
--- /dev/null
+++ b/gr-digital/hier/.gitignore
@@ -0,0 +1,2 @@
+/Makefile
+/Makefile.in
diff --git a/gr-digital/hier/CMakeLists.txt b/gr-digital/hier/CMakeLists.txt
new file mode 100644
index 0000000000..f46acc81e0
--- /dev/null
+++ b/gr-digital/hier/CMakeLists.txt
@@ -0,0 +1,43 @@
+# Copyright 2011 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+
+########################################################################
+# This file included, use CMake directory variables
+########################################################################
+
+LIST(APPEND gr_digital_sources
+ ${CMAKE_CURRENT_SOURCE_DIR}/digital_gmskmod_bc.cc
+ ${CMAKE_CURRENT_SOURCE_DIR}/digital_cpmmod_bc.cc
+)
+
+INSTALL(FILES
+ ${CMAKE_CURRENT_SOURCE_DIR}/digital_gmskmod_bc.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/digital_cpmmod_bc.h
+ DESTINATION ${GR_INCLUDE_DIR}/gnuradio
+ COMPONENT "digital_devel"
+)
+
+INSTALL(
+ FILES
+ ${CMAKE_CURRENT_SOURCE_DIR}/_digital_hier.i
+ ${CMAKE_CURRENT_SOURCE_DIR}/digital_gmskmod_bc.i
+ ${CMAKE_CURRENT_SOURCE_DIR}/digital_cpmmod_bc.i
+ DESTINATION ${GR_INCLUDE_DIR}/gnuradio/swig
+ COMPONENT "digital_swig"
+)
diff --git a/gr-digital/hier/Makefile.am b/gr-digital/hier/Makefile.am
new file mode 100644
index 0000000000..b11b85f77c
--- /dev/null
+++ b/gr-digital/hier/Makefile.am
@@ -0,0 +1,40 @@
+#
+# Copyright 2011 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+
+include $(top_srcdir)/Makefile.common
+
+AM_CPPFLAGS = $(STD_DEFINES_AND_INCLUDES) $(WITH_INCLUDES)
+
+noinst_LTLIBRARIES = libdigital_hier.la
+
+libdigital_hier_la_SOURCES = \
+ digital_gmskmod_bc.cc \
+ digital_cpmmod_bc.cc
+
+grinclude_HEADERS = \
+ digital_gmskmod_bc.h \
+ digital_cpmmod_bc.h
+
+
+swiginclude_HEADERS = \
+ _digital_hier.i \
+ digital_gmskmod_bc.i \
+ digital_cpmmod_bc.i
diff --git a/gr-digital/hier/_digital_hier.i b/gr-digital/hier/_digital_hier.i
new file mode 100644
index 0000000000..022e38644b
--- /dev/null
+++ b/gr-digital/hier/_digital_hier.i
@@ -0,0 +1,33 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2011 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+%{
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <digital_cpmmod_bc.h>
+#include <digital_gmskmod_bc.h>
+%}
+
+%include "digital_cpmmod_bc.i"
+%include "digital_gmskmod_bc.i"
diff --git a/gr-digital/hier/digital_cpmmod_bc.cc b/gr-digital/hier/digital_cpmmod_bc.cc
new file mode 100644
index 0000000000..a95b604d14
--- /dev/null
+++ b/gr-digital/hier/digital_cpmmod_bc.cc
@@ -0,0 +1,69 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2010 Free Software Foundation, Inc.
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <digital_cpmmod_bc.h>
+#include <gr_io_signature.h>
+
+
+// Shared pointer constructor
+digital_cpmmod_bc_sptr
+digital_make_cpmmod_bc(int type, float h,
+ unsigned samples_per_sym,
+ unsigned L, double beta)
+{
+ return gnuradio::get_initial_sptr(new digital_cpmmod_bc((gr_cpm::cpm_type)type,
+ h, samples_per_sym,
+ L, beta));
+}
+
+
+digital_cpmmod_bc::digital_cpmmod_bc(gr_cpm::cpm_type type, float h,
+ unsigned samples_per_sym,
+ unsigned L, double beta)
+ : gr_hier_block2("digital_cpmmod_bc",
+ gr_make_io_signature(1, 1, sizeof(char)),
+ gr_make_io_signature2(1, 1, sizeof(gr_complex), sizeof(float))),
+ d_taps(gr_cpm::phase_response(type, samples_per_sym, L, beta)),
+ d_char_to_float(gr_make_char_to_float()),
+ d_pulse_shaper(gr_make_interp_fir_filter_fff(samples_per_sym, d_taps)),
+ d_fm(gr_make_frequency_modulator_fc(M_PI * h))
+{
+ switch (type) {
+ case gr_cpm::LRC:
+ case gr_cpm::LSRC:
+ case gr_cpm::LREC:
+ case gr_cpm::TFM:
+ case gr_cpm::GAUSSIAN:
+ break;
+
+ default:
+ throw std::invalid_argument("invalid CPM type");
+ }
+
+ connect(self(), 0, d_char_to_float, 0);
+ connect(d_char_to_float, 0, d_pulse_shaper, 0);
+ connect(d_pulse_shaper, 0, d_fm, 0);
+ connect(d_fm, 0, self(), 0);
+}
+
diff --git a/gr-digital/hier/digital_cpmmod_bc.h b/gr-digital/hier/digital_cpmmod_bc.h
new file mode 100644
index 0000000000..4e9547cd64
--- /dev/null
+++ b/gr-digital/hier/digital_cpmmod_bc.h
@@ -0,0 +1,96 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2010 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_DIGITAL_CPMMOD_BC_H
+#define INCLUDED_DIGITAL_CPMMOD_BC_H
+
+#include <digital_api.h>
+#include <gr_hier_block2.h>
+#include <gr_char_to_float.h>
+#include <gr_interp_fir_filter_fff.h>
+#include <gr_frequency_modulator_fc.h>
+#include <gr_cpm.h>
+
+
+class digital_cpmmod_bc;
+typedef boost::shared_ptr<digital_cpmmod_bc> digital_cpmmod_bc_sptr;
+
+
+DIGITAL_API digital_cpmmod_bc_sptr
+digital_make_cpmmod_bc(int type, float h,
+ unsigned samples_per_sym,
+ unsigned L, double beta=0.3);
+
+/*!
+ * \brief Generic CPM modulator
+ *
+ * \ingroup modulation_blk
+ *
+ * \param type The modulation type. Can be one of LREC, LRC, LSRC, TFM
+ * or GAUSSIAN. See gr_cpm::phase_response() for a
+ * detailed description.
+ * \param h The modulation index. \f$ h \cdot \pi\f$ is the maximum
+ * phase change that can occur between two symbols, i.e., if
+ * you only send ones, the phase will increase by \f$ h \cdot
+ * \pi\f$ every \p samples_per_sym samples. Set this to 0.5
+ * for Minimum Shift Keying variants.
+ * \param samples_per_sym Samples per symbol.
+ * \param L The length of the phase duration in symbols. For L=1, this
+ * yields full- response CPM symbols, for L > 1,
+ * partial-response.
+ * \param beta For LSRC, this is the rolloff factor. For Gaussian
+ * pulses, this is the 3 dB time-bandwidth product.
+ *
+ * Examples:
+ * - Setting h = 0.5, L = 1, type = LREC yields MSK.
+ * - Setting h = 0.5, type = GAUSSIAN and beta = 0.3 yields GMSK
+ * as used in GSM.
+ *
+ * The input of this block are symbols from an M-ary alphabet
+ * +/-1, +/-3, ..., +/-(M-1). Usually, M = 2 and therefore, the
+ * valid inputs are +/-1.
+ * The modulator will silently accept any other inputs, though.
+ * The output is the phase-modulated signal.
+ */
+class DIGITAL_API digital_cpmmod_bc : public gr_hier_block2
+{
+ friend DIGITAL_API digital_cpmmod_bc_sptr digital_make_cpmmod_bc(int type, float h,
+ unsigned samples_per_sym,
+ unsigned L, double beta);
+
+ std::vector<float> d_taps;
+ gr_char_to_float_sptr d_char_to_float;
+ gr_interp_fir_filter_fff_sptr d_pulse_shaper;
+ gr_frequency_modulator_fc_sptr d_fm;
+
+protected:
+ digital_cpmmod_bc(gr_cpm::cpm_type type, float h,
+ unsigned samples_per_sym,
+ unsigned L, double beta);
+
+public:
+ //! Return the phase response FIR taps
+ std::vector<float> get_taps() { return d_taps; };
+};
+
+#endif /* INCLUDED_DIGITAL_CPMMOD_BC_H */
+
diff --git a/gr-digital/hier/digital_cpmmod_bc.i b/gr-digital/hier/digital_cpmmod_bc.i
new file mode 100644
index 0000000000..fa7c50da75
--- /dev/null
+++ b/gr-digital/hier/digital_cpmmod_bc.i
@@ -0,0 +1,40 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2010 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+GR_SWIG_BLOCK_MAGIC(digital, cpmmod_bc)
+
+digital_cpmmod_bc_sptr
+digital_make_cpmmod_bc(int type, float h,
+ unsigned samples_per_sym,
+ unsigned L, double beta=0.3);
+
+class digital_cpmmod_bc : public gr_hier_block2
+{
+ private:
+ digital_cpmmod_bc(int type, float h,
+ unsigned samples_per_sym,
+ unsigned L, double beta);
+
+ public:
+ std::vector<float> get_taps();
+};
+
diff --git a/gr-digital/hier/digital_gmskmod_bc.cc b/gr-digital/hier/digital_gmskmod_bc.cc
new file mode 100644
index 0000000000..e53e900370
--- /dev/null
+++ b/gr-digital/hier/digital_gmskmod_bc.cc
@@ -0,0 +1,44 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2010 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <digital_gmskmod_bc.h>
+#include <gr_io_signature.h>
+
+// Shared pointer constructor
+digital_gmskmod_bc_sptr
+digital_make_gmskmod_bc(unsigned samples_per_sym,
+ double bt, unsigned L)
+{
+ return gnuradio::get_initial_sptr(new digital_gmskmod_bc(samples_per_sym, bt, L));
+}
+
+
+digital_gmskmod_bc::digital_gmskmod_bc(unsigned samples_per_sym,
+ double bt, unsigned L)
+ : digital_cpmmod_bc(gr_cpm::GAUSSIAN, 0.5, samples_per_sym, L, bt)
+{
+}
+
diff --git a/gr-digital/hier/digital_gmskmod_bc.h b/gr-digital/hier/digital_gmskmod_bc.h
new file mode 100644
index 0000000000..33fcc6c126
--- /dev/null
+++ b/gr-digital/hier/digital_gmskmod_bc.h
@@ -0,0 +1,62 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2010 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_DIGITAL_GMSKMOD_BC_H
+#define INCLUDED_DIGITAL_GMSKMOD_BC_H
+
+#include <digital_api.h>
+#include <digital_cpmmod_bc.h>
+
+class digital_gmskmod_bc;
+typedef boost::shared_ptr<digital_gmskmod_bc> digital_gmskmod_bc_sptr;
+
+
+DIGITAL_API digital_gmskmod_bc_sptr
+digital_make_gmskmod_bc(unsigned samples_per_sym=2,
+ double bt=0.3, unsigned L=4);
+
+/*!
+ * \brief GMSK modulator
+ *
+ * \ingroup modulation_blk
+ *
+ * \param samples_per_sym Samples per symbol.
+ * \param bt The 3 dB time-bandwidth product.
+ * \param L The length of the phase duration in symbols. The Gaussian
+ * pulse is truncated after L symbols.
+ *
+ * The input of this block are symbols from an M-ary alphabet
+ * +/-1, +/-3, ..., +/-(M-1). Usually, M = 2 and therefore, the
+ * valid inputs are +/-1.
+ * The modulator will silently accept any other inputs, though.
+ * The output is the phase-modulated signal.
+ */
+class DIGITAL_API digital_gmskmod_bc : public digital_cpmmod_bc
+{
+ friend DIGITAL_API digital_gmskmod_bc_sptr digital_make_gmskmod_bc(unsigned samples_per_sym,
+ double bt, unsigned L);
+ digital_gmskmod_bc(unsigned samples_per_sym,
+ double bt, unsigned L);
+};
+
+#endif /* INCLUDED_DIGITAL_GMSKMOD_BC_H */
+
diff --git a/gr-digital/hier/digital_gmskmod_bc.i b/gr-digital/hier/digital_gmskmod_bc.i
new file mode 100644
index 0000000000..ad7b82237e
--- /dev/null
+++ b/gr-digital/hier/digital_gmskmod_bc.i
@@ -0,0 +1,39 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2010 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+GR_SWIG_BLOCK_MAGIC(digital, gmskmod_bc)
+
+digital_gmskmod_bc_sptr
+digital_make_gmskmod_bc(unsigned samples_per_sym=2,
+ double bt=0.3, unsigned L=4);
+
+class digital_gmskmod_bc : public gr_hier_block2
+{
+ private:
+ digital_cpmmod_bc(int type, float h,
+ unsigned samples_per_sym,
+ double beta, unsigned L);
+
+ public:
+ std::vector<float> get_taps();
+};
+
diff --git a/gr-digital/lib/Makefile.am b/gr-digital/lib/Makefile.am
index 4a9359fce2..ce961ef2ee 100644
--- a/gr-digital/lib/Makefile.am
+++ b/gr-digital/lib/Makefile.am
@@ -61,6 +61,7 @@ libgnuradio_digital_la_SOURCES = \
digital_mpsk_receiver_cc.cc
libgnuradio_digital_la_LIBADD = \
- $(GNURADIO_CORE_LA)
+ $(GNURADIO_CORE_LA) \
+ $(abs_top_builddir)/gr-digital/hier/libdigital_hier.la
libgnuradio_digital_la_LDFLAGS = $(NO_UNDEFINED) $(LTVERSIONFLAGS)
diff --git a/gr-digital/lib/digital_constellation.cc b/gr-digital/lib/digital_constellation.cc
index d1f2184391..0c100f38ed 100644
--- a/gr-digital/lib/digital_constellation.cc
+++ b/gr-digital/lib/digital_constellation.cc
@@ -411,6 +411,20 @@ digital_constellation_qpsk::digital_constellation_qpsk ()
d_constellation[1] = gr_complex(SQRT_TWO, -SQRT_TWO);
d_constellation[2] = gr_complex(-SQRT_TWO, SQRT_TWO);
d_constellation[3] = gr_complex(SQRT_TWO, SQRT_TWO);
+
+ /*
+ d_constellation[0] = gr_complex(SQRT_TWO, SQRT_TWO);
+ d_constellation[1] = gr_complex(-SQRT_TWO, SQRT_TWO);
+ d_constellation[2] = gr_complex(SQRT_TWO, -SQRT_TWO);
+ d_constellation[3] = gr_complex(SQRT_TWO, -SQRT_TWO);
+ */
+
+ d_pre_diff_code.resize(4);
+ d_pre_diff_code[0] = 0x0;
+ d_pre_diff_code[1] = 0x2;
+ d_pre_diff_code[2] = 0x3;
+ d_pre_diff_code[3] = 0x1;
+
d_rotational_symmetry = 4;
d_dimensionality = 1;
calc_arity();
@@ -422,8 +436,80 @@ digital_constellation_qpsk::decision_maker(const gr_complex *sample)
// Real component determines small bit.
// Imag component determines big bit.
return 2*(imag(*sample)>0) + (real(*sample)>0);
+
+ /*
+ bool a = real(*sample) > 0;
+ bool b = imag(*sample) > 0;
+ if(a) {
+ if(b)
+ return 0x0;
+ else
+ return 0x1;
+ }
+ else {
+ if(b)
+ return 0x2;
+ else
+ return 0x3;
+ }
+ */
+}
+
+
+/********************************************************************/
+
+
+digital_constellation_dqpsk_sptr
+digital_make_constellation_dqpsk()
+{
+ return digital_constellation_dqpsk_sptr(new digital_constellation_dqpsk ());
}
+digital_constellation_dqpsk::digital_constellation_dqpsk ()
+{
+ // This constellation is not gray coded, which allows
+ // us to use differential encodings (through gr_diff_encode and
+ // gr_diff_decode) on the symbols.
+ d_constellation.resize(4);
+ d_constellation[0] = gr_complex(+SQRT_TWO, +SQRT_TWO);
+ d_constellation[1] = gr_complex(-SQRT_TWO, +SQRT_TWO);
+ d_constellation[2] = gr_complex(-SQRT_TWO, -SQRT_TWO);
+ d_constellation[3] = gr_complex(+SQRT_TWO, -SQRT_TWO);
+
+ // Use this mapping to convert to gray code before diff enc.
+ d_pre_diff_code.resize(4);
+ d_pre_diff_code[0] = 0x0;
+ d_pre_diff_code[1] = 0x1;
+ d_pre_diff_code[2] = 0x3;
+ d_pre_diff_code[3] = 0x2;
+ d_apply_pre_diff_code = true;
+
+ d_rotational_symmetry = 4;
+ d_dimensionality = 1;
+ calc_arity();
+}
+
+unsigned int
+digital_constellation_dqpsk::decision_maker(const gr_complex *sample)
+{
+ // Slower deicison maker as we can't slice along one axis.
+ // Maybe there's a better way to do this, still.
+
+ bool a = real(*sample) > 0;
+ bool b = imag(*sample) > 0;
+ if(a) {
+ if(b)
+ return 0x0;
+ else
+ return 0x3;
+ }
+ else {
+ if(b)
+ return 0x1;
+ else
+ return 0x2;
+ }
+}
digital_constellation_8psk_sptr
digital_make_constellation_8psk()
diff --git a/gr-digital/lib/digital_constellation.h b/gr-digital/lib/digital_constellation.h
index df00f38986..9b2a585883 100644
--- a/gr-digital/lib/digital_constellation.h
+++ b/gr-digital/lib/digital_constellation.h
@@ -42,8 +42,10 @@ typedef boost::shared_ptr<digital_constellation> digital_constellation_sptr;
class DIGITAL_API digital_constellation : public boost::enable_shared_from_this<digital_constellation>
{
public:
- digital_constellation (std::vector<gr_complex> constellation, std::vector<unsigned int> pre_diff_code,
- unsigned int rotational_symmetry, unsigned int dimensionality);
+ digital_constellation (std::vector<gr_complex> constellation,
+ std::vector<unsigned int> pre_diff_code,
+ unsigned int rotational_symmetry,
+ unsigned int dimensionality);
digital_constellation ();
//! Returns the constellation points for a symbol value
@@ -74,6 +76,8 @@ public:
std::vector<std::vector<gr_complex> > v_points();
//! Whether to apply an encoding before doing differential encoding. (e.g. gray coding)
bool apply_pre_diff_code() { return d_apply_pre_diff_code;}
+ //! Whether to apply an encoding before doing differential encoding. (e.g. gray coding)
+ void set_pre_diff_code(bool a) { d_apply_pre_diff_code = a;}
//! Returns the encoding to apply before differential encoding.
std::vector<unsigned int> pre_diff_code() { return d_pre_diff_code;}
//! Returns the order of rotational symmetry.
@@ -82,7 +86,7 @@ public:
unsigned int dimensionality() {return d_dimensionality;}
unsigned int bits_per_symbol () {
- return floor(log(double(d_constellation.size()))/d_dimensionality/log(2.0));
+ return floor(log(d_constellation.size())/d_dimensionality/log(2));
}
unsigned int arity () {
@@ -120,17 +124,19 @@ typedef boost::shared_ptr<digital_constellation_calcdist> digital_constellation_
// public constructor
DIGITAL_API digital_constellation_calcdist_sptr
-digital_make_constellation_calcdist (std::vector<gr_complex> constellation, std::vector<unsigned int> pre_diff_code,
- unsigned int rotational_symmetry, unsigned int dimensionality);
+digital_make_constellation_calcdist (std::vector<gr_complex> constellation,
+ std::vector<unsigned int> pre_diff_code,
+ unsigned int rotational_symmetry,
+ unsigned int dimensionality);
class DIGITAL_API digital_constellation_calcdist : public digital_constellation
{
public:
digital_constellation_calcdist (std::vector<gr_complex> constellation,
- std::vector<unsigned int> pre_diff_code,
- unsigned int rotational_symmetry,
- unsigned int dimensionality);
+ std::vector<unsigned int> pre_diff_code,
+ unsigned int rotational_symmetry,
+ unsigned int dimensionality);
unsigned int decision_maker (const gr_complex *sample);
// void calc_metric(gr_complex *sample, float *metric, trellis_metric_type_t type);
// void calc_euclidean_metric(gr_complex *sample, float *metric);
@@ -155,10 +161,10 @@ class DIGITAL_API digital_constellation_sector : public digital_constellation
public:
digital_constellation_sector (std::vector<gr_complex> constellation,
- std::vector<unsigned int> pre_diff_code,
- unsigned int rotational_symmetry,
- unsigned int dimensionality,
- unsigned int n_sectors);
+ std::vector<unsigned int> pre_diff_code,
+ unsigned int rotational_symmetry,
+ unsigned int dimensionality,
+ unsigned int n_sectors);
unsigned int decision_maker (const gr_complex *sample);
@@ -194,19 +200,25 @@ typedef boost::shared_ptr<digital_constellation_rect> digital_constellation_rect
// public constructor
DIGITAL_API digital_constellation_rect_sptr
-digital_make_constellation_rect (std::vector<gr_complex> constellation, std::vector<unsigned int> pre_diff_code,
- unsigned int rotational_symmetry,
- unsigned int real_sectors, unsigned int imag_sectors,
- float width_real_sectors, float width_imag_sectors);
+digital_make_constellation_rect (std::vector<gr_complex> constellation,
+ std::vector<unsigned int> pre_diff_code,
+ unsigned int rotational_symmetry,
+ unsigned int real_sectors,
+ unsigned int imag_sectors,
+ float width_real_sectors,
+ float width_imag_sectors);
class DIGITAL_API digital_constellation_rect : public digital_constellation_sector
{
public:
- digital_constellation_rect (std::vector<gr_complex> constellation, std::vector<unsigned int> pre_diff_code,
- unsigned int rotational_symmetry,
- unsigned int real_sectors, unsigned int imag_sectors,
- float width_real_sectors, float width_imag_sectors);
+ digital_constellation_rect (std::vector<gr_complex> constellation,
+ std::vector<unsigned int> pre_diff_code,
+ unsigned int rotational_symmetry,
+ unsigned int real_sectors,
+ unsigned int imag_sectors,
+ float width_real_sectors,
+ float width_imag_sectors);
protected:
@@ -222,10 +234,13 @@ class DIGITAL_API digital_constellation_rect : public digital_constellation_sect
float d_width_imag_sectors;
friend DIGITAL_API digital_constellation_rect_sptr
- digital_make_constellation_rect (std::vector<gr_complex> constellation, std::vector<unsigned int> pre_diff_code,
- unsigned int rotational_symmetry,
- unsigned int real_sectors, unsigned int imag_sectors,
- float width_real_sectors, float width_imag_sectors);
+ digital_make_constellation_rect (std::vector<gr_complex> constellation,
+ std::vector<unsigned int> pre_diff_code,
+ unsigned int rotational_symmetry,
+ unsigned int real_sectors,
+ unsigned int imag_sectors,
+ float width_real_sectors,
+ float width_imag_sectors);
};
@@ -323,6 +338,33 @@ class DIGITAL_API digital_constellation_qpsk : public digital_constellation
};
+/************************************************************/
+/* digital_constellation_dqpsk */
+/* */
+/* Works with differential encoding; slower decisions. */
+/* */
+/************************************************************/
+
+//! \brief DQPSK-specific constellation and decision maker
+class digital_constellation_dqpsk;
+typedef boost::shared_ptr<digital_constellation_dqpsk> digital_constellation_dqpsk_sptr;
+
+// public constructor
+DIGITAL_API digital_constellation_dqpsk_sptr
+digital_make_constellation_dqpsk ();
+
+class DIGITAL_API digital_constellation_dqpsk : public digital_constellation
+{
+ public:
+
+ digital_constellation_dqpsk ();
+ unsigned int decision_maker (const gr_complex *sample);
+
+ friend DIGITAL_API digital_constellation_dqpsk_sptr
+ digital_make_constellation_dqpsk ();
+
+};
+
/************************************************************/
/* digital_constellation_8psk */
diff --git a/gr-digital/lib/digital_constellation_receiver_cb.cc b/gr-digital/lib/digital_constellation_receiver_cb.cc
index e2b6bf1d80..b9239962a7 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 5e414dfed2..d33be89585 100644
--- a/gr-digital/lib/digital_constellation_receiver_cb.h
+++ b/gr-digital/lib/digital_constellation_receiver_cb.h
@@ -26,6 +26,7 @@
#include <digital_api.h>
#include <gr_block.h>
#include <digital_constellation.h>
+#include <gri_control_loop.h>
#include <gr_complex.h>
#include <math.h>
#include <fstream>
@@ -64,134 +65,14 @@ digital_make_constellation_receiver_cb (digital_constellation_sptr constellation
*
*/
-class DIGITAL_API digital_constellation_receiver_cb : public gr_block
+class DIGITAL_API digital_constellation_receiver_cb : public gr_block, public gri_control_loop
{
- public:
+public:
int general_work (int noutput_items,
gr_vector_int &ninput_items,
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items);
-
- /*******************************************************************
- SET FUNCTIONS
- *******************************************************************/
-
- /*!
- * \brief Set the loop bandwidth
- *
- * Set the loop filter's bandwidth to \p bw. This should be between
- * 2*pi/200 and 2*pi/100 (in rads/samp). It must also be a positive
- * number.
- *
- * When a new damping factor is set, the gains, alpha and beta, of the loop
- * are recalculated by a call to update_gains().
- *
- * \param bw (float) new bandwidth
- *
- */
- void set_loop_bandwidth(float bw);
-
- /*!
- * \brief Set the loop damping factor
- *
- * Set the loop filter's damping factor to \p df. The damping factor
- * should be sqrt(2)/2.0 for critically damped systems.
- * Set it to anything else only if you know what you are doing. It must
- * be a number between 0 and 1.
- *
- * When a new damping factor is set, the gains, alpha and beta, of the loop
- * are recalculated by a call to update_gains().
- *
- * \param df (float) new damping factor
- *
- */
- void set_damping_factor(float df);
-
- /*!
- * \brief Set the loop gain alpha
- *
- * Set's the loop filter's alpha gain parameter.
- *
- * This value should really only be set by adjusting the loop bandwidth
- * and damping factor.
- *
- * \param alpha (float) new alpha gain
- *
- */
- void set_alpha(float alpha);
-
- /*!
- * \brief Set the loop gain beta
- *
- * Set's the loop filter's beta gain parameter.
- *
- * This value should really only be set by adjusting the loop bandwidth
- * and damping factor.
- *
- * \param beta (float) new beta gain
- *
- */
- void set_beta(float beta);
-
- /*!
- * \brief Set the phase/freq recovery loop's frequency.
- *
- * Set's the phase/freq recovery loop's frequency. While this is normally
- * updated by the inner loop of the algorithm, it could be useful to
- * manually initialize, set, or reset this under certain circumstances.
- *
- * \param freq (float) new frequency
- *
- */
- void set_frequency(float freq);
-
- /*!
- * \brief Set the phase/freq recovery loop's phase.
- *
- * Set's the phase/freq recovery loop's phase. While this is normally
- * updated by the inner loop of the algorithm, it could be useful to
- * manually initialize, set, or reset this under certain circumstances.
- *
- * \param phase (float) new phase
- *
- */
- void set_phase(float phase);
-
- /*******************************************************************
- GET FUNCTIONS
- *******************************************************************/
-
- /*!
- * \brief Returns the loop bandwidth
- */
- float get_loop_bandwidth() const;
-
- /*!
- * \brief Returns the loop damping factor
- */
- float get_damping_factor() const;
-
- /*!
- * \brief Returns the loop gain alpha
- */
- float get_alpha() const;
-
- /*!
- * \brief Returns the loop gain beta
- */
- float get_beta() const;
-
- /*!
- * \brief Get the phase/freq recovery loop's frequency estimate
- */
- float get_frequency() const;
-
- /*!
- * \brief Get the phase/freq loop's phase estimate
- */
- float get_phase() const;
-
protected:
/*!
@@ -211,18 +92,9 @@ protected:
void phase_error_tracking(float phase_error);
- private:
+private:
unsigned int d_M;
- // Members related to carrier and phase tracking
- float d_freq, d_max_freq, d_min_freq;
- float d_phase;
-
- float d_loop_bw;
- float d_damping;
- float d_alpha;
- float d_beta;
-
digital_constellation_sptr d_constellation;
unsigned int d_current_const_point;
@@ -230,20 +102,11 @@ protected:
static const unsigned int DLLEN = 8;
//! delay line plus some length for overflow protection
- __GR_ATTR_ALIGNED(8) gr_complex d_dl[2*DLLEN];
+ gr_complex d_dl[2*DLLEN] __attribute__ ((aligned(8)));
//! index to delay line
unsigned int d_dl_idx;
- /*! \brief update the system gains from the loop bandwidth and damping factor
- *
- * This function updates the system gains based on the loop
- * bandwidth and damping factor of the system.
- * These two factors can be set separately through their own
- * set functions.
- */
- void update_gains();
-
friend DIGITAL_API digital_constellation_receiver_cb_sptr
digital_make_constellation_receiver_cb (digital_constellation_sptr constell,
float loop_bw, float fmin, float fmax);
diff --git a/gr-digital/lib/digital_fll_band_edge_cc.cc b/gr-digital/lib/digital_fll_band_edge_cc.cc
index 70cb543519..05c092622a 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 c7a56a7c9c..6ef8376ace 100644
--- a/gr-digital/lib/digital_fll_band_edge_cc.h
+++ b/gr-digital/lib/digital_fll_band_edge_cc.h
@@ -26,6 +26,7 @@
#include <digital_api.h>
#include <gr_sync_block.h>
+#include <gri_control_loop.h>
class digital_fll_band_edge_cc;
typedef boost::shared_ptr<digital_fll_band_edge_cc> digital_fll_band_edge_cc_sptr;
@@ -40,39 +41,51 @@ DIGITAL_API digital_fll_band_edge_cc_sptr digital_make_fll_band_edge_cc (float s
*
* \ingroup general
*
- * The frequency lock loop derives a band-edge filter that covers the upper and lower bandwidths
- * of a digitally-modulated signal. The bandwidth range is determined by the excess bandwidth
- * (e.g., rolloff factor) of the modulated signal. The placement in frequency of the band-edges
- * is determined by the oversampling ratio (number of samples per symbol) and the excess bandwidth.
- * The size of the filters should be fairly large so as to average over a number of symbols.
+ * The frequency lock loop derives a band-edge filter that covers the
+ * upper and lower bandwidths of a digitally-modulated signal. The
+ * bandwidth range is determined by the excess bandwidth (e.g.,
+ * rolloff factor) of the modulated signal. The placement in frequency
+ * of the band-edges is determined by the oversampling ratio (number
+ * of samples per symbol) and the excess bandwidth. The size of the
+ * filters should be fairly large so as to average over a number of
+ * symbols.
*
- * The FLL works by filtering the upper and lower band edges into x_u(t) and x_l(t), respectively.
- * These are combined to form cc(t) = x_u(t) + x_l(t) and ss(t) = x_u(t) - x_l(t). Combining
- * these to form the signal e(t) = Re{cc(t) \\times ss(t)^*} (where ^* is the complex conjugate)
- * provides an error signal at the DC term that is directly proportional to the carrier frequency.
- * We then make a second-order loop using the error signal that is the running average of e(t).
+ * The FLL works by filtering the upper and lower band edges into
+ * x_u(t) and x_l(t), respectively. These are combined to form cc(t)
+ * = x_u(t) + x_l(t) and ss(t) = x_u(t) - x_l(t). Combining these to
+ * form the signal e(t) = Re{cc(t) \\times ss(t)^*} (where ^* is the
+ * complex conjugate) provides an error signal at the DC term that is
+ * directly proportional to the carrier frequency. We then make a
+ * second-order loop using the error signal that is the running
+ * average of e(t).
*
- * In practice, the above equation can be simplified by just comparing the absolute value squared
- * of the output of both filters: abs(x_l(t))^2 - abs(x_u(t))^2 = norm(x_l(t)) - norm(x_u(t)).
+ * In practice, the above equation can be simplified by just comparing
+ * the absolute value squared of the output of both filters:
+ * abs(x_l(t))^2 - abs(x_u(t))^2 = norm(x_l(t)) - norm(x_u(t)).
*
- * In theory, the band-edge filter is the derivative of the matched filter in frequency,
- * (H_be(f) = \\frac{H(f)}{df}. In practice, this comes down to a quarter sine wave at the point
- * of the matched filter's rolloff (if it's a raised-cosine, the derivative of a cosine is a sine).
- * Extend this sine by another quarter wave to make a half wave around the band-edges is equivalent
- * in time to the sum of two sinc functions. The baseband filter fot the band edges is therefore
- * derived from this sum of sincs. The band edge filters are then just the baseband signal
- * modulated to the correct place in frequency. All of these calculations are done in the
+ * In theory, the band-edge filter is the derivative of the matched
+ * filter in frequency, (H_be(f) = \\frac{H(f)}{df}. In practice, this
+ * comes down to a quarter sine wave at the point of the matched
+ * filter's rolloff (if it's a raised-cosine, the derivative of a
+ * cosine is a sine). Extend this sine by another quarter wave to
+ * make a half wave around the band-edges is equivalent in time to the
+ * sum of two sinc functions. The baseband filter fot the band edges
+ * is therefore derived from this sum of sincs. The band edge filters
+ * are then just the baseband signal modulated to the correct place in
+ * frequency. All of these calculations are done in the
* 'design_filter' function.
*
- * Note: We use FIR filters here because the filters have to have a flat phase response over the
- * entire frequency range to allow their comparisons to be valid.
+ * Note: We use FIR filters here because the filters have to have a
+ * flat phase response over the entire frequency range to allow their
+ * comparisons to be valid.
*
- * It is very important that the band edge filters be the derivatives of the pulse shaping filter,
- * and that they be linear phase. Otherwise, the variance of the error will be very large.
+ * It is very important that the band edge filters be the derivatives
+ * of the pulse shaping filter, and that they be linear
+ * phase. Otherwise, the variance of the error will be very large.
*
*/
-class DIGITAL_API digital_fll_band_edge_cc : public gr_sync_block
+class DIGITAL_API digital_fll_band_edge_cc : public gr_sync_block, public gri_control_loop
{
private:
/*!
@@ -90,21 +103,11 @@ class DIGITAL_API digital_fll_band_edge_cc : public gr_sync_block
float d_sps;
float d_rolloff;
int d_filter_size;
- float d_max_freq;
- float d_min_freq;
-
- float d_loop_bw;
- float d_damping;
- float d_alpha;
- float d_beta;
std::vector<gr_complex> d_taps_lower;
std::vector<gr_complex> d_taps_upper;
bool d_updated;
- float d_freq;
- float d_phase;
-
/*!
* Build the FLL
* \param samps_per_sym (float) number of samples per symbol
@@ -116,11 +119,6 @@ class DIGITAL_API digital_fll_band_edge_cc : public gr_sync_block
int filter_size, float bandwidth);
/*!
- * \brief Update the gains, alpha and beta, of the loop filter.
- */
- void update_gains();
-
- /*!
* Design the band-edge filter based on the number of samples per symbol,
* filter rolloff factor, and the filter size
*
@@ -138,67 +136,11 @@ public:
*******************************************************************/
/*!
- * \brief Set the loop bandwidth
- *
- * Set the loop filter's bandwidth to \p bw. This should be between
- * 2*pi/200 and 2*pi/100 (in rads/samp). It must also be a positive
- * number.
- *
- * When a new damping factor is set, the gains, alpha and beta, of the loop
- * are recalculated by a call to update_gains().
- *
- * \param bw (float) new bandwidth
- *
- */
- void set_loop_bandwidth(float bw);
-
- /*!
- * \brief Set the loop damping factor
- *
- * Set the loop filter's damping factor to \p df. The damping factor
- * should be sqrt(2)/2.0 for critically damped systems.
- * Set it to anything else only if you know what you are doing. It must
- * be a number between 0 and 1.
- *
- * When a new damping factor is set, the gains, alpha and beta, of the loop
- * are recalculated by a call to update_gains().
- *
- * \param df (float) new damping factor
- *
- */
- void set_damping_factor(float df);
-
- /*!
- * \brief Set the loop gain alpha
- *
- * Set's the loop filter's alpha gain parameter.
- *
- * This value should really only be set by adjusting the loop bandwidth
- * and damping factor.
- *
- * \param alpha (float) new alpha gain
- *
- */
- void set_alpha(float alpha);
-
- /*!
- * \brief Set the loop gain beta
- *
- * Set's the loop filter's beta gain parameter.
- *
- * This value should really only be set by adjusting the loop bandwidth
- * and damping factor.
- *
- * \param beta (float) new beta gain
- *
- */
- void set_beta(float beta);
-
- /*!
* \brief Set the number of samples per symbol
*
- * Set's the number of samples per symbol the system should use. This value
- * is uesd to calculate the filter taps and will force a recalculation.
+ * Set's the number of samples per symbol the system should
+ * use. This value is uesd to calculate the filter taps and will
+ * force a recalculation.
*
* \param sps (float) new samples per symbol
*
@@ -208,13 +150,14 @@ public:
/*!
* \brief Set the rolloff factor of the shaping filter
*
- * This sets the rolloff factor that is used in the pulse shaping filter
- * and is used to calculate the filter taps. Changing this will force a
- * recalculation of the filter taps.
+ * This sets the rolloff factor that is used in the pulse shaping
+ * filter and is used to calculate the filter taps. Changing this
+ * will force a recalculation of the filter taps.
*
- * This should be the same value that is used in the transmitter's pulse
- * shaping filter. It must be between 0 and 1 and is usually between
- * 0.2 and 0.5 (where 0.22 and 0.35 are commonly used values).
+ * This should be the same value that is used in the transmitter's
+ * pulse shaping filter. It must be between 0 and 1 and is usually
+ * between 0.2 and 0.5 (where 0.22 and 0.35 are commonly used
+ * values).
*
* \param rolloff (float) new shaping filter rolloff factor [0,1]
*
@@ -224,68 +167,25 @@ public:
/*!
* \brief Set the number of taps in the filter
*
- * This sets the number of taps in the band-edge filters. Setting this will
- * force a recalculation of the filter taps.
+ * This sets the number of taps in the band-edge filters. Setting
+ * this will force a recalculation of the filter taps.
*
- * This should be about the same number of taps used in the transmitter's
- * shaping filter and also not very large. A large number of taps will
- * result in a large delay between input and frequency estimation, and
- * so will not be as accurate. Between 30 and 70 taps is usual.
+ * This should be about the same number of taps used in the
+ * transmitter's shaping filter and also not very large. A large
+ * number of taps will result in a large delay between input and
+ * frequency estimation, and so will not be as accurate. Between 30
+ * and 70 taps is usual.
*
* \param filter_size (float) number of taps in the filters
*
*/
void set_filter_size(int filter_size);
- /*!
- * \brief Set the FLL's frequency.
- *
- * Set's the FLL's frequency. While this is normally updated by the
- * inner loop of the algorithm, it could be useful to manually initialize,
- * set, or reset this under certain circumstances.
- *
- * \param freq (float) new frequency
- *
- */
- void set_frequency(float freq);
-
- /*!
- * \brief Set the FLL's phase.
- *
- * Set's the FLL's phase. While this is normally updated by the
- * inner loop of the algorithm, it could be useful to manually initialize,
- * set, or reset this under certain circumstances.
- *
- * \param phase (float) new phase
- *
- */
- void set_phase(float phase);
-
/*******************************************************************
GET FUNCTIONS
*******************************************************************/
/*!
- * \brief Returns the loop bandwidth
- */
- float get_loop_bandwidth() const;
-
- /*!
- * \brief Returns the loop damping factor
- */
- float get_damping_factor() const;
-
- /*!
- * \brief Returns the loop gain alpha
- */
- float get_alpha() const;
-
- /*!
- * \brief Returns the loop gain beta
- */
- float get_beta() const;
-
- /*!
* \brief Returns the number of sampler per symbol used for the filter
*/
float get_samples_per_symbol() const;
@@ -301,16 +201,6 @@ public:
int get_filter_size() const;
/*!
- * \brief Get the FLL's frequency estimate
- */
- float get_frequency() const;
-
- /*!
- * \brief Get the FLL's phase estimate
- */
- float get_phase() const;
-
- /*!
* Print the taps to screen.
*/
void print_taps();
diff --git a/gr-digital/lib/digital_mpsk_receiver_cc.cc b/gr-digital/lib/digital_mpsk_receiver_cc.cc
index 3b2ea98404..363b86c9f2 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 8a6352ec7b..85cd81e992 100644
--- a/gr-digital/lib/digital_mpsk_receiver_cc.h
+++ b/gr-digital/lib/digital_mpsk_receiver_cc.h
@@ -25,6 +25,7 @@
#include <digital_api.h>
#include <gruel/attributes.h>
+#include <gri_control_loop.h>
#include <gr_block.h>
#include <gr_complex.h>
#include <fstream>
@@ -37,41 +38,48 @@ typedef boost::shared_ptr<digital_mpsk_receiver_cc> digital_mpsk_receiver_cc_spt
// public constructor
DIGITAL_API digital_mpsk_receiver_cc_sptr
digital_make_mpsk_receiver_cc (unsigned int M, float theta,
- float alpha, float beta,
+ float loop_bw,
float fmin, float fmax,
float mu, float gain_mu,
float omega, float gain_omega, float omega_rel);
/*!
- * \brief This block takes care of receiving M-PSK modulated signals through phase, frequency, and symbol
- * synchronization.
+ * \brief This block takes care of receiving M-PSK modulated signals
+ * through phase, frequency, and symbol synchronization.
* \ingroup sync_blk
* \ingroup demod_blk
*
- * This block takes care of receiving M-PSK modulated signals through phase, frequency, and symbol
- * synchronization. It performs carrier frequency and phase locking as well as symbol timing recovery.
- * It works with (D)BPSK, (D)QPSK, and (D)8PSK as tested currently. It should also work for OQPSK and
- * PI/4 DQPSK.
+ * This block takes care of receiving M-PSK modulated signals through
+ * phase, frequency, and symbol synchronization. It performs carrier
+ * frequency and phase locking as well as symbol timing recovery. It
+ * works with (D)BPSK, (D)QPSK, and (D)8PSK as tested currently. It
+ * should also work for OQPSK and PI/4 DQPSK.
*
- * The phase and frequency synchronization are based on a Costas loop that finds the error of the incoming
- * signal point compared to its nearest constellation point. The frequency and phase of the NCO are
- * updated according to this error. There are optimized phase error detectors for BPSK and QPSK, but 8PSK
- * is done using a brute-force computation of the constellation points to find the minimum.
+ * The phase and frequency synchronization are based on a Costas loop
+ * that finds the error of the incoming signal point compared to its
+ * nearest constellation point. The frequency and phase of the NCO are
+ * updated according to this error. There are optimized phase error
+ * detectors for BPSK and QPSK, but 8PSK is done using a brute-force
+ * computation of the constellation points to find the minimum.
*
- * The symbol synchronization is done using a modified Mueller and Muller circuit from the paper:
+ * The symbol synchronization is done using a modified Mueller and
+ * Muller circuit from the paper:
*
- * G. R. Danesfahani, T.G. Jeans, "Optimisation of modified Mueller and Muller
- * algorithm," Electronics Letters, Vol. 31, no. 13, 22 June 1995, pp. 1032 - 1033.
+ * G. R. Danesfahani, T.G. Jeans, "Optimisation of modified Mueller
+ * and Muller algorithm," Electronics Letters, Vol. 31, no. 13, 22
+ * June 1995, pp. 1032 - 1033.
*
- * This circuit interpolates the downconverted sample (using the NCO developed by the Costas loop)
- * every mu samples, then it finds the sampling error based on this and the past symbols and the decision
- * made on the samples. Like the phase error detector, there are optimized decision algorithms for BPSK
- * and QPKS, but 8PSK uses another brute force computation against all possible symbols. The modifications
- * to the M&M used here reduce self-noise.
+ * This circuit interpolates the downconverted sample (using the NCO
+ * developed by the Costas loop) every mu samples, then it finds the
+ * sampling error based on this and the past symbols and the decision
+ * made on the samples. Like the phase error detector, there are
+ * optimized decision algorithms for BPSK and QPKS, but 8PSK uses
+ * another brute force computation against all possible symbols. The
+ * modifications to the M&M used here reduce self-noise.
*
*/
-class DIGITAL_API digital_mpsk_receiver_cc : public gr_block
+class DIGITAL_API digital_mpsk_receiver_cc : public gr_block, public gri_control_loop
{
public:
~digital_mpsk_receiver_cc ();
@@ -112,43 +120,14 @@ class DIGITAL_API digital_mpsk_receiver_cc : public gr_block
//! (M&M) Sets value for omega gain factor
void set_gain_omega (float gain_omega) { d_gain_omega = gain_omega; }
-
-
- // Member function related to the phase/frequency tracking portion of the receiver
- //! (CL) Returns the value for alpha (the phase gain term)
- float alpha() const { return d_alpha; }
-
- //! (CL) Returns the value of beta (the frequency gain term)
- float beta() const { return d_beta; }
-
- //! (CL) Returns the current value of the frequency of the NCO in the Costas loop
- float freq() const { return d_freq; }
-
- //! (CL) Returns the current value of the phase of the NCO in the Costal loop
- float phase() const { return d_phase; }
-
- //! (CL) Sets the value for alpha (the phase gain term)
- void set_alpha(float alpha) { d_alpha = alpha; }
-
- //! (CL) Setss the value of beta (the frequency gain term)
- void set_beta(float beta) { d_beta = beta; }
-
- //! (CL) Sets the current value of the frequency of the NCO in the Costas loop
- void set_freq(float freq) { d_freq = freq; }
-
- //! (CL) Setss the current value of the phase of the NCO in the Costal loop
- void set_phase(float phase) { d_phase = phase; }
-
-
protected:
-
- /*!
+
+ /*!
* \brief Constructor to synchronize incoming M-PSK symbols
*
* \param M modulation order of the M-PSK modulation
* \param theta any constant phase rotation from the real axis of the constellation
- * \param alpha gain parameter to adjust the phase in the Costas loop (~0.01)
- * \param beta gain parameter to adjust the frequency in the Costas loop (~alpha^2/4)
+ * \param loop_bw Loop bandwidth to set gains of phase/freq tracking loop
* \param fmin minimum normalized frequency value the loop can achieve
* \param fmax maximum normalized frequency value the loop can achieve
* \param mu initial parameter for the interpolator [0,1]
@@ -161,7 +140,7 @@ protected:
* value of M.
*/
digital_mpsk_receiver_cc (unsigned int M, float theta,
- float alpha, float beta,
+ float loop_bw,
float fmin, float fmax,
float mu, float gain_mu,
float omega, float gain_omega, float omega_rel);
@@ -172,54 +151,61 @@ protected:
void phase_error_tracking(gr_complex sample);
-/*!
+ /*!
* \brief Phase error detector for MPSK modulations.
*
* \param sample the I&Q sample from which to determine the phase error
*
- * This function determines the phase error for any MPSK signal by creating a set of PSK constellation points
- * and doing a brute-force search to see which point minimizes the Euclidean distance. This point is then used
- * to derotate the sample to the real-axis and a atan (using the fast approximation function) to determine the
- * phase difference between the incoming sample and the real constellation point
+ * This function determines the phase error for any MPSK signal by
+ * creating a set of PSK constellation points and doing a
+ * brute-force search to see which point minimizes the Euclidean
+ * distance. This point is then used to derotate the sample to the
+ * real-axis and a atan (using the fast approximation function) to
+ * determine the phase difference between the incoming sample and
+ * the real constellation point
*
* This should be cleaned up and made more efficient.
*
* \returns the approximated phase error.
- */
+ */
float phase_error_detector_generic(gr_complex sample) const; // generic for M but more costly
- /*!
+ /*!
* \brief Phase error detector for BPSK modulation.
*
* \param sample the I&Q sample from which to determine the phase error
*
- * This function determines the phase error using a simple BPSK phase error detector by multiplying the real
- * and imaginary (the error signal) components together. As the imaginary part goes to 0, so does this error.
+ * This function determines the phase error using a simple BPSK
+ * phase error detector by multiplying the real and imaginary (the
+ * error signal) components together. As the imaginary part goes to
+ * 0, so does this error.
*
* \returns the approximated phase error.
- */
+ */
float phase_error_detector_bpsk(gr_complex sample) const; // optimized for BPSK
- /*!
+ /*!
* \brief Phase error detector for QPSK modulation.
*
* \param sample the I&Q sample from which to determine the phase error
*
- * This function determines the phase error using the limiter approach in a standard 4th order Costas loop
+ * This function determines the phase error using the limiter
+ * approach in a standard 4th order Costas loop
*
* \returns the approximated phase error.
- */
+ */
float phase_error_detector_qpsk(gr_complex sample) const;
- /*!
+ /*!
* \brief Decision maker for a generic MPSK constellation.
*
* \param sample the baseband I&Q sample from which to make the decision
*
- * This decision maker is a generic implementation that does a brute-force search
- * for the constellation point that minimizes the error between it and the incoming signal.
+ * This decision maker is a generic implementation that does a
+ * brute-force search for the constellation point that minimizes the
+ * error between it and the incoming signal.
*
* \returns the index to d_constellation that minimizes the error/
*/
@@ -231,46 +217,44 @@ protected:
*
* \param sample the baseband I&Q sample from which to make the decision
*
- * This decision maker is a simple slicer function that makes a decision on the symbol based on its
- * placement on the real axis of greater than 0 or less than 0; the quadrature component is always 0.
+ * This decision maker is a simple slicer function that makes a
+ * decision on the symbol based on its placement on the real axis of
+ * greater than 0 or less than 0; the quadrature component is always
+ * 0.
*
* \returns the index to d_constellation that minimizes the error/
- */
+ */
unsigned int decision_bpsk(gr_complex sample) const;
- /*!
+ /*!
* \brief Decision maker for QPSK constellation.
*
* \param sample the baseband I&Q sample from which to make the decision
*
- * This decision maker is a simple slicer function that makes a decision on the symbol based on its
- * placement versus both axes and returns which quadrant the symbol is in.
+ * This decision maker is a simple slicer function that makes a
+ * decision on the symbol based on its placement versus both axes
+ * and returns which quadrant the symbol is in.
*
* \returns the index to d_constellation that minimizes the error/
- */
+ */
unsigned int decision_qpsk(gr_complex sample) const;
- private:
+private:
unsigned int d_M;
float d_theta;
- // Members related to carrier and phase tracking
- float d_alpha;
- float d_beta;
- float d_freq, d_max_freq, d_min_freq;
- float d_phase;
-
-/*!
+ /*!
* \brief Decision maker function pointer
*
* \param sample the baseband I&Q sample from which to make the decision
*
- * This is a function pointer that is set in the constructor to point to the proper decision function
- * for the specified constellation order.
+ * This is a function pointer that is set in the constructor to
+ * point to the proper decision function for the specified
+ * constellation order.
*
* \return index into d_constellation point that is the closest to the recieved sample
- */
+ */
unsigned int (digital_mpsk_receiver_cc::*d_decision)(gr_complex sample) const; // pointer to decision function
@@ -283,14 +267,15 @@ protected:
gr_complex d_p_2T, d_p_1T, d_p_0T;
gr_complex d_c_2T, d_c_1T, d_c_0T;
- /*!
+ /*!
* \brief Phase error detector function pointer
*
* \param sample the I&Q sample from which to determine the phase error
*
- * This is a function pointer that is set in the constructor to point to the proper phase error detector
- * function for the specified constellation order.
- */
+ * This is a function pointer that is set in the constructor to
+ * point to the proper phase error detector function for the
+ * specified constellation order.
+ */
float (digital_mpsk_receiver_cc::*d_phase_error_detector)(gr_complex sample) const;
@@ -308,7 +293,7 @@ protected:
friend DIGITAL_API digital_mpsk_receiver_cc_sptr
digital_make_mpsk_receiver_cc (unsigned int M, float theta,
- float alpha, float beta,
+ float loop_bw,
float fmin, float fmax,
float mu, float gain_mu,
float omega, float gain_omega, float omega_rel);
diff --git a/gr-digital/python/Makefile.am b/gr-digital/python/Makefile.am
index 6c61002f16..a33e4963d6 100644
--- a/gr-digital/python/Makefile.am
+++ b/gr-digital/python/Makefile.am
@@ -35,6 +35,7 @@ noinst_PYTHON = \
qa_binary_slicer_fb.py \
qa_clock_recovery_mm.py \
qa_cma_equalizer.py \
+ qa_cpm.py \
qa_constellation.py \
qa_constellation_receiver.py \
qa_constellation_decoder_cb.py \
diff --git a/gr-digital/python/__init__.py b/gr-digital/python/__init__.py
index 4046f7fafe..7173fa09d8 100644
--- a/gr-digital/python/__init__.py
+++ b/gr-digital/python/__init__.py
@@ -26,6 +26,7 @@ from psk2 import *
from bpsk import *
from qpsk import *
from qam import *
+from gmsk import *
from pkt import *
from packet_utils import *
from crc import *
diff --git a/gr-digital/python/generic_mod_demod.py b/gr-digital/python/generic_mod_demod.py
index da8e2cfd99..b1986512f0 100644
--- a/gr-digital/python/generic_mod_demod.py
+++ b/gr-digital/python/generic_mod_demod.py
@@ -54,7 +54,7 @@ def add_common_options(parser):
Sets options common to both modulator and demodulator.
"""
parser.add_option("-p", "--constellation-points", type="int", default=_def_constellation_points,
- help="set the number of constellation points (must be a power of 2 (power of 4 for QAM) [default=%default]")
+ help="set the number of constellation points (must be a power of 2 for psk, power of 4 for QAM) [default=%default]")
parser.add_option("", "--non-differential", action="store_true",
dest="differential", default=False,
help="do not use differential encoding [default=%default]")
@@ -120,7 +120,7 @@ class generic_mod(gr.hier_block2):
self.bytes2chunks = \
gr.packed_to_unpacked_bb(self.bits_per_symbol(), gr.GR_MSB_FIRST)
- if self._constellation.apply_pre_diff_code():
+ if gray_coded == True:
self.symbol_mapper = gr.map_bb(self._constellation.pre_diff_code())
if differential:
@@ -142,7 +142,7 @@ class generic_mod(gr.hier_block2):
# Connect
blocks = [self, self.bytes2chunks]
- if self._constellation.apply_pre_diff_code():
+ if gray_coded == True:
blocks.append(self.symbol_mapper)
if differential:
blocks.append(self.diffenc)
@@ -211,6 +211,7 @@ class generic_demod(gr.hier_block2):
samples_per_symbol=_def_samples_per_symbol,
differential=_def_differential,
excess_bw=_def_excess_bw,
+ gray_coded=True,
freq_bw=_def_freq_bw,
timing_bw=_def_timing_bw,
phase_bw=_def_phase_bw,
@@ -228,9 +229,11 @@ class generic_demod(gr.hier_block2):
@type samples_per_symbol: float
@param excess_bw: Root-raised cosine filter excess bandwidth
@type excess_bw: float
+ @param gray_coded: turn gray coding on/off
+ @type gray_coded: bool
@param freq_bw: loop filter lock-in bandwidth
@type freq_bw: float
- @param timing_bw: timing recoery loop lock-in bandwidth
+ @param timing_bw: timing recovery loop lock-in bandwidth
@type timing_bw: float
@param phase_bw: phase recovery loop bandwidth
@type phase_bw: float
@@ -265,8 +268,9 @@ class generic_demod(gr.hier_block2):
self.agc = gr.agc2_cc(0.6e-1, 1e-3, 1, 1, 100)
# Frequency correction
+ fll_ntaps = 55
self.freq_recov = digital_swig.fll_band_edge_cc(self._samples_per_symbol, self._excess_bw,
- ntaps, self._freq_bw)
+ fll_ntaps, self._freq_bw)
# symbol timing recovery with RRC data filter
taps = gr.firdes.root_raised_cosine(nfilts, nfilts*self._samples_per_symbol,
@@ -280,12 +284,12 @@ class generic_demod(gr.hier_block2):
self.receiver = digital_swig.constellation_receiver_cb(
self._constellation, self._phase_bw,
fmin, fmax)
-
+
# Do differential decoding based on phase change of symbols
if differential:
self.diffdec = gr.diff_decoder_bb(arity)
- if self._constellation.apply_pre_diff_code():
+ if gray_coded:
self.symbol_mapper = gr.map_bb(
mod_codes.invert_code(self._constellation.pre_diff_code()))
@@ -297,9 +301,10 @@ class generic_demod(gr.hier_block2):
if log:
self._setup_logging()
-
+
# Connect and Initialize base class
- blocks = [self, self.agc, self.freq_recov, self.time_recov, self.receiver]
+ blocks = [self, self.agc, self.freq_recov,
+ self.time_recov, self.receiver]
if differential:
blocks.append(self.diffdec)
if self._constellation.apply_pre_diff_code():
diff --git a/gr-digital/python/gmsk.py b/gr-digital/python/gmsk.py
index 3b6c016a0b..ba122821e1 100644
--- a/gr-digital/python/gmsk.py
+++ b/gr-digital/python/gmsk.py
@@ -25,7 +25,9 @@
# See gnuradio-examples/python/digital for examples
from gnuradio import gr
-from gnuradio import modulation_utils
+import digital_swig
+import modulation_utils2
+
from math import pi
import numpy
from pprint import pprint
@@ -37,11 +39,9 @@ _def_bt = 0.35
_def_verbose = False
_def_log = False
-_def_gain_mu = None
-_def_mu = 0.5
-_def_freq_error = 0.0
-_def_omega_relative_limit = 0.005
-
+# Symbol timing recovery
+_def_timing_bw = 2*pi/100.0
+_def_timing_max_dev = 1.5
# /////////////////////////////////////////////////////////////////////////////
# GMSK modulator
@@ -79,7 +79,8 @@ class gmsk_mod(gr.hier_block2):
self._bt = bt
if not isinstance(samples_per_symbol, int) or samples_per_symbol < 2:
- raise TypeError, ("samples_per_symbol must be an integer >= 2, is %r" % (samples_per_symbol,))
+ raise TypeError, ("samples_per_symbol must be an integer >= 2, is %r" % \
+ (samples_per_symbol,))
ntaps = 4 * samples_per_symbol # up to 3 bits in filter at once
sensitivity = (pi / 2) / samples_per_symbol # phase change per bit = pi / 2
@@ -128,11 +129,11 @@ class gmsk_mod(gr.hier_block2):
def _setup_logging(self):
print "Modulation logging turned on."
self.connect(self.nrz,
- gr.file_sink(gr.sizeof_float, "nrz.dat"))
+ gr.file_sink(gr.sizeof_float, "tx_gmsk_nrz.32f"))
self.connect(self.gaussian_filter,
- gr.file_sink(gr.sizeof_float, "gaussian_filter.dat"))
+ gr.file_sink(gr.sizeof_float, "tx_gmsk_gaussian_filter.32f"))
self.connect(self.fmmod,
- gr.file_sink(gr.sizeof_gr_complex, "fmmod.dat"))
+ gr.file_sink(gr.sizeof_gr_complex, "tx_gmsk_fmmod.32fc"))
def add_options(parser):
@@ -148,7 +149,7 @@ class gmsk_mod(gr.hier_block2):
"""
Given command line options, create dictionary suitable for passing to __init__
"""
- return modulation_utils.extract_kwargs_from_options(gmsk_mod.__init__,
+ return modulation_utils2.extract_kwargs_from_options(gmsk_mod.__init__,
('self',), options)
extract_kwargs_from_options=staticmethod(extract_kwargs_from_options)
@@ -162,10 +163,8 @@ class gmsk_demod(gr.hier_block2):
def __init__(self,
samples_per_symbol=_def_samples_per_symbol,
- gain_mu=_def_gain_mu,
- mu=_def_mu,
- omega_relative_limit=_def_omega_relative_limit,
- freq_error=_def_freq_error,
+ bt=_def_bt,
+ timing_bw=_def_timing_bw,
verbose=_def_verbose,
log=_def_log):
"""
@@ -177,21 +176,12 @@ class gmsk_demod(gr.hier_block2):
@param samples_per_symbol: samples per baud
@type samples_per_symbol: integer
+ @param timing_bw: timing recovery loop lock-in bandwidth
+ @type timing_bw: float
@param verbose: Print information about modulator?
@type verbose: bool
@param log: Print modualtion data to files?
@type log: bool
-
- Clock recovery parameters. These all have reasonble defaults.
-
- @param gain_mu: controls rate of mu adjustment
- @type gain_mu: float
- @param mu: fractional delay [0.0, 1.0]
- @type mu: float
- @param omega_relative_limit: sets max variation in omega
- @type omega_relative_limit: float, typically 0.000200 (200 ppm)
- @param freq_error: bit rate error as a fraction
- @param float
"""
gr.hier_block2.__init__(self, "gmsk_demod",
@@ -199,33 +189,31 @@ class gmsk_demod(gr.hier_block2):
gr.io_signature(1, 1, gr.sizeof_char)) # Output signature
self._samples_per_symbol = samples_per_symbol
- self._gain_mu = gain_mu
- self._mu = mu
- self._omega_relative_limit = omega_relative_limit
- self._freq_error = freq_error
+ self._bt = bt
+ self._timing_bw = timing_bw
+ self._timing_max_dev= _def_timing_max_dev
if samples_per_symbol < 2:
raise TypeError, "samples_per_symbol >= 2, is %f" % samples_per_symbol
- self._omega = samples_per_symbol*(1+self._freq_error)
-
- if not self._gain_mu:
- self._gain_mu = 0.175
-
- self._gain_omega = .25 * self._gain_mu * self._gain_mu # critically damped
-
# Demodulate FM
sensitivity = (pi / 2) / samples_per_symbol
self.fmdemod = gr.quadrature_demod_cf(1.0 / sensitivity)
# the clock recovery block tracks the symbol clock and resamples as needed.
# the output of the block is a stream of soft symbols (float)
- self.clock_recovery = gr.clock_recovery_mm_ff(self._omega, self._gain_omega,
- self._mu, self._gain_mu,
- self._omega_relative_limit)
-
+ nfilts = 32
+ ntaps = 11 * int(self._samples_per_symbol*nfilts)
+ taps = gr.firdes.gaussian(nfilts,
+ nfilts*self._samples_per_symbol,
+ self._bt, ntaps)
+ self.clock_recovery = \
+ gr.pfb_clock_sync_fff(self._samples_per_symbol,
+ self._timing_bw, taps,
+ nfilts, nfilts//2, self._timing_max_dev)
+
# slice the floats at 0, outputting 1 bit (the LSB of the output byte) per sample
- self.slicer = gr.binary_slicer_fb()
+ self.slicer = digital_swig.binary_slicer_fb()
if verbose:
self._print_verbage()
@@ -245,48 +233,38 @@ class gmsk_demod(gr.hier_block2):
def _print_verbage(self):
- print "bits per symbol = %d" % self.bits_per_symbol()
- print "M&M clock recovery omega = %f" % self._omega
- print "M&M clock recovery gain mu = %f" % self._gain_mu
- print "M&M clock recovery mu = %f" % self._mu
- print "M&M clock recovery omega rel. limit = %f" % self._omega_relative_limit
- print "frequency error = %f" % self._freq_error
+ print "bits per symbol: %d" % self.bits_per_symbol()
+ print "Bandwidth-Time Prod: %f" % self._bw
+ print "Timing bandwidth: %.2e" % self._timing_bw
def _setup_logging(self):
print "Demodulation logging turned on."
self.connect(self.fmdemod,
- gr.file_sink(gr.sizeof_float, "fmdemod.dat"))
+ gr.file_sink(gr.sizeof_float, "rx_gmsk_fmdemod.32f"))
self.connect(self.clock_recovery,
- gr.file_sink(gr.sizeof_float, "clock_recovery.dat"))
+ gr.file_sink(gr.sizeof_float, "rx_gmsk_clock_recovery.32f"))
self.connect(self.slicer,
- gr.file_sink(gr.sizeof_char, "slicer.dat"))
+ gr.file_sink(gr.sizeof_char, "rx_gmsk_slicer.8b"))
def add_options(parser):
"""
Adds GMSK demodulation-specific options to the standard parser
"""
- parser.add_option("", "--gain-mu", type="float", default=_def_gain_mu,
- help="M&M clock recovery gain mu [default=%default] (GMSK/PSK)")
- parser.add_option("", "--mu", type="float", default=_def_mu,
- help="M&M clock recovery mu [default=%default] (GMSK/PSK)")
- parser.add_option("", "--omega-relative-limit", type="float", default=_def_omega_relative_limit,
- help="M&M clock recovery omega relative limit [default=%default] (GMSK/PSK)")
- parser.add_option("", "--freq-error", type="float", default=_def_freq_error,
- help="M&M clock recovery frequency error [default=%default] (GMSK)")
+ parser.add_option("", "--timing-bw", type="float", default=_def_timing_bw,
+ help="set timing symbol sync loop gain lock-in bandwidth [default=%default]")
add_options=staticmethod(add_options)
def extract_kwargs_from_options(options):
"""
Given command line options, create dictionary suitable for passing to __init__
"""
- return modulation_utils.extract_kwargs_from_options(gmsk_demod.__init__,
- ('self',), options)
+ return modulation_utils2.extract_kwargs_from_options(gmsk_demod.__init__,
+ ('self',), options)
extract_kwargs_from_options=staticmethod(extract_kwargs_from_options)
-
#
# Add these to the mod/demod registry
#
-modulation_utils.add_type_1_mod('gmsk', gmsk_mod)
-modulation_utils.add_type_1_demod('gmsk', gmsk_demod)
+modulation_utils2.add_type_1_mod('gmsk', gmsk_mod)
+modulation_utils2.add_type_1_demod('gmsk', gmsk_demod)
diff --git a/gr-digital/python/qa_constellation.py b/gr-digital/python/qa_constellation.py
index 02afb8d2da..264ff7de64 100755
--- a/gr-digital/python/qa_constellation.py
+++ b/gr-digital/python/qa_constellation.py
@@ -70,10 +70,8 @@ tested_constellation_info = (
'mod_code': tested_mod_codes, },
True, None),
(digital_swig.constellation_bpsk, {}, True, None),
- # No differential testing for qpsk because it is gray-coded.
- # This is because soft decision making is simpler if we can assume
- # gray coding.
(digital_swig.constellation_qpsk, {}, False, None),
+ (digital_swig.constellation_dqpsk, {}, True, None),
(digital_swig.constellation_8psk, {}, False, None),
(twod_constell, {}, True, None),
(threed_constell, {}, True, None),
@@ -143,8 +141,8 @@ class test_constellation (gr_unittest.TestCase):
class mod_demod(gr.hier_block2):
def __init__(self, constellation, differential, rotation):
if constellation.arity() > 256:
- # If this becomes limiting some of the blocks should be generalised so that they can work
- # with shorts and ints as well as chars.
+ # If this becomes limiting some of the blocks should be generalised so
+ # that they can work with shorts and ints as well as chars.
raise ValueError("Constellation cannot contain more than 256 points.")
gr.hier_block2.__init__(self, "mod_demod",
@@ -174,7 +172,8 @@ class mod_demod(gr.hier_block2):
if self.differential:
self.blocks.append(gr.diff_encoder_bb(arity))
# Convert to constellation symbols.
- self.blocks.append(gr.chunks_to_symbols_bc(self.constellation.points(), self.constellation.dimensionality()))
+ self.blocks.append(gr.chunks_to_symbols_bc(self.constellation.points(),
+ self.constellation.dimensionality()))
# CHANNEL
# Channel just consists of a rotation to check differential coding.
if rotation is not None:
diff --git a/gr-digital/python/qa_constellation_receiver.py b/gr-digital/python/qa_constellation_receiver.py
index 79dded8ba3..25107e4a74 100755
--- a/gr-digital/python/qa_constellation_receiver.py
+++ b/gr-digital/python/qa_constellation_receiver.py
@@ -29,6 +29,7 @@ from generic_mod_demod import generic_mod, generic_demod
from qa_constellation import tested_constellations, twod_constell
+import math
# Set a seed so that if errors turn up they are reproducible.
# 1234 fails
@@ -47,11 +48,8 @@ FREQUENCY_OFFSET = 0.01
TIMING_OFFSET = 1.0
# RECEIVER PARAMETERS
-# Increased from normal default of 0.01 to speed things up.
-FREQ_ALPHA = 0.02
-# Decreased from normal default of 0.1 is required for the constellations
-# with smaller point separations.
-PHASE_ALPHA = 0.02
+FREQ_BW = 2*math.pi/100.0
+PHASE_BW = 2*math.pi/100.0
class test_constellation_receiver (gr_unittest.TestCase):
@@ -127,8 +125,8 @@ class rec_test_tb (gr.top_block):
channel = gr.channel_model(NOISE_VOLTAGE, FREQUENCY_OFFSET, TIMING_OFFSET)
# Receiver Blocks
demod = generic_demod(constellation, differential=differential,
- freq_alpha=FREQ_ALPHA,
- phase_alpha=PHASE_ALPHA)
+ freq_bw=FREQ_BW,
+ phase_bw=PHASE_BW)
self.dst = gr.vector_sink_b()
self.connect(src, packer, mod, channel, demod, self.dst)
diff --git a/gr-digital/python/qa_cpm.py b/gr-digital/python/qa_cpm.py
new file mode 100755
index 0000000000..12a84c76c2
--- /dev/null
+++ b/gr-digital/python/qa_cpm.py
@@ -0,0 +1,91 @@
+#!/usr/bin/env python
+#
+# Copyright 2010 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+
+from gnuradio import gr, gr_unittest
+import digital_swig
+import numpy
+
+class test_cpm(gr_unittest.TestCase):
+
+ def setUp (self):
+ self.tb = gr.top_block ()
+
+ def tearDown (self):
+ self.tb = None
+
+ def do_check_phase_shift(self, type, name):
+ sps = 2
+ L = 1
+ in_bits = (1,) * 20
+ src = gr.vector_source_b(in_bits, False)
+ cpm = digital_swig.cpmmod_bc(type, 0.5, sps, L)
+ arg = gr.complex_to_arg()
+ sink = gr.vector_sink_f()
+
+ self.tb.connect(src, cpm, arg, sink)
+ self.tb.run()
+
+ symbol_phases = numpy.array(sink.data()[sps*L-1::sps])
+ phase_diff = numpy.mod(numpy.subtract(symbol_phases[1:], symbol_phases[:-1]),
+ (2*numpy.pi,) * (len(symbol_phases)-1))
+ self.assertFloatTuplesAlmostEqual(tuple(phase_diff), (0.5 * numpy.pi,) * len(phase_diff), 5,
+ msg="Phase shift was not correct for CPM method " + name)
+
+ def test_001_lrec(self):
+ self.do_check_phase_shift(gr.cpm.LRC, 'LREC')
+
+ def test_001_lrc(self):
+ self.do_check_phase_shift(gr.cpm.LRC, 'LRC')
+
+ def test_001_lsrc(self):
+ self.do_check_phase_shift(gr.cpm.LSRC, 'LSRC')
+
+ def test_001_ltfm(self):
+ self.do_check_phase_shift(gr.cpm.TFM, 'TFM')
+
+ def test_001_lgmsk(self):
+ sps = 2
+ L = 5
+ bt = 0.3
+ in_bits = (1,) * 20
+ src = gr.vector_source_b(in_bits, False)
+ gmsk = digital_swig.gmskmod_bc(sps, bt, L)
+ arg = gr.complex_to_arg()
+ sink = gr.vector_sink_f()
+
+ self.tb.connect(src, gmsk, arg, sink)
+ self.tb.run()
+
+ symbol_phases = numpy.array(sink.data()[sps*L-1::sps])
+ phase_diff = numpy.mod(numpy.subtract(symbol_phases[1:], symbol_phases[:-1]),
+ (2*numpy.pi,) * (len(symbol_phases)-1))
+ self.assertFloatTuplesAlmostEqual(tuple(phase_diff), (0.5 * numpy.pi,) * len(phase_diff), 5,
+ msg="Phase shift was not correct for GMSK")
+
+ def test_phase_response(self):
+ phase_response = gr.cpm.phase_response(gr.cpm.LREC, 2, 4)
+ self.assertAlmostEqual(numpy.sum(phase_response), 1)
+
+
+if __name__ == '__main__':
+ gr_unittest.run(test_cpm, "test_cpm.xml")
+
diff --git a/gr-digital/python/qa_crc32.py b/gr-digital/python/qa_crc32.py
index f86813f3f3..f86813f3f3 100644..100755
--- a/gr-digital/python/qa_crc32.py
+++ b/gr-digital/python/qa_crc32.py
diff --git a/gr-digital/python/qa_fll_band_edge.py b/gr-digital/python/qa_fll_band_edge.py
index 088eb2b680..088eb2b680 100644..100755
--- a/gr-digital/python/qa_fll_band_edge.py
+++ b/gr-digital/python/qa_fll_band_edge.py
diff --git a/gr-digital/python/qa_lms_equalizer.py b/gr-digital/python/qa_lms_equalizer.py
index 025c785aa4..025c785aa4 100644..100755
--- a/gr-digital/python/qa_lms_equalizer.py
+++ b/gr-digital/python/qa_lms_equalizer.py
diff --git a/gr-digital/python/qa_mpsk_receiver.py b/gr-digital/python/qa_mpsk_receiver.py
index 7e9a76e1f2..6531e59f7a 100644..100755
--- a/gr-digital/python/qa_mpsk_receiver.py
+++ b/gr-digital/python/qa_mpsk_receiver.py
@@ -36,8 +36,7 @@ class test_mpsk_receiver(gr_unittest.TestCase):
# Test BPSK sync
M = 2
theta = 0
- alpha = 0.1
- beta = 0.25*alpha*alpha
+ loop_bw = cmath.pi/100.0
fmin = -0.5
fmax = 0.5
mu = 0.25
@@ -46,7 +45,7 @@ class test_mpsk_receiver(gr_unittest.TestCase):
gain_omega = 0.001
omega_rel = 0.001
- self.test = digital_swig.mpsk_receiver_cc(M, theta, alpha, beta,
+ self.test = digital_swig.mpsk_receiver_cc(M, theta, loop_bw,
fmin, fmax, mu, gain_mu,
omega, gain_omega,
omega_rel)
@@ -68,8 +67,8 @@ class test_mpsk_receiver(gr_unittest.TestCase):
expected_result = expected_result[len_e - Ncmp:]
dst_data = dst_data[len_d - Ncmp:]
- #print expected_result
- #print dst_data
+ #for e,d in zip(expected_result, dst_data):
+ # print e, d
self.assertComplexTuplesAlmostEqual (expected_result, dst_data, 1)
@@ -78,8 +77,7 @@ class test_mpsk_receiver(gr_unittest.TestCase):
# Test QPSK sync
M = 4
theta = 0
- alpha = 0.1
- beta = 0.25*alpha*alpha
+ loop_bw = 2*cmath.pi/100.0
fmin = -0.5
fmax = 0.5
mu = 0.25
@@ -88,11 +86,11 @@ class test_mpsk_receiver(gr_unittest.TestCase):
gain_omega = 0.001
omega_rel = 0.001
- self.test = digital_swig.mpsk_receiver_cc(M, theta, alpha, beta,
+ self.test = digital_swig.mpsk_receiver_cc(M, theta, loop_bw,
fmin, fmax, mu, gain_mu,
omega, gain_omega,
omega_rel)
-
+
data = 1000*[complex( 0.707, 0.707), complex( 0.707, 0.707),
complex(-0.707, 0.707), complex(-0.707, 0.707),
complex(-0.707, -0.707), complex(-0.707, -0.707),
@@ -103,8 +101,8 @@ class test_mpsk_receiver(gr_unittest.TestCase):
self.tb.connect(self.src, self.test, self.snk)
self.tb.run()
- expected_result = 1000*[complex(1.2, 0), complex(0, 1.2),
- complex(-1.2, 0), complex(0, -1.2)]
+ expected_result = 1000*[complex(0, -1.0), complex(1.0, 0),
+ complex(0, 1.0), complex(-1.0, 0)]
dst_data = self.snk.data()
# Only compare last Ncmp samples
@@ -114,9 +112,9 @@ class test_mpsk_receiver(gr_unittest.TestCase):
expected_result = expected_result[len_e - Ncmp:]
dst_data = dst_data[len_d - Ncmp:]
- #print expected_result
- #print dst_data
-
+ #for e,d in zip(expected_result, dst_data):
+ # print e, d
+
self.assertComplexTuplesAlmostEqual (expected_result, dst_data, 1)
if __name__ == '__main__':
diff --git a/gr-digital/python/qpsk.py b/gr-digital/python/qpsk.py
index 76e5df2701..481b7cb5b7 100644
--- a/gr-digital/python/qpsk.py
+++ b/gr-digital/python/qpsk.py
@@ -100,10 +100,77 @@ class qpsk_demod(generic_demod):
super(qpsk_demod, self).__init__(constellation=constellation,
*args, **kwargs)
+
+
+# /////////////////////////////////////////////////////////////////////////////
+# DQPSK constellation
+# /////////////////////////////////////////////////////////////////////////////
+
+def dqpsk_constellation(m=_def_constellation_points):
+ if m != _def_constellation_points:
+ raise ValueError("DQPSK can only have 4 constellation points.")
+ return digital_swig.constellation_dqpsk()
+
+# /////////////////////////////////////////////////////////////////////////////
+# DQPSK modulator
+# /////////////////////////////////////////////////////////////////////////////
+
+class dqpsk_mod(generic_mod):
+
+ def __init__(self, constellation_points=_def_constellation_points,
+ gray_coded=_def_gray_coded,
+ differential=True, *args, **kwargs):
+ """
+ Hierarchical block for RRC-filtered DQPSK modulation.
+
+ The input is a byte stream (unsigned char) and the
+ output is the complex modulated signal at baseband.
+
+ See generic_mod block for list of parameters.
+ """
+
+ constellation_points = _def_constellation_points
+ constellation = digital_swig.constellation_dqpsk()
+ if constellation_points != 4:
+ raise ValueError('Number of constellation points must be 4 for DQPSK.')
+ super(dqpsk_mod, self).__init__(constellation=constellation,
+ gray_coded=gray_coded,
+ differential=True,
+ *args, **kwargs)
+
+# /////////////////////////////////////////////////////////////////////////////
+# DQPSK demodulator
+#
+# /////////////////////////////////////////////////////////////////////////////
+
+class dqpsk_demod(generic_demod):
+
+ def __init__(self, constellation_points=_def_constellation_points,
+ differential=True, *args, **kwargs):
+
+ """
+ Hierarchical block for RRC-filtered DQPSK modulation.
+
+ The input is a byte stream (unsigned char) and the
+ output is the complex modulated signal at baseband.
+
+ See generic_demod block for list of parameters.
+ """
+ constellation_points = _def_constellation_points
+ constellation = digital_swig.constellation_dqpsk()
+ if constellation_points != 4:
+ raise ValueError('Number of constellation points must be 4 for DQPSK.')
+ super(dqpsk_demod, self).__init__(constellation=constellation,
+ differential=True,
+ *args, **kwargs)
+
#
# Add these to the mod/demod registry
#
modulation_utils2.add_type_1_mod('qpsk', qpsk_mod)
modulation_utils2.add_type_1_demod('qpsk', qpsk_demod)
modulation_utils2.add_type_1_constellation('qpsk', qpsk_constellation)
+modulation_utils2.add_type_1_mod('dqpsk', dqpsk_mod)
+modulation_utils2.add_type_1_demod('dqpsk', dqpsk_demod)
+modulation_utils2.add_type_1_constellation('dqpsk', dqpsk_constellation)
diff --git a/gr-digital/swig/CMakeLists.txt b/gr-digital/swig/CMakeLists.txt
index b62c024e06..5c6477aa18 100644
--- a/gr-digital/swig/CMakeLists.txt
+++ b/gr-digital/swig/CMakeLists.txt
@@ -30,10 +30,11 @@ SET(GR_SWIG_INCLUDE_DIRS
SET(GR_SWIG_LIBRARIES gnuradio-digital)
+GR_SWIG_MAKE(digital_hier digital_hier.i)
GR_SWIG_MAKE(digital_swig digital_swig.i)
GR_SWIG_INSTALL(
- TARGETS digital_swig
+ TARGETS digital_hier digital_swig
DESTINATION ${GR_PYTHON_DIR}/gnuradio/digital
COMPONENT "digital_python"
)
diff --git a/gr-digital/swig/Makefile.am b/gr-digital/swig/Makefile.am
index c0d28c24c6..6604665b0f 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 bd9aabcea1..95d6aea899 100644
--- a/gr-digital/swig/Makefile.swig.gen
+++ b/gr-digital/swig/Makefile.swig.gen
@@ -101,8 +101,7 @@ _digital_swig_la_LDFLAGS = \
_digital_swig_la_CXXFLAGS = \
$(STD_SWIG_CXX_FLAGS) \
- -I$(top_builddir) \
- $(digital_swig_la_swig_cxxflags)
+ -I$(top_builddir)
python/digital_swig.cc: digital_swig.py
digital_swig.py: digital_swig.i
@@ -143,3 +142,148 @@ gnuradio/digital_swig-primitive.scm: gnuradio/digital_swig.scm
endif # end of GUILE
+# -*- Makefile -*-
+#
+# Copyright 2009,2011 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+
+# Makefile.swig.gen for digital_hier.i
+
+## Default install locations for these files:
+##
+## Default location for the Python directory is:
+## ${prefix}/lib/python${python_version}/site-packages/[category]/digital_hier
+## Default location for the Python exec directory is:
+## ${exec_prefix}/lib/python${python_version}/site-packages/[category]/digital_hier
+##
+## The following can be overloaded to change the install location, but
+## this has to be done in the including Makefile.am -before-
+## Makefile.swig is included.
+
+digital_hier_pythondir_category ?= gnuradio/digital_hier
+digital_hier_pylibdir_category ?= $(digital_hier_pythondir_category)
+digital_hier_pythondir = $(pythondir)/$(digital_hier_pythondir_category)
+digital_hier_pylibdir = $(pyexecdir)/$(digital_hier_pylibdir_category)
+
+# The .so libraries for the guile modules get installed whereever guile
+# is installed, usually /usr/lib/guile/gnuradio/
+# FIXME: determince whether these should be installed with gnuradio.
+digital_hier_scmlibdir = $(libdir)
+
+# The scm files for the guile modules get installed where ever guile
+# is installed, usually /usr/share/guile/site/digital_hier
+# FIXME: determince whether these should be installed with gnuradio.
+digital_hier_scmdir = $(guiledir)
+
+## SWIG headers are always installed into the same directory.
+
+digital_hier_swigincludedir = $(swigincludedir)
+
+## This is a template file for a "generated" Makefile addition (in
+## this case, "Makefile.swig.gen"). By including the top-level
+## Makefile.swig, this file will be used to generate the SWIG
+## dependencies. Assign the variable TOP_SWIG_FILES to be the list of
+## SWIG .i files to generated wrappings for; there can be more than 1
+## so long as the names are unique (no sorting is done on the
+## TOP_SWIG_FILES list). This file explicitly assumes that a SWIG .i
+## file will generate .cc, .py, and possibly .h files -- meaning that
+## all of these files will have the same base name (that provided for
+## the SWIG .i file).
+##
+## This code is setup to ensure parallel MAKE ("-j" or "-jN") does the
+## right thing. For more info, see <
+## http://sources.redhat.com/automake/automake.html#Multiple-Outputs >
+
+## Other cleaned files: dependency files generated by SWIG or this Makefile
+
+MOSTLYCLEANFILES += $(DEPDIR)/*.S*
+
+## Various SWIG variables. These can be overloaded in the including
+## Makefile.am by setting the variable value there, then including
+## Makefile.swig .
+
+digital_hier_swiginclude_HEADERS = \
+ digital_hier.i \
+ $(digital_hier_swiginclude_headers)
+
+if PYTHON
+digital_hier_pylib_LTLIBRARIES = \
+ _digital_hier.la
+
+_digital_hier_la_SOURCES = \
+ python/digital_hier.cc \
+ $(digital_hier_la_swig_sources)
+
+digital_hier_python_PYTHON = \
+ digital_hier.py \
+ $(digital_hier_python)
+
+_digital_hier_la_LIBADD = \
+ $(STD_SWIG_LA_LIB_ADD) \
+ $(digital_hier_la_swig_libadd)
+
+_digital_hier_la_LDFLAGS = \
+ $(STD_SWIG_LA_LD_FLAGS) \
+ $(digital_hier_la_swig_ldflags)
+
+_digital_hier_la_CXXFLAGS = \
+ $(STD_SWIG_CXX_FLAGS) \
+ -I$(top_builddir) \
+ $(digital_hier_la_swig_cxxflags)
+
+python/digital_hier.cc: digital_hier.py
+digital_hier.py: digital_hier.i
+
+# Include the python dependencies for this file
+-include python/digital_hier.d
+
+endif # end of if python
+
+if GUILE
+
+digital_hier_scmlib_LTLIBRARIES = \
+ libguile-gnuradio-digital_hier.la
+libguile_gnuradio_digital_hier_la_SOURCES = \
+ guile/digital_hier.cc \
+ $(digital_hier_la_swig_sources)
+nobase_digital_hier_scm_DATA = \
+ gnuradio/digital_hier.scm \
+ gnuradio/digital_hier-primitive.scm
+libguile_gnuradio_digital_hier_la_LIBADD = \
+ $(STD_SWIG_LA_LIB_ADD) \
+ $(digital_hier_la_swig_libadd)
+libguile_gnuradio_digital_hier_la_LDFLAGS = \
+ $(STD_SWIG_LA_LD_FLAGS) \
+ $(digital_hier_la_swig_ldflags)
+libguile_gnuradio_digital_hier_la_CXXFLAGS = \
+ $(STD_SWIG_CXX_FLAGS) \
+ -I$(top_builddir) \
+ $(digital_hier_la_swig_cxxflags)
+
+guile/digital_hier.cc: gnuradio/digital_hier.scm
+gnuradio/digital_hier.scm: digital_hier.i
+gnuradio/digital_hier-primitive.scm: gnuradio/digital_hier.scm
+
+# Include the guile dependencies for this file
+-include guile/digital_hier.d
+
+endif # end of GUILE
+
+
diff --git a/gr-digital/swig/digital_constellation.i b/gr-digital/swig/digital_constellation.i
index ae31d443e6..7e0ad6afec 100644
--- a/gr-digital/swig/digital_constellation.i
+++ b/gr-digital/swig/digital_constellation.i
@@ -50,6 +50,7 @@ public:
unsigned int arity ();
digital_constellation_sptr base ();
bool apply_pre_diff_code();
+ void set_pre_diff_code(bool a);
std::vector<unsigned int> pre_diff_code();
unsigned int rotational_symmetry();
unsigned int dimensionality();
@@ -152,6 +153,23 @@ public:
digital_constellation_qpsk ();
};
+/*
+ DQPSK Constellation
+*/
+
+class digital_constellation_dqpsk;
+typedef boost::shared_ptr<digital_constellation_dqpsk> digital_constellation_dqpsk_sptr;
+%template(digital_constellation_dqpsk_sptr) boost::shared_ptr<digital_constellation_dqpsk>;
+%rename(constellation_dqpsk) digital_make_constellation_dqpsk;
+digital_constellation_dqpsk_sptr digital_make_constellation_dqpsk();
+%ignore digital_constellation_dqpsk;
+
+class digital_constellation_dqpsk : public digital_constellation
+{
+public:
+ digital_constellation_dqpsk ();
+};
+
/*
8PSK Constellation
diff --git a/gr-digital/swig/digital_constellation_receiver_cb.i b/gr-digital/swig/digital_constellation_receiver_cb.i
index e4be5f39f1..9c4ba645e0 100644
--- a/gr-digital/swig/digital_constellation_receiver_cb.i
+++ b/gr-digital/swig/digital_constellation_receiver_cb.i
@@ -28,23 +28,9 @@ digital_constellation_receiver_cb_sptr
digital_make_constellation_receiver_cb (digital_constellation_sptr constellation,
float loop_bw, float fmin, float fmax);
-class digital_constellation_receiver_cb : public gr_block
+class digital_constellation_receiver_cb : public gr_block, public gri_control_loop
{
private:
digital_constellation_receiver_cb (digital_contellation_sptr constellation,
float loop_bw, float fmin, float fmax);
-public:
- void set_loop_bandwidth(float bw);
- void set_damping_factor(float df);
- void set_alpha(float alpha);
- void set_beta(float beta);
- void set_frequency(float freq);
- void set_phase(float phase);
-
- float get_loop_bandwidth() const;
- float get_damping_factor() const;
- float get_alpha() const;
- float get_beta() const;
- float get_frequency() const;
- float get_phase() const;
};
diff --git a/gr-digital/swig/digital_fll_band_edge_cc.i b/gr-digital/swig/digital_fll_band_edge_cc.i
index f022bc7e18..3efcb89ed1 100644
--- a/gr-digital/swig/digital_fll_band_edge_cc.i
+++ b/gr-digital/swig/digital_fll_band_edge_cc.i
@@ -27,7 +27,7 @@ digital_fll_band_edge_cc_sptr digital_make_fll_band_edge_cc (float samps_per_sym
int filter_size,
float bandwidth);
-class digital_fll_band_edge_cc : public gr_sync_block
+class digital_fll_band_edge_cc : public gr_sync_block, public gri_control_loop
{
private:
digital_fll_band_edge_cc (float samps_per_sym, float rolloff,
diff --git a/gr-digital/swig/digital_hier.i b/gr-digital/swig/digital_hier.i
new file mode 100644
index 0000000000..e004461d26
--- /dev/null
+++ b/gr-digital/swig/digital_hier.i
@@ -0,0 +1,40 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2009,2010 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef SWIGIMPORTED
+%module(directors="1") digital_hier
+#endif
+
+ //%feature("autodoc", "1"); // generate python docstrings
+
+%include "gnuradio.i" // the common stuff
+
+%include "_digital_hier.i"
+
+#if SWIGGUILE
+%scheme %{
+(load-extension-global "libguile-gnuradio-digital_hier" "scm_init_gnuradio_digital_hier_module")
+%}
+
+%goops %{
+ (use-modules (gnuradio gnuradio_core_runtime))
+%}
+#endif
diff --git a/gr-digital/swig/digital_mpsk_receiver_cc.i b/gr-digital/swig/digital_mpsk_receiver_cc.i
index cdc9f661b5..b51411f6fb 100644
--- a/gr-digital/swig/digital_mpsk_receiver_cc.i
+++ b/gr-digital/swig/digital_mpsk_receiver_cc.i
@@ -23,16 +23,16 @@
GR_SWIG_BLOCK_MAGIC(digital,mpsk_receiver_cc);
digital_mpsk_receiver_cc_sptr digital_make_mpsk_receiver_cc (unsigned int M, float theta,
- float alpha, float beta,
+ float loop_bw,
float fmin, float fmax,
float mu, float gain_mu,
float omega, float gain_omega,
float omega_rel);
-class digital_mpsk_receiver_cc : public gr_block
+class digital_mpsk_receiver_cc : public gr_block, public gri_control_loop
{
private:
digital_mpsk_receiver_cc (unsigned int M,float theta,
- float alpha, float beta,
+ float loop_bw,
float fmin, float fmax,
float mu, float gain_mu,
float omega, float gain_omega, float omega_rel);
@@ -49,12 +49,4 @@ public:
}
void set_gain_mu (float gain_mu) { d_gain_mu = gain_mu; }
void set_gain_omega (float gain_omega) { d_gain_omega = gain_omega; }
- float alpha() const { return d_alpha; }
- float beta() const { return d_beta; }
- float freq() const { return d_freq; }
- float phase() const { return d_phase; }
- void set_alpha(float alpha) { d_alpha = alpha; }
- void set_beta(float beta) { d_beta = beta; }
- void set_freq(float freq) { d_freq = freq; }
- void set_phase(float phase) { d_phase = phase; }
};
diff --git a/gr-digital/swig/digital_swig.i b/gr-digital/swig/digital_swig.i
index 0328ca2fcc..ca50f9c501 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"