Construisez une horloge numérique dans Wireworld

32

Inspiré par cette question Game of Life .

Wireworld simule des "électrons" traversant des "fils", dont les dispositions simples produisent un comportement typique de porte logique.

Je vous mets au défi de construire une horloge numérique dans l'automate cellulaire Wireworld. Votre horloge doit compter vers le haut de 00h00 à 23h59 de la manière habituelle, ou jusqu'à 11h59 avec un indicateur AM / PM, puis réinitialiser.

Votre entrée doit être visiblement divisée en deux parties. La partie A doit contenir toute la logique de non-affichage, toutes les parties impliquées dans l'incrémentation et la boucle des chiffres. La partie B sera l'affichage et la logique qui le pilote. La seule connexion entre ces deux parties devrait être 16 fils représentant les quatre chiffres de l'heure en BCD (avec un fil en option pour l'indicateur AM / PM et un fil en option pour une ligne d'horloge de signal si vos signaux ne sont pas continus). (EDIT: les fils toujours nuls peuvent être omis)

La synchronisation du comportement d'horloge doit être cohérente. La simulation devrait prendre le même nombre de ticks pour chacune des 1440 transitions entre états. Tous les électrons sur les 16 fils doivent être émis par la partie A en même temps et commencer leur voyage en parallèle.

Il s'agit d'une compétition de code-golf. Votre score est l'aire du rectangle de délimitation aligné autour de la partie A.

Par analogie, s'il s'agissait d'un langage textuel, votre score serait la taille de la fonction de gestion de l'horloge produisant quatre sorties 4 bits, qui contient une boucle et la logique pour 4 compteurs, pas la fonction qui décode et imprime cette sortie.

Votre partie B peut être aussi grande ou petite que vous le souhaitez. Il est uniquement nécessaire pour que la sortie de votre soumission puisse être vue par quelqu'un qui l'exécute, car il n'y a pas de moyen facile de simplement "déboguer" les sorties d'un circuit wireworld. Plusieurs circuits BCD-> 7 segments sont disponibles en ligne. N'hésitez pas à utiliser celui que vous souhaitez, ou créez le vôtre si vous avez besoin d'une ligne de signal cadencé, et affichez votre indicateur AM / PM à une échelle similaire aux chiffres.

EDIT: la partie B est désormais facultative. Si vous n'avez que les sorties BCD de votre partie A, n'hésitez pas à les soumettre. Il sera plus fastidieux de confirmer que l'horloge fonctionne, mais je peux très bien lire une rangée de bits dans une simulation interrompue.

Sparr
la source
Voici un petit simulateur en ligne.
NonlinearFruit
J'ai travaillé sur cela mais je ne l'ai vu que la semaine dernière, donc je vais probablement manquer la prime. Je ne trouve pas une version à 4 fils d'un wireworld bcd-> 7-segment; la construction d'un convertisseur 4 à 2 devant le populaire appareil à 2 fils à 7 segments (comme celui qui est fourni avec le golly) peut être la voie à suivre. Un problème avec cet appareil est que, bien qu'il soit beau, il est lent à mettre à jour, ce qui gonflera la taille de la partie A car il peut pomper les nombres plus rapidement qu'ils ne peuvent être affichés et doit être artificiellement ralenti.
wyldstallyns
J'ai une cellule de 150 000 cellules qui fonctionne, partie A, que je peux prouver, mais il manque actuellement une partie B conforme aux règles
wyldstallyns
Je ne m'attendais pas à ce que la partie B soit difficile. À quelle distance sont vos électrons dans la partie A?
Sparr
1
@wyldstallyns Il ferme le 16/12/2016 03: 30: 35Z (vous pouvez survoler le 'demain' pour obtenir les heures précises). La plus grande chance pour vous. J'aime vraiment votre horloge. C'est une idée élégamment simple et une excellente exécution. Je dois admettre que j'ai également été surpris de voir combien d'espace le mien a fini par occuper à la fin. Et je serais intéressé de voir toutes les améliorations que vous pourriez apporter au vôtre. Alors, bonne chance :)
niemiro

