gnuradio-core/src/python/gnuradio/blks/Makefile \
gnuradio-core/src/python/gnuradio/blksimpl/Makefile \
gnuradio-core/src/python/gnuradio/blks2/Makefile \
- gnuradio-core/src/python/gnuradio/blksimpl2/Makefile \
+ gnuradio-core/src/python/gnuradio/blks2impl/Makefile \
gnuradio-core/src/python/gnuradio/gr/Makefile \
gnuradio-core/src/python/gnuradio/gr/run_tests \
gnuradio-core/src/python/gnuradio/gru/Makefile \
gnuradio-examples/python/apps/hf_radio/Makefile \
gnuradio-examples/python/apps/Makefile \
gnuradio-examples/python/audio/Makefile \
+ gnuradio-examples/python/dect/Makefile \
gnuradio-examples/python/digital/Makefile \
gnuradio-examples/python/digital_voice/Makefile \
- gnuradio-examples/python/hier/Makefile \
- gnuradio-examples/python/hier/audio/Makefile \
- gnuradio-examples/python/hier/networking/Makefile \
- gnuradio-examples/python/hier/digital/Makefile \
- gnuradio-examples/python/hier/dect/Makefile \
- gnuradio-examples/python/hier/ofdm/Makefile \
- gnuradio-examples/python/hier/sounder/Makefile \
- gnuradio-examples/python/hier/usrp/Makefile \
gnuradio-examples/python/multi-antenna/Makefile \
gnuradio-examples/python/multi_usrp/Makefile \
- gnuradio-examples/python/networking/Makefile \
+ gnuradio-examples/python/network/Makefile \
gnuradio-examples/python/ofdm/Makefile \
gnuradio-examples/python/usrp/Makefile \
])
$EXTRACT gnuradio-core/src/python/gnuradio/blks/Makefile grblkspython_PYTHON >>$NAME
$EXTRACT gnuradio-core/src/python/gnuradio/blks2/Makefile grblks2python_PYTHON >>$NAME
$EXTRACT gnuradio-core/src/python/gnuradio/blksimpl/Makefile grblkspython_PYTHON >>$NAME
-$EXTRACT gnuradio-core/src/python/gnuradio/blksimpl2/Makefile grblkspython_PYTHON >>$NAME
+$EXTRACT gnuradio-core/src/python/gnuradio/blks2impl/Makefile grblkspython_PYTHON >>$NAME
$EXTRACT gnuradio-core/src/python/gnuradio/gru/Makefile grblkspython_PYTHON >>$NAME
$EXTRACT gnuradio-core/src/python/gnuradio/gruimpl/Makefile grupython_PYTHON >>$NAME
$EXTRACT gnuradio-core/src/python/gnuradio/vocoder/Makefile grvocoderpython_PYTHON >>$NAME
$EXTRACT gnuradio-examples/python/apps/hf_explorer/Makefile ourdata_DATA >>$NAME
$EXTRACT gnuradio-examples/python/apps/hf_radio/Makefile ourdata_DATA >>$NAME
$EXTRACT gnuradio-examples/python/audio/Makefile ourdata_DATA >>$NAME
+$EXTRACT gnuradio-examples/python/dect/Makefile ourdata_DATA >>$NAME
$EXTRACT gnuradio-examples/python/digital/Makefile ourdata_DATA >>$NAME
$EXTRACT gnuradio-examples/python/digital_voice/Makefile ourdata_DATA >>$NAME
$EXTRACT gnuradio-examples/python/multi-antenna/Makefile ourdata_DATA >>$NAME
$EXTRACT gnuradio-examples/python/multi_usrp/Makefile ourdata_DATA >>$NAME
+$EXTRACT gnuradio-examples/python/network/Makefile ourdata_DATA >>$NAME
$EXTRACT gnuradio-examples/python/ofdm/Makefile ourdata_DATA >>$NAME
$EXTRACT gnuradio-examples/python/usrp/Makefile ourdata_DATA >>$NAME
delete d_detail;
}
+void
+gr_hier_block2::connect(gr_basic_block_sptr block)
+{
+ d_detail->connect(block);
+}
+
void
gr_hier_block2::connect(gr_basic_block_sptr src, int src_port,
gr_basic_block_sptr dst, int dst_port)
d_detail->connect(src, src_port, dst, dst_port);
}
+void
+gr_hier_block2::disconnect(gr_basic_block_sptr block)
+{
+ d_detail->disconnect(block);
+}
+
void
gr_hier_block2::disconnect(gr_basic_block_sptr src, int src_port,
gr_basic_block_sptr dst, int dst_port)
d_detail->disconnect(src, src_port, dst, dst_port);
}
+void
+gr_hier_block2::disconnect_all()
+{
+ d_detail->disconnect_all();
+}
+
void
gr_hier_block2::lock()
{
public:
virtual ~gr_hier_block2();
+ void connect(gr_basic_block_sptr block);
+
void connect(gr_basic_block_sptr src, int src_port,
gr_basic_block_sptr dst, int dst_port);
+ void disconnect(gr_basic_block_sptr block);
+
void disconnect(gr_basic_block_sptr src, int src_port,
gr_basic_block_sptr dst, int dst_port);
- /*!
- * Lock a flowgraph in preparation for reconfiguration. When an equal
- * number of calls to lock() and unlock() have occurred, the flowgraph
- * will be restarted automatically.
- *
- * N.B. lock() and unlock() cannot be called from a flowgraph thread
- * (E.g., gr_block::work method) or deadlock will occur when
- * reconfiguration happens.
- */
+ void disconnect_all();
virtual void lock();
-
- /*!
- * Lock a flowgraph in preparation for reconfiguration. When an equal
- * number of calls to lock() and unlock() have occurred, the flowgraph
- * will be restarted automatically.
- *
- * N.B. lock() and unlock() cannot be called from a flowgraph thread
- * (E.g., gr_block::work method) or deadlock will occur when
- * reconfiguration happens.
- */
virtual void unlock();
gr_flat_flowgraph_sptr flatten() const;
class gr_hier_block2 : public gr_basic_block
{
private:
- gr_hier_block2(const std::string name,
- gr_io_signature_sptr input_signature,
- gr_io_signature_sptr output_signature);
-
+ gr_hier_block2(const std::string name,
+ gr_io_signature_sptr input_signature,
+ gr_io_signature_sptr output_signature);
+
public:
- ~gr_hier_block2 ();
-
- // Add a named block to the container
- void connect(gr_basic_block_sptr src, int src_port,
- gr_basic_block_sptr dst, int dst_port)
- throw (std::invalid_argument);
- void disconnect(gr_basic_block_sptr src, int src_port,
- gr_basic_block_sptr dst, int dst_port)
- throw (std::invalid_argument);
- void lock();
- void unlock();
+ ~gr_hier_block2 ();
+
+ void connect(gr_basic_block_sptr block)
+ throw (std::invalid_argument);
+ void connect(gr_basic_block_sptr src, int src_port,
+ gr_basic_block_sptr dst, int dst_port)
+ throw (std::invalid_argument);
+ void disconnect(gr_basic_block_sptr block)
+ throw (std::invalid_argument);
+ void disconnect(gr_basic_block_sptr src, int src_port,
+ gr_basic_block_sptr dst, int dst_port)
+ throw (std::invalid_argument);
+ void disconnect_all();
+ void lock();
+ void unlock();
};
d_owner = 0; // Don't use delete, we didn't allocate
}
+void
+gr_hier_block2_detail::connect(gr_basic_block_sptr block)
+{
+ std::stringstream msg;
+
+ // Check if duplicate
+ if (std::find(d_blocks.begin(), d_blocks.end(), block) != d_blocks.end()) {
+ msg << "Block " << block << " already connected.";
+ throw std::invalid_argument(msg.str());
+ }
+
+ // Check if has inputs or outputs
+ if (block->input_signature()->max_streams() != 0 ||
+ block->output_signature()->max_streams() != 0) {
+ msg << "Block " << block << " must not have any input or output ports";
+ throw std::invalid_argument(msg.str());
+ }
+
+ d_blocks.push_back(block);
+}
+
void
gr_hier_block2_detail::connect(gr_basic_block_sptr src, int src_port,
gr_basic_block_sptr dst, int dst_port)
// TODO: connects to NC
}
+void
+gr_hier_block2_detail::disconnect(gr_basic_block_sptr block)
+{
+ for (gr_basic_block_viter_t p = d_blocks.begin(); p != d_blocks.end(); p++) {
+ if (*p == block) {
+ d_blocks.erase(p);
+ return;
+ }
+ }
+
+ std::stringstream msg;
+ msg << "cannot disconnect block " << block << ", not found";
+ throw std::invalid_argument(msg.str());
+}
+
void
gr_hier_block2_detail::disconnect(gr_basic_block_sptr src, int src_port,
gr_basic_block_sptr dst, int dst_port)
return result;
}
+void
+gr_hier_block2_detail::disconnect_all()
+{
+ d_fg->clear();
+ d_blocks.clear();
+ d_inputs.clear();
+ d_outputs.clear();
+}
+
gr_endpoint
gr_hier_block2_detail::resolve_endpoint(const gr_endpoint &endp, bool is_input) const
{
sfg->connect(src_endp, dst_endp);
}
- gr_basic_block_vector_t blocks = d_fg->calc_used_blocks();
+ // Construct unique list of blocks used either in edges or
+ // by themselves. I hate STL.
+ gr_basic_block_vector_t blocks, tmp = d_fg->calc_used_blocks();
+ std::insert_iterator<gr_basic_block_vector_t> inserter(blocks, blocks.begin());
+ std::vector<gr_basic_block_sptr>::const_iterator p; // Because flatten_aux is const
+ for (p = d_blocks.begin(); p != d_blocks.end(); p++)
+ tmp.push_back(*p);
+ sort(tmp.begin(), tmp.end());
+ unique_copy(tmp.begin(), tmp.end(), inserter);
// Recurse hierarchical children
for (gr_basic_block_viter_t p = blocks.begin(); p != blocks.end(); p++) {
class gr_hier_block2_detail : boost::noncopyable
{
-private:
- friend class gr_hier_block2;
- friend class gr_runtime_impl;
-
- // Constructor--it's private, only friends can instantiate
- gr_hier_block2_detail(gr_hier_block2 *owner);
-
- // Private implementation data
- gr_hier_block2 *d_owner;
- gr_hier_block2_detail *d_parent_detail;
- gr_flowgraph_sptr d_fg;
- gr_endpoint_vector_t d_inputs;
- gr_endpoint_vector_t d_outputs;
+public:
+ gr_hier_block2_detail(gr_hier_block2 *owner);
+ ~gr_hier_block2_detail();
- // Private implementation methods
- void connect(gr_basic_block_sptr src, int src_port,
- gr_basic_block_sptr dst, int dst_port);
- void disconnect(gr_basic_block_sptr, int src_port,
- gr_basic_block_sptr, int dst_port);
- void connect_input(int my_port, int port, gr_basic_block_sptr block);
- void connect_output(int my_port, int port, gr_basic_block_sptr block);
- void disconnect_input(int my_port, int port, gr_basic_block_sptr block);
- void disconnect_output(int my_port, int port, gr_basic_block_sptr block);
- void flatten_aux(gr_flat_flowgraph_sptr sfg) const;
- gr_endpoint resolve_port(int port, bool is_input);
- gr_endpoint resolve_endpoint(const gr_endpoint &endp, bool is_input) const;
- void lock();
- void unlock();
+ void connect(gr_basic_block_sptr block);
+ void connect(gr_basic_block_sptr src, int src_port,
+ gr_basic_block_sptr dst, int dst_port);
+ void disconnect(gr_basic_block_sptr block);
+ void disconnect(gr_basic_block_sptr, int src_port,
+ gr_basic_block_sptr, int dst_port);
+ void disconnect_all();
+ void lock();
+ void unlock();
+ void flatten_aux(gr_flat_flowgraph_sptr sfg) const;
-public:
- ~gr_hier_block2_detail();
+private:
+
+ // Private implementation data
+ gr_hier_block2 *d_owner;
+ gr_hier_block2_detail *d_parent_detail;
+ gr_flowgraph_sptr d_fg;
+ gr_endpoint_vector_t d_inputs;
+ gr_endpoint_vector_t d_outputs;
+ gr_basic_block_vector_t d_blocks;
+
+ void connect_input(int my_port, int port, gr_basic_block_sptr block);
+ void connect_output(int my_port, int port, gr_basic_block_sptr block);
+ void disconnect_input(int my_port, int port, gr_basic_block_sptr block);
+ void disconnect_output(int my_port, int port, gr_basic_block_sptr block);
+ gr_endpoint resolve_port(int port, bool is_input);
+ gr_endpoint resolve_endpoint(const gr_endpoint &endp, bool is_input) const;
};
#endif /* INCLUDED_GR_HIER_BLOCK2_DETAIL_H */
{
d_impl->unlock();
}
+
+bool
+gr_top_block::is_running()
+{
+ return d_impl->is_running();
+}
* reconfiguration happens.
*/
virtual void unlock();
+
+ /*!
+ * Returns true if flowgraph is running
+ */
+ bool is_running();
};
#endif /* INCLUDED_GR_TOP_BLOCK_H */
void run();
void lock();
void unlock();
+ bool is_running();
};
%{
// Unlock the top block at end of reconfiguration
void unlock();
+ // Return true if flowgraph is running
+ bool is_running() const { return d_running; }
+
private:
bool d_running;
include $(top_srcdir)/Makefile.common
-SUBDIRS = gr gru gruimpl blks blksimpl blks2 blksimpl2 vocoder
+SUBDIRS = gr gru gruimpl blks blksimpl blks2 blks2impl vocoder
grpython_PYTHON = \
__init__.py \
# to manually update this file.
for p in __path__:
- filenames = glob.glob (os.path.join (p, "..", "blksimpl2", "*.py"))
+ filenames = glob.glob (os.path.join (p, "..", "blks2impl", "*.py"))
for f in filenames:
f = os.path.basename(f).lower()
f = f[:-3]
if f == '__init__':
continue
# print f
- exec "from gnuradio.blksimpl2.%s import *" % (f,)
+ exec "from gnuradio.blks2impl.%s import *" % (f,)
--- /dev/null
+#
+# Copyright 2005,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.
+#
+
+include $(top_srcdir)/Makefile.common
+
+# EXTRA_DIST = run_tests.in
+# TESTS = run_tests
+
+grblkspythondir = $(grpythondir)/blks2impl
+
+grblkspython_PYTHON = \
+ __init__.py \
+ am_demod.py \
+ channel_model.py \
+ dbpsk.py \
+ dqpsk.py \
+ d8psk.py \
+ filterbank.py \
+ fm_demod.py \
+ fm_emph.py \
+ gmsk.py \
+ cpm.py \
+ nbfm_rx.py \
+ nbfm_tx.py \
+ ofdm.py \
+ ofdm_receiver.py \
+ ofdm_sync_fixed.py \
+ ofdm_sync_ml.py \
+ ofdm_sync_pnac.py \
+ ofdm_sync_pn.py \
+ pkt.py \
+ psk.py \
+ qam.py \
+ qam8.py \
+ qam16.py \
+ qam64.py \
+ qam256.py \
+ rational_resampler.py \
+ standard_squelch.py \
+ wfm_rcv.py \
+ wfm_rcv_pll.py \
+ wfm_tx.py
+
+
+noinst_PYTHON =
+
+CLEANFILES = *.pyc *.pyo
--- /dev/null
+# make this a package
--- /dev/null
+#
+# Copyright 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.
+#
+
+from gnuradio import gr, optfir
+
+class am_demod_cf(gr.hier_block2):
+ """
+ Generalized AM demodulation block with audio filtering.
+
+ This block demodulates a band-limited, complex down-converted AM
+ channel into the the original baseband signal, applying low pass
+ filtering to the audio output. It produces a float stream in the
+ range [-1.0, +1.0].
+
+ @param channel_rate: incoming sample rate of the AM baseband
+ @type sample_rate: integer
+ @param audio_decim: input to output decimation rate
+ @type audio_decim: integer
+ @param audio_pass: audio low pass filter passband frequency
+ @type audio_pass: float
+ @param audio_stop: audio low pass filter stop frequency
+ @type audio_stop: float
+ """
+ def __init__(self, channel_rate, audio_decim, audio_pass, audio_stop):
+ gr.hier_block2.__init__(self, "am_demod_cf",
+ gr.io_signature(1, 1, gr.sizeof_gr_complex), # Input signature
+ gr.io_signature(1, 1, gr.sizeof_float)) # Input signature
+
+ MAG = gr.complex_to_mag()
+ DCR = gr.add_const_ff(-1.0)
+
+ audio_taps = optfir.low_pass(0.5, # Filter gain
+ channel_rate, # Sample rate
+ audio_pass, # Audio passband
+ audio_stop, # Audio stopband
+ 0.1, # Passband ripple
+ 60) # Stopband attenuation
+ LPF = gr.fir_filter_fff(audio_decim, audio_taps)
+
+ self.connect(self, MAG, DCR, LPF, self)
+
+class demod_10k0a3e_cf(am_demod_cf):
+ """
+ AM demodulation block, 10 KHz channel.
+
+ This block demodulates an AM channel conformant to 10K0A3E emission
+ standards, such as broadcast band AM transmissions.
+
+ @param channel_rate: incoming sample rate of the AM baseband
+ @type sample_rate: integer
+ @param audio_decim: input to output decimation rate
+ @type audio_decim: integer
+ """
+ def __init__(self, channel_rate, audio_decim):
+ am_demod_cf.__init__(self, channel_rate, audio_decim,
+ 5000, # Audio passband
+ 5500) # Audio stopband
+
\ No newline at end of file
--- /dev/null
+#!/usr/bin/env python
+#
+# Copyright 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.
+#
+
+from gnuradio import gr
+
+class channel_model(gr.hier_block):
+ def __init__(self, fg, noise_voltage=0.0, frequency_offset=0.0, epsilon=1.0, taps=[1.0,0.0]):
+ ''' Creates a channel model that includes:
+ - AWGN noise power in terms of noise voltage
+ - A frequency offest in the channel in ratio
+ - A timing offset ratio to model clock difference (epsilon)
+ - Multipath taps
+ '''
+
+ print epsilon
+ self.timing_offset = gr.fractional_interpolator_cc(0, epsilon)
+
+ self.multipath = gr.fir_filter_ccc(1, taps)
+
+ self.noise_adder = gr.add_cc()
+ self.noise = gr.noise_source_c(gr.GR_GAUSSIAN,noise_voltage)
+ self.freq_offset = gr.sig_source_c(1, gr.GR_SIN_WAVE, frequency_offset, 1.0, 0.0)
+ self.mixer_offset = gr.multiply_cc()
+
+ fg.connect(self.timing_offset, self.multipath)
+ fg.connect(self.multipath, (self.mixer_offset,0))
+ fg.connect(self.freq_offset,(self.mixer_offset,1))
+ fg.connect(self.mixer_offset, (self.noise_adder,1))
+ fg.connect(self.noise, (self.noise_adder,0))
+
+ gr.hier_block.__init__(self, fg, self.timing_offset, self.noise_adder)
+
+ def set_noise_voltage(noise_voltage):
+ self.noise.set_amplitude(noise_voltage)
+
+ def set_frequency_offset(frequency_offset):
+ self.freq_offset.set_frequency(frequency_offset)
+
+ def set_taps(taps):
+ self.multipath.set_taps(taps)
--- /dev/null
+#
+# CPM modulation and demodulation.
+#
+#
+# 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
+
+from gnuradio import gr
+from gnuradio import modulation_utils
+from math import pi
+import numpy
+from pprint import pprint
+import inspect
+
+# default values (used in __init__ and add_options)
+_def_samples_per_symbol = 2
+_def_bits_per_symbol = 1
+_def_h_numerator = 1
+_def_h_denominator = 2
+_def_cpm_type = 0 # 0=CPFSK, 1=GMSK, 2=RC, 3=GENERAL
+_def_bt = 0.35
+_def_symbols_per_pulse = 1
+_def_generic_taps = numpy.empty(1)
+_def_verbose = False
+_def_log = False
+
+
+# /////////////////////////////////////////////////////////////////////////////
+# CPM modulator
+# /////////////////////////////////////////////////////////////////////////////
+
+class cpm_mod(gr.hier_block2):
+ def __init__(self,
+ samples_per_symbol=_def_samples_per_symbol,
+ bits_per_symbol=_def_bits_per_symbol,
+ h_numerator=_def_h_numerator,
+ h_denominator=_def_h_denominator,
+ cpm_type=_def_cpm_type,
+ bt=_def_bt,
+ symbols_per_pulse=_def_symbols_per_pulse,
+ generic_taps=_def_generic_taps,
+ verbose=_def_verbose,
+ log=_def_log):
+ """
+ Hierarchical block for Continuous Phase
+ modulation.
+
+ The input is a byte stream (unsigned char)
+ representing packed bits and the
+ output is the complex modulated signal at baseband.
+
+ See Proakis for definition of generic CPM signals:
+ s(t)=exp(j phi(t))
+ phi(t)= 2 pi h int_0^t f(t') dt'
+ f(t)=sum_k a_k g(t-kT)
+ (normalizing assumption: int_0^infty g(t) dt = 1/2)
+
+ @param samples_per_symbol: samples per baud >= 2
+ @type samples_per_symbol: integer
+ @param bits_per_symbol: bits per symbol
+ @type bits_per_symbol: integer
+ @param h_numerator: numerator of modulation index
+ @type h_numerator: integer
+ @param h_denominator: denominator of modulation index (numerator and denominator must be relative primes)
+ @type h_denominator: integer
+ @param cpm_type: supported types are: 0=CPFSK, 1=GMSK, 2=RC, 3=GENERAL
+ @type cpm_type: integer
+ @param bt: bandwidth symbol time product for GMSK
+ @type bt: float
+ @param symbols_per_pulse: shaping pulse duration in symbols
+ @type symbols_per_pulse: integer
+ @param generic_taps: define a generic CPM pulse shape (sum = samples_per_symbol/2)
+ @type generic_taps: array of floats
+
+ @param verbose: Print information about modulator?
+ @type verbose: bool
+ @param debug: Print modulation data to files?
+ @type debug: bool
+ """
+
+ gr.hier_block2.__init__("cpm_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._bits_per_symbol = bits_per_symbol
+ self._h_numerator = h_numerator
+ self._h_denominator = h_denominator
+ self._cpm_type = cpm_type
+ self._bt=bt
+ if cpm_type == 0 or cpm_type == 2 or cpm_type == 3: # CPFSK, RC, Generic
+ self._symbols_per_pulse = symbols_per_pulse
+ elif cpm_type == 1: # GMSK
+ self._symbols_per_pulse = 4
+ else:
+ raise TypeError, ("cpm_type must be an integer in {0,1,2,3}, is %r" % (cpm_type,))
+
+ self._generic_taps=numpy.array(generic_taps)
+
+ if not isinstance(samples_per_symbol, int) or samples_per_symbol < 2:
+ raise TypeError, ("samples_per_symbol must be an integer >= 2, is %r" % (samples_per_symbol,))
+
+ self.nsymbols = 2**bits_per_symbol
+ self.sym_alphabet=numpy.arange(-(self.nsymbols-1),self.nsymbols,2)
+
+
+ self.ntaps = self._symbols_per_pulse * samples_per_symbol
+ sensitivity = 2 * pi * h_numerator / h_denominator / samples_per_symbol
+
+ # Unpack Bytes into bits_per_symbol groups
+ self.B2s = gr.packed_to_unpacked_bb(bits_per_symbol,gr.GR_MSB_FIRST)
+
+
+ # Turn it into symmetric PAM data.
+ self.pam = gr.chunks_to_symbols_bf(self.sym_alphabet,1)
+
+ # Generate pulse (sum of taps = samples_per_symbol/2)
+ if cpm_type == 0: # CPFSK
+ self.taps= (1.0/self._symbols_per_pulse/2,) * self.ntaps
+ elif cpm_type == 1: # GMSK
+ gaussian_taps = gr.firdes.gaussian(
+ 1.0/2, # gain
+ samples_per_symbol, # symbol_rate
+ bt, # bandwidth * symbol time
+ self.ntaps # number of taps
+ )
+ sqwave = (1,) * samples_per_symbol # rectangular window
+ self.taps = numpy.convolve(numpy.array(gaussian_taps),numpy.array(sqwave))
+ elif cpm_type == 2: # Raised Cosine
+ # generalize it for arbitrary roll-off factor
+ self.taps = (1-numpy.cos(2*pi*numpy.arange(0,self.ntaps)/samples_per_symbol/self._symbols_per_pulse))/(2*self._symbols_per_pulse)
+ elif cpm_type == 3: # Generic CPM
+ self.taps = generic_taps
+ else:
+ raise TypeError, ("cpm_type must be an integer in {0,1,2,3}, is %r" % (cpm_type,))
+
+ self.filter = gr.interp_fir_filter_fff(samples_per_symbol, self.taps)
+
+ # FM modulation
+ self.fmmod = gr.frequency_modulator_fc(sensitivity)
+
+ if verbose:
+ self._print_verbage()
+
+ if log:
+ self._setup_logging()
+
+ # Connect
+ self.connect(self, self.B2s, self.pam, self.filter, self.fmmod, self)
+
+ #def samples_per_symbol(self):
+ #return self._samples_per_symbol
+
+ #def bits_per_symbol(self):
+ #return self._bits_per_symbol
+
+ #def h_numerator(self):
+ #return self._h_numerator
+
+ #def h_denominator(self):
+ #return self._h_denominator
+
+ #def cpm_type(self):
+ #return self._cpm_type
+
+ #def bt(self):
+ #return self._bt
+
+ #def symbols_per_pulse(self):
+ #return self._symbols_per_pulse
+
+
+ def _print_verbage(self):
+ print "Samples per symbol = %d" % self._samples_per_symbol
+ print "Bits per symbol = %d" % self._bits_per_symbol
+ print "h = " , self._h_numerator , " / " , self._h_denominator
+ print "Symbol alphabet = " , self.sym_alphabet
+ print "Symbols per pulse = %d" % self._symbols_per_pulse
+ print "taps = " , self.taps
+
+ print "CPM type = %d" % self._cpm_type
+ if self._cpm_type == 1:
+ print "Gaussian filter BT = %.2f" % self._bt
+
+
+ def _setup_logging(self):
+ print "Modulation logging turned on."
+ self.connect(self.B2s,
+ gr.file_sink(gr.sizeof_float, "symbols.dat"))
+ self.connect(self.pam,
+ gr.file_sink(gr.sizeof_float, "pam.dat"))
+ self.connect(self.filter,
+ gr.file_sink(gr.sizeof_float, "filter.dat"))
+ self.connect(self.fmmod,
+ gr.file_sink(gr.sizeof_gr_complex, "fmmod.dat"))
+
+
+ def add_options(parser):
+ """
+ Adds CPM modulation-specific options to the standard parser
+ """
+ parser.add_option("", "--bt", type="float", default=_def_bt,
+ help="set bandwidth-time product [default=%default] (GMSK)")
+ 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(cpm_mod.__init__,
+ ('self',), options)
+ extract_kwargs_from_options=staticmethod(extract_kwargs_from_options)
+
+
+
+# /////////////////////////////////////////////////////////////////////////////
+# CPM demodulator
+# /////////////////////////////////////////////////////////////////////////////
+#
+# Not yet implemented
+#
+
+
+
+#
+# Add these to the mod/demod registry
+#
+modulation_utils.add_type_1_mod('cpm', cpm_mod)
+#modulation_utils.add_type_1_demod('cpm', cpm_demod)
--- /dev/null
+#
+# 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 8PSK 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 = 3
+_def_excess_bw = 0.35
+_def_gray_code = True
+_def_verbose = False
+_def_log = False
+
+_def_costas_alpha = 0.175
+_def_gain_mu = 0.175
+_def_mu = 0.5
+_def_omega_relative_limit = 0.005
+
+
+# /////////////////////////////////////////////////////////////////////////////
+# D8PSK modulator
+# /////////////////////////////////////////////////////////////////////////////
+
+class d8psk_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, "d8psk_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 = 1
+ 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 3
+ bits_per_symbol = staticmethod(bits_per_symbol) # make it a static method. RTFM
+
+ def _print_verbage(self):
+ print "bits per symbol = %d" % self.bits_per_symbol()
+ print "Gray code = %s" % self._gray_code
+ print "RS 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 8PSK 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(d8psk_mod.__init__,
+ ('self',), options)
+ extract_kwargs_from_options=staticmethod(extract_kwargs_from_options)
+
+
+# /////////////////////////////////////////////////////////////////////////////
+# D8PSK demodulator
+#
+# Differentially coherent detection of differentially encoded 8psk
+# /////////////////////////////////////////////////////////////////////////////
+
+class d8psk_demod(gr.hier_block2):
+
+ def __init__(self,
+ samples_per_symbol=_def_samples_per_symbol,
+ excess_bw=_def_excess_bw,
+ costas_alpha=_def_costas_alpha,
+ gain_mu=_def_gain_mu,
+ mu=_def_mu,
+ omega_relative_limit=_def_omega_relative_limit,
+ 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 gain_mu: for M&M block
+ @type gain_mu: float
+ @param mu: for M&M block
+ @type mu: float
+ @param omega_relative_limit: for M&M block
+ @type omega_relative_limit: 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, "d8psk_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._mm_gain_mu = gain_mu
+ self._mm_mu = mu
+ self._mm_omega_relative_limit = omega_relative_limit
+ 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
+ scale = (1.0/16384.0)
+ self.pre_scaler = gr.multiply_const_cc(scale) # scale the signal from full-range to +-1
+ #self.agc = gr.agc_cc(1e-2, 1, 1, 100)
+ self.agc = gr.agc2_cc(1e-1, 1e-2, 1, 1, 100)
+ #self.agc = gr.feedforward_agc_cc(16, 1.0)
+
+ # RRC data filter
+ ntaps = 11 * samples_per_symbol
+ self.rrc_taps = gr.firdes.root_raised_cosine(
+ 1.0, # gain
+ 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(1, self.rrc_taps)
+
+ # symbol clock recovery
+ 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
+
+ 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)
+
+ # 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.pre_scaler, self.agc, self.rrc_filter, self.receiver,
+ 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 3
+ 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 "M&M mu: %.2f" % self._mm_mu
+ print "M&M mu gain: %.2e" % self._mm_gain_mu
+ print "M&M omega: %.2f" % self._mm_omega
+ print "M&M omega gain: %.2e" % self._mm_gain_omega
+ print "M&M omega limit: %.2f" % self._mm_omega_relative_limit
+
+
+ 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.receiver,
+ gr.file_sink(gr.sizeof_gr_complex, "rx_receiver.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-mu", type="float", default=_def_gain_mu,
+ help="set M&M symbol sync loop gain mu value [default=%default] (PSK)")
+ parser.add_option("", "--mu", type="float", default=_def_mu,
+ help="set M&M symbol sync loop mu value [default=%default] (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(
+ d8psk_demod.__init__, ('self',), options)
+ extract_kwargs_from_options=staticmethod(extract_kwargs_from_options)
+
+
+#
+# Add these to the mod/demod registry
+#
+# NOT READY TO BE USED YET -- ENABLE AT YOUR OWN RISK
+modulation_utils.add_type_1_mod('d8psk', d8psk_mod)
+modulation_utils.add_type_1_demod('d8psk', d8psk_demod)
--- /dev/null
+#
+# 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_gain_mu = None
+_def_mu = 0.5
+_def_omega_relative_limit = 0.005
+
+
+# /////////////////////////////////////////////////////////////////////////////
+# DBPSK modulator
+# /////////////////////////////////////////////////////////////////////////////
+
+class dbpsk_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(dbpsk_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 dbpsk_demod(gr.hier_block2):
+
+ def __init__(self,
+ samples_per_symbol=_def_samples_per_symbol,
+ excess_bw=_def_excess_bw,
+ costas_alpha=_def_costas_alpha,
+ gain_mu=_def_gain_mu,
+ mu=_def_mu,
+ omega_relative_limit=_def_omega_relative_limit,
+ 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_alphas: float
+ @param gain_mu: for M&M block
+ @type gain_mu: float
+ @param mu: for M&M block
+ @type mu: float
+ @param omega_relative_limit: for M&M block
+ @type omega_relative_limit: 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, "dbpsk_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._mm_gain_mu = gain_mu
+ self._mm_mu = mu
+ self._mm_omega_relative_limit = omega_relative_limit
+ 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
+ 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
+ self.rrc_taps = gr.firdes.root_raised_cosine(
+ 1.0, # gain
+ 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(1, self.rrc_taps)
+
+ # 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.025
+ fmax = 0.025
+
+ 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)
+
+ # 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 and Initialize base class
+ self.connect(self, self.pre_scaler, self.agc, self.rrc_filter, self.receiver,
+ 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: %.2e" % self._costas_alpha
+ print "Costas Loop beta: %.2e" % self._costas_beta
+ print "M&M mu: %.2f" % self._mm_mu
+ print "M&M mu gain: %.2e" % self._mm_gain_mu
+ print "M&M omega: %.2f" % self._mm_omega
+ print "M&M omega gain: %.2e" % self._mm_gain_omega
+ print "M&M omega limit: %.2f" % self._mm_omega_relative_limit
+
+ 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.receiver,
+ gr.file_sink(gr.sizeof_gr_complex, "rx_receiver.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-mu", type="float", default=_def_gain_mu,
+ help="set M&M symbol sync loop gain mu value [default=%default] (GMSK/PSK)")
+ parser.add_option("", "--mu", type="float", default=_def_mu,
+ help="set M&M symbol sync loop mu value [default=%default] (GMSK/PSK)")
+ parser.add_option("", "--omega-relative-limit", type="float", default=_def_omega_relative_limit,
+ help="M&M clock recovery omega relative limit [default=%default] (GMSK/PSK)")
+ 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(
+ dbpsk_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('dbpsk', dbpsk_mod)
+modulation_utils.add_type_1_demod('dbpsk', dbpsk_demod)
--- /dev/null
+#!/usr/bin/env python
+#
+# Copyright 2005 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.
+#
+
+"""
+Digital voice Tx and Rx using GSM 13kbit vocoder and GMSK.
+
+Runs channel at 32kbit/sec. Currently uses fake channel coding,
+but there's room for a rate 1/2 coder.
+"""
+
+from gnuradio import gr, gru
+from gnuradio.blksimpl.gmsk import gmsk_mod, gmsk_demod
+
+from gnuradio.vocoder import gsm_full_rate
+
+# Size of gsm full rate speech encoder output packet in bytes
+
+GSM_FRAME_SIZE = 33
+
+# Size of packet in bytes that we send to GMSK modulator:
+#
+# Target: 256kS/sec air rate.
+#
+# 256kS 1 sym 1 bit 1 byte 0.020 sec 80 bytes
+# ---- * ----- * ----- * ------ * --------- = --------
+# sec 8 S 1 sym 8 bits frame frame
+#
+# gr_simple_framer add 10 bytes of overhead.
+
+AIR_FRAME_SIZE = 70
+
+
+class digital_voice_tx(gr.hier_block):
+ """
+ Hierarchical block for digital voice tranmission.
+
+ The input is 8kS/sec floating point audio in the range [-1,+1]
+ The output is 256kS/sec GMSK modulated complex baseband signal in the range [-1,+1].
+ """
+ def __init__(self, fg):
+ samples_per_symbol = 8
+ symbol_rate = 32000
+ bt = 0.3 # Gaussian filter bandwidth * symbol time
+
+ src_scale = gr.multiply_const_ff(32767)
+ f2s = gr.float_to_short()
+ voice_coder = gsm_full_rate.encode_sp()
+
+ channel_coder = gr.fake_channel_encoder_pp(GSM_FRAME_SIZE, AIR_FRAME_SIZE)
+ p2s = gr.parallel_to_serial(gr.sizeof_char, AIR_FRAME_SIZE)
+
+ mod = gmsk_mod(fg, sps=samples_per_symbol,
+ symbol_rate=symbol_rate, bt=bt,
+ p_size=AIR_FRAME_SIZE)
+
+ fg.connect(src_scale, f2s, voice_coder, channel_coder, p2s, mod)
+ gr.hier_block.__init__(self, fg, src_scale, mod)
+
+
+class digital_voice_rx(gr.hier_block):
+ """
+ Hierarchical block for digital voice reception.
+
+ The input is 256kS/sec GMSK modulated complex baseband signal.
+ The output is 8kS/sec floating point audio in the range [-1,+1]
+ """
+ def __init__(self, fg):
+ samples_per_symbol = 8
+ symbol_rate = 32000
+
+ demod = gmsk_demod(fg, sps=samples_per_symbol,
+ symbol_rate=symbol_rate,
+ p_size=AIR_FRAME_SIZE)
+
+ s2p = gr.serial_to_parallel(gr.sizeof_char, AIR_FRAME_SIZE)
+ channel_decoder = gr.fake_channel_decoder_pp(AIR_FRAME_SIZE, GSM_FRAME_SIZE)
+
+ voice_decoder = gsm_full_rate.decode_ps()
+ s2f = gr.short_to_float ()
+ sink_scale = gr.multiply_const_ff(1.0/32767.)
+
+ fg.connect(demod, s2p, channel_decoder, voice_decoder, s2f, sink_scale)
+ gr.hier_block.__init__(self, fg, demod, sink_scale)
--- /dev/null
+#
+# 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 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.15
+_def_gain_mu = None
+_def_mu = 0.5
+_def_omega_relative_limit = 0.005
+
+
+# /////////////////////////////////////////////////////////////////////////////
+# DQPSK modulator
+# /////////////////////////////////////////////////////////////////////////////
+
+class dqpsk_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, "dqpsk_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(dqpsk_mod.__init__,
+ ('self',), options)
+ extract_kwargs_from_options=staticmethod(extract_kwargs_from_options)
+
+
+# /////////////////////////////////////////////////////////////////////////////
+# DQPSK demodulator
+#
+# Differentially coherent detection of differentially encoded qpsk
+# /////////////////////////////////////////////////////////////////////////////
+
+class dqpsk_demod(gr.hier_block2):
+
+ def __init__(self,
+ samples_per_symbol=_def_samples_per_symbol,
+ excess_bw=_def_excess_bw,
+ costas_alpha=_def_costas_alpha,
+ gain_mu=_def_gain_mu,
+ mu=_def_mu,
+ omega_relative_limit=_def_omega_relative_limit,
+ 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 gain_mu: for M&M block
+ @type gain_mu: float
+ @param mu: for M&M block
+ @type mu: float
+ @param omega_relative_limit: for M&M block
+ @type omega_relative_limit: 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, "dqpsk_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._mm_gain_mu = gain_mu
+ self._mm_mu = mu
+ self._mm_omega_relative_limit = omega_relative_limit
+ 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
+ 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
+ self.rrc_taps = gr.firdes.root_raised_cosine(
+ 1.0, # gain
+ 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(1, self.rrc_taps)
+
+ if not self._mm_gain_mu:
+ sbs_to_mm = {2: 0.050, 3: 0.075, 4: 0.11, 5: 0.125, 6: 0.15, 7: 0.15}
+ self._mm_gain_mu = sbs_to_mm[samples_per_symbol]
+
+ 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
+
+ self.receiver=gr.mpsk_receiver_cc(arity, pi/4.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)
+
+ # 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 & Initialize base class
+ self.connect(self, self.pre_scaler, self.agc, self.rrc_filter, self.receiver,
+ 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 "M&M mu: %.2f" % self._mm_mu
+ print "M&M mu gain: %.2e" % self._mm_gain_mu
+ print "M&M omega: %.2f" % self._mm_omega
+ print "M&M omega gain: %.2e" % self._mm_gain_omega
+ print "M&M omega limit: %.2f" % self._mm_omega_relative_limit
+
+ 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.receiver,
+ gr.file_sink(gr.sizeof_gr_complex, "rx_receiver.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-mu", type="float", default=_def_gain_mu,
+ help="set M&M symbol sync loop gain mu value [default=%default] (PSK)")
+ parser.add_option("", "--mu", type="float", default=_def_mu,
+ help="set M&M symbol sync loop mu value [default=%default] (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(
+ dqpsk_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('dqpsk', dqpsk_mod)
+modulation_utils.add_type_1_demod('dqpsk', dqpsk_demod)
--- /dev/null
+#
+# Copyright 2005,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.
+#
+
+import sys
+from gnuradio import gr, gru
+
+def _generate_synthesis_taps(mpoints):
+ return [] # FIXME
+
+
+def _split_taps(taps, mpoints):
+ assert (len(taps) % mpoints) == 0
+ result = [list() for x in range(mpoints)]
+ for i in xrange(len(taps)):
+ (result[i % mpoints]).append(taps[i])
+ return [tuple(x) for x in result]
+
+
+class synthesis_filterbank(gr.hier_block2):
+ """
+ Uniformly modulated polyphase DFT filter bank: synthesis
+
+ See http://cnx.rice.edu/content/m10424/latest
+ """
+ def __init__(self, mpoints, taps=None):
+ """
+ Takes M complex streams in, produces single complex stream out
+ that runs at M times the input sample rate
+
+ @param mpoints: number of freq bins/interpolation factor/subbands
+ @param taps: filter taps for subband filter
+
+ The channel spacing is equal to the input sample rate.
+ The total bandwidth and output sample rate are equal the input
+ sample rate * nchannels.
+
+ Output stream to frequency mapping:
+
+ channel zero is at zero frequency.
+
+ if mpoints is odd:
+
+ Channels with increasing positive frequencies come from
+ channels 1 through (N-1)/2.
+
+ Channel (N+1)/2 is the maximum negative frequency, and
+ frequency increases through N-1 which is one channel lower
+ than the zero frequency.
+
+ if mpoints is even:
+
+ Channels with increasing positive frequencies come from
+ channels 1 through (N/2)-1.
+
+ Channel (N/2) is evenly split between the max positive and
+ negative bins.
+
+ Channel (N/2)+1 is the maximum negative frequency, and
+ frequency increases through N-1 which is one channel lower
+ than the zero frequency.
+
+ Channels near the frequency extremes end up getting cut
+ off by subsequent filters and therefore have diminished
+ utility.
+ """
+ item_size = gr.sizeof_gr_complex
+ gr.hier_block2.__init__(self, "synthesis_filterbank",
+ gr.io_signature(mpoints, mpoints, item_size), # Input signature
+ gr.io_signature(1, 1, item_size)) # Output signature
+
+
+ if taps is None:
+ taps = _generate_synthesis_taps(mpoints)
+
+ # pad taps to multiple of mpoints
+ r = len(taps) % mpoints
+ if r != 0:
+ taps = taps + (mpoints - r) * (0,)
+
+ # split in mpoints separate set of taps
+ sub_taps = _split_taps(taps, mpoints)
+
+ self.ss2v = gr.streams_to_vector(item_size, mpoints)
+ self.ifft = gr.fft_vcc(mpoints, False, [])
+ self.v2ss = gr.vector_to_streams(item_size, mpoints)
+ # mpoints filters go in here...
+ self.ss2s = gr.streams_to_stream(item_size, mpoints)
+
+ for i in range(mpoints):
+ self.connect((self, i), (self.ss2v, i))
+
+ self.connect(self.ss2v, self.ifft, self.v2ss, self)
+
+ # build mpoints fir filters...
+ for i in range(mpoints):
+ f = gr.fft_filter_ccc(1, sub_taps[i])
+ self.connect((self.v2ss, i), f)
+ self.connect(f, (self.ss2s, i))
+
+
+class analysis_filterbank(gr.hier_block2):
+ """
+ Uniformly modulated polyphase DFT filter bank: analysis
+
+ See http://cnx.rice.edu/content/m10424/latest
+ """
+ def __init__(self, mpoints, taps=None):
+ """
+ Takes 1 complex stream in, produces M complex streams out
+ that runs at 1/M times the input sample rate
+
+ @param mpoints: number of freq bins/interpolation factor/subbands
+ @param taps: filter taps for subband filter
+
+ Same channel to frequency mapping as described above.
+ """
+ item_size = gr.sizeof_gr_complex
+ gr.hier_block2.__init__(self, "analysis_filterbank",
+ gr.io_signature(1, 1, item_size), # Input signature
+ gr.io_signature(mpoints, mpoints, item_size)) # Output signature
+
+ if taps is None:
+ taps = _generate_synthesis_taps(mpoints)
+
+ # pad taps to multiple of mpoints
+ r = len(taps) % mpoints
+ if r != 0:
+ taps = taps + (mpoints - r) * (0,)
+
+ # split in mpoints separate set of taps
+ sub_taps = _split_taps(taps, mpoints)
+
+ # print >> sys.stderr, "mpoints =", mpoints, "len(sub_taps) =", len(sub_taps)
+
+ self.s2ss = gr.stream_to_streams(item_size, mpoints)
+ # filters here
+ self.ss2v = gr.streams_to_vector(item_size, mpoints)
+ self.fft = gr.fft_vcc(mpoints, True, [])
+ self.v2ss = gr.vector_to_streams(item_size, mpoints)
+
+ self.connect(self, self.s2ss)
+
+ # build mpoints fir filters...
+ for i in range(mpoints):
+ f = gr.fft_filter_ccc(1, sub_taps[mpoints-i-1])
+ self.connect((self.s2ss, i), f)
+ self.connect(f, (self.ss2v, i))
+ self.connect((self.v2ss, i), (self, i))
+
+ self.connect(self.ss2v, self.fft, self.v2ss)
--- /dev/null
+#
+# Copyright 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.
+#
+
+from gnuradio import gr, optfir
+from gnuradio.blks2impl.fm_emph import fm_deemph
+from math import pi
+
+class fm_demod_cf(gr.hier_block2):
+ """
+ Generalized FM demodulation block with deemphasis and audio
+ filtering.
+
+ This block demodulates a band-limited, complex down-converted FM
+ channel into the the original baseband signal, optionally applying
+ deemphasis. Low pass filtering is done on the resultant signal. It
+ produces an output float strem in the range of [-1.0, +1.0].
+
+ @param channel_rate: incoming sample rate of the FM baseband
+ @type sample_rate: integer
+ @param deviation: maximum FM deviation (default = 5000)
+ @type deviation: float
+ @param audio_decim: input to output decimation rate
+ @type audio_decim: integer
+ @param audio_pass: audio low pass filter passband frequency
+ @type audio_pass: float
+ @param audio_stop: audio low pass filter stop frequency
+ @type audio_stop: float
+ @param gain: gain applied to audio output (default = 1.0)
+ @type gain: float
+ @param tau: deemphasis time constant (default = 75e-6), specify 'None'
+ to prevent deemphasis
+ """
+ def __init__(self, channel_rate, audio_decim, deviation,
+ audio_pass, audio_stop, gain=1.0, tau=75e-6):
+ gr.hier_block2.__init__(self, "fm_demod_cf",
+ gr.io_signature(1, 1, gr.sizeof_gr_complex), # Input signature
+ gr.io_signature(1, 1, gr.sizeof_float)) # Output signature
+
+ k = channel_rate/(2*pi*deviation)
+ QUAD = gr.quadrature_demod_cf(k)
+
+ audio_taps = optfir.low_pass(gain, # Filter gain
+ channel_rate, # Sample rate
+ audio_pass, # Audio passband
+ audio_stop, # Audio stopband
+ 0.1, # Passband ripple
+ 60) # Stopband attenuation
+ LPF = gr.fir_filter_fff(audio_decim, audio_taps)
+
+ if tau is not None:
+ DEEMPH = fm_deemph(channel_rate, tau)
+ self.connect(self, QUAD, DEEMPH, LPF, self)
+ else:
+ self.connect(self, QUAD, LPF, self)
+
+class demod_20k0f3e_cf(fm_demod_cf):
+ """
+ NBFM demodulation block, 20 KHz channels
+
+ This block demodulates a complex, downconverted, narrowband FM
+ channel conforming to 20K0F3E emission standards, outputting
+ floats in the range [-1.0, +1.0].
+
+ @param sample_rate: incoming sample rate of the FM baseband
+ @type sample_rate: integer
+ @param audio_decim: input to output decimation rate
+ @type audio_decim: integer
+ """
+ def __init__(self, channel_rate, audio_decim):
+ fm_demod_cf.__init__(self, channel_rate, audio_decim,
+ 5000, # Deviation
+ 3000, # Audio passband frequency
+ 4000) # Audio stopband frequency
+
+class demod_200kf3e_cf(fm_demod_cf):
+ """
+ WFM demodulation block, mono.
+
+ This block demodulates a complex, downconverted, wideband FM
+ channel conforming to 200KF3E emission standards, outputting
+ floats in the range [-1.0, +1.0].
+
+ @param sample_rate: incoming sample rate of the FM baseband
+ @type sample_rate: integer
+ @param audio_decim: input to output decimation rate
+ @type audio_decim: integer
+ """
+ def __init__(self, channel_rate, audio_decim):
+ fm_demod_cf.__init__(self, channel_rate, audio_decim,
+ 75000, # Deviation
+ 15000, # Audio passband
+ 16000, # Audio stopband
+ 20.0) # Audio gain
--- /dev/null
+#
+# Copyright 2005,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.
+#
+
+from gnuradio import gr
+import math
+
+
+#
+# 1
+# H(s) = -------
+# 1 + s
+#
+# tau is the RC time constant.
+# critical frequency: w_p = 1/tau
+#
+# We prewarp and use the bilinear z-transform to get our IIR coefficients.
+# See "Digital Signal Processing: A Practical Approach" by Ifeachor and Jervis
+#
+
+class fm_deemph(gr.hier_block2):
+ """
+ FM Deemphasis IIR filter.
+ """
+
+
+ def __init__(self, fs, tau=75e-6):
+ """
+ @param fs: sampling frequency in Hz
+ @type fs: float
+ @param tau: Time constant in seconds (75us in US, 50us in EUR)
+ @type tau: float
+ """
+ gr.hier_block2.__init__(self, "fm_deemph",
+ gr.io_signature(1, 1, gr.sizeof_float), # Input signature
+ gr.io_signature(1, 1, gr.sizeof_float)) # Output signature
+
+ w_p = 1/tau
+ w_pp = math.tan (w_p / (fs * 2)) # prewarped analog freq
+
+ a1 = (w_pp - 1)/(w_pp + 1)
+ b0 = w_pp/(1 + w_pp)
+ b1 = b0
+
+ btaps = [b0, b1]
+ ataps = [1, a1]
+
+ if 0:
+ print "btaps =", btaps
+ print "ataps =", ataps
+ global plot1
+ plot1 = gru.gnuplot_freqz (gru.freqz (btaps, ataps), fs, True)
+
+ deemph = gr.iir_filter_ffd(btaps, ataps)
+ self.connect(self, deemph, self)
+
+#
+# 1 + s*t1
+# H(s) = ----------
+# 1 + s*t2
+#
+# I think this is the right transfer function.
+#
+#
+# This fine ASCII rendition is based on Figure 5-15
+# in "Digital and Analog Communication Systems", Leon W. Couch II
+#
+#
+# R1
+# +-----||------+
+# | |
+# o------+ +-----+--------o
+# | C1 | |
+# +----/\/\/\/--+ \
+# /
+# \ R2
+# /
+# \
+# |
+# o--------------------------+--------o
+#
+# f1 = 1/(2*pi*t1) = 1/(2*pi*R1*C)
+#
+# 1 R1 + R2
+# f2 = ------- = ------------
+# 2*pi*t2 2*pi*R1*R2*C
+#
+# t1 is 75us in US, 50us in EUR
+# f2 should be higher than our audio bandwidth.
+#
+#
+# The Bode plot looks like this:
+#
+#
+# /----------------
+# /
+# / <-- slope = 20dB/decade
+# /
+# -------------/
+# f1 f2
+#
+# We prewarp and use the bilinear z-transform to get our IIR coefficients.
+# See "Digital Signal Processing: A Practical Approach" by Ifeachor and Jervis
+#
+
+class fm_preemph(gr.hier_block2):
+ """
+ FM Preemphasis IIR filter.
+ """
+ def __init__(self, fs, tau=75e-6):
+ """
+ @param fs: sampling frequency in Hz
+ @type fs: float
+ @param tau: Time constant in seconds (75us in US, 50us in EUR)
+ @type tau: float
+ """
+
+ gr.hier_block2.__init__(self, "fm_deemph",
+ gr.io_signature(1, 1, gr.sizeof_float), # Input signature
+ gr.io_signature(1, 1, gr.sizeof_float)) # Output signature
+
+ # FIXME make this compute the right answer
+
+ btaps = [1]
+ ataps = [1]
+
+ if 0:
+ print "btaps =", btaps
+ print "ataps =", ataps
+ global plot2
+ plot2 = gru.gnuplot_freqz (gru.freqz (btaps, ataps), fs, True)
+
+ preemph = gr.iir_filter_ffd(btaps, ataps)
+ self.connect(self, preemph, self)
--- /dev/null
+#
+# GMSK modulation and demodulation.
+#
+#
+# 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
+
+from gnuradio import gr
+from gnuradio import modulation_utils
+from math import pi
+import numpy
+from pprint import pprint
+import inspect
+
+# default values (used in __init__ and add_options)
+_def_samples_per_symbol = 2
+_def_bt = 0.35
+_def_verbose = False
+_def_log = False
+
+_def_gain_mu = None
+_def_mu = 0.5
+_def_freq_error = 0.0
+_def_omega_relative_limit = 0.005
+
+
+# /////////////////////////////////////////////////////////////////////////////
+# GMSK modulator
+# /////////////////////////////////////////////////////////////////////////////
+
+class gmsk_mod(gr.hier_block2):
+
+ def __init__(self,
+ samples_per_symbol=_def_samples_per_symbol,
+ bt=_def_bt,
+ verbose=_def_verbose,
+ log=_def_log):
+ """
+ Hierarchical block for Gaussian Minimum Shift Key (GMSK)
+ 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 bt: Gaussian filter bandwidth * symbol time
+ @type bt: float
+ @param verbose: Print information about modulator?
+ @type verbose: bool
+ @param debug: Print modualtion data to files?
+ @type debug: bool
+ """
+
+ gr.hier_block2.__init__(self, "gmsk_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._bt = bt
+
+ if not isinstance(samples_per_symbol, int) or samples_per_symbol < 2:
+ raise TypeError, ("samples_per_symbol must be an integer >= 2, is %r" % (samples_per_symbol,))
+
+ ntaps = 4 * samples_per_symbol # up to 3 bits in filter at once
+ sensitivity = (pi / 2) / samples_per_symbol # phase change per bit = pi / 2
+
+ # Turn it into NRZ data.
+ self.nrz = gr.bytes_to_syms()
+
+ # Form Gaussian filter
+ # Generate Gaussian response (Needs to be convolved with window below).
+ self.gaussian_taps = gr.firdes.gaussian(
+ 1, # gain
+ samples_per_symbol, # symbol_rate
+ bt, # bandwidth * symbol time
+ ntaps # number of taps
+ )
+
+ self.sqwave = (1,) * samples_per_symbol # rectangular window
+ self.taps = numpy.convolve(numpy.array(self.gaussian_taps),numpy.array(self.sqwave))
+ self.gaussian_filter = gr.interp_fir_filter_fff(samples_per_symbol, self.taps)
+
+ # FM modulation
+ self.fmmod = gr.frequency_modulator_fc(sensitivity)
+
+ if verbose:
+ self._print_verbage()
+
+ if log:
+ self._setup_logging()
+
+ # Connect & Initialize base class
+ self.connect(self, self.nrz, self.gaussian_filter, self.fmmod, 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.
+
+
+ def _print_verbage(self):
+ print "bits per symbol = %d" % self.bits_per_symbol()
+ print "Gaussian filter bt = %.2f" % self._bt
+
+
+ def _setup_logging(self):
+ print "Modulation logging turned on."
+ self.connect(self.nrz,
+ gr.file_sink(gr.sizeof_float, "nrz.dat"))
+ self.connect(self.gaussian_filter,
+ gr.file_sink(gr.sizeof_float, "gaussian_filter.dat"))
+ self.connect(self.fmmod,
+ gr.file_sink(gr.sizeof_gr_complex, "fmmod.dat"))
+
+
+ def add_options(parser):
+ """
+ Adds GMSK modulation-specific options to the standard parser
+ """
+ parser.add_option("", "--bt", type="float", default=_def_bt,
+ help="set bandwidth-time product [default=%default] (GMSK)")
+ add_options=staticmethod(add_options)
+
+
+ def extract_kwargs_from_options(options):
+ """
+ Given command line options, create dictionary suitable for passing to __init__
+ """
+ return modulation_utils.extract_kwargs_from_options(gmsk_mod.__init__,
+ ('self',), options)
+ extract_kwargs_from_options=staticmethod(extract_kwargs_from_options)
+
+
+
+# /////////////////////////////////////////////////////////////////////////////
+# GMSK demodulator
+# /////////////////////////////////////////////////////////////////////////////
+
+class gmsk_demod(gr.hier_block2):
+
+ def __init__(self,
+ samples_per_symbol=_def_samples_per_symbol,
+ gain_mu=_def_gain_mu,
+ mu=_def_mu,
+ omega_relative_limit=_def_omega_relative_limit,
+ freq_error=_def_freq_error,
+ verbose=_def_verbose,
+ log=_def_log):
+ """
+ Hierarchical block for Gaussian Minimum Shift Key (GMSK)
+ demodulation.
+
+ The input is the complex modulated signal at baseband.
+ The output is a stream of bits packed 1 bit per byte (the LSB)
+
+ @param samples_per_symbol: samples per baud
+ @type samples_per_symbol: integer
+ @param verbose: Print information about modulator?
+ @type verbose: bool
+ @param log: Print modualtion data to files?
+ @type log: bool
+
+ Clock recovery parameters. These all have reasonble defaults.
+
+ @param gain_mu: controls rate of mu adjustment
+ @type gain_mu: float
+ @param mu: fractional delay [0.0, 1.0]
+ @type mu: float
+ @param omega_relative_limit: sets max variation in omega
+ @type omega_relative_limit: float, typically 0.000200 (200 ppm)
+ @param freq_error: bit rate error as a fraction
+ @param float
+ """
+
+ gr.hier_block2.__init__(self, "gmsk_demod",
+ 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._gain_mu = gain_mu
+ self._mu = mu
+ self._omega_relative_limit = omega_relative_limit
+ self._freq_error = freq_error
+
+ if samples_per_symbol < 2:
+ raise TypeError, "samples_per_symbol >= 2, is %f" % samples_per_symbol
+
+ self._omega = samples_per_symbol*(1+self._freq_error)
+
+ if not self._gain_mu:
+ self._gain_mu = 0.175
+
+ self._gain_omega = .25 * self._gain_mu * self._gain_mu # critically damped
+
+ # Demodulate FM
+ sensitivity = (pi / 2) / samples_per_symbol
+ self.fmdemod = gr.quadrature_demod_cf(1.0 / sensitivity)
+
+ # the clock recovery block tracks the symbol clock and resamples as needed.
+ # the output of the block is a stream of soft symbols (float)
+ self.clock_recovery = gr.clock_recovery_mm_ff(self._omega, self._gain_omega,
+ self._mu, self._gain_mu,
+ self._omega_relative_limit)
+
+ # slice the floats at 0, outputting 1 bit (the LSB of the output byte) per sample
+ self.slicer = gr.binary_slicer_fb()
+
+ if verbose:
+ self._print_verbage()
+
+ if log:
+ self._setup_logging()
+
+ # Connect & Initialize base class
+ self.connect(self, self.fmdemod, self.clock_recovery, self.slicer, 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.
+
+
+ def _print_verbage(self):
+ print "bits per symbol = %d" % self.bits_per_symbol()
+ print "M&M clock recovery omega = %f" % self._omega
+ print "M&M clock recovery gain mu = %f" % self._gain_mu
+ print "M&M clock recovery mu = %f" % self._mu
+ print "M&M clock recovery omega rel. limit = %f" % self._omega_relative_limit
+ print "frequency error = %f" % self._freq_error
+
+
+ def _setup_logging(self):
+ print "Demodulation logging turned on."
+ self.connect(self.fmdemod,
+ gr.file_sink(gr.sizeof_float, "fmdemod.dat"))
+ self.connect(self.clock_recovery,
+ gr.file_sink(gr.sizeof_float, "clock_recovery.dat"))
+ self.connect(self.slicer,
+ gr.file_sink(gr.sizeof_char, "slicer.dat"))
+
+ def add_options(parser):
+ """
+ Adds GMSK demodulation-specific options to the standard parser
+ """
+ parser.add_option("", "--gain-mu", type="float", default=_def_gain_mu,
+ help="M&M clock recovery gain mu [default=%default] (GMSK/PSK)")
+ parser.add_option("", "--mu", type="float", default=_def_mu,
+ help="M&M clock recovery mu [default=%default] (GMSK/PSK)")
+ parser.add_option("", "--omega-relative-limit", type="float", default=_def_omega_relative_limit,
+ help="M&M clock recovery omega relative limit [default=%default] (GMSK/PSK)")
+ parser.add_option("", "--freq-error", type="float", default=_def_freq_error,
+ help="M&M clock recovery frequency error [default=%default] (GMSK)")
+ add_options=staticmethod(add_options)
+
+ def extract_kwargs_from_options(options):
+ """
+ Given command line options, create dictionary suitable for passing to __init__
+ """
+ return modulation_utils.extract_kwargs_from_options(gmsk_demod.__init__,
+ ('self',), options)
+ extract_kwargs_from_options=staticmethod(extract_kwargs_from_options)
+
+
+#
+# Add these to the mod/demod registry
+#
+modulation_utils.add_type_1_mod('gmsk', gmsk_mod)
+modulation_utils.add_type_1_demod('gmsk', gmsk_demod)
--- /dev/null
+#
+# Copyright 2005 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.
+#
+
+import math
+from gnuradio import gr, optfir
+from gnuradio.blks2impl.fm_emph import fm_deemph
+#from gnuradio.blks2impl.standard_squelch import standard_squelch
+
+class nbfm_rx(gr.hier_block2):
+ def __init__(self, audio_rate, quad_rate, tau=75e-6, max_dev=5e3):
+ """
+ Narrow Band FM Receiver.
+
+ Takes a single complex baseband input stream and produces a single
+ float output stream of audio sample in the range [-1, +1].
+
+ @param audio_rate: sample rate of audio stream, >= 16k
+ @type audio_rate: integer
+ @param quad_rate: sample rate of output stream
+ @type quad_rate: integer
+ @param tau: preemphasis time constant (default 75e-6)
+ @type tau: float
+ @param max_dev: maximum deviation in Hz (default 5e3)
+ @type max_dev: float
+
+ quad_rate must be an integer multiple of audio_rate.
+
+ Exported sub-blocks (attributes):
+ squelch
+ quad_demod
+ deemph
+ audio_filter
+ """
+
+ gr.hier_block2.__init__(self, "nbfm_rx",
+ gr.io_signature(1, 1, gr.sizeof_gr_complex), # Input signature
+ gr.io_signature(1, 1, gr.sizeof_float)) # Output signature
+
+ # FIXME audio_rate and quad_rate ought to be exact rationals
+ audio_rate = int(audio_rate)
+ quad_rate = int(quad_rate)
+
+ if quad_rate % audio_rate != 0:
+ raise ValueError, "quad_rate is not an integer multiple of audio_rate"
+
+ squelch_threshold = 20 # dB
+ #self.squelch = gr.simple_squelch_cc(squelch_threshold, 0.001)
+
+ # FM Demodulator input: complex; output: float
+ k = quad_rate/(2*math.pi*max_dev)
+ self.quad_demod = gr.quadrature_demod_cf(k)
+
+ # FM Deemphasis IIR filter
+ self.deemph = fm_deemph (quad_rate, tau=tau)
+
+ # compute FIR taps for audio filter
+ audio_decim = quad_rate // audio_rate
+ audio_taps = gr.firdes.low_pass (1.0, # gain
+ quad_rate, # sampling rate
+ 4.5e3, # Audio LPF cutoff
+ 2.5e3, # Transition band
+ gr.firdes.WIN_HAMMING) # filter type
+
+ print "len(audio_taps) =", len(audio_taps)
+
+ # Decimating audio filter
+ # input: float; output: float; taps: float
+ self.audio_filter = gr.fir_filter_fff(audio_decim, audio_taps)
+
+ self.connect(self, self.quad_demod, self.deemph, self.audio_filter, self)
--- /dev/null
+#
+# Copyright 2005 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.
+#
+
+import math
+from gnuradio import gr, optfir
+from gnuradio.blks2impl.fm_emph import fm_preemph
+
+#from gnuradio import ctcss
+
+class nbfm_tx(gr.hier_block2):
+ def __init__(self, audio_rate, quad_rate, tau=75e-6, max_dev=5e3):
+ """
+ Narrow Band FM Transmitter.
+
+ Takes a single float input stream of audio samples in the range [-1,+1]
+ and produces a single FM modulated complex baseband output.
+
+ @param audio_rate: sample rate of audio stream, >= 16k
+ @type audio_rate: integer
+ @param quad_rate: sample rate of output stream
+ @type quad_rate: integer
+ @param tau: preemphasis time constant (default 75e-6)
+ @type tau: float
+ @param max_dev: maximum deviation in Hz (default 5e3)
+ @type max_dev: float
+
+ quad_rate must be an integer multiple of audio_rate.
+ """
+
+ gr.hier_block2.__init__(self, "nbfm_tx",
+ gr.io_signature(1, 1, gr.sizeof_float), # Input signature
+ gr.io_signature(1, 1, gr.sizeof_gr_complex)) # Output signature
+
+ # FIXME audio_rate and quad_rate ought to be exact rationals
+ audio_rate = int(audio_rate)
+ quad_rate = int(quad_rate)
+
+ if quad_rate % audio_rate != 0:
+ raise ValueError, "quad_rate is not an integer multiple of audio_rate"
+
+
+ do_interp = audio_rate != quad_rate
+
+ if do_interp:
+ interp_factor = quad_rate / audio_rate
+ interp_taps = optfir.low_pass (interp_factor, # gain
+ quad_rate, # Fs
+ 4500, # passband cutoff
+ 7000, # stopband cutoff
+ 0.1, # passband ripple dB
+ 40) # stopband atten dB
+
+ #print "len(interp_taps) =", len(interp_taps)
+ self.interpolator = gr.interp_fir_filter_fff (interp_factor, interp_taps)
+
+ self.preemph = fm_preemph (quad_rate, tau=tau)
+
+ k = 2 * math.pi * max_dev / quad_rate
+ self.modulator = gr.frequency_modulator_fc (k)
+
+ if do_interp:
+ self.connect (self, self.interpolator, self.preemph, self.modulator, self)
+ else:
+ self.connect(self, self.preemph, self.modulator, self)
+
+
+class ctcss_gen_f(gr.hier_block2):
+ def __init__(self, sample_rate, tone_freq):
+ gr.hier_block2.__init__(self, "ctcss_gen_f",
+ gr.io_signature(0, 0, 0), # Input signature
+ gr.io_signature(1, 1, gr.sizeof_float)) # Output signature
+
+ self.plgen = gr.sig_source_f(sample_rate, gr.GR_SIN_WAVE, tone_freq, 0.1, 0.0)
+ self.connect(self.plgen, self)
--- /dev/null
+
+#
+# Copyright 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.
+#
+
+import math
+from numpy import fft
+from gnuradio import gr, ofdm_packet_utils
+import gnuradio.gr.gr_threading as _threading
+import psk, qam
+
+from gnuradio.blksimpl.ofdm_receiver import ofdm_receiver
+
+
+# /////////////////////////////////////////////////////////////////////////////
+# mod/demod with packets as i/o
+# /////////////////////////////////////////////////////////////////////////////
+
+class ofdm_mod(gr.hier_block):
+ """
+ Modulates an OFDM stream. Based on the options fft_length, occupied_tones, and
+ cp_length, this block creates OFDM symbols using a specified modulation option.
+
+ Send packets by calling send_pkt
+ """
+ def __init__(self, fg, options, msgq_limit=2, pad_for_usrp=True):
+ """
+ Hierarchical block for sending packets
+
+ Packets to be sent are enqueued by calling send_pkt.
+ The output is the complex modulated signal at baseband.
+
+ @param fg: flow graph
+ @type fg: flow graph
+ @param options: pass modulation options from higher layers (fft length, occupied tones, etc.)
+ @param msgq_limit: maximum number of messages in message queue
+ @type msgq_limit: int
+ @param pad_for_usrp: If true, packets are padded such that they end up a multiple of 128 samples
+ """
+
+ self._pad_for_usrp = pad_for_usrp
+ self._modulation = options.modulation
+ self._fft_length = options.fft_length
+ self._occupied_tones = options.occupied_tones
+ self._cp_length = options.cp_length
+
+ win = [] #[1 for i in range(self._fft_length)]
+
+ # Use freq domain to get doubled-up known symbol for correlation in time domain
+ zeros_on_left = int(math.ceil((self._fft_length - self._occupied_tones)/2.0))
+ ksfreq = known_symbols_4512_3[0:self._occupied_tones]
+ for i in range(len(ksfreq)):
+ if((zeros_on_left + i) & 1):
+ ksfreq[i] = 0
+
+ # hard-coded known symbols
+ preambles = (ksfreq,
+ known_symbols_4512_1[0:self._occupied_tones],
+ known_symbols_4512_2[0:self._occupied_tones])
+
+ padded_preambles = list()
+ for pre in preambles:
+ padded = self._fft_length*[0,]
+ padded[zeros_on_left : zeros_on_left + self._occupied_tones] = pre
+ padded_preambles.append(padded)
+
+ symbol_length = options.fft_length + options.cp_length
+
+ mods = {"bpsk": 2, "qpsk": 4, "8psk": 8, "qam8": 8, "qam16": 16, "qam64": 64, "qam256": 256}
+ arity = mods[self._modulation]
+
+ rot = 1
+ if self._modulation == "qpsk":
+ rot = (0.707+0.707j)
+
+ if(self._modulation.find("psk") >= 0):
+ rotated_const = map(lambda pt: pt * rot, psk.gray_constellation[arity])
+ elif(self._modulation.find("qam") >= 0):
+ rotated_const = map(lambda pt: pt * rot, qam.constellation[arity])
+ #print rotated_const
+ self._pkt_input = gr.ofdm_mapper_bcv(rotated_const, msgq_limit,
+ options.occupied_tones, options.fft_length)
+
+ self.preambles = gr.ofdm_insert_preamble(self._fft_length, padded_preambles)
+ self.ifft = gr.fft_vcc(self._fft_length, False, win, True)
+ self.cp_adder = gr.ofdm_cyclic_prefixer(self._fft_length, symbol_length)
+ self.scale = gr.multiply_const_cc(1.0 / math.sqrt(self._fft_length))
+
+ fg.connect((self._pkt_input, 0), (self.preambles, 0))
+ fg.connect((self._pkt_input, 1), (self.preambles, 1))
+ fg.connect(self.preambles, self.ifft, self.cp_adder, self.scale)
+
+ if options.verbose:
+ self._print_verbage()
+
+ if options.log:
+ fg.connect(self._pkt_input, gr.file_sink(gr.sizeof_gr_complex*options.fft_length,
+ "ofdm_mapper_c.dat"))
+
+ gr.hier_block.__init__(self, fg, None, self.scale)
+
+ def send_pkt(self, payload='', eof=False):
+ """
+ Send the payload.
+
+ @param payload: data to send
+ @type payload: string
+ """
+ if eof:
+ msg = gr.message(1) # tell self._pkt_input we're not sending any more packets
+ else:
+ # print "original_payload =", string_to_hex_list(payload)
+ pkt = ofdm_packet_utils.make_packet(payload, 1, 1, self._pad_for_usrp, whitening=True)
+
+ #print "pkt =", string_to_hex_list(pkt)
+ msg = gr.message_from_string(pkt)
+ self._pkt_input.msgq().insert_tail(msg)
+
+ def add_options(normal, expert):
+ """
+ Adds OFDM-specific options to the Options Parser
+ """
+ normal.add_option("-m", "--modulation", type="string", default="bpsk",
+ help="set modulation type (bpsk or qpsk) [default=%default]")
+ expert.add_option("", "--fft-length", type="intx", default=512,
+ help="set the number of FFT bins [default=%default]")
+ expert.add_option("", "--occupied-tones", type="intx", default=200,
+ help="set the number of occupied FFT bins [default=%default]")
+ expert.add_option("", "--cp-length", type="intx", default=128,
+ help="set the number of bits in the cyclic prefix [default=%default]")
+ # Make a static method to call before instantiation
+ add_options = staticmethod(add_options)
+
+ def _print_verbage(self):
+ """
+ Prints information about the OFDM modulator
+ """
+ print "\nOFDM Modulator:"
+ print "Modulation Type: %s" % (self._modulation)
+ print "FFT length: %3d" % (self._fft_length)
+ print "Occupied Tones: %3d" % (self._occupied_tones)
+ print "CP length: %3d" % (self._cp_length)
+
+
+class ofdm_demod(gr.hier_block):
+ """
+ Demodulates a received OFDM stream. Based on the options fft_length, occupied_tones, and
+ cp_length, this block performs synchronization, FFT, and demodulation of incoming OFDM
+ symbols and passes packets up the a higher layer.
+
+ The input is complex baseband. When packets are demodulated, they are passed to the
+ app via the callback.
+ """
+
+ def __init__(self, fg, options, callback=None):
+ """
+ Hierarchical block for demodulating and deframing packets.
+
+ The input is the complex modulated signal at baseband.
+ Demodulated packets are sent to the handler.
+
+ @param fg: flow graph
+ @type fg: flow graph
+ @param options: pass modulation options from higher layers (fft length, occupied tones, etc.)
+ @param callback: function of two args: ok, payload
+ @type callback: ok: bool; payload: string
+ """
+ self._rcvd_pktq = gr.msg_queue() # holds packets from the PHY
+
+ self._modulation = options.modulation
+ self._fft_length = options.fft_length
+ self._occupied_tones = options.occupied_tones
+ self._cp_length = options.cp_length
+ self._snr = options.snr
+
+
+ # Use freq domain to get doubled-up known symbol for correlation in time domain
+ ksfreq = known_symbols_4512_3[0:self._occupied_tones]
+ for i in range(len(ksfreq)):
+ if(i&1):
+ ksfreq[i] = 0
+
+ zeros_on_left = int(math.ceil((self._fft_length - self._occupied_tones)/2.0))
+ zeros_on_right = self._fft_length - self._occupied_tones - zeros_on_left
+ ks0 = zeros_on_left*[0.0,]
+ ks0.extend(ksfreq)
+ ks0.extend(zeros_on_right*[0.0,])
+
+ ks0time = fft.ifft(ks0)
+ # ADD SCALING FACTOR
+ ks0time = ks0time.tolist()
+
+ # hard-coded known symbols
+ preambles = (ks0time,
+ known_symbols_4512_1[0:self._occupied_tones],
+ known_symbols_4512_2[0:self._occupied_tones])
+
+ symbol_length = self._fft_length + self._cp_length
+ self.ofdm_recv = ofdm_receiver(fg, self._fft_length, self._cp_length,
+ self._occupied_tones, self._snr, preambles,
+ options.log)
+
+ mods = {"bpsk": 2, "qpsk": 4, "8psk": 8, "qam8": 8, "qam16": 16, "qam64": 64, "qam256": 256}
+ arity = mods[self._modulation]
+
+ rot = 1
+ if self._modulation == "qpsk":
+ rot = (0.707+0.707j)
+
+ if(self._modulation.find("psk") >= 0):
+ rotated_const = map(lambda pt: pt * rot, psk.gray_constellation[arity])
+ elif(self._modulation.find("qam") >= 0):
+ rotated_const = map(lambda pt: pt * rot, qam.constellation[arity])
+ #print rotated_const
+ self.ofdm_demod = gr.ofdm_frame_sink(rotated_const, range(arity),
+ self._rcvd_pktq,
+ self._occupied_tones)
+
+ fg.connect((self.ofdm_recv, 0), (self.ofdm_demod, 0))
+ fg.connect((self.ofdm_recv, 1), (self.ofdm_demod, 1))
+
+ if options.verbose:
+ self._print_verbage()
+
+ gr.hier_block.__init__(self, fg, self.ofdm_recv, None)
+ self._watcher = _queue_watcher_thread(self._rcvd_pktq, callback)
+
+
+ def add_options(normal, expert):
+ """
+ Adds OFDM-specific options to the Options Parser
+ """
+ normal.add_option("-m", "--modulation", type="string", default="bpsk",
+ help="set modulation type (bpsk or qpsk) [default=%default]")
+ expert.add_option("", "--fft-length", type="intx", default=512,
+ help="set the number of FFT bins [default=%default]")
+ expert.add_option("", "--occupied-tones", type="intx", default=200,
+ help="set the number of occupied FFT bins [default=%default]")
+ expert.add_option("", "--cp-length", type="intx", default=128,
+ help="set the number of bits in the cyclic prefix [default=%default]")
+ # Make a static method to call before instantiation
+ add_options = staticmethod(add_options)
+
+ def _print_verbage(self):
+ """
+ Prints information about the OFDM demodulator
+ """
+ print "\nOFDM Demodulator:"
+ print "Modulation Type: %s" % (self._modulation)
+ print "FFT length: %3d" % (self._fft_length)
+ print "Occupied Tones: %3d" % (self._occupied_tones)
+ print "CP length: %3d" % (self._cp_length)
+
+
+
+class _queue_watcher_thread(_threading.Thread):
+ def __init__(self, rcvd_pktq, callback):
+ _threading.Thread.__init__(self)
+ self.setDaemon(1)
+ self.rcvd_pktq = rcvd_pktq
+ self.callback = callback
+ self.keep_running = True
+ self.start()
+
+
+ def run(self):
+ while self.keep_running:
+ msg = self.rcvd_pktq.delete_head()
+ ok, payload = ofdm_packet_utils.unmake_packet(msg.to_string())
+ if self.callback:
+ self.callback(ok, payload)
+
+# Generating known symbols with:
+# i = [2*random.randint(0,1)-1 for i in range(4512)]
+
+known_symbols_200_1 = [1.0, 1.0, -1.0, 1.0, -1.0, -1.0, 1.0, 1.0, 1.0, 1.0, -1.0, 1.0, 1.0, -1.0, 1.0, -1.0, -1.0, 1.0, -1.0, -1.0, 1.0, -1.0, -1.0, 1.0, -1.0, -1.0, 1.0, 1.0, -1.0, 1.0, -1.0, 1.0, -1.0, 1.0, -1.0, -1.0, 1.0, -1.0, 1.0, -1.0, -1.0, -1.0, -1.0, 1.0, 1.0, 1.0, 1.0, -1.0, -1.0, 1.0, -1.0, -1.0, 1.0, -1.0, -1.0, 1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, 1.0, -1.0, -1.0, -1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, 1.0, 1.0, -1.0, 1.0, -1.0, -1.0, -1.0, 1.0, 1.0, 1.0, -1.0, -1.0, 1.0, -1.0, -1.0, -1.0, -1.0, 1.0, 1.0, 1.0, 1.0, 1.0, -1.0, -1.0, 1.0, 1.0, 1.0, -1.0, -1.0, 1.0, 1.0, -1.0, 1.0, 1.0, 1.0, -1.0, -1.0, 1.0, -1.0, 1.0, -1.0, -1.0, -1.0, -1.0, -1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, -1.0, 1.0, -1.0, 1.0, -1.0, 1.0, -1.0, 1.0, -1.0, 1.0, 1.0, 1.0, 1.0, 1.0, -1.0, -1.0, 1.0, 1.0, -1.0, 1.0, 1.0, 1.0, -1.0, 1.0, -1.0, 1.0, 1.0, 1.0, 1.0, 1.0, -1.0, 1.0, 1.0, 1.0, -1.0, -1.0, -1.0, 1.0, -1.0, 1.0, 1.0, 1.0, -1.0, -1.0, -1.0, -1.0, -1.0, 1.0, -1.0, -1.0, -1.0, 1.0, -1.0, -1.0, -1.0, 1.0, 1.0, -1.0, 1.0, 1.0, 1.0, 1.0, 1.0, -1.0, 1.0, 1.0, 1.0, -1.0, 1.0, 1.0, -1.0]
+
+known_symbols_200_2 = [-1.0, -1.0, -1.0, 1.0, 1.0, 1.0, -1.0, -1.0, -1.0, 1.0, 1.0, -1.0, -1.0, 1.0, 1.0, 1.0, 1.0, -1.0, 1.0, -1.0, 1.0, -1.0, 1.0, -1.0, 1.0, -1.0, -1.0, -1.0, 1.0, -1.0, 1.0, 1.0, 1.0, -1.0, -1.0, -1.0, -1.0, 1.0, -1.0, -1.0, 1.0, 1.0, -1.0, -1.0, 1.0, -1.0, -1.0, 1.0, 1.0, 1.0, 1.0, 1.0, -1.0, 1.0, 1.0, -1.0, -1.0, -1.0, 1.0, -1.0, 1.0, -1.0, 1.0, 1.0, 1.0, 1.0, -1.0, 1.0, -1.0, 1.0, -1.0, -1.0, -1.0, 1.0, -1.0, 1.0, -1.0, 1.0, 1.0, 1.0, -1.0, 1.0, -1.0, 1.0, 1.0, 1.0, -1.0, -1.0, 1.0, 1.0, -1.0, -1.0, -1.0, 1.0, 1.0, 1.0, 1.0, -1.0, -1.0, -1.0, -1.0, -1.0, 1.0, -1.0, 1.0, 1.0, 1.0, 1.0, -1.0, -1.0, 1.0, -1.0, -1.0, 1.0, -1.0, -1.0, 1.0, -1.0, 1.0, 1.0, 1.0, -1.0, -1.0, 1.0, -1.0, -1.0, -1.0, -1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, -1.0, 1.0, 1.0, -1.0, -1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, -1.0, 1.0, -1.0, 1.0, 1.0, 1.0, 1.0, -1.0, 1.0, 1.0, -1.0, 1.0, -1.0, -1.0, -1.0, 1.0, 1.0, -1.0, -1.0, 1.0, 1.0, 1.0, -1.0, 1.0, -1.0, 1.0, -1.0, -1.0, -1.0, 1.0, -1.0, -1.0, -1.0, 1.0, 1.0, 1.0, -1.0, -1.0, 1.0, -1.0, 1.0, -1.0, 1.0, -1.0, -1.0, -1.0, -1.0, -1.0, 1.0, -1.0, -1.0, -1.0, 1.0, 1.0, 1.0]
+
+
+known_symbols_4512_1 = [-1, 1, 1, 1, -1, -1, 1, -1, 1, -1, 1, 1, 1, 1, 1, -1, -1, 1, 1, -1, -1, 1, 1, -1, 1, -1, 1, -1, 1, 1, -1, -1, 1, 1, 1, 1, -1, 1, 1, -1, -1, 1, 1, -1, -1, 1, -1, 1, -1, -1, 1, -1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, 1, -1, 1, 1, -1, 1, 1, 1, 1, 1, -1, -1, -1, 1, 1, -1, -1, 1, -1, -1, 1, 1, -1, 1, -1, -1, -1, -1, 1, 1, -1, 1, 1, 1, 1, 1, -1, 1, -1, -1, -1, 1, 1, -1, 1, -1, 1, 1, -1, 1, -1, 1, 1, -1, 1, 1, 1, -1, -1, -1, 1, -1, -1, -1, 1, 1, 1, -1, -1, -1, -1, 1, -1, 1, 1, -1, 1, -1, 1, -1, -1, -1, -1, -1, -1, -1, 1, 1, -1, 1, -1, -1, -1, 1, -1, 1, -1, 1, -1, 1, -1, -1, -1, -1, 1, -1, -1, -1, 1, -1, -1, -1, -1, -1, -1, -1, 1, 1, -1, -1, 1, 1, -1, 1, -1, -1, -1, 1, 1, 1, -1, 1, -1, 1, -1, 1, -1, 1, 1, -1, -1, 1, 1, 1, -1, -1, 1, 1, -1, 1, -1, -1, 1, 1, -1, -1, 1, -1, -1, -1, 1, -1, 1, -1, 1, 1, -1, 1, 1, 1, 1, -1, 1, 1, -1, 1, -1, 1, 1, -1, -1, 1, -1, -1, 1, -1, 1, -1, 1, -1, 1, 1, -1, -1, 1, 1, 1, -1, 1, -1, 1, 1, 1, 1, 1, 1, -1, 1, -1, 1, -1, -1, -1, 1, -1, 1, -1, 1, 1, -1, 1, -1, 1, -1, -1, -1, 1, -1, 1, -1, 1, -1, -1, -1, -1, 1, -1, -1, -1, 1, 1, 1, -1, 1, 1, 1, -1, -1, 1, 1, -1, -1, -1, 1, -1, -1, -1, -1, -1, -1, 1, -1, 1, -1, 1, -1, 1, -1, -1, -1, 1, -1, -1, 1, 1, -1, 1, 1, 1, 1, 1, 1, -1, 1, -1, -1, 1, -1, -1, 1, 1, 1, -1, 1, 1, 1, 1, 1, -1, 1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, -1, 1, 1, 1, 1, -1, -1, -1, 1, -1, -1, 1, 1, -1, -1, 1, -1, -1, -1, 1, -1, 1, -1, -1, 1, 1, -1, 1, 1, 1, -1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, 1, 1, -1, 1, 1, -1, 1, 1, -1, 1, -1, 1, -1, -1, -1, -1, -1, 1, -1, 1, 1, 1, 1, -1, 1, -1, 1, -1, -1, 1, 1, -1, 1, -1, 1, 1, 1, 1, 1, 1, -1, 1, 1, -1, 1, 1, 1, 1, 1, 1, -1, 1, 1, 1, -1, -1, 1, -1, -1, 1, 1, 1, 1, 1, -1, -1, -1, 1, -1, -1, -1, 1, 1, 1, 1, -1, 1, 1, 1, 1, 1, 1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, 1, -1, 1, 1, 1, 1, 1, 1, -1, -1, 1, 1, 1, -1, -1, 1, -1, -1, -1, 1, -1, -1, 1, 1, -1, -1, -1, -1, 1, 1, 1, -1, -1, 1, 1, -1, -1, 1, 1, 1, 1, 1, -1, 1, -1, -1, 1, 1, 1, 1, -1, -1, -1, -1, -1, 1, -1, 1, -1, -1, -1, -1, 1, 1, 1, -1, -1, 1, 1, 1, -1, -1, 1, -1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, -1, -1, -1, 1, -1, 1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, 1, -1, 1, 1, -1, 1, -1, -1, -1, 1, -1, 1, -1, 1, -1, -1, -1, -1, 1, -1, 1, -1, 1, -1, 1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, 1, -1, -1, -1, 1, -1, -1, -1, -1, -1, -1, -1, 1, -1, 1, 1, -1, -1, -1, -1, 1, -1, -1, 1, -1, -1, 1, -1, -1, -1, 1, 1, 1, 1, 1, -1, -1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, -1, -1, -1, 1, -1, 1, 1, -1, -1, 1, -1, -1, -1, -1, 1, 1, -1, -1, 1, -1, -1, -1, -1, -1, -1, -1, 1, -1, -1, 1, 1, -1, 1, -1, -1, -1, -1, -1, 1, -1, -1, -1, 1, 1, -1, 1, 1, -1, 1, -1, 1, -1, -1, -1, -1, 1, 1, -1, 1, 1, -1, 1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, -1, -1, -1, -1, 1, 1, 1, 1, -1, -1, -1, 1, -1, 1, -1, 1, 1, 1, 1, -1, -1, 1, 1, -1, 1, -1, 1, -1, 1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, 1, -1, -1, 1, -1, -1, 1, -1, 1, 1, 1, 1, 1, 1, 1, -1, 1, -1, 1, 1, -1, 1, -1, 1, 1, 1, 1, 1, -1, -1, -1, -1, 1, -1, -1, 1, -1, 1, -1, 1, -1, -1, -1, -1, -1, 1, 1, 1, -1, 1, 1, -1, 1, 1, 1, -1, -1, 1, -1, -1, -1, -1, 1, -1, 1, 1, -1, -1, -1, -1, 1, -1, -1, 1, -1, 1, -1, -1, -1, 1, -1, -1, -1, 1, 1, -1, -1, 1, -1, -1, -1, -1, -1, 1, 1, -1, 1, -1, -1, 1, 1, -1, -1, -1, 1, 1, -1, -1, -1, 1, 1, -1, 1, -1, -1, 1, 1, 1, 1, 1, -1, 1, -1, 1, 1, -1, -1, 1, -1, 1, -1, 1, 1, -1, 1, -1, -1, 1, -1, 1, -1, -1, -1, -1, -1, 1, -1, -1, 1, 1, 1, 1, 1, -1, -1, 1, 1, 1, -1, 1, -1, 1, -1, 1, 1, 1, -1, 1, 1, -1, 1, 1, -1, 1, 1, 1, 1, -1, 1, 1, -1, -1, -1, 1, 1, -1, 1, 1, -1, 1, -1, -1, 1, 1, -1, 1, 1, 1, -1, -1, 1, -1, 1, -1, 1, 1, -1, 1, -1, 1, -1, 1, -1, 1, 1, 1, -1, -1, -1, 1, 1, 1, -1, 1, -1, 1, -1, 1, 1, 1, 1, 1, 1, 1, -1, 1, -1, 1, -1, -1, -1, 1, -1, 1, 1, 1, -1, 1, -1, 1, -1, -1, 1, -1, 1, 1, 1, 1, 1, -1, 1, 1, -1, -1, -1, 1, -1, 1, 1, -1, 1, -1, 1, 1, 1, 1, -1, -1, -1, 1, 1, -1, -1, -1, -1, -1, -1, -1, 1, -1, -1, -1, 1, 1, 1, 1, 1, -1, -1, 1, -1, 1, -1, 1, 1, -1, 1, 1, -1, 1, -1, -1, 1, 1, -1, -1, -1, 1, -1, 1, -1, -1, 1, 1, 1, 1, 1, -1, 1, -1, 1, -1, 1, 1, -1, -1, 1, 1, 1, 1, 1, 1, -1, 1, -1, -1, -1, -1, -1, -1, 1, -1, 1, -1, 1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, -1, 1, -1, 1, 1, 1, 1, 1, 1, -1, -1, 1, 1, 1, 1, -1, -1, 1, -1, -1, 1, -1, -1, -1, 1, -1, 1, -1, -1, 1, 1, 1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, -1, -1, -1, 1, -1, -1, -1, -1, 1, -1, 1, 1, -1, -1, -1, 1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, 1, 1, 1, -1, 1, -1, 1, -1, -1, -1, 1, -1, 1, -1, -1, 1, -1, -1, -1, -1, 1, 1, 1, -1, -1, 1, 1, -1, -1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, -1, 1, -1, 1, -1, -1, -1, 1, 1, 1, 1, 1, 1, -1, 1, -1, -1, 1, 1, 1, 1, -1, 1, 1, -1, 1, 1, -1, -1, -1, 1, 1, -1, -1, -1, 1, -1, 1, 1, 1, 1, -1, -1, 1, 1, 1, -1, 1, 1, -1, 1, -1, 1, 1, -1, -1, 1, 1, 1, 1, -1, -1, 1, -1, -1, 1, -1, -1, 1, -1, 1, -1, -1, 1, 1, 1, -1, -1, 1, 1, -1, -1, -1, -1, 1, -1, -1, -1, 1, -1, -1, -1, -1, 1, 1, -1, -1, 1, -1, -1, -1, -1, -1, 1, -1, -1, 1, 1, -1, 1, 1, 1, -1, -1, -1, 1, -1, -1, 1, -1, 1, 1, -1, -1, -1, 1, -1, -1, 1, -1, 1, 1, -1, 1, -1, 1, 1, 1, 1, 1, -1, -1, -1, -1, 1, 1, -1, -1, 1, 1, -1, 1, 1, -1, -1, -1, 1, -1, -1, -1, 1, -1, -1, -1, -1, -1, 1, 1, -1, 1, -1, -1, 1, 1, -1, 1, -1, 1, 1, 1, -1, 1, -1, 1, -1, -1, -1, 1, 1, 1, 1, 1, -1, 1, -1, -1, -1, 1, 1, -1, -1, -1, 1, -1, -1, -1, -1, -1, 1, -1, 1, 1, -1, -1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, 1, 1, -1, -1, -1, 1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, -1, 1, 1, 1, -1, 1, 1, -1, -1, -1, 1, 1, -1, -1, -1, -1, -1, -1, 1, -1, -1, 1, 1, -1, -1, 1, -1, -1, 1, 1, 1, -1, -1, 1, -1, -1, 1, 1, 1, -1, -1, 1, 1, -1, 1, -1, 1, -1, -1, 1, -1, -1, 1, -1, -1, 1, 1, 1, -1, -1, 1, 1, 1, 1, 1, 1, -1, -1, 1, -1, 1, -1, 1, 1, -1, -1, 1, -1, -1, -1, 1, -1, 1, 1, 1, 1, -1, -1, -1, 1, -1, 1, -1, 1, 1, -1, 1, -1, 1, -1, 1, 1, 1, -1, -1, -1, -1, 1, -1, 1, -1, 1, -1, -1, -1, -1, -1, -1, 1, -1, 1, 1, 1, 1, -1, 1, 1, 1, 1, 1, -1, 1, -1, -1, -1, 1, -1, -1, -1, 1, 1, -1, -1, -1, 1, -1, 1, 1, 1, 1, 1, 1, 1, -1, -1, 1, -1, 1, 1, 1, -1, -1, 1, -1, 1, -1, -1, 1, 1, 1, -1, -1, 1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, 1, 1, -1, 1, 1, 1, -1, -1, 1, 1, 1, -1, 1, -1, 1, 1, 1, -1, -1, -1, 1, -1, 1, -1, 1, 1, -1, -1, -1, -1, -1, -1, 1, 1, -1, -1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, -1, -1, 1, -1, -1, 1, 1, 1, -1, -1, -1, -1, -1, 1, 1, 1, 1, -1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, -1, 1, 1, -1, -1, -1, 1, -1, -1, 1, 1, 1, 1, -1, -1, -1, 1, 1, -1, -1, 1, 1, 1, 1, 1, 1, -1, -1, 1, 1, 1, -1, 1, 1, 1, 1, -1, -1, 1, -1, -1, -1, 1, 1, 1, 1, -1, -1, -1, -1, 1, -1, -1, 1, 1, 1, 1, 1, 1, -1, 1, -1, 1, 1, 1, -1, 1, 1, -1, -1, 1, -1, 1, -1, 1, -1, -1, 1, 1, -1, -1, -1, 1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, 1, -1, 1, -1, -1, 1, 1, 1, -1, 1, 1, -1, -1, -1, -1, -1, 1, -1, 1, 1, -1, -1, 1, 1, 1, -1, 1, -1, -1, -1, 1, 1, -1, 1, 1, 1, -1, -1, 1, -1, 1, 1, 1, -1, 1, 1, 1, 1, -1, 1, -1, -1, 1, -1, -1, -1, -1, 1, 1, -1, -1, 1, 1, -1, -1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1, 1, -1, -1, -1, -1, 1, 1, -1, -1, -1, -1, -1, -1, 1, -1, 1, -1, 1, 1, 1, -1, -1, -1, -1, 1, -1, -1, -1, 1, -1, 1, -1, -1, -1, -1, -1, -1, -1, 1, -1, 1, -1, -1, -1, 1, -1, -1, -1, 1, -1, 1, 1, -1, 1, 1, -1, 1, -1, 1, 1, -1, 1, -1, 1, 1, -1, 1, 1, -1, 1, 1, 1, 1, -1, 1, -1, 1, -1, 1, 1, -1, -1, 1, -1, 1, 1, -1, 1, -1, -1, -1, -1, -1, -1, 1, 1, 1, -1, 1, -1, 1, 1, -1, 1, 1, 1, 1, -1, 1, -1, 1, -1, -1, -1, -1, 1, 1, -1, -1, -1, 1, -1, 1, -1, -1, 1, -1, 1, -1, -1, -1, 1, 1, 1, -1, 1, 1, -1, -1, 1, -1, -1, 1, -1, 1, 1, -1, -1, -1, -1, -1, -1, 1, 1, -1, 1, -1, -1, -1, -1, -1, 1, -1, 1, 1, 1, 1, 1, 1, -1, 1, -1, 1, -1, -1, -1, 1, -1, 1, 1, -1, -1, -1, -1, 1, -1, -1, -1, 1, 1, 1, 1, -1, -1, 1, -1, 1, 1, -1, -1, 1, -1, -1, 1, -1, 1, -1, -1, 1, -1, -1, -1, 1, 1, 1, -1, 1, 1, -1, -1, -1, 1, -1, 1, -1, 1, -1, 1, -1, -1, 1, 1, -1, -1, -1, -1, 1, -1, 1, 1, 1, 1, -1, 1, 1, 1, -1, -1, -1, 1, 1, -1, -1, 1, 1, -1, 1, 1, 1, 1, 1, -1, 1, -1, 1, 1, 1, -1, -1, -1, 1, -1, 1, 1, 1, 1, -1, 1, 1, 1, -1, 1, -1, 1, -1, -1, -1, 1, 1, -1, 1, 1, 1, 1, -1, -1, -1, -1, -1, 1, -1, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, -1, 1, -1, 1, 1, -1, -1, -1, 1, 1, 1, 1, -1, 1, -1, -1, 1, -1, 1, -1, -1, -1, 1, 1, -1, -1, 1, -1, 1, -1, 1, 1, 1, -1, -1, 1, 1, -1, 1, 1, -1, 1, -1, -1, -1, -1, -1, 1, -1, 1, 1, 1, -1, 1, -1, 1, -1, -1, -1, 1, 1, 1, -1, 1, 1, 1, 1, -1, -1, 1, -1, 1, 1, 1, 1, 1, 1, 1, -1, 1, -1, 1, 1, 1, 1, -1, 1, 1, -1, 1, 1, -1, 1, 1, 1, -1, 1, 1, 1, -1, 1, -1, -1, -1, -1, -1, 1, -1, -1, -1, 1, 1, -1, 1, 1, -1, 1, -1, 1, 1, 1, 1, 1, -1, 1, -1, -1, 1, 1, -1, -1, -1, -1, -1, -1, 1, 1, -1, 1, -1, -1, 1, 1, -1, -1, -1, 1, 1, 1, 1, -1, -1, -1, -1, 1, -1, 1, 1, -1, -1, -1, -1, -1, 1, -1, 1, -1, 1, -1, 1, 1, 1, -1, 1, -1, 1, 1, -1, 1, -1, -1, 1, -1, -1, -1, -1, 1, 1, 1, -1, -1, 1, 1, 1, 1, -1, -1, -1, 1, 1, -1, -1, 1, -1, -1, -1, -1, -1, -1, 1, 1, -1, -1, 1, 1, 1, -1, -1, -1, 1, 1, 1, 1, 1, -1, -1, -1, 1, 1, -1, 1, -1, 1, 1, 1, -1, 1, -1, 1, -1, -1, 1, -1, 1, 1, 1, -1, 1, -1, 1, -1, 1, 1, 1, -1, -1, 1, 1, 1, 1, -1, 1, -1, 1, -1, -1, -1, 1, 1, 1, -1, -1, 1, -1, 1, -1, -1, -1, 1, -1, 1, 1, 1, -1, -1, 1, -1, 1, -1, 1, 1, -1, 1, 1, 1, -1, 1, 1, 1, -1, 1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, -1, -1, -1, 1, -1, -1, -1, -1, -1, 1, -1, -1, 1, -1, 1, -1, 1, 1, 1, 1, 1, -1, 1, 1, 1, -1, -1, 1, 1, -1, 1, 1, -1, 1, -1, -1, 1, -1, -1, -1, 1, 1, 1, -1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, 1, -1, 1, -1, 1, 1, 1, -1, 1, 1, -1, 1, 1, 1, -1, -1, -1, 1, -1, -1, -1, 1, 1, 1, -1, 1, -1, -1, 1, -1, -1, 1, 1, 1, 1, -1, 1, -1, 1, -1, -1, 1, 1, 1, 1, 1, 1, -1, 1, 1, -1, 1, 1, -1, 1, -1, -1, -1, 1, -1, 1, -1, -1, 1, -1, 1, 1, -1, -1, -1, 1, -1, -1, -1, 1, -1, -1, 1, 1, 1, 1, -1, 1, -1, -1, -1, 1, -1, 1, -1, 1, -1, 1, 1, 1, -1, -1, 1, -1, -1, 1, 1, -1, -1, 1, -1, 1, -1, 1, -1, -1, -1, 1, 1, -1, 1, 1, 1, 1, -1, 1, 1, 1, -1, -1, -1, 1, 1, -1, 1, 1, -1, 1, -1, 1, 1, -1, -1, -1, 1, -1, 1, 1, 1, -1, -1, -1, -1, -1, -1, 1, 1, -1, -1, -1, -1, 1, 1, 1, -1, -1, -1, 1, -1, 1, -1, 1, 1, -1, 1, 1, -1, -1, 1, -1, -1, -1, 1, 1, -1, -1, -1, 1, 1, -1, -1, -1, -1, 1, 1, -1, -1, 1, -1, 1, -1, -1, 1, 1, 1, 1, 1, 1, -1, -1, 1, -1, 1, -1, -1, -1, -1, 1, -1, 1, 1, 1, 1, -1, 1, -1, 1, 1, 1, -1, -1, 1, 1, 1, 1, 1, -1, 1, 1, -1, -1, 1, 1, 1, 1, 1, 1, 1, -1, -1, 1, -1, -1, 1, -1, -1, 1, -1, -1, -1, -1, 1, 1, -1, -1, 1, -1, 1, 1, -1, -1, 1, -1, -1, -1, 1, 1, -1, 1, 1, -1, 1, 1, -1, 1, 1, 1, -1, -1, -1, 1, 1, -1, 1, -1, 1, 1, 1, -1, 1, 1, 1, 1, 1, -1, 1, -1, 1, -1, 1, -1, -1, -1, 1, -1, 1, -1, -1, 1, 1, 1, 1, -1, 1, -1, -1, -1, 1, -1, 1, 1, -1, -1, -1, 1, -1, 1, -1, -1, 1, -1, -1, -1, 1, -1, -1, -1, 1, -1, -1, 1, 1, 1, -1, -1, 1, -1, 1, -1, 1, -1, -1, -1, -1, 1, 1, -1, 1, 1, 1, -1, -1, -1, -1, -1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1, 1, -1, -1, -1, 1, -1, -1, 1, -1, 1, -1, 1, -1, -1, -1, -1, 1, -1, 1, 1, 1, 1, -1, 1, -1, 1, 1, -1, 1, 1, 1, -1, -1, 1, -1, -1, -1, 1, -1, -1, -1, 1, -1, -1, -1, 1, 1, 1, 1, -1, -1, 1, 1, 1, -1, 1, 1, -1, -1, 1, -1, 1, -1, -1, -1, -1, 1, -1, 1, -1, 1, 1, -1, 1, -1, -1, 1, -1, 1, -1, 1, -1, 1, 1, 1, -1, 1, 1, -1, 1, -1, -1, 1, -1, 1, -1, 1, -1, 1, 1, -1, 1, 1, -1, -1, 1, 1, 1, -1, -1, -1, 1, 1, -1, -1, -1, 1, 1, 1, -1, 1, -1, 1, 1, 1, -1, 1, 1, -1, -1, 1, -1, 1, -1, 1, 1, 1, -1, 1, -1, -1, 1, 1, 1, 1, 1, -1, 1, -1, -1, -1, -1, -1, 1, -1, 1, -1, -1, -1, -1, -1, 1, -1, -1, -1, 1, 1, -1, -1, 1, 1, -1, -1, -1, 1, -1, -1, 1, 1, 1, 1, -1, -1, 1, -1, -1, 1, -1, -1, -1, 1, 1, -1, -1, 1, 1, -1, 1, 1, 1, 1, -1, -1, 1, 1, 1, -1, 1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1, 1, -1, 1, -1, -1, -1, 1, -1, 1, 1, -1, -1, 1, -1, -1, -1, -1, 1, 1, 1, -1, 1, 1, -1, -1, -1, 1, -1, -1, 1, -1, 1, -1, 1, 1, -1, -1, -1, 1, -1, 1, -1, -1, -1, 1, 1, -1, -1, 1, 1, -1, -1, 1, 1, 1, 1, 1, -1, 1, -1, -1, -1, 1, 1, 1, -1, -1, -1, 1, 1, 1, -1, -1, 1, 1, 1, -1, 1, -1, -1, -1, -1, -1, 1, 1, 1, -1, -1, -1, 1, 1, 1, -1, 1, -1, 1, -1, -1, -1, -1, 1, -1, -1, -1, 1, 1, 1, -1, 1, 1, -1, -1, 1, -1, 1, -1, -1, 1, 1, -1, -1, 1, -1, 1, -1, 1, -1, -1, 1, -1, -1, 1, -1, 1, 1, 1, -1, 1, -1, -1, -1, -1, 1, -1, 1, -1, -1, -1, -1, 1, 1, 1, -1, -1, -1, -1, -1, 1, -1, -1, 1, -1, 1, 1, 1, 1, -1, -1, 1, 1, -1, 1, 1, 1, -1, 1, -1, -1, -1, -1, 1, -1, 1, 1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, -1, 1, -1, 1, 1, -1, 1, -1, -1, -1, -1, -1, -1, 1, -1, 1, 1, -1, 1, -1, 1, 1, 1, -1, -1, -1, 1, 1, -1, 1, 1, -1, 1, 1, -1, 1, 1, -1, 1, -1, 1, -1, -1, 1, -1, 1, -1, -1, -1, 1, 1, -1, 1, 1, -1, -1, -1, 1, 1, -1, -1, 1, -1, 1, -1, -1, 1, 1, 1, 1, -1, 1, -1, -1, 1, -1, 1, -1, 1, 1, 1, 1, -1, 1, -1, -1, -1, 1, -1, 1, 1, -1, 1, 1, -1, -1, -1, 1, -1, 1, -1, 1, 1, 1, -1, -1, -1, -1, 1, 1, -1, 1, 1, 1, 1, -1, -1, -1, -1, 1, 1, 1, 1, 1, -1, 1, 1, -1, 1, -1, -1, 1, 1, 1, -1, 1, 1, 1, 1, 1, 1, 1, -1, -1, 1, 1, -1, 1, 1, -1, -1, 1, 1, -1, -1, -1, -1, -1, -1, 1, 1, -1, -1, 1, -1, 1, 1, 1, 1, -1, 1, -1, 1, 1, 1, 1, -1, -1, -1, -1, -1, 1, 1, -1, 1, 1, 1, -1, -1, 1, 1, -1, -1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, -1, 1, 1, 1, 1, -1, -1, 1, 1, -1, 1, 1, -1, -1, 1, 1, 1, -1, 1, -1, -1, 1, -1, -1, 1, 1, 1, -1, -1, -1, -1, -1, -1, 1, -1, -1, -1, -1, 1, -1, -1, 1, 1, -1, 1, 1, 1, -1, -1, -1, 1, 1, 1, 1, -1, -1, 1, 1, -1, -1, -1, 1, -1, -1, -1, 1, 1, -1, -1, -1, 1, -1, 1, -1, -1, 1, -1, 1, 1, -1, 1, -1, 1, 1, 1, -1, 1, -1, -1, 1, 1, -1, 1, 1, -1, 1, -1, 1, -1, -1, -1, 1, 1, -1, -1, 1, -1, -1, -1, -1, 1, -1, -1, 1, -1, 1, 1, 1, -1, -1, -1, -1, 1, -1, 1, 1, -1, -1, -1, -1, 1, 1, -1, 1, 1, -1, -1, 1, 1, 1, -1, -1, -1, -1, -1, 1, -1, 1, -1, 1, 1, -1, -1, -1, 1, 1, 1, -1, 1, 1, 1, -1, 1, -1, 1, -1, -1, 1, 1, -1, -1, -1, 1, 1, 1, 1, -1, -1, -1, -1, 1, -1, -1, 1, 1, -1, -1, 1, 1, 1, 1, 1, 1, -1, 1, -1, 1, -1, -1, 1, 1, -1, -1, 1, -1, 1, -1, -1, 1, 1, 1, 1, 1, -1, -1, 1, 1, -1, -1, -1, -1, -1, -1, 1, 1, -1, -1, -1, -1, -1, -1, 1, -1, -1, 1, 1, -1, 1, -1, 1, 1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, -1, 1, -1, 1, -1, 1, 1, 1, -1, 1, 1, 1, -1, -1, -1, -1, 1, 1, 1, -1, 1, 1, 1, 1, 1, -1, 1, 1, 1, 1, 1, -1, 1, 1, -1, 1, -1, 1, 1, -1, -1, 1, -1, 1, -1, -1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, 1, 1, 1, -1, -1, -1, 1, 1, -1, 1, -1, -1, 1, 1, -1, -1, 1, 1, -1, -1, -1, 1, 1, -1, 1, 1, -1, -1, -1, 1, 1, 1, 1, 1, -1, -1, 1, -1, -1, 1, -1, 1, 1, 1, -1, 1, 1, 1, 1, -1, -1, 1, 1, -1, -1, -1, -1, 1, 1, 1, -1, -1, 1, -1, 1, -1, -1, -1, 1, -1, 1, 1, 1, -1, -1, -1, -1, 1, -1, -1, 1, 1, 1, -1, 1, -1, 1, 1, 1, -1, 1, 1, -1, 1, -1, 1, 1, -1, 1, 1, -1, 1, 1, 1, -1, 1, 1, 1, -1, -1, -1, 1, -1, 1, 1, 1, 1, 1, -1, 1, 1, 1, -1, -1, 1, 1, 1, 1, 1, -1, -1, 1, 1, -1, -1, -1, -1, 1, -1, 1, -1, -1, -1, -1, -1, -1, 1, -1, -1, 1, -1, 1, -1, 1, 1, -1, -1, 1, 1, -1, -1, -1, -1, 1, 1, 1, -1, 1, 1, -1, 1, 1, -1, -1, -1, 1, 1, -1, 1, 1, 1, 1, -1, 1, -1, 1, -1, -1, -1, -1, 1, 1, 1, 1, -1, -1, 1, -1, 1, 1, -1, 1, 1, 1, 1, -1, -1, 1, -1, -1, 1, -1, -1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1, -1, 1, 1, 1, 1, -1, -1, -1, 1, -1, -1, -1, -1, -1, 1, -1, -1, -1, -1, 1, -1, -1, 1, 1, -1, -1, 1, 1, -1, -1, -1, -1, -1, -1, 1, 1, -1, -1, 1, 1, 1, 1, -1, -1, -1, -1, -1, 1, -1, 1, -1, -1, 1, -1, 1, 1, 1, 1, 1, -1, 1, 1, -1, -1, -1, -1, 1, 1, 1, -1, -1, 1, 1, -1, 1, 1, 1, -1, -1, -1, 1, -1, -1, 1, -1, -1, 1, 1, -1, -1, -1, -1, 1, 1, 1, -1, -1, 1, 1, -1, 1, -1, 1, -1, 1, -1, -1, 1, 1, 1, -1, 1, 1, 1, 1, -1, 1, 1, 1, 1, 1, -1, 1, 1, -1, 1, -1, -1, 1, -1, -1, 1, 1, 1, -1, -1, -1, 1, 1, -1, -1, -1, -1, -1, -1, -1, 1, 1, -1, -1, -1, 1, -1, 1, -1, -1, 1, 1, -1, -1, 1, 1, -1, 1, -1, -1, -1, 1, 1, 1, -1, 1, 1, -1, -1, -1, -1, 1, -1, -1, -1, 1, -1, -1, -1, 1, 1, -1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, -1, -1, -1, 1, -1, 1, 1, 1, -1, -1, 1, 1, 1, 1, -1, -1, 1, 1, 1, -1, 1, 1, -1, 1, 1, 1, 1, -1, -1, -1, -1, 1, -1, 1, -1, -1, 1, -1, 1, -1, 1, 1, 1, -1, -1, -1, -1, 1, 1, 1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, 1, 1, 1, 1, -1, -1, 1, 1, 1, 1, 1, -1, -1, 1, 1, 1, -1, -1, -1, -1, 1, 1, -1, 1, 1, -1, 1, 1, -1, -1, 1, -1, 1, 1, -1, -1, 1, -1, 1, 1, -1, 1, 1, 1, 1, 1, 1, -1, 1, -1, -1, -1, 1, -1, 1, 1, -1, -1, 1, 1, 1, 1, -1, -1, 1]
+
+known_symbols_4512_2 = [1, 1, 1, -1, -1, -1, 1, -1, -1, -1, -1, -1, 1, -1, 1, -1, -1, 1, 1, 1, 1, -1, 1, -1, -1, 1, -1, -1, 1, -1, -1, 1, 1, -1, -1, 1, 1, 1, 1, 1, -1, 1, 1, 1, -1, 1, -1, -1, -1, -1, 1, 1, -1, -1, 1, -1, 1, 1, 1, 1, 1, 1, 1, -1, -1, 1, 1, 1, -1, 1, -1, -1, 1, 1, -1, -1, -1, -1, 1, 1, -1, -1, 1, -1, 1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1, 1, -1, 1, 1, 1, -1, -1, 1, 1, 1, -1, -1, 1, 1, 1, 1, 1, 1, 1, -1, 1, -1, -1, -1, 1, -1, -1, -1, -1, -1, 1, -1, 1, 1, 1, -1, 1, -1, 1, -1, -1, 1, 1, 1, -1, 1, 1, 1, -1, 1, 1, 1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1, 1, -1, -1, 1, 1, -1, -1, 1, 1, -1, 1, 1, 1, 1, 1, 1, -1, 1, -1, -1, -1, -1, 1, -1, -1, 1, -1, -1, 1, -1, -1, 1, 1, 1, -1, 1, -1, 1, 1, 1, -1, 1, -1, 1, -1, -1, 1, 1, 1, -1, 1, -1, -1, -1, 1, 1, 1, -1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1, 1, -1, 1, -1, -1, -1, -1, -1, 1, -1, -1, -1, 1, 1, -1, 1, -1, -1, -1, -1, 1, 1, -1, -1, -1, 1, 1, -1, 1, 1, -1, -1, 1, -1, 1, 1, -1, -1, 1, 1, -1, -1, -1, -1, 1, 1, 1, -1, -1, -1, 1, -1, -1, -1, 1, 1, 1, 1, -1, -1, 1, -1, -1, 1, 1, -1, 1, -1, -1, -1, 1, -1, 1, 1, -1, 1, -1, -1, 1, -1, -1, 1, -1, 1, 1, -1, -1, -1, -1, -1, 1, 1, -1, -1, -1, -1, 1, 1, -1, 1, 1, -1, -1, -1, 1, -1, -1, 1, 1, 1, 1, 1, 1, -1, -1, 1, -1, 1, -1, 1, -1, -1, -1, 1, 1, -1, -1, -1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, 1, -1, -1, -1, 1, 1, 1, -1, 1, -1, -1, 1, 1, 1, 1, -1, -1, 1, -1, 1, -1, 1, 1, 1, 1, -1, -1, 1, -1, 1, -1, -1, 1, 1, -1, 1, 1, -1, -1, -1, -1, 1, -1, 1, -1, -1, -1, 1, 1, -1, -1, -1, 1, 1, -1, 1, -1, -1, -1, 1, 1, -1, 1, 1, -1, -1, -1, 1, 1, 1, -1, 1, 1, -1, -1, -1, 1, -1, -1, -1, -1, 1, 1, 1, -1, 1, 1, 1, -1, 1, -1, -1, 1, 1, 1, -1, 1, 1, 1, -1, -1, 1, 1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, -1, -1, 1, -1, -1, 1, -1, 1, -1, -1, 1, 1, 1, 1, 1, 1, -1, -1, 1, 1, 1, 1, -1, -1, -1, -1, 1, 1, 1, -1, 1, -1, 1, 1, -1, -1, 1, -1, -1, 1, 1, 1, -1, -1, 1, 1, 1, 1, 1, -1, 1, -1, -1, 1, -1, -1, -1, 1, 1, 1, 1, -1, 1, 1, -1, 1, 1, -1, 1, -1, 1, 1, 1, 1, -1, 1, -1, -1, 1, 1, 1, -1, 1, -1, 1, -1, -1, 1, -1, -1, 1, 1, -1, -1, -1, 1, 1, -1, 1, 1, 1, 1, -1, -1, -1, 1, 1, 1, 1, 1, 1, -1, 1, -1, -1, -1, 1, -1, -1, 1, 1, -1, 1, 1, -1, 1, -1, 1, 1, -1, 1, -1, -1, -1, -1, -1, -1, 1, 1, -1, -1, 1, -1, 1, -1, -1, -1, -1, 1, -1, -1, -1, 1, 1, -1, -1, -1, -1, -1, 1, 1, -1, -1, -1, 1, 1, -1, -1, -1, 1, 1, -1, 1, -1, 1, 1, -1, -1, 1, -1, -1, -1, -1, 1, 1, -1, 1, 1, -1, -1, -1, -1, 1, -1, -1, 1, 1, 1, 1, 1, 1, 1, -1, 1, 1, -1, 1, 1, -1, 1, -1, -1, -1, -1, 1, -1, 1, 1, 1, 1, 1, 1, -1, 1, -1, -1, 1, 1, 1, 1, -1, -1, 1, -1, -1, 1, 1, -1, -1, -1, 1, 1, -1, -1, -1, 1, -1, 1, -1, 1, -1, 1, -1, -1, -1, 1, 1, -1, 1, 1, -1, 1, -1, 1, -1, -1, 1, 1, 1, 1, 1, -1, -1, 1, 1, 1, -1, -1, -1, 1, 1, 1, 1, -1, -1, 1, -1, 1, -1, 1, 1, 1, 1, -1, -1, -1, -1, -1, 1, 1, -1, -1, 1, -1, -1, -1, 1, -1, 1, -1, -1, 1, -1, 1, 1, 1, -1, 1, -1, -1, -1, 1, 1, -1, 1, 1, -1, -1, -1, -1, 1, -1, 1, -1, 1, 1, 1, -1, 1, 1, 1, -1, 1, 1, 1, 1, -1, 1, -1, 1, 1, -1, 1, -1, -1, 1, -1, -1, 1, -1, -1, -1, 1, 1, -1, -1, -1, -1, 1, -1, 1, 1, 1, 1, -1, -1, 1, 1, -1, 1, 1, 1, -1, -1, -1, 1, -1, -1, -1, 1, -1, 1, 1, -1, 1, 1, 1, 1, 1, -1, 1, 1, 1, 1, 1, 1, -1, -1, 1, 1, 1, -1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, 1, -1, -1, -1, 1, -1, 1, 1, -1, 1, -1, 1, 1, -1, -1, 1, 1, 1, 1, -1, 1, 1, 1, -1, 1, -1, -1, 1, -1, 1, 1, 1, -1, -1, 1, -1, -1, -1, 1, 1, 1, 1, -1, 1, -1, 1, 1, -1, -1, -1, -1, -1, -1, 1, -1, -1, 1, 1, 1, -1, -1, 1, -1, -1, 1, -1, -1, -1, -1, 1, 1, 1, -1, -1, -1, -1, 1, 1, -1, -1, 1, -1, -1, -1, 1, -1, -1, -1, -1, -1, 1, -1, 1, -1, 1, -1, -1, -1, 1, 1, -1, 1, -1, 1, -1, -1, 1, -1, -1, 1, 1, -1, -1, 1, 1, 1, 1, -1, -1, -1, -1, 1, -1, 1, 1, 1, 1, 1, -1, -1, -1, -1, 1, -1, 1, 1, -1, 1, 1, -1, -1, -1, 1, -1, 1, -1, -1, -1, 1, 1, -1, 1, 1, -1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, 1, -1, -1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1, 1, 1, 1, 1, -1, 1, -1, 1, -1, 1, 1, -1, -1, 1, 1, -1, -1, -1, 1, -1, 1, 1, -1, 1, -1, -1, 1, 1, 1, -1, 1, 1, -1, -1, 1, -1, 1, -1, -1, -1, -1, -1, 1, -1, 1, 1, -1, 1, -1, -1, -1, -1, 1, -1, -1, 1, 1, -1, -1, 1, -1, 1, -1, -1, -1, -1, 1, 1, 1, -1, 1, 1, -1, -1, -1, -1, 1, 1, -1, 1, -1, -1, -1, -1, 1, 1, -1, -1, 1, -1, -1, -1, 1, -1, 1, 1, 1, 1, 1, 1, -1, 1, -1, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, -1, -1, 1, -1, 1, 1, 1, -1, 1, -1, 1, -1, -1, 1, 1, -1, -1, -1, -1, 1, -1, -1, -1, 1, 1, -1, -1, 1, 1, -1, -1, -1, -1, 1, -1, 1, 1, -1, 1, -1, -1, 1, 1, 1, -1, 1, -1, -1, -1, -1, 1, 1, -1, 1, -1, -1, 1, -1, 1, 1, -1, 1, -1, -1, -1, -1, 1, 1, -1, 1, 1, 1, -1, -1, 1, 1, -1, -1, -1, 1, 1, -1, -1, -1, -1, -1, 1, 1, -1, 1, -1, 1, -1, -1, -1, 1, -1, 1, -1, 1, 1, -1, 1, 1, -1, 1, 1, -1, -1, -1, 1, 1, 1, 1, 1, -1, -1, -1, 1, -1, 1, 1, 1, 1, 1, 1, 1, -1, 1, 1, -1, -1, 1, 1, 1, -1, -1, 1, -1, 1, -1, -1, -1, -1, 1, 1, 1, -1, 1, 1, -1, 1, -1, -1, -1, 1, 1, 1, 1, 1, -1, 1, 1, 1, -1, 1, 1, 1, -1, 1, 1, -1, 1, 1, -1, -1, -1, -1, 1, 1, -1, -1, 1, -1, 1, -1, -1, 1, -1, 1, 1, -1, -1, 1, -1, 1, 1, 1, 1, -1, 1, -1, 1, -1, -1, 1, -1, 1, 1, 1, -1, 1, 1, 1, 1, 1, -1, -1, -1, 1, 1, -1, 1, 1, -1, 1, -1, 1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, -1, 1, -1, 1, 1, 1, -1, -1, -1, 1, 1, -1, -1, 1, -1, 1, -1, -1, 1, -1, 1, -1, -1, 1, 1, 1, -1, -1, 1, 1, -1, 1, 1, 1, -1, 1, -1, -1, -1, 1, -1, 1, 1, -1, 1, 1, 1, -1, 1, 1, 1, 1, 1, -1, -1, -1, -1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, -1, 1, 1, -1, -1, -1, 1, 1, -1, 1, -1, 1, 1, 1, -1, 1, -1, -1, -1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1, 1, 1, -1, -1, -1, 1, 1, 1, 1, -1, 1, -1, 1, 1, -1, 1, 1, 1, -1, -1, 1, 1, -1, -1, -1, 1, 1, -1, 1, 1, -1, -1, -1, 1, -1, 1, -1, 1, 1, -1, 1, 1, -1, -1, 1, -1, -1, -1, 1, -1, -1, -1, 1, -1, 1, 1, -1, -1, 1, 1, -1, -1, -1, 1, 1, 1, 1, 1, -1, -1, -1, 1, 1, -1, 1, 1, 1, 1, -1, 1, 1, -1, 1, -1, 1, 1, 1, -1, 1, 1, 1, 1, 1, -1, 1, 1, -1, 1, 1, -1, 1, -1, 1, 1, -1, -1, 1, 1, 1, -1, 1, 1, -1, 1, 1, 1, -1, 1, -1, 1, -1, -1, -1, -1, 1, 1, -1, 1, 1, 1, -1, 1, -1, -1, -1, 1, 1, -1, -1, 1, 1, 1, -1, -1, -1, 1, 1, -1, 1, 1, -1, 1, 1, 1, -1, -1, -1, 1, -1, 1, 1, -1, -1, -1, 1, 1, 1, 1, -1, -1, 1, 1, -1, -1, -1, 1, -1, 1, -1, 1, -1, -1, -1, 1, -1, 1, -1, 1, 1, -1, 1, -1, -1, 1, 1, 1, -1, 1, 1, 1, 1, 1, -1, -1, 1, 1, 1, -1, -1, 1, -1, 1, 1, 1, -1, 1, 1, 1, 1, 1, -1, 1, -1, -1, -1, 1, 1, -1, -1, -1, -1, -1, 1, -1, 1, -1, 1, -1, 1, -1, -1, 1, -1, -1, 1, -1, 1, 1, 1, 1, 1, 1, -1, 1, 1, -1, 1, 1, 1, 1, 1, 1, -1, 1, 1, -1, 1, 1, 1, 1, -1, -1, -1, -1, -1, 1, 1, -1, 1, -1, 1, 1, -1, 1, -1, 1, 1, -1, 1, 1, 1, -1, -1, -1, -1, -1, -1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, -1, -1, -1, -1, 1, 1, -1, 1, -1, -1, 1, 1, -1, 1, -1, 1, 1, -1, 1, -1, -1, -1, 1, 1, 1, 1, -1, -1, 1, 1, 1, 1, -1, -1, -1, 1, -1, -1, -1, 1, 1, -1, -1, -1, -1, -1, 1, 1, -1, -1, 1, 1, -1, 1, 1, 1, -1, 1, -1, -1, -1, 1, 1, -1, -1, 1, -1, -1, -1, -1, 1, -1, 1, -1, -1, 1, -1, -1, -1, 1, 1, -1, -1, 1, 1, 1, -1, -1, 1, 1, 1, 1, 1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, 1, -1, 1, -1, -1, 1, -1, -1, 1, -1, -1, -1, -1, -1, -1, 1, -1, 1, -1, 1, -1, 1, 1, 1, -1, -1, 1, 1, -1, -1, 1, 1, -1, 1, 1, -1, -1, 1, -1, 1, -1, -1, 1, 1, -1, 1, 1, 1, 1, -1, 1, -1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, -1, -1, 1, 1, -1, -1, 1, 1, 1, -1, 1, -1, -1, -1, 1, -1, -1, 1, 1, -1, -1, -1, 1, -1, -1, 1, -1, 1, 1, 1, -1, -1, -1, 1, 1, 1, -1, -1, 1, 1, -1, 1, -1, 1, -1, 1, -1, 1, 1, -1, 1, -1, -1, 1, 1, 1, 1, -1, 1, -1, 1, 1, -1, -1, 1, -1, -1, 1, 1, -1, -1, 1, -1, 1, 1, -1, 1, 1, -1, 1, -1, -1, 1, 1, -1, 1, 1, 1, -1, -1, -1, 1, -1, -1, -1, 1, -1, -1, -1, 1, 1, -1, 1, 1, -1, -1, -1, 1, 1, 1, -1, 1, 1, 1, -1, 1, 1, -1, -1, -1, 1, 1, 1, 1, -1, 1, 1, 1, -1, -1, 1, -1, 1, 1, -1, 1, 1, 1, -1, 1, 1, -1, 1, -1, 1, 1, -1, 1, -1, 1, 1, -1, -1, 1, -1, -1, -1, -1, 1, 1, -1, -1, 1, -1, -1, 1, 1, -1, -1, -1, 1, 1, 1, -1, -1, 1, -1, 1, 1, 1, 1, -1, 1, 1, 1, 1, -1, 1, -1, 1, 1, -1, -1, 1, 1, 1, -1, -1, -1, -1, 1, 1, -1, -1, 1, 1, 1, -1, 1, 1, 1, 1, -1, 1, -1, 1, 1, 1, 1, 1, -1, -1, -1, -1, 1, 1, -1, -1, 1, 1, 1, 1, 1, -1, 1, 1, -1, 1, 1, 1, -1, 1, -1, 1, -1, -1, -1, -1, -1, 1, -1, -1, -1, 1, -1, 1, -1, 1, 1, -1, 1, -1, -1, 1, 1, -1, 1, 1, 1, 1, 1, -1, 1, -1, -1, 1, 1, -1, -1, -1, 1, -1, 1, -1, 1, 1, 1, -1, -1, 1, -1, -1, -1, -1, -1, -1, 1, 1, -1, 1, 1, -1, -1, 1, -1, -1, 1, -1, -1, 1, 1, -1, 1, -1, -1, 1, -1, -1, -1, -1, 1, 1, -1, 1, -1, -1, 1, -1, 1, 1, 1, -1, 1, 1, 1, 1, -1, 1, -1, 1, 1, 1, -1, -1, 1, 1, -1, -1, 1, -1, -1, -1, 1, -1, -1, 1, 1, 1, 1, 1, -1, 1, 1, -1, 1, -1, -1, -1, -1, 1, -1, 1, -1, -1, 1, -1, 1, 1, -1, -1, 1, 1, -1, -1, -1, -1, 1, -1, 1, 1, 1, -1, 1, 1, 1, -1, -1, -1, 1, 1, -1, -1, -1, 1, -1, 1, 1, -1, -1, 1, -1, 1, 1, -1, 1, -1, 1, 1, 1, -1, 1, 1, 1, 1, 1, -1, 1, -1, -1, -1, -1, 1, 1, 1, -1, 1, -1, -1, 1, -1, 1, -1, 1, 1, -1, 1, 1, 1, 1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, -1, -1, 1, -1, -1, -1, 1, 1, 1, -1, -1, 1, 1, -1, 1, 1, 1, 1, 1, -1, 1, -1, 1, 1, -1, -1, 1, -1, -1, 1, -1, -1, -1, 1, -1, 1, -1, -1, -1, 1, -1, -1, -1, 1, 1, 1, 1, 1, -1, -1, -1, 1, 1, 1, 1, 1, 1, -1, 1, 1, -1, 1, 1, -1, -1, 1, 1, 1, 1, 1, -1, -1, 1, 1, 1, -1, -1, -1, -1, 1, 1, 1, 1, -1, 1, -1, 1, 1, -1, -1, -1, -1, 1, 1, 1, -1, -1, 1, 1, -1, -1, 1, -1, -1, -1, 1, 1, -1, 1, 1, -1, -1, -1, -1, 1, -1, -1, 1, -1, -1, -1, 1, 1, -1, -1, -1, -1, 1, 1, -1, 1, 1, 1, 1, 1, -1, -1, 1, 1, -1, -1, 1, 1, 1, -1, -1, 1, 1, 1, -1, 1, -1, -1, 1, 1, 1, -1, 1, -1, -1, -1, 1, -1, 1, -1, -1, 1, -1, -1, -1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, 1, -1, 1, -1, 1, 1, 1, -1, 1, -1, -1, 1, -1, -1, -1, -1, 1, 1, 1, 1, -1, -1, 1, 1, 1, 1, -1, -1, -1, -1, 1, -1, 1, 1, 1, -1, 1, -1, -1, 1, 1, 1, 1, -1, -1, 1, 1, 1, -1, 1, 1, -1, 1, 1, -1, 1, 1, -1, 1, 1, -1, 1, 1, -1, 1, 1, -1, 1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, -1, -1, 1, 1, 1, -1, -1, -1, 1, -1, 1, 1, -1, 1, -1, 1, 1, -1, 1, -1, -1, 1, 1, 1, 1, 1, -1, -1, -1, -1, 1, 1, 1, 1, -1, -1, -1, 1, 1, 1, 1, -1, -1, -1, -1, -1, 1, 1, 1, 1, -1, 1, -1, 1, -1, -1, -1, 1, 1, -1, -1, -1, -1, -1, 1, -1, 1, 1, 1, 1, -1, 1, 1, 1, -1, 1, -1, -1, -1, 1, -1, -1, -1, 1, -1, 1, -1, 1, 1, -1, -1, -1, 1, -1, -1, 1, 1, 1, -1, -1, 1, 1, -1, 1, 1, 1, -1, -1, 1, -1, -1, 1, 1, 1, -1, -1, 1, -1, -1, 1, 1, -1, -1, -1, -1, -1, 1, -1, -1, 1, -1, 1, 1, -1, 1, -1, -1, -1, 1, 1, 1, 1, 1, -1, -1, 1, -1, 1, 1, 1, -1, 1, -1, -1, 1, 1, 1, -1, 1, 1, 1, -1, -1, 1, 1, 1, 1, -1, -1, 1, -1, 1, 1, -1, -1, -1, 1, -1, -1, 1, 1, 1, -1, 1, 1, 1, 1, 1, 1, -1, -1, 1, 1, -1, -1, -1, -1, 1, 1, 1, 1, 1, -1, 1, 1, -1, 1, -1, -1, 1, 1, 1, -1, 1, 1, -1, -1, 1, 1, 1, -1, -1, 1, -1, -1, 1, -1, 1, -1, -1, 1, 1, 1, -1, -1, -1, 1, 1, 1, -1, 1, 1, -1, -1, 1, 1, 1, 1, -1, -1, -1, 1, -1, -1, 1, -1, 1, -1, 1, -1, -1, -1, -1, 1, 1, -1, 1, 1, -1, -1, 1, -1, 1, -1, -1, -1, -1, 1, 1, -1, 1, -1, -1, 1, -1, -1, 1, 1, -1, -1, 1, 1, 1, -1, -1, -1, -1, 1, -1, -1, 1, -1, 1, -1, -1, -1, -1, 1, 1, -1, 1, 1, 1, 1, 1, 1, -1, 1, 1, -1, 1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, 1, -1, 1, -1, -1, 1, 1, -1, -1, -1, 1, -1, -1, -1, 1, 1, 1, -1, 1, -1, 1, 1, -1, 1, -1, 1, 1, 1, -1, 1, -1, -1, -1, -1, -1, -1, -1, 1, -1, -1, 1, -1, 1, 1, -1, 1, 1, -1, 1, -1, 1, 1, 1, -1, 1, -1, 1, 1, 1, -1, -1, 1, 1, -1, 1, 1, -1, -1, 1, -1, -1, 1, 1, 1, -1, 1, -1, -1, 1, 1, -1, -1, -1, -1, 1, -1, 1, -1, -1, 1, -1, 1, 1, -1, 1, -1, 1, 1, 1, -1, -1, 1, -1, -1, -1, 1, -1, -1, -1, 1, 1, 1, 1, 1, 1, -1, -1, -1, 1, 1, -1, 1, -1, -1, -1, 1, 1, 1, 1, 1, 1, -1, -1, 1, -1, 1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1, -1, -1, -1, -1, -1, -1, -1, 1, -1, 1, -1, -1, 1, -1, -1, -1, 1, -1, -1, 1, -1, -1, 1, 1, -1, 1, 1, -1, -1, 1, -1, -1, -1, -1, 1, -1, -1, -1, 1, -1, 1, -1, -1, 1, 1, -1, -1, 1, 1, -1, 1, 1, -1, 1, -1, 1, -1, -1, 1, -1, -1, 1, 1, -1, -1, -1, 1, 1, -1, -1, -1, 1, -1, 1, 1, -1, 1, -1, 1, 1, 1, 1, -1, -1, -1, 1, 1, -1, 1, -1, -1, 1, -1, 1, -1, -1, 1, 1, -1, 1, -1, -1, 1, 1, 1, -1, 1, -1, -1, -1, -1, -1, 1, -1, 1, -1, 1, -1, -1, 1, -1, 1, 1, -1, -1, -1, -1, -1, 1, 1, -1, 1, 1, -1, 1, 1, 1, 1, -1, -1, -1, 1, 1, 1, 1, 1, 1, -1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, 1, -1, 1, -1, -1, 1, -1, -1, 1, -1, 1, 1, -1, 1, 1, 1, 1, 1, -1, 1, -1, -1, 1, 1, -1, -1, -1, 1, 1, 1, 1, -1, -1, 1, -1, 1, 1, -1, 1, -1, 1, 1, -1, 1, 1, -1, -1, -1, 1, -1, 1, 1, -1, 1, -1, 1, -1, -1, 1, -1, -1, 1, -1, 1, -1, 1, -1, -1, 1, 1, 1, -1, -1, 1, 1, 1, 1, 1, -1, -1, -1, 1, 1, 1, -1, -1, -1, 1, 1, 1, 1, -1, 1, 1, 1, -1, 1, -1, -1, -1, -1, -1, 1, -1, -1, -1, -1, -1, -1, -1, 1, -1, -1, -1, 1, -1, 1, -1, 1, 1, 1, 1, 1, -1, 1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, 1, -1, -1, 1, -1, -1, -1, 1, -1, -1, 1, -1, 1, 1, -1, 1, -1, 1, -1, 1, 1, 1, 1, -1, 1, -1, -1, 1, 1, 1, -1, 1, 1, 1, -1, 1, 1, 1, 1, -1, 1, -1, 1, 1, 1, -1, 1, -1, 1, 1, -1, 1, -1, 1, -1, 1, 1, -1, -1, 1, -1, -1, 1, 1, -1, -1, 1, 1, -1, 1, -1, -1, -1, 1, -1, 1, 1, -1, 1, 1, -1, 1, -1, 1, 1, -1, -1, 1, -1, -1, -1, 1, -1, -1, -1, 1, 1, 1, -1, -1, 1, -1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, 1, -1, 1, -1, 1, 1, 1, -1, 1, -1, -1, -1, 1, -1, -1, -1, 1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, 1, -1, -1, 1, 1, -1, 1, -1, -1, 1, -1, -1, -1, 1, -1, -1, 1, 1, -1, -1, -1, 1, -1, -1, 1, -1, 1, 1, 1, 1, 1, -1, 1, -1, -1, 1, 1, 1, -1, -1, -1, 1, 1, 1, 1, -1, -1, 1, -1, 1, 1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, -1, 1, -1, -1, -1, -1, 1, -1, 1, -1, -1, -1, -1, 1, -1, 1, 1, -1, 1, 1, -1, 1, 1, 1, -1, 1, -1, -1, 1, 1, -1, 1, -1, -1, -1, -1, 1, -1, -1, 1, -1, 1, -1, -1, -1, 1, -1, -1, 1, -1, 1, 1, -1, -1, -1, -1, 1, 1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, 1, 1, 1, 1, -1, 1, -1, 1, 1, -1, 1, -1, 1, 1, -1, 1, 1, -1, 1, -1, -1, 1, -1, -1, -1, -1, -1, -1, 1, 1, 1, -1, -1, 1, 1, 1, -1, -1, 1, -1, 1, 1, 1, 1, 1, -1, 1, 1, -1, -1, -1, -1, 1, 1, 1, -1, 1, 1, -1, -1, -1, 1, -1, 1, 1, 1, -1, 1, 1, -1, 1, 1, -1, 1, 1, 1, -1, -1, 1, 1, -1, 1, -1, -1, -1, 1, 1, 1, -1, -1, 1, 1, -1, 1, 1, 1, 1, -1, -1, -1, -1, 1, -1, 1, 1, -1, -1, -1, 1, 1, -1, -1, 1, 1, -1, 1, -1, -1, 1, -1, -1, 1, 1, -1, -1, 1, 1, -1, -1, 1, -1, 1, -1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, -1, -1, -1, -1, 1, -1, 1, 1, 1, -1, 1, -1, -1, -1, 1, -1, -1, -1, -1, 1, -1, 1, 1, -1, 1, 1, -1, 1, 1, -1, -1, -1, -1, 1, 1, -1, 1, 1, -1, 1, 1, -1, 1, -1, 1, 1, -1, 1, -1, 1, -1, -1, 1, -1, 1, 1, -1, -1, 1, -1, -1, -1, -1, -1, 1, -1, 1, -1, 1, -1, -1, 1, 1, 1, -1, -1, 1, -1, 1, -1, -1, -1, 1, 1, -1, -1, 1, 1, 1, 1, -1, -1, -1, -1, -1, 1, -1, 1, -1, -1, 1, -1, -1, -1, -1, -1, 1, -1, -1, -1, 1, -1, -1, -1, 1, -1, 1, -1, 1, 1, -1, -1, 1, -1, 1, 1, 1, 1, -1, -1, -1, 1, 1, 1, -1, 1, -1, -1, 1, -1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, -1, 1, -1, -1, -1, -1, -1, -1, 1, -1, 1, -1, 1, 1, 1, -1, -1, 1, -1, -1, 1, 1, -1, -1, 1, 1, -1, -1, -1, 1, 1, 1, -1, 1, 1, 1, 1, 1, 1, -1, 1, 1, -1, 1, -1, 1, -1, 1, -1, -1, 1, -1, -1, 1, -1, -1, 1, 1, 1, -1, -1, 1, -1, -1, -1, -1, -1, 1, 1, 1, 1, -1, -1, -1, 1, -1, -1, 1, 1, 1, 1, -1, 1, 1, 1, 1, -1, 1, 1, -1, -1, -1, 1, -1, 1, -1, -1, 1, -1, -1, 1, 1, -1, 1, -1, 1, -1, 1, 1, -1, -1, -1, -1, -1, -1, -1, 1, -1, -1, 1, -1, 1, -1, 1, 1, 1, 1, -1, -1, -1, 1, 1, -1, -1, 1, 1, 1, 1, 1, 1, -1, -1, 1, -1, 1, 1, 1, 1, 1, 1, -1, -1, 1, -1, -1, 1, 1, -1, 1, 1, 1, 1, 1, -1, 1, 1, 1, 1, -1, 1, -1, -1, 1, 1, -1, -1, -1, -1, -1, -1, 1, -1, 1, -1, 1, 1, 1, -1, -1, 1, -1, 1, 1, 1, 1, 1, 1, 1, -1, 1, 1, 1, 1, 1, -1, -1, 1, -1, 1, 1, -1, 1, -1, 1, 1, -1, 1, 1, -1, -1, 1, -1, -1, -1, -1, -1, 1, -1, 1, -1, 1, 1, -1, 1, -1, 1, -1, -1, -1, 1, -1, 1, -1, -1, -1, -1, 1, -1, 1, 1, -1, 1, -1, -1, 1, -1, -1, -1, 1, 1, -1, -1, -1, -1, 1, -1, -1, 1, 1, 1, 1, -1, -1, -1, 1, -1, -1, -1, -1, 1, 1, 1, 1, 1, -1, -1, 1, 1, -1, -1, 1, 1, -1, 1, 1, -1, -1, -1, 1, -1, -1, -1, -1, -1, -1, 1, -1, -1, 1, 1, -1, -1, -1, -1, -1, 1, 1, -1, 1, 1, 1, 1, -1, 1, -1, -1, -1, 1, 1, -1, 1, -1, 1, 1, -1, -1, 1, -1, 1, 1, -1, 1, 1, 1, 1, 1, 1, -1, -1, -1, 1, -1, -1, 1, 1, -1, -1, -1, -1, -1, -1, -1, 1, -1, -1, 1, -1, 1, -1, 1, -1, 1, 1, 1, 1, -1, -1, -1, 1, 1, -1, 1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, -1, -1, 1, -1, 1, -1, -1, -1, -1, -1, 1, 1, -1, -1, 1, 1, -1, -1, 1, -1, 1, 1, 1, 1, -1, -1, 1, 1, -1, -1, -1, 1, -1, -1, -1, 1, 1, 1, 1, -1, -1]
+
+
+known_symbols_4512_impulse = 4512*[1,]
+
+known_symbols_4512_3 = [-1, -1, 1, -1, 1, 1, -1, -1, 1, -1, 1, 1, -1, 1, -1, -1, 1, -1, 1, -1, 1, 1, -1, -1, -1, 1, -1, 1, 1, -1, 1, -1, -1, -1, -1, -1, -1, -1, 1, 1, -1, -1, 1, 1, 1, -1, 1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, -1, -1, 1, -1, 1, -1, -1, 1, -1, 1, 1, 1, 1, -1, 1, -1, 1, -1, 1, -1, -1, -1, 1, -1, -1, -1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, 1, -1, -1, 1, -1, 1, 1, 1, -1, -1, -1, -1, -1, -1, 1, -1, -1, -1, -1, 1, -1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, 1, 1, 1, 1, -1, -1, 1, -1, 1, -1, 1, 1, 1, 1, -1, -1, 1, -1, 1, 1, 1, 1, -1, 1, -1, -1, 1, -1, 1, 1, 1, -1, -1, -1, 1, 1, 1, 1, 1, 1, -1, -1, 1, 1, 1, -1, -1, 1, -1, -1, 1, 1, 1, -1, -1, 1, 1, -1, 1, -1, -1, -1, -1, -1, -1, 1, 1, -1, -1, 1, -1, -1, 1, -1, 1, -1, -1, 1, 1, -1, 1, 1, 1, 1, -1, 1, 1, 1, -1, 1, -1, 1, 1, 1, -1, 1, 1, -1, 1, 1, 1, -1, 1, 1, 1, 1, -1, 1, -1, -1, 1, -1, -1, 1, 1, 1, -1, 1, -1, -1, -1, -1, -1, 1, -1, 1, -1, 1, 1, 1, 1, -1, 1, -1, -1, -1, 1, -1, 1, 1, -1, -1, -1, 1, 1, -1, -1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, 1, -1, 1, 1, 1, 1, -1, 1, -1, 1, 1, 1, -1, -1, 1, -1, 1, -1, -1, -1, -1, -1, 1, 1, -1, 1, 1, 1, -1, 1, -1, 1, 1, -1, -1, -1, 1, -1, -1, 1, -1, -1, 1, 1, -1, 1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1, 1, -1, 1, 1, 1, -1, -1, 1, 1, 1, -1, 1, 1, -1, 1, 1, 1, -1, 1, -1, 1, 1, -1, -1, 1, -1, -1, -1, 1, 1, -1, -1, 1, -1, -1, 1, -1, 1, 1, -1, -1, -1, -1, 1, -1, -1, 1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, -1, -1, -1, 1, -1, 1, 1, 1, 1, 1, 1, 1, -1, -1, 1, -1, 1, -1, -1, 1, -1, 1, 1, -1, 1, -1, 1, 1, -1, 1, -1, -1, -1, 1, 1, -1, 1, 1, 1, 1, -1, 1, -1, -1, -1, 1, -1, -1, 1, 1, 1, -1, 1, -1, 1, 1, -1, -1, -1, -1, 1, -1, 1, -1, -1, -1, 1, 1, -1, -1, 1, -1, -1, 1, 1, -1, -1, 1, -1, -1, 1, -1, -1, -1, 1, -1, 1, -1, 1, 1, 1, 1, 1, 1, -1, -1, 1, -1, 1, -1, -1, -1, -1, -1, 1, 1, -1, 1, 1, 1, 1, -1, 1, 1, 1, -1, -1, 1, 1, 1, -1, 1, 1, 1, 1, 1, -1, 1, -1, -1, -1, -1, -1, -1, 1, 1, -1, -1, 1, -1, 1, 1, 1, 1, -1, 1, -1, 1, -1, -1, 1, -1, -1, -1, -1, 1, 1, -1, 1, 1, 1, -1, -1, 1, 1, 1, -1, -1, -1, -1, 1, -1, 1, -1, 1, -1, -1, -1, -1, -1, -1, 1, 1, -1, 1, 1, 1, 1, 1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, 1, 1, 1, 1, 1, 1, -1, 1, -1, 1, -1, -1, -1, 1, 1, -1, 1, 1, 1, -1, 1, -1, -1, 1, 1, 1, 1, -1, 1, 1, 1, 1, 1, 1, -1, -1, -1, 1, 1, 1, -1, 1, 1, -1, -1, -1, -1, 1, 1, 1, -1, 1, 1, -1, 1, 1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, -1, -1, 1, -1, -1, 1, 1, -1, -1, -1, -1, -1, -1, 1, 1, -1, -1, 1, 1, -1, 1, -1, -1, -1, -1, 1, -1, 1, -1, 1, 1, 1, -1, 1, 1, -1, -1, 1, 1, 1, 1, -1, -1, 1, -1, -1, -1, 1, -1, -1, -1, 1, 1, -1, -1, -1, 1, -1, 1, -1, 1, 1, -1, 1, -1, 1, 1, 1, -1, 1, 1, 1, -1, -1, 1, -1, -1, -1, -1, 1, 1, 1, 1, 1, -1, 1, -1, -1, 1, 1, -1, 1, -1, 1, -1, -1, 1, -1, -1, -1, 1, 1, -1, -1, 1, 1, 1, -1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, -1, -1, 1, 1, -1, -1, 1, -1, 1, 1, 1, -1, -1, 1, 1, -1, 1, -1, -1, -1, 1, -1, -1, -1, 1, 1, -1, 1, -1, 1, 1, -1, 1, -1, -1, 1, 1, 1, -1, -1, -1, 1, 1, -1, 1, 1, 1, 1, -1, 1, 1, -1, -1, 1, 1, 1, -1, 1, 1, 1, -1, 1, 1, 1, 1, 1, -1, 1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1, -1, -1, 1, -1, 1, 1, 1, 1, -1, -1, -1, 1, 1, -1, -1, -1, -1, -1, 1, -1, -1, 1, 1, -1, -1, 1, 1, -1, -1, 1, -1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, 1, 1, -1, 1, -1, -1, -1, 1, -1, -1, 1, 1, 1, -1, -1, 1, -1, 1, 1, 1, -1, -1, 1, -1, -1, 1, 1, 1, -1, -1, 1, -1, 1, 1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, 1, -1, -1, 1, -1, 1, -1, -1, -1, -1, 1, -1, -1, 1, 1, -1, 1, -1, -1, -1, -1, -1, 1, 1, 1, 1, -1, 1, 1, 1, 1, 1, 1, -1, 1, 1, 1, 1, -1, -1, -1, -1, 1, -1, -1, 1, 1, -1, 1, 1, -1, 1, -1, 1, -1, -1, 1, -1, 1, -1, -1, 1, -1, -1, 1, 1, 1, -1, 1, 1, 1, 1, 1, -1, 1, -1, -1, 1, -1, 1, -1, -1, 1, 1, -1, 1, -1, -1, -1, -1, 1, -1, 1, -1, 1, 1, 1, -1, -1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, -1, -1, 1, 1, 1, 1, -1, -1, 1, 1, -1, -1, 1, -1, -1, 1, -1, 1, 1, -1, 1, 1, 1, -1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, 1, -1, 1, -1, 1, -1, -1, 1, 1, 1, 1, 1, 1, -1, 1, -1, -1, 1, -1, 1, 1, -1, 1, 1, 1, -1, -1, 1, 1, -1, 1, 1, 1, -1, -1, 1, -1, 1, 1, -1, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, -1, 1, 1, -1, 1, -1, 1, -1, 1, 1, -1, 1, -1, 1, 1, -1, 1, 1, 1, -1, -1, 1, -1, 1, -1, -1, -1, 1, -1, -1, -1, 1, -1, -1, 1, -1, 1, -1, 1, 1, 1, 1, 1, -1, 1, 1, 1, 1, -1, 1, -1, 1, 1, -1, 1, -1, 1, 1, -1, -1, 1, -1, 1, 1, 1, -1, 1, -1, 1, 1, -1, 1, 1, 1, -1, 1, 1, 1, -1, -1, 1, -1, -1, 1, 1, -1, -1, 1, 1, -1, -1, -1, -1, -1, 1, -1, 1, 1, -1, -1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, 1, -1, 1, 1, 1, -1, 1, 1, 1, -1, 1, 1, -1, 1, -1, -1, -1, 1, -1, 1, -1, 1, 1, -1, 1, -1, -1, 1, -1, 1, -1, -1, -1, 1, -1, 1, 1, 1, 1, -1, -1, 1, -1, 1, -1, 1, 1, -1, -1, 1, 1, 1, -1, 1, -1, -1, -1, -1, -1, 1, -1, 1, -1, -1, 1, -1, 1, 1, 1, 1, 1, -1, 1, 1, -1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, 1, -1, 1, -1, 1, -1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1, -1, -1, -1, 1, 1, 1, 1, 1, -1, -1, -1, 1, 1, 1, 1, 1, 1, -1, 1, -1, 1, -1, -1, 1, 1, 1, 1, -1, -1, 1, -1, 1, 1, 1, 1, -1, 1, 1, 1, 1, -1, 1, 1, -1, 1, -1, 1, -1, -1, 1, -1, -1, -1, -1, 1, -1, 1, -1, 1, 1, 1, 1, 1, -1, 1, -1, 1, 1, 1, -1, -1, 1, 1, 1, 1, -1, -1, 1, 1, -1, 1, 1, 1, 1, -1, -1, 1, 1, 1, -1, 1, 1, -1, -1, -1, -1, 1, 1, 1, 1, 1, -1, -1, 1, -1, 1, 1, 1, -1, -1, -1, -1, -1, -1, 1, -1, 1, -1, -1, -1, 1, -1, 1, -1, 1, -1, -1, -1, 1, -1, 1, -1, 1, 1, 1, -1, -1, -1, -1, 1, -1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, -1, 1, -1, 1, 1, -1, 1, -1, 1, 1, 1, -1, 1, -1, -1, 1, 1, 1, -1, 1, 1, 1, -1, -1, 1, -1, -1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, -1, 1, -1, -1, 1, -1, 1, -1, 1, 1, 1, 1, 1, 1, -1, 1, -1, 1, -1, -1, 1, -1, 1, -1, -1, -1, 1, 1, 1, 1, -1, 1, 1, 1, -1, -1, 1, 1, 1, 1, 1, -1, 1, -1, -1, -1, -1, -1, 1, 1, 1, -1, 1, -1, 1, -1, -1, -1, 1, -1, -1, -1, 1, 1, 1, 1, -1, -1, -1, 1, -1, -1, 1, 1, 1, -1, -1, -1, -1, -1, -1, 1, -1, 1, -1, 1, 1, 1, 1, -1, -1, 1, 1, -1, 1, 1, 1, -1, 1, -1, -1, -1, 1, -1, 1, 1, -1, -1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, 1, -1, -1, -1, 1, -1, 1, -1, -1, 1, 1, -1, 1, -1, -1, -1, -1, 1, -1, 1, 1, -1, -1, -1, 1, 1, 1, 1, 1, -1, -1, -1, 1, -1, -1, 1, 1, -1, -1, -1, 1, -1, 1, 1, 1, -1, -1, 1, 1, -1, -1, -1, 1, -1, 1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, -1, -1, 1, -1, 1, 1, -1, -1, -1, -1, 1, -1, -1, 1, -1, 1, 1, 1, -1, 1, -1, 1, -1, 1, -1, -1, -1, 1, -1, -1, -1, 1, -1, -1, 1, -1, 1, -1, -1, 1, -1, 1, 1, 1, 1, 1, -1, -1, -1, 1, 1, -1, 1, 1, 1, -1, -1, 1, 1, -1, -1, 1, -1, -1, 1, 1, -1, -1, -1, -1, 1, -1, -1, 1, -1, -1, -1, 1, 1, -1, -1, 1, -1, 1, -1, -1, 1, -1, -1, 1, -1, 1, -1, 1, 1, 1, -1, 1, 1, -1, -1, -1, 1, 1, -1, 1, 1, -1, 1, 1, 1, 1, 1, -1, 1, -1, -1, 1, 1, -1, 1, 1, 1, -1, -1, 1, -1, -1, -1, -1, -1, 1, -1, 1, 1, 1, 1, -1, 1, -1, 1, 1, -1, 1, -1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, 1, 1, 1, -1, 1, -1, -1, -1, -1, 1, -1, -1, 1, 1, 1, -1, 1, -1, 1, 1, -1, -1, 1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, 1, -1, 1, 1, -1, 1, -1, -1, 1, -1, -1, -1, 1, 1, 1, -1, 1, -1, -1, 1, -1, -1, -1, -1, -1, -1, 1, -1, -1, -1, -1, 1, -1, 1, 1, 1, -1, 1, -1, -1, -1, 1, 1, -1, 1, -1, -1, -1, -1, 1, -1, -1, -1, -1, 1, -1, 1, 1, -1, 1, 1, -1, 1, 1, 1, -1, 1, 1, 1, -1, 1, 1, 1, -1, -1, -1, -1, 1, -1, -1, -1, -1, -1, 1, -1, -1, 1, -1, 1, -1, 1, -1, -1, 1, -1, 1, -1, -1, 1, 1, -1, -1, 1, 1, -1, -1, 1, 1, -1, 1, 1, -1, 1, -1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, 1, 1, 1, -1, 1, -1, -1, -1, -1, 1, -1, -1, -1, -1, 1, -1, 1, 1, -1, -1, -1, 1, -1, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, -1, -1, 1, -1, 1, -1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, -1, -1, 1, 1, 1, -1, -1, 1, -1, 1, 1, 1, -1, 1, -1, 1, 1, 1, -1, 1, 1, -1, 1, 1, -1, 1, -1, -1, 1, 1, 1, -1, 1, -1, -1, 1, -1, -1, -1, 1, -1, -1, 1, -1, -1, 1, 1, -1, -1, -1, 1, 1, -1, -1, 1, 1, -1, -1, -1, 1, 1, -1, 1, 1, 1, -1, 1, -1, -1, 1, 1, 1, 1, -1, 1, 1, 1, -1, 1, -1, 1, 1, 1, 1, -1, -1, 1, 1, 1, -1, 1, -1, 1, -1, -1, -1, -1, 1, -1, 1, -1, -1, -1, 1, -1, -1, -1, 1, 1, -1, 1, 1, 1, 1, -1, 1, 1, 1, 1, -1, -1, -1, 1, -1, -1, 1, 1, 1, -1, 1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, -1, 1, -1, -1, -1, 1, 1, -1, -1, -1, -1, -1, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, -1, 1, 1, -1, 1, -1, -1, -1, 1, -1, 1, -1, 1, -1, -1, 1, -1, -1, 1, -1, 1, -1, 1, -1, -1, 1, -1, 1, 1, 1, -1, 1, -1, 1, 1, -1, -1, -1, 1, -1, 1, 1, 1, 1, -1, -1, 1, 1, 1, -1, -1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, 1, 1, -1, 1, 1, -1, 1, -1, -1, -1, 1, 1, -1, -1, -1, -1, 1, 1, -1, -1, 1, 1, -1, 1, -1, -1, -1, 1, -1, -1, -1, -1, -1, -1, -1, 1, 1, -1, -1, -1, 1, -1, 1, -1, 1, -1, 1, -1, -1, 1, 1, -1, 1, 1, 1, -1, 1, 1, -1, 1, 1, -1, -1, -1, 1, 1, -1, -1, -1, -1, 1, -1, -1, -1, 1, 1, 1, -1, 1, 1, 1, 1, -1, -1, -1, -1, -1, 1, 1, 1, 1, -1, -1, 1, -1, 1, -1, 1, -1, 1, 1, 1, -1, 1, 1, 1, -1, 1, 1, 1, -1, 1, 1, -1, -1, 1, -1, -1, 1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, -1, -1, 1, 1, 1, 1, -1, -1, 1, -1, 1, -1, 1, -1, 1, -1, -1, 1, -1, 1, -1, -1, -1, -1, 1, 1, -1, 1, 1, 1, 1, -1, -1, 1, 1, -1, -1, 1, -1, -1, -1, 1, 1, -1, -1, -1, -1, 1, 1, 1, -1, -1, -1, -1, -1, -1, 1, -1, -1, -1, -1, -1, -1, 1, 1, -1, -1, -1, -1, 1, -1, -1, -1, 1, 1, 1, -1, 1, -1, -1, -1, -1, -1, -1, 1, -1, 1, 1, -1, 1, 1, 1, 1, -1, 1, 1, 1, 1, 1, -1, -1, 1, 1, -1, -1, -1, -1, -1, -1, -1, 1, 1, -1, 1, -1, -1, -1, 1, 1, 1, 1, 1, 1, -1, -1, 1, 1, -1, 1, -1, -1, 1, -1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, 1, -1, 1, 1, -1, -1, 1, -1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, -1, 1, -1, 1, 1, -1, 1, -1, -1, -1, 1, -1, -1, -1, 1, 1, -1, -1, 1, -1, 1, 1, 1, -1, -1, -1, -1, -1, 1, 1, 1, -1, -1, 1, -1, 1, 1, 1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, -1, -1, 1, -1, 1, -1, 1, -1, 1, -1, -1, 1, -1, 1, 1, -1, 1, -1, 1, -1, 1, 1, -1, 1, -1, 1, -1, -1, 1, -1, -1, -1, 1, -1, -1, 1, 1, -1, -1, 1, -1, 1, -1, 1, 1, 1, 1, -1, 1, 1, -1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, 1, -1, -1, 1, -1, 1, 1, -1, -1, 1, -1, -1, -1, 1, -1, 1, 1, -1, 1, 1, 1, 1, 1, -1, 1, 1, 1, -1, 1, -1, 1, -1, 1, -1, -1, 1, -1, 1, -1, -1, -1, 1, 1, -1, -1, 1, -1, 1, -1, 1, -1, 1, 1, 1, -1, 1, -1, 1, -1, 1, -1, 1, 1, 1, -1, 1, -1, 1, -1, 1, 1, 1, 1, -1, 1, 1, 1, -1, -1, -1, -1, -1, 1, -1, 1, -1, -1, 1, 1, 1, -1, -1, -1, 1, -1, -1, 1, -1, -1, -1, 1, -1, 1, -1, 1, 1, -1, 1, -1, 1, -1, -1, 1, -1, 1, -1, -1, 1, -1, -1, 1, -1, -1, 1, -1, -1, -1, -1, 1, -1, 1, 1, 1, -1, -1, -1, -1, 1, 1, 1, -1, -1, 1, -1, 1, -1, -1, -1, 1, 1, -1, 1, 1, -1, -1, 1, 1, 1, -1, -1, -1, 1, -1, 1, 1, -1, -1, -1, -1, -1, -1, 1, 1, -1, 1, -1, -1, -1, -1, 1, 1, 1, -1, 1, 1, 1, 1, -1, 1, -1, -1, -1, 1, 1, -1, -1, -1, 1, -1, 1, -1, 1, -1, -1, 1, -1, 1, 1, -1, -1, 1, -1, -1, -1, 1, -1, 1, 1, -1, -1, -1, 1, -1, 1, -1, -1, -1, -1, 1, 1, -1, 1, 1, -1, 1, 1, 1, -1, -1, -1, -1, -1, 1, 1, -1, 1, -1, 1, -1, -1, -1, -1, -1, 1, 1, -1, -1, 1, 1, 1, 1, -1, -1, 1, 1, 1, -1, 1, 1, 1, -1, 1, -1, -1, -1, -1, 1, 1, -1, -1, 1, -1, -1, 1, -1, -1, -1, 1, 1, 1, -1, -1, 1, -1, 1, 1, -1, -1, 1, -1, -1, -1, -1, -1, -1, 1, -1, 1, -1, -1, 1, -1, -1, -1, 1, 1, 1, 1, -1, 1, 1, -1, -1, 1, -1, 1, -1, 1, 1, -1, 1, 1, -1, 1, 1, 1, 1, -1, -1, -1, 1, -1, -1, 1, 1, -1, -1, 1, -1, -1, 1, 1, 1, -1, -1, -1, -1, -1, 1, -1, -1, 1, 1, 1, 1, -1, -1, -1, -1, 1, 1, -1, -1, 1, -1, -1, -1, 1, -1, 1, -1, -1, 1, 1, 1, -1, 1, -1, 1, -1, -1, -1, -1, -1, 1, -1, 1, 1, -1, -1, 1, 1, 1, 1, -1, 1, -1, 1, 1, -1, -1, 1, 1, 1, -1, -1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, -1, -1, -1, -1, 1, -1, 1, 1, 1, 1, -1, 1, -1, 1, 1, 1, 1, -1, 1, 1, 1, 1, -1, 1, -1, -1, -1, -1, 1, 1, 1, -1, 1, 1, 1, 1, -1, -1, 1, 1, -1, 1, -1, 1, -1, -1, 1, 1, -1, -1, -1, -1, 1, -1, -1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, 1, -1, -1, -1, -1, -1, 1, 1, -1, 1, -1, -1, -1, 1, 1, -1, 1, -1, -1, -1, 1, -1, 1, -1, -1, 1, -1, -1, -1, -1, 1, -1, -1, -1, 1, -1, -1, 1, -1, -1, -1, -1, -1, -1, 1, -1, 1, 1, -1, 1, -1, 1, 1, -1, 1, -1, -1, -1, -1, 1, -1, -1, -1, 1, 1, -1, -1, 1, 1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, 1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, 1, 1, -1, -1, 1, 1, -1, -1, 1, 1, 1, 1, -1, 1, -1, -1, 1, -1, 1, -1, -1, -1, -1, 1, 1, -1, -1, 1, -1, 1, 1, 1, 1, -1, -1, 1, 1, -1, 1, 1, -1, 1, 1, -1, -1, -1, 1, -1, 1, 1, -1, -1, 1, -1, 1, 1, -1, -1, 1, 1, 1, -1, 1, 1, -1, -1, 1, 1, -1, -1, 1, 1, 1, 1, 1, -1, 1, -1, 1, -1, 1, 1, 1, -1, 1, -1, 1, 1, 1, -1, 1, 1, 1, 1, -1, -1, 1, -1, 1, -1, -1, -1, -1, 1, 1, -1, 1, -1, 1, -1, 1, 1, 1, 1, -1, -1, 1, 1, -1, 1, -1, 1, -1, 1, 1, 1, -1, -1, -1, 1, -1, -1, -1, 1, 1, 1, 1, 1, -1, 1, 1, 1, 1, -1, -1, -1, 1, 1, -1, -1, 1, -1, -1, -1, 1, 1, -1, -1, 1, 1, -1, -1, -1, 1, 1, -1, -1, 1, -1, 1, -1, -1, 1, 1, -1, -1, 1, -1, 1, 1, 1, 1, -1, -1, -1, -1, 1, -1, -1, -1, -1, 1, 1, -1, -1, -1, -1, 1, -1, -1, -1, -1, -1, 1, 1, -1, 1, -1, -1, 1, -1, 1, -1, 1, 1, -1, -1, -1, 1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1, 1, -1, 1, 1, 1, -1, 1, -1, -1, 1, -1, 1, 1, 1, -1, -1, -1, 1, 1, 1, -1, 1, -1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, -1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, 1, -1, 1, 1, -1, -1, -1, -1, 1, -1, 1, -1, 1, 1, 1, 1, -1, 1, -1, -1, -1, -1, 1, -1, -1, -1, -1, 1, 1, -1, 1, -1, 1, 1, -1, -1, 1, -1, -1, -1, -1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, -1, -1, 1, -1, 1, -1, 1, 1, 1, -1, -1, 1, 1, 1, 1, -1, -1, 1, 1, 1, 1, -1, -1, 1, 1, 1, 1, 1, 1, -1, -1, 1, -1, 1, 1, -1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1, -1, -1, 1, -1, -1, -1, -1, 1, -1, -1, -1, -1, -1, 1, 1, -1, 1, -1, -1, -1, -1, 1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1, -1, 1, -1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, 1, 1, -1, -1, 1, -1, 1, -1, -1, -1, -1, -1, -1, 1, -1, 1, 1, -1, 1, -1, -1, -1, 1, 1, -1, 1, -1, -1, 1, -1, 1, 1, -1, 1, -1, -1, 1, -1, 1, -1, 1, -1, -1, 1, -1, -1, -1, 1, 1, -1, -1, 1, -1, -1, 1, -1, -1, -1, 1, -1, 1, 1, -1, -1, -1, -1, -1, 1, -1, 1, 1, -1, 1, 1, -1, -1, 1, 1, 1, -1, 1, 1, 1, -1, 1, 1, -1, -1, 1, 1, 1, 1, 1, 1, -1, -1, -1, 1, 1, -1, -1, -1, -1, 1, 1, -1, -1, 1, 1, -1, 1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, -1, 1, 1, -1, 1, -1, 1, -1, 1, -1, 1, 1, -1, -1, -1, -1, 1, 1, -1, 1, -1, -1, 1, 1, -1, 1, 1, -1, -1, -1, 1, 1, 1, -1, 1, 1, 1, -1, 1, 1, -1, 1, 1, -1, 1, -1, -1, 1, 1, 1, -1, 1, -1, 1, 1, 1, 1, -1, -1, -1, 1, -1, 1, -1, -1, 1, -1, 1, 1, -1, -1, -1, 1, -1, 1, -1, 1, 1, 1, -1, 1, 1, -1, 1, 1, -1, -1, -1, -1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1, -1, -1, -1, 1, 1, 1, -1, -1, 1, -1, -1, -1, 1, 1, 1, 1, -1, -1, -1, 1, -1, 1, 1, 1, -1, 1, 1, 1, -1, -1, -1, 1, 1, -1, -1, 1, 1, -1, 1, -1, -1, 1, -1, -1, -1, 1, 1, -1, 1, -1, -1, 1, 1, -1, 1, -1, -1, 1, -1, -1, -1, 1, 1, -1, 1, 1, -1, 1, -1, -1, -1, -1, 1, -1, -1, 1, 1, -1, 1, 1, 1, 1, 1, -1, 1, -1, 1, 1, 1, 1, -1, -1, 1, 1, -1, 1, -1, 1, -1, -1, 1, -1, -1, -1, 1, -1, -1, -1, 1, 1, 1, -1, -1, 1, 1, -1, -1, -1, -1, 1, -1, 1, -1, 1, 1, 1, -1, 1, 1, -1, 1, -1, 1, -1, -1, 1, -1, -1, -1, -1, 1, 1, -1, -1, 1, -1, -1, 1, 1, 1, -1, -1, -1, -1, 1, -1, -1, 1, -1, 1, 1, 1, 1, 1, -1, -1, -1, -1, 1, -1, -1, -1, 1, 1, 1, 1, -1, -1, -1, -1, 1, -1, -1, 1, 1, 1, -1, 1, -1, 1, -1, 1, 1, -1, -1, -1, 1, 1, 1, 1, -1, -1, -1, 1, 1, -1, 1, 1, 1, 1, 1, -1, 1, 1, -1, 1, 1, 1, -1, 1, -1, -1, 1, 1, -1, 1, -1, 1, -1, 1, 1, -1, -1, -1, 1, 1, -1, 1, -1, 1, -1, -1, -1, -1, 1, 1, 1, 1, -1, 1, -1, 1, -1, -1, -1, 1, -1, -1, 1, -1, 1, 1, -1, -1, -1, -1, 1, 1, -1, -1, 1, -1, 1, -1, -1, 1, -1, 1, -1, -1, 1, -1, -1, 1, 1, -1, 1, -1, -1, 1, -1, 1, -1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1, -1, -1, 1, 1, 1, 1, -1, -1, -1, -1, 1, -1, 1, -1, 1, -1, -1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, 1, 1, -1, 1, -1, 1, -1, 1, -1, -1, 1, -1, 1, 1, 1, 1, -1, -1, -1, -1, 1, -1, -1, 1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, -1, 1, -1, 1, -1, -1, -1, 1, 1, 1, 1, -1, -1, 1, 1, 1, -1, 1, -1, -1, 1, -1, 1, 1, 1, -1, 1, 1, -1, 1, -1, 1, -1, 1, 1, -1, 1, 1, -1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, -1, 1, -1, 1, -1, -1, -1, 1, -1, -1, 1, -1, -1, 1, 1, 1, 1, 1, 1, -1, 1, 1, -1, 1, -1, 1, -1, -1, -1, 1, 1, -1, 1, -1, 1, -1, 1, -1, 1, 1, 1, 1, -1, 1, 1, -1, -1, -1, 1, -1, 1, -1, 1, 1, 1, 1, -1, 1, 1, 1, 1, -1, 1, -1, -1, -1, -1, -1, -1, -1, 1, -1, -1, -1, -1, -1, 1, 1, -1, 1, -1]
--- /dev/null
+#!/usr/bin/env python
+#
+# Copyright 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.
+#
+
+import math
+from gnuradio import gr
+from gnuradio.blksimpl.ofdm_sync_ml import ofdm_sync_ml
+from gnuradio.blksimpl.ofdm_sync_pn import ofdm_sync_pn
+from gnuradio.blksimpl.ofdm_sync_pnac import ofdm_sync_pnac
+
+class ofdm_receiver(gr.hier_block):
+ def __init__(self, fg, fft_length, cp_length, occupied_tones, snr, ks, logging=False):
+ self.fg = fg
+
+ bw = (float(occupied_tones) / float(fft_length)) / 2.0
+ tb = bw*0.08
+ chan_coeffs = gr.firdes.low_pass (1.0, # gain
+ 1.0, # sampling rate
+ bw+tb, # midpoint of trans. band
+ tb, # width of trans. band
+ gr.firdes.WIN_HAMMING) # filter type
+ self.chan_filt = gr.fft_filter_ccc(1, chan_coeffs)
+
+ win = [1 for i in range(fft_length)]
+
+ SYNC = "pn"
+ if SYNC == "ml":
+ self.ofdm_sync = ofdm_sync_ml(fg, fft_length, cp_length, snr, logging)
+ elif SYNC == "pn":
+ self.ofdm_sync = ofdm_sync_pn(fg, fft_length, cp_length, logging)
+ elif SYNC == "pnac":
+ self.ofdm_sync = ofdm_sync_pnac(fg, fft_length, cp_length, ks[0])
+
+ self.fft_demod = gr.fft_vcc(fft_length, True, win, True)
+ self.ofdm_corr = gr.ofdm_correlator(occupied_tones, fft_length,
+ cp_length, ks[1], ks[2])
+
+ self.fg.connect(self.chan_filt, self.ofdm_sync, self.fft_demod, self.ofdm_corr)
+
+ if logging:
+ self.fg.connect(self.chan_filt, gr.file_sink(gr.sizeof_gr_complex, "chan_filt_c.dat"))
+ self.fg.connect(self.fft_demod, gr.file_sink(gr.sizeof_gr_complex*fft_length, "fft_out_c.dat"))
+ self.fg.connect(self.ofdm_corr, gr.file_sink(gr.sizeof_gr_complex*occupied_tones, "ofdm_corr_out_c.dat"))
+ self.fg.connect((self.ofdm_corr,1), gr.file_sink(1, "found_corr_b.dat"))
+
+ gr.hier_block.__init__(self, fg, self.chan_filt, self.ofdm_corr)
--- /dev/null
+#!/usr/bin/env python
+#
+# Copyright 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.
+#
+
+import math
+from gnuradio import gr
+
+class ofdm_sync_fixed(gr.hier_block):
+ def __init__(self, fg, fft_length, cp_length, snr):
+ self.fg = fg
+
+ # Use a fixed trigger point instead of sync block
+ data = (fft_length+cp_len)*[0,]
+ data[(fft_length+cp_len)-1] = 1
+ peak_trigger = gr.vector_source_b(data, True)
+
+ self.fg.connect(peak_trigger, (self.sampler,1))
+
+ if 1:
+ self.fg.connect(self.sampler, gr.file_sink(gr.sizeof_gr_complex*fft_length,
+ "ofdm_sync_fixed-sampler_c.dat"))
+
+ gr.hier_block.__init__(self, fg, (self.sampler,0), self.sampler)
--- /dev/null
+#!/usr/bin/env python
+#
+# Copyright 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.
+#
+
+import math
+from gnuradio import gr
+
+class ofdm_sync_ml(gr.hier_block):
+ def __init__(self, fg, fft_length, cp_length, snr, logging):
+ ''' Maximum Likelihood OFDM synchronizer:
+ J. van de Beek, M. Sandell, and P. O. Borjesson, "ML Estimation
+ of Time and Frequency Offset in OFDM Systems," IEEE Trans.
+ Signal Processing, vol. 45, no. 7, pp. 1800-1805, 1997.
+ '''
+
+ self.fg = fg
+
+ # FIXME: when converting to hier_block2's, the output signature
+ # should be the output of the divider (the normalized peaks) and
+ # the angle value out of the sample and hold block
+
+ self.input = gr.add_const_cc(0)
+
+ SNR = 10.0**(snr/10.0)
+ rho = SNR / (SNR + 1.0)
+ symbol_length = fft_length + cp_length
+
+ # ML Sync
+
+ # Energy Detection from ML Sync
+
+ # Create a delay line
+ self.delay = gr.delay(gr.sizeof_gr_complex, fft_length)
+ self.fg.connect(self.input, self.delay)
+
+ # magnitude squared blocks
+ self.magsqrd1 = gr.complex_to_mag_squared()
+ self.magsqrd2 = gr.complex_to_mag_squared()
+ self.adder = gr.add_ff()
+
+ moving_sum_taps = [rho/2 for i in range(cp_length)]
+ self.moving_sum_filter = gr.fir_filter_fff(1,moving_sum_taps)
+
+ self.fg.connect(self.input,self.magsqrd1)
+ self.fg.connect(self.delay,self.magsqrd2)
+ self.fg.connect(self.magsqrd1,(self.adder,0))
+ self.fg.connect(self.magsqrd2,(self.adder,1))
+ self.fg.connect(self.adder,self.moving_sum_filter)
+
+
+ # Correlation from ML Sync
+ self.conjg = gr.conjugate_cc();
+ self.mixer = gr.multiply_cc();
+
+ movingsum2_taps = [1.0 for i in range(cp_length)]
+ self.movingsum2 = gr.fir_filter_ccf(1,movingsum2_taps)
+
+ # Correlator data handler
+ self.c2mag = gr.complex_to_mag()
+ self.angle = gr.complex_to_arg()
+ self.fg.connect(self.input,(self.mixer,1))
+ self.fg.connect(self.delay,self.conjg,(self.mixer,0))
+ self.fg.connect(self.mixer,self.movingsum2,self.c2mag)
+ self.fg.connect(self.movingsum2,self.angle)
+
+ # ML Sync output arg, need to find maximum point of this
+ self.diff = gr.sub_ff()
+ self.fg.connect(self.c2mag,(self.diff,0))
+ self.fg.connect(self.moving_sum_filter,(self.diff,1))
+
+ #ML measurements input to sampler block and detect
+ nco_sensitivity = -1.0/fft_length
+ self.f2c = gr.float_to_complex()
+ self.sampler = gr.ofdm_sampler(fft_length,symbol_length)
+ self.pk_detect = gr.peak_detector_fb(0.2, 0.25, 30, 0.0005)
+ self.sample_and_hold = gr.sample_and_hold_ff()
+ self.nco = gr.frequency_modulator_fc(nco_sensitivity)
+ self.sigmix = gr.multiply_cc()
+
+ # Mix the signal with an NCO controlled by the sync loop
+ self.fg.connect(self.input, (self.sigmix,0))
+ self.fg.connect(self.nco, (self.sigmix,1))
+ self.fg.connect(self.sigmix, (self.sampler,0))
+
+ # use the sync loop values to set the sampler and the NCO
+ # self.diff = theta
+ # self.angle = epsilon
+
+ self.fg.connect(self.diff, self.pk_detect)
+
+ use_dpll = 1
+ if use_dpll:
+ self.dpll = gr.dpll_bb(float(symbol_length),0.01)
+ self.fg.connect(self.pk_detect, self.dpll)
+ self.fg.connect(self.dpll, (self.sampler,1))
+ self.fg.connect(self.dpll, (self.sample_and_hold,1))
+ else:
+ self.fg.connect(self.pk_detect, (self.sampler,1))
+ self.fg.connect(self.pk_detect, (self.sample_and_hold,1))
+
+ self.fg.connect(self.angle, (self.sample_and_hold,0))
+ self.fg.connect(self.sample_and_hold, self.nco)
+
+ if logging:
+ self.fg.connect(self.diff, gr.file_sink(gr.sizeof_float, "ofdm_sync_ml-theta_f.dat"))
+ self.fg.connect(self.angle, gr.file_sink(gr.sizeof_float, "ofdm_sync_ml-epsilon_f.dat"))
+ self.fg.connect(self.pk_detect, gr.file_sink(gr.sizeof_char, "ofdm_sync_ml-peaks_b.dat"))
+ if use_dpll:
+ self.fg.connect(self.dpll, gr.file_sink(gr.sizeof_char, "ofdm_sync_ml-dpll_b.dat"))
+
+ self.fg.connect(self.sigmix, gr.file_sink(gr.sizeof_gr_complex, "ofdm_sync_ml-sigmix_c.dat"))
+ self.fg.connect(self.sampler, gr.file_sink(gr.sizeof_gr_complex*fft_length, "ofdm_sync_ml-sampler_c.dat"))
+ self.fg.connect(self.sample_and_hold, gr.file_sink(gr.sizeof_float, "ofdm_sync_ml-sample_and_hold_f.dat"))
+ self.fg.connect(self.nco, gr.file_sink(gr.sizeof_gr_complex, "ofdm_sync_ml-nco_c.dat"))
+ self.fg.connect(self.input, gr.file_sink(gr.sizeof_gr_complex, "ofdm_sync_ml-input_c.dat"))
+
+ gr.hier_block.__init__(self, fg, self.input, self.sampler)
--- /dev/null
+#!/usr/bin/env python
+#
+# Copyright 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.
+#
+
+import math
+from numpy import fft
+from gnuradio import gr
+
+class ofdm_sync_pn(gr.hier_block):
+ def __init__(self, fg, fft_length, cp_length, logging=False):
+ ''' OFDM synchronization using PN Correlation:
+ T. M. Schmidl and D. C. Cox, "Robust Frequency and Timing
+ Synchonization for OFDM," IEEE Trans. Communications, vol. 45,
+ no. 12, 1997.
+ '''
+
+ self.fg = fg
+
+ # FIXME: when converting to hier_block2's, the output signature
+ # should be the output of the divider (the normalized peaks) and
+ # the angle value out of the sample and hold block
+
+ self.input = gr.add_const_cc(0)
+
+ symbol_length = fft_length + cp_length
+
+ # PN Sync
+
+ # Create a delay line
+ self.delay = gr.delay(gr.sizeof_gr_complex, fft_length/2)
+
+ # Correlation from ML Sync
+ self.conjg = gr.conjugate_cc();
+ self.corr = gr.multiply_cc();
+
+ # Create a moving sum filter for the corr output
+ if 1:
+ moving_sum_taps = [1.0 for i in range(fft_length//2)]
+ self.moving_sum_filter = gr.fir_filter_ccf(1,moving_sum_taps)
+ else:
+ moving_sum_taps = [complex(1.0,0.0) for i in range(fft_length//2)]
+ self.moving_sum_filter = gr.fft_filter_ccc(1,moving_sum_taps)
+
+ # Create a moving sum filter for the input
+ self.inputmag2 = gr.complex_to_mag_squared()
+ movingsum2_taps = [1.0 for i in range(fft_length//2)]
+
+ if 1:
+ self.inputmovingsum = gr.fir_filter_fff(1,movingsum2_taps)
+ else:
+ self.inputmovingsum = gr.fft_filter_fff(1,movingsum2_taps)
+
+ self.square = gr.multiply_ff()
+ self.normalize = gr.divide_ff()
+
+ # Get magnitude (peaks) and angle (phase/freq error)
+ self.c2mag = gr.complex_to_mag_squared()
+ self.angle = gr.complex_to_arg()
+
+ self.sample_and_hold = gr.sample_and_hold_ff()
+
+ # Mix the signal with an NCO controlled by the sync loop
+ nco_sensitivity = -2.0/fft_length
+ self.nco = gr.frequency_modulator_fc(nco_sensitivity)
+ self.sigmix = gr.multiply_cc()
+
+ #ML measurements input to sampler block and detect
+ self.sub1 = gr.add_const_ff(-1)
+ self.pk_detect = gr.peak_detector_fb(0.2, 0.25, 30, 0.0005)
+ self.regen = gr.regenerate_bb(symbol_length)
+
+ self.sampler = gr.ofdm_sampler(fft_length,symbol_length)
+
+ self.fg.connect(self.input, self.delay)
+ self.fg.connect(self.input, (self.corr,0))
+ self.fg.connect(self.delay, self.conjg)
+ self.fg.connect(self.conjg, (self.corr,1))
+ self.fg.connect(self.corr, self.moving_sum_filter)
+ self.fg.connect(self.moving_sum_filter, self.c2mag)
+ self.fg.connect(self.moving_sum_filter, self.angle)
+ self.fg.connect(self.angle, (self.sample_and_hold,0))
+ self.fg.connect(self.sample_and_hold, self.nco)
+
+ self.fg.connect(self.input, (self.sigmix,0))
+ self.fg.connect(self.nco, (self.sigmix,1))
+ self.fg.connect(self.sigmix, (self.sampler,0))
+
+ self.fg.connect(self.input, self.inputmag2, self.inputmovingsum)
+ self.fg.connect(self.inputmovingsum, (self.square,0))
+ self.fg.connect(self.inputmovingsum, (self.square,1))
+ self.fg.connect(self.square, (self.normalize,1))
+ self.fg.connect(self.c2mag, (self.normalize,0))
+
+ # Create a moving sum filter for the corr output
+ matched_filter_taps = [1.0/cp_length for i in range(cp_length)]
+ self.matched_filter = gr.fir_filter_fff(1,matched_filter_taps)
+ self.fg.connect(self.normalize, self.matched_filter)
+
+ self.fg.connect(self.matched_filter, self.sub1, self.pk_detect)
+ self.fg.connect(self.pk_detect, self.regen)
+ self.fg.connect(self.regen, (self.sampler,1))
+ self.fg.connect(self.pk_detect, (self.sample_and_hold,1))
+
+
+ if logging:
+ self.fg.connect(self.matched_filter, gr.file_sink(gr.sizeof_float, "ofdm_sync_pn-mf_f.dat"))
+ self.fg.connect(self.normalize, gr.file_sink(gr.sizeof_float, "ofdm_sync_pn-theta_f.dat"))
+ self.fg.connect(self.angle, gr.file_sink(gr.sizeof_float, "ofdm_sync_pn-epsilon_f.dat"))
+ self.fg.connect(self.pk_detect, gr.file_sink(gr.sizeof_char, "ofdm_sync_pn-peaks_b.dat"))
+ self.fg.connect(self.regen, gr.file_sink(gr.sizeof_char, "ofdm_sync_pn-regen_b.dat"))
+ self.fg.connect(self.sigmix, gr.file_sink(gr.sizeof_gr_complex, "ofdm_sync_pn-sigmix_c.dat"))
+ self.fg.connect(self.sampler, gr.file_sink(gr.sizeof_gr_complex*fft_length, "ofdm_sync_pn-sampler_c.dat"))
+ self.fg.connect(self.sample_and_hold, gr.file_sink(gr.sizeof_float, "ofdm_sync_pn-sample_and_hold_f.dat"))
+ self.fg.connect(self.nco, gr.file_sink(gr.sizeof_gr_complex, "ofdm_sync_pn-nco_c.dat"))
+ self.fg.connect(self.input, gr.file_sink(gr.sizeof_gr_complex, "ofdm_sync_pn-input_c.dat"))
+
+ gr.hier_block.__init__(self, fg, self.input, self.sampler)
--- /dev/null
+#!/usr/bin/env python
+#
+# Copyright 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.
+#
+
+import math
+from numpy import fft
+from gnuradio import gr
+
+class ofdm_sync_pnac(gr.hier_block):
+ def __init__(self, fg, fft_length, cp_length, ks):
+ self.fg = fg
+
+ # FIXME: when converting to hier_block2's, the output signature
+ # should be the output of the divider (the normalized peaks) and
+ # the angle value out of the sample and hold block
+
+ self.input = gr.add_const_cc(0)
+
+ symbol_length = fft_length + cp_length
+
+ # PN Sync
+
+ # autocorrelate with the known symbol
+ ks = ks[0:fft_length//2]
+ ks.reverse()
+ self.crosscorr_filter = gr.fir_filter_ccc(1, ks)
+ self.fg.connect(self.crosscorr_filter, gr.file_sink(gr.sizeof_gr_complex, "crosscorr.dat"))
+
+ # Create a delay line
+ self.delay = gr.delay(gr.sizeof_gr_complex, fft_length/2)
+
+ # Correlation from ML Sync
+ self.conjg = gr.conjugate_cc();
+ self.corr = gr.multiply_cc();
+
+ # Create a moving sum filter for the corr output
+ moving_sum_taps = [1.0 for i in range(fft_length//2)]
+ self.moving_sum_filter = gr.fir_filter_ccf(1,moving_sum_taps)
+
+ # Create a moving sum filter for the input
+ self.inputmag2 = gr.complex_to_mag_squared()
+ movingsum2_taps = [1.0 for i in range(fft_length/2)]
+ self.inputmovingsum = gr.fir_filter_fff(1,movingsum2_taps)
+ self.square = gr.multiply_ff()
+ self.normalize = gr.divide_ff()
+
+ # Get magnitude (peaks) and angle (phase/freq error)
+ self.c2mag = gr.complex_to_mag_squared()
+ self.angle = gr.complex_to_arg()
+
+ self.sample_and_hold = gr.sample_and_hold_ff()
+
+ # Mix the signal with an NCO controlled by the sync loop
+ nco_sensitivity = -1.0/fft_length
+ self.nco = gr.frequency_modulator_fc(nco_sensitivity)
+ self.sigmix = gr.multiply_cc()
+
+ #ML measurements input to sampler block and detect
+ self.sub1 = gr.add_const_ff(-1)
+ self.pk_detect = gr.peak_detector_fb(0.2, 0.25, 30, 0.0005)
+
+ self.sampler = gr.ofdm_sampler(fft_length,symbol_length)
+
+ self.fg.connect(self.input, self.crosscorr_filter)
+ self.fg.connect(self.crosscorr_filter, self.delay)
+ self.fg.connect(self.crosscorr_filter, (self.corr,0))
+ self.fg.connect(self.delay, self.conjg)
+ self.fg.connect(self.conjg, (self.corr,1))
+ self.fg.connect(self.corr, self.moving_sum_filter)
+ self.fg.connect(self.moving_sum_filter, self.c2mag)
+ self.fg.connect(self.moving_sum_filter, self.angle)
+ self.fg.connect(self.angle, (self.sample_and_hold,0))
+ self.fg.connect(self.sample_and_hold, self.nco)
+
+ self.fg.connect(self.input, (self.sigmix,0))
+ self.fg.connect(self.nco, (self.sigmix,1))
+ self.fg.connect(self.sigmix, (self.sampler,0))
+
+ self.fg.connect(self.input, self.inputmag2, self.inputmovingsum)
+ self.fg.connect(self.inputmovingsum, (self.square,0))
+ self.fg.connect(self.inputmovingsum, (self.square,1))
+ self.fg.connect(self.square, (self.normalize,1))
+ self.fg.connect(self.c2mag, (self.normalize,0))
+ self.fg.connect(self.normalize, self.sub1, self.pk_detect)
+
+ self.fg.connect(self.pk_detect, (self.sampler,1))
+ self.fg.connect(self.pk_detect, (self.sample_and_hold,1))
+
+
+ if 1:
+ self.fg.connect(self.normalize, gr.file_sink(gr.sizeof_float,
+ "ofdm_sync_pnac-theta_f.dat"))
+ self.fg.connect(self.angle, gr.file_sink(gr.sizeof_float,
+ "ofdm_sync_pnac-epsilon_f.dat"))
+ self.fg.connect(self.pk_detect, gr.file_sink(gr.sizeof_char,
+ "ofdm_sync_pnac-peaks_b.dat"))
+ self.fg.connect(self.sigmix, gr.file_sink(gr.sizeof_gr_complex,
+ "ofdm_sync_pnac-sigmix_c.dat"))
+ self.fg.connect(self.sampler, gr.file_sink(gr.sizeof_gr_complex*fft_length,
+ "ofdm_sync_pnac-sampler_c.dat"))
+ self.fg.connect(self.sample_and_hold, gr.file_sink(gr.sizeof_float,
+ "ofdm_sync_pnac-sample_and_hold_f.dat"))
+ self.fg.connect(self.nco, gr.file_sink(gr.sizeof_gr_complex,
+ "ofdm_sync_pnac-nco_c.dat"))
+ self.fg.connect(self.input, gr.file_sink(gr.sizeof_gr_complex,
+ "ofdm_sync_pnac-input_c.dat"))
+
+ gr.hier_block.__init__(self, fg, self.input, self.sampler)
--- /dev/null
+#
+# 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.
+#
+
+from math import pi
+from gnuradio import gr, packet_utils
+import gnuradio.gr.gr_threading as _threading
+
+
+# /////////////////////////////////////////////////////////////////////////////
+# mod/demod with packets as i/o
+# /////////////////////////////////////////////////////////////////////////////
+
+class mod_pkts(gr.hier_block2):
+ """
+ Wrap an arbitrary digital modulator in our packet handling framework.
+
+ Send packets by calling send_pkt
+ """
+ def __init__(self, modulator, access_code=None, msgq_limit=2, pad_for_usrp=True, use_whitener_offset=False):
+ """
+ Hierarchical block for sending packets
+
+ Packets to be sent are enqueued by calling send_pkt.
+ The output is the complex modulated signal at baseband.
+
+ @param modulator: instance of modulator class (gr_block or hier_block2)
+ @type modulator: complex baseband out
+ @param access_code: AKA sync vector
+ @type access_code: string of 1's and 0's between 1 and 64 long
+ @param msgq_limit: maximum number of messages in message queue
+ @type msgq_limit: int
+ @param pad_for_usrp: If true, packets are padded such that they end up a multiple of 128 samples
+ @param use_whitener_offset: If true, start of whitener XOR string is incremented each packet
+
+ See gmsk_mod for remaining parameters
+ """
+
+ gr.hier_block2.__init__(self, "mod_pkts",
+ gr.io_signature(0, 0, 0), # Input signature
+ gr.io_signature(1, 1, gr.sizeof_gr_complex)) # Output signature
+
+ self._modulator = modulator
+ self._pad_for_usrp = pad_for_usrp
+ self._use_whitener_offset = use_whitener_offset
+ self._whitener_offset = 0
+
+ if access_code is None:
+ access_code = packet_utils.default_access_code
+ if not packet_utils.is_1_0_string(access_code):
+ raise ValueError, "Invalid access_code %r. Must be string of 1's and 0's" % (access_code,)
+ self._access_code = access_code
+
+ # accepts messages from the outside world
+ self._pkt_input = gr.message_source(gr.sizeof_char, msgq_limit)
+ self.connect(self._pkt_input, self._modulator, self)
+
+ def send_pkt(self, payload='', eof=False):
+ """
+ Send the payload.
+
+ @param payload: data to send
+ @type payload: string
+ """
+ if eof:
+ msg = gr.message(1) # tell self._pkt_input we're not sending any more packets
+ else:
+ # print "original_payload =", string_to_hex_list(payload)
+ pkt = packet_utils.make_packet(payload,
+ self._modulator.samples_per_symbol(),
+ self._modulator.bits_per_symbol(),
+ self._access_code,
+ self._pad_for_usrp,
+ self._whitener_offset)
+ #print "pkt =", string_to_hex_list(pkt)
+ msg = gr.message_from_string(pkt)
+ if self._use_whitener_offset is True:
+ self._whitener_offset = (self._whitener_offset + 1) % 16
+
+ self._pkt_input.msgq().insert_tail(msg)
+
+
+
+class demod_pkts(gr.hier_block2):
+ """
+ Wrap an arbitrary digital demodulator in our packet handling framework.
+
+ The input is complex baseband. When packets are demodulated, they are passed to the
+ app via the callback.
+ """
+
+ def __init__(self, demodulator, access_code=None, callback=None, threshold=-1):
+ """
+ Hierarchical block for demodulating and deframing packets.
+
+ The input is the complex modulated signal at baseband.
+ Demodulated packets are sent to the handler.
+
+ @param demodulator: instance of demodulator class (gr_block or hier_block2)
+ @type demodulator: complex baseband in
+ @param access_code: AKA sync vector
+ @type access_code: string of 1's and 0's
+ @param callback: function of two args: ok, payload
+ @type callback: ok: bool; payload: string
+ @param threshold: detect access_code with up to threshold bits wrong (-1 -> use default)
+ @type threshold: int
+ """
+
+ gr.hier_block2.__init__(self, "demod_pkts",
+ gr.io_signature(1, 1, gr.sizeof_gr_complex), # Input signature
+ gr.io_signature(0, 0, 0)) # Output signature
+
+ self._demodulator = demodulator
+ if access_code is None:
+ access_code = packet_utils.default_access_code
+ if not packet_utils.is_1_0_string(access_code):
+ raise ValueError, "Invalid access_code %r. Must be string of 1's and 0's" % (access_code,)
+ self._access_code = access_code
+
+ if threshold == -1:
+ threshold = 12 # FIXME raise exception
+
+ self._rcvd_pktq = gr.msg_queue() # holds packets from the PHY
+ self.correlator = gr.correlate_access_code_bb(access_code, threshold)
+
+ self.framer_sink = gr.framer_sink_1(self._rcvd_pktq)
+ self.connect(self, self._demodulator, self.correlator, self.framer_sink)
+
+ self._watcher = _queue_watcher_thread(self._rcvd_pktq, callback)
+
+
+class _queue_watcher_thread(_threading.Thread):
+ def __init__(self, rcvd_pktq, callback):
+ _threading.Thread.__init__(self)
+ self.setDaemon(1)
+ self.rcvd_pktq = rcvd_pktq
+ self.callback = callback
+ self.keep_running = True
+ self.start()
+
+
+ def run(self):
+ while self.keep_running:
+ msg = self.rcvd_pktq.delete_head()
+ ok, payload = packet_utils.unmake_packet(msg.to_string(), int(msg.arg1()))
+ if self.callback:
+ self.callback(ok, payload)
--- /dev/null
+#
+# Copyright 2005,2006 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 math import pi, sqrt, log10
+import math, cmath
+
+# The following algorithm generates Gray coded constellations for M-PSK for M=[2,4,8]
+def make_gray_constellation(m):
+ # number of bits/symbol (log2(M))
+ k = int(log10(m) / log10(2.0))
+
+ coeff = 1
+ const_map = []
+ bits = [0]*3
+ for i in range(m):
+ # get a vector of the k bits to use in this mapping
+ bits[3-k:3] = [((i&(0x01 << k-j-1)) >> k-j-1) for j in range(k)]
+
+ theta = -(2*bits[0]-1)*(2*pi/m)*(bits[0]+abs(bits[1]-bits[2])+2*bits[1])
+ re = math.cos(theta)
+ im = math.sin(theta)
+ const_map.append(complex(re, im)) # plug it into the constellation
+
+ # return the constellation; by default, it is normalized
+ return const_map
+
+# This makes a constellation that increments around the unit circle
+def make_constellation(m):
+ return [cmath.exp(i * 2 * pi / m * 1j) for i in range(m)]
+
+# Common definition of constellations for Tx and Rx
+constellation = {
+ 2 : make_constellation(2), # BPSK
+ 4 : make_constellation(4), # QPSK
+ 8 : make_constellation(8) # 8PSK
+ }
+
+gray_constellation = {
+ 2 : make_gray_constellation(2), # BPSK
+ 4 : make_gray_constellation(4), # QPSK
+ 8 : make_gray_constellation(8) # 8PSK
+ }
+
+# -----------------------
+# Do Gray code
+# -----------------------
+# binary to gray coding -- constellation does Gray coding
+binary_to_gray = {
+ 2 : range(2),
+ 4 : [0,1,3,2],
+ 8 : [0, 1, 3, 2, 7, 6, 4, 5]
+ }
+
+# gray to binary
+gray_to_binary = {
+ 2 : range(2),
+ 4 : [0,1,3,2],
+ 8 : [0, 1, 3, 2, 6, 7, 5, 4]
+ }
+
+# -----------------------
+# Don't Gray code
+# -----------------------
+# identity mapping
+binary_to_ungray = {
+ 2 : range(2),
+ 4 : range(4),
+ 8 : range(8)
+ }
+
+# identity mapping
+ungray_to_binary = {
+ 2 : range(2),
+ 4 : range(4),
+ 8 : range(8)
+ }
--- /dev/null
+#
+# Copyright 2005,2006 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 math import pi, sqrt
+import math
+
+# These constellations are generated for Gray coding when symbos [1, ..., m] are used
+# Mapping to Gray coding is therefore unnecessary
+
+def make_constellation(m):
+ # number of bits/symbol (log2(M))
+ k = int(math.log10(m) / math.log10(2.0))
+
+ coeff = 1
+ const_map = []
+ for i in range(m):
+ a = (i&(0x01 << k-1)) >> k-1
+ b = (i&(0x01 << k-2)) >> k-2
+ bits_i = [((i&(0x01 << k-j-1)) >> k-j-1) for j in range(2, k, 2)]
+ bits_q = [((i&(0x01 << k-j-1)) >> k-j-1) for j in range(3, k, 2)]
+
+ ss = 0
+ ll = len(bits_i)
+ for ii in range(ll):
+ rr = 0
+ for jj in range(ll-ii):
+ rr = abs(bits_i[jj] - rr)
+ ss += rr*pow(2.0, ii+1)
+ re = (2*a-1)*(ss+1)
+
+ ss = 0
+ ll = len(bits_q)
+ for ii in range(ll):
+ rr = 0
+ for jj in range(ll-ii):
+ rr = abs(bits_q[jj] - rr)
+ ss += rr*pow(2.0, ii+1)
+ im = (2*b-1)*(ss+1)
+
+ a = max(re, im)
+ if a > coeff:
+ coeff = a
+ const_map.append(complex(re, im))
+
+ norm_map = [complex(i.real/coeff, i.imag/coeff) for i in const_map]
+ return norm_map
+
+# Common definition of constellations for Tx and Rx
+constellation = {
+ 4 : make_constellation(4), # QAM4 (QPSK)
+ 8 : make_constellation(8), # QAM8
+ 16: make_constellation(16), # QAM16
+ 64: make_constellation(64), # QAM64
+ 256: make_constellation(256) # QAM256
+ }
+
+# -----------------------
+# Do Gray code
+# -----------------------
+# binary to gray coding
+binary_to_gray = {
+ 4 : range(4),
+ 8 : range(8),
+ 16: range(16),
+ 64: range(64),
+ 256: range(256)
+ }
+
+# gray to binary
+gray_to_binary = {
+ 4 : range(4),
+ 8 : range(8),
+ 16: range(16),
+ 64: range(64),
+ 256: range(256)
+ }
+
+# -----------------------
+# Don't Gray code
+# -----------------------
+# identity mapping
+binary_to_ungray = {
+ 4 : range(4),
+ 8 : range(8),
+ 16: range(16),
+ 64: range(64)
+ }
+
+# identity mapping
+ungray_to_binary = {
+ 4 : range(4),
+ 8 : range(8),
+ 16: range(16),
+ 64: range(64)
+ }
--- /dev/null
+#
+# 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
+
+"""
+QAM16 modulation and demodulation.
+"""
+
+from gnuradio import gr, gru, modulation_utils
+from math import pi, sqrt
+import qam
+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 = None
+_def_gain_mu = 0.03
+_def_mu = 0.05
+_def_omega_relative_limit = 0.005
+
+
+# /////////////////////////////////////////////////////////////////////////////
+# QAM16 modulator
+# /////////////////////////////////////////////////////////////////////////////
+
+class qam16_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, "qam16_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(qam.binary_to_gray[arity])
+ else:
+ self.symbol_mapper = gr.map_bb(qam.binary_to_ungray[arity])
+
+ self.diffenc = gr.diff_encoder_bb(arity)
+
+ rot = 1.0
+ print "constellation with %d arity" % arity
+ rotated_const = map(lambda pt: pt * rot, qam.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
+ 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 4
+ bits_per_symbol = staticmethod(bits_per_symbol) # make it a static method. RTFM
+
+ def _print_verbage(self):
+ 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, "bytes2chunks.dat"))
+ self.connect(self.symbol_mapper,
+ gr.file_sink(gr.sizeof_char, "graycoder.dat"))
+ self.connect(self.diffenc,
+ gr.file_sink(gr.sizeof_char, "diffenc.dat"))
+ self.connect(self.chunks2symbols,
+ gr.file_sink(gr.sizeof_gr_complex, "chunks2symbols.dat"))
+ self.connect(self.rrc_filter,
+ gr.file_sink(gr.sizeof_gr_complex, "rrc_filter.dat"))
+
+ def add_options(parser):
+ """
+ Adds QAM 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(qam16_mod.__init__,
+ ('self',), options)
+ extract_kwargs_from_options=staticmethod(extract_kwargs_from_options)
+
+
+# /////////////////////////////////////////////////////////////////////////////
+# QAM16 demodulator
+#
+# /////////////////////////////////////////////////////////////////////////////
+
+class qam16_demod(gr.hier_block2):
+
+ def __init__(self,
+ samples_per_symbol=_def_samples_per_symbol,
+ excess_bw=_def_excess_bw,
+ costas_alpha=_def_costas_alpha,
+ gain_mu=_def_gain_mu,
+ mu=_def_mu,
+ omega_relative_limit=_def_omega_relative_limit,
+ gray_code=_def_gray_code,
+ verbose=_def_verbose,
+ log=_def_log):
+
+ gr.hier_block2.__init__(self, "qam16_demod",
+ gr.io_signature(1, 1, gr.sizeof_gr_complex), # Input signature
+ gr.io_signature(1, 1, gr.sizeof_char)) # Output signature
+ # do this
+ pass
+
+ def bits_per_symbol(self=None): # staticmethod that's also callable on an instance
+ return 4
+ bits_per_symbol = staticmethod(bits_per_symbol) # make it a static method. RTFM
+
+#
+# Add these to the mod/demod registry
+#
+# NOT READY TO BE USED YET -- ENABLE AT YOUR OWN RISK
+#modulation_utils.add_type_1_mod('qam16', qam16_mod)
+#modulation_utils.add_type_1_demod('qam16', qam16_demod)
--- /dev/null
+#
+# 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
+
+"""
+QAM256 modulation and demodulation.
+"""
+
+from gnuradio import gr, gru, modulation_utils
+from math import pi, sqrt
+import qam
+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 = None
+_def_gain_mu = 0.03
+_def_mu = 0.05
+_def_omega_relative_limit = 0.005
+
+
+# /////////////////////////////////////////////////////////////////////////////
+# QAM256 modulator
+# /////////////////////////////////////////////////////////////////////////////
+
+class qam256_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, "qam256_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(qam.binary_to_gray[arity])
+ else:
+ self.symbol_mapper = gr.map_bb(qam.binary_to_ungray[arity])
+
+ self.diffenc = gr.diff_encoder_bb(arity)
+
+ rot = 1.0
+ print "constellation with %d arity" % arity
+ rotated_const = map(lambda pt: pt * rot, qam.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
+ 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 8
+ bits_per_symbol = staticmethod(bits_per_symbol) # make it a static method. RTFM
+
+ def _print_verbage(self):
+ 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, "bytes2chunks.dat"))
+ self.connect(self.symbol_mapper,
+ gr.file_sink(gr.sizeof_char, "graycoder.dat"))
+ self.connect(self.diffenc,
+ gr.file_sink(gr.sizeof_char, "diffenc.dat"))
+ self.connect(self.chunks2symbols,
+ gr.file_sink(gr.sizeof_gr_complex, "chunks2symbols.dat"))
+ self.connect(self.rrc_filter,
+ gr.file_sink(gr.sizeof_gr_complex, "rrc_filter.dat"))
+
+ def add_options(parser):
+ """
+ Adds QAM 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(qam256_mod.__init__,
+ ('self',), options)
+ extract_kwargs_from_options=staticmethod(extract_kwargs_from_options)
+
+
+# /////////////////////////////////////////////////////////////////////////////
+# QAM256 demodulator
+#
+# /////////////////////////////////////////////////////////////////////////////
+
+class qam256_demod(gr.hier_block2):
+
+ def __init__(self,
+ samples_per_symbol=_def_samples_per_symbol,
+ excess_bw=_def_excess_bw,
+ costas_alpha=_def_costas_alpha,
+ gain_mu=_def_gain_mu,
+ mu=_def_mu,
+ omega_relative_limit=_def_omega_relative_limit,
+ gray_code=_def_gray_code,
+ verbose=_def_verbose,
+ log=_def_log):
+
+ gr.hier_block2.__init__(self, "qam256_demod",
+ gr.io_signature(1, 1, gr.sizeof_gr_complex), # Input signature
+ gr.io_signature(1, 1, gr.sizeof_char)) # Output signature
+
+ # do this
+ pass
+
+ def bits_per_symbol(self=None): # staticmethod that's also callable on an instance
+ return 8
+ bits_per_symbol = staticmethod(bits_per_symbol) # make it a static method. RTFM
+
+#
+# Add these to the mod/demod registry
+#
+# NOT READY TO BE USED YET -- ENABLE AT YOUR OWN RISK
+#modulation_utils.add_type_1_mod('qam256', qam256_mod)
+#modulation_utils.add_type_1_demod('qam256', qam256_demod)
--- /dev/null
+#
+# 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 QPSK modulation and demodulation.
+"""
+
+from gnuradio import gr, gru, modulation_utils
+from math import pi, sqrt
+import qam
+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 = None
+_def_gain_mu = 0.03
+_def_mu = 0.05
+_def_omega_relative_limit = 0.005
+
+
+# /////////////////////////////////////////////////////////////////////////////
+# QAM64 modulator
+# /////////////////////////////////////////////////////////////////////////////
+
+class qam64_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, "qam64_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(qam.binary_to_gray[arity])
+ else:
+ self.symbol_mapper = gr.map_bb(qam.binary_to_ungray[arity])
+
+ self.diffenc = gr.diff_encoder_bb(arity)
+
+ rot = 1.0
+ print "constellation with %d arity" % arity
+ rotated_const = map(lambda pt: pt * rot, qam.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
+ 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 6
+ bits_per_symbol = staticmethod(bits_per_symbol) # make it a static method. RTFM
+
+ def _print_verbage(self):
+ 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, "bytes2chunks.dat"))
+ self.connect(self.symbol_mapper,
+ gr.file_sink(gr.sizeof_char, "graycoder.dat"))
+ self.connect(self.diffenc,
+ gr.file_sink(gr.sizeof_char, "diffenc.dat"))
+ self.connect(self.chunks2symbols,
+ gr.file_sink(gr.sizeof_gr_complex, "chunks2symbols.dat"))
+ self.connect(self.rrc_filter,
+ gr.file_sink(gr.sizeof_gr_complex, "rrc_filter.dat"))
+
+ def add_options(parser):
+ """
+ Adds QAM 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(qam64_mod.__init__,
+ ('self',), options)
+ extract_kwargs_from_options=staticmethod(extract_kwargs_from_options)
+
+
+# /////////////////////////////////////////////////////////////////////////////
+# QAM16 demodulator
+#
+# /////////////////////////////////////////////////////////////////////////////
+
+class qam64_demod(gr.hier_block2):
+
+ def __init__(self,
+ samples_per_symbol=_def_samples_per_symbol,
+ excess_bw=_def_excess_bw,
+ costas_alpha=_def_costas_alpha,
+ gain_mu=_def_gain_mu,
+ mu=_def_mu,
+ omega_relative_limit=_def_omega_relative_limit,
+ gray_code=_def_gray_code,
+ verbose=_def_verbose,
+ log=_def_log):
+
+ gr.hier_block2.__init__(self, "qam64_demod",
+ gr.io_signature(1, 1, gr.sizeof_gr_complex), # Input signature
+ gr.io_signature(1, 1, gr.sizeof_char)) # Output signature
+
+ # do this
+ pass
+
+ def bits_per_symbol(self=None): # staticmethod that's also callable on an instance
+ return 6
+ bits_per_symbol = staticmethod(bits_per_symbol) # make it a static method. RTFM
+
+#
+# Add these to the mod/demod registry
+#
+# NOT READY TO BE USED YET -- ENABLE AT YOUR OWN RISK
+#modulation_utils.add_type_1_mod('qam64', qam64_mod)
+#modulation_utils.add_type_1_demod('qam16', qam16_demod)
--- /dev/null
+#
+# 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
+
+"""
+QAM8 modulation and demodulation.
+"""
+
+from gnuradio import gr, gru, modulation_utils
+from math import pi, sqrt
+import qam
+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 = None
+_def_gain_mu = 0.03
+_def_mu = 0.05
+_def_omega_relative_limit = 0.005
+
+
+# /////////////////////////////////////////////////////////////////////////////
+# QAM8 modulator
+# /////////////////////////////////////////////////////////////////////////////
+
+class qam8_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, "qam8_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(qam.binary_to_gray[arity])
+ else:
+ self.symbol_mapper = gr.map_bb(qam.binary_to_ungray[arity])
+
+ self.diffenc = gr.diff_encoder_bb(arity)
+
+ rot = 1.0
+ print "constellation with %d arity" % arity
+ rotated_const = map(lambda pt: pt * rot, qam.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
+ 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 3
+ bits_per_symbol = staticmethod(bits_per_symbol) # make it a static method. RTFM
+
+ def _print_verbage(self):
+ 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, "bytes2chunks.dat"))
+ self.connect(self.symbol_mapper,
+ gr.file_sink(gr.sizeof_char, "graycoder.dat"))
+ self.connect(self.diffenc,
+ gr.file_sink(gr.sizeof_char, "diffenc.dat"))
+ self.connect(self.chunks2symbols,
+ gr.file_sink(gr.sizeof_gr_complex, "chunks2symbols.dat"))
+ self.connect(self.rrc_filter,
+ gr.file_sink(gr.sizeof_gr_complex, "rrc_filter.dat"))
+
+ def add_options(parser):
+ """
+ Adds QAM 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(qam8_mod.__init__,
+ ('self',), options)
+ extract_kwargs_from_options=staticmethod(extract_kwargs_from_options)
+
+
+# /////////////////////////////////////////////////////////////////////////////
+# QAM8 demodulator
+#
+# /////////////////////////////////////////////////////////////////////////////
+
+class qam8_demod(gr.hier_block2):
+
+ def __init__(self,
+ samples_per_symbol=_def_samples_per_symbol,
+ excess_bw=_def_excess_bw,
+ costas_alpha=_def_costas_alpha,
+ gain_mu=_def_gain_mu,
+ mu=_def_mu,
+ omega_relative_limit=_def_omega_relative_limit,
+ gray_code=_def_gray_code,
+ verbose=_def_verbose,
+ log=_def_log):
+
+ gr.hier_block2.__init__(self, "qam8_demod",
+ gr.io_signature(1, 1, gr.sizeof_gr_complex), # Input signature
+ gr.io_signature(1, 1, gr.sizeof_gr_char)) # Output signature
+
+ # do this
+ pass
+
+ def bits_per_symbol(self=None): # staticmethod that's also callable on an instance
+ return 3
+ bits_per_symbol = staticmethod(bits_per_symbol) # make it a static method. RTFM
+
+#
+# Add these to the mod/demod registry
+#
+# NOT READY TO BE USED YET -- ENABLE AT YOUR OWN RISK
+modulation_utils.add_type_1_mod('qam8', qam8_mod)
+#modulation_utils.add_type_1_demod('qam8', qam8_demod)
--- /dev/null
+#
+# Copyright 2005,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.
+#
+
+from gnuradio import gr, gru
+
+_plot = None
+
+def design_filter(interpolation, decimation, fractional_bw):
+ """
+ Given the interpolation rate, decimation rate and a fractional bandwidth,
+ design a set of taps.
+
+ @param interpolation: interpolation factor
+ @type interpolation: integer > 0
+ @param decimation: decimation factor
+ @type decimation: integer > 0
+ @param fractional_bw: fractional bandwidth in (0, 0.5) 0.4 works well.
+ @type fractional_bw: float
+ @returns: sequence of numbers
+ """
+
+ if fractional_bw >= 0.5 or fractional_bw <= 0:
+ raise ValueError, "Invalid fractional_bandwidth, must be in (0, 0.5)"
+
+ beta = 5.0
+ trans_width = 0.5 - fractional_bw
+ mid_transition_band = 0.5 - trans_width/2
+
+ taps = gr.firdes.low_pass(interpolation, # gain
+ 1, # Fs
+ mid_transition_band/interpolation, # trans mid point
+ trans_width/interpolation, # transition width
+ gr.firdes.WIN_KAISER,
+ beta # beta
+ )
+
+ return taps
+
+
+
+class _rational_resampler_base(gr.hier_block2):
+ """
+ base class for all rational resampler variants.
+ """
+ def __init__(self, resampler_base,
+ interpolation, decimation, taps=None, fractional_bw=None):
+ """
+ Rational resampling polyphase FIR filter.
+
+ Either taps or fractional_bw may be specified, but not both.
+ If neither is specified, a reasonable default, 0.4, is used as
+ the fractional_bw.
+
+ @param interpolation: interpolation factor
+ @type interpolation: integer > 0
+ @param decimation: decimation factor
+ @type decimation: integer > 0
+ @param taps: optional filter coefficients
+ @type taps: sequence
+ @param fractional_bw: fractional bandwidth in (0, 0.5), measured at final freq (use 0.4)
+ @type fractional_bw: float
+ """
+
+ if not isinstance(interpolation, int) or interpolation < 1:
+ raise ValueError, "interpolation must be an integer >= 1"
+
+ if not isinstance(decimation, int) or decimation < 1:
+ raise ValueError, "decimation must be an integer >= 1"
+
+ if taps is None and fractional_bw is None:
+ fractional_bw = 0.4
+
+ d = gru.gcd(interpolation, decimation)
+ interpolation = interpolation // d
+ decimation = decimation // d
+
+ if taps is None:
+ taps = design_filter(interpolation, decimation, fractional_bw)
+
+ resampler = resampler_base(interpolation, decimation, taps)
+ gr.hier_block2.__init__(self, "rational_resampler",
+ gr.io_signature(1, 1, resampler.input_signature().sizeof_stream_item(0)),
+ gr.io_signature(1, 1, resampler.output_signature().sizeof_stream_item(0)))
+
+ self.connect(self, resampler, self)
+
+
+class rational_resampler_fff(_rational_resampler_base):
+ def __init__(self, interpolation, decimation, taps=None, fractional_bw=None):
+ """
+ Rational resampling polyphase FIR filter with
+ float input, float output and float taps.
+ """
+ _rational_resampler_base.__init__(self, gr.rational_resampler_base_fff,
+ interpolation, decimation, taps, fractional_bw)
+
+class rational_resampler_ccf(_rational_resampler_base):
+ def __init__(self, interpolation, decimation, taps=None, fractional_bw=None):
+ """
+ Rational resampling polyphase FIR filter with
+ complex input, complex output and float taps.
+ """
+ _rational_resampler_base.__init__(self, gr.rational_resampler_base_ccf,
+ interpolation, decimation, taps, fractional_bw)
+
+class rational_resampler_ccc(_rational_resampler_base):
+ def __init__(self, interpolation, decimation, taps=None, fractional_bw=None):
+ """
+ Rational resampling polyphase FIR filter with
+ complex input, complex output and complex taps.
+ """
+ _rational_resampler_base.__init__(self, gr.rational_resampler_base_ccc,
+ interpolation, decimation, taps, fractional_bw)
--- /dev/null
+#
+# Copyright 2005,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.
+#
+
+import math
+from gnuradio import gr, optfir
+
+class standard_squelch(gr.hier_block2):
+ def __init__(self, audio_rate):
+ gr.hier_block2.__init__(self, "standard_squelch",
+ gr.io_signature(1, 1, gr.sizeof_float), # Input signature
+ gr.io_signature(1, 1, gr.sizeof_float)) # Output signature
+
+ self.input_node = gr.add_const_ff(0) # FIXME kludge
+
+ self.low_iir = gr.iir_filter_ffd((0.0193,0,-0.0193),(1,1.9524,-0.9615))
+ self.low_square = gr.multiply_ff()
+ self.low_smooth = gr.single_pole_iir_filter_ff(1/(0.01*audio_rate)) # 100ms time constant
+
+ self.hi_iir = gr.iir_filter_ffd((0.0193,0,-0.0193),(1,1.3597,-0.9615))
+ self.hi_square = gr.multiply_ff()
+ self.hi_smooth = gr.single_pole_iir_filter_ff(1/(0.01*audio_rate))
+
+ self.sub = gr.sub_ff();
+ self.add = gr.add_ff();
+ self.gate = gr.threshold_ff(0.3,0.43,0)
+ self.squelch_lpf = gr.single_pole_iir_filter_ff(1/(0.01*audio_rate))
+
+ self.div = gr.divide_ff()
+ self.squelch_mult = gr.multiply_ff()
+
+ self.connect (self, self.input_node)
+ self.connect (self.input_node, (self.squelch_mult, 0))
+
+ self.connect (self.input_node,self.low_iir)
+ self.connect (self.low_iir,(self.low_square,0))
+ self.connect (self.low_iir,(self.low_square,1))
+ self.connect (self.low_square,self.low_smooth,(self.sub,0))
+ self.connect (self.low_smooth, (self.add,0))
+
+ self.connect (self.input_node,self.hi_iir)
+ self.connect (self.hi_iir,(self.hi_square,0))
+ self.connect (self.hi_iir,(self.hi_square,1))
+ self.connect (self.hi_square,self.hi_smooth,(self.sub,1))
+ self.connect (self.hi_smooth, (self.add,1))
+
+ self.connect (self.sub, (self.div, 0))
+ self.connect (self.add, (self.div, 1))
+ self.connect (self.div, self.gate, self.squelch_lpf, (self.squelch_mult,1))
+ self.connect (self.squelch_mult, self)
+
+ def set_threshold(self, threshold):
+ self.gate.set_hi(threshold)
+
+ def threshold(self):
+ return self.gate.hi()
+
+ def squelch_range(self):
+ return (0.0, 1.0, 1.0/100)
--- /dev/null
+#
+# Copyright 2005,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.
+#
+
+from gnuradio import gr
+from gnuradio.blks2impl.fm_emph import fm_deemph
+import math
+
+class wfm_rcv(gr.hier_block2):
+ def __init__ (self, quad_rate, audio_decimation):
+ """
+ Hierarchical block for demodulating a broadcast FM signal.
+
+ The input is the downconverted complex baseband signal (gr_complex).
+ The output is the demodulated audio (float).
+
+ @param quad_rate: input sample rate of complex baseband input.
+ @type quad_rate: float
+ @param audio_decimation: how much to decimate quad_rate to get to audio.
+ @type audio_decimation: integer
+ """
+ gr.hier_block2.__init__(self, "wfm_rcv",
+ gr.io_signature(1, 1, gr.sizeof_gr_complex), # Input signature
+ gr.io_signature(1, 1, gr.sizeof_float)) # Output signature
+
+ volume = 20.
+
+ max_dev = 75e3
+ fm_demod_gain = quad_rate/(2*math.pi*max_dev)
+ audio_rate = quad_rate / audio_decimation
+
+
+ # We assign to self so that outsiders can grab the demodulator
+ # if they need to. E.g., to plot its output.
+ #
+ # input: complex; output: float
+ self.fm_demod = gr.quadrature_demod_cf (fm_demod_gain)
+
+ # input: float; output: float
+ self.deemph = fm_deemph (audio_rate)
+
+ # compute FIR filter taps for audio filter
+ width_of_transition_band = audio_rate / 32
+ audio_coeffs = gr.firdes.low_pass (1.0, # gain
+ quad_rate, # sampling rate
+ audio_rate/2 - width_of_transition_band,
+ width_of_transition_band,
+ gr.firdes.WIN_HAMMING)
+ # input: float; output: float
+ self.audio_filter = gr.fir_filter_fff (audio_decimation, audio_coeffs)
+
+ self.connect (self, self.fm_demod, self.audio_filter, self.deemph, self)
--- /dev/null
+#
+# Copyright 2005,2006 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.blks2impl.fm_emph import fm_deemph
+import math
+
+class wfm_rcv_pll(gr.hier_block2):
+ def __init__ (self, demod_rate, audio_decimation):
+ """
+ Hierarchical block for demodulating a broadcast FM signal.
+
+ The input is the downconverted complex baseband signal (gr_complex).
+ The output is two streams of the demodulated audio (float) 0=Left, 1=Right.
+
+ @param demod_rate: input sample rate of complex baseband input.
+ @type demod_rate: float
+ @param audio_decimation: how much to decimate demod_rate to get to audio.
+ @type audio_decimation: integer
+ """
+ gr.hier_block2.__init__(self, "wfm_rcv_pll",
+ gr.io_signature(1, 1, gr.sizeof_gr_complex), # Input signature
+ gr.io_signature(1, 2, gr.sizeof_float)) # Output signature
+ bandwidth = 200e3
+ audio_rate = demod_rate / audio_decimation
+
+
+ # We assign to self so that outsiders can grab the demodulator
+ # if they need to. E.g., to plot its output.
+ #
+ # input: complex; output: float
+ alpha = 0.25*bandwidth * math.pi / demod_rate
+ beta = alpha * alpha / 4.0
+ max_freq = 2.0*math.pi*100e3/demod_rate
+
+ self.fm_demod = gr.pll_freqdet_cf (alpha,beta,max_freq,-max_freq)
+
+ # input: float; output: float
+ self.deemph_Left = fm_deemph (audio_rate)
+ self.deemph_Right = fm_deemph (audio_rate)
+
+ # compute FIR filter taps for audio filter
+ width_of_transition_band = audio_rate / 32
+ audio_coeffs = gr.firdes.low_pass (1.0 , # gain
+ demod_rate, # sampling rate
+ 15000 ,
+ width_of_transition_band,
+ gr.firdes.WIN_HAMMING)
+ # input: float; output: float
+ self.audio_filter = gr.fir_filter_fff (audio_decimation, audio_coeffs)
+ if 1:
+ # Pick off the stereo carrier/2 with this filter. It attenuated 10 dB so apply 10 dB gain
+ # We pick off the negative frequency half because we want to base band by it!
+ ## NOTE THIS WAS HACKED TO OFFSET INSERTION LOSS DUE TO DEEMPHASIS
+
+ stereo_carrier_filter_coeffs = gr.firdes.complex_band_pass(10.0,
+ demod_rate,
+ -19020,
+ -18980,
+ width_of_transition_band,
+ gr.firdes.WIN_HAMMING)
+
+ #print "len stereo carrier filter = ",len(stereo_carrier_filter_coeffs)
+ #print "stereo carrier filter ", stereo_carrier_filter_coeffs
+ #print "width of transition band = ",width_of_transition_band, " audio rate = ", audio_rate
+
+ # Pick off the double side band suppressed carrier Left-Right audio. It is attenuated 10 dB so apply 10 dB gain
+
+ stereo_dsbsc_filter_coeffs = gr.firdes.complex_band_pass(20.0,
+ demod_rate,
+ 38000-15000/2,
+ 38000+15000/2,
+ width_of_transition_band,
+ gr.firdes.WIN_HAMMING)
+ #print "len stereo dsbsc filter = ",len(stereo_dsbsc_filter_coeffs)
+ #print "stereo dsbsc filter ", stereo_dsbsc_filter_coeffs
+ # construct overlap add filter system from coefficients for stereo carrier
+
+ self.stereo_carrier_filter = gr.fir_filter_fcc(audio_decimation, stereo_carrier_filter_coeffs)
+
+ # carrier is twice the picked off carrier so arrange to do a commplex multiply
+
+ self.stereo_carrier_generator = gr.multiply_cc();
+
+ # Pick off the rds signal
+
+ stereo_rds_filter_coeffs = gr.firdes.complex_band_pass(30.0,
+ demod_rate,
+ 57000 - 1500,
+ 57000 + 1500,
+ width_of_transition_band,
+ gr.firdes.WIN_HAMMING)
+ #print "len stereo dsbsc filter = ",len(stereo_dsbsc_filter_coeffs)
+ #print "stereo dsbsc filter ", stereo_dsbsc_filter_coeffs
+ # construct overlap add filter system from coefficients for stereo carrier
+
+ self.stereo_carrier_filter = gr.fir_filter_fcc(audio_decimation, stereo_carrier_filter_coeffs)
+ self.rds_signal_filter = gr.fir_filter_fcc(audio_decimation, stereo_rds_filter_coeffs)
+
+
+
+
+
+
+ self.rds_carrier_generator = gr.multiply_cc();
+ self.rds_signal_generator = gr.multiply_cc();
+ self_rds_signal_processor = gr.null_sink(gr.sizeof_gr_complex);
+
+
+
+ alpha = 5 * 0.25 * math.pi / (audio_rate)
+ beta = alpha * alpha / 4.0
+ max_freq = -2.0*math.pi*18990/audio_rate;
+ min_freq = -2.0*math.pi*19010/audio_rate;
+
+ self.stereo_carrier_pll_recovery = gr.pll_refout_cc(alpha,beta,max_freq,min_freq);
+ #self.stereo_carrier_pll_recovery.squelch_enable(False) #pll_refout does not have squelch yet, so disabled for now
+
+
+ # set up mixer (multiplier) to get the L-R signal at baseband
+
+ self.stereo_basebander = gr.multiply_cc();
+
+ # pick off the real component of the basebanded L-R signal. The imaginary SHOULD be zero
+
+ self.LmR_real = gr.complex_to_real();
+ self.Make_Left = gr.add_ff();
+ self.Make_Right = gr.sub_ff();
+
+ self.stereo_dsbsc_filter = gr.fir_filter_fcc(audio_decimation, stereo_dsbsc_filter_coeffs)
+
+
+ if 1:
+
+ # send the real signal to complex filter to pick off the carrier and then to one side of a multiplier
+ self.connect (self, self.fm_demod,self.stereo_carrier_filter,self.stereo_carrier_pll_recovery, (self.stereo_carrier_generator,0))
+ # send the already filtered carrier to the otherside of the carrier
+ self.connect (self.stereo_carrier_pll_recovery, (self.stereo_carrier_generator,1))
+ # the resulting signal from this multiplier is the carrier with correct phase but at -38000 Hz.
+
+ # send the new carrier to one side of the mixer (multiplier)
+ self.connect (self.stereo_carrier_generator, (self.stereo_basebander,0))
+ # send the demphasized audio to the DSBSC pick off filter, the complex
+ # DSBSC signal at +38000 Hz is sent to the other side of the mixer/multiplier
+ self.connect (self.fm_demod,self.stereo_dsbsc_filter, (self.stereo_basebander,1))
+ # the result is BASEBANDED DSBSC with phase zero!
+
+ # Pick off the real part since the imaginary is theoretically zero and then to one side of a summer
+ self.connect (self.stereo_basebander, self.LmR_real, (self.Make_Left,0))
+ #take the same real part of the DSBSC baseband signal and send it to negative side of a subtracter
+ self.connect (self.LmR_real,(self.Make_Right,1))
+
+ # Make rds carrier by taking the squared pilot tone and multiplying by pilot tone
+ self.connect (self.stereo_basebander,(self.rds_carrier_generator,0))
+ self.connect (self.stereo_carrier_pll_recovery,(self.rds_carrier_generator,1))
+ # take signal, filter off rds, send into mixer 0 channel
+ self.connect (self.fm_demod,self.rds_signal_filter,(self.rds_signal_generator,0))
+ # take rds_carrier_generator output and send into mixer 1 channel
+ self.connect (self.rds_carrier_generator,(self.rds_signal_generator,1))
+ # send basebanded rds signal and send into "processor" which for now is a null sink
+ self.connect (self.rds_signal_generator,self_rds_signal_processor)
+
+
+ if 1:
+ # pick off the audio, L+R that is what we used to have and send it to the summer
+ self.connect(self.fm_demod, self.audio_filter, (self.Make_Left, 1))
+ # take the picked off L+R audio and send it to the PLUS side of the subtractor
+ self.connect(self.audio_filter,(self.Make_Right, 0))
+ # The result of Make_Left gets (L+R) + (L-R) and results in 2*L
+ # The result of Make_Right gets (L+R) - (L-R) and results in 2*R
+ self.connect(self.Make_Left , self.deemph_Left, (self, 0))
+ self.connect(self.Make_Right, self.deemph_Right, (self, 1))
+ else:
+ self.connect (self.fm_demod, self.audio_filter, self)
--- /dev/null
+#
+# Copyright 2005,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.
+#
+
+import math
+from gnuradio import gr, optfir
+from gnuradio.blks2impl.fm_emph import fm_preemph
+
+class wfm_tx(gr.hier_block2):
+ def __init__(self, audio_rate, quad_rate, tau=75e-6, max_dev=75e3):
+ """
+ Wide Band FM Transmitter.
+
+ Takes a single float input stream of audio samples in the range [-1,+1]
+ and produces a single FM modulated complex baseband output.
+
+ @param audio_rate: sample rate of audio stream, >= 16k
+ @type audio_rate: integer
+ @param quad_rate: sample rate of output stream
+ @type quad_rate: integer
+ @param tau: preemphasis time constant (default 75e-6)
+ @type tau: float
+ @param max_dev: maximum deviation in Hz (default 75e3)
+ @type max_dev: float
+
+ quad_rate must be an integer multiple of audio_rate.
+ """
+ gr.hier_block2.__init__(self, "wfm_tx",
+ gr.io_signature(1, 1, gr.sizeof_float), # Input signature
+ gr.io_signature(1, 1, gr.sizeof_gr_complex)) # Output signature
+
+ # FIXME audio_rate and quad_rate ought to be exact rationals
+ audio_rate = int(audio_rate)
+ quad_rate = int(quad_rate)
+
+ if quad_rate % audio_rate != 0:
+ raise ValueError, "quad_rate is not an integer multiple of audio_rate"
+
+
+ do_interp = audio_rate != quad_rate
+
+ if do_interp:
+ interp_factor = quad_rate / audio_rate
+ interp_taps = optfir.low_pass (interp_factor, # gain
+ quad_rate, # Fs
+ 16000, # passband cutoff
+ 18000, # stopband cutoff
+ 0.1, # passband ripple dB
+ 40) # stopband atten dB
+
+ print "len(interp_taps) =", len(interp_taps)
+ self.interpolator = gr.interp_fir_filter_fff (interp_factor, interp_taps)
+
+ self.preemph = fm_preemph (quad_rate, tau=tau)
+
+ k = 2 * math.pi * max_dev / quad_rate
+ self.modulator = gr.frequency_modulator_fc (k)
+
+ if do_interp:
+ self.connect (self, self.interpolator, self.preemph, self.modulator, self)
+ else:
+ self.connect(self, self.preemph, self.modulator, self)
+++ /dev/null
-#
-# Copyright 2005 Free Software Foundation, Inc.
-#
-# This file is part of GNU Radio
-#
-# GNU Radio is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 3, or (at your option)
-# any later version.
-#
-# GNU Radio is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with GNU Radio; see the file COPYING. If not, write to
-# the Free Software Foundation, Inc., 51 Franklin Street,
-# Boston, MA 02110-1301, USA.
-#
-
-include $(top_srcdir)/Makefile.common
-
-# EXTRA_DIST = run_tests.in
-# TESTS = run_tests
-
-grblkspythondir = $(grpythondir)/blksimpl2
-
-grblkspython_PYTHON = \
- __init__.py \
- dbpsk.py \
- dqpsk.py \
- d8psk.py \
- filterbank.py \
- gmsk.py \
- pkt.py \
- psk.py \
- rational_resampler.py
-
-noinst_PYTHON =
-
-CLEANFILES = *.pyc *.pyo
+++ /dev/null
-# make this a package
+++ /dev/null
-#
-# 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 8PSK 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 = 3
-_def_excess_bw = 0.35
-_def_gray_code = True
-_def_verbose = False
-_def_log = False
-
-_def_costas_alpha = 0.01
-_def_gain_mu = 0.05
-_def_mu = 0.5
-_def_omega_relative_limit = 0.005
-
-
-# /////////////////////////////////////////////////////////////////////////////
-# DQPSK modulator
-# /////////////////////////////////////////////////////////////////////////////
-
-class d8psk_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, "d8psk_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 = 1
- 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)
-
- # Connect components
- self.connect(self, self.bytes2chunks, self.symbol_mapper, 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): # staticmethod that's also callable on an instance
- return 3
- 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 "RS 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_symbol_mapper.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 8PSK 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(d8psk_mod.__init__,
- ('self', 'fg'), options)
- extract_kwargs_from_options=staticmethod(extract_kwargs_from_options)
-
-
-# /////////////////////////////////////////////////////////////////////////////
-# D8PSK demodulator
-#
-# Differentially coherent detection of differentially encoded 8psk
-# /////////////////////////////////////////////////////////////////////////////
-
-WITH_SYNC = False
-class d8psk_demod(gr.hier_block2):
-
- def __init__(self,
- samples_per_symbol=_def_samples_per_symbol,
- excess_bw=_def_excess_bw,
- costas_alpha=_def_costas_alpha,
- gain_mu=_def_gain_mu,
- mu=_def_mu,
- omega_relative_limit=_def_omega_relative_limit,
- 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 gain_mu: for M&M block
- @type gain_mu: float
- @param mu: for M&M block
- @type mu: float
- @param omega_relative_limit: for M&M block
- @type omega_relative_limit: 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, "d8psk_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._mm_gain_mu = gain_mu
- self._mm_mu = mu
- self._mm_omega_relative_limit = omega_relative_limit
- 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
- 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, 1.0)
-
- # RRC data filter
- ntaps = 11 * samples_per_symbol
- self.rrc_taps = gr.firdes.root_raised_cosine(
- 1.0, # gain
- 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(1, self.rrc_taps)
-
- # symbol clock recovery
- 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.05
- fmax = 0.05
-
- 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.diffdec = gr.diff_decoder_bb(arity)
-
- # 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())
-
-
- # Connect and Initialize base class
- self.connect(self, self.pre_scaler, self.agc, self.rrc_filter, self.receiver,
- self.slicer, self.symbol_mapper, self.unpack, 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): # staticmethod that's also callable on an instance
- return 3
- 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 "M&M mu: %.2f" % self._mm_mu
- print "M&M mu gain: %.2e" % self._mm_gain_mu
- print "M&M omega: %.2f" % self._mm_omega
- print "M&M omega gain: %.2e" % self._mm_gain_omega
- print "M&M omega limit: %.2f" % self._mm_omega_relative_limit
-
-
- def _setup_logging(self):
- print "Demodulation 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.receiver, gr.file_sink(gr.sizeof_gr_complex, "rx_receiver.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 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=None,
- help="set Costas loop alpha value [default=%default] (PSK)")
- parser.add_option("", "--gain-mu", type="float", default=_def_gain_mu,
- help="set M&M symbol sync loop gain mu value [default=%default] (PSK)")
- parser.add_option("", "--mu", type="float", default=_def_mu,
- help="set M&M symbol sync loop mu value [default=%default] (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(
- d8psk_demod.__init__, ('self', 'fg'), options)
- extract_kwargs_from_options=staticmethod(extract_kwargs_from_options)
-
-
-#
-# Add these to the mod/demod registry
-#
-# NOT READY TO BE USED YET -- ENABLE AT YOUR OWN RISK
-#modulation_utils.add_type_1_mod('d8psk', d8psk_mod)
-#modulation_utils.add_type_1_demod('d8psk', d8psk_demod)
+++ /dev/null
-#
-# 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.15
-_def_gain_mu = 0.1
-_def_mu = 0.5
-_def_omega_relative_limit = 0.005
-
-
-# /////////////////////////////////////////////////////////////////////////////
-# DBPSK modulator
-# /////////////////////////////////////////////////////////////////////////////
-
-class dbpsk_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 components
- 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(dbpsk_mod.__init__,
- ('self', 'fg'), 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_symbol_mapper.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 dbpsk_demod(gr.hier_block2):
-
- def __init__(self,
- samples_per_symbol=_def_samples_per_symbol,
- excess_bw=_def_excess_bw,
- costas_alpha=_def_costas_alpha,
- gain_mu=_def_gain_mu,
- mu=_def_mu,
- omega_relative_limit=_def_omega_relative_limit,
- 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_alphas: float
- @param gain_mu: for M&M block
- @type gain_mu: float
- @param mu: for M&M block
- @type mu: float
- @param omega_relative_limit: for M&M block
- @type omega_relative_limit: 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, "dbpsk_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._mm_gain_mu = gain_mu
- self._mm_mu = mu
- self._mm_omega_relative_limit = omega_relative_limit
- 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
- 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, 1.0)
-
-
- # RRC data filter
- ntaps = 11 * samples_per_symbol
- self.rrc_taps = gr.firdes.root_raised_cosine(
- 1.0, # gain
- 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(1, self.rrc_taps)
-
- # symbol clock recovery
- 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.02
- fmax = 0.02
-
- 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)
-
- # Using differential decoding
- 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())
-
- # Connect and Initialize base class
- self.connect(self, self.pre_scaler, self.agc, self.rrc_filter, self.receiver,
- self.diffdec, self.slicer, self.symbol_mapper, self.unpack, 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): # 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: %.2e" % self._costas_alpha
- print "Costas Loop beta: %.2e" % self._costas_beta
- print "M&M mu: %.2f" % self._mm_mu
- print "M&M mu gain: %.2e" % self._mm_gain_mu
- print "M&M omega: %.2f" % self._mm_omega
- print "M&M omega gain: %.2e" % self._mm_gain_omega
- print "M&M omega limit: %.2f" % self._mm_omega_relative_limit
-
- def _setup_logging(self):
- print "Demodulation 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.receiver, gr.file_sink(gr.sizeof_gr_complex, "rx_receiver.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-mu", type="float", default=_def_gain_mu,
- help="set M&M symbol sync loop gain mu value [default=%default] (GMSK/PSK)")
- parser.add_option("", "--mu", type="float", default=_def_mu,
- help="set M&M symbol sync loop mu value [default=%default] (GMSK/PSK)")
- parser.add_option("", "--omega-relative-limit", type="float", default=_def_omega_relative_limit,
- help="M&M clock recovery omega relative limit [default=%default] (GMSK/PSK)")
- 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(
- dbpsk_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('dbpsk', dbpsk_mod)
-modulation_utils.add_type_1_demod('dbpsk', dbpsk_demod)
+++ /dev/null
-#
-# 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 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.15
-_def_gain_mu = 0.1
-_def_mu = 0.5
-_def_omega_relative_limit = 0.005
-
-
-# /////////////////////////////////////////////////////////////////////////////
-# DQPSK modulator
-# /////////////////////////////////////////////////////////////////////////////
-
-class dqpsk_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, "dqpsk_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)
-
- # Connect components
- 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): # 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_symbol_mapper.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(dqpsk_mod.__init__,
- ('self', 'fg'), options)
- extract_kwargs_from_options=staticmethod(extract_kwargs_from_options)
-
-
-# /////////////////////////////////////////////////////////////////////////////
-# DQPSK demodulator
-#
-# Differentially coherent detection of differentially encoded qpsk
-# /////////////////////////////////////////////////////////////////////////////
-
-class dqpsk_demod(gr.hier_block2):
-
- def __init__(self,
- samples_per_symbol=_def_samples_per_symbol,
- excess_bw=_def_excess_bw,
- costas_alpha=_def_costas_alpha,
- gain_mu=_def_gain_mu,
- mu=_def_mu,
- omega_relative_limit=_def_omega_relative_limit,
- 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 gain_mu: for M&M block
- @type gain_mu: float
- @param mu: for M&M block
- @type mu: float
- @param omega_relative_limit: for M&M block
- @type omega_relative_limit: 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, "dqpsk_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._mm_gain_mu = gain_mu
- self._mm_mu = mu
- self._mm_omega_relative_limit = omega_relative_limit
- 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
- scale = (1.0/16384.0)
- self.pre_scaler = gr.multiply_const_cc(scale) # scale the signal from full-range to +-1
- self.agc = gr.feedforward_agc_cc(16, 2.0)
-
- # RRC data filter
- ntaps = 11 * samples_per_symbol
- self.rrc_taps = gr.firdes.root_raised_cosine(
- 1.0, # gain
- 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(1, self.rrc_taps)
-
- # symbol clock recovery
- 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.01
- fmax = 0.01
-
- self.receiver=gr.mpsk_receiver_cc(arity, pi/4.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)
-
- # 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())
-
- # Connect and Initialize base class
- self.connect(self, self.pre_scaler, self.agc, self.rrc_filter, self.receiver, self.diffdec,
- self.slicer, self.symbol_mapper, self.unpack, 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): # 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 "M&M mu: %.2f" % self._mm_mu
- print "M&M mu gain: %.2e" % self._mm_gain_mu
- print "M&M omega: %.2f" % self._mm_omega
- print "M&M omega gain: %.2e" % self._mm_gain_omega
- print "M&M omega limit: %.2f" % self._mm_omega_relative_limit
-
- def _setup_logging(self):
- print "Demodulation 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.receiver, gr.file_sink(gr.sizeof_gr_complex, "rx_receiver.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 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=None,
- help="set Costas loop alpha value [default=%default] (PSK)")
- parser.add_option("", "--gain-mu", type="float", default=_def_gain_mu,
- help="set M&M symbol sync loop gain mu value [default=%default] (PSK)")
- parser.add_option("", "--mu", type="float", default=_def_mu,
- help="set M&M symbol sync loop mu value [default=%default] (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(
- dqpsk_demod.__init__, ('self', 'fg'), options)
- extract_kwargs_from_options=staticmethod(extract_kwargs_from_options)
-
-
-#
-# Add these to the mod/demod registry
-#
-modulation_utils.add_type_1_mod('dqpsk', dqpsk_mod)
-modulation_utils.add_type_1_demod('dqpsk', dqpsk_demod)
+++ /dev/null
-#
-# Copyright 2005 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.
-#
-
-import sys
-from gnuradio import gr, gru
-
-def _generate_synthesis_taps(mpoints):
- return [] # FIXME
-
-
-def _split_taps(taps, mpoints):
- assert (len(taps) % mpoints) == 0
- result = [list() for x in range(mpoints)]
- for i in xrange(len(taps)):
- (result[i % mpoints]).append(taps[i])
- return [tuple(x) for x in result]
-
-
-class synthesis_filterbank(gr.hier_block2):
- """
- Uniformly modulated polyphase DFT filter bank: synthesis
-
- See http://cnx.rice.edu/content/m10424/latest
- """
- def __init__(self, mpoints, taps=None):
- """
- Takes M complex streams in, produces single complex stream out
- that runs at M times the input sample rate
-
- @param fg: flow_graph
- @param mpoints: number of freq bins/interpolation factor/subbands
- @param taps: filter taps for subband filter
-
- The channel spacing is equal to the input sample rate.
- The total bandwidth and output sample rate are equal the input
- sample rate * nchannels.
-
- Output stream to frequency mapping:
-
- channel zero is at zero frequency.
-
- if mpoints is odd:
-
- Channels with increasing positive frequencies come from
- channels 1 through (N-1)/2.
-
- Channel (N+1)/2 is the maximum negative frequency, and
- frequency increases through N-1 which is one channel lower
- than the zero frequency.
-
- if mpoints is even:
-
- Channels with increasing positive frequencies come from
- channels 1 through (N/2)-1.
-
- Channel (N/2) is evenly split between the max positive and
- negative bins.
-
- Channel (N/2)+1 is the maximum negative frequency, and
- frequency increases through N-1 which is one channel lower
- than the zero frequency.
-
- Channels near the frequency extremes end up getting cut
- off by subsequent filters and therefore have diminished
- utility.
- """
- item_size = gr.sizeof_gr_complex
- gr.hier_block2.__init__(self, "synthesis_filterbank",
- gr.io_signature(mpoints, mpoints, item_size),
- gr.io_signature(1, 1, item_size))
-
- if taps is None:
- taps = _generate_synthesis_taps(mpoints)
-
- # pad taps to multiple of mpoints
- r = len(taps) % mpoints
- if r != 0:
- taps = taps + (mpoints - r) * (0,)
-
- # split in mpoints separate set of taps
- sub_taps = _split_taps(taps, mpoints)
-
- self.ss2v = gr.streams_to_vector(item_size, mpoints)
- self.ifft = gr.fft_vcc(mpoints, False, [])
- self.v2ss = gr.vector_to_streams(item_size, mpoints)
- # mpoints filters go in here...
- self.ss2s = gr.streams_to_stream(item_size, mpoints)
-
- for i in range(mpoints):
- self.connect((self, i), (self.ss2v, i))
-
- self.connect(self.ss2v, self.ifft, self.v2ss, self)
-
- # build mpoints fir filters...
- for i in range(mpoints):
- f = gr.fft_filter_ccc(1, sub_taps[i])
- self.connect((self.v2ss, i), f)
- self.connect(f, (self.ss2s, i))
-
-
-class analysis_filterbank(gr.hier_block2):
- """
- Uniformly modulated polyphase DFT filter bank: analysis
-
- See http://cnx.rice.edu/content/m10424/latest
- """
- def __init__(self, mpoints, taps=None):
- """
- Takes 1 complex stream in, produces M complex streams out
- that runs at 1/M times the input sample rate
-
- @param fg: flow_graph
- @param mpoints: number of freq bins/interpolation factor/subbands
- @param taps: filter taps for subband filter
-
- Same channel to frequency mapping as described above.
- """
- item_size = gr.sizeof_gr_complex
- gr.hier_block2.__init__(self, "analysis_filterbank",
- gr.io_signature(1, 1, item_size),
- gr.io_signature(mpoints, mpoints, item_size))
-
- if taps is None:
- taps = _generate_synthesis_taps(mpoints)
-
- # pad taps to multiple of mpoints
- r = len(taps) % mpoints
- if r != 0:
- taps = taps + (mpoints - r) * (0,)
-
- # split in mpoints separate set of taps
- sub_taps = _split_taps(taps, mpoints)
-
- # print >> sys.stderr, "mpoints =", mpoints, "len(sub_taps) =", len(sub_taps)
-
- self.s2ss = gr.stream_to_streams(item_size, mpoints)
- # filters here
- self.ss2v = gr.streams_to_vector(item_size, mpoints)
- self.fft = gr.fft_vcc(mpoints, True, [])
- self.v2ss = gr.vector_to_streams(item_size, mpoints)
-
- self.connect(self, self.s2ss)
-
- # build mpoints fir filters...
- for i in range(mpoints):
- f = gr.fft_filter_ccc(1, sub_taps[mpoints-i-1])
- self.connect((self.s2ss, i), f)
- self.connect(f, (self.ss2v, i))
-
- self.connect(self.ss2v, self.fft, self.v2ss)
-
- for i in range(mpoints):
- self.connect((self.v2ss, i), (self, i))
-
-
-
+++ /dev/null
-#
-# GMSK modulation and demodulation.
-#
-#
-# 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
-
-from gnuradio import gr
-from gnuradio import modulation_utils
-from math import pi
-import numpy
-from pprint import pprint
-import inspect
-
-# default values (used in __init__ and add_options)
-_def_samples_per_symbol = 2
-_def_bt = 0.35
-_def_verbose = False
-_def_log = False
-
-_def_gain_mu = 0.05
-_def_mu = 0.5
-_def_freq_error = 0.0
-_def_omega_relative_limit = 0.005
-
-
-# /////////////////////////////////////////////////////////////////////////////
-# GMSK modulator
-# /////////////////////////////////////////////////////////////////////////////
-
-class gmsk_mod(gr.hier_block2):
-
- def __init__(self,
- samples_per_symbol=_def_samples_per_symbol,
- bt=_def_bt,
- verbose=_def_verbose,
- log=_def_log):
- """
- Hierarchical block for Gaussian Minimum Shift Key (GMSK)
- 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 bt: Gaussian filter bandwidth * symbol time
- @type bt: float
- @param verbose: Print information about modulator?
- @type verbose: bool
- @param debug: Print modualtion data to files?
- @type debug: bool
- """
-
- gr.hier_block2.__init__(self, "gmsk_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._bt = bt
-
- if not isinstance(samples_per_symbol, int) or samples_per_symbol < 2:
- raise TypeError, ("samples_per_symbol must be an integer >= 2, is %r" % (samples_per_symbol,))
-
- ntaps = 4 * samples_per_symbol # up to 3 bits in filter at once
- sensitivity = (pi / 2) / samples_per_symbol # phase change per bit = pi / 2
-
- # Turn it into NRZ data.
- self.nrz = gr.bytes_to_syms()
-
- # Form Gaussian filter
- # Generate Gaussian response (Needs to be convolved with window below).
- self.gaussian_taps = gr.firdes.gaussian(
- 1, # gain
- samples_per_symbol, # symbol_rate
- bt, # bandwidth * symbol time
- ntaps # number of taps
- )
-
- self.sqwave = (1,) * samples_per_symbol # rectangular window
- self.taps = numpy.convolve(numpy.array(self.gaussian_taps),numpy.array(self.sqwave))
- self.gaussian_filter = gr.interp_fir_filter_fff(samples_per_symbol, self.taps)
-
- # FM modulation
- self.fmmod = gr.frequency_modulator_fc(sensitivity)
-
- # Connect components
- self.connect(self, self.nrz, self.gaussian_filter, self.fmmod, 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): # staticmethod that's also callable on an instance
- return 1
- bits_per_symbol = staticmethod(bits_per_symbol) # make it a static method.
-
-
- def _print_verbage(self):
- print "bits per symbol = %d" % self.bits_per_symbol()
- print "Gaussian filter bt = %.2f" % self._bt
-
-
- def _setup_logging(self):
- print "Modulation logging turned on."
- self.connect(self.nrz, gr.file_sink(gr.sizeof_float, "tx_nrz.dat"))
- self.connect(self.gaussian_filter, gr.file_sink(gr.sizeof_float, "tx_gaussian_filter.dat"))
- self.connect(self.fmmod, gr.file_sink(gr.sizeof_gr_complex, "tx_fmmod.dat"))
-
- def add_options(parser):
- """
- Adds GMSK modulation-specific options to the standard parser
- """
- parser.add_option("", "--bt", type="float", default=_def_bt,
- help="set bandwidth-time product [default=%default] (GMSK)")
- add_options=staticmethod(add_options)
-
-
- def extract_kwargs_from_options(options):
- """
- Given command line options, create dictionary suitable for passing to __init__
- """
- return modulation_utils.extract_kwargs_from_options(gmsk_mod.__init__,
- ('self', 'fg'), options)
- extract_kwargs_from_options=staticmethod(extract_kwargs_from_options)
-
-
-
-# /////////////////////////////////////////////////////////////////////////////
-# GMSK demodulator
-# /////////////////////////////////////////////////////////////////////////////
-
-class gmsk_demod(gr.hier_block2):
-
- def __init__(self,
- samples_per_symbol=_def_samples_per_symbol,
- gain_mu=_def_gain_mu,
- mu=_def_mu,
- omega_relative_limit=_def_omega_relative_limit,
- freq_error=_def_freq_error,
- verbose=_def_verbose,
- log=_def_log):
- """
- Hierarchical block for Gaussian Minimum Shift Key (GMSK)
- demodulation.
-
- The input is the complex modulated signal at baseband.
- The output is a stream of bits packed 1 bit per byte (the LSB)
-
- @param samples_per_symbol: samples per baud
- @type samples_per_symbol: integer
- @param verbose: Print information about modulator?
- @type verbose: bool
- @param log: Print modualtion data to files?
- @type log: bool
-
- Clock recovery parameters. These all have reasonble defaults.
-
- @param gain_mu: controls rate of mu adjustment
- @type gain_mu: float
- @param mu: fractional delay [0.0, 1.0]
- @type mu: float
- @param omega_relative_limit: sets max variation in omega
- @type omega_relative_limit: float, typically 0.000200 (200 ppm)
- @param freq_error: bit rate error as a fraction
- @param float
- """
-
- gr.hier_block2.__init__(self, "gmsk_demod",
- 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._gain_mu = gain_mu
- self._mu = mu
- self._omega_relative_limit = omega_relative_limit
- self._freq_error = freq_error
-
- if samples_per_symbol < 2:
- raise TypeError, "samples_per_symbol >= 2, is %f" % samples_per_symbol
-
- self._omega = samples_per_symbol*(1+self._freq_error)
-
- self._gain_omega = .25 * self._gain_mu * self._gain_mu # critically damped
-
- # Demodulate FM
- sensitivity = (pi / 2) / samples_per_symbol
- self.fmdemod = gr.quadrature_demod_cf(1.0 / sensitivity)
-
- # the clock recovery block tracks the symbol clock and resamples as needed.
- # the output of the block is a stream of soft symbols (float)
- self.clock_recovery = gr.clock_recovery_mm_ff(self._omega, self._gain_omega,
- self._mu, self._gain_mu,
- self._omega_relative_limit)
-
- # slice the floats at 0, outputting 1 bit (the LSB of the output byte) per sample
- self.slicer = gr.binary_slicer_fb()
-
- # Connect components
- self.connect(self, self.fmdemod, self.clock_recovery, self.slicer, 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): # staticmethod that's also callable on an instance
- return 1
- bits_per_symbol = staticmethod(bits_per_symbol) # make it a static method.
-
- def _print_verbage(self):
- print "bits per symbol = %d" % self.bits_per_symbol()
- print "M&M clock recovery omega = %f" % self._omega
- print "M&M clock recovery gain mu = %f" % self._gain_mu
- print "M&M clock recovery mu = %f" % self._mu
- print "M&M clock recovery omega rel. limit = %f" % self._omega_relative_limit
- print "frequency error = %f" % self._freq_error
-
-
- def _setup_logging(self):
- print "Demodulation logging turned on."
- self.connect(self.fmdemod, gr.file_sink(gr.sizeof_float, "rx_fmdemod.dat"))
- self.connect(self.clock_recovery, gr.file_sink(gr.sizeof_float, "rx_clock_recovery.dat"))
- self.connect(self.slicer, gr.file_sink(gr.sizeof_char, "rx_slicer.dat"))
-
- def add_options(parser):
- """
- Adds GMSK demodulation-specific options to the standard parser
- """
- parser.add_option("", "--gain-mu", type="float", default=_def_gain_mu,
- help="M&M clock recovery gain mu [default=%default] (GMSK/PSK)")
- parser.add_option("", "--mu", type="float", default=_def_mu,
- help="M&M clock recovery mu [default=%default] (GMSK/PSK)")
- parser.add_option("", "--omega-relative-limit", type="float", default=_def_omega_relative_limit,
- help="M&M clock recovery omega relative limit [default=%default] (GMSK/PSK)")
- parser.add_option("", "--freq-error", type="float", default=_def_freq_error,
- help="M&M clock recovery frequency error [default=%default] (GMSK)")
- add_options=staticmethod(add_options)
-
- def extract_kwargs_from_options(options):
- """
- Given command line options, create dictionary suitable for passing to __init__
- """
- return modulation_utils.extract_kwargs_from_options(gmsk_demod.__init__,
- ('self', 'fg'), options)
- extract_kwargs_from_options=staticmethod(extract_kwargs_from_options)
-
-
-#
-# Add these to the mod/demod registry
-#
-modulation_utils.add_type_1_mod('gmsk', gmsk_mod)
-modulation_utils.add_type_1_demod('gmsk', gmsk_demod)
+++ /dev/null
-#
-# 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.
-#
-
-from math import pi
-from gnuradio import gr, packet_utils
-import gnuradio.gr.gr_threading as _threading
-
-
-# /////////////////////////////////////////////////////////////////////////////
-# mod/demod with packets as i/o
-# /////////////////////////////////////////////////////////////////////////////
-
-class mod_pkts(gr.hier_block2):
- """
- Wrap an arbitrary digital modulator in our packet handling framework.
-
- Send packets by calling send_pkt
- """
- def __init__(self, modulator, access_code=None, msgq_limit=2, pad_for_usrp=True):
- """
- Hierarchical block for sending packets
-
- Packets to be sent are enqueued by calling send_pkt.
- The output is the complex modulated signal at baseband.
-
- @param modulator: instance of modulator class (gr_block or hier_block)
- @type modulator: complex baseband out
- @param access_code: AKA sync vector
- @type access_code: string of 1's and 0's between 1 and 64 long
- @param msgq_limit: maximum number of messages in message queue
- @type msgq_limit: int
- @param pad_for_usrp: If true, packets are padded such that they end up a multiple of 128 samples
- """
-
- gr.hier_block2.__init__(self, "mod_pkts",
- gr.io_signature(0,0,0), # Input signature
- gr.io_signature(1,1,gr.sizeof_gr_complex)) # Output signature
-
- self._modulator = modulator
- self._pad_for_usrp = pad_for_usrp
-
- if access_code is None:
- access_code = packet_utils.default_access_code
- if not packet_utils.is_1_0_string(access_code):
- raise ValueError, "Invalid access_code %r. Must be string of 1's and 0's" % (access_code,)
- self._access_code = access_code
-
- # accepts messages from the outside world
- self._pkt_input = gr.message_source(gr.sizeof_char, msgq_limit)
- self.connect(self._pkt_input, self._modulator, self)
-
- def send_pkt(self, payload='', eof=False):
- """
- Send the payload.
-
- @param payload: data to send
- @type payload: string
- """
- if eof:
- msg = gr.message(1) # tell self._pkt_input we're not sending any more packets
- else:
- # print "original_payload =", string_to_hex_list(payload)
- pkt = packet_utils.make_packet(payload,
- self._modulator.samples_per_symbol(),
- self._modulator.bits_per_symbol(),
- self._access_code,
- self._pad_for_usrp)
- #print "pkt =", string_to_hex_list(pkt)
- msg = gr.message_from_string(pkt)
- self._pkt_input.msgq().insert_tail(msg)
-
-
-
-class demod_pkts(gr.hier_block2):
- """
- Wrap an arbitrary digital demodulator in our packet handling framework.
-
- The input is complex baseband. When packets are demodulated, they are passed to the
- app via the callback.
- """
-
- def __init__(self, demodulator, access_code=None, callback=None, threshold=-1):
- """
- Hierarchical block for demodulating and deframing packets.
-
- The input is the complex modulated signal at baseband.
- Demodulated packets are sent to the handler.
-
- @param demodulator: instance of demodulator class (gr_block or hier_block)
- @type demodulator: complex baseband in
- @param access_code: AKA sync vector
- @type access_code: string of 1's and 0's
- @param callback: function of two args: ok, payload
- @type callback: ok: bool; payload: string
- @param threshold: detect access_code with up to threshold bits wrong (-1 -> use default)
- @type threshold: int
- """
-
- gr.hier_block2.__init__(self, "demod_pkts",
- gr.io_signature(1,1,gr.sizeof_gr_complex), # Input signature
- gr.io_signature(0,0,0)) # Output signature
-
- self._demodulator = demodulator
- if access_code is None:
- access_code = packet_utils.default_access_code
- if not packet_utils.is_1_0_string(access_code):
- raise ValueError, "Invalid access_code %r. Must be string of 1's and 0's" % (access_code,)
- self._access_code = access_code
-
- if threshold == -1:
- threshold = 12 # FIXME raise exception
-
- self._rcvd_pktq = gr.msg_queue() # holds packets from the PHY
-
- self._correlator = gr.correlate_access_code_bb(access_code, threshold)
- self._framer_sink = gr.framer_sink_1(self._rcvd_pktq)
- self.connect(self, self._demodulator, self._correlator, self._framer_sink)
-
- self._watcher = _queue_watcher_thread(self._rcvd_pktq, callback)
-
-
-class _queue_watcher_thread(_threading.Thread):
- def __init__(self, rcvd_pktq, callback):
- _threading.Thread.__init__(self)
- self.setDaemon(1)
- self.rcvd_pktq = rcvd_pktq
- self.callback = callback
- self.keep_running = True
- self.start()
-
-
- def run(self):
- while self.keep_running:
- msg = self.rcvd_pktq.delete_head()
- ok, payload = packet_utils.unmake_packet(msg.to_string())
- if self.callback:
- self.callback(ok, payload)
+++ /dev/null
-#
-# Copyright 2005,2006 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 math import pi, sqrt, log10
-import math, cmath
-
-# The following algorithm generates Gray coded constellations for M-PSK for M=[2,4,8]
-def make_gray_constellation(m):
- # number of bits/symbol (log2(M))
- k = int(log10(m) / log10(2.0))
-
- coeff = 1
- const_map = []
- bits = [0]*3
- for i in range(m):
- # get a vector of the k bits to use in this mapping
- bits[3-k:3] = [((i&(0x01 << k-j-1)) >> k-j-1) for j in range(k)]
-
- theta = -(2*bits[0]-1)*(2*pi/m)*(bits[0]+abs(bits[1]-bits[2])+2*bits[1])
- re = math.cos(theta)
- im = math.sin(theta)
- const_map.append(complex(re, im)) # plug it into the constellation
-
- # return the constellation; by default, it is normalized
- return const_map
-
-# This makes a constellation that increments around the unit circle
-def make_constellation(m):
- return [cmath.exp(i * 2 * pi / m * 1j) for i in range(m)]
-
-# Common definition of constellations for Tx and Rx
-constellation = {
- 2 : make_constellation(2), # BPSK
- 4 : make_constellation(4), # QPSK
- 8 : make_constellation(8) # 8PSK
- }
-
-# -----------------------
-# Do Gray code
-# -----------------------
-# binary to gray coding -- constellation does Gray coding
-binary_to_gray = {
- 2 : range(2),
- 4 : [0,1,3,2],
- 8 : [0, 1, 3, 2, 7, 6, 4, 5]
- }
-
-# gray to binary
-gray_to_binary = {
- 2 : range(2),
- 4 : [0,1,3,2],
- 8 : [0, 1, 3, 2, 6, 7, 5, 4]
- }
-
-# -----------------------
-# Don't Gray code
-# -----------------------
-# identity mapping
-binary_to_ungray = {
- 2 : range(2),
- 4 : range(4),
- 8 : range(8)
- }
-
-# identity mapping
-ungray_to_binary = {
- 2 : range(2),
- 4 : range(4),
- 8 : range(8)
- }
+++ /dev/null
-#
-# Copyright 2005,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.
-#
-
-from gnuradio import gr, gru
-
-_plot = None
-
-def design_filter(interpolation, decimation, fractional_bw):
- """
- Given the interpolation rate, decimation rate and a fractional bandwidth,
- design a set of taps.
-
- @param interpolation: interpolation factor
- @type interpolation: integer > 0
- @param decimation: decimation factor
- @type decimation: integer > 0
- @param fractional_bw: fractional bandwidth in (0, 0.5) 0.4 works well.
- @type fractional_bw: float
- @returns: sequence of numbers
- """
-
- if fractional_bw >= 0.5 or fractional_bw <= 0:
- raise ValueError, "Invalid fractional_bandwidth, must be in (0, 0.5)"
-
- beta = 5.0
- trans_width = 0.5 - fractional_bw
- mid_transition_band = 0.5 - trans_width/2
-
- taps = gr.firdes.low_pass(interpolation, # gain
- 1, # Fs
- mid_transition_band/interpolation, # trans mid point
- trans_width/interpolation, # transition width
- gr.firdes.WIN_KAISER,
- beta # beta
- )
-
- return taps
-
-
-
-class _rational_resampler_base(gr.hier_block2):
- """
- base class for all rational resampler variants.
- """
- def __init__(self, resampler_base,
- interpolation, decimation, taps=None, fractional_bw=None):
- """
- Rational resampling polyphase FIR filter.
-
- Either taps or fractional_bw may be specified, but not both.
- If neither is specified, a reasonable default, 0.4, is used as
- the fractional_bw.
-
- @param interpolation: interpolation factor
- @type interpolation: integer > 0
- @param decimation: decimation factor
- @type decimation: integer > 0
- @param taps: optional filter coefficients
- @type taps: sequence
- @param fractional_bw: fractional bandwidth in (0, 0.5), measured at final freq (use 0.4)
- @type fractional_bw: float
- """
-
- if not isinstance(interpolation, int) or interpolation < 1:
- raise ValueError, "interpolation must be an integer >= 1"
-
- if not isinstance(decimation, int) or decimation < 1:
- raise ValueError, "decimation must be an integer >= 1"
-
- if taps is None and fractional_bw is None:
- fractional_bw = 0.4
-
- d = gru.gcd(interpolation, decimation)
- interpolation = interpolation // d
- decimation = decimation // d
-
- if taps is None:
- taps = design_filter(interpolation, decimation, fractional_bw)
-
- resampler = resampler_base(interpolation, decimation, taps)
- gr.hier_block2.__init__(self, resampler.name(),
- gr.io_signature(1, 1, resampler.input_signature().sizeof_stream_item(0)),
- gr.io_signature(1, 1, resampler.output_signature().sizeof_stream_item(1)))
-
- self.connect(self, resampler, self)
-
-
-class rational_resampler_fff(_rational_resampler_base):
- def __init__(self, interpolation, decimation, taps=None, fractional_bw=None):
- """
- Rational resampling polyphase FIR filter with
- float input, float output and float taps.
- """
- _rational_resampler_base.__init__(self, gr.rational_resampler_base_fff,
- interpolation, decimation, taps, fractional_bw)
-
-class rational_resampler_ccf(_rational_resampler_base):
- def __init__(self, interpolation, decimation, taps=None, fractional_bw=None):
- """
- Rational resampling polyphase FIR filter with
- complex input, complex output and float taps.
- """
- _rational_resampler_base.__init__(self, gr.rational_resampler_base_ccf,
- interpolation, decimation, taps, fractional_bw)
-
-class rational_resampler_ccc(_rational_resampler_base):
- def __init__(self, interpolation, decimation, taps=None, fractional_bw=None):
- """
- Rational resampling polyphase FIR filter with
- complex input, complex output and complex taps.
- """
- _rational_resampler_base.__init__(self, gr.rational_resampler_base_ccc,
- interpolation, decimation, taps, fractional_bw)
return getattr(self._hb, name)
def connect(self, *points):
- '''connect requires two or more arguments that can be coerced to endpoints.
+ '''connect requires one or more arguments that can be coerced to endpoints.
If more than two arguments are provided, they are connected together successively.
'''
- if len (points) < 2:
- raise ValueError, ("connect requires at least two endpoints; %d provided." % (len (points),))
- for i in range (1, len (points)):
- self._connect(points[i-1], points[i])
+ if len (points) < 1:
+ raise ValueError, ("connect requires at least one endpoint; %d provided." % (len (points),))
+ else:
+ if len(points) == 1:
+ self._hb.connect(points[0].basic_block())
+ else:
+ for i in range (1, len (points)):
+ self._connect(points[i-1], points[i])
def _connect(self, src, dst):
(src_block, src_port) = self._coerce_endpoint(src)
raise ValueError("unable to coerce endpoint")
def disconnect(self, *points):
- '''connect requires two or more arguments that can be coerced to endpoints.
+ '''connect requires one or more arguments that can be coerced to endpoints.
If more than two arguments are provided, they are disconnected successively.
'''
- if len (points) < 2:
+ if len (points) < 1:
raise ValueError, ("disconnect requires at least two endpoints; %d provided." % (len (points),))
- for i in range (1, len (points)):
- self._disconnect(points[i-1], points[i])
+ else:
+ if len (points) == 1:
+ self._hb.disconnect(points[0].basic_block())
+ else:
+ for i in range (1, len (points)):
+ self._disconnect(points[i-1], points[i])
def _disconnect(self, src, dst):
(src_block, src_port) = self._coerce_endpoint(src)
hblock.run()
self.assertEquals(data, dst.data())
+ def test_021_connect_single(self):
+ hblock = gr.top_block("test_block")
+ blk = gr.hier_block2("block",
+ gr.io_signature(0, 0, 0),
+ gr.io_signature(0, 0, 0))
+ hblock.connect(blk)
+
+ def test_022_connect_single_with_ports(self):
+ hblock = gr.top_block("test_block")
+ blk = gr.hier_block2("block",
+ gr.io_signature(1, 1, 1),
+ gr.io_signature(1, 1, 1))
+ self.assertRaises(ValueError,
+ lambda: hblock.connect(blk))
+
+ def test_023_connect_single_twice(self):
+ hblock = gr.top_block("test_block")
+ blk = gr.hier_block2("block",
+ gr.io_signature(0, 0, 0),
+ gr.io_signature(0, 0, 0))
+ hblock.connect(blk)
+ self.assertRaises(ValueError,
+ lambda: hblock.connect(blk))
+
+ def test_024_disconnect_single(self):
+ hblock = gr.top_block("test_block")
+ blk = gr.hier_block2("block",
+ gr.io_signature(0, 0, 0),
+ gr.io_signature(0, 0, 0))
+ hblock.connect(blk)
+ hblock.disconnect(blk)
+
+ def test_025_disconnect_single_not_connected(self):
+ hblock = gr.top_block("test_block")
+ blk = gr.hier_block2("block",
+ gr.io_signature(0, 0, 0),
+ gr.io_signature(0, 0, 0))
+ self.assertRaises(ValueError,
+ lambda: hblock.disconnect(blk))
+
+ def test_026_run_single(self):
+ expected_data = (1.0,)
+ tb = gr.top_block("top_block")
+ hb = gr.hier_block2("block",
+ gr.io_signature(0, 0, 0),
+ gr.io_signature(0, 0, 0))
+ src = gr.vector_source_f(expected_data)
+ dst = gr.vector_sink_f()
+ hb.connect(src, dst)
+ tb.connect(hb)
+ tb.run()
+ self.assertEquals(expected_data, dst.data())
+
if __name__ == "__main__":
gr_unittest.main()
# in the original C++ class (gr_hier_block2), then they would all be inherited here
def connect(self, *points):
- '''connect requires two or more arguments that can be coerced to endpoints.
+ '''connect requires one or more arguments that can be coerced to endpoints.
If more than two arguments are provided, they are connected together successively.
'''
- if len (points) < 2:
- raise ValueError, ("connect requires at least two endpoints; %d provided." % (len (points),))
- for i in range (1, len (points)):
- self._connect(points[i-1], points[i])
+ if len (points) < 1:
+ raise ValueError, ("connect requires at least one endpoint; %d provided." % (len (points),))
+ else:
+ if len(points) == 1:
+ self._tb.connect(points[0].basic_block())
+ else:
+ for i in range (1, len (points)):
+ self._connect(points[i-1], points[i])
def _connect(self, src, dst):
(src_block, src_port) = self._coerce_endpoint(src)
raise ValueError("unable to coerce endpoint")
def disconnect(self, *points):
- '''connect requires two or more arguments that can be coerced to endpoints.
+ '''connect requires one or more arguments that can be coerced to endpoints.
If more than two arguments are provided, they are disconnected successively.
'''
- if len (points) < 2:
+ if len (points) < 1:
raise ValueError, ("disconnect requires at least two endpoints; %d provided." % (len (points),))
- for i in range (1, len (points)):
- self._disconnect(points[i-1], points[i])
+ else:
+ if len(points) == 1:
+ self._tb.disconnect(points[0].basic_block())
+ else:
+ for i in range (1, len (points)):
+ self._disconnect(points[i-1], points[i])
def _disconnect(self, src, dst):
(src_block, src_port) = self._coerce_endpoint(src)
include $(top_srcdir)/Makefile.common
SUBDIRS = \
- apps \
- audio \
- digital_voice \
- digital \
- multi-antenna \
- multi_usrp \
- networking \
- usrp \
- hier \
- ofdm
+ apps \
+ audio \
+ dect \
+ digital \
+ digital_voice \
+ multi-antenna \
+ multi_usrp \
+ network \
+ ofdm \
+ usrp
# Make example scripts with #! executable
install-data-local:
import os, wx, sys, math
import wx.lib.evtmgr as em
-from gnuradio.wxgui import powermate, fftsink
+from gnuradio.wxgui import powermate, fftsink2
from gnuradio import gr, audio, eng_notation, usrp, gru
from gnuradio.eng_option import eng_option
from optparse import OptionParser
self.xdata = []
self.ydata = []
- self.fg = gr.flow_graph()
+ self.tb = gr.top_block()
# radio variables, initial conditions
self.frequency = self.usrp_center
# save radio data to a file
if SAVE_RADIO_TO_FILE:
file = gr.file_sink(gr.sizeof_short, options.radio_file)
- self.fg.connect (self.src, file)
+ self.tb.connect (self.src, file)
# 2nd DDC
xlate_taps = gr.firdes.low_pass ( \
s2f1 = gr.short_to_float()
s2f2 = gr.short_to_float()
src_f2c = gr.float_to_complex()
- self.fg.connect(self.src,s2ss)
- self.fg.connect((s2ss,0),s2f1)
- self.fg.connect((s2ss,1),s2f2)
- self.fg.connect(s2f1,(src_f2c,0))
- self.fg.connect(s2f2,(src_f2c,1))
+ self.tb.connect(self.src,s2ss)
+ self.tb.connect((s2ss,0),s2f1)
+ self.tb.connect((s2ss,1),s2f2)
+ self.tb.connect(s2f1,(src_f2c,0))
+ self.tb.connect(s2f2,(src_f2c,1))
# Complex Audio filter
self.audio_filter = gr.fir_filter_ccc ( 1, audio_coeffs)
# Main +/- 16Khz spectrum display
- self.fft = fftsink.fft_sink_c (self.fg, self.panel_2, fft_size=512, sample_rate=self.af_sample_rate, average=True, size=(640,240))
+ self.fft = fftsink2.fft_sink_c (self.panel_2, fft_size=512, sample_rate=self.af_sample_rate, average=True, size=(640,240))
# AM Sync carrier
if AM_SYNC_DISPLAY:
- self.fft2 = fftsink.fft_sink_c (self.fg, self.panel_9, y_per_div=20, fft_size=512, sample_rate=self.af_sample_rate, average=True, size=(640,240))
+ self.fft2 = fftsink.fft_sink_c (self.tb, self.panel_9, y_per_div=20, fft_size=512, sample_rate=self.af_sample_rate, average=True, size=(640,240))
c2f = gr.complex_to_float()
self.scale = gr.multiply_const_ff(0.00001)
dst = audio.sink(long(self.af_sample_rate))
- self.fg.connect(src_f2c,self.xlate,self.fft)
- self.fg.connect(self.xlate,self.audio_filter,self.sel_am,(am_det,0))
- self.fg.connect(self.sel_am,pll,self.pll_carrier_scale,self.pll_carrier_filter,c2f3)
- self.fg.connect((c2f3,0),phaser1,(f2c,0))
- self.fg.connect((c2f3,1),phaser2,(f2c,1))
- self.fg.connect(f2c,(am_det,1))
- self.fg.connect(am_det,c2f2,(combine,0))
- self.fg.connect(self.audio_filter,c2f,self.sel_sb,(combine,1))
+ self.tb.connect(src_f2c,self.xlate,self.fft)
+ self.tb.connect(self.xlate,self.audio_filter,self.sel_am,(am_det,0))
+ self.tb.connect(self.sel_am,pll,self.pll_carrier_scale,self.pll_carrier_filter,c2f3)
+ self.tb.connect((c2f3,0),phaser1,(f2c,0))
+ self.tb.connect((c2f3,1),phaser2,(f2c,1))
+ self.tb.connect(f2c,(am_det,1))
+ self.tb.connect(am_det,c2f2,(combine,0))
+ self.tb.connect(self.audio_filter,c2f,self.sel_sb,(combine,1))
if AM_SYNC_DISPLAY:
- self.fg.connect(self.pll_carrier_filter,self.fft2)
- self.fg.connect(combine,self.scale)
- self.fg.connect(self.scale,(sqr1,0))
- self.fg.connect(self.scale,(sqr1,1))
- self.fg.connect(sqr1, intr, offset, (agc, 1))
- self.fg.connect(self.scale,(agc, 0))
- self.fg.connect(agc,dst)
+ self.tb.connect(self.pll_carrier_filter,self.fft2)
+ self.tb.connect(combine,self.scale)
+ self.tb.connect(self.scale,(sqr1,0))
+ self.tb.connect(self.scale,(sqr1,1))
+ self.tb.connect(sqr1, intr, offset, (agc, 1))
+ self.tb.connect(self.scale,(agc, 0))
+ self.tb.connect(agc,dst)
if SAVE_AUDIO_TO_FILE:
f_out = gr.file_sink(gr.sizeof_short,options.audio_file)
sc1 = gr.multiply_const_ff(64000)
f2s1 = gr.float_to_short()
- self.fg.connect(agc,sc1,f2s1,f_out)
+ self.tb.connect(agc,sc1,f2s1,f_out)
- self.fg.start()
+ self.tb.start()
# for mouse position reporting on fft display
em.eventManager.Register(self.Mouse, wx.EVT_MOTION, self.fft.win)
# Menu exit
def TimeToQuit(self, event):
- self.fg.stop()
+ self.tb.stop()
self.Close(True)
# Powermate being turned
#!/usr/bin/env python
#
-# Copyright 2004,2005 Free Software Foundation, Inc.
+# Copyright 2004,2005,2007 Free Software Foundation, Inc.
#
# This file is part of GNU Radio
#
from gnuradio.eng_option import eng_option
from optparse import OptionParser
-class my_graph(gr.flow_graph):
+class my_top_block(gr.top_block):
def __init__(self):
- gr.flow_graph.__init__(self)
+ gr.top_block.__init__(self)
parser = OptionParser(option_class=eng_option)
parser.add_option("-I", "--audio-input", type="string", default="",
if __name__ == '__main__':
try:
- my_graph().run()
+ my_top_block().run()
except KeyboardInterrupt:
pass
#!/usr/bin/env python
#
-# Copyright 2004,2005 Free Software Foundation, Inc.
+# Copyright 2004,2005,2007 Free Software Foundation, Inc.
#
# This file is part of GNU Radio
#
from gnuradio import gr, gru, audio
from gnuradio import eng_notation
from gnuradio.eng_option import eng_option
-from gnuradio.wxgui import stdgui, fftsink, waterfallsink, scopesink, form, slider
+from gnuradio.wxgui import stdgui2, fftsink2, waterfallsink2, scopesink2, form, slider
from optparse import OptionParser
import wx
import sys
-class app_flow_graph(stdgui.gui_flow_graph):
+class app_top_block(stdgui2.std_top_block):
def __init__(self, frame, panel, vbox, argv):
- stdgui.gui_flow_graph.__init__(self)
+ stdgui2.std_top_block.__init__(self, frame, panel, vbox, argv)
self.frame = frame
self.panel = panel
# build the graph
if options.waterfall:
self.scope = \
- waterfallsink.waterfall_sink_f (self, panel, fft_size=1024, sample_rate=sample_rate)
+ waterfallsink2.waterfall_sink_f (panel, fft_size=1024, sample_rate=sample_rate)
elif options.oscilloscope:
- self.scope = scopesink.scope_sink_f(self, panel, sample_rate=sample_rate)
+ self.scope = scopesink2.scope_sink_f(panel, sample_rate=sample_rate)
else:
- self.scope = fftsink.fft_sink_f (self, panel, fft_size=1024, sample_rate=sample_rate, fft_rate=30)
+ self.scope = fftsink2.fft_sink_f (panel, fft_size=1024, sample_rate=sample_rate, fft_rate=30)
self.src = audio.source (sample_rate, options.audio_input)
def main ():
- app = stdgui.stdapp(app_flow_graph, "Audio FFT", nstatus=1)
+ app = stdgui2.stdapp(app_top_block, "Audio FFT", nstatus=1)
app.MainLoop()
if __name__ == '__main__':
#!/usr/bin/env python
#
-# Copyright 2004,2005 Free Software Foundation, Inc.
+# Copyright 2004,2005,2007 Free Software Foundation, Inc.
#
# This file is part of GNU Radio
#
from optparse import OptionParser
-class my_graph(gr.flow_graph):
+class my_top_block(gr.top_block):
def __init__(self):
- gr.flow_graph.__init__(self)
+ gr.top_block.__init__(self)
parser = OptionParser(option_class=eng_option)
parser.add_option("-F", "--filename", type="string", default="audio.dat",
if __name__ == '__main__':
try:
- my_graph().run()
+ my_top_block().run()
except KeyboardInterrupt:
pass
#!/usr/bin/env python
#
-# Copyright 2004 Free Software Foundation, Inc.
+# Copyright 2004,2007 Free Software Foundation, Inc.
#
# This file is part of GNU Radio
#
from gnuradio.eng_option import eng_option
from optparse import OptionParser
-class my_graph(gr.flow_graph):
+class my_top_block(gr.top_block):
def __init__(self):
- gr.flow_graph.__init__(self)
+ gr.top_block.__init__(self)
usage="%prog: [options] output_filename"
parser = OptionParser(option_class=eng_option, usage=usage)
if __name__ == '__main__':
try:
- my_graph().run()
+ my_top_block().run()
except KeyboardInterrupt:
pass
#!/usr/bin/env python
#
-# Copyright 2004,2005 Free Software Foundation, Inc.
+# Copyright 2004,2005,2007 Free Software Foundation, Inc.
#
# This file is part of GNU Radio
#
from gnuradio.eng_option import eng_option
from optparse import OptionParser
-class my_graph(gr.flow_graph):
+class my_top_block(gr.top_block):
def __init__(self):
- gr.flow_graph.__init__(self)
+ gr.top_block.__init__(self)
parser = OptionParser(option_class=eng_option)
parser.add_option("-O", "--audio-output", type="string", default="",
if __name__ == '__main__':
try:
- my_graph().run()
+ my_top_block().run()
except KeyboardInterrupt:
pass
#!/usr/bin/env python
#
-# Copyright 2004,2005 Free Software Foundation, Inc.
+# Copyright 2004,2005,2007 Free Software Foundation, Inc.
#
# This file is part of GNU Radio
#
#print os.getpid()
#raw_input('Attach gdb and press Enter: ')
-class my_graph(gr.flow_graph):
+class my_top_block(gr.top_block):
def __init__(self):
- gr.flow_graph.__init__(self)
+ gr.top_block.__init__(self)
parser = OptionParser(option_class=eng_option)
parser.add_option("-O", "--audio-output", type="string", default="",
if __name__ == '__main__':
try:
- my_graph().run()
+ my_top_block().run()
except KeyboardInterrupt:
pass
#!/usr/bin/env python
#
-# Copyright 2004,2006 Free Software Foundation, Inc.
+# Copyright 2004,2006,2007 Free Software Foundation, Inc.
#
# This file is part of GNU Radio
#
#print os.getpid()
#raw_input('Attach gdb and press Enter: ')
-class my_graph(gr.flow_graph):
+class my_top_block(gr.top_block):
def __init__(self):
- gr.flow_graph.__init__(self)
+ gr.top_block.__init__(self)
parser = OptionParser(option_class=eng_option)
parser.add_option("-O", "--audio-output", type="string", default="",
if __name__ == '__main__':
try:
- my_graph().run()
+ my_top_block().run()
except KeyboardInterrupt:
pass
from gnuradio.eng_option import eng_option
from optparse import OptionParser
-class my_graph(gr.flow_graph):
+class my_top_block(gr.top_block):
def __init__(self):
- gr.flow_graph.__init__(self)
+ gr.top_block.__init__(self)
parser = OptionParser(option_class=eng_option)
parser.add_option("-O", "--audio-output", type="string", default="",
if __name__ == '__main__':
try:
- my_graph().run()
+ my_top_block().run()
except KeyboardInterrupt:
pass
#!/usr/bin/env python
+#
+# Copyright 2004,2005,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.
+
#
# Gang - Here's a simple script that demonstrates spectrum inversion
# using the multiply by [1,-1] method (mixing with Nyquist frequency).
from gnuradio.eng_option import eng_option
from optparse import OptionParser
-class my_graph(gr.flow_graph):
+class my_top_block(gr.top_block):
def __init__(self):
- gr.flow_graph.__init__(self)
+ gr.top_block.__init__(self)
parser = OptionParser(option_class=eng_option)
parser.add_option("-I", "--audio-input", type="string", default="",
if __name__ == '__main__':
try:
- my_graph().run()
+ my_top_block().run()
except KeyboardInterrupt:
pass
#!/usr/bin/env python
#
-# Copyright 2004,2005 Free Software Foundation, Inc.
+# Copyright 2004,2005,2007 Free Software Foundation, Inc.
#
# This file is part of GNU Radio
#
# Boston, MA 02110-1301, USA.
#
-from gnuradio import gr, gru, blks
+from gnuradio import gr, gru, blks2
from gnuradio import audio
from gnuradio.eng_option import eng_option
from optparse import OptionParser
-class my_graph(gr.flow_graph):
+class my_top_block(gr.top_block):
def __init__(self):
- gr.flow_graph.__init__(self)
+ gr.top_block.__init__(self)
parser = OptionParser(option_class=eng_option)
parser.add_option("-O", "--audio-output", type="string", default="",
ampl = 0.1
src0 = gr.sig_source_f (input_rate, gr.GR_SIN_WAVE, 650, ampl)
- rr = blks.rational_resampler_fff(self, interp, decim)
+ rr = blks2.rational_resampler_fff(interp, decim)
dst = audio.sink (output_rate, options.audio_output)
self.connect (src0, rr, (dst, 0))
if __name__ == '__main__':
try:
- my_graph().run()
+ my_top_block().run()
except KeyboardInterrupt:
pass
--- /dev/null
+#
+# Copyright 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.
+#
+
+include $(top_srcdir)/Makefile.common
+
+EXTRA_DIST = \
+ README \
+ dect_receiver.py \
+ usrp_source.py \
+ usrp_dect.py
+
+ourdatadir = $(exampledir)/dect
+ourdata_DATA = $(EXTRA_DIST)
+
+MOSTLYCLEANFILES = *.pyc *~
--- /dev/null
+This directory contains a work in progress service monitor for DECT
+digital cordless phone base stations and handsets.
+
+
+Status
+------
+
+2007 Apr 27 - Converted to new hier_block2 format
+2007 Apr 03 - Development on hold.
+2007 Feb 11 - Added GMSK demodulation and option to log to file
+2007 Feb 10 - Able to tune and log filtered baseband to file
+
+
+Files
+-----
+
+usrp_dect.py - DECT receiver application
+
+dect_receiver.py - Top-level hierarchical block (new type) implementing
+ receiver
+
+usrp_source.py - Hierarchical block (new type) implementing a USRP
+ complex source, with convenience functions for tuning,
+ gain, decimation, etc.
+
+gmsk2.py - Hierarchical block (new type) implementing GMSK
+ modulation and demodulation. This will eventually go
+ into the core blksimpl directory
+
+DECT Modulation Details
+-----------------------
+
+In the US, the FCC has allocated four carrier frequencies for DECT usage:
+
+Channel Frequency
+------- ---------
+ 1 1921.536 MHz
+ 2 1923.264 MHz
+ 3 1924.992 MHz
+ 4 1926.720 MHz
+
+These are spaced at 1.728 MHz intervals.
+
+The DECT PHY uses GMSK with a 0.5 bandwidth-time product at 1.152 Msym/sec,
+for an occupied bandwidth (99% power) of 1.186 MHz (1.03 x symbol rate.)
+
--- /dev/null
+#!/usr/bin/env python
+#
+# Copyright 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.
+#
+
+from gnuradio import gr, optfir, blks2
+from usrp_source import usrp_source_c
+
+_dect_symbol_rate = 1.152e6
+_dect_occupied_bandwidth = _dect_symbol_rate * 1.03 # BT=0.5
+_dect_channel_bandwidth = 1.728e6
+
+# Top-level hierarchical block that implements DECT demodulation and
+# decoding.
+class dect_receiver(gr.top_block):
+ def __init__(self, options):
+ gr.top_block.__init__(self, "dect_receiver")
+ self._options = options
+
+ # Need greater than 2 samples per symbol. This makes a decimation
+ # rate of 26 and a samples per symbol of 2.136752
+ if_rate = 2.461538e6
+ self._usrp = usrp_source_c(which=0,
+ subdev_spec=options.rx_subdev_spec,
+ if_rate=if_rate,
+ gain=options.gain,
+ freq=options.freq,
+ calibration=options.calibration,
+ verbose=options.verbose)
+
+ # Filter baseband to 1.186 MHz passband, 1.728 MHz stopband
+ chan_taps = optfir.low_pass(1.0, # Gain
+ if_rate, # Sample rate
+ _dect_occupied_bandwidth/2, # One sided modulation bandwidth
+ _dect_channel_bandwidth/2, # One sided channel bandwidth
+ 1.0, # Passband ripple (db)
+ 60) # Stopband attenuation (db)
+ if self._options.verbose:
+ print "Channel filter has", len(chan_taps), "taps"
+ self._channel_filter = gr.freq_xlating_fir_filter_ccf(1, # Decimation rate
+ chan_taps, # Filter taps
+ 0.0, # Offset frequency
+ if_rate) # Sample rate
+
+ self._demod = blks2.gmsk_demod(samples_per_symbol=if_rate/_dect_symbol_rate,
+ verbose=options.verbose)
+
+ self._sink = gr.null_sink(gr.sizeof_char)
+ self.connect(self._usrp, self._channel_filter, self._demod, self._sink)
+
+ # Log baseband to file if requested
+ if options.log_baseband is not None:
+ if options.verbose:
+ print "Logging baseband to file", options.log_baseband
+ self.baseband_log = gr.file_sink(gr.sizeof_gr_complex, options.log_baseband)
+ self.connect(self._channel_filter, self.baseband_log)
+
+ # Log demodulator output to file if requested
+ if options.log_demod is not None:
+ if options.verbose:
+ print "Logging demodulator to file", options.log_demod
+ self.demod_log = gr.file_sink(gr.sizeof_char, options.log_demod)
+ self.connect(self._demod, self.demod_log)
--- /dev/null
+#!/usr/bin/env python
+#
+# Copyright 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.
+#
+
+from gnuradio import gr, eng_notation
+from gnuradio.eng_option import eng_option
+from optparse import OptionParser
+from dect_receiver import dect_receiver
+import sys
+
+def main():
+ parser = OptionParser(option_class=eng_option)
+ parser.add_option("-R", "--rx-subdev-spec", type="subdev", default=None,
+ help="select USRP Rx side A or B (default=first one with a daughterboard)")
+ parser.add_option("-f", "--freq", type="eng_float", default=None,
+ help="set frequency to FREQ", metavar="FREQ")
+ parser.add_option("", "--calibration", type="eng_float", default=0.0,
+ help="set frequency calibration offset to FREQ")
+ parser.add_option("-g", "--gain", type="eng_float", default=None,
+ help="set gain in dB (default is midpoint)")
+ parser.add_option("-v", "--verbose", action="store_true", default=False,
+ help="print extra debugging info")
+ parser.add_option("", "--log-baseband", default=None,
+ help="log filtered baseband to file")
+ parser.add_option("", "--log-demod", default=None,
+ help="log demodulator output to file")
+ (options, args) = parser.parse_args()
+
+ if len(sys.argv) == 1 or len(args) != 0:
+ parser.print_help()
+ sys.exit(1)
+
+ # Create an instance of a hierarchical block
+ top_block = dect_receiver(options)
+
+ try:
+ # Run forever
+ top_block.run()
+ except KeyboardInterrupt:
+ # Ctrl-C exits
+ pass
+
+if __name__ == '__main__':
+ main ()
--- /dev/null
+#!/usr/bin/env python
+#
+# Copyright 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.
+#
+
+from gnuradio import gr, usrp, eng_notation
+n2s = eng_notation.num_to_str
+
+# Hierarchical block implementing a USRP source for complex floats,
+# with convenience functions for gain, tune, decimation, etc.
+#
+class usrp_source_c(gr.hier_block2):
+ """
+ Create a USRP source object supplying complex floats.
+ """
+ def __init__(self, which=0, subdev_spec=None, gain=None, if_rate=None,
+ freq=0.0, calibration=0.0, verbose=False):
+ # Call hierarchical block constructor
+ gr.hier_block2.__init__(self,
+ "usrp_source_c", # Block typename
+ gr.io_signature(0,0,0), # Input signature
+ gr.io_signature(1,1,gr.sizeof_gr_complex)) # Output signature
+
+ self._verbose = verbose
+ self._u = usrp.source_c(which)
+ if self._verbose:
+ print 'ADC sample rate is', n2s(self._u.adc_rate()), "sps"
+ self.set_subdev(subdev_spec)
+ self.set_if_rate(if_rate)
+ self.set_gain(gain)
+ self.set_calibration(calibration)
+ self.tune(freq)
+ self.connect(self._u, self)
+
+ def set_subdev(self, subdev_spec):
+ if subdev_spec is None:
+ subdev_spec = self.pick_subdevice()
+ self._subdev = usrp.selected_subdev(self._u, subdev_spec)
+ self._u.set_mux(usrp.determine_rx_mux_value(self._u, subdev_spec))
+ if self._verbose:
+ print 'RX using', self._subdev.name(), 'daughterboard'
+
+ def pick_subdevice(self):
+ """
+ The user didn't specify a subdevice.
+ If there's a daughterboard on A, select A.
+ If there's a daughterboard on B, select B.
+ Otherwise, select A.
+ """
+ if self._u.db[0][0].dbid() >= 0: # dbid is < 0 if there's no d'board or a problem
+ return (0, 0)
+ if self._u.db[1][0].dbid() >= 0:
+ return (1, 0)
+ return (0, 0)
+
+ def set_if_rate(self, if_rate):
+ # If no IF rate specified, set to maximum decimation
+ if if_rate is None:
+ self._decim = 256
+ else:
+ self._decim = int(self._u.adc_rate()/if_rate)
+
+ self._u.set_decim_rate(self._decim)
+ self._if_rate = self._u.adc_rate()/self._decim
+
+ if self._verbose:
+ print "USRP decimation rate is", self._decim
+ print "USRP IF rate is", n2s(self._if_rate), "sps"
+
+ def set_gain(self, gain):
+ # If no gain specified, set to midrange
+ if gain is None:
+ g = self._subdev.gain_range()
+ gain = (g[0]+g[1])/2.0
+ self._gain = gain
+ self._subdev.set_gain(self._gain)
+
+ def set_calibration(self, calibration):
+ self._cal = calibration
+ if self._verbose:
+ print "Using frequency calibration offset of", n2s(calibration), "Hz"
+
+ def tune(self, freq):
+ """
+ Set the center frequency we're interested in.
+
+ @param target_freq: frequency in Hz
+ @type: bool
+
+ Tuning is a two step process. First we ask the front-end to
+ tune as close to the desired frequency as it can. Then we use
+ the result of that operation and our target_frequency to
+ determine the value for the digital down converter.
+ """
+ self._tune_result = usrp.tune(self._u, 0, self._subdev, freq+self._cal)
+ if self._tune_result:
+ if self._verbose:
+ print "Baseband frequency is", n2s(self._tune_result.baseband_freq), "Hz"
+ print "DXC frequency is", n2s(self._tune_result.dxc_freq), "Hz"
+ print "Center frequency is", n2s(freq), "Hz"
+ print "Residual frequency is", n2s(self._tune_result.residual_freq), "Hz"
+ return True
+
+ return False
+
+if __name__ == '__main__':
+ src = usrp_source_c(verbose=True)
EXTRA_DIST = \
README \
+ benchmark_loopback.py \
benchmark_rx.py \
benchmark_tx.py \
fusb_options.py \
gen_whitener.py \
pick_bitrate.py \
receive_path.py \
+ receive_path_lb.py \
rx_voice.py \
run_length.py \
transmit_path.py \
+ transmit_path_lb.py \
tunnel.py \
tx_voice.py
ourdatadir = $(exampledir)/digital
ourdata_DATA = $(EXTRA_DIST)
+
+MOSTLYCLEANFILES = *.pyc *.pyo *~
from receive_path_lb import receive_path
import fusb_options
-class awgn_channel(gr.hier_block):
- def __init__(self, fg, sample_rate, noise_voltage, frequency_offset, seed=False):
- self.input = gr.add_const_cc(0) # dummy input device
-
+class awgn_channel(gr.hier_block2):
+ def __init__(self, sample_rate, noise_voltage, frequency_offset, seed=False):
+
+ gr.hier_block2.__init__(self, "awgn_channel",
+ gr.io_signature(1, 1, gr.sizeof_gr_complex), # Input signature
+ gr.io_signature(1, 1, gr.sizeof_gr_complex)) # Output signature
+
# Create the Gaussian noise source
if not seed:
self.noise = gr.noise_source_c(gr.GR_GAUSSIAN, noise_voltage)
self.mixer = gr.multiply_cc()
# Connect the components
- fg.connect(self.input, (self.mixer, 0))
- fg.connect(self.offset, (self.mixer, 1))
- fg.connect(self.mixer, (self.adder, 0))
- fg.connect(self.noise, (self.adder, 1))
-
- gr.hier_block.__init__(self, fg, self.input, self.adder)
+ self.connect(self, (self.mixer, 0))
+ self.connect(self.offset, (self.mixer, 1))
+ self.connect(self.mixer, (self.adder, 0))
+ self.connect(self.noise, (self.adder, 1))
+ self.connect(self.adder, self)
-class my_graph(gr.flow_graph):
+class my_top_block(gr.top_block):
def __init__(self, mod_class, demod_class, rx_callback, options):
- gr.flow_graph.__init__(self)
+ gr.top_block.__init__(self)
channelon = True;
noise_power = power_in_signal/SNR
noise_voltage = math.sqrt(noise_power)
- self.txpath = transmit_path(self, mod_class, options)
+ self.txpath = transmit_path(mod_class, options)
self.throttle = gr.throttle(gr.sizeof_gr_complex, options.sample_rate)
- self.rxpath = receive_path(self, demod_class, rx_callback, options)
+ self.rxpath = receive_path(demod_class, rx_callback, options)
if channelon:
- self.channel = awgn_channel(self, options.sample_rate, noise_voltage,
+ self.channel = awgn_channel(options.sample_rate, noise_voltage,
frequency_offset, options.seed)
if options.discontinuous:
# print payload[2:len(payload)]
def send_pkt(payload='', eof=False):
- return fg.txpath.send_pkt(payload, eof)
+ return tb.txpath.send_pkt(payload, eof)
mods = modulation_utils.type_1_mods()
print "Warning: failed to enable realtime scheduling"
# Create an instance of a hierarchical block
- fg = my_graph(mods[options.modulation], demods[options.modulation], rx_callback, options)
- fg.start()
+ tb = my_top_block(mods[options.modulation], demods[options.modulation], rx_callback, options)
+ tb.start()
# generate and send packets
nbytes = int(1e6 * options.megabytes)
send_pkt(eof=True)
- fg.wait()
+ tb.wait()
if __name__ == '__main__':
try:
#!/usr/bin/env python
#
-# Copyright 2005,2006 Free Software Foundation, Inc.
+# Copyright 2005,2006,2007 Free Software Foundation, Inc.
#
# This file is part of GNU Radio
#
#print os.getpid()
#raw_input('Attach and press enter: ')
-
-class my_graph(gr.flow_graph):
-
- def __init__(self, demod_class, rx_callback, options):
- gr.flow_graph.__init__(self)
- self.rxpath = receive_path(self, demod_class, rx_callback, options)
+class my_top_block(gr.top_block):
+ def __init__(self, demodulator, rx_callback, options):
+ gr.top_block.__init__(self)
+ self.rxpath = receive_path(demodulator, rx_callback, options)
+ self.connect(self.rxpath)
# /////////////////////////////////////////////////////////////////////////////
# main
# build the graph
- fg = my_graph(demods[options.modulation], rx_callback, options)
+ 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."
- fg.start() # start flow graph
- fg.wait() # wait for it to finish
+ tb.start() # start flow graph
+ tb.wait() # wait for it to finish
if __name__ == '__main__':
try:
#!/usr/bin/env python
#
-# Copyright 2005, 2006 Free Software Foundation, Inc.
+# Copyright 2005, 2006, 2007 Free Software Foundation, Inc.
#
# This file is part of GNU Radio
#
#print os.getpid()
#raw_input('Attach and press enter')
-
-class my_graph(gr.flow_graph):
- def __init__(self, modulator_class, options):
- gr.flow_graph.__init__(self)
- self.txpath = transmit_path(self, modulator_class, options)
-
+class my_top_block(gr.top_block):
+ def __init__(self, modulator, options):
+ gr.top_block.__init__(self)
+ self.txpath = transmit_path(modulator, options)
+ self.connect(self.txpath)
# /////////////////////////////////////////////////////////////////////////////
# main
def main():
def send_pkt(payload='', eof=False):
- return fg.txpath.send_pkt(payload, eof)
+ return tb.txpath.send_pkt(payload, eof)
def rx_callback(ok, payload):
print "ok = %r, payload = '%s'" % (ok, payload)
source_file = open(options.from_file, 'r')
# build the graph
- fg = my_graph(mods[options.modulation], options)
+ 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"
- fg.start() # start flow graph
-
+ tb.start() # start flow graph
+
# generate and send packets
nbytes = int(1e6 * options.megabytes)
n = 0
pktno += 1
send_pkt(eof=True)
- fg.wait() # wait for it to finish
+
+ tb.wait() # wait for it to finish
if __name__ == '__main__':
try:
#!/usr/bin/env python
#
-# Copyright 2005,2006 Free Software Foundation, Inc.
+# Copyright 2005,2006,2007 Free Software Foundation, Inc.
#
# This file is part of GNU Radio
#
# Boston, MA 02110-1301, USA.
#
-from gnuradio import gr, gru, blks
+from gnuradio import gr, gru, blks2
from gnuradio import usrp
from gnuradio import eng_notation
import copy
# receive path
# /////////////////////////////////////////////////////////////////////////////
-class receive_path(gr.hier_block):
- def __init__(self, fg, demod_class, rx_callback, options):
+class receive_path(gr.hier_block2):
+ def __init__(self, demod_class, rx_callback, options):
+
+ gr.hier_block2.__init__(self, "receive_path",
+ gr.io_signature(0, 0, 0), # Input signature
+ gr.io_signature(0, 0, 0)) # Output signature
options = copy.copy(options) # make a copy so we can destructively modify
# receiver
self.packet_receiver = \
- blks.demod_pkts(fg,
- self._demod_class(fg, **demod_kwargs),
- access_code=None,
- callback=self._rx_callback,
- threshold=-1)
+ blks2.demod_pkts(self._demod_class(**demod_kwargs),
+ access_code=None,
+ callback=self._rx_callback,
+ threshold=-1)
# Carrier Sensing Blocks
alpha = 0.001
if options.log_rx_power == True:
self.probe = gr.probe_avg_mag_sqrd_cf(thresh,alpha)
self.power_sink = gr.file_sink(gr.sizeof_float, "rxpower.dat")
- fg.connect(self.chan_filt, self.probe, self.power_sink)
+ self.connect(self.chan_filt, self.probe, self.power_sink)
else:
self.probe = gr.probe_avg_mag_sqrd_c(thresh,alpha)
- fg.connect(self.chan_filt, self.probe)
+ self.connect(self.chan_filt, self.probe)
# Display some information about the setup
if self._verbose:
self._print_verbage()
- fg.connect(self.u, self.chan_filt, self.packet_receiver)
- gr.hier_block.__init__(self, fg, None, None)
+ self.connect(self.u, self.chan_filt, self.packet_receiver)
def _setup_usrp_source(self):
self.u = usrp.source_c (fusb_block_size=self._fusb_block_size,
print "decim: %3d" % (self._decim)
print "Rx Frequency: %s" % (eng_notation.num_to_str(self._rx_freq))
# print "Rx Frequency: %f" % (self._rx_freq)
+
+ def __del__(self):
+ # Avoid weak reference error
+ del self.subdev
def add_freq_option(parser):
"""
#!/usr/bin/env python
#
-# Copyright 2005,2006 Free Software Foundation, Inc.
+# Copyright 2005,2006,2007 Free Software Foundation, Inc.
#
# This file is part of GNU Radio
#
# Boston, MA 02110-1301, USA.
#
-from gnuradio import gr, gru, blks
+from gnuradio import gr, gru, blks2
from gnuradio import eng_notation
import copy
import sys
# receive path
# /////////////////////////////////////////////////////////////////////////////
-class receive_path(gr.hier_block):
- def __init__(self, fg, demod_class, rx_callback, options):
+class receive_path(gr.hier_block2):
+ def __init__(self, demod_class, rx_callback, options):
+ gr.hier_block2.__init__(self, "receive_path",
+ gr.io_signature(1, 1, gr.sizeof_gr_complex), # Input signature
+ gr.io_signature(0, 0, 0)) # Output signature
+
options = copy.copy(options) # make a copy so we can destructively modify
# receiver
self.packet_receiver = \
- blks.demod_pkts(fg,
- self._demod_class(fg, **demod_kwargs),
- access_code=None,
- callback=self._rx_callback,
- threshold=-1)
+ blks2.demod_pkts(self._demod_class(**demod_kwargs),
+ access_code=None,
+ callback=self._rx_callback,
+ threshold=-1)
# Carrier Sensing Blocks
alpha = 0.001
if self._verbose:
self._print_verbage()
+ # connect block input to channel filter
+ self.connect(self, self.channel_filter)
+
# connect the channel input filter to the carrier power detector
- fg.connect(self.channel_filter, self.probe)
+ self.connect(self.channel_filter, self.probe)
# connect channel filter to the packet receiver
- fg.connect(self.channel_filter, self.packet_receiver)
-
- gr.hier_block.__init__(self, fg, self.channel_filter, None)
+ self.connect(self.channel_filter, self.packet_receiver)
def bitrate(self):
return self._bitrate
import random
import struct
+import sys
# from current dir
from receive_path import receive_path
#raw_input('Attach and press enter')
-class audio_tx(gr.hier_block):
- def __init__(self, fg, audio_output_dev):
+class audio_tx(gr.hier_block2):
+ def __init__(self, audio_output_dev):
+ gr.hier_block2.__init__(self, "audio_tx",
+ gr.io_signature(0, 0, 0), # Input signature
+ gr.io_signature(0, 0, 0)) # Output signature
+
self.packet_src = gr.message_source(33)
voice_decoder = gsm_full_rate.decode_ps()
s2f = gr.short_to_float ()
sink_scale = gr.multiply_const_ff(1.0/32767.)
audio_sink = audio.sink(8000, audio_output_dev)
- fg.connect(self.packet_src, voice_decoder, s2f, sink_scale, audio_sink)
- gr.hier_block.__init__(self, fg, self.packet_src, audio_sink)
+ self.connect(self.packet_src, voice_decoder, s2f, sink_scale, audio_sink)
def msgq(self):
return self.packet_src.msgq()
-class my_graph(gr.flow_graph):
-
+class my_top_block(gr.top_block):
def __init__(self, demod_class, rx_callback, options):
- gr.flow_graph.__init__(self)
- self.rxpath = receive_path(self, demod_class, rx_callback, options)
- self.audio_tx = audio_tx(self, options.audio_output)
-
+ gr.top_block.__init__(self)
+ self.rxpath = receive_path(demod_class, rx_callback, options)
+ self.audio_tx = audio_tx(options.audio_output)
+ self.connect(self.rxpath)
+ self.connect(self.audio_tx)
# /////////////////////////////////////////////////////////////////////////////
# main
# build the graph
- fg = my_graph(demods[options.modulation], rx_callback, options)
+ 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."
- fg.start() # start flow graph
- fg.wait() # wait for it to finish
+ tb.run()
if __name__ == '__main__':
try:
#
-# Copyright 2005,2006 Free Software Foundation, Inc.
+# Copyright 2005,2006,2007 Free Software Foundation, Inc.
#
# This file is part of GNU Radio
#
# Boston, MA 02110-1301, USA.
#
-from gnuradio import gr, gru, blks
+from gnuradio import gr, gru, blks2
from gnuradio import usrp
from gnuradio import eng_notation
# transmit path
# /////////////////////////////////////////////////////////////////////////////
-class transmit_path(gr.hier_block):
- def __init__(self, fg, modulator_class, options):
+class transmit_path(gr.hier_block2):
+ def __init__(self, modulator_class, options):
'''
See below for what options should hold
'''
+ gr.hier_block2.__init__(self, "transmit_path",
+ gr.io_signature(0, 0, 0), # Input signature
+ gr.io_signature(0, 0, 0)) # Output signature
options = copy.copy(options) # make a copy so we can destructively modify
# transmitter
self.packet_transmitter = \
- blks.mod_pkts(fg,
- self._modulator_class(fg, **mod_kwargs),
- access_code=None,
- msgq_limit=4,
- pad_for_usrp=True,
- use_whitener_offset=options.use_whitener_offset)
+ blks2.mod_pkts(self._modulator_class(**mod_kwargs),
+ access_code=None,
+ msgq_limit=4,
+ pad_for_usrp=True,
+ use_whitener_offset=options.use_whitener_offset)
# Set the USRP for maximum transmit gain
self._print_verbage()
# Create and setup transmit path flow graph
- fg.connect(self.packet_transmitter, self.amp, self.u)
- gr.hier_block.__init__(self, fg, None, None)
+ self.connect(self.packet_transmitter, self.amp, self.u)
def _setup_usrp_sink(self):
"""
#
-# Copyright 2005,2006 Free Software Foundation, Inc.
+# Copyright 2005, 2006, 2007 Free Software Foundation, Inc.
#
# This file is part of GNU Radio
#
# Boston, MA 02110-1301, USA.
#
-from gnuradio import gr, gru, blks
+from gnuradio import gr, gru, blks2
from gnuradio import eng_notation
import copy
# transmit path
# /////////////////////////////////////////////////////////////////////////////
-class transmit_path(gr.hier_block):
- def __init__(self, fg, modulator_class, options):
+class transmit_path(gr.hier_block2):
+ def __init__(self, modulator_class, options):
'''
See below for what options should hold
'''
+ gr.hier_block2.__init__(self, "transmit_path",
+ gr.io_signature(0, 0, 0), # Input signature
+ gr.io_signature(1, 1, gr.sizeof_gr_complex)) # Output signature
options = copy.copy(options) # make a copy so we can destructively modify
mod_kwargs = self._modulator_class.extract_kwargs_from_options(options)
# transmitter
+ print self._modulator_class
+ print mod_kwargs
+ modulator = self._modulator_class(**mod_kwargs)
self.packet_transmitter = \
- blks.mod_pkts(fg,
- self._modulator_class(fg, **mod_kwargs),
- access_code=None,
- msgq_limit=4,
- pad_for_usrp=True)
+ blks2.mod_pkts(modulator,
+ access_code=None,
+ msgq_limit=4,
+ pad_for_usrp=True)
self.amp = gr.multiply_const_cc(1)
self.set_tx_amplitude(self._tx_amplitude)
self._print_verbage()
# Connect components in the flowgraph
- fg.connect(self.packet_transmitter, self.amp)
-
- gr.hier_block.__init__(self, fg, None, self.amp)
+ self.connect(self.packet_transmitter, self.amp, self)
def set_tx_amplitude(self, ampl):
"""
# the flow graph
# /////////////////////////////////////////////////////////////////////////////
-class my_graph(gr.flow_graph):
+class my_top_block(gr.top_block):
def __init__(self, mod_class, demod_class,
rx_callback, options):
- gr.flow_graph.__init__(self)
- self.txpath = transmit_path(self, mod_class, options)
- self.rxpath = receive_path(self, demod_class, rx_callback, options)
+ gr.top_block.__init__(self)
+ self.txpath = transmit_path(mod_class, options)
+ self.rxpath = receive_path(demod_class, rx_callback, options)
def send_pkt(self, payload='', eof=False):
return self.txpath.send_pkt(payload, eof)
def __init__(self, tun_fd, verbose=False):
self.tun_fd = tun_fd # file descriptor for TUN/TAP interface
self.verbose = verbose
- self.fg = None # flow graph (access to PHY)
+ self.tb = None # top block (access to PHY)
- def set_flow_graph(self, fg):
- self.fg = fg
+ def set_top_block(self, tb):
+ self.tb = tb
def phy_rx_callback(self, ok, payload):
"""
while 1:
payload = os.read(self.tun_fd, 10*1024)
if not payload:
- self.fg.send_pkt(eof=True)
+ self.tb.send_pkt(eof=True)
break
if self.verbose:
print "Tx: len(payload) = %4d" % (len(payload),)
delay = min_delay
- while self.fg.carrier_sensed():
+ while self.tb.carrier_sensed():
sys.stderr.write('B')
time.sleep(delay)
if delay < 0.050:
delay = delay * 2 # exponential back-off
- self.fg.send_pkt(payload)
+ self.tb.send_pkt(payload)
# /////////////////////////////////////////////////////////////////////////////
# build the graph (PHY)
- fg = my_graph(mods[options.modulation],
- demods[options.modulation],
- mac.phy_rx_callback,
- options)
+ tb = my_top_block(mods[options.modulation],
+ demods[options.modulation],
+ mac.phy_rx_callback,
+ options)
- mac.set_flow_graph(fg) # give the MAC a handle for the PHY
+ mac.set_top_block(tb) # give the MAC a handle for the PHY
- if fg.txpath.bitrate() != fg.rxpath.bitrate():
+ if tb.txpath.bitrate() != tb.rxpath.bitrate():
print "WARNING: Transmit bitrate = %sb/sec, Receive bitrate = %sb/sec" % (
- eng_notation.num_to_str(fg.txpath.bitrate()),
- eng_notation.num_to_str(fg.rxpath.bitrate()))
+ eng_notation.num_to_str(tb.txpath.bitrate()),
+ eng_notation.num_to_str(tb.rxpath.bitrate()))
print "modulation: %s" % (options.modulation,)
print "freq: %s" % (eng_notation.num_to_str(options.tx_freq))
- print "bitrate: %sb/sec" % (eng_notation.num_to_str(fg.txpath.bitrate()),)
- print "samples/symbol: %3d" % (fg.txpath.samples_per_symbol(),)
- #print "interp: %3d" % (fg.txpath.interp(),)
- #print "decim: %3d" % (fg.rxpath.decim(),)
+ print "bitrate: %sb/sec" % (eng_notation.num_to_str(tb.txpath.bitrate()),)
+ print "samples/symbol: %3d" % (tb.txpath.samples_per_symbol(),)
+ #print "interp: %3d" % (tb.txpath.interp(),)
+ #print "decim: %3d" % (tb.rxpath.decim(),)
- fg.rxpath.set_carrier_threshold(options.carrier_threshold)
+ tb.rxpath.set_carrier_threshold(options.carrier_threshold)
print "Carrier sense threshold:", options.carrier_threshold, "dB"
print
print
- fg.start() # Start executing the flow graph (runs in separate threads)
+ tb.start() # Start executing the flow graph (runs in separate threads)
mac.main_loop() # don't expect this to return...
- fg.stop() # but if it does, tell flow graph to stop.
- fg.wait() # wait for it to finish
+ tb.stop() # but if it does, tell flow graph to stop.
+ tb.wait() # wait for it to finish
if __name__ == '__main__':
#!/usr/bin/env python
#
-# Copyright 2005,2006 Free Software Foundation, Inc.
+# Copyright 2005,2006,2007 Free Software Foundation, Inc.
#
# This file is part of GNU Radio
#
#raw_input('Attach and press enter')
-class audio_rx(gr.hier_block):
- def __init__(self, fg, audio_input_dev):
+class audio_rx(gr.hier_block2):
+ def __init__(self, audio_input_dev):
+ gr.hier_block2.__init__(self, "audio_rx",
+ gr.io_signature(0, 0, 0), # Input signature
+ gr.io_signature(0, 0, 0)) # Output signature
sample_rate = 8000
src = audio.source(sample_rate, audio_input_dev)
src_scale = gr.multiply_const_ff(32767)
voice_coder = gsm_full_rate.encode_sp()
self.packets_from_encoder = gr.msg_queue()
packet_sink = gr.message_sink(33, self.packets_from_encoder, False)
- fg.connect(src, src_scale, f2s, voice_coder, packet_sink)
- gr.hier_block.__init__(self, fg, src, packet_sink)
+ self.connect(src, src_scale, f2s, voice_coder, packet_sink)
def get_encoded_voice_packet(self):
return self.packets_from_encoder.delete_head()
-class my_graph(gr.flow_graph):
+class my_top_block(gr.top_block):
def __init__(self, modulator_class, options):
- gr.flow_graph.__init__(self)
- self.txpath = transmit_path(self, modulator_class, options)
- self.audio_rx = audio_rx(self, options.audio_input)
-
+ gr.top_block.__init__(self)
+ self.txpath = transmit_path(modulator_class, options)
+ self.audio_rx = audio_rx(options.audio_input)
+ self.connect(self.txpath)
+ self.connect(self.audio_rx)
# /////////////////////////////////////////////////////////////////////////////
def main():
def send_pkt(payload='', eof=False):
- return fg.txpath.send_pkt(payload, eof)
+ return tb.txpath.send_pkt(payload, eof)
def rx_callback(ok, payload):
print "ok = %r, payload = '%s'" % (ok, payload)
# build the graph
- fg = my_graph(mods[options.modulation], options)
+ 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"
- fg.start() # start flow graph
+ tb.start() # start flow graph
# generate and send packets
nbytes = int(1e6 * options.megabytes)
pktno = 0
while nbytes == 0 or n < nbytes:
- packet = fg.audio_rx.get_encoded_voice_packet()
+ packet = tb.audio_rx.get_encoded_voice_packet()
s = packet.to_string()
send_pkt(s)
n += len(s)
pktno += 1
send_pkt(eof=True)
- fg.wait() # wait for it to finish
- fg.txpath.set_auto_tr(False)
+ tb.wait() # wait for it to finish
+ tb.txpath.set_auto_tr(False)
if __name__ == '__main__':
try:
main()
except KeyboardInterrupt:
- pass
+ pass
\ No newline at end of file
# Boston, MA 02110-1301, USA.
#
-from gnuradio import gr, blks
+from gnuradio import gr, blks2
from gnuradio import audio
from gnuradio.eng_option import eng_option
from optparse import OptionParser
parser.print_help()
raise SystemExit, 1
- fg = gr.flow_graph()
+ tb = gr.top_block()
src = audio.source(int(options.sample_rate), options.audio_input)
- tx = blks.cvsd_encode(fg, options.resample_rate)
+ tx = blks2.cvsd_encode(options.resample_rate)
# todo: add noise
- rx = blks.cvsd_decode(fg, options.resample_rate)
+ rx = blks2.cvsd_decode(options.resample_rate)
dst = audio.sink(int(options.sample_rate), options.audio_output)
- fg.connect(src, tx, rx, dst)
+ tb.connect(src, tx, rx, dst)
+ tb.run()
- fg.start()
-
- raw_input ('Press Enter to exit: ')
- fg.stop()
-
-
if __name__ == '__main__':
+ print "Enter CTRL-C to exit"
try:
main()
except KeyboardInterrupt:
# Boston, MA 02110-1301, USA.
#
-from gnuradio import gr, blks
+from gnuradio import gr, blks2
from gnuradio import audio
from gnuradio.eng_option import eng_option
from optparse import OptionParser
-class my_graph(gr.flow_graph):
+class my_top_block(gr.top_block):
def __init__(self):
- gr.flow_graph.__init__(self)
+ gr.top_block.__init__(self)
parser = OptionParser(option_class=eng_option)
parser.add_option("-I", "--audio-input", type="string", default="",
sample_rate = 8000
src = audio.source(sample_rate, options.audio_input)
- tx = blks.digital_voice_tx(self)
+ tx = blks2.digital_voice_tx(self)
if_gain = gr.multiply_const_cc(10000)
# channel simulator here...
- rx = blks.digital_voice_rx(self)
+ rx = blks2.digital_voice_rx(self)
dst = audio.sink(sample_rate, options.audio_output)
self.connect(src, tx, if_gain, rx, dst)
if __name__ == '__main__':
try:
- my_graph().run()
+ my_top_block().run()
except KeyboardInterrupt:
pass
+++ /dev/null
-#
-# Copyright 2006 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.
-#
-
-SUBDIRS = \
- audio \
- dect \
- digital \
- ofdm \
- networking \
- sounder \
- usrp
+++ /dev/null
-#
-# Copyright 2006 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.
-#
-
-EXTRA_DIST = \
- dial_tone2.py
+++ /dev/null
-#!/usr/bin/env python
-#
-# Copyright 2004,2005,2006 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 audio
-from gnuradio.eng_option import eng_option
-from optparse import OptionParser
-
-# Top-level block creating a dial tone
-# Derives from new class gr.hier_block2
-class dial_tone(gr.top_block):
- def __init__(self,
- sample_rate, # Audio output sample rate (int)
- audio_output, # Audio output device
- amplitude): # Output volume (0.0-1.0)
-
- gr.top_block.__init__(self, "dial_tone")
-
- src0 = gr.sig_source_f(sample_rate, gr.GR_SIN_WAVE, 350, amplitude)
- src1 = gr.sig_source_f(sample_rate, gr.GR_SIN_WAVE, 440, amplitude)
- dst = audio.sink(sample_rate, audio_output)
-
- self.connect(src0, (dst, 0))
- self.connect(src1, (dst, 1))
-
-if __name__ == '__main__':
- parser = OptionParser(option_class=eng_option)
- parser.add_option("-O", "--audio-output", type="string", default="",
- help="pcm output device name. E.g., hw:0,0 or /dev/dsp")
- parser.add_option("-r", "--sample-rate", type="eng_float", default=48000,
- help="set sample rate to RATE (48000)")
- parser.add_option("-a", "--amplitude", type="eng_float", default=0.1,
- help="set output volume to AMPLITUDE (0.1)")
- (options, args) = parser.parse_args()
- if len(args) != 0:
- parser.print_help()
- raise SystemExit, 1
-
- # Create an instance of a hierarchical block
- top = dial_tone(int(options.sample_rate),
- options.audio_output,
- options.amplitude)
-
- try:
- # Run forever
- top.run()
- except KeyboardInterrupt:
- # Ctrl-C exits
- pass
+++ /dev/null
-#
-# Copyright 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.
-#
-
-EXTRA_DIST = \
- README \
- dect_receiver.py \
- usrp_source.py \
- usrp_dect.py
-
-MOSTLYCLEANFILES = *.pyc *~
+++ /dev/null
-This directory contains a work in progress service monitor for DECT
-digital cordless phone base stations and handsets.
-
-
-Status
-------
-
-2007 Apr 27 - Converted to new hier_block2 format
-2007 Apr 03 - Development on hold.
-2007 Feb 11 - Added GMSK demodulation and option to log to file
-2007 Feb 10 - Able to tune and log filtered baseband to file
-
-
-Files
------
-
-usrp_dect.py - DECT receiver application
-
-dect_receiver.py - Top-level hierarchical block (new type) implementing
- receiver
-
-usrp_source.py - Hierarchical block (new type) implementing a USRP
- complex source, with convenience functions for tuning,
- gain, decimation, etc.
-
-gmsk2.py - Hierarchical block (new type) implementing GMSK
- modulation and demodulation. This will eventually go
- into the core blksimpl directory
-
-DECT Modulation Details
------------------------
-
-In the US, the FCC has allocated four carrier frequencies for DECT usage:
-
-Channel Frequency
-------- ---------
- 1 1921.536 MHz
- 2 1923.264 MHz
- 3 1924.992 MHz
- 4 1926.720 MHz
-
-These are spaced at 1.728 MHz intervals.
-
-The DECT PHY uses GMSK with a 0.5 bandwidth-time product at 1.152 Msym/sec,
-for an occupied bandwidth (99% power) of 1.186 MHz (1.03 x symbol rate.)
-
+++ /dev/null
-#!/usr/bin/env python
-#
-# Copyright 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.
-#
-
-from gnuradio import gr, optfir
-from usrp_source import usrp_source_c
-from gmsk2 import gmsk2_demod
-
-_dect_symbol_rate = 1.152e6
-_dect_occupied_bandwidth = _dect_symbol_rate * 1.03 # BT=0.5
-_dect_channel_bandwidth = 1.728e6
-
-# Top-level hierarchical block that implements DECT demodulation and
-# decoding.
-class dect_receiver(gr.top_block):
- def __init__(self, options):
- gr.top_block.__init__(self, "dect_receiver")
- self._options = options
-
- # Need greater than 2 samples per symbol. This makes a decimation
- # rate of 26 and a samples per symbol of 2.136752
- if_rate = 2.461538e6
- self._usrp = usrp_source_c(which=0,
- subdev_spec=options.rx_subdev_spec,
- if_rate=if_rate,
- gain=options.gain,
- freq=options.freq,
- calibration=options.calibration,
- verbose=options.verbose)
-
- # Filter baseband to 1.186 MHz passband, 1.728 MHz stopband
- chan_taps = optfir.low_pass(1.0, # Gain
- if_rate, # Sample rate
- _dect_occupied_bandwidth/2, # One sided modulation bandwidth
- _dect_channel_bandwidth/2, # One sided channel bandwidth
- 1.0, # Passband ripple (db)
- 60) # Stopband attenuation (db)
- if self._options.verbose:
- print "Channel filter has", len(chan_taps), "taps"
- self._channel_filter = gr.freq_xlating_fir_filter_ccf(1, # Decimation rate
- chan_taps, # Filter taps
- 0.0, # Offset frequency
- if_rate) # Sample rate
-
- self._demod = gmsk2_demod(samples_per_symbol=if_rate/_dect_symbol_rate,
- verbose=options.verbose)
-
- self._sink = gr.null_sink(gr.sizeof_char)
- self.connect(self._usrp, self._channel_filter, self._demod, self._sink)
-
- # Log baseband to file if requested
- if options.log_baseband is not None:
- if options.verbose:
- print "Logging baseband to file", options.log_baseband
- self.baseband_log = gr.file_sink(gr.sizeof_gr_complex, options.log_baseband)
- self.connect(self._channel_filter, self.baseband_log)
-
- # Log demodulator output to file if requested
- if options.log_demod is not None:
- if options.verbose:
- print "Logging demodulator to file", options.log_demod
- self.demod_log = gr.file_sink(gr.sizeof_char, options.log_demod)
- self.connect(self._demod, self.demod_log)
+++ /dev/null
-#
-# GMSK modulation and demodulation.
-#
-#
-# 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
-
-from gnuradio import gr
-from gnuradio import modulation_utils
-from math import pi
-import numpy
-from pprint import pprint
-import inspect
-
-# default values (used in __init__ and add_options)
-_def_samples_per_symbol = 2
-_def_bt = 0.35
-_def_verbose = False
-_def_log = False
-
-_def_gain_mu = 0.05
-_def_mu = 0.5
-_def_freq_error = 0.0
-_def_omega_relative_limit = 0.005
-
-
-# /////////////////////////////////////////////////////////////////////////////
-# GMSK modulator
-# /////////////////////////////////////////////////////////////////////////////
-
-class gmsk2_mod(gr.hier_block2):
-
- def __init__(self,
- samples_per_symbol=_def_samples_per_symbol,
- bt=_def_bt,
- verbose=_def_verbose,
- log=_def_log):
- """
- Hierarchical block for Gaussian Minimum Shift Key (GMSK)
- 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 bt: Gaussian filter bandwidth * symbol time
- @type bt: float
- @param verbose: Print information about modulator?
- @type verbose: bool
- @param debug: Print modualtion data to files?
- @type debug: bool
- """
- gr.hier_block2.__init__(self,
- "gmsk2_mod", # Block typename
- 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._bt = bt
-
- if not isinstance(samples_per_symbol, int) or samples_per_symbol < 2:
- raise TypeError, ("samples_per_symbol must be an integer >= 2, is %r" % (samples_per_symbol,))
-
- ntaps = 4 * samples_per_symbol # up to 3 bits in filter at once
- sensitivity = (pi / 2) / samples_per_symbol # phase change per bit = pi / 2
-
- # Turn it into NRZ data.
- self.nrz = gr.bytes_to_syms()
-
- # Form Gaussian filter
- # Generate Gaussian response (Needs to be convolved with window below).
- self.gaussian_taps = gr.firdes.gaussian(
- 1, # gain
- samples_per_symbol, # symbol_rate
- bt, # bandwidth * symbol time
- ntaps # number of taps
- )
-
- self.sqwave = (1,) * samples_per_symbol # rectangular window
- self.taps = numpy.convolve(numpy.array(self.gaussian_taps),numpy.array(self.sqwave))
- self.gaussian_filter = gr.interp_fir_filter_fff(samples_per_symbol, self.taps)
-
- # FM modulation
- self.fmmod = gr.frequency_modulator_fc(sensitivity)
-
- if verbose:
- self._print_verbage()
-
- self.connect(self, self.nrz, self.gaussian_filter, self.fmmod, self)
-
- if log:
- self._setup_logging()
-
- 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.
-
- def _print_verbage(self):
- print "bits per symbol = %d" % self.bits_per_symbol()
- print "Gaussian filter bt = %.2f" % self._bt
-
-
- def _setup_logging(self):
- print "Modulation logging turned on."
- self.connect(self.nrz, gr.file_sink(gr.sizeof_float, "nrz.dat"))
- self.connect(self.gaussian_filter, gr.file_sink(gr.sizeof_float, "gaussian_filter.dat"))
- self.connect(self.fmmod, gr.file_sink(gr.sizeof_gr_complex, "fmmod.dat"))
-
- def add_options(parser):
- """
- Adds GMSK modulation-specific options to the standard parser
- """
- parser.add_option("", "--bt", type="float", default=_def_bt,
- help="set bandwidth-time product [default=%default] (GMSK)")
- add_options=staticmethod(add_options)
-
- # FIXME: figure out what has to change for gr.hier_block2 version
- #def extract_kwargs_from_options(options):
- # """
- # Given command line options, create dictionary suitable for passing to __init__
- # """
- # return modulation_utils.extract_kwargs_from_options(gmsk_mod.__init__,
- # ('self', 'fg'), options)
- #extract_kwargs_from_options=staticmethod(extract_kwargs_from_options)
-
-
-# /////////////////////////////////////////////////////////////////////////////
-# GMSK demodulator
-# /////////////////////////////////////////////////////////////////////////////
-
-class gmsk2_demod(gr.hier_block2):
-
- def __init__(self,
- samples_per_symbol=_def_samples_per_symbol,
- gain_mu=_def_gain_mu,
- mu=_def_mu,
- omega_relative_limit=_def_omega_relative_limit,
- freq_error=_def_freq_error,
- verbose=_def_verbose,
- log=_def_log):
- """
- Hierarchical block for Gaussian Minimum Shift Key (GMSK)
- demodulation.
-
- The input is the complex modulated signal at baseband.
- The output is a stream of bits packed 1 bit per byte (the LSB)
-
- @param samples_per_symbol: samples per baud
- @type samples_per_symbol: integer
- @param verbose: Print information about modulator?
- @type verbose: bool
- @param log: Print modualtion data to files?
- @type log: bool
-
- Clock recovery parameters. These all have reasonble defaults.
-
- @param gain_mu: controls rate of mu adjustment
- @type gain_mu: float
- @param mu: fractional delay [0.0, 1.0]
- @type mu: float
- @param omega_relative_limit: sets max variation in omega
- @type omega_relative_limit: float, typically 0.000200 (200 ppm)
- @param freq_error: bit rate error as a fraction
- @param float
- """
-
- gr.hier_block2.__init__(self,
- "gmsk2_demod", # Block typename
- 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._gain_mu = gain_mu
- self._mu = mu
- self._omega_relative_limit = omega_relative_limit
- self._freq_error = freq_error
-
- if samples_per_symbol < 2:
- raise TypeError, "samples_per_symbol >= 2, is %f" % samples_per_symbol
-
- self._omega = samples_per_symbol*(1+self._freq_error)
-
- self._gain_omega = .25 * self._gain_mu * self._gain_mu # critically damped
-
- # Demodulate FM
- sensitivity = (pi / 2) / samples_per_symbol
- self.fmdemod = gr.quadrature_demod_cf(1.0 / sensitivity)
-
- # the clock recovery block tracks the symbol clock and resamples as needed.
- # the output of the block is a stream of soft symbols (float)
- self.clock_recovery = gr.clock_recovery_mm_ff(self._omega, self._gain_omega,
- self._mu, self._gain_mu,
- self._omega_relative_limit)
-
- # slice the floats at 0, outputting 1 bit (the LSB of the output byte) per sample
- self.slicer = gr.binary_slicer_fb()
-
- if verbose:
- self._print_verbage()
-
- self.connect(self, self.fmdemod, self.clock_recovery, self.slicer, self)
-
- if log:
- self._setup_logging()
-
- 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.
-
- def _print_verbage(self):
- print "bits per symbol = %d" % self.bits_per_symbol()
- print "M&M clock recovery omega = %f" % self._omega
- print "M&M clock recovery gain mu = %f" % self._gain_mu
- print "M&M clock recovery mu = %f" % self._mu
- print "M&M clock recovery omega rel. limit = %f" % self._omega_relative_limit
- print "frequency error = %f" % self._freq_error
-
-
- def _setup_logging(self):
- print "Demodulation logging turned on."
- self.connect(fmdemod, gr.file_sink(gr.sizeof_float, "fmdemod.dat"))
- self.connect(clock_recovery, gr.file_sink(gr.sizeof_float, "clock_recovery.dat"))
- self.connect(slicer, gr.file_sink(gr.sizeof_char, "slicer.dat"))
-
- def add_options(parser):
- """
- Adds GMSK demodulation-specific options to the standard parser
- """
- parser.add_option("", "--gain-mu", type="float", default=_def_gain_mu,
- help="M&M clock recovery gain mu [default=%default] (GMSK/PSK)")
- parser.add_option("", "--mu", type="float", default=_def_mu,
- help="M&M clock recovery mu [default=%default] (GMSK/PSK)")
- parser.add_option("", "--omega-relative-limit", type="float", default=_def_omega_relative_limit,
- help="M&M clock recovery omega relative limit [default=%default] (GMSK/PSK)")
- parser.add_option("", "--freq-error", type="float", default=_def_freq_error,
- help="M&M clock recovery frequency error [default=%default] (GMSK)")
- add_options=staticmethod(add_options)
-
- # FIXME: figure out what this is for gr.hier_block2 version
- #def extract_kwargs_from_options(options):
- # """
- # Given command line options, create dictionary suitable for passing to __init__
- # """
- # return modulation_utils.extract_kwargs_from_options(gmsk_demod.__init__,
- # ('self', 'fg'), options)
- #extract_kwargs_from_options=staticmethod(extract_kwargs_from_options)
-
-#
-# Add these to the mod/demod registry
-#
-modulation_utils.add_type_1_mod('gmsk2', gmsk2_mod)
-modulation_utils.add_type_1_demod('gmsk2', gmsk2_demod)
+++ /dev/null
-#!/usr/bin/env python
-#
-# Copyright 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.
-#
-
-from gnuradio import gr, eng_notation
-from gnuradio.eng_option import eng_option
-from optparse import OptionParser
-from dect_receiver import dect_receiver
-import sys
-
-def main():
- parser = OptionParser(option_class=eng_option)
- parser.add_option("-R", "--rx-subdev-spec", type="subdev", default=None,
- help="select USRP Rx side A or B (default=first one with a daughterboard)")
- parser.add_option("-f", "--freq", type="eng_float", default=None,
- help="set frequency to FREQ", metavar="FREQ")
- parser.add_option("", "--calibration", type="eng_float", default=0.0,
- help="set frequency calibration offset to FREQ")
- parser.add_option("-g", "--gain", type="eng_float", default=None,
- help="set gain in dB (default is midpoint)")
- parser.add_option("-v", "--verbose", action="store_true", default=False,
- help="print extra debugging info")
- parser.add_option("", "--log-baseband", default=None,
- help="log filtered baseband to file")
- parser.add_option("", "--log-demod", default=None,
- help="log demodulator output to file")
- (options, args) = parser.parse_args()
-
- if len(sys.argv) == 1 or len(args) != 0:
- parser.print_help()
- sys.exit(1)
-
- # Create an instance of a hierarchical block
- top_block = dect_receiver(options)
-
- try:
- # Run forever
- top_block.run()
- except KeyboardInterrupt:
- # Ctrl-C exits
- pass
-
-if __name__ == '__main__':
- main ()
+++ /dev/null
-#!/usr/bin/env python
-#
-# Copyright 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.
-#
-
-from gnuradio import gr, usrp, eng_notation
-n2s = eng_notation.num_to_str
-
-# Hierarchical block implementing a USRP source for complex floats,
-# with convenience functions for gain, tune, decimation, etc.
-#
-class usrp_source_c(gr.hier_block2):
- """
- Create a USRP source object supplying complex floats.
- """
- def __init__(self, which=0, subdev_spec=None, gain=None, if_rate=None,
- freq=0.0, calibration=0.0, verbose=False):
- # Call hierarchical block constructor
- gr.hier_block2.__init__(self,
- "usrp_source_c", # Block typename
- gr.io_signature(0,0,0), # Input signature
- gr.io_signature(1,1,gr.sizeof_gr_complex)) # Output signature
-
- self._verbose = verbose
- self._u = usrp.source_c(which)
- if self._verbose:
- print 'ADC sample rate is', n2s(self._u.adc_rate()), "sps"
- self.set_subdev(subdev_spec)
- self.set_if_rate(if_rate)
- self.set_gain(gain)
- self.set_calibration(calibration)
- self.tune(freq)
- self.connect(self._u, self)
-
- def set_subdev(self, subdev_spec):
- if subdev_spec is None:
- subdev_spec = self.pick_subdevice()
- self._subdev = usrp.selected_subdev(self._u, subdev_spec)
- self._u.set_mux(usrp.determine_rx_mux_value(self._u, subdev_spec))
- if self._verbose:
- print 'RX using', self._subdev.name(), 'daughterboard'
-
- def pick_subdevice(self):
- """
- The user didn't specify a subdevice.
- If there's a daughterboard on A, select A.
- If there's a daughterboard on B, select B.
- Otherwise, select A.
- """
- if self._u.db[0][0].dbid() >= 0: # dbid is < 0 if there's no d'board or a problem
- return (0, 0)
- if self._u.db[1][0].dbid() >= 0:
- return (1, 0)
- return (0, 0)
-
- def set_if_rate(self, if_rate):
- # If no IF rate specified, set to maximum decimation
- if if_rate is None:
- self._decim = 256
- else:
- self._decim = int(self._u.adc_rate()/if_rate)
-
- self._u.set_decim_rate(self._decim)
- self._if_rate = self._u.adc_rate()/self._decim
-
- if self._verbose:
- print "USRP decimation rate is", self._decim
- print "USRP IF rate is", n2s(self._if_rate), "sps"
-
- def set_gain(self, gain):
- # If no gain specified, set to midrange
- if gain is None:
- g = self._subdev.gain_range()
- gain = (g[0]+g[1])/2.0
- self._gain = gain
- self._subdev.set_gain(self._gain)
-
- def set_calibration(self, calibration):
- self._cal = calibration
- if self._verbose:
- print "Using frequency calibration offset of", n2s(calibration), "Hz"
-
- def tune(self, freq):
- """
- Set the center frequency we're interested in.
-
- @param target_freq: frequency in Hz
- @type: bool
-
- Tuning is a two step process. First we ask the front-end to
- tune as close to the desired frequency as it can. Then we use
- the result of that operation and our target_frequency to
- determine the value for the digital down converter.
- """
- self._tune_result = usrp.tune(self._u, 0, self._subdev, freq+self._cal)
- if self._tune_result:
- if self._verbose:
- print "Baseband frequency is", n2s(self._tune_result.baseband_freq), "Hz"
- print "DXC frequency is", n2s(self._tune_result.dxc_freq), "Hz"
- print "Center frequency is", n2s(freq), "Hz"
- print "Residual frequency is", n2s(self._tune_result.residual_freq), "Hz"
- return True
-
- return False
-
-if __name__ == '__main__':
- src = usrp_source_c(verbose=True)
+++ /dev/null
-#
-# Copyright 2004 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.
-#
-
-EXTRA_DIST = \
- README \
- benchmark_loopback.py \
- benchmark_rx.py \
- benchmark_tx.py \
- fusb_options.py \
- pick_bitrate.py \
- receive_path.py \
- receive_path_lb.py \
- rx_voice.py \
- transmit_path.py \
- transmit_path_lb.py \
- tunnel.py \
- tx_voice.py
-
-MOSTLYCLEANFILES = *~ *.pyc *.dat
+++ /dev/null
-Quick overview of what's here:
-
-* benchmark_tx.py: generates packets of the size you
-specify and sends them across the air using the USRP. Known to work
-well using the USRP with the RFX transceiver daughterboards.
-You can specify the bitrate to use with the -r <bitrate> command line
-parameter. The default is 500k. Some machines will do 1M or more.
-You can select the modulation to use with the -m <modulation> command
-line argument. The legal values for <modulation> are gmsk, dbpsk and dqpsk.
-
-* benchmark_rx.py: the receiver half of benchmark_tx.py.
-Command line arguments are pretty much the same as rx. Works well
-with a USRP and RFX transceiver daughterboards. Will also work
-with TVRX daugherboard, but you'll need to fiddle with the gain. See
-below. Prints a summary of each packet received and keeps a running
-total of packets received, and how many of them were error free.
-There are two levels of error reporting going on. If the access code
-(PN code) and header of a packet were properly detected, then you'll
-get an output line. If the CRC32 of the payload was correct you get
-"ok = True", else "ok = False". The "pktno" is extracted from the
-received packet. If there are skipped numbers, you're missing some
-packets. Be sure you've got a suitable antenna connected to the TX/RX
-port on each board. For the RFX-400, "70 cm" / 420 MHz antennas for ham
-handi-talkies work great. These are available at ham radio supplies,
-etc. The boards need to be at least 3m apart. You can also try
-experimenting with the rx gain (-g <gain> command line option).
-
-Generally speaking, I start the rx first on one machine, and then fire
-up the tx on the other machine. The tx also supports a discontinous
-transmission mode where it sends bursts of 5 packets and then waits 1
-second. This is useful for ensuring that all the receiver control
-loops lock up fast enough.
-
-* tunnel.py: This program provides a framework for building your own
-MACs. It creates a "TAP" interface in the kernel, typically gr0,
-and sends and receives ethernet frames through it. See
-/usr/src/linux/Documentation/networking/tuntap.txt and/or Google for
-"universal tun tap". The Linux 2.6 kernel includes the tun module, you
-don't have to build it. You may have to "modprobe tun" if it's not
-loaded by default. If /dev/net/tun doesn't exist, try "modprobe tun".
-
-To run this program you'll need to be root or running with the
-appropriate capability to open the tun interface. You'll need to fire
-up two copies on different machines. Once each is running you'll need
-to ifconfig the gr0 interface to set the IP address.
-
-This will allow two machines to talk, but anything beyond the two
-machines depends on your networking setup. Left as an exercise...
-
-On machine A:
-
- $ su
- # ./tunnel.py --freq 423.0M --bitrate 500k
- # # in another window on A, also as root...
- # ifconfig gr0 192.168.200.1
-
-
-On machine B:
-
- $ su
- # ./tunnel.py --freq 423.0M --bitrate 500k
- # # in another window on B, also as root...
- # ifconfig gr0 192.168.200.2
-
-Now, on machine A you shold be able to ping machine B:
-
- $ ping 192.168.200.2
-
-and you should see some output for each packet in the
-tunnel.py window if you used the -v option.
-
-Likewise, on machine B:
-
- $ ping 192.168.200.1
-
-This now uses a carrier sense MAC, so you should be able to ssh
-between the machines, web browse, etc.
+++ /dev/null
-#!/usr/bin/env python
-#!/usr/bin/env python
-#
-# 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.
-#
-
-from gnuradio import gr, gru, modulation_utils
-from gnuradio import eng_notation
-from gnuradio.eng_option import eng_option
-from optparse import OptionParser
-
-import random, time, struct, sys, math
-
-# from current dir
-from transmit_path_lb import transmit_path
-from receive_path_lb import receive_path
-import fusb_options
-
-class awgn_channel(gr.hier_block2):
- def __init__(self, sample_rate, noise_voltage, frequency_offset, seed=False):
- gr.hier_block2.__init__(self, "awgn_channel",
- gr.io_signature(1,1,gr.sizeof_gr_complex), # Input signature
- gr.io_signature(1,1,gr.sizeof_gr_complex)) # Output signature
-
- # Create the Gaussian noise source
- if not seed:
- self.noise = gr.noise_source_c(gr.GR_GAUSSIAN, noise_voltage)
- else:
- rseed = int(time.time())
- self.noise = gr.noise_source_c(gr.GR_GAUSSIAN, noise_voltage, rseed)
- self.adder = gr.add_cc()
-
- # Create the frequency offset
- self.offset = gr.sig_source_c((sample_rate*1.0), gr.GR_SIN_WAVE, frequency_offset, 1.0, 0.0)
- self.mixer = gr.multiply_cc()
-
- # Connect the components
- self.connect(self, (self.mixer, 0))
- self.connect(self.offset, (self.mixer, 1))
- self.connect(self.mixer, (self.adder, 0))
- self.connect(self.noise, (self.adder, 1))
- self.connect(self.adder, self)
-
-
-class my_graph(gr.top_block):
- def __init__(self, mod_class, demod_class, rx_callback, options):
- gr.top_block.__init__(self, "my_graph")
-
- channelon = True;
-
- SNR = 10.0**(options.snr/10.0)
- frequency_offset = options.frequency_offset
-
- power_in_signal = abs(options.tx_amplitude)**2
- noise_power = power_in_signal/SNR
- noise_voltage = math.sqrt(noise_power)
-
- 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)
-
- if channelon:
- self.channel = awgn_channel(options.sample_rate, noise_voltage, frequency_offset, options.seed)
- self.connect(self.txpath, self.throttle, self.channel, self.rxpath)
- else:
- self.connect(self.txpath, self.throttle, self.rxpath)
-
-# /////////////////////////////////////////////////////////////////////////////
-# main
-# /////////////////////////////////////////////////////////////////////////////
-
-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)
-
- def send_pkt(payload='', eof=False):
- return top_block.txpath.send_pkt(payload, eof)
-
-
- mods = modulation_utils.type_1_mods()
- demods = modulation_utils.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',
- 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)")
-
- channel_grp.add_option("", "--sample-rate", type="eng_float", default=1e5,
- help="set speed of channel/simulation rate to RATE [default=%default]")
- channel_grp.add_option("", "--snr", type="eng_float", default=30,
- help="set the SNR of the channel in dB [default=%default]")
- channel_grp.add_option("", "--frequency-offset", type="eng_float", default=0,
- help="set frequency offset introduced by channel [default=%default]")
- channel_grp.add_option("", "--seed", action="store_true", default=False,
- help="use a random seed for AWGN noise [default=%default]")
-
- transmit_path.add_options(parser, expert_grp)
- receive_path.add_options(parser, expert_grp)
-
- for mod in mods.values():
- mod.add_options(expert_grp)
- for demod in demods.values():
- demod.add_options(expert_grp)
-
- (options, args) = parser.parse_args ()
-
- if len(args) != 0:
- parser.print_help()
- sys.exit(1)
-
- r = gr.enable_realtime_scheduling()
- if r != gr.RT_OK:
- print "Warning: failed to enable realtime scheduling"
-
- # Create an instance of a hierarchical block
- top_block = my_graph(mods[options.modulation], demods[options.modulation], rx_callback, options)
- top_block.start()
-
- # generate and send packets
- nbytes = int(1e6 * options.megabytes)
- n = 0
- pktno = 0
- pkt_size = int(options.size)
-
- while n < nbytes:
- send_pkt(struct.pack('!H', pktno) + (pkt_size - 2) * chr(pktno & 0xff))
- n += pkt_size
- if options.discontinuous and pktno % 5 == 4:
- time.sleep(1)
- pktno += 1
-
- send_pkt(eof=True)
-
- top_block.wait()
-
-if __name__ == '__main__':
- try:
- main()
- except KeyboardInterrupt:
- pass
+++ /dev/null
-#!/usr/bin/env python
-#
-# 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.
-#
-
-from gnuradio import gr, gru, modulation_utils
-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
-from receive_path import receive_path
-import fusb_options
-
-#import os
-#print os.getpid()
-#raw_input('Attach and press enter: ')
-
-# /////////////////////////////////////////////////////////////////////////////
-# 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_utils.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='gmsk',
- help="Select modulation from: %s [default=%%default]"
- % (', '.join(demods.keys()),))
-
- receive_path.add_options(parser, expert_grp)
-
- for mod in demods.values():
- mod.add_options(expert_grp)
-
- fusb_options.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)
-
- r = gr.enable_realtime_scheduling()
- if r != gr.RT_OK:
- print "Warning: Failed to enable realtime scheduling."
-
- # Create an instance of a hierarchical block
- top_block = receive_path(demods[options.modulation], rx_callback, options)
- top_block.run()
-
-if __name__ == '__main__':
- try:
- main()
- except KeyboardInterrupt:
- pass
+++ /dev/null
-#!/usr/bin/env python
-#
-# 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.
-#
-
-from gnuradio import gr, gru, modulation_utils
-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
-from transmit_path import transmit_path
-import fusb_options
-
-#import os
-#print os.getpid()
-#raw_input('Attach and press enter')
-
-# /////////////////////////////////////////////////////////////////////////////
-# main
-# /////////////////////////////////////////////////////////////////////////////
-
-def main():
-
- def send_pkt(payload='', eof=False):
- return top_block.send_pkt(payload, eof)
-
- def rx_callback(ok, payload):
- print "ok = %r, payload = '%s'" % (ok, payload)
-
- mods = modulation_utils.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='gmsk',
- 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)")
-
- transmit_path.add_options(parser, expert_grp)
-
- for mod in mods.values():
- mod.add_options(expert_grp)
-
- fusb_options.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)
-
- r = gr.enable_realtime_scheduling()
- if r != gr.RT_OK:
- print "Warning: failed to enable realtime scheduling"
-
- # Create an instance of a hierarchical block
- top_block = transmit_path(mods[options.modulation], options)
- top_block.start()
-
- # generate and send packets
- nbytes = int(1e6 * options.megabytes)
- n = 0
- pktno = 0
- pkt_size = int(options.size)
-
- while n < nbytes:
- send_pkt(struct.pack('!H', pktno) + (pkt_size - 2) * chr(pktno & 0xff))
- n += pkt_size
- sys.stderr.write('.')
- if options.discontinuous and pktno % 5 == 4:
- time.sleep(1)
- pktno += 1
-
- send_pkt(eof=True)
- top_block.wait()
-
-if __name__ == '__main__':
- try:
- main()
- except KeyboardInterrupt:
- pass
+++ /dev/null
-#
-# Copyright 2006 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.
-#
-
-def add_options(parser):
- """
- Add Fast USB specifc options to command line parser.
-
- @param parser: instance of OptionParser
- """
- parser.add_option("-B", "--fusb-block-size", type="int", default=0,
- help="specify fast usb block size [default=%default]")
- parser.add_option("-N", "--fusb-nblocks", type="int", default=0,
- help="specify number of fast usb blocks [default=%default]")
+++ /dev/null
-#
-# Copyright 2005,2006 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.
-#
-
-_default_bitrate = 500e3
-
-_valid_samples_per_symbol = (2,3,4,5,6,7)
-
-def _gen_tx_info(converter_rate):
- results = []
- for samples_per_symbol in _valid_samples_per_symbol:
- for interp in range(16, 512 + 1, 4):
- bitrate = converter_rate / interp / samples_per_symbol
- results.append((bitrate, samples_per_symbol, interp))
- results.sort()
- return results
-
-def _gen_rx_info(converter_rate):
- results = []
- for samples_per_symbol in _valid_samples_per_symbol:
- for decim in range(8, 256 + 1, 2):
- bitrate = converter_rate / decim / samples_per_symbol
- results.append((bitrate, samples_per_symbol, decim))
- results.sort()
- return results
-
-def _filter_info(info, samples_per_symbol, xrate):
- if samples_per_symbol is not None:
- info = [x for x in info if x[1] == samples_per_symbol]
- if xrate is not None:
- info = [x for x in info if x[2] == xrate]
- return info
-
-def _pick_best(target_bitrate, bits_per_symbol, info):
- """
- @returns tuple (bitrate, samples_per_symbol, interp_rate_or_decim_rate)
- """
- if len(info) == 0:
- raise RuntimeError, "info is zero length!"
-
- if target_bitrate is None: # return the fastest one
- return info[-1]
-
- # convert bit rate to symbol rate
- target_symbolrate = target_bitrate / bits_per_symbol
-
- # Find the closest matching symbol rate.
- # In the event of a tie, the one with the lowest samples_per_symbol wins.
- # (We already sorted them, so the first one is the one we take)
-
- best = info[0]
- best_delta = abs(target_symbolrate - best[0])
- for x in info[1:]:
- delta = abs(target_symbolrate - x[0])
- if delta < best_delta:
- best_delta = delta
- best = x
-
- # convert symbol rate back to bit rate
- return ((best[0] * bits_per_symbol),) + best[1:]
-
-def _pick_bitrate(bitrate, bits_per_symbol, samples_per_symbol,
- xrate, converter_rate, gen_info):
- """
- @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"
-
- if samples_per_symbol is not None and xrate is not None: # completely determined
- return (float(converter_rate) / xrate / samples_per_symbol,
- samples_per_symbol, xrate)
-
- if bitrate is None and samples_per_symbol is None and xrate is None:
- bitrate = _default_bitrate
-
- # now we have a target bitrate and possibly an xrate or
- # samples_per_symbol constraint, but not both of them.
-
- return _pick_best(bitrate, bits_per_symbol,
- _filter_info(gen_info(converter_rate), samples_per_symbol, xrate))
-
-# ---------------------------------------------------------------------------------------
-
-def pick_tx_bitrate(bitrate, bits_per_symbol, samples_per_symbol,
- interp_rate, converter_rate=128e6):
- """
- 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
-
- @returns tuple (bitrate, samples_per_symbol, interp_rate)
- """
- return _pick_bitrate(bitrate, bits_per_symbol, samples_per_symbol,
- interp_rate, converter_rate, _gen_tx_info)
-
-
-def pick_rx_bitrate(bitrate, bits_per_symbol, samples_per_symbol,
- decim_rate, converter_rate=64e6):
- """
- 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
-
- @returns tuple (bitrate, samples_per_symbol, decim_rate)
- """
- return _pick_bitrate(bitrate, bits_per_symbol, samples_per_symbol,
- decim_rate, converter_rate, _gen_rx_info)
+++ /dev/null
-#!/usr/bin/env python
-#
-# 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.
-#
-
-from gnuradio import gr, gru, blks2
-from gnuradio import usrp
-from gnuradio import eng_notation
-import copy
-import sys
-
-# from current dir
-from pick_bitrate import pick_rx_bitrate
-
-# /////////////////////////////////////////////////////////////////////////////
-# receive path
-# /////////////////////////////////////////////////////////////////////////////
-
-class receive_path(gr.top_block):
- def __init__(self, demod_class, rx_callback, options):
- gr.top_block.__init__(self, "receive_path")
- options = copy.copy(options) # make a copy so we can destructively modify
-
- self._verbose = options.verbose
- self._rx_freq = options.rx_freq # receiver's center frequency
- self._rx_gain = options.rx_gain # receiver's gain
- self._rx_subdev_spec = options.rx_subdev_spec # daughterboard to use
- self._bitrate = options.bitrate # desired bit rate
- self._decim = options.decim # Decimating rate for the USRP (prelim)
- self._samples_per_symbol = options.samples_per_symbol # desired samples/symbol
- self._fusb_block_size = options.fusb_block_size # usb info for USRP
- self._fusb_nblocks = options.fusb_nblocks # usb info for USRP
-
- self._rx_callback = rx_callback # this callback is fired when there's a packet available
- self._demod_class = demod_class # the demodulator_class we're using
-
- if self._rx_freq is None:
- sys.stderr.write("-f FREQ or --freq FREQ or --rx-freq FREQ must be specified\n")
- raise SystemExit
-
- # Set up USRP source; also adjusts decim, samples_per_symbol, and bitrate
- self._setup_usrp_source()
-
- g = self.subdev.gain_range()
- if options.show_rx_gain_range:
- print "Rx Gain Range: minimum = %g, maximum = %g, step size = %g" \
- % (g[0], g[1], g[2])
-
- self.set_gain(options.rx_gain)
-
- self.set_auto_tr(True) # enable Auto Transmit/Receive switching
-
- # Set RF frequency
- ok = self.set_freq(self._rx_freq)
- if not ok:
- print "Failed to set Rx frequency to %s" % (eng_notation.num_to_str(self._rx_freq))
- raise ValueError, eng_notation.num_to_str(self._rx_freq)
-
- # copy the final answers back into options for use by demodulator
- options.samples_per_symbol = self._samples_per_symbol
- options.bitrate = self._bitrate
- options.decim = self._decim
-
- # Get demod_kwargs
- demod_kwargs = self._demod_class.extract_kwargs_from_options(options)
-
- # Design filter to get actual channel we want
- sw_decim = 1
- chan_coeffs = gr.firdes.low_pass (1.0, # gain
- sw_decim * self._samples_per_symbol, # sampling rate
- 1.0, # midpoint of trans. band
- 0.5, # width of trans. band
- gr.firdes.WIN_HANN) # filter type
-
- # Decimating channel filter
- # complex in and out, float taps
- self.chan_filt = gr.fft_filter_ccc(sw_decim, chan_coeffs)
- #self.chan_filt = gr.fir_filter_ccf(sw_decim, chan_coeffs)
- # receiver
- self.packet_receiver = \
- blks2.demod_pkts(self._demod_class(**demod_kwargs),
- access_code=None,
- callback=self._rx_callback,
- threshold=-1)
-
- # Carrier Sensing Blocks
- alpha = 0.001
- thresh = 30 # in dB, will have to adjust
- self.probe = gr.probe_avg_mag_sqrd_c(thresh,alpha)
-
- # Display some information about the setup
- if self._verbose:
- self._print_verbage()
-
- self.channel_filter = gr.fft_filter_ccc(sw_decim, chan_coeffs)
-
- # connect the channel input filter to the carrier power detector
- self.connect(self.u, self.channel_filter, self.probe)
-
- # connect channel filter to the packet receiver
- self.connect(self.channel_filter, self.packet_receiver)
-
-
- def _setup_usrp_source(self):
- self.u = usrp.source_c (fusb_block_size=self._fusb_block_size,
- fusb_nblocks=self._fusb_nblocks)
- adc_rate = self.u.adc_rate()
-
- # derive values of bitrate, samples_per_symbol, and decim from desired info
- (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.set_decim_rate(self._decim)
-
- # determine the daughterboard subdevice we're using
- if self._rx_subdev_spec is None:
- self._rx_subdev_spec = usrp.pick_rx_subdevice(self.u)
- self.subdev = usrp.selected_subdev(self.u, self._rx_subdev_spec)
-
- self.u.set_mux(usrp.determine_rx_mux_value(self.u, self._rx_subdev_spec))
-
- def set_freq(self, target_freq):
- """
- Set the center frequency we're interested in.
-
- @param target_freq: frequency in Hz
- @rypte: bool
-
- Tuning is a two step process. First we ask the front-end to
- tune as close to the desired frequency as it can. Then we use
- the result of that operation and our target_frequency to
- determine the value for the digital up converter.
- """
- r = self.u.tune(0, self.subdev, target_freq)
- if r:
- return True
-
- return False
-
- def set_gain(self, gain):
- """
- Sets the analog gain in the USRP
- """
- if gain is None:
- r = self.subdev.gain_range()
- gain = (r[0] + r[1])/2 # set gain to midpoint
- self.gain = gain
- return self.subdev.set_gain(gain)
-
- def set_auto_tr(self, enable):
- return self.subdev.set_auto_tr(enable)
-
- def bitrate(self):
- return self._bitrate
-
- def samples_per_symbol(self):
- return self._samples_per_symbol
-
- def decim(self):
- return self._decim
-
- def carrier_sensed(self):
- """
- Return True if we think carrier is present.
- """
- #return self.probe.level() > X
- return self.probe.unmuted()
-
- def carrier_threshold(self):
- """
- Return current setting in dB.
- """
- return self.probe.threshold()
-
- def set_carrier_threshold(self, threshold_in_db):
- """
- Set carrier threshold.
-
- @param threshold_in_db: set detection threshold
- @type threshold_in_db: float (dB)
- """
- self.probe.set_threshold(threshold_in_db)
-
-
- def add_options(normal, expert):
- """
- Adds receiver-specific options to the Options Parser
- """
- add_freq_option(normal)
- if not normal.has_option("--bitrate"):
- normal.add_option("-r", "--bitrate", type="eng_float", default=None,
- help="specify bitrate. samples-per-symbol and interp/decim will be derived.")
- normal.add_option("-R", "--rx-subdev-spec", type="subdev", default=None,
- help="select USRP Rx side A or B")
- normal.add_option("", "--rx-gain", type="eng_float", default=None, metavar="GAIN",
- help="set receiver gain in dB [default=midpoint]. See also --show-rx-gain-range")
- normal.add_option("", "--show-rx-gain-range", action="store_true", default=False,
- help="print min and max Rx gain available on selected daughterboard")
- normal.add_option("-v", "--verbose", action="store_true", default=False)
- expert.add_option("-S", "--samples-per-symbol", type="int", default=None,
- help="set samples/symbol [default=%default]")
- expert.add_option("", "--rx-freq", type="eng_float", default=None,
- help="set Rx frequency to FREQ [default=%default]", metavar="FREQ")
- expert.add_option("-d", "--decim", type="intx", default=None,
- help="set fpga decimation rate to DECIM [default=%default]")
- expert.add_option("", "--log", action="store_true", default=False,
- help="Log all parts of flow graph to files (CAUTION: lots of data)")
-
- # Make a static method to call before instantiation
- add_options = staticmethod(add_options)
-
-
- def _print_verbage(self):
- """
- Prints information about the receive path
- """
- print "\nReceive Path:"
- print "Using RX d'board %s" % (self.subdev.side_and_name(),)
- print "Rx gain: %g" % (self.gain,)
- 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 "decim: %3d" % (self._decim)
- print "Rx Frequency: %s" % (eng_notation.num_to_str(self._rx_freq))
-
-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")
+++ /dev/null
-#!/usr/bin/env python
-#
-# Copyright 2005,2006 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, blks2
-from gnuradio import eng_notation
-import copy
-import sys
-
-# /////////////////////////////////////////////////////////////////////////////
-# receive path
-# /////////////////////////////////////////////////////////////////////////////
-
-class receive_path(gr.hier_block2):
- def __init__(self, demod_class, rx_callback, options):
- gr.hier_block2.__init__(self, "receive_path",
- gr.io_signature(1,1,gr.sizeof_gr_complex), # Input signature
- gr.io_signature(0,0,0)) # Output signature
-
- options = copy.copy(options) # make a copy so we can destructively modify
-
- self._verbose = options.verbose
- self._bitrate = options.bitrate # desired bit rate
- self._samples_per_symbol = options.samples_per_symbol # desired samples/symbol
-
- self._rx_callback = rx_callback # this callback is fired when there's a packet available
- self._demod_class = demod_class # the demodulator_class we're using
-
- # Get demod_kwargs
- demod_kwargs = self._demod_class.extract_kwargs_from_options(options)
-
- # Design filter to get actual channel we want
- sw_decim = 1
- chan_coeffs = gr.firdes.low_pass (1.0, # gain
- sw_decim * self._samples_per_symbol, # sampling rate
- 1.0, # midpoint of trans. band
- 0.5, # width of trans. band
- gr.firdes.WIN_HANN) # filter type
-
- # receiver
- self.packet_receiver = \
- blks2.demod_pkts(self._demod_class(**demod_kwargs),
- access_code=None,
- callback=self._rx_callback,
- threshold=-1)
-
- # Carrier Sensing Blocks
- alpha = 0.001
- thresh = 30 # in dB, will have to adjust
- self.probe = gr.probe_avg_mag_sqrd_c(thresh,alpha)
-
- # Display some information about the setup
- if self._verbose:
- self._print_verbage()
-
- self.channel_filter = gr.fft_filter_ccc(sw_decim, chan_coeffs)
-
- # connect the channel input filter to the carrier power detector
- self.connect(self, self.channel_filter, self.probe)
-
- # connect channel filter to the packet receiver
- self.connect(self.channel_filter, self.packet_receiver)
-
- def bitrate(self):
- return self._bitrate
-
- def samples_per_symbol(self):
- return self._samples_per_symbol
-
- def carrier_sensed(self):
- """
- Return True if we think carrier is present.
- """
- #return self.probe.level() > X
- return self.probe.unmuted()
-
- def carrier_threshold(self):
- """
- Return current setting in dB.
- """
- return self.probe.threshold()
-
- def set_carrier_threshold(self, threshold_in_db):
- """
- Set carrier threshold.
-
- @param threshold_in_db: set detection threshold
- @type threshold_in_db: float (dB)
- """
- self.probe.set_threshold(threshold_in_db)
-
-
- def add_options(normal, expert):
- """
- Adds receiver-specific options to the Options Parser
- """
- if not normal.has_option("--bitrate"):
- normal.add_option("-r", "--bitrate", type="eng_float", default=100e3,
- help="specify bitrate [default=%default].")
- normal.add_option("", "--show-rx-gain-range", action="store_true", default=False,
- help="print min and max Rx gain available on selected daughterboard")
- normal.add_option("-v", "--verbose", action="store_true", default=False)
- expert.add_option("-S", "--samples-per-symbol", type="int", default=2,
- 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)")
-
- # Make a static method to call before instantiation
- add_options = staticmethod(add_options)
-
-
- def _print_verbage(self):
- """
- Prints information about the receive 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)
+++ /dev/null
-#!/usr/bin/env python
-#
-# Copyright 2005,2006 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_utils
-from gnuradio import usrp
-from gnuradio import audio
-from gnuradio import eng_notation
-from gnuradio.eng_option import eng_option
-from optparse import OptionParser
-
-from gnuradio.vocoder import gsm_full_rate
-
-import random
-import struct
-
-# from current dir
-from receive_path import receive_path
-import fusb_options
-
-#import os
-#print os.getpid()
-#raw_input('Attach and press enter')
-
-
-class audio_tx(gr.hier_block):
- def __init__(self, fg, audio_output_dev):
- self.packet_src = gr.message_source(33)
- voice_decoder = gsm_full_rate.decode_ps()
- s2f = gr.short_to_float ()
- sink_scale = gr.multiply_const_ff(1.0/32767.)
- audio_sink = audio.sink(8000, audio_output_dev)
- fg.connect(self.packet_src, voice_decoder, s2f, sink_scale, audio_sink)
- gr.hier_block.__init__(self, fg, self.packet_src, audio_sink)
-
- def msgq(self):
- return self.packet_src.msgq()
-
-
-class my_graph(gr.flow_graph):
-
- def __init__(self, demod_class, rx_callback, options):
- gr.flow_graph.__init__(self)
- self.rxpath = receive_path(self, demod_class, rx_callback, options)
- self.audio_tx = audio_tx(self, options.audio_output)
-
-
-# /////////////////////////////////////////////////////////////////////////////
-# 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
- n_rcvd += 1
- if ok:
- n_right += 1
-
- fg.audio_tx.msgq().insert_tail(gr.message_from_string(payload))
-
- print "ok = %r n_rcvd = %4d n_right = %4d" % (
- ok, n_rcvd, n_right)
-
- demods = modulation_utils.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='gmsk',
- help="Select modulation from: %s [default=%%default]"
- % (', '.join(demods.keys()),))
- parser.add_option("-O", "--audio-output", type="string", default="",
- help="pcm output device name. E.g., hw:0,0 or /dev/dsp")
-
- receive_path.add_options(parser, expert_grp)
-
- for mod in demods.values():
- mod.add_options(expert_grp)
-
- fusb_options.add_options(expert_grp)
-
- parser.set_defaults(bitrate=50e3) # override default bitrate default
- (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
- fg = my_graph(demods[options.modulation], rx_callback, options)
-
- r = gr.enable_realtime_scheduling()
- if r != gr.RT_OK:
- print "Warning: Failed to enable realtime scheduling."
-
- fg.start() # start flow graph
- fg.wait() # wait for it to finish
-
-if __name__ == '__main__':
- try:
- main()
- except KeyboardInterrupt:
- pass
+++ /dev/null
-#
-# 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.
-#
-
-from gnuradio import gr, gru, blks2
-from gnuradio import usrp
-from gnuradio import eng_notation
-
-import copy
-import sys
-
-# from current dir
-from pick_bitrate import pick_tx_bitrate
-
-# /////////////////////////////////////////////////////////////////////////////
-# transmit path
-# /////////////////////////////////////////////////////////////////////////////
-
-class transmit_path(gr.top_block):
- def __init__(self, modulator_class, options):
- '''
- See below for what options should hold
- '''
-
- gr.top_block.__init__(self, "transmit_path")
- options = copy.copy(options) # make a copy so we can destructively modify
-
- self._verbose = options.verbose
- self._tx_freq = options.tx_freq # tranmitter's center frequency
- self._tx_amplitude = options.tx_amplitude # digital amplitude sent to USRP
- self._tx_subdev_spec = options.tx_subdev_spec # daughterboard to use
- self._bitrate = options.bitrate # desired bit rate
- self._interp = options.interp # interpolating rate for the USRP (prelim)
- self._samples_per_symbol = options.samples_per_symbol # desired samples/baud
- self._fusb_block_size = options.fusb_block_size # usb info for USRP
- self._fusb_nblocks = options.fusb_nblocks # usb info for USRP
-
- self._modulator_class = modulator_class # the modulator_class we are using
-
- if self._tx_freq is None:
- sys.stderr.write("-f FREQ or --freq FREQ or --tx-freq FREQ must be specified\n")
- raise SystemExit
-
- # Set up USRP sink; also adjusts interp, samples_per_symbol, and bitrate
- self._setup_usrp_sink()
-
- # copy the final answers back into options for use by modulator
- options.samples_per_symbol = self._samples_per_symbol
- options.bitrate = self._bitrate
- options.interp = self._interp
-
- # Get mod_kwargs
- mod_kwargs = self._modulator_class.extract_kwargs_from_options(options)
-
- # Set center frequency of USRP
- ok = self.set_freq(self._tx_freq)
- if not ok:
- print "Failed to set Tx frequency to %s" % (eng_notation.num_to_str(self._tx_freq),)
- raise ValueError
-
- # transmitter
- self.packet_transmitter = \
- blks2.mod_pkts(self._modulator_class(**mod_kwargs),
- access_code=None,
- msgq_limit=4,
- pad_for_usrp=True)
-
- # Set the USRP for maximum transmit gain
- # (Note that on the RFX cards this is a nop.)
- self.set_gain(self.subdev.gain_range()[0])
-
- self.amp = gr.multiply_const_cc(1)
- self.set_tx_amplitude(self._tx_amplitude)
-
- # enable Auto Transmit/Receive switching
- self.set_auto_tr(True)
-
- # Display some information about the setup
- if self._verbose:
- self._print_verbage()
-
- self.connect(self.packet_transmitter, self.amp, self.u)
-
- def _setup_usrp_sink(self):
- """
- Creates a USRP sink, determines the settings for best bitrate,
- and attaches to the transmitter's subdevice.
- """
- self.u = usrp.sink_c(fusb_block_size=self._fusb_block_size,
- fusb_nblocks=self._fusb_nblocks)
- dac_rate = self.u.dac_rate();
-
- # derive values of bitrate, samples_per_symbol, and interp from desired info
- (self._bitrate, self._samples_per_symbol, self._interp) = \
- pick_tx_bitrate(self._bitrate, self._modulator_class.bits_per_symbol(),
- self._samples_per_symbol, self._interp, dac_rate)
-
- self.u.set_interp_rate(self._interp)
-
- # determine the daughterboard subdevice we're using
- if self._tx_subdev_spec is None:
- self._tx_subdev_spec = usrp.pick_tx_subdevice(self.u)
- self.u.set_mux(usrp.determine_tx_mux_value(self.u, self._tx_subdev_spec))
- self.subdev = usrp.selected_subdev(self.u, self._tx_subdev_spec)
-
-
- def set_freq(self, target_freq):
- """
- Set the center frequency we're interested in.
-
- @param target_freq: frequency in Hz
- @rypte: bool
-
- Tuning is a two step process. First we ask the front-end to
- tune as close to the desired frequency as it can. Then we use
- the result of that operation and our target_frequency to
- determine the value for the digital up converter.
- """
- r = self.u.tune(self.subdev._which, self.subdev, target_freq)
- if r:
- return True
-
- return False
-
- def set_gain(self, gain):
- """
- Sets the analog gain in the USRP
- """
- self.gain = gain
- self.subdev.set_gain(gain)
-
- def set_tx_amplitude(self, ampl):
- """
- Sets the transmit amplitude sent to the USRP
- @param: ampl 0 <= ampl < 32768. Try 8000
- """
- self._tx_amplitude = max(0.0, min(ampl, 32767.0))
- self.amp.set_k(self._tx_amplitude)
-
- def set_auto_tr(self, enable):
- """
- Turns on auto transmit/receive of USRP daughterboard (if exits; else ignored)
- """
- return self.subdev.set_auto_tr(enable)
-
- def send_pkt(self, payload='', eof=False):
- """
- Calls the transmitter method to send a packet
- """
- return self.packet_transmitter.send_pkt(payload, eof)
-
- def bitrate(self):
- return self._bitrate
-
- def samples_per_symbol(self):
- return self._samples_per_symbol
-
- def interp(self):
- return self._interp
-
- def add_options(normal, expert):
- """
- Adds transmitter-specific options to the Options Parser
- """
- add_freq_option(normal)
- if not normal.has_option('--bitrate'):
- normal.add_option("-r", "--bitrate", type="eng_float", default=None,
- help="specify bitrate. samples-per-symbol and interp/decim will be derived.")
- normal.add_option("-T", "--tx-subdev-spec", type="subdev", default=None,
- help="select USRP Tx side A or B")
- normal.add_option("", "--tx-amplitude", type="eng_float", default=12000, metavar="AMPL",
- help="set transmitter digital amplitude: 0 <= AMPL < 32768 [default=%default]")
- normal.add_option("-v", "--verbose", action="store_true", default=False)
-
- expert.add_option("-S", "--samples-per-symbol", type="int", default=None,
- help="set samples/symbol [default=%default]")
- expert.add_option("", "--tx-freq", type="eng_float", default=None,
- help="set transmit frequency to FREQ [default=%default]", metavar="FREQ")
- expert.add_option("-i", "--interp", type="intx", default=None,
- help="set fpga interpolation rate to INTERP [default=%default]")
- expert.add_option("", "--log", action="store_true", default=False,
- help="Log all parts of flow graph to file (CAUTION: lots of data)")
-
- # Make a static method to call before instantiation
- add_options = staticmethod(add_options)
-
- def _print_verbage(self):
- """
- Prints information about the transmit path
- """
- print "Using TX d'board %s" % (self.subdev.side_and_name(),)
- 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 "interp: %3d" % (self._interp)
- print "Tx Frequency: %s" % (eng_notation.num_to_str(self._tx_freq))
-
-
-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")
+++ /dev/null
-#
-# 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.
-#
-
-from gnuradio import gr, gru, blks2
-from gnuradio import eng_notation
-
-import copy
-import sys
-
-# /////////////////////////////////////////////////////////////////////////////
-# transmit path
-# /////////////////////////////////////////////////////////////////////////////
-
-class transmit_path(gr.hier_block2):
- def __init__(self, modulator_class, options):
- '''
- See below for what options should hold
- '''
-
- gr.hier_block2.__init__(self, "transmit_path",
- gr.io_signature(0,0,0), # Input signature
- gr.io_signature(1,1,gr.sizeof_gr_complex)) # Output signature
-
- options = copy.copy(options) # make a copy so we can destructively modify
-
- self._verbose = options.verbose
- self._tx_amplitude = options.tx_amplitude # digital amplitude sent to USRP
- self._bitrate = options.bitrate # desired bit rate
- self._samples_per_symbol = options.samples_per_symbol # desired samples/baud
-
- self._modulator_class = modulator_class # the modulator_class we are using
-
- # Get mod_kwargs
- mod_kwargs = self._modulator_class.extract_kwargs_from_options(options)
-
- # transmitter
- self.packet_transmitter = \
- blks2.mod_pkts(self._modulator_class(**mod_kwargs),
- access_code=None,
- msgq_limit=4,
- pad_for_usrp=True)
-
- self.amp = gr.multiply_const_cc(1)
- self.set_tx_amplitude(self._tx_amplitude)
-
- # Display some information about the setup
- if self._verbose:
- self._print_verbage()
-
- # Connect blocks in the flowgraph; set amp component to the output of this block
- self.connect(self.packet_transmitter, self.amp, self)
-
- def set_tx_amplitude(self, ampl):
- """
- Sets the transmit amplitude sent to the USRP
- @param: ampl 0 <= ampl < 32768. Try 8000
- """
- self._tx_amplitude = max(0.0, min(ampl, 32767.0))
- self.amp.set_k(self._tx_amplitude)
-
- def send_pkt(self, payload='', eof=False):
- """
- Calls the transmitter method to send a packet
- """
- return self.packet_transmitter.send_pkt(payload, eof)
-
- def bitrate(self):
- return self._bitrate
-
- def samples_per_symbol(self):
- return self._samples_per_symbol
-
- def add_options(normal, expert):
- """
- Adds transmitter-specific options to the Options Parser
- """
- if not normal.has_option('--bitrate'):
- normal.add_option("-r", "--bitrate", type="eng_float", default=100e3,
- help="specify bitrate [default=%default].")
- normal.add_option("", "--tx-amplitude", type="eng_float", default=12000, metavar="AMPL",
- help="set transmitter digital amplitude: 0 <= AMPL < 32768 [default=%default]")
- normal.add_option("-v", "--verbose", action="store_true", default=False)
-
- expert.add_option("-S", "--samples-per-symbol", type="int", default=2,
- 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)")
-
- # Make a static method to call before instantiation
- add_options = staticmethod(add_options)
-
- def _print_verbage(self):
- """
- Prints information about the transmit path
- """
- 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)
-
+++ /dev/null
-#!/usr/bin/env python
-#
-# Copyright 2005,2006 Free Software Foundation, Inc.
-#
-# This file is part of GNU Radio
-#
-# GNU Radio is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 3, or (at your option)
-# any later version.
-#
-# GNU Radio is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with GNU Radio; see the file COPYING. If not, write to
-# the Free Software Foundation, Inc., 51 Franklin Street,
-# Boston, MA 02110-1301, USA.
-#
-
-
-# /////////////////////////////////////////////////////////////////////////////
-#
-# This code sets up up a virtual ethernet interface (typically gr0),
-# and relays packets between the interface and the GNU Radio PHY+MAC
-#
-# What this means in plain language, is that if you've got a couple
-# of USRPs on different machines, and if you run this code on those
-# machines, you can talk between them using normal TCP/IP networking.
-#
-# /////////////////////////////////////////////////////////////////////////////
-
-
-from gnuradio import gr, gru, modulation_utils
-from gnuradio import usrp
-from gnuradio import eng_notation
-from gnuradio.eng_option import eng_option
-from optparse import OptionParser
-
-import random
-import time
-import struct
-import sys
-import os
-
-# from current dir
-from transmit_path import transmit_path
-from receive_path import receive_path
-import fusb_options
-
-#print os.getpid()
-#raw_input('Attach and press enter')
-
-
-# /////////////////////////////////////////////////////////////////////////////
-#
-# Use the Universal TUN/TAP device driver to move packets to/from kernel
-#
-# See /usr/src/linux/Documentation/networking/tuntap.txt
-#
-# /////////////////////////////////////////////////////////////////////////////
-
-# Linux specific...
-# TUNSETIFF ifr flags from <linux/tun_if.h>
-
-IFF_TUN = 0x0001 # tunnel IP packets
-IFF_TAP = 0x0002 # tunnel ethernet frames
-IFF_NO_PI = 0x1000 # don't pass extra packet info
-IFF_ONE_QUEUE = 0x2000 # beats me ;)
-
-def open_tun_interface(tun_device_filename):
- from fcntl import ioctl
-
- mode = IFF_TAP | IFF_NO_PI
- TUNSETIFF = 0x400454ca
-
- tun = os.open(tun_device_filename, os.O_RDWR)
- ifs = ioctl(tun, TUNSETIFF, struct.pack("16sH", "gr%d", mode))
- ifname = ifs[:16].strip("\x00")
- return (tun, ifname)
-
-
-# /////////////////////////////////////////////////////////////////////////////
-# the flow graph
-# /////////////////////////////////////////////////////////////////////////////
-
-class my_graph(gr.flow_graph):
-
- def __init__(self, mod_class, demod_class,
- rx_callback, options):
-
- gr.flow_graph.__init__(self)
- self.txpath = transmit_path(self, mod_class, options)
- self.rxpath = receive_path(self, demod_class, rx_callback, options)
-
- def send_pkt(self, payload='', eof=False):
- return self.txpath.send_pkt(payload, eof)
-
- def carrier_sensed(self):
- """
- Return True if the receive path thinks there's carrier
- """
- return self.rxpath.carrier_sensed()
-
-
-# /////////////////////////////////////////////////////////////////////////////
-# Carrier Sense MAC
-# /////////////////////////////////////////////////////////////////////////////
-
-class cs_mac(object):
- """
- Prototype carrier sense MAC
-
- Reads packets from the TUN/TAP interface, and sends them to the PHY.
- Receives packets from the PHY via phy_rx_callback, and sends them
- into the TUN/TAP interface.
-
- Of course, we're not restricted to getting packets via TUN/TAP, this
- is just an example.
- """
- def __init__(self, tun_fd, verbose=False):
- self.tun_fd = tun_fd # file descriptor for TUN/TAP interface
- self.verbose = verbose
- self.fg = None # flow graph (access to PHY)
-
- def set_flow_graph(self, fg):
- self.fg = fg
-
- def phy_rx_callback(self, ok, payload):
- """
- Invoked by thread associated with PHY to pass received packet up.
-
- @param ok: bool indicating whether payload CRC was OK
- @param payload: contents of the packet (string)
- """
- if self.verbose:
- print "Rx: ok = %r len(payload) = %4d" % (ok, len(payload))
- if ok:
- os.write(self.tun_fd, payload)
-
- def main_loop(self):
- """
- Main loop for MAC.
- Only returns if we get an error reading from TUN.
-
- FIXME: may want to check for EINTR and EAGAIN and reissue read
- """
- min_delay = 0.001 # seconds
-
- while 1:
- payload = os.read(self.tun_fd, 10*1024)
- if not payload:
- self.fg.send_pkt(eof=True)
- break
-
- if self.verbose:
- print "Tx: len(payload) = %4d" % (len(payload),)
-
- delay = min_delay
- while self.fg.carrier_sensed():
- sys.stderr.write('B')
- time.sleep(delay)
- if delay < 0.050:
- delay = delay * 2 # exponential back-off
-
- self.fg.send_pkt(payload)
-
-
-# /////////////////////////////////////////////////////////////////////////////
-# main
-# /////////////////////////////////////////////////////////////////////////////
-
-def main():
-
- mods = modulation_utils.type_1_mods()
- demods = modulation_utils.type_1_demods()
-
- 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='gmsk',
- help="Select modulation from: %s [default=%%default]"
- % (', '.join(mods.keys()),))
-
- parser.add_option("-v","--verbose", action="store_true", default=False)
- expert_grp.add_option("-c", "--carrier-threshold", type="eng_float", default=30,
- help="set carrier detect threshold (dB) [default=%default]")
- expert_grp.add_option("","--tun-device-filename", default="/dev/net/tun",
- help="path to tun device file [default=%default]")
-
- transmit_path.add_options(parser, expert_grp)
- receive_path.add_options(parser, expert_grp)
-
- for mod in mods.values():
- mod.add_options(expert_grp)
-
- for demod in demods.values():
- demod.add_options(expert_grp)
-
- fusb_options.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 or 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)
-
- # open the TUN/TAP interface
- (tun_fd, tun_ifname) = open_tun_interface(options.tun_device_filename)
-
- # Attempt to enable realtime scheduling
- r = gr.enable_realtime_scheduling()
- if r == gr.RT_OK:
- realtime = True
- else:
- realtime = False
- print "Note: failed to enable realtime scheduling"
-
-
- # If the user hasn't set the fusb_* parameters on the command line,
- # pick some values that will reduce latency.
-
- if options.fusb_block_size == 0 and options.fusb_nblocks == 0:
- if realtime: # be more aggressive
- options.fusb_block_size = gr.prefs().get_long('fusb', 'rt_block_size', 1024)
- options.fusb_nblocks = gr.prefs().get_long('fusb', 'rt_nblocks', 16)
- else:
- options.fusb_block_size = gr.prefs().get_long('fusb', 'block_size', 4096)
- options.fusb_nblocks = gr.prefs().get_long('fusb', 'nblocks', 16)
-
- #print "fusb_block_size =", options.fusb_block_size
- #print "fusb_nblocks =", options.fusb_nblocks
-
- # instantiate the MAC
- mac = cs_mac(tun_fd, verbose=True)
-
-
- # build the graph (PHY)
- fg = my_graph(mods[options.modulation],
- demods[options.modulation],
- mac.phy_rx_callback,
- options)
-
- mac.set_flow_graph(fg) # give the MAC a handle for the PHY
-
- if fg.txpath.bitrate() != fg.rxpath.bitrate():
- print "WARNING: Transmit bitrate = %sb/sec, Receive bitrate = %sb/sec" % (
- eng_notation.num_to_str(fg.txpath.bitrate()),
- eng_notation.num_to_str(fg.rxpath.bitrate()))
-
- print "modulation: %s" % (options.modulation,)
- print "freq: %s" % (eng_notation.num_to_str(options.tx_freq))
- print "bitrate: %sb/sec" % (eng_notation.num_to_str(fg.txpath.bitrate()),)
- print "samples/symbol: %3d" % (fg.txpath.samples_per_symbol(),)
- #print "interp: %3d" % (fg.txpath.interp(),)
- #print "decim: %3d" % (fg.rxpath.decim(),)
-
- fg.rxpath.set_carrier_threshold(options.carrier_threshold)
- print "Carrier sense threshold:", options.carrier_threshold, "dB"
-
- print
- print "Allocated virtual ethernet interface: %s" % (tun_ifname,)
- print "You must now use ifconfig to set its IP address. E.g.,"
- print
- print " $ sudo ifconfig %s 192.168.200.1" % (tun_ifname,)
- print
- print "Be sure to use a different address in the same subnet for each machine."
- print
-
-
- fg.start() # Start executing the flow graph (runs in separate threads)
-
- mac.main_loop() # don't expect this to return...
-
- fg.stop() # but if it does, tell flow graph to stop.
- fg.wait() # wait for it to finish
-
-
-if __name__ == '__main__':
- try:
- main()
- except KeyboardInterrupt:
- pass
+++ /dev/null
-#!/usr/bin/env python
-#
-# Copyright 2005,2006 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_utils
-from gnuradio import usrp
-from gnuradio import audio
-from gnuradio import eng_notation
-from gnuradio.eng_option import eng_option
-from optparse import OptionParser
-
-from gnuradio.vocoder import gsm_full_rate
-
-import random
-import time
-import struct
-import sys
-
-# from current dir
-from transmit_path import transmit_path
-import fusb_options
-
-#import os
-#print os.getpid()
-#raw_input('Attach and press enter')
-
-
-class audio_rx(gr.hier_block):
- def __init__(self, fg, audio_input_dev):
- sample_rate = 8000
- src = audio.source(sample_rate, audio_input_dev)
- src_scale = gr.multiply_const_ff(32767)
- f2s = gr.float_to_short()
- voice_coder = gsm_full_rate.encode_sp()
- self.packets_from_encoder = gr.msg_queue()
- packet_sink = gr.message_sink(33, self.packets_from_encoder, False)
- fg.connect(src, src_scale, f2s, voice_coder, packet_sink)
- gr.hier_block.__init__(self, fg, src, packet_sink)
-
- def get_encoded_voice_packet(self):
- return self.packets_from_encoder.delete_head()
-
-
-class my_graph(gr.flow_graph):
-
- def __init__(self, modulator_class, options):
- gr.flow_graph.__init__(self)
- self.txpath = transmit_path(self, modulator_class, options)
- self.audio_rx = audio_rx(self, options.audio_input)
-
-
-
-# /////////////////////////////////////////////////////////////////////////////
-# main
-# /////////////////////////////////////////////////////////////////////////////
-
-def main():
-
- def send_pkt(payload='', eof=False):
- return fg.txpath.send_pkt(payload, eof)
-
- def rx_callback(ok, payload):
- print "ok = %r, payload = '%s'" % (ok, payload)
-
- mods = modulation_utils.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='gmsk',
- help="Select modulation from: %s [default=%%default]"
- % (', '.join(mods.keys()),))
- parser.add_option("-M", "--megabytes", type="eng_float", default=0,
- help="set megabytes to transmit [default=inf]")
- parser.add_option("-I", "--audio-input", type="string", default="",
- help="pcm input device name. E.g., hw:0,0 or /dev/dsp")
-
- transmit_path.add_options(parser, expert_grp)
-
- for mod in mods.values():
- mod.add_options(expert_grp)
-
- fusb_options.add_options(expert_grp)
-
- parser.set_defaults(bitrate=50e3) # override default bitrate default
- (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)
-
-
- # build the graph
- fg = my_graph(mods[options.modulation], options)
-
- r = gr.enable_realtime_scheduling()
- if r != gr.RT_OK:
- print "Warning: failed to enable realtime scheduling"
-
-
- fg.start() # start flow graph
-
- # generate and send packets
- nbytes = int(1e6 * options.megabytes)
- n = 0
- pktno = 0
-
- while nbytes == 0 or n < nbytes:
- packet = fg.audio_rx.get_encoded_voice_packet()
- s = packet.to_string()
- send_pkt(s)
- n += len(s)
- sys.stderr.write('.')
- pktno += 1
-
- send_pkt(eof=True)
- fg.wait() # wait for it to finish
- fg.txpath.set_auto_tr(False)
-
-
-if __name__ == '__main__':
- try:
- main()
- except KeyboardInterrupt:
- pass
+++ /dev/null
-#
-# Copyright 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.
-#
-
-EXTRA_DIST = \
- audio_sink.py \
- audio_source.py \
- dial_tone_sink.py \
- dial_tone_source.py \
- vector_sink.py \
- vector_source.py
-
-MOSTLYCLEANFILES = *.pyc *~
+++ /dev/null
-#!/usr/bin/env python
-#
-# Copyright 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.
-#
-
-from gnuradio import gr, audio
-from gnuradio.eng_option import eng_option
-from optparse import OptionParser
-
-class audio_sink(gr.top_block):
- def __init__(self, src, port, pkt_size, sample_rate):
- gr.top_block.__init__(self, "audio_sink")
- src = gr.udp_source(gr.sizeof_float, src, port, pkt_size)
- dst = audio.sink(sample_rate)
- self.connect(src, dst)
-
-if __name__ == '__main__':
- parser = OptionParser(option_class=eng_option)
- parser.add_option("", "--src-name", type="string", default="localhost",
- help="local host name (domain name or IP address)")
- parser.add_option("", "--src-port", type="int", default=65500,
- help="port value to listen to for connection")
- parser.add_option("", "--packet-size", type="int", default=1472,
- help="packet size.")
- parser.add_option("-r", "--sample-rate", type="int", default=32000,
- help="audio signal sample rate [default=%default]")
- (options, args) = parser.parse_args()
- if len(args) != 0:
- parser.print_help()
- raise SystemExit, 1
-
- # Create an instance of a hierarchical block
- top_block = audio_sink(options.src_name, options.src_port,
- options.packet_size, options.sample_rate)
-
- try:
- # Run forever
- top_block.run()
- except KeyboardInterrupt:
- # Ctrl-C exits
- pass
-
+++ /dev/null
-#!/usr/bin/env python
-#
-# Copyright 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.
-#
-
-from gnuradio import gr, audio
-from gnuradio.eng_option import eng_option
-from optparse import OptionParser
-
-class audio_source(gr.top_block):
- def __init__(self, src, dst, port, pkt_size, sample_rate):
- gr.top_block.__init__(self, "audio_source")
- self.audio = audio.source(sample_rate)
- self.sink = gr.udp_sink(gr.sizeof_float, src, 0, dst, port, pkt_size)
- self.connect(self.audio, self.sink)
-
-if __name__ == '__main__':
- parser = OptionParser(option_class=eng_option)
- parser.add_option("", "--src-name", type="string", default="localhost",
- help="local host name (domain name or IP address)")
- parser.add_option("", "--dst-name", type="string", default="localhost",
- help="Remote host name (domain name or IP address")
- parser.add_option("", "--dst-port", type="int", default=65500,
- help="port value to connect to")
- parser.add_option("", "--packet-size", type="int", default=1472,
- help="packet size.")
- parser.add_option("-r", "--sample-rate", type="int", default=32000 ,
- help="audio signal sample rate [default=%default]")
- (options, args) = parser.parse_args()
- if len(args) != 0:
- parser.print_help()
- raise SystemExit, 1
-
- # Create an instance of a hierarchical block
- top_block = audio_source(options.src_name, options.dst_name, options.dst_port,
- options.packet_size, options.sample_rate)
-
- try:
- # Run forever
- top_block.run()
- except KeyboardInterrupt:
- # Ctrl-C exits
- pass
-
+++ /dev/null
-#!/usr/bin/env python
-#
-# Copyright 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.
-#
-
-from gnuradio import gr, audio
-from gnuradio.eng_option import eng_option
-from optparse import OptionParser
-
-class dial_tone_sink(gr.top_block):
- def __init__(self, src, port, pkt_size, sample_rate):
- gr.top_block.__init__(self, "dial_tone_sink")
- udp = gr.udp_source(gr.sizeof_float, src, port, pkt_size)
- sink = audio.sink(sample_rate)
- self.connect(udp, sink)
-
-if __name__ == '__main__':
- parser = OptionParser(option_class=eng_option)
- parser.add_option("", "--src-name", type="string", default="localhost",
- help="local host name (domain name or IP address)")
- parser.add_option("", "--src-port", type="int", default=65500,
- help="port value to listen to for connection")
- parser.add_option("", "--packet-size", type="int", default=1472,
- help="packet size.")
- parser.add_option("-r", "--sample-rate", type="int", default=8000,
- help="audio signal sample rate [default=%default]")
- (options, args) = parser.parse_args()
- if len(args) != 0:
- parser.print_help()
- raise SystemExit, 1
-
- # Create an instance of a hierarchical block
- top_block = dial_tone_sink(options.src_name, options.src_port,
- options.packet_size, options.sample_rate)
-
- try:
- # Run forever
- top_block.run()
- except KeyboardInterrupt:
- # Ctrl-C exits
- pass
-
+++ /dev/null
-#!/usr/bin/env python
-#
-# Copyright 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.
-#
-
-from gnuradio import gr
-from gnuradio.eng_option import eng_option
-from optparse import OptionParser
-
-class dial_tone_source(gr.top_block):
- def __init__(self, src, dst, port, pkt_size, sample_rate):
- gr.top_block.__init__(self, "dial_tone_source")
-
- amplitude = 0.3
- src0 = gr.sig_source_f (sample_rate, gr.GR_SIN_WAVE, 350, amplitude)
- src1 = gr.sig_source_f (sample_rate, gr.GR_SIN_WAVE, 440, amplitude)
- add = gr.add_ff()
-
- # Throttle needed here to account for the other side's audio card sampling rate
- thr = gr.throttle(gr.sizeof_float, sample_rate)
- sink = gr.udp_sink(gr.sizeof_float, src, 0, dst, port, pkt_size)
- self.connect(src0, (add, 0))
- self.connect(src1, (add, 1))
- self.connect(add, thr, sink)
-
-if __name__ == '__main__':
- parser = OptionParser(option_class=eng_option)
- parser.add_option("", "--src-name", type="string", default="localhost",
- help="local host name (domain name or IP address)")
- parser.add_option("", "--dst-name", type="string", default="localhost",
- help="Remote host name (domain name or IP address")
- parser.add_option("", "--dst-port", type="int", default=65500,
- help="port value to connect to")
- parser.add_option("", "--packet-size", type="int", default=1472,
- help="packet size.")
- parser.add_option("-r", "--sample-rate", type="int", default=8000,
- help="audio signal sample rate [default=%default]")
- (options, args) = parser.parse_args()
- if len(args) != 0:
- parser.print_help()
- raise SystemExit, 1
-
- # Create an instance of a hierarchical block
- top_block = dial_tone_source(options.src_name, options.dst_name, options.dst_port,
- options.packet_size, options.sample_rate)
-
- try:
- # Run forever
- top_block.run()
- except KeyboardInterrupt:
- # Ctrl-C exits
- pass
-
+++ /dev/null
-#!/usr/bin/env python
-#
-# Copyright 2006 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.eng_option import eng_option
-from optparse import OptionParser
-
-class vector_sink(gr.top_block):
- def __init__(self, src, port, pkt_size):
- gr.top_block.__init__(self, "vector_sink")
-
- udp = gr.udp_source(gr.sizeof_float, src, port, pkt_size)
- sink = gr.file_sink(gr.sizeof_float, "received.dat")
- self.connect(udp, sink)
-
-if __name__ == "__main__":
- parser = OptionParser(option_class=eng_option)
- parser.add_option("", "--src-name", type="string", default="localhost",
- help="local host name (domain name or IP address)")
- parser.add_option("", "--src-port", type="int", default=65500,
- help="port value to listen to for connection")
- parser.add_option("", "--packet-size", type="int", default=1471,
- help="packet size.")
- (options, args) = parser.parse_args()
- if len(args) != 0:
- parser.print_help()
- raise SystemExit, 1
-
- # Create an instance of a hierarchical block
- top_block = vector_sink(options.src_name, options.src_port, options.packet_size)
-
- try:
- # Run forever
- top_block.run()
- except KeyboardInterrupt:
- # Ctrl-C exits
- pass
-
+++ /dev/null
-#!/usr/bin/env python
-#
-# Copyright 2006 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.eng_option import eng_option
-from optparse import OptionParser
-
-class vector_source(gr.top_block):
- def __init__(self, src, dst, port, pkt_size):
- gr.top_block.__init__(self, "vector_source")
- data = [i*0.01 for i in range(1000)]
- vec = gr.vector_source_f(data, True)
- udp = gr.udp_sink(gr.sizeof_float, src, 0, dst, port, pkt_size)
- self.connect(vec, udp)
-
-if __name__ == '__main__':
- parser = OptionParser(option_class=eng_option)
- parser.add_option("", "--src-name", type="string", default="localhost",
- help="local host name (domain name or IP address)")
- parser.add_option("", "--dst-name", type="string", default="localhost",
- help="Remote host name (domain name or IP address")
- parser.add_option("", "--dst-port", type="int", default=65500,
- help="port value to connect to")
- parser.add_option("", "--packet-size", type="int", default=1471,
- help="packet size.")
- (options, args) = parser.parse_args()
- if len(args) != 0:
- parser.print_help()
- raise SystemExit, 1
-
-# Create an instance of a hierarchical block
- top_block = vector_source(options.src_name, options.dst_name,
- options.dst_port, options.packet_size)
-
- try:
- # Run forever
- top_block.run()
- except KeyboardInterrupt:
- # Ctrl-C exits
- pass
-
+++ /dev/null
-#
-# Copyright 2006 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.
-#
-
-EXTRA_DIST =
\ No newline at end of file
+++ /dev/null
-#
-# Copyright 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.
-#
-
-EXTRA_DIST = \
- usrp_sounder_rx.py \
- usrp_sounder_tx.py \
- usrp_source.py \
- usrp_sink.py \
- sounder_rx.py \
- sounder_tx.py
-
-MOSTLYCLEANFILES = *.pyc *~ *.dat
+++ /dev/null
-#!/usr/bin/env python
-#
-# Copyright 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.
-#
-
-from gnuradio import gr, usrp, eng_notation
-from usrp_source import usrp_source_c
-import math
-
-n2s = eng_notation.num_to_str
-
-class sounder_rx(gr.hier_block2):
- """
- Creates a channel sounder receiver block with the given parameters.
- """
-
- def __init__(self, chip_rate, degree, verbose):
-
- # Call hierarchical block constructor
- # Top-level blocks have no inputs or outputs
- gr.hier_block2.__init__(self,
- "sounder_rx", # Block typename
- gr.io_signature(1, 1, gr.sizeof_gr_complex), # Input signature
- gr.io_signature(1, 1, gr.sizeof_gr_complex)) # Output signature
-
- self._degree = degree
- self._chip_rate = chip_rate
- self._verbose = verbose
- self._length = 2**self._degree-1
- self._rep_rate = self._chip_rate/float(self._length)
-
- if self._verbose:
- print "Using PN sequence of degree", self._degree, "length", self._length
- print "Sequence repetition rate is", n2s(self._rep_rate), "per sec"
-
- self.connect(self, gr.pn_correlator_cc(self._degree), self)
+++ /dev/null
-#!/usr/bin/env python
-#
-# Copyright 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.
-#
-
-from gnuradio import gr, usrp, eng_notation
-import math
-
-n2s = eng_notation.num_to_str
-
-class sounder_tx(gr.hier_block2):
- """
- Creates a channel sounder generator with the given parameters.
- """
-
- def __init__(self, degree, chip_rate, verbose):
- gr.hier_block2.__init__(self,
- "sounder_tx", # Block typename
- gr.io_signature(0,0,0), # Input signature
- gr.io_signature(1, 1, gr.sizeof_float)) # Output signature
-
- self._degree = degree
- self._chip_rate = chip_rate
- self._verbose = verbose
- self._length = 2**degree-1
-
- # Connect PN source to block output
- self.connect(gr.glfsr_source_f(degree), self)
+++ /dev/null
-#!/usr/bin/env python
-#
-# Copyright 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.
-#
-
-from gnuradio import gr, usrp, eng_notation
-n2s = eng_notation.num_to_str
-
-# Hierarchical block implementing a USRP sink for complex floats,
-# with convenience functions for tuning, interpolation, etc.
-#
-class usrp_sink_c(gr.hier_block2):
- """
- Create a USRP sink object accepting complex floats.
- """
- def __init__(self, which=0, subdev_spec=None, if_rate=None,
- freq=0.0, calibration=0.0, verbose=False):
- # Call hierarchical block constructor
- gr.hier_block2.__init__(self,
- "usrp_sink_c", # Block typename
- gr.io_signature(1,1,gr.sizeof_gr_complex), # Input signature
- gr.io_signature(0,0,0)) # Output signature
-
- self._verbose = verbose
- self._u = usrp.sink_c(which)
- if self._verbose:
- print 'DAC sample rate is', n2s(self._u.dac_rate()), "sps"
- self.set_subdev(subdev_spec)
- self.set_if_rate(if_rate)
- self.set_calibration(calibration)
- self.tune(freq)
- self.connect(self, self._u)
-
- def set_subdev(self, subdev_spec):
- if subdev_spec is None:
- subdev_spec = self.pick_subdevice()
- self._subdev = usrp.selected_subdev(self._u, subdev_spec)
- self._u.set_mux(usrp.determine_tx_mux_value(self._u, subdev_spec))
- if self._verbose:
- print 'TX using', self._subdev.name(), 'daughterboard'
-
- def pick_subdevice(self):
- """
- The user didn't specify a subdevice.
- If there's a daughterboard on A, select A.
- If there's a daughterboard on B, select B.
- Otherwise, select A.
- """
- if self._u.db[0][0].dbid() >= 0: # dbid is < 0 if there's no d'board or a problem
- return (0, 0)
- if self._u.db[1][0].dbid() >= 0:
- return (1, 0)
- return (0, 0)
-
- def set_if_rate(self, if_rate):
- # If no IF rate specified, set to maximum interpolation
- if if_rate is None:
- self._interp = 512
- else:
- self._interp = 4*int(self._u.dac_rate()/(4.0*if_rate)+0.5)
-
-
- self._if_rate = self._u.dac_rate()/self._interp
- self._u.set_interp_rate(self._interp)
-
- if self._verbose:
- print "USRP interpolation rate is", self._interp
- print "USRP IF rate is", n2s(self._if_rate), "sps"
-
- def set_calibration(self, calibration):
- self._cal = calibration
- if self._verbose:
- print "Using frequency calibration offset of", n2s(calibration), "Hz"
-
- def tune(self, freq):
- """
- Set the center frequency we're interested in.
-
- @param target_freq: frequency in Hz
- @type: bool
-
- Tuning is a two step process. First we ask the front-end to
- tune as close to the desired frequency as it can. Then we use
- the result of that operation and our target_frequency to
- determine the value for the digital down converter.
- """
- self._tune_result = self._u.tune(self._subdev._which, self._subdev, freq+self._cal)
- if self._tune_result:
- if self._verbose:
- print "Baseband frequency is", n2s(self._tune_result.baseband_freq), "Hz"
- print "DXC frequency is", n2s(self._tune_result.dxc_freq), "Hz"
- print "Center frequency is", n2s(freq), "Hz"
- print "Residual frequency is", n2s(self._tune_result.residual_freq), "Hz"
- return True
-
- return False
-
-if __name__ == '__main__':
- sink = usrp_sink_c(verbose=True)
-
+++ /dev/null
-#!/usr/bin/env python
-#
-# Copyright 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.
-#
-
-from gnuradio import gr, eng_notation
-from gnuradio.eng_option import eng_option
-from optparse import OptionParser
-from usrp_source import usrp_source_c
-from sounder_rx import sounder_rx
-
-n2s = eng_notation.num_to_str
-
-class usrp_sounder_rx(gr.top_block):
- def __init__(self, options):
- gr.top_block.__init__(self, "usrp_sounder_rx")
- self._options = options
- self._u = usrp_source_c(0,
- self._options.rx_subdev_spec,
- self._options.gain,
- self._options.chip_rate,
- self._options.freq,
- self._options.cal,
- self._options.verbose)
- self._options.chip_rate = self._u._if_rate
- self._length = 2**self._options.degree-1
- self._receiver = sounder_rx(self._options.chip_rate,
- self._options.degree,
- self._options.verbose)
-
- samples = 100 * self._length**2
-
- head = gr.head(gr.sizeof_gr_complex, samples)
- c2m = gr.complex_to_mag()
- s2v = gr.stream_to_vector(gr.sizeof_float, self._length)
- lpf = gr.single_pole_iir_filter_ff(self._options.alpha, self._length)
- v2s = gr.vector_to_stream(gr.sizeof_float, self._length)
- sink = gr.file_sink(gr.sizeof_float, "impulse.dat")
-
- self.connect(self._u, head, self._receiver, c2m, s2v, lpf, v2s, sink)
-
- if self._options.verbose:
- print "Chip rate is", n2s(self._options.chip_rate), "chips/sec"
- print "Resolution is", n2s(1.0/self._options.chip_rate), "sec"
- print "Using PN code of degree", self._options.degree
-
-def main():
- parser = OptionParser(option_class=eng_option)
- parser.add_option("-R", "--rx-subdev-spec", type="subdev", default=None,
- help="select USRP Rx side A or B (default=first found)")
- parser.add_option("-f", "--freq", type="eng_float", default=0.0,
- help="set center frequency (default=%default)")
- parser.add_option("-c", "--cal", type="eng_float", default=0.0,
- help="set frequency calibration offset (default=%default)")
- parser.add_option("-v", "--verbose", action="store_true", default=False,
- help="print extra debugging info")
- parser.add_option("-d", "--degree", type="int", default=10,
- help="set PN code degree (length=2**degree-1, default=%default)")
- parser.add_option("-r", "--chip-rate", type="eng_float", default=8e6,
- help="set sounder chip rate (default=%default)")
- parser.add_option("-g", "--gain", type="eng_float", default=None,
- help="set receiver gain (default=%default)")
- parser.add_option("", "--alpha", type="eng_float", default=1.0,
- help="set smoothing constant (default=%default)")
- (options, args) = parser.parse_args()
- if len(args) != 0:
- parser.print_help()
- sys.exit(1)
-
- top_block = usrp_sounder_rx(options)
-
- try:
- top_block.run()
- except KeyboardInterrupt:
- pass
-
-if __name__ == '__main__':
- main ()
+++ /dev/null
-#!/usr/bin/env python
-#
-# Copyright 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.
-#
-
-from gnuradio import gr, eng_notation
-from gnuradio.eng_option import eng_option
-from optparse import OptionParser
-from usrp_sink import usrp_sink_c
-from sounder_tx import sounder_tx
-
-n2s = eng_notation.num_to_str
-
-class usrp_sounder_tx(gr.top_block):
- def __init__(self, subdev_spec, freq, cal, verbose, degree, chip_rate, amplitude):
-
- # Call hierarchical block constructor
- # Top-level blocks have no inputs or outputs
- gr.top_block.__init__(self, "usrp_sounder_tx")
- self._freq = freq
- self._cal = cal
- self._verbose = verbose
- self._degree = degree
- self._length = 2**degree-1
- self._amplitude = amplitude
-
- self._u = usrp_sink_c(0, subdev_spec, chip_rate, self._freq, self._cal, self._verbose)
- self._chip_rate = self._u._if_rate
- self._max_time = float(self._length)/self._chip_rate
- self._pn = sounder_tx(self._degree, self._chip_rate, self._verbose)
- self._gain = gr.multiply_const_ff(amplitude)
- self._f2c = gr.float_to_complex()
- self.connect(self._pn, self._gain, self._f2c, self._u)
-
- if self._verbose:
- print "Chip rate is", n2s(self._chip_rate), "chips/sec"
- print "Resolution is", n2s(1.0/self._chip_rate), "sec"
- print "Using PN code of degree", self._degree, "length", 2**self._degree-1
- print "Maximum measurable impulse response is", n2s(self._max_time), "sec"
- print "Output amplitude is", amplitude
-
-
-def main():
- parser = OptionParser(option_class=eng_option)
-
- # Transmit path options
- parser.add_option("-T", "--tx-subdev-spec", type="subdev", default=None,
- help="select USRP Rx side A or B (default=first found)")
- parser.add_option("-f", "--freq", type="eng_float", default=0.0,
- help="set center frequency (default=%default)")
- parser.add_option("-c", "--cal", type="eng_float", default=0.0,
- help="set frequency calibration offset (default=%default)")
- parser.add_option("-v", "--verbose", action="store_true", default=False,
- help="print extra debugging info")
- parser.add_option("-d", "--degree", type="int", default=10,
- help="set PN code degree (length=2**degree-1, default=%default)")
- parser.add_option("-r", "--chip-rate", type="eng_float", default=8e6,
- help="set sounder chip rate (default=%default)")
- parser.add_option("-g", "--amplitude", type="eng_float", default=8000.0,
- help="set output amplitude (default=%default)")
- parser.add_option("", "--real-time", action="store_true", default=False,
- help="Attempt to enable real-time scheduling")
- (options, args) = parser.parse_args()
-
- if len(args) != 0:
- parser.print_help()
- sys.exit(1)
-
- if not options.real_time:
- realtime = False
- else:
- # Attempt to enable realtime scheduling
- r = gr.enable_realtime_scheduling()
- if r == gr.RT_OK:
- realtime = True
- else:
- realtime = False
- print "Note: failed to enable realtime scheduling"
-
- # Create an instance of a hierarchical block
- top_block = usrp_sounder_tx(options.tx_subdev_spec, options.freq, options.cal,
- options.verbose, options.degree, options.chip_rate,
- options.amplitude)
-
- try:
- # Run forever
- top_block.run()
- except KeyboardInterrupt:
- # Ctrl-C exits
- pass
-
-if __name__ == '__main__':
- main ()
+++ /dev/null
-#!/usr/bin/env python
-#
-# Copyright 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.
-#
-
-from gnuradio import gr, usrp, eng_notation
-n2s = eng_notation.num_to_str
-
-# Hierarchical block implementing a USRP source for complex floats,
-# with convenience functions for gain, tune, decimation, etc.
-#
-class usrp_source_c(gr.hier_block2):
- """
- Create a USRP source object supplying complex floats.
- """
- def __init__(self, which=0, subdev_spec=None, gain=None, if_rate=None,
- freq=0.0, calibration=0.0, verbose=False):
- # Call hierarchical block constructor
- gr.hier_block2.__init__(self,
- "usrp_source_c", # Block typename
- gr.io_signature(0,0,0), # Input signature
- gr.io_signature(1,1,gr.sizeof_gr_complex)) # Output signature
-
- self._verbose = verbose
- self._u = usrp.source_c(which)
- if self._verbose:
- print 'ADC sample rate is', n2s(self._u.adc_rate()), "sps"
- self.set_subdev(subdev_spec)
- self.set_if_rate(if_rate)
- self.set_gain(gain)
- self.set_calibration(calibration)
- self.tune(freq)
- self.connect(self._u, self)
-
- def set_subdev(self, subdev_spec):
- if subdev_spec is None:
- subdev_spec = self.pick_subdevice()
- self._subdev = usrp.selected_subdev(self._u, subdev_spec)
- self._u.set_mux(usrp.determine_rx_mux_value(self._u, subdev_spec))
- if self._verbose:
- print 'RX using', self._subdev.name(), 'daughterboard'
-
- def pick_subdevice(self):
- """
- The user didn't specify a subdevice.
- If there's a daughterboard on A, select A.
- If there's a daughterboard on B, select B.
- Otherwise, select A.
- """
- if self._u.db[0][0].dbid() >= 0: # dbid is < 0 if there's no d'board or a problem
- return (0, 0)
- if self._u.db[1][0].dbid() >= 0:
- return (1, 0)
- return (0, 0)
-
- def set_if_rate(self, if_rate):
- # If no IF rate specified, set to maximum decimation
- if if_rate is None:
- self._decim = 256
- else:
- self._decim = int(self._u.adc_rate()/if_rate)
-
- self._u.set_decim_rate(self._decim)
- self._if_rate = self._u.adc_rate()/self._decim
-
- if self._verbose:
- print "USRP decimation rate is", self._decim
- print "USRP IF rate is", n2s(self._if_rate), "sps"
-
- def set_gain(self, gain):
- # If no gain specified, set to midrange
- if gain is None:
- g = self._subdev.gain_range()
- gain = (g[0]+g[1])/2.0
- self._gain = gain
- self._subdev.set_gain(self._gain)
- if self._verbose:
- print "USRP gain set to", self._gain
-
- def set_calibration(self, calibration):
- self._cal = calibration
- if self._verbose:
- print "Using frequency calibration offset of", n2s(calibration), "Hz"
-
- def tune(self, freq):
- """
- Set the center frequency we're interested in.
-
- @param target_freq: frequency in Hz
- @type: bool
-
- Tuning is a two step process. First we ask the front-end to
- tune as close to the desired frequency as it can. Then we use
- the result of that operation and our target_frequency to
- determine the value for the digital down converter.
- """
- self._tune_result = usrp.tune(self._u, 0, self._subdev, freq+self._cal)
- if self._tune_result:
- if self._verbose:
- print "Baseband frequency is", n2s(self._tune_result.baseband_freq), "Hz"
- print "DXC frequency is", n2s(self._tune_result.dxc_freq), "Hz"
- print "Center frequency is", n2s(freq), "Hz"
- print "Residual frequency is", n2s(self._tune_result.residual_freq), "Hz"
- return True
-
- return False
-
-if __name__ == '__main__':
- src = usrp_source_c(verbose=True)
+++ /dev/null
-#
-# Copyright 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.
-#
-
-EXTRA_DIST = \
- usrp_fft.py \
- usrp_siggen.py
-
-MOSTLYCLEANFILES = *.pyc *~
+++ /dev/null
-#!/usr/bin/env python
-#
-# Copyright 2004,2005,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.
-#
-
-from gnuradio import gr, gru
-from gnuradio import usrp
-from gnuradio import eng_notation
-from gnuradio.eng_option import eng_option
-from gnuradio.wxgui import stdgui2, fftsink2, waterfallsink2, scopesink2, form, slider
-from optparse import OptionParser
-import wx
-import sys
-
-
-def pick_subdevice(u):
- """
- The user didn't specify a subdevice on the command line.
- If there's a daughterboard on A, select A.
- If there's a daughterboard on B, select B.
- Otherwise, select A.
- """
- if u.db[0][0].dbid() >= 0: # dbid is < 0 if there's no d'board or a problem
- return (0, 0)
- if u.db[1][0].dbid() >= 0:
- return (1, 0)
- return (0, 0)
-
-
-class app_top_block(stdgui2.std_top_block):
- def __init__(self, frame, panel, vbox, argv):
- stdgui2.std_top_block.__init__(self, frame, panel, vbox, argv)
-
- self.frame = frame
- self.panel = panel
-
- parser = OptionParser(option_class=eng_option)
- parser.add_option("-R", "--rx-subdev-spec", type="subdev", default=None,
- help="select USRP Rx side A or B (default=first one with a daughterboard)")
- parser.add_option("-d", "--decim", type="int", default=16,
- help="set fgpa decimation rate to DECIM [default=%default]")
- parser.add_option("-f", "--freq", type="eng_float", default=None,
- help="set frequency to FREQ", metavar="FREQ")
- parser.add_option("-g", "--gain", type="eng_float", default=None,
- help="set gain in dB (default is midpoint)")
- parser.add_option("-W", "--waterfall", action="store_true", default=False,
- help="Enable waterfall display")
- parser.add_option("-8", "--width-8", action="store_true", default=False,
- help="Enable 8-bit samples across USB")
- parser.add_option("-S", "--oscilloscope", action="store_true", default=False,
- help="Enable oscilloscope display")
- (options, args) = parser.parse_args()
- if len(args) != 0:
- parser.print_help()
- sys.exit(1)
-
- self.show_debug_info = True
-
- self.u = usrp.source_c(decim_rate=options.decim)
- if options.rx_subdev_spec is None:
- options.rx_subdev_spec = pick_subdevice(self.u)
- self.u.set_mux(usrp.determine_rx_mux_value(self.u, options.rx_subdev_spec))
-
- if options.width_8:
- width = 8
- shift = 8
- format = self.u.make_format(width, shift)
- print "format =", hex(format)
- r = self.u.set_format(format)
- print "set_format =", r
-
- # determine the daughterboard subdevice we're using
- self.subdev = usrp.selected_subdev(self.u, options.rx_subdev_spec)
-
- input_rate = self.u.adc_freq() / self.u.decim_rate()
-
-
- if options.waterfall:
- self.scope = waterfallsink2.waterfall_sink_c (panel, fft_size=1024, sample_rate=input_rate)
- elif options.oscilloscope:
- self.scope = scopesink2.scope_sink_c(panel, sample_rate=input_rate)
- else:
- self.scope = fftsink2.fft_sink_c (panel, fft_size=1024, sample_rate=input_rate)
-
- self.connect(self.u, self.scope)
-
- self._build_gui(vbox)
-
- # set initial values
-
- if options.gain is None:
- # if no gain was specified, use the mid-point in dB
- g = self.subdev.gain_range()
- options.gain = float(g[0]+g[1])/2
-
- if options.freq is None:
- # if no freq was specified, use the mid-point
- r = self.subdev.freq_range()
- options.freq = float(r[0]+r[1])/2
-
- self.set_gain(options.gain)
-
- if self.show_debug_info:
- self.myform['decim'].set_value(self.u.decim_rate())
- self.myform['fs@usb'].set_value(self.u.adc_freq() / self.u.decim_rate())
- self.myform['dbname'].set_value(self.subdev.name())
- self.myform['baseband'].set_value(0)
- self.myform['ddc'].set_value(0)
-
- if not(self.set_freq(options.freq)):
- self._set_status_msg("Failed to set initial frequency")
-
- def _set_status_msg(self, msg):
- self.frame.GetStatusBar().SetStatusText(msg, 0)
-
- def _build_gui(self, vbox):
-
- def _form_set_freq(kv):
- return self.set_freq(kv['freq'])
-
- vbox.Add(self.scope.win, 10, wx.EXPAND)
-
- # add control area at the bottom
- self.myform = myform = form.form()
- hbox = wx.BoxSizer(wx.HORIZONTAL)
- hbox.Add((5,0), 0, 0)
- myform['freq'] = form.float_field(
- parent=self.panel, sizer=hbox, label="Center freq", weight=1,
- callback=myform.check_input_and_call(_form_set_freq, self._set_status_msg))
-
- hbox.Add((5,0), 0, 0)
- g = self.subdev.gain_range()
- myform['gain'] = form.slider_field(parent=self.panel, sizer=hbox, label="Gain",
- weight=3,
- min=int(g[0]), max=int(g[1]),
- callback=self.set_gain)
-
- hbox.Add((5,0), 0, 0)
- vbox.Add(hbox, 0, wx.EXPAND)
-
- self._build_subpanel(vbox)
-
- def _build_subpanel(self, vbox_arg):
- # build a secondary information panel (sometimes hidden)
-
- # FIXME figure out how to have this be a subpanel that is always
- # created, but has its visibility controlled by foo.Show(True/False)
-
- def _form_set_decim(kv):
- return self.set_decim(kv['decim'])
-
- if not(self.show_debug_info):
- return
-
- panel = self.panel
- vbox = vbox_arg
- myform = self.myform
-
- #panel = wx.Panel(self.panel, -1)
- #vbox = wx.BoxSizer(wx.VERTICAL)
-
- hbox = wx.BoxSizer(wx.HORIZONTAL)
- hbox.Add((5,0), 0)
-
- myform['decim'] = form.int_field(
- parent=panel, sizer=hbox, label="Decim",
- callback=myform.check_input_and_call(_form_set_decim, self._set_status_msg))
-
- hbox.Add((5,0), 1)
- myform['fs@usb'] = form.static_float_field(
- parent=panel, sizer=hbox, label="Fs@USB")
-
- hbox.Add((5,0), 1)
- myform['dbname'] = form.static_text_field(
- parent=panel, sizer=hbox)
-
- hbox.Add((5,0), 1)
- myform['baseband'] = form.static_float_field(
- parent=panel, sizer=hbox, label="Analog BB")
-
- hbox.Add((5,0), 1)
- myform['ddc'] = form.static_float_field(
- parent=panel, sizer=hbox, label="DDC")
-
- hbox.Add((5,0), 0)
- vbox.Add(hbox, 0, wx.EXPAND)
-
-
- def set_freq(self, target_freq):
- """
- Set the center frequency we're interested in.
-
- @param target_freq: frequency in Hz
- @rypte: bool
-
- Tuning is a two step process. First we ask the front-end to
- tune as close to the desired frequency as it can. Then we use
- the result of that operation and our target_frequency to
- determine the value for the digital down converter.
- """
- r = self.u.tune(0, self.subdev, target_freq)
-
- if r:
- self.myform['freq'].set_value(target_freq) # update displayed value
- if self.show_debug_info:
- self.myform['baseband'].set_value(r.baseband_freq)
- self.myform['ddc'].set_value(r.dxc_freq)
- return True
-
- return False
-
- def set_gain(self, gain):
- self.myform['gain'].set_value(gain) # update displayed value
- self.subdev.set_gain(gain)
-
- def set_decim(self, decim):
- ok = self.u.set_decim_rate(decim)
- if not ok:
- print "set_decim failed"
- input_rate = self.u.adc_freq() / self.u.decim_rate()
- self.scope.set_sample_rate(input_rate)
- if self.show_debug_info: # update displayed values
- self.myform['decim'].set_value(self.u.decim_rate())
- self.myform['fs@usb'].set_value(self.u.adc_freq() / self.u.decim_rate())
- return ok
-
-def main ():
- app = stdgui2.stdapp(app_top_block, "USRP FFT", nstatus=1)
- app.MainLoop()
-
-if __name__ == '__main__':
- main ()
+++ /dev/null
-#!/usr/bin/env python
-
-from gnuradio import gr, gru
-from gnuradio import usrp
-from gnuradio.eng_option import eng_option
-from gnuradio import eng_notation
-from optparse import OptionParser
-import sys
-
-class my_graph(gr.top_block):
- def __init__ (self, type, ampl, wfreq, offset, subdev_spec, interp, rf_freq):
- gr.top_block.__init__(self, "usrp_siggen")
-
- # controllable values
- self.interp = interp
- self.waveform_type = type
- self.waveform_ampl = ampl
- self.waveform_freq = wfreq
- self.waveform_offset = offset
-
- self.u = usrp.sink_c (0, self.interp)
-
- # determine the daughterboard subdevice we're using
- if subdev_spec is None:
- ubdev_spec = usrp.pick_tx_subdevice(self.u)
- m = usrp.determine_tx_mux_value(self.u, subdev_spec)
- self.u.set_mux(m)
- self.subdev = usrp.selected_subdev(self.u, subdev_spec)
- self.subdev.set_gain(self.subdev.gain_range()[1]) # set max Tx gain
- self.subdev.set_enable(True) # enable transmitter
- print "Using TX d'board %s" % (self.subdev.side_and_name(),)
-
- if not self.set_freq(rf_freq):
- sys.stderr.write('Failed to set RF frequency\n')
- raise SystemExit
-
- if type == gr.GR_SIN_WAVE or type == gr.GR_CONST_WAVE:
- self.src = gr.sig_source_c (self.usb_freq (),
- gr.GR_SIN_WAVE,
- self.waveform_freq,
- self.waveform_ampl,
- self.waveform_offset)
-
- elif type == gr.GR_UNIFORM or type == gr.GR_GAUSSIAN:
- self.src = gr.noise_source_c (gr.GR_UNIFORM,
- self.waveform_ampl)
-
- else:
- raise ValueError, type
-
- self.connect (self.src, self.u)
-
-
- def usb_freq (self):
- return self.u.dac_freq() / self.interp
-
- def usb_throughput (self):
- return self.usb_freq () * 4
-
- def set_freq(self, target_freq):
- """
- Set the center frequency we're interested in.
-
- @param target_freq: frequency in Hz
- @rypte: bool
-
- Tuning is a two step process. First we ask the front-end to
- tune as close to the desired frequency as it can. Then we use
- the result of that operation and our target_frequency to
- determine the value for the digital up converter.
- """
- r = self.u.tune(self.subdev._which, self.subdev, target_freq)
- if r:
- #print "r.baseband_freq =", eng_notation.num_to_str(r.baseband_freq)
- #print "r.dxc_freq =", eng_notation.num_to_str(r.dxc_freq)
- #print "r.residual_freq =", eng_notation.num_to_str(r.residual_freq)
- #print "r.inverted =", r.inverted
- return True
-
- return False
-
-
-
-def main ():
- parser = OptionParser (option_class=eng_option)
- parser.add_option ("-T", "--tx-subdev-spec", type="subdev", default=(0, 0),
- help="select USRP Tx side A or B")
- parser.add_option ("-f", "--rf-freq", type="eng_float", default=None,
- help="set RF center frequency to FREQ")
- parser.add_option ("-i", "--interp", type="int", default=64,
- help="set fgpa interpolation rate to INTERP [default=%default]")
-
- parser.add_option ("--sine", dest="type", action="store_const", const=gr.GR_SIN_WAVE,
- help="generate a complex sinusoid [default]", default=gr.GR_SIN_WAVE)
- parser.add_option ("--const", dest="type", action="store_const", const=gr.GR_CONST_WAVE,
- help="generate a constant output")
- parser.add_option ("--gaussian", dest="type", action="store_const", const=gr.GR_GAUSSIAN,
- help="generate Gaussian random output")
- parser.add_option ("--uniform", dest="type", action="store_const", const=gr.GR_UNIFORM,
- help="generate Uniform random output")
-
- parser.add_option ("-w", "--waveform-freq", type="eng_float", default=100e3,
- help="set waveform frequency to FREQ [default=%default]")
- parser.add_option ("-a", "--amplitude", type="eng_float", default=16e3,
- help="set waveform amplitude to AMPLITUDE [default=%default]", metavar="AMPL")
- parser.add_option ("-o", "--offset", type="eng_float", default=0,
- help="set waveform offset to OFFSET [default=%default]")
- (options, args) = parser.parse_args ()
-
- if len(args) != 0:
- parser.print_help()
- raise SystemExit
-
- if options.rf_freq is None:
- sys.stderr.write("usrp_siggen: must specify RF center frequency with -f RF_FREQ\n")
- parser.print_help()
- raise SystemExit
-
- top_block = my_graph(options.type, options.amplitude, options.waveform_freq, options.offset,
- options.tx_subdev_spec, options.interp, options.rf_freq)
-
- try:
- # Run forever
- top_block.run()
- except KeyboardInterrupt:
- # Ctrl-C exits
- pass
-
-if __name__ == '__main__':
- main ()
--- /dev/null
+#
+# Copyright 2006 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.
+#
+
+EXTRA_DIST = \
+ measurement_slave.py
\ No newline at end of file
--- /dev/null
+#!/usr/bin/env python
+#
+# Copyright 2006 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.
+#
+
+import struct
+import socket
+import asyncore
+import sys
+import optparse
+import random
+from gnuradio.eng_option import eng_option
+import gnuradio.gr.gr_threading as _threading
+
+LOOP_TIMEOUT = 0.001
+BROADCAST_ADDR = '255.255.255.255'
+
+BROADCAST_PORT = 27010 # UDP
+CONTROL_PORT = 27011 # TCP
+
+PKT_HEADER_SIZE = 4 # 32-bit int
+
+logfile = None
+
+def unpack_header(s):
+ (len,) = struct.unpack('!i', s)
+ return (len,)
+
+def pack_header(len):
+ return struct.pack('!i', len)
+
+
+class control_port_listener(asyncore.dispatcher):
+ def __init__(self, port=CONTROL_PORT, udp_socket=None, verbose=False):
+ """
+ @param port: TCP port to listen on.
+ @type port: int
+ """
+ asyncore.dispatcher.__init__(self)
+
+ self._verbose = verbose
+ self._udp_socket = udp_socket
+
+ host = '' # symbolic name for localhost
+ self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
+ self.set_reuse_addr()
+
+ try:
+ self.bind((host, port))
+ except socket.error, err:
+ sys.stderr.write('Failed to bind to %s: %s\n' %
+ ((host, port), os.strerror (err.args[0]),))
+ sys.exit(1)
+
+ self.listen(3)
+
+ def handle_accept(self):
+ socket, addr = self.accept()
+ sys.stderr.write("handle_accept: %r\n" % (addr,))
+ if not(socket is None):
+ # instantiate a server
+ s = control_server(socket, addr, self._udp_socket, self._verbose)
+
+
+class gr_dispatcher(asyncore.dispatcher):
+ def __init__(self, sock=None, map=None):
+ asyncore.dispatcher.__init__(self, sock=sock, map=map)
+
+ def read_packet(self):
+ """
+ Returns None or packet
+ """
+ s = self.recvall(PKT_HEADER_SIZE)
+ if s == '':
+ return None
+
+ (payload_len,) = unpack_header(s)
+
+ payload_len = int(payload_len)
+
+ if payload_len == 0:
+ payload = ''
+ else:
+ payload = self.recvall(payload_len)
+ if len(payload) != payload_len:
+ sys.stderr.write ('short recv, expected %d bytes, got %d\n' % (
+ payload_len, len(payload)))
+ raise RuntimeError, "short recv"
+
+ return payload
+
+ def recvall(self, buffer_size):
+ result = ''
+ while len(result) < buffer_size:
+ data = self.recv(buffer_size - len(result))
+ if not data:
+ return ''
+ result += data
+ return result
+
+
+class pkt_receiver_thread(_threading.Thread):
+ def __init__(self, socket):
+ _threading.Thread.__init__(self)
+ self.setDaemon(1)
+ self.socket = socket
+ self.keep_running = True
+ self.start()
+
+ def run(self):
+ while self.keep_running:
+ pkt, sender = self.socket.recvfrom(10000)
+ if pkt:
+ if len(pkt) > 2:
+ t = struct.unpack('!H', pkt[0:2])
+ seqno = t[0]
+ else:
+ seqno = -1
+
+ logfile.write('RCVD seqno %4d len %4d from %s\n' % (seqno, len(pkt), sender))
+ logfile.flush()
+
+
+class control_server(gr_dispatcher):
+ def __init__(self, socket, addr, udp_socket, verbose=False):
+ gr_dispatcher.__init__(self, sock=socket)
+
+ self._udp_socket = udp_socket
+ self.verbose = verbose
+ self.setblocking(1)
+
+ def writable(self):
+ return False
+
+ def handle_read(self):
+ pkt = self.read_packet()
+ if pkt:
+ annotate = 'ANNOTATE'
+ if pkt.startswith(annotate):
+ logfile.write(pkt[len(annotate)+1:])
+ logfile.write('\n')
+ logfile.flush()
+ elif pkt.startswith('SEND'):
+ tokens = pkt.split()
+ if len(tokens) < 4:
+ invalid_packet(pkt)
+ else:
+ npkts = int(tokens[1])
+ size = int(tokens[2])
+ power = float(tokens[3])
+ send_test_packets(self._udp_socket, npkts, size, power)
+ else:
+ invalid_packet(pkt)
+
+ def handle_close(self):
+ self.close()
+
+
+def invalid_packet(pkt):
+ sys.stderr.write('received unrecognized packet: %s\n' % (pkt,))
+
+
+def make_random_payload(size):
+ p = [0] * size
+ if 1:
+ for i in range(size):
+ p[i] = chr(random.randint(0, 255))
+ else:
+ for i in range(size):
+ p[i] = chr(i % 256)
+ return ''.join(p)
+
+
+def send_test_packets(udp_socket, npkts, size, power):
+ # we ignore power for now...
+ size = max(2, size)
+ payload = make_random_payload(size - 2)
+ for n in range(npkts):
+ pkt = struct.pack('!H', n) + payload
+ udp_socket.sendto(pkt, (BROADCAST_ADDR, BROADCAST_PORT))
+ #udp_socket.sendall(pkt)
+
+
+def open_udp_broadcast_socket(gr0_host_ip, port):
+ s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
+# s.bind((gr0_host_ip, port))
+ s.bind(('', port))
+ s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
+# s.connect((BROADCAST_ADDR, port))
+ return s
+
+
+def main():
+ global logfile
+
+ usage = 'usage: %prog [options] gr0-ip-addr'
+ parser = optparse.OptionParser (option_class=eng_option, usage=usage)
+ parser.add_option('-l', '--logfile', type='string', default=None,
+ help="specify log file name [default=<stdout>]")
+ parser.add_option('-v', '--verbose', action="store_true", default=False,
+ help="enable verbose diagnostics")
+
+ (options, args) = parser.parse_args ()
+ if len(args) != 1:
+ parser.print_help()
+ sys.exit(1)
+
+ gr0_ip_addr = args[0]
+ if options.logfile is None:
+ logfile = sys.stdout
+ else:
+ logfile = file(options.logfile, 'w')
+
+ udp_socket = open_udp_broadcast_socket(gr0_ip_addr, BROADCAST_PORT)
+ R = pkt_receiver_thread(udp_socket)
+ L = control_port_listener(CONTROL_PORT, udp_socket=udp_socket, verbose=options.verbose)
+ asyncore.loop(LOOP_TIMEOUT)
+
+
+if __name__ == '__main__':
+ try:
+ main()
+ except KeyboardInterrupt:
+ pass
--- /dev/null
+#
+# Copyright 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.
+#
+
+EXTRA_DIST = \
+ usrp_sounder_rx.py \
+ usrp_sounder_tx.py \
+ usrp_source.py \
+ usrp_sink.py \
+ sounder_rx.py \
+ sounder_tx.py
+
+MOSTLYCLEANFILES = *.pyc *~ *.dat
--- /dev/null
+#!/usr/bin/env python
+#
+# Copyright 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.
+#
+
+from gnuradio import gr, usrp, eng_notation
+from usrp_source import usrp_source_c
+import math
+
+n2s = eng_notation.num_to_str
+
+class sounder_rx(gr.hier_block2):
+ """
+ Creates a channel sounder receiver block with the given parameters.
+ """
+
+ def __init__(self, chip_rate, degree, verbose):
+
+ # Call hierarchical block constructor
+ # Top-level blocks have no inputs or outputs
+ gr.hier_block2.__init__(self,
+ "sounder_rx", # Block typename
+ gr.io_signature(1, 1, gr.sizeof_gr_complex), # Input signature
+ gr.io_signature(1, 1, gr.sizeof_gr_complex)) # Output signature
+
+ self._degree = degree
+ self._chip_rate = chip_rate
+ self._verbose = verbose
+ self._length = 2**self._degree-1
+ self._rep_rate = self._chip_rate/float(self._length)
+
+ if self._verbose:
+ print "Using PN sequence of degree", self._degree, "length", self._length
+ print "Sequence repetition rate is", n2s(self._rep_rate), "per sec"
+
+ self.connect(self, gr.pn_correlator_cc(self._degree), self)
--- /dev/null
+#!/usr/bin/env python
+#
+# Copyright 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.
+#
+
+from gnuradio import gr, usrp, eng_notation
+import math
+
+n2s = eng_notation.num_to_str
+
+class sounder_tx(gr.hier_block2):
+ """
+ Creates a channel sounder generator with the given parameters.
+ """
+
+ def __init__(self, degree, chip_rate, verbose):
+ gr.hier_block2.__init__(self,
+ "sounder_tx", # Block typename
+ gr.io_signature(0,0,0), # Input signature
+ gr.io_signature(1, 1, gr.sizeof_float)) # Output signature
+
+ self._degree = degree
+ self._chip_rate = chip_rate
+ self._verbose = verbose
+ self._length = 2**degree-1
+
+ # Connect PN source to block output
+ self.connect(gr.glfsr_source_f(degree), self)
--- /dev/null
+#!/usr/bin/env python
+#
+# Copyright 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.
+#
+
+from gnuradio import gr, usrp, eng_notation
+n2s = eng_notation.num_to_str
+
+# Hierarchical block implementing a USRP sink for complex floats,
+# with convenience functions for tuning, interpolation, etc.
+#
+class usrp_sink_c(gr.hier_block2):
+ """
+ Create a USRP sink object accepting complex floats.
+ """
+ def __init__(self, which=0, subdev_spec=None, if_rate=None,
+ freq=0.0, calibration=0.0, verbose=False):
+ # Call hierarchical block constructor
+ gr.hier_block2.__init__(self,
+ "usrp_sink_c", # Block typename
+ gr.io_signature(1,1,gr.sizeof_gr_complex), # Input signature
+ gr.io_signature(0,0,0)) # Output signature
+
+ self._verbose = verbose
+ self._u = usrp.sink_c(which)
+ if self._verbose:
+ print 'DAC sample rate is', n2s(self._u.dac_rate()), "sps"
+ self.set_subdev(subdev_spec)
+ self.set_if_rate(if_rate)
+ self.set_calibration(calibration)
+ self.tune(freq)
+ self.connect(self, self._u)
+
+ def set_subdev(self, subdev_spec):
+ if subdev_spec is None:
+ subdev_spec = self.pick_subdevice()
+ self._subdev = usrp.selected_subdev(self._u, subdev_spec)
+ self._u.set_mux(usrp.determine_tx_mux_value(self._u, subdev_spec))
+ if self._verbose:
+ print 'TX using', self._subdev.name(), 'daughterboard'
+
+ def pick_subdevice(self):
+ """
+ The user didn't specify a subdevice.
+ If there's a daughterboard on A, select A.
+ If there's a daughterboard on B, select B.
+ Otherwise, select A.
+ """
+ if self._u.db[0][0].dbid() >= 0: # dbid is < 0 if there's no d'board or a problem
+ return (0, 0)
+ if self._u.db[1][0].dbid() >= 0:
+ return (1, 0)
+ return (0, 0)
+
+ def set_if_rate(self, if_rate):
+ # If no IF rate specified, set to maximum interpolation
+ if if_rate is None:
+ self._interp = 512
+ else:
+ self._interp = 4*int(self._u.dac_rate()/(4.0*if_rate)+0.5)
+
+
+ self._if_rate = self._u.dac_rate()/self._interp
+ self._u.set_interp_rate(self._interp)
+
+ if self._verbose:
+ print "USRP interpolation rate is", self._interp
+ print "USRP IF rate is", n2s(self._if_rate), "sps"
+
+ def set_calibration(self, calibration):
+ self._cal = calibration
+ if self._verbose:
+ print "Using frequency calibration offset of", n2s(calibration), "Hz"
+
+ def tune(self, freq):
+ """
+ Set the center frequency we're interested in.
+
+ @param target_freq: frequency in Hz
+ @type: bool
+
+ Tuning is a two step process. First we ask the front-end to
+ tune as close to the desired frequency as it can. Then we use
+ the result of that operation and our target_frequency to
+ determine the value for the digital down converter.
+ """
+ self._tune_result = self._u.tune(self._subdev._which, self._subdev, freq+self._cal)
+ if self._tune_result:
+ if self._verbose:
+ print "Baseband frequency is", n2s(self._tune_result.baseband_freq), "Hz"
+ print "DXC frequency is", n2s(self._tune_result.dxc_freq), "Hz"
+ print "Center frequency is", n2s(freq), "Hz"
+ print "Residual frequency is", n2s(self._tune_result.residual_freq), "Hz"
+ return True
+
+ return False
+
+if __name__ == '__main__':
+ sink = usrp_sink_c(verbose=True)
+
--- /dev/null
+#!/usr/bin/env python
+#
+# Copyright 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.
+#
+
+from gnuradio import gr, eng_notation
+from gnuradio.eng_option import eng_option
+from optparse import OptionParser
+from usrp_source import usrp_source_c
+from sounder_rx import sounder_rx
+
+n2s = eng_notation.num_to_str
+
+class usrp_sounder_rx(gr.top_block):
+ def __init__(self, options):
+ gr.top_block.__init__(self, "usrp_sounder_rx")
+ self._options = options
+ self._u = usrp_source_c(0,
+ self._options.rx_subdev_spec,
+ self._options.gain,
+ self._options.chip_rate,
+ self._options.freq,
+ self._options.cal,
+ self._options.verbose)
+ self._options.chip_rate = self._u._if_rate
+ self._length = 2**self._options.degree-1
+ self._receiver = sounder_rx(self._options.chip_rate,
+ self._options.degree,
+ self._options.verbose)
+
+ samples = 100 * self._length**2
+
+ head = gr.head(gr.sizeof_gr_complex, samples)
+ c2m = gr.complex_to_mag()
+ s2v = gr.stream_to_vector(gr.sizeof_float, self._length)
+ lpf = gr.single_pole_iir_filter_ff(self._options.alpha, self._length)
+ v2s = gr.vector_to_stream(gr.sizeof_float, self._length)
+ sink = gr.file_sink(gr.sizeof_float, "impulse.dat")
+
+ self.connect(self._u, head, self._receiver, c2m, s2v, lpf, v2s, sink)
+
+ if self._options.verbose:
+ print "Chip rate is", n2s(self._options.chip_rate), "chips/sec"
+ print "Resolution is", n2s(1.0/self._options.chip_rate), "sec"
+ print "Using PN code of degree", self._options.degree
+
+def main():
+ parser = OptionParser(option_class=eng_option)
+ parser.add_option("-R", "--rx-subdev-spec", type="subdev", default=None,
+ help="select USRP Rx side A or B (default=first found)")
+ parser.add_option("-f", "--freq", type="eng_float", default=0.0,
+ help="set center frequency (default=%default)")
+ parser.add_option("-c", "--cal", type="eng_float", default=0.0,
+ help="set frequency calibration offset (default=%default)")
+ parser.add_option("-v", "--verbose", action="store_true", default=False,
+ help="print extra debugging info")
+ parser.add_option("-d", "--degree", type="int", default=10,
+ help="set PN code degree (length=2**degree-1, default=%default)")
+ parser.add_option("-r", "--chip-rate", type="eng_float", default=8e6,
+ help="set sounder chip rate (default=%default)")
+ parser.add_option("-g", "--gain", type="eng_float", default=None,
+ help="set receiver gain (default=%default)")
+ parser.add_option("", "--alpha", type="eng_float", default=1.0,
+ help="set smoothing constant (default=%default)")
+ (options, args) = parser.parse_args()
+ if len(args) != 0:
+ parser.print_help()
+ sys.exit(1)
+
+ top_block = usrp_sounder_rx(options)
+
+ try:
+ top_block.run()
+ except KeyboardInterrupt:
+ pass
+
+if __name__ == '__main__':
+ main ()
--- /dev/null
+#!/usr/bin/env python
+#
+# Copyright 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.
+#
+
+from gnuradio import gr, eng_notation
+from gnuradio.eng_option import eng_option
+from optparse import OptionParser
+from usrp_sink import usrp_sink_c
+from sounder_tx import sounder_tx
+
+n2s = eng_notation.num_to_str
+
+class usrp_sounder_tx(gr.top_block):
+ def __init__(self, subdev_spec, freq, cal, verbose, degree, chip_rate, amplitude):
+
+ # Call hierarchical block constructor
+ # Top-level blocks have no inputs or outputs
+ gr.top_block.__init__(self, "usrp_sounder_tx")
+ self._freq = freq
+ self._cal = cal
+ self._verbose = verbose
+ self._degree = degree
+ self._length = 2**degree-1
+ self._amplitude = amplitude
+
+ self._u = usrp_sink_c(0, subdev_spec, chip_rate, self._freq, self._cal, self._verbose)
+ self._chip_rate = self._u._if_rate
+ self._max_time = float(self._length)/self._chip_rate
+ self._pn = sounder_tx(self._degree, self._chip_rate, self._verbose)
+ self._gain = gr.multiply_const_ff(amplitude)
+ self._f2c = gr.float_to_complex()
+ self.connect(self._pn, self._gain, self._f2c, self._u)
+
+ if self._verbose:
+ print "Chip rate is", n2s(self._chip_rate), "chips/sec"
+ print "Resolution is", n2s(1.0/self._chip_rate), "sec"
+ print "Using PN code of degree", self._degree, "length", 2**self._degree-1
+ print "Maximum measurable impulse response is", n2s(self._max_time), "sec"
+ print "Output amplitude is", amplitude
+
+
+def main():
+ parser = OptionParser(option_class=eng_option)
+
+ # Transmit path options
+ parser.add_option("-T", "--tx-subdev-spec", type="subdev", default=None,
+ help="select USRP Rx side A or B (default=first found)")
+ parser.add_option("-f", "--freq", type="eng_float", default=0.0,
+ help="set center frequency (default=%default)")
+ parser.add_option("-c", "--cal", type="eng_float", default=0.0,
+ help="set frequency calibration offset (default=%default)")
+ parser.add_option("-v", "--verbose", action="store_true", default=False,
+ help="print extra debugging info")
+ parser.add_option("-d", "--degree", type="int", default=10,
+ help="set PN code degree (length=2**degree-1, default=%default)")
+ parser.add_option("-r", "--chip-rate", type="eng_float", default=8e6,
+ help="set sounder chip rate (default=%default)")
+ parser.add_option("-g", "--amplitude", type="eng_float", default=8000.0,
+ help="set output amplitude (default=%default)")
+ parser.add_option("", "--real-time", action="store_true", default=False,
+ help="Attempt to enable real-time scheduling")
+ (options, args) = parser.parse_args()
+
+ if len(args) != 0:
+ parser.print_help()
+ sys.exit(1)
+
+ if not options.real_time:
+ realtime = False
+ else:
+ # Attempt to enable realtime scheduling
+ r = gr.enable_realtime_scheduling()
+ if r == gr.RT_OK:
+ realtime = True
+ else:
+ realtime = False
+ print "Note: failed to enable realtime scheduling"
+
+ # Create an instance of a hierarchical block
+ top_block = usrp_sounder_tx(options.tx_subdev_spec, options.freq, options.cal,
+ options.verbose, options.degree, options.chip_rate,
+ options.amplitude)
+
+ try:
+ # Run forever
+ top_block.run()
+ except KeyboardInterrupt:
+ # Ctrl-C exits
+ pass
+
+if __name__ == '__main__':
+ main ()
--- /dev/null
+#!/usr/bin/env python
+#
+# Copyright 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.
+#
+
+from gnuradio import gr, usrp, eng_notation
+n2s = eng_notation.num_to_str
+
+# Hierarchical block implementing a USRP source for complex floats,
+# with convenience functions for gain, tune, decimation, etc.
+#
+class usrp_source_c(gr.hier_block2):
+ """
+ Create a USRP source object supplying complex floats.
+ """
+ def __init__(self, which=0, subdev_spec=None, gain=None, if_rate=None,
+ freq=0.0, calibration=0.0, verbose=False):
+ # Call hierarchical block constructor
+ gr.hier_block2.__init__(self,
+ "usrp_source_c", # Block typename
+ gr.io_signature(0,0,0), # Input signature
+ gr.io_signature(1,1,gr.sizeof_gr_complex)) # Output signature
+
+ self._verbose = verbose
+ self._u = usrp.source_c(which)
+ if self._verbose:
+ print 'ADC sample rate is', n2s(self._u.adc_rate()), "sps"
+ self.set_subdev(subdev_spec)
+ self.set_if_rate(if_rate)
+ self.set_gain(gain)
+ self.set_calibration(calibration)
+ self.tune(freq)
+ self.connect(self._u, self)
+
+ def set_subdev(self, subdev_spec):
+ if subdev_spec is None:
+ subdev_spec = self.pick_subdevice()
+ self._subdev = usrp.selected_subdev(self._u, subdev_spec)
+ self._u.set_mux(usrp.determine_rx_mux_value(self._u, subdev_spec))
+ if self._verbose:
+ print 'RX using', self._subdev.name(), 'daughterboard'
+
+ def pick_subdevice(self):
+ """
+ The user didn't specify a subdevice.
+ If there's a daughterboard on A, select A.
+ If there's a daughterboard on B, select B.
+ Otherwise, select A.
+ """
+ if self._u.db[0][0].dbid() >= 0: # dbid is < 0 if there's no d'board or a problem
+ return (0, 0)
+ if self._u.db[1][0].dbid() >= 0:
+ return (1, 0)
+ return (0, 0)
+
+ def set_if_rate(self, if_rate):
+ # If no IF rate specified, set to maximum decimation
+ if if_rate is None:
+ self._decim = 256
+ else:
+ self._decim = int(self._u.adc_rate()/if_rate)
+
+ self._u.set_decim_rate(self._decim)
+ self._if_rate = self._u.adc_rate()/self._decim
+
+ if self._verbose:
+ print "USRP decimation rate is", self._decim
+ print "USRP IF rate is", n2s(self._if_rate), "sps"
+
+ def set_gain(self, gain):
+ # If no gain specified, set to midrange
+ if gain is None:
+ g = self._subdev.gain_range()
+ gain = (g[0]+g[1])/2.0
+ self._gain = gain
+ self._subdev.set_gain(self._gain)
+ if self._verbose:
+ print "USRP gain set to", self._gain
+
+ def set_calibration(self, calibration):
+ self._cal = calibration
+ if self._verbose:
+ print "Using frequency calibration offset of", n2s(calibration), "Hz"
+
+ def tune(self, freq):
+ """
+ Set the center frequency we're interested in.
+
+ @param target_freq: frequency in Hz
+ @type: bool
+
+ Tuning is a two step process. First we ask the front-end to
+ tune as close to the desired frequency as it can. Then we use
+ the result of that operation and our target_frequency to
+ determine the value for the digital down converter.
+ """
+ self._tune_result = usrp.tune(self._u, 0, self._subdev, freq+self._cal)
+ if self._tune_result:
+ if self._verbose:
+ print "Baseband frequency is", n2s(self._tune_result.baseband_freq), "Hz"
+ print "DXC frequency is", n2s(self._tune_result.dxc_freq), "Hz"
+ print "Center frequency is", n2s(freq), "Hz"
+ print "Residual frequency is", n2s(self._tune_result.residual_freq), "Hz"
+ return True
+
+ return False
+
+if __name__ == '__main__':
+ src = usrp_source_c(verbose=True)
--- /dev/null
+#
+# Copyright 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.
+#
+
+include $(top_srcdir)/Makefile.common
+
+EXTRA_DIST = \
+ audio_sink.py \
+ audio_source.py \
+ dial_tone_sink.py \
+ dial_tone_source.py \
+ vector_sink.py \
+ vector_source.py
+
+ourdatadir = $(exampledir)/network
+ourdata_DATA = $(EXTRA_DIST)
+
+MOSTLYCLEANFILES = *.pyc *~
--- /dev/null
+#!/usr/bin/env python
+#
+# Copyright 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.
+#
+
+from gnuradio import gr, audio
+from gnuradio.eng_option import eng_option
+from optparse import OptionParser
+
+class audio_sink(gr.top_block):
+ def __init__(self, src, port, pkt_size, sample_rate):
+ gr.top_block.__init__(self, "audio_sink")
+ src = gr.udp_source(gr.sizeof_float, src, port, pkt_size)
+ dst = audio.sink(sample_rate)
+ self.connect(src, dst)
+
+if __name__ == '__main__':
+ parser = OptionParser(option_class=eng_option)
+ parser.add_option("", "--src-name", type="string", default="localhost",
+ help="local host name (domain name or IP address)")
+ parser.add_option("", "--src-port", type="int", default=65500,
+ help="port value to listen to for connection")
+ parser.add_option("", "--packet-size", type="int", default=1472,
+ help="packet size.")
+ parser.add_option("-r", "--sample-rate", type="int", default=32000,
+ help="audio signal sample rate [default=%default]")
+ (options, args) = parser.parse_args()
+ if len(args) != 0:
+ parser.print_help()
+ raise SystemExit, 1
+
+ # Create an instance of a hierarchical block
+ top_block = audio_sink(options.src_name, options.src_port,
+ options.packet_size, options.sample_rate)
+
+ try:
+ # Run forever
+ top_block.run()
+ except KeyboardInterrupt:
+ # Ctrl-C exits
+ pass
+
--- /dev/null
+#!/usr/bin/env python
+#
+# Copyright 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.
+#
+
+from gnuradio import gr, audio
+from gnuradio.eng_option import eng_option
+from optparse import OptionParser
+
+class audio_source(gr.top_block):
+ def __init__(self, src, dst, port, pkt_size, sample_rate):
+ gr.top_block.__init__(self, "audio_source")
+ self.audio = audio.source(sample_rate)
+ self.sink = gr.udp_sink(gr.sizeof_float, src, 0, dst, port, pkt_size)
+ self.connect(self.audio, self.sink)
+
+if __name__ == '__main__':
+ parser = OptionParser(option_class=eng_option)
+ parser.add_option("", "--src-name", type="string", default="localhost",
+ help="local host name (domain name or IP address)")
+ parser.add_option("", "--dst-name", type="string", default="localhost",
+ help="Remote host name (domain name or IP address")
+ parser.add_option("", "--dst-port", type="int", default=65500,
+ help="port value to connect to")
+ parser.add_option("", "--packet-size", type="int", default=1472,
+ help="packet size.")
+ parser.add_option("-r", "--sample-rate", type="int", default=32000 ,
+ help="audio signal sample rate [default=%default]")
+ (options, args) = parser.parse_args()
+ if len(args) != 0:
+ parser.print_help()
+ raise SystemExit, 1
+
+ # Create an instance of a hierarchical block
+ top_block = audio_source(options.src_name, options.dst_name, options.dst_port,
+ options.packet_size, options.sample_rate)
+
+ try:
+ # Run forever
+ top_block.run()
+ except KeyboardInterrupt:
+ # Ctrl-C exits
+ pass
+
--- /dev/null
+#!/usr/bin/env python
+#
+# Copyright 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.
+#
+
+from gnuradio import gr, audio
+from gnuradio.eng_option import eng_option
+from optparse import OptionParser
+
+class dial_tone_sink(gr.top_block):
+ def __init__(self, src, port, pkt_size, sample_rate):
+ gr.top_block.__init__(self, "dial_tone_sink")
+ udp = gr.udp_source(gr.sizeof_float, src, port, pkt_size)
+ sink = audio.sink(sample_rate)
+ self.connect(udp, sink)
+
+if __name__ == '__main__':
+ parser = OptionParser(option_class=eng_option)
+ parser.add_option("", "--src-name", type="string", default="localhost",
+ help="local host name (domain name or IP address)")
+ parser.add_option("", "--src-port", type="int", default=65500,
+ help="port value to listen to for connection")
+ parser.add_option("", "--packet-size", type="int", default=1472,
+ help="packet size.")
+ parser.add_option("-r", "--sample-rate", type="int", default=8000,
+ help="audio signal sample rate [default=%default]")
+ (options, args) = parser.parse_args()
+ if len(args) != 0:
+ parser.print_help()
+ raise SystemExit, 1
+
+ # Create an instance of a hierarchical block
+ top_block = dial_tone_sink(options.src_name, options.src_port,
+ options.packet_size, options.sample_rate)
+
+ try:
+ # Run forever
+ top_block.run()
+ except KeyboardInterrupt:
+ # Ctrl-C exits
+ pass
+
--- /dev/null
+#!/usr/bin/env python
+#
+# Copyright 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.
+#
+
+from gnuradio import gr
+from gnuradio.eng_option import eng_option
+from optparse import OptionParser
+
+class dial_tone_source(gr.top_block):
+ def __init__(self, src, dst, port, pkt_size, sample_rate):
+ gr.top_block.__init__(self, "dial_tone_source")
+
+ amplitude = 0.3
+ src0 = gr.sig_source_f (sample_rate, gr.GR_SIN_WAVE, 350, amplitude)
+ src1 = gr.sig_source_f (sample_rate, gr.GR_SIN_WAVE, 440, amplitude)
+ add = gr.add_ff()
+
+ # Throttle needed here to account for the other side's audio card sampling rate
+ thr = gr.throttle(gr.sizeof_float, sample_rate)
+ sink = gr.udp_sink(gr.sizeof_float, src, 0, dst, port, pkt_size)
+ self.connect(src0, (add, 0))
+ self.connect(src1, (add, 1))
+ self.connect(add, thr, sink)
+
+if __name__ == '__main__':
+ parser = OptionParser(option_class=eng_option)
+ parser.add_option("", "--src-name", type="string", default="localhost",
+ help="local host name (domain name or IP address)")
+ parser.add_option("", "--dst-name", type="string", default="localhost",
+ help="Remote host name (domain name or IP address")
+ parser.add_option("", "--dst-port", type="int", default=65500,
+ help="port value to connect to")
+ parser.add_option("", "--packet-size", type="int", default=1472,
+ help="packet size.")
+ parser.add_option("-r", "--sample-rate", type="int", default=8000,
+ help="audio signal sample rate [default=%default]")
+ (options, args) = parser.parse_args()
+ if len(args) != 0:
+ parser.print_help()
+ raise SystemExit, 1
+
+ # Create an instance of a hierarchical block
+ top_block = dial_tone_source(options.src_name, options.dst_name, options.dst_port,
+ options.packet_size, options.sample_rate)
+
+ try:
+ # Run forever
+ top_block.run()
+ except KeyboardInterrupt:
+ # Ctrl-C exits
+ pass
+
--- /dev/null
+#!/usr/bin/env python
+#
+# Copyright 2006 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.eng_option import eng_option
+from optparse import OptionParser
+
+class vector_sink(gr.top_block):
+ def __init__(self, src, port, pkt_size):
+ gr.top_block.__init__(self, "vector_sink")
+
+ udp = gr.udp_source(gr.sizeof_float, src, port, pkt_size)
+ sink = gr.file_sink(gr.sizeof_float, "received.dat")
+ self.connect(udp, sink)
+
+if __name__ == "__main__":
+ parser = OptionParser(option_class=eng_option)
+ parser.add_option("", "--src-name", type="string", default="localhost",
+ help="local host name (domain name or IP address)")
+ parser.add_option("", "--src-port", type="int", default=65500,
+ help="port value to listen to for connection")
+ parser.add_option("", "--packet-size", type="int", default=1471,
+ help="packet size.")
+ (options, args) = parser.parse_args()
+ if len(args) != 0:
+ parser.print_help()
+ raise SystemExit, 1
+
+ # Create an instance of a hierarchical block
+ top_block = vector_sink(options.src_name, options.src_port, options.packet_size)
+
+ try:
+ # Run forever
+ top_block.run()
+ except KeyboardInterrupt:
+ # Ctrl-C exits
+ pass
+
--- /dev/null
+#!/usr/bin/env python
+#
+# Copyright 2006 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.eng_option import eng_option
+from optparse import OptionParser
+
+class vector_source(gr.top_block):
+ def __init__(self, src, dst, port, pkt_size):
+ gr.top_block.__init__(self, "vector_source")
+ data = [i*0.01 for i in range(1000)]
+ vec = gr.vector_source_f(data, True)
+ udp = gr.udp_sink(gr.sizeof_float, src, 0, dst, port, pkt_size)
+ self.connect(vec, udp)
+
+if __name__ == '__main__':
+ parser = OptionParser(option_class=eng_option)
+ parser.add_option("", "--src-name", type="string", default="localhost",
+ help="local host name (domain name or IP address)")
+ parser.add_option("", "--dst-name", type="string", default="localhost",
+ help="Remote host name (domain name or IP address")
+ parser.add_option("", "--dst-port", type="int", default=65500,
+ help="port value to connect to")
+ parser.add_option("", "--packet-size", type="int", default=1471,
+ help="packet size.")
+ (options, args) = parser.parse_args()
+ if len(args) != 0:
+ parser.print_help()
+ raise SystemExit, 1
+
+# Create an instance of a hierarchical block
+ top_block = vector_source(options.src_name, options.dst_name,
+ options.dst_port, options.packet_size)
+
+ try:
+ # Run forever
+ top_block.run()
+ except KeyboardInterrupt:
+ # Ctrl-C exits
+ pass
+
+++ /dev/null
-#
-# Copyright 2006 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.
-#
-
-EXTRA_DIST = \
- measurement_slave.py
\ No newline at end of file
+++ /dev/null
-#!/usr/bin/env python
-#
-# Copyright 2006 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.
-#
-
-import struct
-import socket
-import asyncore
-import sys
-import optparse
-import random
-from gnuradio.eng_option import eng_option
-import gnuradio.gr.gr_threading as _threading
-
-LOOP_TIMEOUT = 0.001
-BROADCAST_ADDR = '255.255.255.255'
-
-BROADCAST_PORT = 27010 # UDP
-CONTROL_PORT = 27011 # TCP
-
-PKT_HEADER_SIZE = 4 # 32-bit int
-
-logfile = None
-
-def unpack_header(s):
- (len,) = struct.unpack('!i', s)
- return (len,)
-
-def pack_header(len):
- return struct.pack('!i', len)
-
-
-class control_port_listener(asyncore.dispatcher):
- def __init__(self, port=CONTROL_PORT, udp_socket=None, verbose=False):
- """
- @param port: TCP port to listen on.
- @type port: int
- """
- asyncore.dispatcher.__init__(self)
-
- self._verbose = verbose
- self._udp_socket = udp_socket
-
- host = '' # symbolic name for localhost
- self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
- self.set_reuse_addr()
-
- try:
- self.bind((host, port))
- except socket.error, err:
- sys.stderr.write('Failed to bind to %s: %s\n' %
- ((host, port), os.strerror (err.args[0]),))
- sys.exit(1)
-
- self.listen(3)
-
- def handle_accept(self):
- socket, addr = self.accept()
- sys.stderr.write("handle_accept: %r\n" % (addr,))
- if not(socket is None):
- # instantiate a server
- s = control_server(socket, addr, self._udp_socket, self._verbose)
-
-
-class gr_dispatcher(asyncore.dispatcher):
- def __init__(self, sock=None, map=None):
- asyncore.dispatcher.__init__(self, sock=sock, map=map)
-
- def read_packet(self):
- """
- Returns None or packet
- """
- s = self.recvall(PKT_HEADER_SIZE)
- if s == '':
- return None
-
- (payload_len,) = unpack_header(s)
-
- payload_len = int(payload_len)
-
- if payload_len == 0:
- payload = ''
- else:
- payload = self.recvall(payload_len)
- if len(payload) != payload_len:
- sys.stderr.write ('short recv, expected %d bytes, got %d\n' % (
- payload_len, len(payload)))
- raise RuntimeError, "short recv"
-
- return payload
-
- def recvall(self, buffer_size):
- result = ''
- while len(result) < buffer_size:
- data = self.recv(buffer_size - len(result))
- if not data:
- return ''
- result += data
- return result
-
-
-class pkt_receiver_thread(_threading.Thread):
- def __init__(self, socket):
- _threading.Thread.__init__(self)
- self.setDaemon(1)
- self.socket = socket
- self.keep_running = True
- self.start()
-
- def run(self):
- while self.keep_running:
- pkt, sender = self.socket.recvfrom(10000)
- if pkt:
- if len(pkt) > 2:
- t = struct.unpack('!H', pkt[0:2])
- seqno = t[0]
- else:
- seqno = -1
-
- logfile.write('RCVD seqno %4d len %4d from %s\n' % (seqno, len(pkt), sender))
- logfile.flush()
-
-
-class control_server(gr_dispatcher):
- def __init__(self, socket, addr, udp_socket, verbose=False):
- gr_dispatcher.__init__(self, sock=socket)
-
- self._udp_socket = udp_socket
- self.verbose = verbose
- self.setblocking(1)
-
- def writable(self):
- return False
-
- def handle_read(self):
- pkt = self.read_packet()
- if pkt:
- annotate = 'ANNOTATE'
- if pkt.startswith(annotate):
- logfile.write(pkt[len(annotate)+1:])
- logfile.write('\n')
- logfile.flush()
- elif pkt.startswith('SEND'):
- tokens = pkt.split()
- if len(tokens) < 4:
- invalid_packet(pkt)
- else:
- npkts = int(tokens[1])
- size = int(tokens[2])
- power = float(tokens[3])
- send_test_packets(self._udp_socket, npkts, size, power)
- else:
- invalid_packet(pkt)
-
- def handle_close(self):
- self.close()
-
-
-def invalid_packet(pkt):
- sys.stderr.write('received unrecognized packet: %s\n' % (pkt,))
-
-
-def make_random_payload(size):
- p = [0] * size
- if 1:
- for i in range(size):
- p[i] = chr(random.randint(0, 255))
- else:
- for i in range(size):
- p[i] = chr(i % 256)
- return ''.join(p)
-
-
-def send_test_packets(udp_socket, npkts, size, power):
- # we ignore power for now...
- size = max(2, size)
- payload = make_random_payload(size - 2)
- for n in range(npkts):
- pkt = struct.pack('!H', n) + payload
- udp_socket.sendto(pkt, (BROADCAST_ADDR, BROADCAST_PORT))
- #udp_socket.sendall(pkt)
-
-
-def open_udp_broadcast_socket(gr0_host_ip, port):
- s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
-# s.bind((gr0_host_ip, port))
- s.bind(('', port))
- s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
-# s.connect((BROADCAST_ADDR, port))
- return s
-
-
-def main():
- global logfile
-
- usage = 'usage: %prog [options] gr0-ip-addr'
- parser = optparse.OptionParser (option_class=eng_option, usage=usage)
- parser.add_option('-l', '--logfile', type='string', default=None,
- help="specify log file name [default=<stdout>]")
- parser.add_option('-v', '--verbose', action="store_true", default=False,
- help="enable verbose diagnostics")
-
- (options, args) = parser.parse_args ()
- if len(args) != 1:
- parser.print_help()
- sys.exit(1)
-
- gr0_ip_addr = args[0]
- if options.logfile is None:
- logfile = sys.stdout
- else:
- logfile = file(options.logfile, 'w')
-
- udp_socket = open_udp_broadcast_socket(gr0_ip_addr, BROADCAST_PORT)
- R = pkt_receiver_thread(udp_socket)
- L = control_port_listener(CONTROL_PORT, udp_socket=udp_socket, verbose=options.verbose)
- asyncore.loop(LOOP_TIMEOUT)
-
-
-if __name__ == '__main__':
- try:
- main()
- except KeyboardInterrupt:
- pass
fusb_options.py \
pick_bitrate.py \
receive_path.py \
- transmit_path.py
+ transmit_path.py \
+ ofdm_mod_demod_test.py \
+ ofdm_sync.m \
+ ofdm_sync_pn.m \
+ plot_ofdm.m \
+ tunnel.py
ourdatadir = $(exampledir)/ofdm
ourdata_DATA = $(EXTRA_DIST)
#!/usr/bin/env python
+#
+# 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.
+#
"""
Transmit N simultaneous narrow band FM signals.
from gnuradio import gr, eng_notation
from gnuradio import usrp
from gnuradio import audio
-from gnuradio import blks
+from gnuradio import blks2
from gnuradio.eng_option import eng_option
from optparse import OptionParser
from usrpm import usrp_dbid
import math
import sys
-from gnuradio.wxgui import stdgui, fftsink
+from gnuradio.wxgui import stdgui2, fftsink2
from gnuradio import tx_debug_gui
import wx
########################################################
# instantiate one transmit chain for each call
-class pipeline(gr.hier_block):
- def __init__(self, fg, filename, lo_freq, audio_rate, if_rate):
+class pipeline(gr.hier_block2):
+ def __init__(self, filename, lo_freq, audio_rate, if_rate):
+
+ gr.hier_block2.__init__(self, "pipeline",
+ gr.io_signature(0, 0, 0), # Input signature
+ gr.io_signature(1, 1, gr.sizeof_gr_complex)) # Output signature
src = gr.file_source (gr.sizeof_float, filename, True)
- fmtx = blks.nbfm_tx (fg, audio_rate, if_rate,
- max_dev=5e3, tau=75e-6)
+ fmtx = blks2.nbfm_tx (audio_rate, if_rate, max_dev=5e3, tau=75e-6)
# Local oscillator
lo = gr.sig_source_c (if_rate, # sample rate
0) # DC Offset
mixer = gr.multiply_cc ()
- fg.connect (src, fmtx, (mixer, 0))
- fg.connect (lo, (mixer, 1))
-
- gr.hier_block.__init__(self, fg, src, mixer)
-
+ self.connect (src, fmtx, (mixer, 0))
+ self.connect (lo, (mixer, 1))
-class fm_tx_graph (stdgui.gui_flow_graph):
+class fm_tx_block(stdgui2.std_top_block):
def __init__(self, frame, panel, vbox, argv):
MAX_CHANNELS = 7
- stdgui.gui_flow_graph.__init__ (self, frame, panel, vbox, argv)
+ stdgui2.std_top_block.__init__ (self, frame, panel, vbox, argv)
parser = OptionParser (option_class=eng_option)
parser.add_option("-T", "--tx-subdev-spec", type="subdev", default=None,
step = 25e3
offset = (0 * step, 1 * step, -1 * step, 2 * step, -2 * step, 3 * step, -3 * step)
for i in range (options.nchannels):
- t = pipeline (self, "audio-%d.dat" % (i % 4), offset[i],
- self.audio_rate, self.usrp_rate)
- self.connect (t, (sum, i))
+ t = pipeline("audio-%d.dat" % (i % 4), offset[i],
+ self.audio_rate, self.usrp_rate)
+ self.connect(t, (sum, i))
gain = gr.multiply_const_cc (4000.0 / options.nchannels)
# plot an FFT to verify we are sending what we want
if 1:
- post_mod = fftsink.fft_sink_c(self, panel, title="Post Modulation",
- fft_size=512, sample_rate=self.usrp_rate,
- y_per_div=20, ref_level=40)
+ post_mod = fftsink2.fft_sink_c(panel, title="Post Modulation",
+ fft_size=512, sample_rate=self.usrp_rate,
+ y_per_div=20, ref_level=40)
self.connect (sum, post_mod)
vbox.Add (post_mod.win, 1, wx.EXPAND)
return False
def main ():
- app = stdgui.stdapp (fm_tx_graph, "Multichannel FM Tx")
+ app = stdgui2.stdapp(fm_tx_block, "Multichannel FM Tx", nstatus=1)
app.MainLoop ()
if __name__ == '__main__':
#!/usr/bin/env python
+#
+# 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.
+#
"""
Transmit 2 signals, one out each daughterboard.
from gnuradio.eng_notation import num_to_str, str_to_num
from gnuradio import usrp
from gnuradio import audio
-from gnuradio import blks
+from gnuradio import blks2
from gnuradio.eng_option import eng_option
from optparse import OptionParser
from usrpm import usrp_dbid
import sys
-class example_signal_0(gr.hier_block):
+class example_signal_0(gr.hier_block2):
"""
Sinusoid at 600 Hz.
"""
- def __init__(self, fg, sample_rate):
+ def __init__(self, sample_rate):
+ gr.hier_block2.__init__(self, "example_signal_0",
+ gr.io_signature(0, 0, 0), # Input signature
+ gr.io_signature(1, 1, gr.sizeof_gr_complex)) # Output signature
src = gr.sig_source_c (sample_rate, # sample rate
gr.GR_SIN_WAVE, # waveform type
1.0, # amplitude
0) # DC Offset
- gr.hier_block.__init__(self, fg, None, src)
+ self.connect(src, self)
-class example_signal_1(gr.hier_block):
+class example_signal_1(gr.hier_block2):
"""
North American dial tone (350 + 440 Hz).
"""
- def __init__(self, fg, sample_rate):
+ def __init__(self, sample_rate):
+ gr.hier_block2.__init__(self, "example_signal_1",
+ gr.io_signature(0, 0, 0), # Input signature
+ gr.io_signature(1, 1, gr.sizeof_gr_complex)) # Output signature
src0 = gr.sig_source_c (sample_rate, # sample rate
gr.GR_SIN_WAVE, # waveform type
1.0, # amplitude
0) # DC Offset
sum = gr.add_cc()
- fg.connect(src0, (sum, 0))
- fg.connect(src1, (sum, 1))
-
- gr.hier_block.__init__(self, fg, None, sum)
-
-
+ self.connect(src0, (sum, 0))
+ self.connect(src1, (sum, 1))
+ self.connect(sum, self)
-class my_graph(gr.flow_graph):
+class my_top_block(gr.top_block):
def __init__(self):
- gr.flow_graph.__init__ (self)
+ gr.top_block.__init__(self)
usage="%prog: [options] side-A-tx-freq side-B-tx-freq"
parser = OptionParser (option_class=eng_option, usage=usage)
# ----------------------------------------------------------------
# build two signal sources, interleave them, amplify and connect them to usrp
- sig0 = example_signal_0(self, self.usrp_rate)
- sig1 = example_signal_1(self, self.usrp_rate)
+ sig0 = example_signal_0(self.usrp_rate)
+ sig1 = example_signal_1(self.usrp_rate)
intl = gr.interleave(gr.sizeof_gr_complex)
self.connect(sig0, (intl, 0))
if __name__ == '__main__':
try:
- my_graph().run()
+ my_top_block().run()
except KeyboardInterrupt:
pass
#!/usr/bin/env python
#
-# Copyright 2004 Free Software Foundation, Inc.
+# Copyright 2004,2007 Free Software Foundation, Inc.
#
# This file is part of GNU Radio
#
from gnuradio.eng_option import eng_option
from optparse import OptionParser
-def ramp_source (fg):
+def ramp_source ():
period = 2**16
src = gr.vector_source_s (range (-period/2, period/2, 1), True)
return src
-def build_graph (tx_enable, rx_enable):
+def build_block (tx_enable, rx_enable):
max_usb_rate = 8e6 # 8 MS/sec
dac_freq = 128e6
adc_freq = 64e6
rx_mux = 0x00003210
rx_decim = int ((adc_freq * rx_nchan) / (max_usb_rate/2)) # 32
- fg = gr.flow_graph ()
+ tb = gr.top_block ()
if tx_enable:
tx_src0 = gr.sig_source_c (dac_freq/tx_interp, gr.GR_CONST_WAVE, 0, 16e3, 0)
usrp_tx = usrp.sink_c (0, tx_interp, tx_nchan, tx_mux)
usrp_tx.set_tx_freq (0, 10e6)
usrp_tx.set_tx_freq (1, 9e6)
- fg.connect (tx_src0, usrp_tx)
+ tb.connect (tx_src0, usrp_tx)
if rx_enable:
usrp_rx = usrp.source_c (0, rx_decim, rx_nchan, rx_mux)
usrp_rx.set_rx_freq (0, 5.5e6)
usrp_rx.set_rx_freq (1, 6.5e6)
rx_dst0 = gr.null_sink (gr.sizeof_gr_complex)
- fg.connect (usrp_rx, rx_dst0)
+ tb.connect (usrp_rx, rx_dst0)
- return fg
+ return tb
def main ():
parser = OptionParser (option_class=eng_option)
parser.add_option ("-r", action="store_true", dest="rx_enable",
default=False, help="enable Rx path")
(options, args) = parser.parse_args ()
- fg = build_graph (options.tx_enable, options.rx_enable)
+ tb = build_block (options.tx_enable, options.rx_enable)
- fg.start ()
+ tb.start ()
raw_input ('Press Enter to quit: ')
- fg.stop ()
+ tb.stop ()
if __name__ == '__main__':
main ()
# print "tx_interp =", tx_interp, "rx_decim =", rx_decim
assert (tx_interp == 2 * rx_decim)
- fg = gr.flow_graph ()
+ tb = gr.top_block ()
# Build the Tx pipeline
data_src = gr.lfsr_32k_source_s ()
src_head = gr.head (gr.sizeof_short, int (stream_length * 2))
usrp_tx = usrp.sink_s (0, tx_interp)
- fg.connect (data_src, src_head, usrp_tx)
+ tb.connect (data_src, src_head, usrp_tx)
# and the Rx pipeline
usrp_rx = usrp.source_s (0, rx_decim, 1, 0x32103210, usrp.FPGA_MODE_LOOPBACK)
head = gr.head (gr.sizeof_short, stream_length)
check = gr.check_lfsr_32k_s ()
- fg.connect (usrp_rx, head, check)
+ tb.connect (usrp_rx, head, check)
- fg.run ()
+ tb.run ()
ntotal = check.ntotal ()
nright = check.nright ()
#!/usr/bin/env python
#
-# Copyright 2005 Free Software Foundation, Inc.
+# Copyright 2005,2007 Free Software Foundation, Inc.
#
# This file is part of GNU Radio
#
from gnuradio import gr, gru, eng_notation
from gnuradio import usrp
from gnuradio import audio
-from gnuradio import blks
+from gnuradio import blks2
from gnuradio.eng_option import eng_option
-from gnuradio.wxgui import stdgui, fftsink, scopesink, slider, form
+from gnuradio.wxgui import stdgui2, fftsink2, scopesink2, slider, form
from usrpm import usrp_dbid
from numpy import convolve, array
# Control Stuff
# ////////////////////////////////////////////////////////////////////////
-class ptt_graph(stdgui.gui_flow_graph):
+class ptt_block(stdgui2.std_top_block):
def __init__(self, frame, panel, vbox, argv):
- stdgui.gui_flow_graph.__init__ (self, frame, panel, vbox, argv)
+ stdgui2.std_top_block.__init__ (self, frame, panel, vbox, argv)
self.frame = frame
self.space_bar_pressed = False
if options.freq < 1e6:
options.freq *= 1e6
- self.txpath = transmit_path(self, options.tx_subdev_spec, options.audio_input)
- self.rxpath = receive_path(self, options.rx_subdev_spec, options.rx_gain, options.audio_output)
+ self.txpath = transmit_path(options.tx_subdev_spec, options.audio_input)
+ self.rxpath = receive_path(options.rx_subdev_spec, options.rx_gain, options.audio_output)
+ self.connect(self.txpath)
+ self.connect(self.rxpath)
+
self._build_gui(frame, panel, vbox, argv, options.no_gui)
self.set_transmit(False)
panel.SetFocus()
if 1 and not(no_gui):
- rx_fft = fftsink.fft_sink_c (self, panel, title="Rx Input", fft_size=512,
+ rx_fft = fftsink2.fft_sink_c(panel, title="Rx Input", fft_size=512,
sample_rate=self.rxpath.if_rate,
ref_level=80, y_per_div=20)
self.connect (self.rxpath.u, rx_fft)
vbox.Add (rx_fft.win, 1, wx.EXPAND)
if 1 and not(no_gui):
- rx_fft = fftsink.fft_sink_c (self, panel, title="Post s/w DDC",
+ rx_fft = fftsink2.fft_sink_c(panel, title="Post s/w DDC",
fft_size=512, sample_rate=self.rxpath.quad_rate,
ref_level=80, y_per_div=20)
self.connect (self.rxpath.ddc, rx_fft)
vbox.Add (rx_fft.win, 1, wx.EXPAND)
if 0 and not(no_gui):
- foo = scopesink.scope_sink_f (self, panel, title="Squelch",
- sample_rate=32000)
+ foo = scopesink2.scope_sink_f(panel, title="Squelch",
+ sample_rate=32000)
self.connect (self.rxpath.fmrx.div, (foo,0))
self.connect (self.rxpath.fmrx.gate, (foo,1))
self.connect (self.rxpath.fmrx.squelch_lpf, (foo,2))
vbox.Add (foo.win, 1, wx.EXPAND)
if 0 and not(no_gui):
- tx_fft = fftsink.fft_sink_c (self, panel, title="Tx Output",
+ tx_fft = fftsink2.fft_sink_c(panel, title="Tx Output",
fft_size=512, sample_rate=self.txpath.usrp_rate)
self.connect (self.txpath.amp, tx_fft)
vbox.Add (tx_fft.win, 1, wx.EXPAND)
# Transmit Path
# ////////////////////////////////////////////////////////////////////////
-class transmit_path(gr.hier_block):
- def __init__(self, fg, subdev_spec, audio_input):
-
+class transmit_path(gr.hier_block2):
+ def __init__(self, subdev_spec, audio_input):
+ gr.hier_block2.__init__(self, "transmit_path",
+ gr.io_signature(0, 0, 0), # Input signature
+ gr.io_signature(0, 0, 0)) # Output signature
+
self.u = usrp.sink_c ()
dac_rate = self.u.dac_rate();
audio_taps = convolve(array(lpf),array(hpf))
self.audio_filt = gr.fir_filter_fff(1,audio_taps)
- self.pl = blks.ctcss_gen_f(fg, self.audio_rate,123.0)
+ self.pl = blks2.ctcss_gen_f(self.audio_rate,123.0)
self.add_pl = gr.add_ff()
- fg.connect(self.pl,(self.add_pl,1))
+ self.connect(self.pl,(self.add_pl,1))
- self.fmtx = blks.nbfm_tx(fg, self.audio_rate, self.if_rate)
+ self.fmtx = blks2.nbfm_tx(self.audio_rate, self.if_rate)
self.amp = gr.multiply_const_cc (self.normal_gain)
# determine the daughterboard subdevice we're using
self.subdev = usrp.selected_subdev(self.u, subdev_spec)
print "TX using", self.subdev.name()
- fg.connect(self.audio, self.audio_amp, self.audio_filt,
- (self.add_pl,0), self.fmtx, self.amp, self.u)
-
- gr.hier_block.__init__(self, fg, None, None)
+ self.connect(self.audio, self.audio_amp, self.audio_filt,
+ (self.add_pl,0), self.fmtx, self.amp, self.u)
self.set_gain(self.subdev.gain_range()[1]) # set max Tx gain
# Receive Path
# ////////////////////////////////////////////////////////////////////////
-class receive_path(gr.hier_block):
- def __init__(self, fg, subdev_spec, gain, audio_output):
+class receive_path(gr.hier_block2):
+ def __init__(self, subdev_spec, gain, audio_output):
+ gr.hier_block2.__init__(self, "receive_path",
+ gr.io_signature(0, 0, 0), # Input signature
+ gr.io_signature(0, 0, 0)) # Output signature
self.u = usrp.source_c ()
adc_rate = self.u.adc_rate()
self.if_rate) # input sample rate
# instantiate the guts of the single channel receiver
- self.fmrx = blks.nbfm_rx(fg, audio_rate, self.quad_rate)
+ self.fmrx = blks2.nbfm_rx(audio_rate, self.quad_rate)
# standard squelch block
- self.squelch = blks.standard_squelch(fg, audio_rate)
+ self.squelch = blks2.standard_squelch(audio_rate)
# audio gain / mute block
self._audio_gain = gr.multiply_const_ff(1.0)
audio_sink = audio.sink (int(audio_rate), audio_output)
# now wire it all together
- fg.connect (self.u, self.ddc, self.fmrx, self.squelch, self._audio_gain, audio_sink)
- gr.hier_block.__init__(self, fg, self.u, audio_sink)
+ self.connect (self.u, self.ddc, self.fmrx, self.squelch, self._audio_gain, audio_sink)
if gain is None:
# if no gain was specified, use the mid-point in dB
# ////////////////////////////////////////////////////////////////////////
def main():
- app = stdgui.stdapp(ptt_graph, "NBFM Push to Talk")
+ app = stdgui2.stdapp(ptt_block, "NBFM Push to Talk")
app.MainLoop()
if __name__ == '__main__':
#!/usr/bin/env python
+#
+# Copyright 2005,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.
+#
from gnuradio import gr, gru, eng_notation, optfir
from gnuradio import audio
from gnuradio import usrp
-from gnuradio import blks
+from gnuradio import blks2
from gnuradio.eng_option import eng_option
from gnuradio.wxgui import slider, powermate
-from gnuradio.wxgui import stdgui, fftsink, form
+from gnuradio.wxgui import stdgui2, fftsink2, form
from optparse import OptionParser
from usrpm import usrp_dbid
import sys
# Control Stuff
#////////////////////////////////////////////////////////////////////////
-class my_graph (stdgui.gui_flow_graph):
+class my_top_block (stdgui2.std_top_block):
def __init__(self,frame,panel,vbox,argv):
- stdgui.gui_flow_graph.__init__ (self,frame,panel,vbox,argv)
+ stdgui2.std_top_block.__init__ (self,frame,panel,vbox,argv)
parser=OptionParser(option_class=eng_option)
parser.add_option("-R", "--rx-subdev-spec", type="subdev", default=None,
self.freq = 0
self.freq_step = 25e3
- self.rxpath = receive_path(self, options.rx_subdev_spec, options.gain, options.audio_output)
-
+ self.rxpath = receive_path(options.rx_subdev_spec, options.gain, options.audio_output)
+ self.connect(self.rxpath)
+
self._build_gui(vbox, options.no_gui)
# set initial values
self.src_fft = None
if 1 and not(no_gui):
- self.src_fft = fftsink.fft_sink_c (self, self.panel, title="Data from USRP",
+ self.src_fft = fftsink2.fft_sink_c(self.panel, title="Data from USRP",
fft_size=512, sample_rate=self.rxpath.if_rate,
ref_level=80, y_per_div=20)
self.connect (self.rxpath.u, self.src_fft)
vbox.Add (self.src_fft.win, 4, wx.EXPAND)
-
if 1 and not(no_gui):
- rx_fft = fftsink.fft_sink_c (self, self.panel, title="Post s/w DDC",
+ rx_fft = fftsink2.fft_sink_c(self.panel, title="Post s/w DDC",
fft_size=512, sample_rate=self.rxpath.quad_rate,
ref_level=80, y_per_div=20)
self.connect (self.rxpath.ddc, rx_fft)
vbox.Add (rx_fft.win, 4, wx.EXPAND)
if 1 and not(no_gui):
- post_deemph_fft = fftsink.fft_sink_f (self, self.panel, title="Post Deemph",
+ post_deemph_fft = fftsink2.fft_sink_f(self.panel, title="Post Deemph",
fft_size=512, sample_rate=self.rxpath.audio_rate,
y_per_div=10, ref_level=-40)
self.connect (self.rxpath.fmrx.deemph, post_deemph_fft)
vbox.Add (post_deemph_fft.win, 4, wx.EXPAND)
if 0:
- post_filt_fft = fftsink.fft_sink_f (self, self.panel, title="Post Filter",
+ post_filt_fft = fftsink2.fft_sink_f(self.panel, title="Post Filter",
fft_size=512, sample_rate=audio_rate,
y_per_div=10, ref_level=-40)
self.connect (self.guts.audio_filter, post_filt)
USE_SIMPLE_SQUELCH = False
-class receive_path(gr.hier_block):
- def __init__(self, fg, subdev_spec, gain, audio_output):
+class receive_path(gr.hier_block2):
+ def __init__(self, subdev_spec, gain, audio_output):
+ gr.hier_block2.__init__(self, "receive_path",
+ gr.io_signature(0, 0, 0), # Input signature
+ gr.io_signature(0, 0, 0)) # Output signature
self.u = usrp.source_c ()
adc_rate = self.u.adc_rate()
if USE_SIMPLE_SQUELCH:
self.squelch = gr.simple_squelch_cc(20)
else:
- self.squelch = blks.standard_squelch(fg, self.audio_rate)
+ self.squelch = blks2.standard_squelch(self.audio_rate)
# instantiate the guts of the single channel receiver
- self.fmrx = blks.nbfm_rx(fg, self.audio_rate, self.quad_rate)
+ self.fmrx = blks2.nbfm_rx(self.audio_rate, self.quad_rate)
# audio gain / mute block
self._audio_gain = gr.multiply_const_ff(1.0)
# now wire it all together
if USE_SIMPLE_SQUELCH:
- fg.connect (self.u, self.ddc, self.squelch, self.fmrx,
- self._audio_gain, audio_sink)
+ self.connect (self.u, self.ddc, self.squelch, self.fmrx,
+ self._audio_gain, audio_sink)
else:
- fg.connect (self.u, self.ddc, self.fmrx, self.squelch,
- self._audio_gain, audio_sink)
-
- gr.hier_block.__init__(self, fg, self.u, audio_sink)
+ self.connect (self.u, self.ddc, self.fmrx, self.squelch,
+ self._audio_gain, audio_sink)
if gain is None:
# if no gain was specified, use the mid-point in dB
# ////////////////////////////////////////////////////////////////////////
if __name__ == '__main__':
- app = stdgui.stdapp (my_graph, "USRP NBFM RX")
+ app = stdgui2.stdapp (my_top_block, "USRP NBFM RX")
app.MainLoop ()
#!/usr/bin/env python
+#
+# Copyright 2005,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.
+#
from gnuradio import gr, gru, eng_notation, optfir, window
from gnuradio import audio
from gnuradio import usrp
-from gnuradio import blks
from gnuradio.eng_option import eng_option
from optparse import OptionParser
from usrpm import usrp_dbid
"""
This class allows C++ code to callback into python.
"""
- def __init__(self, fg):
+ def __init__(self, tb):
gr.feval_dd.__init__(self)
- self.fg = fg
+ self.tb = tb
def eval(self, ignore):
"""
#
# message on stderr. Not exactly helpful ;)
- new_freq = self.fg.set_next_freq()
+ new_freq = self.tb.set_next_freq()
return new_freq
except Exception, e:
self.data = struct.unpack('%df' % (self.vlen,), t)
-class my_graph(gr.flow_graph):
+class my_top_block(gr.top_block):
def __init__(self):
- gr.flow_graph.__init__(self)
+ gr.top_block.__init__(self)
usage = "usage: %prog [options] min_freq max_freq"
parser = OptionParser(option_class=eng_option, usage=usage)
self.subdev.set_gain(gain)
-def main_loop(fg):
+def main_loop(tb):
while 1:
# Get the next message sent from the C++ code (blocking call).
# It contains the center frequency and the mag squared of the fft
- m = parse_msg(fg.msgq.delete_head())
+ m = parse_msg(tb.msgq.delete_head())
# Print center freq so we know that something is happening...
print m.center_freq
if __name__ == '__main__':
- fg = my_graph()
+ tb = my_top_block()
try:
- fg.start() # start executing flow graph in another thread...
- main_loop(fg)
+ tb.start() # start executing flow graph in another thread...
+ main_loop(tb)
except KeyboardInterrupt:
pass
#!/usr/bin/env python
#
-# Copyright 2004 Free Software Foundation, Inc.
+# Copyright 2004,2007 Free Software Foundation, Inc.
#
# This file is part of GNU Radio
#
tx_interp = 32 # tx should be twice rx
rx_decim = 16
- fg = gr.flow_graph ()
+ tb = gr.top_block ()
data_src = gr.lfsr_32k_source_s ()
# usrp_tx = usrp.sink_s (0, tx_interp, 1, 0x98)
usrp_tx = usrp.sink_s (0, tx_interp)
- fg.connect (data_src, usrp_tx)
+ tb.connect (data_src, usrp_tx)
usrp_rx = usrp.source_s (0, rx_decim, 1, 0x32103210, usrp.FPGA_MODE_LOOPBACK)
sink = gr.check_lfsr_32k_s ()
- fg.connect (usrp_rx, sink)
+ tb.connect (usrp_rx, sink)
# file_sink = gr.file_sink (gr.sizeof_short, "loopback.dat")
- # fg.connect (usrp_rx, file_sink)
+ # tb.connect (usrp_rx, file_sink)
- return fg
+ return tb
def main ():
- fg = build_graph ()
+ tb = build_graph ()
try:
- fg.run()
+ tb.run()
except KeyboardInterrupt:
pass
#!/usr/bin/env python
+#
+# 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.
+#
+
"""
Realtime capture and display of analog Tv stations.
Can also use a file as source or sink
print "FYI: gr-video-sdl is not installed"
print "realtime SDL video output window will not be available"
from gnuradio import usrp
-from gnuradio import blks
from gnuradio.eng_option import eng_option
from gnuradio.wxgui import slider, powermate
-from gnuradio.wxgui import stdgui, fftsink, form
+from gnuradio.wxgui import stdgui2, fftsink2, form
from optparse import OptionParser
from usrpm import usrp_dbid
import sys
usrp_dbid.BASIC_RX))
-class tv_rx_graph (stdgui.gui_flow_graph):
+class tv_rx_block (stdgui2.std_top_block):
def __init__(self,frame,panel,vbox,argv):
- stdgui.gui_flow_graph.__init__ (self,frame,panel,vbox,argv)
+ stdgui2.std_top_block.__init__ (self,frame,panel,vbox,argv)
usage="%prog: [options] [input_filename]. \n If you don't specify an input filename the usrp will be used as source\n " \
"Make sure your input capture file containes interleaved shorts not complex floats"
if __name__ == '__main__':
- app = stdgui.stdapp (tv_rx_graph, "USRP TV RX black-and-white")
+ app = stdgui2.stdapp (tv_rx_block, "USRP TV RX black-and-white")
app.MainLoop ()
#!/usr/bin/env python
+#
+# 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.
+#
"""
Reads from a file and generates PAL TV pictures in black and white
print "realtime \"sdl\" video output window will not be available"
-class my_graph(gr.flow_graph):
+class my_top_block(gr.top_block):
def __init__(self):
- gr.flow_graph.__init__(self)
+ gr.top_block.__init__(self)
usage="%prog: [options] output_filename. \n Special output_filename \"sdl\" will use video_sink_sdl as realtime output window. " \
"You then need to have gr-video-sdl installed. \n" \
if __name__ == '__main__':
try:
- my_graph().run()
+ my_top_block().run()
except KeyboardInterrupt:
pass
#!/usr/bin/env python
+#
+# 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.
+#
from gnuradio import gr, gru, eng_notation, optfir
from gnuradio import audio
from gnuradio import usrp
-from gnuradio import blks
+from gnuradio import blks2
from gnuradio.eng_option import eng_option
from gnuradio.wxgui import slider, powermate
-from gnuradio.wxgui import stdgui, fftsink, form
+from gnuradio.wxgui import stdgui2, fftsink2, form
from optparse import OptionParser
from usrpm import usrp_dbid
import sys
usrp_dbid.BASIC_RX))
-class wfm_rx_graph (stdgui.gui_flow_graph):
+class wfm_rx_block (stdgui2.std_top_block):
def __init__(self,frame,panel,vbox,argv):
- stdgui.gui_flow_graph.__init__ (self,frame,panel,vbox,argv)
+ stdgui2.std_top_block.__init__ (self,frame,panel,vbox,argv)
parser=OptionParser(option_class=eng_option)
parser.add_option("-R", "--rx-subdev-spec", type="subdev", default=None,
#print len(chan_filt_coeffs)
chan_filt = gr.fir_filter_ccf (chanfilt_decim, chan_filt_coeffs)
- self.guts = blks.wfm_rcv (self, demod_rate, audio_decimation)
+ self.guts = blks2.wfm_rcv (demod_rate, audio_decimation)
self.volume_control = gr.multiply_const_ff(self.vol)
if 1:
- self.src_fft = fftsink.fft_sink_c (self, self.panel, title="Data from USRP",
+ self.src_fft = fftsink2.fft_sink_c(self.panel, title="Data from USRP",
fft_size=512, sample_rate=usrp_rate)
self.connect (self.u, self.src_fft)
vbox.Add (self.src_fft.win, 4, wx.EXPAND)
if 1:
- post_filt_fft = fftsink.fft_sink_f (self, self.panel, title="Post Demod",
+ post_filt_fft = fftsink2.fft_sink_f(self.panel, title="Post Demod",
fft_size=1024, sample_rate=usrp_rate,
y_per_div=10, ref_level=0)
self.connect (self.guts.fm_demod, post_filt_fft)
vbox.Add (post_filt_fft.win, 4, wx.EXPAND)
if 0:
- post_deemph_fft = fftsink.fft_sink_f (self, self.panel, title="Post Deemph",
+ post_deemph_fft = fftsink2.fft_sink_f(self.panel, title="Post Deemph",
fft_size=512, sample_rate=audio_rate,
y_per_div=10, ref_level=-20)
self.connect (self.guts.deemph, post_deemph_fft)
if __name__ == '__main__':
- app = stdgui.stdapp (wfm_rx_graph, "USRP WFM RX")
+ app = stdgui2.stdapp (wfm_rx_block, "USRP WFM RX")
app.MainLoop ()
#!/usr/bin/env python
+#
+# 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.
+#
from gnuradio import gr, gru, eng_notation, optfir
from gnuradio import audio
from gnuradio import usrp
-from gnuradio import blks
+from gnuradio import blks2
from gnuradio.eng_option import eng_option
from optparse import OptionParser
from usrpm import usrp_dbid
usrp_dbid.BASIC_RX))
-class wfm_rx_graph (gr.flow_graph):
+class wfm_rx_block (gr.top_block):
def __init__(self):
- gr.flow_graph.__init__(self)
+ gr.top_block.__init__(self)
parser=OptionParser(option_class=eng_option)
parser.add_option("-R", "--rx-subdev-spec", type="subdev", default=None,
for n in range(2):
chan_filt = gr.fir_filter_ccf (chanfilt_decim, chan_filt_coeffs)
- guts = blks.wfm_rcv (self, demod_rate, audio_decimation)
+ guts = blks2.wfm_rcv (demod_rate, audio_decimation)
volume_control = gr.multiply_const_ff(self.vol)
self.connect((di, n), chan_filt)
self.connect(chan_filt, guts, volume_control)
def set_gain(self, gain):
self.subdev.set_gain(gain)
+ def __del__(self):
+ # Avoid weak-reference error
+ del self.subdev
if __name__ == '__main__':
- fg = wfm_rx_graph()
+ tb = wfm_rx_block()
try:
- fg.run()
+ tb.run()
except KeyboardInterrupt:
pass
#!/usr/bin/env python
+#
+# 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.
+#
from gnuradio import gr, gru, eng_notation, optfir
from gnuradio import audio
from gnuradio import usrp
-from gnuradio import blks
+from gnuradio import blks2
from gnuradio.eng_option import eng_option
from optparse import OptionParser
from usrpm import usrp_dbid
usrp_dbid.BASIC_RX))
-class wfm_rx_graph (gr.flow_graph):
+class wfm_rx_block (gr.top_block):
def __init__(self):
- gr.flow_graph.__init__(self)
+ gr.top_block.__init__(self)
parser=OptionParser(option_class=eng_option)
parser.add_option("-R", "--rx-subdev-spec", type="subdev", default=None,
#print len(chan_filt_coeffs)
chan_filt = gr.fir_filter_ccf (chanfilt_decim, chan_filt_coeffs)
- self.guts = blks.wfm_rcv (self, demod_rate, audio_decimation)
+ self.guts = blks2.wfm_rcv (demod_rate, audio_decimation)
self.volume_control = gr.multiply_const_ff(self.vol)
if __name__ == '__main__':
- fg = wfm_rx_graph()
+ tb = wfm_rx_block()
try:
- fg.run()
+ tb.run()
except KeyboardInterrupt:
pass
#!/usr/bin/env python
+#
+# 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.
+#
from gnuradio import gr, gru, eng_notation, optfir
from gnuradio import audio
from gnuradio import usrp
-from gnuradio import blks
+from gnuradio import blks2
from gnuradio.eng_option import eng_option
from gnuradio.wxgui import slider, powermate
-from gnuradio.wxgui import stdgui, fftsink, form, scopesink
+from gnuradio.wxgui import stdgui2, fftsink2, form, scopesink2
from optparse import OptionParser
from usrpm import usrp_dbid
import sys
usrp_dbid.TV_RX_REV_3,
usrp_dbid.BASIC_RX))
-class wfm_rx_graph (stdgui.gui_flow_graph):
+class wfm_rx_block (stdgui2.std_top_block):
def __init__(self,frame,panel,vbox,argv):
- stdgui.gui_flow_graph.__init__ (self,frame,panel,vbox,argv)
+ stdgui2.std_top_block.__init__ (self,frame,panel,vbox,argv)
parser=OptionParser(option_class=eng_option)
parser.add_option("-R", "--rx-subdev-spec", type="subdev", default=None,
chan_filt = gr.fir_filter_ccf (chanfilt_decim, chan_filt_coeffs)
- #self.guts = blks.wfm_rcv (self, demod_rate, audio_decimation)
- self.guts = blks.wfm_rcv_pll (self, demod_rate, audio_decimation)
+ #self.guts = blks2.wfm_rcv (demod_rate, audio_decimation)
+ self.guts = blks2.wfm_rcv_pll (demod_rate, audio_decimation)
# FIXME rework {add,multiply}_const_* to handle multiple streams
self.volume_control_l = gr.multiply_const_ff(self.vol)
if 1:
- self.src_fft = fftsink.fft_sink_c (self, self.panel, title="Data from USRP",
+ self.src_fft = fftsink2.fft_sink_c(self.panel, title="Data from USRP",
fft_size=512, sample_rate=usrp_rate)
self.connect (self.u, self.src_fft)
vbox.Add (self.src_fft.win, 4, wx.EXPAND)
if 1:
- post_fm_demod_fft = fftsink.fft_sink_f (self, self.panel, title="Post FM Demod",
- fft_size=512, sample_rate=demod_rate,
- y_per_div=10, ref_level=0)
+ post_fm_demod_fft = fftsink2.fft_sink_f(self.panel, title="Post FM Demod",
+ fft_size=512, sample_rate=demod_rate,
+ y_per_div=10, ref_level=0)
self.connect (self.guts.fm_demod, post_fm_demod_fft)
vbox.Add (post_fm_demod_fft.win, 4, wx.EXPAND)
if 0:
- post_stereo_carrier_generator_fft = fftsink.fft_sink_c (self, self.panel, title="Post Stereo_carrier_generator",
+ post_stereo_carrier_generator_fft = fftsink2.fft_sink_c (self.panel, title="Post Stereo_carrier_generator",
fft_size=512, sample_rate=audio_rate,
y_per_div=10, ref_level=0)
self.connect (self.guts.stereo_carrier_generator, post_stereo_carrier_generator_fft)
vbox.Add (post_stereo_carrier_generator_fft.win, 4, wx.EXPAND)
if 0:
- post_deemphasis_left = fftsink.fft_sink_f (self, self.panel, title="Post_Deemphasis_Left",
+ post_deemphasis_left = fftsink2.fft_sink_f (self.panel, title="Post_Deemphasis_Left",
fft_size=512, sample_rate=audio_rate,
y_per_div=10, ref_level=0)
self.connect (self.guts.deemph_Left, post_deemphasis_left)
vbox.Add (post_deemphasis_left.win, 4, wx.EXPAND)
if 0:
- post_deemphasis_right = fftsink.fft_sink_f (self, self.panel, title="Post_Deemphasis_Right",
+ post_deemphasis_right = fftsink2.fft_sink_f(self.panel, title="Post_Deemphasis_Right",
fft_size=512, sample_rate=audio_rate,
y_per_div=10, ref_level=-20)
self.connect (self.guts.deemph_Left, post_deemphasis_right)
if 0:
- LmR_fft = fftsink.fft_sink_f (self, self.panel, title="LmR",
- fft_size=512, sample_rate=audio_rate,
- y_per_div=10, ref_level=-20)
+ LmR_fft = fftsink2.fft_sink_f(self.panel, title="LmR",
+ fft_size=512, sample_rate=audio_rate,
+ y_per_div=10, ref_level=-20)
self.connect (self.guts.LmR_real,LmR_fft)
vbox.Add (LmR_fft.win, 4, wx.EXPAND)
if 0:
- self.scope = scopesink.scope_sink_f(self, self.panel, sample_rate=demod_rate)
+ self.scope = scopesink2.scope_sink_f(self.panel, sample_rate=demod_rate)
self.connect (self.guts.fm_demod_a,self.scope)
vbox.Add (self.scope.win,4,wx.EXPAND)
if __name__ == '__main__':
- app = stdgui.stdapp (wfm_rx_graph, "USRP WFM RX")
+ app = stdgui2.stdapp (wfm_rx_block, "USRP WFM RX")
app.MainLoop ()
from gnuradio import gr, gru, eng_notation, optfir
from gnuradio import audio
from gnuradio import usrp
-from gnuradio import blks
-from gnuradio.blksimpl.fm_emph import fm_deemph
+from gnuradio.blks2impl.fm_emph import fm_deemph
from gnuradio.eng_option import eng_option
from gnuradio.wxgui import slider, powermate
-from gnuradio.wxgui import stdgui, fftsink, form
+from gnuradio.wxgui import stdgui2, fftsink2, form
from optparse import OptionParser
from usrpm import usrp_dbid
import sys
usrp_dbid.BASIC_RX))
-class wfm_rx_sca_graph (stdgui.gui_flow_graph):
+class wfm_rx_sca_block (stdgui2.std_top_block):
def __init__(self,frame,panel,vbox,argv):
- stdgui.gui_flow_graph.__init__ (self,frame,panel,vbox,argv)
+ stdgui2.std_top_block.__init__ (self,frame,panel,vbox,argv)
parser=OptionParser(option_class=eng_option)
parser.add_option("-R", "--rx-subdev-spec", type="subdev", default=None,
self.audio_filter = gr.fir_filter_fff (audio_decimation, audio_coeffs)
# Create deemphasis block that is applied after SCA demodulation
- self.deemph = fm_deemph (self, audio_rate, sca_tau)
+ self.deemph = fm_deemph (audio_rate, sca_tau)
self.volume_control = gr.multiply_const_ff(self.vol)
return self.set_sca_freq(kv['sca_freq'])
if 1:
- self.src_fft = fftsink.fft_sink_c (self, self.panel, title="Data from USRP",
+ self.src_fft = fftsink2.fft_sink_c(self.panel, title="Data from USRP",
fft_size=512, sample_rate=usrp_rate)
self.connect (self.u, self.src_fft)
vbox.Add (self.src_fft.win, 4, wx.EXPAND)
if 1:
- post_demod_fft = fftsink.fft_sink_f (self, self.panel, title="Post FM Demod",
- fft_size=2048, sample_rate=demod_rate,
- y_per_div=10, ref_level=0)
+ post_demod_fft = fftsink2.fft_sink_f(self.panel, title="Post FM Demod",
+ fft_size=2048, sample_rate=demod_rate,
+ y_per_div=10, ref_level=0)
self.connect (self.fm_demod, post_demod_fft)
vbox.Add (post_demod_fft.win, 4, wx.EXPAND)
if 0:
- post_demod_sca_fft = fftsink.fft_sink_f (self, self.panel, title="Post SCA Demod",
+ post_demod_sca_fft = fftsink2.fft_sink_f(self.panel, title="Post SCA Demod",
fft_size=1024, sample_rate=sca_demod_rate,
y_per_div=10, ref_level=0)
self.connect (self.fm_demod_sca, post_demod_sca_fft)
vbox.Add (post_demod_sca_fft.win, 4, wx.EXPAND)
if 0:
- post_deemph_fft = fftsink.fft_sink_f (self, self.panel, title="Post SCA Deemph",
+ post_deemph_fft = fftsink2.fft_sink_f (self.panel, title="Post SCA Deemph",
fft_size=512, sample_rate=audio_rate,
y_per_div=10, ref_level=-20)
self.connect (self.deemph, post_deemph_fft)
if __name__ == '__main__':
- app = stdgui.stdapp (wfm_rx_sca_graph, "USRP WFM SCA RX")
+ app = stdgui2.stdapp (wfm_rx_sca_block, "USRP WFM SCA RX")
app.MainLoop ()
#!/usr/bin/env python
+#
+# 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.
+#
from gnuradio import gr, gru, eng_notation, optfir
from gnuradio import audio
from gnuradio import usrp
-from gnuradio import blks
+from gnuradio import blks2
from gnuradio.eng_option import eng_option
from gnuradio.wxgui import slider, powermate
-from gnuradio.wxgui import stdgui, fftsink, form
+from gnuradio.wxgui import stdgui2, fftsink2, form
from optparse import OptionParser
from usrpm import usrp_dbid
import sys
usrp_dbid.BASIC_RX))
-class wxapt_rx_graph (stdgui.gui_flow_graph):
+class wxapt_rx_block (stdgui2.std_top_block):
def __init__(self,frame,panel,vbox,argv):
- stdgui.gui_flow_graph.__init__ (self,frame,panel,vbox,argv)
+ stdgui2.std_top_block.__init__ (self,frame,panel,vbox,argv)
parser=OptionParser(option_class=eng_option)
parser.add_option("-R", "--rx-subdev-spec", type="subdev", default=None,
#print len(chan_filt_coeffs)
chan_filt = gr.fir_filter_ccf (chanfilt_decim, chan_filt_coeffs)
- self.guts = blks.wfm_rcv (self, demod_rate, audio_decimation)
+ self.guts = blks2.wfm_rcv (demod_rate, audio_decimation)
self.volume_control = gr.multiply_const_ff(self.vol)
if 1:
- self.src_fft = fftsink.fft_sink_c (self, self.panel, title="Data from USRP",
+ self.src_fft = fftsink2.fft_sink_c (self.panel, title="Data from USRP",
fft_size=512, sample_rate=usrp_rate)
self.connect (self.u, self.src_fft)
vbox.Add (self.src_fft.win, 4, wx.EXPAND)
if 1:
- post_deemph_fft = fftsink.fft_sink_f (self, self.panel, title="Post Deemph",
+ post_deemph_fft = fftsink2.fft_sink_f (self.panel, title="Post Deemph",
fft_size=512, sample_rate=demod_rate,
y_per_div=10, ref_level=-20)
self.connect (self.guts.deemph, post_deemph_fft)
vbox.Add (post_deemph_fft.win, 4, wx.EXPAND)
if 1:
- post_filt_fft = fftsink.fft_sink_f (self, self.panel, title="Post Filter",
+ post_filt_fft = fftsink2.fft_sink_f (self.panel, title="Post Filter",
fft_size=512, sample_rate=audio_rate,
y_per_div=10, ref_level=0)
self.connect (self.guts.audio_filter, post_filt_fft)
if __name__ == '__main__':
- app = stdgui.stdapp (wxapt_rx_graph, "USRP WXAPT RX")
+ app = stdgui2.stdapp (wxapt_rx_block, "USRP WXAPT RX")
app.MainLoop ()
run_tests
-grblkspythondir = $(grpythondir)/blksimpl
+grblkspythondir = $(grpythondir)/blks2impl
grblkspython_PYTHON = \
cvsd.py
from gnuradio import gr
from gnuradio.vocoder import cvsd_vocoder
-class cvsd_encode(gr.hier_block):
+class cvsd_encode(gr.hier_block2):
'''
This is a wrapper for the CVSD encoder that performs interpolation and filtering
necessary to work with the vocoding. It converts an incoming float (+-1) to a short, scales
higher the interpolation rate are, the better the sound quality.
'''
- def __init__(self, fg, resample=8, bw=0.5):
+ def __init__(self, resample=8, bw=0.5):
'''
When using the CVSD vocoder, appropriate sampling rates are from 8k to 64k with resampling rates
from 1 to 8. A rate of 8k with a resampling rate of 8 provides a good quality signal.
'''
+
+ gr.hier_block2.__init__(self, "cvsd_encode",
+ gr.io_signature(1, 1, gr.sizeof_float), # Input signature
+ gr.io_signature(1, 1, gr.sizeof_char)) # Output signature
+
scale_factor = 32000.0
self.interp = resample
f2s = gr.float_to_short()
enc = cvsd_vocoder.encode_sb()
- fg.connect(src_scale, interp, f2s, enc)
- gr.hier_block.__init__(self, fg, src_scale, enc)
+ self.connect(self, src_scale, interp, f2s, enc, self)
-class cvsd_decode(gr.hier_block):
+class cvsd_decode(gr.hier_block2):
'''
This is a wrapper for the CVSD decoder that performs decimation and filtering
necessary to work with the vocoding. It converts an incoming CVSD-encoded short to a float, decodes it
higher the interpolation rate are, the better the sound quality.
'''
- def __init__(self, fg, resample=8, bw=0.5):
+ def __init__(self, resample=8, bw=0.5):
'''
When using the CVSD vocoder, appropriate sampling rates are from 8k to 64k with resampling rates
from 1 to 8. A rate of 8k with a resampling rate of 8 provides a good quality signal.
'''
+ gr.hier_block2.__init__(self, "cvsd_decode",
+ gr.io_signature(1, 1, gr.sizeof_char), # Input signature
+ gr.io_signature(1, 1, gr.sizeof_float)) # Output signature
+
scale_factor = 32000.0
self.decim = resample
decim = gr.fir_filter_fff(self.decim, taps)
sink_scale = gr.multiply_const_ff(1.0/scale_factor)
- fg.connect(dec, s2f, decim, sink_scale)
- gr.hier_block.__init__(self, fg, dec, sink_scale)
+ self.connect(self, dec, s2f, decim, sink_scale, self)
# Boston, MA 02110-1301, USA.
#
-from gnuradio import gr, blks
+from gnuradio import gr, blks2
from gnuradio import audio
from gnuradio.vocoder import cvsd_vocoder
sample_rate = 8000
scale_factor = 32000
- fg = gr.flow_graph()
+ tb = gr.top_block()
src = audio.source(sample_rate, "plughw:0,0")
src_scale = gr.multiply_const_ff(scale_factor)
- interp = blks.rational_resampler_fff(fg, 8, 1)
+ interp = blks2.rational_resampler_fff(8, 1)
f2s = gr.float_to_short ()
enc = cvsd_vocoder.encode_sb()
dec = cvsd_vocoder.decode_bs()
s2f = gr.short_to_float ()
- decim = blks.rational_resampler_fff(fg, 1, 8)
+ decim = blks2.rational_resampler_fff(1, 8)
sink_scale = gr.multiply_const_ff(1.0/scale_factor)
sink = audio.sink(sample_rate, "plughw:0,0")
- fg.connect(src, src_scale, interp, f2s, enc)
- fg.connect(enc, dec, s2f, decim, sink_scale, sink)
+ tb.connect(src, src_scale, interp, f2s, enc)
+ tb.connect(enc, dec, s2f, decim, sink_scale, sink)
if 0: # debug
- fg.connect(src, gr.file_sink(gr.sizeof_float, "source.dat"))
- fg.connect(src_scale, gr.file_sink(gr.sizeof_float, "src_scale.dat"))
- fg.connect(interp, gr.file_sink(gr.sizeof_float, "interp.dat"))
- fg.connect(f2s, gr.file_sink(gr.sizeof_short, "f2s.dat"))
- fg.connect(enc, gr.file_sink(gr.sizeof_char, "enc.dat"))
- fg.connect(dec, gr.file_sink(gr.sizeof_short, "dec.dat"))
- fg.connect(s2f, gr.file_sink(gr.sizeof_float, "s2f.dat"))
- fg.connect(decim, gr.file_sink(gr.sizeof_float, "decim.dat"))
- fg.connect(sink_scale, gr.file_sink(gr.sizeof_float, "sink_scale.dat"))
+ tb.conect(src, gr.file_sink(gr.sizeof_float, "source.dat"))
+ tb.conect(src_scale, gr.file_sink(gr.sizeof_float, "src_scale.dat"))
+ tb.conect(interp, gr.file_sink(gr.sizeof_float, "interp.dat"))
+ tb.conect(f2s, gr.file_sink(gr.sizeof_short, "f2s.dat"))
+ tb.conect(enc, gr.file_sink(gr.sizeof_char, "enc.dat"))
+ tb.conect(dec, gr.file_sink(gr.sizeof_short, "dec.dat"))
+ tb.conect(s2f, gr.file_sink(gr.sizeof_float, "s2f.dat"))
+ tb.conect(decim, gr.file_sink(gr.sizeof_float, "decim.dat"))
+ tb.conect(sink_scale, gr.file_sink(gr.sizeof_float, "sink_scale.dat"))
- return fg
+ return tb
if __name__ == '__main__':
- fg = build_graph()
- fg.start()
- raw_input ('Press Enter to exit: ')
- fg.stop()
+ tb = build_graph()
+ print "Enter CTRL-C to stop"
+ try:
+ tb.run()
+ except KeyboardInterrupt:
+ pass
# Boston, MA 02110-1301, USA.
#
-from gnuradio import gr, gr_unittest, blks
+from gnuradio import gr, gr_unittest, blks2
import cvsd_vocoder
class qa_cvsd_test (gr_unittest.TestCase):
def setUp (self):
- self.fg = gr.flow_graph ()
+ self.tb = gr.top_block()
def tearDown (self):
- self.fg = None
+ self.tb = None
+ """ Disable for now
def test01(self):
sample_rate = 8000
scale_factor = 32000
head = gr.head(gr.sizeof_float, 100)
src_scale = gr.multiply_const_ff(scale_factor)
- interp = blks.rational_resampler_fff(self.fg, 8, 1)
+ interp = blks2.rational_resampler_fff(8, 1)
f2s = gr.float_to_short ()
enc = cvsd_vocoder.encode_sb()
dec = cvsd_vocoder.decode_bs()
s2f = gr.short_to_float ()
- decim = blks.rational_resampler_fff(self.fg, 1, 8)
+ decim = blks2.rational_resampler_fff(1, 8)
sink_scale = gr.multiply_const_ff(1.0/scale_factor)
sink = gr.vector_sink_f()
- self.fg.connect(src, head, src_scale, interp, f2s, enc)
- self.fg.connect(enc, dec, s2f, decim, sink_scale, sink)
- self.fg.run()
-
+ self.tb.connect(src, src_scale, interp, f2s, enc)
+ self.tb.connect(enc, dec, s2f, decim, sink_scale, head, sink)
+ self.tb.run()
+ print sink.data()
+
self.assertFloatTuplesAlmostEqual (expected_data, sink.data(), 5)
-
+ """
+
if __name__ == '__main__':
gr_unittest.main ()
if options.log:
self.connect((bank, i), gr.file_sink(gr.sizeof_gr_complex, 'chan_'+'%3.3f'%(freq/1e6)+'.dat'))
+ def __del__(self):
+ # Avoid weak-ref error
+ del self.subdev
+
def main():
parser = OptionParser(option_class=eng_option)
parser.add_option("-f", "--frequency", type="eng_float", default=929.5e6,
#!/usr/bin/env python
#
-# Copyright 2004,2005 Free Software Foundation, Inc.
+# Copyright 2004,2005,2007 Free Software Foundation, Inc.
#
# This file is part of GNU Radio
#
from gnuradio import usrp
from gnuradio import eng_notation
from gnuradio.eng_option import eng_option
-from gnuradio.wxgui import stdgui, fftsink, waterfallsink, scopesink, form, slider
+from gnuradio.wxgui import stdgui2, fftsink2, waterfallsink2, scopesink2, form, slider
from optparse import OptionParser
import wx
import sys
return (0, 0)
-class app_flow_graph(stdgui.gui_flow_graph):
+class app_top_block(stdgui2.std_top_block):
def __init__(self, frame, panel, vbox, argv):
- stdgui.gui_flow_graph.__init__(self)
+ stdgui2.std_top_block.__init__(self, frame, panel, vbox, argv)
self.frame = frame
self.panel = panel
if options.waterfall:
self.scope = \
- waterfallsink.waterfall_sink_c (self, panel, fft_size=1024, sample_rate=input_rate)
+ waterfallsink2.waterfall_sink_c (panel, fft_size=1024, sample_rate=input_rate)
elif options.oscilloscope:
- self.scope = scopesink.scope_sink_c(self, panel, sample_rate=input_rate)
+ self.scope = scopesink2.scope_sink_c(panel, sample_rate=input_rate)
else:
- self.scope = fftsink.fft_sink_c (self, panel, fft_size=1024, sample_rate=input_rate)
+ self.scope = fftsink2.fft_sink_c (panel, fft_size=1024, sample_rate=input_rate)
self.connect(self.u, self.scope)
return ok
def main ():
- app = stdgui.stdapp(app_flow_graph, "USRP FFT", nstatus=1)
+ app = stdgui2.stdapp(app_top_block, "USRP FFT", nstatus=1)
app.MainLoop()
if __name__ == '__main__':
#!/usr/bin/env python
#
-# Copyright 2004,2005,2006 Free Software Foundation, Inc.
+# Copyright 2004,2005,2006,2007 Free Software Foundation, Inc.
#
# This file is part of GNU Radio
#
from gnuradio import usrp
from gnuradio import eng_notation
from gnuradio.eng_option import eng_option
-from gnuradio.wxgui import stdgui, fftsink, waterfallsink, scopesink, form, slider
+from gnuradio.wxgui import stdgui2, scopesink2, form, slider
from optparse import OptionParser
import wx
import sys
return (0, 0)
-class app_flow_graph(stdgui.gui_flow_graph):
+class app_top_block(stdgui2.std_top_block):
def __init__(self, frame, panel, vbox, argv):
- stdgui.gui_flow_graph.__init__(self)
+ stdgui2.std_top_block.__init__(self, frame, panel, vbox, argv)
self.frame = frame
self.panel = panel
input_rate = self.u.adc_freq() / self.u.decim_rate()
- self.scope = scopesink.scope_sink_c(self, panel, sample_rate=input_rate,
+ self.scope = scopesink2.scope_sink_c(panel, sample_rate=input_rate,
frame_decim=options.frame_decim,
v_scale=options.v_scale,
t_scale=options.t_scale)
return ok
def main ():
- app = stdgui.stdapp(app_flow_graph, "USRP O'scope", nstatus=1)
+ app = stdgui2.stdapp(app_top_block, "USRP O'scope", nstatus=1)
app.MainLoop()
if __name__ == '__main__':
from gnuradio import usrp
from gnuradio.eng_option import eng_option
from optparse import OptionParser
+import sys
-class my_graph(gr.flow_graph):
+class my_top_block(gr.top_block):
def __init__(self):
- gr.flow_graph.__init__(self)
+ gr.top_block.__init__(self)
usage="%prog: [options] output_filename"
parser = OptionParser(option_class=eng_option, usage=usage)
sys.stderr.write('Failed to set frequency\n')
raise SystemExit, 1
+ def __del__(self):
+ # Avoid weak reference error
+ del self.subdev
if __name__ == '__main__':
try:
- my_graph().run()
+ my_top_block().run()
except KeyboardInterrupt:
pass
#!/usr/bin/env python
-
-from gnuradio import gr, gru, usrp, optfir, audio, eng_notation, blks
+#
+# Copyright 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.
+#
+
+from gnuradio import gr, gru, usrp, optfir, audio, eng_notation, blks2
from gnuradio.eng_option import eng_option
from optparse import OptionParser
+import sys
"""
This example application demonstrates receiving and demodulating
# (usrp_decim, channel_decim, audio_decim, channel_pass, channel_stop, demod)
demod_params = {
- 'AM' : (250, 16, 1, 5000, 8000, blks.demod_10k0a3e_cf),
- 'FM' : (250, 8, 4, 8000, 9000, blks.demod_20k0f3e_cf),
- 'WFM' : (250, 1, 8, 90000, 100000, blks.demod_200kf3e_cf)
+ 'AM' : (250, 16, 1, 5000, 8000, blks2.demod_10k0a3e_cf),
+ 'FM' : (250, 8, 4, 8000, 9000, blks2.demod_20k0f3e_cf),
+ 'WFM' : (250, 1, 8, 90000, 100000, blks2.demod_200kf3e_cf)
}
-class usrp_source_c(gr.hier_block):
+class usrp_src(gr.hier_block2):
"""
Create a USRP source object supplying complex floats.
Calibration value is the offset from the tuned frequency to
the actual frequency.
"""
- def __init__(self, fg, subdev_spec, decim, gain=None, calibration=0.0):
+ def __init__(self, subdev_spec, decim, gain=None, calibration=0.0):
+ gr.hier_block2.__init__(self, "usrp_src",
+ gr.io_signature(0, 0, 0), # Input signature
+ gr.io_signature(1, 1, gr.sizeof_gr_complex)) # Output signature
+
self._decim = decim
self._src = usrp.source_c()
if subdev_spec is None:
self._subdev.set_gain(gain)
self._cal = calibration
- gr.hier_block.__init__(self, fg, self._src, self._src)
+ self.connect(self._src, self)
def tune(self, freq):
result = usrp.tune(self._src, 0, self._subdev, freq+self._cal)
def rate(self):
return self._src.adc_rate()/self._decim
-class app_flow_graph(gr.flow_graph):
- def __init__(self, options, args):
- gr.flow_graph.__init__(self)
+class app_top_block(gr.top_block):
+ def __init__(self, options):
+ gr.top_block.__init__(self)
self.options = options
- self.args = args
(usrp_decim, channel_decim, audio_decim,
channel_pass, channel_stop, demod) = demod_params[options.modulation]
- USRP = usrp_source_c(self, # Flow graph
- options.rx_subdev_spec, # Daugherboard spec
- usrp_decim, # IF decimation ratio
- options.gain, # Receiver gain
- options.calibration) # Frequency offset
+ USRP = usrp_src(options.rx_subdev_spec, # Daugherboard spec
+ usrp_decim, # IF decimation ratio
+ options.gain, # Receiver gain
+ options.calibration) # Frequency offset
USRP.tune(options.frequency)
if_rate = USRP.rate()
1.0, # Initial gain
1.0) # Maximum gain
- DEMOD = demod(self, channel_rate, audio_decim)
+ DEMOD = demod(channel_rate, audio_decim)
# From RF to audio
self.connect(USRP, CHAN, RFSQL, AGC, DEMOD)
out_lcm = gru.lcm(audio_rate, options.output_rate)
out_interp = int(out_lcm // audio_rate)
out_decim = int(out_lcm // options.output_rate)
- RSAMP = blks.rational_resampler_fff(self, out_interp, out_decim)
+ RSAMP = blks2.rational_resampler_fff(out_interp, out_decim)
self.connect(tail, RSAMP)
tail = RSAMP
def main():
parser = OptionParser(option_class=eng_option)
- parser.add_option("-f", "--frequency", type="eng_float",
+ parser.add_option("-f", "--frequency", type="eng_float", default=None,
help="set receive frequency to Hz", metavar="Hz")
parser.add_option("-R", "--rx-subdev-spec", type="subdev",
help="select USRP Rx side A or B", metavar="SUBDEV")
help="set CTCSS squelch to FREQ", metavar="FREQ")
(options, args) = parser.parse_args()
+ if options.frequency is None:
+ print "Must supply receive frequency with -f"
+ sys.exit(1)
+
if options.frequency < 1e6:
options.frequency *= 1e6
- fg = app_flow_graph(options, args)
+ tb = app_top_block(options)
try:
- fg.run()
+ tb.run()
except KeyboardInterrupt:
pass
import sys
-class my_graph(gr.flow_graph):
+class my_top_block(gr.top_block):
def __init__ (self):
- gr.flow_graph.__init__(self)
+ gr.top_block.__init__(self)
# controllable values
self.interp = 64
parser.print_help()
raise SystemExit
- fg = my_graph()
- fg.set_interpolator (options.interp)
- fg.set_waveform_type (options.type)
- fg.set_waveform_freq (options.waveform_freq)
- fg.set_waveform_ampl (options.amplitude)
- fg.set_waveform_offset (options.offset)
+ tb = my_top_block()
+ tb.set_interpolator (options.interp)
+ tb.set_waveform_type (options.type)
+ tb.set_waveform_freq (options.waveform_freq)
+ tb.set_waveform_ampl (options.amplitude)
+ tb.set_waveform_offset (options.offset)
# determine the daughterboard subdevice we're using
if options.tx_subdev_spec is None:
- options.tx_subdev_spec = usrp.pick_tx_subdevice(fg.u)
+ options.tx_subdev_spec = usrp.pick_tx_subdevice(tb.u)
- m = usrp.determine_tx_mux_value(fg.u, options.tx_subdev_spec)
+ m = usrp.determine_tx_mux_value(tb.u, options.tx_subdev_spec)
#print "mux = %#04x" % (m,)
- fg.u.set_mux(m)
- fg.subdev = usrp.selected_subdev(fg.u, options.tx_subdev_spec)
- print "Using TX d'board %s" % (fg.subdev.side_and_name(),)
+ tb.u.set_mux(m)
+ tb.subdev = usrp.selected_subdev(tb.u, options.tx_subdev_spec)
+ print "Using TX d'board %s" % (tb.subdev.side_and_name(),)
if options.gain is None:
- fg.subdev.set_gain(fg.subdev.gain_range()[1]) # set max Tx gain
+ tb.subdev.set_gain(fg.subdev.gain_range()[1]) # set max Tx gain
else:
- fg.subdev.set_gain(options.gain) # set max Tx gain
+ tb.subdev.set_gain(options.gain) # set max Tx gain
- if not fg.set_freq(options.rf_freq):
+ if not tb.set_freq(options.rf_freq):
sys.stderr.write('Failed to set RF frequency\n')
raise SystemExit
- fg.subdev.set_enable(True) # enable transmitter
+ tb.subdev.set_enable(True) # enable transmitter
try:
- fg.run()
+ tb.run()
except KeyboardInterrupt:
pass
#!/usr/bin/env python
#
-# Copyright 2004 Free Software Foundation, Inc.
+# Copyright 2004,2007 Free Software Foundation, Inc.
#
# This file is part of GNU Radio
#
def build_graph ():
rx_decim = 32
- fg = gr.flow_graph ()
+ tb = gr.top_block ()
usrp_rx = usrp.source_s (0, rx_decim, 1, 0x32103210, usrp.FPGA_MODE_COUNTING)
sink = gr.check_counting_s ()
- fg.connect (usrp_rx, sink)
+ tb.connect (usrp_rx, sink)
# file_sink = gr.file_sink (gr.sizeof_short, 'counting.dat')
- # fg.connect (usrp_rx, file_sink)
+ # tb.connect (usrp_rx, file_sink)
- return fg
+ return tb
def main ():
- fg = build_graph ()
+ tb = build_graph ()
try:
- fg.run()
+ tb.run()
except KeyboardInterrupt:
pass
#!/usr/bin/env python
#
-# Copyright 2004 Free Software Foundation, Inc.
+# Copyright 2004,2007 Free Software Foundation, Inc.
#
# This file is part of GNU Radio
#
from gnuradio import usrp
-def ramp_source (fg):
+def ramp_source (tb):
period = 2**16
src = gr.vector_source_s (range (-period/2, period/2, 1), True)
return src
tx_interp = 32 # tx should be twice rx
rx_decim = 16
- fg = gr.flow_graph ()
+ tb = gr.top_block ()
- data_src = ramp_source (fg)
+ data_src = ramp_source (tb)
# usrp_tx = usrp.sink_s (0, tx_interp, 1, 0x98)
usrp_tx = usrp.sink_s (0, tx_interp)
- fg.connect (data_src, usrp_tx)
+ tb.connect (data_src, usrp_tx)
usrp_rx = usrp.source_s (0, rx_decim, 1, 0x32103210, usrp.FPGA_MODE_LOOPBACK)
sink = gr.check_counting_s ()
- fg.connect (usrp_rx, sink)
+ tb.connect (usrp_rx, sink)
# file_sink = gr.file_sink (gr.sizeof_short, "loopback.dat")
- # fg.connect (usrp_rx, file_sink)
+ # tb.connect (usrp_rx, file_sink)
- return fg
+ return tb
def main ():
- fg = build_graph ()
+ tb = build_graph ()
try:
- fg.run()
+ tb.run()
except KeyboardInterrupt:
pass