Aunque GNU Radio es un proyecto versátil conformado con una gran cantidad de herramientas que permiten realizar múltiples procesos en Software Radio, muchas veces se requiere de operaciones específicas que difícilmente serán integradas en el proyecto original. La integración de estas funciones especiales pueden ser desarrolladas por el usuario por medio de herramientas como gr_modtool, donde a través de código en C++ o Python se puede desarrollar cualquier función para el procesamiento digital de la señal que no este considerado dentro del proyecto de GNU Radio.

Lenguajes de programación como C++ y Python gozan de una popularidad entre los programadores de tal manera que se desarrollan proyectos independientes especializados que facilitan el desarrollo de programas orientados a analizar o solucionar áreas muy específicas, un caso es IT++ que es una biblioteca de clases y funciones para álgebra lineal, optimización numérica, procesamiento de señales, comunicaciones y estadística. Utilizada ampliamente tanto en la industria como en la investigación.

Integración de IT++ en módulos out-of-tree

Los módulos out-of-tree de GNU Radio utilizan la herramienta CMAKE que es una familia de herramientas diseñadas para compilar y probar software, de esta manera se puede indicar a GNU Radio la incorporación de bibliotecas externas al proyecto out-of-tree por medio de archivos CMAKE. Estos archivos generan variables globales con la ubicación de los archivos de la biblioteca a instalar.

En el caso de IT++, el archivo se llama FindITPP.cmake y se tiene que guardar en ~/gr-Tu_modulo/cmake/modules, quedando el archivo cmake como sigue.

INCLUDE(FindPkgConfig)
PKG_CHECK_MODULES(PC_ITPP QUIET gnuradio-core)

FIND_PATH(
    ITPP_INCLUDE_DIRS
    NAMES itpp/itbase.h
    HINTS $ENV{ITPP_DIR}/include
        ${PC_ITPP_INCLUDE_DIR}
    PATHS /usr/local/include
          /usr/include
	  /usr/pkgs64/include
)

FIND_LIBRARY(
    ITPP_LIBRARIES
    NAMES itpp
    HINTS $ENV{ITPP_DIR}/lib
        ${PC_ITPP_LIBDIR}
    PATHS /usr/local/lib
          /usr/local/lib64
          /usr/lib
          /usr/lib64
	  /usr/pkgs64/lib
)

