Ordinateur complet Turing 8 bits dans Factorio



Je souhaite partager mon projet créé dans Factorio basé sur la logique offerte par ce jeu. Ce projet a été inspiré par un grand esprit, qui a écrit un guide étape par étape pour créer presque la même voiture, mais dans le monde réel. Je recommande de le regarder, cela vous aidera à comprendre et à recréer ce projet: ordinateur 8 bits



Je baisse la tête vers Ben Eater, qui m'a tant appris à travers sa chaîne, et j'ai envie de lui consacrer ce petit projet. Super boulot Ben!



Voici un ordinateur calculant le nombre de Fibonacci, après avoir dépassé la limite de 8 bits (255), il effectue un branchement conditionnel et recommence:



image


Voyons comment fonctionne cet ordinateur. Et n'ayez pas peur - je suis sûr qu'avec les bases, vous pouvez le faire aussi! Commençons par la disposition générale de l'ordinateur. Ici, j'ai mis en évidence les domaines importants. Ci-dessous, je vais vous expliquer comment je les ai créés.



CLK est une minuterie qui assure la synchronisation de la machine. Les processeurs modernes sont capables de fonctionner à 4-5 GHz (4-5 000 000 000 Hz). Pour le moment, ma machine peut fonctionner à 2 Hz en raison des limitations des portes logiques Factorio - chaque entrée doit être calculée pour chaque combinateur (porte), donc si nous en avons 10 d'affilée, nous devons attendre 10 chronomètres de jeu (fps ) pour démarrer le cycle suivant du système. Sinon, les signaux seront confondus et le calcul ne sera pas effectué.



PC (compteur de programme, compteur de programme) - le compteur indique dans quelle partie du programme nous nous trouvons. Les programmes sont lus à partir de la mémoire de 16 octets (un octet contient 8 bits). Le compteur compte jusqu'à 16 (4 bits) au format binaire (0000, 0001, 0010, 0011, 0100, 0101 ... 1111), donc chacun de ces calculs nous donne une adresse de registre, que nous pouvons plus tard récupérer de la mémoire et effectuer avec lui des actions. Il contient également un Jump qui réinitialise le compteur. Nous pouvons entrer une valeur différente pour aller à un emplacement spécifique dans notre mémoire / code.



BUS est le principal point de connexion pour tous les composants informatiques. Nous pouvons transférer des données vers / depuis celui-ci. Pour ce faire, nous utilisons des signaux de contrôle qui ouvrent / ferment les portes de chaque composant, de sorte que plus de deux portes ne soient jamais ouvertes (donc les données ne sont pas mélangées).



ALU est notre "calculatrice" qui effectue des opérations d'addition et de soustraction (elle peut faire beaucoup plus sur des processeurs plus complexes!). Il reçoit instantanément ce qui se trouve dans les registres A et B, puis effectue des opérations logiques (on sélectionne l'opération par le décodeur d'instructions). Ensuite, ces données sont envoyées au bus (bus). ALU stocke également des indicateurs qui peuvent être utilisés dans les fonctions de branche conditionnelle.



Registres A et B - ils peuvent stocker des nombres de 8 bits, qui sont ensuite concaténés dans l'ALU. Les deux registres peuvent envoyer et recevoir des données du bus.



Register address / Decoder (RAD) - lit une adresse de 4 bits à partir du bus et décode la quantité de RAM que nous devons lire. Par exemple, l'adresse 1110 contient la valeur 0000 0011 (voir image).



RAM - Les PC modernes ont généralement environ 16 Go de mémoire (16 000 000 000 octets). Nous n'avons que 16 octets ... Cela nous laisse de la place pour 16 instructions ou moins afin que nous puissions stocker des données / variables dans d'autres parties de la mémoire. Fondamentalement, la RAM ici est de 16 registres différents, comme ceux que nous utilisons ailleurs, ils sont simplement accessibles via un décodeur de registre.



Registre d'instructions (IR) / décodeur (DC) - Nous pouvons mettre des données dans le registre d'instructions à partir du BUS, puis les décoder pour dire comment le programme doit se comporter. Seuls 4 bits sont utilisés (surlignés en turquoise), ce qui nous donne 16 types de commandes programmables. Disons que nous avons une commande OUT qui imprime ce qui est stocké dans le registre A. Elle est codée en 1110, donc quand une telle commande atteint le registre, nous pouvons la décoder et dire à l'ordinateur comment procéder.



