« SE3 PSE Binome2023-1 » : différence entre les versions

De projets-se.plil.fr
Aller à la navigation Aller à la recherche
(Page créée avec « Sa »)
 
 
(138 versions intermédiaires par 2 utilisateurs non affichées)
Ligne 1 : Ligne 1 :
Sa
=<div class="mcwiki-header" style="border-radius: 40px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #33AFDE; vertical-align: top; width: 98%;"> Manette Space Invader </div>=
''Notre projet est de créer une manette de jeu sur mesure, spécialement conçue pour être compatible avec le jeu Space Invader sur lequel nous avons pu travailler au cours du projet d'informatique. En utilisant un PCB, nous cherchons à offrir une interface simple mais efficace qui permet une expérience de jeu ✧・゚: *lumineuse*:・゚✧.''
 
=<div class="mcwiki-header" style="border-radius: 40px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #97D8F0; vertical-align: top; width: 98%;"> Limitations et fonctionnalités </div>=
 
* Taille de la carte : 10x10 cm maximum
* Utilisation de LEDs <span style="color: Red;">rouges</span> selon ce qu'il se passe dans le jeu (victoire, défaite, tirs, etc.)
* 4 boutons : deux de déplacement (gauche et droite), un de tir et un dernier pour toute action supplémentaire que nous déterminerons par la suite
 
=<div class="mcwiki-header" style="border-radius: 40px; padding: 15px; font-weight: bold; color: #FFFFFF; text-align: center; font-size: 80%; background: #97D8F0; vertical-align: top; width: 98%;"> Déroulé du Projet </div>=
== Séance 1 --- 4 Mars 2024 ==
Découverte du sujet et prise de décisions sur les fonctionnalités de la manette.
 
== Séance 2 --- 11 Mars 2024 ==
[[Fichier:Schématique_Kicad.jpg|droite|616x616px]]
 
 
 
