TPI SE3 2024/2025
Objectif du projet informatique
Le but de ce projet est de vous faire concevoir et réaliser deux programmes. Un programme classique sur PC et un programme tournant sur un système embarqué. Les deux programmes vont utiliser des bibliothèques, à la fois des bibliothèques USB (libusb-1.0, bibliothèque joystick et LUFA) mais aussi des bibliothèques que vous allez devoir concevoir et écrire.
Matériel
Poour 2024/2025 vous pouvez utiliser la carte "programmateur ISP" que vous avez réalisé en "programmation des systèmes embarqués", en particulier si vous avez prévu assez de boutons et de LED. Si votre carte ne vous parait pas adaptée, vous pouvez utiliser une des manettes déjà réalisées.
Les boutons seront utilisés pour diriger votre vaisseau et les LED pour afficher votre nombre de vies restantes.
En cas de microcontrôleur non initialisé ou briqué, il est toujours possible de flasher l’ATMega32u4 au travers du connecteur ICSP prévu. Un connecteur ICSP dispose de toutes les lignes permettant de flasher un ATMega, à savoir l’alimentation, le reset et les lignes du bus SPI. Si vous en arrivez là, il vous faudra un Arduino à utiliser comme programmateur et quelques câbles pour connecter l’Arduino à la manette.
Programmation sur microcontrôleur
Vous devez programmer l'ATmega8u2 de votre carte ou l’ATMega32u4 de la manette pour gérer le bus USB et réaliser un périphérique USB. Vous utiliserez avr-gcc
comme compilateur C. Le téléchargement du programme sur le microcontrôleur se fera en utilisant l’utilitaire dfu-programmer
capable de programmer les AVR ATMega8u2 et ATMega32u4 via le bus USB. Vous n’aurez pas à programmer directement les registres du microntrôleur pour gérer l’USB, vous utiliserez une bibliothèque nommée LUFA dont une version utilisable est disponible ici.
Sur le principe vous devez implanter un périphérique USB HID (périphérique d’interface homme-machine, Human Interface Device en patoi). Plus précisement vous devez implanter un périphérique USB HID clavier. Un tel périphérique comporte une interface de classe HID avec au minimum un point d’accès entrant (IN). Vous devez faire en sorte que votre clavier gère les boutons de la carte comme des touches. Votre clavier USB doit aussi contrôler les LED présentes sur la carte.
Vous ajouterez à ce périphérique USB une interface supplémentaire pour gérer les codes des touches. L’interface supplémentaire doit présenter un point d’accès de type interruption en écriture (endpoint OUT). Les données envoyées sur ce point d’accès doivent avoir une taille de deux octets. Le premier octet représente le numéro du bouton sur la carte, le second octet représente le code (symbole) retourné au PC par votre clavier lorsque le bouton est utilisé. Grâce à cette interface supplémentaire vous pourrez programmer votre "clavier USB" pour envoyer les codes des touches utilisées par votre jeu "envahisseur".
Les associations numéro de bouton et code de touche doivent être sauvées en EEPROM. Pour cela vous pouvez utiliser les fonctions d'avr-gcc
dont les prototypes se trouvent dans <avr/eeprom.h
,
à savoir eeprom_write_byte
et eeprom_read_byte
.
Installation d'un chargeur DFU
Cette étape n'est probablement pas nécessaire, les AVR avec gestion USB matérielle étant généralement programmés d'usine avec un tel chargeur.
Pour installer un chargeur vous devez utiliser un programmateur AVR sous la forme d’un Arduino Uno programmé avec le programme ArduinoISP
.
Commencez par modifier les fuses du microcontrôleur pour lui demander d’utiliser une horloge externe (à partir de 8Mhz) et permettre d’appeler le chargeur avec le bouton HWB :
avrdude -c stk500v1 -p atmega32u4 -P /dev/ttyACM0 -b 19200 -U lfuse:w:0xFF:m -U efuse:w:0xF7:m
Ensuite utilisez l'un des binaires de cette Fichier:AVR DFU bootloaders.zip et flashez le sur le microcontrôleur :
avrdude -c stk500v1 -p atmega32u4 -P /dev/ttyACM0 -b 19200 -U flash:w:ATMega32U4-usbdevice_dfu-1_0_0.hex
Enfin connectez votre carte en USB et vérifiez qu’elle est bien en mode DFU/USB avec la commande lsusb
.
5.2 Téléversement du programme
Pour téléverser votre programme sur l’ATMega32u4, le paquetage Debian dfu-programmer est nécessaire. Installez le au besoin. La procédure à suivre pour charger votre programme sur l’ATMega32u4 est la suivante :
appuyez sur le bouton de passage en mode chargeur (bouton HWB) puis sur le bouton de réinitialisation (RST), relachez d’abord le second puis le premier ; la carte doit être listée comme en mode DFU dans un lsusb, vous pouvez alors exécuter les commandes suivantes :
dfu-programmer atmega32u4 erase dfu-programmer atmega32u4 flash Manette.hex dfu-programmer atmega32u4 reset
vous pouvez aussi taper simplement make dfu ; débranchez et rebranchez votre carte, votre programme doit être actif sur l’ATMega32u4.
5.3 Prise en main
Commencez par un test basique de la manette : faites clignoter des LED. Testez aussi les boutons. Pour le programme de test, vous pouvez partir du programme que vous avez écrit dans le module "microprocesseur". 5.4 Code LUFA d’exemple
Sur le site http://www.fourwalledcubicle.com/LUFA.php, téléchargez la dernière version de la bibliothèque USB LUFA. Créez un répertoire PolytechLille au même niveau que les répertoires Demos et Projects. Dans ce répertoire, copiez la démonstration du sous-chemin Device/LowLevel/Joystick sous le nom, par exemple, Manette. Renommez aussi les fichiers dans le répertoire et modifiez le makefile. Au niveau du makefile indiquez atmega32u4 comme microcontrôleur, NONE comme platine, ajustez le chemin d’accès LUFA_PATH et passez à 8Mhz. 5.5 Adaptation du code à la manette
Modifiez le fichier makefile. Modifiez ensuite le fichier Manette.c, en particulier la fonction CALLBACK_HID_Device_CreateHIDReport pour créer des rapports HID en fonction des valeurs retournées par les boutons. 5.6 Gestion des actionneurs
En toute théorie, il serait possible d’intégrer la gestion des LED sous la classe USB HID. Le moins que l’on puisse dire c’est que cela complexifie considérablement le descripteur HID et encore il faut faire de l’ingéniérie inverse pour le constituer. Nous allons donc procéder autrement. Vous allez ajouter, à l’interface standard HID, une autre interface de classe spécifique au vendeur (USB_CSCP_VendorSpecificClass, pas de descripteur supplémentaire nécessaire) peuplée d’un point d’accès de type interruption en écriture (endpoint OUT). La communication sur ce point d’accès se fera sur un octet. Ce octet doit commander les LED de la carte.
Pour la gestion des points d’accès interruption, vous pouvez vous aider de la démonstration Keyboard dans le répertoire Device/LowLevel. La déclaration des interfaces et des points d’accès est clairement montrée dans les fichiers Descriptors.c et Descriptors.h de cette démonstration. La gestion de points d’accès de type interruption est montrée dans l’autre source C de la démonstration, cherchez les fonctions Endpoint_ConfigureEndpoint, Endpoint_SelectEndpoint, etc.
N’hésitez pas à consulter la documentation de la bibliothèque sur Internet. 6 Utilisation en tant que manette dans le jeu
Pour utiliser votre manette dans le jeu "envahisseurs" que vous programmez utilisez le pilote joystick SDL.
Vous pouvez vous appuyer sur le tutoriel : https://alexandre-laurent.developpez.com/tutoriels/sdl/joysticks/. 7 Utilisation des LED de la manette dans le jeu
Nous souhaitons enfin pouvoir utiliser les actionneurs de la manette (LED). Nous n’avons pas intégré ces actionneurs à l’interface HID mais nous avons créé une interface spécifique pour les contrôler.
Nous allons donc utiliser la bibliothèque USB libusb-1.0 pour écrire des fonctions C permettant de contrôler les LED. Vous avez le manuel complet de la bibliothèque à l’URL http://libusb.sourceforge.net/api-1.0/modules.html. Vous trouverez un résumé de la bibliothèque à l’URL https://rex.plil.fr/Enseignement/Systeme/Systeme.PSE/. Pour cette utilisation assez basique nous utiliserons les fonctions de communication bloquantes. 7.1 Enumération des périphériques USB
Ecrivez une fonction pour examiner tous les périphériques USB disponibles sur les bus USB de votre machine de TP. Dès qu’un périphérique s’avère être un périphérique USB du type cherché, sauvez la "poignée" (obtenue avec libusb_open) vers ce périphérique dans un tableau statique global de type libusb_device_handle* periphs[MAX_PERIPH].
Vous pouvez utiliser la commande lsusb pour trouver les identifiants USB de votre type de périphérique. Pour chaque périphérique sélectionné, faites afficher le numéro du bus sur lequel se trouve le périphérique ainsi que son adresse sur ce bus. 7.2 Appropriation des interfaces spécifiques
Une fois un périphérique détecté, il faut récupérer sa configuration. La fonction libusb_get_active_config_descriptor qui permet cela nécessite un pointeur sur périphérique de type libusb_device *. Vous pouvez retrouver ce pointeur en fonction de la "poignée" par la fonction libusb_get_device. Faites afficher la valeur de cette configuration.
Il vous reste ensuite, à réclamer les interfaces nécessaires pour votre usage. Attention, la fonction libusb_claim_interface nécessite le numéro de l’interface et pas son indice. Vous allez donc parcourir la structure arborescente de description de configuration du périphérique de la façon suivante :
itérer sur le nombre d’interfaces ; explorer chaque sous-structure d’interface de classe LIBUSB_CLASS_VENDOR_SPEC ; pour chaque interface, prendre la première alternative d’interface ; trouver le numéro d’interface pour utilisation avec libusb_claim_interface ; récupérer le point d’accès présent, sauver le numéro du point d’accès dans une variable globale (pas la peine de déclarer un tableau, tous les périphériques de même identifiant sont réputés avoir les mêmes numéros de point d’accès).
Affichez l’indice et le numéro de chaque interface détectée et réclamée. Affichez aussi le numéro du point d’accès trouvé. 7.3 Fermeture du périphérique USB
Ecrivez une fonction qui libère les périphériques détectés. Pour cela, relachez toutes les interfaces réclamées puis fermez la "poignée". Vous allez devoir, à nouveau, explorer la structure arborescente de description de configuration du périphérique ou sauver les numéros des interfaces dans le tableau global. Affichez l’indice et le numéro de chaque interface libérée. 7.4 Gestion des actionneurs
Vous pouvez maintenant ajouter le contrôle des LED sous la forme d’une bibliothèque dynamique (répertoire à part dans votre projet "envahisseurs"). Les fonctions de cette bibliothèque sont a appeler dans votre jeu.
L’état du vaisseau doit être affiché, sous la forme d’un barre de vie, sur les LED de la manette.
Ce document a été traduit de LATEX par HEVEA