INCLUDE(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(ITPP DEFAULT_MSG ITPP_LIBRARIES ITPP_INCLUDE_DIRS)
MARK_AS_ADVANCED(ITPP_LIBRARIES ITPP_INCLUDE_DIRS)

Así mismo hay que indicar a CMAKE que tiene que utilizar el nuevo archivo cmake, para ello se modifica el archivo CmakeLists.txt ubicado en la raíz del proyecto.

En la sección # Find gnuradio build dependencies se agrega la línea

find_package(ITPP)

En la parte final de la sección permite agregar un mensaje de error en caso de que la biblioteca no este instalada en el sistema.

if(NOT ITPP_FOUND)
    message(FATAL_ERROR "IT++ Core required to compile Tu_Modulo")
endif()

En la sección de # Setup the include and linker paths se agrega la línea ${ITPP_INCLUDE_DIRS} para include_directories y la línea ${ITPP_LIBRARY_DIRS} para link_directories, quedando como sigue:

include_directories(
    ${CMAKE_SOURCE_DIR}/lib
    ${CMAKE_SOURCE_DIR}/include
    ${CMAKE_BINARY_DIR}/lib
    ${CMAKE_BINARY_DIR}/include
    ${Boost_INCLUDE_DIRS}
    ${CPPUNIT_INCLUDE_DIRS}
    ${ITPP_INCLUDE_DIRS}
    ${GNURADIO_ALL_INCLUDE_DIRS}
)

link_directories(
    ${Boost_LIBRARY_DIRS}
    ${CPPUNIT_LIBRARY_DIRS}
    ${ITPP_LIBRARY_DIRS}
    ${GNURADIO_RUNTIME_LIBRARY_DIRS}
)

Finalmente el archivo CMakeLists.txt, con sus modificaciones incluidas, quedaría:

# Copyright 2011,2012 Free Software Foundation, Inc.
#
# This file is part of GNU Radio
#
# GNU Radio is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3, or (at your option)
# any later version.
#
# GNU Radio is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with GNU Radio; see the file COPYING.  If not, write to
# the Free Software Foundation, Inc., 51 Franklin Street,
# Boston, MA 02110-1301, USA.


########################################################################
# Project setup
########################################################################
cmake_minimum_required(VERSION 2.6)
project(gr-Tu_modulo CXX C)
enable_testing()

#select the release build type by default to get optimization flags
if(NOT CMAKE_BUILD_TYPE)
   set(CMAKE_BUILD_TYPE "Release")
   message(STATUS "Build type not specified: defaulting to release.")
endif(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE ${CMAKE_BUILD_TYPE} CACHE STRING "")

list(APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/Modules)

########################################################################
# Compiler specific setup
########################################################################
if(CMAKE_COMPILER_IS_GNUCXX AND NOT WIN32)
    #http://gcc.gnu.org/wiki/Visibility
    add_definitions(-fvisibility=hidden)
endif()

########################################################################
# Find boost
########################################################################
if(UNIX AND EXISTS "/usr/lib64")
    list(APPEND BOOST_LIBRARYDIR "/usr/lib64") #fedora 64-bit fix
endif(UNIX AND EXISTS "/usr/lib64")
set(Boost_ADDITIONAL_VERSIONS
    "1.35.0" "1.35" "1.36.0" "1.36" "1.37.0" "1.37" "1.38.0" "1.38" "1.39.0" "1.39"
    "1.40.0" "1.40" "1.41.0" "1.41" "1.42.0" "1.42" "1.43.0" "1.43" "1.44.0" "1.44"
    "1.45.0" "1.45" "1.46.0" "1.46" "1.47.0" "1.47" "1.48.0" "1.48" "1.49.0" "1.49"
    "1.50.0" "1.50" "1.51.0" "1.51" "1.52.0" "1.52" "1.53.0" "1.53" "1.54.0" "1.54"
    "1.55.0" "1.55" "1.56.0" "1.56" "1.57.0" "1.57" "1.58.0" "1.58" "1.59.0" "1.59"
    "1.60.0" "1.60" "1.61.0" "1.61" "1.62.0" "1.62" "1.63.0" "1.63" "1.64.0" "1.64"
    "1.65.0" "1.65" "1.66.0" "1.66" "1.67.0" "1.67" "1.68.0" "1.68" "1.69.0" "1.69"
)
find_package(Boost "1.35" COMPONENTS filesystem system)

if(NOT Boost_FOUND)
    message(FATAL_ERROR "Boost required to compile Tu_modulo")
endif()

########################################################################
# Install directories
########################################################################
include(GrPlatform) #define LIB_SUFFIX
set(GR_RUNTIME_DIR      bin)
set(GR_LIBRARY_DIR      lib${LIB_SUFFIX})
set(GR_INCLUDE_DIR      include/Tu_modulo)
set(GR_DATA_DIR         share)
set(GR_PKG_DATA_DIR     ${GR_DATA_DIR}/${CMAKE_PROJECT_NAME})
set(GR_DOC_DIR          ${GR_DATA_DIR}/doc)
set(GR_PKG_DOC_DIR      ${GR_DOC_DIR}/${CMAKE_PROJECT_NAME})
set(GR_CONF_DIR         etc)
set(GR_PKG_CONF_DIR     ${GR_CONF_DIR}/${CMAKE_PROJECT_NAME}/conf.d)
set(GR_LIBEXEC_DIR      libexec)
set(GR_PKG_LIBEXEC_DIR  ${GR_LIBEXEC_DIR}/${CMAKE_PROJECT_NAME})
set(GRC_BLOCKS_DIR      ${GR_PKG_DATA_DIR}/grc/blocks)

########################################################################
# Find gnuradio build dependencies
########################################################################
find_package(CppUnit)
find_package(ITPP)
# Search for GNU Radio and its components and versions. Add any
# components required to the list of GR_REQUIRED_COMPONENTS (in all
# caps such as FILTER or FFT) and change the version to the minimum
# API compatible version required.
set(GR_REQUIRED_COMPONENTS RUNTIME)
find_package(Gnuradio "3.7.2" REQUIRED)

if(NOT CPPUNIT_FOUND)
    message(FATAL_ERROR "CppUnit required to compile Tu_modulo")
endif()
if(NOT ITPP_FOUND)
    message(FATAL_ERROR "IT++ Core required to compile Tu_modulo")
endif()
########################################################################
# Setup the include and linker paths
########################################################################
include_directories(
    ${CMAKE_SOURCE_DIR}/lib
    ${CMAKE_SOURCE_DIR}/include
    ${CMAKE_BINARY_DIR}/lib
    ${CMAKE_BINARY_DIR}/include
    ${Boost_INCLUDE_DIRS}
    ${CPPUNIT_INCLUDE_DIRS}
    ${ITPP_INCLUDE_DIRS}
    ${GNURADIO_ALL_INCLUDE_DIRS}
)

link_directories(
    ${Boost_LIBRARY_DIRS}
    ${CPPUNIT_LIBRARY_DIRS}
    ${ITPP_LIBRARY_DIRS}
    ${GNURADIO_RUNTIME_LIBRARY_DIRS}
)

# Set component parameters
set(GR_TU_MODULO_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/include CACHE INTERNAL "" FORCE)
set(GR_TU_MODULO_SWIG_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/swig CACHE INTERNAL "" FORCE)

########################################################################
# Create uninstall target
########################################################################
configure_file(
    ${CMAKE_SOURCE_DIR}/cmake/cmake_uninstall.cmake.in
    ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake
@ONLY)

add_custom_target(uninstall
    ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake
)

########################################################################
# Add subdirectories
########################################################################
add_subdirectory(include/Tu_modulo)
add_subdirectory(lib)
add_subdirectory(swig)
add_subdirectory(python)
add_subdirectory(grc)
add_subdirectory(apps)
add_subdirectory(docs)

########################################################################
# Install cmake search helper for this library
########################################################################
install(FILES cmake/Modules/Tu_moduloConfig.cmake        
    DESTINATION lib/cmake/Tu_modulo
)

Desarrollo de bloques con IT++

En este caso se desarrollarán dos bloques con funciones de IT++, el codificador y decodificador convolucional. Para ello, por medio de gr_modtool se requiere crear dos bloques con tres valores de entrada, uno para el polinomio, otro para la tasa de codificación y uno último para indicar la cantidad de registros que tiene el codificador.

Desde una terminal de linux, se ejecuta gr_modtool

$ gr_modtool add
GNU Radio module name identified: Tu_modulo
Enter code type: sync
Language: C++
Enter name of block/code (without module name prefix): encodconv_vff
Block/code identifier: encodconv_vff
Enter valid argument list, including default arguments: int val1, int val2, int val3
Add Python QA code? [Y/n]
Add C++ QA code? [y/N]
Adding file 'lib/encodconv_vff_impl.h'...
Adding file 'lib/encodconv_vff_impl.cc'...
Adding file 'include/Tu_modulo/encodconv_vff.h'...
Editing swig/Tu_modulo_swig.i...
Adding file 'python/qa_encodconv_vff.py'...
Editing python/CMakeLists.txt...
Adding file 'grc/Tu_modulo_encodconv_vff.xml'...
Editing grc/CMakeLists.txt...

Para el decodificador, se crea un bloque con las mismas características

$ gr_modtool add
GNU Radio module name identified: Tu_modulo
Enter code type: sync
Language: C++
Enter name of block/code (without module name prefix): decodconv_vff
Block/code identifier: decodconv_vff
Enter valid argument list, including default arguments: int val1, int val2, int val3
Add Python QA code? [Y/n]
Add C++ QA code? [y/N]
Adding file 'lib/decodconv_vff_impl.h'...
Adding file 'lib/decodconv_vff_impl.cc'...
Adding file 'include/Tu_modulo/decodconv_vff.h'...
Editing swig/Tu_modulo_swig.i...
Adding file 'python/qa_decodconv_vff.py'...
Editing python/CMakeLists.txt...
Adding file 'grc/Tu_modulo_decodconv_vff.xml'...
Editing grc/CmakeLists.txt...

Codificador convolucional

Dentro del archivo encodconv_vff_impl.cc que se ubica en ~/gr-Tu_modulo/lib se indica que se utilizará la biblioteca de IT++

#include <itpp/itcomm.h>

En la sección de encodconv_vff_impl::encodconv_vff_impl(int val1, int val2, int val3) se indican los parámetros del bloque tales como la cantidad de flujos de datos, tamaño de los paquetes de entrada y salida, así como asignar a las variables internas las variables públicas que se capturaron en el bloque de GRC.

encodconv_vff_impl::encodconv_vff_impl(int val1, int val2, int val3)
  : gr::sync_block("encodconv_vff",
          gr::io_signature::make(1, 1, sizeof(float) * val3),
          gr::io_signature::make(1, 1, sizeof(float) * val3 * sizeof(val1)))
{
	polsize = sizeof(val1);
	cl = val2;
	pz = val3;

	for (int i = 0; i < 0x100; i++){
		polynom[i] = i;
	}

	memcpy(polynom, (char*)&val1, sizeof(val1));

	// -- Channel code parameters --

	itpp::ivec generator(polsize);

	for (int i = 0; i < polsize; i++){
		generator[i] = polynom[i];
	}

	code.set_generator_polynomials(generator, cl);
}

Como se puede observar, varias funciones de IT++ se han utilizado como parte del código del bloque de procesamiento, para llamar cualquier otra función solo se indica con el formato itpp::función, de esta manera, el compilador reconocerá que la función forma parte de la biblioteca de IT++.

En la sección de procesamiento de la señal // Do <+signal processing+> se realizará la codificación convolucional de los paquetes de entrada de acuerdo a los parámetros previamente definidos, por lo que el código final queda como sigue:

int
encodconv_vff_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];
    float *out = (float *) output_items[0];

    itpp::bvec tempin(pz * sizeof(float));
	itpp::bvec tempout(pz * polsize * sizeof(float));

	for (int j = 0; j < (pz * sizeof(float)); j++){
		tempin[j] = in[j];
	}

	code.encode_tailbite(tempin, tempout);

	for (int k = 0; k < (pz * polsize * sizeof(float)); k++){
		out[k] = tempout[k];
	}

    // Tell runtime system how many output items we produced.
    return noutput_items;
}

