Mettre le jeu "Snake" sur la planche Ă  pain. Partie 1: machines d'Ă©tat

À loisir, mon fils et moi Ă©tudions l'Ă©lectronique numĂ©rique. RĂ©cemment, nous sommes arrivĂ©s au chapitre sur les machines Ă  Ă©tats finis. Cette rubrique regorge de tĂąches typiques, telles qu'un sĂ©maphore ou un distributeur automatique. Mais ils sont tous ternes et trop simples, et certains sont gĂ©nĂ©ralement, franchement, farfelus. AprĂšs avoir Ă©tudiĂ© des exemples simples, je voulais faire quelque chose de plus intĂ©ressant et complexe. Le jeu classique «serpent» a attirĂ© mon attention (mon fils l'a jouĂ© au tĂ©lĂ©phone), et j'ai suggĂ©rĂ© de le faire sur des machines d'État. AprĂšs tout, l'Ă©tat du jeu est assez final (surtout si vous vous limitez Ă  un petit champ), et Ă  partir des entrĂ©es, il n'y a que 4 boutons. Et c'est ce que nous avons obtenu.


Le jeu Snake (c'est un serpent, un python, un boa constrictor, etc.) est largement connu de tous. Elle vient des annĂ©es 70 lointaines, mais je ne vais pas rĂ©pĂ©ter son histoire, que vous pouvez lire sur Wikipedia ou de nombreux articles sur HabrĂ©. Le jeu a des rĂšgles assez simples et en mĂȘme temps un gameplay addictif)) GrĂące Ă  cela, il est souvent utilisĂ© pour des tutoriels ou des exemples de code . Dans les langages de programmation de haut niveau, faire un tel jeu est assez simple. Mais dans des conditions plus limitĂ©es, la plus intĂ©ressante commence, par exemple, une implĂ©mentation sur LabVIEW . Il existe Ă©galement de nombreuses options sur FPGA: lien 1 , lien 2 , lien 3, Lien 4 . Mais il n'y a pas eu une seule option sur des puces TTL distinctes de sĂ©rie standard. C’est ce que nous allons faire.

Il semblerait que les solutions FPGA soient les plus proches pour nous, et vous pouvez emprunter beaucoup Ă  partir de lĂ ? Mais dans toutes les options que j'ai examinĂ©es, elles sont facilement dispersĂ©es dans les registres gauche et droit. Par exemple, trĂšs souvent, un bit ou un numĂ©ro distinct est attribuĂ© Ă  chaque cellule de champ. Nous ne pouvons pas le faire avec de la poudre libre, car chaque nouveau registre est un microcircuit sĂ©parĂ© qui doit ĂȘtre placĂ© quelque part, puis connectĂ©. Par consĂ©quent, nous rayons toute l'expĂ©rience accumulĂ©e par d'autres dĂ©veloppeurs et ferons tout Ă  partir de zĂ©ro. En bonus, nous collecterons tout sur les puces domestiques (et mieux - soviĂ©tiques) de la sĂ©rie k555 / kr1533, Ă  l'exception des ROMs, qui devront ĂȘtre renouvelĂ©es.

Formulation du problĂšme


Nous aurons de telles restrictions: un champ de taille 8 × 8 cellules ( matrice LED chinoise ), une longueur de queue de 8 cellules. Un serpent peut traverser les murs, mais nous ne traiterons pas l'intersection avec la queue dans un premier temps (afin de ne pas compliquer la conception, vous pouvez l'ajouter plus tard). Pour dĂ©crire l'Ă©tat complet du jeu, nous avons besoin de:

  1. Position de la tĂȘte (X = 0..7, Y = 0..7, 6 bits)
  2. Sens de dĂ©placement (↑ ↓ ← →, 2 bits)
  3. Position Apple (X, Y, 6 bits)
  4. Longueur de queue (0..7, 3 bits)
  5. La position des cellules de la queue (de 0 Ă  7 morceaux de 6 bits chacun)

Au total, 65 bits sont obtenus, mĂȘme si nous prenons des registres de 8 bits chacun, seuls 8 de ces microcircuits (et un dĂ©clencheur de plus) sont nĂ©cessaires pour stocker l'Ă©tat, c'est beaucoup.

Mais la queue ne peut pas ĂȘtre situĂ©e oĂč elle veut, elle "pousse" de la tĂȘte. Par consĂ©quent, nous pouvons stocker non pas les coordonnĂ©es complĂštes de chaque section de la queue, mais uniquement la direction dans laquelle la direction de la cellule (ou tĂȘte) prĂ©cĂ©dente doit ĂȘtre dessinĂ©e. Ensuite, au lieu de 6 × 8 = 48 bits, nous avons besoin de 4 × 8 = 16 bits, ce qui reprĂ©sente une Ă©conomie de quatre cas de registre!

Machines automatiques


Essayons de tout faire sur des machines similaires à Moore ou Miles. Pour implémenter un tel automate, il suffit d'avoir un peu de mémoire d'état (registre) et de logique combinatoire pour basculer entre eux.


Image de Wikipedia

Habituellement, une machine à états est décrite comme un graphique des états et des transitions entre eux. Parfois, il est plus pratique de créer un tableau de transitions vers un nouvel état, l'exemple le plus simple (de Wikipedia):

vous pouvez trouver plus d'informations et de belles images, par exemple, dans cet article sur Habré

Petite digression
, , . , ROM , ROM. ( , ).

, , .


, « » .



Un serpent de diffĂ©rents Ă©tats (si vous ne tenez pas compte de la position de la pomme) peut avoir 2 ^ 8 + 2 ^ 10 + ... + 2 ^ 24 ≈ 32 millions. Il n'est pas possible de les Ă©crire dans le tableau, et encore plus de dessiner un graphe de transition. Mais la plupart des transitions sont tout Ă  fait les mĂȘmes (la tĂȘte ne dĂ©place qu'une seule cellule adjacente et la queue se dĂ©place d'une section par tour). Dans ce cas, nous ne pouvons pas dĂ©crire chaque Ă©tat individuel, mais formuler un nouvel Ă©tat en fonction du prĂ©cĂ©dent. De plus, on peut diviser l'ensemble du jeu en plusieurs automates parallĂšles: 1) une machine automatique de direction, 2) une machine automatique de position de la tĂȘte, 3) une machine automatique pour la queue. Et pour rĂ©gler chacun d'eux comme il sera plus pratique:

