Didactitiel mémoire
Mes connaissances viennent des niveaux mis en partage par
Aspherex ainsi que des didacticiels vidéos de
Comphermc. Voici les liens vers les videos:
LBP2-Torials 20: Feedback Loops (part 1)LBP2-Torials 20: Feedback Loops (part 2)Ce didactitiel s'appuie sur mon niveau
Curseur*10. Je vous conseille de le finir car je donne la puce mémoire et les mémoires à nœud de circuit de chaque bits en fin de niveau.
Vous pouvez vous aider du forum pour y parvenir.Comme vous le savez, en mode joué, il n'existe pas de mémoire comme on nous le propose par exemple lors de l'enregistrement en mode création pour les sackbots.
Pour arriver à le faire, il existe plusieurs moyens, celui que je vais vous expliquer n'est pas le plus simple mais c'est celui qui permet, je pense, de mémoriser le plus longtemps possible car tout est fait grâce à des portes logiques(ou gates). Dans mon niveau, le temps mémorisé est d'environ 4 minutes.
Les bases:Il existe plusieurs gates or, and, xor ... mais toutes ne permettent pas d'être utilisées en tant que mémoire.
- La mémoire à nœud de circuit: Vous allez me dire ca commence bien je ne capte rien.
En fait, en mode création lancé (avec le sigle Play en haut à droite), si vous mettez une pile puis un nœud de circuit derrière et que vous reprenez la sortie du nœud sur l'entrée, et bien vous avez fait une mémoire.
Certes cette mémoire n'a pas l'air très utile puisqu'une pile fait la même chose et qu'il est impossible de changer la valeur de cette mémoire. En fait par ce moyen, vous avez la possibilité de faire des batteries de n'importe quelle valeur et bien plus précise que celle fournie dans LBP (qui ne varie que de 1%). Je reviendrai sur ce point un peu plus tard.
- La mémoire "gate or avec retour sur une entrée" est celle qui permet d'enregistrer une valeur durant un jeu.
Rappel En mode normal, si vous avez une batterie de 10% et une autre de 20% reliées à une gate "or", la sortie sera celle de la batterie la plus puissante, dans notre cas 20%. |
Maintenant, si vous reliez la sortie à une des entrées, vous pourrez enregistrer la valeur de votre entrée. Celle-ci restera tant que vous ne mettez pas un signal plus fort en entrée.
Vous me direz c'est bien beau, mais si je veux mémoriser une valeur pendant un temps et re-stocker une autre par la suite, comment dois-je m'y prendre ? Et bien c'est plus simple qu'il n'y parait. Soit vous ouvrez la boucle de retour (avec une gate and par exemple) ou soit en la mettant dans une puce que vous désactivez (par l'entrée du bas) alors la valeur est perdue.
Il faut donc comprendre que c'est aussi à double tranchant, car parfois pour éviter d'avoir trop de puces actives en même temps, il est préférable de les désactiver.
Qui dit désactiver une puce avec mémoires dit perte de données même pour celles faites avec des nœuds de circuit.
- La mémoire combo "détecteur de clé magnétique"/ "clé magnétique" : C'est la dernière méthode et la plus compliquée. En fait en plus d'offrir une mémoire plus flexible permet le calcul sur celle-ci. Le signal de la clé magnétique peut alors être traité par d'autres puces grâce à des detecteurs de clé magnétique (C'est grâce à cette méthode que le cube 99 fonctionne dans mon niveau.)
Rappel: tout détecteur de clé magnétique se trouvant dans une puce est incapable de détecter une clé magnétique se trouvant dans cette même puce.
C'est pour cette raison que la clé doit se trouver en dehors de la puce.
Toutes les actions de calcul doivent être des impulsions, c'est à dire qu'elles ne sont activées qu'une seule fois dans la puce. Si ce n'était pas le cas, le calcul serait impossible car dépendrait du temps d'activation. C’est pour cette raison qu’il y a un compteur à 1 avec sa sortie vers son reset. J’ai utilisé une mémoire à nœud de circuit à la place d’une batterie. Une batterie peut faire l'affaire si l’on ne tient pas compte des erreurs de calcul. Ici le bouton vert permet d’ajouter la valeur d’une batterie, le bouton rouge de retrancher la valeur d’une autre.
Enregistrement:Pour faire des enregistrements, il suffit d'utiliser le principe des mémoires mais en les activant les unes après les autres. Et c'est là que cela devient dur, car pour enregistrer, il faut beaucoup de "gates or avec retour sur une entrée". Pour environ 26 secondes d'enregistrement, il m'en a fallu 396.
J'ai donc mis 99 "gates or avec retour sur une entrée" dans une puce avec un sélecteur à 100 sorties. Une sortie du sélecteur (la 100e) étant vide car elle permet de laisser la mémoire au repos.
Grâce à deux gates "and" avant et après la "gate or avec retour sur une entrée", j'arrive à isoler chaque mémoire.
Le changement de sortie du sélecteur est donné par les impulsions d'une gate "xor" avec retour sur son entrée, ce qui permet d'avoir des impulsions très rapide. La 99e sortie et une impulsion (donnée par la gate xor) active la mémoire suivante. Cette mémoire revient ensuite au repos à la 100e sortie dû à l'impulsion.
Voici une puce allégée par rapport à de la puce un peu plus haut avec seulement 9 mémoires à la place des 99.
Compression/décompression:Alors là accrochez vous à vos bretelles. Ca va être du lourd très lourd... et oui, je vais vous parler de:
BinaireJe rappelle juste quelques faits avant de continuer :
Ce qu’il faut savoir en binaire, si on multiplie la valeur par deux, on décale alors tous les bits vers la gauche. Exemple : 1111 0000 1010 1100 x 2 = 1 1110 0001 0101 1000. Comme il y a un nombre max de bits dans tout système, j’ai donc multiplié beaucoup de fois par 2. A chaque multiplication, chaque dépassement me donnait alors le bit et le nombre de fois multiplié, sa position. Exemple : avec 1011 1001 (Je limite à un nombre max de 8 bits afin de comprendre le fonctionnement)
| x2 | reste | Bit 9 | Nombre de multiplications | 1011 1001 | 1 0111 0010 | 0111 0010 | 1 | 1 | 0111 0010 | 0 1110 0100 | 1110 0100 | 0 | 2 | 1110 0100 | 1 1100 1000 | 1100 1000 | 1 | 3 | 1100 1000 | 1 1001 0000 | 1001 0000 | 1 | 4 | 1001 0000 | 1 0010 0000 | 0010 0000 | 1 | 5 | 0010 0000 | 0 0100 0000 | 0100 0000 | 0 | 6 | 0100 0000 | 0 1000 0000 | 1000 0000 | 0 | 7 | 1000 0000 | 1 0000 0000 | 0000 0000 | 1 | 8 | En lisant la colonne Bit9 de haut en bas, je retrouve bien ma valeur de départ |
Pour en revenir au sujet, il faut donc trouver le moyen de multiplier par 2 le signal. Si l’on additionne le signal par lui-même, cela revient à la même chose. Pour se faire, il faut utiliser les combinateurs de signaux.
Ceux qui se sont déjà amusé à ouvrir des circuits, où l'on additionnait deux signaux analogiques, doivent connaître ce petit circuit.
Il a la particularité de très bien fonctionner si le total est inférieur ou égal à 100%. Qu'en est-il si ce n'est pas le cas?
Prenons plusieurs exemples :
Entrée 1 | Entrée 2 | Not Entrée 1 | (Not Entrée 1)- Entrée 2 | Not((Not Entrée 1)- Entrée 2) | Total par calcul | Statut |
10% | 20% | 90% | 70% | 30% | 30% | OK |
60% | 30% | 40% | 10% | 90% | 90% | OK |
30% | 60% | 70% | 10% | 90% | 90% | OK |
20% | 80% | 80% | 0% | 100% | 100% | OK |
40% | 70% | 60% | -10% | 90% | 110% | non OK |
80% | 40% | 20% | -20% | 80% | 120% | non OK |
40% | 80% | 60% | -20% | 80% | 120% | non OK |
Ce que l’on remarque, c’est que dès que la sortie «
(Not Entrée 1)- Entrée 2» est négative, le résultat n’est pas juste car le total des 2 est supérieur à 100%.
Il suffit alors de vérifier le signe de cette sortie. Si elle est positive, mettre une gate not à la suite donnera le bon résultat. Si elle est négative, on aura le bon résultat (signe mis à part)
Il s'agit en fait de deux circuits faisant exactement la même chose. Dans le circuit du bas, j'ai utilisé le circuit d'
Aspherex pour voir si le signal était supérieur à zéro au lieu d’un séquenceur avec "action d'entrée: Position" et une batterie de à 100%. LBP préfére cette solution: moins de thermo et plus rapide à excécuter.
C'est en faisant mumuse avec ce circuit, en les mettant les uns après les autres, que j'ai découvert que le signal analogique a 24 bits. Cela veut donc dire pouvant avoir les valeurs de 0 à 16777215 (1111 1111 1111 1111 1111 1111 en binaire) tout en restant super précis.
J'ai alors fabriqué au moyen de mémoires à nœud de circuit, toutes les batteries correspondant à chaque bit. Grâce à une batterie sur 0% et de 2 chronos (grande valeur max > 2000s) l’un derrière l’autre (le dernier étant sur vitesse), j'avais un signal analogique qui amplifiait de manière très très lente. Pour cela je modifiais la valeur initiale du premier chrono sur 0.1s et attendait que la lumière du bit correspondant s’allumait et le refaisait revenir à 0 le temps de créer la boucle sur le nœud de circuit.
La puce longue est composée de 24 puces montrées plus haut en image avec pour chaqu'une, la sortie "Reste" sur l'entrée de la puce suivante et les sorties Bit9 raccordées à des lumières paramétrées sur variateur. Une fois que j'ai eu mes 24 mémoires à nœud de circuit, j'ai pu faire les circuits de compression.
Exemple théorique de la décomposition du signal du niveau Curseur*10Afin de coder et décoder le signal, il faut mettre en place une procédure incluant toutes les informations que l’on a besoin de sauvegarder. La place dans la donnée peut être aussi importante.
Dans le cas du niveau, les plus importantes sont :
- l’étage où se trouve le curseur puisque suivant son étage, je décoderai ou non le reste pour savoir sa position sur le jeu.
- l’état du curseur, c'est-à-dire s’il appuie sur un bouton permettant de passer un nouvel étage.
Les moins importantes sont
- les positions suivant x et y du curseur. Car elles ne sont pas forcément utiles si le curseur actif se trouve dans un étage bien plus haut ou plus bas que celui qui a été enregistré. Je ne vais pas tout décoder alors que le curseur n’est pas visible.
Ceci la procédure mise en place dans le cas du niveau. (X correspondant à un bit)
XXXX | XXXX | XXXX XXXX XXXX XXXX |
Etage | Etat du curseur | Position suivant X et Y du curseur |
Reprenons tout cela.- Etage : a la valeur 0 en binaire 0000 lorsque rien n’est enregistré. Dès qu’il y a enregistrement, la valeur binaire de l’étage lui est donnée. (0001=1e, 0010=2e, 0011=3e,… , 1111=15e) le 16e étage n’existant pas puisque c’est la fin du niveau.
- Etat du curseur : il s’agit en fait uniquement des interrupteurs et cubes présents dans le jeu qui ont été appuyés.
Par exemple : - étage 6 le bouton est appuyé
- étage 8 le bouton est appuyé
- étage 10 le cube 99 est appuyé
- étage 15 le bouton de droite est appuyé
- étage 15 le bouton du milieu est appuyé
- étage 15 le bouton du gauche est appuyé
Position suivant X et Y du curseur : C'est par le moyen de la compression avec pertes que j'ai pu mettre ces deux données dans les 16 bits restants. Je parle bien de compression avec pertes car la précision de position des curseurs n'est plus aussi bonne, mais heureusement cela n’est pas visible.Avec des clés magnétiques sur proximité, j’ai deux données analogiques correspondant à la position X et Y du curseur sur la puce qui bouge. Les deux suiveurs bloqués sur un axe suivent la clé magnétique rouge:
Voici le principe, si j’ai un signal analogique et que je garde uniquement les bits de poids le plus fort, j’ai donc un système moins précis mais utilisant moins de bits.
Axe | X | Y |
Donnée init. | XXXX XXXX XXXX XXXX XXXX XXXX | YYYY YYYY YYYY YYYY YYYY YYYY |
Donnée gardée | X24X23X22X21 X20X19X18X17 XXXX XXXX XXXX XXXX | Y24Y23Y22Y21 Y20Y19Y18Y17 YYYY YYYY YYYY YYYY |
Données reformées | (4 bits étage) (4 bits état) X24Y24X23Y23 X22Y22X21Y21 X20Y20X19Y19 X18Y18X17Y17 |
J’ai entremêlé les bits pour éviter que tout retard de décodage n’engendre de déplacements irréels du curseur. Dans le cas de retard, seul les bits faibles peuvent être mal décodés. En mettant également les bits faibles à la fin je minimise l’importance de ces erreurs. Ce qui n’est pas le cas si j’avais mis:
(4 bits étage) (4 bits état)
X24X23 X22X21 X20X19X18X17 Y24Y23Y22Y21 Y20Y19Y18Y17comme données reformées. Cela peut avoir de réels répercussions sur la position Y du curseur.
Mise en pratique de la décomposition du signal du niveau Curseur*10Voici la puce d’encodage : | Puce encodage X (9) 0000 0000 1000 0000 0000 0000 (11) 0000 0000 0010 0000 0000 0000 (13) 0000 0000 0000 1000 0000 0000 (15) 0000 0000 0000 0010 0000 0000 (17) 0000 0000 0000 0000 1000 0000 (19) 0000 0000 0000 0000 0010 0000 (21) 0000 0000 0000 0000 0000 1000 (23) 0000 0000 0000 0000 0000 0010 Les 8 premiers bits analogiques de X sont ainsi déplacé puis additionné (par la puce à droite) |
L’étage et l’état sont donnés par d’autres puces puis réceptionnés déjà encodé grâce à des détecteurs de clé magnétique. Les additions sont faites pour englober le tout dans une donnée analogique. |
Puce encodage Y (10) 0000 0000 0100 0000 0000 0000 (12) 0000 0000 0001 0000 0000 0000 (14) 0000 0000 0000 0100 0000 0000 (16) 0000 0000 0000 0001 0000 0000 (18) 0000 0000 0000 0000 0100 0000 (20) 0000 0000 0000 0000 0001 0000 (22) 0000 0000 0000 0000 0000 0100 (24) 0000 0000 0000 0000 0000 0001 Les 8 premiers bits analogiques de Y sont ainsi déplacé puis additionné (par la puce à droite) |
Voici la puce de décodage : Les 2 puces de gauche séparent les 24 bits du signal analogique enregistré. Les fils se croisent en sortie de la puce des bits les plus faibles (puce du bas) pour X et Y | | Les puces de droite retransmettent les valeurs sur les bits les plus forts afin de pouvoir être traitées. |
Valeur des mémoires à nœud de circuit : (1) 1000 0000 0000 0000 0000 0000 (2) 0100 0000 0000 0000 0000 0000 (3) 0010 0000 0000 0000 0000 0000 (4) 0001 0000 0000 0000 0000 0000 (5) 0000 1000 0000 0000 0000 0000 (6) 0000 0100 0000 0000 0000 0000 (7) 0000 0010 0000 0000 0000 0000 (8) 0000 0001 0000 0000 0000 0000 |
ApplicationsCe didacticiel se divise en 3 parties, la mémoire unique, l'enregistrement dans le temps grâce aux mémoires uniques et l'utilisation de la compression grâce à la décomposition du signal analogique en binaire.
La mise en commun de ces trois idées a permis de mémoriser les positions d'un curseur, mais il peut le faire également pour un sackbot ou tout autre chose.
Il faut garder à l'esprit que le système ne peut mémoriser que des données précises. La position en est une par exemple alors que le fait d'avancer un sackboy n'en est pas car dépend de l'orientation du joystick. Il est donc possible de mémoriser les positions d'un sackboy dans une zone bien définie du style carré ou rectangle.
Je suis entrain de vérifier si l'on peut faire fonctionner la puce d'enregistrement à l'envers et donc faire revenir sur ces pas un sackbot par exemple.
Chacune des idées peut être prise indépendamment ou en combinant que 2. On a vu que l'on pouvait faire des calculs sur les mémoires uniques alors pourquoi pas une calculatrice grâce à l'utilisation du binaire avec? Faire un système de points, l'addition et la soustraction étant immédiate. Le coupler avec le système de score peut ainsi permettre enfin de différencier le score de chacun des joueurs.
On peut faire dire plein de choses à une valeur analogique, c'est maintenant à vous de trouver ce qu'elle doit dire!!!
Ce didactitiel est soumis à changements. Il se peut que quelques erreurs s'y soient glissées
Je vous remercie de l'avoir lu et espère qu'il vous aidera!!