summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohnathan Corgan <johnathan@corganlabs.com>2015-04-02 11:55:14 -0700
committerJohnathan Corgan <johnathan@corganlabs.com>2015-04-02 11:55:14 -0700
commit50b66458748057fe19dca5b736cc9ece331905d0 (patch)
tree6e17ea3b893501c59d89608ffbc2dbfe9e3797b1
parentc6b430aec86325991239b0378a74eba508d0f0a7 (diff)
parentf1281442c99ecdcae548f427559431cb637582dd (diff)
Merge branch 'master' into next
-rw-r--r--gnuradio-runtime/include/gnuradio/hier_block2.h48
-rw-r--r--gnuradio-runtime/lib/flat_flowgraph.cc8
-rw-r--r--gnuradio-runtime/lib/flat_flowgraph.h4
-rw-r--r--gnuradio-runtime/lib/hier_block2.cc93
-rw-r--r--gnuradio-runtime/lib/hier_block2_detail.cc184
-rw-r--r--gnuradio-runtime/lib/hier_block2_detail.h4
-rw-r--r--gnuradio-runtime/swig/hier_block2.i8
-rw-r--r--gr-digital/grc/digital_chunks_to_symbols.xml1
-rw-r--r--gr-digital/include/gnuradio/digital/chunks_to_symbols_XX.h.t1
-rw-r--r--gr-digital/lib/chunks_to_symbols_XX_impl.cc.t2
-rw-r--r--gr-digital/lib/chunks_to_symbols_XX_impl.h.t2
-rwxr-xr-xgr-digital/python/digital/qa_chunks_to_symbols.py33
-rw-r--r--gr-fec/examples/271.127.3.112402
-rw-r--r--gr-fec/grc/fec_block_tree.xml2
-rw-r--r--gr-fec/grc/ldpc_decoder_def_list.xml88
-rwxr-xr-xgr-fec/grc/ldpc_encoder_def_list.xml75
-rw-r--r--gr-fec/include/gnuradio/fec/alist.h121
-rw-r--r--gr-fec/include/gnuradio/fec/awgn_bp.h175
-rw-r--r--gr-fec/include/gnuradio/fec/cldpc.h115
-rw-r--r--gr-fec/include/gnuradio/fec/generic_decoder.h9
-rw-r--r--gr-fec/include/gnuradio/fec/gf2mat.h111
-rw-r--r--gr-fec/include/gnuradio/fec/gf2vec.h71
-rw-r--r--gr-fec/include/gnuradio/fec/ldpc_decoder.h79
-rwxr-xr-xgr-fec/include/gnuradio/fec/ldpc_encoder.h61
-rw-r--r--gr-fec/include/gnuradio/fec/maxstar.h99
-rw-r--r--gr-fec/lib/CMakeLists.txt7
-rw-r--r--gr-fec/lib/alist.cc205
-rw-r--r--gr-fec/lib/async_decoder_impl.cc31
-rw-r--r--gr-fec/lib/async_encoder_impl.cc20
-rw-r--r--gr-fec/lib/awgn_bp.cc259
-rw-r--r--gr-fec/lib/cldpc.cc132
-rw-r--r--gr-fec/lib/gf2mat.cc193
-rw-r--r--gr-fec/lib/gf2vec.cc91
-rw-r--r--gr-fec/lib/ldpc_decoder.cc105
-rwxr-xr-xgr-fec/lib/ldpc_encoder.cc76
-rw-r--r--gr-fec/swig/fec_swig.i4
-rw-r--r--grc/blocks/options.xml16
-rw-r--r--grc/gui/ActionHandler.py4
-rw-r--r--grc/gui/Bars.py53
-rw-r--r--grc/gui/Connection.py6
-rw-r--r--grc/gui/Dialogs.py8
-rw-r--r--grc/gui/FlowGraph.py21
-rw-r--r--grc/gui/MainWindow.py35
-rw-r--r--grc/gui/Param.py30
-rw-r--r--grc/gui/Preferences.py10
-rw-r--r--grc/gui/PropsDialog.py19
-rw-r--r--grc/python/Generator.py16
-rw-r--r--grc/python/flow_graph.tmpl34
-rwxr-xr-xgrc/scripts/gnuradio-companion107
49 files changed, 3172 insertions, 106 deletions
diff --git a/gnuradio-runtime/include/gnuradio/hier_block2.h b/gnuradio-runtime/include/gnuradio/hier_block2.h
index 1bf8dddc1a..3a74a37d6d 100644
--- a/gnuradio-runtime/include/gnuradio/hier_block2.h
+++ b/gnuradio-runtime/include/gnuradio/hier_block2.h
@@ -56,6 +56,7 @@ namespace gr {
* \brief Private implementation details of gr::hier_block2
*/
hier_block2_detail *d_detail;
+
protected:
hier_block2(void) {} // allows pure virtual interface sub-classes
@@ -170,6 +171,37 @@ namespace gr {
*/
virtual void unlock();
+ /*!
+ * \brief Returns max buffer size (itemcount) on output port \p i.
+ */
+ size_t max_output_buffer(size_t i=0);
+
+ /*!
+ * \brief Sets max buffer size (itemcount) on all output ports.
+ */
+ void set_max_output_buffer(size_t max_output_buffer);
+
+ /*!
+ * \brief Sets max buffer size (itemcount) on output port \p port.
+ */
+ void set_max_output_buffer(int port, size_t max_output_buffer);
+
+ /*!
+ * \brief Returns min buffer size (itemcount) on output port \p i.
+ */
+ size_t min_output_buffer(size_t i=0);
+
+ /*!
+ * \brief Sets min buffer size (itemcount) on all output ports.
+ */
+ void set_min_output_buffer(size_t min_output_buffer);
+
+ /*!
+ * \brief Sets min buffer size (itemcount) on output port \p port.
+ */
+ void set_min_output_buffer(int port, size_t min_output_buffer);
+
+
// This is a public method for ease of code organization, but should be
// ignored by the user.
flat_flowgraph_sptr flatten() const;
@@ -233,6 +265,22 @@ namespace gr {
* call could be misleading.
*/
std::vector<int> processor_affinity();
+
+ /*!
+ * \brief Get if all block min buffers should be set.
+ *
+ * \details this returns whether all the block min output buffers
+ * should be set or just the block ports connected to the hier ports.
+ */
+ bool all_min_output_buffer_p(void);
+
+ /*!
+ * \brief Get if all block max buffers should be set.
+ *
+ * \details this returns whether all the block max output buffers
+ * should be set or just the block ports connected to the hier ports.
+ */
+ bool all_max_output_buffer_p(void);
};
/*!
diff --git a/gnuradio-runtime/lib/flat_flowgraph.cc b/gnuradio-runtime/lib/flat_flowgraph.cc
index 9e5964cb7d..b580238b7c 100644
--- a/gnuradio-runtime/lib/flat_flowgraph.cc
+++ b/gnuradio-runtime/lib/flat_flowgraph.cc
@@ -50,6 +50,7 @@ namespace gr {
flat_flowgraph::flat_flowgraph()
{
+ configure_default_loggers(d_logger, d_debug_logger, "flat_flowgraph");
}
flat_flowgraph::~flat_flowgraph()
@@ -107,6 +108,13 @@ namespace gr {
detail->set_output(i, buffer);
// Update the block's max_output_buffer based on what was actually allocated.
+ if((grblock->max_output_buffer(i) != buffer->bufsize()) && (grblock->max_output_buffer(i) != -1))
+ GR_LOG_WARN(d_logger, boost::format("Block (%1%) max output buffer set to %2% instead of requested %3%") \
+ % grblock->alias() % buffer->bufsize() % grblock->max_output_buffer(i));
+ //std::cout << ">>> Warning: Block (" << grblock->alias()
+ // << ") max output buffer set to " << buffer->bufsize()
+ // << " instead of requested " << grblock->max_output_buffer(i)
+ // << std::endl;
grblock->set_max_output_buffer(i, buffer->bufsize());
}
diff --git a/gnuradio-runtime/lib/flat_flowgraph.h b/gnuradio-runtime/lib/flat_flowgraph.h
index 6c299ee5f9..fad14279ae 100644
--- a/gnuradio-runtime/lib/flat_flowgraph.h
+++ b/gnuradio-runtime/lib/flat_flowgraph.h
@@ -26,6 +26,7 @@
#include <gnuradio/api.h>
#include <gnuradio/flowgraph.h>
#include <gnuradio/block.h>
+#include <gnuradio/logger.h>
namespace gr {
@@ -89,6 +90,9 @@ namespace gr {
* start and restarts.
*/
void setup_buffer_alignment(block_sptr block);
+
+ gr::logger_ptr d_logger;
+ gr::logger_ptr d_debug_logger;
};
} /* namespace gr */
diff --git a/gnuradio-runtime/lib/hier_block2.cc b/gnuradio-runtime/lib/hier_block2.cc
index f145b9344b..4d2c460c12 100644
--- a/gnuradio-runtime/lib/hier_block2.cc
+++ b/gnuradio-runtime/lib/hier_block2.cc
@@ -182,4 +182,97 @@ namespace gr {
return dot_graph_fg(hierblock2->flatten());
}
+ size_t
+ hier_block2::max_output_buffer(size_t i)
+ {
+ if(i >= d_detail->d_max_output_buffer.size())
+ throw std::invalid_argument("hier_block2::max_output_buffer: port out of range.");
+ return d_detail->d_max_output_buffer[i];
+ }
+
+ void
+ hier_block2::set_max_output_buffer(size_t max_output_buffer)
+ {
+ if(output_signature()->max_streams()>0)
+ {
+ if(d_detail->d_max_output_buffer.size() == 0)
+ throw std::length_error("hier_block2::max_output_buffer: out_sig greater than zero, buff_vect isn't");
+ for(size_t idx = 0; idx < output_signature()->max_streams(); idx++){
+ d_detail->d_max_output_buffer[idx] = max_output_buffer;
+ }
+ }
+ }
+
+ void
+ hier_block2::set_max_output_buffer(int port, size_t max_output_buffer)
+ {
+ if((size_t)port >= d_detail->d_max_output_buffer.size())
+ throw std::invalid_argument("hier_block2::max_output_buffer: port out of range.");
+ else{
+ d_detail->d_max_output_buffer[port] = max_output_buffer;
+ }
+ }
+
+ size_t
+ hier_block2::min_output_buffer(size_t i)
+ {
+ if(i >= d_detail->d_min_output_buffer.size())
+ throw std::invalid_argument("hier_block2::min_output_buffer: port out of range.");
+ return d_detail->d_min_output_buffer[i];
+ }
+
+ void
+ hier_block2::set_min_output_buffer(size_t min_output_buffer)
+ {
+ if(output_signature()->max_streams()>0)
+ {
+ if(d_detail->d_min_output_buffer.size() == 0)
+ throw std::length_error("hier_block2::min_output_buffer: out_sig greater than zero, buff_vect isn't");
+ for(size_t idx = 0; idx < output_signature()->max_streams(); idx++){
+ d_detail->d_min_output_buffer[idx] = min_output_buffer;
+ }
+ }
+ }
+
+ void
+ hier_block2::set_min_output_buffer(int port, size_t min_output_buffer)
+ {
+ if((size_t)port >= d_detail->d_min_output_buffer.size())
+ throw std::invalid_argument("hier_block2::min_output_buffer: port out of range.");
+ else{
+ d_detail->d_min_output_buffer[port] = min_output_buffer;
+ }
+ }
+
+ bool
+ hier_block2::all_min_output_buffer_p(void)
+ {
+ if(d_detail->d_min_output_buffer.size() > 0){
+ bool all_equal = true;
+ for(int idx = 1; (idx < d_detail->d_min_output_buffer.size()) && all_equal; idx++){
+ if(d_detail->d_min_output_buffer[0] != d_detail->d_min_output_buffer[idx])
+ all_equal = false;
+ }
+ return all_equal;
+ }
+ else{
+ return false;
+ }
+ }
+ bool
+ hier_block2::all_max_output_buffer_p(void)
+ {
+ if(d_detail->d_max_output_buffer.size() > 0){
+ bool all_equal = true;
+ for(int idx = 1; (idx < d_detail->d_max_output_buffer.size()) && all_equal; idx++){
+ if(d_detail->d_max_output_buffer[0] != d_detail->d_max_output_buffer[idx])
+ all_equal = false;
+ }
+ return all_equal;
+ }
+ else{
+ return false;
+ }
+ }
+
} /* namespace gr */
diff --git a/gnuradio-runtime/lib/hier_block2_detail.cc b/gnuradio-runtime/lib/hier_block2_detail.cc
index ad8fc87122..a735de3fff 100644
--- a/gnuradio-runtime/lib/hier_block2_detail.cc
+++ b/gnuradio-runtime/lib/hier_block2_detail.cc
@@ -56,6 +56,9 @@ namespace gr {
d_inputs = std::vector<endpoint_vector_t>(max_inputs);
d_outputs = endpoint_vector_t(max_outputs);
+
+ d_max_output_buffer = std::vector<size_t>(std::max(max_outputs,1), 0);
+ d_min_output_buffer = std::vector<size_t>(std::max(max_outputs,1), 0);
}
hier_block2_detail::~hier_block2_detail()
@@ -513,6 +516,24 @@ namespace gr {
// Only run setup_rpc if ControlPort config param is enabled.
bool ctrlport_on = prefs::singleton()->get_bool("ControlPort", "on", false);
+
+ size_t min_buff(0), max_buff(0);
+ // Determine how the buffers should be set
+ bool set_all_min_buff = d_owner->all_min_output_buffer_p();
+ bool set_all_max_buff = d_owner->all_max_output_buffer_p();
+ // Get the min and max buffer length
+ if(set_all_min_buff){
+ if(HIER_BLOCK2_DETAIL_DEBUG)
+ std::cout << "Getting (" << (d_owner->alias()).c_str()
+ << ") min buffer" << std::endl;
+ min_buff = d_owner->min_output_buffer();
+ }
+ if(set_all_max_buff){
+ if(HIER_BLOCK2_DETAIL_DEBUG)
+ std::cout << "Getting (" << (d_owner->alias()).c_str()
+ << ") max buffer" << std::endl;
+ max_buff = d_owner->max_output_buffer();
+ }
// For every block (gr::block and gr::hier_block2), set up the RPC
// interface.
@@ -526,6 +547,60 @@ namespace gr {
b->rpc_set();
}
}
+ if(set_all_min_buff){
+ //sets the min buff for every block within hier_block2
+ if(min_buff != 0){
+ block_sptr bb = boost::dynamic_pointer_cast<block>(b);
+ if(bb != 0){
+ if(bb->min_output_buffer(0) != min_buff){
+ if(HIER_BLOCK2_DETAIL_DEBUG)
+ std::cout << "Block (" << (bb->alias()).c_str()
+ << ") min_buff (" << min_buff
+ << ")" << std::endl;
+ bb->set_min_output_buffer(min_buff);
+ }
+ }
+ else{
+ hier_block2_sptr hh = boost::dynamic_pointer_cast<hier_block2>(b);
+ if(hh != 0){
+ if(hh->min_output_buffer(0) != min_buff){
+ if(HIER_BLOCK2_DETAIL_DEBUG)
+ std::cout << "HBlock (" << (hh->alias()).c_str()
+ << ") min_buff (" << min_buff
+ << ")" << std::endl;
+ hh->set_min_output_buffer(min_buff);
+ }
+ }
+ }
+ }
+ }
+ if(set_all_max_buff){
+ //sets the max buff for every block within hier_block2
+ if(max_buff != 0){
+ block_sptr bb = boost::dynamic_pointer_cast<block>(b);
+ if(bb != 0){
+ if(bb->max_output_buffer(0) != max_buff){
+ if(HIER_BLOCK2_DETAIL_DEBUG)
+ std::cout << "Block (" << (bb->alias()).c_str()
+ << ") max_buff (" << max_buff
+ << ")" << std::endl;
+ bb->set_max_output_buffer(max_buff);
+ }
+ }
+ else{
+ hier_block2_sptr hh = boost::dynamic_pointer_cast<hier_block2>(b);
+ if(hh != 0){
+ if(hh->max_output_buffer(0) != max_buff){
+ if(HIER_BLOCK2_DETAIL_DEBUG)
+ std::cout << "HBlock (" << (hh->alias()).c_str()
+ << ") max_buff (" << max_buff
+ << ")" << std::endl;
+ hh->set_max_output_buffer(max_buff);
+ }
+ }
+ }
+ }
+ }
b = p->dst().block();
if(ctrlport_on) {
@@ -534,6 +609,60 @@ namespace gr {
b->rpc_set();
}
}
+ if(set_all_min_buff){
+ //sets the min buff for every block within hier_block2
+ if(min_buff != 0){
+ block_sptr bb = boost::dynamic_pointer_cast<block>(b);
+ if(bb != 0){
+ if(bb->min_output_buffer(0) != min_buff){
+ if(HIER_BLOCK2_DETAIL_DEBUG)
+ std::cout << "Block (" << (bb->alias()).c_str()
+ << ") min_buff (" << min_buff
+ << ")" << std::endl;
+ bb->set_min_output_buffer(min_buff);
+ }
+ }
+ else{
+ hier_block2_sptr hh = boost::dynamic_pointer_cast<hier_block2>(b);
+ if(hh != 0){
+ if(hh->min_output_buffer(0) != min_buff){
+ if(HIER_BLOCK2_DETAIL_DEBUG)
+ std::cout << "HBlock (" << (hh->alias()).c_str()
+ << ") min_buff (" << min_buff
+ << ")" << std::endl;
+ hh->set_min_output_buffer(min_buff);
+ }
+ }
+ }
+ }
+ }
+ if(set_all_max_buff){
+ //sets the max buff for every block within hier_block2
+ if(max_buff != 0){
+ block_sptr bb = boost::dynamic_pointer_cast<block>(b);
+ if(bb != 0){
+ if(bb->max_output_buffer(0) != max_buff){
+ if(HIER_BLOCK2_DETAIL_DEBUG)
+ std::cout << "Block (" << (bb->alias()).c_str()
+ << ") max_buff (" << max_buff
+ << ")" << std::endl;
+ bb->set_max_output_buffer(max_buff);
+ }
+ }
+ else{
+ hier_block2_sptr hh = boost::dynamic_pointer_cast<hier_block2>(b);
+ if(hh != 0){
+ if(hh->max_output_buffer(0) != max_buff){
+ if(HIER_BLOCK2_DETAIL_DEBUG)
+ std::cout << "HBlock (" << (hh->alias()).c_str()
+ << ") max_buff (" << max_buff
+ << ")" << std::endl;
+ hh->set_max_output_buffer(max_buff);
+ }
+ }
+ }
+ }
+ }
}
if(HIER_BLOCK2_DETAIL_DEBUG)
@@ -641,6 +770,61 @@ namespace gr {
<< " is not connected internally";
throw std::runtime_error(msg.str());
}
+ // Set the buffers of only the blocks connected to the hier output
+ if(!set_all_min_buff){
+ min_buff = d_owner->min_output_buffer(i);
+ if(min_buff != 0){
+ block_sptr bb = boost::dynamic_pointer_cast<block>(blk);
+ if(bb != 0){
+ int bb_src_port = d_outputs[i].port();
+ if(HIER_BLOCK2_DETAIL_DEBUG)
+ std::cout << "Block (" << (bb->alias()).c_str()
+ << ") Port (" << bb_src_port
+ << ") min_buff (" << min_buff
+ << ")" << std::endl;
+ bb->set_min_output_buffer(bb_src_port, min_buff);
+ }
+ else{
+ hier_block2_sptr hh = boost::dynamic_pointer_cast<hier_block2>(blk);
+ if(hh != 0){
+ int hh_src_port = d_outputs[i].port();
+ if(HIER_BLOCK2_DETAIL_DEBUG)
+ std::cout << "HBlock (" << (hh->alias()).c_str()
+ << ") Port (" << hh_src_port
+ << ") min_buff ("<< min_buff
+ << ")" << std::endl;
+ hh->set_min_output_buffer(hh_src_port, min_buff);
+ }
+ }
+ }
+ }
+ if(!set_all_max_buff){
+ max_buff = d_owner->max_output_buffer(i);
+ if(max_buff != 0){
+ block_sptr bb = boost::dynamic_pointer_cast<block>(blk);
+ if(bb != 0){
+ int bb_src_port = d_outputs[i].port();
+ if(HIER_BLOCK2_DETAIL_DEBUG)
+ std::cout << "Block (" << (bb->alias()).c_str()
+ << ") Port (" << bb_src_port
+ << ") max_buff (" << max_buff
+ << ")" << std::endl;
+ bb->set_max_output_buffer(bb_src_port, max_buff);
+ }
+ else{
+ hier_block2_sptr hh = boost::dynamic_pointer_cast<hier_block2>(blk);
+ if(hh != 0){
+ int hh_src_port = d_outputs[i].port();
+ if(HIER_BLOCK2_DETAIL_DEBUG)
+ std::cout << "HBlock (" << (hh->alias()).c_str()
+ << ") Port (" << hh_src_port
+ << ") max_buff (" << max_buff
+ << ")" << std::endl;
+ hh->set_max_output_buffer(hh_src_port, max_buff);
+ }
+ }
+ }
+ }
tmp.push_back(blk);
}
sort(tmp.begin(), tmp.end());
diff --git a/gnuradio-runtime/lib/hier_block2_detail.h b/gnuradio-runtime/lib/hier_block2_detail.h
index 806738360f..8c38c3754a 100644
--- a/gnuradio-runtime/lib/hier_block2_detail.h
+++ b/gnuradio-runtime/lib/hier_block2_detail.h
@@ -57,6 +57,10 @@ namespace gr {
void set_processor_affinity(const std::vector<int> &mask);
void unset_processor_affinity();
std::vector<int> processor_affinity();
+
+ // Track output buffer min/max settings
+ std::vector<size_t> d_max_output_buffer;
+ std::vector<size_t> d_min_output_buffer;
private:
// Private implementation data
diff --git a/gnuradio-runtime/swig/hier_block2.i b/gnuradio-runtime/swig/hier_block2.i
index 053f24721d..12190d0452 100644
--- a/gnuradio-runtime/swig/hier_block2.i
+++ b/gnuradio-runtime/swig/hier_block2.i
@@ -91,6 +91,14 @@ namespace gr {
void unset_processor_affinity();
std::vector<int> processor_affinity();
+ // Methods to manage block's min/max buffer sizes.
+ size_t max_output_buffer(int i);
+ void set_max_output_buffer(size_t max_output_buffer);
+ void set_max_output_buffer(int port, size_t max_output_buffer);
+ size_t min_output_buffer(int i);
+ void set_min_output_buffer(size_t min_output_buffer);
+ void set_min_output_buffer(int port, size_t min_output_buffer);
+
gr::hier_block2_sptr to_hier_block2(); // Needed for Python type coercion
};
diff --git a/gr-digital/grc/digital_chunks_to_symbols.xml b/gr-digital/grc/digital_chunks_to_symbols.xml
index 494be274df..9c6f952ec0 100644
--- a/gr-digital/grc/digital_chunks_to_symbols.xml
+++ b/gr-digital/grc/digital_chunks_to_symbols.xml
@@ -9,6 +9,7 @@
<key>digital_chunks_to_symbols_xx</key>
<import>from gnuradio import digital</import>
<make>digital.chunks_to_symbols_$(in_type.fcn)$(out_type.fcn)($symbol_table, $dimension)</make>
+ <callback>set_symbol_table($symbol_table)</callback>
<param>
<name>Input Type</name>
<key>in_type</key>
diff --git a/gr-digital/include/gnuradio/digital/chunks_to_symbols_XX.h.t b/gr-digital/include/gnuradio/digital/chunks_to_symbols_XX.h.t
index c6f2060c34..6683ea94fc 100644
--- a/gr-digital/include/gnuradio/digital/chunks_to_symbols_XX.h.t
+++ b/gr-digital/include/gnuradio/digital/chunks_to_symbols_XX.h.t
@@ -68,6 +68,7 @@ namespace gr {
virtual int D() const = 0;
virtual std::vector<@O_TYPE@> symbol_table() const = 0;
+ virtual void set_symbol_table(const std::vector<@O_TYPE@> &symbol_table) =0;
};
} /* namespace digital */
diff --git a/gr-digital/lib/chunks_to_symbols_XX_impl.cc.t b/gr-digital/lib/chunks_to_symbols_XX_impl.cc.t
index fd334b99d7..b08bdde08f 100644
--- a/gr-digital/lib/chunks_to_symbols_XX_impl.cc.t
+++ b/gr-digital/lib/chunks_to_symbols_XX_impl.cc.t
@@ -87,7 +87,7 @@ namespace gr {
void
- @IMPL_NAME@::set_symbol_table(std::vector<@O_TYPE@> &symbol_table)
+ @IMPL_NAME@::set_symbol_table(const std::vector<@O_TYPE@> &symbol_table)
{
d_symbol_table.resize(0);
for (unsigned int i=0; i<symbol_table.size(); i++) {
diff --git a/gr-digital/lib/chunks_to_symbols_XX_impl.h.t b/gr-digital/lib/chunks_to_symbols_XX_impl.h.t
index 031bb6947c..e0857bfb3c 100644
--- a/gr-digital/lib/chunks_to_symbols_XX_impl.h.t
+++ b/gr-digital/lib/chunks_to_symbols_XX_impl.h.t
@@ -45,7 +45,7 @@ namespace gr {
void set_vector_from_pmt(std::vector<gr_complex> &symbol_table, pmt::pmt_t &symbol_table_pmt);
void handle_set_symbol_table(pmt::pmt_t symbol_table_pmt);
- void set_symbol_table(std::vector<@O_TYPE@> &symbol_table);
+ void set_symbol_table(const std::vector<@O_TYPE@> &symbol_table);
int D() const { return d_D; }
std::vector<@O_TYPE@> symbol_table() const { return d_symbol_table; }
diff --git a/gr-digital/python/digital/qa_chunks_to_symbols.py b/gr-digital/python/digital/qa_chunks_to_symbols.py
index d6a9566807..0d80f71d6c 100755
--- a/gr-digital/python/digital/qa_chunks_to_symbols.py
+++ b/gr-digital/python/digital/qa_chunks_to_symbols.py
@@ -136,6 +136,39 @@ class test_chunks_to_symbols(gr_unittest.TestCase):
actual_result = dst.data()
self.assertEqual(expected_result, actual_result)
+
+ def test_sf_callback(self):
+ constA = [-3, -1, 1, 3]
+ constB = [12, -12, 6, -6]
+ src_data = (0, 1, 2, 3, 3, 2, 1, 0)
+ expected_result=(12, -12, 6, -6, -6, 6, -12, 12)
+
+ src = blocks.vector_source_s(src_data, False, 1, "")
+ op = digital.chunks_to_symbols_sf(constA)
+ op.set_symbol_table(constB)
+ dst = blocks.vector_sink_f()
+ self.tb.connect(src, op)
+ self.tb.connect(op, dst)
+ self.tb.run()
+ actual_result = dst.data()
+ self.assertEqual(expected_result, actual_result)
+
+ def test_sc_callback(self):
+ constA = [-3.0+1j, -1.0-1j, 1.0+1j, 3-1j]
+ constB = [12.0+1j, -12.0-1j, 6.0+1j, -6-1j]
+ src_data = (0, 1, 2, 3, 3, 2, 1, 0)
+ expected_result=(12.0+1j, -12.0-1j, 6.0+1j, -6-1j, -6-1j, 6+1j, -12-1j, 12+1j)
+
+ src = blocks.vector_source_s(src_data, False, 1, "")
+ op = digital.chunks_to_symbols_sc(constA)
+ op.set_symbol_table(constB)
+ dst = blocks.vector_sink_c()
+ self.tb.connect(src, op)
+ self.tb.connect(op, dst)
+ self.tb.run()
+ actual_result = dst.data()
+ self.assertEqual(expected_result, actual_result)
+
def test_sf_tag(self):
constA = [-3.0, -1.0, 1.0, 3]
constB = [12.0, -12.0, 6.0, -6]
diff --git a/gr-fec/examples/271.127.3.112 b/gr-fec/examples/271.127.3.112
new file mode 100644
index 0000000000..205d5adab1
--- /dev/null
+++ b/gr-fec/examples/271.127.3.112
@@ -0,0 +1,402 @@
+271 127
+3 7
+3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
+7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6
+121 50 63
+20 1 68
+98 56 60
+48 99 57
+53 31 59
+93 101 46
+47 15 2
+9 49 75
+38 39 77
+118 16 55
+76 13 40
+29 54 91
+48 23 114
+94 24 68
+100 114 21
+127 19 34
+44 8 33
+3 123 50
+78 100 79
+59 81 98
+67 39 37
+124 54 47
+7 27 64
+67 28 74
+51 75 118
+5 88 55
+45 81 18
+66 103 99
+41 82 102
+65 123 86
+118 25 119
+60 78 113
+89 110 87
+88 30 22
+4 14 44
+110 102 17
+122 125 70
+46 22 109
+16 90 97
+35 73 58
+102 3 119
+127 11 10
+59 36 111
+37 50 78
+34 73 101
+92 74 29
+79 26 40
+97 22 100
+65 84 12
+26 55 9
+38 21 31
+108 45 70
+3 43 26
+57 105 33
+51 31 74
+69 71 60
+96 124 117
+93 72 71
+13 5 30
+42 86 11
+37 6 95
+12 50 47
+43 113 80
+90 107 9
+24 125 44
+83 82 15
+107 28 21
+7 87 81
+124 104 23
+89 121 98
+5 122 27
+83 38 12
+77 120 76
+4 25 33
+40 114 95
+108 20 23
+37 56 2
+126 89 24
+53 52 10
+120 109 117
+49 64 8
+111 6 77
+70 49 19
+112 96 1
+14 72 10
+36 17 87
+7 32 115
+28 34 5
+72 18 8
+29 49 11
+63 119 13
+83 61 11
+27 17 26
+51 93 82
+39 91 61
+30 110 115
+22 15 28
+115 20 42
+96 67 97
+116 38 105
+27 45 32
+16 3 6
+106 14 88
+58 51 61
+103 29 20
+94 84 117
+6 109 13
+19 66 53
+86 30 57
+48 105 43
+35 12 25
+58 14 18
+44 36 1
+62 46 35
+41 64 69
+113 121 1
+9 127 4
+43 92 42
+52 25 104
+35 7 122
+112 120 36
+65 71 23
+52 54 41
+39 85 32
+32 80 24
+48 123 63
+15 40 31
+90 106 56
+21 45 91
+116 92 68
+112 18 116
+80 125 47
+4 17 2
+106 107 101
+94 108 62
+126 69 99
+41 95 34
+111 19 2
+75 62 42
+104 103 33
+84 85 16
+73 46 76
+10 85 8
+79 126 66
+68 63 3
+59 25 91
+69 2 81
+50 23 89
+69 49 22
+80 98 30
+24 31 127
+88 37 104
+52 18 37
+6 104 65
+40 2 22
+6 81 40
+110 33 51
+110 5 42
+112 84 119
+74 53 63
+60 123 124
+4 104 60
+122 105 55
+43 12 16
+126 44 114
+124 84 118
+57 10 50
+98 108 13
+116 22 126
+54 95 18
+107 19 7
+45 28 118
+61 54 72
+6 39 97
+67 34 93
+10 42 121
+94 91 123
+66 96 40
+75 78 44
+71 49 101
+88 83 26
+20 62 7
+119 87 38
+17 32 100
+63 87 85
+92 30 15
+82 23 60
+113 98 20
+5 73 24
+46 102 89
+71 62 58
+65 9 48
+99 45 62
+86 23 26
+91 117 51
+65 42 36
+87 112 126
+127 50 114
+125 124 102
+41 8 114
+54 77 1
+29 99 33
+111 45 47
+30 14 105
+108 107 116
+19 47 32
+76 122 112
+116 21 64
+72 80 92
+110 14 64
+35 108 78
+55 4 89
+115 82 27
+25 56 27
+17 95 111
+59 43 29
+47 61 16
+39 81 90
+15 35 18
+103 85 13
+106 99 34
+109 66 90
+26 115 31
+120 27 3
+83 70 10
+118 57 4
+41 15 58
+34 36 117
+125 28 53
+109 38 24
+35 20 5
+36 96 16
+72 106 19
+1 46 122
+94 76 97
+106 2 61
+80 48 13
+68 52 74
+94 121 82
+86 113 14
+57 37 107
+44 119 48
+121 68 31
+66 46 125
+77 7 79
+90 3 83
+102 9 73
+84 100 58
+29 73 78
+103 67 11
+33 49 32
+12 8 28
+93 69 97
+120 127 67
+71 75 103
+92 101 52
+105 96 85
+120 75 56
+88 79 53
+17 8 1
+59 64 101
+109 12 79
+77 21 113
+11 93 38
+11 74 70
+41 115 123
+25 117 55
+70 86 100
+43 56 76
+95 9 51
+21 111 39
+260 234 201 116 113 84 2
+236 155 147 138 133 77 7
+246 224 145 102 53 41 18
+226 212 162 133 117 74 35
+231 189 158 88 71 59 26
+174 156 154 107 102 82 61
+245 182 171 120 87 68 23
+260 252 200 143 89 81 17
+270 247 192 117 64 50 8
+225 176 167 143 85 79 42
+265 264 250 92 90 60 42
+262 252 164 111 72 62 49
+237 220 168 107 91 59 11
+240 210 204 112 103 85 35
+227 219 186 127 97 66 7
+232 217 164 141 102 39 10
+260 215 184 133 93 86 36
+219 170 153 131 112 89 27
+233 206 171 138 108 83 16
+231 188 182 105 98 76 2
+271 263 208 129 67 51 15
+169 155 149 97 48 38 34
+194 187 148 122 76 69 13
+230 189 151 125 78 65 14
+267 214 146 119 111 74 31
+223 194 181 93 53 50 47
+224 214 213 101 93 71 23
+252 229 172 97 88 67 24
+249 216 202 105 90 46 12
+204 186 150 109 96 59 34
+243 223 151 127 55 51 5
+251 206 184 125 124 101 87
+251 202 157 140 74 54 17
+228 221 175 137 88 45 16
+231 219 211 120 114 111 40
+232 228 196 121 113 86 43
+241 153 152 77 61 44 21
+264 230 183 100 72 51 9
+271 218 174 124 95 21 9
+178 156 155 127 75 47 11
+266 227 200 137 123 115 29
+196 176 158 139 118 98 60
+269 216 164 118 110 63 53
+242 179 165 113 65 35 17
+203 193 172 129 101 52 27
+244 234 190 142 114 38 6
+217 206 203 132 62 22 7
+242 237 192 126 110 13 4
+251 180 149 90 83 81 8
+198 167 148 62 44 18 1
+270 195 157 104 94 55 25
+256 238 153 123 119 79 0
+259 229 160 108 79 5 0
+201 173 170 123 22 12 0
+267 212 163 50 26 10 0
+269 258 214 128 77 3 0
+241 226 167 109 54 4 0
+248 227 191 112 104 40 0
+261 216 146 43 20 5 0
+187 162 161 56 32 3 0
+236 217 173 104 95 92 0
+193 191 182 139 135 114 0
+185 160 145 126 91 1 0
+261 210 208 115 81 23 0
+196 192 154 122 49 30 0
+244 222 178 144 108 28 0
+254 250 175 99 24 21 0
+243 238 145 130 14 2 0
+253 149 147 136 115 56 0
+268 265 225 83 52 37 0
+255 191 180 122 58 56 0
+233 209 173 89 85 58 0
+249 247 189 142 45 40 0
+265 238 160 55 46 24 0
+258 255 179 139 25 8 0
+269 235 207 142 73 11 0
+263 245 201 82 73 9 0
+249 211 179 44 32 19 0
+262 259 245 144 47 19 0
+237 209 150 132 125 63 0
+218 156 147 68 27 20 0
+239 213 187 94 66 29 0
+246 225 181 92 72 66 0
+248 166 159 141 106 49 0
+257 220 185 143 141 124 0
+268 240 194 109 60 30 0
+197 185 183 86 68 33 0
+259 181 152 103 34 26 0
+212 190 148 78 70 33 0
+246 222 218 128 64 39 0
+195 177 146 129 95 12 0
+256 209 186 130 118 46 0
+264 253 175 94 58 6 0
+239 235 177 135 106 14 0
+270 215 170 137 75 61 0
+257 232 178 99 84 57 0
+253 235 174 99 48 39 0
+188 168 150 70 20 3 0
+221 202 193 136 28 4 0
+268 248 184 48 19 15 0
+261 256 180 134 45 6 0
+247 199 190 41 36 29 0
+255 250 220 140 105 28 0
+162 154 152 140 119 69 0
+257 204 163 110 100 54 0
+236 233 221 134 128 103 0
+241 205 171 134 67 64 0
+211 205 168 135 76 52 0
+262 230 222 107 80 38 0
+210 158 157 96 36 33 0
+271 215 203 138 82 43 0
+207 197 159 131 121 84 0
+263 240 188 116 63 32 0
+200 198 165 75 15 13 0
+266 223 213 98 96 87 0
+208 205 169 131 130 100 0
+267 228 195 106 80 57 0
+226 172 166 31 25 10 0
+242 183 159 91 41 31 0
+258 254 224 121 80 73 0
+243 239 176 116 70 1 0
+234 207 163 120 71 37 0
+266 177 161 126 30 18 0
+199 166 161 69 57 22 0
+244 229 199 132 65 37 0
+197 169 165 144 136 78 0
+254 198 151 117 42 16 0
diff --git a/gr-fec/grc/fec_block_tree.xml b/gr-fec/grc/fec_block_tree.xml
index c674531e3f..97610f08c8 100644
--- a/gr-fec/grc/fec_block_tree.xml
+++ b/gr-fec/grc/fec_block_tree.xml
@@ -12,6 +12,7 @@
<name>Decoders</name>
<block>variable_cc_decoder_def</block>
<block>variable_repetition_decoder_def</block>
+ <block>variable_ldpc_decoder_def</block>
<block>variable_dummy_decoder_def</block>
</cat>
<cat>
@@ -19,6 +20,7 @@
<block>variable_cc_encoder_def</block>
<block>variable_ccsds_encoder_def</block>
<block>variable_repetition_encoder_def</block>
+ <block>variable_ldpc_encoder_def</block>
<block>variable_dummy_encoder_def</block>
</cat>
<block>fec_extended_encoder</block>
diff --git a/gr-fec/grc/ldpc_decoder_def_list.xml b/gr-fec/grc/ldpc_decoder_def_list.xml
new file mode 100644
index 0000000000..22df93909f
--- /dev/null
+++ b/gr-fec/grc/ldpc_decoder_def_list.xml
@@ -0,0 +1,88 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+# FEC MAKING FOR GREAT JUSTICE
+###################################################
+ -->
+<block>
+ <name>LDPC Decoder Definition</name>
+ <key>variable_ldpc_decoder_def</key>
+ <import>from gnuradio import fec</import>
+ <var_make>
+#if int($ndim())==0 #
+self.$(id) = $(id) = fec.ldpc_decoder.make($file, $sigma, $max_iter); #slurp
+#else if int($ndim())==1 #
+self.$(id) = $(id) = map( (lambda a: fec.ldpc_decoder.make($file, $sigma, $max_iter)), range(0,$dim1) ); #slurp
+#else
+self.$(id) = $(id) = map( (lambda b: map( ( lambda a: fec.ldpc_decoder.make($file, $sigma, $max_iter)), range(0,$dim2) ) ), range(0,$dim1)); #slurp
+#end if</var_make>
+ <make></make>
+
+<!-- This definition below is wierd, it seems required for the GRC to be happy, im confused -->
+ <param>
+ <name>Ignore Me</name>
+ <key>value</key>
+ <value>"ok"</value>
+ <type>raw</type>
+ <hide>all</hide>
+ </param>
+
+ <param>
+ <name>Parallelism</name>
+ <key>ndim</key>
+ <value>0</value>
+ <type>enum</type>
+ <option>
+ <name>0</name>
+ <key>0</key>
+ </option>
+ <option>
+ <name>1</name>
+ <key>1</key>
+ </option>
+ <option>
+ <name>2</name>
+ <key>2</key>
+ </option>
+ </param>
+
+ <param>
+ <name>Dimension 1</name>
+ <key>dim1</key>
+ <value>4</value>
+ <type>int</type>
+ <hide>#if (int($ndim()) >= 1) then 'none' else 'all' #</hide>
+ </param>
+
+ <param>
+ <name>Dimension 2</name>
+ <key>dim2</key>
+ <value>4</value>
+ <type>int</type>
+ <hide>#if (int($ndim()) >= 2) then 'none' else 'all' #</hide>
+ </param>
+
+ <param>
+ <name>AList File</name>
+ <key>file</key>
+ <type>file_open</type>
+ </param>
+
+ <param>
+ <name>Sigma</name>
+ <key>sigma</key>
+ <value>0.5</value>
+ <type>float</type>
+ </param>
+
+ <param>
+ <name>Max Iterations</name>
+ <key>max_iter</key>
+ <value>50</value>
+ <type>int</type>
+ </param>
+
+ <doc>
+ This block does some kind of ldpc
+ </doc>
+</block>
diff --git a/gr-fec/grc/ldpc_encoder_def_list.xml b/gr-fec/grc/ldpc_encoder_def_list.xml
new file mode 100755
index 0000000000..5975f781dd
--- /dev/null
+++ b/gr-fec/grc/ldpc_encoder_def_list.xml
@@ -0,0 +1,75 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+# FEC MAKING FOR GREAT JUSTICE
+###################################################
+ -->
+<block>
+ <name>LDPC Encoder Definition</name>
+ <key>variable_ldpc_encoder_def</key>
+ <import>from gnuradio import fec</import>
+ <var_make>
+#if int($ndim())==0 #
+self.$(id) = $(id) = fec.ldpc_encoder_make($file); #slurp
+#else if int($ndim())==1 #
+self.$(id) = $(id) = map( (lambda a: fec.ldpc_encoder_make($file)), range(0,$dim1) ); #slurp
+#else
+self.$(id) = $(id) = map( (lambda b: map( ( lambda a: fec.ldpc_encoder_make($file)), range(0,$dim2) ) ), range(0,$dim1)); #slurp
+#end if</var_make>
+ <var_value>fec.ldpc_encoder_make($file)</var_value>
+ <make></make>
+
+<!-- This definition below is wierd, it seems required for the GRC to be happy, im confused -->
+ <param>
+ <name>Ignore Me</name>
+ <key>value</key>
+ <value>"ok"</value>
+ <type>raw</type>
+ <hide>all</hide>
+ </param>
+
+ <param>
+ <name>Parallelism</name>
+ <key>ndim</key>
+ <value>0</value>
+ <type>enum</type>
+ <option>
+ <name>0</name>
+ <key>0</key>
+ </option>
+ <option>
+ <name>1</name>
+ <key>1</key>
+ </option>
+ <option>
+ <name>2</name>
+ <key>2</key>
+ </option>
+ </param>
+
+ <param>
+ <name>Dimension 1</name>
+ <key>dim1</key>
+ <value>1</value>
+ <type>int</type>
+ <hide>#if (int($ndim()) >= 1) then 'none' else 'all' #</hide>
+ </param>
+
+ <param>
+ <name>Dimension 2</name>
+ <key>dim2</key>
+ <value>4</value>
+ <type>int</type>
+ <hide>#if (int($ndim()) >= 2) then 'none' else 'all' #</hide>
+ </param>
+
+ <param>
+ <name>AList File</name>
+ <key>file</key>
+ <type>file_open</type>
+ </param>
+
+ <doc>
+ This block does LDPC
+ </doc>
+</block>
diff --git a/gr-fec/include/gnuradio/fec/alist.h b/gr-fec/include/gnuradio/fec/alist.h
new file mode 100644
index 0000000000..85f6a79cd7
--- /dev/null
+++ b/gr-fec/include/gnuradio/fec/alist.h
@@ -0,0 +1,121 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2015 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+ /* -----------------------------------------------------------------
+ *
+ * This class handles sparse matrices specified in alist-format.
+ * For details about alist format please visit the link below.
+ * - http://www.inference.phy.cam.ac.uk/mackay/codes/alist.html
+ *
+ * Alist class is an efficient way of representing a sparse matrix
+ * the parity check matrix H of an LDPC code for instance.
+ *
+ */
+
+#ifndef ALIST_H
+#define ALIST_H
+
+#include <iostream>
+#include <fstream>
+#include <sstream>
+#include <vector>
+#include <stdlib.h>
+#include <gnuradio/fec/api.h>
+
+class FEC_API alist
+{
+ public:
+
+ //! Default Constructor
+ alist() : data_ok(false) {}
+
+ //! Constructor which loads alist class from an alist-file
+ alist(const char * fname);
+
+ //! Read alist data from a file
+ void read(const char * fname);
+
+ //! Write alist data to a file
+ void write(const char * fname) const;
+
+ //! Retuns N, the number of variable nodes
+ int get_N();
+
+ //! Return M, the number of check nodes
+ int get_M();
+
+ //! Return the m_list variable
+ std::vector< std::vector<int> > get_mlist();
+
+ //! Returns the n_list variable
+ std::vector< std::vector<int> > get_nlist();
+
+ //! Returns the num_mlist variable
+ std::vector<int> get_num_mlist();
+
+ //! Returns the num_nlist variable
+ std::vector<int> get_num_nlist();
+
+ //! Returns the max_num_nlist variable
+ int get_max_num_nlist();
+
+ //! Returns the max_num_mlist variable
+ int get_max_num_mlist();
+
+ //! Prints the nlist[i] variable
+ void print_nlist_i(int i);
+
+ //! Prints the mlist[i] variable
+ void print_mlist_i(int i);
+
+ //! Returns the corresponding H matrix
+ std::vector<std::vector<char> > get_matrix();
+
+ protected:
+ //! A variable indicating if data has been read from alist-file
+ bool data_ok;
+
+ //! Number of variable nodes
+ int N;
+
+ //! Number of check nodes
+ int M;
+
+ //! Maximum weight of rows
+ int max_num_mlist;
+
+ //! Maximum weight of columns
+ int max_num_nlist;
+
+ //! Weight of each column n
+ std::vector<int> num_nlist;
+
+ //! Weight of each row m
+ std::vector<int> num_mlist;
+
+ //! List of integer coordinates along each rows with non-zero entries
+ std::vector< std::vector<int> > mlist;
+
+ //! List of integer coordinates along each column with non-zero entries
+ std::vector< std::vector<int> > nlist;
+};
+#endif // ifndef ALIST_H
diff --git a/gr-fec/include/gnuradio/fec/awgn_bp.h b/gr-fec/include/gnuradio/fec/awgn_bp.h
new file mode 100644
index 0000000000..f420d76394
--- /dev/null
+++ b/gr-fec/include/gnuradio/fec/awgn_bp.h
@@ -0,0 +1,175 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2015 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+/* -----------------------------------------------------------------
+ *
+ * This class defines functions for message passing mechanism for a
+ * AWGN channel. Message passing (also known as belief propagation)
+ * is used for decoding LDPC codes. Details of how LDPC codes are
+ * decoded is available in the link below
+ * - http://www.cs.utoronto.ca/~radford/ftp/LDPC-2012-02-11/decoding.html
+ *
+ * Belief propagation decoding is a suboptimal but efficient method of
+ * decoding LDPC codes.
+ *
+ */
+
+#ifndef AWGN_BP_H
+#define AWGN_BP_H
+
+#include <vector>
+#include <cmath>
+#include <iostream>
+#include "gf2mat.h"
+#include "alist.h"
+#include <gnuradio/fec/api.h>
+
+class FEC_API awgn_bp
+{
+ public:
+ //! Default constructor
+ awgn_bp () {};
+
+ //! A constructor for given GF2Mat and sigma
+ awgn_bp (const GF2Mat X, float sgma);
+
+ //! A constructor for given alist and sigma
+ awgn_bp (alist _list, float sgma);
+
+ //! Initializes the class using given alist and sigma
+ void set_alist_sigma(alist _list, float sgma);
+
+ //! Returns the variable Q
+ std::vector< std::vector<double> > get_Q();
+
+ //! Returns the variable R
+ std::vector< std::vector<double> > get_R();
+
+ //! Returns the variable H
+ GF2Mat get_H();
+
+ //! Calculates the likelihood ratios given an input vector
+ void rx_lr_calc(std::vector<float> codeword);
+
+ //! Returns the variable rx_lr
+ std::vector<double> get_rx_lr();
+
+ //! Returns the variable lr
+ std::vector<double> get_lr();
+
+ //! Initializes the sum product algorithm set-up
+ void spa_initialize();
+
+ //! Updates the check-nodes based on messages from variable nodes
+ void update_chks();
+
+ //! Updates the variable-nodes based on messages from check nodes
+ void update_vars();
+
+ //! Returns the current estimate
+ std::vector<char> get_estimate();
+
+ //! Computes initial estimate based on the vector rx_word
+ void compute_init_estimate(std::vector<float> rx_word);
+
+ //! Computes the estimate based on current likelihood-ratios lr
+ void decision();
+
+ //! Returns the syndrome for the current estimate
+ std::vector<char> get_syndrome();
+
+ //! Returns the syndrome for the input codeword
+ std::vector<char> get_syndrome(const std::vector<char> codeword);
+
+ //! Checks if the current estimate is a codeword
+ bool is_codeword();
+
+ //! Checks if the input is a codeword
+ bool is_codeword(const std::vector<char> codeword);
+
+ //! Sets the variable K
+ void set_K(int k);
+
+ //! Returns the variable K
+ int get_K();
+
+ //! Sets the variable max_iterations
+ void set_max_iterations(int k);
+
+ //! Returns the variable max_iterations
+ int get_max_iterations();
+
+ /*!
+ \brief Decodes the given vector rx_word by message passing.
+
+ \param *niterations is the number of message passing iterations
+ done to decode this codeword
+ */
+ std::vector<char> decode (std::vector<float> rx_word,
+ int *niterations);
+ private:
+ //! The number of check nodes in the tanner-graph
+ int M;
+
+ //! The number of variable nodes in the tanner-graph
+ int N;
+
+ //! The dimension of the code used
+ int K;
+
+ //! The maximum number of message passing iterations allowed
+ int max_iterations;
+
+ //! The parity check matrix of the LDPC code
+ GF2Mat H;
+
+ //! The standard-deviation of the AWGN channel
+ float sigma;
+
+ //! Matrix holding messages from check nodes to variable nodes
+ std::vector< std::vector<double> > R;
+
+ //! Matrix holding messages from variable nodes to check nodes
+ std::vector< std::vector<double> > Q;
+
+ //! The array of likelihood computed from the channel output
+ std::vector<double> rx_lr;
+
+ //! The array for holding likelihoods computed on BP decoding
+ std::vector<double> lr;
+
+ //! List of integer coordinates along each column with non-zero entries
+ std::vector < std::vector<int> > nlist;
+
+ //! List of integer coordinates along each row with non-zero entries
+ std::vector < std::vector<int> > mlist;
+
+ //! Weight of each column n
+ std::vector <int> num_nlist;
+
+ //! Weight of each row m
+ std::vector <int> num_mlist;
+
+ //! The array for holding estimate computed on BP decoding
+ std::vector<char> estimate;
+};
+#endif // ifndef AWGN_BP_H
diff --git a/gr-fec/include/gnuradio/fec/cldpc.h b/gr-fec/include/gnuradio/fec/cldpc.h
new file mode 100644
index 0000000000..6bc7c02343
--- /dev/null
+++ b/gr-fec/include/gnuradio/fec/cldpc.h
@@ -0,0 +1,115 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2015 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 LDPC_H
+#define LDPC_H
+
+#include <iostream>
+#include <vector>
+
+#include "gnuradio/fec/gf2vec.h"
+#include "gnuradio/fec/gf2mat.h"
+#include "gnuradio/fec/alist.h"
+
+
+#include <gnuradio/fec/api.h>
+class FEC_API cldpc
+{
+ public:
+ //! Default constructor
+ cldpc() {};
+
+ //! Constructs the LDPC class from given GF2mat X
+ cldpc(const GF2Mat X);
+
+ //! Constructs the class from the given alist _list
+ cldpc(const alist _list);
+
+ //! Prints the variable permute
+ void print_permute();
+
+ /*!
+ \brief Encode the given vector dataword.
+
+ dataword is of length K where K is the dimension of the code.
+ The function returns a vector of length N where N is the
+ block-length of the code.
+
+ For encoding a G matrix in the form [I P] is obtained from the
+ parity matrix H, by (a) Column permutations, (b) Row additions
+ and (c) Row permutations. Details of encoding is given in
+ section A.1 of the reference given below.
+ - "Modern Coding Theory", T Richardson and R Urbanke.
+ */
+ std::vector<char> encode(std::vector<char> dataword);
+
+ //! Returns the dimension of the code
+ int dimension();
+
+ //! Returns the parity check matrix H
+ GF2Mat get_H();
+
+ //! Returns the matrix G used in encoding
+ GF2Mat get_G();
+
+ //! Returns the variable M
+ int get_M();
+
+ //! Returns the variable N
+ int get_N();
+
+ //! Returns the syndrome for a given vector "in"
+ std::vector<char> syndrome(const std::vector<char> in);
+
+ //! Returns true if "in" is a codeword, else false
+ bool is_codeword(const std::vector<char> in);
+
+ //! Set the variable _list
+ void set_alist(const alist _list);
+
+ //! Obtain systematic bits from "in"
+ std::vector<char> get_systematic_bits(std::vector<char> in);
+
+ private:
+ //! The parity check matrix
+ GF2Mat H;
+
+ //! An equivalent matrix obtained from H used for encoding
+ GF2Mat G;
+
+ //! Stores the column permutation in obtaining G from H
+ std::vector<int> permute;
+
+ //! Rank of the H matrix
+ int rank_H;
+
+ //! The number of check nodes in the Tanner-graph
+ int M;
+
+ //! The number of variable nodes in the Tanner-graph
+ int N;
+
+ //! The dimension of the code
+ size_t K;
+};
+
+#endif // ifndef LDPC_H
diff --git a/gr-fec/include/gnuradio/fec/generic_decoder.h b/gr-fec/include/gnuradio/fec/generic_decoder.h
index 0e14d49e76..bfce85a8c1 100644
--- a/gr-fec/include/gnuradio/fec/generic_decoder.h
+++ b/gr-fec/include/gnuradio/fec/generic_decoder.h
@@ -210,6 +210,15 @@ namespace gr {
* behavior. It should also provide bounds checks.
*/
virtual bool set_frame_size(unsigned int frame_size) = 0;
+
+
+ /*!
+ * Get repetitions to decode.
+ *
+ * The child class should implement this function and return the
+ * number of iterations required to decode.
+ */
+ virtual float get_iterations(){ return -1; }
};
/*! see generic_decoder::get_output_size() */
diff --git a/gr-fec/include/gnuradio/fec/gf2mat.h b/gr-fec/include/gnuradio/fec/gf2mat.h
new file mode 100644
index 0000000000..963b20830d
--- /dev/null
+++ b/gr-fec/include/gnuradio/fec/gf2mat.h
@@ -0,0 +1,111 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2015 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 GF2MAT_H
+#define GF2MAT_H
+#include <vector>
+#include "gf2vec.h"
+#include "alist.h"
+
+class GF2Mat
+{
+ //! The matrix H
+ std::vector < std::vector <char> > H;
+
+ //! Number of rows in H
+ int M;
+
+ //! Number of columns in H
+ int N;
+
+ public:
+ //! Default constructor
+ GF2Mat() {};
+
+ //! Construct an M x N matrix with all 0 entries
+ GF2Mat(int m, int n);
+
+ //! Loads the matrix from alist _list
+ GF2Mat(alist _list);
+
+ //! Initializes the class from a 2-D vector X
+ GF2Mat(std::vector <std::vector <char> > X);
+
+ //! Returns the variable M
+ int get_M();
+
+ //! Returns the variable N
+ int get_N();
+
+ //! Set the element at (i, j) coordinate to val
+ void set_element(int i, int j, char val);
+
+ //! Returns the element at coordinate (i, j)
+ char get_element(int i, int j);
+
+ //! Returns the ith row
+ GF2Vec get_row(int i);
+
+ //! Returns the ith column
+ GF2Vec get_col(int i);
+
+ //! Returns the ith row
+ GF2Vec operator[](int i);
+
+ //! Prints the matrix H
+ void print_matrix();
+
+ //! Sets the ith column with the given vector
+ void set_col(int i, GF2Vec vec);
+
+ //! Sets the ith row with the given vector
+ void set_row(int i, GF2Vec vec);
+
+ //! Swaps columns i and j
+ void swap_cols(int i, int j);
+
+ //! Adds column j to i and replace i with the sum
+ void add_cols(int i, int j);
+
+ //! Add row j to i and replace j with the sum
+ void add_rows(int i, int j);
+
+ //! Returns the variable H
+ std::vector<std::vector<char> > get_H();
+
+ /*!
+ \brief Obtains an equivalent representation of H for encoding
+
+ For encoding a G matrix in the form [I P] is obtained from the
+ parity matrix H, by (a) Column permutations, (b) Row additions
+ and (c) Row permutations. Details of encoding is given in
+ section A.1 of the reference given below.
+ - "Modern Coding Theory", T Richardson and R Urbanke.
+
+ \param p is the column permutation during this operation
+ \
+ */
+ GF2Mat get_G(std::vector<int> & p, int & rank);
+
+};
+
+#endif // #ifndef GF2MAT_H
diff --git a/gr-fec/include/gnuradio/fec/gf2vec.h b/gr-fec/include/gnuradio/fec/gf2vec.h
new file mode 100644
index 0000000000..1b406c0278
--- /dev/null
+++ b/gr-fec/include/gnuradio/fec/gf2vec.h
@@ -0,0 +1,71 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2015 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 GF2VEC_H
+#define GF2VEC_H
+#include <vector>
+
+class GF2Vec
+{
+ //! The vector vec
+ std::vector<char> vec;
+
+ //! Resize the vector
+ void resize(int size);
+
+ public:
+
+ //! Default constructor
+ GF2Vec() {}
+
+ //! Constructs a vector of length "size" with all 0 entries
+ GF2Vec(int size);
+
+ //! Returns the vector
+ std::vector<char> get_vec();
+
+ //! Returns the size of the vector
+ int size();
+
+ //! Resets the vector with the given input
+ void set_vec(std::vector<char>);
+
+ //! Access the ith element
+ char & operator [](int i);
+
+ //! Overloading the operator '='
+ void operator=(GF2Vec x);
+
+ //! Obtain a subvector between the indices i to j
+ GF2Vec sub_vector(int i, int j);
+
+ //! Overloading the operator '+'
+ friend GF2Vec operator+(GF2Vec a, GF2Vec b);
+
+ //! Overloading the operator '*'
+ friend char operator*(GF2Vec a, GF2Vec b);
+
+ //! Prints the vector
+ void print_vec();
+};
+
+#endif // #ifndef GF2VEC_H
diff --git a/gr-fec/include/gnuradio/fec/ldpc_decoder.h b/gr-fec/include/gnuradio/fec/ldpc_decoder.h
new file mode 100644
index 0000000000..02cf12d585
--- /dev/null
+++ b/gr-fec/include/gnuradio/fec/ldpc_decoder.h
@@ -0,0 +1,79 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2015 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_LDPC_DECODER_H
+#define INCLUDED_LDPC_DECODER_H
+
+typedef float INPUT_DATATYPE;
+typedef unsigned char OUTPUT_DATATYPE;
+
+#include <map>
+#include <string>
+#include <gnuradio/fec/decoder.h>
+#include <vector>
+
+#include <gnuradio/fec/cldpc.h>
+#include <gnuradio/fec/alist.h>
+#include <gnuradio/fec/awgn_bp.h>
+
+namespace gr {
+ namespace fec {
+
+
+#define MAXLOG 1e7
+
+class FEC_API ldpc_decoder : public generic_decoder {
+ //private constructor
+ ldpc_decoder (std::string alist_file, float sigma, int max_iterations);
+
+ //plug into the generic fec api
+ int get_history();
+ float get_shift();
+ const char* get_conversion();
+ void generic_work(void *inBuffer, void *outbuffer);
+ float d_iterations;
+ int inputSize, outputSize;
+
+ alist d_list;
+ cldpc d_code;
+ awgn_bp d_spa;
+
+ public:
+ ~ldpc_decoder ();
+
+ double rate() { return (1.0*get_output_size() / get_input_size()); }
+ bool set_frame_size(unsigned int frame_size) { return false; }
+
+ static generic_decoder::sptr
+ make (std::string alist_file, float sigma=0.5, int max_iterations=50);
+ int get_output_size();
+ int get_input_size();
+ int get_input_item_size();
+ int get_output_item_size();
+ float get_iterations(){ return d_iterations; }
+
+};
+
+}
+}
+
+#endif /* INCLUDED_LDPC_DECODER_H */
diff --git a/gr-fec/include/gnuradio/fec/ldpc_encoder.h b/gr-fec/include/gnuradio/fec/ldpc_encoder.h
new file mode 100755
index 0000000000..1ed02e8efe
--- /dev/null
+++ b/gr-fec/include/gnuradio/fec/ldpc_encoder.h
@@ -0,0 +1,61 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2015 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_LDPC_ENCODER_H
+#define INCLUDED_LDPC_ENCODER_H
+
+#include <gnuradio/fec/encoder.h>
+#include <gnuradio/fec/cldpc.h>
+#include <gnuradio/fec/alist.h>
+#include <map>
+#include <string>
+#include <vector>
+
+namespace gr {
+ namespace fec {
+
+ class FEC_API ldpc_encoder : public generic_encoder {
+ //private constructor
+ ldpc_encoder (std::string alist_file);
+
+ //plug into the generic fec api
+ void generic_work(void *inBuffer, void *outbuffer);
+
+ // memory allocated for processing
+ int outputSize;
+ int inputSize;
+ alist d_list;
+ cldpc d_code;
+
+ public:
+ ~ldpc_encoder ();
+ static generic_encoder::sptr make (std::string alist_file);
+ double rate() { return (1.0*get_input_size() / get_output_size()); }
+ bool set_frame_size(unsigned int frame_size) { return false; }
+ int get_output_size();
+ int get_input_size();
+ };
+
+ }
+}
+
+#endif /* INCLUDED_LDPC_ENCODER_H */
diff --git a/gr-fec/include/gnuradio/fec/maxstar.h b/gr-fec/include/gnuradio/fec/maxstar.h
new file mode 100644
index 0000000000..f226550e5c
--- /dev/null
+++ b/gr-fec/include/gnuradio/fec/maxstar.h
@@ -0,0 +1,99 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2015 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.
+ */
+
+/* File maxstar.h
+
+ Description: Performs the max* operations (Jacobian logarithm) defined as:
+ max*( x, y ) = max( x,y) + log( 1 + exp( - |x-y| ) )
+
+ There are several versions of this function, max_starX, where "X":
+ X = 0 For linear approximation to log-MAP
+ = 1 For max-log-MAP algorithm (i.e. max*(x,y) = max(x,y) )
+ = 2 For Constant-log-MAP algorithm
+ = 3 For log-MAP, correction factor from small nonuniform table and interpolation
+ = 4 For log-MAP, correction factor uses C function calls
+
+ Calling syntax:
+ output = max_starX( delta1, delta2 )
+
+ Where:
+ output = The result of max*(x,y)
+
+ delta1 = T] he first argument (i.e. x) of max*(x,y)
+ delta2 = The second argument (i.e. y) of max*(x,y)
+
+ Functions max_star0, max_star1, max_star2, max_star3, and max_star4
+ are part of the Iterative Solutions Coded Modulation Library
+ The Iterative Solutions Coded Modulation Library is free software;
+ you can redistribute it and/or modify it under the terms of
+ the GNU Lesser General Public License as published by the
+ Free Software Foundation; either version 2.1 of the License,
+ or (at your option) any later version.
+
+*/
+
+#ifndef INCLUDED_FECAPI_MAXSTAR_H
+#define INCLUDED_FECAPI_MAXSTAR_H
+
+/* values for the jacobian logarithm table (DecoderType=4) */
+#define BOUNDARY0 0
+#define BOUNDARY1 0.4200
+#define BOUNDARY2 0.8500
+#define BOUNDARY3 1.3100
+#define BOUNDARY4 1.8300
+#define BOUNDARY5 2.4100
+#define BOUNDARY6 3.1300
+#define BOUNDARY7 4.0800
+#define BOUNDARY8 5.6000
+
+#define SLOPE0 -0.44788139700522
+#define SLOPE1 -0.34691145436176
+#define SLOPE2 -0.25432579542705
+#define SLOPE3 -0.17326680196715
+#define SLOPE4 -0.10822110027877
+#define SLOPE5 -0.06002650498009
+#define SLOPE6 -0.02739265095522
+#define SLOPE7 -0.00860202759280
+
+#define VALUE0 0.68954718055995
+#define VALUE1 0.50153699381775
+#define VALUE2 0.35256506844219
+#define VALUE3 0.23567520254575
+#define VALUE4 0.14607646552283
+#define VALUE5 0.08360822736113
+#define VALUE6 0.04088914377547
+#define VALUE7 0.01516612536801
+
+/* values for the constant log-MAP algorithm (DecoderType=3) */
+#define CVALUE 0.5
+#define TVALUE 1.5
+
+/* values for the linear approximation (DecoderType=1) */
+#define TTHRESH 2.508
+#define AVALUE -0.236
+#define BVALUE 0.592
+
+/* Values for linear approximation (DecoderType=5) */
+#define AJIAN -0.24904163195436
+#define TJIAN 2.50681740420944
+
+#endif
diff --git a/gr-fec/lib/CMakeLists.txt b/gr-fec/lib/CMakeLists.txt
index 884bb4489a..99f701cc2c 100644
--- a/gr-fec/lib/CMakeLists.txt
+++ b/gr-fec/lib/CMakeLists.txt
@@ -71,6 +71,13 @@ list(APPEND gnuradio_fec_sources
puncture_bb_impl.cc
puncture_ff_impl.cc
depuncture_bb_impl.cc
+ ldpc_encoder.cc
+ ldpc_decoder.cc
+ cldpc.cc
+ awgn_bp.cc
+ gf2vec.cc
+ gf2mat.cc
+ alist.cc
)
#Add Windows DLL resource file if using MSVC
diff --git a/gr-fec/lib/alist.cc b/gr-fec/lib/alist.cc
new file mode 100644
index 0000000000..ac7cb3384e
--- /dev/null
+++ b/gr-fec/lib/alist.cc
@@ -0,0 +1,205 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2015 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include <gnuradio/fec/alist.h>
+
+alist::alist(const char * fname)
+ : data_ok(false) {
+ read(fname);
+}
+
+std::vector<std::vector<char> > alist::get_matrix() {
+ std::vector<std::vector<char> > mat;
+ mat.resize(M);
+ for ( int i = 0; i < M; i++ ) {
+ mat[i].resize(N);
+ for ( int j = 0; j < N; j++ ) {
+ mat[i][j] = char(0);
+ }
+ for ( int k = 0; k < num_mlist[i]; k++ ) {
+ mat[i][mlist[i][k] - 1] = char(1);
+ }
+ }
+ return mat;
+}
+
+std::vector< std::vector<int> > alist::get_mlist() {
+ return mlist;
+}
+
+std::vector< std::vector<int> > alist::get_nlist() {
+ return nlist;
+}
+
+std::vector<int> alist::get_num_mlist() {
+ return num_mlist;
+}
+
+std::vector<int> alist::get_num_nlist() {
+ return num_nlist;
+}
+
+void alist::read(const char * fname) {
+ std::ifstream file;
+ std::string line;
+ std::stringstream ss;
+
+ file.open(fname);
+ if(!(file.is_open())) {
+ std::cout << "Could not open the file" << std::endl;
+ }
+
+ // Parse N and M
+ std::getline(file, line);
+ ss << line;
+ ss >> N >> M;
+ num_nlist.resize(N);
+ num_mlist.resize(M);
+ nlist.resize(N);
+ mlist.resize(M);
+ ss.seekg(0, std::ios::end);
+ ss.clear();
+
+ // parse max_num_n and max_num_m
+ std::getline(file, line);
+ ss << line;
+ ss >> max_num_nlist >> max_num_mlist;
+ ss.seekg(0, std::ios::end);
+ ss.clear();
+
+ // Parse weight of each column n
+ std::getline(file, line);
+ ss << line;
+ for (int i = 0; i < N; i++ ) {
+ ss >> num_nlist[i];
+ nlist[i].resize(num_nlist[i]);
+ }
+ ss.seekg(0, std::ios::end);
+ ss.clear();
+
+ // Parse weight of each row m
+ std::getline(file, line);
+ ss << line;
+ for (int i = 0; i < M; i++ ) {
+ ss >> num_mlist[i];
+ mlist[i].resize(num_mlist[i]);
+ }
+ ss.seekg(0, std::ios::end);
+ ss.clear();
+
+ // Parse indices with non zero entries in ith column
+ for (int column = 0; column < N; column++) {
+ std::getline(file, line);
+ ss << line;
+ for (int entry = 0; entry < num_nlist[column]; entry++) {
+ ss >> nlist[column][entry];
+ }
+ ss.seekg(0, std::ios::end);
+ ss.clear();
+ }
+
+ // Parse indices with non zero entries in ith row
+ for (int row = 0; row < M; row++) {
+ std::getline(file, line);
+ ss << line;
+ for (int entry = 0; entry < num_mlist[row]; entry++) {
+ ss >> mlist[row][entry];
+ }
+ ss.seekg(0, std::ios::end);
+ ss.clear();
+ }
+
+ file.close();
+ data_ok = true;
+}
+
+void alist::write(const char * fname) const
+{
+ if (!data_ok) {
+ std::cout << "Data not ok, exiting" << std::endl;
+ exit(1);
+ }
+ // Else
+ std::ofstream file(fname, std::ofstream::out);
+ // Write N and M
+ file << N << " " << M << std::endl;
+ file << max_num_nlist << " " << max_num_mlist << std::endl;
+ // Write column weights
+ for (size_t i = 0; i < num_nlist.size() - 1; i++) {
+ file << num_nlist[i] << " ";
+ }
+ file << num_nlist[num_nlist.size() - 1] << std::endl;
+ // Write row weights
+ for (size_t i = 0; i < num_mlist.size() - 1; i++) {
+ file << num_mlist[i] << " ";
+ }
+ file << num_mlist[num_mlist.size() - 1] << std::endl;
+ // Write non zero indices in the ith column
+ for (int i = 0; i < N; i++) {
+ for (int j = 0; j < num_nlist[i] - 1; j++) {
+ file << nlist[i][j] << "\t";
+ }
+ file << nlist[i][num_nlist[i] - 1];
+ file << std::endl;
+ }
+ // Write non zero indices in the ith row
+ for (int i = 0; i < M; i++) {
+ for (int j = 0; j < num_mlist[i] - 1; j++) {
+ file << mlist[i][j] << "\t";
+ }
+ file << mlist[i][num_mlist[i] - 1];
+ file << std::endl;
+ }
+ file.close();
+}
+
+int alist::get_N() {
+ return N;
+}
+
+int alist::get_M() {
+ return M;
+}
+
+int alist::get_max_num_nlist() {
+ return max_num_nlist;
+}
+
+int alist::get_max_num_mlist() {
+ return max_num_mlist;
+}
+
+void alist::print_nlist_i(int column) {
+ std::cout << "Indices in column " << column << std::endl;
+ for (int i = 0; i < num_nlist[column] - 1; i++) {
+ std::cout << nlist[column][i] << ", ";
+ }
+ std::cout << nlist[column][num_nlist[column] - 1] << std::endl;
+}
+
+void alist::print_mlist_i(int row) {
+ std::cout << "Indices in row " << row << std::endl;
+ for (int i = 0; i < num_mlist[row] - 1; i++) {
+ std::cout << mlist[row][i] << ", ";
+ }
+ std::cout << mlist[row][num_mlist[row] - 1] << std::endl;
+}
diff --git a/gr-fec/lib/async_decoder_impl.cc b/gr-fec/lib/async_decoder_impl.cc
index f5924ec1f9..2cdea6a1a6 100644
--- a/gr-fec/lib/async_decoder_impl.cc
+++ b/gr-fec/lib/async_decoder_impl.cc
@@ -114,15 +114,27 @@ namespace gr {
int diff = d_decoder->rate()*d_decoder->get_input_size() - d_decoder->get_output_size();
int nbits_in = pmt::length(bits);
- int nbits_out = nbits_in*d_decoder->rate() - diff;
+ size_t nbits_out = 0;
+ size_t nblocks = 1;
+ bool variable_frame_size = d_decoder->set_frame_size(nbits_out);
// Check here if the frame size is larger than what we've
// allocated for in the constructor.
- if(nbits_in > d_max_bits_in) {
+ if(variable_frame_size && (nbits_in > d_max_bits_in)) {
throw std::runtime_error("async_decoder: Received frame larger than max frame size.");
}
- d_decoder->set_frame_size(nbits_out);
+ // set up nbits_out
+ if(variable_frame_size){
+ nbits_out = nbits_in*d_decoder->rate() - diff;
+ } else {
+ nblocks = nbits_in / d_decoder->get_input_size();
+ nbits_out = nblocks * d_decoder->get_output_size();
+ if(nblocks * d_decoder->get_input_size() != nbits_in){
+ throw std::runtime_error("bad block multiple in!");
+ }
+ }
+
size_t o0(0);
const float* f32in = pmt::f32vector_elements(bits, o0);
@@ -133,6 +145,14 @@ namespace gr {
volk_32f_s32f_multiply_32f(d_tmp_f32, f32in, 48.0f, nbits_in);
}
else {
+
+ // grow d_tmp_f32 if needed
+ if(nbits_in > d_max_bits_in){
+ d_max_bits_in = nbits_in;
+ volk_free(d_tmp_f32);
+ d_tmp_f32 = (float*)volk_malloc(d_max_bits_in*sizeof(float),
+ volk_get_alignment());
+ }
memcpy(d_tmp_f32, f32in, nbits_in*sizeof(float));
}
@@ -149,9 +169,12 @@ namespace gr {
d_decoder->generic_work((void*)d_tmp_u8, (void*)u8out);
}
else {
- d_decoder->generic_work((void*)d_tmp_f32, (void*)u8out);
+ for(size_t i=0; i<nblocks; i++){
+ d_decoder->generic_work((void*)&d_tmp_f32[i*d_decoder->get_input_size()], (void*)&u8out[i*d_decoder->get_output_size()]);
+ }
}
+ meta = pmt::dict_add(meta, pmt::mp("iterations"), pmt::mp(d_decoder->get_iterations()) );
message_port_pub(d_out_port, pmt::cons(meta, outvec));
}
diff --git a/gr-fec/lib/async_encoder_impl.cc b/gr-fec/lib/async_encoder_impl.cc
index d6ce67d491..106ad25cc4 100644
--- a/gr-fec/lib/async_encoder_impl.cc
+++ b/gr-fec/lib/async_encoder_impl.cc
@@ -110,9 +110,21 @@ namespace gr {
int nbits_in = pmt::length(bits);
const uint8_t* bits_in = pmt::u8vector_elements(bits, o0);
- d_encoder->set_frame_size(nbits_in);
+ bool variable_framesize = d_encoder->set_frame_size(nbits_in);
+ size_t nbits_out = 0;
+ size_t nblocks = 1;
+ if( variable_framesize ){
+ nbits_out = d_encoder->get_output_size();
+ } else {
+ nblocks = nbits_in / d_encoder->get_input_size();
+ if( nblocks * d_encoder->get_input_size() != nbits_in ){
+ printf("nblocks: %d, in_block_size: %d, got_input_size: %d\n",
+ nblocks, d_encoder->get_input_size(), nbits_in);
+ throw std::runtime_error("input does not divide into code block size!");
+ }
+ nbits_out = nblocks * d_encoder->get_output_size();
+ }
- int nbits_out = d_encoder->get_output_size();
// buffers for output bits to go to
pmt::pmt_t outvec = pmt::make_u8vector(nbits_out, 0x00);
@@ -123,7 +135,9 @@ namespace gr {
d_encoder->generic_work((void*)d_bits_in, (void*)bits_out);
}
else {
- d_encoder->generic_work((void*)bits_in, (void*)bits_out);
+ for(size_t i=0; i<nblocks; i++){
+ d_encoder->generic_work((void*) &bits_in[i*d_encoder->get_input_size()], (void*)&bits_out[i*d_encoder->get_output_size()]);
+ }
}
pmt::pmt_t msg_pair = pmt::cons(meta, outvec);
diff --git a/gr-fec/lib/awgn_bp.cc b/gr-fec/lib/awgn_bp.cc
new file mode 100644
index 0000000000..66a50c0d56
--- /dev/null
+++ b/gr-fec/lib/awgn_bp.cc
@@ -0,0 +1,259 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2015 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include <gnuradio/fec/awgn_bp.h>
+
+awgn_bp::awgn_bp ( const GF2Mat X, float sgma) {
+ H = X;
+ M = H.get_M();
+ N = H.get_N();
+ Q.resize(M);
+ R.resize(M);
+ sigma = sgma;
+ for (int i = 0; i < M; i++) {
+ Q[i].resize(N);
+ R[i].resize(N);
+ }
+ lr.resize(N);
+ estimate.resize(N);
+}
+
+awgn_bp::awgn_bp ( alist _list, float sgma) {
+ H = GF2Mat(_list);
+ mlist = _list.get_mlist();
+ nlist = _list.get_nlist();
+ num_mlist = _list.get_num_mlist();
+ num_nlist = _list.get_num_nlist();
+ M = H.get_M();
+ N = H.get_N();
+ Q.resize(M);
+ R.resize(M);
+ sigma = sgma;
+ for (int i = 0; i < M; i++) {
+ Q[i].resize(N);
+ R[i].resize(N);
+ }
+ lr.resize(N);
+ estimate.resize(N);
+}
+
+void awgn_bp::set_alist_sigma(alist _list, float sgma) {
+ H = GF2Mat(_list);
+ mlist = _list.get_mlist();
+ nlist = _list.get_nlist();
+ num_mlist = _list.get_num_mlist();
+ num_nlist = _list.get_num_nlist();
+ M = H.get_M();
+ N = H.get_N();
+ Q.resize(M);
+ R.resize(M);
+ sigma = sgma;
+ for (int i = 0; i < M; i++) {
+ Q[i].resize(N);
+ R[i].resize(N);
+ }
+ lr.resize(N);
+ estimate.resize(N);
+}
+
+std::vector< std::vector<double> > awgn_bp::get_Q() {
+ return Q;
+}
+
+std::vector< std::vector<double> > awgn_bp::get_R() {
+ return R;
+}
+
+GF2Mat awgn_bp::get_H() {
+ return H;
+}
+
+void awgn_bp::rx_lr_calc(std::vector<float> codeword) {
+ rx_lr.resize(N);
+ float y;
+ for ( int i = 0; i < N; i++){
+ y = codeword[i];
+ rx_lr[i] = exp((-1*y)/(2*sigma*sigma));
+ }
+}
+
+std::vector<double> awgn_bp::get_rx_lr() {
+ return rx_lr;
+}
+
+std::vector<double> awgn_bp::get_lr() {
+ return lr;
+}
+
+void awgn_bp::spa_initialize() {
+ int row;
+ for ( int var = 0; var < N; var++ ) {
+ for ( int i = 0; i < num_nlist[var]; i++ ) {
+ row = nlist[var][i] - 1;
+ Q[row][var] = rx_lr[var];
+ }
+ }
+}
+
+void awgn_bp::update_chks() {
+ double product, _prdct;
+ int v;
+ for ( int chk = 0; chk < M; chk++ ) {
+ product = double(1.0);
+ for (int i = 0; i < num_mlist[chk]; i++) {
+ v = mlist[chk][i] - 1;
+ product = product*double( 2/(1 + Q[chk][v]) - 1 );
+ }
+ for ( int i = 0; i < num_mlist[chk]; i++ ) {
+ v = mlist[chk][i] - 1;
+ _prdct = product/double( 2/(1 + Q[chk][v]) - 1);
+ R[chk][v] = double((1 - _prdct)/(1 + _prdct));
+ }
+ }
+}
+
+void awgn_bp::update_vars() {
+ double _sum, __sum;
+ int c;
+ for ( int var = 0; var < N; var++ ) {
+ _sum = rx_lr[var];
+ for ( int i = 0; i < num_nlist[var]; i++ ) {
+ c = nlist[var][i] - 1;
+ _sum = _sum * double(R[c][var]);
+ }
+ lr[var] = _sum;
+ for ( int i = 0; i < num_nlist[var]; i++ ) {
+ c = nlist[var][i] - 1;
+ __sum = _sum/R[c][var];
+ Q[c][var] = __sum;
+ }
+ }
+}
+
+std::vector<char> awgn_bp::get_estimate() {
+ return estimate;
+}
+
+void awgn_bp::compute_init_estimate(std::vector<float> rx_word) {
+ for (size_t i = 0; i < rx_word.size(); i++ ) {
+ if (rx_word[i] < 0)
+ estimate[i] = char(1);
+ else
+ estimate[i] = char(0);
+ }
+}
+
+void awgn_bp::decision() {
+ for ( int i = 0; i < N; i++ ){
+ if ( lr[i] > 1 )
+ estimate[i] = char(1);
+ else
+ estimate[i] = char(0);
+ }
+}
+
+void awgn_bp::set_K(int k) {
+ K = k;
+}
+
+int awgn_bp::get_K() {
+ return K;
+}
+
+std::vector<char> awgn_bp::get_syndrome(std::vector<char> codeword) {
+ std::vector<char> synd;
+ synd.resize(N - K);
+ GF2Vec in_bvec;
+ in_bvec.set_vec(codeword);
+ for ( int i = 0; i < N - K; i++ ) {
+ synd[i] = H[i]*in_bvec;
+ }
+ return synd;
+}
+
+std::vector<char> awgn_bp::get_syndrome() {
+ std::vector<char> synd;
+ synd.resize(N - K);
+ GF2Vec in_bvec;
+ in_bvec.set_vec(estimate);
+ for ( int i = 0; i < N - K; i++ ) {
+ synd[i] = H[i]*in_bvec;
+ }
+ return synd;
+}
+
+bool awgn_bp::is_codeword(std::vector<char> codeword) {
+ std::vector<char> synd;
+ synd = get_syndrome(codeword);
+ bool is_code;
+ is_code = true;
+ for ( int i = 0; i < N - K; i++ ) {
+ if ( synd[i] != char(0) ) {
+ is_code = false;
+ }
+ }
+ return is_code;
+}
+
+bool awgn_bp::is_codeword() {
+ std::vector<char> synd;
+ synd = get_syndrome();
+ bool is_code;
+ is_code = true;
+ for ( int i = 0; i < N - K; i++ ) {
+ if ( synd[i] != char(0) ) {
+ is_code = false;
+ }
+ }
+ return is_code;
+}
+
+void awgn_bp::set_max_iterations(int k) {
+ max_iterations = k;
+}
+
+int awgn_bp::get_max_iterations() {
+ return max_iterations;
+}
+
+std::vector<char> awgn_bp::decode(std::vector<float> rx_word,
+ int *niteration) {
+ *niteration = 0;
+ compute_init_estimate(rx_word);
+ if (is_codeword()) {
+ return estimate;
+ }
+ else {
+ rx_lr_calc(rx_word);
+ spa_initialize();
+ while (*niteration < max_iterations) {
+ *niteration += 1;
+ update_chks();
+ update_vars();
+ decision();
+ if (is_codeword()) {
+ break;
+ }
+ }
+ return estimate;
+ }
+}
diff --git a/gr-fec/lib/cldpc.cc b/gr-fec/lib/cldpc.cc
new file mode 100644
index 0000000000..df7be904f0
--- /dev/null
+++ b/gr-fec/lib/cldpc.cc
@@ -0,0 +1,132 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2015 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include <gnuradio/fec/cldpc.h>
+#include <stdexcept>
+
+cldpc::cldpc(const GF2Mat X) {
+ H = X;
+ M = H.get_M();
+ N = H.get_N();
+ G = H.get_G(permute, rank_H);
+ K = N - rank_H;
+}
+
+cldpc::cldpc(const alist _list) {
+ H = GF2Mat(_list);
+ M = H.get_M();
+ N = H.get_N();
+ G = H.get_G(permute, rank_H);
+ K = N - rank_H;
+}
+
+void cldpc::set_alist(const alist _list) {
+ H = GF2Mat(_list);
+ M = H.get_M();
+ N = H.get_N();
+ G = H.get_G(permute, rank_H);
+ K = N - rank_H;
+}
+
+std::vector<char> cldpc::get_systematic_bits(std::vector<char> in) {
+ std::vector<char> data;
+ data.resize(K);
+ int index;
+ for (size_t i = 0; i < K; i++ ) {
+ index = permute[i + rank_H];
+ data[i] = in[index];
+ }
+ return data;
+}
+
+void cldpc::print_permute() {
+ for (size_t i = 0; i < permute.size(); i++ ) {
+ std::cout << permute[i] << ", ";
+ }
+ std::cout << "\n";
+}
+
+std::vector<char> cldpc::syndrome(const std::vector<char> in) {
+ std::vector<char> synd;
+ synd.resize(rank_H);
+ GF2Vec in_bvec;
+ in_bvec.set_vec(in);
+ for ( int i = 0; i < rank_H; i++ ) {
+ synd[i] = H[i]*in_bvec;
+ }
+ return synd;
+}
+
+bool cldpc::is_codeword(const std::vector<char> in) {
+ std::vector<char> synd;
+ synd = syndrome(in);
+ bool is_code;
+ is_code = true;
+ for ( int i = 0; i < rank_H; i++ ) {
+ if ( synd[i] != char(0) ) {
+ is_code = false;
+ }
+ }
+ return is_code;
+}
+
+std::vector<char> cldpc::encode(std::vector<char> dataword) {
+ if (dataword.size() == K) {
+ GF2Vec x(N);
+ GF2Vec data(K);
+ data.set_vec(dataword);
+ for ( int i = rank_H; i < N; i++ ) {
+ x[i] = dataword[i - rank_H];
+ }
+ for ( int i = 0; i < rank_H; i++ ) {
+ x[i] = G[i].sub_vector(N-K, N)*data;
+ }
+ GF2Vec y(N);
+ for ( int i = 0; i < N; i++ ) {
+ y[permute[i]] = x[i];
+ }
+ return y.get_vec();
+ } else {
+ throw std::runtime_error("bad vector length!");
+ return std::vector<char>();
+ }
+}
+
+int cldpc::dimension() {
+ return K;
+}
+
+int cldpc::get_M() {
+ return M;
+}
+
+int cldpc::get_N() {
+ return N;
+}
+
+GF2Mat cldpc::get_H() {
+ return H;
+}
+
+GF2Mat cldpc::get_G() {
+ return G;
+}
diff --git a/gr-fec/lib/gf2mat.cc b/gr-fec/lib/gf2mat.cc
new file mode 100644
index 0000000000..87cb300890
--- /dev/null
+++ b/gr-fec/lib/gf2mat.cc
@@ -0,0 +1,193 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2015 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include <gnuradio/fec/gf2mat.h>
+#include <iostream>
+
+GF2Mat::GF2Mat(int m, int n) {
+ M = m;
+ N = n;
+ H.resize(M);
+ for ( int i = 0; i < M; i++ ) {
+ H[i].resize(N);
+ for ( int j = 0; j < N; j++ ) {
+ H[i][j] = char(0);
+ }
+ }
+}
+
+GF2Mat::GF2Mat(std::vector <std::vector<char> > X) {
+ M = X.size();
+ N = X[0].size();
+ H.resize(M);
+ for ( int i = 0; i < M; i++ ) {
+ H[i].resize(N);
+ for ( int j = 0; j < N; j++ ){
+ H[i][j] = X[i][j];
+ }
+ }
+}
+
+GF2Mat::GF2Mat(alist _list) {
+ M = _list.get_M();
+ N = _list.get_N();
+ H.resize(M);
+ for ( int i = 0; i < M; i++ ) {
+ H[i].resize(N);
+ for ( int j = 0; j < N; j++ ) {
+ H[i][j] = char(0);
+ }
+ }
+ H = _list.get_matrix();
+}
+
+int GF2Mat::get_M() {
+ return M;
+}
+
+int GF2Mat::get_N() {
+ return N;
+}
+
+void GF2Mat::set_element(int i, int j, char val) {
+ H[i][j] = val;
+}
+
+char GF2Mat::get_element(int i, int j) {
+ return H[i][j];
+}
+
+void GF2Mat::print_matrix() {
+ for (int i = 0; i < M; i++) {
+ for (int j = 0; j < N; j++) {
+ std::cout << int(H[i][j]) << " ";
+ }
+ std::cout << '\n';
+ }
+}
+
+GF2Vec GF2Mat::operator[](int i) {
+ GF2Vec row(N);
+ row.set_vec(H[i]);
+ return row;
+}
+
+GF2Vec GF2Mat::get_row(int i) {
+ GF2Vec row(N);
+ for ( int j = 0; j < N; j++ ){
+ row[j] = H[i][j];
+ }
+ return row;
+}
+
+GF2Vec GF2Mat::get_col(int i) {
+ GF2Vec col(M);
+ for ( int j = 0; j < M; j++ ) {
+ col[j] = H[j][i];
+ }
+ return col;
+}
+
+void GF2Mat::add_cols(int i, int j) {
+ for ( int row = 0; row < M; row++ ) {
+ H[row][i] = H[row][i] xor H[row][j];
+ }
+}
+
+void GF2Mat::add_rows(int i, int j) {
+ for ( int col = 0; col < N; col++ ) {
+ H[i][col] = H[i][col] xor H[j][col];
+ }
+}
+
+void GF2Mat::set_row(int row, GF2Vec vec) {
+ for ( int j = 0; j < N; j++ ) {
+ H[row][j] = vec[j];
+ }
+}
+
+void GF2Mat::set_col(int col, GF2Vec vec) {
+ for ( int j = 0; j < M; j++ ) {
+ H[j][col] = vec[j];
+ }
+}
+
+void GF2Mat::swap_cols(int i, int j) {
+ GF2Vec tmp;
+ tmp = get_col(i);
+ set_col(i, get_col(j));
+ set_col(j, tmp);
+}
+
+GF2Mat GF2Mat::get_G(std::vector<int> & permute,
+ int & rank) {
+ permute.resize(N);
+ rank = 0;
+ for ( int col = 0; col < N; col++ ) {
+ permute[col] = col;
+ }
+ GF2Mat G(H);
+ int diag = 0;
+ int limit = M;
+ int temp;
+ while (diag < limit) {
+ bool non_zero = false;
+ for ( int col = diag; col < N; col++ ) {
+ if ( G.get_element(diag, col) == char(1) ) {
+ non_zero = true;
+ rank++;
+ G.swap_cols(diag, col);
+ temp = permute[diag];
+ permute[diag] = permute[col];
+ permute[col] = temp;
+ break;
+ }
+ }
+ if (non_zero) {
+ for ( int row = 0; row < diag; row++ ) {
+ if (G.get_element(row, diag) == char(1)){
+ G.add_rows(row, diag);
+ }
+ }
+ for ( int row = diag + 1; row < M; row++ ) {
+ if (G.get_element(row, diag) == char(1)) {
+ G.add_rows(row, diag);
+ }
+ }
+ diag++;
+ }
+ else{
+ GF2Vec current_row;
+ current_row = G.get_row(diag);
+ for ( int row = diag; row < limit - 1; row++ ) {
+ G.set_row(row, G.get_row(row + 1));
+ }
+ G.set_row(limit - 1, current_row);
+ limit--;
+ }
+ }
+ return G;
+}
+
+std::vector<std::vector<char> > GF2Mat::get_H() {
+ return H;
+}
diff --git a/gr-fec/lib/gf2vec.cc b/gr-fec/lib/gf2vec.cc
new file mode 100644
index 0000000000..464bf6a39e
--- /dev/null
+++ b/gr-fec/lib/gf2vec.cc
@@ -0,0 +1,91 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2015 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include <gnuradio/fec/gf2vec.h>
+#include <iostream>
+
+GF2Vec::GF2Vec(int size) {
+ vec.resize(size);
+ for( int i = 0; i < size; i++) {
+ vec[i] = char(0);
+ }
+}
+
+void GF2Vec::set_vec(const std::vector<char> in) {
+ resize(in.size());
+ for (size_t i = 0; i < vec.size(); i++ ) {
+ vec[i] = in[i];
+ }
+}
+
+std::vector<char> GF2Vec::get_vec(){
+ return vec;
+}
+
+int GF2Vec::size() {
+ return vec.size();
+}
+
+char & GF2Vec::operator[](int i) {
+ return vec[i];
+}
+
+GF2Vec operator+(GF2Vec a, GF2Vec b) {
+ GF2Vec sum(a.size());
+ for( int i = 0; i < sum.size(); i++) {
+ sum[i] = a[i] ^ b[i];
+ }
+ return sum;
+}
+
+GF2Vec GF2Vec::sub_vector(int from, int to) {
+ int len = to - from;
+ GF2Vec x(len);
+ for ( int i = 0; i < len; i++ ) {
+ x[i] = vec[i + from];
+ }
+ return x;
+}
+
+char operator*(GF2Vec a, GF2Vec b) {
+ char sum;
+ sum = char(0);
+ for (int i = 0; i < a.size(); i++) {
+ sum = sum ^ ( a[i] & b[i] );
+ }
+ return sum;
+}
+
+void GF2Vec::print_vec() {
+ for (int i = 0; i < size(); i++ ) {
+ std::cout << int(vec[i]) << " ";
+ }
+ std::cout << '\n';
+}
+
+void GF2Vec::resize(int size) {
+ vec.resize(size);
+}
+
+void GF2Vec::operator=(GF2Vec x) {
+ set_vec(x.get_vec());
+}
diff --git a/gr-fec/lib/ldpc_decoder.cc b/gr-fec/lib/ldpc_decoder.cc
new file mode 100644
index 0000000000..066024c9e0
--- /dev/null
+++ b/gr-fec/lib/ldpc_decoder.cc
@@ -0,0 +1,105 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2015 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include <gnuradio/fec/ldpc_decoder.h>
+#include <math.h>
+#include <boost/assign/list_of.hpp>
+#include <volk/volk.h>
+#include <sstream>
+#include <stdio.h>
+#include <vector>
+#include <gnuradio/fec/decoder.h>
+#include <algorithm> // for std::reverse
+#include <string.h> // for memcpy
+#include <gnuradio/fec/maxstar.h>
+
+
+namespace gr {
+ namespace fec {
+
+generic_decoder::sptr
+ldpc_decoder::make(std::string alist_file, float sigma, int max_iterations)
+{
+ return generic_decoder::sptr(new ldpc_decoder(alist_file, sigma, max_iterations));
+}
+
+ldpc_decoder::ldpc_decoder (std::string alist_file, float sigma, int max_iterations)
+ : generic_decoder("ldpc_decoder")
+{
+ if(!boost::filesystem::exists( alist_file ))
+ throw std::runtime_error("Bad AList file name!");
+ d_list.read(alist_file.c_str());
+ d_code.set_alist(d_list);
+ d_spa.set_alist_sigma(d_list, sigma);
+ inputSize = d_code.get_N();
+ outputSize = d_code.dimension();
+ d_spa.set_K(outputSize);
+ d_spa.set_max_iterations(max_iterations);
+}
+
+int ldpc_decoder::get_output_size() {
+ return outputSize;
+}
+
+int ldpc_decoder::get_input_size() {
+ return inputSize;
+}
+
+void ldpc_decoder::generic_work(void *inBuffer, void *outBuffer) {
+ const float *inPtr = (const float *) inBuffer;
+ unsigned char *out = (unsigned char *) outBuffer;
+
+ std::vector<float> rx(inputSize);
+ for(int i=0; i<inputSize; i++){ rx[i] = inPtr[i] * (-1); }
+ //memcpy(&rx[0], inPtr, inputSize*sizeof(float));
+ int n_iterations = 0;
+ std::vector<char> estimate( d_spa.decode(rx, &n_iterations) );
+ std::vector<char> data( d_code.get_systematic_bits(estimate) );
+ memcpy(out, &data[0], outputSize);
+ d_iterations = n_iterations;
+}
+
+int ldpc_decoder::get_input_item_size() {
+ return sizeof(INPUT_DATATYPE);
+}
+
+int ldpc_decoder::get_output_item_size() {
+ return sizeof(OUTPUT_DATATYPE);
+}
+
+int ldpc_decoder::get_history() {
+ return 0;
+}
+
+float ldpc_decoder::get_shift() {
+ return 0.0;
+}
+
+const char* ldpc_decoder::get_conversion() {
+ return "none";
+}
+
+ldpc_decoder::~ldpc_decoder() {
+}
+
+}
+}
diff --git a/gr-fec/lib/ldpc_encoder.cc b/gr-fec/lib/ldpc_encoder.cc
new file mode 100755
index 0000000000..813715a06b
--- /dev/null
+++ b/gr-fec/lib/ldpc_encoder.cc
@@ -0,0 +1,76 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2015 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include <gnuradio/fec/ldpc_encoder.h>
+#include <math.h>
+#include <boost/assign/list_of.hpp>
+#include <volk/volk.h>
+#include <sstream>
+#include <stdio.h>
+#include <vector>
+#include <algorithm> // for std::reverse
+#include <string.h> // for memcpy
+
+namespace gr {
+ namespace fec {
+
+generic_encoder::sptr
+ldpc_encoder::make(std::string alist_file)
+{
+ return generic_encoder::sptr(new ldpc_encoder(alist_file));
+}
+
+ldpc_encoder::ldpc_encoder (std::string alist_file)
+{
+ if(!boost::filesystem::exists( alist_file ))
+ throw std::runtime_error("Bad AList file name!");
+ d_list.read(alist_file.c_str());
+ d_code.set_alist(d_list);
+ inputSize = d_code.dimension();
+ outputSize = d_code.get_N();
+ printf("ENCODER: inputSize = %d, outputSize = %d\n",inputSize, outputSize);
+}
+
+int ldpc_encoder::get_output_size() {
+ return outputSize;
+}
+
+int ldpc_encoder::get_input_size() {
+ return inputSize;
+}
+
+void ldpc_encoder::generic_work(void *inBuffer, void *outBuffer) {
+ const unsigned char *in = (const unsigned char *) inBuffer;
+ unsigned char *out = (unsigned char *) outBuffer;
+ std::vector<char> inbuf(inputSize);
+ memcpy(&inbuf[0], in, inputSize);
+ std::vector<char> coded(d_code.encode(inbuf));
+ memcpy(&out[0], &coded[0], coded.size());
+}
+
+
+ldpc_encoder::~ldpc_encoder()
+{
+}
+
+}
+}
diff --git a/gr-fec/swig/fec_swig.i b/gr-fec/swig/fec_swig.i
index 8ad845fd1c..858c72d78f 100644
--- a/gr-fec/swig/fec_swig.i
+++ b/gr-fec/swig/fec_swig.i
@@ -58,6 +58,8 @@
#include "gnuradio/fec/puncture_bb.h"
#include "gnuradio/fec/puncture_ff.h"
#include "gnuradio/fec/depuncture_bb.h"
+#include "gnuradio/fec/ldpc_encoder.h"
+#include "gnuradio/fec/ldpc_decoder.h"
%}
%include "gnuradio/fec/generic_decoder.h"
@@ -82,6 +84,8 @@
%include "gnuradio/fec/puncture_bb.h"
%include "gnuradio/fec/puncture_ff.h"
%include "gnuradio/fec/depuncture_bb.h"
+%include "gnuradio/fec/ldpc_encoder.h"
+%include "gnuradio/fec/ldpc_decoder.h"
GR_SWIG_BLOCK_MAGIC2(fec, decoder);
GR_SWIG_BLOCK_MAGIC2(fec, encoder);
diff --git a/grc/blocks/options.xml b/grc/blocks/options.xml
index c1c94e4e24..6588dc72d0 100644
--- a/grc/blocks/options.xml
+++ b/grc/blocks/options.xml
@@ -158,6 +158,22 @@ part#slurp
<key>1</key>
</option>
</param>
+ <param>
+ <name>Thread-safe setters</name>
+ <key>thread_safe_setters</key>
+ <value></value>
+ <type>enum</type>
+ <hide>part</hide>
+ <option>
+ <name>Off</name>
+ <key></key>
+ </option>
+ <option>
+ <name>On</name>
+ <key>1</key>
+ </option>
+ <tab>Advanced</tab>
+ </param>
<check>len($window_size) == 2</check>
<check>300 &lt;= $(window_size)[0] &lt;= 4096</check>
<check>300 &lt;= $(window_size)[1] &lt;= 4096</check>
diff --git a/grc/gui/ActionHandler.py b/grc/gui/ActionHandler.py
index 6c56a94e9c..116dff189b 100644
--- a/grc/gui/ActionHandler.py
+++ b/grc/gui/ActionHandler.py
@@ -108,7 +108,7 @@ class ActionHandler:
def _handle_action(self, action):
#print action
##################################################
- # Initalize/Quit
+ # Initialize/Quit
##################################################
if action == Actions.APPLICATION_INITIALIZE:
for action in Actions.get_all_actions(): action.set_sensitive(False) #set all actions disabled
@@ -129,7 +129,7 @@ class ActionHandler:
Actions.XML_PARSER_ERRORS_DISPLAY.set_sensitive(True)
if not self.init_file_paths:
- self.init_file_paths = Preferences.files_open()
+ self.init_file_paths = filter(os.path.exists, Preferences.files_open())
if not self.init_file_paths: self.init_file_paths = ['']
for file_path in self.init_file_paths:
if file_path: self.main_window.new_page(file_path) #load pages from file paths
diff --git a/grc/gui/Bars.py b/grc/gui/Bars.py
index 5041a28f14..6ce614bc99 100644
--- a/grc/gui/Bars.py
+++ b/grc/gui/Bars.py
@@ -121,6 +121,30 @@ MENU_BAR_LIST = (
Actions.ABOUT_WINDOW_DISPLAY,
]),
)
+
+
+CONTEXT_MENU_LIST = [
+ Actions.BLOCK_CUT,
+ Actions.BLOCK_COPY,
+ Actions.BLOCK_PASTE,
+ Actions.ELEMENT_DELETE,
+ None,
+ Actions.BLOCK_ROTATE_CCW,
+ Actions.BLOCK_ROTATE_CW,
+ Actions.BLOCK_ENABLE,
+ Actions.BLOCK_DISABLE,
+ None,
+ (gtk.Action('More', '_More', None, None), [
+ Actions.BLOCK_CREATE_HIER,
+ Actions.OPEN_HIER,
+ None,
+ Actions.BUSSIFY_SOURCES,
+ Actions.BUSSIFY_SINKS,
+ ]),
+ Actions.BLOCK_PARAM_MODIFY
+]
+
+
class Toolbar(gtk.Toolbar):
"""The gtk toolbar with actions added from the toolbar list."""
@@ -138,6 +162,7 @@ class Toolbar(gtk.Toolbar):
action.set_property('tooltip', action.get_property('tooltip'))
else: self.add(gtk.SeparatorToolItem())
+
class MenuBar(gtk.MenuBar):
"""The gtk menu bar with actions added from the menu bar list."""
@@ -157,7 +182,29 @@ class MenuBar(gtk.MenuBar):
main_menu = gtk.Menu()
main_menu_item.set_submenu(main_menu)
for action in actions:
- if action: #append a menu item
- main_menu.append(action.create_menu_item())
- else: main_menu.append(gtk.SeparatorMenuItem())
+ main_menu.append(action.create_menu_item() if action else
+ gtk.SeparatorMenuItem())
main_menu.show_all() #this show all is required for the separators to show
+
+
+class ContextMenu(gtk.Menu):
+ """The gtk menu with actions added from the context menu list."""
+
+ def __init__(self):
+ gtk.Menu.__init__(self)
+ for action in CONTEXT_MENU_LIST:
+ if isinstance(action, tuple):
+ action, sub_menu_action_list = action
+ item = action.create_menu_item()
+ self.append(item)
+ sub_menu = gtk.Menu()
+ item.set_submenu(sub_menu)
+ for action in sub_menu_action_list:
+ sub_menu.append(action.create_menu_item() if action else
+ gtk.SeparatorMenuItem())
+ sub_menu.show_all()
+
+ else:
+ self.append(action.create_menu_item() if action else
+ gtk.SeparatorMenuItem())
+ self.show_all()
diff --git a/grc/gui/Connection.py b/grc/gui/Connection.py
index f075a18175..badf8e8a82 100644
--- a/grc/gui/Connection.py
+++ b/grc/gui/Connection.py
@@ -37,8 +37,8 @@ class Connection(Element):
def __init__(self):
Element.__init__(self)
- self._color = Colors.CONNECTION_ENABLED_COLOR
- self._bg_color = self._arrow_color = self._color
+ # can't use Colors.CONNECTION_ENABLED_COLOR here, might not be defined (grcc)
+ self._bg_color = self._arrow_color = self._color = None
def get_coordinate(self):
"""
@@ -48,7 +48,7 @@ class Connection(Element):
Returns:
0, 0
"""
- return (0, 0)
+ return 0, 0
def get_rotation(self):
"""
diff --git a/grc/gui/Dialogs.py b/grc/gui/Dialogs.py
index eb0a6c11b0..e1fc680bde 100644
--- a/grc/gui/Dialogs.py
+++ b/grc/gui/Dialogs.py
@@ -116,7 +116,7 @@ class TextDisplay(gtk.TextView):
menu.show_all()
return False
-def MessageDialogHelper(type, buttons, title=None, markup=None):
+def MessageDialogHelper(type, buttons, title=None, markup=None, default_response=None, extra_buttons=None):
"""
Create a modal message dialog and run it.
@@ -126,8 +126,10 @@ def MessageDialogHelper(type, buttons, title=None, markup=None):
gtk.BUTTONS_NONE, gtk.BUTTONS_OK, gtk.BUTTONS_CLOSE, gtk.BUTTONS_CANCEL, gtk.BUTTONS_YES_NO, gtk.BUTTONS_OK_CANCEL
Args:
- tittle: the title of the window (string)
+ title: the title of the window (string)
markup: the message text with pango markup
+ default_response: if set, determines which button is highlighted by default
+ extra_buttons: a tuple containing pairs of values; each value is the button's text and the button's return value
Returns:
the gtk response from run()
@@ -135,6 +137,8 @@ def MessageDialogHelper(type, buttons, title=None, markup=None):
message_dialog = gtk.MessageDialog(None, gtk.DIALOG_MODAL, type, buttons)
if title: message_dialog.set_title(title)
if markup: message_dialog.set_markup(markup)
+ if extra_buttons: message_dialog.add_buttons(*extra_buttons)
+ if default_response: message_dialog.set_default_response(default_response)
response = message_dialog.run()
message_dialog.destroy()
return response
diff --git a/grc/gui/FlowGraph.py b/grc/gui/FlowGraph.py
index 794d992e4e..f8be2f6cc3 100644
--- a/grc/gui/FlowGraph.py
+++ b/grc/gui/FlowGraph.py
@@ -27,6 +27,7 @@ pygtk.require('2.0')
import gtk
import random
import Messages
+import Bars
class FlowGraph(Element):
"""
@@ -54,25 +55,7 @@ class FlowGraph(Element):
# current mouse hover element
self.element_under_mouse = None
#context menu
- self._context_menu = gtk.Menu()
- for action in [
- Actions.BLOCK_CUT,
- Actions.BLOCK_COPY,
- Actions.BLOCK_PASTE,
- Actions.ELEMENT_DELETE,
- None,
- Actions.BLOCK_ROTATE_CCW,
- Actions.BLOCK_ROTATE_CW,
- Actions.BLOCK_ENABLE,
- Actions.BLOCK_DISABLE,
- None,
- Actions.BLOCK_CREATE_HIER,
- Actions.OPEN_HIER,
- Actions.BUSSIFY_SOURCES,
- Actions.BUSSIFY_SINKS,
- None,
- Actions.BLOCK_PARAM_MODIFY
- ]: self._context_menu.append(action.create_menu_item() if action else gtk.SeparatorMenuItem())
+ self._context_menu = Bars.ContextMenu()
self.get_context_menu = lambda: self._context_menu
###########################################################################
diff --git a/grc/gui/MainWindow.py b/grc/gui/MainWindow.py
index d1cf866ce7..07d0661e94 100644
--- a/grc/gui/MainWindow.py
+++ b/grc/gui/MainWindow.py
@@ -209,9 +209,11 @@ class MainWindow(gtk.Window):
open_files = filter(lambda file: file, self._get_files()) #filter blank files
open_file = self.get_page().get_file_path()
#close each page
- for page in self.get_pages():
+ for page in sorted(self.get_pages(), key=lambda p: p.get_saved()):
self.page_to_be_closed = page
- self.close_page(False)
+ closed = self.close_page(False)
+ if not closed:
+ break
if self.notebook.get_n_pages(): return False
#save state before closing
Preferences.files_open(open_files)
@@ -236,17 +238,23 @@ class MainWindow(gtk.Window):
if self.page_to_be_closed.get_proc() or not self.page_to_be_closed.get_saved():
self._set_page(self.page_to_be_closed)
#unsaved? ask the user
- if not self.page_to_be_closed.get_saved() and self._save_changes():
- Actions.FLOW_GRAPH_SAVE() #try to save
- if not self.page_to_be_closed.get_saved(): #still unsaved?
- self.page_to_be_closed = None #set the page to be closed back to None
- return
+ if not self.page_to_be_closed.get_saved():
+ response = self._save_changes() # return value is either OK, CLOSE, or CANCEL
+ if response == gtk.RESPONSE_OK:
+ Actions.FLOW_GRAPH_SAVE() #try to save
+ if not self.page_to_be_closed.get_saved(): #still unsaved?
+ self.page_to_be_closed = None #set the page to be closed back to None
+ return False
+ elif response == gtk.RESPONSE_CANCEL:
+ self.page_to_be_closed = None
+ return False
#stop the flow graph if executing
if self.page_to_be_closed.get_proc(): Actions.FLOW_GRAPH_KILL()
#remove the page
self.notebook.remove_page(self.notebook.page_num(self.page_to_be_closed))
if ensure and self.notebook.get_n_pages() == 0: self.new_page() #no pages, make a new one
self.page_to_be_closed = None #set the page to be closed back to None
+ return True
############################################################
# Misc
@@ -337,12 +345,17 @@ class MainWindow(gtk.Window):
Save changes to flow graph?
Returns:
- true if yes
+ the response_id (see buttons variable below)
"""
+ buttons = (
+ 'Close without saving', gtk.RESPONSE_CLOSE,
+ gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
+ gtk.STOCK_SAVE, gtk.RESPONSE_OK
+ )
return MessageDialogHelper(
- gtk.MESSAGE_QUESTION, gtk.BUTTONS_YES_NO, 'Unsaved Changes!',
- 'Would you like to save changes before closing?'
- ) == gtk.RESPONSE_YES
+ gtk.MESSAGE_QUESTION, gtk.BUTTONS_NONE, 'Unsaved Changes!',
+ 'Would you like to save changes before closing?', gtk.RESPONSE_OK, buttons
+ )
def _get_files(self):
"""
diff --git a/grc/gui/Param.py b/grc/gui/Param.py
index 2ef8603a83..1efa56326e 100644
--- a/grc/gui/Param.py
+++ b/grc/gui/Param.py
@@ -72,20 +72,31 @@ class InputParam(gtk.HBox):
self._changed_but_unchecked = True
self._update_gui()
- def _apply_change(self, *args):
+ def apply_change(self, *args):
"""
Handle a gui change by setting the new param value,
calling the callback (if applicable), and updating.
"""
+ if not self._changed_but_unchecked:
+ return
#set the new value
self.param.set_value(self.get_text())
#call the callback
- if self._callback: self._callback(*args)
- else: self.param.validate()
+ if self._callback:
+ self._callback(*args)
+ else:
+ self.param.validate()
#gui update
self._changed_but_unchecked = False
self._update_gui()
+ def _handle_key_press(self, widget, event):
+ if event.keyval == gtk.keysyms.Return and event.state & gtk.gdk.CONTROL_MASK:
+ self.apply_change()
+ return True
+ return False
+
+
class EntryParam(InputParam):
"""Provide an entry box for strings and numbers."""
@@ -94,7 +105,8 @@ class EntryParam(InputParam):
self._input = gtk.Entry()
self._input.set_text(self.param.get_value())
self._input.connect('changed', self._mark_changed)
- self._input.connect('focus-out-event', self._apply_change)
+ self._input.connect('focus-out-event', self.apply_change)
+ self._input.connect('key-press-event', self._handle_key_press)
self.pack_start(self._input, True)
def get_text(self): return self._input.get_text()
def set_color(self, color):
@@ -114,7 +126,7 @@ class EnumParam(InputParam):
self._input = gtk.combo_box_new_text()
for option in self.param.get_options(): self._input.append_text(option.get_name())
self._input.set_active(self.param.get_option_keys().index(self.param.get_value()))
- self._input.connect('changed', self._apply_change)
+ self._input.connect('changed', self.apply_change)
self.pack_start(self._input, False)
def get_text(self): return self.param.get_option_keys()[self._input.get_active()]
def set_tooltip_text(self, text):
@@ -123,6 +135,7 @@ class EnumParam(InputParam):
except AttributeError:
pass # no tooltips for old GTK
+
class EnumEntryParam(InputParam):
"""Provide an entry box and drop down menu for Raw Enum types."""
@@ -134,9 +147,10 @@ class EnumEntryParam(InputParam):
except:
self._input.set_active(-1)
self._input.get_child().set_text(self.param.get_value())
- self._input.connect('changed', self._apply_change)
+ self._input.connect('changed', self.apply_change)
self._input.get_child().connect('changed', self._mark_changed)
- self._input.get_child().connect('focus-out-event', self._apply_change)
+ self._input.get_child().connect('focus-out-event', self.apply_change)
+ self._input.get_child().connect('key-press-event', self._handle_key_press)
self.pack_start(self._input, False)
def get_text(self):
if self._input.get_active() == -1: return self._input.get_child().get_text()
@@ -191,7 +205,7 @@ class FileParam(EntryParam):
if gtk.RESPONSE_OK == file_dialog.run(): #run the dialog
file_path = file_dialog.get_filename() #get the file path
self._input.set_text(file_path)
- self._apply_change()
+ self.apply_change()
file_dialog.destroy() #destroy the dialog
diff --git a/grc/gui/Preferences.py b/grc/gui/Preferences.py
index 1d6675da32..e7b05519ea 100644
--- a/grc/gui/Preferences.py
+++ b/grc/gui/Preferences.py
@@ -68,9 +68,11 @@ def files_open(files=None):
files = list()
i = 0
while True:
- try: files.append(_config_parser.get('files_open', 'file_open_%d'%i))
- except: return files
- i = i + 1
+ try:
+ files.append(_config_parser.get('files_open', 'file_open_%d'%i))
+ except:
+ return files
+ i += 1
def reports_window_position(pos=None):
if pos is not None: _config_parser.set('main', 'reports_window_position', pos)
@@ -91,4 +93,4 @@ def bool_entry(key, active=None, default=True):
try:
return _config_parser.getboolean('main', key)
except:
- return default \ No newline at end of file
+ return default
diff --git a/grc/gui/PropsDialog.py b/grc/gui/PropsDialog.py
index d7ba8c51c9..d172175aba 100644
--- a/grc/gui/PropsDialog.py
+++ b/grc/gui/PropsDialog.py
@@ -65,7 +65,9 @@ class PropsDialog(gtk.Dialog):
gtk.Dialog.__init__(
self,
title='Properties: %s' % block.get_name(),
- buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT, gtk.STOCK_OK, gtk.RESPONSE_ACCEPT),
+ buttons=(gtk.STOCK_OK, gtk.RESPONSE_ACCEPT,
+ gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT,
+ gtk.STOCK_APPLY, gtk.RESPONSE_APPLY)
)
self._block = block
self.set_size_request(MIN_DIALOG_WIDTH, MIN_DIALOG_HEIGHT)
@@ -109,6 +111,7 @@ class PropsDialog(gtk.Dialog):
# Connect events
self.connect('key-press-event', self._handle_key_press)
self.connect('show', self._update_gui)
+ self.connect('response', self._handle_response)
self.show_all() # show all (performs initial gui update)
def _params_changed(self):
@@ -183,11 +186,18 @@ class PropsDialog(gtk.Dialog):
Returns:
false to forward the keypress
"""
- if event.keyval == gtk.keysyms.Return:
+ if event.keyval == gtk.keysyms.Return and event.state & gtk.gdk.CONTROL_MASK == 0:
self.response(gtk.RESPONSE_ACCEPT)
return True # handled here
return False # forward the keypress
+ def _handle_response(self, widget, response):
+ if response == gtk.RESPONSE_APPLY:
+ for tab, label, vbox in self._params_boxes:
+ vbox.forall(lambda c: c.apply_change())
+ return True
+ return False
+
def run(self):
"""
Run the dialog and get its response.
@@ -195,6 +205,9 @@ class PropsDialog(gtk.Dialog):
Returns:
true if the response was accept
"""
- response = gtk.Dialog.run(self)
+ response = gtk.RESPONSE_APPLY
+ # don't close dialog on apply click
+ while response == gtk.RESPONSE_APPLY:
+ response = gtk.Dialog.run(self)
self.destroy()
return response == gtk.RESPONSE_ACCEPT
diff --git a/grc/python/Generator.py b/grc/python/Generator.py
index 7512cfb633..a3f9f10fc1 100644
--- a/grc/python/Generator.py
+++ b/grc/python/Generator.py
@@ -101,9 +101,12 @@ class TopBlockGenerator(object):
"This is usually undesired. Consider "
"removing the throttle block.")
# generate
- open(self.get_file_path(), 'w').write(
- self._build_python_code_from_template()
- )
+ with open(self.get_file_path(), 'w') as fp:
+ fp.write(self._build_python_code_from_template())
+ try:
+ os.chmod(self.get_file_path(), self._mode)
+ except:
+ pass
def get_popen(self):
"""
@@ -231,6 +234,10 @@ class HierBlockGenerator(TopBlockGenerator):
TopBlockGenerator.write(self)
ParseXML.to_file(self._build_block_n_from_flow_graph_io(), self.get_file_path_xml())
ParseXML.validate_dtd(self.get_file_path_xml(), BLOCK_DTD)
+ try:
+ os.chmod(self.get_file_path_xml(), self._mode)
+ except:
+ pass
def _build_block_n_from_flow_graph_io(self):
"""
@@ -254,7 +261,8 @@ class HierBlockGenerator(TopBlockGenerator):
self._flow_graph.get_option('id').replace('_', ' ').title()
block_n['key'] = block_key
block_n['category'] = self._flow_graph.get_option('category')
- block_n['import'] = 'execfile("{0}")'.format(self.get_file_path())
+ block_n['import'] = "from {0} import {0} # grc-generated hier_block".format(
+ self._flow_graph.get_option('id'))
# make data
if parameters:
block_n['make'] = '{cls}(\n {kwargs},\n)'.format(
diff --git a/grc/python/flow_graph.tmpl b/grc/python/flow_graph.tmpl
index 859611e528..814b513213 100644
--- a/grc/python/flow_graph.tmpl
+++ b/grc/python/flow_graph.tmpl
@@ -1,4 +1,6 @@
-#!/usr/bin/env python
+#if $generate_options != 'hb'
+#!/usr/bin/env python2
+#end if
########################################################
##Cheetah template - gnuradio_python
##
@@ -19,7 +21,7 @@ $code#slurp
#import time
#set $DIVIDER = '#'*50
$DIVIDER
-# Gnuradio Python Flow Graph
+# GNU Radio Python Flow Graph
# Title: $title
#if $flow_graph.get_option('author')
# Author: $flow_graph.get_option('author')
@@ -29,6 +31,9 @@ $DIVIDER
#end if
# Generated: $time.ctime()
$DIVIDER
+#if $flow_graph.get_option('thread_safe_setters')
+import threading
+#end if
## Call XInitThreads as the _very_ first thing.
## After some Qt import, it's too late
@@ -48,8 +53,15 @@ if __name__ == '__main__':
########################################################
##Create Imports
########################################################
+#if any(imp.endswith("# grc-generated hier_block") for imp in $imports)
+import os
+import sys
+#set imports = $filter(lambda i: i not in ("import os", "import sys"), $imports)
+sys.path.append(os.environ.get('GRC_HIER_PATH', os.path.expanduser('~/.grc_gnuradio')))
+
+#end if
#for $imp in $imports
-$imp
+$(imp.replace(" # grc-generated hier_block", ""))
#end for
########################################################
@@ -132,6 +144,10 @@ gr.io_signaturev($(len($io_sigs)), $(len($io_sigs)), [$(', '.join($size_strs))])
self.message_port_register_hier_in("$pad['label']")
#end for
#end if
+#if $flow_graph.get_option('thread_safe_setters')
+
+ self._lock = threading.RLock()
+#end if
########################################################
##Create Parameters
## Set the parameter to a property of self.
@@ -255,10 +271,18 @@ gr.io_signaturev($(len($io_sigs)), $(len($io_sigs)), [$(', '.join($size_strs))])
return self.$id
def set_$(id)(self, $id):
+ #if $flow_graph.get_option('thread_safe_setters')
+ with self._lock:
+ self.$id = $id
+ #for $callback in $var_id2cbs[$id]
+ $indent($callback)
+ #end for
+ #else
self.$id = $id
- #for $callback in $var_id2cbs[$id]
+ #for $callback in $var_id2cbs[$id]
$indent($callback)
- #end for
+ #end for
+ #end if
#end for
########################################################
diff --git a/grc/scripts/gnuradio-companion b/grc/scripts/gnuradio-companion
index 6d45ecc246..239fc95d8a 100755
--- a/grc/scripts/gnuradio-companion
+++ b/grc/scripts/gnuradio-companion
@@ -1,6 +1,6 @@
#!/usr/bin/env python
"""
-Copyright 2009-2012 Free Software Foundation, Inc.
+Copyright 2009-2015 Free Software Foundation, Inc.
This file is part of GNU Radio
GNU Radio Companion is free software; you can redistribute it and/or
@@ -18,13 +18,16 @@ along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
"""
+import os
+import sys
+import optparse
+
import pygtk
pygtk.require('2.0')
import gtk
-try: from gnuradio import gr
-except ImportError, e:
- d = gtk.MessageDialog(type=gtk.MESSAGE_ERROR, buttons=gtk.BUTTONS_CLOSE, message_format="""
+
+GR_IMPORT_ERROR_MESSAGE = """\
Cannot import gnuradio.
Is the python path environment variable set correctly?
@@ -34,39 +37,77 @@ Is the library path environment variable set correctly?
Linux: LD_LIBRARY_PATH
Windows: PATH
MacOSX: DYLD_LIBRARY_PATH
-""")
- d.set_title(str(e))
- d.run()
- exit(-1)
-
-from optparse import OptionParser
-import os
+"""
-if __name__ == "__main__":
- if ('GR_DONT_LOAD_PREFS' in os.environ.keys() and
- (not 'GRC_BLOCKS_PATH' in os.environ.keys() or len(os.environ['GRC_BLOCKS_PATH']) == 0)):
- d = gtk.MessageDialog(
- type=gtk.MESSAGE_ERROR,
- buttons=gtk.BUTTONS_CLOSE,
- message_format="""Can't find block definitions. Use config.conf or GRC_BLOCKS_PATH. """)
- d.set_title("No block definitions available.")
- d.run()
- exit(-1)
- usage = 'usage: %prog [options] [saved flow graphs]'
- version = """
+VERSION_AND_DISCLAIMER_TEMPLATE = """\
GNU Radio Companion %s
This program is part of GNU Radio
GRC comes with ABSOLUTELY NO WARRANTY.
-This is free software,
-and you are welcome to redistribute it.
-"""%gr.version()
- parser = OptionParser(usage=usage, version=version)
- (options, args) = parser.parse_args()
- from gnuradio.grc.python.Platform import Platform
- from gnuradio.grc.gui.ActionHandler import ActionHandler
- #setup icon using icon theme
- try: gtk.window_set_default_icon(gtk.IconTheme().load_icon('gnuradio-grc', 256, 0))
- except: pass
+This is free software, and you are welcome to redistribute it.
+"""
+
+
+def show_gtk_error_dialog(title, message):
+ d = gtk.MessageDialog(type=gtk.MESSAGE_ERROR, buttons=gtk.BUTTONS_CLOSE,
+ message_format=message)
+ d.set_title(title)
+ d.run()
+
+
+def check_gnuradio_import():
+ try:
+ from gnuradio import gr
+ except ImportError as e:
+ show_gtk_error_dialog(str(e), GR_IMPORT_ERROR_MESSAGE)
+ exit(-1)
+
+
+def ensure_blocks_path():
+ if 'GR_DONT_LOAD_PREFS' in os.environ and not os.environ.get('GRC_BLOCKS_PATH', ''):
+ show_gtk_error_dialog(
+ title="No block definitions available.",
+ message="Can't find block definitions. Use config.conf or GRC_BLOCKS_PATH."
+ )
+ exit(-1)
+
+
+def get_source_tree_root():
+ source_tree_subpath = "/grc/scripts"
+ script_path = os.path.dirname(__file__)
+ if script_path.endswith(source_tree_subpath):
+ return script_path[:-len(source_tree_subpath)]
+
+
+def main():
+ from gnuradio import gr
+
+ parser = optparse.OptionParser(
+ usage='usage: %prog [options] [saved flow graphs]',
+ version=VERSION_AND_DISCLAIMER_TEMPLATE % gr.version())
+ options, args = parser.parse_args()
+
+ source_tree_root = get_source_tree_root()
+ if not source_tree_root:
+ # run the installed version
+ from gnuradio.grc.python.Platform import Platform
+ from gnuradio.grc.gui.ActionHandler import ActionHandler
+
+ else:
+ print("Running from source tree")
+ sys.path.insert(1, source_tree_root)
+ from grc.python.Platform import Platform
+ from grc.gui.ActionHandler import ActionHandler
+
+ try:
+ gtk.window_set_default_icon(gtk.IconTheme().load_icon('gnuradio-grc', 256, 0))
+ except:
+ pass
+
ActionHandler(args, Platform())
+
+if __name__ == '__main__':
+ check_gnuradio_import()
+ ensure_blocks_path()
+ main()