La operación de codificación es realizada por el comando code.encode_tailbite(tempin, tempout); , disminuyendo así la cantidad de líneas para desarrollar un codificador convolucional.

La versión final del código es

/* -*- c++ -*- */
/*
 * Copyright 2014 IVAN RODRIGUEZ.
 *
 * This is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3, or (at your option)
 * any later version.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this software; see the file COPYING.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street,
 * Boston, MA 02110-1301, USA.
 */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include <gnuradio/io_signature.h>
#include "encodconv_vff_impl.h"
#include <itpp/itcomm.h>

namespace gr {
  namespace Tu_modulo {

    encodconv_vff::sptr
    encodconv_vff::make(int val1, int val2, int val3)
    {
      return gnuradio::get_initial_sptr
        (new encodconv_vff_impl(val1, val2, val3));
    }

    /*
     * The private constructor
     */
    encodconv_vff_impl::encodconv_vff_impl(int val1, int val2, int val3)
      : gr::sync_block("encodconv_vff",
              gr::io_signature::make(1, 1, sizeof(float) * val3),
              gr::io_signature::make(1, 1, sizeof(float) * val3 * sizeof(val1)))
    {
    	polsize = sizeof(val1);
		cl = val2;
		pz = val3;

		for (int i = 0; i < 0x100; i++){
			polynom[i] = i;
		}

		memcpy(polynom, (char*)&val1, sizeof(val1));

		// -- Channel code parameters --

		itpp::ivec generator(polsize);

		for (int i = 0; i < polsize; i++){
			generator[i] = polynom[i];
		}

		code.set_generator_polynomials(generator, cl);
    }