1) ,  │  
  ────────────────────┌───────────────────
   ←        ←/↓/↑     │ ←
   ←          →       │ →
   ↑        ↑/←/→     │ ↑
   ↑          ↓       │ ↓
   ......          │

2) ,  │  
  ─────────────────────┌──────────────
   ←             (x,y) │ (x-1, y)
   →             (x,y) │ (x+1, y)
   ↑             (x,y) │ (x, y-1)
   ↓             (x,y) │ (x, y+1)

3) ,                       │  
  ─────────────────────────────────────────┌──────────────────────────
   ←            (t1,t2,t3,t4,t5,t6,t7,t8)  │ (←,t1,t2,t3,t4,t5,t6,t7)
   ......                               │


Direction


Commençons par la machine directionnelle. Si vous réfléchissez bien, vous pouvez l'assembler sur une logique distincte. Mais, comme la tùche dans son ensemble est déjà assez grande, j'ai décidé qu'il serait plus facile de créer une table de recherche à partir de l'EEPROM et d'écrire la table de transition manuellement. Il aura 6 entrées, ce qui signifie seulement 64 valeurs, que nous pouvons simplement insérer dans l'éditeur hexadécimal.



TĂȘte


Pour une machine de position de tĂȘte, l'Ă©criture d'une telle table sera beaucoup plus difficile. Mais il ne contient essentiellement que 2 opĂ©rations: +1 et -1. Ils peuvent ĂȘtre implĂ©mentĂ©s sur un additionneur 4 bits K155IM6. Pour +1, nous ajouterons nos coordonnĂ©es avec b'0001, et pour -1 avec b'1111 (qui est en fait -1 dans le code supplĂ©mentaire ). Nous aurons besoin de deux additionneurs (pour x et y), un peu de logique, et nous stockerons l'Ă©tat dans le registre IR27 Ă  8 bits (nous en avons encore besoin de beaucoup):



Assemblons-le sur la carte, et pour vĂ©rification, nous connecterons immĂ©diatement la matrice LED avec deux dĂ©codeurs. Le dĂ©codeur Ă  sorties inverses est ID7, et pour le direct il serait possible de prendre K561ID1 (CD4028), mais je ne l’avais pas sous la main. Une autre option est de prendre 8 transistors comme clĂ©s, mais je ne voulais pas le faire, j'ai donc dĂ» bĂȘtement dĂ©penser une autre EEPROM (y Ă©crire seulement 8 cellules). La logique de la nouvelle position de la tĂȘte sur une carte sĂ©parĂ©e en haut Une autre digression





