Cours:Elen4 TNS TP TpsReel : Différence entre versions
(→Seconde partie - codage d'un filtre RII) |
|||
Ligne 2 : | Ligne 2 : | ||
<center> | <center> | ||
− | '''<big>TP6 : Temps réel : Codage d'un bloc en C++ / démodulation | + | '''<big>TP6 : Temps réel : Codage d'un bloc en C++ / démodulation </big>''' |
</center> | </center> | ||
− | Le but de ce TP est de réaliser l'implémentation temps-réel en C++ de filtres IIR. | + | Le but de ce TP est de réaliser l'implémentation temps-réel en C++ de filtres IIR. Cette implémentation sera réalisée en créant un bloc Gnuradio qui execute un traitement codé en C++ |
=== Codage de bloc Gnuradio en c++ === | === Codage de bloc Gnuradio en c++ === | ||
− | |||
− | |||
Ce guide est inspirée du guide [https://wiki.gnuradio.org/index.php?title=Creating_C%2B%2B_OOT_with_gr-modtool Creating an OOT (C++ block example)] en l'adaptant pour nos besoins : | Ce guide est inspirée du guide [https://wiki.gnuradio.org/index.php?title=Creating_C%2B%2B_OOT_with_gr-modtool Creating an OOT (C++ block example)] en l'adaptant pour nos besoins : | ||
Ligne 19 : | Ligne 17 : | ||
* Vous pourrez utiliser <code>gedit</code> pour éditer les divers fichiers. | * Vous pourrez utiliser <code>gedit</code> pour éditer les divers fichiers. | ||
− | + | ==== Création d'un module externe ==== | |
Dans les lignes qui suivent, le <code>$</code> indique que l'on saisi une commande dans un terminal. Le <code>$</code> n'est pas à saisir. | Dans les lignes qui suivent, le <code>$</code> indique que l'on saisi une commande dans un terminal. Le <code>$</code> n'est pas à saisir. | ||
Ligne 45 : | Ligne 43 : | ||
</source> | </source> | ||
− | + | ==== Création d'un bloc dans ce module ==== | |
* Ajoutez un nouveau bloc nommé <code>passetout</code> : | * Ajoutez un nouveau bloc nommé <code>passetout</code> : | ||
Ligne 96 : | Ligne 94 : | ||
* Le tout sera compilé par un <code>Makefile</code> généré par <code>cmake</code>. | * Le tout sera compilé par un <code>Makefile</code> généré par <code>cmake</code>. | ||
− | + | ==== Fichier <code>passetout_impl.h</code> ==== | |
Le code utile généré est le suivant : | Le code utile généré est le suivant : | ||
Ligne 123 : | Ligne 121 : | ||
Le travail sera réalisé dans la méthode <code>work()</code>, mais nous n'avons pas de modification à apporter dans les déclarations par défaut. | Le travail sera réalisé dans la méthode <code>work()</code>, mais nous n'avons pas de modification à apporter dans les déclarations par défaut. | ||
− | + | ==== Fichier <code>passetout_impl.cc</code> ==== | |
+ | |||
Le code utile généré est le suivant : | Le code utile généré est le suivant : | ||
Ligne 220 : | Ligne 219 : | ||
# changer <code>return noutput_items;</code> en <code>return 1;</code> (un seul échantillon a été consommé). | # changer <code>return noutput_items;</code> en <code>return 1;</code> (un seul échantillon a été consommé). | ||
− | + | ==== Fichier <code>monModule_passetout.block.yml</code> ==== | |
Ce fichier au format YAML (''yet another markup language'') fait le lien entre le code c++ et le code python utilisé en interne par GnuRadio. | Ce fichier au format YAML (''yet another markup language'') fait le lien entre le code c++ et le code python utilisé en interne par GnuRadio. | ||
Ligne 304 : | Ligne 303 : | ||
</source> | </source> | ||
− | + | ==== Compilation et installation ==== | |
Voici les étapes : | Voici les étapes : | ||
Ligne 322 : | Ligne 321 : | ||
{{Todos| Exécuter chacune de ces lignes, en contrôlant l'absence d'erreur. Dans le cas contraire, contrôler les fichiers <code>.h</code>, <code>.cc</code> et <code>.yaml</code>}} | {{Todos| Exécuter chacune de ces lignes, en contrôlant l'absence d'erreur. Dans le cas contraire, contrôler les fichiers <code>.h</code>, <code>.cc</code> et <code>.yaml</code>}} | ||
− | + | ==== Utilisation du bloc et test ==== | |
* Dans GRC, rafraichir la liste des bloc (bouton ''reload'') | * Dans GRC, rafraichir la liste des bloc (bouton ''reload'') |
Version du 28 mars 2023 à 10:26
TP6 : Temps réel : Codage d'un bloc en C++ / démodulation
Le but de ce TP est de réaliser l'implémentation temps-réel en C++ de filtres IIR. Cette implémentation sera réalisée en créant un bloc Gnuradio qui execute un traitement codé en C++
Sommaire
[masquer]Codage de bloc Gnuradio en c++
Ce guide est inspirée du guide Creating an OOT (C++ block example) en l'adaptant pour nos besoins :
Nous allons créer un simple bloc qui recopie son entrée (en float
) sur sa sortie. Donc le filtre caractérisé par y(n) = x(n) ou encore H(z)=1. Il s'agit donc d'une sorte de filtre passe-tout.
Suivez bien toutes les étapes, sans aller trop rapidement
- Vous pourrez utiliser
gedit
pour éditer les divers fichiers.
Création d'un module externe
Dans les lignes qui suivent, le $
indique que l'on saisi une commande dans un terminal. Le $
n'est pas à saisir.
- Ouvrez un terminal et placez-vous à la racine de votre dossier personnel :
$ cd $HOME
- Créez un dossier de travail dédié à gnuradio et déplacez-vous à l'intérieur :
$ mkdir gnuradio
$ cd gnuradio
- GNU Radio est livré avec gr_modtool, un utilitaire qui permet de créer des modules externes (OOT). Créons un module
monModule
$ gr_modtool newmod monModule
- Le dossier
gr-monModule
est créé et contient tout le code squelette d'un module OOT, mais il n'a pas encore de blocs. Déplacez-vous dansgr-monModule
:
$ cd gr-monModule
- Vous pouvez afficher le contenu de ce dossier par
$ ls
Création d'un bloc dans ce module
- Ajoutez un nouveau bloc nommé
passetout
:
$ gr_modtool add passetout
- Quelques questions permettent alors de spécifier le type de bloc
GNU Radio module name identified: passetout
('sink', 'source', 'sync', 'decimator', 'interpolator', 'general', 'tagged_stream', 'hier', 'noblock')
Saisissez sync
comme type de bloc, car le bloc que nous écrivons produira le même nombre d'échantillons en sortie que le nombre d'échantillons consommés depuis l'entrée.
Enter block type: sync
- Spécifiez
cpp
comme langage :
Language (python/cpp): cpp
Language: C++
Block/code identifier: passetout
- Spécifiez un nom pour le copyright :
Please specify the copyright holder: Bibi
- Il est possible de spécifier des paramètres d'entrée qui peuvent permettre de régler le fonctionnement du bloc. Ce ne sera pas notre cas, ne rien saisir sur cette question :
Enter valid argument list, including default arguments:
- De même, on ne donnera pas de code permettant de tester le bon fonctionnement :
Add Python QA code? [Y/n] n
Add C++ QA code? [Y/n] n
- Plusieurs fichers sont alors crées :
Adding file 'lib/passetout_impl.h'...
Adding file 'lib/passetout_impl.cc'...
Adding file 'include/gnuradio/monModule/passetout.h'...
Adding file 'python/monModule/bindings/docstrings/passetout_pydoc_template.h'...
Adding file 'python/monModule/bindings/passetout_python.cc'...
Adding file 'grc/monModule_passetout.block.yml'...
Editing grc/CMakeLists.txt...
Quelques indications :
- le fichier
passetout_impl.h
contient l'entête de la classe de notre bloc - le fichier
passetout_impl.cc
contient l'implémentation de la classe de notre bloc - le fichier
monModule_passetout.block.yml
va contenir des informations faisant le lien entre notre code c++ et le code python utilisé en interne par Gnuradio - Le tout sera compilé par un
Makefile
généré parcmake
.
Fichier passetout_impl.h
Le code utile généré est le suivant :
class passetout_impl : public passetout
{
private:
// Nothing to declare in this block.
public:
passetout_impl();
~passetout_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);
};
Pour se réveiller les neurones sur la POO, qu'est-ce que sont
-
passetout_impl()
, -
~passetout_impl()
, -
private
,public
?
Le travail sera réalisé dans la méthode work()
, mais nous n'avons pas de modification à apporter dans les déclarations par défaut.
Fichier passetout_impl.cc
Le code utile généré est le suivant :
passetout_impl.cc
Détaillons :
#pragma message("set the following appropriately and remove this warning")
using input_type = float;
#pragma message("set the following appropriately and remove this warning")
using output_type = float;
On spécifie ici le type des données d'entrée et de sortie. Pas de modification à apporter, il suffit de supprimer les deux
#pragma
passetout_impl::passetout_impl()
: gr::sync_block("passetout",
gr::io_signature::make(
1 /* min inputs */, 1 /* max inputs */, sizeof(input_type)),
gr::io_signature::make(
1 /* min outputs */, 1 /*max outputs */, sizeof(output_type)))
{
}
On spécifie ici le nombre d'entrée (1) et le nombre de sorties (1). Pas de modification non plus.
Expliquez la syntaxe
passetout_impl::passetout_impl() : gr::sync_block(...)"
int passetout_impl::work(int noutput_items,
gr_vector_const_void_star& input_items,
gr_vector_void_star& output_items)
{
auto in = static_cast<const input_type*>(input_items[0]);
auto out = static_cast<output_type*>(output_items[0]);
#pragma message("Implement the signal processing in your block and remove this warning")
// Do <+signal processing+>
// Tell runtime system how many output items we produced.
return noutput_items;
}
Cette méthode work()
implémente véritablement le filtrage.
- Les tableaux
in
etout
contiennent respectivement les données en entrée et les données en sortie. Il faut donc calculerout
en fonction dein
- Les données d'entrée arrivent par paquets dans un buffer. La variable
noutput_items
contient le nombre de données disponibles en entrées. - à la fin de la méthode, on renvoie le nombre de données en sortie que l'on a calculé (entre 1 et
noutput_items
). Les données d'entrées éventuellement non consommées seront conservées dans le buffer pour le prochain appel dework()
On souhaite ici seulement recopier l'entrée sur la sortie, donc
- Enlever la ligne
#pragma
- ajouter le code
out[0] = in[0];
(on recopie le premier échantillon disponible en entrée) - changer
return noutput_items;
enreturn 1;
(un seul échantillon a été consommé).
Fichier monModule_passetout.block.yml
Ce fichier au format YAML (yet another markup language) fait le lien entre le code c++ et le code python utilisé en interne par GnuRadio.
monModule_passetout.block.yml
Mettre à jour la section
parameters
(pas de paramètres, on commente) :
#parameters:
#- id: parametername_replace_me
# label: FIX ME:
# dtype: string
# default: You need to fill in your grc/customModule_testMod.block.yaml
Mettre à jour la section
inputs
:
inputs:
- label: in0
domain: stream
dtype: float
Mettre à jour la section
output
:
outputs:
- label: out0
domain: stream
dtype: float
Compilation et installation
Voici les étapes :
$ cd CHEMIN-DE-VOTRE-DOSSIER/gr-monModule
$ mkdir build
$ cd build
$ cmake ..
$ make
$ make install
-
cmake ..
lance la création des fichiersMakefile
qui permettent la compilation et l'installation -
make
lance la compilation -
make install
lance l'installation (copie des fichiers dans les dossiers gnuradio)
Exécuter chacune de ces lignes, en contrôlant l'absence d'erreur. Dans le cas contraire, contrôler les fichiers
.h
, .cc
et .yaml
Utilisation du bloc et test
- Dans GRC, rafraichir la liste des bloc (bouton reload)
- le bloc
passetout
doit être présent dans la sectionmonModule
- Tester le bon fonctionnement de ce bloc en lui envoyant une sinusoïde que vous devez observer identique à la sortie du bloc. Vérifier avec des graphes.