    /*
     * Our virtual destructor.
     */
    encodconv_vff_impl::~encodconv_vff_impl()
    {
    }

    int
    encodconv_vff_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];
        float *out = (float *) output_items[0];

        itpp::bvec tempin(pz * sizeof(float));
		itpp::bvec tempout(pz * polsize * sizeof(float));

		for (int j = 0; j < (pz * sizeof(float)); j++){
			tempin[j] = in[j];
		}

		code.encode_tailbite(tempin, tempout);

		for (int k = 0; k < (pz * polsize * sizeof(float)); k++){
			out[k] = tempout[k];
		}

        // Tell runtime system how many output items we produced.
        return noutput_items;
    }

  } /* namespace Tu_modulo */
} /* namespace gr */

Decodificador convolucional

De manera similar al codificador convolucional, es necesario modificar el archivo decodconv_vff_impl.cc, en una primera instancia se agrega la línea donde se indica que se utilizará la biblioteca de IT++.

#include <itpp/itcomm.h>

En la sección de decodconv_vff_impl::decodconv_vff_impl(int val1, int val2, int val3) se indican los parámetros del bloque,

decodconv_vff_impl::decodconv_vff_impl(int val1, int val2, int val3)
  : gr::sync_block("decodconv_vff",
          gr::io_signature::make(1, 1, sizeof(float) * val3 * sizeof(val1)),
          gr::io_signature::make(1, 1, sizeof(float) * val3))
{
	polsize = sizeof(val1);
	cl = val2;
	pz = val3;

	for (int i = 0; i < 0x100; i++){
		polynom[i] = i;
	}

	memcpy(polynom, (char*)&val1, sizeof(val1));

	// -- Channel code parameters --

	itpp::ivec generator(polsize);

	for (int i = 0; i < polsize; i++){
		generator[i] = polynom[i];
	}

	code.set_generator_polynomials(generator, cl);
}