Nous avons finalisé le choix des composants, en sélectionnant les éléments nécessaires pour notre manette. Les composants retenus incluent le microcontrôleur ATMega16u4, des boutons poussoirs, et biensur, de nombreuses LEDs. Une fois cette sélection terminée, nous avons commencé la conception du schéma électrique de notre PCB. Voici le rendu final (cette conception a pris quelques séances de plus pour le finaliser et le corriger afin de l'envoyer se faire produire. Nous jugeons judicieux de mettre le rendu final dans cette section
 
Une remarque à faire est que nous n'avons pas tout à fait bien placé les boutons poussoir lors du routage. En tout cas, ils n'ont pas la disposition optimale considérant leurs utilités et noms respectifs.  En effet, lors de la programmation de ces derniers nous veillerons bien a se référer au bons boutons.
[[Fichier:3d manette.png|sans_cadre|501x501px|gauche]][[Fichier:Pcbmanette.png|sans_cadre|532x532px]]
 
== Séance 3 --- 18 Mars 2024 ==
Durant cette séance, nous terminons la conception et du routage du PCB et nous avons utilisé un fichier Makefile (qui a été fourni lors de TP de MicroProcesseurs plus tôt dans le semestre) pour exécuter un code visant à faire clignoter des LEDs sur une carte des étudiants de l'année dernière.
 
Voici la vidéo de l'exécution de notre code et notre code :                                                                                                                   
 
[[Fichier:Clignotement.mp4|bordure|gauche|400x400px]][[Fichier:Code Clignotement LED .jpg|600x600px|droite|sans_cadre]]<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>Cette partie du projet nous permet de comprendre comment nous aurons à nous y prendre lors de la programmation de notre future manette, notamment pour la manipulation de LEDs, ce qui dans notre cas est plutôt pertinent.
== Séance 4 --- 25 Mars 2024 ==
Voici notre lien git : https://archives.plil.fr/kelbachi/Projet-USB.git
 
== Séance 5 --- 3 Avril 2024 ==
 
Nous avons reçu notre carte, nous soudons les composants (ATmega16u4, Quartz, Port USB, ISP, etc.). Notre séance s'est essentiellement écoulée sur une tentative de resolution du probleme de notre carte à l'aide d'un Arduino et en utilisant la connexion ISP:
[[Fichier:Installation_Bootloader.jpg|gauche|sans_cadre|489x489px]][[Fichier:Video_leds.mp4|sans_cadre|530x470px]]
 
 
<br><br><br>Nous ne trouvons pas le problème de la carte. En effet elle n'apparaît pas lors de la saisie de la commande <code>lsusb</code> dans le terminal. Ainsi, après plusieurs essais nous avons décidé de recommencer notre carte, nous avons un ATmega16u4 qui a un Bootloader préinstallé.
 
== Séance 6 --- 8 Avril 2024 ==
Après avoir décidé lors de la seance precedente de recommencer la soudure des composant depuis le départ, nous continuons de faire cela.
 
== Séance 7 --- 10 Avril 2024 ==
 
Nous avons maintenant une carte avec un Bootloader fonctionnel. On la detecte ave la commande <code>lsusb</code>.
[[Fichier:Lsusb fonctionne.jpg|centré|sans_cadre|552x552px]]
 
 
Nous passons par la suite a la programmation de la LUFA.
== Séance 8 --- 17 Avril 2024 ==
En modifiant le fichier Joystick présent dans les fichiers que nous avons récupérés en début de projet, nous devons obtenir le code nous permettant d'identifier la manette comme un Joystick, avec des axe X, Y et des boutons. Nous les testerons avec la commande <code>jstest-gtk</code>.
 
Tout d'abord nous avons écrit notre code, nous modifions les fonctions <code>SteupHardware(void)</code> et <code>GetNextReport(USB_JoystickReport_Data_t* const ReportData)</code>:
 
<syntaxhighlight lang="c" line>
void SetupHardware(void)
{
#if (ARCH == ARCH_AVR8)
/* Disable watchdog if enabled by bootloader/fuses */
MCUSR &= ~(1 << WDRF);
wdt_disable();
 
/* Disable clock division */
clock_prescale_set(clock_div_1);
#elif (ARCH == ARCH_XMEGA)
/* Start the PLL to multiply the 2MHz RC oscillator to 32MHz and switch the CPU core to run from it */
XMEGACLK_StartPLL(CLOCK_SRC_INT_RC2MHZ, 2000000, F_CPU);
XMEGACLK_SetCPUClockSource(CLOCK_SRC_PLL);
 
/* Start the 32MHz internal RC oscillator and start the DFLL to increase it to 48MHz using the USB SOF as a reference */
XMEGACLK_StartInternalOscillator(CLOCK_SRC_INT_RC32MHZ);
XMEGACLK_StartDFLL(CLOCK_SRC_INT_RC32MHZ, DFLL_REF_INT_USBSOF, F_USB);
 
PMIC.CTRL = PMIC_LOLVLEN_bm | PMIC_MEDLVLEN_bm | PMIC_HILVLEN_bm;
#endif
 
/* Hardware Initialization */
DDRD &= ~((1<<LEFT) | (1<<UP) | (1<<DOWN));
DDRC &= ~(1<<RIGHT);
PORTD |= (1<<LEFT) | (1<<UP) | (1<<DOWN);
PORTC |= (1<<RIGHT);
USB_Init();
}
 
/** Event handler for the USB_Connect event. This indicates that the device is enumerating via the status LEDs and
*  starts the library USB task to begin the enumeration and USB management process.
*/
void EVENT_USB_Device_Connect(void)
{
/* Indicate USB enumerating */
LEDs_SetAllLEDs(LEDMASK_USB_ENUMERATING);
}
 
</syntaxhighlight>
<br>
<syntaxhighlight lang="c" line>
bool GetNextReport(USB_JoystickReport_Data_t* const ReportData)
{
bool          InputChanged    = true;
 
/* Clear the report contents */
memset(ReportData, 0, sizeof(USB_JoystickReport_Data_t));
 
 
if (!(PINC & (1 << RIGHT))) ReportData->X=100;
if (!(PIND & (1 << LEFT))) ReportData->X=-100;
if (!(PIND & (1 << UP)))  ReportData->Button |= 1;
if (!(PIND & (1 << DOWN)))  ReportData->Button |= 2;
 
 
/* Return whether the new report is different to the previous report or not */
return InputChanged;
}
</syntaxhighlight>
 
Avec notre code, un seul des boutons ne fonctionne et <span style="color: Silver;">-spoiler alert-</span> nous n'avons pas trouvé la source du problème lors de cette séance.
 
== Séance 9 --- 22 Mai 2024 ==
Le problème était qu'il fallait changer le type de carte (BOARD) dans le Makefile en "NONE":
 
<syntaxhighlight lang="c" line>
CU          = atmega16u4
ARCH        = AVR8
BOARD        = NONE
F_CPU        = 8000000
F_USB        = $(F_CPU)
OPTIMIZATION = s
TARGET      = Joystick
SRC          = $(TARGET).c Descriptors.c $(LUFA_SRC_USB)
LUFA_PATH    = ../../LUFA
CC_FLAGS    = -DUSE_LUFA_CONFIG_HEADER -IConfig/
</syntaxhighlight>
 
[[Fichier:Video Joystick.mp4|centré|sans_cadre|600x500px]]
 
== Séance 10 --- 28 Mai 2024 ==
 
Nous avons modifié le fichier Minimal.c pour pouvoir manipuler les LEDs. On le fusionne alors avec notre fichier Joystick.c pour pouvoir manipuler les LEDs et les boutons en même temps.
Nous n'avons pas réussi à faire fonctionner cette fusion, mais voilà nos deux codes:
 
1- Minimal.c:
 
<syntaxhighlight lang="c" line>
/** \file
*
*  Main source file for the Minimal demo. This file contains the main tasks of the demo and
*  is responsible for the initial application hardware configuration.
*/
 
#define INCLUDE_FROM_MINIMAL_C#include "Minimal.h"
 
#define JTD 7
 
/** Main program entry point. This routine configures the hardware required by the application, then
*  enters a loop to run the application tasks in sequence.
*/
int main(void) {
 
  SetupHardware();
  MCUCR |= (1 << JTD);
  MCUCR |= (1 << JTD);
  GlobalInterruptEnable();
 
  for (;;) {
    USB_USBTask();
    fct_IN();
    fct_OUT();
 
  }
}
 
/** Configures the board hardware and chip peripherals for the demo's functionality. */
void SetupHardware(void) {
  #if(ARCH == ARCH_AVR8)
  /* Disable watchdog if enabled by bootloader/fuses */
  MCUSR &= ~(1 << WDRF);
  wdt_disable();
 
  /* Disable clock division */
  clock_prescale_set(clock_div_1);
  #elif(ARCH == ARCH_XMEGA)
  /* Start the PLL to multiply the 2MHz RC oscillator to 32MHz and switch the CPU core to run from it */
  XMEGACLK_StartPLL(CLOCK_SRC_INT_RC2MHZ, 2000000, F_CPU);
  XMEGACLK_SetCPUClockSource(CLOCK_SRC_PLL);
 
  /* Start the 32MHz internal RC oscillator and start the DFLL to increase it to 48MHz using the USB SOF as a reference */
  XMEGACLK_StartInternalOscillator(CLOCK_SRC_INT_RC32MHZ);
  XMEGACLK_StartDFLL(CLOCK_SRC_INT_RC32MHZ, DFLL_REF_INT_USBSOF, F_USB);
 
  PMIC.CTRL = PMIC_LOLVLEN_bm | PMIC_MEDLVLEN_bm | PMIC_HILVLEN_bm;
  #endif
 
  /* Hardware Initialization */
  USB_Init();
  //(volatile uint8_t) DDRF;
  DDRD |= (1 << 2) | (1 << 3); // Configure PD2 and PD3 as outputs
  DDRD &= ~((1 << 4) | (1 << 5) | (1 << 6) | (1 << 7)); // Configure PD4 to PD7 as inputs
  DDRC |= (1 << 6); // Configure PC6 as output
  DDRC &= ~(1 << 7); // Configure PC7 as input
  DDRF |= (1 << 0) | (1 << 1);
}
 
/** Event handler for the USB_Connect event. This indicates that the device is enumerating via the status LEDs. */
void EVENT_USB_Device_Connect(void) {
  // Allume une LED pour indiquer que l'appareil est connecté
  PORTF |= (1 << 0); // Utilise PF0 pour indiquer la connexion
}
 
/** Event handler for the USB_Disconnect event. This indicates that the device is no longer connected to a host via
*  the status LEDs.
*/
void EVENT_USB_Device_Disconnect(void) {
  // Éteint la LED pour indiquer que l'appareil est déconnecté
  PORTF &= ~(1 << 0); // Utilise PF0 pour indiquer la déconnexion
}
 
/** Event handler for the USB_ConfigurationChanged event. This is fired when the host set the current configuration
*  of the USB device after enumeration - the device endpoints are configured.
*/
void EVENT_USB_Device_ConfigurationChanged(void) {
  Endpoint_ConfigureEndpoint(EPADDR_IN, EP_TYPE_INTERRUPT, EPSIZE, 1);
  Endpoint_ConfigureEndpoint(EPADDR_OUT, EP_TYPE_INTERRUPT, EPSIZE, 1);
 
  // Allume une autre LED pour indiquer que la configuration a changé
  PORTF |= (1 << 1); // Utilise PF1 pour indiquer le changement de configuration
}
 
/** Event handler for the USB_ControlRequest event. This is used to catch and process control requests sent to
*  the device from the USB host before passing along unhandled control requests to the library for processing
*  internally.
*/
 
void BlinkLEDs(void) {
  // Code pour clignoter les LEDs
  for (int i = 0; i < 10; i++) { // Blink 10 times
    PORTF |= 0x03; // Allume toutes les LEDs
    _delay_ms(200); // Attendre 200ms
    PORTF &= ~0x03; // Éteint toutes les LEDs
    _delay_ms(200); // Attendre 200ms
  }
}
 
void EVENT_USB_Device_ControlRequest(void) {
  // Gère les requêtes de contrôle USB
  switch (USB_ControlRequest.bRequest) {
  case 0x01: // Requête pour clignoter les LEDs en cas de collision
    BlinkLEDs();
    Endpoint_ClearSETUP(); // Préparer pour les réponses (si nécessaire)
    Endpoint_Write_8(0x00); // Répondre avec une valeur si nécessaire
    Endpoint_ClearIN(); // Finaliser la réponse (si nécessaire)
    break;
 
    // Ajoute d'autres cas de requêtes de contrôle si nécessaire
  default:
    break;
  }
}
 
void fct_OUT(void) {
  /* Select the OUT Endpoint */
  Endpoint_SelectEndpoint(EPADDR_OUT);
  /* Check if Endpoint contains a packet */
  if (Endpoint_IsOUTReceived()) {
    /* Check to see if the packet contains data */
    if (Endpoint_IsReadWriteAllowed()) {
      /* Read from the host */
      uint8_t octet1 = Endpoint_Read_8();
      uint8_t octet2 = Endpoint_Read_8();
      /* Process the data from the host */
      if (octet1 <= 127)
        PORTF |= 0x01;
 
      else
        PORTF &= ~0x01;
 
      if (octet2 <= 127)
        PORTF |= 0x2;
      else
        PORTF &= ~0x02;
    }
    /* Handshake the OUT Endpoint - clear endpoint and ready for next report */
    Endpoint_ClearOUT();
  }
}
 
void fct_IN(void) {
  /* Select the IN Endpoint */
  Endpoint_SelectEndpoint(EPADDR_IN);
  /* Check if Endpoint Ready for Read/Write */
  if (Endpoint_IsReadWriteAllowed()) {
    /* Write Keyboard Report Data */
    uint8_t c;
    c = 42;
    Endpoint_Write_8(c);
 
    /* Affiche un message dans le terminal pour indiquer que l'octet a été envoyé */
    printf("1 octet bien envoyé depuis la manette\n");
 
    /* Finalize the stream transfer to send the last packet */
    Endpoint_ClearIN();
  }
}
</syntaxhighlight>
 
2- Fusion.c:
 
<syntaxhighlight lang="c" line>
 
/** \file
*
*  Main source file for the Minimal Joystick demo. This file contains the main tasks of the demo and
*  is responsible for the initial application hardware configuration.
*/
 
#include "Minimal.h"
#include "Joystick.h"
 
#define JTD 7
#define DOWN PD4
#define LEFT PD5
#define UP PD7
#define RIGHT PC7
 
/** Main program entry point. This routine configures the hardware required by the application, then
*  enters a loop to run the application tasks in sequence.
*/
int main(void) {
  SetupHardware();
  MCUCR |= (1 << JTD);
  MCUCR |= (1 << JTD);
  GlobalInterruptEnable();
 
  for (;;) {
    USB_USBTask();
    fct_IN();
    fct_OUT();
    HID_Task();
  }
}
 
/** Configures the board hardware and chip peripherals for the demo's functionality. */
void SetupHardware(void) {
#if (ARCH == ARCH_AVR8)
  /* Disable watchdog if enabled by bootloader/fuses */
  MCUSR &= ~(1 << WDRF);
  wdt_disable();
 
  /* Disable clock division */
  clock_prescale_set(clock_div_1);
#elif (ARCH == ARCH_XMEGA)
  /* Start the PLL to multiply the 2MHz RC oscillator to 32MHz and switch the CPU core to run from it */
  XMEGACLK_StartPLL(CLOCK_SRC_INT_RC2MHZ, 2000000, F_CPU);
  XMEGACLK_SetCPUClockSource(CLOCK_SRC_PLL);
 
  /* Start the 32MHz internal RC oscillator and start the DFLL to increase it to 48MHz using the USB SOF as a reference */
  XMEGACLK_StartInternalOscillator(CLOCK_SRC_INT_RC32MHZ);
  XMEGACLK_StartDFLL(CLOCK_SRC_INT_RC32MHZ, DFLL_REF_INT_USBSOF, F_USB);
 
  PMIC.CTRL = PMIC_LOLVLEN_bm | PMIC_MEDLVLEN_bm | PMIC_HILVLEN_bm;
#endif
 
  /* Hardware Initialization */
  USB_Init();
 
  // Joystick Initialization
  DDRD &= ~((1 << LEFT) | (1 << UP) | (1 << DOWN));
  DDRC &= ~(1 << RIGHT);
  PORTD |= (1 << LEFT) | (1 << UP) | (1 << DOWN);
  PORTC |= (1 << RIGHT);
 
  // Minimal Demo Initialization
  DDRD |= (1 << 2) | (1 << 3); // Configure PD2 and PD3 as outputs
  DDRD &= ~((1 << 4) | (1 << 5) | (1 << 6) | (1 << 7)); // Configure PD4 to PD7 as inputs
  DDRC |= (1 << 6); // Configure PC6 as output
  DDRC &= ~(1 << 7); // Configure PC7 as input
  DDRF |= (1 << 0) | (1 << 1);
}
 
/** Event handler for the USB_Connect event. This indicates that the device is enumerating via the status LEDs. */
void EVENT_USB_Device_Connect(void) {
  // Allume une LED pour indiquer que l'appareil est connecté
  PORTF |= (1 << 0); // Utilise PF0 pour indiquer la connexion
  LEDs_SetAllLEDs(LEDMASK_USB_ENUMERATING);
}
 
/** Event handler for the USB_Disconnect event. This indicates that the device is no longer connected to a host via
*  the status LEDs.
*/
void EVENT_USB_Device_Disconnect(void) {
  // Éteint la LED pour indiquer que l'appareil est déconnecté
  PORTF &= ~(1 << 0); // Utilise PF0 pour indiquer la déconnexion
  LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY);
}
 