Prenons une courte pause et sauvons la planche Ă  pain (et quelques cas de puces). Nous profiterons Ă  nouveau du fait que tout circuit combinĂ© peut ĂȘtre remplacĂ© par une LUT en Ă©crivant le tableau dans la ROM. Mais comment faire cela pour une si grande table? Nous allons utiliser une autre astuce - nous ferons le contraire: remplacer l'EEPROM par notre circuit logique et le mettre dans le programmateur. Les jambes inutilisĂ©es sont connectĂ©es Ă  la terre via des rĂ©sistances. (Cela ne pourrait pas ĂȘtre fait si vous plongiez dans les paramĂštres du programmeur) Maintenant, nous allons lire notre diagramme logique en tant que ROM et obtenir un tableau. Nous l'Ă©crivons avec le mĂȘme programmeur dans une vĂ©ritable EEPROM, que nous mettons Ă  la place d'un circuit d'Ă©lĂ©ments sĂ©parĂ©s.







Queue


La queue a une longueur (dans nos limites) de 2 Ă  8 cellules. Pour stocker cette longueur, vous pouvez utiliser un compteur conventionnel avec une entrĂ©e de rĂ©solution de compte. En fait, ce sera la mĂȘme machine Ă  Ă©tats finis, dans laquelle le nouvel Ă©tat S 'sera Ă©gal Ă  S + 1 ou juste S (si le compte est interdit). La queue elle-mĂȘme (ou plutĂŽt, la direction oĂč elle pousse), nous allons stocker dans deux registres de 8 bits. ThĂ©oriquement, on pouvait prendre des registres Ă  dĂ©calage prĂȘts Ă  l'emploi (par exemple, IR8), mais ils n'Ă©taient pas Ă  portĂ©e de main, donc les mĂȘmes IR27 ont Ă©tĂ© utilisĂ©s. À chaque Ă©tape, la direction actuelle du mouvement de la tĂȘte est Ă©crite dans le premier bit du registre et la valeur de la prĂ©cĂ©dente dans le second et le suivant. Pour obtenir la direction de la croissance de la queue, il suffit d'inverser un bit. Vous pouvez le faire tout de suite lors de l'enregistrement, mais j'ai dĂ©cidĂ© qu'il valait mieux laisser l'inverse pour le circuit restant.

SchĂšme


Au total, notre machine du prochain mouvement prend cette forme: Cette image (comme tout le monde) est cliquable. Il s'agit d'une partie plutĂŽt «pure» (d'un point de vue thĂ©orique) du schĂ©ma. Exemple presque parfait pour une machine Moore codĂ©e en sortie . U1 est responsable de la nouvelle direction, U2 de la position de la tĂȘte, qui sont stockĂ©es dans U5. U3 et U4 sont utilisĂ©s pour la queue, et sa longueur est stockĂ©e (et augmentĂ©e) dans U6. Ensuite, nous devrons afficher tout ce que nous avons Ă  l'Ă©cran, et il y aura Ă©galement un vaisseau spatial, uniquement sous une forme plus sale. Ainsi qu'un gĂ©nĂ©rateur de nombres alĂ©atoires primitifs, une transition entre des circuits avec un signal d'horloge diffĂ©rent et d'autres hacks.







Total


J'espÚre que cet article vous a intéressé et j'essaierai de terminer rapidement la deuxiÚme partie.

Et si vous ĂȘtes dĂ©jĂ  dĂ©chirĂ© par la bataille, rempli de maquettes, de microcircuits et d'Ă©crans Ă  points, un fichier avec le circuit ROM et le firmware est joint Ă  cet article. Mini-spoiler: pour rĂ©pĂ©ter la conception, vous aurez besoin d'environ 6 prototypes, 4 EEPROM 28C16 et un peu plus de deux douzaines d'autres puces.

Eh bien, comme il se doit: aimer, partager, retweets, s'inscrire, appuyer sur la cloche, etc ...)) Et pour aujourd'hui tout, merci de votre attention! À suivre




Archive avec firmware ROM et schéma

UPD général : la deuxiÚme partie est disponible ici .

All Articles