Réponses:

36

Horloge à verrouillage

Score - 53 508 (dont seulement 36 828 sont activement utilisés en raison de la conception en forme de L)

Horloge en cours d'exécution

Enregistrement de haute qualité - https://1drv.ms/u/s!ArQEzxH5nQLKhvt_HHfcqQKo2FODLQ
Golly pattern - https://1drv.ms/u/s!ArQEzxH5nQLKhvwAmwCY-IPiBuBmmw

Des principes directeurs -

  • Comme c'était la première fois que j'utilisais un automate cellulaire, j'ai évité de chaîner de gros composants préfabriqués. Une approche valide que je n'ai pas adoptée aurait été un additionneur binaire commençant à zéro et en ajoutant continuellement un à la dernière sortie, suivi d'un convertisseur binaire en BCD, d'un démultiplexeur d'affichage, d'un décodeur à 7 segments et d'un affichage à 7 segments.
  • Il devrait être possible de démarrer à froid l'horloge. Je me suis imposé la restriction supplémentaire qu'une seule tête d'électrons placée sur une cellule conductrice spécifique devrait correctement démarrer l'horloge. Je ne voulais pas exiger une synchronisation manuelle minutieuse de nombreuses bascules disparates et d'éléments de synchronisation individuels avant de commencer la simulation.

Partie I: Le compteur de minutes

Mathématiques

Compter de 0 à 9 en binaire (pour le chiffre des minutes les moins significatives) va comme suit -

0 - 0000
1 - 0001
2 - 0010
3 - 0011
4 - 0100
5 - 0101
6 - 0110
7 - 0111
8 - 1000
9 - 1001

En lisant que sous forme de colonnes, le flux de bits le moins significatif (2 ^ 0 unités) passe à 01010101, le flux de 2 ^ 1 unités à 0011001100, le flux de 2 ^ 2 unités à 0000111100 et le flux de 2 ^ 3 unités à 0000000011.

Le premier est simple - il vous suffit de basculer 01 pour toujours. Le troisième est un flux de quatre 1, six 0, déphasé de six zéros. Le quatrième est un flux de huit 0 et deux 1.

