summaryrefslogtreecommitdiff
path: root/gnuradio-core
diff options
context:
space:
mode:
Diffstat (limited to 'gnuradio-core')
-rw-r--r--gnuradio-core/src/lib/filter/gr_pfb_clock_sync_ccf.cc163
-rw-r--r--gnuradio-core/src/lib/filter/gr_pfb_clock_sync_ccf.h50
-rw-r--r--gnuradio-core/src/lib/filter/gr_pfb_clock_sync_ccf.i13
-rw-r--r--gnuradio-core/src/lib/general/Makefile.am3
-rw-r--r--gnuradio-core/src/lib/general/general.i5
-rw-r--r--gnuradio-core/src/lib/general/gr_copy.cc71
-rw-r--r--gnuradio-core/src/lib/general/gr_copy.h62
-rw-r--r--gnuradio-core/src/lib/general/gr_copy.i36
-rw-r--r--gnuradio-core/src/lib/general/gr_mpsk_receiver_cc.cc2
-rw-r--r--gnuradio-core/src/lib/io/gr_histo_sink_f.cc11
-rw-r--r--gnuradio-core/src/lib/io/gr_histo_sink_f.h4
-rw-r--r--gnuradio-core/src/lib/missing/Makefile.am14
-rw-r--r--gnuradio-core/src/python/gnuradio/blks2impl/Makefile.am2
-rw-r--r--gnuradio-core/src/python/gnuradio/blks2impl/dbpsk.py20
-rw-r--r--gnuradio-core/src/python/gnuradio/blks2impl/dbpsk2.py351
-rw-r--r--gnuradio-core/src/python/gnuradio/blks2impl/dqpsk.py8
-rw-r--r--gnuradio-core/src/python/gnuradio/blks2impl/dqpsk2.py353
-rw-r--r--gnuradio-core/src/python/gnuradio/gr/Makefile.am1
-rwxr-xr-xgnuradio-core/src/python/gnuradio/gr/qa_copy.py58
19 files changed, 1109 insertions, 118 deletions
diff --git a/gnuradio-core/src/lib/filter/gr_pfb_clock_sync_ccf.cc b/gnuradio-core/src/lib/filter/gr_pfb_clock_sync_ccf.cc
index 91cbf74c6..433b7d613 100644
--- a/gnuradio-core/src/lib/filter/gr_pfb_clock_sync_ccf.cc
+++ b/gnuradio-core/src/lib/filter/gr_pfb_clock_sync_ccf.cc
@@ -33,45 +33,51 @@
#include <gr_io_signature.h>
#include <gr_math.h>
-gr_pfb_clock_sync_ccf_sptr gr_make_pfb_clock_sync_ccf (float sps, float gain,
+gr_pfb_clock_sync_ccf_sptr gr_make_pfb_clock_sync_ccf (double sps, float gain,
const std::vector<float> &taps,
unsigned int filter_size,
- float init_phase)
+ float init_phase,
+ float max_rate_deviation)
{
return gr_pfb_clock_sync_ccf_sptr (new gr_pfb_clock_sync_ccf (sps, gain, taps,
filter_size,
- init_phase));
+ init_phase,
+ max_rate_deviation));
}
-
-gr_pfb_clock_sync_ccf::gr_pfb_clock_sync_ccf (float sps, float gain,
+int ios[] = {sizeof(gr_complex), sizeof(float), sizeof(float), sizeof(float)};
+std::vector<int> iosig(ios, ios+sizeof(ios)/sizeof(int));
+gr_pfb_clock_sync_ccf::gr_pfb_clock_sync_ccf (double sps, float gain,
const std::vector<float> &taps,
unsigned int filter_size,
- float init_phase)
+ float init_phase,
+ float max_rate_deviation)
: gr_block ("pfb_clock_sync_ccf",
gr_make_io_signature (1, 1, sizeof(gr_complex)),
- gr_make_io_signature2 (2, 2, sizeof(gr_complex), sizeof(float))),
- d_updated (false), d_sps(sps), d_alpha(gain)
+ gr_make_io_signaturev (1, 4, iosig)),
+ d_updated (false), d_nfilters(filter_size),
+ d_max_dev(max_rate_deviation)
{
d_nfilters = filter_size;
+ d_sps = floor(sps);
// Store the last filter between calls to work
// The accumulator keeps track of overflow to increment the stride correctly.
// set it here to the fractional difference based on the initial phaes
- // assert(init_phase <= 2*M_PI);
- float x = init_phase / (2*M_PI); //normalize initial phase
- d_acc = x*(d_nfilters-1);
- d_last_filter = (int)floor(d_acc);
- d_acc = fmodf(d_acc, 1);
- d_start_count = 0;
-
+ set_alpha(gain);
+ set_beta(0.25*gain*gain);
+ d_k = init_phase;
+ d_rate = (sps-floor(sps))*(double)d_nfilters;
+ d_rate_i = (int)floor(d_rate);
+ d_rate_f = d_rate - (float)d_rate_i;
+ d_filtnum = (int)floor(d_k);
d_filters = std::vector<gr_fir_ccf*>(d_nfilters);
d_diff_filters = std::vector<gr_fir_ccf*>(d_nfilters);
// Create an FIR filter for each channel and zero out the taps
std::vector<float> vtaps(0, d_nfilters);
- for(unsigned int i = 0; i < d_nfilters; i++) {
+ for(int i = 0; i < d_nfilters; i++) {
d_filters[i] = gr_fir_util::create_gr_fir_ccf(vtaps);
d_diff_filters[i] = gr_fir_util::create_gr_fir_ccf(vtaps);
}
@@ -85,7 +91,7 @@ gr_pfb_clock_sync_ccf::gr_pfb_clock_sync_ccf (float sps, float gain,
gr_pfb_clock_sync_ccf::~gr_pfb_clock_sync_ccf ()
{
- for(unsigned int i = 0; i < d_nfilters; i++) {
+ for(int i = 0; i < d_nfilters; i++) {
delete d_filters[i];
}
}
@@ -95,7 +101,7 @@ gr_pfb_clock_sync_ccf::set_taps (const std::vector<float> &newtaps,
std::vector< std::vector<float> > &ourtaps,
std::vector<gr_fir_ccf*> &ourfilter)
{
- unsigned int i,j;
+ int i,j;
unsigned int ntaps = newtaps.size();
d_taps_per_filter = (unsigned int)ceil((double)ntaps/(double)d_nfilters);
@@ -114,13 +120,13 @@ gr_pfb_clock_sync_ccf::set_taps (const std::vector<float> &newtaps,
// Partition the filter
for(i = 0; i < d_nfilters; i++) {
// Each channel uses all d_taps_per_filter with 0's if not enough taps to fill out
- ourtaps[i] = std::vector<float>(d_taps_per_filter, 0);
+ ourtaps[d_nfilters-1-i] = std::vector<float>(d_taps_per_filter, 0);
for(j = 0; j < d_taps_per_filter; j++) {
- ourtaps[i][j] = tmp_taps[i + j*d_nfilters]; // add taps to channels in reverse order
+ ourtaps[d_nfilters - 1 - i][j] = tmp_taps[i + j*d_nfilters];
}
// Build a filter for each channel and add it's taps to it
- ourfilter[i]->set_taps(ourtaps[i]);
+ ourfilter[i]->set_taps(ourtaps[d_nfilters-1-i]);
}
// Set the history to ensure enough input items for each filter
@@ -133,38 +139,53 @@ void
gr_pfb_clock_sync_ccf::create_diff_taps(const std::vector<float> &newtaps,
std::vector<float> &difftaps)
{
+ float maxtap = 1e-20;
difftaps.clear();
difftaps.push_back(0); //newtaps[0]);
for(unsigned int i = 1; i < newtaps.size()-1; i++) {
- difftaps.push_back(newtaps[i+1] - newtaps[i-1]);
+ float tap = newtaps[i+1] - newtaps[i-1];
+ difftaps.push_back(tap);
+ if(tap > maxtap) {
+ maxtap = tap;
+ }
}
difftaps.push_back(0);//-newtaps[newtaps.size()-1]);
+
+ // Scale the differential taps; helps scale error term to better update state
+ // FIXME: should this be scaled this way or use the same gain as the taps?
+ for(unsigned int i = 0; i < difftaps.size(); i++) {
+ difftaps[i] /= maxtap;
+ }
}
void
gr_pfb_clock_sync_ccf::print_taps()
{
- unsigned int i, j;
+ int i, j;
+ printf("[ ");
for(i = 0; i < d_nfilters; i++) {
- printf("filter[%d]: [%.4e, ", i, d_taps[i][0]);
+ printf("[%.4e, ", d_taps[i][0]);
for(j = 1; j < d_taps_per_filter-1; j++) {
printf("%.4e,", d_taps[i][j]);
}
- printf("%.4e]\n", d_taps[i][j]);
+ printf("%.4e],", d_taps[i][j]);
}
+ printf(" ]\n");
}
void
gr_pfb_clock_sync_ccf::print_diff_taps()
{
- unsigned int i, j;
+ int i, j;
+ printf("[ ");
for(i = 0; i < d_nfilters; i++) {
- printf("filter[%d]: [%.4e, ", i, d_dtaps[i][0]);
+ printf("[%.4e, ", d_dtaps[i][0]);
for(j = 1; j < d_taps_per_filter-1; j++) {
printf("%.4e,", d_dtaps[i][j]);
}
- printf("%.4e]\n", d_dtaps[i][j]);
+ printf("%.4e],", d_dtaps[i][j]);
}
+ printf(" ]\n");
}
@@ -172,8 +193,7 @@ std::vector<float>
gr_pfb_clock_sync_ccf::channel_taps(int channel)
{
std::vector<float> taps;
- unsigned int i;
- for(i = 0; i < d_taps_per_filter; i++) {
+ for(int i = 0; i < d_taps_per_filter; i++) {
taps.push_back(d_taps[channel][i]);
}
return taps;
@@ -183,8 +203,7 @@ std::vector<float>
gr_pfb_clock_sync_ccf::diff_channel_taps(int channel)
{
std::vector<float> taps;
- unsigned int i;
- for(i = 0; i < d_taps_per_filter; i++) {
+ for(int i = 0; i < d_taps_per_filter; i++) {
taps.push_back(d_dtaps[channel][i]);
}
return taps;
@@ -199,7 +218,13 @@ gr_pfb_clock_sync_ccf::general_work (int noutput_items,
{
gr_complex *in = (gr_complex *) input_items[0];
gr_complex *out = (gr_complex *) output_items[0];
- float *err = (float *) output_items[1];
+
+ float *err, *outrate, *outk;
+ if(output_items.size() > 2) {
+ err = (float *) output_items[1];
+ outrate = (float*)output_items[2];
+ outk = (float*)output_items[3];
+ }
if (d_updated) {
d_updated = false;
@@ -209,50 +234,50 @@ gr_pfb_clock_sync_ccf::general_work (int noutput_items,
// We need this many to process one output
int nrequired = ninput_items[0] - d_taps_per_filter;
- int i = 0, count = d_start_count;
- float error = 0;
+ int i = 0, count = 0;
+ float error, error_r, error_i;
// produce output as long as we can and there are enough input samples
while((i < noutput_items) && (count < nrequired)) {
- out[i] = d_filters[d_last_filter]->filter(&in[count]);
- error = (out[i] * d_diff_filters[d_last_filter]->filter(&in[count])).real();
- err[i] = error;
-
- d_acc += d_alpha*error;
- gr_branchless_clip(d_acc, 1);
-
- int newfilter;
- newfilter = (int)((float)d_last_filter + d_acc);
- if(newfilter != (int)d_last_filter)
- d_acc = 0.5;
-
- if(newfilter >= (int)d_nfilters) {
- d_last_filter = newfilter - d_nfilters;
- count++;
+ d_filtnum = (int)floor(d_k);
+
+ // Keep the current filter number in [0, d_nfilters]
+ // If we've run beyond the last filter, wrap around and go to next sample
+ // If we've go below 0, wrap around and go to previous sample
+ while(d_filtnum >= d_nfilters) {
+ d_k -= d_nfilters;
+ d_filtnum -= d_nfilters;
+ count += 1;
}
- else if(newfilter < 0) {
- d_last_filter = d_nfilters + newfilter;
- count--;
- }
- else {
- d_last_filter = newfilter;
+ while(d_filtnum < 0) {
+ d_k += d_nfilters;
+ d_filtnum += d_nfilters;
+ count -= 1;
}
+ out[i] = d_filters[d_filtnum]->filter(&in[count]);
+ gr_complex diff = d_diff_filters[d_filtnum]->filter(&in[count]);
+ error_r = out[i].real() * diff.real();
+ error_i = out[i].imag() * diff.imag();
+ error = (error_i + error_r) / 2.0; // average error from I&Q channel
+
+ // Run the control loop to update the current phase (k) and tracking rate
+ d_k = d_k + d_alpha*error + d_rate_i + d_rate_f;
+ d_rate_f = d_rate_f + d_beta*error;
+
+ // Keep our rate within a good range
+ d_rate_f = gr_branchless_clip(d_rate_f, d_max_dev);
+
i++;
- count += d_sps;
- }
+ count += (int)floor(d_sps);
- // Set the start index at the next entrance to the work function
- // if we stop because we run out of input items, jump ahead in the
- // next call to work. Otherwise, we can start at zero.
- if(count > nrequired) {
- d_start_count = count - (nrequired);
- consume_each(ninput_items[0]-d_taps_per_filter);
- }
- else {
- d_start_count = 0;
- consume_each(count);
+ if(output_items.size() > 2) {
+ err[i] = error;
+ outrate[i] = d_rate_f;
+ outk[i] = d_k;
+ }
}
-
+ consume_each(count);
+
return i;
}
diff --git a/gnuradio-core/src/lib/filter/gr_pfb_clock_sync_ccf.h b/gnuradio-core/src/lib/filter/gr_pfb_clock_sync_ccf.h
index 1a04e55c7..a07192a7f 100644
--- a/gnuradio-core/src/lib/filter/gr_pfb_clock_sync_ccf.h
+++ b/gnuradio-core/src/lib/filter/gr_pfb_clock_sync_ccf.h
@@ -28,10 +28,11 @@
class gr_pfb_clock_sync_ccf;
typedef boost::shared_ptr<gr_pfb_clock_sync_ccf> gr_pfb_clock_sync_ccf_sptr;
-gr_pfb_clock_sync_ccf_sptr gr_make_pfb_clock_sync_ccf (float sps, float gain,
- const std::vector<float> &taps,
- unsigned int filter_size=32,
- float init_phase=0);
+gr_pfb_clock_sync_ccf_sptr gr_make_pfb_clock_sync_ccf (double sps, float gain,
+ const std::vector<float> &taps,
+ unsigned int filter_size=32,
+ float init_phase=0,
+ float max_rate_deviation=1.5);
class gr_fir_ccf;
@@ -50,31 +51,38 @@ class gr_pfb_clock_sync_ccf : public gr_block
/*!
* Build the polyphase filterbank timing synchronizer.
*/
- friend gr_pfb_clock_sync_ccf_sptr gr_make_pfb_clock_sync_ccf (float sps, float gain,
+ friend gr_pfb_clock_sync_ccf_sptr gr_make_pfb_clock_sync_ccf (double sps, float gain,
const std::vector<float> &taps,
unsigned int filter_size,
- float init_phase);
+ float init_phase,
+ float max_rate_deviation);
bool d_updated;
- unsigned int d_sps;
+ double d_sps;
+ double d_sample_num;
float d_alpha;
- unsigned int d_nfilters;
+ float d_beta;
+ int d_nfilters;
std::vector<gr_fir_ccf*> d_filters;
std::vector<gr_fir_ccf*> d_diff_filters;
std::vector< std::vector<float> > d_taps;
std::vector< std::vector<float> > d_dtaps;
- float d_acc;
- unsigned int d_last_filter;
- unsigned int d_start_count;
- unsigned int d_taps_per_filter;
+ float d_k;
+ float d_rate;
+ float d_rate_i;
+ float d_rate_f;
+ float d_max_dev;
+ int d_filtnum;
+ int d_taps_per_filter;
/*!
* Build the polyphase filterbank timing synchronizer.
*/
- gr_pfb_clock_sync_ccf (float sps, float gain,
+ gr_pfb_clock_sync_ccf (double sps, float gain,
const std::vector<float> &taps,
unsigned int filter_size,
- float init_phase);
+ float init_phase,
+ float max_rate_deviation);
void create_diff_taps(const std::vector<float> &newtaps,
std::vector<float> &difftaps);
@@ -96,6 +104,20 @@ public:
*/
void print_taps();
void print_diff_taps();
+
+ void set_alpha(float alpha)
+ {
+ d_alpha = alpha;
+ }
+ void set_beta(float beta)
+ {
+ d_beta = beta;
+ }
+
+ void set_max_rate_deviation(float m)
+ {
+ d_max_dev = m;
+ }
int general_work (int noutput_items,
gr_vector_int &ninput_items,
diff --git a/gnuradio-core/src/lib/filter/gr_pfb_clock_sync_ccf.i b/gnuradio-core/src/lib/filter/gr_pfb_clock_sync_ccf.i
index 729d4a1aa..197984287 100644
--- a/gnuradio-core/src/lib/filter/gr_pfb_clock_sync_ccf.i
+++ b/gnuradio-core/src/lib/filter/gr_pfb_clock_sync_ccf.i
@@ -22,18 +22,20 @@
GR_SWIG_BLOCK_MAGIC(gr,pfb_clock_sync_ccf);
-gr_pfb_clock_sync_ccf_sptr gr_make_pfb_clock_sync_ccf (float sps, float gain,
+gr_pfb_clock_sync_ccf_sptr gr_make_pfb_clock_sync_ccf (double sps, float gain,
const std::vector<float> &taps,
unsigned int filter_size=32,
- float init_phase=0);
+ float init_phase=0,
+ float max_rate_deviation=1.5);
class gr_pfb_clock_sync_ccf : public gr_block
{
private:
- gr_pfb_clock_sync_ccf (float sps, float gain,
+ gr_pfb_clock_sync_ccf (double sps, float gain,
const std::vector<float> &taps,
unsigned int filter_size,
- float init_phase);
+ float init_phase,
+ float max_rate_deviation);
public:
~gr_pfb_clock_sync_ccf ();
@@ -46,4 +48,7 @@ class gr_pfb_clock_sync_ccf : public gr_block
std::vector<float> diff_channel_taps(int channel);
void print_taps();
void print_diff_taps();
+ void set_alpha(float alpha);
+ void set_beta(float beta);
+ void set_max_rate_deviation(float m);
};
diff --git a/gnuradio-core/src/lib/general/Makefile.am b/gnuradio-core/src/lib/general/Makefile.am
index 9b070b865..cf6ff1e65 100644
--- a/gnuradio-core/src/lib/general/Makefile.am
+++ b/gnuradio-core/src/lib/general/Makefile.am
@@ -51,6 +51,7 @@ libgeneral_la_SOURCES = \
gr_complex_to_interleaved_short.cc \
gr_complex_to_xxx.cc \
gr_conjugate_cc.cc \
+ gr_copy.cc \
gr_constellation_decoder_cb.cc \
gr_correlate_access_code_bb.cc \
gr_costas_loop_cc.cc \
@@ -204,6 +205,7 @@ grinclude_HEADERS = \
gr_complex_to_xxx.h \
gr_conjugate_cc.h \
gr_constellation_decoder_cb.h \
+ gr_copy.h \
gr_correlate_access_code_bb.h \
gr_costas_loop_cc.h \
gr_count_bits.h \
@@ -373,6 +375,7 @@ swiginclude_HEADERS = \
gr_complex_to_xxx.i \
gr_conjugate_cc.i \
gr_constellation_decoder_cb.i \
+ gr_copy.i \
gr_correlate_access_code_bb.i \
gr_costas_loop_cc.i \
gr_cpfsk_bc.i \
diff --git a/gnuradio-core/src/lib/general/general.i b/gnuradio-core/src/lib/general/general.i
index 0684e63a5..e1161c8eb 100644
--- a/gnuradio-core/src/lib/general/general.i
+++ b/gnuradio-core/src/lib/general/general.i
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/*
- * Copyright 2004,2005,2006,2007,2008 Free Software Foundation, Inc.
+ * Copyright 2004,2005,2006,2007,2008,2009 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
@@ -139,7 +139,7 @@
#include <gr_stretch_ff.h>
#include <gr_wavelet_ff.h>
#include <gr_wvps_ff.h>
-
+#include <gr_copy.h>
%}
%include "gr_nop.i"
@@ -259,3 +259,4 @@
%include "gr_stretch_ff.i"
%include "gr_wavelet_ff.i"
%include "gr_wvps_ff.i"
+%include "gr_copy.i"
diff --git a/gnuradio-core/src/lib/general/gr_copy.cc b/gnuradio-core/src/lib/general/gr_copy.cc
new file mode 100644
index 000000000..c6564c231
--- /dev/null
+++ b/gnuradio-core/src/lib/general/gr_copy.cc
@@ -0,0 +1,71 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2006,2009 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 <gr_copy.h>
+#include <gr_io_signature.h>
+#include <string.h>
+
+gr_copy_sptr
+gr_make_copy(size_t itemsize)
+{
+ return gnuradio::get_initial_sptr(new gr_copy(itemsize));
+}
+
+gr_copy::gr_copy(size_t itemsize)
+ : gr_block ("copy",
+ gr_make_io_signature (1, 1, itemsize),
+ gr_make_io_signature (1, 1, itemsize)),
+ d_itemsize(itemsize),
+ d_enabled(true)
+{
+}
+
+bool
+gr_copy::check_topology(int ninputs, int noutputs)
+{
+ return ninputs == noutputs;
+}
+
+int
+gr_copy::general_work(int noutput_items,
+ gr_vector_int &ninput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+{
+ const uint8_t *in = (const uint8_t *) input_items[0];
+ uint8_t *out = (uint8_t *) output_items[0];
+
+ int n = std::min<int>(ninput_items[0], noutput_items);
+ int j = 0;
+
+ if (d_enabled) {
+ memcpy(out, in, n*d_itemsize);
+ j = n;
+ }
+
+ consume_each(n);
+ return j;
+}
diff --git a/gnuradio-core/src/lib/general/gr_copy.h b/gnuradio-core/src/lib/general/gr_copy.h
new file mode 100644
index 000000000..d99aef8b7
--- /dev/null
+++ b/gnuradio-core/src/lib/general/gr_copy.h
@@ -0,0 +1,62 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2006,2009 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_GR_COPY_H
+#define INCLUDED_GR_COPY_H
+
+#include <gr_block.h>
+
+class gr_copy;
+typedef boost::shared_ptr<gr_copy> gr_copy_sptr;
+
+gr_copy_sptr gr_make_copy(size_t itemsize);
+
+/*!
+ * \brief output[i] = input[i]
+ * \ingroup misc_blk
+ *
+ * When enabled (default), this block copies its input to its output.
+ * When disabled, this block drops its input on the floor.
+ *
+ */
+class gr_copy : public gr_block
+{
+ size_t d_itemsize;
+ bool d_enabled;
+
+ friend gr_copy_sptr gr_make_copy(size_t itemsize);
+ gr_copy(size_t itemsize);
+
+ public:
+
+ bool check_topology(int ninputs, int noutputs);
+
+ void set_enabled(bool enable) { d_enabled = enable; }
+ bool enabled() const { return d_enabled;}
+
+ int general_work(int noutput_items,
+ gr_vector_int &ninput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+};
+
+#endif
diff --git a/gnuradio-core/src/lib/general/gr_copy.i b/gnuradio-core/src/lib/general/gr_copy.i
new file mode 100644
index 000000000..e260d8e84
--- /dev/null
+++ b/gnuradio-core/src/lib/general/gr_copy.i
@@ -0,0 +1,36 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2006,2009 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+GR_SWIG_BLOCK_MAGIC(gr,copy)
+
+gr_copy_sptr gr_make_copy(size_t itemsize);
+
+class gr_copy : public gr_block
+{
+ private:
+ gr_copy(size_t itemsize);
+
+public:
+
+ void set_enabled(bool enabled);
+ bool enabled();
+};
diff --git a/gnuradio-core/src/lib/general/gr_mpsk_receiver_cc.cc b/gnuradio-core/src/lib/general/gr_mpsk_receiver_cc.cc
index 49bbb8d36..1efa82703 100644
--- a/gnuradio-core/src/lib/general/gr_mpsk_receiver_cc.cc
+++ b/gnuradio-core/src/lib/general/gr_mpsk_receiver_cc.cc
@@ -265,8 +265,6 @@ gr_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);
-
- phase_error = gr_branchless_clip(phase_error, 1.0);
d_freq += d_beta*phase_error; // adjust frequency based on error
d_phase += d_freq + d_alpha*phase_error; // adjust phase based on error
diff --git a/gnuradio-core/src/lib/io/gr_histo_sink_f.cc b/gnuradio-core/src/lib/io/gr_histo_sink_f.cc
index a923a7e45..2885fe428 100644
--- a/gnuradio-core/src/lib/io/gr_histo_sink_f.cc
+++ b/gnuradio-core/src/lib/io/gr_histo_sink_f.cc
@@ -53,7 +53,6 @@ gr_histo_sink_f::gr_histo_sink_f (gr_msg_queue_sptr msgq)
: gr_sync_block ("histo_sink_f", gr_make_io_signature (1, 1, sizeof (float)), gr_make_io_signature (0, 0, 0)),
d_msgq (msgq), d_num_bins(11), d_frame_size(1000), d_sample_count(0), d_bins(NULL), d_samps(NULL)
{
- pthread_mutex_init(&d_mutex, 0);
//allocate arrays and clear
set_num_bins(d_num_bins);
set_frame_size(d_frame_size);
@@ -61,7 +60,6 @@ gr_histo_sink_f::gr_histo_sink_f (gr_msg_queue_sptr msgq)
gr_histo_sink_f::~gr_histo_sink_f (void)
{
- pthread_mutex_destroy(&d_mutex);
delete [] d_samps;
delete [] d_bins;
}
@@ -72,7 +70,7 @@ gr_histo_sink_f::work (int noutput_items,
gr_vector_void_star &output_items)
{
const float *in = (const float *) input_items[0];
- pthread_mutex_lock(&d_mutex);
+ gruel::scoped_lock guard(d_mutex); // hold mutex for duration of this function
for (unsigned int i = 0; i < (unsigned int)noutput_items; i++){
d_samps[d_sample_count] = in[i];
d_sample_count++;
@@ -82,7 +80,6 @@ gr_histo_sink_f::work (int noutput_items,
clear();
}
}
- pthread_mutex_unlock(&d_mutex);
return noutput_items;
}
@@ -148,22 +145,20 @@ gr_histo_sink_f::get_num_bins(void){
**************************************************/
void
gr_histo_sink_f::set_frame_size(unsigned int frame_size){
- pthread_mutex_lock(&d_mutex);
+ gruel::scoped_lock guard(d_mutex); // hold mutex for duration of this function
d_frame_size = frame_size;
/* allocate a new sample array */
delete [] d_samps;
d_samps = new float[d_frame_size];
clear();
- pthread_mutex_unlock(&d_mutex);
}
void
gr_histo_sink_f::set_num_bins(unsigned int num_bins){
- pthread_mutex_lock(&d_mutex);
+ gruel::scoped_lock guard(d_mutex); // hold mutex for duration of this function
d_num_bins = num_bins;
/* allocate a new bin array */
delete [] d_bins;
d_bins = new unsigned int[d_num_bins];
clear();
- pthread_mutex_unlock(&d_mutex);
}
diff --git a/gnuradio-core/src/lib/io/gr_histo_sink_f.h b/gnuradio-core/src/lib/io/gr_histo_sink_f.h
index 640398c60..8ba45ec55 100644
--- a/gnuradio-core/src/lib/io/gr_histo_sink_f.h
+++ b/gnuradio-core/src/lib/io/gr_histo_sink_f.h
@@ -25,7 +25,7 @@
#include <gr_sync_block.h>
#include <gr_msg_queue.h>
-#include <pthread.h>
+#include <gruel/thread.h>
class gr_histo_sink_f;
typedef boost::shared_ptr<gr_histo_sink_f> gr_histo_sink_f_sptr;
@@ -45,7 +45,7 @@ private:
unsigned int d_sample_count;
unsigned int *d_bins;
float *d_samps;
- pthread_mutex_t d_mutex;
+ gruel::mutex d_mutex;
friend gr_histo_sink_f_sptr gr_make_histo_sink_f (gr_msg_queue_sptr msgq);
gr_histo_sink_f (gr_msg_queue_sptr msgq);
diff --git a/gnuradio-core/src/lib/missing/Makefile.am b/gnuradio-core/src/lib/missing/Makefile.am
index 08e521cb3..238370910 100644
--- a/gnuradio-core/src/lib/missing/Makefile.am
+++ b/gnuradio-core/src/lib/missing/Makefile.am
@@ -1,5 +1,5 @@
#
-# Copyright 2003,2004,2008 Free Software Foundation, Inc.
+# Copyright 2003,2004,2008,2009 Free Software Foundation, Inc.
#
# This file is part of GNU Radio
#
@@ -33,6 +33,14 @@ EXTRA_DIST = \
noinst_LTLIBRARIES = libmissing.la
-libmissing_la_SOURCES = \
- bug_work_around_8.cc \
+libmissing_la_common_SOURCES = \
+ bug_work_around_8.cc
+
+powerpc_CODE = \
posix_memalign.cc
+
+if MD_CPU_powerpc
+libmissing_la_SOURCES = $(libmissing_la_common_SOURCES) $(powerpc_CODE)
+else
+libmissing_la_SOURCES = $(libmissing_la_common_SOURCES)
+endif
diff --git a/gnuradio-core/src/python/gnuradio/blks2impl/Makefile.am b/gnuradio-core/src/python/gnuradio/blks2impl/Makefile.am
index f0825b151..68d683623 100644
--- a/gnuradio-core/src/python/gnuradio/blks2impl/Makefile.am
+++ b/gnuradio-core/src/python/gnuradio/blks2impl/Makefile.am
@@ -31,7 +31,9 @@ grblkspython_PYTHON = \
am_demod.py \
channel_model.py \
dbpsk.py \
+ dbpsk2.py \
dqpsk.py \
+ dqpsk2.py \
d8psk.py \
filterbank.py \
fm_demod.py \
diff --git a/gnuradio-core/src/python/gnuradio/blks2impl/dbpsk.py b/gnuradio-core/src/python/gnuradio/blks2impl/dbpsk.py
index 3147bfa2a..860015c3f 100644
--- a/gnuradio-core/src/python/gnuradio/blks2impl/dbpsk.py
+++ b/gnuradio-core/src/python/gnuradio/blks2impl/dbpsk.py
@@ -1,5 +1,5 @@
#
-# Copyright 2005,2006,2007 Free Software Foundation, Inc.
+# Copyright 2005,2006,2007,2009 Free Software Foundation, Inc.
#
# This file is part of GNU Radio
#
@@ -251,20 +251,20 @@ class dbpsk_demod(gr.hier_block2):
# symbol clock recovery
if not self._mm_gain_mu:
self._mm_gain_mu = 0.1
-
+
self._mm_omega = self._samples_per_symbol
self._mm_gain_omega = .25 * self._mm_gain_mu * self._mm_gain_mu
self._costas_beta = 0.25 * self._costas_alpha * self._costas_alpha
- fmin = -0.1
- fmax = 0.1
+ fmin = -0.25
+ fmax = 0.25
self.receiver=gr.mpsk_receiver_cc(arity, 0,
- self._costas_alpha, self._costas_beta,
- fmin, fmax,
- self._mm_mu, self._mm_gain_mu,
- self._mm_omega, self._mm_gain_omega,
- self._mm_omega_relative_limit)
-
+ self._costas_alpha, self._costas_beta,
+ fmin, fmax,
+ self._mm_mu, self._mm_gain_mu,
+ self._mm_omega, self._mm_gain_omega,
+ self._mm_omega_relative_limit)
+
# Do differential decoding based on phase change of symbols
self.diffdec = gr.diff_phasor_cc()
diff --git a/gnuradio-core/src/python/gnuradio/blks2impl/dbpsk2.py b/gnuradio-core/src/python/gnuradio/blks2impl/dbpsk2.py
new file mode 100644
index 000000000..4541b453b
--- /dev/null
+++ b/gnuradio-core/src/python/gnuradio/blks2impl/dbpsk2.py
@@ -0,0 +1,351 @@
+#
+# Copyright 2005,2006,2007 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.
+#
+
+# See gnuradio-examples/python/digital for examples
+
+"""
+differential BPSK modulation and demodulation.
+"""
+
+from gnuradio import gr, gru, modulation_utils
+from math import pi, sqrt
+import psk
+import cmath
+from pprint import pprint
+
+# default values (used in __init__ and add_options)
+_def_samples_per_symbol = 2
+_def_excess_bw = 0.35
+_def_gray_code = True
+_def_verbose = False
+_def_log = False
+
+_def_costas_alpha = 0.1
+_def_timing_alpha = 0.100
+_def_timing_beta = 0.010
+_def_timing_max_dev = 1.5
+
+
+# /////////////////////////////////////////////////////////////////////////////
+# DBPSK modulator
+# /////////////////////////////////////////////////////////////////////////////
+
+class dbpsk2_mod(gr.hier_block2):
+
+ def __init__(self,
+ samples_per_symbol=_def_samples_per_symbol,
+ excess_bw=_def_excess_bw,
+ gray_code=_def_gray_code,
+ verbose=_def_verbose,
+ log=_def_log):
+ """
+ Hierarchical block for RRC-filtered differential BPSK modulation.
+
+ The input is a byte stream (unsigned char) and the
+ output is the complex modulated signal at baseband.
+
+ @param samples_per_symbol: samples per baud >= 2
+ @type samples_per_symbol: integer
+ @param excess_bw: Root-raised cosine filter excess bandwidth
+ @type excess_bw: float
+ @param gray_code: Tell modulator to Gray code the bits
+ @type gray_code: bool
+ @param verbose: Print information about modulator?
+ @type verbose: bool
+ @param log: Log modulation data to files?
+ @type log: bool
+ """
+
+ gr.hier_block2.__init__(self, "dbpsk_mod",
+ gr.io_signature(1, 1, gr.sizeof_char), # Input signature
+ gr.io_signature(1, 1, gr.sizeof_gr_complex)) # Output signature
+
+ self._samples_per_symbol = samples_per_symbol
+ self._excess_bw = excess_bw
+ self._gray_code = gray_code
+
+ if not isinstance(self._samples_per_symbol, int) or self._samples_per_symbol < 2:
+ raise TypeError, ("sbp must be an integer >= 2, is %d" % self._samples_per_symbol)
+
+ ntaps = 11 * self._samples_per_symbol
+
+ arity = pow(2,self.bits_per_symbol())
+
+ # turn bytes into k-bit vectors
+ self.bytes2chunks = \
+ gr.packed_to_unpacked_bb(self.bits_per_symbol(), gr.GR_MSB_FIRST)
+
+ if self._gray_code:
+ self.symbol_mapper = gr.map_bb(psk.binary_to_gray[arity])
+ else:
+ self.symbol_mapper = gr.map_bb(psk.binary_to_ungray[arity])
+
+ self.diffenc = gr.diff_encoder_bb(arity)
+
+ self.chunks2symbols = gr.chunks_to_symbols_bc(psk.constellation[arity])
+
+ # pulse shaping filter
+ self.rrc_taps = gr.firdes.root_raised_cosine(
+ self._samples_per_symbol, # gain (samples_per_symbol since we're
+ # interpolating by samples_per_symbol)
+ self._samples_per_symbol, # sampling rate
+ 1.0, # symbol rate
+ self._excess_bw, # excess bandwidth (roll-off factor)
+ ntaps)
+ self.rrc_filter = gr.interp_fir_filter_ccf(self._samples_per_symbol,
+ self.rrc_taps)
+
+ # Connect
+ self.connect(self, self.bytes2chunks, self.symbol_mapper, self.diffenc,
+ self.chunks2symbols, self.rrc_filter, self)
+
+ if verbose:
+ self._print_verbage()
+
+ if log:
+ self._setup_logging()
+
+
+ def samples_per_symbol(self):
+ return self._samples_per_symbol
+
+ def bits_per_symbol(self=None): # static method that's also callable on an instance
+ return 1
+ bits_per_symbol = staticmethod(bits_per_symbol) # make it a static method. RTFM
+
+ def add_options(parser):
+ """
+ Adds DBPSK modulation-specific options to the standard parser
+ """
+ parser.add_option("", "--excess-bw", type="float", default=_def_excess_bw,
+ help="set RRC excess bandwith factor [default=%default]")
+ parser.add_option("", "--no-gray-code", dest="gray_code",
+ action="store_false", default=True,
+ help="disable gray coding on modulated bits (PSK)")
+ 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(dbpsk2_mod.__init__,
+ ('self',), options)
+ extract_kwargs_from_options=staticmethod(extract_kwargs_from_options)
+
+
+ def _print_verbage(self):
+ print "\nModulator:"
+ print "bits per symbol: %d" % self.bits_per_symbol()
+ print "Gray code: %s" % self._gray_code
+ print "RRC roll-off factor: %.2f" % self._excess_bw
+
+ def _setup_logging(self):
+ print "Modulation logging turned on."
+ self.connect(self.bytes2chunks,
+ gr.file_sink(gr.sizeof_char, "tx_bytes2chunks.dat"))
+ self.connect(self.symbol_mapper,
+ gr.file_sink(gr.sizeof_char, "tx_graycoder.dat"))
+ self.connect(self.diffenc,
+ gr.file_sink(gr.sizeof_char, "tx_diffenc.dat"))
+ self.connect(self.chunks2symbols,
+ gr.file_sink(gr.sizeof_gr_complex, "tx_chunks2symbols.dat"))
+ self.connect(self.rrc_filter,
+ gr.file_sink(gr.sizeof_gr_complex, "tx_rrc_filter.dat"))
+
+
+# /////////////////////////////////////////////////////////////////////////////
+# DBPSK demodulator
+#
+# Differentially coherent detection of differentially encoded BPSK
+# /////////////////////////////////////////////////////////////////////////////
+
+class dbpsk2_demod(gr.hier_block2):
+
+ def __init__(self,
+ samples_per_symbol=_def_samples_per_symbol,
+ excess_bw=_def_excess_bw,
+ costas_alpha=_def_costas_alpha,
+ timing_alpha=_def_timing_alpha,
+ timing_max_dev=_def_timing_max_dev,
+ gray_code=_def_gray_code,
+ verbose=_def_verbose,
+ log=_def_log):
+ """
+ Hierarchical block for RRC-filtered differential BPSK demodulation
+
+ The input is the complex modulated signal at baseband.
+ The output is a stream of bits packed 1 bit per byte (LSB)
+
+ @param samples_per_symbol: samples per symbol >= 2
+ @type samples_per_symbol: float
+ @param excess_bw: Root-raised cosine filter excess bandwidth
+ @type excess_bw: float
+ @param costas_alpha: loop filter gain
+ @type costas_alpha: float
+ @param timing_alpha: timing loop alpha gain
+ @type timing_alpha: float
+ @param timing_max: timing loop maximum rate deviations
+ @type timing_max: float
+ @param gray_code: Tell modulator to Gray code the bits
+ @type gray_code: bool
+ @param verbose: Print information about modulator?
+ @type verbose: bool
+ @param debug: Print modualtion data to files?
+ @type debug: bool
+ """
+
+ gr.hier_block2.__init__(self, "dbpsk2_demod",
+ gr.io_signature(1, 1, gr.sizeof_gr_complex), # Input signature
+ gr.io_signature(1, 1, gr.sizeof_char)) # Output signature
+
+ self._samples_per_symbol = samples_per_symbol
+ self._excess_bw = excess_bw
+ self._costas_alpha = costas_alpha
+ self._timing_alpha = timing_alpha
+ self._timing_beta = _def_timing_beta
+ self._timing_max_dev=timing_max_dev
+ self._gray_code = gray_code
+
+ if samples_per_symbol < 2:
+ raise TypeError, "samples_per_symbol must be >= 2, is %r" % (samples_per_symbol,)
+
+ arity = pow(2,self.bits_per_symbol())
+
+ # Automatic gain control
+ self.agc = gr.agc2_cc(0.6e-1, 1e-3, 1, 1, 100)
+ #self.agc = gr.feedforward_agc_cc(16, 1.0)
+
+ self._costas_beta = 0.25 * self._costas_alpha * self._costas_alpha
+ # Allow a frequency swing of +/- half of the sample rate
+ fmin = -0.5
+ fmax = 0.5
+
+ self.clock_recov = gr.costas_loop_cc(self._costas_alpha,
+ self._costas_beta,
+ fmax, fmin, arity)
+
+ # symbol timing recovery with RRC data filter
+ nfilts = 32
+ ntaps = 11 * samples_per_symbol*nfilts
+ taps = gr.firdes.root_raised_cosine(nfilts, nfilts, 1.0/float(self._samples_per_symbol), self._excess_bw, ntaps)
+ self.time_recov = gr.pfb_clock_sync_ccf(self._samples_per_symbol,
+ self._timing_alpha,
+ taps, nfilts, nfilts/2, self._timing_max_dev)
+ self.time_recov.set_beta(self._timing_beta)
+
+ # Do differential decoding based on phase change of symbols
+ self.diffdec = gr.diff_phasor_cc()
+
+ # find closest constellation point
+ rot = 1
+ rotated_const = map(lambda pt: pt * rot, psk.constellation[arity])
+ self.slicer = gr.constellation_decoder_cb(rotated_const, range(arity))
+
+ if self._gray_code:
+ self.symbol_mapper = gr.map_bb(psk.gray_to_binary[arity])
+ else:
+ self.symbol_mapper = gr.map_bb(psk.ungray_to_binary[arity])
+
+ # unpack the k bit vector into a stream of bits
+ self.unpack = gr.unpack_k_bits_bb(self.bits_per_symbol())
+
+ if verbose:
+ self._print_verbage()
+
+ if log:
+ self._setup_logging()
+
+ # Connect
+ self.connect(self, self.agc,
+ self.clock_recov,
+ self.time_recov,
+ self.diffdec, self.slicer, self.symbol_mapper, self.unpack, self)
+
+ def samples_per_symbol(self):
+ return self._samples_per_symbol
+
+ def bits_per_symbol(self=None): # staticmethod that's also callable on an instance
+ return 1
+ bits_per_symbol = staticmethod(bits_per_symbol) # make it a static method. RTFM
+
+ def _print_verbage(self):
+ print "\nDemodulator:"
+ print "bits per symbol: %d" % self.bits_per_symbol()
+ print "Gray code: %s" % self._gray_code
+ print "RRC roll-off factor: %.2f" % self._excess_bw
+ print "Costas Loop alpha: %.2f" % self._costas_alpha
+ print "Costas Loop beta: %.2f" % self._costas_beta
+ print "Timing alpha gain: %.2f" % self._timing_alpha
+ print "Timing beta gain: %.2f" % self._timing_beta
+ print "Timing max dev: %.2f" % self._timing_max_dev
+
+ def _setup_logging(self):
+ print "Modulation logging turned on."
+ self.connect(self.pre_scaler,
+ gr.file_sink(gr.sizeof_gr_complex, "rx_prescaler.dat"))
+ self.connect(self.agc,
+ gr.file_sink(gr.sizeof_gr_complex, "rx_agc.dat"))
+ self.connect(self.rrc_filter,
+ gr.file_sink(gr.sizeof_gr_complex, "rx_rrc_filter.dat"))
+ self.connect(self.clock_recov,
+ gr.file_sink(gr.sizeof_gr_complex, "rx_clock_recov.dat"))
+ self.connect(self.time_recov,
+ gr.file_sink(gr.sizeof_gr_complex, "rx_time_recov.dat"))
+ self.connect(self.diffdec,
+ gr.file_sink(gr.sizeof_gr_complex, "rx_diffdec.dat"))
+ self.connect(self.slicer,
+ gr.file_sink(gr.sizeof_char, "rx_slicer.dat"))
+ self.connect(self.symbol_mapper,
+ gr.file_sink(gr.sizeof_char, "rx_symbol_mapper.dat"))
+ self.connect(self.unpack,
+ gr.file_sink(gr.sizeof_char, "rx_unpack.dat"))
+
+ def add_options(parser):
+ """
+ Adds DBPSK demodulation-specific options to the standard parser
+ """
+ parser.add_option("", "--excess-bw", type="float", default=_def_excess_bw,
+ help="set RRC excess bandwith factor [default=%default] (PSK)")
+ parser.add_option("", "--no-gray-code", dest="gray_code",
+ action="store_false", default=_def_gray_code,
+ help="disable gray coding on modulated bits (PSK)")
+ parser.add_option("", "--costas-alpha", type="float", default=None,
+ help="set Costas loop alpha value [default=%default] (PSK)")
+ parser.add_option("", "--gain-alpha", type="float", default=_def_timing_alpha,
+ help="set timing symbol sync loop gain alpha value [default=%default] (GMSK/PSK)")
+ parser.add_option("", "--gain-beta", type="float", default=_def_timing_beta,
+ help="set timing symbol sync loop gain beta value [default=%default] (GMSK/PSK)")
+ parser.add_option("", "--timing-max-dev", type="float", default=_def_timing_max_dev,
+ help="set timing symbol sync loop maximum deviation [default=%default] (GMSK/PSK)")
+ 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(
+ dbpsk2_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('dbpsk2', dbpsk2_mod)
+modulation_utils.add_type_1_demod('dbpsk2', dbpsk2_demod)
diff --git a/gnuradio-core/src/python/gnuradio/blks2impl/dqpsk.py b/gnuradio-core/src/python/gnuradio/blks2impl/dqpsk.py
index 8c15d2173..42d534168 100644
--- a/gnuradio-core/src/python/gnuradio/blks2impl/dqpsk.py
+++ b/gnuradio-core/src/python/gnuradio/blks2impl/dqpsk.py
@@ -1,5 +1,5 @@
#
-# Copyright 2005,2006,2007 Free Software Foundation, Inc.
+# Copyright 2005,2006,2007,2009 Free Software Foundation, Inc.
#
# This file is part of GNU Radio
#
@@ -255,8 +255,8 @@ class dqpsk_demod(gr.hier_block2):
self._mm_omega = self._samples_per_symbol
self._mm_gain_omega = .25 * self._mm_gain_mu * self._mm_gain_mu
self._costas_beta = 0.25 * self._costas_alpha * self._costas_alpha
- fmin = -0.025
- fmax = 0.025
+ fmin = -0.25
+ fmax = 0.25
self.receiver=gr.mpsk_receiver_cc(arity, pi/4.0,
self._costas_alpha, self._costas_beta,
@@ -264,7 +264,7 @@ class dqpsk_demod(gr.hier_block2):
self._mm_mu, self._mm_gain_mu,
self._mm_omega, self._mm_gain_omega,
self._mm_omega_relative_limit)
-
+
# Perform Differential decoding on the constellation
self.diffdec = gr.diff_phasor_cc()
diff --git a/gnuradio-core/src/python/gnuradio/blks2impl/dqpsk2.py b/gnuradio-core/src/python/gnuradio/blks2impl/dqpsk2.py
new file mode 100644
index 000000000..9704ac98c
--- /dev/null
+++ b/gnuradio-core/src/python/gnuradio/blks2impl/dqpsk2.py
@@ -0,0 +1,353 @@
+#
+# Copyright 2005,2006,2007,2009 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.
+#
+
+# See gnuradio-examples/python/digital for examples
+
+"""
+differential QPSK modulation and demodulation.
+"""
+
+from gnuradio import gr, gru, modulation_utils
+from math import pi, sqrt
+import psk
+import cmath
+from pprint import pprint
+
+# default values (used in __init__ and add_options)
+_def_samples_per_symbol = 2
+_def_excess_bw = 0.35
+_def_gray_code = True
+_def_verbose = False
+_def_log = False
+
+_def_costas_alpha = 0.01
+_def_timing_alpha = 0.100
+_def_timing_beta = 0.010
+_def_timing_max_dev = 1.5
+
+
+# /////////////////////////////////////////////////////////////////////////////
+# DQPSK modulator
+# /////////////////////////////////////////////////////////////////////////////
+
+class dqpsk2_mod(gr.hier_block2):
+
+ def __init__(self,
+ samples_per_symbol=_def_samples_per_symbol,
+ excess_bw=_def_excess_bw,
+ gray_code=_def_gray_code,
+ verbose=_def_verbose,
+ log=_def_log):
+ """
+ Hierarchical block for RRC-filtered QPSK modulation.
+
+ The input is a byte stream (unsigned char) and the
+ output is the complex modulated signal at baseband.
+
+ @param samples_per_symbol: samples per symbol >= 2
+ @type samples_per_symbol: integer
+ @param excess_bw: Root-raised cosine filter excess bandwidth
+ @type excess_bw: float
+ @param gray_code: Tell modulator to Gray code the bits
+ @type gray_code: bool
+ @param verbose: Print information about modulator?
+ @type verbose: bool
+ @param debug: Print modualtion data to files?
+ @type debug: bool
+ """
+
+ gr.hier_block2.__init__(self, "dqpsk2_mod",
+ gr.io_signature(1, 1, gr.sizeof_char), # Input signature
+ gr.io_signature(1, 1, gr.sizeof_gr_complex)) # Output signature
+
+ self._samples_per_symbol = samples_per_symbol
+ self._excess_bw = excess_bw
+ self._gray_code = gray_code
+
+ if not isinstance(samples_per_symbol, int) or samples_per_symbol < 2:
+ raise TypeError, ("sbp must be an integer >= 2, is %d" % samples_per_symbol)
+
+ ntaps = 11 * samples_per_symbol
+
+ arity = pow(2,self.bits_per_symbol())
+
+ # turn bytes into k-bit vectors
+ self.bytes2chunks = \
+ gr.packed_to_unpacked_bb(self.bits_per_symbol(), gr.GR_MSB_FIRST)
+
+ if self._gray_code:
+ self.symbol_mapper = gr.map_bb(psk.binary_to_gray[arity])
+ else:
+ self.symbol_mapper = gr.map_bb(psk.binary_to_ungray[arity])
+
+ self.diffenc = gr.diff_encoder_bb(arity)
+
+ rot = .707 + .707j
+ rotated_const = map(lambda pt: pt * rot, psk.constellation[arity])
+ self.chunks2symbols = gr.chunks_to_symbols_bc(rotated_const)
+
+ # pulse shaping filter
+ self.rrc_taps = gr.firdes.root_raised_cosine(
+ self._samples_per_symbol, # gain (sps since we're interpolating by sps)
+ self._samples_per_symbol, # sampling rate
+ 1.0, # symbol rate
+ self._excess_bw, # excess bandwidth (roll-off factor)
+ ntaps)
+
+ self.rrc_filter = gr.interp_fir_filter_ccf(self._samples_per_symbol, self.rrc_taps)
+
+ if verbose:
+ self._print_verbage()
+
+ if log:
+ self._setup_logging()
+
+ # Connect & Initialize base class
+ self.connect(self, self.bytes2chunks, self.symbol_mapper, self.diffenc,
+ self.chunks2symbols, self.rrc_filter, self)
+
+ def samples_per_symbol(self):
+ return self._samples_per_symbol
+
+ def bits_per_symbol(self=None): # staticmethod that's also callable on an instance
+ return 2
+ bits_per_symbol = staticmethod(bits_per_symbol) # make it a static method. RTFM
+
+ def _print_verbage(self):
+ print "\nModulator:"
+ print "bits per symbol: %d" % self.bits_per_symbol()
+ print "Gray code: %s" % self._gray_code
+ print "RRS roll-off factor: %f" % self._excess_bw
+
+ def _setup_logging(self):
+ print "Modulation logging turned on."
+ self.connect(self.bytes2chunks,
+ gr.file_sink(gr.sizeof_char, "tx_bytes2chunks.dat"))
+ self.connect(self.symbol_mapper,
+ gr.file_sink(gr.sizeof_char, "tx_graycoder.dat"))
+ self.connect(self.diffenc,
+ gr.file_sink(gr.sizeof_char, "tx_diffenc.dat"))
+ self.connect(self.chunks2symbols,
+ gr.file_sink(gr.sizeof_gr_complex, "tx_chunks2symbols.dat"))
+ self.connect(self.rrc_filter,
+ gr.file_sink(gr.sizeof_gr_complex, "tx_rrc_filter.dat"))
+
+ def add_options(parser):
+ """
+ Adds QPSK modulation-specific options to the standard parser
+ """
+ parser.add_option("", "--excess-bw", type="float", default=_def_excess_bw,
+ help="set RRC excess bandwith factor [default=%default] (PSK)")
+ parser.add_option("", "--no-gray-code", dest="gray_code",
+ action="store_false", default=_def_gray_code,
+ help="disable gray coding on modulated bits (PSK)")
+ 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(dqpsk2_mod.__init__,
+ ('self',), options)
+ extract_kwargs_from_options=staticmethod(extract_kwargs_from_options)
+
+
+# /////////////////////////////////////////////////////////////////////////////
+# DQPSK demodulator
+#
+# Differentially coherent detection of differentially encoded qpsk
+# /////////////////////////////////////////////////////////////////////////////
+
+class dqpsk2_demod(gr.hier_block2):
+
+ def __init__(self,
+ samples_per_symbol=_def_samples_per_symbol,
+ excess_bw=_def_excess_bw,
+ costas_alpha=_def_costas_alpha,
+ timing_alpha=_def_timing_alpha,
+ timing_max_dev=_def_timing_max_dev,
+ gray_code=_def_gray_code,
+ verbose=_def_verbose,
+ log=_def_log):
+ """
+ Hierarchical block for RRC-filtered DQPSK demodulation
+
+ The input is the complex modulated signal at baseband.
+ The output is a stream of bits packed 1 bit per byte (LSB)
+
+ @param samples_per_symbol: samples per symbol >= 2
+ @type samples_per_symbol: float
+ @param excess_bw: Root-raised cosine filter excess bandwidth
+ @type excess_bw: float
+ @param costas_alpha: loop filter gain
+ @type costas_alphas: float
+ @param timing_alpha: timing loop alpha gain
+ @type timing_alpha: float
+ @param timing_max: timing loop maximum rate deviations
+ @type timing_max: float
+ @param gray_code: Tell modulator to Gray code the bits
+ @type gray_code: bool
+ @param verbose: Print information about modulator?
+ @type verbose: bool
+ @param debug: Print modualtion data to files?
+ @type debug: bool
+ """
+
+ gr.hier_block2.__init__(self, "dqpsk2_demod",
+ gr.io_signature(1, 1, gr.sizeof_gr_complex), # Input signature
+ gr.io_signature(1, 1, gr.sizeof_char)) # Output signature
+
+ self._samples_per_symbol = samples_per_symbol
+ self._excess_bw = excess_bw
+ self._costas_alpha = costas_alpha
+ self._timing_alpha = timing_alpha
+ self._timing_beta = _def_timing_beta
+ self._timing_max_dev=timing_max_dev
+ self._gray_code = gray_code
+
+ if samples_per_symbol < 2:
+ raise TypeError, "sbp must be >= 2, is %d" % samples_per_symbol
+
+ arity = pow(2,self.bits_per_symbol())
+
+ # Automatic gain control
+ self.agc = gr.agc2_cc(0.6e-1, 1e-3, 1, 1, 100)
+ #self.agc = gr.feedforward_agc_cc(16, 2.0)
+
+ self._costas_beta = 0.25 * self._costas_alpha * self._costas_alpha
+ # Allow a frequency swing of +/- half of the sample rate
+ fmin = -0.5
+ fmax = 0.5
+
+ self.clock_recov = gr.costas_loop_cc(self._costas_alpha,
+ self._costas_beta,
+ fmax, fmin, arity)
+
+ # symbol timing recovery with RRC data filter
+ nfilts = 32
+ ntaps = 11 * samples_per_symbol*nfilts
+ taps = gr.firdes.root_raised_cosine(nfilts, nfilts, 1.0/float(self._samples_per_symbol), self._excess_bw, ntaps)
+ self.time_recov = gr.pfb_clock_sync_ccf(self._samples_per_symbol,
+ self._timing_alpha,
+ taps, nfilts, nfilts/2, self._timing_max_dev)
+ self.time_recov.set_beta(self._timing_beta)
+
+ # Perform Differential decoding on the constellation
+ self.diffdec = gr.diff_phasor_cc()
+
+ # find closest constellation point
+ rot = 1
+ rotated_const = map(lambda pt: pt * rot, psk.constellation[arity])
+ self.slicer = gr.constellation_decoder_cb(rotated_const, range(arity))
+
+ if self._gray_code:
+ self.symbol_mapper = gr.map_bb(psk.gray_to_binary[arity])
+ else:
+ self.symbol_mapper = gr.map_bb(psk.ungray_to_binary[arity])
+
+ # unpack the k bit vector into a stream of bits
+ self.unpack = gr.unpack_k_bits_bb(self.bits_per_symbol())
+
+ if verbose:
+ self._print_verbage()
+
+ if log:
+ self._setup_logging()
+
+ # Connect
+ self.connect(self, self.agc,
+ self.clock_recov,
+ self.time_recov,
+ self.diffdec, self.slicer, self.symbol_mapper, self.unpack, self)
+
+ def samples_per_symbol(self):
+ return self._samples_per_symbol
+
+ def bits_per_symbol(self=None): # staticmethod that's also callable on an instance
+ return 2
+ bits_per_symbol = staticmethod(bits_per_symbol) # make it a static method. RTFM
+
+ def _print_verbage(self):
+ print "\nDemodulator:"
+ print "bits per symbol: %d" % self.bits_per_symbol()
+ print "Gray code: %s" % self._gray_code
+ print "RRC roll-off factor: %.2f" % self._excess_bw
+ print "Costas Loop alpha: %.2e" % self._costas_alpha
+ print "Costas Loop beta: %.2e" % self._costas_beta
+ print "Timing alpha gain: %.2f" % self._timing_alpha
+ print "Timing beta gain: %.2f" % self._timing_beta
+ print "Timing max dev: %.2f" % self._timing_max_dev
+
+ def _setup_logging(self):
+ print "Modulation logging turned on."
+ self.connect(self.pre_scaler,
+ gr.file_sink(gr.sizeof_gr_complex, "rx_prescaler.dat"))
+ self.connect(self.agc,
+ gr.file_sink(gr.sizeof_gr_complex, "rx_agc.dat"))
+ self.connect(self.rrc_filter,
+ gr.file_sink(gr.sizeof_gr_complex, "rx_rrc_filter.dat"))
+ self.connect(self.clock_recov,
+ gr.file_sink(gr.sizeof_gr_complex, "rx_clock_recov.dat"))
+ self.connect(self.time_recov,
+ gr.file_sink(gr.sizeof_gr_complex, "rx_time_recov.dat"))
+ self.connect(self.diffdec,
+ gr.file_sink(gr.sizeof_gr_complex, "rx_diffdec.dat"))
+ self.connect(self.slicer,
+ gr.file_sink(gr.sizeof_char, "rx_slicer.dat"))
+ self.connect(self.symbol_mapper,
+ gr.file_sink(gr.sizeof_char, "rx_gray_decoder.dat"))
+ self.connect(self.unpack,
+ gr.file_sink(gr.sizeof_char, "rx_unpack.dat"))
+
+ def add_options(parser):
+ """
+ Adds modulation-specific options to the standard parser
+ """
+ parser.add_option("", "--excess-bw", type="float", default=_def_excess_bw,
+ help="set RRC excess bandwith factor [default=%default] (PSK)")
+ parser.add_option("", "--no-gray-code", dest="gray_code",
+ action="store_false", default=_def_gray_code,
+ help="disable gray coding on modulated bits (PSK)")
+ parser.add_option("", "--costas-alpha", type="float", default=_def_costas_alpha,
+ help="set Costas loop alpha value [default=%default] (PSK)")
+ parser.add_option("", "--gain-alpha", type="float", default=_def_timing_alpha,
+ help="set timing symbol sync loop gain alpha value [default=%default] (GMSK/PSK)")
+ parser.add_option("", "--gain-beta", type="float", default=_def_timing_beta,
+ help="set timing symbol sync loop gain beta value [default=%default] (GMSK/PSK)")
+ parser.add_option("", "--timing-max-dev", type="float", default=_def_timing_max_dev,
+ help="set timing symbol sync loop maximum deviation [default=%default] (GMSK/PSK)")
+ 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(
+ dqpsk2_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('dqpsk2', dqpsk2_mod)
+modulation_utils.add_type_1_demod('dqpsk2', dqpsk2_demod)
diff --git a/gnuradio-core/src/python/gnuradio/gr/Makefile.am b/gnuradio-core/src/python/gnuradio/gr/Makefile.am
index 41ef52240..3aff89ee7 100644
--- a/gnuradio-core/src/python/gnuradio/gr/Makefile.am
+++ b/gnuradio-core/src/python/gnuradio/gr/Makefile.am
@@ -54,6 +54,7 @@ noinst_PYTHON = \
qa_cma_equalizer.py \
qa_complex_to_xxx.py \
qa_constellation_decoder_cb.py \
+ qa_copy.py \
qa_correlate_access_code.py \
qa_delay.py \
qa_diff_encoder.py \
diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_copy.py b/gnuradio-core/src/python/gnuradio/gr/qa_copy.py
new file mode 100755
index 000000000..7f9f72a7b
--- /dev/null
+++ b/gnuradio-core/src/python/gnuradio/gr/qa_copy.py
@@ -0,0 +1,58 @@
+#!/usr/bin/env python
+#
+# Copyright 2009 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
+
+class test_copy(gr_unittest.TestCase):
+
+ def setUp (self):
+ self.tb = gr.top_block ()
+
+ def tearDown (self):
+ self.tb = None
+
+ def test_copy (self):
+ src_data = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
+ expected_result = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
+ src = gr.vector_source_b(src_data)
+ op = gr.copy(gr.sizeof_char)
+ dst = gr.vector_sink_b()
+ self.tb.connect(src, op, dst)
+ self.tb.run()
+ dst_data = dst.data()
+ self.assertEqual(expected_result, dst_data)
+
+ def test_copy_drop (self):
+ src_data = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
+ expected_result = ()
+ src = gr.vector_source_b(src_data)
+ op = gr.copy(gr.sizeof_char)
+ op.set_enabled(False)
+ dst = gr.vector_sink_b()
+ self.tb.connect(src, op, dst)
+ self.tb.run()
+ dst_data = dst.data()
+ self.assertEqual(expected_result, dst_data)
+
+
+if __name__ == '__main__':
+ gr_unittest.main ()