Ajout de l'algo de découverte

This commit is contained in:
2025-03-07 16:11:28 +01:00
parent fad0f40e9f
commit 06932777cd
2 changed files with 81 additions and 1 deletions

82
Doc.md
View File

@@ -23,11 +23,91 @@ Voici une liste des compromis qui sont autorisés pour faciliter le développeme
- On peut partir du principe que toutes les matrices seront ajoutées dans la même orientation (Ca nous permet de "hard coder" les directions cardinales pour faciliter le routing des messages)
- On peut partir du principe que la carte master est en bas à gauche de la matrice tant toutes les cartes ont le même firmware (Si on branche une autre carte elle doit aussi pouvoir être master, juste elle ne prendra pas en compte les matrices qui ne sont pas dans sa diagonale directe)
- On peut partir du principe que la matrice de matrice sera toujours rectangulaire et que on ajoute des colonnes ou des lignes entières. (Donc si on ajoute une matrice seule dans un bord et que ca ne fait plus un rectangle ca ne marchera pas)
- On aura toujours un rectangle plein, pas de trous dans la matrice
## Principe de fonctionnement
Quand on branche le coin de la matrice à notre linux, one élection très simple se fait pour determiner quelle carte est maitre et qui sont les esclaves.
![Diagramme 1](./Media/MasterElection.png "Election par le port USB")
![Fig 1](./Media/MasterElection.png "Election par le port USB")
Par défaut à la mise sous tension, une carte est toujours esclave. Cependant, si la carte detecte que elle est branchée (soit par detection USB soit par un paquet UART envoyé par le driver c'est encore à discuter) elle devient maitre et va pouvoir commencer le processus de découverte de ses environs.
### Decouverte automatique
#### Initialisation
Comme la carte maitre n'a techniquement aucune idée de ses entourages. Elle va créer un grand tableau de possibles et tenter de le remplir avec l'architecture réelle.
![Fig 2](./Media/GridStart.png "Grille maitre de départ")
Pour plus facilement expliquer le fonctionnement de l'algorythme on va prendre un exemple de matrice réelle rectangulaire
![Fig 3](./Media/GridReal.png "Veritable grille dans le monde réel")
On peut voir que on a une grille réelle de largeur 4 et de hauteur 3. Cela nous ferait donc 16x16x4x3 leds (4096 leds) mais evidemment l'algorythme est censé fonctionner avec une grille plus petite,plus grande, et de "facteur de forme" (ratio largeur-longeur) différent.
On peut voir que on a des connections en UART qui partent du haut et de la droite de notre carte maitre et toutes les autres cartes sont interconnectées avec des lignes UART également.
#### Découverte des côtés
Pour découvrir nos environs on pourrait penser à pleins de methodes. Comme on sait que notre matrice est rectangulaire et que elle est en principe pleine on va pouvoir utiliser une techique assez simple.
La carte master va envoyer un paquet special en haut et à droite. Ce paquet spécial va être reconnu par les cartes slaves.
![Fig 4](./Media/SlaveSideDiscovery.png "Algo simplifié de l'esclave pendant la détection des côtés")
Le but est que chaque esclave qui recoit le paquet spécial incrémente une valeur dedans et le renvoie à l'opposé de la ou elle l'a recu (Ex elle recoit le paquet depuis le bas, elle l'envoie en haut)
Si elle ne peut pas l'envoyer car il n'y a plus de voisin dans la direction. Alors c'est que on est arrivé à la fin de la ligne et donc l'esclave envoie une réponse au master avec le chiffre incrémenté qui représente le nombre de matrices connectées dans la ligne.
Comme on a pas encore de système d'adresse, il faut aussi prévoir un routage simple qui dit que quand un slave recoit un message pour le master mais que il n'a pas de position, alors il relaie simplement le message à l'opposé.
De cette facon, en principe, le master envoie un paquet à gauche et un paquet en haut et après un court délai il recoit une réponse qui lui permet de se faire une idée des dimensions de la matrice réelle.
![Fig 5](./Media/GridSideDiscovered.png "Recherche des côtés")
A part de la on peut assez facilement déduire de la véritable taille de la grille et on est donc prêt à assigner une position à toutes les cartes de la grille.
#### Assignement des positions.
##### Pourquoi faire ?
![Meme 1](./Media/PourquoiFaire.png "Omar Sy, pourquoi faire ?")
Maintenant que l'on a une idée de à quoi ressemble notre grille il va falloir assigner une position à toutes nos cartes. Pourquoi? Et bien par ce que pour la suite nous allons devoir trouver un moyen de router les instructions du master à toutes les cartes de la grille et pour cela il faut que chaque carte aie une notion de sa position dans le systeme.
Chaque carte va avoir une position X;Y qui représente sa position dans le tableau interne au master mais aussi à sa position physique dans l'espace. Cela permet de très facilement savoir ou envoyer nimporte quel information de pixel.
Imaginons notre grille de 16x16x4x3 pixels. Cela représente un écran de 64:48px Si on veut par exemple toucher au pixel 34:12 on sait que il faut l'envoyer à la carte qui se trouve en (34//16):(12//16) => 2:0. C'est super facile. Pour ce qui est des avantages au niveau routage on en parle un peu plus bas.
##### Comment faire ?
Comme on sait quelles sont les dimensions des côtés de notre matrice, on peut infèrer de à quoi ressemble toute la matrice et on peut la représenter dans un tableau de la sorte dans notre master :
![Fig 6](./Media/GridFinal.png "Etat de la grille après reconnaissance")
Sauf que pour le moment seule le master connait les positions des différentes cartes. Il va donc falloir venir dire à chaque carte quelle position elle occupe dans la matrice.
Pour ca on va y aller étape par étape ligne par ligne et colonne par colonne.
Par défaut au démarrage chaque carte est un esclave et n'a pas de position. Ensuite quand elle recoit un numéro, à moins de recevoir un paquet d'invalidation (Voir plus bas), elle le garde jusqu'à ce que elle soit éteinte.
Pour assigner les positions, le maitre va donc envoyer un paquet pour chaque carte selon le protocole de communication que l'on va voir un peu plus bas.
![Fig 7](./Media/SlaveAssignement.png "Assignement de la position")
Quand une carte recoit un paquet d'assignation, elle peut y lire l'addresse de destination. Si la carte n'a pas encore de position assignée, alors c'est que la position lui est destinée et elle peut donc prendre comme position celle du paquet. Quand elle a pris la position, elle envoie un paquet au master pour confirmer et que le master puisse savoir quand la grille est prête. Elle peut l'envoyer facilement car le Master est toujours en 0,0
Si une carte recoit un paquet qui est pour une autre carte, alors elle va l'envoyer en direction de cette dernière. Comment elle fait pour l'envoyer dans la bonne direction, on en parle aussi juste après quand on parlera du protocole de communication en detail.
##### Côté master
Du côte du master, c'est assez simple, on va envoyer un paquet d'assignation pour chaque carte en envoyer les paquets sur les deux sorties et en principe, comme les cartes choppent leurs addresses au fur et à mesure, les paquets pourront aller de plus en plus loin dans la grille. Le master n'a plus qu'à attendre les réponses de toutes les cartes pour continuer.
Si le master ne recoit pas tous les ACK au bout d'un certain temps, alors il renvoie un paquet d'assignement aux cartes qui n'ont pas répnondu. Si ca ne fonctionne pas plusieurs fois alors il invalide toute la matrice (Voir plus bas quand on parle de l'ajout d'une carte dans la grille) et il recommence le processus depuis le début en allant découvrir les côtés.
##### Resultat
En principe, après toutes ces étapes, le master a une grille interne qui repertorie la position de toutes les cartes et toutes les cartes ont une position. Le master est donc prêt à envoyer des paquets à nimporte quelle carte de la grille en fonction de son addresse et chaque carte est capable de répondre. On a donc un écran initialisé.

BIN
Media/PourquoiFaire.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 530 KiB