SE3 PSE Binome2023-9
Bienvenue sur le Wiki Manette ! Ce wiki est organisé de manière chronologique, et l'avancement est mis à jour à chaque séance.
4 Mars 2024
Découverte du sujet et des fichiers fournis.
11 Mars 2024, PCB
Ajout de deux boutons qui permettent d'obtenir une manette style Master System et de 4 LEDs qui peuvent servir d'indicateurs de vies ou autre...
Le PCB est routé, les coins sont légèrement arrondis pour une meilleure prise en main.
Fichier GERBER de la manette: Fichier:SE3-pad-bonningre-GERBER.zip
18 Mars 2024, AVR
J'utilise le Makefile fournit pour les TP MicroP pour compiler le code puis le mode DFU de l'atmega8u2 pour envoyer le code dans la carte en USB avec 'dfu-programmer'
25 Mars 2024, GIT
Aujourd'hui travail sur le programme avec la bibliothèque LUFA, les fichiers sont sur le GIT du projet : GIT
La partie Lufa est dans le dossier `Manette/Lufa` du dépôt (le dossier `src` contient le jeu space invaders)
3 Avril 2024, PCB
Le PCB est arrivé, je soude les composants nécessaires pour faire fonctionner l'atmega et une LED pour le tester.
La LED connectée au 5v s'allume mais impossible de détecter l'atmega en USB (mode DFU) avec la commande lsusb
Je test au multimètre que les différents pins 5V sont bien alimentés, les pins Reset et HWB sont aussi bien pullup à 5V (GND quand boutons respectifs appuyés) et la continuité sur les pins D- et D+ de l'USB est bien présente.
Peut-être que l'atmega32u4 n'a pas le bootloader avec DFU USB de préinstallé (ou que les fuses internes ne sont pas correctement configurées pour notre crystal), je soude le connecteur ISP pour essayer de le programmer via cette interface
Avec un programmateur ISP je lis la partie de l'atmega qui contient le bootloader, elle est apparemment vide et on peut voir que les fuses sont 0x52 0x99 et 0xFF (avec le calculateur de fuse pour atmega32u4 on constate que ce n'est pas les valeurs qu'il faut pour notre projet)
8 Avril 2024, DFU et Bootloader
Grâce à l'aide de monsieur Redon le problème est résolue et la carte est bien reconnue en USB, nous sommes parvenu à programmer la manette par ISP mais pour plus de simplicité il faut installer le bootloader USB.
Pour les commandes utilisant une arduino comme programmeur ISP il faut indiquer -c stk500v1
au lieu de -c arduino
sinon on obtient un erreur et l'atmega n'est pas programmé.
Pour commencer il faut utiliser la commande suivante pour modifier les fuses (avec une Arduino comme programmeur ISP), ça permet de faire comprendre à l'atmega32u4 qu'on utilise un crystal 8Mhz et qu'il faut pouvoir passer en DFU 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 il faut télécharger le bootloader USB sur le site microchip : Bootloader DFU AVR (tableau Embedded Software) et le flasher avec la commande suivante (toujours par ISP avec l'Arduino) :
avrdude -c stk500v1 -p atmega32u4 -P /dev/ttyACM0 -b 19200 -U flash:w:ATMega32U4-usbdevice_dfu-1_0_0.hex
On débranche le programmateur ISP et on branche la manette en USB, elle apparait bien avec lsusb
:
On peut ensuite modifier le makefile du code Lufa en changeant le type de MCU et la fréquence (8Mhz), et programmer la manette directement par USB avec la commande make dfu
. Pour repasser en DFU il suffit de maintenir le bouton HWB pendant un reset.
Tous les composants sont soudés :
En modifiant le code Lufa on peut allumer les led, pour celles sur les pins PF4 et PF5 il faut désactiver le JTAG en copiant deux fois cette ligne au niveau de la déclaration des pins : MCUCR |= (1<<JTD);
Il ne reste plus qu'à contrôler les LEDs avec un endpoint et ajouter le code pour les boutons, affaire à suivre...
10 Avril 2024, Lufa
Maintenant que les LEDs sont bien initialisées et contrôlables je m'attaque aux boutons, il n'y a pas de pullup sur le PCB, il faut donc utiliser les PullUp intégrés de l'AVR
Je test ensuite au multimètre, on a bien 5V sur les pins des boutons (avant la configuration des pullup il y avait entre 0.5 et 2v) et 0v quand ils sont appuyés.
Je retourne maintenant sur Lufa et LibUSB pour envoyer des données sur l'endpoint. Le code est dans le dépôt GIT
10 Avril 2024, Lufa
En modifiant l'exemple Joystick de la bibliothèque Lufa on obtient la partie Joystick du projet, la manette est bien reconnue comme un Joystick 2 axes et 2 boutons.
On peut les tester avec jstest-gtk
Ici on appuie sur le bouton du bas et A, ça fonctionne parfaitement
Pour les LEDs, en modifiant minimal.c et en utilisant libusb on peut contrôler les leds en envoyant des données dans l'endpoint.
Lors de la séance prochaine il faudra donc merge les deux projets Lufa pour avoir la fonction Joystick et le contrôle des LEDs en même temps.
22 Mai 2024, Lufa
Les deux projets ont été merge, la manette comporte donc une interface HID pour le Joystick et une interface pour les LEDs.
Dans le fichier qui permet d'envoyer des données sur l'endpoint il a fallu remplacer libusb_get_device_descriptor()
par libusb_get_active_config_descriptor()
car le noyau capture le Joystick.
L'InPoint pour les LEDs a été supprimé, on ne fait qu'envoyer un octet dans l'Endpoint pour allumer ou éteindre les Led, l'interface des LEDs ne renvoie aucune donnée donc l'Inpoint n'était pas utile.
La partie hardware du projet est terminée, il ne reste plus qu'à ajouter la gestion du Joystick et des Leds dans le Space Invaders.
Fin du projet
La gestion du joystick et la gestion des LEDs de la manette ont été ajoutées au jeu Space Invaders. Le joystick permet de déplacer le joueur et de tirer un missile. Lors du tir d'un missile, les 4 LEDs de la manette s'allument. Il faut ensuite attendre (cooldown) pour pouvoir tirer à nouveau. Pendant ce temps d'attente, les LEDs s'éteignent successivement. Lorsque les LEDs sont toutes éteintes, le canon est prêt à tirer à nouveau.
Quelques exemples des fonctions ajoutées dans Space Invaders.
Cette fonction vérifie si la manette (Louloupad) est branchée et que LibUSB arrive à envoyer des données dans l'endpoint (autorisations suffisantes)
if (SendToController(0x01) == 0){ // On test si l'envoi de données dans l'endpoint fonctionne (Louloupad branché ET autorisations suffisantes pour LibUSB)
led = 1;
allumer_toutes_leds(led);
}
Exemple de fonction qui contrôle les LEDs, cette fonction allume toutes les LEDs de la manette, la fonction SendToController est définie dans le fichier src/LibUSB/usb.c
/*
* Cette fonction allume toutes les leds de la manette, seulement si le paramètre led est à 1
* Led est à 1 seulement si le Louloupad est branché et Space est executé en superutilisateur (nécessaire pour utiliser LibUSB)
*/
void allumer_toutes_leds(int led){
if(led){
SendToController(0x01);
SendToController(0x02);
SendToController(0x03);
SendToController(0x04);
}
}
Pour le déplacement du joueur il suffit de comparer la position du Joystick et de lire le bouton appuyé avec les fonctions SDL_JoystickGetAxis()
et SDL_SDL_JoystickGetButton()
Par exemple pour le déplacement à droite :
if (SDL_JoystickGetAxis(Joystick, 0) > 0){
move_liste(*player, MOUVEMENT_LATERAL_PLAYER, 0); // Déplacement à droite
}
Le code du jeu ainsi que les différentes Lufa utilisées au long du projet (Joystick seul, LEDs seules, merge des deux) et les fichiers tests qui m'ont permis d'envoyer des données dans l'endpoint avec LibUSB sont tous dans le dêpot GIT du projet (lien un peu plus haut sur cette page).
Vidéo finale du projet :