diff options
author | Johnathan Corgan <johnathan@corganlabs.com> | 2016-03-27 06:51:27 -0700 |
---|---|---|
committer | Johnathan Corgan <johnathan@corganlabs.com> | 2016-03-27 06:51:27 -0700 |
commit | 315880c4c9dc6a3ff2c87552fada960ed337d9ff (patch) | |
tree | 56646f5f90d063096652df7a6fa8d81a0d222d26 | |
parent | 61ac8a9a685ef64db3d4478f4072b705d059e6ec (diff) | |
parent | d44dae83c5b486ad320cf2274e4fbcf79c9178c1 (diff) |
Merge branch 'master' into next
-rw-r--r-- | gnuradio-runtime/include/pmt/pmt.h | 4 | ||||
-rw-r--r-- | gnuradio-runtime/python/gnuradio/ctrlport/gr-perf-monitorx | 46 | ||||
-rw-r--r-- | gr-blocks/include/gnuradio/blocks/vector_source_X.h.t | 1 | ||||
-rw-r--r-- | gr-blocks/lib/vector_source_X_impl.h.t | 1 | ||||
-rwxr-xr-x | gr-blocks/python/blocks/qa_vector_sink_source.py | 36 | ||||
-rw-r--r-- | gr-digital/grc/digital_constellation.xml | 51 | ||||
-rw-r--r-- | gr-fec/examples/ber_curve_gen_ldpc.grc | 22 | ||||
-rw-r--r-- | gr-fec/grc/fec_bercurve_generator.xml | 9 | ||||
-rw-r--r-- | gr-fec/grc/ldpc_decoder_def_list.xml | 6 | ||||
-rw-r--r-- | gr-fec/grc/variable_ldpc_G_matrix_object.xml | 2 | ||||
-rw-r--r-- | gr-fec/grc/variable_ldpc_H_matrix_object.xml | 2 | ||||
-rw-r--r-- | gr-fec/grc/variable_ldpc_bit_flip_decoder.xml | 12 | ||||
-rw-r--r-- | gr-fec/grc/variable_ldpc_encoder_G.xml | 11 | ||||
-rw-r--r-- | gr-fec/grc/variable_ldpc_encoder_H.xml | 6 | ||||
-rw-r--r-- | gr-fec/python/fec/bercurve_generator.py | 6 |
15 files changed, 166 insertions, 49 deletions
diff --git a/gnuradio-runtime/include/pmt/pmt.h b/gnuradio-runtime/include/pmt/pmt.h index f601c85348..00564cc8d3 100644 --- a/gnuradio-runtime/include/pmt/pmt.h +++ b/gnuradio-runtime/include/pmt/pmt.h @@ -279,7 +279,7 @@ PMT_API std::complex<double> to_complex(pmt_t z); //! Return true if \p x is the empty list, otherwise return false. PMT_API bool is_null(const pmt_t& x); -//! Return true if \p obj is a pair, else false. +//! Return true if \p obj is a pair, else false (warning: also returns true for a dict) PMT_API bool is_pair(const pmt_t& obj); //! Return a newly allocated pair whose car is \p x and whose cdr is \p y. @@ -575,7 +575,7 @@ PMT_API std::complex<double> *c64vector_writable_elements(pmt_t v, size_t &len); * ------------------------------------------------------------------------ */ -//! Return true if \p obj is a dictionary +//! Return true if \p obj is a dictionary (warning: also returns true for a pair) PMT_API bool is_dict(const pmt_t &obj); //! Make an empty dictionary diff --git a/gnuradio-runtime/python/gnuradio/ctrlport/gr-perf-monitorx b/gnuradio-runtime/python/gnuradio/ctrlport/gr-perf-monitorx index bb53e02cc4..cc9f76f864 100644 --- a/gnuradio-runtime/python/gnuradio/ctrlport/gr-perf-monitorx +++ b/gnuradio-runtime/python/gnuradio/ctrlport/gr-perf-monitorx @@ -28,7 +28,18 @@ try: matplotlib.use("QT4Agg") import matplotlib.pyplot as plt from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas - from matplotlib.backends.backend_qt4agg import NavigationToolbar2QTAgg as NavigationToolbar + + # Manage different matplotlib versions + try: + from matplotlib.backends.backend_qt4agg import NavigationToolbar2QTAgg as NavigationToolbar + except ImportError: + try: + from matplotlib.backends.backend_qt4agg import NavigationToolbar2QT as NavigationToolbar + except ImportError: + print sys.argv[0], "could not load QTAgg backend." + sys.exit(1) + + from matplotlib.figure import Figure except ImportError: print sys.argv[0], "requires networkx and matplotlib.", \ @@ -42,6 +53,11 @@ import itertools from gnuradio import gr, ctrlport from gnuradio.ctrlport.GrDataPlotter import * +if float(nx.__version__) >= 1.11: + from networkx.drawing.nx_agraph import graphviz_layout +else: + graphviz_layout = nx.graphviz_layout + class MAINWindow(QtGui.QMainWindow): def minimumSizeHint(self): return QtGui.QSize(800,600) @@ -310,13 +326,12 @@ class DataTable(QtGui.QWidget): self.sp = self.f.add_subplot(111) self.sp.autoscale_view(True,True,True) self.sp.set_autoscale_on(True) - self.canvas = FigureCanvas(self.f) # set up tabs self.tabber = QtGui.QTabWidget(); self.layout.addWidget(self.tabber); self.tabber.addTab(self.perfTable,"Table View"); - self.tabber.addTab(self.canvas, "Graph View"); + self.tabber.addTab(self.f.canvas, "Graph View"); # set up timer self.timer = QtCore.QTimer() @@ -402,7 +417,7 @@ class DataTableBuffers(DataTable): for r,w in zip(self.disp, sorted_fullness): r.set_height(w[1]) - self.canvas.draw() + self.f.canvas.draw() class DataTableRuntimes(DataTable): def __init__(self, radioclient, G): @@ -423,7 +438,7 @@ class DataTableRuntimes(DataTable): total_work = 1 work_times = dict(zip( map(lambda x: x.split("::")[0], wrk_knobs.keys()), - map(lambda x: x.value/total_work, wrk_knobs.values()))) + map(lambda x: 1e-10 + x.value/total_work, wrk_knobs.values()))) # update table view if(self.perfTable.isVisible()): @@ -441,7 +456,6 @@ class DataTableRuntimes(DataTable): else: sorted_work = work_times.items() - f = plt.figure(self.f.number) if(not self.disp): self.disp = self.sp.bar(range(0,len(sorted_work)), map(lambda x: x[1], sorted_work), @@ -456,7 +470,7 @@ class DataTableRuntimes(DataTable): for r,w in zip(self.disp, sorted_work): r.set_height(w[1]) - self.canvas.draw() + self.f.canvas.draw() class MForm(QtGui.QWidget): def update(self): @@ -775,11 +789,10 @@ class MForm(QtGui.QWidget): self.sp.autoscale_view(True,True,True); self.sp.set_autoscale_on(True) - self.canvas = FigureCanvas(self.f) - self.layout.addWidget(self.canvas); + self.layout.addWidget(self.f.canvas); - self.pos = nx.graphviz_layout(self.G); - #self.pos = nx.pygraphviz_layout(self.G); + self.pos = graphviz_layout(self.G); + #self.pos = pygraphviz_layout(self.G); #self.pos = nx.spectral_layout(self.G); #self.pos = nx.circular_layout(self.G); #self.pos = nx.shell_layout(self.G); @@ -840,14 +853,14 @@ class MForm(QtGui.QWidget): def drawGraph(self): self.do_update = True - self.canvas.updateGeometry() + self.f.canvas.updateGeometry() self.sp.clear() plt.figure(self.f.number) plt.subplot(111) nx.draw(self.G, self.pos, edge_color=self.edge_weights, node_color='#A0CBE2', - width=map(lambda x: 3+math.log(x), self.edge_weights), + width=map(lambda x: 3+math.log(x+1e-20), self.edge_weights), node_shape="s", node_size=self.node_weights, edge_cmap=plt.cm.Reds, @@ -857,8 +870,7 @@ class MForm(QtGui.QWidget): nx.draw_networkx_labels(self.G, self.pos, font_size=12) - self.canvas.draw() - self.canvas.show() + self.f.canvas.show() def updateGraph(self): @@ -872,7 +884,7 @@ class MForm(QtGui.QWidget): nx.draw_networkx_edges(self.G, self.pos, edge_color=self.edge_weights, - width=map(lambda x: 3+math.log(x), self.edge_weights), + width=map(lambda x: 3+math.log(x+1e-20), self.edge_weights), edge_cmap=plt.cm.Reds, ax=self.sp, arrows=False) @@ -880,7 +892,7 @@ class MForm(QtGui.QWidget): nx.draw_networkx_labels(self.G, self.pos, ax=self.sp, font_size=12) - self.canvas.draw() + self.f.canvas.draw() class MyApp(object): diff --git a/gr-blocks/include/gnuradio/blocks/vector_source_X.h.t b/gr-blocks/include/gnuradio/blocks/vector_source_X.h.t index d5298e8b47..b0ca6b869f 100644 --- a/gr-blocks/include/gnuradio/blocks/vector_source_X.h.t +++ b/gr-blocks/include/gnuradio/blocks/vector_source_X.h.t @@ -76,6 +76,7 @@ namespace gr { virtual void rewind() = 0; virtual void set_data(const std::vector<@TYPE@> &data, const std::vector<tag_t> &tags=std::vector<tag_t>()) = 0; + virtual void set_repeat(bool repeat) = 0; }; } /* namespace blocks */ diff --git a/gr-blocks/lib/vector_source_X_impl.h.t b/gr-blocks/lib/vector_source_X_impl.h.t index 2641c6661b..bc9b329d8f 100644 --- a/gr-blocks/lib/vector_source_X_impl.h.t +++ b/gr-blocks/lib/vector_source_X_impl.h.t @@ -50,6 +50,7 @@ namespace gr { void rewind() { d_offset=0; } void set_data(const std::vector<@TYPE@> &data, const std::vector<tag_t> &tags); + void set_repeat(bool repeat) { d_repeat=repeat; }; int work(int noutput_items, gr_vector_const_void_star &input_items, diff --git a/gr-blocks/python/blocks/qa_vector_sink_source.py b/gr-blocks/python/blocks/qa_vector_sink_source.py index 5dab7014cd..026713f5f4 100755 --- a/gr-blocks/python/blocks/qa_vector_sink_source.py +++ b/gr-blocks/python/blocks/qa_vector_sink_source.py @@ -46,6 +46,7 @@ class test_vector_sink_source(gr_unittest.TestCase): self.tb = None def test_001(self): + # Test that sink has data set in source for the simplest case src_data = [float(x) for x in range(16)] expected_result = tuple(src_data) @@ -58,6 +59,7 @@ class test_vector_sink_source(gr_unittest.TestCase): self.assertEqual(expected_result, result_data) def test_002(self): + # Test vectors (the gnuradio vector I/O type) src_data = [float(x) for x in range(16)] expected_result = tuple(src_data) @@ -70,11 +72,14 @@ class test_vector_sink_source(gr_unittest.TestCase): self.assertEqual(expected_result, result_data) def test_003(self): + # Test that we can only make vectors (the I/O type) if the input + # vector has sufficient size src_data = [float(x) for x in range(16)] expected_result = tuple(src_data) self.assertRaises(RuntimeError, lambda : blocks.vector_source_f(src_data, False, 3)) def test_004(self): + # Test sending and receiving tagged streams src_data = [float(x) for x in range(16)] expected_result = tuple(src_data) src_tags = tuple([make_tag('key', 'val', 0, 'src')]) @@ -92,6 +97,7 @@ class test_vector_sink_source(gr_unittest.TestCase): self.assertTrue(compare_tags(expected_tags[0], result_tags[0])) def test_005(self): + # Test that repeat works (with tagged streams) length = 16 src_data = [float(x) for x in range(length)] expected_result = tuple(src_data + src_data) @@ -112,6 +118,36 @@ class test_vector_sink_source(gr_unittest.TestCase): self.assertTrue(compare_tags(expected_tags[0], result_tags[0])) self.assertTrue(compare_tags(expected_tags[1], result_tags[1])) + def test_006(self): + # Test set_data + src_data = [float(x) for x in range(16)] + expected_result = tuple(src_data) + + src = blocks.vector_source_f((3,1,4)) + dst = blocks.vector_sink_f() + src.set_data(src_data) + + self.tb.connect(src, dst) + self.tb.run() + result_data = dst.data() + self.assertEqual(expected_result, result_data) + + def test_007(self): + # Test set_repeat + src_data = [float(x) for x in range(16)] + expected_result = tuple(src_data) + + src = blocks.vector_source_f(src_data, True) + dst = blocks.vector_sink_f() + src.set_repeat(False) + + self.tb.connect(src, dst) + # will timeout if set_repeat does not work + self.tb.run() + result_data = dst.data() + self.assertEqual(expected_result, result_data) + + if __name__ == '__main__': gr_unittest.run(test_vector_sink_source, "test_vector_sink_source.xml") diff --git a/gr-digital/grc/digital_constellation.xml b/gr-digital/grc/digital_constellation.xml index 5254e4d799..ef5364d248 100644 --- a/gr-digital/grc/digital_constellation.xml +++ b/gr-digital/grc/digital_constellation.xml @@ -9,7 +9,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> +#if str($type) == "calcdist" +self.$(id) = $(id) = digital.constellation_calcdist($const_points, $sym_map, $rot_sym, $dims).base() +#else +self.$(id) = $(id) = digital.constellation_$(type)().base() +#end if + #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' @@ -17,16 +23,53 @@ self.$(id).set_soft_dec_lut($soft_dec_lut, $precision) #end if </var_make> - <var_value>digital.constellation_calcdist($const_points, $sym_map, $rot_sym, $dims)</var_value> +<var_value> +#if str($type) == "calcdist" +digital.constellation_calcdist($const_points, $sym_map, $rot_sym, $dims) +#else +digital.constellation_$(type)() +#end if +</var_value> <make></make> <!--<callback></callback>--> <param> + <name>Constellation Type</name> + <key>type</key> + <type>enum</type> + <option> + <name>Variable Constellation</name> + <key>calcdist</key> + </option> + <option> + <name>BPSK</name> + <key>bpsk</key> + </option> + <option> + <name>QPSK</name> + <key>qpsk</key> + </option> + <option> + <name>DQPSK</name> + <key>dqpsk</key> + </option> + <option> + <name>8PSK</name> + <key>8psk</key> + </option> + <option> + <name>16QAM</name> + <key>16qam</key> + </option> + + </param> + <param> <name>Symbol Map</name> <key>sym_map</key> <value>[0, 1, 3, 2]</value> <type>int_vector</type> + <hide> #if str($type) == "calcdist" then 'none' else 'all' #</hide> </param> <param> @@ -34,6 +77,7 @@ self.$(id).set_soft_dec_lut($soft_dec_lut, $precision) <key>const_points</key> <value>[-1-1j, -1+1j, 1+1j, 1-1j]</value> <type>complex_vector</type> + <hide> #if str($type) == "calcdist" then 'none' else 'all' #</hide> </param> <param> @@ -41,6 +85,7 @@ self.$(id).set_soft_dec_lut($soft_dec_lut, $precision) <key>rot_sym</key> <value>4</value> <type>int</type> + <hide> #if str($type) == "calcdist" then 'none' else 'all' #</hide> </param> <param> @@ -48,8 +93,8 @@ self.$(id).set_soft_dec_lut($soft_dec_lut, $precision) <key>dims</key> <value>1</value> <type>int</type> + <hide> #if str($type) == "calcdist" then 'none' else 'all' #</hide> </param> - <param> <name>Soft Decisions Precision</name> <key>precision</key> diff --git a/gr-fec/examples/ber_curve_gen_ldpc.grc b/gr-fec/examples/ber_curve_gen_ldpc.grc index 41b654077b..6a0d57561b 100644 --- a/gr-fec/examples/ber_curve_gen_ldpc.grc +++ b/gr-fec/examples/ber_curve_gen_ldpc.grc @@ -249,7 +249,7 @@ </param> <param> <key>_coordinate</key> - <value>(632, 547)</value> + <value>(700, 547)</value> </param> <param> <key>_rotation</key> @@ -367,11 +367,7 @@ </param> </block> <block> - <key>variable_ldpc_encoder_def</key> - <param> - <key>file</key> - <value></value> - </param> + <key>variable_ldpc_encoder_H_def</key> <param> <key>comment</key> <value></value> @@ -397,14 +393,14 @@ <value>0</value> </param> <param> - <key>gap</key> - <value>0</value> - </param> - <param> <key>id</key> <value>enc_ldpc</value> </param> <param> + <key>H</key> + <value>H</value> + </param> + <param> <key>value</key> <value>"ok"</value> </param> @@ -414,7 +410,7 @@ </param> </block> <block> - <key>variable_ldpc_gen_mtrx_encoder_def</key> + <key>variable_ldpc_encoder_G_def</key> <param> <key>comment</key> <value></value> @@ -433,7 +429,7 @@ </param> <param> <key>_coordinate</key> - <value>(624, 427)</value> + <value>(700, 427)</value> </param> <param> <key>_rotation</key> @@ -1003,7 +999,7 @@ </param> <param> <key>label3</key> - <value>LDPC (R.U. matrix)</value> + <value>LDPC (H matrix)</value> </param> <param> <key>marker3</key> diff --git a/gr-fec/grc/fec_bercurve_generator.xml b/gr-fec/grc/fec_bercurve_generator.xml index 4d0d47e15b..5dfc7c6714 100644 --- a/gr-fec/grc/fec_bercurve_generator.xml +++ b/gr-fec/grc/fec_bercurve_generator.xml @@ -91,5 +91,14 @@ </source> <doc> + Note that this block tries to launch many parallel codes to run simultaneously. Thus, it requires that the definitions for each encoder and decoder (specified in the "Encoder list" and "Decoder list") be configured with a parallelism > 0. If the parallelism for one of the encoder or decoder definition blocks is configured to 0, you will likely see an error like: + + generic_decoder=decoder_list[i], + TypeError: 'generic_decoder_sptr' object does not support indexing + + or + + generic_encoder=encoder_list[i], + TypeError: 'generic_encoder_sptr' object does not support indexing </doc> </block> diff --git a/gr-fec/grc/ldpc_decoder_def_list.xml b/gr-fec/grc/ldpc_decoder_def_list.xml index 8304e037bf..007f85505c 100644 --- a/gr-fec/grc/ldpc_decoder_def_list.xml +++ b/gr-fec/grc/ldpc_decoder_def_list.xml @@ -78,6 +78,10 @@ self.$(id) = $(id) = map( (lambda b: map( ( lambda a: fec.ldpc_decoder.make($fil </param> <doc> - This block does some kind of ldpc +This is a soft-decision decoder that uses belief propagation (also known as message passing) that is described at: + +www.cs.toronto.edu/~radford/ftp/LDPC-2012-02-11/decoding.html + +Designed for a memoryless AWGN channel, it assumes a noise variance of the value specified for sigma. </doc> </block> diff --git a/gr-fec/grc/variable_ldpc_G_matrix_object.xml b/gr-fec/grc/variable_ldpc_G_matrix_object.xml index cd6b02c718..cd9360c7f7 100644 --- a/gr-fec/grc/variable_ldpc_G_matrix_object.xml +++ b/gr-fec/grc/variable_ldpc_G_matrix_object.xml @@ -32,7 +32,7 @@ This block creates a LDPC Generator Matrix variable. This variable can be used by: - 1) LDPC Generator Matrix Encoder Definition block + 1) LDPC Encoder Definition (via Generator) block 2) LDPC Bit Flip Decoder Definition block Provide an alist file, which contains a Generator matrix, G, in the standard format G = [I P], where I is an identity matrix and P is the parity submatrix. diff --git a/gr-fec/grc/variable_ldpc_H_matrix_object.xml b/gr-fec/grc/variable_ldpc_H_matrix_object.xml index 81476d6617..1bfb6be060 100644 --- a/gr-fec/grc/variable_ldpc_H_matrix_object.xml +++ b/gr-fec/grc/variable_ldpc_H_matrix_object.xml @@ -38,7 +38,7 @@ This block creates a FEC LDPC Parity Check Matrix variable. This variable can be used by: - 1) LDPC Encoder Definition block + 1) LDPC Encoder Definition (via Parity Check) block 2) LDPC Bit Flip Decoder Definition block The format of alist files is described at: diff --git a/gr-fec/grc/variable_ldpc_bit_flip_decoder.xml b/gr-fec/grc/variable_ldpc_bit_flip_decoder.xml index 2b407f360b..d905ce27fb 100644 --- a/gr-fec/grc/variable_ldpc_bit_flip_decoder.xml +++ b/gr-fec/grc/variable_ldpc_bit_flip_decoder.xml @@ -10,11 +10,11 @@ <import>from gnuradio import fec</import> <var_make> #if int($ndim())==0 # -self.$(id) = $(id) = fec.ldpc_bit_flip_decoder.make(${matrix_object}.get_base_ptr(), $max_iterations) +self.$(id) = $(id) = fec.ldpc_bit_flip_decoder.make(${matrix_object}.get_base_sptr(), $max_iterations) #else if int($ndim())==1 # -self.$(id) = $(id) = map((lambda a: fec.ldpc_bit_flip_decoder.make(${matrix_object}.get_base_ptr(), $max_iterations)), range(0,$dim1)) #slurp +self.$(id) = $(id) = map((lambda a: fec.ldpc_bit_flip_decoder.make(${matrix_object}.get_base_sptr(), $max_iterations)), range(0,$dim1)) #slurp #else -self.$(id) = $(id) = map((lambda b: map((lambda a: fec.ldpc_bit_flip_decoder.make(${matrix_object}.get_base_ptr(), $max_iterations)), range(0,$dim2))), range(0,$dim1)) #slurp +self.$(id) = $(id) = map((lambda b: map((lambda a: fec.ldpc_bit_flip_decoder.make(${matrix_object}.get_base_sptr(), $max_iterations)), range(0,$dim2))), range(0,$dim1)) #slurp #end if</var_make> <make></make> @@ -78,10 +78,8 @@ self.$(id) = $(id) = map((lambda b: map((lambda a: fec.ldpc_bit_flip_decoder.mak This block creates a LDPC Bit Flip Decoder Definition variable. The decoder requires knowledge of the matrix used to create (encode) the codewords. In the LDPC FEC Matrix ID field, input the ID of either a: - 1) LDPC Matrix variable, or - 2) LDPC R. U. Parity Check Matrix variable - -Be sure to specify the same matrix ID as the matrix that was used for encoding. + 1) LDPC Generator Matrix variable, or + 2) LDPC Parity Check Matrix variable Max iterations may be increased from 100 for possibly better performance, but significantly higher number of iterations may slow things down. </doc> diff --git a/gr-fec/grc/variable_ldpc_encoder_G.xml b/gr-fec/grc/variable_ldpc_encoder_G.xml index 74d95fad38..3b4dbeee25 100644 --- a/gr-fec/grc/variable_ldpc_encoder_G.xml +++ b/gr-fec/grc/variable_ldpc_encoder_G.xml @@ -1,7 +1,7 @@ <?xml version="1.0"?> <!-- ################################################### -# FEC LDPC GENERATOR MATRIX ENCODER +# FEC LDPC ENCODER DEFINITION (VIA GENERATOR) ################################################### --> @@ -13,9 +13,9 @@ #if int($ndim())==0 # self.$(id) = $(id) = fec.ldpc_gen_mtrx_encoder_make($G) #else if int($ndim())==1 # -self.$(id) = $(id) = map((lambda a: fec.ldpc_encoder_make($G)), range(0,$dim1)) #slurp +self.$(id) = $(id) = map((lambda a: fec.ldpc_gen_mtrx_encoder_make($G)), range(0,$dim1)) #slurp #else -self.$(id) = $(id) = map((lambda b: map((lambda a: fec.ldpc_encoder_make($G)), range(0,$dim2))), range(0,$dim1)) #slurp +self.$(id) = $(id) = map((lambda b: map((lambda a: fec.ldpc_gen_mtrx_encoder_make($G)), range(0,$dim2))), range(0,$dim1)) #slurp #end if</var_make> <make></make> @@ -69,4 +69,9 @@ self.$(id) = $(id) = map((lambda b: map((lambda a: fec.ldpc_encoder_make($G)), r <type>raw</type> </param> + <doc> +Given a generator matrix in systematic form, G = [I|P], where I is the identity matrix and P is the parity submatrix, the information word s is encoded into a codeword x via: + +x = G'*s + </doc> </block> diff --git a/gr-fec/grc/variable_ldpc_encoder_H.xml b/gr-fec/grc/variable_ldpc_encoder_H.xml index 403f8097c9..555891b095 100644 --- a/gr-fec/grc/variable_ldpc_encoder_H.xml +++ b/gr-fec/grc/variable_ldpc_encoder_H.xml @@ -1,7 +1,7 @@ <?xml version="1.0"?> <!-- ################################################### -# FEC LDPC RICHARDSON URBANKE ENCODER +# FEC LDPC ENCODER DEFINITION (PARITY CHECK) ################################################### --> <block> @@ -67,5 +67,9 @@ self.$(id) = $(id) = map((lambda b: map((lambda a: fec.ldpc_par_mtrx_encoder_mak <value></value> <type>raw</type> </param> + <doc> +This block creates a LDPC Encoder Definition variable. +This encoder performs a reduced complexity algorithm described by Richardson and Urbanke in Appendix A of their book: Modern Coding Theory. Compared to the block "LDPC Encoder Definition (via Generator)," this encoder requires orders of magnitude fewer operations to create each codeword. This is accomplished by completing a significant amount of the complex matrix manipulation (including inverse, multiplication, and Gaussian elimination operations) during preprocessing. The disadvantage of this encoder is that it requires a specially formatted matrix. However, GNU Radio includes python scripts to format a standard parity check matrix appropriately for this encoder, as well as a small library of encoding-ready matrices for use. + </doc> </block> diff --git a/gr-fec/python/fec/bercurve_generator.py b/gr-fec/python/fec/bercurve_generator.py index e67d1e17c2..3221a683ce 100644 --- a/gr-fec/python/fec/bercurve_generator.py +++ b/gr-fec/python/fec/bercurve_generator.py @@ -44,6 +44,12 @@ class bercurve_generator(gr.hier_block2): self.deinterleave = blocks.deinterleave(gr.sizeof_char*1) self.connect(self.random_gen_b_0, self.deinterleave) self.ber_generators = [] + + # FIXME It would be good to check that the encoder_list and + # decoder_list have parallelism set to > 0. If parallelism + # is set to 0, a map isn't passed and an indexing error is + # thrown on line 53 or 54 below. + for i in range(0, len(esno)): ber_generator_temp = fec_test( generic_encoder=encoder_list[i], |