Compteur de microcode (MC) - Similaire au compteur de programme, mais situé à l'intérieur du décodeur d'instructions. Nous donne la possibilité de parcourir chaque commande.



LCD / Screen est en fait un registre, mais plus compliqué, puisqu'il imprime son contenu sur un écran LCD (Lamp-Combinator-Display, "un affichage de lanternes et de combinateurs").



Carte de commutation (SB) - Ce panneau nous montre les fonctions de commutation que nous envoyons pour contrôler chacun des composants de l'ordinateur. À l'heure actuelle, il existe 17 commutateurs différents qui contrôlent différentes choses. Par exemple, si nous voulons lire depuis BUS vers le registre A, ou écrire dans la mémoire / registre de commande, etc. Les commutateurs décrits ci-dessous peuvent être utilisés pour contrôler manuellement la machine.



Flags (F) - un registre pour stocker les drapeaux (carry [T] - lorsque nous dépassons les valeurs de 8 bits lors de l'ajout, la mise à zéro de [O] - lorsque la somme / différence est de 0). Ils nous aideront avec les commandes de saut conditionnel.



image


Permettez-moi d'abord d'entrer plus en détail sur chaque composant, et à la fin, nous verrons comment programmer un ordinateur, car le processus deviendra plus clair. Si vous n'êtes intéressé que par la programmation, passez à la dernière partie de l'article.



CLK est notre générateur de synchronisation, la chose la plus importante dans tout calcul. Je voulais créer un oscillateur qui a un signal haut [C = 1] et un signal bas [C = 0] en même temps.



(1) Il s'agit d'un combinateur de constantes de base qui fournit des signaux à un générateur. Il saute à (2) où l'entrée et la sortie sont fusionnées. Grâce à cette configuration, à chaque horloge de jeu (UPS), la valeur de [C] est augmentée de 1. Lorsqu'elle atteint [Z], elle est remise à 0. Autrement dit, Z nous indique combien d'horloge de jeu il faut pour réinitialiser le générateur. Il y a aussi un simple diviseur par 2 ci-dessous, qui maintient le générateur haut pendant la moitié du temps et bas pendant la moitié du temps. Lorsque C est inférieur à [Y] (qui est la moitié de [Z]), le générateur est haut, sinon il est bas.



L'inséreuse (4) est utilisée comme générateur de synchronisation secondaire au cas où nous aurions besoin de plus de contrôle sur les graduations. Si vous mettez quelque chose dans le premier coffre, un battement se produira. Si nous avons besoin de 5 barres, nous devons y placer cinq objets.



(5) est le premier signal de commande. [H] est l'abréviation de la commande HALT {HLT}. Lorsqu'il a une valeur basse [H = 0], alors le générateur fonctionne normalement, et s'il est élevé, il passe en mode manuel. Ceci est facilité par les portes de commande, elles (5a) sont utilisées pour un fonctionnement normal, et lorsque le signal [H] n'est pas 0, alors le mode manuel est activé et [C] (notre CLK) est émis.



J'ai également créé un signal inversé en utilisant la porte (6) - lorsque la sortie est basse, le signal inversé est haut. Je ne l'utilise pas dans une voiture, mais c'est une bonne idée de s'en souvenir pour référence future.



Le signal [C] traverse le système via le fil vert. Je voulais l'isoler sur un fil complètement séparé (par exemple, notre BUS est sur le fil rouge) afin qu'il puisse être facilement suivi et ne pas confondre avec d'autres signaux.



image


Registres - ne vous laissez pas intimider par eux. Il s'agit probablement de la partie la plus complexe de l'ensemble du système, mais il est important de comprendre le fonctionnement de l'ensemble de la machine.



Les registres contiennent des valeurs. Dans la vie ordinaire, il faudrait créer un registre pour chacun des 8 bits et autres signaux. Heureusement, Factorio vous permet d'envoyer plusieurs signaux sur une seule ligne. Ce sont essentiellement des déclencheurs JK.



Brièvement sur leur fonctionnement. À chaque impulsion de synchronisation, ils vident ce qui se trouve à l'intérieur et conservent la valeur entrante. S'il n'y a pas de valeurs entrantes (toutes des zéros), elles sont effacées dans le cycle de synchronisation. Bien sûr, nous ne voulons pas qu'ils soient toujours vides, après tout, nous devons y stocker des valeurs. Par conséquent, nous utilisons la logique de contrôle, dont je vais maintenant parler, et nous traiterons de la magie noire de la création d'un déclencheur plus tard.



Les valeurs enregistrées (1) sont affichées avec des lampes de poche. Lorsque le voyant est allumé, cela signifie 1, et éteint cela signifie 0. Comme vous pouvez le voir, nous stockons actuellement la valeur 1110 1001.



Pour sortir la valeur sur le bus, nous utilisons la logique de commande de porte (2). Lorsque le signal [K] est bas, cette porte délivre tout ce qui se trouve à l'intérieur du registre vers le bus principal.



Pourquoi l'utilisons-nous lorsque le signal est faible et non élevé? Parce que les portes logiques émettent tout ce qui leur est fourni (rouge *), et par conséquent, le bus aura un signal [K], et nous n'en avons pas besoin, nous avons seulement besoin de [7, 6, 5, 4, 3 , 2, 10]. Pour la même raison, nous devons filtrer les signaux de commande avec la porte (3) afin de ne recevoir [K] que lorsque nous en avons besoin.



La porte (4) est connectée à la fois au bus (fil rouge) et aux signaux de commande (fil vert). Comme dans le cas précédent, le registre reçoit une entrée lorsque le signal [A] est au niveau bas. Pour filtrer tous les autres signaux, nous utilisons une porte logique (4a). En fait, il prend toutes les entrées du bus et des signaux de commande indésirables, puis les ajoute au combinateur (4b), dont les entrées sont toujours des signaux [7, 6, ... 0] = 1. Alors si l'un des signaux vaut 0, alors il émet chacun de ces signaux = 1. C'est simple, non? Dans ce cas, seules les valeurs du bus qui sont importantes pour nous entrent dans les registres (les valeurs 0 seront toujours 1, elles clignotent pendant un cycle d'horloge, puis restent désactivées pendant tout le cycle CLK haut).



Dans une telle situation, lorsque [C] devient haut, l'obturateur (6) émet le signal [NOIR] et l'obturateur (6a) annule [C]. Mais comme il faut 1 UPS de plus pour se réduire à zéro, la porte (6) émet un signal en si peu de temps.



Ce signal est ensuite transféré à la porte (7), qui s'ouvre également pendant un court instant. La porte (7b) annule le signal [NOIR] afin qu'il ne soit pas stocké dans la porte (8), qui est utilisée comme gardien de notre signal. Ceci est similaire au réseau CLK, car l'entrée et la sortie sont connectées ensemble. S'il n'y a pas d'entrée, il reste inchangé. Si nous modifions à nouveau l'horloge sans entrer de nouvelles données, la porte (7a) entrera un signal inversé par rapport à la valeur stockée dans le registre pour l'effacer.



Maintenant que nous savons comment fonctionnent la reconnaissance des changements et les registres, nous savons presque tout.



image


ALU - ajouter / soustraire constamment ce qui est dans les registres (A) et (B). Nous contrôlons seulement s'il faut le sortir sur le bus [Z] ou changer le mode pour soustraire [S].



Comment ça fonctionne? Pour avoir une image complète, je recommande de regarder certaines des vidéos de Ben Iter, car l'explication sera trois fois plus longue que mon article.



Je vais seulement expliquer comment créer un tel additionneur dans Factorio.



Pour ce faire, nous avons besoin de trois types de portes: XOR (1), AND (2) et OR (3). Heureusement, ils sont assez faciles à créer. Puisque nous pouvons utiliser plusieurs signaux sur la même ligne, nos premières portes XOR et AND peuvent être simplifiées à seulement deux, et nous n'avons pas besoin de les faire pour les 8 bits. Cela nous permet de faire (4) partie de la chaîne et de la dupliquer pour chaque bit.



La soustraction est effectuée avec le signal [S], qui inverse les signaux provenant du registre (B).



ALU produit également le report (lorsque la somme dépasse 8 bits), la remise à zéro et le stocke dans le registre de droite (F dans l'image avec l'ordinateur principal).



image


LCD / Écran - Cela semble intimidant, mais honnêtement, c'était le plus facile à faire. Il ne faut que du temps pour tout connecter correctement.



Tout d'abord, nous créons un registre dont l'entrée est contrôlée par le signal [P]. Ensuite, nous multiplions chaque bit par sa valeur, en le convertissant en valeur décimale pour obtenir le même signal avec une valeur décimale (c'est une sorte de triche dans Factorio, mais le manque d'EEPROM programmables ne nous permet pas de trop tourner). Pour convertir, il suffit de prendre le premier bit [0] et de le multiplier par * 1, puis de prendre le deuxième bit [1] et de multiplier par * 2, le troisième [2] par * 4, et ainsi de suite. Dans le processus, nous produisons une valeur arbitraire pour déterminer le nombre résultant (dans ce cas, c'est [une goutte d'eau]).



L'écran LCD s'allume en 9 étapes pour les nombres (3). Nous avons juste besoin de régler ces lumières correspondant aux étapes (1), puis d'utiliser les portes (2) pour afficher la valeur exactement là où nous en avons besoin. Vous devez juste vous rappeler d'ajouter un combinateur de constantes séparé (3) et de le connecter à une seule porte spéciale (2). Ensuite, nous connectons simplement toutes les lumières les unes aux autres et leur donnons des instructions sur l'étape dans laquelle elles se trouvent (1).



image


Registre RAM / mémoire (RAD) - Ici, je vais expliquer comment la RAM fonctionne à peu près.



Nous connaissons déjà des registres qui utilisent des impulsions de synchronisation pour stocker des valeurs. La RAM n'est qu'une grille de 16 (dans notre cas) registres différents (2). Leurs entrées sont contrôlées par un autre registre (1) qui stocke 4 bits [0, 1, 2, 3], qui nous indique vers quel emplacement mémoire nous pointons. Ceci est mis en œuvre à l'aide d'un décodeur d'adresse (3), qui fonctionne de manière similaire à LED / écran. Chaque porte reçoit une valeur du combinateur de constantes (dans notre cas 1100 bin = 10 déc), puis délivre le nom du signal du registre correspondant (dans notre cas [M]) afin que la valeur soit accessible (dans notre cas 00110 0011).



La programmation manuelle de la mémoire mérite également d'être mentionnée ici. Cela peut être fait en utilisant le signal [W], activé / désactivé à l'aide du combinateur de constantes (4). Un autre combinateur (5) nous permet de changer l'adresse, et nous utilisons un autre combinateur (6) pour entrer la valeur. Au final, on met juste tout dans le coffre (7), de sorte que lors de la synchronisation, on transfère manuellement les valeurs vers la RAM, sans toucher au CLK principal de l'ordinateur.



image


Compteur de programme (PC) - sa tâche est de calculer à quelle étape du programme nous nous trouvons (1). Au démarrage, elle a une valeur de 0000, cette adresse est lue depuis la RAM et transférée vers le registre de commande pour interprétation. Une fois la commande terminée, nous pouvons incrémenter le compteur avec le signal [X], puis il devient égal à 0001, et à l'itération suivante, cette adresse est extraite de la mémoire et la boucle continue.



Bien sûr, nous devons parfois effectuer des branchements inconditionnels ou conditionnels vers d'autres parties du programme. Nous pouvons le faire avec le signal [J]. S'il est bas (dans notre cas, bas signifie actif), alors il est réinitialisé, lit à partir du bus l'adresse à laquelle il doit sauter, et la stocke dans le registre (2). Lorsque [J] redevient haut, il signale le détecteur de changement (situé directement sous 2) au PC.



Le compteur lui-même fonctionne de la même manière que CLK, mais au lieu de compter constamment les cycles d'horloge, il compte les cycles d'horloge lorsque des changements dans CLK sont détectés (en fait, uniquement lorsque X et CLK sont actifs). Cela peut être vu directement dans l'image (1).



Le signal peut ensuite être appliqué au bus à l'aide du signal de commande [C].



image


Carte de commutation (SB) - C'est le bon moment pour expliquer chaque signal de commande utilisé dans le programme.



Les signaux sont divisés en deux couleurs, les vertes vers la gauche, les rouges vers la droite. Chaque signal des combinateurs constants est en fait passé sous forme de valeurs [-1]. Autrement dit, lorsque les combinateurs sont réglés sur *! = 0, ils peuvent émettre le signal 1. Pour cette raison, lorsque la logique de commande envoie le signal [1], ils sont annulés, et nous obtenons [0], et dans tous les cas nous besoin juste de cela (vous pouvez lire dans la partie où j'explique les registres).



[H] - arrête le générateur d'horloge (passe en mode manuel), un signal haut signifie que CLK n'est pas commuté.



[Q] - l'adresse de la RAM, dans laquelle se trouve le registre, avec un signal haut, le registre d'adresse de RAM sauvegardera la valeur du bus dans le prochain cycle CLK.



[Y] - Entrée de la mémoire RAM, lorsque le signal RAM est élevé, il sauvegardera la valeur du bus dans le prochain cycle CLK (à l'adresse stockée dans le registre d'adresse).



[R] - Sortie RAM, lorsque le signal RAM est haut, il délivre la valeur au bus dans le prochain cycle CLK (à partir de l'adresse stockée dans le registre d'adresse).



[V] - entrée du registre de commande, lorsque le signal est haut, le registre de commande enregistre la valeur du bus dans le cycle CLK suivant.



[U] - sortie du registre de commande, lorsque le signal est haut, le registre de commande délivre la valeur au bus dans le cycle CLK suivant (uniquement les 4 derniers bits [3, 2, 1, 0]).



[C] - sortie du compteur de programme, lorsque le signal est haut, le compteur de programme délivre la valeur sur le bus dans le cycle CLK suivant (uniquement les 4 premiers bits [7, 6, 5, 4]).



[J] - entrée de l'adresse de transition, lorsque le signal est haut, le compteur de programme définira la valeur du bus dans le prochain cycle CLK (uniquement les 4 derniers bits [3, 2, 1, 0]).



[X] - augmentant la valeur du compteur de commandes, lorsque le signal est haut, le compteur de programme effectue un incrément dans le cycle CLK suivant.



[A] - entrée du registre A, avec un signal haut dans le registre A, la valeur du bus est sauvegardée dans le cycle d'horloge CLK suivant.



[K] - sortie du registre A, avec un signal haut du registre A, la valeur est sortie sur le bus dans le cycle d'horloge CLK suivant.



[Z] - Broche ALU, lorsque le signal ALU est haut, il délivre la valeur au bus lors du prochain cycle CLK.



[S] - soustraction (ALU), lorsque le signal est haut, l'ALU change son mode de l'addition à la soustraction.



[B] - entrée du registre B, avec un signal haut dans le registre B, la valeur du bus est sauvegardée dans le cycle d'horloge CLK suivant.



[L] - sortie du registre B, avec un signal haut du registre B, la valeur est sortie sur le bus dans le cycle d'horloge CLK suivant.



[P] - entrée dans le registre LCD / écran, lorsque le signal est haut, la valeur du bus est sauvegardée dans le registre LCD / écran dans le prochain cycle CLK, et cette valeur est affichée.



[W] - entrée du registre des drapeaux, lorsque le signal est haut, le registre des drapeaux enregistre le report de ALU (lorsque 8 bits sont dépassés), zéro (lorsque l'opération ALU = 0000 0000).



[signal rose] - drapeau de retenue levé [T]



[signal turquoise] - drapeau zéro levé [O]



Disons maintenant que nous devons effectuer une action OUT: prenez ce qui est dans le registre A et imprimez-le sur l'écran LCD / écran (registre). .. Pour ce faire manuellement, il suffit d'activer (en désactivant le combinateur de constantes pour une certaine lettre) le signal [K] (sortie du registre A -> bus) et le signal [P] (bus -> entrée du registre lcd / écran), puis exécutez l'horloge CLK.



image


Registre de commande / décodeur / compteur de microcode - c'est là que la magie commence. Maintenant que nous savons comment contrôler manuellement un ordinateur, cela nous aidera à comprendre. ce qui doit être fait pour qu'il puisse se gérer.



(1) le compteur de microcode comptera jusqu'à 8 (le nombre peut être réduit si nous n'en avons pas besoin autant), c'est-à-dire que nous pouvons exécuter 8 commandes marche / arrêt différentes pour effectuer une action en une seule commande.



(2) les commandes sont lues dans un registre à partir du bus, pour cela nous devons activer les signaux [C] (sortie du compteur de commandes -> bus) et [Q] (bus -> adresse mémoire d'entrée), puis lire la RAM [R] (RAM de sortie -> bus) dans le registre de commande [V] (bus -> registre de commande), et aussi pour incrémenter le compteur [X].



Puisque toutes les actions ci-dessus doivent être effectuées à chaque fois, j'ai connecté tout cela (4) directement au compteur du microcode afin que cela se produise à chaque fois que le compteur passe par les étapes 0 et 1.



Lorsqu'il y a quelque chose dans le registre, nous pouvons utiliser des tables de vérité similaires à celles que nous avons créées pour le registre d'adresse RAM et les sorties sur l'écran LCD / écran.



Les valeurs [D] du registre de commande (il est toujours supérieur à 8) et le compteur de microcode (toujours égal ou inférieur à 8) peuvent être ajoutés, et en utilisant le nombre résultant, nous pouvons créer des portes logiques. Cela se fait par des portes (3).



L'exemple montre la commande 0110 XXXX (48 + X en déc, pour laquelle j'ai programmé la commande JMP), qui est ensuite ajoutée à l'étape 2 du compteur de microcodes, ce qui donne 50.



Autre exemple: commande ADD (0010 XXXX - 16 + X en déc); après les étapes 0 et 1, le microcode sera 2, c'est-à-dire que les registres 18-24 peuvent être utilisés pour une autre partie du code (dans ce cas, nous n'avons besoin que de 18-20, car ADD est un processus en 3 étapes).



(5) Les drapeaux de report sont traités par des portes logiques simples, l'entrée est désactivée sur celles-ci uniquement si aucune retenue [T] ou zéro [O] n'est appliquée aux portes logiques.



Voici ma liste complète des commandes implémentées (vous pouvez les changer ou ajouter les vôtres!):



0 NOP - 0000 XXXX - ne fait rien.



1 LDA X - 0001 XXXX - charge la valeur de l'adresse X RAM dans le registre A.



2 ADD X - 0010 XXXX - charge la valeur de l'adresse X RAM dans le registre B, puis sort l'addition et la place dans le registre A.



3 ADD X - 0011 XXXX - charge la valeur de l'adresse X RAM dans le registre B, puis sort la soustraction et la place dans le registre A.



4 STA X - 0100 XXXX - charge la valeur du registre A et la stocke dans la RAM à l'adresse



X.5 LDI X - 0101 XXXX - charge rapidement la valeur du registre de commande ( seulement valeur 4 bits) dans le registre A.



6 JMP X - 0110 XXXX - inconditionnel (se produit toujours), le passage à la valeur X (PC affecte la valeur de X).



7 JC X - 0111 XXXX - lorsque la valeur de report [T] est vraie, passe à la valeur X (affecte PC à X).



8 JO X - 1000 XXXX - lorsque le transfert de zéro [O] est vrai, alors il passe à la valeur X (affecte la valeur PC à X).



9 OUR X - 1001 XXXX - affiche la valeur de l'adresse X RAM.

...

...

...

14 OUT - 1110 XXXX - Exécute l'affichage à partir du registre A (X ne fait rien).



15 HLT - 1111 XXXX - arrête le générateur de synchronisation (X ne fait rien).



Écrivons un programme simple et voyons comment cela fonctionne!



0 LDA 3 - charger la valeur dans le registre A à partir de l'adresse mémoire 3



1 OUT - afficher la valeur du registre A.



2 HLT - arrêter CLK, c'est-à-dire toute la machine.



3 42 - valeur mémorisée



C'est-à-dire que ce programme sort la valeur mémorisée à l'adresse 3 RAM (0011 en binaire).



Convertissons-le en binaire:



0 Adresse: 0000, valeur: 0001 0011



1 Adresse: 0001, valeur: 1110 0000



2 Adresse: 0010, valeur: 1111 0000



3 Adresse: 0011, valeur: 0010 1010



Autrement dit, pour écrire un programme, nous devons écrire en mémoire (W sur le panneau de mémoire; voir la partie avec l'image RAM), en commençant à l'adresse 0000, et entrer la valeur 0001 0011 à l'intérieur (0001 signifie la commande LDA, où 0011 est X, c'est-à-dire l'adresse 3 en mémoire) ...



Ensuite, nous faisons de même pour les autres équipes.



N'oubliez pas de tourner à nouveau [W] au vert et de sauvegarder l'arrêt du compteur.



Vous pouvez également réinitialiser le PC en sautant avec J (il n'est pas nécessaire de changer le rythme CLK).



All Articles