# Tutorat Système

Etudiants: Raphaël MARTIN, Pierre FRISON.

## nInvaders contrôlé par Arduino

### Procédure automatique

Pour simplifier la mise en place du programme de l'atmega328p et de l'atmega16u2, nous avons créer un script pour guider l'utilisateur dans les manipulations et exécuter les commandes à ça place.

Lancez le script installAndPlay.sh à la racine du projet.

Avec le shield orienté avec le joystick à gauche et les boutons à droite, les commandes sont les suivantes :
 * Bouton gauche : déplacement à gauche
 * Bouton haut : lancer une partie et tirer
 * Bouton droit : déplacement à droite

Amusez-vous bien ! (pour relancer le jeu sans installation utilisez play.sh)

### Procédure manuelle

Si notre script échoue voici la procédure manuelle :
 * Court-circuitez le pin de reset de l'atmega16u2 à la masse
 * cd atmega16u2/base/
 * make
 * Débranchez et rebranchez la carte Arduino
 * cd atmega328p/
 * make upload
 * Court-circuitez le pin de reset de l'atmega16u2 à la masse
 * cd atmega16u2/custom/PolytechLille/PAD/
 * make upload
 * Débranchez et rebranchez la carte Arduino
 * cd ninvaders
 * make exec
 * Le jeu devrait se lancer

## Tests préprogrammés

Avec l'atmega328p et l'atmega16u2 programmé avec nos programmes, il est possible de réaliser différents tests à partir du PC. Il existe 4 programmes de test :
 * ListDevices : retourne une liste de tous les appareils connectés avec des détails.
 * ListEndpoints : cherche l'Arduino et affiche la liste des endpoints programmés avec quelques détails.
 * SendData : cherche l'Arduino et envoi une séquence automatique via les endpoints pour faire clignoter des LEDs sur l'arduino.
 * ReceiveAndSendData : cherche l'Arduino et se met en attente de données envoyé par la carte via l'endpoint dédié aux boutons. Lorsque l'utilisateur appui sur un bouton, les données sont réceptionnées et retourné sur l'endpoint des LEDs pour ordonner à l'Arduino leur allumage.

## Détails et explications techniques

### Modification de nInvaders

Pour implémenter le contrôle par la carte Arduino, nous avons principalement modifié la fonction readInput. Nous avons choisi de lire les entrées par scrutation. Nous avons donc ajouté un timeout à la fonction getch pour le clavier et nous avons utiliser la fonction receiveData avec un timeout de 50 ms. De ce fait le jeu n'est pas bloqué.

Il suffit ensuite de faire correspondre les données reçues avec des actions en jeu.

### Pilote USB

Pour simplifier l'utilisation du code, nous avons créé plusieurs fonctions clées :
 * Une fonction "start" pour initialiser le librairie usb-1.0, chercher la carte Arduino grâce à ses IDs, réclamer les interfaces, détacher le kernel des interfaces et lister les endpoints dans un tableau.
 * Une fonction "sendData" pour envoyer des données.
 * Une fonction "receiveData" pour recevoir des données.
 * Une fonction "stop" pour libérer les interfaces et supprimer les structures de données.

Ce découpage s'inspire du fonctionnement des sockets (dans son utilisation uniquement, le fonctionnement étant évidemment différent).

### atmega328p

L'atmega328p nous sert ici pour acquérir la valeur des différents capteurs (boutons et joystick) et allumer les LEDs sur commande. Pour nous simplifier la tâche, nous avons utiliser un ordonnanceur et écrit 3 tâches :
 * Pour l'affichage des LEDs
 * Pour la lecture de la valeur des boutons
 * Pour la lecture des axes du joystick

### atmega16u2

L'atmega16u2 sert uniquement de traducteur entre le PC et l'atmega328p. Il lit les informations transmises par le PC via les endpoint et le retransmet via liaison série et vis versa. (Voir "Conventions pour la communication" pour plus de détails sur les traductions).

### Conventions pour la communication

De 328p vers 16u2 : 0bXYZZZZZZ
* X = 0 -> les Z sont les états de chaque bouton
* X = 1 & Y = 0 -> les Z correspondent à la valeur X du joystick
* X = 1 & Y = 1 -> les Z correspondent à la valeur Y du joystick

De 16u2 vers PC. Cas des boutons (Endpoint 0x83) : 0b00ZZZZZZ
* 2u2 -> PC (endpoint button 1) : 0b000ZZZZZ
* Z : état d'un bouton

De 16u2 vers PC. Cas du joystick (Endpoint 0x84) : 0b1YZZZZZZ
* 12u2 -> PC (endpoint button 2) : 0bX0YYYYYY
* X = 0 -> valeur en X du joystick
* X = 1 -> valeur en Y du joystick

De PC vers 16u2. Cas des LEDs 8 9 10 11 12 (Endpoint 0x01) : 0b000XXXXX
* X = état d'une LED (LEDs 8 9 10 11 12)

De PC vers 16u2. Cas de la LED 13 (Endpoint 0x02) : 0b0000000X
* X = état de la LED 13

De 16u2 vers 328p : 0b00YYYYYY
* Y = état d'une LED (LEDs 8 9 10 11 12 13)

## Notes

Les licences de certains programmes ont été supprimé pour gagner de la place (nInvaders notemment). Ce projet est à usage privé uniquement.