/** Event handler for the USB_ConfigurationChanged event. This is fired when the host set the current configuration
*  of the USB device after enumeration - the device endpoints are configured.
*/
void EVENT_USB_Device_ConfigurationChanged(void) {
  bool ConfigSuccess = true;
 
  /* Setup HID Report Endpoint */
  ConfigSuccess &= Endpoint_ConfigureEndpoint(JOYSTICK_EPADDR, EP_TYPE_INTERRUPT, JOYSTICK_EPSIZE, 1);
  Endpoint_ConfigureEndpoint(EPADDR_IN, EP_TYPE_INTERRUPT, EPSIZE, 1);
  Endpoint_ConfigureEndpoint(EPADDR_OUT, EP_TYPE_INTERRUPT, EPSIZE, 1);
 
  // Allume une autre LED pour indiquer que la configuration a changé
  PORTF |= (1 << 1); // Utilise PF1 pour indiquer le changement de configuration
 
  /* Indicate endpoint configuration success or failure */
  LEDs_SetAllLEDs(ConfigSuccess ? LEDMASK_USB_READY : LEDMASK_USB_ERROR);
}
 
/** Event handler for the USB_ControlRequest event. This is used to catch and process control requests sent to
*  the device from the USB host before passing along unhandled control requests to the library for processing
*  internally.
*/
void EVENT_USB_Device_ControlRequest(void) {
  // Gère les requêtes de contrôle USB
  switch (USB_ControlRequest.bRequest) {
  case 0x01: // Requête pour clignoter les LEDs en cas de collision
    BlinkLEDs();
    Endpoint_ClearSETUP(); // Préparer pour les réponses (si nécessaire)
    Endpoint_Write_8(0x00); // Répondre avec une valeur si nécessaire
    Endpoint_ClearIN(); // Finaliser la réponse (si nécessaire)
    break;
 
    // Ajoute d'autres cas de requêtes de contrôle si nécessaire
  case HID_REQ_GetReport:
    if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE)) {
      USB_JoystickReport_Data_t JoystickReportData;
 
      /* Create the next HID report to send to the host */
      GetNextReport(&JoystickReportData);
 
      Endpoint_ClearSETUP();
 
      /* Write the report data to the control endpoint */
      Endpoint_Write_Control_Stream_LE(&JoystickReportData, sizeof(JoystickReportData));
      Endpoint_ClearOUT();
    }
    break;
 
  default:
    break;
  }
}
 
