diff options
97 files changed, 5250 insertions, 2084 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 5a561723b0..356ef0d4eb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -41,8 +41,8 @@ list(APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/Modules) # Set the version information here set(VERSION_INFO_MAJOR_VERSION 3) set(VERSION_INFO_API_COMPAT 7) -set(VERSION_INFO_MINOR_VERSION 1) -set(VERSION_INFO_MAINT_VERSION 0) +set(VERSION_INFO_MINOR_VERSION 2) +set(VERSION_INFO_MAINT_VERSION git) include(GrVersion) #setup version info # Append -O2 optimization flag for Debug builds diff --git a/docs/doxygen/other/perf_counters.dox b/docs/doxygen/other/perf_counters.dox index 518b04e780..c09f17c029 100644 --- a/docs/doxygen/other/perf_counters.dox +++ b/docs/doxygen/other/perf_counters.dox @@ -5,7 +5,7 @@ Each block can have a set of Performance Counters that the schedule keeps track of. These counters measure and store information about different performance metrics of their operation. The concept is -fairly extensible, but currently, GNU Radio defines five types of +fairly extensible, but currently, GNU Radio defines the following Performance Counters: \li noutput_items: number of items the block can produce. @@ -13,20 +13,21 @@ Performance Counters: \li input_buffers_full: % of how full each input buffer is. \li output_buffers_full: % of how full each output buffer is. \li work_time: number of CPU ticks during the call to general_work(). +\li work_time_total: Accumulated sum of work_time. -For each Performance Counter, we can retrieve the instantaneous, -average, and variance from the block. Access to these counters is done -through a simple set of functions added to every block in the -flowgraph: +For each Performance Counter except the work_time_total, we can +retrieve the instantaneous, average, and variance from the +block. Access to these counters is done through a simple set of +functions added to every block in the flowgraph: \code float pc_<name>[_<type>](); \endcode -In the above, the \<name\> field is one of the five counters in the -above list of counters. The optional \<type\> suffix is either 'avg' to -get the average value or 'var' to get the variance. Without a suffix, -the function returns the most recent instantaneous value. +In the above, the \<name\> field is one of the counters in the above +list of counters. The optional \<type\> suffix is either 'avg' to get +the average value or 'var' to get the variance. Without a suffix, the +function returns the most recent instantaneous value. We can also reset the Performance Counters back to zero to remove any history of the current average and variance calculations for a diff --git a/gnuradio-runtime/include/gnuradio/block.h b/gnuradio-runtime/include/gnuradio/block.h index b8cbcfc552..5cd5dbb4a4 100644 --- a/gnuradio-runtime/include/gnuradio/block.h +++ b/gnuradio-runtime/include/gnuradio/block.h @@ -461,6 +461,11 @@ namespace gr { float pc_work_time_var(); /*! + * \brief Gets total clock cycles spent in work. + */ + float pc_work_time_total(); + + /*! * \brief Resets the performance counters */ void reset_perf_counters(); diff --git a/gnuradio-runtime/include/gnuradio/block_detail.h b/gnuradio-runtime/include/gnuradio/block_detail.h index b7531baf6d..b336cb86f7 100644 --- a/gnuradio-runtime/include/gnuradio/block_detail.h +++ b/gnuradio-runtime/include/gnuradio/block_detail.h @@ -227,6 +227,8 @@ namespace gr { float pc_output_buffers_full_var(size_t which); std::vector<float> pc_output_buffers_full_var(); float pc_work_time_var(); + + float pc_work_time_total(); tpb_detail d_tpb; // used by thread-per-block scheduler int d_produce_or; @@ -257,6 +259,7 @@ namespace gr { float d_ins_work_time; float d_avg_work_time; float d_var_work_time; + float d_total_work_time; float d_pc_counter; block_detail(unsigned int ninputs, unsigned int noutputs); diff --git a/gnuradio-runtime/lib/block.cc b/gnuradio-runtime/lib/block.cc index 7a55e09561..e76daefe48 100644 --- a/gnuradio-runtime/lib/block.cc +++ b/gnuradio-runtime/lib/block.cc @@ -635,6 +635,17 @@ namespace gr { } } + float + block::pc_work_time_total() + { + if(d_detail) { + return d_detail->pc_work_time_total(); + } + else { + return 0; + } + } + void block::reset_perf_counters() { @@ -712,6 +723,13 @@ namespace gr { DISPTIME | DISPOPTSTRIP))); d_rpc_vars.push_back( + rpcbasic_sptr(new rpcbasic_register_get<block, float>( + alias(), "total work time", &block::pc_work_time_total, + pmt::mp(0), pmt::mp(1e9), pmt::mp(0), + "", "Total clock cycles in calls to work", RPC_PRIVLVL_MIN, + DISPTIME | DISPOPTSTRIP))); + + d_rpc_vars.push_back( rpcbasic_sptr(new rpcbasic_register_get<block, std::vector<float> >( alias(), "input \% full", &block::pc_input_buffers_full, pmt::make_c32vector(0,0), pmt::make_c32vector(0,1), pmt::make_c32vector(0,0), diff --git a/gnuradio-runtime/lib/block_detail.cc b/gnuradio-runtime/lib/block_detail.cc index fd1240ae56..1020916ec2 100644 --- a/gnuradio-runtime/lib/block_detail.cc +++ b/gnuradio-runtime/lib/block_detail.cc @@ -272,6 +272,7 @@ namespace gr { d_ins_work_time = diff; d_avg_work_time = diff; d_var_work_time = 0; + d_total_work_time = diff; d_ins_nproduced = nproduced; d_avg_nproduced = nproduced; d_var_nproduced = 0; @@ -300,6 +301,7 @@ namespace gr { d_ins_work_time = diff; d_avg_work_time = d_avg_work_time + d/d_pc_counter; d_var_work_time = d_var_work_time + d*d; + d_total_work_time += diff; d = nproduced - d_avg_nproduced; d_ins_nproduced = nproduced; @@ -493,4 +495,10 @@ namespace gr { return d_var_work_time/(d_pc_counter-1); } + float + block_detail::pc_work_time_total() + { + return d_total_work_time; + } + } /* namespace gr */ diff --git a/gnuradio-runtime/swig/block.i b/gnuradio-runtime/swig/block.i index 7b7ac8ee43..1f9b70ce0c 100644 --- a/gnuradio-runtime/swig/block.i +++ b/gnuradio-runtime/swig/block.i @@ -89,6 +89,7 @@ class gr::block : public gr::basic_block float pc_work_time(); float pc_work_time_avg(); float pc_work_time_var(); + float pc_work_time_total(); // Methods to manage processor affinity. void set_processor_affinity(const std::vector<int> &mask); diff --git a/gnuradio-runtime/swig/gnuradio.i b/gnuradio-runtime/swig/gnuradio.i index 0789d1ad82..c756ce9189 100644 --- a/gnuradio-runtime/swig/gnuradio.i +++ b/gnuradio-runtime/swig/gnuradio.i @@ -72,5 +72,7 @@ #include <gnuradio/block_gateway.h> #include <gnuradio/feval.h> #include <gnuradio/py_feval.h> +#include <gnuradio/high_res_timer.h> %} +%include <gnuradio/high_res_timer.h> diff --git a/gr-analog/grc/analog_agc3_xx.xml b/gr-analog/grc/analog_agc3_xx.xml index 5ad4d7829a..1e6b9fd382 100644 --- a/gr-analog/grc/analog_agc3_xx.xml +++ b/gr-analog/grc/analog_agc3_xx.xml @@ -8,7 +8,7 @@ <name>AGC3</name> <key>analog_agc3_xx</key> <import>from gnuradio import analog</import> - <make>analog.agc3_$(type.fcn)($attack_rate, $decay_rate, $reference, $gain) + <make>analog.agc3_$(type.fcn)($attack_rate, $decay_rate, $reference, $gain, $iir_update_decim) self.$(id).set_max_gain($max_gain)</make> <callback>set_attack_rate($attack_rate)</callback> <callback>set_decay_rate($decay_rate)</callback> @@ -60,6 +60,12 @@ self.$(id).set_max_gain($max_gain)</make> <value>65536</value> <type>real</type> </param> + <param> + <name>IIR Update Decimation</name> + <key>iir_update_decim</key> + <value>1</value> + <type>real</type> + </param> <sink> <name>in</name> <type>$type</type> diff --git a/gr-analog/include/gnuradio/analog/agc3_cc.h b/gr-analog/include/gnuradio/analog/agc3_cc.h index 9cd6e60e1e..eb542eae08 100644 --- a/gr-analog/include/gnuradio/analog/agc3_cc.h +++ b/gr-analog/include/gnuradio/analog/agc3_cc.h @@ -54,9 +54,11 @@ namespace gr { * \param decay_rate the update rate of the loop when in decay mode. * \param reference reference value to adjust signal power to. * \param gain initial gain value. + * \param iir_update_decim stride by this number of samples before + * computing an IIR gain update */ static sptr make(float attack_rate = 1e-1, float decay_rate = 1e-2, - float reference = 1.0, float gain = 1.0); + float reference = 1.0, float gain = 1.0, int iir_update_decim=1); virtual float attack_rate() const = 0; virtual float decay_rate() const = 0; diff --git a/gr-analog/lib/agc3_cc_impl.cc b/gr-analog/lib/agc3_cc_impl.cc index b8f1104c45..86e2212927 100644 --- a/gr-analog/lib/agc3_cc_impl.cc +++ b/gr-analog/lib/agc3_cc_impl.cc @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2006,2010,2012 Free Software Foundation, Inc. + * Copyright 2006,2010,2012,2013 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -24,6 +24,7 @@ #include "config.h" #endif +#include <float.h> #include <vector> #include "agc3_cc_impl.h" @@ -35,22 +36,23 @@ namespace gr { agc3_cc::sptr agc3_cc::make(float attack_rate, float decay_rate, - float reference, float gain) + float reference, float gain, int iir_update_decim) { return gnuradio::get_initial_sptr (new agc3_cc_impl(attack_rate, decay_rate, - reference, gain)); + reference, gain, iir_update_decim)); } agc3_cc_impl::agc3_cc_impl(float attack_rate, float decay_rate, - float reference, float gain) + float reference, float gain, int iir_update_decim) : sync_block("agc3_cc", io_signature::make(1, 1, sizeof(gr_complex)), io_signature::make(1, 1, sizeof(gr_complex))), d_attack(attack_rate), d_decay(decay_rate), d_reference(reference), d_gain(gain), d_max_gain(65536), - d_reset(true) + d_reset(true), d_iir_update_decim(iir_update_decim) { + set_output_multiple(iir_update_decim*4); const int alignment_multiple = volk_get_alignment() / sizeof(gr_complex); set_alignment(std::max(1, alignment_multiple)); @@ -60,6 +62,7 @@ namespace gr { { } + int agc3_cc_impl::work(int noutput_items, gr_vector_const_void_star &input_items, @@ -67,17 +70,17 @@ namespace gr { { const gr_complex *in = (const gr_complex*)input_items[0]; gr_complex *out = (gr_complex*)output_items[0]; - // Compute magnitude of each sample + #ifdef __GNUC__ + // Compute a linear average on reset (no expected) + if(__builtin_expect(d_reset, false)) { float mags[noutput_items] __attribute__ ((aligned (16))); volk_32fc_magnitude_32f(mags, &in[0], noutput_items); - // Compute a linear average on reset (no expected) - if(__builtin_expect(d_reset, false)) { #else - std::vector<float> mags(noutput_items); - volk_32fc_magnitude_32f(&mags[0], &in[0], noutput_items); - // Compute a linear average on reset (no expected) + // Compute a linear average on reset (no expected) if(!d_reset) { + std::vector<float> mags(noutput_items); + volk_32fc_magnitude_32f(&mags[0], &in[0], noutput_items); #endif float mag(0.0); for(int i=0; i<noutput_items; i++) { @@ -100,13 +103,41 @@ namespace gr { } else { // Otherwise perform a normal iir update - for(int i=0; i<noutput_items; i++) { - float newlevel = mags[i]; // abs(in[i]); - float rate = (newlevel > d_reference/d_gain)?d_attack:d_decay; - d_gain = newlevel==0?(d_gain*(1-rate)):(d_gain*(1-rate)) + (d_reference/newlevel)*rate; - out[i] = in[i] * d_gain; +#ifdef _MSC_VER + std::vector<float> mag_sq(noutput_items/d_iir_update_decim); + std::vector<float> inv_mag(noutput_items/d_iir_update_decim); +#else + float mag_sq[noutput_items/d_iir_update_decim] __attribute__ ((aligned (16))); + float inv_mag[noutput_items/d_iir_update_decim] __attribute__ ((aligned (16))); +#endif + + // generate squared magnitudes at decimated rate (gather operation) + for(int i=0; i<noutput_items/d_iir_update_decim; i++){ + int idx = i*d_iir_update_decim; + mag_sq[i] = in[idx].real()*in[idx].real() + in[idx].imag()*in[idx].imag(); } - } + + // compute inverse square roots + volk_32f_invsqrt_32f_a(&inv_mag[0], &mag_sq[0], noutput_items/d_iir_update_decim); + + // apply updates + for(int i=0; i<noutput_items/d_iir_update_decim; i++){ + float magi = inv_mag[i]; +#ifdef _MSC_VER + if(!_finite(magi)){ +#else + if(std::isfinite(magi)){ +#endif + float rate = (magi > d_gain/d_reference)?d_decay:d_attack; + d_gain = d_gain*(1-rate) + d_reference*magi*rate; + } else { + d_gain = d_gain*(1-d_decay); + } + for(int j=i*d_iir_update_decim; j<(i+1)*d_iir_update_decim; j++){ + out[j] = in[j] * d_gain; + } + } + } return noutput_items; } diff --git a/gr-analog/lib/agc3_cc_impl.h b/gr-analog/lib/agc3_cc_impl.h index 77cc1978c5..a239370972 100644 --- a/gr-analog/lib/agc3_cc_impl.h +++ b/gr-analog/lib/agc3_cc_impl.h @@ -32,7 +32,7 @@ namespace gr { { public: agc3_cc_impl(float attack_rate = 1e-1, float decay_rate = 1e-2, - float reference = 1.0, float gain = 1.0); + float reference = 1.0, float gain = 1.0, int iir_update_decim=1); ~agc3_cc_impl(); float attack_rate() const { return d_attack; } @@ -58,6 +58,7 @@ namespace gr { float d_gain; float d_max_gain; bool d_reset; + int d_iir_update_decim; }; } /* namespace analog */ diff --git a/gr-blocks/grc/blocks_block_tree.xml b/gr-blocks/grc/blocks_block_tree.xml index c6c797f52a..18e6a05213 100644 --- a/gr-blocks/grc/blocks_block_tree.xml +++ b/gr-blocks/grc/blocks_block_tree.xml @@ -183,6 +183,7 @@ <block>blocks_tag_gate</block> <block>blocks_tagged_file_sink</block> <block>blocks_tagged_stream_mux</block> + <block>blocks_stream_to_tagged_stream</block> </cat> <cat> <name>Type Converters</name> diff --git a/gr-blocks/grc/blocks_file_sink.xml b/gr-blocks/grc/blocks_file_sink.xml index 75ef86a6b8..ece21fd2ae 100644 --- a/gr-blocks/grc/blocks_file_sink.xml +++ b/gr-blocks/grc/blocks_file_sink.xml @@ -8,7 +8,7 @@ <name>File Sink</name> <key>blocks_file_sink</key> <import>from gnuradio import blocks</import> - <make>blocks.file_sink($type.size*$vlen, $file) + <make>blocks.file_sink($type.size*$vlen, $file, $append) self.$(id).set_unbuffered($unbuffered)</make> <callback>set_unbuffered($unbuffered)</callback> <callback>open($file)</callback> @@ -68,6 +68,20 @@ self.$(id).set_unbuffered($unbuffered)</make> <key>True</key> </option> </param> + <param> + <name>Append file</name> + <key>append</key> + <value>False</value> + <type>bool</type> + <option> + <name>Append</name> + <key>True</key> + </option> + <option> + <name>Overwrite</name> + <key>False</key> + </option> + </param> <check>$vlen > 0</check> <sink> diff --git a/gr-blocks/grc/blocks_stream_to_tagged_stream.xml b/gr-blocks/grc/blocks_stream_to_tagged_stream.xml new file mode 100644 index 0000000000..cf35e7554c --- /dev/null +++ b/gr-blocks/grc/blocks_stream_to_tagged_stream.xml @@ -0,0 +1,64 @@ +<?xml version="1.0"?> +<block> + <name>Stream to Tagged Stream</name> + <key>blocks_stream_to_tagged_stream</key> + <import>from gnuradio import blocks</import> + <make>blocks.stream_to_tagged_stream($type.size, $vlen, $packet_len, $len_tag_key)</make> + <param> + <name>Type</name> + <key>type</key> + <type>enum</type> + <option> + <name>Complex</name> + <key>complex</key> + <opt>size:gr.sizeof_gr_complex</opt> + </option> + <option> + <name>Float</name> + <key>float</key> + <opt>size:gr.sizeof_float</opt> + </option> + <option> + <name>Int</name> + <key>int</key> + <opt>size:gr.sizeof_int</opt> + </option> + <option> + <name>Short</name> + <key>short</key> + <opt>size:gr.sizeof_short</opt> + </option> + <option> + <name>Byte</name> + <key>byte</key> + <opt>size:gr.sizeof_char</opt> + </option> + </param> + <param> + <name>Vector Length</name> + <key>vlen</key> + <value>1</value> + <type>int</type> + </param> + <param> + <name>Packet Length</name> + <key>packet_len</key> + <type>int</type> + </param> + <param> + <name>Length Tag Key</name> + <key>len_tag_key</key> + <value>"packet_len"</value> + <type>string</type> + </param> + <sink> + <name>in</name> + <type>$type</type> + <vlen>$vlen</vlen> + </sink> + <source> + <name>out</name> + <type>$type</type> + <vlen>$vlen</vlen> + </source> +</block> diff --git a/gr-blocks/include/gnuradio/blocks/CMakeLists.txt b/gr-blocks/include/gnuradio/blocks/CMakeLists.txt index de52e3e3e7..83338b771d 100644 --- a/gr-blocks/include/gnuradio/blocks/CMakeLists.txt +++ b/gr-blocks/include/gnuradio/blocks/CMakeLists.txt @@ -173,7 +173,7 @@ install(FILES plateau_detector_fb.h probe_rate.h regenerate_bb.h - repack_bits_bb.h + repack_bits_bb.h repeat.h rms_cf.h rms_ff.h @@ -183,6 +183,7 @@ install(FILES socket_pdu.h stream_mux.h stream_to_streams.h + stream_to_tagged_stream.h stream_to_vector.h streams_to_stream.h streams_to_vector.h diff --git a/gr-blocks/include/gnuradio/blocks/file_sink.h b/gr-blocks/include/gnuradio/blocks/file_sink.h index c1041683d3..177964682d 100644 --- a/gr-blocks/include/gnuradio/blocks/file_sink.h +++ b/gr-blocks/include/gnuradio/blocks/file_sink.h @@ -45,8 +45,10 @@ namespace gr { * \brief Make a file sink. * \param itemsize size of the input data items. * \param filename name of the file to open and write output to. + * \param append if true, data is appended to the file instead of + * overwriting the initial content. */ - static sptr make(size_t itemsize, const char *filename); + static sptr make(size_t itemsize, const char *filename, bool append=false); }; } /* namespace blocks */ diff --git a/gr-blocks/include/gnuradio/blocks/file_sink_base.h b/gr-blocks/include/gnuradio/blocks/file_sink_base.h index 812da6dfae..253b5ea122 100644 --- a/gr-blocks/include/gnuradio/blocks/file_sink_base.h +++ b/gr-blocks/include/gnuradio/blocks/file_sink_base.h @@ -42,9 +42,10 @@ namespace gr { bool d_is_binary; boost::mutex d_mutex; bool d_unbuffered; + bool d_append; protected: - file_sink_base(const char *filename, bool is_binary); + file_sink_base(const char *filename, bool is_binary, bool append); public: file_sink_base() {} diff --git a/gr-blocks/include/gnuradio/blocks/stream_to_tagged_stream.h b/gr-blocks/include/gnuradio/blocks/stream_to_tagged_stream.h new file mode 100644 index 0000000000..ccc85240c1 --- /dev/null +++ b/gr-blocks/include/gnuradio/blocks/stream_to_tagged_stream.h @@ -0,0 +1,62 @@ +/* -*- c++ -*- */ +/* + * Copyright 2013 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_BLOCKS_STREAM_TO_TAGGED_STREAM_H +#define INCLUDED_BLOCKS_STREAM_TO_TAGGED_STREAM_H + +#include <gnuradio/blocks/api.h> +#include <gnuradio/sync_block.h> + +namespace gr { + namespace blocks { + + /*! + * \brief Converts a regular stream into a tagged stream. + * \ingroup blocks + * + * All this block does is add length tags in regular intervals. + * It can be used to connect a regular stream to a gr::tagged_stream_block. + */ + class BLOCKS_API stream_to_tagged_stream : virtual public gr::sync_block + { + public: + typedef boost::shared_ptr<stream_to_tagged_stream> sptr; + + /*! + * \param itemsize Item size + * \param vlen Vector length of the input items. Note that one vector is one item. + * \param packet_len Number of items per tagged stream packet. One tag is written every \p packet_len items. + * \param len_tag_key Key of the length tag. + */ + static sptr make( + size_t itemsize, + int vlen, + unsigned packet_len, + const std::string &len_tag_key + ); + }; + + } // namespace blocks +} // namespace gr + +#endif /* INCLUDED_BLOCKS_STREAM_TO_TAGGED_STREAM_H */ + diff --git a/gr-blocks/lib/CMakeLists.txt b/gr-blocks/lib/CMakeLists.txt index 1c7bd80ae0..6eded4a273 100644 --- a/gr-blocks/lib/CMakeLists.txt +++ b/gr-blocks/lib/CMakeLists.txt @@ -225,6 +225,7 @@ list(APPEND gr_blocks_sources stream_mux_impl.cc stream_pdu_base.cc stream_to_streams_impl.cc + stream_to_tagged_stream_impl.cc stream_to_vector_impl.cc streams_to_stream_impl.cc streams_to_vector_impl.cc @@ -237,6 +238,7 @@ list(APPEND gr_blocks_sources transcendental_impl.cc tcp_connection.cc tuntap_pdu_impl.cc + tag_gate_impl.cc tagged_stream_mux_impl.cc uchar_array_to_float.cc uchar_to_float_impl.cc @@ -285,8 +287,7 @@ list(APPEND blocks_libs ${LOG4CPP_LIBRARIES} ) -add_library(gnuradio-blocks SHARED ${gr_blocks_sources} - tag_gate_impl.cc) +add_library(gnuradio-blocks SHARED ${gr_blocks_sources}) add_dependencies(gnuradio-blocks blocks_generated_includes) target_link_libraries(gnuradio-blocks ${blocks_libs}) diff --git a/gr-blocks/lib/file_sink_base.cc b/gr-blocks/lib/file_sink_base.cc index 42e2eae528..81bc94f351 100644 --- a/gr-blocks/lib/file_sink_base.cc +++ b/gr-blocks/lib/file_sink_base.cc @@ -53,8 +53,8 @@ namespace gr { namespace blocks { - file_sink_base::file_sink_base(const char *filename, bool is_binary) - : d_fp(0), d_new_fp(0), d_updated(false), d_is_binary(is_binary) + file_sink_base::file_sink_base(const char *filename, bool is_binary, bool append) + : d_fp(0), d_new_fp(0), d_updated(false), d_is_binary(is_binary), d_append(append) { if (!open(filename)) throw std::runtime_error ("can't open file"); @@ -76,9 +76,13 @@ namespace gr { // we use the open system call to get access to the O_LARGEFILE flag. int fd; - if((fd = ::open(filename, - O_WRONLY|O_CREAT|O_TRUNC|OUR_O_LARGEFILE|OUR_O_BINARY, - 0664)) < 0){ + int flags; + if(d_append) { + flags = O_WRONLY|O_CREAT|O_APPEND|OUR_O_LARGEFILE|OUR_O_BINARY; + } else { + flags = O_WRONLY|O_CREAT|O_TRUNC|OUR_O_LARGEFILE|OUR_O_BINARY; + } + if((fd = ::open(filename, flags, 0664)) < 0){ perror(filename); return false; } diff --git a/gr-blocks/lib/file_sink_impl.cc b/gr-blocks/lib/file_sink_impl.cc index e78576e288..ab36dcd4e6 100644 --- a/gr-blocks/lib/file_sink_impl.cc +++ b/gr-blocks/lib/file_sink_impl.cc @@ -32,17 +32,17 @@ namespace gr { namespace blocks { file_sink::sptr - file_sink::make(size_t itemsize, const char *filename) + file_sink::make(size_t itemsize, const char *filename, bool append) { return gnuradio::get_initial_sptr - (new file_sink_impl(itemsize, filename)); + (new file_sink_impl(itemsize, filename, append)); } - file_sink_impl::file_sink_impl(size_t itemsize, const char *filename) + file_sink_impl::file_sink_impl(size_t itemsize, const char *filename, bool append) : sync_block("file_sink", io_signature::make(1, 1, itemsize), io_signature::make(0, 0, 0)), - file_sink_base(filename, true), + file_sink_base(filename, true, append), d_itemsize(itemsize) { } diff --git a/gr-blocks/lib/file_sink_impl.h b/gr-blocks/lib/file_sink_impl.h index f86009419e..9e0c81569b 100644 --- a/gr-blocks/lib/file_sink_impl.h +++ b/gr-blocks/lib/file_sink_impl.h @@ -34,7 +34,7 @@ namespace gr { size_t d_itemsize; public: - file_sink_impl(size_t itemsize, const char *filename); + file_sink_impl(size_t itemsize, const char *filename, bool append=false); ~file_sink_impl(); int work(int noutput_items, diff --git a/gr-blocks/lib/stream_to_tagged_stream_impl.cc b/gr-blocks/lib/stream_to_tagged_stream_impl.cc new file mode 100644 index 0000000000..08395bf653 --- /dev/null +++ b/gr-blocks/lib/stream_to_tagged_stream_impl.cc @@ -0,0 +1,74 @@ +/* -*- c++ -*- */ +/* + * Copyright 2013 <+YOU OR YOUR COMPANY+>. + * + * This 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. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <cstring> +#include <gnuradio/io_signature.h> +#include "stream_to_tagged_stream_impl.h" + +namespace gr { + namespace blocks { + + stream_to_tagged_stream::sptr + stream_to_tagged_stream::make(size_t itemsize, int vlen, unsigned packet_len, const std::string &len_tag_key) + { + return gnuradio::get_initial_sptr + (new stream_to_tagged_stream_impl(itemsize, vlen, packet_len, len_tag_key)); + } + + stream_to_tagged_stream_impl::stream_to_tagged_stream_impl(size_t itemsize, int vlen, unsigned packet_len, const std::string &len_tag_key) + : gr::sync_block("stream_to_tagged_stream", + gr::io_signature::make(1, 1, itemsize * vlen), + gr::io_signature::make(1, 1, itemsize * vlen)), + d_itemsize(itemsize * vlen), + d_packet_len(packet_len), + d_packet_len_pmt(pmt::from_long(packet_len)), + d_len_tag_key(pmt::string_to_symbol(len_tag_key)), + d_next_tag_pos(0) + {} + + stream_to_tagged_stream_impl::~stream_to_tagged_stream_impl() + { + } + + int + stream_to_tagged_stream_impl::work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) + { + const unsigned char *in = (const unsigned char *) input_items[0]; + unsigned char *out = (unsigned char *) output_items[0]; + // Copy data + memcpy(out, in, noutput_items * d_itemsize); + // Add tags every d_packet_len + while(d_next_tag_pos < nitems_written(0) + noutput_items) { + add_item_tag(0, d_next_tag_pos, d_len_tag_key, d_packet_len_pmt); + d_next_tag_pos += d_packet_len; + } + + return noutput_items; + } + + } /* namespace blocks */ +} /* namespace gr */ + diff --git a/gr-blocks/lib/stream_to_tagged_stream_impl.h b/gr-blocks/lib/stream_to_tagged_stream_impl.h new file mode 100644 index 0000000000..106d90b86a --- /dev/null +++ b/gr-blocks/lib/stream_to_tagged_stream_impl.h @@ -0,0 +1,53 @@ +/* -*- c++ -*- */ +/* + * Copyright 2013 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_BLOCKS_STREAM_TO_TAGGED_STREAM_IMPL_H +#define INCLUDED_BLOCKS_STREAM_TO_TAGGED_STREAM_IMPL_H + +#include <gnuradio/blocks/stream_to_tagged_stream.h> + +namespace gr { + namespace blocks { + + class stream_to_tagged_stream_impl : public stream_to_tagged_stream + { + private: + size_t d_itemsize; + unsigned d_packet_len; + pmt::pmt_t d_packet_len_pmt; + pmt::pmt_t d_len_tag_key; + uint64_t d_next_tag_pos; + + public: + stream_to_tagged_stream_impl(size_t itemsize, int vlen, unsigned packet_len, const std::string &tag_len_key); + ~stream_to_tagged_stream_impl(); + + int work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + }; + + } // namespace blocks +} // namespace gr + +#endif /* INCLUDED_BLOCKS_STREAM_TO_TAGGED_STREAM_IMPL_H */ + diff --git a/gr-blocks/python/blocks/qa_stream_to_tagged_stream.py b/gr-blocks/python/blocks/qa_stream_to_tagged_stream.py new file mode 100755 index 0000000000..0d3f503abd --- /dev/null +++ b/gr-blocks/python/blocks/qa_stream_to_tagged_stream.py @@ -0,0 +1,53 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +# Copyright 202013 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +from gnuradio import gr, gr_unittest +from gnuradio import blocks + +class qa_stream_to_tagged_stream (gr_unittest.TestCase): + + def setUp (self): + self.tb = gr.top_block () + + def tearDown (self): + self.tb = None + + def test_001_t (self): + src_data = (1, ) * 50 + packet_len = 10L + len_tag_key = 'packet_len' + src = blocks.vector_source_f(src_data, False, 1) + tagger = blocks.stream_to_tagged_stream(gr.sizeof_float, 1, packet_len, len_tag_key) + sink = blocks.vector_sink_f() + self.tb.connect(src, tagger, sink) + self.tb.run () + self.assertEqual(sink.data(), src_data) + tags = [gr.tag_to_python(x) for x in sink.tags()] + tags = sorted([(x.offset, x.key, x.value) for x in tags]) + expected_tags = [(long(pos), 'packet_len', packet_len) for pos in range(0, 50, 10) ] + self.assertEqual(tags, expected_tags) + + +if __name__ == '__main__': + gr_unittest.run(qa_stream_to_tagged_stream, "qa_stream_to_tagged_stream.xml") + diff --git a/gr-blocks/swig/blocks_swig1.i b/gr-blocks/swig/blocks_swig1.i index 431062e454..c87b4df03e 100644 --- a/gr-blocks/swig/blocks_swig1.i +++ b/gr-blocks/swig/blocks_swig1.i @@ -30,6 +30,7 @@ #include "gnuradio/blocks/skiphead.h" #include "gnuradio/blocks/stream_mux.h" #include "gnuradio/blocks/stream_to_streams.h" +#include "gnuradio/blocks/stream_to_tagged_stream.h" #include "gnuradio/blocks/stream_to_vector.h" #include "gnuradio/blocks/streams_to_stream.h" #include "gnuradio/blocks/streams_to_vector.h" @@ -61,6 +62,7 @@ %include "gnuradio/blocks/skiphead.h" %include "gnuradio/blocks/stream_mux.h" %include "gnuradio/blocks/stream_to_streams.h" +%include "gnuradio/blocks/stream_to_tagged_stream.h" %include "gnuradio/blocks/stream_to_vector.h" %include "gnuradio/blocks/streams_to_stream.h" %include "gnuradio/blocks/streams_to_vector.h" @@ -91,6 +93,7 @@ GR_SWIG_BLOCK_MAGIC2(blocks, skiphead); GR_SWIG_BLOCK_MAGIC2(blocks, stream_mux); GR_SWIG_BLOCK_MAGIC2(blocks, stream_to_streams); +GR_SWIG_BLOCK_MAGIC2(blocks, stream_to_tagged_stream); GR_SWIG_BLOCK_MAGIC2(blocks, stream_to_vector); GR_SWIG_BLOCK_MAGIC2(blocks, streams_to_stream); GR_SWIG_BLOCK_MAGIC2(blocks, streams_to_vector); diff --git a/gr-channels/grc/channels_channel_model.xml b/gr-channels/grc/channels_channel_model.xml index fa881a10b5..909301de94 100644 --- a/gr-channels/grc/channels_channel_model.xml +++ b/gr-channels/grc/channels_channel_model.xml @@ -15,6 +15,7 @@ epsilon=$epsilon, taps=$taps, noise_seed=$seed, + block_tags=$block_tags )</make> <callback>set_noise_voltage($noise_voltage)</callback> <callback>set_frequency_offset($freq_offset)</callback> @@ -50,6 +51,23 @@ <value>0</value> <type>int</type> </param> + <param> + <name>Block Tag Propagation</name> + <key>block_tags</key> + <value>False</value> + <type>enum</type> + <hide>$block_tags.hide_block</hide> + <option> + <name>Yes</name> + <key>True</key> + <opt>hide_block:</opt> + </option> + <option> + <name>No</name> + <key>False</key> + <opt>hide_block:part</opt> + </option> + </param> <sink> <name>in</name> <type>complex</type> diff --git a/gr-channels/grc/channels_channel_model2.xml b/gr-channels/grc/channels_channel_model2.xml index e8162f53d4..85355a1029 100644 --- a/gr-channels/grc/channels_channel_model2.xml +++ b/gr-channels/grc/channels_channel_model2.xml @@ -14,6 +14,7 @@ epsilon=$epsilon, taps=$taps, noise_seed=$seed, + block_tags=$block_tags )</make> <callback>set_noise_voltage($noise_voltage)</callback> <callback>set_taps($taps)</callback> @@ -42,6 +43,23 @@ <value>0</value> <type>int</type> </param> + <param> + <name>Block Tag Propagation</name> + <key>block_tags</key> + <value>False</value> + <type>enum</type> + <hide>$block_tags.hide_block</hide> + <option> + <name>Yes</name> + <key>True</key> + <opt>hide_block:</opt> + </option> + <option> + <name>No</name> + <key>False</key> + <opt>hide_block:part</opt> + </option> + </param> <sink> <name>in</name> <type>complex</type> diff --git a/gr-channels/include/gnuradio/channels/channel_model.h b/gr-channels/include/gnuradio/channels/channel_model.h index 8b533ac7da..6a1e4a08cb 100644 --- a/gr-channels/include/gnuradio/channels/channel_model.h +++ b/gr-channels/include/gnuradio/channels/channel_model.h @@ -43,7 +43,10 @@ namespace gr { * the AWGN noise source. * * Multipath can be approximated in this model by using a FIR - * filter representation of a multipath delay profile.. + * filter representation of a multipath delay profile. + * + * To simulate a channel with time-variant channel, use a + * gr::channels::channel_model2. */ class CHANNELS_API channel_model : virtual public hier_block2 { @@ -64,12 +67,14 @@ namespace gr { * the transmitter and receiver. 1.0 is no difference. * \param taps Taps of a FIR filter to emulate a multipath delay profile. * \param noise_seed A random number generator seed for the noise source. + * \param block_tags If true, tags will not be able to propagate through this block. */ static sptr make(double noise_voltage=0.0, double frequency_offset=0.0, double epsilon=1.0, const std::vector<gr_complex> &taps=std::vector<gr_complex>(1,1), - double noise_seed=0); + double noise_seed=0, + bool block_tags=false); virtual void set_noise_voltage(double noise_voltage) = 0; virtual void set_frequency_offset(double frequency_offset) = 0; diff --git a/gr-channels/include/gnuradio/channels/channel_model2.h b/gr-channels/include/gnuradio/channels/channel_model2.h index 05084931ee..6c52f34d81 100644 --- a/gr-channels/include/gnuradio/channels/channel_model2.h +++ b/gr-channels/include/gnuradio/channels/channel_model2.h @@ -81,11 +81,13 @@ namespace gr { * the transmitter and receiver. 1.0 is no difference. * \param taps Taps of a FIR filter to emulate a multipath delay profile. * \param noise_seed A random number generator seed for the noise source. + * \param block_tags If true, tags will not be able to propagate through this block. */ static sptr make(double noise_voltage=0.0, double epsilon=1.0, const std::vector<gr_complex> &taps=std::vector<gr_complex>(1,1), - double noise_seed=0); + double noise_seed=0, + bool block_tags=false); virtual void set_noise_voltage(double noise_voltage) = 0; virtual void set_taps(const std::vector<gr_complex> &taps) = 0; diff --git a/gr-channels/lib/channel_model2_impl.cc b/gr-channels/lib/channel_model2_impl.cc index 13eb033def..7533871de2 100644 --- a/gr-channels/lib/channel_model2_impl.cc +++ b/gr-channels/lib/channel_model2_impl.cc @@ -33,20 +33,23 @@ namespace gr { channel_model2::make(double noise_voltage, double epsilon, const std::vector<gr_complex> &taps, - double noise_seed) + double noise_seed, + bool block_tags) { return gnuradio::get_initial_sptr (new channel_model2_impl(noise_voltage, epsilon, taps, - noise_seed)); + noise_seed, + block_tags)); } // Hierarchical block constructor channel_model2_impl::channel_model2_impl(double noise_voltage, double epsilon, const std::vector<gr_complex> &taps, - double noise_seed) + double noise_seed, + bool block_tags) : hier_block2("channel_model2", io_signature::make2(3, 3, sizeof(gr_complex), sizeof(float)), io_signature::make(1, 1, sizeof(gr_complex))) @@ -78,6 +81,10 @@ namespace gr { connect(d_mixer_offset, 0, d_noise_adder, 1); connect(d_noise, 0, d_noise_adder, 0); connect(d_noise_adder, 0, self(), 0); + + if (block_tags) { + d_timing_offset->set_tag_propagation_policy(gr::block::TPP_DONT); + } } channel_model2_impl::~channel_model2_impl() diff --git a/gr-channels/lib/channel_model2_impl.h b/gr-channels/lib/channel_model2_impl.h index db2a667f9c..3bf1adb44e 100644 --- a/gr-channels/lib/channel_model2_impl.h +++ b/gr-channels/lib/channel_model2_impl.h @@ -55,7 +55,8 @@ namespace gr { channel_model2_impl(double noise_voltage, double epsilon, const std::vector<gr_complex> &taps, - double noise_seed); + double noise_seed, + bool block_tags); ~channel_model2_impl(); diff --git a/gr-channels/lib/channel_model_impl.cc b/gr-channels/lib/channel_model_impl.cc index b232f9b235..7db4e6aa5c 100644 --- a/gr-channels/lib/channel_model_impl.cc +++ b/gr-channels/lib/channel_model_impl.cc @@ -32,14 +32,16 @@ namespace gr { double frequency_offset, double epsilon, const std::vector<gr_complex> &taps, - double noise_seed) + double noise_seed, + bool block_tags) { return gnuradio::get_initial_sptr (new channel_model_impl(noise_voltage, frequency_offset, epsilon, taps, - noise_seed)); + noise_seed, + block_tags)); } // Hierarchical block constructor @@ -47,7 +49,9 @@ namespace gr { double frequency_offset, double epsilon, const std::vector<gr_complex> &taps, - double noise_seed) + double noise_seed, + bool block_tags + ) : hier_block2("channel_model", io_signature::make(1, 1, sizeof(gr_complex)), io_signature::make(1, 1, sizeof(gr_complex))) @@ -75,6 +79,10 @@ namespace gr { connect(d_mixer_offset, 0, d_noise_adder, 1); connect(d_noise, 0, d_noise_adder, 0); connect(d_noise_adder, 0, self(), 0); + + if (block_tags) { + d_timing_offset->set_tag_propagation_policy(gr::block::TPP_DONT); + } } channel_model_impl::~channel_model_impl() diff --git a/gr-channels/lib/channel_model_impl.h b/gr-channels/lib/channel_model_impl.h index da00e98da2..3faf6c3bbe 100644 --- a/gr-channels/lib/channel_model_impl.h +++ b/gr-channels/lib/channel_model_impl.h @@ -54,7 +54,8 @@ namespace gr { double frequency_offset, double epsilon, const std::vector<gr_complex> &taps, - double noise_seed); + double noise_seed, + bool block_tags); ~channel_model_impl(); diff --git a/gr-digital/doc/digital.dox b/gr-digital/doc/digital.dox index 2809c6a943..48feda3485 100644 --- a/gr-digital/doc/digital.dox +++ b/gr-digital/doc/digital.dox @@ -20,4 +20,461 @@ by using: help(digital) \endcode +\section digital_constellations Constellation Objects + +GNU Radio supports the creation and use of Constellation objects for +many of its digital communications needs. We define these +constellations with a set of constellation points in complex space and +the symbol mappings to those points. For a constellation that has 4 +symbols, it then has log2(4) = 2 bits/symbol. We define this +constellation with: + +<pre> + constel_points = [c0, c1, c2, c3] + symbols = [s0, s1, s2, s3] +</pre> + +In this case: \f$c_i \in C\f$ and \f$s_i \in [00, 01, 10, +11]\f$. Also, the mapping is a 1-to-1 for the items in both lists, so +the symbol \f$s_0\f$ is positioned in complex space at the point +\f$c_0\f$. + +In the code itself, the symbols are referred to as the +'pre_diff_code' since this is the mapping before the application of +differential modulation, if used. + +The constellation object classes are defined in constellation.h. There +is a hierarchy of classes for different purposes and which represent +special classes of constellations. The all derive from the virtual +class gr::digital::constellation. All constellations we will make are +based on classes derived from this base: + +<pre> +gr::digital::constellation + --> gr::digital::constellation_calcdist + --> gr::digital::constellation_sector + --> gr::digital::constellation_rect + --> gr::digital::constellation_expl_rect + --> gr::digital::constellation_psk + --> gr::digital::constellation_bpsk + --> gr::digital::constellation_qpsk + --> gr::digital::constellation_dqpsk + --> gr::digital::constellation_8psk +</pre> + +Each constellation class has a set of attributes and functions useful +for manipulating the constellations and for converting symbols to and +from complex points. One of the more important functions is the +gr::digital::constellation::decision_maker function that takes in a +sample in complex space and returns the symbol that it maps to. How +this calculation is performed generally distinguishes the +constellation classes from each other. + +The gr::digital::constellation_calcdist is the most generic +constellation class we can create. This takes in the constellation +points, symbol mapping, a rotational symmetry, and the number of +dimensions. The decision_maker function takes in a complex sample x +and calculates the Euclidean distance between x and each point in the +constellation map of the object. The constellation point that has the +minimum Euclidean distance to x is selected as the best match. The +decision_maker will then return the symbol value that matches to this +selected constellation point. + +We then have a concept of a constellation with a well-defined concept +of sectors in the gr::digital::constellation_sector. This is farther +refined if we know that the constellation is rectangular and can use +the gr::digital::constellation_rect class. These classes have an +overloaded decision_maker function that is specific to how the sectors +are defined in the constructor. Essentially, the decision making math +for this class is less costly than calculating the Euclidean distance +for each point in the space. So if we can sectorize our constellation, +using this class will be computationally cheaper. + +Finally, we have a set of pre-defined, hard-coded constellations for +BPSK (gr::digital::constellation_bpsk), QPSK +(gr::digital::constellation_qpsk), DQPSK +(gr::digital::constellation_dqpsk), and 8PSK +(gr::digital::constellation_8psk). These derive directly from +gr::digital::constellation and specifically overload the decision_maker +function. We have very simple metrics for calculating decisions for +each of these constellations. For BPSK, we simply slice on the real +axis. Samples are based solely on whether the real part of the complex +symbol x is greater than or less than 0. Similar, simple, decision +makers are defined for the others. + +Note that these specific constellations for the PSK modulations are +defined for only one mapping of the constellation points to the +symbols. Each is Gray coded, but for a specific Gray coding that is +hard-coded into the class. + + +\subsection grc_constellations Constellation Objects in GRC + +GRC provides two constellation representations that we can use to more +easily define and interact with constellation objects. These are +located in the 'Modulators' category as 'Constellation Object' and +'Constellation Rect. Object'. These allow us to easily specify the +constellation points, symbol list, and other properties of the +constellation objects. They return the base() of the object, so the +variable's ID can be used directly with blocks that accept +constellation objects. + +These constellation blocks also allow us to specify the soft decision +LUT if using the constellation object for soft decision outputs. The +input can either be 'None' (default), a list of the soft bits that +were generated externally or by another function, or 'auto' where the +block will automatically calculate the soft decisions based on the +constellation points and symbol map. + + +\section digital_python_helpers Python Constellation Helper Functions + +A series of helper functions are defined in Python to create +different, common constellations. There are various functions that +have various levels of complexity in their definitions. + +\subsection digital_python_helpers_psk PSK Python Helpers + +There are two modules imported directly into gnuradio.digital. The +first is gr-digital/python/digital/psk.py and the second is +gr-digital/python/digital/psk_constellations.py. The +gr-digital/python/digital/psk.py module defines the following +constellations: + +<pre> + psk_constellation(m, mod_code, differential) +</pre> + +This function defines a PSK modulation of order 'm' (that is, there +are m number of constellation points / symbols). The 'mod_code' is +either mod_codes.GRAY_CODE or mode_codes.NO_CODE to set the symbol +mapping up as either Gray coded or not. The 'differential' argument is +either True to use differential coding or False for non-differential +coding. + +This function creates and returns a constellation object that can then +be used by any block that takes a constellation +(gr::digital::constellation_decoder_cb, +gr::digital::constellation_receiver_cb, +gr::digital::constellation_soft_decoder_cf, or +gr::digital::lms_dd_equalizer_cc). + +The gr-digital/python/digital/psk.py module also holds functions +similar to digital.psk_constellation but that create a full modulator +and demodulator chain derived from digital.generic_mod_demod. + +<pre> + psk_mod(constellation_points, mod_code, differential, *args, **kwargs) + psk_demod(constellation_points, mod_code, differential, *args, **kwargs) +</pre> + +The args and kwargs are parameters of the generic_mod or generic_demod +passed directly to them. See \ref digital_generic_mod_demod for +details of this interface. + +There is another Python file full of helper functions to create +different constellations. This is found in the +gr-digital/python/digital/psk_constellation.py file. This file +provides functions that build the vectors of constellation points and +symbol mappings that can be used to create a constellation +object. These are particularly helpful when using the Constellation +Obj. and Constellation Rect. GUI elements in GRC. + +The gr-digital/python/digital/psk_constellation.py file has extensive +documentation that describes the naming scheme used for the different +constellations that will not be repeated here. The main thing to +understand is that these functions define constellations of the same +order with different Gray code mappings. The function names are: + +<pre> + (const_points, symbol_map) = psk_M_0xk_<permutation>() +</pre> + +Where M is the order of the modulation (2 for BPSK, 4 for QPSK, +etc.), and k and \<permutation\> define a particular encoding for the +Gray code mapping used. The documentation in the file explains how +these two concepts define the Gray code mapping. + +These functions are also simply named "psk_M_n" when n is an integer +from 0 to N-1 for however many mappings are defined for that +modulation. Not all modulations are fully defined, and the value +for n has no other meaning except as a counter. + +The functions return a tuple of lists. The first list in the tuple is +the list of complex constellation points and the second list contains +the symbols mapped to those points. These lists can then be passed to +a constellation class directly to create a constellation of any Gray +code mapping needed. + +While not all Gray code mappings of the modulations are defined, there +is a generator function to automatically build any rotation of a basis +constellation: + +<pre> + (const_points, symbol_map) = \ + constellation_map_generator(basis_cpoints, basis_symbols, k, pi) +</pre> + +We provide a basis constellation map and symbol map as the fundamental +rotation of the constellation points. This function uses the k and pi +inputs (see the discussion in psk_constellation.py for what these +mean) to return a new rotation of the constellation's symbols. If the +basis symbols are Gray coded than the output symbols will also be Gray +coded. Note that this algorithm specifically depends on the +constellation in complex space to be square to preserve the Gray code +property. + + +\subsection digital_python_helpers_qam QAM Python Helpers + +Similar to defining PSK modulations, GNU Radio also has helpers for +some QAM modulations, found in gr-digital/python/digital/qam.py and +gr-digital/python/digital/qam_constellations.py. Similar functions to +what has been described for PSK exist here: + +<pre> + qam_constellation(constellation_points, differential, mod_code, + large_ampls_to_corners) + qam_mod(constellation_points, differential, mod_code, *args, **kwargs) + qam_demod(constellation_points, differential, mod_code, + large_ampls_to_corner, *args, **kwargs) +</pre> + +The parameters to these functions is the same as for the PSK +equivalents. The new argument 'large_ampls_to_corner' is defined in +the documentation as: + +<pre> + large_ampls_to_corners: If this is set to True then when the + constellation is making decisions, points that are far outside + the constellation are mapped to the closest corner rather than + the closet constellation point. This can help with phase + locking. +</pre> + +Similarly, gr-digital/python/digital/qam_constellations.py defines a of +QAM constellation functions that return a tuple containing the +constellation points and the symbol mappings. The naming scheme is +defined in depth in the module itself and is similar to the equivalent +set of PSK functions. + +Currently, only a subset of 16QAM symbol mappings are defined, but we +can use of the constellation_map_generator function described in the +previous section to define more mapping rotations for and square QAM +modulation. + + +\section digital_generic_mod_demod The Generic Modulator/Demodulator +Hierarchical Blocks + +Since digital modulation and demodulation are complex functions, the +different parts can be done by different existing GNU Radio blocks. We +have combined these into a generic modulator and generic demodulator +hierarchical blocks to make access and use much easier. This file can +be found as gr-digital/python/digital/generic_mod_demod.py. + +\subsection digital_generic_mod Generic Modulator + +The modulator constructor looks like: + +<pre> + digital.generic_mod(constellation, differential, samples_per_symbol, + pre_diff_code, excess_bw, verbose, log) +</pre> + +The 'constellation' arg is a constellation object as defined above in +\ref digital_constellations and can represent any constellation +mapping. The 'differential' arg is a bool to turn differential coding +on/off. The block also performs pulse shaping and interpolates the +pulse-shaped filter to some number of 'samples_per_symbol'. The pulse +shaping is a root raised cosine filter defined by the excess +bandwidth (or alpha) parameter called 'excess_bw.' + +We can also turn on a verbose mode to output information to the +user. The 'log' parameter toggles logging data on/off. When logging is +turned on, it stores every stage of the modulation to a different file +so that each stage can be independently analyzed. + + +\subsection digital_generic_demod Generic Demodulator + +The demodulator looks like: + +<pre> + digital.generic_demod(constellation, differential, samples_per_symbol, + pre_diff_code, excess_bw, freq_bw, timing_bw, + phase_bw, verbose, log) +</pre> + +The additional parameters to the demodulator are the loop bandwidths +for the different signal recovery loops used internally. There are +separate loops for frequency acquisition, timing acquisition, and fine +frequency / phase acquisition, controlled in tern by each of the +three 'X_bw' arguments. Otherwise, the arguments are the same as the +modulator. + + +\subsection digital_generic_guts Guts of the Modulator and Demodulator + +The generic modulator looks like the following: + +<pre> + blocks.packed_to_unpacked_bb: takes in packed bytes + digital.map_bb: maps baseband symbols to the pre-differential encoding + digital.diff_encoder_bb: differentially encode symbols + digital.chunks_to_symbols_bc: convert symbols to complex samples + filter.pfb_arb_resampler_ccf: perform upsampling to samps/symbol and pulse shape +</pre> + +The mapping and chunks-to-symbols stages are done using the +information provided by the constellation object. + +Note that the modulator takes in packed bytes, which means that all 8 +bits per byte are used and unpacked into k bits per symbol. + +The generic demodulator looks like the following: + +<pre> + digital.fll_band_edge_cc: Performs coarse frequency correction + digital.pfb_clock_sync_ccf: Matched filtering and timing recovery + digital.constellation_receiver_cb: Phase tracking and decision making (hard bits) + digital.diff_decoder_bb: Differential decoding + digital.map_bb: Map to pre-differential symbols + blocks.unpack_k_bits_bb: Unpack k bits/symbol to a stream of bits +</pre> + +This block outputs unpacked bits, so each output item represents a +single bit of data. A block like 'pack_k_bits' can be used following +this to convert the data back into bytes. + + +\section digital_softbits Support for Soft Decisions + +To support soft decisions of the receivers instead of the current hard +decisions, the constellation objects also accept a soft decision +look-up table (LUT) or can be told to generate a LUT based on the +constellation points and symbol map. + +All constellation objects can accept a new LUT using the +gr::digital::constellation::set_soft_dec_lut function. This function +takes in a LUT, which is a vector of floating point tuples (in C++ it +is just a vector\<vector\<float\>\>) and a precision value that +specifies how accurate the LUT is to a given number of bits. + +The constellation objects also have two functions to calculate the +soft decisions from their constellation and symbol map. The +gr::digital::constellation::calc_soft_dec takes a complex number (and +optional noise power) and returns the soft decisions as a list of +floats. This function is used internally in the +gr::digital::constellation::gen_soft_dec_lut, which takes in the LUT's +precision (as a number of bits) and an optional noise power estimate, +if known. This function calculates the soft decisions itself. These +functions are very expensive because each constellation point is taken +into account during the calculation. We provide the +gr::digital::constellation::set_soft_dec_lut in order to allow users +to use one of the many known approximations to more quickly generate +the soft decision LUT. + +The gr::digital::constellation::calc_soft_dec function could be used +instead of drawing directly from a LUT, which is probably only +important if the noise floor or channel estimates are likely to change +and we want to account for this in the decisions. The basic +implementation of the soft decision calculation is the full +calculation based on the distance between the sample and all points in +the constellation space. If using this function for real-time +decisions, a new object should inherit from the +gr::digital::constellation class (or whichever child class is being +used) and redefine this function with a faster approximation +calculation. + +Note: If no soft decision LUT is defined but +gr::digital::constellation::soft_decision_maker is called then the +full calculation from gr::digital::constellation::calc_soft_dec is +used by default. + +The LUT is a list of tuples, where each index of the list is some +quantized (to some number of bits of precision) point in the +constellation space. At each index, there is a tuple of \e k soft +bit values for a constellation with \e k bits/symbol. + +To help with this, the file +gr-digital/python/digital/soft_dec_lut_gen.py can be used to create +these tables. The function digital.soft_dec_table_generator(generator, +precision) function generates a LUT based on some generator function +and the number of bits of precision required. This file contains +documentation explaining the system better. Or the +digital.soft_dec_table(constel, symbols, prec, npwr=1) can be used +which takes in the constellation map and symbols to do the full raw +calculation of the softbits as opposed to a generator function. + +To further aid the LUT creation, the digital module also defines a +number of functions that can be used as soft decision generators for +the soft_dec_table function. These functions are found in +psk_constellations.py and qam_constellations.py. These files were +already mentioned as they contain a set of functions that return +tuples of constellation points and Gray-mapped symbols for different +modulations. But these files contain a second set of functions +prefixed by 'sd_' which are soft decision LUT generator functions Each +LUT generator takes in a complex value and returns the tuple of soft +decisions for that point in complex space. To aid with this, +soft_dec_lut_gen.py defines a 'calc_from_table' function that takes in +a complex sample, the precision of the table, and the LUT itself and +returns the tuple of soft decisions in the LUT that is closest to the +given symbol. Each of these functions can be found directly from the +'digital' Python module. + +The LUTs are defined from min to max constellation points in both the +real and imaginary axes. That means that signals coming in outside of +these bounds are clipped to 1. So there is no added certainty for +values beyond these bounds. + +The gr::digital::constellation_soft_decoder_cf block takes in a +constellation object where a soft decision LUT is defined. It takes in +complex samples and produces a stream of floats of soft decisions. The +soft decision outputs are not grouped together, it is just a stream of +floats. So this block acts as an interpolator that takes in 1 complex +sample and return \e k float for \e k bits per symbol. + + +\subsection soft_dec_api Review of the Soft Decision API/Functions + +Files of interest: +\li psk_constellations.py: PSK constellations and soft decision generators +\li qam_constellations.py: QAM constellations and soft decision generators +\li soft_dec_lut_gen.py: Functions to build soft decision LUTs and test them +\li test_soft_decisions.py: A script that generates a random complex +sample and calculates the soft decisions using various methods. Plots +the sample against the full constellation. Requires matplotlib installed. + +Functions: +\li digital.sd_psk_2_*: Returns (constellation, symbol_map) lists for +different rotations for BPSK. +\li digital.sd_psk_4_*: Returns (constellation, symbol_map) lists for +different rotations for QPSK. +\li digital.sd_qam_16_*: Returns (constellation, symbol_map) lists for +different rotations for 16QAM. +\li digital.soft_dec_table_generator: Takes in a generator function +(like the digital.sd_XXX above) and creates a LUT to a specific precision. +\li digital.soft_dec_table: Takes in a constellation/symbol map and +uses digital.calc_soft_dec to generate a LUT to a specific precision. +\li digital.calc_soft_dec: Takes a complex sample and calculates the +soft decisions for a given constellation/symbol mapping. +\li digital.calc_soft_dec_from_table: Given a sample and a LUT, +returns the soft decisions of the LUT for the nearest point to the +sample. + +C++ Interface: +\li gr::digital::constellation::gen_soft_dec_lut: uses calc_soft_dec +to internally generate a soft decision LUT. +\li gr::digital::constellation::calc_soft_dec: calculates the soft +decisions for a given sample from the full constellation/symbol map. +\li gr::digital::constellation::set_soft_dec_lut: Set the soft +decision LUT from an externally-calculated LUT. +\li gr::digital::constellation::has_soft_dec_lut: has the LUT been +set/generated or not. +\li gr::digital::constellation::soft_decision_maker: Used by +gr::digital::constellation_soft_decoder to convert samples to soft +decisions. If a LUT is defined, uses it; else, uses calc_soft_dec. + + */ diff --git a/gr-digital/examples/ofdm/ofdm_loopback.grc b/gr-digital/examples/ofdm/ofdm_loopback.grc index a6b3b147f1..ad8e4a3ef7 100644 --- a/gr-digital/examples/ofdm/ofdm_loopback.grc +++ b/gr-digital/examples/ofdm/ofdm_loopback.grc @@ -1,6 +1,6 @@ <?xml version='1.0' encoding='ASCII'?> <flow_graph> - <timestamp>Tue Jun 11 22:44:34 2013</timestamp> + <timestamp>Tue Aug 27 15:09:37 2013</timestamp> <block> <key>options</key> <param> @@ -64,7 +64,7 @@ <key>variable</key> <param> <key>id</key> - <value>len_tag_key</value> + <value>tx_signal</value> </param> <param> <key>_enabled</key> @@ -72,11 +72,34 @@ </param> <param> <key>value</key> - <value>"packet_len"</value> + <value>[numpy.sin(2 * numpy.pi * 1.0/8 * x) for x in range(packet_len)]</value> </param> <param> <key>_coordinate</key> - <value>(345, 0)</value> + <value>(176, -1)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>variable</key> + <param> + <key>id</key> + <value>packet_len</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>value</key> + <value>8*2</value> + </param> + <param> + <key>_coordinate</key> + <value>(258, 64)</value> </param> <param> <key>_rotation</key> @@ -107,6 +130,29 @@ </param> </block> <block> + <key>variable</key> + <param> + <key>id</key> + <value>len_tag_key</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>value</key> + <value>"packet_len"</value> + </param> + <param> + <key>_coordinate</key> + <value>(345, 0)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> <key>import</key> <param> <key>id</key> @@ -153,10 +199,10 @@ </param> </block> <block> - <key>wxgui_fftsink2</key> + <key>blocks_vector_to_stream</key> <param> <key>id</key> - <value>wxgui_fftsink2_0</value> + <value>blocks_vector_to_stream_0</value> </param> <param> <key>_enabled</key> @@ -164,59 +210,121 @@ </param> <param> <key>type</key> - <value>complex</value> + <value>byte</value> </param> <param> - <key>title</key> - <value>Rx Spectrum</value> + <key>num_items</key> + <value>4</value> </param> <param> - <key>samp_rate</key> - <value>100e3</value> + <key>vlen</key> + <value>1</value> </param> <param> - <key>baseband_freq</key> + <key>affinity</key> + <value></value> + </param> + <param> + <key>minoutbuf</key> <value>0</value> </param> <param> - <key>y_per_div</key> - <value>10</value> + <key>_coordinate</key> + <value>(261, 140)</value> </param> <param> - <key>y_divs</key> - <value>10</value> + <key>_rotation</key> + <value>0</value> </param> + </block> + <block> + <key>blocks_tag_debug</key> <param> - <key>ref_level</key> + <key>id</key> + <value>blocks_tag_debug_0</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>type</key> + <value>byte</value> + </param> + <param> + <key>name</key> + <value>Rx Packets</value> + </param> + <param> + <key>num_inputs</key> + <value>1</value> + </param> + <param> + <key>vlen</key> + <value>1</value> + </param> + <param> + <key>display</key> + <value>True</value> + </param> + <param> + <key>affinity</key> + <value></value> + </param> + <param> + <key>_coordinate</key> + <value>(345, 424)</value> + </param> + <param> + <key>_rotation</key> <value>0</value> </param> + </block> + <block> + <key>wxgui_scopesink2</key> <param> - <key>ref_scale</key> - <value>2.0</value> + <key>id</key> + <value>wxgui_scopesink2_0</value> </param> <param> - <key>fft_size</key> - <value>1024</value> + <key>_enabled</key> + <value>True</value> </param> <param> - <key>fft_rate</key> - <value>15</value> + <key>type</key> + <value>float</value> </param> <param> - <key>peak_hold</key> - <value>False</value> + <key>title</key> + <value>Scope Plot</value> </param> <param> - <key>average</key> - <value>False</value> + <key>samp_rate</key> + <value>1.0</value> </param> <param> - <key>avg_alpha</key> + <key>v_scale</key> <value>0</value> </param> <param> - <key>win</key> - <value>None</value> + <key>v_offset</key> + <value>0</value> + </param> + <param> + <key>t_scale</key> + <value>0</value> + </param> + <param> + <key>ac_couple</key> + <value>False</value> + </param> + <param> + <key>xy_mode</key> + <value>False</value> + </param> + <param> + <key>num_inputs</key> + <value>1</value> </param> <param> <key>win_size</key> @@ -231,12 +339,20 @@ <value></value> </param> <param> - <key>freqvar</key> - <value>None</value> + <key>trig_mode</key> + <value>wxgui.TRIG_MODE_AUTO</value> + </param> + <param> + <key>y_axis_label</key> + <value>Counts</value> + </param> + <param> + <key>affinity</key> + <value></value> </param> <param> <key>_coordinate</key> - <value>(59, 384)</value> + <value>(550, 323)</value> </param> <param> <key>_rotation</key> @@ -244,54 +360,38 @@ </param> </block> <block> - <key>variable_slider</key> + <key>blocks_stream_to_vector</key> <param> <key>id</key> - <value>noise_voltage</value> + <value>blocks_stream_to_vector_0</value> </param> <param> <key>_enabled</key> <value>True</value> </param> <param> - <key>label</key> - <value>Noise Amplitude</value> - </param> - <param> - <key>value</key> - <value>0.01</value> + <key>type</key> + <value>byte</value> </param> <param> - <key>min</key> - <value>0</value> + <key>num_items</key> + <value>4</value> </param> <param> - <key>max</key> + <key>vlen</key> <value>1</value> </param> <param> - <key>num_steps</key> - <value>100</value> - </param> - <param> - <key>style</key> - <value>wx.SL_HORIZONTAL</value> - </param> - <param> - <key>converver</key> - <value>float_converter</value> - </param> - <param> - <key>grid_pos</key> + <key>affinity</key> <value></value> </param> <param> - <key>notebook</key> - <value></value> + <key>minoutbuf</key> + <value>0</value> </param> <param> <key>_coordinate</key> - <value>(695, 439)</value> + <value>(348, 347)</value> </param> <param> <key>_rotation</key> @@ -302,7 +402,7 @@ <key>variable_slider</key> <param> <key>id</key> - <value>freq_offset</value> + <value>noise_voltage</value> </param> <param> <key>_enabled</key> @@ -310,19 +410,19 @@ </param> <param> <key>label</key> - <value>Frequency Offset (Multiples of Sub-carrier spacing)</value> + <value>Noise Amplitude</value> </param> <param> <key>value</key> - <value>0</value> + <value>0.01</value> </param> <param> <key>min</key> - <value>-3</value> + <value>0</value> </param> <param> <key>max</key> - <value>3</value> + <value>1</value> </param> <param> <key>num_steps</key> @@ -346,7 +446,7 @@ </param> <param> <key>_coordinate</key> - <value>(696, 264)</value> + <value>(707, 496)</value> </param> <param> <key>_rotation</key> @@ -354,10 +454,10 @@ </param> </block> <block> - <key>blocks_throttle</key> + <key>wxgui_fftsink2</key> <param> <key>id</key> - <value>blocks_throttle_0</value> + <value>wxgui_fftsink2_0</value> </param> <param> <key>_enabled</key> @@ -368,79 +468,80 @@ <value>complex</value> </param> <param> - <key>samples_per_second</key> + <key>title</key> + <value>Rx Spectrum</value> + </param> + <param> + <key>samp_rate</key> <value>100e3</value> </param> <param> - <key>vlen</key> - <value>1</value> + <key>baseband_freq</key> + <value>0</value> </param> <param> - <key>_coordinate</key> - <value>(252, 212)</value> + <key>y_per_div</key> + <value>10</value> </param> <param> - <key>_rotation</key> - <value>180</value> + <key>y_divs</key> + <value>10</value> </param> - </block> - <block> - <key>digital_ofdm_rx</key> <param> - <key>id</key> - <value>digital_ofdm_rx_0</value> + <key>ref_level</key> + <value>0</value> </param> <param> - <key>_enabled</key> - <value>True</value> + <key>ref_scale</key> + <value>2.0</value> </param> <param> - <key>fft_len</key> - <value>fft_len</value> + <key>fft_size</key> + <value>1024</value> </param> <param> - <key>cp_len</key> - <value>fft_len/4</value> + <key>fft_rate</key> + <value>15</value> </param> <param> - <key>packet_len_key</key> - <value>"rx_len"</value> + <key>peak_hold</key> + <value>False</value> </param> <param> - <key>occupied_carriers</key> - <value>()</value> + <key>average</key> + <value>False</value> </param> <param> - <key>pilot_carriers</key> - <value>()</value> + <key>avg_alpha</key> + <value>0</value> </param> <param> - <key>pilot_symbols</key> - <value>()</value> + <key>win</key> + <value>None</value> </param> <param> - <key>sync_word1</key> - <value>()</value> + <key>win_size</key> + <value></value> </param> <param> - <key>sync_word2</key> - <value>()</value> + <key>grid_pos</key> + <value></value> </param> <param> - <key>header_mod</key> - <value>"BPSK"</value> + <key>notebook</key> + <value></value> </param> <param> - <key>payload_mod</key> - <value>"QPSK"</value> + <key>freqvar</key> + <value>None</value> </param> <param> - <key>log</key> - <value>False</value> + <key>affinity</key> + <value></value> </param> <param> <key>_coordinate</key> - <value>(59, 258)</value> + <value>(71, 441)</value> </param> <param> <key>_rotation</key> @@ -448,22 +549,54 @@ </param> </block> <block> - <key>variable</key> + <key>variable_slider</key> <param> <key>id</key> - <value>packet_len</value> + <value>freq_offset</value> </param> <param> <key>_enabled</key> <value>True</value> </param> <param> + <key>label</key> + <value>Frequency Offset (Multiples of Sub-carrier spacing)</value> + </param> + <param> <key>value</key> - <value>8*2</value> + <value>0</value> + </param> + <param> + <key>min</key> + <value>-3</value> + </param> + <param> + <key>max</key> + <value>3</value> + </param> + <param> + <key>num_steps</key> + <value>100</value> + </param> + <param> + <key>style</key> + <value>wx.SL_HORIZONTAL</value> + </param> + <param> + <key>converver</key> + <value>float_converter</value> + </param> + <param> + <key>grid_pos</key> + <value></value> + </param> + <param> + <key>notebook</key> + <value></value> </param> <param> <key>_coordinate</key> - <value>(258, 64)</value> + <value>(708, 321)</value> </param> <param> <key>_rotation</key> @@ -471,33 +604,49 @@ </param> </block> <block> - <key>variable</key> + <key>blocks_tag_gate</key> <param> <key>id</key> - <value>tx_signal</value> + <value>blocks_tag_gate_0</value> </param> <param> <key>_enabled</key> <value>True</value> </param> <param> - <key>value</key> - <value>[numpy.sin(2 * numpy.pi * 1.0/8 * x) for x in range(packet_len)]</value> + <key>type</key> + <value>complex</value> + </param> + <param> + <key>vlen</key> + <value>1</value> + </param> + <param> + <key>propagate_tags</key> + <value>False</value> + </param> + <param> + <key>affinity</key> + <value></value> + </param> + <param> + <key>minoutbuf</key> + <value>0</value> </param> <param> <key>_coordinate</key> - <value>(176, -1)</value> + <value>(523, 243)</value> </param> <param> <key>_rotation</key> - <value>0</value> + <value>180</value> </param> </block> <block> - <key>blocks_vector_to_stream</key> + <key>blocks_throttle</key> <param> <key>id</key> - <value>blocks_vector_to_stream_0</value> + <value>blocks_throttle_0</value> </param> <param> <key>_enabled</key> @@ -505,23 +654,31 @@ </param> <param> <key>type</key> - <value>byte</value> + <value>complex</value> </param> <param> - <key>num_items</key> - <value>4</value> + <key>samples_per_second</key> + <value>100e3</value> </param> <param> <key>vlen</key> <value>1</value> </param> <param> + <key>affinity</key> + <value></value> + </param> + <param> + <key>minoutbuf</key> + <value>0</value> + </param> + <param> <key>_coordinate</key> - <value>(261, 140)</value> + <value>(267, 243)</value> </param> <param> <key>_rotation</key> - <value>0</value> + <value>180</value> </param> </block> <block> @@ -555,39 +712,16 @@ <value>1</value> </param> <param> - <key>_coordinate</key> - <value>(-1, 101)</value> + <key>affinity</key> + <value></value> </param> <param> - <key>_rotation</key> + <key>minoutbuf</key> <value>0</value> </param> - </block> - <block> - <key>blocks_stream_to_vector</key> - <param> - <key>id</key> - <value>blocks_stream_to_vector_0</value> - </param> - <param> - <key>_enabled</key> - <value>True</value> - </param> - <param> - <key>type</key> - <value>byte</value> - </param> - <param> - <key>num_items</key> - <value>4</value> - </param> - <param> - <key>vlen</key> - <value>1</value> - </param> <param> <key>_coordinate</key> - <value>(336, 290)</value> + <value>(3, 124)</value> </param> <param> <key>_rotation</key> @@ -595,74 +729,46 @@ </param> </block> <block> - <key>wxgui_scopesink2</key> + <key>channels_channel_model</key> <param> <key>id</key> - <value>wxgui_scopesink2_0</value> + <value>channels_channel_model_0</value> </param> <param> <key>_enabled</key> <value>True</value> </param> <param> - <key>type</key> - <value>float</value> + <key>noise_voltage</key> + <value>noise_voltage</value> </param> <param> - <key>title</key> - <value>Scope Plot</value> + <key>freq_offset</key> + <value>freq_offset * 1.0/fft_len</value> </param> <param> - <key>samp_rate</key> + <key>epsilon</key> <value>1.0</value> </param> <param> - <key>v_scale</key> - <value>0</value> - </param> - <param> - <key>v_offset</key> - <value>0</value> + <key>taps</key> + <value>1.0 + 1.0j</value> </param> <param> - <key>t_scale</key> + <key>seed</key> <value>0</value> </param> <param> - <key>ac_couple</key> - <value>False</value> - </param> - <param> - <key>xy_mode</key> - <value>False</value> - </param> - <param> - <key>num_inputs</key> - <value>1</value> - </param> - <param> - <key>win_size</key> + <key>affinity</key> <value></value> </param> <param> - <key>grid_pos</key> - <value></value> - </param> - <param> - <key>notebook</key> - <value></value> - </param> - <param> - <key>trig_mode</key> - <value>wxgui.TRIG_MODE_AUTO</value> - </param> - <param> - <key>y_axis_label</key> - <value>Counts</value> + <key>minoutbuf</key> + <value>0</value> </param> <param> <key>_coordinate</key> - <value>(538, 266)</value> + <value>(764, 93)</value> </param> <param> <key>_rotation</key> @@ -670,10 +776,10 @@ </param> </block> <block> - <key>digital_ofdm_tx</key> + <key>digital_ofdm_rx</key> <param> <key>id</key> - <value>digital_ofdm_tx_0</value> + <value>digital_ofdm_rx_0</value> </param> <param> <key>_enabled</key> @@ -689,7 +795,7 @@ </param> <param> <key>packet_len_key</key> - <value>len_tag_key</value> + <value>"rx_len"</value> </param> <param> <key>occupied_carriers</key> @@ -720,16 +826,24 @@ <value>"QPSK"</value> </param> <param> - <key>rolloff</key> - <value>0</value> + <key>scramble_bits</key> + <value>False</value> </param> <param> <key>log</key> <value>False</value> </param> <param> + <key>affinity</key> + <value></value> + </param> + <param> + <key>minoutbuf</key> + <value>0</value> + </param> + <param> <key>_coordinate</key> - <value>(464, 77)</value> + <value>(71, 315)</value> </param> <param> <key>_rotation</key> @@ -737,108 +851,78 @@ </param> </block> <block> - <key>channels_channel_model</key> + <key>digital_ofdm_tx</key> <param> <key>id</key> - <value>channels_channel_model_0</value> + <value>digital_ofdm_tx_0</value> </param> <param> <key>_enabled</key> <value>True</value> </param> <param> - <key>noise_voltage</key> - <value>noise_voltage</value> + <key>fft_len</key> + <value>fft_len</value> </param> <param> - <key>freq_offset</key> - <value>freq_offset * 1.0/fft_len</value> + <key>cp_len</key> + <value>fft_len/4</value> </param> <param> - <key>epsilon</key> - <value>1.0</value> + <key>packet_len_key</key> + <value>len_tag_key</value> </param> <param> - <key>taps</key> - <value>1.0 + 1.0j</value> + <key>occupied_carriers</key> + <value>()</value> </param> <param> - <key>seed</key> - <value>0</value> + <key>pilot_carriers</key> + <value>()</value> </param> <param> - <key>_coordinate</key> - <value>(747, 85)</value> + <key>pilot_symbols</key> + <value>()</value> </param> <param> - <key>_rotation</key> - <value>0</value> + <key>sync_word1</key> + <value>()</value> </param> - </block> - <block> - <key>blocks_tag_gate</key> <param> - <key>id</key> - <value>blocks_tag_gate_0</value> + <key>sync_word2</key> + <value>()</value> </param> <param> - <key>_enabled</key> - <value>True</value> + <key>header_mod</key> + <value>"BPSK"</value> </param> <param> - <key>type</key> - <value>complex</value> + <key>payload_mod</key> + <value>"QPSK"</value> </param> <param> - <key>vlen</key> - <value>1</value> + <key>rolloff</key> + <value>0</value> </param> <param> - <key>propagate_tags</key> + <key>scramble_bits</key> <value>False</value> </param> <param> - <key>_coordinate</key> - <value>(508, 212)</value> - </param> - <param> - <key>_rotation</key> - <value>180</value> - </param> - </block> - <block> - <key>blocks_tag_debug</key> - <param> - <key>id</key> - <value>blocks_tag_debug_0</value> - </param> - <param> - <key>_enabled</key> - <value>True</value> - </param> - <param> - <key>type</key> - <value>byte</value> - </param> - <param> - <key>name</key> - <value>Rx Packets</value> - </param> - <param> - <key>num_inputs</key> - <value>1</value> + <key>log</key> + <value>False</value> </param> <param> - <key>vlen</key> - <value>1</value> + <key>affinity</key> + <value></value> </param> <param> - <key>display</key> - <value>True</value> + <key>minoutbuf</key> + <value>0</value> </param> <param> <key>_coordinate</key> - <value>(333, 367)</value> + <value>(488, 77)</value> </param> <param> <key>_rotation</key> @@ -858,20 +942,20 @@ <sink_key>0</sink_key> </connection> <connection> - <source_block_id>blocks_throttle_0</source_block_id> - <sink_block_id>digital_ofdm_rx_0</sink_block_id> + <source_block_id>digital_ofdm_tx_0</source_block_id> + <sink_block_id>channels_channel_model_0</sink_block_id> <source_key>0</source_key> <sink_key>0</sink_key> </connection> <connection> - <source_block_id>blocks_throttle_0</source_block_id> - <sink_block_id>wxgui_fftsink2_0</sink_block_id> + <source_block_id>channels_channel_model_0</source_block_id> + <sink_block_id>blocks_tag_gate_0</sink_block_id> <source_key>0</source_key> <sink_key>0</sink_key> </connection> <connection> - <source_block_id>digital_ofdm_rx_0</source_block_id> - <sink_block_id>blocks_stream_to_vector_0</sink_block_id> + <source_block_id>blocks_stream_to_vector_0</source_block_id> + <sink_block_id>wxgui_scopesink2_0</sink_block_id> <source_key>0</source_key> <sink_key>0</sink_key> </connection> @@ -882,26 +966,26 @@ <sink_key>0</sink_key> </connection> <connection> - <source_block_id>blocks_tag_gate_0</source_block_id> - <sink_block_id>blocks_throttle_0</sink_block_id> + <source_block_id>digital_ofdm_rx_0</source_block_id> + <sink_block_id>blocks_stream_to_vector_0</sink_block_id> <source_key>0</source_key> <sink_key>0</sink_key> </connection> <connection> - <source_block_id>blocks_stream_to_vector_0</source_block_id> - <sink_block_id>wxgui_scopesink2_0</sink_block_id> + <source_block_id>blocks_throttle_0</source_block_id> + <sink_block_id>wxgui_fftsink2_0</sink_block_id> <source_key>0</source_key> <sink_key>0</sink_key> </connection> <connection> - <source_block_id>digital_ofdm_tx_0</source_block_id> - <sink_block_id>channels_channel_model_0</sink_block_id> + <source_block_id>blocks_throttle_0</source_block_id> + <sink_block_id>digital_ofdm_rx_0</sink_block_id> <source_key>0</source_key> <sink_key>0</sink_key> </connection> <connection> - <source_block_id>channels_channel_model_0</source_block_id> - <sink_block_id>blocks_tag_gate_0</sink_block_id> + <source_block_id>blocks_tag_gate_0</source_block_id> + <sink_block_id>blocks_throttle_0</sink_block_id> <source_key>0</source_key> <sink_key>0</sink_key> </connection> diff --git a/gr-digital/examples/ofdm/rx_ofdm.grc b/gr-digital/examples/ofdm/rx_ofdm.grc index e38b84f65a..5a65ec8b17 100644 --- a/gr-digital/examples/ofdm/rx_ofdm.grc +++ b/gr-digital/examples/ofdm/rx_ofdm.grc @@ -1,6 +1,6 @@ <?xml version='1.0' encoding='ASCII'?> <flow_graph> - <timestamp>Tue May 14 11:03:11 2013</timestamp> + <timestamp>Sun Oct 27 16:24:42 2013</timestamp> <block> <key>options</key> <param> @@ -61,22 +61,22 @@ </param> </block> <block> - <key>import</key> + <key>variable</key> <param> <key>id</key> - <value>import_1</value> + <value>payload_mod</value> </param> <param> <key>_enabled</key> <value>True</value> </param> <param> - <key>import</key> - <value>from gnuradio.digital.utils import tagged_streams</value> + <key>value</key> + <value>digital.constellation_qpsk()</value> </param> <param> <key>_coordinate</key> - <value>(163, 0)</value> + <value>(663, 1)</value> </param> <param> <key>_rotation</key> @@ -87,7 +87,7 @@ <key>variable</key> <param> <key>id</key> - <value>fft_len</value> + <value>samp_rate</value> </param> <param> <key>_enabled</key> @@ -95,11 +95,11 @@ </param> <param> <key>value</key> - <value>64</value> + <value>10000</value> </param> <param> <key>_coordinate</key> - <value>(301, -1)</value> + <value>(170, 65)</value> </param> <param> <key>_rotation</key> @@ -110,7 +110,7 @@ <key>variable</key> <param> <key>id</key> - <value>payload_mod</value> + <value>header_equalizer</value> </param> <param> <key>_enabled</key> @@ -118,11 +118,11 @@ </param> <param> <key>value</key> - <value>digital.constellation_qpsk()</value> + <value>digital.ofdm_equalizer_simpledfe(fft_len, header_mod.base(), occupied_carriers, pilot_carriers, pilot_symbols)</value> </param> <param> <key>_coordinate</key> - <value>(648, 0)</value> + <value>(931, 69)</value> </param> <param> <key>_rotation</key> @@ -133,7 +133,7 @@ <key>variable</key> <param> <key>id</key> - <value>header_mod</value> + <value>payload_equalizer</value> </param> <param> <key>_enabled</key> @@ -141,11 +141,11 @@ </param> <param> <key>value</key> - <value>digital.constellation_bpsk()</value> + <value>digital.ofdm_equalizer_simpledfe(fft_len, payload_mod.base(), occupied_carriers, pilot_carriers, pilot_symbols, 1)</value> </param> <param> <key>_coordinate</key> - <value>(490, 0)</value> + <value>(1112, 73)</value> </param> <param> <key>_rotation</key> @@ -156,7 +156,7 @@ <key>variable</key> <param> <key>id</key> - <value>occupied_carriers</value> + <value>sync_word2</value> </param> <param> <key>_enabled</key> @@ -164,11 +164,11 @@ </param> <param> <key>value</key> - <value>(range(-26, -21) + range(-20, -7) + range(-6, 0) + range(1, 7) + range(8, 21) + range(22, 27),)</value> + <value>[0j, 0j, 0j, 0j, 0j, 0j, (-1+0j), (-1+0j), (-1+0j), (-1+0j), (1+0j), (1+0j), (-1+0j), (-1+0j), (-1+0j), (1+0j), (-1+0j), (1+0j), (1+0j), (1 +0j), (1+0j), (1+0j), (-1+0j), (-1+0j), (-1+0j), (-1+0j), (-1+0j), (1+0j), (-1+0j), (-1+0j), (1+0j), (-1+0j), 0j, (1+0j), (-1+0j), (1+0j), (1+0j), (1+0j), (-1+0j), (1+0j), (1+0j), (1+0j), (-1+0j), (1+0j), (1+0j), (1+0j), (1+0j), (-1+0j), (1+0j), (-1+0j), (-1+0j), (-1+0j), (1+0j), (-1+0j), (1+0j), (-1+0j), (-1+0j), (-1+0j), (-1+0j), 0j, 0j, 0j, 0j, 0j]</value> </param> <param> <key>_coordinate</key> - <value>(598, 64)</value> + <value>(399, 66)</value> </param> <param> <key>_rotation</key> @@ -179,7 +179,7 @@ <key>variable</key> <param> <key>id</key> - <value>pilot_carriers</value> + <value>sync_word1</value> </param> <param> <key>_enabled</key> @@ -187,11 +187,11 @@ </param> <param> <key>value</key> - <value>((-21, -7, 7, 21,),)</value> + <value>[0., 0., 0., 0., 0., 0., 0., 1.41421356, 0., -1.41421356, 0., 1.41421356, 0., -1.41421356, 0., -1.41421356, 0., -1.41421356, 0., 1.41421356, 0., -1.41421356, 0., 1.41421356, 0., -1.41421356, 0., -1.41421356, 0., -1.41421356, 0., -1.41421356, 0., 1.41421356, 0., -1.41421356, 0., 1.41421356, 0., 1.41421356, 0., 1.41421356, 0., -1.41421356, 0., 1.41421356, 0., 1.41421356, 0., 1.41421356, 0., -1.41421356, 0., 1.41421356, 0., 1.41421356, 0., 1.41421356, 0., 0., 0., 0., 0., 0.]</value> </param> <param> <key>_coordinate</key> - <value>(751, 64)</value> + <value>(255, 67)</value> </param> <param> <key>_rotation</key> @@ -202,7 +202,7 @@ <key>variable</key> <param> <key>id</key> - <value>pilot_symbols</value> + <value>fft_len</value> </param> <param> <key>_enabled</key> @@ -210,11 +210,11 @@ </param> <param> <key>value</key> - <value>((1, 1, 1, -1,),)</value> + <value>64</value> </param> <param> <key>_coordinate</key> - <value>(875, 65)</value> + <value>(301, -1)</value> </param> <param> <key>_rotation</key> @@ -225,7 +225,7 @@ <key>variable</key> <param> <key>id</key> - <value>sync_word2</value> + <value>header_mod</value> </param> <param> <key>_enabled</key> @@ -233,11 +233,11 @@ </param> <param> <key>value</key> - <value>(0, 0, 0, 0, 0, 1, 1, -1.0, -1, 1.0, 1, 1.0, -1, -1.0, -1, 1.0, 1, -1.0, 1, 1.0, 1, -1.0, -1, -1.0, -1, 1.0, -1, 1.0, -1, 1.0, 1, -1.0, 0, 1.0, 1, -1.0, 1, 1.0, -1, -1.0, 1, -1.0, -1, -1.0, 1, 1.0, 1, -1.0, 1, 1.0, -1, 1.0, -1, -1.0, -1, 1.0, 1, -1.0, 0, 0, 0, 0, 0, 0)</value> + <value>digital.constellation_bpsk()</value> </param> <param> <key>_coordinate</key> - <value>(457, 64)</value> + <value>(490, 0)</value> </param> <param> <key>_rotation</key> @@ -248,7 +248,7 @@ <key>variable</key> <param> <key>id</key> - <value>sync_word1</value> + <value>packet_len</value> </param> <param> <key>_enabled</key> @@ -256,11 +256,11 @@ </param> <param> <key>value</key> - <value>(0, 0, 0, 0, 0, 0, 0, -1.0, 0, 1.0, 0, 1.0, 0, -1.0, 0, 1.0, 0, -1.0, 0, 1.0, 0, -1.0, 0, -1.0, 0, 1.0, 0, 1.0, 0, 1.0, 0, -1.0, 0, 1.0, 0, -1.0, 0, 1.0, 0, -1.0, 0, -1.0, 0, -1.0, 0, 1.0, 0, -1.0, 0, 1.0, 0, 1.0, 0, -1.0, 0, 1.0, 0, -1.0, 0, 0, 0, 0, 0, 0)</value> + <value>96</value> </param> <param> <key>_coordinate</key> - <value>(313, 64)</value> + <value>(1034, 0)</value> </param> <param> <key>_rotation</key> @@ -271,7 +271,7 @@ <key>variable</key> <param> <key>id</key> - <value>samp_rate</value> + <value>pilot_carriers</value> </param> <param> <key>_enabled</key> @@ -279,11 +279,11 @@ </param> <param> <key>value</key> - <value>3200000</value> + <value>((-21, -7, 7, 21,),)</value> </param> <param> <key>_coordinate</key> - <value>(218, 64)</value> + <value>(692, 70)</value> </param> <param> <key>_rotation</key> @@ -291,22 +291,22 @@ </param> </block> <block> - <key>virtual_sink</key> + <key>variable</key> <param> <key>id</key> - <value>virtual_sink_0_0</value> + <value>pilot_symbols</value> </param> <param> <key>_enabled</key> <value>True</value> </param> <param> - <key>stream_id</key> - <value>Payload Stream</value> + <key>value</key> + <value>((1, 1, 1, -1,),)</value> </param> <param> <key>_coordinate</key> - <value>(968, 374)</value> + <value>(813, 70)</value> </param> <param> <key>_rotation</key> @@ -314,22 +314,22 @@ </param> </block> <block> - <key>virtual_sink</key> + <key>variable</key> <param> <key>id</key> - <value>virtual_sink_0</value> + <value>occupied_carriers</value> </param> <param> <key>_enabled</key> <value>True</value> </param> <param> - <key>stream_id</key> - <value>Header Stream</value> + <key>value</key> + <value>(range(-26, -21) + range(-20, -7) + range(-6, 0) + range(1, 7) + range(8, 21) + range(22, 27),)</value> </param> <param> <key>_coordinate</key> - <value>(969, 305)</value> + <value>(541, 70)</value> </param> <param> <key>_rotation</key> @@ -337,30 +337,22 @@ </param> </block> <block> - <key>digital_ofdm_sync_sc_cfb</key> + <key>variable</key> <param> <key>id</key> - <value>digital_ofdm_sync_sc_cfb_0</value> + <value>length_tag_key</value> </param> <param> <key>_enabled</key> <value>True</value> </param> <param> - <key>fft_len</key> - <value>fft_len</value> - </param> - <param> - <key>cp_len</key> - <value>fft_len/4</value> - </param> - <param> - <key>use_even_carriers</key> - <value>False</value> + <key>value</key> + <value>"frame_len"</value> </param> <param> <key>_coordinate</key> - <value>(244, 137)</value> + <value>(367, -1)</value> </param> <param> <key>_rotation</key> @@ -368,34 +360,22 @@ </param> </block> <block> - <key>analog_noise_source_x</key> + <key>variable</key> <param> <key>id</key> - <value>analog_noise_source_x_0</value> + <value>packet_length_tag_key</value> </param> <param> <key>_enabled</key> <value>True</value> </param> <param> - <key>type</key> - <value>complex</value> - </param> - <param> - <key>noise_type</key> - <value>analog.GR_GAUSSIAN</value> - </param> - <param> - <key>amp</key> - <value>1</value> - </param> - <param> - <key>seed</key> - <value>0</value> + <key>value</key> + <value>"packet_len"</value> </param> <param> <key>_coordinate</key> - <value>(0, 220)</value> + <value>(1132, 0)</value> </param> <param> <key>_rotation</key> @@ -403,30 +383,22 @@ </param> </block> <block> - <key>blocks_multiply_xx</key> + <key>variable</key> <param> <key>id</key> - <value>blocks_multiply_xx_0</value> + <value>header_formatter</value> </param> <param> <key>_enabled</key> <value>True</value> </param> <param> - <key>type</key> - <value>complex</value> - </param> - <param> - <key>num_inputs</key> - <value>2</value> - </param> - <param> - <key>vlen</key> - <value>1</value> + <key>value</key> + <value>digital.packet_header_ofdm(occupied_carriers, n_syms=1, len_tag_key=packet_length_tag_key, frame_len_tag_key=length_tag_key, bits_per_header_sym=header_mod.bits_per_symbol(), bits_per_payload_sym=payload_mod.bits_per_symbol(), scramble_header=False)</value> </param> <param> <key>_coordinate</key> - <value>(798, 137)</value> + <value>(855, 0)</value> </param> <param> <key>_rotation</key> @@ -434,30 +406,22 @@ </param> </block> <block> - <key>blocks_throttle</key> + <key>import</key> <param> <key>id</key> - <value>blocks_throttle_0</value> + <value>import_1</value> </param> <param> <key>_enabled</key> <value>True</value> </param> <param> - <key>type</key> - <value>complex</value> - </param> - <param> - <key>samples_per_second</key> - <value>samp_rate</value> - </param> - <param> - <key>vlen</key> - <value>1</value> + <key>import</key> + <value>from gnuradio.digital.utils import tagged_streams</value> </param> <param> <key>_coordinate</key> - <value>(186, 235)</value> + <value>(163, 0)</value> </param> <param> <key>_rotation</key> @@ -465,697 +429,651 @@ </param> </block> <block> - <key>uhd_usrp_source</key> + <key>analog_random_source_x</key> <param> <key>id</key> - <value>uhd_usrp_source_0</value> + <value>analog_random_source_x_0</value> </param> <param> <key>_enabled</key> - <value>False</value> + <value>True</value> </param> <param> <key>type</key> - <value>fc32</value> - </param> - <param> - <key>otw</key> - <value></value> - </param> - <param> - <key>stream_args</key> - <value></value> + <value>byte</value> </param> <param> - <key>dev_addr</key> - <value></value> + <key>min</key> + <value>0</value> </param> <param> - <key>sync</key> - <value></value> + <key>max</key> + <value>255</value> </param> <param> - <key>clock_rate</key> - <value>0.0</value> + <key>num_samps</key> + <value>1000</value> </param> <param> - <key>num_mboards</key> - <value>1</value> + <key>repeat</key> + <value>True</value> </param> <param> - <key>clock_source0</key> + <key>affinity</key> <value></value> </param> <param> - <key>time_source0</key> - <value></value> + <key>minoutbuf</key> + <value>0</value> </param> <param> - <key>sd_spec0</key> - <value></value> + <key>_coordinate</key> + <value>(2, 167)</value> </param> <param> - <key>clock_source1</key> - <value></value> + <key>_rotation</key> + <value>0</value> </param> + </block> + <block> + <key>analog_frequency_modulator_fc</key> <param> - <key>time_source1</key> - <value></value> + <key>id</key> + <value>analog_frequency_modulator_fc_0</value> </param> <param> - <key>sd_spec1</key> - <value></value> + <key>_enabled</key> + <value>True</value> </param> <param> - <key>clock_source2</key> - <value></value> + <key>sensitivity</key> + <value>-2.0/fft_len</value> </param> <param> - <key>time_source2</key> + <key>affinity</key> <value></value> </param> <param> - <key>sd_spec2</key> - <value></value> + <key>minoutbuf</key> + <value>0</value> </param> <param> - <key>clock_source3</key> - <value></value> + <key>_coordinate</key> + <value>(920, 171)</value> </param> <param> - <key>time_source3</key> - <value></value> + <key>_rotation</key> + <value>0</value> </param> + </block> + <block> + <key>blocks_throttle</key> <param> - <key>sd_spec3</key> - <value></value> + <key>id</key> + <value>blocks_throttle_0</value> </param> <param> - <key>clock_source4</key> - <value></value> + <key>_enabled</key> + <value>True</value> </param> <param> - <key>time_source4</key> - <value></value> + <key>type</key> + <value>complex</value> </param> <param> - <key>sd_spec4</key> - <value></value> + <key>samples_per_second</key> + <value>samp_rate</value> </param> <param> - <key>clock_source5</key> - <value></value> + <key>vlen</key> + <value>1</value> </param> <param> - <key>time_source5</key> + <key>affinity</key> <value></value> </param> <param> - <key>sd_spec5</key> - <value></value> + <key>minoutbuf</key> + <value>0</value> </param> <param> - <key>clock_source6</key> - <value></value> + <key>_coordinate</key> + <value>(440, 187)</value> </param> <param> - <key>time_source6</key> - <value></value> + <key>_rotation</key> + <value>0</value> </param> + </block> + <block> + <key>blocks_delay</key> <param> - <key>sd_spec6</key> - <value></value> + <key>id</key> + <value>blocks_delay_0</value> </param> <param> - <key>clock_source7</key> - <value></value> + <key>_enabled</key> + <value>True</value> </param> <param> - <key>time_source7</key> - <value></value> + <key>type</key> + <value>complex</value> </param> <param> - <key>sd_spec7</key> - <value></value> + <key>delay</key> + <value>fft_len+fft_len/4</value> </param> <param> - <key>nchan</key> + <key>num_ports</key> <value>1</value> </param> <param> - <key>samp_rate</key> - <value>samp_rate</value> - </param> - <param> - <key>center_freq0</key> - <value>0</value> - </param> - <param> - <key>gain0</key> - <value>0</value> + <key>vlen</key> + <value>1</value> </param> <param> - <key>ant0</key> + <key>affinity</key> <value></value> </param> <param> - <key>bw0</key> - <value>0</value> - </param> - <param> - <key>center_freq1</key> - <value>0</value> - </param> - <param> - <key>gain1</key> + <key>minoutbuf</key> <value>0</value> </param> <param> - <key>ant1</key> - <value></value> - </param> - <param> - <key>bw1</key> - <value>0</value> + <key>_coordinate</key> + <value>(637, 294)</value> </param> <param> - <key>center_freq2</key> + <key>_rotation</key> <value>0</value> </param> + </block> + <block> + <key>blocks_multiply_xx</key> <param> - <key>gain2</key> - <value>0</value> + <key>id</key> + <value>blocks_multiply_xx_0</value> </param> <param> - <key>ant2</key> - <value></value> + <key>_enabled</key> + <value>True</value> </param> <param> - <key>bw2</key> - <value>0</value> + <key>type</key> + <value>complex</value> </param> <param> - <key>center_freq3</key> - <value>0</value> + <key>num_inputs</key> + <value>2</value> </param> <param> - <key>gain3</key> - <value>0</value> + <key>vlen</key> + <value>1</value> </param> <param> - <key>ant3</key> + <key>affinity</key> <value></value> </param> <param> - <key>bw3</key> - <value>0</value> - </param> - <param> - <key>center_freq4</key> - <value>0</value> - </param> - <param> - <key>gain4</key> + <key>minoutbuf</key> <value>0</value> </param> <param> - <key>ant4</key> - <value></value> - </param> - <param> - <key>bw4</key> - <value>0</value> + <key>_coordinate</key> + <value>(1117, 265)</value> </param> <param> - <key>center_freq5</key> + <key>_rotation</key> <value>0</value> </param> + </block> + <block> + <key>digital_ofdm_sync_sc_cfb</key> <param> - <key>gain5</key> - <value>0</value> + <key>id</key> + <value>digital_ofdm_sync_sc_cfb_0</value> </param> <param> - <key>ant5</key> - <value></value> + <key>_enabled</key> + <value>True</value> </param> <param> - <key>bw5</key> - <value>0</value> + <key>fft_len</key> + <value>fft_len</value> </param> <param> - <key>center_freq6</key> - <value>0</value> + <key>cp_len</key> + <value>fft_len/4</value> </param> <param> - <key>gain6</key> - <value>0</value> + <key>use_even_carriers</key> + <value>False</value> </param> <param> - <key>ant6</key> + <key>affinity</key> <value></value> </param> <param> - <key>bw6</key> + <key>minoutbuf</key> <value>0</value> </param> <param> - <key>center_freq7</key> - <value>0</value> + <key>_coordinate</key> + <value>(627, 175)</value> </param> <param> - <key>gain7</key> + <key>_rotation</key> <value>0</value> </param> + </block> + <block> + <key>digital_packet_headerparser_b</key> <param> - <key>ant7</key> - <value></value> - </param> - <param> - <key>bw7</key> - <value>0</value> + <key>id</key> + <value>digital_packet_headerparser_b_0</value> </param> <param> - <key>center_freq8</key> - <value>0</value> + <key>_enabled</key> + <value>True</value> </param> <param> - <key>gain8</key> - <value>0</value> + <key>header_formatter</key> + <value>header_formatter.base()</value> </param> <param> - <key>ant8</key> + <key>affinity</key> <value></value> </param> <param> - <key>bw8</key> - <value>0</value> - </param> - <param> - <key>center_freq9</key> + <key>minoutbuf</key> <value>0</value> </param> <param> - <key>gain9</key> - <value>0</value> + <key>_coordinate</key> + <value>(634, 529)</value> </param> <param> - <key>ant9</key> - <value></value> + <key>_rotation</key> + <value>180</value> </param> + </block> + <block> + <key>digital_constellation_decoder_cb</key> <param> - <key>bw9</key> - <value>0</value> + <key>id</key> + <value>digital_constellation_decoder_cb_0</value> </param> <param> - <key>center_freq10</key> - <value>0</value> + <key>_enabled</key> + <value>True</value> </param> <param> - <key>gain10</key> - <value>0</value> + <key>constellation</key> + <value>header_mod.base()</value> </param> <param> - <key>ant10</key> + <key>affinity</key> <value></value> </param> <param> - <key>bw10</key> + <key>minoutbuf</key> <value>0</value> </param> <param> - <key>center_freq11</key> - <value>0</value> + <key>_coordinate</key> + <value>(903, 530)</value> </param> <param> - <key>gain11</key> - <value>0</value> + <key>_rotation</key> + <value>180</value> </param> + </block> + <block> + <key>fft_vxx</key> <param> - <key>ant11</key> - <value></value> + <key>id</key> + <value>fft_vxx_0</value> </param> <param> - <key>bw11</key> - <value>0</value> + <key>_enabled</key> + <value>True</value> </param> <param> - <key>center_freq12</key> - <value>0</value> + <key>type</key> + <value>complex</value> </param> <param> - <key>gain12</key> - <value>0</value> + <key>fft_size</key> + <value>fft_len</value> </param> <param> - <key>ant12</key> - <value></value> + <key>forward</key> + <value>True</value> </param> <param> - <key>bw12</key> - <value>0</value> + <key>window</key> + <value>()</value> </param> <param> - <key>center_freq13</key> - <value>0</value> + <key>shift</key> + <value>True</value> </param> <param> - <key>gain13</key> - <value>0</value> + <key>nthreads</key> + <value>1</value> </param> <param> - <key>ant13</key> + <key>affinity</key> <value></value> </param> <param> - <key>bw13</key> + <key>minoutbuf</key> <value>0</value> </param> <param> - <key>center_freq14</key> - <value>0</value> + <key>_coordinate</key> + <value>(217, 576)</value> </param> <param> - <key>gain14</key> + <key>_rotation</key> <value>0</value> </param> + </block> + <block> + <key>virtual_sink</key> <param> - <key>ant14</key> - <value></value> - </param> - <param> - <key>bw14</key> - <value>0</value> + <key>id</key> + <value>virtual_sink_0</value> </param> <param> - <key>center_freq15</key> - <value>0</value> + <key>_enabled</key> + <value>True</value> </param> <param> - <key>gain15</key> - <value>0</value> + <key>stream_id</key> + <value>Header Stream</value> </param> <param> - <key>ant15</key> - <value></value> + <key>_coordinate</key> + <value>(1098, 414)</value> </param> <param> - <key>bw15</key> + <key>_rotation</key> <value>0</value> </param> + </block> + <block> + <key>blocks_stream_to_tagged_stream</key> <param> - <key>center_freq16</key> - <value>0</value> + <key>id</key> + <value>blocks_stream_to_tagged_stream_0</value> </param> <param> - <key>gain16</key> - <value>0</value> + <key>_enabled</key> + <value>True</value> </param> <param> - <key>ant16</key> - <value></value> + <key>type</key> + <value>byte</value> </param> <param> - <key>bw16</key> - <value>0</value> + <key>vlen</key> + <value>1</value> </param> <param> - <key>center_freq17</key> - <value>0</value> + <key>packet_len</key> + <value>packet_len</value> </param> <param> - <key>gain17</key> - <value>0</value> + <key>len_tag_key</key> + <value>packet_length_tag_key</value> </param> <param> - <key>ant17</key> + <key>affinity</key> <value></value> </param> <param> - <key>bw17</key> - <value>0</value> - </param> - <param> - <key>center_freq18</key> - <value>0</value> - </param> - <param> - <key>gain18</key> + <key>minoutbuf</key> <value>0</value> </param> <param> - <key>ant18</key> - <value></value> - </param> - <param> - <key>bw18</key> - <value>0</value> + <key>_coordinate</key> + <value>(171, 182)</value> </param> <param> - <key>center_freq19</key> + <key>_rotation</key> <value>0</value> </param> + </block> + <block> + <key>digital_header_payload_demux</key> <param> - <key>gain19</key> - <value>0</value> + <key>id</key> + <value>digital_header_payload_demux_0</value> </param> <param> - <key>ant19</key> - <value></value> + <key>_enabled</key> + <value>True</value> </param> <param> - <key>bw19</key> - <value>0</value> + <key>header_len</key> + <value>3</value> </param> <param> - <key>center_freq20</key> - <value>0</value> + <key>items_per_symbol</key> + <value>fft_len</value> </param> <param> - <key>gain20</key> - <value>0</value> + <key>guard_interval</key> + <value>fft_len/4</value> </param> <param> - <key>ant20</key> - <value></value> + <key>length_tag_key</key> + <value>length_tag_key</value> </param> <param> - <key>bw20</key> - <value>0</value> + <key>trigger_tag_key</key> + <value>""</value> </param> <param> - <key>center_freq21</key> - <value>0</value> + <key>output_symbols</key> + <value>True</value> </param> <param> - <key>gain21</key> - <value>0</value> + <key>type</key> + <value>complex</value> </param> <param> - <key>ant21</key> + <key>affinity</key> <value></value> </param> <param> - <key>bw21</key> + <key>minoutbuf</key> <value>0</value> </param> <param> - <key>center_freq22</key> - <value>0</value> + <key>_coordinate</key> + <value>(775, 408)</value> </param> <param> - <key>gain22</key> + <key>_rotation</key> <value>0</value> </param> + </block> + <block> + <key>digital_ofdm_chanest_vcvc</key> <param> - <key>ant22</key> - <value></value> + <key>id</key> + <value>digital_ofdm_chanest_vcvc_0</value> </param> <param> - <key>bw22</key> - <value>0</value> + <key>_enabled</key> + <value>True</value> </param> <param> - <key>center_freq23</key> - <value>0</value> + <key>sync_symbol1</key> + <value>sync_word1</value> </param> <param> - <key>gain23</key> - <value>0</value> + <key>sync_symbol2</key> + <value>sync_word2</value> </param> <param> - <key>ant23</key> - <value></value> + <key>n_data_symbols</key> + <value>1</value> </param> <param> - <key>bw23</key> + <key>eq_noise_red_len</key> <value>0</value> </param> <param> - <key>center_freq24</key> - <value>0</value> + <key>max_carr_offset</key> + <value>3</value> </param> <param> - <key>gain24</key> - <value>0</value> + <key>force_one_symbol</key> + <value>False</value> </param> <param> - <key>ant24</key> + <key>affinity</key> <value></value> </param> <param> - <key>bw24</key> + <key>minoutbuf</key> <value>0</value> </param> <param> - <key>center_freq25</key> - <value>0</value> + <key>_coordinate</key> + <value>(442, 584)</value> </param> <param> - <key>gain25</key> + <key>_rotation</key> <value>0</value> </param> + </block> + <block> + <key>digital_ofdm_frame_equalizer_vcvc</key> <param> - <key>ant25</key> - <value></value> + <key>id</key> + <value>digital_ofdm_frame_equalizer_vcvc_0</value> </param> <param> - <key>bw25</key> - <value>0</value> + <key>_enabled</key> + <value>True</value> </param> <param> - <key>center_freq26</key> - <value>0</value> + <key>fft_len</key> + <value>fft_len</value> </param> <param> - <key>gain26</key> - <value>0</value> + <key>cp_len</key> + <value>fft_len/4</value> </param> <param> - <key>ant26</key> - <value></value> + <key>equalizer</key> + <value>header_equalizer.base()</value> </param> <param> - <key>bw26</key> - <value>0</value> + <key>len_tag_key</key> + <value>length_tag_key</value> </param> <param> - <key>center_freq27</key> - <value>0</value> + <key>propagate_channel_state</key> + <value>True</value> </param> <param> - <key>gain27</key> - <value>0</value> + <key>fixed_frame_len</key> + <value>1</value> </param> <param> - <key>ant27</key> + <key>affinity</key> <value></value> </param> <param> - <key>bw27</key> + <key>minoutbuf</key> <value>0</value> </param> <param> - <key>center_freq28</key> - <value>0</value> - </param> - <param> - <key>gain28</key> - <value>0</value> - </param> - <param> - <key>ant28</key> - <value></value> + <key>_coordinate</key> + <value>(675, 577)</value> </param> <param> - <key>bw28</key> + <key>_rotation</key> <value>0</value> </param> + </block> + <block> + <key>virtual_source</key> <param> - <key>center_freq29</key> - <value>0</value> + <key>id</key> + <value>virtual_source_1</value> </param> <param> - <key>gain29</key> - <value>0</value> + <key>_enabled</key> + <value>True</value> </param> <param> - <key>ant29</key> - <value></value> + <key>stream_id</key> + <value>Payload Stream</value> </param> <param> - <key>bw29</key> - <value>0</value> + <key>_coordinate</key> + <value>(0, 732)</value> </param> <param> - <key>center_freq30</key> + <key>_rotation</key> <value>0</value> </param> + </block> + <block> + <key>digital_ofdm_serializer_vcc</key> <param> - <key>gain30</key> - <value>0</value> + <key>id</key> + <value>digital_ofdm_serializer_vcc_header</value> </param> <param> - <key>ant30</key> - <value></value> + <key>_enabled</key> + <value>True</value> </param> <param> - <key>bw30</key> - <value>0</value> + <key>fft_len</key> + <value>fft_len</value> </param> <param> - <key>center_freq31</key> - <value>0</value> + <key>occupied_carriers</key> + <value>occupied_carriers</value> </param> <param> - <key>gain31</key> - <value>0</value> + <key>len_tag_key</key> + <value>length_tag_key</value> </param> <param> - <key>ant31</key> + <key>packet_len_tag_key</key> <value></value> </param> <param> - <key>bw31</key> - <value>0</value> - </param> - <param> - <key>_coordinate</key> - <value>(0, 135)</value> - </param> - <param> - <key>_rotation</key> + <key>symbols_skipped</key> <value>0</value> </param> - </block> - <block> - <key>blocks_delay</key> <param> - <key>id</key> - <value>blocks_delay_0</value> + <key>carr_offset_key</key> + <value></value> </param> <param> - <key>_enabled</key> + <key>input_is_shifted</key> <value>True</value> </param> <param> - <key>type</key> - <value>complex</value> - </param> - <param> - <key>delay</key> - <value>fft_len+fft_len/4</value> - </param> - <param> - <key>num_ports</key> - <value>1</value> + <key>affinity</key> + <value></value> </param> <param> - <key>vlen</key> - <value>1</value> + <key>minoutbuf</key> + <value>0</value> </param> <param> <key>_coordinate</key> - <value>(398, 235)</value> + <value>(914, 584)</value> </param> <param> <key>_rotation</key> @@ -1163,22 +1081,22 @@ </param> </block> <block> - <key>variable</key> + <key>virtual_sink</key> <param> <key>id</key> - <value>length_tag_key</value> + <value>virtual_sink_1</value> </param> <param> <key>_enabled</key> <value>True</value> </param> <param> - <key>value</key> - <value>"frame_len"</value> + <key>stream_id</key> + <value>Payload Stream</value> </param> <param> <key>_coordinate</key> - <value>(367, -1)</value> + <value>(1094, 470)</value> </param> <param> <key>_rotation</key> @@ -1186,22 +1104,22 @@ </param> </block> <block> - <key>variable</key> + <key>virtual_source</key> <param> <key>id</key> - <value>header_formatter</value> + <value>virtual_source_0</value> </param> <param> <key>_enabled</key> <value>True</value> </param> <param> - <key>value</key> - <value>digital.packet_header_ofdm(occupied_carriers, 1, "packet_len", length_tag_key)</value> + <key>stream_id</key> + <value>Header Stream</value> </param> <param> <key>_coordinate</key> - <value>(811, -1)</value> + <value>(5, 606)</value> </param> <param> <key>_rotation</key> @@ -1209,89 +1127,50 @@ </param> </block> <block> - <key>digital_header_payload_demux</key> + <key>fft_vxx</key> <param> <key>id</key> - <value>digital_header_payload_demux_0</value> + <value>fft_vxx_1</value> </param> <param> <key>_enabled</key> <value>True</value> </param> <param> - <key>header_len</key> - <value>3</value> - </param> - <param> - <key>items_per_symbol</key> - <value>fft_len</value> - </param> - <param> - <key>guard_interval</key> - <value>fft_len/4</value> - </param> - <param> - <key>length_tag_key</key> - <value>length_tag_key</value> - </param> - <param> - <key>trigger_tag_key</key> - <value>""</value> - </param> - <param> - <key>output_symbols</key> - <value>True</value> - </param> - <param> <key>type</key> <value>complex</value> </param> <param> - <key>_coordinate</key> - <value>(678, 298)</value> - </param> - <param> - <key>_rotation</key> - <value>0</value> - </param> - </block> - <block> - <key>digital_ofdm_chanest_vcvc</key> - <param> - <key>id</key> - <value>digital_ofdm_chanest_vcvc_1</value> + <key>fft_size</key> + <value>fft_len</value> </param> <param> - <key>_enabled</key> + <key>forward</key> <value>True</value> </param> <param> - <key>sync_symbol1</key> - <value>sync_word1</value> + <key>window</key> + <value></value> </param> <param> - <key>sync_symbol2</key> - <value>sync_word2</value> + <key>shift</key> + <value>True</value> </param> <param> - <key>n_data_symbols</key> + <key>nthreads</key> <value>1</value> </param> <param> - <key>eq_noise_red_len</key> - <value>0</value> - </param> - <param> - <key>max_carr_offset</key> - <value>-1</value> + <key>affinity</key> + <value></value> </param> <param> - <key>force_one_symbol</key> - <value>False</value> + <key>minoutbuf</key> + <value>0</value> </param> <param> <key>_coordinate</key> - <value>(453, 520)</value> + <value>(221, 702)</value> </param> <param> <key>_rotation</key> @@ -1302,7 +1181,7 @@ <key>digital_ofdm_frame_equalizer_vcvc</key> <param> <key>id</key> - <value>digital_ofdm_frame_equalizer_vcvc_0_0</value> + <value>digital_ofdm_frame_equalizer_vcvc_1</value> </param> <param> <key>_enabled</key> @@ -1318,19 +1197,31 @@ </param> <param> <key>equalizer</key> - <value>digital.ofdm_equalizer_simpledfe(fft_len, header_mod.base(), occupied_carriers, pilot_carriers, pilot_symbols).base()</value> + <value>payload_equalizer.base()</value> </param> <param> <key>len_tag_key</key> - <value>length_tag_name</value> + <value>length_tag_key</value> </param> <param> <key>propagate_channel_state</key> <value>True</value> </param> <param> + <key>fixed_frame_len</key> + <value>0</value> + </param> + <param> + <key>affinity</key> + <value></value> + </param> + <param> + <key>minoutbuf</key> + <value>0</value> + </param> + <param> <key>_coordinate</key> - <value>(698, 520)</value> + <value>(672, 702)</value> </param> <param> <key>_rotation</key> @@ -1338,33 +1229,33 @@ </param> </block> <block> - <key>digital_packet_headerparser_b</key> + <key>virtual_sink</key> <param> <key>id</key> - <value>digital_packet_headerparser_b_0</value> + <value>virtual_sink_1_0</value> </param> <param> <key>_enabled</key> <value>True</value> </param> <param> - <key>header_formatter</key> - <value>header_formatter.formatter()</value> + <key>stream_id</key> + <value>Payload IQ</value> </param> <param> <key>_coordinate</key> - <value>(919, 501)</value> + <value>(1139, 732)</value> </param> <param> <key>_rotation</key> - <value>90</value> + <value>0</value> </param> </block> <block> <key>digital_ofdm_serializer_vcc</key> <param> <key>id</key> - <value>digital_ofdm_serializer_vcc_0</value> + <value>digital_ofdm_serializer_vcc_payload</value> </param> <param> <key>_enabled</key> @@ -1384,23 +1275,31 @@ </param> <param> <key>packet_len_tag_key</key> - <value>""</value> + <value>packet_length_tag_key</value> </param> <param> <key>symbols_skipped</key> - <value>0</value> + <value>1</value> </param> <param> <key>carr_offset_key</key> - <value>""</value> + <value></value> </param> <param> <key>input_is_shifted</key> <value>True</value> </param> <param> + <key>affinity</key> + <value></value> + </param> + <param> + <key>minoutbuf</key> + <value>0</value> + </param> + <param> <key>_coordinate</key> - <value>(187, 678)</value> + <value>(916, 710)</value> </param> <param> <key>_rotation</key> @@ -1408,45 +1307,34 @@ </param> </block> <block> - <key>digital_constellation_decoder_cb</key> + <key>digital_crc32_bb</key> <param> <key>id</key> - <value>digital_constellation_decoder_cb_0_0</value> + <value>digital_crc32_bb_0</value> </param> <param> <key>_enabled</key> <value>True</value> </param> <param> - <key>constellation</key> - <value>header_mod.base()</value> - </param> - <param> - <key>_coordinate</key> - <value>(449, 702)</value> - </param> - <param> - <key>_rotation</key> - <value>0</value> + <key>check</key> + <value>True</value> </param> - </block> - <block> - <key>virtual_source</key> <param> - <key>id</key> - <value>virtual_source_0_0</value> + <key>lengthtagname</key> + <value>packet_length_tag_key</value> </param> <param> - <key>_enabled</key> - <value>True</value> + <key>affinity</key> + <value></value> </param> <param> - <key>stream_id</key> - <value>Payload Stream</value> + <key>minoutbuf</key> + <value>0</value> </param> <param> <key>_coordinate</key> - <value>(0, 814)</value> + <value>(659, 841)</value> </param> <param> <key>_rotation</key> @@ -1454,38 +1342,42 @@ </param> </block> <block> - <key>blocks_tag_debug</key> + <key>blocks_repack_bits_bb</key> <param> <key>id</key> - <value>blocks_tag_debug_0</value> + <value>blocks_repack_bits_bb_0</value> </param> <param> <key>_enabled</key> <value>True</value> </param> <param> - <key>type</key> - <value>byte</value> + <key>k</key> + <value>payload_mod.bits_per_symbol()</value> </param> <param> - <key>name</key> - <value>Rx Packets</value> + <key>l</key> + <value>8</value> </param> <param> - <key>num_inputs</key> - <value>1</value> + <key>len_tag_key</key> + <value>packet_length_tag_key</value> </param> <param> - <key>vlen</key> - <value>1</value> + <key>align_output</key> + <value>True</value> </param> <param> - <key>display</key> - <value>True</value> + <key>affinity</key> + <value></value> + </param> + <param> + <key>minoutbuf</key> + <value>0</value> </param> <param> <key>_coordinate</key> - <value>(904, 948)</value> + <value>(430, 826)</value> </param> <param> <key>_rotation</key> @@ -1496,7 +1388,7 @@ <key>digital_constellation_decoder_cb</key> <param> <key>id</key> - <value>digital_constellation_decoder_cb_0</value> + <value>digital_constellation_decoder_cb_1</value> </param> <param> <key>_enabled</key> @@ -1507,8 +1399,16 @@ <value>payload_mod.base()</value> </param> <param> + <key>affinity</key> + <value></value> + </param> + <param> + <key>minoutbuf</key> + <value>0</value> + </param> + <param> <key>_coordinate</key> - <value>(416, 956)</value> + <value>(183, 848)</value> </param> <param> <key>_rotation</key> @@ -1516,26 +1416,22 @@ </param> </block> <block> - <key>digital_crc32_bb</key> + <key>virtual_source</key> <param> <key>id</key> - <value>digital_crc32_bb_0</value> + <value>virtual_source_0_0</value> </param> <param> <key>_enabled</key> <value>True</value> </param> <param> - <key>check</key> - <value>False</value> - </param> - <param> - <key>lengthtagname</key> - <value>"packet_len"</value> + <key>stream_id</key> + <value>Payload IQ</value> </param> <param> <key>_coordinate</key> - <value>(663, 948)</value> + <value>(1, 851)</value> </param> <param> <key>_rotation</key> @@ -1543,10 +1439,10 @@ </param> </block> <block> - <key>fft_vxx</key> + <key>blocks_tag_debug</key> <param> <key>id</key> - <value>fft_vxx_0</value> + <value>blocks_tag_debug_1</value> </param> <param> <key>_enabled</key> @@ -1554,54 +1450,31 @@ </param> <param> <key>type</key> - <value>complex</value> - </param> - <param> - <key>fft_size</key> - <value>fft_len</value> - </param> - <param> - <key>forward</key> - <value>True</value> - </param> - <param> - <key>window</key> - <value></value> + <value>byte</value> </param> <param> - <key>shift</key> - <value>True</value> + <key>name</key> + <value>Rx Bytes</value> </param> <param> - <key>nthreads</key> + <key>num_inputs</key> <value>1</value> </param> <param> - <key>_coordinate</key> - <value>(223, 512)</value> - </param> - <param> - <key>_rotation</key> - <value>0</value> - </param> - </block> - <block> - <key>virtual_source</key> - <param> - <key>id</key> - <value>virtual_source_0</value> + <key>vlen</key> + <value>1</value> </param> <param> - <key>_enabled</key> + <key>display</key> <value>True</value> </param> <param> - <key>stream_id</key> - <value>Header Stream</value> + <key>affinity</key> + <value></value> </param> <param> <key>_coordinate</key> - <value>(1, 544)</value> + <value>(898, 841)</value> </param> <param> <key>_rotation</key> @@ -1609,65 +1482,50 @@ </param> </block> <block> - <key>analog_frequency_modulator_fc</key> + <key>channels_channel_model</key> <param> <key>id</key> - <value>analog_frequency_modulator_fc_0</value> + <value>channels_channel_model_0</value> </param> <param> <key>_enabled</key> <value>True</value> </param> <param> - <key>sensitivity</key> - <value>-2.0/fft_len</value> - </param> - <param> - <key>_coordinate</key> - <value>(578, 133)</value> - </param> - <param> - <key>_rotation</key> - <value>0</value> + <key>noise_voltage</key> + <value>0.1</value> </param> - </block> - <block> - <key>fft_vxx</key> <param> - <key>id</key> - <value>fft_vxx_0_0</value> + <key>freq_offset</key> + <value>0 * 1.0/fft_len</value> </param> <param> - <key>_enabled</key> - <value>True</value> + <key>epsilon</key> + <value>1.0</value> </param> <param> - <key>type</key> - <value>complex</value> + <key>taps</key> + <value>1.0</value> </param> <param> - <key>fft_size</key> - <value>fft_len</value> + <key>seed</key> + <value>0</value> </param> <param> - <key>forward</key> + <key>block_tags</key> <value>True</value> </param> <param> - <key>window</key> + <key>affinity</key> <value></value> </param> <param> - <key>shift</key> - <value>True</value> - </param> - <param> - <key>nthreads</key> - <value>1</value> + <key>minoutbuf</key> + <value>0</value> </param> <param> <key>_coordinate</key> - <value>(218, 782)</value> + <value>(303, 372)</value> </param> <param> <key>_rotation</key> @@ -1675,10 +1533,10 @@ </param> </block> <block> - <key>digital_ofdm_serializer_vcc</key> + <key>digital_ofdm_tx</key> <param> <key>id</key> - <value>digital_ofdm_serializer_vcc_1</value> + <value>digital_ofdm_tx_0</value> </param> <param> <key>_enabled</key> @@ -1689,71 +1547,64 @@ <value>fft_len</value> </param> <param> - <key>occupied_carriers</key> - <value>occupied_carriers</value> - </param> - <param> - <key>len_tag_key</key> - <value>length_tag_key</value> + <key>cp_len</key> + <value>fft_len/4</value> </param> <param> - <key>packet_len_tag_key</key> - <value>"packet_len"</value> + <key>packet_len_key</key> + <value>packet_length_tag_key</value> </param> <param> - <key>symbols_skipped</key> - <value>0</value> + <key>occupied_carriers</key> + <value>occupied_carriers</value> </param> <param> - <key>carr_offset_key</key> - <value>""</value> + <key>pilot_carriers</key> + <value>pilot_carriers</value> </param> <param> - <key>input_is_shifted</key> - <value>True</value> + <key>pilot_symbols</key> + <value>pilot_symbols</value> </param> <param> - <key>_coordinate</key> - <value>(778, 790)</value> + <key>sync_word1</key> + <value>sync_word1</value> </param> <param> - <key>_rotation</key> - <value>0</value> + <key>sync_word2</key> + <value>sync_word2</value> </param> - </block> - <block> - <key>digital_ofdm_frame_equalizer_vcvc</key> <param> - <key>id</key> - <value>digital_ofdm_frame_equalizer_vcvc_1</value> + <key>header_mod</key> + <value>"BPSK"</value> </param> <param> - <key>_enabled</key> - <value>True</value> + <key>payload_mod</key> + <value>"QPSK"</value> </param> <param> - <key>fft_len</key> - <value>fft_len</value> + <key>rolloff</key> + <value>0</value> </param> <param> - <key>cp_len</key> - <value>fft_len/4</value> + <key>scramble_bits</key> + <value>False</value> </param> <param> - <key>equalizer</key> - <value>digital.ofdm_equalizer_simpledfe(fft_len, header_mod.base(), occupied_carriers, pilot_carriers, pilot_symbols, 2).base()</value> + <key>log</key> + <value>True</value> </param> <param> - <key>len_tag_key</key> - <value>length_tag_key</value> + <key>affinity</key> + <value></value> </param> <param> - <key>propagate_channel_state</key> - <value>True</value> + <key>minoutbuf</key> + <value>0</value> </param> <param> <key>_coordinate</key> - <value>(474, 782)</value> + <value>(58, 327)</value> </param> <param> <key>_rotation</key> @@ -1761,39 +1612,33 @@ </param> </block> <connection> - <source_block_id>digital_ofdm_frame_equalizer_vcvc_0_0</source_block_id> - <sink_block_id>digital_ofdm_serializer_vcc_0</sink_block_id> + <source_block_id>analog_random_source_x_0</source_block_id> + <sink_block_id>blocks_stream_to_tagged_stream_0</sink_block_id> <source_key>0</source_key> <sink_key>0</sink_key> </connection> <connection> - <source_block_id>virtual_source_0</source_block_id> - <sink_block_id>fft_vxx_0</sink_block_id> + <source_block_id>blocks_stream_to_tagged_stream_0</source_block_id> + <sink_block_id>digital_ofdm_tx_0</sink_block_id> <source_key>0</source_key> <sink_key>0</sink_key> </connection> <connection> - <source_block_id>digital_packet_headerparser_b_0</source_block_id> - <sink_block_id>digital_header_payload_demux_0</sink_block_id> - <source_key>header_data</source_key> - <sink_key>header_data</sink_key> - </connection> - <connection> - <source_block_id>digital_constellation_decoder_cb_0_0</source_block_id> - <sink_block_id>digital_packet_headerparser_b_0</sink_block_id> + <source_block_id>digital_ofdm_tx_0</source_block_id> + <sink_block_id>channels_channel_model_0</sink_block_id> <source_key>0</source_key> <sink_key>0</sink_key> </connection> <connection> - <source_block_id>digital_ofdm_serializer_vcc_0</source_block_id> - <sink_block_id>digital_constellation_decoder_cb_0_0</sink_block_id> + <source_block_id>channels_channel_model_0</source_block_id> + <sink_block_id>blocks_throttle_0</sink_block_id> <source_key>0</source_key> <sink_key>0</sink_key> </connection> <connection> - <source_block_id>digital_header_payload_demux_0</source_block_id> - <sink_block_id>virtual_sink_0_0</sink_block_id> - <source_key>1</source_key> + <source_block_id>blocks_throttle_0</source_block_id> + <sink_block_id>digital_ofdm_sync_sc_cfb_0</sink_block_id> + <source_key>0</source_key> <sink_key>0</sink_key> </connection> <connection> @@ -1803,34 +1648,34 @@ <sink_key>0</sink_key> </connection> <connection> - <source_block_id>blocks_throttle_0</source_block_id> - <sink_block_id>digital_ofdm_sync_sc_cfb_0</sink_block_id> + <source_block_id>digital_ofdm_sync_sc_cfb_0</source_block_id> + <sink_block_id>analog_frequency_modulator_fc_0</sink_block_id> <source_key>0</source_key> <sink_key>0</sink_key> </connection> <connection> - <source_block_id>uhd_usrp_source_0</source_block_id> - <sink_block_id>digital_ofdm_sync_sc_cfb_0</sink_block_id> + <source_block_id>analog_frequency_modulator_fc_0</source_block_id> + <sink_block_id>blocks_multiply_xx_0</sink_block_id> <source_key>0</source_key> <sink_key>0</sink_key> </connection> <connection> - <source_block_id>analog_noise_source_x_0</source_block_id> - <sink_block_id>blocks_throttle_0</sink_block_id> + <source_block_id>blocks_multiply_xx_0</source_block_id> + <sink_block_id>digital_header_payload_demux_0</sink_block_id> <source_key>0</source_key> <sink_key>0</sink_key> </connection> <connection> - <source_block_id>analog_frequency_modulator_fc_0</source_block_id> - <sink_block_id>blocks_multiply_xx_0</sink_block_id> + <source_block_id>blocks_throttle_0</source_block_id> + <sink_block_id>blocks_delay_0</sink_block_id> <source_key>0</source_key> <sink_key>0</sink_key> </connection> <connection> - <source_block_id>digital_ofdm_sync_sc_cfb_0</source_block_id> - <sink_block_id>analog_frequency_modulator_fc_0</sink_block_id> + <source_block_id>blocks_delay_0</source_block_id> + <sink_block_id>blocks_multiply_xx_0</sink_block_id> <source_key>0</source_key> - <sink_key>0</sink_key> + <sink_key>1</sink_key> </connection> <connection> <source_block_id>digital_ofdm_sync_sc_cfb_0</source_block_id> @@ -1839,74 +1684,98 @@ <sink_key>1</sink_key> </connection> <connection> - <source_block_id>blocks_multiply_xx_0</source_block_id> + <source_block_id>digital_header_payload_demux_0</source_block_id> + <sink_block_id>virtual_sink_1</sink_block_id> + <source_key>1</source_key> + <sink_key>0</sink_key> + </connection> + <connection> + <source_block_id>digital_packet_headerparser_b_0</source_block_id> <sink_block_id>digital_header_payload_demux_0</sink_block_id> + <source_key>header_data</source_key> + <sink_key>header_data</sink_key> + </connection> + <connection> + <source_block_id>digital_ofdm_chanest_vcvc_0</source_block_id> + <sink_block_id>digital_ofdm_frame_equalizer_vcvc_0</sink_block_id> <source_key>0</source_key> <sink_key>0</sink_key> </connection> <connection> - <source_block_id>blocks_delay_0</source_block_id> - <sink_block_id>blocks_multiply_xx_0</sink_block_id> + <source_block_id>digital_ofdm_frame_equalizer_vcvc_0</source_block_id> + <sink_block_id>digital_ofdm_serializer_vcc_header</sink_block_id> <source_key>0</source_key> - <sink_key>1</sink_key> + <sink_key>0</sink_key> </connection> <connection> - <source_block_id>blocks_throttle_0</source_block_id> - <sink_block_id>blocks_delay_0</sink_block_id> + <source_block_id>digital_ofdm_serializer_vcc_header</source_block_id> + <sink_block_id>digital_constellation_decoder_cb_0</sink_block_id> <source_key>0</source_key> <sink_key>0</sink_key> </connection> <connection> - <source_block_id>uhd_usrp_source_0</source_block_id> - <sink_block_id>blocks_delay_0</sink_block_id> + <source_block_id>digital_constellation_decoder_cb_0</source_block_id> + <sink_block_id>digital_packet_headerparser_b_0</sink_block_id> <source_key>0</source_key> <sink_key>0</sink_key> </connection> <connection> <source_block_id>fft_vxx_0</source_block_id> - <sink_block_id>digital_ofdm_chanest_vcvc_1</sink_block_id> + <sink_block_id>digital_ofdm_chanest_vcvc_0</sink_block_id> <source_key>0</source_key> <sink_key>0</sink_key> </connection> <connection> - <source_block_id>digital_ofdm_chanest_vcvc_1</source_block_id> - <sink_block_id>digital_ofdm_frame_equalizer_vcvc_0_0</sink_block_id> + <source_block_id>virtual_source_0</source_block_id> + <sink_block_id>fft_vxx_0</sink_block_id> <source_key>0</source_key> <sink_key>0</sink_key> </connection> <connection> - <source_block_id>digital_crc32_bb_0</source_block_id> - <sink_block_id>blocks_tag_debug_0</sink_block_id> + <source_block_id>virtual_source_1</source_block_id> + <sink_block_id>fft_vxx_1</sink_block_id> <source_key>0</source_key> <sink_key>0</sink_key> </connection> <connection> - <source_block_id>digital_constellation_decoder_cb_0</source_block_id> - <sink_block_id>digital_crc32_bb_0</sink_block_id> + <source_block_id>digital_ofdm_serializer_vcc_payload</source_block_id> + <sink_block_id>virtual_sink_1_0</sink_block_id> <source_key>0</source_key> <sink_key>0</sink_key> </connection> <connection> - <source_block_id>digital_ofdm_serializer_vcc_1</source_block_id> - <sink_block_id>digital_constellation_decoder_cb_0</sink_block_id> + <source_block_id>digital_ofdm_frame_equalizer_vcvc_1</source_block_id> + <sink_block_id>digital_ofdm_serializer_vcc_payload</sink_block_id> <source_key>0</source_key> <sink_key>0</sink_key> </connection> <connection> - <source_block_id>virtual_source_0_0</source_block_id> - <sink_block_id>fft_vxx_0_0</sink_block_id> + <source_block_id>fft_vxx_1</source_block_id> + <sink_block_id>digital_ofdm_frame_equalizer_vcvc_1</sink_block_id> <source_key>0</source_key> <sink_key>0</sink_key> </connection> <connection> - <source_block_id>fft_vxx_0_0</source_block_id> - <sink_block_id>digital_ofdm_frame_equalizer_vcvc_1</sink_block_id> + <source_block_id>digital_crc32_bb_0</source_block_id> + <sink_block_id>blocks_tag_debug_1</sink_block_id> <source_key>0</source_key> <sink_key>0</sink_key> </connection> <connection> - <source_block_id>digital_ofdm_frame_equalizer_vcvc_1</source_block_id> - <sink_block_id>digital_ofdm_serializer_vcc_1</sink_block_id> + <source_block_id>blocks_repack_bits_bb_0</source_block_id> + <sink_block_id>digital_crc32_bb_0</sink_block_id> + <source_key>0</source_key> + <sink_key>0</sink_key> + </connection> + <connection> + <source_block_id>virtual_source_0_0</source_block_id> + <sink_block_id>digital_constellation_decoder_cb_1</sink_block_id> + <source_key>0</source_key> + <sink_key>0</sink_key> + </connection> + <connection> + <source_block_id>digital_constellation_decoder_cb_1</source_block_id> + <sink_block_id>blocks_repack_bits_bb_0</sink_block_id> <source_key>0</source_key> <sink_key>0</sink_key> </connection> diff --git a/gr-digital/examples/ofdm/tx_ofdm.grc b/gr-digital/examples/ofdm/tx_ofdm.grc index dcaeed2e72..c2995d919e 100644 --- a/gr-digital/examples/ofdm/tx_ofdm.grc +++ b/gr-digital/examples/ofdm/tx_ofdm.grc @@ -1,6 +1,6 @@ <?xml version='1.0' encoding='ASCII'?> <flow_graph> - <timestamp>Tue May 14 10:52:12 2013</timestamp> + <timestamp>Sun Oct 27 16:23:43 2013</timestamp> <block> <key>options</key> <param> @@ -61,57 +61,22 @@ </param> </block> <block> - <key>virtual_source</key> - <param> - <key>id</key> - <value>virtual_source_0_0</value> - </param> - <param> - <key>_enabled</key> - <value>True</value> - </param> - <param> - <key>stream_id</key> - <value>Payload Bits</value> - </param> - <param> - <key>_coordinate</key> - <value>(0, 458)</value> - </param> - <param> - <key>_rotation</key> - <value>0</value> - </param> - </block> - <block> - <key>blocks_tagged_stream_mux</key> + <key>variable</key> <param> <key>id</key> - <value>blocks_tagged_stream_mux_0</value> + <value>length_tag_key</value> </param> <param> <key>_enabled</key> <value>True</value> </param> <param> - <key>type</key> - <value>complex</value> - </param> - <param> - <key>ninputs</key> - <value>2</value> - </param> - <param> - <key>lengthtagname</key> - <value>length_tag_name</value> - </param> - <param> - <key>vlen</key> - <value>1</value> + <key>value</key> + <value>"packet_len"</value> </param> <param> <key>_coordinate</key> - <value>(510, 428)</value> + <value>(352, 0)</value> </param> <param> <key>_rotation</key> @@ -119,22 +84,22 @@ </param> </block> <block> - <key>virtual_sink</key> + <key>variable</key> <param> <key>id</key> - <value>virtual_sink_0_0</value> + <value>samp_rate</value> </param> <param> <key>_enabled</key> <value>True</value> </param> <param> - <key>stream_id</key> - <value>Payload Bits</value> + <key>value</key> + <value>100000</value> </param> <param> <key>_coordinate</key> - <value>(746, 312)</value> + <value>(255, 0)</value> </param> <param> <key>_rotation</key> @@ -142,45 +107,22 @@ </param> </block> <block> - <key>virtual_source</key> + <key>variable</key> <param> <key>id</key> - <value>virtual_source_0</value> + <value>rolloff</value> </param> <param> <key>_enabled</key> <value>True</value> </param> <param> - <key>stream_id</key> - <value>Header Bits</value> - </param> - <param> - <key>_coordinate</key> - <value>(0, 384)</value> - </param> - <param> - <key>_rotation</key> + <key>value</key> <value>0</value> </param> - </block> - <block> - <key>digital_packet_headergenerator_bb</key> - <param> - <key>id</key> - <value>digital_packet_headergenerator_bb_0</value> - </param> - <param> - <key>_enabled</key> - <value>True</value> - </param> - <param> - <key>header_formatter</key> - <value>header_formatter.formatter()</value> - </param> <param> <key>_coordinate</key> - <value>(514, 231)</value> + <value>(898, -1)</value> </param> <param> <key>_rotation</key> @@ -188,34 +130,22 @@ </param> </block> <block> - <key>blocks_repack_bits_bb</key> + <key>variable</key> <param> <key>id</key> - <value>blocks_repack_bits_bb_0</value> + <value>payload_mod</value> </param> <param> <key>_enabled</key> <value>True</value> </param> <param> - <key>k</key> - <value>8</value> - </param> - <param> - <key>l</key> - <value>payload_mod.bits_per_symbol()</value> - </param> - <param> - <key>len_tag_key</key> - <value>length_tag_name</value> - </param> - <param> - <key>align_output</key> - <value>False</value> + <key>value</key> + <value>digital.constellation_qpsk()</value> </param> <param> <key>_coordinate</key> - <value>(522, 289)</value> + <value>(734, 0)</value> </param> <param> <key>_rotation</key> @@ -223,22 +153,22 @@ </param> </block> <block> - <key>virtual_sink</key> + <key>variable</key> <param> <key>id</key> - <value>header_bits</value> + <value>header_mod</value> </param> <param> <key>_enabled</key> <value>True</value> </param> <param> - <key>stream_id</key> - <value>Header Bits</value> + <key>value</key> + <value>digital.constellation_bpsk()</value> </param> <param> <key>_coordinate</key> - <value>(748, 231)</value> + <value>(567, 0)</value> </param> <param> <key>_rotation</key> @@ -246,26 +176,22 @@ </param> </block> <block> - <key>digital_crc32_bb</key> + <key>variable</key> <param> <key>id</key> - <value>digital_crc32_bb_0</value> + <value>packet_len</value> </param> <param> <key>_enabled</key> <value>True</value> </param> <param> - <key>check</key> - <value>False</value> - </param> - <param> - <key>lengthtagname</key> - <value>length_tag_name</value> + <key>value</key> + <value>96</value> </param> <param> <key>_coordinate</key> - <value>(242, 223)</value> + <value>(476, 0)</value> </param> <param> <key>_rotation</key> @@ -299,7 +225,7 @@ <key>variable</key> <param> <key>id</key> - <value>length_tag_name</value> + <value>header_formatter</value> </param> <param> <key>_enabled</key> @@ -307,11 +233,11 @@ </param> <param> <key>value</key> - <value>"packet_len"</value> + <value>digital.packet_header_ofdm(occupied_carriers, 1, length_tag_key)</value> </param> <param> <key>_coordinate</key> - <value>(352, 0)</value> + <value>(708, 64)</value> </param> <param> <key>_rotation</key> @@ -322,7 +248,7 @@ <key>variable</key> <param> <key>id</key> - <value>packet_len</value> + <value>pilot_carriers</value> </param> <param> <key>_enabled</key> @@ -330,11 +256,11 @@ </param> <param> <key>value</key> - <value>96</value> + <value>((-21, -7, 7, 21,),)</value> </param> <param> <key>_coordinate</key> - <value>(476, 0)</value> + <value>(480, 64)</value> </param> <param> <key>_rotation</key> @@ -345,7 +271,7 @@ <key>variable</key> <param> <key>id</key> - <value>header_mod</value> + <value>occupied_carriers</value> </param> <param> <key>_enabled</key> @@ -353,11 +279,11 @@ </param> <param> <key>value</key> - <value>digital.constellation_bpsk()</value> + <value>(range(-26, -21) + range(-20, -7) + range(-6, 0) + range(1, 7) + range(8, 21) + range(22, 27),)</value> </param> <param> <key>_coordinate</key> - <value>(567, 0)</value> + <value>(329, 64)</value> </param> <param> <key>_rotation</key> @@ -368,7 +294,7 @@ <key>variable</key> <param> <key>id</key> - <value>payload_mod</value> + <value>pilot_symbols</value> </param> <param> <key>_enabled</key> @@ -376,11 +302,11 @@ </param> <param> <key>value</key> - <value>digital.constellation_qpsk()</value> + <value>((1, 1, 1, -1,),)</value> </param> <param> <key>_coordinate</key> - <value>(734, 0)</value> + <value>(601, 64)</value> </param> <param> <key>_rotation</key> @@ -391,7 +317,7 @@ <key>variable</key> <param> <key>id</key> - <value>rolloff</value> + <value>sync_word2</value> </param> <param> <key>_enabled</key> @@ -399,11 +325,11 @@ </param> <param> <key>value</key> - <value>0</value> + <value>[0, 0, 0, 0, 0, 0, -1, -1, -1, -1, 1, 1, -1, -1, -1, 1, -1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, 1, -1, -1, 1, -1, 0, 1, -1, 1, 1, 1, -1, 1, 1, 1, -1, 1, 1, 1, 1, -1, 1, -1, -1, -1, 1, -1, 1, -1, -1, -1, -1, 0, 0, 0, 0, 0] </value> </param> <param> <key>_coordinate</key> - <value>(898, -1)</value> + <value>(496, 128)</value> </param> <param> <key>_rotation</key> @@ -414,7 +340,7 @@ <key>variable</key> <param> <key>id</key> - <value>samp_rate</value> + <value>sync_word1</value> </param> <param> <key>_enabled</key> @@ -422,11 +348,11 @@ </param> <param> <key>value</key> - <value>100000</value> + <value>[0., 0., 0., 0., 0., 0., 0., 1.41421356, 0., -1.41421356, 0., 1.41421356, 0., -1.41421356, 0., -1.41421356, 0., -1.41421356, 0., 1.41421356, 0., -1.41421356, 0., 1.41421356, 0., -1.41421356, 0., -1.41421356, 0., -1.41421356, 0., -1.41421356, 0., 1.41421356, 0., -1.41421356, 0., 1.41421356, 0., 1.41421356, 0., 1.41421356, 0., -1.41421356, 0., 1.41421356, 0., 1.41421356, 0., 1.41421356, 0., -1.41421356, 0., 1.41421356, 0., 1.41421356, 0., 1.41421356, 0., 0., 0., 0., 0., 0.]</value> </param> <param> <key>_coordinate</key> - <value>(255, 0)</value> + <value>(352, 128)</value> </param> <param> <key>_rotation</key> @@ -434,22 +360,22 @@ </param> </block> <block> - <key>variable</key> + <key>virtual_source</key> <param> <key>id</key> - <value>sync_word2</value> + <value>virtual_source_0_0</value> </param> <param> <key>_enabled</key> <value>True</value> </param> <param> - <key>value</key> - <value>(0, 0, 0, 0, 0, 1, 1, -1.0, -1, 1.0, 1, 1.0, -1, -1.0, -1, 1.0, 1, -1.0, 1, 1.0, 1, -1.0, -1, -1.0, -1, 1.0, -1, 1.0, -1, 1.0, 1, -1.0, 0, 1.0, 1, -1.0, 1, 1.0, -1, -1.0, 1, -1.0, -1, -1.0, 1, 1.0, 1, -1.0, 1, 1.0, -1, 1.0, -1, -1.0, -1, 1.0, 1, -1.0, 0, 0, 0, 0, 0, 0)</value> + <key>stream_id</key> + <value>Payload Bits</value> </param> <param> <key>_coordinate</key> - <value>(496, 128)</value> + <value>(0, 458)</value> </param> <param> <key>_rotation</key> @@ -457,22 +383,22 @@ </param> </block> <block> - <key>variable</key> + <key>import</key> <param> <key>id</key> - <value>sync_word1</value> + <value>import_0</value> </param> <param> <key>_enabled</key> <value>True</value> </param> <param> - <key>value</key> - <value>(0, 0, 0, 0, 0, 0, 0, -1.0, 0, 1.0, 0, 1.0, 0, -1.0, 0, 1.0, 0, -1.0, 0, 1.0, 0, -1.0, 0, -1.0, 0, 1.0, 0, 1.0, 0, 1.0, 0, -1.0, 0, 1.0, 0, -1.0, 0, 1.0, 0, -1.0, 0, -1.0, 0, -1.0, 0, 1.0, 0, -1.0, 0, 1.0, 0, 1.0, 0, -1.0, 0, 1.0, 0, -1.0, 0, 0, 0, 0, 0, 0)</value> + <key>import</key> + <value>import numpy</value> </param> <param> <key>_coordinate</key> - <value>(352, 128)</value> + <value>(237, 93)</value> </param> <param> <key>_rotation</key> @@ -480,22 +406,22 @@ </param> </block> <block> - <key>variable</key> + <key>import</key> <param> <key>id</key> - <value>occupied_carriers</value> + <value>import_1</value> </param> <param> <key>_enabled</key> <value>True</value> </param> <param> - <key>value</key> - <value>(range(-26, -21) + range(-20, -7) + range(-6, 0) + range(1, 7) + range(8, 21) + range(22, 27),)</value> + <key>import</key> + <value>from gnuradio.digital.utils import tagged_streams</value> </param> <param> <key>_coordinate</key> - <value>(329, 64)</value> + <value>(99, 93)</value> </param> <param> <key>_rotation</key> @@ -503,22 +429,22 @@ </param> </block> <block> - <key>variable</key> + <key>import</key> <param> <key>id</key> - <value>pilot_carriers</value> + <value>import_0_0</value> </param> <param> <key>_enabled</key> <value>True</value> </param> <param> - <key>value</key> - <value>((-21, -7, 7, 21,),)</value> + <key>import</key> + <value>import random</value> </param> <param> <key>_coordinate</key> - <value>(480, 64)</value> + <value>(3, 94)</value> </param> <param> <key>_rotation</key> @@ -526,22 +452,22 @@ </param> </block> <block> - <key>variable</key> + <key>virtual_source</key> <param> <key>id</key> - <value>header_formatter</value> + <value>virtual_source_0_0_0_0</value> </param> <param> <key>_enabled</key> <value>True</value> </param> <param> - <key>value</key> - <value>digital.packet_header_ofdm(occupied_carriers, 1, length_tag_name)</value> + <key>stream_id</key> + <value>Time Domain</value> </param> <param> <key>_coordinate</key> - <value>(708, 64)</value> + <value>(1, 747)</value> </param> <param> <key>_rotation</key> @@ -549,22 +475,22 @@ </param> </block> <block> - <key>variable</key> + <key>virtual_sink</key> <param> <key>id</key> - <value>pilot_symbols</value> + <value>virtual_sink_0_0_0</value> </param> <param> <key>_enabled</key> <value>True</value> </param> <param> - <key>value</key> - <value>((1, 1, 1, -1,),)</value> + <key>stream_id</key> + <value>Pre-OFDM</value> </param> <param> <key>_coordinate</key> - <value>(601, 64)</value> + <value>(745, 441)</value> </param> <param> <key>_rotation</key> @@ -572,68 +498,46 @@ </param> </block> <block> - <key>import</key> + <key>digital_chunks_to_symbols_xx</key> <param> <key>id</key> - <value>import_0</value> + <value>digital_chunks_to_symbols_xx_0_0</value> </param> <param> <key>_enabled</key> <value>True</value> </param> <param> - <key>import</key> - <value>import numpy</value> - </param> - <param> - <key>_coordinate</key> - <value>(237, 93)</value> + <key>in_type</key> + <value>byte</value> </param> <param> - <key>_rotation</key> - <value>0</value> + <key>out_type</key> + <value>complex</value> </param> - </block> - <block> - <key>import</key> <param> - <key>id</key> - <value>import_1</value> + <key>symbol_table</key> + <value>payload_mod.points()</value> </param> <param> - <key>_enabled</key> - <value>True</value> + <key>dimension</key> + <value>1</value> </param> <param> - <key>import</key> - <value>from gnuradio.digital.utils import tagged_streams</value> + <key>num_ports</key> + <value>1</value> </param> <param> - <key>_coordinate</key> - <value>(99, 93)</value> + <key>affinity</key> + <value></value> </param> <param> - <key>_rotation</key> + <key>minoutbuf</key> <value>0</value> </param> - </block> - <block> - <key>import</key> - <param> - <key>id</key> - <value>import_0_0</value> - </param> - <param> - <key>_enabled</key> - <value>True</value> - </param> - <param> - <key>import</key> - <value>import random</value> - </param> <param> <key>_coordinate</key> - <value>(3, 94)</value> + <value>(212, 450)</value> </param> <param> <key>_rotation</key> @@ -644,7 +548,7 @@ <key>virtual_source</key> <param> <key>id</key> - <value>virtual_source_0_0_0_0</value> + <value>virtual_source_0_0_0</value> </param> <param> <key>_enabled</key> @@ -652,11 +556,11 @@ </param> <param> <key>stream_id</key> - <value>Time Domain</value> + <value>Pre-OFDM</value> </param> <param> <key>_coordinate</key> - <value>(1, 747)</value> + <value>(0, 578)</value> </param> <param> <key>_rotation</key> @@ -664,30 +568,22 @@ </param> </block> <block> - <key>blocks_multiply_const_vxx</key> + <key>virtual_sink</key> <param> <key>id</key> - <value>blocks_multiply_const_vxx_0</value> + <value>virtual_sink_0</value> </param> <param> <key>_enabled</key> <value>True</value> </param> <param> - <key>type</key> - <value>complex</value> - </param> - <param> - <key>const</key> - <value>0.05</value> - </param> - <param> - <key>vlen</key> - <value>1</value> + <key>stream_id</key> + <value>Time Domain</value> </param> <param> <key>_coordinate</key> - <value>(209, 747)</value> + <value>(855, 578)</value> </param> <param> <key>_rotation</key> @@ -695,10 +591,10 @@ </param> </block> <block> - <key>wxgui_scopesink2</key> + <key>fft_vxx</key> <param> <key>id</key> - <value>wxgui_scopesink2_0</value> + <value>fft_vxx_0</value> </param> <param> <key>_enabled</key> @@ -709,60 +605,36 @@ <value>complex</value> </param> <param> - <key>title</key> - <value>Scope Plot</value> - </param> - <param> - <key>samp_rate</key> - <value>samp_rate</value> - </param> - <param> - <key>v_scale</key> - <value>0</value> - </param> - <param> - <key>v_offset</key> - <value>0</value> - </param> - <param> - <key>t_scale</key> - <value>0</value> - </param> - <param> - <key>ac_couple</key> - <value>False</value> + <key>fft_size</key> + <value>fft_len</value> </param> <param> - <key>xy_mode</key> + <key>forward</key> <value>False</value> </param> <param> - <key>num_inputs</key> - <value>1</value> + <key>window</key> + <value>()</value> </param> <param> - <key>win_size</key> - <value></value> + <key>shift</key> + <value>True</value> </param> <param> - <key>grid_pos</key> - <value></value> + <key>nthreads</key> + <value>1</value> </param> <param> - <key>notebook</key> + <key>affinity</key> <value></value> </param> <param> - <key>trig_mode</key> - <value>wxgui.TRIG_MODE_AUTO</value> - </param> - <param> - <key>y_axis_label</key> - <value>Counts</value> + <key>minoutbuf</key> + <value>0</value> </param> <param> <key>_coordinate</key> - <value>(584, 724)</value> + <value>(414, 548)</value> </param> <param> <key>_rotation</key> @@ -770,10 +642,10 @@ </param> </block> <block> - <key>blocks_throttle</key> + <key>blocks_multiply_const_vxx</key> <param> <key>id</key> - <value>blocks_throttle_0</value> + <value>blocks_multiply_const_vxx_0</value> </param> <param> <key>_enabled</key> @@ -784,16 +656,24 @@ <value>complex</value> </param> <param> - <key>samples_per_second</key> - <value>samp_rate</value> + <key>const</key> + <value>0.05</value> </param> <param> <key>vlen</key> <value>1</value> </param> <param> + <key>affinity</key> + <value></value> + </param> + <param> + <key>minoutbuf</key> + <value>0</value> + </param> + <param> <key>_coordinate</key> - <value>(402, 747)</value> + <value>(209, 747)</value> </param> <param> <key>_rotation</key> @@ -801,662 +681,670 @@ </param> </block> <block> - <key>uhd_usrp_sink</key> + <key>digital_chunks_to_symbols_xx</key> <param> <key>id</key> - <value>uhd_usrp_sink_0</value> + <value>digital_chunks_to_symbols_xx_0</value> </param> <param> <key>_enabled</key> - <value>False</value> - </param> - <param> - <key>type</key> - <value>fc32</value> - </param> - <param> - <key>otw</key> - <value></value> - </param> - <param> - <key>stream_args</key> - <value></value> + <value>True</value> </param> <param> - <key>dev_addr</key> - <value></value> + <key>in_type</key> + <value>byte</value> </param> <param> - <key>sync</key> - <value></value> + <key>out_type</key> + <value>complex</value> </param> <param> - <key>clock_rate</key> - <value>0.0</value> + <key>symbol_table</key> + <value>header_mod.points()</value> </param> <param> - <key>num_mboards</key> + <key>dimension</key> <value>1</value> </param> <param> - <key>clock_source0</key> - <value></value> - </param> - <param> - <key>time_source0</key> - <value></value> - </param> - <param> - <key>sd_spec0</key> - <value></value> - </param> - <param> - <key>clock_source1</key> - <value></value> + <key>num_ports</key> + <value>1</value> </param> <param> - <key>time_source1</key> + <key>affinity</key> <value></value> </param> <param> - <key>sd_spec1</key> - <value></value> + <key>minoutbuf</key> + <value>0</value> </param> <param> - <key>clock_source2</key> - <value></value> + <key>_coordinate</key> + <value>(214, 376)</value> </param> <param> - <key>time_source2</key> - <value></value> + <key>_rotation</key> + <value>0</value> </param> + </block> + <block> + <key>analog_random_source_x</key> <param> - <key>sd_spec2</key> - <value></value> + <key>id</key> + <value>analog_random_source_x_0</value> </param> <param> - <key>clock_source3</key> - <value></value> + <key>_enabled</key> + <value>True</value> </param> <param> - <key>time_source3</key> - <value></value> + <key>type</key> + <value>byte</value> </param> <param> - <key>sd_spec3</key> - <value></value> + <key>min</key> + <value>0</value> </param> <param> - <key>clock_source4</key> - <value></value> + <key>max</key> + <value>255</value> </param> <param> - <key>time_source4</key> - <value></value> + <key>num_samps</key> + <value>1000</value> </param> <param> - <key>sd_spec4</key> - <value></value> + <key>repeat</key> + <value>True</value> </param> <param> - <key>clock_source5</key> + <key>affinity</key> <value></value> </param> <param> - <key>time_source5</key> - <value></value> + <key>minoutbuf</key> + <value>0</value> </param> <param> - <key>sd_spec5</key> - <value></value> + <key>_coordinate</key> + <value>(13, 220)</value> </param> <param> - <key>clock_source6</key> - <value></value> + <key>_rotation</key> + <value>0</value> </param> + </block> + <block> + <key>blocks_tagged_stream_mux</key> <param> - <key>time_source6</key> - <value></value> + <key>id</key> + <value>blocks_tagged_stream_mux_0</value> </param> <param> - <key>sd_spec6</key> - <value></value> + <key>_enabled</key> + <value>True</value> </param> <param> - <key>clock_source7</key> - <value></value> + <key>type</key> + <value>complex</value> </param> <param> - <key>time_source7</key> - <value></value> + <key>ninputs</key> + <value>2</value> </param> <param> - <key>sd_spec7</key> - <value></value> + <key>lengthtagname</key> + <value>length_tag_key</value> </param> <param> - <key>nchan</key> + <key>vlen</key> <value>1</value> </param> <param> - <key>samp_rate</key> - <value>samp_rate</value> - </param> - <param> - <key>center_freq0</key> - <value>0</value> + <key>affinity</key> + <value></value> </param> <param> - <key>gain0</key> + <key>minoutbuf</key> <value>0</value> </param> <param> - <key>ant0</key> - <value></value> + <key>_coordinate</key> + <value>(510, 428)</value> </param> <param> - <key>bw0</key> + <key>_rotation</key> <value>0</value> </param> + </block> + <block> + <key>digital_ofdm_cyclic_prefixer</key> <param> - <key>center_freq1</key> - <value>0</value> + <key>id</key> + <value>digital_ofdm_cyclic_prefixer_0</value> </param> <param> - <key>gain1</key> - <value>0</value> + <key>_enabled</key> + <value>True</value> </param> <param> - <key>ant1</key> - <value></value> + <key>input_size</key> + <value>fft_len</value> </param> <param> - <key>bw1</key> - <value>0</value> + <key>cp_len</key> + <value>fft_len/4</value> </param> <param> - <key>center_freq2</key> - <value>0</value> + <key>rolloff</key> + <value>rolloff</value> </param> <param> - <key>gain2</key> - <value>0</value> + <key>tagname</key> + <value>length_tag_key</value> </param> <param> - <key>ant2</key> + <key>affinity</key> <value></value> </param> <param> - <key>bw2</key> + <key>minoutbuf</key> <value>0</value> </param> <param> - <key>center_freq3</key> - <value>0</value> + <key>_coordinate</key> + <value>(632, 564)</value> </param> <param> - <key>gain3</key> + <key>_rotation</key> <value>0</value> </param> + </block> + <block> + <key>blocks_tag_gate</key> <param> - <key>ant3</key> - <value></value> - </param> - <param> - <key>bw3</key> - <value>0</value> + <key>id</key> + <value>blocks_tag_gate_0</value> </param> <param> - <key>center_freq4</key> - <value>0</value> + <key>_enabled</key> + <value>True</value> </param> <param> - <key>gain4</key> - <value>0</value> + <key>type</key> + <value>complex</value> </param> <param> - <key>ant4</key> - <value></value> + <key>vlen</key> + <value>1</value> </param> <param> - <key>bw4</key> - <value>0</value> + <key>propagate_tags</key> + <value>False</value> </param> <param> - <key>center_freq5</key> - <value>0</value> + <key>affinity</key> + <value></value> </param> <param> - <key>gain5</key> + <key>minoutbuf</key> <value>0</value> </param> <param> - <key>ant5</key> - <value></value> + <key>_coordinate</key> + <value>(372, 747)</value> </param> <param> - <key>bw5</key> + <key>_rotation</key> <value>0</value> </param> + </block> + <block> + <key>blocks_repack_bits_bb</key> <param> - <key>center_freq6</key> - <value>0</value> + <key>id</key> + <value>blocks_repack_bits_bb_0</value> </param> <param> - <key>gain6</key> - <value>0</value> + <key>_enabled</key> + <value>True</value> </param> <param> - <key>ant6</key> - <value></value> + <key>k</key> + <value>8</value> </param> <param> - <key>bw6</key> - <value>0</value> + <key>l</key> + <value>payload_mod.bits_per_symbol()</value> </param> <param> - <key>center_freq7</key> - <value>0</value> + <key>len_tag_key</key> + <value>length_tag_key</value> </param> <param> - <key>gain7</key> - <value>0</value> + <key>align_output</key> + <value>False</value> </param> <param> - <key>ant7</key> + <key>affinity</key> <value></value> </param> <param> - <key>bw7</key> + <key>minoutbuf</key> <value>0</value> </param> <param> - <key>center_freq8</key> - <value>0</value> + <key>_coordinate</key> + <value>(710, 301)</value> </param> <param> - <key>gain8</key> + <key>_rotation</key> <value>0</value> </param> + </block> + <block> + <key>digital_packet_headergenerator_bb</key> <param> - <key>ant8</key> - <value></value> - </param> - <param> - <key>bw8</key> - <value>0</value> + <key>id</key> + <value>digital_packet_headergenerator_bb_0</value> </param> <param> - <key>center_freq9</key> - <value>0</value> + <key>_enabled</key> + <value>True</value> </param> <param> - <key>gain9</key> - <value>0</value> + <key>header_formatter</key> + <value>header_formatter.formatter()</value> </param> <param> - <key>ant9</key> + <key>affinity</key> <value></value> </param> <param> - <key>bw9</key> + <key>minoutbuf</key> <value>0</value> </param> <param> - <key>center_freq10</key> - <value>0</value> + <key>_coordinate</key> + <value>(703, 242)</value> </param> <param> - <key>gain10</key> + <key>_rotation</key> <value>0</value> </param> + </block> + <block> + <key>blocks_stream_to_tagged_stream</key> <param> - <key>ant10</key> - <value></value> + <key>id</key> + <value>blocks_stream_to_tagged_stream_0</value> </param> <param> - <key>bw10</key> - <value>0</value> + <key>_enabled</key> + <value>True</value> </param> <param> - <key>center_freq11</key> - <value>0</value> + <key>type</key> + <value>byte</value> </param> <param> - <key>gain11</key> - <value>0</value> + <key>vlen</key> + <value>1</value> </param> <param> - <key>ant11</key> - <value></value> + <key>packet_len</key> + <value>packet_len</value> </param> <param> - <key>bw11</key> - <value>0</value> + <key>len_tag_key</key> + <value>length_tag_key</value> </param> <param> - <key>center_freq12</key> - <value>0</value> + <key>affinity</key> + <value></value> </param> <param> - <key>gain12</key> + <key>minoutbuf</key> <value>0</value> </param> <param> - <key>ant12</key> - <value></value> + <key>_coordinate</key> + <value>(193, 235)</value> </param> <param> - <key>bw12</key> + <key>_rotation</key> <value>0</value> </param> + </block> + <block> + <key>virtual_sink</key> <param> - <key>center_freq13</key> - <value>0</value> + <key>id</key> + <value>header_bits</value> </param> <param> - <key>gain13</key> - <value>0</value> + <key>_enabled</key> + <value>True</value> </param> <param> - <key>ant13</key> - <value></value> + <key>stream_id</key> + <value>Header Bits</value> </param> <param> - <key>bw13</key> - <value>0</value> + <key>_coordinate</key> + <value>(936, 243)</value> </param> <param> - <key>center_freq14</key> + <key>_rotation</key> <value>0</value> </param> + </block> + <block> + <key>virtual_sink</key> <param> - <key>gain14</key> - <value>0</value> + <key>id</key> + <value>virtual_sink_0_0</value> </param> <param> - <key>ant14</key> - <value></value> + <key>_enabled</key> + <value>True</value> </param> <param> - <key>bw14</key> - <value>0</value> + <key>stream_id</key> + <value>Payload Bits</value> </param> <param> - <key>center_freq15</key> - <value>0</value> + <key>_coordinate</key> + <value>(934, 324)</value> </param> <param> - <key>gain15</key> + <key>_rotation</key> <value>0</value> </param> + </block> + <block> + <key>virtual_source</key> <param> - <key>ant15</key> - <value></value> + <key>id</key> + <value>virtual_source_0</value> </param> <param> - <key>bw15</key> - <value>0</value> + <key>_enabled</key> + <value>True</value> </param> <param> - <key>center_freq16</key> - <value>0</value> + <key>stream_id</key> + <value>Header Bits</value> </param> <param> - <key>gain16</key> - <value>0</value> + <key>_coordinate</key> + <value>(1, 382)</value> </param> <param> - <key>ant16</key> - <value></value> + <key>_rotation</key> + <value>0</value> </param> + </block> + <block> + <key>blocks_tag_debug</key> <param> - <key>bw16</key> - <value>0</value> + <key>id</key> + <value>blocks_tag_debug_0</value> </param> <param> - <key>center_freq17</key> - <value>0</value> + <key>_enabled</key> + <value>True</value> </param> <param> - <key>gain17</key> - <value>0</value> + <key>type</key> + <value>byte</value> </param> <param> - <key>ant17</key> - <value></value> + <key>name</key> + <value>Rx'd Packets</value> </param> <param> - <key>bw17</key> - <value>0</value> + <key>num_inputs</key> + <value>1</value> </param> <param> - <key>center_freq18</key> - <value>0</value> + <key>vlen</key> + <value>1</value> </param> <param> - <key>gain18</key> - <value>0</value> + <key>display</key> + <value>True</value> </param> <param> - <key>ant18</key> + <key>affinity</key> <value></value> </param> <param> - <key>bw18</key> - <value>0</value> + <key>_coordinate</key> + <value>(437, 872)</value> </param> <param> - <key>center_freq19</key> + <key>_rotation</key> <value>0</value> </param> + </block> + <block> + <key>blocks_throttle</key> <param> - <key>gain19</key> - <value>0</value> + <key>id</key> + <value>blocks_throttle_0</value> </param> <param> - <key>ant19</key> - <value></value> + <key>_enabled</key> + <value>True</value> </param> <param> - <key>bw19</key> - <value>0</value> + <key>type</key> + <value>complex</value> </param> <param> - <key>center_freq20</key> - <value>0</value> + <key>samples_per_second</key> + <value>samp_rate</value> </param> <param> - <key>gain20</key> - <value>0</value> + <key>vlen</key> + <value>1</value> </param> <param> - <key>ant20</key> + <key>affinity</key> <value></value> </param> <param> - <key>bw20</key> + <key>minoutbuf</key> <value>0</value> </param> <param> - <key>center_freq21</key> - <value>0</value> + <key>_coordinate</key> + <value>(558, 747)</value> </param> <param> - <key>gain21</key> + <key>_rotation</key> <value>0</value> </param> + </block> + <block> + <key>virtual_source</key> <param> - <key>ant21</key> - <value></value> - </param> - <param> - <key>bw21</key> - <value>0</value> + <key>id</key> + <value>virtual_source_1</value> </param> <param> - <key>center_freq22</key> - <value>0</value> + <key>_enabled</key> + <value>True</value> </param> <param> - <key>gain22</key> - <value>0</value> + <key>stream_id</key> + <value>Tx Signal</value> </param> <param> - <key>ant22</key> - <value></value> + <key>_coordinate</key> + <value>(5, 879)</value> </param> <param> - <key>bw22</key> + <key>_rotation</key> <value>0</value> </param> + </block> + <block> + <key>digital_crc32_bb</key> <param> - <key>center_freq23</key> - <value>0</value> + <key>id</key> + <value>digital_crc32_bb_0</value> </param> <param> - <key>gain23</key> - <value>0</value> + <key>_enabled</key> + <value>True</value> </param> <param> - <key>ant23</key> - <value></value> + <key>check</key> + <value>False</value> </param> <param> - <key>bw23</key> - <value>0</value> + <key>lengthtagname</key> + <value>length_tag_key</value> </param> <param> - <key>center_freq24</key> - <value>0</value> + <key>affinity</key> + <value></value> </param> <param> - <key>gain24</key> + <key>minoutbuf</key> <value>0</value> </param> <param> - <key>ant24</key> - <value></value> + <key>_coordinate</key> + <value>(430, 235)</value> </param> <param> - <key>bw24</key> + <key>_rotation</key> <value>0</value> </param> + </block> + <block> + <key>digital_ofdm_carrier_allocator_cvc</key> <param> - <key>center_freq25</key> - <value>0</value> + <key>id</key> + <value>digital_ofdm_carrier_allocator_cvc_0</value> </param> <param> - <key>gain25</key> - <value>0</value> + <key>_enabled</key> + <value>True</value> </param> <param> - <key>ant25</key> - <value></value> + <key>fft_len</key> + <value>fft_len</value> </param> <param> - <key>bw25</key> - <value>0</value> + <key>occupied_carriers</key> + <value>occupied_carriers</value> </param> <param> - <key>center_freq26</key> - <value>0</value> + <key>pilot_carriers</key> + <value>pilot_carriers</value> </param> <param> - <key>gain26</key> - <value>0</value> + <key>pilot_symbols</key> + <value>pilot_symbols</value> </param> <param> - <key>ant26</key> - <value></value> + <key>sync_words</key> + <value>(sync_word1, sync_word2)</value> </param> <param> - <key>bw26</key> - <value>0</value> + <key>len_tag_key</key> + <value>length_tag_key</value> </param> <param> - <key>center_freq27</key> - <value>0</value> + <key>affinity</key> + <value></value> </param> <param> - <key>gain27</key> + <key>minoutbuf</key> <value>0</value> </param> <param> - <key>ant27</key> - <value></value> + <key>_coordinate</key> + <value>(192, 540)</value> </param> <param> - <key>bw27</key> + <key>_rotation</key> <value>0</value> </param> + </block> + <block> + <key>digital_ofdm_rx</key> <param> - <key>center_freq28</key> - <value>0</value> + <key>id</key> + <value>digital_ofdm_rx_0</value> </param> <param> - <key>gain28</key> - <value>0</value> + <key>_enabled</key> + <value>True</value> </param> <param> - <key>ant28</key> - <value></value> + <key>fft_len</key> + <value>fft_len</value> </param> <param> - <key>bw28</key> - <value>0</value> + <key>cp_len</key> + <value>fft_len/4</value> </param> <param> - <key>center_freq29</key> - <value>0</value> + <key>packet_len_key</key> + <value>"length"</value> </param> <param> - <key>gain29</key> - <value>0</value> + <key>occupied_carriers</key> + <value>occupied_carriers</value> </param> <param> - <key>ant29</key> - <value></value> + <key>pilot_carriers</key> + <value>pilot_carriers</value> </param> <param> - <key>bw29</key> - <value>0</value> + <key>pilot_symbols</key> + <value>pilot_symbols</value> </param> <param> - <key>center_freq30</key> - <value>0</value> + <key>sync_word1</key> + <value>sync_word1</value> </param> <param> - <key>gain30</key> - <value>0</value> + <key>sync_word2</key> + <value>sync_word2</value> </param> <param> - <key>ant30</key> - <value></value> + <key>header_mod</key> + <value>"BPSK"</value> </param> <param> - <key>bw30</key> - <value>0</value> + <key>payload_mod</key> + <value>"QPSK"</value> </param> <param> - <key>center_freq31</key> - <value>0</value> + <key>scramble_bits</key> + <value>False</value> </param> <param> - <key>gain31</key> - <value>0</value> + <key>log</key> + <value>False</value> </param> <param> - <key>ant31</key> + <key>affinity</key> <value></value> </param> <param> - <key>bw31</key> + <key>minoutbuf</key> <value>0</value> </param> <param> <key>_coordinate</key> - <value>(401, 670)</value> + <value>(193, 802)</value> </param> <param> <key>_rotation</key> @@ -1467,7 +1355,7 @@ <key>virtual_sink</key> <param> <key>id</key> - <value>virtual_sink_0_0_0</value> + <value>virtual_sink_1</value> </param> <param> <key>_enabled</key> @@ -1475,11 +1363,11 @@ </param> <param> <key>stream_id</key> - <value>Pre-OFDM</value> + <value>Tx Signal</value> </param> <param> <key>_coordinate</key> - <value>(745, 441)</value> + <value>(771, 698)</value> </param> <param> <key>_rotation</key> @@ -1487,10 +1375,10 @@ </param> </block> <block> - <key>blocks_vector_source_x</key> + <key>wxgui_scopesink2</key> <param> <key>id</key> - <value>blocks_vector_source_x_0</value> + <value>wxgui_scopesink2_0</value> </param> <param> <key>_enabled</key> @@ -1498,105 +1386,67 @@ </param> <param> <key>type</key> - <value>byte</value> - </param> - <param> - <key>vector</key> - <value>range(packet_len)</value> - </param> - <param> - <key>tags</key> - <value>tagged_streams.make_lengthtags((packet_len,), (0,), length_tag_name)</value> - </param> - <param> - <key>repeat</key> - <value>True</value> + <value>complex</value> </param> <param> - <key>vlen</key> - <value>1</value> + <key>title</key> + <value>Scope Plot</value> </param> <param> - <key>_coordinate</key> - <value>(0, 215)</value> + <key>samp_rate</key> + <value>samp_rate</value> </param> <param> - <key>_rotation</key> + <key>v_scale</key> <value>0</value> </param> - </block> - <block> - <key>digital_chunks_to_symbols_xx</key> <param> - <key>id</key> - <value>digital_chunks_to_symbols_xx_0_0</value> - </param> - <param> - <key>_enabled</key> - <value>True</value> - </param> - <param> - <key>in_type</key> - <value>byte</value> + <key>v_offset</key> + <value>0</value> </param> <param> - <key>out_type</key> - <value>complex</value> + <key>t_scale</key> + <value>0</value> </param> <param> - <key>symbol_table</key> - <value>payload_mod.points()</value> + <key>ac_couple</key> + <value>False</value> </param> <param> - <key>dimension</key> - <value>1</value> + <key>xy_mode</key> + <value>False</value> </param> <param> - <key>num_ports</key> + <key>num_inputs</key> <value>1</value> </param> <param> - <key>_coordinate</key> - <value>(212, 450)</value> - </param> - <param> - <key>_rotation</key> - <value>0</value> - </param> - </block> - <block> - <key>digital_chunks_to_symbols_xx</key> - <param> - <key>id</key> - <value>digital_chunks_to_symbols_xx_0</value> - </param> - <param> - <key>_enabled</key> - <value>True</value> + <key>win_size</key> + <value></value> </param> <param> - <key>in_type</key> - <value>byte</value> + <key>grid_pos</key> + <value></value> </param> <param> - <key>out_type</key> - <value>complex</value> + <key>notebook</key> + <value></value> </param> <param> - <key>symbol_table</key> - <value>header_mod.points()</value> + <key>trig_mode</key> + <value>wxgui.TRIG_MODE_AUTO</value> </param> <param> - <key>dimension</key> - <value>1</value> + <key>y_axis_label</key> + <value>Counts</value> </param> <param> - <key>num_ports</key> - <value>1</value> + <key>affinity</key> + <value></value> </param> <param> <key>_coordinate</key> - <value>(214, 376)</value> + <value>(773, 768)</value> </param> <param> <key>_rotation</key> @@ -1686,175 +1536,12 @@ <value>None</value> </param> <param> - <key>_coordinate</key> - <value>(402, 796)</value> - </param> - <param> - <key>_rotation</key> - <value>0</value> - </param> - </block> - <block> - <key>virtual_source</key> - <param> - <key>id</key> - <value>virtual_source_0_0_0</value> - </param> - <param> - <key>_enabled</key> - <value>True</value> - </param> - <param> - <key>stream_id</key> - <value>Pre-OFDM</value> - </param> - <param> - <key>_coordinate</key> - <value>(0, 578)</value> - </param> - <param> - <key>_rotation</key> - <value>0</value> - </param> - </block> - <block> - <key>digital_ofdm_carrier_allocator_cvc</key> - <param> - <key>id</key> - <value>digital_ofdm_carrier_allocator_cvc_0</value> - </param> - <param> - <key>_enabled</key> - <value>True</value> - </param> - <param> - <key>fft_len</key> - <value>fft_len</value> - </param> - <param> - <key>occupied_carriers</key> - <value>occupied_carriers</value> - </param> - <param> - <key>pilot_carriers</key> - <value>pilot_carriers</value> - </param> - <param> - <key>pilot_symbols</key> - <value>pilot_symbols</value> - </param> - <param> - <key>sync_words</key> - <value>(sync_word1, sync_word2)</value> - </param> - <param> - <key>len_tag_key</key> - <value>length_tag_name</value> - </param> - <param> - <key>_coordinate</key> - <value>(191, 540)</value> - </param> - <param> - <key>_rotation</key> - <value>0</value> - </param> - </block> - <block> - <key>digital_ofdm_cyclic_prefixer</key> - <param> - <key>id</key> - <value>digital_ofdm_cyclic_prefixer_0</value> - </param> - <param> - <key>_enabled</key> - <value>True</value> - </param> - <param> - <key>input_size</key> - <value>fft_len</value> - </param> - <param> - <key>cp_len</key> - <value>fft_len/4</value> - </param> - <param> - <key>rolloff</key> - <value>rolloff</value> - </param> - <param> - <key>tagname</key> - <value>length_tag_name</value> - </param> - <param> - <key>_coordinate</key> - <value>(631, 563)</value> - </param> - <param> - <key>_rotation</key> - <value>0</value> - </param> - </block> - <block> - <key>virtual_sink</key> - <param> - <key>id</key> - <value>virtual_sink_0</value> - </param> - <param> - <key>_enabled</key> - <value>True</value> - </param> - <param> - <key>stream_id</key> - <value>Time Domain</value> - </param> - <param> - <key>_coordinate</key> - <value>(855, 578)</value> - </param> - <param> - <key>_rotation</key> - <value>0</value> - </param> - </block> - <block> - <key>fft_vxx</key> - <param> - <key>id</key> - <value>fft_vxx_0</value> - </param> - <param> - <key>_enabled</key> - <value>True</value> - </param> - <param> - <key>type</key> - <value>complex</value> - </param> - <param> - <key>fft_size</key> - <value>fft_len</value> - </param> - <param> - <key>forward</key> - <value>False</value> - </param> - <param> - <key>window</key> - <value>()</value> - </param> - <param> - <key>shift</key> - <value>True</value> - </param> - <param> - <key>nthreads</key> - <value>1</value> + <key>affinity</key> + <value></value> </param> <param> <key>_coordinate</key> - <value>(414, 548)</value> + <value>(775, 862)</value> </param> <param> <key>_rotation</key> @@ -1880,40 +1567,52 @@ <sink_key>0</sink_key> </connection> <connection> - <source_block_id>digital_crc32_bb_0</source_block_id> - <sink_block_id>digital_packet_headergenerator_bb_0</sink_block_id> + <source_block_id>digital_chunks_to_symbols_xx_0_0</source_block_id> + <sink_block_id>blocks_tagged_stream_mux_0</sink_block_id> + <source_key>0</source_key> + <sink_key>1</sink_key> + </connection> + <connection> + <source_block_id>virtual_source_0_0_0_0</source_block_id> + <sink_block_id>blocks_multiply_const_vxx_0</sink_block_id> <source_key>0</source_key> <sink_key>0</sink_key> </connection> <connection> - <source_block_id>digital_crc32_bb_0</source_block_id> - <sink_block_id>blocks_repack_bits_bb_0</sink_block_id> + <source_block_id>virtual_source_0_0_0</source_block_id> + <sink_block_id>digital_ofdm_carrier_allocator_cvc_0</sink_block_id> <source_key>0</source_key> <sink_key>0</sink_key> </connection> <connection> - <source_block_id>digital_packet_headergenerator_bb_0</source_block_id> - <sink_block_id>header_bits</sink_block_id> + <source_block_id>digital_ofdm_carrier_allocator_cvc_0</source_block_id> + <sink_block_id>fft_vxx_0</sink_block_id> <source_key>0</source_key> <sink_key>0</sink_key> </connection> <connection> - <source_block_id>blocks_repack_bits_bb_0</source_block_id> - <sink_block_id>virtual_sink_0_0</sink_block_id> + <source_block_id>fft_vxx_0</source_block_id> + <sink_block_id>digital_ofdm_cyclic_prefixer_0</sink_block_id> <source_key>0</source_key> <sink_key>0</sink_key> </connection> <connection> - <source_block_id>blocks_vector_source_x_0</source_block_id> - <sink_block_id>digital_crc32_bb_0</sink_block_id> + <source_block_id>digital_ofdm_cyclic_prefixer_0</source_block_id> + <sink_block_id>virtual_sink_0</sink_block_id> <source_key>0</source_key> <sink_key>0</sink_key> </connection> <connection> - <source_block_id>digital_chunks_to_symbols_xx_0_0</source_block_id> - <sink_block_id>blocks_tagged_stream_mux_0</sink_block_id> + <source_block_id>blocks_multiply_const_vxx_0</source_block_id> + <sink_block_id>blocks_tag_gate_0</sink_block_id> <source_key>0</source_key> - <sink_key>1</sink_key> + <sink_key>0</sink_key> + </connection> + <connection> + <source_block_id>blocks_tag_gate_0</source_block_id> + <sink_block_id>blocks_throttle_0</sink_block_id> + <source_key>0</source_key> + <sink_key>0</sink_key> </connection> <connection> <source_block_id>digital_chunks_to_symbols_xx_0</source_block_id> @@ -1922,8 +1621,8 @@ <sink_key>0</sink_key> </connection> <connection> - <source_block_id>virtual_source_0_0_0_0</source_block_id> - <sink_block_id>blocks_multiply_const_vxx_0</sink_block_id> + <source_block_id>analog_random_source_x_0</source_block_id> + <sink_block_id>blocks_stream_to_tagged_stream_0</sink_block_id> <source_key>0</source_key> <sink_key>0</sink_key> </connection> @@ -1934,44 +1633,56 @@ <sink_key>0</sink_key> </connection> <connection> - <source_block_id>blocks_multiply_const_vxx_0</source_block_id> - <sink_block_id>blocks_throttle_0</sink_block_id> + <source_block_id>blocks_throttle_0</source_block_id> + <sink_block_id>wxgui_fftsink2_0</sink_block_id> <source_key>0</source_key> <sink_key>0</sink_key> </connection> <connection> - <source_block_id>blocks_multiply_const_vxx_0</source_block_id> - <sink_block_id>wxgui_fftsink2_0</sink_block_id> + <source_block_id>blocks_stream_to_tagged_stream_0</source_block_id> + <sink_block_id>digital_crc32_bb_0</sink_block_id> <source_key>0</source_key> <sink_key>0</sink_key> </connection> <connection> - <source_block_id>blocks_multiply_const_vxx_0</source_block_id> - <sink_block_id>uhd_usrp_sink_0</sink_block_id> + <source_block_id>digital_crc32_bb_0</source_block_id> + <sink_block_id>digital_packet_headergenerator_bb_0</sink_block_id> <source_key>0</source_key> <sink_key>0</sink_key> </connection> <connection> - <source_block_id>virtual_source_0_0_0</source_block_id> - <sink_block_id>digital_ofdm_carrier_allocator_cvc_0</sink_block_id> + <source_block_id>digital_crc32_bb_0</source_block_id> + <sink_block_id>blocks_repack_bits_bb_0</sink_block_id> <source_key>0</source_key> <sink_key>0</sink_key> </connection> <connection> - <source_block_id>digital_ofdm_carrier_allocator_cvc_0</source_block_id> - <sink_block_id>fft_vxx_0</sink_block_id> + <source_block_id>digital_packet_headergenerator_bb_0</source_block_id> + <sink_block_id>header_bits</sink_block_id> <source_key>0</source_key> <sink_key>0</sink_key> </connection> <connection> - <source_block_id>fft_vxx_0</source_block_id> - <sink_block_id>digital_ofdm_cyclic_prefixer_0</sink_block_id> + <source_block_id>blocks_repack_bits_bb_0</source_block_id> + <sink_block_id>virtual_sink_0_0</sink_block_id> <source_key>0</source_key> <sink_key>0</sink_key> </connection> <connection> - <source_block_id>digital_ofdm_cyclic_prefixer_0</source_block_id> - <sink_block_id>virtual_sink_0</sink_block_id> + <source_block_id>digital_ofdm_rx_0</source_block_id> + <sink_block_id>blocks_tag_debug_0</sink_block_id> + <source_key>0</source_key> + <sink_key>0</sink_key> + </connection> + <connection> + <source_block_id>virtual_source_1</source_block_id> + <sink_block_id>digital_ofdm_rx_0</sink_block_id> + <source_key>0</source_key> + <sink_key>0</sink_key> + </connection> + <connection> + <source_block_id>blocks_throttle_0</source_block_id> + <sink_block_id>virtual_sink_1</sink_block_id> <source_key>0</source_key> <sink_key>0</sink_key> </connection> diff --git a/gr-digital/grc/digital_block_tree.xml b/gr-digital/grc/digital_block_tree.xml index d1033e8572..a5fba4ff4d 100644 --- a/gr-digital/grc/digital_block_tree.xml +++ b/gr-digital/grc/digital_block_tree.xml @@ -59,7 +59,10 @@ <block>digital_psk_demod</block> <block>digital_qam_mod</block> <block>digital_qam_demod</block> + <block>digital_constellation_modulator</block> <block>digital_constellation_receiver_cb</block> + <block>variable_constellation</block> + <block>variable_constellation_rect</block> </cat> <cat> <name>Packet Operators</name> @@ -101,6 +104,7 @@ <block>digital_chunks_to_symbols_xx</block> <block>digital_constellation_decoder_cb</block> <block>digital_constellation_receiver_cb</block> + <block>digital_constellation_soft_decoder_cf</block> <block>digital_diff_decoder_bb</block> <block>digital_diff_encoder_bb</block> <block>digital_diff_phasor_cc</block> diff --git a/grc/blocks/variable_constellation.xml b/gr-digital/grc/digital_constellation.xml index 7d23ede9be..8d2a34f1fa 100644 --- a/grc/blocks/variable_constellation.xml +++ b/gr-digital/grc/digital_constellation.xml @@ -11,7 +11,13 @@ <key>variable_constellation</key> <category>Modulators</category> <import>from gnuradio import digital</import> - <var_make>self.$(id) = $(id) = digital.constellation_calcdist($const_points, $sym_map, $rot_sym, $dims).base()</var_make> + <var_make>self.$(id) = $(id) = digital.constellation_calcdist($const_points, $sym_map, $rot_sym, $dims).base() +#if str($soft_dec_lut).lower() == '"auto"' or str($soft_dec_lut).lower() == "'auto'" +self.$(id).gen_soft_dec_lut($precision) +#else if str($soft_dec_lut) != 'None' +self.$(id).set_soft_dec_lut($soft_dec_lut, $precision) +#end if +</var_make> <make></make> <!--<callback></callback>--> @@ -48,4 +54,18 @@ <value>1</value> <type>int</type> </param> + <param> + <name>Soft Decisions Precision</name> + <key>precision</key> + <value>8</value> + <type>int</type> + <hide>part</hide> + </param> + <param> + <name>Soft Decisions LUT</name> + <key>soft_dec_lut</key> + <value>None</value> + <type>raw</type> + <hide>#if str($soft_dec_lut) == 'None' then 'part' else 'none'#</hide> + </param> </block> diff --git a/gr-digital/grc/digital_constellation_modulator.xml b/gr-digital/grc/digital_constellation_modulator.xml new file mode 100644 index 0000000000..7b7ce24e47 --- /dev/null +++ b/gr-digital/grc/digital_constellation_modulator.xml @@ -0,0 +1,111 @@ +<?xml version="1.0"?> + +<!-- + Copyright 2013 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. +--> + +<!-- +################################################### +## Modulates any given constellation object +################################################### + --> +<block> + <name>Constellation Modulator</name> + <key>digital_constellation_modulator</key> + <import>from gnuradio import digital</import> + <make>digital.generic_mod( + constellation=$constellation, + differential=$differential, + samples_per_symbol=$samples_per_symbol, + pre_diff_code=True, + excess_bw=$excess_bw, + verbose=$verbose, + log=$log, + )</make> + <param> + <name>Constellation</name> + <key>constellation</key> + <type>raw</type> + </param> + <param> + <name>Differential Encoding</name> + <key>differential</key> + <value>True</value> + <type>bool</type> + <option> + <name>Yes</name> + <key>True</key> + </option> + <option> + <name>No</name> + <key>False</key> + </option> + </param> + <param> + <name>Samples/Symbol</name> + <key>samples_per_symbol</key> + <value>2</value> + <type>int</type> + </param> + <param> + <name>Excess BW</name> + <key>excess_bw</key> + <value>0.35</value> + <type>real</type> + </param> + <param> + <name>Verbose</name> + <key>verbose</key> + <value>False</value> + <type>bool</type> + <hide>#if str($verbose) == 'False' then 'part' else 'none'#</hide> + <option> + <name>On</name> + <key>True</key> + </option> + <option> + <name>Off</name> + <key>False</key> + </option> + </param> + <param> + <name>Logging</name> + <key>log</key> + <value>False</value> + <type>bool</type> + <hide>#if str($log) == 'False' then 'part' else 'none'#</hide> + <option> + <name>On</name> + <key>True</key> + </option> + <option> + <name>Off</name> + <key>False</key> + </option> + </param> + <sink> + <name>in</name> + <type>byte</type> + </sink> + <source> + <name>out</name> + <type>complex</type> + </source> +</block> diff --git a/grc/blocks/variable_constellation_rect.xml b/gr-digital/grc/digital_constellation_rect.xml index 5c136ee324..e6acc14bc4 100644 --- a/grc/blocks/variable_constellation_rect.xml +++ b/gr-digital/grc/digital_constellation_rect.xml @@ -11,9 +11,13 @@ <key>variable_constellation_rect</key> <category>Modulators</category> <import>from gnuradio import digital</import> - <var_make>self.$(id) = $(id) = digital.constellation_rect($const_points, $sym_map, $rot_sym, $real_sect, $imag_sect, $w_real_sect, $w_imag_sect).base()</var_make> + <var_make>self.$(id) = $(id) = digital.constellation_rect($const_points, $sym_map, $rot_sym, $real_sect, $imag_sect, $w_real_sect, $w_imag_sect).base() +#if str($softbits_lut) != 'None' +self.$(id).set_softbits($softbits_lut, $precision) +#end if +</var_make> <make></make> - <!--<callback></callback>--> + <!--<callback>set_softbits($softbits_lut, $precision)</callback>--> <!-- Required to 'trick' GRC into using this as a proper variable--> <param> @@ -66,4 +70,18 @@ <value>1</value> <type>int</type> </param> + <param> + <name>Soft bits precision</name> + <key>precision</key> + <value>8</value> + <type>int</type> + <hide>part</hide> + </param> + <param> + <name>Soft bits LUT</name> + <key>softbits_lut</key> + <value>None</value> + <type>raw</type> + <hide>#if str($softbits_lut) == 'None' then 'part' else 'none'#</hide> + </param> </block> diff --git a/gr-digital/grc/digital_constellation_soft_decoder_cf.xml b/gr-digital/grc/digital_constellation_soft_decoder_cf.xml new file mode 100644 index 0000000000..6b0995acc9 --- /dev/null +++ b/gr-digital/grc/digital_constellation_soft_decoder_cf.xml @@ -0,0 +1,25 @@ +<?xml version="1.0"?> +<!-- +################################################### +##Constellation Decoder, soft bits out +################################################### + --> +<block> + <name>Constellation Soft Decoder</name> + <key>digital_constellation_soft_decoder_cf</key> + <import>from gnuradio import digital</import> + <make>digital.constellation_soft_decoder_cf($constellation)</make> + <param> + <name>Constellation Object</name> + <key>constellation</key> + <type>raw</type> + </param> + <sink> + <name>in</name> + <type>complex</type> + </sink> + <source> + <name>out</name> + <type>float</type> + </source> +</block> diff --git a/gr-digital/grc/digital_ofdm_rx.xml b/gr-digital/grc/digital_ofdm_rx.xml index 6f10a2e944..9c2bf65e9d 100644 --- a/gr-digital/grc/digital_ofdm_rx.xml +++ b/gr-digital/grc/digital_ofdm_rx.xml @@ -24,7 +24,8 @@ #end if bps_header=$header_mod.bps, bps_payload=$payload_mod.bps, - debug_log=$log + debug_log=$log, + scramble_bits=$scramble_bits )</make> <param> <name>FFT Length</name> @@ -145,6 +146,21 @@ </option> </param> <param> + <name>Scramble Bits</name> + <key>scramble_bits</key> + <value>False</value> + <type>enum</type> + <hide> #if $scramble_bits then 'part' else 'none'#</hide> + <option> + <name>No</name> + <key>False</key> + </option> + <option> + <name>Yes</name> + <key>True</key> + </option> + </param> + <param> <name>Log Debug Info</name> <key>log</key> <value>False</value> diff --git a/gr-digital/grc/digital_ofdm_tx.xml b/gr-digital/grc/digital_ofdm_tx.xml index cde045d840..bad0b2b13d 100644 --- a/gr-digital/grc/digital_ofdm_tx.xml +++ b/gr-digital/grc/digital_ofdm_tx.xml @@ -24,7 +24,8 @@ bps_header=$header_mod.bps, bps_payload=$payload_mod.bps, rolloff=$rolloff, - debug_log=$log + debug_log=$log, + scramble_bits=$scramble_bits )</make> <param> <name>FFT Length</name> @@ -151,6 +152,21 @@ <type>int</type> </param> <param> + <name>Scramble Bits</name> + <key>scramble_bits</key> + <value>False</value> + <type>enum</type> + <hide> #if $scramble_bits then 'part' else 'none'#</hide> + <option> + <name>No</name> + <key>False</key> + </option> + <option> + <name>Yes</name> + <key>True</key> + </option> + </param> + <param> <name>Log Debug Info</name> <key>log</key> <value>False</value> diff --git a/gr-digital/include/gnuradio/digital/CMakeLists.txt b/gr-digital/include/gnuradio/digital/CMakeLists.txt index 275da16d87..7515df7042 100644 --- a/gr-digital/include/gnuradio/digital/CMakeLists.txt +++ b/gr-digital/include/gnuradio/digital/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright 2011,2012 Free Software Foundation, Inc. +# Copyright 2011-2013 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -84,6 +84,7 @@ install(FILES constellation.h constellation_decoder_cb.h constellation_receiver_cb.h + constellation_soft_decoder_cf.h correlate_access_code_bb.h correlate_access_code_tag_bb.h costas_loop_cc.h diff --git a/gr-digital/include/gnuradio/digital/additive_scrambler_bb.h b/gr-digital/include/gnuradio/digital/additive_scrambler_bb.h index 73fd395d67..ac765121a8 100644 --- a/gr-digital/include/gnuradio/digital/additive_scrambler_bb.h +++ b/gr-digital/include/gnuradio/digital/additive_scrambler_bb.h @@ -36,14 +36,19 @@ namespace gr { * Scramble an input stream using an LFSR. * * \details - * This block works on the LSB only of the input data stream, - * i.e., on an "unpacked binary" stream, and produces the same - * format on its output. + * This block scrambles up to 8 bits per byte of the input + * data stream, starting at the LSB. * * The scrambler works by XORing the incoming bit stream by the * output of the LFSR. Optionally, after 'count' bits have been * processed, the shift register is reset to the seed value. * This allows processing fixed length vectors of samples. + * + * Alternatively, the LFSR can be reset using a reset tag to + * scramble variable length vectors. However, it cannot be reset + * between bytes. + * + * For details on configuring the LFSR, see gr::digital::lfsr. */ class DIGITAL_API additive_scrambler_bb : virtual public sync_block { @@ -57,15 +62,17 @@ namespace gr { * \param mask Polynomial mask for LFSR * \param seed Initial shift register contents * \param len Shift register length - * \param count Number of bits after which shift register is reset, 0=never - * + * \param count Number of bytes after which shift register is reset, 0=never + * \param bits_per_byte Number of bits per byte + * \param reset_tag_key When a tag with this key is detected, the shift register is reset (when this is set, count is ignored!) */ - static sptr make(int mask, int seed, int len, int count=0); + static sptr make(int mask, int seed, int len, int count=0, int bits_per_byte=1, const std::string &reset_tag_key=""); virtual int mask() const = 0; virtual int seed() const = 0; virtual int len() const = 0; virtual int count() const = 0; + virtual int bits_per_byte() = 0; }; } /* namespace digital */ diff --git a/gr-digital/include/gnuradio/digital/constellation.h b/gr-digital/include/gnuradio/digital/constellation.h index 6ee274dd04..b2464aa856 100644 --- a/gr-digital/include/gnuradio/digital/constellation.h +++ b/gr-digital/include/gnuradio/digital/constellation.h @@ -120,6 +120,76 @@ namespace gr { return shared_from_this(); } + /*! \brief Generates the soft decision LUT based on + * constellation and symbol map. + * + * \details Generates the soft decision LUT based on + * constellation and symbol map. It can be given a estimate of + * the noise power in the channel as \p npwr. + * + * \param precision Number of bits of precision on each axis. + * \param npwr Estimate of the noise power (if known). + * + * This is expensive to compute. + */ + void gen_soft_dec_lut(int precision, float npwr=1.0); + + /*! \brief Calculate soft decisions for the given \p sample. + * + * \details Calculate the soft decisions from the given \p sample + * at the given noise power \p npwr. + * + * This is a very costly algorithm (especially for higher order + * modulations) and should be used sparingly. It uses the + * gen_soft_dec_lut function to generate the LUT, which + * should be done once or if a large change in the noise floor + * is detected. + * + * Instead of using this function, generate the LUT using the + * gen_soft_dec_lut after creating the constellation object + * and then use the soft_decision_maker function to return the + * answer from the LUT. + * + * \param sample The complex sample to get the soft decisions. + * \param npwr Estimate of the noise power (if known). + */ + virtual std::vector<float> calc_soft_dec(gr_complex sample, float npwr=1.0); + + /*! \brief Define a soft decision look-up table. + * + * \details Define a soft decision look-up table (LUT). Because + * soft decisions can be calculated in various ways with various + * levels of accuracy and complexity, this function allows + * users to create a LUT in their own way. + * + * Setting the LUT here means that has_soft_dec_lut will return + * true. Decision vectors returned by soft_decision_maker will + * be calculated using this LUT. + * + * \param soft_dec_lut The soft decision LUT as a vector of + * tuples (vectors in C++) of soft decisions. Each + * element of the LUT is a vector of k-bit floats (where + * there are k bits/sample in the constellation). + * \param precision The number of bits of precision used when + * generating the LUT. + */ + void set_soft_dec_lut(const std::vector< std::vector<float> > &soft_dec_lut, + int precision); + + //! Returns True if the soft decision LUT has been defined, False otherwise. + bool has_soft_dec_lut(); + + /*! \brief Returns the soft decisions for the given \p sample. + * + * \details Returns the soft decisions for the given \p + * sample. If a LUT is defined for the object, the decisions + * will be calculated from there. Otherwise, this function will + * call calc_soft_dec directly to calculate the soft decisions. + * + * \param sample The complex sample to get the soft decisions. + */ + std::vector<float> soft_decision_maker(gr_complex sample); + protected: std::vector<gr_complex> d_constellation; std::vector<int> d_pre_diff_code; @@ -130,10 +200,17 @@ namespace gr { //! The factor by which the user given constellation points were //! scaled by to achieve an average amplitude of 1. float d_scalefactor; + float d_re_min, d_re_max, d_im_min, d_im_max; + + std::vector< std::vector<float> > d_soft_dec_lut; + int d_lut_precision; + float d_lut_scale; float get_distance(unsigned int index, const gr_complex *sample); unsigned int get_closest_point(const gr_complex *sample); void calc_arity(); + + void max_min_axes(); }; /************************************************************/ @@ -418,6 +495,10 @@ namespace gr { /*! * \brief Digital constellation for QPSK * \ingroup digital + * + * 01 | 11 + * ------- + * 00 | 10 */ class DIGITAL_API constellation_qpsk : public constellation { @@ -446,6 +527,10 @@ namespace gr { /*! * \brief Digital constellation for DQPSK * \ingroup digital + * + * 01 | 00 + * ------- + * 11 | 10 */ class DIGITAL_API constellation_dqpsk : public constellation { @@ -474,6 +559,12 @@ namespace gr { /*! * \brief Digital constellation for 8PSK * \ingroup digital + * + * 101 | 100 + * 001 | 000 + * ----------------- + * 011 | 010 + * 111 | 110 */ class DIGITAL_API constellation_8psk : public constellation { diff --git a/gr-digital/include/gnuradio/digital/constellation_soft_decoder_cf.h b/gr-digital/include/gnuradio/digital/constellation_soft_decoder_cf.h new file mode 100644 index 0000000000..433be3a8f9 --- /dev/null +++ b/gr-digital/include/gnuradio/digital/constellation_soft_decoder_cf.h @@ -0,0 +1,62 @@ +/* -*- c++ -*- */ +/* + * Copyright 2013 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_DIGITAL_CONSTELLATION_SOFT_DECODER_CF_H +#define INCLUDED_DIGITAL_CONSTELLATION_SOFT_DECODER_CF_H + +#include <gnuradio/digital/api.h> +#include <gnuradio/digital/constellation.h> +#include <gnuradio/sync_interpolator.h> + +namespace gr { + namespace digital { + + /*! + * \brief Constellation Decoder + * \ingroup symbol_coding_blk + * + * \details + * Decode a constellation's points from a complex space to soft + * bits based on the map and soft decision lUT of the \p + * consetllation object. + */ + class DIGITAL_API constellation_soft_decoder_cf + : virtual public sync_interpolator + { + public: + // gr::digital::constellation_soft_decoder_cf::sptr + typedef boost::shared_ptr<constellation_soft_decoder_cf> sptr; + + /*! + * \brief Make constellation decoder block. + * + * \param constellation A constellation derived from class + * 'constellation'. Use base() method to get a shared pointer to + * this base class type. + */ + static sptr make(constellation_sptr constellation); + }; + + } /* namespace digital */ +} /* namespace gr */ + +#endif /* INCLUDED_DIGITAL_CONSTELLATION_SOFT_DECODER_CF_H */ diff --git a/gr-digital/include/gnuradio/digital/packet_header_default.h b/gr-digital/include/gnuradio/digital/packet_header_default.h index 0654a32a63..6567dd7626 100644 --- a/gr-digital/include/gnuradio/digital/packet_header_default.h +++ b/gr-digital/include/gnuradio/digital/packet_header_default.h @@ -25,6 +25,7 @@ #include <gnuradio/tags.h> #include <gnuradio/digital/api.h> #include <boost/enable_shared_from_this.hpp> +#include <boost/crc.hpp> namespace gr { namespace digital { @@ -69,12 +70,15 @@ namespace gr { * * Uses the following header format: * Bits 0-11: The packet length (what was stored in the tag with key \p len_tag_key) - * Bits 12-27: The header number (counts up everytime this function is called) - * Bit 28: Even parity bit + * Bits 12-23: The header number (counts up everytime this function is called) + * Bit 24-31: 8-Bit CRC * All other bits: Are set to zero * - * If the header length is smaller than 29, bits are simply left out. For this + * If the header length is smaller than 32, bits are simply left out. For this * reason, they always start with the LSB. + * + * However, it is recommended to stay above 32 Bits, in order to have a working + * CRC. */ virtual bool header_formatter( long packet_len, @@ -104,6 +108,7 @@ namespace gr { int d_bits_per_byte; unsigned d_header_number; unsigned d_mask; + boost::crc_optimal<8, 0x07, 0xFF, 0x00, false, false> d_crc_impl; }; } // namespace digital diff --git a/gr-digital/include/gnuradio/digital/packet_header_ofdm.h b/gr-digital/include/gnuradio/digital/packet_header_ofdm.h index 4603450915..40255daf6d 100644 --- a/gr-digital/include/gnuradio/digital/packet_header_ofdm.h +++ b/gr-digital/include/gnuradio/digital/packet_header_ofdm.h @@ -45,17 +45,31 @@ namespace gr { const std::string &frame_len_tag_key, const std::string &num_tag_key, int bits_per_header_sym, - int bits_per_payload_sym); + int bits_per_payload_sym, + bool scramble_header); ~packet_header_ofdm(); /*! + * \brief Header formatter. + * + * Does the same as packet_header_default::header_formatter(), but + * optionally scrambles the bits (this is more important for OFDM to avoid + * PAPR spikes). + */ + bool header_formatter( + long packet_len, + unsigned char *out, + const std::vector<tag_t> &tags + ); + + /*! * \brief Inverse function to header_formatter(). * * Does the same as packet_header_default::header_parser(), but * adds another tag that stores the number of OFDM symbols in the * packet. * Note that there is usually no linear connection between the number - * of OFDM symbols and the packet length, because, a packet might + * of OFDM symbols and the packet length because a packet might * finish mid-OFDM-symbol. */ bool header_parser( @@ -77,6 +91,8 @@ namespace gr { * required to figure out how many OFDM symbols * are necessary to encode the given number of * bytes. + * \param scramble_header Set this to true to scramble the bits. This is highly + * recommended, as it reduces PAPR spikes. */ static sptr make( const std::vector<std::vector<int> > &occupied_carriers, @@ -85,15 +101,17 @@ namespace gr { const std::string &frame_len_tag_key="frame_len", const std::string &num_tag_key="packet_num", int bits_per_header_sym=1, - int bits_per_payload_sym=1 + int bits_per_payload_sym=1, + bool scramble_header=false ); protected: - pmt::pmt_t d_frame_len_tag_key; + pmt::pmt_t d_frame_len_tag_key; //!< Tag key of the additional frame length tag const std::vector<std::vector<int> > d_occupied_carriers; //!< Which carriers/symbols carry data int d_syms_per_set; //!< Helper variable: Total number of elements in d_occupied_carriers int d_bits_per_payload_sym; + std::vector<unsigned char> d_scramble_mask; //!< Bits are xor'd with this before tx'ing }; } // namespace digital diff --git a/gr-digital/lib/CMakeLists.txt b/gr-digital/lib/CMakeLists.txt index a17c91a85a..dee52308ca 100644 --- a/gr-digital/lib/CMakeLists.txt +++ b/gr-digital/lib/CMakeLists.txt @@ -120,6 +120,7 @@ list(APPEND digital_sources constellation.cc constellation_decoder_cb_impl.cc constellation_receiver_cb_impl.cc + constellation_soft_decoder_cf_impl.cc correlate_access_code_bb_impl.cc correlate_access_code_tag_bb_impl.cc costas_loop_cc_impl.cc diff --git a/gr-digital/lib/additive_scrambler_bb_impl.cc b/gr-digital/lib/additive_scrambler_bb_impl.cc index 8f2229e6b6..96e1fbbc25 100644 --- a/gr-digital/lib/additive_scrambler_bb_impl.cc +++ b/gr-digital/lib/additive_scrambler_bb_impl.cc @@ -31,23 +31,35 @@ namespace gr { namespace digital { additive_scrambler_bb::sptr - additive_scrambler_bb::make(int mask, int seed, int len, int count) + additive_scrambler_bb::make (int mask, int seed, + int len, int count, + int bits_per_byte, + const std::string &reset_tag_key) { return gnuradio::get_initial_sptr(new additive_scrambler_bb_impl - (mask, seed, len, count)); + (mask, seed, len, count, bits_per_byte, reset_tag_key)); } additive_scrambler_bb_impl::additive_scrambler_bb_impl(int mask, int seed, int len, - int count) + int count, + int bits_per_byte, + const std::string &reset_tag_key) : sync_block("additive_scrambler_bb", io_signature::make(1, 1, sizeof(unsigned char)), io_signature::make(1, 1, sizeof(unsigned char))), d_lfsr(mask, seed, len), - d_count(count), - d_bits(0), d_len(len), d_seed(seed) + d_count(reset_tag_key.empty() ? count : -1), + d_bytes(0), d_len(len), d_seed(seed), + d_bits_per_byte(bits_per_byte), d_reset_tag_key(pmt::string_to_symbol(reset_tag_key)) { + if (d_count < -1) { + throw std::invalid_argument("count must be non-negative!"); + } + if (d_bits_per_byte < 1 || d_bits_per_byte > 8) { + throw std::invalid_argument("bits_per_byte must be in [1, 8]"); + } } additive_scrambler_bb_impl::~additive_scrambler_bb_impl() @@ -78,6 +90,28 @@ namespace gr { return d_count; } + int additive_scrambler_bb_impl::_get_next_reset_index(int noutput_items, int last_reset_index /* = -1 */) + { + int reset_index = noutput_items; // This is a value that gets never reached in the for loop + if (d_count == -1) { + std::vector<gr::tag_t> tags; + get_tags_in_range(tags, 0, nitems_read(0), nitems_read(0)+noutput_items, d_reset_tag_key); + for (unsigned i = 0; i < tags.size(); i++) { + int reset_pos = tags[i].offset - nitems_read(0); + if (reset_pos < reset_index && reset_pos > last_reset_index) { + reset_index = reset_pos; + }; + } + } else { + if (last_reset_index == -1) { + reset_index = d_count - d_bytes; + } else { + reset_index = last_reset_index + d_count; + } + } + return reset_index; + } + int additive_scrambler_bb_impl::work(int noutput_items, gr_vector_const_void_star &input_items, @@ -85,14 +119,19 @@ namespace gr { { const unsigned char *in = (const unsigned char *)input_items[0]; unsigned char *out = (unsigned char *)output_items[0]; + int reset_index = _get_next_reset_index(noutput_items); for(int i = 0; i < noutput_items; i++) { - out[i] = in[i]^d_lfsr.next_bit(); - if(d_count > 0) { - if(++d_bits == d_count) { - d_lfsr.reset(); - d_bits = 0; - } + unsigned char scramble_byte = 0x00; + for (int k = 0; k < d_bits_per_byte; k++) { + scramble_byte ^= (d_lfsr.next_bit() << k); + } + out[i] = in[i] ^ scramble_byte; + d_bytes++; + if (i == reset_index) { + d_lfsr.reset(); + d_bytes = 0; + reset_index = _get_next_reset_index(noutput_items, reset_index); } } diff --git a/gr-digital/lib/additive_scrambler_bb_impl.h b/gr-digital/lib/additive_scrambler_bb_impl.h index b621637e67..a3b31c02bc 100644 --- a/gr-digital/lib/additive_scrambler_bb_impl.h +++ b/gr-digital/lib/additive_scrambler_bb_impl.h @@ -34,21 +34,27 @@ namespace gr { { private: digital::lfsr d_lfsr; - int d_count; - int d_bits; + int d_count; //!< Reset the LFSR after this many bytes (not bits) + int d_bytes; //!< Count the processed bytes int d_len; int d_seed; + int d_bits_per_byte; + pmt::pmt_t d_reset_tag_key; //!< Reset the LFSR when this tag is received + + int _get_next_reset_index(int noutput_items, int last_reset_index=-1); public: additive_scrambler_bb_impl(int mask, int seed, - int len, int count=0); + int len, int count=0, + int bits_per_byte=1, const std::string &reset_tag_key=""); ~additive_scrambler_bb_impl(); int mask() const; int seed() const; int len() const; int count() const; - + int bits_per_byte() { return d_bits_per_byte; }; + int work(int noutput_items, gr_vector_const_void_star &input_items, gr_vector_void_star &output_items); diff --git a/gr-digital/lib/constellation.cc b/gr-digital/lib/constellation.cc index 2c70bb0944..ff86531f0f 100644 --- a/gr-digital/lib/constellation.cc +++ b/gr-digital/lib/constellation.cc @@ -33,6 +33,7 @@ #include <stdlib.h> #include <float.h> #include <stdexcept> +#include <boost/format.hpp> namespace gr { namespace digital { @@ -48,7 +49,9 @@ namespace gr { d_constellation(constell), d_pre_diff_code(pre_diff_code), d_rotational_symmetry(rotational_symmetry), - d_dimensionality(dimensionality) + d_dimensionality(dimensionality), + d_lut_precision(0), + d_lut_scale(0) { // Scale constellation points so that average magnitude is 1. float summed_mag = 0; @@ -59,7 +62,7 @@ namespace gr { } d_scalefactor = constsize/summed_mag; for (unsigned int i=0; i<constsize; i++) { - d_constellation[i] = d_constellation[i]*d_scalefactor; + d_constellation[i] = d_constellation[i]*d_scalefactor; } if(pre_diff_code.size() == 0) d_apply_pre_diff_code = false; @@ -233,10 +236,154 @@ namespace gr { } + void + constellation::gen_soft_dec_lut(int precision, float npwr) + { + max_min_axes(); + d_lut_scale = powf(2.0, static_cast<float>(precision)); + float xstep = (d_re_max - d_re_min) / (d_lut_scale-1); + float ystep = (d_im_max - d_im_min) / (d_lut_scale-1); + d_soft_dec_lut.clear(); + + float y = d_im_min; + while(y < d_im_max) { + float x = d_re_min; + while(x < d_re_max) { + gr_complex pt = gr_complex(x, y); + d_soft_dec_lut.push_back(calc_soft_dec(pt, npwr)); + x += xstep; + } + y += ystep; + } + + d_lut_precision = precision; + } + + std::vector<float> + constellation::calc_soft_dec(gr_complex sample, float npwr) + { + int M = static_cast<int>(d_constellation.size()); + int k = static_cast<int>(log10f(static_cast<float>(M))/log10f(2.0)); + std::vector<float> tmp(2*k, 0); + std::vector<float> s(k, 0); + + float scale = d_scalefactor*d_scalefactor; + + for(int i = 0; i < M; i++) { + // Calculate the distance between the sample and the current + // constellation point. + float dist = powf(std::abs(sample - d_constellation[i]), 2.0f); + + // Calculate the probability factor from the distance and + // the scaled noise power. + float d = expf(-dist / (2.0*npwr*scale)); + + for(int j = 0; j < k; j++) { + // Get the bit at the jth index + int mask = 1 << j; + int bit = (d_pre_diff_code[i] & mask) >> j; + + // If the bit is a 0, add to the probability of a zero + if(bit == 0) + tmp[2*j+0] += d; + // else, add to the probability of a one + else + tmp[2*j+1] += d; + } + } + + // Calculate the log-likelihood ratio for all bits based on the + // probability of ones (tmp[2*i+1]) over the probability of a zero + // (tmp[2*i+0]). + for(int i = 0; i < k; i++) { + s[k-1-i] = (logf(tmp[2*i+1]) - logf(tmp[2*i+0])) * scale; + } + + return s; + } + + void + constellation::set_soft_dec_lut(const std::vector< std::vector<float> > &soft_dec_lut, + int precision) + { + max_min_axes(); + + d_soft_dec_lut = soft_dec_lut; + d_lut_precision = precision; + d_lut_scale = powf(2.0, static_cast<float>(precision)); + } + + bool + constellation::has_soft_dec_lut() + { + return d_soft_dec_lut.size() > 0; + } + + std::vector<float> + constellation::soft_decision_maker(gr_complex sample) + { + if(has_soft_dec_lut()) { + float xre = sample.real(); + float xim = sample.imag(); + + float xstep = (d_re_max-d_re_min) / d_lut_scale; + float ystep = (d_im_max-d_im_min) / d_lut_scale; + + float xscale = (d_lut_scale / (d_re_max-d_re_min)) - xstep; + float yscale = (d_lut_scale / (d_im_max-d_im_min)) - ystep; + + xre = floorf((-d_re_min + std::min(d_re_max, std::max(d_re_min, xre))) * xscale); + xim = floorf((-d_im_min + std::min(d_im_max, std::max(d_im_min, xim))) * yscale); + int index = static_cast<int>(d_lut_scale*xim + xre); + + int max_index = d_lut_scale*d_lut_scale; + if(index > max_index) { + return d_soft_dec_lut[max_index-1]; + } + + if(index < 0) + throw std::runtime_error("constellation::soft_decision_maker: input sample out of range."); + + return d_soft_dec_lut[index]; + } + else { + return calc_soft_dec(sample); + } + } + + void + constellation::max_min_axes() + { + // Find min/max of constellation for both real and imag axes. + d_re_min = 1e20; + d_im_min = 1e20; + d_re_max = -1e20; + d_im_max = -1e20; + for(size_t i = 0; i < d_constellation.size(); i++) { + if(d_constellation[i].real() > d_re_max) + d_re_max = d_constellation[i].real(); + if(d_constellation[i].imag() > d_im_max) + d_im_max = d_constellation[i].imag(); + + if(d_constellation[i].real() < d_re_min) + d_re_min = d_constellation[i].real(); + if(d_constellation[i].imag() < d_im_min) + d_im_min = d_constellation[i].imag(); + } + if(d_im_min == 0) + d_im_min = d_re_min; + if(d_im_max == 0) + d_im_max = d_re_max; + if(d_re_min == 0) + d_re_min = d_im_min; + if(d_re_max == 0) + d_re_max = d_im_max; + } + /********************************************************************/ - constellation_calcdist::sptr + constellation_calcdist::sptr constellation_calcdist::make(std::vector<gr_complex> constell, std::vector<int> pre_diff_code, unsigned int rotational_symmetry, diff --git a/gr-digital/lib/constellation_soft_decoder_cf_impl.cc b/gr-digital/lib/constellation_soft_decoder_cf_impl.cc new file mode 100644 index 0000000000..cd0a844119 --- /dev/null +++ b/gr-digital/lib/constellation_soft_decoder_cf_impl.cc @@ -0,0 +1,78 @@ +/* -*- c++ -*- */ +/* + * Copyright 2013 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "constellation_soft_decoder_cf_impl.h" +#include <gnuradio/io_signature.h> + +namespace gr { + namespace digital { + + constellation_soft_decoder_cf::sptr + constellation_soft_decoder_cf::make(constellation_sptr constellation) + { + return gnuradio::get_initial_sptr + (new constellation_soft_decoder_cf_impl(constellation)); + } + + constellation_soft_decoder_cf_impl:: + constellation_soft_decoder_cf_impl(constellation_sptr constellation) + : sync_interpolator("constellation_soft_decoder_cf", + io_signature::make(1, 1, sizeof(gr_complex)), + io_signature::make(1, 1, sizeof(float)), + constellation->bits_per_symbol()), + d_constellation(constellation), + d_dim(constellation->dimensionality()), + d_bps(constellation->bits_per_symbol()) + { + } + + constellation_soft_decoder_cf_impl::~constellation_soft_decoder_cf_impl() + { + } + + int + constellation_soft_decoder_cf_impl::work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) + { + gr_complex const *in = (const gr_complex*)input_items[0]; + float *out = (float*)output_items[0]; + + std::vector<float> bits; + + // FIXME: figure out how to manage d_dim + for(int i = 0; i < noutput_items/d_bps; i++) { + bits = d_constellation->soft_decision_maker(in[i]); + for(size_t j = 0; j < bits.size(); j++) { + out[d_bps*i+j] = bits[j]; + } + } + + return noutput_items; + } + + } /* namespace digital */ +} /* namespace gr */ diff --git a/gr-digital/lib/constellation_soft_decoder_cf_impl.h b/gr-digital/lib/constellation_soft_decoder_cf_impl.h new file mode 100644 index 0000000000..8a1159b627 --- /dev/null +++ b/gr-digital/lib/constellation_soft_decoder_cf_impl.h @@ -0,0 +1,50 @@ +/* -*- c++ -*- */ +/* + * Copyright 2013 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_DIGITAL_CONSTELLATION_SOFT_DECODER_CF_IMPL_H +#define INCLUDED_DIGITAL_CONSTELLATION_SOFT_DECODER_CF_IMPL_H + +#include <gnuradio/digital/constellation_soft_decoder_cf.h> + +namespace gr { + namespace digital { + + class constellation_soft_decoder_cf_impl : public constellation_soft_decoder_cf + { + private: + constellation_sptr d_constellation; + unsigned int d_dim; + int d_bps; + + public: + constellation_soft_decoder_cf_impl(constellation_sptr constellation); + ~constellation_soft_decoder_cf_impl(); + + int work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + }; + + } /* namespace digital */ +} /* namespace gr */ + +#endif /* INCLUDED_DIGITAL_CONSTELLATION_SOFT_DECODER_CF_IMPL_H */ diff --git a/gr-digital/lib/packet_header_default.cc b/gr-digital/lib/packet_header_default.cc index ef5f39dc97..12b8613b6d 100644 --- a/gr-digital/lib/packet_header_default.cc +++ b/gr-digital/lib/packet_header_default.cc @@ -69,27 +69,28 @@ namespace gr { ) { packet_len &= 0x0FFF; + d_crc_impl.reset(); + d_crc_impl.process_bytes((void const *) &packet_len, 2); + d_crc_impl.process_bytes((void const *) &d_header_number, 2); + unsigned char crc = d_crc_impl(); memset(out, 0x00, d_header_len); - int parity = 0; int k = 0; // Position in out for (int i = 0; i < 12 && k < d_header_len; i += d_bits_per_byte, k++) { out[k] = (unsigned char) ((packet_len >> i) & d_mask); - parity += out[k]; } - for (int i = 0; i < 16 && k < d_header_len; i += d_bits_per_byte, k++) { + for (int i = 0; i < 12 && k < d_header_len; i += d_bits_per_byte, k++) { out[k] = (unsigned char) ((d_header_number >> i) & d_mask); - parity += out[k]; } - if (k < d_header_len) { - out[k] = (unsigned char) (parity % 2); + for (int i = 0; i < 8 && k < d_header_len; i += d_bits_per_byte, k++) { + out[k] = (unsigned char) ((crc >> i) & d_mask); } d_header_number++; + d_header_number &= 0x0FFF; return true; } - bool packet_header_default::header_parser( const unsigned char *in, std::vector<tag_t> &tags) @@ -109,25 +110,30 @@ namespace gr { return true; } if (d_num_tag_key == pmt::PMT_NIL) { - k += 16; + k += 12; } else { - for (int i = 0; i < 16 && k < d_header_len; i += d_bits_per_byte, k++) { + for (int i = 0; i < 12 && k < d_header_len; i += d_bits_per_byte, k++) { header_num |= (((int) in[k]) & d_mask) << i; } tag.key = d_num_tag_key; tag.value = pmt::from_long(header_num); tags.push_back(tag); } - if (k >= d_header_len) { return true; } - int parity = in[k]; - for (int i = 0; i < 28; i++) { - parity += in[i]; + d_crc_impl.reset(); + d_crc_impl.process_bytes((void const *) &header_len, 2); + d_crc_impl.process_bytes((void const *) &header_num, 2); + unsigned char crc_calcd = d_crc_impl(); + for (int i = 0; i < 8 && k < d_header_len; i += d_bits_per_byte, k++) { + if ( (((int) in[k]) & d_mask) != (((int) crc_calcd >> i) & d_mask) ) { + return false; + } } - return !(parity % 2); + + return true; } } /* namespace digital */ diff --git a/gr-digital/lib/packet_header_ofdm.cc b/gr-digital/lib/packet_header_ofdm.cc index f163657bab..4893b866e2 100644 --- a/gr-digital/lib/packet_header_ofdm.cc +++ b/gr-digital/lib/packet_header_ofdm.cc @@ -24,6 +24,7 @@ #endif #include <gnuradio/digital/packet_header_ofdm.h> +#include <gnuradio/digital/lfsr.h> namespace gr { namespace digital { @@ -46,11 +47,13 @@ namespace gr { const std::string &frame_len_tag_key, const std::string &num_tag_key, int bits_per_header_sym, - int bits_per_payload_sym) + int bits_per_payload_sym, + bool scramble_header) { return packet_header_ofdm::sptr( new packet_header_ofdm( - occupied_carriers, n_syms, len_tag_key, frame_len_tag_key, num_tag_key, bits_per_header_sym, bits_per_payload_sym + occupied_carriers, n_syms, len_tag_key, frame_len_tag_key, num_tag_key, + bits_per_header_sym, bits_per_payload_sym, scramble_header ) ); } @@ -62,8 +65,9 @@ namespace gr { const std::string &frame_len_tag_key, const std::string &num_tag_key, int bits_per_header_sym, - int bits_per_payload_sym) - : packet_header_default( + int bits_per_payload_sym, + bool scramble_header + ) : packet_header_default( _get_header_len_from_occupied_carriers(occupied_carriers, n_syms), len_tag_key, num_tag_key, @@ -71,23 +75,47 @@ namespace gr { d_frame_len_tag_key(pmt::string_to_symbol(frame_len_tag_key)), d_occupied_carriers(occupied_carriers), d_syms_per_set(0), - d_bits_per_payload_sym(bits_per_payload_sym) + d_bits_per_payload_sym(bits_per_payload_sym), + d_scramble_mask(d_header_len, 0) { for (unsigned i = 0; i < d_occupied_carriers.size(); i++) { d_syms_per_set += d_occupied_carriers[i].size(); } + + // Init scrambler mask + if (scramble_header) { + // These are just random values which already have OK PAPR: + gr::digital::lfsr shift_reg(0x8a, 0x6f, 7); + for (int i = 0; i < d_header_len; i++) { + for (int k = 0; k < bits_per_header_sym; k++) { + d_scramble_mask[i] ^= shift_reg.next_bit() << k; + } + } + } } packet_header_ofdm::~packet_header_ofdm() { } + bool packet_header_ofdm::header_formatter(long packet_len, unsigned char *out, const std::vector<tag_t> &tags) + { + bool ret_val = packet_header_default::header_formatter(packet_len, out, tags); + for (int i = 0; i < d_header_len; i++) { + out[i] ^= d_scramble_mask[i]; + } + return ret_val; + } bool packet_header_ofdm::header_parser( const unsigned char *in, std::vector<tag_t> &tags) { - if (!packet_header_default::header_parser(in, tags)) { + std::vector<unsigned char> in_descrambled(d_header_len, 0); + for (int i = 0; i < d_header_len; i++) { + in_descrambled[i] = in[i] ^ d_scramble_mask[i]; + } + if (!packet_header_default::header_parser(&in_descrambled[0], tags)) { return false; } int packet_len = 0; // # of bytes in this frame diff --git a/gr-digital/python/digital/CMakeLists.txt b/gr-digital/python/digital/CMakeLists.txt index 30066d9aac..e0cb77fb21 100644 --- a/gr-digital/python/digital/CMakeLists.txt +++ b/gr-digital/python/digital/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright 2011-212 Free Software Foundation, Inc. +# Copyright 2011-2013 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -26,6 +26,7 @@ GR_PYTHON_INSTALL( FILES __init__.py bpsk.py + constellation_map_generator.py cpm.py crc.py generic_mod_demod.py @@ -43,9 +44,12 @@ GR_PYTHON_INSTALL( packet_utils.py pkt.py psk.py + psk_constellations.py qam.py qamlike.py + qam_constellations.py qpsk.py + soft_dec_lut_gen.py DESTINATION ${GR_PYTHON_DIR}/gnuradio/digital COMPONENT "digital_python" ) diff --git a/gr-digital/python/digital/__init__.py b/gr-digital/python/digital/__init__.py index 5059e4eec8..79b740644d 100644 --- a/gr-digital/python/digital/__init__.py +++ b/gr-digital/python/digital/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2011 Free Software Foundation, Inc. +# Copyright 2011-2013 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -50,6 +50,10 @@ from ofdm_sync_ml import * from ofdm_sync_pnac import * from ofdm_sync_pn import * from ofdm_txrx import ofdm_tx, ofdm_rx +from soft_dec_lut_gen import * +from psk_constellations import * +from qam_constellations import * +from constellation_map_generator import * import packet_utils import ofdm_packet_utils diff --git a/gr-digital/python/digital/constellation_map_generator.py b/gr-digital/python/digital/constellation_map_generator.py new file mode 100644 index 0000000000..bf689676c3 --- /dev/null +++ b/gr-digital/python/digital/constellation_map_generator.py @@ -0,0 +1,52 @@ +#!/usr/bin/env python +# +# Copyright 2013 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 constellation_map_generator(basis_cpoints, basis_symbols, k, pi): + ''' + Uses the a basis constellation provided (e.g., from + psk_constellation.psk_4()) and the the k and permutation index + (pi) to generate a new Gray-coded symbol map to the constellation + points provided in the basis. + + The basis_cpoints are the constellation points of the basis + constellation, and basis_symbols are the symbols that correspond + to the constellation points. + + The selection of k and pi will provide an automorphism the + hyperoctahedral group of the basis constellation. + + This function returns a tuple of (constellation_points, + symbol_map). The constellation_points is a list of the + constellation points in complex space and the symbol_map is a list + of the log2(M)-bit symbols for the constellation points (i.e., + symbol_map[i] are the bits associated with + constellation_points[i]). + ''' + const_points, s = basis() + symbols = list() + for s_i in s: + tmp = 0 + for i,p in enumerate(pi): + bit = (s_i >> i) & 0x1 + tmp |= bit << p + symbols.append(tmp ^ k) + return (const_points, symbols) diff --git a/gr-digital/python/digital/ofdm_txrx.py b/gr-digital/python/digital/ofdm_txrx.py index a48a48db41..06e375e3d6 100644 --- a/gr-digital/python/digital/ofdm_txrx.py +++ b/gr-digital/python/digital/ofdm_txrx.py @@ -63,6 +63,7 @@ _seq_seed = 42 def _get_active_carriers(fft_len, occupied_carriers, pilot_carriers): + """ Returns a list of all carriers that at some point carry data or pilots. """ active_carriers = list() for carrier in list(occupied_carriers[0]) + list(pilot_carriers[0]): if carrier < 0: @@ -134,6 +135,8 @@ class ofdm_tx(gr.hier_block2): sync_word2: The second sync preamble symbol. This has to be filled entirely. Also used for coarse frequency offset and channel estimation. rolloff: The rolloff length in samples. Must be smaller than the CP. + debug_log: Write output into log files (Warning: creates lots of data!) + scramble_bits: Activates the scramblers (set this to True unless debugging) """ def __init__(self, fft_len=_def_fft_len, cp_len=_def_cp_len, packet_length_tag_key=_def_packet_length_tag_key, @@ -145,7 +148,8 @@ class ofdm_tx(gr.hier_block2): sync_word1=None, sync_word2=None, rolloff=0, - debug_log=False + debug_log=False, + scramble_bits=False ): gr.hier_block2.__init__(self, "ofdm_tx", gr.io_signature(1, 1, gr.sizeof_char), @@ -159,7 +163,6 @@ class ofdm_tx(gr.hier_block2): self.pilot_symbols = pilot_symbols self.bps_header = bps_header self.bps_payload = bps_payload - n_sync_words = 1 self.sync_word1 = sync_word1 if sync_word1 is None: self.sync_word1 = _make_sync_word1(fft_len, occupied_carriers, pilot_carriers) @@ -167,15 +170,19 @@ class ofdm_tx(gr.hier_block2): if len(sync_word1) != self.fft_len: raise ValueError("Length of sync sequence(s) must be FFT length.") self.sync_words = [self.sync_word1,] - self.sync_word2 = () if sync_word2 is None: self.sync_word2 = _make_sync_word2(fft_len, occupied_carriers, pilot_carriers) + else: + self.sync_word2 = sync_word2 if len(self.sync_word2): if len(self.sync_word2) != fft_len: raise ValueError("Length of sync sequence(s) must be FFT length.") self.sync_word2 = list(self.sync_word2) - n_sync_words = 2 self.sync_words.append(self.sync_word2) + if scramble_bits: + self.scramble_seed = 0x7f + else: + self.scramble_seed = 0x00 # We deactivate the scrambler by init'ing it with zeros ### Header modulation ################################################ crc = digital.crc32_bb(False, self.packet_length_tag_key) header_constellation = _get_constellation(bps_header) @@ -183,18 +190,34 @@ class ofdm_tx(gr.hier_block2): formatter_object = digital.packet_header_ofdm( occupied_carriers=occupied_carriers, n_syms=1, bits_per_header_sym=self.bps_header, - bits_per_payload_sym=self.bps_payload + bits_per_payload_sym=self.bps_payload, + scramble_header=scramble_bits ) header_gen = digital.packet_headergenerator_bb(formatter_object.base(), self.packet_length_tag_key) header_payload_mux = blocks.tagged_stream_mux(gr.sizeof_gr_complex*1, self.packet_length_tag_key) - self.connect(self, crc, header_gen, header_mod, (header_payload_mux, 0)) + self.connect( + self, + crc, + header_gen, + header_mod, + (header_payload_mux, 0) + ) if debug_log: self.connect(header_gen, blocks.file_sink(1, 'tx-hdr.dat')) ### Payload modulation ############################################### payload_constellation = _get_constellation(bps_payload) payload_mod = digital.chunks_to_symbols_bc(payload_constellation.points()) + payload_scrambler = digital.additive_scrambler_bb( + 0x8a, + self.scramble_seed, + 7, + 0, # Don't reset after fixed length (let the reset tag do that) + bits_per_byte=bps_payload, + reset_tag_key=self.packet_length_tag_key + ) self.connect( crc, + payload_scrambler, blocks.repack_bits_bb( 8, # Unpack 8 bits per byte bps_payload, @@ -226,8 +249,8 @@ class ofdm_tx(gr.hier_block2): ) self.connect(header_payload_mux, allocator, ffter, cyclic_prefixer, self) if debug_log: - self.connect(allocator, blocks.file_sink(8*64, 'tx-post-allocator.dat')) - self.connect(cyclic_prefixer, blocks.file_sink(8, 'tx-signal.dat')) + self.connect(allocator, blocks.file_sink(gr.sizeof_gr_complex * fft_len, 'tx-post-allocator.dat')) + self.connect(cyclic_prefixer, blocks.file_sink(gr.sizeof_gr_complex, 'tx-signal.dat')) class ofdm_rx(gr.hier_block2): @@ -262,7 +285,8 @@ class ofdm_rx(gr.hier_block2): bps_payload=1, sync_word1=None, sync_word2=None, - debug_log=False + debug_log=False, + scramble_bits=False ): gr.hier_block2.__init__(self, "ofdm_rx", gr.io_signature(1, 1, gr.sizeof_gr_complex), @@ -291,6 +315,10 @@ class ofdm_rx(gr.hier_block2): raise ValueError("Length of sync sequence(s) must be FFT length.") self.sync_word2 = sync_word2 n_sync_words = 2 + if scramble_bits: + self.scramble_seed = 0x7f + else: + self.scramble_seed = 0x00 # We deactivate the scrambler by init'ing it with zeros ### Sync ############################################################ sync_detect = digital.ofdm_sync_sc_cfb(fft_len, cp_len) delay = blocks.delay(gr.sizeof_gr_complex, fft_len+cp_len) @@ -315,8 +343,12 @@ class ofdm_rx(gr.hier_block2): chanest = digital.ofdm_chanest_vcvc(self.sync_word1, self.sync_word2, 1) header_constellation = _get_constellation(bps_header) header_equalizer = digital.ofdm_equalizer_simpledfe( - fft_len, header_constellation.base(), - occupied_carriers, pilot_carriers, pilot_symbols, 0, 0 + fft_len, + header_constellation.base(), + occupied_carriers, + pilot_carriers, + pilot_symbols, + symbols_skipped=0, ) header_eq = digital.ofdm_frame_equalizer_vcvc( header_equalizer.base(), @@ -336,10 +368,19 @@ class ofdm_rx(gr.hier_block2): frame_length_tag_key, packet_num_tag_key, bps_header, - bps_payload + bps_payload, + scramble_header=scramble_bits ) header_parser = digital.packet_headerparser_b(header_formatter.formatter()) - self.connect((hpd, 0), header_fft, chanest, header_eq, header_serializer, header_demod, header_parser) + self.connect( + (hpd, 0), + header_fft, + chanest, + header_eq, + header_serializer, + header_demod, + header_parser + ) self.msg_connect(header_parser, "header_data", hpd, "header_data") if debug_log: self.connect((chanest, 1), blocks.file_sink(gr.sizeof_gr_complex * fft_len, 'channel-estimate.dat')) @@ -347,16 +388,18 @@ class ofdm_rx(gr.hier_block2): self.connect((chanest, 0), blocks.tag_debug(gr.sizeof_gr_complex * fft_len, 'post-hdr-chanest')) self.connect(header_eq, blocks.file_sink(gr.sizeof_gr_complex * fft_len, 'post-hdr-eq.dat')) self.connect(header_serializer, blocks.file_sink(gr.sizeof_gr_complex, 'post-hdr-serializer.dat')) - self.connect(header_demod, blocks.file_sink(1, 'post-hdr-demod.dat')) + self.connect(header_descrambler, blocks.file_sink(1, 'post-hdr-demod.dat')) ### Payload demod #################################################### payload_fft = fft.fft_vcc(self.fft_len, True, (), True) payload_constellation = _get_constellation(bps_payload) payload_equalizer = digital.ofdm_equalizer_simpledfe( - fft_len, payload_constellation.base(), + fft_len, + payload_constellation.base(), occupied_carriers, pilot_carriers, pilot_symbols, - 1 # Skip 1 symbol (that was already in the header) + symbols_skipped=1, # (that was already in the header) + alpha=0.1 ) payload_eq = digital.ofdm_frame_equalizer_vcvc( payload_equalizer.base(), @@ -370,11 +413,29 @@ class ofdm_rx(gr.hier_block2): 1 # Skip 1 symbol (that was already in the header) ) payload_demod = digital.constellation_decoder_cb(payload_constellation.base()) + self.payload_descrambler = digital.additive_scrambler_bb( + 0x8a, + self.scramble_seed, + 7, + 0, # Don't reset after fixed length + bits_per_byte=bps_payload, + reset_tag_key=self.packet_length_tag_key + ) repack = blocks.repack_bits_bb(bps_payload, 8, self.packet_length_tag_key, True) - crc = digital.crc32_bb(True, self.packet_length_tag_key) - self.connect((hpd, 1), payload_fft, payload_eq, payload_serializer, payload_demod, repack, crc, self) + self.crc = digital.crc32_bb(True, self.packet_length_tag_key) + self.connect( + (hpd, 1), + payload_fft, + payload_eq, + payload_serializer, + payload_demod, + repack, + self.payload_descrambler, + self.crc, + self + ) if debug_log: - self.connect((hpd, 1), blocks.tag_debug(gr.sizeof_gr_complex*fft_len, 'post-hpd')); + self.connect((hpd, 1), blocks.tag_debug(gr.sizeof_gr_complex*fft_len, 'post-hpd')) self.connect(payload_fft, blocks.file_sink(gr.sizeof_gr_complex*fft_len, 'post-payload-fft.dat')) self.connect(payload_eq, blocks.file_sink(gr.sizeof_gr_complex*fft_len, 'post-payload-eq.dat')) self.connect(payload_serializer, blocks.file_sink(gr.sizeof_gr_complex, 'post-payload-serializer.dat')) diff --git a/gr-digital/python/digital/packet_utils.py b/gr-digital/python/digital/packet_utils.py index 2929758ef0..865f3adbb4 100644 --- a/gr-digital/python/digital/packet_utils.py +++ b/gr-digital/python/digital/packet_utils.py @@ -71,7 +71,7 @@ def conv_1_0_string_to_packed_binary_string(s): default_access_code = \ conv_packed_binary_string_to_1_0_string('\xAC\xDD\xA4\xE2\xF2\x8C\x20\xFC') -preamble = \ +default_preamble = \ conv_packed_binary_string_to_1_0_string('\xA4\xF2') def is_1_0_string(s): @@ -102,8 +102,8 @@ def make_header(payload_len, whitener_offset=0): return struct.pack('!HH', val, val) def make_packet(payload, samples_per_symbol, bits_per_symbol, - access_code=default_access_code, pad_for_usrp=True, - whitener_offset=0, whitening=True): + preamble=default_preamble, access_code=default_access_code, + pad_for_usrp=True, whitener_offset=0, whitening=True): """ Build a packet, given access code, payload, and whitener offset @@ -111,12 +111,16 @@ def make_packet(payload, samples_per_symbol, bits_per_symbol, payload: packet payload, len [0, 4096] samples_per_symbol: samples per symbol (needed for padding calculation) (int) bits_per_symbol: (needed for padding calculation) (int) + preamble: string of ascii 0's and 1's access_code: string of ascii 0's and 1's whitener_offset: offset into whitener string to use [0-16) Packet will have access code at the beginning, followed by length, payload and finally CRC-32. """ + if not is_1_0_string(preamble): + raise ValueError, "preamble must be a string containing only 0's and 1's (%r)" % (preamble,) + if not is_1_0_string(access_code): raise ValueError, "access_code must be a string containing only 0's and 1's (%r)" % (access_code,) diff --git a/gr-digital/python/digital/pkt.py b/gr-digital/python/digital/pkt.py index 434548906e..fbdcaa3a66 100644 --- a/gr-digital/python/digital/pkt.py +++ b/gr-digital/python/digital/pkt.py @@ -40,8 +40,8 @@ class mod_pkts(gr.hier_block2): Send packets by calling send_pkt """ - def __init__(self, modulator, access_code=None, msgq_limit=2, pad_for_usrp=True, - use_whitener_offset=False, modulate=True): + def __init__(self, modulator, preamble=None, access_code=None, msgq_limit=2, + pad_for_usrp=True, use_whitener_offset=False, modulate=True): """ Hierarchical block for sending packets @@ -72,6 +72,12 @@ class mod_pkts(gr.hier_block2): 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 preamble is None: + preamble = packet_utils.default_preamble + if not packet_utils.is_1_0_string(preamble): + raise ValueError, "Invalid preamble %r. Must be string of 1's and 0's" % (preamble,) + self._preamble = preamble # accepts messages from the outside world self._pkt_input = blocks.message_source(gr.sizeof_char, msgq_limit) @@ -91,6 +97,7 @@ class mod_pkts(gr.hier_block2): pkt = packet_utils.make_packet(payload, self._modulator.samples_per_symbol(), self._modulator.bits_per_symbol(), + self._preamble, self._access_code, self._pad_for_usrp, self._whitener_offset) diff --git a/gr-digital/python/digital/psk_constellations.py b/gr-digital/python/digital/psk_constellations.py new file mode 100755 index 0000000000..ee62c33a0c --- /dev/null +++ b/gr-digital/python/digital/psk_constellations.py @@ -0,0 +1,308 @@ +#!/usr/bin/env python +# +# Copyright 2013 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 numpy +from constellation_map_generator import * + +''' +Note on the naming scheme. Each constellation is named using a prefix +for the type of constellation, the order of the constellation, and a +distinguishing feature, which comes in three modes: + +- No extra feature: the basic Gray-coded constellation map; others + will be derived from this type. +- A single number: an indexed number to uniquely identify different + constellation maps. +- 0xN_x0_x1..._xM: A permutation of the base constellation, explained + below. + +For rectangular constellations (BPSK, QPSK, QAM), we can define a +hyperspace and look for all symmetries. This is also known as the +automorphism group of the hypercube, aka the hyperoctahedral +group. What this means is that we can easily define all possible +rotations in terms of the first base mapping by creating the mapping: + + f(x) = k XOR pi(x) + +The x is the bit string for the symbol we are altering. Then k is a +bit string of n bits where n is the number of bits per symbol in the +constellation (e.g., 2 for QPSK or 6 for QAM64). The pi is a +permutation function specified as pi_0, pi_1..., pi_n-1. This permutes +the bits from the base constellation symbol to a new code, which is +then xor'd by k. + +The value of k is from 0 to 2^n-1 and pi is a list of all bit +positions. + +The total number of Gray coded modulations is (2^n)*(n!). + +We create aliases for all possible naming schemes for the +constellations. So if a hyperoctahedral group is defined, we also set +this function equal to a function name using a unique ID number, and +we always select one rotation as our basic rotation that the other +rotations are based off of. +''' + +# BPSK Constellation Mappings + +def psk_2_0x0(): + ''' + 0 | 1 + ''' + const_points = [-1, 1] + symbols = [0, 1] + return (const_points, symbols) +psk_2 = psk_2_0x0 # Basic BPSK rotation +psk_2_0 = psk_2 # First ID for BPSK rotations + +def psk_2_0x1(): + ''' + 1 | 0 + ''' + const_points = [-1, 1] + symbols = [1, 0] + return (const_points, symbols) +psk_2_1 = psk_2_0x1 + + +############################################################ +# BPSK Soft bit LUT generators +############################################################ + +def sd_psk_2_0x0(x, Es=1): + ''' + 0 | 1 + ''' + x_re = x.real + dist = Es*numpy.sqrt(2) + return [dist*x_re,] +sd_psk_2 = sd_psk_2_0x0 # Basic BPSK rotation +sd_psk_2_0 = sd_psk_2 # First ID for BPSK rotations + +def sd_psk_2_0x1(x, Es=1): + ''' + 1 | 0 + ''' + x_re = [x.real,] + dist = Es*numpy.sqrt(2) + return -dist*x_re +sd_psk_2_1 = sd_psk_2_0x1 + + +############################################################ +# QPSK Constellation Mappings +############################################################ + +def psk_4_0x0_0_1(): + ''' + 10 | 11 + ------- + 00 | 01 + ''' + const_points = [-1-1j, 1-1j, + -1+1j, 1+1j] + symbols = [0, 1, 2, 3] + return (const_points, symbols) +psk_4 = psk_4_0x0_0_1 +psk_4_0 = psk_4 + +def psk_4_0x1_0_1(): + ''' + 11 | 10 + ------- + 01 | 00 + ''' + k = 0x1 + pi = [0, 1] + return constellation_map_generator(psk_4, k, pi) +psk_4_1 = psk_4_0x1_0_1 + +def psk_4_0x2_0_1(): + ''' + 00 | 01 + ------- + 10 | 11 + ''' + k = 0x2 + pi = [0, 1] + return constellation_map_generator(psk_4, k, pi) +psk_4_2 = psk_4_0x2_0_1 + +def psk_4_0x3_0_1(): + ''' + 01 | 00 + ------- + 11 | 10 + ''' + k = 0x3 + pi = [0, 1] + return constellation_map_generator(psk_4, k, pi) +psk_4_3 = psk_4_0x3_0_1 + +def psk_4_0x0_1_0(): + ''' + 01 | 11 + ------- + 00 | 10 + ''' + k = 0x0 + pi = [1, 0] + return constellation_map_generator(psk_4, k, pi) +psk_4_4 = psk_4_0x0_1_0 + +def psk_4_0x1_1_0(): + ''' + 00 | 10 + ------- + 01 | 11 + ''' + k = 0x1 + pi = [1, 0] + return constellation_map_generator(psk_4, k, pi) +psk_4_5 = psk_4_0x1_1_0 + +def psk_4_0x2_1_0(): + ''' + 11 | 01 + ------- + 10 | 00 + ''' + k = 0x2 + pi = [1, 0] + return constellation_map_generator(psk_4, k, pi) +psk_4_6 = psk_4_0x2_1_0 + +def psk_4_0x3_1_0(): + ''' + 10 | 00 + ------- + 11 | 01 + ''' + k = 0x3 + pi = [1, 0] + return constellation_map_generator(psk_4, k, pi) +psk_4_7 = psk_4_0x3_1_0 + + + +############################################################ +# QPSK Constellation Softbit LUT generators +############################################################ + +def sd_psk_4_0x0_0_1(x, Es=1): + ''' + 10 | 11 + ------- + 00 | 01 + ''' + x_re = x.real + x_im = x.imag + dist = Es*numpy.sqrt(2) + return [dist*x_im, dist*x_re] +sd_psk_4 = sd_psk_4_0x0_0_1 +sd_psk_4_0 = sd_psk_4 + +def sd_psk_4_0x1_0_1(x, Es=1): + ''' + 11 | 10 + ------- + 01 | 00 + ''' + x_re = x.real + x_im = x.imag + dist = Es*numpy.sqrt(2) + return [dist*x_im, -dist*x_re] +sd_psk_4_1 = sd_psk_4_0x1_0_1 + +def sd_psk_4_0x2_0_1(x, Es=1): + ''' + 00 | 01 + ------- + 10 | 11 + ''' + x_re = x.real + x_im = x.imag + dist = Es*numpy.sqrt(2) + return [-dist*x_im, dist*x_re] +sd_psk_4_2 = sd_psk_4_0x2_0_1 + +def sd_psk_4_0x3_0_1(x, Es=1): + ''' + 01 | 00 + ------- + 11 | 10 + ''' + x_re = x.real + x_im = x.imag + dist = Es*numpy.sqrt(2) + return [-dist*x_im, -dist*x_re] +sd_psk_4_3 = sd_psk_4_0x3_0_1 + +def sd_psk_4_0x0_1_0(x, Es=1): + ''' + 01 | 11 + ------- + 00 | 10 + ''' + x_re = x.real + x_im = x.imag + dist = Es*numpy.sqrt(2) + return [dist*x_re, dist*x_im] +sd_psk_4_4 = sd_psk_4_0x0_1_0 + +def sd_psk_4_0x1_1_0(x, Es=1): + ''' + 00 | 10 + ------- + 01 | 11 + ''' + x_re = x.real + x_im = x.imag + dist = Es*numpy.sqrt(2) + return [dist*x_re, -dist*x_im] +sd_psk_4_5 = sd_psk_4_0x1_1_0 + + +def sd_psk_4_0x2_1_0(x, Es=1): + ''' + 11 | 01 + ------- + 10 | 00 + ''' + x_re = x.real + x_im = x.imag + dist = Es*numpy.sqrt(2) + return [-dist*x_re, dist*x_im] +sd_psk_4_6 = sd_psk_4_0x2_1_0 + +def sd_psk_4_0x3_1_0(x, Es=1): + ''' + 10 | 00 + ------- + 11 | 01 + ''' + x_re = x.real + x_im = x.imag + dist = Es*numpy.sqrt(2) + return [-dist*x_re, -dist*x_im] +sd_psk_4_7 = sd_psk_4_0x3_1_0 + diff --git a/gr-digital/python/digital/qa_constellation.py b/gr-digital/python/digital/qa_constellation.py index 83a875af4b..00248f4f09 100644 --- a/gr-digital/python/digital/qa_constellation.py +++ b/gr-digital/python/digital/qa_constellation.py @@ -21,7 +21,7 @@ # import random -from cmath import exp, pi, log +from cmath import exp, pi, log, sqrt from gnuradio import gr, gr_unittest, digital, blocks from gnuradio.digital.utils import mod_codes @@ -185,6 +185,86 @@ class test_constellation(gr_unittest.TestCase): first = constellation.bits_per_symbol() self.assertEqual(self.src_data[first:len(data)], data[first:]) + def test_soft_qpsk_gen(self): + prec = 8 + constel, code = digital.psk_4_0() + + rot_sym = 1 + side = 2 + width = 2 + c = digital.constellation_rect(constel, code, rot_sym, + side, side, width, width) + + # Get max energy/symbol in constellation + constel = c.points() + Es = max([abs(constel_i) for constel_i in constel]) + + table = digital.soft_dec_table_generator(digital.sd_psk_4_0, prec, Es) + c.set_soft_dec_lut(table, prec) + + x = sqrt(2.0)/2.0 + step = (x.real+x.real) / (2**prec - 1) + samples = [ -x-x*1j, -x+x*1j, + x+x*1j, x-x*1j, + (-x+128*step)+(-x+128*step)*1j, + (-x+64*step) +(-x+64*step)*1j, (-x+64*step) +(-x+192*step)*1j, + (-x+192*step)+(-x+192*step)*1j, (-x+192*step)+(-x+64*step)*1j,] + + y_python_raw_calc = [] + y_python_gen_calc = [] + y_python_table = [] + y_cpp_raw_calc = [] + y_cpp_table = [] + for sample in samples: + y_python_raw_calc += digital.calc_soft_dec(sample, constel, code) + y_python_gen_calc += digital.sd_psk_4_0(sample, Es) + y_python_table += digital.calc_soft_dec_from_table(sample, table, prec, Es) + + y_cpp_raw_calc += c.calc_soft_dec(sample) + y_cpp_table += c.soft_decision_maker(sample) + + self.assertFloatTuplesAlmostEqual(y_python_raw_calc, y_python_gen_calc, 4) + self.assertFloatTuplesAlmostEqual(y_python_raw_calc, y_python_table, 2) + self.assertFloatTuplesAlmostEqual(y_cpp_raw_calc, y_cpp_table, 4) + + def test_soft_qpsk_calc(self): + prec = 8 + constel, code = digital.psk_4_0() + + rot_sym = 1 + side = 2 + width = 2 + c = digital.constellation_rect(constel, code, rot_sym, + side, side, width, width) + + # Get max energy/symbol in constellation + constel = c.points() + Es = max([abs(constel_i) for constel_i in constel]) + + table = digital.soft_dec_table(constel, code, prec) + c.gen_soft_dec_lut(prec) + + x = sqrt(2.0)/2.0 + step = (x.real+x.real) / (2**prec - 1) + samples = [ -x-x*1j, -x+x*1j, + x+x*1j, x-x*1j, + (-x+128*step)+(-x+128*step)*1j, + (-x+64*step) +(-x+64*step)*1j, (-x+64*step) +(-x+192*step)*1j, + (-x+192*step)+(-x+192*step)*1j, (-x+192*step)+(-x+64*step)*1j,] + + y_python_raw_calc = [] + y_python_table = [] + y_cpp_raw_calc = [] + y_cpp_table = [] + for sample in samples: + y_python_raw_calc += digital.calc_soft_dec(sample, constel, code) + y_python_table += digital.calc_soft_dec_from_table(sample, table, prec, Es) + + y_cpp_raw_calc += c.calc_soft_dec(sample) + y_cpp_table += c.soft_decision_maker(sample) + + self.assertFloatTuplesAlmostEqual(y_python_raw_calc, y_python_table, 4) + self.assertFloatTuplesAlmostEqual(y_cpp_raw_calc, y_cpp_table, 4) class mod_demod(gr.hier_block2): def __init__(self, constellation, differential, rotation): diff --git a/gr-digital/python/digital/qa_constellation_soft_decoder_cf.py b/gr-digital/python/digital/qa_constellation_soft_decoder_cf.py new file mode 100644 index 0000000000..6cd757537a --- /dev/null +++ b/gr-digital/python/digital/qa_constellation_soft_decoder_cf.py @@ -0,0 +1,112 @@ +#!/usr/bin/env python +# +# Copyright 2013 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +from gnuradio import gr, gr_unittest, digital, blocks +from math import sqrt + +class test_constellation_soft_decoder(gr_unittest.TestCase): + + def setUp(self): + self.tb = gr.top_block() + + def tearDown(self): + self.tb = None + + def test_constellation_soft_decoder_cf_bpsk(self): + prec = 8 + src_data = (0.5 + 0.5j, 0.1 - 1.2j, -0.8 - 0.1j, -0.45 + 0.8j, + 0.8 + 1.0j, -0.5 + 0.1j, 0.1 - 1.2j, 1+1j) + lut = digital.soft_dec_table_generator(digital.sd_psk_2_0x0, prec) + expected_result = list() + for s in src_data: + expected_result += digital.calc_soft_dec_from_table(s, lut, prec, Es=2/sqrt(2)) + + cnst_pts, code = digital.psk_2_0x0() + cnst = digital.constellation_calcdist(cnst_pts, code, 2, 1) + cnst.set_soft_dec_lut(lut, int(prec)) + src = blocks.vector_source_c(src_data) + op = digital.constellation_soft_decoder_cf(cnst.base()) + dst = blocks.vector_sink_f() + + self.tb.connect(src, op) + self.tb.connect(op, dst) + self.tb.run() # run the graph and wait for it to finish + + actual_result = dst.data() # fetch the contents of the sink + #print "actual result", actual_result + #print "expected result", expected_result + self.assertFloatTuplesAlmostEqual(expected_result, actual_result, 4) + + def test_constellation_soft_decoder_cf_qpsk(self): + prec = 8 + src_data = (0.5 + 0.5j, 0.1 - 1.2j, -0.8 - 0.1j, -0.45 + 0.8j, + 0.8 + 1.0j, -0.5 + 0.1j, 0.1 - 1.2j, 1+1j) + lut = digital.soft_dec_table_generator(digital.sd_psk_4_0x0_0_1, prec) + expected_result = list() + for s in src_data: + expected_result += digital.calc_soft_dec_from_table(s, lut, prec) + + cnst_pts,code = digital.psk_4_0x0_0_1() + cnst = digital.constellation_calcdist(cnst_pts, code, 2, 1) + cnst.set_soft_dec_lut(lut, int(prec)) + src = blocks.vector_source_c(src_data) + op = digital.constellation_soft_decoder_cf(cnst.base()) + dst = blocks.vector_sink_f() + + self.tb.connect(src, op) + self.tb.connect(op, dst) + self.tb.run() # run the graph and wait for it to finish + + actual_result = dst.data() # fetch the contents of the sink + #print "actual result", actual_result + #print "expected result", expected_result + self.assertFloatTuplesAlmostEqual(expected_result, actual_result, 5) + + def test_constellation_soft_decoder_cf_qam16(self): + prec = 8 + src_data = (0.5 + 0.5j, 0.1 - 1.2j, -0.8 - 0.1j, -0.45 + 0.8j, + 0.8 + 1.0j, -0.5 + 0.1j, 0.1 - 1.2j, 1+1j) + lut = digital.soft_dec_table_generator(digital.sd_qam_16_0x0_0_1_2_3, prec) + expected_result = list() + for s in src_data: + expected_result += digital.calc_soft_dec_from_table(s, lut, prec) + + cnst_pts = digital.qam_16_0x0_0_1_2_3() + cnst = digital.constellation_calcdist(cnst_pts[0], cnst_pts[1], 2, 1) + cnst.set_soft_dec_lut(lut, int(prec)) + src = blocks.vector_source_c(src_data) + op = digital.constellation_soft_decoder_cf(cnst.base()) + dst = blocks.vector_sink_f() + + self.tb.connect(src, op) + self.tb.connect(op, dst) + self.tb.run() # run the graph and wait for it to finish + + actual_result = dst.data() # fetch the contents of the sink + #print "actual result", actual_result + #print "expected result", expected_result + self.assertFloatTuplesAlmostEqual(expected_result, actual_result, 5) + + +if __name__ == '__main__': + gr_unittest.run(test_constellation_soft_decoder, "test_constellation_soft_decoder.xml") + diff --git a/gr-digital/python/digital/qa_ofdm_txrx.py b/gr-digital/python/digital/qa_ofdm_txrx.py index adf93ee356..6f5bd2ed10 100755 --- a/gr-digital/python/digital/qa_ofdm_txrx.py +++ b/gr-digital/python/digital/qa_ofdm_txrx.py @@ -31,11 +31,11 @@ from gnuradio.digital.utils import tagged_streams LOG_DEBUG_INFO=False class ofdm_tx_fg (gr.top_block): - def __init__(self, data, len_tag_key): + def __init__(self, data, len_tag_key, scramble_bits=False): gr.top_block.__init__(self, "ofdm_tx") tx_data, tags = tagged_streams.packets_to_vectors((data,), len_tag_key) src = blocks.vector_source_b(data, False, 1, tags) - self.tx = ofdm_tx(packet_length_tag_key=len_tag_key, debug_log=LOG_DEBUG_INFO) + self.tx = ofdm_tx(packet_length_tag_key=len_tag_key, debug_log=LOG_DEBUG_INFO, scramble_bits=scramble_bits) self.sink = blocks.vector_sink_c() self.connect(src, self.tx, self.sink) @@ -43,12 +43,12 @@ class ofdm_tx_fg (gr.top_block): return self.sink.data() class ofdm_rx_fg (gr.top_block): - def __init__(self, samples, len_tag_key, channel=None, prepend_zeros=100): + def __init__(self, samples, len_tag_key, channel=None, prepend_zeros=100, scramble_bits=False): gr.top_block.__init__(self, "ofdm_rx") if prepend_zeros: samples = (0,) * prepend_zeros + tuple(samples) src = blocks.vector_source_c(tuple(samples) + (0,) * 1000) - self.rx = ofdm_rx(frame_length_tag_key=len_tag_key, debug_log=LOG_DEBUG_INFO) + self.rx = ofdm_rx(frame_length_tag_key=len_tag_key, debug_log=LOG_DEBUG_INFO, scramble_bits=scramble_bits) if channel is not None: self.connect(src, channel, self.rx) else: @@ -113,6 +113,28 @@ class test_ofdm_txrx (gr_unittest.TestCase): self.assertEqual(tuple(tx_fg.tx.sync_word2), tuple(rx_fg.rx.sync_word2)) self.assertEqual(test_data, rx_data) + def test_003_tx1packet_scramble(self): + """ Same as before, use scrambler. """ + len_tag_key = 'frame_len' + n_bytes = 21 + fft_len = 64 + test_data = tuple([random.randint(0, 255) for x in range(n_bytes)]) + # 1.0/fft_len is one sub-carrier, a fine freq offset stays below that + freq_offset = 1.0 / fft_len * 0.7 + #channel = channels.channel_model(0.01, freq_offset) + channel = None + # Tx + tx_fg = ofdm_tx_fg(test_data, len_tag_key, scramble_bits=True) + tx_fg.run() + tx_samples = tx_fg.get_tx_samples() + # Rx + rx_fg = ofdm_rx_fg(tx_samples, len_tag_key, channel, prepend_zeros=100, scramble_bits=True) + rx_fg.run() + rx_data = rx_fg.get_rx_bytes() + self.assertEqual(tuple(tx_fg.tx.sync_word1), tuple(rx_fg.rx.sync_word1)) + self.assertEqual(tuple(tx_fg.tx.sync_word2), tuple(rx_fg.rx.sync_word2)) + self.assertEqual(test_data, rx_data) + def test_004_tx1packet_large_fO(self): """ Transmit one packet, with slight AWGN and large frequency offset. Check packet is received and no bit errors have occurred. """ diff --git a/gr-digital/python/digital/qa_packet_headergenerator_bb.py b/gr-digital/python/digital/qa_packet_headergenerator_bb.py index 3697bd1eb7..bec0828e4b 100755 --- a/gr-digital/python/digital/qa_packet_headergenerator_bb.py +++ b/gr-digital/python/digital/qa_packet_headergenerator_bb.py @@ -81,10 +81,10 @@ class qa_packet_headergenerator_bb (gr_unittest.TestCase): self.tb.connect(src, header, sink) self.tb.run() expected_data = ( - # | Number of symbols | Packet number | Parity - 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, - 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + # | Number of symbols | Packet number | CRC + 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, + 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, + 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1 ) self.assertEqual(sink.data(), expected_data) diff --git a/gr-digital/python/digital/qa_packet_headerparser_b.py b/gr-digital/python/digital/qa_packet_headerparser_b.py index abd23c8945..1844991bc0 100755 --- a/gr-digital/python/digital/qa_packet_headerparser_b.py +++ b/gr-digital/python/digital/qa_packet_headerparser_b.py @@ -38,13 +38,13 @@ class qa_packet_headerparser_b (gr_unittest.TestCase): """ First header: Packet length 4, packet num 0 Second header: Packet 2, packet num 1 - Third header: Invalid (parity bit does not check) (would be len 4, num 2) + Third header: Invalid (CRC does not check) (would be len 4, num 2) """ encoded_headers = ( - # | Number of bytes | Packet number | Parity - 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, - 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0 + # | Number of bytes | Packet number | CRC + 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, + 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, + 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1 ) packet_len_tagname = "packet_len" random_tag = gr.tag_t() @@ -99,9 +99,9 @@ class qa_packet_headerparser_b (gr_unittest.TestCase): 2 bits per complex symbol, 32 carriers => 64 bits = 8 bytes per OFDM symbol """ encoded_headers = ( - # | Number of bytes | Packet number | Parity - 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, - 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + # | Number of bytes | Packet number | CRC + 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, + 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, ) packet_len_tagname = "packet_len" frame_len_tagname = "frame_len" @@ -130,6 +130,40 @@ class qa_packet_headerparser_b (gr_unittest.TestCase): self.assertEqual(msg1, {'packet_len': 193*4, 'frame_len': 25, 'packet_num': 0}) self.assertEqual(msg2, {'packet_len': 8*4, 'frame_len': 1, 'packet_num': 1}) + def test_004_ofdm_scramble(self): + """ + Test scrambling for OFDM header gen + """ + header_len = 32 + packet_length = 23 + packet_len_tagname = "packet_len" + frame_len_tagname = "frame_len" + data, tags = tagged_streams.packets_to_vectors([range(packet_length),range(packet_length),], packet_len_tagname) + src = blocks.vector_source_b(data, False, 1, tags) + header_formatter = digital.packet_header_ofdm( + (range(32),), # 32 carriers are occupied (which doesn't matter here) + 1, # 1 OFDM symbol per header (= 32 bits) + packet_len_tagname, + frame_len_tagname, + "packet_num", + 1, # 1 bit per header symbols (BPSK) + 2, # 2 bits per payload symbol (QPSK) + scramble_header=True + ) + header_gen = digital.packet_headergenerator_bb(header_formatter.base()) + header_parser = digital.packet_headerparser_b(header_formatter.base()) + sink = blocks.message_debug() + self.tb.connect(src, header_gen, header_parser) + self.tb.msg_connect(header_parser, "header_data", sink, "store") + self.tb.start() + time.sleep(1) + self.tb.stop() + self.tb.wait() + msg = pmt.to_python(sink.get_message(0)) + self.assertEqual(msg, {'packet_len': packet_length, 'packet_num': 0, 'frame_len': 4}) + msg = pmt.to_python(sink.get_message(1)) + self.assertEqual(msg, {'packet_len': packet_length, 'packet_num': 1, 'frame_len': 4}) + if __name__ == '__main__': gr_unittest.run(qa_packet_headerparser_b, "qa_packet_headerparser_b.xml") diff --git a/gr-digital/python/digital/qa_scrambler.py b/gr-digital/python/digital/qa_scrambler.py index 05daebd389..4d35879b1f 100755 --- a/gr-digital/python/digital/qa_scrambler.py +++ b/gr-digital/python/digital/qa_scrambler.py @@ -21,6 +21,7 @@ # from gnuradio import gr, gr_unittest, digital, blocks +import pmt class test_scrambler(gr_unittest.TestCase): @@ -60,5 +61,42 @@ class test_scrambler(gr_unittest.TestCase): self.tb.run() self.assertEqual(src_data, dst.data()) + def test_additive_scrambler_reset_3bpb(self): + src_data = (5,)*2000 + src = blocks.vector_source_b(src_data, False) + scrambler = digital.additive_scrambler_bb(0x8a, 0x7f, 7, 100, 3) + descrambler = digital.additive_scrambler_bb(0x8a, 0x7f, 7, 100, 3) + dst = blocks.vector_sink_b() + dst2 = blocks.vector_sink_b() + self.tb.connect(src, scrambler, descrambler, dst) + self.tb.connect(scrambler, dst2) + self.tb.run() + if not (src_data == dst.data()): + self.fail('Not equal.') + self.assertEqual(src_data, src_data) + + def test_additive_scrambler_tags(self): + src_data = (1,)*1000 + src = blocks.vector_source_b(src_data, False) + scrambler = digital.additive_scrambler_bb(0x8a, 0x7f, 7, 100) + descrambler = digital.additive_scrambler_bb(0x8a, 0x7f, 7, 100) + reset_tag_key = 'reset_lfsr' + reset_tag1 = gr.tag_t() + reset_tag1.key = pmt.string_to_symbol(reset_tag_key) + reset_tag1.offset = 17 + reset_tag2 = gr.tag_t() + reset_tag2.key = pmt.string_to_symbol(reset_tag_key) + reset_tag2.offset = 110 + reset_tag3 = gr.tag_t() + reset_tag3.key = pmt.string_to_symbol(reset_tag_key) + reset_tag3.offset = 523 + src = blocks.vector_source_b(src_data, False, 1, (reset_tag1, reset_tag2, reset_tag3)) + scrambler = digital.additive_scrambler_bb(0x8a, 0x7f, 7, 100, 1, reset_tag_key) + descrambler = digital.additive_scrambler_bb(0x8a, 0x7f, 7, 100, 1, reset_tag_key) + dst = blocks.vector_sink_b() + self.tb.connect(src, scrambler, descrambler, dst) + self.tb.run() + self.assertEqual(src_data, dst.data()) + if __name__ == '__main__': gr_unittest.run(test_scrambler, "test_scrambler.xml") diff --git a/gr-digital/python/digital/qam_constellations.py b/gr-digital/python/digital/qam_constellations.py new file mode 100755 index 0000000000..4e8ee08a61 --- /dev/null +++ b/gr-digital/python/digital/qam_constellations.py @@ -0,0 +1,521 @@ +#!/usr/bin/env python +# +# Copyright 2013 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 numpy +from constellation_map_generator import * + +''' +Note on the naming scheme. Each constellation is named using a prefix +for the type of constellation, the order of the constellation, and a +distinguishing feature, which comes in three modes: + +- No extra feature: the basic Gray-coded constellation map; others + will be derived from this type. +- A single number: an indexed number to uniquely identify different + constellation maps. +- 0xN_x0_x1..._xM: A permutation of the base constellation, explained + below. + +For rectangular constellations (BPSK, QPSK, QAM), we can define a +hyperspace and look for all symmetries. This is also known as the +automorphism group of the hypercube, aka the hyperoctahedral +group. What this means is that we can easily define all possible +rotations in terms of the first base mapping by creating the mapping: + + f(x) = k XOR pi(x) + +The x is the bit string for the symbol we are altering. Then k is a +bit string of n bits where n is the number of bits per symbol in the +constellation (e.g., 2 for QPSK or 6 for QAM64). The pi is a +permutation function specified as pi_0, pi_1..., pi_n-1. This permutes +the bits from the base constellation symbol to a new code, which is +then xor'd by k. + +The value of k is from 0 to 2^n-1 and pi is a list of all bit +positions. + +The permutation are given for b0_b1_b2_... for the total number of +bits. In the constellation diagrams shown in the comments, the bit +ordering is shown as [b3b2b1b0]. Bit values returned from the soft bit +LUTs are in the order [b3, b2, b1, b0]. + + +The total number of Gray coded modulations is (2^n)*(n!). + +We create aliases for all possible naming schemes for the +constellations. So if a hyperoctahedral group is defined, we also set +this function equal to a function name using a unique ID number, and +we always select one rotation as our basic rotation that the other +rotations are based off of. + +For 16QAM: + - n = 4 + - (2^n)*(n!) = 384 + - k \in [0x0, 0xF] + - pi = 0, 1, 2, 3 + 0, 1, 3, 2 + 0, 2, 1, 3 + 0, 2, 3, 1 + 0, 3, 1, 2 + 0, 3, 2, 1 + 1, 0, 2, 3 + 1, 0, 3, 2 + 1, 2, 0, 3 + 1, 2, 3, 0 + 1, 3, 0, 2 + 1, 3, 2, 0 + 2, 0, 1, 3 + 2, 0, 3, 1 + 2, 1, 0, 3 + 2, 1, 3, 0 + 2, 3, 0, 1 + 2, 3, 1, 0 + 3, 0, 1, 2 + 3, 0, 2, 1 + 3, 1, 0, 2 + 3, 1, 2, 0 + 3, 2, 0, 1 + 3, 2, 1, 0 +''' + +def qam_16_0x0_0_1_2_3(): + ''' + 0010 0110 | 1110 1010 + + 0011 0111 | 1111 1011 + ----------------------- + 0001 0101 | 1101 1001 + + 0000 0100 | 1100 1000 + ''' + const_points = [-3-3j, -1-3j, 1-3j, 3-3j, + -3-1j, -1-1j, 1-1j, 3-1j, + -3+1j, -1+1j, 1+1j, 3+1j, + -3+3j, -1+3j, 1+3j, 3+3j] + symbols = [0x0, 0x4, 0xC, 0x8, + 0x1, 0x5, 0xD, 0x9, + 0x3, 0x7, 0xF, 0xB, + 0x2, 0x6, 0xE, 0xA] + return (const_points, symbols) +qam_16 = qam_16_0x0_0_1_2_3 +qam_16_0 = qam_16 + +def qam_16_0x1_0_1_2_3(): + ''' + 0011 0111 | 1111 1011 + + 0010 0110 | 1110 1010 + ----------------------- + 0000 0100 | 1100 1000 + + 0001 0101 | 1101 1001 + ''' + k = 0x1 + pi = [0, 1, 2, 3] + return constellation_map_generator(qam_16, k, pi) +qam_16_1 = qam_16_0x1_0_1_2_3 + +def qam_16_0x2_0_1_2_3(): + ''' + 0000 0100 | 1100 1000 + + 0001 0101 | 1101 1001 + ----------------------- + 0011 0111 | 1111 1011 + + 0010 0110 | 1110 1010 + ''' + k = 0x2 + pi = [0, 1, 2, 3] + return constellation_map_generator(qam_16, k, pi) +qam_16_2 = qam_16_0x2_0_1_2_3 + +def qam_16_0x3_0_1_2_3(): + ''' + 0001 0101 | 1101 1001 + + 0000 0100 | 1100 1000 + ----------------------- + 0010 0110 | 1110 1010 + + 0011 0111 | 1111 1011 + ''' + k = 0x3 + pi = [0, 1, 2, 3] + return constellation_map_generator(qam_16, k, pi) +qam_16_3 = qam_16_0x3_0_1_2_3 + + +def qam_16_0x0_1_0_2_3(): + ''' + 0001 0101 | 1101 1001 + + 0011 0111 | 1111 1011 + ----------------------- + 0010 0110 | 1110 1010 + + 0000 0100 | 1100 1000 + ''' + k = 0x0 + pi = [1, 0, 2, 3] + return constellation_map_generator(qam_16, k, pi) +qam_16_4 = qam_16_0x0_1_0_2_3 + +def qam_16_0x1_1_0_2_3(): + ''' + 0000 0100 | 1100 1000 + + 0010 0110 | 1110 1010 + ----------------------- + 0011 0111 | 1111 1011 + + 0001 0101 | 1101 1001 + ''' + k = 0x1 + pi = [1, 0, 2, 3] + return constellation_map_generator(qam_16, k, pi) +qam_16_5 = qam_16_0x1_1_0_2_3 + +def qam_16_0x2_1_0_2_3(): + ''' + 0011 0111 | 1111 1011 + + 0001 0101 | 1101 1001 + ----------------------- + 0000 0100 | 1100 1000 + + 0010 0110 | 1110 1010 + ''' + k = 0x2 + pi = [1, 0, 2, 3] + return constellation_map_generator(qam_16, k, pi) +qam_16_6 = qam_16_0x2_1_0_2_3 + +def qam_16_0x3_1_0_2_3(): + ''' + 0010 0110 | 1110 1010 + + 0000 0100 | 1100 1000 + ----------------------- + 0001 0101 | 1101 1001 + + 0011 0111 | 1111 1011 + ''' + k = 0x3 + pi = [1, 0, 2, 3] + return constellation_map_generator(qam_16, k, pi) +qam_16_7 = qam_16_0x3_1_0_2_3 + + +# Soft bit LUT generators + +def sd_qam_16_0x0_0_1_2_3(x, Es=1): + ''' + Soft bit LUT generator for constellation: + + 0010 0110 | 1110 1010 + + 0011 0111 | 1111 1011 + ----------------------- + 0001 0101 | 1101 1001 + + 0000 0100 | 1100 1000 + ''' + + dist = Es*numpy.sqrt(2) + boundary = dist/3.0 + dist0 = dist/6.0 +# print "Sample: ", x +# print "Es: ", Es +# print "Distance: ", dist +# print "Boundary: ", boundary +# print "1st Bound: ", dist0 + + x_re = x.real + x_im = x.imag + + if x_re < -boundary: + b3 = boundary*(x_re + dist0) + elif x_re < boundary: + b3 = x_re + else: + b3 = boundary*(x_re - dist0) + + if x_im < -boundary: + b1 = boundary*(x_im + dist0) + elif x_im < boundary: + b1 = x_im + else: + b1 = boundary*(x_im - dist0) + + b2 = -abs(x_re) + boundary + b0 = -abs(x_im) + boundary + + return [(Es/2)*b3, (Es/2)*b2, (Es/2)*b1, (Es/2)*b0] +sd_qam_16 = sd_qam_16_0x0_0_1_2_3 +sd_qam_16_0 = sd_qam_16 + +def sd_qam_16_0x1_0_1_2_3(x, Es=1): + ''' + Soft bit LUT generator for constellation: + + 0011 0111 | 1111 1011 + + 0010 0110 | 1110 1010 + ----------------------- + 0000 0100 | 1100 1000 + + 0001 0101 | 1101 1001 + ''' + x_re = 3*x.real + x_im = 3*x.imag + + if x_re < -2: + b3 = 2*(x_re + 1) + elif x_re < 2: + b3 = x_re + else: + b3 = 2*(x_re - 1) + + if x_im < -2: + b1 = 2*(x_im + 1) + elif x_im < 2: + b1 = x_im + else: + b1 = 2*(x_im - 1) + + b2 = -abs(x_re) + 2 + b0 = +abs(x_im) - 2 + + return [b3, b2, b1, b0] +sd_qam_16_1 = sd_qam_16_0x1_0_1_2_3 + +def sd_qam_16_0x2_0_1_2_3(x, Es=1): + ''' + Soft bit LUT generator for constellation: + + 0000 0100 | 1100 1000 + + 0001 0101 | 1101 1001 + ----------------------- + 0011 0111 | 1111 1011 + + 0010 0110 | 1110 1010 + ''' + + x_re = 3*x.real + x_im = 3*x.imag + + if x_re < -2: + b3 = 2*(x_re + 1) + elif x_re < 2: + b3 = x_re + else: + b3 = 2*(x_re - 1) + + if x_im < -2: + b1 = -2*(x_im + 1) + elif x_im < 2: + b1 = -x_im + else: + b1 = -2*(x_im - 1) + + b2 = -abs(x_re) + 2 + b0 = -abs(x_im) + 2 + + return [b3, b2, b1, b0] +sd_qam_16_2 = sd_qam_16_0x2_0_1_2_3 + +def sd_qam_16_0x3_0_1_2_3(x, Es=1): + ''' + Soft bit LUT generator for constellation: + + 0001 0101 | 1101 1001 + + 0000 0100 | 1100 1000 + ----------------------- + 0010 0110 | 1110 1010 + + 0011 0111 | 1111 1011 + ''' + x_re = 3*x.real + x_im = 3*x.imag + + if x_re < -2: + b3 = 2*(x_re + 1) + elif x_re < 2: + b3 = x_re + else: + b3 = 2*(x_re - 1) + + if x_im < -2: + b1 = -2*(x_im + 1) + elif x_im < 2: + b1 = -x_im + else: + b1 = -2*(x_im - 1) + + b2 = -abs(x_re) + 2 + b0 = +abs(x_im) - 2 + + return [b3, b2, b1, b0] +sd_qam_16_3 = sd_qam_16_0x3_0_1_2_3 + +def sd_qam_16_0x0_1_0_2_3(x, Es=1): + ''' + Soft bit LUT generator for constellation: + + 0001 0101 | 1101 1001 + + 0011 0111 | 1111 1011 + ----------------------- + 0010 0110 | 1110 1010 + + 0000 0100 | 1100 1000 + ''' + x_re = 3*x.real + x_im = 3*x.imag + + if x_re < -2: + b3 = 2*(x_re + 1) + elif x_re < 2: + b3 = x_re + else: + b3 = 2*(x_re - 1) + + if x_im < -2: + b0 = 2*(x_im + 1) + elif x_im < 2: + b0 = x_im + else: + b0 = 2*(x_im - 1) + + b2 = -abs(x_re) + 2 + b1 = -abs(x_im) + 2 + + return [b3, b2, b1, b0] +sd_qam_16_4 = sd_qam_16_0x0_1_0_2_3 + +def sd_qam_16_0x1_1_0_2_3(x, Es=1): + ''' + Soft bit LUT generator for constellation: + + 0000 0100 | 1100 1000 + + 0010 0110 | 1110 1010 + ----------------------- + 0011 0111 | 1111 1011 + + 0001 0101 | 1101 1001 + ''' + x_re = 3*x.real + x_im = 3*x.imag + + if x_re < -2: + b3 = 2*(x_re + 1) + elif x_re < 2: + b3 = x_re + else: + b3 = 2*(x_re - 1) + + if x_im < -2: + b0 = -2*(x_im + 1) + elif x_im < 2: + b0 = -x_im + else: + b0 = -2*(x_im - 1) + + b2 = -abs(x_re) + 2 + b1 = -abs(x_im) + 2 + + return [b3, b2, b1, b0] +sd_qam_16_5 = sd_qam_16_0x1_1_0_2_3 + +def sd_qam_16_0x2_1_0_2_3(x, Es=1): + ''' + Soft bit LUT generator for constellation: + + 0011 0111 | 1111 1011 + + 0001 0101 | 1101 1001 + ----------------------- + 0000 0100 | 1100 1000 + + 0010 0110 | 1110 1010 + ''' + x_re = 3*x.real + x_im = 3*x.imag + + if x_re < -2: + b3 = 2*(x_re + 1) + elif x_re < 2: + b3 = x_re + else: + b3 = 2*(x_re - 1) + + if x_im < -2: + b0 = 2*(x_im + 1) + elif x_im < 2: + b0 = x_im + else: + b0 = 2*(x_im - 1) + + b2 = -abs(x_re) + 2 + b1 = +abs(x_im) - 2 + + return [b3, b2, b1, b0] +sd_qam_16_6 = sd_qam_16_0x2_1_0_2_3 + +def sd_qam_16_0x3_1_0_2_3(x, Es=1): + ''' + Soft bit LUT generator for constellation: + + 0010 0110 | 1110 1010 + + 0000 0100 | 1100 1000 + ----------------------- + 0001 0101 | 1101 1001 + + 0011 0111 | 1111 1011 + ''' + x_re = 3*x.real + x_im = 3*x.imag + + if x_re < -2: + b3 = 2*(x_re + 1) + elif x_re < 2: + b3 = x_re + else: + b3 = 2*(x_re - 1) + + if x_im < -2: + b0 = -2*(x_im + 1) + elif x_im < 2: + b0 = -x_im + else: + b0 = -2*(x_im - 1) + + b2 = -abs(x_re) + 2 + b1 = +abs(x_im) - 2 + + return [b3, b2, b1, b0] +sd_qam_16_7 = sd_qam_16_0x3_1_0_2_3 diff --git a/gr-digital/python/digital/soft_dec_lut_gen.py b/gr-digital/python/digital/soft_dec_lut_gen.py new file mode 100644 index 0000000000..24d8bbdc2e --- /dev/null +++ b/gr-digital/python/digital/soft_dec_lut_gen.py @@ -0,0 +1,232 @@ +#!/usr/bin/env python +# +# Copyright 2013 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 numpy + +def soft_dec_table_generator(soft_dec_gen, prec, Es=1): + ''' + Builds a LUT that is a list of tuples. The tuple represents the + soft decisions for the constellation/bit mapping at any given + point in the complex space, (x,y). + + The table is built to a precision specified by the 'prec' + argument. There are (2x2)^prec samples in the sample space, so we + get the precision of 2^prec samples in both the real and imaginary + axes. + + The space is represented where index 0 is the bottom left corner + and the maximum index is the upper left. The table index for a + surface space with 4 bits of precision looks like the following: + + 240 241 242 243 244 245 246 247 | 248 249 250 251 252 253 254 255 + 224 225 226 227 228 229 230 231 | 232 233 234 235 236 237 238 239 + 208 209 210 211 212 213 214 215 | 216 217 218 219 220 221 222 223 + 192 193 194 195 196 197 198 199 | 200 201 202 203 204 205 206 207 + 176 177 178 179 180 181 182 183 | 184 185 186 187 188 189 190 191 + 160 161 162 163 164 165 166 167 | 168 169 170 171 172 173 174 175 + 144 145 146 147 148 149 150 151 | 152 153 154 155 156 157 158 159 + 128 129 130 131 132 133 134 135 | 136 137 138 139 140 141 142 143 + ----------------------------------------------------------------- + 112 113 114 115 116 117 118 119 | 120 121 122 123 124 125 126 127 + 96 97 98 99 100 101 102 103 | 104 105 106 107 108 109 110 111 + 80 81 82 83 84 85 86 87 | 88 89 90 91 92 93 94 95 + 64 65 66 67 68 69 70 71 | 72 73 74 75 76 77 78 79 + 48 49 50 51 52 53 54 55 | 56 57 58 59 60 61 62 63 + 32 33 34 35 36 37 38 39 | 40 41 42 43 44 45 46 47 + 16 17 18 19 20 21 22 23 | 24 25 26 27 28 29 30 31 + 0 1 2 3 4 5 6 7 | 8 9 10 11 12 13 14 15 + + We then calculate coordinates from -1 to 1 with 2^prec points for + both the x and y axes. We then sample starting at (-1, -1) and + move left to right on the x-axis and then move up a row on the + y-axis. For every point in this sampled space, we calculate the + soft decisions for the given constellation/mapping. This is done + by passing in the function 'soft_dec_gen' as an argument to this + function. This takes in the x/y coordinates and outputs the soft + decisions. These soft decisions are stored into the list at the + index from the above table as a tuple. + + The function 'calc_from_table' takes in a point and reverses this + operation. It converts the point from the coordinates (-1,-1) to + (1,1) into an index value in the table and returns the tuple of + soft decisions at that index. + + Es is the energy per symbol. This is passed to the function to + provide the bounds when calling the generator function since they + don't know how the constellation was normalized. Using the + (maximum) energy per symbol for constellation allows us to provide + any scaling of the constellation (normalized to sum to 1, + normalized so the outside points sit on +/-1, etc.) but still + calculate the soft decisions as we would given the full + constellation. + ''' + + npts = 2.0**prec + maxd = Es*numpy.sqrt(2)/2 + yrng = numpy.linspace(-maxd, maxd, npts) + xrng = numpy.linspace(-maxd, maxd, npts) + + table = [] + for y in yrng: + for x in xrng: + pt = complex(x, y) + decs = soft_dec_gen(pt, Es) + table.append(decs) + return table + +def soft_dec_table(constel, symbols, prec, npwr=1): + ''' + Similar in nature to soft_dec_table_generator above. Instead, this + takes in the constellation and symbol points along with the noise + power estimate and uses calc_soft_dec (below) to generate the + LUT. + + Instead of assuming that the constellation is normalied (e.g., all + points are between -1 and 1), this function calculates the min/max + of both the real and imaginary axes and uses those when + constructing the LUT. So when using this version of the LUT, the + samples and the constellations must be working on the same + magnitudes. + + Because this uses the calc_soft_dec function, it can be quite + a bit more expensive to generate the LUT, though it should be + one-time work. + ''' + + re_min = min(numpy.array(constel).real) + im_min = min(numpy.array(constel).imag) + re_max = max(numpy.array(constel).real) + im_max = max(numpy.array(constel).imag) + + npts = 2.0**prec + yrng = numpy.linspace(im_min, im_max, npts) + xrng = numpy.linspace(re_min, re_max, npts) + + table = [] + for y in yrng: + for x in xrng: + pt = complex(x, y) + decs = calc_soft_dec(pt, constel, symbols, npwr) + table.append(decs) + return table + +def calc_soft_dec_from_table(sample, table, prec, Es=1): + ''' + Takes in a complex sample and converts it from the coordinates + (-1,-1) to (1,1) into an index value. The index value points to a + location in the provided LUT 'table' and returns the soft + decisions tuple at that index. + + sample: the complex sample to calculate the soft decisions + from. + + table: the LUT. + + prec: the precision used when generating the LUT. + + Es: the energy per symbol. This is passed to the function to + provide the bounds when calling the generator function since they + don't know how the constellation was normalized. Using the + (maximum) energy per symbol for constellation allows us to provide + any scaling of the constellation (normalized to sum to 1, + normalized so the outside points sit on +/-1, etc.) but still + calculate the soft decisions as we would given the full + constellation. + ''' + lut_scale = 2**prec + maxd = Es*numpy.sqrt(2)/2 + step = 2*maxd / lut_scale + scale = (lut_scale) / (2*maxd) - step + + xre = sample.real + xim = sample.imag + xre = int((maxd + min(maxd, max(-maxd, xre))) * scale) + xim = int((maxd + min(maxd, max(-maxd, xim))) * scale) + index = int(xre + lut_scale*xim) + + max_index = lut_scale**2 + if(index > max_index): + return table[0]; + + if(index < 0): + raise RuntimeError("calc_from_table: input sample out of range.") + + return table[index] + +def calc_soft_dec(sample, constel, symbols, npwr=1): + ''' + This function takes in any consteallation and symbol symbol set + (where symbols[i] is the set of bits at constellation point + constel[i] and an estimate of the noise power and produces the + soft decisions for the given sample. + + If known, the noise power of the received sample may be passed in + to this function as npwr. + + This is an incredibly costly algorthm because it must calculate + the Euclidean distance between the sample and all points in the + constellation to build up its probability + calculations. Conversely, it should work for any given + constellation/symbol map. + + The function returns a vector of k soft decisions. Decisions less + than 0 are more likely to indicate a '0' bit and decisions greater + than 0 are more likely to indicate a '1' bit. + ''' + + M = len(constel) + k = int(numpy.log2(M)) + tmp = 2*k*[0,] + s = k*[0,] + + # Find a scaling factor for the constellation, however it was normalized. + constel = numpy.array(constel) + scale = min(min(abs(constel.real)), min(abs(constel.imag))) + + for i in range(M): + # Calculate the distance between the sample and the current + # constellation point. + dist = abs(sample - constel[i])**2 + + # Calculate the probability factor from the distance and the + # scaled noise power. + d = numpy.exp(-dist/(2*npwr*scale**2)) + + for j in range(k): + # Get the bit at the jth index + mask = 1<<j + bit = (symbols[i] & mask) >> j + + # If the bit is a 0, add to the probability of a zero + if(bit == 0): + tmp[2*j+0] += d + # else, add to the probability of a one + else: + tmp[2*j+1] += d + + # Calculate the log-likelihood ratio for all bits based on the + # probability of ones (tmp[2*i+1]) over the probability of a zero + # (tmp[2*i+0]). + for i in range(k): + s[k-1-i] = (numpy.log(tmp[2*i+1]) - numpy.log(tmp[2*i+0])) * scale**2 + + return s diff --git a/gr-digital/python/digital/test_soft_decisions.py b/gr-digital/python/digital/test_soft_decisions.py new file mode 100755 index 0000000000..78714100b7 --- /dev/null +++ b/gr-digital/python/digital/test_soft_decisions.py @@ -0,0 +1,135 @@ +#!/usr/bin/env python +# +# Copyright 2013 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 numpy, pylab, sys +from gnuradio import digital +from soft_dec_lut_gen import * +from psk_constellations import * +from qam_constellations import * + +def test_qpsk(i, sample, prec): + qpsk_const_list = [psk_4_0, psk_4_1, psk_4_2, psk_4_3, + psk_4_4, psk_4_5, psk_4_6, psk_4_7] + qpsk_lut_gen_list = [sd_psk_4_0, sd_psk_4_1, sd_psk_4_2, sd_psk_4_3, + sd_psk_4_4, sd_psk_4_5, sd_psk_4_6, sd_psk_4_7] + + constel, code = qpsk_const_list[i]() + qpsk_lut_gen = qpsk_lut_gen_list[i] + + rot_sym = 1 + side = 2 + width = 2 + c = digital.constellation_rect(constel, code, rot_sym, + side, side, width, width) + + # Get max energy/symbol in constellation + constel = c.points() + Es = max([numpy.sqrt(constel_i.real**2 + constel_i.imag**2) for constel_i in constel]) + + #table = soft_dec_table_generator(qpsk_lut_gen, prec, Es) + table = soft_dec_table(constel, code, prec) + + c.gen_soft_dec_lut(prec) + #c.set_soft_dec_lut(table, prec) + + y_python_gen_calc = qpsk_lut_gen(sample, Es) + y_python_table = calc_soft_dec_from_table(sample, table, prec, Es) + y_python_raw_calc = calc_soft_dec(sample, constel, code) + y_cpp_table = c.soft_decision_maker(sample) + y_cpp_raw_calc = c.calc_soft_dec(sample) + + return (y_python_gen_calc, y_python_table, y_python_raw_calc, + y_cpp_table, y_cpp_raw_calc, constel, code, c) + +def test_qam16(i, sample, prec): + sample = sample/1 + qam_const_list = [qam_16_0, ] + qam_lut_gen_list = [sd_qam_16_0, ] + + constel, code = qam_const_list[i]() + qam_lut_gen = qam_lut_gen_list[i] + + rot_sym = 4 + side = 2 + width = 2 + c = digital.constellation_rect(constel, code, rot_sym, + side, side, width, width) + + # Get max energy/symbol in constellation + constel = c.points() + Es = max([abs(constel_i) for constel_i in constel]) + + #table = soft_dec_table_generator(qam_lut_gen, prec, Es) + table = soft_dec_table(constel, code, prec, 1) + + #c.gen_soft_dec_lut(prec) + c.set_soft_dec_lut(table, prec) + + y_python_gen_calc = qam_lut_gen(sample, Es) + y_python_table = calc_soft_dec_from_table(sample, table, prec, Es) + y_python_raw_calc = calc_soft_dec(sample, constel, code, 1) + y_cpp_table = c.soft_decision_maker(sample) + y_cpp_raw_calc = c.calc_soft_dec(sample) + + return (y_python_gen_calc, y_python_table, y_python_raw_calc, + y_cpp_table, y_cpp_raw_calc, constel, code, c) + +if __name__ == "__main__": + + index = 0 + prec = 8 + + x_re = 2*numpy.random.random()-1 + x_im = 2*numpy.random.random()-1 + x = x_re + x_im*1j + #x = -1 + -0.j + + if 1: + y_python_gen_calc, y_python_table, y_python_raw_calc, \ + y_cpp_table, y_cpp_raw_calc, constel, code, c \ + = test_qpsk(index, x, prec) + else: + y_python_gen_calc, y_python_table, y_python_raw_calc, \ + y_cpp_table, y_cpp_raw_calc, constel, code, c \ + = test_qam16(index, x, prec) + + k = numpy.log2(len(constel)) + + print "Sample: ", x + print "Python Generator Calculated: ", (y_python_gen_calc) + print "Python Generator Table: ", (y_python_table) + print "Python Raw calc: ", (y_python_raw_calc) + print "C++ Table calc: ", (y_cpp_table) + print "C++ Raw calc: ", (y_cpp_raw_calc) + + fig = pylab.figure(1) + sp1 = fig.add_subplot(1,1,1) + sp1.plot([c.real for c in constel], + [c.imag for c in constel], 'bo') + sp1.plot(x.real, x.imag, 'ro') + sp1.set_xlim([-1.5, 1.5]) + sp1.set_ylim([-1.5, 1.5]) + fill = int(numpy.log2(len(constel))) + for i,c in enumerate(constel): + sp1.text(1.2*c.real, 1.2*c.imag, bin(code[i])[2:].zfill(fill), + ha='center', va='center', size=18) + pylab.show() diff --git a/gr-digital/swig/digital_swig.i b/gr-digital/swig/digital_swig.i index fb0b97aa11..b16200c2f6 100644 --- a/gr-digital/swig/digital_swig.i +++ b/gr-digital/swig/digital_swig.i @@ -51,6 +51,7 @@ #include "gnuradio/digital/constellation.h" #include "gnuradio/digital/constellation_decoder_cb.h" #include "gnuradio/digital/constellation_receiver_cb.h" +#include "gnuradio/digital/constellation_soft_decoder_cf.h" #include "gnuradio/digital/correlate_access_code_bb.h" #include "gnuradio/digital/correlate_access_code_tag_bb.h" #include "gnuradio/digital/costas_loop_cc.h" @@ -120,6 +121,7 @@ %include "gnuradio/digital/constellation.h" %include "gnuradio/digital/constellation_decoder_cb.h" %include "gnuradio/digital/constellation_receiver_cb.h" +%include "gnuradio/digital/constellation_soft_decoder_cf.h" %include "gnuradio/digital/correlate_access_code_bb.h" %include "gnuradio/digital/correlate_access_code_tag_bb.h" %include "gnuradio/digital/costas_loop_cc.h" @@ -184,6 +186,7 @@ GR_SWIG_BLOCK_MAGIC2(digital, clock_recovery_mm_ff); GR_SWIG_BLOCK_MAGIC2(digital, cma_equalizer_cc); GR_SWIG_BLOCK_MAGIC2(digital, constellation_decoder_cb); GR_SWIG_BLOCK_MAGIC2(digital, constellation_receiver_cb); +GR_SWIG_BLOCK_MAGIC2(digital, constellation_soft_decoder_cf); GR_SWIG_BLOCK_MAGIC2(digital, correlate_access_code_bb); GR_SWIG_BLOCK_MAGIC2(digital, correlate_access_code_tag_bb); GR_SWIG_BLOCK_MAGIC2(digital, costas_loop_cc); diff --git a/gr-uhd/apps/uhd_fft b/gr-uhd/apps/uhd_fft index 41da61aca3..9edd75288f 100755 --- a/gr-uhd/apps/uhd_fft +++ b/gr-uhd/apps/uhd_fft @@ -200,12 +200,12 @@ class app_top_block(stdgui2.std_top_block): callback=self.set_gain) try: - mboard_id = self.u.get_usrp_info().get("mboard_id") - mboard_serial = self.u.get_usrp_info().get("mboard_serial") + mboard_id = self.u.get_usrp_info()["mboard_id"] + mboard_serial = self.u.get_usrp_info()["mboard_serial"] if mboard_serial == "": mboard_serial = "no serial" - dboard_subdev_name = self.u.get_usrp_info().get("rx_subdev_name") - dboard_serial = self.u.get_usrp_info().get("rx_serial") + dboard_subdev_name = self.u.get_usrp_info()["rx_subdev_name"] + dboard_serial = self.u.get_usrp_info()["rx_serial"] if dboard_serial == "": dboard_serial = "no serial" subdev = self.u.get_subdev_spec() diff --git a/gr-uhd/apps/uhd_rx_cfile b/gr-uhd/apps/uhd_rx_cfile index 9f5ef19893..d727d8752a 100755 --- a/gr-uhd/apps/uhd_rx_cfile +++ b/gr-uhd/apps/uhd_rx_cfile @@ -95,19 +95,19 @@ class rx_cfile_block(gr.top_block): try: info = self._u.get_usrp_info() - mboard_id = info.get("mboard_id").split(" ")[0] - if info.get("mboard_serial") == "": + mboard_id = info["mboard_id"].split(" ")[0] + if info["mboard_serial"] == "": mboard_serial = "no serial" else: - mboard_serial = info.get("mboard_serial") + mboard_serial = info["mboard_serial"] - rx_id = info.get("rx_id").split(" ")[0] - if info.get("rx_serial") == "": + rx_id = info["rx_id"].split(" ")[0] + if info["rx_serial"] == "": rx_serial = "no serial" else: - rx_serial = info.get("rx_serial") - rx_antenna = info.get("rx_antenna") - rx_subdev_spec = info.get("rx_subdev_spec") + rx_serial = info["rx_serial"] + rx_antenna = info["rx_antenna"] + rx_subdev_spec = info["rx_subdev_spec"] print "Motherboard: %s (%s)" % (mboard_id, mboard_serial) if "B200" in mboard_id or "B210" in mboard_id: diff --git a/gr-uhd/apps/uhd_siggen_base.py b/gr-uhd/apps/uhd_siggen_base.py index 84dff1f504..0245c007b7 100644 --- a/gr-uhd/apps/uhd_siggen_base.py +++ b/gr-uhd/apps/uhd_siggen_base.py @@ -112,12 +112,12 @@ class top_block(gr.top_block, pubsub): # Setup USRP Configuration value try: usrp_info = self._u.get_usrp_info() - mboard_id = usrp_info.get("mboard_id") - mboard_serial = usrp_info.get("mboard_serial") + mboard_id = usrp_info["mboard_id"] + mboard_serial = usrp_info["mboard_serial"] if mboard_serial == "": mboard_serial = "no serial" - dboard_subdev_name = usrp_info.get("tx_subdev_name") - dboard_serial = usrp_info.get("tx_serial") + dboard_subdev_name = usrp_info["tx_subdev_name"] + dboard_serial = usrp_info["tx_serial"] if dboard_serial == "": dboard_serial = "no serial" subdev = self._u.get_subdev_spec() diff --git a/gr-uhd/swig/uhd_swig.i b/gr-uhd/swig/uhd_swig.i index de5b8c2dad..c98416f307 100644 --- a/gr-uhd/swig/uhd_swig.i +++ b/gr-uhd/swig/uhd_swig.i @@ -64,6 +64,11 @@ %include <uhd/types/dict.hpp> %template(string_string_dict_t) uhd::dict<std::string, std::string>; //define after dict +%extend uhd::dict<std::string, std::string>{ + std::string __getitem__(std::string key) {return (*self)[key];} + void __setitem__(std::string key, std::string val) {(*self)[key] = val;} +}; + %include <uhd/types/device_addr.hpp> %include <uhd/types/io_type.hpp> diff --git a/gr-utils/python/modtool/gr-newmod/CMakeLists.txt b/gr-utils/python/modtool/gr-newmod/CMakeLists.txt index 7ff80ff7ac..2dac3461a8 100644 --- a/gr-utils/python/modtool/gr-newmod/CMakeLists.txt +++ b/gr-utils/python/modtool/gr-newmod/CMakeLists.txt @@ -146,3 +146,10 @@ add_subdirectory(python) add_subdirectory(grc) add_subdirectory(apps) add_subdirectory(docs) + +######################################################################## +# Install cmake search helper for this library +######################################################################## +install(FILES cmake/Modules/howtoConfig.cmake + DESTINATION lib/cmake/howto +) diff --git a/gr-utils/python/modtool/gr-newmod/cmake/Modules/howtoConfig.cmake b/gr-utils/python/modtool/gr-newmod/cmake/Modules/howtoConfig.cmake new file mode 100644 index 0000000000..329a007608 --- /dev/null +++ b/gr-utils/python/modtool/gr-newmod/cmake/Modules/howtoConfig.cmake @@ -0,0 +1,30 @@ +INCLUDE(FindPkgConfig) +PKG_CHECK_MODULES(PC_HOWTO howto) + +FIND_PATH( + HOWTO_INCLUDE_DIRS + NAMES howto/api.h + HINTS $ENV{HOWTO_DIR}/include + ${PC_HOWTO_INCLUDEDIR} + PATHS ${CMAKE_INSTALL_PREEFIX}/include + /usr/local/include + /usr/include +) + +FIND_LIBRARY( + HOWTO_LIBRARIES + NAMES gnuradio-howto + HINTS $ENV{HOWTO_DIR}/lib + ${PC_HOWTO_LIBDIR} + PATHS ${CMAKE_INSTALL_PREFIX}/lib + ${CMAKE_INSTALL_PREFIX}/lib64 + /usr/local/lib + /usr/local/lib64 + /usr/lib + /usr/lib64 +) + +INCLUDE(FindPackageHandleStandardArgs) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(HOWTO DEFAULT_MSG HOWTO_LIBRARIES HOWTO_INCLUDE_DIRS) +MARK_AS_ADVANCED(HOWTO_LIBRARIES HOWTO_INCLUDE_DIRS) + diff --git a/gr-utils/python/modtool/gr-newmod/examples/README b/gr-utils/python/modtool/gr-newmod/examples/README new file mode 100644 index 0000000000..c012bdfa0a --- /dev/null +++ b/gr-utils/python/modtool/gr-newmod/examples/README @@ -0,0 +1,4 @@ +It is considered good practice to add examples in here to demonstrate the +functionality of your OOT module. Python scripts, GRC flow graphs or other +code can go here. + diff --git a/gr-utils/python/modtool/modtool_add.py b/gr-utils/python/modtool/modtool_add.py index 10f89c569d..60748e3f1b 100644 --- a/gr-utils/python/modtool/modtool_add.py +++ b/gr-utils/python/modtool/modtool_add.py @@ -193,6 +193,7 @@ class ModToolAdd(ModTool): Cheetah.Template.Template( Templates['qa_cmakeentry36'], searchList={'basename': os.path.splitext(fname_qa_cc)[0], + 'upperbasename': os.path.splitext(fname_qa_cc)[0].upper(), 'filename': fname_qa_cc, 'modname': self._info['modname'] } diff --git a/gr-utils/python/modtool/modtool_base.py b/gr-utils/python/modtool/modtool_base.py index 577985b6f3..f8fc8639c4 100644 --- a/gr-utils/python/modtool/modtool_base.py +++ b/gr-utils/python/modtool/modtool_base.py @@ -125,6 +125,7 @@ class ModTool(object): self._info['includedir'] = 'include' self._file['cminclude'] = os.path.join(self._info['includedir'], 'CMakeLists.txt') self._file['cmswig'] = os.path.join('swig', 'CMakeLists.txt') + self._file['cmfind'] = os.path.join('cmake', 'Modules', 'howtoConfig.cmake') def _check_directory(self, directory): """ Guesses if dir is a valid GNU Radio module directory by looking for diff --git a/grc/base/Block.py b/grc/base/Block.py index 9736c0ac44..970cf516fe 100644 --- a/grc/base/Block.py +++ b/grc/base/Block.py @@ -192,6 +192,7 @@ class Block(Element): def get_name(self): return self._name def get_key(self): return self._key def get_category(self): return self._category + def set_category(self, cat): self._category = cat def get_doc(self): return '' def get_ports(self): return self.get_sources() + self.get_sinks() def get_ports_gui(self): return self.filter_bus_port(self.get_sources()) + self.filter_bus_port(self.get_sinks()); diff --git a/grc/base/Platform.py b/grc/base/Platform.py index bb80e29552..88cbf32b89 100644 --- a/grc/base/Platform.py +++ b/grc/base/Platform.py @@ -143,15 +143,15 @@ class Platform(_Element): print >> sys.stderr, 'Warning: Block key "%s" not found when loading category tree.'%(block_key) continue block = self.get_block(block_key) - #if it exists, the block's category overrides the block tree - if not block.get_category(): block_tree.add_block(parent, block) - #load the block tree + #if it exists, the block's category shall not be overridden by the xml tree + if not block.get_category(): block.set_category(parent) + #load the block tree and update the categories for each block for block_tree_file in self._block_tree_files: - #recursivly add all blocks in the tree + #recursivly put categories in blocks load_category(ParseXML.from_file(block_tree_file).find('cat')) - #add all other blocks, use the catgory tag + #add blocks to block tree for block in self.get_blocks(): - #blocks with empty categories are in the xml block tree or hidden + #blocks with empty categories are hidden if not block.get_category(): continue block_tree.add_block(block.get_category(), block) diff --git a/grc/blocks/blks2_packet_encoder.xml b/grc/blocks/blks2_packet_encoder.xml index b184ebd31c..88e1ba350c 100644 --- a/grc/blocks/blks2_packet_encoder.xml +++ b/grc/blocks/blks2_packet_encoder.xml @@ -11,6 +11,7 @@ <make>grc_blks2.packet_mod_$(type.fcn)(grc_blks2.packet_encoder( samples_per_symbol=$samples_per_symbol, bits_per_symbol=$bits_per_symbol, + preamble=$preamble, access_code=$access_code, pad_for_usrp=$pad_for_usrp, ), @@ -58,6 +59,12 @@ <type>int</type> </param> <param> + <name>Preamble</name> + <key>preamble</key> + <value></value> + <type>string</type> + </param> + <param> <name>Access Code</name> <key>access_code</key> <value></value> @@ -93,6 +100,8 @@ <doc> Packet encoder block, for use with the gnuradio modulator blocks: gmsk, dpsk, qam. +Preamble: string of 1's and 0's, leave blank for automatic. + Access Code: string of 1's and 0's, leave blank for automatic. Payload Length: 0 for automatic. diff --git a/grc/grc_gnuradio/blks2/packet.py b/grc/grc_gnuradio/blks2/packet.py index 10dd002471..872f08ca2e 100644 --- a/grc/grc_gnuradio/blks2/packet.py +++ b/grc/grc_gnuradio/blks2/packet.py @@ -68,7 +68,7 @@ class packet_encoder(gr.hier_block2): Hierarchical block for wrapping packet-based modulators. """ - def __init__(self, samples_per_symbol, bits_per_symbol, access_code='', pad_for_usrp=True): + def __init__(self, samples_per_symbol, bits_per_symbol, preamble='', access_code='', pad_for_usrp=True): """ packet_mod constructor. @@ -83,10 +83,15 @@ class packet_encoder(gr.hier_block2): self._samples_per_symbol = samples_per_symbol self._bits_per_symbol = bits_per_symbol self._pad_for_usrp = pad_for_usrp + if not preamble: #get preamble + preamble = packet_utils.default_preamble if not access_code: #get access code access_code = packet_utils.default_access_code + if not packet_utils.is_1_0_string(preamble): + raise ValueError, "Invalid preamble %r. Must be string of 1's and 0's" % (preamble,) 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._preamble = preamble self._access_code = access_code self._pad_for_usrp = pad_for_usrp #create blocks @@ -113,6 +118,7 @@ class packet_encoder(gr.hier_block2): payload, self._samples_per_symbol, self._bits_per_symbol, + self._preamble, self._access_code, self._pad_for_usrp ) diff --git a/grc/gui/ActionHandler.py b/grc/gui/ActionHandler.py index 71d62fc8f5..87576ccae1 100644 --- a/grc/gui/ActionHandler.py +++ b/grc/gui/ActionHandler.py @@ -83,6 +83,8 @@ class ActionHandler: Returns: false to let gtk handle the key action """ + # prevent key event stealing while the search box is active + if self.main_window.btwin.search_entry.has_focus(): return False if not self.get_focus_flag(): return False return Actions.handle_key_press(event) @@ -121,6 +123,8 @@ class ActionHandler: if Preferences.file_open() in self.init_file_paths: self.main_window.new_page(Preferences.file_open(), show=True) if not self.get_page(): self.main_window.new_page() #ensure that at least a blank page exists + + self.main_window.btwin.search_entry.hide() elif action == Actions.APPLICATION_QUIT: if self.main_window.close_pages(): gtk.main_quit() @@ -442,6 +446,9 @@ class ActionHandler: self.platform.loadblocks() self.main_window.btwin.clear(); self.platform.load_block_tree(self.main_window.btwin); + elif action == Actions.FIND_BLOCKS: + self.main_window.btwin.search_entry.show() + self.main_window.set_focus(self.main_window.btwin.search_entry) elif action == Actions.OPEN_HIER: bn = []; for b in self.get_flow_graph().get_selected_blocks(): @@ -484,6 +491,7 @@ class ActionHandler: Actions.BUSSIFY_SOURCES.set_sensitive(bool(self.get_flow_graph().get_selected_blocks())) Actions.BUSSIFY_SINKS.set_sensitive(bool(self.get_flow_graph().get_selected_blocks())) Actions.RELOAD_BLOCKS.set_sensitive(True) + Actions.FIND_BLOCKS.set_sensitive(True) #set the exec and stop buttons self.update_exec_stop() #saved status diff --git a/grc/gui/Actions.py b/grc/gui/Actions.py index a70109c021..5daf45def8 100644 --- a/grc/gui/Actions.py +++ b/grc/gui/Actions.py @@ -290,6 +290,13 @@ RELOAD_BLOCKS = Action( tooltip='Reload Blocks', stock_id=gtk.STOCK_REFRESH ) +FIND_BLOCKS = Action( + label='Find Blocks', + tooltip='Search for a block by bame or key', + stock_id=gtk.STOCK_FIND, + keypresses=(gtk.keysyms.f, gtk.gdk.CONTROL_MASK, + gtk.keysyms.slash, NO_MODS_MASK), +) OPEN_HIER = Action( label='Open H_ier', tooltip='Open the source of the selected hierarchical block', diff --git a/grc/gui/Bars.py b/grc/gui/Bars.py index e2b7f4f9bc..92d87c8809 100644 --- a/grc/gui/Bars.py +++ b/grc/gui/Bars.py @@ -50,6 +50,7 @@ TOOLBAR_LIST = ( Actions.BLOCK_ENABLE, Actions.BLOCK_DISABLE, None, + Actions.FIND_BLOCKS, Actions.RELOAD_BLOCKS, Actions.OPEN_HIER, Actions.BUSSIFY_SOURCES, @@ -88,6 +89,7 @@ MENU_BAR_LIST = ( ]), (gtk.Action('View', '_View', None, None), [ Actions.ERRORS_WINDOW_DISPLAY, + Actions.FIND_BLOCKS, ]), (gtk.Action('Build', '_Build', None, None), [ Actions.FLOW_GRAPH_GEN, diff --git a/grc/gui/BlockTreeWindow.py b/grc/gui/BlockTreeWindow.py index ced6429c62..2173cb0d98 100644 --- a/grc/gui/BlockTreeWindow.py +++ b/grc/gui/BlockTreeWindow.py @@ -18,6 +18,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA """ from Constants import DEFAULT_BLOCKS_WINDOW_WIDTH, DND_TARGETS +import Actions import Utils import pygtk pygtk.require('2.0') @@ -46,7 +47,7 @@ class BlockTreeWindow(gtk.VBox): Create a tree view of the possible blocks in the platform. The tree view nodes will be category names, the leaves will be block names. A mouse double click or button press action will trigger the add block event. - + Args: platform: the particular platform will all block prototypes get_flow_graph: get the selected flow graph @@ -54,21 +55,33 @@ class BlockTreeWindow(gtk.VBox): gtk.VBox.__init__(self) self.platform = platform self.get_flow_graph = get_flow_graph - #make the tree model for holding blocks + + # search entry + self.search_entry = gtk.Entry() + self.search_entry.set_icon_from_stock(gtk.ENTRY_ICON_PRIMARY, gtk.STOCK_FIND) + self.search_entry.set_icon_activatable(gtk.ENTRY_ICON_PRIMARY, False) + self.search_entry.set_icon_from_stock(gtk.ENTRY_ICON_SECONDARY, gtk.STOCK_CLOSE) + self.search_entry.connect('icon-release', self._handle_icon_event) + self.search_entry.connect('changed', self._update_search_tree) + self.search_entry.connect('key-press-event', self._handle_search_key_press) + self.pack_start(self.search_entry, False) + + #make the tree model for holding blocks and a temporary one for search results self.treestore = gtk.TreeStore(gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_STRING) + self.treestore_search = gtk.TreeStore(gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_STRING) + self.treeview = gtk.TreeView(self.treestore) self.treeview.set_enable_search(False) #disable pop up search box + self.treeview.set_search_column(-1) # really disable search + self.treeview.set_headers_visible(False) self.treeview.add_events(gtk.gdk.BUTTON_PRESS_MASK) self.treeview.connect('button-press-event', self._handle_mouse_button_press) - selection = self.treeview.get_selection() - selection.set_mode('single') - selection.connect('changed', self._handle_selection_change) + self.treeview.connect('key-press-event', self._handle_search_key_press) + + self.treeview.get_selection().set_mode('single') renderer = gtk.CellRendererText() column = gtk.TreeViewColumn('Blocks', renderer, text=NAME_INDEX) self.treeview.append_column(column) - #setup the search - self.treeview.set_enable_search(True) - self.treeview.set_search_equal_func(self._handle_search) #try to enable the tooltips (available in pygtk 2.12 and above) try: self.treeview.set_tooltip_column(DOC_INDEX) except: pass @@ -84,51 +97,48 @@ class BlockTreeWindow(gtk.VBox): scrolled_window.add_with_viewport(self.treeview) scrolled_window.set_size_request(DEFAULT_BLOCKS_WINDOW_WIDTH, -1) self.pack_start(scrolled_window) - #add button - self.add_button = gtk.Button(None, gtk.STOCK_ADD) - self.add_button.connect('clicked', self._handle_add_button) - self.pack_start(self.add_button, False) #map categories to iters, automatic mapping for root self._categories = {tuple(): None} + self._categories_search = {tuple(): None} #add blocks and categories self.platform.load_block_tree(self) - #initialize - self._update_add_button() def clear(self): self.treestore.clear(); self._categories = {tuple(): None} - ############################################################ ## Block Tree Methods ############################################################ - def add_block(self, category, block=None): + def add_block(self, category, block=None, treestore=None, categories=None): """ Add a block with category to this selection window. Add only the category when block is None. - + Args: category: the category list or path string block: the block object or None """ + if treestore is None: treestore = self.treestore + if categories is None: categories = self._categories + if isinstance(category, str): category = category.split('/') category = tuple(filter(lambda x: x, category)) #tuple is hashable #add category and all sub categories for i, cat_name in enumerate(category): sub_category = category[:i+1] - if sub_category not in self._categories: - iter = self.treestore.insert_before(self._categories[sub_category[:-1]], None) - self.treestore.set_value(iter, NAME_INDEX, '[ %s ]'%cat_name) - self.treestore.set_value(iter, KEY_INDEX, '') - self.treestore.set_value(iter, DOC_INDEX, Utils.parse_template(CAT_MARKUP_TMPL, cat=cat_name)) - self._categories[sub_category] = iter + if sub_category not in categories: + iter = treestore.insert_before(categories[sub_category[:-1]], None) + treestore.set_value(iter, NAME_INDEX, '[ %s ]'%cat_name) + treestore.set_value(iter, KEY_INDEX, '') + treestore.set_value(iter, DOC_INDEX, Utils.parse_template(CAT_MARKUP_TMPL, cat=cat_name)) + categories[sub_category] = iter #add block if block is None: return - iter = self.treestore.insert_before(self._categories[category], None) - self.treestore.set_value(iter, NAME_INDEX, block.get_name()) - self.treestore.set_value(iter, KEY_INDEX, block.get_key()) - self.treestore.set_value(iter, DOC_INDEX, Utils.parse_template(DOC_MARKUP_TMPL, doc=block.get_doc())) + iter = treestore.insert_before(categories[category], None) + treestore.set_value(iter, NAME_INDEX, block.get_name()) + treestore.set_value(iter, KEY_INDEX, block.get_key()) + treestore.set_value(iter, DOC_INDEX, Utils.parse_template(DOC_MARKUP_TMPL, doc=block.get_doc())) ############################################################ ## Helper Methods @@ -136,7 +146,7 @@ class BlockTreeWindow(gtk.VBox): def _get_selected_block_key(self): """ Get the currently selected block key. - + Returns: the key of the selected block or a empty string """ @@ -144,39 +154,84 @@ class BlockTreeWindow(gtk.VBox): treestore, iter = selection.get_selected() return iter and treestore.get_value(iter, KEY_INDEX) or '' - def _update_add_button(self): - """ - Update the add button's sensitivity. - The button should be active only if a block is selected. - """ - key = self._get_selected_block_key() - self.add_button.set_sensitive(bool(key)) - def _add_selected_block(self): """ Add the selected block with the given key to the flow graph. """ key = self._get_selected_block_key() - if key: self.get_flow_graph().add_new_block(key) + if key: + self.get_flow_graph().add_new_block(key) + return True + return False + + def _expand_category(self): + treestore, iter = self.treeview.get_selection().get_selected() + if iter and treestore.iter_has_child(iter): + path = self.treestore.get_path(iter) + self.treeview.expand_to_path(path) ############################################################ ## Event Handlers ############################################################ - def _handle_search(self, model, column, key, iter): - #determine which blocks match the search key - blocks = self.get_flow_graph().get_parent().get_blocks() - matching_blocks = filter(lambda b: key in b.get_key() or key in b.get_name().lower(), blocks) - #remove the old search category - try: self.treestore.remove(self._categories.pop((self._search_category, ))) - except (KeyError, AttributeError): pass #nothing to remove - #create a search category - if not matching_blocks: return - self._search_category = 'Search: %s'%key - for block in matching_blocks: self.add_block(self._search_category, block) - #expand the search category - path = self.treestore.get_path(self._categories[(self._search_category, )]) - self.treeview.collapse_all() - self.treeview.expand_row(path, open_all=False) + def _handle_icon_event(self, widget, icon, event): + if icon == gtk.ENTRY_ICON_PRIMARY: + pass + elif icon == gtk.ENTRY_ICON_SECONDARY: + widget.set_text('') + self.search_entry.hide() + + def _update_search_tree(self, widget): + key = widget.get_text().lower() + if not key: + self.treeview.set_model(self.treestore) + self.treeview.collapse_all() + else: + blocks = self.get_flow_graph().get_parent().get_blocks() + matching_blocks = filter(lambda b: key in b.get_key().lower() or key in b.get_name().lower(), blocks) + + self.treestore_search.clear() + self._categories_search = {tuple(): None} + for block in matching_blocks: + self.add_block(block.get_category() or 'None', block, + self.treestore_search, self._categories_search) + self.treeview.set_model(self.treestore_search) + self.treeview.expand_all() + + def _handle_search_key_press(self, widget, event): + """Handle Return and Escape key events in search entry and treeview""" + if event.keyval == gtk.keysyms.Return: + # add block on enter + + if widget == self.search_entry: + # Get the first block in the search tree and add it + selected = self.treestore_search.get_iter_first() + while self.treestore_search.iter_children(selected): + selected = self.treestore_search.iter_children(selected) + if selected is not None: + key = self.treestore_search.get_value(selected, KEY_INDEX) + if key: self.get_flow_graph().add_new_block(key) + elif widget == self.treeview: + self._add_selected_block() or self._expand_category() + else: + return False # propagate event + + elif event.keyval == gtk.keysyms.Escape: + # reset the search + self.search_entry.set_text('') + self.search_entry.hide() + + elif event.state & gtk.gdk.CONTROL_MASK and event.keyval == gtk.keysyms.f: + # propagation doesn't work although treeview search is disabled =( + # manually trigger action... + Actions.FIND_BLOCKS.activate() + + elif event.keyval == gtk.keysyms.slash: + Actions.FIND_BLOCKS.activate() + + else: + return False # propagate event + + return True def _handle_drag_get_data(self, widget, drag_context, selection_data, info, time): """ @@ -194,17 +249,3 @@ class BlockTreeWindow(gtk.VBox): """ if event.button == 1 and event.type == gtk.gdk._2BUTTON_PRESS: self._add_selected_block() - - def _handle_selection_change(self, selection): - """ - Handle a selection change in the tree view. - If a selection changes, set the add button sensitive. - """ - self._update_add_button() - - def _handle_add_button(self, widget): - """ - Handle the add button clicked signal. - Call add selected block. - """ - self._add_selected_block() diff --git a/grc/gui/DrawingArea.py b/grc/gui/DrawingArea.py index 64be4d3ea6..1313e90420 100644 --- a/grc/gui/DrawingArea.py +++ b/grc/gui/DrawingArea.py @@ -51,7 +51,8 @@ class DrawingArea(gtk.DrawingArea): gtk.gdk.POINTER_MOTION_MASK | \ gtk.gdk.BUTTON_RELEASE_MASK | \ gtk.gdk.LEAVE_NOTIFY_MASK | \ - gtk.gdk.ENTER_NOTIFY_MASK + gtk.gdk.ENTER_NOTIFY_MASK | \ + gtk.gdk.FOCUS_CHANGE_MASK ) #setup drag and drop self.drag_dest_set(gtk.DEST_DEFAULT_ALL, DND_TARGETS, gtk.gdk.ACTION_COPY) @@ -59,9 +60,11 @@ class DrawingArea(gtk.DrawingArea): #setup the focus flag self._focus_flag = False self.get_focus_flag = lambda: self._focus_flag - def _handle_focus_event(widget, event, focus_flag): self._focus_flag = focus_flag - self.connect('leave-notify-event', _handle_focus_event, False) - self.connect('enter-notify-event', _handle_focus_event, True) + def _handle_notify_event(widget, event, focus_flag): self._focus_flag = focus_flag + self.connect('leave-notify-event', _handle_notify_event, False) + self.connect('enter-notify-event', _handle_notify_event, True) + self.set_can_focus(True) + self.connect('focus-out-event', self._handle_focus_lost_event) def new_pixmap(self, width, height): return gtk.gdk.Pixmap(self.window, width, height, -1) def get_pixbuf(self): @@ -83,6 +86,7 @@ class DrawingArea(gtk.DrawingArea): """ Forward button click information to the flow graph. """ + self.grab_focus() self.ctrl_mask = event.state & gtk.gdk.CONTROL_MASK if event.button == 1: self._flow_graph.handle_mouse_selector_press( double_click=(event.type == gtk.gdk._2BUTTON_PRESS), @@ -133,3 +137,8 @@ class DrawingArea(gtk.DrawingArea): gc = self.window.new_gc() self._flow_graph.draw(gc, self._pixmap) self.window.draw_drawable(gc, self._pixmap, 0, 0, 0, 0, -1, -1) + + def _handle_focus_lost_event(self, widget, event): + self._flow_graph.unselect() + self._flow_graph.update_selected() + self._flow_graph.queue_draw()
\ No newline at end of file diff --git a/grc/gui/MainWindow.py b/grc/gui/MainWindow.py index 677f202e1f..dd378ad079 100644 --- a/grc/gui/MainWindow.py +++ b/grc/gui/MainWindow.py @@ -304,7 +304,7 @@ class MainWindow(gtk.Window): def get_focus_flag(self): """ Get the focus flag from the current page. - + Returns: the focus flag """ diff --git a/volk/kernels/volk/volk_32f_invsqrt_32f.h b/volk/kernels/volk/volk_32f_invsqrt_32f.h new file mode 100644 index 0000000000..17dfe3b9c6 --- /dev/null +++ b/volk/kernels/volk/volk_32f_invsqrt_32f.h @@ -0,0 +1,77 @@ +#ifndef INCLUDED_volk_32f_invsqrt_32f_a_H +#define INCLUDED_volk_32f_invsqrt_32f_a_H + +#include <inttypes.h> +#include <stdio.h> +#include <math.h> + +static inline float Q_rsqrt( float number ) +{ + long i; + float x2, y; + const float threehalfs = 1.5F; + + x2 = number * 0.5F; + y = number; + i = * ( long * ) &y; // evil floating point bit level hacking + i = 0x5f3759df - ( i >> 1 ); // what the fuck? + y = * ( float * ) &i; + y = y * ( threehalfs - ( x2 * y * y ) ); // 1st iteration +// y = y * ( threehalfs - ( x2 * y * y ) ); // 2nd iteration, this can be removed + + return y; +} + +#ifdef LV_HAVE_SSE +#include <xmmintrin.h> +/*! + \brief Sqrts the two input vectors and store their results in the third vector + \param cVector The vector where the results will be stored + \param aVector One of the vectors to be invsqrted + \param num_points The number of values in aVector and bVector to be invsqrted together and stored into cVector +*/ +static inline void volk_32f_invsqrt_32f_a_sse(float* cVector, const float* aVector, unsigned int num_points){ + unsigned int number = 0; + const unsigned int quarterPoints = num_points / 4; + + float* cPtr = cVector; + const float* aPtr = aVector; + + __m128 aVal, cVal; + for(;number < quarterPoints; number++){ + + aVal = _mm_load_ps(aPtr); + + cVal = _mm_rsqrt_ps(aVal); + + _mm_store_ps(cPtr,cVal); // Store the results back into the C container + + aPtr += 4; + cPtr += 4; + } + + number = quarterPoints * 4; + for(;number < num_points; number++){ + *cPtr++ = Q_rsqrt(*aPtr++); + } +} +#endif /* LV_HAVE_SSE */ + +#ifdef LV_HAVE_GENERIC +/*! + \brief Sqrts the two input vectors and store their results in the third vector + \param cVector The vector where the results will be stored + \param aVector One of the vectors to be invsqrted + \param num_points The number of values in aVector and bVector to be invsqrted together and stored into cVector +*/ +static inline void volk_32f_invsqrt_32f_generic(float* cVector, const float* aVector, unsigned int num_points){ + float* cPtr = cVector; + const float* aPtr = aVector; + unsigned int number = 0; + for(number = 0; number < num_points; number++){ + *cPtr++ = Q_rsqrt(*aPtr++); + } +} +#endif /* LV_HAVE_GENERIC */ + +#endif /* INCLUDED_volk_32f_invsqrt_32f_a_H */ |