diff options
author | Tom Rondeau | 2010-03-14 18:39:03 -0400 |
---|---|---|
committer | Tom Rondeau | 2010-03-14 18:39:03 -0400 |
commit | 1bec5c5eaef7ff2e98f37ff60d6b61c1310e582d (patch) | |
tree | 516c0235982d37bdcd6c9634c61dc5f80aaa1542 | |
parent | 18ecca1b9e57f047130a124bd8cc90cbe34feff0 (diff) | |
parent | 6de98961cf9b93c486c8c6825789de94dc79afae (diff) | |
download | gnuradio-1bec5c5eaef7ff2e98f37ff60d6b61c1310e582d.tar.gz gnuradio-1bec5c5eaef7ff2e98f37ff60d6b61c1310e582d.tar.bz2 gnuradio-1bec5c5eaef7ff2e98f37ff60d6b61c1310e582d.zip |
Merge branch 'digital'
23 files changed, 1070 insertions, 354 deletions
diff --git a/gnuradio-core/src/lib/general/gr_fll_band_edge_cc.cc b/gnuradio-core/src/lib/general/gr_fll_band_edge_cc.cc index 030e45ddf..7f2c468b7 100644 --- a/gnuradio-core/src/lib/general/gr_fll_band_edge_cc.cc +++ b/gnuradio-core/src/lib/general/gr_fll_band_edge_cc.cc @@ -53,7 +53,7 @@ gr_fll_band_edge_cc_sptr gr_make_fll_band_edge_cc (float samps_per_sym, float ro } -static int ios[] = {sizeof(gr_complex), sizeof(float), sizeof(float), sizeof(float)}; +static int ios[] = {sizeof(gr_complex), sizeof(float), sizeof(float), sizeof(gr_complex)}; static std::vector<int> iosig(ios, ios+sizeof(ios)/sizeof(int)); gr_fll_band_edge_cc::gr_fll_band_edge_cc (float samps_per_sym, float rolloff, int filter_size, float alpha, float beta) @@ -83,10 +83,11 @@ gr_fll_band_edge_cc::~gr_fll_band_edge_cc () void gr_fll_band_edge_cc::set_alpha(float alpha) { - float eta = sqrt(2.0)/2.0; - float theta = alpha; - d_alpha = (4*eta*theta) / (1.0 + 2.0*eta*theta + theta*theta); - d_beta = (4*theta*theta) / (1.0 + 2.0*eta*theta + theta*theta); + //float eta = sqrt(2.0)/2.0; + //float theta = alpha; + //d_alpha = (4*eta*theta) / (1.0 + 2.0*eta*theta + theta*theta); + //d_beta = (4*theta*theta) / (1.0 + 2.0*eta*theta + theta*theta); + d_alpha = alpha; } void @@ -160,11 +161,12 @@ gr_fll_band_edge_cc::work (int noutput_items, const gr_complex *in = (const gr_complex *) input_items[0]; gr_complex *out = (gr_complex *) output_items[0]; - float *frq, *phs, *err; + float *frq, *phs; + gr_complex *err; if(output_items.size() > 2) { frq = (float *) output_items[1]; phs = (float *) output_items[2]; - err = (float *) output_items[3]; + err = (gr_complex *) output_items[3]; } if (d_updated) { @@ -174,16 +176,17 @@ gr_fll_band_edge_cc::work (int noutput_items, int i; gr_complex nco_out; - float out_upper, out_lower; + gr_complex out_upper, out_lower; float error; + float avg_k = 0.1; for(i = 0; i < noutput_items; i++) { nco_out = gr_expj(d_phase); out[i] = in[i] * nco_out; - out_upper = norm(d_filter_upper->filter(&out[i])); - out_lower = norm(d_filter_lower->filter(&out[i])); - error = out_lower - out_upper; - d_error = 0.01*error + 0.99*d_error; // average error + out_upper = (d_filter_upper->filter(&out[i])); + out_lower = (d_filter_lower->filter(&out[i])); + error = -real((out_upper + out_lower) * conj(out_upper - out_lower)); + d_error = avg_k*error + avg_k*d_error; // average error d_freq = d_freq + d_beta * d_error; d_phase = d_phase + d_freq + d_alpha * d_error; diff --git a/gnuradio-core/src/lib/general/gr_fll_band_edge_cc.h b/gnuradio-core/src/lib/general/gr_fll_band_edge_cc.h index 09baf7fde..178e18f3e 100644 --- a/gnuradio-core/src/lib/general/gr_fll_band_edge_cc.h +++ b/gnuradio-core/src/lib/general/gr_fll_band_edge_cc.h @@ -45,8 +45,12 @@ class gri_fft_complex; * (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 calculating the power in both the upper and lower bands and comparing them. The - * difference in power between the filters is proportional to the frequency offset. + * + * 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 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 diff --git a/gnuradio-core/src/python/gnuradio/Makefile.am b/gnuradio-core/src/python/gnuradio/Makefile.am index dcc0017b3..f0516f2fd 100644 --- a/gnuradio-core/src/python/gnuradio/Makefile.am +++ b/gnuradio-core/src/python/gnuradio/Makefile.am @@ -30,6 +30,7 @@ grpython_PYTHON = \ eng_notation.py \ eng_option.py \ modulation_utils.py \ + modulation_utils2.py \ ofdm_packet_utils.py \ packet_utils.py \ gr_unittest.py \ diff --git a/gnuradio-core/src/python/gnuradio/blks2impl/Makefile.am b/gnuradio-core/src/python/gnuradio/blks2impl/Makefile.am index 68d683623..7b24fb69d 100644 --- a/gnuradio-core/src/python/gnuradio/blks2impl/Makefile.am +++ b/gnuradio-core/src/python/gnuradio/blks2impl/Makefile.am @@ -1,5 +1,5 @@ # -# Copyright 2005,2007,2009 Free Software Foundation, Inc. +# Copyright 2005,2007,2009,2010 Free Software Foundation, Inc. # # This file is part of GNU Radio # diff --git a/gnuradio-core/src/python/gnuradio/blks2impl/dbpsk.py b/gnuradio-core/src/python/gnuradio/blks2impl/dbpsk.py index 860015c3f..55e4890f3 100644 --- a/gnuradio-core/src/python/gnuradio/blks2impl/dbpsk.py +++ b/gnuradio-core/src/python/gnuradio/blks2impl/dbpsk.py @@ -233,10 +233,10 @@ class dbpsk_demod(gr.hier_block2): arity = pow(2,self.bits_per_symbol()) # Automatic gain control - scale = (1.0/16384.0) - self.pre_scaler = gr.multiply_const_cc(scale) # scale the signal from full-range to +-1 - #self.agc = gr.agc2_cc(0.6e-1, 1e-3, 1, 1, 100) - self.agc = gr.feedforward_agc_cc(16, 2.0) + #scale = (1.0/16384.0) + #self.pre_scaler = gr.multiply_const_cc(scale) # scale the signal from full-range to +-1 + self.agc = gr.agc2_cc(0.6e-1, 1e-3, 1, 1, 100) + #self.agc = gr.feedforward_agc_cc(16, 2.0) # RRC data filter ntaps = 11 * samples_per_symbol @@ -288,7 +288,7 @@ class dbpsk_demod(gr.hier_block2): self._setup_logging() # Connect and Initialize base class - self.connect(self, self.pre_scaler, self.agc, self.rrc_filter, self.receiver, + self.connect(self, self.agc, self.rrc_filter, self.receiver, self.diffdec, self.slicer, self.symbol_mapper, self.unpack, self) def samples_per_symbol(self): diff --git a/gnuradio-core/src/python/gnuradio/blks2impl/dbpsk2.py b/gnuradio-core/src/python/gnuradio/blks2impl/dbpsk2.py index e9fb3df89..d7bcf5390 100644 --- a/gnuradio-core/src/python/gnuradio/blks2impl/dbpsk2.py +++ b/gnuradio-core/src/python/gnuradio/blks2impl/dbpsk2.py @@ -1,5 +1,5 @@ # -# Copyright 2005,2006,2007 Free Software Foundation, Inc. +# Copyright 2009,2010 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -25,7 +25,7 @@ differential BPSK modulation and demodulation. """ -from gnuradio import gr, gru, modulation_utils +from gnuradio import gr, gru, modulation_utils2 from math import pi, sqrt, ceil import psk import cmath @@ -38,8 +38,8 @@ _def_gray_code = True _def_verbose = False _def_log = False -_def_freq_alpha = 4e-3 -_def_costas_alpha = 0.1 +_def_freq_alpha = 0.010 +_def_phase_alpha = 0.1 _def_timing_alpha = 0.100 _def_timing_beta = 0.010 _def_timing_max_dev = 1.5 @@ -83,7 +83,7 @@ class dbpsk2_mod(gr.hier_block2): self._excess_bw = excess_bw self._gray_code = gray_code - if not isinstance(self._samples_per_symbol, int) or self._samples_per_symbol < 2: + if self._samples_per_symbol < 2: raise TypeError, ("sbp must be an integer >= 2, is %d" % self._samples_per_symbol) arity = pow(2,self.bits_per_symbol()) @@ -103,7 +103,7 @@ class dbpsk2_mod(gr.hier_block2): # pulse shaping filter nfilts = 32 - ntaps = nfilts * 11 * self._samples_per_symbol # make nfilts filters of ntaps each + ntaps = nfilts * 11 * int(self._samples_per_symbol) # make nfilts filters of ntaps each self.rrc_taps = gr.firdes.root_raised_cosine( nfilts, # gain nfilts, # sampling rate based on 32 filters in resampler @@ -145,7 +145,7 @@ class dbpsk2_mod(gr.hier_block2): """ Given command line options, create dictionary suitable for passing to __init__ """ - return modulation_utils.extract_kwargs_from_options(dbpsk2_mod.__init__, + return modulation_utils2.extract_kwargs_from_options(dbpsk2_mod.__init__, ('self',), options) extract_kwargs_from_options=staticmethod(extract_kwargs_from_options) @@ -182,7 +182,7 @@ class dbpsk2_demod(gr.hier_block2): samples_per_symbol=_def_samples_per_symbol, excess_bw=_def_excess_bw, freq_alpha=_def_freq_alpha, - costas_alpha=_def_costas_alpha, + phase_alpha=_def_phase_alpha, timing_alpha=_def_timing_alpha, timing_max_dev=_def_timing_max_dev, gray_code=_def_gray_code, @@ -201,8 +201,8 @@ class dbpsk2_demod(gr.hier_block2): @type excess_bw: float @param freq_alpha: loop filter gain for frequency recovery @type freq_alpha: float - @param costas_alpha: loop filter gain for phase/fine frequency recovery - @type costas_alpha: float + @param phase_alpha: loop filter gain for phase/fine frequency recovery + @type phase_alpha: float @param timing_alpha: loop alpha gain for timing recovery @type timing_alpha: float @param timing_max: timing loop maximum rate deviations @@ -226,8 +226,8 @@ class dbpsk2_demod(gr.hier_block2): self._samples_per_symbol = samples_per_symbol self._excess_bw = excess_bw self._freq_alpha = freq_alpha - self._freq_beta = 0.25*self._freq_alpha**2 - self._costas_alpha = costas_alpha + self._freq_beta = 0.10*self._freq_alpha + self._phase_alpha = phase_alpha self._timing_alpha = timing_alpha self._timing_beta = _def_timing_beta self._timing_max_dev=timing_max_dev @@ -259,13 +259,13 @@ class dbpsk2_demod(gr.hier_block2): self.time_recov.set_beta(self._timing_beta) # Perform phase / fine frequency correction - self._costas_beta = 0.25 * self._costas_alpha * self._costas_alpha + self._phase_beta = 0.25 * self._phase_alpha * self._phase_alpha # Allow a frequency swing of +/- half of the sample rate fmin = -0.5 fmax = 0.5 - self.phase_recov = gr.costas_loop_cc(self._costas_alpha, - self._costas_beta, + self.phase_recov = gr.costas_loop_cc(self._phase_alpha, + self._phase_beta, fmax, fmin, arity) # Do differential decoding based on phase change of symbols @@ -308,29 +308,27 @@ class dbpsk2_demod(gr.hier_block2): 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 "FLL gain: %.2f" % self._freq_alpha - 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 "FLL gain: %.2e" % self._freq_alpha + print "Timing alpha gain: %.2e" % self._timing_alpha + print "Timing beta gain: %.2e" % self._timing_beta print "Timing max dev: %.2f" % self._timing_max_dev + print "Phase track alpha: %.2e" % self._phase_alpha + print "Phase track beta: %.2e" % self._phase_beta 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.freq_recov, + gr.file_sink(gr.sizeof_gr_complex, "rx_freq_recov.dat")) self.connect(self.time_recov, gr.file_sink(gr.sizeof_gr_complex, "rx_time_recov.dat")) + self.connect(self.phase_recov, + gr.file_sink(gr.sizeof_gr_complex, "rx_phase_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")) + 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, @@ -347,11 +345,11 @@ class dbpsk2_demod(gr.hier_block2): help="disable gray coding on modulated bits (PSK)") parser.add_option("", "--freq-alpha", type="float", default=_def_freq_alpha, help="set frequency lock loop alpha gain value [default=%default] (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, + parser.add_option("", "--phase-alpha", type="float", default=_def_phase_alpha, + help="set phase tracking loop alpha value [default=%default] (PSK)") + parser.add_option("", "--timing-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, + parser.add_option("", "--timing-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)") @@ -361,11 +359,11 @@ class dbpsk2_demod(gr.hier_block2): """ Given command line options, create dictionary suitable for passing to __init__ """ - return modulation_utils.extract_kwargs_from_options( + return modulation_utils2.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) +modulation_utils2.add_type_1_mod('dbpsk2', dbpsk2_mod) +modulation_utils2.add_type_1_demod('dbpsk2', dbpsk2_demod) diff --git a/gnuradio-core/src/python/gnuradio/blks2impl/dqpsk2.py b/gnuradio-core/src/python/gnuradio/blks2impl/dqpsk2.py index 9fae6acca..e1e627707 100644 --- a/gnuradio-core/src/python/gnuradio/blks2impl/dqpsk2.py +++ b/gnuradio-core/src/python/gnuradio/blks2impl/dqpsk2.py @@ -1,5 +1,5 @@ # -# Copyright 2005,2006,2007,2009 Free Software Foundation, Inc. +# Copyright 2009,2010 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -25,7 +25,7 @@ differential QPSK modulation and demodulation. """ -from gnuradio import gr, gru, modulation_utils +from gnuradio import gr, gru, modulation_utils2 from math import pi, sqrt import psk import cmath @@ -38,8 +38,8 @@ _def_gray_code = True _def_verbose = False _def_log = False -_def_freq_alpha = 4e-3 -_def_costas_alpha = 0.01 +_def_freq_alpha = 0.010 +_def_phase_alpha = 0.01 _def_timing_alpha = 0.100 _def_timing_beta = 0.010 _def_timing_max_dev = 1.5 @@ -83,8 +83,8 @@ class dqpsk2_mod(gr.hier_block2): 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) + if samples_per_symbol < 2: + raise TypeError, ("sbp must be >= 2, is %f" % samples_per_symbol) ntaps = 11 * samples_per_symbol @@ -107,7 +107,7 @@ class dqpsk2_mod(gr.hier_block2): # pulse shaping filter nfilts = 32 - ntaps = nfilts * 11 * self._samples_per_symbol # make nfilts filters of ntaps each + ntaps = 11 * int(nfilts * self._samples_per_symbol) # make nfilts filters of ntaps each self.rrc_taps = gr.firdes.root_raised_cosine( nfilts, # gain nfilts, # sampling rate based on 32 filters in resampler @@ -168,7 +168,7 @@ class dqpsk2_mod(gr.hier_block2): """ Given command line options, create dictionary suitable for passing to __init__ """ - return modulation_utils.extract_kwargs_from_options(dqpsk2_mod.__init__, + return modulation_utils2.extract_kwargs_from_options(dqpsk2_mod.__init__, ('self',), options) extract_kwargs_from_options=staticmethod(extract_kwargs_from_options) @@ -185,7 +185,7 @@ class dqpsk2_demod(gr.hier_block2): samples_per_symbol=_def_samples_per_symbol, excess_bw=_def_excess_bw, freq_alpha=_def_freq_alpha, - costas_alpha=_def_costas_alpha, + phase_alpha=_def_phase_alpha, timing_alpha=_def_timing_alpha, timing_max_dev=_def_timing_max_dev, gray_code=_def_gray_code, @@ -204,8 +204,8 @@ class dqpsk2_demod(gr.hier_block2): @type excess_bw: float @param freq_alpha: loop filter gain for frequency recovery @type freq_alpha: float - @param costas_alpha: loop filter gain - @type costas_alphas: float + @param phase_alpha: loop filter gain + @type phase_alphas: float @param timing_alpha: timing loop alpha gain @type timing_alpha: float @param timing_max: timing loop maximum rate deviations @@ -230,7 +230,7 @@ class dqpsk2_demod(gr.hier_block2): self._excess_bw = excess_bw self._freq_alpha = freq_alpha self._freq_beta = 0.25*self._freq_alpha**2 - self._costas_alpha = costas_alpha + self._phase_alpha = phase_alpha self._timing_alpha = timing_alpha self._timing_beta = _def_timing_beta self._timing_max_dev=timing_max_dev @@ -264,13 +264,13 @@ class dqpsk2_demod(gr.hier_block2): # Perform phase / fine frequency correction - self._costas_beta = 0.25 * self._costas_alpha * self._costas_alpha + self._phase_beta = 0.25 * self._phase_alpha * self._phase_alpha # Allow a frequency swing of +/- half of the sample rate fmin = -0.5 fmax = 0.5 - self.phase_recov = gr.costas_loop_cc(self._costas_alpha, - self._costas_beta, + self.phase_recov = gr.costas_loop_cc(self._phase_alpha, + self._phase_beta, fmax, fmin, arity) @@ -315,24 +315,22 @@ class dqpsk2_demod(gr.hier_block2): print "Gray code: %s" % self._gray_code print "RRC roll-off factor: %.2f" % self._excess_bw print "FLL gain: %.2f" % self._freq_alpha - 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 + print "Phase track alpha: %.2e" % self._phase_alpha + print "Phase track beta: %.2e" % self._phase_beta 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.freq_recov, + gr.file_sink(gr.sizeof_gr_complex, "rx_freq_recov.dat")) self.connect(self.time_recov, gr.file_sink(gr.sizeof_gr_complex, "rx_time_recov.dat")) + self.connect(self.phase_recov, + gr.file_sink(gr.sizeof_gr_complex, "rx_phase_recov.dat")) self.connect(self.diffdec, gr.file_sink(gr.sizeof_gr_complex, "rx_diffdec.dat")) self.connect(self.slicer, @@ -344,7 +342,7 @@ class dqpsk2_demod(gr.hier_block2): def add_options(parser): """ - Adds modulation-specific options to the standard parser + Adds DQPSK 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)") @@ -353,11 +351,11 @@ class dqpsk2_demod(gr.hier_block2): help="disable gray coding on modulated bits (PSK)") parser.add_option("", "--freq-alpha", type="float", default=_def_freq_alpha, help="set frequency lock loop alpha gain value [default=%default] (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, + parser.add_option("", "--phase-alpha", type="float", default=_def_phase_alpha, + help="set phase tracking loop alpha value [default=%default] (PSK)") + parser.add_option("", "--timing-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, + parser.add_option("", "--timing-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)") @@ -367,7 +365,7 @@ class dqpsk2_demod(gr.hier_block2): """ Given command line options, create dictionary suitable for passing to __init__ """ - return modulation_utils.extract_kwargs_from_options( + return modulation_utils2.extract_kwargs_from_options( dqpsk2_demod.__init__, ('self',), options) extract_kwargs_from_options=staticmethod(extract_kwargs_from_options) @@ -375,5 +373,5 @@ class dqpsk2_demod(gr.hier_block2): # # 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) +modulation_utils2.add_type_1_mod('dqpsk2', dqpsk2_mod) +modulation_utils2.add_type_1_demod('dqpsk2', dqpsk2_demod) diff --git a/gnuradio-core/src/python/gnuradio/modulation_utils2.py b/gnuradio-core/src/python/gnuradio/modulation_utils2.py new file mode 100644 index 000000000..c5dba3e79 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/modulation_utils2.py @@ -0,0 +1,81 @@ +# +# 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 this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# + +""" +Miscellaneous utilities for managing mods and demods, as well as other items +useful in dealing with generalized handling of different modulations and demods. +""" + +import inspect + + +# Type 1 modulators accept a stream of bytes on their input and produce complex baseband output +_type_1_modulators = {} + +def type_1_mods(): + return _type_1_modulators + +def add_type_1_mod(name, mod_class): + _type_1_modulators[name] = mod_class + + +# Type 1 demodulators accept complex baseband input and produce a stream of bits, packed +# 1 bit / byte as their output. Their output is completely unambiguous. There is no need +# to resolve phase or polarity ambiguities. +_type_1_demodulators = {} + +def type_1_demods(): + return _type_1_demodulators + +def add_type_1_demod(name, demod_class): + _type_1_demodulators[name] = demod_class + + +def extract_kwargs_from_options(function, excluded_args, options): + """ + Given a function, a list of excluded arguments and the result of + parsing command line options, create a dictionary of key word + arguments suitable for passing to the function. The dictionary + will be populated with key/value pairs where the keys are those + that are common to the function's argument list (minus the + excluded_args) and the attributes in options. The values are the + corresponding values from options unless that value is None. + In that case, the corresponding dictionary entry is not populated. + + (This allows different modulations that have the same parameter + names, but different default values to coexist. The downside is + that --help in the option parser will list the default as None, + but in that case the default provided in the __init__ argument + list will be used since there is no kwargs entry.) + + @param function: the function whose parameter list will be examined + @param excluded_args: function arguments that are NOT to be added to the dictionary + @type excluded_args: sequence of strings + @param options: result of command argument parsing + @type options: optparse.Values + """ + # Try this in C++ ;) + args, varargs, varkw, defaults = inspect.getargspec(function) + d = {} + for kw in [a for a in args if a not in excluded_args]: + if hasattr(options, kw): + if getattr(options, kw) is not None: + d[kw] = getattr(options, kw) + return d diff --git a/gnuradio-core/src/python/gnuradio/packet_utils.py b/gnuradio-core/src/python/gnuradio/packet_utils.py index 1417c17fa..e36b05413 100644 --- a/gnuradio-core/src/python/gnuradio/packet_utils.py +++ b/gnuradio-core/src/python/gnuradio/packet_utils.py @@ -143,7 +143,7 @@ def make_packet(payload, samples_per_symbol, bits_per_symbol, (payload_with_crc), '\x55')) if pad_for_usrp: - pkt = pkt + (_npadding_bytes(len(pkt), samples_per_symbol, bits_per_symbol) * '\x55') + pkt = pkt + (_npadding_bytes(len(pkt), int(samples_per_symbol), bits_per_symbol) * '\x55') #print "make_packet: len(pkt) =", len(pkt) return pkt diff --git a/gnuradio-examples/grc/demod/digital_freq_lock.grc b/gnuradio-examples/grc/demod/digital_freq_lock.grc index 37ee8123e..36037febb 100644 --- a/gnuradio-examples/grc/demod/digital_freq_lock.grc +++ b/gnuradio-examples/grc/demod/digital_freq_lock.grc @@ -1,6 +1,6 @@ <?xml version='1.0' encoding='ASCII'?> <flow_graph> - <timestamp>Fri Jan 29 18:10:00 2010</timestamp> + <timestamp>Sat Mar 6 17:17:12 2010</timestamp> <block> <key>options</key> <param> @@ -980,54 +980,50 @@ </param> </block> <block> - <key>variable_slider</key> + <key>root_raised_cosine_filter</key> <param> <key>id</key> - <value>alpha</value> + <value>root_raised_cosine_filter_0</value> </param> <param> <key>_enabled</key> <value>True</value> </param> <param> - <key>label</key> - <value>Freq Alpha</value> - </param> - <param> - <key>value</key> - <value>0</value> + <key>type</key> + <value>interp_fir_filter_ccf</value> </param> <param> - <key>min</key> - <value>0</value> + <key>decim</key> + <value>1</value> </param> <param> - <key>max</key> - <value>0.001</value> + <key>interp</key> + <value>spb_gen</value> </param> <param> - <key>num_steps</key> - <value>1000</value> + <key>gain</key> + <value>2*spb_gen</value> </param> <param> - <key>style</key> - <value>wx.SL_HORIZONTAL</value> + <key>samp_rate</key> + <value>1.0</value> </param> <param> - <key>converver</key> - <value>float_converter</value> + <key>sym_rate</key> + <value>1./spb_gen</value> </param> <param> - <key>grid_pos</key> - <value></value> + <key>alpha</key> + <value>rolloff</value> </param> <param> - <key>notebook</key> - <value></value> + <key>ntaps</key> + <value>44</value> </param> <param> <key>_coordinate</key> - <value>(552, 4)</value> + <value>(978, 157)</value> </param> <param> <key>_rotation</key> @@ -1035,105 +1031,81 @@ </param> </block> <block> - <key>variable_slider</key> + <key>gr_fll_band_edge_cc</key> <param> <key>id</key> - <value>beta</value> + <value>gr_fll_band_edge_cc_0</value> </param> <param> <key>_enabled</key> <value>True</value> </param> <param> - <key>label</key> - <value>Freq Beta</value> - </param> - <param> - <key>value</key> - <value>0</value> - </param> - <param> - <key>min</key> - <value>0.0</value> - </param> - <param> - <key>max</key> - <value>0.0001</value> + <key>type</key> + <value>cc</value> </param> <param> - <key>num_steps</key> - <value>1000</value> + <key>samps_per_sym</key> + <value>spb_gen</value> </param> <param> - <key>style</key> - <value>wx.SL_HORIZONTAL</value> + <key>rolloff</key> + <value>rolloff</value> </param> <param> - <key>converver</key> - <value>float_converter</value> + <key>filter_size</key> + <value>44</value> </param> <param> - <key>grid_pos</key> - <value></value> + <key>alpha</key> + <value>alpha</value> </param> <param> - <key>notebook</key> - <value></value> + <key>beta</key> + <value>beta</value> </param> <param> <key>_coordinate</key> - <value>(668, 5)</value> + <value>(874, 664)</value> </param> <param> <key>_rotation</key> - <value>180</value> + <value>0</value> </param> </block> <block> - <key>root_raised_cosine_filter</key> + <key>gr_channel_model</key> <param> <key>id</key> - <value>root_raised_cosine_filter_0</value> + <value>gr_channel_model_0</value> </param> <param> <key>_enabled</key> <value>True</value> </param> <param> - <key>type</key> - <value>interp_fir_filter_ccf</value> - </param> - <param> - <key>decim</key> - <value>1</value> - </param> - <param> - <key>interp</key> - <value>spb_gen</value> + <key>noise_voltage</key> + <value>noise_amp</value> </param> <param> - <key>gain</key> - <value>2*spb_gen</value> + <key>freq_offset</key> + <value>freq_offset</value> </param> <param> - <key>samp_rate</key> + <key>epsilon</key> <value>1.0</value> </param> <param> - <key>sym_rate</key> - <value>1./spb_gen</value> - </param> - <param> - <key>alpha</key> - <value>rolloff</value> + <key>taps</key> + <value>1.0</value> </param> <param> - <key>ntaps</key> - <value>44</value> + <key>seed</key> + <value>42</value> </param> <param> <key>_coordinate</key> - <value>(978, 157)</value> + <value>(618, 376)</value> </param> <param> <key>_rotation</key> @@ -1141,81 +1113,109 @@ </param> </block> <block> - <key>gr_fll_band_edge_cc</key> + <key>variable_slider</key> <param> <key>id</key> - <value>gr_fll_band_edge_cc_0</value> + <value>beta</value> </param> <param> <key>_enabled</key> <value>True</value> </param> <param> - <key>type</key> - <value>cc</value> + <key>label</key> + <value>Freq Beta</value> </param> <param> - <key>samps_per_sym</key> - <value>spb_gen</value> + <key>value</key> + <value>0</value> </param> <param> - <key>rolloff</key> - <value>rolloff</value> + <key>min</key> + <value>0.0</value> </param> <param> - <key>filter_size</key> - <value>44</value> + <key>max</key> + <value>0.01</value> </param> <param> - <key>alpha</key> - <value>alpha</value> + <key>num_steps</key> + <value>1000</value> </param> <param> - <key>beta</key> - <value>beta</value> + <key>style</key> + <value>wx.SL_HORIZONTAL</value> + </param> + <param> + <key>converver</key> + <value>float_converter</value> + </param> + <param> + <key>grid_pos</key> + <value></value> + </param> + <param> + <key>notebook</key> + <value></value> </param> <param> <key>_coordinate</key> - <value>(874, 664)</value> + <value>(668, 5)</value> </param> <param> <key>_rotation</key> - <value>0</value> + <value>180</value> </param> </block> <block> - <key>gr_channel_model</key> + <key>variable_slider</key> <param> <key>id</key> - <value>gr_channel_model_0</value> + <value>alpha</value> </param> <param> <key>_enabled</key> <value>True</value> </param> <param> - <key>noise_voltage</key> - <value>noise_amp</value> + <key>label</key> + <value>Freq Alpha</value> </param> <param> - <key>freq_offset</key> - <value>freq_offset</value> + <key>value</key> + <value>0</value> </param> <param> - <key>epsilon</key> - <value>1.0</value> + <key>min</key> + <value>0</value> </param> <param> - <key>taps</key> - <value>1.0</value> + <key>max</key> + <value>0.1</value> </param> <param> - <key>seed</key> - <value>42</value> + <key>num_steps</key> + <value>1000</value> + </param> + <param> + <key>style</key> + <value>wx.SL_HORIZONTAL</value> + </param> + <param> + <key>converver</key> + <value>float_converter</value> + </param> + <param> + <key>grid_pos</key> + <value></value> + </param> + <param> + <key>notebook</key> + <value></value> </param> <param> <key>_coordinate</key> - <value>(618, 376)</value> + <value>(552, 4)</value> </param> <param> <key>_rotation</key> diff --git a/gnuradio-examples/grc/demod/pam_sync.grc b/gnuradio-examples/grc/demod/pam_sync.grc index 80a7aef0c..8571995a5 100644 --- a/gnuradio-examples/grc/demod/pam_sync.grc +++ b/gnuradio-examples/grc/demod/pam_sync.grc @@ -1,6 +1,6 @@ <?xml version='1.0' encoding='ASCII'?> <flow_graph> - <timestamp>Mon Feb 1 18:58:32 2010</timestamp> + <timestamp>Sat Mar 6 17:17:22 2010</timestamp> <block> <key>options</key> <param> @@ -713,116 +713,6 @@ <key>variable_slider</key> <param> <key>id</key> - <value>freq_beta</value> - </param> - <param> - <key>_enabled</key> - <value>True</value> - </param> - <param> - <key>label</key> - <value>Freq Beta</value> - </param> - <param> - <key>value</key> - <value>0</value> - </param> - <param> - <key>min</key> - <value>0.0</value> - </param> - <param> - <key>max</key> - <value>0.0001</value> - </param> - <param> - <key>num_steps</key> - <value>1000</value> - </param> - <param> - <key>style</key> - <value>wx.SL_HORIZONTAL</value> - </param> - <param> - <key>converver</key> - <value>float_converter</value> - </param> - <param> - <key>grid_pos</key> - <value></value> - </param> - <param> - <key>notebook</key> - <value></value> - </param> - <param> - <key>_coordinate</key> - <value>(836, 9)</value> - </param> - <param> - <key>_rotation</key> - <value>180</value> - </param> - </block> - <block> - <key>variable_slider</key> - <param> - <key>id</key> - <value>freq_alpha</value> - </param> - <param> - <key>_enabled</key> - <value>True</value> - </param> - <param> - <key>label</key> - <value>Freq Alpha</value> - </param> - <param> - <key>value</key> - <value>0</value> - </param> - <param> - <key>min</key> - <value>0</value> - </param> - <param> - <key>max</key> - <value>0.001</value> - </param> - <param> - <key>num_steps</key> - <value>1000</value> - </param> - <param> - <key>style</key> - <value>wx.SL_HORIZONTAL</value> - </param> - <param> - <key>converver</key> - <value>float_converter</value> - </param> - <param> - <key>grid_pos</key> - <value></value> - </param> - <param> - <key>notebook</key> - <value></value> - </param> - <param> - <key>_coordinate</key> - <value>(734, 10)</value> - </param> - <param> - <key>_rotation</key> - <value>0</value> - </param> - </block> - <block> - <key>variable_slider</key> - <param> - <key>id</key> <value>phase_alpha</value> </param> <param> @@ -1621,6 +1511,116 @@ <value>0</value> </param> </block> + <block> + <key>variable_slider</key> + <param> + <key>id</key> + <value>freq_alpha</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>label</key> + <value>Freq Alpha</value> + </param> + <param> + <key>value</key> + <value>0</value> + </param> + <param> + <key>min</key> + <value>0</value> + </param> + <param> + <key>max</key> + <value>0.1</value> + </param> + <param> + <key>num_steps</key> + <value>1000</value> + </param> + <param> + <key>style</key> + <value>wx.SL_HORIZONTAL</value> + </param> + <param> + <key>converver</key> + <value>float_converter</value> + </param> + <param> + <key>grid_pos</key> + <value></value> + </param> + <param> + <key>notebook</key> + <value></value> + </param> + <param> + <key>_coordinate</key> + <value>(734, 10)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>variable_slider</key> + <param> + <key>id</key> + <value>freq_beta</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>label</key> + <value>Freq Beta</value> + </param> + <param> + <key>value</key> + <value>0</value> + </param> + <param> + <key>min</key> + <value>0.0</value> + </param> + <param> + <key>max</key> + <value>0.01</value> + </param> + <param> + <key>num_steps</key> + <value>1000</value> + </param> + <param> + <key>style</key> + <value>wx.SL_HORIZONTAL</value> + </param> + <param> + <key>converver</key> + <value>float_converter</value> + </param> + <param> + <key>grid_pos</key> + <value></value> + </param> + <param> + <key>notebook</key> + <value></value> + </param> + <param> + <key>_coordinate</key> + <value>(836, 9)</value> + </param> + <param> + <key>_rotation</key> + <value>180</value> + </param> + </block> <connection> <source_block_id>random_source_x_0</source_block_id> <sink_block_id>gr_uchar_to_float_0</sink_block_id> diff --git a/gnuradio-examples/python/digital/benchmark_loopback.py b/gnuradio-examples/python/digital/benchmark_loopback.py index 4cc4a7bee..47e4f2028 100755 --- a/gnuradio-examples/python/digital/benchmark_loopback.py +++ b/gnuradio-examples/python/digital/benchmark_loopback.py @@ -44,6 +44,11 @@ class my_top_block(gr.top_block): noise_power = power_in_signal/SNR noise_voltage = math.sqrt(noise_power) + # With new interface, sps does not get set by default, but + # in the loopback, we don't recalculate it; so just force it here + if(options.samples_per_symbol == None): + options.samples_per_symbol = 2 + self.txpath = transmit_path(mod_class, options) self.throttle = gr.throttle(gr.sizeof_gr_complex, options.sample_rate) self.rxpath = receive_path(demod_class, rx_callback, options) diff --git a/gnuradio-examples/python/digital/benchmark_qt_loopback2.py b/gnuradio-examples/python/digital/benchmark_qt_loopback2.py index 1cb95198e..56c6c7f52 100755 --- a/gnuradio-examples/python/digital/benchmark_qt_loopback2.py +++ b/gnuradio-examples/python/digital/benchmark_qt_loopback2.py @@ -1,6 +1,26 @@ #!/usr/bin/env python - -from gnuradio import gr, gru, modulation_utils +# +# 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, gru, modulation_utils2 from gnuradio import eng_notation from gnuradio.eng_option import eng_option from optparse import OptionParser @@ -223,6 +243,11 @@ class my_top_block(gr.top_block): self._noise_voltage = self.get_noise_voltage(self._snr_dB) + # With new interface, sps does not get set by default, but + # in the loopback, we don't recalculate it; so just force it here + if(options.samples_per_symbol == None): + options.samples_per_symbol = 2 + self.txpath = transmit_path(mod_class, options) self.throttle = gr.throttle(gr.sizeof_gr_complex, self.sample_rate()) self.rxpath = receive_path(demod_class, rx_callback, options) @@ -269,6 +294,7 @@ class my_top_block(gr.top_block): self.phase_recov = self.rxpath.packet_receiver._demodulator.phase_recov self.time_recov = self.rxpath.packet_receiver._demodulator.time_recov self.freq_recov.set_alpha(self._gain_freq) + self.freq_recov.set_beta(self._gain_freq/10.0) self.phase_recov.set_alpha(self._gain_phase) self.phase_recov.set_beta(0.25*self._gain_phase*self._gain_phase) self.time_recov.set_alpha(self._gain_clock) @@ -367,6 +393,7 @@ class my_top_block(gr.top_block): self._gain_freq = gain_freq #self._gain_freq_beta = .25 * self._gain_freq * self._gain_freq self.rxpath.packet_receiver._demodulator.freq_recov.set_alpha(self._gain_freq) + self.rxpath.packet_receiver._demodulator.freq_recov.set_beta(self._gain_freq/10.0) #self.rxpath.packet_receiver._demodulator.freq_recov.set_beta(self._gain_fre_beta) @@ -431,15 +458,15 @@ def main(): def send_pkt(payload='', eof=False): return tb.txpath.send_pkt(payload, eof) - mods = modulation_utils.type_1_mods() - demods = modulation_utils.type_1_demods() + mods = modulation_utils2.type_1_mods() + demods = modulation_utils2.type_1_demods() parser = OptionParser(option_class=eng_option, conflict_handler="resolve") expert_grp = parser.add_option_group("Expert") channel_grp = parser.add_option_group("Channel") parser.add_option("-m", "--modulation", type="choice", choices=mods.keys(), - default='dbpsk', + default='dbpsk2', help="Select modulation from: %s [default=%%default]" % (', '.join(mods.keys()),)) diff --git a/gnuradio-examples/python/digital/benchmark_qt_rx2.py b/gnuradio-examples/python/digital/benchmark_qt_rx2.py index cabbecb6f..0c37f4c6a 100755 --- a/gnuradio-examples/python/digital/benchmark_qt_rx2.py +++ b/gnuradio-examples/python/digital/benchmark_qt_rx2.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# Copyright 2005,2006,2007,2009 Free Software Foundation, Inc. +# Copyright 2010 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -20,7 +20,7 @@ # Boston, MA 02110-1301, USA. # -from gnuradio import gr, gru, modulation_utils +from gnuradio import gr, gru, modulation_utils2 from gnuradio import usrp from gnuradio import eng_notation from gnuradio.eng_option import eng_option @@ -33,7 +33,7 @@ import sys # from current dir from receive_path import receive_path -from pick_bitrate import pick_rx_bitrate +from pick_bitrate2 import pick_rx_bitrate try: from gnuradio.qtgui import qtgui @@ -219,7 +219,7 @@ class my_top_block(gr.top_block): # FIXME: do better exposure to lower issues for control self._gain_clock = self.rxpath.packet_receiver._demodulator._timing_alpha - self._gain_phase = self.rxpath.packet_receiver._demodulator._costas_alpha + self._gain_phase = self.rxpath.packet_receiver._demodulator._phase_alpha self._gain_freq = self.rxpath.packet_receiver._demodulator._freq_alpha self.connect(self.u, self.rxpath) @@ -242,8 +242,8 @@ class my_top_block(gr.top_block): # Connect to the QT sinks # FIXME: make better exposure to receiver from rxpath - #self.receiver = self.rxpath.packet_receiver._demodulator.phase_recov - self.receiver = self.rxpath.packet_receiver._demodulator.freq_recov + self.receiver = self.rxpath.packet_receiver._demodulator.phase_recov + #self.receiver = self.rxpath.packet_receiver._demodulator.freq_recov self.connect(self.u, self.snk_rxin) self.connect(self.receiver, self.snk_rx) @@ -267,9 +267,9 @@ class my_top_block(gr.top_block): self.u.set_decim(self._decim) (self._bitrate, self._samples_per_symbol, self._decim) = \ - pick_rx_bitrate(self._bitrate, self._demod_class.bits_per_symbol(), \ - self._samples_per_symbol, self._decim, adc_rate, \ - self.u.get_decim_rates()) + pick_rx_bitrate(options.bitrate, self._demod_class.bits_per_symbol(), \ + options.samples_per_symbol, options.decim, \ + adc_rate, self.u.get_decim_rates()) self.u.set_decim(self._decim) self.set_auto_tr(True) # enable Auto Transmit/Receive switching @@ -353,6 +353,7 @@ class my_top_block(gr.top_block): self._gain_freq = gain_freq #self._gain_freq_beta = .25 * self._gain_freq * self._gain_freq self.rxpath.packet_receiver._demodulator.freq_recov.set_alpha(self._gain_freq) + self.rxpath.packet_receiver._demodulator.freq_recov.set_beta(self._gain_freq/10.0) #self.rxpath.packet_receiver._demodulator.freq_recov.set_beta(self._gain_fre_beta) @@ -423,14 +424,14 @@ def main(): ok, pktno, n_rcvd, n_right) - demods = modulation_utils.type_1_demods() + demods = modulation_utils2.type_1_demods() # Create Options Parser: parser = OptionParser (option_class=eng_option, conflict_handler="resolve") expert_grp = parser.add_option_group("Expert") parser.add_option("-m", "--modulation", type="choice", choices=demods.keys(), - default='dbpsk', + default='dbpsk2', help="Select modulation from: %s [default=%%default]" % (', '.join(demods.keys()),)) diff --git a/gnuradio-examples/python/digital/benchmark_rx2.py b/gnuradio-examples/python/digital/benchmark_rx2.py new file mode 100755 index 000000000..fe422be83 --- /dev/null +++ b/gnuradio-examples/python/digital/benchmark_rx2.py @@ -0,0 +1,114 @@ +#!/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, gru, modulation_utils2 +from gnuradio import usrp +from gnuradio import eng_notation +from gnuradio.eng_option import eng_option +from optparse import OptionParser + +import random +import struct +import sys + +# from current dir +import usrp_receive_path2 + +#import os +#print os.getpid() +#raw_input('Attach and press enter: ') + +class my_top_block(gr.top_block): + def __init__(self, demodulator, rx_callback, options): + gr.top_block.__init__(self) + + # Set up receive path + self.rxpath = usrp_receive_path2.usrp_receive_path(demodulator, rx_callback, options) + + self.connect(self.rxpath) + +# ///////////////////////////////////////////////////////////////////////////// +# main +# ///////////////////////////////////////////////////////////////////////////// + +global n_rcvd, n_right + +def main(): + global n_rcvd, n_right + + n_rcvd = 0 + n_right = 0 + + def rx_callback(ok, payload): + global n_rcvd, n_right + (pktno,) = struct.unpack('!H', payload[0:2]) + n_rcvd += 1 + if ok: + n_right += 1 + + print "ok = %5s pktno = %4d n_rcvd = %4d n_right = %4d" % ( + ok, pktno, n_rcvd, n_right) + + + demods = modulation_utils2.type_1_demods() + + # Create Options Parser: + parser = OptionParser (option_class=eng_option, conflict_handler="resolve") + expert_grp = parser.add_option_group("Expert") + + parser.add_option("-m", "--modulation", type="choice", choices=demods.keys(), + default='dbpsk2', + help="Select modulation from: %s [default=%%default]" + % (', '.join(demods.keys()),)) + + usrp_receive_path2.add_options(parser, expert_grp) + + for mod in demods.values(): + mod.add_options(expert_grp) + + (options, args) = parser.parse_args () + + if len(args) != 0: + parser.print_help(sys.stderr) + sys.exit(1) + + if options.rx_freq is None: + sys.stderr.write("You must specify -f FREQ or --freq FREQ\n") + parser.print_help(sys.stderr) + sys.exit(1) + + + # build the graph + tb = my_top_block(demods[options.modulation], rx_callback, 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/gnuradio-examples/python/digital/benchmark_tx2.py b/gnuradio-examples/python/digital/benchmark_tx2.py new file mode 100755 index 000000000..6093dba61 --- /dev/null +++ b/gnuradio-examples/python/digital/benchmark_tx2.py @@ -0,0 +1,135 @@ +#!/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, gru, modulation_utils2 +from gnuradio import usrp +from gnuradio import eng_notation +from gnuradio.eng_option import eng_option +from optparse import OptionParser + +import random, time, struct, sys + +# from current dir +import usrp_transmit_path2 + +#import os +#print os.getpid() +#raw_input('Attach and press enter') + +class my_top_block(gr.top_block): + def __init__(self, modulator, options): + gr.top_block.__init__(self) + + self.txpath = usrp_transmit_path2.usrp_transmit_path(modulator, options) + + self.connect(self.txpath) + +# ///////////////////////////////////////////////////////////////////////////// +# main +# ///////////////////////////////////////////////////////////////////////////// + +def main(): + + def send_pkt(payload='', eof=False): + return tb.txpath.send_pkt(payload, eof) + + def rx_callback(ok, payload): + print "ok = %r, payload = '%s'" % (ok, payload) + + mods = modulation_utils2.type_1_mods() + + parser = OptionParser(option_class=eng_option, conflict_handler="resolve") + expert_grp = parser.add_option_group("Expert") + + parser.add_option("-m", "--modulation", type="choice", choices=mods.keys(), + default='dbpsk2', + help="Select modulation from: %s [default=%%default]" + % (', '.join(mods.keys()),)) + + parser.add_option("-s", "--size", type="eng_float", default=1500, + help="set packet size [default=%default]") + parser.add_option("-M", "--megabytes", type="eng_float", default=1.0, + help="set megabytes to transmit [default=%default]") + parser.add_option("","--discontinuous", action="store_true", default=False, + help="enable discontinous transmission (bursts of 5 packets)") + parser.add_option("","--from-file", default=None, + help="use file for packet contents") + + usrp_transmit_path2.add_options(parser, expert_grp) + + for mod in mods.values(): + mod.add_options(expert_grp) + + (options, args) = parser.parse_args () + + if len(args) != 0: + parser.print_help() + sys.exit(1) + + if options.tx_freq is None: + sys.stderr.write("You must specify -f FREQ or --freq FREQ\n") + parser.print_help(sys.stderr) + sys.exit(1) + + if options.from_file is not None: + source_file = open(options.from_file, 'r') + + # build the graph + tb = my_top_block(mods[options.modulation], options) + + r = gr.enable_realtime_scheduling() + if r != gr.RT_OK: + print "Warning: failed to enable realtime scheduling" + + tb.start() # start flow graph + + # generate and send packets + nbytes = int(1e6 * options.megabytes) + n = 0 + pktno = 0 + pkt_size = int(options.size) + + while n < nbytes: + if options.from_file is None: + data = (pkt_size - 2) * chr(pktno & 0xff) + else: + data = source_file.read(pkt_size - 2) + if data == '': + break; + + payload = struct.pack('!H', pktno & 0xffff) + data + send_pkt(payload) + n += len(payload) + sys.stderr.write('.') + if options.discontinuous and pktno % 5 == 4: + time.sleep(1) + pktno += 1 + + send_pkt(eof=True) + + tb.wait() # wait for it to finish + +if __name__ == '__main__': + try: + main() + except KeyboardInterrupt: + pass diff --git a/gnuradio-examples/python/digital/pick_bitrate2.py b/gnuradio-examples/python/digital/pick_bitrate2.py new file mode 100644 index 000000000..92539560c --- /dev/null +++ b/gnuradio-examples/python/digital/pick_bitrate2.py @@ -0,0 +1,154 @@ +# +# 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 eng_notation + +_default_bitrate = 500e3 +_sps_min = 2 +_sps_max = 100 + +def _pick_bitrate(bitrate, bits_per_symbol, samples_per_symbol, + xrate, converter_rate, xrates): + """ + @returns tuple (bitrate, samples_per_symbol, interp_rate_or_decim_rate) + """ + + if not isinstance(bits_per_symbol, int) or bits_per_symbol < 1: + raise ValueError, "bits_per_symbol must be an int >= 1" + + converter_rate = float(converter_rate) + bits_per_symbol = float(bits_per_symbol) + + # completely determined; if bitrate is specified, this overwrites it + if (samples_per_symbol is not None) and (xrate is not None): + bitrate = converter_rate / bits_per_symbol / xrate / samples_per_symbol + + # If only SPS is given + if (bitrate is None) and (samples_per_symbol is not None) and (xrate is None): + xrate = max(xrates) + bitrate = converter_rate / bits_per_symbol / xrate / samples_per_symbol + + # If only xrate is given, just set SPS to 2 and calculate bitrate + if (bitrate is None) and (samples_per_symbol is None) and (xrate is not None): + samples_per_symbol = 2.0 + bitrate = converter_rate / bits_per_symbol / xrate / samples_per_symbol + + # If no parameters are give, use the default bit rate + if (bitrate is None) and (samples_per_symbol is None) and (xrate is None): + bitrate = _default_bitrate + + # If only bitrate is specified, return max xrate and appropriate + # samples per symbol (minimum of 2.0) to reach bit rate + if (samples_per_symbol is None) and (xrate is None): + xrates.sort() + for i in xrange(len(xrates)): + if((converter_rate / bits_per_symbol / xrates[i]) >= 2*bitrate): + rate = xrates[i] + else: + break + + try: + xrate = rate + except UnboundLocalError: + raise ValueError("Requested bitrate out of bounds") + + samples_per_symbol = converter_rate / bits_per_symbol / rate / bitrate + bitrate = converter_rate / bits_per_symbol / xrate / samples_per_symbol + + # If bitrate and xrate are specified + if(samples_per_symbol is None): + samples_per_symbol = converter_rate / xrate / bits_per_symbol / bitrate + + # If bitrate and SPS are specified + if(xrate is None): + xrate = converter_rate / samples_per_symbol / bits_per_symbol / bitrate + if((xrate in xrates) == False): + # Find the closest avaiable rate larger than the calculated one + xrates.sort() + for x in xrates: + if(x > xrate): + xrate = x + break + if(xrate > max(xrates)): + xrate = max(xrates) + + bitrate = converter_rate / bits_per_symbol / xrate / samples_per_symbol + print "Could not find suitable rate for specified SPS and Bitrate" + print "Using rate = %d for bitrate of %sbps" % \ + (xrate, (eng_notation.num_to_str(bitrate))) + + if((xrate in xrates) == False): + raise ValueError(("Invalid rate (rate = %d)" % xrate)) + if((samples_per_symbol < _sps_min) or (samples_per_symbol > _sps_max)): + raise ValueError(("Invalid samples per symbol (sps = %.2f). Must be in [%.0f, %.0f]." \ + % (samples_per_symbol, _sps_min, _sps_max))) + + return (bitrate, samples_per_symbol, int(xrate)) + + +def pick_tx_bitrate(bitrate, bits_per_symbol, samples_per_symbol, + interp_rate, converter_rate, possible_interps): + """ + Given the 4 input parameters, return at configuration that matches + + @param bitrate: desired bitrate or None + @type bitrate: number or None + @param bits_per_symbol: E.g., BPSK -> 1, QPSK -> 2, 8-PSK -> 3 + @type bits_per_symbol: integer >= 1 + @param samples_per_symbol: samples/baud (aka samples/symbol) + @type samples_per_symbol: number or None + @param interp_rate: USRP interpolation factor + @type interp_rate: integer or None + @param converter_rate: converter sample rate in Hz + @type converter_rate: number + @param possible_interps: a list of possible rates + @type possible_interps: a list of integers + + @returns tuple (bitrate, samples_per_symbol, interp_rate) + """ + + return _pick_bitrate(bitrate, bits_per_symbol, samples_per_symbol, + interp_rate, converter_rate, possible_interps) + + +def pick_rx_bitrate(bitrate, bits_per_symbol, samples_per_symbol, + decim_rate, converter_rate, possible_decims): + """ + Given the 4 input parameters, return at configuration that matches + + @param bitrate: desired bitrate or None + @type bitrate: number or None + @param bits_per_symbol: E.g., BPSK -> 1, QPSK -> 2, 8-PSK -> 3 + @type bits_per_symbol: integer >= 1 + @param samples_per_symbol: samples/baud (aka samples/symbol) + @type samples_per_symbol: number or None + @param decim_rate: USRP decimation factor + @type decim_rate: integer or None + @param converter_rate: converter sample rate in Hz + @type converter_rate: number + @param possible_decims: a list of possible rates + @type possible_decims: a list of integers + + @returns tuple (bitrate, samples_per_symbol, decim_rate) + """ + + return _pick_bitrate(bitrate, bits_per_symbol, samples_per_symbol, + decim_rate, converter_rate, possible_decims) diff --git a/gnuradio-examples/python/digital/receive_path.py b/gnuradio-examples/python/digital/receive_path.py index c229aa9e4..0024d6941 100644 --- a/gnuradio-examples/python/digital/receive_path.py +++ b/gnuradio-examples/python/digital/receive_path.py @@ -119,7 +119,7 @@ class receive_path(gr.hier_block2): normal.add_option("-r", "--bitrate", type="eng_float", default=100e3, help="specify bitrate [default=%default].") normal.add_option("-v", "--verbose", action="store_true", default=False) - expert.add_option("-S", "--samples-per-symbol", type="int", default=2, + expert.add_option("-S", "--samples-per-symbol", type="float", default=None, help="set samples/symbol [default=%default]") expert.add_option("", "--log", action="store_true", default=False, help="Log all parts of flow graph to files (CAUTION: lots of data)") @@ -135,4 +135,4 @@ class receive_path(gr.hier_block2): print "\nReceive Path:" print "modulation: %s" % (self._demod_class.__name__) print "bitrate: %sb/s" % (eng_notation.num_to_str(self._bitrate)) - print "samples/symbol: %3d" % (self._samples_per_symbol) + print "samples/symbol: %.4f" % (self._samples_per_symbol) diff --git a/gnuradio-examples/python/digital/transmit_path.py b/gnuradio-examples/python/digital/transmit_path.py index 9badcdc08..86ebf75c3 100644 --- a/gnuradio-examples/python/digital/transmit_path.py +++ b/gnuradio-examples/python/digital/transmit_path.py @@ -99,7 +99,7 @@ class transmit_path(gr.hier_block2): help="set transmitter digital amplitude: 0 <= AMPL < 1 [default=%default]") normal.add_option("-v", "--verbose", action="store_true", default=False) - expert.add_option("-S", "--samples-per-symbol", type="int", default=2, + expert.add_option("-S", "--samples-per-symbol", type="float", default=None, help="set samples/symbol [default=%default]") expert.add_option("", "--log", action="store_true", default=False, help="Log all parts of flow graph to file (CAUTION: lots of data)") @@ -114,5 +114,5 @@ class transmit_path(gr.hier_block2): print "Tx amplitude %s" % (self._tx_amplitude) print "modulation: %s" % (self._modulator_class.__name__) print "bitrate: %sb/s" % (eng_notation.num_to_str(self._bitrate)) - print "samples/symbol: %3d" % (self._samples_per_symbol) + print "samples/symbol: %.4f" % (self._samples_per_symbol) diff --git a/gnuradio-examples/python/digital/usrp_receive_path.py b/gnuradio-examples/python/digital/usrp_receive_path.py index 517825cc1..a8f16e28a 100644 --- a/gnuradio-examples/python/digital/usrp_receive_path.py +++ b/gnuradio-examples/python/digital/usrp_receive_path.py @@ -59,37 +59,35 @@ class usrp_receive_path(gr.hier_block2): if options.rx_freq is None: sys.stderr.write("-f FREQ or --freq FREQ or --rx-freq FREQ must be specified\n") raise SystemExit - rx_path = receive_path.receive_path(demod_class, rx_callback, options) - for attr in dir(rx_path): #forward the methods - if not attr.startswith('_') and not hasattr(self, attr): - setattr(self, attr, getattr(rx_path, attr)) #setup usrp self._demod_class = demod_class self._setup_usrp_source(options) - # Set up resampler based on rate determined by _setup_usrp_source - rs_taps = gr.firdes.low_pass_2(32, 32, 0.45, 0.1, 60) - self.resampler = gr.pfb_arb_resampler_ccf(self.rs_rate, rs_taps) + rx_path = receive_path.receive_path(demod_class, rx_callback, options) + for attr in dir(rx_path): #forward the methods + if not attr.startswith('_') and not hasattr(self, attr): + setattr(self, attr, getattr(rx_path, attr)) #connect - self.connect(self.u, self.resampler, rx_path) + self.connect(self.u, rx_path) def _setup_usrp_source(self, options): self.u = usrp_options.create_usrp_source(options) adc_rate = self.u.adc_rate() self.rs_rate = options.bitrate - if options.verbose: - print 'USRP Source:', self.u + (self._bitrate, self._samples_per_symbol, self._decim) = \ pick_rx_bitrate(options.bitrate, self._demod_class.bits_per_symbol(), \ - options.samples_per_symbol, options.decim, adc_rate, \ - self.u.get_decim_rates()) + options.samples_per_symbol, options.decim, + adc_rate, self.u.get_decim_rates()) - # Calculate resampler rate based on requested and actual rates - self.rs_rate = 1.0 /(self._bitrate / self.rs_rate) - - print "Resampling by %f to get bitrate of %ssps" % ( self.rs_rate, eng_notation.num_to_str(self._bitrate/self.rs_rate)) + if options.verbose: + print 'USRP Source:', self.u + print 'Decimation: ', self._decim + + options.samples_per_symbol = self._samples_per_symbol + options.decim = self._decim self.u.set_decim(self._decim) diff --git a/gnuradio-examples/python/digital/usrp_receive_path2.py b/gnuradio-examples/python/digital/usrp_receive_path2.py new file mode 100644 index 000000000..d20017204 --- /dev/null +++ b/gnuradio-examples/python/digital/usrp_receive_path2.py @@ -0,0 +1,96 @@ +# +# 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 +from gnuradio import usrp_options +import receive_path +from pick_bitrate2 import pick_rx_bitrate +from gnuradio import eng_notation + +def add_freq_option(parser): + """ + Hackery that has the -f / --freq option set both tx_freq and rx_freq + """ + def freq_callback(option, opt_str, value, parser): + parser.values.rx_freq = value + parser.values.tx_freq = value + + if not parser.has_option('--freq'): + parser.add_option('-f', '--freq', type="eng_float", + action="callback", callback=freq_callback, + help="set Tx and/or Rx frequency to FREQ [default=%default]", + metavar="FREQ") + +def add_options(parser, expert): + add_freq_option(parser) + usrp_options.add_rx_options(parser) + receive_path.receive_path.add_options(parser, expert) + expert.add_option("", "--rx-freq", type="eng_float", default=None, + help="set Rx frequency to FREQ [default=%default]", metavar="FREQ") + parser.add_option("-v", "--verbose", action="store_true", default=False) + +class usrp_receive_path(gr.hier_block2): + + def __init__(self, demod_class, rx_callback, options): + ''' + See below for what options should hold + ''' + gr.hier_block2.__init__(self, "usrp_receive_path", + gr.io_signature(0, 0, 0), # Input signature + gr.io_signature(0, 0, 0)) # Output signature + if options.rx_freq is None: + sys.stderr.write("-f FREQ or --freq FREQ or --rx-freq FREQ must be specified\n") + raise SystemExit + + #setup usrp + self._demod_class = demod_class + self._setup_usrp_source(options) + + rx_path = receive_path.receive_path(demod_class, rx_callback, options) + for attr in dir(rx_path): #forward the methods + if not attr.startswith('_') and not hasattr(self, attr): + setattr(self, attr, getattr(rx_path, attr)) + + #connect + self.connect(self.u, rx_path) + + def _setup_usrp_source(self, options): + self.u = usrp_options.create_usrp_source(options) + adc_rate = self.u.adc_rate() + self.rs_rate = options.bitrate + + (self._bitrate, self._samples_per_symbol, self._decim) = \ + pick_rx_bitrate(options.bitrate, self._demod_class.bits_per_symbol(), \ + options.samples_per_symbol, options.decim, + adc_rate, self.u.get_decim_rates()) + + if options.verbose: + print 'USRP Source:', self.u + print 'Decimation: ', self._decim + + options.samples_per_symbol = self._samples_per_symbol + options.decim = self._decim + + self.u.set_decim(self._decim) + + if not self.u.set_center_freq(options.rx_freq): + print "Failed to set Rx frequency to %s" % (eng_notation.num_to_str(options.rx_freq)) + raise ValueError, eng_notation.num_to_str(options.rx_freq) diff --git a/gnuradio-examples/python/digital/usrp_transmit_path.py b/gnuradio-examples/python/digital/usrp_transmit_path.py index ee63dcd2b..f0f467599 100644 --- a/gnuradio-examples/python/digital/usrp_transmit_path.py +++ b/gnuradio-examples/python/digital/usrp_transmit_path.py @@ -58,21 +58,18 @@ class usrp_transmit_path(gr.hier_block2): if options.tx_freq is None: sys.stderr.write("-f FREQ or --freq FREQ or --tx-freq FREQ must be specified\n") raise SystemExit - tx_path = transmit_path.transmit_path(modulator_class, options) - for attr in dir(tx_path): #forward the methods - if not attr.startswith('_') and not hasattr(self, attr): - setattr(self, attr, getattr(tx_path, attr)) #setup usrp self._modulator_class = modulator_class self._setup_usrp_sink(options) - # Set up resampler based on rate determined by _setup_usrp_sink - rs_taps = gr.firdes.low_pass_2(32, 32, 0.45, 0.1, 60) - self.resampler = gr.pfb_arb_resampler_ccf(self.rs_rate, rs_taps) + tx_path = transmit_path.transmit_path(modulator_class, options) + for attr in dir(tx_path): #forward the methods + if not attr.startswith('_') and not hasattr(self, attr): + setattr(self, attr, getattr(tx_path, attr)) #connect - self.connect(tx_path, self.resampler, self.u) + self.connect(tx_path, self.u) def _setup_usrp_sink(self, options): """ @@ -82,17 +79,20 @@ class usrp_transmit_path(gr.hier_block2): self.u = usrp_options.create_usrp_sink(options) dac_rate = self.u.dac_rate() self.rs_rate = options.bitrate # Store requested bit rate - if options.verbose: - print 'USRP Sink:', self.u + (self._bitrate, self._samples_per_symbol, self._interp) = \ - pick_tx_bitrate(options.bitrate, self._modulator_class.bits_per_symbol(), \ - options.samples_per_symbol, options.interp, dac_rate, \ - self.u.get_interp_rates()) + pick_tx_bitrate(options.bitrate, self._modulator_class.bits_per_symbol(), + options.samples_per_symbol, options.interp, + dac_rate, self.u.get_interp_rates()) - # Calculate resampler rate based on requested and actual rates - self.rs_rate = self._bitrate / self.rs_rate - print "Resampling by %f to get bitrate of %ssps" % (self.rs_rate, eng_notation.num_to_str(self._bitrate/self.rs_rate)) + options.interp = self._interp + options.samples_per_symbol = self._samples_per_symbol + options.bitrate = self._bitrate + if options.verbose: + print 'USRP Sink:', self.u + print "Interpolation Rate: ", self._interp + self.u.set_interp(self._interp) self.u.set_auto_tr(True) diff --git a/gnuradio-examples/python/digital/usrp_transmit_path2.py b/gnuradio-examples/python/digital/usrp_transmit_path2.py new file mode 100644 index 000000000..54930e5a0 --- /dev/null +++ b/gnuradio-examples/python/digital/usrp_transmit_path2.py @@ -0,0 +1,101 @@ +# +# 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 +from gnuradio import usrp_options +import transmit_path +from pick_bitrate2 import pick_tx_bitrate +from gnuradio import eng_notation + +def add_freq_option(parser): + """ + Hackery that has the -f / --freq option set both tx_freq and rx_freq + """ + def freq_callback(option, opt_str, value, parser): + parser.values.rx_freq = value + parser.values.tx_freq = value + + if not parser.has_option('--freq'): + parser.add_option('-f', '--freq', type="eng_float", + action="callback", callback=freq_callback, + help="set Tx and/or Rx frequency to FREQ [default=%default]", + metavar="FREQ") + +def add_options(parser, expert): + add_freq_option(parser) + usrp_options.add_tx_options(parser) + transmit_path.transmit_path.add_options(parser, expert) + expert.add_option("", "--tx-freq", type="eng_float", default=None, + help="set transmit frequency to FREQ [default=%default]", metavar="FREQ") + parser.add_option("-v", "--verbose", action="store_true", default=False) + +class usrp_transmit_path(gr.hier_block2): + def __init__(self, modulator_class, options): + ''' + See below for what options should hold + ''' + gr.hier_block2.__init__(self, "usrp_transmit_path", + gr.io_signature(0, 0, 0), # Input signature + gr.io_signature(0, 0, 0)) # Output signature + if options.tx_freq is None: + sys.stderr.write("-f FREQ or --freq FREQ or --tx-freq FREQ must be specified\n") + raise SystemExit + + #setup usrp + self._modulator_class = modulator_class + self._setup_usrp_sink(options) + + tx_path = transmit_path.transmit_path(modulator_class, options) + for attr in dir(tx_path): #forward the methods + if not attr.startswith('_') and not hasattr(self, attr): + setattr(self, attr, getattr(tx_path, attr)) + + #connect + self.connect(tx_path, self.u) + + def _setup_usrp_sink(self, options): + """ + Creates a USRP sink, determines the settings for best bitrate, + and attaches to the transmitter's subdevice. + """ + self.u = usrp_options.create_usrp_sink(options) + dac_rate = self.u.dac_rate() + self.rs_rate = options.bitrate # Store requested bit rate + + (self._bitrate, self._samples_per_symbol, self._interp) = \ + pick_tx_bitrate(options.bitrate, self._modulator_class.bits_per_symbol(), + options.samples_per_symbol, options.interp, + dac_rate, self.u.get_interp_rates()) + + options.interp = self._interp + options.samples_per_symbol = self._samples_per_symbol + options.bitrate = self._bitrate + + if options.verbose: + print 'USRP Sink:', self.u + print "Interpolation Rate: ", self._interp + + self.u.set_interp(self._interp) + self.u.set_auto_tr(True) + + if not self.u.set_center_freq(options.tx_freq): + print "Failed to set Rx frequency to %s" % (eng_notation.num_to_str(options.tx_freq)) + raise ValueError, eng_notation.num_to_str(options.tx_freq) |