/** Function to manage HID report generation and transmission to the host. */
void HID_Task(void) {
  /* Device must be connected and configured for the task to run */
  if (USB_DeviceState != DEVICE_STATE_Configured)
    return;
 
  /* Select the Joystick Report Endpoint */
  Endpoint_SelectEndpoint(JOYSTICK_EPADDR);
 
  /* Check to see if the host is ready for another packet */
  if (Endpoint_IsINReady()) {
    USB_JoystickReport_Data_t JoystickReportData;
 
    /* Create the next HID report to send to the host */
    GetNextReport(&JoystickReportData);
 
    /* Write Joystick Report Data */
    Endpoint_Write_Stream_LE(&JoystickReportData, sizeof(JoystickReportData), NULL);
 
    /* Finalize the stream transfer to send the last packet */
    Endpoint_ClearIN();
 
    /* Clear the report data afterwards */
    memset(&JoystickReportData, 0, sizeof(JoystickReportData));
  }
}
 
void BlinkLEDs(void) {
  // Code pour clignoter les LEDs
  for (int i = 0; i < 10; i++) { // Blink 10 times
    PORTF |= 0x03; // Allume toutes les LEDs
    _delay_ms(200); // Attendre 200ms
    PORTF &= ~0x03; // Éteint toutes les LEDs
    _delay_ms(200); // Attendre 200ms
  }
}
 
void fct_OUT(void) {
  /* Select the OUT Endpoint */
  Endpoint_SelectEndpoint(EPADDR_OUT);
  /* Check if Endpoint contains a packet */
  if (Endpoint_IsOUTReceived()) {
    /* Check to see if the packet contains data */
    if (Endpoint_IsReadWriteAllowed()) {
      /* Read from the host */
      uint8_t octet1 = Endpoint_Read_8();
      uint8_t octet2 = Endpoint_Read_8();
      /* Process the data from the host */
      if (octet1 <= 127)
        PORTF |= 0x01;
      else
        PORTF &= ~0x01;
 
      if (octet2 <= 127)
        PORTF |= 0x2;
      else
        PORTF &= ~0x02;
    }
    /* Handshake the OUT Endpoint - clear endpoint and ready for next report */
    Endpoint_ClearOUT();
  }
}
 
void fct_IN(void) {
  /* Select the IN Endpoint */
  Endpoint_SelectEndpoint(EPADDR_IN);
  /* Check if Endpoint Ready for Read/Write */
  if (Endpoint_IsReadWriteAllowed()) {
    /* Write Keyboard Report Data */
    uint8_t c;
    c = 42;
    Endpoint_Write_8(c);
 
    /* Affiche un message dans le terminal pour indiquer que l'octet a été envoyé */
    printf("1 octet bien envoyé depuis la manette\n");
 
    /* Finalize the stream transfer to send the last packet */
    Endpoint_ClearIN();
  }
}
 
