Este documento tiene por objetivo indicar los pasos a seguir a modo de ejemplo para llevar a cabo la inclusión de nuevos módulos (out-of-tree) y bloques en el proyecto GNU Radio.
Este proceso se lleva a cabo mediante el uso del script gr-modtool.py, el cual permite crear, modificar y eliminar módulos y/o bloques de procesado.
Generación de un nuevo módulo (out of tree):
Para crear un nuevo módulo bastará con escribir en pantalla el siguiente comando:
$gr_modtool.py newmod nombre_del_módulo.
Con este simple comando, el script genera todo el esqueleto de un módulo anteriormente descrito, en este caso se ha tomado como nombre del módulo prueba.
Generación de un nuevo bloque de procesado:
Para generar un nuevo bloque de procesado hay que escribir el siguiente comando una vez se haya posicionado dentro de la carpeta del módulo que queremos que lo incluya, en nuestro caso queremos que el bloque se encuentre dentro del nuevo módulo creado:
$cd gr-nombre_del_módulo
$gr_modtool add nombre_del_bloque
Una vez se haya escrito esto preguntará por el tipo de bloque que deseas añadir, estos son: source, sink, hier, sync, decimator, interpolator, general, noblock. Sin adentrarse en las características de cada uno, se escogerá el bloque de tipo general, una vez escrito general en la pantalla, lo siguiente que se pide es que se introduzca es la lista de argumentos, esto no hace falta todavía puesto que se indicará más tarde, al pulsar la tecla Intro preguntará si se quiere añadir Python QA code, este código es utilizado a modo banco de pruebas para asegurarnos de que el bloque realiza su función correctamente, inmediatamente después se vuelve a preguntar por si se quiere añadir un C++ QA code, otra forma de comprobar el correcto funcionamiento es visualizar el resultado y ver que coincide con el
esperado por lo que no hace falta implementar estos test. Una vez se ha contestado a las preguntas anteriores, el bloque se habrá añadido al módulo, y quedaría por realizar la propia implementación del bloque.
Implementación del bloque de procesado:
En este caso se ha decidido implementar un multiplexor 2:1 a modo ejemplo, se realizarán todos los pasos necesarios para disponer de este nuevo bloque en la interfaz GNU Radio-companion, donde se comprobará su correcto funcionamiento.
Lo primero que se ha de hacer, es escribir el código fuente del nuevo bloque, este se escribirá en el archivo mux_impl.cc, a continuación se muestra el código modificado:
/* The private constructor */
prueba_multiplexor::prueba_multiplexor() : gr_block (“multiplexor”,
gr_make_io_signature(3,3,sizeof(char),sizeof(char),sizeof(char)),//indicamos que son tres entradas; dos de datos y una de control. Las entradas //de
datos son de tipo float, mientras que la de control es short gr_make_io_signature (1,1,sizeof(char)))
// la salida será del mismo tipo que la entrada.
int prueba_mux::general_work (int noutput_items, gr_vector_int &ninput_items,
gr_vector_const_void_star &input_items, gr_vector_void_star &output_items) {
// se asignan las entradas y la salida
const char *in0=(char *) input_items[0]; const char *in1=(char *) input_items[1]; const char *ctrl=(char *) input_items[2];
const char *out=(char*) output_items[0]; for (int i = 0; i<noutput_items; i++){ if (ctrl[i] ==1){ out[i]=in0[i]; } else{ out[i]=in1[i]; } } return noutput_items ;
Si además se quiere disponer del nuevo bloque en la interfaz GNU Radio-companion, se ha de escribir manualmente el archivo xml situado en la carpeta grnombre_del_módulo/grc quedando de la siguiente manera:
<?xml version="1.0"?> <block> <name>multiplexor</name> <key>prueba_multiplexor</key> <category>prueba</category> <import>import prueba</import> <make>prueba.multiplexor()</make> <sink> <name>in</name> <type>byte</type> </sink>
<sink> <name>in</name> <type>byte</type> </sink> <sink> <name>in</name> <type>byte</type> </sink> <source> <name>out</name> <type>byte</type> </source> </block>
Una vez creada la estructura del nuevo módulo e implementado el bloque de procesado, queda por instalar para que esté disponible en el proyecto GNU Radio. Para ello nos situamos en la carpeta raíz del módulo y escribimos en la terminal:
$ mkdir build $ cd build $ cmake ../ $ make
$ sudo make install $ sudo ldconfig
El uso del script presenta diferentes bugs o problemas en el desarrollo de proyectos, tales como:
Al momento de ejecutar el comando “cmake ../” se genera un error de que no encuentra el archivo “gruel_common.i” dando el siguiente aviso: “/usr/local/include/gnuradio/swig/gnuradio.i:31: Error: Unable to find „gruel_common.i…”. Este error se genera por el uso de swig con los parámetro de configuración obtenidos a través del archivo “CmakeLists.txt” en el folder “swig”. Este error se corrige agregando al archivo “CmakeLists.txt” el siguiente código en la línea 38 foreach(incdir ${GRUEL_INCLUDE_DIRS})
list(APPEND GR_SWIG_INCLUDE_DIRS ${incdir}/gruel/swig) endforeach(incdir)
Así también otro método para corregir el error es sustituyendo el archivo “CmakeLists.txt” por el que se ubica en el ejemplo “gr-howto-write-a-block” reemplazando los “howto” por el nombre del módulo del proyecto propio, puede usarse el “CmakeLists.txt” generado por gr-modtool.py para revisar las líneas que deben modificarse.
Este error sólo se genera al momento de crear la estructura de directorios del módulo out-of-tree. Por lo que una vez corregido no se presentará de nuevo.
Al terminar de compilar e instalar el nuevo módulo con sus bloques se genera el error “ImportError: /usr/local/lib… swig.so: undefined symbol: …”. Esto se debe a que no se declaró las funciones del bloque como exportaciones API. El error se corrige dentro de la librería del bloque a implementar (TuMódulo_bloque.h) que se ubica dentro del directorio “include”. Se agrega el código que incluye a la libería API del módulo a desarrollar en la línea 24, esto es arriba de “#include <gr_block.h>”:
24 #include <TuMódulo_api.h>
Además de agregar la invocación de la librería, TUMODULO_API en las líneas 30, 36 y 38 quedando de la siguiente manera:
();
36 class TUMODULO_API TuMódulo_TuBloque : public gr_block 38 friend TUMODULO_API TuMódulo_TuBloque_sptr
TuMódulo_make_TuBloque ();
Este procedimiento se deberá realizar cada vez que se agregue un nuevo bloque al módulo out-of-tree.
Al modificar el módulo, se requiere volver a ejecutar los comandos instalación del bloque.