De igual manera, en la sección de procesamiento de la señal del bloque de procesamiento // Do <+signal processing+> se realizará la decodificación de los paquetes de entrada de acuerdo a los parámetros previamente definidos utilizando la biblioteca de IT++,

int
decodconv_vff_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];
    float *out = (float *) output_items[0];

itpp::bvec tempbin(pz * polsize * sizeof(float));
itpp::bvec tempout(pz * sizeof(float));
itpp::vec tempin(pz * polsize * sizeof(float));

	for (int j = 0; j < (pz  * polsize * sizeof(float)); j++){
		tempbin[j] = in[j];
	}

	tempin = to_vec(tempbin);
	tempin = -(tempin * 2 - 1);

	code.decode_tailbite(tempin, tempout);

	for (int k = 0; k < (pz * sizeof(float)); k++){
		out[k] = tempout[k];
	}

    // Tell runtime system how many output items we produced.
    return noutput_items;
}

En este bloque la operación de decodificación es realizada por el comando code.decode_tailbite(tempin, tempout);

El código final del bloque de procesamiento es

/* -*- c++ -*- */
/*
 * Copyright 2014 IVAN RODRIGUEZ.
 *
 * This is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3, or (at your option)
 * any later version.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this software; see the file COPYING.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street,
 * Boston, MA 02110-1301, USA.
 */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include <gnuradio/io_signature.h>
#include "decodconv_vff_impl.h"
#include <itpp/itcomm.h>

namespace gr {
  namespace Tu_modulo {

    decodconv_vff::sptr
    decodconv_vff::make(int val1, int val2, int val3)
    {
      return gnuradio::get_initial_sptr
        (new decodconv_vff_impl(val1, val2, val3));
    }

    /*
     * The private constructor
     */
    decodconv_vff_impl::decodconv_vff_impl(int val1, int val2, int val3)
      : gr::sync_block("decodconv_vff",
              gr::io_signature::make(1, 1, sizeof(float) * val3 * sizeof(val1)),
              gr::io_signature::make(1, 1, sizeof(float) * val3))
    {
    	polsize = sizeof(val1);
		cl = val2;
		pz = val3;

		for (int i = 0; i < 0x100; i++){
			polynom[i] = i;
		}

		memcpy(polynom, (char*)&val1, sizeof(val1));

		// -- Channel code parameters --

		itpp::ivec generator(polsize);

		for (int i = 0; i < polsize; i++){
			generator[i] = polynom[i];
		}

		code.set_generator_polynomials(generator, cl);
    }

    /*
     * Our virtual destructor.
     */
    decodconv_vff_impl::~decodconv_vff_impl()
    {
    }

    int
    decodconv_vff_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];
        float *out = (float *) output_items[0];

	itpp::bvec tempbin(pz * polsize * sizeof(float));
	itpp::bvec tempout(pz * sizeof(float));
	itpp::vec tempin(pz * polsize * sizeof(float));