/** Fills the given HID report data structure with the next HID report to send to the host.
*
*  \param[out] ReportData  Pointer to a HID report data structure to be filled
*
*  \return Boolean \c true if the new report differs from the last report, \c false otherwise
*/
bool GetNextReport(USB_JoystickReport_Data_t* const ReportData) {
  bool InputChanged = true;
 
  /* Clear the report contents */
  memset(ReportData, 0, sizeof(USB_JoystickReport_Data_t));
 
  if (!(PINC & (1 << RIGHT))) ReportData->X = 100;
  if (!(PIND & (1 << LEFT))) ReportData->X = -100;
  if (!(PIND & (1 << UP))) ReportData->Button |= 1;
  if (!(PIND & (1 << DOWN))) ReportData->Button |= 2;
 
  /* Return whether the new report is different to the previous report or not */
  return InputChanged;
}
 
</syntaxhighlight>
 
== Conclusion ==
 
Nous n'avons pas réussi à terminer le projet de la manette pour le jeu Space Invader en raison de nombreux problèmes techniques et du manque de temps. Malgré nos efforts, les défis rencontrés ont empêché l'achèvement du projet dans les délais impartis.

Version actuelle datée du 10 juin 2024 à 20:39

Manette Space Invader

Notre projet est de créer une manette de jeu sur mesure, spécialement conçue pour être compatible avec le jeu Space Invader sur lequel nous avons pu travailler au cours du projet d'informatique. En utilisant un PCB, nous cherchons à offrir une interface simple mais efficace qui permet une expérience de jeu ✧・゚: *lumineuse*:・゚✧.

Limitations et fonctionnalités

  • Taille de la carte : 10x10 cm maximum
  • Utilisation de LEDs rouges selon ce qu'il se passe dans le jeu (victoire, défaite, tirs, etc.)
  • 4 boutons : deux de déplacement (gauche et droite), un de tir et un dernier pour toute action supplémentaire que nous déterminerons par la suite

Déroulé du Projet

Séance 1 --- 4 Mars 2024

Découverte du sujet et prise de décisions sur les fonctionnalités de la manette.

Séance 2 --- 11 Mars 2024

Schématique Kicad.jpg


