<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="fr">
	<id>https://projets-se.plil.fr/mediawiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Adjadjaa</id>
	<title>projets-se.plil.fr - Contributions [fr]</title>
	<link rel="self" type="application/atom+xml" href="https://projets-se.plil.fr/mediawiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Adjadjaa"/>
	<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php/Sp%C3%A9cial:Contributions/Adjadjaa"/>
	<updated>2026-04-17T00:42:31Z</updated>
	<subtitle>Contributions</subtitle>
	<generator>MediaWiki 1.39.1</generator>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-5&amp;diff=7385</id>
		<title>SE4Binome2024-5</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-5&amp;diff=7385"/>
		<updated>2025-01-26T16:37:57Z</updated>

		<summary type="html">&lt;p&gt;Adjadjaa : /* Explications générales sur la réalisation de la carte */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Introduction=&lt;br /&gt;
&lt;br /&gt;
Ce wiki documente le développement d’un pico-ordinateur modulaire. Ce dernier est constitué d’une carte principale, composée d’une carte Shield permettant la connexion des cartes filles, et d’une carte mère (initialement simulée par une Arduino Uno avant sa conception finale). Plusieurs cartes filles sont prévues, chacune remplissant une fonction spécifique : gestion du clavier, affichage, port série, réseau, mémoire de masse et son.&lt;br /&gt;
&lt;br /&gt;
Notre binôme est spécifiquement chargé du développement de la carte fille dédiée au clavier.&lt;br /&gt;
&lt;br /&gt;
Toutes les ressources nécessaires, incluant les codes sources et les schémas, sont disponibles sur le dépôt Git suivant :  [https://gitea.plil.fr/ktouron/se4-djadja-touron_pico.git Lien du Git]&lt;br /&gt;
&lt;br /&gt;
= Carte Shield =&lt;br /&gt;
[[Fichier:Carte Recto non soudé.jpg|vignette|left|thumb|350px|Recto de la carte avant soudage des composants]]&lt;br /&gt;
[[Fichier:Verso non solder.jpeg.jpg|vignette|thumb|right|300px|Verso de la carte avant soudage des composants]]&lt;br /&gt;
[[Fichier:Carde shield soudé.jpg|vignette|thumb|center|350px|Photo de la carte avec les composants soudés]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Test==&lt;br /&gt;
=== Allumage de LEDS sur Programmateur AVR ===&lt;br /&gt;
Avant de programmer directement sur le shield, nous avons allumé des LED pour tester la carte. Nous avons directement utilisé le code exemple fourni par l'IDE arduino en adaptant simplement les pins correspondant aux leds. [https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/PicoShield/Programmation/Blink Code du test]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Vid_test_carte_mp4.mp4|vignette|thumb|center|700px|Vidéo de Test des leds]]&lt;br /&gt;
&lt;br /&gt;
=== Lecture de la carte SD ===&lt;br /&gt;
Avant de programmer directement sur le shield, nous avons tester si la carte SD était bien détectée et lue. On a utilisé le code test présent dans l'IDE arduino en adaptant le port utilisé.[https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/PicoShield/Programmation/CardInfo Code du test]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Resultat SD.jpg|vignette|thumb|center|700px|Carte SD bien détéctée]]&lt;br /&gt;
&lt;br /&gt;
=== Connecteurs IDC HE10 ===&lt;br /&gt;
Afin de tester nos connecteur HE10, nous avons utilisé un afficher 7 segments (Sparkfun 7 segments display). Pour pouvoir vérifier leurs fonctionnements nous avons branché l'afficheur sur chaque connecteur tour à tour. Le programme implanté est un simple connecteur à afficher sur l'afficheur. Voici une vidéo du compteur fonctionnant sur un des 5 connecteurs HE10. ([https://learn.sparkfun.com/tutorials/using-the-serial-7-segment-display/all Code ici (section : Example 2 SPI)])&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Se4-5-7segments.mp4|vignette|alt=se4-5-7segments|Test connecteur HE10 avec afficheur 7 segments.|center]]&lt;br /&gt;
&lt;br /&gt;
== Ordonnanceur ==&lt;br /&gt;
Pour les interruptions de notre ordonnanceur nous avons utilisé la procédure d'initialisation du minuteur avec le Timer1 disponible dans les cours de Mr.Redon en renseignant une période de 20ms. Nous l'avons disposé dans le fichier minuteur.c car nous n'allons plus le modifier pour le reste du projet. Dans un autre fichier process.c (avec process.h), nous allons y mettre nos structures pour les process et leurs états puis une union pour le temps qui le caractérise ainsi que toutes les fonctions associés.&lt;br /&gt;
&lt;br /&gt;
[https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/Ordonnanceur Lien du répertoire]&lt;br /&gt;
&lt;br /&gt;
=== Processus ===&lt;br /&gt;
==== Structure ====&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:right; width: 48%; padding-left: 10px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
    uint16_t adresseDepart;  //adresse de la fonction de départ &lt;br /&gt;
    uint16_t adressePile;       //adresse de la pile d'exécution&lt;br /&gt;
    Etat etat;        &lt;br /&gt;
} Process;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Notre structure caractérisant un processus est définie par les trois champs ci-contre.&lt;br /&gt;
&lt;br /&gt;
Une adresse de départ correspondant à la fonction du processus associé, l'adresse où se situe le processus dans la pile puis l'état de la tâche. Nous avons décidé de faire une structure à part entière compte tenu des multitudes d'états que nous pourrons ajouter pendant la progression du projet.&lt;br /&gt;
&lt;br /&gt;
==== Etat d'un processus ====&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:right; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
typedef union {&lt;br /&gt;
  int sleepingtime;       &lt;br /&gt;
} Time;&lt;br /&gt;
&lt;br /&gt;
typedef struct {&lt;br /&gt;
  int id;&lt;br /&gt;
  Time time;&lt;br /&gt;
} Etat ;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
L'état d'un processus est alors une structure à deux champs (pour l'instant), l'id doit correspondre à un '#DEFINE' pour avoir un sens tandis que nous avons choisi de faire une union pour le temps qui caractérise notre état afin qu'il puisse avoir un nom et type de variable cohérent avec son état.(Ici seulement sleepingtime car seul l'état endormi existe pour le moment)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
  {| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
  |+ Tableau des états&lt;br /&gt;
  |-&lt;br /&gt;
  ! Etat !! ACTIVE !! SLEEPY !! ... !! ...&lt;br /&gt;
  |-&lt;br /&gt;
  | Id || 0 || 1 || ... || ...&lt;br /&gt;
  |}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Procédures principales ====&lt;br /&gt;
&lt;br /&gt;
=== ISR ===&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:right; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
ISR(TIMER1_COMPA_vect, ISR_NAKED)    // Procédure d'interruption&lt;br /&gt;
{&lt;br /&gt;
  TCNT1=0;//reset timer&lt;br /&gt;
  /* Sauvegarde du contexte de la tâche interrompue */&lt;br /&gt;
  portSAVE_REGISTERS();&lt;br /&gt;
   table_process[indice_tache].adressePile = SP;&lt;br /&gt;
  /* Appel à l'ordonnanceur */&lt;br /&gt;
  selectProcess();&lt;br /&gt;
  /* Récupération du contexte de la tâche ré-activée */&lt;br /&gt;
  SP = table_process[indice_tache].adressePile;&lt;br /&gt;
  portRESTORE_REGISTERS();&lt;br /&gt;
  &lt;br /&gt;
  asm volatile ( &amp;quot;reti&amp;quot; );&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
L'ISR est ce qu'il va être executer lors des interruptions toutes les 20 millisecondes. Cela consiste à sauvegarder tous les registres de la tâche qui était en cours avant l'appel de l'ISR pour ensuite passer à la tâche suivante valide (c'est à dire active) sans oublier de charger les registres de la nouvelle tâche.&lt;br /&gt;
&lt;br /&gt;
Nous devons également, à chaque fois avant de changer de tâche, enregistrer le pointeur de pile dans le processus afin de pouvoir revenir là ou elle en est la prochaine fois qu'elle sera appelée. Respectivement, une fois la nouvelle tâche choisie, le pointeur de pile doit prendre l'adresse de là ou en était la tâche avant qu'elle soit interrompue.&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Séléction de processus ====&lt;br /&gt;
Lors de la séléction de processus, nous devons parcourir tous les processus jusqu'au moment où nous en trouvons un actif. Ainsi, il deviendra la tâche que nous traiterons lors du prochain intervalle de 20 ms. A ce stade, à chaque fois que la procédure selectProcess est appelée, nous devons réduire le temps de repos de chaque process endormi de 20 ms. D'autres conditions pourrons être ajoutée si ajout d'état a lieu. (voir l'ajout de selectProcess dans l'ISR)&lt;br /&gt;
&lt;br /&gt;
=== Test ===&lt;br /&gt;
==== Clignotement de deux LED à fréquences indivisibles entre elles ====&lt;br /&gt;
Afin de vérifier la réussite de notre ordonnanceur à fonctionnement tourniquet, nous avons programmer deux simples tâches changeant l'état d'une LED. Une à une fréquence 200ms et l'autre 300ms (avec un _delay_ms).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:left; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void tache1(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTC ^= (1 &amp;lt;&amp;lt; PC0);&lt;br /&gt;
    _delay_ms(300);}}&lt;br /&gt;
void tache2(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTD ^= (1 &amp;lt;&amp;lt; PD7);&lt;br /&gt;
    _delay_ms(200);}}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
[[Fichier:B5_test1.mp4|vignette|alt=test des frequences imprevisibles|test des frequences imprevisibles]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Clignotement grâce à l'état endormi ====&lt;br /&gt;
Nous ajoutons l'état endormi afin que nos tâches ne mettent pas en pause l'ordonnanceur avec un _delay_ms. Pour cela, nous incorporons une fonction makeSleep qui permet de mettre la tâche qui l'appelle dans cet état.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:left; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void makeSleep(int t){&lt;br /&gt;
  table_process[indice_tache].etat.id = SLEEPY;&lt;br /&gt;
  table_process[indice_tache].etat.time.sleepingtime = t;&lt;br /&gt;
  TIMER1_COMPA_vect();}&lt;br /&gt;
void tache1(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTC ^= (1 &amp;lt;&amp;lt; PC0);&lt;br /&gt;
    _delay_ms(300);}}&lt;br /&gt;
void tache3(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTC ^= (1 &amp;lt;&amp;lt; PC3);&lt;br /&gt;
    //_delay_ms(1000);&lt;br /&gt;
    makeSleep(1000);}}&lt;br /&gt;
void tache2(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTD ^= (1 &amp;lt;&amp;lt; PD7);&lt;br /&gt;
    //_delay_ms(1000);&lt;br /&gt;
    makeSleep(700);}}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
[[Fichier:B5_test2.mp4|vignette|alt=test des frequences imprevisibles|test des frequences imprevisibles]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
A noter que la première tâche executée ne doit pas être endormie.&lt;br /&gt;
&lt;br /&gt;
=== Communication série et SPI ===&lt;br /&gt;
A l'aide du cours de Mr.Redon et de ressources sur internet nous avons pu confectionner deux librairies, une pour la communication SPI et une pour série (dans le répertoire Ordonnanceur/OldLibs car elle seront remplacées par celles données par Mr.Redon plus tard). Nous pouvons allons faire deux tâche distinctes dans notre ordonnanceur, une pour la communication série qui va récupérer le caractère d'une touche pressée pour l'écrire dans une variable globale tandis que la tâche SPI va lire cette variable globale est l'affiché sur un afficheur 7 segments.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:left; width: 48%; padding-left: 25px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
  void serial(void){&lt;br /&gt;
  while(1){&lt;br /&gt;
    data = USART_Receive();&lt;br /&gt;
    USART_sendChar(data);&lt;br /&gt;
    makeSleep(20);&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:right; width: 48%; padding-right: 25px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void aff7segments(void){&lt;br /&gt;
  while(1){&lt;br /&gt;
    aff_activer();&lt;br /&gt;
    aff_echange(data);&lt;br /&gt;
    aff_desactiver();&lt;br /&gt;
    makeSleep(1000);&lt;br /&gt;
    effacer_affichage();&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
[[Fichier:B5_serie_spi.mp4|vignette|alt=série et spi avec ordonnancement |série et spi avec ordonnancement|center|800px]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Carte Fille Matrice de touches =&lt;br /&gt;
==Explications générales sur la réalisation de la carte==&lt;br /&gt;
&lt;br /&gt;
Pour concevoir la carte fille dédiée au clavier, nous avons réutilisé un ancien clavier DELL équipé d’une matrice déjà fonctionnelle. L’idée consiste à connecter les sorties de cette matrice directement à notre carte fille à l’aide d’un connecteur adapté.&lt;br /&gt;
&lt;br /&gt;
Cependant, un défi se pose : la matrice du clavier comprend un total de 26 sorties (sans compter les LED et autres signaux). Cela dépasse largement les capacités en nombre de broches d’un ATmega328P.&lt;br /&gt;
&lt;br /&gt;
Pour remédier à ce problème, nous avons mis en place une solution d’encodage. Nous avons utilisé un décodeur (3 vers 8) pour gérer les lignes et trois encodeurs (8 vers 3) pour gérer les colonnes. Les encodeurs sont montés en cascade pour réduire significativement le nombre de broches nécessaires. Cette solution permet de minimiser l'utilisation des broches du microcontrôleur.&lt;br /&gt;
&lt;br /&gt;
Nous avons opté pour le décodeur 74HC138D (qui va envoyer un 0 parmi des 1) et trois encodeurs CD4532BM (qui cherche le premier 1 parmi des 0). On sent quand même les problèmes venir petit à petit. Nous avons étudié la datasheet et comment la mise en cascade fonctionne.&lt;br /&gt;
[[Fichier:Cascade.png|vignette|alt=Mise en cascade des encodeurs.|Mise en cascade des encodeurs.]]&lt;br /&gt;
On voit qu'un encodeur possède un bus de sortie de 5 bits. GS -&amp;gt; à l'état haut quand le composant reçoit un 1, 0 sinon. E0 -&amp;gt; à l'état haut quand il reçoit seulement des 0, 1 sinon. Puis Q2, Q1 ,Q0 la représentation binaire de l'entrée donnée.&lt;br /&gt;
&lt;br /&gt;
Afin de les mettre en cascade, il faut relié le E0 d'un premier encodeur au Ei de l'autre. Ensuite, nous allons faire un &amp;quot;OU&amp;quot; entre les GS afin de savoir si un des encodeurs reçoit un 1, puis grâce aux GS des deux premiers encodeurs nous sauront quelle encodeur à reçu le 1 (si les deux sont &amp;amp; 0 alors c'est le troisième). De même, faire une porte &amp;quot;OU&amp;quot; sur Q2, Q1, Q0 afin de réduire le nombre d'entrées/sorties nécessaires. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Par ailleurs, étant donné que nous utilisons directement le clavier Dell, il a été nécessaire de concevoir la carte avec des dimensions strictement identiques à celles de la carte d’origine, notamment en ce qui concerne sa largeur. Nous avons également dû ajouter des trous aux emplacements précis pour permettre de visser correctement la carte. Nous avons également dû créer l'empreinte KiCad du connecteur de la matrice, car celle-ci n’était pas disponible dans les bibliothèques existantes.[https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/CF_Clavier/Footprint_KeyboardDell_DJADJA Empreinte du connecteur matrice]. Pour les connecteurs HE-10 et AVR-ISP, nous avons veillé à les positionner sur la face opposée au connecteur de la matrice. Cela permet de les rendre directement accessibles une fois tous les composants branchés, facilitant ainsi les connexions et les manipulations.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
[[Fichier:Clavier dell.png||thumb|right|800px|Clavier DELL]]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Connecteur de base clavier dell.png||thumb|left|500px|Carte du clavier DELL]]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Matrice clavier dell.png||thumb|right|800px|Matrice du clavier DELL]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Détails des composants ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;ATmega328P&amp;lt;/u&amp;gt;&lt;br /&gt;
* Micro-contrôleur&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;74HC138D&amp;lt;/u&amp;gt;&lt;br /&gt;
* Décodeur 3-&amp;gt;8: envoie un 0 parmi des 1.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;CD4532BM&amp;lt;/u&amp;gt;&lt;br /&gt;
* Encodeur 8-&amp;gt;3&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;74LS32&amp;lt;/u&amp;gt;&lt;br /&gt;
* Porte logique Or pour la mise en cascade des encodeurs.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Connecteur HE10&amp;lt;/u&amp;gt;&lt;br /&gt;
* Connecteur pour la liaison PicoShield-CarteFille&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Connecteur de la matrice&amp;lt;/u&amp;gt;&lt;br /&gt;
* Simplement une empreinte que l'on a créé [https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/CF_Clavier/Footprint_KeyboardDell_DJADJA Lien vers la bibliothèque présent sur le git]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;AVR-ISP-6&amp;lt;/u&amp;gt;&lt;br /&gt;
* Programmateur AVR&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;LED_SMD&amp;lt;/u&amp;gt;&lt;br /&gt;
* 3 LEDs&lt;br /&gt;
&lt;br /&gt;
== Hardware ==&lt;br /&gt;
===Kicad===&lt;br /&gt;
[[Fichier:Schematique carte fille clavier dell.png|center|1000px|vignette|Schématique de la carte Fille]]&lt;br /&gt;
&lt;br /&gt;
Pour réaliser la carte fille, nous avions dans un premier temps conçu une carte avec une matrice de touches directement implenter sur celle-ci, mais jugeant que cela était trop simple nous avons été redirigé vers l'utilisation d'une matrice déjà réalisé. Ainsi nous avons avons reutiliser celle d'un vieux clavier dell en créant les empreintes à la bonne taille pour se connecter sur la matrice&lt;br /&gt;
 &lt;br /&gt;
[[Fichier:Pcb recto carte fille clavier dell.png|left|480px|vignette|Avant du PCB]][[Fichier:Pcb verso carte fille clavier dell.png|right|480px|vignette|Arrière du PCB]]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Capture d’écran 2024-11-20 à 12.09.07.png|left|600px|vignette|PCB vue 3D avant]][[Fichier:Capture d’écran 2024-11-20 à 12.09.33.png|right|480px|vignette|PCB vue 3D arrière]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Différents Problèmes rencontrés===&lt;br /&gt;
Avant même la réception de la carte, alors que nous commençons a essayé d'écrire un premier programme, nous nous rendions compte qu'envoyer un 0 parmi des 1 et de rechercher un 1 parmi des 0 ne fonctionnera pas (logique). Nous avons alors pris la décision de changer le décodeur car il était pour nous plus simple de changer un composant que les trois encodeurs. Nous avons opté pour lui de la même famille, le 74HTC238D.&lt;br /&gt;
&lt;br /&gt;
Dès la réception de la carte, nous avons effectué un premier test avec une simple programmation de LED. Nous nous sommes rapidement aperçus que nous avions configuré deux noms d'étiquettes de reset distinctes sur KiCad : une pour l'AVR (RST) et une pour le connecteur HE-10 (RESET). Cependant, seul le reset du connecteur HE-10 était correctement relié au microcontrôleur. Pour résoudre ce problème, nous avons simplement connecté les deux broches de reset à l'aide d'un fil.&lt;br /&gt;
&lt;br /&gt;
Lors de l'examen initial de notre carte, nous avons également constaté une erreur que nous avions commise. En effet, comme nous avions initialement conçu une matrice de touches sans encodeurs ni décodeurs, il n'était donc pas nécessaire d'intégrer des résistances de pull-up ou de pull-down. Nous avons alors juste rajouter ces composants, or il en résulte que lorsqu'une touche sera pressée, un 1 sera bien envoyé mais pas parmi des 0, parmi des états indéterminé. En général, les états indéterminés, on aime pas trop, surtout quand cela empêche ta carte de pouvoir fonctionner comme voulu. Il a donc été nécessaire d'ajouter des résistances de pull-down sur chaque colonne de notre clavier. Afin de simplifier cette modification, nous avons utilisé des résistances CMS que nous avons positionnées comme des dominos (verticalement), ce qui nous a permis de faire passer un fil de masse directement au-dessus des résistances.&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Resistance pull Up domino.jpg|center|500px|vignette|Résistances de Pull-down sur les colonnes]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Une fois tous ces problèmes de base résolus, nous avons enfin pu nous attaquer à la programmation du clavier. Pour vérifier que toutes les touches étaient correctement détectées, nous avons réalisé un petit programme de test ([https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/CF_Clavier/prog/test.c Code du test]). Ce programme nous a permis d’associer chaque LED à un décodeur différent via la broche GS des décodeurs. Ainsi, nous avons pu identifier quelles touches ne répondaient pas. Premièrement, beaucoup de touches ne répondaient pas, moins d'une dizaine. Nous avons alors fait de multiples tests au multimètre sur notre carte mais aussi sur une autre matrice de touches similaire. Une des hypothèses fut qu'il fallait bien étamer les pistes pour permettre la conduction entre la carte et la matrice. Nous avons alors rajouter de l'étain, puis + de touches commençaient à fonctionner. Il fallait alors un nouveau programme de test pour détecter quelles lignes ou colonnes n'étaient pas bien étamés afin de permettre une conduction ([https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/CF_Clavier/prog/detect.c Code de détection]). Il suffisait ainsi de rajouter de l'étain sur les colonnes et les lignes qui ne répondaient pas. Enfin, toutes les touches sont détectées lors de d'une pression !&lt;br /&gt;
&lt;br /&gt;
==Programmation de la carte==&lt;br /&gt;
===Programme de test===&lt;br /&gt;
&lt;br /&gt;
[https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/CF_Clavier/prog/test.c Code du test]&lt;br /&gt;
&lt;br /&gt;
Lorsqu'une touche est pressée, le contact mécanique rebondit, générant plusieurs signaux rapides. Pour éviter que ces rebonds ne soient interprétés comme plusieurs pressions, nous avons simplement ajouté un délai de 100 millisecondes dans notre programme, ce qui permet d’ignorer ces variations et de ne retenir qu’un signal stable.&lt;br /&gt;
&lt;br /&gt;
Afin de tester chaque touche de notre matrice, nous avons décidé de faire le programme le plus simple possible en utilisant les broches GS de nos encodeurs. Il n'y a pas d'histoire de ligne ou de colonnes ici, si une touche est pressée alors le GS de l'encodeur ou sa colonne est reliée passera à l'état haut. Une manière très simple de savoir si une touche est utilisable et si nos trois encodeurs sont opérationnels également. Nous avons trois leds pour trois encodeurs, pour chaque encodeur, s'allumera une led spécifique si il reçoit un 1 parmi des 0.&lt;br /&gt;
&lt;br /&gt;
Afin de mettre en place ce système, il nous faut un programme capable de balayer toutes les lignes de notre matrice via un décodeur.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:left; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
int tab_outputs[8][3] = {&lt;br /&gt;
    {0, 0, 0},&lt;br /&gt;
    {1, 0, 0},&lt;br /&gt;
    {0, 1, 0},&lt;br /&gt;
    {1, 1, 0},&lt;br /&gt;
    {0, 0, 1},&lt;br /&gt;
    {1, 0, 1},&lt;br /&gt;
    {0, 1, 1},&lt;br /&gt;
    {1, 1, 1},&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void maj_output(int lig){&lt;br /&gt;
    for (int i = 0 ; i &amp;lt; 3 ; i++){&lt;br /&gt;
        if (tab_outputs[lig][i] == 0){&lt;br /&gt;
            PORTC &amp;amp;= ~(1 &amp;lt;&amp;lt; i);&lt;br /&gt;
        }&lt;br /&gt;
        else if (tab_outputs[lig][i] == 1){&lt;br /&gt;
            PORTC |= (1 &amp;lt;&amp;lt; i);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Fichier:B5_test_matrice.mp4|vignette|alt=test d'une touche pressée |test d'une touche pressée|right|800px]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
Ici, grâce à l'initialisation d'un tableau de la représentation en binaire des chiffres 0 à 7, il suffit de faire une procédure qui prend en paramètre le numéro de ligne souhaitée puis de vérifier dans le tableau quelle sortie mettre à 0 et 1. Nous avions remarqué que mettre les sorties pour les décodeurs sur le même port côte à côte facilite la programmation.&lt;br /&gt;
&lt;br /&gt;
===Programme de détection===&lt;br /&gt;
&lt;br /&gt;
[https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/CF_Clavier/prog/detect.c Code du test]&lt;br /&gt;
&lt;br /&gt;
Dans le projet, nous avons eu des problèmes de lignes et colonnes qui n'était pas conduit entre notre carte et la matrice. Pour les identifier, nous avons mis en place un programme de détection qui lors de la pression d'une touche, va afficher grâce aux leds, de quel encodeur sa colonne régit puis quelle ligne et quelle colonne est activée. Ce programme permet ainsi de diagnostiquer rapidement les problèmes de conduction entre la carte et la matrice en identifiant précisément les correspondances défectueuses. &lt;br /&gt;
&lt;br /&gt;
Pour cela, nous avons imaginer deux fonctions show_ligne et show_colonne, permettant d'afficher sur nos trois leds la ligne et la colonne. Si les leds affichent : double clignotements de la led du milieu  (allumée, éteint, allumé) puis (éteint, allumée, allumée) alors la ligne L6 (voir KiCad) et la 4e colonne du deuxième encodeur sont activées.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:left; width: 48%; padding-left: 25px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void show_ligne(int i){&lt;br /&gt;
    turn_off_leds();&lt;br /&gt;
    for (int bit = 0; bit &amp;lt; 3; bit++){&lt;br /&gt;
        if (tab_outputs[i][bit] == 1) {&lt;br /&gt;
            PORTC |= (1 &amp;lt;&amp;lt; (bit+LED1));&lt;br /&gt;
        }&lt;br /&gt;
        else &lt;br /&gt;
            PORTC &amp;amp;= ~(1 &amp;lt;&amp;lt; (bit+LED1));&lt;br /&gt;
        }&lt;br /&gt;
    _delay_ms(SHOW_TIME);&lt;br /&gt;
    turn_off_leds();&lt;br /&gt;
}}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:right; width: 48%; padding-right: 25px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void show_colonne(){&lt;br /&gt;
    turn_off_leds();&lt;br /&gt;
    for (int i = Q0; i &amp;lt; Q2 + 1 ; i++){&lt;br /&gt;
        if (((inputs &amp;gt;&amp;gt; i) &amp;amp; 1) == 1) {&lt;br /&gt;
            PORTC |= (1 &amp;lt;&amp;lt; (i+LED1));&lt;br /&gt;
        }&lt;br /&gt;
        else &lt;br /&gt;
            PORTC &amp;amp;= ~(1 &amp;lt;&amp;lt; (i+LED1));&lt;br /&gt;
    }&lt;br /&gt;
    _delay_ms(SHOW_TIME);&lt;br /&gt;
    turn_off_leds();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
Les deux fonctions se ressemblent beaucoup, la différence étant que show_ligne va prendre un paramètre un entier selon la ligne que nous voulons afficher alors que colonne va directement regarde dans le bus d'entrées la représentation binaire de la colonne activée. A noter que le fait que les LEDs et Q2, Q1, Q0 sont successivement placés sur le même port rend la programmation plus simple à réaliser.&lt;br /&gt;
&lt;br /&gt;
A noter la présence d'un 'uint8_t inputs;' où l'on va assigner PIND à chaque début d'une boucle, en effet pendant l'afficher l'utilisateur ne reste pas forcément la touche enfoncées ce qui changera les valeurs du bus d'entrée. Il est alors important de sauvegarder l'état de ce bus avant de l'afficher.&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
[[Fichier:B5_test_detect.mp4|vignette|alt=test de la détection d'une touche |test de la détection d'une touche|center|800px]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Ping pong===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/CF_Clavier/prog/PingPongSPI Code du test]&lt;br /&gt;
&lt;br /&gt;
A l'aide des ressources envoyées par Mr.Redon, nous avons de quoi communiquer entre le shield et notre carte fille. Pour cela, nous avons du modifié un tout petit peu les programmes. En effet, nous avons ajouter un #define pour le Chip Select de notre clavier (le bon connecteur HE10 sur lequel nous allons le connecter) afin que ce soit bien lui qui sera sélectionné lors du spi_select et spi_deselect. Le shield va envoyer un 1 en SPI pour indiquer au clavier qu'il est sur écoute et qu'il attend un envoie de la carte fille.&lt;br /&gt;
&lt;br /&gt;
Cette communication va nous permettre de bien mapper toutes nos touches.&lt;br /&gt;
&lt;br /&gt;
Nous avons décidé de faire un tableau en 3 dimensions afin de faciliter le mapping. Pourquoi 3 dimensions ? Nous avons une première dimension pour le numéro de ligne (0 à 7), pour le numéro de colonne (0 à 7) puis pour le numéro d'encodeur (0 à 2). Le bus d'entrée nous donnant un numéro de ligne entre 0 et 7, nous avons trouvé plus facile de procéder de cette manière. Voici un exemple.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:center; width: 48%;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
char tab_touches[8][8][3] = {&lt;br /&gt;
    {{'\0'/*AltGr*/, '\0', '\0'}, {'\0', '\0', '\0'}, {'-', ' ', '\0'}, {'\0'/*Fleche gauche*/, 'b', '\0'}, {'\0'/*Fleche droite*/, '\0', '\0'}, {'\0'/*Fleche bas*/, '\0', '\0'}, {'\0', '\0', '\0'}, {'\0', '!', '\0'}}, &lt;br /&gt;
    {{'\0', 'x', 'w'}, {'\0', 'c', '\0'/*CTRL Droit*/}, {'*', '\n', '\0'}, {'\0'/*Pause*/, 'v', '\0'}, {'/', ',', '\0'}, {'\0'/*Verr Num*/, ';', '\0'}, {'\0'/*Touch window droite*/, ':', '\0'}, {'\0'/*Shift droit*/, '*', '\0'}}, &lt;br /&gt;
    {{'\0'/*Arret*/, 'z', 'a'}, {'\0'/*Options*/, 'e', '\0'}, {'9', '\0', '\0'}, {'\0', 'r', '\0'}, {'8', 'u', '\0'}, {'7', 'i', '\0'}, {'\0', 'o', '\0'}, {'*', 'p', '\0'}}, &lt;br /&gt;
    {{'\0', 's', 'q'}, {'\0'/*Touche window gauche*/, 'd', '\0'}, {'3', '\0', '\0'}, {'\n', 'f', '\0'}, {'2', 'j', '\0'}, {'1', 'k', '\0'}, {'\0', 'l', '\0'}, {'\0', 'm', '\0'}}, &lt;br /&gt;
    {{'\0', '\0', '\0'}, {'\0', '\0', '\0'}, {'\0', '\0', '\0'}, {'\0', '\0', '\0'}, {'\0', '\0', '\0'}, {'\0', '\0', 'w'}, {'\0', '\0', '\0'}, {'\0', '\0', '\0'}}, &lt;br /&gt;
    {{'\0', '&amp;lt;', '\0'}, {'\0', '\0', '\0'}, {'.', '\0', '\0'}, {'\0', 'g', '\0'}, {'0', 'h', '\0'}, {'\0', '\0', '\0'}, {'\0', '\0', '\0'}, {'\0', '%', '\0'}}, &lt;br /&gt;
    {{'\0', '\0'/*MAJ*/, '\0'/*tab*/}, {'\0', '\0'/*F3*/, '\0'}, {'\0', 8, '\0'}, {'\0', 't', '\0'}, {'5', 'y', '\0'}, {'4', '$', '\0'}, {'\0', '\0'/*F7*/, '\0'}, {'\0'/*Shift gauche*/, '^', '\0'}}, &lt;br /&gt;
    {{'\0', '\0'/*F1*/, '\0'/*œ*/}, {'\0', '\0'/*F2*/, '\0'/*CTRL Gauche*/}, {'\0'/*Page haut*/, '\0'/*F9*/, '\0'}, {'\0'/*Debut*/, '(', '\0'}, {'\0'/*Insert*/, '-', '\0'}, {'\0'/*Supp*/, '=', '\0'}, {'t', '\n'/*F8*/, '\0'}, {'g', ')', '\0'}}&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Notre clavier ne supporte pas l'appuie de plusieurs touches en simultané à cause de la présence de décodeurs et d'encodeurs, le shift devient inutilisable, seulement maj est opérationnel. Afin de permettre l'utilisation de altgr, il fonctionnera comme le maj mais les deux ne pourront pas être activés en même temps.&lt;br /&gt;
&lt;br /&gt;
Nous avons tout d'abord mit des valeurs au hasard mais unique dans le tableau, puis nous avons identifié les touches pour une case dans le tableau, nous avons fait ce processus plusieurs fois afin de trouver toutes les cases des touches du clavier dans le tableau. Pour permettre l'utilisation du maj et du altgr, nous avons créer deux autres tableau comme ça, un chacun avec ses touches assignées. Lors de l'envoie, il faut vérifier dans quel mode nous nous trouvons pour envoyer le caractère dans le bon tableau (alt, maj ou classique).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:left; width: 48%; padding-left: 25px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
  while(1)&lt;br /&gt;
  {&lt;br /&gt;
    spi_select();&lt;br /&gt;
    uint8_t r=spi_exch(1);&lt;br /&gt;
    if (r != 1) printf(&amp;quot;%c&amp;quot;,r);&lt;br /&gt;
    spi_deselect();&lt;br /&gt;
    _delay_ms(20);&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:right; width: 48%; padding-right: 25px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void envoyer(){&lt;br /&gt;
    printf(&amp;quot;Clavier attente\n&amp;quot;);&lt;br /&gt;
      uint8_t message=spi_wait();&lt;br /&gt;
      printf(&amp;quot;Clavier reçu %d\n&amp;quot;,message);&lt;br /&gt;
      if (message == 1)&lt;br /&gt;
        spi_sendback(temp);&lt;br /&gt;
      printf(&amp;quot;Clavier retour préparé %d\n&amp;quot;,temp);&lt;br /&gt;
  &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
Ici le shield (à gauche) va envoyer un 1 en SPI pour dire au clavier qu'il est prêt à l'écouter, si il reçoit autre chose qu'un 1 (son propre envoie) alors il l'affiche. Le clavier (à droite) va envoyer son dernier caractère dont la touche a été pressée lorsqu'il reçoit ce fameux 1.&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
[[Fichier:B5_test_pingpong.mp4|vignette|alt=test clavier sur shield (sans démonstration de altgr et maj) |test clavier sur shield (sans démonstration de altgr et maj)|center|800px]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Implémentation dans l'ordonnanceur===&lt;br /&gt;
Pour pouvoir utiliser le clavier avec l'ordonnanceur, il suffit de faire de notre while(1) précédent, une tâche a part entière de notre ordonnanceur. Sur cet exemple on voit l'utilisation du alt et du maj.&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
[[Fichier:B5_test_final.mp4|vignette|alt=test clavier avec ordonnancement |test clavier avec ordonnancement|center|800px]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;/div&gt;</summary>
		<author><name>Adjadjaa</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-5&amp;diff=7382</id>
		<title>SE4Binome2024-5</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-5&amp;diff=7382"/>
		<updated>2025-01-26T16:31:40Z</updated>

		<summary type="html">&lt;p&gt;Adjadjaa : /* Programme de détection */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Introduction=&lt;br /&gt;
&lt;br /&gt;
Ce wiki documente le développement d’un pico-ordinateur modulaire. Ce dernier est constitué d’une carte principale, composée d’une carte Shield permettant la connexion des cartes filles, et d’une carte mère (initialement simulée par une Arduino Uno avant sa conception finale). Plusieurs cartes filles sont prévues, chacune remplissant une fonction spécifique : gestion du clavier, affichage, port série, réseau, mémoire de masse et son.&lt;br /&gt;
&lt;br /&gt;
Notre binôme est spécifiquement chargé du développement de la carte fille dédiée au clavier.&lt;br /&gt;
&lt;br /&gt;
Toutes les ressources nécessaires, incluant les codes sources et les schémas, sont disponibles sur le dépôt Git suivant :  [https://gitea.plil.fr/ktouron/se4-djadja-touron_pico.git Lien du Git]&lt;br /&gt;
&lt;br /&gt;
= Carte Shield =&lt;br /&gt;
[[Fichier:Carte Recto non soudé.jpg|vignette|left|thumb|350px|Recto de la carte avant soudage des composants]]&lt;br /&gt;
[[Fichier:Verso non solder.jpeg.jpg|vignette|thumb|right|300px|Verso de la carte avant soudage des composants]]&lt;br /&gt;
[[Fichier:Carde shield soudé.jpg|vignette|thumb|center|350px|Photo de la carte avec les composants soudés]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Test==&lt;br /&gt;
=== Allumage de LEDS sur Programmateur AVR ===&lt;br /&gt;
Avant de programmer directement sur le shield, nous avons allumé des LED pour tester la carte. Nous avons directement utilisé le code exemple fourni par l'IDE arduino en adaptant simplement les pins correspondant aux leds. [https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/PicoShield/Programmation/Blink Code du test]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Vid_test_carte_mp4.mp4|vignette|thumb|center|700px|Vidéo de Test des leds]]&lt;br /&gt;
&lt;br /&gt;
=== Lecture de la carte SD ===&lt;br /&gt;
Avant de programmer directement sur le shield, nous avons tester si la carte SD était bien détectée et lue. On a utilisé le code test présent dans l'IDE arduino en adaptant le port utilisé.[https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/PicoShield/Programmation/CardInfo Code du test]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Resultat SD.jpg|vignette|thumb|center|700px|Carte SD bien détéctée]]&lt;br /&gt;
&lt;br /&gt;
=== Connecteurs IDC HE10 ===&lt;br /&gt;
Afin de tester nos connecteur HE10, nous avons utilisé un afficher 7 segments (Sparkfun 7 segments display). Pour pouvoir vérifier leurs fonctionnements nous avons branché l'afficheur sur chaque connecteur tour à tour. Le programme implanté est un simple connecteur à afficher sur l'afficheur. Voici une vidéo du compteur fonctionnant sur un des 5 connecteurs HE10. ([https://learn.sparkfun.com/tutorials/using-the-serial-7-segment-display/all Code ici (section : Example 2 SPI)])&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Se4-5-7segments.mp4|vignette|alt=se4-5-7segments|Test connecteur HE10 avec afficheur 7 segments.|center]]&lt;br /&gt;
&lt;br /&gt;
== Ordonnanceur ==&lt;br /&gt;
Pour les interruptions de notre ordonnanceur nous avons utilisé la procédure d'initialisation du minuteur avec le Timer1 disponible dans les cours de Mr.Redon en renseignant une période de 20ms. Nous l'avons disposé dans le fichier minuteur.c car nous n'allons plus le modifier pour le reste du projet. Dans un autre fichier process.c (avec process.h), nous allons y mettre nos structures pour les process et leurs états puis une union pour le temps qui le caractérise ainsi que toutes les fonctions associés.&lt;br /&gt;
&lt;br /&gt;
[https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/Ordonnanceur Lien du répertoire]&lt;br /&gt;
&lt;br /&gt;
=== Processus ===&lt;br /&gt;
==== Structure ====&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:right; width: 48%; padding-left: 10px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
    uint16_t adresseDepart;  //adresse de la fonction de départ &lt;br /&gt;
    uint16_t adressePile;       //adresse de la pile d'exécution&lt;br /&gt;
    Etat etat;        &lt;br /&gt;
} Process;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Notre structure caractérisant un processus est définie par les trois champs ci-contre.&lt;br /&gt;
&lt;br /&gt;
Une adresse de départ correspondant à la fonction du processus associé, l'adresse où se situe le processus dans la pile puis l'état de la tâche. Nous avons décidé de faire une structure à part entière compte tenu des multitudes d'états que nous pourrons ajouter pendant la progression du projet.&lt;br /&gt;
&lt;br /&gt;
==== Etat d'un processus ====&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:right; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
typedef union {&lt;br /&gt;
  int sleepingtime;       &lt;br /&gt;
} Time;&lt;br /&gt;
&lt;br /&gt;
typedef struct {&lt;br /&gt;
  int id;&lt;br /&gt;
  Time time;&lt;br /&gt;
} Etat ;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
L'état d'un processus est alors une structure à deux champs (pour l'instant), l'id doit correspondre à un '#DEFINE' pour avoir un sens tandis que nous avons choisi de faire une union pour le temps qui caractérise notre état afin qu'il puisse avoir un nom et type de variable cohérent avec son état.(Ici seulement sleepingtime car seul l'état endormi existe pour le moment)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
  {| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
  |+ Tableau des états&lt;br /&gt;
  |-&lt;br /&gt;
  ! Etat !! ACTIVE !! SLEEPY !! ... !! ...&lt;br /&gt;
  |-&lt;br /&gt;
  | Id || 0 || 1 || ... || ...&lt;br /&gt;
  |}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Procédures principales ====&lt;br /&gt;
&lt;br /&gt;
=== ISR ===&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:right; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
ISR(TIMER1_COMPA_vect, ISR_NAKED)    // Procédure d'interruption&lt;br /&gt;
{&lt;br /&gt;
  TCNT1=0;//reset timer&lt;br /&gt;
  /* Sauvegarde du contexte de la tâche interrompue */&lt;br /&gt;
  portSAVE_REGISTERS();&lt;br /&gt;
   table_process[indice_tache].adressePile = SP;&lt;br /&gt;
  /* Appel à l'ordonnanceur */&lt;br /&gt;
  selectProcess();&lt;br /&gt;
  /* Récupération du contexte de la tâche ré-activée */&lt;br /&gt;
  SP = table_process[indice_tache].adressePile;&lt;br /&gt;
  portRESTORE_REGISTERS();&lt;br /&gt;
  &lt;br /&gt;
  asm volatile ( &amp;quot;reti&amp;quot; );&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
L'ISR est ce qu'il va être executer lors des interruptions toutes les 20 millisecondes. Cela consiste à sauvegarder tous les registres de la tâche qui était en cours avant l'appel de l'ISR pour ensuite passer à la tâche suivante valide (c'est à dire active) sans oublier de charger les registres de la nouvelle tâche.&lt;br /&gt;
&lt;br /&gt;
Nous devons également, à chaque fois avant de changer de tâche, enregistrer le pointeur de pile dans le processus afin de pouvoir revenir là ou elle en est la prochaine fois qu'elle sera appelée. Respectivement, une fois la nouvelle tâche choisie, le pointeur de pile doit prendre l'adresse de là ou en était la tâche avant qu'elle soit interrompue.&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Séléction de processus ====&lt;br /&gt;
Lors de la séléction de processus, nous devons parcourir tous les processus jusqu'au moment où nous en trouvons un actif. Ainsi, il deviendra la tâche que nous traiterons lors du prochain intervalle de 20 ms. A ce stade, à chaque fois que la procédure selectProcess est appelée, nous devons réduire le temps de repos de chaque process endormi de 20 ms. D'autres conditions pourrons être ajoutée si ajout d'état a lieu. (voir l'ajout de selectProcess dans l'ISR)&lt;br /&gt;
&lt;br /&gt;
=== Test ===&lt;br /&gt;
==== Clignotement de deux LED à fréquences indivisibles entre elles ====&lt;br /&gt;
Afin de vérifier la réussite de notre ordonnanceur à fonctionnement tourniquet, nous avons programmer deux simples tâches changeant l'état d'une LED. Une à une fréquence 200ms et l'autre 300ms (avec un _delay_ms).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:left; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void tache1(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTC ^= (1 &amp;lt;&amp;lt; PC0);&lt;br /&gt;
    _delay_ms(300);}}&lt;br /&gt;
void tache2(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTD ^= (1 &amp;lt;&amp;lt; PD7);&lt;br /&gt;
    _delay_ms(200);}}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
[[Fichier:B5_test1.mp4|vignette|alt=test des frequences imprevisibles|test des frequences imprevisibles]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Clignotement grâce à l'état endormi ====&lt;br /&gt;
Nous ajoutons l'état endormi afin que nos tâches ne mettent pas en pause l'ordonnanceur avec un _delay_ms. Pour cela, nous incorporons une fonction makeSleep qui permet de mettre la tâche qui l'appelle dans cet état.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:left; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void makeSleep(int t){&lt;br /&gt;
  table_process[indice_tache].etat.id = SLEEPY;&lt;br /&gt;
  table_process[indice_tache].etat.time.sleepingtime = t;&lt;br /&gt;
  TIMER1_COMPA_vect();}&lt;br /&gt;
void tache1(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTC ^= (1 &amp;lt;&amp;lt; PC0);&lt;br /&gt;
    _delay_ms(300);}}&lt;br /&gt;
void tache3(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTC ^= (1 &amp;lt;&amp;lt; PC3);&lt;br /&gt;
    //_delay_ms(1000);&lt;br /&gt;
    makeSleep(1000);}}&lt;br /&gt;
void tache2(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTD ^= (1 &amp;lt;&amp;lt; PD7);&lt;br /&gt;
    //_delay_ms(1000);&lt;br /&gt;
    makeSleep(700);}}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
[[Fichier:B5_test2.mp4|vignette|alt=test des frequences imprevisibles|test des frequences imprevisibles]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
A noter que la première tâche executée ne doit pas être endormie.&lt;br /&gt;
&lt;br /&gt;
=== Communication série et SPI ===&lt;br /&gt;
A l'aide du cours de Mr.Redon et de ressources sur internet nous avons pu confectionner deux librairies, une pour la communication SPI et une pour série (dans le répertoire Ordonnanceur/OldLibs car elle seront remplacées par celles données par Mr.Redon plus tard). Nous pouvons allons faire deux tâche distinctes dans notre ordonnanceur, une pour la communication série qui va récupérer le caractère d'une touche pressée pour l'écrire dans une variable globale tandis que la tâche SPI va lire cette variable globale est l'affiché sur un afficheur 7 segments.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:left; width: 48%; padding-left: 25px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
  void serial(void){&lt;br /&gt;
  while(1){&lt;br /&gt;
    data = USART_Receive();&lt;br /&gt;
    USART_sendChar(data);&lt;br /&gt;
    makeSleep(20);&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:right; width: 48%; padding-right: 25px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void aff7segments(void){&lt;br /&gt;
  while(1){&lt;br /&gt;
    aff_activer();&lt;br /&gt;
    aff_echange(data);&lt;br /&gt;
    aff_desactiver();&lt;br /&gt;
    makeSleep(1000);&lt;br /&gt;
    effacer_affichage();&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
[[Fichier:B5_serie_spi.mp4|vignette|alt=série et spi avec ordonnancement |série et spi avec ordonnancement|center|800px]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Carte Fille Matrice de touches =&lt;br /&gt;
==Explications générales sur la réalisation de la carte==&lt;br /&gt;
&lt;br /&gt;
Pour concevoir la carte fille dédiée au clavier, nous avons réutilisé un ancien clavier DELL équipé d’une matrice déjà fonctionnelle. L’idée consiste à connecter les sorties de cette matrice directement à notre carte fille à l’aide d’un connecteur adapté.&lt;br /&gt;
&lt;br /&gt;
Cependant, un défi se pose : la matrice du clavier comprend un total de 26 sorties (sans compter les LED et autres signaux). Cela dépasse largement les capacités en nombre de broches d’un ATmega328P.&lt;br /&gt;
&lt;br /&gt;
Pour remédier à ce problème, nous avons mis en place une solution d’encodage. Nous avons utilisé un décodeur (3 vers 8) pour gérer les lignes et trois encodeurs (8 vers 3) pour gérer les colonnes. Les encodeurs sont montés en cascade pour réduire significativement le nombre de broches nécessaires. Cette solution permet de minimiser l'utilisation des broches du microcontrôleur.&lt;br /&gt;
&lt;br /&gt;
Nous avons opté pour le décodeur 74HC138D (qui va envoyer un 0 parmi des 1) et trois encodeurs CD4532BM (qui cherche le premier 1 parmi des 0). On sent quand même les problèmes venir petit à petit. Nous avons étudié la datasheet et comment la mise en cascade fonctionne.&lt;br /&gt;
[[Fichier:Cascade.png|vignette|alt=Mise en cascade des encodeurs.|Mise en cascade des encodeurs.]]&lt;br /&gt;
On voit qu'un encodeur possède un bus de sortie de 5 bits. GS -&amp;gt; à l'état haut quand le composant reçoit un 1, 0 sinon. E0 -&amp;gt; à l'état haut quand il reçoit seulement des 0, 1 sinon. Puis Q2, Q1 ,Q0 la représentation binaire de l'entrée donnée.&lt;br /&gt;
&lt;br /&gt;
Afin de les mettre en cascade, il faut relié le E0 d'un premier encodeur au Ei de l'autre. Ensuite, nous allons faire un &amp;quot;OU&amp;quot; entre les GS afin de savoir si un des encodeurs reçoit un 1, puis grâce aux GS des deux premiers encodeurs nous sauront quelle encodeur à reçu le 1 (si les deux sont &amp;amp; 0 alors c'est le troisième). De même, faire une porte &amp;quot;OU&amp;quot; sur Q2, Q1, Q0 afin de réduire le nombre d'entrées/sorties nécessaires. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Par ailleurs, étant donné que nous utilisons directement le clavier Dell, il a été nécessaire de concevoir la carte avec des dimensions strictement identiques à celles de la carte d’origine, notamment en ce qui concerne sa largeur. Nous avons également dû ajouter des trous aux emplacements précis pour permettre de visser correctement la carte. Nous avons également dû créer l'empreinte KiCad du connecteur de la matrice, car celle-ci n’était pas disponible dans les bibliothèques existantes.[https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/CF_Clavier/Footprint_KeyboardDell_DJADJA Empreinte du connecteur matrice]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
[[Fichier:Clavier dell.png||thumb|right|800px|Clavier DELL]]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Connecteur de base clavier dell.png||thumb|left|500px|Carte du clavier DELL]]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Matrice clavier dell.png||thumb|right|800px|Matrice du clavier DELL]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Détails des composants ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;ATmega328P&amp;lt;/u&amp;gt;&lt;br /&gt;
* Micro-contrôleur&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;74HC138D&amp;lt;/u&amp;gt;&lt;br /&gt;
* Décodeur 3-&amp;gt;8: envoie un 0 parmi des 1.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;CD4532BM&amp;lt;/u&amp;gt;&lt;br /&gt;
* Encodeur 8-&amp;gt;3&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;74LS32&amp;lt;/u&amp;gt;&lt;br /&gt;
* Porte logique Or pour la mise en cascade des encodeurs.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Connecteur HE10&amp;lt;/u&amp;gt;&lt;br /&gt;
* Connecteur pour la liaison PicoShield-CarteFille&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Connecteur de la matrice&amp;lt;/u&amp;gt;&lt;br /&gt;
* Simplement une empreinte que l'on a créé [https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/CF_Clavier/Footprint_KeyboardDell_DJADJA Lien vers la bibliothèque présent sur le git]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;AVR-ISP-6&amp;lt;/u&amp;gt;&lt;br /&gt;
* Programmateur AVR&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;LED_SMD&amp;lt;/u&amp;gt;&lt;br /&gt;
* 3 LEDs&lt;br /&gt;
&lt;br /&gt;
== Hardware ==&lt;br /&gt;
===Kicad===&lt;br /&gt;
[[Fichier:Schematique carte fille clavier dell.png|center|1000px|vignette|Schématique de la carte Fille]]&lt;br /&gt;
&lt;br /&gt;
Pour réaliser la carte fille, nous avions dans un premier temps conçu une carte avec une matrice de touches directement implenter sur celle-ci, mais jugeant que cela était trop simple nous avons été redirigé vers l'utilisation d'une matrice déjà réalisé. Ainsi nous avons avons reutiliser celle d'un vieux clavier dell en créant les empreintes à la bonne taille pour se connecter sur la matrice&lt;br /&gt;
 &lt;br /&gt;
[[Fichier:Pcb recto carte fille clavier dell.png|left|480px|vignette|Avant du PCB]][[Fichier:Pcb verso carte fille clavier dell.png|right|480px|vignette|Arrière du PCB]]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Capture d’écran 2024-11-20 à 12.09.07.png|left|600px|vignette|PCB vue 3D avant]][[Fichier:Capture d’écran 2024-11-20 à 12.09.33.png|right|480px|vignette|PCB vue 3D arrière]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Différents Problèmes rencontrés===&lt;br /&gt;
Avant même la réception de la carte, alors que nous commençons a essayé d'écrire un premier programme, nous nous rendions compte qu'envoyer un 0 parmi des 1 et de rechercher un 1 parmi des 0 ne fonctionnera pas (logique). Nous avons alors pris la décision de changer le décodeur car il était pour nous plus simple de changer un composant que les trois encodeurs. Nous avons opté pour lui de la même famille, le 74HTC238D.&lt;br /&gt;
&lt;br /&gt;
Dès la réception de la carte, nous avons effectué un premier test avec une simple programmation de LED. Nous nous sommes rapidement aperçus que nous avions configuré deux noms d'étiquettes de reset distinctes sur KiCad : une pour l'AVR (RST) et une pour le connecteur HE-10 (RESET). Cependant, seul le reset du connecteur HE-10 était correctement relié au microcontrôleur. Pour résoudre ce problème, nous avons simplement connecté les deux broches de reset à l'aide d'un fil.&lt;br /&gt;
&lt;br /&gt;
Lors de l'examen initial de notre carte, nous avons également constaté une erreur que nous avions commise. En effet, comme nous avions initialement conçu une matrice de touches sans encodeurs ni décodeurs, il n'était donc pas nécessaire d'intégrer des résistances de pull-up ou de pull-down. Nous avons alors juste rajouter ces composants, or il en résulte que lorsqu'une touche sera pressée, un 1 sera bien envoyé mais pas parmi des 0, parmi des états indéterminé. En général, les états indéterminés, on aime pas trop, surtout quand cela empêche ta carte de pouvoir fonctionner comme voulu. Il a donc été nécessaire d'ajouter des résistances de pull-down sur chaque colonne de notre clavier. Afin de simplifier cette modification, nous avons utilisé des résistances CMS que nous avons positionnées comme des dominos (verticalement), ce qui nous a permis de faire passer un fil de masse directement au-dessus des résistances.&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Resistance pull Up domino.jpg|center|500px|vignette|Résistances de Pull-down sur les colonnes]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Une fois tous ces problèmes de base résolus, nous avons enfin pu nous attaquer à la programmation du clavier. Pour vérifier que toutes les touches étaient correctement détectées, nous avons réalisé un petit programme de test ([https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/CF_Clavier/prog/test.c Code du test]). Ce programme nous a permis d’associer chaque LED à un décodeur différent via la broche GS des décodeurs. Ainsi, nous avons pu identifier quelles touches ne répondaient pas. Premièrement, beaucoup de touches ne répondaient pas, moins d'une dizaine. Nous avons alors fait de multiples tests au multimètre sur notre carte mais aussi sur une autre matrice de touches similaire. Une des hypothèses fut qu'il fallait bien étamer les pistes pour permettre la conduction entre la carte et la matrice. Nous avons alors rajouter de l'étain, puis + de touches commençaient à fonctionner. Il fallait alors un nouveau programme de test pour détecter quelles lignes ou colonnes n'étaient pas bien étamés afin de permettre une conduction ([https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/CF_Clavier/prog/detect.c Code de détection]). Il suffisait ainsi de rajouter de l'étain sur les colonnes et les lignes qui ne répondaient pas. Enfin, toutes les touches sont détectées lors de d'une pression !&lt;br /&gt;
&lt;br /&gt;
==Programmation de la carte==&lt;br /&gt;
===Programme de test===&lt;br /&gt;
&lt;br /&gt;
[https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/CF_Clavier/prog/test.c Code du test]&lt;br /&gt;
&lt;br /&gt;
Lorsqu'une touche est pressée, le contact mécanique rebondit, générant plusieurs signaux rapides. Pour éviter que ces rebonds ne soient interprétés comme plusieurs pressions, nous avons simplement ajouté un délai de 100 millisecondes dans notre programme, ce qui permet d’ignorer ces variations et de ne retenir qu’un signal stable.&lt;br /&gt;
&lt;br /&gt;
Afin de tester chaque touche de notre matrice, nous avons décidé de faire le programme le plus simple possible en utilisant les broches GS de nos encodeurs. Il n'y a pas d'histoire de ligne ou de colonnes ici, si une touche est pressée alors le GS de l'encodeur ou sa colonne est reliée passera à l'état haut. Une manière très simple de savoir si une touche est utilisable et si nos trois encodeurs sont opérationnels également. Nous avons trois leds pour trois encodeurs, pour chaque encodeur, s'allumera une led spécifique si il reçoit un 1 parmi des 0.&lt;br /&gt;
&lt;br /&gt;
Afin de mettre en place ce système, il nous faut un programme capable de balayer toutes les lignes de notre matrice via un décodeur.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:left; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
int tab_outputs[8][3] = {&lt;br /&gt;
    {0, 0, 0},&lt;br /&gt;
    {1, 0, 0},&lt;br /&gt;
    {0, 1, 0},&lt;br /&gt;
    {1, 1, 0},&lt;br /&gt;
    {0, 0, 1},&lt;br /&gt;
    {1, 0, 1},&lt;br /&gt;
    {0, 1, 1},&lt;br /&gt;
    {1, 1, 1},&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void maj_output(int lig){&lt;br /&gt;
    for (int i = 0 ; i &amp;lt; 3 ; i++){&lt;br /&gt;
        if (tab_outputs[lig][i] == 0){&lt;br /&gt;
            PORTC &amp;amp;= ~(1 &amp;lt;&amp;lt; i);&lt;br /&gt;
        }&lt;br /&gt;
        else if (tab_outputs[lig][i] == 1){&lt;br /&gt;
            PORTC |= (1 &amp;lt;&amp;lt; i);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Fichier:B5_test_matrice.mp4|vignette|alt=test d'une touche pressée |test d'une touche pressée|right|800px]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
Ici, grâce à l'initialisation d'un tableau de la représentation en binaire des chiffres 0 à 7, il suffit de faire une procédure qui prend en paramètre le numéro de ligne souhaitée puis de vérifier dans le tableau quelle sortie mettre à 0 et 1. Nous avions remarqué que mettre les sorties pour les décodeurs sur le même port côte à côte facilite la programmation.&lt;br /&gt;
&lt;br /&gt;
===Programme de détection===&lt;br /&gt;
&lt;br /&gt;
[https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/CF_Clavier/prog/detect.c Code du test]&lt;br /&gt;
&lt;br /&gt;
Dans le projet, nous avons eu des problèmes de lignes et colonnes qui n'était pas conduit entre notre carte et la matrice. Pour les identifier, nous avons mis en place un programme de détection qui lors de la pression d'une touche, va afficher grâce aux leds, de quel encodeur sa colonne régit puis quelle ligne et quelle colonne est activée. Ce programme permet ainsi de diagnostiquer rapidement les problèmes de conduction entre la carte et la matrice en identifiant précisément les correspondances défectueuses. &lt;br /&gt;
&lt;br /&gt;
Pour cela, nous avons imaginer deux fonctions show_ligne et show_colonne, permettant d'afficher sur nos trois leds la ligne et la colonne. Si les leds affichent : double clignotements de la led du milieu  (allumée, éteint, allumé) puis (éteint, allumée, allumée) alors la ligne L6 (voir KiCad) et la 4e colonne du deuxième encodeur sont activées.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:left; width: 48%; padding-left: 25px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void show_ligne(int i){&lt;br /&gt;
    turn_off_leds();&lt;br /&gt;
    for (int bit = 0; bit &amp;lt; 3; bit++){&lt;br /&gt;
        if (tab_outputs[i][bit] == 1) {&lt;br /&gt;
            PORTC |= (1 &amp;lt;&amp;lt; (bit+LED1));&lt;br /&gt;
        }&lt;br /&gt;
        else &lt;br /&gt;
            PORTC &amp;amp;= ~(1 &amp;lt;&amp;lt; (bit+LED1));&lt;br /&gt;
        }&lt;br /&gt;
    _delay_ms(SHOW_TIME);&lt;br /&gt;
    turn_off_leds();&lt;br /&gt;
}}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:right; width: 48%; padding-right: 25px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void show_colonne(){&lt;br /&gt;
    turn_off_leds();&lt;br /&gt;
    for (int i = Q0; i &amp;lt; Q2 + 1 ; i++){&lt;br /&gt;
        if (((inputs &amp;gt;&amp;gt; i) &amp;amp; 1) == 1) {&lt;br /&gt;
            PORTC |= (1 &amp;lt;&amp;lt; (i+LED1));&lt;br /&gt;
        }&lt;br /&gt;
        else &lt;br /&gt;
            PORTC &amp;amp;= ~(1 &amp;lt;&amp;lt; (i+LED1));&lt;br /&gt;
    }&lt;br /&gt;
    _delay_ms(SHOW_TIME);&lt;br /&gt;
    turn_off_leds();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
Les deux fonctions se ressemblent beaucoup, la différence étant que show_ligne va prendre un paramètre un entier selon la ligne que nous voulons afficher alors que colonne va directement regarde dans le bus d'entrées la représentation binaire de la colonne activée. A noter que le fait que les LEDs et Q2, Q1, Q0 sont successivement placés sur le même port rend la programmation plus simple à réaliser.&lt;br /&gt;
&lt;br /&gt;
A noter la présence d'un 'uint8_t inputs;' où l'on va assigner PIND à chaque début d'une boucle, en effet pendant l'afficher l'utilisateur ne reste pas forcément la touche enfoncées ce qui changera les valeurs du bus d'entrée. Il est alors important de sauvegarder l'état de ce bus avant de l'afficher.&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
[[Fichier:B5_test_detect.mp4|vignette|alt=test de la détection d'une touche |test de la détection d'une touche|center|800px]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Ping pong===&lt;br /&gt;
A l'aide des ressources envoyées par Mr.Redon, nous avons de quoi communiquer entre le shield et notre carte fille. Pour cela, nous avons du modifié un tout petit peu les programmes. En effet, nous avons ajouter un #define pour le Chip Select de notre clavier (le bon connecteur HE10 sur lequel nous allons le connecter) afin que ce soit bien lui qui sera sélectionné lors du spi_select et spi_deselect. Le shield va envoyer un 1 en SPI pour indiquer au clavier qu'il est sur écoute et qu'il attend un envoie de la carte fille.&lt;br /&gt;
&lt;br /&gt;
Cette communication va nous permettre de bien mapper toutes nos touches.&lt;br /&gt;
&lt;br /&gt;
Nous avons décidé de faire un tableau en 3 dimensions afin de faciliter le mapping. Pourquoi 3 dimensions ? Nous avons une première dimension pour le numéro de ligne (0 à 7), pour le numéro de colonne (0 à 7) puis pour le numéro d'encodeur (0 à 2). Le bus d'entrée nous donnant un numéro de ligne entre 0 et 7, nous avons trouvé plus facile de procéder de cette manière. Voici un exemple.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:center; width: 48%;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
char tab_touches[8][8][3] = {&lt;br /&gt;
    {{'\0'/*AltGr*/, '\0', '\0'}, {'\0', '\0', '\0'}, {'-', ' ', '\0'}, {'\0'/*Fleche gauche*/, 'b', '\0'}, {'\0'/*Fleche droite*/, '\0', '\0'}, {'\0'/*Fleche bas*/, '\0', '\0'}, {'\0', '\0', '\0'}, {'\0', '!', '\0'}}, &lt;br /&gt;
    {{'\0', 'x', 'w'}, {'\0', 'c', '\0'/*CTRL Droit*/}, {'*', '\n', '\0'}, {'\0'/*Pause*/, 'v', '\0'}, {'/', ',', '\0'}, {'\0'/*Verr Num*/, ';', '\0'}, {'\0'/*Touch window droite*/, ':', '\0'}, {'\0'/*Shift droit*/, '*', '\0'}}, &lt;br /&gt;
    {{'\0'/*Arret*/, 'z', 'a'}, {'\0'/*Options*/, 'e', '\0'}, {'9', '\0', '\0'}, {'\0', 'r', '\0'}, {'8', 'u', '\0'}, {'7', 'i', '\0'}, {'\0', 'o', '\0'}, {'*', 'p', '\0'}}, &lt;br /&gt;
    {{'\0', 's', 'q'}, {'\0'/*Touche window gauche*/, 'd', '\0'}, {'3', '\0', '\0'}, {'\n', 'f', '\0'}, {'2', 'j', '\0'}, {'1', 'k', '\0'}, {'\0', 'l', '\0'}, {'\0', 'm', '\0'}}, &lt;br /&gt;
    {{'\0', '\0', '\0'}, {'\0', '\0', '\0'}, {'\0', '\0', '\0'}, {'\0', '\0', '\0'}, {'\0', '\0', '\0'}, {'\0', '\0', 'w'}, {'\0', '\0', '\0'}, {'\0', '\0', '\0'}}, &lt;br /&gt;
    {{'\0', '&amp;lt;', '\0'}, {'\0', '\0', '\0'}, {'.', '\0', '\0'}, {'\0', 'g', '\0'}, {'0', 'h', '\0'}, {'\0', '\0', '\0'}, {'\0', '\0', '\0'}, {'\0', '%', '\0'}}, &lt;br /&gt;
    {{'\0', '\0'/*MAJ*/, '\0'/*tab*/}, {'\0', '\0'/*F3*/, '\0'}, {'\0', 8, '\0'}, {'\0', 't', '\0'}, {'5', 'y', '\0'}, {'4', '$', '\0'}, {'\0', '\0'/*F7*/, '\0'}, {'\0'/*Shift gauche*/, '^', '\0'}}, &lt;br /&gt;
    {{'\0', '\0'/*F1*/, '\0'/*œ*/}, {'\0', '\0'/*F2*/, '\0'/*CTRL Gauche*/}, {'\0'/*Page haut*/, '\0'/*F9*/, '\0'}, {'\0'/*Debut*/, '(', '\0'}, {'\0'/*Insert*/, '-', '\0'}, {'\0'/*Supp*/, '=', '\0'}, {'t', '\n'/*F8*/, '\0'}, {'g', ')', '\0'}}&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Notre clavier ne supporte pas l'appuie de plusieurs touches en simultané à cause de la présence de décodeurs et d'encodeurs, le shift devient inutilisable, seulement maj est opérationnel. Afin de permettre l'utilisation de altgr, il fonctionnera comme le maj mais les deux ne pourront pas être activés en même temps.&lt;br /&gt;
&lt;br /&gt;
Nous avons tout d'abord mit des valeurs au hasard mais unique dans le tableau, puis nous avons identifié les touches pour une case dans le tableau, nous avons fait ce processus plusieurs fois afin de trouver toutes les cases des touches du clavier dans le tableau. Pour permettre l'utilisation du maj et du altgr, nous avons créer deux autres tableau comme ça, un chacun avec ses touches assignées. Lors de l'envoie, il faut vérifier dans quel mode nous nous trouvons pour envoyer le caractère dans le bon tableau (alt, maj ou classique).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:left; width: 48%; padding-left: 25px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
  while(1)&lt;br /&gt;
  {&lt;br /&gt;
    spi_select();&lt;br /&gt;
    uint8_t r=spi_exch(1);&lt;br /&gt;
    if (r != 1) printf(&amp;quot;%c&amp;quot;,r);&lt;br /&gt;
    spi_deselect();&lt;br /&gt;
    _delay_ms(20);&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:right; width: 48%; padding-right: 25px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void envoyer(){&lt;br /&gt;
    printf(&amp;quot;Clavier attente\n&amp;quot;);&lt;br /&gt;
      uint8_t message=spi_wait();&lt;br /&gt;
      printf(&amp;quot;Clavier reçu %d\n&amp;quot;,message);&lt;br /&gt;
      if (message == 1)&lt;br /&gt;
        spi_sendback(temp);&lt;br /&gt;
      printf(&amp;quot;Clavier retour préparé %d\n&amp;quot;,temp);&lt;br /&gt;
  &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
Ici le shield (à gauche) va envoyer un 1 en SPI pour dire au clavier qu'il est prêt à l'écouter, si il reçoit autre chose qu'un 1 (son propre envoie) alors il l'affiche. Le clavier (à droite) va envoyer son dernier caractère dont la touche a été pressée lorsqu'il reçoit ce fameux 1.&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
[[Fichier:B5_test_pingpong.mp4|vignette|alt=test clavier sur shield (sans démonstration de altgr et maj) |test clavier sur shield (sans démonstration de altgr et maj)|center|800px]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Implémentation dans l'ordonnanceur===&lt;br /&gt;
Pour pouvoir utiliser le clavier avec l'ordonnanceur, il suffit de faire de notre while(1) précédent, une tâche a part entière de notre ordonnanceur. Sur cet exemple on voit l'utilisation du alt et du maj.&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
[[Fichier:B5_test_final.mp4|vignette|alt=test clavier avec ordonnancement |test clavier avec ordonnancement|center|800px]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;/div&gt;</summary>
		<author><name>Adjadjaa</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-5&amp;diff=7381</id>
		<title>SE4Binome2024-5</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-5&amp;diff=7381"/>
		<updated>2025-01-26T16:30:04Z</updated>

		<summary type="html">&lt;p&gt;Adjadjaa : /* Carte Fille Matrice de touches */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Introduction=&lt;br /&gt;
&lt;br /&gt;
Ce wiki documente le développement d’un pico-ordinateur modulaire. Ce dernier est constitué d’une carte principale, composée d’une carte Shield permettant la connexion des cartes filles, et d’une carte mère (initialement simulée par une Arduino Uno avant sa conception finale). Plusieurs cartes filles sont prévues, chacune remplissant une fonction spécifique : gestion du clavier, affichage, port série, réseau, mémoire de masse et son.&lt;br /&gt;
&lt;br /&gt;
Notre binôme est spécifiquement chargé du développement de la carte fille dédiée au clavier.&lt;br /&gt;
&lt;br /&gt;
Toutes les ressources nécessaires, incluant les codes sources et les schémas, sont disponibles sur le dépôt Git suivant :  [https://gitea.plil.fr/ktouron/se4-djadja-touron_pico.git Lien du Git]&lt;br /&gt;
&lt;br /&gt;
= Carte Shield =&lt;br /&gt;
[[Fichier:Carte Recto non soudé.jpg|vignette|left|thumb|350px|Recto de la carte avant soudage des composants]]&lt;br /&gt;
[[Fichier:Verso non solder.jpeg.jpg|vignette|thumb|right|300px|Verso de la carte avant soudage des composants]]&lt;br /&gt;
[[Fichier:Carde shield soudé.jpg|vignette|thumb|center|350px|Photo de la carte avec les composants soudés]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Test==&lt;br /&gt;
=== Allumage de LEDS sur Programmateur AVR ===&lt;br /&gt;
Avant de programmer directement sur le shield, nous avons allumé des LED pour tester la carte. Nous avons directement utilisé le code exemple fourni par l'IDE arduino en adaptant simplement les pins correspondant aux leds. [https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/PicoShield/Programmation/Blink Code du test]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Vid_test_carte_mp4.mp4|vignette|thumb|center|700px|Vidéo de Test des leds]]&lt;br /&gt;
&lt;br /&gt;
=== Lecture de la carte SD ===&lt;br /&gt;
Avant de programmer directement sur le shield, nous avons tester si la carte SD était bien détectée et lue. On a utilisé le code test présent dans l'IDE arduino en adaptant le port utilisé.[https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/PicoShield/Programmation/CardInfo Code du test]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Resultat SD.jpg|vignette|thumb|center|700px|Carte SD bien détéctée]]&lt;br /&gt;
&lt;br /&gt;
=== Connecteurs IDC HE10 ===&lt;br /&gt;
Afin de tester nos connecteur HE10, nous avons utilisé un afficher 7 segments (Sparkfun 7 segments display). Pour pouvoir vérifier leurs fonctionnements nous avons branché l'afficheur sur chaque connecteur tour à tour. Le programme implanté est un simple connecteur à afficher sur l'afficheur. Voici une vidéo du compteur fonctionnant sur un des 5 connecteurs HE10. ([https://learn.sparkfun.com/tutorials/using-the-serial-7-segment-display/all Code ici (section : Example 2 SPI)])&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Se4-5-7segments.mp4|vignette|alt=se4-5-7segments|Test connecteur HE10 avec afficheur 7 segments.|center]]&lt;br /&gt;
&lt;br /&gt;
== Ordonnanceur ==&lt;br /&gt;
Pour les interruptions de notre ordonnanceur nous avons utilisé la procédure d'initialisation du minuteur avec le Timer1 disponible dans les cours de Mr.Redon en renseignant une période de 20ms. Nous l'avons disposé dans le fichier minuteur.c car nous n'allons plus le modifier pour le reste du projet. Dans un autre fichier process.c (avec process.h), nous allons y mettre nos structures pour les process et leurs états puis une union pour le temps qui le caractérise ainsi que toutes les fonctions associés.&lt;br /&gt;
&lt;br /&gt;
[https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/Ordonnanceur Lien du répertoire]&lt;br /&gt;
&lt;br /&gt;
=== Processus ===&lt;br /&gt;
==== Structure ====&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:right; width: 48%; padding-left: 10px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
    uint16_t adresseDepart;  //adresse de la fonction de départ &lt;br /&gt;
    uint16_t adressePile;       //adresse de la pile d'exécution&lt;br /&gt;
    Etat etat;        &lt;br /&gt;
} Process;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Notre structure caractérisant un processus est définie par les trois champs ci-contre.&lt;br /&gt;
&lt;br /&gt;
Une adresse de départ correspondant à la fonction du processus associé, l'adresse où se situe le processus dans la pile puis l'état de la tâche. Nous avons décidé de faire une structure à part entière compte tenu des multitudes d'états que nous pourrons ajouter pendant la progression du projet.&lt;br /&gt;
&lt;br /&gt;
==== Etat d'un processus ====&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:right; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
typedef union {&lt;br /&gt;
  int sleepingtime;       &lt;br /&gt;
} Time;&lt;br /&gt;
&lt;br /&gt;
typedef struct {&lt;br /&gt;
  int id;&lt;br /&gt;
  Time time;&lt;br /&gt;
} Etat ;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
L'état d'un processus est alors une structure à deux champs (pour l'instant), l'id doit correspondre à un '#DEFINE' pour avoir un sens tandis que nous avons choisi de faire une union pour le temps qui caractérise notre état afin qu'il puisse avoir un nom et type de variable cohérent avec son état.(Ici seulement sleepingtime car seul l'état endormi existe pour le moment)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
  {| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
  |+ Tableau des états&lt;br /&gt;
  |-&lt;br /&gt;
  ! Etat !! ACTIVE !! SLEEPY !! ... !! ...&lt;br /&gt;
  |-&lt;br /&gt;
  | Id || 0 || 1 || ... || ...&lt;br /&gt;
  |}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Procédures principales ====&lt;br /&gt;
&lt;br /&gt;
=== ISR ===&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:right; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
ISR(TIMER1_COMPA_vect, ISR_NAKED)    // Procédure d'interruption&lt;br /&gt;
{&lt;br /&gt;
  TCNT1=0;//reset timer&lt;br /&gt;
  /* Sauvegarde du contexte de la tâche interrompue */&lt;br /&gt;
  portSAVE_REGISTERS();&lt;br /&gt;
   table_process[indice_tache].adressePile = SP;&lt;br /&gt;
  /* Appel à l'ordonnanceur */&lt;br /&gt;
  selectProcess();&lt;br /&gt;
  /* Récupération du contexte de la tâche ré-activée */&lt;br /&gt;
  SP = table_process[indice_tache].adressePile;&lt;br /&gt;
  portRESTORE_REGISTERS();&lt;br /&gt;
  &lt;br /&gt;
  asm volatile ( &amp;quot;reti&amp;quot; );&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
L'ISR est ce qu'il va être executer lors des interruptions toutes les 20 millisecondes. Cela consiste à sauvegarder tous les registres de la tâche qui était en cours avant l'appel de l'ISR pour ensuite passer à la tâche suivante valide (c'est à dire active) sans oublier de charger les registres de la nouvelle tâche.&lt;br /&gt;
&lt;br /&gt;
Nous devons également, à chaque fois avant de changer de tâche, enregistrer le pointeur de pile dans le processus afin de pouvoir revenir là ou elle en est la prochaine fois qu'elle sera appelée. Respectivement, une fois la nouvelle tâche choisie, le pointeur de pile doit prendre l'adresse de là ou en était la tâche avant qu'elle soit interrompue.&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Séléction de processus ====&lt;br /&gt;
Lors de la séléction de processus, nous devons parcourir tous les processus jusqu'au moment où nous en trouvons un actif. Ainsi, il deviendra la tâche que nous traiterons lors du prochain intervalle de 20 ms. A ce stade, à chaque fois que la procédure selectProcess est appelée, nous devons réduire le temps de repos de chaque process endormi de 20 ms. D'autres conditions pourrons être ajoutée si ajout d'état a lieu. (voir l'ajout de selectProcess dans l'ISR)&lt;br /&gt;
&lt;br /&gt;
=== Test ===&lt;br /&gt;
==== Clignotement de deux LED à fréquences indivisibles entre elles ====&lt;br /&gt;
Afin de vérifier la réussite de notre ordonnanceur à fonctionnement tourniquet, nous avons programmer deux simples tâches changeant l'état d'une LED. Une à une fréquence 200ms et l'autre 300ms (avec un _delay_ms).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:left; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void tache1(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTC ^= (1 &amp;lt;&amp;lt; PC0);&lt;br /&gt;
    _delay_ms(300);}}&lt;br /&gt;
void tache2(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTD ^= (1 &amp;lt;&amp;lt; PD7);&lt;br /&gt;
    _delay_ms(200);}}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
[[Fichier:B5_test1.mp4|vignette|alt=test des frequences imprevisibles|test des frequences imprevisibles]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Clignotement grâce à l'état endormi ====&lt;br /&gt;
Nous ajoutons l'état endormi afin que nos tâches ne mettent pas en pause l'ordonnanceur avec un _delay_ms. Pour cela, nous incorporons une fonction makeSleep qui permet de mettre la tâche qui l'appelle dans cet état.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:left; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void makeSleep(int t){&lt;br /&gt;
  table_process[indice_tache].etat.id = SLEEPY;&lt;br /&gt;
  table_process[indice_tache].etat.time.sleepingtime = t;&lt;br /&gt;
  TIMER1_COMPA_vect();}&lt;br /&gt;
void tache1(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTC ^= (1 &amp;lt;&amp;lt; PC0);&lt;br /&gt;
    _delay_ms(300);}}&lt;br /&gt;
void tache3(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTC ^= (1 &amp;lt;&amp;lt; PC3);&lt;br /&gt;
    //_delay_ms(1000);&lt;br /&gt;
    makeSleep(1000);}}&lt;br /&gt;
void tache2(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTD ^= (1 &amp;lt;&amp;lt; PD7);&lt;br /&gt;
    //_delay_ms(1000);&lt;br /&gt;
    makeSleep(700);}}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
[[Fichier:B5_test2.mp4|vignette|alt=test des frequences imprevisibles|test des frequences imprevisibles]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
A noter que la première tâche executée ne doit pas être endormie.&lt;br /&gt;
&lt;br /&gt;
=== Communication série et SPI ===&lt;br /&gt;
A l'aide du cours de Mr.Redon et de ressources sur internet nous avons pu confectionner deux librairies, une pour la communication SPI et une pour série (dans le répertoire Ordonnanceur/OldLibs car elle seront remplacées par celles données par Mr.Redon plus tard). Nous pouvons allons faire deux tâche distinctes dans notre ordonnanceur, une pour la communication série qui va récupérer le caractère d'une touche pressée pour l'écrire dans une variable globale tandis que la tâche SPI va lire cette variable globale est l'affiché sur un afficheur 7 segments.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:left; width: 48%; padding-left: 25px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
  void serial(void){&lt;br /&gt;
  while(1){&lt;br /&gt;
    data = USART_Receive();&lt;br /&gt;
    USART_sendChar(data);&lt;br /&gt;
    makeSleep(20);&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:right; width: 48%; padding-right: 25px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void aff7segments(void){&lt;br /&gt;
  while(1){&lt;br /&gt;
    aff_activer();&lt;br /&gt;
    aff_echange(data);&lt;br /&gt;
    aff_desactiver();&lt;br /&gt;
    makeSleep(1000);&lt;br /&gt;
    effacer_affichage();&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
[[Fichier:B5_serie_spi.mp4|vignette|alt=série et spi avec ordonnancement |série et spi avec ordonnancement|center|800px]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Carte Fille Matrice de touches =&lt;br /&gt;
==Explications générales sur la réalisation de la carte==&lt;br /&gt;
&lt;br /&gt;
Pour concevoir la carte fille dédiée au clavier, nous avons réutilisé un ancien clavier DELL équipé d’une matrice déjà fonctionnelle. L’idée consiste à connecter les sorties de cette matrice directement à notre carte fille à l’aide d’un connecteur adapté.&lt;br /&gt;
&lt;br /&gt;
Cependant, un défi se pose : la matrice du clavier comprend un total de 26 sorties (sans compter les LED et autres signaux). Cela dépasse largement les capacités en nombre de broches d’un ATmega328P.&lt;br /&gt;
&lt;br /&gt;
Pour remédier à ce problème, nous avons mis en place une solution d’encodage. Nous avons utilisé un décodeur (3 vers 8) pour gérer les lignes et trois encodeurs (8 vers 3) pour gérer les colonnes. Les encodeurs sont montés en cascade pour réduire significativement le nombre de broches nécessaires. Cette solution permet de minimiser l'utilisation des broches du microcontrôleur.&lt;br /&gt;
&lt;br /&gt;
Nous avons opté pour le décodeur 74HC138D (qui va envoyer un 0 parmi des 1) et trois encodeurs CD4532BM (qui cherche le premier 1 parmi des 0). On sent quand même les problèmes venir petit à petit. Nous avons étudié la datasheet et comment la mise en cascade fonctionne.&lt;br /&gt;
[[Fichier:Cascade.png|vignette|alt=Mise en cascade des encodeurs.|Mise en cascade des encodeurs.]]&lt;br /&gt;
On voit qu'un encodeur possède un bus de sortie de 5 bits. GS -&amp;gt; à l'état haut quand le composant reçoit un 1, 0 sinon. E0 -&amp;gt; à l'état haut quand il reçoit seulement des 0, 1 sinon. Puis Q2, Q1 ,Q0 la représentation binaire de l'entrée donnée.&lt;br /&gt;
&lt;br /&gt;
Afin de les mettre en cascade, il faut relié le E0 d'un premier encodeur au Ei de l'autre. Ensuite, nous allons faire un &amp;quot;OU&amp;quot; entre les GS afin de savoir si un des encodeurs reçoit un 1, puis grâce aux GS des deux premiers encodeurs nous sauront quelle encodeur à reçu le 1 (si les deux sont &amp;amp; 0 alors c'est le troisième). De même, faire une porte &amp;quot;OU&amp;quot; sur Q2, Q1, Q0 afin de réduire le nombre d'entrées/sorties nécessaires. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Par ailleurs, étant donné que nous utilisons directement le clavier Dell, il a été nécessaire de concevoir la carte avec des dimensions strictement identiques à celles de la carte d’origine, notamment en ce qui concerne sa largeur. Nous avons également dû ajouter des trous aux emplacements précis pour permettre de visser correctement la carte. Nous avons également dû créer l'empreinte KiCad du connecteur de la matrice, car celle-ci n’était pas disponible dans les bibliothèques existantes.[https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/CF_Clavier/Footprint_KeyboardDell_DJADJA Empreinte du connecteur matrice]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
[[Fichier:Clavier dell.png||thumb|right|800px|Clavier DELL]]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Connecteur de base clavier dell.png||thumb|left|500px|Carte du clavier DELL]]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Matrice clavier dell.png||thumb|right|800px|Matrice du clavier DELL]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Détails des composants ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;ATmega328P&amp;lt;/u&amp;gt;&lt;br /&gt;
* Micro-contrôleur&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;74HC138D&amp;lt;/u&amp;gt;&lt;br /&gt;
* Décodeur 3-&amp;gt;8: envoie un 0 parmi des 1.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;CD4532BM&amp;lt;/u&amp;gt;&lt;br /&gt;
* Encodeur 8-&amp;gt;3&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;74LS32&amp;lt;/u&amp;gt;&lt;br /&gt;
* Porte logique Or pour la mise en cascade des encodeurs.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Connecteur HE10&amp;lt;/u&amp;gt;&lt;br /&gt;
* Connecteur pour la liaison PicoShield-CarteFille&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Connecteur de la matrice&amp;lt;/u&amp;gt;&lt;br /&gt;
* Simplement une empreinte que l'on a créé [https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/CF_Clavier/Footprint_KeyboardDell_DJADJA Lien vers la bibliothèque présent sur le git]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;AVR-ISP-6&amp;lt;/u&amp;gt;&lt;br /&gt;
* Programmateur AVR&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;LED_SMD&amp;lt;/u&amp;gt;&lt;br /&gt;
* 3 LEDs&lt;br /&gt;
&lt;br /&gt;
== Hardware ==&lt;br /&gt;
===Kicad===&lt;br /&gt;
[[Fichier:Schematique carte fille clavier dell.png|center|1000px|vignette|Schématique de la carte Fille]]&lt;br /&gt;
&lt;br /&gt;
Pour réaliser la carte fille, nous avions dans un premier temps conçu une carte avec une matrice de touches directement implenter sur celle-ci, mais jugeant que cela était trop simple nous avons été redirigé vers l'utilisation d'une matrice déjà réalisé. Ainsi nous avons avons reutiliser celle d'un vieux clavier dell en créant les empreintes à la bonne taille pour se connecter sur la matrice&lt;br /&gt;
 &lt;br /&gt;
[[Fichier:Pcb recto carte fille clavier dell.png|left|480px|vignette|Avant du PCB]][[Fichier:Pcb verso carte fille clavier dell.png|right|480px|vignette|Arrière du PCB]]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Capture d’écran 2024-11-20 à 12.09.07.png|left|600px|vignette|PCB vue 3D avant]][[Fichier:Capture d’écran 2024-11-20 à 12.09.33.png|right|480px|vignette|PCB vue 3D arrière]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Différents Problèmes rencontrés===&lt;br /&gt;
Avant même la réception de la carte, alors que nous commençons a essayé d'écrire un premier programme, nous nous rendions compte qu'envoyer un 0 parmi des 1 et de rechercher un 1 parmi des 0 ne fonctionnera pas (logique). Nous avons alors pris la décision de changer le décodeur car il était pour nous plus simple de changer un composant que les trois encodeurs. Nous avons opté pour lui de la même famille, le 74HTC238D.&lt;br /&gt;
&lt;br /&gt;
Dès la réception de la carte, nous avons effectué un premier test avec une simple programmation de LED. Nous nous sommes rapidement aperçus que nous avions configuré deux noms d'étiquettes de reset distinctes sur KiCad : une pour l'AVR (RST) et une pour le connecteur HE-10 (RESET). Cependant, seul le reset du connecteur HE-10 était correctement relié au microcontrôleur. Pour résoudre ce problème, nous avons simplement connecté les deux broches de reset à l'aide d'un fil.&lt;br /&gt;
&lt;br /&gt;
Lors de l'examen initial de notre carte, nous avons également constaté une erreur que nous avions commise. En effet, comme nous avions initialement conçu une matrice de touches sans encodeurs ni décodeurs, il n'était donc pas nécessaire d'intégrer des résistances de pull-up ou de pull-down. Nous avons alors juste rajouter ces composants, or il en résulte que lorsqu'une touche sera pressée, un 1 sera bien envoyé mais pas parmi des 0, parmi des états indéterminé. En général, les états indéterminés, on aime pas trop, surtout quand cela empêche ta carte de pouvoir fonctionner comme voulu. Il a donc été nécessaire d'ajouter des résistances de pull-down sur chaque colonne de notre clavier. Afin de simplifier cette modification, nous avons utilisé des résistances CMS que nous avons positionnées comme des dominos (verticalement), ce qui nous a permis de faire passer un fil de masse directement au-dessus des résistances.&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Resistance pull Up domino.jpg|center|500px|vignette|Résistances de Pull-down sur les colonnes]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Une fois tous ces problèmes de base résolus, nous avons enfin pu nous attaquer à la programmation du clavier. Pour vérifier que toutes les touches étaient correctement détectées, nous avons réalisé un petit programme de test ([https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/CF_Clavier/prog/test.c Code du test]). Ce programme nous a permis d’associer chaque LED à un décodeur différent via la broche GS des décodeurs. Ainsi, nous avons pu identifier quelles touches ne répondaient pas. Premièrement, beaucoup de touches ne répondaient pas, moins d'une dizaine. Nous avons alors fait de multiples tests au multimètre sur notre carte mais aussi sur une autre matrice de touches similaire. Une des hypothèses fut qu'il fallait bien étamer les pistes pour permettre la conduction entre la carte et la matrice. Nous avons alors rajouter de l'étain, puis + de touches commençaient à fonctionner. Il fallait alors un nouveau programme de test pour détecter quelles lignes ou colonnes n'étaient pas bien étamés afin de permettre une conduction ([https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/CF_Clavier/prog/detect.c Code de détection]). Il suffisait ainsi de rajouter de l'étain sur les colonnes et les lignes qui ne répondaient pas. Enfin, toutes les touches sont détectées lors de d'une pression !&lt;br /&gt;
&lt;br /&gt;
==Programmation de la carte==&lt;br /&gt;
===Programme de test===&lt;br /&gt;
&lt;br /&gt;
[https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/CF_Clavier/prog/test.c Code du test]&lt;br /&gt;
&lt;br /&gt;
Lorsqu'une touche est pressée, le contact mécanique rebondit, générant plusieurs signaux rapides. Pour éviter que ces rebonds ne soient interprétés comme plusieurs pressions, nous avons simplement ajouté un délai de 100 millisecondes dans notre programme, ce qui permet d’ignorer ces variations et de ne retenir qu’un signal stable.&lt;br /&gt;
&lt;br /&gt;
Afin de tester chaque touche de notre matrice, nous avons décidé de faire le programme le plus simple possible en utilisant les broches GS de nos encodeurs. Il n'y a pas d'histoire de ligne ou de colonnes ici, si une touche est pressée alors le GS de l'encodeur ou sa colonne est reliée passera à l'état haut. Une manière très simple de savoir si une touche est utilisable et si nos trois encodeurs sont opérationnels également. Nous avons trois leds pour trois encodeurs, pour chaque encodeur, s'allumera une led spécifique si il reçoit un 1 parmi des 0.&lt;br /&gt;
&lt;br /&gt;
Afin de mettre en place ce système, il nous faut un programme capable de balayer toutes les lignes de notre matrice via un décodeur.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:left; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
int tab_outputs[8][3] = {&lt;br /&gt;
    {0, 0, 0},&lt;br /&gt;
    {1, 0, 0},&lt;br /&gt;
    {0, 1, 0},&lt;br /&gt;
    {1, 1, 0},&lt;br /&gt;
    {0, 0, 1},&lt;br /&gt;
    {1, 0, 1},&lt;br /&gt;
    {0, 1, 1},&lt;br /&gt;
    {1, 1, 1},&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void maj_output(int lig){&lt;br /&gt;
    for (int i = 0 ; i &amp;lt; 3 ; i++){&lt;br /&gt;
        if (tab_outputs[lig][i] == 0){&lt;br /&gt;
            PORTC &amp;amp;= ~(1 &amp;lt;&amp;lt; i);&lt;br /&gt;
        }&lt;br /&gt;
        else if (tab_outputs[lig][i] == 1){&lt;br /&gt;
            PORTC |= (1 &amp;lt;&amp;lt; i);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Fichier:B5_test_matrice.mp4|vignette|alt=test d'une touche pressée |test d'une touche pressée|right|800px]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
Ici, grâce à l'initialisation d'un tableau de la représentation en binaire des chiffres 0 à 7, il suffit de faire une procédure qui prend en paramètre le numéro de ligne souhaitée puis de vérifier dans le tableau quelle sortie mettre à 0 et 1. Nous avions remarqué que mettre les sorties pour les décodeurs sur le même port côte à côte facilite la programmation.&lt;br /&gt;
&lt;br /&gt;
===Programme de détection===&lt;br /&gt;
&lt;br /&gt;
([https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/CF_Clavier/prog/detect.c Code du test])&lt;br /&gt;
&lt;br /&gt;
Dans le projet, nous avons eu des problèmes de lignes et colonnes qui n'était pas conduit entre notre carte et la matrice. Pour les identifier, nous avons mis en place un programme de détection qui lors de la pression d'une touche, va afficher grâce aux leds, de quel encodeur sa colonne régit puis quelle ligne et quelle colonne est activée. Ce programme permet ainsi de diagnostiquer rapidement les problèmes de conduction entre la carte et la matrice en identifiant précisément les correspondances défectueuses. &lt;br /&gt;
&lt;br /&gt;
Pour cela, nous avons imaginer deux fonctions show_ligne et show_colonne, permettant d'afficher sur nos trois leds la ligne et la colonne. Si les leds affichent : double clignotements de la led du milieu  (allumée, éteint, allumé) puis (éteint, allumée, allumée) alors la ligne L6 (voir KiCad) et la 4e colonne du deuxième encodeur sont activées.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:left; width: 48%; padding-left: 25px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void show_ligne(int i){&lt;br /&gt;
    turn_off_leds();&lt;br /&gt;
    for (int bit = 0; bit &amp;lt; 3; bit++){&lt;br /&gt;
        if (tab_outputs[i][bit] == 1) {&lt;br /&gt;
            PORTC |= (1 &amp;lt;&amp;lt; (bit+LED1));&lt;br /&gt;
        }&lt;br /&gt;
        else &lt;br /&gt;
            PORTC &amp;amp;= ~(1 &amp;lt;&amp;lt; (bit+LED1));&lt;br /&gt;
        }&lt;br /&gt;
    _delay_ms(SHOW_TIME);&lt;br /&gt;
    turn_off_leds();&lt;br /&gt;
}}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:right; width: 48%; padding-right: 25px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void show_colonne(){&lt;br /&gt;
    turn_off_leds();&lt;br /&gt;
    for (int i = Q0; i &amp;lt; Q2 + 1 ; i++){&lt;br /&gt;
        if (((inputs &amp;gt;&amp;gt; i) &amp;amp; 1) == 1) {&lt;br /&gt;
            PORTC |= (1 &amp;lt;&amp;lt; (i+LED1));&lt;br /&gt;
        }&lt;br /&gt;
        else &lt;br /&gt;
            PORTC &amp;amp;= ~(1 &amp;lt;&amp;lt; (i+LED1));&lt;br /&gt;
    }&lt;br /&gt;
    _delay_ms(SHOW_TIME);&lt;br /&gt;
    turn_off_leds();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
Les deux fonctions se ressemblent beaucoup, la différence étant que show_ligne va prendre un paramètre un entier selon la ligne que nous voulons afficher alors que colonne va directement regarde dans le bus d'entrées la représentation binaire de la colonne activée. A noter que le fait que les LEDs et Q2, Q1, Q0 sont successivement placés sur le même port rend la programmation plus simple à réaliser.&lt;br /&gt;
&lt;br /&gt;
A noter la présence d'un 'uint8_t inputs;' où l'on va assigner PIND à chaque début d'une boucle, en effet pendant l'afficher l'utilisateur ne reste pas forcément la touche enfoncées ce qui changera les valeurs du bus d'entrée. Il est alors important de sauvegarder l'état de ce bus avant de l'afficher.&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
[[Fichier:B5_test_detect.mp4|vignette|alt=test de la détection d'une touche |test de la détection d'une touche|center|800px]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Ping pong===&lt;br /&gt;
A l'aide des ressources envoyées par Mr.Redon, nous avons de quoi communiquer entre le shield et notre carte fille. Pour cela, nous avons du modifié un tout petit peu les programmes. En effet, nous avons ajouter un #define pour le Chip Select de notre clavier (le bon connecteur HE10 sur lequel nous allons le connecter) afin que ce soit bien lui qui sera sélectionné lors du spi_select et spi_deselect. Le shield va envoyer un 1 en SPI pour indiquer au clavier qu'il est sur écoute et qu'il attend un envoie de la carte fille.&lt;br /&gt;
&lt;br /&gt;
Cette communication va nous permettre de bien mapper toutes nos touches.&lt;br /&gt;
&lt;br /&gt;
Nous avons décidé de faire un tableau en 3 dimensions afin de faciliter le mapping. Pourquoi 3 dimensions ? Nous avons une première dimension pour le numéro de ligne (0 à 7), pour le numéro de colonne (0 à 7) puis pour le numéro d'encodeur (0 à 2). Le bus d'entrée nous donnant un numéro de ligne entre 0 et 7, nous avons trouvé plus facile de procéder de cette manière. Voici un exemple.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:center; width: 48%;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
char tab_touches[8][8][3] = {&lt;br /&gt;
    {{'\0'/*AltGr*/, '\0', '\0'}, {'\0', '\0', '\0'}, {'-', ' ', '\0'}, {'\0'/*Fleche gauche*/, 'b', '\0'}, {'\0'/*Fleche droite*/, '\0', '\0'}, {'\0'/*Fleche bas*/, '\0', '\0'}, {'\0', '\0', '\0'}, {'\0', '!', '\0'}}, &lt;br /&gt;
    {{'\0', 'x', 'w'}, {'\0', 'c', '\0'/*CTRL Droit*/}, {'*', '\n', '\0'}, {'\0'/*Pause*/, 'v', '\0'}, {'/', ',', '\0'}, {'\0'/*Verr Num*/, ';', '\0'}, {'\0'/*Touch window droite*/, ':', '\0'}, {'\0'/*Shift droit*/, '*', '\0'}}, &lt;br /&gt;
    {{'\0'/*Arret*/, 'z', 'a'}, {'\0'/*Options*/, 'e', '\0'}, {'9', '\0', '\0'}, {'\0', 'r', '\0'}, {'8', 'u', '\0'}, {'7', 'i', '\0'}, {'\0', 'o', '\0'}, {'*', 'p', '\0'}}, &lt;br /&gt;
    {{'\0', 's', 'q'}, {'\0'/*Touche window gauche*/, 'd', '\0'}, {'3', '\0', '\0'}, {'\n', 'f', '\0'}, {'2', 'j', '\0'}, {'1', 'k', '\0'}, {'\0', 'l', '\0'}, {'\0', 'm', '\0'}}, &lt;br /&gt;
    {{'\0', '\0', '\0'}, {'\0', '\0', '\0'}, {'\0', '\0', '\0'}, {'\0', '\0', '\0'}, {'\0', '\0', '\0'}, {'\0', '\0', 'w'}, {'\0', '\0', '\0'}, {'\0', '\0', '\0'}}, &lt;br /&gt;
    {{'\0', '&amp;lt;', '\0'}, {'\0', '\0', '\0'}, {'.', '\0', '\0'}, {'\0', 'g', '\0'}, {'0', 'h', '\0'}, {'\0', '\0', '\0'}, {'\0', '\0', '\0'}, {'\0', '%', '\0'}}, &lt;br /&gt;
    {{'\0', '\0'/*MAJ*/, '\0'/*tab*/}, {'\0', '\0'/*F3*/, '\0'}, {'\0', 8, '\0'}, {'\0', 't', '\0'}, {'5', 'y', '\0'}, {'4', '$', '\0'}, {'\0', '\0'/*F7*/, '\0'}, {'\0'/*Shift gauche*/, '^', '\0'}}, &lt;br /&gt;
    {{'\0', '\0'/*F1*/, '\0'/*œ*/}, {'\0', '\0'/*F2*/, '\0'/*CTRL Gauche*/}, {'\0'/*Page haut*/, '\0'/*F9*/, '\0'}, {'\0'/*Debut*/, '(', '\0'}, {'\0'/*Insert*/, '-', '\0'}, {'\0'/*Supp*/, '=', '\0'}, {'t', '\n'/*F8*/, '\0'}, {'g', ')', '\0'}}&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Notre clavier ne supporte pas l'appuie de plusieurs touches en simultané à cause de la présence de décodeurs et d'encodeurs, le shift devient inutilisable, seulement maj est opérationnel. Afin de permettre l'utilisation de altgr, il fonctionnera comme le maj mais les deux ne pourront pas être activés en même temps.&lt;br /&gt;
&lt;br /&gt;
Nous avons tout d'abord mit des valeurs au hasard mais unique dans le tableau, puis nous avons identifié les touches pour une case dans le tableau, nous avons fait ce processus plusieurs fois afin de trouver toutes les cases des touches du clavier dans le tableau. Pour permettre l'utilisation du maj et du altgr, nous avons créer deux autres tableau comme ça, un chacun avec ses touches assignées. Lors de l'envoie, il faut vérifier dans quel mode nous nous trouvons pour envoyer le caractère dans le bon tableau (alt, maj ou classique).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:left; width: 48%; padding-left: 25px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
  while(1)&lt;br /&gt;
  {&lt;br /&gt;
    spi_select();&lt;br /&gt;
    uint8_t r=spi_exch(1);&lt;br /&gt;
    if (r != 1) printf(&amp;quot;%c&amp;quot;,r);&lt;br /&gt;
    spi_deselect();&lt;br /&gt;
    _delay_ms(20);&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:right; width: 48%; padding-right: 25px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void envoyer(){&lt;br /&gt;
    printf(&amp;quot;Clavier attente\n&amp;quot;);&lt;br /&gt;
      uint8_t message=spi_wait();&lt;br /&gt;
      printf(&amp;quot;Clavier reçu %d\n&amp;quot;,message);&lt;br /&gt;
      if (message == 1)&lt;br /&gt;
        spi_sendback(temp);&lt;br /&gt;
      printf(&amp;quot;Clavier retour préparé %d\n&amp;quot;,temp);&lt;br /&gt;
  &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
Ici le shield (à gauche) va envoyer un 1 en SPI pour dire au clavier qu'il est prêt à l'écouter, si il reçoit autre chose qu'un 1 (son propre envoie) alors il l'affiche. Le clavier (à droite) va envoyer son dernier caractère dont la touche a été pressée lorsqu'il reçoit ce fameux 1.&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
[[Fichier:B5_test_pingpong.mp4|vignette|alt=test clavier sur shield (sans démonstration de altgr et maj) |test clavier sur shield (sans démonstration de altgr et maj)|center|800px]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Implémentation dans l'ordonnanceur===&lt;br /&gt;
Pour pouvoir utiliser le clavier avec l'ordonnanceur, il suffit de faire de notre while(1) précédent, une tâche a part entière de notre ordonnanceur. Sur cet exemple on voit l'utilisation du alt et du maj.&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
[[Fichier:B5_test_final.mp4|vignette|alt=test clavier avec ordonnancement |test clavier avec ordonnancement|center|800px]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;/div&gt;</summary>
		<author><name>Adjadjaa</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-5&amp;diff=7379</id>
		<title>SE4Binome2024-5</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-5&amp;diff=7379"/>
		<updated>2025-01-26T16:25:33Z</updated>

		<summary type="html">&lt;p&gt;Adjadjaa : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Introduction=&lt;br /&gt;
&lt;br /&gt;
Ce wiki documente le développement d’un pico-ordinateur modulaire. Ce dernier est constitué d’une carte principale, composée d’une carte Shield permettant la connexion des cartes filles, et d’une carte mère (initialement simulée par une Arduino Uno avant sa conception finale). Plusieurs cartes filles sont prévues, chacune remplissant une fonction spécifique : gestion du clavier, affichage, port série, réseau, mémoire de masse et son.&lt;br /&gt;
&lt;br /&gt;
Notre binôme est spécifiquement chargé du développement de la carte fille dédiée au clavier.&lt;br /&gt;
&lt;br /&gt;
Toutes les ressources nécessaires, incluant les codes sources et les schémas, sont disponibles sur le dépôt Git suivant :  [https://gitea.plil.fr/ktouron/se4-djadja-touron_pico.git Lien du Git]&lt;br /&gt;
&lt;br /&gt;
= Carte Shield =&lt;br /&gt;
[[Fichier:Carte Recto non soudé.jpg|vignette|left|thumb|350px|Recto de la carte avant soudage des composants]]&lt;br /&gt;
[[Fichier:Verso non solder.jpeg.jpg|vignette|thumb|right|300px|Verso de la carte avant soudage des composants]]&lt;br /&gt;
[[Fichier:Carde shield soudé.jpg|vignette|thumb|center|350px|Photo de la carte avec les composants soudés]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Test==&lt;br /&gt;
=== Allumage de LEDS sur Programmateur AVR ===&lt;br /&gt;
Avant de programmer directement sur le shield, nous avons allumé des LED pour tester la carte. Nous avons directement utilisé le code exemple fourni par l'IDE arduino en adaptant simplement les pins correspondant aux leds. [https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/PicoShield/Programmation/Blink Code du test]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Vid_test_carte_mp4.mp4|vignette|thumb|center|700px|Vidéo de Test des leds]]&lt;br /&gt;
&lt;br /&gt;
=== Lecture de la carte SD ===&lt;br /&gt;
Avant de programmer directement sur le shield, nous avons tester si la carte SD était bien détectée et lue. On a utilisé le code test présent dans l'IDE arduino en adaptant le port utilisé.[https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/PicoShield/Programmation/CardInfo Code du test]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Resultat SD.jpg|vignette|thumb|center|700px|Carte SD bien détéctée]]&lt;br /&gt;
&lt;br /&gt;
=== Connecteurs IDC HE10 ===&lt;br /&gt;
Afin de tester nos connecteur HE10, nous avons utilisé un afficher 7 segments (Sparkfun 7 segments display). Pour pouvoir vérifier leurs fonctionnements nous avons branché l'afficheur sur chaque connecteur tour à tour. Le programme implanté est un simple connecteur à afficher sur l'afficheur. Voici une vidéo du compteur fonctionnant sur un des 5 connecteurs HE10. ([https://learn.sparkfun.com/tutorials/using-the-serial-7-segment-display/all Code ici (section : Example 2 SPI)])&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Se4-5-7segments.mp4|vignette|alt=se4-5-7segments|Test connecteur HE10 avec afficheur 7 segments.|center]]&lt;br /&gt;
&lt;br /&gt;
== Ordonnanceur ==&lt;br /&gt;
Pour les interruptions de notre ordonnanceur nous avons utilisé la procédure d'initialisation du minuteur avec le Timer1 disponible dans les cours de Mr.Redon en renseignant une période de 20ms. Nous l'avons disposé dans le fichier minuteur.c car nous n'allons plus le modifier pour le reste du projet. Dans un autre fichier process.c (avec process.h), nous allons y mettre nos structures pour les process et leurs états puis une union pour le temps qui le caractérise ainsi que toutes les fonctions associés.&lt;br /&gt;
&lt;br /&gt;
[https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/Ordonnanceur Lien du répertoire]&lt;br /&gt;
&lt;br /&gt;
=== Processus ===&lt;br /&gt;
==== Structure ====&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:right; width: 48%; padding-left: 10px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
    uint16_t adresseDepart;  //adresse de la fonction de départ &lt;br /&gt;
    uint16_t adressePile;       //adresse de la pile d'exécution&lt;br /&gt;
    Etat etat;        &lt;br /&gt;
} Process;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Notre structure caractérisant un processus est définie par les trois champs ci-contre.&lt;br /&gt;
&lt;br /&gt;
Une adresse de départ correspondant à la fonction du processus associé, l'adresse où se situe le processus dans la pile puis l'état de la tâche. Nous avons décidé de faire une structure à part entière compte tenu des multitudes d'états que nous pourrons ajouter pendant la progression du projet.&lt;br /&gt;
&lt;br /&gt;
==== Etat d'un processus ====&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:right; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
typedef union {&lt;br /&gt;
  int sleepingtime;       &lt;br /&gt;
} Time;&lt;br /&gt;
&lt;br /&gt;
typedef struct {&lt;br /&gt;
  int id;&lt;br /&gt;
  Time time;&lt;br /&gt;
} Etat ;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
L'état d'un processus est alors une structure à deux champs (pour l'instant), l'id doit correspondre à un '#DEFINE' pour avoir un sens tandis que nous avons choisi de faire une union pour le temps qui caractérise notre état afin qu'il puisse avoir un nom et type de variable cohérent avec son état.(Ici seulement sleepingtime car seul l'état endormi existe pour le moment)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
  {| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
  |+ Tableau des états&lt;br /&gt;
  |-&lt;br /&gt;
  ! Etat !! ACTIVE !! SLEEPY !! ... !! ...&lt;br /&gt;
  |-&lt;br /&gt;
  | Id || 0 || 1 || ... || ...&lt;br /&gt;
  |}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Procédures principales ====&lt;br /&gt;
&lt;br /&gt;
=== ISR ===&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:right; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
ISR(TIMER1_COMPA_vect, ISR_NAKED)    // Procédure d'interruption&lt;br /&gt;
{&lt;br /&gt;
  TCNT1=0;//reset timer&lt;br /&gt;
  /* Sauvegarde du contexte de la tâche interrompue */&lt;br /&gt;
  portSAVE_REGISTERS();&lt;br /&gt;
   table_process[indice_tache].adressePile = SP;&lt;br /&gt;
  /* Appel à l'ordonnanceur */&lt;br /&gt;
  selectProcess();&lt;br /&gt;
  /* Récupération du contexte de la tâche ré-activée */&lt;br /&gt;
  SP = table_process[indice_tache].adressePile;&lt;br /&gt;
  portRESTORE_REGISTERS();&lt;br /&gt;
  &lt;br /&gt;
  asm volatile ( &amp;quot;reti&amp;quot; );&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
L'ISR est ce qu'il va être executer lors des interruptions toutes les 20 millisecondes. Cela consiste à sauvegarder tous les registres de la tâche qui était en cours avant l'appel de l'ISR pour ensuite passer à la tâche suivante valide (c'est à dire active) sans oublier de charger les registres de la nouvelle tâche.&lt;br /&gt;
&lt;br /&gt;
Nous devons également, à chaque fois avant de changer de tâche, enregistrer le pointeur de pile dans le processus afin de pouvoir revenir là ou elle en est la prochaine fois qu'elle sera appelée. Respectivement, une fois la nouvelle tâche choisie, le pointeur de pile doit prendre l'adresse de là ou en était la tâche avant qu'elle soit interrompue.&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Séléction de processus ====&lt;br /&gt;
Lors de la séléction de processus, nous devons parcourir tous les processus jusqu'au moment où nous en trouvons un actif. Ainsi, il deviendra la tâche que nous traiterons lors du prochain intervalle de 20 ms. A ce stade, à chaque fois que la procédure selectProcess est appelée, nous devons réduire le temps de repos de chaque process endormi de 20 ms. D'autres conditions pourrons être ajoutée si ajout d'état a lieu. (voir l'ajout de selectProcess dans l'ISR)&lt;br /&gt;
&lt;br /&gt;
=== Test ===&lt;br /&gt;
==== Clignotement de deux LED à fréquences indivisibles entre elles ====&lt;br /&gt;
Afin de vérifier la réussite de notre ordonnanceur à fonctionnement tourniquet, nous avons programmer deux simples tâches changeant l'état d'une LED. Une à une fréquence 200ms et l'autre 300ms (avec un _delay_ms).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:left; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void tache1(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTC ^= (1 &amp;lt;&amp;lt; PC0);&lt;br /&gt;
    _delay_ms(300);}}&lt;br /&gt;
void tache2(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTD ^= (1 &amp;lt;&amp;lt; PD7);&lt;br /&gt;
    _delay_ms(200);}}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
[[Fichier:B5_test1.mp4|vignette|alt=test des frequences imprevisibles|test des frequences imprevisibles]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Clignotement grâce à l'état endormi ====&lt;br /&gt;
Nous ajoutons l'état endormi afin que nos tâches ne mettent pas en pause l'ordonnanceur avec un _delay_ms. Pour cela, nous incorporons une fonction makeSleep qui permet de mettre la tâche qui l'appelle dans cet état.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:left; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void makeSleep(int t){&lt;br /&gt;
  table_process[indice_tache].etat.id = SLEEPY;&lt;br /&gt;
  table_process[indice_tache].etat.time.sleepingtime = t;&lt;br /&gt;
  TIMER1_COMPA_vect();}&lt;br /&gt;
void tache1(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTC ^= (1 &amp;lt;&amp;lt; PC0);&lt;br /&gt;
    _delay_ms(300);}}&lt;br /&gt;
void tache3(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTC ^= (1 &amp;lt;&amp;lt; PC3);&lt;br /&gt;
    //_delay_ms(1000);&lt;br /&gt;
    makeSleep(1000);}}&lt;br /&gt;
void tache2(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTD ^= (1 &amp;lt;&amp;lt; PD7);&lt;br /&gt;
    //_delay_ms(1000);&lt;br /&gt;
    makeSleep(700);}}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
[[Fichier:B5_test2.mp4|vignette|alt=test des frequences imprevisibles|test des frequences imprevisibles]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
A noter que la première tâche executée ne doit pas être endormie.&lt;br /&gt;
&lt;br /&gt;
=== Communication série et SPI ===&lt;br /&gt;
A l'aide du cours de Mr.Redon et de ressources sur internet nous avons pu confectionner deux librairies, une pour la communication SPI et une pour série (dans le répertoire Ordonnanceur/OldLibs car elle seront remplacées par celles données par Mr.Redon plus tard). Nous pouvons allons faire deux tâche distinctes dans notre ordonnanceur, une pour la communication série qui va récupérer le caractère d'une touche pressée pour l'écrire dans une variable globale tandis que la tâche SPI va lire cette variable globale est l'affiché sur un afficheur 7 segments.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:left; width: 48%; padding-left: 25px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
  void serial(void){&lt;br /&gt;
  while(1){&lt;br /&gt;
    data = USART_Receive();&lt;br /&gt;
    USART_sendChar(data);&lt;br /&gt;
    makeSleep(20);&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:right; width: 48%; padding-right: 25px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void aff7segments(void){&lt;br /&gt;
  while(1){&lt;br /&gt;
    aff_activer();&lt;br /&gt;
    aff_echange(data);&lt;br /&gt;
    aff_desactiver();&lt;br /&gt;
    makeSleep(1000);&lt;br /&gt;
    effacer_affichage();&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
[[Fichier:B5_serie_spi.mp4|vignette|alt=test clavier sur shield (sans démonstration de altgr et maj) |test clavier sur shield (sans démonstration de altgr et maj)|center|800px]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Carte Fille Matrice de touches =&lt;br /&gt;
==Explications générales sur la réalisation de la carte==&lt;br /&gt;
&lt;br /&gt;
Pour concevoir la carte fille dédiée au clavier, nous avons réutilisé un ancien clavier DELL équipé d’une matrice déjà fonctionnelle. L’idée consiste à connecter les sorties de cette matrice directement à notre carte fille à l’aide d’un connecteur adapté.&lt;br /&gt;
&lt;br /&gt;
Cependant, un défi se pose : la matrice du clavier comprend un total de 26 sorties (sans compter les LED et autres signaux). Cela dépasse largement les capacités en nombre de broches d’un ATmega328P.&lt;br /&gt;
&lt;br /&gt;
Pour remédier à ce problème, nous avons mis en place une solution d’encodage. Nous avons utilisé un décodeur (3 vers 8) pour gérer les lignes et trois encodeurs (8 vers 3) pour gérer les colonnes. Les encodeurs sont montés en cascade pour réduire significativement le nombre de broches nécessaires. Cette solution permet de maximiser les ressources du microcontrôleur tout en gérant efficacement les signaux de la matrice.&lt;br /&gt;
&lt;br /&gt;
Nous avons opté pour le décodeur 74HC138D (qui va envoyer un 0 parmi des 1) et trois encodeurs CD4532BM (qui cherche le premier 1 parmi des 0). On sent quand même les problèmes venir petit à petit. Nous avons étudié la datasheet et comment la mise en cascade fonctionne.&lt;br /&gt;
[[Fichier:Cascade.png|vignette|alt=Mise en cascade des encodeurs.|Mise en cascade des encodeurs.]]&lt;br /&gt;
On voit qu'un encodeur possède un bus de sortie de 5 bits. GS -&amp;gt; à l'état haut quand le composant reçoit un 1, 0 sinon. E0 -&amp;gt; à l'état haut quand il reçoit seulement des 0, 1 sinon. Puis Q2, Q1 ,Q0 la représentation binaire de l'entrée donnée.&lt;br /&gt;
&lt;br /&gt;
Afin de les mettre en cascade, il faut relié le E0 d'un premier encodeur au Ei de l'autre. Ensuite, nous allons faire un &amp;quot;OU&amp;quot; entre les GS afin de savoir si un des encodeurs reçoit un 1, puis grâce aux GS des deux premiers encodeurs nous sauront quelle encodeur à reçu le 1 (si les deux sont &amp;amp; 0 alors c'est le troisième). De même, faire une porte &amp;quot;OU&amp;quot; sur Q2, Q1, Q0 afin de réduire le nombre d'entrées/sorties nécessaires.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Par ailleurs, étant donné que nous utilisons directement le clavier Dell, il a été nécessaire de concevoir la carte avec des dimensions strictement identiques à celles de la carte d’origine, notamment en ce qui concerne sa largeur. Nous avons également dû ajouter des trous aux emplacements précis pour permettre de visser correctement la carte. Nous avons également dû créer l'empreinte KiCad du connecteur de la matrice, car celle-ci n’était pas disponible dans les bibliothèques existantes.[https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/CF_Clavier/Footprint_KeyboardDell_DJADJA Empreinte du connecteur matrice]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
[[Fichier:Clavier dell.png||thumb|right|800px|Clavier DELL]]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Connecteur de base clavier dell.png||thumb|left|500px|Carte du clavier DELL]]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Matrice clavier dell.png||thumb|right|800px|Matrice du clavier DELL]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Détails des composants ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;ATmega328P&amp;lt;/u&amp;gt;&lt;br /&gt;
* Micro-contrôleur&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;74HC138D&amp;lt;/u&amp;gt;&lt;br /&gt;
* Décodeur : envoie un 0 parmi des 1.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;CD4532BM&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;74LS32&amp;lt;/u&amp;gt;&lt;br /&gt;
* Porte logique Or pour la mise en cascade des encodeurs.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Connecteur HE10&amp;lt;/u&amp;gt;&lt;br /&gt;
* Connecteur pour la liaison PicoShield-CarteFille&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Connecteur de la matrice&amp;lt;/u&amp;gt;&lt;br /&gt;
* Simplement une empreinte que l'on a créé [https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/CF_Clavier/Footprint_KeyboardDell_DJADJA Lien vers la bibliothèque présent sur le git]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;AVR-ISP-6&amp;lt;/u&amp;gt;&lt;br /&gt;
* Programmateur AVR&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;LED_SMD&amp;lt;/u&amp;gt;&lt;br /&gt;
* 3 LEDs&lt;br /&gt;
&lt;br /&gt;
== Hardware ==&lt;br /&gt;
===Kicad===&lt;br /&gt;
[[Fichier:Schematique carte fille clavier dell.png|center|1000px|vignette|Schématique de la carte Fille]]&lt;br /&gt;
&lt;br /&gt;
Pour réaliser la carte fille, nous avions dans un premier temps conçu une carte avec une matrice de touches directement implenter sur celle-ci, mais jugeant que cela était trop simple nous avons été redirigé vers l'utilisation d'une matrice déjà réalisé. Ainsi nous avons avons reutiliser celle d'un vieux clavier dell en créant les empreintes à la bonne taille pour se connecter sur la matrice&lt;br /&gt;
 &lt;br /&gt;
[[Fichier:Pcb recto carte fille clavier dell.png|left|480px|vignette|Avant du PCB]][[Fichier:Pcb verso carte fille clavier dell.png|right|480px|vignette|Arrière du PCB]]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Capture d’écran 2024-11-20 à 12.09.07.png|left|600px|vignette|PCB vue 3D avant]][[Fichier:Capture d’écran 2024-11-20 à 12.09.33.png|right|480px|vignette|PCB vue 3D arrière]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Différents Problèmes rencontrés===&lt;br /&gt;
Avant même la réception de la carte, alors que nous commençons a essayé d'écrire un premier programme, nous nous rendions compte qu'envoyer un 0 parmi des 1 et de rechercher un 1 parmi des 0 ne fonctionnera pas (logique). Nous avons alors pris la décision de changer le décodeur car il était pour nous plus simple de changer un composant que les trois encodeurs. Nous avons opté pour lui de la même famille, le 74HTC238D.&lt;br /&gt;
&lt;br /&gt;
Dès la réception de la carte, nous avons effectué un premier test avec une simple programmation de LED. Nous nous sommes rapidement aperçus que nous avions configuré deux noms d'étiquettes de reset distinctes sur KiCad : une pour l'AVR (RST) et une pour le connecteur HE-10 (RESET). Cependant, seul le reset du connecteur HE-10 était correctement relié au microcontrôleur. Pour résoudre ce problème, nous avons simplement connecté les deux broches de reset à l'aide d'un fil.&lt;br /&gt;
&lt;br /&gt;
Lors de l'examen initial de notre carte, nous avons également constaté une erreur que nous avions commise. En effet, comme nous avions initialement conçu une matrice de touches sans encodeurs ni décodeurs, il n'était donc pas nécessaire d'intégrer des résistances de pull-up ou de pull-down. Nous avons alors juste rajouter ces composants, or il en résulte que lorsqu'une touche sera pressée, un 1 sera bien envoyé mais pas parmi des 0, parmi des états indéterminé. En général, les états indéterminés, on aime pas trop, surtout quand cela empêche ta carte de pouvoir fonctionner comme voulu. Il a donc été nécessaire d'ajouter des résistances de pull-down sur chaque colonne de notre clavier. Afin de simplifier cette modification, nous avons utilisé des résistances CMS que nous avons positionnées comme des dominos (verticalement), ce qui nous a permis de faire passer un fil de masse directement au-dessus des résistances.&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Resistance pull Up domino.jpg|center|500px|vignette|Résistances de Pull-down sur les colonnes]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Une fois tous ces problèmes de base résolus, nous avons enfin pu nous attaquer à la programmation du clavier. Pour vérifier que toutes les touches étaient correctement détectées, nous avons réalisé un petit programme de test ([https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/CF_Clavier/prog/test.c Code du test]). Ce programme nous a permis d’associer chaque LED à un décodeur différent via la broche GS des décodeurs. Ainsi, nous avons pu identifier quelles touches ne répondaient pas. Premièrement, beaucoup de touches ne répondaient pas, moins d'une dizaine. Nous avons alors fait de multiples tests au multimètre sur notre carte mais aussi sur une autre matrice de touches similaire. Une des hypothèses fut qu'il fallait bien étamer les pistes pour permettre la conduction entre la carte et la matrice. Nous avons alors rajouter de l'étain, puis + de touches commençaient à fonctionner. Il fallait alors un nouveau programme de test pour détecter quelles lignes ou colonnes n'étaient pas bien étamés afin de permettre une conduction ([https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/CF_Clavier/prog/detect.c Code de détection]). Il suffisait ainsi de rajouter de l'étain sur les colonnes et les lignes qui ne répondaient pas. Enfin, toutes les touches sont détectées lors de d'une pression !&lt;br /&gt;
&lt;br /&gt;
==Programmation de la carte==&lt;br /&gt;
===Programme de test===&lt;br /&gt;
&lt;br /&gt;
[https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/CF_Clavier/prog/test.c Code du test]&lt;br /&gt;
&lt;br /&gt;
Lorsqu'une touche est pressée, le contact mécanique rebondit, générant plusieurs signaux rapides. Pour éviter que ces rebonds ne soient interprétés comme plusieurs pressions, nous avons simplement ajouté un délai de 100 millisecondes dans notre programme, ce qui permet d’ignorer ces variations et de ne retenir qu’un signal stable.&lt;br /&gt;
&lt;br /&gt;
Afin de tester chaque touche de notre matrice, nous avons décidé de faire le programme le plus simple possible en utilisant les broches GS de nos encodeurs. Il n'y a pas d'histoire de ligne ou de colonnes ici, si une touche est pressée alors le GS de l'encodeur ou sa colonne est reliée passera à l'état haut. Une manière très simple de savoir si une touche est utilisable et si nos trois encodeurs sont opérationnels également. Nous avons trois leds pour trois encodeurs, pour chaque encodeur, s'allumera une led spécifique si il reçoit un 1 parmi des 0.&lt;br /&gt;
&lt;br /&gt;
Afin de mettre en place ce système, il nous faut un programme capable de balayer toutes les lignes de notre matrice via un décodeur.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:left; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
int tab_outputs[8][3] = {&lt;br /&gt;
    {0, 0, 0},&lt;br /&gt;
    {1, 0, 0},&lt;br /&gt;
    {0, 1, 0},&lt;br /&gt;
    {1, 1, 0},&lt;br /&gt;
    {0, 0, 1},&lt;br /&gt;
    {1, 0, 1},&lt;br /&gt;
    {0, 1, 1},&lt;br /&gt;
    {1, 1, 1},&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void maj_output(int lig){&lt;br /&gt;
    for (int i = 0 ; i &amp;lt; 3 ; i++){&lt;br /&gt;
        if (tab_outputs[lig][i] == 0){&lt;br /&gt;
            PORTC &amp;amp;= ~(1 &amp;lt;&amp;lt; i);&lt;br /&gt;
        }&lt;br /&gt;
        else if (tab_outputs[lig][i] == 1){&lt;br /&gt;
            PORTC |= (1 &amp;lt;&amp;lt; i);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Fichier:B5_test_matrice.mp4|vignette|alt=test d'une touche pressée |test d'une touche pressée|right|800px]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
Ici, grâce à l'initialisation d'un tableau de la représentation en binaire des chiffres 0 à 7, il suffit de faire une procédure qui prend en paramètre le numéro de ligne souhaitée puis de vérifier dans le tableau quelle sortie mettre à 0 et 1. Nous avions remarqué que mettre les sorties pour les décodeurs sur le même port côte à côte facilite la programmation.&lt;br /&gt;
&lt;br /&gt;
===Programme de détection===&lt;br /&gt;
&lt;br /&gt;
([https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/CF_Clavier/prog/detect.c Code du test])&lt;br /&gt;
&lt;br /&gt;
Dans le projet, nous avons eu des problèmes de lignes et colonnes qui n'était pas conduit entre notre carte et la matrice. Pour les identifier, nous avons mis en place un programme de détection qui lors de la pression d'une touche, va afficher grâce aux leds, de quel encodeur sa colonne régit puis quelle ligne et quelle colonne est activée. Ce programme permet ainsi de diagnostiquer rapidement les problèmes de conduction entre la carte et la matrice en identifiant précisément les correspondances défectueuses. &lt;br /&gt;
&lt;br /&gt;
Pour cela, nous avons imaginer deux fonctions show_ligne et show_colonne, permettant d'afficher sur nos trois leds la ligne et la colonne. Si les leds affichent : double clignotements de la led du milieu  (allumée, éteint, allumé) puis (éteint, allumée, allumée) alors la ligne L6 (voir KiCad) et la 4e colonne du deuxième encodeur sont activées.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:left; width: 48%; padding-left: 25px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void show_ligne(int i){&lt;br /&gt;
    turn_off_leds();&lt;br /&gt;
    for (int bit = 0; bit &amp;lt; 3; bit++){&lt;br /&gt;
        if (tab_outputs[i][bit] == 1) {&lt;br /&gt;
            PORTC |= (1 &amp;lt;&amp;lt; (bit+LED1));&lt;br /&gt;
        }&lt;br /&gt;
        else &lt;br /&gt;
            PORTC &amp;amp;= ~(1 &amp;lt;&amp;lt; (bit+LED1));&lt;br /&gt;
        }&lt;br /&gt;
    _delay_ms(SHOW_TIME);&lt;br /&gt;
    turn_off_leds();&lt;br /&gt;
}}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:right; width: 48%; padding-right: 25px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void show_colonne(){&lt;br /&gt;
    turn_off_leds();&lt;br /&gt;
    for (int i = Q0; i &amp;lt; Q2 + 1 ; i++){&lt;br /&gt;
        if (((inputs &amp;gt;&amp;gt; i) &amp;amp; 1) == 1) {&lt;br /&gt;
            PORTC |= (1 &amp;lt;&amp;lt; (i+LED1));&lt;br /&gt;
        }&lt;br /&gt;
        else &lt;br /&gt;
            PORTC &amp;amp;= ~(1 &amp;lt;&amp;lt; (i+LED1));&lt;br /&gt;
    }&lt;br /&gt;
    _delay_ms(SHOW_TIME);&lt;br /&gt;
    turn_off_leds();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
Les deux fonctions se ressemblent beaucoup, la différence étant que show_ligne va prendre un paramètre un entier selon la ligne que nous voulons afficher alors que colonne va directement regarde dans le bus d'entrées la représentation binaire de la colonne activée. A noter que le fait que les LEDs et Q2, Q1, Q0 sont successivement placés sur le même port rend la programmation plus simple à réaliser.&lt;br /&gt;
&lt;br /&gt;
A noter la présence d'un 'uint8_t inputs;' où l'on va assigner PIND à chaque début d'une boucle, en effet pendant l'afficher l'utilisateur ne reste pas forcément la touche enfoncées ce qui changera les valeurs du bus d'entrée. Il est alors important de sauvegarder l'état de ce bus avant de l'afficher.&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
[[Fichier:B5_test_detect.mp4|vignette|alt=test de la détection d'une touche |test de la détection d'une touche|center|800px]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Ping pong===&lt;br /&gt;
A l'aide des ressources envoyées par Mr.Redon, nous avons de quoi communiquer entre le shield et notre carte fille. Pour cela, nous avons du modifié un tout petit peu les programmes. En effet, nous avons ajouter un #define pour le Chip Select de notre clavier (le bon connecteur HE10 sur lequel nous allons le connecter) afin que ce soit bien lui qui sera sélectionné lors du spi_select et spi_deselect. Le shield va envoyer un 1 en SPI pour indiquer au clavier qu'il est sur écoute et qu'il attend un envoie de la carte fille.&lt;br /&gt;
&lt;br /&gt;
Cette communication va nous permettre de bien mapper toutes nos touches.&lt;br /&gt;
&lt;br /&gt;
Nous avons décidé de faire un tableau en 3 dimensions afin de faciliter le mapping. Pourquoi 3 dimensions ? Nous avons une première dimension pour le numéro de ligne (0 à 7), pour le numéro de colonne (0 à 7) puis pour le numéro d'encodeur (0 à 2). Le bus d'entrée nous donnant un numéro de ligne entre 0 et 7, nous avons trouvé plus facile de procéder de cette manière. Voici un exemple.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:center; width: 48%;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
char tab_touches[8][8][3] = {&lt;br /&gt;
    {{'\0'/*AltGr*/, '\0', '\0'}, {'\0', '\0', '\0'}, {'-', ' ', '\0'}, {'\0'/*Fleche gauche*/, 'b', '\0'}, {'\0'/*Fleche droite*/, '\0', '\0'}, {'\0'/*Fleche bas*/, '\0', '\0'}, {'\0', '\0', '\0'}, {'\0', '!', '\0'}}, &lt;br /&gt;
    {{'\0', 'x', 'w'}, {'\0', 'c', '\0'/*CTRL Droit*/}, {'*', '\n', '\0'}, {'\0'/*Pause*/, 'v', '\0'}, {'/', ',', '\0'}, {'\0'/*Verr Num*/, ';', '\0'}, {'\0'/*Touch window droite*/, ':', '\0'}, {'\0'/*Shift droit*/, '*', '\0'}}, &lt;br /&gt;
    {{'\0'/*Arret*/, 'z', 'a'}, {'\0'/*Options*/, 'e', '\0'}, {'9', '\0', '\0'}, {'\0', 'r', '\0'}, {'8', 'u', '\0'}, {'7', 'i', '\0'}, {'\0', 'o', '\0'}, {'*', 'p', '\0'}}, &lt;br /&gt;
    {{'\0', 's', 'q'}, {'\0'/*Touche window gauche*/, 'd', '\0'}, {'3', '\0', '\0'}, {'\n', 'f', '\0'}, {'2', 'j', '\0'}, {'1', 'k', '\0'}, {'\0', 'l', '\0'}, {'\0', 'm', '\0'}}, &lt;br /&gt;
    {{'\0', '\0', '\0'}, {'\0', '\0', '\0'}, {'\0', '\0', '\0'}, {'\0', '\0', '\0'}, {'\0', '\0', '\0'}, {'\0', '\0', 'w'}, {'\0', '\0', '\0'}, {'\0', '\0', '\0'}}, &lt;br /&gt;
    {{'\0', '&amp;lt;', '\0'}, {'\0', '\0', '\0'}, {'.', '\0', '\0'}, {'\0', 'g', '\0'}, {'0', 'h', '\0'}, {'\0', '\0', '\0'}, {'\0', '\0', '\0'}, {'\0', '%', '\0'}}, &lt;br /&gt;
    {{'\0', '\0'/*MAJ*/, '\0'/*tab*/}, {'\0', '\0'/*F3*/, '\0'}, {'\0', 8, '\0'}, {'\0', 't', '\0'}, {'5', 'y', '\0'}, {'4', '$', '\0'}, {'\0', '\0'/*F7*/, '\0'}, {'\0'/*Shift gauche*/, '^', '\0'}}, &lt;br /&gt;
    {{'\0', '\0'/*F1*/, '\0'/*œ*/}, {'\0', '\0'/*F2*/, '\0'/*CTRL Gauche*/}, {'\0'/*Page haut*/, '\0'/*F9*/, '\0'}, {'\0'/*Debut*/, '(', '\0'}, {'\0'/*Insert*/, '-', '\0'}, {'\0'/*Supp*/, '=', '\0'}, {'t', '\n'/*F8*/, '\0'}, {'g', ')', '\0'}}&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Notre clavier ne supporte pas l'appuie de plusieurs touches en simultané à cause de la présence de décodeurs et d'encodeurs, le shift devient inutilisable, seulement maj est opérationnel. Afin de permettre l'utilisation de altgr, il fonctionnera comme le maj mais les deux ne pourront pas être activés en même temps.&lt;br /&gt;
&lt;br /&gt;
Nous avons tout d'abord mit des valeurs au hasard mais unique dans le tableau, puis nous avons identifié les touches pour une case dans le tableau, nous avons fait ce processus plusieurs fois afin de trouver toutes les cases des touches du clavier dans le tableau. Pour permettre l'utilisation du maj et du altgr, nous avons créer deux autres tableau comme ça, un chacun avec ses touches assignées. Lors de l'envoie, il faut vérifier dans quel mode nous nous trouvons pour envoyer le caractère dans le bon tableau (alt, maj ou classique).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:left; width: 48%; padding-left: 25px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
  while(1)&lt;br /&gt;
  {&lt;br /&gt;
    spi_select();&lt;br /&gt;
    uint8_t r=spi_exch(1);&lt;br /&gt;
    if (r != 1) printf(&amp;quot;%c&amp;quot;,r);&lt;br /&gt;
    spi_deselect();&lt;br /&gt;
    _delay_ms(20);&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:right; width: 48%; padding-right: 25px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void envoyer(){&lt;br /&gt;
    printf(&amp;quot;Clavier attente\n&amp;quot;);&lt;br /&gt;
      uint8_t message=spi_wait();&lt;br /&gt;
      printf(&amp;quot;Clavier reçu %d\n&amp;quot;,message);&lt;br /&gt;
      if (message == 1)&lt;br /&gt;
        spi_sendback(temp);&lt;br /&gt;
      printf(&amp;quot;Clavier retour préparé %d\n&amp;quot;,temp);&lt;br /&gt;
  &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
Ici le shield (à gauche) va envoyer un 1 en SPI pour dire au clavier qu'il est prêt à l'écouter, si il reçoit autre chose qu'un 1 (son propre envoie) alors il l'affiche. Le clavier (à droite) va envoyer son dernier caractère dont la touche a été pressée lorsqu'il reçoit ce fameux 1.&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
[[Fichier:B5_test_pingpong.mp4|vignette|alt=test clavier sur shield (sans démonstration de altgr et maj) |test clavier sur shield (sans démonstration de altgr et maj)|center|800px]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Implémentation dans l'ordonnanceur===&lt;br /&gt;
Pour pouvoir utiliser le clavier avec l'ordonnanceur, il suffit de faire de notre while(1) précédent, une tâche a part entière de notre ordonnanceur. Sur cet exemple on voit l'utilisation du alt et du maj.&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
[[Fichier:B5_test_final.mp4|vignette|alt=test clavier avec ordonnancement |test clavier avec ordonnancement|center|800px]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;/div&gt;</summary>
		<author><name>Adjadjaa</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-5&amp;diff=7373</id>
		<title>SE4Binome2024-5</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-5&amp;diff=7373"/>
		<updated>2025-01-26T16:17:29Z</updated>

		<summary type="html">&lt;p&gt;Adjadjaa : /* Explications générales sur la réalisation de la carte */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Introduction=&lt;br /&gt;
&lt;br /&gt;
Ce wiki documente le développement d’un pico-ordinateur modulaire. Ce dernier est constitué d’une carte principale, composée d’une carte Shield permettant la connexion des cartes filles, et d’une carte mère (initialement simulée par une Arduino Uno avant sa conception finale). Plusieurs cartes filles sont prévues, chacune remplissant une fonction spécifique : gestion du clavier, affichage, port série, réseau, mémoire de masse et son.&lt;br /&gt;
&lt;br /&gt;
Notre binôme est spécifiquement chargé du développement de la carte fille dédiée au clavier.&lt;br /&gt;
&lt;br /&gt;
Toutes les ressources nécessaires, incluant les codes sources et les schémas, sont disponibles sur le dépôt Git suivant :  [https://gitea.plil.fr/ktouron/se4-djadja-touron_pico.git Lien du Git]&lt;br /&gt;
&lt;br /&gt;
= Carte Shield =&lt;br /&gt;
[[Fichier:Carte Recto non soudé.jpg|vignette|left|thumb|350px|Recto de la carte avant soudage des composants]]&lt;br /&gt;
[[Fichier:Verso non solder.jpeg.jpg|vignette|thumb|right|300px|Verso de la carte avant soudage des composants]]&lt;br /&gt;
[[Fichier:Carde shield soudé.jpg|vignette|thumb|center|350px|Photo de la carte avec les composants soudés]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Test==&lt;br /&gt;
=== Allumage de LEDS sur Programmateur AVR ===&lt;br /&gt;
Avant de programmer directement sur le shield, nous avons allumé des LED pour tester la carte. Nous avons directement utilisé le code exemple fourni par l'IDE arduino en adaptant simplement les pins correspondant aux leds. [https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/PicoShield/Programmation/Blink Code du test]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Vid_test_carte_mp4.mp4|vignette|thumb|center|700px|Vidéo de Test des leds]]&lt;br /&gt;
&lt;br /&gt;
=== Lecture de la carte SD ===&lt;br /&gt;
Avant de programmer directement sur le shield, nous avons tester si la carte SD était bien détectée et lue. On a utilisé le code test présent dans l'IDE arduino en adaptant le port utilisé.[https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/PicoShield/Programmation/CardInfo Code du test]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Resultat SD.jpg|vignette|thumb|center|700px|Carte SD bien détéctée]]&lt;br /&gt;
&lt;br /&gt;
=== Connecteurs IDC HE10 ===&lt;br /&gt;
Afin de tester nos connecteur HE10, nous avons utilisé un afficher 7 segments (Sparkfun 7 segments display). Pour pouvoir vérifier leurs fonctionnements nous avons branché l'afficheur sur chaque connecteur tour à tour. Le programme implanté est un simple connecteur à afficher sur l'afficheur. Voici une vidéo du compteur fonctionnant sur un des 5 connecteurs HE10. ([https://learn.sparkfun.com/tutorials/using-the-serial-7-segment-display/all Code ici (section : Example 2 SPI)])&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Se4-5-7segments.mp4|vignette|alt=se4-5-7segments|Test connecteur HE10 avec afficheur 7 segments.|center]]&lt;br /&gt;
== Ordonnanceur ==&lt;br /&gt;
Pour les interruptions de notre ordonnanceur nous avons utilisé la procédure d'initialisation du minuteur avec le Timer1 disponible dans les cours de Mr.Redon en renseignant une période de 20ms. Nous l'avons disposé dans le fichier minuteur.c car nous n'allons plus le modifier pour le reste du projet. Dans un autre fichier process.c (avec process.h), nous allons y mettre nos structures pour les process et leurs états puis une union pour le temps qui le caractérise ainsi que toutes les fonctions associés.&lt;br /&gt;
&lt;br /&gt;
[https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/Ordonnanceur Lien du répertoire]&lt;br /&gt;
&lt;br /&gt;
=== Processus ===&lt;br /&gt;
==== Structure ====&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:right; width: 48%; padding-left: 10px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
    uint16_t adresseDepart;  //adresse de la fonction de départ &lt;br /&gt;
    uint16_t adressePile;       //adresse de la pile d'exécution&lt;br /&gt;
    Etat etat;        &lt;br /&gt;
} Process;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Notre structure caractérisant un processus est définie par les trois champs ci-contre.&lt;br /&gt;
&lt;br /&gt;
Une adresse de départ correspondant à la fonction du processus associé, l'adresse où se situe le processus dans la pile puis l'état de la tâche. Nous avons décidé de faire une structure à part entière compte tenu des multitudes d'états que nous pourrons ajouter pendant la progression du projet.&lt;br /&gt;
&lt;br /&gt;
==== Etat d'un processus ====&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:right; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
typedef union {&lt;br /&gt;
  int sleepingtime;       &lt;br /&gt;
} Time;&lt;br /&gt;
&lt;br /&gt;
typedef struct {&lt;br /&gt;
  int id;&lt;br /&gt;
  Time time;&lt;br /&gt;
} Etat ;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
L'état d'un processus est alors une structure à deux champs (pour l'instant), l'id doit correspondre à un '#DEFINE' pour avoir un sens tandis que nous avons choisi de faire une union pour le temps qui caractérise notre état afin qu'il puisse avoir un nom et type de variable cohérent avec son état.(Ici seulement sleepingtime car seul l'état endormi existe pour le moment)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
  {| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
  |+ Tableau des états&lt;br /&gt;
  |-&lt;br /&gt;
  ! Etat !! ACTIVE !! SLEEPY !! ... !! ...&lt;br /&gt;
  |-&lt;br /&gt;
  | Id || 0 || 1 || ... || ...&lt;br /&gt;
  |}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Procédures principales ====&lt;br /&gt;
&lt;br /&gt;
=== ISR ===&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:right; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
ISR(TIMER1_COMPA_vect, ISR_NAKED)    // Procédure d'interruption&lt;br /&gt;
{&lt;br /&gt;
  TCNT1=0;//reset timer&lt;br /&gt;
  /* Sauvegarde du contexte de la tâche interrompue */&lt;br /&gt;
  portSAVE_REGISTERS();&lt;br /&gt;
   table_process[indice_tache].adressePile = SP;&lt;br /&gt;
  /* Appel à l'ordonnanceur */&lt;br /&gt;
  selectProcess();&lt;br /&gt;
  /* Récupération du contexte de la tâche ré-activée */&lt;br /&gt;
  SP = table_process[indice_tache].adressePile;&lt;br /&gt;
  portRESTORE_REGISTERS();&lt;br /&gt;
  &lt;br /&gt;
  asm volatile ( &amp;quot;reti&amp;quot; );&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
L'ISR est ce qu'il va être executer lors des interruptions toutes les 20 millisecondes. Cela consiste à sauvegarder tous les registres de la tâche qui était en cours avant l'appel de l'ISR pour ensuite passer à la tâche suivante valide (c'est à dire active) sans oublier de charger les registres de la nouvelle tâche.&lt;br /&gt;
&lt;br /&gt;
Nous devons également, à chaque fois avant de changer de tâche, enregistrer le pointeur de pile dans le processus afin de pouvoir revenir là ou elle en est la prochaine fois qu'elle sera appelée. Respectivement, une fois la nouvelle tâche choisie, le pointeur de pile doit prendre l'adresse de là ou en était la tâche avant qu'elle soit interrompue.&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Séléction de processus ====&lt;br /&gt;
Lors de la séléction de processus, nous devons parcourir tous les processus jusqu'au moment où nous en trouvons un actif. Ainsi, il deviendra la tâche que nous traiterons lors du prochain intervalle de 20 ms. A ce stade, à chaque fois que la procédure selectProcess est appelée, nous devons réduire le temps de repos de chaque process endormi de 20 ms. D'autres conditions pourrons être ajoutée si ajout d'état a lieu. (voir l'ajout de selectProcess dans l'ISR)&lt;br /&gt;
&lt;br /&gt;
=== Test ===&lt;br /&gt;
==== Clignotement de deux LED à fréquences indivisibles entre elles ====&lt;br /&gt;
Afin de vérifier la réussite de notre ordonnanceur à fonctionnement tourniquet, nous avons programmer deux simples tâches changeant l'état d'une LED. Une à une fréquence 200ms et l'autre 300ms (avec un _delay_ms).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:left; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void tache1(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTC ^= (1 &amp;lt;&amp;lt; PC0);&lt;br /&gt;
    _delay_ms(300);}}&lt;br /&gt;
void tache2(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTD ^= (1 &amp;lt;&amp;lt; PD7);&lt;br /&gt;
    _delay_ms(200);}}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
[[Fichier:B5_test1.mp4|vignette|alt=test des frequences imprevisibles|test des frequences imprevisibles]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Clignotement grâce à l'état endormi ====&lt;br /&gt;
Nous ajoutons l'état endormi afin que nos tâches ne mettent pas en pause l'ordonnanceur avec un _delay_ms. Pour cela, nous incorporons une fonction makeSleep qui permet de mettre la tâche qui l'appelle dans cet état.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:left; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void makeSleep(int t){&lt;br /&gt;
  table_process[indice_tache].etat.id = SLEEPY;&lt;br /&gt;
  table_process[indice_tache].etat.time.sleepingtime = t;&lt;br /&gt;
  TIMER1_COMPA_vect();}&lt;br /&gt;
void tache1(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTC ^= (1 &amp;lt;&amp;lt; PC0);&lt;br /&gt;
    _delay_ms(300);}}&lt;br /&gt;
void tache3(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTC ^= (1 &amp;lt;&amp;lt; PC3);&lt;br /&gt;
    //_delay_ms(1000);&lt;br /&gt;
    makeSleep(1000);}}&lt;br /&gt;
void tache2(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTD ^= (1 &amp;lt;&amp;lt; PD7);&lt;br /&gt;
    //_delay_ms(1000);&lt;br /&gt;
    makeSleep(700);}}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
[[Fichier:B5_test2.mp4|vignette|alt=test des frequences imprevisibles|test des frequences imprevisibles]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
A noter que la première tâche executée ne doit pas être endormie.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Carte Fille Matrice de touches =&lt;br /&gt;
==Explications générales sur la réalisation de la carte==&lt;br /&gt;
&lt;br /&gt;
Pour concevoir la carte fille dédiée au clavier, nous avons réutilisé un ancien clavier DELL équipé d’une matrice déjà fonctionnelle. L’idée consiste à connecter les sorties de cette matrice directement à notre carte fille à l’aide d’un connecteur adapté.&lt;br /&gt;
&lt;br /&gt;
Cependant, un défi se pose : la matrice du clavier comprend un total de 26 sorties (sans compter les LED et autres signaux). Cela dépasse largement les capacités en nombre de broches d’un ATmega328P.&lt;br /&gt;
&lt;br /&gt;
Pour remédier à ce problème, nous avons mis en place une solution d’encodage. Nous avons utilisé un décodeur (3 vers 8) pour gérer les lignes et trois encodeurs (8 vers 3) pour gérer les colonnes. Les encodeurs sont montés en cascade pour réduire significativement le nombre de broches nécessaires. Cette solution permet de maximiser les ressources du microcontrôleur tout en gérant efficacement les signaux de la matrice.&lt;br /&gt;
&lt;br /&gt;
Nous avons opté pour le décodeur 74HC138D (qui va envoyer un 0 parmi des 1) et trois encodeurs CD4532BM (qui cherche le premier 1 parmi des 0). On sent quand même les problèmes venir petit à petit. &lt;br /&gt;
&lt;br /&gt;
Par ailleurs, étant donné que nous utilisons directement le clavier Dell, il a été nécessaire de concevoir la carte avec des dimensions strictement identiques à celles de la carte d’origine, notamment en ce qui concerne sa largeur. Nous avons également dû ajouter des trous aux emplacements précis pour permettre de visser correctement la carte. Nous avons également dû créer l'empreinte KiCad du connecteur de la matrice, car celle-ci n’était pas disponible dans les bibliothèques existantes.[https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/CF_Clavier/Footprint_KeyboardDell_DJADJA Empreinte du connecteur matrice]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
[[Fichier:Clavier dell.png||thumb|right|800px|Clavier DELL]]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Connecteur de base clavier dell.png||thumb|left|500px|Carte du clavier DELL]]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Matrice clavier dell.png||thumb|right|800px|Matrice du clavier DELL]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Détails des composants ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;ATmega328P&amp;lt;/u&amp;gt;&lt;br /&gt;
* Micro-contrôleur&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;74HC138D&amp;lt;/u&amp;gt;&lt;br /&gt;
* Décodeur : envoie un 0 parmi des 1.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;CD4532BM&amp;lt;/u&amp;gt;&lt;br /&gt;
* Encodeur : Nous avons étudié la datasheet et comment la mise en cascade fonctionne.&lt;br /&gt;
[[Fichier:Cascade.png|vignette|alt=Mise en cascade des encodeurs.|Mise en cascade des encodeurs.]]&lt;br /&gt;
On voit qu'un encodeur possède un bus de sortie de 5 bits. GS -&amp;gt; à l'état haut quand le composant reçoit un 1, 0 sinon. E0 -&amp;gt; à l'état haut quand il reçoit seulement des 0, 1 sinon. Puis Q2, Q1 ,Q0 la représentation binaire de l'entrée donnée.&lt;br /&gt;
&lt;br /&gt;
Afin de les mettre en cascade, il faut relié le E0 d'un premier encodeur au Ei de l'autre. Ensuite, nous allons faire un &amp;quot;OU&amp;quot; entre les GS afin de savoir si un des encodeurs reçoit un 1, puis grâce aux GS des deux premiers encodeurs nous sauront quelle encodeur à reçu le 1 (si les deux sont &amp;amp; 0 alors c'est le troisième). De même, faire une porte &amp;quot;OU&amp;quot; sur Q2, Q1, Q0 afin de réduire le nombre d'entrées/sorties nécessaires.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&amp;lt;u&amp;gt;74LS32&amp;lt;/u&amp;gt;&lt;br /&gt;
* Porte logique Or pour la mise en cascade des encodeurs.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Connecteur HE10&amp;lt;/u&amp;gt;&lt;br /&gt;
* Connecteur pour la liaison PicoShield-CarteFille&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Connecteur de la matrice&amp;lt;/u&amp;gt;&lt;br /&gt;
* Simplement une empreinte que l'on a créé [https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/CF_Clavier/Footprint_KeyboardDell_DJADJA Lien vers la bibliothèque présent sur le git]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;AVR-ISP-6&amp;lt;/u&amp;gt;&lt;br /&gt;
* Programmateur AVR&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;LED_SMD&amp;lt;/u&amp;gt;&lt;br /&gt;
* 3 LEDs&lt;br /&gt;
&lt;br /&gt;
== Hardware ==&lt;br /&gt;
===Kicad===&lt;br /&gt;
[[Fichier:Schematique carte fille clavier dell.png|center|1000px|vignette|Schématique de la carte Fille]]&lt;br /&gt;
&lt;br /&gt;
Pour réaliser la carte fille, nous avions dans un premier temps conçu une carte avec une matrice de touches directement implenter sur celle-ci, mais jugeant que cela était trop simple nous avons été redirigé vers l'utilisation d'une matrice déjà réalisé. Ainsi nous avons avons reutiliser celle d'un vieux clavier dell en créant les empreintes à la bonne taille pour se connecter sur la matrice&lt;br /&gt;
 &lt;br /&gt;
[[Fichier:Pcb recto carte fille clavier dell.png|left|480px|vignette|Avant du PCB]][[Fichier:Pcb verso carte fille clavier dell.png|right|480px|vignette|Arrière du PCB]]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Capture d’écran 2024-11-20 à 12.09.07.png|left|600px|vignette|PCB vue 3D avant]][[Fichier:Capture d’écran 2024-11-20 à 12.09.33.png|right|480px|vignette|PCB vue 3D arrière]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Carte après soudure des composants====&lt;br /&gt;
&lt;br /&gt;
===Différents Problèmes rencontrés===&lt;br /&gt;
Avant même la réception de la carte, alors que nous commençons a essayé d'écrire un premier programme, nous nous rendions compte qu'envoyer un 0 parmi des 1 et de rechercher un 1 parmi des 0 ne fonctionnera pas (logique). Nous avons alors pris la décision de changer le décodeur car il était pour nous plus simple de changer un composant que les trois encodeurs. Nous avons opté pour lui de la même famille, le 74HTC238D.&lt;br /&gt;
&lt;br /&gt;
Dès la réception de la carte, nous avons effectué un premier test avec une simple programmation de LED. Nous nous sommes rapidement aperçus que nous avions configuré deux noms d'étiquettes de reset distinctes sur KiCad : une pour l'AVR (RST) et une pour le connecteur HE-10 (RESET). Cependant, seul le reset du connecteur HE-10 était correctement relié au microcontrôleur. Pour résoudre ce problème, nous avons simplement connecté les deux broches de reset à l'aide d'un fil.&lt;br /&gt;
&lt;br /&gt;
Lors de l'examen initial de notre carte, nous avons également constaté une erreur que nous avions commise. En effet, comme nous avions initialement conçu une matrice de touches sans encodeurs ni décodeurs, il n'était donc pas nécessaire d'intégrer des résistances de pull-up ou de pull-down. Nous avons alors juste rajouter ces composants, or il en résulte que lorsqu'une touche sera pressée, un 1 sera bien envoyé mais pas parmi des 0, parmi des états indéterminé. En général, les états indéterminés, on aime pas trop, surtout quand cela empêche ta carte de pouvoir fonctionner comme voulu. Il a donc été nécessaire d'ajouter des résistances de pull-down sur chaque colonne de notre clavier. Afin de simplifier cette modification, nous avons utilisé des résistances CMS que nous avons positionnées comme des dominos (verticalement), ce qui nous a permis de faire passer un fil de masse directement au-dessus des résistances.&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Resistance pull Up domino.jpg|center|500px|vignette|Résistances de Pull-down sur les colonnes]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Une fois tous ces problèmes de base résolus, nous avons enfin pu nous attaquer à la programmation du clavier. Pour vérifier que toutes les touches étaient correctement détectées, nous avons réalisé un petit programme de test ([https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/CF_Clavier/prog/test.c Code du test]). Ce programme nous a permis d’associer chaque LED à un décodeur différent via la broche GS des décodeurs. Ainsi, nous avons pu identifier quelles touches ne répondaient pas. Premièrement, beaucoup de touches ne répondaient pas, moins d'une dizaine. Nous avons alors fait de multiples tests au multimètre sur notre carte mais aussi sur une autre matrice de touches similaire. Une des hypothèses fut qu'il fallait bien étamer les pistes pour permettre la conduction entre la carte et la matrice. Nous avons alors rajouter de l'étain, puis + de touches commençaient à fonctionner. Il fallait alors un nouveau programme de test pour détecter quelles lignes ou colonnes n'étaient pas bien étamés afin de permettre une conduction ([https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/CF_Clavier/prog/detect.c Code de détection]). Il suffisait ainsi de rajouter de l'étain sur les colonnes et les lignes qui ne répondaient pas. Enfin, toutes les touches sont détectées lors de d'une pression !&lt;br /&gt;
&lt;br /&gt;
==Programmation de la carte==&lt;br /&gt;
===Programme de test===&lt;br /&gt;
&lt;br /&gt;
([https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/CF_Clavier/prog/test.c Code du test])&lt;br /&gt;
&lt;br /&gt;
Afin de tester chaque touche de notre matrice, nous avons décidé de faire le programme le plus simple possible en utilisant les broches GS de nos encodeurs. Il n'y a pas d'histoire de ligne ou de colonnes ici, si une touche est pressée alors le GS de l'encodeur ou sa colonne est reliée passera à l'état haut. Une manière très simple de savoir si une touche est utilisable et si nos trois encodeurs sont opérationnels également. Nous avons trois leds pour trois encodeurs, pour chaque encodeur, s'allumera une led spécifique si il reçoit un 1 parmi des 0.&lt;br /&gt;
&lt;br /&gt;
Afin de mettre en place ce système, il nous faut un programme capable de balayer toutes les lignes de notre matrice via un décodeur.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:left; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
int tab_outputs[8][3] = {&lt;br /&gt;
    {0, 0, 0},&lt;br /&gt;
    {1, 0, 0},&lt;br /&gt;
    {0, 1, 0},&lt;br /&gt;
    {1, 1, 0},&lt;br /&gt;
    {0, 0, 1},&lt;br /&gt;
    {1, 0, 1},&lt;br /&gt;
    {0, 1, 1},&lt;br /&gt;
    {1, 1, 1},&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void maj_output(int lig){&lt;br /&gt;
    for (int i = 0 ; i &amp;lt; 3 ; i++){&lt;br /&gt;
        if (tab_outputs[lig][i] == 0){&lt;br /&gt;
            PORTC &amp;amp;= ~(1 &amp;lt;&amp;lt; i);&lt;br /&gt;
        }&lt;br /&gt;
        else if (tab_outputs[lig][i] == 1){&lt;br /&gt;
            PORTC |= (1 &amp;lt;&amp;lt; i);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Fichier:B5_test_matrice.mp4|vignette|alt=test d'une touche pressée |test d'une touche pressée|right|800px]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
Ici, grâce à l'initialisation d'un tableau de la représentation en binaire des chiffres 0 à 7, il suffit de faire une procédure qui prend en paramètre le numéro de ligne souhaitée puis de vérifier dans le tableau quelle sortie mettre à 0 et 1. Nous avions remarqué que mettre les sorties pour les décodeurs sur le même port côte à côte facilite la programmation.&lt;br /&gt;
&lt;br /&gt;
===Programme de détection===&lt;br /&gt;
&lt;br /&gt;
([https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/CF_Clavier/prog/detect.c Code du test])&lt;br /&gt;
&lt;br /&gt;
Dans le projet, nous avons eu des problèmes de lignes et colonnes qui n'était pas conduit entre notre carte et la matrice. Pour les identifier, nous avons mis en place un programme de détection qui lors de la pression d'une touche, va afficher grâce aux leds, de quel encodeur sa colonne régit puis quelle ligne et quelle colonne est activée. Ce programme permet ainsi de diagnostiquer rapidement les problèmes de conduction entre la carte et la matrice en identifiant précisément les correspondances défectueuses. &lt;br /&gt;
&lt;br /&gt;
Pour cela, nous avons imaginer deux fonctions show_ligne et show_colonne, permettant d'afficher sur nos trois leds la ligne et la colonne. Si les leds affichent : double clignotements de la led du milieu  (allumée, éteint, allumé) puis (éteint, allumée, allumée) alors la ligne L6 (voir KiCad) et la 4e colonne du deuxième encodeur sont activées.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:left; width: 48%; padding-left: 25px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void show_ligne(int i){&lt;br /&gt;
    turn_off_leds();&lt;br /&gt;
    for (int bit = 0; bit &amp;lt; 3; bit++){&lt;br /&gt;
        if (tab_outputs[i][bit] == 1) {&lt;br /&gt;
            PORTC |= (1 &amp;lt;&amp;lt; (bit+LED1));&lt;br /&gt;
        }&lt;br /&gt;
        else &lt;br /&gt;
            PORTC &amp;amp;= ~(1 &amp;lt;&amp;lt; (bit+LED1));&lt;br /&gt;
        }&lt;br /&gt;
    _delay_ms(SHOW_TIME);&lt;br /&gt;
    turn_off_leds();&lt;br /&gt;
}}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:right; width: 48%; padding-right: 25px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void show_colonne(){&lt;br /&gt;
    turn_off_leds();&lt;br /&gt;
    for (int i = Q0; i &amp;lt; Q2 + 1 ; i++){&lt;br /&gt;
        if (((inputs &amp;gt;&amp;gt; i) &amp;amp; 1) == 1) {&lt;br /&gt;
            PORTC |= (1 &amp;lt;&amp;lt; (i+LED1));&lt;br /&gt;
        }&lt;br /&gt;
        else &lt;br /&gt;
            PORTC &amp;amp;= ~(1 &amp;lt;&amp;lt; (i+LED1));&lt;br /&gt;
    }&lt;br /&gt;
    _delay_ms(SHOW_TIME);&lt;br /&gt;
    turn_off_leds();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
Les deux fonctions se ressemblent beaucoup, la différence étant que show_ligne va prendre un paramètre un entier selon la ligne que nous voulons afficher alors que colonne va directement regarde dans le bus d'entrées la représentation binaire de la colonne activée. A noter que le fait que les LEDs et Q2, Q1, Q0 sont successivement placés sur le même port rend la programmation plus simple à réaliser.&lt;br /&gt;
&lt;br /&gt;
A noter la présence d'un 'uint8_t inputs;' où l'on va assigner PIND à chaque début d'une boucle, en effet pendant l'afficher l'utilisateur ne reste pas forcément la touche enfoncées ce qui changera les valeurs du bus d'entrée. Il est alors important de sauvegarder l'état de ce bus avant de l'afficher.&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
[[Fichier:B5_test_detect.mp4|vignette|alt=test de la détection d'une touche |test de la détection d'une touche|center|800px]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Ping pong===&lt;br /&gt;
A l'aide des ressources envoyées par Mr.Redon, nous avons de quoi communiquer entre le shield et notre carte fille. Pour cela, nous avons du modifié un tout petit peu les programmes. En effet, nous avons ajouter un #define pour le Chip Select de notre clavier (le bon connecteur HE10 sur lequel nous allons le connecter) afin que ce soit bien lui qui sera sélectionné lors du spi_select et spi_deselect. Le shield va envoyer un 1 en SPI pour indiquer au clavier qu'il est sur écoute et qu'il attend un envoie de la carte fille.&lt;br /&gt;
&lt;br /&gt;
Cette communication va nous permettre de bien mapper toutes nos touches.&lt;br /&gt;
&lt;br /&gt;
Nous avons décidé de faire un tableau en 3 dimensions afin de faciliter le mapping. Pourquoi 3 dimensions ? Nous avons une première dimension pour le numéro de ligne (0 à 7), pour le numéro de colonne (0 à 7) puis pour le numéro d'encodeur (0 à 2). Le bus d'entrée nous donnant un numéro de ligne entre 0 et 7, nous avons trouvé plus facile de procéder de cette manière. Voici un exemple.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:center; width: 48%;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
char tab_touches[8][8][3] = {&lt;br /&gt;
    {{'\0'/*AltGr*/, '\0', '\0'}, {'\0', '\0', '\0'}, {'-', ' ', '\0'}, {'\0'/*Fleche gauche*/, 'b', '\0'}, {'\0'/*Fleche droite*/, '\0', '\0'}, {'\0'/*Fleche bas*/, '\0', '\0'}, {'\0', '\0', '\0'}, {'\0', '!', '\0'}}, &lt;br /&gt;
    {{'\0', 'x', 'w'}, {'\0', 'c', '\0'/*CTRL Droit*/}, {'*', '\n', '\0'}, {'\0'/*Pause*/, 'v', '\0'}, {'/', ',', '\0'}, {'\0'/*Verr Num*/, ';', '\0'}, {'\0'/*Touch window droite*/, ':', '\0'}, {'\0'/*Shift droit*/, '*', '\0'}}, &lt;br /&gt;
    {{'\0'/*Arret*/, 'z', 'a'}, {'\0'/*Options*/, 'e', '\0'}, {'9', '\0', '\0'}, {'\0', 'r', '\0'}, {'8', 'u', '\0'}, {'7', 'i', '\0'}, {'\0', 'o', '\0'}, {'*', 'p', '\0'}}, &lt;br /&gt;
    {{'\0', 's', 'q'}, {'\0'/*Touche window gauche*/, 'd', '\0'}, {'3', '\0', '\0'}, {'\n', 'f', '\0'}, {'2', 'j', '\0'}, {'1', 'k', '\0'}, {'\0', 'l', '\0'}, {'\0', 'm', '\0'}}, &lt;br /&gt;
    {{'\0', '\0', '\0'}, {'\0', '\0', '\0'}, {'\0', '\0', '\0'}, {'\0', '\0', '\0'}, {'\0', '\0', '\0'}, {'\0', '\0', 'w'}, {'\0', '\0', '\0'}, {'\0', '\0', '\0'}}, &lt;br /&gt;
    {{'\0', '&amp;lt;', '\0'}, {'\0', '\0', '\0'}, {'.', '\0', '\0'}, {'\0', 'g', '\0'}, {'0', 'h', '\0'}, {'\0', '\0', '\0'}, {'\0', '\0', '\0'}, {'\0', '%', '\0'}}, &lt;br /&gt;
    {{'\0', '\0'/*MAJ*/, '\0'/*tab*/}, {'\0', '\0'/*F3*/, '\0'}, {'\0', 8, '\0'}, {'\0', 't', '\0'}, {'5', 'y', '\0'}, {'4', '$', '\0'}, {'\0', '\0'/*F7*/, '\0'}, {'\0'/*Shift gauche*/, '^', '\0'}}, &lt;br /&gt;
    {{'\0', '\0'/*F1*/, '\0'/*œ*/}, {'\0', '\0'/*F2*/, '\0'/*CTRL Gauche*/}, {'\0'/*Page haut*/, '\0'/*F9*/, '\0'}, {'\0'/*Debut*/, '(', '\0'}, {'\0'/*Insert*/, '-', '\0'}, {'\0'/*Supp*/, '=', '\0'}, {'t', '\n'/*F8*/, '\0'}, {'g', ')', '\0'}}&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Notre clavier ne supporte pas l'appuie de plusieurs touches en simultané à cause de la présence de décodeurs et d'encodeurs, le shift devient inutilisable, seulement maj est opérationnel. Afin de permettre l'utilisation de altgr, il fonctionnera comme le maj mais les deux ne pourront pas être activés en même temps.&lt;br /&gt;
&lt;br /&gt;
Nous avons tout d'abord mit des valeurs au hasard mais unique dans le tableau, puis nous avons identifié les touches pour une case dans le tableau, nous avons fait ce processus plusieurs fois afin de trouver toutes les cases des touches du clavier dans le tableau. Pour permettre l'utilisation du maj et du altgr, nous avons créer deux autres tableau comme ça, un chacun avec ses touches assignées. Lors de l'envoie, il faut vérifier dans quel mode nous nous trouvons pour envoyer le caractère dans le bon tableau (alt, maj ou classique).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:left; width: 48%; padding-left: 25px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
  while(1)&lt;br /&gt;
  {&lt;br /&gt;
    spi_select();&lt;br /&gt;
    uint8_t r=spi_exch(1);&lt;br /&gt;
    if (r != 1) printf(&amp;quot;%c&amp;quot;,r);&lt;br /&gt;
    spi_deselect();&lt;br /&gt;
    _delay_ms(20);&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:right; width: 48%; padding-right: 25px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void envoyer(){&lt;br /&gt;
    printf(&amp;quot;Clavier attente\n&amp;quot;);&lt;br /&gt;
      uint8_t message=spi_wait();&lt;br /&gt;
      printf(&amp;quot;Clavier reçu %d\n&amp;quot;,message);&lt;br /&gt;
      if (message == 1)&lt;br /&gt;
        spi_sendback(temp);&lt;br /&gt;
      printf(&amp;quot;Clavier retour préparé %d\n&amp;quot;,temp);&lt;br /&gt;
  &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
Ici le shield (à gauche) va envoyer un 1 en SPI pour dire au clavier qu'il est prêt à l'écouter, si il reçoit autre chose qu'un 1 (son propre envoie) alors il l'affiche. Le clavier (à droite) va envoyer son dernier caractère dont la touche a été pressée lorsqu'il reçoit ce fameux 1.&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
[[Fichier:B5_test_pingpong.mp4|vignette|alt=test clavier sur shield (sans démonstration de altgr et maj) |test clavier sur shield (sans démonstration de altgr et maj)|center|800px]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Implémentation dans l'ordonnanceur===&lt;br /&gt;
Pour pouvoir utiliser le clavier avec l'ordonnanceur, il suffit de faire de notre while(1) précédent, une tâche a part entière de notre ordonnanceur. Sur cet exemple on voit l'utilisation du alt et du maj.&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
[[Fichier:B5_test_final.mp4|vignette|alt=test clavier avec ordonnancement |test clavier avec ordonnancement|center|800px]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;/div&gt;</summary>
		<author><name>Adjadjaa</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-5&amp;diff=7364</id>
		<title>SE4Binome2024-5</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-5&amp;diff=7364"/>
		<updated>2025-01-26T16:11:01Z</updated>

		<summary type="html">&lt;p&gt;Adjadjaa : /* Explications générales sur la réalisation de la carte */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Introduction=&lt;br /&gt;
&lt;br /&gt;
Ce wiki documente le développement d’un pico-ordinateur modulaire. Ce dernier est constitué d’une carte principale, composée d’une carte Shield permettant la connexion des cartes filles, et d’une carte mère (initialement simulée par une Arduino Uno avant sa conception finale). Plusieurs cartes filles sont prévues, chacune remplissant une fonction spécifique : gestion du clavier, affichage, port série, réseau, mémoire de masse et son.&lt;br /&gt;
&lt;br /&gt;
Notre binôme est spécifiquement chargé du développement de la carte fille dédiée au clavier.&lt;br /&gt;
&lt;br /&gt;
Toutes les ressources nécessaires, incluant les codes sources et les schémas, sont disponibles sur le dépôt Git suivant :  [https://gitea.plil.fr/ktouron/se4-djadja-touron_pico.git Lien du Git]&lt;br /&gt;
&lt;br /&gt;
= Carte Shield =&lt;br /&gt;
[[Fichier:Carte Recto non soudé.jpg|vignette|left|thumb|350px|Recto de la carte avant soudage des composants]]&lt;br /&gt;
[[Fichier:Verso non solder.jpeg.jpg|vignette|thumb|right|300px|Verso de la carte avant soudage des composants]]&lt;br /&gt;
[[Fichier:Carde shield soudé.jpg|vignette|thumb|center|350px|Photo de la carte avec les composants soudés]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Test==&lt;br /&gt;
=== Allumage de LEDS sur Programmateur AVR ===&lt;br /&gt;
Avant de programmer directement sur le shield, nous avons allumé des LED pour tester la carte. Nous avons directement utilisé le code exemple fourni par l'IDE arduino en adaptant simplement les pins correspondant aux leds. [https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/PicoShield/Programmation/Blink Code du test]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Vid_test_carte_mp4.mp4|vignette|thumb|center|700px|Vidéo de Test des leds]]&lt;br /&gt;
&lt;br /&gt;
=== Lecture de la carte SD ===&lt;br /&gt;
Avant de programmer directement sur le shield, nous avons tester si la carte SD était bien détectée et lue. On a utilisé le code test présent dans l'IDE arduino en adaptant le port utilisé.[https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/PicoShield/Programmation/CardInfo Code du test]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Resultat SD.jpg|vignette|thumb|center|700px|Carte SD bien détéctée]]&lt;br /&gt;
&lt;br /&gt;
=== Connecteurs IDC HE10 ===&lt;br /&gt;
Afin de tester nos connecteur HE10, nous avons utilisé un afficher 7 segments (Sparkfun 7 segments display). Pour pouvoir vérifier leurs fonctionnements nous avons branché l'afficheur sur chaque connecteur tour à tour. Le programme implanté est un simple connecteur à afficher sur l'afficheur. Voici une vidéo du compteur fonctionnant sur un des 5 connecteurs HE10. ([https://learn.sparkfun.com/tutorials/using-the-serial-7-segment-display/all Code ici (section : Example 2 SPI)])&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Se4-5-7segments.mp4|vignette|alt=se4-5-7segments|Test connecteur HE10 avec afficheur 7 segments.|center]]&lt;br /&gt;
== Ordonnanceur ==&lt;br /&gt;
Pour les interruptions de notre ordonnanceur nous avons utilisé la procédure d'initialisation du minuteur avec le Timer1 disponible dans les cours de Mr.Redon en renseignant une période de 20ms. Nous l'avons disposé dans le fichier minuteur.c car nous n'allons plus le modifier pour le reste du projet. Dans un autre fichier process.c (avec process.h), nous allons y mettre nos structures pour les process et leurs états puis une union pour le temps qui le caractérise ainsi que toutes les fonctions associés.&lt;br /&gt;
&lt;br /&gt;
[https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/Ordonnanceur Lien du répertoire]&lt;br /&gt;
&lt;br /&gt;
=== Processus ===&lt;br /&gt;
==== Structure ====&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:right; width: 48%; padding-left: 10px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
    uint16_t adresseDepart;  //adresse de la fonction de départ &lt;br /&gt;
    uint16_t adressePile;       //adresse de la pile d'exécution&lt;br /&gt;
    Etat etat;        &lt;br /&gt;
} Process;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Notre structure caractérisant un processus est définie par les trois champs ci-contre.&lt;br /&gt;
&lt;br /&gt;
Une adresse de départ correspondant à la fonction du processus associé, l'adresse où se situe le processus dans la pile puis l'état de la tâche. Nous avons décidé de faire une structure à part entière compte tenu des multitudes d'états que nous pourrons ajouter pendant la progression du projet.&lt;br /&gt;
&lt;br /&gt;
==== Etat d'un processus ====&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:right; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
typedef union {&lt;br /&gt;
  int sleepingtime;       &lt;br /&gt;
} Time;&lt;br /&gt;
&lt;br /&gt;
typedef struct {&lt;br /&gt;
  int id;&lt;br /&gt;
  Time time;&lt;br /&gt;
} Etat ;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
L'état d'un processus est alors une structure à deux champs (pour l'instant), l'id doit correspondre à un '#DEFINE' pour avoir un sens tandis que nous avons choisi de faire une union pour le temps qui caractérise notre état afin qu'il puisse avoir un nom et type de variable cohérent avec son état.(Ici seulement sleepingtime car seul l'état endormi existe pour le moment)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
  {| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
  |+ Tableau des états&lt;br /&gt;
  |-&lt;br /&gt;
  ! Etat !! ACTIVE !! SLEEPY !! ... !! ...&lt;br /&gt;
  |-&lt;br /&gt;
  | Id || 0 || 1 || ... || ...&lt;br /&gt;
  |}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Procédures principales ====&lt;br /&gt;
&lt;br /&gt;
=== ISR ===&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:right; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
ISR(TIMER1_COMPA_vect, ISR_NAKED)    // Procédure d'interruption&lt;br /&gt;
{&lt;br /&gt;
  TCNT1=0;//reset timer&lt;br /&gt;
  /* Sauvegarde du contexte de la tâche interrompue */&lt;br /&gt;
  portSAVE_REGISTERS();&lt;br /&gt;
   table_process[indice_tache].adressePile = SP;&lt;br /&gt;
  /* Appel à l'ordonnanceur */&lt;br /&gt;
  selectProcess();&lt;br /&gt;
  /* Récupération du contexte de la tâche ré-activée */&lt;br /&gt;
  SP = table_process[indice_tache].adressePile;&lt;br /&gt;
  portRESTORE_REGISTERS();&lt;br /&gt;
  &lt;br /&gt;
  asm volatile ( &amp;quot;reti&amp;quot; );&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
L'ISR est ce qu'il va être executer lors des interruptions toutes les 20 millisecondes. Cela consiste à sauvegarder tous les registres de la tâche qui était en cours avant l'appel de l'ISR pour ensuite passer à la tâche suivante valide (c'est à dire active) sans oublier de charger les registres de la nouvelle tâche.&lt;br /&gt;
&lt;br /&gt;
Nous devons également, à chaque fois avant de changer de tâche, enregistrer le pointeur de pile dans le processus afin de pouvoir revenir là ou elle en est la prochaine fois qu'elle sera appelée. Respectivement, une fois la nouvelle tâche choisie, le pointeur de pile doit prendre l'adresse de là ou en était la tâche avant qu'elle soit interrompue.&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Séléction de processus ====&lt;br /&gt;
Lors de la séléction de processus, nous devons parcourir tous les processus jusqu'au moment où nous en trouvons un actif. Ainsi, il deviendra la tâche que nous traiterons lors du prochain intervalle de 20 ms. A ce stade, à chaque fois que la procédure selectProcess est appelée, nous devons réduire le temps de repos de chaque process endormi de 20 ms. D'autres conditions pourrons être ajoutée si ajout d'état a lieu. (voir l'ajout de selectProcess dans l'ISR)&lt;br /&gt;
&lt;br /&gt;
=== Test ===&lt;br /&gt;
==== Clignotement de deux LED à fréquences indivisibles entre elles ====&lt;br /&gt;
Afin de vérifier la réussite de notre ordonnanceur à fonctionnement tourniquet, nous avons programmer deux simples tâches changeant l'état d'une LED. Une à une fréquence 200ms et l'autre 300ms (avec un _delay_ms).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:left; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void tache1(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTC ^= (1 &amp;lt;&amp;lt; PC0);&lt;br /&gt;
    _delay_ms(300);}}&lt;br /&gt;
void tache2(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTD ^= (1 &amp;lt;&amp;lt; PD7);&lt;br /&gt;
    _delay_ms(200);}}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
[[Fichier:B5_test1.mp4|vignette|alt=test des frequences imprevisibles|test des frequences imprevisibles]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Clignotement grâce à l'état endormi ====&lt;br /&gt;
Nous ajoutons l'état endormi afin que nos tâches ne mettent pas en pause l'ordonnanceur avec un _delay_ms. Pour cela, nous incorporons une fonction makeSleep qui permet de mettre la tâche qui l'appelle dans cet état.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:left; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void makeSleep(int t){&lt;br /&gt;
  table_process[indice_tache].etat.id = SLEEPY;&lt;br /&gt;
  table_process[indice_tache].etat.time.sleepingtime = t;&lt;br /&gt;
  TIMER1_COMPA_vect();}&lt;br /&gt;
void tache1(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTC ^= (1 &amp;lt;&amp;lt; PC0);&lt;br /&gt;
    _delay_ms(300);}}&lt;br /&gt;
void tache3(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTC ^= (1 &amp;lt;&amp;lt; PC3);&lt;br /&gt;
    //_delay_ms(1000);&lt;br /&gt;
    makeSleep(1000);}}&lt;br /&gt;
void tache2(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTD ^= (1 &amp;lt;&amp;lt; PD7);&lt;br /&gt;
    //_delay_ms(1000);&lt;br /&gt;
    makeSleep(700);}}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
[[Fichier:B5_test2.mp4|vignette|alt=test des frequences imprevisibles|test des frequences imprevisibles]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
A noter que la première tâche executée ne doit pas être endormie.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Carte Fille Matrice de touches =&lt;br /&gt;
==Explications générales sur la réalisation de la carte==&lt;br /&gt;
&lt;br /&gt;
Pour concevoir la carte fille dédiée au clavier, nous avons réutilisé un ancien clavier DELL équipé d’une matrice déjà fonctionnelle. L’idée consiste à connecter les sorties de cette matrice directement à notre carte fille à l’aide d’un connecteur adapté.&lt;br /&gt;
&lt;br /&gt;
Cependant, un défi se pose : la matrice du clavier comprend un total de 26 sorties (sans compter les LED et autres signaux). Cela dépasse largement les capacités en nombre de broches d’un ATmega328P.&lt;br /&gt;
&lt;br /&gt;
Pour remédier à ce problème, nous avons mis en place une solution d’encodage. Nous avons utilisé un décodeur (3 vers 8) pour gérer les lignes et trois encodeurs (8 vers 3) pour gérer les colonnes. Les encodeurs sont montés en cascade pour réduire significativement le nombre de broches nécessaires. Cette solution permet de maximiser les ressources du microcontrôleur tout en gérant efficacement les signaux de la matrice.&lt;br /&gt;
&lt;br /&gt;
Nous avons opté pour le décodeur 74HC138D (qui va envoyer un 0 parmi des 1) et trois encodeurs CD4532BM (qui cherche le premier 1 parmi des 0). On sent quand même les problèmes venir petit à petit.&lt;br /&gt;
&lt;br /&gt;
Par ailleurs, étant donné que nous utilisons directement le clavier Dell, il a été nécessaire de concevoir la carte avec des dimensions strictement identiques à celles de la carte d’origine, notamment en ce qui concerne sa largeur. Nous avons également dû ajouter des trous aux emplacements précis pour permettre de visser correctement la carte. Nous avons également dû créer l'empreinte KiCad du connecteur de la matrice, car celle-ci n’était pas disponible dans les bibliothèques existantes.[https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/CF_Clavier/Footprint_KeyboardDell_DJADJA Empreinte du connecteur matrice]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
[[Fichier:Clavier dell.png||thumb|right|800px|Clavier DELL]]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Connecteur de base clavier dell.png||thumb|left|500px|Carte du clavier DELL]]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Matrice clavier dell.png||thumb|right|800px|Matrice du clavier DELL]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Détails des composants ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;ATmega328P&amp;lt;/u&amp;gt;&lt;br /&gt;
* Micro-contrôleur&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;74HC138D&amp;lt;/u&amp;gt;&lt;br /&gt;
* Décodeur : envoie un 0 parmi des 1.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;CD4532BM&amp;lt;/u&amp;gt;&lt;br /&gt;
* Encodeur : Nous avons étudié la datasheet et comment la mise en cascade fonctionne.&lt;br /&gt;
[[Fichier:Cascade.png|vignette|alt=Mise en cascade des encodeurs.|Mise en cascade des encodeurs.]]&lt;br /&gt;
On voit qu'un encodeur possède un bus de sortie de 5 bits. GS -&amp;gt; à l'état haut quand le composant reçoit un 1, 0 sinon. E0 -&amp;gt; à l'état haut quand il reçoit seulement des 0, 1 sinon. Puis Q2, Q1 ,Q0 la représentation binaire de l'entrée donnée.&lt;br /&gt;
&lt;br /&gt;
Afin de les mettre en cascade, il faut relié le E0 d'un premier encodeur au Ei de l'autre. Ensuite, nous allons faire un &amp;quot;OU&amp;quot; entre les GS afin de savoir si un des encodeurs reçoit un 1, puis grâce aux GS des deux premiers encodeurs nous sauront quelle encodeur à reçu le 1 (si les deux sont &amp;amp; 0 alors c'est le troisième). De même, faire une porte &amp;quot;OU&amp;quot; sur Q2, Q1, Q0 afin de réduire le nombre d'entrées/sorties nécessaires.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&amp;lt;u&amp;gt;74LS32&amp;lt;/u&amp;gt;&lt;br /&gt;
* Porte logique Or pour la mise en cascade des encodeurs.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Connecteur HE10&amp;lt;/u&amp;gt;&lt;br /&gt;
* Connecteur pour la liaison PicoShield-CarteFille&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Connecteur de la matrice&amp;lt;/u&amp;gt;&lt;br /&gt;
* Simplement une empreinte que l'on a créé [https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/CF_Clavier/Footprint_KeyboardDell_DJADJA Lien vers la bibliothèque présent sur le git]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;AVR-ISP-6&amp;lt;/u&amp;gt;&lt;br /&gt;
* Programmateur AVR&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;LED_SMD&amp;lt;/u&amp;gt;&lt;br /&gt;
* 3 LEDs&lt;br /&gt;
&lt;br /&gt;
== Hardware ==&lt;br /&gt;
===Kicad===&lt;br /&gt;
[[Fichier:Schematique carte fille clavier dell.png|center|1000px|vignette|Schématique de la carte Fille]]&lt;br /&gt;
&lt;br /&gt;
Pour réaliser la carte fille, nous avions dans un premier temps conçu une carte avec une matrice de touches directement implenter sur celle-ci, mais jugeant que cela était trop simple nous avons été redirigé vers l'utilisation d'une matrice déjà réalisé. Ainsi nous avons avons reutiliser celle d'un vieux clavier dell en créant les empreintes à la bonne taille pour se connecter sur la matrice&lt;br /&gt;
 &lt;br /&gt;
[[Fichier:Pcb recto carte fille clavier dell.png|left|480px|vignette|Avant du PCB]][[Fichier:Pcb verso carte fille clavier dell.png|right|480px|vignette|Arrière du PCB]]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Capture d’écran 2024-11-20 à 12.09.07.png|left|600px|vignette|PCB vue 3D avant]][[Fichier:Capture d’écran 2024-11-20 à 12.09.33.png|right|480px|vignette|PCB vue 3D arrière]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Carte après soudure des composants====&lt;br /&gt;
&lt;br /&gt;
===Différents Problèmes rencontrés===&lt;br /&gt;
Avant même la réception de la carte, alors que nous commençons a essayé d'écrire un premier programme, nous nous rendions compte qu'envoyer un 0 parmi des 1 et de rechercher un 1 parmi des 0 ne fonctionnera pas (logique). Nous avons alors pris la décision de changer le décodeur car il était pour nous plus simple de changer un composant que les trois encodeurs. Nous avons opté pour lui de la même famille, le 74HTC238D.&lt;br /&gt;
&lt;br /&gt;
Dès la réception de la carte, nous avons effectué un premier test avec une simple programmation de LED. Nous nous sommes rapidement aperçus que nous avions configuré deux noms d'étiquettes de reset distinctes sur KiCad : une pour l'AVR (RST) et une pour le connecteur HE-10 (RESET). Cependant, seul le reset du connecteur HE-10 était correctement relié au microcontrôleur. Pour résoudre ce problème, nous avons simplement connecté les deux broches de reset à l'aide d'un fil.&lt;br /&gt;
&lt;br /&gt;
Lors de l'examen initial de notre carte, nous avons également constaté une erreur que nous avions commise. En effet, comme nous avions initialement conçu une matrice de touches sans encodeurs ni décodeurs, il n'était donc pas nécessaire d'intégrer des résistances de pull-up ou de pull-down. Nous avons alors juste rajouter ces composants, or il en résulte que lorsqu'une touche sera pressée, un 1 sera bien envoyé mais pas parmi des 0, parmi des états indéterminé. En général, les états indéterminés, on aime pas trop, surtout quand cela empêche ta carte de pouvoir fonctionner comme voulu. Il a donc été nécessaire d'ajouter des résistances de pull-down sur chaque colonne de notre clavier. Afin de simplifier cette modification, nous avons utilisé des résistances CMS que nous avons positionnées comme des dominos (verticalement), ce qui nous a permis de faire passer un fil de masse directement au-dessus des résistances.&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Resistance pull Up domino.jpg|center|500px|vignette|Résistances de Pull-down sur les colonnes]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Une fois tous ces problèmes de base résolus, nous avons enfin pu nous attaquer à la programmation du clavier. Pour vérifier que toutes les touches étaient correctement détectées, nous avons réalisé un petit programme de test ([https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/CF_Clavier/prog/test.c Code du test]). Ce programme nous a permis d’associer chaque LED à un décodeur différent via la broche GS des décodeurs. Ainsi, nous avons pu identifier quelles touches ne répondaient pas. Premièrement, beaucoup de touches ne répondaient pas, moins d'une dizaine. Nous avons alors fait de multiples tests au multimètre sur notre carte mais aussi sur une autre matrice de touches similaire. Une des hypothèses fut qu'il fallait bien étamer les pistes pour permettre la conduction entre la carte et la matrice. Nous avons alors rajouter de l'étain, puis + de touches commençaient à fonctionner. Il fallait alors un nouveau programme de test pour détecter quelles lignes ou colonnes n'étaient pas bien étamés afin de permettre une conduction ([https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/CF_Clavier/prog/detect.c Code de détection]). Il suffisait ainsi de rajouter de l'étain sur les colonnes et les lignes qui ne répondaient pas. Enfin, toutes les touches sont détectées lors de d'une pression !&lt;br /&gt;
&lt;br /&gt;
==Programmation de la carte==&lt;br /&gt;
===Programme de test===&lt;br /&gt;
&lt;br /&gt;
([https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/CF_Clavier/prog/test.c Code du test])&lt;br /&gt;
&lt;br /&gt;
Afin de tester chaque touche de notre matrice, nous avons décidé de faire le programme le plus simple possible en utilisant les broches GS de nos encodeurs. Il n'y a pas d'histoire de ligne ou de colonnes ici, si une touche est pressée alors le GS de l'encodeur ou sa colonne est reliée passera à l'état haut. Une manière très simple de savoir si une touche est utilisable et si nos trois encodeurs sont opérationnels également. Nous avons trois leds pour trois encodeurs, pour chaque encodeur, s'allumera une led spécifique si il reçoit un 1 parmi des 0.&lt;br /&gt;
&lt;br /&gt;
Afin de mettre en place ce système, il nous faut un programme capable de balayer toutes les lignes de notre matrice via un décodeur.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:left; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
int tab_outputs[8][3] = {&lt;br /&gt;
    {0, 0, 0},&lt;br /&gt;
    {1, 0, 0},&lt;br /&gt;
    {0, 1, 0},&lt;br /&gt;
    {1, 1, 0},&lt;br /&gt;
    {0, 0, 1},&lt;br /&gt;
    {1, 0, 1},&lt;br /&gt;
    {0, 1, 1},&lt;br /&gt;
    {1, 1, 1},&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void maj_output(int lig){&lt;br /&gt;
    for (int i = 0 ; i &amp;lt; 3 ; i++){&lt;br /&gt;
        if (tab_outputs[lig][i] == 0){&lt;br /&gt;
            PORTC &amp;amp;= ~(1 &amp;lt;&amp;lt; i);&lt;br /&gt;
        }&lt;br /&gt;
        else if (tab_outputs[lig][i] == 1){&lt;br /&gt;
            PORTC |= (1 &amp;lt;&amp;lt; i);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Fichier:B5_test_matrice.mp4|vignette|alt=test d'une touche pressée |test d'une touche pressée|right|800px]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
Ici, grâce à l'initialisation d'un tableau de la représentation en binaire des chiffres 0 à 7, il suffit de faire une procédure qui prend en paramètre le numéro de ligne souhaitée puis de vérifier dans le tableau quelle sortie mettre à 0 et 1. Nous avions remarqué que mettre les sorties pour les décodeurs sur le même port côte à côte facilite la programmation.&lt;br /&gt;
&lt;br /&gt;
===Programme de détection===&lt;br /&gt;
&lt;br /&gt;
([https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/CF_Clavier/prog/detect.c Code du test])&lt;br /&gt;
&lt;br /&gt;
Dans le projet, nous avons eu des problèmes de lignes et colonnes qui n'était pas conduit entre notre carte et la matrice. Pour les identifier, nous avons mis en place un programme de détection qui lors de la pression d'une touche, va afficher grâce aux leds, de quel encodeur sa colonne régit puis quelle ligne et quelle colonne est activée. Ce programme permet ainsi de diagnostiquer rapidement les problèmes de conduction entre la carte et la matrice en identifiant précisément les correspondances défectueuses. &lt;br /&gt;
&lt;br /&gt;
Pour cela, nous avons imaginer deux fonctions show_ligne et show_colonne, permettant d'afficher sur nos trois leds la ligne et la colonne. Si les leds affichent : double clignotements de la led du milieu  (allumée, éteint, allumé) puis (éteint, allumée, allumée) alors la ligne L6 (voir KiCad) et la 4e colonne du deuxième encodeur sont activées.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:left; width: 48%; padding-left: 25px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void show_ligne(int i){&lt;br /&gt;
    turn_off_leds();&lt;br /&gt;
    for (int bit = 0; bit &amp;lt; 3; bit++){&lt;br /&gt;
        if (tab_outputs[i][bit] == 1) {&lt;br /&gt;
            PORTC |= (1 &amp;lt;&amp;lt; (bit+LED1));&lt;br /&gt;
        }&lt;br /&gt;
        else &lt;br /&gt;
            PORTC &amp;amp;= ~(1 &amp;lt;&amp;lt; (bit+LED1));&lt;br /&gt;
        }&lt;br /&gt;
    _delay_ms(SHOW_TIME);&lt;br /&gt;
    turn_off_leds();&lt;br /&gt;
}}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:right; width: 48%; padding-right: 25px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void show_colonne(){&lt;br /&gt;
    turn_off_leds();&lt;br /&gt;
    for (int i = Q0; i &amp;lt; Q2 + 1 ; i++){&lt;br /&gt;
        if (((inputs &amp;gt;&amp;gt; i) &amp;amp; 1) == 1) {&lt;br /&gt;
            PORTC |= (1 &amp;lt;&amp;lt; (i+LED1));&lt;br /&gt;
        }&lt;br /&gt;
        else &lt;br /&gt;
            PORTC &amp;amp;= ~(1 &amp;lt;&amp;lt; (i+LED1));&lt;br /&gt;
    }&lt;br /&gt;
    _delay_ms(SHOW_TIME);&lt;br /&gt;
    turn_off_leds();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
Les deux fonctions se ressemblent beaucoup, la différence étant que show_ligne va prendre un paramètre un entier selon la ligne que nous voulons afficher alors que colonne va directement regarde dans le bus d'entrées la représentation binaire de la colonne activée. A noter que le fait que les LEDs et Q2, Q1, Q0 sont successivement placés sur le même port rend la programmation plus simple à réaliser.&lt;br /&gt;
&lt;br /&gt;
A noter la présence d'un 'uint8_t inputs;' où l'on va assigner PIND à chaque début d'une boucle, en effet pendant l'afficher l'utilisateur ne reste pas forcément la touche enfoncées ce qui changera les valeurs du bus d'entrée. Il est alors important de sauvegarder l'état de ce bus avant de l'afficher.&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
[[Fichier:B5_test_detect.mp4|vignette|alt=test de la détection d'une touche |test de la détection d'une touche|center|800px]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Ping pong===&lt;br /&gt;
A l'aide des ressources envoyées par Mr.Redon, nous avons de quoi communiquer entre le shield et notre carte fille. Pour cela, nous avons du modifié un tout petit peu les programmes. En effet, nous avons ajouter un #define pour le Chip Select de notre clavier (le bon connecteur HE10 sur lequel nous allons le connecter) afin que ce soit bien lui qui sera sélectionné lors du spi_select et spi_deselect. Le shield va envoyer un 1 en SPI pour indiquer au clavier qu'il est sur écoute et qu'il attend un envoie de la carte fille.&lt;br /&gt;
&lt;br /&gt;
Cette communication va nous permettre de bien mapper toutes nos touches.&lt;br /&gt;
&lt;br /&gt;
Nous avons décidé de faire un tableau en 3 dimensions afin de faciliter le mapping. Pourquoi 3 dimensions ? Nous avons une première dimension pour le numéro de ligne (0 à 7), pour le numéro de colonne (0 à 7) puis pour le numéro d'encodeur (0 à 2). Le bus d'entrée nous donnant un numéro de ligne entre 0 et 7, nous avons trouvé plus facile de procéder de cette manière. Voici un exemple.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:center; width: 48%;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
char tab_touches[8][8][3] = {&lt;br /&gt;
    {{'\0'/*AltGr*/, '\0', '\0'}, {'\0', '\0', '\0'}, {'-', ' ', '\0'}, {'\0'/*Fleche gauche*/, 'b', '\0'}, {'\0'/*Fleche droite*/, '\0', '\0'}, {'\0'/*Fleche bas*/, '\0', '\0'}, {'\0', '\0', '\0'}, {'\0', '!', '\0'}}, &lt;br /&gt;
    {{'\0', 'x', 'w'}, {'\0', 'c', '\0'/*CTRL Droit*/}, {'*', '\n', '\0'}, {'\0'/*Pause*/, 'v', '\0'}, {'/', ',', '\0'}, {'\0'/*Verr Num*/, ';', '\0'}, {'\0'/*Touch window droite*/, ':', '\0'}, {'\0'/*Shift droit*/, '*', '\0'}}, &lt;br /&gt;
    {{'\0'/*Arret*/, 'z', 'a'}, {'\0'/*Options*/, 'e', '\0'}, {'9', '\0', '\0'}, {'\0', 'r', '\0'}, {'8', 'u', '\0'}, {'7', 'i', '\0'}, {'\0', 'o', '\0'}, {'*', 'p', '\0'}}, &lt;br /&gt;
    {{'\0', 's', 'q'}, {'\0'/*Touche window gauche*/, 'd', '\0'}, {'3', '\0', '\0'}, {'\n', 'f', '\0'}, {'2', 'j', '\0'}, {'1', 'k', '\0'}, {'\0', 'l', '\0'}, {'\0', 'm', '\0'}}, &lt;br /&gt;
    {{'\0', '\0', '\0'}, {'\0', '\0', '\0'}, {'\0', '\0', '\0'}, {'\0', '\0', '\0'}, {'\0', '\0', '\0'}, {'\0', '\0', 'w'}, {'\0', '\0', '\0'}, {'\0', '\0', '\0'}}, &lt;br /&gt;
    {{'\0', '&amp;lt;', '\0'}, {'\0', '\0', '\0'}, {'.', '\0', '\0'}, {'\0', 'g', '\0'}, {'0', 'h', '\0'}, {'\0', '\0', '\0'}, {'\0', '\0', '\0'}, {'\0', '%', '\0'}}, &lt;br /&gt;
    {{'\0', '\0'/*MAJ*/, '\0'/*tab*/}, {'\0', '\0'/*F3*/, '\0'}, {'\0', 8, '\0'}, {'\0', 't', '\0'}, {'5', 'y', '\0'}, {'4', '$', '\0'}, {'\0', '\0'/*F7*/, '\0'}, {'\0'/*Shift gauche*/, '^', '\0'}}, &lt;br /&gt;
    {{'\0', '\0'/*F1*/, '\0'/*œ*/}, {'\0', '\0'/*F2*/, '\0'/*CTRL Gauche*/}, {'\0'/*Page haut*/, '\0'/*F9*/, '\0'}, {'\0'/*Debut*/, '(', '\0'}, {'\0'/*Insert*/, '-', '\0'}, {'\0'/*Supp*/, '=', '\0'}, {'t', '\n'/*F8*/, '\0'}, {'g', ')', '\0'}}&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Notre clavier ne supporte pas l'appuie de plusieurs touches en simultané à cause de la présence de décodeurs et d'encodeurs, le shift devient inutilisable, seulement maj est opérationnel. Afin de permettre l'utilisation de altgr, il fonctionnera comme le maj mais les deux ne pourront pas être activés en même temps.&lt;br /&gt;
&lt;br /&gt;
Nous avons tout d'abord mit des valeurs au hasard mais unique dans le tableau, puis nous avons identifié les touches pour une case dans le tableau, nous avons fait ce processus plusieurs fois afin de trouver toutes les cases des touches du clavier dans le tableau. Pour permettre l'utilisation du maj et du altgr, nous avons créer deux autres tableau comme ça, un chacun avec ses touches assignées. Lors de l'envoie, il faut vérifier dans quel mode nous nous trouvons pour envoyer le caractère dans le bon tableau (alt, maj ou classique).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:left; width: 48%; padding-left: 25px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
  while(1)&lt;br /&gt;
  {&lt;br /&gt;
    spi_select();&lt;br /&gt;
    uint8_t r=spi_exch(1);&lt;br /&gt;
    if (r != 1) printf(&amp;quot;%c&amp;quot;,r);&lt;br /&gt;
    spi_deselect();&lt;br /&gt;
    _delay_ms(20);&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:right; width: 48%; padding-right: 25px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void envoyer(){&lt;br /&gt;
    printf(&amp;quot;Clavier attente\n&amp;quot;);&lt;br /&gt;
      uint8_t message=spi_wait();&lt;br /&gt;
      printf(&amp;quot;Clavier reçu %d\n&amp;quot;,message);&lt;br /&gt;
      if (message == 1)&lt;br /&gt;
        spi_sendback(temp);&lt;br /&gt;
      printf(&amp;quot;Clavier retour préparé %d\n&amp;quot;,temp);&lt;br /&gt;
  &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
Ici le shield (à gauche) va envoyer un 1 en SPI pour dire au clavier qu'il est prêt à l'écouter, si il reçoit autre chose qu'un 1 (son propre envoie) alors il l'affiche. Le clavier (à droite) va envoyer son dernier caractère dont la touche a été pressée lorsqu'il reçoit ce fameux 1.&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
[[Fichier:B5_test_pingpong.mp4|vignette|alt=test clavier sur shield (sans démonstration de altgr et maj) |test clavier sur shield (sans démonstration de altgr et maj)|center|800px]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Implémentation dans l'ordonnanceur===&lt;br /&gt;
Pour pouvoir utiliser le clavier avec l'ordonnanceur, il suffit de faire de notre while(1) précédent, une tâche a part entière de notre ordonnanceur. Sur cet exemple on voit l'utilisation du alt et du maj.&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
[[Fichier:B5_test_final.mp4|vignette|alt=test clavier avec ordonnancement |test clavier avec ordonnancement|center|800px]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;/div&gt;</summary>
		<author><name>Adjadjaa</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-5&amp;diff=7360</id>
		<title>SE4Binome2024-5</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-5&amp;diff=7360"/>
		<updated>2025-01-26T16:04:22Z</updated>

		<summary type="html">&lt;p&gt;Adjadjaa : /* Différents Problèmes rencontrés */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Introduction=&lt;br /&gt;
&lt;br /&gt;
Ce wiki documente le développement d’un pico-ordinateur modulaire. Ce dernier est constitué d’une carte principale, composée d’une carte Shield permettant la connexion des cartes filles, et d’une carte mère (initialement simulée par une Arduino Uno avant sa conception finale). Plusieurs cartes filles sont prévues, chacune remplissant une fonction spécifique : gestion du clavier, affichage, port série, réseau, mémoire de masse et son.&lt;br /&gt;
&lt;br /&gt;
Notre binôme est spécifiquement chargé du développement de la carte fille dédiée au clavier.&lt;br /&gt;
&lt;br /&gt;
Toutes les ressources nécessaires, incluant les codes sources et les schémas, sont disponibles sur le dépôt Git suivant :  [https://gitea.plil.fr/ktouron/se4-djadja-touron_pico.git Lien du Git]&lt;br /&gt;
&lt;br /&gt;
= Carte Shield =&lt;br /&gt;
[[Fichier:Carte Recto non soudé.jpg|vignette|left|thumb|350px|Recto de la carte avant soudage des composants]]&lt;br /&gt;
[[Fichier:Verso non solder.jpeg.jpg|vignette|thumb|right|300px|Verso de la carte avant soudage des composants]]&lt;br /&gt;
[[Fichier:Carde shield soudé.jpg|vignette|thumb|center|350px|Photo de la carte avec les composants soudés]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Test==&lt;br /&gt;
=== Allumage de LEDS sur Programmateur AVR ===&lt;br /&gt;
Avant de programmer directement sur le shield, nous avons allumé des LED pour tester la carte. Nous avons directement utilisé le code exemple fourni par l'IDE arduino en adaptant simplement les pins correspondant aux leds. [https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/PicoShield/Programmation/Blink Code du test]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Vid_test_carte_mp4.mp4|vignette|thumb|center|700px|Vidéo de Test des leds]]&lt;br /&gt;
&lt;br /&gt;
=== Lecture de la carte SD ===&lt;br /&gt;
Avant de programmer directement sur le shield, nous avons tester si la carte SD était bien détectée et lue. On a utilisé le code test présent dans l'IDE arduino en adaptant le port utilisé.[https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/PicoShield/Programmation/CardInfo Code du test]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Resultat SD.jpg|vignette|thumb|center|700px|Carte SD bien détéctée]]&lt;br /&gt;
&lt;br /&gt;
=== Connecteurs IDC HE10 ===&lt;br /&gt;
Afin de tester nos connecteur HE10, nous avons utilisé un afficher 7 segments (Sparkfun 7 segments display). Pour pouvoir vérifier leurs fonctionnements nous avons branché l'afficheur sur chaque connecteur tour à tour. Le programme implanté est un simple connecteur à afficher sur l'afficheur. Voici une vidéo du compteur fonctionnant sur un des 5 connecteurs HE10. ([https://learn.sparkfun.com/tutorials/using-the-serial-7-segment-display/all Code ici (section : Example 2 SPI)])&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Se4-5-7segments.mp4|vignette|alt=se4-5-7segments|Test connecteur HE10 avec afficheur 7 segments.|center]]&lt;br /&gt;
== Ordonnanceur ==&lt;br /&gt;
Pour les interruptions de notre ordonnanceur nous avons utilisé la procédure d'initialisation du minuteur avec le Timer1 disponible dans les cours de Mr.Redon en renseignant une période de 20ms. Nous l'avons disposé dans le fichier minuteur.c car nous n'allons plus le modifier pour le reste du projet. Dans un autre fichier process.c (avec process.h), nous allons y mettre nos structures pour les process et leurs états puis une union pour le temps qui le caractérise ainsi que toutes les fonctions associés.&lt;br /&gt;
&lt;br /&gt;
[https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/Ordonnanceur Lien du répertoire]&lt;br /&gt;
&lt;br /&gt;
=== Processus ===&lt;br /&gt;
==== Structure ====&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:right; width: 48%; padding-left: 10px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
    uint16_t adresseDepart;  //adresse de la fonction de départ &lt;br /&gt;
    uint16_t adressePile;       //adresse de la pile d'exécution&lt;br /&gt;
    Etat etat;        &lt;br /&gt;
} Process;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Notre structure caractérisant un processus est définie par les trois champs ci-contre.&lt;br /&gt;
&lt;br /&gt;
Une adresse de départ correspondant à la fonction du processus associé, l'adresse où se situe le processus dans la pile puis l'état de la tâche. Nous avons décidé de faire une structure à part entière compte tenu des multitudes d'états que nous pourrons ajouter pendant la progression du projet.&lt;br /&gt;
&lt;br /&gt;
==== Etat d'un processus ====&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:right; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
typedef union {&lt;br /&gt;
  int sleepingtime;       &lt;br /&gt;
} Time;&lt;br /&gt;
&lt;br /&gt;
typedef struct {&lt;br /&gt;
  int id;&lt;br /&gt;
  Time time;&lt;br /&gt;
} Etat ;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
L'état d'un processus est alors une structure à deux champs (pour l'instant), l'id doit correspondre à un '#DEFINE' pour avoir un sens tandis que nous avons choisi de faire une union pour le temps qui caractérise notre état afin qu'il puisse avoir un nom et type de variable cohérent avec son état.(Ici seulement sleepingtime car seul l'état endormi existe pour le moment)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
  {| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
  |+ Tableau des états&lt;br /&gt;
  |-&lt;br /&gt;
  ! Etat !! ACTIVE !! SLEEPY !! ... !! ...&lt;br /&gt;
  |-&lt;br /&gt;
  | Id || 0 || 1 || ... || ...&lt;br /&gt;
  |}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Procédures principales ====&lt;br /&gt;
&lt;br /&gt;
=== ISR ===&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:right; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
ISR(TIMER1_COMPA_vect, ISR_NAKED)    // Procédure d'interruption&lt;br /&gt;
{&lt;br /&gt;
  TCNT1=0;//reset timer&lt;br /&gt;
  /* Sauvegarde du contexte de la tâche interrompue */&lt;br /&gt;
  portSAVE_REGISTERS();&lt;br /&gt;
   table_process[indice_tache].adressePile = SP;&lt;br /&gt;
  /* Appel à l'ordonnanceur */&lt;br /&gt;
  selectProcess();&lt;br /&gt;
  /* Récupération du contexte de la tâche ré-activée */&lt;br /&gt;
  SP = table_process[indice_tache].adressePile;&lt;br /&gt;
  portRESTORE_REGISTERS();&lt;br /&gt;
  &lt;br /&gt;
  asm volatile ( &amp;quot;reti&amp;quot; );&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
L'ISR est ce qu'il va être executer lors des interruptions toutes les 20 millisecondes. Cela consiste à sauvegarder tous les registres de la tâche qui était en cours avant l'appel de l'ISR pour ensuite passer à la tâche suivante valide (c'est à dire active) sans oublier de charger les registres de la nouvelle tâche.&lt;br /&gt;
&lt;br /&gt;
Nous devons également, à chaque fois avant de changer de tâche, enregistrer le pointeur de pile dans le processus afin de pouvoir revenir là ou elle en est la prochaine fois qu'elle sera appelée. Respectivement, une fois la nouvelle tâche choisie, le pointeur de pile doit prendre l'adresse de là ou en était la tâche avant qu'elle soit interrompue.&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Séléction de processus ====&lt;br /&gt;
Lors de la séléction de processus, nous devons parcourir tous les processus jusqu'au moment où nous en trouvons un actif. Ainsi, il deviendra la tâche que nous traiterons lors du prochain intervalle de 20 ms. A ce stade, à chaque fois que la procédure selectProcess est appelée, nous devons réduire le temps de repos de chaque process endormi de 20 ms. D'autres conditions pourrons être ajoutée si ajout d'état a lieu. (voir l'ajout de selectProcess dans l'ISR)&lt;br /&gt;
&lt;br /&gt;
=== Test ===&lt;br /&gt;
==== Clignotement de deux LED à fréquences indivisibles entre elles ====&lt;br /&gt;
Afin de vérifier la réussite de notre ordonnanceur à fonctionnement tourniquet, nous avons programmer deux simples tâches changeant l'état d'une LED. Une à une fréquence 200ms et l'autre 300ms (avec un _delay_ms).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:left; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void tache1(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTC ^= (1 &amp;lt;&amp;lt; PC0);&lt;br /&gt;
    _delay_ms(300);}}&lt;br /&gt;
void tache2(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTD ^= (1 &amp;lt;&amp;lt; PD7);&lt;br /&gt;
    _delay_ms(200);}}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
[[Fichier:B5_test1.mp4|vignette|alt=test des frequences imprevisibles|test des frequences imprevisibles]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Clignotement grâce à l'état endormi ====&lt;br /&gt;
Nous ajoutons l'état endormi afin que nos tâches ne mettent pas en pause l'ordonnanceur avec un _delay_ms. Pour cela, nous incorporons une fonction makeSleep qui permet de mettre la tâche qui l'appelle dans cet état.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:left; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void makeSleep(int t){&lt;br /&gt;
  table_process[indice_tache].etat.id = SLEEPY;&lt;br /&gt;
  table_process[indice_tache].etat.time.sleepingtime = t;&lt;br /&gt;
  TIMER1_COMPA_vect();}&lt;br /&gt;
void tache1(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTC ^= (1 &amp;lt;&amp;lt; PC0);&lt;br /&gt;
    _delay_ms(300);}}&lt;br /&gt;
void tache3(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTC ^= (1 &amp;lt;&amp;lt; PC3);&lt;br /&gt;
    //_delay_ms(1000);&lt;br /&gt;
    makeSleep(1000);}}&lt;br /&gt;
void tache2(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTD ^= (1 &amp;lt;&amp;lt; PD7);&lt;br /&gt;
    //_delay_ms(1000);&lt;br /&gt;
    makeSleep(700);}}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
[[Fichier:B5_test2.mp4|vignette|alt=test des frequences imprevisibles|test des frequences imprevisibles]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
A noter que la première tâche executée ne doit pas être endormie.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Carte Fille Matrice de touches =&lt;br /&gt;
==Explications générales sur la réalisation de la carte==&lt;br /&gt;
&lt;br /&gt;
Pour concevoir la carte fille dédiée au clavier, nous avons réutilisé un ancien clavier DELL équipé d’une matrice déjà fonctionnelle. L’idée consiste à connecter les sorties de cette matrice directement à notre carte fille à l’aide d’un connecteur adapté.&lt;br /&gt;
&lt;br /&gt;
Cependant, un défi se pose : la matrice du clavier comprend un total de 26 sorties (sans compter les LED et autres signaux). Cela dépasse largement les capacités en nombre de broches d’un ATmega328P.&lt;br /&gt;
&lt;br /&gt;
Pour remédier à ce problème, nous avons mis en place une solution d’encodage. Nous avons utilisé un décodeur (3 vers 8) pour gérer les lignes et trois encodeurs (8 vers 3) pour gérer les colonnes. Les encodeurs sont montés en cascade pour réduire significativement le nombre de broches nécessaires. Cette solution permet de maximiser les ressources du microcontrôleur tout en gérant efficacement les signaux de la matrice.&lt;br /&gt;
&lt;br /&gt;
Nous avons opté pour le décodeur 74HC138D (qui va envoyer un 0 parmi des 1) et trois encodeurs CD4532BM (qui cherche le premier 1 parmi des 0). On sent quand même les problèmes venir petit à petit.&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
[[Fichier:Clavier dell.png||thumb|right|800px|Clavier DELL]]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Connecteur de base clavier dell.png||thumb|left|500px|Carte du clavier DELL]]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Matrice clavier dell.png||thumb|right|800px|Matrice du clavier DELL]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Détails des composants ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;ATmega328P&amp;lt;/u&amp;gt;&lt;br /&gt;
* Micro-contrôleur&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;74HC138D&amp;lt;/u&amp;gt;&lt;br /&gt;
* Décodeur : envoie un 0 parmi des 1.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;CD4532BM&amp;lt;/u&amp;gt;&lt;br /&gt;
* Encodeur : Nous avons étudié la datasheet et comment la mise en cascade fonctionne.&lt;br /&gt;
[[Fichier:Cascade.png|vignette|alt=Mise en cascade des encodeurs.|Mise en cascade des encodeurs.]]&lt;br /&gt;
On voit qu'un encodeur possède un bus de sortie de 5 bits. GS -&amp;gt; à l'état haut quand le composant reçoit un 1, 0 sinon. E0 -&amp;gt; à l'état haut quand il reçoit seulement des 0, 1 sinon. Puis Q2, Q1 ,Q0 la représentation binaire de l'entrée donnée.&lt;br /&gt;
&lt;br /&gt;
Afin de les mettre en cascade, il faut relié le E0 d'un premier encodeur au Ei de l'autre. Ensuite, nous allons faire un &amp;quot;OU&amp;quot; entre les GS afin de savoir si un des encodeurs reçoit un 1, puis grâce aux GS des deux premiers encodeurs nous sauront quelle encodeur à reçu le 1 (si les deux sont &amp;amp; 0 alors c'est le troisième). De même, faire une porte &amp;quot;OU&amp;quot; sur Q2, Q1, Q0 afin de réduire le nombre d'entrées/sorties nécessaires.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&amp;lt;u&amp;gt;74LS32&amp;lt;/u&amp;gt;&lt;br /&gt;
* Porte logique Or pour la mise en cascade des encodeurs.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Connecteur HE10&amp;lt;/u&amp;gt;&lt;br /&gt;
* Connecteur pour la liaison PicoShield-CarteFille&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Connecteur de la matrice&amp;lt;/u&amp;gt;&lt;br /&gt;
* Simplement une empreinte que l'on a créé [https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/CF_Clavier/Footprint_KeyboardDell_DJADJA Lien vers la bibliothèque présent sur le git]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;AVR-ISP-6&amp;lt;/u&amp;gt;&lt;br /&gt;
* Programmateur AVR&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;LED_SMD&amp;lt;/u&amp;gt;&lt;br /&gt;
* 3 LEDs&lt;br /&gt;
&lt;br /&gt;
== Hardware ==&lt;br /&gt;
===Kicad===&lt;br /&gt;
[[Fichier:Schematique carte fille clavier dell.png|center|1000px|vignette|Schématique de la carte Fille]]&lt;br /&gt;
&lt;br /&gt;
Pour réaliser la carte fille, nous avions dans un premier temps conçu une carte avec une matrice de touches directement implenter sur celle-ci, mais jugeant que cela était trop simple nous avons été redirigé vers l'utilisation d'une matrice déjà réalisé. Ainsi nous avons avons reutiliser celle d'un vieux clavier dell en créant les empreintes à la bonne taille pour se connecter sur la matrice&lt;br /&gt;
 &lt;br /&gt;
[[Fichier:Pcb recto carte fille clavier dell.png|left|480px|vignette|Avant du PCB]][[Fichier:Pcb verso carte fille clavier dell.png|right|480px|vignette|Arrière du PCB]]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Capture d’écran 2024-11-20 à 12.09.07.png|left|600px|vignette|PCB vue 3D avant]][[Fichier:Capture d’écran 2024-11-20 à 12.09.33.png|right|480px|vignette|PCB vue 3D arrière]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Carte après soudure des composants====&lt;br /&gt;
&lt;br /&gt;
===Différents Problèmes rencontrés===&lt;br /&gt;
Avant même la réception de la carte, alors que nous commençons a essayé d'écrire un premier programme, nous nous rendions compte qu'envoyer un 0 parmi des 1 et de rechercher un 1 parmi des 0 ne fonctionnera pas (logique). Nous avons alors pris la décision de changer le décodeur car il était pour nous plus simple de changer un composant que les trois encodeurs. Nous avons opté pour lui de la même famille, le 74HTC238D.&lt;br /&gt;
&lt;br /&gt;
Dès la réception de la carte, nous avons effectué un premier test avec une simple programmation de LED. Nous nous sommes rapidement aperçus que nous avions configuré deux noms d'étiquettes de reset distinctes sur KiCad : une pour l'AVR (RST) et une pour le connecteur HE-10 (RESET). Cependant, seul le reset du connecteur HE-10 était correctement relié au microcontrôleur. Pour résoudre ce problème, nous avons simplement connecté les deux broches de reset à l'aide d'un fil.&lt;br /&gt;
&lt;br /&gt;
Lors de l'examen initial de notre carte, nous avons également constaté une erreur que nous avions commise. En effet, comme nous avions initialement conçu une matrice de touches sans encodeurs ni décodeurs, il n'était donc pas nécessaire d'intégrer des résistances de pull-up ou de pull-down. Nous avons alors juste rajouter ces composants, or il en résulte que lorsqu'une touche sera pressée, un 1 sera bien envoyé mais pas parmi des 0, parmi des états indéterminé. En général, les états indéterminés, on aime pas trop, surtout quand cela empêche ta carte de pouvoir fonctionner comme voulu. Il a donc été nécessaire d'ajouter des résistances de pull-down sur chaque colonne de notre clavier. Afin de simplifier cette modification, nous avons utilisé des résistances CMS que nous avons positionnées comme des dominos (verticalement), ce qui nous a permis de faire passer un fil de masse directement au-dessus des résistances.&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Resistance pull Up domino.jpg|center|500px|vignette|Résistances de Pull-down sur les colonnes]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Une fois tous ces problèmes de base résolus, nous avons enfin pu nous attaquer à la programmation du clavier. Pour vérifier que toutes les touches étaient correctement détectées, nous avons réalisé un petit programme de test ([https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/CF_Clavier/prog/test.c Code du test]). Ce programme nous a permis d’associer chaque LED à un décodeur différent via la broche GS des décodeurs. Ainsi, nous avons pu identifier quelles touches ne répondaient pas. Premièrement, beaucoup de touches ne répondaient pas, moins d'une dizaine. Nous avons alors fait de multiples tests au multimètre sur notre carte mais aussi sur une autre matrice de touches similaire. Une des hypothèses fut qu'il fallait bien étamer les pistes pour permettre la conduction entre la carte et la matrice. Nous avons alors rajouter de l'étain, puis + de touches commençaient à fonctionner. Il fallait alors un nouveau programme de test pour détecter quelles lignes ou colonnes n'étaient pas bien étamés afin de permettre une conduction ([https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/CF_Clavier/prog/detect.c Code de détection]). Il suffisait ainsi de rajouter de l'étain sur les colonnes et les lignes qui ne répondaient pas. Enfin, toutes les touches sont détectées lors de d'une pression !&lt;br /&gt;
&lt;br /&gt;
==Programmation de la carte==&lt;br /&gt;
===Programme de test===&lt;br /&gt;
&lt;br /&gt;
([https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/CF_Clavier/prog/test.c Code du test])&lt;br /&gt;
&lt;br /&gt;
Afin de tester chaque touche de notre matrice, nous avons décidé de faire le programme le plus simple possible en utilisant les broches GS de nos encodeurs. Il n'y a pas d'histoire de ligne ou de colonnes ici, si une touche est pressée alors le GS de l'encodeur ou sa colonne est reliée passera à l'état haut. Une manière très simple de savoir si une touche est utilisable et si nos trois encodeurs sont opérationnels également. Nous avons trois leds pour trois encodeurs, pour chaque encodeur, s'allumera une led spécifique si il reçoit un 1 parmi des 0.&lt;br /&gt;
&lt;br /&gt;
Afin de mettre en place ce système, il nous faut un programme capable de balayer toutes les lignes de notre matrice via un décodeur.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:left; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
int tab_outputs[8][3] = {&lt;br /&gt;
    {0, 0, 0},&lt;br /&gt;
    {1, 0, 0},&lt;br /&gt;
    {0, 1, 0},&lt;br /&gt;
    {1, 1, 0},&lt;br /&gt;
    {0, 0, 1},&lt;br /&gt;
    {1, 0, 1},&lt;br /&gt;
    {0, 1, 1},&lt;br /&gt;
    {1, 1, 1},&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void maj_output(int lig){&lt;br /&gt;
    for (int i = 0 ; i &amp;lt; 3 ; i++){&lt;br /&gt;
        if (tab_outputs[lig][i] == 0){&lt;br /&gt;
            PORTC &amp;amp;= ~(1 &amp;lt;&amp;lt; i);&lt;br /&gt;
        }&lt;br /&gt;
        else if (tab_outputs[lig][i] == 1){&lt;br /&gt;
            PORTC |= (1 &amp;lt;&amp;lt; i);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Fichier:B5_test_matrice.mp4|vignette|alt=test d'une touche pressée |test d'une touche pressée|right|800px]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
Ici, grâce à l'initialisation d'un tableau de la représentation en binaire des chiffres 0 à 7, il suffit de faire une procédure qui prend en paramètre le numéro de ligne souhaitée puis de vérifier dans le tableau quelle sortie mettre à 0 et 1. Nous avions remarqué que mettre les sorties pour les décodeurs sur le même port côte à côte facilite la programmation.&lt;br /&gt;
&lt;br /&gt;
===Programme de détection===&lt;br /&gt;
&lt;br /&gt;
([https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/CF_Clavier/prog/detect.c Code du test])&lt;br /&gt;
&lt;br /&gt;
Dans le projet, nous avons eu des problèmes de lignes et colonnes qui n'était pas conduit entre notre carte et la matrice. Pour les identifier, nous avons mis en place un programme de détection qui lors de la pression d'une touche, va afficher grâce aux leds, de quel encodeur sa colonne régit puis quelle ligne et quelle colonne est activée. Ce programme permet ainsi de diagnostiquer rapidement les problèmes de conduction entre la carte et la matrice en identifiant précisément les correspondances défectueuses. &lt;br /&gt;
&lt;br /&gt;
Pour cela, nous avons imaginer deux fonctions show_ligne et show_colonne, permettant d'afficher sur nos trois leds la ligne et la colonne. Si les leds affichent : double clignotements de la led du milieu  (allumée, éteint, allumé) puis (éteint, allumée, allumée) alors la ligne L6 (voir KiCad) et la 4e colonne du deuxième encodeur sont activées.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:left; width: 48%; padding-left: 25px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void show_ligne(int i){&lt;br /&gt;
    turn_off_leds();&lt;br /&gt;
    for (int bit = 0; bit &amp;lt; 3; bit++){&lt;br /&gt;
        if (tab_outputs[i][bit] == 1) {&lt;br /&gt;
            PORTC |= (1 &amp;lt;&amp;lt; (bit+LED1));&lt;br /&gt;
        }&lt;br /&gt;
        else &lt;br /&gt;
            PORTC &amp;amp;= ~(1 &amp;lt;&amp;lt; (bit+LED1));&lt;br /&gt;
        }&lt;br /&gt;
    _delay_ms(SHOW_TIME);&lt;br /&gt;
    turn_off_leds();&lt;br /&gt;
}}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:right; width: 48%; padding-right: 25px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void show_colonne(){&lt;br /&gt;
    turn_off_leds();&lt;br /&gt;
    for (int i = Q0; i &amp;lt; Q2 + 1 ; i++){&lt;br /&gt;
        if (((inputs &amp;gt;&amp;gt; i) &amp;amp; 1) == 1) {&lt;br /&gt;
            PORTC |= (1 &amp;lt;&amp;lt; (i+LED1));&lt;br /&gt;
        }&lt;br /&gt;
        else &lt;br /&gt;
            PORTC &amp;amp;= ~(1 &amp;lt;&amp;lt; (i+LED1));&lt;br /&gt;
    }&lt;br /&gt;
    _delay_ms(SHOW_TIME);&lt;br /&gt;
    turn_off_leds();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
Les deux fonctions se ressemblent beaucoup, la différence étant que show_ligne va prendre un paramètre un entier selon la ligne que nous voulons afficher alors que colonne va directement regarde dans le bus d'entrées la représentation binaire de la colonne activée. A noter que le fait que les LEDs et Q2, Q1, Q0 sont successivement placés sur le même port rend la programmation plus simple à réaliser.&lt;br /&gt;
&lt;br /&gt;
A noter la présence d'un 'uint8_t inputs;' où l'on va assigner PIND à chaque début d'une boucle, en effet pendant l'afficher l'utilisateur ne reste pas forcément la touche enfoncées ce qui changera les valeurs du bus d'entrée. Il est alors important de sauvegarder l'état de ce bus avant de l'afficher.&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
[[Fichier:B5_test_detect.mp4|vignette|alt=test de la détection d'une touche |test de la détection d'une touche|center|800px]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Ping pong===&lt;br /&gt;
A l'aide des ressources envoyées par Mr.Redon, nous avons de quoi communiquer entre le shield et notre carte fille. Pour cela, nous avons du modifié un tout petit peu les programmes. En effet, nous avons ajouter un #define pour le Chip Select de notre clavier (le bon connecteur HE10 sur lequel nous allons le connecter) afin que ce soit bien lui qui sera sélectionné lors du spi_select et spi_deselect. Le shield va envoyer un 1 en SPI pour indiquer au clavier qu'il est sur écoute et qu'il attend un envoie de la carte fille.&lt;br /&gt;
&lt;br /&gt;
Cette communication va nous permettre de bien mapper toutes nos touches.&lt;br /&gt;
&lt;br /&gt;
Nous avons décidé de faire un tableau en 3 dimensions afin de faciliter le mapping. Pourquoi 3 dimensions ? Nous avons une première dimension pour le numéro de ligne (0 à 7), pour le numéro de colonne (0 à 7) puis pour le numéro d'encodeur (0 à 2). Le bus d'entrée nous donnant un numéro de ligne entre 0 et 7, nous avons trouvé plus facile de procéder de cette manière. Voici un exemple.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:center; width: 48%;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
char tab_touches[8][8][3] = {&lt;br /&gt;
    {{'\0'/*AltGr*/, '\0', '\0'}, {'\0', '\0', '\0'}, {'-', ' ', '\0'}, {'\0'/*Fleche gauche*/, 'b', '\0'}, {'\0'/*Fleche droite*/, '\0', '\0'}, {'\0'/*Fleche bas*/, '\0', '\0'}, {'\0', '\0', '\0'}, {'\0', '!', '\0'}}, &lt;br /&gt;
    {{'\0', 'x', 'w'}, {'\0', 'c', '\0'/*CTRL Droit*/}, {'*', '\n', '\0'}, {'\0'/*Pause*/, 'v', '\0'}, {'/', ',', '\0'}, {'\0'/*Verr Num*/, ';', '\0'}, {'\0'/*Touch window droite*/, ':', '\0'}, {'\0'/*Shift droit*/, '*', '\0'}}, &lt;br /&gt;
    {{'\0'/*Arret*/, 'z', 'a'}, {'\0'/*Options*/, 'e', '\0'}, {'9', '\0', '\0'}, {'\0', 'r', '\0'}, {'8', 'u', '\0'}, {'7', 'i', '\0'}, {'\0', 'o', '\0'}, {'*', 'p', '\0'}}, &lt;br /&gt;
    {{'\0', 's', 'q'}, {'\0'/*Touche window gauche*/, 'd', '\0'}, {'3', '\0', '\0'}, {'\n', 'f', '\0'}, {'2', 'j', '\0'}, {'1', 'k', '\0'}, {'\0', 'l', '\0'}, {'\0', 'm', '\0'}}, &lt;br /&gt;
    {{'\0', '\0', '\0'}, {'\0', '\0', '\0'}, {'\0', '\0', '\0'}, {'\0', '\0', '\0'}, {'\0', '\0', '\0'}, {'\0', '\0', 'w'}, {'\0', '\0', '\0'}, {'\0', '\0', '\0'}}, &lt;br /&gt;
    {{'\0', '&amp;lt;', '\0'}, {'\0', '\0', '\0'}, {'.', '\0', '\0'}, {'\0', 'g', '\0'}, {'0', 'h', '\0'}, {'\0', '\0', '\0'}, {'\0', '\0', '\0'}, {'\0', '%', '\0'}}, &lt;br /&gt;
    {{'\0', '\0'/*MAJ*/, '\0'/*tab*/}, {'\0', '\0'/*F3*/, '\0'}, {'\0', 8, '\0'}, {'\0', 't', '\0'}, {'5', 'y', '\0'}, {'4', '$', '\0'}, {'\0', '\0'/*F7*/, '\0'}, {'\0'/*Shift gauche*/, '^', '\0'}}, &lt;br /&gt;
    {{'\0', '\0'/*F1*/, '\0'/*œ*/}, {'\0', '\0'/*F2*/, '\0'/*CTRL Gauche*/}, {'\0'/*Page haut*/, '\0'/*F9*/, '\0'}, {'\0'/*Debut*/, '(', '\0'}, {'\0'/*Insert*/, '-', '\0'}, {'\0'/*Supp*/, '=', '\0'}, {'t', '\n'/*F8*/, '\0'}, {'g', ')', '\0'}}&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Notre clavier ne supporte pas l'appuie de plusieurs touches en simultané à cause de la présence de décodeurs et d'encodeurs, le shift devient inutilisable, seulement maj est opérationnel. Afin de permettre l'utilisation de altgr, il fonctionnera comme le maj mais les deux ne pourront pas être activés en même temps.&lt;br /&gt;
&lt;br /&gt;
Nous avons tout d'abord mit des valeurs au hasard mais unique dans le tableau, puis nous avons identifié les touches pour une case dans le tableau, nous avons fait ce processus plusieurs fois afin de trouver toutes les cases des touches du clavier dans le tableau. Pour permettre l'utilisation du maj et du altgr, nous avons créer deux autres tableau comme ça, un chacun avec ses touches assignées. Lors de l'envoie, il faut vérifier dans quel mode nous nous trouvons pour envoyer le caractère dans le bon tableau (alt, maj ou classique).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:left; width: 48%; padding-left: 25px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
  while(1)&lt;br /&gt;
  {&lt;br /&gt;
    spi_select();&lt;br /&gt;
    uint8_t r=spi_exch(1);&lt;br /&gt;
    if (r != 1) printf(&amp;quot;%c&amp;quot;,r);&lt;br /&gt;
    spi_deselect();&lt;br /&gt;
    _delay_ms(20);&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:right; width: 48%; padding-right: 25px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void envoyer(){&lt;br /&gt;
    printf(&amp;quot;Clavier attente\n&amp;quot;);&lt;br /&gt;
      uint8_t message=spi_wait();&lt;br /&gt;
      printf(&amp;quot;Clavier reçu %d\n&amp;quot;,message);&lt;br /&gt;
      if (message == 1)&lt;br /&gt;
        spi_sendback(temp);&lt;br /&gt;
      printf(&amp;quot;Clavier retour préparé %d\n&amp;quot;,temp);&lt;br /&gt;
  &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
Ici le shield (à gauche) va envoyer un 1 en SPI pour dire au clavier qu'il est prêt à l'écouter, si il reçoit autre chose qu'un 1 (son propre envoie) alors il l'affiche. Le clavier (à droite) va envoyer son dernier caractère dont la touche a été pressée lorsqu'il reçoit ce fameux 1.&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
[[Fichier:B5_test_pingpong.mp4|vignette|alt=test clavier sur shield (sans démonstration de altgr et maj) |test clavier sur shield (sans démonstration de altgr et maj)|center|800px]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Implémentation dans l'ordonnanceur===&lt;br /&gt;
Pour pouvoir utiliser le clavier avec l'ordonnanceur, il suffit de faire de notre while(1) précédent, une tâche a part entière de notre ordonnanceur. Sur cet exemple on voit l'utilisation du alt et du maj.&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
[[Fichier:B5_test_final.mp4|vignette|alt=test clavier avec ordonnancement |test clavier avec ordonnancement|center|800px]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;/div&gt;</summary>
		<author><name>Adjadjaa</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-5&amp;diff=7357</id>
		<title>SE4Binome2024-5</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-5&amp;diff=7357"/>
		<updated>2025-01-26T16:01:47Z</updated>

		<summary type="html">&lt;p&gt;Adjadjaa : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Introduction=&lt;br /&gt;
&lt;br /&gt;
Ce wiki documente le développement d’un pico-ordinateur modulaire. Ce dernier est constitué d’une carte principale, composée d’une carte Shield permettant la connexion des cartes filles, et d’une carte mère (initialement simulée par une Arduino Uno avant sa conception finale). Plusieurs cartes filles sont prévues, chacune remplissant une fonction spécifique : gestion du clavier, affichage, port série, réseau, mémoire de masse et son.&lt;br /&gt;
&lt;br /&gt;
Notre binôme est spécifiquement chargé du développement de la carte fille dédiée au clavier.&lt;br /&gt;
&lt;br /&gt;
Toutes les ressources nécessaires, incluant les codes sources et les schémas, sont disponibles sur le dépôt Git suivant :  [https://gitea.plil.fr/ktouron/se4-djadja-touron_pico.git Lien du Git]&lt;br /&gt;
&lt;br /&gt;
= Carte Shield =&lt;br /&gt;
[[Fichier:Carte Recto non soudé.jpg|vignette|left|thumb|350px|Recto de la carte avant soudage des composants]]&lt;br /&gt;
[[Fichier:Verso non solder.jpeg.jpg|vignette|thumb|right|300px|Verso de la carte avant soudage des composants]]&lt;br /&gt;
[[Fichier:Carde shield soudé.jpg|vignette|thumb|center|350px|Photo de la carte avec les composants soudés]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Test==&lt;br /&gt;
=== Allumage de LEDS sur Programmateur AVR ===&lt;br /&gt;
Avant de programmer directement sur le shield, nous avons allumé des LED pour tester la carte. Nous avons directement utilisé le code exemple fourni par l'IDE arduino en adaptant simplement les pins correspondant aux leds. [https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/PicoShield/Programmation/Blink Code du test]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Vid_test_carte_mp4.mp4|vignette|thumb|center|700px|Vidéo de Test des leds]]&lt;br /&gt;
&lt;br /&gt;
=== Lecture de la carte SD ===&lt;br /&gt;
Avant de programmer directement sur le shield, nous avons tester si la carte SD était bien détectée et lue. On a utilisé le code test présent dans l'IDE arduino en adaptant le port utilisé.[https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/PicoShield/Programmation/CardInfo Code du test]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Resultat SD.jpg|vignette|thumb|center|700px|Carte SD bien détéctée]]&lt;br /&gt;
&lt;br /&gt;
=== Connecteurs IDC HE10 ===&lt;br /&gt;
Afin de tester nos connecteur HE10, nous avons utilisé un afficher 7 segments (Sparkfun 7 segments display). Pour pouvoir vérifier leurs fonctionnements nous avons branché l'afficheur sur chaque connecteur tour à tour. Le programme implanté est un simple connecteur à afficher sur l'afficheur. Voici une vidéo du compteur fonctionnant sur un des 5 connecteurs HE10. ([https://learn.sparkfun.com/tutorials/using-the-serial-7-segment-display/all Code ici (section : Example 2 SPI)])&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Se4-5-7segments.mp4|vignette|alt=se4-5-7segments|Test connecteur HE10 avec afficheur 7 segments.|center]]&lt;br /&gt;
== Ordonnanceur ==&lt;br /&gt;
Pour les interruptions de notre ordonnanceur nous avons utilisé la procédure d'initialisation du minuteur avec le Timer1 disponible dans les cours de Mr.Redon en renseignant une période de 20ms. Nous l'avons disposé dans le fichier minuteur.c car nous n'allons plus le modifier pour le reste du projet. Dans un autre fichier process.c (avec process.h), nous allons y mettre nos structures pour les process et leurs états puis une union pour le temps qui le caractérise ainsi que toutes les fonctions associés.&lt;br /&gt;
&lt;br /&gt;
[https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/Ordonnanceur Lien du répertoire]&lt;br /&gt;
&lt;br /&gt;
=== Processus ===&lt;br /&gt;
==== Structure ====&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:right; width: 48%; padding-left: 10px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
    uint16_t adresseDepart;  //adresse de la fonction de départ &lt;br /&gt;
    uint16_t adressePile;       //adresse de la pile d'exécution&lt;br /&gt;
    Etat etat;        &lt;br /&gt;
} Process;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Notre structure caractérisant un processus est définie par les trois champs ci-contre.&lt;br /&gt;
&lt;br /&gt;
Une adresse de départ correspondant à la fonction du processus associé, l'adresse où se situe le processus dans la pile puis l'état de la tâche. Nous avons décidé de faire une structure à part entière compte tenu des multitudes d'états que nous pourrons ajouter pendant la progression du projet.&lt;br /&gt;
&lt;br /&gt;
==== Etat d'un processus ====&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:right; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
typedef union {&lt;br /&gt;
  int sleepingtime;       &lt;br /&gt;
} Time;&lt;br /&gt;
&lt;br /&gt;
typedef struct {&lt;br /&gt;
  int id;&lt;br /&gt;
  Time time;&lt;br /&gt;
} Etat ;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
L'état d'un processus est alors une structure à deux champs (pour l'instant), l'id doit correspondre à un '#DEFINE' pour avoir un sens tandis que nous avons choisi de faire une union pour le temps qui caractérise notre état afin qu'il puisse avoir un nom et type de variable cohérent avec son état.(Ici seulement sleepingtime car seul l'état endormi existe pour le moment)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
  {| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
  |+ Tableau des états&lt;br /&gt;
  |-&lt;br /&gt;
  ! Etat !! ACTIVE !! SLEEPY !! ... !! ...&lt;br /&gt;
  |-&lt;br /&gt;
  | Id || 0 || 1 || ... || ...&lt;br /&gt;
  |}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Procédures principales ====&lt;br /&gt;
&lt;br /&gt;
=== ISR ===&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:right; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
ISR(TIMER1_COMPA_vect, ISR_NAKED)    // Procédure d'interruption&lt;br /&gt;
{&lt;br /&gt;
  TCNT1=0;//reset timer&lt;br /&gt;
  /* Sauvegarde du contexte de la tâche interrompue */&lt;br /&gt;
  portSAVE_REGISTERS();&lt;br /&gt;
   table_process[indice_tache].adressePile = SP;&lt;br /&gt;
  /* Appel à l'ordonnanceur */&lt;br /&gt;
  selectProcess();&lt;br /&gt;
  /* Récupération du contexte de la tâche ré-activée */&lt;br /&gt;
  SP = table_process[indice_tache].adressePile;&lt;br /&gt;
  portRESTORE_REGISTERS();&lt;br /&gt;
  &lt;br /&gt;
  asm volatile ( &amp;quot;reti&amp;quot; );&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
L'ISR est ce qu'il va être executer lors des interruptions toutes les 20 millisecondes. Cela consiste à sauvegarder tous les registres de la tâche qui était en cours avant l'appel de l'ISR pour ensuite passer à la tâche suivante valide (c'est à dire active) sans oublier de charger les registres de la nouvelle tâche.&lt;br /&gt;
&lt;br /&gt;
Nous devons également, à chaque fois avant de changer de tâche, enregistrer le pointeur de pile dans le processus afin de pouvoir revenir là ou elle en est la prochaine fois qu'elle sera appelée. Respectivement, une fois la nouvelle tâche choisie, le pointeur de pile doit prendre l'adresse de là ou en était la tâche avant qu'elle soit interrompue.&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Séléction de processus ====&lt;br /&gt;
Lors de la séléction de processus, nous devons parcourir tous les processus jusqu'au moment où nous en trouvons un actif. Ainsi, il deviendra la tâche que nous traiterons lors du prochain intervalle de 20 ms. A ce stade, à chaque fois que la procédure selectProcess est appelée, nous devons réduire le temps de repos de chaque process endormi de 20 ms. D'autres conditions pourrons être ajoutée si ajout d'état a lieu. (voir l'ajout de selectProcess dans l'ISR)&lt;br /&gt;
&lt;br /&gt;
=== Test ===&lt;br /&gt;
==== Clignotement de deux LED à fréquences indivisibles entre elles ====&lt;br /&gt;
Afin de vérifier la réussite de notre ordonnanceur à fonctionnement tourniquet, nous avons programmer deux simples tâches changeant l'état d'une LED. Une à une fréquence 200ms et l'autre 300ms (avec un _delay_ms).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:left; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void tache1(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTC ^= (1 &amp;lt;&amp;lt; PC0);&lt;br /&gt;
    _delay_ms(300);}}&lt;br /&gt;
void tache2(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTD ^= (1 &amp;lt;&amp;lt; PD7);&lt;br /&gt;
    _delay_ms(200);}}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
[[Fichier:B5_test1.mp4|vignette|alt=test des frequences imprevisibles|test des frequences imprevisibles]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Clignotement grâce à l'état endormi ====&lt;br /&gt;
Nous ajoutons l'état endormi afin que nos tâches ne mettent pas en pause l'ordonnanceur avec un _delay_ms. Pour cela, nous incorporons une fonction makeSleep qui permet de mettre la tâche qui l'appelle dans cet état.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:left; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void makeSleep(int t){&lt;br /&gt;
  table_process[indice_tache].etat.id = SLEEPY;&lt;br /&gt;
  table_process[indice_tache].etat.time.sleepingtime = t;&lt;br /&gt;
  TIMER1_COMPA_vect();}&lt;br /&gt;
void tache1(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTC ^= (1 &amp;lt;&amp;lt; PC0);&lt;br /&gt;
    _delay_ms(300);}}&lt;br /&gt;
void tache3(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTC ^= (1 &amp;lt;&amp;lt; PC3);&lt;br /&gt;
    //_delay_ms(1000);&lt;br /&gt;
    makeSleep(1000);}}&lt;br /&gt;
void tache2(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTD ^= (1 &amp;lt;&amp;lt; PD7);&lt;br /&gt;
    //_delay_ms(1000);&lt;br /&gt;
    makeSleep(700);}}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
[[Fichier:B5_test2.mp4|vignette|alt=test des frequences imprevisibles|test des frequences imprevisibles]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
A noter que la première tâche executée ne doit pas être endormie.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Carte Fille Matrice de touches =&lt;br /&gt;
==Explications générales sur la réalisation de la carte==&lt;br /&gt;
&lt;br /&gt;
Pour concevoir la carte fille dédiée au clavier, nous avons réutilisé un ancien clavier DELL équipé d’une matrice déjà fonctionnelle. L’idée consiste à connecter les sorties de cette matrice directement à notre carte fille à l’aide d’un connecteur adapté.&lt;br /&gt;
&lt;br /&gt;
Cependant, un défi se pose : la matrice du clavier comprend un total de 26 sorties (sans compter les LED et autres signaux). Cela dépasse largement les capacités en nombre de broches d’un ATmega328P.&lt;br /&gt;
&lt;br /&gt;
Pour remédier à ce problème, nous avons mis en place une solution d’encodage. Nous avons utilisé un décodeur (3 vers 8) pour gérer les lignes et trois encodeurs (8 vers 3) pour gérer les colonnes. Les encodeurs sont montés en cascade pour réduire significativement le nombre de broches nécessaires. Cette solution permet de maximiser les ressources du microcontrôleur tout en gérant efficacement les signaux de la matrice.&lt;br /&gt;
&lt;br /&gt;
Nous avons opté pour le décodeur 74HC138D (qui va envoyer un 0 parmi des 1) et trois encodeurs CD4532BM (qui cherche le premier 1 parmi des 0). On sent quand même les problèmes venir petit à petit.&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
[[Fichier:Clavier dell.png||thumb|right|800px|Clavier DELL]]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Connecteur de base clavier dell.png||thumb|left|500px|Carte du clavier DELL]]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Matrice clavier dell.png||thumb|right|800px|Matrice du clavier DELL]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Détails des composants ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;ATmega328P&amp;lt;/u&amp;gt;&lt;br /&gt;
* Micro-contrôleur&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;74HC138D&amp;lt;/u&amp;gt;&lt;br /&gt;
* Décodeur : envoie un 0 parmi des 1.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;CD4532BM&amp;lt;/u&amp;gt;&lt;br /&gt;
* Encodeur : Nous avons étudié la datasheet et comment la mise en cascade fonctionne.&lt;br /&gt;
[[Fichier:Cascade.png|vignette|alt=Mise en cascade des encodeurs.|Mise en cascade des encodeurs.]]&lt;br /&gt;
On voit qu'un encodeur possède un bus de sortie de 5 bits. GS -&amp;gt; à l'état haut quand le composant reçoit un 1, 0 sinon. E0 -&amp;gt; à l'état haut quand il reçoit seulement des 0, 1 sinon. Puis Q2, Q1 ,Q0 la représentation binaire de l'entrée donnée.&lt;br /&gt;
&lt;br /&gt;
Afin de les mettre en cascade, il faut relié le E0 d'un premier encodeur au Ei de l'autre. Ensuite, nous allons faire un &amp;quot;OU&amp;quot; entre les GS afin de savoir si un des encodeurs reçoit un 1, puis grâce aux GS des deux premiers encodeurs nous sauront quelle encodeur à reçu le 1 (si les deux sont &amp;amp; 0 alors c'est le troisième). De même, faire une porte &amp;quot;OU&amp;quot; sur Q2, Q1, Q0 afin de réduire le nombre d'entrées/sorties nécessaires.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&amp;lt;u&amp;gt;74LS32&amp;lt;/u&amp;gt;&lt;br /&gt;
* Porte logique Or pour la mise en cascade des encodeurs.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Connecteur HE10&amp;lt;/u&amp;gt;&lt;br /&gt;
* Connecteur pour la liaison PicoShield-CarteFille&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Connecteur de la matrice&amp;lt;/u&amp;gt;&lt;br /&gt;
* Simplement une empreinte que l'on a créé [https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/CF_Clavier/Footprint_KeyboardDell_DJADJA Lien vers la bibliothèque présent sur le git]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;AVR-ISP-6&amp;lt;/u&amp;gt;&lt;br /&gt;
* Programmateur AVR&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;LED_SMD&amp;lt;/u&amp;gt;&lt;br /&gt;
* 3 LEDs&lt;br /&gt;
&lt;br /&gt;
== Hardware ==&lt;br /&gt;
===Kicad===&lt;br /&gt;
[[Fichier:Schematique carte fille clavier dell.png|center|1000px|vignette|Schématique de la carte Fille]]&lt;br /&gt;
&lt;br /&gt;
Pour réaliser la carte fille, nous avions dans un premier temps conçu une carte avec une matrice de touches directement implenter sur celle-ci, mais jugeant que cela était trop simple nous avons été redirigé vers l'utilisation d'une matrice déjà réalisé. Ainsi nous avons avons reutiliser celle d'un vieux clavier dell en créant les empreintes à la bonne taille pour se connecter sur la matrice&lt;br /&gt;
 &lt;br /&gt;
[[Fichier:Pcb recto carte fille clavier dell.png|left|480px|vignette|Avant du PCB]][[Fichier:Pcb verso carte fille clavier dell.png|right|480px|vignette|Arrière du PCB]]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Capture d’écran 2024-11-20 à 12.09.07.png|left|600px|vignette|PCB vue 3D avant]][[Fichier:Capture d’écran 2024-11-20 à 12.09.33.png|right|480px|vignette|PCB vue 3D arrière]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Carte après soudure des composants====&lt;br /&gt;
&lt;br /&gt;
===Différents Problèmes rencontrés===&lt;br /&gt;
Avant même la réception de la carte, alors que nous commençons a essayé d'écrire un premier programme, nous nous rendions compte qu'envoyer un 0 parmi des 1 et de rechercher un 1 parmi des 0 ne fonctionnera pas (logique). Nous avons alors pris la décision de changer le décodeur car il était pour nous plus simple de changer un composant que les trois encodeurs. Nous avons opté pour lui de la même famille, le 74HTC238D.&lt;br /&gt;
&lt;br /&gt;
Dès la réception de la carte, nous avons effectué un premier test avec une simple programmation de LED. Nous nous sommes rapidement aperçus que nous avions configuré deux noms d'étiquettes de reset distinctes sur KiCad : une pour l'AVR (RST) et une pour le connecteur HE-10 (RESET). Cependant, seul le reset du connecteur HE-10 était correctement relié au microcontrôleur. Pour résoudre ce problème, nous avons simplement connecté les deux broches de reset à l'aide d'un fil.&lt;br /&gt;
&lt;br /&gt;
Lors de l'examen initial de notre carte, nous avons également constaté une erreur que nous avions commise. En effet, comme nous avions initialement conçu une matrice de touches sans encodeurs ni décodeurs, il n'était donc pas nécessaire d'intégrer des résistances de pull-up ou de pull-down. Nous avons alors juste rajouter ces composants, or il en résulte que lorsqu'une touche sera pressée, un 1 sera bien envoyé mais pas parmi des 0, parmi des états indéterminé. En général, les états indéterminés, on aime pas trop, surtout quand cela empêche ta carte de pouvoir fonctionner comme voulu. Il a donc été nécessaire d'ajouter des résistances de pull-down sur chaque colonne de notre clavier. Afin de simplifier cette modification, nous avons utilisé des résistances CMS que nous avons positionnées comme des dominos (verticalement), ce qui nous a permis de faire passer un fil de masse directement au-dessus des résistances.&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Resistance pull Up domino.jpg|vignette|Résistances de Pull-down sur les colonnes]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Une fois tous ces problèmes de base résolus, nous avons enfin pu nous attaquer à la programmation du clavier. Pour vérifier que toutes les touches étaient correctement détectées, nous avons réalisé un petit programme de test ([https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/CF_Clavier/prog/test.c Code du test]). Ce programme nous a permis d’associer chaque LED à un décodeur différent via la broche GS des décodeurs. Ainsi, nous avons pu identifier quelles touches ne répondaient pas. Premièrement, beaucoup de touches ne répondaient pas, moins d'une dizaine. Nous avons alors fait de multiples tests au multimètre sur notre carte mais aussi sur une autre matrice de touches similaire. Une des hypothèses fut qu'il fallait bien étamer les pistes pour permettre la conduction entre la carte et la matrice. Nous avons alors rajouter de l'étain, puis + de touches commençaient à fonctionner. Il fallait alors un nouveau programme de test pour détecter quelles lignes ou colonnes n'étaient pas bien étamés afin de permettre une conduction ([https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/CF_Clavier/prog/detect.c Code de détection]). Il suffisait ainsi de rajouter de l'étain sur les colonnes et les lignes qui ne répondaient pas. Enfin, toutes les touches sont détectées lors de d'une pression !&lt;br /&gt;
&lt;br /&gt;
==Programmation de la carte==&lt;br /&gt;
===Programme de test===&lt;br /&gt;
&lt;br /&gt;
([https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/CF_Clavier/prog/test.c Code du test])&lt;br /&gt;
&lt;br /&gt;
Afin de tester chaque touche de notre matrice, nous avons décidé de faire le programme le plus simple possible en utilisant les broches GS de nos encodeurs. Il n'y a pas d'histoire de ligne ou de colonnes ici, si une touche est pressée alors le GS de l'encodeur ou sa colonne est reliée passera à l'état haut. Une manière très simple de savoir si une touche est utilisable et si nos trois encodeurs sont opérationnels également. Nous avons trois leds pour trois encodeurs, pour chaque encodeur, s'allumera une led spécifique si il reçoit un 1 parmi des 0.&lt;br /&gt;
&lt;br /&gt;
Afin de mettre en place ce système, il nous faut un programme capable de balayer toutes les lignes de notre matrice via un décodeur.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:left; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
int tab_outputs[8][3] = {&lt;br /&gt;
    {0, 0, 0},&lt;br /&gt;
    {1, 0, 0},&lt;br /&gt;
    {0, 1, 0},&lt;br /&gt;
    {1, 1, 0},&lt;br /&gt;
    {0, 0, 1},&lt;br /&gt;
    {1, 0, 1},&lt;br /&gt;
    {0, 1, 1},&lt;br /&gt;
    {1, 1, 1},&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void maj_output(int lig){&lt;br /&gt;
    for (int i = 0 ; i &amp;lt; 3 ; i++){&lt;br /&gt;
        if (tab_outputs[lig][i] == 0){&lt;br /&gt;
            PORTC &amp;amp;= ~(1 &amp;lt;&amp;lt; i);&lt;br /&gt;
        }&lt;br /&gt;
        else if (tab_outputs[lig][i] == 1){&lt;br /&gt;
            PORTC |= (1 &amp;lt;&amp;lt; i);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Fichier:B5_test_matrice.mp4|vignette|alt=test d'une touche pressée |test d'une touche pressée|right|800px]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
Ici, grâce à l'initialisation d'un tableau de la représentation en binaire des chiffres 0 à 7, il suffit de faire une procédure qui prend en paramètre le numéro de ligne souhaitée puis de vérifier dans le tableau quelle sortie mettre à 0 et 1. Nous avions remarqué que mettre les sorties pour les décodeurs sur le même port côte à côte facilite la programmation.&lt;br /&gt;
&lt;br /&gt;
===Programme de détection===&lt;br /&gt;
&lt;br /&gt;
([https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/CF_Clavier/prog/detect.c Code du test])&lt;br /&gt;
&lt;br /&gt;
Dans le projet, nous avons eu des problèmes de lignes et colonnes qui n'était pas conduit entre notre carte et la matrice. Pour les identifier, nous avons mis en place un programme de détection qui lors de la pression d'une touche, va afficher grâce aux leds, de quel encodeur sa colonne régit puis quelle ligne et quelle colonne est activée. Ce programme permet ainsi de diagnostiquer rapidement les problèmes de conduction entre la carte et la matrice en identifiant précisément les correspondances défectueuses. &lt;br /&gt;
&lt;br /&gt;
Pour cela, nous avons imaginer deux fonctions show_ligne et show_colonne, permettant d'afficher sur nos trois leds la ligne et la colonne. Si les leds affichent : double clignotements de la led du milieu  (allumée, éteint, allumé) puis (éteint, allumée, allumée) alors la ligne L6 (voir KiCad) et la 4e colonne du deuxième encodeur sont activées.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:left; width: 48%; padding-left: 25px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void show_ligne(int i){&lt;br /&gt;
    turn_off_leds();&lt;br /&gt;
    for (int bit = 0; bit &amp;lt; 3; bit++){&lt;br /&gt;
        if (tab_outputs[i][bit] == 1) {&lt;br /&gt;
            PORTC |= (1 &amp;lt;&amp;lt; (bit+LED1));&lt;br /&gt;
        }&lt;br /&gt;
        else &lt;br /&gt;
            PORTC &amp;amp;= ~(1 &amp;lt;&amp;lt; (bit+LED1));&lt;br /&gt;
        }&lt;br /&gt;
    _delay_ms(SHOW_TIME);&lt;br /&gt;
    turn_off_leds();&lt;br /&gt;
}}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:right; width: 48%; padding-right: 25px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void show_colonne(){&lt;br /&gt;
    turn_off_leds();&lt;br /&gt;
    for (int i = Q0; i &amp;lt; Q2 + 1 ; i++){&lt;br /&gt;
        if (((inputs &amp;gt;&amp;gt; i) &amp;amp; 1) == 1) {&lt;br /&gt;
            PORTC |= (1 &amp;lt;&amp;lt; (i+LED1));&lt;br /&gt;
        }&lt;br /&gt;
        else &lt;br /&gt;
            PORTC &amp;amp;= ~(1 &amp;lt;&amp;lt; (i+LED1));&lt;br /&gt;
    }&lt;br /&gt;
    _delay_ms(SHOW_TIME);&lt;br /&gt;
    turn_off_leds();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
Les deux fonctions se ressemblent beaucoup, la différence étant que show_ligne va prendre un paramètre un entier selon la ligne que nous voulons afficher alors que colonne va directement regarde dans le bus d'entrées la représentation binaire de la colonne activée. A noter que le fait que les LEDs et Q2, Q1, Q0 sont successivement placés sur le même port rend la programmation plus simple à réaliser.&lt;br /&gt;
&lt;br /&gt;
A noter la présence d'un 'uint8_t inputs;' où l'on va assigner PIND à chaque début d'une boucle, en effet pendant l'afficher l'utilisateur ne reste pas forcément la touche enfoncées ce qui changera les valeurs du bus d'entrée. Il est alors important de sauvegarder l'état de ce bus avant de l'afficher.&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
[[Fichier:B5_test_detect.mp4|vignette|alt=test de la détection d'une touche |test de la détection d'une touche|center|800px]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Ping pong===&lt;br /&gt;
A l'aide des ressources envoyées par Mr.Redon, nous avons de quoi communiquer entre le shield et notre carte fille. Pour cela, nous avons du modifié un tout petit peu les programmes. En effet, nous avons ajouter un #define pour le Chip Select de notre clavier (le bon connecteur HE10 sur lequel nous allons le connecter) afin que ce soit bien lui qui sera sélectionné lors du spi_select et spi_deselect. Le shield va envoyer un 1 en SPI pour indiquer au clavier qu'il est sur écoute et qu'il attend un envoie de la carte fille.&lt;br /&gt;
&lt;br /&gt;
Cette communication va nous permettre de bien mapper toutes nos touches.&lt;br /&gt;
&lt;br /&gt;
Nous avons décidé de faire un tableau en 3 dimensions afin de faciliter le mapping. Pourquoi 3 dimensions ? Nous avons une première dimension pour le numéro de ligne (0 à 7), pour le numéro de colonne (0 à 7) puis pour le numéro d'encodeur (0 à 2). Le bus d'entrée nous donnant un numéro de ligne entre 0 et 7, nous avons trouvé plus facile de procéder de cette manière. Voici un exemple.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:center; width: 48%;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
char tab_touches[8][8][3] = {&lt;br /&gt;
    {{'\0'/*AltGr*/, '\0', '\0'}, {'\0', '\0', '\0'}, {'-', ' ', '\0'}, {'\0'/*Fleche gauche*/, 'b', '\0'}, {'\0'/*Fleche droite*/, '\0', '\0'}, {'\0'/*Fleche bas*/, '\0', '\0'}, {'\0', '\0', '\0'}, {'\0', '!', '\0'}}, &lt;br /&gt;
    {{'\0', 'x', 'w'}, {'\0', 'c', '\0'/*CTRL Droit*/}, {'*', '\n', '\0'}, {'\0'/*Pause*/, 'v', '\0'}, {'/', ',', '\0'}, {'\0'/*Verr Num*/, ';', '\0'}, {'\0'/*Touch window droite*/, ':', '\0'}, {'\0'/*Shift droit*/, '*', '\0'}}, &lt;br /&gt;
    {{'\0'/*Arret*/, 'z', 'a'}, {'\0'/*Options*/, 'e', '\0'}, {'9', '\0', '\0'}, {'\0', 'r', '\0'}, {'8', 'u', '\0'}, {'7', 'i', '\0'}, {'\0', 'o', '\0'}, {'*', 'p', '\0'}}, &lt;br /&gt;
    {{'\0', 's', 'q'}, {'\0'/*Touche window gauche*/, 'd', '\0'}, {'3', '\0', '\0'}, {'\n', 'f', '\0'}, {'2', 'j', '\0'}, {'1', 'k', '\0'}, {'\0', 'l', '\0'}, {'\0', 'm', '\0'}}, &lt;br /&gt;
    {{'\0', '\0', '\0'}, {'\0', '\0', '\0'}, {'\0', '\0', '\0'}, {'\0', '\0', '\0'}, {'\0', '\0', '\0'}, {'\0', '\0', 'w'}, {'\0', '\0', '\0'}, {'\0', '\0', '\0'}}, &lt;br /&gt;
    {{'\0', '&amp;lt;', '\0'}, {'\0', '\0', '\0'}, {'.', '\0', '\0'}, {'\0', 'g', '\0'}, {'0', 'h', '\0'}, {'\0', '\0', '\0'}, {'\0', '\0', '\0'}, {'\0', '%', '\0'}}, &lt;br /&gt;
    {{'\0', '\0'/*MAJ*/, '\0'/*tab*/}, {'\0', '\0'/*F3*/, '\0'}, {'\0', 8, '\0'}, {'\0', 't', '\0'}, {'5', 'y', '\0'}, {'4', '$', '\0'}, {'\0', '\0'/*F7*/, '\0'}, {'\0'/*Shift gauche*/, '^', '\0'}}, &lt;br /&gt;
    {{'\0', '\0'/*F1*/, '\0'/*œ*/}, {'\0', '\0'/*F2*/, '\0'/*CTRL Gauche*/}, {'\0'/*Page haut*/, '\0'/*F9*/, '\0'}, {'\0'/*Debut*/, '(', '\0'}, {'\0'/*Insert*/, '-', '\0'}, {'\0'/*Supp*/, '=', '\0'}, {'t', '\n'/*F8*/, '\0'}, {'g', ')', '\0'}}&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Notre clavier ne supporte pas l'appuie de plusieurs touches en simultané à cause de la présence de décodeurs et d'encodeurs, le shift devient inutilisable, seulement maj est opérationnel. Afin de permettre l'utilisation de altgr, il fonctionnera comme le maj mais les deux ne pourront pas être activés en même temps.&lt;br /&gt;
&lt;br /&gt;
Nous avons tout d'abord mit des valeurs au hasard mais unique dans le tableau, puis nous avons identifié les touches pour une case dans le tableau, nous avons fait ce processus plusieurs fois afin de trouver toutes les cases des touches du clavier dans le tableau. Pour permettre l'utilisation du maj et du altgr, nous avons créer deux autres tableau comme ça, un chacun avec ses touches assignées. Lors de l'envoie, il faut vérifier dans quel mode nous nous trouvons pour envoyer le caractère dans le bon tableau (alt, maj ou classique).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:left; width: 48%; padding-left: 25px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
  while(1)&lt;br /&gt;
  {&lt;br /&gt;
    spi_select();&lt;br /&gt;
    uint8_t r=spi_exch(1);&lt;br /&gt;
    if (r != 1) printf(&amp;quot;%c&amp;quot;,r);&lt;br /&gt;
    spi_deselect();&lt;br /&gt;
    _delay_ms(20);&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:right; width: 48%; padding-right: 25px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void envoyer(){&lt;br /&gt;
    printf(&amp;quot;Clavier attente\n&amp;quot;);&lt;br /&gt;
      uint8_t message=spi_wait();&lt;br /&gt;
      printf(&amp;quot;Clavier reçu %d\n&amp;quot;,message);&lt;br /&gt;
      if (message == 1)&lt;br /&gt;
        spi_sendback(temp);&lt;br /&gt;
      printf(&amp;quot;Clavier retour préparé %d\n&amp;quot;,temp);&lt;br /&gt;
  &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
Ici le shield (à gauche) va envoyer un 1 en SPI pour dire au clavier qu'il est prêt à l'écouter, si il reçoit autre chose qu'un 1 (son propre envoie) alors il l'affiche. Le clavier (à droite) va envoyer son dernier caractère dont la touche a été pressée lorsqu'il reçoit ce fameux 1.&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
[[Fichier:B5_test_pingpong.mp4|vignette|alt=test clavier sur shield (sans démonstration de altgr et maj) |test clavier sur shield (sans démonstration de altgr et maj)|center|800px]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Implémentation dans l'ordonnanceur===&lt;br /&gt;
Pour pouvoir utiliser le clavier avec l'ordonnanceur, il suffit de faire de notre while(1) précédent, une tâche a part entière de notre ordonnanceur. Sur cet exemple on voit l'utilisation du alt et du maj.&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
[[Fichier:B5_test_final.mp4|vignette|alt=test clavier avec ordonnancement |test clavier avec ordonnancement|center|800px]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;/div&gt;</summary>
		<author><name>Adjadjaa</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-5&amp;diff=7356</id>
		<title>SE4Binome2024-5</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-5&amp;diff=7356"/>
		<updated>2025-01-26T16:00:24Z</updated>

		<summary type="html">&lt;p&gt;Adjadjaa : /* Différents Problèmes rencontrés */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Introduction=&lt;br /&gt;
&lt;br /&gt;
Ce wiki documente le développement d’un pico-ordinateur modulaire. Ce dernier est constitué d’une carte principale, composée d’une carte Shield permettant la connexion des cartes filles, et d’une carte mère (initialement simulée par une Arduino Uno avant sa conception finale). Plusieurs cartes filles sont prévues, chacune remplissant une fonction spécifique : gestion du clavier, affichage, port série, réseau, mémoire de masse et son.&lt;br /&gt;
&lt;br /&gt;
Notre binôme est spécifiquement chargé du développement de la carte fille dédiée au clavier.&lt;br /&gt;
&lt;br /&gt;
Toutes les ressources nécessaires, incluant les codes sources et les schémas, sont disponibles sur le dépôt Git suivant :  [https://gitea.plil.fr/ktouron/se4-djadja-touron_pico.git Lien du Git]&lt;br /&gt;
&lt;br /&gt;
= Carte Shield =&lt;br /&gt;
[[Fichier:Carte Recto non soudé.jpg|vignette|left|thumb|350px|Recto de la carte avant soudage des composants]]&lt;br /&gt;
[[Fichier:Verso non solder.jpeg.jpg|vignette|thumb|right|300px|Verso de la carte avant soudage des composants]]&lt;br /&gt;
[[Fichier:Carde shield soudé.jpg|vignette|thumb|center|350px|Photo de la carte avec les composants soudés]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Test==&lt;br /&gt;
=== Allumage de LEDS sur Programmateur AVR ===&lt;br /&gt;
Avant de programmer directement sur le shield, nous avons allumé des LED pour tester la carte. Nous avons directement utilisé le code exemple fourni par l'IDE arduino en adaptant simplement les pins correspondant aux leds. [https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/PicoShield/Programmation/Blink Code du test]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Vid_test_carte_mp4.mp4|vignette|thumb|center|700px|Vidéo de Test des leds]]&lt;br /&gt;
&lt;br /&gt;
=== Lecture de la carte SD ===&lt;br /&gt;
Avant de programmer directement sur le shield, nous avons tester si la carte SD était bien détectée et lue. On a utilisé le code test présent dans l'IDE arduino en adaptant le port utilisé.[https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/PicoShield/Programmation/CardInfo Code du test]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Resultat SD.jpg|vignette|thumb|center|700px|Carte SD bien détéctée]]&lt;br /&gt;
&lt;br /&gt;
=== Connecteurs IDC HE10 ===&lt;br /&gt;
Afin de tester nos connecteur HE10, nous avons utilisé un afficher 7 segments (Sparkfun 7 segments display). Pour pouvoir vérifier leurs fonctionnements nous avons branché l'afficheur sur chaque connecteur tour à tour. Le programme implanté est un simple connecteur à afficher sur l'afficheur. Voici une vidéo du compteur fonctionnant sur un des 5 connecteurs HE10. ([https://learn.sparkfun.com/tutorials/using-the-serial-7-segment-display/all Code ici (section : Example 2 SPI)])&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Se4-5-7segments.mp4|vignette|alt=se4-5-7segments|Test connecteur HE10 avec afficheur 7 segments.|center]]&lt;br /&gt;
== Ordonnanceur ==&lt;br /&gt;
Pour les interruptions de notre ordonnanceur nous avons utilisé la procédure d'initialisation du minuteur avec le Timer1 disponible dans les cours de Mr.Redon en renseignant une période de 20ms. Nous l'avons disposé dans le fichier minuteur.c car nous n'allons plus le modifier pour le reste du projet. Dans un autre fichier process.c (avec process.h), nous allons y mettre nos structures pour les process et leurs états puis une union pour le temps qui le caractérise ainsi que toutes les fonctions associés.&lt;br /&gt;
&lt;br /&gt;
[https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/Ordonnanceur Lien du répertoire]&lt;br /&gt;
&lt;br /&gt;
=== Processus ===&lt;br /&gt;
==== Structure ====&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:right; width: 48%; padding-left: 10px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
    uint16_t adresseDepart;  //adresse de la fonction de départ &lt;br /&gt;
    uint16_t adressePile;       //adresse de la pile d'exécution&lt;br /&gt;
    Etat etat;        &lt;br /&gt;
} Process;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Notre structure caractérisant un processus est définie par les trois champs ci-contre.&lt;br /&gt;
&lt;br /&gt;
Une adresse de départ correspondant à la fonction du processus associé, l'adresse où se situe le processus dans la pile puis l'état de la tâche. Nous avons décidé de faire une structure à part entière compte tenu des multitudes d'états que nous pourrons ajouter pendant la progression du projet.&lt;br /&gt;
&lt;br /&gt;
==== Etat d'un processus ====&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:right; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
typedef union {&lt;br /&gt;
  int sleepingtime;       &lt;br /&gt;
} Time;&lt;br /&gt;
&lt;br /&gt;
typedef struct {&lt;br /&gt;
  int id;&lt;br /&gt;
  Time time;&lt;br /&gt;
} Etat ;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
L'état d'un processus est alors une structure à deux champs (pour l'instant), l'id doit correspondre à un '#DEFINE' pour avoir un sens tandis que nous avons choisi de faire une union pour le temps qui caractérise notre état afin qu'il puisse avoir un nom et type de variable cohérent avec son état.(Ici seulement sleepingtime car seul l'état endormi existe pour le moment)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
  {| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
  |+ Tableau des états&lt;br /&gt;
  |-&lt;br /&gt;
  ! Etat !! ACTIVE !! SLEEPY !! ... !! ...&lt;br /&gt;
  |-&lt;br /&gt;
  | Id || 0 || 1 || ... || ...&lt;br /&gt;
  |}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Procédures principales ====&lt;br /&gt;
&lt;br /&gt;
=== ISR ===&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:right; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
ISR(TIMER1_COMPA_vect, ISR_NAKED)    // Procédure d'interruption&lt;br /&gt;
{&lt;br /&gt;
  TCNT1=0;//reset timer&lt;br /&gt;
  /* Sauvegarde du contexte de la tâche interrompue */&lt;br /&gt;
  portSAVE_REGISTERS();&lt;br /&gt;
   table_process[indice_tache].adressePile = SP;&lt;br /&gt;
  /* Appel à l'ordonnanceur */&lt;br /&gt;
  selectProcess();&lt;br /&gt;
  /* Récupération du contexte de la tâche ré-activée */&lt;br /&gt;
  SP = table_process[indice_tache].adressePile;&lt;br /&gt;
  portRESTORE_REGISTERS();&lt;br /&gt;
  &lt;br /&gt;
  asm volatile ( &amp;quot;reti&amp;quot; );&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
L'ISR est ce qu'il va être executer lors des interruptions toutes les 20 millisecondes. Cela consiste à sauvegarder tous les registres de la tâche qui était en cours avant l'appel de l'ISR pour ensuite passer à la tâche suivante valide (c'est à dire active) sans oublier de charger les registres de la nouvelle tâche.&lt;br /&gt;
&lt;br /&gt;
Nous devons également, à chaque fois avant de changer de tâche, enregistrer le pointeur de pile dans le processus afin de pouvoir revenir là ou elle en est la prochaine fois qu'elle sera appelée. Respectivement, une fois la nouvelle tâche choisie, le pointeur de pile doit prendre l'adresse de là ou en était la tâche avant qu'elle soit interrompue.&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Séléction de processus ====&lt;br /&gt;
Lors de la séléction de processus, nous devons parcourir tous les processus jusqu'au moment où nous en trouvons un actif. Ainsi, il deviendra la tâche que nous traiterons lors du prochain intervalle de 20 ms. A ce stade, à chaque fois que la procédure selectProcess est appelée, nous devons réduire le temps de repos de chaque process endormi de 20 ms. D'autres conditions pourrons être ajoutée si ajout d'état a lieu. (voir l'ajout de selectProcess dans l'ISR)&lt;br /&gt;
&lt;br /&gt;
=== Test ===&lt;br /&gt;
==== Clignotement de deux LED à fréquences indivisibles entre elles ====&lt;br /&gt;
Afin de vérifier la réussite de notre ordonnanceur à fonctionnement tourniquet, nous avons programmer deux simples tâches changeant l'état d'une LED. Une à une fréquence 200ms et l'autre 300ms (avec un _delay_ms).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:left; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void tache1(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTC ^= (1 &amp;lt;&amp;lt; PC0);&lt;br /&gt;
    _delay_ms(300);}}&lt;br /&gt;
void tache2(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTD ^= (1 &amp;lt;&amp;lt; PD7);&lt;br /&gt;
    _delay_ms(200);}}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
[[Fichier:B5_test1.mp4|vignette|alt=test des frequences imprevisibles|test des frequences imprevisibles]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Clignotement grâce à l'état endormi ====&lt;br /&gt;
Nous ajoutons l'état endormi afin que nos tâches ne mettent pas en pause l'ordonnanceur avec un _delay_ms. Pour cela, nous incorporons une fonction makeSleep qui permet de mettre la tâche qui l'appelle dans cet état.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:left; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void makeSleep(int t){&lt;br /&gt;
  table_process[indice_tache].etat.id = SLEEPY;&lt;br /&gt;
  table_process[indice_tache].etat.time.sleepingtime = t;&lt;br /&gt;
  TIMER1_COMPA_vect();}&lt;br /&gt;
void tache1(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTC ^= (1 &amp;lt;&amp;lt; PC0);&lt;br /&gt;
    _delay_ms(300);}}&lt;br /&gt;
void tache3(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTC ^= (1 &amp;lt;&amp;lt; PC3);&lt;br /&gt;
    //_delay_ms(1000);&lt;br /&gt;
    makeSleep(1000);}}&lt;br /&gt;
void tache2(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTD ^= (1 &amp;lt;&amp;lt; PD7);&lt;br /&gt;
    //_delay_ms(1000);&lt;br /&gt;
    makeSleep(700);}}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
[[Fichier:B5_test2.mp4|vignette|alt=test des frequences imprevisibles|test des frequences imprevisibles]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
A noter que la première tâche executée ne doit pas être endormie.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Carte Fille Matrice de touches =&lt;br /&gt;
==Explications générales sur la réalisation de la carte==&lt;br /&gt;
&lt;br /&gt;
Pour concevoir la carte fille dédiée au clavier, nous avons réutilisé un ancien clavier DELL équipé d’une matrice déjà fonctionnelle. L’idée consiste à connecter les sorties de cette matrice directement à notre carte fille à l’aide d’un connecteur adapté.&lt;br /&gt;
&lt;br /&gt;
Cependant, un défi se pose : la matrice du clavier comprend un total de 26 sorties (sans compter les LED et autres signaux). Cela dépasse largement les capacités en nombre de broches d’un ATmega328P.&lt;br /&gt;
&lt;br /&gt;
Pour remédier à ce problème, nous avons mis en place une solution d’encodage. Nous avons utilisé un décodeur (3 vers 8) pour gérer les lignes et trois encodeurs (8 vers 3) pour gérer les colonnes. Les encodeurs sont montés en cascade pour réduire significativement le nombre de broches nécessaires. Cette solution permet de maximiser les ressources du microcontrôleur tout en gérant efficacement les signaux de la matrice.&lt;br /&gt;
&lt;br /&gt;
Nous avons opté pour le décodeur 74HC138D (qui va envoyer un 0 parmi des 1) et trois encodeurs CD4532BM (qui cherche le premier 1 parmi des 0). On sent quand même les problèmes venir petit à petit.&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
[[Fichier:Clavier dell.png||thumb|right|800px|Clavier DELL]]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Connecteur de base clavier dell.png||thumb|left|500px|Carte du clavier DELL]]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Matrice clavier dell.png||thumb|right|800px|Matrice du clavier DELL]]&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Détails des composants ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;ATmega328P&amp;lt;/u&amp;gt;&lt;br /&gt;
* Micro-contrôleur&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;74HC138D&amp;lt;/u&amp;gt;&lt;br /&gt;
* Décodeur : envoie un 0 parmi des 1.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;CD4532BM&amp;lt;/u&amp;gt;&lt;br /&gt;
* Encodeur : Nous avons étudié la datasheet et comment la mise en cascade fonctionne.&lt;br /&gt;
[[Fichier:Cascade.png|vignette|alt=Mise en cascade des encodeurs.|Mise en cascade des encodeurs.]]&lt;br /&gt;
On voit qu'un encodeur possède un bus de sortie de 5 bits. GS -&amp;gt; à l'état haut quand le composant reçoit un 1, 0 sinon. E0 -&amp;gt; à l'état haut quand il reçoit seulement des 0, 1 sinon. Puis Q2, Q1 ,Q0 la représentation binaire de l'entrée donnée.&lt;br /&gt;
&lt;br /&gt;
Afin de les mettre en cascade, il faut relié le E0 d'un premier encodeur au Ei de l'autre. Ensuite, nous allons faire un &amp;quot;OU&amp;quot; entre les GS afin de savoir si un des encodeurs reçoit un 1, puis grâce aux GS des deux premiers encodeurs nous sauront quelle encodeur à reçu le 1 (si les deux sont &amp;amp; 0 alors c'est le troisième). De même, faire une porte &amp;quot;OU&amp;quot; sur Q2, Q1, Q0 afin de réduire le nombre d'entrées/sorties nécessaires.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&amp;lt;u&amp;gt;74LS32&amp;lt;/u&amp;gt;&lt;br /&gt;
* Porte logique Or pour la mise en cascade des encodeurs.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Connecteur HE10&amp;lt;/u&amp;gt;&lt;br /&gt;
* Connecteur pour la liaison PicoShield-CarteFille&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Connecteur de la matrice&amp;lt;/u&amp;gt;&lt;br /&gt;
* Simplement une empreinte que l'on a créé [https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/CF_Clavier/Footprint_KeyboardDell_DJADJA Lien vers la bibliothèque présent sur le git]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;AVR-ISP-6&amp;lt;/u&amp;gt;&lt;br /&gt;
* Programmateur AVR&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;LED_SMD&amp;lt;/u&amp;gt;&lt;br /&gt;
* 3 LEDs&lt;br /&gt;
&lt;br /&gt;
== Hardware ==&lt;br /&gt;
===Kicad===&lt;br /&gt;
[[Fichier:Schematique carte fille clavier dell.png|center|1000px|vignette|Schématique de la carte Fille]]&lt;br /&gt;
&lt;br /&gt;
Pour réaliser la carte fille, nous avions dans un premier temps conçu une carte avec une matrice de touches directement implenter sur celle-ci, mais jugeant que cela était trop simple nous avons été redirigé vers l'utilisation d'une matrice déjà réalisé. Ainsi nous avons avons reutiliser celle d'un vieux clavier dell en créant les empreintes à la bonne taille pour se connecter sur la matrice&lt;br /&gt;
 &lt;br /&gt;
[[Fichier:Pcb recto carte fille clavier dell.png|left|480px|vignette|Avant du PCB]][[Fichier:Pcb verso carte fille clavier dell.png|right|480px|vignette|Arrière du PCB]]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Capture d’écran 2024-11-20 à 12.09.07.png|left|600px|vignette|PCB vue 3D avant]][[Fichier:Capture d’écran 2024-11-20 à 12.09.33.png|right|480px|vignette|PCB vue 3D arrière]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Carte après soudure des composants====&lt;br /&gt;
&lt;br /&gt;
===Différents Problèmes rencontrés===&lt;br /&gt;
Avant même la réception de la carte, alors que nous commençons a essayé d'écrire un premier programme, nous nous rendions compte qu'envoyer un 0 parmi des 1 et de rechercher un 1 parmi des 0 ne fonctionnera pas (logique). Nous avons alors pris la décision de changer le décodeur car il était pour nous plus simple de changer un composant que les trois encodeurs. Nous avons opté pour lui de la même famille, le 74HTC238D.&lt;br /&gt;
&lt;br /&gt;
Dès la réception de la carte, nous avons effectué un premier test avec une simple programmation de LED. Nous nous sommes rapidement aperçus que nous avions configuré deux noms d'étiquettes de reset distinctes sur KiCad : une pour l'AVR (RST) et une pour le connecteur HE-10 (RESET). Cependant, seul le reset du connecteur HE-10 était correctement relié au microcontrôleur. Pour résoudre ce problème, nous avons simplement connecté les deux broches de reset à l'aide d'un fil.&lt;br /&gt;
&lt;br /&gt;
Lors de l'examen initial de notre carte, nous avons également constaté une erreur que nous avions commise. En effet, comme nous avions initialement conçu une matrice de touches sans encodeurs ni décodeurs, il n'était donc pas nécessaire d'intégrer des résistances de pull-up ou de pull-down. Nous avons alors juste rajouter ces composants, or il en résulte que lorsqu'une touche sera pressée, un 1 sera bien envoyé mais pas parmi des 0, parmi des états indéterminé. En général, les états indéterminés, on aime pas trop, surtout quand cela empêche ta carte de pouvoir fonctionner comme voulu. Il a donc été nécessaire d'ajouter des résistances de pull-down sur chaque colonne de notre clavier. Afin de simplifier cette modification, nous avons utilisé des résistances CMS que nous avons positionnées comme des dominos (verticalement), ce qui nous a permis de faire passer un fil de masse directement au-dessus des résistances.&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Resistance pull Up domino.jpg|vignette|Résistances de Pull-down sur les colonnes]]&lt;br /&gt;
&lt;br /&gt;
Une fois tous ces problèmes de base résolus, nous avons enfin pu nous attaquer à la programmation du clavier. Pour vérifier que toutes les touches étaient correctement détectées, nous avons réalisé un petit programme de test ([https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/CF_Clavier/prog/test.c Code du test]). Ce programme nous a permis d’associer chaque LED à un décodeur différent via la broche GS des décodeurs. Ainsi, nous avons pu identifier quelles touches ne répondaient pas. Premièrement, beaucoup de touches ne répondaient pas, moins d'une dizaine. Nous avons alors fait de multiples tests au multimètre sur notre carte mais aussi sur une autre matrice de touches similaire. Une des hypothèses fut qu'il fallait bien étamer les pistes pour permettre la conduction entre la carte et la matrice. Nous avons alors rajouter de l'étain, puis + de touches commençaient à fonctionner. Il fallait alors un nouveau programme de test pour détecter quelles lignes ou colonnes n'étaient pas bien étamés afin de permettre une conduction ([https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/CF_Clavier/prog/detect.c Code de détection]). Il suffisait ainsi de rajouter de l'étain sur les colonnes et les lignes qui ne répondaient pas. Enfin, toutes les touches sont détectées lors de d'une pression !&lt;br /&gt;
&lt;br /&gt;
==Programmation de la carte==&lt;br /&gt;
===Programme de test===&lt;br /&gt;
&lt;br /&gt;
([https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/CF_Clavier/prog/test.c Code du test])&lt;br /&gt;
&lt;br /&gt;
Afin de tester chaque touche de notre matrice, nous avons décidé de faire le programme le plus simple possible en utilisant les broches GS de nos encodeurs. Il n'y a pas d'histoire de ligne ou de colonnes ici, si une touche est pressée alors le GS de l'encodeur ou sa colonne est reliée passera à l'état haut. Une manière très simple de savoir si une touche est utilisable et si nos trois encodeurs sont opérationnels également. Nous avons trois leds pour trois encodeurs, pour chaque encodeur, s'allumera une led spécifique si il reçoit un 1 parmi des 0.&lt;br /&gt;
&lt;br /&gt;
Afin de mettre en place ce système, il nous faut un programme capable de balayer toutes les lignes de notre matrice via un décodeur.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:left; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
int tab_outputs[8][3] = {&lt;br /&gt;
    {0, 0, 0},&lt;br /&gt;
    {1, 0, 0},&lt;br /&gt;
    {0, 1, 0},&lt;br /&gt;
    {1, 1, 0},&lt;br /&gt;
    {0, 0, 1},&lt;br /&gt;
    {1, 0, 1},&lt;br /&gt;
    {0, 1, 1},&lt;br /&gt;
    {1, 1, 1},&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void maj_output(int lig){&lt;br /&gt;
    for (int i = 0 ; i &amp;lt; 3 ; i++){&lt;br /&gt;
        if (tab_outputs[lig][i] == 0){&lt;br /&gt;
            PORTC &amp;amp;= ~(1 &amp;lt;&amp;lt; i);&lt;br /&gt;
        }&lt;br /&gt;
        else if (tab_outputs[lig][i] == 1){&lt;br /&gt;
            PORTC |= (1 &amp;lt;&amp;lt; i);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Fichier:B5_test_matrice.mp4|vignette|alt=test d'une touche pressée |test d'une touche pressée|right|800px]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
Ici, grâce à l'initialisation d'un tableau de la représentation en binaire des chiffres 0 à 7, il suffit de faire une procédure qui prend en paramètre le numéro de ligne souhaitée puis de vérifier dans le tableau quelle sortie mettre à 0 et 1. Nous avions remarqué que mettre les sorties pour les décodeurs sur le même port côte à côte facilite la programmation.&lt;br /&gt;
&lt;br /&gt;
===Programme de détection===&lt;br /&gt;
&lt;br /&gt;
([https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/CF_Clavier/prog/detect.c Code du test])&lt;br /&gt;
&lt;br /&gt;
Dans le projet, nous avons eu des problèmes de lignes et colonnes qui n'était pas conduit entre notre carte et la matrice. Pour les identifier, nous avons mis en place un programme de détection qui lors de la pression d'une touche, va afficher grâce aux leds, de quel encodeur sa colonne régit puis quelle ligne et quelle colonne est activée. Ce programme permet ainsi de diagnostiquer rapidement les problèmes de conduction entre la carte et la matrice en identifiant précisément les correspondances défectueuses. &lt;br /&gt;
&lt;br /&gt;
Pour cela, nous avons imaginer deux fonctions show_ligne et show_colonne, permettant d'afficher sur nos trois leds la ligne et la colonne. Si les leds affichent : double clignotements de la led du milieu  (allumée, éteint, allumé) puis (éteint, allumée, allumée) alors la ligne L6 (voir KiCad) et la 4e colonne du deuxième encodeur sont activées.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:left; width: 48%; padding-left: 25px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void show_ligne(int i){&lt;br /&gt;
    turn_off_leds();&lt;br /&gt;
    for (int bit = 0; bit &amp;lt; 3; bit++){&lt;br /&gt;
        if (tab_outputs[i][bit] == 1) {&lt;br /&gt;
            PORTC |= (1 &amp;lt;&amp;lt; (bit+LED1));&lt;br /&gt;
        }&lt;br /&gt;
        else &lt;br /&gt;
            PORTC &amp;amp;= ~(1 &amp;lt;&amp;lt; (bit+LED1));&lt;br /&gt;
        }&lt;br /&gt;
    _delay_ms(SHOW_TIME);&lt;br /&gt;
    turn_off_leds();&lt;br /&gt;
}}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:right; width: 48%; padding-right: 25px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void show_colonne(){&lt;br /&gt;
    turn_off_leds();&lt;br /&gt;
    for (int i = Q0; i &amp;lt; Q2 + 1 ; i++){&lt;br /&gt;
        if (((inputs &amp;gt;&amp;gt; i) &amp;amp; 1) == 1) {&lt;br /&gt;
            PORTC |= (1 &amp;lt;&amp;lt; (i+LED1));&lt;br /&gt;
        }&lt;br /&gt;
        else &lt;br /&gt;
            PORTC &amp;amp;= ~(1 &amp;lt;&amp;lt; (i+LED1));&lt;br /&gt;
    }&lt;br /&gt;
    _delay_ms(SHOW_TIME);&lt;br /&gt;
    turn_off_leds();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
Les deux fonctions se ressemblent beaucoup, la différence étant que show_ligne va prendre un paramètre un entier selon la ligne que nous voulons afficher alors que colonne va directement regarde dans le bus d'entrées la représentation binaire de la colonne activée. A noter que le fait que les LEDs et Q2, Q1, Q0 sont successivement placés sur le même port rend la programmation plus simple à réaliser.&lt;br /&gt;
&lt;br /&gt;
A noter la présence d'un 'uint8_t inputs;' où l'on va assigner PIND à chaque début d'une boucle, en effet pendant l'afficher l'utilisateur ne reste pas forcément la touche enfoncées ce qui changera les valeurs du bus d'entrée. Il est alors important de sauvegarder l'état de ce bus avant de l'afficher.&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
[[Fichier:B5_test_detect.mp4|vignette|alt=test de la détection d'une touche |test de la détection d'une touche|center|800px]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Ping pong===&lt;br /&gt;
A l'aide des ressources envoyées par Mr.Redon, nous avons de quoi communiquer entre le shield et notre carte fille. Pour cela, nous avons du modifié un tout petit peu les programmes. En effet, nous avons ajouter un #define pour le Chip Select de notre clavier (le bon connecteur HE10 sur lequel nous allons le connecter) afin que ce soit bien lui qui sera sélectionné lors du spi_select et spi_deselect. Le shield va envoyer un 1 en SPI pour indiquer au clavier qu'il est sur écoute et qu'il attend un envoie de la carte fille.&lt;br /&gt;
&lt;br /&gt;
Cette communication va nous permettre de bien mapper toutes nos touches.&lt;br /&gt;
&lt;br /&gt;
Nous avons décidé de faire un tableau en 3 dimensions afin de faciliter le mapping. Pourquoi 3 dimensions ? Nous avons une première dimension pour le numéro de ligne (0 à 7), pour le numéro de colonne (0 à 7) puis pour le numéro d'encodeur (0 à 2). Le bus d'entrée nous donnant un numéro de ligne entre 0 et 7, nous avons trouvé plus facile de procéder de cette manière. Voici un exemple.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:center; width: 48%;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
char tab_touches[8][8][3] = {&lt;br /&gt;
    {{'\0'/*AltGr*/, '\0', '\0'}, {'\0', '\0', '\0'}, {'-', ' ', '\0'}, {'\0'/*Fleche gauche*/, 'b', '\0'}, {'\0'/*Fleche droite*/, '\0', '\0'}, {'\0'/*Fleche bas*/, '\0', '\0'}, {'\0', '\0', '\0'}, {'\0', '!', '\0'}}, &lt;br /&gt;
    {{'\0', 'x', 'w'}, {'\0', 'c', '\0'/*CTRL Droit*/}, {'*', '\n', '\0'}, {'\0'/*Pause*/, 'v', '\0'}, {'/', ',', '\0'}, {'\0'/*Verr Num*/, ';', '\0'}, {'\0'/*Touch window droite*/, ':', '\0'}, {'\0'/*Shift droit*/, '*', '\0'}}, &lt;br /&gt;
    {{'\0'/*Arret*/, 'z', 'a'}, {'\0'/*Options*/, 'e', '\0'}, {'9', '\0', '\0'}, {'\0', 'r', '\0'}, {'8', 'u', '\0'}, {'7', 'i', '\0'}, {'\0', 'o', '\0'}, {'*', 'p', '\0'}}, &lt;br /&gt;
    {{'\0', 's', 'q'}, {'\0'/*Touche window gauche*/, 'd', '\0'}, {'3', '\0', '\0'}, {'\n', 'f', '\0'}, {'2', 'j', '\0'}, {'1', 'k', '\0'}, {'\0', 'l', '\0'}, {'\0', 'm', '\0'}}, &lt;br /&gt;
    {{'\0', '\0', '\0'}, {'\0', '\0', '\0'}, {'\0', '\0', '\0'}, {'\0', '\0', '\0'}, {'\0', '\0', '\0'}, {'\0', '\0', 'w'}, {'\0', '\0', '\0'}, {'\0', '\0', '\0'}}, &lt;br /&gt;
    {{'\0', '&amp;lt;', '\0'}, {'\0', '\0', '\0'}, {'.', '\0', '\0'}, {'\0', 'g', '\0'}, {'0', 'h', '\0'}, {'\0', '\0', '\0'}, {'\0', '\0', '\0'}, {'\0', '%', '\0'}}, &lt;br /&gt;
    {{'\0', '\0'/*MAJ*/, '\0'/*tab*/}, {'\0', '\0'/*F3*/, '\0'}, {'\0', 8, '\0'}, {'\0', 't', '\0'}, {'5', 'y', '\0'}, {'4', '$', '\0'}, {'\0', '\0'/*F7*/, '\0'}, {'\0'/*Shift gauche*/, '^', '\0'}}, &lt;br /&gt;
    {{'\0', '\0'/*F1*/, '\0'/*œ*/}, {'\0', '\0'/*F2*/, '\0'/*CTRL Gauche*/}, {'\0'/*Page haut*/, '\0'/*F9*/, '\0'}, {'\0'/*Debut*/, '(', '\0'}, {'\0'/*Insert*/, '-', '\0'}, {'\0'/*Supp*/, '=', '\0'}, {'t', '\n'/*F8*/, '\0'}, {'g', ')', '\0'}}&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Notre clavier ne supporte pas l'appuie de plusieurs touches en simultané à cause de la présence de décodeurs et d'encodeurs, le shift devient inutilisable, seulement maj est opérationnel. Afin de permettre l'utilisation de altgr, il fonctionnera comme le maj mais les deux ne pourront pas être activés en même temps.&lt;br /&gt;
&lt;br /&gt;
Nous avons tout d'abord mit des valeurs au hasard mais unique dans le tableau, puis nous avons identifié les touches pour une case dans le tableau, nous avons fait ce processus plusieurs fois afin de trouver toutes les cases des touches du clavier dans le tableau. Pour permettre l'utilisation du maj et du altgr, nous avons créer deux autres tableau comme ça, un chacun avec ses touches assignées. Lors de l'envoie, il faut vérifier dans quel mode nous nous trouvons pour envoyer le caractère dans le bon tableau (alt, maj ou classique).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:left; width: 48%; padding-left: 25px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
  while(1)&lt;br /&gt;
  {&lt;br /&gt;
    spi_select();&lt;br /&gt;
    uint8_t r=spi_exch(1);&lt;br /&gt;
    if (r != 1) printf(&amp;quot;%c&amp;quot;,r);&lt;br /&gt;
    spi_deselect();&lt;br /&gt;
    _delay_ms(20);&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:right; width: 48%; padding-right: 25px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void envoyer(){&lt;br /&gt;
    printf(&amp;quot;Clavier attente\n&amp;quot;);&lt;br /&gt;
      uint8_t message=spi_wait();&lt;br /&gt;
      printf(&amp;quot;Clavier reçu %d\n&amp;quot;,message);&lt;br /&gt;
      if (message == 1)&lt;br /&gt;
        spi_sendback(temp);&lt;br /&gt;
      printf(&amp;quot;Clavier retour préparé %d\n&amp;quot;,temp);&lt;br /&gt;
  &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
Ici le shield (à gauche) va envoyer un 1 en SPI pour dire au clavier qu'il est prêt à l'écouter, si il reçoit autre chose qu'un 1 (son propre envoie) alors il l'affiche. Le clavier (à droite) va envoyer son dernier caractère dont la touche a été pressée lorsqu'il reçoit ce fameux 1.&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
[[Fichier:B5_test_pingpong.mp4|vignette|alt=test clavier sur shield (sans démonstration de altgr et maj) |test clavier sur shield (sans démonstration de altgr et maj)|center|800px]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Implémentation dans l'ordonnanceur===&lt;br /&gt;
Pour pouvoir utiliser le clavier avec l'ordonnanceur, il suffit de faire de notre while(1) précédent, une tâche a part entière de notre ordonnanceur. Sur cet exemple on voit l'utilisation du alt et du maj.&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
[[Fichier:B5_test_final.mp4|vignette|alt=test clavier avec ordonnancement |test clavier avec ordonnancement|center|800px]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;/div&gt;</summary>
		<author><name>Adjadjaa</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=Fichier:Resistance_pull_Up_domino.jpg&amp;diff=7355</id>
		<title>Fichier:Resistance pull Up domino.jpg</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=Fichier:Resistance_pull_Up_domino.jpg&amp;diff=7355"/>
		<updated>2025-01-26T15:59:47Z</updated>

		<summary type="html">&lt;p&gt;Adjadjaa : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Resistance pull Up domino&lt;/div&gt;</summary>
		<author><name>Adjadjaa</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-5&amp;diff=7279</id>
		<title>SE4Binome2024-5</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-5&amp;diff=7279"/>
		<updated>2025-01-25T21:45:07Z</updated>

		<summary type="html">&lt;p&gt;Adjadjaa : /* Carte Fille Matrice de touches */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Introduction=&lt;br /&gt;
&lt;br /&gt;
Ce wiki documente le développement d’un pico-ordinateur modulaire. Ce dernier est constitué d’une carte principale, composée d’une carte Shield permettant la connexion des cartes filles, et d’une carte mère (initialement simulée par une Arduino Uno avant sa conception finale). Plusieurs cartes filles sont prévues, chacune remplissant une fonction spécifique : gestion du clavier, affichage, port série, réseau, mémoire de masse et son.&lt;br /&gt;
&lt;br /&gt;
Notre binôme est spécifiquement chargé du développement de la carte fille dédiée au clavier.&lt;br /&gt;
&lt;br /&gt;
Toutes les ressources nécessaires, incluant les codes sources et les schémas, sont disponibles sur le dépôt Git suivant :  [https://gitea.plil.fr/ktouron/se4-djadja-touron_pico.git Lien du Git]&lt;br /&gt;
&lt;br /&gt;
= Carte Shield =&lt;br /&gt;
[[Fichier:Carte Recto non soudé.jpg|vignette|left|thumb|350px|Recto de la carte avant soudage des composants]]&lt;br /&gt;
[[Fichier:Verso non solder.jpeg.jpg|vignette|thumb|right|300px|Verso de la carte avant soudage des composants]]&lt;br /&gt;
[[Fichier:Carde shield soudé.jpg|vignette|thumb|center|350px|Photo de la carte avec les composants soudés]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Test==&lt;br /&gt;
=== Allumage de LEDS sur Programmateur AVR ===&lt;br /&gt;
Avant de programmer directement sur le shield, nous avons allumé des LED pour tester la carte. Nous avons directement utilisé le code exemple fourni par l'IDE arduino en adaptant simplement les pins correspondant aux leds. [https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/PicoShield/Programmation/Blink Code du test]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Vid_test_carte_mp4.mp4|vignette|thumb|center|700px|Vidéo de Test des leds]]&lt;br /&gt;
&lt;br /&gt;
=== Lecture de la carte SD ===&lt;br /&gt;
Avant de programmer directement sur le shield, nous avons tester si la carte SD était bien détectée et lue. On a utilisé le code test présent dans l'IDE arduino en adaptant le port utilisé.[https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/PicoShield/Programmation/CardInfo Code du test]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Resultat SD.jpg|vignette|thumb|center|700px|Carte SD bien détéctée]]&lt;br /&gt;
&lt;br /&gt;
=== Connecteurs IDC HE10 ===&lt;br /&gt;
Afin de tester nos connecteur HE10, nous avons utilisé un afficher 7 segments (Sparkfun 7 segments display). Pour pouvoir vérifier leurs fonctionnements nous avons branché l'afficheur sur chaque connecteur tour à tour. Le programme implanté est un simple connecteur à afficher sur l'afficheur. Voici une vidéo du compteur fonctionnant sur un des 5 connecteurs HE10. ([https://learn.sparkfun.com/tutorials/using-the-serial-7-segment-display/all Code ici (section : Example 2 SPI)])&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Se4-5-7segments.mp4|vignette|alt=se4-5-7segments|Test connecteur HE10 avec afficheur 7 segments.|center]]&lt;br /&gt;
== Ordonnanceur ==&lt;br /&gt;
Pour les interruptions de notre ordonnanceur nous avons utilisé la procédure d'initialisation du minuteur avec le Timer1 disponible dans les cours de Mr.Redon en renseignant une période de 20ms. Nous l'avons disposé dans le fichier minuteur.c car nous n'allons plus le modifier pour le reste du projet. Dans un autre fichier process.c (avec process.h), nous allons y mettre nos structures pour les process et leurs états puis une union pour le temps qui le caractérise ainsi que toutes les fonctions associés.&lt;br /&gt;
&lt;br /&gt;
[https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/Ordonnanceur Lien du répertoire]&lt;br /&gt;
&lt;br /&gt;
=== Processus ===&lt;br /&gt;
==== Structure ====&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:right; width: 48%; padding-left: 10px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
    uint16_t adresseDepart;  //adresse de la fonction de départ &lt;br /&gt;
    uint16_t adressePile;       //adresse de la pile d'exécution&lt;br /&gt;
    Etat etat;        &lt;br /&gt;
} Process;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Notre structure caractérisant un processus est définie par les trois champs ci-contre.&lt;br /&gt;
&lt;br /&gt;
Une adresse de départ correspondant à la fonction du processus associé, l'adresse où se situe le processus dans la pile puis l'état de la tâche. Nous avons décidé de faire une structure à part entière compte tenu des multitudes d'états que nous pourrons ajouter pendant la progression du projet.&lt;br /&gt;
&lt;br /&gt;
==== Etat d'un processus ====&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:right; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
typedef union {&lt;br /&gt;
  int sleepingtime;       &lt;br /&gt;
} Time;&lt;br /&gt;
&lt;br /&gt;
typedef struct {&lt;br /&gt;
  int id;&lt;br /&gt;
  Time time;&lt;br /&gt;
} Etat ;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
L'état d'un processus est alors une structure à deux champs (pour l'instant), l'id doit correspondre à un '#DEFINE' pour avoir un sens tandis que nous avons choisi de faire une union pour le temps qui caractérise notre état afin qu'il puisse avoir un nom et type de variable cohérent avec son état.(Ici seulement sleepingtime car seul l'état endormi existe pour le moment)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
  {| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
  |+ Tableau des états&lt;br /&gt;
  |-&lt;br /&gt;
  ! Etat !! ACTIVE !! SLEEPY !! ... !! ...&lt;br /&gt;
  |-&lt;br /&gt;
  | Id || 0 || 1 || ... || ...&lt;br /&gt;
  |}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Procédures principales ====&lt;br /&gt;
&lt;br /&gt;
=== ISR ===&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:right; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
ISR(TIMER1_COMPA_vect, ISR_NAKED)    // Procédure d'interruption&lt;br /&gt;
{&lt;br /&gt;
  TCNT1=0;//reset timer&lt;br /&gt;
  /* Sauvegarde du contexte de la tâche interrompue */&lt;br /&gt;
  portSAVE_REGISTERS();&lt;br /&gt;
   table_process[indice_tache].adressePile = SP;&lt;br /&gt;
  /* Appel à l'ordonnanceur */&lt;br /&gt;
  selectProcess();&lt;br /&gt;
  /* Récupération du contexte de la tâche ré-activée */&lt;br /&gt;
  SP = table_process[indice_tache].adressePile;&lt;br /&gt;
  portRESTORE_REGISTERS();&lt;br /&gt;
  &lt;br /&gt;
  asm volatile ( &amp;quot;reti&amp;quot; );&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
L'ISR est ce qu'il va être executer lors des interruptions toutes les 20 millisecondes. Cela consiste à sauvegarder tous les registres de la tâche qui était en cours avant l'appel de l'ISR pour ensuite passer à la tâche suivante valide (c'est à dire active) sans oublier de charger les registres de la nouvelle tâche.&lt;br /&gt;
&lt;br /&gt;
Nous devons également, à chaque fois avant de changer de tâche, enregistrer le pointeur de pile dans le processus afin de pouvoir revenir là ou elle en est la prochaine fois qu'elle sera appelée. Respectivement, une fois la nouvelle tâche choisie, le pointeur de pile doit prendre l'adresse de là ou en était la tâche avant qu'elle soit interrompue.&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Séléction de processus ====&lt;br /&gt;
Lors de la séléction de processus, nous devons parcourir tous les processus jusqu'au moment où nous en trouvons un actif. Ainsi, il deviendra la tâche que nous traiterons lors du prochain intervalle de 20 ms. A ce stade, à chaque fois que la procédure selectProcess est appelée, nous devons réduire le temps de repos de chaque process endormi de 20 ms. D'autres conditions pourrons être ajoutée si ajout d'état a lieu.&lt;br /&gt;
&lt;br /&gt;
=== Test ===&lt;br /&gt;
==== Clignotement de deux LED à fréquences indivisibles entre elles ====&lt;br /&gt;
Afin de vérifier la réussite de notre ordonnanceur à fonctionnement tourniquet, nous avons programmer deux simples tâches changeant l'état d'une LED. Une à une fréquence 200ms et l'autre 300ms (avec un _delay_ms).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:left; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void tache1(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTC ^= (1 &amp;lt;&amp;lt; PC0);&lt;br /&gt;
    _delay_ms(300);}}&lt;br /&gt;
void tache2(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTD ^= (1 &amp;lt;&amp;lt; PD7);&lt;br /&gt;
    _delay_ms(200);}}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
[[Fichier:B5_test1.mp4|vignette|alt=test des frequences imprevisibles|test des frequences imprevisibles]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Clignotement grâce à l'état endormi ====&lt;br /&gt;
Nous ajoutons l'état endormi afin que nos tâches ne mettent pas en pause l'ordonnanceur avec un _delay_ms. Pour cela, nous incorporons une fonction makeSleep qui permet de mettre la tâche qui l'appelle dans cet état.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:left; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void makeSleep(int t){&lt;br /&gt;
  table_process[indice_tache].etat.id = SLEEPY;&lt;br /&gt;
  table_process[indice_tache].etat.time.sleepingtime = t;&lt;br /&gt;
  TIMER1_COMPA_vect();}&lt;br /&gt;
void tache1(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTC ^= (1 &amp;lt;&amp;lt; PC0);&lt;br /&gt;
    _delay_ms(300);}}&lt;br /&gt;
void tache3(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTC ^= (1 &amp;lt;&amp;lt; PC3);&lt;br /&gt;
    //_delay_ms(1000);&lt;br /&gt;
    makeSleep(1000);}}&lt;br /&gt;
void tache2(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTD ^= (1 &amp;lt;&amp;lt; PD7);&lt;br /&gt;
    //_delay_ms(1000);&lt;br /&gt;
    makeSleep(700);}}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
[[Fichier:B5_test2.mp4|vignette|alt=test des frequences imprevisibles|test des frequences imprevisibles]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
A noter que la première tâche executée ne doit pas être endormie.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Carte Fille Matrice de touches =&lt;br /&gt;
==Explications générales sur la réalisation de la carte==&lt;br /&gt;
[[Fichier:Clavier dell.png||thumb|right|300px|Clavier DELL]]&lt;br /&gt;
[[Fichier:Matrice clavier dell.png||thumb|right|300px|Matrice du clavier DELL]]&lt;br /&gt;
[[Fichier:Connecteur de base clavier dell.png||thumb|right|200px|Matrice du clavier DELL]]&lt;br /&gt;
&lt;br /&gt;
Pour concevoir la carte fille dédiée au clavier, nous avons réutilisé un ancien clavier DELL équipé d’une matrice déjà fonctionnelle. L’idée consiste à connecter les sorties de cette matrice directement à notre carte fille à l’aide d’un connecteur adapté.&lt;br /&gt;
&lt;br /&gt;
Cependant, un défi se pose : la matrice du clavier comprend un total de 26 sorties (sans compter les LED et autres signaux). Cela dépasse largement les capacités en nombre de broches d’un ATmega328P.&lt;br /&gt;
&lt;br /&gt;
Pour remédier à ce problème, nous avons mis en place une solution d’encodage. Nous avons utilisé un décodeur (3 vers 8) pour gérer les lignes et trois encodeurs (8 vers 3) pour gérer les colonnes. Les encodeurs sont montés en parallèle pour réduire significativement le nombre de broches nécessaires.Cette solution permet de maximiser les ressources du microcontrôleur tout en gérant efficacement les signaux de la matrice.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Détails des composants ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;ATmega328P&amp;lt;/u&amp;gt;&lt;br /&gt;
* Micro-contrôleur&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;74HC138D&amp;lt;/u&amp;gt;&lt;br /&gt;
* Décodeur&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;CD4532BM&amp;lt;/u&amp;gt;&lt;br /&gt;
* Encodeur&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;74LS32&amp;lt;/u&amp;gt;&lt;br /&gt;
* Porte logique Or pour la mise en parallèle des encodeurs&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Connecteur HE10&amp;lt;/u&amp;gt;&lt;br /&gt;
* Connecteur pour la liaison PicoShield-CarteFille&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Connecteur de la matrice&amp;lt;/u&amp;gt;&lt;br /&gt;
* Simplement une empreinte que l'on a créé [https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/CF_Clavier/Footprint_KeyboardDell_DJADJA Lien vers la bibliothèque présent sur le git]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;AVR-ISP-6&amp;lt;/u&amp;gt;&lt;br /&gt;
* Programmateur AVR&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;LED_SMD&amp;lt;/u&amp;gt;&lt;br /&gt;
* 3 LEDs&lt;br /&gt;
&lt;br /&gt;
== Hardware ==&lt;br /&gt;
===Kicad===&lt;br /&gt;
[[Fichier:Schematique carte fille clavier dell.png|center|1000px|vignette|Schématique de la carte Fille]]&lt;br /&gt;
&lt;br /&gt;
Pour réaliser la carte fille, nous avions dans un premier temps conçu une carte avec une matrice de touches directement implenter sur celle-ci, mais jugeant que cela était trop simple nous avons été redirigé vers l'utilisation d'une matrice déjà réalisé. Ainsi nous avons avons reutiliser celle d'un vieux clavier dell en créant les empreintes à la bonne taille pour se connecter sur la matrice&lt;br /&gt;
 &lt;br /&gt;
[[Fichier:Pcb recto carte fille clavier dell.png|left|480px|vignette|Avant du PCB]][[Fichier:Pcb verso carte fille clavier dell.png|right|480px|vignette|Arrière du PCB]]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Capture d’écran 2024-11-20 à 12.09.07.png|left|600px|vignette|PCB vue 3D avant]][[Fichier:Capture d’écran 2024-11-20 à 12.09.33.png|right|480px|vignette|PCB vue 3D arrière]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Carte après soudure des composants====&lt;br /&gt;
&lt;br /&gt;
===Différents Problèmes rencontrés===&lt;br /&gt;
Dès la réception de la carte, nous avons effectué un premier test avec une simple programmation de LED. Nous nous sommes rapidement aperçus que nous avions configuré deux broches de reset distinctes : une pour l'AVR et une pour le connecteur HE-10. Cependant, seul le reset du connecteur HE-10 était correctement relié au microcontrôleur. Pour résoudre ce problème, nous avons simplement connecté les deux broches de reset à l'aide d'un fil.&lt;br /&gt;
&lt;br /&gt;
Lors de l'examen initial de notre carte, nous avons également constaté une erreur que nous avions commise. En effet, comme nous avions initialement conçu une matrice de touches sans encodeurs ni décodeurs, il n'était donc pas nécessaire d'intégrer des résistances de pull-up ou de pull-down. Il a donc été nécessaire d'ajouter des résistances de pull-down sur chaque colonne de notre clavier. Afin de simplifier cette modification, nous avons utilisé des résistances CMS que nous avons positionnées comme des dominos, ce qui nous a permis de faire passer un fil de masse directement au-dessus des résistances.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Une fois tous ces problèmes de base résolus, nous avons enfin pu nous attaquer à la programmation du clavier. Pour vérifier que toutes les touches étaient correctement détectées, nous avons réalisé un petit programme de test ([https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/CF_Clavier/prog/test.c Code du test]). Ce programme nous a permis d’associer chaque LED à un décodeur différent via la broche GS des décodeurs. Ainsi, nous avons pu identifier quelles touches ne répondaient pas.&lt;br /&gt;
&lt;br /&gt;
Ensuite, nous avons analysé les lignes et colonnes communes aux touches défectueuses pour mieux cerner l’origine du problème. À ce stade, nous avons constaté que la majorité des touches n’étaient pas détectées. Après réflexion, nous avons supposé que le problème venait probablement d’une mauvaise interconnexion entre notre carte et la matrice de touches. Pour corriger cela, nous avons soigneusement étamé les pistes afin d’assurer une meilleure conduction. Nous avons répété l’opération 3 à 4 fois pour trouver la quantité idéale d’étain et garantir une connexion fiable.&lt;/div&gt;</summary>
		<author><name>Adjadjaa</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-5&amp;diff=7278</id>
		<title>SE4Binome2024-5</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-5&amp;diff=7278"/>
		<updated>2025-01-25T20:52:46Z</updated>

		<summary type="html">&lt;p&gt;Adjadjaa : /* Hardware */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Introduction=&lt;br /&gt;
&lt;br /&gt;
Ce wiki documente le développement d’un pico-ordinateur modulaire. Ce dernier est constitué d’une carte principale, composée d’une carte Shield permettant la connexion des cartes filles, et d’une carte mère (initialement simulée par une Arduino Uno avant sa conception finale). Plusieurs cartes filles sont prévues, chacune remplissant une fonction spécifique : gestion du clavier, affichage, port série, réseau, mémoire de masse et son.&lt;br /&gt;
&lt;br /&gt;
Notre binôme est spécifiquement chargé du développement de la carte fille dédiée au clavier.&lt;br /&gt;
&lt;br /&gt;
Toutes les ressources nécessaires, incluant les codes sources et les schémas, sont disponibles sur le dépôt Git suivant :  [https://gitea.plil.fr/ktouron/se4-djadja-touron_pico.git Lien du Git]&lt;br /&gt;
&lt;br /&gt;
= Carte Shield =&lt;br /&gt;
[[Fichier:Carte Recto non soudé.jpg|vignette|left|thumb|350px|Recto de la carte avant soudage des composants]]&lt;br /&gt;
[[Fichier:Verso non solder.jpeg.jpg|vignette|thumb|right|300px|Verso de la carte avant soudage des composants]]&lt;br /&gt;
[[Fichier:Carde shield soudé.jpg|vignette|thumb|center|350px|Photo de la carte avec les composants soudés]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Test==&lt;br /&gt;
=== Allumage de LEDS sur Programmateur AVR ===&lt;br /&gt;
Avant de programmer directement sur le shield, nous avons allumé des LED pour tester la carte. Nous avons directement utilisé le code exemple fourni par l'IDE arduino en adaptant simplement les pins correspondant aux leds. [https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/PicoShield/Programmation/Blink Code du test]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Vid_test_carte_mp4.mp4|vignette|thumb|center|700px|Vidéo de Test des leds]]&lt;br /&gt;
&lt;br /&gt;
=== Lecture de la carte SD ===&lt;br /&gt;
Avant de programmer directement sur le shield, nous avons tester si la carte SD était bien détectée et lue. On a utilisé le code test présent dans l'IDE arduino en adaptant le port utilisé.[https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/PicoShield/Programmation/CardInfo Code du test]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Resultat SD.jpg|vignette|thumb|center|700px|Carte SD bien détéctée]]&lt;br /&gt;
&lt;br /&gt;
=== Connecteurs IDC HE10 ===&lt;br /&gt;
Afin de tester nos connecteur HE10, nous avons utilisé un afficher 7 segments (Sparkfun 7 segments display). Pour pouvoir vérifier leurs fonctionnements nous avons branché l'afficheur sur chaque connecteur tour à tour. Le programme implanté est un simple connecteur à afficher sur l'afficheur. Voici une vidéo du compteur fonctionnant sur un des 5 connecteurs HE10. ([https://learn.sparkfun.com/tutorials/using-the-serial-7-segment-display/all Code ici (section : Example 2 SPI)])&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Se4-5-7segments.mp4|vignette|alt=se4-5-7segments|Test connecteur HE10 avec afficheur 7 segments.|center]]&lt;br /&gt;
== Ordonnanceur ==&lt;br /&gt;
Pour les interruptions de notre ordonnanceur nous avons utilisé la procédure d'initialisation du minuteur avec le Timer1 disponible dans les cours de Mr.Redon en renseignant une période de 20ms. Nous l'avons disposé dans le fichier minuteur.c car nous n'allons plus le modifier pour le reste du projet. Dans un autre fichier process.c (avec process.h), nous allons y mettre nos structures pour les process et leurs états puis une union pour le temps qui le caractérise ainsi que toutes les fonctions associés.&lt;br /&gt;
&lt;br /&gt;
[https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/Ordonnanceur Lien du répertoire]&lt;br /&gt;
&lt;br /&gt;
=== Processus ===&lt;br /&gt;
==== Structure ====&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:right; width: 48%; padding-left: 10px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
    uint16_t adresseDepart;  //adresse de la fonction de départ &lt;br /&gt;
    uint16_t adressePile;       //adresse de la pile d'exécution&lt;br /&gt;
    Etat etat;        &lt;br /&gt;
} Process;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Notre structure caractérisant un processus est définie par les trois champs ci-contre.&lt;br /&gt;
&lt;br /&gt;
Une adresse de départ correspondant à la fonction du processus associé, l'adresse où se situe le processus dans la pile puis l'état de la tâche. Nous avons décidé de faire une structure à part entière compte tenu des multitudes d'états que nous pourrons ajouter pendant la progression du projet.&lt;br /&gt;
&lt;br /&gt;
==== Etat d'un processus ====&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:right; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
typedef union {&lt;br /&gt;
  int sleepingtime;       &lt;br /&gt;
} Time;&lt;br /&gt;
&lt;br /&gt;
typedef struct {&lt;br /&gt;
  int id;&lt;br /&gt;
  Time time;&lt;br /&gt;
} Etat ;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
L'état d'un processus est alors une structure à deux champs (pour l'instant), l'id doit correspondre à un '#DEFINE' pour avoir un sens tandis que nous avons choisi de faire une union pour le temps qui caractérise notre état afin qu'il puisse avoir un nom et type de variable cohérent avec son état.(Ici seulement sleepingtime car seul l'état endormi existe pour le moment)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
  {| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
  |+ Tableau des états&lt;br /&gt;
  |-&lt;br /&gt;
  ! Etat !! ACTIVE !! SLEEPY !! ... !! ...&lt;br /&gt;
  |-&lt;br /&gt;
  | Id || 0 || 1 || ... || ...&lt;br /&gt;
  |}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Procédures principales ====&lt;br /&gt;
&lt;br /&gt;
=== ISR ===&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:right; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
ISR(TIMER1_COMPA_vect, ISR_NAKED)    // Procédure d'interruption&lt;br /&gt;
{&lt;br /&gt;
  TCNT1=0;//reset timer&lt;br /&gt;
  /* Sauvegarde du contexte de la tâche interrompue */&lt;br /&gt;
  portSAVE_REGISTERS();&lt;br /&gt;
   table_process[indice_tache].adressePile = SP;&lt;br /&gt;
  /* Appel à l'ordonnanceur */&lt;br /&gt;
  selectProcess();&lt;br /&gt;
  /* Récupération du contexte de la tâche ré-activée */&lt;br /&gt;
  SP = table_process[indice_tache].adressePile;&lt;br /&gt;
  portRESTORE_REGISTERS();&lt;br /&gt;
  &lt;br /&gt;
  asm volatile ( &amp;quot;reti&amp;quot; );&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
L'ISR est ce qu'il va être executer lors des interruptions toutes les 20 millisecondes. Cela consiste à sauvegarder tous les registres de la tâche qui était en cours avant l'appel de l'ISR pour ensuite passer à la tâche suivante valide (c'est à dire active) sans oublier de charger les registres de la nouvelle tâche.&lt;br /&gt;
&lt;br /&gt;
Nous devons également, à chaque fois avant de changer de tâche, enregistrer le pointeur de pile dans le processus afin de pouvoir revenir là ou elle en est la prochaine fois qu'elle sera appelée. Respectivement, une fois la nouvelle tâche choisie, le pointeur de pile doit prendre l'adresse de là ou en était la tâche avant qu'elle soit interrompue.&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Séléction de processus ====&lt;br /&gt;
Lors de la séléction de processus, nous devons parcourir tous les processus jusqu'au moment où nous en trouvons un actif. Ainsi, il deviendra la tâche que nous traiterons lors du prochain intervalle de 20 ms. A ce stade, à chaque fois que la procédure selectProcess est appelée, nous devons réduire le temps de repos de chaque process endormi de 20 ms. D'autres conditions pourrons être ajoutée si ajout d'état a lieu.&lt;br /&gt;
&lt;br /&gt;
=== Test ===&lt;br /&gt;
==== Clignotement de deux LED à fréquences indivisibles entre elles ====&lt;br /&gt;
Afin de vérifier la réussite de notre ordonnanceur à fonctionnement tourniquet, nous avons programmer deux simples tâches changeant l'état d'une LED. Une à une fréquence 200ms et l'autre 300ms (avec un _delay_ms).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:left; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void tache1(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTC ^= (1 &amp;lt;&amp;lt; PC0);&lt;br /&gt;
    _delay_ms(300);}}&lt;br /&gt;
void tache2(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTD ^= (1 &amp;lt;&amp;lt; PD7);&lt;br /&gt;
    _delay_ms(200);}}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
[[Fichier:B5_test1.mp4|vignette|alt=test des frequences imprevisibles|test des frequences imprevisibles]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Clignotement grâce à l'état endormi ====&lt;br /&gt;
Nous ajoutons l'état endormi afin que nos tâches ne mettent pas en pause l'ordonnanceur avec un _delay_ms. Pour cela, nous incorporons une fonction makeSleep qui permet de mettre la tâche qui l'appelle dans cet état.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:left; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void makeSleep(int t){&lt;br /&gt;
  table_process[indice_tache].etat.id = SLEEPY;&lt;br /&gt;
  table_process[indice_tache].etat.time.sleepingtime = t;&lt;br /&gt;
  TIMER1_COMPA_vect();}&lt;br /&gt;
void tache1(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTC ^= (1 &amp;lt;&amp;lt; PC0);&lt;br /&gt;
    _delay_ms(300);}}&lt;br /&gt;
void tache3(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTC ^= (1 &amp;lt;&amp;lt; PC3);&lt;br /&gt;
    //_delay_ms(1000);&lt;br /&gt;
    makeSleep(1000);}}&lt;br /&gt;
void tache2(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTD ^= (1 &amp;lt;&amp;lt; PD7);&lt;br /&gt;
    //_delay_ms(1000);&lt;br /&gt;
    makeSleep(700);}}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
[[Fichier:B5_test2.mp4|vignette|alt=test des frequences imprevisibles|test des frequences imprevisibles]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
A noter que la première tâche executée ne doit pas être endormie.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Carte Fille Matrice de touches =&lt;br /&gt;
==Explications générales sur la réalisation de la carte==&lt;br /&gt;
[[Fichier:Clavier dell.png||thumb|right|300px|Clavier DELL]]&lt;br /&gt;
[[Fichier:Matrice clavier dell.png||thumb|right|300px|Matrice du clavier DELL]]&lt;br /&gt;
[[Fichier:Connecteur de base clavier dell.png||thumb|right|200px|Matrice du clavier DELL]]&lt;br /&gt;
&lt;br /&gt;
Pour concevoir la carte fille dédiée au clavier, nous avons réutilisé un ancien clavier DELL équipé d’une matrice déjà fonctionnelle. L’idée consiste à connecter les sorties de cette matrice directement à notre carte fille à l’aide d’un connecteur adapté.&lt;br /&gt;
&lt;br /&gt;
Cependant, un défi se pose : la matrice du clavier comprend un total de 26 sorties (sans compter les LED et autres signaux). Cela dépasse largement les capacités en nombre de broches d’un ATmega328P.&lt;br /&gt;
&lt;br /&gt;
Pour remédier à ce problème, nous avons mis en place une solution d’encodage. Nous avons utilisé un décodeur (3 vers 8) pour gérer les lignes et trois encodeurs (8 vers 3) pour gérer les colonnes. Les encodeurs sont montés en parallèle pour réduire significativement le nombre de broches nécessaires.Cette solution permet de maximiser les ressources du microcontrôleur tout en gérant efficacement les signaux de la matrice.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Détails des composants ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;ATmega328P&amp;lt;/u&amp;gt;&lt;br /&gt;
* Micro-contrôleur&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;74HC138D&amp;lt;/u&amp;gt;&lt;br /&gt;
* Décodeur&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;CD4532BM&amp;lt;/u&amp;gt;&lt;br /&gt;
* Encodeur&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;74LS32&amp;lt;/u&amp;gt;&lt;br /&gt;
* Porte logique Or pour la mise en parallèle des encodeurs&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Connecteur HE10&amp;lt;/u&amp;gt;&lt;br /&gt;
* Connecteur pour la liaison PicoShield-CarteFille&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Connecteur de la matrice&amp;lt;/u&amp;gt;&lt;br /&gt;
* Simplement une empreinte que l'on a créé [https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/CF_Clavier/Footprint_KeyboardDell_DJADJA Lien vers la bibliothèque présent sur le git]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;AVR-ISP-6&amp;lt;/u&amp;gt;&lt;br /&gt;
* Programmateur AVR&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;LED_SMD&amp;lt;/u&amp;gt;&lt;br /&gt;
* 3 LEDs&lt;br /&gt;
&lt;br /&gt;
== Hardware ==&lt;br /&gt;
===Kicad===&lt;br /&gt;
[[Fichier:Schematique carte fille clavier dell.png|center|1000px|vignette|Schématique de la carte Fille]]&lt;br /&gt;
&lt;br /&gt;
Pour réaliser la carte fille, nous avions dans un premier temps conçu une carte avec une matrice de touches directement implenter sur celle-ci, mais jugeant que cela était trop simple nous avons été redirigé vers l'utilisation d'une matrice déjà réalisé. Ainsi nous avons avons reutiliser celle d'un vieux clavier dell en créant les empreintes à la bonne taille pour se connecter sur la matrice&lt;br /&gt;
 &lt;br /&gt;
[[Fichier:Pcb recto carte fille clavier dell.png|left|480px|vignette|Avant du PCB]][[Fichier:Pcb verso carte fille clavier dell.png|right|480px|vignette|Arrière du PCB]]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Capture d’écran 2024-11-20 à 12.09.07.png|left|600px|vignette|PCB vue 3D avant]][[Fichier:Capture d’écran 2024-11-20 à 12.09.33.png|right|480px|vignette|PCB vue 3D arrière]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Carte après soudure des composants====&lt;/div&gt;</summary>
		<author><name>Adjadjaa</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-5&amp;diff=7001</id>
		<title>SE4Binome2024-5</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-5&amp;diff=7001"/>
		<updated>2024-12-18T13:20:54Z</updated>

		<summary type="html">&lt;p&gt;Adjadjaa : /* Kicad */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Introduction=&lt;br /&gt;
&lt;br /&gt;
Ce wiki documente le développement d’un pico-ordinateur modulaire. Ce dernier est constitué d’une carte principale, composée d’une carte Shield permettant la connexion des cartes filles, et d’une carte mère (initialement simulée par une Arduino Uno avant sa conception finale). Plusieurs cartes filles sont prévues, chacune remplissant une fonction spécifique : gestion du clavier, affichage, port série, réseau, mémoire de masse et son.&lt;br /&gt;
&lt;br /&gt;
Notre binôme est spécifiquement chargé du développement de la carte fille dédiée au clavier.&lt;br /&gt;
&lt;br /&gt;
Toutes les ressources nécessaires, incluant les codes sources et les schémas, sont disponibles sur le dépôt Git suivant :  [https://gitea.plil.fr/ktouron/se4-djadja-touron_pico.git Lien du Git]&lt;br /&gt;
&lt;br /&gt;
= Carte Shield =&lt;br /&gt;
[[Fichier:Carte Recto non soudé.jpg|vignette|left|thumb|350px|Recto de la carte avant soudage des composants]]&lt;br /&gt;
[[Fichier:Verso non solder.jpeg.jpg|vignette|thumb|right|300px|Verso de la carte avant soudage des composants]]&lt;br /&gt;
[[Fichier:Carde shield soudé.jpg|vignette|thumb|center|350px|Photo de la carte avec les composants soudés]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Test==&lt;br /&gt;
=== Allumage de LEDS sur Programmateur AVR ===&lt;br /&gt;
Avant de programmer directement sur le shield, nous avons allumé des LED pour tester la carte. Nous avons directement utilisé le code exemple fourni par l'IDE arduino en adaptant simplement les pins correspondant aux leds. [https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/PicoShield/Programmation/Blink Code du test]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Vid_test_carte_mp4.mp4|vignette|thumb|center|700px|Vidéo de Test des leds]]&lt;br /&gt;
&lt;br /&gt;
=== Lecture de la carte SD ===&lt;br /&gt;
Avant de programmer directement sur le shield, nous avons tester si la carte SD était bien détectée et lue. On a utilisé le code test présent dans l'IDE arduino en adaptant le port utilisé.[https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/PicoShield/Programmation/CardInfo Code du test]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Resultat SD.jpg|vignette|thumb|center|700px|Carte SD bien détéctée]]&lt;br /&gt;
&lt;br /&gt;
=== Connecteurs IDC HE10 ===&lt;br /&gt;
Afin de tester nos connecteur HE10, nous avons utilisé un afficher 7 segments (Sparkfun 7 segments display). Pour pouvoir vérifier leurs fonctionnements nous avons branché l'afficheur sur chaque connecteur tour à tour. Le programme implanté est un simple connecteur à afficher sur l'afficheur. Voici une vidéo du compteur fonctionnant sur un des 5 connecteurs HE10. ([https://learn.sparkfun.com/tutorials/using-the-serial-7-segment-display/all Code ici (section : Example 2 SPI)])&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Se4-5-7segments.mp4|vignette|alt=se4-5-7segments|Test connecteur HE10 avec afficheur 7 segments.|center]]&lt;br /&gt;
== Ordonnanceur ==&lt;br /&gt;
Pour les interruptions de notre ordonnanceur nous avons utilisé la procédure d'initialisation du minuteur avec le Timer1 disponible dans les cours de Mr.Redon en renseignant une période de 20ms. Nous l'avons disposé dans le fichier minuteur.c car nous n'allons plus le modifier pour le reste du projet. Dans un autre fichier process.c (avec process.h), nous allons y mettre nos structures pour les process et leurs états puis une union pour le temps qui le caractérise ainsi que toutes les fonctions associés.&lt;br /&gt;
&lt;br /&gt;
[https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/Ordonnanceur Lien du répertoire]&lt;br /&gt;
&lt;br /&gt;
=== Processus ===&lt;br /&gt;
==== Structure ====&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:right; width: 48%; padding-left: 10px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
    uint16_t adresseDepart;  //adresse de la fonction de départ &lt;br /&gt;
    uint16_t adressePile;       //adresse de la pile d'exécution&lt;br /&gt;
    Etat etat;        &lt;br /&gt;
} Process;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Notre structure caractérisant un processus est définie par les trois champs ci-contre.&lt;br /&gt;
&lt;br /&gt;
Une adresse de départ correspondant à la fonction du processus associé, l'adresse où se situe le processus dans la pile puis l'état de la tâche. Nous avons décidé de faire une structure à part entière compte tenu des multitudes d'états que nous pourrons ajouter pendant la progression du projet.&lt;br /&gt;
&lt;br /&gt;
==== Etat d'un processus ====&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:right; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
typedef union {&lt;br /&gt;
  int sleepingtime;       &lt;br /&gt;
} Time;&lt;br /&gt;
&lt;br /&gt;
typedef struct {&lt;br /&gt;
  int id;&lt;br /&gt;
  Time time;&lt;br /&gt;
} Etat ;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
L'état d'un processus est alors une structure à deux champs (pour l'instant), l'id doit correspondre à un '#DEFINE' pour avoir un sens tandis que nous avons choisi de faire une union pour le temps qui caractérise notre état afin qu'il puisse avoir un nom et type de variable cohérent avec son état.(Ici seulement sleepingtime car seul l'état endormi existe pour le moment)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
  {| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
  |+ Tableau des états&lt;br /&gt;
  |-&lt;br /&gt;
  ! Etat !! ACTIVE !! SLEEPY !! ... !! ...&lt;br /&gt;
  |-&lt;br /&gt;
  | Id || 0 || 1 || ... || ...&lt;br /&gt;
  |}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Procédures principales ====&lt;br /&gt;
&lt;br /&gt;
=== ISR ===&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:right; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
ISR(TIMER1_COMPA_vect, ISR_NAKED)    // Procédure d'interruption&lt;br /&gt;
{&lt;br /&gt;
  TCNT1=0;//reset timer&lt;br /&gt;
  /* Sauvegarde du contexte de la tâche interrompue */&lt;br /&gt;
  portSAVE_REGISTERS();&lt;br /&gt;
   table_process[indice_tache].adressePile = SP;&lt;br /&gt;
  /* Appel à l'ordonnanceur */&lt;br /&gt;
  selectProcess();&lt;br /&gt;
  /* Récupération du contexte de la tâche ré-activée */&lt;br /&gt;
  SP = table_process[indice_tache].adressePile;&lt;br /&gt;
  portRESTORE_REGISTERS();&lt;br /&gt;
  &lt;br /&gt;
  asm volatile ( &amp;quot;reti&amp;quot; );&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
L'ISR est ce qu'il va être executer lors des interruptions toutes les 20 millisecondes. Cela consiste à sauvegarder tous les registres de la tâche qui était en cours avant l'appel de l'ISR pour ensuite passer à la tâche suivante valide (c'est à dire active) sans oublier de charger les registres de la nouvelle tâche.&lt;br /&gt;
&lt;br /&gt;
Nous devons également, à chaque fois avant de changer de tâche, enregistrer le pointeur de pile dans le processus afin de pouvoir revenir là ou elle en est la prochaine fois qu'elle sera appelée. Respectivement, une fois la nouvelle tâche choisie, le pointeur de pile doit prendre l'adresse de là ou en était la tâche avant qu'elle soit interrompue.&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Séléction de processus ====&lt;br /&gt;
Lors de la séléction de processus, nous devons parcourir tous les processus jusqu'au moment où nous en trouvons un actif. Ainsi, il deviendra la tâche que nous traiterons lors du prochain intervalle de 20 ms. A ce stade, à chaque fois que la procédure selectProcess est appelée, nous devons réduire le temps de repos de chaque process endormi de 20 ms. D'autres conditions pourrons être ajoutée si ajout d'état a lieu.&lt;br /&gt;
&lt;br /&gt;
=== Test ===&lt;br /&gt;
==== Clignotement de deux LED à fréquences indivisibles entre elles ====&lt;br /&gt;
Afin de vérifier la réussite de notre ordonnanceur à fonctionnement tourniquet, nous avons programmer deux simples tâches changeant l'état d'une LED. Une à une fréquence 200ms et l'autre 300ms (avec un _delay_ms).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:left; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void tache1(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTC ^= (1 &amp;lt;&amp;lt; PC0);&lt;br /&gt;
    _delay_ms(300);}}&lt;br /&gt;
void tache2(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTD ^= (1 &amp;lt;&amp;lt; PD7);&lt;br /&gt;
    _delay_ms(200);}}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
[[Fichier:B5_test1.mp4|vignette|alt=test des frequences imprevisibles|test des frequences imprevisibles]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Clignotement grâce à l'état endormi ====&lt;br /&gt;
Nous ajoutons l'état endormi afin que nos tâches ne mettent pas en pause l'ordonnanceur avec un _delay_ms. Pour cela, nous incorporons une fonction makeSleep qui permet de mettre la tâche qui l'appelle dans cet état.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:left; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void makeSleep(int t){&lt;br /&gt;
  table_process[indice_tache].etat.id = SLEEPY;&lt;br /&gt;
  table_process[indice_tache].etat.time.sleepingtime = t;&lt;br /&gt;
  TIMER1_COMPA_vect();}&lt;br /&gt;
void tache1(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTC ^= (1 &amp;lt;&amp;lt; PC0);&lt;br /&gt;
    _delay_ms(300);}}&lt;br /&gt;
void tache3(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTC ^= (1 &amp;lt;&amp;lt; PC3);&lt;br /&gt;
    //_delay_ms(1000);&lt;br /&gt;
    makeSleep(1000);}}&lt;br /&gt;
void tache2(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTD ^= (1 &amp;lt;&amp;lt; PD7);&lt;br /&gt;
    //_delay_ms(1000);&lt;br /&gt;
    makeSleep(700);}}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
[[Fichier:B5_test2.mp4|vignette|alt=test des frequences imprevisibles|test des frequences imprevisibles]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
A noter que la première tâche executée ne doit pas être endormie.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Carte Fille Matrice de touches =&lt;br /&gt;
==Explications générales sur la réalisation de la carte==&lt;br /&gt;
[[Fichier:Clavier dell.png||thumb|right|300px|Clavier DELL]]&lt;br /&gt;
[[Fichier:Matrice clavier dell.png||thumb|right|300px|Matrice du clavier DELL]]&lt;br /&gt;
[[Fichier:Connecteur de base clavier dell.png||thumb|right|200px|Matrice du clavier DELL]]&lt;br /&gt;
&lt;br /&gt;
Pour concevoir la carte fille dédiée au clavier, nous avons réutilisé un ancien clavier DELL équipé d’une matrice déjà fonctionnelle. L’idée consiste à connecter les sorties de cette matrice directement à notre carte fille à l’aide d’un connecteur adapté.&lt;br /&gt;
&lt;br /&gt;
Cependant, un défi se pose : la matrice du clavier comprend un total de 26 sorties (sans compter les LED et autres signaux). Cela dépasse largement les capacités en nombre de broches d’un ATmega328P.&lt;br /&gt;
&lt;br /&gt;
Pour remédier à ce problème, nous avons mis en place une solution d’encodage. Nous avons utilisé un décodeur (3 vers 8) pour gérer les lignes et trois encodeurs (8 vers 3) pour gérer les colonnes. Les encodeurs sont montés en parallèle pour réduire significativement le nombre de broches nécessaires.Cette solution permet de maximiser les ressources du microcontrôleur tout en gérant efficacement les signaux de la matrice.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Détails des composants ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;ATmega328P&amp;lt;/u&amp;gt;&lt;br /&gt;
* Micro-contrôleur&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;74HC138D&amp;lt;/u&amp;gt;&lt;br /&gt;
* Décodeur&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;CD4532BM&amp;lt;/u&amp;gt;&lt;br /&gt;
* Encodeur&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;74LS32&amp;lt;/u&amp;gt;&lt;br /&gt;
* Porte logique Or pour la mise en parallèle des encodeurs&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Connecteur HE10&amp;lt;/u&amp;gt;&lt;br /&gt;
* Connecteur pour la liaison PicoShield-CarteFille&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Connecteur de la matrice&amp;lt;/u&amp;gt;&lt;br /&gt;
* Simplement une empreinte que l'on a créé [https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/CF_Clavier/Footprint_KeyboardDell_DJADJA Lien vers la bibliothèque présent sur le git]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;AVR-ISP-6&amp;lt;/u&amp;gt;&lt;br /&gt;
* Programmateur AVR&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;LED_SMD&amp;lt;/u&amp;gt;&lt;br /&gt;
* 3 LEDs&lt;br /&gt;
&lt;br /&gt;
== Hardware ==&lt;br /&gt;
===Kicad===&lt;br /&gt;
[[Fichier:Schematique carte fille clavier dell.png|center|1000px|vignette|Schématique de la carte Fille]]&lt;br /&gt;
&lt;br /&gt;
Pour réaliser la carte fille, nous avions dans un premier temps conçu une carte avec une matrice de touches directement implenter sur celle-ci, mais jugeant que cela était trop simple nous avons été redirigé vers l'utilisation d'une matrice déjà réalisé. Ainsi nous avons avons reutiliser celle d'un vieux clavier dell en créant les empreintes à la bonne taille pour se connecter sur la matrice&lt;br /&gt;
 &lt;br /&gt;
[[Fichier:Pcb recto carte fille clavier dell.png|left|480px|vignette|Avant du PCB]][[Fichier:Pcb verso carte fille clavier dell.png|right|480px|vignette|Arrière du PCB]]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Capture d’écran 2024-11-20 à 12.09.07.png|left|600px|vignette|PCB vue 3D avant]][[Fichier:Capture d’écran 2024-11-20 à 12.09.33.png|right|480px|vignette|PCB vue 3D arrière]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
====Reçu carte vierge====&lt;br /&gt;
&lt;br /&gt;
====Carte après soudure des composants====&lt;/div&gt;</summary>
		<author><name>Adjadjaa</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-5&amp;diff=6873</id>
		<title>SE4Binome2024-5</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-5&amp;diff=6873"/>
		<updated>2024-11-20T11:17:13Z</updated>

		<summary type="html">&lt;p&gt;Adjadjaa : /* Kicad */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Introduction=&lt;br /&gt;
&lt;br /&gt;
Ce wiki documente le développement d’un pico-ordinateur modulaire. Ce dernier est constitué d’une carte principale, composée d’une carte Shield permettant la connexion des cartes filles, et d’une carte mère (initialement simulée par une Arduino Uno avant sa conception finale). Plusieurs cartes filles sont prévues, chacune remplissant une fonction spécifique : gestion du clavier, affichage, port série, réseau, mémoire de masse et son.&lt;br /&gt;
&lt;br /&gt;
Notre binôme est spécifiquement chargé du développement de la carte fille dédiée au clavier.&lt;br /&gt;
&lt;br /&gt;
Toutes les ressources nécessaires, incluant les codes sources et les schémas, sont disponibles sur le dépôt Git suivant :  [https://gitea.plil.fr/ktouron/se4-djadja-touron_pico.git Lien du Git]&lt;br /&gt;
&lt;br /&gt;
= Carte Shield =&lt;br /&gt;
[[Fichier:Carte Recto non soudé.jpg|vignette|left|thumb|350px|Recto de la carte avant soudage des composants]]&lt;br /&gt;
[[Fichier:Verso non solder.jpeg.jpg|vignette|thumb|right|300px|Verso de la carte avant soudage des composants]]&lt;br /&gt;
[[Fichier:Carde shield soudé.jpg|vignette|thumb|center|350px|Photo de la carte avec les composants soudés]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Test==&lt;br /&gt;
=== Allumage de LEDS sur Programmateur AVR ===&lt;br /&gt;
Avant de programmer directement sur le shield, nous avons allumé des LED pour tester la carte. Nous avons directement utilisé le code exemple fourni par l'IDE arduino en adaptant simplement les pins correspondant aux leds. [https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/PicoShield/Programmation/Blink Code du test]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Vid_test_carte_mp4.mp4|vignette|thumb|center|700px|Vidéo de Test des leds]]&lt;br /&gt;
&lt;br /&gt;
=== Lecture de la carte SD ===&lt;br /&gt;
Avant de programmer directement sur le shield, nous avons tester si la carte SD était bien détectée et lue. On a utilisé le code test présent dans l'IDE arduino en adaptant le port utilisé.[https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/PicoShield/Programmation/CardInfo Code du test]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Resultat SD.jpg|vignette|thumb|center|700px|Carte SD bien détéctée]]&lt;br /&gt;
&lt;br /&gt;
=== Connecteurs IDC HE10 ===&lt;br /&gt;
Afin de tester nos connecteur HE10, nous avons utilisé un afficher 7 segments (Sparkfun 7 segments display). Pour pouvoir vérifier leurs fonctionnements nous avons branché l'afficheur sur chaque connecteur tour à tour. Le programme implanté est un simple connecteur à afficher sur l'afficheur. Voici une vidéo du compteur fonctionnant sur un des 5 connecteurs HE10. ([https://learn.sparkfun.com/tutorials/using-the-serial-7-segment-display/all Code ici (section : Example 2 SPI)])&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Se4-5-7segments.mp4|vignette|alt=se4-5-7segments|Test connecteur HE10 avec afficheur 7 segments.|center]]&lt;br /&gt;
== Ordonnanceur ==&lt;br /&gt;
Pour les interruptions de notre ordonnanceur nous avons utilisé la procédure d'initialisation du minuteur avec le Timer1 disponible dans les cours de Mr.Redon en renseignant une période de 20ms. Nous l'avons disposé dans le fichier minuteur.c car nous n'allons plus le modifier pour le reste du projet. Dans un autre fichier process.c (avec process.h), nous allons y mettre nos structures pour les process et leurs états puis une union pour le temps qui le caractérise ainsi que toutes les fonctions associés.&lt;br /&gt;
&lt;br /&gt;
[https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/Ordonnanceur Lien du répertoire]&lt;br /&gt;
&lt;br /&gt;
=== Processus ===&lt;br /&gt;
==== Structure ====&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:right; width: 48%; padding-left: 10px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
    uint16_t adresseDepart;  //adresse de la fonction de départ &lt;br /&gt;
    uint16_t adressePile;       //adresse de la pile d'exécution&lt;br /&gt;
    Etat etat;        &lt;br /&gt;
} Process;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Notre structure caractérisant un processus est définie par les trois champs ci-contre.&lt;br /&gt;
&lt;br /&gt;
Une adresse de départ correspondant à la fonction du processus associé, l'adresse où se situe le processus dans la pile puis l'état de la tâche. Nous avons décidé de faire une structure à part entière compte tenu des multitudes d'états que nous pourrons ajouter pendant la progression du projet.&lt;br /&gt;
&lt;br /&gt;
==== Etat d'un processus ====&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:right; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
typedef union {&lt;br /&gt;
  int sleepingtime;       &lt;br /&gt;
} Time;&lt;br /&gt;
&lt;br /&gt;
typedef struct {&lt;br /&gt;
  int id;&lt;br /&gt;
  Time time;&lt;br /&gt;
} Etat ;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
L'état d'un processus est alors une structure à deux champs (pour l'instant), l'id doit correspondre à un '#DEFINE' pour avoir un sens tandis que nous avons choisi de faire une union pour le temps qui caractérise notre état afin qu'il puisse avoir un nom et type de variable cohérent avec son état.(Ici seulement sleepingtime car seul l'état endormi existe pour le moment)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
  {| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
  |+ Tableau des états&lt;br /&gt;
  |-&lt;br /&gt;
  ! Etat !! ACTIVE !! SLEEPY !! ... !! ...&lt;br /&gt;
  |-&lt;br /&gt;
  | Id || 0 || 1 || ... || ...&lt;br /&gt;
  |}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Procédures principales ====&lt;br /&gt;
&lt;br /&gt;
=== ISR ===&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:right; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
ISR(TIMER1_COMPA_vect, ISR_NAKED)    // Procédure d'interruption&lt;br /&gt;
{&lt;br /&gt;
  TCNT1=0;//reset timer&lt;br /&gt;
  /* Sauvegarde du contexte de la tâche interrompue */&lt;br /&gt;
  portSAVE_REGISTERS();&lt;br /&gt;
   table_process[indice_tache].adressePile = SP;&lt;br /&gt;
  /* Appel à l'ordonnanceur */&lt;br /&gt;
  selectProcess();&lt;br /&gt;
  /* Récupération du contexte de la tâche ré-activée */&lt;br /&gt;
  SP = table_process[indice_tache].adressePile;&lt;br /&gt;
  portRESTORE_REGISTERS();&lt;br /&gt;
  &lt;br /&gt;
  asm volatile ( &amp;quot;reti&amp;quot; );&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
L'ISR est ce qu'il va être executer lors des interruptions toutes les 20 millisecondes. Cela consiste à sauvegarder tous les registres de la tâche qui était en cours avant l'appel de l'ISR pour ensuite passer à la tâche suivante valide (c'est à dire active) sans oublier de charger les registres de la nouvelle tâche.&lt;br /&gt;
&lt;br /&gt;
Nous devons également, à chaque fois avant de changer de tâche, enregistrer le pointeur de pile dans le processus afin de pouvoir revenir là ou elle en est la prochaine fois qu'elle sera appelée. Respectivement, une fois la nouvelle tâche choisie, le pointeur de pile doit prendre l'adresse de là ou en était la tâche avant qu'elle soit interrompue.&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Séléction de processus ====&lt;br /&gt;
Lors de la séléction de processus, nous devons parcourir tous les processus jusqu'au moment où nous en trouvons un actif. Ainsi, il deviendra la tâche que nous traiterons lors du prochain intervalle de 20 ms. A ce stade, à chaque fois que la procédure selectProcess est appelée, nous devons réduire le temps de repos de chaque process endormi de 20 ms. D'autres conditions pourrons être ajoutée si ajout d'état a lieu.&lt;br /&gt;
&lt;br /&gt;
=== Test ===&lt;br /&gt;
==== Clignotement de deux LED à fréquences indivisibles entre elles ====&lt;br /&gt;
Afin de vérifier la réussite de notre ordonnanceur à fonctionnement tourniquet, nous avons programmer deux simples tâches changeant l'état d'une LED. Une à une fréquence 200ms et l'autre 300ms (avec un _delay_ms).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:left; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void tache1(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTC ^= (1 &amp;lt;&amp;lt; PC0);&lt;br /&gt;
    _delay_ms(300);}}&lt;br /&gt;
void tache2(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTD ^= (1 &amp;lt;&amp;lt; PD7);&lt;br /&gt;
    _delay_ms(200);}}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
[[Fichier:B5_test1.mp4|vignette|alt=test des frequences imprevisibles|test des frequences imprevisibles]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Clignotement grâce à l'état endormi ====&lt;br /&gt;
Nous ajoutons l'état endormi afin que nos tâches ne mettent pas en pause l'ordonnanceur avec un _delay_ms. Pour cela, nous incorporons une fonction makeSleep qui permet de mettre la tâche qui l'appelle dans cet état.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:left; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void makeSleep(int t){&lt;br /&gt;
  table_process[indice_tache].etat.id = SLEEPY;&lt;br /&gt;
  table_process[indice_tache].etat.time.sleepingtime = t;&lt;br /&gt;
  TIMER1_COMPA_vect();}&lt;br /&gt;
void tache1(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTC ^= (1 &amp;lt;&amp;lt; PC0);&lt;br /&gt;
    _delay_ms(300);}}&lt;br /&gt;
void tache3(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTC ^= (1 &amp;lt;&amp;lt; PC3);&lt;br /&gt;
    //_delay_ms(1000);&lt;br /&gt;
    makeSleep(1000);}}&lt;br /&gt;
void tache2(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTD ^= (1 &amp;lt;&amp;lt; PD7);&lt;br /&gt;
    //_delay_ms(1000);&lt;br /&gt;
    makeSleep(700);}}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
[[Fichier:B5_test2.mp4|vignette|alt=test des frequences imprevisibles|test des frequences imprevisibles]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
A noter que la première tâche executée ne doit pas être endormie.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Carte Fille Matrice de touches =&lt;br /&gt;
==Explications générales sur la réalisation de la carte==&lt;br /&gt;
[[Fichier:Clavier dell.png||thumb|right|300px|Clavier DELL]]&lt;br /&gt;
[[Fichier:Matrice clavier dell.png||thumb|right|300px|Matrice du clavier DELL]]&lt;br /&gt;
[[Fichier:Connecteur de base clavier dell.png||thumb|right|200px|Matrice du clavier DELL]]&lt;br /&gt;
&lt;br /&gt;
Pour concevoir la carte fille dédiée au clavier, nous avons réutilisé un ancien clavier DELL équipé d’une matrice déjà fonctionnelle. L’idée consiste à connecter les sorties de cette matrice directement à notre carte fille à l’aide d’un connecteur adapté.&lt;br /&gt;
&lt;br /&gt;
Cependant, un défi se pose : la matrice du clavier comprend un total de 26 sorties (sans compter les LED et autres signaux). Cela dépasse largement les capacités en nombre de broches d’un ATmega328P.&lt;br /&gt;
&lt;br /&gt;
Pour remédier à ce problème, nous avons mis en place une solution d’encodage. Nous avons utilisé un décodeur (3 vers 8) pour gérer les lignes et trois encodeurs (8 vers 3) pour gérer les colonnes. Les encodeurs sont montés en parallèle pour réduire significativement le nombre de broches nécessaires.Cette solution permet de maximiser les ressources du microcontrôleur tout en gérant efficacement les signaux de la matrice.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Détails des composants ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;ATmega328P&amp;lt;/u&amp;gt;&lt;br /&gt;
* Micro-contrôleur&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;74HC138D&amp;lt;/u&amp;gt;&lt;br /&gt;
* Décodeur&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;CD4532BM&amp;lt;/u&amp;gt;&lt;br /&gt;
* Encodeur&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;74LS32&amp;lt;/u&amp;gt;&lt;br /&gt;
* Porte logique Or pour la mise en parallèle des encodeurs&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Connecteur HE10&amp;lt;/u&amp;gt;&lt;br /&gt;
* Connecteur pour la liaison PicoShield-CarteFille&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Connecteur de la matrice&amp;lt;/u&amp;gt;&lt;br /&gt;
* Simplement une empreinte que l'on a créé [https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/CF_Clavier/Footprint_KeyboardDell_DJADJA Lien vers la bibliothèque présent sur le git]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;AVR-ISP-6&amp;lt;/u&amp;gt;&lt;br /&gt;
* Programmateur AVR&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;LED_SMD&amp;lt;/u&amp;gt;&lt;br /&gt;
* 3 LEDs&lt;br /&gt;
&lt;br /&gt;
== Hardware ==&lt;br /&gt;
===Kicad===&lt;br /&gt;
[[Fichier:Schematique carte fille clavier dell.png|center|1000px|vignette|Schématique de la carte Fille]]&lt;br /&gt;
&lt;br /&gt;
TEXTE à REMPLIR&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Pcb recto carte fille clavier dell.png|left|480px|vignette|Avant du PCB]][[Fichier:Pcb verso carte fille clavier dell.png|right|480px|vignette|Arrière du PCB]]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Capture d’écran 2024-11-20 à 12.09.07.png|left|600px|vignette|PCB vue 3D avant]][[Fichier:Capture d’écran 2024-11-20 à 12.09.33.png|right|480px|vignette|PCB vue 3D arrière]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
====Reçu carte vierge====&lt;br /&gt;
&lt;br /&gt;
====Carte après soudure des composants====&lt;/div&gt;</summary>
		<author><name>Adjadjaa</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-5&amp;diff=6872</id>
		<title>SE4Binome2024-5</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-5&amp;diff=6872"/>
		<updated>2024-11-20T11:16:30Z</updated>

		<summary type="html">&lt;p&gt;Adjadjaa : /* Kicad */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Introduction=&lt;br /&gt;
&lt;br /&gt;
Ce wiki documente le développement d’un pico-ordinateur modulaire. Ce dernier est constitué d’une carte principale, composée d’une carte Shield permettant la connexion des cartes filles, et d’une carte mère (initialement simulée par une Arduino Uno avant sa conception finale). Plusieurs cartes filles sont prévues, chacune remplissant une fonction spécifique : gestion du clavier, affichage, port série, réseau, mémoire de masse et son.&lt;br /&gt;
&lt;br /&gt;
Notre binôme est spécifiquement chargé du développement de la carte fille dédiée au clavier.&lt;br /&gt;
&lt;br /&gt;
Toutes les ressources nécessaires, incluant les codes sources et les schémas, sont disponibles sur le dépôt Git suivant :  [https://gitea.plil.fr/ktouron/se4-djadja-touron_pico.git Lien du Git]&lt;br /&gt;
&lt;br /&gt;
= Carte Shield =&lt;br /&gt;
[[Fichier:Carte Recto non soudé.jpg|vignette|left|thumb|350px|Recto de la carte avant soudage des composants]]&lt;br /&gt;
[[Fichier:Verso non solder.jpeg.jpg|vignette|thumb|right|300px|Verso de la carte avant soudage des composants]]&lt;br /&gt;
[[Fichier:Carde shield soudé.jpg|vignette|thumb|center|350px|Photo de la carte avec les composants soudés]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Test==&lt;br /&gt;
=== Allumage de LEDS sur Programmateur AVR ===&lt;br /&gt;
Avant de programmer directement sur le shield, nous avons allumé des LED pour tester la carte. Nous avons directement utilisé le code exemple fourni par l'IDE arduino en adaptant simplement les pins correspondant aux leds. [https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/PicoShield/Programmation/Blink Code du test]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Vid_test_carte_mp4.mp4|vignette|thumb|center|700px|Vidéo de Test des leds]]&lt;br /&gt;
&lt;br /&gt;
=== Lecture de la carte SD ===&lt;br /&gt;
Avant de programmer directement sur le shield, nous avons tester si la carte SD était bien détectée et lue. On a utilisé le code test présent dans l'IDE arduino en adaptant le port utilisé.[https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/PicoShield/Programmation/CardInfo Code du test]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Resultat SD.jpg|vignette|thumb|center|700px|Carte SD bien détéctée]]&lt;br /&gt;
&lt;br /&gt;
=== Connecteurs IDC HE10 ===&lt;br /&gt;
Afin de tester nos connecteur HE10, nous avons utilisé un afficher 7 segments (Sparkfun 7 segments display). Pour pouvoir vérifier leurs fonctionnements nous avons branché l'afficheur sur chaque connecteur tour à tour. Le programme implanté est un simple connecteur à afficher sur l'afficheur. Voici une vidéo du compteur fonctionnant sur un des 5 connecteurs HE10. ([https://learn.sparkfun.com/tutorials/using-the-serial-7-segment-display/all Code ici (section : Example 2 SPI)])&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Se4-5-7segments.mp4|vignette|alt=se4-5-7segments|Test connecteur HE10 avec afficheur 7 segments.|center]]&lt;br /&gt;
== Ordonnanceur ==&lt;br /&gt;
Pour les interruptions de notre ordonnanceur nous avons utilisé la procédure d'initialisation du minuteur avec le Timer1 disponible dans les cours de Mr.Redon en renseignant une période de 20ms. Nous l'avons disposé dans le fichier minuteur.c car nous n'allons plus le modifier pour le reste du projet. Dans un autre fichier process.c (avec process.h), nous allons y mettre nos structures pour les process et leurs états puis une union pour le temps qui le caractérise ainsi que toutes les fonctions associés.&lt;br /&gt;
&lt;br /&gt;
[https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/Ordonnanceur Lien du répertoire]&lt;br /&gt;
&lt;br /&gt;
=== Processus ===&lt;br /&gt;
==== Structure ====&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:right; width: 48%; padding-left: 10px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
    uint16_t adresseDepart;  //adresse de la fonction de départ &lt;br /&gt;
    uint16_t adressePile;       //adresse de la pile d'exécution&lt;br /&gt;
    Etat etat;        &lt;br /&gt;
} Process;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Notre structure caractérisant un processus est définie par les trois champs ci-contre.&lt;br /&gt;
&lt;br /&gt;
Une adresse de départ correspondant à la fonction du processus associé, l'adresse où se situe le processus dans la pile puis l'état de la tâche. Nous avons décidé de faire une structure à part entière compte tenu des multitudes d'états que nous pourrons ajouter pendant la progression du projet.&lt;br /&gt;
&lt;br /&gt;
==== Etat d'un processus ====&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:right; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
typedef union {&lt;br /&gt;
  int sleepingtime;       &lt;br /&gt;
} Time;&lt;br /&gt;
&lt;br /&gt;
typedef struct {&lt;br /&gt;
  int id;&lt;br /&gt;
  Time time;&lt;br /&gt;
} Etat ;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
L'état d'un processus est alors une structure à deux champs (pour l'instant), l'id doit correspondre à un '#DEFINE' pour avoir un sens tandis que nous avons choisi de faire une union pour le temps qui caractérise notre état afin qu'il puisse avoir un nom et type de variable cohérent avec son état.(Ici seulement sleepingtime car seul l'état endormi existe pour le moment)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
  {| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
  |+ Tableau des états&lt;br /&gt;
  |-&lt;br /&gt;
  ! Etat !! ACTIVE !! SLEEPY !! ... !! ...&lt;br /&gt;
  |-&lt;br /&gt;
  | Id || 0 || 1 || ... || ...&lt;br /&gt;
  |}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Procédures principales ====&lt;br /&gt;
&lt;br /&gt;
=== ISR ===&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:right; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
ISR(TIMER1_COMPA_vect, ISR_NAKED)    // Procédure d'interruption&lt;br /&gt;
{&lt;br /&gt;
  TCNT1=0;//reset timer&lt;br /&gt;
  /* Sauvegarde du contexte de la tâche interrompue */&lt;br /&gt;
  portSAVE_REGISTERS();&lt;br /&gt;
   table_process[indice_tache].adressePile = SP;&lt;br /&gt;
  /* Appel à l'ordonnanceur */&lt;br /&gt;
  selectProcess();&lt;br /&gt;
  /* Récupération du contexte de la tâche ré-activée */&lt;br /&gt;
  SP = table_process[indice_tache].adressePile;&lt;br /&gt;
  portRESTORE_REGISTERS();&lt;br /&gt;
  &lt;br /&gt;
  asm volatile ( &amp;quot;reti&amp;quot; );&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
L'ISR est ce qu'il va être executer lors des interruptions toutes les 20 millisecondes. Cela consiste à sauvegarder tous les registres de la tâche qui était en cours avant l'appel de l'ISR pour ensuite passer à la tâche suivante valide (c'est à dire active) sans oublier de charger les registres de la nouvelle tâche.&lt;br /&gt;
&lt;br /&gt;
Nous devons également, à chaque fois avant de changer de tâche, enregistrer le pointeur de pile dans le processus afin de pouvoir revenir là ou elle en est la prochaine fois qu'elle sera appelée. Respectivement, une fois la nouvelle tâche choisie, le pointeur de pile doit prendre l'adresse de là ou en était la tâche avant qu'elle soit interrompue.&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Séléction de processus ====&lt;br /&gt;
Lors de la séléction de processus, nous devons parcourir tous les processus jusqu'au moment où nous en trouvons un actif. Ainsi, il deviendra la tâche que nous traiterons lors du prochain intervalle de 20 ms. A ce stade, à chaque fois que la procédure selectProcess est appelée, nous devons réduire le temps de repos de chaque process endormi de 20 ms. D'autres conditions pourrons être ajoutée si ajout d'état a lieu.&lt;br /&gt;
&lt;br /&gt;
=== Test ===&lt;br /&gt;
==== Clignotement de deux LED à fréquences indivisibles entre elles ====&lt;br /&gt;
Afin de vérifier la réussite de notre ordonnanceur à fonctionnement tourniquet, nous avons programmer deux simples tâches changeant l'état d'une LED. Une à une fréquence 200ms et l'autre 300ms (avec un _delay_ms).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:left; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void tache1(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTC ^= (1 &amp;lt;&amp;lt; PC0);&lt;br /&gt;
    _delay_ms(300);}}&lt;br /&gt;
void tache2(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTD ^= (1 &amp;lt;&amp;lt; PD7);&lt;br /&gt;
    _delay_ms(200);}}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
[[Fichier:B5_test1.mp4|vignette|alt=test des frequences imprevisibles|test des frequences imprevisibles]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Clignotement grâce à l'état endormi ====&lt;br /&gt;
Nous ajoutons l'état endormi afin que nos tâches ne mettent pas en pause l'ordonnanceur avec un _delay_ms. Pour cela, nous incorporons une fonction makeSleep qui permet de mettre la tâche qui l'appelle dans cet état.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:left; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void makeSleep(int t){&lt;br /&gt;
  table_process[indice_tache].etat.id = SLEEPY;&lt;br /&gt;
  table_process[indice_tache].etat.time.sleepingtime = t;&lt;br /&gt;
  TIMER1_COMPA_vect();}&lt;br /&gt;
void tache1(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTC ^= (1 &amp;lt;&amp;lt; PC0);&lt;br /&gt;
    _delay_ms(300);}}&lt;br /&gt;
void tache3(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTC ^= (1 &amp;lt;&amp;lt; PC3);&lt;br /&gt;
    //_delay_ms(1000);&lt;br /&gt;
    makeSleep(1000);}}&lt;br /&gt;
void tache2(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTD ^= (1 &amp;lt;&amp;lt; PD7);&lt;br /&gt;
    //_delay_ms(1000);&lt;br /&gt;
    makeSleep(700);}}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
[[Fichier:B5_test2.mp4|vignette|alt=test des frequences imprevisibles|test des frequences imprevisibles]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
A noter que la première tâche executée ne doit pas être endormie.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Carte Fille Matrice de touches =&lt;br /&gt;
==Explications générales sur la réalisation de la carte==&lt;br /&gt;
[[Fichier:Clavier dell.png||thumb|right|300px|Clavier DELL]]&lt;br /&gt;
[[Fichier:Matrice clavier dell.png||thumb|right|300px|Matrice du clavier DELL]]&lt;br /&gt;
[[Fichier:Connecteur de base clavier dell.png||thumb|right|200px|Matrice du clavier DELL]]&lt;br /&gt;
&lt;br /&gt;
Pour concevoir la carte fille dédiée au clavier, nous avons réutilisé un ancien clavier DELL équipé d’une matrice déjà fonctionnelle. L’idée consiste à connecter les sorties de cette matrice directement à notre carte fille à l’aide d’un connecteur adapté.&lt;br /&gt;
&lt;br /&gt;
Cependant, un défi se pose : la matrice du clavier comprend un total de 26 sorties (sans compter les LED et autres signaux). Cela dépasse largement les capacités en nombre de broches d’un ATmega328P.&lt;br /&gt;
&lt;br /&gt;
Pour remédier à ce problème, nous avons mis en place une solution d’encodage. Nous avons utilisé un décodeur (3 vers 8) pour gérer les lignes et trois encodeurs (8 vers 3) pour gérer les colonnes. Les encodeurs sont montés en parallèle pour réduire significativement le nombre de broches nécessaires.Cette solution permet de maximiser les ressources du microcontrôleur tout en gérant efficacement les signaux de la matrice.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Détails des composants ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;ATmega328P&amp;lt;/u&amp;gt;&lt;br /&gt;
* Micro-contrôleur&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;74HC138D&amp;lt;/u&amp;gt;&lt;br /&gt;
* Décodeur&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;CD4532BM&amp;lt;/u&amp;gt;&lt;br /&gt;
* Encodeur&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;74LS32&amp;lt;/u&amp;gt;&lt;br /&gt;
* Porte logique Or pour la mise en parallèle des encodeurs&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Connecteur HE10&amp;lt;/u&amp;gt;&lt;br /&gt;
* Connecteur pour la liaison PicoShield-CarteFille&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Connecteur de la matrice&amp;lt;/u&amp;gt;&lt;br /&gt;
* Simplement une empreinte que l'on a créé [https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/CF_Clavier/Footprint_KeyboardDell_DJADJA Lien vers la bibliothèque présent sur le git]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;AVR-ISP-6&amp;lt;/u&amp;gt;&lt;br /&gt;
* Programmateur AVR&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;LED_SMD&amp;lt;/u&amp;gt;&lt;br /&gt;
* 3 LEDs&lt;br /&gt;
&lt;br /&gt;
== Hardware ==&lt;br /&gt;
===Kicad===&lt;br /&gt;
[[Fichier:Schematique carte fille clavier dell.png|center|1000px|vignette|Schématique de la carte Fille]]&lt;br /&gt;
&lt;br /&gt;
TEXTE à REMPLIR&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Pcb recto carte fille clavier dell.png|left|480px|vignette|Avant du PCB]][[Fichier:Pcb verso carte fille clavier dell.png|right|480px|vignette|Arrière du PCB]]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Capture d’écran 2024-11-20 à 12.09.07.png|left|480px|vignette|PCB vue 3D avant]][[Fichier:Capture d’écran 2024-11-20 à 12.09.33.png|right|480px|vignette|PCB vue 3D arrière]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
====Reçu carte vierge====&lt;br /&gt;
&lt;br /&gt;
====Carte après soudure des composants====&lt;/div&gt;</summary>
		<author><name>Adjadjaa</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=Fichier:Capture_d%E2%80%99%C3%A9cran_2024-11-20_%C3%A0_12.09.33.png&amp;diff=6871</id>
		<title>Fichier:Capture d’écran 2024-11-20 à 12.09.33.png</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=Fichier:Capture_d%E2%80%99%C3%A9cran_2024-11-20_%C3%A0_12.09.33.png&amp;diff=6871"/>
		<updated>2024-11-20T11:15:41Z</updated>

		<summary type="html">&lt;p&gt;Adjadjaa : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;e&lt;/div&gt;</summary>
		<author><name>Adjadjaa</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=Fichier:Capture_d%E2%80%99%C3%A9cran_2024-11-20_%C3%A0_12.09.07.png&amp;diff=6870</id>
		<title>Fichier:Capture d’écran 2024-11-20 à 12.09.07.png</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=Fichier:Capture_d%E2%80%99%C3%A9cran_2024-11-20_%C3%A0_12.09.07.png&amp;diff=6870"/>
		<updated>2024-11-20T11:15:21Z</updated>

		<summary type="html">&lt;p&gt;Adjadjaa : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;e&lt;/div&gt;</summary>
		<author><name>Adjadjaa</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=Fichier:Pcb_verso_carte_fille_clavier_dell.png&amp;diff=6868</id>
		<title>Fichier:Pcb verso carte fille clavier dell.png</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=Fichier:Pcb_verso_carte_fille_clavier_dell.png&amp;diff=6868"/>
		<updated>2024-11-20T11:10:03Z</updated>

		<summary type="html">&lt;p&gt;Adjadjaa : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;pcb verso carte fille clavier dell&lt;/div&gt;</summary>
		<author><name>Adjadjaa</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=Fichier:Pcb_recto_carte_fille_clavier_dell.png&amp;diff=6867</id>
		<title>Fichier:Pcb recto carte fille clavier dell.png</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=Fichier:Pcb_recto_carte_fille_clavier_dell.png&amp;diff=6867"/>
		<updated>2024-11-20T11:09:41Z</updated>

		<summary type="html">&lt;p&gt;Adjadjaa : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;pcb recto carte fille clavier dell&lt;/div&gt;</summary>
		<author><name>Adjadjaa</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-5&amp;diff=6866</id>
		<title>SE4Binome2024-5</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-5&amp;diff=6866"/>
		<updated>2024-11-20T11:07:48Z</updated>

		<summary type="html">&lt;p&gt;Adjadjaa : /* Hardware */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Introduction=&lt;br /&gt;
&lt;br /&gt;
Ce wiki documente le développement d’un pico-ordinateur modulaire. Ce dernier est constitué d’une carte principale, composée d’une carte Shield permettant la connexion des cartes filles, et d’une carte mère (initialement simulée par une Arduino Uno avant sa conception finale). Plusieurs cartes filles sont prévues, chacune remplissant une fonction spécifique : gestion du clavier, affichage, port série, réseau, mémoire de masse et son.&lt;br /&gt;
&lt;br /&gt;
Notre binôme est spécifiquement chargé du développement de la carte fille dédiée au clavier.&lt;br /&gt;
&lt;br /&gt;
Toutes les ressources nécessaires, incluant les codes sources et les schémas, sont disponibles sur le dépôt Git suivant :  [https://gitea.plil.fr/ktouron/se4-djadja-touron_pico.git Lien du Git]&lt;br /&gt;
&lt;br /&gt;
= Carte Shield =&lt;br /&gt;
[[Fichier:Carte Recto non soudé.jpg|vignette|left|thumb|350px|Recto de la carte avant soudage des composants]]&lt;br /&gt;
[[Fichier:Verso non solder.jpeg.jpg|vignette|thumb|right|300px|Verso de la carte avant soudage des composants]]&lt;br /&gt;
[[Fichier:Carde shield soudé.jpg|vignette|thumb|center|350px|Photo de la carte avec les composants soudés]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Test==&lt;br /&gt;
=== Allumage de LEDS sur Programmateur AVR ===&lt;br /&gt;
Avant de programmer directement sur le shield, nous avons allumé des LED pour tester la carte. Nous avons directement utilisé le code exemple fourni par l'IDE arduino en adaptant simplement les pins correspondant aux leds. [https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/PicoShield/Programmation/Blink Code du test]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Vid_test_carte_mp4.mp4|vignette|thumb|center|700px|Vidéo de Test des leds]]&lt;br /&gt;
&lt;br /&gt;
=== Lecture de la carte SD ===&lt;br /&gt;
Avant de programmer directement sur le shield, nous avons tester si la carte SD était bien détectée et lue. On a utilisé le code test présent dans l'IDE arduino en adaptant le port utilisé.[https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/PicoShield/Programmation/CardInfo Code du test]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Resultat SD.jpg|vignette|thumb|center|700px|Carte SD bien détéctée]]&lt;br /&gt;
&lt;br /&gt;
=== Connecteurs IDC HE10 ===&lt;br /&gt;
Afin de tester nos connecteur HE10, nous avons utilisé un afficher 7 segments (Sparkfun 7 segments display). Pour pouvoir vérifier leurs fonctionnements nous avons branché l'afficheur sur chaque connecteur tour à tour. Le programme implanté est un simple connecteur à afficher sur l'afficheur. Voici une vidéo du compteur fonctionnant sur un des 5 connecteurs HE10. ([https://learn.sparkfun.com/tutorials/using-the-serial-7-segment-display/all Code ici (section : Example 2 SPI)])&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Se4-5-7segments.mp4|vignette|alt=se4-5-7segments|Test connecteur HE10 avec afficheur 7 segments.|center]]&lt;br /&gt;
== Ordonnanceur ==&lt;br /&gt;
Pour les interruptions de notre ordonnanceur nous avons utilisé la procédure d'initialisation du minuteur avec le Timer1 disponible dans les cours de Mr.Redon en renseignant une période de 20ms. Nous l'avons disposé dans le fichier minuteur.c car nous n'allons plus le modifier pour le reste du projet. Dans un autre fichier process.c (avec process.h), nous allons y mettre nos structures pour les process et leurs états puis une union pour le temps qui le caractérise ainsi que toutes les fonctions associés.&lt;br /&gt;
&lt;br /&gt;
[https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/Ordonnanceur Lien du répertoire]&lt;br /&gt;
&lt;br /&gt;
=== Processus ===&lt;br /&gt;
==== Structure ====&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:right; width: 48%; padding-left: 10px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
    uint16_t adresseDepart;  //adresse de la fonction de départ &lt;br /&gt;
    uint16_t adressePile;       //adresse de la pile d'exécution&lt;br /&gt;
    Etat etat;        &lt;br /&gt;
} Process;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Notre structure caractérisant un processus est définie par les trois champs ci-contre.&lt;br /&gt;
&lt;br /&gt;
Une adresse de départ correspondant à la fonction du processus associé, l'adresse où se situe le processus dans la pile puis l'état de la tâche. Nous avons décidé de faire une structure à part entière compte tenu des multitudes d'états que nous pourrons ajouter pendant la progression du projet.&lt;br /&gt;
&lt;br /&gt;
==== Etat d'un processus ====&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:right; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
typedef union {&lt;br /&gt;
  int sleepingtime;       &lt;br /&gt;
} Time;&lt;br /&gt;
&lt;br /&gt;
typedef struct {&lt;br /&gt;
  int id;&lt;br /&gt;
  Time time;&lt;br /&gt;
} Etat ;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
L'état d'un processus est alors une structure à deux champs (pour l'instant), l'id doit correspondre à un '#DEFINE' pour avoir un sens tandis que nous avons choisi de faire une union pour le temps qui caractérise notre état afin qu'il puisse avoir un nom et type de variable cohérent avec son état.(Ici seulement sleepingtime car seul l'état endormi existe pour le moment)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
  {| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
  |+ Tableau des états&lt;br /&gt;
  |-&lt;br /&gt;
  ! Etat !! ACTIVE !! SLEEPY !! ... !! ...&lt;br /&gt;
  |-&lt;br /&gt;
  | Id || 0 || 1 || ... || ...&lt;br /&gt;
  |}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Procédures principales ====&lt;br /&gt;
&lt;br /&gt;
=== ISR ===&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:right; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
ISR(TIMER1_COMPA_vect, ISR_NAKED)    // Procédure d'interruption&lt;br /&gt;
{&lt;br /&gt;
  TCNT1=0;//reset timer&lt;br /&gt;
  /* Sauvegarde du contexte de la tâche interrompue */&lt;br /&gt;
  portSAVE_REGISTERS();&lt;br /&gt;
   table_process[indice_tache].adressePile = SP;&lt;br /&gt;
  /* Appel à l'ordonnanceur */&lt;br /&gt;
  selectProcess();&lt;br /&gt;
  /* Récupération du contexte de la tâche ré-activée */&lt;br /&gt;
  SP = table_process[indice_tache].adressePile;&lt;br /&gt;
  portRESTORE_REGISTERS();&lt;br /&gt;
  &lt;br /&gt;
  asm volatile ( &amp;quot;reti&amp;quot; );&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
L'ISR est ce qu'il va être executer lors des interruptions toutes les 20 millisecondes. Cela consiste à sauvegarder tous les registres de la tâche qui était en cours avant l'appel de l'ISR pour ensuite passer à la tâche suivante valide (c'est à dire active) sans oublier de charger les registres de la nouvelle tâche.&lt;br /&gt;
&lt;br /&gt;
Nous devons également, à chaque fois avant de changer de tâche, enregistrer le pointeur de pile dans le processus afin de pouvoir revenir là ou elle en est la prochaine fois qu'elle sera appelée. Respectivement, une fois la nouvelle tâche choisie, le pointeur de pile doit prendre l'adresse de là ou en était la tâche avant qu'elle soit interrompue.&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Séléction de processus ====&lt;br /&gt;
Lors de la séléction de processus, nous devons parcourir tous les processus jusqu'au moment où nous en trouvons un actif. Ainsi, il deviendra la tâche que nous traiterons lors du prochain intervalle de 20 ms. A ce stade, à chaque fois que la procédure selectProcess est appelée, nous devons réduire le temps de repos de chaque process endormi de 20 ms. D'autres conditions pourrons être ajoutée si ajout d'état a lieu.&lt;br /&gt;
&lt;br /&gt;
=== Test ===&lt;br /&gt;
==== Clignotement de deux LED à fréquences indivisibles entre elles ====&lt;br /&gt;
Afin de vérifier la réussite de notre ordonnanceur à fonctionnement tourniquet, nous avons programmer deux simples tâches changeant l'état d'une LED. Une à une fréquence 200ms et l'autre 300ms (avec un _delay_ms).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:left; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void tache1(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTC ^= (1 &amp;lt;&amp;lt; PC0);&lt;br /&gt;
    _delay_ms(300);}}&lt;br /&gt;
void tache2(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTD ^= (1 &amp;lt;&amp;lt; PD7);&lt;br /&gt;
    _delay_ms(200);}}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
[[Fichier:B5_test1.mp4|vignette|alt=test des frequences imprevisibles|test des frequences imprevisibles]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Clignotement grâce à l'état endormi ====&lt;br /&gt;
Nous ajoutons l'état endormi afin que nos tâches ne mettent pas en pause l'ordonnanceur avec un _delay_ms. Pour cela, nous incorporons une fonction makeSleep qui permet de mettre la tâche qui l'appelle dans cet état.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:left; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void makeSleep(int t){&lt;br /&gt;
  table_process[indice_tache].etat.id = SLEEPY;&lt;br /&gt;
  table_process[indice_tache].etat.time.sleepingtime = t;&lt;br /&gt;
  TIMER1_COMPA_vect();}&lt;br /&gt;
void tache1(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTC ^= (1 &amp;lt;&amp;lt; PC0);&lt;br /&gt;
    _delay_ms(300);}}&lt;br /&gt;
void tache3(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTC ^= (1 &amp;lt;&amp;lt; PC3);&lt;br /&gt;
    //_delay_ms(1000);&lt;br /&gt;
    makeSleep(1000);}}&lt;br /&gt;
void tache2(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTD ^= (1 &amp;lt;&amp;lt; PD7);&lt;br /&gt;
    //_delay_ms(1000);&lt;br /&gt;
    makeSleep(700);}}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
[[Fichier:B5_test2.mp4|vignette|alt=test des frequences imprevisibles|test des frequences imprevisibles]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
A noter que la première tâche executée ne doit pas être endormie.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Carte Fille Matrice de touches =&lt;br /&gt;
==Explications générales sur la réalisation de la carte==&lt;br /&gt;
[[Fichier:Clavier dell.png||thumb|right|300px|Clavier DELL]]&lt;br /&gt;
[[Fichier:Matrice clavier dell.png||thumb|right|300px|Matrice du clavier DELL]]&lt;br /&gt;
[[Fichier:Connecteur de base clavier dell.png||thumb|right|200px|Matrice du clavier DELL]]&lt;br /&gt;
&lt;br /&gt;
Pour concevoir la carte fille dédiée au clavier, nous avons réutilisé un ancien clavier DELL équipé d’une matrice déjà fonctionnelle. L’idée consiste à connecter les sorties de cette matrice directement à notre carte fille à l’aide d’un connecteur adapté.&lt;br /&gt;
&lt;br /&gt;
Cependant, un défi se pose : la matrice du clavier comprend un total de 26 sorties (sans compter les LED et autres signaux). Cela dépasse largement les capacités en nombre de broches d’un ATmega328P.&lt;br /&gt;
&lt;br /&gt;
Pour remédier à ce problème, nous avons mis en place une solution d’encodage. Nous avons utilisé un décodeur (3 vers 8) pour gérer les lignes et trois encodeurs (8 vers 3) pour gérer les colonnes. Les encodeurs sont montés en parallèle pour réduire significativement le nombre de broches nécessaires.Cette solution permet de maximiser les ressources du microcontrôleur tout en gérant efficacement les signaux de la matrice.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Détails des composants ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;ATmega328P&amp;lt;/u&amp;gt;&lt;br /&gt;
* Micro-contrôleur&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;74HC138D&amp;lt;/u&amp;gt;&lt;br /&gt;
* Décodeur&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;CD4532BM&amp;lt;/u&amp;gt;&lt;br /&gt;
* Encodeur&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;74LS32&amp;lt;/u&amp;gt;&lt;br /&gt;
* Porte logique Or pour la mise en parallèle des encodeurs&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Connecteur HE10&amp;lt;/u&amp;gt;&lt;br /&gt;
* Connecteur pour la liaison PicoShield-CarteFille&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Connecteur de la matrice&amp;lt;/u&amp;gt;&lt;br /&gt;
* Simplement une empreinte que l'on a créé [https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/CF_Clavier/Footprint_KeyboardDell_DJADJA Lien vers la bibliothèque présent sur le git]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;AVR-ISP-6&amp;lt;/u&amp;gt;&lt;br /&gt;
* Programmateur AVR&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;LED_SMD&amp;lt;/u&amp;gt;&lt;br /&gt;
* 3 LEDs&lt;br /&gt;
&lt;br /&gt;
== Hardware ==&lt;br /&gt;
===Kicad===&lt;br /&gt;
[[Fichier:Schematique carte fille clavier dell.png|center|1000px|vignette|Schématique de la carte Fille]]&lt;br /&gt;
====Reçu carte vierge====&lt;br /&gt;
&lt;br /&gt;
====Carte après soudure des composants====&lt;/div&gt;</summary>
		<author><name>Adjadjaa</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=Fichier:Schematique_carte_fille_clavier_dell.png&amp;diff=6865</id>
		<title>Fichier:Schematique carte fille clavier dell.png</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=Fichier:Schematique_carte_fille_clavier_dell.png&amp;diff=6865"/>
		<updated>2024-11-20T11:07:03Z</updated>

		<summary type="html">&lt;p&gt;Adjadjaa : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Schematique carte fille clavier dell&lt;/div&gt;</summary>
		<author><name>Adjadjaa</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-5&amp;diff=6864</id>
		<title>SE4Binome2024-5</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-5&amp;diff=6864"/>
		<updated>2024-11-20T11:05:37Z</updated>

		<summary type="html">&lt;p&gt;Adjadjaa : /* Détails des composants */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Introduction=&lt;br /&gt;
&lt;br /&gt;
Ce wiki documente le développement d’un pico-ordinateur modulaire. Ce dernier est constitué d’une carte principale, composée d’une carte Shield permettant la connexion des cartes filles, et d’une carte mère (initialement simulée par une Arduino Uno avant sa conception finale). Plusieurs cartes filles sont prévues, chacune remplissant une fonction spécifique : gestion du clavier, affichage, port série, réseau, mémoire de masse et son.&lt;br /&gt;
&lt;br /&gt;
Notre binôme est spécifiquement chargé du développement de la carte fille dédiée au clavier.&lt;br /&gt;
&lt;br /&gt;
Toutes les ressources nécessaires, incluant les codes sources et les schémas, sont disponibles sur le dépôt Git suivant :  [https://gitea.plil.fr/ktouron/se4-djadja-touron_pico.git Lien du Git]&lt;br /&gt;
&lt;br /&gt;
= Carte Shield =&lt;br /&gt;
[[Fichier:Carte Recto non soudé.jpg|vignette|left|thumb|350px|Recto de la carte avant soudage des composants]]&lt;br /&gt;
[[Fichier:Verso non solder.jpeg.jpg|vignette|thumb|right|300px|Verso de la carte avant soudage des composants]]&lt;br /&gt;
[[Fichier:Carde shield soudé.jpg|vignette|thumb|center|350px|Photo de la carte avec les composants soudés]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Test==&lt;br /&gt;
=== Allumage de LEDS sur Programmateur AVR ===&lt;br /&gt;
Avant de programmer directement sur le shield, nous avons allumé des LED pour tester la carte. Nous avons directement utilisé le code exemple fourni par l'IDE arduino en adaptant simplement les pins correspondant aux leds. [https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/PicoShield/Programmation/Blink Code du test]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Vid_test_carte_mp4.mp4|vignette|thumb|center|700px|Vidéo de Test des leds]]&lt;br /&gt;
&lt;br /&gt;
=== Lecture de la carte SD ===&lt;br /&gt;
Avant de programmer directement sur le shield, nous avons tester si la carte SD était bien détectée et lue. On a utilisé le code test présent dans l'IDE arduino en adaptant le port utilisé.[https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/PicoShield/Programmation/CardInfo Code du test]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Resultat SD.jpg|vignette|thumb|center|700px|Carte SD bien détéctée]]&lt;br /&gt;
&lt;br /&gt;
=== Connecteurs IDC HE10 ===&lt;br /&gt;
Afin de tester nos connecteur HE10, nous avons utilisé un afficher 7 segments (Sparkfun 7 segments display). Pour pouvoir vérifier leurs fonctionnements nous avons branché l'afficheur sur chaque connecteur tour à tour. Le programme implanté est un simple connecteur à afficher sur l'afficheur. Voici une vidéo du compteur fonctionnant sur un des 5 connecteurs HE10. ([https://learn.sparkfun.com/tutorials/using-the-serial-7-segment-display/all Code ici (section : Example 2 SPI)])&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Se4-5-7segments.mp4|vignette|alt=se4-5-7segments|Test connecteur HE10 avec afficheur 7 segments.|center]]&lt;br /&gt;
== Ordonnanceur ==&lt;br /&gt;
Pour les interruptions de notre ordonnanceur nous avons utilisé la procédure d'initialisation du minuteur avec le Timer1 disponible dans les cours de Mr.Redon en renseignant une période de 20ms. Nous l'avons disposé dans le fichier minuteur.c car nous n'allons plus le modifier pour le reste du projet. Dans un autre fichier process.c (avec process.h), nous allons y mettre nos structures pour les process et leurs états puis une union pour le temps qui le caractérise ainsi que toutes les fonctions associés.&lt;br /&gt;
&lt;br /&gt;
[https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/Ordonnanceur Lien du répertoire]&lt;br /&gt;
&lt;br /&gt;
=== Processus ===&lt;br /&gt;
==== Structure ====&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:right; width: 48%; padding-left: 10px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
    uint16_t adresseDepart;  //adresse de la fonction de départ &lt;br /&gt;
    uint16_t adressePile;       //adresse de la pile d'exécution&lt;br /&gt;
    Etat etat;        &lt;br /&gt;
} Process;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Notre structure caractérisant un processus est définie par les trois champs ci-contre.&lt;br /&gt;
&lt;br /&gt;
Une adresse de départ correspondant à la fonction du processus associé, l'adresse où se situe le processus dans la pile puis l'état de la tâche. Nous avons décidé de faire une structure à part entière compte tenu des multitudes d'états que nous pourrons ajouter pendant la progression du projet.&lt;br /&gt;
&lt;br /&gt;
==== Etat d'un processus ====&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:right; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
typedef union {&lt;br /&gt;
  int sleepingtime;       &lt;br /&gt;
} Time;&lt;br /&gt;
&lt;br /&gt;
typedef struct {&lt;br /&gt;
  int id;&lt;br /&gt;
  Time time;&lt;br /&gt;
} Etat ;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
L'état d'un processus est alors une structure à deux champs (pour l'instant), l'id doit correspondre à un '#DEFINE' pour avoir un sens tandis que nous avons choisi de faire une union pour le temps qui caractérise notre état afin qu'il puisse avoir un nom et type de variable cohérent avec son état.(Ici seulement sleepingtime car seul l'état endormi existe pour le moment)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
  {| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
  |+ Tableau des états&lt;br /&gt;
  |-&lt;br /&gt;
  ! Etat !! ACTIVE !! SLEEPY !! ... !! ...&lt;br /&gt;
  |-&lt;br /&gt;
  | Id || 0 || 1 || ... || ...&lt;br /&gt;
  |}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Procédures principales ====&lt;br /&gt;
&lt;br /&gt;
=== ISR ===&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:right; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
ISR(TIMER1_COMPA_vect, ISR_NAKED)    // Procédure d'interruption&lt;br /&gt;
{&lt;br /&gt;
  TCNT1=0;//reset timer&lt;br /&gt;
  /* Sauvegarde du contexte de la tâche interrompue */&lt;br /&gt;
  portSAVE_REGISTERS();&lt;br /&gt;
   table_process[indice_tache].adressePile = SP;&lt;br /&gt;
  /* Appel à l'ordonnanceur */&lt;br /&gt;
  selectProcess();&lt;br /&gt;
  /* Récupération du contexte de la tâche ré-activée */&lt;br /&gt;
  SP = table_process[indice_tache].adressePile;&lt;br /&gt;
  portRESTORE_REGISTERS();&lt;br /&gt;
  &lt;br /&gt;
  asm volatile ( &amp;quot;reti&amp;quot; );&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
L'ISR est ce qu'il va être executer lors des interruptions toutes les 20 millisecondes. Cela consiste à sauvegarder tous les registres de la tâche qui était en cours avant l'appel de l'ISR pour ensuite passer à la tâche suivante valide (c'est à dire active) sans oublier de charger les registres de la nouvelle tâche.&lt;br /&gt;
&lt;br /&gt;
Nous devons également, à chaque fois avant de changer de tâche, enregistrer le pointeur de pile dans le processus afin de pouvoir revenir là ou elle en est la prochaine fois qu'elle sera appelée. Respectivement, une fois la nouvelle tâche choisie, le pointeur de pile doit prendre l'adresse de là ou en était la tâche avant qu'elle soit interrompue.&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Séléction de processus ====&lt;br /&gt;
Lors de la séléction de processus, nous devons parcourir tous les processus jusqu'au moment où nous en trouvons un actif. Ainsi, il deviendra la tâche que nous traiterons lors du prochain intervalle de 20 ms. A ce stade, à chaque fois que la procédure selectProcess est appelée, nous devons réduire le temps de repos de chaque process endormi de 20 ms. D'autres conditions pourrons être ajoutée si ajout d'état a lieu.&lt;br /&gt;
&lt;br /&gt;
=== Test ===&lt;br /&gt;
==== Clignotement de deux LED à fréquences indivisibles entre elles ====&lt;br /&gt;
Afin de vérifier la réussite de notre ordonnanceur à fonctionnement tourniquet, nous avons programmer deux simples tâches changeant l'état d'une LED. Une à une fréquence 200ms et l'autre 300ms (avec un _delay_ms).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:left; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void tache1(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTC ^= (1 &amp;lt;&amp;lt; PC0);&lt;br /&gt;
    _delay_ms(300);}}&lt;br /&gt;
void tache2(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTD ^= (1 &amp;lt;&amp;lt; PD7);&lt;br /&gt;
    _delay_ms(200);}}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
[[Fichier:B5_test1.mp4|vignette|alt=test des frequences imprevisibles|test des frequences imprevisibles]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Clignotement grâce à l'état endormi ====&lt;br /&gt;
Nous ajoutons l'état endormi afin que nos tâches ne mettent pas en pause l'ordonnanceur avec un _delay_ms. Pour cela, nous incorporons une fonction makeSleep qui permet de mettre la tâche qui l'appelle dans cet état.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:left; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void makeSleep(int t){&lt;br /&gt;
  table_process[indice_tache].etat.id = SLEEPY;&lt;br /&gt;
  table_process[indice_tache].etat.time.sleepingtime = t;&lt;br /&gt;
  TIMER1_COMPA_vect();}&lt;br /&gt;
void tache1(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTC ^= (1 &amp;lt;&amp;lt; PC0);&lt;br /&gt;
    _delay_ms(300);}}&lt;br /&gt;
void tache3(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTC ^= (1 &amp;lt;&amp;lt; PC3);&lt;br /&gt;
    //_delay_ms(1000);&lt;br /&gt;
    makeSleep(1000);}}&lt;br /&gt;
void tache2(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTD ^= (1 &amp;lt;&amp;lt; PD7);&lt;br /&gt;
    //_delay_ms(1000);&lt;br /&gt;
    makeSleep(700);}}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
[[Fichier:B5_test2.mp4|vignette|alt=test des frequences imprevisibles|test des frequences imprevisibles]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
A noter que la première tâche executée ne doit pas être endormie.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Carte Fille Matrice de touches =&lt;br /&gt;
==Explications générales sur la réalisation de la carte==&lt;br /&gt;
[[Fichier:Clavier dell.png||thumb|right|300px|Clavier DELL]]&lt;br /&gt;
[[Fichier:Matrice clavier dell.png||thumb|right|300px|Matrice du clavier DELL]]&lt;br /&gt;
[[Fichier:Connecteur de base clavier dell.png||thumb|right|200px|Matrice du clavier DELL]]&lt;br /&gt;
&lt;br /&gt;
Pour concevoir la carte fille dédiée au clavier, nous avons réutilisé un ancien clavier DELL équipé d’une matrice déjà fonctionnelle. L’idée consiste à connecter les sorties de cette matrice directement à notre carte fille à l’aide d’un connecteur adapté.&lt;br /&gt;
&lt;br /&gt;
Cependant, un défi se pose : la matrice du clavier comprend un total de 26 sorties (sans compter les LED et autres signaux). Cela dépasse largement les capacités en nombre de broches d’un ATmega328P.&lt;br /&gt;
&lt;br /&gt;
Pour remédier à ce problème, nous avons mis en place une solution d’encodage. Nous avons utilisé un décodeur (3 vers 8) pour gérer les lignes et trois encodeurs (8 vers 3) pour gérer les colonnes. Les encodeurs sont montés en parallèle pour réduire significativement le nombre de broches nécessaires.Cette solution permet de maximiser les ressources du microcontrôleur tout en gérant efficacement les signaux de la matrice.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Détails des composants ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;ATmega328P&amp;lt;/u&amp;gt;&lt;br /&gt;
* Micro-contrôleur&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;74HC138D&amp;lt;/u&amp;gt;&lt;br /&gt;
* Décodeur&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;CD4532BM&amp;lt;/u&amp;gt;&lt;br /&gt;
* Encodeur&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;74LS32&amp;lt;/u&amp;gt;&lt;br /&gt;
* Porte logique Or pour la mise en parallèle des encodeurs&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Connecteur HE10&amp;lt;/u&amp;gt;&lt;br /&gt;
* Connecteur pour la liaison PicoShield-CarteFille&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Connecteur de la matrice&amp;lt;/u&amp;gt;&lt;br /&gt;
* Simplement une empreinte que l'on a créé [https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/CF_Clavier/Footprint_KeyboardDell_DJADJA Lien vers la bibliothèque présent sur le git]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;AVR-ISP-6&amp;lt;/u&amp;gt;&lt;br /&gt;
* Programmateur AVR&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;LED_SMD&amp;lt;/u&amp;gt;&lt;br /&gt;
* 3 LEDs&lt;br /&gt;
&lt;br /&gt;
== Hardware ==&lt;br /&gt;
===Kicad===&lt;br /&gt;
&lt;br /&gt;
====Reçu carte vierge====&lt;br /&gt;
&lt;br /&gt;
====Carte après soudure des composants====&lt;/div&gt;</summary>
		<author><name>Adjadjaa</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-5&amp;diff=6863</id>
		<title>SE4Binome2024-5</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-5&amp;diff=6863"/>
		<updated>2024-11-20T11:01:20Z</updated>

		<summary type="html">&lt;p&gt;Adjadjaa : /* Carte Fille Matrice de touches */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Introduction=&lt;br /&gt;
&lt;br /&gt;
Ce wiki documente le développement d’un pico-ordinateur modulaire. Ce dernier est constitué d’une carte principale, composée d’une carte Shield permettant la connexion des cartes filles, et d’une carte mère (initialement simulée par une Arduino Uno avant sa conception finale). Plusieurs cartes filles sont prévues, chacune remplissant une fonction spécifique : gestion du clavier, affichage, port série, réseau, mémoire de masse et son.&lt;br /&gt;
&lt;br /&gt;
Notre binôme est spécifiquement chargé du développement de la carte fille dédiée au clavier.&lt;br /&gt;
&lt;br /&gt;
Toutes les ressources nécessaires, incluant les codes sources et les schémas, sont disponibles sur le dépôt Git suivant :  [https://gitea.plil.fr/ktouron/se4-djadja-touron_pico.git Lien du Git]&lt;br /&gt;
&lt;br /&gt;
= Carte Shield =&lt;br /&gt;
[[Fichier:Carte Recto non soudé.jpg|vignette|left|thumb|350px|Recto de la carte avant soudage des composants]]&lt;br /&gt;
[[Fichier:Verso non solder.jpeg.jpg|vignette|thumb|right|300px|Verso de la carte avant soudage des composants]]&lt;br /&gt;
[[Fichier:Carde shield soudé.jpg|vignette|thumb|center|350px|Photo de la carte avec les composants soudés]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Test==&lt;br /&gt;
=== Allumage de LEDS sur Programmateur AVR ===&lt;br /&gt;
Avant de programmer directement sur le shield, nous avons allumé des LED pour tester la carte. Nous avons directement utilisé le code exemple fourni par l'IDE arduino en adaptant simplement les pins correspondant aux leds. [https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/PicoShield/Programmation/Blink Code du test]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Vid_test_carte_mp4.mp4|vignette|thumb|center|700px|Vidéo de Test des leds]]&lt;br /&gt;
&lt;br /&gt;
=== Lecture de la carte SD ===&lt;br /&gt;
Avant de programmer directement sur le shield, nous avons tester si la carte SD était bien détectée et lue. On a utilisé le code test présent dans l'IDE arduino en adaptant le port utilisé.[https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/PicoShield/Programmation/CardInfo Code du test]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Resultat SD.jpg|vignette|thumb|center|700px|Carte SD bien détéctée]]&lt;br /&gt;
&lt;br /&gt;
=== Connecteurs IDC HE10 ===&lt;br /&gt;
Afin de tester nos connecteur HE10, nous avons utilisé un afficher 7 segments (Sparkfun 7 segments display). Pour pouvoir vérifier leurs fonctionnements nous avons branché l'afficheur sur chaque connecteur tour à tour. Le programme implanté est un simple connecteur à afficher sur l'afficheur. Voici une vidéo du compteur fonctionnant sur un des 5 connecteurs HE10. ([https://learn.sparkfun.com/tutorials/using-the-serial-7-segment-display/all Code ici (section : Example 2 SPI)])&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Se4-5-7segments.mp4|vignette|alt=se4-5-7segments|Test connecteur HE10 avec afficheur 7 segments.|center]]&lt;br /&gt;
== Ordonnanceur ==&lt;br /&gt;
Pour les interruptions de notre ordonnanceur nous avons utilisé la procédure d'initialisation du minuteur avec le Timer1 disponible dans les cours de Mr.Redon en renseignant une période de 20ms. Nous l'avons disposé dans le fichier minuteur.c car nous n'allons plus le modifier pour le reste du projet. Dans un autre fichier process.c (avec process.h), nous allons y mettre nos structures pour les process et leurs états puis une union pour le temps qui le caractérise ainsi que toutes les fonctions associés.&lt;br /&gt;
&lt;br /&gt;
[https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/Ordonnanceur Lien du répertoire]&lt;br /&gt;
&lt;br /&gt;
=== Processus ===&lt;br /&gt;
==== Structure ====&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:right; width: 48%; padding-left: 10px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
    uint16_t adresseDepart;  //adresse de la fonction de départ &lt;br /&gt;
    uint16_t adressePile;       //adresse de la pile d'exécution&lt;br /&gt;
    Etat etat;        &lt;br /&gt;
} Process;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Notre structure caractérisant un processus est définie par les trois champs ci-contre.&lt;br /&gt;
&lt;br /&gt;
Une adresse de départ correspondant à la fonction du processus associé, l'adresse où se situe le processus dans la pile puis l'état de la tâche. Nous avons décidé de faire une structure à part entière compte tenu des multitudes d'états que nous pourrons ajouter pendant la progression du projet.&lt;br /&gt;
&lt;br /&gt;
==== Etat d'un processus ====&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:right; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
typedef union {&lt;br /&gt;
  int sleepingtime;       &lt;br /&gt;
} Time;&lt;br /&gt;
&lt;br /&gt;
typedef struct {&lt;br /&gt;
  int id;&lt;br /&gt;
  Time time;&lt;br /&gt;
} Etat ;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
L'état d'un processus est alors une structure à deux champs (pour l'instant), l'id doit correspondre à un '#DEFINE' pour avoir un sens tandis que nous avons choisi de faire une union pour le temps qui caractérise notre état afin qu'il puisse avoir un nom et type de variable cohérent avec son état.(Ici seulement sleepingtime car seul l'état endormi existe pour le moment)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
  {| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
  |+ Tableau des états&lt;br /&gt;
  |-&lt;br /&gt;
  ! Etat !! ACTIVE !! SLEEPY !! ... !! ...&lt;br /&gt;
  |-&lt;br /&gt;
  | Id || 0 || 1 || ... || ...&lt;br /&gt;
  |}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Procédures principales ====&lt;br /&gt;
&lt;br /&gt;
=== ISR ===&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:right; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
ISR(TIMER1_COMPA_vect, ISR_NAKED)    // Procédure d'interruption&lt;br /&gt;
{&lt;br /&gt;
  TCNT1=0;//reset timer&lt;br /&gt;
  /* Sauvegarde du contexte de la tâche interrompue */&lt;br /&gt;
  portSAVE_REGISTERS();&lt;br /&gt;
   table_process[indice_tache].adressePile = SP;&lt;br /&gt;
  /* Appel à l'ordonnanceur */&lt;br /&gt;
  selectProcess();&lt;br /&gt;
  /* Récupération du contexte de la tâche ré-activée */&lt;br /&gt;
  SP = table_process[indice_tache].adressePile;&lt;br /&gt;
  portRESTORE_REGISTERS();&lt;br /&gt;
  &lt;br /&gt;
  asm volatile ( &amp;quot;reti&amp;quot; );&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
L'ISR est ce qu'il va être executer lors des interruptions toutes les 20 millisecondes. Cela consiste à sauvegarder tous les registres de la tâche qui était en cours avant l'appel de l'ISR pour ensuite passer à la tâche suivante valide (c'est à dire active) sans oublier de charger les registres de la nouvelle tâche.&lt;br /&gt;
&lt;br /&gt;
Nous devons également, à chaque fois avant de changer de tâche, enregistrer le pointeur de pile dans le processus afin de pouvoir revenir là ou elle en est la prochaine fois qu'elle sera appelée. Respectivement, une fois la nouvelle tâche choisie, le pointeur de pile doit prendre l'adresse de là ou en était la tâche avant qu'elle soit interrompue.&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Séléction de processus ====&lt;br /&gt;
Lors de la séléction de processus, nous devons parcourir tous les processus jusqu'au moment où nous en trouvons un actif. Ainsi, il deviendra la tâche que nous traiterons lors du prochain intervalle de 20 ms. A ce stade, à chaque fois que la procédure selectProcess est appelée, nous devons réduire le temps de repos de chaque process endormi de 20 ms. D'autres conditions pourrons être ajoutée si ajout d'état a lieu.&lt;br /&gt;
&lt;br /&gt;
=== Test ===&lt;br /&gt;
==== Clignotement de deux LED à fréquences indivisibles entre elles ====&lt;br /&gt;
Afin de vérifier la réussite de notre ordonnanceur à fonctionnement tourniquet, nous avons programmer deux simples tâches changeant l'état d'une LED. Une à une fréquence 200ms et l'autre 300ms (avec un _delay_ms).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:left; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void tache1(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTC ^= (1 &amp;lt;&amp;lt; PC0);&lt;br /&gt;
    _delay_ms(300);}}&lt;br /&gt;
void tache2(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTD ^= (1 &amp;lt;&amp;lt; PD7);&lt;br /&gt;
    _delay_ms(200);}}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
[[Fichier:B5_test1.mp4|vignette|alt=test des frequences imprevisibles|test des frequences imprevisibles]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Clignotement grâce à l'état endormi ====&lt;br /&gt;
Nous ajoutons l'état endormi afin que nos tâches ne mettent pas en pause l'ordonnanceur avec un _delay_ms. Pour cela, nous incorporons une fonction makeSleep qui permet de mettre la tâche qui l'appelle dans cet état.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:left; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void makeSleep(int t){&lt;br /&gt;
  table_process[indice_tache].etat.id = SLEEPY;&lt;br /&gt;
  table_process[indice_tache].etat.time.sleepingtime = t;&lt;br /&gt;
  TIMER1_COMPA_vect();}&lt;br /&gt;
void tache1(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTC ^= (1 &amp;lt;&amp;lt; PC0);&lt;br /&gt;
    _delay_ms(300);}}&lt;br /&gt;
void tache3(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTC ^= (1 &amp;lt;&amp;lt; PC3);&lt;br /&gt;
    //_delay_ms(1000);&lt;br /&gt;
    makeSleep(1000);}}&lt;br /&gt;
void tache2(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTD ^= (1 &amp;lt;&amp;lt; PD7);&lt;br /&gt;
    //_delay_ms(1000);&lt;br /&gt;
    makeSleep(700);}}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
[[Fichier:B5_test2.mp4|vignette|alt=test des frequences imprevisibles|test des frequences imprevisibles]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
A noter que la première tâche executée ne doit pas être endormie.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Carte Fille Matrice de touches =&lt;br /&gt;
==Explications générales sur la réalisation de la carte==&lt;br /&gt;
[[Fichier:Clavier dell.png||thumb|right|300px|Clavier DELL]]&lt;br /&gt;
[[Fichier:Matrice clavier dell.png||thumb|right|300px|Matrice du clavier DELL]]&lt;br /&gt;
[[Fichier:Connecteur de base clavier dell.png||thumb|right|200px|Matrice du clavier DELL]]&lt;br /&gt;
&lt;br /&gt;
Pour concevoir la carte fille dédiée au clavier, nous avons réutilisé un ancien clavier DELL équipé d’une matrice déjà fonctionnelle. L’idée consiste à connecter les sorties de cette matrice directement à notre carte fille à l’aide d’un connecteur adapté.&lt;br /&gt;
&lt;br /&gt;
Cependant, un défi se pose : la matrice du clavier comprend un total de 26 sorties (sans compter les LED et autres signaux). Cela dépasse largement les capacités en nombre de broches d’un ATmega328P.&lt;br /&gt;
&lt;br /&gt;
Pour remédier à ce problème, nous avons mis en place une solution d’encodage. Nous avons utilisé un décodeur (3 vers 8) pour gérer les lignes et trois encodeurs (8 vers 3) pour gérer les colonnes. Les encodeurs sont montés en parallèle pour réduire significativement le nombre de broches nécessaires.Cette solution permet de maximiser les ressources du microcontrôleur tout en gérant efficacement les signaux de la matrice.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Détails des composants ===&lt;br /&gt;
&lt;br /&gt;
==== ATmega328P ====&lt;br /&gt;
* Micro-contrôleur&lt;br /&gt;
&lt;br /&gt;
==== 74HC138D ====&lt;br /&gt;
* Décodeur&lt;br /&gt;
&lt;br /&gt;
==== CD4532BM ====&lt;br /&gt;
* Encodeur&lt;br /&gt;
&lt;br /&gt;
==== 74LS32 ====&lt;br /&gt;
* Porte logique Or pour la mise en parallèle des encodeurs&lt;br /&gt;
&lt;br /&gt;
==== Connecteur HE10 ====&lt;br /&gt;
* Connecteur pour la liaison PicoShield-CarteFille&lt;br /&gt;
&lt;br /&gt;
==== Connecteur de la matrice ====&lt;br /&gt;
* Simplement une empreinte que l'on a créé [https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/CF_Clavier/Footprint_KeyboardDell_DJADJA Lien vers la bibliothèque présent sur le git]&lt;br /&gt;
&lt;br /&gt;
==== AVR-ISP-6 ====&lt;br /&gt;
* Programmateur AVR&lt;br /&gt;
&lt;br /&gt;
==== LED_SMD ====&lt;br /&gt;
* 3 LEDs&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Hardware ==&lt;br /&gt;
===Kicad===&lt;br /&gt;
&lt;br /&gt;
====Reçu carte vierge====&lt;br /&gt;
&lt;br /&gt;
====Carte après soudure des composants====&lt;/div&gt;</summary>
		<author><name>Adjadjaa</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-5&amp;diff=6861</id>
		<title>SE4Binome2024-5</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-5&amp;diff=6861"/>
		<updated>2024-11-20T10:58:51Z</updated>

		<summary type="html">&lt;p&gt;Adjadjaa : /* Carte Fille Matrice de touches */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Introduction=&lt;br /&gt;
&lt;br /&gt;
Ce wiki documente le développement d’un pico-ordinateur modulaire. Ce dernier est constitué d’une carte principale, composée d’une carte Shield permettant la connexion des cartes filles, et d’une carte mère (initialement simulée par une Arduino Uno avant sa conception finale). Plusieurs cartes filles sont prévues, chacune remplissant une fonction spécifique : gestion du clavier, affichage, port série, réseau, mémoire de masse et son.&lt;br /&gt;
&lt;br /&gt;
Notre binôme est spécifiquement chargé du développement de la carte fille dédiée au clavier.&lt;br /&gt;
&lt;br /&gt;
Toutes les ressources nécessaires, incluant les codes sources et les schémas, sont disponibles sur le dépôt Git suivant :  [https://gitea.plil.fr/ktouron/se4-djadja-touron_pico.git Lien du Git]&lt;br /&gt;
&lt;br /&gt;
= Carte Shield =&lt;br /&gt;
[[Fichier:Carte Recto non soudé.jpg|vignette|left|thumb|350px|Recto de la carte avant soudage des composants]]&lt;br /&gt;
[[Fichier:Verso non solder.jpeg.jpg|vignette|thumb|right|300px|Verso de la carte avant soudage des composants]]&lt;br /&gt;
[[Fichier:Carde shield soudé.jpg|vignette|thumb|center|350px|Photo de la carte avec les composants soudés]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Test==&lt;br /&gt;
=== Allumage de LEDS sur Programmateur AVR ===&lt;br /&gt;
Avant de programmer directement sur le shield, nous avons allumé des LED pour tester la carte. Nous avons directement utilisé le code exemple fourni par l'IDE arduino en adaptant simplement les pins correspondant aux leds. [https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/PicoShield/Programmation/Blink Code du test]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Vid_test_carte_mp4.mp4|vignette|thumb|center|700px|Vidéo de Test des leds]]&lt;br /&gt;
&lt;br /&gt;
=== Lecture de la carte SD ===&lt;br /&gt;
Avant de programmer directement sur le shield, nous avons tester si la carte SD était bien détectée et lue. On a utilisé le code test présent dans l'IDE arduino en adaptant le port utilisé.[https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/PicoShield/Programmation/CardInfo Code du test]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Resultat SD.jpg|vignette|thumb|center|700px|Carte SD bien détéctée]]&lt;br /&gt;
&lt;br /&gt;
=== Connecteurs IDC HE10 ===&lt;br /&gt;
Afin de tester nos connecteur HE10, nous avons utilisé un afficher 7 segments (Sparkfun 7 segments display). Pour pouvoir vérifier leurs fonctionnements nous avons branché l'afficheur sur chaque connecteur tour à tour. Le programme implanté est un simple connecteur à afficher sur l'afficheur. Voici une vidéo du compteur fonctionnant sur un des 5 connecteurs HE10. ([https://learn.sparkfun.com/tutorials/using-the-serial-7-segment-display/all Code ici (section : Example 2 SPI)])&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Se4-5-7segments.mp4|vignette|alt=se4-5-7segments|Test connecteur HE10 avec afficheur 7 segments.|center]]&lt;br /&gt;
== Ordonnanceur ==&lt;br /&gt;
Pour les interruptions de notre ordonnanceur nous avons utilisé la procédure d'initialisation du minuteur avec le Timer1 disponible dans les cours de Mr.Redon en renseignant une période de 20ms. Nous l'avons disposé dans le fichier minuteur.c car nous n'allons plus le modifier pour le reste du projet. Dans un autre fichier process.c (avec process.h), nous allons y mettre nos structures pour les process et leurs états puis une union pour le temps qui le caractérise ainsi que toutes les fonctions associés.&lt;br /&gt;
&lt;br /&gt;
[https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/Ordonnanceur Lien du répertoire]&lt;br /&gt;
&lt;br /&gt;
=== Processus ===&lt;br /&gt;
==== Structure ====&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:right; width: 48%; padding-left: 10px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
    uint16_t adresseDepart;  //adresse de la fonction de départ &lt;br /&gt;
    uint16_t adressePile;       //adresse de la pile d'exécution&lt;br /&gt;
    Etat etat;        &lt;br /&gt;
} Process;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Notre structure caractérisant un processus est définie par les trois champs ci-contre.&lt;br /&gt;
&lt;br /&gt;
Une adresse de départ correspondant à la fonction du processus associé, l'adresse où se situe le processus dans la pile puis l'état de la tâche. Nous avons décidé de faire une structure à part entière compte tenu des multitudes d'états que nous pourrons ajouter pendant la progression du projet.&lt;br /&gt;
&lt;br /&gt;
==== Etat d'un processus ====&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:right; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
typedef union {&lt;br /&gt;
  int sleepingtime;       &lt;br /&gt;
} Time;&lt;br /&gt;
&lt;br /&gt;
typedef struct {&lt;br /&gt;
  int id;&lt;br /&gt;
  Time time;&lt;br /&gt;
} Etat ;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
L'état d'un processus est alors une structure à deux champs (pour l'instant), l'id doit correspondre à un '#DEFINE' pour avoir un sens tandis que nous avons choisi de faire une union pour le temps qui caractérise notre état afin qu'il puisse avoir un nom et type de variable cohérent avec son état.(Ici seulement sleepingtime car seul l'état endormi existe pour le moment)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
  {| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
  |+ Tableau des états&lt;br /&gt;
  |-&lt;br /&gt;
  ! Etat !! ACTIVE !! SLEEPY !! ... !! ...&lt;br /&gt;
  |-&lt;br /&gt;
  | Id || 0 || 1 || ... || ...&lt;br /&gt;
  |}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Procédures principales ====&lt;br /&gt;
&lt;br /&gt;
=== ISR ===&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:right; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
ISR(TIMER1_COMPA_vect, ISR_NAKED)    // Procédure d'interruption&lt;br /&gt;
{&lt;br /&gt;
  TCNT1=0;//reset timer&lt;br /&gt;
  /* Sauvegarde du contexte de la tâche interrompue */&lt;br /&gt;
  portSAVE_REGISTERS();&lt;br /&gt;
   table_process[indice_tache].adressePile = SP;&lt;br /&gt;
  /* Appel à l'ordonnanceur */&lt;br /&gt;
  selectProcess();&lt;br /&gt;
  /* Récupération du contexte de la tâche ré-activée */&lt;br /&gt;
  SP = table_process[indice_tache].adressePile;&lt;br /&gt;
  portRESTORE_REGISTERS();&lt;br /&gt;
  &lt;br /&gt;
  asm volatile ( &amp;quot;reti&amp;quot; );&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
L'ISR est ce qu'il va être executer lors des interruptions toutes les 20 millisecondes. Cela consiste à sauvegarder tous les registres de la tâche qui était en cours avant l'appel de l'ISR pour ensuite passer à la tâche suivante valide (c'est à dire active) sans oublier de charger les registres de la nouvelle tâche.&lt;br /&gt;
&lt;br /&gt;
Nous devons également, à chaque fois avant de changer de tâche, enregistrer le pointeur de pile dans le processus afin de pouvoir revenir là ou elle en est la prochaine fois qu'elle sera appelée. Respectivement, une fois la nouvelle tâche choisie, le pointeur de pile doit prendre l'adresse de là ou en était la tâche avant qu'elle soit interrompue.&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Séléction de processus ====&lt;br /&gt;
Lors de la séléction de processus, nous devons parcourir tous les processus jusqu'au moment où nous en trouvons un actif. Ainsi, il deviendra la tâche que nous traiterons lors du prochain intervalle de 20 ms. A ce stade, à chaque fois que la procédure selectProcess est appelée, nous devons réduire le temps de repos de chaque process endormi de 20 ms. D'autres conditions pourrons être ajoutée si ajout d'état a lieu.&lt;br /&gt;
&lt;br /&gt;
=== Test ===&lt;br /&gt;
==== Clignotement de deux LED à fréquences indivisibles entre elles ====&lt;br /&gt;
Afin de vérifier la réussite de notre ordonnanceur à fonctionnement tourniquet, nous avons programmer deux simples tâches changeant l'état d'une LED. Une à une fréquence 200ms et l'autre 300ms (avec un _delay_ms).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:left; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void tache1(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTC ^= (1 &amp;lt;&amp;lt; PC0);&lt;br /&gt;
    _delay_ms(300);}}&lt;br /&gt;
void tache2(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTD ^= (1 &amp;lt;&amp;lt; PD7);&lt;br /&gt;
    _delay_ms(200);}}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
[[Fichier:B5_test1.mp4|vignette|alt=test des frequences imprevisibles|test des frequences imprevisibles]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Clignotement grâce à l'état endormi ====&lt;br /&gt;
Nous ajoutons l'état endormi afin que nos tâches ne mettent pas en pause l'ordonnanceur avec un _delay_ms. Pour cela, nous incorporons une fonction makeSleep qui permet de mettre la tâche qui l'appelle dans cet état.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:left; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void makeSleep(int t){&lt;br /&gt;
  table_process[indice_tache].etat.id = SLEEPY;&lt;br /&gt;
  table_process[indice_tache].etat.time.sleepingtime = t;&lt;br /&gt;
  TIMER1_COMPA_vect();}&lt;br /&gt;
void tache1(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTC ^= (1 &amp;lt;&amp;lt; PC0);&lt;br /&gt;
    _delay_ms(300);}}&lt;br /&gt;
void tache3(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTC ^= (1 &amp;lt;&amp;lt; PC3);&lt;br /&gt;
    //_delay_ms(1000);&lt;br /&gt;
    makeSleep(1000);}}&lt;br /&gt;
void tache2(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTD ^= (1 &amp;lt;&amp;lt; PD7);&lt;br /&gt;
    //_delay_ms(1000);&lt;br /&gt;
    makeSleep(700);}}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
[[Fichier:B5_test2.mp4|vignette|alt=test des frequences imprevisibles|test des frequences imprevisibles]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
A noter que la première tâche executée ne doit pas être endormie.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Carte Fille Matrice de touches =&lt;br /&gt;
==Explications générales sur la réalisation de la carte==&lt;br /&gt;
[[Fichier:Clavier dell.png||thumb|right|300px|Clavier DELL]]&lt;br /&gt;
[[Fichier:Matrice clavier dell.png||thumb|right|300px|Matrice du clavier DELL]]&lt;br /&gt;
[[Fichier:Connecteur de base clavier dell.png||thumb|right|200px|Matrice du clavier DELL]]&lt;br /&gt;
&lt;br /&gt;
Pour concevoir la carte fille dédiée au clavier, nous avons réutilisé un ancien clavier DELL équipé d’une matrice déjà fonctionnelle. L’idée consiste à connecter les sorties de cette matrice directement à notre carte fille à l’aide d’un connecteur adapté.&lt;br /&gt;
&lt;br /&gt;
Cependant, un défi se pose : la matrice du clavier comprend un total de 26 sorties (sans compter les LED et autres signaux). Cela dépasse largement les capacités en nombre de broches d’un ATmega328P.&lt;br /&gt;
&lt;br /&gt;
Pour remédier à ce problème, nous avons mis en place une solution d’encodage. Nous avons utilisé un décodeur (3 vers 8) pour gérer les lignes et trois encodeurs (8 vers 3) pour gérer les colonnes. Les encodeurs sont montés en parallèle pour réduire significativement le nombre de broches nécessaires.Cette solution permet de maximiser les ressources du microcontrôleur tout en gérant efficacement les signaux de la matrice.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Détails des composants ==&lt;br /&gt;
&lt;br /&gt;
=== ATmega328P ===&lt;br /&gt;
* Micro-contrôleur&lt;br /&gt;
&lt;br /&gt;
=== 74HC138D ===&lt;br /&gt;
* Décodeur&lt;br /&gt;
&lt;br /&gt;
=== CD4532BM ===&lt;br /&gt;
* Encodeur&lt;br /&gt;
&lt;br /&gt;
=== 74LS32 ===&lt;br /&gt;
* Porte logique Or pour la mise en parallèle des encodeurs&lt;br /&gt;
&lt;br /&gt;
=== Connecteur HE10 ===&lt;br /&gt;
* Connecteur pour la liaison PicoShield-CarteFille&lt;br /&gt;
&lt;br /&gt;
=== Connecteur de la matrice ===&lt;br /&gt;
* Simplement une empreinte que l'on a créé [https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/CF_Clavier/Footprint_KeyboardDell_DJADJA Lien vers la bibliothèque présent sur le git]&lt;br /&gt;
&lt;br /&gt;
=== AVR-ISP-6 ===&lt;br /&gt;
* Programmateur AVR&lt;br /&gt;
&lt;br /&gt;
=== LED_SMD ===&lt;br /&gt;
* 3 LEDs&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Carte ==&lt;br /&gt;
&lt;br /&gt;
=== Fille après soudure des composants ===&lt;/div&gt;</summary>
		<author><name>Adjadjaa</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-5&amp;diff=6859</id>
		<title>SE4Binome2024-5</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-5&amp;diff=6859"/>
		<updated>2024-11-20T10:57:19Z</updated>

		<summary type="html">&lt;p&gt;Adjadjaa : /* Carte Fille Matrice de touches */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Introduction=&lt;br /&gt;
&lt;br /&gt;
Ce wiki documente le développement d’un pico-ordinateur modulaire. Ce dernier est constitué d’une carte principale, composée d’une carte Shield permettant la connexion des cartes filles, et d’une carte mère (initialement simulée par une Arduino Uno avant sa conception finale). Plusieurs cartes filles sont prévues, chacune remplissant une fonction spécifique : gestion du clavier, affichage, port série, réseau, mémoire de masse et son.&lt;br /&gt;
&lt;br /&gt;
Notre binôme est spécifiquement chargé du développement de la carte fille dédiée au clavier.&lt;br /&gt;
&lt;br /&gt;
Toutes les ressources nécessaires, incluant les codes sources et les schémas, sont disponibles sur le dépôt Git suivant :  [https://gitea.plil.fr/ktouron/se4-djadja-touron_pico.git Lien du Git]&lt;br /&gt;
&lt;br /&gt;
= Carte Shield =&lt;br /&gt;
[[Fichier:Carte Recto non soudé.jpg|vignette|left|thumb|350px|Recto de la carte avant soudage des composants]]&lt;br /&gt;
[[Fichier:Verso non solder.jpeg.jpg|vignette|thumb|right|300px|Verso de la carte avant soudage des composants]]&lt;br /&gt;
[[Fichier:Carde shield soudé.jpg|vignette|thumb|center|350px|Photo de la carte avec les composants soudés]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Test==&lt;br /&gt;
=== Allumage de LEDS sur Programmateur AVR ===&lt;br /&gt;
Avant de programmer directement sur le shield, nous avons allumé des LED pour tester la carte. Nous avons directement utilisé le code exemple fourni par l'IDE arduino en adaptant simplement les pins correspondant aux leds. [https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/PicoShield/Programmation/Blink Code du test]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Vid_test_carte_mp4.mp4|vignette|thumb|center|700px|Vidéo de Test des leds]]&lt;br /&gt;
&lt;br /&gt;
=== Lecture de la carte SD ===&lt;br /&gt;
Avant de programmer directement sur le shield, nous avons tester si la carte SD était bien détectée et lue. On a utilisé le code test présent dans l'IDE arduino en adaptant le port utilisé.[https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/PicoShield/Programmation/CardInfo Code du test]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Resultat SD.jpg|vignette|thumb|center|700px|Carte SD bien détéctée]]&lt;br /&gt;
&lt;br /&gt;
=== Connecteurs IDC HE10 ===&lt;br /&gt;
Afin de tester nos connecteur HE10, nous avons utilisé un afficher 7 segments (Sparkfun 7 segments display). Pour pouvoir vérifier leurs fonctionnements nous avons branché l'afficheur sur chaque connecteur tour à tour. Le programme implanté est un simple connecteur à afficher sur l'afficheur. Voici une vidéo du compteur fonctionnant sur un des 5 connecteurs HE10. ([https://learn.sparkfun.com/tutorials/using-the-serial-7-segment-display/all Code ici (section : Example 2 SPI)])&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Se4-5-7segments.mp4|vignette|alt=se4-5-7segments|Test connecteur HE10 avec afficheur 7 segments.|center]]&lt;br /&gt;
== Ordonnanceur ==&lt;br /&gt;
Pour les interruptions de notre ordonnanceur nous avons utilisé la procédure d'initialisation du minuteur avec le Timer1 disponible dans les cours de Mr.Redon en renseignant une période de 20ms. Nous l'avons disposé dans le fichier minuteur.c car nous n'allons plus le modifier pour le reste du projet. Dans un autre fichier process.c (avec process.h), nous allons y mettre nos structures pour les process et leurs états puis une union pour le temps qui le caractérise ainsi que toutes les fonctions associés.&lt;br /&gt;
&lt;br /&gt;
[https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/Ordonnanceur Lien du répertoire]&lt;br /&gt;
&lt;br /&gt;
=== Processus ===&lt;br /&gt;
==== Structure ====&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:right; width: 48%; padding-left: 10px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
    uint16_t adresseDepart;  //adresse de la fonction de départ &lt;br /&gt;
    uint16_t adressePile;       //adresse de la pile d'exécution&lt;br /&gt;
    Etat etat;        &lt;br /&gt;
} Process;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Notre structure caractérisant un processus est définie par les trois champs ci-contre.&lt;br /&gt;
&lt;br /&gt;
Une adresse de départ correspondant à la fonction du processus associé, l'adresse où se situe le processus dans la pile puis l'état de la tâche. Nous avons décidé de faire une structure à part entière compte tenu des multitudes d'états que nous pourrons ajouter pendant la progression du projet.&lt;br /&gt;
&lt;br /&gt;
==== Etat d'un processus ====&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:right; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
typedef union {&lt;br /&gt;
  int sleepingtime;       &lt;br /&gt;
} Time;&lt;br /&gt;
&lt;br /&gt;
typedef struct {&lt;br /&gt;
  int id;&lt;br /&gt;
  Time time;&lt;br /&gt;
} Etat ;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
L'état d'un processus est alors une structure à deux champs (pour l'instant), l'id doit correspondre à un '#DEFINE' pour avoir un sens tandis que nous avons choisi de faire une union pour le temps qui caractérise notre état afin qu'il puisse avoir un nom et type de variable cohérent avec son état.(Ici seulement sleepingtime car seul l'état endormi existe pour le moment)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
  {| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
  |+ Tableau des états&lt;br /&gt;
  |-&lt;br /&gt;
  ! Etat !! ACTIVE !! SLEEPY !! ... !! ...&lt;br /&gt;
  |-&lt;br /&gt;
  | Id || 0 || 1 || ... || ...&lt;br /&gt;
  |}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Procédures principales ====&lt;br /&gt;
&lt;br /&gt;
=== ISR ===&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:right; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
ISR(TIMER1_COMPA_vect, ISR_NAKED)    // Procédure d'interruption&lt;br /&gt;
{&lt;br /&gt;
  TCNT1=0;//reset timer&lt;br /&gt;
  /* Sauvegarde du contexte de la tâche interrompue */&lt;br /&gt;
  portSAVE_REGISTERS();&lt;br /&gt;
   table_process[indice_tache].adressePile = SP;&lt;br /&gt;
  /* Appel à l'ordonnanceur */&lt;br /&gt;
  selectProcess();&lt;br /&gt;
  /* Récupération du contexte de la tâche ré-activée */&lt;br /&gt;
  SP = table_process[indice_tache].adressePile;&lt;br /&gt;
  portRESTORE_REGISTERS();&lt;br /&gt;
  &lt;br /&gt;
  asm volatile ( &amp;quot;reti&amp;quot; );&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
L'ISR est ce qu'il va être executer lors des interruptions toutes les 20 millisecondes. Cela consiste à sauvegarder tous les registres de la tâche qui était en cours avant l'appel de l'ISR pour ensuite passer à la tâche suivante valide (c'est à dire active) sans oublier de charger les registres de la nouvelle tâche.&lt;br /&gt;
&lt;br /&gt;
Nous devons également, à chaque fois avant de changer de tâche, enregistrer le pointeur de pile dans le processus afin de pouvoir revenir là ou elle en est la prochaine fois qu'elle sera appelée. Respectivement, une fois la nouvelle tâche choisie, le pointeur de pile doit prendre l'adresse de là ou en était la tâche avant qu'elle soit interrompue.&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Séléction de processus ====&lt;br /&gt;
Lors de la séléction de processus, nous devons parcourir tous les processus jusqu'au moment où nous en trouvons un actif. Ainsi, il deviendra la tâche que nous traiterons lors du prochain intervalle de 20 ms. A ce stade, à chaque fois que la procédure selectProcess est appelée, nous devons réduire le temps de repos de chaque process endormi de 20 ms. D'autres conditions pourrons être ajoutée si ajout d'état a lieu.&lt;br /&gt;
&lt;br /&gt;
=== Test ===&lt;br /&gt;
==== Clignotement de deux LED à fréquences indivisibles entre elles ====&lt;br /&gt;
Afin de vérifier la réussite de notre ordonnanceur à fonctionnement tourniquet, nous avons programmer deux simples tâches changeant l'état d'une LED. Une à une fréquence 200ms et l'autre 300ms (avec un _delay_ms).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:left; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void tache1(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTC ^= (1 &amp;lt;&amp;lt; PC0);&lt;br /&gt;
    _delay_ms(300);}}&lt;br /&gt;
void tache2(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTD ^= (1 &amp;lt;&amp;lt; PD7);&lt;br /&gt;
    _delay_ms(200);}}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
[[Fichier:B5_test1.mp4|vignette|alt=test des frequences imprevisibles|test des frequences imprevisibles]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Clignotement grâce à l'état endormi ====&lt;br /&gt;
Nous ajoutons l'état endormi afin que nos tâches ne mettent pas en pause l'ordonnanceur avec un _delay_ms. Pour cela, nous incorporons une fonction makeSleep qui permet de mettre la tâche qui l'appelle dans cet état.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:left; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void makeSleep(int t){&lt;br /&gt;
  table_process[indice_tache].etat.id = SLEEPY;&lt;br /&gt;
  table_process[indice_tache].etat.time.sleepingtime = t;&lt;br /&gt;
  TIMER1_COMPA_vect();}&lt;br /&gt;
void tache1(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTC ^= (1 &amp;lt;&amp;lt; PC0);&lt;br /&gt;
    _delay_ms(300);}}&lt;br /&gt;
void tache3(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTC ^= (1 &amp;lt;&amp;lt; PC3);&lt;br /&gt;
    //_delay_ms(1000);&lt;br /&gt;
    makeSleep(1000);}}&lt;br /&gt;
void tache2(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTD ^= (1 &amp;lt;&amp;lt; PD7);&lt;br /&gt;
    //_delay_ms(1000);&lt;br /&gt;
    makeSleep(700);}}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
[[Fichier:B5_test2.mp4|vignette|alt=test des frequences imprevisibles|test des frequences imprevisibles]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
A noter que la première tâche executée ne doit pas être endormie.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Carte Fille Matrice de touches =&lt;br /&gt;
==Explications générales sur la réalisation de la carte==&lt;br /&gt;
[[Fichier:Clavier dell.png||thumb|right|300px|Clavier DELL]]&lt;br /&gt;
[[Fichier:Matrice clavier dell.png||thumb|right|300px|Matrice du clavier DELL]]&lt;br /&gt;
[[Fichier:Connecteur de base clavier dell.png||thumb|right|200px|Matrice du clavier DELL]]&lt;br /&gt;
&lt;br /&gt;
Pour concevoir la carte fille dédiée au clavier, nous avons réutilisé un ancien clavier DELL équipé d’une matrice déjà fonctionnelle. L’idée consiste à connecter les sorties de cette matrice directement à notre carte fille à l’aide d’un connecteur adapté.&lt;br /&gt;
&lt;br /&gt;
Cependant, un défi se pose : la matrice du clavier comprend un total de 26 sorties (sans compter les LED et autres signaux). Cela dépasse largement les capacités en nombre de broches d’un ATmega328P.&lt;br /&gt;
&lt;br /&gt;
Pour remédier à ce problème, nous avons mis en place une solution d’encodage. Nous avons utilisé un décodeur (3 vers 8) pour gérer les lignes et trois encodeurs (8 vers 3) pour gérer les colonnes. Les encodeurs sont montés en parallèle pour réduire significativement le nombre de broches nécessaires.Cette solution permet de maximiser les ressources du microcontrôleur tout en gérant efficacement les signaux de la matrice.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Détails des composants ==&lt;br /&gt;
&lt;br /&gt;
=== ATmega328P ===&lt;br /&gt;
* Micro-contrôleur&lt;br /&gt;
&lt;br /&gt;
=== 74HC138D ===&lt;br /&gt;
* Décodeur&lt;br /&gt;
&lt;br /&gt;
=== CD4532BM ===&lt;br /&gt;
* Encodeur&lt;br /&gt;
&lt;br /&gt;
=== 74LS32 ===&lt;br /&gt;
* Porte logique Or pour la mise en parallèle des encodeurs&lt;br /&gt;
&lt;br /&gt;
=== Connecteur HE10 ===&lt;br /&gt;
* Connecteur pour la liaison PicoShield-CarteFille&lt;br /&gt;
&lt;br /&gt;
=== Connecteur de la matrice ===&lt;br /&gt;
* Simplement une empreinte que l'on a créé[https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/CF_Clavier/Footprint_KeyboardDell_DJADJA Lien vers le git]&lt;br /&gt;
&lt;br /&gt;
=== AVR-ISP-6 ===&lt;br /&gt;
* Programmateur AVR&lt;br /&gt;
&lt;br /&gt;
=== LED_SMD ===&lt;br /&gt;
* 3 LEDs&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Carte ==&lt;br /&gt;
&lt;br /&gt;
=== Fille après soudure des composants ===&lt;/div&gt;</summary>
		<author><name>Adjadjaa</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-5&amp;diff=6851</id>
		<title>SE4Binome2024-5</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-5&amp;diff=6851"/>
		<updated>2024-11-20T10:37:13Z</updated>

		<summary type="html">&lt;p&gt;Adjadjaa : /* Explications générales sur la réalisation de la carte */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Introduction=&lt;br /&gt;
&lt;br /&gt;
Ce wiki documente le développement d’un pico-ordinateur modulaire. Ce dernier est constitué d’une carte principale, composée d’une carte Shield permettant la connexion des cartes filles, et d’une carte mère (initialement simulée par une Arduino Uno avant sa conception finale). Plusieurs cartes filles sont prévues, chacune remplissant une fonction spécifique : gestion du clavier, affichage, port série, réseau, mémoire de masse et son.&lt;br /&gt;
&lt;br /&gt;
Notre binôme est spécifiquement chargé du développement de la carte fille dédiée au clavier.&lt;br /&gt;
&lt;br /&gt;
Toutes les ressources nécessaires, incluant les codes sources et les schémas, sont disponibles sur le dépôt Git suivant :  [https://gitea.plil.fr/ktouron/se4-djadja-touron_pico.git Lien du Git]&lt;br /&gt;
&lt;br /&gt;
= Carte Shield =&lt;br /&gt;
[[Fichier:Carte Recto non soudé.jpg|vignette|left|thumb|350px|Recto de la carte avant soudage des composants]]&lt;br /&gt;
[[Fichier:Verso non solder.jpeg.jpg|vignette|thumb|right|300px|Verso de la carte avant soudage des composants]]&lt;br /&gt;
[[Fichier:Carde shield soudé.jpg|vignette|thumb|center|350px|Photo de la carte avec les composants soudés]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Test==&lt;br /&gt;
=== Allumage de LEDS sur Programmateur AVR ===&lt;br /&gt;
Avant de programmer directement sur le shield, nous avons allumé des LED pour tester la carte. Nous avons directement utilisé le code exemple fourni par l'IDE arduino en adaptant simplement les pins correspondant aux leds. [https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/PicoShield/Programmation/Blink Code du test]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Vid_test_carte_mp4.mp4|vignette|thumb|center|700px|Vidéo de Test des leds]]&lt;br /&gt;
&lt;br /&gt;
=== Lecture de la carte SD ===&lt;br /&gt;
Avant de programmer directement sur le shield, nous avons tester si la carte SD était bien détectée et lue. On a utilisé le code test présent dans l'IDE arduino en adaptant le port utilisé.[https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/PicoShield/Programmation/CardInfo Code du test]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Resultat SD.jpg|vignette|thumb|center|700px|Carte SD bien détéctée]]&lt;br /&gt;
&lt;br /&gt;
=== Connecteurs IDC HE10 ===&lt;br /&gt;
Afin de tester nos connecteur HE10, nous avons utilisé un afficher 7 segments (Sparkfun 7 segments display). Pour pouvoir vérifier leurs fonctionnements nous avons branché l'afficheur sur chaque connecteur tour à tour. Le programme implanté est un simple connecteur à afficher sur l'afficheur. Voici une vidéo du compteur fonctionnant sur un des 5 connecteurs HE10. ([https://learn.sparkfun.com/tutorials/using-the-serial-7-segment-display/all Code ici (section : Example 2 SPI)])&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Se4-5-7segments.mp4|vignette|alt=se4-5-7segments|Test connecteur HE10 avec afficheur 7 segments.|center]]&lt;br /&gt;
== Ordonnanceur ==&lt;br /&gt;
Pour les interruptions de notre ordonnanceur nous avons utilisé la procédure d'initialisation du minuteur avec le Timer1 disponible dans les cours de Mr.Redon en renseignant une période de 20ms. Nous l'avons disposé dans le fichier minuteur.c car nous n'allons plus le modifier pour le reste du projet. Dans un autre fichier process.c (avec process.h), nous allons y mettre nos structures pour les process et leurs états puis une union pour le temps qui le caractérise ainsi que toutes les fonctions associés.&lt;br /&gt;
&lt;br /&gt;
[https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/Ordonnanceur Lien du répertoire]&lt;br /&gt;
&lt;br /&gt;
=== Processus ===&lt;br /&gt;
==== Structure ====&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:right; width: 48%; padding-left: 10px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
    uint16_t adresseDepart;  //adresse de la fonction de départ &lt;br /&gt;
    uint16_t adressePile;       //adresse de la pile d'exécution&lt;br /&gt;
    Etat etat;        &lt;br /&gt;
} Process;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Notre structure caractérisant un processus est définie par les trois champs ci-contre.&lt;br /&gt;
&lt;br /&gt;
Une adresse de départ correspondant à la fonction du processus associé, l'adresse où se situe le processus dans la pile puis l'état de la tâche. Nous avons décidé de faire une structure à part entière compte tenu des multitudes d'états que nous pourrons ajouter pendant la progression du projet.&lt;br /&gt;
&lt;br /&gt;
==== Etat d'un processus ====&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:right; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
typedef union {&lt;br /&gt;
  int sleepingtime;       &lt;br /&gt;
} Time;&lt;br /&gt;
&lt;br /&gt;
typedef struct {&lt;br /&gt;
  int id;&lt;br /&gt;
  Time time;&lt;br /&gt;
} Etat ;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
L'état d'un processus est alors une structure à deux champs (pour l'instant), l'id doit correspondre à un '#DEFINE' pour avoir un sens tandis que nous avons choisi de faire une union pour le temps qui caractérise notre état afin qu'il puisse avoir un nom et type de variable cohérent avec son état.(Ici seulement sleepingtime car seul l'état endormi existe pour le moment)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
  {| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
  |+ Tableau des états&lt;br /&gt;
  |-&lt;br /&gt;
  ! Etat !! ACTIVE !! SLEEPY !! ... !! ...&lt;br /&gt;
  |-&lt;br /&gt;
  | Id || 0 || 1 || ... || ...&lt;br /&gt;
  |}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Procédures principales ====&lt;br /&gt;
&lt;br /&gt;
=== ISR ===&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:right; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
ISR(TIMER1_COMPA_vect, ISR_NAKED)    // Procédure d'interruption&lt;br /&gt;
{&lt;br /&gt;
  TCNT1=0;//reset timer&lt;br /&gt;
  /* Sauvegarde du contexte de la tâche interrompue */&lt;br /&gt;
  portSAVE_REGISTERS();&lt;br /&gt;
   table_process[indice_tache].adressePile = SP;&lt;br /&gt;
  /* Appel à l'ordonnanceur */&lt;br /&gt;
  selectProcess();&lt;br /&gt;
  /* Récupération du contexte de la tâche ré-activée */&lt;br /&gt;
  SP = table_process[indice_tache].adressePile;&lt;br /&gt;
  portRESTORE_REGISTERS();&lt;br /&gt;
  &lt;br /&gt;
  asm volatile ( &amp;quot;reti&amp;quot; );&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
L'ISR est ce qu'il va être executer lors des interruptions toutes les 20 millisecondes. Cela consiste à sauvegarder tous les registres de la tâche qui était en cours avant l'appel de l'ISR pour ensuite passer à la tâche suivante valide (c'est à dire active) sans oublier de charger les registres de la nouvelle tâche.&lt;br /&gt;
&lt;br /&gt;
Nous devons également, à chaque fois avant de changer de tâche, enregistrer le pointeur de pile dans le processus afin de pouvoir revenir là ou elle en est la prochaine fois qu'elle sera appelée. Respectivement, une fois la nouvelle tâche choisie, le pointeur de pile doit prendre l'adresse de là ou en était la tâche avant qu'elle soit interrompue.&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Séléction de processus ====&lt;br /&gt;
Lors de la séléction de processus, nous devons parcourir tous les processus jusqu'au moment où nous en trouvons un actif. Ainsi, il deviendra la tâche que nous traiterons lors du prochain intervalle de 20 ms. A ce stade, à chaque fois que la procédure selectProcess est appelée, nous devons réduire le temps de repos de chaque process endormi de 20 ms. D'autres conditions pourrons être ajoutée si ajout d'état a lieu.&lt;br /&gt;
&lt;br /&gt;
=== Test ===&lt;br /&gt;
==== Clignotement de deux LED à fréquences indivisibles entre elles ====&lt;br /&gt;
Afin de vérifier la réussite de notre ordonnanceur à fonctionnement tourniquet, nous avons programmer deux simples tâches changeant l'état d'une LED. Une à une fréquence 200ms et l'autre 300ms (avec un _delay_ms).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:left; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void tache1(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTC ^= (1 &amp;lt;&amp;lt; PC0);&lt;br /&gt;
    _delay_ms(300);}}&lt;br /&gt;
void tache2(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTD ^= (1 &amp;lt;&amp;lt; PD7);&lt;br /&gt;
    _delay_ms(200);}}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
[[Fichier:B5_test1.mp4|vignette|alt=test des frequences imprevisibles|test des frequences imprevisibles]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Clignotement grâce à l'état endormi ====&lt;br /&gt;
Nous ajoutons l'état endormi afin que nos tâches ne mettent pas en pause l'ordonnanceur avec un _delay_ms. Pour cela, nous incorporons une fonction makeSleep qui permet de mettre la tâche qui l'appelle dans cet état.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:left; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void makeSleep(int t){&lt;br /&gt;
  table_process[indice_tache].etat.id = SLEEPY;&lt;br /&gt;
  table_process[indice_tache].etat.time.sleepingtime = t;&lt;br /&gt;
  TIMER1_COMPA_vect();}&lt;br /&gt;
void tache1(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTC ^= (1 &amp;lt;&amp;lt; PC0);&lt;br /&gt;
    _delay_ms(300);}}&lt;br /&gt;
void tache3(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTC ^= (1 &amp;lt;&amp;lt; PC3);&lt;br /&gt;
    //_delay_ms(1000);&lt;br /&gt;
    makeSleep(1000);}}&lt;br /&gt;
void tache2(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTD ^= (1 &amp;lt;&amp;lt; PD7);&lt;br /&gt;
    //_delay_ms(1000);&lt;br /&gt;
    makeSleep(700);}}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
[[Fichier:B5_test2.mp4|vignette|alt=test des frequences imprevisibles|test des frequences imprevisibles]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
A noter que la première tâche executée ne doit pas être endormie.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Carte Fille Matrice de touches =&lt;br /&gt;
==Explications générales sur la réalisation de la carte==&lt;br /&gt;
[[Fichier:Clavier dell.png||thumb|right|300px|Clavier DELL]]&lt;br /&gt;
[[Fichier:Matrice clavier dell.png||thumb|right|300px|Matrice du clavier DELL]]&lt;br /&gt;
[[Fichier:Connecteur de base clavier dell.png||thumb|right|200px|Matrice du clavier DELL]]&lt;br /&gt;
&lt;br /&gt;
Pour concevoir la carte fille dédiée au clavier, nous avons réutilisé un ancien clavier DELL équipé d’une matrice déjà fonctionnelle. L’idée consiste à connecter les sorties de cette matrice directement à notre carte fille à l’aide d’un connecteur adapté.&lt;br /&gt;
&lt;br /&gt;
Cependant, un défi se pose : la matrice du clavier comprend un total de 26 sorties (sans compter les LED et autres signaux). Cela dépasse largement les capacités en nombre de broches d’un ATmega328P.&lt;br /&gt;
&lt;br /&gt;
Pour remédier à ce problème, nous avons mis en place une solution d’encodage. Nous avons utilisé un décodeur (3 vers 8) pour gérer les lignes et trois encodeurs (8 vers 3) pour gérer les colonnes. Les encodeurs sont montés en parallèle pour réduire significativement le nombre de broches nécessaires.Cette solution permet de maximiser les ressources du microcontrôleur tout en gérant efficacement les signaux de la matrice.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Carte ==&lt;br /&gt;
&lt;br /&gt;
=== Fille après soudure des composants ===&lt;/div&gt;</summary>
		<author><name>Adjadjaa</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-5&amp;diff=6850</id>
		<title>SE4Binome2024-5</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-5&amp;diff=6850"/>
		<updated>2024-11-20T10:32:59Z</updated>

		<summary type="html">&lt;p&gt;Adjadjaa : /* Carte Fille Matrice de touches */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Introduction=&lt;br /&gt;
&lt;br /&gt;
Ce wiki documente le développement d’un pico-ordinateur modulaire. Ce dernier est constitué d’une carte principale, composée d’une carte Shield permettant la connexion des cartes filles, et d’une carte mère (initialement simulée par une Arduino Uno avant sa conception finale). Plusieurs cartes filles sont prévues, chacune remplissant une fonction spécifique : gestion du clavier, affichage, port série, réseau, mémoire de masse et son.&lt;br /&gt;
&lt;br /&gt;
Notre binôme est spécifiquement chargé du développement de la carte fille dédiée au clavier.&lt;br /&gt;
&lt;br /&gt;
Toutes les ressources nécessaires, incluant les codes sources et les schémas, sont disponibles sur le dépôt Git suivant :  [https://gitea.plil.fr/ktouron/se4-djadja-touron_pico.git Lien du Git]&lt;br /&gt;
&lt;br /&gt;
= Carte Shield =&lt;br /&gt;
[[Fichier:Carte Recto non soudé.jpg|vignette|left|thumb|350px|Recto de la carte avant soudage des composants]]&lt;br /&gt;
[[Fichier:Verso non solder.jpeg.jpg|vignette|thumb|right|300px|Verso de la carte avant soudage des composants]]&lt;br /&gt;
[[Fichier:Carde shield soudé.jpg|vignette|thumb|center|350px|Photo de la carte avec les composants soudés]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Test==&lt;br /&gt;
=== Allumage de LEDS sur Programmateur AVR ===&lt;br /&gt;
Avant de programmer directement sur le shield, nous avons allumé des LED pour tester la carte. Nous avons directement utilisé le code exemple fourni par l'IDE arduino en adaptant simplement les pins correspondant aux leds. [https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/PicoShield/Programmation/Blink Code du test]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Vid_test_carte_mp4.mp4|vignette|thumb|center|700px|Vidéo de Test des leds]]&lt;br /&gt;
&lt;br /&gt;
=== Lecture de la carte SD ===&lt;br /&gt;
Avant de programmer directement sur le shield, nous avons tester si la carte SD était bien détectée et lue. On a utilisé le code test présent dans l'IDE arduino en adaptant le port utilisé.[https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/PicoShield/Programmation/CardInfo Code du test]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Resultat SD.jpg|vignette|thumb|center|700px|Carte SD bien détéctée]]&lt;br /&gt;
&lt;br /&gt;
=== Connecteurs IDC HE10 ===&lt;br /&gt;
Afin de tester nos connecteur HE10, nous avons utilisé un afficher 7 segments (Sparkfun 7 segments display). Pour pouvoir vérifier leurs fonctionnements nous avons branché l'afficheur sur chaque connecteur tour à tour. Le programme implanté est un simple connecteur à afficher sur l'afficheur. Voici une vidéo du compteur fonctionnant sur un des 5 connecteurs HE10. ([https://learn.sparkfun.com/tutorials/using-the-serial-7-segment-display/all Code ici (section : Example 2 SPI)])&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Se4-5-7segments.mp4|vignette|alt=se4-5-7segments|Test connecteur HE10 avec afficheur 7 segments.|center]]&lt;br /&gt;
== Ordonnanceur ==&lt;br /&gt;
Pour les interruptions de notre ordonnanceur nous avons utilisé la procédure d'initialisation du minuteur avec le Timer1 disponible dans les cours de Mr.Redon en renseignant une période de 20ms. Nous l'avons disposé dans le fichier minuteur.c car nous n'allons plus le modifier pour le reste du projet. Dans un autre fichier process.c (avec process.h), nous allons y mettre nos structures pour les process et leurs états puis une union pour le temps qui le caractérise ainsi que toutes les fonctions associés.&lt;br /&gt;
&lt;br /&gt;
[https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/Ordonnanceur Lien du répertoire]&lt;br /&gt;
&lt;br /&gt;
=== Processus ===&lt;br /&gt;
==== Structure ====&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:right; width: 48%; padding-left: 10px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
    uint16_t adresseDepart;  //adresse de la fonction de départ &lt;br /&gt;
    uint16_t adressePile;       //adresse de la pile d'exécution&lt;br /&gt;
    Etat etat;        &lt;br /&gt;
} Process;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Notre structure caractérisant un processus est définie par les trois champs ci-contre.&lt;br /&gt;
&lt;br /&gt;
Une adresse de départ correspondant à la fonction du processus associé, l'adresse où se situe le processus dans la pile puis l'état de la tâche. Nous avons décidé de faire une structure à part entière compte tenu des multitudes d'états que nous pourrons ajouter pendant la progression du projet.&lt;br /&gt;
&lt;br /&gt;
==== Etat d'un processus ====&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:right; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
typedef union {&lt;br /&gt;
  int sleepingtime;       &lt;br /&gt;
} Time;&lt;br /&gt;
&lt;br /&gt;
typedef struct {&lt;br /&gt;
  int id;&lt;br /&gt;
  Time time;&lt;br /&gt;
} Etat ;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
L'état d'un processus est alors une structure à deux champs (pour l'instant), l'id doit correspondre à un '#DEFINE' pour avoir un sens tandis que nous avons choisi de faire une union pour le temps qui caractérise notre état afin qu'il puisse avoir un nom et type de variable cohérent avec son état.(Ici seulement sleepingtime car seul l'état endormi existe pour le moment)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
  {| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
  |+ Tableau des états&lt;br /&gt;
  |-&lt;br /&gt;
  ! Etat !! ACTIVE !! SLEEPY !! ... !! ...&lt;br /&gt;
  |-&lt;br /&gt;
  | Id || 0 || 1 || ... || ...&lt;br /&gt;
  |}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Procédures principales ====&lt;br /&gt;
&lt;br /&gt;
=== ISR ===&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:right; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
ISR(TIMER1_COMPA_vect, ISR_NAKED)    // Procédure d'interruption&lt;br /&gt;
{&lt;br /&gt;
  TCNT1=0;//reset timer&lt;br /&gt;
  /* Sauvegarde du contexte de la tâche interrompue */&lt;br /&gt;
  portSAVE_REGISTERS();&lt;br /&gt;
   table_process[indice_tache].adressePile = SP;&lt;br /&gt;
  /* Appel à l'ordonnanceur */&lt;br /&gt;
  selectProcess();&lt;br /&gt;
  /* Récupération du contexte de la tâche ré-activée */&lt;br /&gt;
  SP = table_process[indice_tache].adressePile;&lt;br /&gt;
  portRESTORE_REGISTERS();&lt;br /&gt;
  &lt;br /&gt;
  asm volatile ( &amp;quot;reti&amp;quot; );&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
L'ISR est ce qu'il va être executer lors des interruptions toutes les 20 millisecondes. Cela consiste à sauvegarder tous les registres de la tâche qui était en cours avant l'appel de l'ISR pour ensuite passer à la tâche suivante valide (c'est à dire active) sans oublier de charger les registres de la nouvelle tâche.&lt;br /&gt;
&lt;br /&gt;
Nous devons également, à chaque fois avant de changer de tâche, enregistrer le pointeur de pile dans le processus afin de pouvoir revenir là ou elle en est la prochaine fois qu'elle sera appelée. Respectivement, une fois la nouvelle tâche choisie, le pointeur de pile doit prendre l'adresse de là ou en était la tâche avant qu'elle soit interrompue.&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Séléction de processus ====&lt;br /&gt;
Lors de la séléction de processus, nous devons parcourir tous les processus jusqu'au moment où nous en trouvons un actif. Ainsi, il deviendra la tâche que nous traiterons lors du prochain intervalle de 20 ms. A ce stade, à chaque fois que la procédure selectProcess est appelée, nous devons réduire le temps de repos de chaque process endormi de 20 ms. D'autres conditions pourrons être ajoutée si ajout d'état a lieu.&lt;br /&gt;
&lt;br /&gt;
=== Test ===&lt;br /&gt;
==== Clignotement de deux LED à fréquences indivisibles entre elles ====&lt;br /&gt;
Afin de vérifier la réussite de notre ordonnanceur à fonctionnement tourniquet, nous avons programmer deux simples tâches changeant l'état d'une LED. Une à une fréquence 200ms et l'autre 300ms (avec un _delay_ms).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:left; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void tache1(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTC ^= (1 &amp;lt;&amp;lt; PC0);&lt;br /&gt;
    _delay_ms(300);}}&lt;br /&gt;
void tache2(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTD ^= (1 &amp;lt;&amp;lt; PD7);&lt;br /&gt;
    _delay_ms(200);}}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
[[Fichier:B5_test1.mp4|vignette|alt=test des frequences imprevisibles|test des frequences imprevisibles]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Clignotement grâce à l'état endormi ====&lt;br /&gt;
Nous ajoutons l'état endormi afin que nos tâches ne mettent pas en pause l'ordonnanceur avec un _delay_ms. Pour cela, nous incorporons une fonction makeSleep qui permet de mettre la tâche qui l'appelle dans cet état.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:left; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void makeSleep(int t){&lt;br /&gt;
  table_process[indice_tache].etat.id = SLEEPY;&lt;br /&gt;
  table_process[indice_tache].etat.time.sleepingtime = t;&lt;br /&gt;
  TIMER1_COMPA_vect();}&lt;br /&gt;
void tache1(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTC ^= (1 &amp;lt;&amp;lt; PC0);&lt;br /&gt;
    _delay_ms(300);}}&lt;br /&gt;
void tache3(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTC ^= (1 &amp;lt;&amp;lt; PC3);&lt;br /&gt;
    //_delay_ms(1000);&lt;br /&gt;
    makeSleep(1000);}}&lt;br /&gt;
void tache2(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTD ^= (1 &amp;lt;&amp;lt; PD7);&lt;br /&gt;
    //_delay_ms(1000);&lt;br /&gt;
    makeSleep(700);}}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
[[Fichier:B5_test2.mp4|vignette|alt=test des frequences imprevisibles|test des frequences imprevisibles]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
A noter que la première tâche executée ne doit pas être endormie.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Carte Fille Matrice de touches =&lt;br /&gt;
==Explications générales sur la réalisation de la carte==&lt;br /&gt;
[[Fichier:Clavier dell.png||thumb|right|300px|Clavier DELL]]&lt;br /&gt;
[[Fichier:Matrice clavier dell.png||thumb|right|300px|Matrice du clavier DELL]]&lt;br /&gt;
Pour concevoir la carte fille dédiée au clavier, nous avons réutilisé un ancien clavier DELL équipé d’une matrice déjà fonctionnelle. L’idée consiste à connecter les sorties de cette matrice directement à notre carte fille à l’aide d’un connecteur adapté.&lt;br /&gt;
&lt;br /&gt;
Cependant, un défi se pose : la matrice du clavier comprend un total de 26 sorties (sans compter les LED et autres signaux). Cela dépasse largement les capacités en nombre de broches d’un ATmega328P.&lt;br /&gt;
&lt;br /&gt;
Pour remédier à ce problème, nous avons mis en place une solution d’encodage. Nous avons utilisé un décodeur (3 vers 8) pour gérer les lignes et trois encodeurs (8 vers 3) pour gérer les colonnes. Les encodeurs sont montés en parallèle pour réduire significativement le nombre de broches nécessaires.Cette solution permet de maximiser les ressources du microcontrôleur tout en gérant efficacement les signaux de la matrice.&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
== Carte ==&lt;br /&gt;
&lt;br /&gt;
=== Fille après soudure des composants ===&lt;/div&gt;</summary>
		<author><name>Adjadjaa</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=Fichier:Connecteur_de_base_clavier_dell.png&amp;diff=6846</id>
		<title>Fichier:Connecteur de base clavier dell.png</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=Fichier:Connecteur_de_base_clavier_dell.png&amp;diff=6846"/>
		<updated>2024-11-20T10:23:55Z</updated>

		<summary type="html">&lt;p&gt;Adjadjaa : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Connecteur de base clavier dell&lt;/div&gt;</summary>
		<author><name>Adjadjaa</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=Fichier:Matrice_clavier_dell.png&amp;diff=6844</id>
		<title>Fichier:Matrice clavier dell.png</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=Fichier:Matrice_clavier_dell.png&amp;diff=6844"/>
		<updated>2024-11-20T10:19:54Z</updated>

		<summary type="html">&lt;p&gt;Adjadjaa : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Matrice clavier dell&lt;/div&gt;</summary>
		<author><name>Adjadjaa</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-5&amp;diff=6843</id>
		<title>SE4Binome2024-5</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-5&amp;diff=6843"/>
		<updated>2024-11-20T10:17:48Z</updated>

		<summary type="html">&lt;p&gt;Adjadjaa : /* Carte Fille Matrice de touches */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Introduction=&lt;br /&gt;
&lt;br /&gt;
Ce wiki documente le développement d’un pico-ordinateur modulaire. Ce dernier est constitué d’une carte principale, composée d’une carte Shield permettant la connexion des cartes filles, et d’une carte mère (initialement simulée par une Arduino Uno avant sa conception finale). Plusieurs cartes filles sont prévues, chacune remplissant une fonction spécifique : gestion du clavier, affichage, port série, réseau, mémoire de masse et son.&lt;br /&gt;
&lt;br /&gt;
Notre binôme est spécifiquement chargé du développement de la carte fille dédiée au clavier.&lt;br /&gt;
&lt;br /&gt;
Toutes les ressources nécessaires, incluant les codes sources et les schémas, sont disponibles sur le dépôt Git suivant :  [https://gitea.plil.fr/ktouron/se4-djadja-touron_pico.git Lien du Git]&lt;br /&gt;
&lt;br /&gt;
= Carte Shield =&lt;br /&gt;
[[Fichier:Carte Recto non soudé.jpg|vignette|left|thumb|350px|Recto de la carte avant soudage des composants]]&lt;br /&gt;
[[Fichier:Verso non solder.jpeg.jpg|vignette|thumb|right|300px|Verso de la carte avant soudage des composants]]&lt;br /&gt;
[[Fichier:Carde shield soudé.jpg|vignette|thumb|center|350px|Photo de la carte avec les composants soudés]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Test==&lt;br /&gt;
=== Allumage de LEDS sur Programmateur AVR ===&lt;br /&gt;
Avant de programmer directement sur le shield, nous avons allumé des LED pour tester la carte. Nous avons directement utilisé le code exemple fourni par l'IDE arduino en adaptant simplement les pins correspondant aux leds. [https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/PicoShield/Programmation/Blink Code du test]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Vid_test_carte_mp4.mp4|vignette|thumb|center|700px|Vidéo de Test des leds]]&lt;br /&gt;
&lt;br /&gt;
=== Lecture de la carte SD ===&lt;br /&gt;
Avant de programmer directement sur le shield, nous avons tester si la carte SD était bien détectée et lue. On a utilisé le code test présent dans l'IDE arduino en adaptant le port utilisé.[https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/PicoShield/Programmation/CardInfo Code du test]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Resultat SD.jpg|vignette|thumb|center|700px|Carte SD bien détéctée]]&lt;br /&gt;
&lt;br /&gt;
=== Connecteurs IDC HE10 ===&lt;br /&gt;
Afin de tester nos connecteur HE10, nous avons utilisé un afficher 7 segments (Sparkfun 7 segments display). Pour pouvoir vérifier leurs fonctionnements nous avons branché l'afficheur sur chaque connecteur tour à tour. Le programme implanté est un simple connecteur à afficher sur l'afficheur. Voici une vidéo du compteur fonctionnant sur un des 5 connecteurs HE10. ([https://learn.sparkfun.com/tutorials/using-the-serial-7-segment-display/all Code ici (section : Example 2 SPI)])&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Se4-5-7segments.mp4|vignette|alt=se4-5-7segments|Test connecteur HE10 avec afficheur 7 segments.|center]]&lt;br /&gt;
== Ordonnanceur ==&lt;br /&gt;
Pour les interruptions de notre ordonnanceur nous avons utilisé la procédure d'initialisation du minuteur avec le Timer1 disponible dans les cours de Mr.Redon en renseignant une période de 20ms. Nous l'avons disposé dans le fichier minuteur.c car nous n'allons plus le modifier pour le reste du projet. Dans un autre fichier process.c (avec process.h), nous allons y mettre nos structures pour les process et leurs états puis une union pour le temps qui le caractérise ainsi que toutes les fonctions associés.&lt;br /&gt;
&lt;br /&gt;
[https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/Ordonnanceur Lien du répertoire]&lt;br /&gt;
&lt;br /&gt;
=== Processus ===&lt;br /&gt;
==== Structure ====&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:right; width: 48%; padding-left: 10px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
    uint16_t adresseDepart;  //adresse de la fonction de départ &lt;br /&gt;
    uint16_t adressePile;       //adresse de la pile d'exécution&lt;br /&gt;
    Etat etat;        &lt;br /&gt;
} Process;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Notre structure caractérisant un processus est définie par les trois champs ci-contre.&lt;br /&gt;
&lt;br /&gt;
Une adresse de départ correspondant à la fonction du processus associé, l'adresse où se situe le processus dans la pile puis l'état de la tâche. Nous avons décidé de faire une structure à part entière compte tenu des multitudes d'états que nous pourrons ajouter pendant la progression du projet.&lt;br /&gt;
&lt;br /&gt;
==== Etat d'un processus ====&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:right; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
typedef union {&lt;br /&gt;
  int sleepingtime;       &lt;br /&gt;
} Time;&lt;br /&gt;
&lt;br /&gt;
typedef struct {&lt;br /&gt;
  int id;&lt;br /&gt;
  Time time;&lt;br /&gt;
} Etat ;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
L'état d'un processus est alors une structure à deux champs (pour l'instant), l'id doit correspondre à un '#DEFINE' pour avoir un sens tandis que nous avons choisi de faire une union pour le temps qui caractérise notre état afin qu'il puisse avoir un nom et type de variable cohérent avec son état.(Ici seulement sleepingtime car seul l'état endormi existe pour le moment)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
  {| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
  |+ Tableau des états&lt;br /&gt;
  |-&lt;br /&gt;
  ! Etat !! ACTIVE !! SLEEPY !! ... !! ...&lt;br /&gt;
  |-&lt;br /&gt;
  | Id || 0 || 1 || ... || ...&lt;br /&gt;
  |}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Procédures principales ====&lt;br /&gt;
&lt;br /&gt;
=== ISR ===&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:right; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
ISR(TIMER1_COMPA_vect, ISR_NAKED)    // Procédure d'interruption&lt;br /&gt;
{&lt;br /&gt;
  TCNT1=0;//reset timer&lt;br /&gt;
  /* Sauvegarde du contexte de la tâche interrompue */&lt;br /&gt;
  portSAVE_REGISTERS();&lt;br /&gt;
   table_process[indice_tache].adressePile = SP;&lt;br /&gt;
  /* Appel à l'ordonnanceur */&lt;br /&gt;
  selectProcess();&lt;br /&gt;
  /* Récupération du contexte de la tâche ré-activée */&lt;br /&gt;
  SP = table_process[indice_tache].adressePile;&lt;br /&gt;
  portRESTORE_REGISTERS();&lt;br /&gt;
  &lt;br /&gt;
  asm volatile ( &amp;quot;reti&amp;quot; );&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
L'ISR est ce qu'il va être executer lors des interruptions toutes les 20 millisecondes. Cela consiste à sauvegarder tous les registres de la tâche qui était en cours avant l'appel de l'ISR pour ensuite passer à la tâche suivante valide (c'est à dire active) sans oublier de charger les registres de la nouvelle tâche.&lt;br /&gt;
&lt;br /&gt;
Nous devons également, à chaque fois avant de changer de tâche, enregistrer le pointeur de pile dans le processus afin de pouvoir revenir là ou elle en est la prochaine fois qu'elle sera appelée. Respectivement, une fois la nouvelle tâche choisie, le pointeur de pile doit prendre l'adresse de là ou en était la tâche avant qu'elle soit interrompue.&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Séléction de processus ====&lt;br /&gt;
Lors de la séléction de processus, nous devons parcourir tous les processus jusqu'au moment où nous en trouvons un actif. Ainsi, il deviendra la tâche que nous traiterons lors du prochain intervalle de 20 ms. A ce stade, à chaque fois que la procédure selectProcess est appelée, nous devons réduire le temps de repos de chaque process endormi de 20 ms. D'autres conditions pourrons être ajoutée si ajout d'état a lieu.&lt;br /&gt;
&lt;br /&gt;
=== Test ===&lt;br /&gt;
==== Clignotement de deux LED à fréquences indivisibles entre elles ====&lt;br /&gt;
Afin de vérifier la réussite de notre ordonnanceur à fonctionnement tourniquet, nous avons programmer deux simples tâches changeant l'état d'une LED. Une à une fréquence 200ms et l'autre 300ms (avec un _delay_ms).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:left; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void tache1(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTC ^= (1 &amp;lt;&amp;lt; PC0);&lt;br /&gt;
    _delay_ms(300);}}&lt;br /&gt;
void tache2(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTD ^= (1 &amp;lt;&amp;lt; PD7);&lt;br /&gt;
    _delay_ms(200);}}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
[[Fichier:B5_test1.mp4|vignette|alt=test des frequences imprevisibles|test des frequences imprevisibles]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Clignotement grâce à l'état endormi ====&lt;br /&gt;
Nous ajoutons l'état endormi afin que nos tâches ne mettent pas en pause l'ordonnanceur avec un _delay_ms. Pour cela, nous incorporons une fonction makeSleep qui permet de mettre la tâche qui l'appelle dans cet état.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:left; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void makeSleep(int t){&lt;br /&gt;
  table_process[indice_tache].etat.id = SLEEPY;&lt;br /&gt;
  table_process[indice_tache].etat.time.sleepingtime = t;&lt;br /&gt;
  TIMER1_COMPA_vect();}&lt;br /&gt;
void tache1(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTC ^= (1 &amp;lt;&amp;lt; PC0);&lt;br /&gt;
    _delay_ms(300);}}&lt;br /&gt;
void tache3(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTC ^= (1 &amp;lt;&amp;lt; PC3);&lt;br /&gt;
    //_delay_ms(1000);&lt;br /&gt;
    makeSleep(1000);}}&lt;br /&gt;
void tache2(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTD ^= (1 &amp;lt;&amp;lt; PD7);&lt;br /&gt;
    //_delay_ms(1000);&lt;br /&gt;
    makeSleep(700);}}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
[[Fichier:B5_test2.mp4|vignette|alt=test des frequences imprevisibles|test des frequences imprevisibles]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
A noter que la première tâche executée ne doit pas être endormie.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Carte Fille Matrice de touches =&lt;br /&gt;
==Explications générales sur la réalisation de la carte==&lt;br /&gt;
&lt;br /&gt;
Pour concevoir la carte fille dédiée au clavier, nous avons réutilisé un ancien clavier DELL équipé d’une matrice déjà fonctionnelle. L’idée consiste à connecter les sorties de cette matrice directement à notre carte fille à l’aide d’un connecteur adapté.&lt;br /&gt;
[[Fichier:Clavier dell.png||thumb|right|400px]]&lt;br /&gt;
Cependant, un défi se pose : la matrice du clavier comprend un total de 26 sorties (sans compter les LED et autres signaux). Cela dépasse largement les capacités en nombre de broches d’un ATmega328P.&lt;br /&gt;
&lt;br /&gt;
Pour remédier à ce problème, nous avons mis en place une solution d’encodage. Nous avons utilisé un décodeur (3 vers 8) pour gérer les lignes et trois encodeurs (8 vers 3) pour gérer les colonnes. Les encodeurs sont montés en parallèle pour réduire significativement le nombre de broches nécessaires.Cette solution permet de maximiser les ressources du microcontrôleur tout en gérant efficacement les signaux de la matrice.&lt;br /&gt;
&lt;br /&gt;
== Carte ==&lt;br /&gt;
&lt;br /&gt;
=== Fille après soudure des composants ===&lt;/div&gt;</summary>
		<author><name>Adjadjaa</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=Fichier:Clavier_dell.png&amp;diff=6841</id>
		<title>Fichier:Clavier dell.png</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=Fichier:Clavier_dell.png&amp;diff=6841"/>
		<updated>2024-11-20T10:16:28Z</updated>

		<summary type="html">&lt;p&gt;Adjadjaa : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;clavier dell&lt;/div&gt;</summary>
		<author><name>Adjadjaa</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-5&amp;diff=6839</id>
		<title>SE4Binome2024-5</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-5&amp;diff=6839"/>
		<updated>2024-11-20T10:08:19Z</updated>

		<summary type="html">&lt;p&gt;Adjadjaa : /* Carte Fille Matrice de touches */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Introduction=&lt;br /&gt;
&lt;br /&gt;
Ce wiki documente le développement d’un pico-ordinateur modulaire. Ce dernier est constitué d’une carte principale, composée d’une carte Shield permettant la connexion des cartes filles, et d’une carte mère (initialement simulée par une Arduino Uno avant sa conception finale). Plusieurs cartes filles sont prévues, chacune remplissant une fonction spécifique : gestion du clavier, affichage, port série, réseau, mémoire de masse et son.&lt;br /&gt;
&lt;br /&gt;
Notre binôme est spécifiquement chargé du développement de la carte fille dédiée au clavier.&lt;br /&gt;
&lt;br /&gt;
Toutes les ressources nécessaires, incluant les codes sources et les schémas, sont disponibles sur le dépôt Git suivant :  [https://gitea.plil.fr/ktouron/se4-djadja-touron_pico.git Lien du Git]&lt;br /&gt;
&lt;br /&gt;
= Carte Shield =&lt;br /&gt;
[[Fichier:Carte Recto non soudé.jpg|vignette|left|thumb|350px|Recto de la carte avant soudage des composants]]&lt;br /&gt;
[[Fichier:Verso non solder.jpeg.jpg|vignette|thumb|right|300px|Verso de la carte avant soudage des composants]]&lt;br /&gt;
[[Fichier:Carde shield soudé.jpg|vignette|thumb|center|350px|Photo de la carte avec les composants soudés]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Test==&lt;br /&gt;
=== Allumage de LEDS sur Programmateur AVR ===&lt;br /&gt;
Avant de programmer directement sur le shield, nous avons allumé des LED pour tester la carte. Nous avons directement utilisé le code exemple fourni par l'IDE arduino en adaptant simplement les pins correspondant aux leds. [https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/PicoShield/Programmation/Blink Code du test]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Vid_test_carte_mp4.mp4|vignette|thumb|center|700px|Vidéo de Test des leds]]&lt;br /&gt;
&lt;br /&gt;
=== Lecture de la carte SD ===&lt;br /&gt;
Avant de programmer directement sur le shield, nous avons tester si la carte SD était bien détectée et lue. On a utilisé le code test présent dans l'IDE arduino en adaptant le port utilisé.[https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/PicoShield/Programmation/CardInfo Code du test]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Resultat SD.jpg|vignette|thumb|center|700px|Carte SD bien détéctée]]&lt;br /&gt;
&lt;br /&gt;
=== Connecteurs IDC HE10 ===&lt;br /&gt;
Afin de tester nos connecteur HE10, nous avons utilisé un afficher 7 segments (Sparkfun 7 segments display). Pour pouvoir vérifier leurs fonctionnements nous avons branché l'afficheur sur chaque connecteur tour à tour. Le programme implanté est un simple connecteur à afficher sur l'afficheur. Voici une vidéo du compteur fonctionnant sur un des 5 connecteurs HE10. ([https://learn.sparkfun.com/tutorials/using-the-serial-7-segment-display/all Code ici (section : Example 2 SPI)])&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Se4-5-7segments.mp4|vignette|alt=se4-5-7segments|Test connecteur HE10 avec afficheur 7 segments.|center]]&lt;br /&gt;
== Ordonnanceur ==&lt;br /&gt;
Pour les interruptions de notre ordonnanceur nous avons utilisé la procédure d'initialisation du minuteur avec le Timer1 disponible dans les cours de Mr.Redon en renseignant une période de 20ms. Nous l'avons disposé dans le fichier minuteur.c car nous n'allons plus le modifier pour le reste du projet. Dans un autre fichier process.c (avec process.h), nous allons y mettre nos structures pour les process et leurs états puis une union pour le temps qui le caractérise ainsi que toutes les fonctions associés.&lt;br /&gt;
&lt;br /&gt;
[https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/Ordonnanceur Lien du répertoire]&lt;br /&gt;
&lt;br /&gt;
=== Processus ===&lt;br /&gt;
==== Structure ====&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:right; width: 48%; padding-left: 10px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
    uint16_t adresseDepart;  //adresse de la fonction de départ &lt;br /&gt;
    uint16_t adressePile;       //adresse de la pile d'exécution&lt;br /&gt;
    Etat etat;        &lt;br /&gt;
} Process;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Notre structure caractérisant un processus est définie par les trois champs ci-contre.&lt;br /&gt;
&lt;br /&gt;
Une adresse de départ correspondant à la fonction du processus associé, l'adresse où se situe le processus dans la pile puis l'état de la tâche. Nous avons décidé de faire une structure à part entière compte tenu des multitudes d'états que nous pourrons ajouter pendant la progression du projet.&lt;br /&gt;
&lt;br /&gt;
==== Etat d'un processus ====&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:right; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
typedef union {&lt;br /&gt;
  int sleepingtime;       &lt;br /&gt;
} Time;&lt;br /&gt;
&lt;br /&gt;
typedef struct {&lt;br /&gt;
  int id;&lt;br /&gt;
  Time time;&lt;br /&gt;
} Etat ;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
L'état d'un processus est alors une structure à deux champs (pour l'instant), l'id doit correspondre à un '#DEFINE' pour avoir un sens tandis que nous avons choisi de faire une union pour le temps qui caractérise notre état afin qu'il puisse avoir un nom et type de variable cohérent avec son état.(Ici seulement sleepingtime car seul l'état endormi existe pour le moment)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
  {| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
  |+ Tableau des états&lt;br /&gt;
  |-&lt;br /&gt;
  ! Etat !! ACTIVE !! SLEEPY !! ... !! ...&lt;br /&gt;
  |-&lt;br /&gt;
  | Id || 0 || 1 || ... || ...&lt;br /&gt;
  |}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Procédures principales ====&lt;br /&gt;
&lt;br /&gt;
=== ISR ===&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:right; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
ISR(TIMER1_COMPA_vect, ISR_NAKED)    // Procédure d'interruption&lt;br /&gt;
{&lt;br /&gt;
  TCNT1=0;//reset timer&lt;br /&gt;
  /* Sauvegarde du contexte de la tâche interrompue */&lt;br /&gt;
  portSAVE_REGISTERS();&lt;br /&gt;
   table_process[indice_tache].adressePile = SP;&lt;br /&gt;
  /* Appel à l'ordonnanceur */&lt;br /&gt;
  selectProcess();&lt;br /&gt;
  /* Récupération du contexte de la tâche ré-activée */&lt;br /&gt;
  SP = table_process[indice_tache].adressePile;&lt;br /&gt;
  portRESTORE_REGISTERS();&lt;br /&gt;
  &lt;br /&gt;
  asm volatile ( &amp;quot;reti&amp;quot; );&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
L'ISR est ce qu'il va être executer lors des interruptions toutes les 20 millisecondes. Cela consiste à sauvegarder tous les registres de la tâche qui était en cours avant l'appel de l'ISR pour ensuite passer à la tâche suivante valide (c'est à dire active) sans oublier de charger les registres de la nouvelle tâche.&lt;br /&gt;
&lt;br /&gt;
Nous devons également, à chaque fois avant de changer de tâche, enregistrer le pointeur de pile dans le processus afin de pouvoir revenir là ou elle en est la prochaine fois qu'elle sera appelée. Respectivement, une fois la nouvelle tâche choisie, le pointeur de pile doit prendre l'adresse de là ou en était la tâche avant qu'elle soit interrompue.&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Séléction de processus ====&lt;br /&gt;
Lors de la séléction de processus, nous devons parcourir tous les processus jusqu'au moment où nous en trouvons un actif. Ainsi, il deviendra la tâche que nous traiterons lors du prochain intervalle de 20 ms. A ce stade, à chaque fois que la procédure selectProcess est appelée, nous devons réduire le temps de repos de chaque process endormi de 20 ms. D'autres conditions pourrons être ajoutée si ajout d'état a lieu.&lt;br /&gt;
&lt;br /&gt;
=== Test ===&lt;br /&gt;
==== Clignotement de deux LED à fréquences indivisibles entre elles ====&lt;br /&gt;
Afin de vérifier la réussite de notre ordonnanceur à fonctionnement tourniquet, nous avons programmer deux simples tâches changeant l'état d'une LED. Une à une fréquence 200ms et l'autre 300ms (avec un _delay_ms).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:left; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void tache1(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTC ^= (1 &amp;lt;&amp;lt; PC0);&lt;br /&gt;
    _delay_ms(300);}}&lt;br /&gt;
void tache2(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTD ^= (1 &amp;lt;&amp;lt; PD7);&lt;br /&gt;
    _delay_ms(200);}}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
[[Fichier:B5_test1.mp4|vignette|alt=test des frequences imprevisibles|test des frequences imprevisibles]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Clignotement grâce à l'état endormi ====&lt;br /&gt;
Nous ajoutons l'état endormi afin que nos tâches ne mettent pas en pause l'ordonnanceur avec un _delay_ms. Pour cela, nous incorporons une fonction makeSleep qui permet de mettre la tâche qui l'appelle dans cet état.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:left; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void makeSleep(int t){&lt;br /&gt;
  table_process[indice_tache].etat.id = SLEEPY;&lt;br /&gt;
  table_process[indice_tache].etat.time.sleepingtime = t;&lt;br /&gt;
  TIMER1_COMPA_vect();}&lt;br /&gt;
void tache1(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTC ^= (1 &amp;lt;&amp;lt; PC0);&lt;br /&gt;
    _delay_ms(300);}}&lt;br /&gt;
void tache3(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTC ^= (1 &amp;lt;&amp;lt; PC3);&lt;br /&gt;
    //_delay_ms(1000);&lt;br /&gt;
    makeSleep(1000);}}&lt;br /&gt;
void tache2(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTD ^= (1 &amp;lt;&amp;lt; PD7);&lt;br /&gt;
    //_delay_ms(1000);&lt;br /&gt;
    makeSleep(700);}}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
[[Fichier:B5_test2.mp4|vignette|alt=test des frequences imprevisibles|test des frequences imprevisibles]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
A noter que la première tâche executée ne doit pas être endormie.&lt;br /&gt;
&lt;br /&gt;
= Carte Fille Matrice de touches =&lt;br /&gt;
==Explications générales sur la réalisation de la carte==&lt;br /&gt;
&lt;br /&gt;
Pour concevoir la carte fille dédiée au clavier, nous avons réutilisé un ancien clavier DELL équipé d’une matrice déjà fonctionnelle. L’idée consiste à connecter les sorties de cette matrice directement à notre carte fille à l’aide d’un connecteur adapté.&lt;br /&gt;
&lt;br /&gt;
Cependant, un défi se pose : la matrice du clavier comprend un total de 26 sorties (sans compter les LED et autres signaux). Cela dépasse largement les capacités en nombre de broches d’un ATmega328P.&lt;br /&gt;
&lt;br /&gt;
Pour remédier à ce problème, nous avons mis en place une solution d’encodage. Nous avons utilisé un décodeur (3 vers 8) pour gérer les lignes et trois encodeurs (8 vers 3) pour gérer les colonnes. Les encodeurs sont montés en parallèle pour réduire significativement le nombre de broches nécessaires.Cette solution permet de maximiser les ressources du microcontrôleur tout en gérant efficacement les signaux de la matrice.&lt;br /&gt;
&lt;br /&gt;
== Carte ==&lt;br /&gt;
&lt;br /&gt;
=== Fille après soudure des composants ===&lt;/div&gt;</summary>
		<author><name>Adjadjaa</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-5&amp;diff=6752</id>
		<title>SE4Binome2024-5</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-5&amp;diff=6752"/>
		<updated>2024-11-18T11:08:34Z</updated>

		<summary type="html">&lt;p&gt;Adjadjaa : /* Carte Shield */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Introduction=&lt;br /&gt;
&lt;br /&gt;
Ce wiki documente le développement d’un pico-ordinateur modulaire. Ce dernier est constitué d’une carte principale, composée d’une carte Shield permettant la connexion des cartes filles, et d’une carte mère (initialement simulée par une Arduino Uno avant sa conception finale). Plusieurs cartes filles sont prévues, chacune remplissant une fonction spécifique : gestion du clavier, affichage, port série, réseau, mémoire de masse et son.&lt;br /&gt;
&lt;br /&gt;
Notre binôme est spécifiquement chargé du développement de la carte fille dédiée au clavier.&lt;br /&gt;
&lt;br /&gt;
Toutes les ressources nécessaires, incluant les codes sources et les schémas, sont disponibles sur le dépôt Git suivant :  [https://gitea.plil.fr/ktouron/se4-djadja-touron_pico.git Lien du Git]&lt;br /&gt;
&lt;br /&gt;
= Carte Shield =&lt;br /&gt;
[[Fichier:Carte Recto non soudé.jpg|vignette|left|thumb|350px|Recto de la carte avant soudage des composants]]&lt;br /&gt;
[[Fichier:Verso non solder.jpeg.jpg|vignette|thumb|right|300px|Verso de la carte avant soudage des composants]]&lt;br /&gt;
[[Fichier:Carde shield soudé.jpg|vignette|thumb|center|350px|Photo de la carte avec les composants soudés]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Test==&lt;br /&gt;
=== Allumage de LEDS sur Programmateur AVR ===&lt;br /&gt;
Avant de programmer directement sur le shield, nous avons allumé des LED pour tester la carte. Nous avons directement utilisé le code exemple fourni par l'IDE arduino en adaptant simplement les pins correspondant aux leds. [https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/PicoShield/Programmation/Blink Code du test]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Vid_test_carte_mp4.mp4|vignette|thumb|center|700px|Vidéo de Test des leds]]&lt;br /&gt;
&lt;br /&gt;
=== Lecture de la carte SD ===&lt;br /&gt;
Avant de programmer directement sur le shield, nous avons tester si la carte SD était bien détectée et lue. On a utilisé le code test présent dans l'IDE arduino en adaptant le port utilisé.[https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/PicoShield/Programmation/CardInfo Code du test]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Resultat SD.jpg|vignette|thumb|center|700px|Carte SD bien détéctée]]&lt;br /&gt;
&lt;br /&gt;
=== Connecteurs IDC HE10 ===&lt;br /&gt;
Afin de tester nos connecteur HE10, nous avons utilisé un afficher 7 segments (Sparkfun 7 segments display). Pour pouvoir vérifier leurs fonctionnements nous avons branché l'afficheur sur chaque connecteur tour à tour. Le programme implanté est un simple connecteur à afficher sur l'afficheur. Voici une vidéo du compteur fonctionnant sur un des 5 connecteurs HE10. ([https://learn.sparkfun.com/tutorials/using-the-serial-7-segment-display/all Code ici (section : Example 2 SPI)])&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Se4-5-7segments.mp4|vignette|alt=se4-5-7segments|Test connecteur HE10 avec afficheur 7 segments.|center]]&lt;br /&gt;
== Ordonnanceur ==&lt;br /&gt;
Pour les interruptions de notre ordonnanceur nous avons utilisé la procédure d'initialisation du minuteur avec le Timer1 disponible dans les cours de Mr.Redon en renseignant une période de 20ms. Nous l'avons disposé dans le fichier minuteur.c car nous n'allons plus le modifier pour le reste du projet. Dans un autre fichier process.c (avec process.h), nous allons y mettre nos structures pour les process et leurs états puis une union pour le temps qui le caractérise ainsi que toutes les fonctions associés.&lt;br /&gt;
&lt;br /&gt;
[https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/Ordonnanceur Lien du répertoire]&lt;br /&gt;
&lt;br /&gt;
=== Processus ===&lt;br /&gt;
==== Structure ====&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:right; width: 48%; padding-left: 10px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
    uint16_t adresseDepart;  //adresse de la fonction de départ &lt;br /&gt;
    uint16_t adressePile;       //adresse de la pile d'exécution&lt;br /&gt;
    Etat etat;        &lt;br /&gt;
} Process;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Notre structure caractérisant un processus est définie par les trois champs ci-contre.&lt;br /&gt;
&lt;br /&gt;
Une adresse de départ correspondant à la fonction du processus associé, l'adresse où se situe le processus dans la pile puis l'état de la tâche. Nous avons décidé de faire une structure à part entière compte tenu des multitudes d'états que nous pourrons ajouter pendant la progression du projet.&lt;br /&gt;
&lt;br /&gt;
==== Etat d'un processus ====&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:right; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
typedef union {&lt;br /&gt;
  int sleepingtime;       &lt;br /&gt;
} Time;&lt;br /&gt;
&lt;br /&gt;
typedef struct {&lt;br /&gt;
  int id;&lt;br /&gt;
  Time time;&lt;br /&gt;
} Etat ;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
L'état d'un processus est alors une structure à deux champs (pour l'instant), l'id doit correspondre à un '#DEFINE' pour avoir un sens tandis que nous avons choisi de faire une union pour le temps qui caractérise notre état afin qu'il puisse avoir un nom et type de variable cohérent avec son état.(Ici seulement sleepingtime car seul l'état endormi existe pour le moment)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
  {| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
  |+ Tableau des états&lt;br /&gt;
  |-&lt;br /&gt;
  ! Etat !! ACTIVE !! SLEEPY !! ... !! ...&lt;br /&gt;
  |-&lt;br /&gt;
  | Id || 0 || 1 || ... || ...&lt;br /&gt;
  |}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Procédures principales ====&lt;br /&gt;
&lt;br /&gt;
=== ISR ===&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:right; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
ISR(TIMER1_COMPA_vect, ISR_NAKED)    // Procédure d'interruption&lt;br /&gt;
{&lt;br /&gt;
  TCNT1=0;//reset timer&lt;br /&gt;
  /* Sauvegarde du contexte de la tâche interrompue */&lt;br /&gt;
  portSAVE_REGISTERS();&lt;br /&gt;
   table_process[indice_tache].adressePile = SP;&lt;br /&gt;
  /* Appel à l'ordonnanceur */&lt;br /&gt;
  selectProcess();&lt;br /&gt;
  /* Récupération du contexte de la tâche ré-activée */&lt;br /&gt;
  SP = table_process[indice_tache].adressePile;&lt;br /&gt;
  portRESTORE_REGISTERS();&lt;br /&gt;
  &lt;br /&gt;
  asm volatile ( &amp;quot;reti&amp;quot; );&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
L'ISR est ce qu'il va être executer lors des interruptions toutes les 20 millisecondes. Cela consiste à sauvegarder tous les registres de la tâche qui était en cours avant l'appel de l'ISR pour ensuite passer à la tâche suivante valide (c'est à dire active) sans oublier de charger les registres de la nouvelle tâche.&lt;br /&gt;
&lt;br /&gt;
Nous devons également, à chaque fois avant de changer de tâche, enregistrer le pointeur de pile dans le processus afin de pouvoir revenir là ou elle en est la prochaine fois qu'elle sera appelée. Respectivement, une fois la nouvelle tâche choisie, le pointeur de pile doit prendre l'adresse de là ou en était la tâche avant qu'elle soit interrompue.&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Séléction de processus ====&lt;br /&gt;
Lors de la séléction de processus, nous devons parcourir tous les processus jusqu'au moment où nous en trouvons un actif. Ainsi, il deviendra la tâche que nous traiterons lors du prochain intervalle de 20 ms. A ce stade, à chaque fois que la procédure selectProcess est appelée, nous devons réduire le temps de repos de chaque process endormi de 20 ms. D'autres conditions pourrons être ajoutée si ajout d'état a lieu.&lt;br /&gt;
&lt;br /&gt;
=== Test ===&lt;br /&gt;
==== Clignotement de deux LED à fréquences indivisibles entre elles ====&lt;br /&gt;
Afin de vérifier la réussite de notre ordonnanceur à fonctionnement tourniquet, nous avons programmer deux simples tâches changeant l'état d'une LED. Une à une fréquence 200ms et l'autre 300ms (avec un _delay_ms).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:left; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void tache1(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTC ^= (1 &amp;lt;&amp;lt; PC0);&lt;br /&gt;
    _delay_ms(300);}}&lt;br /&gt;
void tache2(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTD ^= (1 &amp;lt;&amp;lt; PD7);&lt;br /&gt;
    _delay_ms(200);}}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
[[Fichier:B5_test1.mp4|vignette|alt=test des frequences imprevisibles|test des frequences imprevisibles]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Clignotement grâce à l'état endormi ====&lt;br /&gt;
Nous ajoutons l'état endormi afin que nos tâches ne mettent pas en pause l'ordonnanceur avec un _delay_ms. Pour cela, nous incorporons une fonction makeSleep qui permet de mettre la tâche qui l'appelle dans cet état.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:left; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void makeSleep(int t){&lt;br /&gt;
  table_process[indice_tache].etat.id = SLEEPY;&lt;br /&gt;
  table_process[indice_tache].etat.time.sleepingtime = t;&lt;br /&gt;
  TIMER1_COMPA_vect();}&lt;br /&gt;
void tache1(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTC ^= (1 &amp;lt;&amp;lt; PC0);&lt;br /&gt;
    _delay_ms(300);}}&lt;br /&gt;
void tache3(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTC ^= (1 &amp;lt;&amp;lt; PC3);&lt;br /&gt;
    //_delay_ms(1000);&lt;br /&gt;
    makeSleep(1000);}}&lt;br /&gt;
void tache2(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTD ^= (1 &amp;lt;&amp;lt; PD7);&lt;br /&gt;
    //_delay_ms(1000);&lt;br /&gt;
    makeSleep(700);}}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
[[Fichier:B5_test2.mp4|vignette|alt=test des frequences imprevisibles|test des frequences imprevisibles]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
A noter que la première tâche executée ne doit pas être endormie.&lt;br /&gt;
&lt;br /&gt;
= Carte Fille Matrice de touches =&lt;br /&gt;
&lt;br /&gt;
== Carte ==&lt;br /&gt;
&lt;br /&gt;
=== Fille après soudure des composants ===&lt;/div&gt;</summary>
		<author><name>Adjadjaa</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-5&amp;diff=6751</id>
		<title>SE4Binome2024-5</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-5&amp;diff=6751"/>
		<updated>2024-11-18T11:07:37Z</updated>

		<summary type="html">&lt;p&gt;Adjadjaa : /* Carte Shield */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Introduction=&lt;br /&gt;
&lt;br /&gt;
Ce wiki documente le développement d’un pico-ordinateur modulaire. Ce dernier est constitué d’une carte principale, composée d’une carte Shield permettant la connexion des cartes filles, et d’une carte mère (initialement simulée par une Arduino Uno avant sa conception finale). Plusieurs cartes filles sont prévues, chacune remplissant une fonction spécifique : gestion du clavier, affichage, port série, réseau, mémoire de masse et son.&lt;br /&gt;
&lt;br /&gt;
Notre binôme est spécifiquement chargé du développement de la carte fille dédiée au clavier.&lt;br /&gt;
&lt;br /&gt;
Toutes les ressources nécessaires, incluant les codes sources et les schémas, sont disponibles sur le dépôt Git suivant :  [https://gitea.plil.fr/ktouron/se4-djadja-touron_pico.git Lien du Git]&lt;br /&gt;
&lt;br /&gt;
= Carte Shield =&lt;br /&gt;
[[Fichier:Carte Recto non soudé.jpg|vignette|left|thumb|350px|Recto de la carte avant soudage des composants]]&lt;br /&gt;
[[Fichier:Verso non solder.jpeg.jpg|vignette|thumb|center|350px|Verso de la carte avant soudage des composants]]&lt;br /&gt;
[[Fichier:Carde shield soudé.jpg|vignette|thumb|right|300px|Photo de la carte avec les composants soudés]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Test==&lt;br /&gt;
=== Allumage de LEDS sur Programmateur AVR ===&lt;br /&gt;
Avant de programmer directement sur le shield, nous avons allumé des LED pour tester la carte. Nous avons directement utilisé le code exemple fourni par l'IDE arduino en adaptant simplement les pins correspondant aux leds. [https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/PicoShield/Programmation/Blink Code du test]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Vid_test_carte_mp4.mp4|vignette|thumb|center|700px|Vidéo de Test des leds]]&lt;br /&gt;
&lt;br /&gt;
=== Lecture de la carte SD ===&lt;br /&gt;
Avant de programmer directement sur le shield, nous avons tester si la carte SD était bien détectée et lue. On a utilisé le code test présent dans l'IDE arduino en adaptant le port utilisé.[https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/PicoShield/Programmation/CardInfo Code du test]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Resultat SD.jpg|vignette|thumb|center|700px|Carte SD bien détéctée]]&lt;br /&gt;
&lt;br /&gt;
=== Connecteurs IDC HE10 ===&lt;br /&gt;
Afin de tester nos connecteur HE10, nous avons utilisé un afficher 7 segments (Sparkfun 7 segments display). Pour pouvoir vérifier leurs fonctionnements nous avons branché l'afficheur sur chaque connecteur tour à tour. Le programme implanté est un simple connecteur à afficher sur l'afficheur. Voici une vidéo du compteur fonctionnant sur un des 5 connecteurs HE10. ([https://learn.sparkfun.com/tutorials/using-the-serial-7-segment-display/all Code ici (section : Example 2 SPI)])&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Se4-5-7segments.mp4|vignette|alt=se4-5-7segments|Test connecteur HE10 avec afficheur 7 segments.|center]]&lt;br /&gt;
== Ordonnanceur ==&lt;br /&gt;
Pour les interruptions de notre ordonnanceur nous avons utilisé la procédure d'initialisation du minuteur avec le Timer1 disponible dans les cours de Mr.Redon en renseignant une période de 20ms. Nous l'avons disposé dans le fichier minuteur.c car nous n'allons plus le modifier pour le reste du projet. Dans un autre fichier process.c (avec process.h), nous allons y mettre nos structures pour les process et leurs états puis une union pour le temps qui le caractérise ainsi que toutes les fonctions associés.&lt;br /&gt;
&lt;br /&gt;
[https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/Ordonnanceur Lien du répertoire]&lt;br /&gt;
&lt;br /&gt;
=== Processus ===&lt;br /&gt;
==== Structure ====&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:right; width: 48%; padding-left: 10px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
    uint16_t adresseDepart;  //adresse de la fonction de départ &lt;br /&gt;
    uint16_t adressePile;       //adresse de la pile d'exécution&lt;br /&gt;
    Etat etat;        &lt;br /&gt;
} Process;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Notre structure caractérisant un processus est définie par les trois champs ci-contre.&lt;br /&gt;
&lt;br /&gt;
Une adresse de départ correspondant à la fonction du processus associé, l'adresse où se situe le processus dans la pile puis l'état de la tâche. Nous avons décidé de faire une structure à part entière compte tenu des multitudes d'états que nous pourrons ajouter pendant la progression du projet.&lt;br /&gt;
&lt;br /&gt;
==== Etat d'un processus ====&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:right; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
typedef union {&lt;br /&gt;
  int sleepingtime;       &lt;br /&gt;
} Time;&lt;br /&gt;
&lt;br /&gt;
typedef struct {&lt;br /&gt;
  int id;&lt;br /&gt;
  Time time;&lt;br /&gt;
} Etat ;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
L'état d'un processus est alors une structure à deux champs (pour l'instant), l'id doit correspondre à un '#DEFINE' pour avoir un sens tandis que nous avons choisi de faire une union pour le temps qui caractérise notre état afin qu'il puisse avoir un nom et type de variable cohérent avec son état.(Ici seulement sleepingtime car seul l'état endormi existe pour le moment)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
  {| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
  |+ Tableau des états&lt;br /&gt;
  |-&lt;br /&gt;
  ! Etat !! ACTIVE !! SLEEPY !! ... !! ...&lt;br /&gt;
  |-&lt;br /&gt;
  | Id || 0 || 1 || ... || ...&lt;br /&gt;
  |}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Procédures principales ====&lt;br /&gt;
&lt;br /&gt;
=== ISR ===&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:right; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
ISR(TIMER1_COMPA_vect, ISR_NAKED)    // Procédure d'interruption&lt;br /&gt;
{&lt;br /&gt;
  TCNT1=0;//reset timer&lt;br /&gt;
  /* Sauvegarde du contexte de la tâche interrompue */&lt;br /&gt;
  portSAVE_REGISTERS();&lt;br /&gt;
   table_process[indice_tache].adressePile = SP;&lt;br /&gt;
  /* Appel à l'ordonnanceur */&lt;br /&gt;
  selectProcess();&lt;br /&gt;
  /* Récupération du contexte de la tâche ré-activée */&lt;br /&gt;
  SP = table_process[indice_tache].adressePile;&lt;br /&gt;
  portRESTORE_REGISTERS();&lt;br /&gt;
  &lt;br /&gt;
  asm volatile ( &amp;quot;reti&amp;quot; );&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
L'ISR est ce qu'il va être executer lors des interruptions toutes les 20 millisecondes. Cela consiste à sauvegarder tous les registres de la tâche qui était en cours avant l'appel de l'ISR pour ensuite passer à la tâche suivante valide (c'est à dire active) sans oublier de charger les registres de la nouvelle tâche.&lt;br /&gt;
&lt;br /&gt;
Nous devons également, à chaque fois avant de changer de tâche, enregistrer le pointeur de pile dans le processus afin de pouvoir revenir là ou elle en est la prochaine fois qu'elle sera appelée. Respectivement, une fois la nouvelle tâche choisie, le pointeur de pile doit prendre l'adresse de là ou en était la tâche avant qu'elle soit interrompue.&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Séléction de processus ====&lt;br /&gt;
Lors de la séléction de processus, nous devons parcourir tous les processus jusqu'au moment où nous en trouvons un actif. Ainsi, il deviendra la tâche que nous traiterons lors du prochain intervalle de 20 ms. A ce stade, à chaque fois que la procédure selectProcess est appelée, nous devons réduire le temps de repos de chaque process endormi de 20 ms. D'autres conditions pourrons être ajoutée si ajout d'état a lieu.&lt;br /&gt;
&lt;br /&gt;
=== Test ===&lt;br /&gt;
==== Clignotement de deux LED à fréquences indivisibles entre elles ====&lt;br /&gt;
Afin de vérifier la réussite de notre ordonnanceur à fonctionnement tourniquet, nous avons programmer deux simples tâches changeant l'état d'une LED. Une à une fréquence 200ms et l'autre 300ms (avec un _delay_ms).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:left; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void tache1(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTC ^= (1 &amp;lt;&amp;lt; PC0);&lt;br /&gt;
    _delay_ms(300);}}&lt;br /&gt;
void tache2(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTD ^= (1 &amp;lt;&amp;lt; PD7);&lt;br /&gt;
    _delay_ms(200);}}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
[[Fichier:B5_test1.mp4|vignette|alt=test des frequences imprevisibles|test des frequences imprevisibles]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Clignotement grâce à l'état endormi ====&lt;br /&gt;
Nous ajoutons l'état endormi afin que nos tâches ne mettent pas en pause l'ordonnanceur avec un _delay_ms. Pour cela, nous incorporons une fonction makeSleep qui permet de mettre la tâche qui l'appelle dans cet état.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:left; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void makeSleep(int t){&lt;br /&gt;
  table_process[indice_tache].etat.id = SLEEPY;&lt;br /&gt;
  table_process[indice_tache].etat.time.sleepingtime = t;&lt;br /&gt;
  TIMER1_COMPA_vect();}&lt;br /&gt;
void tache1(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTC ^= (1 &amp;lt;&amp;lt; PC0);&lt;br /&gt;
    _delay_ms(300);}}&lt;br /&gt;
void tache3(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTC ^= (1 &amp;lt;&amp;lt; PC3);&lt;br /&gt;
    //_delay_ms(1000);&lt;br /&gt;
    makeSleep(1000);}}&lt;br /&gt;
void tache2(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTD ^= (1 &amp;lt;&amp;lt; PD7);&lt;br /&gt;
    //_delay_ms(1000);&lt;br /&gt;
    makeSleep(700);}}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
[[Fichier:B5_test2.mp4|vignette|alt=test des frequences imprevisibles|test des frequences imprevisibles]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
A noter que la première tâche executée ne doit pas être endormie.&lt;br /&gt;
&lt;br /&gt;
= Carte Fille Matrice de touches =&lt;br /&gt;
&lt;br /&gt;
== Carte ==&lt;br /&gt;
&lt;br /&gt;
=== Fille après soudure des composants ===&lt;/div&gt;</summary>
		<author><name>Adjadjaa</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-5&amp;diff=6750</id>
		<title>SE4Binome2024-5</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-5&amp;diff=6750"/>
		<updated>2024-11-18T11:07:10Z</updated>

		<summary type="html">&lt;p&gt;Adjadjaa : /* Carte Shield */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Introduction=&lt;br /&gt;
&lt;br /&gt;
Ce wiki documente le développement d’un pico-ordinateur modulaire. Ce dernier est constitué d’une carte principale, composée d’une carte Shield permettant la connexion des cartes filles, et d’une carte mère (initialement simulée par une Arduino Uno avant sa conception finale). Plusieurs cartes filles sont prévues, chacune remplissant une fonction spécifique : gestion du clavier, affichage, port série, réseau, mémoire de masse et son.&lt;br /&gt;
&lt;br /&gt;
Notre binôme est spécifiquement chargé du développement de la carte fille dédiée au clavier.&lt;br /&gt;
&lt;br /&gt;
Toutes les ressources nécessaires, incluant les codes sources et les schémas, sont disponibles sur le dépôt Git suivant :  [https://gitea.plil.fr/ktouron/se4-djadja-touron_pico.git Lien du Git]&lt;br /&gt;
&lt;br /&gt;
= Carte Shield =&lt;br /&gt;
[[Fichier:Carte Recto non soudé.jpg|vignette|left|thumb|350px|Recto de la carte avant soudage des composants]]&lt;br /&gt;
[[Fichier:Verso non solder.jpeg.jpg|vignette|left|thumb|350px|Verso de la carte avant soudage des composants]]&lt;br /&gt;
[[Fichier:Carde shield soudé.jpg|vignette|thumb|right|300px|Photo de la carte avec les composants soudés]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Test==&lt;br /&gt;
=== Allumage de LEDS sur Programmateur AVR ===&lt;br /&gt;
Avant de programmer directement sur le shield, nous avons allumé des LED pour tester la carte. Nous avons directement utilisé le code exemple fourni par l'IDE arduino en adaptant simplement les pins correspondant aux leds. [https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/PicoShield/Programmation/Blink Code du test]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Vid_test_carte_mp4.mp4|vignette|thumb|center|700px|Vidéo de Test des leds]]&lt;br /&gt;
&lt;br /&gt;
=== Lecture de la carte SD ===&lt;br /&gt;
Avant de programmer directement sur le shield, nous avons tester si la carte SD était bien détectée et lue. On a utilisé le code test présent dans l'IDE arduino en adaptant le port utilisé.[https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/PicoShield/Programmation/CardInfo Code du test]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Resultat SD.jpg|vignette|thumb|center|700px|Carte SD bien détéctée]]&lt;br /&gt;
&lt;br /&gt;
=== Connecteurs IDC HE10 ===&lt;br /&gt;
Afin de tester nos connecteur HE10, nous avons utilisé un afficher 7 segments (Sparkfun 7 segments display). Pour pouvoir vérifier leurs fonctionnements nous avons branché l'afficheur sur chaque connecteur tour à tour. Le programme implanté est un simple connecteur à afficher sur l'afficheur. Voici une vidéo du compteur fonctionnant sur un des 5 connecteurs HE10. ([https://learn.sparkfun.com/tutorials/using-the-serial-7-segment-display/all Code ici (section : Example 2 SPI)])&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Se4-5-7segments.mp4|vignette|alt=se4-5-7segments|Test connecteur HE10 avec afficheur 7 segments.|center]]&lt;br /&gt;
== Ordonnanceur ==&lt;br /&gt;
Pour les interruptions de notre ordonnanceur nous avons utilisé la procédure d'initialisation du minuteur avec le Timer1 disponible dans les cours de Mr.Redon en renseignant une période de 20ms. Nous l'avons disposé dans le fichier minuteur.c car nous n'allons plus le modifier pour le reste du projet. Dans un autre fichier process.c (avec process.h), nous allons y mettre nos structures pour les process et leurs états puis une union pour le temps qui le caractérise ainsi que toutes les fonctions associés.&lt;br /&gt;
&lt;br /&gt;
[https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/Ordonnanceur Lien du répertoire]&lt;br /&gt;
&lt;br /&gt;
=== Processus ===&lt;br /&gt;
==== Structure ====&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:right; width: 48%; padding-left: 10px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
    uint16_t adresseDepart;  //adresse de la fonction de départ &lt;br /&gt;
    uint16_t adressePile;       //adresse de la pile d'exécution&lt;br /&gt;
    Etat etat;        &lt;br /&gt;
} Process;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Notre structure caractérisant un processus est définie par les trois champs ci-contre.&lt;br /&gt;
&lt;br /&gt;
Une adresse de départ correspondant à la fonction du processus associé, l'adresse où se situe le processus dans la pile puis l'état de la tâche. Nous avons décidé de faire une structure à part entière compte tenu des multitudes d'états que nous pourrons ajouter pendant la progression du projet.&lt;br /&gt;
&lt;br /&gt;
==== Etat d'un processus ====&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:right; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
typedef union {&lt;br /&gt;
  int sleepingtime;       &lt;br /&gt;
} Time;&lt;br /&gt;
&lt;br /&gt;
typedef struct {&lt;br /&gt;
  int id;&lt;br /&gt;
  Time time;&lt;br /&gt;
} Etat ;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
L'état d'un processus est alors une structure à deux champs (pour l'instant), l'id doit correspondre à un '#DEFINE' pour avoir un sens tandis que nous avons choisi de faire une union pour le temps qui caractérise notre état afin qu'il puisse avoir un nom et type de variable cohérent avec son état.(Ici seulement sleepingtime car seul l'état endormi existe pour le moment)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
  {| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
  |+ Tableau des états&lt;br /&gt;
  |-&lt;br /&gt;
  ! Etat !! ACTIVE !! SLEEPY !! ... !! ...&lt;br /&gt;
  |-&lt;br /&gt;
  | Id || 0 || 1 || ... || ...&lt;br /&gt;
  |}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Procédures principales ====&lt;br /&gt;
&lt;br /&gt;
=== ISR ===&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:right; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
ISR(TIMER1_COMPA_vect, ISR_NAKED)    // Procédure d'interruption&lt;br /&gt;
{&lt;br /&gt;
  TCNT1=0;//reset timer&lt;br /&gt;
  /* Sauvegarde du contexte de la tâche interrompue */&lt;br /&gt;
  portSAVE_REGISTERS();&lt;br /&gt;
   table_process[indice_tache].adressePile = SP;&lt;br /&gt;
  /* Appel à l'ordonnanceur */&lt;br /&gt;
  selectProcess();&lt;br /&gt;
  /* Récupération du contexte de la tâche ré-activée */&lt;br /&gt;
  SP = table_process[indice_tache].adressePile;&lt;br /&gt;
  portRESTORE_REGISTERS();&lt;br /&gt;
  &lt;br /&gt;
  asm volatile ( &amp;quot;reti&amp;quot; );&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
L'ISR est ce qu'il va être executer lors des interruptions toutes les 20 millisecondes. Cela consiste à sauvegarder tous les registres de la tâche qui était en cours avant l'appel de l'ISR pour ensuite passer à la tâche suivante valide (c'est à dire active) sans oublier de charger les registres de la nouvelle tâche.&lt;br /&gt;
&lt;br /&gt;
Nous devons également, à chaque fois avant de changer de tâche, enregistrer le pointeur de pile dans le processus afin de pouvoir revenir là ou elle en est la prochaine fois qu'elle sera appelée. Respectivement, une fois la nouvelle tâche choisie, le pointeur de pile doit prendre l'adresse de là ou en était la tâche avant qu'elle soit interrompue.&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Séléction de processus ====&lt;br /&gt;
Lors de la séléction de processus, nous devons parcourir tous les processus jusqu'au moment où nous en trouvons un actif. Ainsi, il deviendra la tâche que nous traiterons lors du prochain intervalle de 20 ms. A ce stade, à chaque fois que la procédure selectProcess est appelée, nous devons réduire le temps de repos de chaque process endormi de 20 ms. D'autres conditions pourrons être ajoutée si ajout d'état a lieu.&lt;br /&gt;
&lt;br /&gt;
=== Test ===&lt;br /&gt;
==== Clignotement de deux LED à fréquences indivisibles entre elles ====&lt;br /&gt;
Afin de vérifier la réussite de notre ordonnanceur à fonctionnement tourniquet, nous avons programmer deux simples tâches changeant l'état d'une LED. Une à une fréquence 200ms et l'autre 300ms (avec un _delay_ms).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:left; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void tache1(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTC ^= (1 &amp;lt;&amp;lt; PC0);&lt;br /&gt;
    _delay_ms(300);}}&lt;br /&gt;
void tache2(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTD ^= (1 &amp;lt;&amp;lt; PD7);&lt;br /&gt;
    _delay_ms(200);}}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
[[Fichier:B5_test1.mp4|vignette|alt=test des frequences imprevisibles|test des frequences imprevisibles]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Clignotement grâce à l'état endormi ====&lt;br /&gt;
Nous ajoutons l'état endormi afin que nos tâches ne mettent pas en pause l'ordonnanceur avec un _delay_ms. Pour cela, nous incorporons une fonction makeSleep qui permet de mettre la tâche qui l'appelle dans cet état.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:left; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void makeSleep(int t){&lt;br /&gt;
  table_process[indice_tache].etat.id = SLEEPY;&lt;br /&gt;
  table_process[indice_tache].etat.time.sleepingtime = t;&lt;br /&gt;
  TIMER1_COMPA_vect();}&lt;br /&gt;
void tache1(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTC ^= (1 &amp;lt;&amp;lt; PC0);&lt;br /&gt;
    _delay_ms(300);}}&lt;br /&gt;
void tache3(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTC ^= (1 &amp;lt;&amp;lt; PC3);&lt;br /&gt;
    //_delay_ms(1000);&lt;br /&gt;
    makeSleep(1000);}}&lt;br /&gt;
void tache2(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTD ^= (1 &amp;lt;&amp;lt; PD7);&lt;br /&gt;
    //_delay_ms(1000);&lt;br /&gt;
    makeSleep(700);}}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
[[Fichier:B5_test2.mp4|vignette|alt=test des frequences imprevisibles|test des frequences imprevisibles]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
A noter que la première tâche executée ne doit pas être endormie.&lt;br /&gt;
&lt;br /&gt;
= Carte Fille Matrice de touches =&lt;br /&gt;
&lt;br /&gt;
== Carte ==&lt;br /&gt;
&lt;br /&gt;
=== Fille après soudure des composants ===&lt;/div&gt;</summary>
		<author><name>Adjadjaa</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-5&amp;diff=6749</id>
		<title>SE4Binome2024-5</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-5&amp;diff=6749"/>
		<updated>2024-11-18T11:06:38Z</updated>

		<summary type="html">&lt;p&gt;Adjadjaa : /* Carte Shield */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Introduction=&lt;br /&gt;
&lt;br /&gt;
Ce wiki documente le développement d’un pico-ordinateur modulaire. Ce dernier est constitué d’une carte principale, composée d’une carte Shield permettant la connexion des cartes filles, et d’une carte mère (initialement simulée par une Arduino Uno avant sa conception finale). Plusieurs cartes filles sont prévues, chacune remplissant une fonction spécifique : gestion du clavier, affichage, port série, réseau, mémoire de masse et son.&lt;br /&gt;
&lt;br /&gt;
Notre binôme est spécifiquement chargé du développement de la carte fille dédiée au clavier.&lt;br /&gt;
&lt;br /&gt;
Toutes les ressources nécessaires, incluant les codes sources et les schémas, sont disponibles sur le dépôt Git suivant :  [https://gitea.plil.fr/ktouron/se4-djadja-touron_pico.git Lien du Git]&lt;br /&gt;
&lt;br /&gt;
= Carte Shield =&lt;br /&gt;
[[Fichier:Carte Recto non soudé.jpg|vignette|left|thumb|350px|Recto de la carte avant soudage des composants]]&lt;br /&gt;
[[Fichier:Verso non solder.jpeg.jpg|vignette|thumb|center|350px|Verso de la carte avant soudage des composants]]&lt;br /&gt;
[[Fichier:Carde shield soudé.jpg|vignette|thumb|right|300px|Photo de la carte avec les composants soudés]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Test==&lt;br /&gt;
=== Allumage de LEDS sur Programmateur AVR ===&lt;br /&gt;
Avant de programmer directement sur le shield, nous avons allumé des LED pour tester la carte. Nous avons directement utilisé le code exemple fourni par l'IDE arduino en adaptant simplement les pins correspondant aux leds. [https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/PicoShield/Programmation/Blink Code du test]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Vid_test_carte_mp4.mp4|vignette|thumb|center|700px|Vidéo de Test des leds]]&lt;br /&gt;
&lt;br /&gt;
=== Lecture de la carte SD ===&lt;br /&gt;
Avant de programmer directement sur le shield, nous avons tester si la carte SD était bien détectée et lue. On a utilisé le code test présent dans l'IDE arduino en adaptant le port utilisé.[https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/PicoShield/Programmation/CardInfo Code du test]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Resultat SD.jpg|vignette|thumb|center|700px|Carte SD bien détéctée]]&lt;br /&gt;
&lt;br /&gt;
=== Connecteurs IDC HE10 ===&lt;br /&gt;
Afin de tester nos connecteur HE10, nous avons utilisé un afficher 7 segments (Sparkfun 7 segments display). Pour pouvoir vérifier leurs fonctionnements nous avons branché l'afficheur sur chaque connecteur tour à tour. Le programme implanté est un simple connecteur à afficher sur l'afficheur. Voici une vidéo du compteur fonctionnant sur un des 5 connecteurs HE10. ([https://learn.sparkfun.com/tutorials/using-the-serial-7-segment-display/all Code ici (section : Example 2 SPI)])&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Se4-5-7segments.mp4|vignette|alt=se4-5-7segments|Test connecteur HE10 avec afficheur 7 segments.|center]]&lt;br /&gt;
== Ordonnanceur ==&lt;br /&gt;
Pour les interruptions de notre ordonnanceur nous avons utilisé la procédure d'initialisation du minuteur avec le Timer1 disponible dans les cours de Mr.Redon en renseignant une période de 20ms. Nous l'avons disposé dans le fichier minuteur.c car nous n'allons plus le modifier pour le reste du projet. Dans un autre fichier process.c (avec process.h), nous allons y mettre nos structures pour les process et leurs états puis une union pour le temps qui le caractérise ainsi que toutes les fonctions associés.&lt;br /&gt;
&lt;br /&gt;
[https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/Ordonnanceur Lien du répertoire]&lt;br /&gt;
&lt;br /&gt;
=== Processus ===&lt;br /&gt;
==== Structure ====&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:right; width: 48%; padding-left: 10px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
    uint16_t adresseDepart;  //adresse de la fonction de départ &lt;br /&gt;
    uint16_t adressePile;       //adresse de la pile d'exécution&lt;br /&gt;
    Etat etat;        &lt;br /&gt;
} Process;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Notre structure caractérisant un processus est définie par les trois champs ci-contre.&lt;br /&gt;
&lt;br /&gt;
Une adresse de départ correspondant à la fonction du processus associé, l'adresse où se situe le processus dans la pile puis l'état de la tâche. Nous avons décidé de faire une structure à part entière compte tenu des multitudes d'états que nous pourrons ajouter pendant la progression du projet.&lt;br /&gt;
&lt;br /&gt;
==== Etat d'un processus ====&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:right; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
typedef union {&lt;br /&gt;
  int sleepingtime;       &lt;br /&gt;
} Time;&lt;br /&gt;
&lt;br /&gt;
typedef struct {&lt;br /&gt;
  int id;&lt;br /&gt;
  Time time;&lt;br /&gt;
} Etat ;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
L'état d'un processus est alors une structure à deux champs (pour l'instant), l'id doit correspondre à un '#DEFINE' pour avoir un sens tandis que nous avons choisi de faire une union pour le temps qui caractérise notre état afin qu'il puisse avoir un nom et type de variable cohérent avec son état.(Ici seulement sleepingtime car seul l'état endormi existe pour le moment)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
  {| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
  |+ Tableau des états&lt;br /&gt;
  |-&lt;br /&gt;
  ! Etat !! ACTIVE !! SLEEPY !! ... !! ...&lt;br /&gt;
  |-&lt;br /&gt;
  | Id || 0 || 1 || ... || ...&lt;br /&gt;
  |}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Procédures principales ====&lt;br /&gt;
&lt;br /&gt;
=== ISR ===&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:right; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
ISR(TIMER1_COMPA_vect, ISR_NAKED)    // Procédure d'interruption&lt;br /&gt;
{&lt;br /&gt;
  TCNT1=0;//reset timer&lt;br /&gt;
  /* Sauvegarde du contexte de la tâche interrompue */&lt;br /&gt;
  portSAVE_REGISTERS();&lt;br /&gt;
   table_process[indice_tache].adressePile = SP;&lt;br /&gt;
  /* Appel à l'ordonnanceur */&lt;br /&gt;
  selectProcess();&lt;br /&gt;
  /* Récupération du contexte de la tâche ré-activée */&lt;br /&gt;
  SP = table_process[indice_tache].adressePile;&lt;br /&gt;
  portRESTORE_REGISTERS();&lt;br /&gt;
  &lt;br /&gt;
  asm volatile ( &amp;quot;reti&amp;quot; );&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
L'ISR est ce qu'il va être executer lors des interruptions toutes les 20 millisecondes. Cela consiste à sauvegarder tous les registres de la tâche qui était en cours avant l'appel de l'ISR pour ensuite passer à la tâche suivante valide (c'est à dire active) sans oublier de charger les registres de la nouvelle tâche.&lt;br /&gt;
&lt;br /&gt;
Nous devons également, à chaque fois avant de changer de tâche, enregistrer le pointeur de pile dans le processus afin de pouvoir revenir là ou elle en est la prochaine fois qu'elle sera appelée. Respectivement, une fois la nouvelle tâche choisie, le pointeur de pile doit prendre l'adresse de là ou en était la tâche avant qu'elle soit interrompue.&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Séléction de processus ====&lt;br /&gt;
Lors de la séléction de processus, nous devons parcourir tous les processus jusqu'au moment où nous en trouvons un actif. Ainsi, il deviendra la tâche que nous traiterons lors du prochain intervalle de 20 ms. A ce stade, à chaque fois que la procédure selectProcess est appelée, nous devons réduire le temps de repos de chaque process endormi de 20 ms. D'autres conditions pourrons être ajoutée si ajout d'état a lieu.&lt;br /&gt;
&lt;br /&gt;
=== Test ===&lt;br /&gt;
==== Clignotement de deux LED à fréquences indivisibles entre elles ====&lt;br /&gt;
Afin de vérifier la réussite de notre ordonnanceur à fonctionnement tourniquet, nous avons programmer deux simples tâches changeant l'état d'une LED. Une à une fréquence 200ms et l'autre 300ms (avec un _delay_ms).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:left; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void tache1(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTC ^= (1 &amp;lt;&amp;lt; PC0);&lt;br /&gt;
    _delay_ms(300);}}&lt;br /&gt;
void tache2(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTD ^= (1 &amp;lt;&amp;lt; PD7);&lt;br /&gt;
    _delay_ms(200);}}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
[[Fichier:B5_test1.mp4|vignette|alt=test des frequences imprevisibles|test des frequences imprevisibles]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Clignotement grâce à l'état endormi ====&lt;br /&gt;
Nous ajoutons l'état endormi afin que nos tâches ne mettent pas en pause l'ordonnanceur avec un _delay_ms. Pour cela, nous incorporons une fonction makeSleep qui permet de mettre la tâche qui l'appelle dans cet état.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:left; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void makeSleep(int t){&lt;br /&gt;
  table_process[indice_tache].etat.id = SLEEPY;&lt;br /&gt;
  table_process[indice_tache].etat.time.sleepingtime = t;&lt;br /&gt;
  TIMER1_COMPA_vect();}&lt;br /&gt;
void tache1(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTC ^= (1 &amp;lt;&amp;lt; PC0);&lt;br /&gt;
    _delay_ms(300);}}&lt;br /&gt;
void tache3(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTC ^= (1 &amp;lt;&amp;lt; PC3);&lt;br /&gt;
    //_delay_ms(1000);&lt;br /&gt;
    makeSleep(1000);}}&lt;br /&gt;
void tache2(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTD ^= (1 &amp;lt;&amp;lt; PD7);&lt;br /&gt;
    //_delay_ms(1000);&lt;br /&gt;
    makeSleep(700);}}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
[[Fichier:B5_test2.mp4|vignette|alt=test des frequences imprevisibles|test des frequences imprevisibles]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
A noter que la première tâche executée ne doit pas être endormie.&lt;br /&gt;
&lt;br /&gt;
= Carte Fille Matrice de touches =&lt;br /&gt;
&lt;br /&gt;
== Carte ==&lt;br /&gt;
&lt;br /&gt;
=== Fille après soudure des composants ===&lt;/div&gt;</summary>
		<author><name>Adjadjaa</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-5&amp;diff=6747</id>
		<title>SE4Binome2024-5</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-5&amp;diff=6747"/>
		<updated>2024-11-18T11:06:18Z</updated>

		<summary type="html">&lt;p&gt;Adjadjaa : /* Carte Shield */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Introduction=&lt;br /&gt;
&lt;br /&gt;
Ce wiki documente le développement d’un pico-ordinateur modulaire. Ce dernier est constitué d’une carte principale, composée d’une carte Shield permettant la connexion des cartes filles, et d’une carte mère (initialement simulée par une Arduino Uno avant sa conception finale). Plusieurs cartes filles sont prévues, chacune remplissant une fonction spécifique : gestion du clavier, affichage, port série, réseau, mémoire de masse et son.&lt;br /&gt;
&lt;br /&gt;
Notre binôme est spécifiquement chargé du développement de la carte fille dédiée au clavier.&lt;br /&gt;
&lt;br /&gt;
Toutes les ressources nécessaires, incluant les codes sources et les schémas, sont disponibles sur le dépôt Git suivant :  [https://gitea.plil.fr/ktouron/se4-djadja-touron_pico.git Lien du Git]&lt;br /&gt;
&lt;br /&gt;
= Carte Shield =&lt;br /&gt;
[[Fichier:Carte Recto non soudé.jpg|vignette|left|thumb|350px|Recto de la carte avant soudage des composants]]&lt;br /&gt;
[[Fichier:Verso non solder.jpeg.jpg|vignette|thumb|center|350px|Verso de la carte avant soudage des composants]]&lt;br /&gt;
[[Fichier:Carde shield soudé.jpg|vignette|thumb|right|350px|Photo de la carte avec les composants soudés]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Test==&lt;br /&gt;
=== Allumage de LEDS sur Programmateur AVR ===&lt;br /&gt;
Avant de programmer directement sur le shield, nous avons allumé des LED pour tester la carte. Nous avons directement utilisé le code exemple fourni par l'IDE arduino en adaptant simplement les pins correspondant aux leds. [https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/PicoShield/Programmation/Blink Code du test]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Vid_test_carte_mp4.mp4|vignette|thumb|center|700px|Vidéo de Test des leds]]&lt;br /&gt;
&lt;br /&gt;
=== Lecture de la carte SD ===&lt;br /&gt;
Avant de programmer directement sur le shield, nous avons tester si la carte SD était bien détectée et lue. On a utilisé le code test présent dans l'IDE arduino en adaptant le port utilisé.[https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/PicoShield/Programmation/CardInfo Code du test]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Resultat SD.jpg|vignette|thumb|center|700px|Carte SD bien détéctée]]&lt;br /&gt;
&lt;br /&gt;
=== Connecteurs IDC HE10 ===&lt;br /&gt;
Afin de tester nos connecteur HE10, nous avons utilisé un afficher 7 segments (Sparkfun 7 segments display). Pour pouvoir vérifier leurs fonctionnements nous avons branché l'afficheur sur chaque connecteur tour à tour. Le programme implanté est un simple connecteur à afficher sur l'afficheur. Voici une vidéo du compteur fonctionnant sur un des 5 connecteurs HE10. ([https://learn.sparkfun.com/tutorials/using-the-serial-7-segment-display/all Code ici (section : Example 2 SPI)])&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Se4-5-7segments.mp4|vignette|alt=se4-5-7segments|Test connecteur HE10 avec afficheur 7 segments.|center]]&lt;br /&gt;
== Ordonnanceur ==&lt;br /&gt;
Pour les interruptions de notre ordonnanceur nous avons utilisé la procédure d'initialisation du minuteur avec le Timer1 disponible dans les cours de Mr.Redon en renseignant une période de 20ms. Nous l'avons disposé dans le fichier minuteur.c car nous n'allons plus le modifier pour le reste du projet. Dans un autre fichier process.c (avec process.h), nous allons y mettre nos structures pour les process et leurs états puis une union pour le temps qui le caractérise ainsi que toutes les fonctions associés.&lt;br /&gt;
&lt;br /&gt;
[https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/Ordonnanceur Lien du répertoire]&lt;br /&gt;
&lt;br /&gt;
=== Processus ===&lt;br /&gt;
==== Structure ====&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:right; width: 48%; padding-left: 10px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
    uint16_t adresseDepart;  //adresse de la fonction de départ &lt;br /&gt;
    uint16_t adressePile;       //adresse de la pile d'exécution&lt;br /&gt;
    Etat etat;        &lt;br /&gt;
} Process;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Notre structure caractérisant un processus est définie par les trois champs ci-contre.&lt;br /&gt;
&lt;br /&gt;
Une adresse de départ correspondant à la fonction du processus associé, l'adresse où se situe le processus dans la pile puis l'état de la tâche. Nous avons décidé de faire une structure à part entière compte tenu des multitudes d'états que nous pourrons ajouter pendant la progression du projet.&lt;br /&gt;
&lt;br /&gt;
==== Etat d'un processus ====&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:right; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
typedef union {&lt;br /&gt;
  int sleepingtime;       &lt;br /&gt;
} Time;&lt;br /&gt;
&lt;br /&gt;
typedef struct {&lt;br /&gt;
  int id;&lt;br /&gt;
  Time time;&lt;br /&gt;
} Etat ;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
L'état d'un processus est alors une structure à deux champs (pour l'instant), l'id doit correspondre à un '#DEFINE' pour avoir un sens tandis que nous avons choisi de faire une union pour le temps qui caractérise notre état afin qu'il puisse avoir un nom et type de variable cohérent avec son état.(Ici seulement sleepingtime car seul l'état endormi existe pour le moment)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
  {| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
  |+ Tableau des états&lt;br /&gt;
  |-&lt;br /&gt;
  ! Etat !! ACTIVE !! SLEEPY !! ... !! ...&lt;br /&gt;
  |-&lt;br /&gt;
  | Id || 0 || 1 || ... || ...&lt;br /&gt;
  |}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Procédures principales ====&lt;br /&gt;
&lt;br /&gt;
=== ISR ===&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:right; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
ISR(TIMER1_COMPA_vect, ISR_NAKED)    // Procédure d'interruption&lt;br /&gt;
{&lt;br /&gt;
  TCNT1=0;//reset timer&lt;br /&gt;
  /* Sauvegarde du contexte de la tâche interrompue */&lt;br /&gt;
  portSAVE_REGISTERS();&lt;br /&gt;
   table_process[indice_tache].adressePile = SP;&lt;br /&gt;
  /* Appel à l'ordonnanceur */&lt;br /&gt;
  selectProcess();&lt;br /&gt;
  /* Récupération du contexte de la tâche ré-activée */&lt;br /&gt;
  SP = table_process[indice_tache].adressePile;&lt;br /&gt;
  portRESTORE_REGISTERS();&lt;br /&gt;
  &lt;br /&gt;
  asm volatile ( &amp;quot;reti&amp;quot; );&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
L'ISR est ce qu'il va être executer lors des interruptions toutes les 20 millisecondes. Cela consiste à sauvegarder tous les registres de la tâche qui était en cours avant l'appel de l'ISR pour ensuite passer à la tâche suivante valide (c'est à dire active) sans oublier de charger les registres de la nouvelle tâche.&lt;br /&gt;
&lt;br /&gt;
Nous devons également, à chaque fois avant de changer de tâche, enregistrer le pointeur de pile dans le processus afin de pouvoir revenir là ou elle en est la prochaine fois qu'elle sera appelée. Respectivement, une fois la nouvelle tâche choisie, le pointeur de pile doit prendre l'adresse de là ou en était la tâche avant qu'elle soit interrompue.&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Séléction de processus ====&lt;br /&gt;
Lors de la séléction de processus, nous devons parcourir tous les processus jusqu'au moment où nous en trouvons un actif. Ainsi, il deviendra la tâche que nous traiterons lors du prochain intervalle de 20 ms. A ce stade, à chaque fois que la procédure selectProcess est appelée, nous devons réduire le temps de repos de chaque process endormi de 20 ms. D'autres conditions pourrons être ajoutée si ajout d'état a lieu.&lt;br /&gt;
&lt;br /&gt;
=== Test ===&lt;br /&gt;
==== Clignotement de deux LED à fréquences indivisibles entre elles ====&lt;br /&gt;
Afin de vérifier la réussite de notre ordonnanceur à fonctionnement tourniquet, nous avons programmer deux simples tâches changeant l'état d'une LED. Une à une fréquence 200ms et l'autre 300ms (avec un _delay_ms).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:left; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void tache1(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTC ^= (1 &amp;lt;&amp;lt; PC0);&lt;br /&gt;
    _delay_ms(300);}}&lt;br /&gt;
void tache2(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTD ^= (1 &amp;lt;&amp;lt; PD7);&lt;br /&gt;
    _delay_ms(200);}}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
[[Fichier:B5_test1.mp4|vignette|alt=test des frequences imprevisibles|test des frequences imprevisibles]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Clignotement grâce à l'état endormi ====&lt;br /&gt;
Nous ajoutons l'état endormi afin que nos tâches ne mettent pas en pause l'ordonnanceur avec un _delay_ms. Pour cela, nous incorporons une fonction makeSleep qui permet de mettrela tâche qui l'appelle dans cet état.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:left; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void makeSleep(int t){&lt;br /&gt;
  table_process[indice_tache].etat.id = SLEEPY;&lt;br /&gt;
  table_process[indice_tache].etat.time.sleepingtime = t;&lt;br /&gt;
  TIMER1_COMPA_vect();}&lt;br /&gt;
void tache1(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTC ^= (1 &amp;lt;&amp;lt; PC0);&lt;br /&gt;
    _delay_ms(300);}}&lt;br /&gt;
void tache3(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTC ^= (1 &amp;lt;&amp;lt; PC3);&lt;br /&gt;
    //_delay_ms(1000);&lt;br /&gt;
    makeSleep(1000);}}&lt;br /&gt;
void tache2(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTD ^= (1 &amp;lt;&amp;lt; PD7);&lt;br /&gt;
    //_delay_ms(1000);&lt;br /&gt;
    makeSleep(700);}}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
[[Fichier:B5_test2.mp4|vignette|alt=test des frequences imprevisibles|test des frequences imprevisibles]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
A noter que la première tâche executée ne doit pas être endormie.&lt;br /&gt;
&lt;br /&gt;
= Carte Fille Matrice de touches =&lt;br /&gt;
&lt;br /&gt;
== Carte ==&lt;br /&gt;
&lt;br /&gt;
=== Fille après soudure des composants ===&lt;/div&gt;</summary>
		<author><name>Adjadjaa</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-5&amp;diff=6745</id>
		<title>SE4Binome2024-5</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-5&amp;diff=6745"/>
		<updated>2024-11-18T11:04:37Z</updated>

		<summary type="html">&lt;p&gt;Adjadjaa : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Introduction=&lt;br /&gt;
&lt;br /&gt;
Ce wiki documente le développement d’un pico-ordinateur modulaire. Ce dernier est constitué d’une carte principale, composée d’une carte Shield permettant la connexion des cartes filles, et d’une carte mère (initialement simulée par une Arduino Uno avant sa conception finale). Plusieurs cartes filles sont prévues, chacune remplissant une fonction spécifique : gestion du clavier, affichage, port série, réseau, mémoire de masse et son.&lt;br /&gt;
&lt;br /&gt;
Notre binôme est spécifiquement chargé du développement de la carte fille dédiée au clavier.&lt;br /&gt;
&lt;br /&gt;
Toutes les ressources nécessaires, incluant les codes sources et les schémas, sont disponibles sur le dépôt Git suivant :  [https://gitea.plil.fr/ktouron/se4-djadja-touron_pico.git Lien du Git]&lt;br /&gt;
&lt;br /&gt;
= Carte Shield =&lt;br /&gt;
[[Fichier:Carte Recto non soudé.jpg|vignette|left|thumb|350px|Recto de la carte avant soudage des composants]]&lt;br /&gt;
[[Fichier:Verso non solder.jpeg.jpg|vignette|thumb|right|350px|Verso de la carte avant soudage des composants]]&lt;br /&gt;
[[Fichier:Carde shield soudé.jpg|vignette|thumb|center|400px|Photo de la carte avec les composants soudés]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Test==&lt;br /&gt;
=== Allumage de LEDS sur Programmateur AVR ===&lt;br /&gt;
Avant de programmer directement sur le shield, nous avons allumé des LED pour tester la carte. Nous avons directement utilisé le code exemple fourni par l'IDE arduino en adaptant simplement les pins correspondant aux leds. [https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/PicoShield/Programmation/Blink Code du test]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Vid_test_carte_mp4.mp4|vignette|thumb|center|700px|Vidéo de Test des leds]]&lt;br /&gt;
&lt;br /&gt;
=== Lecture de la carte SD ===&lt;br /&gt;
Avant de programmer directement sur le shield, nous avons tester si la carte SD était bien détectée et lue. On a utilisé le code test présent dans l'IDE arduino en adaptant le port utilisé.[https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/PicoShield/Programmation/CardInfo Code du test]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Resultat SD.jpg|vignette|thumb|center|700px|Carte SD bien détéctée]]&lt;br /&gt;
&lt;br /&gt;
=== Connecteurs IDC HE10 ===&lt;br /&gt;
Afin de tester nos connecteur HE10, nous avons utilisé un afficher 7 segments (Sparkfun 7 segments display). Pour pouvoir vérifier leurs fonctionnements nous avons branché l'afficheur sur chaque connecteur tour à tour. Le programme implanté est un simple connecteur à afficher sur l'afficheur. Voici une vidéo du compteur fonctionnant sur un des 5 connecteurs HE10. ([https://learn.sparkfun.com/tutorials/using-the-serial-7-segment-display/all Code ici (section : Example 2 SPI)])&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Se4-5-7segments.mp4|vignette|alt=se4-5-7segments|Test connecteur HE10 avec afficheur 7 segments.|center]]&lt;br /&gt;
== Ordonnanceur ==&lt;br /&gt;
Pour les interruptions de notre ordonnanceur nous avons utilisé la procédure d'initialisation du minuteur avec le Timer1 disponible dans les cours de Mr.Redon en renseignant une période de 20ms. Nous l'avons disposé dans le fichier minuteur.c car nous n'allons plus le modifier pour le reste du projet. Dans un autre fichier process.c (avec process.h), nous allons y mettre nos structures pour les process et leurs états puis une union pour le temps qui le caractérise ainsi que toutes les fonctions associés.&lt;br /&gt;
&lt;br /&gt;
[https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/Ordonnanceur Lien du répertoire]&lt;br /&gt;
&lt;br /&gt;
=== Processus ===&lt;br /&gt;
==== Structure ====&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:right; width: 48%; padding-left: 10px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
    uint16_t adresseDepart;  //adresse de la fonction de départ &lt;br /&gt;
    uint16_t adressePile;       //adresse de la pile d'exécution&lt;br /&gt;
    Etat etat;        &lt;br /&gt;
} Process;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Notre structure caractérisant un processus est définie par les trois champs ci-contre.&lt;br /&gt;
&lt;br /&gt;
Une adresse de départ correspondant à la fonction du processus associé, l'adresse où se situe le processus dans la pile puis l'état de la tâche. Nous avons décidé de faire une structure à part entière compte tenu des multitudes d'états que nous pourrons ajouter pendant la progression du projet.&lt;br /&gt;
&lt;br /&gt;
==== Etat d'un processus ====&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:right; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
typedef union {&lt;br /&gt;
  int sleepingtime;       &lt;br /&gt;
} Time;&lt;br /&gt;
&lt;br /&gt;
typedef struct {&lt;br /&gt;
  int id;&lt;br /&gt;
  Time time;&lt;br /&gt;
} Etat ;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
L'état d'un processus est alors une structure à deux champs (pour l'instant), l'id doit correspondre à un '#DEFINE' pour avoir un sens tandis que nous avons choisi de faire une union pour le temps qui caractérise notre état afin qu'il puisse avoir un nom et type de variable cohérent avec son état.(Ici seulement sleepingtime car seul l'état endormi existe pour le moment)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
  {| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
  |+ Tableau des états&lt;br /&gt;
  |-&lt;br /&gt;
  ! Etat !! ACTIVE !! SLEEPY !! ... !! ...&lt;br /&gt;
  |-&lt;br /&gt;
  | Id || 0 || 1 || ... || ...&lt;br /&gt;
  |}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Procédures principales ====&lt;br /&gt;
&lt;br /&gt;
=== ISR ===&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:right; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
ISR(TIMER1_COMPA_vect, ISR_NAKED)    // Procédure d'interruption&lt;br /&gt;
{&lt;br /&gt;
  TCNT1=0;//reset timer&lt;br /&gt;
  /* Sauvegarde du contexte de la tâche interrompue */&lt;br /&gt;
  portSAVE_REGISTERS();&lt;br /&gt;
   table_process[indice_tache].adressePile = SP;&lt;br /&gt;
  /* Appel à l'ordonnanceur */&lt;br /&gt;
  selectProcess();&lt;br /&gt;
  /* Récupération du contexte de la tâche ré-activée */&lt;br /&gt;
  SP = table_process[indice_tache].adressePile;&lt;br /&gt;
  portRESTORE_REGISTERS();&lt;br /&gt;
  &lt;br /&gt;
  asm volatile ( &amp;quot;reti&amp;quot; );&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
L'ISR est ce qu'il va être executer lors des interruptions toutes les 20 millisecondes. Cela consiste à sauvegarder tous les registres de la tâche qui était en cours avant l'appel de l'ISR pour ensuite passer à la tâche suivante valide (c'est à dire active) sans oublier de charger les registres de la nouvelle tâche.&lt;br /&gt;
&lt;br /&gt;
Nous devons également, à chaque fois avant de changer de tâche, enregistrer le pointeur de pile dans le processus afin de pouvoir revenir là ou elle en est la prochaine fois qu'elle sera appelée. Respectivement, une fois la nouvelle tâche choisie, le pointeur de pile doit prendre l'adresse de là ou en était la tâche avant qu'elle soit interrompue.&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Séléction de processus ====&lt;br /&gt;
Lors de la séléction de processus, nous devons parcourir tous les processus jusqu'au moment où nous en trouvons un actif. Ainsi, il deviendra la tâche que nous traiterons lors du prochain intervalle de 20 ms. A ce stade, à chaque fois que la procédure selectProcess est appelée, nous devons réduire le temps de repos de chaque process endormi de 20 ms. D'autres conditions pourrons être ajoutée si ajout d'état a lieu.&lt;br /&gt;
&lt;br /&gt;
=== Test ===&lt;br /&gt;
==== Clignotement de deux LED à fréquences indivisibles entre elles ====&lt;br /&gt;
Afin de vérifier la réussite de notre ordonnanceur à fonctionnement tourniquet, nous avons programmer deux simples tâches changeant l'état d'une LED. Une à une fréquence 200ms et l'autre 300ms (avec un __delay_ms).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:left; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void tache1(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTC ^= (1 &amp;lt;&amp;lt; PC0);&lt;br /&gt;
    _delay_ms(300);}}&lt;br /&gt;
void tache2(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTD ^= (1 &amp;lt;&amp;lt; PD7);&lt;br /&gt;
    _delay_ms(200);}}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
[[Fichier:B5_test1.mp4|vignette|alt=test des frequences imprevisibles|test des frequences imprevisibles]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Clignotement grâce à l'état endormi ====&lt;br /&gt;
Nous ajoutons l'état endormi afin que nos tâches ne mettent pas en pause l'ordonnanceur avec un _delay_ms. Pour cela, nous incorporons une fonction makeSleep qui permet de mettrela tâche qui l'appelle dans cet état.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:left; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void makeSleep(int t){&lt;br /&gt;
  table_process[indice_tache].etat.id = SLEEPY;&lt;br /&gt;
  table_process[indice_tache].etat.time.sleepingtime = t;&lt;br /&gt;
  TIMER1_COMPA_vect();}&lt;br /&gt;
void tache1(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTC ^= (1 &amp;lt;&amp;lt; PC0);&lt;br /&gt;
    _delay_ms(300);}}&lt;br /&gt;
void tache3(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTC ^= (1 &amp;lt;&amp;lt; PC3);&lt;br /&gt;
    //_delay_ms(1000);&lt;br /&gt;
    makeSleep(1000);}}&lt;br /&gt;
void tache2(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTD ^= (1 &amp;lt;&amp;lt; PD7);&lt;br /&gt;
    //_delay_ms(1000);&lt;br /&gt;
    makeSleep(700);}}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
[[Fichier:B5_test2.mp4|vignette|alt=test des frequences imprevisibles|test des frequences imprevisibles]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
A noter que la première tâche executée ne doit pas être endormie.&lt;br /&gt;
&lt;br /&gt;
= Carte Fille Matrice de touches =&lt;br /&gt;
&lt;br /&gt;
== Carte ==&lt;br /&gt;
&lt;br /&gt;
=== Fille après soudure des composants ===&lt;/div&gt;</summary>
		<author><name>Adjadjaa</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-5&amp;diff=6744</id>
		<title>SE4Binome2024-5</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-5&amp;diff=6744"/>
		<updated>2024-11-18T11:02:55Z</updated>

		<summary type="html">&lt;p&gt;Adjadjaa : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Introduction=&lt;br /&gt;
&lt;br /&gt;
Ce wiki documente le développement d’un pico-ordinateur modulaire. Ce dernier est constitué d’une carte principale, composée d’une carte Shield permettant la connexion des cartes filles, et d’une carte mère (initialement simulée par une Arduino Uno avant sa conception finale). Plusieurs cartes filles sont prévues, chacune remplissant une fonction spécifique : gestion du clavier, affichage, port série, réseau, mémoire de masse et son.&lt;br /&gt;
&lt;br /&gt;
Notre binôme est spécifiquement chargé du développement de la carte fille dédiée au clavier.&lt;br /&gt;
&lt;br /&gt;
Toutes les ressources nécessaires, incluant les codes sources et les schémas, sont disponibles sur le dépôt Git suivant :  [https://gitea.plil.fr/ktouron/se4-djadja-touron_pico.git Lien du Git]&lt;br /&gt;
&lt;br /&gt;
= Carte Shield =&lt;br /&gt;
[[Fichier:Carte Recto non soudé.jpg|vignette|left|thumb|350px|Recto de la carte avant soudage des composants]]&lt;br /&gt;
[[Fichier:Verso non solder.jpeg.jpg|vignette|thumb|right|350px|Verso de la carte avant soudage des composants]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Carte Shield après soudure des composants ==&lt;br /&gt;
[[Fichier:Carde shield soudé.jpg|vignette|thumb|center|400px|Photo de la carte avec les composants soudés]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Test==&lt;br /&gt;
=== Allumage de LEDS sur Programmateur AVR ===&lt;br /&gt;
Avant de programmer directement sur le shield, nous avons allumé des LED pour tester la carte. Nous avons directement utilisé le code exemple fourni par l'IDE arduino en adaptant simplement les pins correspondant aux leds. [https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/PicoShield/Programmation/Blink Code du test]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Vid_test_carte_mp4.mp4|vignette|thumb|center|700px|Vidéo de Test des leds]]&lt;br /&gt;
&lt;br /&gt;
=== Lecture de la carte SD ===&lt;br /&gt;
Avant de programmer directement sur le shield, nous avons tester si la carte SD était bien détectée et lue. On a utilisé le code test présent dans l'IDE arduino en adaptant le port utilisé.[https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/PicoShield/Programmation/CardInfo Code du test]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Resultat SD.jpg|vignette|thumb|center|700px|Carte SD bien détéctée]]&lt;br /&gt;
&lt;br /&gt;
=== Connecteurs IDC HE10 ===&lt;br /&gt;
Afin de tester nos connecteur HE10, nous avons utilisé un afficher 7 segments (Sparkfun 7 segments display). Pour pouvoir vérifier leurs fonctionnements nous avons branché l'afficheur sur chaque connecteur tour à tour. Le programme implanté est un simple connecteur à afficher sur l'afficheur. Voici une vidéo du compteur fonctionnant sur un des 5 connecteurs HE10. ([https://learn.sparkfun.com/tutorials/using-the-serial-7-segment-display/all Code ici (section : Example 2 SPI)])&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Se4-5-7segments.mp4|vignette|alt=se4-5-7segments|Test connecteur HE10 avec afficheur 7 segments.|center]]&lt;br /&gt;
== Ordonnanceur ==&lt;br /&gt;
Pour les interruptions de notre ordonnanceur nous avons utilisé la procédure d'initialisation du minuteur avec le Timer1 disponible dans les cours de Mr.Redon en renseignant une période de 20ms. Nous l'avons disposé dans le fichier minuteur.c car nous n'allons plus le modifier pour le reste du projet. Dans un autre fichier process.c (avec process.h), nous allons y mettre nos structures pour les process et leurs états puis une union pour le temps qui le caractérise ainsi que toutes les fonctions associés.&lt;br /&gt;
&lt;br /&gt;
[https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/Ordonnanceur Lien du répertoire]&lt;br /&gt;
&lt;br /&gt;
=== Processus ===&lt;br /&gt;
==== Structure ====&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:right; width: 48%; padding-left: 10px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
    uint16_t adresseDepart;  //adresse de la fonction de départ &lt;br /&gt;
    uint16_t adressePile;       //adresse de la pile d'exécution&lt;br /&gt;
    Etat etat;        &lt;br /&gt;
} Process;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Notre structure caractérisant un processus est définie par les trois champs ci-contre.&lt;br /&gt;
&lt;br /&gt;
Une adresse de départ correspondant à la fonction du processus associé, l'adresse où se situe le processus dans la pile puis l'état de la tâche. Nous avons décidé de faire une structure à part entière compte tenu des multitudes d'états que nous pourrons ajouter pendant la progression du projet.&lt;br /&gt;
&lt;br /&gt;
==== Etat d'un processus ====&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:right; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
typedef union {&lt;br /&gt;
  int sleepingtime;       &lt;br /&gt;
} Time;&lt;br /&gt;
&lt;br /&gt;
typedef struct {&lt;br /&gt;
  int id;&lt;br /&gt;
  Time time;&lt;br /&gt;
} Etat ;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
L'état d'un processus est alors une structure à deux champs (pour l'instant), l'id doit correspondre à un '#DEFINE' pour avoir un sens tandis que nous avons choisi de faire une union pour le temps qui caractérise notre état afin qu'il puisse avoir un nom et type de variable cohérent avec son état.(Ici seulement sleepingtime car seul l'état endormi existe pour le moment)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
  {| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
  |+ Tableau des états&lt;br /&gt;
  |-&lt;br /&gt;
  ! Etat !! ACTIVE !! SLEEPY !! ... !! ...&lt;br /&gt;
  |-&lt;br /&gt;
  | Id || 0 || 1 || ... || ...&lt;br /&gt;
  |}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Procédures principales ====&lt;br /&gt;
&lt;br /&gt;
=== ISR ===&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:right; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
ISR(TIMER1_COMPA_vect, ISR_NAKED)    // Procédure d'interruption&lt;br /&gt;
{&lt;br /&gt;
  TCNT1=0;//reset timer&lt;br /&gt;
  /* Sauvegarde du contexte de la tâche interrompue */&lt;br /&gt;
  portSAVE_REGISTERS();&lt;br /&gt;
   table_process[indice_tache].adressePile = SP;&lt;br /&gt;
  /* Appel à l'ordonnanceur */&lt;br /&gt;
  selectProcess();&lt;br /&gt;
  /* Récupération du contexte de la tâche ré-activée */&lt;br /&gt;
  SP = table_process[indice_tache].adressePile;&lt;br /&gt;
  portRESTORE_REGISTERS();&lt;br /&gt;
  &lt;br /&gt;
  asm volatile ( &amp;quot;reti&amp;quot; );&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
L'ISR est ce qu'il va être executer lors des interruptions toutes les 20 millisecondes. Cela consiste à sauvegarder tous les registres de la tâche qui était en cours avant l'appel de l'ISR pour ensuite passer à la tâche suivante valide (c'est à dire active) sans oublier de charger les registres de la nouvelle tâche.&lt;br /&gt;
&lt;br /&gt;
Nous devons également, à chaque fois avant de changer de tâche, enregistrer le pointeur de pile dans le processus afin de pouvoir revenir là ou elle en est la prochaine fois qu'elle sera appelée. Respectivement, une fois la nouvelle tâche choisie, le pointeur de pile doit prendre l'adresse de là ou en était la tâche avant qu'elle soit interrompue.&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Séléction de processus ====&lt;br /&gt;
Lors de la séléction de processus, nous devons parcourir tous les processus jusqu'au moment où nous en trouvons un actif. Ainsi, il deviendra la tâche que nous traiterons lors du prochain intervalle de 20 ms. A ce stade, à chaque fois que la procédure selectProcess est appelée, nous devons réduire le temps de repos de chaque process endormi de 20 ms. D'autres conditions pourrons être ajoutée si ajout d'état a lieu.&lt;br /&gt;
&lt;br /&gt;
=== Test ===&lt;br /&gt;
==== Clignotement de deux LED à fréquences indivisibles entre elles ====&lt;br /&gt;
Afin de vérifier la réussite de notre ordonnanceur à fonctionnement tourniquet, nous avons programmer deux simples tâches changeant l'état d'une LED. Une à une fréquence 200ms et l'autre 300ms (avec un __delay_ms).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:left; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void tache1(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTC ^= (1 &amp;lt;&amp;lt; PC0);&lt;br /&gt;
    _delay_ms(300);}}&lt;br /&gt;
void tache2(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTD ^= (1 &amp;lt;&amp;lt; PD7);&lt;br /&gt;
    _delay_ms(200);}}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
[[Fichier:B5_test1.mp4|vignette|alt=test des frequences imprevisibles|test des frequences imprevisibles]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Clignotement grâce à l'état endormi ====&lt;br /&gt;
Nous ajoutons l'état endormi afin que nos tâches ne mettent pas en pause l'ordonnanceur avec un _delay_ms. Pour cela, nous incorporons une fonction makeSleep qui permet de mettrela tâche qui l'appelle dans cet état.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:left; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void makeSleep(int t){&lt;br /&gt;
  table_process[indice_tache].etat.id = SLEEPY;&lt;br /&gt;
  table_process[indice_tache].etat.time.sleepingtime = t;&lt;br /&gt;
  TIMER1_COMPA_vect();}&lt;br /&gt;
void tache1(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTC ^= (1 &amp;lt;&amp;lt; PC0);&lt;br /&gt;
    _delay_ms(300);}}&lt;br /&gt;
void tache3(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTC ^= (1 &amp;lt;&amp;lt; PC3);&lt;br /&gt;
    //_delay_ms(1000);&lt;br /&gt;
    makeSleep(1000);}}&lt;br /&gt;
void tache2(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTD ^= (1 &amp;lt;&amp;lt; PD7);&lt;br /&gt;
    //_delay_ms(1000);&lt;br /&gt;
    makeSleep(700);}}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
[[Fichier:B5_test2.mp4|vignette|alt=test des frequences imprevisibles|test des frequences imprevisibles]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
A noter que la première tâche executée ne doit pas être endormie.&lt;br /&gt;
&lt;br /&gt;
= Carte Fille Matrice de touches =&lt;br /&gt;
&lt;br /&gt;
== Carte ==&lt;br /&gt;
&lt;br /&gt;
=== Fille après soudure des composants ===&lt;/div&gt;</summary>
		<author><name>Adjadjaa</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-5&amp;diff=6742</id>
		<title>SE4Binome2024-5</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-5&amp;diff=6742"/>
		<updated>2024-11-18T11:01:05Z</updated>

		<summary type="html">&lt;p&gt;Adjadjaa : /* Ordonnanceur = */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Introduction=&lt;br /&gt;
&lt;br /&gt;
Ce wiki documente le développement d’un pico-ordinateur modulaire. Ce dernier est constitué d’une carte principale, composée d’une carte Shield permettant la connexion des cartes filles, et d’une carte mère (initialement simulée par une Arduino Uno avant sa conception finale). Plusieurs cartes filles sont prévues, chacune remplissant une fonction spécifique : gestion du clavier, affichage, port série, réseau, mémoire de masse et son.&lt;br /&gt;
&lt;br /&gt;
Notre binôme est spécifiquement chargé du développement de la carte fille dédiée au clavier.&lt;br /&gt;
&lt;br /&gt;
Toutes les ressources nécessaires, incluant les codes sources et les schémas, sont disponibles sur le dépôt Git suivant :  [https://gitea.plil.fr/ktouron/se4-djadja-touron_pico.git Lien du Git]&lt;br /&gt;
&lt;br /&gt;
= Carte Shield =&lt;br /&gt;
== Hardware ==&lt;br /&gt;
[[Fichier:Carte Recto non soudé.jpg|vignette|left|thumb|350px|Recto de la carte avant soudage des composants]]&lt;br /&gt;
[[Fichier:Verso non solder.jpeg.jpg|vignette|thumb|right|350px|Verso de la carte avant soudage des composants]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Carte Shield après soudure des composants ===&lt;br /&gt;
[[Fichier:Carde shield soudé.jpg|vignette|thumb|center|400px|Photo de la carte avec les composants soudés]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Software ==&lt;br /&gt;
===Test===&lt;br /&gt;
==== Allumage de LEDS sur Programmateur AVR ====&lt;br /&gt;
Avant de programmer directement sur le shield, nous avons allumé des LED pour tester la carte. Nous avons directement utilisé le code exemple fourni par l'IDE arduino en adaptant simplement les pins correspondant aux leds. [https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/PicoShield/Programmation/Blink Code du test]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Vid_test_carte_mp4.mp4|vignette|thumb|center|700px|Vidéo de Test des leds]]&lt;br /&gt;
&lt;br /&gt;
==== Lecture de la carte SD ====&lt;br /&gt;
Avant de programmer directement sur le shield, nous avons tester si la carte SD était bien détectée et lue. On a utilisé le code test présent dans l'IDE arduino en adaptant le port utilisé.[https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/PicoShield/Programmation/CardInfo Code du test]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Resultat SD.jpg|vignette|thumb|center|700px|Carte SD bien détéctée]]&lt;br /&gt;
&lt;br /&gt;
==== Connecteurs IDC HE10 ====&lt;br /&gt;
Afin de tester nos connecteur HE10, nous avons utilisé un afficher 7 segments (Sparkfun 7 segments display). Pour pouvoir vérifier leurs fonctionnements nous avons branché l'afficheur sur chaque connecteur tour à tour. Le programme implanté est un simple connecteur à afficher sur l'afficheur. Voici une vidéo du compteur fonctionnant sur un des 5 connecteurs HE10. ([https://learn.sparkfun.com/tutorials/using-the-serial-7-segment-display/all Code ici (section : Example 2 SPI)])&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Se4-5-7segments.mp4|vignette|alt=se4-5-7segments|Test connecteur HE10 avec afficheur 7 segments.|center]]&lt;br /&gt;
=== Ordonnanceur ===&lt;br /&gt;
Pour les interruptions de notre ordonnanceur nous avons utilisé la procédure d'initialisation du minuteur avec le Timer1 disponible dans les cours de Mr.Redon en renseignant une période de 20ms. Nous l'avons disposé dans le fichier minuteur.c car nous n'allons plus le modifier pour le reste du projet. Dans un autre fichier process.c (avec process.h), nous allons y mettre nos structures pour les process et leurs états puis une union pour le temps qui le caractérise ainsi que toutes les fonctions associés.&lt;br /&gt;
&lt;br /&gt;
[https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/Ordonnanceur Lien du répertoire]&lt;br /&gt;
&lt;br /&gt;
==== Processus ====&lt;br /&gt;
===== Structure =====&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:right; width: 48%; padding-left: 10px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
    uint16_t adresseDepart;  //adresse de la fonction de départ &lt;br /&gt;
    uint16_t adressePile;       //adresse de la pile d'exécution&lt;br /&gt;
    Etat etat;        &lt;br /&gt;
} Process;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Notre structure caractérisant un processus est définie par les trois champs ci-contre.&lt;br /&gt;
&lt;br /&gt;
Une adresse de départ correspondant à la fonction du processus associé, l'adresse où se situe le processus dans la pile puis l'état de la tâche. Nous avons décidé de faire une structure à part entière compte tenu des multitudes d'états que nous pourrons ajouter pendant la progression du projet.&lt;br /&gt;
&lt;br /&gt;
===== Etat d'un processus =====&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:right; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
typedef union {&lt;br /&gt;
  int sleepingtime;       &lt;br /&gt;
} Time;&lt;br /&gt;
&lt;br /&gt;
typedef struct {&lt;br /&gt;
  int id;&lt;br /&gt;
  Time time;&lt;br /&gt;
} Etat ;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
L'état d'un processus est alors une structure à deux champs (pour l'instant), l'id doit correspondre à un '#DEFINE' pour avoir un sens tandis que nous avons choisi de faire une union pour le temps qui caractérise notre état afin qu'il puisse avoir un nom et type de variable cohérent avec son état.(Ici seulement sleepingtime car seul l'état endormi existe pour le moment)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
  {| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
  |+ Tableau des états&lt;br /&gt;
  |-&lt;br /&gt;
  ! Etat !! ACTIVE !! SLEEPY !! ... !! ...&lt;br /&gt;
  |-&lt;br /&gt;
  | Id || 0 || 1 || ... || ...&lt;br /&gt;
  |}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== Procédures principales =====&lt;br /&gt;
&lt;br /&gt;
==== ISR ====&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:right; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
ISR(TIMER1_COMPA_vect, ISR_NAKED)    // Procédure d'interruption&lt;br /&gt;
{&lt;br /&gt;
  TCNT1=0;//reset timer&lt;br /&gt;
  /* Sauvegarde du contexte de la tâche interrompue */&lt;br /&gt;
  portSAVE_REGISTERS();&lt;br /&gt;
   table_process[indice_tache].adressePile = SP;&lt;br /&gt;
  /* Appel à l'ordonnanceur */&lt;br /&gt;
  selectProcess();&lt;br /&gt;
  /* Récupération du contexte de la tâche ré-activée */&lt;br /&gt;
  SP = table_process[indice_tache].adressePile;&lt;br /&gt;
  portRESTORE_REGISTERS();&lt;br /&gt;
  &lt;br /&gt;
  asm volatile ( &amp;quot;reti&amp;quot; );&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
L'ISR est ce qu'il va être executer lors des interruptions toutes les 20 millisecondes. Cela consiste à sauvegarder tous les registres de la tâche qui était en cours avant l'appel de l'ISR pour ensuite passer à la tâche suivante valide (c'est à dire active) sans oublier de charger les registres de la nouvelle tâche.&lt;br /&gt;
&lt;br /&gt;
Nous devons également, à chaque fois avant de changer de tâche, enregistrer le pointeur de pile dans le processus afin de pouvoir revenir là ou elle en est la prochaine fois qu'elle sera appelée. Respectivement, une fois la nouvelle tâche choisie, le pointeur de pile doit prendre l'adresse de là ou en était la tâche avant qu'elle soit interrompue.&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== Séléction de processus =====&lt;br /&gt;
Lors de la séléction de processus, nous devons parcourir tous les processus jusqu'au moment où nous en trouvons un actif. Ainsi, il deviendra la tâche que nous traiterons lors du prochain intervalle de 20 ms. A ce stade, à chaque fois que la procédure selectProcess est appelée, nous devons réduire le temps de repos de chaque process endormi de 20 ms. D'autres conditions pourrons être ajoutée si ajout d'état a lieu.&lt;br /&gt;
&lt;br /&gt;
==== Test ====&lt;br /&gt;
===== Clignotement de deux LED à fréquences indivisibles entre elles =====&lt;br /&gt;
Afin de vérifier la réussite de notre ordonnanceur à fonctionnement tourniquet, nous avons programmer deux simples tâches changeant l'état d'une LED. Une à une fréquence 200ms et l'autre 300ms (avec un __delay_ms).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:left; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void tache1(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTC ^= (1 &amp;lt;&amp;lt; PC0);&lt;br /&gt;
    _delay_ms(300);}}&lt;br /&gt;
void tache2(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTD ^= (1 &amp;lt;&amp;lt; PD7);&lt;br /&gt;
    _delay_ms(200);}}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
[[Fichier:B5_test1.mp4|vignette|alt=test des frequences imprevisibles|test des frequences imprevisibles]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== Clignotement grâce à l'état endormi =====&lt;br /&gt;
Nous ajoutons l'état endormi afin que nos tâches ne mettent pas en pause l'ordonnanceur avec un _delay_ms. Pour cela, nous incorporons une fonction makeSleep qui permet de mettrela tâche qui l'appelle dans cet état.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:left; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void makeSleep(int t){&lt;br /&gt;
  table_process[indice_tache].etat.id = SLEEPY;&lt;br /&gt;
  table_process[indice_tache].etat.time.sleepingtime = t;&lt;br /&gt;
  TIMER1_COMPA_vect();}&lt;br /&gt;
void tache1(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTC ^= (1 &amp;lt;&amp;lt; PC0);&lt;br /&gt;
    _delay_ms(300);}}&lt;br /&gt;
void tache3(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTC ^= (1 &amp;lt;&amp;lt; PC3);&lt;br /&gt;
    //_delay_ms(1000);&lt;br /&gt;
    makeSleep(1000);}}&lt;br /&gt;
void tache2(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTD ^= (1 &amp;lt;&amp;lt; PD7);&lt;br /&gt;
    //_delay_ms(1000);&lt;br /&gt;
    makeSleep(700);}}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
[[Fichier:B5_test2.mp4|vignette|alt=test des frequences imprevisibles|test des frequences imprevisibles]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
A noter que la première tâche executée ne doit pas être endormie.&lt;br /&gt;
&lt;br /&gt;
= Carte Fille Matrice de touches =&lt;br /&gt;
&lt;br /&gt;
== Carte ==&lt;br /&gt;
&lt;br /&gt;
=== Fille après soudure des composants ===&lt;/div&gt;</summary>
		<author><name>Adjadjaa</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-5&amp;diff=6741</id>
		<title>SE4Binome2024-5</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-5&amp;diff=6741"/>
		<updated>2024-11-18T11:00:36Z</updated>

		<summary type="html">&lt;p&gt;Adjadjaa : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Introduction=&lt;br /&gt;
&lt;br /&gt;
Ce wiki documente le développement d’un pico-ordinateur modulaire. Ce dernier est constitué d’une carte principale, composée d’une carte Shield permettant la connexion des cartes filles, et d’une carte mère (initialement simulée par une Arduino Uno avant sa conception finale). Plusieurs cartes filles sont prévues, chacune remplissant une fonction spécifique : gestion du clavier, affichage, port série, réseau, mémoire de masse et son.&lt;br /&gt;
&lt;br /&gt;
Notre binôme est spécifiquement chargé du développement de la carte fille dédiée au clavier.&lt;br /&gt;
&lt;br /&gt;
Toutes les ressources nécessaires, incluant les codes sources et les schémas, sont disponibles sur le dépôt Git suivant :  [https://gitea.plil.fr/ktouron/se4-djadja-touron_pico.git Lien du Git]&lt;br /&gt;
&lt;br /&gt;
= Carte Shield =&lt;br /&gt;
== Hardware ==&lt;br /&gt;
[[Fichier:Carte Recto non soudé.jpg|vignette|left|thumb|350px|Recto de la carte avant soudage des composants]]&lt;br /&gt;
[[Fichier:Verso non solder.jpeg.jpg|vignette|thumb|right|350px|Verso de la carte avant soudage des composants]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Carte Shield après soudure des composants ===&lt;br /&gt;
[[Fichier:Carde shield soudé.jpg|vignette|thumb|center|400px|Photo de la carte avec les composants soudés]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Software ==&lt;br /&gt;
===Test===&lt;br /&gt;
==== Allumage de LEDS sur Programmateur AVR ====&lt;br /&gt;
Avant de programmer directement sur le shield, nous avons allumé des LED pour tester la carte. Nous avons directement utilisé le code exemple fourni par l'IDE arduino en adaptant simplement les pins correspondant aux leds. [https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/PicoShield/Programmation/Blink Code du test]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Vid_test_carte_mp4.mp4|vignette|thumb|center|700px|Vidéo de Test des leds]]&lt;br /&gt;
&lt;br /&gt;
==== Lecture de la carte SD ====&lt;br /&gt;
Avant de programmer directement sur le shield, nous avons tester si la carte SD était bien détectée et lue. On a utilisé le code test présent dans l'IDE arduino en adaptant le port utilisé.[https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/PicoShield/Programmation/CardInfo Code du test]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Resultat SD.jpg|vignette|thumb|center|700px|Carte SD bien détéctée]]&lt;br /&gt;
&lt;br /&gt;
==== Connecteurs IDC HE10 ====&lt;br /&gt;
Afin de tester nos connecteur HE10, nous avons utilisé un afficher 7 segments (Sparkfun 7 segments display). Pour pouvoir vérifier leurs fonctionnements nous avons branché l'afficheur sur chaque connecteur tour à tour. Le programme implanté est un simple connecteur à afficher sur l'afficheur. Voici une vidéo du compteur fonctionnant sur un des 5 connecteurs HE10. ([https://learn.sparkfun.com/tutorials/using-the-serial-7-segment-display/all Code ici (section : Example 2 SPI)])&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Se4-5-7segments.mp4|vignette|alt=se4-5-7segments|Test connecteur HE10 avec afficheur 7 segments.|center]]&lt;br /&gt;
=== Ordonnanceur ====&lt;br /&gt;
Pour les interruptions de notre ordonnanceur nous avons utilisé la procédure d'initialisation du minuteur avec le Timer1 disponible dans les cours de Mr.Redon en renseignant une période de 20ms. Nous l'avons disposé dans le fichier minuteur.c car nous n'allons plus le modifier pour le reste du projet. Dans un autre fichier process.c (avec process.h), nous allons y mettre nos structures pour les process et leurs états puis une union pour le temps qui le caractérise ainsi que toutes les fonctions associés.&lt;br /&gt;
&lt;br /&gt;
[https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/Ordonnanceur Lien du répertoire]&lt;br /&gt;
&lt;br /&gt;
==== Processus ====&lt;br /&gt;
===== Structure =====&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:right; width: 48%; padding-left: 10px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
    uint16_t adresseDepart;  //adresse de la fonction de départ &lt;br /&gt;
    uint16_t adressePile;       //adresse de la pile d'exécution&lt;br /&gt;
    Etat etat;        &lt;br /&gt;
} Process;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Notre structure caractérisant un processus est définie par les trois champs ci-contre.&lt;br /&gt;
&lt;br /&gt;
Une adresse de départ correspondant à la fonction du processus associé, l'adresse où se situe le processus dans la pile puis l'état de la tâche. Nous avons décidé de faire une structure à part entière compte tenu des multitudes d'états que nous pourrons ajouter pendant la progression du projet.&lt;br /&gt;
&lt;br /&gt;
===== Etat d'un processus =====&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:right; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
typedef union {&lt;br /&gt;
  int sleepingtime;       &lt;br /&gt;
} Time;&lt;br /&gt;
&lt;br /&gt;
typedef struct {&lt;br /&gt;
  int id;&lt;br /&gt;
  Time time;&lt;br /&gt;
} Etat ;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
L'état d'un processus est alors une structure à deux champs (pour l'instant), l'id doit correspondre à un '#DEFINE' pour avoir un sens tandis que nous avons choisi de faire une union pour le temps qui caractérise notre état afin qu'il puisse avoir un nom et type de variable cohérent avec son état.(Ici seulement sleepingtime car seul l'état endormi existe pour le moment)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
  {| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
  |+ Tableau des états&lt;br /&gt;
  |-&lt;br /&gt;
  ! Etat !! ACTIVE !! SLEEPY !! ... !! ...&lt;br /&gt;
  |-&lt;br /&gt;
  | Id || 0 || 1 || ... || ...&lt;br /&gt;
  |}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== Procédures principales =====&lt;br /&gt;
&lt;br /&gt;
==== ISR ====&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:right; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
ISR(TIMER1_COMPA_vect, ISR_NAKED)    // Procédure d'interruption&lt;br /&gt;
{&lt;br /&gt;
  TCNT1=0;//reset timer&lt;br /&gt;
  /* Sauvegarde du contexte de la tâche interrompue */&lt;br /&gt;
  portSAVE_REGISTERS();&lt;br /&gt;
   table_process[indice_tache].adressePile = SP;&lt;br /&gt;
  /* Appel à l'ordonnanceur */&lt;br /&gt;
  selectProcess();&lt;br /&gt;
  /* Récupération du contexte de la tâche ré-activée */&lt;br /&gt;
  SP = table_process[indice_tache].adressePile;&lt;br /&gt;
  portRESTORE_REGISTERS();&lt;br /&gt;
  &lt;br /&gt;
  asm volatile ( &amp;quot;reti&amp;quot; );&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
L'ISR est ce qu'il va être executer lors des interruptions toutes les 20 millisecondes. Cela consiste à sauvegarder tous les registres de la tâche qui était en cours avant l'appel de l'ISR pour ensuite passer à la tâche suivante valide (c'est à dire active) sans oublier de charger les registres de la nouvelle tâche.&lt;br /&gt;
&lt;br /&gt;
Nous devons également, à chaque fois avant de changer de tâche, enregistrer le pointeur de pile dans le processus afin de pouvoir revenir là ou elle en est la prochaine fois qu'elle sera appelée. Respectivement, une fois la nouvelle tâche choisie, le pointeur de pile doit prendre l'adresse de là ou en était la tâche avant qu'elle soit interrompue.&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== Séléction de processus =====&lt;br /&gt;
Lors de la séléction de processus, nous devons parcourir tous les processus jusqu'au moment où nous en trouvons un actif. Ainsi, il deviendra la tâche que nous traiterons lors du prochain intervalle de 20 ms. A ce stade, à chaque fois que la procédure selectProcess est appelée, nous devons réduire le temps de repos de chaque process endormi de 20 ms. D'autres conditions pourrons être ajoutée si ajout d'état a lieu.&lt;br /&gt;
&lt;br /&gt;
==== Test ====&lt;br /&gt;
===== Clignotement de deux LED à fréquences indivisibles entre elles =====&lt;br /&gt;
Afin de vérifier la réussite de notre ordonnanceur à fonctionnement tourniquet, nous avons programmer deux simples tâches changeant l'état d'une LED. Une à une fréquence 200ms et l'autre 300ms (avec un __delay_ms).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:left; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void tache1(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTC ^= (1 &amp;lt;&amp;lt; PC0);&lt;br /&gt;
    _delay_ms(300);}}&lt;br /&gt;
void tache2(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTD ^= (1 &amp;lt;&amp;lt; PD7);&lt;br /&gt;
    _delay_ms(200);}}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
[[Fichier:B5_test1.mp4|vignette|alt=test des frequences imprevisibles|test des frequences imprevisibles]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== Clignotement grâce à l'état endormi =====&lt;br /&gt;
Nous ajoutons l'état endormi afin que nos tâches ne mettent pas en pause l'ordonnanceur avec un _delay_ms. Pour cela, nous incorporons une fonction makeSleep qui permet de mettrela tâche qui l'appelle dans cet état.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:left; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void makeSleep(int t){&lt;br /&gt;
  table_process[indice_tache].etat.id = SLEEPY;&lt;br /&gt;
  table_process[indice_tache].etat.time.sleepingtime = t;&lt;br /&gt;
  TIMER1_COMPA_vect();}&lt;br /&gt;
void tache1(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTC ^= (1 &amp;lt;&amp;lt; PC0);&lt;br /&gt;
    _delay_ms(300);}}&lt;br /&gt;
void tache3(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTC ^= (1 &amp;lt;&amp;lt; PC3);&lt;br /&gt;
    //_delay_ms(1000);&lt;br /&gt;
    makeSleep(1000);}}&lt;br /&gt;
void tache2(void){&lt;br /&gt;
  while (1){&lt;br /&gt;
    PORTD ^= (1 &amp;lt;&amp;lt; PD7);&lt;br /&gt;
    //_delay_ms(1000);&lt;br /&gt;
    makeSleep(700);}}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
[[Fichier:B5_test2.mp4|vignette|alt=test des frequences imprevisibles|test des frequences imprevisibles]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
A noter que la première tâche executée ne doit pas être endormie.&lt;br /&gt;
= Carte Fille Matrice de touches =&lt;br /&gt;
&lt;br /&gt;
== Carte ==&lt;br /&gt;
&lt;br /&gt;
=== Fille après soudure des composants ===&lt;/div&gt;</summary>
		<author><name>Adjadjaa</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-5&amp;diff=6708</id>
		<title>SE4Binome2024-5</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-5&amp;diff=6708"/>
		<updated>2024-11-18T10:00:41Z</updated>

		<summary type="html">&lt;p&gt;Adjadjaa : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Introduction=&lt;br /&gt;
&lt;br /&gt;
Ce wiki documente le développement d’un pico-ordinateur modulaire. Ce dernier est constitué d’une carte principale, composée d’une carte Shield permettant la connexion des cartes filles, et d’une carte mère (initialement simulée par une Arduino Uno avant sa conception finale). Plusieurs cartes filles sont prévues, chacune remplissant une fonction spécifique : gestion du clavier, affichage, port série, réseau, mémoire de masse et son.&lt;br /&gt;
&lt;br /&gt;
Notre binôme est spécifiquement chargé du développement de la carte fille dédiée au clavier.&lt;br /&gt;
&lt;br /&gt;
Toutes les ressources nécessaires, incluant les codes sources et les schémas, sont disponibles sur le dépôt Git suivant :  [https://gitea.plil.fr/ktouron/se4-djadja-touron_pico.git Lien du Git]&lt;br /&gt;
&lt;br /&gt;
= Carte Shield =&lt;br /&gt;
== Hardware ==&lt;br /&gt;
[[Fichier:Carte Recto non soudé.jpg|vignette|left|thumb|350px|Recto de la carte avant soudage des composants]]&lt;br /&gt;
[[Fichier:Verso non solder.jpeg.jpg|vignette|thumb|right|350px|Verso de la carte avant soudage des composants]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Carte Shield après soudure des composants ===&lt;br /&gt;
[[Fichier:Carde shield soudé.jpg|vignette|thumb|center|400px|Photo de la carte avec les composants soudés]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Software ==&lt;br /&gt;
===Test===&lt;br /&gt;
==== Allumage de LEDS sur Programmateur AVR ====&lt;br /&gt;
Avant de programmer directement sur le shield, nous avons allumé des LED pour tester la carte. Nous avons directement utilisé le code exemple fourni par l'IDE arduino en adaptant simplement les pins correspondant aux leds. [https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/PicoShield/Programmation/Blink Code du test]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Vid_test_carte_mp4.mp4|vignette|thumb|center|700px|Vidéo de Test des leds]]&lt;br /&gt;
&lt;br /&gt;
==== Lecture de la carte SD ====&lt;br /&gt;
Avant de programmer directement sur le shield, nous avons tester si la carte SD était bien détectée et lue. On a utilisé le code test présent dans l'IDE arduino en adaptant le port utilisé.[https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/PicoShield/Programmation/CardInfo Code du test]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Resultat SD.jpg|vignette|thumb|center|700px|Carte SD bien détéctée]]&lt;br /&gt;
&lt;br /&gt;
==== Connecteurs IDC HE10 ====&lt;br /&gt;
Afin de tester nos connecteur HE10, nous avons utilisé un afficher 7 segments (Sparkfun 7 segments display). Pour pouvoir vérifier leurs fonctionnements nous avons branché l'afficheur sur chaque connecteur tour à tour. Le programme implanté est un simple connecteur à afficher sur l'afficheur. Voici une vidéo du compteur fonctionnant sur un des 5 connecteurs HE10. ([https://learn.sparkfun.com/tutorials/using-the-serial-7-segment-display/all Code ici (section : Example 2 SPI)])&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Se4-5-7segments.mp4|vignette|alt=se4-5-7segments|Test connecteur HE10 avec afficheur 7 segments.|center]]&lt;br /&gt;
&lt;br /&gt;
= Carte Fille Matrice de touches =&lt;br /&gt;
&lt;br /&gt;
== Carte ==&lt;br /&gt;
&lt;br /&gt;
=== Fille après soudure des composants ===&lt;br /&gt;
&lt;br /&gt;
= Ordonnanceur =&lt;br /&gt;
Pour les interruptions de notre ordonnanceur nous avons utilisé la procédure d'initialisation du minuteur avec le Timer1 disponible dans les cours de Mr.Redon en renseignant une période de 20ms. Nous l'avons disposé dans le fichier minuteur.c car nous n'allons plus le modifier pour le reste du projet. Dans un autre fichier process.c (avec process.h), nous allons y mettre nos structures pour les process et leurs états puis une union pour le temps qui le caractérise ainsi que toutes les fonctions associés.&lt;br /&gt;
&lt;br /&gt;
[https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/Ordonnanceur Lien du répertoire]&lt;br /&gt;
&lt;br /&gt;
== Processus ==&lt;br /&gt;
=== Structure ===&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:right; width: 48%; padding-left: 10px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
    uint16_t adresseDepart;  //adresse de la fonction de départ &lt;br /&gt;
    uint16_t adressePile;       //adresse de la pile d'exécution&lt;br /&gt;
    Etat etat;        &lt;br /&gt;
} Process;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Notre structure caractérisant un processus est définie par les trois champs ci-contre.&lt;br /&gt;
&lt;br /&gt;
Une adresse de départ correspondant à la fonction du processus associé, l'adresse où se situe le processus dans la pile puis l'état de la tâche. Nous avons décidé de faire une structure à part entière compte tenu des multitudes d'états que nous pourrons ajouter pendant la progression du projet.&lt;br /&gt;
&lt;br /&gt;
=== Etat d'un processus ===&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:right; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
typedef union {&lt;br /&gt;
  int sleepingtime;       &lt;br /&gt;
} Time;&lt;br /&gt;
&lt;br /&gt;
typedef struct {&lt;br /&gt;
  int id;&lt;br /&gt;
  Time time;&lt;br /&gt;
} Etat ;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
L'état d'un processus est alors une structure à deux champs (pour l'instant), l'id doit correspondre à un '#DEFINE' pour avoir un sens tandis que nous avons choisi de faire une union pour le temps qui caractérise notre état afin qu'il puisse avoir un nom et type de variable cohérent avec son état.(Ici seulement sleepingtime car seul l'état endormi existe pour le moment)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
  {| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
  |+ Tableau des états&lt;br /&gt;
  |-&lt;br /&gt;
  ! Etat !! ACTIVE !! SLEEPY !! ... !! ...&lt;br /&gt;
  |-&lt;br /&gt;
  | Id || 0 || 1 || ... || ...&lt;br /&gt;
  |}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Procédures principales ===&lt;br /&gt;
&lt;br /&gt;
== ISR ==&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:right; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
ISR(TIMER1_COMPA_vect, ISR_NAKED)    // Procédure d'interruption&lt;br /&gt;
{&lt;br /&gt;
  TCNT1=0;//reset timer&lt;br /&gt;
  /* Sauvegarde du contexte de la tâche interrompue */&lt;br /&gt;
  portSAVE_REGISTERS();&lt;br /&gt;
   table_process[indice_tache].adressePile = SP;&lt;br /&gt;
  /* Appel à l'ordonnanceur */&lt;br /&gt;
  selectProcess();&lt;br /&gt;
  /* Récupération du contexte de la tâche ré-activée */&lt;br /&gt;
  SP = table_process[indice_tache].adressePile;&lt;br /&gt;
  portRESTORE_REGISTERS();&lt;br /&gt;
  &lt;br /&gt;
  asm volatile ( &amp;quot;reti&amp;quot; );&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
L'ISR est ce qu'il va être executer lors des interruptions toutes les 20 millisecondes. Cela consiste à sauvegarder tous les registres de la tâche qui était en cours avant l'appel de l'ISR pour ensuite passer à la tâche suivante valide (c'est à dire active) sans oublier de charger les registres de la nouvelle tâche.&lt;br /&gt;
&lt;br /&gt;
Nous devons également, à chaque fois avant de changer de tâche, enregistrer le pointeur de pile dans le processus afin de pouvoir revenir là ou elle en est la prochaine fois qu'elle sera appelée. Respectivement, une fois la nouvelle tâche choisie, le pointeur de pile doit prendre l'adresse de là ou en était la tâche avant qu'elle soit interrompue.&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Séléction de processus ===&lt;br /&gt;
Lors de la séléction de processus, nous devons parcourir tous les processus jusqu'au moment où nous en trouvons un actif. Ainsi, il deviendra la tâche que nous traiterons lors du prochain intervalle de 20 ms. A ce stade, à chaque fois que la procédure selectProcess est appelée, nous devons réduire le temps de repos de chaque process endormi de 20 ms. D'autres conditions pourrons être ajoutée si ajout d'état a lieu.&lt;br /&gt;
&lt;br /&gt;
== Test ==&lt;br /&gt;
=== Clignotement de deux LED à fréquences indivisibles entre elles ===&lt;br /&gt;
[[Fichier:B5_test1.mp4|vignette|alt=test des frequences imprevisibles|test des frequences imprevisibles]]&lt;br /&gt;
 ===&lt;br /&gt;
Afin de vérifier la réussite de notre ordonnanceur à fonctionnement tourniquet, nous avons programmer deux simples tâches changeant l'état d'une LED. Une à une fréquence 200ms et l'autre 300ms (avec un __delay_ms).&lt;/div&gt;</summary>
		<author><name>Adjadjaa</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-5&amp;diff=6698</id>
		<title>SE4Binome2024-5</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-5&amp;diff=6698"/>
		<updated>2024-11-18T09:53:46Z</updated>

		<summary type="html">&lt;p&gt;Adjadjaa : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Introduction=&lt;br /&gt;
&lt;br /&gt;
Ce wiki documente le développement d’un pico-ordinateur modulaire. Ce dernier est constitué d’une carte principale, composée d’une carte Shield permettant la connexion des cartes filles, et d’une carte mère (initialement simulée par une Arduino Uno avant sa conception finale). Plusieurs cartes filles sont prévues, chacune remplissant une fonction spécifique : gestion du clavier, affichage, port série, réseau, mémoire de masse et son.&lt;br /&gt;
&lt;br /&gt;
Notre binôme est spécifiquement chargé du développement de la carte fille dédiée au clavier.&lt;br /&gt;
&lt;br /&gt;
Toutes les ressources nécessaires, incluant les codes sources et les schémas, sont disponibles sur le dépôt Git suivant :  [https://gitea.plil.fr/ktouron/se4-djadja-touron_pico.git Lien du Git]&lt;br /&gt;
&lt;br /&gt;
= Carte Shield =&lt;br /&gt;
== Hardware ==&lt;br /&gt;
[[Fichier:Carte Recto non soudé.jpg|vignette|left|thumb|350px|Recto de la carte avant soudage des composants]]&lt;br /&gt;
[[Fichier:Verso non solder.jpeg.jpg|vignette|thumb|right|350px|Verso de la carte avant soudage des composants]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Carte Shield après soudure des composants ===&lt;br /&gt;
[[Fichier:Carde shield soudé.jpg|vignette|thumb|center|400px|Photo de la carte avec les composants soudés]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Software ==&lt;br /&gt;
=== Test Allumage de LEDS sur Programmateur AVR ===&lt;br /&gt;
Avant de programmer directement sur le shield, nous avons allumé des LED pour tester la carte. Nous avons directement utilisé le code exemple fourni par l'IDE arduino en adaptant simplement les pins correspondant aux leds. [https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/PicoShield/Programmation/Blink Code du test]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Vid_test_carte_mp4.mp4|vignette|thumb|center|700px|Vidéo de Test des leds]]&lt;br /&gt;
&lt;br /&gt;
=== Test de lecture de la carte SD ===&lt;br /&gt;
Avant de programmer directement sur le shield, nous avons tester si la carte SD était bien détectée et lue. On a utilisé le code test présent dans l'IDE arduino en adaptant le port utilisé.[https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/PicoShield/Programmation/CardInfo Code du test]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Resultat SD.jpg|vignette|thumb|center|700px|Carte SD bien détéctée]]&lt;br /&gt;
&lt;br /&gt;
=== Test des connecteurs IDC HE10 ===&lt;br /&gt;
Afin de tester nos connecteur HE10, nous avons utilisé un afficher 7 segments (Sparkfun 7 segments display). Pour pouvoir vérifier leurs fonctionnements nous avons branché l'afficheur sur chaque connecteur tour à tour. Le programme implanté est un simple connecteur à afficher sur l'afficheur. Voici une vidéo du compteur fonctionnant sur un des 5 connecteurs HE10. ([https://learn.sparkfun.com/tutorials/using-the-serial-7-segment-display/all Code ici (section : Example 2 SPI)])&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Se4-5-7segments.mp4|vignette|alt=se4-5-7segments|Test connecteur HE10 avec afficheur 7 segments.|center]]&lt;br /&gt;
&lt;br /&gt;
= Carte Fille Matrice de touches =&lt;br /&gt;
&lt;br /&gt;
== Carte ==&lt;br /&gt;
&lt;br /&gt;
=== Fille après soudure des composants ===&lt;br /&gt;
&lt;br /&gt;
= Ordonnanceur =&lt;br /&gt;
Pour les interruptions de notre ordonnanceur nous avons utilisé la procédure d'initialisation du minuteur avec le Timer1 disponible dans les cours de Mr.Redon en renseignant une période de 20ms. Nous l'avons disposé dans le fichier minuteur.c car nous n'allons plus le modifier pour le reste du projet. Dans un autre fichier process.c (avec process.h), nous allons y mettre nos structures pour les process et leurs états puis une union pour le temps qui le caractérise ainsi que toutes les fonctions associés.&lt;br /&gt;
&lt;br /&gt;
[https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/Ordonnanceur Lien du répertoire]&lt;br /&gt;
&lt;br /&gt;
== Processus ==&lt;br /&gt;
=== Structure ===&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:right; width: 48%; padding-left: 10px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
    uint16_t adresseDepart;  //adresse de la fonction de départ &lt;br /&gt;
    uint16_t adressePile;       //adresse de la pile d'exécution&lt;br /&gt;
    Etat etat;        &lt;br /&gt;
} Process;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Notre structure caractérisant un processus est définie par les trois champs ci-contre.&lt;br /&gt;
&lt;br /&gt;
Une adresse de départ correspondant à la fonction du processus associé, l'adresse où se situe le processus dans la pile puis l'état de la tâche. Nous avons décidé de faire une structure à part entière compte tenu des multitudes d'états que nous pourrons ajouter pendant la progression du projet.&lt;br /&gt;
&lt;br /&gt;
=== Etat d'un processus ===&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:right; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
typedef union {&lt;br /&gt;
  int sleepingtime;       &lt;br /&gt;
} Time;&lt;br /&gt;
&lt;br /&gt;
typedef struct {&lt;br /&gt;
  int id;&lt;br /&gt;
  Time time;&lt;br /&gt;
} Etat ;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
L'état d'un processus est alors une structure à deux champs (pour l'instant), l'id doit correspondre à un '#DEFINE' pour avoir un sens tandis que nous avons choisi de faire une union pour le temps qui caractérise notre état afin qu'il puisse avoir un nom et type de variable cohérent avec son état.(Ici seulement sleepingtime car seul l'état endormi existe pour le moment)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
  {| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
  |+ Tableau des états&lt;br /&gt;
  |-&lt;br /&gt;
  ! Etat !! ACTIVE !! SLEEPY !! ... !! ...&lt;br /&gt;
  |-&lt;br /&gt;
  | Id || 0 || 1 || ... || ...&lt;br /&gt;
  |}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Procédures principales ===&lt;br /&gt;
&lt;br /&gt;
== ISR ==&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:right; width: 48%; padding-left: 100px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
ISR(TIMER1_COMPA_vect, ISR_NAKED)    // Procédure d'interruption&lt;br /&gt;
{&lt;br /&gt;
  TCNT1=0;//reset timer&lt;br /&gt;
  /* Sauvegarde du contexte de la tâche interrompue */&lt;br /&gt;
  portSAVE_REGISTERS();&lt;br /&gt;
   table_process[indice_tache].adressePile = SP;&lt;br /&gt;
  /* Appel à l'ordonnanceur */&lt;br /&gt;
  selectProcess();&lt;br /&gt;
  /* Récupération du contexte de la tâche ré-activée */&lt;br /&gt;
  SP = table_process[indice_tache].adressePile;&lt;br /&gt;
  portRESTORE_REGISTERS();&lt;br /&gt;
  &lt;br /&gt;
  asm volatile ( &amp;quot;reti&amp;quot; );&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
L'ISR est ce qu'il va être executer lors des interruptions toutes les 20 millisecondes. Cela consiste à sauvegarder tous les registres de la tâche qui était en cours avant l'appel de l'ISR pour ensuite passer à la tâche suivante valide (c'est à dire active) sans oublier de charger les registres de la nouvelle tâche.&lt;br /&gt;
&lt;br /&gt;
Nous devons également, à chaque fois avant de changer de tâche, enregistrer le pointeur de pile dans le processus afin de pouvoir revenir là ou elle en est la prochaine fois qu'elle sera appelée. Respectivement, une fois la nouvelle tâche choisie, le pointeur de pile doit prendre l'adresse de là ou en était la tâche avant qu'elle soit interrompue.&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Séléction de processus ===&lt;br /&gt;
Lors de la séléction de processus, nous devons parcourir tous les processus jusqu'au moment où nous en trouvons un actif. Ainsi, il deviendra la tâche que nous traiterons lors du prochain intervalle de 20 ms. A ce stade, à chaque fois que la procédure selectProcess est appelée, nous devons réduire le temps de repos de chaque process endormi de 20 ms. D'autres conditions pourrons être ajoutée si ajout d'état a lieu.&lt;br /&gt;
&lt;br /&gt;
== Test ==&lt;br /&gt;
=== Clignotement de deux LED à fréquences indivisibles ===&lt;/div&gt;</summary>
		<author><name>Adjadjaa</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-5&amp;diff=6599</id>
		<title>SE4Binome2024-5</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-5&amp;diff=6599"/>
		<updated>2024-11-13T10:11:56Z</updated>

		<summary type="html">&lt;p&gt;Adjadjaa : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Introduction=&lt;br /&gt;
&lt;br /&gt;
Ce wiki documente le développement d’un pico-ordinateur modulaire. Ce dernier est constitué d’une carte principale, composée d’une carte Shield permettant la connexion des cartes filles, et d’une carte mère (initialement simulée par une Arduino Uno avant sa conception finale). Plusieurs cartes filles sont prévues, chacune remplissant une fonction spécifique : gestion du clavier, affichage, port série, réseau, mémoire de masse et son.&lt;br /&gt;
&lt;br /&gt;
Notre binôme est spécifiquement chargé du développement de la carte fille dédiée au clavier.&lt;br /&gt;
&lt;br /&gt;
Toutes les ressources nécessaires, incluant les codes sources et les schémas, sont disponibles sur le dépôt Git suivant :  [https://gitea.plil.fr/ktouron/se4-djadja-touron_pico.git Lien du Git]&lt;br /&gt;
&lt;br /&gt;
= Carte Shield =&lt;br /&gt;
[[Fichier:Carte Recto non soudé.jpg|vignette|left|thumb|350px|Recto de la carte avant soudage des composants]]&lt;br /&gt;
[[Fichier:Verso non solder.jpeg.jpg|vignette|thumb|right|350px|Verso de la carte avant soudage des composants]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Carte Shield après soudure des composants ==&lt;br /&gt;
[[Fichier:Carde shield soudé.jpg|vignette|thumb|center|400px|Photo de la carte avec les composants soudés]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Allumage de LEDS sur Programmateur AVR ==&lt;br /&gt;
Avant de programmer directement sur le shield, nous avons allumé des LED pour tester la carte. Nous avons directement utilisé le code exemple fourni par l'IDE arduino en adaptant simplement les pins correspondant aux leds.&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/PicoShield/Programmation/Blink&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Vid_test_carte_mp4.mp4|vignette|thumb|center|700px|Vidéo de Test des leds]]&lt;br /&gt;
&lt;br /&gt;
== Test de lecture de la carte SD ==&lt;br /&gt;
Avant de programmer directement sur le shield, nous avons tester si la carte SD était bien détectée et lue. On a utilisé le code test présent dans l'IDE arduino en adaptant le port utilisé.&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/PicoShield/Programmation/CardInfo&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Resultat SD.jpg|vignette|thumb|center|700px|Carte SD bien détéctée]]&lt;br /&gt;
&lt;br /&gt;
== Test des connecteurs IDC HE10 ==&lt;br /&gt;
Afin de tester nos connecteur HE10, nous avons utilisé un afficher 7 segments (Sparkfun 7 segments display). Pour pouvoir vérifier leurs fonctionnements nous avons branché l'afficheur sur chaque connecteur tour à tour. Le programme implanté est un simple connecteur à afficher sur l'afficheur. Voici une vidéo du compteur fonctionnant sur un des 5 connecteurs HE10. ([https://learn.sparkfun.com/tutorials/using-the-serial-7-segment-display/all Code ici (section : Example 2 SPI)])&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Se4-5-7segments.mp4|vignette|alt=se4-5-7segments|Test connecteur HE10 avec afficheur 7 segments.|center]]&lt;br /&gt;
&lt;br /&gt;
= Carte Fille =&lt;br /&gt;
&lt;br /&gt;
== Carte Fille après soudure des composants ==&lt;br /&gt;
&lt;br /&gt;
= Ordonnanceur =&lt;br /&gt;
Pour les interruptions de notre ordonnanceur nous avons utilisé la procédure d'initialisation du minuteur avec le Timer1 disponible dans les cours de Mr.Redon en renseignant une période de 20ms. Nous l'avons disposé dans le fichier minuteur.c car nous n'allons plus le modifier pour le reste du projet. Dans un autre fichier process.c (avec process.h), nous allons y mettre nos structures pour les process et leurs états puis une union pour le temps qui le caractérise ainsi que toutes les fonctions associés.&lt;br /&gt;
&lt;br /&gt;
[https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/Ordonnanceur Lien du répertoire]&lt;br /&gt;
&lt;br /&gt;
== Processus ==&lt;br /&gt;
=== Structure principale ===&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:right; width: 48%; padding-left: 10px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
    uint16_t adresseDepart;  //adresse de la fonction de départ &lt;br /&gt;
    uint16_t adressePile;       //adresse de la pile d'exécution&lt;br /&gt;
    Etat etat;        &lt;br /&gt;
} Process;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Notre structure caractérisant un processus est définie par les trois champs ci-contre.&lt;br /&gt;
&lt;br /&gt;
Une adresse de départ correspondant à la fonction du processus associé, l'adresse où se situe le processus dans la pile puis l'état de la tâche. Nous avons décidé de faire une structure à part entière compte tenu des multitudes détat que nous pourrons ajouter pendant la progression du projet.&lt;br /&gt;
&lt;br /&gt;
=== Etat d'un processus ===&lt;br /&gt;
&lt;br /&gt;
==Coder le tableau des structures des processus==&lt;br /&gt;
Ce tableau des structures permet à un process d'ếtre caractériser par l'adresse du début de sa pile, l'adresse de la tâche (procédure) qu'elle va effectuer pui sont état (1 : réveillé, 0 : endormi). &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
    uint16_t adresseDepart;  //adresse de la fonction de départ &lt;br /&gt;
    uint16_t adressePile;       //adresse de la pile d'exécution&lt;br /&gt;
    bool etat;          //état du processus (1 ou 0)&lt;br /&gt;
} Process;&lt;br /&gt;
&lt;br /&gt;
Process table_process[MAXPROCESS];&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Coder la fonction d'initialisation de la pile d'un processus==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line&amp;gt;&lt;br /&gt;
A REMPLIR&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Taches ∞ pour faire clignoter deux leds à 2 fréquences premières entre elle==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line&amp;gt;&lt;br /&gt;
A REMPLIR&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
[[Fichier:Ordonnanceur cligno led.mp4|vignette|thumb|center|700px|Clignotement des leds à des fréquences premières entre elle avec l'ordonnanceur]]&lt;br /&gt;
&lt;br /&gt;
==Lancement des deux tâches en parallèle grâce à l'ordonnanceur à tourniquet==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line&amp;gt;&lt;br /&gt;
A REMPLIR&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Adjadjaa</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-5&amp;diff=6598</id>
		<title>SE4Binome2024-5</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-5&amp;diff=6598"/>
		<updated>2024-11-13T10:11:25Z</updated>

		<summary type="html">&lt;p&gt;Adjadjaa : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Introduction=&lt;br /&gt;
&lt;br /&gt;
Ce wiki documente le développement d’un pico-ordinateur modulaire. Ce dernier est constitué d’une carte principale, composée d’une carte Shield permettant la connexion des cartes filles, et d’une carte mère (initialement simulée par une Arduino Uno avant sa conception finale). Plusieurs cartes filles sont prévues, chacune remplissant une fonction spécifique : gestion du clavier, affichage, port série, réseau, mémoire de masse et son.&lt;br /&gt;
&lt;br /&gt;
Notre binôme est spécifiquement chargé du développement de la carte fille dédiée au clavier.&lt;br /&gt;
&lt;br /&gt;
Toutes les ressources nécessaires, incluant les codes sources et les schémas, sont disponibles sur le dépôt Git suivant : Lien vers le Git.&lt;br /&gt;
&lt;br /&gt;
= Carte Shield =&lt;br /&gt;
[[Fichier:Carte Recto non soudé.jpg|vignette|left|thumb|350px|Recto de la carte avant soudage des composants]]&lt;br /&gt;
[[Fichier:Verso non solder.jpeg.jpg|vignette|thumb|right|350px|Verso de la carte avant soudage des composants]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Carte Shield après soudure des composants ==&lt;br /&gt;
[[Fichier:Carde shield soudé.jpg|vignette|thumb|center|400px|Photo de la carte avec les composants soudés]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Allumage de LEDS sur Programmateur AVR ==&lt;br /&gt;
Avant de programmer directement sur le shield, nous avons allumé des LED pour tester la carte. Nous avons directement utilisé le code exemple fourni par l'IDE arduino en adaptant simplement les pins correspondant aux leds.&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/PicoShield/Programmation/Blink&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Vid_test_carte_mp4.mp4|vignette|thumb|center|700px|Vidéo de Test des leds]]&lt;br /&gt;
&lt;br /&gt;
== Test de lecture de la carte SD ==&lt;br /&gt;
Avant de programmer directement sur le shield, nous avons tester si la carte SD était bien détectée et lue. On a utilisé le code test présent dans l'IDE arduino en adaptant le port utilisé.&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/PicoShield/Programmation/CardInfo&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Resultat SD.jpg|vignette|thumb|center|700px|Carte SD bien détéctée]]&lt;br /&gt;
&lt;br /&gt;
== Test des connecteurs IDC HE10 ==&lt;br /&gt;
Afin de tester nos connecteur HE10, nous avons utilisé un afficher 7 segments (Sparkfun 7 segments display). Pour pouvoir vérifier leurs fonctionnements nous avons branché l'afficheur sur chaque connecteur tour à tour. Le programme implanté est un simple connecteur à afficher sur l'afficheur. Voici une vidéo du compteur fonctionnant sur un des 5 connecteurs HE10. ([https://learn.sparkfun.com/tutorials/using-the-serial-7-segment-display/all Code ici (section : Example 2 SPI)])&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Se4-5-7segments.mp4|vignette|alt=se4-5-7segments|Test connecteur HE10 avec afficheur 7 segments.|center]]&lt;br /&gt;
&lt;br /&gt;
= Carte Fille =&lt;br /&gt;
&lt;br /&gt;
== Carte Fille après soudure des composants ==&lt;br /&gt;
&lt;br /&gt;
= Ordonnanceur =&lt;br /&gt;
Pour les interruptions de notre ordonnanceur nous avons utilisé la procédure d'initialisation du minuteur avec le Timer1 disponible dans les cours de Mr.Redon en renseignant une période de 20ms. Nous l'avons disposé dans le fichier minuteur.c car nous n'allons plus le modifier pour le reste du projet. Dans un autre fichier process.c (avec process.h), nous allons y mettre nos structures pour les process et leurs états puis une union pour le temps qui le caractérise ainsi que toutes les fonctions associés.&lt;br /&gt;
&lt;br /&gt;
[https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/Ordonnanceur Lien du répertoire]&lt;br /&gt;
&lt;br /&gt;
== Processus ==&lt;br /&gt;
=== Structure principale ===&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:right; width: 48%; padding-left: 10px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
    uint16_t adresseDepart;  //adresse de la fonction de départ &lt;br /&gt;
    uint16_t adressePile;       //adresse de la pile d'exécution&lt;br /&gt;
    Etat etat;        &lt;br /&gt;
} Process;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Notre structure caractérisant un processus est définie par les trois champs ci-contre.&lt;br /&gt;
&lt;br /&gt;
Une adresse de départ correspondant à la fonction du processus associé, l'adresse où se situe le processus dans la pile puis l'état de la tâche. Nous avons décidé de faire une structure à part entière compte tenu des multitudes détat que nous pourrons ajouter pendant la progression du projet.&lt;br /&gt;
&lt;br /&gt;
=== Etat d'un processus ===&lt;br /&gt;
&lt;br /&gt;
==Coder le tableau des structures des processus==&lt;br /&gt;
Ce tableau des structures permet à un process d'ếtre caractériser par l'adresse du début de sa pile, l'adresse de la tâche (procédure) qu'elle va effectuer pui sont état (1 : réveillé, 0 : endormi). &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
    uint16_t adresseDepart;  //adresse de la fonction de départ &lt;br /&gt;
    uint16_t adressePile;       //adresse de la pile d'exécution&lt;br /&gt;
    bool etat;          //état du processus (1 ou 0)&lt;br /&gt;
} Process;&lt;br /&gt;
&lt;br /&gt;
Process table_process[MAXPROCESS];&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Coder la fonction d'initialisation de la pile d'un processus==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line&amp;gt;&lt;br /&gt;
A REMPLIR&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Taches ∞ pour faire clignoter deux leds à 2 fréquences premières entre elle==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line&amp;gt;&lt;br /&gt;
A REMPLIR&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
[[Fichier:Ordonnanceur cligno led.mp4|vignette|thumb|center|700px|Clignotement des leds à des fréquences premières entre elle avec l'ordonnanceur]]&lt;br /&gt;
&lt;br /&gt;
==Lancement des deux tâches en parallèle grâce à l'ordonnanceur à tourniquet==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line&amp;gt;&lt;br /&gt;
A REMPLIR&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Adjadjaa</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-5&amp;diff=6595</id>
		<title>SE4Binome2024-5</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-5&amp;diff=6595"/>
		<updated>2024-11-13T10:10:07Z</updated>

		<summary type="html">&lt;p&gt;Adjadjaa : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Introduction=&lt;br /&gt;
&lt;br /&gt;
Ce wiki présente le développement d'un pico-ordinateur. Il sera composé d'une carte principale, composé d'une carte shield permettant la connexion des cartes filles et d'une carte mère (arduino uno avant la réalisation de celle-ci),et de différentes cartes filles assurant les fonctions suivantes: clavier, affichage, port série, réseau, mémoire de masse et son. Notre binôme sera en charge de la carte fille clavier. Les ressources nécessaires, y compris les codes sources et les schémas, sont accessibles via le dépôt Git suivant : [https://gitea.plil.fr/ktouron/se4-djadja-touron_pico.git Lien du Git]&lt;br /&gt;
&lt;br /&gt;
= Carte Shield =&lt;br /&gt;
[[Fichier:Carte Recto non soudé.jpg|vignette|left|thumb|350px|Recto de la carte avant soudage des composants]]&lt;br /&gt;
[[Fichier:Verso non solder.jpeg.jpg|vignette|thumb|right|350px|Verso de la carte avant soudage des composants]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Carte Shield après soudure des composants ==&lt;br /&gt;
[[Fichier:Carde shield soudé.jpg|vignette|thumb|center|400px|Photo de la carte avec les composants soudés]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Allumage de LEDS sur Programmateur AVR ==&lt;br /&gt;
Avant de programmer directement sur le shield, nous avons allumé des LED pour tester la carte. Nous avons directement utilisé le code exemple fourni par l'IDE arduino en adaptant simplement les pins correspondant aux leds.&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/PicoShield/Programmation/Blink&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Vid_test_carte_mp4.mp4|vignette|thumb|center|700px|Vidéo de Test des leds]]&lt;br /&gt;
&lt;br /&gt;
== Test de lecture de la carte SD ==&lt;br /&gt;
Avant de programmer directement sur le shield, nous avons tester si la carte SD était bien détectée et lue. On a utilisé le code test présent dans l'IDE arduino en adaptant le port utilisé.&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/PicoShield/Programmation/CardInfo&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Resultat SD.jpg|vignette|thumb|center|700px|Carte SD bien détéctée]]&lt;br /&gt;
&lt;br /&gt;
== Test des connecteurs IDC HE10 ==&lt;br /&gt;
Afin de tester nos connecteur HE10, nous avons utilisé un afficher 7 segments (Sparkfun 7 segments display). Pour pouvoir vérifier leurs fonctionnements nous avons branché l'afficheur sur chaque connecteur tour à tour. Le programme implanté est un simple connecteur à afficher sur l'afficheur. Voici une vidéo du compteur fonctionnant sur un des 5 connecteurs HE10. ([https://learn.sparkfun.com/tutorials/using-the-serial-7-segment-display/all Code ici (section : Example 2 SPI)])&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Se4-5-7segments.mp4|vignette|alt=se4-5-7segments|Test connecteur HE10 avec afficheur 7 segments.|center]]&lt;br /&gt;
&lt;br /&gt;
= Carte Fille =&lt;br /&gt;
&lt;br /&gt;
== Carte Fille après soudure des composants ==&lt;br /&gt;
&lt;br /&gt;
= Ordonnanceur =&lt;br /&gt;
Pour les interruptions de notre ordonnanceur nous avons utilisé la procédure d'initialisation du minuteur avec le Timer1 disponible dans les cours de Mr.Redon en renseignant une période de 20ms. Nous l'avons disposé dans le fichier minuteur.c car nous n'allons plus le modifier pour le reste du projet. Dans un autre fichier process.c (avec process.h), nous allons y mettre nos structures pour les process et leurs états puis une union pour le temps qui le caractérise ainsi que toutes les fonctions associés.&lt;br /&gt;
&lt;br /&gt;
[https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/Ordonnanceur Lien du répertoire]&lt;br /&gt;
&lt;br /&gt;
== Processus ==&lt;br /&gt;
=== Structure principale ===&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:right; width: 48%; padding-left: 10px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
    uint16_t adresseDepart;  //adresse de la fonction de départ &lt;br /&gt;
    uint16_t adressePile;       //adresse de la pile d'exécution&lt;br /&gt;
    Etat etat;        &lt;br /&gt;
} Process;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Notre structure caractérisant un processus est définie par les trois champs ci-contre.&lt;br /&gt;
&lt;br /&gt;
Une adresse de départ correspondant à la fonction du processus associé, l'adresse où se situe le processus dans la pile puis l'état de la tâche. Nous avons décidé de faire une structure à part entière compte tenu des multitudes détat que nous pourrons ajouter pendant la progression du projet.&lt;br /&gt;
&lt;br /&gt;
=== Etat d'un processus ===&lt;br /&gt;
&lt;br /&gt;
==Coder le tableau des structures des processus==&lt;br /&gt;
Ce tableau des structures permet à un process d'ếtre caractériser par l'adresse du début de sa pile, l'adresse de la tâche (procédure) qu'elle va effectuer pui sont état (1 : réveillé, 0 : endormi). &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
    uint16_t adresseDepart;  //adresse de la fonction de départ &lt;br /&gt;
    uint16_t adressePile;       //adresse de la pile d'exécution&lt;br /&gt;
    bool etat;          //état du processus (1 ou 0)&lt;br /&gt;
} Process;&lt;br /&gt;
&lt;br /&gt;
Process table_process[MAXPROCESS];&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Coder la fonction d'initialisation de la pile d'un processus==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line&amp;gt;&lt;br /&gt;
A REMPLIR&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Taches ∞ pour faire clignoter deux leds à 2 fréquences premières entre elle==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line&amp;gt;&lt;br /&gt;
A REMPLIR&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
[[Fichier:Ordonnanceur cligno led.mp4|vignette|thumb|center|700px|Clignotement des leds à des fréquences premières entre elle avec l'ordonnanceur]]&lt;br /&gt;
&lt;br /&gt;
==Lancement des deux tâches en parallèle grâce à l'ordonnanceur à tourniquet==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line&amp;gt;&lt;br /&gt;
A REMPLIR&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Adjadjaa</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-5&amp;diff=6591</id>
		<title>SE4Binome2024-5</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-5&amp;diff=6591"/>
		<updated>2024-11-13T10:08:05Z</updated>

		<summary type="html">&lt;p&gt;Adjadjaa : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Introduction=&lt;br /&gt;
&lt;br /&gt;
Ce wiki présente le développement d'un pico-ordinateur. Il sera composé d'une carte principale, composé d'une carte shield permettant la connexion des cartes filles et d'une carte mère (arduino uno avant la réalisation de celle-ci),et de différentes cartes filles assurant les fonctions suivantes: clavier, affichage, port série, réseau, mémoire de masse et son. Notre binôme sera en charge de la carte fille clavier. Les ressources nécessaires, y compris les codes sources et les schémas, sont accessibles via le dépôt Git suivant : https://gitea.plil.fr/ktouron/se4-djadja-touron_pico.git&lt;br /&gt;
&lt;br /&gt;
Carte fille clavier &amp;quot;matrice de touches&amp;quot;&lt;br /&gt;
&lt;br /&gt;
= Carte Shield =&lt;br /&gt;
[[Fichier:Carte Recto non soudé.jpg|vignette|left|thumb|350px|Recto de la carte avant soudage des composants]]&lt;br /&gt;
[[Fichier:Verso non solder.jpeg.jpg|vignette|thumb|right|350px|Verso de la carte avant soudage des composants]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Carte Shield après soudure des composants ==&lt;br /&gt;
[[Fichier:Carde shield soudé.jpg|vignette|thumb|center|400px|Photo de la carte avec les composants soudés]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Allumage de LEDS sur Programmateur AVR ==&lt;br /&gt;
Avant de programmer directement sur le shield, nous avons allumé des LED pour tester la carte. Nous avons directement utilisé le code exemple fourni par l'IDE arduino en adaptant simplement les pins correspondant aux leds.&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/PicoShield/Programmation/Blink&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Vid_test_carte_mp4.mp4|vignette|thumb|center|700px|Vidéo de Test des leds]]&lt;br /&gt;
&lt;br /&gt;
== Test de lecture de la carte SD ==&lt;br /&gt;
Avant de programmer directement sur le shield, nous avons tester si la carte SD était bien détectée et lue. On a utilisé le code test présent dans l'IDE arduino en adaptant le port utilisé.&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/PicoShield/Programmation/CardInfo&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Resultat SD.jpg|vignette|thumb|center|700px|Carte SD bien détéctée]]&lt;br /&gt;
&lt;br /&gt;
== Test des connecteurs IDC HE10 ==&lt;br /&gt;
Afin de tester nos connecteur HE10, nous avons utilisé un afficher 7 segments (Sparkfun 7 segments display). Pour pouvoir vérifier leurs fonctionnements nous avons branché l'afficheur sur chaque connecteur tour à tour. Le programme implanté est un simple connecteur à afficher sur l'afficheur. Voici une vidéo du compteur fonctionnant sur un des 5 connecteurs HE10. ([https://learn.sparkfun.com/tutorials/using-the-serial-7-segment-display/all Code ici (section : Example 2 SPI)])&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Se4-5-7segments.mp4|vignette|alt=se4-5-7segments|Test connecteur HE10 avec afficheur 7 segments.|center]]&lt;br /&gt;
&lt;br /&gt;
= Carte Fille =&lt;br /&gt;
&lt;br /&gt;
== Carte Fille après soudure des composants ==&lt;br /&gt;
&lt;br /&gt;
= Ordonnanceur =&lt;br /&gt;
Pour les interruptions de notre ordonnanceur nous avons utilisé la procédure d'initialisation du minuteur avec le Timer1 disponible dans les cours de Mr.Redon en renseignant une période de 20ms. Nous l'avons disposé dans le fichier minuteur.c car nous n'allons plus le modifier pour le reste du projet. Dans un autre fichier process.c (avec process.h), nous allons y mettre nos structures pour les process et leurs états puis une union pour le temps qui le caractérise ainsi que toutes les fonctions associés.&lt;br /&gt;
&lt;br /&gt;
[https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/Ordonnanceur Lien du répertoire]&lt;br /&gt;
&lt;br /&gt;
== Processus ==&lt;br /&gt;
=== Structure principale ===&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:right; width: 48%; padding-left: 10px;&amp;quot;&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
    uint16_t adresseDepart;  //adresse de la fonction de départ &lt;br /&gt;
    uint16_t adressePile;       //adresse de la pile d'exécution&lt;br /&gt;
    Etat etat;        &lt;br /&gt;
} Process;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Notre structure caractérisant un processus est définie par les trois champs ci-contre.&lt;br /&gt;
&lt;br /&gt;
Une adresse de départ correspondant à la fonction du processus associé, l'adresse où se situe le processus dans la pile puis l'état de la tâche. Nous avons décidé de faire une structure à part entière compte tenu des multitudes détat que nous pourrons ajouter pendant la progression du projet.&lt;br /&gt;
&lt;br /&gt;
=== Etat d'un processus ===&lt;br /&gt;
&lt;br /&gt;
==Coder le tableau des structures des processus==&lt;br /&gt;
Ce tableau des structures permet à un process d'ếtre caractériser par l'adresse du début de sa pile, l'adresse de la tâche (procédure) qu'elle va effectuer pui sont état (1 : réveillé, 0 : endormi). &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
    uint16_t adresseDepart;  //adresse de la fonction de départ &lt;br /&gt;
    uint16_t adressePile;       //adresse de la pile d'exécution&lt;br /&gt;
    bool etat;          //état du processus (1 ou 0)&lt;br /&gt;
} Process;&lt;br /&gt;
&lt;br /&gt;
Process table_process[MAXPROCESS];&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Coder la fonction d'initialisation de la pile d'un processus==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line&amp;gt;&lt;br /&gt;
A REMPLIR&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Taches ∞ pour faire clignoter deux leds à 2 fréquences premières entre elle==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line&amp;gt;&lt;br /&gt;
A REMPLIR&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
[[Fichier:Ordonnanceur cligno led.mp4|vignette|thumb|center|700px|Clignotement des leds à des fréquences premières entre elle avec l'ordonnanceur]]&lt;br /&gt;
&lt;br /&gt;
==Lancement des deux tâches en parallèle grâce à l'ordonnanceur à tourniquet==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line&amp;gt;&lt;br /&gt;
A REMPLIR&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Adjadjaa</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-5&amp;diff=6299</id>
		<title>SE4Binome2024-5</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-5&amp;diff=6299"/>
		<updated>2024-10-15T13:47:43Z</updated>

		<summary type="html">&lt;p&gt;Adjadjaa : /* Carte Shield */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;git : https://gitea.plil.fr/ktouron/se4-djadja-touron_pico.git&lt;br /&gt;
&lt;br /&gt;
Carte fille clavier &amp;quot;matrice de touches&amp;quot;&lt;br /&gt;
=Hardware=&lt;br /&gt;
&lt;br /&gt;
== Carte Shield ==&lt;br /&gt;
[[Fichier:Carte Recto non soudé.jpg|vignette|left|thumb|350px|Recto de la carte avant soudage des composants]]&lt;br /&gt;
[[Fichier:Verso non solder.jpeg.jpg|vignette|thumb|right|350px|Verso de la carte avant soudage des composants]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Carte Shield après soudure des composants ==&lt;br /&gt;
[[Fichier:Carde shield soudé.jpg|vignette|thumb|center|400px|Photo de la carte avec les composants soudés]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Carte Fille ==&lt;br /&gt;
&lt;br /&gt;
== Carte Fille après soudure des composants ==&lt;br /&gt;
&lt;br /&gt;
= Software =&lt;br /&gt;
== Carte Shield ==&lt;br /&gt;
=== Allumage de LEDS sur Programmateur AVR ===&lt;br /&gt;
Avant de programmer directement sur le shield, nous avons allumé des LED pour tester la carte. Nous avons directement utilisé le code exemple fourni par l'IDE arduino en adaptant simplement les pins correspondant aux leds.&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/PicoShield/Programmation/Blink&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Vid_test_carte_mp4.mp4|vignette|thumb|center|700px|Vidéo de Test des leds]]&lt;br /&gt;
&lt;br /&gt;
=== Test de lecture de la carte SD ===&lt;br /&gt;
Avant de programmer directement sur le shield, nous avons tester si la carte SD était bien détectée et lue. On a utilisé le code test présent dans l'IDE arduino en adaptant le port utilisé.&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/PicoShield/Programmation/CardInfo&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Resultat SD.jpg|vignette|thumb|center|700px|Carte SD bien détéctée]]&lt;br /&gt;
&lt;br /&gt;
=== Test des connecteurs IDC HE10 ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Ordonnanceur===&lt;br /&gt;
==== Allumer la LED broche PB5 avec Timer1 ISR ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line&amp;gt;&lt;br /&gt;
#define CTC1            WGM12           // Meilleur nom pour le bit&lt;br /&gt;
&lt;br /&gt;
#define PERIODE         20&lt;br /&gt;
&lt;br /&gt;
void init_minuteur(int diviseur,long periode){&lt;br /&gt;
  TCCR1A=0;               // Le mode choisi n'utilise pas ce registre&lt;br /&gt;
  TCCR1B=(1&amp;lt;&amp;lt;CTC1);       // Réinitialisation du minuteur sur expiration&lt;br /&gt;
  switch(diviseur){&lt;br /&gt;
    case    8: TCCR1B |= (1&amp;lt;&amp;lt;CS11); break;&lt;br /&gt;
    case   64: TCCR1B |= (1&amp;lt;&amp;lt;CS11 | 11&amp;lt;&amp;lt;CS10); break;&lt;br /&gt;
    case  256: TCCR1B |= (1&amp;lt;&amp;lt;CS12); break;&lt;br /&gt;
    case 1024: TCCR1B |= (1&amp;lt;&amp;lt;CS12 | 1&amp;lt;&amp;lt;CS10); break;&lt;br /&gt;
    }&lt;br /&gt;
  // Un cycle prend 1/F_CPU secondes.&lt;br /&gt;
  // Un pas de compteur prend diviseur/F_CPU secondes.&lt;br /&gt;
  // Pour une periode en millisecondes, il faut (periode/1000)/(diviseur/F_CPU) pas&lt;br /&gt;
  // soit (periode*F_CPU)/(1000*diviseur)&lt;br /&gt;
  OCR1A=F_CPU/1000*periode/diviseur;  // Calcul du pas&lt;br /&gt;
  TCNT1=0;                // Compteur initialisé&lt;br /&gt;
  TIMSK1=(1&amp;lt;&amp;lt;OCIE1A);     // Comparaison du compteur avec OCR1A&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
ISR(TIMER1_COMPA_vect/*, ISR_NAKED*/)    // Procédure d'interruption&lt;br /&gt;
{&lt;br /&gt;
  PORTB ^= (1 &amp;lt;&amp;lt; PB5); &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int main(void){&lt;br /&gt;
  DDRB |= (1 &amp;lt;&amp;lt; PB5);                       &lt;br /&gt;
  init_minuteur(256,PERIODE);&lt;br /&gt;
  sei();&lt;br /&gt;
  while(1);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Macros de sauvegarde et restauration des registres====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line&amp;gt;&lt;br /&gt;
#define portSAVE_REGISTERS() \&lt;br /&gt;
asm volatile ( \&lt;br /&gt;
&amp;quot;push r0 \n\t&amp;quot; \&lt;br /&gt;
&amp;quot;in r0, __SREG__ \n\t&amp;quot;\&lt;br /&gt;
&amp;quot;cli \n\t&amp;quot; \&lt;br /&gt;
&amp;quot;push r0 \n\t&amp;quot;\ &lt;br /&gt;
&amp;quot;push r1 \n\t&amp;quot; \&lt;br /&gt;
&amp;quot;clr r1 \n\t&amp;quot; \&lt;br /&gt;
&amp;quot;push r2 \n\t&amp;quot;\&lt;br /&gt;
&amp;quot;push r3 \n\t&amp;quot;\&lt;br /&gt;
&amp;quot;push r4 \n\t&amp;quot;\&lt;br /&gt;
&amp;quot;push r5 \n\t&amp;quot;\&lt;br /&gt;
&amp;quot;push r6 \n\t&amp;quot;\&lt;br /&gt;
&amp;quot;push r7 \n\t&amp;quot;\&lt;br /&gt;
&amp;quot;push r8 \n\t&amp;quot;\&lt;br /&gt;
&amp;quot;push r9 \n\t&amp;quot;\&lt;br /&gt;
&amp;quot;push r10 \n\t&amp;quot;\&lt;br /&gt;
&amp;quot;push r11 \n\t&amp;quot;\&lt;br /&gt;
&amp;quot;push r12 \n\t&amp;quot;\&lt;br /&gt;
&amp;quot;push r13 \n\t&amp;quot;\&lt;br /&gt;
&amp;quot;push r14 \n\t&amp;quot;\&lt;br /&gt;
&amp;quot;push r15 \n\t&amp;quot;\&lt;br /&gt;
&amp;quot;push r16 \n\t&amp;quot;\&lt;br /&gt;
&amp;quot;push r17 \n\t&amp;quot; \&lt;br /&gt;
&amp;quot;push r18 \n\t&amp;quot;\&lt;br /&gt;
&amp;quot;push r19 \n\t&amp;quot;\&lt;br /&gt;
&amp;quot;push r20 \n\t&amp;quot; \&lt;br /&gt;
&amp;quot;push r21 \n\t&amp;quot;\&lt;br /&gt;
&amp;quot;push r22 \n\t&amp;quot;\&lt;br /&gt;
&amp;quot;push r23 \n\t&amp;quot;\&lt;br /&gt;
&amp;quot;push r24 \n\t&amp;quot;\&lt;br /&gt;
&amp;quot;push r25 \n\t&amp;quot;\&lt;br /&gt;
&amp;quot;push r26 \n\t&amp;quot;\&lt;br /&gt;
&amp;quot;push r27 \n\t&amp;quot;\&lt;br /&gt;
&amp;quot;push r28 \n\t&amp;quot;\&lt;br /&gt;
&amp;quot;push r29 \n\t&amp;quot;\&lt;br /&gt;
&amp;quot;push r30 \n\t&amp;quot;\&lt;br /&gt;
&amp;quot;push r31 \n\t&amp;quot;\&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
#define portRESTORE_REGISTERS() \&lt;br /&gt;
asm volatile (\&lt;br /&gt;
&amp;quot;pop r31 \n\t&amp;quot; \&lt;br /&gt;
&amp;quot;pop r30 \n\t&amp;quot;\&lt;br /&gt;
&amp;quot;pop r29 \n\t&amp;quot; \&lt;br /&gt;
&amp;quot;pop r28 \n\t&amp;quot;  \&lt;br /&gt;
&amp;quot;pop r27 \n\t&amp;quot; \&lt;br /&gt;
&amp;quot;pop r26 \n\t&amp;quot; \&lt;br /&gt;
&amp;quot;pop r25 \n\t&amp;quot;\&lt;br /&gt;
&amp;quot;pop r24 \n\t&amp;quot; \&lt;br /&gt;
&amp;quot;pop r23 \n\t&amp;quot; \&lt;br /&gt;
&amp;quot;pop r22 \n\t&amp;quot; \&lt;br /&gt;
&amp;quot;pop r21 \n\t&amp;quot; \&lt;br /&gt;
&amp;quot;pop r20 \n\t&amp;quot; \&lt;br /&gt;
&amp;quot;pop r19 \n\t&amp;quot; \&lt;br /&gt;
&amp;quot;pop r18 \n\t&amp;quot; \&lt;br /&gt;
&amp;quot;pop r17 \n\t&amp;quot; \&lt;br /&gt;
&amp;quot;pop r16 \n\t&amp;quot; \&lt;br /&gt;
&amp;quot;pop r15 \n\t&amp;quot; \&lt;br /&gt;
&amp;quot;pop r14 \n\t&amp;quot; \&lt;br /&gt;
&amp;quot;pop r13 \n\t&amp;quot; \&lt;br /&gt;
&amp;quot;pop r12 \n\t&amp;quot; \&lt;br /&gt;
&amp;quot;pop r11 \n\t&amp;quot; \&lt;br /&gt;
&amp;quot;pop r10 \n\t&amp;quot;\&lt;br /&gt;
&amp;quot;pop r9 \n\t&amp;quot; \&lt;br /&gt;
&amp;quot;pop r8 \n\t&amp;quot; \&lt;br /&gt;
&amp;quot;pop r7 \n\t&amp;quot; \&lt;br /&gt;
&amp;quot;pop r6 \n\t&amp;quot; \&lt;br /&gt;
&amp;quot;pop r5 \n\t&amp;quot; \&lt;br /&gt;
&amp;quot;pop r4 \n\t&amp;quot; \&lt;br /&gt;
&amp;quot;pop r3 \n\t&amp;quot; \&lt;br /&gt;
&amp;quot;pop r2 \n\t&amp;quot; \&lt;br /&gt;
&amp;quot;pop r1 \n\t&amp;quot; \&lt;br /&gt;
&amp;quot;pop r0 \n\t&amp;quot; \&lt;br /&gt;
&amp;quot;out __SREG__, r0 \n\t&amp;quot;\ &lt;br /&gt;
&amp;quot;pop r0 \n\t&amp;quot; \&lt;br /&gt;
);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Coder le tableau des structures des processus====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
    uint16_t adresseDepart;  //adresse de la fonction de départ &lt;br /&gt;
    uint16_t adressePile;       //adresse de la pile d'exécution&lt;br /&gt;
    bool etat;          //état du processus (1 ou 0)&lt;br /&gt;
} Process;&lt;br /&gt;
&lt;br /&gt;
Process table_process[MAXPROCESS];&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Coder la fonction d'initialisation de la pile d'un processus====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line&amp;gt;&lt;br /&gt;
A REMPLIR&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Taches ∞ pour faire clignoter deux leds à 2 fréquences premières entre elle====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line&amp;gt;&lt;br /&gt;
A REMPLIR&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
[[Fichier:Ordonnanceur cligno led.mp4|vignette|thumb|center|700px|Clignotement des leds à des fréquences premières entre elle avec l'ordonnanceur]]&lt;br /&gt;
&lt;br /&gt;
====Lancement des deux tâches en parallèle grâce à l'ordonnanceur à tourniquet====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line&amp;gt;&lt;br /&gt;
A REMPLIR&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Adjadjaa</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-5&amp;diff=6294</id>
		<title>SE4Binome2024-5</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-5&amp;diff=6294"/>
		<updated>2024-10-15T13:44:15Z</updated>

		<summary type="html">&lt;p&gt;Adjadjaa : /* Test de lecture de la carte SD */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;git : https://gitea.plil.fr/ktouron/se4-djadja-touron_pico.git&lt;br /&gt;
&lt;br /&gt;
Carte fille clavier &amp;quot;matrice de touches&amp;quot;&lt;br /&gt;
=Hardware=&lt;br /&gt;
&lt;br /&gt;
== Carte Shield ==&lt;br /&gt;
[[Fichier:Carte Recto non soudé.jpg|vignette|left|thumb|350px|Recto de la carte avant soudage des composants]]&lt;br /&gt;
[[Fichier:Verso non solder.jpeg.jpg|vignette|thumb|right|350px|Verso de la carte avant soudage des composants]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Carte Shield après soudure des composants ==&lt;br /&gt;
[[Fichier:Carde shield soudé.jpg|vignette|thumb|center|400px|Photo de la carte avec les composants soudés]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Carte Fille ==&lt;br /&gt;
&lt;br /&gt;
== Carte Fille après soudure des composants ==&lt;br /&gt;
&lt;br /&gt;
= Software =&lt;br /&gt;
== Carte Shield ==&lt;br /&gt;
=== Allumage de LEDS sur Programmateur AVR ===&lt;br /&gt;
Avant de programmer directement sur le shield, nous avons allumé des LED pour tester la carte. Nous avons directement utilisé le code exemple fourni par l'IDE arduino en adaptant simplement les pins correspondant aux leds.&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/PicoShield/Programmation/Blink&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Vid_test_carte_mp4.mp4|vignette|thumb|center|700px|Vidéo de Test des leds]]&lt;br /&gt;
&lt;br /&gt;
=== Test de lecture de la carte SD ===&lt;br /&gt;
Avant de programmer directement sur le shield, nous avons tester si la carte SD était bien détectée et lue. On a utilisé le code test présent dans l'IDE arduino en adaptant le port utilisé.&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/PicoShield/Programmation/CardInfo&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Resultat SD.jpg|vignette|thumb|center|700px|Carte SD bien détéctée]]&lt;br /&gt;
&lt;br /&gt;
=== Ordonnanceur===&lt;br /&gt;
==== Allumer la LED broche PB5 avec Timer1 ISR ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line&amp;gt;&lt;br /&gt;
#define CTC1            WGM12           // Meilleur nom pour le bit&lt;br /&gt;
&lt;br /&gt;
#define PERIODE         20&lt;br /&gt;
&lt;br /&gt;
void init_minuteur(int diviseur,long periode){&lt;br /&gt;
  TCCR1A=0;               // Le mode choisi n'utilise pas ce registre&lt;br /&gt;
  TCCR1B=(1&amp;lt;&amp;lt;CTC1);       // Réinitialisation du minuteur sur expiration&lt;br /&gt;
  switch(diviseur){&lt;br /&gt;
    case    8: TCCR1B |= (1&amp;lt;&amp;lt;CS11); break;&lt;br /&gt;
    case   64: TCCR1B |= (1&amp;lt;&amp;lt;CS11 | 11&amp;lt;&amp;lt;CS10); break;&lt;br /&gt;
    case  256: TCCR1B |= (1&amp;lt;&amp;lt;CS12); break;&lt;br /&gt;
    case 1024: TCCR1B |= (1&amp;lt;&amp;lt;CS12 | 1&amp;lt;&amp;lt;CS10); break;&lt;br /&gt;
    }&lt;br /&gt;
  // Un cycle prend 1/F_CPU secondes.&lt;br /&gt;
  // Un pas de compteur prend diviseur/F_CPU secondes.&lt;br /&gt;
  // Pour une periode en millisecondes, il faut (periode/1000)/(diviseur/F_CPU) pas&lt;br /&gt;
  // soit (periode*F_CPU)/(1000*diviseur)&lt;br /&gt;
  OCR1A=F_CPU/1000*periode/diviseur;  // Calcul du pas&lt;br /&gt;
  TCNT1=0;                // Compteur initialisé&lt;br /&gt;
  TIMSK1=(1&amp;lt;&amp;lt;OCIE1A);     // Comparaison du compteur avec OCR1A&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
ISR(TIMER1_COMPA_vect/*, ISR_NAKED*/)    // Procédure d'interruption&lt;br /&gt;
{&lt;br /&gt;
  PORTB ^= (1 &amp;lt;&amp;lt; PB5); &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int main(void){&lt;br /&gt;
  DDRB |= (1 &amp;lt;&amp;lt; PB5);                       &lt;br /&gt;
  init_minuteur(256,PERIODE);&lt;br /&gt;
  sei();&lt;br /&gt;
  while(1);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Macros de sauvegarde et restauration des registres====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line&amp;gt;&lt;br /&gt;
#define portSAVE_REGISTERS() \&lt;br /&gt;
asm volatile ( \&lt;br /&gt;
&amp;quot;push r0 \n\t&amp;quot; \&lt;br /&gt;
&amp;quot;in r0, __SREG__ \n\t&amp;quot;\&lt;br /&gt;
&amp;quot;cli \n\t&amp;quot; \&lt;br /&gt;
&amp;quot;push r0 \n\t&amp;quot;\ &lt;br /&gt;
&amp;quot;push r1 \n\t&amp;quot; \&lt;br /&gt;
&amp;quot;clr r1 \n\t&amp;quot; \&lt;br /&gt;
&amp;quot;push r2 \n\t&amp;quot;\&lt;br /&gt;
&amp;quot;push r3 \n\t&amp;quot;\&lt;br /&gt;
&amp;quot;push r4 \n\t&amp;quot;\&lt;br /&gt;
&amp;quot;push r5 \n\t&amp;quot;\&lt;br /&gt;
&amp;quot;push r6 \n\t&amp;quot;\&lt;br /&gt;
&amp;quot;push r7 \n\t&amp;quot;\&lt;br /&gt;
&amp;quot;push r8 \n\t&amp;quot;\&lt;br /&gt;
&amp;quot;push r9 \n\t&amp;quot;\&lt;br /&gt;
&amp;quot;push r10 \n\t&amp;quot;\&lt;br /&gt;
&amp;quot;push r11 \n\t&amp;quot;\&lt;br /&gt;
&amp;quot;push r12 \n\t&amp;quot;\&lt;br /&gt;
&amp;quot;push r13 \n\t&amp;quot;\&lt;br /&gt;
&amp;quot;push r14 \n\t&amp;quot;\&lt;br /&gt;
&amp;quot;push r15 \n\t&amp;quot;\&lt;br /&gt;
&amp;quot;push r16 \n\t&amp;quot;\&lt;br /&gt;
&amp;quot;push r17 \n\t&amp;quot; \&lt;br /&gt;
&amp;quot;push r18 \n\t&amp;quot;\&lt;br /&gt;
&amp;quot;push r19 \n\t&amp;quot;\&lt;br /&gt;
&amp;quot;push r20 \n\t&amp;quot; \&lt;br /&gt;
&amp;quot;push r21 \n\t&amp;quot;\&lt;br /&gt;
&amp;quot;push r22 \n\t&amp;quot;\&lt;br /&gt;
&amp;quot;push r23 \n\t&amp;quot;\&lt;br /&gt;
&amp;quot;push r24 \n\t&amp;quot;\&lt;br /&gt;
&amp;quot;push r25 \n\t&amp;quot;\&lt;br /&gt;
&amp;quot;push r26 \n\t&amp;quot;\&lt;br /&gt;
&amp;quot;push r27 \n\t&amp;quot;\&lt;br /&gt;
&amp;quot;push r28 \n\t&amp;quot;\&lt;br /&gt;
&amp;quot;push r29 \n\t&amp;quot;\&lt;br /&gt;
&amp;quot;push r30 \n\t&amp;quot;\&lt;br /&gt;
&amp;quot;push r31 \n\t&amp;quot;\&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
#define portRESTORE_REGISTERS() \&lt;br /&gt;
asm volatile (\&lt;br /&gt;
&amp;quot;pop r31 \n\t&amp;quot; \&lt;br /&gt;
&amp;quot;pop r30 \n\t&amp;quot;\&lt;br /&gt;
&amp;quot;pop r29 \n\t&amp;quot; \&lt;br /&gt;
&amp;quot;pop r28 \n\t&amp;quot;  \&lt;br /&gt;
&amp;quot;pop r27 \n\t&amp;quot; \&lt;br /&gt;
&amp;quot;pop r26 \n\t&amp;quot; \&lt;br /&gt;
&amp;quot;pop r25 \n\t&amp;quot;\&lt;br /&gt;
&amp;quot;pop r24 \n\t&amp;quot; \&lt;br /&gt;
&amp;quot;pop r23 \n\t&amp;quot; \&lt;br /&gt;
&amp;quot;pop r22 \n\t&amp;quot; \&lt;br /&gt;
&amp;quot;pop r21 \n\t&amp;quot; \&lt;br /&gt;
&amp;quot;pop r20 \n\t&amp;quot; \&lt;br /&gt;
&amp;quot;pop r19 \n\t&amp;quot; \&lt;br /&gt;
&amp;quot;pop r18 \n\t&amp;quot; \&lt;br /&gt;
&amp;quot;pop r17 \n\t&amp;quot; \&lt;br /&gt;
&amp;quot;pop r16 \n\t&amp;quot; \&lt;br /&gt;
&amp;quot;pop r15 \n\t&amp;quot; \&lt;br /&gt;
&amp;quot;pop r14 \n\t&amp;quot; \&lt;br /&gt;
&amp;quot;pop r13 \n\t&amp;quot; \&lt;br /&gt;
&amp;quot;pop r12 \n\t&amp;quot; \&lt;br /&gt;
&amp;quot;pop r11 \n\t&amp;quot; \&lt;br /&gt;
&amp;quot;pop r10 \n\t&amp;quot;\&lt;br /&gt;
&amp;quot;pop r9 \n\t&amp;quot; \&lt;br /&gt;
&amp;quot;pop r8 \n\t&amp;quot; \&lt;br /&gt;
&amp;quot;pop r7 \n\t&amp;quot; \&lt;br /&gt;
&amp;quot;pop r6 \n\t&amp;quot; \&lt;br /&gt;
&amp;quot;pop r5 \n\t&amp;quot; \&lt;br /&gt;
&amp;quot;pop r4 \n\t&amp;quot; \&lt;br /&gt;
&amp;quot;pop r3 \n\t&amp;quot; \&lt;br /&gt;
&amp;quot;pop r2 \n\t&amp;quot; \&lt;br /&gt;
&amp;quot;pop r1 \n\t&amp;quot; \&lt;br /&gt;
&amp;quot;pop r0 \n\t&amp;quot; \&lt;br /&gt;
&amp;quot;out __SREG__, r0 \n\t&amp;quot;\ &lt;br /&gt;
&amp;quot;pop r0 \n\t&amp;quot; \&lt;br /&gt;
);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Coder le tableau des structures des processus====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
    uint16_t adresseDepart;  //adresse de la fonction de départ &lt;br /&gt;
    uint16_t adressePile;       //adresse de la pile d'exécution&lt;br /&gt;
    bool etat;          //état du processus (1 ou 0)&lt;br /&gt;
} Process;&lt;br /&gt;
&lt;br /&gt;
Process table_process[MAXPROCESS];&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Coder la fonction d'initialisation de la pile d'un processus====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line&amp;gt;&lt;br /&gt;
A REMPLIR&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Taches ∞ pour faire clignoter deux leds à 2 fréquences premières entre elle====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line&amp;gt;&lt;br /&gt;
A REMPLIR&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
[[Fichier:Ordonnanceur cligno led.mp4|vignette|thumb|center|700px|Clignotement des leds à des fréquences premières entre elle avec l'ordonnanceur]]&lt;br /&gt;
&lt;br /&gt;
====Lancement des deux tâches en parallèle grâce à l'ordonnanceur à tourniquet====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line&amp;gt;&lt;br /&gt;
A REMPLIR&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Adjadjaa</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-5&amp;diff=6293</id>
		<title>SE4Binome2024-5</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2024-5&amp;diff=6293"/>
		<updated>2024-10-15T13:42:48Z</updated>

		<summary type="html">&lt;p&gt;Adjadjaa : /* Allumage de LEDS sur Programmateur AVR */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;git : https://gitea.plil.fr/ktouron/se4-djadja-touron_pico.git&lt;br /&gt;
&lt;br /&gt;
Carte fille clavier &amp;quot;matrice de touches&amp;quot;&lt;br /&gt;
=Hardware=&lt;br /&gt;
&lt;br /&gt;
== Carte Shield ==&lt;br /&gt;
[[Fichier:Carte Recto non soudé.jpg|vignette|left|thumb|350px|Recto de la carte avant soudage des composants]]&lt;br /&gt;
[[Fichier:Verso non solder.jpeg.jpg|vignette|thumb|right|350px|Verso de la carte avant soudage des composants]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Carte Shield après soudure des composants ==&lt;br /&gt;
[[Fichier:Carde shield soudé.jpg|vignette|thumb|center|400px|Photo de la carte avec les composants soudés]]&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Carte Fille ==&lt;br /&gt;
&lt;br /&gt;
== Carte Fille après soudure des composants ==&lt;br /&gt;
&lt;br /&gt;
= Software =&lt;br /&gt;
== Carte Shield ==&lt;br /&gt;
=== Allumage de LEDS sur Programmateur AVR ===&lt;br /&gt;
Avant de programmer directement sur le shield, nous avons allumé des LED pour tester la carte. Nous avons directement utilisé le code exemple fourni par l'IDE arduino en adaptant simplement les pins correspondant aux leds.&lt;br /&gt;
&lt;br /&gt;
https://gitea.plil.fr/ktouron/se4-djadja-touron_pico/src/branch/main/PicoShield/Programmation/Blink&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Vid_test_carte_mp4.mp4|vignette|thumb|center|700px|Vidéo de Test des leds]]&lt;br /&gt;
&lt;br /&gt;
=== Test de lecture de la carte SD ===&lt;br /&gt;
Avant de programmer directement sur le shield, nous avons tester si la carte SD était bien détecté et lu&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line&amp;gt;&lt;br /&gt;
#include &amp;lt;SPI.h&amp;gt;&lt;br /&gt;
#include &amp;lt;SD.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Sd2Card card;&lt;br /&gt;
SdVolume volume;&lt;br /&gt;
SdFile root;&lt;br /&gt;
&lt;br /&gt;
const int chipSelect = 10;&lt;br /&gt;
&lt;br /&gt;
void setup() {&lt;br /&gt;
  // Open serial communications and wait for port to open:&lt;br /&gt;
  Serial.begin(9600);&lt;br /&gt;
  while (!Serial) {&lt;br /&gt;
    ; // wait for serial port to connect. Needed for native USB port only&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
  Serial.print(&amp;quot;\nInitializing SD card...&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
  // we'll use the initialization code from the utility libraries&lt;br /&gt;
  // since we're just testing if the card is working!&lt;br /&gt;
  if (!card.init(SPI_HALF_SPEED, chipSelect)) {&lt;br /&gt;
    Serial.println(&amp;quot;initialization failed. Things to check:&amp;quot;);&lt;br /&gt;
    Serial.println(&amp;quot;* is a card inserted?&amp;quot;);&lt;br /&gt;
    Serial.println(&amp;quot;* is your wiring correct?&amp;quot;);&lt;br /&gt;
    Serial.println(&amp;quot;* did you change the chipSelect pin to match your shield or module?&amp;quot;);&lt;br /&gt;
    while (1);&lt;br /&gt;
  } else {&lt;br /&gt;
    Serial.println(&amp;quot;Wiring is correct and a card is present.&amp;quot;);&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  // print the type of card&lt;br /&gt;
  Serial.println();&lt;br /&gt;
  Serial.print(&amp;quot;Card type:         &amp;quot;);&lt;br /&gt;
  switch (card.type()) {&lt;br /&gt;
    case SD_CARD_TYPE_SD1:&lt;br /&gt;
      Serial.println(&amp;quot;SD1&amp;quot;);&lt;br /&gt;
      break;&lt;br /&gt;
    case SD_CARD_TYPE_SD2:&lt;br /&gt;
      Serial.println(&amp;quot;SD2&amp;quot;);&lt;br /&gt;
      break;&lt;br /&gt;
    case SD_CARD_TYPE_SDHC:&lt;br /&gt;
      Serial.println(&amp;quot;SDHC&amp;quot;);&lt;br /&gt;
      break;&lt;br /&gt;
    default:&lt;br /&gt;
      Serial.println(&amp;quot;Unknown&amp;quot;);&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  // Now we will try to open the 'volume'/'partition' - it should be FAT16 or FAT32&lt;br /&gt;
  if (!volume.init(card)) {&lt;br /&gt;
    Serial.println(&amp;quot;Could not find FAT16/FAT32 partition.\nMake sure you've formatted the card&amp;quot;);&lt;br /&gt;
    while (1);&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  Serial.print(&amp;quot;Clusters:          &amp;quot;);&lt;br /&gt;
  Serial.println(volume.clusterCount());&lt;br /&gt;
  Serial.print(&amp;quot;Blocks x Cluster:  &amp;quot;);&lt;br /&gt;
  Serial.println(volume.blocksPerCluster());&lt;br /&gt;
&lt;br /&gt;
  Serial.print(&amp;quot;Total Blocks:      &amp;quot;);&lt;br /&gt;
  Serial.println(volume.blocksPerCluster() * volume.clusterCount());&lt;br /&gt;
  Serial.println();&lt;br /&gt;
&lt;br /&gt;
  // print the type and size of the first FAT-type volume&lt;br /&gt;
  uint32_t volumesize;&lt;br /&gt;
  Serial.print(&amp;quot;Volume type is:    FAT&amp;quot;);&lt;br /&gt;
  Serial.println(volume.fatType(), DEC);&lt;br /&gt;
&lt;br /&gt;
  volumesize = volume.blocksPerCluster();    // clusters are collections of blocks&lt;br /&gt;
  volumesize *= volume.clusterCount();       // we'll have a lot of clusters&lt;br /&gt;
  volumesize /= 2;                           // SD card blocks are always 512 bytes (2 blocks are 1KB)&lt;br /&gt;
  Serial.print(&amp;quot;Volume size (Kb):  &amp;quot;);&lt;br /&gt;
  Serial.println(volumesize);&lt;br /&gt;
  Serial.print(&amp;quot;Volume size (Mb):  &amp;quot;);&lt;br /&gt;
  volumesize /= 1024;&lt;br /&gt;
  Serial.println(volumesize);&lt;br /&gt;
  Serial.print(&amp;quot;Volume size (Gb):  &amp;quot;);&lt;br /&gt;
  Serial.println((float)volumesize / 1024.0);&lt;br /&gt;
&lt;br /&gt;
  Serial.println(&amp;quot;\nFiles found on the card (name, date and size in bytes): &amp;quot;);&lt;br /&gt;
  root.openRoot(volume);&lt;br /&gt;
&lt;br /&gt;
  // list all files in the card with date and size&lt;br /&gt;
  root.ls(LS_R | LS_DATE | LS_SIZE);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void loop(void) {&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
[[Fichier:Resultat SD.jpg|vignette|thumb|center|700px|Carte SD bien détéctée]]&lt;br /&gt;
&lt;br /&gt;
=== Ordonnanceur===&lt;br /&gt;
==== Allumer la LED broche PB5 avec Timer1 ISR ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line&amp;gt;&lt;br /&gt;
#define CTC1            WGM12           // Meilleur nom pour le bit&lt;br /&gt;
&lt;br /&gt;
#define PERIODE         20&lt;br /&gt;
&lt;br /&gt;
void init_minuteur(int diviseur,long periode){&lt;br /&gt;
  TCCR1A=0;               // Le mode choisi n'utilise pas ce registre&lt;br /&gt;
  TCCR1B=(1&amp;lt;&amp;lt;CTC1);       // Réinitialisation du minuteur sur expiration&lt;br /&gt;
  switch(diviseur){&lt;br /&gt;
    case    8: TCCR1B |= (1&amp;lt;&amp;lt;CS11); break;&lt;br /&gt;
    case   64: TCCR1B |= (1&amp;lt;&amp;lt;CS11 | 11&amp;lt;&amp;lt;CS10); break;&lt;br /&gt;
    case  256: TCCR1B |= (1&amp;lt;&amp;lt;CS12); break;&lt;br /&gt;
    case 1024: TCCR1B |= (1&amp;lt;&amp;lt;CS12 | 1&amp;lt;&amp;lt;CS10); break;&lt;br /&gt;
    }&lt;br /&gt;
  // Un cycle prend 1/F_CPU secondes.&lt;br /&gt;
  // Un pas de compteur prend diviseur/F_CPU secondes.&lt;br /&gt;
  // Pour une periode en millisecondes, il faut (periode/1000)/(diviseur/F_CPU) pas&lt;br /&gt;
  // soit (periode*F_CPU)/(1000*diviseur)&lt;br /&gt;
  OCR1A=F_CPU/1000*periode/diviseur;  // Calcul du pas&lt;br /&gt;
  TCNT1=0;                // Compteur initialisé&lt;br /&gt;
  TIMSK1=(1&amp;lt;&amp;lt;OCIE1A);     // Comparaison du compteur avec OCR1A&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
ISR(TIMER1_COMPA_vect/*, ISR_NAKED*/)    // Procédure d'interruption&lt;br /&gt;
{&lt;br /&gt;
  PORTB ^= (1 &amp;lt;&amp;lt; PB5); &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int main(void){&lt;br /&gt;
  DDRB |= (1 &amp;lt;&amp;lt; PB5);                       &lt;br /&gt;
  init_minuteur(256,PERIODE);&lt;br /&gt;
  sei();&lt;br /&gt;
  while(1);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Macros de sauvegarde et restauration des registres====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line&amp;gt;&lt;br /&gt;
#define portSAVE_REGISTERS() \&lt;br /&gt;
asm volatile ( \&lt;br /&gt;
&amp;quot;push r0 \n\t&amp;quot; \&lt;br /&gt;
&amp;quot;in r0, __SREG__ \n\t&amp;quot;\&lt;br /&gt;
&amp;quot;cli \n\t&amp;quot; \&lt;br /&gt;
&amp;quot;push r0 \n\t&amp;quot;\ &lt;br /&gt;
&amp;quot;push r1 \n\t&amp;quot; \&lt;br /&gt;
&amp;quot;clr r1 \n\t&amp;quot; \&lt;br /&gt;
&amp;quot;push r2 \n\t&amp;quot;\&lt;br /&gt;
&amp;quot;push r3 \n\t&amp;quot;\&lt;br /&gt;
&amp;quot;push r4 \n\t&amp;quot;\&lt;br /&gt;
&amp;quot;push r5 \n\t&amp;quot;\&lt;br /&gt;
&amp;quot;push r6 \n\t&amp;quot;\&lt;br /&gt;
&amp;quot;push r7 \n\t&amp;quot;\&lt;br /&gt;
&amp;quot;push r8 \n\t&amp;quot;\&lt;br /&gt;
&amp;quot;push r9 \n\t&amp;quot;\&lt;br /&gt;
&amp;quot;push r10 \n\t&amp;quot;\&lt;br /&gt;
&amp;quot;push r11 \n\t&amp;quot;\&lt;br /&gt;
&amp;quot;push r12 \n\t&amp;quot;\&lt;br /&gt;
&amp;quot;push r13 \n\t&amp;quot;\&lt;br /&gt;
&amp;quot;push r14 \n\t&amp;quot;\&lt;br /&gt;
&amp;quot;push r15 \n\t&amp;quot;\&lt;br /&gt;
&amp;quot;push r16 \n\t&amp;quot;\&lt;br /&gt;
&amp;quot;push r17 \n\t&amp;quot; \&lt;br /&gt;
&amp;quot;push r18 \n\t&amp;quot;\&lt;br /&gt;
&amp;quot;push r19 \n\t&amp;quot;\&lt;br /&gt;
&amp;quot;push r20 \n\t&amp;quot; \&lt;br /&gt;
&amp;quot;push r21 \n\t&amp;quot;\&lt;br /&gt;
&amp;quot;push r22 \n\t&amp;quot;\&lt;br /&gt;
&amp;quot;push r23 \n\t&amp;quot;\&lt;br /&gt;
&amp;quot;push r24 \n\t&amp;quot;\&lt;br /&gt;
&amp;quot;push r25 \n\t&amp;quot;\&lt;br /&gt;
&amp;quot;push r26 \n\t&amp;quot;\&lt;br /&gt;
&amp;quot;push r27 \n\t&amp;quot;\&lt;br /&gt;
&amp;quot;push r28 \n\t&amp;quot;\&lt;br /&gt;
&amp;quot;push r29 \n\t&amp;quot;\&lt;br /&gt;
&amp;quot;push r30 \n\t&amp;quot;\&lt;br /&gt;
&amp;quot;push r31 \n\t&amp;quot;\&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
#define portRESTORE_REGISTERS() \&lt;br /&gt;
asm volatile (\&lt;br /&gt;
&amp;quot;pop r31 \n\t&amp;quot; \&lt;br /&gt;
&amp;quot;pop r30 \n\t&amp;quot;\&lt;br /&gt;
&amp;quot;pop r29 \n\t&amp;quot; \&lt;br /&gt;
&amp;quot;pop r28 \n\t&amp;quot;  \&lt;br /&gt;
&amp;quot;pop r27 \n\t&amp;quot; \&lt;br /&gt;
&amp;quot;pop r26 \n\t&amp;quot; \&lt;br /&gt;
&amp;quot;pop r25 \n\t&amp;quot;\&lt;br /&gt;
&amp;quot;pop r24 \n\t&amp;quot; \&lt;br /&gt;
&amp;quot;pop r23 \n\t&amp;quot; \&lt;br /&gt;
&amp;quot;pop r22 \n\t&amp;quot; \&lt;br /&gt;
&amp;quot;pop r21 \n\t&amp;quot; \&lt;br /&gt;
&amp;quot;pop r20 \n\t&amp;quot; \&lt;br /&gt;
&amp;quot;pop r19 \n\t&amp;quot; \&lt;br /&gt;
&amp;quot;pop r18 \n\t&amp;quot; \&lt;br /&gt;
&amp;quot;pop r17 \n\t&amp;quot; \&lt;br /&gt;
&amp;quot;pop r16 \n\t&amp;quot; \&lt;br /&gt;
&amp;quot;pop r15 \n\t&amp;quot; \&lt;br /&gt;
&amp;quot;pop r14 \n\t&amp;quot; \&lt;br /&gt;
&amp;quot;pop r13 \n\t&amp;quot; \&lt;br /&gt;
&amp;quot;pop r12 \n\t&amp;quot; \&lt;br /&gt;
&amp;quot;pop r11 \n\t&amp;quot; \&lt;br /&gt;
&amp;quot;pop r10 \n\t&amp;quot;\&lt;br /&gt;
&amp;quot;pop r9 \n\t&amp;quot; \&lt;br /&gt;
&amp;quot;pop r8 \n\t&amp;quot; \&lt;br /&gt;
&amp;quot;pop r7 \n\t&amp;quot; \&lt;br /&gt;
&amp;quot;pop r6 \n\t&amp;quot; \&lt;br /&gt;
&amp;quot;pop r5 \n\t&amp;quot; \&lt;br /&gt;
&amp;quot;pop r4 \n\t&amp;quot; \&lt;br /&gt;
&amp;quot;pop r3 \n\t&amp;quot; \&lt;br /&gt;
&amp;quot;pop r2 \n\t&amp;quot; \&lt;br /&gt;
&amp;quot;pop r1 \n\t&amp;quot; \&lt;br /&gt;
&amp;quot;pop r0 \n\t&amp;quot; \&lt;br /&gt;
&amp;quot;out __SREG__, r0 \n\t&amp;quot;\ &lt;br /&gt;
&amp;quot;pop r0 \n\t&amp;quot; \&lt;br /&gt;
);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Coder le tableau des structures des processus====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
    uint16_t adresseDepart;  //adresse de la fonction de départ &lt;br /&gt;
    uint16_t adressePile;       //adresse de la pile d'exécution&lt;br /&gt;
    bool etat;          //état du processus (1 ou 0)&lt;br /&gt;
} Process;&lt;br /&gt;
&lt;br /&gt;
Process table_process[MAXPROCESS];&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Coder la fonction d'initialisation de la pile d'un processus====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line&amp;gt;&lt;br /&gt;
A REMPLIR&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Taches ∞ pour faire clignoter deux leds à 2 fréquences premières entre elle====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line&amp;gt;&lt;br /&gt;
A REMPLIR&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
[[Fichier:Ordonnanceur cligno led.mp4|vignette|thumb|center|700px|Clignotement des leds à des fréquences premières entre elle avec l'ordonnanceur]]&lt;br /&gt;
&lt;br /&gt;
====Lancement des deux tâches en parallèle grâce à l'ordonnanceur à tourniquet====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line&amp;gt;&lt;br /&gt;
A REMPLIR&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Adjadjaa</name></author>
	</entry>
</feed>