Le second est un peu plus difficile car il a une asymétrie désagréable. Cependant, je remarque que (où. Est l'opérateur concat):

0011001100. 0011001100 = 0011001100. NON (1100110011) = 00110011001100110011 XOR 0000000000111111111111 = 5 (0011) XOR 00000000001111111111

(Par ailleurs, comme évoqué plus tard, la majorité de mon horloge fonctionne sur un ticker de 60 temps.

Conception

Les flux de sortie de haut en bas vont des unités de minutes (2 ^ 0, 2 ^ 1, 2 ^ 2, 2 ^ 3) puis des dizaines de minutes (2 ^ 0, 2 ^ 2, 2 ^ 1). Notez que les deux fils inférieurs sont croisés.

Compteur de minutes annoté

  1. Horloge principale de 120 temps.
  2. Où placer un électron pour un démarrage à froid. Sans queue d'électrons, il se divise dans deux directions, mais la diode immédiatement au-dessus attrape l'une d'entre elles, ce qui donne un bel électron de cyclisme qui fait le tour de la boucle de 120 temps.
  3. Horloge secondaire à 12 temps.
  4. La bobine de conducteur + diode démarre l'horloge secondaire à 12 temps. Les mots ne peuvent pas décrire à quel point ce petit morceau devait être synchronisé. Vous devez synchroniser les horloges de 120 et 60 temps, puis synchroniser dans les pseudo-horloges de 24 temps et de fréquence de 24 temps, puis rattacher l'horloge de 24 temps à l'horloge de 120 temps, sinon la porte XOR ne fonctionne pas. .
  5. Déphasage.
  6. Tongues. Un seul électron sur l'entrée frappe d'abord la ligne définie, puis après un laps de temps très spécifique, frappe la ligne de réinitialisation en donnant précisément une impulsion d'entrée, une impulsion de sortie.
  7. L'ajout de bosses ici - sur la ligne de réinitialisation, augmente le délai entre le réglage et la réinitialisation sur la bascule. Chaque bosse supplémentaire donne une impulsion supplémentaire. La bascule ci-dessous a neuf bosses supplémentaires, donc dix impulsions entre le réglage et la réinitialisation.
  8. Porte XOR pour ma ligne délicate de 2 ^ 1 unités de minutes.
  9. La porte ET-NON et les longueurs de pièces très spécifiques signifient que chaque impulsion d'électrons qui vient de passer se double et annihile l'électron derrière. Diviseur de fréquence. Crée une horloge à 24 temps à partir de la source secondaire à 12 temps.
  10. Horloge secondaire à 60 temps, qui fait la plupart du travail. Il est juste plus facile de démarrer une horloge rapide à partir d'une horloge plus lente, donc l'horloge la plus lente (120 battements) est le maître, même si elle est à peine utilisée. L'horloge à 60 temps est le cœur de cette chose.
  11. Fil de rétroaction qui ne transporte des électrons que lorsque l'horloge à 60 temps tourne. Il est utilisé en conjonction avec une porte ET-NON pour empêcher le redémarrage de l'horloge à plusieurs reprises à partir du maître 120 temps. Sinon, beaucoup de choses horribles se produisent et Ctrl-Z est sauveur.
  12. La diode à partir de laquelle l'horloge à 60 temps est démarrée.
  13. L'ensemble de cet appareil est une bascule, une porte ET et une porte ET-NON combinées. Il donne un verrou. Une impulsion le démarre, une impulsion l'arrête.
  14. Boucle de fil pour calibrer le loquet à 10 impulsions activées, 10 impulsions désactivées pour une entrée d'impulsion sur dix. Sans cela, nous obtenons 12 impulsions, 8 impulsions. Ces verrous dix sur dix constituent les composants de base des blocs de dix minutes de la même manière que les bascules électroniques de 6 microns (1 impulsion) formaient les composants de base des unités de minutes.
  15. L'impulsion initiale de démarrage à froid a causé toutes sortes de problèmes, y compris le décalage de deux battements avec les horloges qu'elle démarre. Cela gâche les verrous. Cette porte ET capture et élimine les impulsions désynchronisées - en particulier l'impulsion de démarrage.
  16. C'est une partie du design que je regrette un peu rétrospectivement. Il prend un électron, le divise en cinq et annihile les cinq électrons derrière, prenant 111111 à 100000.
  17. Cela prend un électron et le coud sur le devant. Deux phases à venir pour être précis. Cela prend 100000 et fait 101000. Combiné avec la partie 16, nous obtenons 111111 -> 100000 -> 101000. Rétrospectivement, j'aurais aimé faire 111111 -> 101010 -> 101000; il aurait obtenu le même effet dans moins d'espace.
  18. Les motifs ci-dessus sont ensuite poussés dans le loquet inférieur pour obtenir 20 allumés, 40 éteints. Celui-ci est divisé, la moitié est déphasée de 20 unités, puis celles-ci forment les deux flux binaires d'ordre élevé des dizaines de minutes.

Partie II: Le compteur d'heures

Explication

L'entrée du compteur horaire est une impulsion électronique unique, une fois par heure. La première étape consiste à la réduire à une seule impulsion électronique, une fois toutes les douze heures. Ceci est réalisé en utilisant plusieurs primitives "verrouiller et rattraper".

Un «verrou» est une bascule de 6 microns connectée à un ET-NON et à une porte ET pour donner un verrou marche / arrêt de 6 microns. Un "catch" prend un flux continu d'électrons en entrée, laisse passer le premier, puis annihile tous les autres électrons derrière, jusqu'à ce que le flux se termine à quel point le catch se réinitialise.

Placer un verrou, suivi d'un verrou, en série, entraîne un électron dans -> allume le verrou, un électron à l'autre extrémité (le reste est capturé par le crochet). Ensuite, le deuxième électron entrant -> désactive le verrou, la capture se réinitialise silencieusement. Effet net: le premier électron passe à travers, le deuxième électron est annihilé, et ainsi de suite, quelle que soit la durée du retard entre ces électrons .

Maintenant, enchaînez deux "verrous et captures" en série, et vous n'avez plus qu'un électrons sur quatre à passer.

Ensuite, prenez un troisième "verrou et accrochage", mais cette fois, incorporez un quatrième verrou et accrochage sur la ligne SET de la bascule, entre la porte ET-NON et la bascule SET. Je vais vous laisser réfléchir à la façon dont cela fonctionne, mais cette fois, seul un électron sur trois passe, quelle que soit la durée du retard entre ces électrons .

Enfin, prenez un sur quatre électrons et un sur trois, combinez-les avec une porte ET, et seulement un sur douze électrons passe à travers. Cette section entière est le gâchis désordonné des chemins en haut à gauche du compteur d'heures ci-dessous.

Ensuite, prenez l'électron toutes les douze heures et divisez-le en un toutes les heures, mais sortez-les chacun sur un fil conducteur différent. Ceci est réalisé en utilisant le long conducteur enroulé avec treize points de sortie.

Prenez ces électrons - un par heure dans différents conducteurs, et frappez une ligne SET de bascule. La ligne RESET sur cette même bascule est alors frappée par le conducteur de l'heure suivante, donnant soixante impulsions sur chaque fil par heure.

Enfin - prenez ces impulsions et passez-les dans sept octets et demi de ROM (mémoire morte) pour sortir les flux binaires BCD corrects. Voir ici pour une explication plus détaillée de la ROM WireWorld: http://www.quinapalus.com/wires6.html

Conception

Compteur d'heures annoté

  1. Un électron par heure d'entrée.
  2. Premier verrou.
  3. Première prise.
  4. "Latch & catch" intégré sur une ligne SET "latch & catch" externe.
  5. ET porte.
  6. Verrou AM / PM (activé / désactivé toutes les douze heures).
  7. Chaque boucle de fil mesure 6x60 = 360 unités.
  8. Flip / Flop tourné sur le côté pour créer un profil plus petit.
  9. Sept octets et demi de ROM.

Remarques

  1. En raison de sa conception à un électron par minute et à 6 microns, exécutez la simulation à six générations par minute (une génération toutes les 10 secondes) pour une horloge en temps réel.
  2. La ligne AM / PM est haute (1) pour AM, basse (0) pour PM. Cela peut sembler une façon de procéder un peu inhabituelle, mais il y a une justification. Lors d'un démarrage à froid de l'horloge, la ligne AM / PM est naturellement basse (0) au départ. Dès que la ligne AM / PM est tirée haut (1), cela indique que le comptage a commencé à 00h00. Toute sortie avant ce point doit être ignorée, toute sortie après ce point est considérée comme significative.

Liens utiles

niemiro
la source
exigences modifiées afin que les sorties toujours nulles puissent être omises. les bits 4s et 8s pour les dizaines d'heures ne sont jamais utilisés, ni le bit 8s pour les dizaines de minutes.
Sparr
Solide! Véritable ingénierie. Est-ce que l'une des autres portes logiques aurait été utile? Je suis sur le point d'en forcer brutalement certains.
wyldstallyns
1
C'est beau
Sparr
1
Oh mon deuil qui est juste assez proche maintenant, je suis obligé d'essayer d'optimiser le mien. J'ai des motifs répétitifs que je pourrais raccourcir pour faire de la place aux autres.
wyldstallyns
3
Je ne sais pas à quel point vous êtes actif sur les méta, c'est pour vous faire savoir que j'ai nommé cette réponse pour le Best of PPCG 2016 .
Peter Taylor
5

Mémoire de ligne à retard - 51 x 2880 = 146880

Image

Zoom arrière:

Image

La sortie sort du haut de chaque boucle.

Je mets tous les états directement sur le fil avec cette lua, laissant golly les électrons avancer entre les bits afin que nous n'ayons pas à suivre le fil avec un curseur.

J'ai utilisé cette méthode naïve pour définir une barre et un cours accéléré wireworld, golly et lua.

local g = golly()

local minutes_in_day = 1440 -- 60x24
local interval = 4 -- how often to send electrons

local function bcd4(num)
    num=math.floor(num)
    local t={}
    for b=4,1,-1 do
        t[b]=math.floor(math.fmod(num,2))
        num=(num-t[b])/2
    end
    return table.concat(t)
end

local function makewire(x,y1,y2)
    for y1=1,y2 do g.setcell(x,y1,3) end
end

local function makeloop(x,y,size)
    local len = size/2 - 1
    makewire(x,y+1,len); makewire(x+2,y+1,len) -- main wires
    g.setcell(x+1,y,3); g.setcell(x+1,y+len,3) -- endcape
end

local function paint(x,y,pattern)
    for v in string.gmatch(pattern,".") do
        if v=="1" then g.setcell(x, y, 1); g.setcell(x, y-1, 2) end
        x = x + 4
    end
    g.show(pattern);g.update() -- slows things down but more interesting to watch
    for i=1,interval do g.step() end
end

for x=0,63,4 do makeloop(x,0,minutes_in_day * interval) end

for hour = 0,23 do
      for minute = 0,59 do
         paint( 0, 2, bcd4(hour/10) .. bcd4(hour%10) .. bcd4(minute/10) .. bcd4(minute%10) )
      end
end

Pour les tests, j'ai ajouté ces fils supérieurs et j'ai regardé leurs conseils.

Imgur

Voici le script pour collecter les 4 ensembles de BCD 4 fils au globe oculaire.

-- watches 16 wires spaced 4 apart starting at (0,-4)
local ticks = 1440 -- set to match the length of your 24 hour loop
local g = golly()
local output = ""
local nums = {  ["0000"] = "0", ["0001"] = "1", ["0010"] = "2", ["0011"] = "3", ["0100"] = "4",
                ["0101"] = "5", ["0110"] = "6", ["0111"] = "7", ["1000"] = "8", ["1001"] = "9",
                ["1010"] = "A", ["1011"] = "B", ["1100"] = "C", ["1101"] = "D", ["1110"] = "E",
                ["1111"] = "F" } -- full set in case we have errors (i did)

for i=0,ticks,1 do
   local text = ""
   for i=0,48,16 do -- set your X here, change the 0 and 48
       local word = ""
       for j=0,15,4 do
            local bit = g.getcell(i+j,-4) -- set your Y here, change -4
            if bit == 0 or bit == 3 then word = word .. "0" else word = word .. "1" end
       end
       text = text .. nums[word]
   end
   g.show(text); output = output..' '..text
   g.update(); g.step();g.step();g.step();g.step()
end
g.note(output)

La réponse finale nécessite l'élagage des lignes toujours nulles et le routage du reste vers leurs entrées BCD correctes.

wyldstallyns
la source
exigences modifiées afin que les sorties toujours nulles puissent être omises. les bits 4s et 8s pour les dizaines d'heures ne sont jamais utilisés, ni les bits 8s pour les dizaines de minutes.
Sparr
2
Il s'agit d'une implémentation hilarante et impressionnante!
Sparr
1
Ok j'ai été battu avec une autre horloge fonctionnelle à la 11ème heure. Je vais attaquer les boucles les plus longues et les plus courtes avec différentes astuces.
wyldstallyns
Je ne vais pas le retirer. Je peux économiser 1 / 4e de la taille en passant à des impulsions de 3 microns, mais il ne sera toujours pas assez serré pour battre niemiro.
wyldstallyns