Nous avons finalisé le choix des composants, en sélectionnant les éléments nécessaires pour notre manette. Les composants retenus incluent le microcontrôleur ATMega16u4, des boutons poussoirs, et biensur, de nombreuses LEDs. Une fois cette sélection terminée, nous avons commencé la conception du schéma électrique de notre PCB. Voici le rendu final (cette conception a pris quelques séances de plus pour le finaliser et le corriger afin de l'envoyer se faire produire. Nous jugeons judicieux de mettre le rendu final dans cette section

Une remarque à faire est que nous n'avons pas tout à fait bien placé les boutons poussoir lors du routage. En tout cas, ils n'ont pas la disposition optimale considérant leurs utilités et noms respectifs. En effet, lors de la programmation de ces derniers nous veillerons bien a se référer au bons boutons.

3d manette.png

Pcbmanette.png

Séance 3 --- 18 Mars 2024

Durant cette séance, nous terminons la conception et du routage du PCB et nous avons utilisé un fichier Makefile (qui a été fourni lors de TP de MicroProcesseurs plus tôt dans le semestre) pour exécuter un code visant à faire clignoter des LEDs sur une carte des étudiants de l'année dernière.

Voici la vidéo de l'exécution de notre code et notre code :

Code Clignotement LED .jpg




















Cette partie du projet nous permet de comprendre comment nous aurons à nous y prendre lors de la programmation de notre future manette, notamment pour la manipulation de LEDs, ce qui dans notre cas est plutôt pertinent.

Séance 4 --- 25 Mars 2024

Voici notre lien git : https://archives.plil.fr/kelbachi/Projet-USB.git

Séance 5 --- 3 Avril 2024

Nous avons reçu notre carte, nous soudons les composants (ATmega16u4, Quartz, Port USB, ISP, etc.). Notre séance s'est essentiellement écoulée sur une tentative de resolution du probleme de notre carte à l'aide d'un Arduino et en utilisant la connexion ISP:

Installation Bootloader.jpg





Nous ne trouvons pas le problème de la carte. En effet elle n'apparaît pas lors de la saisie de la commande lsusb dans le terminal. Ainsi, après plusieurs essais nous avons décidé de recommencer notre carte, nous avons un ATmega16u4 qui a un Bootloader préinstallé.

Séance 6 --- 8 Avril 2024

Après avoir décidé lors de la seance precedente de recommencer la soudure des composant depuis le départ, nous continuons de faire cela.

Séance 7 --- 10 Avril 2024

Nous avons maintenant une carte avec un Bootloader fonctionnel. On la detecte ave la commande lsusb.

Lsusb fonctionne.jpg


Nous passons par la suite a la programmation de la LUFA.

Séance 8 --- 17 Avril 2024

En modifiant le fichier Joystick présent dans les fichiers que nous avons récupérés en début de projet, nous devons obtenir le code nous permettant d'identifier la manette comme un Joystick, avec des axe X, Y et des boutons. Nous les testerons avec la commande jstest-gtk.

Tout d'abord nous avons écrit notre code, nous modifions les fonctions SteupHardware(void) et GetNextReport(USB_JoystickReport_Data_t* const ReportData):

void SetupHardware(void)
{
#if (ARCH == ARCH_AVR8)
	/* Disable watchdog if enabled by bootloader/fuses */
	MCUSR &= ~(1 << WDRF);
	wdt_disable();

	/* Disable clock division */
	clock_prescale_set(clock_div_1);
#elif (ARCH == ARCH_XMEGA)
	/* Start the PLL to multiply the 2MHz RC oscillator to 32MHz and switch the CPU core to run from it */
	XMEGACLK_StartPLL(CLOCK_SRC_INT_RC2MHZ, 2000000, F_CPU);
	XMEGACLK_SetCPUClockSource(CLOCK_SRC_PLL);

	/* Start the 32MHz internal RC oscillator and start the DFLL to increase it to 48MHz using the USB SOF as a reference */
	XMEGACLK_StartInternalOscillator(CLOCK_SRC_INT_RC32MHZ);
	XMEGACLK_StartDFLL(CLOCK_SRC_INT_RC32MHZ, DFLL_REF_INT_USBSOF, F_USB);

	PMIC.CTRL = PMIC_LOLVLEN_bm | PMIC_MEDLVLEN_bm | PMIC_HILVLEN_bm;
#endif

	/* Hardware Initialization */
	
	DDRD &= ~((1<<LEFT) | (1<<UP) | (1<<DOWN));
	DDRC &= ~(1<<RIGHT);
	PORTD |= (1<<LEFT) | (1<<UP) | (1<<DOWN);
	PORTC |= (1<<RIGHT);
	
	USB_Init();
}

/** Event handler for the USB_Connect event. This indicates that the device is enumerating via the status LEDs and
 *  starts the library USB task to begin the enumeration and USB management process.
 */
void EVENT_USB_Device_Connect(void)
{
	/* Indicate USB enumerating */
	LEDs_SetAllLEDs(LEDMASK_USB_ENUMERATING);
}


bool GetNextReport(USB_JoystickReport_Data_t* const ReportData)
{
	bool           InputChanged     = true;

	/* Clear the report contents */
	memset(ReportData, 0, sizeof(USB_JoystickReport_Data_t));


	if (!(PINC & (1 << RIGHT))) ReportData->X=100;
	if (!(PIND & (1 << LEFT))) ReportData->X=-100; 
	if (!(PIND & (1 << UP)))   ReportData->Button |= 1;
	if (!(PIND & (1 << DOWN)))   ReportData->Button |= 2;


	/* Return whether the new report is different to the previous report or not */
	return InputChanged;
}

Avec notre code, un seul des boutons ne fonctionne et -spoiler alert- nous n'avons pas trouvé la source du problème lors de cette séance.

Séance 9 --- 22 Mai 2024

Le problème était qu'il fallait changer le type de carte (BOARD) dans le Makefile en "NONE":

CU          = atmega16u4
ARCH         = AVR8
BOARD        = NONE
F_CPU        = 8000000
F_USB        = $(F_CPU)
OPTIMIZATION = s
TARGET       = Joystick
SRC          = $(TARGET).c Descriptors.c $(LUFA_SRC_USB)
LUFA_PATH    = ../../LUFA
CC_FLAGS     = -DUSE_LUFA_CONFIG_HEADER -IConfig/

Séance 10 --- 28 Mai 2024

Nous avons modifié le fichier Minimal.c pour pouvoir manipuler les LEDs. On le fusionne alors avec notre fichier Joystick.c pour pouvoir manipuler les LEDs et les boutons en même temps. Nous n'avons pas réussi à faire fonctionner cette fusion, mais voilà nos deux codes:

1- Minimal.c:

/** \file
 *
 *  Main source file for the Minimal demo. This file contains the main tasks of the demo and
 *  is responsible for the initial application hardware configuration.
 */

#define INCLUDE_FROM_MINIMAL_C#include "Minimal.h"

#define JTD 7

/** Main program entry point. This routine configures the hardware required by the application, then
 *  enters a loop to run the application tasks in sequence.
 */
int main(void) {

  SetupHardware();
  MCUCR |= (1 << JTD);
  MCUCR |= (1 << JTD);
  GlobalInterruptEnable();

  for (;;) {
    USB_USBTask();
    fct_IN();
    fct_OUT();

  }
}

/** Configures the board hardware and chip peripherals for the demo's functionality. */
void SetupHardware(void) {
  #if(ARCH == ARCH_AVR8)
  /* Disable watchdog if enabled by bootloader/fuses */
  MCUSR &= ~(1 << WDRF);
  wdt_disable();

  /* Disable clock division */
  clock_prescale_set(clock_div_1);
  #elif(ARCH == ARCH_XMEGA)
  /* Start the PLL to multiply the 2MHz RC oscillator to 32MHz and switch the CPU core to run from it */
  XMEGACLK_StartPLL(CLOCK_SRC_INT_RC2MHZ, 2000000, F_CPU);
  XMEGACLK_SetCPUClockSource(CLOCK_SRC_PLL);

  /* Start the 32MHz internal RC oscillator and start the DFLL to increase it to 48MHz using the USB SOF as a reference */
  XMEGACLK_StartInternalOscillator(CLOCK_SRC_INT_RC32MHZ);
  XMEGACLK_StartDFLL(CLOCK_SRC_INT_RC32MHZ, DFLL_REF_INT_USBSOF, F_USB);

  PMIC.CTRL = PMIC_LOLVLEN_bm | PMIC_MEDLVLEN_bm | PMIC_HILVLEN_bm;
  #endif

  /* Hardware Initialization */
  USB_Init();
  //(volatile uint8_t) DDRF;
  DDRD |= (1 << 2) | (1 << 3); // Configure PD2 and PD3 as outputs
  DDRD &= ~((1 << 4) | (1 << 5) | (1 << 6) | (1 << 7)); // Configure PD4 to PD7 as inputs
  DDRC |= (1 << 6); // Configure PC6 as output
  DDRC &= ~(1 << 7); // Configure PC7 as input
  DDRF |= (1 << 0) | (1 << 1);
}

/** Event handler for the USB_Connect event. This indicates that the device is enumerating via the status LEDs. */
void EVENT_USB_Device_Connect(void) {
  // Allume une LED pour indiquer que l'appareil est connecté
  PORTF |= (1 << 0); // Utilise PF0 pour indiquer la connexion
}

/** Event handler for the USB_Disconnect event. This indicates that the device is no longer connected to a host via
 *  the status LEDs.
 */
void EVENT_USB_Device_Disconnect(void) {
  // Éteint la LED pour indiquer que l'appareil est déconnecté
  PORTF &= ~(1 << 0); // Utilise PF0 pour indiquer la déconnexion
}

/** Event handler for the USB_ConfigurationChanged event. This is fired when the host set the current configuration
 *  of the USB device after enumeration - the device endpoints are configured.
 */
void EVENT_USB_Device_ConfigurationChanged(void) {
  Endpoint_ConfigureEndpoint(EPADDR_IN, EP_TYPE_INTERRUPT, EPSIZE, 1);
  Endpoint_ConfigureEndpoint(EPADDR_OUT, EP_TYPE_INTERRUPT, EPSIZE, 1);

  // Allume une autre LED pour indiquer que la configuration a changé
  PORTF |= (1 << 1); // Utilise PF1 pour indiquer le changement de configuration
}

/** Event handler for the USB_ControlRequest event. This is used to catch and process control requests sent to
 *  the device from the USB host before passing along unhandled control requests to the library for processing
 *  internally.
 */

void BlinkLEDs(void) {
  // Code pour clignoter les LEDs
  for (int i = 0; i < 10; i++) { // Blink 10 times
    PORTF |= 0x03; // Allume toutes les LEDs
    _delay_ms(200); // Attendre 200ms
    PORTF &= ~0x03; // Éteint toutes les LEDs
    _delay_ms(200); // Attendre 200ms
  }
}

void EVENT_USB_Device_ControlRequest(void) {
  // Gère les requêtes de contrôle USB
  switch (USB_ControlRequest.bRequest) {
  case 0x01: // Requête pour clignoter les LEDs en cas de collision
    BlinkLEDs();
    Endpoint_ClearSETUP(); // Préparer pour les réponses (si nécessaire)
    Endpoint_Write_8(0x00); // Répondre avec une valeur si nécessaire
    Endpoint_ClearIN(); // Finaliser la réponse (si nécessaire)
    break;

    // Ajoute d'autres cas de requêtes de contrôle si nécessaire
  default:
    break;
  }
}

void fct_OUT(void) {
  /* Select the OUT Endpoint */
  Endpoint_SelectEndpoint(EPADDR_OUT);
  /* Check if Endpoint contains a packet */
  if (Endpoint_IsOUTReceived()) {
    /* Check to see if the packet contains data */
    if (Endpoint_IsReadWriteAllowed()) {
      /* Read from the host */
      uint8_t octet1 = Endpoint_Read_8();
      uint8_t octet2 = Endpoint_Read_8();
      /* Process the data from the host */
      if (octet1 <= 127)
        PORTF |= 0x01;

      else
        PORTF &= ~0x01;

      if (octet2 <= 127)
        PORTF |= 0x2;
      else
        PORTF &= ~0x02;
    }
    /* Handshake the OUT Endpoint - clear endpoint and ready for next report */
    Endpoint_ClearOUT();
  }
}

void fct_IN(void) {
  /* Select the IN Endpoint */
  Endpoint_SelectEndpoint(EPADDR_IN);
  /* Check if Endpoint Ready for Read/Write */
  if (Endpoint_IsReadWriteAllowed()) {
    /* Write Keyboard Report Data */
    uint8_t c;
    c = 42;
    Endpoint_Write_8(c);

    /* Affiche un message dans le terminal pour indiquer que l'octet a été envoyé */
    printf("1 octet bien envoyé depuis la manette\n");

    /* Finalize the stream transfer to send the last packet */
    Endpoint_ClearIN();
  }
}

2- Fusion.c:

/** \file
 *
 *  Main source file for the Minimal Joystick demo. This file contains the main tasks of the demo and
 *  is responsible for the initial application hardware configuration.
 */

#include "Minimal.h"
#include "Joystick.h"

#define JTD 7
#define DOWN PD4
#define LEFT PD5
#define UP PD7
#define RIGHT PC7

/** Main program entry point. This routine configures the hardware required by the application, then
 *  enters a loop to run the application tasks in sequence.
 */
int main(void) {
  SetupHardware();
  MCUCR |= (1 << JTD);
  MCUCR |= (1 << JTD);
  GlobalInterruptEnable();

  for (;;) {
    USB_USBTask();
    fct_IN();
    fct_OUT();
    HID_Task();
  }
}

/** Configures the board hardware and chip peripherals for the demo's functionality. */
void SetupHardware(void) {
#if (ARCH == ARCH_AVR8)
  /* Disable watchdog if enabled by bootloader/fuses */
  MCUSR &= ~(1 << WDRF);
  wdt_disable();

  /* Disable clock division */
  clock_prescale_set(clock_div_1);
#elif (ARCH == ARCH_XMEGA)
  /* Start the PLL to multiply the 2MHz RC oscillator to 32MHz and switch the CPU core to run from it */
  XMEGACLK_StartPLL(CLOCK_SRC_INT_RC2MHZ, 2000000, F_CPU);
  XMEGACLK_SetCPUClockSource(CLOCK_SRC_PLL);

  /* Start the 32MHz internal RC oscillator and start the DFLL to increase it to 48MHz using the USB SOF as a reference */
  XMEGACLK_StartInternalOscillator(CLOCK_SRC_INT_RC32MHZ);
  XMEGACLK_StartDFLL(CLOCK_SRC_INT_RC32MHZ, DFLL_REF_INT_USBSOF, F_USB);

  PMIC.CTRL = PMIC_LOLVLEN_bm | PMIC_MEDLVLEN_bm | PMIC_HILVLEN_bm;
#endif

  /* Hardware Initialization */
  USB_Init();

  // Joystick Initialization
  DDRD &= ~((1 << LEFT) | (1 << UP) | (1 << DOWN));
  DDRC &= ~(1 << RIGHT);
  PORTD |= (1 << LEFT) | (1 << UP) | (1 << DOWN);
  PORTC |= (1 << RIGHT);

  // Minimal Demo Initialization
  DDRD |= (1 << 2) | (1 << 3); // Configure PD2 and PD3 as outputs
  DDRD &= ~((1 << 4) | (1 << 5) | (1 << 6) | (1 << 7)); // Configure PD4 to PD7 as inputs
  DDRC |= (1 << 6); // Configure PC6 as output
  DDRC &= ~(1 << 7); // Configure PC7 as input
  DDRF |= (1 << 0) | (1 << 1);
}

/** Event handler for the USB_Connect event. This indicates that the device is enumerating via the status LEDs. */
void EVENT_USB_Device_Connect(void) {
  // Allume une LED pour indiquer que l'appareil est connecté
  PORTF |= (1 << 0); // Utilise PF0 pour indiquer la connexion
  LEDs_SetAllLEDs(LEDMASK_USB_ENUMERATING);
}

/** Event handler for the USB_Disconnect event. This indicates that the device is no longer connected to a host via
 *  the status LEDs.
 */
void EVENT_USB_Device_Disconnect(void) {
  // Éteint la LED pour indiquer que l'appareil est déconnecté
  PORTF &= ~(1 << 0); // Utilise PF0 pour indiquer la déconnexion
  LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY);
}