		for (int j = 0; j < (pz  * polsize * sizeof(float)); j++){
			tempbin[j] = in[j];
		}

		tempin = to_vec(tempbin);
		tempin = -(tempin * 2 - 1);

		code.decode_tailbite(tempin, tempout);

		for (int k = 0; k < (pz * sizeof(float)); k++){
			out[k] = tempout[k];
		}

        // Tell runtime system how many output items we produced.
        return noutput_items;
    }

  } /* namespace Tu_modulo */
} /* namespace gr */

Definiendo las variables públicas en los archivos de cabecera

Para poder utilizar libremente las clases y variables de IT++ dentro de los archivos cc de GNU Radio se requiere modificar los archivos de cabecera h de los bloques de procesamiento. Para el codificador convolucional el archivo es encodconv_vff_impl.h y para el decodificador es decodconv_vff_impl.h.

Dentro del archivo encodconv_vff_impl.h se indica la biblioteca de IT++

#include <itpp/itcomm.h>

en la sección de public se indican las variables a utilizar

 public:
  encodconv_vff_impl(int val1, int val2, int val3);
  unsigned char polynom [0x100];
  int polsize;
  int cl;
  int pz;
  itpp::Convolutional_Code code;

  ~encodconv_vff_impl();

El archivo h del bloque de procesamiento del codificador convolucional queda como sigue

/* -*- c++ -*- */
/*
 * Copyright 2014 IVAN RODRIGUEZ.
 *
 * This is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3, or (at your option)
 * any later version.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this software; see the file COPYING.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street,
 * Boston, MA 02110-1301, USA.
 */

#ifndef INCLUDED_TU_MODULO_ENCODCONV_VFF_IMPL_H
#define INCLUDED_TU_MODULO_ENCODCONV_VFF_IMPL_H

#include <Tu_modulo/encodconv_vff.h>
#include <itpp/itcomm.h>

namespace gr {
  namespace Tu_modulo {

    class encodconv_vff_impl : public encodconv_vff
    {
     private:
      // Nothing to declare in this block.

     public:
      encodconv_vff_impl(int val1, int val2, int val3);
      unsigned char polynom [0x100];
      int polsize;
      int cl;
      int pz;
      itpp::Convolutional_Code code;

      ~encodconv_vff_impl();

      // Where all the action really happens
      int work(int noutput_items,
	       gr_vector_const_void_star &input_items,
	       gr_vector_void_star &output_items);
    };

  } // namespace Tu_modulo
} // namespace gr

#endif /* INCLUDED_TU_MODULO_ENCODCONV_VFF_IMPL_H */

De igual manera en el archivo de cabecera del decodificador decodconv_vff_impl.h se indica la biblioteca de IT++

#include <itpp/itcomm.h>

y en la sección de public las variables requeridas para el procesamiento de la señal, public: decodconv_vff_impl(int val1, int val2, int val3); unsigned char polynom [0x100]; int polsize; int cl; int pz; itpp::Convolutional_Code code;

  ~decodconv_vff_impl();

El archivo de cabecera, en su versión final queda,

/* -*- c++ -*- */
/*
 * Copyright 2014 IVAN RODRIGUEZ.
 *
 * This is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3, or (at your option)
 * any later version.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this software; see the file COPYING.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street,
 * Boston, MA 02110-1301, USA.
 */

#ifndef INCLUDED_TU_MODULO_DECODCONV_VFF_IMPL_H
#define INCLUDED_TU_MODULO_DECODCONV_VFF_IMPL_H

#include <Tu_modulo/decodconv_vff.h>
#include <itpp/itcomm.h>

namespace gr {
  namespace Tu_modulo {

    class decodconv_vff_impl : public decodconv_vff
    {
     private:
      // Nothing to declare in this block.

     public:
      decodconv_vff_impl(int val1, int val2, int val3);
      unsigned char polynom [0x100];
      int polsize;
      int cl;
      int pz;
      itpp::Convolutional_Code code;

      ~decodconv_vff_impl();
      // Where all the action really happens
      int work(int noutput_items,
	       gr_vector_const_void_star &input_items,
	       gr_vector_void_star &output_items);
    };

  } // namespace Tu_modulo
} // namespace gr

