diff options
author | Marcus Müller <mmueller@gnuradio.org> | 2019-08-07 21:45:12 +0200 |
---|---|---|
committer | Marcus Müller <marcus@hostalia.de> | 2019-08-09 23:04:28 +0200 |
commit | f7bbf2c1d8d780294f3e016aff239ca35eb6516e (patch) | |
tree | e09ab6112e02b2215b2d59ac24d3d6ea2edac745 /gr-fec | |
parent | 78431dc6941e3acc67c858277dfe4a0ed583643c (diff) |
Tree: clang-format without the include sorting
Diffstat (limited to 'gr-fec')
142 files changed, 9790 insertions, 10054 deletions
diff --git a/gr-fec/include/gnuradio/fec/alist.h b/gr-fec/include/gnuradio/fec/alist.h index e68a88cd4e..5e4ed54e94 100644 --- a/gr-fec/include/gnuradio/fec/alist.h +++ b/gr-fec/include/gnuradio/fec/alist.h @@ -20,7 +20,7 @@ * Boston, MA 02110-1301, USA. */ - /* ----------------------------------------------------------------- +/* ----------------------------------------------------------------- * * This class handles sparse matrices specified in alist-format. * For details about alist format please visit the link below. @@ -43,19 +43,18 @@ class FEC_API alist { - public: - +public: //! Default Constructor alist() : data_ok(false) {} //! Constructor which loads alist class from an alist-file - alist(const char * fname); + alist(const char* fname); //! Read alist data from a file - void read(const char * fname); + void read(const char* fname); //! Write alist data to a file - void write(const char * fname) const; + void write(const char* fname) const; //! Returns N, the number of variable nodes int get_N(); @@ -64,10 +63,10 @@ class FEC_API alist int get_M(); //! Return the m_list variable - std::vector< std::vector<int> > get_mlist(); + std::vector<std::vector<int>> get_mlist(); //! Returns the n_list variable - std::vector< std::vector<int> > get_nlist(); + std::vector<std::vector<int>> get_nlist(); //! Returns the num_mlist variable std::vector<int> get_num_mlist(); @@ -88,9 +87,9 @@ class FEC_API alist void print_mlist_i(int i); //! Returns the corresponding H matrix - std::vector<std::vector<char> > get_matrix(); + std::vector<std::vector<char>> get_matrix(); - protected: +protected: //! A variable indicating if data has been read from alist-file bool data_ok; @@ -113,9 +112,9 @@ class FEC_API alist std::vector<int> num_mlist; //! List of integer coordinates along each rows with non-zero entries - std::vector< std::vector<int> > mlist; + std::vector<std::vector<int>> mlist; //! List of integer coordinates along each column with non-zero entries - std::vector< std::vector<int> > nlist; + std::vector<std::vector<int>> nlist; }; #endif // ifndef ALIST_H diff --git a/gr-fec/include/gnuradio/fec/api.h b/gr-fec/include/gnuradio/fec/api.h index 51315f6c03..1bc88007e7 100644 --- a/gr-fec/include/gnuradio/fec/api.h +++ b/gr-fec/include/gnuradio/fec/api.h @@ -25,9 +25,9 @@ #include <gnuradio/attributes.h> #ifdef gnuradio_fec_EXPORTS -# define FEC_API __GR_ATTR_EXPORT +#define FEC_API __GR_ATTR_EXPORT #else -# define FEC_API __GR_ATTR_IMPORT +#define FEC_API __GR_ATTR_IMPORT #endif #endif /* INCLUDED_FEC_API_H */ diff --git a/gr-fec/include/gnuradio/fec/async_decoder.h b/gr-fec/include/gnuradio/fec/async_decoder.h index 3c83ffa370..fa14641e01 100644 --- a/gr-fec/include/gnuradio/fec/async_decoder.h +++ b/gr-fec/include/gnuradio/fec/async_decoder.h @@ -29,79 +29,80 @@ #include <boost/shared_ptr.hpp> namespace gr { - namespace fec { +namespace fec { + +/*! + * \brief Creates the decoder block for use in GNU Radio + * flowgraphs from a given FEC API object derived from the + * generic_decoder class. + * \ingroup error_coding_blk + * + * \details + * + * Decodes frames received as async messages over a message + * port. This decoder deployment expects messages of soft decision + * symbols in and can produce either packed, PDU messages (\p + * packed = True) or messages full of unpacked bits (\p packed = + * False). + * + * This decoder works off a full message as one frame or block to + * decode. The message length is used to calculate the frame + * length. To support this, the decoder variable used will have + * had its frame_size set. This block treats that initial + * frame_size value as the maximum transmission unit (MTU) and + * will not process frames larger than that after being decoded. + * + * The packed PDU form of this deployment is designed to work well + * with other PDU-based blocks to operate within the processing + * flow of data packets or frames. + * + * Due to differences in how data is packed and processed, this + * block also offers the ability to change the direction of how + * bits are packed. All inputs messages are one soft decision per + * item. By default, the \p rev_pack mode is set to True. Using + * this setup allows the async block to behave with PDUs in the + * same operation and format as the tagged stream decoders. That + * is, putting the same data into both the tagged stream decoder + * deployment and this with the default setting should produce the + * same data. + * + * Because the block handles data as a full frame per message, + * this decoder deployment cannot work with any decoders that + * require history. For example, the gr::fec::code::cc_decoder + * decoder in streaming mode requires an extra rate*(K-1) bits to + * complete the decoding, so it would have to wait for the next + * message to come in and finish processing. Therefore, the + * streaming mode of the CC decoder is not allowed. The other + * three modes will work with this deployment since the frame is + * self-contained for decoding. + */ +class FEC_API async_decoder : virtual public block +{ +public: + typedef boost::shared_ptr<async_decoder> sptr; /*! - * \brief Creates the decoder block for use in GNU Radio - * flowgraphs from a given FEC API object derived from the - * generic_decoder class. - * \ingroup error_coding_blk - * - * \details - * - * Decodes frames received as async messages over a message - * port. This decoder deployment expects messages of soft decision - * symbols in and can produce either packed, PDU messages (\p - * packed = True) or messages full of unpacked bits (\p packed = - * False). - * - * This decoder works off a full message as one frame or block to - * decode. The message length is used to calculate the frame - * length. To support this, the decoder variable used will have - * had its frame_size set. This block treats that initial - * frame_size value as the maximum transmission unit (MTU) and - * will not process frames larger than that after being decoded. + * Build the PDU-based FEC decoder block from an FECAPI decoder object. * - * The packed PDU form of this deployment is designed to work well - * with other PDU-based blocks to operate within the processing - * flow of data packets or frames. - * - * Due to differences in how data is packed and processed, this - * block also offers the ability to change the direction of how - * bits are packed. All inputs messages are one soft decision per - * item. By default, the \p rev_pack mode is set to True. Using - * this setup allows the async block to behave with PDUs in the - * same operation and format as the tagged stream decoders. That - * is, putting the same data into both the tagged stream decoder - * deployment and this with the default setting should produce the - * same data. - * - * Because the block handles data as a full frame per message, - * this decoder deployment cannot work with any decoders that - * require history. For example, the gr::fec::code::cc_decoder - * decoder in streaming mode requires an extra rate*(K-1) bits to - * complete the decoding, so it would have to wait for the next - * message to come in and finish processing. Therefore, the - * streaming mode of the CC decoder is not allowed. The other - * three modes will work with this deployment since the frame is - * self-contained for decoding. + * \param my_decoder An FECAPI decoder object child of the generic_decoder class. + * \param packed Sets output to packed bytes if true; otherwise, 1 bit per byte. + * \param rev_pack If packing bits, should they be reversed? + * \param mtu The Maximum Transmission Unit (MTU) of the output + * frame that the block will be able to + * process. Specified in bytes and defaults to 1500. */ - class FEC_API async_decoder : virtual public block - { - public: - typedef boost::shared_ptr<async_decoder> sptr; - - /*! - * Build the PDU-based FEC decoder block from an FECAPI decoder object. - * - * \param my_decoder An FECAPI decoder object child of the generic_decoder class. - * \param packed Sets output to packed bytes if true; otherwise, 1 bit per byte. - * \param rev_pack If packing bits, should they be reversed? - * \param mtu The Maximum Transmission Unit (MTU) of the output - * frame that the block will be able to - * process. Specified in bytes and defaults to 1500. - */ - static sptr make(generic_decoder::sptr my_decoder, - bool packed=false, bool rev_pack=true, - int mtu=1500); + static sptr make(generic_decoder::sptr my_decoder, + bool packed = false, + bool rev_pack = true, + int mtu = 1500); - virtual int general_work(int noutput_items, - gr_vector_int& ninput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) = 0; - }; + virtual int general_work(int noutput_items, + gr_vector_int& ninput_items, + gr_vector_const_void_star& input_items, + gr_vector_void_star& output_items) = 0; +}; - } /* namespace fec */ +} /* namespace fec */ } /* namespace gr */ #endif /* INCLUDED_FEC_ASYNC_DECODER_H */ diff --git a/gr-fec/include/gnuradio/fec/async_encoder.h b/gr-fec/include/gnuradio/fec/async_encoder.h index 98ccf0a32a..ed320addee 100644 --- a/gr-fec/include/gnuradio/fec/async_encoder.h +++ b/gr-fec/include/gnuradio/fec/async_encoder.h @@ -29,75 +29,76 @@ #include <boost/shared_ptr.hpp> namespace gr { - namespace fec { +namespace fec { + +/*! + * \brief Creates the encoder block for use in GNU Radio + * flowgraphs with async message from a given FEC API object + * derived from the generic_encoder class. + * \ingroup error_coding_blk + * + * \details + * + * Encodes frames received as async messages or as a PDU over a + * message port. This encoder works off a full message as one + * frame or block to encode. The message length is used as the + * frame length. To support this, the encoder variable used will + * have had its frame_size set. This block treats that initial + * frame_size value as the maximum transmission unit (MTU) and + * will not process frames larger than that. + * + * This deployment works off messages and expects them to either + * be messages full of unpacked bits or PDU messages, which means + * full bytes of a frame from the higher layers, including things + * like headers, tails, CRC check bytes, etc. For handling PDUs, + * set the \p packed option of this deployment block to True. The + * block will then use the FEC API to properly unpack the bits + * from the PDU, pass it through the encoder, and repack them to + * output the PDUs for the next stage of processing. + * + * The packed PDU form of this deployment is designed to work well + * with other PDU-based blocks to operate within the processing + * flow of data packets or frames. + * + * Due to differences in how data is packed and processed, this + * block also offers the ability to change the direction of how + * bits are unpacked and packed, where reading or writing from the + * LSB or MSB. By default, the \p rev_unpack and \p rev_pack modes + * are set to True. Using this setup allows the async block to + * behave with PDUs in the same operation and format as the tagged + * stream encoders. That is, putting the same data into both the + * tagged stream encoder deployment and this with these default + * settings should produce the same data. + */ +class FEC_API async_encoder : virtual public block +{ +public: + typedef boost::shared_ptr<async_encoder> sptr; /*! - * \brief Creates the encoder block for use in GNU Radio - * flowgraphs with async message from a given FEC API object - * derived from the generic_encoder class. - * \ingroup error_coding_blk - * - * \details - * - * Encodes frames received as async messages or as a PDU over a - * message port. This encoder works off a full message as one - * frame or block to encode. The message length is used as the - * frame length. To support this, the encoder variable used will - * have had its frame_size set. This block treats that initial - * frame_size value as the maximum transmission unit (MTU) and - * will not process frames larger than that. + * Build the PDU-based FEC encoder block from an FECAPI encoder object. * - * This deployment works off messages and expects them to either - * be messages full of unpacked bits or PDU messages, which means - * full bytes of a frame from the higher layers, including things - * like headers, tails, CRC check bytes, etc. For handling PDUs, - * set the \p packed option of this deployment block to True. The - * block will then use the FEC API to properly unpack the bits - * from the PDU, pass it through the encoder, and repack them to - * output the PDUs for the next stage of processing. - * - * The packed PDU form of this deployment is designed to work well - * with other PDU-based blocks to operate within the processing - * flow of data packets or frames. - * - * Due to differences in how data is packed and processed, this - * block also offers the ability to change the direction of how - * bits are unpacked and packed, where reading or writing from the - * LSB or MSB. By default, the \p rev_unpack and \p rev_pack modes - * are set to True. Using this setup allows the async block to - * behave with PDUs in the same operation and format as the tagged - * stream encoders. That is, putting the same data into both the - * tagged stream encoder deployment and this with these default - * settings should produce the same data. + * \param my_encoder An FECAPI encoder object child of the generic_encoder class. + * \param packed True if working on packed bytes (like PDUs). + * \param rev_unpack Reverse the unpacking order from input bytes to bits. + * \param rev_pack Reverse the packing order from bits to output bytes. + * \param mtu The Maximum Transmission Unit (MTU) of the input + * frame that the block will be able to + * process. Specified in bytes and defaults to 1500. */ - class FEC_API async_encoder : virtual public block - { - public: - typedef boost::shared_ptr<async_encoder> sptr; - - /*! - * Build the PDU-based FEC encoder block from an FECAPI encoder object. - * - * \param my_encoder An FECAPI encoder object child of the generic_encoder class. - * \param packed True if working on packed bytes (like PDUs). - * \param rev_unpack Reverse the unpacking order from input bytes to bits. - * \param rev_pack Reverse the packing order from bits to output bytes. - * \param mtu The Maximum Transmission Unit (MTU) of the input - * frame that the block will be able to - * process. Specified in bytes and defaults to 1500. - */ - static sptr make(generic_encoder::sptr my_encoder, - bool packed=false, - bool rev_unpack=true, bool rev_pack=true, - int mtu=1500); + static sptr make(generic_encoder::sptr my_encoder, + bool packed = false, + bool rev_unpack = true, + bool rev_pack = true, + int mtu = 1500); - virtual int general_work(int noutput_items, - gr_vector_int& ninput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) = 0; - }; + virtual int general_work(int noutput_items, + gr_vector_int& ninput_items, + gr_vector_const_void_star& input_items, + gr_vector_void_star& output_items) = 0; +}; - } /* namespace fec */ +} /* namespace fec */ } /* namespace gr */ #endif /* INCLUDED_FEC_ASYNC_ENCODER_H */ diff --git a/gr-fec/include/gnuradio/fec/awgn_bp.h b/gr-fec/include/gnuradio/fec/awgn_bp.h index 62fe7e26a4..bbe9ba889c 100644 --- a/gr-fec/include/gnuradio/fec/awgn_bp.h +++ b/gr-fec/include/gnuradio/fec/awgn_bp.h @@ -45,24 +45,24 @@ class FEC_API awgn_bp { - public: +public: //! Default constructor - awgn_bp () {}; + awgn_bp(){}; //! A constructor for given GF2Mat and sigma - awgn_bp (const GF2Mat X, float sgma); + awgn_bp(const GF2Mat X, float sgma); //! A constructor for given alist and sigma - awgn_bp (alist _list, float sgma); + awgn_bp(alist _list, float sgma); //! Initializes the class using given alist and sigma - void set_alist_sigma(alist _list, float sgma); + void set_alist_sigma(alist _list, float sgma); //! Returns the variable Q - std::vector< std::vector<double> > get_Q(); + std::vector<std::vector<double>> get_Q(); //! Returns the variable R - std::vector< std::vector<double> > get_R(); + std::vector<std::vector<double>> get_R(); //! Returns the variable H GF2Mat get_H(); @@ -124,10 +124,10 @@ class FEC_API awgn_bp * \param rx_word The received samples for decoding. * \param niterations The number of message passing iterations * done to decode this codeword. - */ - std::vector<char> decode (std::vector<float> rx_word, - int *niterations); - private: + */ + std::vector<char> decode(std::vector<float> rx_word, int* niterations); + +private: //! The number of check nodes in the tanner-graph int M; @@ -147,10 +147,10 @@ class FEC_API awgn_bp float sigma; //! Matrix holding messages from check nodes to variable nodes - std::vector< std::vector<double> > R; + std::vector<std::vector<double>> R; //! Matrix holding messages from variable nodes to check nodes - std::vector< std::vector<double> > Q; + std::vector<std::vector<double>> Q; //! The array of likelihood computed from the channel output std::vector<double> rx_lr; @@ -159,16 +159,16 @@ class FEC_API awgn_bp std::vector<double> lr; //! List of integer coordinates along each column with non-zero entries - std::vector < std::vector<int> > nlist; + std::vector<std::vector<int>> nlist; //! List of integer coordinates along each row with non-zero entries - std::vector < std::vector<int> > mlist; + std::vector<std::vector<int>> mlist; //! Weight of each column n - std::vector <int> num_nlist; + std::vector<int> num_nlist; //! Weight of each row m - std::vector <int> num_mlist; + std::vector<int> num_mlist; //! The array for holding estimate computed on BP decoding std::vector<char> estimate; diff --git a/gr-fec/include/gnuradio/fec/ber_bf.h b/gr-fec/include/gnuradio/fec/ber_bf.h index 5e219defc1..a8e78c0fc5 100644 --- a/gr-fec/include/gnuradio/fec/ber_bf.h +++ b/gr-fec/include/gnuradio/fec/ber_bf.h @@ -27,66 +27,67 @@ #include <gnuradio/block.h> namespace gr { - namespace fec { +namespace fec { + +/*! + * \brief BER block in FECAPI + * \ingroup error_coding_blk + * + * \details + * + * This block measures the bit error rate between two streams of + * packed data. It compares the bits of each streams and counts + * the number of incorrect bits between them. It outputs the log + * of the bit error rate, so a value of -X is 10^{-X} bit errors. + * + * When the \p mode is set to false (default), it is in streaming + * mode. This means that the output is constantly producing the + * current value of the BER. In this mode, there is a single + * output BER calculation per chunk of bytes passed to it, so + * there is no exact timing between calculations of BER. In this + * mode, the other two parameters to the constructor are ignored. + * + * When \p mode is true, the block is in test mode. This mode is + * used in the ber_curve_gen example and for other offline + * analysis of BER curves. Here, the block waits until at least \p + * berminerrors are observed and then produces a BER + * calculation. The parameter \p ber_limit helps make sure that + * the simulation is controlled. If the BER calculation drops + * below the \p ber_limit setting, the block will exit and simply + * return the set limit; the real BER is therefore some amount + * lower than this. + * + * Note that this block takes in data as packed bytes with 8-bits + * per byte used. It outputs a stream of floats as the log-scale BER. + */ +class FEC_API ber_bf : virtual public block +{ +public: + // gr::fec::ber_bf::sptr + typedef boost::shared_ptr<ber_bf> sptr; /*! - * \brief BER block in FECAPI - * \ingroup error_coding_blk - * - * \details - * - * This block measures the bit error rate between two streams of - * packed data. It compares the bits of each streams and counts - * the number of incorrect bits between them. It outputs the log - * of the bit error rate, so a value of -X is 10^{-X} bit errors. - * - * When the \p mode is set to false (default), it is in streaming - * mode. This means that the output is constantly producing the - * current value of the BER. In this mode, there is a single - * output BER calculation per chunk of bytes passed to it, so - * there is no exact timing between calculations of BER. In this - * mode, the other two parameters to the constructor are ignored. - * - * When \p mode is true, the block is in test mode. This mode is - * used in the ber_curve_gen example and for other offline - * analysis of BER curves. Here, the block waits until at least \p - * berminerrors are observed and then produces a BER - * calculation. The parameter \p ber_limit helps make sure that - * the simulation is controlled. If the BER calculation drops - * below the \p ber_limit setting, the block will exit and simply - * return the set limit; the real BER is therefore some amount - * lower than this. - * - * Note that this block takes in data as packed bytes with 8-bits - * per byte used. It outputs a stream of floats as the log-scale BER. + * Get total number of errors counter value. */ - class FEC_API ber_bf : virtual public block - { - public: - // gr::fec::ber_bf::sptr - typedef boost::shared_ptr<ber_bf> sptr; + virtual long total_errors() = 0; - /*! - * Get total number of errors counter value. - */ - virtual long total_errors() = 0; - - /*! - * Calculate the BER between two streams of data. - * - * \param test_mode false for normal streaming mode (default); - * true for test mode. - * \param berminerrors the block needs to observe this many - * errors before outputting a result. Only valid when - * test_mode=true. - * \param ber_limit if the BER calculation falls below this - * limit, produce this value and exit. Only valid when - * test_mode=true. - */ - static sptr make(bool test_mode = false, int berminerrors=100, float ber_limit=-7.0); - }; + /*! + * Calculate the BER between two streams of data. + * + * \param test_mode false for normal streaming mode (default); + * true for test mode. + * \param berminerrors the block needs to observe this many + * errors before outputting a result. Only valid when + * test_mode=true. + * \param ber_limit if the BER calculation falls below this + * limit, produce this value and exit. Only valid when + * test_mode=true. + */ + static sptr + make(bool test_mode = false, int berminerrors = 100, float ber_limit = -7.0); +}; - } /* namespace fec */ +} /* namespace fec */ } /* namespace gr */ #endif /* INCLUDED_FEC_BER_BF_H */ diff --git a/gr-fec/include/gnuradio/fec/cc_common.h b/gr-fec/include/gnuradio/fec/cc_common.h index 8abf565d4a..5bdd84c213 100644 --- a/gr-fec/include/gnuradio/fec/cc_common.h +++ b/gr-fec/include/gnuradio/fec/cc_common.h @@ -24,28 +24,29 @@ #define INCLUDED_FEC_CC_COMMON_H typedef enum _cc_mode_t { - CC_STREAMING = 0, - CC_TERMINATED, - CC_TRUNCATED, - CC_TAILBITING + CC_STREAMING = 0, + CC_TERMINATED, + CC_TRUNCATED, + CC_TAILBITING } cc_mode_t; typedef union { - //decision_t is a BIT vector - unsigned char* t; - unsigned int* w; - unsigned short* s; - unsigned char* c; + // decision_t is a BIT vector + unsigned char* t; + unsigned int* w; + unsigned short* s; + unsigned char* c; } decision_t; typedef union { - unsigned char* t; + unsigned char* t; } metric_t; struct v { - unsigned char *metrics; - metric_t old_metrics,new_metrics,metrics1,metrics2; /* Pointers to path metrics, swapped on every bit */ - unsigned char *decisions; + unsigned char* metrics; + metric_t old_metrics, new_metrics, metrics1, + metrics2; /* Pointers to path metrics, swapped on every bit */ + unsigned char* decisions; }; #endif /*INCLUDED_FEC_CC_COMMON_H*/ diff --git a/gr-fec/include/gnuradio/fec/cc_decoder.h b/gr-fec/include/gnuradio/fec/cc_decoder.h index 8f29af98ca..c426749da5 100644 --- a/gr-fec/include/gnuradio/fec/cc_decoder.h +++ b/gr-fec/include/gnuradio/fec/cc_decoder.h @@ -30,115 +30,119 @@ #include <string> namespace gr { - namespace fec { - namespace code { +namespace fec { +namespace code { - typedef void(*conv_kernel)(unsigned char *Y, unsigned char *X, - unsigned char *syms, unsigned char *dec, - unsigned int framebits, unsigned int excess, - unsigned char *Branchtab); +typedef void (*conv_kernel)(unsigned char* Y, + unsigned char* X, + unsigned char* syms, + unsigned char* dec, + unsigned int framebits, + unsigned int excess, + unsigned char* Branchtab); - /*! - * \brief Convolutional Code Decoding class. - * \ingroup error_coding_blk - * - * \details - * This class performs convolutional decoding via the Viterbi - * algorithm. While it is set up to take variable values for K, - * rate, and the polynomials, currently, the block is only - * capable of handling the following settings: - * - * \li K = 7 - * \li rate = 1/2 (given as 2 to the constructor) - * \li polynomials = [109, 79] - * - * This is the well-known convolutional part of the Voyager code - * implemented in the CCSDS encoder. - * - * The intent of having this FECAPI code classes fully - * parameterizable is to eventually allow it to take on generic - * settings, much like the cc_encoder class where the CCSDS - * settings would be a highly-optimized version of this. - * - * The decoder is set up with a number of bits per frame in the - * constructor. When not being used in a tagged stream mode, - * this encoder will only process frames of the length provided - * here. If used in a tagged stream block, this setting becomes - * the maximum allowable frame size that the block may process. - * - * The \p mode is a cc_mode_t that specifies how the convolutional - * encoder will behave and under what conditions. - * - * \li 'CC_STREAMING': mode expects an uninterrupted flow of - * samples into the encoder, and the output stream is - * continually encoded. This mode is the only mode for this - * decoder that has a history requirement because it requires - * rate*(K-1) bits more to finish the decoding properly. This - * mode does not work with any deployments that do not allow - * history. - * - * \li 'CC_TERMINATED': is a mode designed for packet-based - * systems. This mode adds rate*(k-1) bits to the output as a - * way to help flush the decoder. - * - * \li 'CC_TAILBITING': is another packet-based method. Instead of - * adding bits onto the end of the packet, this mode will - * continue the code between the payloads of packets by - * pre-initializing the state of the new packet based on the - * state of the last packet for (k-1) bits. - * - * \li 'CC_TRUNCATED': a truncated code always resets the registers - * to the \p start_state between frames. - * - * A common convolutional encoder uses K=7, Rate=1/2, - * Polynomials=[109, 79]. This is the Voyager code from NASA: - * \li 109: b(1101101) --> 1 + x + x^3 + x^4 + x^6 - * \li 79: b(1001111) --> 1 + x^3 + x^4 + x^5 + x^6 - */ - class FEC_API cc_decoder : virtual public generic_decoder - { - public: - - /*! - * Build a convolutional code decoding FEC API object. - * - * \param frame_size Number of bits per frame. If using in the - * tagged stream style, this is the maximum allowable - * number of bits per frame. - * \param k Constraint length (K) of the encoder. - * \param rate Inverse of the coder's rate - * (rate=2 means 2 output bits per 1 input). - * \param polys Vector of polynomials as integers. - * \param start_state Initialization state of the shift register. - * \param end_state Ending state of the shift register. - * \param mode cc_mode_t mode of the encoding. - * \param padded true if the encoded frame is padded - * to the nearest byte. - */ - static generic_decoder::sptr make - (int frame_size, int k, - int rate, std::vector<int> polys, - int start_state=0, int end_state=-1, - cc_mode_t mode=CC_STREAMING, - bool padded=false); +/*! + * \brief Convolutional Code Decoding class. + * \ingroup error_coding_blk + * + * \details + * This class performs convolutional decoding via the Viterbi + * algorithm. While it is set up to take variable values for K, + * rate, and the polynomials, currently, the block is only + * capable of handling the following settings: + * + * \li K = 7 + * \li rate = 1/2 (given as 2 to the constructor) + * \li polynomials = [109, 79] + * + * This is the well-known convolutional part of the Voyager code + * implemented in the CCSDS encoder. + * + * The intent of having this FECAPI code classes fully + * parameterizable is to eventually allow it to take on generic + * settings, much like the cc_encoder class where the CCSDS + * settings would be a highly-optimized version of this. + * + * The decoder is set up with a number of bits per frame in the + * constructor. When not being used in a tagged stream mode, + * this encoder will only process frames of the length provided + * here. If used in a tagged stream block, this setting becomes + * the maximum allowable frame size that the block may process. + * + * The \p mode is a cc_mode_t that specifies how the convolutional + * encoder will behave and under what conditions. + * + * \li 'CC_STREAMING': mode expects an uninterrupted flow of + * samples into the encoder, and the output stream is + * continually encoded. This mode is the only mode for this + * decoder that has a history requirement because it requires + * rate*(K-1) bits more to finish the decoding properly. This + * mode does not work with any deployments that do not allow + * history. + * + * \li 'CC_TERMINATED': is a mode designed for packet-based + * systems. This mode adds rate*(k-1) bits to the output as a + * way to help flush the decoder. + * + * \li 'CC_TAILBITING': is another packet-based method. Instead of + * adding bits onto the end of the packet, this mode will + * continue the code between the payloads of packets by + * pre-initializing the state of the new packet based on the + * state of the last packet for (k-1) bits. + * + * \li 'CC_TRUNCATED': a truncated code always resets the registers + * to the \p start_state between frames. + * + * A common convolutional encoder uses K=7, Rate=1/2, + * Polynomials=[109, 79]. This is the Voyager code from NASA: + * \li 109: b(1101101) --> 1 + x + x^3 + x^4 + x^6 + * \li 79: b(1001111) --> 1 + x^3 + x^4 + x^5 + x^6 + */ +class FEC_API cc_decoder : virtual public generic_decoder +{ +public: + /*! + * Build a convolutional code decoding FEC API object. + * + * \param frame_size Number of bits per frame. If using in the + * tagged stream style, this is the maximum allowable + * number of bits per frame. + * \param k Constraint length (K) of the encoder. + * \param rate Inverse of the coder's rate + * (rate=2 means 2 output bits per 1 input). + * \param polys Vector of polynomials as integers. + * \param start_state Initialization state of the shift register. + * \param end_state Ending state of the shift register. + * \param mode cc_mode_t mode of the encoding. + * \param padded true if the encoded frame is padded + * to the nearest byte. + */ + static generic_decoder::sptr make(int frame_size, + int k, + int rate, + std::vector<int> polys, + int start_state = 0, + int end_state = -1, + cc_mode_t mode = CC_STREAMING, + bool padded = false); - /*! - * Sets the uncoded frame size to \p frame_size. If \p - * frame_size is greater than the value given to the - * constructor, the frame size will be capped by that initial - * value and this function will return false. Otherwise, it - * returns true. - */ - virtual bool set_frame_size(unsigned int frame_size) = 0; + /*! + * Sets the uncoded frame size to \p frame_size. If \p + * frame_size is greater than the value given to the + * constructor, the frame size will be capped by that initial + * value and this function will return false. Otherwise, it + * returns true. + */ + virtual bool set_frame_size(unsigned int frame_size) = 0; - /*! - * Returns the coding rate of this encoder. - */ - virtual double rate() = 0; - }; + /*! + * Returns the coding rate of this encoder. + */ + virtual double rate() = 0; +}; - } /* namespace code */ - } /* namespace fec */ +} /* namespace code */ +} /* namespace fec */ } /* namespace gr */ #endif /* INCLUDED_FEC_CC_DECODER_H */ diff --git a/gr-fec/include/gnuradio/fec/cc_encoder.h b/gr-fec/include/gnuradio/fec/cc_encoder.h index 04ce6299d6..fcaf6dcf27 100644 --- a/gr-fec/include/gnuradio/fec/cc_encoder.h +++ b/gr-fec/include/gnuradio/fec/cc_encoder.h @@ -30,111 +30,113 @@ #include <string> namespace gr { - namespace fec { - namespace code { +namespace fec { +namespace code { - /*! - * \brief Convolutional Code Encoding class. - * \ingroup error_coding_blk - * - * \details - * This class performs convolutional encoding for unpacked bits - * for frames of a constant length. This class is general in its - * application of the convolutional encoding and allows us to - * specify the constraint length, the coding rate, and the - * polynomials used in the coding process. - * - * The parameter \p k sets the constraint length directly. We - * set the coding rate by setting \p rate to R given a desired - * rate of 1/R. That is, for a rate 1/2 coder, we would set \p - * rate to 2. And the polynomial is specified as a vector of - * integers, where each integer represents the coding polynomial - * for a different arm of the code. The number of polynomials - * given must be the same as the value \p rate. - * - * The encoding object holds a shift register that takes in each - * bit from the input stream and then ANDs the shift register - * with each polynomial, and places the parity of the result - * into the output stream. The output stream is therefore also - * unpacked bits. - * - * The encoder is set up with a number of bits per frame in the - * constructor. When not being used in a tagged stream mode, - * this encoder will only process frames of the length provided - * here. If used in a tagged stream block, this setting becomes - * the maximum allowable frame size that the block may process. - * - * The \p mode is a cc_mode_t that specifies how the convolutional - * encoder will behave and under what conditions. - * - * \li 'CC_STREAMING': mode expects an uninterrupted flow of - * samples into the encoder, and the output stream is - * continually encoded. - * - * \li 'CC_TERMINATED': is a mode designed for packet-based - * systems. This mode adds rate*(k-1) bits to the output as a - * way to help flush the decoder. - * - * \li 'CC_TAILBITING': is another packet-based method. Instead of - * adding bits onto the end of the packet, this mode will - * continue the code between the payloads of packets by - * pre-initializing the state of the new packet based on the - * state of the last packet for (k-1) bits. - * - * \li 'CC_TRUNCATED': a truncated code always resets the registers - * to the \p start_state between frames. - * - * A common convolutional encoder uses K=7, Rate=1/2, - * Polynomials=[109, 79]. This is the Voyager code from NASA: - * \li 109: b(1101101) --> 1 + x + x^3 + x^4 + x^6 - * \li 79: b(1001111) --> 1 + x^3 + x^4 + x^5 + x^6 - * - * Another encoder class is provided with gr-fec called the - * gr::fec::code::ccsds_encoder, which implements the above code - * that is more highly optimized for just those specific - * settings. - */ - class FEC_API cc_encoder : virtual public generic_encoder - { - public: - - /*! - * Build a convolutional code encoding FEC API object. - * - * \param frame_size Number of bits per frame. If using in the - * tagged stream style, this is the maximum allowable - * number of bits per frame. - * \param k Constraint length (K) of the encoder. - * \param rate Inverse of the coder's rate - * (rate=2 means 2 output bits per 1 input). - * \param polys Vector of polynomials as integers. - * \param start_state Initialization state of the shift register. - * \param mode cc_mode_t mode of the encoding. - * \param padded true if the encoded frame should be padded - * to the nearest byte. - */ - static generic_encoder::sptr make - (int frame_size, int k, int rate, - std::vector<int> polys, int start_state = 0, - cc_mode_t mode=CC_STREAMING, bool padded=false); +/*! + * \brief Convolutional Code Encoding class. + * \ingroup error_coding_blk + * + * \details + * This class performs convolutional encoding for unpacked bits + * for frames of a constant length. This class is general in its + * application of the convolutional encoding and allows us to + * specify the constraint length, the coding rate, and the + * polynomials used in the coding process. + * + * The parameter \p k sets the constraint length directly. We + * set the coding rate by setting \p rate to R given a desired + * rate of 1/R. That is, for a rate 1/2 coder, we would set \p + * rate to 2. And the polynomial is specified as a vector of + * integers, where each integer represents the coding polynomial + * for a different arm of the code. The number of polynomials + * given must be the same as the value \p rate. + * + * The encoding object holds a shift register that takes in each + * bit from the input stream and then ANDs the shift register + * with each polynomial, and places the parity of the result + * into the output stream. The output stream is therefore also + * unpacked bits. + * + * The encoder is set up with a number of bits per frame in the + * constructor. When not being used in a tagged stream mode, + * this encoder will only process frames of the length provided + * here. If used in a tagged stream block, this setting becomes + * the maximum allowable frame size that the block may process. + * + * The \p mode is a cc_mode_t that specifies how the convolutional + * encoder will behave and under what conditions. + * + * \li 'CC_STREAMING': mode expects an uninterrupted flow of + * samples into the encoder, and the output stream is + * continually encoded. + * + * \li 'CC_TERMINATED': is a mode designed for packet-based + * systems. This mode adds rate*(k-1) bits to the output as a + * way to help flush the decoder. + * + * \li 'CC_TAILBITING': is another packet-based method. Instead of + * adding bits onto the end of the packet, this mode will + * continue the code between the payloads of packets by + * pre-initializing the state of the new packet based on the + * state of the last packet for (k-1) bits. + * + * \li 'CC_TRUNCATED': a truncated code always resets the registers + * to the \p start_state between frames. + * + * A common convolutional encoder uses K=7, Rate=1/2, + * Polynomials=[109, 79]. This is the Voyager code from NASA: + * \li 109: b(1101101) --> 1 + x + x^3 + x^4 + x^6 + * \li 79: b(1001111) --> 1 + x^3 + x^4 + x^5 + x^6 + * + * Another encoder class is provided with gr-fec called the + * gr::fec::code::ccsds_encoder, which implements the above code + * that is more highly optimized for just those specific + * settings. + */ +class FEC_API cc_encoder : virtual public generic_encoder +{ +public: + /*! + * Build a convolutional code encoding FEC API object. + * + * \param frame_size Number of bits per frame. If using in the + * tagged stream style, this is the maximum allowable + * number of bits per frame. + * \param k Constraint length (K) of the encoder. + * \param rate Inverse of the coder's rate + * (rate=2 means 2 output bits per 1 input). + * \param polys Vector of polynomials as integers. + * \param start_state Initialization state of the shift register. + * \param mode cc_mode_t mode of the encoding. + * \param padded true if the encoded frame should be padded + * to the nearest byte. + */ + static generic_encoder::sptr make(int frame_size, + int k, + int rate, + std::vector<int> polys, + int start_state = 0, + cc_mode_t mode = CC_STREAMING, + bool padded = false); - /*! - * Sets the uncoded frame size to \p frame_size. If \p - * frame_size is greater than the value given to the - * constructor, the frame size will be capped by that initial - * value and this function will return false. Otherwise, it - * returns true. - */ - virtual bool set_frame_size(unsigned int frame_size) = 0; + /*! + * Sets the uncoded frame size to \p frame_size. If \p + * frame_size is greater than the value given to the + * constructor, the frame size will be capped by that initial + * value and this function will return false. Otherwise, it + * returns true. + */ + virtual bool set_frame_size(unsigned int frame_size) = 0; - /*! - * Returns the coding rate of this encoder. - */ - virtual double rate() = 0; - }; + /*! + * Returns the coding rate of this encoder. + */ + virtual double rate() = 0; +}; - } /* namespace code */ - } /* namespace fec */ +} /* namespace code */ +} /* namespace fec */ } /* namespace gr */ #endif /* INCLUDED_FEC_CC_ENCODER_H */ diff --git a/gr-fec/include/gnuradio/fec/ccsds_encoder.h b/gr-fec/include/gnuradio/fec/ccsds_encoder.h index f482ad90f7..4eca78084e 100644 --- a/gr-fec/include/gnuradio/fec/ccsds_encoder.h +++ b/gr-fec/include/gnuradio/fec/ccsds_encoder.h @@ -30,88 +30,86 @@ #include <string> namespace gr { - namespace fec { - namespace code { +namespace fec { +namespace code { - /*! - * \brief CCSDS Encoding class for convolutional encoding with - * rate 1/2, K=7, and polynomials [109, 79]. - * \ingroup error_coding_blk - * - * \details - * - * Uses Phil Karn's (KA9Q) implementation of the CCSDS encoder - * for rate 1/2, K=7, and CC polynomial [109, 79]. These are - * non-adjustable in this encoder. For an adjustable CC encoder - * where we can set the rate, constraint length, and polynomial, - * see gr::fec::code::cc_encoder. - * - * The encoder is set up with a number of bits per frame in the - * constructor. When not being used in a tagged stream mode, - * this encoder will only process frames of the length provided - * here. If used in a tagged stream block, this setting becomes - * the maximum allowable frame size that the block may process. - * - * The \p mode is a cc_mode_t that specifies how the convolutional - * encoder will behave and under what conditions. - * - * \li 'CC_STREAMING': mode expects an uninterrupted flow of - * samples into the encoder, and the output stream is - * continually encoded. - * - * \li 'CC_TERMINATED': is a mode designed for packet-based - * systems. This mode adds rate*(k-1) bits to the output as a - * way to help flush the decoder. - * - * \li 'CC_TAILBITING': is another packet-based method. Instead of - * adding bits onto the end of the packet, this mode will - * continue the code between the payloads of packets by - * pre-initializing the state of the new packet based on the - * state of the last packet for (k-1) bits. - * - * \li 'CC_TRUNCATED': a truncated code always resets the registers - * to the \p start_state between frames. - * - * A common convolutional encoder uses K=7, Rate=1/2, - * Polynomials=[109, 79]. This is the Voyager code from NASA: - * \li 109: b(1101101) --> 1 + x + x^3 + x^4 + x^6 - * \li 79: b(1001111) --> 1 + x^3 + x^4 + x^5 + x^6 - */ - class FEC_API ccsds_encoder : virtual public generic_encoder - { - public: - - /*! - * Build the CCSDS (rate=1/2, K=7, polys=[109,79] - * convolutional code FECAPI object. - * - * \param frame_size Number of bits per frame. If using in the - * tagged stream style, this is the maximum allowable - * number of bits per frame. - * \param start_state Initialization state of the shift register. - * \param mode cc_mode_t mode of the encoding. - */ - static generic_encoder::sptr make - (int frame_size, int start_state = 0, - cc_mode_t mode=CC_STREAMING); +/*! + * \brief CCSDS Encoding class for convolutional encoding with + * rate 1/2, K=7, and polynomials [109, 79]. + * \ingroup error_coding_blk + * + * \details + * + * Uses Phil Karn's (KA9Q) implementation of the CCSDS encoder + * for rate 1/2, K=7, and CC polynomial [109, 79]. These are + * non-adjustable in this encoder. For an adjustable CC encoder + * where we can set the rate, constraint length, and polynomial, + * see gr::fec::code::cc_encoder. + * + * The encoder is set up with a number of bits per frame in the + * constructor. When not being used in a tagged stream mode, + * this encoder will only process frames of the length provided + * here. If used in a tagged stream block, this setting becomes + * the maximum allowable frame size that the block may process. + * + * The \p mode is a cc_mode_t that specifies how the convolutional + * encoder will behave and under what conditions. + * + * \li 'CC_STREAMING': mode expects an uninterrupted flow of + * samples into the encoder, and the output stream is + * continually encoded. + * + * \li 'CC_TERMINATED': is a mode designed for packet-based + * systems. This mode adds rate*(k-1) bits to the output as a + * way to help flush the decoder. + * + * \li 'CC_TAILBITING': is another packet-based method. Instead of + * adding bits onto the end of the packet, this mode will + * continue the code between the payloads of packets by + * pre-initializing the state of the new packet based on the + * state of the last packet for (k-1) bits. + * + * \li 'CC_TRUNCATED': a truncated code always resets the registers + * to the \p start_state between frames. + * + * A common convolutional encoder uses K=7, Rate=1/2, + * Polynomials=[109, 79]. This is the Voyager code from NASA: + * \li 109: b(1101101) --> 1 + x + x^3 + x^4 + x^6 + * \li 79: b(1001111) --> 1 + x^3 + x^4 + x^5 + x^6 + */ +class FEC_API ccsds_encoder : virtual public generic_encoder +{ +public: + /*! + * Build the CCSDS (rate=1/2, K=7, polys=[109,79] + * convolutional code FECAPI object. + * + * \param frame_size Number of bits per frame. If using in the + * tagged stream style, this is the maximum allowable + * number of bits per frame. + * \param start_state Initialization state of the shift register. + * \param mode cc_mode_t mode of the encoding. + */ + static generic_encoder::sptr + make(int frame_size, int start_state = 0, cc_mode_t mode = CC_STREAMING); - /*! - * Sets the uncoded frame size to \p frame_size. If \p - * frame_size is greater than the value given to the - * constructor, the frame size will be capped by that initial - * value and this function will return false. Otherwise, it - * returns true. - */ - virtual bool set_frame_size(unsigned int frame_size) = 0; + /*! + * Sets the uncoded frame size to \p frame_size. If \p + * frame_size is greater than the value given to the + * constructor, the frame size will be capped by that initial + * value and this function will return false. Otherwise, it + * returns true. + */ + virtual bool set_frame_size(unsigned int frame_size) = 0; - /*! - * Returns the coding rate of this encoder. - */ - virtual double rate() = 0; - }; + /*! + * Returns the coding rate of this encoder. + */ + virtual double rate() = 0; +}; - } /* namespace code */ - } /* namespace fec */ +} /* namespace code */ +} /* namespace fec */ } /* namespace gr */ #endif /* INCLUDED_FEC_CCSDS_ENCODER_H */ diff --git a/gr-fec/include/gnuradio/fec/cldpc.h b/gr-fec/include/gnuradio/fec/cldpc.h index 6bc7c02343..758594d3e7 100644 --- a/gr-fec/include/gnuradio/fec/cldpc.h +++ b/gr-fec/include/gnuradio/fec/cldpc.h @@ -34,9 +34,9 @@ #include <gnuradio/fec/api.h> class FEC_API cldpc { - public: +public: //! Default constructor - cldpc() {}; + cldpc(){}; //! Constructs the LDPC class from given GF2mat X cldpc(const GF2Mat X); @@ -89,7 +89,7 @@ class FEC_API cldpc //! Obtain systematic bits from "in" std::vector<char> get_systematic_bits(std::vector<char> in); - private: +private: //! The parity check matrix GF2Mat H; diff --git a/gr-fec/include/gnuradio/fec/conv_bit_corr_bb.h b/gr-fec/include/gnuradio/fec/conv_bit_corr_bb.h index 87ab768fcc..a4a23490a5 100644 --- a/gr-fec/include/gnuradio/fec/conv_bit_corr_bb.h +++ b/gr-fec/include/gnuradio/fec/conv_bit_corr_bb.h @@ -28,35 +28,38 @@ #include <vector> namespace gr { - namespace fec { +namespace fec { + +/*! + * \brief Correlate block in FECAPI + * \ingroup error_coding_blk + * + * \details + * + * What does this block do? + */ +class FEC_API conv_bit_corr_bb : virtual public block +{ +public: + // gr::fec::conv_bit_corr_bb::sptr + typedef boost::shared_ptr<conv_bit_corr_bb> sptr; + + static sptr make(std::vector<unsigned long long> correlator, + int corr_sym, + int corr_len, + int cut, + int flush, + float thresh); /*! - * \brief Correlate block in FECAPI - * \ingroup error_coding_blk - * - * \details - * - * What does this block do? + * This subroutine will find the encoded data garble rate + * corresponding to a syndrome density of `target', that is created + * with an annihilating polynomial with 'taps' number of taps. */ - class FEC_API conv_bit_corr_bb : virtual public block - { - public: - // gr::fec::conv_bit_corr_bb::sptr - typedef boost::shared_ptr<conv_bit_corr_bb> sptr; - - static sptr make(std::vector<unsigned long long> correlator, - int corr_sym, int corr_len, int cut, - int flush, float thresh); - - /*! - * This subroutine will find the encoded data garble rate - * corresponding to a syndrome density of `target', that is created - * with an annihilating polynomial with 'taps' number of taps. - */ - virtual float data_garble_rate(int taps, float syn_density) = 0; - }; - - } /* namespace fec */ + virtual float data_garble_rate(int taps, float syn_density) = 0; +}; + +} /* namespace fec */ } /* namespace gr */ #endif /* INCLUDED_FEC_CONV_BIT_CORR_BB_H */ diff --git a/gr-fec/include/gnuradio/fec/decode_ccsds_27_fb.h b/gr-fec/include/gnuradio/fec/decode_ccsds_27_fb.h index 99ed154c81..228e10628f 100644 --- a/gr-fec/include/gnuradio/fec/decode_ccsds_27_fb.h +++ b/gr-fec/include/gnuradio/fec/decode_ccsds_27_fb.h @@ -27,39 +27,38 @@ #include <gnuradio/sync_decimator.h> namespace gr { - namespace fec { +namespace fec { - /*! \brief A rate 1/2, k=7 convolutional decoder for the CCSDS standard - * \ingroup error_coding_blk - * - * \details - * This block performs soft-decision convolutional decoding using the Viterbi - * algorithm. - * - * The input is a stream of (possibly noise corrupted) floating point values - * nominally spanning [-1.0, 1.0], representing the encoded channel symbols - * 0 (-1.0) and 1 (1.0), with erased symbols at 0.0. - * - * The output is MSB first packed bytes of decoded values. - * - * As a rate 1/2 code, there will be one output byte for every 16 input symbols. - * - * This block is designed for continuous data streaming, not packetized data. - * The first 32 bits out will be zeroes, with the output delayed four bytes - * from the corresponding inputs. - */ - - class FEC_API decode_ccsds_27_fb : virtual public sync_decimator - { - public: +/*! \brief A rate 1/2, k=7 convolutional decoder for the CCSDS standard + * \ingroup error_coding_blk + * + * \details + * This block performs soft-decision convolutional decoding using the Viterbi + * algorithm. + * + * The input is a stream of (possibly noise corrupted) floating point values + * nominally spanning [-1.0, 1.0], representing the encoded channel symbols + * 0 (-1.0) and 1 (1.0), with erased symbols at 0.0. + * + * The output is MSB first packed bytes of decoded values. + * + * As a rate 1/2 code, there will be one output byte for every 16 input symbols. + * + * This block is designed for continuous data streaming, not packetized data. + * The first 32 bits out will be zeroes, with the output delayed four bytes + * from the corresponding inputs. + */ - // gr::fec::decode_ccsds_27_fb::sptr - typedef boost::shared_ptr<decode_ccsds_27_fb> sptr; +class FEC_API decode_ccsds_27_fb : virtual public sync_decimator +{ +public: + // gr::fec::decode_ccsds_27_fb::sptr + typedef boost::shared_ptr<decode_ccsds_27_fb> sptr; - static sptr make(); - }; + static sptr make(); +}; - } /* namespace fec */ +} /* namespace fec */ } /* namespace gr */ #endif /* INCLUDED_FEC_DECODE_CCSDS_27_FB_H */ diff --git a/gr-fec/include/gnuradio/fec/decoder.h b/gr-fec/include/gnuradio/fec/decoder.h index 79eeef2197..38946deef3 100644 --- a/gr-fec/include/gnuradio/fec/decoder.h +++ b/gr-fec/include/gnuradio/fec/decoder.h @@ -31,67 +31,67 @@ #include <boost/format.hpp> namespace gr { - namespace fec { +namespace fec { + +/*! + * \brief General FEC decoding block that takes in a decoder + * variable object (derived from gr::fec::general_decoder) for use + * in a flowgraph. + * + * \ingroup error_coding_blk + * + * \details + * This block uses a decoder variable object (derived from + * gr::fec::generic_decoder) to decode data within a + * flowgraph. This block interacts with the general FECAPI + * architecture to handle all passing all input and output data in + * a flowgraph. The decoder variable takes care of understanding + * the requirements, data types and sizes, and boundary conditions + * of the specific FEC decoding algorithm. + * + * Generally, this block is used within the fec.extended_decoder + * Python block to handle some input/output formatting issues. In + * the FECAPI, the decoder variable sets properties like the input + * and output types and sizes and whether the output is packed or + * unpacked bytes. The fec.extended_decoder uses this information + * to set up an gr::hier_block2 structure to make sure the I/O to + * the variable is handled consistently, such as to make sure all + * inputs are floats with one soft symbol per item and the outputs + * are unpacked bytes with the bit in the LSB. + * + * See gr::fec::generic_decoder for detail on what information an + * FECAPI variable object can set if using this block directly and + * not as part of the fec.extended_decoder. + */ +class FEC_API decoder : virtual public block +{ +public: + typedef boost::shared_ptr<decoder> sptr; + typedef boost::shared_array<unsigned char> buf_sptr; /*! - * \brief General FEC decoding block that takes in a decoder - * variable object (derived from gr::fec::general_decoder) for use - * in a flowgraph. - * - * \ingroup error_coding_blk - * - * \details - * This block uses a decoder variable object (derived from - * gr::fec::generic_decoder) to decode data within a - * flowgraph. This block interacts with the general FECAPI - * architecture to handle all passing all input and output data in - * a flowgraph. The decoder variable takes care of understanding - * the requirements, data types and sizes, and boundary conditions - * of the specific FEC decoding algorithm. + * Create the FEC decoder block by taking in the FECAPI decoder + * object as well as input and output sizes. * - * Generally, this block is used within the fec.extended_decoder - * Python block to handle some input/output formatting issues. In - * the FECAPI, the decoder variable sets properties like the input - * and output types and sizes and whether the output is packed or - * unpacked bytes. The fec.extended_decoder uses this information - * to set up an gr::hier_block2 structure to make sure the I/O to - * the variable is handled consistently, such as to make sure all - * inputs are floats with one soft symbol per item and the outputs - * are unpacked bytes with the bit in the LSB. - * - * See gr::fec::generic_decoder for detail on what information an - * FECAPI variable object can set if using this block directly and - * not as part of the fec.extended_decoder. + * \param my_decoder An FECAPI decoder object (See gr::fec::generic_decoder). + * \param input_item_size The size of the input items (often the my_decoder object can + * tell us this). \param output_item_size The size of the output items (often the + * my_decoder object can tell us this). */ - class FEC_API decoder : virtual public block - { - public: - typedef boost::shared_ptr<decoder> sptr; - typedef boost::shared_array<unsigned char> buf_sptr; - - /*! - * Create the FEC decoder block by taking in the FECAPI decoder - * object as well as input and output sizes. - * - * \param my_decoder An FECAPI decoder object (See gr::fec::generic_decoder). - * \param input_item_size The size of the input items (often the my_decoder object can tell us this). - * \param output_item_size The size of the output items (often the my_decoder object can tell us this). - */ - static sptr make(generic_decoder::sptr my_decoder, - size_t input_item_size, - size_t output_item_size); + static sptr make(generic_decoder::sptr my_decoder, + size_t input_item_size, + size_t output_item_size); - virtual int general_work(int noutput_items, - gr_vector_int& ninput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) = 0; - virtual int fixed_rate_ninput_to_noutput(int ninput) = 0; - virtual int fixed_rate_noutput_to_ninput(int noutput) = 0; - virtual void forecast(int noutput_items, - gr_vector_int& ninput_items_required) = 0; - }; + virtual int general_work(int noutput_items, + gr_vector_int& ninput_items, + gr_vector_const_void_star& input_items, + gr_vector_void_star& output_items) = 0; + virtual int fixed_rate_ninput_to_noutput(int ninput) = 0; + virtual int fixed_rate_noutput_to_ninput(int noutput) = 0; + virtual void forecast(int noutput_items, gr_vector_int& ninput_items_required) = 0; +}; - } /* namespace fec */ +} /* namespace fec */ } /* namespace gr */ #endif /* INCLUDED_FEC_DECODER_H */ diff --git a/gr-fec/include/gnuradio/fec/depuncture_bb.h b/gr-fec/include/gnuradio/fec/depuncture_bb.h index de11defd2a..3d085286b7 100644 --- a/gr-fec/include/gnuradio/fec/depuncture_bb.h +++ b/gr-fec/include/gnuradio/fec/depuncture_bb.h @@ -27,85 +27,84 @@ #include <gnuradio/block.h> namespace gr { - namespace fec { +namespace fec { - /*! - * \brief Depuncture a stream of samples. - * \ingroup error_coding_blk - * - * \details +/*! + * \brief Depuncture a stream of samples. + * \ingroup error_coding_blk + * + * \details - * Depuncture a given block of input samples of \p puncsize. The - * items produced is based on the pattern \p puncpat. Basically, - * if: - * - * \code - * k = 0 - * if _puncpat[i] == 1: - * out[i] = input[k++] - * else: - * out[i] = symbol # default sym=127 - * \endcode - * - * This block is designed for unpacked bits - that is, every - * input sample is a bit, either a 1 or 0. It's possible to use - * packed bits as symbols, but the depuncturing will be done on - * the symbol level, not the bit level. - * - * \p puncpat is specified as a 32-bit integer that we can - * convert into the vector _puncpat used in the algorithm above: - * - * \code - * _puncpat = [0,...] - * for i in puncsize: - * _puncpat[i] = puncpat >> (puncsize-1-i) - * \endcode - * - * Example: - * \code - * puncsize = 8 - * puncpat = 0xEF --> [1,1,1,0,1,1,1,1] - * input = [a, b, c, d, e, f, g, h] - * output = [a, b, c, 127, e, f, g, h] - * \endcode - * - * The gr.fec Python module provides a read_bitlist function - * that can turn a string of a puncture pattern into the correct - * integer form. The pattern of 0xEF could be specified as - * fec.readbitlist("11101111"). Also, this allows us to use - * puncsize=len("11101111") to make sure that our sizes are set - * up correctly for the pattern we want. - * - * The fec.extended_decoder takes in the puncture pattern - * directly as a string and uses the readbitlist inside to do - * the conversion. + * Depuncture a given block of input samples of \p puncsize. The + * items produced is based on the pattern \p puncpat. Basically, + * if: + * + * \code + * k = 0 + * if _puncpat[i] == 1: + * out[i] = input[k++] + * else: + * out[i] = symbol # default sym=127 + * \endcode + * + * This block is designed for unpacked bits - that is, every + * input sample is a bit, either a 1 or 0. It's possible to use + * packed bits as symbols, but the depuncturing will be done on + * the symbol level, not the bit level. + * + * \p puncpat is specified as a 32-bit integer that we can + * convert into the vector _puncpat used in the algorithm above: + * + * \code + * _puncpat = [0,...] + * for i in puncsize: + * _puncpat[i] = puncpat >> (puncsize-1-i) + * \endcode + * + * Example: + * \code + * puncsize = 8 + * puncpat = 0xEF --> [1,1,1,0,1,1,1,1] + * input = [a, b, c, d, e, f, g, h] + * output = [a, b, c, 127, e, f, g, h] + * \endcode + * + * The gr.fec Python module provides a read_bitlist function + * that can turn a string of a puncture pattern into the correct + * integer form. The pattern of 0xEF could be specified as + * fec.readbitlist("11101111"). Also, this allows us to use + * puncsize=len("11101111") to make sure that our sizes are set + * up correctly for the pattern we want. + * + * The fec.extended_decoder takes in the puncture pattern + * directly as a string and uses the readbitlist inside to do + * the conversion. + * + * The \p delay parameter delays the application of the puncture + * pattern. This is equivalent to circularly rotating the \p + * puncpat by \p delay. Note that because of the circular shift, + * the delay should be between 0 and \p puncsize, but this is + * not enforced; the effective delay will simply be \p delay mod + * \p puncsize. A negative value here is ignored. + */ +class FEC_API depuncture_bb : virtual public block +{ +public: + // gr::fec::depuncture_bb::sptr + typedef boost::shared_ptr<depuncture_bb> sptr; + + /*! + * \brief Constructs a depuncture block. * - * The \p delay parameter delays the application of the puncture - * pattern. This is equivalent to circularly rotating the \p - * puncpat by \p delay. Note that because of the circular shift, - * the delay should be between 0 and \p puncsize, but this is - * not enforced; the effective delay will simply be \p delay mod - * \p puncsize. A negative value here is ignored. + * \param puncsize Size of block of bits to puncture + * \param puncpat The puncturing pattern + * \param delay Delayed the puncturing pattern by shifting it + * \param symbol The symbol to reinsert into the stream (def=127) */ - class FEC_API depuncture_bb : virtual public block - { - public: - // gr::fec::depuncture_bb::sptr - typedef boost::shared_ptr<depuncture_bb> sptr; - - /*! - * \brief Constructs a depuncture block. - * - * \param puncsize Size of block of bits to puncture - * \param puncpat The puncturing pattern - * \param delay Delayed the puncturing pattern by shifting it - * \param symbol The symbol to reinsert into the stream (def=127) - */ - static sptr make(int puncsize, int puncpat, - int delay=0, char symbol=127); - }; + static sptr make(int puncsize, int puncpat, int delay = 0, char symbol = 127); +}; - } /* namespace fec */ +} /* namespace fec */ } /* namespace gr */ #endif /* INCLUDED_FEC_DEPUNCTURE_BB_H */ diff --git a/gr-fec/include/gnuradio/fec/dummy_decoder.h b/gr-fec/include/gnuradio/fec/dummy_decoder.h index 0561803ea1..f23af94460 100644 --- a/gr-fec/include/gnuradio/fec/dummy_decoder.h +++ b/gr-fec/include/gnuradio/fec/dummy_decoder.h @@ -29,49 +29,47 @@ #include <string> namespace gr { - namespace fec { - namespace code { +namespace fec { +namespace code { - /*! - * \brief Dummy Decoding class. - * \ingroup error_coding_blk - * - * \details - * A dummy decoder class that simply passes the input to the - * output. It is meant to allow us to easily use the FEC API - * encoder and decoder blocks in an application with no coding. - */ - class FEC_API dummy_decoder : virtual public generic_decoder - { - public: - - /*! - * Build a dummy decoding FEC API object. - * - * \param frame_size Number of bits per frame. If using in the - * tagged stream style, this is the maximum allowable - * number of bits per frame. - */ - static generic_decoder::sptr make(int frame_size); - - /*! - * Sets the uncoded frame size to \p frame_size. If \p - * frame_size is greater than the value given to the - * constructor, the frame size will be capped by that initial - * value and this function will return false. Otherwise, it - * returns true. - */ - virtual bool set_frame_size(unsigned int frame_size) = 0; +/*! + * \brief Dummy Decoding class. + * \ingroup error_coding_blk + * + * \details + * A dummy decoder class that simply passes the input to the + * output. It is meant to allow us to easily use the FEC API + * encoder and decoder blocks in an application with no coding. + */ +class FEC_API dummy_decoder : virtual public generic_decoder +{ +public: + /*! + * Build a dummy decoding FEC API object. + * + * \param frame_size Number of bits per frame. If using in the + * tagged stream style, this is the maximum allowable + * number of bits per frame. + */ + static generic_decoder::sptr make(int frame_size); - /*! - * Returns the coding rate of this encoder (it will always be 1). - */ - virtual double rate() = 0; + /*! + * Sets the uncoded frame size to \p frame_size. If \p + * frame_size is greater than the value given to the + * constructor, the frame size will be capped by that initial + * value and this function will return false. Otherwise, it + * returns true. + */ + virtual bool set_frame_size(unsigned int frame_size) = 0; - }; + /*! + * Returns the coding rate of this encoder (it will always be 1). + */ + virtual double rate() = 0; +}; - } /* namespace code */ - } /* namespace fec */ +} /* namespace code */ +} /* namespace fec */ } /* namespace gr */ #endif /* INCLUDED_FEC_DUMMY_DECODER_H */ diff --git a/gr-fec/include/gnuradio/fec/dummy_encoder.h b/gr-fec/include/gnuradio/fec/dummy_encoder.h index b0aa704c8b..a158ae4dc3 100644 --- a/gr-fec/include/gnuradio/fec/dummy_encoder.h +++ b/gr-fec/include/gnuradio/fec/dummy_encoder.h @@ -29,61 +29,60 @@ #include <string> namespace gr { - namespace fec { - namespace code { +namespace fec { +namespace code { - /*! - * \brief Dummy Encoding class. - * \ingroup error_coding_blk - * - * \details - * A dummy encoder class that simply passes the input to the - * output. It is meant to allow us to easily use the FEC API - * encoder and decoder blocks in an application with no coding. - */ - class FEC_API dummy_encoder : virtual public generic_encoder - { - public: - - /*! - * Build a dummy encoding FEC API object. - * - * \param frame_size Number of bits per frame. If using in the - * tagged stream style, this is the maximum allowable - * number of bits per frame. - * \param pack Determines how to handle the input data stream - * as packed or unpacked bits. If set to True, the - * encoder's get_input_conversion will be set to - * 'pack', meaning that the data must be packed before - * being sent to this encoder. Generally handled - * through an extended encoder interface. - * \param packed_bits Determines how the output data stream is - * handled. If set to True, the encoder's - * get_output_conversion returns 'packed_bits', meaning - * that the output data of the encoder is packed and - * should be unpacked. Generally handled through an - * extended encoder interface. - */ - static generic_encoder::sptr make(int frame_size, bool pack = false, - bool packed_bits = false); +/*! + * \brief Dummy Encoding class. + * \ingroup error_coding_blk + * + * \details + * A dummy encoder class that simply passes the input to the + * output. It is meant to allow us to easily use the FEC API + * encoder and decoder blocks in an application with no coding. + */ +class FEC_API dummy_encoder : virtual public generic_encoder +{ +public: + /*! + * Build a dummy encoding FEC API object. + * + * \param frame_size Number of bits per frame. If using in the + * tagged stream style, this is the maximum allowable + * number of bits per frame. + * \param pack Determines how to handle the input data stream + * as packed or unpacked bits. If set to True, the + * encoder's get_input_conversion will be set to + * 'pack', meaning that the data must be packed before + * being sent to this encoder. Generally handled + * through an extended encoder interface. + * \param packed_bits Determines how the output data stream is + * handled. If set to True, the encoder's + * get_output_conversion returns 'packed_bits', meaning + * that the output data of the encoder is packed and + * should be unpacked. Generally handled through an + * extended encoder interface. + */ + static generic_encoder::sptr + make(int frame_size, bool pack = false, bool packed_bits = false); - /*! - * Sets the uncoded frame size to \p frame_size. If \p - * frame_size is greater than the value given to the - * constructor, the frame size will be capped by that initial - * value and this function will return false. Otherwise, it - * returns true. - */ - virtual bool set_frame_size(unsigned int frame_size) = 0; + /*! + * Sets the uncoded frame size to \p frame_size. If \p + * frame_size is greater than the value given to the + * constructor, the frame size will be capped by that initial + * value and this function will return false. Otherwise, it + * returns true. + */ + virtual bool set_frame_size(unsigned int frame_size) = 0; - /*! - * Returns the coding rate of this encoder (it will always be 1). - */ - virtual double rate() = 0; - }; + /*! + * Returns the coding rate of this encoder (it will always be 1). + */ + virtual double rate() = 0; +}; - } /* namespace code */ - } /* namespace fec */ +} /* namespace code */ +} /* namespace fec */ } /* namespace gr */ #endif /* INCLUDED_FEC_DUMMY_ENCODER_H */ diff --git a/gr-fec/include/gnuradio/fec/encode_ccsds_27_bb.h b/gr-fec/include/gnuradio/fec/encode_ccsds_27_bb.h index e1772cd2fe..e38969eae6 100644 --- a/gr-fec/include/gnuradio/fec/encode_ccsds_27_bb.h +++ b/gr-fec/include/gnuradio/fec/encode_ccsds_27_bb.h @@ -27,36 +27,35 @@ #include <gnuradio/sync_interpolator.h> namespace gr { - namespace fec { - - /*! \brief A rate 1/2, k=7 convolutional encoder for the CCSDS standard - * \ingroup error_coding_blk - * - * \details - * This block performs convolutional encoding using the CCSDS standard - * polynomial ("Voyager"). - * - * The input is an MSB first packed stream of bits. - * - * The output is a stream of symbols 0 or 1 representing the encoded data. - * - * As a rate 1/2 code, there will be 16 output symbols for every input byte. - * - * This block is designed for continuous data streaming, not packetized data. - * There is no provision to "flush" the encoder. - */ - - class FEC_API encode_ccsds_27_bb : virtual public sync_interpolator - { - public: - - // gr::fec::encode_ccsds_27_bb::sptr - typedef boost::shared_ptr<encode_ccsds_27_bb> sptr; - - static sptr make(); - }; - - } /* namespace fec */ +namespace fec { + +/*! \brief A rate 1/2, k=7 convolutional encoder for the CCSDS standard + * \ingroup error_coding_blk + * + * \details + * This block performs convolutional encoding using the CCSDS standard + * polynomial ("Voyager"). + * + * The input is an MSB first packed stream of bits. + * + * The output is a stream of symbols 0 or 1 representing the encoded data. + * + * As a rate 1/2 code, there will be 16 output symbols for every input byte. + * + * This block is designed for continuous data streaming, not packetized data. + * There is no provision to "flush" the encoder. + */ + +class FEC_API encode_ccsds_27_bb : virtual public sync_interpolator +{ +public: + // gr::fec::encode_ccsds_27_bb::sptr + typedef boost::shared_ptr<encode_ccsds_27_bb> sptr; + + static sptr make(); +}; + +} /* namespace fec */ } /* namespace gr */ #endif /* INCLUDED_FEC_ENCODE_CCSDS_27_BB_H */ diff --git a/gr-fec/include/gnuradio/fec/encoder.h b/gr-fec/include/gnuradio/fec/encoder.h index fae4bdfdda..084e4ff450 100644 --- a/gr-fec/include/gnuradio/fec/encoder.h +++ b/gr-fec/include/gnuradio/fec/encoder.h @@ -29,48 +29,47 @@ #include <boost/shared_ptr.hpp> namespace gr { - namespace fec { +namespace fec { + +/*! + * \brief Creates the encoder block for use in GNU Radio + * flowgraphs from a given FECAPI object derived from the + * generic_encoder class. + * \ingroup error_coding_blk + * + * \details + * + * Generally, we would use the fec.extended_encoder Python + * implementation to instantiate this. The extended_encoder wraps + * up a few more details, like taking care of puncturing as well + * as the encoder itself. + */ +class FEC_API encoder : virtual public block +{ +public: + typedef boost::shared_ptr<encoder> sptr; /*! - * \brief Creates the encoder block for use in GNU Radio - * flowgraphs from a given FECAPI object derived from the - * generic_encoder class. - * \ingroup error_coding_blk - * - * \details + * Build the FEC encoder block from an FECAPI encoder object. * - * Generally, we would use the fec.extended_encoder Python - * implementation to instantiate this. The extended_encoder wraps - * up a few more details, like taking care of puncturing as well - * as the encoder itself. + * \param my_encoder An FECAPI encoder object child of the generic_encoder class. + * \param input_item_size size of a block of data for the encoder. + * \param output_item_size size of a block of data the encoder will produce. */ - class FEC_API encoder : virtual public block - { - public: - typedef boost::shared_ptr<encoder> sptr; - - /*! - * Build the FEC encoder block from an FECAPI encoder object. - * - * \param my_encoder An FECAPI encoder object child of the generic_encoder class. - * \param input_item_size size of a block of data for the encoder. - * \param output_item_size size of a block of data the encoder will produce. - */ - static sptr make(generic_encoder::sptr my_encoder, - size_t input_item_size, - size_t output_item_size); + static sptr make(generic_encoder::sptr my_encoder, + size_t input_item_size, + size_t output_item_size); - virtual int general_work(int noutput_items, - gr_vector_int& ninput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) = 0; - virtual int fixed_rate_ninput_to_noutput(int ninput) = 0; - virtual int fixed_rate_noutput_to_ninput(int noutput) = 0; - virtual void forecast(int noutput_items, - gr_vector_int& ninput_items_required) = 0; - }; + virtual int general_work(int noutput_items, + gr_vector_int& ninput_items, + gr_vector_const_void_star& input_items, + gr_vector_void_star& output_items) = 0; + virtual int fixed_rate_ninput_to_noutput(int ninput) = 0; + virtual int fixed_rate_noutput_to_ninput(int noutput) = 0; + virtual void forecast(int noutput_items, gr_vector_int& ninput_items_required) = 0; +}; - } /* namespace fec */ +} /* namespace fec */ } /* namespace gr */ #endif /* INCLUDED_FEC_ENCODER_H */ diff --git a/gr-fec/include/gnuradio/fec/fec_mtrx.h b/gr-fec/include/gnuradio/fec/fec_mtrx.h index 1dcee6547a..8aa2ee699a 100644 --- a/gr-fec/include/gnuradio/fec/fec_mtrx.h +++ b/gr-fec/include/gnuradio/fec/fec_mtrx.h @@ -26,140 +26,138 @@ #include <boost/shared_ptr.hpp> namespace gr { - namespace fec { - namespace code { - - typedef struct - { - size_t size; - double *data; - } block_data; - - typedef struct - { - size_t size1; - size_t size2; - size_t tda; - double * data; - block_data * block; - int owner; - } matrix; - - FEC_API void matrix_free(matrix *x); - - typedef boost::shared_ptr<matrix> matrix_sptr; - - class fec_mtrx; - typedef boost::shared_ptr<fec_mtrx> fec_mtrx_sptr; - - /*! - * \brief Read in an alist file and produce the matrix object. - * - * \details - * Takes in a an alist file (the file name as a string) and creates - * the corresponding matrix. The format of alist files is described - * at: http://www.inference.phy.cam.ac.uk/mackay/codes/alist.html - * - * The result is returned as a matrix shared pointer. - * - * \param filename Name of an alist file to use. The alist - * format is described at: - * http://www.inference.phy.cam.ac.uk/mackay/codes/alist.html - */ - FEC_API matrix_sptr read_matrix_from_file(const std::string filename); - FEC_API void write_matrix_to_file(const std::string filename, matrix_sptr M); - - /*! - * \brief Takes a parity check matrix (H) and returns the - * transpose of the generator matrix (G). - * - * The result is returned as a matrix shared pointer. The form - * of this matrix is [I_k | P]^T, where P is the parity check - * matrix. It is a n x k matrix where k is the information - * length and n is the codeword length. - * - * \param H_obj A parity check matrix; generally derived from - * using read_matrix_from_file with a given alist - * file format. - */ - FEC_API matrix_sptr generate_G_transpose(matrix_sptr H_obj); - - /*! - * \brief Takes a parity check matrix (H) and returns the - * generator matrix (G). - * - * The result is returned as a matrix shared pointer. The form - * of this matrix is [I_k | P], where P is the parity check - * matrix. It is a k x n matrix where k is the information - * length and n is the codeword length. - * - * \param H_obj A parity check matrix; generally derived from - * using read_matrix_from_file with a given alist - * file format. - */ - FEC_API matrix_sptr generate_G(matrix_sptr H_obj); - - /*! - * \brief Takes a generator matrix (G) and returns the - * parity check matrix (H). - * - * \param G_obj A parity check matrix; generally derived from - * using read_matrix_from_file with a given alist - * file format. - */ - FEC_API matrix_sptr generate_H(matrix_sptr G_obj); - - /*! - * \brief Takes a matrix and prints it to screen. - * - * \param M a matrix_sptr; generally a G or H matrix for LDPC codes. - * \param numpy will output in a format that can be - * copy-and-pasted directly into a numpy.matrix(~) call - * in Python. - */ - FEC_API void print_matrix(const matrix_sptr M, bool numpy=false); - - /*! - * \brief Base class for FEC matrix objects. - * - * \ingroup error_coding_blk - * - * \details - * - * Base class of ldpc_H_matrix and ldpc_G_matrix classes. The - * child objects can be either generator matrices or parity - * check matrices. This base class can be provided to the - * decoder ldpc_bit_flip_decoder, whereas the encoder classes - * ldpc_gen_mtrx_encoder and ldpc_encoder will not accept this - * base class; they require one of the child classes. - */ - class FEC_API fec_mtrx - { - protected: - fec_mtrx(void) {} // allows pure virtual interface sub-classes - - public: - virtual ~fec_mtrx() {} - - //! Encode \p inbuffer with LDPC H matrix into \p outbuffer. - virtual void encode(unsigned char *outbuffer, - const unsigned char *inbuffer) const = 0; - - //! Decode \p inbuffer with LDPC H matrix into \p outbuffer. - virtual void decode(unsigned char *outbuffer, - const float *inbuffer, - unsigned int frame_size, - unsigned int max_iterations) const = 0; - - //!Get the codeword length n - virtual unsigned int n() const = 0; - - //! Get the information word length k - virtual unsigned int k() const = 0; - }; - - } /* namespace code */ - } /* namespace fec */ +namespace fec { +namespace code { + +typedef struct { + size_t size; + double* data; +} block_data; + +typedef struct { + size_t size1; + size_t size2; + size_t tda; + double* data; + block_data* block; + int owner; +} matrix; + +FEC_API void matrix_free(matrix* x); + +typedef boost::shared_ptr<matrix> matrix_sptr; + +class fec_mtrx; +typedef boost::shared_ptr<fec_mtrx> fec_mtrx_sptr; + +/*! + * \brief Read in an alist file and produce the matrix object. + * + * \details + * Takes in a an alist file (the file name as a string) and creates + * the corresponding matrix. The format of alist files is described + * at: http://www.inference.phy.cam.ac.uk/mackay/codes/alist.html + * + * The result is returned as a matrix shared pointer. + * + * \param filename Name of an alist file to use. The alist + * format is described at: + * http://www.inference.phy.cam.ac.uk/mackay/codes/alist.html + */ +FEC_API matrix_sptr read_matrix_from_file(const std::string filename); +FEC_API void write_matrix_to_file(const std::string filename, matrix_sptr M); + +/*! + * \brief Takes a parity check matrix (H) and returns the + * transpose of the generator matrix (G). + * + * The result is returned as a matrix shared pointer. The form + * of this matrix is [I_k | P]^T, where P is the parity check + * matrix. It is a n x k matrix where k is the information + * length and n is the codeword length. + * + * \param H_obj A parity check matrix; generally derived from + * using read_matrix_from_file with a given alist + * file format. + */ +FEC_API matrix_sptr generate_G_transpose(matrix_sptr H_obj); + +/*! + * \brief Takes a parity check matrix (H) and returns the + * generator matrix (G). + * + * The result is returned as a matrix shared pointer. The form + * of this matrix is [I_k | P], where P is the parity check + * matrix. It is a k x n matrix where k is the information + * length and n is the codeword length. + * + * \param H_obj A parity check matrix; generally derived from + * using read_matrix_from_file with a given alist + * file format. + */ +FEC_API matrix_sptr generate_G(matrix_sptr H_obj); + +/*! + * \brief Takes a generator matrix (G) and returns the + * parity check matrix (H). + * + * \param G_obj A parity check matrix; generally derived from + * using read_matrix_from_file with a given alist + * file format. + */ +FEC_API matrix_sptr generate_H(matrix_sptr G_obj); + +/*! + * \brief Takes a matrix and prints it to screen. + * + * \param M a matrix_sptr; generally a G or H matrix for LDPC codes. + * \param numpy will output in a format that can be + * copy-and-pasted directly into a numpy.matrix(~) call + * in Python. + */ +FEC_API void print_matrix(const matrix_sptr M, bool numpy = false); + +/*! + * \brief Base class for FEC matrix objects. + * + * \ingroup error_coding_blk + * + * \details + * + * Base class of ldpc_H_matrix and ldpc_G_matrix classes. The + * child objects can be either generator matrices or parity + * check matrices. This base class can be provided to the + * decoder ldpc_bit_flip_decoder, whereas the encoder classes + * ldpc_gen_mtrx_encoder and ldpc_encoder will not accept this + * base class; they require one of the child classes. + */ +class FEC_API fec_mtrx +{ +protected: + fec_mtrx(void) {} // allows pure virtual interface sub-classes + +public: + virtual ~fec_mtrx() {} + + //! Encode \p inbuffer with LDPC H matrix into \p outbuffer. + virtual void encode(unsigned char* outbuffer, + const unsigned char* inbuffer) const = 0; + + //! Decode \p inbuffer with LDPC H matrix into \p outbuffer. + virtual void decode(unsigned char* outbuffer, + const float* inbuffer, + unsigned int frame_size, + unsigned int max_iterations) const = 0; + + //! Get the codeword length n + virtual unsigned int n() const = 0; + + //! Get the information word length k + virtual unsigned int k() const = 0; +}; + +} /* namespace code */ +} /* namespace fec */ } /* namespace gr */ #endif /* INCLUDED_fec_mtrx_H */ diff --git a/gr-fec/include/gnuradio/fec/generic_decoder.h b/gr-fec/include/gnuradio/fec/generic_decoder.h index bfce85a8c1..9356c85ce4 100644 --- a/gr-fec/include/gnuradio/fec/generic_decoder.h +++ b/gr-fec/include/gnuradio/fec/generic_decoder.h @@ -29,223 +29,223 @@ #include <boost/format.hpp> namespace gr { - namespace fec { +namespace fec { + +/*! + * \brief Parent class for FECAPI objects. + * + * \ingroup error_coding_blk + * + * \details + * + * Parent of a decoder variable class for FECAPI that will fit + * into the gr::fec::decoder block to handle FEC decoding. This + * class provides the basic information required to fit into the + * FECAPI structure. It provides information about input and + * output data types, potential data conversions, and a few other + * parameters useful to establish the decoder's behavior. + * + * We create objects from FECAPI-derived classes to go into the + * actual GNU Radio decoder block. Each object contains its own + * state and so there should be a one-to-one mapping of an FECAPI + * object and a GR decoder block. Sharing these objects is not + * guaranteed to be thread-safe. + * + * This is a pure virtual class and must be derived from by a + * child class. + * + * \sa gr::fec::code::cc_decoder + * \sa gr::fec::code::ccsds_decoder + */ +class FEC_API generic_decoder +{ +protected: + gr::logger_ptr d_logger; + +public: + friend class decoder; + virtual void generic_work(void* inbuffer, void* outbuffer) = 0; + static int base_unique_id; + int my_id; + int unique_id(); + std::string d_name; + std::string alias() { return (boost::format("%s%d") % d_name % unique_id()).str(); } + +public: + typedef boost::shared_ptr<generic_decoder> sptr; + + generic_decoder(void){}; + generic_decoder(std::string name); + virtual ~generic_decoder(); + + /*! + * Returns the rate of the code. For every r input bits, there + * is 1 output bit, so the rate is 1/r. Used for setting things + * like the encoder block's relative rate. + * + * This function MUST be reimplemented by the child class. + */ + virtual double rate() = 0; + + /*! + * Returns the input size in items that the decoder object uses + * to decode a full frame. Often, this number is the number of + * bits per frame if the input format is unpacked. If the block + * expects packed bytes, then this value should be the number of + * bytes (number of bits / 8) per input frame. + * + * The child class MUST implement this function. + */ + virtual int get_input_size() = 0; /*! - * \brief Parent class for FECAPI objects. + * Returns the output size in items that the decoder object + * produces after decoding a full frame. Often, this number is + * the number of bits in the outputted frame if the input format + * is unpacked. If the block produces packed bytes, then this + * value should be the number of bytes (number of bits / 8) per + * frame produced. This value is generally something like + * get_input_size()/R for a 1/R rate code. * - * \ingroup error_coding_blk + * The child class MUST implement this function. + */ + virtual int get_output_size() = 0; + + /*! + * Sets up history for the decoder when the decoder is required + * to look ahead in the data stream in order to finish + * its processing. * - * \details + * The child class MAY implement this function. If not + * reimplemented, it returns 0. + */ + virtual int get_history(); + + /*! + * Some decoders require the input items to float around a + * particular soft value. We can set that floating value by + * setting this value to return some non-zero number. * - * Parent of a decoder variable class for FECAPI that will fit - * into the gr::fec::decoder block to handle FEC decoding. This - * class provides the basic information required to fit into the - * FECAPI structure. It provides information about input and - * output data types, potential data conversions, and a few other - * parameters useful to establish the decoder's behavior. + * The fec.extended_decoder block will use this to create an + * add_const_ff block before the decoder block to adjust all + * input samples appropriately. * - * We create objects from FECAPI-derived classes to go into the - * actual GNU Radio decoder block. Each object contains its own - * state and so there should be a one-to-one mapping of an FECAPI - * object and a GR decoder block. Sharing these objects is not - * guaranteed to be thread-safe. + * The child class MAY implement this function. If not + * reimplemented, it returns 0. + */ + virtual float get_shift(); + + /*! + * Sets the size of an input item, as in the size of a char or + * float item. * - * This is a pure virtual class and must be derived from by a - * child class. + * The child class SHOULD implement this function. If not + * reimplemented, it returns sizeof(float) as the decoders + * typically expect floating point input types. + */ + virtual int get_input_item_size(); + + /*! + * Sets the size of an output item, as in the size of a char or + * float item. * - * \sa gr::fec::code::cc_decoder - * \sa gr::fec::code::ccsds_decoder + * The child class SHOULD implement this function. If not + * reimplemented, it returns sizeof(char) as the decoders + * typically expect to produce bits or bytes. */ - class FEC_API generic_decoder - { - protected: - gr::logger_ptr d_logger; - - public: - friend class decoder; - virtual void generic_work(void *inbuffer, void *outbuffer) = 0; - static int base_unique_id; - int my_id; - int unique_id(); - std::string d_name; - std::string alias(){ return (boost::format("%s%d")%d_name%unique_id()).str(); } - - public: - typedef boost::shared_ptr<generic_decoder> sptr; - - generic_decoder(void) {}; - generic_decoder(std::string name); - virtual ~generic_decoder(); - - /*! - * Returns the rate of the code. For every r input bits, there - * is 1 output bit, so the rate is 1/r. Used for setting things - * like the encoder block's relative rate. - * - * This function MUST be reimplemented by the child class. - */ - virtual double rate() = 0; - - /*! - * Returns the input size in items that the decoder object uses - * to decode a full frame. Often, this number is the number of - * bits per frame if the input format is unpacked. If the block - * expects packed bytes, then this value should be the number of - * bytes (number of bits / 8) per input frame. - * - * The child class MUST implement this function. - */ - virtual int get_input_size() = 0; - - /*! - * Returns the output size in items that the decoder object - * produces after decoding a full frame. Often, this number is - * the number of bits in the outputted frame if the input format - * is unpacked. If the block produces packed bytes, then this - * value should be the number of bytes (number of bits / 8) per - * frame produced. This value is generally something like - * get_input_size()/R for a 1/R rate code. - * - * The child class MUST implement this function. - */ - virtual int get_output_size() = 0; - - /*! - * Sets up history for the decoder when the decoder is required - * to look ahead in the data stream in order to finish - * its processing. - * - * The child class MAY implement this function. If not - * reimplemented, it returns 0. - */ - virtual int get_history(); - - /*! - * Some decoders require the input items to float around a - * particular soft value. We can set that floating value by - * setting this value to return some non-zero number. - * - * The fec.extended_decoder block will use this to create an - * add_const_ff block before the decoder block to adjust all - * input samples appropriately. - * - * The child class MAY implement this function. If not - * reimplemented, it returns 0. - */ - virtual float get_shift(); - - /*! - * Sets the size of an input item, as in the size of a char or - * float item. - * - * The child class SHOULD implement this function. If not - * reimplemented, it returns sizeof(float) as the decoders - * typically expect floating point input types. - */ - virtual int get_input_item_size(); - - /*! - * Sets the size of an output item, as in the size of a char or - * float item. - * - * The child class SHOULD implement this function. If not - * reimplemented, it returns sizeof(char) as the decoders - * typically expect to produce bits or bytes. - */ - virtual int get_output_item_size(); - - /*! - * Set up a conversion type required to setup the data properly - * for this decoder. The decoder itself will not implement the - * conversion and expects an external wrapper (e.g., - * fec.extended_decoder) to read this value and "do the right - * thing" to format the data. - * - * The default behavior is 'none', which means no conversion is - * required. Whatever the get_input_item_size() value returns, - * the input is expected to conform directly to this. - * - * This may also return 'uchar', which indicates that the - * wrapper should convert the standard float samples to unsigned - * characters, either hard sliced or 8-bit soft symbols. See - * gr::fec::code::cc_decoder as an example decoder that uses - * this conversion format. - * - * If 'packed_bits', the block expects the inputs to be packed - * hard bits. Each input item is a unsigned char where each of - * the 8-bits is a hard bit value. - * - * The child class SHOULD implement this function. If not - * reimplemented, it returns "none". - */ - virtual const char* get_input_conversion(); - - /*! - * Set up a conversion type required to understand the output - * style of this decoder. Generally, follow-on processing - * expects unpacked bits, so we specify the conversion type here - * to indicate what the wrapper (e.g., fec.extended_decoder) - * should do to convert the output samples from the decoder into - * unpacked bits. - * - * The default behavior is 'none', which means no conversion is - * required. This should mean that the output data is produced - * from this decoder as unpacked bit. - * - * If 'unpack', the block produces packed bytes that should be - * unpacked by the wrapper. See gr::fec::code::ccsds_decoder as - * an example of a decoder that produces packed bytes. - * - * The child class SHOULD implement this function. If not - * reimplemented, it returns "none". - */ - virtual const char* get_output_conversion(); - - /*! - * Updates the size of a decoded frame. - * - * The child class MUST implement this function and interpret - * how the \p frame_size information affects the block's - * 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() */ - FEC_API int get_decoder_output_size(generic_decoder::sptr my_decoder); - - /*! see generic_decoder::get_input_size() */ - FEC_API int get_decoder_input_size(generic_decoder::sptr my_decoder); - - /*! see generic_decoder::get_shift() */ - FEC_API float get_shift(generic_decoder::sptr my_decoder); - - /*! see generic_decoder::get_history() */ - FEC_API int get_history(generic_decoder::sptr my_decoder); - - /*! see generic_decoder::get_input_item_size() */ - FEC_API int get_decoder_input_item_size(generic_decoder::sptr my_decoder); - - /*! see generic_decoder::get_output_item_size() */ - FEC_API int get_decoder_output_item_size(generic_decoder::sptr my_decoder); - - /*! see generic_decoder::get_input_conversion() */ - FEC_API const char* get_decoder_input_conversion(generic_decoder::sptr my_decoder); - - /*! see generic_decoder::get_output_conversion() */ - FEC_API const char* get_decoder_output_conversion(generic_decoder::sptr my_decoder); - - } /* namespace fec */ + virtual int get_output_item_size(); + + /*! + * Set up a conversion type required to setup the data properly + * for this decoder. The decoder itself will not implement the + * conversion and expects an external wrapper (e.g., + * fec.extended_decoder) to read this value and "do the right + * thing" to format the data. + * + * The default behavior is 'none', which means no conversion is + * required. Whatever the get_input_item_size() value returns, + * the input is expected to conform directly to this. + * + * This may also return 'uchar', which indicates that the + * wrapper should convert the standard float samples to unsigned + * characters, either hard sliced or 8-bit soft symbols. See + * gr::fec::code::cc_decoder as an example decoder that uses + * this conversion format. + * + * If 'packed_bits', the block expects the inputs to be packed + * hard bits. Each input item is a unsigned char where each of + * the 8-bits is a hard bit value. + * + * The child class SHOULD implement this function. If not + * reimplemented, it returns "none". + */ + virtual const char* get_input_conversion(); + + /*! + * Set up a conversion type required to understand the output + * style of this decoder. Generally, follow-on processing + * expects unpacked bits, so we specify the conversion type here + * to indicate what the wrapper (e.g., fec.extended_decoder) + * should do to convert the output samples from the decoder into + * unpacked bits. + * + * The default behavior is 'none', which means no conversion is + * required. This should mean that the output data is produced + * from this decoder as unpacked bit. + * + * If 'unpack', the block produces packed bytes that should be + * unpacked by the wrapper. See gr::fec::code::ccsds_decoder as + * an example of a decoder that produces packed bytes. + * + * The child class SHOULD implement this function. If not + * reimplemented, it returns "none". + */ + virtual const char* get_output_conversion(); + + /*! + * Updates the size of a decoded frame. + * + * The child class MUST implement this function and interpret + * how the \p frame_size information affects the block's + * 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() */ +FEC_API int get_decoder_output_size(generic_decoder::sptr my_decoder); + +/*! see generic_decoder::get_input_size() */ +FEC_API int get_decoder_input_size(generic_decoder::sptr my_decoder); + +/*! see generic_decoder::get_shift() */ +FEC_API float get_shift(generic_decoder::sptr my_decoder); + +/*! see generic_decoder::get_history() */ +FEC_API int get_history(generic_decoder::sptr my_decoder); + +/*! see generic_decoder::get_input_item_size() */ +FEC_API int get_decoder_input_item_size(generic_decoder::sptr my_decoder); + +/*! see generic_decoder::get_output_item_size() */ +FEC_API int get_decoder_output_item_size(generic_decoder::sptr my_decoder); + +/*! see generic_decoder::get_input_conversion() */ +FEC_API const char* get_decoder_input_conversion(generic_decoder::sptr my_decoder); + +/*! see generic_decoder::get_output_conversion() */ +FEC_API const char* get_decoder_output_conversion(generic_decoder::sptr my_decoder); + +} /* namespace fec */ } /* namespace gr */ #endif /* INCLUDED_FEC_GENRIC_DECODER_H */ diff --git a/gr-fec/include/gnuradio/fec/generic_encoder.h b/gr-fec/include/gnuradio/fec/generic_encoder.h index 7c5e08e5d0..597839eac3 100644 --- a/gr-fec/include/gnuradio/fec/generic_encoder.h +++ b/gr-fec/include/gnuradio/fec/generic_encoder.h @@ -29,124 +29,124 @@ #include <boost/shared_ptr.hpp> namespace gr { - namespace fec { - - class FEC_API generic_encoder - { - protected: - gr::logger_ptr d_logger; - - public: - friend class encoder; - virtual void generic_work(void *in_buffer, void *out_buffer) = 0; - static int base_unique_id; - int my_id; - int unique_id(); - std::string d_name; - std::string alias(){ return (boost::format("%s%d")%d_name%unique_id()).str(); } - - public: - typedef boost::shared_ptr<generic_encoder> sptr; - - /*! - * Returns the rate of the code. For every 1 input bit, there - * are r output bits, so the rate is 1/r. Used for setting - * things like the encoder block's relative rate. - * - * This function MUST be reimplemented by the child class. - */ - virtual double rate() = 0; - - /*! - * Returns the input size in items that the encoder object uses - * to encode a full frame. Often, this number is the number of - * bits per frame if the input format is unpacked. If the block - * expects packed bytes, then this value should be the number of - * bytes (number of bits / 8) per input frame. - * - * The child class MUST implement this function. - */ - virtual int get_input_size() = 0; - - /*! - * Returns the output size in items that the encoder object - * produces after encoding a full frame. Often, this number is - * the number of bits in the outputted frame if the input format - * is unpacked. If the block produces packed bytes, then this - * value should be the number of bytes (number of bits / 8) per - * frame produced. This value is generally something like - * R*get_input_size() for a 1/R rate code. - * - * The child class MUST implement this function. - */ - virtual int get_output_size() = 0; - - /*! - * Set up a conversion type required to setup the data properly - * for this encoder. The encoder itself will not implement the - * conversion and expects an external wrapper (e.g., - * fec.extended_encoder) to read this value and "do the right - * thing" to format the data. - * - * The default behavior is 'none', which means no conversion is - * required. Whatever the get_input_item_size() value returns, - * the input is expected to conform directly to this. Generally, - * this means unpacked bytes. - * - * If 'pack', the block expects the inputs to be packed - * bytes. The wrapper should implement a - * gr::blocks::pack_k_bits_bb(8) block for this. - * - * The child class MAY implement this function. If not - * reimplemented, it returns "none". - */ - virtual const char* get_input_conversion(); - - /*! - * Set up a conversion type required to understand the output - * style of this encoder. Generally an encoder will produce - * unpacked bytes with a bit set in the LSB. - * - * The default behavior is 'none', which means no conversion is - * required and the encoder produces unpacked bytes. - * - * If 'packed_bits', the block produces packed bits and the - * wrapper should unpack these (using, for instance, - * gr::block::unpack_k_bits_bb(8)). - * - * The child class MAY implement this function. If not - * reimplemented, it returns "none". - */ - virtual const char* get_output_conversion(); - - /*! - * Updates the size of the frame to encode. - * - * The child class MUST implement this function and interpret - * how the \p frame_size information affects the block's - * behavior. It should also provide bounds checks. - */ - virtual bool set_frame_size(unsigned int frame_size) = 0; - - generic_encoder(void) {}; - generic_encoder(std::string name); - virtual ~generic_encoder(); - }; - - /*! see generic_encoder::get_output_size() */ - FEC_API int get_encoder_output_size(generic_encoder::sptr my_encoder); - - /*! see generic_encoder::get_input_size() */ - FEC_API int get_encoder_input_size(generic_encoder::sptr my_encoder); - - /*! see generic_encoder::get_input_conversion() */ - FEC_API const char* get_encoder_input_conversion(generic_encoder::sptr my_encoder); - - /*! see generic_encoder::get_output_conversion() */ - FEC_API const char* get_encoder_output_conversion(generic_encoder::sptr my_encoder); - - - } /* namespace fec */ +namespace fec { + +class FEC_API generic_encoder +{ +protected: + gr::logger_ptr d_logger; + +public: + friend class encoder; + virtual void generic_work(void* in_buffer, void* out_buffer) = 0; + static int base_unique_id; + int my_id; + int unique_id(); + std::string d_name; + std::string alias() { return (boost::format("%s%d") % d_name % unique_id()).str(); } + +public: + typedef boost::shared_ptr<generic_encoder> sptr; + + /*! + * Returns the rate of the code. For every 1 input bit, there + * are r output bits, so the rate is 1/r. Used for setting + * things like the encoder block's relative rate. + * + * This function MUST be reimplemented by the child class. + */ + virtual double rate() = 0; + + /*! + * Returns the input size in items that the encoder object uses + * to encode a full frame. Often, this number is the number of + * bits per frame if the input format is unpacked. If the block + * expects packed bytes, then this value should be the number of + * bytes (number of bits / 8) per input frame. + * + * The child class MUST implement this function. + */ + virtual int get_input_size() = 0; + + /*! + * Returns the output size in items that the encoder object + * produces after encoding a full frame. Often, this number is + * the number of bits in the outputted frame if the input format + * is unpacked. If the block produces packed bytes, then this + * value should be the number of bytes (number of bits / 8) per + * frame produced. This value is generally something like + * R*get_input_size() for a 1/R rate code. + * + * The child class MUST implement this function. + */ + virtual int get_output_size() = 0; + + /*! + * Set up a conversion type required to setup the data properly + * for this encoder. The encoder itself will not implement the + * conversion and expects an external wrapper (e.g., + * fec.extended_encoder) to read this value and "do the right + * thing" to format the data. + * + * The default behavior is 'none', which means no conversion is + * required. Whatever the get_input_item_size() value returns, + * the input is expected to conform directly to this. Generally, + * this means unpacked bytes. + * + * If 'pack', the block expects the inputs to be packed + * bytes. The wrapper should implement a + * gr::blocks::pack_k_bits_bb(8) block for this. + * + * The child class MAY implement this function. If not + * reimplemented, it returns "none". + */ + virtual const char* get_input_conversion(); + + /*! + * Set up a conversion type required to understand the output + * style of this encoder. Generally an encoder will produce + * unpacked bytes with a bit set in the LSB. + * + * The default behavior is 'none', which means no conversion is + * required and the encoder produces unpacked bytes. + * + * If 'packed_bits', the block produces packed bits and the + * wrapper should unpack these (using, for instance, + * gr::block::unpack_k_bits_bb(8)). + * + * The child class MAY implement this function. If not + * reimplemented, it returns "none". + */ + virtual const char* get_output_conversion(); + + /*! + * Updates the size of the frame to encode. + * + * The child class MUST implement this function and interpret + * how the \p frame_size information affects the block's + * behavior. It should also provide bounds checks. + */ + virtual bool set_frame_size(unsigned int frame_size) = 0; + + generic_encoder(void){}; + generic_encoder(std::string name); + virtual ~generic_encoder(); +}; + +/*! see generic_encoder::get_output_size() */ +FEC_API int get_encoder_output_size(generic_encoder::sptr my_encoder); + +/*! see generic_encoder::get_input_size() */ +FEC_API int get_encoder_input_size(generic_encoder::sptr my_encoder); + +/*! see generic_encoder::get_input_conversion() */ +FEC_API const char* get_encoder_input_conversion(generic_encoder::sptr my_encoder); + +/*! see generic_encoder::get_output_conversion() */ +FEC_API const char* get_encoder_output_conversion(generic_encoder::sptr my_encoder); + + +} /* namespace fec */ } /* namespace gr */ #endif /* INCLUDED_FEC_GENERIC_ENCODER_H */ diff --git a/gr-fec/include/gnuradio/fec/gf2mat.h b/gr-fec/include/gnuradio/fec/gf2mat.h index 51aa310518..460d1bbc2f 100644 --- a/gr-fec/include/gnuradio/fec/gf2mat.h +++ b/gr-fec/include/gnuradio/fec/gf2mat.h @@ -29,7 +29,7 @@ class GF2Mat { //! The matrix H - std::vector < std::vector <char> > H; + std::vector<std::vector<char>> H; //! Number of rows in H int M; @@ -37,9 +37,9 @@ class GF2Mat //! Number of columns in H int N; - public: +public: //! Default constructor - GF2Mat() {}; + GF2Mat(){}; //! Construct an M x N matrix with all 0 entries GF2Mat(int m, int n); @@ -48,7 +48,7 @@ class GF2Mat GF2Mat(alist _list); //! Initializes the class from a 2-D vector X - GF2Mat(std::vector <std::vector <char> > X); + GF2Mat(std::vector<std::vector<char>> X); //! Returns the variable M int get_M(); @@ -90,7 +90,7 @@ class GF2Mat void add_rows(int i, int j); //! Returns the variable H - std::vector<std::vector<char> > get_H(); + std::vector<std::vector<char>> get_H(); /*! * \brief Obtains an equivalent representation of H for encoding @@ -105,8 +105,7 @@ class GF2Mat * \param p The column permutation during this operation. * \param rank The rank of the matrix. */ - GF2Mat get_G(std::vector<int> & p, int & rank); - + 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 index 15aa890271..5b9e7a5c94 100644 --- a/gr-fec/include/gnuradio/fec/gf2vec.h +++ b/gr-fec/include/gnuradio/fec/gf2vec.h @@ -28,45 +28,45 @@ class GF2Vec { private: - //! The vector vec - std::vector<char> vec; + //! The vector vec + std::vector<char> vec; - //! Resize the vector - void resize(int size); + //! Resize the vector + void resize(int size); public: - //! Default constructor - GF2Vec() {} + //! Default constructor + GF2Vec() {} - //! Constructs a vector of length "size" with all 0 entries - GF2Vec(int size); + //! Constructs a vector of length "size" with all 0 entries + GF2Vec(int size); - //! Returns the vector - std::vector<char> get_vec(); + //! Returns the vector + std::vector<char> get_vec(); - //! Returns the size of the vector - int size(); + //! Returns the size of the vector + int size(); - //! Resets the vector with the given input - void set_vec(const std::vector<char>); + //! Resets the vector with the given input + void set_vec(const std::vector<char>); - //! Access the ith element - char & operator [](int i); + //! Access the ith element + char& operator[](int i); - //! Overloading the operator '=' - void operator=(GF2Vec x); + //! Overloading the operator '=' + void operator=(GF2Vec x); - //! Obtain a subvector between the indices i to j - GF2Vec sub_vector(int i, int j); + //! 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 GF2Vec operator+(GF2Vec a, GF2Vec b); - //! Overloading the operator '*' - friend char operator*(GF2Vec a, GF2Vec b); + //! Overloading the operator '*' + friend char operator*(GF2Vec a, GF2Vec b); - //! Prints the vector - void print_vec(); + //! Prints the vector + void print_vec(); }; #endif // #ifndef GF2VEC_H diff --git a/gr-fec/include/gnuradio/fec/ldpc_G_matrix.h b/gr-fec/include/gnuradio/fec/ldpc_G_matrix.h index 36a598146d..95e8638bc5 100644 --- a/gr-fec/include/gnuradio/fec/ldpc_G_matrix.h +++ b/gr-fec/include/gnuradio/fec/ldpc_G_matrix.h @@ -27,73 +27,73 @@ #include <boost/enable_shared_from_this.hpp> namespace gr { - namespace fec { - namespace code { +namespace fec { +namespace code { - /*! - * \brief Class for storing H or G matrix - * \ingroup error_coding_blk - * - * \details - * This class stores a matrix variable, specifically - * either a: - * - * 1) Generator matrix, G, in the standard format G = [I P], - * where I is an identity matrix and P is the parity - * submatrix. - * - * or - * - * 2) Parity matrix, H, in the standard format H = [P' I], - * where P' is the transpose of the parity submatrix and I - * is an identity matrix. - * - * This variable can used by the ldpc_gen_mtrx_encoder and - * ldpc_bit_flip_decoder classes. - */ - class FEC_API ldpc_G_matrix : virtual public fec_mtrx, - public boost::enable_shared_from_this<ldpc_G_matrix> - { - public: - typedef boost::shared_ptr<ldpc_G_matrix> sptr; +/*! + * \brief Class for storing H or G matrix + * \ingroup error_coding_blk + * + * \details + * This class stores a matrix variable, specifically + * either a: + * + * 1) Generator matrix, G, in the standard format G = [I P], + * where I is an identity matrix and P is the parity + * submatrix. + * + * or + * + * 2) Parity matrix, H, in the standard format H = [P' I], + * where P' is the transpose of the parity submatrix and I + * is an identity matrix. + * + * This variable can used by the ldpc_gen_mtrx_encoder and + * ldpc_bit_flip_decoder classes. + */ +class FEC_API ldpc_G_matrix : virtual public fec_mtrx, + public boost::enable_shared_from_this<ldpc_G_matrix> +{ +public: + typedef boost::shared_ptr<ldpc_G_matrix> sptr; - /*! - * \brief Constructor given alist file - * \details - * 1. Reads in the matrix from an alist file - * 2. Determines if the matrix format is G=[I P] or H=[P' I] - * 3. Solves for G transpose (will be used during encoding) - * - * \param filename Name of an alist file to use. The alist - * format is described at: - * http://www.inference.phy.cam.ac.uk/mackay/codes/alist.html - */ - static sptr make(const std::string filename); + /*! + * \brief Constructor given alist file + * \details + * 1. Reads in the matrix from an alist file + * 2. Determines if the matrix format is G=[I P] or H=[P' I] + * 3. Solves for G transpose (will be used during encoding) + * + * \param filename Name of an alist file to use. The alist + * format is described at: + * http://www.inference.phy.cam.ac.uk/mackay/codes/alist.html + */ + static sptr make(const std::string filename); - //! Encode \p inbuffer with LDPC H matrix into \p outbuffer. - virtual void encode(unsigned char *outbuffer, - const unsigned char *inbuffer) const = 0; + //! Encode \p inbuffer with LDPC H matrix into \p outbuffer. + virtual void encode(unsigned char* outbuffer, + const unsigned char* inbuffer) const = 0; - //! Decode \p inbuffer with LDPC H matrix into \p outbuffer. - virtual void decode(unsigned char *outbuffer, - const float *inbuffer, - unsigned int frame_size, - unsigned int max_iterations) const = 0; + //! Decode \p inbuffer with LDPC H matrix into \p outbuffer. + virtual void decode(unsigned char* outbuffer, + const float* inbuffer, + unsigned int frame_size, + unsigned int max_iterations) const = 0; - /*! - * \brief A pointer to make SWIG work - * - * \details - * SWIG doesn't understand the parent class pointer to this - * child class for the make function of the - * ldpc_bit_flip_decoder; it's expecting a pointer to the base - * class. This returns a shared_from_this instance. - */ - virtual gr::fec::code::fec_mtrx_sptr get_base_sptr() = 0; - }; + /*! + * \brief A pointer to make SWIG work + * + * \details + * SWIG doesn't understand the parent class pointer to this + * child class for the make function of the + * ldpc_bit_flip_decoder; it's expecting a pointer to the base + * class. This returns a shared_from_this instance. + */ + virtual gr::fec::code::fec_mtrx_sptr get_base_sptr() = 0; +}; - } - } -} +} // namespace code +} // namespace fec +} // namespace gr #endif /* INCLUDED_ldpc_G_matrix_H */ diff --git a/gr-fec/include/gnuradio/fec/ldpc_H_matrix.h b/gr-fec/include/gnuradio/fec/ldpc_H_matrix.h index d770a658a3..2ed35c6cdc 100644 --- a/gr-fec/include/gnuradio/fec/ldpc_H_matrix.h +++ b/gr-fec/include/gnuradio/fec/ldpc_H_matrix.h @@ -27,77 +27,77 @@ #include <boost/enable_shared_from_this.hpp> namespace gr { - namespace fec { - namespace code { - /*! - * \brief Parity check matrix in Richardson/Urbanke format - * \ingroup error_coding_blk - * - * \details - * This class stores a matrix for use with the - * ldpc_encoder class. It must be of the specific format - * described by Richardson and Urbanke in Appendix A of their - * book: Modern Coding Theory (ISBN 978-0-521-85229-6). The - * form is: - * \f[\left[\begin{array}{ccc} T & A & B\\ E & C & D \end{array}\right]\f] - * This class can be used with the ldpc_bit_flip_decoder. - * - * To convert a parity check matrix to this format, use the - * python functions in: - * /lib/python2.7/dist-packages/gnuradio/fec/LDPC/Generate_LDPC_matrix.py. - */ - class FEC_API ldpc_H_matrix : virtual public fec_mtrx, - public boost::enable_shared_from_this<ldpc_H_matrix> - { - public: - typedef boost::shared_ptr<ldpc_H_matrix> sptr; +namespace fec { +namespace code { +/*! + * \brief Parity check matrix in Richardson/Urbanke format + * \ingroup error_coding_blk + * + * \details + * This class stores a matrix for use with the + * ldpc_encoder class. It must be of the specific format + * described by Richardson and Urbanke in Appendix A of their + * book: Modern Coding Theory (ISBN 978-0-521-85229-6). The + * form is: + * \f[\left[\begin{array}{ccc} T & A & B\\ E & C & D \end{array}\right]\f] + * This class can be used with the ldpc_bit_flip_decoder. + * + * To convert a parity check matrix to this format, use the + * python functions in: + * /lib/python2.7/dist-packages/gnuradio/fec/LDPC/Generate_LDPC_matrix.py. + */ +class FEC_API ldpc_H_matrix : virtual public fec_mtrx, + public boost::enable_shared_from_this<ldpc_H_matrix> +{ +public: + typedef boost::shared_ptr<ldpc_H_matrix> sptr; - /*! - * \brief Constructor given alist file and gap - * \param filename Name of an alist file to use. The alist - * format is described at: - * http://www.inference.phy.cam.ac.uk/mackay/codes/alist.html - * \param gap A property of the matrix being used. For alist - * files distributed with GNU Radio, this value - * is specified in the alist filename. The gap is - * found during the matrix preprocessing - * algorithm. It is equal to the number of rows in - * submatrices E, C and D. - */ - static sptr make(const std::string filename, unsigned int gap); + /*! + * \brief Constructor given alist file and gap + * \param filename Name of an alist file to use. The alist + * format is described at: + * http://www.inference.phy.cam.ac.uk/mackay/codes/alist.html + * \param gap A property of the matrix being used. For alist + * files distributed with GNU Radio, this value + * is specified in the alist filename. The gap is + * found during the matrix preprocessing + * algorithm. It is equal to the number of rows in + * submatrices E, C and D. + */ + static sptr make(const std::string filename, unsigned int gap); - //! Encode \p inbuffer with LDPC H matrix into \p outbuffer. - virtual void encode(unsigned char *outbuffer, - const unsigned char *inbuffer) const = 0; + //! Encode \p inbuffer with LDPC H matrix into \p outbuffer. + virtual void encode(unsigned char* outbuffer, + const unsigned char* inbuffer) const = 0; - //! Decode \p inbuffer with LDPC H matrix into \p outbuffer. - virtual void decode(unsigned char *outbuffer, - const float *inbuffer, - unsigned int frame_size, - unsigned int max_iterations) const = 0; + //! Decode \p inbuffer with LDPC H matrix into \p outbuffer. + virtual void decode(unsigned char* outbuffer, + const float* inbuffer, + unsigned int frame_size, + unsigned int max_iterations) const = 0; - //!Get the codeword length n - // Handled in fec_mtrx parent class. - virtual unsigned int n() const = 0; + //! Get the codeword length n + // Handled in fec_mtrx parent class. + virtual unsigned int n() const = 0; - //! Get the information word length k - // Handled in fec_mtrx parent class. - virtual unsigned int k() const = 0; + //! Get the information word length k + // Handled in fec_mtrx parent class. + virtual unsigned int k() const = 0; - /*! - * \brief A pointer to make SWIG work - * - * \details - * SWIG doesn't understand the parent class pointer to this - * child class for the make function of the - * ldpc_bit_flip_decoder; it's expecting a pointer to the base - * class. This returns a shared_from_this instance. - */ - virtual gr::fec::code::fec_mtrx_sptr get_base_sptr() = 0; - }; + /*! + * \brief A pointer to make SWIG work + * + * \details + * SWIG doesn't understand the parent class pointer to this + * child class for the make function of the + * ldpc_bit_flip_decoder; it's expecting a pointer to the base + * class. This returns a shared_from_this instance. + */ + virtual gr::fec::code::fec_mtrx_sptr get_base_sptr() = 0; +}; - } - } -} +} // namespace code +} // namespace fec +} // namespace gr #endif /* INCLUDED_ldpc_H_matrix_H */ diff --git a/gr-fec/include/gnuradio/fec/ldpc_bit_flip_decoder.h b/gr-fec/include/gnuradio/fec/ldpc_bit_flip_decoder.h index 6ed0658e93..cbd2b14bdf 100644 --- a/gr-fec/include/gnuradio/fec/ldpc_bit_flip_decoder.h +++ b/gr-fec/include/gnuradio/fec/ldpc_bit_flip_decoder.h @@ -27,65 +27,63 @@ #include <gnuradio/fec/generic_decoder.h> namespace gr { - namespace fec { - namespace code { +namespace fec { +namespace code { - /*! - * \brief LDPC bit flip decoding class - * \ingroup error_coding_blk - * - * \details - * A hard decision bit flip decoder class for decoding low - * density parity check (LDPC) codes. The decoder requires - * knowledge of the matrix used to create (encode) the - * codewords. The simple algorithm is: - * - * 1. Compute parity checks on all of the bits. - * 2. Flip the bit(s) associated with the most failed parity - * checks. - * 3. Check to see if new word is valid. (\f$\overline{x}\f$ - * is a codeword if and only if - * \f$\mathbf{H}\bar{x}^{T}=\overline{0}\f$.) If it is not - * valid, go back to step 1. - * 4. Repeat until valid codeword is found or the maximum - * number of iterations is reached. - */ - class FEC_API ldpc_bit_flip_decoder : virtual public generic_decoder - { - public: - - /*! - * \brief Build a bit flip decoding FEC API object. - * \param mtrx_obj The LDPC parity check matrix to use for - * decoding. This should be the same matrix used for - * encoding. Provide either a ldpc_H_matrix or - * a ldpc_G_matrix object. - * \param max_iter Maximum number of iterations to complete - * during the decoding algorithm. The default is 100 - * because this seemed to be sufficient during - * testing. May be increased for possibly better - * performance, but may slow things down. - */ - static generic_decoder::sptr make(const fec_mtrx_sptr mtrx_obj, - unsigned int max_iter=100); - - /*! - * \brief Sets the uncoded frame size to \p frame_size. - * \details - * Sets the uncoded frame size to \p frame_size. If \p - * frame_size is greater than the value given to the - * constructor, the frame size will be capped by that initial - * value and this function will return false. Otherwise, it - * returns true. - */ - virtual bool set_frame_size(unsigned int frame_size) = 0; +/*! + * \brief LDPC bit flip decoding class + * \ingroup error_coding_blk + * + * \details + * A hard decision bit flip decoder class for decoding low + * density parity check (LDPC) codes. The decoder requires + * knowledge of the matrix used to create (encode) the + * codewords. The simple algorithm is: + * + * 1. Compute parity checks on all of the bits. + * 2. Flip the bit(s) associated with the most failed parity + * checks. + * 3. Check to see if new word is valid. (\f$\overline{x}\f$ + * is a codeword if and only if + * \f$\mathbf{H}\bar{x}^{T}=\overline{0}\f$.) If it is not + * valid, go back to step 1. + * 4. Repeat until valid codeword is found or the maximum + * number of iterations is reached. + */ +class FEC_API ldpc_bit_flip_decoder : virtual public generic_decoder +{ +public: + /*! + * \brief Build a bit flip decoding FEC API object. + * \param mtrx_obj The LDPC parity check matrix to use for + * decoding. This should be the same matrix used for + * encoding. Provide either a ldpc_H_matrix or + * a ldpc_G_matrix object. + * \param max_iter Maximum number of iterations to complete + * during the decoding algorithm. The default is 100 + * because this seemed to be sufficient during + * testing. May be increased for possibly better + * performance, but may slow things down. + */ + static generic_decoder::sptr make(const fec_mtrx_sptr mtrx_obj, + unsigned int max_iter = 100); - //! Returns the coding rate of this decoder. - virtual double rate() = 0; + /*! + * \brief Sets the uncoded frame size to \p frame_size. + * \details + * Sets the uncoded frame size to \p frame_size. If \p + * frame_size is greater than the value given to the + * constructor, the frame size will be capped by that initial + * value and this function will return false. Otherwise, it + * returns true. + */ + virtual bool set_frame_size(unsigned int frame_size) = 0; - }; - } /* namespace code */ - } /* namespace fec */ + //! Returns the coding rate of this decoder. + virtual double rate() = 0; +}; +} /* namespace code */ +} /* namespace fec */ } /* namespace gr */ #endif /* INCLUDED_FEC_LDPC_BIT_FLIP_DECODER_H */ diff --git a/gr-fec/include/gnuradio/fec/ldpc_decoder.h b/gr-fec/include/gnuradio/fec/ldpc_decoder.h index 1a8052bb6c..309710036b 100644 --- a/gr-fec/include/gnuradio/fec/ldpc_decoder.h +++ b/gr-fec/include/gnuradio/fec/ldpc_decoder.h @@ -36,48 +36,47 @@ typedef unsigned char OUTPUT_DATATYPE; #include <gnuradio/fec/awgn_bp.h> namespace gr { - namespace fec { +namespace fec { #define MAXLOG 1e7 - class FEC_API ldpc_decoder : public generic_decoder - { - private: - //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 d_input_size, d_output_size; - double d_rate; - - alist d_list; - cldpc d_code; - awgn_bp d_spa; - - public: - ~ldpc_decoder (); - - double rate(); - bool set_frame_size(unsigned int frame_size); - - 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; } - }; - - } // namespace fec +class FEC_API ldpc_decoder : public generic_decoder +{ +private: + // 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 d_input_size, d_output_size; + double d_rate; + + alist d_list; + cldpc d_code; + awgn_bp d_spa; + +public: + ~ldpc_decoder(); + + double rate(); + bool set_frame_size(unsigned int frame_size); + + 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; } +}; + +} // namespace fec } // namespace gr #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 index 0b9b5d9f01..5764e219d0 100644 --- a/gr-fec/include/gnuradio/fec/ldpc_encoder.h +++ b/gr-fec/include/gnuradio/fec/ldpc_encoder.h @@ -28,20 +28,20 @@ #include <vector> namespace gr { - namespace fec { +namespace fec { - class FEC_API ldpc_encoder : virtual public generic_encoder - { - public: - static generic_encoder::sptr make (std::string alist_file); +class FEC_API ldpc_encoder : virtual public generic_encoder +{ +public: + static generic_encoder::sptr make(std::string alist_file); - virtual double rate() = 0; - virtual bool set_frame_size(unsigned int frame_size) = 0; - virtual int get_output_size() = 0; - virtual int get_input_size() = 0; - }; + virtual double rate() = 0; + virtual bool set_frame_size(unsigned int frame_size) = 0; + virtual int get_output_size() = 0; + virtual int get_input_size() = 0; +}; - } -} +} // namespace fec +} // namespace gr #endif /* INCLUDED_LDPC_ENCODER_H */ diff --git a/gr-fec/include/gnuradio/fec/ldpc_gen_mtrx_encoder.h b/gr-fec/include/gnuradio/fec/ldpc_gen_mtrx_encoder.h index 4966f14692..fd70516a50 100644 --- a/gr-fec/include/gnuradio/fec/ldpc_gen_mtrx_encoder.h +++ b/gr-fec/include/gnuradio/fec/ldpc_gen_mtrx_encoder.h @@ -26,51 +26,51 @@ #include <gnuradio/fec/ldpc_G_matrix.h> namespace gr { - namespace fec { - namespace code { +namespace fec { +namespace code { - /*! - * \brief LDPC generator matrix encoder - * \ingroup error_coding_blk - * - * \details - * A standard encoder class. This method is discussed in many - * textbooks; one is: Turbo Coding for Satellite and Wireless - * Communications by Soleymani, Gao, and Vilaipornsawai. - * Given a generator matrix in systematic form, - * \f$\mathbf{G}=\left[\mathbf{I}_{k}|\mathbf{P}\right]\f$, - * where \f$\mathbf{I}_{k}\f$ is the identity matrix and - * \f$\mathbf{P}\f$ is the parity submatrix, the information - * word \f$\bar{s}\f$ is encoded into a codeword - * \f$\overline{x}\f$ via: - * \f[\overline{x}=\mathbf{G}^{T}\bar{s}\f] - */ - class FEC_API ldpc_gen_mtrx_encoder : virtual public generic_encoder - { - public: - /*! - * \brief Build an encoding FEC API object. - * \param G_obj The ldpc_G_matrix object to use for - * encoding. - */ - static generic_encoder::sptr make(const code::ldpc_G_matrix::sptr G_obj); +/*! + * \brief LDPC generator matrix encoder + * \ingroup error_coding_blk + * + * \details + * A standard encoder class. This method is discussed in many + * textbooks; one is: Turbo Coding for Satellite and Wireless + * Communications by Soleymani, Gao, and Vilaipornsawai. + * Given a generator matrix in systematic form, + * \f$\mathbf{G}=\left[\mathbf{I}_{k}|\mathbf{P}\right]\f$, + * where \f$\mathbf{I}_{k}\f$ is the identity matrix and + * \f$\mathbf{P}\f$ is the parity submatrix, the information + * word \f$\bar{s}\f$ is encoded into a codeword + * \f$\overline{x}\f$ via: + * \f[\overline{x}=\mathbf{G}^{T}\bar{s}\f] + */ +class FEC_API ldpc_gen_mtrx_encoder : virtual public generic_encoder +{ +public: + /*! + * \brief Build an encoding FEC API object. + * \param G_obj The ldpc_G_matrix object to use for + * encoding. + */ + static generic_encoder::sptr make(const code::ldpc_G_matrix::sptr G_obj); - /*! - * \brief Sets the uncoded frame size to \p frame_size. - * \details - * Sets the uncoded frame size to \p frame_size. If \p - * frame_size is greater than the value given to the - * constructor, the frame size will be capped by that initial - * value and this function will return false. Otherwise, it - * returns true. - */ - virtual bool set_frame_size(unsigned int frame_size) = 0; + /*! + * \brief Sets the uncoded frame size to \p frame_size. + * \details + * Sets the uncoded frame size to \p frame_size. If \p + * frame_size is greater than the value given to the + * constructor, the frame size will be capped by that initial + * value and this function will return false. Otherwise, it + * returns true. + */ + virtual bool set_frame_size(unsigned int frame_size) = 0; - //! Returns the coding rate of this encoder. - virtual double rate() = 0; - }; - } /* namespace code */ - } /* namespace fec */ + //! Returns the coding rate of this encoder. + virtual double rate() = 0; +}; +} /* namespace code */ +} /* namespace fec */ } /* namespace gr */ #endif /* INCLUDED_FEC_LDPC_GEN_MTRX_ENCODER_H */ diff --git a/gr-fec/include/gnuradio/fec/ldpc_par_mtrx_encoder.h b/gr-fec/include/gnuradio/fec/ldpc_par_mtrx_encoder.h index 21f91f174c..f1cf958e8e 100755..100644 --- a/gr-fec/include/gnuradio/fec/ldpc_par_mtrx_encoder.h +++ b/gr-fec/include/gnuradio/fec/ldpc_par_mtrx_encoder.h @@ -30,23 +30,23 @@ #include <vector> namespace gr { - namespace fec { - namespace code { +namespace fec { +namespace code { - class FEC_API ldpc_par_mtrx_encoder : virtual public generic_encoder - { - public: - static generic_encoder::sptr make(std::string alist_file, unsigned int gap=0); - static generic_encoder::sptr make_H(const code::ldpc_H_matrix::sptr H_obj); +class FEC_API ldpc_par_mtrx_encoder : virtual public generic_encoder +{ +public: + static generic_encoder::sptr make(std::string alist_file, unsigned int gap = 0); + static generic_encoder::sptr make_H(const code::ldpc_H_matrix::sptr H_obj); - virtual double rate() = 0; - virtual bool set_frame_size(unsigned int frame_size) = 0; - virtual int get_output_size() = 0; - virtual int get_input_size() = 0; - }; + virtual double rate() = 0; + virtual bool set_frame_size(unsigned int frame_size) = 0; + virtual int get_output_size() = 0; + virtual int get_input_size() = 0; +}; - } /* namespace code */ - } /* namespace fec */ +} /* namespace code */ +} /* namespace fec */ } /* namespace gr */ #endif /* INCLUDED_LDPC_PAR_MTRX_ENCODER_H */ diff --git a/gr-fec/include/gnuradio/fec/maxstar.h b/gr-fec/include/gnuradio/fec/maxstar.h index f226550e5c..227de730e8 100644 --- a/gr-fec/include/gnuradio/fec/maxstar.h +++ b/gr-fec/include/gnuradio/fec/maxstar.h @@ -23,30 +23,30 @@ /* File maxstar.h
Description: Performs the max* operations (Jacobian logarithm) defined as:
- max*( x, y ) = max( x,y) + log( 1 + exp( - |x-y| ) )
+ 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
+ = 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)
+ 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)
+ 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,
+ 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.
*/
@@ -55,42 +55,42 @@ #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
+#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
+#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
+#define TTHRESH 2.508
+#define AVALUE -0.236
+#define BVALUE 0.592
/* Values for linear approximation (DecoderType=5) */
#define AJIAN -0.24904163195436
diff --git a/gr-fec/include/gnuradio/fec/polar_common.h b/gr-fec/include/gnuradio/fec/polar_common.h index c36995b59e..3d77b4b1e8 100644 --- a/gr-fec/include/gnuradio/fec/polar_common.h +++ b/gr-fec/include/gnuradio/fec/polar_common.h @@ -31,91 +31,93 @@ // Forward declaration for those objects. SWIG doesn't like them to be #include'd. namespace gr { - namespace blocks { - namespace kernel { - class unpack_k_bits; - } - } +namespace blocks { +namespace kernel { +class unpack_k_bits; } +} // namespace blocks +} // namespace gr namespace gr { - namespace fec { - namespace code { - - /*! - * \brief POLAR code common operations and attributes - * \ingroup error_coding_blk - * - * \details - * Polar codes are based on this paper by Erdal Arikan "Channel - * Polarization: A Method for Constructing Capacity-Achieving Codes - * for Symmetric Binary-Input Memoryless Channels", 2009 block - * holds common information for encoders and decoders. All polar - * encoder/decoders inherit from polar_common. - * - * class holds common info. It is common to all encoders and decoders. - */ - class FEC_API polar_common - { - public: - /*! - * \param block_size codeword size. MUST be a power of 2. - * \param num_info_bits represents the number of information - * bits in a block. Also called frame_size. <= block_size - * \param frozen_bit_positions is an integer vector which - * defines the position of all frozen bits in a block. - * Its size MUST be equal to block_size - num_info_bits. - * Also it must be sorted and every position must only - * occur once. - * \param frozen_bit_values holds an unpacked byte for every - * frozen bit position. It defines if a frozen bit is - * fixed to '0' or '1'. Defaults to all ZERO. - */ - polar_common(int block_size, int num_info_bits, - std::vector<int> frozen_bit_positions, - std::vector<char> frozen_bit_values); - ~polar_common(); - - protected: - const int block_size()const {return d_block_size;}; - const int block_power()const {return d_block_power;}; - const int num_info_bits() const {return d_num_info_bits;}; - - // helper functions - long bit_reverse(long value, int active_bits) const; - void print_packed_bit_array(const unsigned char* printed_array, - const int num_bytes) const; - void print_unpacked_bit_array(const unsigned char* bits, - const unsigned int num_bytes) const; - - std::vector<int> d_frozen_bit_positions; - std::vector<char> d_frozen_bit_values; - std::vector<int> d_info_bit_positions; - std::vector<int> d_info_bit_positions_reversed; - void setup_info_bit_positions_reversed(); -// std::vector<int> d_info_bit_positions_reversed; - - - // VOLK methods - void setup_volk_vectors(); - void volk_encode(unsigned char* out_buf, const unsigned char* in_buf); - void volk_encode_block(unsigned char* out_buf, unsigned char* in_buf); - unsigned char* d_volk_temp; - unsigned char* d_volk_frozen_bit_mask; - unsigned char* d_volk_frozen_bits; - - private: - int d_block_size; // depending on paper called 'N' or 'm' - int d_block_power; - int d_num_info_bits; // mostly abbreviated by 'K' - - void initialize_info_bit_position_vector(); - - gr::blocks::kernel::unpack_k_bits *d_unpacker; // convenience for 'print_packed_bit_array' function. - }; - - } //namespace code - } // namespace fec +namespace fec { +namespace code { + +/*! + * \brief POLAR code common operations and attributes + * \ingroup error_coding_blk + * + * \details + * Polar codes are based on this paper by Erdal Arikan "Channel + * Polarization: A Method for Constructing Capacity-Achieving Codes + * for Symmetric Binary-Input Memoryless Channels", 2009 block + * holds common information for encoders and decoders. All polar + * encoder/decoders inherit from polar_common. + * + * class holds common info. It is common to all encoders and decoders. + */ +class FEC_API polar_common +{ +public: + /*! + * \param block_size codeword size. MUST be a power of 2. + * \param num_info_bits represents the number of information + * bits in a block. Also called frame_size. <= block_size + * \param frozen_bit_positions is an integer vector which + * defines the position of all frozen bits in a block. + * Its size MUST be equal to block_size - num_info_bits. + * Also it must be sorted and every position must only + * occur once. + * \param frozen_bit_values holds an unpacked byte for every + * frozen bit position. It defines if a frozen bit is + * fixed to '0' or '1'. Defaults to all ZERO. + */ + polar_common(int block_size, + int num_info_bits, + std::vector<int> frozen_bit_positions, + std::vector<char> frozen_bit_values); + ~polar_common(); + +protected: + const int block_size() const { return d_block_size; }; + const int block_power() const { return d_block_power; }; + const int num_info_bits() const { return d_num_info_bits; }; + + // helper functions + long bit_reverse(long value, int active_bits) const; + void print_packed_bit_array(const unsigned char* printed_array, + const int num_bytes) const; + void print_unpacked_bit_array(const unsigned char* bits, + const unsigned int num_bytes) const; + + std::vector<int> d_frozen_bit_positions; + std::vector<char> d_frozen_bit_values; + std::vector<int> d_info_bit_positions; + std::vector<int> d_info_bit_positions_reversed; + void setup_info_bit_positions_reversed(); + // std::vector<int> d_info_bit_positions_reversed; + + + // VOLK methods + void setup_volk_vectors(); + void volk_encode(unsigned char* out_buf, const unsigned char* in_buf); + void volk_encode_block(unsigned char* out_buf, unsigned char* in_buf); + unsigned char* d_volk_temp; + unsigned char* d_volk_frozen_bit_mask; + unsigned char* d_volk_frozen_bits; + +private: + int d_block_size; // depending on paper called 'N' or 'm' + int d_block_power; + int d_num_info_bits; // mostly abbreviated by 'K' + + void initialize_info_bit_position_vector(); + + gr::blocks::kernel::unpack_k_bits* + d_unpacker; // convenience for 'print_packed_bit_array' function. +}; + +} // namespace code +} // namespace fec } // namespace gr #endif /* INCLUDED_FEC_POLAR_COMMON_H */ diff --git a/gr-fec/include/gnuradio/fec/polar_decoder_common.h b/gr-fec/include/gnuradio/fec/polar_decoder_common.h index c160f4b871..99fbdb4928 100644 --- a/gr-fec/include/gnuradio/fec/polar_decoder_common.h +++ b/gr-fec/include/gnuradio/fec/polar_decoder_common.h @@ -29,72 +29,79 @@ #include <gnuradio/fec/polar_common.h> namespace gr { - namespace fec { - namespace code { +namespace fec { +namespace code { - /*! - * \brief Class holds common methods and attributes for different - * decoder implementations - */ - class FEC_API polar_decoder_common : public generic_decoder, public polar_common - { - public: - /*! - * - * \param block_size codeword size. MUST be a power of 2. - * \param num_info_bits represents the number of information bits - * in a block. Also called frame_size. <= block_size - * \param frozen_bit_positions is an integer vector which defines - * the position of all frozen bits in a block. Its size - * MUST be equal to block_size - num_info_bits. Also it - * must be sorted and every position must only occur once. - * \param frozen_bit_values holds an unpacked byte for every - * frozen bit position. It defines if a frozen bit is - * fixed to '0' or '1'. Defaults to all ZERO. - */ - polar_decoder_common(int block_size, int num_info_bits, - std::vector<int> frozen_bit_positions, - std::vector<char> frozen_bit_values); - ~polar_decoder_common(); - - // FECAPI - double rate(){return (1.0 * get_output_size() / get_input_size());}; - int get_input_size(){return block_size();}; - int get_output_size(){return num_info_bits();}; - bool set_frame_size(unsigned int frame_size){return false;}; +/*! + * \brief Class holds common methods and attributes for different + * decoder implementations + */ +class FEC_API polar_decoder_common : public generic_decoder, public polar_common +{ +public: + /*! + * + * \param block_size codeword size. MUST be a power of 2. + * \param num_info_bits represents the number of information bits + * in a block. Also called frame_size. <= block_size + * \param frozen_bit_positions is an integer vector which defines + * the position of all frozen bits in a block. Its size + * MUST be equal to block_size - num_info_bits. Also it + * must be sorted and every position must only occur once. + * \param frozen_bit_values holds an unpacked byte for every + * frozen bit position. It defines if a frozen bit is + * fixed to '0' or '1'. Defaults to all ZERO. + */ + polar_decoder_common(int block_size, + int num_info_bits, + std::vector<int> frozen_bit_positions, + std::vector<char> frozen_bit_values); + ~polar_decoder_common(); - private: - static const float D_LLR_FACTOR; - unsigned int d_frozen_bit_counter; + // FECAPI + double rate() { return (1.0 * get_output_size() / get_input_size()); }; + int get_input_size() { return block_size(); }; + int get_output_size() { return num_info_bits(); }; + bool set_frame_size(unsigned int frame_size) { return false; }; - protected: - // calculate LLRs for stage - float llr_odd(const float la, const float lb) const; - float llr_even(const float la, const float lb, const unsigned char f) const; - unsigned char llr_bit_decision(const float llr) const {return (llr < 0.0f) ? 1 : 0;}; +private: + static const float D_LLR_FACTOR; + unsigned int d_frozen_bit_counter; - // control retrieval of frozen bits. - const bool is_frozen_bit(const int u_num) const; - const unsigned char next_frozen_bit(); +protected: + // calculate LLRs for stage + float llr_odd(const float la, const float lb) const; + float llr_even(const float la, const float lb, const unsigned char f) const; + unsigned char llr_bit_decision(const float llr) const + { + return (llr < 0.0f) ? 1 : 0; + }; - // preparation for decoding - void initialize_decoder(unsigned char* u, float* llrs, const float* input); + // control retrieval of frozen bits. + const bool is_frozen_bit(const int u_num) const; + const unsigned char next_frozen_bit(); - // basic algorithm methods - void butterfly(float* llrs, unsigned char* u, const int stage, const int u_num, const int row); - void butterfly_volk(float* llrs, unsigned char* u, const int stage, const int u_num, const int row); - void butterfly_generic(float* llrs, unsigned char* u, const int stage, const int u_num, const int row); - void even_u_values(unsigned char* u_even, const unsigned char* u, const int u_num); - void odd_xor_even_values(unsigned char* u_xor, const unsigned char* u, const int u_num); - void extract_info_bits(unsigned char* output, const unsigned char* input) const; + // preparation for decoding + void initialize_decoder(unsigned char* u, float* llrs, const float* input); - // helper functions. - void print_pretty_llr_vector(const float* llr_vec) const; + // basic algorithm methods + void butterfly( + float* llrs, unsigned char* u, const int stage, const int u_num, const int row); + void butterfly_volk( + float* llrs, unsigned char* u, const int stage, const int u_num, const int row); + void butterfly_generic( + float* llrs, unsigned char* u, const int stage, const int u_num, const int row); + void even_u_values(unsigned char* u_even, const unsigned char* u, const int u_num); + void + odd_xor_even_values(unsigned char* u_xor, const unsigned char* u, const int u_num); + void extract_info_bits(unsigned char* output, const unsigned char* input) const; - }; + // helper functions. + void print_pretty_llr_vector(const float* llr_vec) const; +}; - } // namespace code - } // namespace fec +} // namespace code +} // namespace fec } // namespace gr #endif /* INCLUDED_FEC_POLAR_DECODER_COMMON_H */ diff --git a/gr-fec/include/gnuradio/fec/polar_decoder_sc.h b/gr-fec/include/gnuradio/fec/polar_decoder_sc.h index 3563a06574..b916245c82 100644 --- a/gr-fec/include/gnuradio/fec/polar_decoder_sc.h +++ b/gr-fec/include/gnuradio/fec/polar_decoder_sc.h @@ -29,56 +29,57 @@ namespace gr { - namespace fec { - namespace code { +namespace fec { +namespace code { - /*! - * \brief Standard successive cancellation (SC) decoder for POLAR codes - * - * \details - * It expects float input with bits mapped 1 --> 1, 0 --> -1 - * Or: f = 2.0 * bit - 1.0 - * - */ - class FEC_API polar_decoder_sc : public polar_decoder_common - { - public: - - /*! - * \param block_size codeword size. MUST be a power of 2. - * \param num_info_bits represents the number of information - * bits in a block. Also called frame_size. <= block_size - * \param frozen_bit_positions is an integer vector which - * defines the position of all frozen bits in a block. - * Its size MUST be equal to block_size - num_info_bits. - * Also it must be sorted and every position must only - * occur once. - * \param frozen_bit_values holds an unpacked byte for every - * frozen bit position. It defines if a frozen bit is - * fixed to '0' or '1'. Defaults to all ZERO. - */ - static generic_decoder::sptr make(int block_size, int num_info_bits, - std::vector<int> frozen_bit_positions, - std::vector<char> frozen_bit_values); - ~polar_decoder_sc(); +/*! + * \brief Standard successive cancellation (SC) decoder for POLAR codes + * + * \details + * It expects float input with bits mapped 1 --> 1, 0 --> -1 + * Or: f = 2.0 * bit - 1.0 + * + */ +class FEC_API polar_decoder_sc : public polar_decoder_common +{ +public: + /*! + * \param block_size codeword size. MUST be a power of 2. + * \param num_info_bits represents the number of information + * bits in a block. Also called frame_size. <= block_size + * \param frozen_bit_positions is an integer vector which + * defines the position of all frozen bits in a block. + * Its size MUST be equal to block_size - num_info_bits. + * Also it must be sorted and every position must only + * occur once. + * \param frozen_bit_values holds an unpacked byte for every + * frozen bit position. It defines if a frozen bit is + * fixed to '0' or '1'. Defaults to all ZERO. + */ + static generic_decoder::sptr make(int block_size, + int num_info_bits, + std::vector<int> frozen_bit_positions, + std::vector<char> frozen_bit_values); + ~polar_decoder_sc(); - // FECAPI - void generic_work(void *in_buffer, void *out_buffer); + // FECAPI + void generic_work(void* in_buffer, void* out_buffer); - private: - polar_decoder_sc(int block_size, int num_info_bits, - std::vector<int> frozen_bit_positions, - std::vector<char> frozen_bit_values); +private: + polar_decoder_sc(int block_size, + int num_info_bits, + std::vector<int> frozen_bit_positions, + std::vector<char> frozen_bit_values); - float* d_llr_vec; - unsigned char* d_u_hat_vec; + float* d_llr_vec; + unsigned char* d_u_hat_vec; - unsigned char retrieve_bit_from_llr(float llr, const int pos); - void sc_decode(float* llrs, unsigned char* u); - }; + unsigned char retrieve_bit_from_llr(float llr, const int pos); + void sc_decode(float* llrs, unsigned char* u); +}; - } // namespace code - } // namespace fec +} // namespace code +} // namespace fec } // namespace gr #endif /* INCLUDED_FEC_POLAR_DECODER_SC_H */ diff --git a/gr-fec/include/gnuradio/fec/polar_decoder_sc_list.h b/gr-fec/include/gnuradio/fec/polar_decoder_sc_list.h index 12b896e824..6089929277 100644 --- a/gr-fec/include/gnuradio/fec/polar_decoder_sc_list.h +++ b/gr-fec/include/gnuradio/fec/polar_decoder_sc_list.h @@ -28,67 +28,71 @@ #include <gnuradio/fec/polar_decoder_common.h> namespace gr { - namespace fec { - namespace code { +namespace fec { +namespace code { - namespace polar { - class scl_list; - class path; - } +namespace polar { +class scl_list; +class path; +} // namespace polar - /*! - * \brief Successive cancellation list (SCL) decoder for polar - * codes. - * - * \details - * Decoder is based on Tal, Vardy "List Decoding of Polar Codes", - * 2012 LLR version: Balatsoukas-Stimming, Parizi, Burg "LLR-based - * Successive Cancellation List Decoding of Polar Codes", 2015. - * - * Block expects float input with bits mapped 1 --> 1, 0 --> -1 - * Or: f = 2.0 * bit - 1.0 - */ - class FEC_API polar_decoder_sc_list : public polar_decoder_common - { - public: - /*! - * \param max_list_size caps number of followed decoding paths. - * \param block_size codeword size. MUST be a power of 2. - * \param num_info_bits represents the number of information - * bits in a block. Also called frame_size. <= block_size - * \param frozen_bit_positions is an integer vector which - * defines the position of all frozen bits in a block. - * Its size MUST be equal to block_size - num_info_bits. - * Also it must be sorted and every position must only - * occur once. - * \param frozen_bit_values holds an unpacked byte for every - * frozen bit position. It defines if a frozen bit is - * fixed to '0' or '1'. Defaults to all ZERO. - */ - static generic_decoder::sptr make(int max_list_size, int block_size, - int num_info_bits, std::vector<int> frozen_bit_positions, - std::vector<char> frozen_bit_values); - ~polar_decoder_sc_list(); +/*! + * \brief Successive cancellation list (SCL) decoder for polar + * codes. + * + * \details + * Decoder is based on Tal, Vardy "List Decoding of Polar Codes", + * 2012 LLR version: Balatsoukas-Stimming, Parizi, Burg "LLR-based + * Successive Cancellation List Decoding of Polar Codes", 2015. + * + * Block expects float input with bits mapped 1 --> 1, 0 --> -1 + * Or: f = 2.0 * bit - 1.0 + */ +class FEC_API polar_decoder_sc_list : public polar_decoder_common +{ +public: + /*! + * \param max_list_size caps number of followed decoding paths. + * \param block_size codeword size. MUST be a power of 2. + * \param num_info_bits represents the number of information + * bits in a block. Also called frame_size. <= block_size + * \param frozen_bit_positions is an integer vector which + * defines the position of all frozen bits in a block. + * Its size MUST be equal to block_size - num_info_bits. + * Also it must be sorted and every position must only + * occur once. + * \param frozen_bit_values holds an unpacked byte for every + * frozen bit position. It defines if a frozen bit is + * fixed to '0' or '1'. Defaults to all ZERO. + */ + static generic_decoder::sptr make(int max_list_size, + int block_size, + int num_info_bits, + std::vector<int> frozen_bit_positions, + std::vector<char> frozen_bit_values); + ~polar_decoder_sc_list(); - // FECAPI - void generic_work(void *in_buffer, void *out_buffer); + // FECAPI + void generic_work(void* in_buffer, void* out_buffer); - private: - polar_decoder_sc_list(int max_list_size, int block_size, - int num_info_bits, std::vector<int> frozen_bit_positions, - std::vector<char> frozen_bit_values); +private: + polar_decoder_sc_list(int max_list_size, + int block_size, + int num_info_bits, + std::vector<int> frozen_bit_positions, + std::vector<char> frozen_bit_values); - polar::scl_list* d_scl; + polar::scl_list* d_scl; - void initialize_list(const float* in_buf); - const unsigned char* decode_list(); - void decode_bit(const int u_num); - void calculate_llrs_for_list(const int u_num); - void set_bit_in_list(const int u_num); - }; + void initialize_list(const float* in_buf); + const unsigned char* decode_list(); + void decode_bit(const int u_num); + void calculate_llrs_for_list(const int u_num); + void set_bit_in_list(const int u_num); +}; - } // namespace code - } // namespace fec +} // namespace code +} // namespace fec } // namespace gr #endif /* INCLUDED_POLAR_FEC_DECODER_SC_LIST_H */ diff --git a/gr-fec/include/gnuradio/fec/polar_decoder_sc_systematic.h b/gr-fec/include/gnuradio/fec/polar_decoder_sc_systematic.h index 36a0dc6ec4..5920fff616 100644 --- a/gr-fec/include/gnuradio/fec/polar_decoder_sc_systematic.h +++ b/gr-fec/include/gnuradio/fec/polar_decoder_sc_systematic.h @@ -1,19 +1,19 @@ /* -*- 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, @@ -28,55 +28,57 @@ #include <gnuradio/fec/polar_decoder_common.h> namespace gr { - namespace fec { - namespace code { +namespace fec { +namespace code { - /*! - * \brief Standard systematic successive cancellation (SC) decoder for POLAR codes - * - * \details - * It expects float input with bits mapped 1 --> 1, 0 --> -1 - * Or: f = 2.0 * bit - 1.0 - * - * Systematic encoding indicates that the info bit values are present in the codeword. - * 'info_bit_positions' may be obtained by ordering all non frozen_bit_positions in increasing order. - * One may extract them at their positions after a bit reversal operation. - * encoder -> decoder chain would need additional bit-reversal after encoding + before decoding. - * This is unnecessary. - */ - class FEC_API polar_decoder_sc_systematic : public polar_decoder_common - { - public: - /*! - * \param block_size codeword size. MUST be a power of 2. - * \param num_info_bits represents the number of information - * bits in a block. Also called frame_size. <= block_size - * \param frozen_bit_positions is an integer vector which - * defines the position of all frozen bits in a block. - * Its size MUST be equal to block_size - num_info_bits. - * Also it must be sorted and every position must only - * occur once. - */ - static generic_decoder::sptr make(int block_size, int num_info_bits, - std::vector<int> frozen_bit_positions); +/*! + * \brief Standard systematic successive cancellation (SC) decoder for POLAR codes + * + * \details + * It expects float input with bits mapped 1 --> 1, 0 --> -1 + * Or: f = 2.0 * bit - 1.0 + * + * Systematic encoding indicates that the info bit values are present in the codeword. + * 'info_bit_positions' may be obtained by ordering all non frozen_bit_positions in + * increasing order. One may extract them at their positions after a bit reversal + * operation. encoder -> decoder chain would need additional bit-reversal after encoding + + * before decoding. This is unnecessary. + */ +class FEC_API polar_decoder_sc_systematic : public polar_decoder_common +{ +public: + /*! + * \param block_size codeword size. MUST be a power of 2. + * \param num_info_bits represents the number of information + * bits in a block. Also called frame_size. <= block_size + * \param frozen_bit_positions is an integer vector which + * defines the position of all frozen bits in a block. + * Its size MUST be equal to block_size - num_info_bits. + * Also it must be sorted and every position must only + * occur once. + */ + static generic_decoder::sptr + make(int block_size, int num_info_bits, std::vector<int> frozen_bit_positions); + + ~polar_decoder_sc_systematic(); - ~polar_decoder_sc_systematic(); + // FECAPI + void generic_work(void* in_buffer, void* out_buffer); - // FECAPI - void generic_work(void *in_buffer, void *out_buffer); - private: - polar_decoder_sc_systematic(int block_size, int num_info_bits, std::vector<int> frozen_bit_positions); - float* d_llr_vec; - unsigned char* d_u_hat_vec; - unsigned char* d_frame_vec; - unsigned char retrieve_bit_from_llr(float llr, const int pos); - void sc_decode(float* llrs, unsigned char* u); - void extract_info_bits_reversed(unsigned char* outbuf, const unsigned char* inbuf); - }; +private: + polar_decoder_sc_systematic(int block_size, + int num_info_bits, + std::vector<int> frozen_bit_positions); + float* d_llr_vec; + unsigned char* d_u_hat_vec; + unsigned char* d_frame_vec; + unsigned char retrieve_bit_from_llr(float llr, const int pos); + void sc_decode(float* llrs, unsigned char* u); + void extract_info_bits_reversed(unsigned char* outbuf, const unsigned char* inbuf); +}; - } /* namespace code */ - } // namespace fec +} /* namespace code */ +} // namespace fec } // namespace gr #endif /* INCLUDED_FEC_POLAR_DECODER_SC_SYSTEMATIC_H */ - diff --git a/gr-fec/include/gnuradio/fec/polar_encoder.h b/gr-fec/include/gnuradio/fec/polar_encoder.h index f7d036e849..b3af14ee8a 100644 --- a/gr-fec/include/gnuradio/fec/polar_encoder.h +++ b/gr-fec/include/gnuradio/fec/polar_encoder.h @@ -29,84 +29,88 @@ #include <gnuradio/fec/polar_common.h> namespace gr { - namespace fec { - namespace code { +namespace fec { +namespace code { - /*! - * \brief POLAR encoder - * for basic details see 'polar_common' class. - * \ingroup error_coding_blk - * - * \details - * expects values with MSB first. It needs a full information word and encodes it in one pass. - * Output is a codeword of block_size. - */ - class FEC_API polar_encoder : public generic_encoder, public polar_common - { - public: - /*! - * Factory for a polar code encoder object. - * - * \param block_size defines the codeword size. It MUST be a - * power of 2. - * \param num_info_bits represents the number of information - * bits in a block. Also called frame_size. - * \param frozen_bit_positions is an integer vector which - * defines the position of all frozen bits in a block. - * Its size MUST be equal to block_size - num_info_bits. - * Also it must be sorted and every position must only - * occur once. - * \param frozen_bit_values holds an unpacked byte for every - * frozen bit position. It defines if a frozen bit is - * fixed to '0' or '1'. Defaults to all ZERO. - * \param is_packed choose 1 active bit/byte or 8 active - * bit/byte. if false, VOLK polar encoder is used. - */ - static generic_encoder::sptr make(int block_size, int num_info_bits, - std::vector<int> frozen_bit_positions, - std::vector<char> frozen_bit_values, - bool is_packed = false); - ~polar_encoder(); +/*! + * \brief POLAR encoder + * for basic details see 'polar_common' class. + * \ingroup error_coding_blk + * + * \details + * expects values with MSB first. It needs a full information word and encodes it in one + * pass. Output is a codeword of block_size. + */ +class FEC_API polar_encoder : public generic_encoder, public polar_common +{ +public: + /*! + * Factory for a polar code encoder object. + * + * \param block_size defines the codeword size. It MUST be a + * power of 2. + * \param num_info_bits represents the number of information + * bits in a block. Also called frame_size. + * \param frozen_bit_positions is an integer vector which + * defines the position of all frozen bits in a block. + * Its size MUST be equal to block_size - num_info_bits. + * Also it must be sorted and every position must only + * occur once. + * \param frozen_bit_values holds an unpacked byte for every + * frozen bit position. It defines if a frozen bit is + * fixed to '0' or '1'. Defaults to all ZERO. + * \param is_packed choose 1 active bit/byte or 8 active + * bit/byte. if false, VOLK polar encoder is used. + */ + static generic_encoder::sptr make(int block_size, + int num_info_bits, + std::vector<int> frozen_bit_positions, + std::vector<char> frozen_bit_values, + bool is_packed = false); + ~polar_encoder(); - // FECAPI - void generic_work(void *in_buffer, void *out_buffer); - double rate(){return (1.0 * get_input_size() / get_output_size());}; - int get_input_size(){return num_info_bits() / (d_is_packed ? 8 : 1);}; - int get_output_size(){return block_size() / (d_is_packed ? 8 : 1);}; - bool set_frame_size(unsigned int frame_size){return false;}; - const char* get_input_conversion(){return d_is_packed ? "pack" : "none";}; - const char* get_output_conversion(){return d_is_packed ? "packed_bits" : "none";}; + // FECAPI + void generic_work(void* in_buffer, void* out_buffer); + double rate() { return (1.0 * get_input_size() / get_output_size()); }; + int get_input_size() { return num_info_bits() / (d_is_packed ? 8 : 1); }; + int get_output_size() { return block_size() / (d_is_packed ? 8 : 1); }; + bool set_frame_size(unsigned int frame_size) { return false; }; + const char* get_input_conversion() { return d_is_packed ? "pack" : "none"; }; + const char* get_output_conversion() { return d_is_packed ? "packed_bits" : "none"; }; - private: - polar_encoder(int block_size, int num_info_bits, - std::vector<int>& frozen_bit_positions, - std::vector<char>& frozen_bit_values, bool is_packed); - bool d_is_packed; +private: + polar_encoder(int block_size, + int num_info_bits, + std::vector<int>& frozen_bit_positions, + std::vector<char>& frozen_bit_values, + bool is_packed); + bool d_is_packed; - // c'tor method for packed algorithm setup. - void setup_frozen_bit_inserter(); + // c'tor method for packed algorithm setup. + void setup_frozen_bit_inserter(); - // methods insert input bits and frozen bits into packed array for encoding - unsigned char* d_frozen_bit_prototype; // packed frozen bits are written onto it and later copies are used. - void insert_packed_frozen_bits_and_reverse(unsigned char* target, - const unsigned char* input) const; - void insert_unpacked_bit_into_packed_array_at_position(unsigned char* target, - const unsigned char bit, - const int pos) const; - void insert_packet_bit_into_packed_array_at_position(unsigned char* target, - const unsigned char bit, - const int target_pos, - const int bit_pos) const; + // methods insert input bits and frozen bits into packed array for encoding + unsigned char* d_frozen_bit_prototype; // packed frozen bits are written onto it and + // later copies are used. + void insert_packed_frozen_bits_and_reverse(unsigned char* target, + const unsigned char* input) const; + void insert_unpacked_bit_into_packed_array_at_position(unsigned char* target, + const unsigned char bit, + const int pos) const; + void insert_packet_bit_into_packed_array_at_position(unsigned char* target, + const unsigned char bit, + const int target_pos, + const int bit_pos) const; - // packed encoding methods - void encode_vector_packed(unsigned char* target) const; - void encode_vector_packed_subbyte(unsigned char* target) const; - void encode_packed_byte(unsigned char* target) const; - void encode_vector_packed_interbyte(unsigned char* target) const; - }; + // packed encoding methods + void encode_vector_packed(unsigned char* target) const; + void encode_vector_packed_subbyte(unsigned char* target) const; + void encode_packed_byte(unsigned char* target) const; + void encode_vector_packed_interbyte(unsigned char* target) const; +}; - } // namespace code - } // namespace fec +} // namespace code +} // namespace fec } // namespace gr #endif /* INCLUDED_FEC_POLAR_ENCODER_H */ diff --git a/gr-fec/include/gnuradio/fec/polar_encoder_systematic.h b/gr-fec/include/gnuradio/fec/polar_encoder_systematic.h index 8dd734df71..3b850a3176 100644 --- a/gr-fec/include/gnuradio/fec/polar_encoder_systematic.h +++ b/gr-fec/include/gnuradio/fec/polar_encoder_systematic.h @@ -1,19 +1,19 @@ /* -*- 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, @@ -29,83 +29,64 @@ #include <gnuradio/fec/polar_common.h> namespace gr { - namespace fec { - namespace code { +namespace fec { +namespace code { - /*! - * \brief systematic POLAR encoder - * for basic details see 'polar_common' class. - * \ingroup error_coding_blk - * - * \details - * expects values with MSB first. It needs a full information word and encodes it in one pass. - * Output is a codeword of block_size. - * - * Systematic encoding indicates that the info bit values are present in the codeword. - * 'info_bit_positions' may be obtained by ordering all non frozen_bit_positions in increasing order. - * One may extract them at their positions after a bit reversal operation. - * encoder -> decoder chain would need additional bit-reversal after encoding + before decoding. - * This is unnecessary. - */ - class FEC_API polar_encoder_systematic: public generic_encoder, public polar_common - { - public: - /*! - * Factory for a polar code encoder object. - * - * \param block_size defines the codeword size. It MUST be a - * power of 2. - * \param num_info_bits represents the number of information - * bits in a block. Also called frame_size. - * \param frozen_bit_positions is an integer vector which - * defines the position of all frozen bits in a block. - * Its size MUST be equal to block_size - num_info_bits. - * Also it must be sorted and every position must only - * occur once. Frozen bit values will be set to ZERO! - */ - static generic_encoder::sptr - make(int block_size, int num_info_bits, std::vector<int> frozen_bit_positions); +/*! + * \brief systematic POLAR encoder + * for basic details see 'polar_common' class. + * \ingroup error_coding_blk + * + * \details + * expects values with MSB first. It needs a full information word and encodes it in one + * pass. Output is a codeword of block_size. + * + * Systematic encoding indicates that the info bit values are present in the codeword. + * 'info_bit_positions' may be obtained by ordering all non frozen_bit_positions in + * increasing order. One may extract them at their positions after a bit reversal + * operation. encoder -> decoder chain would need additional bit-reversal after encoding + + * before decoding. This is unnecessary. + */ +class FEC_API polar_encoder_systematic : public generic_encoder, public polar_common +{ +public: + /*! + * Factory for a polar code encoder object. + * + * \param block_size defines the codeword size. It MUST be a + * power of 2. + * \param num_info_bits represents the number of information + * bits in a block. Also called frame_size. + * \param frozen_bit_positions is an integer vector which + * defines the position of all frozen bits in a block. + * Its size MUST be equal to block_size - num_info_bits. + * Also it must be sorted and every position must only + * occur once. Frozen bit values will be set to ZERO! + */ + static generic_encoder::sptr + make(int block_size, int num_info_bits, std::vector<int> frozen_bit_positions); + + // FECAPI + void generic_work(void* in_buffer, void* out_buffer); + double rate() { return (1.0 * get_input_size() / get_output_size()); }; + int get_input_size() { return num_info_bits(); }; + int get_output_size() { return block_size(); }; + bool set_frame_size(unsigned int frame_size) { return false; }; - // FECAPI - void - generic_work(void *in_buffer, void *out_buffer); - double - rate() - { - return (1.0 * get_input_size() / get_output_size()); - } - ; - int - get_input_size() - { - return num_info_bits(); - } - ; - int - get_output_size() - { - return block_size(); - } - ; - bool - set_frame_size(unsigned int frame_size) - { - return false; - } - ; + ~polar_encoder_systematic(); - ~polar_encoder_systematic(); - private: - polar_encoder_systematic(int block_size, int num_info_bits, - std::vector<int> frozen_bit_positions); +private: + polar_encoder_systematic(int block_size, + int num_info_bits, + std::vector<int> frozen_bit_positions); - void bit_reverse_and_reset_frozen_bits(unsigned char *outbuf, const unsigned char *inbuf); - unsigned char* d_volk_syst_intermediate; - }; + void bit_reverse_and_reset_frozen_bits(unsigned char* outbuf, + const unsigned char* inbuf); + unsigned char* d_volk_syst_intermediate; +}; - } // namespace code - } // namespace fec +} // namespace code +} // namespace fec } // namespace gr #endif /* INCLUDED_FEC_POLAR_ENCODER_SYSTEMATIC_H */ - diff --git a/gr-fec/include/gnuradio/fec/puncture_bb.h b/gr-fec/include/gnuradio/fec/puncture_bb.h index 499247efbd..7b5dad7e48 100644 --- a/gr-fec/include/gnuradio/fec/puncture_bb.h +++ b/gr-fec/include/gnuradio/fec/puncture_bb.h @@ -27,82 +27,82 @@ #include <gnuradio/block.h> namespace gr { - namespace fec { +namespace fec { + +/*! + * \brief Puncture a stream of unpacked bits. + * \ingroup error_coding_blk + * + * \details + * Puncture a given block of input samples of \p puncsize. The + * items produced is based on pattern \p puncpat. Basically, if: + * + * \code + * k = 0 + * if _puncpat[i] == 1: + * out[k++] = input[i] + * \endcode + * + * This block is designed for unpacked bits - that is, every + * input sample is a bit, either a 1 or 0. It's possible to use + * packed bits as symbols, but the puncturing will be done on + * the symbol level, not the bit level. + * + * \p puncpat is specified as a 32-bit integer that we can + * convert into the vector _puncpat used in the algorithm above: + * + * \code + * _puncpat = [0,...] + * for i in puncsize: + * _puncpat[i] = puncpat >> (puncsize-1-i) + * \endcode + * + * Example: + * \code + * puncsize = 8 + * puncpat = 0xEF --> [1,1,1,0,1,1,1,1] + * input = [a, b, c, d, e, f, g, h] + * output = [a, b, c, e, f, g, h] + * \endcode + * + * The gr.fec Python module provides a read_bitlist function + * that can turn a string of a puncture pattern into the correct + * integer form. The pattern of 0xEF could be specified as + * fec.readbitlist("11101111"). Also, this allows us to use + * puncsize=len("11101111") to make sure that our sizes are set + * up correctly for the pattern we want. + * + * The fec.extended_encoder takes in the puncture pattern + * directly as a string and uses the readbitlist inside to do + * the conversion. + * + * Note that due to the above concept, the default setting in the + * extended encoder of '11' translates into no puncturing. + * + * The \p delay parameter delays the application of the puncture + * pattern. This is equivalent to circularly rotating the \p + * puncpat by \p delay. Note that because of the circular shift, + * the delay should be between 0 and \p puncsize, but this is + * not enforced; the effective delay will simply be \p delay mod + * \p puncsize. A negative value here is ignored. + */ +class FEC_API puncture_bb : virtual public block +{ +public: + // gr::fec::puncture_bb::sptr + typedef boost::shared_ptr<puncture_bb> sptr; /*! - * \brief Puncture a stream of unpacked bits. - * \ingroup error_coding_blk - * - * \details - * Puncture a given block of input samples of \p puncsize. The - * items produced is based on pattern \p puncpat. Basically, if: - * - * \code - * k = 0 - * if _puncpat[i] == 1: - * out[k++] = input[i] - * \endcode - * - * This block is designed for unpacked bits - that is, every - * input sample is a bit, either a 1 or 0. It's possible to use - * packed bits as symbols, but the puncturing will be done on - * the symbol level, not the bit level. - * - * \p puncpat is specified as a 32-bit integer that we can - * convert into the vector _puncpat used in the algorithm above: - * - * \code - * _puncpat = [0,...] - * for i in puncsize: - * _puncpat[i] = puncpat >> (puncsize-1-i) - * \endcode + * \brief Constructs a puncture block for unpacked bits. * - * Example: - * \code - * puncsize = 8 - * puncpat = 0xEF --> [1,1,1,0,1,1,1,1] - * input = [a, b, c, d, e, f, g, h] - * output = [a, b, c, e, f, g, h] - * \endcode - * - * The gr.fec Python module provides a read_bitlist function - * that can turn a string of a puncture pattern into the correct - * integer form. The pattern of 0xEF could be specified as - * fec.readbitlist("11101111"). Also, this allows us to use - * puncsize=len("11101111") to make sure that our sizes are set - * up correctly for the pattern we want. - * - * The fec.extended_encoder takes in the puncture pattern - * directly as a string and uses the readbitlist inside to do - * the conversion. - * - * Note that due to the above concept, the default setting in the - * extended encoder of '11' translates into no puncturing. - * - * The \p delay parameter delays the application of the puncture - * pattern. This is equivalent to circularly rotating the \p - * puncpat by \p delay. Note that because of the circular shift, - * the delay should be between 0 and \p puncsize, but this is - * not enforced; the effective delay will simply be \p delay mod - * \p puncsize. A negative value here is ignored. + * \param puncsize Size of block of bits to puncture + * \param puncpat The puncturing pattern + * \param delay Delayed the puncturing pattern by shifting it */ - class FEC_API puncture_bb : virtual public block - { - public: - // gr::fec::puncture_bb::sptr - typedef boost::shared_ptr<puncture_bb> sptr; - - /*! - * \brief Constructs a puncture block for unpacked bits. - * - * \param puncsize Size of block of bits to puncture - * \param puncpat The puncturing pattern - * \param delay Delayed the puncturing pattern by shifting it - */ - static sptr make(int puncsize, int puncpat, int delay=0); - }; + static sptr make(int puncsize, int puncpat, int delay = 0); +}; - } /* namespace fec */ +} /* namespace fec */ } /* namespace gr */ #endif /* INCLUDED_FEC_PUNCTURE_BB_H */ diff --git a/gr-fec/include/gnuradio/fec/puncture_ff.h b/gr-fec/include/gnuradio/fec/puncture_ff.h index 49a376a153..5abb5042cd 100644 --- a/gr-fec/include/gnuradio/fec/puncture_ff.h +++ b/gr-fec/include/gnuradio/fec/puncture_ff.h @@ -27,81 +27,81 @@ #include <gnuradio/block.h> namespace gr { - namespace fec { +namespace fec { + +/*! + * \brief Puncture a stream of floats. + * \ingroup error_coding_blk + * + * \details + * For a given block of input samples of \p puncsize, the items + * produced is based on \p puncpat. Basically, if: + * + * \code + * k = 0 + * if _puncpat[i] == 1: + * out[k++] = input[i] + * \endcode + * + * This block is designed for floats, generally 1's and -1's. It's + * possible to use other float values as symbols, but this is not + * the expected operation. + * + * \p puncpat is specified as a 32-bit integer that we can + * convert into the vector _puncpat used in the algorithm above: + * + * \code + * _puncpat = [0,...] + * for i in puncsize: + * _puncpat[i] = puncpat >> (puncsize-1-i) + * \endcode + * + * Example: + * \code + * puncsize = 8 + * puncpat = 0xEF --> [1,1,1,0,1,1,1,1] + * input = [a, b, c, d, e, f, g, h] + * output = [a, b, c, e, f, g, h] + * \endcode + * + * The gr.fec Python module provides a read_bitlist function + * that can turn a string of a puncture pattern into the correct + * integer form. The pattern of 0xEF could be specified as + * fec.readbitlist("11101111"). Also, this allows us to use + * puncsize=len("11101111") to make sure that our sizes are set + * up correctly for the pattern we want. + * + * The fec.extended_encoder takes in the puncture pattern + * directly as a string and uses the readbitlist inside to do + * the conversion. + * + * Note that due to the above concept, the default setting in the + * extended encoder of '11' translates into no puncturing. + * + * The \p delay parameter delays the application of the puncture + * pattern. This is equivalent to circularly rotating the \p + * puncpat by \p delay. Note that because of the circular shift, + * the delay should be between 0 and \p puncsize, but this is + * not enforced; the effective delay will simply be \p delay mod + * \p puncsize. A negative value here is ignored. + */ +class FEC_API puncture_ff : virtual public block +{ +public: + // gr::fec::puncture_ff::sptr + typedef boost::shared_ptr<puncture_ff> sptr; /*! - * \brief Puncture a stream of floats. - * \ingroup error_coding_blk - * - * \details - * For a given block of input samples of \p puncsize, the items - * produced is based on \p puncpat. Basically, if: - * - * \code - * k = 0 - * if _puncpat[i] == 1: - * out[k++] = input[i] - * \endcode - * - * This block is designed for floats, generally 1's and -1's. It's - * possible to use other float values as symbols, but this is not - * the expected operation. - * - * \p puncpat is specified as a 32-bit integer that we can - * convert into the vector _puncpat used in the algorithm above: - * - * \code - * _puncpat = [0,...] - * for i in puncsize: - * _puncpat[i] = puncpat >> (puncsize-1-i) - * \endcode + * \brief Constructs a puncture block for floats. * - * Example: - * \code - * puncsize = 8 - * puncpat = 0xEF --> [1,1,1,0,1,1,1,1] - * input = [a, b, c, d, e, f, g, h] - * output = [a, b, c, e, f, g, h] - * \endcode - * - * The gr.fec Python module provides a read_bitlist function - * that can turn a string of a puncture pattern into the correct - * integer form. The pattern of 0xEF could be specified as - * fec.readbitlist("11101111"). Also, this allows us to use - * puncsize=len("11101111") to make sure that our sizes are set - * up correctly for the pattern we want. - * - * The fec.extended_encoder takes in the puncture pattern - * directly as a string and uses the readbitlist inside to do - * the conversion. - * - * Note that due to the above concept, the default setting in the - * extended encoder of '11' translates into no puncturing. - * - * The \p delay parameter delays the application of the puncture - * pattern. This is equivalent to circularly rotating the \p - * puncpat by \p delay. Note that because of the circular shift, - * the delay should be between 0 and \p puncsize, but this is - * not enforced; the effective delay will simply be \p delay mod - * \p puncsize. A negative value here is ignored. + * \param puncsize Size of block of bits to puncture + * \param puncpat The puncturing pattern + * \param delay Delayed the puncturing pattern by shifting it */ - class FEC_API puncture_ff : virtual public block - { - public: - // gr::fec::puncture_ff::sptr - typedef boost::shared_ptr<puncture_ff> sptr; - - /*! - * \brief Constructs a puncture block for floats. - * - * \param puncsize Size of block of bits to puncture - * \param puncpat The puncturing pattern - * \param delay Delayed the puncturing pattern by shifting it - */ - static sptr make(int puncsize, int puncpat, int delay); - }; + static sptr make(int puncsize, int puncpat, int delay); +}; - } /* namespace fec */ +} /* namespace fec */ } /* namespace gr */ #endif /* INCLUDED_FEC_PUNCTURE_FF_H */ diff --git a/gr-fec/include/gnuradio/fec/repetition_decoder.h b/gr-fec/include/gnuradio/fec/repetition_decoder.h index e17f612b83..cbc41ddeb5 100644 --- a/gr-fec/include/gnuradio/fec/repetition_decoder.h +++ b/gr-fec/include/gnuradio/fec/repetition_decoder.h @@ -29,54 +29,52 @@ #include <string> namespace gr { - namespace fec { - namespace code { +namespace fec { +namespace code { - /*! - * \brief Repetition Decoding class. - * \ingroup error_coding_blk - * - * \details - * A repetition decoder class. This takes a majority vote, - * biased by the \p ap_prob rate, and decides if the number of 1 - * bits > ap_prob, it is a 1; else, it is a 0. - */ - class FEC_API repetition_decoder : virtual public generic_decoder - { - public: - - /*! - * Build a repetition decoding FEC API object. - * - * \param frame_size Number of bits per frame. If using in the - * tagged stream style, this is the maximum allowable - * number of bits per frame. - * \param rep Repetition rate; encoder rate is rep bits out - * for each input bit. - * \param ap_prob The a priori probability that a bit is a 1 - * (generally, unless otherwise known, assume to be - * 0.5). - */ - static generic_decoder::sptr make(int frame_size, int rep, - float ap_prob=0.5); +/*! + * \brief Repetition Decoding class. + * \ingroup error_coding_blk + * + * \details + * A repetition decoder class. This takes a majority vote, + * biased by the \p ap_prob rate, and decides if the number of 1 + * bits > ap_prob, it is a 1; else, it is a 0. + */ +class FEC_API repetition_decoder : virtual public generic_decoder +{ +public: + /*! + * Build a repetition decoding FEC API object. + * + * \param frame_size Number of bits per frame. If using in the + * tagged stream style, this is the maximum allowable + * number of bits per frame. + * \param rep Repetition rate; encoder rate is rep bits out + * for each input bit. + * \param ap_prob The a priori probability that a bit is a 1 + * (generally, unless otherwise known, assume to be + * 0.5). + */ + static generic_decoder::sptr make(int frame_size, int rep, float ap_prob = 0.5); - /*! - * Sets the uncoded frame size to \p frame_size. If \p - * frame_size is greater than the value given to the - * constructor, the frame size will be capped by that initial - * value and this function will return false. Otherwise, it - * returns true. - */ - virtual bool set_frame_size(unsigned int frame_size) = 0; + /*! + * Sets the uncoded frame size to \p frame_size. If \p + * frame_size is greater than the value given to the + * constructor, the frame size will be capped by that initial + * value and this function will return false. Otherwise, it + * returns true. + */ + virtual bool set_frame_size(unsigned int frame_size) = 0; - /*! - * Returns the coding rate of this encoder (it will always be 1). - */ - virtual double rate() = 0; - }; + /*! + * Returns the coding rate of this encoder (it will always be 1). + */ + virtual double rate() = 0; +}; - } /* namespace code */ - } /* namespace fec */ +} /* namespace code */ +} /* namespace fec */ } /* namespace gr */ #endif /* INCLUDED_FEC_REPETITION_DECODER_H */ diff --git a/gr-fec/include/gnuradio/fec/repetition_encoder.h b/gr-fec/include/gnuradio/fec/repetition_encoder.h index 313dc6415f..6efcc31ae5 100644 --- a/gr-fec/include/gnuradio/fec/repetition_encoder.h +++ b/gr-fec/include/gnuradio/fec/repetition_encoder.h @@ -29,50 +29,49 @@ #include <string> namespace gr { - namespace fec { - namespace code { +namespace fec { +namespace code { - /*! - * \brief Repetition Encoding class. - * \ingroup error_coding_blk - * - * \details - * A repetition encoder class that repeats each input bit \p rep - * times. To decode, take a majority vote over the number of - * repetitions. - */ - class FEC_API repetition_encoder : virtual public generic_encoder - { - public: - - /*! - * Build a repetition encoding FEC API object. - * - * \param frame_size Number of bits per frame. If using in the - * tagged stream style, this is the maximum allowable - * number of bits per frame. - * \param rep Repetition rate; encoder rate is rep bits out - * for each input bit. - */ - static generic_encoder::sptr make(int frame_size, int rep); +/*! + * \brief Repetition Encoding class. + * \ingroup error_coding_blk + * + * \details + * A repetition encoder class that repeats each input bit \p rep + * times. To decode, take a majority vote over the number of + * repetitions. + */ +class FEC_API repetition_encoder : virtual public generic_encoder +{ +public: + /*! + * Build a repetition encoding FEC API object. + * + * \param frame_size Number of bits per frame. If using in the + * tagged stream style, this is the maximum allowable + * number of bits per frame. + * \param rep Repetition rate; encoder rate is rep bits out + * for each input bit. + */ + static generic_encoder::sptr make(int frame_size, int rep); - /*! - * Sets the uncoded frame size to \p frame_size. If \p - * frame_size is greater than the value given to the - * constructor, the frame size will be capped by that initial - * value and this function will return false. Otherwise, it - * returns true. - */ - virtual bool set_frame_size(unsigned int frame_size) = 0; + /*! + * Sets the uncoded frame size to \p frame_size. If \p + * frame_size is greater than the value given to the + * constructor, the frame size will be capped by that initial + * value and this function will return false. Otherwise, it + * returns true. + */ + virtual bool set_frame_size(unsigned int frame_size) = 0; - /*! - * Returns the coding rate of this encoder. - */ - virtual double rate() = 0; - }; + /*! + * Returns the coding rate of this encoder. + */ + virtual double rate() = 0; +}; - } /* namespace code */ - } /* namespace fec */ +} /* namespace code */ +} /* namespace fec */ } /* namespace gr */ #endif /* INCLUDED_FEC_REPETITION_ENCODER_H */ diff --git a/gr-fec/include/gnuradio/fec/rs.h b/gr-fec/include/gnuradio/fec/rs.h index 8a28cd31ac..c877e141f8 100644 --- a/gr-fec/include/gnuradio/fec/rs.h +++ b/gr-fec/include/gnuradio/fec/rs.h @@ -5,26 +5,32 @@ */ /* General purpose RS codec, 8-bit symbols */ -FEC_API void encode_rs_char(void *rs,unsigned char *data,unsigned char *parity); -FEC_API int decode_rs_char(void *rs,unsigned char *data,int *eras_pos, int no_eras); -FEC_API void *init_rs_char(unsigned int symsize,unsigned int gfpoly, - unsigned int fcr,unsigned int prim,unsigned int nroots); -FEC_API void free_rs_char(void *rs); +FEC_API void encode_rs_char(void* rs, unsigned char* data, unsigned char* parity); +FEC_API int decode_rs_char(void* rs, unsigned char* data, int* eras_pos, int no_eras); +FEC_API void* init_rs_char(unsigned int symsize, + unsigned int gfpoly, + unsigned int fcr, + unsigned int prim, + unsigned int nroots); +FEC_API void free_rs_char(void* rs); /* General purpose RS codec, integer symbols */ -FEC_API void encode_rs_int(void *rs,int *data,int *parity); -FEC_API int decode_rs_int(void *rs,int *data,int *eras_pos,int no_eras); -FEC_API void *init_rs_int(unsigned int symsize,unsigned int gfpoly,unsigned int fcr, - unsigned int prim,unsigned int nroots); -FEC_API void free_rs_int(void *rs); +FEC_API void encode_rs_int(void* rs, int* data, int* parity); +FEC_API int decode_rs_int(void* rs, int* data, int* eras_pos, int no_eras); +FEC_API void* init_rs_int(unsigned int symsize, + unsigned int gfpoly, + unsigned int fcr, + unsigned int prim, + unsigned int nroots); +FEC_API void free_rs_int(void* rs); /* CCSDS standard (255,223) RS codec with conventional (*not* dual-basis) * symbol representation */ -FEC_API void encode_rs_8(unsigned char *data,unsigned char *parity); -FEC_API int decode_rs_8(unsigned char *data,int *eras_pos,int no_eras); +FEC_API void encode_rs_8(unsigned char* data, unsigned char* parity); +FEC_API int decode_rs_8(unsigned char* data, int* eras_pos, int no_eras); /* Tables to map from conventional->dual (Taltab) and * dual->conventional (Tal1tab) bases */ -extern unsigned char Taltab[],Tal1tab[]; +extern unsigned char Taltab[], Tal1tab[]; diff --git a/gr-fec/include/gnuradio/fec/tagged_decoder.h b/gr-fec/include/gnuradio/fec/tagged_decoder.h index 9ff472f372..5ee3fe8a91 100644 --- a/gr-fec/include/gnuradio/fec/tagged_decoder.h +++ b/gr-fec/include/gnuradio/fec/tagged_decoder.h @@ -30,70 +30,70 @@ #include <boost/shared_array.hpp> namespace gr { - namespace fec { +namespace fec { + +/*! + * \brief General FEC decoding block that takes in a decoder + * variable object (derived from gr::fec::general_decoder) for use + * in a flowgraph. + * + * \ingroup error_coding_blk + * + * \details + * This block uses a decoder variable object (derived from + * gr::fec::generic_decoder) to decode data within a + * flowgraph. This block interacts with the general FECAPI + * architecture to handle all passing all input and output data in + * a flowgraph. The decoder variable takes care of understanding + * the requirements, data types and sizes, and boundary conditions + * of the specific FEC decoding algorithm. + * + * Generally, this block is used within the fec.extended_decoder + * Python block to handle some input/output formatting issues. In + * the FECAPI, the decoder variable sets properties like the input + * and output types and sizes and whether the output is packed or + * unpacked bytes. The fec.extended_decoder uses this information + * to set up an gr::hier_block2 structure to make sure the I/O to + * the variable is handled consistently, such as to make sure all + * inputs are floats with one soft symbol per item and the outputs + * are unpacked bytes with the bit in the LSB. + * + * See gr::fec::generic_decoder for detail on what information an + * FECAPI variable object can set if using this block directly and + * not as part of the fec.extended_decoder. + */ +class FEC_API tagged_decoder : virtual public tagged_stream_block +{ +public: + typedef boost::shared_ptr<tagged_decoder> sptr; + typedef boost::shared_array<unsigned char> buf_sptr; /*! - * \brief General FEC decoding block that takes in a decoder - * variable object (derived from gr::fec::general_decoder) for use - * in a flowgraph. - * - * \ingroup error_coding_blk - * - * \details - * This block uses a decoder variable object (derived from - * gr::fec::generic_decoder) to decode data within a - * flowgraph. This block interacts with the general FECAPI - * architecture to handle all passing all input and output data in - * a flowgraph. The decoder variable takes care of understanding - * the requirements, data types and sizes, and boundary conditions - * of the specific FEC decoding algorithm. + * Create the FEC decoder block by taking in the FECAPI decoder + * object as well as input and output sizes. * - * Generally, this block is used within the fec.extended_decoder - * Python block to handle some input/output formatting issues. In - * the FECAPI, the decoder variable sets properties like the input - * and output types and sizes and whether the output is packed or - * unpacked bytes. The fec.extended_decoder uses this information - * to set up an gr::hier_block2 structure to make sure the I/O to - * the variable is handled consistently, such as to make sure all - * inputs are floats with one soft symbol per item and the outputs - * are unpacked bytes with the bit in the LSB. - * - * See gr::fec::generic_decoder for detail on what information an - * FECAPI variable object can set if using this block directly and - * not as part of the fec.extended_decoder. + * \param my_decoder An FECAPI decoder object (See gr::fec::generic_decoder). + * \param input_item_size The size of the input items (often the my_decoder object can + * tell us this). \param output_item_size The size of the output items (often the + * my_decoder object can tell us this). \param lengthtagname Key name of the tagged + * stream frame size. \param mtu The Maximum Transmission Unit (MTU) of the output + * frame that the block will be able to + * process. Specified in bytes and defaults to 1500. */ - class FEC_API tagged_decoder : virtual public tagged_stream_block - { - public: - typedef boost::shared_ptr<tagged_decoder> sptr; - typedef boost::shared_array<unsigned char> buf_sptr; - - /*! - * Create the FEC decoder block by taking in the FECAPI decoder - * object as well as input and output sizes. - * - * \param my_decoder An FECAPI decoder object (See gr::fec::generic_decoder). - * \param input_item_size The size of the input items (often the my_decoder object can tell us this). - * \param output_item_size The size of the output items (often the my_decoder object can tell us this). - * \param lengthtagname Key name of the tagged stream frame size. - * \param mtu The Maximum Transmission Unit (MTU) of the output - * frame that the block will be able to - * process. Specified in bytes and defaults to 1500. - */ - static sptr make(generic_decoder::sptr my_decoder, - size_t input_item_size, - size_t output_item_size, - const std::string &lengthtagname="packet_len", - int mtu=1500); + static sptr make(generic_decoder::sptr my_decoder, + size_t input_item_size, + size_t output_item_size, + const std::string& lengthtagname = "packet_len", + int mtu = 1500); - virtual int work(int noutput_items, - gr_vector_int& ninput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) = 0; - virtual int calculate_output_stream_length(const gr_vector_int &ninput_items) = 0; - }; + virtual int work(int noutput_items, + gr_vector_int& ninput_items, + gr_vector_const_void_star& input_items, + gr_vector_void_star& output_items) = 0; + virtual int calculate_output_stream_length(const gr_vector_int& ninput_items) = 0; +}; - } /* namespace fec */ +} /* namespace fec */ } /* namespace gr */ #endif /* INCLUDED_FEC_TAGGED_DECODER_H */ diff --git a/gr-fec/include/gnuradio/fec/tagged_encoder.h b/gr-fec/include/gnuradio/fec/tagged_encoder.h index 90cb16e8e4..6a65189d7a 100644 --- a/gr-fec/include/gnuradio/fec/tagged_encoder.h +++ b/gr-fec/include/gnuradio/fec/tagged_encoder.h @@ -29,51 +29,51 @@ #include <boost/shared_ptr.hpp> namespace gr { - namespace fec { +namespace fec { + +/*! + * \brief Creates the encoder block for use in GNU Radio + * flowgraphs from a given FECAPI object derived from the + * generic_encoder class. + * \ingroup error_coding_blk + * + * \details + * + * Generally, we would use the fec.extended_encoder Python + * implementation to instantiate this. The extended_encoder wraps + * up a few more details, like taking care of puncturing as well + * as the encoder itself. + */ +class FEC_API tagged_encoder : virtual public tagged_stream_block +{ +public: + typedef boost::shared_ptr<tagged_encoder> sptr; /*! - * \brief Creates the encoder block for use in GNU Radio - * flowgraphs from a given FECAPI object derived from the - * generic_encoder class. - * \ingroup error_coding_blk - * - * \details + * Build the FEC encoder block from an FECAPI encoder object. * - * Generally, we would use the fec.extended_encoder Python - * implementation to instantiate this. The extended_encoder wraps - * up a few more details, like taking care of puncturing as well - * as the encoder itself. + * \param my_encoder An FECAPI encoder object child of the generic_encoder class. + * \param input_item_size size of a block of data for the encoder. + * \param output_item_size size of a block of data the encoder will produce. + * \param lengthtagname Key name of the tagged stream frame size. + * \param mtu The Maximum Transmission Unit (MTU) of the input + * frame that the block will be able to + * process. Specified in bytes and defaults to 1500. */ - class FEC_API tagged_encoder : virtual public tagged_stream_block - { - public: - typedef boost::shared_ptr<tagged_encoder> sptr; - - /*! - * Build the FEC encoder block from an FECAPI encoder object. - * - * \param my_encoder An FECAPI encoder object child of the generic_encoder class. - * \param input_item_size size of a block of data for the encoder. - * \param output_item_size size of a block of data the encoder will produce. - * \param lengthtagname Key name of the tagged stream frame size. - * \param mtu The Maximum Transmission Unit (MTU) of the input - * frame that the block will be able to - * process. Specified in bytes and defaults to 1500. - */ - static sptr make(generic_encoder::sptr my_encoder, - size_t input_item_size, - size_t output_item_size, - const std::string& lengthtagname="packet_len", - int mtu=1500); + static sptr make(generic_encoder::sptr my_encoder, + size_t input_item_size, + size_t output_item_size, + const std::string& lengthtagname = "packet_len", + int mtu = 1500); - virtual int work(int noutput_items, - gr_vector_int& ninput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) = 0; - virtual int calculate_output_stream_length(const gr_vector_int &ninput_items) = 0; - }; + virtual int work(int noutput_items, + gr_vector_int& ninput_items, + gr_vector_const_void_star& input_items, + gr_vector_void_star& output_items) = 0; + virtual int calculate_output_stream_length(const gr_vector_int& ninput_items) = 0; +}; - } /* namespace fec */ +} /* namespace fec */ } /* namespace gr */ #endif /* INCLUDED_FEC_TAGGED_ENCODER_H */ diff --git a/gr-fec/include/gnuradio/fec/tpc_common.h b/gr-fec/include/gnuradio/fec/tpc_common.h index 1e511734d8..fadb4cb9f7 100644 --- a/gr-fec/include/gnuradio/fec/tpc_common.h +++ b/gr-fec/include/gnuradio/fec/tpc_common.h @@ -26,25 +26,32 @@ #include <vector> namespace gr { -namespace fec { +namespace fec { -class tpc_common { +class tpc_common +{ public: - static int parity_counter( int symbol, int length ); - static void rsc_enc_bit(int input, int state_in, std::vector<int> g, int KK, int nn, - std::vector< std::vector<int> > &output, std::vector< std::vector<int> > &nextStates); - static void precomputeStateTransitionMatrix_RSCPoly( - int numStates, - std::vector<int> g, - int KK, - int nn, - std::vector< std::vector<int> > &output, - std::vector< std::vector<int> > &nextStates); - static void rsc_tail( std::vector<int> &tail_p, std::vector<int> g, int max_states, int mm ); - static void itob(std::vector<int> &binVec, int symbol, int length); + static int parity_counter(int symbol, int length); + static void rsc_enc_bit(int input, + int state_in, + std::vector<int> g, + int KK, + int nn, + std::vector<std::vector<int>>& output, + std::vector<std::vector<int>>& nextStates); + static void + precomputeStateTransitionMatrix_RSCPoly(int numStates, + std::vector<int> g, + int KK, + int nn, + std::vector<std::vector<int>>& output, + std::vector<std::vector<int>>& nextStates); + static void + rsc_tail(std::vector<int>& tail_p, std::vector<int> g, int max_states, int mm); + static void itob(std::vector<int>& binVec, int symbol, int length); }; -} -} +} // namespace fec +} // namespace gr -#endif /* INCLUDED_TPC_COMMON_H */ +#endif /* INCLUDED_TPC_COMMON_H */ diff --git a/gr-fec/include/gnuradio/fec/tpc_decoder.h b/gr-fec/include/gnuradio/fec/tpc_decoder.h index 13d7141819..fd7579b3c4 100644 --- a/gr-fec/include/gnuradio/fec/tpc_decoder.h +++ b/gr-fec/include/gnuradio/fec/tpc_decoder.h @@ -32,22 +32,30 @@ typedef unsigned char OUTPUT_DATATYPE; #include <vector> namespace gr { - namespace fec { +namespace fec { #define MAXLOG 1e7 -class FEC_API tpc_decoder : public generic_decoder { - //private constructor - tpc_decoder (std::vector<int> row_polys, std::vector<int> col_polys, int krow, int kcol, int bval, int qval, int max_iter, int decoder_type); - - //plug into the generic fec api +class FEC_API tpc_decoder : public generic_decoder +{ + // private constructor + tpc_decoder(std::vector<int> row_polys, + std::vector<int> col_polys, + int krow, + int kcol, + int bval, + int qval, + int max_iter, + int decoder_type); + + // plug into the generic fec api int get_history(); - float get_shift(); - int get_input_item_size(); - int get_output_item_size(); - const char* get_conversion(); - void generic_work(void *inBuffer, void *outbuffer); + float get_shift(); + int get_input_item_size(); + int get_output_item_size(); + const char* get_conversion(); + void generic_work(void* inBuffer, void* outbuffer); int get_output_size(); int get_input_size(); @@ -65,11 +73,11 @@ class FEC_API tpc_decoder : public generic_decoder { // store the state transitions & outputs int rowNumStates; - std::vector< std::vector<int> > rowOutputs; - std::vector< std::vector<int> > rowNextStates; + std::vector<std::vector<int>> rowOutputs; + std::vector<std::vector<int>> rowNextStates; int colNumStates; - std::vector< std::vector<int> > colOutputs; - std::vector< std::vector<int> > colNextStates; + std::vector<std::vector<int>> colOutputs; + std::vector<std::vector<int>> colNextStates; int rowEncoder_K; int rowEncoder_n; @@ -88,8 +96,8 @@ class FEC_API tpc_decoder : public generic_decoder { // memory allocated for processing int inputSizeWithPad; - std::vector< std::vector<float> > channel_llr; - std::vector< std::vector<float> > Z; + std::vector<std::vector<float>> channel_llr; + std::vector<std::vector<float>> Z; std::vector<float> extrinsic_info; std::vector<float> input_u_rows; std::vector<float> input_u_cols; @@ -106,11 +114,11 @@ class FEC_API tpc_decoder : public generic_decoder { bool earlyExit; - FILE *fp; + FILE* fp; // soft input soft output decoding int mm_row, max_states_row, num_symbols_row; - std::vector< std::vector<float> > beta_row; + std::vector<std::vector<float>> beta_row; std::vector<float> alpha_prime_row; std::vector<float> alpha_row; std::vector<float> metric_c_row; @@ -120,7 +128,7 @@ class FEC_API tpc_decoder : public generic_decoder { void siso_decode_row(); int mm_col, max_states_col, num_symbols_col; - std::vector< std::vector<float> > beta_col; + std::vector<std::vector<float>> beta_col; std::vector<float> alpha_prime_col; std::vector<float> alpha_col; std::vector<float> metric_c_col; @@ -141,16 +149,24 @@ class FEC_API tpc_decoder : public generic_decoder { float log_map_lut_correction(const float delta1, const float delta2); float log_map_cfunction_correction(const float delta1, const float delta2); - template <typename T> static int sgn(T val); - - public: - static generic_decoder::sptr make (std::vector<int> row_poly, std::vector<int> col_poly, int krow, int kcol, int bval, int qval, int max_iter, int decoder_type); - ~tpc_decoder (); - double rate() { return (1.0*get_output_size() / get_input_size()); } - bool set_frame_size(unsigned int frame_size){ return false; } + template <typename T> + static int sgn(T val); + +public: + static generic_decoder::sptr make(std::vector<int> row_poly, + std::vector<int> col_poly, + int krow, + int kcol, + int bval, + int qval, + int max_iter, + int decoder_type); + ~tpc_decoder(); + double rate() { return (1.0 * get_output_size() / get_input_size()); } + bool set_frame_size(unsigned int frame_size) { return false; } }; -} -} +} // namespace fec +} // namespace gr #endif /* INCLUDED_TPC_DECODER_H */ diff --git a/gr-fec/include/gnuradio/fec/tpc_encoder.h b/gr-fec/include/gnuradio/fec/tpc_encoder.h index ab737654c0..5c0facda60 100644 --- a/gr-fec/include/gnuradio/fec/tpc_encoder.h +++ b/gr-fec/include/gnuradio/fec/tpc_encoder.h @@ -30,39 +30,45 @@ #include <vector> -namespace gr { -namespace fec { +namespace gr { +namespace fec { -class FEC_API tpc_encoder : public generic_encoder { +class FEC_API tpc_encoder : public generic_encoder +{ - //private constructor - tpc_encoder (std::vector<int> row_polys, std::vector<int> col_polys, int krow, int kcol, int bval, int qval); + // private constructor + tpc_encoder(std::vector<int> row_polys, + std::vector<int> col_polys, + int krow, + int kcol, + int bval, + int qval); - //plug into the generic fec api - void generic_work(void *inBuffer, void *outbuffer); + // plug into the generic fec api + void generic_work(void* inBuffer, void* outbuffer); int get_output_size(); int get_input_size(); std::vector<int> d_rowpolys; std::vector<int> d_colpolys; - + unsigned int d_krow; unsigned int d_kcol; - + unsigned int d_bval; unsigned int d_qval; - + // store the state transitions & outputs int rowNumStates; - std::vector< std::vector<int> > rowOutputs; - std::vector< std::vector<int> > rowNextStates; + std::vector<std::vector<int>> rowOutputs; + std::vector<std::vector<int>> rowNextStates; int colNumStates; - std::vector< std::vector<int> > colOutputs; - std::vector< std::vector<int> > colNextStates; - + std::vector<std::vector<int>> colOutputs; + std::vector<std::vector<int>> colNextStates; + std::vector<int> rowTail; std::vector<int> colTail; - + int rowEncoder_K; size_t rowEncoder_n; int rowEncoder_m; @@ -71,41 +77,45 @@ class FEC_API tpc_encoder : public generic_encoder { int colEncoder_m; int outputSize; int inputSize; - + // memory allocated for processing int inputSizeWithPad; std::vector<unsigned char> inputWithPad; - - std::vector< std::vector<uint8_t> > rowEncodedBits; + + std::vector<std::vector<uint8_t>> rowEncodedBits; std::vector<unsigned char> rowToEncode; size_t numRowsToEncode; std::vector<uint8_t> rowEncoded_block; - - std::vector< std::vector<uint8_t> > colEncodedBits; + + std::vector<std::vector<uint8_t>> colEncodedBits; std::vector<unsigned char> colToEncode; int numColsToEncode; std::vector<uint8_t> colEncoded_block; - - void block_conv_encode( std::vector<uint8_t> &output, - std::vector<uint8_t> input, - std::vector< std::vector<int> > transOutputVec, - std::vector< std::vector<int> > transNextStateVec, - std::vector<int> tail, - size_t KK, - size_t nn); - - FILE *fp; - - public: - ~tpc_encoder (); - static generic_encoder::sptr make(std::vector<int> row_poly, std::vector<int> col_poly, int krow, int kcol, int bval, int qval); - double rate() { return (1.0*get_input_size() / get_output_size()); } - bool set_frame_size( unsigned int ){ return false; } + void block_conv_encode(std::vector<uint8_t>& output, + std::vector<uint8_t> input, + std::vector<std::vector<int>> transOutputVec, + std::vector<std::vector<int>> transNextStateVec, + std::vector<int> tail, + size_t KK, + size_t nn); + + FILE* fp; + +public: + ~tpc_encoder(); + static generic_encoder::sptr make(std::vector<int> row_poly, + std::vector<int> col_poly, + int krow, + int kcol, + int bval, + int qval); + double rate() { return (1.0 * get_input_size() / get_output_size()); } + bool set_frame_size(unsigned int) { return false; } }; -} -} +} // namespace fec +} // namespace gr #endif /* INCLUDED_TPC_ENCODER_H */ diff --git a/gr-fec/include/gnuradio/fec/viterbi.h b/gr-fec/include/gnuradio/fec/viterbi.h index 4ba64ed1ed..56f2d896ce 100644 --- a/gr-fec/include/gnuradio/fec/viterbi.h +++ b/gr-fec/include/gnuradio/fec/viterbi.h @@ -30,34 +30,35 @@ #include <gnuradio/fec/api.h> namespace gr { - namespace fec { - - struct FEC_API viterbi_state { - unsigned long path; /* Decoded path to this state */ - long metric; /* Cumulative metric to this state */ - }; - - FEC_API - void gen_met(int mettab[2][256], /* Metric table */ - int amp, /* Signal amplitude */ - double esn0, /* Es/N0 ratio in dB */ - double bias, /* Metric bias */ - int scale); /* Scale factor */ - - FEC_API unsigned char - encode(unsigned char *symbols, unsigned char *data, - unsigned int nbytes,unsigned char encstate); - - FEC_API void - viterbi_chunks_init(struct viterbi_state* state); - - FEC_API void - viterbi_butterfly2(unsigned char *symbols, int mettab[2][256], - struct viterbi_state *state0, struct viterbi_state *state1); - - FEC_API unsigned char - viterbi_get_output(struct viterbi_state *state, unsigned char *outbuf); - } -} +namespace fec { + +struct FEC_API viterbi_state { + unsigned long path; /* Decoded path to this state */ + long metric; /* Cumulative metric to this state */ +}; + +FEC_API +void gen_met(int mettab[2][256], /* Metric table */ + int amp, /* Signal amplitude */ + double esn0, /* Es/N0 ratio in dB */ + double bias, /* Metric bias */ + int scale); /* Scale factor */ + +FEC_API unsigned char encode(unsigned char* symbols, + unsigned char* data, + unsigned int nbytes, + unsigned char encstate); + +FEC_API void viterbi_chunks_init(struct viterbi_state* state); + +FEC_API void viterbi_butterfly2(unsigned char* symbols, + int mettab[2][256], + struct viterbi_state* state0, + struct viterbi_state* state1); + +FEC_API unsigned char viterbi_get_output(struct viterbi_state* state, + unsigned char* outbuf); +} // namespace fec +} // namespace gr #endif /* INCLUDED_VITERBI_H */ diff --git a/gr-fec/lib/alist.cc b/gr-fec/lib/alist.cc index ac7cb3384e..6d94a95cfd 100644 --- a/gr-fec/lib/alist.cc +++ b/gr-fec/lib/alist.cc @@ -22,49 +22,40 @@ #include <gnuradio/fec/alist.h> -alist::alist(const char * fname) - : data_ok(false) { - read(fname); -} +alist::alist(const char* fname) : data_ok(false) { read(fname); } -std::vector<std::vector<char> > alist::get_matrix() { - std::vector<std::vector<char> > mat; +std::vector<std::vector<char>> alist::get_matrix() +{ + std::vector<std::vector<char>> mat; mat.resize(M); - for ( int i = 0; i < M; i++ ) { + for (int i = 0; i < M; i++) { mat[i].resize(N); - for ( int j = 0; j < N; j++ ) { + for (int j = 0; j < N; j++) { mat[i][j] = char(0); } - for ( int k = 0; k < num_mlist[i]; k++ ) { + 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_mlist() { return mlist; } -std::vector< std::vector<int> > alist::get_nlist() { - return nlist; -} +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_mlist() { return num_mlist; } -std::vector<int> alist::get_num_nlist() { - return num_nlist; -} +std::vector<int> alist::get_num_nlist() { return num_nlist; } -void alist::read(const char * fname) { +void alist::read(const char* fname) +{ std::ifstream file; std::string line; std::stringstream ss; - + file.open(fname); - if(!(file.is_open())) { + if (!(file.is_open())) { std::cout << "Could not open the file" << std::endl; } @@ -89,7 +80,7 @@ void alist::read(const char * fname) { // Parse weight of each column n std::getline(file, line); ss << line; - for (int i = 0; i < N; i++ ) { + for (int i = 0; i < N; i++) { ss >> num_nlist[i]; nlist[i].resize(num_nlist[i]); } @@ -99,7 +90,7 @@ void alist::read(const char * fname) { // Parse weight of each row m std::getline(file, line); ss << line; - for (int i = 0; i < M; i++ ) { + for (int i = 0; i < M; i++) { ss >> num_mlist[i]; mlist[i].resize(num_mlist[i]); } @@ -132,7 +123,7 @@ void alist::read(const char * fname) { data_ok = true; } -void alist::write(const char * fname) const +void alist::write(const char* fname) const { if (!data_ok) { std::cout << "Data not ok, exiting" << std::endl; @@ -172,23 +163,16 @@ void alist::write(const char * fname) const file.close(); } -int alist::get_N() { - return N; -} +int alist::get_N() { return N; } -int alist::get_M() { - return M; -} +int alist::get_M() { return M; } -int alist::get_max_num_nlist() { - return max_num_nlist; -} +int alist::get_max_num_nlist() { return max_num_nlist; } -int alist::get_max_num_mlist() { - return max_num_mlist; -} +int alist::get_max_num_mlist() { return max_num_mlist; } -void alist::print_nlist_i(int column) { +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] << ", "; @@ -196,7 +180,8 @@ void alist::print_nlist_i(int column) { std::cout << nlist[column][num_nlist[column] - 1] << std::endl; } -void alist::print_mlist_i(int row) { +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] << ", "; diff --git a/gr-fec/lib/async_decoder_impl.cc b/gr-fec/lib/async_decoder_impl.cc index 4f563d349e..c8db512068 100644 --- a/gr-fec/lib/async_decoder_impl.cc +++ b/gr-fec/lib/async_decoder_impl.cc @@ -30,213 +30,206 @@ #include <stdio.h> namespace gr { - namespace fec { - - async_decoder::sptr - async_decoder::make(generic_decoder::sptr my_decoder, - bool packed, bool rev_pack, - int mtu) - { - return gnuradio::get_initial_sptr - (new async_decoder_impl(my_decoder, packed, rev_pack, mtu)); +namespace fec { + +async_decoder::sptr +async_decoder::make(generic_decoder::sptr my_decoder, bool packed, bool rev_pack, int mtu) +{ + return gnuradio::get_initial_sptr( + new async_decoder_impl(my_decoder, packed, rev_pack, mtu)); +} + +async_decoder_impl::async_decoder_impl(generic_decoder::sptr my_decoder, + bool packed, + bool rev_pack, + int mtu) + : block("async_decoder", io_signature::make(0, 0, 0), io_signature::make(0, 0, 0)) +{ + d_in_port = pmt::mp("in"); + d_out_port = pmt::mp("out"); + + d_decoder = my_decoder; + + if (d_decoder->get_history() > 0) { + throw std::runtime_error("async_decoder deploment does not support decoders with " + "history requirements."); } - async_decoder_impl::async_decoder_impl(generic_decoder::sptr my_decoder, - bool packed, bool rev_pack, - int mtu) - : block("async_decoder", - io_signature::make(0,0,0), - io_signature::make(0,0,0)) - { - d_in_port = pmt::mp("in"); - d_out_port = pmt::mp("out"); + d_packed = packed; + d_rev_pack = rev_pack; + d_mtu = mtu; - d_decoder = my_decoder; + message_port_register_in(d_in_port); + message_port_register_out(d_out_port); - if(d_decoder->get_history() > 0) { - throw std::runtime_error("async_decoder deploment does not support decoders with history requirements."); - } + if (d_packed) { + d_pack = new blocks::kernel::pack_k_bits(8); + set_msg_handler(d_in_port, + boost::bind(&async_decoder_impl::decode_packed, this, _1)); + } else { + set_msg_handler(d_in_port, + boost::bind(&async_decoder_impl::decode_unpacked, this, _1)); + } - d_packed = packed; - d_rev_pack = rev_pack; - d_mtu = mtu; + // The maximum frame size is set by the initial frame size of the decoder. + d_max_bits_in = d_mtu * 8 * 1.0 / d_decoder->rate(); + d_tmp_f32 = (float*)volk_malloc(d_max_bits_in * sizeof(float), volk_get_alignment()); - message_port_register_in(d_in_port); - message_port_register_out(d_out_port); + if (strncmp(d_decoder->get_input_conversion(), "uchar", 5) == 0) { + d_tmp_u8 = + (int8_t*)volk_malloc(d_max_bits_in * sizeof(uint8_t), volk_get_alignment()); + } - if(d_packed) { - d_pack = new blocks::kernel::pack_k_bits(8); - set_msg_handler(d_in_port, boost::bind(&async_decoder_impl::decode_packed, this ,_1)); - } - else { - set_msg_handler(d_in_port, boost::bind(&async_decoder_impl::decode_unpacked, this ,_1)); - } - - // The maximum frame size is set by the initial frame size of the decoder. - d_max_bits_in = d_mtu*8 * 1.0/d_decoder->rate(); - d_tmp_f32 = (float*)volk_malloc(d_max_bits_in*sizeof(float), - volk_get_alignment()); - - if(strncmp(d_decoder->get_input_conversion(), "uchar", 5) == 0) { - d_tmp_u8 = (int8_t*)volk_malloc(d_max_bits_in*sizeof(uint8_t), - volk_get_alignment()); - } - - if(d_packed) { - int max_bits_out = d_mtu*8; - d_bits_out = (uint8_t*)volk_malloc(max_bits_out*sizeof(uint8_t), - volk_get_alignment()); - } + if (d_packed) { + int max_bits_out = d_mtu * 8; + d_bits_out = + (uint8_t*)volk_malloc(max_bits_out * sizeof(uint8_t), volk_get_alignment()); } +} - async_decoder_impl::~async_decoder_impl() - { - if(d_packed) { +async_decoder_impl::~async_decoder_impl() +{ + if (d_packed) { delete d_pack; volk_free(d_bits_out); - } + } - volk_free(d_tmp_f32); + volk_free(d_tmp_f32); - if(strncmp(d_decoder->get_input_conversion(), "uchar", 5) == 0) { + if (strncmp(d_decoder->get_input_conversion(), "uchar", 5) == 0) { volk_free(d_tmp_u8); - } + } +} + +void async_decoder_impl::decode_unpacked(pmt::pmt_t msg) +{ + // extract input pdu + pmt::pmt_t meta(pmt::car(msg)); + pmt::pmt_t bits(pmt::cdr(msg)); + + // Watch out for this diff. It might be over-specializing to the + // CC decoder in terminated mode that has an extra rate(K-1) + // bits added on to the transmitted frame. + int diff = + d_decoder->rate() * d_decoder->get_input_size() - d_decoder->get_output_size(); + + size_t nbits_in = pmt::length(bits); + size_t nbits_out = 0; + size_t nblocks = 1; + bool variable_frame_size = d_decoder->set_frame_size(nbits_in * d_decoder->rate()); + + // Check here if the frame size is larger than what we've + // allocated for in the constructor. + if (variable_frame_size && (nbits_in > d_max_bits_in)) { + throw std::runtime_error( + "async_decoder: Received frame larger than max frame size."); } - void - async_decoder_impl::decode_unpacked(pmt::pmt_t msg) - { - // extract input pdu - pmt::pmt_t meta(pmt::car(msg)); - pmt::pmt_t bits(pmt::cdr(msg)); - - // Watch out for this diff. It might be over-specializing to the - // CC decoder in terminated mode that has an extra rate(K-1) - // bits added on to the transmitted frame. - int diff = d_decoder->rate()*d_decoder->get_input_size() - d_decoder->get_output_size(); - - size_t nbits_in = pmt::length(bits); - size_t nbits_out = 0; - size_t nblocks = 1; - bool variable_frame_size = d_decoder->set_frame_size(nbits_in*d_decoder->rate()); - - // Check here if the frame size is larger than what we've - // allocated for in the constructor. - if(variable_frame_size && (nbits_in > d_max_bits_in)) { - throw std::runtime_error("async_decoder: Received frame larger than max frame size."); - } - - // set up nbits_out - if(variable_frame_size){ - nbits_out = nbits_in*d_decoder->rate() - diff; - } - else { + // 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!"); + 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); - pmt::pmt_t outvec(pmt::make_u8vector(nbits_out, 0x00)); - uint8_t* u8out = pmt::u8vector_writable_elements(outvec, o0); + size_t o0(0); + const float* f32in = pmt::f32vector_elements(bits, o0); + pmt::pmt_t outvec(pmt::make_u8vector(nbits_out, 0x00)); + uint8_t* u8out = pmt::u8vector_writable_elements(outvec, o0); - if(strncmp(d_decoder->get_input_conversion(), "uchar", 5) == 0) { + if (strncmp(d_decoder->get_input_conversion(), "uchar", 5) == 0) { volk_32f_s32f_multiply_32f(d_tmp_f32, f32in, 48.0f, nbits_in); - } - else { - memcpy(d_tmp_f32, f32in, nbits_in*sizeof(float)); - } + } else { + memcpy(d_tmp_f32, f32in, nbits_in * sizeof(float)); + } - if(d_decoder->get_shift() != 0) { - for(size_t n = 0; n < nbits_in; n++) - d_tmp_f32[n] += d_decoder->get_shift(); - } + if (d_decoder->get_shift() != 0) { + for (size_t n = 0; n < nbits_in; n++) + d_tmp_f32[n] += d_decoder->get_shift(); + } - if(strncmp(d_decoder->get_input_conversion(), "uchar", 5) == 0) { - //volk_32f_s32f_convert_8i(d_tmp_u8, d_tmp_f32, 1, nbits_in); - for(size_t n = 0; n < nbits_in; n++) - d_tmp_u8[n] = static_cast<uint8_t>(d_tmp_f32[n]); + if (strncmp(d_decoder->get_input_conversion(), "uchar", 5) == 0) { + // volk_32f_s32f_convert_8i(d_tmp_u8, d_tmp_f32, 1, nbits_in); + for (size_t n = 0; n < nbits_in; n++) + d_tmp_u8[n] = static_cast<uint8_t>(d_tmp_f32[n]); d_decoder->generic_work((void*)d_tmp_u8, (void*)u8out); - } - else { - 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()]); + } else { + 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()]); } - } - - static const pmt::pmt_t iterations_key = pmt::mp("iterations"); - meta = pmt::dict_add(meta, iterations_key, pmt::mp(d_decoder->get_iterations()) ); - message_port_pub(d_out_port, pmt::cons(meta, outvec)); } - void - async_decoder_impl::decode_packed(pmt::pmt_t msg) - { - // extract input pdu - pmt::pmt_t meta(pmt::car(msg)); - pmt::pmt_t bits(pmt::cdr(msg)); - - size_t o0 = 0; - size_t nbits_in = pmt::length(bits); - int nbits_out = nbits_in*d_decoder->rate(); - int nbytes_out = nbits_out/8; - - // Check here if the frame size is larger than what we've - // allocated for in the constructor. - if(nbits_in > d_max_bits_in) { - throw std::runtime_error("async_decoder: Received frame larger than max frame size."); - } + static const pmt::pmt_t iterations_key = pmt::mp("iterations"); + meta = pmt::dict_add(meta, iterations_key, pmt::mp(d_decoder->get_iterations())); + message_port_pub(d_out_port, pmt::cons(meta, outvec)); +} + +void async_decoder_impl::decode_packed(pmt::pmt_t msg) +{ + // extract input pdu + pmt::pmt_t meta(pmt::car(msg)); + pmt::pmt_t bits(pmt::cdr(msg)); + + size_t o0 = 0; + size_t nbits_in = pmt::length(bits); + int nbits_out = nbits_in * d_decoder->rate(); + int nbytes_out = nbits_out / 8; + + // Check here if the frame size is larger than what we've + // allocated for in the constructor. + if (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); + d_decoder->set_frame_size(nbits_out); - pmt::pmt_t outvec(pmt::make_u8vector(nbytes_out, 0x00)); - uint8_t* bytes_out = pmt::u8vector_writable_elements(outvec, o0); - const float* f32in = pmt::f32vector_elements(bits, o0); + pmt::pmt_t outvec(pmt::make_u8vector(nbytes_out, 0x00)); + uint8_t* bytes_out = pmt::u8vector_writable_elements(outvec, o0); + const float* f32in = pmt::f32vector_elements(bits, o0); - if(strncmp(d_decoder->get_input_conversion(), "uchar", 5) == 0) { + if (strncmp(d_decoder->get_input_conversion(), "uchar", 5) == 0) { volk_32f_s32f_multiply_32f(d_tmp_f32, f32in, 48.0f, nbits_in); - } - else { - memcpy(d_tmp_f32, f32in, nbits_in*sizeof(float)); - } + } else { + memcpy(d_tmp_f32, f32in, nbits_in * sizeof(float)); + } - if(d_decoder->get_shift() != 0) { - for(size_t n = 0; n < nbits_in; n++) - d_tmp_f32[n] += d_decoder->get_shift(); - } + if (d_decoder->get_shift() != 0) { + for (size_t n = 0; n < nbits_in; n++) + d_tmp_f32[n] += d_decoder->get_shift(); + } - if(strncmp(d_decoder->get_input_conversion(), "uchar", 5) == 0) { - //volk_32f_s32f_convert_8i(d_tmp_u8, d_tmp_f32, 1.0, nbits_in); - for(size_t n = 0; n < nbits_in; n++) - d_tmp_u8[n] = static_cast<uint8_t>(d_tmp_f32[n]); + if (strncmp(d_decoder->get_input_conversion(), "uchar", 5) == 0) { + // volk_32f_s32f_convert_8i(d_tmp_u8, d_tmp_f32, 1.0, nbits_in); + for (size_t n = 0; n < nbits_in; n++) + d_tmp_u8[n] = static_cast<uint8_t>(d_tmp_f32[n]); d_decoder->generic_work((void*)d_tmp_u8, (void*)d_bits_out); - } - else { + } else { d_decoder->generic_work((void*)d_tmp_f32, (void*)d_bits_out); - } + } - if(d_rev_pack) + if (d_rev_pack) d_pack->pack_rev(bytes_out, d_bits_out, nbytes_out); - else + else d_pack->pack(bytes_out, d_bits_out, nbytes_out); - message_port_pub(d_out_port, pmt::cons(meta, outvec)); - } + message_port_pub(d_out_port, pmt::cons(meta, outvec)); +} - int - async_decoder_impl::general_work(int noutput_items, +int async_decoder_impl::general_work(int noutput_items, gr_vector_int& ninput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) - { - return noutput_items; - } + gr_vector_const_void_star& input_items, + gr_vector_void_star& output_items) +{ + return noutput_items; +} - } /* namespace fec */ +} /* namespace fec */ } /* namespace gr */ diff --git a/gr-fec/lib/async_decoder_impl.h b/gr-fec/lib/async_decoder_impl.h index bb108d5cad..d3bf0adb31 100644 --- a/gr-fec/lib/async_decoder_impl.h +++ b/gr-fec/lib/async_decoder_impl.h @@ -27,43 +27,44 @@ #include <gnuradio/blocks/pack_k_bits.h> namespace gr { - namespace fec { +namespace fec { - class FEC_API async_decoder_impl : public async_decoder - { - private: - generic_decoder::sptr d_decoder; +class FEC_API async_decoder_impl : public async_decoder +{ +private: + generic_decoder::sptr d_decoder; - pmt::pmt_t d_in_port; - pmt::pmt_t d_out_port; + pmt::pmt_t d_in_port; + pmt::pmt_t d_out_port; - blocks::kernel::pack_k_bits *d_pack; + blocks::kernel::pack_k_bits* d_pack; - bool d_packed; - bool d_rev_pack; - int d_mtu; + bool d_packed; + bool d_rev_pack; + int d_mtu; - size_t d_max_bits_in; - float *d_tmp_f32; - int8_t *d_tmp_u8; - uint8_t *d_bits_out; + size_t d_max_bits_in; + float* d_tmp_f32; + int8_t* d_tmp_u8; + uint8_t* d_bits_out; - void decode_packed(pmt::pmt_t msg); - void decode_unpacked(pmt::pmt_t msg); + void decode_packed(pmt::pmt_t msg); + void decode_unpacked(pmt::pmt_t msg); - public: - async_decoder_impl(generic_decoder::sptr my_decoder, - bool packed=false, bool rev_pack=true, - int mtu=1500); - ~async_decoder_impl(); +public: + async_decoder_impl(generic_decoder::sptr my_decoder, + bool packed = false, + bool rev_pack = true, + int mtu = 1500); + ~async_decoder_impl(); - int general_work(int noutput_items, - gr_vector_int& ninput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); - }; + int general_work(int noutput_items, + gr_vector_int& ninput_items, + gr_vector_const_void_star& input_items, + gr_vector_void_star& output_items); +}; - } /* namespace fec */ +} /* namespace fec */ } /* namespace gr */ #endif /* INCLUDED_FEC_ASYNC_DECODER_IMPL_H */ diff --git a/gr-fec/lib/async_encoder_impl.cc b/gr-fec/lib/async_encoder_impl.cc index c7eb3bfb9b..5454388de1 100644 --- a/gr-fec/lib/async_encoder_impl.cc +++ b/gr-fec/lib/async_encoder_impl.cc @@ -30,189 +30,189 @@ #include <stdio.h> namespace gr { - namespace fec { - - async_encoder::sptr - async_encoder::make(generic_encoder::sptr my_encoder, - bool packed, bool rev_unpack, bool rev_pack, - int mtu) - { - return gnuradio::get_initial_sptr - (new async_encoder_impl(my_encoder, packed, rev_unpack, rev_pack, mtu)); - } - - async_encoder_impl::async_encoder_impl(generic_encoder::sptr my_encoder, - bool packed, bool rev_unpack, bool rev_pack, - int mtu) - : block("async_encoder", - io_signature::make(0,0,0), - io_signature::make(0,0,0)) - { - d_in_port = pmt::mp("in"); - d_out_port = pmt::mp("out"); - - d_encoder = my_encoder; - - d_packed = packed; - d_rev_unpack = rev_unpack; - d_rev_pack = rev_pack; - d_mtu = mtu; - - message_port_register_in(d_in_port); - message_port_register_out(d_out_port); - - if(d_packed) { - set_msg_handler(d_in_port, boost::bind(&async_encoder_impl::encode_packed, this ,_1) ); +namespace fec { + +async_encoder::sptr async_encoder::make(generic_encoder::sptr my_encoder, + bool packed, + bool rev_unpack, + bool rev_pack, + int mtu) +{ + return gnuradio::get_initial_sptr( + new async_encoder_impl(my_encoder, packed, rev_unpack, rev_pack, mtu)); +} + +async_encoder_impl::async_encoder_impl(generic_encoder::sptr my_encoder, + bool packed, + bool rev_unpack, + bool rev_pack, + int mtu) + : block("async_encoder", io_signature::make(0, 0, 0), io_signature::make(0, 0, 0)) +{ + d_in_port = pmt::mp("in"); + d_out_port = pmt::mp("out"); + + d_encoder = my_encoder; + + d_packed = packed; + d_rev_unpack = rev_unpack; + d_rev_pack = rev_pack; + d_mtu = mtu; + + message_port_register_in(d_in_port); + message_port_register_out(d_out_port); + + if (d_packed) { + set_msg_handler(d_in_port, + boost::bind(&async_encoder_impl::encode_packed, this, _1)); d_unpack = new blocks::kernel::unpack_k_bits(8); int max_bits_out = d_encoder->rate() * d_mtu * 8; - d_bits_out = (uint8_t*)volk_malloc(max_bits_out*sizeof(uint8_t), - volk_get_alignment()); + d_bits_out = + (uint8_t*)volk_malloc(max_bits_out * sizeof(uint8_t), volk_get_alignment()); - } - else { - set_msg_handler(d_in_port, boost::bind(&async_encoder_impl::encode_unpacked, this ,_1) ); - } + } else { + set_msg_handler(d_in_port, + boost::bind(&async_encoder_impl::encode_unpacked, this, _1)); + } - if(d_packed || (strncmp(d_encoder->get_input_conversion(), "pack", 4) == 0)) { + if (d_packed || (strncmp(d_encoder->get_input_conversion(), "pack", 4) == 0)) { // encode_unpacked: if input conversion is 'pack', pack the input bits // encode_packed: used to repack the output d_pack = new blocks::kernel::pack_k_bits(8); // encode_unpacked: Holds packed bits in when input conversion is packed // encode_packed: holds the output bits of the encoder to be packed - int max_bits_in = d_mtu*8; - d_bits_in = (uint8_t*)volk_malloc(max_bits_in*sizeof(uint8_t), - volk_get_alignment()); - } + int max_bits_in = d_mtu * 8; + d_bits_in = + (uint8_t*)volk_malloc(max_bits_in * sizeof(uint8_t), volk_get_alignment()); } +} - async_encoder_impl::~async_encoder_impl() - { - if(d_packed) { +async_encoder_impl::~async_encoder_impl() +{ + if (d_packed) { delete d_unpack; volk_free(d_bits_out); - } + } - if(d_packed || (strncmp(d_encoder->get_input_conversion(), "pack", 4) == 0)) { + if (d_packed || (strncmp(d_encoder->get_input_conversion(), "pack", 4) == 0)) { delete d_pack; volk_free(d_bits_in); - } } +} - void - async_encoder_impl::encode_unpacked(pmt::pmt_t msg) - { - // extract input pdu - pmt::pmt_t meta(pmt::car(msg)); - pmt::pmt_t bits(pmt::cdr(msg)); +void async_encoder_impl::encode_unpacked(pmt::pmt_t msg) +{ + // extract input pdu + pmt::pmt_t meta(pmt::car(msg)); + pmt::pmt_t bits(pmt::cdr(msg)); - size_t o0 = 0; - int nbits_in = pmt::length(bits); - if(nbits_in > (d_mtu*8)) { + size_t o0 = 0; + int nbits_in = pmt::length(bits); + if (nbits_in > (d_mtu * 8)) { throw std::runtime_error("async_encoder: received message larger than the MTU."); - } + } - const uint8_t* bits_in = pmt::u8vector_elements(bits, o0); + const uint8_t* bits_in = pmt::u8vector_elements(bits, o0); - bool variable_framesize = d_encoder->set_frame_size(nbits_in); - int nbits_out = 0; - int nblocks = 1; - if( variable_framesize ){ + bool variable_framesize = d_encoder->set_frame_size(nbits_in); + int nbits_out = 0; + int nblocks = 1; + if (variable_framesize) { nbits_out = d_encoder->get_output_size(); - } else { + } else { nblocks = nbits_in / d_encoder->get_input_size(); - if( nblocks * d_encoder->get_input_size() != nbits_in ){ + if (nblocks * d_encoder->get_input_size() != nbits_in) { printf("nblocks: %u, in_block_size: %d, got_input_size: %d\n", - nblocks, d_encoder->get_input_size(), nbits_in); + 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(); } + nbits_out = nblocks * d_encoder->get_output_size(); + } - // buffers for output bits to go to - pmt::pmt_t outvec = pmt::make_u8vector(nbits_out, 0x00); - uint8_t* bits_out = pmt::u8vector_writable_elements(outvec, o0); + // buffers for output bits to go to + pmt::pmt_t outvec = pmt::make_u8vector(nbits_out, 0x00); + uint8_t* bits_out = pmt::u8vector_writable_elements(outvec, o0); - if(strncmp(d_encoder->get_input_conversion(), "pack", 4) == 0) { - d_pack->pack(d_bits_in, bits_in, nbits_in/8); + if (strncmp(d_encoder->get_input_conversion(), "pack", 4) == 0) { + d_pack->pack(d_bits_in, bits_in, nbits_in / 8); d_encoder->generic_work((void*)d_bits_in, (void*)bits_out); - } - else { - for(int 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); - message_port_pub(d_out_port, msg_pair); + } else { + for (int 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()]); + } } - void - async_encoder_impl::encode_packed(pmt::pmt_t msg) - { - // extract input pdu - pmt::pmt_t meta(pmt::car(msg)); - pmt::pmt_t bytes(pmt::cdr(msg)); + pmt::pmt_t msg_pair = pmt::cons(meta, outvec); + message_port_pub(d_out_port, msg_pair); +} + +void async_encoder_impl::encode_packed(pmt::pmt_t msg) +{ + // extract input pdu + pmt::pmt_t meta(pmt::car(msg)); + pmt::pmt_t bytes(pmt::cdr(msg)); - size_t o0 = 0; - int nbytes_in = pmt::length(bytes); - if(nbytes_in > d_mtu) { + size_t o0 = 0; + int nbytes_in = pmt::length(bytes); + if (nbytes_in > d_mtu) { throw std::runtime_error("async_encoder: received message larger than the MTU."); - } + } - int nbits_in = 8*nbytes_in; - const uint8_t* bytes_in = pmt::u8vector_elements(bytes, o0); + int nbits_in = 8 * nbytes_in; + const uint8_t* bytes_in = pmt::u8vector_elements(bytes, o0); - d_encoder->set_frame_size(nbits_in); + d_encoder->set_frame_size(nbits_in); - int nbits_out = d_encoder->get_output_size(); - int nbytes_out = nbits_out/8; + int nbits_out = d_encoder->get_output_size(); + int nbytes_out = nbits_out / 8; - if(strncmp(d_encoder->get_input_conversion(), "pack", 4) == 0) { + if (strncmp(d_encoder->get_input_conversion(), "pack", 4) == 0) { // If the input takes packed, anyways, don't go through the // unpacker. Note that if we need the unpacking to reverse, // we won't get that here and might have to correct for it in // the decoder. // d_bits_in > bytes_in, so we're abusing the existence of // this allocated memory here - memcpy(d_bits_in, bytes_in, nbytes_in*sizeof(uint8_t)); - } - else { + memcpy(d_bits_in, bytes_in, nbytes_in * sizeof(uint8_t)); + } else { // Encoder takes a stream of bits, but PDU's are received as // bytes, so we unpack them here. - if(d_rev_unpack) - d_unpack->unpack_rev(d_bits_in, bytes_in, nbytes_in); + if (d_rev_unpack) + d_unpack->unpack_rev(d_bits_in, bytes_in, nbytes_in); else - d_unpack->unpack(d_bits_in, bytes_in, nbytes_in); - } + d_unpack->unpack(d_bits_in, bytes_in, nbytes_in); + } - // buffers for output bytes to go to - pmt::pmt_t outvec = pmt::make_u8vector(nbytes_out, 0x00); - uint8_t* bytes_out = pmt::u8vector_writable_elements(outvec, o0); + // buffers for output bytes to go to + pmt::pmt_t outvec = pmt::make_u8vector(nbytes_out, 0x00); + uint8_t* bytes_out = pmt::u8vector_writable_elements(outvec, o0); - // ENCODE! - d_encoder->generic_work((void*)d_bits_in, (void*)d_bits_out); + // ENCODE! + d_encoder->generic_work((void*)d_bits_in, (void*)d_bits_out); - if(d_rev_pack) + if (d_rev_pack) d_pack->pack_rev(bytes_out, d_bits_out, nbytes_out); - else + else d_pack->pack(bytes_out, d_bits_out, nbytes_out); - pmt::pmt_t msg_pair = pmt::cons(meta, outvec); - message_port_pub(d_out_port, msg_pair); - } + pmt::pmt_t msg_pair = pmt::cons(meta, outvec); + message_port_pub(d_out_port, msg_pair); +} - int - async_encoder_impl::general_work(int noutput_items, +int async_encoder_impl::general_work(int noutput_items, gr_vector_int& ninput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) - { - return noutput_items; - } + gr_vector_const_void_star& input_items, + gr_vector_void_star& output_items) +{ + return noutput_items; +} - } /* namespace fec */ +} /* namespace fec */ } /* namespace gr */ diff --git a/gr-fec/lib/async_encoder_impl.h b/gr-fec/lib/async_encoder_impl.h index 9e130d8e79..80ae80b7d1 100644 --- a/gr-fec/lib/async_encoder_impl.h +++ b/gr-fec/lib/async_encoder_impl.h @@ -28,44 +28,45 @@ #include <gnuradio/blocks/pack_k_bits.h> namespace gr { - namespace fec { +namespace fec { - class FEC_API async_encoder_impl : public async_encoder - { - private: - generic_encoder::sptr d_encoder; +class FEC_API async_encoder_impl : public async_encoder +{ +private: + generic_encoder::sptr d_encoder; - pmt::pmt_t d_in_port; - pmt::pmt_t d_out_port; + pmt::pmt_t d_in_port; + pmt::pmt_t d_out_port; - blocks::kernel::unpack_k_bits *d_unpack; - blocks::kernel::pack_k_bits *d_pack; + blocks::kernel::unpack_k_bits* d_unpack; + blocks::kernel::pack_k_bits* d_pack; - bool d_packed; - bool d_rev_unpack; - bool d_rev_pack; - int d_mtu; + bool d_packed; + bool d_rev_unpack; + bool d_rev_pack; + int d_mtu; - uint8_t* d_bits_in; - uint8_t* d_bits_out; + uint8_t* d_bits_in; + uint8_t* d_bits_out; - void encode_packed(pmt::pmt_t msg); - void encode_unpacked(pmt::pmt_t msg); + void encode_packed(pmt::pmt_t msg); + void encode_unpacked(pmt::pmt_t msg); - public: - async_encoder_impl(generic_encoder::sptr my_encoder, - bool packed=false, - bool rev_unpack=true, bool rev_pack=true, - int mtu=1500); - ~async_encoder_impl(); +public: + async_encoder_impl(generic_encoder::sptr my_encoder, + bool packed = false, + bool rev_unpack = true, + bool rev_pack = true, + int mtu = 1500); + ~async_encoder_impl(); - int general_work(int noutput_items, - gr_vector_int& ninput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); - }; + int general_work(int noutput_items, + gr_vector_int& ninput_items, + gr_vector_const_void_star& input_items, + gr_vector_void_star& output_items); +}; - } /* namespace fec */ +} /* namespace fec */ } /* namespace gr */ #endif /* INCLUDED_FEC_ASYNC_ENCODER_IMPL_H */ diff --git a/gr-fec/lib/awgn_bp.cc b/gr-fec/lib/awgn_bp.cc index 66a50c0d56..fbb4f61767 100644 --- a/gr-fec/lib/awgn_bp.cc +++ b/gr-fec/lib/awgn_bp.cc @@ -22,7 +22,8 @@ #include <gnuradio/fec/awgn_bp.h> -awgn_bp::awgn_bp ( const GF2Mat X, float sgma) { +awgn_bp::awgn_bp(const GF2Mat X, float sgma) +{ H = X; M = H.get_M(); N = H.get_N(); @@ -37,7 +38,8 @@ awgn_bp::awgn_bp ( const GF2Mat X, float sgma) { estimate.resize(N); } -awgn_bp::awgn_bp ( alist _list, float sgma) { +awgn_bp::awgn_bp(alist _list, float sgma) +{ H = GF2Mat(_list); mlist = _list.get_mlist(); nlist = _list.get_nlist(); @@ -56,7 +58,8 @@ awgn_bp::awgn_bp ( alist _list, float sgma) { estimate.resize(N); } -void awgn_bp::set_alist_sigma(alist _list, float sgma) { +void awgn_bp::set_alist_sigma(alist _list, float sgma) +{ H = GF2Mat(_list); mlist = _list.get_mlist(); nlist = _list.get_nlist(); @@ -75,86 +78,79 @@ void awgn_bp::set_alist_sigma(alist _list, float sgma) { estimate.resize(N); } -std::vector< std::vector<double> > awgn_bp::get_Q() { - return Q; -} +std::vector<std::vector<double>> awgn_bp::get_Q() { return Q; } -std::vector< std::vector<double> > awgn_bp::get_R() { - return R; -} +std::vector<std::vector<double>> awgn_bp::get_R() { return R; } -GF2Mat awgn_bp::get_H() { - return H; -} +GF2Mat awgn_bp::get_H() { return H; } -void awgn_bp::rx_lr_calc(std::vector<float> codeword) { +void awgn_bp::rx_lr_calc(std::vector<float> codeword) +{ rx_lr.resize(N); float y; - for ( int i = 0; i < N; i++){ + for (int i = 0; i < N; i++) { y = codeword[i]; - rx_lr[i] = exp((-1*y)/(2*sigma*sigma)); + 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_rx_lr() { return rx_lr; } -std::vector<double> awgn_bp::get_lr() { - return lr; -} +std::vector<double> awgn_bp::get_lr() { return lr; } -void awgn_bp::spa_initialize() { +void awgn_bp::spa_initialize() +{ int row; - for ( int var = 0; var < N; var++ ) { - for ( int i = 0; i < num_nlist[var]; i++ ) { + 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() { +void awgn_bp::update_chks() +{ double product, _prdct; int v; - for ( int chk = 0; chk < M; chk++ ) { + 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 ); + product = product * double(2 / (1 + Q[chk][v]) - 1); } - for ( int i = 0; i < num_mlist[chk]; i++ ) { + 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)); + _prdct = product / double(2 / (1 + Q[chk][v]) - 1); + R[chk][v] = double((1 - _prdct) / (1 + _prdct)); } } } -void awgn_bp::update_vars() { +void awgn_bp::update_vars() +{ double _sum, __sum; int c; - for ( int var = 0; var < N; var++ ) { + for (int var = 0; var < N; var++) { _sum = rx_lr[var]; - for ( int i = 0; i < num_nlist[var]; i++ ) { + 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++ ) { + for (int i = 0; i < num_nlist[var]; i++) { c = nlist[var][i] - 1; - __sum = _sum/R[c][var]; + __sum = _sum / R[c][var]; Q[c][var] = __sum; } } } -std::vector<char> awgn_bp::get_estimate() { - return estimate; -} +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++ ) { +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 @@ -162,87 +158,83 @@ void awgn_bp::compute_init_estimate(std::vector<float> rx_word) { } } -void awgn_bp::decision() { - for ( int i = 0; i < N; i++ ){ - if ( lr[i] > 1 ) +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; -} +void awgn_bp::set_K(int k) { K = k; } -int awgn_bp::get_K() { - return K; -} +int awgn_bp::get_K() { return K; } -std::vector<char> awgn_bp::get_syndrome(std::vector<char> codeword) { +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; + 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> 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; + 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) { +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) ) { + for (int i = 0; i < N - K; i++) { + if (synd[i] != char(0)) { is_code = false; } } return is_code; } -bool awgn_bp::is_codeword() { +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) ) { + 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; -} +void awgn_bp::set_max_iterations(int k) { max_iterations = k; } -int awgn_bp::get_max_iterations() { - return max_iterations; -} +int awgn_bp::get_max_iterations() { return max_iterations; } -std::vector<char> awgn_bp::decode(std::vector<float> rx_word, - int *niteration) { +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 { + } else { rx_lr_calc(rx_word); spa_initialize(); while (*niteration < max_iterations) { diff --git a/gr-fec/lib/ber_bf_impl.cc b/gr-fec/lib/ber_bf_impl.cc index 5fd3ef049c..33127e4309 100644 --- a/gr-fec/lib/ber_bf_impl.cc +++ b/gr-fec/lib/ber_bf_impl.cc @@ -30,96 +30,93 @@ #include <math.h> namespace gr { - namespace fec { +namespace fec { - ber_bf::sptr - ber_bf::make(bool test_mode, int berminerrors, float ber_limit) - { - return gnuradio::get_initial_sptr - (new ber_bf_impl(test_mode, berminerrors, ber_limit)); - } +ber_bf::sptr ber_bf::make(bool test_mode, int berminerrors, float ber_limit) +{ + return gnuradio::get_initial_sptr( + new ber_bf_impl(test_mode, berminerrors, ber_limit)); +} - ber_bf_impl::ber_bf_impl(bool test_mode, int berminerrors, float ber_limit) - : block("fec_ber_bf", - io_signature::make(2, 2, sizeof(unsigned char)), - io_signature::make(1, 1, sizeof(float))), - d_total_errors(0), d_total(0), d_test_mode(test_mode), - d_berminerrors(berminerrors), d_ber_limit(ber_limit) - { - } +ber_bf_impl::ber_bf_impl(bool test_mode, int berminerrors, float ber_limit) + : block("fec_ber_bf", + io_signature::make(2, 2, sizeof(unsigned char)), + io_signature::make(1, 1, sizeof(float))), + d_total_errors(0), + d_total(0), + d_test_mode(test_mode), + d_berminerrors(berminerrors), + d_ber_limit(ber_limit) +{ +} - inline float - ber_bf_impl::calculate_log_ber() const - { - return log10(((double) d_total_errors) / (d_total * 8.0)); - } +inline float ber_bf_impl::calculate_log_ber() const +{ + return log10(((double)d_total_errors) / (d_total * 8.0)); +} - inline void - ber_bf_impl::update_counters(const int items, const unsigned char *inbuffer0, const unsigned char *inbuffer1) - { - uint32_t ret; - for(int i = 0; i < items; i++) { +inline void ber_bf_impl::update_counters(const int items, + const unsigned char* inbuffer0, + const unsigned char* inbuffer1) +{ + uint32_t ret; + for (int i = 0; i < items; i++) { volk_32u_popcnt(&ret, static_cast<uint32_t>(inbuffer0[i] ^ inbuffer1[i])); d_total_errors += ret; - } - d_total += items; } + d_total += items; +} - ber_bf_impl::~ber_bf_impl() - { - } +ber_bf_impl::~ber_bf_impl() {} + +int ber_bf_impl::general_work(int noutput_items, + gr_vector_int& ninput_items, + gr_vector_const_void_star& input_items, + gr_vector_void_star& output_items) +{ + unsigned char* inbuffer0 = (unsigned char*)input_items[0]; + unsigned char* inbuffer1 = (unsigned char*)input_items[1]; + float* outbuffer = (float*)output_items[0]; - int - ber_bf_impl::general_work(int noutput_items, gr_vector_int& ninput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) - { - unsigned char *inbuffer0 = (unsigned char *) input_items[0]; - unsigned char *inbuffer1 = (unsigned char *) input_items[1]; - float *outbuffer = (float *) output_items[0]; + int items = ninput_items[0] <= ninput_items[1] ? ninput_items[0] : ninput_items[1]; - int items = ninput_items[0] <= ninput_items[1] ? ninput_items[0] : ninput_items[1]; + if (d_test_mode) { + if (d_total_errors >= d_berminerrors) { + return WORK_DONE; + } else { + if (items > 0) { + update_counters(items, inbuffer0, inbuffer1); + } + consume_each(items); - if(d_test_mode){ - if(d_total_errors >= d_berminerrors){ - return WORK_DONE; + if (d_total_errors >= d_berminerrors) { + outbuffer[0] = calculate_log_ber(); + GR_LOG_INFO(d_logger, + boost::format(" %1% over %2% --> %3%") % d_total_errors % + (d_total * 8) % outbuffer[0]); + return 1; + } + // check for total_errors to prevent early shutdown at high SNR simulations + else if (calculate_log_ber() < d_ber_limit && d_total_errors > 0) { + GR_LOG_INFO(d_logger, " Min. BER limit reached"); + outbuffer[0] = d_ber_limit; + d_total_errors = d_berminerrors + 1; + return 1; + } else { + return 0; + } } - else{ - if(items > 0){ + } else { // streaming mode + if (items > 0) { update_counters(items, inbuffer0, inbuffer1); - } - consume_each(items); - - if(d_total_errors >= d_berminerrors){ outbuffer[0] = calculate_log_ber(); - GR_LOG_INFO(d_logger, boost::format(" %1% over %2% --> %3%") - % d_total_errors % (d_total * 8) % outbuffer[0]); - return 1; - } - // check for total_errors to prevent early shutdown at high SNR simulations - else if(calculate_log_ber() < d_ber_limit && d_total_errors > 0){ - GR_LOG_INFO(d_logger, " Min. BER limit reached"); - outbuffer[0] = d_ber_limit; - d_total_errors = d_berminerrors + 1; + consume_each(items); return 1; - } - else{ + } else { return 0; - } - } - } - else{ // streaming mode - if(items > 0){ - update_counters(items, inbuffer0, inbuffer1); - outbuffer[0] = calculate_log_ber(); - consume_each(items); - return 1; - } - else{ - return 0; } - } } +} - } /* namespace fec */ -}/* namespace gr */ +} /* namespace fec */ +} /* namespace gr */ diff --git a/gr-fec/lib/ber_bf_impl.h b/gr-fec/lib/ber_bf_impl.h index 75724a4281..58081e7f7b 100644 --- a/gr-fec/lib/ber_bf_impl.h +++ b/gr-fec/lib/ber_bf_impl.h @@ -26,33 +26,35 @@ #include <gnuradio/fec/ber_bf.h> namespace gr { - namespace fec { - - class FEC_API ber_bf_impl : public ber_bf - { - private: - long d_total_errors; - long d_total; - bool d_test_mode; - int d_berminerrors; - float d_ber_limit; - - inline float calculate_log_ber() const; - inline void update_counters(const int items, const unsigned char *inbuffer0, const unsigned char *inbuffer1); - - public: - ber_bf_impl(bool d_test_mode = false, int berminerrors=100, float ber_limit=-7.0); - ~ber_bf_impl(); - - int general_work(int noutput_items, - gr_vector_int& ninput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); - - long total_errors() {return d_total_errors;}; - }; - - } /* namespace fec */ +namespace fec { + +class FEC_API ber_bf_impl : public ber_bf +{ +private: + long d_total_errors; + long d_total; + bool d_test_mode; + int d_berminerrors; + float d_ber_limit; + + inline float calculate_log_ber() const; + inline void update_counters(const int items, + const unsigned char* inbuffer0, + const unsigned char* inbuffer1); + +public: + ber_bf_impl(bool d_test_mode = false, int berminerrors = 100, float ber_limit = -7.0); + ~ber_bf_impl(); + + int general_work(int noutput_items, + gr_vector_int& ninput_items, + gr_vector_const_void_star& input_items, + gr_vector_void_star& output_items); + + long total_errors() { return d_total_errors; }; +}; + +} /* namespace fec */ } /* namespace gr */ #endif /* INCLUDED_FEC_BER_BF_IMPL_H */ diff --git a/gr-fec/lib/cc_decoder_impl.cc b/gr-fec/lib/cc_decoder_impl.cc index c65e67706b..abe5ca59bc 100644 --- a/gr-fec/lib/cc_decoder_impl.cc +++ b/gr-fec/lib/cc_decoder_impl.cc @@ -33,473 +33,455 @@ #include <vector> namespace gr { - namespace fec { - namespace code { - - generic_decoder::sptr - cc_decoder::make(int frame_size, int k, - int rate, std::vector<int> polys, - int start_state, int end_state, - cc_mode_t mode, bool padded) - { - return generic_decoder::sptr - (new cc_decoder_impl(frame_size, k, rate, polys, - start_state, end_state, mode, padded)); - } - - cc_decoder_impl::cc_decoder_impl(int frame_size, int k, - int rate, std::vector<int> polys, - int start_state, int end_state, - cc_mode_t mode, bool padded) - : generic_decoder("cc_decoder"), - d_k(k), - d_rate(rate), - d_polys(polys), - d_mode(mode), - d_padding(0), - d_start_state_chaining(start_state), - d_start_state_nonchaining(start_state), - d_end_state_nonchaining(end_state) - { - // Set max frame size here; all buffers and settings will be - // based on this value. - d_max_frame_size = frame_size; - d_frame_size = frame_size; - - // set up a padding factor. If padding, the encoded frame was exteded - // by this many bits to fit into a full byte. - if(padded && (mode == CC_TERMINATED)) { - d_padding = static_cast<int>(8.0f*ceilf(d_rate*(d_k-1)/8.0f) - (d_rate*(d_k-1))); - } - - d_vp = new struct v; - - d_numstates = 1 << (d_k - 1); - - d_decision_t_size = d_numstates/8; //packed bit array - - d_managed_in_size = 0; - switch(d_mode) { - case(CC_TAILBITING): - d_end_state = &d_end_state_chaining; - d_veclen = d_frame_size + (6 * (d_k - 1)); - d_managed_in = (unsigned char*)volk_malloc(d_veclen*d_rate*sizeof(unsigned char), - volk_get_alignment()); - d_managed_in_size = d_veclen * d_rate; - if(d_managed_in == NULL) { +namespace fec { +namespace code { + +generic_decoder::sptr cc_decoder::make(int frame_size, + int k, + int rate, + std::vector<int> polys, + int start_state, + int end_state, + cc_mode_t mode, + bool padded) +{ + return generic_decoder::sptr(new cc_decoder_impl( + frame_size, k, rate, polys, start_state, end_state, mode, padded)); +} + +cc_decoder_impl::cc_decoder_impl(int frame_size, + int k, + int rate, + std::vector<int> polys, + int start_state, + int end_state, + cc_mode_t mode, + bool padded) + : generic_decoder("cc_decoder"), + d_k(k), + d_rate(rate), + d_polys(polys), + d_mode(mode), + d_padding(0), + d_start_state_chaining(start_state), + d_start_state_nonchaining(start_state), + d_end_state_nonchaining(end_state) +{ + // Set max frame size here; all buffers and settings will be + // based on this value. + d_max_frame_size = frame_size; + d_frame_size = frame_size; + + // set up a padding factor. If padding, the encoded frame was exteded + // by this many bits to fit into a full byte. + if (padded && (mode == CC_TERMINATED)) { + d_padding = static_cast<int>(8.0f * ceilf(d_rate * (d_k - 1) / 8.0f) - + (d_rate * (d_k - 1))); + } + + d_vp = new struct v; + + d_numstates = 1 << (d_k - 1); + + d_decision_t_size = d_numstates / 8; // packed bit array + + d_managed_in_size = 0; + switch (d_mode) { + case (CC_TAILBITING): + d_end_state = &d_end_state_chaining; + d_veclen = d_frame_size + (6 * (d_k - 1)); + d_managed_in = (unsigned char*)volk_malloc( + d_veclen * d_rate * sizeof(unsigned char), volk_get_alignment()); + d_managed_in_size = d_veclen * d_rate; + if (d_managed_in == NULL) { throw std::runtime_error("cc_decoder: bad alloc for d_managed_in\n"); - } - break; - - case(CC_TRUNCATED): - d_veclen = d_frame_size; - d_end_state = &d_end_state_chaining; - break; - - case(CC_TERMINATED): - d_veclen = d_frame_size + d_k - 1; - d_end_state = (end_state == -1) ? &d_end_state_chaining : &d_end_state_nonchaining; - break; - - case(CC_STREAMING): - d_veclen = d_frame_size + d_k - 1; - d_end_state = &d_end_state_chaining; - break; - - default: - throw std::runtime_error("cc_decoder: mode not recognized"); - } - - d_vp->metrics = (unsigned char*)volk_malloc(2*sizeof(unsigned char)*d_numstates, - volk_get_alignment()); - if(d_vp->metrics == NULL) { - throw std::runtime_error("bad alloc for d_vp->metrics!\n"); } + break; - d_vp->metrics1.t = d_vp->metrics; - d_vp->metrics2.t = d_vp->metrics + d_numstates; + case (CC_TRUNCATED): + d_veclen = d_frame_size; + d_end_state = &d_end_state_chaining; + break; - d_vp->decisions = (unsigned char*)volk_malloc(sizeof(unsigned char)*d_veclen*d_decision_t_size, - volk_get_alignment()); - if(d_vp->decisions == NULL) { - throw std::runtime_error("bad alloc for d_vp->decisions!\n"); - } + case (CC_TERMINATED): + d_veclen = d_frame_size + d_k - 1; + d_end_state = + (end_state == -1) ? &d_end_state_chaining : &d_end_state_nonchaining; + break; - Branchtab = (unsigned char*)volk_malloc(sizeof(unsigned char)*d_numstates/2*rate, - volk_get_alignment()); - if(Branchtab == NULL) { - throw std::runtime_error("bad alloc for d_vp->decisions!\n"); - } - - create_viterbi(); - - if(d_k-1<8) { - d_ADDSHIFT = (8-(d_k-1)); - d_SUBSHIFT = 0; - } - else if(d_k-1>8) { - d_ADDSHIFT = 0; - d_SUBSHIFT = ((d_k-1)-8); - } - else { - d_ADDSHIFT = 0; - d_SUBSHIFT = 0; - } + case (CC_STREAMING): + d_veclen = d_frame_size + d_k - 1; + d_end_state = &d_end_state_chaining; + break; - std::map<std::string, conv_kernel> yp_kernel = boost::assign::map_list_of("k=7r=2", volk_8u_x4_conv_k7_r2_8u); + default: + throw std::runtime_error("cc_decoder: mode not recognized"); + } - std::string k_ = "k="; - std::string r_ = "r="; - - std::ostringstream kerneltype; - kerneltype << k_ << d_k << r_ << d_rate; - - d_kernel = yp_kernel[kerneltype.str()]; - if (d_kernel == NULL) { - throw std::runtime_error("cc_decoder: parameters not supported"); - } - } - - cc_decoder_impl::~cc_decoder_impl() - { - volk_free(d_vp->decisions); - volk_free(Branchtab); - volk_free(d_vp->metrics); - - delete d_vp; - - if(d_mode == CC_TAILBITING) { - volk_free(d_managed_in); - } - } - - int - cc_decoder_impl::get_output_size() - { - //unpacked bits - return d_frame_size; - } - - int - cc_decoder_impl::get_input_size() - { - if(d_mode == CC_TERMINATED) { - return d_rate * (d_frame_size + d_k - 1) + d_padding; - } - else { - return d_rate * d_frame_size; - } - } - - int - cc_decoder_impl::get_input_item_size() - { - return 1; - } - - int - cc_decoder_impl::get_history() - { - if(d_mode == CC_STREAMING) { - return d_rate * (d_k - 1); - } - else { - return 0; - } - } - - float - cc_decoder_impl::get_shift() - { - return 128.0; - } - - const char* - cc_decoder_impl::get_input_conversion() - { - return "uchar"; - } - - void - cc_decoder_impl::create_viterbi() - { - int state; - unsigned int i; - partab_init(); - for(state = 0; state < d_numstates/2; state++) { - for(i = 0; i < d_rate; i++) { - Branchtab[i*d_numstates/2+state] = (d_polys[i] < 0) ^ parity((2*state) & abs(d_polys[i])) ? 255 : 0; - } - } - - switch(d_mode) { - case(CC_STREAMING): - d_start_state = &d_start_state_chaining; - init_viterbi_unbiased(d_vp); - break; - - case(CC_TAILBITING): - d_start_state = &d_start_state_nonchaining; - init_viterbi_unbiased(d_vp); - break; - - case(CC_TRUNCATED): - case(CC_TERMINATED): - d_start_state = &d_start_state_nonchaining; - init_viterbi(d_vp, *d_start_state); - break; - - default: - throw std::runtime_error("cc_decoder: mode not recognized"); + d_vp->metrics = (unsigned char*)volk_malloc(2 * sizeof(unsigned char) * d_numstates, + volk_get_alignment()); + if (d_vp->metrics == NULL) { + throw std::runtime_error("bad alloc for d_vp->metrics!\n"); + } + + d_vp->metrics1.t = d_vp->metrics; + d_vp->metrics2.t = d_vp->metrics + d_numstates; + + d_vp->decisions = (unsigned char*)volk_malloc( + sizeof(unsigned char) * d_veclen * d_decision_t_size, volk_get_alignment()); + if (d_vp->decisions == NULL) { + throw std::runtime_error("bad alloc for d_vp->decisions!\n"); + } + + Branchtab = (unsigned char*)volk_malloc( + sizeof(unsigned char) * d_numstates / 2 * rate, volk_get_alignment()); + if (Branchtab == NULL) { + throw std::runtime_error("bad alloc for d_vp->decisions!\n"); + } + + create_viterbi(); + + if (d_k - 1 < 8) { + d_ADDSHIFT = (8 - (d_k - 1)); + d_SUBSHIFT = 0; + } else if (d_k - 1 > 8) { + d_ADDSHIFT = 0; + d_SUBSHIFT = ((d_k - 1) - 8); + } else { + d_ADDSHIFT = 0; + d_SUBSHIFT = 0; + } + + std::map<std::string, conv_kernel> yp_kernel = + boost::assign::map_list_of("k=7r=2", volk_8u_x4_conv_k7_r2_8u); + + std::string k_ = "k="; + std::string r_ = "r="; + + std::ostringstream kerneltype; + kerneltype << k_ << d_k << r_ << d_rate; + + d_kernel = yp_kernel[kerneltype.str()]; + if (d_kernel == NULL) { + throw std::runtime_error("cc_decoder: parameters not supported"); + } +} + +cc_decoder_impl::~cc_decoder_impl() +{ + volk_free(d_vp->decisions); + volk_free(Branchtab); + volk_free(d_vp->metrics); + + delete d_vp; + + if (d_mode == CC_TAILBITING) { + volk_free(d_managed_in); + } +} + +int cc_decoder_impl::get_output_size() +{ + // unpacked bits + return d_frame_size; +} + +int cc_decoder_impl::get_input_size() +{ + if (d_mode == CC_TERMINATED) { + return d_rate * (d_frame_size + d_k - 1) + d_padding; + } else { + return d_rate * d_frame_size; + } +} + +int cc_decoder_impl::get_input_item_size() { return 1; } + +int cc_decoder_impl::get_history() +{ + if (d_mode == CC_STREAMING) { + return d_rate * (d_k - 1); + } else { + return 0; + } +} + +float cc_decoder_impl::get_shift() { return 128.0; } + +const char* cc_decoder_impl::get_input_conversion() { return "uchar"; } + +void cc_decoder_impl::create_viterbi() +{ + int state; + unsigned int i; + partab_init(); + for (state = 0; state < d_numstates / 2; state++) { + for (i = 0; i < d_rate; i++) { + Branchtab[i * d_numstates / 2 + state] = + (d_polys[i] < 0) ^ parity((2 * state) & abs(d_polys[i])) ? 255 : 0; } - - return; - } - - int - cc_decoder_impl::parity(int x) - { - x ^= (x >> 16); - x ^= (x >> 8); - return parityb(x); - } - - int - cc_decoder_impl::parityb(unsigned char x) - { - return Partab[x]; - } - - void - cc_decoder_impl::partab_init(void) - { - int i,cnt,ti; - - /* Initialize parity lookup table */ - for(i=0;i<256;i++){ - cnt = 0; - ti = i; - while(ti){ - if(ti & 1) - cnt++; + } + + switch (d_mode) { + case (CC_STREAMING): + d_start_state = &d_start_state_chaining; + init_viterbi_unbiased(d_vp); + break; + + case (CC_TAILBITING): + d_start_state = &d_start_state_nonchaining; + init_viterbi_unbiased(d_vp); + break; + + case (CC_TRUNCATED): + case (CC_TERMINATED): + d_start_state = &d_start_state_nonchaining; + init_viterbi(d_vp, *d_start_state); + break; + + default: + throw std::runtime_error("cc_decoder: mode not recognized"); + } + + return; +} + +int cc_decoder_impl::parity(int x) +{ + x ^= (x >> 16); + x ^= (x >> 8); + return parityb(x); +} + +int cc_decoder_impl::parityb(unsigned char x) { return Partab[x]; } + +void cc_decoder_impl::partab_init(void) +{ + int i, cnt, ti; + + /* Initialize parity lookup table */ + for (i = 0; i < 256; i++) { + cnt = 0; + ti = i; + while (ti) { + if (ti & 1) + cnt++; ti >>= 1; - } - Partab[i] = cnt & 1; } - } - - int - cc_decoder_impl::init_viterbi(struct v* vp, int starting_state) - { - int i; - - if(vp == NULL) - return -1; - for(i = 0; i < d_numstates; i++) { - vp->metrics1.t[i] = 63; - } - - vp->old_metrics = vp->metrics1; - vp->new_metrics = vp->metrics2; - vp->old_metrics.t[starting_state & (d_numstates-1)] = 0; /* Bias known start state */ - return 0; - } - - int - cc_decoder_impl::init_viterbi_unbiased(struct v* vp) - { - int i; - - if(vp == NULL) - return -1; - for(i=0;i<d_numstates;i++) - vp->metrics1.t[i] = 31; - - vp->old_metrics = vp->metrics1; - vp->new_metrics = vp->metrics2; - //no bias step - return 0; - } - - int - cc_decoder_impl::find_endstate() - { - unsigned char* met = ((d_k + d_veclen)%2 == 0)? d_vp->new_metrics.t : d_vp->old_metrics.t; - - unsigned char min = met[0]; - int state = 0; - for(int i = 1; i < d_numstates; ++i) { - if(met[i] < min) { + Partab[i] = cnt & 1; + } +} + +int cc_decoder_impl::init_viterbi(struct v* vp, int starting_state) +{ + int i; + + if (vp == NULL) + return -1; + for (i = 0; i < d_numstates; i++) { + vp->metrics1.t[i] = 63; + } + + vp->old_metrics = vp->metrics1; + vp->new_metrics = vp->metrics2; + vp->old_metrics.t[starting_state & (d_numstates - 1)] = + 0; /* Bias known start state */ + return 0; +} + +int cc_decoder_impl::init_viterbi_unbiased(struct v* vp) +{ + int i; + + if (vp == NULL) + return -1; + for (i = 0; i < d_numstates; i++) + vp->metrics1.t[i] = 31; + + vp->old_metrics = vp->metrics1; + vp->new_metrics = vp->metrics2; + // no bias step + return 0; +} + +int cc_decoder_impl::find_endstate() +{ + unsigned char* met = + ((d_k + d_veclen) % 2 == 0) ? d_vp->new_metrics.t : d_vp->old_metrics.t; + + unsigned char min = met[0]; + int state = 0; + for (int i = 1; i < d_numstates; ++i) { + if (met[i] < min) { min = met[i]; state = i; - } - - - } - //printf("min %d\n", state); - return state; - } - - int - cc_decoder_impl::update_viterbi_blk(unsigned char* syms, int nbits) - { - unsigned char *d; - - d = d_vp->decisions; - - memset(d,0,d_decision_t_size * nbits); - - d_kernel(d_vp->new_metrics.t, d_vp->old_metrics.t, syms, - d, nbits - (d_k - 1), d_k - 1, Branchtab); - - return 0; - } - - int - cc_decoder_impl::chainback_viterbi(unsigned char* data, - unsigned int nbits, - unsigned int endstate, - unsigned int tailsize) - { - unsigned char *d; - - /* ADDSHIFT and SUBSHIFT make sure that the thing returned is a byte. */ - d = d_vp->decisions; - /* Make room beyond the end of the encoder register so we can - * accumulate a full byte of decoded data - */ - - endstate = (endstate%d_numstates) << d_ADDSHIFT; - - /* The store into data[] only needs to be done every 8 bits. - * But this avoids a conditional branch, and the writes will - * combine in the cache anyway - */ - - d += tailsize * d_decision_t_size ; /* Look past tail */ - int retval; - int dif = tailsize - (d_k - 1); - decision_t dec; - while(nbits-- > d_frame_size - (d_k - 1)) { - int k; - dec.t = &d[nbits * d_decision_t_size]; - k = (dec.w[(endstate>>d_ADDSHIFT)/32] >> ((endstate>>d_ADDSHIFT)%32)) & 1; - - endstate = (endstate >> 1) | (k << (d_k-2+d_ADDSHIFT)); - data[((nbits+dif)%d_frame_size)] = k; - - retval = endstate; - } - nbits += 1; - - while(nbits-- != 0) { - int k; - - dec.t = &d[nbits * d_decision_t_size]; - - k = (dec.w[(endstate>>d_ADDSHIFT)/32] >> ((endstate>>d_ADDSHIFT)%32)) & 1; - - endstate = (endstate >> 1) | (k << (d_k-2+d_ADDSHIFT)); - data[((nbits+dif)%d_frame_size)] = k; } - - return retval >> d_ADDSHIFT; - } - - bool - cc_decoder_impl::set_frame_size(unsigned int frame_size) - { - bool ret = true; - if(frame_size > d_max_frame_size) { - GR_LOG_INFO(d_logger, boost::format("cc_decoder: tried to set frame to %1%; max possible is %2%") \ - % frame_size % d_max_frame_size); - frame_size = d_max_frame_size; - ret = false; + } + // printf("min %d\n", state); + return state; +} + +int cc_decoder_impl::update_viterbi_blk(unsigned char* syms, int nbits) +{ + unsigned char* d; + + d = d_vp->decisions; + + memset(d, 0, d_decision_t_size * nbits); + + d_kernel(d_vp->new_metrics.t, + d_vp->old_metrics.t, + syms, + d, + nbits - (d_k - 1), + d_k - 1, + Branchtab); + + return 0; +} + +int cc_decoder_impl::chainback_viterbi(unsigned char* data, + unsigned int nbits, + unsigned int endstate, + unsigned int tailsize) +{ + unsigned char* d; + + /* ADDSHIFT and SUBSHIFT make sure that the thing returned is a byte. */ + d = d_vp->decisions; + /* Make room beyond the end of the encoder register so we can + * accumulate a full byte of decoded data + */ + + endstate = (endstate % d_numstates) << d_ADDSHIFT; + + /* The store into data[] only needs to be done every 8 bits. + * But this avoids a conditional branch, and the writes will + * combine in the cache anyway + */ + + d += tailsize * d_decision_t_size; /* Look past tail */ + int retval; + int dif = tailsize - (d_k - 1); + decision_t dec; + while (nbits-- > d_frame_size - (d_k - 1)) { + int k; + dec.t = &d[nbits * d_decision_t_size]; + k = (dec.w[(endstate >> d_ADDSHIFT) / 32] >> ((endstate >> d_ADDSHIFT) % 32)) & 1; + + endstate = (endstate >> 1) | (k << (d_k - 2 + d_ADDSHIFT)); + data[((nbits + dif) % d_frame_size)] = k; + + retval = endstate; + } + nbits += 1; + + while (nbits-- != 0) { + int k; + + dec.t = &d[nbits * d_decision_t_size]; + + k = (dec.w[(endstate >> d_ADDSHIFT) / 32] >> ((endstate >> d_ADDSHIFT) % 32)) & 1; + + endstate = (endstate >> 1) | (k << (d_k - 2 + d_ADDSHIFT)); + data[((nbits + dif) % d_frame_size)] = k; + } + + return retval >> d_ADDSHIFT; +} + +bool cc_decoder_impl::set_frame_size(unsigned int frame_size) +{ + bool ret = true; + if (frame_size > d_max_frame_size) { + GR_LOG_INFO( + d_logger, + boost::format("cc_decoder: tried to set frame to %1%; max possible is %2%") % + frame_size % d_max_frame_size); + frame_size = d_max_frame_size; + ret = false; + } + + d_frame_size = frame_size; + + switch (d_mode) { + case (CC_TAILBITING): + d_veclen = d_frame_size + (6 * (d_k - 1)); + if (d_veclen * d_rate > d_managed_in_size) { + throw std::runtime_error( + "cc_decoder: attempt to resize beyond d_managed_in buffer size!\n"); } - - d_frame_size = frame_size; - - switch(d_mode) { - case(CC_TAILBITING): - d_veclen = d_frame_size + (6 * (d_k - 1)); - if(d_veclen * d_rate > d_managed_in_size) { - throw std::runtime_error("cc_decoder: attempt to resize beyond d_managed_in buffer size!\n"); - } - break; - - case(CC_TRUNCATED): - d_veclen = d_frame_size; - break; - - case(CC_STREAMING): - d_veclen = d_frame_size + d_k - 1; - break; - - case(CC_TERMINATED): - // If the input is being padded out to a byte, we know the - // real frame size is without the padding. - d_frame_size -= d_padding * d_rate; - d_veclen = d_frame_size + d_k - 1; - break; - - default: - throw std::runtime_error("cc_decoder: mode not recognized"); - } - - return ret; - } - - double - cc_decoder_impl::rate() - { - return 1.0/static_cast<double>(d_rate); - } - - void - cc_decoder_impl::generic_work(void *inbuffer, void *outbuffer) - { - const unsigned char *in = (const unsigned char *) inbuffer; - unsigned char *out = (unsigned char *) outbuffer; - - switch(d_mode) { - - case(CC_TAILBITING): - memcpy(d_managed_in, in, d_frame_size * d_rate * sizeof(unsigned char)); - memcpy(d_managed_in + d_frame_size * d_rate * sizeof(unsigned char), in, - (d_veclen - d_frame_size) * d_rate * sizeof(unsigned char)); - update_viterbi_blk(d_managed_in, d_veclen); - d_end_state_chaining = find_endstate(); - chainback_viterbi(&out[0], d_frame_size, *d_end_state, d_veclen - d_frame_size); - init_viterbi_unbiased(d_vp); - break; - - - case(CC_TRUNCATED): - update_viterbi_blk((unsigned char*)(&in[0]), d_veclen); - d_end_state_chaining = find_endstate(); - for(unsigned int i = 0; i < d_k-1; ++i) { + break; + + case (CC_TRUNCATED): + d_veclen = d_frame_size; + break; + + case (CC_STREAMING): + d_veclen = d_frame_size + d_k - 1; + break; + + case (CC_TERMINATED): + // If the input is being padded out to a byte, we know the + // real frame size is without the padding. + d_frame_size -= d_padding * d_rate; + d_veclen = d_frame_size + d_k - 1; + break; + + default: + throw std::runtime_error("cc_decoder: mode not recognized"); + } + + return ret; +} + +double cc_decoder_impl::rate() { return 1.0 / static_cast<double>(d_rate); } + +void cc_decoder_impl::generic_work(void* inbuffer, void* outbuffer) +{ + const unsigned char* in = (const unsigned char*)inbuffer; + unsigned char* out = (unsigned char*)outbuffer; + + switch (d_mode) { + + case (CC_TAILBITING): + memcpy(d_managed_in, in, d_frame_size * d_rate * sizeof(unsigned char)); + memcpy(d_managed_in + d_frame_size * d_rate * sizeof(unsigned char), + in, + (d_veclen - d_frame_size) * d_rate * sizeof(unsigned char)); + update_viterbi_blk(d_managed_in, d_veclen); + d_end_state_chaining = find_endstate(); + chainback_viterbi(&out[0], d_frame_size, *d_end_state, d_veclen - d_frame_size); + init_viterbi_unbiased(d_vp); + break; + + + case (CC_TRUNCATED): + update_viterbi_blk((unsigned char*)(&in[0]), d_veclen); + d_end_state_chaining = find_endstate(); + for (unsigned int i = 0; i < d_k - 1; ++i) { out[d_veclen - 1 - i] = ((*d_end_state) >> i) & 1; - } - d_start_state_chaining = chainback_viterbi(&out[0], d_frame_size - (d_k - 1), - *d_end_state, d_k - 1); - init_viterbi(d_vp, *d_start_state); - break; - - case(CC_STREAMING): - case(CC_TERMINATED): - update_viterbi_blk((unsigned char*)(&in[0]), d_veclen); - d_end_state_chaining = find_endstate(); - d_start_state_chaining = chainback_viterbi(&out[0], d_frame_size, *d_end_state, - d_veclen - d_frame_size); - - init_viterbi(d_vp, *d_start_state); - break; - - default: - throw std::runtime_error("cc_decoder: mode not recognized"); } - } - - } /* namespace code */ - } /* namespace fec */ + d_start_state_chaining = + chainback_viterbi(&out[0], d_frame_size - (d_k - 1), *d_end_state, d_k - 1); + init_viterbi(d_vp, *d_start_state); + break; + + case (CC_STREAMING): + case (CC_TERMINATED): + update_viterbi_blk((unsigned char*)(&in[0]), d_veclen); + d_end_state_chaining = find_endstate(); + d_start_state_chaining = chainback_viterbi( + &out[0], d_frame_size, *d_end_state, d_veclen - d_frame_size); + + init_viterbi(d_vp, *d_start_state); + break; + + default: + throw std::runtime_error("cc_decoder: mode not recognized"); + } +} + +} /* namespace code */ +} /* namespace fec */ } /* namespace gr */ diff --git a/gr-fec/lib/cc_decoder_impl.h b/gr-fec/lib/cc_decoder_impl.h index 1015bc3d98..841c5f048c 100644 --- a/gr-fec/lib/cc_decoder_impl.h +++ b/gr-fec/lib/cc_decoder_impl.h @@ -28,76 +28,82 @@ #include <gnuradio/fec/cc_decoder.h> namespace gr { - namespace fec { - namespace code { +namespace fec { +namespace code { - class FEC_API cc_decoder_impl : public cc_decoder - { - private: - //plug into the generic fec api - int get_output_size(); - int get_input_size(); - int get_history(); - float get_shift(); - int get_input_item_size(); - const char* get_input_conversion(); - //const char* get_output_conversion(); +class FEC_API cc_decoder_impl : public cc_decoder +{ +private: + // plug into the generic fec api + int get_output_size(); + int get_input_size(); + int get_history(); + float get_shift(); + int get_input_item_size(); + const char* get_input_conversion(); + // const char* get_output_conversion(); - //everything else... - void create_viterbi(); - int init_viterbi(struct v* vp, int starting_state); - int init_viterbi_unbiased(struct v* vp); - int update_viterbi_blk(unsigned char* syms, int nbits); - int chainback_viterbi(unsigned char* data, unsigned int nbits, - unsigned int endstate, unsigned int tailsize); - int find_endstate(); + // everything else... + void create_viterbi(); + int init_viterbi(struct v* vp, int starting_state); + int init_viterbi_unbiased(struct v* vp); + int update_viterbi_blk(unsigned char* syms, int nbits); + int chainback_viterbi(unsigned char* data, + unsigned int nbits, + unsigned int endstate, + unsigned int tailsize); + int find_endstate(); - unsigned char *Branchtab; - unsigned char Partab[256]; + unsigned char* Branchtab; + unsigned char Partab[256]; - int d_ADDSHIFT; - int d_SUBSHIFT; - conv_kernel d_kernel; - unsigned int d_max_frame_size; - unsigned int d_frame_size; - unsigned int d_k; - unsigned int d_rate; - std::vector<int> d_polys; - cc_mode_t d_mode; - int d_padding; + int d_ADDSHIFT; + int d_SUBSHIFT; + conv_kernel d_kernel; + unsigned int d_max_frame_size; + unsigned int d_frame_size; + unsigned int d_k; + unsigned int d_rate; + std::vector<int> d_polys; + cc_mode_t d_mode; + int d_padding; - struct v* d_vp; - unsigned char* d_managed_in; - unsigned int d_managed_in_size; - int d_numstates; - int d_decision_t_size; - int *d_start_state; - int d_start_state_chaining; - int d_start_state_nonchaining; - int *d_end_state; - int d_end_state_chaining; - int d_end_state_nonchaining; - unsigned int d_veclen; + struct v* d_vp; + unsigned char* d_managed_in; + unsigned int d_managed_in_size; + int d_numstates; + int d_decision_t_size; + int* d_start_state; + int d_start_state_chaining; + int d_start_state_nonchaining; + int* d_end_state; + int d_end_state_chaining; + int d_end_state_nonchaining; + unsigned int d_veclen; - int parity(int x); - int parityb(unsigned char x); - void partab_init(void); + int parity(int x); + int parityb(unsigned char x); + void partab_init(void); - public: - cc_decoder_impl(int frame_size, int k, - int rate, std::vector<int> polys, - int start_state = 0, int end_state = -1, - cc_mode_t mode=CC_STREAMING, bool padded=false); - ~cc_decoder_impl(); +public: + cc_decoder_impl(int frame_size, + int k, + int rate, + std::vector<int> polys, + int start_state = 0, + int end_state = -1, + cc_mode_t mode = CC_STREAMING, + bool padded = false); + ~cc_decoder_impl(); - void generic_work(void *inbuffer, void *outbuffer); - bool set_frame_size(unsigned int frame_size); - double rate(); - }; + void generic_work(void* inbuffer, void* outbuffer); + bool set_frame_size(unsigned int frame_size); + double rate(); +}; - } /* namespace code */ - } /* namespace fec */ +} /* namespace code */ +} /* namespace fec */ } /* namespace gr */ #endif /* INCLUDED_FEC_CC_DECODER_IMPL_H */ diff --git a/gr-fec/lib/cc_encoder_impl.cc b/gr-fec/lib/cc_encoder_impl.cc index 9585d5fcd5..389a41c1c5 100644 --- a/gr-fec/lib/cc_encoder_impl.cc +++ b/gr-fec/lib/cc_encoder_impl.cc @@ -36,169 +36,160 @@ #include <gnuradio/fec/cc_common.h> namespace gr { - namespace fec { - namespace code { - - generic_encoder::sptr - cc_encoder::make(int frame_size, int k, int rate, - std::vector<int> polys, int start_state, - cc_mode_t mode, bool padded) - { - return generic_encoder::sptr - (new cc_encoder_impl(frame_size, k, rate, - polys, start_state, - mode, padded)); - } - - cc_encoder_impl::cc_encoder_impl(int frame_size, int k, int rate, - std::vector<int> polys, int start_state, - cc_mode_t mode, bool padded) - : generic_encoder("cc_encoder"), - d_rate(rate), d_k(k), d_polys(polys), - d_start_state(start_state), - d_mode(mode), d_padding(0) - { - if(static_cast<size_t>(d_rate) != d_polys.size()) { - throw std::runtime_error("cc_encoder: Number of polynomials must be the same as the value of rate"); - } - - partab_init(); - - // set up a padding factor. If padding, extends the encoding - // by this many bits to fit into a full byte. - if(padded && (mode == CC_TERMINATED)) { - d_padding = static_cast<int>(8.0f*ceilf(d_rate*(d_k-1)/8.0f) - (d_rate*(d_k-1))); - } - - d_max_frame_size = frame_size; - set_frame_size(frame_size); - } - - cc_encoder_impl::~cc_encoder_impl() - { - } - - int - cc_encoder_impl::get_output_size() - { - return d_output_size; - } - - int - cc_encoder_impl::get_input_size() - { - return d_frame_size; - } - - bool - cc_encoder_impl::set_frame_size(unsigned int frame_size) - { - bool ret = true; - if(frame_size > d_max_frame_size) { - GR_LOG_INFO(d_logger, boost::format("tried to set frame to %1%; max possible is %2%") \ - % frame_size % d_max_frame_size); - frame_size = d_max_frame_size; - ret = false; - } - - d_frame_size = frame_size; - - if(d_mode == CC_TERMINATED) { - d_output_size = d_rate * (d_frame_size + d_k - 1) + d_padding; - } - /* - else if(d_trunc_intrinsic) { - int cnt = 0; - for(int i = 0; i < d_rate; ++i) { - if (d_polys[i] != 1) { - cnt++; - } - } - d_output_size = (d_rate * (d_frame_size)) + (cnt * (d_k - 1)); +namespace fec { +namespace code { + +generic_encoder::sptr cc_encoder::make(int frame_size, + int k, + int rate, + std::vector<int> polys, + int start_state, + cc_mode_t mode, + bool padded) +{ + return generic_encoder::sptr( + new cc_encoder_impl(frame_size, k, rate, polys, start_state, mode, padded)); +} + +cc_encoder_impl::cc_encoder_impl(int frame_size, + int k, + int rate, + std::vector<int> polys, + int start_state, + cc_mode_t mode, + bool padded) + : generic_encoder("cc_encoder"), + d_rate(rate), + d_k(k), + d_polys(polys), + d_start_state(start_state), + d_mode(mode), + d_padding(0) +{ + if (static_cast<size_t>(d_rate) != d_polys.size()) { + throw std::runtime_error( + "cc_encoder: Number of polynomials must be the same as the value of rate"); + } + + partab_init(); + + // set up a padding factor. If padding, extends the encoding + // by this many bits to fit into a full byte. + if (padded && (mode == CC_TERMINATED)) { + d_padding = static_cast<int>(8.0f * ceilf(d_rate * (d_k - 1) / 8.0f) - + (d_rate * (d_k - 1))); + } + + d_max_frame_size = frame_size; + set_frame_size(frame_size); +} + +cc_encoder_impl::~cc_encoder_impl() {} + +int cc_encoder_impl::get_output_size() { return d_output_size; } + +int cc_encoder_impl::get_input_size() { return d_frame_size; } + +bool cc_encoder_impl::set_frame_size(unsigned int frame_size) +{ + bool ret = true; + if (frame_size > d_max_frame_size) { + GR_LOG_INFO(d_logger, + boost::format("tried to set frame to %1%; max possible is %2%") % + frame_size % d_max_frame_size); + frame_size = d_max_frame_size; + ret = false; + } + + d_frame_size = frame_size; + + if (d_mode == CC_TERMINATED) { + d_output_size = d_rate * (d_frame_size + d_k - 1) + d_padding; + } + /* + else if(d_trunc_intrinsic) { + int cnt = 0; + for(int i = 0; i < d_rate; ++i) { + if (d_polys[i] != 1) { + cnt++; } - */ - else { - d_output_size = d_rate * d_frame_size; - } - - return ret; - } - - double - cc_encoder_impl::rate() - { - return static_cast<double>(d_rate); } - - int - cc_encoder_impl::parity(int x) - { - x ^= (x >> 16); - x ^= (x >> 8); - return parityb(x); - } - - int - cc_encoder_impl::parityb(unsigned char x) - { - return Partab[x]; - } - - void - cc_encoder_impl::partab_init(void) - { - int i,cnt,ti; - - /* Initialize parity lookup table */ - for(i=0;i<256;i++){ - cnt = 0; - ti = i; - while(ti){ - if(ti & 1) - cnt++; + d_output_size = (d_rate * (d_frame_size)) + (cnt * (d_k - 1)); + } + */ + else { + d_output_size = d_rate * d_frame_size; + } + + return ret; +} + +double cc_encoder_impl::rate() { return static_cast<double>(d_rate); } + +int cc_encoder_impl::parity(int x) +{ + x ^= (x >> 16); + x ^= (x >> 8); + return parityb(x); +} + +int cc_encoder_impl::parityb(unsigned char x) { return Partab[x]; } + +void cc_encoder_impl::partab_init(void) +{ + int i, cnt, ti; + + /* Initialize parity lookup table */ + for (i = 0; i < 256; i++) { + cnt = 0; + ti = i; + while (ti) { + if (ti & 1) + cnt++; ti >>= 1; - } - Partab[i] = cnt & 1; } - } + Partab[i] = cnt & 1; + } +} - void - cc_encoder_impl::generic_work(void *in_buffer, void *out_buffer) - { - const unsigned char *in = (const unsigned char *) in_buffer; - unsigned char *out = (unsigned char *) out_buffer; +void cc_encoder_impl::generic_work(void* in_buffer, void* out_buffer) +{ + const unsigned char* in = (const unsigned char*)in_buffer; + unsigned char* out = (unsigned char*)out_buffer; - unsigned char my_state = d_start_state; + unsigned char my_state = d_start_state; - if(d_mode == CC_TAILBITING) { - for(unsigned int i = 0; i < d_k - 1; ++i) { - my_state = (my_state << 1) | (in[d_frame_size - (d_k - 1) + i] & 1); - } + if (d_mode == CC_TAILBITING) { + for (unsigned int i = 0; i < d_k - 1; ++i) { + my_state = (my_state << 1) | (in[d_frame_size - (d_k - 1) + i] & 1); } + } - for(unsigned int i = 0; i < d_frame_size; ++i) { - my_state = (my_state << 1) | (in[i] & 1); - for(unsigned int j = 0; j < d_rate; ++j) { - out[i * d_rate + j] = (d_polys[j] < 0) ^ parity(my_state & abs(d_polys[j])) ? 1 : 0; - } + for (unsigned int i = 0; i < d_frame_size; ++i) { + my_state = (my_state << 1) | (in[i] & 1); + for (unsigned int j = 0; j < d_rate; ++j) { + out[i * d_rate + j] = + (d_polys[j] < 0) ^ parity(my_state & abs(d_polys[j])) ? 1 : 0; } + } - if(d_mode == CC_TERMINATED) { - for(unsigned int i = 0; i < d_k - 1; ++i) { + if (d_mode == CC_TERMINATED) { + for (unsigned int i = 0; i < d_k - 1; ++i) { my_state = (my_state << 1) | ((d_start_state >> (d_k - 2 - i)) & 1); - for(unsigned int j = 0; j < d_rate; ++j) { - out[(i + d_frame_size) * d_rate + j] = (d_polys[j] < 0) ^ parity(my_state & abs(d_polys[j])) ? 1 : 0; + for (unsigned int j = 0; j < d_rate; ++j) { + out[(i + d_frame_size) * d_rate + j] = + (d_polys[j] < 0) ^ parity(my_state & abs(d_polys[j])) ? 1 : 0; } - } } + } - if(d_mode == CC_TRUNCATED) { - my_state = d_start_state; - } + if (d_mode == CC_TRUNCATED) { + my_state = d_start_state; + } - d_start_state = my_state; - } + d_start_state = my_state; +} - } /* namespace code */ - } /* namespace fec */ +} /* namespace code */ +} /* namespace fec */ } /* namespace gr */ diff --git a/gr-fec/lib/cc_encoder_impl.h b/gr-fec/lib/cc_encoder_impl.h index 887553b6fa..ce3f1020a0 100644 --- a/gr-fec/lib/cc_encoder_impl.h +++ b/gr-fec/lib/cc_encoder_impl.h @@ -28,45 +28,49 @@ p * You should have received a copy of the GNU General Public License #include <gnuradio/fec/cc_encoder.h> namespace gr { - namespace fec { - namespace code { +namespace fec { +namespace code { - class FEC_API cc_encoder_impl : public cc_encoder - { - private: - //plug into the generic fec api - void generic_work(void *inbuffer, void *outbuffer); - int get_output_size(); - int get_input_size(); +class FEC_API cc_encoder_impl : public cc_encoder +{ +private: + // plug into the generic fec api + void generic_work(void* inbuffer, void* outbuffer); + int get_output_size(); + int get_input_size(); - //everything else... - unsigned char Partab[256]; - unsigned int d_frame_size; - unsigned int d_max_frame_size; - unsigned int d_rate; - unsigned int d_k; - std::vector<int> d_polys; - int d_start_state; - cc_mode_t d_mode; - int d_padding; - int d_output_size; + // everything else... + unsigned char Partab[256]; + unsigned int d_frame_size; + unsigned int d_max_frame_size; + unsigned int d_rate; + unsigned int d_k; + std::vector<int> d_polys; + int d_start_state; + cc_mode_t d_mode; + int d_padding; + int d_output_size; - int parity(int x); - int parityb(unsigned char x); - void partab_init(void); + int parity(int x); + int parityb(unsigned char x); + void partab_init(void); - public: - cc_encoder_impl(int frame_size, int k, int rate, - std::vector<int> polys, int start_state = 0, - cc_mode_t mode=CC_STREAMING, bool padded=false); - ~cc_encoder_impl(); +public: + cc_encoder_impl(int frame_size, + int k, + int rate, + std::vector<int> polys, + int start_state = 0, + cc_mode_t mode = CC_STREAMING, + bool padded = false); + ~cc_encoder_impl(); - bool set_frame_size(unsigned int frame_size); - double rate(); - }; + bool set_frame_size(unsigned int frame_size); + double rate(); +}; - } /* namespace code */ - } /* namespace fec */ +} /* namespace code */ +} /* namespace fec */ } /* namespace gr */ #endif /* INCLUDED_FEC_CC_ENCODER_IMPL_H */ diff --git a/gr-fec/lib/ccsds_encoder_impl.cc b/gr-fec/lib/ccsds_encoder_impl.cc index 4c873a5288..9b91be4c8b 100644 --- a/gr-fec/lib/ccsds_encoder_impl.cc +++ b/gr-fec/lib/ccsds_encoder_impl.cc @@ -31,120 +31,102 @@ #include <gnuradio/fec/viterbi.h> namespace gr { - namespace fec { - namespace code { - - generic_encoder::sptr - ccsds_encoder::make(int frame_size, int start_state, - cc_mode_t mode) - { - return generic_encoder::sptr - (new ccsds_encoder_impl(frame_size, start_state, mode)); - } - - ccsds_encoder_impl::ccsds_encoder_impl(int frame_size, int start_state, - cc_mode_t mode) - : generic_encoder("ccsds_encoder"), - d_start_state(static_cast<unsigned char>(start_state)), - d_mode(mode) - { - d_max_frame_size = frame_size; - set_frame_size(frame_size); - } - - ccsds_encoder_impl::~ccsds_encoder_impl() - { - } - - int - ccsds_encoder_impl::get_output_size() - { - return d_output_size; - } - - int - ccsds_encoder_impl::get_input_size() - { - return d_frame_size/8; // packed byte input - } - - const char* - ccsds_encoder_impl::get_input_conversion() - { - // Expects packed data input; tell wrapper to pack it. - return "pack"; - } - - bool - ccsds_encoder_impl::set_frame_size(unsigned int frame_size) - { - bool ret = true; - if(frame_size > d_max_frame_size) { - GR_LOG_INFO(d_logger, boost::format("tried to set frame to %1%; max possible is %2%") \ - % frame_size % d_max_frame_size); - frame_size = d_max_frame_size; - ret = false; - } - - d_frame_size = frame_size; - - if(d_mode == CC_TERMINATED) { - d_output_size = 2*(d_frame_size + 7 - 1); - } - else { - d_output_size = 2*d_frame_size; - } - - return ret; - } - - double - ccsds_encoder_impl::rate() - { - return 0.5; - } - - void - ccsds_encoder_impl::generic_work(void *in_buffer, void *out_buffer) - { - unsigned char *in = (unsigned char*) in_buffer; - unsigned char *out = (unsigned char*) out_buffer; - - unsigned char my_state = d_start_state; - - if(d_mode == CC_TAILBITING) { - // Grab K-1 (6) bits of data from the last input byte to add - // onto the from of the encoding stream for tailbiting mode. - unsigned char sym = in[d_frame_size/8 - 1]; - for(unsigned int i = 0; i < 7 - 1; ++i) { +namespace fec { +namespace code { + +generic_encoder::sptr ccsds_encoder::make(int frame_size, int start_state, cc_mode_t mode) +{ + return generic_encoder::sptr(new ccsds_encoder_impl(frame_size, start_state, mode)); +} + +ccsds_encoder_impl::ccsds_encoder_impl(int frame_size, int start_state, cc_mode_t mode) + : generic_encoder("ccsds_encoder"), + d_start_state(static_cast<unsigned char>(start_state)), + d_mode(mode) +{ + d_max_frame_size = frame_size; + set_frame_size(frame_size); +} + +ccsds_encoder_impl::~ccsds_encoder_impl() {} + +int ccsds_encoder_impl::get_output_size() { return d_output_size; } + +int ccsds_encoder_impl::get_input_size() +{ + return d_frame_size / 8; // packed byte input +} + +const char* ccsds_encoder_impl::get_input_conversion() +{ + // Expects packed data input; tell wrapper to pack it. + return "pack"; +} + +bool ccsds_encoder_impl::set_frame_size(unsigned int frame_size) +{ + bool ret = true; + if (frame_size > d_max_frame_size) { + GR_LOG_INFO(d_logger, + boost::format("tried to set frame to %1%; max possible is %2%") % + frame_size % d_max_frame_size); + frame_size = d_max_frame_size; + ret = false; + } + + d_frame_size = frame_size; + + if (d_mode == CC_TERMINATED) { + d_output_size = 2 * (d_frame_size + 7 - 1); + } else { + d_output_size = 2 * d_frame_size; + } + + return ret; +} + +double ccsds_encoder_impl::rate() { return 0.5; } + +void ccsds_encoder_impl::generic_work(void* in_buffer, void* out_buffer) +{ + unsigned char* in = (unsigned char*)in_buffer; + unsigned char* out = (unsigned char*)out_buffer; + + unsigned char my_state = d_start_state; + + if (d_mode == CC_TAILBITING) { + // Grab K-1 (6) bits of data from the last input byte to add + // onto the from of the encoding stream for tailbiting mode. + unsigned char sym = in[d_frame_size / 8 - 1]; + for (unsigned int i = 0; i < 7 - 1; ++i) { my_state = (my_state << 1) | ((sym >> (5 - i)) & 1); - } } - - my_state = encode(out, in, d_frame_size/8, my_state); - - if(d_mode == CC_TERMINATED) { - // encode works on bytes, but we are only adding some number - // of bits to the end of the frame, so we abuse the encode - // function by reshifting the start state within the - // for-loop and only taking the last two bits out of the - // encoded 2-bytes. - unsigned char end_bits[16]; - for(unsigned int i = 0; i < (7 - 1); ++i) { + } + + my_state = encode(out, in, d_frame_size / 8, my_state); + + if (d_mode == CC_TERMINATED) { + // encode works on bytes, but we are only adding some number + // of bits to the end of the frame, so we abuse the encode + // function by reshifting the start state within the + // for-loop and only taking the last two bits out of the + // encoded 2-bytes. + unsigned char end_bits[16]; + for (unsigned int i = 0; i < (7 - 1); ++i) { my_state = (my_state << 1) | ((d_start_state >> (7 - 2 - i)) & 1); encode(&end_bits[0], &my_state, 1, my_state); out[(i + d_frame_size) * 2 + 0] = end_bits[14]; out[(i + d_frame_size) * 2 + 1] = end_bits[15]; - } } + } - if(d_mode == CC_TRUNCATED) { - my_state = d_start_state; - } + if (d_mode == CC_TRUNCATED) { + my_state = d_start_state; + } - d_start_state = my_state; - } + d_start_state = my_state; +} - } /* namespace code */ - } /* namespace fec */ +} /* namespace code */ +} /* namespace fec */ } /* namespace gr */ diff --git a/gr-fec/lib/ccsds_encoder_impl.h b/gr-fec/lib/ccsds_encoder_impl.h index e67890b0f8..f533afa878 100644 --- a/gr-fec/lib/ccsds_encoder_impl.h +++ b/gr-fec/lib/ccsds_encoder_impl.h @@ -28,37 +28,38 @@ #include <gnuradio/fec/ccsds_encoder.h> namespace gr { - namespace fec { - namespace code { +namespace fec { +namespace code { - class FEC_API ccsds_encoder_impl : public ccsds_encoder - { - private: - //plug into the generic fec api - void generic_work(void *inbuffer, void *outbuffer); - int get_output_size(); - int get_input_size(); - const char* get_input_conversion(); +class FEC_API ccsds_encoder_impl : public ccsds_encoder +{ +private: + // plug into the generic fec api + void generic_work(void* inbuffer, void* outbuffer); + int get_output_size(); + int get_input_size(); + const char* get_input_conversion(); - unsigned int d_max_frame_size; - unsigned int d_frame_size; + unsigned int d_max_frame_size; + unsigned int d_frame_size; - unsigned char d_start_state; - cc_mode_t d_mode; + unsigned char d_start_state; + cc_mode_t d_mode; - int d_output_size; + int d_output_size; - public: - ccsds_encoder_impl(int frame_size, int start_state = 0, - cc_mode_t mode=CC_STREAMING); - ~ccsds_encoder_impl(); +public: + ccsds_encoder_impl(int frame_size, + int start_state = 0, + cc_mode_t mode = CC_STREAMING); + ~ccsds_encoder_impl(); - bool set_frame_size(unsigned int frame_size); - double rate(); - }; + bool set_frame_size(unsigned int frame_size); + double rate(); +}; - } /* namespace code */ - } /* namespace fec */ +} /* namespace code */ +} /* namespace fec */ } /* namespace gr */ #endif /* INCLUDED_FEC_CCSDS_ENCODER_IMPL_H */ diff --git a/gr-fec/lib/cldpc.cc b/gr-fec/lib/cldpc.cc index fe17277313..3d105ae18d 100644 --- a/gr-fec/lib/cldpc.cc +++ b/gr-fec/lib/cldpc.cc @@ -23,7 +23,8 @@ #include <gnuradio/fec/cldpc.h> #include <stdexcept> -cldpc::cldpc(const GF2Mat X) { +cldpc::cldpc(const GF2Mat X) +{ H = X; M = H.get_M(); N = H.get_N(); @@ -31,7 +32,8 @@ cldpc::cldpc(const GF2Mat X) { K = N - rank_H; } -cldpc::cldpc(const alist _list) { +cldpc::cldpc(const alist _list) +{ H = GF2Mat(_list); M = H.get_M(); N = H.get_N(); @@ -39,7 +41,8 @@ cldpc::cldpc(const alist _list) { K = N - rank_H; } -void cldpc::set_alist(const alist _list) { +void cldpc::set_alist(const alist _list) +{ H = GF2Mat(_list); M = H.get_M(); N = H.get_N(); @@ -47,99 +50,81 @@ void cldpc::set_alist(const alist _list) { K = N - rank_H; } -std::vector<char> cldpc::get_systematic_bits(std::vector<char> in) { +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++ ) { + 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++ ) { +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> 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; + 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) { +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) ) { + 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) +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]; + 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>(); } - return y.get_vec(); - } - else { - throw std::runtime_error("bad vector length!"); - return std::vector<char>(); - } } -int -cldpc::dimension() -{ - return K; -} +int cldpc::dimension() { return K; } -int -cldpc::get_M() -{ - return M; -} +int cldpc::get_M() { return M; } -int -cldpc::get_N() -{ - return N; -} +int cldpc::get_N() { return N; } -GF2Mat -cldpc::get_H() -{ - return H; -} +GF2Mat cldpc::get_H() { return H; } -GF2Mat -cldpc::get_G() -{ - return G; -} +GF2Mat cldpc::get_G() { return G; } diff --git a/gr-fec/lib/conv_bit_corr_bb_impl.cc b/gr-fec/lib/conv_bit_corr_bb_impl.cc index 7c514168f4..3985493c03 100644 --- a/gr-fec/lib/conv_bit_corr_bb_impl.cc +++ b/gr-fec/lib/conv_bit_corr_bb_impl.cc @@ -30,39 +30,43 @@ #include <stdio.h> namespace gr { - namespace fec { - - conv_bit_corr_bb::sptr - conv_bit_corr_bb::make(std::vector<unsigned long long> correlator, - int corr_sym, int corr_len, int cut, - int flush, float thresh) - { - return gnuradio::get_initial_sptr - (new conv_bit_corr_bb_impl(correlator, corr_sym, corr_len, - cut, flush, thresh)); - } - - conv_bit_corr_bb_impl::conv_bit_corr_bb_impl(std::vector<unsigned long long> correlator, - int corr_sym, int corr_len, int cut, - int flush, float thresh) - : block("conv_bit_corr_bb", - io_signature::make(1, 1, sizeof(unsigned char)), - io_signature::make(1, 1, sizeof(unsigned char))), - d_acquire(-1), - d_produce(0), - d_message(0), - d_thresh(cut * thresh), - d_corr_len(corr_len), - d_corr_sym(corr_sym), - d_lane(0), - d_op(0), - d_flush(flush), - d_flush_count(0), - d_cut(cut), - d_counter(cut), - d_data_garble_rate(0.0), - d_havelock(false) - //d_acquire_track(-1) +namespace fec { + +conv_bit_corr_bb::sptr conv_bit_corr_bb::make(std::vector<unsigned long long> correlator, + int corr_sym, + int corr_len, + int cut, + int flush, + float thresh) +{ + return gnuradio::get_initial_sptr( + new conv_bit_corr_bb_impl(correlator, corr_sym, corr_len, cut, flush, thresh)); +} + +conv_bit_corr_bb_impl::conv_bit_corr_bb_impl(std::vector<unsigned long long> correlator, + int corr_sym, + int corr_len, + int cut, + int flush, + float thresh) + : block("conv_bit_corr_bb", + io_signature::make(1, 1, sizeof(unsigned char)), + io_signature::make(1, 1, sizeof(unsigned char))), + d_acquire(-1), + d_produce(0), + d_message(0), + d_thresh(cut * thresh), + d_corr_len(corr_len), + d_corr_sym(corr_sym), + d_lane(0), + d_op(0), + d_flush(flush), + d_flush_count(0), + d_cut(cut), + d_counter(cut), + d_data_garble_rate(0.0), + d_havelock(false) +// d_acquire_track(-1) // d_msgrecv_rpc(alias(), "messages_recieved", &d_msgrecv, // pmt::mp(0), pmt::mp(65536), pmt::mp(0), @@ -87,172 +91,175 @@ namespace gr { // pmt::mp(0), pmt::mp(1), pmt::mp(0), // "bool","Sync Locked", // RPC_PRIVLVL_MIN, DISPTIME) - { - //big correlator mode (ugh) - std::vector<unsigned char> temp; - for(unsigned int k = 0; k < d_corr_sym; ++k) { +{ + // big correlator mode (ugh) + std::vector<unsigned char> temp; + for (unsigned int k = 0; k < d_corr_sym; ++k) { d_acc.push_back(0); - } - for(unsigned int i = 0; i < d_corr_len; ++i) { - if((correlator[i/64] >> (64 - (i%64) - 1)) & 1) { - temp.push_back(i); + } + for (unsigned int i = 0; i < d_corr_len; ++i) { + if ((correlator[i / 64] >> (64 - (i % 64) - 1)) & 1) { + temp.push_back(i); } - } - d_correlator.push_back(temp); + } + d_correlator.push_back(temp); - for(unsigned int j = 0; j < d_correlator.size(); ++j) { + for (unsigned int j = 0; j < d_correlator.size(); ++j) { std::vector<int> temp(d_corr_sym); d_score_keeper.push_back(temp); - } - - set_history(d_corr_len + d_corr_sym); - d_flush_count = d_corr_len + d_corr_sym - 1; - set_output_multiple(d_corr_sym); } - conv_bit_corr_bb_impl::~conv_bit_corr_bb_impl() - { - } + set_history(d_corr_len + d_corr_sym); + d_flush_count = d_corr_len + d_corr_sym - 1; + set_output_multiple(d_corr_sym); +} - void - conv_bit_corr_bb_impl::catch_msg(pmt::pmt_t msg) - { - //stub code - d_msgrecv++; - } +conv_bit_corr_bb_impl::~conv_bit_corr_bb_impl() {} - int - conv_bit_corr_bb_impl::general_work(int noutput_items, +void conv_bit_corr_bb_impl::catch_msg(pmt::pmt_t msg) +{ + // stub code + d_msgrecv++; +} + +int conv_bit_corr_bb_impl::general_work(int noutput_items, gr_vector_int& ninput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) - { - if(d_flush_count > 0) { - int items = (ninput_items[0] > static_cast<int>(d_flush_count)) ? d_flush_count : ninput_items[0]; - consume_each(items); - d_flush_count -= items; - return 0; - } - - const uint8_t *in = (const uint8_t *) input_items[0]; - uint8_t *score_in = (uint8_t *) input_items[0]; - - //counting on 1:1 forecast + history to provide enough ninput_items... may need to insert check - //printf("%d, %d, %d\n", ninput_items[0], noutput_items, d_counter); - int correlation_cycles = (noutput_items/output_multiple() <= static_cast<int>(d_counter)) ? \ - noutput_items/output_multiple() : d_counter; - - - for(int p = 0; p < correlation_cycles; ++p) { - //reset scores - for(unsigned int j = 0; j < d_correlator.size(); ++j) { - for(unsigned int i = 0; i < d_corr_sym; ++i) { - d_score_keeper[j][i] = 0; - } - } - - //correlate against each correlation constant - for(unsigned int j = 0; j < d_correlator.size(); ++j) { - for(unsigned int k = 0; k < d_corr_sym; ++k) { - for(unsigned int i = 0; i < d_correlator[j].size(); ++i) { - d_score_keeper[j][k] += (score_in[d_correlator[j][i] + k] >= 128) ? 1 : 0; + gr_vector_const_void_star& input_items, + gr_vector_void_star& output_items) +{ + if (d_flush_count > 0) { + int items = (ninput_items[0] > static_cast<int>(d_flush_count)) ? d_flush_count + : ninput_items[0]; + consume_each(items); + d_flush_count -= items; + return 0; + } + + const uint8_t* in = (const uint8_t*)input_items[0]; + uint8_t* score_in = (uint8_t*)input_items[0]; + + // counting on 1:1 forecast + history to provide enough ninput_items... may need to + // insert check printf("%d, %d, %d\n", ninput_items[0], noutput_items, d_counter); + int correlation_cycles = + (noutput_items / output_multiple() <= static_cast<int>(d_counter)) + ? noutput_items / output_multiple() + : d_counter; + + + for (int p = 0; p < correlation_cycles; ++p) { + // reset scores + for (unsigned int j = 0; j < d_correlator.size(); ++j) { + for (unsigned int i = 0; i < d_corr_sym; ++i) { + d_score_keeper[j][i] = 0; } - } + } - for(unsigned int k = 0; k < d_corr_sym; ++k) { - d_acc[j * (d_corr_sym) + k] += d_score_keeper[j][k] % 2; - } - } - score_in += d_corr_sym; - } + // correlate against each correlation constant + for (unsigned int j = 0; j < d_correlator.size(); ++j) { + for (unsigned int k = 0; k < d_corr_sym; ++k) { + for (unsigned int i = 0; i < d_correlator[j].size(); ++i) { + d_score_keeper[j][k] += + (score_in[d_correlator[j][i] + k] >= 128) ? 1 : 0; + } + } - //decrement the cut counter + for (unsigned int k = 0; k < d_corr_sym; ++k) { + d_acc[j * (d_corr_sym) + k] += d_score_keeper[j][k] % 2; + } + } + score_in += d_corr_sym; + } + + // decrement the cut counter - d_counter -= correlation_cycles; + d_counter -= correlation_cycles; - //d_counter == 0: check the accumulator and update states - if(d_counter == 0) { + // d_counter == 0: check the accumulator and update states + if (d_counter == 0) { d_message = 1; - d_produce = 0; - float my_min = 1.0; - for(unsigned int i = 0; (i < d_correlator.size()) && (!d_produce); ++i) { - for(unsigned int k = 0; k < d_corr_sym; ++k) { - - my_min = (d_acc[i * (d_corr_sym) + k]/(float)d_cut < my_min) ? \ - d_acc[i * (d_corr_sym) + k]/(float)d_cut:my_min; - - if(d_acc[i * (d_corr_sym) + k] < d_thresh) { - d_produce = 1; - d_message = 0; - d_acquire = k; - d_lane = i + 1; - d_op = 1; - //printf("winner: lane %u, punc_cycle %u, pos/neg corr %d\n", i, k, d_op); - break; + d_produce = 0; + float my_min = 1.0; + for (unsigned int i = 0; (i < d_correlator.size()) && (!d_produce); ++i) { + for (unsigned int k = 0; k < d_corr_sym; ++k) { + + my_min = (d_acc[i * (d_corr_sym) + k] / (float)d_cut < my_min) + ? d_acc[i * (d_corr_sym) + k] / (float)d_cut + : my_min; + + if (d_acc[i * (d_corr_sym) + k] < d_thresh) { + d_produce = 1; + d_message = 0; + d_acquire = k; + d_lane = i + 1; + d_op = 1; + // printf("winner: lane %u, punc_cycle %u, pos/neg corr %d\n", i, k, + // d_op); + break; + } else if (d_acc[i * (d_corr_sym) + k] > (d_cut - d_thresh)) { + d_acquire = k; + d_lane = i + 1; + d_op = -1; + // printf("winner: lane %u, punc_cycle %u, pos/neg corr %d\n", i, k, + // d_op); + break; + } } - else if(d_acc[i * (d_corr_sym) + k] > (d_cut - d_thresh)) { - d_acquire = k; - d_lane = i + 1; - d_op = -1; - //printf("winner: lane %u, punc_cycle %u, pos/neg corr %d\n", i, k, d_op); - break; + d_data_garble_rate = 100.0 * data_garble_rate(d_correlator[i].size(), my_min); + d_havelock = d_data_garble_rate < 3; + } + + // clear the accumulator, reset the counter + d_counter = d_cut; + for (unsigned int i = 0; i < d_correlator.size(); ++i) { + for (unsigned int k = 0; k < d_corr_sym; ++k) { + d_acc[i * (d_corr_sym) + k] = 0; } - } - d_data_garble_rate = 100.0 * data_garble_rate(d_correlator[i].size(), my_min); - d_havelock = d_data_garble_rate < 3; - } - - //clear the accumulator, reset the counter - d_counter = d_cut; - for(unsigned int i = 0; i < d_correlator.size(); ++i) { - for(unsigned int k = 0; k < d_corr_sym; ++k) { - d_acc[i * (d_corr_sym) + k] = 0; - } - } - - //examine the new states and react to environment, make a final production decision - if(d_message) { - d_msgsent++; - //stub code - d_message = 0; } - } - //states are set - if(d_produce) { - //printf("producing\n"); - unsigned char *out = (unsigned char *) output_items[0]; - memcpy(out, &(in[d_acquire]), correlation_cycles*d_corr_sym*sizeof(unsigned char)); + // examine the new states and react to environment, make a final production + // decision + if (d_message) { + d_msgsent++; + // stub code + d_message = 0; + } + } + // states are set - consume_each(d_corr_sym * correlation_cycles); - return d_corr_sym * correlation_cycles; - } + if (d_produce) { + // printf("producing\n"); + unsigned char* out = (unsigned char*)output_items[0]; + memcpy(out, + &(in[d_acquire]), + correlation_cycles * d_corr_sym * sizeof(unsigned char)); - else { + consume_each(d_corr_sym * correlation_cycles); + return d_corr_sym * correlation_cycles; + } + + else { consume_each(d_corr_sym * correlation_cycles); return 0; - } } +} - float - conv_bit_corr_bb_impl::data_garble_rate(int taps, float target) - { - double base,expo,answer; +float conv_bit_corr_bb_impl::data_garble_rate(int taps, float target) +{ + double base, expo, answer; - if(target > 0.5) - target=1-target; + if (target > 0.5) + target = 1 - target; - base=1.0-2.0*target; - expo=(double) 1/taps; - answer=0.5*(1-pow(base,expo)); + base = 1.0 - 2.0 * target; + expo = (double)1 / taps; + answer = 0.5 * (1 - pow(base, expo)); - if((errno==EDOM) || (errno==ERANGE)) { - fprintf(stderr,"Out of range errors while computing garble rate.\n"); + if ((errno == EDOM) || (errno == ERANGE)) { + fprintf(stderr, "Out of range errors while computing garble rate.\n"); exit(-1); - } - return answer; } + return answer; +} - } /* namespace fec */ +} /* namespace fec */ } /* namespace gr */ - diff --git a/gr-fec/lib/conv_bit_corr_bb_impl.h b/gr-fec/lib/conv_bit_corr_bb_impl.h index 509ad6f23e..14422dd878 100644 --- a/gr-fec/lib/conv_bit_corr_bb_impl.h +++ b/gr-fec/lib/conv_bit_corr_bb_impl.h @@ -26,72 +26,75 @@ #include <gnuradio/fec/conv_bit_corr_bb.h> namespace gr { - namespace fec { +namespace fec { - class FEC_API conv_bit_corr_bb_impl : public conv_bit_corr_bb - { - private: - std::vector< std::vector<int> > d_score_keeper; +class FEC_API conv_bit_corr_bb_impl : public conv_bit_corr_bb +{ +private: + std::vector<std::vector<int>> d_score_keeper; - int d_angry_fop; - int d_acquire; - //int d_acquire_track; - unsigned int d_produce; - unsigned int d_message; - unsigned int d_thresh; - unsigned int d_corr_len; - unsigned int d_corr_sym; - unsigned int d_lane; - unsigned int d_op; - unsigned int d_flush; - unsigned int d_flush_count; - std::vector< std::vector<unsigned char> > d_correlator; - std::vector<unsigned int> d_acc; - uint64_t d_cut; - uint64_t d_counter; - float d_data_garble_rate; + int d_angry_fop; + int d_acquire; + // int d_acquire_track; + unsigned int d_produce; + unsigned int d_message; + unsigned int d_thresh; + unsigned int d_corr_len; + unsigned int d_corr_sym; + unsigned int d_lane; + unsigned int d_op; + unsigned int d_flush; + unsigned int d_flush_count; + std::vector<std::vector<unsigned char>> d_correlator; + std::vector<unsigned int> d_acc; + uint64_t d_cut; + uint64_t d_counter; + float d_data_garble_rate; - void alert_fops(); + void alert_fops(); -// //rpcbasic_register_get<conv_bit_corr_bb, std::vector< int> > d_correlator_rpc; -// rpcbasic_register_variable_rw<uint64_t> d_cut_rpc; // integration period -// rpcbasic_register_variable_rw<int> d_flush_rpc; // time to flush -// rpcbasic_register_variable<uint64_t> d_msgsent_rpc; -// rpcbasic_register_variable<uint64_t> d_msgrecv_rpc; -// rpcbasic_register_variable<float> d_data_garble_rate_rpc; + // //rpcbasic_register_get<conv_bit_corr_bb, std::vector< int> > + // d_correlator_rpc; rpcbasic_register_variable_rw<uint64_t> d_cut_rpc; // + // integration period rpcbasic_register_variable_rw<int> d_flush_rpc; // time to + // flush rpcbasic_register_variable<uint64_t> d_msgsent_rpc; + // rpcbasic_register_variable<uint64_t> d_msgrecv_rpc; + // rpcbasic_register_variable<float> d_data_garble_rate_rpc; - uint64_t d_msgsent,d_msgrecv; - std::vector<int> get_corr() - { + uint64_t d_msgsent, d_msgrecv; + std::vector<int> get_corr() + { std::vector<int> bits; - if(d_correlator.size() < 1) { - return bits; + if (d_correlator.size() < 1) { + return bits; } - for(size_t i = 0; i < d_correlator[0].size(); i++) { - bits.push_back(d_correlator[0][i]); + for (size_t i = 0; i < d_correlator[0].size(); i++) { + bits.push_back(d_correlator[0][i]); } return bits; - } + } - bool d_havelock; - //rpcbasic_register_variable<bool> d_havelock_rpc; + bool d_havelock; + // rpcbasic_register_variable<bool> d_havelock_rpc; - public: - conv_bit_corr_bb_impl(std::vector<unsigned long long> correlator, - int corr_sym, int corr_len, int cut, - int flush, float thresh); - ~conv_bit_corr_bb_impl(); +public: + conv_bit_corr_bb_impl(std::vector<unsigned long long> correlator, + int corr_sym, + int corr_len, + int cut, + int flush, + float thresh); + ~conv_bit_corr_bb_impl(); - void catch_msg(pmt::pmt_t msg); - int general_work(int noutput_items, - gr_vector_int& ninput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); + void catch_msg(pmt::pmt_t msg); + int general_work(int noutput_items, + gr_vector_int& ninput_items, + gr_vector_const_void_star& input_items, + gr_vector_void_star& output_items); - float data_garble_rate(int taps, float target); - }; + float data_garble_rate(int taps, float target); +}; - } /* namespace fec */ +} /* namespace fec */ } /* namespace gr */ #endif /* INCLUDED_FEC_CONV_BIT_CORR_BB_IMPL_H */ diff --git a/gr-fec/lib/decode_ccsds_27_fb_impl.cc b/gr-fec/lib/decode_ccsds_27_fb_impl.cc index 9b782b7098..1ec5f1eaa9 100644 --- a/gr-fec/lib/decode_ccsds_27_fb_impl.cc +++ b/gr-fec/lib/decode_ccsds_27_fb_impl.cc @@ -28,63 +28,63 @@ #include <gnuradio/io_signature.h> namespace gr { - namespace fec { +namespace fec { - decode_ccsds_27_fb::sptr decode_ccsds_27_fb::make() - { - return gnuradio::get_initial_sptr(new decode_ccsds_27_fb_impl()); - } - - decode_ccsds_27_fb_impl::decode_ccsds_27_fb_impl() - : sync_decimator("decode_ccsds_27_fb", - io_signature::make (1, 1, sizeof(float)), - io_signature::make (1, 1, sizeof(char)), - 2*8), d_count(0) // Rate 1/2 code, unpacked to packed conversion - { - float RATE = 0.5; - float ebn0 = 12.0; - float esn0 = RATE*pow(10.0, ebn0/10.0); +decode_ccsds_27_fb::sptr decode_ccsds_27_fb::make() +{ + return gnuradio::get_initial_sptr(new decode_ccsds_27_fb_impl()); +} - gen_met(d_mettab, 100, esn0, 0.0, 256); - viterbi_chunks_init(d_state0); - viterbi_chunks_init(d_state1); - } +decode_ccsds_27_fb_impl::decode_ccsds_27_fb_impl() + : sync_decimator("decode_ccsds_27_fb", + io_signature::make(1, 1, sizeof(float)), + io_signature::make(1, 1, sizeof(char)), + 2 * 8), + d_count(0) // Rate 1/2 code, unpacked to packed conversion +{ + float RATE = 0.5; + float ebn0 = 12.0; + float esn0 = RATE * pow(10.0, ebn0 / 10.0); - int - decode_ccsds_27_fb_impl::work(int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) - { - const float *in = (const float*)input_items[0]; - unsigned char *out = (unsigned char*)output_items[0]; + gen_met(d_mettab, 100, esn0, 0.0, 256); + viterbi_chunks_init(d_state0); + viterbi_chunks_init(d_state1); +} - for (int i = 0; i < noutput_items*16; i++) { - // Translate and clip [-1.0..1.0] to [28..228] - float sample = in[i]*100.0+128.0; - if(sample > 255.0) - sample = 255.0; - else if(sample < 0.0) - sample = 0.0; - unsigned char sym = (unsigned char)(floor(sample)); +int decode_ccsds_27_fb_impl::work(int noutput_items, + gr_vector_const_void_star& input_items, + gr_vector_void_star& output_items) +{ + const float* in = (const float*)input_items[0]; + unsigned char* out = (unsigned char*)output_items[0]; - d_viterbi_in[d_count % 4] = sym; - if((d_count % 4) == 3) { - // Every fourth symbol, perform butterfly operation - viterbi_butterfly2(d_viterbi_in, d_mettab, d_state0, d_state1); + for (int i = 0; i < noutput_items * 16; i++) { + // Translate and clip [-1.0..1.0] to [28..228] + float sample = in[i] * 100.0 + 128.0; + if (sample > 255.0) + sample = 255.0; + else if (sample < 0.0) + sample = 0.0; + unsigned char sym = (unsigned char)(floor(sample)); - // Every sixteenth symbol, read out a byte - if (d_count % 16 == 11) { - // long metric = - viterbi_get_output(d_state0, out++); - // printf("%li\n", *(out-1), metric); - } - } + d_viterbi_in[d_count % 4] = sym; + if ((d_count % 4) == 3) { + // Every fourth symbol, perform butterfly operation + viterbi_butterfly2(d_viterbi_in, d_mettab, d_state0, d_state1); - d_count++; - } + // Every sixteenth symbol, read out a byte + if (d_count % 16 == 11) { + // long metric = + viterbi_get_output(d_state0, out++); + // printf("%li\n", *(out-1), metric); + } + } - return noutput_items; + d_count++; } - } /* namespace fec */ -}/* namespace gr */ + return noutput_items; +} + +} /* namespace fec */ +} /* namespace gr */ diff --git a/gr-fec/lib/decode_ccsds_27_fb_impl.h b/gr-fec/lib/decode_ccsds_27_fb_impl.h index fff01d2374..1f22f6e305 100644 --- a/gr-fec/lib/decode_ccsds_27_fb_impl.h +++ b/gr-fec/lib/decode_ccsds_27_fb_impl.h @@ -27,28 +27,28 @@ #include <gnuradio/fec/viterbi.h> namespace gr { - namespace fec { +namespace fec { - class FEC_API decode_ccsds_27_fb_impl : public decode_ccsds_27_fb - { - private: - // Viterbi state - int d_mettab[2][256]; - struct viterbi_state d_state0[64]; - struct viterbi_state d_state1[64]; - unsigned char d_viterbi_in[16]; +class FEC_API decode_ccsds_27_fb_impl : public decode_ccsds_27_fb +{ +private: + // Viterbi state + int d_mettab[2][256]; + struct viterbi_state d_state0[64]; + struct viterbi_state d_state1[64]; + unsigned char d_viterbi_in[16]; - int d_count; + int d_count; - public: - decode_ccsds_27_fb_impl(); +public: + decode_ccsds_27_fb_impl(); - int work(int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); - }; + int work(int noutput_items, + gr_vector_const_void_star& input_items, + gr_vector_void_star& output_items); +}; - } /* namespace fec */ +} /* namespace fec */ } /* namespace gr */ #endif /* INCLUDED_FEC_DECODE_CCSDS_27_FB_IMPL_H */ diff --git a/gr-fec/lib/decoder_impl.cc b/gr-fec/lib/decoder_impl.cc index bbb4f18772..5af8978700 100644 --- a/gr-fec/lib/decoder_impl.cc +++ b/gr-fec/lib/decoder_impl.cc @@ -29,87 +29,90 @@ #include <stdio.h> namespace gr { - namespace fec { - - decoder::sptr - decoder::make(generic_decoder::sptr my_decoder, - size_t input_item_size, - size_t output_item_size) - { - return gnuradio::get_initial_sptr - ( new decoder_impl(my_decoder, input_item_size, output_item_size)); - } - - decoder_impl::decoder_impl(generic_decoder::sptr my_decoder, - size_t input_item_size, - size_t output_item_size) - : block("fec_decoder", - io_signature::make(1, 1, input_item_size), - io_signature::make(1, 1, output_item_size)), - d_input_item_size(input_item_size), d_output_item_size(output_item_size) - { - set_fixed_rate(true); - set_relative_rate((uint64_t)my_decoder->get_output_size(), - (uint64_t)my_decoder->get_input_size()); - - //want to guarantee you have enough to run at least one time... - //remember! this is not a sync block... set_output_multiple does not - //actually guarantee the output multiple... it DOES guarantee how many - //outputs (hence inputs) are made available... this is WEIRD to do in - //GNU Radio, and the algorithm is sensitive to this value - set_output_multiple(my_decoder->get_output_size() + (my_decoder->get_history())); - d_decoder = my_decoder; - } - - int - decoder_impl::fixed_rate_ninput_to_noutput(int ninput) - { - return (int)(0.5 + ninput*relative_rate()); - } - - int - decoder_impl::fixed_rate_noutput_to_ninput(int noutput) - { - return (int)(0.5 + noutput/relative_rate()); - } - - void - decoder_impl::forecast(int noutput_items, - gr_vector_int& ninput_items_required) - { - ninput_items_required[0] = 0.5 + fixed_rate_noutput_to_ninput(noutput_items); - } - - int - decoder_impl::general_work(int noutput_items, +namespace fec { + +decoder::sptr decoder::make(generic_decoder::sptr my_decoder, + size_t input_item_size, + size_t output_item_size) +{ + return gnuradio::get_initial_sptr( + new decoder_impl(my_decoder, input_item_size, output_item_size)); +} + +decoder_impl::decoder_impl(generic_decoder::sptr my_decoder, + size_t input_item_size, + size_t output_item_size) + : block("fec_decoder", + io_signature::make(1, 1, input_item_size), + io_signature::make(1, 1, output_item_size)), + d_input_item_size(input_item_size), + d_output_item_size(output_item_size) +{ + set_fixed_rate(true); + set_relative_rate((uint64_t)my_decoder->get_output_size(), + (uint64_t)my_decoder->get_input_size()); + + // want to guarantee you have enough to run at least one time... + // remember! this is not a sync block... set_output_multiple does not + // actually guarantee the output multiple... it DOES guarantee how many + // outputs (hence inputs) are made available... this is WEIRD to do in + // GNU Radio, and the algorithm is sensitive to this value + set_output_multiple(my_decoder->get_output_size() + (my_decoder->get_history())); + d_decoder = my_decoder; +} + +int decoder_impl::fixed_rate_ninput_to_noutput(int ninput) +{ + return (int)(0.5 + ninput * relative_rate()); +} + +int decoder_impl::fixed_rate_noutput_to_ninput(int noutput) +{ + return (int)(0.5 + noutput / relative_rate()); +} + +void decoder_impl::forecast(int noutput_items, gr_vector_int& ninput_items_required) +{ + ninput_items_required[0] = 0.5 + fixed_rate_noutput_to_ninput(noutput_items); +} + +int decoder_impl::general_work(int noutput_items, gr_vector_int& ninput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) - { - const unsigned char *in = (unsigned char*)input_items[0]; - unsigned char *out = (unsigned char *)output_items[0]; - - int outnum = (int)(((1.0/relative_rate()) * noutput_items) + 0.5); - int innum = (int)(relative_rate() * (ninput_items[0] - d_decoder->get_history()) + 0.5)/(output_multiple() - d_decoder->get_history()); - - int items = (outnum <= ninput_items[0] - d_decoder->get_history()) ? - noutput_items/(output_multiple() - d_decoder->get_history()) : - innum; - - for(int i = 0; i < items; ++i) { - d_decoder->generic_work((void*)(in+(i*d_decoder->get_input_size()*d_input_item_size)), - (void*)(out+(i*d_decoder->get_output_size()*d_output_item_size))); - - add_item_tag(0, nitems_written(0) + ((i+1)*d_decoder->get_output_size()*d_output_item_size), - pmt::intern(d_decoder->alias()), pmt::PMT_T, pmt::intern(alias())); - } + gr_vector_const_void_star& input_items, + gr_vector_void_star& output_items) +{ + const unsigned char* in = (unsigned char*)input_items[0]; + unsigned char* out = (unsigned char*)output_items[0]; + + int outnum = (int)(((1.0 / relative_rate()) * noutput_items) + 0.5); + int innum = + (int)(relative_rate() * (ninput_items[0] - d_decoder->get_history()) + 0.5) / + (output_multiple() - d_decoder->get_history()); + + int items = (outnum <= ninput_items[0] - d_decoder->get_history()) + ? noutput_items / (output_multiple() - d_decoder->get_history()) + : innum; + + for (int i = 0; i < items; ++i) { + d_decoder->generic_work( + (void*)(in + (i * d_decoder->get_input_size() * d_input_item_size)), + (void*)(out + (i * d_decoder->get_output_size() * d_output_item_size))); + + add_item_tag(0, + nitems_written(0) + + ((i + 1) * d_decoder->get_output_size() * d_output_item_size), + pmt::intern(d_decoder->alias()), + pmt::PMT_T, + pmt::intern(alias())); + } - int consumed = static_cast<int>(items/relative_rate()*(output_multiple() - d_decoder->get_history()) + 0.5); - int returned = items*(output_multiple() - d_decoder->get_history()); + int consumed = static_cast<int>( + items / relative_rate() * (output_multiple() - d_decoder->get_history()) + 0.5); + int returned = items * (output_multiple() - d_decoder->get_history()); - consume_each(consumed); - return returned; - } + consume_each(consumed); + return returned; +} - } /* namespace fec */ +} /* namespace fec */ } /* namespace gr */ diff --git a/gr-fec/lib/decoder_impl.h b/gr-fec/lib/decoder_impl.h index 78b1b926b5..a26b79c7c3 100644 --- a/gr-fec/lib/decoder_impl.h +++ b/gr-fec/lib/decoder_impl.h @@ -26,31 +26,30 @@ #include <gnuradio/fec/decoder.h> namespace gr { - namespace fec { - - class FEC_API decoder_impl : public decoder - { - private: - generic_decoder::sptr d_decoder; - size_t d_input_item_size; - size_t d_output_item_size; - - public: - decoder_impl(generic_decoder::sptr my_decoder, - size_t input_item_size, - size_t output_item_size); - - int general_work(int noutput_items, - gr_vector_int& ninput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); - int fixed_rate_ninput_to_noutput(int ninput); - int fixed_rate_noutput_to_ninput(int noutput); - void forecast(int noutput_items, - gr_vector_int& ninput_items_required); - }; - - } /* namespace fec */ +namespace fec { + +class FEC_API decoder_impl : public decoder +{ +private: + generic_decoder::sptr d_decoder; + size_t d_input_item_size; + size_t d_output_item_size; + +public: + decoder_impl(generic_decoder::sptr my_decoder, + size_t input_item_size, + size_t output_item_size); + + int general_work(int noutput_items, + gr_vector_int& ninput_items, + gr_vector_const_void_star& input_items, + gr_vector_void_star& output_items); + int fixed_rate_ninput_to_noutput(int ninput); + int fixed_rate_noutput_to_ninput(int noutput); + void forecast(int noutput_items, gr_vector_int& ninput_items_required); +}; + +} /* namespace fec */ } /* namespace gr */ #endif /* INCLUDED_FEC_DECODER_IMPL_H */ diff --git a/gr-fec/lib/depuncture_bb_impl.cc b/gr-fec/lib/depuncture_bb_impl.cc index 22417e4f0f..0fa3ba94b0 100644 --- a/gr-fec/lib/depuncture_bb_impl.cc +++ b/gr-fec/lib/depuncture_bb_impl.cc @@ -33,122 +33,114 @@ #include <stdio.h> namespace gr { - namespace fec { - - depuncture_bb::sptr - depuncture_bb::make(int puncsize, int puncpat, - int delay, char symbol) - { - return gnuradio::get_initial_sptr - (new depuncture_bb_impl(puncsize, puncpat, - delay, symbol)); - } - - depuncture_bb_impl::depuncture_bb_impl(int puncsize, int puncpat, - int delay, char symbol) - : block("depuncture_bb", - io_signature::make(1, 1, sizeof(unsigned char)), - io_signature::make(1, 1, sizeof(unsigned char))), - d_puncsize(puncsize), d_delay(delay), d_sym(symbol) - { - // Create a mask of all 1's of puncsize length - int mask = 0; - for(int i = 0; i < d_puncsize; i++) +namespace fec { + +depuncture_bb::sptr depuncture_bb::make(int puncsize, int puncpat, int delay, char symbol) +{ + return gnuradio::get_initial_sptr( + new depuncture_bb_impl(puncsize, puncpat, delay, symbol)); +} + +depuncture_bb_impl::depuncture_bb_impl(int puncsize, int puncpat, int delay, char symbol) + : block("depuncture_bb", + io_signature::make(1, 1, sizeof(unsigned char)), + io_signature::make(1, 1, sizeof(unsigned char))), + d_puncsize(puncsize), + d_delay(delay), + d_sym(symbol) +{ + // Create a mask of all 1's of puncsize length + int mask = 0; + for (int i = 0; i < d_puncsize; i++) mask |= 1 << i; - // Rotate the pattern for the delay value; then mask it if there - // are any excess 1's in the pattern. - for(int i = 0; i < d_delay; ++i) { - puncpat = ((puncpat & 1) << (d_puncsize - 1)) + (puncpat >> 1); - } - d_puncpat = puncpat & mask; - - // Calculate the number of holes in the pattern. The mask is all - // 1's given puncsize and puncpat is a pattern with >= puncsize - // 0's (masked to ensure this). The difference between the - // number of 1's in the mask and the puncpat is the number of - // holes. - uint32_t count_mask=0, count_pat=0; - volk_32u_popcnt(&count_mask, static_cast<uint32_t>(mask)); - volk_32u_popcnt(&count_pat, static_cast<uint32_t>(d_puncpat)); - d_puncholes = count_mask - count_pat; - - set_fixed_rate(true); - set_relative_rate((uint64_t)d_puncsize, - (uint64_t)(d_puncsize - d_puncholes)); - set_output_multiple(d_puncsize); - //set_msg_handler(boost::bind(&depuncture_bb_impl::catch_msg, this, _1)); - } - - depuncture_bb_impl::~depuncture_bb_impl() - { - } - - int - depuncture_bb_impl::fixed_rate_ninput_to_noutput(int ninput) - { - return (int)(((d_puncsize/(double)(d_puncsize - d_puncholes)) * ninput) + .5); - } - - int - depuncture_bb_impl::fixed_rate_noutput_to_ninput(int noutput) - { - return (int)((((d_puncsize - d_puncholes)/(double)(d_puncsize)) * noutput) + .5); + // Rotate the pattern for the delay value; then mask it if there + // are any excess 1's in the pattern. + for (int i = 0; i < d_delay; ++i) { + puncpat = ((puncpat & 1) << (d_puncsize - 1)) + (puncpat >> 1); } + d_puncpat = puncpat & mask; + + // Calculate the number of holes in the pattern. The mask is all + // 1's given puncsize and puncpat is a pattern with >= puncsize + // 0's (masked to ensure this). The difference between the + // number of 1's in the mask and the puncpat is the number of + // holes. + uint32_t count_mask = 0, count_pat = 0; + volk_32u_popcnt(&count_mask, static_cast<uint32_t>(mask)); + volk_32u_popcnt(&count_pat, static_cast<uint32_t>(d_puncpat)); + d_puncholes = count_mask - count_pat; + + set_fixed_rate(true); + set_relative_rate((uint64_t)d_puncsize, (uint64_t)(d_puncsize - d_puncholes)); + set_output_multiple(d_puncsize); + // set_msg_handler(boost::bind(&depuncture_bb_impl::catch_msg, this, _1)); +} + +depuncture_bb_impl::~depuncture_bb_impl() {} + +int depuncture_bb_impl::fixed_rate_ninput_to_noutput(int ninput) +{ + return (int)(((d_puncsize / (double)(d_puncsize - d_puncholes)) * ninput) + .5); +} + +int depuncture_bb_impl::fixed_rate_noutput_to_ninput(int noutput) +{ + return (int)((((d_puncsize - d_puncholes) / (double)(d_puncsize)) * noutput) + .5); +} + +void depuncture_bb_impl::forecast(int noutput_items, gr_vector_int& ninput_items_required) +{ + ninput_items_required[0] = + (int)((((d_puncsize - d_puncholes) / (double)(d_puncsize)) * noutput_items) + .5); +} - void - depuncture_bb_impl::forecast(int noutput_items, - gr_vector_int& ninput_items_required) - { - ninput_items_required[0] = (int)((((d_puncsize - d_puncholes)/(double)(d_puncsize)) * noutput_items) + .5); +/* +void depuncture_bb_impl::catch_msg(pmt::pmt_t msg) +{ + long mlong = pmt::pmt_to_long(msg); + for(int i = 0; i < mlong; ++i) { + d_puncholes = (d_puncholes >> 1) | ((d_puncholes & 1) << (d_puncsize - 1)); + } +} +*/ + +int depuncture_bb_impl::general_work(int noutput_items, + gr_vector_int& ninput_items, + gr_vector_const_void_star& input_items, + gr_vector_void_star& output_items) +{ + const uint8_t* in = (const uint8_t*)input_items[0]; + uint8_t* out = (uint8_t*)output_items[0]; + + for (int i = 0, k = 0; i < noutput_items / output_multiple(); ++i) { + for (int j = 0; j < output_multiple(); ++j) { + out[i * output_multiple() + j] = + ((d_puncpat >> (d_puncsize - 1 - j)) & 1) ? in[k++] : d_sym; + } } /* - void depuncture_bb_impl::catch_msg(pmt::pmt_t msg) - { - long mlong = pmt::pmt_to_long(msg); - for(int i = 0; i < mlong; ++i) { - d_puncholes = (d_puncholes >> 1) | ((d_puncholes & 1) << (d_puncsize - 1)); + GR_LOG_DEBUG(d_debug_logger, ">>>>>> start"); + for(int i = 0, k=0; i < noutput_items; ++i) { + if((d_puncpat >> (d_puncsize - 1 - (i % d_puncsize))) & 1) { + GR_LOG_DEBUG(d_debug_logger, boost::format("%1%...%2%") \ + % out[i] % in[k++]); } - } - */ - - int - depuncture_bb_impl::general_work(int noutput_items, - gr_vector_int& ninput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) - { - const uint8_t *in = (const uint8_t*)input_items[0]; - uint8_t *out = (uint8_t*)output_items[0]; - - for(int i=0, k=0; i < noutput_items/output_multiple(); ++i) { - for(int j = 0; j < output_multiple(); ++j) { - out[i*output_multiple() + j] = ((d_puncpat >> (d_puncsize - 1 - j)) & 1) ? in[k++] : d_sym; - } - } - - /* - GR_LOG_DEBUG(d_debug_logger, ">>>>>> start"); - for(int i = 0, k=0; i < noutput_items; ++i) { - if((d_puncpat >> (d_puncsize - 1 - (i % d_puncsize))) & 1) { - GR_LOG_DEBUG(d_debug_logger, boost::format("%1%...%2%") \ - % out[i] % in[k++]); - } - else { - GR_LOG_DEBUG(d_debug_logger, boost::format("snit %1%") % out[i]); - } + else { + GR_LOG_DEBUG(d_debug_logger, boost::format("snit %1%") % out[i]); } + } - GR_LOG_DEBUG(d_debug_logger, boost::format("comp: %1%, %2%\n") \ - % noutput_items % ninput_items[0]); - GR_LOG_DEBUG(d_debug_logger, boost::format("consuming %1%") \ - % ((int)(((1.0/relative_rate()) * noutput_items) + .5))); - */ + GR_LOG_DEBUG(d_debug_logger, boost::format("comp: %1%, %2%\n") \ + % noutput_items % ninput_items[0]); + GR_LOG_DEBUG(d_debug_logger, boost::format("consuming %1%") \ + % ((int)(((1.0/relative_rate()) * noutput_items) + .5))); + */ - consume_each((int)(((1.0/relative_rate()) * noutput_items) + .5)); - return noutput_items; - } + consume_each((int)(((1.0 / relative_rate()) * noutput_items) + .5)); + return noutput_items; +} - } /* namespace fec */ +} /* namespace fec */ } /* namespace gr */ diff --git a/gr-fec/lib/depuncture_bb_impl.h b/gr-fec/lib/depuncture_bb_impl.h index 013276d7ee..4bf4f347b0 100644 --- a/gr-fec/lib/depuncture_bb_impl.h +++ b/gr-fec/lib/depuncture_bb_impl.h @@ -26,33 +26,31 @@ #include <gnuradio/fec/depuncture_bb.h> namespace gr { - namespace fec { - - class FEC_API depuncture_bb_impl : public depuncture_bb - { - private: - int d_puncsize; - int d_delay; - int d_puncholes; - int d_puncpat; - char d_sym; - - public: - depuncture_bb_impl(int puncsize, int puncpat, - int delay=0, char symbol=127); - ~depuncture_bb_impl(); - - int general_work(int noutput_items, - gr_vector_int& ninput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); - int fixed_rate_ninput_to_noutput(int ninput); - int fixed_rate_noutput_to_ninput(int noutput); - void forecast(int noutput_items, - gr_vector_int& ninput_items_required); - }; - - } /* namespace fec */ +namespace fec { + +class FEC_API depuncture_bb_impl : public depuncture_bb +{ +private: + int d_puncsize; + int d_delay; + int d_puncholes; + int d_puncpat; + char d_sym; + +public: + depuncture_bb_impl(int puncsize, int puncpat, int delay = 0, char symbol = 127); + ~depuncture_bb_impl(); + + int general_work(int noutput_items, + gr_vector_int& ninput_items, + gr_vector_const_void_star& input_items, + gr_vector_void_star& output_items); + int fixed_rate_ninput_to_noutput(int ninput); + int fixed_rate_noutput_to_ninput(int noutput); + void forecast(int noutput_items, gr_vector_int& ninput_items_required); +}; + +} /* namespace fec */ } /* namespace gr */ #endif /* INCLUDED_FEC_DEPUNCTURE_BB_IMPL_H */ diff --git a/gr-fec/lib/dummy_decoder_impl.cc b/gr-fec/lib/dummy_decoder_impl.cc index f1bada4f5a..4cf95b45e7 100644 --- a/gr-fec/lib/dummy_decoder_impl.cc +++ b/gr-fec/lib/dummy_decoder_impl.cc @@ -33,87 +33,64 @@ #include <vector> namespace gr { - namespace fec { - namespace code { - - generic_decoder::sptr - dummy_decoder::make(int frame_size) - { - return generic_decoder::sptr - (new dummy_decoder_impl(frame_size)); - } - - dummy_decoder_impl::dummy_decoder_impl(int frame_size) - : generic_decoder("dummy_decoder") - { - // Set max frame size here; all buffers and settings will be - // based on this value. - d_max_frame_size = frame_size; - set_frame_size(frame_size); - } - - dummy_decoder_impl::~dummy_decoder_impl() - { - } - - int - dummy_decoder_impl::get_output_size() - { - //unpacked bits - return d_frame_size; - } - - int - dummy_decoder_impl::get_input_size() - { - return d_frame_size; - } - - int - dummy_decoder_impl::get_input_item_size() - { - return sizeof(float); - } - - const char* - dummy_decoder_impl::get_input_conversion() - { - return "none"; - } - - bool - dummy_decoder_impl::set_frame_size(unsigned int frame_size) - { - bool ret = true; - if(frame_size > d_max_frame_size) { - GR_LOG_INFO(d_logger, boost::format("tried to set frame to %1%; max possible is %2%") \ - % frame_size % d_max_frame_size); - frame_size = d_max_frame_size; - ret = false; - } - - d_frame_size = frame_size; - - return ret; - } - - double - dummy_decoder_impl::rate() - { - return 1.0; - } - - void - dummy_decoder_impl::generic_work(void *inbuffer, void *outbuffer) - { - const float *in = (const float*)inbuffer; - int8_t *out = (int8_t*)outbuffer; - - //memcpy(out, in, d_frame_size*sizeof(char)); - volk_32f_binary_slicer_8i(out, in, d_frame_size); - //volk_32f_s32f_convert_8i(out, in, 1.0/2.0, d_frame_size); - } - - } /* namespace code */ - } /* namespace fec */ +namespace fec { +namespace code { + +generic_decoder::sptr dummy_decoder::make(int frame_size) +{ + return generic_decoder::sptr(new dummy_decoder_impl(frame_size)); +} + +dummy_decoder_impl::dummy_decoder_impl(int frame_size) : generic_decoder("dummy_decoder") +{ + // Set max frame size here; all buffers and settings will be + // based on this value. + d_max_frame_size = frame_size; + set_frame_size(frame_size); +} + +dummy_decoder_impl::~dummy_decoder_impl() {} + +int dummy_decoder_impl::get_output_size() +{ + // unpacked bits + return d_frame_size; +} + +int dummy_decoder_impl::get_input_size() { return d_frame_size; } + +int dummy_decoder_impl::get_input_item_size() { return sizeof(float); } + +const char* dummy_decoder_impl::get_input_conversion() { return "none"; } + +bool dummy_decoder_impl::set_frame_size(unsigned int frame_size) +{ + bool ret = true; + if (frame_size > d_max_frame_size) { + GR_LOG_INFO(d_logger, + boost::format("tried to set frame to %1%; max possible is %2%") % + frame_size % d_max_frame_size); + frame_size = d_max_frame_size; + ret = false; + } + + d_frame_size = frame_size; + + return ret; +} + +double dummy_decoder_impl::rate() { return 1.0; } + +void dummy_decoder_impl::generic_work(void* inbuffer, void* outbuffer) +{ + const float* in = (const float*)inbuffer; + int8_t* out = (int8_t*)outbuffer; + + // memcpy(out, in, d_frame_size*sizeof(char)); + volk_32f_binary_slicer_8i(out, in, d_frame_size); + // volk_32f_s32f_convert_8i(out, in, 1.0/2.0, d_frame_size); +} + +} /* namespace code */ +} /* namespace fec */ } /* namespace gr */ diff --git a/gr-fec/lib/dummy_decoder_impl.h b/gr-fec/lib/dummy_decoder_impl.h index bcdd606f18..92860c22c7 100644 --- a/gr-fec/lib/dummy_decoder_impl.h +++ b/gr-fec/lib/dummy_decoder_impl.h @@ -28,33 +28,33 @@ #include <gnuradio/fec/dummy_decoder.h> namespace gr { - namespace fec { - namespace code { - - class FEC_API dummy_decoder_impl : public dummy_decoder - { - private: - //plug into the generic fec api - void generic_work(void *inbuffer, void *outbuffer); - int get_output_size(); - int get_input_size(); - int get_input_item_size(); - const char* get_input_conversion(); - //const char* get_output_conversion(); - - unsigned int d_max_frame_size; - unsigned int d_frame_size; - - public: - dummy_decoder_impl(int frame_size); - ~dummy_decoder_impl(); - - bool set_frame_size(unsigned int frame_size); - double rate(); - }; - - } /* namespace code */ - } /* namespace fec */ +namespace fec { +namespace code { + +class FEC_API dummy_decoder_impl : public dummy_decoder +{ +private: + // plug into the generic fec api + void generic_work(void* inbuffer, void* outbuffer); + int get_output_size(); + int get_input_size(); + int get_input_item_size(); + const char* get_input_conversion(); + // const char* get_output_conversion(); + + unsigned int d_max_frame_size; + unsigned int d_frame_size; + +public: + dummy_decoder_impl(int frame_size); + ~dummy_decoder_impl(); + + bool set_frame_size(unsigned int frame_size); + double rate(); +}; + +} /* namespace code */ +} /* namespace fec */ } /* namespace gr */ #endif /* INCLUDED_FEC_DUMMY_DECODER_IMPL_H */ diff --git a/gr-fec/lib/dummy_encoder_impl.cc b/gr-fec/lib/dummy_encoder_impl.cc index d04ff223c9..240a8217fa 100644 --- a/gr-fec/lib/dummy_encoder_impl.cc +++ b/gr-fec/lib/dummy_encoder_impl.cc @@ -30,84 +30,65 @@ #include <sstream> namespace gr { - namespace fec { - namespace code { - - generic_encoder::sptr - dummy_encoder::make(int frame_size, bool pack, bool packed_bits) - { - return generic_encoder::sptr - (new dummy_encoder_impl(frame_size, pack, packed_bits)); - } - - dummy_encoder_impl::dummy_encoder_impl(int frame_size, bool pack, bool packed_bits) - : generic_encoder("dummy_encoder"), - d_pack_input(pack), - d_packed_bits_output(packed_bits) - { - d_max_frame_size = frame_size; - set_frame_size(frame_size); - } - - dummy_encoder_impl::~dummy_encoder_impl() - { - } - - int - dummy_encoder_impl::get_output_size() - { - return d_frame_size; - } - - int - dummy_encoder_impl::get_input_size() - { - return d_frame_size; - } - - const char* - dummy_encoder_impl::get_input_conversion() - { - return d_pack_input ? "pack" : "none"; - } - - const char* - dummy_encoder_impl::get_output_conversion() - { - return d_packed_bits_output ? "packed_bits" : "none"; - } - - bool - dummy_encoder_impl::set_frame_size(unsigned int frame_size) - { - bool ret = true; - if(frame_size > d_max_frame_size) { - GR_LOG_INFO(d_logger, boost::format("tried to set frame to %1%; max possible is %2%") \ - % frame_size % d_max_frame_size); - frame_size = d_max_frame_size; - ret = false; - } - - d_frame_size = frame_size; - - return ret; - } - - double - dummy_encoder_impl::rate() - { - return 1.0; - } - - void - dummy_encoder_impl::generic_work(void *inbuffer, void *outbuffer) - { - const unsigned char *in = (const unsigned char*)inbuffer; - unsigned char *out = (unsigned char*)outbuffer; - - memcpy(out, in, d_frame_size*sizeof(char)); - } - - } /* namespace code */ - } /* namespace fec */ +namespace fec { +namespace code { + +generic_encoder::sptr dummy_encoder::make(int frame_size, bool pack, bool packed_bits) +{ + return generic_encoder::sptr(new dummy_encoder_impl(frame_size, pack, packed_bits)); +} + +dummy_encoder_impl::dummy_encoder_impl(int frame_size, bool pack, bool packed_bits) + : generic_encoder("dummy_encoder"), + d_pack_input(pack), + d_packed_bits_output(packed_bits) +{ + d_max_frame_size = frame_size; + set_frame_size(frame_size); +} + +dummy_encoder_impl::~dummy_encoder_impl() {} + +int dummy_encoder_impl::get_output_size() { return d_frame_size; } + +int dummy_encoder_impl::get_input_size() { return d_frame_size; } + +const char* dummy_encoder_impl::get_input_conversion() +{ + return d_pack_input ? "pack" : "none"; +} + +const char* dummy_encoder_impl::get_output_conversion() +{ + return d_packed_bits_output ? "packed_bits" : "none"; +} + +bool dummy_encoder_impl::set_frame_size(unsigned int frame_size) +{ + bool ret = true; + if (frame_size > d_max_frame_size) { + GR_LOG_INFO(d_logger, + boost::format("tried to set frame to %1%; max possible is %2%") % + frame_size % d_max_frame_size); + frame_size = d_max_frame_size; + ret = false; + } + + d_frame_size = frame_size; + + return ret; +} + +double dummy_encoder_impl::rate() { return 1.0; } + +void dummy_encoder_impl::generic_work(void* inbuffer, void* outbuffer) +{ + const unsigned char* in = (const unsigned char*)inbuffer; + unsigned char* out = (unsigned char*)outbuffer; + + memcpy(out, in, d_frame_size * sizeof(char)); +} + +} /* namespace code */ +} /* namespace fec */ } /* namespace gr */ diff --git a/gr-fec/lib/dummy_encoder_impl.h b/gr-fec/lib/dummy_encoder_impl.h index 029cecbd19..4cd093d8d3 100644 --- a/gr-fec/lib/dummy_encoder_impl.h +++ b/gr-fec/lib/dummy_encoder_impl.h @@ -28,34 +28,34 @@ p * You should have received a copy of the GNU General Public License #include <gnuradio/fec/dummy_encoder.h> namespace gr { - namespace fec { - namespace code { - - class FEC_API dummy_encoder_impl : public dummy_encoder - { - private: - //plug into the generic fec api - void generic_work(void *inbuffer, void *outbuffer); - int get_output_size(); - int get_input_size(); - const char* get_input_conversion(); - const char* get_output_conversion(); - bool d_pack_input; - bool d_packed_bits_output; - - unsigned int d_max_frame_size; - unsigned int d_frame_size; - - public: - dummy_encoder_impl(int frame_size, bool pack = false, bool packed_bits = false); - ~dummy_encoder_impl(); - - bool set_frame_size(unsigned int frame_size); - double rate(); - }; - - } /* namespace code */ - } /* namespace fec */ +namespace fec { +namespace code { + +class FEC_API dummy_encoder_impl : public dummy_encoder +{ +private: + // plug into the generic fec api + void generic_work(void* inbuffer, void* outbuffer); + int get_output_size(); + int get_input_size(); + const char* get_input_conversion(); + const char* get_output_conversion(); + bool d_pack_input; + bool d_packed_bits_output; + + unsigned int d_max_frame_size; + unsigned int d_frame_size; + +public: + dummy_encoder_impl(int frame_size, bool pack = false, bool packed_bits = false); + ~dummy_encoder_impl(); + + bool set_frame_size(unsigned int frame_size); + double rate(); +}; + +} /* namespace code */ +} /* namespace fec */ } /* namespace gr */ #endif /* INCLUDED_FEC_DUMMY_ENCODER_IMPL_H */ diff --git a/gr-fec/lib/encode_ccsds_27_bb_impl.cc b/gr-fec/lib/encode_ccsds_27_bb_impl.cc index e81cfaa75e..b62c152642 100644 --- a/gr-fec/lib/encode_ccsds_27_bb_impl.cc +++ b/gr-fec/lib/encode_ccsds_27_bb_impl.cc @@ -30,34 +30,33 @@ #include <gnuradio/fec/viterbi.h> namespace gr { - namespace fec { - - encode_ccsds_27_bb::sptr encode_ccsds_27_bb::make() - { - return gnuradio::get_initial_sptr(new encode_ccsds_27_bb_impl()); - } - - encode_ccsds_27_bb_impl::encode_ccsds_27_bb_impl() - : sync_interpolator("encode_ccsds_27_bb", - io_signature::make (1, 1, sizeof(char)), - io_signature::make (1, 1, sizeof(char)), - 16) // Rate 1/2 code, packed to unpacked conversion - { - d_encstate = 0; - } - - int - encode_ccsds_27_bb_impl::work(int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) - { - unsigned char *in = (unsigned char *)input_items[0]; - unsigned char *out = (unsigned char *)output_items[0]; - - d_encstate = encode(out, in, noutput_items/16, d_encstate); - - return noutput_items; - } - - } /* namespace fec */ -}/* namespace gr */ +namespace fec { + +encode_ccsds_27_bb::sptr encode_ccsds_27_bb::make() +{ + return gnuradio::get_initial_sptr(new encode_ccsds_27_bb_impl()); +} + +encode_ccsds_27_bb_impl::encode_ccsds_27_bb_impl() + : sync_interpolator("encode_ccsds_27_bb", + io_signature::make(1, 1, sizeof(char)), + io_signature::make(1, 1, sizeof(char)), + 16) // Rate 1/2 code, packed to unpacked conversion +{ + d_encstate = 0; +} + +int encode_ccsds_27_bb_impl::work(int noutput_items, + gr_vector_const_void_star& input_items, + gr_vector_void_star& output_items) +{ + unsigned char* in = (unsigned char*)input_items[0]; + unsigned char* out = (unsigned char*)output_items[0]; + + d_encstate = encode(out, in, noutput_items / 16, d_encstate); + + return noutput_items; +} + +} /* namespace fec */ +} /* namespace gr */ diff --git a/gr-fec/lib/encode_ccsds_27_bb_impl.h b/gr-fec/lib/encode_ccsds_27_bb_impl.h index b48c1a47f1..3226edde14 100644 --- a/gr-fec/lib/encode_ccsds_27_bb_impl.h +++ b/gr-fec/lib/encode_ccsds_27_bb_impl.h @@ -26,22 +26,22 @@ #include <gnuradio/fec/encode_ccsds_27_bb.h> namespace gr { - namespace fec { +namespace fec { - class FEC_API encode_ccsds_27_bb_impl : public encode_ccsds_27_bb - { - private: - unsigned char d_encstate; +class FEC_API encode_ccsds_27_bb_impl : public encode_ccsds_27_bb +{ +private: + unsigned char d_encstate; - public: - encode_ccsds_27_bb_impl(); +public: + encode_ccsds_27_bb_impl(); - int work(int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); - }; + int work(int noutput_items, + gr_vector_const_void_star& input_items, + gr_vector_void_star& output_items); +}; - } /* namespace fec */ +} /* namespace fec */ } /* namespace gr */ #endif /* INCLUDED_FEC_ENCODE_CCSDS_27_BB_IMPL_H */ diff --git a/gr-fec/lib/encoder_impl.cc b/gr-fec/lib/encoder_impl.cc index ec5a818485..21b71e5e97 100644 --- a/gr-fec/lib/encoder_impl.cc +++ b/gr-fec/lib/encoder_impl.cc @@ -29,77 +29,68 @@ #include <stdio.h> namespace gr { - namespace fec { +namespace fec { - encoder::sptr - encoder::make(generic_encoder::sptr my_encoder, - size_t input_item_size, - size_t output_item_size) - { - return gnuradio::get_initial_sptr - (new encoder_impl(my_encoder, input_item_size, - output_item_size)); - } +encoder::sptr encoder::make(generic_encoder::sptr my_encoder, + size_t input_item_size, + size_t output_item_size) +{ + return gnuradio::get_initial_sptr( + new encoder_impl(my_encoder, input_item_size, output_item_size)); +} - encoder_impl::encoder_impl(generic_encoder::sptr my_encoder, - size_t input_item_size, - size_t output_item_size) - : block("fec_encoder", - io_signature::make(1, 1, input_item_size), - io_signature::make(1, 1, output_item_size)), - d_input_item_size(input_item_size), - d_output_item_size(output_item_size) - { - set_fixed_rate(true); - set_relative_rate((uint64_t)my_encoder->get_output_size(), - (uint64_t)my_encoder->get_input_size()); - set_output_multiple(my_encoder->get_output_size()); - d_encoder = my_encoder; +encoder_impl::encoder_impl(generic_encoder::sptr my_encoder, + size_t input_item_size, + size_t output_item_size) + : block("fec_encoder", + io_signature::make(1, 1, input_item_size), + io_signature::make(1, 1, output_item_size)), + d_input_item_size(input_item_size), + d_output_item_size(output_item_size) +{ + set_fixed_rate(true); + set_relative_rate((uint64_t)my_encoder->get_output_size(), + (uint64_t)my_encoder->get_input_size()); + set_output_multiple(my_encoder->get_output_size()); + d_encoder = my_encoder; - d_input_size = d_encoder->get_input_size()*d_input_item_size; - d_output_size = d_encoder->get_output_size()*d_output_item_size; - } + d_input_size = d_encoder->get_input_size() * d_input_item_size; + d_output_size = d_encoder->get_output_size() * d_output_item_size; +} - encoder_impl::~encoder_impl() - { - } +encoder_impl::~encoder_impl() {} - int - encoder_impl::fixed_rate_ninput_to_noutput(int ninput) - { - return (int)(0.5 + ninput*relative_rate()); - } +int encoder_impl::fixed_rate_ninput_to_noutput(int ninput) +{ + return (int)(0.5 + ninput * relative_rate()); +} - int - encoder_impl::fixed_rate_noutput_to_ninput(int noutput) - { - return (int)(0.5 + noutput/relative_rate()); - } +int encoder_impl::fixed_rate_noutput_to_ninput(int noutput) +{ + return (int)(0.5 + noutput / relative_rate()); +} - void - encoder_impl::forecast(int noutput_items, - gr_vector_int& ninput_items_required) - { - ninput_items_required[0] = fixed_rate_noutput_to_ninput(noutput_items); - } +void encoder_impl::forecast(int noutput_items, gr_vector_int& ninput_items_required) +{ + ninput_items_required[0] = fixed_rate_noutput_to_ninput(noutput_items); +} - int - encoder_impl::general_work(int noutput_items, +int encoder_impl::general_work(int noutput_items, gr_vector_int& ninput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) - { - char *inbuffer = (char*)input_items[0]; - char *outbuffer = (char*)output_items[0]; + gr_vector_const_void_star& input_items, + gr_vector_void_star& output_items) +{ + char* inbuffer = (char*)input_items[0]; + char* outbuffer = (char*)output_items[0]; - for(int i = 0; i < noutput_items/output_multiple(); i++) { - d_encoder->generic_work((void*)(inbuffer+(i*d_input_size)), - (void*)(outbuffer+(i*d_output_size))); - } - - consume_each(fixed_rate_noutput_to_ninput(noutput_items)); - return noutput_items; + for (int i = 0; i < noutput_items / output_multiple(); i++) { + d_encoder->generic_work((void*)(inbuffer + (i * d_input_size)), + (void*)(outbuffer + (i * d_output_size))); } - } /* namespace fec */ + consume_each(fixed_rate_noutput_to_ninput(noutput_items)); + return noutput_items; +} + +} /* namespace fec */ } /* namespace gr */ diff --git a/gr-fec/lib/encoder_impl.h b/gr-fec/lib/encoder_impl.h index 3f325219b8..c4ea372dae 100644 --- a/gr-fec/lib/encoder_impl.h +++ b/gr-fec/lib/encoder_impl.h @@ -26,34 +26,33 @@ #include <gnuradio/fec/encoder.h> namespace gr { - namespace fec { - - class FEC_API encoder_impl : public encoder - { - private: - generic_encoder::sptr d_encoder; - size_t d_input_item_size; - size_t d_output_item_size; - size_t d_input_size; - size_t d_output_size; - - public: - encoder_impl(generic_encoder::sptr my_encoder, - size_t input_item_size, - size_t output_item_size); - ~encoder_impl(); - - int general_work(int noutput_items, - gr_vector_int& ninput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); - int fixed_rate_ninput_to_noutput(int ninput); - int fixed_rate_noutput_to_ninput(int noutput); - void forecast(int noutput_items, - gr_vector_int& ninput_items_required); - }; - - } /* namespace fec */ +namespace fec { + +class FEC_API encoder_impl : public encoder +{ +private: + generic_encoder::sptr d_encoder; + size_t d_input_item_size; + size_t d_output_item_size; + size_t d_input_size; + size_t d_output_size; + +public: + encoder_impl(generic_encoder::sptr my_encoder, + size_t input_item_size, + size_t output_item_size); + ~encoder_impl(); + + int general_work(int noutput_items, + gr_vector_int& ninput_items, + gr_vector_const_void_star& input_items, + gr_vector_void_star& output_items); + int fixed_rate_ninput_to_noutput(int ninput); + int fixed_rate_noutput_to_ninput(int noutput); + void forecast(int noutput_items, gr_vector_int& ninput_items_required); +}; + +} /* namespace fec */ } /* namespace gr */ #endif /* INCLUDED_FEC_ENCODER_IMPL_H */ diff --git a/gr-fec/lib/fec_mtrx_impl.cc b/gr-fec/lib/fec_mtrx_impl.cc index d4b0ac07b5..40705d6397 100644 --- a/gr-fec/lib/fec_mtrx_impl.cc +++ b/gr-fec/lib/fec_mtrx_impl.cc @@ -31,467 +31,425 @@ #include <stdexcept> namespace gr { - namespace fec { - namespace code { - - // For use when casting to a matrix_sptr to provide the proper - // callback to free the memory when the reference count goes to - // 0. Needed to know how to cast from our matrix to gsl_matrix. - void matrix_free(matrix *x) - { - gsl_matrix_free((gsl_matrix*)x); - } - - - matrix_sptr - read_matrix_from_file(const std::string filename) - { - std::ifstream inputFile; - unsigned int ncols, nrows; - - // Open the alist file (needs a C-string) - inputFile.open(filename.c_str()); - if(!inputFile) { - std::stringstream s; - s << "There was a problem opening file '" - << filename << "' for reading."; - throw std::runtime_error(s.str()); - } - - // First line of file is matrix size: # columns, # rows - inputFile >> ncols >> nrows; - - // Now we can allocate memory for the GSL matrix - gsl_matrix *temp_matrix = gsl_matrix_alloc(nrows, ncols); - gsl_matrix_set_zero(temp_matrix); - - // The next few lines in the file are not necessary in - // constructing the matrix. - std::string tempBuffer; - unsigned int counter; - for(counter = 0; counter < 4; counter++) { - getline(inputFile, tempBuffer); - } - - // These next lines list the indices for where the 1s are in - // each column. - unsigned int column_count = 0; - std::string row_number; - - while(column_count < ncols) { - getline(inputFile, tempBuffer); - std::stringstream ss(tempBuffer); - - while(ss >> row_number) { +namespace fec { +namespace code { + +// For use when casting to a matrix_sptr to provide the proper +// callback to free the memory when the reference count goes to +// 0. Needed to know how to cast from our matrix to gsl_matrix. +void matrix_free(matrix* x) { gsl_matrix_free((gsl_matrix*)x); } + + +matrix_sptr read_matrix_from_file(const std::string filename) +{ + std::ifstream inputFile; + unsigned int ncols, nrows; + + // Open the alist file (needs a C-string) + inputFile.open(filename.c_str()); + if (!inputFile) { + std::stringstream s; + s << "There was a problem opening file '" << filename << "' for reading."; + throw std::runtime_error(s.str()); + } + + // First line of file is matrix size: # columns, # rows + inputFile >> ncols >> nrows; + + // Now we can allocate memory for the GSL matrix + gsl_matrix* temp_matrix = gsl_matrix_alloc(nrows, ncols); + gsl_matrix_set_zero(temp_matrix); + + // The next few lines in the file are not necessary in + // constructing the matrix. + std::string tempBuffer; + unsigned int counter; + for (counter = 0; counter < 4; counter++) { + getline(inputFile, tempBuffer); + } + + // These next lines list the indices for where the 1s are in + // each column. + unsigned int column_count = 0; + std::string row_number; + + while (column_count < ncols) { + getline(inputFile, tempBuffer); + std::stringstream ss(tempBuffer); + + while (ss >> row_number) { int row_i = atoi(row_number.c_str()); // alist files index starting from 1, not 0, so decrement row_i--; // set the corresponding matrix element to 1 gsl_matrix_set(temp_matrix, row_i, column_count, 1); - } - column_count++; - } - - // Close the alist file - inputFile.close(); - - // Stash the pointer - matrix_sptr H = matrix_sptr((matrix*)temp_matrix, matrix_free); - - return H; - } - - void - write_matrix_to_file(const std::string filename, matrix_sptr M) - { - std::ofstream outputfile; - - // Open the output file - outputfile.open(filename.c_str()); - if(!outputfile) { - std::stringstream s; - s << "There was a problem opening file '" - << filename << "' for writing."; - throw std::runtime_error(s.str()); } - - unsigned int ncols = M->size2; - unsigned int nrows = M->size1; - std::vector<unsigned int> colweights(ncols, 0); - std::vector<unsigned int> rowweights(nrows, 0); - std::stringstream colout; - std::stringstream rowout; - - for(unsigned int c = 0; c < ncols; c++) { - for(unsigned int r = 0; r < nrows; r++) { + column_count++; + } + + // Close the alist file + inputFile.close(); + + // Stash the pointer + matrix_sptr H = matrix_sptr((matrix*)temp_matrix, matrix_free); + + return H; +} + +void write_matrix_to_file(const std::string filename, matrix_sptr M) +{ + std::ofstream outputfile; + + // Open the output file + outputfile.open(filename.c_str()); + if (!outputfile) { + std::stringstream s; + s << "There was a problem opening file '" << filename << "' for writing."; + throw std::runtime_error(s.str()); + } + + unsigned int ncols = M->size2; + unsigned int nrows = M->size1; + std::vector<unsigned int> colweights(ncols, 0); + std::vector<unsigned int> rowweights(nrows, 0); + std::stringstream colout; + std::stringstream rowout; + + for (unsigned int c = 0; c < ncols; c++) { + for (unsigned int r = 0; r < nrows; r++) { double x = gsl_matrix_get((gsl_matrix*)(M.get()), r, c); - if(x == 1) { - colout << (r + 1) << " "; - colweights[c]++; + if (x == 1) { + colout << (r + 1) << " "; + colweights[c]++; } - } - colout << std::endl; } + colout << std::endl; + } - for(unsigned int r = 0; r < nrows; r++) { - for(unsigned int c = 0; c < ncols; c++) { + for (unsigned int r = 0; r < nrows; r++) { + for (unsigned int c = 0; c < ncols; c++) { double x = gsl_matrix_get((gsl_matrix*)(M.get()), r, c); - if(x == 1) { - rowout << (c + 1) << " "; - rowweights[r]++; + if (x == 1) { + rowout << (c + 1) << " "; + rowweights[r]++; } - } - rowout << std::endl; - } - - outputfile << ncols << " " << nrows << std::endl; - outputfile << (*std::max_element(colweights.begin(), colweights.end())) << " " - << (*std::max_element(rowweights.begin(), rowweights.end())) << std::endl; - - std::vector<unsigned int>::iterator itr; - for(itr = colweights.begin(); itr != colweights.end(); itr++) { - outputfile << (*itr) << " "; - } - outputfile << std::endl; - - for(itr = rowweights.begin(); itr != rowweights.end(); itr++) { - outputfile << (*itr) << " "; } - outputfile << std::endl; - - outputfile << colout.str() << rowout.str(); - - // Close the alist file - outputfile.close(); - } - - matrix_sptr - generate_G_transpose(matrix_sptr H_obj) - { - unsigned int k = H_obj->size1; - unsigned int n = H_obj->size2; - unsigned int row_index, col_index; - - gsl_matrix *G_transp = gsl_matrix_alloc(n, k); - - // Grab P' matrix (P' denotes P transposed) - gsl_matrix *P_transpose = gsl_matrix_alloc(n-k, k); - for(row_index = 0; row_index < n-k; row_index++) { - for(col_index = 0; col_index < k; col_index++) { - int value = gsl_matrix_get((gsl_matrix*)(H_obj.get()), - row_index, col_index); + rowout << std::endl; + } + + outputfile << ncols << " " << nrows << std::endl; + outputfile << (*std::max_element(colweights.begin(), colweights.end())) << " " + << (*std::max_element(rowweights.begin(), rowweights.end())) << std::endl; + + std::vector<unsigned int>::iterator itr; + for (itr = colweights.begin(); itr != colweights.end(); itr++) { + outputfile << (*itr) << " "; + } + outputfile << std::endl; + + for (itr = rowweights.begin(); itr != rowweights.end(); itr++) { + outputfile << (*itr) << " "; + } + outputfile << std::endl; + + outputfile << colout.str() << rowout.str(); + + // Close the alist file + outputfile.close(); +} + +matrix_sptr generate_G_transpose(matrix_sptr H_obj) +{ + unsigned int k = H_obj->size1; + unsigned int n = H_obj->size2; + unsigned int row_index, col_index; + + gsl_matrix* G_transp = gsl_matrix_alloc(n, k); + + // Grab P' matrix (P' denotes P transposed) + gsl_matrix* P_transpose = gsl_matrix_alloc(n - k, k); + for (row_index = 0; row_index < n - k; row_index++) { + for (col_index = 0; col_index < k; col_index++) { + int value = gsl_matrix_get((gsl_matrix*)(H_obj.get()), row_index, col_index); gsl_matrix_set(P_transpose, row_index, col_index, value); - } - } - - // Set G transpose matrix (used for encoding) - gsl_matrix_set_zero(G_transp); - for(row_index = 0; row_index < k; row_index++) { - col_index = row_index; - gsl_matrix_set(G_transp, row_index, col_index, 1); } - for(row_index = k; row_index < n; row_index++) { - for(col_index = 0; col_index < k; col_index++) { + } + + // Set G transpose matrix (used for encoding) + gsl_matrix_set_zero(G_transp); + for (row_index = 0; row_index < k; row_index++) { + col_index = row_index; + gsl_matrix_set(G_transp, row_index, col_index, 1); + } + for (row_index = k; row_index < n; row_index++) { + for (col_index = 0; col_index < k; col_index++) { int value = gsl_matrix_get(P_transpose, row_index - k, col_index); gsl_matrix_set(G_transp, row_index, col_index, value); - } } + } - // Stash the pointer - matrix_sptr G = matrix_sptr((matrix*)G_transp, matrix_free); + // Stash the pointer + matrix_sptr G = matrix_sptr((matrix*)G_transp, matrix_free); - // Free memory - gsl_matrix_free(P_transpose); + // Free memory + gsl_matrix_free(P_transpose); - return G; - } + return G; +} - matrix_sptr - generate_G(matrix_sptr H_obj) - { - matrix_sptr G_trans = generate_G_transpose(H_obj); +matrix_sptr generate_G(matrix_sptr H_obj) +{ + matrix_sptr G_trans = generate_G_transpose(H_obj); - unsigned int k = H_obj->size1; - unsigned int n = H_obj->size2; - gsl_matrix *G = gsl_matrix_alloc(k, n); + unsigned int k = H_obj->size1; + unsigned int n = H_obj->size2; + gsl_matrix* G = gsl_matrix_alloc(k, n); - gsl_matrix_transpose_memcpy(G, (gsl_matrix*)(G_trans.get())); + gsl_matrix_transpose_memcpy(G, (gsl_matrix*)(G_trans.get())); - matrix_sptr Gret = matrix_sptr((matrix*)G, matrix_free); - return Gret; - } + matrix_sptr Gret = matrix_sptr((matrix*)G, matrix_free); + return Gret; +} - matrix_sptr - generate_H(matrix_sptr G_obj) - { - unsigned int row_index, col_index; +matrix_sptr generate_H(matrix_sptr G_obj) +{ + unsigned int row_index, col_index; - unsigned int n = G_obj->size2; - unsigned int k = G_obj->size1; + unsigned int n = G_obj->size2; + unsigned int k = G_obj->size1; - gsl_matrix *G_ptr = (gsl_matrix*)(G_obj.get()); - gsl_matrix *H_ptr = gsl_matrix_alloc(n-k, n); + gsl_matrix* G_ptr = (gsl_matrix*)(G_obj.get()); + gsl_matrix* H_ptr = gsl_matrix_alloc(n - k, n); - // Grab P matrix - gsl_matrix *P = gsl_matrix_alloc(k, n-k); - for(row_index = 0; row_index < k; row_index++) { - for(col_index = 0; col_index < n-k; col_index++) { + // Grab P matrix + gsl_matrix* P = gsl_matrix_alloc(k, n - k); + for (row_index = 0; row_index < k; row_index++) { + for (col_index = 0; col_index < n - k; col_index++) { int value = gsl_matrix_get(G_ptr, row_index, col_index + k); gsl_matrix_set(P, row_index, col_index, value); - } } + } - // Calculate P transpose - gsl_matrix *P_transpose = gsl_matrix_alloc(n-k, k); - gsl_matrix_transpose_memcpy(P_transpose, P); + // Calculate P transpose + gsl_matrix* P_transpose = gsl_matrix_alloc(n - k, k); + gsl_matrix_transpose_memcpy(P_transpose, P); - // Set H matrix. H = [-P' I] but since we are doing mod 2, - // -P = P, so H = [P' I] - gsl_matrix_set_zero(H_ptr); - for(row_index = 0; row_index < n-k; row_index++) { - for(col_index = 0; col_index < k; col_index++) { + // Set H matrix. H = [-P' I] but since we are doing mod 2, + // -P = P, so H = [P' I] + gsl_matrix_set_zero(H_ptr); + for (row_index = 0; row_index < n - k; row_index++) { + for (col_index = 0; col_index < k; col_index++) { int value = gsl_matrix_get(P_transpose, row_index, col_index); gsl_matrix_set(H_ptr, row_index, col_index, value); - } } + } - for(row_index = 0; row_index < n-k; row_index++) { - col_index = row_index + k; - gsl_matrix_set(H_ptr, row_index, col_index, 1); - } + for (row_index = 0; row_index < n - k; row_index++) { + col_index = row_index + k; + gsl_matrix_set(H_ptr, row_index, col_index, 1); + } - // Free memory - gsl_matrix_free(P); - gsl_matrix_free(P_transpose); + // Free memory + gsl_matrix_free(P); + gsl_matrix_free(P_transpose); - matrix_sptr H = matrix_sptr((matrix*)H_ptr, matrix_free); - return H; - } + matrix_sptr H = matrix_sptr((matrix*)H_ptr, matrix_free); + return H; +} - void - print_matrix(const matrix_sptr M, bool numpy) - { - if(!numpy) { - for(size_t i = 0; i < M->size1; i++) { - for(size_t j = 0; j < M->size2; j++) { - std::cout << gsl_matrix_get((gsl_matrix*)(M.get()), i, j) << " "; +void print_matrix(const matrix_sptr M, bool numpy) +{ + if (!numpy) { + for (size_t i = 0; i < M->size1; i++) { + for (size_t j = 0; j < M->size2; j++) { + std::cout << gsl_matrix_get((gsl_matrix*)(M.get()), i, j) << " "; } std::cout << std::endl; - } - std::cout << std::endl; } - else { - std::cout << "numpy.matrix([ "; - for(size_t i = 0; i < M->size1; i++) { + std::cout << std::endl; + } else { + std::cout << "numpy.matrix([ "; + for (size_t i = 0; i < M->size1; i++) { std::cout << "[ "; - for(size_t j = 0; j < M->size2; j++) { - std::cout << gsl_matrix_get((gsl_matrix*)(M.get()), i, j) << ", "; + for (size_t j = 0; j < M->size2; j++) { + std::cout << gsl_matrix_get((gsl_matrix*)(M.get()), i, j) << ", "; } std::cout << "], "; - } - std::cout << "])" << std::endl; - } - } - - - fec_mtrx_impl::fec_mtrx_impl() - { - // Assume the convention that parity bits come last in the - // codeword - d_par_bits_last = true; - } - - const gsl_matrix* - fec_mtrx_impl::H() const - { - const gsl_matrix *H_ptr = (gsl_matrix*)(d_H_sptr.get()); - return H_ptr; - } - - unsigned int - fec_mtrx_impl::n() const - { - return d_n; - } - - unsigned int - fec_mtrx_impl::k() const - { - return d_k; - } - - void - fec_mtrx_impl::add_matrices_mod2(gsl_matrix *result, - const gsl_matrix *matrix1, - const gsl_matrix *matrix2) const - { - // This function returns ((matrix1 + matrix2) % 2). - - // Verify that matrix sizes are appropriate - unsigned int matrix1_rows = (*matrix1).size1; - unsigned int matrix1_cols = (*matrix1).size2; - unsigned int matrix2_rows = (*matrix2).size1; - unsigned int matrix2_cols = (*matrix2).size2; - - if (matrix1_rows != matrix2_rows) { - std::cout << "Error in add_matrices_mod2. Matrices do" - << " not have the same number of rows.\n"; - exit(1); } - if (matrix1_cols != matrix2_cols) { - std::cout << "Error in add_matrices_mod2. Matrices do" - << " not have the same number of columns.\n"; - exit(1); - } - - // Copy matrix1 into result - gsl_matrix_memcpy(result, matrix1); - - // Do subtraction. This is not mod 2 yet. - gsl_matrix_add(result, matrix2); - - // Take care of mod 2 manually - unsigned int row_index, col_index; - for (row_index = 0; row_index < matrix1_rows; row_index++) { - for (col_index = 0; col_index < matrix1_cols;col_index++) { + std::cout << "])" << std::endl; + } +} + + +fec_mtrx_impl::fec_mtrx_impl() +{ + // Assume the convention that parity bits come last in the + // codeword + d_par_bits_last = true; +} + +const gsl_matrix* fec_mtrx_impl::H() const +{ + const gsl_matrix* H_ptr = (gsl_matrix*)(d_H_sptr.get()); + return H_ptr; +} + +unsigned int fec_mtrx_impl::n() const { return d_n; } + +unsigned int fec_mtrx_impl::k() const { return d_k; } + +void fec_mtrx_impl::add_matrices_mod2(gsl_matrix* result, + const gsl_matrix* matrix1, + const gsl_matrix* matrix2) const +{ + // This function returns ((matrix1 + matrix2) % 2). + + // Verify that matrix sizes are appropriate + unsigned int matrix1_rows = (*matrix1).size1; + unsigned int matrix1_cols = (*matrix1).size2; + unsigned int matrix2_rows = (*matrix2).size1; + unsigned int matrix2_cols = (*matrix2).size2; + + if (matrix1_rows != matrix2_rows) { + std::cout << "Error in add_matrices_mod2. Matrices do" + << " not have the same number of rows.\n"; + exit(1); + } + if (matrix1_cols != matrix2_cols) { + std::cout << "Error in add_matrices_mod2. Matrices do" + << " not have the same number of columns.\n"; + exit(1); + } + + // Copy matrix1 into result + gsl_matrix_memcpy(result, matrix1); + + // Do subtraction. This is not mod 2 yet. + gsl_matrix_add(result, matrix2); + + // Take care of mod 2 manually + unsigned int row_index, col_index; + for (row_index = 0; row_index < matrix1_rows; row_index++) { + for (col_index = 0; col_index < matrix1_cols; col_index++) { int value = gsl_matrix_get(result, row_index, col_index); int new_value = abs(value) % 2; gsl_matrix_set(result, row_index, col_index, new_value); - } - } - } - - void - fec_mtrx_impl::mult_matrices_mod2(gsl_matrix *result, - const gsl_matrix *matrix1, - const gsl_matrix *matrix2) const - { - // Verify that matrix sizes are appropriate - unsigned int a = (*matrix1).size1; // # of rows - unsigned int b = (*matrix1).size2; // # of columns - unsigned int c = (*matrix2).size1; // # of rows - unsigned int d = (*matrix2).size2; // # of columns - if (b != c) { - std::cout << "Error in " - << "fec_mtrx_impl::mult_matrices_mod2." - << " Matrix dimensions do not allow for matrix " - << "multiplication operation:\nmatrix1 is " - << a << " x " << b << ", and matrix2 is " << c - << " x " << d << ".\n"; - exit(1); } - - // Perform matrix multiplication. This is not mod 2. - gsl_blas_dgemm (CblasNoTrans, CblasNoTrans, 1.0, matrix1, - matrix2, 0.0, result); - - // Take care of mod 2 manually. - unsigned int row_index, col_index; - unsigned int rows = (*result).size1, - cols = (*result).size2; - for (row_index = 0; row_index < rows; row_index++) { - for (col_index = 0; col_index < cols; col_index++) { - int value = gsl_matrix_get(result, row_index,col_index); + } +} + +void fec_mtrx_impl::mult_matrices_mod2(gsl_matrix* result, + const gsl_matrix* matrix1, + const gsl_matrix* matrix2) const +{ + // Verify that matrix sizes are appropriate + unsigned int a = (*matrix1).size1; // # of rows + unsigned int b = (*matrix1).size2; // # of columns + unsigned int c = (*matrix2).size1; // # of rows + unsigned int d = (*matrix2).size2; // # of columns + if (b != c) { + std::cout << "Error in " + << "fec_mtrx_impl::mult_matrices_mod2." + << " Matrix dimensions do not allow for matrix " + << "multiplication operation:\nmatrix1 is " << a << " x " << b + << ", and matrix2 is " << c << " x " << d << ".\n"; + exit(1); + } + + // Perform matrix multiplication. This is not mod 2. + gsl_blas_dgemm(CblasNoTrans, CblasNoTrans, 1.0, matrix1, matrix2, 0.0, result); + + // Take care of mod 2 manually. + unsigned int row_index, col_index; + unsigned int rows = (*result).size1, cols = (*result).size2; + for (row_index = 0; row_index < rows; row_index++) { + for (col_index = 0; col_index < cols; col_index++) { + int value = gsl_matrix_get(result, row_index, col_index); int new_value = value % 2; gsl_matrix_set(result, row_index, col_index, new_value); - } - } - } - - gsl_matrix* - fec_mtrx_impl::calc_inverse_mod2(const gsl_matrix *original_matrix) const - { - - // Let n represent the size of the n x n square matrix - unsigned int n = (*original_matrix).size1; - unsigned int row_index, col_index; - - // Make a copy of the original matrix, call it matrix_altered. - // This matrix will be modified by the GSL functions. - gsl_matrix *matrix_altered = gsl_matrix_alloc(n, n); - gsl_matrix_memcpy(matrix_altered, original_matrix); - - // In order to find the inverse, GSL must perform a LU - // decomposition first. - gsl_permutation *permutation = gsl_permutation_alloc(n); - int signum; - gsl_linalg_LU_decomp(matrix_altered, permutation, &signum); - - // Allocate memory to store the matrix inverse - gsl_matrix *matrix_inverse = gsl_matrix_alloc(n,n); - - // Find matrix inverse. This is not mod2. - int status = gsl_linalg_LU_invert(matrix_altered, - permutation, - matrix_inverse); - - if (status) { - // Inverse not found by GSL functions. - throw "Error in calc_inverse_mod2(): inverse not found.\n"; } + } +} + +gsl_matrix* fec_mtrx_impl::calc_inverse_mod2(const gsl_matrix* original_matrix) const +{ + + // Let n represent the size of the n x n square matrix + unsigned int n = (*original_matrix).size1; + unsigned int row_index, col_index; + + // Make a copy of the original matrix, call it matrix_altered. + // This matrix will be modified by the GSL functions. + gsl_matrix* matrix_altered = gsl_matrix_alloc(n, n); + gsl_matrix_memcpy(matrix_altered, original_matrix); + + // In order to find the inverse, GSL must perform a LU + // decomposition first. + gsl_permutation* permutation = gsl_permutation_alloc(n); + int signum; + gsl_linalg_LU_decomp(matrix_altered, permutation, &signum); - // Find determinant - float determinant = gsl_linalg_LU_det(matrix_altered,signum); + // Allocate memory to store the matrix inverse + gsl_matrix* matrix_inverse = gsl_matrix_alloc(n, n); - // Multiply the matrix inverse by the determinant. - gsl_matrix_scale(matrix_inverse, determinant); + // Find matrix inverse. This is not mod2. + int status = gsl_linalg_LU_invert(matrix_altered, permutation, matrix_inverse); - // Take mod 2 of each element in the matrix. - for (row_index = 0; row_index < n; row_index++) { - for (col_index = 0; col_index < n; col_index++) { + if (status) { + // Inverse not found by GSL functions. + throw "Error in calc_inverse_mod2(): inverse not found.\n"; + } - float value = gsl_matrix_get(matrix_inverse, - row_index, - col_index); + // Find determinant + float determinant = gsl_linalg_LU_det(matrix_altered, signum); + + // Multiply the matrix inverse by the determinant. + gsl_matrix_scale(matrix_inverse, determinant); + + // Take mod 2 of each element in the matrix. + for (row_index = 0; row_index < n; row_index++) { + for (col_index = 0; col_index < n; col_index++) { + + float value = gsl_matrix_get(matrix_inverse, row_index, col_index); // take care of mod 2 int value_cast_as_int = static_cast<int>(value); - int temp_value = abs(fmod(value_cast_as_int,2)); + int temp_value = abs(fmod(value_cast_as_int, 2)); - gsl_matrix_set(matrix_inverse, - row_index, - col_index, - temp_value); - } + gsl_matrix_set(matrix_inverse, row_index, col_index, temp_value); } + } - int max_value = gsl_matrix_max(matrix_inverse); - if (!max_value) { - throw "Error in calc_inverse_mod2(): The matrix inverse found is all zeros.\n"; - } - - // Verify that the inverse was found by taking matrix - // product of original_matrix and the inverse, which should - // equal the identity matrix. - gsl_matrix *test = gsl_matrix_alloc(n,n); - mult_matrices_mod2(test, original_matrix, matrix_inverse); + int max_value = gsl_matrix_max(matrix_inverse); + if (!max_value) { + throw "Error in calc_inverse_mod2(): The matrix inverse found is all zeros.\n"; + } - gsl_matrix *identity = gsl_matrix_alloc(n,n); - gsl_matrix_set_identity(identity); - //int test_if_equal = gsl_matrix_equal(identity,test); - gsl_matrix_sub(identity, test); // should be null set if equal + // Verify that the inverse was found by taking matrix + // product of original_matrix and the inverse, which should + // equal the identity matrix. + gsl_matrix* test = gsl_matrix_alloc(n, n); + mult_matrices_mod2(test, original_matrix, matrix_inverse); - double test_if_not_equal = gsl_matrix_max(identity); + gsl_matrix* identity = gsl_matrix_alloc(n, n); + gsl_matrix_set_identity(identity); + // int test_if_equal = gsl_matrix_equal(identity,test); + gsl_matrix_sub(identity, test); // should be null set if equal - if(test_if_not_equal > 0) { - throw "Error in calc_inverse_mod2(): The matrix inverse found is not valid.\n"; - } + double test_if_not_equal = gsl_matrix_max(identity); - return matrix_inverse; - } + if (test_if_not_equal > 0) { + throw "Error in calc_inverse_mod2(): The matrix inverse found is not valid.\n"; + } - bool - fec_mtrx_impl::parity_bits_come_last() const - { - return d_par_bits_last; - } + return matrix_inverse; +} - fec_mtrx_impl::~fec_mtrx_impl() - { +bool fec_mtrx_impl::parity_bits_come_last() const { return d_par_bits_last; } - } +fec_mtrx_impl::~fec_mtrx_impl() {} - } /* namespace code */ - } /* namespace fec */ +} /* namespace code */ +} /* namespace fec */ } /* namespace gr */ diff --git a/gr-fec/lib/fec_mtrx_impl.h b/gr-fec/lib/fec_mtrx_impl.h index 8857b74321..8b58864e61 100644 --- a/gr-fec/lib/fec_mtrx_impl.h +++ b/gr-fec/lib/fec_mtrx_impl.h @@ -31,68 +31,66 @@ #include <gnuradio/fec/fec_mtrx.h> namespace gr { - namespace fec { - namespace code { +namespace fec { +namespace code { - class fec_mtrx_impl : public fec_mtrx - { - protected: - //! Constructor - fec_mtrx_impl(); +class fec_mtrx_impl : public fec_mtrx +{ +protected: + //! Constructor + fec_mtrx_impl(); - //! Codeword length n - unsigned int d_n; + //! Codeword length n + unsigned int d_n; - //! Information word length k - unsigned int d_k; + //! Information word length k + unsigned int d_k; - //! Number of rows in the matrix read in from alist file - unsigned int d_num_rows; + //! Number of rows in the matrix read in from alist file + unsigned int d_num_rows; - //! Number of columns in the matrix read in from alist file - unsigned int d_num_cols; + //! Number of columns in the matrix read in from alist file + unsigned int d_num_cols; - //! GSL matrix structure for the parity check matrix - matrix_sptr d_H_sptr; + //! GSL matrix structure for the parity check matrix + matrix_sptr d_H_sptr; - //! Flag for whether or not the parity bits come first or last - bool d_par_bits_last; + //! Flag for whether or not the parity bits come first or last + bool d_par_bits_last; - public: - //! Returns the parity check matrix H (needed by decoder) - const gsl_matrix *H() const; +public: + //! Returns the parity check matrix H (needed by decoder) + const gsl_matrix* H() const; - //!Get the codeword length n - unsigned int n() const; + //! Get the codeword length n + unsigned int n() const; - //! Get the information word length k - unsigned int k() const; + //! Get the information word length k + unsigned int k() const; - //! Subtract matrices using mod2 operations - void add_matrices_mod2(gsl_matrix *result, - const gsl_matrix *, - const gsl_matrix *) const; + //! Subtract matrices using mod2 operations + void + add_matrices_mod2(gsl_matrix* result, const gsl_matrix*, const gsl_matrix*) const; - //! Multiply matrices using mod2 operations - void mult_matrices_mod2(gsl_matrix *result, - const gsl_matrix *, - const gsl_matrix *) const; + //! Multiply matrices using mod2 operations + void + mult_matrices_mod2(gsl_matrix* result, const gsl_matrix*, const gsl_matrix*) const; - //! Invert a square matrix using mod2 operations - gsl_matrix *calc_inverse_mod2(const gsl_matrix *) const; + //! Invert a square matrix using mod2 operations + gsl_matrix* calc_inverse_mod2(const gsl_matrix*) const; - /*! - * \brief Get Boolean for whether or not parity bits come first or last - * \details - * The decoder will need to know if the parity bits are - * coming first or last - */ - bool parity_bits_come_last() const; + /*! + * \brief Get Boolean for whether or not parity bits come first or last + * \details + * The decoder will need to know if the parity bits are + * coming first or last + */ + bool parity_bits_come_last() const; - virtual ~fec_mtrx_impl(); - }; - } - } -} + virtual ~fec_mtrx_impl(); +}; +} // namespace code +} // namespace fec +} // namespace gr #endif /* INCLUDED_fec_mtrx_impl_H */ diff --git a/gr-fec/lib/generic_decoder.cc b/gr-fec/lib/generic_decoder.cc index f9608a447d..fac9490495 100644 --- a/gr-fec/lib/generic_decoder.cc +++ b/gr-fec/lib/generic_decoder.cc @@ -29,134 +29,88 @@ #include <stdio.h> namespace gr { - namespace fec { - - generic_decoder::generic_decoder(std::string name) - { - d_name = name; - my_id = base_unique_id++; - - prefs *p = prefs::singleton(); - std::string config_file = p->get_string("LOG", "log_config", ""); - std::string log_level = p->get_string("LOG", "log_level", "off"); - std::string log_file = p->get_string("LOG", "log_file", ""); - - GR_CONFIG_LOGGER(config_file); - - GR_LOG_GETLOGGER(LOG, "gr_log." + alias()); - GR_LOG_SET_LEVEL(LOG, log_level); - if(log_file.size() > 0) { - if(log_file == "stdout") { - GR_LOG_SET_CONSOLE_APPENDER(LOG, "stdout","gr::log :%p: %c{1} - %m%n"); - } - else if(log_file == "stderr") { - GR_LOG_SET_CONSOLE_APPENDER(LOG, "stderr","gr::log :%p: %c{1} - %m%n"); - } - else { - GR_LOG_SET_FILE_APPENDER(LOG, log_file , true,"%r :%p: %c{1} - %m%n"); +namespace fec { + +generic_decoder::generic_decoder(std::string name) +{ + d_name = name; + my_id = base_unique_id++; + + prefs* p = prefs::singleton(); + std::string config_file = p->get_string("LOG", "log_config", ""); + std::string log_level = p->get_string("LOG", "log_level", "off"); + std::string log_file = p->get_string("LOG", "log_file", ""); + + GR_CONFIG_LOGGER(config_file); + + GR_LOG_GETLOGGER(LOG, "gr_log." + alias()); + GR_LOG_SET_LEVEL(LOG, log_level); + if (log_file.size() > 0) { + if (log_file == "stdout") { + GR_LOG_SET_CONSOLE_APPENDER(LOG, "stdout", "gr::log :%p: %c{1} - %m%n"); + } else if (log_file == "stderr") { + GR_LOG_SET_CONSOLE_APPENDER(LOG, "stderr", "gr::log :%p: %c{1} - %m%n"); + } else { + GR_LOG_SET_FILE_APPENDER(LOG, log_file, true, "%r :%p: %c{1} - %m%n"); } - } - - d_logger = LOG; } - generic_decoder::~generic_decoder() - { - } + d_logger = LOG; +} - int - generic_decoder::get_history() - { - return 0; - } +generic_decoder::~generic_decoder() {} - float - generic_decoder::get_shift() - { - return 0.0; - } +int generic_decoder::get_history() { return 0; } - int - generic_decoder::get_input_item_size() - { - return sizeof(float); - } +float generic_decoder::get_shift() { return 0.0; } - int - generic_decoder::get_output_item_size() - { - return sizeof(char); - } +int generic_decoder::get_input_item_size() { return sizeof(float); } - const char* - generic_decoder::get_input_conversion() - { - return "none"; - } +int generic_decoder::get_output_item_size() { return sizeof(char); } - const char* - generic_decoder::get_output_conversion() - { - return "none"; - } +const char* generic_decoder::get_input_conversion() { return "none"; } - int generic_decoder::base_unique_id = 1; - int - generic_decoder::unique_id() - { - return my_id; - } +const char* generic_decoder::get_output_conversion() { return "none"; } - /******************************************************* - * Static functions - ******************************************************/ - int - get_decoder_output_size(generic_decoder::sptr my_decoder) - { - return my_decoder->get_output_size(); - } +int generic_decoder::base_unique_id = 1; +int generic_decoder::unique_id() { return my_id; } - int - get_history(generic_decoder::sptr my_decoder) - { - return my_decoder->get_history(); - } +/******************************************************* + * Static functions + ******************************************************/ +int get_decoder_output_size(generic_decoder::sptr my_decoder) +{ + return my_decoder->get_output_size(); +} - int - get_decoder_input_size(generic_decoder::sptr my_decoder) - { - return my_decoder->get_input_size(); - } +int get_history(generic_decoder::sptr my_decoder) { return my_decoder->get_history(); } - int - get_decoder_output_item_size(generic_decoder::sptr my_decoder) - { - return my_decoder->get_output_item_size(); - } +int get_decoder_input_size(generic_decoder::sptr my_decoder) +{ + return my_decoder->get_input_size(); +} - int - get_decoder_input_item_size(generic_decoder::sptr my_decoder) - { - return my_decoder->get_input_item_size(); - } +int get_decoder_output_item_size(generic_decoder::sptr my_decoder) +{ + return my_decoder->get_output_item_size(); +} - float - get_shift(generic_decoder::sptr my_decoder) - { - return my_decoder->get_shift(); - } +int get_decoder_input_item_size(generic_decoder::sptr my_decoder) +{ + return my_decoder->get_input_item_size(); +} - const char* - get_decoder_input_conversion(generic_decoder::sptr my_decoder) - { - return my_decoder->get_input_conversion(); - } +float get_shift(generic_decoder::sptr my_decoder) { return my_decoder->get_shift(); } - const char* - get_decoder_output_conversion(generic_decoder::sptr my_decoder) - { - return my_decoder->get_output_conversion(); - } +const char* get_decoder_input_conversion(generic_decoder::sptr my_decoder) +{ + return my_decoder->get_input_conversion(); +} + +const char* get_decoder_output_conversion(generic_decoder::sptr my_decoder) +{ + return my_decoder->get_output_conversion(); +} - } /* namespace fec */ +} /* namespace fec */ } /* namespace gr */ diff --git a/gr-fec/lib/generic_encoder.cc b/gr-fec/lib/generic_encoder.cc index db1c9f67e8..430aa3bc4d 100644 --- a/gr-fec/lib/generic_encoder.cc +++ b/gr-fec/lib/generic_encoder.cc @@ -29,86 +29,66 @@ #include <stdio.h> namespace gr { - namespace fec { - - generic_encoder::generic_encoder(std::string name) - { - d_name = name; - my_id = base_unique_id++; - - prefs *p = prefs::singleton(); - std::string config_file = p->get_string("LOG", "log_config", ""); - std::string log_level = p->get_string("LOG", "log_level", "off"); - std::string log_file = p->get_string("LOG", "log_file", ""); - - GR_CONFIG_LOGGER(config_file); - - GR_LOG_GETLOGGER(LOG, "gr_log." + alias()); - GR_LOG_SET_LEVEL(LOG, log_level); - if(log_file.size() > 0) { - if(log_file == "stdout") { - GR_LOG_SET_CONSOLE_APPENDER(LOG, "stdout","gr::log :%p: %c{1} - %m%n"); +namespace fec { + +generic_encoder::generic_encoder(std::string name) +{ + d_name = name; + my_id = base_unique_id++; + + prefs* p = prefs::singleton(); + std::string config_file = p->get_string("LOG", "log_config", ""); + std::string log_level = p->get_string("LOG", "log_level", "off"); + std::string log_file = p->get_string("LOG", "log_file", ""); + + GR_CONFIG_LOGGER(config_file); + + GR_LOG_GETLOGGER(LOG, "gr_log." + alias()); + GR_LOG_SET_LEVEL(LOG, log_level); + if (log_file.size() > 0) { + if (log_file == "stdout") { + GR_LOG_SET_CONSOLE_APPENDER(LOG, "stdout", "gr::log :%p: %c{1} - %m%n"); + } else if (log_file == "stderr") { + GR_LOG_SET_CONSOLE_APPENDER(LOG, "stderr", "gr::log :%p: %c{1} - %m%n"); + } else { + GR_LOG_SET_FILE_APPENDER(LOG, log_file, true, "%r :%p: %c{1} - %m%n"); } - else if(log_file == "stderr") { - GR_LOG_SET_CONSOLE_APPENDER(LOG, "stderr","gr::log :%p: %c{1} - %m%n"); - } - else { - GR_LOG_SET_FILE_APPENDER(LOG, log_file , true,"%r :%p: %c{1} - %m%n"); - } - } - - d_logger = LOG; } - generic_encoder::~generic_encoder() - { - } + d_logger = LOG; +} - const char* - generic_encoder::get_input_conversion() - { - return "none"; - } +generic_encoder::~generic_encoder() {} - const char* - generic_encoder::get_output_conversion() - { - return "none"; - } +const char* generic_encoder::get_input_conversion() { return "none"; } - int generic_encoder::base_unique_id = 1; - int - generic_encoder::unique_id() - { - return my_id; - } +const char* generic_encoder::get_output_conversion() { return "none"; } - /******************************************************* - * Static functions - ******************************************************/ - int - get_encoder_output_size(generic_encoder::sptr my_encoder) - { - return my_encoder->get_output_size(); - } +int generic_encoder::base_unique_id = 1; +int generic_encoder::unique_id() { return my_id; } - int - get_encoder_input_size(generic_encoder::sptr my_encoder) - { - return my_encoder->get_input_size(); - } +/******************************************************* + * Static functions + ******************************************************/ +int get_encoder_output_size(generic_encoder::sptr my_encoder) +{ + return my_encoder->get_output_size(); +} - const char* - get_encoder_input_conversion(generic_encoder::sptr my_encoder) - { - return my_encoder->get_input_conversion(); - } +int get_encoder_input_size(generic_encoder::sptr my_encoder) +{ + return my_encoder->get_input_size(); +} - const char* - get_encoder_output_conversion(generic_encoder::sptr my_encoder) - { - return my_encoder->get_output_conversion(); - } +const char* get_encoder_input_conversion(generic_encoder::sptr my_encoder) +{ + return my_encoder->get_input_conversion(); +} + +const char* get_encoder_output_conversion(generic_encoder::sptr my_encoder) +{ + return my_encoder->get_output_conversion(); +} - } /* namespace fec */ +} /* namespace fec */ } /* namespace gr */ diff --git a/gr-fec/lib/gf2mat.cc b/gr-fec/lib/gf2mat.cc index accc2859f2..3bf660670c 100644 --- a/gr-fec/lib/gf2mat.cc +++ b/gr-fec/lib/gf2mat.cc @@ -23,60 +23,56 @@ #include <gnuradio/fec/gf2mat.h> #include <iostream> -GF2Mat::GF2Mat(int m, int n) { +GF2Mat::GF2Mat(int m, int n) +{ M = m; N = n; H.resize(M); - for ( int i = 0; i < M; i++ ) { + for (int i = 0; i < M; i++) { H[i].resize(N); - for ( int j = 0; j < N; j++ ) { + for (int j = 0; j < N; j++) { H[i][j] = char(0); } } } -GF2Mat::GF2Mat(std::vector <std::vector<char> > X) { +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++ ) { + for (int i = 0; i < M; i++) { H[i].resize(N); - for ( int j = 0; j < N; j++ ){ + for (int j = 0; j < N; j++) { H[i][j] = X[i][j]; } } } -GF2Mat::GF2Mat(alist _list) { +GF2Mat::GF2Mat(alist _list) +{ M = _list.get_M(); N = _list.get_N(); H.resize(M); - for ( int i = 0; i < M; i++ ) { + for (int i = 0; i < M; i++) { H[i].resize(N); - for ( int j = 0; j < N; j++ ) { + 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_M() { return M; } -int GF2Mat::get_N() { - return N; -} +int GF2Mat::get_N() { return N; } -void GF2Mat::set_element(int i, int j, char val) { - H[i][j] = val; -} +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]; -} +char GF2Mat::get_element(int i, int j) { return H[i][j]; } -void GF2Mat::print_matrix() { +void GF2Mat::print_matrix() +{ for (int i = 0; i < M; i++) { for (int j = 0; j < N; j++) { std::cout << int(H[i][j]) << " "; @@ -85,64 +81,72 @@ void GF2Mat::print_matrix() { } } -GF2Vec GF2Mat::operator[](int i) { +GF2Vec GF2Mat::operator[](int i) +{ GF2Vec row(N); row.set_vec(H[i]); return row; } -GF2Vec GF2Mat::get_row(int i) { +GF2Vec GF2Mat::get_row(int i) +{ GF2Vec row(N); - for ( int j = 0; j < N; j++ ){ + for (int j = 0; j < N; j++) { row[j] = H[i][j]; } return row; } -GF2Vec GF2Mat::get_col(int i) { +GF2Vec GF2Mat::get_col(int i) +{ GF2Vec col(M); - for ( int j = 0; j < M; j++ ) { + 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++ ) { +void GF2Mat::add_cols(int i, int j) +{ + for (int row = 0; row < M; row++) { H[row][i] = H[row][i] ^ H[row][j]; } } -void GF2Mat::add_rows(int i, int j) { - for ( int col = 0; col < N; col++ ) { +void GF2Mat::add_rows(int i, int j) +{ + for (int col = 0; col < N; col++) { H[i][col] = H[i][col] ^ H[j][col]; } } -void GF2Mat::set_row(int row, GF2Vec vec) { - for ( int j = 0; j < N; j++ ) { +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++ ) { +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) { +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) { +GF2Mat GF2Mat::get_G(std::vector<int>& permute, int& rank) +{ permute.resize(N); rank = 0; - for ( int col = 0; col < N; col++ ) { + for (int col = 0; col < N; col++) { permute[col] = col; } GF2Mat G(H); @@ -151,8 +155,8 @@ GF2Mat GF2Mat::get_G(std::vector<int> & permute, int temp; while (diag < limit) { bool non_zero = false; - for ( int col = diag; col < N; col++ ) { - if ( G.get_element(diag, col) == char(1) ) { + for (int col = diag; col < N; col++) { + if (G.get_element(diag, col) == char(1)) { non_zero = true; rank++; G.swap_cols(diag, col); @@ -163,22 +167,21 @@ GF2Mat GF2Mat::get_G(std::vector<int> & permute, } } if (non_zero) { - for ( int row = 0; row < diag; row++ ) { - if (G.get_element(row, diag) == char(1)){ + 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++ ) { + for (int row = diag + 1; row < M; row++) { if (G.get_element(row, diag) == char(1)) { G.add_rows(row, diag); } } diag++; - } - else{ + } else { GF2Vec current_row; current_row = G.get_row(diag); - for ( int row = diag; row < limit - 1; row++ ) { + for (int row = diag; row < limit - 1; row++) { G.set_row(row, G.get_row(row + 1)); } G.set_row(limit - 1, current_row); @@ -188,6 +191,4 @@ GF2Mat GF2Mat::get_G(std::vector<int> & permute, return G; } -std::vector<std::vector<char> > GF2Mat::get_H() { - return H; -} +std::vector<std::vector<char>> GF2Mat::get_H() { return H; } diff --git a/gr-fec/lib/gf2vec.cc b/gr-fec/lib/gf2vec.cc index 11df4d8dd0..6aa48e4408 100644 --- a/gr-fec/lib/gf2vec.cc +++ b/gr-fec/lib/gf2vec.cc @@ -23,84 +23,53 @@ #include <gnuradio/fec/gf2vec.h> #include <iostream> -GF2Vec::GF2Vec(int size) -{ - vec.resize(size); -} +GF2Vec::GF2Vec(int size) { vec.resize(size); } -void -GF2Vec::set_vec(const std::vector<char> in) -{ - vec = in; -} +void GF2Vec::set_vec(const std::vector<char> in) { vec = in; } -std::vector<char> -GF2Vec::get_vec() -{ - return vec; -} +std::vector<char> GF2Vec::get_vec() { return vec; } -int -GF2Vec::size() -{ - return vec.size(); -} +int GF2Vec::size() { return vec.size(); } -char& -GF2Vec::operator[](int i) -{ - return vec[i]; -} +char& GF2Vec::operator[](int i) { return vec[i]; } -GF2Vec -operator+(GF2Vec a, GF2Vec b) +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 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) +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; + 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 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; + 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() +void GF2Vec::print_vec() { - for (int i = 0; i < size(); i++ ) { - std::cout << int(vec[i]) << " "; - } - std::cout << '\n'; + 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::resize(int size) { vec.resize(size); } -void -GF2Vec::operator=(GF2Vec x) -{ - set_vec(x.get_vec()); -} +void GF2Vec::operator=(GF2Vec x) { set_vec(x.get_vec()); } diff --git a/gr-fec/lib/ldpc_G_matrix_impl.cc b/gr-fec/lib/ldpc_G_matrix_impl.cc index 0ea76f2ef4..a17c571ec9 100644 --- a/gr-fec/lib/ldpc_G_matrix_impl.cc +++ b/gr-fec/lib/ldpc_G_matrix_impl.cc @@ -29,270 +29,260 @@ #include <iostream> namespace gr { - namespace fec { - namespace code { - - ldpc_G_matrix::sptr - ldpc_G_matrix::make(const std::string filename) - { - return ldpc_G_matrix::sptr - (new ldpc_G_matrix_impl(filename)); - } - - ldpc_G_matrix_impl::ldpc_G_matrix_impl(const std::string filename) - : fec_mtrx_impl() - { - configure_default_loggers(d_logger, d_debug_logger, "ldpc_G_matrix"); - - // Read the matrix from a file in alist format - matrix_sptr x = read_matrix_from_file(filename); - d_num_cols = x->size2; - d_num_rows = x->size1; - - // Make an actual copy so we guarantee that we're not sharing - // memory with another class that reads the same alist file. - gsl_matrix *G = gsl_matrix_alloc(d_num_rows, d_num_cols); - gsl_matrix_memcpy(G, (gsl_matrix*)(x.get())); - - unsigned int row_index, col_index; - - // First, check if we have a generator matrix G in systematic - // form, G = [I P], where I is a k x k identity matrix and P - // is the parity submatrix. - - // Length of codeword = # of columns of generator matrix - d_n = d_num_cols; - // Length of information word = # of rows of generator matrix - d_k = d_num_rows; - - gsl_matrix *I_test = gsl_matrix_alloc(d_k, d_k); - gsl_matrix *identity = gsl_matrix_alloc(d_k, d_k); - gsl_matrix_set_identity(identity); - - for(row_index = 0; row_index < d_k; row_index++) { - for(col_index = 0; col_index < d_k; col_index++) { - int value = gsl_matrix_get(G, row_index, col_index); - gsl_matrix_set(I_test, row_index, col_index, value); - } - } +namespace fec { +namespace code { - // Check if the identity matrix exists in the right spot. - //int test_if_equal = gsl_matrix_equal(identity, I_test); - gsl_matrix_sub(identity, I_test); // should be null set if equal - double test_if_not_equal = gsl_matrix_max(identity); - - // Free memory - gsl_matrix_free(identity); - gsl_matrix_free(I_test); - - //if(!test_if_equal) { - if(test_if_not_equal > 0) { - GR_LOG_ERROR(d_logger, - "Error in ldpc_G_matrix_impl constructor. It appears " - "that the given alist file did not contain either a " - "valid parity check matrix of the form H = [P' I] or " - "a generator matrix of the form G = [I P].\n"); - throw std::runtime_error("ldpc_G_matrix: Bad matrix definition"); - } - - // Our G matrix is verified as correct, now convert it to the - // parity check matrix. +ldpc_G_matrix::sptr ldpc_G_matrix::make(const std::string filename) +{ + return ldpc_G_matrix::sptr(new ldpc_G_matrix_impl(filename)); +} - // Grab P matrix - gsl_matrix *P = gsl_matrix_alloc(d_k, d_n-d_k); - for(row_index = 0; row_index < d_k; row_index++) { - for(col_index = 0; col_index < d_n-d_k; col_index++) { - int value = gsl_matrix_get(G, row_index, col_index + d_k); - gsl_matrix_set(P, row_index, col_index, value); - } - } +ldpc_G_matrix_impl::ldpc_G_matrix_impl(const std::string filename) : fec_mtrx_impl() +{ + configure_default_loggers(d_logger, d_debug_logger, "ldpc_G_matrix"); - // Calculate P transpose - gsl_matrix *P_transpose = gsl_matrix_alloc(d_n-d_k, d_k); - gsl_matrix_transpose_memcpy(P_transpose, P); + // Read the matrix from a file in alist format + matrix_sptr x = read_matrix_from_file(filename); + d_num_cols = x->size2; + d_num_rows = x->size1; - // Set H matrix. H = [-P' I] but since we are doing mod 2, - // -P = P, so H = [P' I] - gsl_matrix *H_ptr = gsl_matrix_alloc(d_n-d_k, d_n); - gsl_matrix_set_zero(H_ptr); - for(row_index = 0; row_index < d_n-d_k; row_index++) { - for(col_index = 0; col_index < d_k; col_index++) { - int value = gsl_matrix_get(P_transpose, row_index, col_index); - gsl_matrix_set(H_ptr, row_index, col_index, value); - } - } + // Make an actual copy so we guarantee that we're not sharing + // memory with another class that reads the same alist file. + gsl_matrix* G = gsl_matrix_alloc(d_num_rows, d_num_cols); + gsl_matrix_memcpy(G, (gsl_matrix*)(x.get())); - for(row_index = 0; row_index < (d_n-d_k); row_index++) { - col_index = row_index + d_k; - gsl_matrix_set(H_ptr, row_index, col_index, 1); - } + unsigned int row_index, col_index; - // Calculate G transpose (used for encoding) - d_G_transp_ptr = gsl_matrix_alloc(d_n, d_k); - gsl_matrix_transpose_memcpy(d_G_transp_ptr, G); + // First, check if we have a generator matrix G in systematic + // form, G = [I P], where I is a k x k identity matrix and P + // is the parity submatrix. - d_H_sptr = matrix_sptr((matrix*)H_ptr); + // Length of codeword = # of columns of generator matrix + d_n = d_num_cols; + // Length of information word = # of rows of generator matrix + d_k = d_num_rows; - // Free memory - gsl_matrix_free(P); - gsl_matrix_free(P_transpose); - gsl_matrix_free(G); - } + gsl_matrix* I_test = gsl_matrix_alloc(d_k, d_k); + gsl_matrix* identity = gsl_matrix_alloc(d_k, d_k); + gsl_matrix_set_identity(identity); - - const gsl_matrix* - ldpc_G_matrix_impl::G_transpose() const - { - const gsl_matrix *G_trans_ptr = d_G_transp_ptr; - return G_trans_ptr; - } - - void - ldpc_G_matrix_impl::encode(unsigned char *outbuffer, - const unsigned char *inbuffer) const - { - - unsigned int index, k = d_k, n = d_n; - gsl_matrix *s = gsl_matrix_alloc(k, 1); - for(index = 0; index < k; index++) { - double value = static_cast<double>(inbuffer[index]); - gsl_matrix_set(s, index, 0, value); - } - - // Simple matrix multiplication to get codeword - gsl_matrix *codeword = gsl_matrix_alloc(G_transpose()->size1, s->size2); - mult_matrices_mod2(codeword, G_transpose(), s); - - // Output - for(index = 0; index < n; index++) { - outbuffer[index] = gsl_matrix_get(codeword, index, 0); + for (row_index = 0; row_index < d_k; row_index++) { + for (col_index = 0; col_index < d_k; col_index++) { + int value = gsl_matrix_get(G, row_index, col_index); + gsl_matrix_set(I_test, row_index, col_index, value); } - - // Free memory - gsl_matrix_free(s); - gsl_matrix_free(codeword); - } - - - void - ldpc_G_matrix_impl::decode(unsigned char *outbuffer, - const float *inbuffer, - unsigned int frame_size, - unsigned int max_iterations) const - { - unsigned int index, n = d_n; - gsl_matrix *x = gsl_matrix_alloc(n, 1); - for (index = 0; index < n; index++) { - double value = inbuffer[index] > 0 ? 1.0 : 0.0; - gsl_matrix_set(x, index, 0, value); + } + + // Check if the identity matrix exists in the right spot. + // int test_if_equal = gsl_matrix_equal(identity, I_test); + gsl_matrix_sub(identity, I_test); // should be null set if equal + double test_if_not_equal = gsl_matrix_max(identity); + + // Free memory + gsl_matrix_free(identity); + gsl_matrix_free(I_test); + + // if(!test_if_equal) { + if (test_if_not_equal > 0) { + GR_LOG_ERROR(d_logger, + "Error in ldpc_G_matrix_impl constructor. It appears " + "that the given alist file did not contain either a " + "valid parity check matrix of the form H = [P' I] or " + "a generator matrix of the form G = [I P].\n"); + throw std::runtime_error("ldpc_G_matrix: Bad matrix definition"); + } + + // Our G matrix is verified as correct, now convert it to the + // parity check matrix. + + // Grab P matrix + gsl_matrix* P = gsl_matrix_alloc(d_k, d_n - d_k); + for (row_index = 0; row_index < d_k; row_index++) { + for (col_index = 0; col_index < d_n - d_k; col_index++) { + int value = gsl_matrix_get(G, row_index, col_index + d_k); + gsl_matrix_set(P, row_index, col_index, value); } - - // Initialize counter - unsigned int count = 0; - - // Calculate syndrome - gsl_matrix *syndrome = gsl_matrix_alloc(H()->size1, x->size2); - mult_matrices_mod2(syndrome, H(), x); - - // Flag for finding a valid codeword - bool found_word = false; - - // If the syndrome is all 0s, then codeword is valid and we - // don't need to loop; we're done. - if (gsl_matrix_isnull(syndrome)) { - found_word = true; + } + + // Calculate P transpose + gsl_matrix* P_transpose = gsl_matrix_alloc(d_n - d_k, d_k); + gsl_matrix_transpose_memcpy(P_transpose, P); + + // Set H matrix. H = [-P' I] but since we are doing mod 2, + // -P = P, so H = [P' I] + gsl_matrix* H_ptr = gsl_matrix_alloc(d_n - d_k, d_n); + gsl_matrix_set_zero(H_ptr); + for (row_index = 0; row_index < d_n - d_k; row_index++) { + for (col_index = 0; col_index < d_k; col_index++) { + int value = gsl_matrix_get(P_transpose, row_index, col_index); + gsl_matrix_set(H_ptr, row_index, col_index, value); } - - // Loop until valid codeword is found, or max number of - // iterations is reached, whichever comes first - while ((count < max_iterations) && !found_word) { - // For each of the n bits in the codeword, determine how - // many of the unsatisfied parity checks involve that bit. - // To do this, first find the nonzero entries in the - // syndrome. The entry numbers correspond to the rows of - // interest in H. - std::vector<int> rows_of_interest_in_H; - for (index = 0; index < (*syndrome).size1; index++) { + } + + for (row_index = 0; row_index < (d_n - d_k); row_index++) { + col_index = row_index + d_k; + gsl_matrix_set(H_ptr, row_index, col_index, 1); + } + + // Calculate G transpose (used for encoding) + d_G_transp_ptr = gsl_matrix_alloc(d_n, d_k); + gsl_matrix_transpose_memcpy(d_G_transp_ptr, G); + + d_H_sptr = matrix_sptr((matrix*)H_ptr); + + // Free memory + gsl_matrix_free(P); + gsl_matrix_free(P_transpose); + gsl_matrix_free(G); +} + + +const gsl_matrix* ldpc_G_matrix_impl::G_transpose() const +{ + const gsl_matrix* G_trans_ptr = d_G_transp_ptr; + return G_trans_ptr; +} + +void ldpc_G_matrix_impl::encode(unsigned char* outbuffer, + const unsigned char* inbuffer) const +{ + + unsigned int index, k = d_k, n = d_n; + gsl_matrix* s = gsl_matrix_alloc(k, 1); + for (index = 0; index < k; index++) { + double value = static_cast<double>(inbuffer[index]); + gsl_matrix_set(s, index, 0, value); + } + + // Simple matrix multiplication to get codeword + gsl_matrix* codeword = gsl_matrix_alloc(G_transpose()->size1, s->size2); + mult_matrices_mod2(codeword, G_transpose(), s); + + // Output + for (index = 0; index < n; index++) { + outbuffer[index] = gsl_matrix_get(codeword, index, 0); + } + + // Free memory + gsl_matrix_free(s); + gsl_matrix_free(codeword); +} + + +void ldpc_G_matrix_impl::decode(unsigned char* outbuffer, + const float* inbuffer, + unsigned int frame_size, + unsigned int max_iterations) const +{ + unsigned int index, n = d_n; + gsl_matrix* x = gsl_matrix_alloc(n, 1); + for (index = 0; index < n; index++) { + double value = inbuffer[index] > 0 ? 1.0 : 0.0; + gsl_matrix_set(x, index, 0, value); + } + + // Initialize counter + unsigned int count = 0; + + // Calculate syndrome + gsl_matrix* syndrome = gsl_matrix_alloc(H()->size1, x->size2); + mult_matrices_mod2(syndrome, H(), x); + + // Flag for finding a valid codeword + bool found_word = false; + + // If the syndrome is all 0s, then codeword is valid and we + // don't need to loop; we're done. + if (gsl_matrix_isnull(syndrome)) { + found_word = true; + } + + // Loop until valid codeword is found, or max number of + // iterations is reached, whichever comes first + while ((count < max_iterations) && !found_word) { + // For each of the n bits in the codeword, determine how + // many of the unsatisfied parity checks involve that bit. + // To do this, first find the nonzero entries in the + // syndrome. The entry numbers correspond to the rows of + // interest in H. + std::vector<int> rows_of_interest_in_H; + for (index = 0; index < (*syndrome).size1; index++) { if (gsl_matrix_get(syndrome, index, 0)) { - rows_of_interest_in_H.push_back(index); + rows_of_interest_in_H.push_back(index); } - } - - // Second, for each bit, determine how many of the - // unsatisfied parity checks involve this bit and store - // the count. - unsigned int i, col_num, n = d_n; - std::vector<int> counts(n,0); - for (i = 0; i < rows_of_interest_in_H.size(); i++) { + } + + // Second, for each bit, determine how many of the + // unsatisfied parity checks involve this bit and store + // the count. + unsigned int i, col_num, n = d_n; + std::vector<int> counts(n, 0); + for (i = 0; i < rows_of_interest_in_H.size(); i++) { unsigned int row_num = rows_of_interest_in_H[i]; for (col_num = 0; col_num < n; col_num++) { - double value = gsl_matrix_get(H(), - row_num, - col_num); - if (value > 0) { - counts[col_num] = counts[col_num] + 1; - } + double value = gsl_matrix_get(H(), row_num, col_num); + if (value > 0) { + counts[col_num] = counts[col_num] + 1; + } } - } + } - // Next, determine which bit(s) is associated with the most - // unsatisfied parity checks, and flip it/them. - int max = 0; - for (index = 0; index < n; index++) { + // Next, determine which bit(s) is associated with the most + // unsatisfied parity checks, and flip it/them. + int max = 0; + for (index = 0; index < n; index++) { if (counts[index] > max) { - max = counts[index]; + max = counts[index]; } - } + } - for (index = 0; index < n; index++) { + for (index = 0; index < n; index++) { if (counts[index] == max) { - unsigned int value = gsl_matrix_get(x, index, 0); - unsigned int new_value = value ^ 1; - gsl_matrix_set(x, index, 0, new_value); + unsigned int value = gsl_matrix_get(x, index, 0); + unsigned int new_value = value ^ 1; + gsl_matrix_set(x, index, 0, new_value); } - } + } - // Check the syndrome; see if valid codeword has been found - mult_matrices_mod2(syndrome, H(), x); - if (gsl_matrix_isnull(syndrome)) { + // Check the syndrome; see if valid codeword has been found + mult_matrices_mod2(syndrome, H(), x); + if (gsl_matrix_isnull(syndrome)) { found_word = true; break; - } - count++; } + count++; + } - // Extract the info word and assign to output. This will - // happen regardless of if a valid codeword was found. - if(parity_bits_come_last()) { - for(index = 0; index < frame_size; index++) { + // Extract the info word and assign to output. This will + // happen regardless of if a valid codeword was found. + if (parity_bits_come_last()) { + for (index = 0; index < frame_size; index++) { outbuffer[index] = gsl_matrix_get(x, index, 0); - } } - else { - for(index = 0; index < frame_size; index++) { + } else { + for (index = 0; index < frame_size; index++) { unsigned int i = index + n - frame_size; int value = gsl_matrix_get(x, i, 0); outbuffer[index] = value; - } } - - // Free memory - gsl_matrix_free(syndrome); - gsl_matrix_free(x); - } - - gr::fec::code::fec_mtrx_sptr - ldpc_G_matrix_impl::get_base_sptr() - { - return shared_from_this(); - } - - ldpc_G_matrix_impl::~ldpc_G_matrix_impl() - { - // Call the gsl_matrix_free function to free memory. - gsl_matrix_free(d_G_transp_ptr); - gsl_matrix_free(d_H_obj); - } - } /* namespace code */ - } /* namespace fec */ + } + + // Free memory + gsl_matrix_free(syndrome); + gsl_matrix_free(x); +} + +gr::fec::code::fec_mtrx_sptr ldpc_G_matrix_impl::get_base_sptr() +{ + return shared_from_this(); +} + +ldpc_G_matrix_impl::~ldpc_G_matrix_impl() +{ + // Call the gsl_matrix_free function to free memory. + gsl_matrix_free(d_G_transp_ptr); + gsl_matrix_free(d_H_obj); +} +} /* namespace code */ +} /* namespace fec */ } /* namespace gr */ diff --git a/gr-fec/lib/ldpc_G_matrix_impl.h b/gr-fec/lib/ldpc_G_matrix_impl.h index 5c2c44fef1..b42c1791c2 100644 --- a/gr-fec/lib/ldpc_G_matrix_impl.h +++ b/gr-fec/lib/ldpc_G_matrix_impl.h @@ -32,73 +32,71 @@ #include <gnuradio/logger.h> namespace gr { - namespace fec { - namespace code { - /*! - * \brief Class for storing H or G matrix - * \ingroup error_coding_blk - * - * \details - * This class stores a GSL matrix variable, specifically - * either a: - * - * 1) Generator matrix, G, in the standard format G = [I P], - * where I is an identity matrix and P is the parity - * submatrix. - * - * or - * - * 2) Parity matrix, H, in the standard format H = [P' I], - * where P' is the transpose of the parity submatrix and I - * is an identity matrix. - * - * This variable can used by the ldpc_gen_mtrx_encoder and - * ldpc_bit_flip_decoder classes. - */ - class ldpc_G_matrix_impl - : public fec_mtrx_impl, public ldpc_G_matrix - { - private: - // GSL matrix structure for transpose of G - gsl_matrix *d_G_transp_ptr; - - gsl_matrix *d_H_obj; - - //! Get the generator matrix (used during encoding) - const gsl_matrix *G_transpose() const; - - gr::logger_ptr d_logger; - gr::logger_ptr d_debug_logger; - - public: - ldpc_G_matrix_impl(const std::string filename); - - void encode(unsigned char *outbuffer, - const unsigned char *inbuffer) const; - - void decode(unsigned char *outbuffer, - const float *inbuffer, - unsigned int frame_size, - unsigned int max_iterations) const; - - unsigned int n() const { return fec_mtrx_impl::n(); } - - unsigned int k() const { return fec_mtrx_impl::k(); } - - gsl_matrix* generate_H(); - - gr::fec::code::fec_mtrx_sptr get_base_sptr(); - - /*! - * \brief Destructor - * \details - * Calls the gsl_matrix_free function to free memory. - */ - virtual ~ldpc_G_matrix_impl(); - }; - - } - } -} +namespace fec { +namespace code { +/*! + * \brief Class for storing H or G matrix + * \ingroup error_coding_blk + * + * \details + * This class stores a GSL matrix variable, specifically + * either a: + * + * 1) Generator matrix, G, in the standard format G = [I P], + * where I is an identity matrix and P is the parity + * submatrix. + * + * or + * + * 2) Parity matrix, H, in the standard format H = [P' I], + * where P' is the transpose of the parity submatrix and I + * is an identity matrix. + * + * This variable can used by the ldpc_gen_mtrx_encoder and + * ldpc_bit_flip_decoder classes. + */ +class ldpc_G_matrix_impl : public fec_mtrx_impl, public ldpc_G_matrix +{ +private: + // GSL matrix structure for transpose of G + gsl_matrix* d_G_transp_ptr; + + gsl_matrix* d_H_obj; + + //! Get the generator matrix (used during encoding) + const gsl_matrix* G_transpose() const; + + gr::logger_ptr d_logger; + gr::logger_ptr d_debug_logger; + +public: + ldpc_G_matrix_impl(const std::string filename); + + void encode(unsigned char* outbuffer, const unsigned char* inbuffer) const; + + void decode(unsigned char* outbuffer, + const float* inbuffer, + unsigned int frame_size, + unsigned int max_iterations) const; + + unsigned int n() const { return fec_mtrx_impl::n(); } + + unsigned int k() const { return fec_mtrx_impl::k(); } + + gsl_matrix* generate_H(); + + gr::fec::code::fec_mtrx_sptr get_base_sptr(); + + /*! + * \brief Destructor + * \details + * Calls the gsl_matrix_free function to free memory. + */ + virtual ~ldpc_G_matrix_impl(); +}; + +} // namespace code +} // namespace fec +} // namespace gr #endif /* INCLUDED_ldpc_G_matrix_impl_H */ diff --git a/gr-fec/lib/ldpc_H_matrix_impl.cc b/gr-fec/lib/ldpc_H_matrix_impl.cc index 4d37899ba6..6b1b17e0f9 100644 --- a/gr-fec/lib/ldpc_H_matrix_impl.cc +++ b/gr-fec/lib/ldpc_H_matrix_impl.cc @@ -30,416 +30,395 @@ #include <stdexcept> namespace gr { - namespace fec { - namespace code { - - ldpc_H_matrix::sptr - ldpc_H_matrix::make(const std::string filename, unsigned int gap) - { - return ldpc_H_matrix::sptr - (new ldpc_H_matrix_impl(filename, gap)); - } - - ldpc_H_matrix_impl::ldpc_H_matrix_impl(const std::string filename, unsigned int gap) - : fec_mtrx_impl() - { - matrix_sptr x = read_matrix_from_file(filename); - d_num_cols = x->size2; - d_num_rows = x->size1; - d_gap = gap; - - // Make an actual copy so we guarantee that we're not sharing - // memory with another class that reads the same alist file. - gsl_matrix *temp_mtrx = gsl_matrix_alloc(d_num_rows, d_num_cols); - gsl_matrix_memcpy(temp_mtrx, (gsl_matrix*)(x.get())); - d_H_sptr = matrix_sptr((matrix*)temp_mtrx, matrix_free); - - // Length of codeword = # of columns - d_n = d_num_cols; - - // Length of information word = (# of columns) - (# of rows) - d_k = d_num_cols - d_num_rows; - - set_parameters_for_encoding(); - - // The parity bits come first in this particular matrix - // format (specifically required for the Richardson Urbanke - // encoder) - d_par_bits_last = false; - - } // Constructor - - const gsl_matrix* - ldpc_H_matrix_impl::A() const - { - const gsl_matrix *A_ptr = &d_A_view.matrix; - return A_ptr; - } - - const gsl_matrix* - ldpc_H_matrix_impl::B() const - { - const gsl_matrix *B_ptr = &d_B_view.matrix; - return B_ptr; - } - - const gsl_matrix* - ldpc_H_matrix_impl::D() const - { - const gsl_matrix *D_ptr = &d_D_view.matrix; - return D_ptr; - } - - const gsl_matrix* - ldpc_H_matrix_impl::E() const - { - const gsl_matrix *E_ptr = &d_E_view.matrix; - return E_ptr; - } - - const gsl_matrix* - ldpc_H_matrix_impl::T() const - { - const gsl_matrix *T_ptr = &d_T_view.matrix; - return T_ptr; - } - - const gsl_matrix* - ldpc_H_matrix_impl::phi_inverse() const - { - const gsl_matrix *phi_inverse_ptr = d_phi_inverse_ptr; - return phi_inverse_ptr; - } - - void - ldpc_H_matrix_impl::set_parameters_for_encoding() - { - - // This function defines all of the submatrices that will be - // needed during encoding. - - unsigned int t = d_num_rows - d_gap; - - // T submatrix - d_T_view = gsl_matrix_submatrix((gsl_matrix*)(d_H_sptr.get()), - 0, 0, t, t); - - gsl_matrix *d_T_inverse_ptr; +namespace fec { +namespace code { + +ldpc_H_matrix::sptr ldpc_H_matrix::make(const std::string filename, unsigned int gap) +{ + return ldpc_H_matrix::sptr(new ldpc_H_matrix_impl(filename, gap)); +} + +ldpc_H_matrix_impl::ldpc_H_matrix_impl(const std::string filename, unsigned int gap) + : fec_mtrx_impl() +{ + matrix_sptr x = read_matrix_from_file(filename); + d_num_cols = x->size2; + d_num_rows = x->size1; + d_gap = gap; + + // Make an actual copy so we guarantee that we're not sharing + // memory with another class that reads the same alist file. + gsl_matrix* temp_mtrx = gsl_matrix_alloc(d_num_rows, d_num_cols); + gsl_matrix_memcpy(temp_mtrx, (gsl_matrix*)(x.get())); + d_H_sptr = matrix_sptr((matrix*)temp_mtrx, matrix_free); + + // Length of codeword = # of columns + d_n = d_num_cols; + + // Length of information word = (# of columns) - (# of rows) + d_k = d_num_cols - d_num_rows; + + set_parameters_for_encoding(); + + // The parity bits come first in this particular matrix + // format (specifically required for the Richardson Urbanke + // encoder) + d_par_bits_last = false; + +} // Constructor + +const gsl_matrix* ldpc_H_matrix_impl::A() const +{ + const gsl_matrix* A_ptr = &d_A_view.matrix; + return A_ptr; +} + +const gsl_matrix* ldpc_H_matrix_impl::B() const +{ + const gsl_matrix* B_ptr = &d_B_view.matrix; + return B_ptr; +} + +const gsl_matrix* ldpc_H_matrix_impl::D() const +{ + const gsl_matrix* D_ptr = &d_D_view.matrix; + return D_ptr; +} + +const gsl_matrix* ldpc_H_matrix_impl::E() const +{ + const gsl_matrix* E_ptr = &d_E_view.matrix; + return E_ptr; +} + +const gsl_matrix* ldpc_H_matrix_impl::T() const +{ + const gsl_matrix* T_ptr = &d_T_view.matrix; + return T_ptr; +} + +const gsl_matrix* ldpc_H_matrix_impl::phi_inverse() const +{ + const gsl_matrix* phi_inverse_ptr = d_phi_inverse_ptr; + return phi_inverse_ptr; +} + +void ldpc_H_matrix_impl::set_parameters_for_encoding() +{ + + // This function defines all of the submatrices that will be + // needed during encoding. + + unsigned int t = d_num_rows - d_gap; + + // T submatrix + d_T_view = gsl_matrix_submatrix((gsl_matrix*)(d_H_sptr.get()), 0, 0, t, t); + + gsl_matrix* d_T_inverse_ptr; + try { + d_T_inverse_ptr = calc_inverse_mod2(&d_T_view.matrix); + } catch (char const* exceptionString) { + std::cout << "Error in set_parameters_for_encoding while " + << "looking for inverse T matrix: " << exceptionString + << "Tip: verify that the correct gap is being " + << "specified for this alist file.\n"; + + throw std::runtime_error("set_parameters_for_encoding"); + } + + // E submatrix + d_E_view = gsl_matrix_submatrix( + (gsl_matrix*)(d_H_sptr.get()), t, 0, d_gap, d_n - d_k - d_gap); + + // A submatrix + d_A_view = gsl_matrix_submatrix((gsl_matrix*)(d_H_sptr.get()), 0, t, t, d_gap); + + // C submatrix (used to find phi but not during encoding) + gsl_matrix_view C_view = + gsl_matrix_submatrix((gsl_matrix*)(d_H_sptr.get()), t, t, d_gap, d_gap); + + // These are just temporary matrices used to find phi. + gsl_matrix* temp1 = gsl_matrix_alloc(d_E_view.matrix.size1, d_T_inverse_ptr->size2); + mult_matrices_mod2(temp1, &d_E_view.matrix, d_T_inverse_ptr); + + gsl_matrix* temp2 = gsl_matrix_alloc(temp1->size1, d_A_view.matrix.size2); + mult_matrices_mod2(temp2, temp1, &d_A_view.matrix); + + // Solve for phi. + gsl_matrix* phi = gsl_matrix_alloc(C_view.matrix.size1, temp2->size2); + add_matrices_mod2(phi, &C_view.matrix, temp2); + + // If phi has at least one nonzero entry, try for inverse. + if (gsl_matrix_max(phi)) { try { - d_T_inverse_ptr = calc_inverse_mod2(&d_T_view.matrix); - } - catch (char const *exceptionString) { - std::cout << "Error in set_parameters_for_encoding while " - << "looking for inverse T matrix: " - << exceptionString - << "Tip: verify that the correct gap is being " - << "specified for this alist file.\n"; - - throw std::runtime_error("set_parameters_for_encoding"); - } - - // E submatrix - d_E_view = gsl_matrix_submatrix((gsl_matrix*)(d_H_sptr.get()), - t, 0, d_gap, d_n-d_k-d_gap); - - // A submatrix - d_A_view = gsl_matrix_submatrix((gsl_matrix*)(d_H_sptr.get()), - 0, t, t, d_gap); - - // C submatrix (used to find phi but not during encoding) - gsl_matrix_view C_view = gsl_matrix_submatrix((gsl_matrix*)(d_H_sptr.get()), - t, t, d_gap, d_gap); - - // These are just temporary matrices used to find phi. - gsl_matrix *temp1 = gsl_matrix_alloc(d_E_view.matrix.size1, d_T_inverse_ptr->size2); - mult_matrices_mod2(temp1, &d_E_view.matrix, d_T_inverse_ptr); - - gsl_matrix *temp2 = gsl_matrix_alloc(temp1->size1, d_A_view.matrix.size2); - mult_matrices_mod2(temp2, temp1, &d_A_view.matrix); - - // Solve for phi. - gsl_matrix *phi = gsl_matrix_alloc(C_view.matrix.size1, temp2->size2); - add_matrices_mod2(phi, &C_view.matrix, temp2); - - // If phi has at least one nonzero entry, try for inverse. - if (gsl_matrix_max(phi)) { - try { - gsl_matrix *inverse_phi = calc_inverse_mod2(phi); + gsl_matrix* inverse_phi = calc_inverse_mod2(phi); // At this point, an inverse was found. d_phi_inverse_ptr = inverse_phi; - } - catch (char const *exceptionString) { + } catch (char const* exceptionString) { std::cout << "Error in set_parameters_for_encoding while" << " finding inverse_phi: " << exceptionString << "Tip: verify that the correct gap is being " << "specified for this alist file.\n"; throw std::runtime_error("set_parameters_for_encoding"); - } } - - // B submatrix - d_B_view = gsl_matrix_submatrix((gsl_matrix*)(d_H_sptr.get()), - 0, t + d_gap, t, d_n-d_gap-t); - - // D submatrix - d_D_view = gsl_matrix_submatrix((gsl_matrix*)(d_H_sptr.get()), - t, t + d_gap, d_gap, d_n-d_gap-t); - - // Free memory - gsl_matrix_free(temp1); - gsl_matrix_free(temp2); - gsl_matrix_free(phi); - gsl_matrix_free(d_T_inverse_ptr); - } - - void - ldpc_H_matrix_impl::back_solve_mod2(gsl_matrix *x, - const gsl_matrix *U, - const gsl_matrix *y) const - { - // Exploit the fact that the matrix T is upper triangular and - // sparse. In the steps to find p1 and p2, back solve rather - // than do matrix multiplication to reduce number of - // operations required. - - // Form is Ux = y where U is upper triangular and y is column - // vector. Solve for x. - - // Allocate memory for the result - int num_rows = (*U).size1; - int num_cols_U = (*U).size2; - - // Back solve - for (int i = num_rows-1; i >= 0; i--) { - // x[i] = y[i] - gsl_matrix_set(x, i, 0, gsl_matrix_get(y, i, 0)); - - int j; - for (j = i+1; j < num_cols_U; j++) { + } + + // B submatrix + d_B_view = gsl_matrix_submatrix( + (gsl_matrix*)(d_H_sptr.get()), 0, t + d_gap, t, d_n - d_gap - t); + + // D submatrix + d_D_view = gsl_matrix_submatrix( + (gsl_matrix*)(d_H_sptr.get()), t, t + d_gap, d_gap, d_n - d_gap - t); + + // Free memory + gsl_matrix_free(temp1); + gsl_matrix_free(temp2); + gsl_matrix_free(phi); + gsl_matrix_free(d_T_inverse_ptr); +} + +void ldpc_H_matrix_impl::back_solve_mod2(gsl_matrix* x, + const gsl_matrix* U, + const gsl_matrix* y) const +{ + // Exploit the fact that the matrix T is upper triangular and + // sparse. In the steps to find p1 and p2, back solve rather + // than do matrix multiplication to reduce number of + // operations required. + + // Form is Ux = y where U is upper triangular and y is column + // vector. Solve for x. + + // Allocate memory for the result + int num_rows = (*U).size1; + int num_cols_U = (*U).size2; + + // Back solve + for (int i = num_rows - 1; i >= 0; i--) { + // x[i] = y[i] + gsl_matrix_set(x, i, 0, gsl_matrix_get(y, i, 0)); + + int j; + for (j = i + 1; j < num_cols_U; j++) { int U_i_j = gsl_matrix_get(U, i, j); - int x_i = gsl_matrix_get(x, i, 0); - int x_j = gsl_matrix_get(x, j, 0); + int x_i = gsl_matrix_get(x, i, 0); + int x_j = gsl_matrix_get(x, j, 0); int temp1 = (U_i_j * x_j) % 2; int temp2 = (x_i + temp1) % 2; gsl_matrix_set(x, i, 0, temp2); - } - // Perform x[i] /= U[i,i], GF(2) operations - int U_i_i = gsl_matrix_get(U, i, i); - int x_i = gsl_matrix_get(x, i, 0); - if(x_i==0 && U_i_i==1) + } + // Perform x[i] /= U[i,i], GF(2) operations + int U_i_i = gsl_matrix_get(U, i, i); + int x_i = gsl_matrix_get(x, i, 0); + if (x_i == 0 && U_i_i == 1) gsl_matrix_set(x, i, 0, 0); - else if (x_i==0 && U_i_i==0) + else if (x_i == 0 && U_i_i == 0) gsl_matrix_set(x, i, 0, 0); - else if (x_i==1 && U_i_i==1) + else if (x_i == 1 && U_i_i == 1) gsl_matrix_set(x, i, 0, 1); - else if (x_i==1 && U_i_i==0) + else if (x_i == 1 && U_i_i == 0) std::cout << "Error in " << " ldpc_H_matrix_impl::back_solve_mod2," << " division not defined.\n"; - else + else std::cout << "Error in ldpc_H_matrix::back_solve_mod2\n"; - } - } - - - void - ldpc_H_matrix_impl::encode(unsigned char *outbuffer, - const unsigned char *inbuffer) const - { - - // Temporary matrix for storing stages of encoding. - gsl_matrix *s, *p1, *p2; - gsl_matrix *temp1, *temp2, *temp3, *temp4, *temp5, *temp6, *temp7; - - unsigned int index, k = d_k; - s = gsl_matrix_alloc(k, 1); - for (index = 0; index < k; index++) { - double value = static_cast<double>(inbuffer[index]); - gsl_matrix_set(s, index, 0, value); - } - - // Solve for p2 (parity part). By using back substitution, - // the overall complexity of determining p2 is O(n + g^2). - temp1 = gsl_matrix_alloc(B()->size1, s->size2); - mult_matrices_mod2(temp1, B(), s); - - temp2 = gsl_matrix_alloc(T()->size1, 1); - back_solve_mod2(temp2, T(), temp1); - - temp3 = gsl_matrix_alloc(E()->size1, temp2->size2); - mult_matrices_mod2(temp3, E(), temp2); - - temp4 = gsl_matrix_alloc(D()->size1, s->size2); - mult_matrices_mod2(temp4, D(), s); - - temp5 = gsl_matrix_alloc(temp4->size1, temp3->size2); - add_matrices_mod2(temp5, temp4, temp3); - - p2 = gsl_matrix_alloc(phi_inverse()->size1, temp5->size2); - mult_matrices_mod2(p2, phi_inverse(), temp5); - - // Solve for p1 (parity part). By using back substitution, - // the overall complexity of determining p1 is O(n). - temp6 = gsl_matrix_alloc(A()->size1, p2->size2); - mult_matrices_mod2(temp6, A(), p2); - - temp7 = gsl_matrix_alloc(temp6->size1, temp1->size2); - add_matrices_mod2(temp7, temp6, temp1); - - p1 = gsl_matrix_alloc(T()->size1, 1); - back_solve_mod2(p1, T(), temp7); - - // Populate the codeword to be output - unsigned int p1_length = (*p1).size1; - unsigned int p2_length = (*p2).size1; - for (index = 0; index < p1_length; index++) { - int value = gsl_matrix_get(p1, index, 0); - outbuffer[index] = value; - } - for (index = 0; index < p2_length; index++) { - int value = gsl_matrix_get(p2, index, 0); - outbuffer[p1_length+index] = value; - } - for (index = 0; index < k; index++) { - int value = gsl_matrix_get(s, index, 0); - outbuffer[p1_length+p2_length+index] = value; - } - - // Free temporary matrices - gsl_matrix_free(temp1); - gsl_matrix_free(temp2); - gsl_matrix_free(temp3); - gsl_matrix_free(temp4); - gsl_matrix_free(temp5); - gsl_matrix_free(temp6); - gsl_matrix_free(temp7); - gsl_matrix_free(p1); - gsl_matrix_free(p2); - } - - - void - ldpc_H_matrix_impl::decode(unsigned char *outbuffer, - const float *inbuffer, - unsigned int frame_size, - unsigned int max_iterations) const - { - unsigned int index, n = d_n; - gsl_matrix *x = gsl_matrix_alloc(n, 1); - for (index = 0; index < n; index++) { - double value = inbuffer[index] > 0 ? 1.0 : 0.0; - gsl_matrix_set(x, index, 0, value); - } - - // Initialize counter - unsigned int count = 0; - - // Calculate syndrome - gsl_matrix *syndrome = gsl_matrix_alloc(H()->size1, x->size2); - mult_matrices_mod2(syndrome, H(), x); - - // Flag for finding a valid codeword - bool found_word = false; - - // If the syndrome is all 0s, then codeword is valid and we - // don't need to loop; we're done. - if (gsl_matrix_isnull(syndrome)) { - found_word = true; - } - - // Loop until valid codeword is found, or max number of - // iterations is reached, whichever comes first - while ((count < max_iterations) && !found_word) { - // For each of the n bits in the codeword, determine how - // many of the unsatisfied parity checks involve that bit. - // To do this, first find the nonzero entries in the - // syndrome. The entry numbers correspond to the rows of - // interest in H. - std::vector<int> rows_of_interest_in_H; - for (index = 0; index < (*syndrome).size1; index++) { + } +} + + +void ldpc_H_matrix_impl::encode(unsigned char* outbuffer, + const unsigned char* inbuffer) const +{ + + // Temporary matrix for storing stages of encoding. + gsl_matrix *s, *p1, *p2; + gsl_matrix *temp1, *temp2, *temp3, *temp4, *temp5, *temp6, *temp7; + + unsigned int index, k = d_k; + s = gsl_matrix_alloc(k, 1); + for (index = 0; index < k; index++) { + double value = static_cast<double>(inbuffer[index]); + gsl_matrix_set(s, index, 0, value); + } + + // Solve for p2 (parity part). By using back substitution, + // the overall complexity of determining p2 is O(n + g^2). + temp1 = gsl_matrix_alloc(B()->size1, s->size2); + mult_matrices_mod2(temp1, B(), s); + + temp2 = gsl_matrix_alloc(T()->size1, 1); + back_solve_mod2(temp2, T(), temp1); + + temp3 = gsl_matrix_alloc(E()->size1, temp2->size2); + mult_matrices_mod2(temp3, E(), temp2); + + temp4 = gsl_matrix_alloc(D()->size1, s->size2); + mult_matrices_mod2(temp4, D(), s); + + temp5 = gsl_matrix_alloc(temp4->size1, temp3->size2); + add_matrices_mod2(temp5, temp4, temp3); + + p2 = gsl_matrix_alloc(phi_inverse()->size1, temp5->size2); + mult_matrices_mod2(p2, phi_inverse(), temp5); + + // Solve for p1 (parity part). By using back substitution, + // the overall complexity of determining p1 is O(n). + temp6 = gsl_matrix_alloc(A()->size1, p2->size2); + mult_matrices_mod2(temp6, A(), p2); + + temp7 = gsl_matrix_alloc(temp6->size1, temp1->size2); + add_matrices_mod2(temp7, temp6, temp1); + + p1 = gsl_matrix_alloc(T()->size1, 1); + back_solve_mod2(p1, T(), temp7); + + // Populate the codeword to be output + unsigned int p1_length = (*p1).size1; + unsigned int p2_length = (*p2).size1; + for (index = 0; index < p1_length; index++) { + int value = gsl_matrix_get(p1, index, 0); + outbuffer[index] = value; + } + for (index = 0; index < p2_length; index++) { + int value = gsl_matrix_get(p2, index, 0); + outbuffer[p1_length + index] = value; + } + for (index = 0; index < k; index++) { + int value = gsl_matrix_get(s, index, 0); + outbuffer[p1_length + p2_length + index] = value; + } + + // Free temporary matrices + gsl_matrix_free(temp1); + gsl_matrix_free(temp2); + gsl_matrix_free(temp3); + gsl_matrix_free(temp4); + gsl_matrix_free(temp5); + gsl_matrix_free(temp6); + gsl_matrix_free(temp7); + gsl_matrix_free(p1); + gsl_matrix_free(p2); +} + + +void ldpc_H_matrix_impl::decode(unsigned char* outbuffer, + const float* inbuffer, + unsigned int frame_size, + unsigned int max_iterations) const +{ + unsigned int index, n = d_n; + gsl_matrix* x = gsl_matrix_alloc(n, 1); + for (index = 0; index < n; index++) { + double value = inbuffer[index] > 0 ? 1.0 : 0.0; + gsl_matrix_set(x, index, 0, value); + } + + // Initialize counter + unsigned int count = 0; + + // Calculate syndrome + gsl_matrix* syndrome = gsl_matrix_alloc(H()->size1, x->size2); + mult_matrices_mod2(syndrome, H(), x); + + // Flag for finding a valid codeword + bool found_word = false; + + // If the syndrome is all 0s, then codeword is valid and we + // don't need to loop; we're done. + if (gsl_matrix_isnull(syndrome)) { + found_word = true; + } + + // Loop until valid codeword is found, or max number of + // iterations is reached, whichever comes first + while ((count < max_iterations) && !found_word) { + // For each of the n bits in the codeword, determine how + // many of the unsatisfied parity checks involve that bit. + // To do this, first find the nonzero entries in the + // syndrome. The entry numbers correspond to the rows of + // interest in H. + std::vector<int> rows_of_interest_in_H; + for (index = 0; index < (*syndrome).size1; index++) { if (gsl_matrix_get(syndrome, index, 0)) { - rows_of_interest_in_H.push_back(index); + rows_of_interest_in_H.push_back(index); } - } - - // Second, for each bit, determine how many of the - // unsatisfied parity checks involve this bit and store - // the count. - unsigned int i, col_num, n = d_n; - std::vector<int> counts(n,0); - for (i = 0; i < rows_of_interest_in_H.size(); i++) { + } + + // Second, for each bit, determine how many of the + // unsatisfied parity checks involve this bit and store + // the count. + unsigned int i, col_num, n = d_n; + std::vector<int> counts(n, 0); + for (i = 0; i < rows_of_interest_in_H.size(); i++) { unsigned int row_num = rows_of_interest_in_H[i]; for (col_num = 0; col_num < n; col_num++) { - double value = gsl_matrix_get(H(), - row_num, - col_num); - if (value > 0) { - counts[col_num] = counts[col_num] + 1; - } + double value = gsl_matrix_get(H(), row_num, col_num); + if (value > 0) { + counts[col_num] = counts[col_num] + 1; + } } - } + } - // Next, determine which bit(s) is associated with the most - // unsatisfied parity checks, and flip it/them. - int max = 0; - for (index = 0; index < n; index++) { + // Next, determine which bit(s) is associated with the most + // unsatisfied parity checks, and flip it/them. + int max = 0; + for (index = 0; index < n; index++) { if (counts[index] > max) { - max = counts[index]; + max = counts[index]; } - } + } - for (index = 0; index < n; index++) { + for (index = 0; index < n; index++) { if (counts[index] == max) { - unsigned int value = gsl_matrix_get(x, index, 0); - unsigned int new_value = value ^ 1; - gsl_matrix_set(x, index, 0, new_value); + unsigned int value = gsl_matrix_get(x, index, 0); + unsigned int new_value = value ^ 1; + gsl_matrix_set(x, index, 0, new_value); } - } + } - // Check the syndrome; see if valid codeword has been found - mult_matrices_mod2(syndrome, H(), x); - if (gsl_matrix_isnull(syndrome)) { + // Check the syndrome; see if valid codeword has been found + mult_matrices_mod2(syndrome, H(), x); + if (gsl_matrix_isnull(syndrome)) { found_word = true; break; - } - count++; } + count++; + } - // Extract the info word and assign to output. This will - // happen regardless of if a valid codeword was found. - if(parity_bits_come_last()) { - for(index = 0; index < frame_size; index++) { + // Extract the info word and assign to output. This will + // happen regardless of if a valid codeword was found. + if (parity_bits_come_last()) { + for (index = 0; index < frame_size; index++) { outbuffer[index] = gsl_matrix_get(x, index, 0); - } } - else { - for(index = 0; index < frame_size; index++) { + } else { + for (index = 0; index < frame_size; index++) { unsigned int i = index + n - frame_size; int value = gsl_matrix_get(x, i, 0); outbuffer[index] = value; - } } - - // Free memory - gsl_matrix_free(syndrome); - gsl_matrix_free(x); - } - - gr::fec::code::fec_mtrx_sptr - ldpc_H_matrix_impl::get_base_sptr() - { - return shared_from_this(); - } - - ldpc_H_matrix_impl::~ldpc_H_matrix_impl() - { - - // Call the gsl_matrix_free function to free memory. - gsl_matrix_free (d_phi_inverse_ptr); - } - } /* namespace code */ - } /* namespace fec */ + } + + // Free memory + gsl_matrix_free(syndrome); + gsl_matrix_free(x); +} + +gr::fec::code::fec_mtrx_sptr ldpc_H_matrix_impl::get_base_sptr() +{ + return shared_from_this(); +} + +ldpc_H_matrix_impl::~ldpc_H_matrix_impl() +{ + + // Call the gsl_matrix_free function to free memory. + gsl_matrix_free(d_phi_inverse_ptr); +} +} /* namespace code */ +} /* namespace fec */ } /* namespace gr */ diff --git a/gr-fec/lib/ldpc_H_matrix_impl.h b/gr-fec/lib/ldpc_H_matrix_impl.h index 89ea4de49b..43025c1705 100644 --- a/gr-fec/lib/ldpc_H_matrix_impl.h +++ b/gr-fec/lib/ldpc_H_matrix_impl.h @@ -25,98 +25,95 @@ #include <gnuradio/fec/ldpc_H_matrix.h> namespace gr { - namespace fec { - namespace code { - - class ldpc_H_matrix_impl - : public fec_mtrx_impl, public ldpc_H_matrix - { - private: - // Gap (assumes matrix is in TABECD form) - unsigned int d_gap; - - // Submatrices found during preprocessing, used for encoding - gsl_matrix_view d_A_view; - gsl_matrix_view d_B_view; - gsl_matrix_view d_D_view; - gsl_matrix_view d_E_view; - gsl_matrix_view d_T_view; - gsl_matrix *d_phi_inverse_ptr; - - //! Sets the submatrix variables needed for encoding - void set_parameters_for_encoding(); - - void back_solve_mod2(gsl_matrix *result, - const gsl_matrix *U, - const gsl_matrix *y) const; - - //! Access the A submatrix, needed during encoding - const gsl_matrix *A() const; - - //! Access the B submatrix, needed during encoding - const gsl_matrix *B() const; - - //! Access the D submatrix, needed during encoding - const gsl_matrix *D() const; - - //! Access the E submatrix, needed during encoding - const gsl_matrix *E() const; - - //! Access the T submatrix, needed during encoding - const gsl_matrix *T() const; - - /*! - * \brief Access the \f$\phi^{-1}\f$ matrix - * \details - * Access the matrix \f$\phi^{-1}\f$, which is needed during - * encoding. \f$\phi\f$ is defined as: - * \f$\phi=C-ET^{-1}A\f$. - */ - const gsl_matrix *phi_inverse() const; - - public: - /*! - * \brief Constructor given alist file and gap - * \param filename Name of an alist file to use. The alist - * format is described at: - * http://www.inference.phy.cam.ac.uk/mackay/codes/alist.html - * \param gap A property of the matrix being used. For alist - * files distributed with GNU Radio, this value - * is specified in the alist filename. The gap is - * found during the matrix preprocessing - * algorithm. It is equal to the number of rows in - * submatrices E, C and D. - */ - ldpc_H_matrix_impl(const std::string filename, unsigned int gap); - - //! Encode \p inbuffer with LDPC H matrix into \p outbuffer. - void encode(unsigned char *outbuffer, - const unsigned char *inbuffer) const; - - //! Decode \p inbuffer with LDPC H matrix into \p outbuffer. - void decode(unsigned char *outbuffer, - const float *inbuffer, - unsigned int frame_size, - unsigned int max_iterations) const; - - //! Redefine these here as part of the public interface - unsigned int n() const { return fec_mtrx_impl::n(); }; - - //! Redefine these here as part of the public interface - unsigned int k() const { return fec_mtrx_impl::k(); }; - - gr::fec::code::fec_mtrx_sptr get_base_sptr(); - - /*! - * \brief Destructor - * \details - * Calls the gsl_matrix_free function to free memory - */ - virtual ~ldpc_H_matrix_impl(); - }; - - } - } -} +namespace fec { +namespace code { + +class ldpc_H_matrix_impl : public fec_mtrx_impl, public ldpc_H_matrix +{ +private: + // Gap (assumes matrix is in TABECD form) + unsigned int d_gap; + + // Submatrices found during preprocessing, used for encoding + gsl_matrix_view d_A_view; + gsl_matrix_view d_B_view; + gsl_matrix_view d_D_view; + gsl_matrix_view d_E_view; + gsl_matrix_view d_T_view; + gsl_matrix* d_phi_inverse_ptr; + + //! Sets the submatrix variables needed for encoding + void set_parameters_for_encoding(); + + void + back_solve_mod2(gsl_matrix* result, const gsl_matrix* U, const gsl_matrix* y) const; + + //! Access the A submatrix, needed during encoding + const gsl_matrix* A() const; + + //! Access the B submatrix, needed during encoding + const gsl_matrix* B() const; + + //! Access the D submatrix, needed during encoding + const gsl_matrix* D() const; + + //! Access the E submatrix, needed during encoding + const gsl_matrix* E() const; + + //! Access the T submatrix, needed during encoding + const gsl_matrix* T() const; + + /*! + * \brief Access the \f$\phi^{-1}\f$ matrix + * \details + * Access the matrix \f$\phi^{-1}\f$, which is needed during + * encoding. \f$\phi\f$ is defined as: + * \f$\phi=C-ET^{-1}A\f$. + */ + const gsl_matrix* phi_inverse() const; + +public: + /*! + * \brief Constructor given alist file and gap + * \param filename Name of an alist file to use. The alist + * format is described at: + * http://www.inference.phy.cam.ac.uk/mackay/codes/alist.html + * \param gap A property of the matrix being used. For alist + * files distributed with GNU Radio, this value + * is specified in the alist filename. The gap is + * found during the matrix preprocessing + * algorithm. It is equal to the number of rows in + * submatrices E, C and D. + */ + ldpc_H_matrix_impl(const std::string filename, unsigned int gap); + + //! Encode \p inbuffer with LDPC H matrix into \p outbuffer. + void encode(unsigned char* outbuffer, const unsigned char* inbuffer) const; + + //! Decode \p inbuffer with LDPC H matrix into \p outbuffer. + void decode(unsigned char* outbuffer, + const float* inbuffer, + unsigned int frame_size, + unsigned int max_iterations) const; + + //! Redefine these here as part of the public interface + unsigned int n() const { return fec_mtrx_impl::n(); }; + + //! Redefine these here as part of the public interface + unsigned int k() const { return fec_mtrx_impl::k(); }; + + gr::fec::code::fec_mtrx_sptr get_base_sptr(); + + /*! + * \brief Destructor + * \details + * Calls the gsl_matrix_free function to free memory + */ + virtual ~ldpc_H_matrix_impl(); +}; + +} // namespace code +} // namespace fec +} // namespace gr #endif /* INCLUDED_ldpc_H_matrix_impl_H */ diff --git a/gr-fec/lib/ldpc_bit_flip_decoder_impl.cc b/gr-fec/lib/ldpc_bit_flip_decoder_impl.cc index 9de4ff1ad9..286b7364f2 100644 --- a/gr-fec/lib/ldpc_bit_flip_decoder_impl.cc +++ b/gr-fec/lib/ldpc_bit_flip_decoder_impl.cc @@ -31,89 +31,71 @@ #include <vector> namespace gr { - namespace fec { - namespace code { - - generic_decoder::sptr - ldpc_bit_flip_decoder::make(const fec_mtrx_sptr mtrx_obj, - unsigned int max_iter) - { - return generic_decoder::sptr - (new ldpc_bit_flip_decoder_impl(mtrx_obj, max_iter)); - } - - ldpc_bit_flip_decoder_impl::ldpc_bit_flip_decoder_impl(const fec_mtrx_sptr mtrx_obj, - unsigned int max_iter) - : generic_decoder("ldpc_bit_flip_decoder") - { - // FEC matrix object to use for decoding - d_mtrx = mtrx_obj; - - d_rate = static_cast<double>(d_mtrx->k())/static_cast<double>(d_mtrx->n()); - - // Set frame size to k, the # of bits in the information word - // All buffers and settings will be based on this value. - set_frame_size(d_mtrx->k()); - // Maximum number of iterations in the decoding algorithm - d_max_iterations = max_iter; - } - - ldpc_bit_flip_decoder_impl::~ldpc_bit_flip_decoder_impl() - { - } - - int - ldpc_bit_flip_decoder_impl::get_output_size() - { - return d_output_size; - } - - int - ldpc_bit_flip_decoder_impl::get_input_size() - { - return d_input_size; - } - - bool - ldpc_bit_flip_decoder_impl::set_frame_size(unsigned int frame_size) - { - if(frame_size % d_mtrx->k() != 0) { - GR_LOG_ERROR(d_logger, boost::format("Frame size (%1% bits) must be a " - "multiple of the information word " - "size of the LDPC matrix, %2%") \ - % frame_size % (d_mtrx->k())); - throw std::runtime_error("ldpc_bit_flip_decoder: cannot use frame size."); - } - - d_output_size = frame_size; - d_input_size = static_cast<int>(round(frame_size / d_rate)); - - return true; - } - - double - ldpc_bit_flip_decoder_impl::rate() - { - return d_rate; - } - - - void - ldpc_bit_flip_decoder_impl::generic_work(void *inbuffer, - void *outbuffer) - { - // Populate the information word - const float *in = (const float*)inbuffer; - unsigned char *out = (unsigned char*) outbuffer; - - int j = 0; - for(int i = 0; i < d_input_size; i+=d_mtrx->n()) { - d_mtrx->decode(&out[j], &in[i], d_mtrx->k(), d_max_iterations); - j += d_mtrx->k(); - } - - } /* ldpc_bit_flip_decoder_impl::generic_work() */ - - } /* namespace code */ - } /* namespace fec */ +namespace fec { +namespace code { + +generic_decoder::sptr ldpc_bit_flip_decoder::make(const fec_mtrx_sptr mtrx_obj, + unsigned int max_iter) +{ + return generic_decoder::sptr(new ldpc_bit_flip_decoder_impl(mtrx_obj, max_iter)); +} + +ldpc_bit_flip_decoder_impl::ldpc_bit_flip_decoder_impl(const fec_mtrx_sptr mtrx_obj, + unsigned int max_iter) + : generic_decoder("ldpc_bit_flip_decoder") +{ + // FEC matrix object to use for decoding + d_mtrx = mtrx_obj; + + d_rate = static_cast<double>(d_mtrx->k()) / static_cast<double>(d_mtrx->n()); + + // Set frame size to k, the # of bits in the information word + // All buffers and settings will be based on this value. + set_frame_size(d_mtrx->k()); + // Maximum number of iterations in the decoding algorithm + d_max_iterations = max_iter; +} + +ldpc_bit_flip_decoder_impl::~ldpc_bit_flip_decoder_impl() {} + +int ldpc_bit_flip_decoder_impl::get_output_size() { return d_output_size; } + +int ldpc_bit_flip_decoder_impl::get_input_size() { return d_input_size; } + +bool ldpc_bit_flip_decoder_impl::set_frame_size(unsigned int frame_size) +{ + if (frame_size % d_mtrx->k() != 0) { + GR_LOG_ERROR(d_logger, + boost::format("Frame size (%1% bits) must be a " + "multiple of the information word " + "size of the LDPC matrix, %2%") % + frame_size % (d_mtrx->k())); + throw std::runtime_error("ldpc_bit_flip_decoder: cannot use frame size."); + } + + d_output_size = frame_size; + d_input_size = static_cast<int>(round(frame_size / d_rate)); + + return true; +} + +double ldpc_bit_flip_decoder_impl::rate() { return d_rate; } + + +void ldpc_bit_flip_decoder_impl::generic_work(void* inbuffer, void* outbuffer) +{ + // Populate the information word + const float* in = (const float*)inbuffer; + unsigned char* out = (unsigned char*)outbuffer; + + int j = 0; + for (int i = 0; i < d_input_size; i += d_mtrx->n()) { + d_mtrx->decode(&out[j], &in[i], d_mtrx->k(), d_max_iterations); + j += d_mtrx->k(); + } + +} /* ldpc_bit_flip_decoder_impl::generic_work() */ + +} /* namespace code */ +} /* namespace fec */ } /* namespace gr */ diff --git a/gr-fec/lib/ldpc_bit_flip_decoder_impl.h b/gr-fec/lib/ldpc_bit_flip_decoder_impl.h index ba331bed62..8bb3f6dc30 100644 --- a/gr-fec/lib/ldpc_bit_flip_decoder_impl.h +++ b/gr-fec/lib/ldpc_bit_flip_decoder_impl.h @@ -24,38 +24,37 @@ #include <gnuradio/fec/ldpc_bit_flip_decoder.h> namespace gr { - namespace fec { - namespace code { - - class FEC_API ldpc_bit_flip_decoder_impl : public ldpc_bit_flip_decoder - { - private: - // Plug into the generic FEC API: - int get_input_size(); // n, # of bits in the received block - int get_output_size(); // k, # of bits in the info word - int d_input_size; - int d_output_size; - - double d_rate; - - // FEC matrix object to use for decoding - fec_mtrx_sptr d_mtrx; - - // Maximum number of iterations to do in decoding algorithm - unsigned int d_max_iterations; - - public: - ldpc_bit_flip_decoder_impl(const fec_mtrx_sptr mtrx_obj, - unsigned int max_iter=100); - ~ldpc_bit_flip_decoder_impl(); - - void generic_work(void *inbuffer, void *outbuffer); - bool set_frame_size(unsigned int frame_size); - double rate(); - }; - - } /* namespace code */ - } /* namespace fec */ +namespace fec { +namespace code { + +class FEC_API ldpc_bit_flip_decoder_impl : public ldpc_bit_flip_decoder +{ +private: + // Plug into the generic FEC API: + int get_input_size(); // n, # of bits in the received block + int get_output_size(); // k, # of bits in the info word + int d_input_size; + int d_output_size; + + double d_rate; + + // FEC matrix object to use for decoding + fec_mtrx_sptr d_mtrx; + + // Maximum number of iterations to do in decoding algorithm + unsigned int d_max_iterations; + +public: + ldpc_bit_flip_decoder_impl(const fec_mtrx_sptr mtrx_obj, unsigned int max_iter = 100); + ~ldpc_bit_flip_decoder_impl(); + + void generic_work(void* inbuffer, void* outbuffer); + bool set_frame_size(unsigned int frame_size); + double rate(); +}; + +} /* namespace code */ +} /* namespace fec */ } /* namespace gr */ #endif /* INCLUDED_FEC_LDPC_BIT_FLIP_DECODER_IMPL_H */ diff --git a/gr-fec/lib/ldpc_decoder.cc b/gr-fec/lib/ldpc_decoder.cc index 55eeac6291..26992066eb 100644 --- a/gr-fec/lib/ldpc_decoder.cc +++ b/gr-fec/lib/ldpc_decoder.cc @@ -28,131 +28,94 @@ #include <stdio.h> #include <vector> #include <gnuradio/fec/decoder.h> -#include <algorithm> // for std::reverse -#include <string.h> // for memcpy +#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); - - d_rate = static_cast<double>(d_code.dimension())/static_cast<double>(d_code.get_N()); - set_frame_size(d_code.dimension()); - - d_spa.set_K(d_output_size); - d_spa.set_max_iterations(max_iterations); - } - - int - ldpc_decoder::get_output_size() - { - return d_output_size; - } - - int - ldpc_decoder::get_input_size() - { - return d_input_size; - } - - double - ldpc_decoder::rate() - { - return d_rate; - } - - bool - ldpc_decoder::set_frame_size(unsigned int frame_size) - { - if(frame_size % d_code.dimension() != 0) { - GR_LOG_ERROR(d_logger, boost::format("Frame size (%1% bits) must be a " - "multiple of the information word " - "size of the LDPC matrix, %2%") \ - % frame_size % (d_code.dimension())); - throw std::runtime_error("ldpc_decoder: cannot use frame size."); - } - - d_output_size = frame_size; - d_input_size = static_cast<int>(round(frame_size / d_rate)); - - return true; - } - - void - ldpc_decoder::generic_work(void *inBuffer, void *outBuffer) - { - const float *in = (const float *) inBuffer; - unsigned char *out = (unsigned char *) outBuffer; - - int j = 0; - std::vector<float> rx(d_code.get_N()); - for(int i = 0; i < d_input_size; i+=d_code.get_N()) { - for(int k = 0; k < d_code.get_N(); k++) { - rx[k] = in[i+k] * (-1); - } - - 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[j], &data[0], d_code.dimension()); - d_iterations = n_iterations; - - j += d_code.dimension(); - } - } - - 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() - { - } - - } // 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); + + d_rate = + static_cast<double>(d_code.dimension()) / static_cast<double>(d_code.get_N()); + set_frame_size(d_code.dimension()); + + d_spa.set_K(d_output_size); + d_spa.set_max_iterations(max_iterations); +} + +int ldpc_decoder::get_output_size() { return d_output_size; } + +int ldpc_decoder::get_input_size() { return d_input_size; } + +double ldpc_decoder::rate() { return d_rate; } + +bool ldpc_decoder::set_frame_size(unsigned int frame_size) +{ + if (frame_size % d_code.dimension() != 0) { + GR_LOG_ERROR(d_logger, + boost::format("Frame size (%1% bits) must be a " + "multiple of the information word " + "size of the LDPC matrix, %2%") % + frame_size % (d_code.dimension())); + throw std::runtime_error("ldpc_decoder: cannot use frame size."); + } + + d_output_size = frame_size; + d_input_size = static_cast<int>(round(frame_size / d_rate)); + + return true; +} + +void ldpc_decoder::generic_work(void* inBuffer, void* outBuffer) +{ + const float* in = (const float*)inBuffer; + unsigned char* out = (unsigned char*)outBuffer; + + int j = 0; + std::vector<float> rx(d_code.get_N()); + for (int i = 0; i < d_input_size; i += d_code.get_N()) { + for (int k = 0; k < d_code.get_N(); k++) { + rx[k] = in[i + k] * (-1); + } + + 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[j], &data[0], d_code.dimension()); + d_iterations = n_iterations; + + j += d_code.dimension(); + } +} + +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() {} + } // namespace fec +} // namespace gr diff --git a/gr-fec/lib/ldpc_encoder_impl.cc b/gr-fec/lib/ldpc_encoder_impl.cc index 4905904cf1..7adaf6b886 100644 --- a/gr-fec/lib/ldpc_encoder_impl.cc +++ b/gr-fec/lib/ldpc_encoder_impl.cc @@ -25,59 +25,46 @@ #include <volk/volk.h> #include <sstream> #include <stdio.h> -#include <algorithm> // for std::reverse -#include <string.h> // for memcpy +#include <algorithm> // for std::reverse +#include <string.h> // for memcpy namespace gr { - namespace fec { +namespace fec { - generic_encoder::sptr - ldpc_encoder::make(std::string alist_file) - { - return generic_encoder::sptr - (new ldpc_encoder_impl(alist_file)); - } +generic_encoder::sptr ldpc_encoder::make(std::string alist_file) +{ + return generic_encoder::sptr(new ldpc_encoder_impl(alist_file)); +} - ldpc_encoder_impl::ldpc_encoder_impl(std::string alist_file) - { - if(!boost::filesystem::exists(alist_file)) { +ldpc_encoder_impl::ldpc_encoder_impl(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_impl::get_output_size() - { - return outputSize; - } + d_list.read(alist_file.c_str()); + d_code.set_alist(d_list); + inputSize = d_code.dimension(); + outputSize = d_code.get_N(); - int - ldpc_encoder_impl::get_input_size() - { - return inputSize; - } + // printf("ENCODER: inputSize = %d, outputSize = %d\n",inputSize, outputSize); +} - void - ldpc_encoder_impl::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()); - } +int ldpc_encoder_impl::get_output_size() { return outputSize; } - ldpc_encoder_impl::~ldpc_encoder_impl() - { - } +int ldpc_encoder_impl::get_input_size() { return inputSize; } - } +void ldpc_encoder_impl::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_impl::~ldpc_encoder_impl() {} + +} // namespace fec +} // namespace gr diff --git a/gr-fec/lib/ldpc_encoder_impl.h b/gr-fec/lib/ldpc_encoder_impl.h index e4293253fa..5889f116d2 100644 --- a/gr-fec/lib/ldpc_encoder_impl.h +++ b/gr-fec/lib/ldpc_encoder_impl.h @@ -31,31 +31,31 @@ #include <vector> namespace gr { - namespace fec { - - class ldpc_encoder_impl : public ldpc_encoder - { - private: - //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_impl(std::string alist_file); - ~ldpc_encoder_impl(); - - 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(); - }; - - } -} +namespace fec { + +class ldpc_encoder_impl : public ldpc_encoder +{ +private: + // 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_impl(std::string alist_file); + ~ldpc_encoder_impl(); + + 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(); +}; + +} // namespace fec +} // namespace gr #endif /* INCLUDED_LDPC_ENCODER_IMPL_H */ diff --git a/gr-fec/lib/ldpc_gen_mtrx_encoder_impl.cc b/gr-fec/lib/ldpc_gen_mtrx_encoder_impl.cc index 32823bb674..76c4268860 100644 --- a/gr-fec/lib/ldpc_gen_mtrx_encoder_impl.cc +++ b/gr-fec/lib/ldpc_gen_mtrx_encoder_impl.cc @@ -26,86 +26,68 @@ #include <sstream> namespace gr { - namespace fec { - namespace code { - - generic_encoder::sptr - ldpc_gen_mtrx_encoder::make(const ldpc_G_matrix::sptr G_obj) - { - return generic_encoder::sptr - (new ldpc_gen_mtrx_encoder_impl(G_obj)); - } - - ldpc_gen_mtrx_encoder_impl::ldpc_gen_mtrx_encoder_impl(const ldpc_G_matrix::sptr G_obj) - : generic_encoder("ldpc_gen_mtrx_encoder") - { - // Generator matrix to use for encoding - d_G = G_obj; - - d_rate = static_cast<double>(d_G->n())/static_cast<double>(d_G->k()); - - // Set frame size to k, the # of bits in the information word - // All buffers and settings will be based on this value. - set_frame_size(d_G->k()); - } - - ldpc_gen_mtrx_encoder_impl::~ldpc_gen_mtrx_encoder_impl() - { - } - - int - ldpc_gen_mtrx_encoder_impl::get_output_size() - { - return d_output_size; - } - - int - ldpc_gen_mtrx_encoder_impl::get_input_size() - { - return d_frame_size; - } - - bool - ldpc_gen_mtrx_encoder_impl::set_frame_size(unsigned int frame_size) - { - bool ret = true; - - if(frame_size % d_G->k() != 0) { - GR_LOG_ERROR(d_logger, boost::format("Frame size (%1% bits) must be a " - "multiple of the information word " - "size of the LDPC matrix (%2%).") \ - % frame_size % (d_G->k())); - throw std::runtime_error("ldpc_gen_mtrx_encoder: cannot use frame size."); - } - - d_frame_size = frame_size; - - d_output_size = static_cast<int>(d_rate * d_frame_size); - - return ret; - } - - double - ldpc_gen_mtrx_encoder_impl::rate() - { - return d_rate; - } - - void - ldpc_gen_mtrx_encoder_impl::generic_work(void *inbuffer, - void *outbuffer) - { - // Populate the information word - const unsigned char *in = (const unsigned char *)inbuffer; - unsigned char *out = (unsigned char*)outbuffer; - - int j = 0; - for(int i = 0; i < get_input_size(); i+=d_G->k()) { - d_G->encode(&out[j], &in[i]); - j += d_G->n(); - } - } - - } /* namespace code */ - } /* namespace fec */ +namespace fec { +namespace code { + +generic_encoder::sptr ldpc_gen_mtrx_encoder::make(const ldpc_G_matrix::sptr G_obj) +{ + return generic_encoder::sptr(new ldpc_gen_mtrx_encoder_impl(G_obj)); +} + +ldpc_gen_mtrx_encoder_impl::ldpc_gen_mtrx_encoder_impl(const ldpc_G_matrix::sptr G_obj) + : generic_encoder("ldpc_gen_mtrx_encoder") +{ + // Generator matrix to use for encoding + d_G = G_obj; + + d_rate = static_cast<double>(d_G->n()) / static_cast<double>(d_G->k()); + + // Set frame size to k, the # of bits in the information word + // All buffers and settings will be based on this value. + set_frame_size(d_G->k()); +} + +ldpc_gen_mtrx_encoder_impl::~ldpc_gen_mtrx_encoder_impl() {} + +int ldpc_gen_mtrx_encoder_impl::get_output_size() { return d_output_size; } + +int ldpc_gen_mtrx_encoder_impl::get_input_size() { return d_frame_size; } + +bool ldpc_gen_mtrx_encoder_impl::set_frame_size(unsigned int frame_size) +{ + bool ret = true; + + if (frame_size % d_G->k() != 0) { + GR_LOG_ERROR(d_logger, + boost::format("Frame size (%1% bits) must be a " + "multiple of the information word " + "size of the LDPC matrix (%2%).") % + frame_size % (d_G->k())); + throw std::runtime_error("ldpc_gen_mtrx_encoder: cannot use frame size."); + } + + d_frame_size = frame_size; + + d_output_size = static_cast<int>(d_rate * d_frame_size); + + return ret; +} + +double ldpc_gen_mtrx_encoder_impl::rate() { return d_rate; } + +void ldpc_gen_mtrx_encoder_impl::generic_work(void* inbuffer, void* outbuffer) +{ + // Populate the information word + const unsigned char* in = (const unsigned char*)inbuffer; + unsigned char* out = (unsigned char*)outbuffer; + + int j = 0; + for (int i = 0; i < get_input_size(); i += d_G->k()) { + d_G->encode(&out[j], &in[i]); + j += d_G->n(); + } +} + +} /* namespace code */ +} /* namespace fec */ } /* namespace gr */ diff --git a/gr-fec/lib/ldpc_gen_mtrx_encoder_impl.h b/gr-fec/lib/ldpc_gen_mtrx_encoder_impl.h index ca4a8c7a37..ee73699e49 100644 --- a/gr-fec/lib/ldpc_gen_mtrx_encoder_impl.h +++ b/gr-fec/lib/ldpc_gen_mtrx_encoder_impl.h @@ -27,38 +27,38 @@ #include <gnuradio/fec/ldpc_G_matrix.h> namespace gr { - namespace fec { - namespace code { +namespace fec { +namespace code { - class FEC_API ldpc_gen_mtrx_encoder_impl : public ldpc_gen_mtrx_encoder - { - private: - void generic_work(void *inbuffer, void *outbuffer); - int get_output_size(); - int get_input_size(); +class FEC_API ldpc_gen_mtrx_encoder_impl : public ldpc_gen_mtrx_encoder +{ +private: + void generic_work(void* inbuffer, void* outbuffer); + int get_output_size(); + int get_input_size(); - // Number of bits in the information word - unsigned int d_frame_size; + // Number of bits in the information word + unsigned int d_frame_size; - // Number of output bits after coding - int d_output_size; + // Number of output bits after coding + int d_output_size; - // Rate of the code, n/k - double d_rate; + // Rate of the code, n/k + double d_rate; - // Matrix object to use for encoding - ldpc_G_matrix::sptr d_G; + // Matrix object to use for encoding + ldpc_G_matrix::sptr d_G; - public: - ldpc_gen_mtrx_encoder_impl(const ldpc_G_matrix::sptr G_obj); - ~ldpc_gen_mtrx_encoder_impl(); +public: + ldpc_gen_mtrx_encoder_impl(const ldpc_G_matrix::sptr G_obj); + ~ldpc_gen_mtrx_encoder_impl(); - bool set_frame_size(unsigned int frame_size); - double rate(); - }; + bool set_frame_size(unsigned int frame_size); + double rate(); +}; - } /* namespace code */ - } /* namespace fec */ +} /* namespace code */ +} /* namespace fec */ } /* namespace gr */ #endif /* INCLUDED_FEC_LDPC_GEN_MTRX_ENCODER_IMPL_H */ diff --git a/gr-fec/lib/ldpc_par_mtrx_encoder_impl.cc b/gr-fec/lib/ldpc_par_mtrx_encoder_impl.cc index ac3faa53b8..16c03574ee 100755..100644 --- a/gr-fec/lib/ldpc_par_mtrx_encoder_impl.cc +++ b/gr-fec/lib/ldpc_par_mtrx_encoder_impl.cc @@ -27,98 +27,88 @@ #include <sstream> #include <stdio.h> #include <vector> -#include <algorithm> // for std::reverse -#include <string.h> // for memcpy +#include <algorithm> // for std::reverse +#include <string.h> // for memcpy namespace gr { - namespace fec { - namespace code { - - generic_encoder::sptr - ldpc_par_mtrx_encoder::make(std::string alist_file, unsigned int gap) - { - code::ldpc_H_matrix::sptr H_obj = code::ldpc_H_matrix::make(alist_file, gap); - return make_H(H_obj); - } - - generic_encoder::sptr - ldpc_par_mtrx_encoder::make_H(const code::ldpc_H_matrix::sptr H_obj) - { - return generic_encoder::sptr - (new ldpc_par_mtrx_encoder_impl(H_obj)); - } - - ldpc_par_mtrx_encoder_impl::ldpc_par_mtrx_encoder_impl(const code::ldpc_H_matrix::sptr H_obj) - : generic_encoder("ldpc_par_mtrx_encoder") - { - // LDPC parity check matrix to use for encoding - d_H = H_obj; - - d_rate = static_cast<double>(d_H->n())/static_cast<double>(d_H->k()); - - // Set frame size to k, the # of bits in the information word - // All buffers and settings will be based on this value. - set_frame_size(d_H->k()); - } - - ldpc_par_mtrx_encoder_impl::~ldpc_par_mtrx_encoder_impl() - { - } - - int - ldpc_par_mtrx_encoder_impl::get_output_size() - { - //return outputSize; - return d_output_size; - } - - int - ldpc_par_mtrx_encoder_impl::get_input_size() - { - //return inputSize; - return d_frame_size; - } - - bool - ldpc_par_mtrx_encoder_impl::set_frame_size(unsigned int frame_size) - { - bool ret = true; - - if(frame_size % d_H->k() != 0) { - GR_LOG_ERROR(d_logger, boost::format("Frame size (%1% bits) must be a " - "multiple of the information word " - "size of the LDPC matrix (%2%).") \ - % frame_size % (d_H->k())); - throw std::runtime_error("ldpc_par_mtrx_encoder: cannot use frame size."); - } - - d_frame_size = frame_size; - - d_output_size = static_cast<int>(d_rate * d_frame_size); - - return ret; - } - - double - ldpc_par_mtrx_encoder_impl::rate() - { - return d_rate; - } - - void - ldpc_par_mtrx_encoder_impl::generic_work(void *inbuffer, void *outbuffer) - { - // Populate the information word - const unsigned char *in = (const unsigned char *)inbuffer; - unsigned char *out = (unsigned char*)outbuffer; - - int j = 0; - for(int i = 0; i < get_input_size(); i+=d_H->k()) { - d_H->encode(&out[j], &in[i]); - j += d_H->n(); - } - } - - } /* namespace code */ - } /* namespace fec */ +namespace fec { +namespace code { + +generic_encoder::sptr ldpc_par_mtrx_encoder::make(std::string alist_file, + unsigned int gap) +{ + code::ldpc_H_matrix::sptr H_obj = code::ldpc_H_matrix::make(alist_file, gap); + return make_H(H_obj); +} + +generic_encoder::sptr ldpc_par_mtrx_encoder::make_H(const code::ldpc_H_matrix::sptr H_obj) +{ + return generic_encoder::sptr(new ldpc_par_mtrx_encoder_impl(H_obj)); +} + +ldpc_par_mtrx_encoder_impl::ldpc_par_mtrx_encoder_impl( + const code::ldpc_H_matrix::sptr H_obj) + : generic_encoder("ldpc_par_mtrx_encoder") +{ + // LDPC parity check matrix to use for encoding + d_H = H_obj; + + d_rate = static_cast<double>(d_H->n()) / static_cast<double>(d_H->k()); + + // Set frame size to k, the # of bits in the information word + // All buffers and settings will be based on this value. + set_frame_size(d_H->k()); +} + +ldpc_par_mtrx_encoder_impl::~ldpc_par_mtrx_encoder_impl() {} + +int ldpc_par_mtrx_encoder_impl::get_output_size() +{ + // return outputSize; + return d_output_size; +} + +int ldpc_par_mtrx_encoder_impl::get_input_size() +{ + // return inputSize; + return d_frame_size; +} + +bool ldpc_par_mtrx_encoder_impl::set_frame_size(unsigned int frame_size) +{ + bool ret = true; + + if (frame_size % d_H->k() != 0) { + GR_LOG_ERROR(d_logger, + boost::format("Frame size (%1% bits) must be a " + "multiple of the information word " + "size of the LDPC matrix (%2%).") % + frame_size % (d_H->k())); + throw std::runtime_error("ldpc_par_mtrx_encoder: cannot use frame size."); + } + + d_frame_size = frame_size; + + d_output_size = static_cast<int>(d_rate * d_frame_size); + + return ret; +} + +double ldpc_par_mtrx_encoder_impl::rate() { return d_rate; } + +void ldpc_par_mtrx_encoder_impl::generic_work(void* inbuffer, void* outbuffer) +{ + // Populate the information word + const unsigned char* in = (const unsigned char*)inbuffer; + unsigned char* out = (unsigned char*)outbuffer; + + int j = 0; + for (int i = 0; i < get_input_size(); i += d_H->k()) { + d_H->encode(&out[j], &in[i]); + j += d_H->n(); + } +} + +} /* namespace code */ +} /* namespace fec */ } /* namespace gr */ diff --git a/gr-fec/lib/ldpc_par_mtrx_encoder_impl.h b/gr-fec/lib/ldpc_par_mtrx_encoder_impl.h index 4f0139ee26..7a62f1bbf5 100644 --- a/gr-fec/lib/ldpc_par_mtrx_encoder_impl.h +++ b/gr-fec/lib/ldpc_par_mtrx_encoder_impl.h @@ -26,39 +26,39 @@ #include <gnuradio/fec/ldpc_par_mtrx_encoder.h> namespace gr { - namespace fec { - namespace code { +namespace fec { +namespace code { - class ldpc_par_mtrx_encoder_impl : public ldpc_par_mtrx_encoder - { - private: - // plug into the generic fec api - void generic_work(void *inbuffer, void *outbuffer); +class ldpc_par_mtrx_encoder_impl : public ldpc_par_mtrx_encoder +{ +private: + // plug into the generic fec api + void generic_work(void* inbuffer, void* outbuffer); - // Number of bits in the frame to be encoded - unsigned int d_frame_size; + // Number of bits in the frame to be encoded + unsigned int d_frame_size; - // Number of output bits after coding - int d_output_size; + // Number of output bits after coding + int d_output_size; - // Rate of the code, n/k - double d_rate; + // Rate of the code, n/k + double d_rate; - // LDPC parity check matrix object - code::ldpc_H_matrix::sptr d_H; + // LDPC parity check matrix object + code::ldpc_H_matrix::sptr d_H; - public: - ldpc_par_mtrx_encoder_impl(const code::ldpc_H_matrix::sptr H_obj); - ~ldpc_par_mtrx_encoder_impl(); +public: + ldpc_par_mtrx_encoder_impl(const code::ldpc_H_matrix::sptr H_obj); + ~ldpc_par_mtrx_encoder_impl(); - double rate(); - bool set_frame_size(unsigned int frame_size); - int get_output_size(); - int get_input_size(); - }; + double rate(); + bool set_frame_size(unsigned int frame_size); + int get_output_size(); + int get_input_size(); +}; - } /* namespace code */ - } /* namespace fec */ +} /* namespace code */ +} /* namespace fec */ } /* namespace gr */ #endif /* INCLUDED_LDPC_PAR_MTRX_ENCODER_IMPL_H */ diff --git a/gr-fec/lib/polar_common.cc b/gr-fec/lib/polar_common.cc index 68d1b97f40..2207b69f37 100644 --- a/gr-fec/lib/polar_common.cc +++ b/gr-fec/lib/polar_common.cc @@ -37,152 +37,159 @@ #include <vector> namespace gr { - namespace fec { - namespace code { - - polar_common::polar_common(int block_size, int num_info_bits, - std::vector<int> frozen_bit_positions, - std::vector<char> frozen_bit_values) : - d_frozen_bit_positions(frozen_bit_positions), d_frozen_bit_values(frozen_bit_values), - d_block_size(block_size), d_block_power((int) log2(float(block_size))), - d_num_info_bits(num_info_bits) - { - if(pow(2, d_block_power) != d_block_size){ - throw std::runtime_error("block_size MUST be a power of 2!"); - } - - unsigned int num_frozen_bits = d_block_size - d_num_info_bits; - if(num_frozen_bits != d_frozen_bit_positions.size()){ - throw std::runtime_error( - "number of frozen bit positions must equal block_size - num_info_bits"); - } - - // According to papers frozen bits default to '0'. - while(d_frozen_bit_values.size() < num_frozen_bits){ - d_frozen_bit_values.push_back(0); - } - initialize_info_bit_position_vector(); - setup_volk_vectors(); - setup_info_bit_positions_reversed(); - - d_unpacker = new gr::blocks::kernel::unpack_k_bits(8); - } - - void - polar_common::initialize_info_bit_position_vector() - { - int num_frozen_bit = 0; - int frozen_pos = d_frozen_bit_positions.at(num_frozen_bit); - for(int i = 0; i < d_block_size; i++) { - if(i != frozen_pos) { - d_info_bit_positions.push_back((int) i); - } - else { +namespace fec { +namespace code { + +polar_common::polar_common(int block_size, + int num_info_bits, + std::vector<int> frozen_bit_positions, + std::vector<char> frozen_bit_values) + : d_frozen_bit_positions(frozen_bit_positions), + d_frozen_bit_values(frozen_bit_values), + d_block_size(block_size), + d_block_power((int)log2(float(block_size))), + d_num_info_bits(num_info_bits) +{ + if (pow(2, d_block_power) != d_block_size) { + throw std::runtime_error("block_size MUST be a power of 2!"); + } + + unsigned int num_frozen_bits = d_block_size - d_num_info_bits; + if (num_frozen_bits != d_frozen_bit_positions.size()) { + throw std::runtime_error( + "number of frozen bit positions must equal block_size - num_info_bits"); + } + + // According to papers frozen bits default to '0'. + while (d_frozen_bit_values.size() < num_frozen_bits) { + d_frozen_bit_values.push_back(0); + } + initialize_info_bit_position_vector(); + setup_volk_vectors(); + setup_info_bit_positions_reversed(); + + d_unpacker = new gr::blocks::kernel::unpack_k_bits(8); +} + +void polar_common::initialize_info_bit_position_vector() +{ + int num_frozen_bit = 0; + int frozen_pos = d_frozen_bit_positions.at(num_frozen_bit); + for (int i = 0; i < d_block_size; i++) { + if (i != frozen_pos) { + d_info_bit_positions.push_back((int)i); + } else { num_frozen_bit++; - num_frozen_bit = std::min(num_frozen_bit, (int) (d_frozen_bit_positions.size() - 1)); + num_frozen_bit = + std::min(num_frozen_bit, (int)(d_frozen_bit_positions.size() - 1)); frozen_pos = d_frozen_bit_positions.at(num_frozen_bit); - } - } - - if((int) d_info_bit_positions.size() != num_info_bits()) { - throw std::runtime_error("polar_common: number of info bit positions MUST equal num_info_bits (K)!"); } - } - - void - polar_common::setup_info_bit_positions_reversed() - { - for(unsigned int i = 0; i < d_info_bit_positions.size(); i++){ - d_info_bit_positions_reversed.push_back((int) bit_reverse((long) d_info_bit_positions.at(i), block_power())); - } - - if((int) d_info_bit_positions_reversed.size() != num_info_bits()) { - throw std::runtime_error("polar_encoder: number of info bit positions MUST equal num_info_bits (K)!"); - } - } - - void - polar_common::setup_volk_vectors() - { - int nfrozen = block_size() - num_info_bits(); - d_volk_temp = (unsigned char*) volk_malloc(sizeof(unsigned char) * block_size(), volk_get_alignment()); - d_volk_frozen_bit_mask = (unsigned char*) volk_malloc(sizeof(unsigned char) * block_size(), volk_get_alignment()); - d_volk_frozen_bits = (unsigned char*) volk_malloc(sizeof(unsigned char) * nfrozen, volk_get_alignment()); - std::copy(d_frozen_bit_values.begin(), d_frozen_bit_values.end(), d_volk_frozen_bits); - std::fill(d_volk_frozen_bits + d_frozen_bit_values.size(), d_volk_frozen_bits + nfrozen, 0); - - unsigned int nfbit = 0; - for(int i = 0; i < block_size(); i++){ - unsigned char m = 0x00; - if(nfbit < d_frozen_bit_positions.size() && d_frozen_bit_positions[nfbit] == i){ + } + + if ((int)d_info_bit_positions.size() != num_info_bits()) { + throw std::runtime_error( + "polar_common: number of info bit positions MUST equal num_info_bits (K)!"); + } +} + +void polar_common::setup_info_bit_positions_reversed() +{ + for (unsigned int i = 0; i < d_info_bit_positions.size(); i++) { + d_info_bit_positions_reversed.push_back( + (int)bit_reverse((long)d_info_bit_positions.at(i), block_power())); + } + + if ((int)d_info_bit_positions_reversed.size() != num_info_bits()) { + throw std::runtime_error( + "polar_encoder: number of info bit positions MUST equal num_info_bits (K)!"); + } +} + +void polar_common::setup_volk_vectors() +{ + int nfrozen = block_size() - num_info_bits(); + d_volk_temp = (unsigned char*)volk_malloc(sizeof(unsigned char) * block_size(), + volk_get_alignment()); + d_volk_frozen_bit_mask = (unsigned char*)volk_malloc( + sizeof(unsigned char) * block_size(), volk_get_alignment()); + d_volk_frozen_bits = (unsigned char*)volk_malloc(sizeof(unsigned char) * nfrozen, + volk_get_alignment()); + std::copy(d_frozen_bit_values.begin(), d_frozen_bit_values.end(), d_volk_frozen_bits); + std::fill( + d_volk_frozen_bits + d_frozen_bit_values.size(), d_volk_frozen_bits + nfrozen, 0); + + unsigned int nfbit = 0; + for (int i = 0; i < block_size(); i++) { + unsigned char m = 0x00; + if (nfbit < d_frozen_bit_positions.size() && d_frozen_bit_positions[nfbit] == i) { m = 0xFF; nfbit++; - } - d_volk_frozen_bit_mask[i] = m; - } - } - - void - polar_common::volk_encode(unsigned char* out_buf, const unsigned char* in_buf) - { - volk_8u_x3_encodepolar_8u_x2(out_buf, d_volk_temp, d_volk_frozen_bit_mask, d_volk_frozen_bits, in_buf, block_size()); - } - - void - polar_common::volk_encode_block(unsigned char* out_buf, unsigned char* in_buf) - { - volk_8u_x2_encodeframepolar_8u(out_buf, in_buf, block_size()); - } - - polar_common::~polar_common() - { - delete d_unpacker; - - volk_free(d_volk_temp); - volk_free(d_volk_frozen_bit_mask); - volk_free(d_volk_frozen_bits); - } - - long - polar_common::bit_reverse(long value, int active_bits) const - { - long r = 0; - for(int i = 0; i < active_bits; i++) { - r <<= 1; - r |= value & 1; - value >>= 1; } - return r; - } - - void - polar_common::print_packed_bit_array(const unsigned char* printed_array, - const int num_bytes) const - { - int num_bits = num_bytes << 3; - unsigned char* temp = new unsigned char[num_bits]; - d_unpacker->unpack(temp, printed_array, num_bytes); - - std::cout << "["; - for(int i = 0; i < num_bits; i++) { - std::cout << (int) *(temp + i) << " "; - } - std::cout << "]" << std::endl; - - delete [] temp; - } - - void - polar_common::print_unpacked_bit_array(const unsigned char* bits, - const unsigned int num_bytes) const - { - std::cout << "( "; - for(unsigned int i = 0; i < num_bytes; i++){ - std::cout << (int) *bits++ << ", "; - } - std::cout << ")" << std::endl; - } - - } /* namespace code */ - } /* namespace fec */ + d_volk_frozen_bit_mask[i] = m; + } +} + +void polar_common::volk_encode(unsigned char* out_buf, const unsigned char* in_buf) +{ + volk_8u_x3_encodepolar_8u_x2(out_buf, + d_volk_temp, + d_volk_frozen_bit_mask, + d_volk_frozen_bits, + in_buf, + block_size()); +} + +void polar_common::volk_encode_block(unsigned char* out_buf, unsigned char* in_buf) +{ + volk_8u_x2_encodeframepolar_8u(out_buf, in_buf, block_size()); +} + +polar_common::~polar_common() +{ + delete d_unpacker; + + volk_free(d_volk_temp); + volk_free(d_volk_frozen_bit_mask); + volk_free(d_volk_frozen_bits); +} + +long polar_common::bit_reverse(long value, int active_bits) const +{ + long r = 0; + for (int i = 0; i < active_bits; i++) { + r <<= 1; + r |= value & 1; + value >>= 1; + } + return r; +} + +void polar_common::print_packed_bit_array(const unsigned char* printed_array, + const int num_bytes) const +{ + int num_bits = num_bytes << 3; + unsigned char* temp = new unsigned char[num_bits]; + d_unpacker->unpack(temp, printed_array, num_bytes); + + std::cout << "["; + for (int i = 0; i < num_bits; i++) { + std::cout << (int)*(temp + i) << " "; + } + std::cout << "]" << std::endl; + + delete[] temp; +} + +void polar_common::print_unpacked_bit_array(const unsigned char* bits, + const unsigned int num_bytes) const +{ + std::cout << "( "; + for (unsigned int i = 0; i < num_bytes; i++) { + std::cout << (int)*bits++ << ", "; + } + std::cout << ")" << std::endl; +} + +} /* namespace code */ +} /* namespace fec */ } /* namespace gr */ diff --git a/gr-fec/lib/polar_decoder_common.cc b/gr-fec/lib/polar_decoder_common.cc index 9d632110f4..1712350172 100644 --- a/gr-fec/lib/polar_decoder_common.cc +++ b/gr-fec/lib/polar_decoder_common.cc @@ -31,165 +31,161 @@ #include <cstdio> namespace gr { - namespace fec { - namespace code { - - const float polar_decoder_common::D_LLR_FACTOR = -2.19722458f; - - polar_decoder_common::polar_decoder_common(int block_size, int num_info_bits, - std::vector<int> frozen_bit_positions, - std::vector<char> frozen_bit_values) : - polar_common(block_size, num_info_bits, frozen_bit_positions, frozen_bit_values), - d_frozen_bit_counter(0) - { - } - - polar_decoder_common::~polar_decoder_common() - { - } - - void - polar_decoder_common::initialize_decoder(unsigned char* u, float* llrs, const float* input) - { - volk_32f_s32f_multiply_32f(llrs + block_size() * block_power(), input, D_LLR_FACTOR, block_size()); - memset(u, 0, sizeof(unsigned char) * block_size() * block_power()); - d_frozen_bit_counter = 0; - } - - float - polar_decoder_common::llr_odd(const float la, const float lb) const - { - return copysignf(1.0f, la) * copysignf(1.0f, lb) * std::min(fabs(la), fabs(lb)); - } - - float - polar_decoder_common::llr_even(const float la, const float lb, const unsigned char f) const - { - switch(f){ - case 0: - return lb + la; - default: - return lb - la; - } - } - - void - polar_decoder_common::butterfly(float* llrs, unsigned char* u, const int stage, - const int u_num, const int row) - { - butterfly_volk(llrs, u, stage, u_num, row); - } - - void - polar_decoder_common::butterfly_generic(float* llrs, unsigned char* u, const int stage, - const int u_num, const int row) - { - const int next_stage = stage + 1; - const int half_stage_size = 0x01 << stage; - const int stage_size = half_stage_size << 1; - const bool is_upper_stage_half = row % stage_size < half_stage_size; - - // // this is a natural bit order impl - float* next_llrs = llrs + block_size(); // LLRs are stored in a consecutive array. - float* call_row_llr = llrs + row; - - const int section = row - (row % stage_size); - const int jump_size = ((row % half_stage_size) << 1) % stage_size; - - const int next_upper_row = section + jump_size; - const int next_lower_row = next_upper_row + 1; - - const float* upper_right_llr_ptr = next_llrs + next_upper_row; - const float* lower_right_llr_ptr = next_llrs + next_lower_row; - - if(!is_upper_stage_half){ - const int u_pos = u_num >> stage; - const unsigned char f = u[u_pos - 1]; - *call_row_llr = llr_even(*upper_right_llr_ptr, *lower_right_llr_ptr, f); - return; - } - - if(block_power() > next_stage){ - unsigned char* u_half = u + block_size(); - odd_xor_even_values(u_half, u, u_num); - butterfly(next_llrs, u_half, next_stage, u_num, next_upper_row); - - even_u_values(u_half, u, u_num); - butterfly(next_llrs, u_half, next_stage, u_num, next_lower_row); - } - - *call_row_llr = llr_odd(*upper_right_llr_ptr, *lower_right_llr_ptr); - } - - void - polar_decoder_common::butterfly_volk(float* llrs, unsigned char* u, const int stage, - const int u_num, const int row) - { - volk_32f_8u_polarbutterfly_32f(llrs, u, block_power(), stage, u_num, row); - } - - - void - polar_decoder_common::even_u_values(unsigned char* u_even, const unsigned char* u, - const int u_num) - { - u++; - for(int i = 1; i < u_num; i += 2){ - *u_even++ = *u; - u += 2; - } - } - - void - polar_decoder_common::odd_xor_even_values(unsigned char* u_xor, const unsigned char* u, - const int u_num) - { - for(int i = 1; i < u_num; i += 2){ - *u_xor++ = *u ^ *(u + 1); - u += 2; - } - } - - const bool - polar_decoder_common::is_frozen_bit(const int u_num) const - { - return d_frozen_bit_counter < d_frozen_bit_positions.size() && u_num == d_frozen_bit_positions.at(d_frozen_bit_counter); - } - - - const unsigned char - polar_decoder_common::next_frozen_bit() - { - return d_frozen_bit_values[d_frozen_bit_counter++]; - } - - void - polar_decoder_common::extract_info_bits(unsigned char* output, const unsigned char* input) const - { - unsigned int frozenbit_num = 0; - for(int i = 0; i < block_size(); i++){ - if(frozenbit_num < d_frozen_bit_positions.size() && d_frozen_bit_positions.at(frozenbit_num) == i){ +namespace fec { +namespace code { + +const float polar_decoder_common::D_LLR_FACTOR = -2.19722458f; + +polar_decoder_common::polar_decoder_common(int block_size, + int num_info_bits, + std::vector<int> frozen_bit_positions, + std::vector<char> frozen_bit_values) + : polar_common(block_size, num_info_bits, frozen_bit_positions, frozen_bit_values), + d_frozen_bit_counter(0) +{ +} + +polar_decoder_common::~polar_decoder_common() {} + +void polar_decoder_common::initialize_decoder(unsigned char* u, + float* llrs, + const float* input) +{ + volk_32f_s32f_multiply_32f( + llrs + block_size() * block_power(), input, D_LLR_FACTOR, block_size()); + memset(u, 0, sizeof(unsigned char) * block_size() * block_power()); + d_frozen_bit_counter = 0; +} + +float polar_decoder_common::llr_odd(const float la, const float lb) const +{ + return copysignf(1.0f, la) * copysignf(1.0f, lb) * std::min(fabs(la), fabs(lb)); +} + +float polar_decoder_common::llr_even(const float la, + const float lb, + const unsigned char f) const +{ + switch (f) { + case 0: + return lb + la; + default: + return lb - la; + } +} + +void polar_decoder_common::butterfly( + float* llrs, unsigned char* u, const int stage, const int u_num, const int row) +{ + butterfly_volk(llrs, u, stage, u_num, row); +} + +void polar_decoder_common::butterfly_generic( + float* llrs, unsigned char* u, const int stage, const int u_num, const int row) +{ + const int next_stage = stage + 1; + const int half_stage_size = 0x01 << stage; + const int stage_size = half_stage_size << 1; + const bool is_upper_stage_half = row % stage_size < half_stage_size; + + // // this is a natural bit order impl + float* next_llrs = llrs + block_size(); // LLRs are stored in a consecutive array. + float* call_row_llr = llrs + row; + + const int section = row - (row % stage_size); + const int jump_size = ((row % half_stage_size) << 1) % stage_size; + + const int next_upper_row = section + jump_size; + const int next_lower_row = next_upper_row + 1; + + const float* upper_right_llr_ptr = next_llrs + next_upper_row; + const float* lower_right_llr_ptr = next_llrs + next_lower_row; + + if (!is_upper_stage_half) { + const int u_pos = u_num >> stage; + const unsigned char f = u[u_pos - 1]; + *call_row_llr = llr_even(*upper_right_llr_ptr, *lower_right_llr_ptr, f); + return; + } + + if (block_power() > next_stage) { + unsigned char* u_half = u + block_size(); + odd_xor_even_values(u_half, u, u_num); + butterfly(next_llrs, u_half, next_stage, u_num, next_upper_row); + + even_u_values(u_half, u, u_num); + butterfly(next_llrs, u_half, next_stage, u_num, next_lower_row); + } + + *call_row_llr = llr_odd(*upper_right_llr_ptr, *lower_right_llr_ptr); +} + +void polar_decoder_common::butterfly_volk( + float* llrs, unsigned char* u, const int stage, const int u_num, const int row) +{ + volk_32f_8u_polarbutterfly_32f(llrs, u, block_power(), stage, u_num, row); +} + + +void polar_decoder_common::even_u_values(unsigned char* u_even, + const unsigned char* u, + const int u_num) +{ + u++; + for (int i = 1; i < u_num; i += 2) { + *u_even++ = *u; + u += 2; + } +} + +void polar_decoder_common::odd_xor_even_values(unsigned char* u_xor, + const unsigned char* u, + const int u_num) +{ + for (int i = 1; i < u_num; i += 2) { + *u_xor++ = *u ^ *(u + 1); + u += 2; + } +} + +const bool polar_decoder_common::is_frozen_bit(const int u_num) const +{ + return d_frozen_bit_counter < d_frozen_bit_positions.size() && + u_num == d_frozen_bit_positions.at(d_frozen_bit_counter); +} + + +const unsigned char polar_decoder_common::next_frozen_bit() +{ + return d_frozen_bit_values[d_frozen_bit_counter++]; +} + +void polar_decoder_common::extract_info_bits(unsigned char* output, + const unsigned char* input) const +{ + unsigned int frozenbit_num = 0; + for (int i = 0; i < block_size(); i++) { + if (frozenbit_num < d_frozen_bit_positions.size() && + d_frozen_bit_positions.at(frozenbit_num) == i) { frozenbit_num++; - } - else{ + } else { *output++ = *input; - } - input++; } - } - - void - polar_decoder_common::print_pretty_llr_vector(const float* llr_vec) const - { - for(int row = 0; row < block_size(); row++) { - std::cout << row << "->" << int(bit_reverse(row, block_power())) << ":\t"; - for(int stage = 0; stage < block_power() + 1; stage++) { + input++; + } +} + +void polar_decoder_common::print_pretty_llr_vector(const float* llr_vec) const +{ + for (int row = 0; row < block_size(); row++) { + std::cout << row << "->" << int(bit_reverse(row, block_power())) << ":\t"; + for (int stage = 0; stage < block_power() + 1; stage++) { printf("%+4.2f, ", llr_vec[(stage * block_size()) + row]); - } - std::cout << std::endl; } - } + std::cout << std::endl; + } +} - } /* namespace code */ - } /* namespace fec */ +} /* namespace code */ +} /* namespace fec */ } /* namespace gr */ diff --git a/gr-fec/lib/polar_decoder_sc.cc b/gr-fec/lib/polar_decoder_sc.cc index c4ac8877ec..731648f4f4 100644 --- a/gr-fec/lib/polar_decoder_sc.cc +++ b/gr-fec/lib/polar_decoder_sc.cc @@ -32,66 +32,65 @@ #include <cstdio> namespace gr { - namespace fec { - namespace code { +namespace fec { +namespace code { - generic_decoder::sptr - polar_decoder_sc::make(int block_size, int num_info_bits, - std::vector<int> frozen_bit_positions, - std::vector<char> frozen_bit_values) - { - return generic_decoder::sptr - (new polar_decoder_sc(block_size, num_info_bits, - frozen_bit_positions, - frozen_bit_values)); - } +generic_decoder::sptr polar_decoder_sc::make(int block_size, + int num_info_bits, + std::vector<int> frozen_bit_positions, + std::vector<char> frozen_bit_values) +{ + return generic_decoder::sptr(new polar_decoder_sc( + block_size, num_info_bits, frozen_bit_positions, frozen_bit_values)); +} - polar_decoder_sc::polar_decoder_sc(int block_size, int num_info_bits, - std::vector<int> frozen_bit_positions, - std::vector<char> frozen_bit_values) : - polar_decoder_common(block_size, num_info_bits, frozen_bit_positions, frozen_bit_values) - { - d_llr_vec = (float*) volk_malloc(sizeof(float) * block_size * (block_power() + 1), volk_get_alignment()); - memset(d_llr_vec, 0, sizeof(float) * block_size * (block_power() + 1)); - d_u_hat_vec = (unsigned char*) volk_malloc(block_size * (block_power() + 1), volk_get_alignment()); - memset(d_u_hat_vec, 0, sizeof(unsigned char) * block_size * (block_power() + 1)); - } +polar_decoder_sc::polar_decoder_sc(int block_size, + int num_info_bits, + std::vector<int> frozen_bit_positions, + std::vector<char> frozen_bit_values) + : polar_decoder_common( + block_size, num_info_bits, frozen_bit_positions, frozen_bit_values) +{ + d_llr_vec = (float*)volk_malloc(sizeof(float) * block_size * (block_power() + 1), + volk_get_alignment()); + memset(d_llr_vec, 0, sizeof(float) * block_size * (block_power() + 1)); + d_u_hat_vec = (unsigned char*)volk_malloc(block_size * (block_power() + 1), + volk_get_alignment()); + memset(d_u_hat_vec, 0, sizeof(unsigned char) * block_size * (block_power() + 1)); +} - polar_decoder_sc::~polar_decoder_sc() - { - volk_free(d_llr_vec); - volk_free(d_u_hat_vec); - } +polar_decoder_sc::~polar_decoder_sc() +{ + volk_free(d_llr_vec); + volk_free(d_u_hat_vec); +} - void - polar_decoder_sc::generic_work(void* in_buffer, void* out_buffer) - { - const float *in = (const float*) in_buffer; - unsigned char *out = (unsigned char*) out_buffer; +void polar_decoder_sc::generic_work(void* in_buffer, void* out_buffer) +{ + const float* in = (const float*)in_buffer; + unsigned char* out = (unsigned char*)out_buffer; - initialize_decoder(d_u_hat_vec, d_llr_vec, in); - sc_decode(d_llr_vec, d_u_hat_vec); - extract_info_bits(out, d_u_hat_vec); - } + initialize_decoder(d_u_hat_vec, d_llr_vec, in); + sc_decode(d_llr_vec, d_u_hat_vec); + extract_info_bits(out, d_u_hat_vec); +} - void - polar_decoder_sc::sc_decode(float* llrs, unsigned char* u) - { - for(int i = 0; i < block_size(); i++){ - butterfly(llrs, u, 0, i, i); - u[i] = retrieve_bit_from_llr(llrs[i], i); - } - } +void polar_decoder_sc::sc_decode(float* llrs, unsigned char* u) +{ + for (int i = 0; i < block_size(); i++) { + butterfly(llrs, u, 0, i, i); + u[i] = retrieve_bit_from_llr(llrs[i], i); + } +} - unsigned char - polar_decoder_sc::retrieve_bit_from_llr(float llr, const int pos) - { - if(is_frozen_bit(pos)){ - return next_frozen_bit(); - } - return llr_bit_decision(llr); - } +unsigned char polar_decoder_sc::retrieve_bit_from_llr(float llr, const int pos) +{ + if (is_frozen_bit(pos)) { + return next_frozen_bit(); + } + return llr_bit_decision(llr); +} - } /* namespace code */ - } /* namespace fec */ +} /* namespace code */ +} /* namespace fec */ } /* namespace gr */ diff --git a/gr-fec/lib/polar_decoder_sc_list.cc b/gr-fec/lib/polar_decoder_sc_list.cc index 158064bab6..8b922d2044 100644 --- a/gr-fec/lib/polar_decoder_sc_list.cc +++ b/gr-fec/lib/polar_decoder_sc_list.cc @@ -33,91 +33,86 @@ #include <algorithm> namespace gr { - namespace fec { - namespace code { +namespace fec { +namespace code { - generic_decoder::sptr - polar_decoder_sc_list::make(int max_list_size, int block_size, int num_info_bits, - std::vector<int> frozen_bit_positions, - std::vector<char> frozen_bit_values) - { - return generic_decoder::sptr - (new polar_decoder_sc_list(max_list_size, block_size, num_info_bits, - frozen_bit_positions, - frozen_bit_values)); - } +generic_decoder::sptr polar_decoder_sc_list::make(int max_list_size, + int block_size, + int num_info_bits, + std::vector<int> frozen_bit_positions, + std::vector<char> frozen_bit_values) +{ + return generic_decoder::sptr(new polar_decoder_sc_list(max_list_size, + block_size, + num_info_bits, + frozen_bit_positions, + frozen_bit_values)); +} - polar_decoder_sc_list::polar_decoder_sc_list(int max_list_size, int block_size, - int num_info_bits, - std::vector<int> frozen_bit_positions, - std::vector<char> frozen_bit_values) - : polar_decoder_common(block_size, num_info_bits, frozen_bit_positions, frozen_bit_values) - { - d_scl = new polar::scl_list(max_list_size, block_size, block_power()); - } +polar_decoder_sc_list::polar_decoder_sc_list(int max_list_size, + int block_size, + int num_info_bits, + std::vector<int> frozen_bit_positions, + std::vector<char> frozen_bit_values) + : polar_decoder_common( + block_size, num_info_bits, frozen_bit_positions, frozen_bit_values) +{ + d_scl = new polar::scl_list(max_list_size, block_size, block_power()); +} - polar_decoder_sc_list::~polar_decoder_sc_list() - { - delete d_scl; - } +polar_decoder_sc_list::~polar_decoder_sc_list() { delete d_scl; } - void - polar_decoder_sc_list::generic_work(void* in_buffer, void* out_buffer) - { - const float *in = (const float*) in_buffer; - unsigned char *out = (unsigned char*) out_buffer; +void polar_decoder_sc_list::generic_work(void* in_buffer, void* out_buffer) +{ + const float* in = (const float*)in_buffer; + unsigned char* out = (unsigned char*)out_buffer; - initialize_list(in); - const unsigned char* temp = decode_list(); - extract_info_bits(out, temp); - } + initialize_list(in); + const unsigned char* temp = decode_list(); + extract_info_bits(out, temp); +} - void - polar_decoder_sc_list::initialize_list(const float* in_buf) - { - polar::path* init_path = d_scl->initial_path(); - initialize_decoder(init_path->u_vec, init_path->llr_vec, in_buf); - } +void polar_decoder_sc_list::initialize_list(const float* in_buf) +{ + polar::path* init_path = d_scl->initial_path(); + initialize_decoder(init_path->u_vec, init_path->llr_vec, in_buf); +} - const unsigned char* - polar_decoder_sc_list::decode_list() - { - for(int u_num = 0; u_num < block_size(); u_num++){ - decode_bit(u_num); - } - return d_scl->optimal_path()->u_vec; - } +const unsigned char* polar_decoder_sc_list::decode_list() +{ + for (int u_num = 0; u_num < block_size(); u_num++) { + decode_bit(u_num); + } + return d_scl->optimal_path()->u_vec; +} - void - polar_decoder_sc_list::decode_bit(const int u_num) - { - calculate_llrs_for_list(u_num); - set_bit_in_list(u_num); - } +void polar_decoder_sc_list::decode_bit(const int u_num) +{ + calculate_llrs_for_list(u_num); + set_bit_in_list(u_num); +} - void - polar_decoder_sc_list::calculate_llrs_for_list(const int u_num) - { - for(unsigned int i = 0; i < d_scl->active_size(); i++){ - polar::path* current_path = d_scl->next_active_path(); - butterfly(current_path->llr_vec, current_path->u_vec, 0, u_num, u_num); - } - } +void polar_decoder_sc_list::calculate_llrs_for_list(const int u_num) +{ + for (unsigned int i = 0; i < d_scl->active_size(); i++) { + polar::path* current_path = d_scl->next_active_path(); + butterfly(current_path->llr_vec, current_path->u_vec, 0, u_num, u_num); + } +} - void - polar_decoder_sc_list::set_bit_in_list(const int u_num) - { - // 1. if frozen bit, update with known value - if(is_frozen_bit(u_num)){ - const unsigned char frozen_bit = next_frozen_bit(); - d_scl->set_frozen_bit(frozen_bit, u_num); - } - // 2. info bit - else{ - d_scl->set_info_bit(u_num); - } - } +void polar_decoder_sc_list::set_bit_in_list(const int u_num) +{ + // 1. if frozen bit, update with known value + if (is_frozen_bit(u_num)) { + const unsigned char frozen_bit = next_frozen_bit(); + d_scl->set_frozen_bit(frozen_bit, u_num); + } + // 2. info bit + else { + d_scl->set_info_bit(u_num); + } +} - } /* namespace code */ - } /* namespace fec */ +} /* namespace code */ +} /* namespace fec */ } /* namespace gr */ diff --git a/gr-fec/lib/polar_decoder_sc_systematic.cc b/gr-fec/lib/polar_decoder_sc_systematic.cc index 8eb6103112..cb51d8b227 100644 --- a/gr-fec/lib/polar_decoder_sc_systematic.cc +++ b/gr-fec/lib/polar_decoder_sc_systematic.cc @@ -1,19 +1,19 @@ /* -*- 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, @@ -29,76 +29,73 @@ #include <volk/volk.h> namespace gr { - namespace fec { - namespace code { +namespace fec { +namespace code { - generic_decoder::sptr - polar_decoder_sc_systematic::make(int block_size, int num_info_bits, - std::vector<int> frozen_bit_positions) - { - return generic_decoder::sptr( - new polar_decoder_sc_systematic(block_size, num_info_bits, frozen_bit_positions)); - } +generic_decoder::sptr polar_decoder_sc_systematic::make( + int block_size, int num_info_bits, std::vector<int> frozen_bit_positions) +{ + return generic_decoder::sptr( + new polar_decoder_sc_systematic(block_size, num_info_bits, frozen_bit_positions)); +} - polar_decoder_sc_systematic::polar_decoder_sc_systematic( - int block_size, int num_info_bits, std::vector<int> frozen_bit_positions) : - polar_decoder_common(block_size, num_info_bits, frozen_bit_positions, std::vector<char>()) - { - d_llr_vec = (float*) volk_malloc(sizeof(float) * block_size * (block_power() + 1), volk_get_alignment()); - memset(d_llr_vec, 0, sizeof(float) * block_size * (block_power() + 1)); - d_u_hat_vec = (unsigned char*) volk_malloc(block_size * (block_power() + 1), volk_get_alignment()); - memset(d_u_hat_vec, 0, sizeof(unsigned char) * block_size * (block_power() + 1)); - d_frame_vec = (unsigned char*) volk_malloc(block_size, volk_get_alignment()); - memset(d_frame_vec, 0, sizeof(unsigned char) * block_size); - } +polar_decoder_sc_systematic::polar_decoder_sc_systematic( + int block_size, int num_info_bits, std::vector<int> frozen_bit_positions) + : polar_decoder_common( + block_size, num_info_bits, frozen_bit_positions, std::vector<char>()) +{ + d_llr_vec = (float*)volk_malloc(sizeof(float) * block_size * (block_power() + 1), + volk_get_alignment()); + memset(d_llr_vec, 0, sizeof(float) * block_size * (block_power() + 1)); + d_u_hat_vec = (unsigned char*)volk_malloc(block_size * (block_power() + 1), + volk_get_alignment()); + memset(d_u_hat_vec, 0, sizeof(unsigned char) * block_size * (block_power() + 1)); + d_frame_vec = (unsigned char*)volk_malloc(block_size, volk_get_alignment()); + memset(d_frame_vec, 0, sizeof(unsigned char) * block_size); +} - polar_decoder_sc_systematic::~polar_decoder_sc_systematic() - { - volk_free(d_llr_vec); - volk_free(d_u_hat_vec); - volk_free(d_frame_vec); - } +polar_decoder_sc_systematic::~polar_decoder_sc_systematic() +{ + volk_free(d_llr_vec); + volk_free(d_u_hat_vec); + volk_free(d_frame_vec); +} - void - polar_decoder_sc_systematic::generic_work(void* in_buffer, void* out_buffer) - { - const float *in = (const float*) in_buffer; - unsigned char *out = (unsigned char*) out_buffer; +void polar_decoder_sc_systematic::generic_work(void* in_buffer, void* out_buffer) +{ + const float* in = (const float*)in_buffer; + unsigned char* out = (unsigned char*)out_buffer; - initialize_decoder(d_u_hat_vec, d_llr_vec, in); - sc_decode(d_llr_vec, d_u_hat_vec); - volk_encode_block(d_frame_vec, d_u_hat_vec); - extract_info_bits_reversed(out, d_frame_vec); - } + initialize_decoder(d_u_hat_vec, d_llr_vec, in); + sc_decode(d_llr_vec, d_u_hat_vec); + volk_encode_block(d_frame_vec, d_u_hat_vec); + extract_info_bits_reversed(out, d_frame_vec); +} - void - polar_decoder_sc_systematic::sc_decode(float* llrs, unsigned char* u) - { - for(int i = 0; i < block_size(); i++){ - butterfly(llrs, u, 0, i, i); - u[i] = retrieve_bit_from_llr(llrs[i], i); - } - } +void polar_decoder_sc_systematic::sc_decode(float* llrs, unsigned char* u) +{ + for (int i = 0; i < block_size(); i++) { + butterfly(llrs, u, 0, i, i); + u[i] = retrieve_bit_from_llr(llrs[i], i); + } +} - unsigned char - polar_decoder_sc_systematic::retrieve_bit_from_llr(float llr, const int pos) - { - if(is_frozen_bit(pos)){ - return next_frozen_bit(); - } - return llr_bit_decision(llr); - } +unsigned char polar_decoder_sc_systematic::retrieve_bit_from_llr(float llr, const int pos) +{ + if (is_frozen_bit(pos)) { + return next_frozen_bit(); + } + return llr_bit_decision(llr); +} - void - polar_decoder_sc_systematic::extract_info_bits_reversed(unsigned char* outbuf, - const unsigned char* inbuf) - { - for(int i = 0; i < num_info_bits(); i++){ - *outbuf++ = inbuf[d_info_bit_positions_reversed[i]]; - } - } +void polar_decoder_sc_systematic::extract_info_bits_reversed(unsigned char* outbuf, + const unsigned char* inbuf) +{ + for (int i = 0; i < num_info_bits(); i++) { + *outbuf++ = inbuf[d_info_bit_positions_reversed[i]]; + } +} - } // namespace code - } /* namespace fec */ +} // namespace code +} /* namespace fec */ } /* namespace gr */ - diff --git a/gr-fec/lib/polar_encoder.cc b/gr-fec/lib/polar_encoder.cc index d587793f4a..07df87f17c 100644 --- a/gr-fec/lib/polar_encoder.cc +++ b/gr-fec/lib/polar_encoder.cc @@ -34,160 +34,148 @@ #include <gnuradio/blocks/unpack_k_bits.h> namespace gr { - namespace fec { - namespace code { - - generic_encoder::sptr - polar_encoder::make(int block_size, int num_info_bits, - std::vector<int> frozen_bit_positions, - std::vector<char> frozen_bit_values, bool is_packed) - { - return generic_encoder::sptr - (new polar_encoder(block_size, num_info_bits, - frozen_bit_positions, - frozen_bit_values, - is_packed)); - } - - polar_encoder::polar_encoder(int block_size, int num_info_bits, - std::vector<int>& frozen_bit_positions, - std::vector<char>& frozen_bit_values, bool is_packed) : - polar_common(block_size, num_info_bits, frozen_bit_positions, frozen_bit_values), - d_is_packed(is_packed) - { - setup_frozen_bit_inserter(); - } - - void - polar_encoder::setup_frozen_bit_inserter() - { - d_frozen_bit_prototype = (unsigned char*) volk_malloc(block_size() >> 3, - volk_get_alignment()); - memset(d_frozen_bit_prototype, 0, block_size() >> 3); - - for(unsigned int i = 0; i < d_frozen_bit_positions.size(); i++) { - int rev_pos = (int) bit_reverse((long) d_frozen_bit_positions.at(i), block_power()); - unsigned char frozen_bit = (unsigned char) d_frozen_bit_values.at(i); - insert_unpacked_bit_into_packed_array_at_position(d_frozen_bit_prototype, frozen_bit, - rev_pos); - } - } - - polar_encoder::~polar_encoder() - { - volk_free(d_frozen_bit_prototype); - } - - void - polar_encoder::generic_work(void* in_buffer, void* out_buffer) - { - const unsigned char *in = (const unsigned char*) in_buffer; - unsigned char *out = (unsigned char*) out_buffer; - - if(d_is_packed){ - insert_packed_frozen_bits_and_reverse(out, in); - encode_vector_packed(out); - } - else{ - volk_encode(out, in); - } - } - - void - polar_encoder::encode_vector_packed(unsigned char* target) const - { - encode_vector_packed_subbyte(target); - encode_vector_packed_interbyte(target); - } - - void - polar_encoder::encode_vector_packed_subbyte(unsigned char* target) const - { - int num_bytes_per_block = block_size() >> 3; - while(num_bytes_per_block) { - encode_packed_byte(target); - ++target; - --num_bytes_per_block; - } - } - - void - polar_encoder::encode_packed_byte(unsigned char* target) const - { - // this method only produces correct results if block_size > 4. - // this is assumed to be the case. - *target ^= 0xaa & (*target << 1); - *target ^= 0xcc & (*target << 2); - *target ^= *target << 4; - } - - void - polar_encoder::encode_vector_packed_interbyte(unsigned char* target) const - { - int branch_byte_size = 1; - unsigned char* pos; - int n_branches = block_size() >> 4; - int byte = 0; - for(int stage = 3; stage < block_power(); ++stage) { - pos = target; - - for(int branch = 0; branch < n_branches; ++branch) { +namespace fec { +namespace code { + +generic_encoder::sptr polar_encoder::make(int block_size, + int num_info_bits, + std::vector<int> frozen_bit_positions, + std::vector<char> frozen_bit_values, + bool is_packed) +{ + return generic_encoder::sptr(new polar_encoder( + block_size, num_info_bits, frozen_bit_positions, frozen_bit_values, is_packed)); +} + +polar_encoder::polar_encoder(int block_size, + int num_info_bits, + std::vector<int>& frozen_bit_positions, + std::vector<char>& frozen_bit_values, + bool is_packed) + : polar_common(block_size, num_info_bits, frozen_bit_positions, frozen_bit_values), + d_is_packed(is_packed) +{ + setup_frozen_bit_inserter(); +} + +void polar_encoder::setup_frozen_bit_inserter() +{ + d_frozen_bit_prototype = + (unsigned char*)volk_malloc(block_size() >> 3, volk_get_alignment()); + memset(d_frozen_bit_prototype, 0, block_size() >> 3); + + for (unsigned int i = 0; i < d_frozen_bit_positions.size(); i++) { + int rev_pos = (int)bit_reverse((long)d_frozen_bit_positions.at(i), block_power()); + unsigned char frozen_bit = (unsigned char)d_frozen_bit_values.at(i); + insert_unpacked_bit_into_packed_array_at_position( + d_frozen_bit_prototype, frozen_bit, rev_pos); + } +} + +polar_encoder::~polar_encoder() { volk_free(d_frozen_bit_prototype); } + +void polar_encoder::generic_work(void* in_buffer, void* out_buffer) +{ + const unsigned char* in = (const unsigned char*)in_buffer; + unsigned char* out = (unsigned char*)out_buffer; + + if (d_is_packed) { + insert_packed_frozen_bits_and_reverse(out, in); + encode_vector_packed(out); + } else { + volk_encode(out, in); + } +} + +void polar_encoder::encode_vector_packed(unsigned char* target) const +{ + encode_vector_packed_subbyte(target); + encode_vector_packed_interbyte(target); +} + +void polar_encoder::encode_vector_packed_subbyte(unsigned char* target) const +{ + int num_bytes_per_block = block_size() >> 3; + while (num_bytes_per_block) { + encode_packed_byte(target); + ++target; + --num_bytes_per_block; + } +} + +void polar_encoder::encode_packed_byte(unsigned char* target) const +{ + // this method only produces correct results if block_size > 4. + // this is assumed to be the case. + *target ^= 0xaa & (*target << 1); + *target ^= 0xcc & (*target << 2); + *target ^= *target << 4; +} + +void polar_encoder::encode_vector_packed_interbyte(unsigned char* target) const +{ + int branch_byte_size = 1; + unsigned char* pos; + int n_branches = block_size() >> 4; + int byte = 0; + for (int stage = 3; stage < block_power(); ++stage) { + pos = target; + + for (int branch = 0; branch < n_branches; ++branch) { byte = 0; - while(byte < branch_byte_size) { - *pos ^= *(pos + branch_byte_size); - ++pos; - ++byte; + while (byte < branch_byte_size) { + *pos ^= *(pos + branch_byte_size); + ++pos; + ++byte; } pos += branch_byte_size; - } - - n_branches >>= 1; - branch_byte_size <<= 1; } - } - - void - polar_encoder::insert_packed_frozen_bits_and_reverse(unsigned char* target, - const unsigned char* input) const - { - memcpy(target, d_frozen_bit_prototype, block_size() >> 3); - const int* info_bit_reversed_positions_ptr = &d_info_bit_positions_reversed[0]; - int bit_num = 0; - unsigned char byte = *input; - int bit_pos; - while(bit_num < num_info_bits()) { - bit_pos = *info_bit_reversed_positions_ptr++; - insert_packet_bit_into_packed_array_at_position(target, byte, bit_pos, bit_num % 8); - ++bit_num; - if(bit_num % 8 == 0) { + + n_branches >>= 1; + branch_byte_size <<= 1; + } +} + +void polar_encoder::insert_packed_frozen_bits_and_reverse( + unsigned char* target, const unsigned char* input) const +{ + memcpy(target, d_frozen_bit_prototype, block_size() >> 3); + const int* info_bit_reversed_positions_ptr = &d_info_bit_positions_reversed[0]; + int bit_num = 0; + unsigned char byte = *input; + int bit_pos; + while (bit_num < num_info_bits()) { + bit_pos = *info_bit_reversed_positions_ptr++; + insert_packet_bit_into_packed_array_at_position( + target, byte, bit_pos, bit_num % 8); + ++bit_num; + if (bit_num % 8 == 0) { ++input; byte = *input; - } } - } - - void - polar_encoder::insert_unpacked_bit_into_packed_array_at_position(unsigned char* target, - const unsigned char bit, - const int pos) const - { - int byte_pos = pos >> 3; - int bit_pos = pos & 0x7; - *(target + byte_pos) ^= bit << (7 - bit_pos); - } - - void - polar_encoder::insert_packet_bit_into_packed_array_at_position(unsigned char* target, - const unsigned char bit, - const int target_pos, - const int bit_pos) const - { - insert_unpacked_bit_into_packed_array_at_position(target, (bit >> (7 - bit_pos)) & 0x01, - target_pos); - } - - } /* namespace code */ - } /* namespace fec */ + } +} + +void polar_encoder::insert_unpacked_bit_into_packed_array_at_position( + unsigned char* target, const unsigned char bit, const int pos) const +{ + int byte_pos = pos >> 3; + int bit_pos = pos & 0x7; + *(target + byte_pos) ^= bit << (7 - bit_pos); +} + +void polar_encoder::insert_packet_bit_into_packed_array_at_position( + unsigned char* target, + const unsigned char bit, + const int target_pos, + const int bit_pos) const +{ + insert_unpacked_bit_into_packed_array_at_position( + target, (bit >> (7 - bit_pos)) & 0x01, target_pos); +} + +} /* namespace code */ +} /* namespace fec */ } /* namespace gr */ diff --git a/gr-fec/lib/polar_encoder_systematic.cc b/gr-fec/lib/polar_encoder_systematic.cc index 80bfa1ca0c..05b1472aa7 100644 --- a/gr-fec/lib/polar_encoder_systematic.cc +++ b/gr-fec/lib/polar_encoder_systematic.cc @@ -1,19 +1,19 @@ /* -*- 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, @@ -29,51 +29,49 @@ #include <volk/volk.h> namespace gr { - namespace fec { - namespace code { +namespace fec { +namespace code { - generic_encoder::sptr - polar_encoder_systematic::make(int block_size, int num_info_bits, - std::vector<int> frozen_bit_positions) - { - return generic_encoder::sptr( - new polar_encoder_systematic(block_size, num_info_bits, frozen_bit_positions)); - } +generic_encoder::sptr polar_encoder_systematic::make( + int block_size, int num_info_bits, std::vector<int> frozen_bit_positions) +{ + return generic_encoder::sptr( + new polar_encoder_systematic(block_size, num_info_bits, frozen_bit_positions)); +} - polar_encoder_systematic::polar_encoder_systematic(int block_size, int num_info_bits, - std::vector<int> frozen_bit_positions) : - polar_common(block_size, num_info_bits, frozen_bit_positions, std::vector<char>()) - { - d_volk_syst_intermediate = (unsigned char*) volk_malloc(sizeof(unsigned char) * block_size, volk_get_alignment()); - } +polar_encoder_systematic::polar_encoder_systematic(int block_size, + int num_info_bits, + std::vector<int> frozen_bit_positions) + : polar_common(block_size, num_info_bits, frozen_bit_positions, std::vector<char>()) +{ + d_volk_syst_intermediate = (unsigned char*)volk_malloc( + sizeof(unsigned char) * block_size, volk_get_alignment()); +} - polar_encoder_systematic::~polar_encoder_systematic() - { - volk_free(d_volk_syst_intermediate); - } +polar_encoder_systematic::~polar_encoder_systematic() +{ + volk_free(d_volk_syst_intermediate); +} - void - polar_encoder_systematic::generic_work(void* in_buffer, void* out_buffer) - { - const unsigned char *in = (const unsigned char*) in_buffer; - unsigned char *out = (unsigned char*) out_buffer; +void polar_encoder_systematic::generic_work(void* in_buffer, void* out_buffer) +{ + const unsigned char* in = (const unsigned char*)in_buffer; + unsigned char* out = (unsigned char*)out_buffer; - volk_encode(out, in); - bit_reverse_and_reset_frozen_bits(d_volk_syst_intermediate, out); - volk_encode_block(out, d_volk_syst_intermediate); - } + volk_encode(out, in); + bit_reverse_and_reset_frozen_bits(d_volk_syst_intermediate, out); + volk_encode_block(out, d_volk_syst_intermediate); +} - void - polar_encoder_systematic::bit_reverse_and_reset_frozen_bits(unsigned char* outbuf, - const unsigned char* inbuf) - { - memset(outbuf, 0, sizeof(unsigned char) * block_size()); - for(int i = 0; i < num_info_bits(); i++){ - outbuf[d_info_bit_positions[i]] = inbuf[d_info_bit_positions_reversed[i]]; - } - } +void polar_encoder_systematic::bit_reverse_and_reset_frozen_bits( + unsigned char* outbuf, const unsigned char* inbuf) +{ + memset(outbuf, 0, sizeof(unsigned char) * block_size()); + for (int i = 0; i < num_info_bits(); i++) { + outbuf[d_info_bit_positions[i]] = inbuf[d_info_bit_positions_reversed[i]]; + } +} - } /* namespace code */ - } /* namespace fec */ +} /* namespace code */ +} /* namespace fec */ } /* namespace gr */ - diff --git a/gr-fec/lib/puncture_bb_impl.cc b/gr-fec/lib/puncture_bb_impl.cc index 53808fb158..14995b84c4 100644 --- a/gr-fec/lib/puncture_bb_impl.cc +++ b/gr-fec/lib/puncture_bb_impl.cc @@ -33,122 +33,114 @@ #include <stdio.h> namespace gr { - namespace fec { - - puncture_bb::sptr - puncture_bb::make(int puncsize, int puncpat, int delay) - { - return gnuradio::get_initial_sptr - (new puncture_bb_impl(puncsize, puncpat, delay)); - } - - puncture_bb_impl::puncture_bb_impl(int puncsize, int puncpat, int delay) - : block("puncture_bb", - io_signature::make(1, 1, sizeof(char)), - io_signature::make(1, 1, sizeof(char))), - d_puncsize(puncsize), d_delay(delay) - { - // Create a mask of all 1's of puncsize length - int mask = 0; - for(int i = 0; i < d_puncsize; i++) +namespace fec { + +puncture_bb::sptr puncture_bb::make(int puncsize, int puncpat, int delay) +{ + return gnuradio::get_initial_sptr(new puncture_bb_impl(puncsize, puncpat, delay)); +} + +puncture_bb_impl::puncture_bb_impl(int puncsize, int puncpat, int delay) + : block("puncture_bb", + io_signature::make(1, 1, sizeof(char)), + io_signature::make(1, 1, sizeof(char))), + d_puncsize(puncsize), + d_delay(delay) +{ + // Create a mask of all 1's of puncsize length + int mask = 0; + for (int i = 0; i < d_puncsize; i++) mask |= 1 << i; - // Rotate the pattern for the delay value; then mask it if there - // are any excess 1's in the pattern. - for(int i = 0; i < d_delay; ++i) { - puncpat = ((puncpat & 1) << (d_puncsize - 1)) + (puncpat >> 1); - } - d_puncpat = puncpat & mask; - - // Calculate the number of holes in the pattern. The mask is all - // 1's given puncsize and puncpat is a pattern with >= puncsize - // 0's (masked to ensure this). The difference between the - // number of 1's in the mask and the puncpat is the number of - // holes. - uint32_t count_mask=0, count_pat=0; - volk_32u_popcnt(&count_mask, static_cast<uint32_t>(mask)); - volk_32u_popcnt(&count_pat, static_cast<uint32_t>(d_puncpat)); - d_puncholes = count_mask - count_pat; - - set_fixed_rate(true); - set_relative_rate((uint64_t)(d_puncsize - d_puncholes), - (uint64_t)d_puncsize); - set_output_multiple(d_puncsize - d_puncholes); - //set_msg_handler(boost::bind(&puncture_bb_impl::catch_msg, this, _1)); + // Rotate the pattern for the delay value; then mask it if there + // are any excess 1's in the pattern. + for (int i = 0; i < d_delay; ++i) { + puncpat = ((puncpat & 1) << (d_puncsize - 1)) + (puncpat >> 1); } + d_puncpat = puncpat & mask; + + // Calculate the number of holes in the pattern. The mask is all + // 1's given puncsize and puncpat is a pattern with >= puncsize + // 0's (masked to ensure this). The difference between the + // number of 1's in the mask and the puncpat is the number of + // holes. + uint32_t count_mask = 0, count_pat = 0; + volk_32u_popcnt(&count_mask, static_cast<uint32_t>(mask)); + volk_32u_popcnt(&count_pat, static_cast<uint32_t>(d_puncpat)); + d_puncholes = count_mask - count_pat; + + set_fixed_rate(true); + set_relative_rate((uint64_t)(d_puncsize - d_puncholes), (uint64_t)d_puncsize); + set_output_multiple(d_puncsize - d_puncholes); + // set_msg_handler(boost::bind(&puncture_bb_impl::catch_msg, this, _1)); +} + +puncture_bb_impl::~puncture_bb_impl() {} + +int puncture_bb_impl::fixed_rate_ninput_to_noutput(int ninput) +{ + return (int)((((d_puncsize - d_puncholes) / (double)(d_puncsize)) * ninput) + .5); +} + +int puncture_bb_impl::fixed_rate_noutput_to_ninput(int noutput) +{ + return (int)(((d_puncsize / (double)(d_puncsize - d_puncholes)) * noutput) + .5); +} + +void puncture_bb_impl::forecast(int noutput_items, gr_vector_int& ninput_items_required) +{ + ninput_items_required[0] = + (int)(((d_puncsize / (double)(d_puncsize - d_puncholes)) * noutput_items) + .5); +} - puncture_bb_impl::~puncture_bb_impl() - { - } - - int - puncture_bb_impl::fixed_rate_ninput_to_noutput(int ninput) - { - return (int)((((d_puncsize - d_puncholes)/(double)(d_puncsize)) * ninput) + .5); - } - - int - puncture_bb_impl::fixed_rate_noutput_to_ninput(int noutput) - { - return (int)(((d_puncsize/(double)(d_puncsize-d_puncholes)) * noutput) + .5); - } - - void - puncture_bb_impl::forecast(int noutput_items, - gr_vector_int& ninput_items_required) - { - ninput_items_required[0] = (int)(((d_puncsize/(double)(d_puncsize-d_puncholes)) * noutput_items) + .5); +/* +void +puncture_bb_impl::catch_msg(pmt::pmt_t msg) +{ + long mlong = pmt::pmt_to_long(msg); + for(int i = 0; i < mlong; ++i) { + d_puncholes = (d_puncholes >> 1) | ((d_puncholes & 1) << (d_puncsize - 1)); + } +} +*/ + +int puncture_bb_impl::general_work(int noutput_items, + gr_vector_int& ninput_items, + gr_vector_const_void_star& input_items, + gr_vector_void_star& output_items) +{ + const char* in = (const char*)input_items[0]; + char* out = (char*)output_items[0]; + + for (int i = 0, k = 0; i < noutput_items / output_multiple(); ++i) { + for (int j = 0; j < d_puncsize; ++j) { + if ((d_puncpat >> (d_puncsize - 1 - j)) & 1) { + out[k++] = in[i * d_puncsize + j]; + } + } } /* - void - puncture_bb_impl::catch_msg(pmt::pmt_t msg) - { - long mlong = pmt::pmt_to_long(msg); - for(int i = 0; i < mlong; ++i) { - d_puncholes = (d_puncholes >> 1) | ((d_puncholes & 1) << (d_puncsize - 1)); + GR_LOG_DEBUG(d_debug_logger, ">>>>>> start"); + for(int i = 0, k=0; i < noutput_items; ++i) { + if((d_puncpat >> (d_puncsize - 1 - (i % d_puncsize))) & 1) { + GR_LOG_DEBUG(d_debug_logger, boost::format("%1%...%2%") \ + % out[k++] % in[i]); } - } - */ - - int - puncture_bb_impl::general_work(int noutput_items, - gr_vector_int& ninput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) - { - const char *in = (const char *)input_items[0]; - char *out = (char *)output_items[0]; - - for(int i=0, k=0; i < noutput_items/output_multiple(); ++i) { - for(int j = 0; j < d_puncsize; ++j) { - if((d_puncpat >> (d_puncsize - 1 - j)) & 1) { - out[k++] = in[i*d_puncsize + j]; - } - } - } - - /* - GR_LOG_DEBUG(d_debug_logger, ">>>>>> start"); - for(int i = 0, k=0; i < noutput_items; ++i) { - if((d_puncpat >> (d_puncsize - 1 - (i % d_puncsize))) & 1) { - GR_LOG_DEBUG(d_debug_logger, boost::format("%1%...%2%") \ - % out[k++] % in[i]); - } - else { - GR_LOG_DEBUG(d_debug_logger, boost::format("snit %1%") % in[i]); - } + else { + GR_LOG_DEBUG(d_debug_logger, boost::format("snit %1%") % in[i]); } + } - GR_LOG_DEBUG(d_debug_logger, boost::format("comp: %1%, %2%\n") \ - % noutput_items % ninput_items[0]); - GR_LOG_DEBUG(d_debug_logger, boost::format("consuming %1%") \ - % ((int)(((1.0/relative_rate()) * noutput_items) + .5))); - */ + GR_LOG_DEBUG(d_debug_logger, boost::format("comp: %1%, %2%\n") \ + % noutput_items % ninput_items[0]); + GR_LOG_DEBUG(d_debug_logger, boost::format("consuming %1%") \ + % ((int)(((1.0/relative_rate()) * noutput_items) + .5))); + */ - consume_each((int)(((1.0/relative_rate()) * noutput_items) + .5)); - return noutput_items; - } + consume_each((int)(((1.0 / relative_rate()) * noutput_items) + .5)); + return noutput_items; +} - } /* namespace fec */ -}/* namespace gr */ +} /* namespace fec */ +} /* namespace gr */ diff --git a/gr-fec/lib/puncture_bb_impl.h b/gr-fec/lib/puncture_bb_impl.h index abf9c09dc1..eb2f835a22 100644 --- a/gr-fec/lib/puncture_bb_impl.h +++ b/gr-fec/lib/puncture_bb_impl.h @@ -26,33 +26,32 @@ #include <gnuradio/fec/puncture_bb.h> namespace gr { - namespace fec { - - class FEC_API puncture_bb_impl : public puncture_bb - { - private: - int d_puncsize; - int d_delay; - int d_puncholes; - int d_puncpat; - - public: - puncture_bb_impl(int puncsize, int puncpat, int delay=0); - ~puncture_bb_impl(); - - //void catch_msg(pmt::pmt_t msg); - - int general_work(int noutput_items, - gr_vector_int& ninput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); - int fixed_rate_ninput_to_noutput(int ninput); - int fixed_rate_noutput_to_ninput(int noutput); - void forecast(int noutput_items, - gr_vector_int& ninput_items_required); - }; - - } /* namespace fec */ +namespace fec { + +class FEC_API puncture_bb_impl : public puncture_bb +{ +private: + int d_puncsize; + int d_delay; + int d_puncholes; + int d_puncpat; + +public: + puncture_bb_impl(int puncsize, int puncpat, int delay = 0); + ~puncture_bb_impl(); + + // void catch_msg(pmt::pmt_t msg); + + int general_work(int noutput_items, + gr_vector_int& ninput_items, + gr_vector_const_void_star& input_items, + gr_vector_void_star& output_items); + int fixed_rate_ninput_to_noutput(int ninput); + int fixed_rate_noutput_to_ninput(int noutput); + void forecast(int noutput_items, gr_vector_int& ninput_items_required); +}; + +} /* namespace fec */ } /* namespace gr */ #endif /* INCLUDED_FEC_PUNCTURE_BB_IMPL_H */ diff --git a/gr-fec/lib/puncture_ff_impl.cc b/gr-fec/lib/puncture_ff_impl.cc index abc3da541a..d4c1c05723 100644 --- a/gr-fec/lib/puncture_ff_impl.cc +++ b/gr-fec/lib/puncture_ff_impl.cc @@ -33,122 +33,114 @@ #include <stdio.h> namespace gr { - namespace fec { - - puncture_ff::sptr - puncture_ff::make(int puncsize, int puncpat, int delay) - { - return gnuradio::get_initial_sptr - (new puncture_ff_impl(puncsize, puncpat, delay)); - } - - puncture_ff_impl::puncture_ff_impl(int puncsize, int puncpat, int delay) - : block("puncture_ff", - io_signature::make(1, 1, sizeof(float)), - io_signature::make(1, 1, sizeof(float))), - d_puncsize(puncsize), d_delay(delay) - { - // Create a mask of all 1's of puncsize length - int mask = 0; - for(int i = 0; i < d_puncsize; i++) +namespace fec { + +puncture_ff::sptr puncture_ff::make(int puncsize, int puncpat, int delay) +{ + return gnuradio::get_initial_sptr(new puncture_ff_impl(puncsize, puncpat, delay)); +} + +puncture_ff_impl::puncture_ff_impl(int puncsize, int puncpat, int delay) + : block("puncture_ff", + io_signature::make(1, 1, sizeof(float)), + io_signature::make(1, 1, sizeof(float))), + d_puncsize(puncsize), + d_delay(delay) +{ + // Create a mask of all 1's of puncsize length + int mask = 0; + for (int i = 0; i < d_puncsize; i++) mask |= 1 << i; - // Rotate the pattern for the delay value; then mask it if there - // are any excess 1's in the pattern. - for(int i = 0; i < d_delay; ++i) { - puncpat = ((puncpat & 1) << (d_puncsize - 1)) + (puncpat >> 1); - } - d_puncpat = puncpat & mask; - - // Calculate the number of holes in the pattern. The mask is all - // 1's given puncsize and puncpat is a pattern with >= puncsize - // 0's (masked to ensure this). The difference between the - // number of 1's in the mask and the puncpat is the number of - // holes. - uint32_t count_mask=0, count_pat=0; - volk_32u_popcnt(&count_mask, static_cast<uint32_t>(mask)); - volk_32u_popcnt(&count_pat, static_cast<uint32_t>(d_puncpat)); - d_puncholes = count_mask - count_pat; - - set_fixed_rate(true); - set_relative_rate((uint64_t)(d_puncsize - d_puncholes), - (uint64_t)d_puncsize); - set_output_multiple(d_puncsize - d_puncholes); - //set_msg_handler(boost::bind(&puncture_ff_impl::catch_msg, this, _1)); + // Rotate the pattern for the delay value; then mask it if there + // are any excess 1's in the pattern. + for (int i = 0; i < d_delay; ++i) { + puncpat = ((puncpat & 1) << (d_puncsize - 1)) + (puncpat >> 1); } + d_puncpat = puncpat & mask; + + // Calculate the number of holes in the pattern. The mask is all + // 1's given puncsize and puncpat is a pattern with >= puncsize + // 0's (masked to ensure this). The difference between the + // number of 1's in the mask and the puncpat is the number of + // holes. + uint32_t count_mask = 0, count_pat = 0; + volk_32u_popcnt(&count_mask, static_cast<uint32_t>(mask)); + volk_32u_popcnt(&count_pat, static_cast<uint32_t>(d_puncpat)); + d_puncholes = count_mask - count_pat; + + set_fixed_rate(true); + set_relative_rate((uint64_t)(d_puncsize - d_puncholes), (uint64_t)d_puncsize); + set_output_multiple(d_puncsize - d_puncholes); + // set_msg_handler(boost::bind(&puncture_ff_impl::catch_msg, this, _1)); +} + +puncture_ff_impl::~puncture_ff_impl() {} + +int puncture_ff_impl::fixed_rate_ninput_to_noutput(int ninput) +{ + return (int)((((d_puncsize - d_puncholes) / (double)(d_puncsize)) * ninput) + .5); +} + +int puncture_ff_impl::fixed_rate_noutput_to_ninput(int noutput) +{ + return (int)(((d_puncsize / (double)(d_puncsize - d_puncholes)) * noutput) + .5); +} + +void puncture_ff_impl::forecast(int noutput_items, gr_vector_int& ninput_items_required) +{ + ninput_items_required[0] = + (int)(((d_puncsize / (double)(d_puncsize - d_puncholes)) * noutput_items) + .5); +} - puncture_ff_impl::~puncture_ff_impl() - { - } - - int - puncture_ff_impl::fixed_rate_ninput_to_noutput(int ninput) - { - return (int)((((d_puncsize - d_puncholes)/(double)(d_puncsize)) * ninput) + .5); - } - - int - puncture_ff_impl::fixed_rate_noutput_to_ninput(int noutput) - { - return (int)(((d_puncsize/(double)(d_puncsize-d_puncholes)) * noutput) + .5); - } - - void - puncture_ff_impl::forecast(int noutput_items, - gr_vector_int& ninput_items_required) - { - ninput_items_required[0] = (int)(((d_puncsize/(double)(d_puncsize-d_puncholes)) * noutput_items) + .5); +/* +void +puncture_ff_impl::catch_msg(pmt::pmt_t msg) +{ + long mlong = pmt::pmt_to_long(msg); + for(int i = 0; i < mlong; ++i) { + d_puncholes = (d_puncholes >> 1) | ((d_puncholes & 1) << (d_puncsize - 1)); + } +} +*/ + +int puncture_ff_impl::general_work(int noutput_items, + gr_vector_int& ninput_items, + gr_vector_const_void_star& input_items, + gr_vector_void_star& output_items) +{ + const float* in = (const float*)input_items[0]; + float* out = (float*)output_items[0]; + + for (int i = 0, k = 0; i < noutput_items / output_multiple(); ++i) { + for (int j = 0; j < d_puncsize; ++j) { + if ((d_puncpat >> (d_puncsize - 1 - j)) & 1) { + out[k++] = in[i * d_puncsize + j]; + } + } } /* - void - puncture_ff_impl::catch_msg(pmt::pmt_t msg) - { - long mlong = pmt::pmt_to_long(msg); - for(int i = 0; i < mlong; ++i) { - d_puncholes = (d_puncholes >> 1) | ((d_puncholes & 1) << (d_puncsize - 1)); + GR_LOG_DEBUG(d_debug_logger, ">>>>>> start"); + for(int i = 0, k=0; i < noutput_items; ++i) { + if((d_puncpat >> (d_puncsize - 1 - (i % d_puncsize))) & 1) { + GR_LOG_DEBUG(d_debug_logger, boost::format("%1%...%2%") \ + % out[k++] % in[i]); } - } - */ - - int - puncture_ff_impl::general_work(int noutput_items, - gr_vector_int& ninput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) - { - const float *in = (const float *)input_items[0]; - float *out = (float *)output_items[0]; - - for(int i=0, k=0; i < noutput_items/output_multiple(); ++i) { - for(int j = 0; j < d_puncsize; ++j) { - if((d_puncpat >> (d_puncsize - 1 - j)) & 1) { - out[k++] = in[i*d_puncsize + j]; - } - } - } - - /* - GR_LOG_DEBUG(d_debug_logger, ">>>>>> start"); - for(int i = 0, k=0; i < noutput_items; ++i) { - if((d_puncpat >> (d_puncsize - 1 - (i % d_puncsize))) & 1) { - GR_LOG_DEBUG(d_debug_logger, boost::format("%1%...%2%") \ - % out[k++] % in[i]); - } - else { - GR_LOG_DEBUG(d_debug_logger, boost::format("snit %1%") % in[i]); - } + else { + GR_LOG_DEBUG(d_debug_logger, boost::format("snit %1%") % in[i]); } + } - GR_LOG_DEBUG(d_debug_logger, boost::format("comp: %1%, %2%\n") \ - % noutput_items % ninput_items[0]); - GR_LOG_DEBUG(d_debug_logger, boost::format("consuming %1%") \ - % ((int)(((1.0/relative_rate()) * noutput_items) + .5))); - */ + GR_LOG_DEBUG(d_debug_logger, boost::format("comp: %1%, %2%\n") \ + % noutput_items % ninput_items[0]); + GR_LOG_DEBUG(d_debug_logger, boost::format("consuming %1%") \ + % ((int)(((1.0/relative_rate()) * noutput_items) + .5))); + */ - consume_each((int)(((1.0/relative_rate()) * noutput_items) + .5)); - return noutput_items; - } + consume_each((int)(((1.0 / relative_rate()) * noutput_items) + .5)); + return noutput_items; +} - } /* namespace fec */ -}/* namespace gr */ +} /* namespace fec */ +} /* namespace gr */ diff --git a/gr-fec/lib/puncture_ff_impl.h b/gr-fec/lib/puncture_ff_impl.h index e86d0d25c5..f2b147381a 100644 --- a/gr-fec/lib/puncture_ff_impl.h +++ b/gr-fec/lib/puncture_ff_impl.h @@ -26,33 +26,32 @@ #include <gnuradio/fec/puncture_ff.h> namespace gr { - namespace fec { - - class FEC_API puncture_ff_impl : public puncture_ff - { - private: - int d_puncsize; - int d_delay; - int d_puncholes; - int d_puncpat; - - public: - puncture_ff_impl(int puncsize, int puncpat, int delay); - ~puncture_ff_impl(); - - //void catch_msg(pmt::pmt_t msg); - - int general_work(int noutput_items, - gr_vector_int& ninput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); - int fixed_rate_ninput_to_noutput(int ninput); - int fixed_rate_noutput_to_ninput(int noutput); - void forecast(int noutput_items, - gr_vector_int& ninput_items_required); - }; - - } /* namespace fec */ +namespace fec { + +class FEC_API puncture_ff_impl : public puncture_ff +{ +private: + int d_puncsize; + int d_delay; + int d_puncholes; + int d_puncpat; + +public: + puncture_ff_impl(int puncsize, int puncpat, int delay); + ~puncture_ff_impl(); + + // void catch_msg(pmt::pmt_t msg); + + int general_work(int noutput_items, + gr_vector_int& ninput_items, + gr_vector_const_void_star& input_items, + gr_vector_void_star& output_items); + int fixed_rate_ninput_to_noutput(int ninput); + int fixed_rate_noutput_to_ninput(int noutput); + void forecast(int noutput_items, gr_vector_int& ninput_items_required); +}; + +} /* namespace fec */ } /* namespace gr */ #endif /* INCLUDED_FEC_PUNCTURE_FF_IMPL_H */ diff --git a/gr-fec/lib/reed-solomon/ccsds.h b/gr-fec/lib/reed-solomon/ccsds.h index 0f2bde6186..52746f5835 100644 --- a/gr-fec/lib/reed-solomon/ccsds.h +++ b/gr-fec/lib/reed-solomon/ccsds.h @@ -1 +1 @@ -extern unsigned char Taltab[],Tal1tab[]; +extern unsigned char Taltab[], Tal1tab[]; diff --git a/gr-fec/lib/reed-solomon/char.h b/gr-fec/lib/reed-solomon/char.h index 4d3f22e5db..80435b633a 100644 --- a/gr-fec/lib/reed-solomon/char.h +++ b/gr-fec/lib/reed-solomon/char.h @@ -10,26 +10,27 @@ /* Reed-Solomon codec control block */ struct rs { - unsigned int mm; /* Bits per symbol */ - unsigned int nn; /* Symbols per block (= (1<<mm)-1) */ - unsigned char *alpha_to; /* log lookup table */ - unsigned char *index_of; /* Antilog lookup table */ - unsigned char *genpoly; /* Generator polynomial */ - unsigned int nroots; /* Number of generator roots = number of parity symbols */ - unsigned char fcr; /* First consecutive root, index form */ - unsigned char prim; /* Primitive element, index form */ - unsigned char iprim; /* prim-th root of 1, index form */ - int *modnn_table; /* modnn lookup table, 512 entries */ + unsigned int mm; /* Bits per symbol */ + unsigned int nn; /* Symbols per block (= (1<<mm)-1) */ + unsigned char* alpha_to; /* log lookup table */ + unsigned char* index_of; /* Antilog lookup table */ + unsigned char* genpoly; /* Generator polynomial */ + unsigned int nroots; /* Number of generator roots = number of parity symbols */ + unsigned char fcr; /* First consecutive root, index form */ + unsigned char prim; /* Primitive element, index form */ + unsigned char iprim; /* prim-th root of 1, index form */ + int* modnn_table; /* modnn lookup table, 512 entries */ }; -static inline unsigned int modnn(struct rs *rs, unsigned int x){ - while (x >= rs->nn) { - x -= rs->nn; - x = (x >> rs->mm) + (x & rs->nn); - } - return x; +static inline unsigned int modnn(struct rs* rs, unsigned int x) +{ + while (x >= rs->nn) { + x -= rs->nn; + x = (x >> rs->mm) + (x & rs->nn); + } + return x; } -#define MODNN(x) modnn(rs,x) +#define MODNN(x) modnn(rs, x) #define MM (rs->mm) #define NN (rs->nn) @@ -47,12 +48,11 @@ static inline unsigned int modnn(struct rs *rs, unsigned int x){ #define INIT_RS init_rs_char #define FREE_RS free_rs_char -FEC_API void ENCODE_RS(void *p,DTYPE *data,DTYPE *parity); -FEC_API int DECODE_RS(void *p,DTYPE *data,int *eras_pos,int no_eras); -FEC_API void *INIT_RS(unsigned int symsize,unsigned int gfpoly,unsigned int fcr, - unsigned int prim,unsigned int nroots); -FEC_API void FREE_RS(void *p); - - - - +FEC_API void ENCODE_RS(void* p, DTYPE* data, DTYPE* parity); +FEC_API int DECODE_RS(void* p, DTYPE* data, int* eras_pos, int no_eras); +FEC_API void* INIT_RS(unsigned int symsize, + unsigned int gfpoly, + unsigned int fcr, + unsigned int prim, + unsigned int nroots); +FEC_API void FREE_RS(void* p); diff --git a/gr-fec/lib/reed-solomon/decode_rs.c b/gr-fec/lib/reed-solomon/decode_rs.c index 9de22c87f5..df05527494 100644 --- a/gr-fec/lib/reed-solomon/decode_rs.c +++ b/gr-fec/lib/reed-solomon/decode_rs.c @@ -10,10 +10,10 @@ #include <string.h> #ifndef NULL -#define NULL ((void *)0) +#define NULL ((void*)0) #endif -#define min(a,b) ((a) < (b) ? (a) : (b)) +#define min(a, b) ((a) < (b) ? (a) : (b)) #ifdef FIXED #include "fixed.h" @@ -25,249 +25,254 @@ int DECODE_RS( #ifndef FIXED -void *p, + void* p, #endif -DTYPE *data, int *eras_pos, int no_eras){ + DTYPE* data, + int* eras_pos, + int no_eras) +{ #ifndef FIXED - struct rs *rs = (struct rs *)p; + struct rs* rs = (struct rs*)p; #endif - int deg_lambda, el, deg_omega; - int i, j, r, k; + int deg_lambda, el, deg_omega; + int i, j, r, k; #ifdef MAX_ARRAY - DTYPE u,q,tmp,num1,num2,den,discr_r; - DTYPE lambda[MAX_ARRAY], s[MAX_ARRAY]; /* Err+Eras Locator poly - * and syndrome poly */ - DTYPE b[MAX_ARRAY], t[MAX_ARRAY], omega[MAX_ARRAY]; - DTYPE root[MAX_ARRAY], reg[MAX_ARRAY], loc[MAX_ARRAY]; + DTYPE u, q, tmp, num1, num2, den, discr_r; + DTYPE lambda[MAX_ARRAY], s[MAX_ARRAY]; /* Err+Eras Locator poly + * and syndrome poly */ + DTYPE b[MAX_ARRAY], t[MAX_ARRAY], omega[MAX_ARRAY]; + DTYPE root[MAX_ARRAY], reg[MAX_ARRAY], loc[MAX_ARRAY]; #else - DTYPE u,q,tmp,num1,num2,den,discr_r; - DTYPE lambda[NROOTS+1], s[NROOTS]; /* Err+Eras Locator poly - * and syndrome poly */ - DTYPE b[NROOTS+1], t[NROOTS+1], omega[NROOTS+1]; - DTYPE root[NROOTS], reg[NROOTS+1], loc[NROOTS]; + DTYPE u, q, tmp, num1, num2, den, discr_r; + DTYPE lambda[NROOTS + 1], s[NROOTS]; /* Err+Eras Locator poly + * and syndrome poly */ + DTYPE b[NROOTS + 1], t[NROOTS + 1], omega[NROOTS + 1]; + DTYPE root[NROOTS], reg[NROOTS + 1], loc[NROOTS]; #endif - int syn_error, count; + int syn_error, count; - /* form the syndromes; i.e., evaluate data(x) at roots of g(x) */ - for(i=0;(unsigned int)i<NROOTS;i++) - s[i] = data[0]; + /* form the syndromes; i.e., evaluate data(x) at roots of g(x) */ + for (i = 0; (unsigned int)i < NROOTS; i++) + s[i] = data[0]; - for(j=1;(unsigned int)j<NN;j++){ - for(i=0;(unsigned int)i<NROOTS;i++){ - if(s[i] == 0){ - s[i] = data[j]; - } else { - s[i] = data[j] ^ ALPHA_TO[MODNN(INDEX_OF[s[i]] + (FCR+i)*PRIM)]; - } + for (j = 1; (unsigned int)j < NN; j++) { + for (i = 0; (unsigned int)i < NROOTS; i++) { + if (s[i] == 0) { + s[i] = data[j]; + } else { + s[i] = data[j] ^ ALPHA_TO[MODNN(INDEX_OF[s[i]] + (FCR + i) * PRIM)]; + } + } } - } - /* Convert syndromes to index form, checking for nonzero condition */ - syn_error = 0; - for(i=0;(unsigned int)i<NROOTS;i++){ - syn_error |= s[i]; - s[i] = INDEX_OF[s[i]]; - } - - if (!syn_error) { - /* if syndrome is zero, data[] is a codeword and there are no - * errors to correct. So return data[] unmodified - */ - count = 0; - goto finish; - } - memset(&lambda[1],0,NROOTS*sizeof(lambda[0])); - lambda[0] = 1; + /* Convert syndromes to index form, checking for nonzero condition */ + syn_error = 0; + for (i = 0; (unsigned int)i < NROOTS; i++) { + syn_error |= s[i]; + s[i] = INDEX_OF[s[i]]; + } - if (no_eras > 0) { - /* Init lambda to be the erasure locator polynomial */ - lambda[1] = ALPHA_TO[MODNN(PRIM*(NN-1-eras_pos[0]))]; - for (i = 1; i < no_eras; i++) { - u = MODNN(PRIM*(NN-1-eras_pos[i])); - for (j = i+1; j > 0; j--) { - tmp = INDEX_OF[lambda[j - 1]]; - if(tmp != A0) - lambda[j] ^= ALPHA_TO[MODNN(u + tmp)]; - } + if (!syn_error) { + /* if syndrome is zero, data[] is a codeword and there are no + * errors to correct. So return data[] unmodified + */ + count = 0; + goto finish; } + memset(&lambda[1], 0, NROOTS * sizeof(lambda[0])); + lambda[0] = 1; + + if (no_eras > 0) { + /* Init lambda to be the erasure locator polynomial */ + lambda[1] = ALPHA_TO[MODNN(PRIM * (NN - 1 - eras_pos[0]))]; + for (i = 1; i < no_eras; i++) { + u = MODNN(PRIM * (NN - 1 - eras_pos[i])); + for (j = i + 1; j > 0; j--) { + tmp = INDEX_OF[lambda[j - 1]]; + if (tmp != A0) + lambda[j] ^= ALPHA_TO[MODNN(u + tmp)]; + } + } #if DEBUG >= 1 - /* Test code that verifies the erasure locator polynomial just constructed - Needed only for decoder debugging. */ + /* Test code that verifies the erasure locator polynomial just constructed + Needed only for decoder debugging. */ - /* find roots of the erasure location polynomial */ - for(i=1;i<=no_eras;i++) - reg[i] = INDEX_OF[lambda[i]]; + /* find roots of the erasure location polynomial */ + for (i = 1; i <= no_eras; i++) + reg[i] = INDEX_OF[lambda[i]]; - count = 0; - for (i = 1,k=IPRIM-1; i <= NN; i++,k = MODNN(k+IPRIM)) { - q = 1; - for (j = 1; j <= no_eras; j++) - if (reg[j] != A0) { - reg[j] = MODNN(reg[j] + j); - q ^= ALPHA_TO[reg[j]]; - } - if (q != 0) - continue; - /* store root and error location number indices */ - root[count] = i; - loc[count] = k; - count++; - } - if (count != no_eras) { - printf("count = %d no_eras = %d\n lambda(x) is WRONG\n",count,no_eras); - count = -1; - goto finish; - } + count = 0; + for (i = 1, k = IPRIM - 1; i <= NN; i++, k = MODNN(k + IPRIM)) { + q = 1; + for (j = 1; j <= no_eras; j++) + if (reg[j] != A0) { + reg[j] = MODNN(reg[j] + j); + q ^= ALPHA_TO[reg[j]]; + } + if (q != 0) + continue; + /* store root and error location number indices */ + root[count] = i; + loc[count] = k; + count++; + } + if (count != no_eras) { + printf("count = %d no_eras = %d\n lambda(x) is WRONG\n", count, no_eras); + count = -1; + goto finish; + } #if DEBUG >= 2 - printf("\n Erasure positions as determined by roots of Eras Loc Poly:\n"); - for (i = 0; i < count; i++) - printf("%d ", loc[i]); - printf("\n"); + printf("\n Erasure positions as determined by roots of Eras Loc Poly:\n"); + for (i = 0; i < count; i++) + printf("%d ", loc[i]); + printf("\n"); #endif #endif - } - for(i=0;(unsigned int)i<NROOTS+1;i++) - b[i] = INDEX_OF[lambda[i]]; - - /* - * Begin Berlekamp-Massey algorithm to determine error+erasure - * locator polynomial - */ - r = no_eras; - el = no_eras; - while ((unsigned int)(++r) <= NROOTS) { /* r is the step number */ - /* Compute discrepancy at the r-th step in poly-form */ - discr_r = 0; - for (i = 0; i < r; i++){ - if ((lambda[i] != 0) && (s[r-i-1] != A0)) { - discr_r ^= ALPHA_TO[MODNN(INDEX_OF[lambda[i]] + s[r-i-1])]; - } } - discr_r = INDEX_OF[discr_r]; /* Index form */ - if (discr_r == A0) { - /* 2 lines below: B(x) <-- x*B(x) */ - memmove(&b[1],b,NROOTS*sizeof(b[0])); - b[0] = A0; - } else { - /* 7 lines below: T(x) <-- lambda(x) - discr_r*x*b(x) */ - t[0] = lambda[0]; - for (i = 0 ; (unsigned int)i < NROOTS; i++) { - if(b[i] != A0) - t[i+1] = lambda[i+1] ^ ALPHA_TO[MODNN(discr_r + b[i])]; - else - t[i+1] = lambda[i+1]; - } - if (2 * el <= r + no_eras - 1) { - el = r + no_eras - el; - /* - * 2 lines below: B(x) <-- inv(discr_r) * - * lambda(x) - */ - for (i = 0; (unsigned int)i <= NROOTS; i++) - b[i] = (lambda[i] == 0) ? A0 : MODNN(INDEX_OF[lambda[i]] - discr_r + NN); - } else { - /* 2 lines below: B(x) <-- x*B(x) */ - memmove(&b[1],b,NROOTS*sizeof(b[0])); - b[0] = A0; - } - memcpy(lambda,t,(NROOTS+1)*sizeof(t[0])); + for (i = 0; (unsigned int)i < NROOTS + 1; i++) + b[i] = INDEX_OF[lambda[i]]; + + /* + * Begin Berlekamp-Massey algorithm to determine error+erasure + * locator polynomial + */ + r = no_eras; + el = no_eras; + while ((unsigned int)(++r) <= NROOTS) { /* r is the step number */ + /* Compute discrepancy at the r-th step in poly-form */ + discr_r = 0; + for (i = 0; i < r; i++) { + if ((lambda[i] != 0) && (s[r - i - 1] != A0)) { + discr_r ^= ALPHA_TO[MODNN(INDEX_OF[lambda[i]] + s[r - i - 1])]; + } + } + discr_r = INDEX_OF[discr_r]; /* Index form */ + if (discr_r == A0) { + /* 2 lines below: B(x) <-- x*B(x) */ + memmove(&b[1], b, NROOTS * sizeof(b[0])); + b[0] = A0; + } else { + /* 7 lines below: T(x) <-- lambda(x) - discr_r*x*b(x) */ + t[0] = lambda[0]; + for (i = 0; (unsigned int)i < NROOTS; i++) { + if (b[i] != A0) + t[i + 1] = lambda[i + 1] ^ ALPHA_TO[MODNN(discr_r + b[i])]; + else + t[i + 1] = lambda[i + 1]; + } + if (2 * el <= r + no_eras - 1) { + el = r + no_eras - el; + /* + * 2 lines below: B(x) <-- inv(discr_r) * + * lambda(x) + */ + for (i = 0; (unsigned int)i <= NROOTS; i++) + b[i] = + (lambda[i] == 0) ? A0 : MODNN(INDEX_OF[lambda[i]] - discr_r + NN); + } else { + /* 2 lines below: B(x) <-- x*B(x) */ + memmove(&b[1], b, NROOTS * sizeof(b[0])); + b[0] = A0; + } + memcpy(lambda, t, (NROOTS + 1) * sizeof(t[0])); + } } - } - /* Convert lambda to index form and compute deg(lambda(x)) */ - deg_lambda = 0; - for(i=0;(unsigned int)i<NROOTS+1;i++){ - lambda[i] = INDEX_OF[lambda[i]]; - if(lambda[i] != A0) - deg_lambda = i; - } - /* Find roots of the error+erasure locator polynomial by Chien search */ - memcpy(®[1],&lambda[1],NROOTS*sizeof(reg[0])); - count = 0; /* Number of roots of lambda(x) */ - for (i = 1,k=IPRIM-1; (unsigned int)i <= NN; i++,k = MODNN(k+IPRIM)) { - q = 1; /* lambda[0] is always 0 */ - for (j = deg_lambda; j > 0; j--){ - if (reg[j] != A0) { - reg[j] = MODNN(reg[j] + j); - q ^= ALPHA_TO[reg[j]]; - } + /* Convert lambda to index form and compute deg(lambda(x)) */ + deg_lambda = 0; + for (i = 0; (unsigned int)i < NROOTS + 1; i++) { + lambda[i] = INDEX_OF[lambda[i]]; + if (lambda[i] != A0) + deg_lambda = i; } - if (q != 0) - continue; /* Not a root */ - /* store root (index-form) and error location number */ -#if DEBUG>=2 - printf("count %d root %d loc %d\n",count,i,k); + /* Find roots of the error+erasure locator polynomial by Chien search */ + memcpy(®[1], &lambda[1], NROOTS * sizeof(reg[0])); + count = 0; /* Number of roots of lambda(x) */ + for (i = 1, k = IPRIM - 1; (unsigned int)i <= NN; i++, k = MODNN(k + IPRIM)) { + q = 1; /* lambda[0] is always 0 */ + for (j = deg_lambda; j > 0; j--) { + if (reg[j] != A0) { + reg[j] = MODNN(reg[j] + j); + q ^= ALPHA_TO[reg[j]]; + } + } + if (q != 0) + continue; /* Not a root */ + /* store root (index-form) and error location number */ +#if DEBUG >= 2 + printf("count %d root %d loc %d\n", count, i, k); #endif - root[count] = i; - loc[count] = k; - /* If we've already found max possible roots, - * abort the search to save time - */ - if(++count == deg_lambda) - break; - } - if (deg_lambda != count) { + root[count] = i; + loc[count] = k; + /* If we've already found max possible roots, + * abort the search to save time + */ + if (++count == deg_lambda) + break; + } + if (deg_lambda != count) { + /* + * deg(lambda) unequal to number of roots => uncorrectable + * error detected + */ + count = -1; + goto finish; + } /* - * deg(lambda) unequal to number of roots => uncorrectable - * error detected + * Compute err+eras evaluator poly omega(x) = s(x)*lambda(x) (modulo + * x**NROOTS). in index form. Also find deg(omega). */ - count = -1; - goto finish; - } - /* - * Compute err+eras evaluator poly omega(x) = s(x)*lambda(x) (modulo - * x**NROOTS). in index form. Also find deg(omega). - */ - deg_omega = 0; - for (i = 0; (unsigned int)i < NROOTS;i++){ - tmp = 0; - j = (deg_lambda < i) ? deg_lambda : i; - for(;j >= 0; j--){ - if ((s[i - j] != A0) && (lambda[j] != A0)) - tmp ^= ALPHA_TO[MODNN(s[i - j] + lambda[j])]; + deg_omega = 0; + for (i = 0; (unsigned int)i < NROOTS; i++) { + tmp = 0; + j = (deg_lambda < i) ? deg_lambda : i; + for (; j >= 0; j--) { + if ((s[i - j] != A0) && (lambda[j] != A0)) + tmp ^= ALPHA_TO[MODNN(s[i - j] + lambda[j])]; + } + if (tmp != 0) + deg_omega = i; + omega[i] = INDEX_OF[tmp]; } - if(tmp != 0) - deg_omega = i; - omega[i] = INDEX_OF[tmp]; - } - omega[NROOTS] = A0; + omega[NROOTS] = A0; - /* - * Compute error values in poly-form. num1 = omega(inv(X(l))), num2 = - * inv(X(l))**(FCR-1) and den = lambda_pr(inv(X(l))) all in poly-form - */ - for (j = count-1; j >=0; j--) { - num1 = 0; - for (i = deg_omega; i >= 0; i--) { - if (omega[i] != A0) - num1 ^= ALPHA_TO[MODNN(omega[i] + i * root[j])]; - } - num2 = ALPHA_TO[MODNN(root[j] * (FCR - 1) + NN)]; - den = 0; + /* + * Compute error values in poly-form. num1 = omega(inv(X(l))), num2 = + * inv(X(l))**(FCR-1) and den = lambda_pr(inv(X(l))) all in poly-form + */ + for (j = count - 1; j >= 0; j--) { + num1 = 0; + for (i = deg_omega; i >= 0; i--) { + if (omega[i] != A0) + num1 ^= ALPHA_TO[MODNN(omega[i] + i * root[j])]; + } + num2 = ALPHA_TO[MODNN(root[j] * (FCR - 1) + NN)]; + den = 0; - /* lambda[i+1] for i even is the formal derivative lambda_pr of lambda[i] */ - for (i = (int)min((unsigned int)deg_lambda,NROOTS-1) & ~1; i >= 0; i -=2) { - if(lambda[i+1] != A0) - den ^= ALPHA_TO[MODNN(lambda[i+1] + i * root[j])]; - } - if (den == 0) { + /* lambda[i+1] for i even is the formal derivative lambda_pr of lambda[i] */ + for (i = (int)min((unsigned int)deg_lambda, NROOTS - 1) & ~1; i >= 0; i -= 2) { + if (lambda[i + 1] != A0) + den ^= ALPHA_TO[MODNN(lambda[i + 1] + i * root[j])]; + } + if (den == 0) { #if DEBUG >= 1 - printf("\n ERROR: denominator = 0\n"); + printf("\n ERROR: denominator = 0\n"); #endif - count = -1; - goto finish; + count = -1; + goto finish; + } + /* Apply error to data */ + if (num1 != 0) { + data[loc[j]] ^= + ALPHA_TO[MODNN(INDEX_OF[num1] + INDEX_OF[num2] + NN - INDEX_OF[den])]; + } } - /* Apply error to data */ - if (num1 != 0) { - data[loc[j]] ^= ALPHA_TO[MODNN(INDEX_OF[num1] + INDEX_OF[num2] + NN - INDEX_OF[den])]; +finish: + if (eras_pos != NULL) { + for (i = 0; i < count; i++) + eras_pos[i] = loc[i]; } - } - finish: - if(eras_pos != NULL){ - for(i=0;i<count;i++) - eras_pos[i] = loc[i]; - } - return count; + return count; } diff --git a/gr-fec/lib/reed-solomon/decode_rs_ccsds.c b/gr-fec/lib/reed-solomon/decode_rs_ccsds.c index 2543d3a640..e842bfaf84 100644 --- a/gr-fec/lib/reed-solomon/decode_rs_ccsds.c +++ b/gr-fec/lib/reed-solomon/decode_rs_ccsds.c @@ -8,20 +8,21 @@ #include "fixed.h" #include "ccsds.h" -int decode_rs_ccsds(unsigned char *data,int *eras_pos,int no_eras){ - int i,r; - unsigned char cdata[NN]; +int decode_rs_ccsds(unsigned char* data, int* eras_pos, int no_eras) +{ + int i, r; + unsigned char cdata[NN]; - /* Convert data from dual basis to conventional */ - for(i=0;i<NN;i++) - cdata[i] = Tal1tab[data[i]]; + /* Convert data from dual basis to conventional */ + for (i = 0; i < NN; i++) + cdata[i] = Tal1tab[data[i]]; - r = decode_rs_8(cdata,eras_pos,no_eras); + r = decode_rs_8(cdata, eras_pos, no_eras); - if(r > 0){ - /* Convert from conventional to dual basis */ - for(i=0;i<NN;i++) - data[i] = Taltab[cdata[i]]; - } - return r; + if (r > 0) { + /* Convert from conventional to dual basis */ + for (i = 0; i < NN; i++) + data[i] = Taltab[cdata[i]]; + } + return r; } diff --git a/gr-fec/lib/reed-solomon/encode_rs.c b/gr-fec/lib/reed-solomon/encode_rs.c index 992aa3f4df..2cadee1ca9 100644 --- a/gr-fec/lib/reed-solomon/encode_rs.c +++ b/gr-fec/lib/reed-solomon/encode_rs.c @@ -14,48 +14,50 @@ void ENCODE_RS( #ifndef FIXED -void *p, + void* p, #endif -DTYPE *data, DTYPE *bb){ + DTYPE* data, + DTYPE* bb) +{ #ifndef FIXED - struct rs *rs = (struct rs *)p; + struct rs* rs = (struct rs*)p; #endif - unsigned int i, j; - DTYPE feedback; + unsigned int i, j; + DTYPE feedback; - memset(bb,0,NROOTS*sizeof(DTYPE)); + memset(bb, 0, NROOTS * sizeof(DTYPE)); - for(i=0;i<NN-NROOTS;i++){ - feedback = INDEX_OF[data[i] ^ bb[0]]; - if(feedback != A0){ /* feedback term is non-zero */ + for (i = 0; i < NN - NROOTS; i++) { + feedback = INDEX_OF[data[i] ^ bb[0]]; + if (feedback != A0) { /* feedback term is non-zero */ #ifdef UNNORMALIZED - /* This line is unnecessary when GENPOLY[NROOTS] is unity, as it must - * always be for the polynomials constructed by init_rs() - */ - feedback = MODNN(NN - GENPOLY[NROOTS] + feedback); + /* This line is unnecessary when GENPOLY[NROOTS] is unity, as it must + * always be for the polynomials constructed by init_rs() + */ + feedback = MODNN(NN - GENPOLY[NROOTS] + feedback); #endif - for(j=1;j<NROOTS;j++) + for (j = 1; j < NROOTS; j++) #ifdef FIXED - bb[j] ^= ALPHA_TO[MODNN(feedback + GENPOLY[NROOTS-j])]; + bb[j] ^= ALPHA_TO[MODNN(feedback + GENPOLY[NROOTS - j])]; #elif defined(BIGSYM) - // Same as above; keeping as a separate line in case these change. - bb[j] ^= ALPHA_TO[MODNN(feedback + GENPOLY[NROOTS-j])]; + // Same as above; keeping as a separate line in case these change. + bb[j] ^= ALPHA_TO[MODNN(feedback + GENPOLY[NROOTS - j])]; #else - bb[j] ^= ALPHA_TO[rs->modnn_table[feedback + GENPOLY[NROOTS-j]]]; + bb[j] ^= ALPHA_TO[rs->modnn_table[feedback + GENPOLY[NROOTS - j]]]; #endif - } - /* Shift */ - memmove(&bb[0],&bb[1],sizeof(DTYPE)*(NROOTS-1)); - if(feedback != A0) + } + /* Shift */ + memmove(&bb[0], &bb[1], sizeof(DTYPE) * (NROOTS - 1)); + if (feedback != A0) #ifdef FIXED - bb[NROOTS-1] = ALPHA_TO[MODNN(feedback + GENPOLY[0])]; + bb[NROOTS - 1] = ALPHA_TO[MODNN(feedback + GENPOLY[0])]; #elif defined(BIGSYM) - // Same as above; keeping as a separate line in case these change. - bb[NROOTS-1] = ALPHA_TO[MODNN(feedback + GENPOLY[0])]; + // Same as above; keeping as a separate line in case these change. + bb[NROOTS - 1] = ALPHA_TO[MODNN(feedback + GENPOLY[0])]; #else - bb[NROOTS-1] = ALPHA_TO[rs->modnn_table[feedback + GENPOLY[0]]]; + bb[NROOTS - 1] = ALPHA_TO[rs->modnn_table[feedback + GENPOLY[0]]]; #endif - else - bb[NROOTS-1] = 0; - } + else + bb[NROOTS - 1] = 0; + } } diff --git a/gr-fec/lib/reed-solomon/encode_rs_ccsds.c b/gr-fec/lib/reed-solomon/encode_rs_ccsds.c index a748b34689..aae16ae37d 100644 --- a/gr-fec/lib/reed-solomon/encode_rs_ccsds.c +++ b/gr-fec/lib/reed-solomon/encode_rs_ccsds.c @@ -8,17 +8,18 @@ #include "fixed.h" #include "ccsds.h" -void encode_rs_ccsds(unsigned char *data,unsigned char *parity){ - int i; - unsigned char cdata[NN-NROOTS]; +void encode_rs_ccsds(unsigned char* data, unsigned char* parity) +{ + int i; + unsigned char cdata[NN - NROOTS]; - /* Convert data from dual basis to conventional */ - for(i=0;i<NN-NROOTS;i++) - cdata[i] = Tal1tab[data[i]]; + /* Convert data from dual basis to conventional */ + for (i = 0; i < NN - NROOTS; i++) + cdata[i] = Tal1tab[data[i]]; - encode_rs_8(cdata,parity); + encode_rs_8(cdata, parity); - /* Convert parity from conventional to dual basis */ - for(i=0;i<NN-NROOTS;i++) - parity[i] = Taltab[parity[i]]; + /* Convert parity from conventional to dual basis */ + for (i = 0; i < NN - NROOTS; i++) + parity[i] = Taltab[parity[i]]; } diff --git a/gr-fec/lib/reed-solomon/exercise.c b/gr-fec/lib/reed-solomon/exercise.c index 41ed4f2148..562a051f17 100644 --- a/gr-fec/lib/reed-solomon/exercise.c +++ b/gr-fec/lib/reed-solomon/exercise.c @@ -34,101 +34,103 @@ #elif defined(CCSDS) #define PRINTPARM printf("CCSDS (255,223):"); #else -#define PRINTPARM printf("(%d,%d):",rs->nn,rs->nn-rs->nroots); +#define PRINTPARM printf("(%d,%d):", rs->nn, rs->nn - rs->nroots); #endif /* Exercise the RS codec passed as an argument */ int EXERCISE( #if !defined(CCSDS) && !defined(FIXED) -void *p, + void* p, #endif -int trials){ + int trials) +{ #if !defined(CCSDS) && !defined(FIXED) - struct rs *rs = (struct rs *)p; + struct rs* rs = (struct rs*)p; #endif #if MAX_ARRAY - DTYPE block[MAX_ARRAY],tblock[MAX_ARRAY]; - unsigned int i; - int errors; - int errlocs[MAX_ARRAY]; - int derrlocs[MAX_ARRAY]; + DTYPE block[MAX_ARRAY], tblock[MAX_ARRAY]; + unsigned int i; + int errors; + int errlocs[MAX_ARRAY]; + int derrlocs[MAX_ARRAY]; #else - DTYPE block[NN],tblock[NN]; - unsigned int i; - int errors; - int errlocs[NN]; - int derrlocs[NROOTS]; + DTYPE block[NN], tblock[NN]; + unsigned int i; + int errors; + int errlocs[NN]; + int derrlocs[NROOTS]; #endif - int derrors; - int errval,errloc; - int erasures; - int decoder_errors = 0; + int derrors; + int errval, errloc; + int erasures; + int decoder_errors = 0; - while(trials-- != 0){ - /* Test up to the error correction capacity of the code */ - for(errors=0;(unsigned int)errors <= NROOTS/2;errors++){ + while (trials-- != 0) { + /* Test up to the error correction capacity of the code */ + for (errors = 0; (unsigned int)errors <= NROOTS / 2; errors++) { - /* Load block with random data and encode */ - for(i=0;i<NN-NROOTS;i++) - block[i] = rand() & NN; + /* Load block with random data and encode */ + for (i = 0; i < NN - NROOTS; i++) + block[i] = rand() & NN; #if defined(CCSDS) || defined(FIXED) - ENCODE_RS(&block[0],&block[NN-NROOTS]); + ENCODE_RS(&block[0], &block[NN - NROOTS]); #else - ENCODE_RS(rs,&block[0],&block[NN-NROOTS]); + ENCODE_RS(rs, &block[0], &block[NN - NROOTS]); #endif - /* Make temp copy, seed with errors */ - memcpy(tblock,block,sizeof(tblock)); - memset(errlocs,0,sizeof(errlocs)); - memset(derrlocs,0,sizeof(derrlocs)); - erasures=0; - for(i=0;i<(unsigned int)errors;i++){ - do { - errval = rand() & NN; - } while(errval == 0); /* Error value must be nonzero */ + /* Make temp copy, seed with errors */ + memcpy(tblock, block, sizeof(tblock)); + memset(errlocs, 0, sizeof(errlocs)); + memset(derrlocs, 0, sizeof(derrlocs)); + erasures = 0; + for (i = 0; i < (unsigned int)errors; i++) { + do { + errval = rand() & NN; + } while (errval == 0); /* Error value must be nonzero */ - do { - errloc = rand() % NN; - } while(errlocs[errloc] != 0); /* Must not choose the same location twice */ + do { + errloc = rand() % NN; + } while (errlocs[errloc] != + 0); /* Must not choose the same location twice */ - errlocs[errloc] = 1; + errlocs[errloc] = 1; #if FLAG_ERASURE - if(rand() & 1) /* 50-50 chance */ - derrlocs[erasures++] = errloc; + if (rand() & 1) /* 50-50 chance */ + derrlocs[erasures++] = errloc; #endif - tblock[errloc] ^= errval; - } + tblock[errloc] ^= errval; + } - /* Decode the errored block */ + /* Decode the errored block */ #if defined(CCSDS) || defined(FIXED) - derrors = DECODE_RS(tblock,derrlocs,erasures); + derrors = DECODE_RS(tblock, derrlocs, erasures); #else - derrors = DECODE_RS(rs,tblock,derrlocs,erasures); + derrors = DECODE_RS(rs, tblock, derrlocs, erasures); #endif - if(derrors != errors){ - PRINTPARM - printf(" decoder says %d errors, true number is %d\n",derrors,errors); - decoder_errors++; - } - for(i=0;i<(unsigned int)derrors;i++){ - if(errlocs[derrlocs[i]] == 0){ - PRINTPARM - printf(" decoder indicates error in location %d without error\n",i); - decoder_errors++; - } - } - if(memcmp(tblock,block,sizeof(tblock)) != 0){ - PRINTPARM - printf(" uncorrected errors! output ^ input:"); - decoder_errors++; - for(i=0;i<NN;i++) - printf(" %02x",tblock[i] ^ block[i]); - printf("\n"); - } + if (derrors != errors) { + PRINTPARM + printf(" decoder says %d errors, true number is %d\n", derrors, errors); + decoder_errors++; + } + for (i = 0; i < (unsigned int)derrors; i++) { + if (errlocs[derrlocs[i]] == 0) { + PRINTPARM + printf(" decoder indicates error in location %d without error\n", i); + decoder_errors++; + } + } + if (memcmp(tblock, block, sizeof(tblock)) != 0) { + PRINTPARM + printf(" uncorrected errors! output ^ input:"); + decoder_errors++; + for (i = 0; i < NN; i++) + printf(" %02x", tblock[i] ^ block[i]); + printf("\n"); + } + } } - } - return decoder_errors; + return decoder_errors; } diff --git a/gr-fec/lib/reed-solomon/fixed.h b/gr-fec/lib/reed-solomon/fixed.h index d45f4d47b5..feb3105b0f 100644 --- a/gr-fec/lib/reed-solomon/fixed.h +++ b/gr-fec/lib/reed-solomon/fixed.h @@ -9,12 +9,13 @@ #include <gnuradio/fec/api.h> -static inline int mod255(int x){ - while (x >= 255) { - x -= 255; - x = (x >> 8) + (x & 255); - } - return x; +static inline int mod255(int x) +{ + while (x >= 255) { + x -= 255; + x = (x >> 8) + (x & 255); + } + return x; } #define MODNN(x) mod255(x) @@ -36,5 +37,5 @@ extern unsigned char CCSDS_poly[]; #define ENCODE_RS encode_rs_8 #define DECODE_RS decode_rs_8 -FEC_API void ENCODE_RS(DTYPE *data,DTYPE *parity); -FEC_API int DECODE_RS(DTYPE *data, int *eras_pos, int no_eras);
\ No newline at end of file +FEC_API void ENCODE_RS(DTYPE* data, DTYPE* parity); +FEC_API int DECODE_RS(DTYPE* data, int* eras_pos, int no_eras);
\ No newline at end of file diff --git a/gr-fec/lib/reed-solomon/gen_ccsds.c b/gr-fec/lib/reed-solomon/gen_ccsds.c index 1e4e4f5363..a069834346 100644 --- a/gr-fec/lib/reed-solomon/gen_ccsds.c +++ b/gr-fec/lib/reed-solomon/gen_ccsds.c @@ -5,30 +5,31 @@ #include <stdio.h> #include "char.h" -int main(){ - struct rs *rs; - int i; +int main() +{ + struct rs* rs; + int i; - rs = init_rs_char(8,0x187,112,11,32); /* CCSDS standard */ - printf("unsigned char CCSDS_alpha_to[] = {"); - for(i=0;i<256;i++){ - if((i % 16) == 0) - printf("\n"); - printf("0x%02x,",rs->alpha_to[i]); - } - printf("\n};\n\nunsigned char CCSDS_index_of[] = {"); - for(i=0;i<256;i++){ - if((i % 16) == 0) - printf("\n"); - printf("%3d,",rs->index_of[i]); - } - printf("\n};\n\nunsigned char CCSDS_poly[] = {"); - for(i=0;i<33;i++){ - if((i % 16) == 0) - printf("\n"); + rs = init_rs_char(8, 0x187, 112, 11, 32); /* CCSDS standard */ + printf("unsigned char CCSDS_alpha_to[] = {"); + for (i = 0; i < 256; i++) { + if ((i % 16) == 0) + printf("\n"); + printf("0x%02x,", rs->alpha_to[i]); + } + printf("\n};\n\nunsigned char CCSDS_index_of[] = {"); + for (i = 0; i < 256; i++) { + if ((i % 16) == 0) + printf("\n"); + printf("%3d,", rs->index_of[i]); + } + printf("\n};\n\nunsigned char CCSDS_poly[] = {"); + for (i = 0; i < 33; i++) { + if ((i % 16) == 0) + printf("\n"); - printf("%3d,",rs->genpoly[i]); - } - printf("\n};\n"); - exit(0); + printf("%3d,", rs->genpoly[i]); + } + printf("\n};\n"); + exit(0); } diff --git a/gr-fec/lib/reed-solomon/gen_ccsds_tal.c b/gr-fec/lib/reed-solomon/gen_ccsds_tal.c index 9dde18917b..9db195d79c 100644 --- a/gr-fec/lib/reed-solomon/gen_ccsds_tal.c +++ b/gr-fec/lib/reed-solomon/gen_ccsds_tal.c @@ -11,7 +11,7 @@ * May be used under the terms of the GNU General Public License (GPL) */ #include <stdio.h> -unsigned char Taltab[256],Tal1tab[256]; +unsigned char Taltab[256], Tal1tab[256]; static unsigned char tal[] = { 0x8d, 0xef, 0xec, 0x86, 0xfa, 0x99, 0xaf, 0x7b }; @@ -20,31 +20,31 @@ static unsigned char tal[] = { 0x8d, 0xef, 0xec, 0x86, 0xfa, 0x99, 0xaf, 0x7b }; * and Berlekamp's dual basis representation * (l0, l1, ...l7) */ -int main(){ - int i,j,k; +int main() +{ + int i, j, k; - for(i=0;i<256;i++){/* For each value of input */ - Taltab[i] = 0; - for(j=0;j<8;j++) /* for each column of matrix */ - for(k=0;k<8;k++){ /* for each row of matrix */ - if(i & (1<<k)) - Taltab[i] ^= tal[7-k] & (1<<j); - } - Tal1tab[Taltab[i]] = i; - } - printf("unsigned char Taltab[] = {\n"); - for(i=0;i<256;i++){ - if((i % 16) == 0) - printf("\n"); - printf("0x%02x,",Taltab[i]); - } - printf("\n};\n\nunsigned char Tal1tab[] = {"); - for(i=0;i<256;i++){ - if((i % 16) == 0) - printf("\n"); - printf("0x%02x,",Tal1tab[i]); - } - printf("\n};\n"); - exit(0); + for (i = 0; i < 256; i++) { /* For each value of input */ + Taltab[i] = 0; + for (j = 0; j < 8; j++) /* for each column of matrix */ + for (k = 0; k < 8; k++) { /* for each row of matrix */ + if (i & (1 << k)) + Taltab[i] ^= tal[7 - k] & (1 << j); + } + Tal1tab[Taltab[i]] = i; + } + printf("unsigned char Taltab[] = {\n"); + for (i = 0; i < 256; i++) { + if ((i % 16) == 0) + printf("\n"); + printf("0x%02x,", Taltab[i]); + } + printf("\n};\n\nunsigned char Tal1tab[] = {"); + for (i = 0; i < 256; i++) { + if ((i % 16) == 0) + printf("\n"); + printf("0x%02x,", Tal1tab[i]); + } + printf("\n};\n"); + exit(0); } - diff --git a/gr-fec/lib/reed-solomon/init_rs.c b/gr-fec/lib/reed-solomon/init_rs.c index c3d8921616..b71992ab36 100644 --- a/gr-fec/lib/reed-solomon/init_rs.c +++ b/gr-fec/lib/reed-solomon/init_rs.c @@ -14,21 +14,22 @@ #endif #ifndef NULL -#define NULL ((void *)0) +#define NULL ((void*)0) #endif -void FREE_RS(void *p){ - struct rs *rs = (struct rs *)p; +void FREE_RS(void* p) +{ + struct rs* rs = (struct rs*)p; - free(rs->alpha_to); - free(rs->index_of); - free(rs->genpoly); + free(rs->alpha_to); + free(rs->index_of); + free(rs->genpoly); #ifdef FIXED #elif defined(BIGSYM) #else - free(rs->modnn_table); + free(rs->modnn_table); #endif - free(rs); + free(rs); } /* Initialize a Reed-Solomon codec @@ -38,109 +39,115 @@ void FREE_RS(void *p){ * prim = primitive element to generate polynomial roots * nroots = RS code generator polynomial degree (number of roots) */ -void *INIT_RS(unsigned int symsize,unsigned int gfpoly,unsigned fcr,unsigned prim, - unsigned int nroots){ - struct rs *rs; - int sr,root,iprim; - unsigned int i, j; - - if(symsize > 8*sizeof(DTYPE)) - return NULL; /* Need version with ints rather than chars */ - - if(fcr >= (1u<<symsize)) - return NULL; - if(prim == 0 || prim >= (1u<<symsize)) - return NULL; - if(nroots >= (1u<<symsize)) - return NULL; /* Can't have more roots than symbol values! */ - - rs = (struct rs *)calloc(1,sizeof(struct rs)); - rs->mm = symsize; - rs->nn = (1<<symsize)-1; - - rs->alpha_to = (DTYPE *)malloc(sizeof(DTYPE)*(rs->nn+1)); - if(rs->alpha_to == NULL){ - free(rs); - return NULL; - } - rs->index_of = (DTYPE *)malloc(sizeof(DTYPE)*(rs->nn+1)); - if(rs->index_of == NULL){ - free(rs->alpha_to); - free(rs); - return NULL; - } +void* INIT_RS(unsigned int symsize, + unsigned int gfpoly, + unsigned fcr, + unsigned prim, + unsigned int nroots) +{ + struct rs* rs; + int sr, root, iprim; + unsigned int i, j; + + if (symsize > 8 * sizeof(DTYPE)) + return NULL; /* Need version with ints rather than chars */ + + if (fcr >= (1u << symsize)) + return NULL; + if (prim == 0 || prim >= (1u << symsize)) + return NULL; + if (nroots >= (1u << symsize)) + return NULL; /* Can't have more roots than symbol values! */ + + rs = (struct rs*)calloc(1, sizeof(struct rs)); + rs->mm = symsize; + rs->nn = (1 << symsize) - 1; + + rs->alpha_to = (DTYPE*)malloc(sizeof(DTYPE) * (rs->nn + 1)); + if (rs->alpha_to == NULL) { + free(rs); + return NULL; + } + rs->index_of = (DTYPE*)malloc(sizeof(DTYPE) * (rs->nn + 1)); + if (rs->index_of == NULL) { + free(rs->alpha_to); + free(rs); + return NULL; + } - /* Generate Galois field lookup tables */ - rs->index_of[0] = A0; /* log(zero) = -inf */ - rs->alpha_to[A0] = 0; /* alpha**-inf = 0 */ - sr = 1; - for(i=0;i<rs->nn;i++){ - rs->index_of[sr] = i; - rs->alpha_to[i] = sr; - sr <<= 1; - if(sr & (1<<symsize)) - sr ^= gfpoly; - sr &= rs->nn; - } - if(sr != 1){ - /* field generator polynomial is not primitive! */ - free(rs->alpha_to); - free(rs->index_of); - free(rs); - return NULL; - } + /* Generate Galois field lookup tables */ + rs->index_of[0] = A0; /* log(zero) = -inf */ + rs->alpha_to[A0] = 0; /* alpha**-inf = 0 */ + sr = 1; + for (i = 0; i < rs->nn; i++) { + rs->index_of[sr] = i; + rs->alpha_to[i] = sr; + sr <<= 1; + if (sr & (1 << symsize)) + sr ^= gfpoly; + sr &= rs->nn; + } + if (sr != 1) { + /* field generator polynomial is not primitive! */ + free(rs->alpha_to); + free(rs->index_of); + free(rs); + return NULL; + } - /* Form RS code generator polynomial from its roots */ - rs->genpoly = (DTYPE *)malloc(sizeof(DTYPE)*(nroots+1)); - if(rs->genpoly == NULL){ - free(rs->alpha_to); - free(rs->index_of); - free(rs); - return NULL; - } - rs->fcr = fcr; - rs->prim = prim; - rs->nroots = nroots; - - /* Find prim-th root of 1, used in decoding */ - for(iprim=1;(iprim % prim) != 0;iprim += rs->nn) - ; - rs->iprim = iprim / prim; - - rs->genpoly[0] = 1; - for (i = 0,root=fcr*prim; i < nroots; i++,root += prim) { - rs->genpoly[i+1] = 1; - - /* Multiply rs->genpoly[] by @**(root + x) */ - for (j = i; j > 0; j--){ - if (rs->genpoly[j] != 0) - rs->genpoly[j] = rs->genpoly[j-1] ^ rs->alpha_to[modnn(rs,rs->index_of[rs->genpoly[j]] + root)]; - else - rs->genpoly[j] = rs->genpoly[j-1]; + /* Form RS code generator polynomial from its roots */ + rs->genpoly = (DTYPE*)malloc(sizeof(DTYPE) * (nroots + 1)); + if (rs->genpoly == NULL) { + free(rs->alpha_to); + free(rs->index_of); + free(rs); + return NULL; } - /* rs->genpoly[0] can never be zero */ - rs->genpoly[0] = rs->alpha_to[modnn(rs,rs->index_of[rs->genpoly[0]] + root)]; - } - /* convert rs->genpoly[] to index form for quicker encoding */ - for (i = 0; i <= nroots; i++) - rs->genpoly[i] = rs->index_of[rs->genpoly[i]]; + rs->fcr = fcr; + rs->prim = prim; + rs->nroots = nroots; + + /* Find prim-th root of 1, used in decoding */ + for (iprim = 1; (iprim % prim) != 0; iprim += rs->nn) + ; + rs->iprim = iprim / prim; + + rs->genpoly[0] = 1; + for (i = 0, root = fcr * prim; i < nroots; i++, root += prim) { + rs->genpoly[i + 1] = 1; + + /* Multiply rs->genpoly[] by @**(root + x) */ + for (j = i; j > 0; j--) { + if (rs->genpoly[j] != 0) + rs->genpoly[j] = + rs->genpoly[j - 1] ^ + rs->alpha_to[modnn(rs, rs->index_of[rs->genpoly[j]] + root)]; + else + rs->genpoly[j] = rs->genpoly[j - 1]; + } + /* rs->genpoly[0] can never be zero */ + rs->genpoly[0] = rs->alpha_to[modnn(rs, rs->index_of[rs->genpoly[0]] + root)]; + } + /* convert rs->genpoly[] to index form for quicker encoding */ + for (i = 0; i <= nroots; i++) + rs->genpoly[i] = rs->index_of[rs->genpoly[i]]; #ifdef FIXED #elif defined(BIGSYM) #else - /* Form modnn lookup table */ - rs->modnn_table = (int *)malloc(sizeof(int)*(2<<((sizeof(unsigned char))*8))); - if(rs->modnn_table == NULL){ - free(rs->genpoly); - free(rs->alpha_to); - free(rs->index_of); - free(rs); - return NULL; - } - for(i = 0; i < (2<<((sizeof(unsigned char))*8)); i++){ - j = i; - rs->modnn_table[i] = modnn(rs,j); - } + /* Form modnn lookup table */ + rs->modnn_table = (int*)malloc(sizeof(int) * (2 << ((sizeof(unsigned char)) * 8))); + if (rs->modnn_table == NULL) { + free(rs->genpoly); + free(rs->alpha_to); + free(rs->index_of); + free(rs); + return NULL; + } + for (i = 0; i < (2 << ((sizeof(unsigned char)) * 8)); i++) { + j = i; + rs->modnn_table[i] = modnn(rs, j); + } #endif #if 0 @@ -150,5 +157,5 @@ void *INIT_RS(unsigned int symsize,unsigned int gfpoly,unsigned fcr,unsigned pri } #endif - return rs; + return rs; } diff --git a/gr-fec/lib/reed-solomon/int.h b/gr-fec/lib/reed-solomon/int.h index 818629abb4..80dd50d3f2 100644 --- a/gr-fec/lib/reed-solomon/int.h +++ b/gr-fec/lib/reed-solomon/int.h @@ -9,25 +9,26 @@ /* Reed-Solomon codec control block */ struct FEC_API rs { - unsigned int mm; /* Bits per symbol */ - unsigned int nn; /* Symbols per block (= (1<<mm)-1) */ - int *alpha_to; /* log lookup table */ - int *index_of; /* Antilog lookup table */ - int *genpoly; /* Generator polynomial */ - unsigned int nroots; /* Number of generator roots = number of parity symbols */ - unsigned int fcr; /* First consecutive root, index form */ - unsigned int prim; /* Primitive element, index form */ - unsigned int iprim; /* prim-th root of 1, index form */ + unsigned int mm; /* Bits per symbol */ + unsigned int nn; /* Symbols per block (= (1<<mm)-1) */ + int* alpha_to; /* log lookup table */ + int* index_of; /* Antilog lookup table */ + int* genpoly; /* Generator polynomial */ + unsigned int nroots; /* Number of generator roots = number of parity symbols */ + unsigned int fcr; /* First consecutive root, index form */ + unsigned int prim; /* Primitive element, index form */ + unsigned int iprim; /* prim-th root of 1, index form */ }; -static inline int modnn(struct rs *rs,int x){ - while (x >= rs->nn) { - x -= rs->nn; - x = (x >> rs->mm) + (x & rs->nn); - } - return x; +static inline int modnn(struct rs* rs, int x) +{ + while (x >= rs->nn) { + x -= rs->nn; + x = (x >> rs->mm) + (x & rs->nn); + } + return x; } -#define MODNN(x) modnn(rs,x) +#define MODNN(x) modnn(rs, x) #define MM (rs->mm) #define NN (rs->nn) @@ -45,11 +46,11 @@ static inline int modnn(struct rs *rs,int x){ #define INIT_RS init_rs_int #define FREE_RS free_rs_int -FEC_API void ENCODE_RS(void *p,DTYPE *data,DTYPE *parity); -FEC_API int DECODE_RS(void *p,DTYPE *data,int *eras_pos,int no_eras); -void *INIT_RS(unsigned int symsize,unsigned int gfpoly,unsigned int fcr, - unsigned int prim,unsigned int nroots); -FEC_API void FREE_RS(void *p); - - - +FEC_API void ENCODE_RS(void* p, DTYPE* data, DTYPE* parity); +FEC_API int DECODE_RS(void* p, DTYPE* data, int* eras_pos, int no_eras); +void* INIT_RS(unsigned int symsize, + unsigned int gfpoly, + unsigned int fcr, + unsigned int prim, + unsigned int nroots); +FEC_API void FREE_RS(void* p); diff --git a/gr-fec/lib/reed-solomon/rstest.c b/gr-fec/lib/reed-solomon/rstest.c index e2783843e9..c8fc000700 100644 --- a/gr-fec/lib/reed-solomon/rstest.c +++ b/gr-fec/lib/reed-solomon/rstest.c @@ -14,104 +14,110 @@ #include <time.h> #include <gnuradio/fec/rs.h> -int exercise_char(void *,int); +int exercise_char(void*, int); #ifdef ALL_VERSIONS -int exercise_int(void *,int); +int exercise_int(void*, int); int exercise_8(int); int exercise_ccsds(int); #endif struct { - int symsize; - int genpoly; - int fcs; - int prim; - int nroots; - int ntrials; + int symsize; + int genpoly; + int fcs; + int prim; + int nroots; + int ntrials; } Tab[] = { - {2, 0x7, 1, 1, 1, 10 }, - {3, 0xb, 1, 1, 2, 10 }, - {4, 0x13, 1, 1, 4, 10 }, - {5, 0x25, 1, 1, 6, 10 }, - {6, 0x43, 1, 1, 8, 10 }, - {7, 0x89, 1, 1, 10, 10 }, - {8, 0x11d, 1, 1, 32, 10 }, - {8, 0x187, 112,11, 32, 10 }, /* Duplicates CCSDS codec */ + { 2, 0x7, 1, 1, 1, 10 }, + { 3, 0xb, 1, 1, 2, 10 }, + { 4, 0x13, 1, 1, 4, 10 }, + { 5, 0x25, 1, 1, 6, 10 }, + { 6, 0x43, 1, 1, 8, 10 }, + { 7, 0x89, 1, 1, 10, 10 }, + { 8, 0x11d, 1, 1, 32, 10 }, + { 8, 0x187, 112, 11, 32, 10 }, /* Duplicates CCSDS codec */ #ifdef ALL_VESIONS - {9, 0x211, 1, 1, 32, 10 }, - {10,0x409, 1, 1, 32, 10 }, - {11,0x805, 1, 1, 32, 10 }, - {12,0x1053, 1, 1, 32, 5 }, - {13,0x201b, 1, 1, 32, 2 }, - {14,0x4443, 1, 1, 32, 1 }, - {15,0x8003, 1, 1, 32, 1 }, - {16,0x1100b, 1, 1, 32, 1 }, + { 9, 0x211, 1, 1, 32, 10 }, + { 10, 0x409, 1, 1, 32, 10 }, + { 11, 0x805, 1, 1, 32, 10 }, + { 12, 0x1053, 1, 1, 32, 5 }, + { 13, 0x201b, 1, 1, 32, 2 }, + { 14, 0x4443, 1, 1, 32, 1 }, + { 15, 0x8003, 1, 1, 32, 1 }, + { 16, 0x1100b, 1, 1, 32, 1 }, #endif - {0, 0, 0, 0, 0}, + { 0, 0, 0, 0, 0 }, }; -int main(){ - void *handle; - int errs,terrs; - int i; +int main() +{ + void* handle; + int errs, terrs; + int i; - terrs = 0; - srand(time(NULL)); + terrs = 0; + srand(time(NULL)); #ifdef ALL_VERSIONS - printf("Testing fixed (255,223) RS codec..."); - fflush(stdout); - errs = exercise_8(10); - terrs += errs; - if(errs == 0){ - printf("OK\n"); - } - printf("Testing CCSDS standard (255,223) RS codec..."); - fflush(stdout); - errs = exercise_ccsds(10); - terrs += errs; - if(errs == 0){ - printf("OK\n"); - } + printf("Testing fixed (255,223) RS codec..."); + fflush(stdout); + errs = exercise_8(10); + terrs += errs; + if (errs == 0) { + printf("OK\n"); + } + printf("Testing CCSDS standard (255,223) RS codec..."); + fflush(stdout); + errs = exercise_ccsds(10); + terrs += errs; + if (errs == 0) { + printf("OK\n"); + } #endif - for(i=0;Tab[i].symsize != 0;i++){ - int nn,kk; + for (i = 0; Tab[i].symsize != 0; i++) { + int nn, kk; - nn = (1<<Tab[i].symsize) - 1; - kk = nn - Tab[i].nroots; - printf("Testing (%d,%d) RS codec...",nn,kk); - fflush(stdout); - if(Tab[i].symsize <= 8){ - if((handle = init_rs_char(Tab[i].symsize,Tab[i].genpoly,Tab[i].fcs,Tab[i].prim,Tab[i].nroots)) == NULL){ - printf("init_rs_char failed!\n"); - continue; - } - errs = exercise_char(handle,Tab[i].ntrials); - } else { + nn = (1 << Tab[i].symsize) - 1; + kk = nn - Tab[i].nroots; + printf("Testing (%d,%d) RS codec...", nn, kk); + fflush(stdout); + if (Tab[i].symsize <= 8) { + if ((handle = init_rs_char(Tab[i].symsize, + Tab[i].genpoly, + Tab[i].fcs, + Tab[i].prim, + Tab[i].nroots)) == NULL) { + printf("init_rs_char failed!\n"); + continue; + } + errs = exercise_char(handle, Tab[i].ntrials); + } else { #ifdef ALL_VERSIONS - if((handle = init_rs_int(Tab[i].symsize,Tab[i].genpoly,Tab[i].fcs,Tab[i].prim,Tab[i].nroots)) == NULL){ - printf("init_rs_int failed!\n"); - continue; - } - errs = exercise_int(handle,Tab[i].ntrials); + if ((handle = init_rs_int(Tab[i].symsize, + Tab[i].genpoly, + Tab[i].fcs, + Tab[i].prim, + Tab[i].nroots)) == NULL) { + printf("init_rs_int failed!\n"); + continue; + } + errs = exercise_int(handle, Tab[i].ntrials); #else - printf ("init_rs_init support is not enabled\n"); - exit (1); + printf("init_rs_init support is not enabled\n"); + exit(1); #endif - - } - terrs += errs; - if(errs == 0){ - printf("OK\n"); + } + terrs += errs; + if (errs == 0) { + printf("OK\n"); + } + free_rs_char(handle); } - free_rs_char(handle); - } - if(terrs == 0) - printf("All codec tests passed!\n"); + if (terrs == 0) + printf("All codec tests passed!\n"); - exit(0); + exit(0); } - - diff --git a/gr-fec/lib/repetition_decoder_impl.cc b/gr-fec/lib/repetition_decoder_impl.cc index bce41de5ca..ed8ba11eee 100644 --- a/gr-fec/lib/repetition_decoder_impl.cc +++ b/gr-fec/lib/repetition_decoder_impl.cc @@ -33,112 +33,84 @@ #include <vector> namespace gr { - namespace fec { - namespace code { - - generic_decoder::sptr - repetition_decoder::make(int frame_size, int rep, - float ap_prob) - { - return generic_decoder::sptr - (new repetition_decoder_impl(frame_size, rep, - ap_prob)); - } - - repetition_decoder_impl::repetition_decoder_impl(int frame_size, int rep, - float ap_prob) - : generic_decoder("repetition_decoder") - { - // Set max frame size here; all buffers and settings will be - // based on this value. - d_max_frame_size = frame_size; - set_frame_size(frame_size); - - if(rep < 0) - throw std::runtime_error("repetition_encoder: repetition rate must be >= 0"); - if((ap_prob < 0) || (ap_prob > 1.0)) - throw std::runtime_error("repetition_encoder: a priori probability rate must be in [0, 1]"); - - d_rep = rep; - d_ap_prob = ap_prob; - d_trials.resize(d_rep); - } - - repetition_decoder_impl::~repetition_decoder_impl() - { - } - - int - repetition_decoder_impl::get_output_size() - { - //unpacked bits - return d_frame_size; - } - - int - repetition_decoder_impl::get_input_size() - { - return d_frame_size*d_rep; - } - - int - repetition_decoder_impl::get_input_item_size() - { - return sizeof(float); - } - - const char* - repetition_decoder_impl::get_input_conversion() - { - return "none"; - } - - float - repetition_decoder_impl::get_shift() - { - return 0; - } - - bool - repetition_decoder_impl::set_frame_size(unsigned int frame_size) - { - bool ret = true; - if(frame_size > d_max_frame_size) { - GR_LOG_INFO(d_logger, boost::format("tried to set frame to %1%; max possible is %2%") \ - % frame_size % d_max_frame_size); - frame_size = d_max_frame_size; - ret = false; +namespace fec { +namespace code { + +generic_decoder::sptr repetition_decoder::make(int frame_size, int rep, float ap_prob) +{ + return generic_decoder::sptr(new repetition_decoder_impl(frame_size, rep, ap_prob)); +} + +repetition_decoder_impl::repetition_decoder_impl(int frame_size, int rep, float ap_prob) + : generic_decoder("repetition_decoder") +{ + // Set max frame size here; all buffers and settings will be + // based on this value. + d_max_frame_size = frame_size; + set_frame_size(frame_size); + + if (rep < 0) + throw std::runtime_error("repetition_encoder: repetition rate must be >= 0"); + if ((ap_prob < 0) || (ap_prob > 1.0)) + throw std::runtime_error( + "repetition_encoder: a priori probability rate must be in [0, 1]"); + + d_rep = rep; + d_ap_prob = ap_prob; + d_trials.resize(d_rep); +} + +repetition_decoder_impl::~repetition_decoder_impl() {} + +int repetition_decoder_impl::get_output_size() +{ + // unpacked bits + return d_frame_size; +} + +int repetition_decoder_impl::get_input_size() { return d_frame_size * d_rep; } + +int repetition_decoder_impl::get_input_item_size() { return sizeof(float); } + +const char* repetition_decoder_impl::get_input_conversion() { return "none"; } + +float repetition_decoder_impl::get_shift() { return 0; } + +bool repetition_decoder_impl::set_frame_size(unsigned int frame_size) +{ + bool ret = true; + if (frame_size > d_max_frame_size) { + GR_LOG_INFO(d_logger, + boost::format("tried to set frame to %1%; max possible is %2%") % + frame_size % d_max_frame_size); + frame_size = d_max_frame_size; + ret = false; + } + + d_frame_size = frame_size; + + return ret; +} + +double repetition_decoder_impl::rate() { return 1.0 / static_cast<double>(d_rep); } + +void repetition_decoder_impl::generic_work(void* inbuffer, void* outbuffer) +{ + const float* in = (const float*)inbuffer; + unsigned char* out = (unsigned char*)outbuffer; + + for (unsigned int i = 0; i < d_frame_size; i++) { + for (unsigned int r = 0; r < d_rep; r++) { + d_trials[r] = (in[d_rep * i + r] > 0) ? 1.0f : 0.0f; } - - d_frame_size = frame_size; - - return ret; - } - - double - repetition_decoder_impl::rate() - { - return 1.0/static_cast<double>(d_rep); - } - - void - repetition_decoder_impl::generic_work(void *inbuffer, void *outbuffer) - { - const float *in = (const float*)inbuffer; - unsigned char *out = (unsigned char *) outbuffer; - - for(unsigned int i = 0; i < d_frame_size; i++) { - for(unsigned int r = 0; r < d_rep; r++) { - d_trials[r] = (in[d_rep*i + r] > 0) ? 1.0f : 0.0f; - } - float res = std::count(d_trials.begin(), d_trials.end(), 1.0f); - if((res / static_cast<float>(d_rep)) > d_ap_prob) + float res = std::count(d_trials.begin(), d_trials.end(), 1.0f); + if ((res / static_cast<float>(d_rep)) > d_ap_prob) out[i] = 1; - else + else out[i] = 0; - } - } + } +} - } /* namespace code */ - } /* namespace fec */ +} /* namespace code */ +} /* namespace fec */ } /* namespace gr */ diff --git a/gr-fec/lib/repetition_decoder_impl.h b/gr-fec/lib/repetition_decoder_impl.h index 33fb174456..2a058a0894 100644 --- a/gr-fec/lib/repetition_decoder_impl.h +++ b/gr-fec/lib/repetition_decoder_impl.h @@ -29,39 +29,38 @@ #include <gnuradio/fec/repetition_decoder.h> namespace gr { - namespace fec { - namespace code { +namespace fec { +namespace code { - class FEC_API repetition_decoder_impl : public repetition_decoder - { - private: - //plug into the generic fec api - void generic_work(void *inbuffer, void *outbuffer); - int get_output_size(); - int get_input_size(); - int get_input_item_size(); - float get_shift(); - const char* get_input_conversion(); - //const char* get_output_conversion(); +class FEC_API repetition_decoder_impl : public repetition_decoder +{ +private: + // plug into the generic fec api + void generic_work(void* inbuffer, void* outbuffer); + int get_output_size(); + int get_input_size(); + int get_input_item_size(); + float get_shift(); + const char* get_input_conversion(); + // const char* get_output_conversion(); - unsigned int d_max_frame_size; - unsigned int d_frame_size; - unsigned int d_rep; - float d_ap_prob; + unsigned int d_max_frame_size; + unsigned int d_frame_size; + unsigned int d_rep; + float d_ap_prob; - std::vector<float> d_trials; + std::vector<float> d_trials; - public: - repetition_decoder_impl(int frame_size, int rep, - float ap_prob=0.5); - ~repetition_decoder_impl(); +public: + repetition_decoder_impl(int frame_size, int rep, float ap_prob = 0.5); + ~repetition_decoder_impl(); - bool set_frame_size(unsigned int frame_size); - double rate(); - }; + bool set_frame_size(unsigned int frame_size); + double rate(); +}; - } /* namespace code */ - } /* namespace fec */ +} /* namespace code */ +} /* namespace fec */ } /* namespace gr */ #endif /* INCLUDED_FEC_REPETITION_DECODER_IMPL_H */ diff --git a/gr-fec/lib/repetition_encoder_impl.cc b/gr-fec/lib/repetition_encoder_impl.cc index dd6bc01615..5be5995110 100644 --- a/gr-fec/lib/repetition_encoder_impl.cc +++ b/gr-fec/lib/repetition_encoder_impl.cc @@ -30,79 +30,62 @@ #include <sstream> namespace gr { - namespace fec { - namespace code { - - generic_encoder::sptr - repetition_encoder::make(int frame_size, int rep) - { - return generic_encoder::sptr - (new repetition_encoder_impl(frame_size, rep)); - } - - repetition_encoder_impl::repetition_encoder_impl(int frame_size, int rep) - : generic_encoder("repetition_encoder") - { - d_max_frame_size = frame_size; - set_frame_size(frame_size); - - if(rep < 0) - throw std::runtime_error("repetition_encoder: repetition rate must be >= 0"); - - d_rep = rep; - } - - repetition_encoder_impl::~repetition_encoder_impl() - { - } - - int - repetition_encoder_impl::get_output_size() - { - return d_frame_size*d_rep; - } - - int - repetition_encoder_impl::get_input_size() - { - return d_frame_size; - } - - bool - repetition_encoder_impl::set_frame_size(unsigned int frame_size) - { - bool ret = true; - if(frame_size > d_max_frame_size) { - GR_LOG_INFO(d_logger, boost::format("tried to set frame to %1%; max possible is %2%") \ - % frame_size % d_max_frame_size); - frame_size = d_max_frame_size; - ret = false; - } +namespace fec { +namespace code { + +generic_encoder::sptr repetition_encoder::make(int frame_size, int rep) +{ + return generic_encoder::sptr(new repetition_encoder_impl(frame_size, rep)); +} + +repetition_encoder_impl::repetition_encoder_impl(int frame_size, int rep) + : generic_encoder("repetition_encoder") +{ + d_max_frame_size = frame_size; + set_frame_size(frame_size); + + if (rep < 0) + throw std::runtime_error("repetition_encoder: repetition rate must be >= 0"); + + d_rep = rep; +} + +repetition_encoder_impl::~repetition_encoder_impl() {} + +int repetition_encoder_impl::get_output_size() { return d_frame_size * d_rep; } + +int repetition_encoder_impl::get_input_size() { return d_frame_size; } + +bool repetition_encoder_impl::set_frame_size(unsigned int frame_size) +{ + bool ret = true; + if (frame_size > d_max_frame_size) { + GR_LOG_INFO(d_logger, + boost::format("tried to set frame to %1%; max possible is %2%") % + frame_size % d_max_frame_size); + frame_size = d_max_frame_size; + ret = false; + } - d_frame_size = frame_size; + d_frame_size = frame_size; - return ret; - } + return ret; +} - double - repetition_encoder_impl::rate() - { - return static_cast<double>(d_rep); - } +double repetition_encoder_impl::rate() { return static_cast<double>(d_rep); } - void - repetition_encoder_impl::generic_work(void *inbuffer, void *outbuffer) - { - const unsigned char *in = (const unsigned char*)inbuffer; - unsigned char *out = (unsigned char*)outbuffer; +void repetition_encoder_impl::generic_work(void* inbuffer, void* outbuffer) +{ + const unsigned char* in = (const unsigned char*)inbuffer; + unsigned char* out = (unsigned char*)outbuffer; - for(unsigned int i = 0; i < d_frame_size; i++) { - for(unsigned int r = 0; r < d_rep; r++) { - out[d_rep*i + r] = in[i]; - } + for (unsigned int i = 0; i < d_frame_size; i++) { + for (unsigned int r = 0; r < d_rep; r++) { + out[d_rep * i + r] = in[i]; } - } + } +} - } /* namespace code */ - } /* namespace fec */ +} /* namespace code */ +} /* namespace fec */ } /* namespace gr */ diff --git a/gr-fec/lib/repetition_encoder_impl.h b/gr-fec/lib/repetition_encoder_impl.h index 4730110817..278b585f3a 100644 --- a/gr-fec/lib/repetition_encoder_impl.h +++ b/gr-fec/lib/repetition_encoder_impl.h @@ -28,31 +28,31 @@ p * You should have received a copy of the GNU General Public License #include <gnuradio/fec/repetition_encoder.h> namespace gr { - namespace fec { - namespace code { - - class FEC_API repetition_encoder_impl : public repetition_encoder - { - private: - //plug into the generic fec api - void generic_work(void *inbuffer, void *outbuffer); - int get_output_size(); - int get_input_size(); - - unsigned int d_max_frame_size; - unsigned int d_frame_size; - unsigned int d_rep; - - public: - repetition_encoder_impl(int frame_size, int rep); - ~repetition_encoder_impl(); - - bool set_frame_size(unsigned int frame_size); - double rate(); - }; - - } /* namespace code */ - } /* namespace fec */ +namespace fec { +namespace code { + +class FEC_API repetition_encoder_impl : public repetition_encoder +{ +private: + // plug into the generic fec api + void generic_work(void* inbuffer, void* outbuffer); + int get_output_size(); + int get_input_size(); + + unsigned int d_max_frame_size; + unsigned int d_frame_size; + unsigned int d_rep; + +public: + repetition_encoder_impl(int frame_size, int rep); + ~repetition_encoder_impl(); + + bool set_frame_size(unsigned int frame_size); + double rate(); +}; + +} /* namespace code */ +} /* namespace fec */ } /* namespace gr */ #endif /* INCLUDED_FEC_REPETITION_ENCODER_IMPL_H */ diff --git a/gr-fec/lib/scl_list.cc b/gr-fec/lib/scl_list.cc index 3e47af1c3f..2b126358ec 100644 --- a/gr-fec/lib/scl_list.cc +++ b/gr-fec/lib/scl_list.cc @@ -27,167 +27,164 @@ #include <volk/volk.h> namespace gr { - namespace fec { - namespace code { - namespace polar { - - scl_list::scl_list(const unsigned int size, - const unsigned int block_size, - const unsigned int block_power): - d_list_size(size), - d_num_buff_elements(block_size * (block_power + 1)) - { - for(unsigned int i = 0; i < 2 * size; i++){ - d_path_list.push_back(new path()); - } - - for(unsigned int i = 0; i < size; i++){ - d_path_list[i]->llr_vec = (float*) volk_malloc(sizeof(float) * d_num_buff_elements, volk_get_alignment()); - memset(d_path_list[i]->llr_vec, 0, sizeof(float) * d_num_buff_elements); - d_path_list[i]->u_vec = (unsigned char*) volk_malloc(sizeof(unsigned char) * d_num_buff_elements, volk_get_alignment()); - memset(d_path_list[i]->u_vec, 0, sizeof(unsigned char) * d_num_buff_elements); - d_path_list[i]->owns_vectors = true; - } - - d_path_list[0]->is_active = true; - d_active_path_counter = 1; - d_active_pos = 0; +namespace fec { +namespace code { +namespace polar { + +scl_list::scl_list(const unsigned int size, + const unsigned int block_size, + const unsigned int block_power) + : d_list_size(size), d_num_buff_elements(block_size * (block_power + 1)) +{ + for (unsigned int i = 0; i < 2 * size; i++) { + d_path_list.push_back(new path()); + } + + for (unsigned int i = 0; i < size; i++) { + d_path_list[i]->llr_vec = (float*)volk_malloc(sizeof(float) * d_num_buff_elements, + volk_get_alignment()); + memset(d_path_list[i]->llr_vec, 0, sizeof(float) * d_num_buff_elements); + d_path_list[i]->u_vec = (unsigned char*)volk_malloc( + sizeof(unsigned char) * d_num_buff_elements, volk_get_alignment()); + memset(d_path_list[i]->u_vec, 0, sizeof(unsigned char) * d_num_buff_elements); + d_path_list[i]->owns_vectors = true; + } + + d_path_list[0]->is_active = true; + d_active_path_counter = 1; + d_active_pos = 0; +} + +scl_list::~scl_list() +{ + for (unsigned int i = 0; i < d_path_list.size(); i++) { + delete d_path_list[i]; + } +} + + +const path* scl_list::optimal_path() +{ + const path* temp = *std::min_element( + d_path_list.begin(), d_path_list.begin() + d_active_path_counter, path_compare); + reset(); + return temp; +} + +void scl_list::reset() +{ + // leave 0th element active for next iteration + d_path_list[0]->path_metric = 0.0f; + for (unsigned int i = 1; i < d_path_list.size(); i++) { + d_path_list[i]->is_active = false; + d_path_list[i]->path_metric = 0.0f; + } + d_active_path_counter = 1; + d_active_pos = 0; +} + +void scl_list::set_info_bit(const int bit_pos) +{ + if (d_active_path_counter < d_list_size) { + const int offset = d_active_path_counter; + for (int i = 0; i < offset; i++) { + duplicate_path(d_path_list[i + offset], d_path_list[i]); + d_path_list[i]->path_metric = update_path_metric( + d_path_list[i]->path_metric, d_path_list[i]->llr_vec[bit_pos], 0); + d_path_list[i + offset]->path_metric = + update_path_metric(d_path_list[i + offset]->path_metric, + d_path_list[i + offset]->llr_vec[bit_pos], + 1); + d_path_list[i]->u_vec[bit_pos] = 0; + d_path_list[i + offset]->u_vec[bit_pos] = 1; } + } else { - scl_list::~scl_list() - { - for(unsigned int i = 0; i < d_path_list.size(); i++){ - delete d_path_list[i]; - } + for (unsigned int i = 0; i < d_list_size; i++) { + branch_paths(d_path_list[i + d_list_size], + d_path_list[i], + d_path_list[i]->llr_vec[bit_pos]); } + std::sort(d_path_list.begin(), d_path_list.end(), path_compare); - - const path* - scl_list::optimal_path() - { - const path* temp = *std::min_element(d_path_list.begin(), d_path_list.begin() + d_active_path_counter, path_compare); - reset(); - return temp; - } - - void - scl_list::reset() - { - // leave 0th element active for next iteration - d_path_list[0]->path_metric = 0.0f; - for(unsigned int i = 1; i < d_path_list.size(); i++){ - d_path_list[i]->is_active = false; - d_path_list[i]->path_metric = 0.0f; - } - d_active_path_counter = 1; - d_active_pos = 0; - } - - void - scl_list::set_info_bit(const int bit_pos) - { - if(d_active_path_counter < d_list_size) { - const int offset = d_active_path_counter; - for(int i = 0; i < offset; i++) { - duplicate_path(d_path_list[i + offset], d_path_list[i]); - d_path_list[i]->path_metric = update_path_metric(d_path_list[i]->path_metric, - d_path_list[i]->llr_vec[bit_pos], 0); - d_path_list[i + offset]->path_metric = update_path_metric - (d_path_list[i + offset]->path_metric, d_path_list[i + offset]->llr_vec[bit_pos], 1); - d_path_list[i]->u_vec[bit_pos] = 0; - d_path_list[i + offset]->u_vec[bit_pos] = 1; - } - } - else { - - for(unsigned int i = 0; i < d_list_size; i++) { - branch_paths(d_path_list[i + d_list_size], d_path_list[i], d_path_list[i]->llr_vec[bit_pos]); - } - std::sort(d_path_list.begin(), d_path_list.end(), path_compare); - - for(unsigned int i = 0; i < d_list_size; i++) { - if(!d_path_list[i]->owns_vectors) { + for (unsigned int i = 0; i < d_list_size; i++) { + if (!d_path_list[i]->owns_vectors) { int t_pos = d_list_size; - while(!d_path_list[t_pos]->owns_vectors) { - t_pos++; + while (!d_path_list[t_pos]->owns_vectors) { + t_pos++; } steal_vector_ownership(d_path_list[i], d_path_list[t_pos]); d_path_list[i]->u_vec[bit_pos] = 1; - } - else{ + } else { d_path_list[i]->u_vec[bit_pos] = 0; - } } - } - d_active_pos = 0; - } - - void - scl_list::branch_paths(path* target, path* original, const float llr) - { - target->path_metric = update_path_metric(original->path_metric, llr, 1); - original->path_metric = update_path_metric(original->path_metric, llr, 0); - target->llr_vec = original->llr_vec; - target->u_vec = original->u_vec; - } - - void - scl_list::steal_vector_ownership(path* target, path* original) - { - memcpy(original->llr_vec, target->llr_vec, sizeof(float) * d_num_buff_elements); - memcpy(original->u_vec, target->u_vec, sizeof(unsigned char) * d_num_buff_elements); - target->llr_vec = original->llr_vec; - target->u_vec = original->u_vec; - target->owns_vectors = true; - original->owns_vectors = false; - } - - void - scl_list::duplicate_path(path* target, const path* original) - { - memcpy(target->llr_vec, original->llr_vec, sizeof(float) * d_num_buff_elements); - memcpy(target->u_vec, original->u_vec, sizeof(unsigned char) * d_num_buff_elements); - target->path_metric = original->path_metric; - d_active_path_counter++; - target->is_active = true; - } - - float - scl_list::update_path_metric(const float last_pm, const float llr, - const float ui) const - { - if((ui == 0 && llr > 0.0f) || (ui == 1 && llr < 0.0f)){ - // if(ui == (unsigned char) (0.5 * 1 - copysignf(1.0f, llr))){ - return last_pm; - } - return last_pm + fabs(llr); - } - - void - scl_list::set_frozen_bit(const unsigned char frozen_bit, const int bit_pos) - { - for(unsigned int i = 0; i < d_active_path_counter; i++){ - d_path_list[i]->u_vec[bit_pos] = frozen_bit; - d_path_list[i]->path_metric = update_path_metric(d_path_list[i]->path_metric, - d_path_list[i]->llr_vec[bit_pos], - frozen_bit); - } - d_active_pos = 0; - } - - path::path(): - path_metric(0.0f), owns_vectors(false), is_active(false), llr_vec(NULL), u_vec(NULL) - { } - - path::~path(){ - if(owns_vectors){ - volk_free(llr_vec); - volk_free(u_vec); - } - } - - } /* namespace polar */ - } /* namespace code */ - } /* namespace fec */ + } + d_active_pos = 0; +} + +void scl_list::branch_paths(path* target, path* original, const float llr) +{ + target->path_metric = update_path_metric(original->path_metric, llr, 1); + original->path_metric = update_path_metric(original->path_metric, llr, 0); + target->llr_vec = original->llr_vec; + target->u_vec = original->u_vec; +} + +void scl_list::steal_vector_ownership(path* target, path* original) +{ + memcpy(original->llr_vec, target->llr_vec, sizeof(float) * d_num_buff_elements); + memcpy(original->u_vec, target->u_vec, sizeof(unsigned char) * d_num_buff_elements); + target->llr_vec = original->llr_vec; + target->u_vec = original->u_vec; + target->owns_vectors = true; + original->owns_vectors = false; +} + +void scl_list::duplicate_path(path* target, const path* original) +{ + memcpy(target->llr_vec, original->llr_vec, sizeof(float) * d_num_buff_elements); + memcpy(target->u_vec, original->u_vec, sizeof(unsigned char) * d_num_buff_elements); + target->path_metric = original->path_metric; + d_active_path_counter++; + target->is_active = true; +} + +float scl_list::update_path_metric(const float last_pm, + const float llr, + const float ui) const +{ + if ((ui == 0 && llr > 0.0f) || (ui == 1 && llr < 0.0f)) { + // if(ui == (unsigned char) (0.5 * 1 - copysignf(1.0f, llr))){ + return last_pm; + } + return last_pm + fabs(llr); +} + +void scl_list::set_frozen_bit(const unsigned char frozen_bit, const int bit_pos) +{ + for (unsigned int i = 0; i < d_active_path_counter; i++) { + d_path_list[i]->u_vec[bit_pos] = frozen_bit; + d_path_list[i]->path_metric = update_path_metric( + d_path_list[i]->path_metric, d_path_list[i]->llr_vec[bit_pos], frozen_bit); + } + d_active_pos = 0; +} + +path::path() + : path_metric(0.0f), owns_vectors(false), is_active(false), llr_vec(NULL), u_vec(NULL) +{ +} + +path::~path() +{ + if (owns_vectors) { + volk_free(llr_vec); + volk_free(u_vec); + } +} + +} /* namespace polar */ +} /* namespace code */ +} /* namespace fec */ } /* namespace gr */ diff --git a/gr-fec/lib/scl_list.h b/gr-fec/lib/scl_list.h index 60e5cae8cd..9d014cc33c 100644 --- a/gr-fec/lib/scl_list.h +++ b/gr-fec/lib/scl_list.h @@ -26,60 +26,62 @@ #include <vector> namespace gr { - namespace fec { - namespace code { - namespace polar { +namespace fec { +namespace code { +namespace polar { - struct path { - path(); - ~path(); - float path_metric; - bool owns_vectors; - bool is_active; - float* llr_vec; - unsigned char* u_vec; - }; +struct path { + path(); + ~path(); + float path_metric; + bool owns_vectors; + bool is_active; + float* llr_vec; + unsigned char* u_vec; +}; - /*! - * \brief List implementation for Successive Cancellation List decoders - * - */ - class scl_list{ - const unsigned int d_list_size; - const unsigned int d_num_buff_elements; - std::vector<path*> d_path_list; - unsigned int d_active_path_counter; - unsigned int d_active_pos; +/*! + * \brief List implementation for Successive Cancellation List decoders + * + */ +class scl_list +{ + const unsigned int d_list_size; + const unsigned int d_num_buff_elements; + std::vector<path*> d_path_list; + unsigned int d_active_path_counter; + unsigned int d_active_pos; - float update_path_metric(const float last_pm, const float llr, const float ui) const; - void duplicate_path(path* target, const path* original); - void branch_paths(path* target, path* original, const float llr); - void steal_vector_ownership(path* target, path* original); - void reset(); + float update_path_metric(const float last_pm, const float llr, const float ui) const; + void duplicate_path(path* target, const path* original); + void branch_paths(path* target, path* original, const float llr); + void steal_vector_ownership(path* target, path* original); + void reset(); - // comparator for std::sort - static bool path_compare(path* first, path* second) { - return first->path_metric < second->path_metric; - }; + // comparator for std::sort + static bool path_compare(path* first, path* second) + { + return first->path_metric < second->path_metric; + }; - public: - scl_list(const unsigned int list_size, const unsigned int block_size, - const unsigned int block_power); - virtual - ~scl_list(); - const unsigned int size() const {return d_list_size;}; - const unsigned int active_size() const {return d_active_path_counter;}; +public: + scl_list(const unsigned int list_size, + const unsigned int block_size, + const unsigned int block_power); + virtual ~scl_list(); + const unsigned int size() const { return d_list_size; }; + const unsigned int active_size() const { return d_active_path_counter; }; - path* initial_path() const {return d_path_list[0];}; - path* next_active_path(){return d_path_list[d_active_pos++];}; - void set_frozen_bit(const unsigned char frozen_bit, const int bit_pos); - void set_info_bit(const int bit_pos); - const path* optimal_path(); - }; + path* initial_path() const { return d_path_list[0]; }; + path* next_active_path() { return d_path_list[d_active_pos++]; }; + void set_frozen_bit(const unsigned char frozen_bit, const int bit_pos); + void set_info_bit(const int bit_pos); + const path* optimal_path(); +}; - } /* namespace polar */ - } /* namespace code */ - } /* namespace fec */ +} /* namespace polar */ +} /* namespace code */ +} /* namespace fec */ } /* namespace gr */ #endif /* INCLUDED_FEC_SCL_LIST_H */ diff --git a/gr-fec/lib/tagged_decoder_impl.cc b/gr-fec/lib/tagged_decoder_impl.cc index 3fc6508d0b..e40da234b2 100644 --- a/gr-fec/lib/tagged_decoder_impl.cc +++ b/gr-fec/lib/tagged_decoder_impl.cc @@ -29,68 +29,62 @@ #include <stdio.h> namespace gr { - namespace fec { +namespace fec { - tagged_decoder::sptr - tagged_decoder::make(generic_decoder::sptr my_decoder, - size_t input_item_size, - size_t output_item_size, - const std::string &lengthtagname, - int mtu) - { - return gnuradio::get_initial_sptr - ( new tagged_decoder_impl(my_decoder, input_item_size, - output_item_size, lengthtagname, - mtu)); - } +tagged_decoder::sptr tagged_decoder::make(generic_decoder::sptr my_decoder, + size_t input_item_size, + size_t output_item_size, + const std::string& lengthtagname, + int mtu) +{ + return gnuradio::get_initial_sptr(new tagged_decoder_impl( + my_decoder, input_item_size, output_item_size, lengthtagname, mtu)); +} - tagged_decoder_impl::tagged_decoder_impl(generic_decoder::sptr my_decoder, - size_t input_item_size, - size_t output_item_size, - const std::string &lengthtagname, - int mtu) - : tagged_stream_block("fec_tagged_decoder", - io_signature::make(1, 1, input_item_size), - io_signature::make(1, 1, output_item_size), - lengthtagname), +tagged_decoder_impl::tagged_decoder_impl(generic_decoder::sptr my_decoder, + size_t input_item_size, + size_t output_item_size, + const std::string& lengthtagname, + int mtu) + : tagged_stream_block("fec_tagged_decoder", + io_signature::make(1, 1, input_item_size), + io_signature::make(1, 1, output_item_size), + lengthtagname), d_mtu(mtu) - { - d_decoder = my_decoder; - d_decoder->set_frame_size(d_mtu*8); +{ + d_decoder = my_decoder; + d_decoder->set_frame_size(d_mtu * 8); - set_relative_rate(d_decoder->rate()); - } + set_relative_rate(d_decoder->rate()); +} - int - tagged_decoder_impl::calculate_output_stream_length(const gr_vector_int &ninput_items) - { - if((ninput_items[0]*d_decoder->rate()) > (d_mtu*8)) { +int tagged_decoder_impl::calculate_output_stream_length(const gr_vector_int& ninput_items) +{ + if ((ninput_items[0] * d_decoder->rate()) > (d_mtu * 8)) { throw std::runtime_error("tagged_encoder: received frame is larger than MTU."); - } - d_decoder->set_frame_size(round(ninput_items[0]*d_decoder->rate())); - return d_decoder->get_output_size(); } + d_decoder->set_frame_size(round(ninput_items[0] * d_decoder->rate())); + return d_decoder->get_output_size(); +} - tagged_decoder_impl::~tagged_decoder_impl() - { - } +tagged_decoder_impl::~tagged_decoder_impl() {} - int - tagged_decoder_impl::work(int noutput_items, +int tagged_decoder_impl::work(int noutput_items, gr_vector_int& ninput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) - { - const unsigned char *in = (unsigned char*)input_items[0]; - unsigned char *out = (unsigned char *)output_items[0]; + gr_vector_const_void_star& input_items, + gr_vector_void_star& output_items) +{ + const unsigned char* in = (unsigned char*)input_items[0]; + unsigned char* out = (unsigned char*)output_items[0]; - GR_LOG_DEBUG(d_debug_logger, boost::format("%1%, %2%, %3%") \ - % noutput_items % ninput_items[0] % d_decoder->get_output_size()); + GR_LOG_DEBUG(d_debug_logger, + boost::format("%1%, %2%, %3%") % noutput_items % ninput_items[0] % + d_decoder->get_output_size()); - d_decoder->generic_work((void*)in, (void*)out); + d_decoder->generic_work((void*)in, (void*)out); - return d_decoder->get_output_size(); - } + return d_decoder->get_output_size(); +} - } /* namespace fec */ +} /* namespace fec */ } /* namespace gr */ diff --git a/gr-fec/lib/tagged_decoder_impl.h b/gr-fec/lib/tagged_decoder_impl.h index d6ad10d5fa..9099e6524f 100644 --- a/gr-fec/lib/tagged_decoder_impl.h +++ b/gr-fec/lib/tagged_decoder_impl.h @@ -26,30 +26,30 @@ #include <gnuradio/fec/tagged_decoder.h> namespace gr { - namespace fec { - - class FEC_API tagged_decoder_impl : public tagged_decoder - { - private: - generic_decoder::sptr d_decoder; - int d_mtu; - - public: - tagged_decoder_impl(generic_decoder::sptr my_decoder, - size_t input_item_size, - size_t output_item_size, - const std::string &lengthtagname="packet_len", - int mtu=1500); - ~tagged_decoder_impl(); - - int work(int noutput_items, - gr_vector_int& ninput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); - int calculate_output_stream_length(const gr_vector_int &ninput_items); - }; - - } /* namespace fec */ +namespace fec { + +class FEC_API tagged_decoder_impl : public tagged_decoder +{ +private: + generic_decoder::sptr d_decoder; + int d_mtu; + +public: + tagged_decoder_impl(generic_decoder::sptr my_decoder, + size_t input_item_size, + size_t output_item_size, + const std::string& lengthtagname = "packet_len", + int mtu = 1500); + ~tagged_decoder_impl(); + + int work(int noutput_items, + gr_vector_int& ninput_items, + gr_vector_const_void_star& input_items, + gr_vector_void_star& output_items); + int calculate_output_stream_length(const gr_vector_int& ninput_items); +}; + +} /* namespace fec */ } /* namespace gr */ #endif /* INCLUDED_FEC_TAGGED_DECODER_IMPL_H */ diff --git a/gr-fec/lib/tagged_encoder_impl.cc b/gr-fec/lib/tagged_encoder_impl.cc index f6757c2647..0190caf7a1 100644 --- a/gr-fec/lib/tagged_encoder_impl.cc +++ b/gr-fec/lib/tagged_encoder_impl.cc @@ -29,68 +29,62 @@ #include <stdio.h> namespace gr { - namespace fec { +namespace fec { - tagged_encoder::sptr - tagged_encoder::make(generic_encoder::sptr my_encoder, - size_t input_item_size, - size_t output_item_size, - const std::string& lengthtagname, - int mtu) - { - return gnuradio::get_initial_sptr - (new tagged_encoder_impl(my_encoder, input_item_size, - output_item_size, - lengthtagname, mtu)); - } +tagged_encoder::sptr tagged_encoder::make(generic_encoder::sptr my_encoder, + size_t input_item_size, + size_t output_item_size, + const std::string& lengthtagname, + int mtu) +{ + return gnuradio::get_initial_sptr(new tagged_encoder_impl( + my_encoder, input_item_size, output_item_size, lengthtagname, mtu)); +} - tagged_encoder_impl::tagged_encoder_impl(generic_encoder::sptr my_encoder, - size_t input_item_size, - size_t output_item_size, - const std::string& lengthtagname, - int mtu) - : tagged_stream_block("fec_tagged_encoder", - io_signature::make(1, 1, input_item_size), - io_signature::make(1, 1, output_item_size), - lengthtagname), +tagged_encoder_impl::tagged_encoder_impl(generic_encoder::sptr my_encoder, + size_t input_item_size, + size_t output_item_size, + const std::string& lengthtagname, + int mtu) + : tagged_stream_block("fec_tagged_encoder", + io_signature::make(1, 1, input_item_size), + io_signature::make(1, 1, output_item_size), + lengthtagname), d_mtu(mtu) - { - d_encoder = my_encoder; +{ + d_encoder = my_encoder; - d_encoder->set_frame_size(d_mtu*8); - set_relative_rate(d_encoder->rate()); - } + d_encoder->set_frame_size(d_mtu * 8); + set_relative_rate(d_encoder->rate()); +} - tagged_encoder_impl::~tagged_encoder_impl() - { - } +tagged_encoder_impl::~tagged_encoder_impl() {} - int - tagged_encoder_impl::calculate_output_stream_length(const gr_vector_int &ninput_items) - { - if(ninput_items[0] > (d_mtu*8)) { +int tagged_encoder_impl::calculate_output_stream_length(const gr_vector_int& ninput_items) +{ + if (ninput_items[0] > (d_mtu * 8)) { throw std::runtime_error("tagged_encoder: received frame is larger than MTU."); - } - d_encoder->set_frame_size(ninput_items[0]); - return d_encoder->get_output_size(); } + d_encoder->set_frame_size(ninput_items[0]); + return d_encoder->get_output_size(); +} - int - tagged_encoder_impl::work(int noutput_items, +int tagged_encoder_impl::work(int noutput_items, gr_vector_int& ninput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) - { - char *inbuffer = (char*)input_items[0]; - char *outbuffer = (char*)output_items[0]; + gr_vector_const_void_star& input_items, + gr_vector_void_star& output_items) +{ + char* inbuffer = (char*)input_items[0]; + char* outbuffer = (char*)output_items[0]; - GR_LOG_DEBUG(d_debug_logger, boost::format("nout: %1% nin: %2% ret: %3%") \ - % noutput_items % ninput_items[0] % d_encoder->get_output_size()); + GR_LOG_DEBUG(d_debug_logger, + boost::format("nout: %1% nin: %2% ret: %3%") % noutput_items % + ninput_items[0] % d_encoder->get_output_size()); - d_encoder->generic_work((void*)(inbuffer), (void*)(outbuffer)); + d_encoder->generic_work((void*)(inbuffer), (void*)(outbuffer)); - return d_encoder->get_output_size(); - } + return d_encoder->get_output_size(); +} - } /* namespace fec */ +} /* namespace fec */ } /* namespace gr */ diff --git a/gr-fec/lib/tagged_encoder_impl.h b/gr-fec/lib/tagged_encoder_impl.h index b9363d1754..686b46862f 100644 --- a/gr-fec/lib/tagged_encoder_impl.h +++ b/gr-fec/lib/tagged_encoder_impl.h @@ -26,30 +26,30 @@ #include <gnuradio/fec/tagged_encoder.h> namespace gr { - namespace fec { - - class FEC_API tagged_encoder_impl : public tagged_encoder - { - private: - generic_encoder::sptr d_encoder; - int d_mtu; - - public: - tagged_encoder_impl(generic_encoder::sptr my_encoder, - size_t input_item_size, - size_t output_item_size, - const std::string &lengthtagname="packet_len", - int mtu=1500); - ~tagged_encoder_impl(); - - int work(int noutput_items, - gr_vector_int& ninput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); - int calculate_output_stream_length(const gr_vector_int &ninput_items); - }; - - } /* namespace fec */ +namespace fec { + +class FEC_API tagged_encoder_impl : public tagged_encoder +{ +private: + generic_encoder::sptr d_encoder; + int d_mtu; + +public: + tagged_encoder_impl(generic_encoder::sptr my_encoder, + size_t input_item_size, + size_t output_item_size, + const std::string& lengthtagname = "packet_len", + int mtu = 1500); + ~tagged_encoder_impl(); + + int work(int noutput_items, + gr_vector_int& ninput_items, + gr_vector_const_void_star& input_items, + gr_vector_void_star& output_items); + int calculate_output_stream_length(const gr_vector_int& ninput_items); +}; + +} /* namespace fec */ } /* namespace gr */ #endif /* INCLUDED_FEC_TAGGED_ENCODER_IMPL_H */ diff --git a/gr-fec/lib/tpc_common.cc b/gr-fec/lib/tpc_common.cc index 4d6a744580..ac55f63c8a 100644 --- a/gr-fec/lib/tpc_common.cc +++ b/gr-fec/lib/tpc_common.cc @@ -22,76 +22,88 @@ #include <gnuradio/fec/tpc_common.h> -namespace gr { - namespace fec { +namespace gr { +namespace fec { -int tpc_common::parity_counter( int symbol, int length ) { +int tpc_common::parity_counter(int symbol, int length) +{ int counter; int temp_parity = 0; - for (counter=0;counter<length;counter++) { - temp_parity = temp_parity^(symbol&1); - symbol = symbol>>1; + for (counter = 0; counter < length; counter++) { + temp_parity = temp_parity ^ (symbol & 1); + symbol = symbol >> 1; } - return( temp_parity ); + return (temp_parity); } -void tpc_common::rsc_enc_bit(int input, int state_in, std::vector<int> g, int KK, int nn, - std::vector< std::vector<int> > &outputVec, std::vector< std::vector<int> > &nextStateVec) { +void tpc_common::rsc_enc_bit(int input, + int state_in, + std::vector<int> g, + int KK, + int nn, + std::vector<std::vector<int>>& outputVec, + std::vector<std::vector<int>>& nextStateVec) +{ int state, i, out, a_k; // systematic output out = input; // determine feedback bit - a_k = input^tpc_common::parity_counter( g[0]&state_in, KK ); + a_k = input ^ tpc_common::parity_counter(g[0] & state_in, KK); // create a word made up of state and feedback bit - state = (a_k<<(KK-1))^state_in; + state = (a_k << (KK - 1)) ^ state_in; // AND the word with the generators - for (i=1;i<nn;i++) { + for (i = 1; i < nn; i++) { // update output symbol - out = (out<<1) + tpc_common::parity_counter( state&g[i], KK ); + out = (out << 1) + tpc_common::parity_counter(state & g[i], KK); } outputVec[input][state_in] = out; - nextStateVec[input][state_in] = (state>>1); + nextStateVec[input][state_in] = (state >> 1); } void tpc_common::precomputeStateTransitionMatrix_RSCPoly( - int numStates, - std::vector<int> g, - int KK, - int nn, - std::vector< std::vector<int> > &output, - std::vector< std::vector<int> > &nextStates) { - - for(int input=0; input<2; input++) { - for(int state=0; state<numStates; state++) { + int numStates, + std::vector<int> g, + int KK, + int nn, + std::vector<std::vector<int>>& output, + std::vector<std::vector<int>>& nextStates) +{ + + for (int input = 0; input < 2; input++) { + for (int state = 0; state < numStates; state++) { tpc_common::rsc_enc_bit(input, state, g, KK, nn, output, nextStates); } } } -void tpc_common::rsc_tail( std::vector<int> &tail_p, std::vector<int> g, int max_states, int mm ) { +void tpc_common::rsc_tail(std::vector<int>& tail_p, + std::vector<int> g, + int max_states, + int mm) +{ // Determine the tail for each state - for(int state=0;state<max_states;state++) { + for (int state = 0; state < max_states; state++) { // determine feedback word - tail_p[state] = tpc_common::parity_counter( g[0]&state, mm ); + tail_p[state] = tpc_common::parity_counter(g[0] & state, mm); } return; } -void tpc_common::itob(std::vector<int> &binVec, int symbol, int length) { +void tpc_common::itob(std::vector<int>& binVec, int symbol, int length) +{ /// Go through each bit in the vector - for (int counter=0;counter<length;counter++) { - binVec[length-counter-1] = (symbol&1); - symbol = symbol>>1; + for (int counter = 0; counter < length; counter++) { + binVec[length - counter - 1] = (symbol & 1); + symbol = symbol >> 1; } - } -} -} +} // namespace fec +} // namespace gr diff --git a/gr-fec/lib/tpc_decoder.cc b/gr-fec/lib/tpc_decoder.cc index 3381d55dc8..3477e30aab 100644 --- a/gr-fec/lib/tpc_decoder.cc +++ b/gr-fec/lib/tpc_decoder.cc @@ -30,57 +30,85 @@ #include <stdio.h> #include <vector> -#include <algorithm> // for std::reverse -#include <string.h> // for memcpy +#include <algorithm> // for std::reverse +#include <string.h> // for memcpy #include <gnuradio/fec/maxstar.h> namespace gr { - namespace fec { - -generic_decoder::sptr -tpc_decoder::make(std::vector<int> row_polys, std::vector<int> col_polys, int krow, int kcol, int bval, int qval, int max_iter, int decoder_type) +namespace fec { + +generic_decoder::sptr tpc_decoder::make(std::vector<int> row_polys, + std::vector<int> col_polys, + int krow, + int kcol, + int bval, + int qval, + int max_iter, + int decoder_type) { - return generic_decoder::sptr(new tpc_decoder(row_polys, col_polys, krow, kcol, bval, qval, max_iter, decoder_type)); + return generic_decoder::sptr(new tpc_decoder( + row_polys, col_polys, krow, kcol, bval, qval, max_iter, decoder_type)); } -tpc_decoder::tpc_decoder (std::vector<int> row_polys, std::vector<int> col_polys, int krow, int kcol, int bval, int qval, int max_iter, int decoder_type) - : generic_decoder("tpc_decoder"), d_rowpolys(row_polys), d_colpolys(col_polys), d_krow(krow), d_kcol(kcol), - d_bval(bval), d_qval(qval), d_max_iter(max_iter), d_decoder_type(decoder_type) +tpc_decoder::tpc_decoder(std::vector<int> row_polys, + std::vector<int> col_polys, + int krow, + int kcol, + int bval, + int qval, + int max_iter, + int decoder_type) + : generic_decoder("tpc_decoder"), + d_rowpolys(row_polys), + d_colpolys(col_polys), + d_krow(krow), + d_kcol(kcol), + d_bval(bval), + d_qval(qval), + d_max_iter(max_iter), + d_decoder_type(decoder_type) { // first we operate on data chunks of get_input_size() // TODO: should we verify this and throw an error if it doesn't match? YES // hwo do we do that? - rowEncoder_K = ceil(log(d_rowpolys[0])/log(2)); // rowEncoder_K is the constraint length of the row encoder polynomial + rowEncoder_K = ceil( + log(d_rowpolys[0]) / + log(2)); // rowEncoder_K is the constraint length of the row encoder polynomial rowEncoder_n = d_rowpolys.size(); rowEncoder_m = rowEncoder_K - 1; - colEncoder_K = ceil(log(d_colpolys[0])/log(2)); // colEncoder_K is the constraint length of the col encoder polynomial + colEncoder_K = ceil( + log(d_colpolys[0]) / + log(2)); // colEncoder_K is the constraint length of the col encoder polynomial colEncoder_n = d_colpolys.size(); colEncoder_m = colEncoder_K - 1; // calculate the input and output sizes - inputSize = ((d_krow+rowEncoder_m)*rowEncoder_n)*((d_kcol+colEncoder_m)*colEncoder_n) - d_bval; - outputSize = (d_krow*d_kcol - (d_bval+d_qval)); + inputSize = ((d_krow + rowEncoder_m) * rowEncoder_n) * + ((d_kcol + colEncoder_m) * colEncoder_n) - + d_bval; + outputSize = (d_krow * d_kcol - (d_bval + d_qval)); fp = NULL; - //DEBUG_PRINT("inputSize=%d outputSize=%d\n", inputSize, outputSize); - //fp = fopen("c_decoder_output.txt", "w"); + // DEBUG_PRINT("inputSize=%d outputSize=%d\n", inputSize, outputSize); + // fp = fopen("c_decoder_output.txt", "w"); - rowNumStates = 1 << (rowEncoder_m); // 2^(row_mm) - colNumStates = 1 << (colEncoder_m); // 2^(col_mm) - rowOutputs.resize(2, std::vector<int>(rowNumStates,0)); - rowNextStates.resize(2, std::vector<int>(rowNumStates,0)); - colOutputs.resize(2, std::vector<int>(colNumStates,0)); - colNextStates.resize(2, std::vector<int>(colNumStates,0));; + rowNumStates = 1 << (rowEncoder_m); // 2^(row_mm) + colNumStates = 1 << (colEncoder_m); // 2^(col_mm) + rowOutputs.resize(2, std::vector<int>(rowNumStates, 0)); + rowNextStates.resize(2, std::vector<int>(rowNumStates, 0)); + colOutputs.resize(2, std::vector<int>(colNumStates, 0)); + colNextStates.resize(2, std::vector<int>(colNumStates, 0)); + ; // precalculate the state transition matrix for the row polynomial - tpc_common::precomputeStateTransitionMatrix_RSCPoly(rowNumStates, d_rowpolys, rowEncoder_K, rowEncoder_n, - rowOutputs, rowNextStates); + tpc_common::precomputeStateTransitionMatrix_RSCPoly( + rowNumStates, d_rowpolys, rowEncoder_K, rowEncoder_n, rowOutputs, rowNextStates); // precalculate the state transition matrix for the column polynomial - tpc_common::precomputeStateTransitionMatrix_RSCPoly(colNumStates, d_colpolys, colEncoder_K, colEncoder_n, - colOutputs, colNextStates); + tpc_common::precomputeStateTransitionMatrix_RSCPoly( + colNumStates, d_colpolys, colEncoder_K, colEncoder_n, colOutputs, colNextStates); codeword_M = d_kcol + colEncoder_K - 1; codeword_N = d_krow + rowEncoder_K - 1; @@ -90,7 +118,7 @@ tpc_decoder::tpc_decoder (std::vector<int> row_polys, std::vector<int> col_polys channel_llr.resize(codeword_M, std::vector<float>(codeword_N, 0)); Z.resize(codeword_M, std::vector<float>(codeword_N, 0)); - extrinsic_info.resize(codeword_M*codeword_N, 0); + extrinsic_info.resize(codeword_M * codeword_N, 0); input_u_rows.resize(d_krow, 0); input_u_cols.resize(d_kcol, 0); @@ -100,59 +128,62 @@ tpc_decoder::tpc_decoder (std::vector<int> row_polys, std::vector<int> col_polys output_u_cols.resize(d_kcol, 0); output_c_rows.resize(codeword_N, 0); - output_c_cols.resize(codeword_M*codeword_N, 0); + output_c_cols.resize(codeword_M * codeword_N, 0); output_c_col_idx = 0; // setup the max_star function based on decoder type - switch(d_decoder_type) { - case 0: - max_star = &tpc_decoder::linear_log_map; - break; - case 1: - max_star = &tpc_decoder::max_log_map; - break; - case 2: - max_star = &tpc_decoder::constant_log_map; - break; - case 3: - max_star = &tpc_decoder::log_map_lut_correction; - break; - case 4: - max_star = &tpc_decoder::log_map_cfunction_correction; - break; - default: - max_star = &tpc_decoder::linear_log_map; - break; + switch (d_decoder_type) { + case 0: + max_star = &tpc_decoder::linear_log_map; + break; + case 1: + max_star = &tpc_decoder::max_log_map; + break; + case 2: + max_star = &tpc_decoder::constant_log_map; + break; + case 3: + max_star = &tpc_decoder::log_map_lut_correction; + break; + case 4: + max_star = &tpc_decoder::log_map_cfunction_correction; + break; + default: + max_star = &tpc_decoder::linear_log_map; + break; } - // declare the reverse sweep trellis - // the beta vector is logically laid out in memory as follows, assuming the - // following values (for educational purposes) - // defined: LL = 6, rowEncoder_K = 3, derived: mm_row=2, max_states_row=4, rowEncoder_n=1, num_symbols_row=2 - // state_idx - //------------------------------------------------------------------------- - // 0 B(0,0) <-- the calculated beta value at state=0, time=0 - // - // 1 B(0,1) - // - // 2 B(0,2) - // - // 3 B(0,3) - //------------------------------------------------------------------------- - //k(time) = 0 1 2 3 4 5 6 7 8 + // declare the reverse sweep trellis + // the beta vector is logically laid out in memory as follows, assuming the + // following values (for educational purposes) + // defined: LL = 6, rowEncoder_K = 3, derived: mm_row=2, max_states_row=4, + // rowEncoder_n=1, num_symbols_row=2 state_idx + //------------------------------------------------------------------------- + // 0 B(0,0) <-- the calculated beta value at state=0, time=0 + // + // 1 B(0,1) + // + // 2 B(0,2) + // + // 3 B(0,3) + //------------------------------------------------------------------------- + // k(time) = 0 1 2 3 4 5 6 7 8 // setup row siso decoder - mm_row = rowEncoder_K-1; // encoder memory - max_states_row = 1 << mm_row; // 2^mm_row - num_symbols_row = 1 << rowEncoder_n; // 2^rowEncoder_n + mm_row = rowEncoder_K - 1; // encoder memory + max_states_row = 1 << mm_row; // 2^mm_row + num_symbols_row = 1 << rowEncoder_n; // 2^rowEncoder_n - beta_row.resize(input_u_rows.size()+rowEncoder_K, std::vector<float>(max_states_row, 0)); + beta_row.resize(input_u_rows.size() + rowEncoder_K, + std::vector<float>(max_states_row, 0)); // forward sweep trellis for current time instant only (t=k) alpha_prime_row.resize(max_states_row, 0); // forward sweep trellis for next time instant only (t=k+1) alpha_row.resize(max_states_row, 0); - // likelihood vector that input_c[idx] corresponds to a symbol in the set of [0 ... num_symbols_row-1] + // likelihood vector that input_c[idx] corresponds to a symbol in the set of [0 ... + // num_symbols_row-1] metric_c_row.resize(num_symbols_row, 0); - // temporary vector to store the appropriate indexes of input_c that we want to test the likelihood of + // temporary vector to store the appropriate indexes of input_c that we want to test + // the likelihood of rec_array_row.resize(rowEncoder_n, 0); // log-likelihood ratios of the coded bit being a 1 num_llr_c_row.resize(rowEncoder_n, 0); @@ -161,49 +192,48 @@ tpc_decoder::tpc_decoder (std::vector<int> row_polys, std::vector<int> col_polys // setup column siso decoder - mm_col = colEncoder_K-1; // encoder memory - max_states_col = 1 << mm_col; // 2^mm_col - num_symbols_col = 1 << colEncoder_n; // 2^colEncoder_n - beta_col.resize(input_u_cols.size()+colEncoder_K, std::vector<float>(max_states_col, 0)); - // forward sweep trellis for current time instant only (t=k) - alpha_prime_col.resize(max_states_col, 0); - // forward sweep trellis for next time instant only (t=k+1) - alpha_col.resize(max_states_col, 0); - // likelihood vector that input_c[idx] corresponds to a symbol in the set of [0 ... num_symbols_col-1] - metric_c_col.resize(num_symbols_col, 0); - // temporary vector to store the appropriate indexes of input_c that we want to test the likelihood of - rec_array_col.resize(colEncoder_n, 0); - // log-likelihood ratios of the coded bit being a 1 - num_llr_c_col.resize(colEncoder_n, 0); - // log-likelihood ratios of the coded bit being a 0 - den_llr_c_col.resize(colEncoder_n, 0); - - mInit = (d_bval+d_qval)/d_krow; // integer division - nInit = (d_bval+d_qval) - mInit*d_krow; - - numInitLoadIter = d_bval/codeword_N; - numInitRemaining = d_bval - codeword_N*numInitLoadIter; + mm_col = colEncoder_K - 1; // encoder memory + max_states_col = 1 << mm_col; // 2^mm_col + num_symbols_col = 1 << colEncoder_n; // 2^colEncoder_n + beta_col.resize(input_u_cols.size() + colEncoder_K, + std::vector<float>(max_states_col, 0)); + // forward sweep trellis for current time instant only (t=k) + alpha_prime_col.resize(max_states_col, 0); + // forward sweep trellis for next time instant only (t=k+1) + alpha_col.resize(max_states_col, 0); + // likelihood vector that input_c[idx] corresponds to a symbol in the set of [0 ... + // num_symbols_col-1] + metric_c_col.resize(num_symbols_col, 0); + // temporary vector to store the appropriate indexes of input_c that we want to test + // the likelihood of + rec_array_col.resize(colEncoder_n, 0); + // log-likelihood ratios of the coded bit being a 1 + num_llr_c_col.resize(colEncoder_n, 0); + // log-likelihood ratios of the coded bit being a 0 + den_llr_c_col.resize(colEncoder_n, 0); -} + mInit = (d_bval + d_qval) / d_krow; // integer division + nInit = (d_bval + d_qval) - mInit * d_krow; -int tpc_decoder::get_output_size() { - return outputSize; + numInitLoadIter = d_bval / codeword_N; + numInitRemaining = d_bval - codeword_N * numInitLoadIter; } -int tpc_decoder::get_input_size() { - return inputSize; -} +int tpc_decoder::get_output_size() { return outputSize; } + +int tpc_decoder::get_input_size() { return inputSize; } // this code borrows heavily from CML library, please look @: // http://code.google.com/p/iscml // it has been refactored to work w/ gnuradio in C++ environment, // as well as some comments being added to help understand // exactly what is going on w/ the siso decoder -void tpc_decoder::siso_decode_row() { +void tpc_decoder::siso_decode_row() +{ int LL, state, k, ii, symbol, mask; float app_in, delta1, delta2; - LL = input_u_rows.size(); // code length + LL = input_u_rows.size(); // code length // log-likelihood ratio of the uncoded bit being a 1 float num_llr_u; @@ -217,114 +247,122 @@ void tpc_decoder::siso_decode_row() { // for(state=1; state<max_states_row; state++) { // beta_row[LL+rowEncoder_K-1][state] = -MAXLOG; // } - // filling w/ 0xCC yields a value close to -MAXLOG, and memset is faster than for loops - memset(&beta_row[LL+rowEncoder_K-1][1], 0xCC, sizeof(float)*(max_states_row-1)); + // filling w/ 0xCC yields a value close to -MAXLOG, and memset is faster than for + // loops + memset( + &beta_row[LL + rowEncoder_K - 1][1], 0xCC, sizeof(float) * (max_states_row - 1)); - // initialize alpha_prime_row (current time instant), alpha_prime_row then gets updated - // by shifting in alpha_row at the end of each time instant of processing + // initialize alpha_prime_row (current time instant), alpha_prime_row then gets + // updated by shifting in alpha_row at the end of each time instant of processing // alpha_row needs to get initialized at the beginning of each processing loop, so we // initialize alpha_row in the forward sweep processing loop // the initialization below is saying that the likelihood of starting at state=0 is // 100%, b/c state 1, 2, 3's likelihoods are basically -inf - // as with the beta_row array, this implies that the forward trellis started at state=0 + // as with the beta_row array, this implies that the forward trellis started at + // state=0 // for (state=1;state<max_states_row;state++) { // alpha_prime_row[state] = -MAXLOG; // } - memset(&alpha_prime_row[1], 0xCC, sizeof(float)*(max_states_row-1)); - - // compute the beta_row matrix first, which is the reverse sweep (hence we start at the last - // time instant-1 and work our way back to t=0). we start at last time instant-1 b/c - // we already filled in beta_row values for the last time instant, forcing the trellis to - // start at state=0 -// DEBUG_PRINT("LL=%d KK=%d mm=%d\n", LL, rowEncoder_K, mm_row); -// DEBUG_PRINT_F(fp, "LL=%d KK=%d mm=%d\n", LL, rowEncoder_K, mm_row); - for (k=(LL+(rowEncoder_K-1)-1); k>=0; k--) { + memset(&alpha_prime_row[1], 0xCC, sizeof(float) * (max_states_row - 1)); + + // compute the beta_row matrix first, which is the reverse sweep (hence we start at + // the last time instant-1 and work our way back to t=0). we start at last time + // instant-1 b/c we already filled in beta_row values for the last time instant, + // forcing the trellis to start at state=0 + // DEBUG_PRINT("LL=%d KK=%d mm=%d\n", LL, rowEncoder_K, mm_row); + // DEBUG_PRINT_F(fp, "LL=%d KK=%d mm=%d\n", LL, rowEncoder_K, mm_row); + for (k = (LL + (rowEncoder_K - 1) - 1); k >= 0; k--) { // TODO: figure out why this is needed? I'm still confused by this - if (k<LL) { + if (k < LL) { app_in = input_u_rows[k]; - } - else { + } else { app_in = 0; } // get the input associated w/ this time instant - memcpy(&rec_array_row[0], &input_c_rows[rowEncoder_n*k], sizeof(float)*rowEncoder_n); - -// DEBUG_PRINT("k=%d\n", k); -// DEBUG_PRINT_F(fp, "k=%d\n", k); -// -// DEBUG_PRINT("rec_array -->\n"); -// DEBUG_PRINT_FLOAT_ARRAY_AS_FLOAT(&rec_array_row[0], rec_array_row.size()); -// DEBUG_PRINT_F(fp, "rec_array -->\n"); -// DEBUG_PRINT_FLOAT_ARRAY_AS_FLOAT_F(fp, &rec_array_row[0], rec_array_row.size()); + memcpy(&rec_array_row[0], + &input_c_rows[rowEncoder_n * k], + sizeof(float) * rowEncoder_n); + + // DEBUG_PRINT("k=%d\n", k); + // DEBUG_PRINT_F(fp, "k=%d\n", k); + // + // DEBUG_PRINT("rec_array -->\n"); + // DEBUG_PRINT_FLOAT_ARRAY_AS_FLOAT(&rec_array_row[0], + // rec_array_row.size()); DEBUG_PRINT_F(fp, "rec_array -->\n"); + // DEBUG_PRINT_FLOAT_ARRAY_AS_FLOAT_F(fp, &rec_array_row[0], + // rec_array_row.size()); // for each input at this time instant, create a metric which // represents the likelihood that this input corresponds to // each of the possible symbols - for(symbol=0; symbol<num_symbols_row; symbol++) { + for (symbol = 0; symbol < num_symbols_row; symbol++) { metric_c_row[symbol] = gamma(rec_array_row, symbol); } -// DEBUG_PRINT("metric_c -->\n"); -// DEBUG_PRINT_FLOAT_ARRAY_AS_FLOAT(&metric_c_row[0], metric_c_row.size()); -// DEBUG_PRINT_F(fp, "metric_c -->\n"); -// DEBUG_PRINT_FLOAT_ARRAY_AS_FLOAT_F(fp, &metric_c_row[0], metric_c_row.size()); + // DEBUG_PRINT("metric_c -->\n"); + // DEBUG_PRINT_FLOAT_ARRAY_AS_FLOAT(&metric_c_row[0], + // metric_c_row.size()); DEBUG_PRINT_F(fp, "metric_c -->\n"); + // DEBUG_PRINT_FLOAT_ARRAY_AS_FLOAT_F(fp, &metric_c_row[0], + // metric_c_row.size()); // step through all states -- populating the beta_row values for each node // in the trellis diagram as shown above w/ the maximum-likelihood // of this current node coming from the previous node - for ( state=0; state< max_states_row; state++ ) { + for (state = 0; state < max_states_row; state++) { // data 0 branch - delta1 = beta_row[k+1][rowNextStates[0][state]] + metric_c_row[rowOutputs[0][state]]; + delta1 = beta_row[k + 1][rowNextStates[0][state]] + + metric_c_row[rowOutputs[0][state]]; // data 1 branch - delta2 = beta_row[k+1][rowNextStates[1][state]] + metric_c_row[rowOutputs[1][state]] + app_in; + delta2 = beta_row[k + 1][rowNextStates[1][state]] + + metric_c_row[rowOutputs[1][state]] + app_in; // update beta_row beta_row[k][state] = (*this.*max_star)(delta1, delta2); -// DEBUG_PRINT("delta1=%f delta2=%f beta=%f\n", delta1, delta2, beta_row[k][state]); -// DEBUG_PRINT_F(fp, "delta1=%f delta2=%f beta=%f\n", delta1, delta2, beta_row[k][state]); + // DEBUG_PRINT("delta1=%f delta2=%f beta=%f\n", delta1, delta2, + // beta_row[k][state]); DEBUG_PRINT_F(fp, "delta1=%f delta2=%f + // beta=%f\n", delta1, delta2, beta_row[k][state]); } // normalize beta_row - for (state=1;state<max_states_row;state++) { - beta_row[k][state] = beta_row[k][state] - beta_row[k][0]; + for (state = 1; state < max_states_row; state++) { + beta_row[k][state] = beta_row[k][state] - beta_row[k][0]; } beta_row[k][0] = 0; - } // compute the forward sweep (alpha_row values), and update the llr's // notice that we start at time index=1, b/c time index=0 has already been // initialized, and we are forcing the trellis to start from state=0 - for(k=1; k<LL+rowEncoder_K; k++) { + for (k = 1; k < LL + rowEncoder_K; k++) { // initialize the llr's for the uncoded bits num_llr_u = -MAXLOG; den_llr_u = -MAXLOG; // initialize alpha_row -// for (state=0;state<max_states_row;state++) { -// alpha_row[state] = -MAXLOG; -// } - memset(&alpha_row[0], 0xCC, max_states_row*sizeof(float)); + // for (state=0;state<max_states_row;state++) { + // alpha_row[state] = -MAXLOG; + // } + memset(&alpha_row[0], 0xCC, max_states_row * sizeof(float)); // assign inputs - if (k-1 < LL) - app_in = input_u_rows[k-1]; + if (k - 1 < LL) + app_in = input_u_rows[k - 1]; else app_in = 0; // initialize the llr's for the coded bits, and get the correct // input bits for this time instant - for (ii=0;ii<rowEncoder_n;ii++) { + for (ii = 0; ii < rowEncoder_n; ii++) { den_llr_c_row[ii] = -MAXLOG; num_llr_c_row[ii] = -MAXLOG; - rec_array_row[ii] = input_c_rows[rowEncoder_n*(k-1)+ii]; + rec_array_row[ii] = input_c_rows[rowEncoder_n * (k - 1) + ii]; } // for each input at this time instant, create a metric which // represents the likelihood that this input corresponds to // each of the possible symbols - for(symbol=0; symbol<num_symbols_row; symbol++) { + for (symbol = 0; symbol < num_symbols_row; symbol++) { metric_c_row[ii] = gamma(rec_array_row, symbol); } @@ -338,11 +376,11 @@ void tpc_decoder::siso_decode_row() { // we are looping over, and delta2 represents a transition from the previous // time instant to the current time instant for input (either 0 or 1) that // we've already calculated. Essentially, b/c we can have multiple possible - // transitions into the current alpha_row node of interest, and we need to store the - // maximum likelihood of all those transitions, we keep delta2 as a previously + // transitions into the current alpha_row node of interest, and we need to store + // the maximum likelihood of all those transitions, we keep delta2 as a previously // calculated transition, and then take the max* of that, which can be thought // of as a maximum (in the MAX-LOG-MAP approximation) - for ( state=0; state<max_states_row; state++ ) { + for (state = 0; state < max_states_row; state++) { // Data 0 branch delta1 = alpha_prime_row[state] + metric_c_row[rowOutputs[0][state]]; delta2 = alpha_row[rowNextStates[0][state]]; @@ -355,16 +393,17 @@ void tpc_decoder::siso_decode_row() { } // compute the llr's - for (state=0;state<max_states_row;state++) { + for (state = 0; state < max_states_row; state++) { // data 0 branch (departing) - delta1 = alpha_prime_row[state] + metric_c_row[rowOutputs[0][state]] + beta_row[k][rowNextStates[0][state]]; + delta1 = alpha_prime_row[state] + metric_c_row[rowOutputs[0][state]] + + beta_row[k][rowNextStates[0][state]]; // the information bit delta2 = den_llr_u; den_llr_u = (*this.*max_star)(delta1, delta2); - mask = 1<<(rowEncoder_n-1); + mask = 1 << (rowEncoder_n - 1); // go through all the code bits - for (ii=0;ii<rowEncoder_n;ii++) { - if ( rowOutputs[0][state]&mask ) { + for (ii = 0; ii < rowEncoder_n; ii++) { + if (rowOutputs[0][state] & mask) { // this code bit 1 delta2 = num_llr_c_row[ii]; num_llr_c_row[ii] = (*this.*max_star)(delta1, delta2); @@ -373,18 +412,19 @@ void tpc_decoder::siso_decode_row() { delta2 = den_llr_c_row[ii]; den_llr_c_row[ii] = (*this.*max_star)(delta1, delta2); } - mask = mask>>1; + mask = mask >> 1; } // data 1 branch (departing) - delta1 = alpha_prime_row[state] + metric_c_row[rowOutputs[1][state]] + beta_row[k][rowNextStates[1][state]] + app_in; + delta1 = alpha_prime_row[state] + metric_c_row[rowOutputs[1][state]] + + beta_row[k][rowNextStates[1][state]] + app_in; // the information bit delta2 = num_llr_u; num_llr_u = (*this.*max_star)(delta1, delta2); - mask = 1<<(rowEncoder_n-1); + mask = 1 << (rowEncoder_n - 1); // go through all the code bits - for (ii=0;ii<rowEncoder_n;ii++) { - if ( rowOutputs[1][state]&mask ) { + for (ii = 0; ii < rowEncoder_n; ii++) { + if (rowOutputs[1][state] & mask) { // this code bit 1 delta2 = num_llr_c_row[ii]; num_llr_c_row[ii] = (*this.*max_star)(delta1, delta2); @@ -393,7 +433,7 @@ void tpc_decoder::siso_decode_row() { delta2 = den_llr_c_row[ii]; den_llr_c_row[ii] = (*this.*max_star)(delta1, delta2); } - mask = mask>>1; + mask = mask >> 1; } // shift alpha_row back to alpha_prime_row @@ -401,19 +441,23 @@ void tpc_decoder::siso_decode_row() { } // assign uncoded outputs - if (k-1<LL) { - output_u_rows[k-1] = num_llr_u - den_llr_u; + if (k - 1 < LL) { + output_u_rows[k - 1] = num_llr_u - den_llr_u; } // assign coded outputs - volk_32f_x2_subtract_32f(&output_c_rows[rowEncoder_n*(k-1)], &num_llr_c_row[0], &den_llr_c_row[0], rowEncoder_n); + volk_32f_x2_subtract_32f(&output_c_rows[rowEncoder_n * (k - 1)], + &num_llr_c_row[0], + &den_llr_c_row[0], + rowEncoder_n); } } -void tpc_decoder::siso_decode_col() { +void tpc_decoder::siso_decode_col() +{ int LL, state, k, ii, symbol, mask; float app_in, delta1, delta2; - LL = input_u_cols.size(); // code length + LL = input_u_cols.size(); // code length // log-likelihood ratio of the uncoded bit being a 1 float num_llr_u; @@ -424,116 +468,123 @@ void tpc_decoder::siso_decode_col() { // this initialization is saying that the likelihood that the reverse sweep // starts at state=0 is 100%, b/c state 1, 2, 3's likelihood's are basically -inf // this implies that the forward trellis terminated at the 0 state -// for(state=1; state<max_states_col; state++) { -// beta_col[LL+colEncoder_K-1][state] = -MAXLOG; -// } - memset(&beta_col[LL+colEncoder_K-1][1], 0xCC, sizeof(float)*(max_states_col-1)); + // for(state=1; state<max_states_col; state++) { + // beta_col[LL+colEncoder_K-1][state] = -MAXLOG; + // } + memset( + &beta_col[LL + colEncoder_K - 1][1], 0xCC, sizeof(float) * (max_states_col - 1)); - // initialize alpha_prime_col (current time instant), alpha_prime_col then gets updated - // by shifting in alpha_col at the end of each time instant of processing + // initialize alpha_prime_col (current time instant), alpha_prime_col then gets + // updated by shifting in alpha_col at the end of each time instant of processing // alpha_col needs to get initialized at the beginning of each processing loop, so we // initialize alpha_col in the forward sweep processing loop // the initialization below is saying that the likelihood of starting at state=0 is // 100%, b/c state 1, 2, 3's likelihoods are basically -inf - // as with the beta_col array, this implies that the forward trellis started at state=0 -// for (state=1;state<max_states_col;state++) { -// alpha_prime_col[state] = -MAXLOG; -// } - memset(&alpha_prime_col[1], 0xCC, sizeof(float)*(max_states_col-1)); - - // compute the beta_col matrix first, which is the reverse sweep (hence we start at the last - // time instant-1 and work our way back to t=0). we start at last time instant-1 b/c - // we already filled in beta_col values for the last time instant, forcing the trellis to - // start at state=0 -// DEBUG_PRINT("LL=%d KK=%d mm=%d\n", LL, colEncoder_K, mm_col); -// DEBUG_PRINT_F(fp, "LL=%d KK=%d mm=%d\n", LL, colEncoder_K, mm_col); - for (k=(LL+(colEncoder_K-1)-1); k>=0; k--) { + // as with the beta_col array, this implies that the forward trellis started at + // state=0 + // for (state=1;state<max_states_col;state++) { + // alpha_prime_col[state] = -MAXLOG; + // } + memset(&alpha_prime_col[1], 0xCC, sizeof(float) * (max_states_col - 1)); + + // compute the beta_col matrix first, which is the reverse sweep (hence we start at + // the last time instant-1 and work our way back to t=0). we start at last time + // instant-1 b/c we already filled in beta_col values for the last time instant, + // forcing the trellis to start at state=0 + // DEBUG_PRINT("LL=%d KK=%d mm=%d\n", LL, colEncoder_K, mm_col); + // DEBUG_PRINT_F(fp, "LL=%d KK=%d mm=%d\n", LL, colEncoder_K, mm_col); + for (k = (LL + (colEncoder_K - 1) - 1); k >= 0; k--) { // TODO: figure out why this is needed? I'm still confused by this - if (k<LL) { + if (k < LL) { app_in = input_u_cols[k]; - } - else { + } else { app_in = 0; } // get the input associated w/ this time instant - memcpy(&rec_array_col[0], &input_c_cols[colEncoder_n*k], sizeof(float)*colEncoder_n); - -// DEBUG_PRINT("k=%d\n", k); -// DEBUG_PRINT_F(fp, "k=%d\n", k); -// -// DEBUG_PRINT("rec_array -->\n"); -// DEBUG_PRINT_FLOAT_ARRAY_AS_FLOAT(&rec_array[0], rec_array_col.size()); -// DEBUG_PRINT_F(fp, "rec_array -->\n"); -// DEBUG_PRINT_FLOAT_ARRAY_AS_FLOAT_F(fp, &rec_array[0], rec_array_col.size()); + memcpy(&rec_array_col[0], + &input_c_cols[colEncoder_n * k], + sizeof(float) * colEncoder_n); + + // DEBUG_PRINT("k=%d\n", k); + // DEBUG_PRINT_F(fp, "k=%d\n", k); + // + // DEBUG_PRINT("rec_array -->\n"); + // DEBUG_PRINT_FLOAT_ARRAY_AS_FLOAT(&rec_array[0], rec_array_col.size()); + // DEBUG_PRINT_F(fp, "rec_array -->\n"); + // DEBUG_PRINT_FLOAT_ARRAY_AS_FLOAT_F(fp, &rec_array[0], + // rec_array_col.size()); // for each input at this time instant, create a metric which // represents the likelihood that this input corresponds to // each of the possible symbols - for(symbol=0; symbol<num_symbols_col; symbol++) { + for (symbol = 0; symbol < num_symbols_col; symbol++) { metric_c_col[symbol] = gamma(rec_array_col, symbol); } -// DEBUG_PRINT("metric_c -->\n"); -// DEBUG_PRINT_FLOAT_ARRAY_AS_FLOAT(&metric_c_col[0], metric_c_col.size()); -// DEBUG_PRINT_F(fp, "metric_c -->\n"); -// DEBUG_PRINT_FLOAT_ARRAY_AS_FLOAT_F(fp, &metric_c_col[0], metric_c_col.size()); + // DEBUG_PRINT("metric_c -->\n"); + // DEBUG_PRINT_FLOAT_ARRAY_AS_FLOAT(&metric_c_col[0], + // metric_c_col.size()); DEBUG_PRINT_F(fp, "metric_c -->\n"); + // DEBUG_PRINT_FLOAT_ARRAY_AS_FLOAT_F(fp, &metric_c_col[0], + // metric_c_col.size()); // step through all states -- populating the beta_col values for each node // in the trellis diagram as shown above w/ the maximum-likelihood // of this current node coming from the previous node - for ( state=0; state< max_states_col; state++ ) { + for (state = 0; state < max_states_col; state++) { // data 0 branch - delta1 = beta_col[k+1][colNextStates[0][state]] + metric_c_col[colOutputs[0][state]]; + delta1 = beta_col[k + 1][colNextStates[0][state]] + + metric_c_col[colOutputs[0][state]]; // data 1 branch - delta2 = beta_col[k+1][colNextStates[1][state]] + metric_c_col[colOutputs[1][state]] + app_in; + delta2 = beta_col[k + 1][colNextStates[1][state]] + + metric_c_col[colOutputs[1][state]] + app_in; // update beta_col beta_col[k][state] = (*this.*max_star)(delta1, delta2); -// DEBUG_PRINT("delta1=%f delta2=%f beta=%f\n", delta1, delta2, beta_col[k][state]); -// DEBUG_PRINT_F(fp, "delta1=%f delta2=%f beta=%f\n", delta1, delta2, beta_col[k][state]); + // DEBUG_PRINT("delta1=%f delta2=%f beta=%f\n", delta1, delta2, + // beta_col[k][state]); DEBUG_PRINT_F(fp, "delta1=%f delta2=%f + // beta=%f\n", delta1, delta2, beta_col[k][state]); } // normalize beta_col - for (state=1;state<max_states_col;state++) { - beta_col[k][state] = beta_col[k][state] - beta_col[k][0]; + for (state = 1; state < max_states_col; state++) { + beta_col[k][state] = beta_col[k][state] - beta_col[k][0]; } beta_col[k][0] = 0; - } // compute the forward sweep (alpha_col values), and update the llr's // notice that we start at time index=1, b/c time index=0 has already been // initialized, and we are forcing the trellis to start from state=0 - for(k=1; k<LL+colEncoder_K; k++) { + for (k = 1; k < LL + colEncoder_K; k++) { // initialize the llr's for the uncoded bits num_llr_u = -MAXLOG; den_llr_u = -MAXLOG; // initialize alpha_col -// for (state=0;state<max_states_col;state++) { -// alpha_col[state] = -MAXLOG; -// } - memset(&alpha_col[0], 0xCC, max_states_col*sizeof(float)); + // for (state=0;state<max_states_col;state++) { + // alpha_col[state] = -MAXLOG; + // } + memset(&alpha_col[0], 0xCC, max_states_col * sizeof(float)); // assign inputs - if (k-1 < LL) - app_in = input_u_cols[k-1]; + if (k - 1 < LL) + app_in = input_u_cols[k - 1]; else app_in = 0; // initialize the llr's for the coded bits, and get the correct // input bits for this time instant - for (ii=0;ii<colEncoder_n;ii++) { + for (ii = 0; ii < colEncoder_n; ii++) { den_llr_c_col[ii] = -MAXLOG; num_llr_c_col[ii] = -MAXLOG; - rec_array_col[ii] = input_c_cols[colEncoder_n*(k-1)+ii]; + rec_array_col[ii] = input_c_cols[colEncoder_n * (k - 1) + ii]; } // for each input at this time instant, create a metric which // represents the likelihood that this input corresponds to // each of the possible symbols - for(symbol=0; symbol<num_symbols_col; symbol++) { + for (symbol = 0; symbol < num_symbols_col; symbol++) { metric_c_col[ii] = gamma(rec_array_col, symbol); } @@ -547,11 +598,11 @@ void tpc_decoder::siso_decode_col() { // we are looping over, and delta2 represents a transition from the previous // time instant to the current time instant for input (either 0 or 1) that // we've already calculated. Essentially, b/c we can have multiple possible - // transitions into the current alpha_col node of interest, and we need to store the - // maximum likelihood of all those transitions, we keep delta2 as a previously + // transitions into the current alpha_col node of interest, and we need to store + // the maximum likelihood of all those transitions, we keep delta2 as a previously // calculated transition, and then take the max* of that, which can be thought // of as a maximum (in the MAX-LOG-MAP approximation) - for ( state=0; state<max_states_col; state++ ) { + for (state = 0; state < max_states_col; state++) { // Data 0 branch delta1 = alpha_prime_col[state] + metric_c_col[colOutputs[0][state]]; delta2 = alpha_col[colNextStates[0][state]]; @@ -564,16 +615,17 @@ void tpc_decoder::siso_decode_col() { } // compute the llr's - for (state=0;state<max_states_col;state++) { + for (state = 0; state < max_states_col; state++) { // data 0 branch (departing) - delta1 = alpha_prime_col[state] + metric_c_col[colOutputs[0][state]] + beta_col[k][colNextStates[0][state]]; + delta1 = alpha_prime_col[state] + metric_c_col[colOutputs[0][state]] + + beta_col[k][colNextStates[0][state]]; // the information bit delta2 = den_llr_u; den_llr_u = (*this.*max_star)(delta1, delta2); - mask = 1<<(colEncoder_n-1); + mask = 1 << (colEncoder_n - 1); // go through all the code bits - for (ii=0;ii<colEncoder_n;ii++) { - if ( colOutputs[0][state]&mask ) { + for (ii = 0; ii < colEncoder_n; ii++) { + if (colOutputs[0][state] & mask) { // this code bit 1 delta2 = num_llr_c_col[ii]; num_llr_c_col[ii] = (*this.*max_star)(delta1, delta2); @@ -582,18 +634,19 @@ void tpc_decoder::siso_decode_col() { delta2 = den_llr_c_col[ii]; den_llr_c_col[ii] = (*this.*max_star)(delta1, delta2); } - mask = mask>>1; + mask = mask >> 1; } // data 1 branch (departing) - delta1 = alpha_prime_col[state] + metric_c_col[colOutputs[1][state]] + beta_col[k][colNextStates[1][state]] + app_in; + delta1 = alpha_prime_col[state] + metric_c_col[colOutputs[1][state]] + + beta_col[k][colNextStates[1][state]] + app_in; // the information bit delta2 = num_llr_u; num_llr_u = (*this.*max_star)(delta1, delta2); - mask = 1<<(colEncoder_n-1); + mask = 1 << (colEncoder_n - 1); // go through all the code bits - for (ii=0;ii<colEncoder_n;ii++) { - if ( colOutputs[1][state]&mask ) { + for (ii = 0; ii < colEncoder_n; ii++) { + if (colOutputs[1][state] & mask) { // this code bit 1 delta2 = num_llr_c_col[ii]; num_llr_c_col[ii] = (*this.*max_star)(delta1, delta2); @@ -602,7 +655,7 @@ void tpc_decoder::siso_decode_col() { delta2 = den_llr_c_col[ii]; den_llr_c_col[ii] = (*this.*max_star)(delta1, delta2); } - mask = mask>>1; + mask = mask >> 1; } // shift alpha_col back to alpha_prime_col @@ -610,303 +663,320 @@ void tpc_decoder::siso_decode_col() { } // assign uncoded outputs - if (k-1<LL) { - output_u_cols[k-1] = num_llr_u - den_llr_u; + if (k - 1 < LL) { + output_u_cols[k - 1] = num_llr_u - den_llr_u; } // assign coded outputs - volk_32f_x2_subtract_32f(&output_c_cols[output_c_col_idx+rowEncoder_n*(k-1)], &num_llr_c_col[0], &den_llr_c_col[0], colEncoder_n); + volk_32f_x2_subtract_32f( + &output_c_cols[output_c_col_idx + rowEncoder_n * (k - 1)], + &num_llr_c_col[0], + &den_llr_c_col[0], + colEncoder_n); } } -float tpc_decoder::linear_log_map(const float delta1, const float delta2) { +float tpc_decoder::linear_log_map(const float delta1, const float delta2) +{ float diff; diff = delta2 - delta1; - if ( diff > TJIAN ) - return( delta2 ); - else if ( diff < -TJIAN ) - return( delta1 ); - else if ( diff > 0 ) - return( delta2 + AJIAN*(diff-TJIAN) ); + if (diff > TJIAN) + return (delta2); + else if (diff < -TJIAN) + return (delta1); + else if (diff > 0) + return (delta2 + AJIAN * (diff - TJIAN)); else - return( delta1 - AJIAN*(diff+TJIAN) ); + return (delta1 - AJIAN * (diff + TJIAN)); } // MAX-LOG-MAP approximation -float tpc_decoder::max_log_map(const float delta1, const float delta2) { - if(delta1>delta2) return delta1; +float tpc_decoder::max_log_map(const float delta1, const float delta2) +{ + if (delta1 > delta2) + return delta1; return delta2; } -float tpc_decoder::constant_log_map(const float delta1, const float delta2) { +float tpc_decoder::constant_log_map(const float delta1, const float delta2) +{ // Return maximum of delta1 and delta2 // and in correction value if |delta1-delta2| < TVALUE register float diff; diff = delta2 - delta1; - if ( diff > TVALUE ) - return( delta2 ); - else if ( diff < -TVALUE ) - return( delta1 ); - else if ( diff > 0 ) - return( delta2 + CVALUE ); + if (diff > TVALUE) + return (delta2); + else if (diff < -TVALUE) + return (delta1); + else if (diff > 0) + return (delta2 + CVALUE); else - return( delta1 + CVALUE ); + return (delta1 + CVALUE); } -float tpc_decoder::log_map_lut_correction(const float delta1, const float delta2) { +float tpc_decoder::log_map_lut_correction(const float delta1, const float delta2) +{ float diff; - diff = (float) fabs( delta2 - delta1 ); + diff = (float)fabs(delta2 - delta1); if (delta1 > delta2) { - if (diff > BOUNDARY8 ) - return( delta1 ); - else if ( diff > BOUNDARY4 ) { - if (diff > BOUNDARY6 ) { - if ( diff > BOUNDARY7 ) - return( delta1 + VALUE7 + SLOPE7*(diff-BOUNDARY7) ); + if (diff > BOUNDARY8) + return (delta1); + else if (diff > BOUNDARY4) { + if (diff > BOUNDARY6) { + if (diff > BOUNDARY7) + return (delta1 + VALUE7 + SLOPE7 * (diff - BOUNDARY7)); else - return( delta1 + VALUE6 + SLOPE6*(diff-BOUNDARY6) ); + return (delta1 + VALUE6 + SLOPE6 * (diff - BOUNDARY6)); } else { - if ( diff > BOUNDARY5 ) - return( delta1 + VALUE5 + SLOPE5*(diff-BOUNDARY5) ); + if (diff > BOUNDARY5) + return (delta1 + VALUE5 + SLOPE5 * (diff - BOUNDARY5)); else - return( delta1 + VALUE4 + SLOPE4*(diff-BOUNDARY4) ); + return (delta1 + VALUE4 + SLOPE4 * (diff - BOUNDARY4)); } } else { - if (diff > BOUNDARY2 ) { - if ( diff > BOUNDARY3 ) - return( delta1 + VALUE3 + SLOPE3*(diff-BOUNDARY3) ); + if (diff > BOUNDARY2) { + if (diff > BOUNDARY3) + return (delta1 + VALUE3 + SLOPE3 * (diff - BOUNDARY3)); else - return( delta1 + VALUE2 + SLOPE2*(diff-BOUNDARY2) ); + return (delta1 + VALUE2 + SLOPE2 * (diff - BOUNDARY2)); } else { - if ( diff > BOUNDARY1 ) - return( delta1 + VALUE1 + SLOPE1*(diff-BOUNDARY1) ); + if (diff > BOUNDARY1) + return (delta1 + VALUE1 + SLOPE1 * (diff - BOUNDARY1)); else - return( delta1 + VALUE0 + SLOPE0*(diff-BOUNDARY0) ); + return (delta1 + VALUE0 + SLOPE0 * (diff - BOUNDARY0)); } } } else { - if (diff > BOUNDARY8 ) - return( delta2 ); - else if ( diff > BOUNDARY4 ) { - if (diff > BOUNDARY6 ) { - if ( diff > BOUNDARY7 ) - return( delta2 + VALUE7 + SLOPE7*(diff-BOUNDARY7) ); + if (diff > BOUNDARY8) + return (delta2); + else if (diff > BOUNDARY4) { + if (diff > BOUNDARY6) { + if (diff > BOUNDARY7) + return (delta2 + VALUE7 + SLOPE7 * (diff - BOUNDARY7)); else - return( delta2 + VALUE6 + SLOPE6*(diff-BOUNDARY6) ); + return (delta2 + VALUE6 + SLOPE6 * (diff - BOUNDARY6)); } else { - if ( diff > BOUNDARY5 ) - return( delta2 + VALUE5 + SLOPE5*(diff-BOUNDARY5) ); + if (diff > BOUNDARY5) + return (delta2 + VALUE5 + SLOPE5 * (diff - BOUNDARY5)); else - return( delta2 + VALUE4 + SLOPE4*(diff-BOUNDARY4) ); + return (delta2 + VALUE4 + SLOPE4 * (diff - BOUNDARY4)); } } else { - if (diff > BOUNDARY2 ) { - if ( diff > BOUNDARY3 ) - return( delta2 + VALUE3 + SLOPE3*(diff-BOUNDARY3) ); + if (diff > BOUNDARY2) { + if (diff > BOUNDARY3) + return (delta2 + VALUE3 + SLOPE3 * (diff - BOUNDARY3)); else - return( delta2 + VALUE2 + SLOPE2*(diff-BOUNDARY2) ); + return (delta2 + VALUE2 + SLOPE2 * (diff - BOUNDARY2)); } else { - if ( diff > BOUNDARY1 ) - return( delta2 + VALUE1 + SLOPE1*(diff-BOUNDARY1) ); + if (diff > BOUNDARY1) + return (delta2 + VALUE1 + SLOPE1 * (diff - BOUNDARY1)); else - return( delta2 + VALUE0 + SLOPE0*(diff-BOUNDARY0) ); + return (delta2 + VALUE0 + SLOPE0 * (diff - BOUNDARY0)); } } } } -float tpc_decoder::log_map_cfunction_correction(const float delta1, const float delta2) { +float tpc_decoder::log_map_cfunction_correction(const float delta1, const float delta2) +{ // Use C-function calls to compute the correction function if (delta1 > delta2) { - return( (float) (delta1 + log( 1 + exp( delta2-delta1) ) ) ); - } else { - return( (float) (delta2 + log( 1 + exp( delta1-delta2) ) ) ); + return ((float)(delta1 + log(1 + exp(delta2 - delta1)))); + } else { + return ((float)(delta2 + log(1 + exp(delta1 - delta2)))); } } -float tpc_decoder::gamma(const std::vector<float> rx_array, const int symbol) { +float tpc_decoder::gamma(const std::vector<float> rx_array, const int symbol) +{ float rm = 0; int ii; int mask; int nn = rx_array.size(); mask = 1; - for (ii=0;ii<nn;ii++) { - if (symbol&mask) - rm += rx_array[nn-ii-1]; - mask = mask<<1; + for (ii = 0; ii < nn; ii++) { + if (symbol & mask) + rm += rx_array[nn - ii - 1]; + mask = mask << 1; } -// DEBUG_PRINT("nn=%d symbol=%d rm = %f\n", nn, symbol, rm); -// DEBUG_PRINT_F(fp, "nn=%d symbol=%d rm = %f\n", nn, symbol, rm); + // DEBUG_PRINT("nn=%d symbol=%d rm = %f\n", nn, symbol, rm); + // DEBUG_PRINT_F(fp, "nn=%d symbol=%d rm = %f\n", nn, symbol, rm); - return(rm); + return (rm); } -template <typename T> int tpc_decoder::sgn(T val) { +template <typename T> +int tpc_decoder::sgn(T val) +{ return (T(0) < val) - (val < T(0)); } -void tpc_decoder::generic_work(void *inBuffer, void *outBuffer) { - const float *inPtr = (const float *) inBuffer; - unsigned char *out = (unsigned char *) outBuffer; +void tpc_decoder::generic_work(void* inBuffer, void* outBuffer) +{ + const float* inPtr = (const float*)inBuffer; + unsigned char* out = (unsigned char*)outBuffer; unsigned int m, n, ii; int iter; - for(ii=0; ii<numInitLoadIter; ii++) { - memset(&channel_llr[ii][0], 0, sizeof(float)*codeword_N); - memset(&Z[ii][0], 0, sizeof(float)*codeword_N); + for (ii = 0; ii < numInitLoadIter; ii++) { + memset(&channel_llr[ii][0], 0, sizeof(float) * codeword_N); + memset(&Z[ii][0], 0, sizeof(float) * codeword_N); + } + memset(&channel_llr[ii][0], 0, sizeof(float) * numInitRemaining); + memset(&Z[ii][0], 0, sizeof(float) * numInitRemaining); + memcpy(&channel_llr[ii][numInitRemaining], + &inPtr[0], + (codeword_N - numInitRemaining) * sizeof(float)); + memcpy(&Z[ii][numInitRemaining], + &inPtr[0], + (codeword_N - numInitRemaining) * sizeof(float)); + int inPtrIdx = codeword_N - numInitRemaining; + for (ii = ii + 1; ii < codeword_M; ii++) { + memcpy(&channel_llr[ii][0], &inPtr[inPtrIdx], sizeof(float) * codeword_N); + memcpy(&Z[ii][0], &inPtr[inPtrIdx], sizeof(float) * codeword_N); + inPtrIdx += codeword_N; } - memset(&channel_llr[ii][0], 0, sizeof(float)*numInitRemaining); - memset(&Z[ii][0], 0, sizeof(float)*numInitRemaining); - memcpy(&channel_llr[ii][numInitRemaining], &inPtr[0], (codeword_N-numInitRemaining)*sizeof(float)); - memcpy(&Z[ii][numInitRemaining], &inPtr[0], (codeword_N-numInitRemaining)*sizeof(float)); - int inPtrIdx = codeword_N-numInitRemaining; - for(ii=ii+1; ii<codeword_M; ii++) { - memcpy(&channel_llr[ii][0], &inPtr[inPtrIdx], sizeof(float)*codeword_N); - memcpy(&Z[ii][0], &inPtr[inPtrIdx], sizeof(float)*codeword_N); - inPtrIdx += codeword_N; - } // clear out extrinsic-info between blocks - memset(&extrinsic_info[0], 0, sizeof(float)*extrinsic_info.size()); + memset(&extrinsic_info[0], 0, sizeof(float) * extrinsic_info.size()); - //DEBUG_PRINT("Starting TURBO Decoding\n"); + // DEBUG_PRINT("Starting TURBO Decoding\n"); - for(iter=0; iter<d_max_iter; iter++) { - //DEBUG_PRINT("Turbo Iter=%d\n", iter+1); - //DEBUG_PRINT_F(fp, "Turbo Iter=%d\n", iter+1); + for (iter = 0; iter < d_max_iter; iter++) { + // DEBUG_PRINT("Turbo Iter=%d\n", iter+1); + // DEBUG_PRINT_F(fp, "Turbo Iter=%d\n", iter+1); // decode each row - for(m=0; m<codeword_M; m++) { + for (m = 0; m < codeword_M; m++) { // stage the data - volk_32f_x2_add_32f(&input_c_rows[0], &channel_llr[m][0], &extrinsic_info[m*codeword_N], codeword_N); + volk_32f_x2_add_32f(&input_c_rows[0], + &channel_llr[m][0], + &extrinsic_info[m * codeword_N], + codeword_N); - //DEBUG_PRINT("input_c_rows -->\n"); - //DEBUG_PRINT_FLOAT_ARRAY_AS_FLOAT(&input_c_rows[0], codeword_N); - //DEBUG_PRINT_F(fp, "input_c_rows -->\n"); - //DEBUG_PRINT_FLOAT_ARRAY_AS_FLOAT_F(fp, &input_c_rows[0], codeword_N); + // DEBUG_PRINT("input_c_rows -->\n"); + // DEBUG_PRINT_FLOAT_ARRAY_AS_FLOAT(&input_c_rows[0], codeword_N); + // DEBUG_PRINT_F(fp, "input_c_rows -->\n"); + // DEBUG_PRINT_FLOAT_ARRAY_AS_FLOAT_F(fp, &input_c_rows[0], codeword_N); // call siso decode siso_decode_row(); - //DEBUG_PRINT("output_u_rows -->\n"); - //DEBUG_PRINT_FLOAT_ARRAY_AS_FLOAT(&output_u_rows[0], output_u_rows.size()); - //DEBUG_PRINT_F(fp, "output_u_rows -->\n"); - //DEBUG_PRINT_FLOAT_ARRAY_AS_FLOAT_F(fp, &output_u_rows[0], output_u_rows.size()); - //DEBUG_PRINT("output_c_rows -->\n"); - //DEBUG_PRINT_FLOAT_ARRAY_AS_FLOAT(&output_c_rows[0], output_c_rows.size()); - //DEBUG_PRINT_F(fp, "output_c_rows -->\n"); - //DEBUG_PRINT_FLOAT_ARRAY_AS_FLOAT_F(fp, &output_c_rows[0], output_c_rows.size()); - - // copy the output coded back into Z, so we can feed it back through the decoder - // for more iterations - volk_32f_x2_subtract_32f(&Z[m][0], &output_c_rows[0], &extrinsic_info[m*codeword_N], codeword_N); + // DEBUG_PRINT("output_u_rows -->\n"); + // DEBUG_PRINT_FLOAT_ARRAY_AS_FLOAT(&output_u_rows[0], output_u_rows.size()); + // DEBUG_PRINT_F(fp, "output_u_rows -->\n"); + // DEBUG_PRINT_FLOAT_ARRAY_AS_FLOAT_F(fp, &output_u_rows[0], + // output_u_rows.size()); DEBUG_PRINT("output_c_rows -->\n"); + // DEBUG_PRINT_FLOAT_ARRAY_AS_FLOAT(&output_c_rows[0], output_c_rows.size()); + // DEBUG_PRINT_F(fp, "output_c_rows -->\n"); + // DEBUG_PRINT_FLOAT_ARRAY_AS_FLOAT_F(fp, &output_c_rows[0], + // output_c_rows.size()); + + // copy the output coded back into Z, so we can feed it back through the + // decoder for more iterations + volk_32f_x2_subtract_32f( + &Z[m][0], &output_c_rows[0], &extrinsic_info[m * codeword_N], codeword_N); } // decode each col earlyExit = true; output_c_col_idx = 0; - for(n=0; n<codeword_N; n++) { + for (n = 0; n < codeword_N; n++) { // stage the data - for(ii=0; ii<codeword_M; ii++) { + for (ii = 0; ii < codeword_M; ii++) { input_c_cols[ii] = Z[ii][n]; } - //DEBUG_PRINT("input_c_cols -->\n"); - //DEBUG_PRINT_FLOAT_ARRAY_AS_FLOAT(&input_c_cols[0], codeword_M); - //DEBUG_PRINT_F(fp, "input_c_cols -->\n"); - //DEBUG_PRINT_FLOAT_ARRAY_AS_FLOAT_F(fp, &input_c_cols[0], codeword_M); + // DEBUG_PRINT("input_c_cols -->\n"); + // DEBUG_PRINT_FLOAT_ARRAY_AS_FLOAT(&input_c_cols[0], codeword_M); + // DEBUG_PRINT_F(fp, "input_c_cols -->\n"); + // DEBUG_PRINT_FLOAT_ARRAY_AS_FLOAT_F(fp, &input_c_cols[0], codeword_M); // call siso decode siso_decode_col(); - //DEBUG_PRINT("output_u_cols -->\n"); - //DEBUG_PRINT_FLOAT_ARRAY_AS_FLOAT(&output_u_cols[0], output_u_cols.size()); - //DEBUG_PRINT_F(fp, "output_u_cols -->\n"); - //DEBUG_PRINT_FLOAT_ARRAY_AS_FLOAT_F(fp, &output_u_cols[0], output_u_cols.size()); - //DEBUG_PRINT("output_c_cols -->\n"); - //DEBUG_PRINT_FLOAT_ARRAY_AS_FLOAT(&output_c_cols[output_c_col_idx], codeword_M); - //DEBUG_PRINT_F(fp, "output_c_cols -->\n"); - //DEBUG_PRINT_FLOAT_ARRAY_AS_FLOAT_F(fp, &output_c_cols[output_c_col_idx], codeword_M); - - // create the extrinsic_info vector, which subtracts from input_c_cols to prevent feedback - //DEBUG_PRINT("extrinsic_info -->\n"); - //DEBUG_PRINT_F(fp, "extrinsic_info -->\n"); - for(ii=0; ii<codeword_M; ii++) { - extrinsic_info[ii*codeword_N+n] = output_c_cols[output_c_col_idx+ii] - input_c_cols[ii]; - - if(earlyExit) { - if(sgn(output_c_cols[output_c_col_idx+ii])!=sgn(input_c_cols[ii])) { - earlyExit = false; - } - } - - - //DEBUG_PRINT("%f ", extrinsic_info[ii*codeword_N+n]); - //DEBUG_PRINT_F(fp, "%f ", extrinsic_info[ii*codeword_N+n]); + // DEBUG_PRINT("output_u_cols -->\n"); + // DEBUG_PRINT_FLOAT_ARRAY_AS_FLOAT(&output_u_cols[0], output_u_cols.size()); + // DEBUG_PRINT_F(fp, "output_u_cols -->\n"); + // DEBUG_PRINT_FLOAT_ARRAY_AS_FLOAT_F(fp, &output_u_cols[0], + // output_u_cols.size()); DEBUG_PRINT("output_c_cols -->\n"); + // DEBUG_PRINT_FLOAT_ARRAY_AS_FLOAT(&output_c_cols[output_c_col_idx], + // codeword_M); DEBUG_PRINT_F(fp, "output_c_cols -->\n"); + // DEBUG_PRINT_FLOAT_ARRAY_AS_FLOAT_F(fp, &output_c_cols[output_c_col_idx], + // codeword_M); + + // create the extrinsic_info vector, which subtracts from input_c_cols to + // prevent feedback + // DEBUG_PRINT("extrinsic_info -->\n"); + // DEBUG_PRINT_F(fp, "extrinsic_info -->\n"); + for (ii = 0; ii < codeword_M; ii++) { + extrinsic_info[ii * codeword_N + n] = + output_c_cols[output_c_col_idx + ii] - input_c_cols[ii]; + + if (earlyExit) { + if (sgn(output_c_cols[output_c_col_idx + ii]) != + sgn(input_c_cols[ii])) { + earlyExit = false; + } + } + + + // DEBUG_PRINT("%f ", extrinsic_info[ii*codeword_N+n]); + // DEBUG_PRINT_F(fp, "%f ", extrinsic_info[ii*codeword_N+n]); } - //DEBUG_PRINT("\n"); - //DEBUG_PRINT_F(fp, "\n"); + // DEBUG_PRINT("\n"); + // DEBUG_PRINT_F(fp, "\n"); output_c_col_idx += codeword_M; } - if(earlyExit) break; + if (earlyExit) + break; } - ii=0; - for(m=0; m<d_kcol; m++) { - for(n=0; n<d_krow; n++) { - if(ii==0) { - m = mInit; - n = nInit; - } - - // make a hard decision -// if(output_matrix[n*codeword_M+m]>0) { - if(output_c_cols[n*codeword_M+m]>0) { - out[ii++] = (unsigned char) 1; - } - else { - out[ii++] = (unsigned char) 0; - } - } - } - - //DEBUG_PRINT(("Output\n")); - //DEBUG_PRINT_UCHAR_ARRAY(out, outputSize); - //DEBUG_PRINT_F(fp, "Output\n"); - //DEBUG_PRINT_UCHAR_ARRAY_F(fp, out, outputSize); -} + ii = 0; + for (m = 0; m < d_kcol; m++) { + for (n = 0; n < d_krow; n++) { + if (ii == 0) { + m = mInit; + n = nInit; + } -int tpc_decoder::get_input_item_size() { - return sizeof(INPUT_DATATYPE); -} + // make a hard decision + // if(output_matrix[n*codeword_M+m]>0) { + if (output_c_cols[n * codeword_M + m] > 0) { + out[ii++] = (unsigned char)1; + } else { + out[ii++] = (unsigned char)0; + } + } + } -int tpc_decoder::get_output_item_size() { - return sizeof(OUTPUT_DATATYPE); + // DEBUG_PRINT(("Output\n")); + // DEBUG_PRINT_UCHAR_ARRAY(out, outputSize); + // DEBUG_PRINT_F(fp, "Output\n"); + // DEBUG_PRINT_UCHAR_ARRAY_F(fp, out, outputSize); } -int tpc_decoder::get_history() { - return 0; -} +int tpc_decoder::get_input_item_size() { return sizeof(INPUT_DATATYPE); } -float tpc_decoder::get_shift() { - return 0.0; -} +int tpc_decoder::get_output_item_size() { return sizeof(OUTPUT_DATATYPE); } -const char* tpc_decoder::get_conversion() { - return "none"; -} +int tpc_decoder::get_history() { return 0; } + +float tpc_decoder::get_shift() { return 0.0; } + +const char* tpc_decoder::get_conversion() { return "none"; } tpc_decoder::~tpc_decoder() { - if(fp) - fclose(fp); + if (fp) + fclose(fp); } -} -} +} // namespace fec +} // namespace gr diff --git a/gr-fec/lib/tpc_encoder.cc b/gr-fec/lib/tpc_encoder.cc index c9d89d7531..381235c62c 100755..100644 --- a/gr-fec/lib/tpc_encoder.cc +++ b/gr-fec/lib/tpc_encoder.cc @@ -31,103 +31,123 @@ #include <stdio.h> #include <vector> -#include <algorithm> // for std::reverse -#include <string.h> // for memcpy +#include <algorithm> // for std::reverse +#include <string.h> // for memcpy namespace gr { namespace fec { -generic_encoder::sptr -tpc_encoder::make(std::vector<int> row_polys, std::vector<int> col_polys, int krow, int kcol, int bval, int qval) +generic_encoder::sptr tpc_encoder::make(std::vector<int> row_polys, + std::vector<int> col_polys, + int krow, + int kcol, + int bval, + int qval) { - return generic_encoder::sptr(new tpc_encoder(row_polys, col_polys, krow, kcol, bval, qval)); + return generic_encoder::sptr( + new tpc_encoder(row_polys, col_polys, krow, kcol, bval, qval)); } -tpc_encoder::tpc_encoder (std::vector<int> row_polys, std::vector<int> col_polys, int krow, int kcol, int bval, int qval) - : d_rowpolys(row_polys), d_colpolys(col_polys), d_krow(krow), d_kcol(kcol), - d_bval(bval), d_qval(qval) +tpc_encoder::tpc_encoder(std::vector<int> row_polys, + std::vector<int> col_polys, + int krow, + int kcol, + int bval, + int qval) + : d_rowpolys(row_polys), + d_colpolys(col_polys), + d_krow(krow), + d_kcol(kcol), + d_bval(bval), + d_qval(qval) { // first we operate on data chunks of get_input_size() // TODO: should we verify this and throw an error if it doesn't match? YES // hwo do we do that? // calculate the input and output sizes - inputSize = (d_krow*d_kcol - (d_bval+d_qval)); - rowEncoder_K = ceil(log(d_rowpolys[0])/log(2)); // rowEncoder_K is the constraint length of the row encoder polynomial + inputSize = (d_krow * d_kcol - (d_bval + d_qval)); + rowEncoder_K = ceil( + log(d_rowpolys[0]) / + log(2)); // rowEncoder_K is the constraint length of the row encoder polynomial rowEncoder_n = d_rowpolys.size(); rowEncoder_m = rowEncoder_K - 1; - colEncoder_K = ceil(log(d_colpolys[0])/log(2)); // colEncoder_K is the constraint length of the col encoder polynomial + colEncoder_K = ceil( + log(d_colpolys[0]) / + log(2)); // colEncoder_K is the constraint length of the col encoder polynomial colEncoder_n = d_colpolys.size(); colEncoder_m = colEncoder_K - 1; - outputSize = ((d_krow+rowEncoder_m)*rowEncoder_n)*((d_kcol+colEncoder_m)*colEncoder_n) - d_bval; + outputSize = ((d_krow + rowEncoder_m) * rowEncoder_n) * + ((d_kcol + colEncoder_m) * colEncoder_n) - + d_bval; fp = NULL; - //DEBUG_PRINT("inputSize=%d outputSize=%d\n", inputSize, outputSize); - //fp = fopen("c_encoder_output.txt", "w"); + // DEBUG_PRINT("inputSize=%d outputSize=%d\n", inputSize, outputSize); + // fp = fopen("c_encoder_output.txt", "w"); // resize internal matrices - rowNumStates = 1 << (rowEncoder_K-1); // 2^(row_mm) - colNumStates = 1 << (colEncoder_K-1); // 2^(col_mm) - rowOutputs.resize(2, std::vector<int>(rowNumStates,0)); - rowNextStates.resize(2, std::vector<int>(rowNumStates,0)); - colOutputs.resize(2, std::vector<int>(colNumStates,0)); - colNextStates.resize(2, std::vector<int>(colNumStates,0));; + rowNumStates = 1 << (rowEncoder_K - 1); // 2^(row_mm) + colNumStates = 1 << (colEncoder_K - 1); // 2^(col_mm) + rowOutputs.resize(2, std::vector<int>(rowNumStates, 0)); + rowNextStates.resize(2, std::vector<int>(rowNumStates, 0)); + colOutputs.resize(2, std::vector<int>(colNumStates, 0)); + colNextStates.resize(2, std::vector<int>(colNumStates, 0)); + ; rowTail.resize(rowNumStates, 0); colTail.resize(colNumStates, 0); // precalculate the state transition matrix for the row polynomial - tpc_common::precomputeStateTransitionMatrix_RSCPoly(rowNumStates, d_rowpolys, rowEncoder_K, rowEncoder_n, - rowOutputs, rowNextStates); + tpc_common::precomputeStateTransitionMatrix_RSCPoly( + rowNumStates, d_rowpolys, rowEncoder_K, rowEncoder_n, rowOutputs, rowNextStates); // calculate the tail for the row tpc_common::rsc_tail(rowTail, d_rowpolys, rowNumStates, rowEncoder_m); // precalculate the state transition matrix for the column polynomial - tpc_common::precomputeStateTransitionMatrix_RSCPoly(colNumStates, d_colpolys, colEncoder_K, colEncoder_n, - colOutputs, colNextStates); + tpc_common::precomputeStateTransitionMatrix_RSCPoly( + colNumStates, d_colpolys, colEncoder_K, colEncoder_n, colOutputs, colNextStates); // calculate the tail for the col tpc_common::rsc_tail(colTail, d_colpolys, colNumStates, colEncoder_m); // pre-allocate memory we use for encoding - inputSizeWithPad = d_bval+d_qval+inputSize; + inputSizeWithPad = d_bval + d_qval + inputSize; inputWithPad.resize(inputSizeWithPad, 0); - numRowsToEncode = inputSizeWithPad/d_krow; // this should be OK w/ integer division -- TODO: check this? - rowToEncode.resize(d_krow,0); - rowEncoded_block.resize(d_krow+(rowEncoder_m*rowEncoder_n), 0); - rowEncodedBits.resize(d_kcol, std::vector<uint8_t>(rowEncoder_m*rowEncoder_n,0) ); - - numColsToEncode = d_krow+(rowEncoder_m*rowEncoder_n); - colToEncode.resize(d_kcol,0); - colEncoded_block.resize(d_kcol+(colEncoder_m*colEncoder_n), 0); - colEncodedBits.resize(d_krow+(rowEncoder_m*rowEncoder_n), std::vector<uint8_t>(colEncoder_m*colEncoder_n,0) ); + numRowsToEncode = + inputSizeWithPad / + d_krow; // this should be OK w/ integer division -- TODO: check this? + rowToEncode.resize(d_krow, 0); + rowEncoded_block.resize(d_krow + (rowEncoder_m * rowEncoder_n), 0); + rowEncodedBits.resize(d_kcol, std::vector<uint8_t>(rowEncoder_m * rowEncoder_n, 0)); + + numColsToEncode = d_krow + (rowEncoder_m * rowEncoder_n); + colToEncode.resize(d_kcol, 0); + colEncoded_block.resize(d_kcol + (colEncoder_m * colEncoder_n), 0); + colEncodedBits.resize(d_krow + (rowEncoder_m * rowEncoder_n), + std::vector<uint8_t>(colEncoder_m * colEncoder_n, 0)); } -int tpc_encoder::get_output_size() { - return outputSize; -} +int tpc_encoder::get_output_size() { return outputSize; } -int tpc_encoder::get_input_size() { - return inputSize; -} +int tpc_encoder::get_input_size() { return inputSize; } -void tpc_encoder::block_conv_encode( std::vector<uint8_t> &output, - std::vector<uint8_t> input, - std::vector< std::vector<int> > transOutputVec, - std::vector< std::vector<int> > transNextStateVec, - std::vector<int> tail, - size_t KK, - size_t nn) +void tpc_encoder::block_conv_encode(std::vector<uint8_t>& output, + std::vector<uint8_t> input, + std::vector<std::vector<int>> transOutputVec, + std::vector<std::vector<int>> transNextStateVec, + std::vector<int> tail, + size_t KK, + size_t nn) { size_t outsym, ii, jj; int state = 0; size_t LL = input.size(); - std::vector<int> binVec(nn,0); + std::vector<int> binVec(nn, 0); // encode data bits one bit at a time - for (ii=0; ii<LL; ii++) { + for (ii = 0; ii < LL; ii++) { // determine the output symbol outsym = transOutputVec[(int)input[ii]][state]; @@ -135,16 +155,16 @@ void tpc_encoder::block_conv_encode( std::vector<uint8_t> &output, state = transNextStateVec[(int)input[ii]][state]; // Convert symbol to a binary vector - tpc_common::itob( binVec, outsym, nn ); + tpc_common::itob(binVec, outsym, nn); // Assign to output : TODO: investigate using memcpy for this? - for (jj=0;jj<nn;jj++) { - output[nn*ii+jj] = binVec[jj]; + for (jj = 0; jj < nn; jj++) { + output[nn * ii + jj] = binVec[jj]; } } // encode tail - for (ii=LL;ii<LL+KK-1;ii++) { + for (ii = LL; ii < LL + KK - 1; ii++) { // determine the output symbol outsym = transOutputVec[tail[state]][state]; @@ -152,192 +172,205 @@ void tpc_encoder::block_conv_encode( std::vector<uint8_t> &output, state = transNextStateVec[tail[state]][state]; // Convert symbol to a binary vector - tpc_common::itob( binVec, outsym, nn ); + tpc_common::itob(binVec, outsym, nn); // Assign to output : TODO: investigate using memcpy for this? - for (jj=0;jj<nn;jj++) { - output[nn*ii+jj] = binVec[jj]; + for (jj = 0; jj < nn; jj++) { + output[nn * ii + jj] = binVec[jj]; } } } -void tpc_encoder::generic_work(void *inBuffer, void *outBuffer) { - const uint8_t *in = (const uint8_t *) inBuffer; - uint8_t *out = (uint8_t *) outBuffer; +void tpc_encoder::generic_work(void* inBuffer, void* outBuffer) +{ + const uint8_t* in = (const uint8_t*)inBuffer; + uint8_t* out = (uint8_t*)outBuffer; - size_t ii, jj; // indexing var + size_t ii, jj; // indexing var - //DEBUG_PRINT_UCHAR_ARRAY(in, inputSize); + // DEBUG_PRINT_UCHAR_ARRAY(in, inputSize); // TODO: probably a better way to do this than memcpy? - memcpy(&inputWithPad[d_bval+d_qval], in, sizeof(unsigned char)*inputSize); + memcpy(&inputWithPad[d_bval + d_qval], in, sizeof(unsigned char) * inputSize); - //DEBUG_PRINT("Input with Pad -->\n"); - //DEBUG_PRINT_UCHAR_ARRAY(&inputWithPad[0], inputSizeWithPad); - //DEBUG_PRINT_F(fp, "Input with Pad -->\n"); - //DEBUG_PRINT_UCHAR_ARRAY_F(fp, &inputWithPad[0], inputSizeWithPad); + // DEBUG_PRINT("Input with Pad -->\n"); + // DEBUG_PRINT_UCHAR_ARRAY(&inputWithPad[0], inputSizeWithPad); + // DEBUG_PRINT_F(fp, "Input with Pad -->\n"); + // DEBUG_PRINT_UCHAR_ARRAY_F(fp, &inputWithPad[0], inputSizeWithPad); // encode the row data - for(ii=0; ii<numRowsToEncode; ii++) { + for (ii = 0; ii < numRowsToEncode; ii++) { // populate rowToEncode - memcpy(&rowToEncode[0], &inputWithPad[ii*d_krow], sizeof(unsigned char)*d_krow); + memcpy( + &rowToEncode[0], &inputWithPad[ii * d_krow], sizeof(unsigned char) * d_krow); - //DEBUG_PRINT("Encoding row=[%d] -->\n",ii); - //DEBUG_PRINT_UCHAR_ARRAY(&rowToEncode[0], d_krow); - //DEBUG_PRINT_F(fp, "Encoding row=[%d] -->\n",ii); - //DEBUG_PRINT_UCHAR_ARRAY_F(fp, &rowToEncode[0], d_krow); + // DEBUG_PRINT("Encoding row=[%d] -->\n",ii); + // DEBUG_PRINT_UCHAR_ARRAY(&rowToEncode[0], d_krow); + // DEBUG_PRINT_F(fp, "Encoding row=[%d] -->\n",ii); + // DEBUG_PRINT_UCHAR_ARRAY_F(fp, &rowToEncode[0], d_krow); // encode it - block_conv_encode( rowEncoded_block, - rowToEncode, - rowOutputs, - rowNextStates, - rowTail, - rowEncoder_K, - rowEncoder_n); - - //DEBUG_PRINT("Row Encoded Block=[%d] -->\n",ii); - //DEBUG_PRINT_FLOAT_ARRAY_AS_UCHAR(&rowEncoded_block[0], tmp); - //DEBUG_PRINT_F(fp, "Row Encoded Block=[%d] -->\n",ii); - //DEBUG_PRINT_FLOAT_ARRAY_AS_UCHAR_F(fp, &rowEncoded_block[0], tmp); + block_conv_encode(rowEncoded_block, + rowToEncode, + rowOutputs, + rowNextStates, + rowTail, + rowEncoder_K, + rowEncoder_n); + + // DEBUG_PRINT("Row Encoded Block=[%d] -->\n",ii); + // DEBUG_PRINT_FLOAT_ARRAY_AS_UCHAR(&rowEncoded_block[0], tmp); + // DEBUG_PRINT_F(fp, "Row Encoded Block=[%d] -->\n",ii); + // DEBUG_PRINT_FLOAT_ARRAY_AS_UCHAR_F(fp, &rowEncoded_block[0], tmp); // store only the encoded bits, b/c we read out the data in a special way - memcpy(&rowEncodedBits[ii][0], &rowEncoded_block[d_krow], sizeof(uint8_t)*(rowEncoder_m*rowEncoder_n)); + memcpy(&rowEncodedBits[ii][0], + &rowEncoded_block[d_krow], + sizeof(uint8_t) * (rowEncoder_m * rowEncoder_n)); -// DEBUG_PRINT("Row Encoded Bits"); -// tmp = rowEncoder_m*rowEncoder_n; -// DEBUG_PRINT_FLOAT_ARRAY_AS_UCHAR(&rowEncodedBits[ii][0], tmp); + // DEBUG_PRINT("Row Encoded Bits"); + // tmp = rowEncoder_m*rowEncoder_n; + // DEBUG_PRINT_FLOAT_ARRAY_AS_UCHAR(&rowEncodedBits[ii][0], tmp); } // encode the column data size_t numDataColsToEncode = d_krow; - size_t numCheckColsToEncode = numColsToEncode-numDataColsToEncode; - for(ii=0; ii<numDataColsToEncode; ii++) { + size_t numCheckColsToEncode = numColsToEncode - numDataColsToEncode; + for (ii = 0; ii < numDataColsToEncode; ii++) { // populate colToEncode - for(jj=0; jj<d_kcol; jj++) { - colToEncode[jj] = inputWithPad[jj*d_krow+ii]; + for (jj = 0; jj < d_kcol; jj++) { + colToEncode[jj] = inputWithPad[jj * d_krow + ii]; } - //DEBUG_PRINT("Encoding col=[%d] -->\n",ii); - //DEBUG_PRINT_UCHAR_ARRAY(&colToEncode[0], d_kcol); - //DEBUG_PRINT_F(fp, "Encoding col=[%d] -->\n",ii); - //DEBUG_PRINT_UCHAR_ARRAY_F(fp, &colToEncode[0], d_kcol); + // DEBUG_PRINT("Encoding col=[%d] -->\n",ii); + // DEBUG_PRINT_UCHAR_ARRAY(&colToEncode[0], d_kcol); + // DEBUG_PRINT_F(fp, "Encoding col=[%d] -->\n",ii); + // DEBUG_PRINT_UCHAR_ARRAY_F(fp, &colToEncode[0], d_kcol); // encode it - block_conv_encode( colEncoded_block, - colToEncode, - colOutputs, - colNextStates, - colTail, - colEncoder_K, - colEncoder_n); - - //DEBUG_PRINT("Col Encoded Block=[%d] -->\n",ii); - //DEBUG_PRINT_FLOAT_ARRAY_AS_UCHAR(&colEncoded_block[0], tmp); - //DEBUG_PRINT_F(fp, "Col Encoded Block=[%d] -->\n",ii); - //DEBUG_PRINT_FLOAT_ARRAY_AS_UCHAR_F(fp, &colEncoded_block[0], tmp); + block_conv_encode(colEncoded_block, + colToEncode, + colOutputs, + colNextStates, + colTail, + colEncoder_K, + colEncoder_n); + + // DEBUG_PRINT("Col Encoded Block=[%d] -->\n",ii); + // DEBUG_PRINT_FLOAT_ARRAY_AS_UCHAR(&colEncoded_block[0], tmp); + // DEBUG_PRINT_F(fp, "Col Encoded Block=[%d] -->\n",ii); + // DEBUG_PRINT_FLOAT_ARRAY_AS_UCHAR_F(fp, &colEncoded_block[0], tmp); // store only the encoded bits, b/c we read the data out in a special way - memcpy(&colEncodedBits[ii][0], &colEncoded_block[d_kcol], sizeof(uint8_t)*(colEncoder_m*colEncoder_n)); + memcpy(&colEncodedBits[ii][0], + &colEncoded_block[d_kcol], + sizeof(uint8_t) * (colEncoder_m * colEncoder_n)); -// DEBUG_PRINT("Col Encoded Bits"); -// tmp = colEncoder_m*colEncoder_n; -// DEBUG_PRINT_FLOAT_ARRAY(&colEncodedBits[ii][0], tmp); + // DEBUG_PRINT("Col Encoded Bits"); + // tmp = colEncoder_m*colEncoder_n; + // DEBUG_PRINT_FLOAT_ARRAY(&colEncodedBits[ii][0], tmp); } // encode checks on checks (encode the row-encoded bits) - for(ii=0; ii<numCheckColsToEncode; ii++) { + for (ii = 0; ii < numCheckColsToEncode; ii++) { // populate colToEncode - for(jj=0; jj<d_kcol; jj++) { - colToEncode[jj] = rowEncodedBits[jj][ii]; // indexing is weird b/c of the way we declared the vector :( + for (jj = 0; jj < d_kcol; jj++) { + colToEncode[jj] = rowEncodedBits[jj][ii]; // indexing is weird b/c of the way + // we declared the vector :( } - //DEBUG_PRINT("Encoding col=[%d] -->\n",ii+numDataColsToEncode); - //DEBUG_PRINT_UCHAR_ARRAY(&colToEncode[0], d_kcol); - //DEBUG_PRINT_F(fp, "Encoding col=[%d] -->\n",ii+numDataColsToEncode); - //DEBUG_PRINT_UCHAR_ARRAY_F(fp, &colToEncode[0], d_kcol); + // DEBUG_PRINT("Encoding col=[%d] -->\n",ii+numDataColsToEncode); + // DEBUG_PRINT_UCHAR_ARRAY(&colToEncode[0], d_kcol); + // DEBUG_PRINT_F(fp, "Encoding col=[%d] -->\n",ii+numDataColsToEncode); + // DEBUG_PRINT_UCHAR_ARRAY_F(fp, &colToEncode[0], d_kcol); // encode it - block_conv_encode( colEncoded_block, - colToEncode, - colOutputs, - colNextStates, - colTail, - colEncoder_K, - colEncoder_n); + block_conv_encode(colEncoded_block, + colToEncode, + colOutputs, + colNextStates, + colTail, + colEncoder_K, + colEncoder_n); - //DEBUG_PRINT("Col Encoded Block=[%d] -->\n",ii+numDataColsToEncode); - //DEBUG_PRINT_FLOAT_ARRAY_AS_UCHAR(&colEncoded_block[0], tmp); + // DEBUG_PRINT("Col Encoded Block=[%d] -->\n",ii+numDataColsToEncode); + // DEBUG_PRINT_FLOAT_ARRAY_AS_UCHAR(&colEncoded_block[0], tmp); - //DEBUG_PRINT_F(fp, "Col Encoded Block=[%d] -->\n",ii+numDataColsToEncode); - //DEBUG_PRINT_FLOAT_ARRAY_AS_UCHAR_F(fp, &colEncoded_block[0], tmp); + // DEBUG_PRINT_F(fp, "Col Encoded Block=[%d] -->\n",ii+numDataColsToEncode); + // DEBUG_PRINT_FLOAT_ARRAY_AS_UCHAR_F(fp, &colEncoded_block[0], tmp); // store only the encoded bits, b/c we read the data out in a special way - memcpy(&colEncodedBits[ii+numDataColsToEncode][0], &colEncoded_block[d_kcol], sizeof(uint8_t)*(colEncoder_m*colEncoder_n)); + memcpy(&colEncodedBits[ii + numDataColsToEncode][0], + &colEncoded_block[d_kcol], + sizeof(uint8_t) * (colEncoder_m * colEncoder_n)); -// DEBUG_PRINT("Col Encoded Bits"); -// tmp = colEncoder_m*colEncoder_n; -// DEBUG_PRINT_FLOAT_ARRAY(&colEncodedBits[ii][0], tmp); + // DEBUG_PRINT("Col Encoded Bits"); + // tmp = colEncoder_m*colEncoder_n; + // DEBUG_PRINT_FLOAT_ARRAY(&colEncodedBits[ii][0], tmp); } unsigned char* inputDataPtr; - uint8_t *outputDataPtr = out; + uint8_t* outputDataPtr = out; int curRowInRowEncodedBits = 0; // read out the data along the rows into the "out" array // skip B zeros & do the first row - inputDataPtr = &inputWithPad[d_bval]; - if(d_bval > d_krow){ throw std::runtime_error("bval must be < krow"); } - size_t firstRowRemainingBits = d_krow-d_bval; - for(ii=0; ii<firstRowRemainingBits; ii++) { + inputDataPtr = &inputWithPad[d_bval]; + if (d_bval > d_krow) { + throw std::runtime_error("bval must be < krow"); + } + size_t firstRowRemainingBits = d_krow - d_bval; + for (ii = 0; ii < firstRowRemainingBits; ii++) { *outputDataPtr++ = (uint8_t)(*inputDataPtr++); } // copy the encoded bits - memcpy(outputDataPtr, &rowEncodedBits[curRowInRowEncodedBits++][0], - sizeof(uint8_t)*(rowEncoder_m*rowEncoder_n)); + memcpy(outputDataPtr, + &rowEncodedBits[curRowInRowEncodedBits++][0], + sizeof(uint8_t) * (rowEncoder_m * rowEncoder_n)); - outputDataPtr += (rowEncoder_m*rowEncoder_n); + outputDataPtr += (rowEncoder_m * rowEncoder_n); // copy out the rest of the data - for(ii=1; ii<d_kcol; ii++) { // ii starts at 1, b/c we already did idx=0 + for (ii = 1; ii < d_kcol; ii++) { // ii starts at 1, b/c we already did idx=0 // copy systematic bits - for(jj=0; jj<d_krow; jj++) { + for (jj = 0; jj < d_krow; jj++) { *outputDataPtr++ = (uint8_t)(*inputDataPtr++); } // copy the encoded bits - memcpy(outputDataPtr, &rowEncodedBits[curRowInRowEncodedBits++][0], - sizeof(uint8_t)*(rowEncoder_m*rowEncoder_n)); + memcpy(outputDataPtr, + &rowEncodedBits[curRowInRowEncodedBits++][0], + sizeof(uint8_t) * (rowEncoder_m * rowEncoder_n)); - outputDataPtr += (rowEncoder_m*rowEncoder_n); + outputDataPtr += (rowEncoder_m * rowEncoder_n); } // copy the encoded cols - for(ii=0; ii<(colEncoder_m*colEncoder_n); ii++) { + for (ii = 0; ii < (colEncoder_m * colEncoder_n); ii++) { // copy checks - for(jj=0; jj<d_krow; jj++) { + for (jj = 0; jj < d_krow; jj++) { *outputDataPtr++ = colEncodedBits[jj][ii]; } int kk = jj; // copy checks on checks - for(jj=0; jj<(rowEncoder_m*rowEncoder_n); jj++) { + for (jj = 0; jj < (rowEncoder_m * rowEncoder_n); jj++) { *outputDataPtr++ = colEncodedBits[kk++][ii]; } } - //DEBUG_PRINT("Output\n"); - //DEBUG_PRINT_FLOAT_ARRAY_AS_UCHAR(out, outputSize); - //DEBUG_PRINT_F(fp, "Output\n"); - //DEBUG_PRINT_FLOAT_ARRAY_AS_UCHAR_F(fp, out, outputSize); + // DEBUG_PRINT("Output\n"); + // DEBUG_PRINT_FLOAT_ARRAY_AS_UCHAR(out, outputSize); + // DEBUG_PRINT_F(fp, "Output\n"); + // DEBUG_PRINT_FLOAT_ARRAY_AS_UCHAR_F(fp, out, outputSize); } tpc_encoder::~tpc_encoder() { - if(fp) - fclose(fp); + if (fp) + fclose(fp); } -} -} +} // namespace fec +} // namespace gr diff --git a/gr-fec/lib/viterbi/decode.cc b/gr-fec/lib/viterbi/decode.cc index 3b948818fe..98d2644f89 100644 --- a/gr-fec/lib/viterbi/decode.cc +++ b/gr-fec/lib/viterbi/decode.cc @@ -33,54 +33,54 @@ #include <cmath> #define MAXCHUNKSIZE 4096 -#define MAXENCSIZE MAXCHUNKSIZE*16 +#define MAXENCSIZE MAXCHUNKSIZE * 16 int main() { - unsigned char data[MAXCHUNKSIZE]; - signed char syms[MAXENCSIZE]; - int count = 0; + unsigned char data[MAXCHUNKSIZE]; + signed char syms[MAXENCSIZE]; + int count = 0; - // Initialize metric table - int mettab[2][256]; - int amp = 100; - float RATE=0.5; - float ebn0 = 12.0; - float esn0 = RATE*pow(10.0, ebn0/10); - gen_met(mettab, amp, esn0, 0.0, 4); + // Initialize metric table + int mettab[2][256]; + int amp = 100; + float RATE = 0.5; + float ebn0 = 12.0; + float esn0 = RATE * pow(10.0, ebn0 / 10); + gen_met(mettab, amp, esn0, 0.0, 4); - // Initialize decoder state - struct gr::fec::viterbi_state state0[64]; - struct gr::fec::viterbi_state state1[64]; - unsigned char viterbi_in[16]; - gr::fec::viterbi_chunks_init(state0); + // Initialize decoder state + struct gr::fec::viterbi_state state0[64]; + struct gr::fec::viterbi_state state1[64]; + unsigned char viterbi_in[16]; + gr::fec::viterbi_chunks_init(state0); - while (!feof(stdin)) { - unsigned int n = fread(syms, 1, MAXENCSIZE, stdin); - unsigned char *out = data; + while (!feof(stdin)) { + unsigned int n = fread(syms, 1, MAXENCSIZE, stdin); + unsigned char* out = data; - for (unsigned int i = 0; i < n; i++) { + for (unsigned int i = 0; i < n; i++) { - // FIXME: This implements hard decoding by slicing the input stream - unsigned char sym = syms[i] > 0 ? -amp : amp; + // FIXME: This implements hard decoding by slicing the input stream + unsigned char sym = syms[i] > 0 ? -amp : amp; - // Write the symbol to the decoder input - viterbi_in[count % 4] = sym; + // Write the symbol to the decoder input + viterbi_in[count % 4] = sym; - // Every four symbols, perform the butterfly2 operation - if ((count % 4) == 3) { - gr::fec::viterbi_butterfly2(viterbi_in, mettab, state0, state1); + // Every four symbols, perform the butterfly2 operation + if ((count % 4) == 3) { + gr::fec::viterbi_butterfly2(viterbi_in, mettab, state0, state1); - // Every sixteen symbols, perform the readback operation - if ((count > 64) && (count % 16) == 11) { - gr::fec::viterbi_get_output(state0, out); - fwrite(out++, 1, 1, stdout); - } - } + // Every sixteen symbols, perform the readback operation + if ((count > 64) && (count % 16) == 11) { + gr::fec::viterbi_get_output(state0, out); + fwrite(out++, 1, 1, stdout); + } + } - count++; + count++; + } } - } - return 0; + return 0; } diff --git a/gr-fec/lib/viterbi/encode.cc b/gr-fec/lib/viterbi/encode.cc index bf857ff7b8..6936f0bfba 100644 --- a/gr-fec/lib/viterbi/encode.cc +++ b/gr-fec/lib/viterbi/encode.cc @@ -34,19 +34,19 @@ #include <cstdio> #define MAXCHUNKSIZE 4096 -#define MAXENCSIZE MAXCHUNKSIZE*16 +#define MAXENCSIZE MAXCHUNKSIZE * 16 int main() { - unsigned char encoder_state = 0; - unsigned char data[MAXCHUNKSIZE]; - unsigned char syms[MAXENCSIZE]; + unsigned char encoder_state = 0; + unsigned char data[MAXCHUNKSIZE]; + unsigned char syms[MAXENCSIZE]; - while (!feof(stdin)) { - unsigned int n = fread(data, 1, MAXCHUNKSIZE, stdin); - encoder_state = gr::fec::encode(syms, data, n, encoder_state); - fwrite(syms, 1, n*16, stdout); - } + while (!feof(stdin)) { + unsigned int n = fread(data, 1, MAXCHUNKSIZE, stdin); + encoder_state = gr::fec::encode(syms, data, n, encoder_state); + fwrite(syms, 1, n * 16, stdout); + } - return 0; + return 0; } diff --git a/gr-fec/lib/viterbi/metrics.cc b/gr-fec/lib/viterbi/metrics.cc index c94133be15..9ec2f37e17 100644 --- a/gr-fec/lib/viterbi/metrics.cc +++ b/gr-fec/lib/viterbi/metrics.cc @@ -37,94 +37,96 @@ /* Symbols are offset-binary, with 128 corresponding to an erased (no * information) symbol */ -#define OFFSET 128 +#define OFFSET 128 -#include<gnuradio/math.h> +#include <gnuradio/math.h> #include <cstdlib> #include <cmath> /* Normal function integrated from -Inf to x. Range: 0-1 */ -#define normal(x) (0.5 + 0.5*erf((x)/GR_M_SQRT2)) +#define normal(x) (0.5 + 0.5 * erf((x) / GR_M_SQRT2)) /* Logarithm base 2 */ -#define gr_log2(x) (log(x)*GR_M_LOG2E) +#define gr_log2(x) (log(x) * GR_M_LOG2E) -namespace gr{ - namespace fec{ +namespace gr { +namespace fec { /* Generate log-likelihood metrics for 8-bit soft quantized channel * assuming AWGN and BPSK */ - void - gen_met(int mettab[2][256], /* Metric table, [sent sym][rx symbol] */ - int amp, /* Signal amplitude, units */ - double esn0, /* Es/N0 ratio in dB */ - double bias, /* Metric bias; 0 for viterbi, rate for sequential */ - int scale) /* Scale factor */ - { - double noise; - int s,bit; - double metrics[2][256]; - double p0,p1; - - /* Es/N0 as power ratio */ - esn0 = pow(10.,esn0/10); - - noise = 0.5/esn0; /* only half the noise for BPSK */ - noise = sqrt(noise); /* noise/signal Voltage ratio */ - - /* Zero is a special value, since this sample includes all - * lower samples that were clipped to this value, i.e., it - * takes the whole lower tail of the curve - */ - p1 = normal(((0-OFFSET+0.5)/amp - 1)/noise); /* P(s|1) */ - - /* Prob of this value occurring for a 0-bit */ /* P(s|0) */ - p0 = normal(((0-OFFSET+0.5)/amp + 1)/noise); - metrics[0][0] = gr_log2(2*p0/(p1+p0)) - bias; - metrics[1][0] = gr_log2(2*p1/(p1+p0)) - bias; - - for(s=1;s<255;s++){ +void gen_met(int mettab[2][256], /* Metric table, [sent sym][rx symbol] */ + int amp, /* Signal amplitude, units */ + double esn0, /* Es/N0 ratio in dB */ + double bias, /* Metric bias; 0 for viterbi, rate for sequential */ + int scale) /* Scale factor */ +{ + double noise; + int s, bit; + double metrics[2][256]; + double p0, p1; + + /* Es/N0 as power ratio */ + esn0 = pow(10., esn0 / 10); + + noise = 0.5 / esn0; /* only half the noise for BPSK */ + noise = sqrt(noise); /* noise/signal Voltage ratio */ + + /* Zero is a special value, since this sample includes all + * lower samples that were clipped to this value, i.e., it + * takes the whole lower tail of the curve + */ + p1 = normal(((0 - OFFSET + 0.5) / amp - 1) / noise); /* P(s|1) */ + + /* Prob of this value occurring for a 0-bit */ /* P(s|0) */ + p0 = normal(((0 - OFFSET + 0.5) / amp + 1) / noise); + metrics[0][0] = gr_log2(2 * p0 / (p1 + p0)) - bias; + metrics[1][0] = gr_log2(2 * p1 / (p1 + p0)) - bias; + + for (s = 1; s < 255; s++) { /* P(s|1), prob of receiving s given 1 transmitted */ - p1 = normal(((s-OFFSET+0.5)/amp - 1)/noise) - - normal(((s-OFFSET-0.5)/amp - 1)/noise); + p1 = normal(((s - OFFSET + 0.5) / amp - 1) / noise) - + normal(((s - OFFSET - 0.5) / amp - 1) / noise); /* P(s|0), prob of receiving s given 0 transmitted */ - p0 = normal(((s-OFFSET+0.5)/amp + 1)/noise) - - normal(((s-OFFSET-0.5)/amp + 1)/noise); + p0 = normal(((s - OFFSET + 0.5) / amp + 1) / noise) - + normal(((s - OFFSET - 0.5) / amp + 1) / noise); #ifdef notdef - printf("P(%d|1) = %lg, P(%d|0) = %lg\n",s,p1,s,p0); + printf("P(%d|1) = %lg, P(%d|0) = %lg\n", s, p1, s, p0); #endif - metrics[0][s] = gr_log2(2*p0/(p1+p0)) - bias; - metrics[1][s] = gr_log2(2*p1/(p1+p0)) - bias; - } - /* 255 is also a special value */ - /* P(s|1) */ - p1 = 1 - normal(((255-OFFSET-0.5)/amp - 1)/noise); - /* P(s|0) */ - p0 = 1 - normal(((255-OFFSET-0.5)/amp + 1)/noise); - - metrics[0][255] = gr_log2(2*p0/(p1+p0)) - bias; - metrics[1][255] = gr_log2(2*p1/(p1+p0)) - bias; -#ifdef notdef - /* The probability of a raw symbol error is the probability - * that a 1-bit would be received as a sample with value - * 0-128. This is the offset normal curve integrated from -Inf to 0. - */ - printf("symbol Pe = %lg\n",normal(-1/noise)); + metrics[0][s] = gr_log2(2 * p0 / (p1 + p0)) - bias; + metrics[1][s] = gr_log2(2 * p1 / (p1 + p0)) - bias; + } + /* 255 is also a special value */ + /* P(s|1) */ + p1 = 1 - normal(((255 - OFFSET - 0.5) / amp - 1) / noise); + /* P(s|0) */ + p0 = 1 - normal(((255 - OFFSET - 0.5) / amp + 1) / noise); + + metrics[0][255] = gr_log2(2 * p0 / (p1 + p0)) - bias; + metrics[1][255] = gr_log2(2 * p1 / (p1 + p0)) - bias; +#ifdef notdef + /* The probability of a raw symbol error is the probability + * that a 1-bit would be received as a sample with value + * 0-128. This is the offset normal curve integrated from -Inf to 0. + */ + printf("symbol Pe = %lg\n", normal(-1 / noise)); #endif - for(bit=0;bit<2;bit++){ - for(s=0;s<256;s++){ - /* Scale and round to nearest integer */ - mettab[bit][s] = floor(metrics[bit][s] * scale + 0.5); -#ifdef notdef - printf("metrics[%d][%d] = %lg, mettab = %d\n", - bit,s,metrics[bit][s],mettab[bit][s]); + for (bit = 0; bit < 2; bit++) { + for (s = 0; s < 256; s++) { + /* Scale and round to nearest integer */ + mettab[bit][s] = floor(metrics[bit][s] * scale + 0.5); +#ifdef notdef + printf("metrics[%d][%d] = %lg, mettab = %d\n", + bit, + s, + metrics[bit][s], + mettab[bit][s]); #endif } - } } - } } +} // namespace fec +} // namespace gr diff --git a/gr-fec/lib/viterbi/tab.cc b/gr-fec/lib/viterbi/tab.cc index 1c135acfee..79107e073b 100644 --- a/gr-fec/lib/viterbi/tab.cc +++ b/gr-fec/lib/viterbi/tab.cc @@ -22,36 +22,13 @@ /* 8-bit parity lookup table, generated by partab.c */ unsigned char Partab[] = { - 0, 1, 1, 0, 1, 0, 0, 1, - 1, 0, 0, 1, 0, 1, 1, 0, - 1, 0, 0, 1, 0, 1, 1, 0, - 0, 1, 1, 0, 1, 0, 0, 1, - 1, 0, 0, 1, 0, 1, 1, 0, - 0, 1, 1, 0, 1, 0, 0, 1, - 0, 1, 1, 0, 1, 0, 0, 1, - 1, 0, 0, 1, 0, 1, 1, 0, - 1, 0, 0, 1, 0, 1, 1, 0, - 0, 1, 1, 0, 1, 0, 0, 1, - 0, 1, 1, 0, 1, 0, 0, 1, - 1, 0, 0, 1, 0, 1, 1, 0, - 0, 1, 1, 0, 1, 0, 0, 1, - 1, 0, 0, 1, 0, 1, 1, 0, - 1, 0, 0, 1, 0, 1, 1, 0, - 0, 1, 1, 0, 1, 0, 0, 1, - 1, 0, 0, 1, 0, 1, 1, 0, - 0, 1, 1, 0, 1, 0, 0, 1, - 0, 1, 1, 0, 1, 0, 0, 1, - 1, 0, 0, 1, 0, 1, 1, 0, - 0, 1, 1, 0, 1, 0, 0, 1, - 1, 0, 0, 1, 0, 1, 1, 0, - 1, 0, 0, 1, 0, 1, 1, 0, - 0, 1, 1, 0, 1, 0, 0, 1, - 0, 1, 1, 0, 1, 0, 0, 1, - 1, 0, 0, 1, 0, 1, 1, 0, - 1, 0, 0, 1, 0, 1, 1, 0, - 0, 1, 1, 0, 1, 0, 0, 1, - 1, 0, 0, 1, 0, 1, 1, 0, - 0, 1, 1, 0, 1, 0, 0, 1, - 0, 1, 1, 0, 1, 0, 0, 1, - 1, 0, 0, 1, 0, 1, 1, 0, + 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, + 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, + 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, + 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, + 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, + 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, + 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, + 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, + 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, }; diff --git a/gr-fec/lib/viterbi/viterbi.cc b/gr-fec/lib/viterbi/viterbi.cc index 11b9f79b9a..21f99d95f8 100644 --- a/gr-fec/lib/viterbi/viterbi.cc +++ b/gr-fec/lib/viterbi/viterbi.cc @@ -32,8 +32,8 @@ * length there is not much point in changing them. But if you do, you * will have to regenerate the BUTTERFLY macro calls in viterbi() */ -#define POLYA 0x6d -#define POLYB 0x4f +#define POLYA 0x6d +#define POLYB 0x4f /* The basic Viterbi decoder operation, called a "butterfly" * operation because of the way it looks on a trellis diagram. Each @@ -59,81 +59,81 @@ * as the Intel x86 family where evaluating these expressions at runtime * would spill over into memory. */ -#define BUTTERFLY(i,sym) { \ - int m0,m1;\ -\ - /* ACS for 0 branch */\ - m0 = state[i].metric + mets[sym]; /* 2*i */\ - m1 = state[i+32].metric + mets[3^sym]; /* 2*i + 64 */\ - if(m0 > m1){\ - next[2*i].metric = m0;\ - next[2*i].path = state[i].path << 1;\ - } else {\ - next[2*i].metric = m1;\ - next[2*i].path = (state[i+32].path << 1)|1;\ - }\ - /* ACS for 1 branch */\ - m0 = state[i].metric + mets[3^sym]; /* 2*i + 1 */\ - m1 = state[i+32].metric + mets[sym]; /* 2*i + 65 */\ - if(m0 > m1){\ - next[2*i+1].metric = m0;\ - next[2*i+1].path = state[i].path << 1;\ - } else {\ - next[2*i+1].metric = m1;\ - next[2*i+1].path = (state[i+32].path << 1)|1;\ - }\ -} +#define BUTTERFLY(i, sym) \ + { \ + int m0, m1; \ + \ + /* ACS for 0 branch */ \ + m0 = state[i].metric + mets[sym]; /* 2*i */ \ + m1 = state[i + 32].metric + mets[3 ^ sym]; /* 2*i + 64 */ \ + if (m0 > m1) { \ + next[2 * i].metric = m0; \ + next[2 * i].path = state[i].path << 1; \ + } else { \ + next[2 * i].metric = m1; \ + next[2 * i].path = (state[i + 32].path << 1) | 1; \ + } \ + /* ACS for 1 branch */ \ + m0 = state[i].metric + mets[3 ^ sym]; /* 2*i + 1 */ \ + m1 = state[i + 32].metric + mets[sym]; /* 2*i + 65 */ \ + if (m0 > m1) { \ + next[2 * i + 1].metric = m0; \ + next[2 * i + 1].path = state[i].path << 1; \ + } else { \ + next[2 * i + 1].metric = m1; \ + next[2 * i + 1].path = (state[i + 32].path << 1) | 1; \ + } \ + } -extern unsigned char Partab[]; /* Parity lookup table */ +extern unsigned char Partab[]; /* Parity lookup table */ namespace gr { - namespace fec { - - /* Convolutionally encode data into binary symbols */ - unsigned char - encode(unsigned char *symbols, - unsigned char *data, - unsigned int nbytes, - unsigned char encstate) - { - int i; - - while(nbytes-- != 0){ - for(i=7;i>=0;i--){ - encstate = (encstate << 1) | ((*data >> i) & 1); - *symbols++ = Partab[encstate & POLYA]; - *symbols++ = Partab[encstate & POLYB]; +namespace fec { + +/* Convolutionally encode data into binary symbols */ +unsigned char encode(unsigned char* symbols, + unsigned char* data, + unsigned int nbytes, + unsigned char encstate) +{ + int i; + + while (nbytes-- != 0) { + for (i = 7; i >= 0; i--) { + encstate = (encstate << 1) | ((*data >> i) & 1); + *symbols++ = Partab[encstate & POLYA]; + *symbols++ = Partab[encstate & POLYB]; } data++; - } - - return encstate; } - /* Viterbi decoder */ - int - viterbi(unsigned long *metric, /* Final path metric (returned value) */ - unsigned char *data, /* Decoded output data */ - unsigned char *symbols, /* Raw deinterleaved input symbols */ - unsigned int nbits, /* Number of output bits */ - int mettab[2][256] /* Metric table, [sent sym][rx symbol] */ - ){ - unsigned int bitcnt = 0; - int mets[4]; - long bestmetric; - int beststate,i; - struct viterbi_state state0[64],state1[64],*state,*next; - - state = state0; - next = state1; - - /* Initialize starting metrics to prefer 0 state */ - state[0].metric = 0; - for(i=1;i<64;i++) + return encstate; +} + +/* Viterbi decoder */ +int viterbi(unsigned long* metric, /* Final path metric (returned value) */ + unsigned char* data, /* Decoded output data */ + unsigned char* symbols, /* Raw deinterleaved input symbols */ + unsigned int nbits, /* Number of output bits */ + int mettab[2][256] /* Metric table, [sent sym][rx symbol] */ +) +{ + unsigned int bitcnt = 0; + int mets[4]; + long bestmetric; + int beststate, i; + struct viterbi_state state0[64], state1[64], *state, *next; + + state = state0; + next = state1; + + /* Initialize starting metrics to prefer 0 state */ + state[0].metric = 0; + for (i = 1; i < 64; i++) state[i].metric = -999999; - state[0].path = 0; + state[0].path = 0; - for(bitcnt = 0;bitcnt < nbits;bitcnt++){ + for (bitcnt = 0; bitcnt < nbits; bitcnt++) { /* Read input symbol pair and compute all possible branch * metrics */ @@ -144,116 +144,120 @@ namespace gr { symbols += 2; /* These macro calls were generated by genbut.c */ - BUTTERFLY(0,0); - BUTTERFLY(1,1); - BUTTERFLY(2,3); - BUTTERFLY(3,2); - BUTTERFLY(4,3); - BUTTERFLY(5,2); - BUTTERFLY(6,0); - BUTTERFLY(7,1); - BUTTERFLY(8,0); - BUTTERFLY(9,1); - BUTTERFLY(10,3); - BUTTERFLY(11,2); - BUTTERFLY(12,3); - BUTTERFLY(13,2); - BUTTERFLY(14,0); - BUTTERFLY(15,1); - BUTTERFLY(16,2); - BUTTERFLY(17,3); - BUTTERFLY(18,1); - BUTTERFLY(19,0); - BUTTERFLY(20,1); - BUTTERFLY(21,0); - BUTTERFLY(22,2); - BUTTERFLY(23,3); - BUTTERFLY(24,2); - BUTTERFLY(25,3); - BUTTERFLY(26,1); - BUTTERFLY(27,0); - BUTTERFLY(28,1); - BUTTERFLY(29,0); - BUTTERFLY(30,2); - BUTTERFLY(31,3); + BUTTERFLY(0, 0); + BUTTERFLY(1, 1); + BUTTERFLY(2, 3); + BUTTERFLY(3, 2); + BUTTERFLY(4, 3); + BUTTERFLY(5, 2); + BUTTERFLY(6, 0); + BUTTERFLY(7, 1); + BUTTERFLY(8, 0); + BUTTERFLY(9, 1); + BUTTERFLY(10, 3); + BUTTERFLY(11, 2); + BUTTERFLY(12, 3); + BUTTERFLY(13, 2); + BUTTERFLY(14, 0); + BUTTERFLY(15, 1); + BUTTERFLY(16, 2); + BUTTERFLY(17, 3); + BUTTERFLY(18, 1); + BUTTERFLY(19, 0); + BUTTERFLY(20, 1); + BUTTERFLY(21, 0); + BUTTERFLY(22, 2); + BUTTERFLY(23, 3); + BUTTERFLY(24, 2); + BUTTERFLY(25, 3); + BUTTERFLY(26, 1); + BUTTERFLY(27, 0); + BUTTERFLY(28, 1); + BUTTERFLY(29, 0); + BUTTERFLY(30, 2); + BUTTERFLY(31, 3); /* Swap current and next states */ - if(bitcnt & 1){ - state = state0; - next = state1; + if (bitcnt & 1) { + state = state0; + next = state1; } else { - state = state1; - next = state0; + state = state1; + next = state0; } // ETTUS - //if(bitcnt > nbits-7){ + // if(bitcnt > nbits-7){ /* In tail, poison non-zero nodes */ - //for(i=1;i<64;i += 2) + // for(i=1;i<64;i += 2) // state[i].metric = -9999999; //} /* Produce output every 8 bits once path memory is full */ - if((bitcnt % 8) == 5 && bitcnt > 32){ - /* Find current best path */ - bestmetric = state[0].metric; - beststate = 0; - for(i=1;i<64;i++){ - if(state[i].metric > bestmetric){ - bestmetric = state[i].metric; - beststate = i; + if ((bitcnt % 8) == 5 && bitcnt > 32) { + /* Find current best path */ + bestmetric = state[0].metric; + beststate = 0; + for (i = 1; i < 64; i++) { + if (state[i].metric > bestmetric) { + bestmetric = state[i].metric; + beststate = i; + } } - } -#ifdef notdef - printf("metrics[%d] = %d state = %lx\n",beststate, - state[beststate].metric,state[beststate].path); +#ifdef notdef + printf("metrics[%d] = %d state = %lx\n", + beststate, + state[beststate].metric, + state[beststate].path); #endif - *data++ = state[beststate].path >> 24; + *data++ = state[beststate].path >> 24; } - - } - /* Output remaining bits from 0 state */ - // ETTUS Find best state instead - bestmetric = state[0].metric; - beststate = 0; - for(i=1;i<64;i++){ - if(state[i].metric > bestmetric){ - bestmetric = state[i].metric; - beststate = i; + } + /* Output remaining bits from 0 state */ + // ETTUS Find best state instead + bestmetric = state[0].metric; + beststate = 0; + for (i = 1; i < 64; i++) { + if (state[i].metric > bestmetric) { + bestmetric = state[i].metric; + beststate = i; } - } - if((i = bitcnt % 8) != 6) - state[beststate].path <<= 6-i; - - *data++ = state[beststate].path >> 24; - *data++ = state[beststate].path >> 16; - *data++ = state[beststate].path >> 8; - *data = state[beststate].path; - //printf ("BS = %d\tBSM = %d\tM0 = %d\n",beststate,state[beststate].metric,state[0].metric); - *metric = state[beststate].metric; - return 0; } + if ((i = bitcnt % 8) != 6) + state[beststate].path <<= 6 - i; + + *data++ = state[beststate].path >> 24; + *data++ = state[beststate].path >> 16; + *data++ = state[beststate].path >> 8; + *data = state[beststate].path; + // printf ("BS = %d\tBSM = %d\tM0 = + // %d\n",beststate,state[beststate].metric,state[0].metric); + *metric = state[beststate].metric; + return 0; +} - void - viterbi_chunks_init(struct viterbi_state* state) { - // Initialize starting metrics to prefer 0 state - int i; - state[0].metric = 0; - state[0].path = 0; - for(i=1;i<64;i++) +void viterbi_chunks_init(struct viterbi_state* state) +{ + // Initialize starting metrics to prefer 0 state + int i; + state[0].metric = 0; + state[0].path = 0; + for (i = 1; i < 64; i++) state[i].metric = -999999; - } +} - void - viterbi_butterfly8(unsigned char *symbols, int mettab[2][256], struct viterbi_state *state0, struct viterbi_state *state1) - { - unsigned int bitcnt; - int mets[4]; - - struct viterbi_state *state, *next; - state = state0; - next = state1; - // Operate on 16 symbols (8 bits) at a time - for(bitcnt = 0;bitcnt < 8;bitcnt++){ +void viterbi_butterfly8(unsigned char* symbols, + int mettab[2][256], + struct viterbi_state* state0, + struct viterbi_state* state1) +{ + unsigned int bitcnt; + int mets[4]; + + struct viterbi_state *state, *next; + state = state0; + next = state1; + // Operate on 16 symbols (8 bits) at a time + for (bitcnt = 0; bitcnt < 8; bitcnt++) { // Read input symbol pair and compute all possible branch metrics mets[0] = mettab[0][symbols[0]] + mettab[0][symbols[1]]; mets[1] = mettab[0][symbols[0]] + mettab[1][symbols[1]]; @@ -262,99 +266,174 @@ namespace gr { symbols += 2; // These macro calls were generated by genbut.c - BUTTERFLY(0,0);BUTTERFLY(1,1);BUTTERFLY(2,3);BUTTERFLY(3,2); - BUTTERFLY(4,3);BUTTERFLY(5,2);BUTTERFLY(6,0);BUTTERFLY(7,1); - BUTTERFLY(8,0);BUTTERFLY(9,1);BUTTERFLY(10,3);BUTTERFLY(11,2); - BUTTERFLY(12,3);BUTTERFLY(13,2);BUTTERFLY(14,0);BUTTERFLY(15,1); - BUTTERFLY(16,2);BUTTERFLY(17,3);BUTTERFLY(18,1);BUTTERFLY(19,0); - BUTTERFLY(20,1);BUTTERFLY(21,0);BUTTERFLY(22,2);BUTTERFLY(23,3); - BUTTERFLY(24,2);BUTTERFLY(25,3);BUTTERFLY(26,1);BUTTERFLY(27,0); - BUTTERFLY(28,1);BUTTERFLY(29,0);BUTTERFLY(30,2);BUTTERFLY(31,3); + BUTTERFLY(0, 0); + BUTTERFLY(1, 1); + BUTTERFLY(2, 3); + BUTTERFLY(3, 2); + BUTTERFLY(4, 3); + BUTTERFLY(5, 2); + BUTTERFLY(6, 0); + BUTTERFLY(7, 1); + BUTTERFLY(8, 0); + BUTTERFLY(9, 1); + BUTTERFLY(10, 3); + BUTTERFLY(11, 2); + BUTTERFLY(12, 3); + BUTTERFLY(13, 2); + BUTTERFLY(14, 0); + BUTTERFLY(15, 1); + BUTTERFLY(16, 2); + BUTTERFLY(17, 3); + BUTTERFLY(18, 1); + BUTTERFLY(19, 0); + BUTTERFLY(20, 1); + BUTTERFLY(21, 0); + BUTTERFLY(22, 2); + BUTTERFLY(23, 3); + BUTTERFLY(24, 2); + BUTTERFLY(25, 3); + BUTTERFLY(26, 1); + BUTTERFLY(27, 0); + BUTTERFLY(28, 1); + BUTTERFLY(29, 0); + BUTTERFLY(30, 2); + BUTTERFLY(31, 3); // Swap current and next states - if(bitcnt & 1){ - state = state0; - next = state1; + if (bitcnt & 1) { + state = state0; + next = state1; } else { - state = state1; - next = state0; + state = state1; + next = state0; } - } } +} - void - viterbi_butterfly2(unsigned char *symbols, int mettab[2][256], struct viterbi_state *state0, struct viterbi_state *state1) - { - //unsigned int bitcnt; - int mets[4]; - - struct viterbi_state *state, *next; - state = state0; - next = state1; - // Operate on 4 symbols (2 bits) at a time - - // Read input symbol pair and compute all possible branch metrics - mets[0] = mettab[0][symbols[0]] + mettab[0][symbols[1]]; - mets[1] = mettab[0][symbols[0]] + mettab[1][symbols[1]]; - mets[2] = mettab[1][symbols[0]] + mettab[0][symbols[1]]; - mets[3] = mettab[1][symbols[0]] + mettab[1][symbols[1]]; - - // These macro calls were generated by genbut.c - BUTTERFLY(0,0);BUTTERFLY(1,1);BUTTERFLY(2,3);BUTTERFLY(3,2); - BUTTERFLY(4,3);BUTTERFLY(5,2);BUTTERFLY(6,0);BUTTERFLY(7,1); - BUTTERFLY(8,0);BUTTERFLY(9,1);BUTTERFLY(10,3);BUTTERFLY(11,2); - BUTTERFLY(12,3);BUTTERFLY(13,2);BUTTERFLY(14,0);BUTTERFLY(15,1); - BUTTERFLY(16,2);BUTTERFLY(17,3);BUTTERFLY(18,1);BUTTERFLY(19,0); - BUTTERFLY(20,1);BUTTERFLY(21,0);BUTTERFLY(22,2);BUTTERFLY(23,3); - BUTTERFLY(24,2);BUTTERFLY(25,3);BUTTERFLY(26,1);BUTTERFLY(27,0); - BUTTERFLY(28,1);BUTTERFLY(29,0);BUTTERFLY(30,2);BUTTERFLY(31,3); - - state = state1; - next = state0; - - // Read input symbol pair and compute all possible branch metrics - mets[0] = mettab[0][symbols[2]] + mettab[0][symbols[3]]; - mets[1] = mettab[0][symbols[2]] + mettab[1][symbols[3]]; - mets[2] = mettab[1][symbols[2]] + mettab[0][symbols[3]]; - mets[3] = mettab[1][symbols[2]] + mettab[1][symbols[3]]; - - // These macro calls were generated by genbut.c - BUTTERFLY(0,0);BUTTERFLY(1,1);BUTTERFLY(2,3);BUTTERFLY(3,2); - BUTTERFLY(4,3);BUTTERFLY(5,2);BUTTERFLY(6,0);BUTTERFLY(7,1); - BUTTERFLY(8,0);BUTTERFLY(9,1);BUTTERFLY(10,3);BUTTERFLY(11,2); - BUTTERFLY(12,3);BUTTERFLY(13,2);BUTTERFLY(14,0);BUTTERFLY(15,1); - BUTTERFLY(16,2);BUTTERFLY(17,3);BUTTERFLY(18,1);BUTTERFLY(19,0); - BUTTERFLY(20,1);BUTTERFLY(21,0);BUTTERFLY(22,2);BUTTERFLY(23,3); - BUTTERFLY(24,2);BUTTERFLY(25,3);BUTTERFLY(26,1);BUTTERFLY(27,0); - BUTTERFLY(28,1);BUTTERFLY(29,0);BUTTERFLY(30,2);BUTTERFLY(31,3); - } +void viterbi_butterfly2(unsigned char* symbols, + int mettab[2][256], + struct viterbi_state* state0, + struct viterbi_state* state1) +{ + // unsigned int bitcnt; + int mets[4]; + + struct viterbi_state *state, *next; + state = state0; + next = state1; + // Operate on 4 symbols (2 bits) at a time + + // Read input symbol pair and compute all possible branch metrics + mets[0] = mettab[0][symbols[0]] + mettab[0][symbols[1]]; + mets[1] = mettab[0][symbols[0]] + mettab[1][symbols[1]]; + mets[2] = mettab[1][symbols[0]] + mettab[0][symbols[1]]; + mets[3] = mettab[1][symbols[0]] + mettab[1][symbols[1]]; + + // These macro calls were generated by genbut.c + BUTTERFLY(0, 0); + BUTTERFLY(1, 1); + BUTTERFLY(2, 3); + BUTTERFLY(3, 2); + BUTTERFLY(4, 3); + BUTTERFLY(5, 2); + BUTTERFLY(6, 0); + BUTTERFLY(7, 1); + BUTTERFLY(8, 0); + BUTTERFLY(9, 1); + BUTTERFLY(10, 3); + BUTTERFLY(11, 2); + BUTTERFLY(12, 3); + BUTTERFLY(13, 2); + BUTTERFLY(14, 0); + BUTTERFLY(15, 1); + BUTTERFLY(16, 2); + BUTTERFLY(17, 3); + BUTTERFLY(18, 1); + BUTTERFLY(19, 0); + BUTTERFLY(20, 1); + BUTTERFLY(21, 0); + BUTTERFLY(22, 2); + BUTTERFLY(23, 3); + BUTTERFLY(24, 2); + BUTTERFLY(25, 3); + BUTTERFLY(26, 1); + BUTTERFLY(27, 0); + BUTTERFLY(28, 1); + BUTTERFLY(29, 0); + BUTTERFLY(30, 2); + BUTTERFLY(31, 3); + + state = state1; + next = state0; + + // Read input symbol pair and compute all possible branch metrics + mets[0] = mettab[0][symbols[2]] + mettab[0][symbols[3]]; + mets[1] = mettab[0][symbols[2]] + mettab[1][symbols[3]]; + mets[2] = mettab[1][symbols[2]] + mettab[0][symbols[3]]; + mets[3] = mettab[1][symbols[2]] + mettab[1][symbols[3]]; + + // These macro calls were generated by genbut.c + BUTTERFLY(0, 0); + BUTTERFLY(1, 1); + BUTTERFLY(2, 3); + BUTTERFLY(3, 2); + BUTTERFLY(4, 3); + BUTTERFLY(5, 2); + BUTTERFLY(6, 0); + BUTTERFLY(7, 1); + BUTTERFLY(8, 0); + BUTTERFLY(9, 1); + BUTTERFLY(10, 3); + BUTTERFLY(11, 2); + BUTTERFLY(12, 3); + BUTTERFLY(13, 2); + BUTTERFLY(14, 0); + BUTTERFLY(15, 1); + BUTTERFLY(16, 2); + BUTTERFLY(17, 3); + BUTTERFLY(18, 1); + BUTTERFLY(19, 0); + BUTTERFLY(20, 1); + BUTTERFLY(21, 0); + BUTTERFLY(22, 2); + BUTTERFLY(23, 3); + BUTTERFLY(24, 2); + BUTTERFLY(25, 3); + BUTTERFLY(26, 1); + BUTTERFLY(27, 0); + BUTTERFLY(28, 1); + BUTTERFLY(29, 0); + BUTTERFLY(30, 2); + BUTTERFLY(31, 3); +} - unsigned char - viterbi_get_output(struct viterbi_state *state, unsigned char *outbuf) { - // Produce output every 8 bits once path memory is full - // if((bitcnt % 8) == 5 && bitcnt > 32) { - - // Find current best path - unsigned int i,beststate; - int bestmetric; - - bestmetric = state[0].metric; - beststate = 0; - for(i=1;i<64;i++) - if(state[i].metric > bestmetric) { - bestmetric = state[i].metric; - beststate = i; +unsigned char viterbi_get_output(struct viterbi_state* state, unsigned char* outbuf) +{ + // Produce output every 8 bits once path memory is full + // if((bitcnt % 8) == 5 && bitcnt > 32) { + + // Find current best path + unsigned int i, beststate; + int bestmetric; + + bestmetric = state[0].metric; + beststate = 0; + for (i = 1; i < 64; i++) + if (state[i].metric > bestmetric) { + bestmetric = state[i].metric; + beststate = i; } - *outbuf = state[beststate].path >> 24; - return bestmetric; - } + *outbuf = state[beststate].path >> 24; + return bestmetric; +} - //printf ("BS = %d\tBSM = %d\tM0 = %d\n",beststate,state[beststate].metric,state[0].metric); - // In tail, poison non-zero nodes - //if(bits_out > packet_size-7) - // for(i=1;i<64;i += 2) - // state[i].metric = -9999999; +// printf ("BS = %d\tBSM = %d\tM0 = +// %d\n",beststate,state[beststate].metric,state[0].metric); +// In tail, poison non-zero nodes +// if(bits_out > packet_size-7) +// for(i=1;i<64;i += 2) +// state[i].metric = -9999999; - } -} +} // namespace fec +} // namespace gr |