/** Event handler for the USB_ConfigurationChanged event. This is fired when the host set the current configuration
 *  of the USB device after enumeration - the device endpoints are configured.
 */
void EVENT_USB_Device_ConfigurationChanged(void) {
  bool ConfigSuccess = true;

  /* Setup HID Report Endpoint */
  ConfigSuccess &= Endpoint_ConfigureEndpoint(JOYSTICK_EPADDR, EP_TYPE_INTERRUPT, JOYSTICK_EPSIZE, 1);
  Endpoint_ConfigureEndpoint(EPADDR_IN, EP_TYPE_INTERRUPT, EPSIZE, 1);
  Endpoint_ConfigureEndpoint(EPADDR_OUT, EP_TYPE_INTERRUPT, EPSIZE, 1);

  // Allume une autre LED pour indiquer que la configuration a changé
  PORTF |= (1 << 1); // Utilise PF1 pour indiquer le changement de configuration

  /* Indicate endpoint configuration success or failure */
  LEDs_SetAllLEDs(ConfigSuccess ? LEDMASK_USB_READY : LEDMASK_USB_ERROR);
}

/** Event handler for the USB_ControlRequest event. This is used to catch and process control requests sent to
 *  the device from the USB host before passing along unhandled control requests to the library for processing
 *  internally.
 */