#endif /* INCLUDED_TU_MODULO_DECODCONV_VFF_IMPL_H */

Interfaz gráfica de GRC

Los bloques de procesamiento mostrados en GNU Radio Companion son archivos xml que se ubican en ~/gr-Tu_modulo/grc, para el codificador convolucional es Tu_modulo_encodconv_vff.xml y para el decodificador Tu_modulo_decodconv_vff.xml.

Los parámetros a modificar son <name>, <param>, <sink> y <source>, los bloques del decodificador y codificador convolucional quedan como sigue,

<?xml version="1.0"?>
<block>
  <name>Convolutional Encoder</name>
  <key>Tu_modulo_encodconv_vff</key>
  <category>Tu_modulo</category>
  <import>import Tu_modulo</import>
  <make>Tu_modulo.encodconv_vff($val1, $val2, $val3)</make>
  <!-- Make one 'param' node for every Parameter you want settable from the GUI.
       Sub-nodes:
       * name
       * key (makes the value accessible as $keyname, e.g. in the make node)
       * type -->
  <param>
    <name>Generator Polynomial</name>
    <key>val1</key>
    <type>int_vector</type>
  </param>

  <param>
    <name>Constraint Length</name>
    <key>val2</key>
    <type>int</type>
  </param>

  <param>
    <name>Packet Size</name>
    <key>val3</key>
    <type>int</type>
  </param>

  <param>
    <name>Rate (1/N)</name>
    <key>val4</key>
    <type>int</type>
  </param>

  <!-- Make one 'sink' node per input. Sub-nodes:
       * name (an identifier for the GUI)
       * type
       * vlen
       * optional (set to 1 for optional inputs) -->
  <sink>
    <name>in</name>
    <type>float</type>
    <vlen>$val3</vlen>
  </sink>

  <!-- Make one 'source' node per output. Sub-nodes:
       * name (an identifier for the GUI)
       * type
       * vlen
       * optional (set to 1 for optional inputs) -->
  <source>
    <name>out</name>
    <type>float</type>
    <vlen>$val3 * $val4</vlen>
  </source>
</block>
<?xml version="1.0"?>
<block>
  <name>Convolutional Decoder</name>
  <key>Tu_modulo_decodconv_vff</key>
  <category>Tu_modulo</category>
  <import>import Tu_modulo</import>
  <make>Tu_modulo.decodconv_vff($val1, $val2, $val3)</make>
  <!-- Make one 'param' node for every Parameter you want settable from the GUI.
       Sub-nodes:
       * name
       * key (makes the value accessible as $keyname, e.g. in the make node)
       * type -->
  <param>
    <name>Generator Polynomial</name>
    <key>val1</key>
    <type>int_vector</type>
  </param>

  <param>
    <name>Constraint Length</name>
    <key>val2</key>
    <type>int</type>
  </param>

  <param>
    <name>Packet Size</name>
    <key>val3</key>
    <type>int</type>
  </param>

  <param>
    <name>Rate (1/N)</name>
    <key>val4</key>
    <type>int</type>
  </param>

  <!-- Make one 'sink' node per input. Sub-nodes:
       * name (an identifier for the GUI)
       * type
       * vlen
       * optional (set to 1 for optional inputs) -->

    <name>in</name>
    <type>float</type>
    <vlen>$val3 * $val4</vlen>
  </sink>

  <!-- Make one 'source' node per output. Sub-nodes:
       * name (an identifier for the GUI)
       * type
       * vlen
       * optional (set to 1 for optional inputs) -->
  <source>
    <name>out</name>
    <type>float</type>
    <vlen>$val3</vlen>
  </source>
</block>

Compilación de los bloques

Una vez ya realizado todos los procesos referentes al código de programación de los bloques de procesamiento se procede a integrarlos en el proyecto de GNU Radio. Esto se realiza por medio de una serie de comandos desde una terminal de linux en la raíz del proyecto. En caso de no tener una carpeta de build, se crea por medio de comandos de linux

$ mkdir build
$ cd build

Una vez dentro de la carpeta de build, se procede a compilar el proyecto

$ cmake ../
$ make
$ sudo make install
$ sudo ldconfig

De esa manera queda integrado el módulo out-of-tree dentro de GNU Radio.

@viktor_ivan