« SE3 PSE Binome2023-1 » : différence entre les versions
Aucun résumé des modifications |
|||
(13 versions intermédiaires par le même utilisateur non affichées) | |||
Ligne 14 : | Ligne 14 : | ||
== Séance 2 --- 11 Mars 2024 == | == Séance 2 --- 11 Mars 2024 == | ||
[[Fichier:Schématique_Kicad.jpg|droite| | [[Fichier:Schématique_Kicad.jpg|droite|616x616px]] | ||
Ligne 21 : | Ligne 21 : | ||
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. | 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| | [[Fichier:3d manette.png|sans_cadre|501x501px|gauche]][[Fichier:Pcbmanette.png|sans_cadre|532x532px]] | ||
== Séance 3 --- 18 Mars 2024 == | == Séance 3 --- 18 Mars 2024 == | ||
Ligne 53 : | Ligne 53 : | ||
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>. | 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>. | ||
Avec notre code, un seul des | 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 == | == Séance 9 --- 22 Mai 2024 == | ||
Le problème était qu'il fallait changer le type de carte dans le Makefile en "NONE". | 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]] | [[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
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.
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 :
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:
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
.
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.