void EVENT_USB_Device_ControlRequest(void) {
  // Gère les requêtes de contrôle USB
  switch (USB_ControlRequest.bRequest) {
  case 0x01: // Requête pour clignoter les LEDs en cas de collision
    BlinkLEDs();
    Endpoint_ClearSETUP(); // Préparer pour les réponses (si nécessaire)
    Endpoint_Write_8(0x00); // Répondre avec une valeur si nécessaire
    Endpoint_ClearIN(); // Finaliser la réponse (si nécessaire)
    break;

    // Ajoute d'autres cas de requêtes de contrôle si nécessaire
  case HID_REQ_GetReport:
    if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE)) {
      USB_JoystickReport_Data_t JoystickReportData;

      /* Create the next HID report to send to the host */
      GetNextReport(&JoystickReportData);

      Endpoint_ClearSETUP();

      /* Write the report data to the control endpoint */
      Endpoint_Write_Control_Stream_LE(&JoystickReportData, sizeof(JoystickReportData));
      Endpoint_ClearOUT();
    }
    break;

  default:
    break;
  }
}

/** Function to manage HID report generation and transmission to the host. */
void HID_Task(void) {
  /* Device must be connected and configured for the task to run */
  if (USB_DeviceState != DEVICE_STATE_Configured)
    return;

  /* Select the Joystick Report Endpoint */
  Endpoint_SelectEndpoint(JOYSTICK_EPADDR);

  /* Check to see if the host is ready for another packet */
  if (Endpoint_IsINReady()) {
    USB_JoystickReport_Data_t JoystickReportData;

    /* Create the next HID report to send to the host */
    GetNextReport(&JoystickReportData);

    /* Write Joystick Report Data */
    Endpoint_Write_Stream_LE(&JoystickReportData, sizeof(JoystickReportData), NULL);

    /* Finalize the stream transfer to send the last packet */
    Endpoint_ClearIN();

    /* Clear the report data afterwards */
    memset(&JoystickReportData, 0, sizeof(JoystickReportData));
  }
}

void BlinkLEDs(void) {
  // Code pour clignoter les LEDs
  for (int i = 0; i < 10; i++) { // Blink 10 times
    PORTF |= 0x03; // Allume toutes les LEDs
    _delay_ms(200); // Attendre 200ms
    PORTF &= ~0x03; // Éteint toutes les LEDs
    _delay_ms(200); // Attendre 200ms
  }
}

void fct_OUT(void) {
  /* Select the OUT Endpoint */
  Endpoint_SelectEndpoint(EPADDR_OUT);
  /* Check if Endpoint contains a packet */
  if (Endpoint_IsOUTReceived()) {
    /* Check to see if the packet contains data */
    if (Endpoint_IsReadWriteAllowed()) {
      /* Read from the host */
      uint8_t octet1 = Endpoint_Read_8();
      uint8_t octet2 = Endpoint_Read_8();
      /* Process the data from the host */
      if (octet1 <= 127)
        PORTF |= 0x01;
      else
        PORTF &= ~0x01;

      if (octet2 <= 127)
        PORTF |= 0x2;
      else
        PORTF &= ~0x02;
    }
    /* Handshake the OUT Endpoint - clear endpoint and ready for next report */
    Endpoint_ClearOUT();
  }
}

void fct_IN(void) {
  /* Select the IN Endpoint */
  Endpoint_SelectEndpoint(EPADDR_IN);
  /* Check if Endpoint Ready for Read/Write */
  if (Endpoint_IsReadWriteAllowed()) {
    /* Write Keyboard Report Data */
    uint8_t c;
    c = 42;
    Endpoint_Write_8(c);

    /* Affiche un message dans le terminal pour indiquer que l'octet a été envoyé */
    printf("1 octet bien envoyé depuis la manette\n");

    /* Finalize the stream transfer to send the last packet */
    Endpoint_ClearIN();
  }
}

/** Fills the given HID report data structure with the next HID report to send to the host.
 *
 *  \param[out] ReportData  Pointer to a HID report data structure to be filled
 *
 *  \return Boolean \c true if the new report differs from the last report, \c false otherwise
 */
bool GetNextReport(USB_JoystickReport_Data_t* const ReportData) {
  bool InputChanged = true;

  /* Clear the report contents */
  memset(ReportData, 0, sizeof(USB_JoystickReport_Data_t));

  if (!(PINC & (1 << RIGHT))) ReportData->X = 100;
  if (!(PIND & (1 << LEFT))) ReportData->X = -100;
  if (!(PIND & (1 << UP))) ReportData->Button |= 1;
  if (!(PIND & (1 << DOWN))) ReportData->Button |= 2;

  /* Return whether the new report is different to the previous report or not */
  return InputChanged;
}

Conclusion

Nous n'avons pas réussi à terminer le projet de la manette pour le jeu Space Invader en raison de nombreux problèmes techniques et du manque de temps. Malgré nos efforts, les défis rencontrés ont empêché l'achèvement du projet dans les délais impartis.