Costruisci un orologio digitale in Wireworld


32

Ispirato da questa domanda di Game of Life .

Wireworld simula gli "elettroni" che fluiscono attraverso i "fili", le cui disposizioni semplici producono il tipico comportamento del gate logico.

Ti sfido a costruire un orologio digitale nell'automa cellulare Wireworld. L'orologio deve contare verso l'alto dalle 00:00 alle 23:59 come di consueto, oppure fino alle 11:59 con un indicatore AM / PM, quindi resettare.

La tua voce dovrebbe essere visibilmente divisa in due parti. La parte A dovrebbe contenere tutta la logica di non visualizzazione, tutte le parti coinvolte nell'incremento e nel loop delle cifre. La parte B sarà il display e la logica che lo guida. L'unica connessione tra queste due parti dovrebbe essere 16 fili che rappresentano le quattro cifre dell'ora in BCD (con un filo opzionale per l'indicatore AM / PM e un filo opzionale per una linea di segnale se i segnali non sono continui). (EDIT: i cavi sempre zero possono essere omessi)

I tempi del comportamento dell'orologio dovrebbero essere coerenti. La simulazione dovrebbe assumere lo stesso numero di tick per ciascuna delle 1440 transizioni tra stati. Tutti gli elettroni sui 16 fili dovrebbero essere emessi dalla parte A contemporaneamente e iniziare il loro viaggio in parallelo.

Questa è una competizione di code-golf. Il tuo punteggio è l'area del riquadro di delimitazione allineato all'asse che circonda la parte A.

Per analogia, se questo fosse un linguaggio testuale, il tuo punteggio sarebbe la dimensione della funzione di gestione del clock che produce quattro output a 4 bit, che contiene un loop e la logica per 4 contatori, non la funzione che decodifica e stampa quell'output.

La tua parte B può essere grande o piccola come desideri. È necessario solo affinché l'output del tuo invio possa essere visto da qualcuno che lo esegue, poiché non esiste un modo semplice per "eseguire il debug" degli output da un circuito wireworld. Ci sono più circuiti BCD-> 7 segmenti disponibili online. Sentiti libero di usare quello che preferisci o creane uno tuo se hai bisogno di una linea di segnale con clock e mostra il tuo indicatore AM / PM su una scala simile alle cifre.

EDIT: la parte B è ora facoltativa. Se hai solo le uscite BCD dalla tua parte A, sentiti libero di inviarlo. Sarà più noioso confermare che l'orologio funziona, ma posso leggere una fila di bit bene in una simulazione in pausa.


Ecco un piccolo simulatore online.
NonlinearFruit

Ci ho lavorato ma l'ho visto solo la scorsa settimana, quindi probabilmente mi mancherà la taglia. Non riesco a trovare una versione a 4 fili di un wireworld bcd-> 7 segmenti; costruire un convertitore da 4 a 2 di fronte al popolare dispositivo a 7 segmenti a 2 fili (come quello fornito in dotazione) può essere la strada da percorrere. Un problema con quel dispositivo è che, sebbene sia bello, è lento da aggiornare, il che gonfia le dimensioni della Parte A perché può pompare i numeri più velocemente di quanto possano essere visualizzati e deve essere rallentato artificialmente.
wyldstallyns,

Ho una parte funzionante di 150.000 celle che posso dimostrare che funziona ma che attualmente non ha una parte B. conforme alle
regole

Non mi aspettavo che la parte B fosse difficile. Quanto distanti sono i tuoi elettroni nella parte A?
Sparr,

1
@wyldstallyns Si chiude il 16/12/2016 alle 03:30: 35Z (puoi passare con il mouse su "domani" per ottenere gli orari precisi). Buona fortuna a te. Mi piace davvero il tuo orologio. È un'idea elegantemente semplice e un'esecuzione eccellente. Devo ammettere di essere stato anche sorpreso da quanto spazio alla fine il mio ha finito. E sarei interessato a vedere eventuali miglioramenti che puoi trovare nel tuo. Quindi, buona fortuna :)
niemiro,

Risposte:


36

Orologio a scatto

Punteggio - 53.508 (di cui solo 36.828 sono attivamente utilizzati a causa del design a forma di L)

Orologio in esecuzione

Registrazione di alta qualità - https://1drv.ms/u/s!ArQEzxH5nQLKhvt_HHfcqQKo2FODLQ
Modello Golly - https://1drv.ms/u/s!ArQEzxH5nQLKhvwAmwCY-IPiBuBmBw

Principi guida -

  • Dato che era la prima volta che usavo un automa cellulare, evitavo di mettere insieme componenti premade di grandi dimensioni. Un approccio valido che non ho adottato sarebbe stato un sommatore binario a partire da zero e aggiungendo continuamente uno all'ultima uscita, seguito da un convertitore da binario a BCD, demultiplexer di visualizzazione, decodificatore a 7 segmenti e display a 7 segmenti.
  • Dovrebbe essere possibile avviare a freddo l'orologio. Mi sono imposto la restrizione aggiuntiva che una singola testa di elettrone posizionata in una specifica cella di conduttore dovrebbe avviare correttamente l'orologio. Non volevo richiedere un'attenta sincronizzazione manuale di molti diversi infradito e singoli elementi di temporizzazione prima di iniziare la simulazione.

Parte I: il contatore dei minuti

Matematica

Il conteggio da 0 a 9 in binario (per la cifra dei minuti meno significativa) procede come segue:

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

Leggendo che come colonne, il flusso meno significativo (flusso di bit 2 ^ 0 unità) va 01010101, il flusso di unità 2 ^ 1 va 0011001100, il flusso di unità 2 ^ 2 va 0000111100 e il flusso di unità 2 ^ 3 va 0000000011.

Il primo è facile: basta capovolgere 01 per sempre. Il terzo è un flusso di quattro 1, sei 0, sfasati di sei zeri. Il quarto è un flusso di otto 0 e due 1.

Il secondo è un po 'più difficile in quanto ha una brutta asimmetria. Tuttavia, noto che (dove. È operatore concat):

0011001100. 0011001100 = 0011001100. NOT (1100110011) = 00110011001100110011 XOR 00000000001111111111 = 5 (0011) XOR 00000000001111111111

(Per inciso, come accennato in seguito, la maggior parte del mio orologio gira su un ticker a 60 battute. L'onda a doppia lunghezza 00000000001111111111 è dove arriva la necessità del ticker a 120 battute).

Design

I flussi di output dall'alto verso il basso vanno Unità di minuti (2 ^ 0, 2 ^ 1, 2 ^ 2, 2 ^ 3) quindi Decine di minuti (2 ^ 0, 2 ^ 2, 2 ^ 1). Si noti che i due fili inferiori sono incrociati.

Contatore dei minuti annotato

  1. Orologio principale a 120 battute.
  2. Dove posizionare un elettrone per un avviamento a freddo. Senza alcuna coda di elettroni si divide in due direzioni, ma il diodo immediatamente sopra cattura uno di questi dando un piacevole elettrone ciclico che gira e gira intorno al ciclo di 120 battute.
  3. Orologio secondario a 12 battute.
  4. La bobina del conduttore + diodo avvia l'orologio a 12 battute secondario. Le parole non possono descrivere quanto faticosamente questo piccolo pezzo fosse sincronizzato. Devi sincronizzare i clock di 120 e 60 beat, quindi sincronizzare negli pseudo clock di 24-beat a 12-beat e halver in frequenza a 24-beat, seguiti da ricollegare il clock a 24-beat al clock a 120-beat altrimenti il ​​gate XOR non funziona .
  5. Sfasamento.
  6. Ciabatte infradito. Un singolo elettrone sull'ingresso colpisce prima la linea impostata, quindi dopo un tempo molto specifico, colpisce la linea di ripristino dando esattamente un impulso in entrata, un impulso in uscita.
  7. Aggiungendo qui le gobbe - sulla linea di reset, aumenta il ritardo tra set e reset sul flip-flop. Ogni gobba in più dà un impulso in più. Il flip-flop sotto ha nove gobbe extra, quindi dieci impulsi tra set e reset.
  8. Porta XOR per la mia linea di 2 ^ 1 unità di minuti complicata.
  9. La porta AND-NOT e le lunghezze delle parti molto specifiche significano che ogni impulso di elettroni che passa raddoppia su se stesso e annichilisce l'elettrone dietro. Dimezzatore di frequenza. Crea un clock a 24 battute dalla sorgente secondaria a 12 battute.
  10. Orologio secondario a 60 battute, che in realtà svolge la maggior parte del lavoro. È solo più facile avviare un orologio veloce da uno più lento, quindi l'orologio più lento (120 battiti) è il master, anche se viene usato a malapena. L'orologio a 60 battiti è il cuore di questa cosa.
  11. Cavo di feedback che trasporta elettroni solo quando il cronometro a 60 battiti ticchetta. Viene utilizzato in combinazione con un gate AND-NOT per impedire il riavvio ripetuto dell'orologio dal master a 120 battute. Altrimenti accadono molte cose orribili e Ctrl-Z è salvatore.
  12. Il diodo da cui parte l'orologio a 60 battute.
  13. L'intero dispositivo è un flip flop, AND gate e AND-NOT gate combinati. Dà un fermo. Un impulso dentro lo avvia, un impulso dentro lo interrompe.
  14. Ciclo di filo per calibrare il fermo a 10 impulsi on, 10 impulsi off per un ingresso impulso uno su dieci. Senza di essa otteniamo 12 impulsi, 8 impulsi disattivati. Questi fermi da dieci a dieci formano i componenti di base dei blocchi da dieci minuti nello stesso modo in cui le infradito da 6 micron (1 impulso) costituivano i componenti di base delle unità dei minuti.
  15. L'impulso iniziale di avvio a freddo ha causato tutti i tipi di problemi, tra cui l'essere due battiti sfasati con gli orologi che inizia. Questo incasina i chiavistelli. Questa porta AND cattura e elimina gli impulsi non sincronizzati, in particolare l'impulso iniziale.
  16. Questa è una parte del progetto che in qualche modo mi pento in retrospettiva. Prende un elettrone, lo divide in cinque e annichilisce i cinque elettroni dietro, portando da 111111 a 100000.
  17. Questo prende un elettrone e lo ricama sul davanti. Due fasi future per essere precisi. Ci vogliono 100000 e fanno 101000. In combinazione con la parte 16 otteniamo 111111 -> 100000 -> 101000. A posteriori vorrei aver fatto 111111 -> 101010 -> 101000; avrebbe ottenuto lo stesso effetto in meno spazio.
  18. I suddetti motivi vengono quindi inseriti nel fermo inferiore per ottenere 20 on, 40 off. Questo è diviso, metà è sfasata di 20 unità e quindi formano i due flussi di bit di alto ordine delle decine di minuti.

Parte II: il contatore delle ore

Spiegazione

L'ingresso al contatore delle ore è un singolo impulso elettronico, una volta ogni ora. Il primo passo è ridurre questo a un singolo impulso elettronico, una volta ogni dodici ore. Ciò si ottiene utilizzando diverse primitive "latch & catch".

Un "latch" è un flip-flop da 6 micron collegato a un AND-NOT e un gate AND per fornire un latch on / off da 6 micron. Una "cattura" prende un flusso continuo di elettroni come input, consente il primo passaggio, quindi annichilisce ogni altro elettrone dietro, fino a quando il flusso termina a quel punto la cattura si reimposta.

Se si posiziona un fermo, seguito da un fermo, in serie, si ottiene un elettrone in -> attiva il fermo, un elettrone fuori dall'altra estremità (resto bloccato dal fermo). Quindi il secondo elettrone in -> disattiva il fermo, la cattura si ripristina silenziosamente. Effetto netto: il primo elettrone passa attraverso, il secondo elettrone viene annientato, e così via e così via, indipendentemente da quanto tempo è il ritardo tra quegli elettroni .

Ora incatena due "latch & catch" in serie e hai solo un elettrone su quattro che passa attraverso.

Quindi, prendi un terzo "latch and catch", ma questa volta incorpora un intero quarto latch e cattura la linea SET flip-flop, tra il gate AND-NOT e il SET flip-flop. Ti lascio pensare a come funziona, ma questa volta passa solo un elettrone su tre, indipendentemente da quanto tempo è il ritardo tra quegli elettroni .

Infine, prendi uno su quattro elettroni e uno su tre, combinali con una porta AND e solo uno su dodici elettroni passa attraverso. Tutta questa sezione è la confusione disordinata di percorsi in alto a sinistra del contatore delle ore in basso.

Quindi, prendi l'elettrone ogni dodici ore e ripartiscilo in uno ogni ora, ma invia ciascuno su un filo conduttore diverso. Ciò si ottiene utilizzando il conduttore a spirale lunga con tredici punti di uscita.

Prendi questi elettroni, uno all'ora lungo diversi conduttori, e colpisci una linea SET flip-flop. La linea RESET su quello stesso flip flop viene quindi colpita dal conduttore dell'ora successiva, dando sessanta impulsi in giù ogni filo all'ora.

Infine, prendi questi impulsi e passali in sette byte e mezzo di ROM (memoria di sola lettura) per produrre i flussi di bit BCD corretti. Vedere qui per una spiegazione più dettagliata della ROM WireWorld: http://www.quinapalus.com/wires6.html

Design

Contatore orario annotato

  1. Un ingresso elettronico per ora.
  2. Primo fermo.
  3. Prima cattura.
  4. "Latch & catch" incorporato in una linea SET "latch & catch" esterna.
  5. E cancello.
  6. Latch AM / PM (acceso / spento una volta ogni dodici ore).
  7. Ogni anello di filo ha una lunghezza di 6x60 = 360 unità.
  8. Flip / Flop ruotato su un lato per creare un profilo più piccolo.
  9. Sette e mezzo byte di ROM.

Gli appunti

  1. Grazie al suo un elettrone al minuto, design da 6 micron, esegui la simulazione a sei generazioni al minuto (una generazione ogni 10 secondi) per un orologio in tempo reale.
  2. La linea AM / PM è alta (1) per AM, bassa (0) per PM. Questo potrebbe sembrare un modo leggermente insolito di scegliere, ma c'è una giustificazione. Durante un avvio a freddo dell'orologio, la linea AM / PM inizialmente è naturalmente bassa (0). Non appena la linea AM / PM viene alzata (1), ciò indica che il conteggio è iniziato alle 12:00. Tutto l'output prima di questo punto deve essere ignorato, tutto l'output dopo questo punto è considerato significativo.

link utili


requisiti modificati in modo da poter omettere le uscite sempre zero. i bit 4s e 8s per le decine di ore non vengono mai utilizzati, né gli 8s bit per le decine di minuti.
Sparr,

Solido! Vera ingegneria. Qualcuna delle altre porte logiche sarebbe stata utile? Sto per forzare un po 'la forza.
wyldstallyns,

1
È bellissimo
Sparr il

1
Oh buon dolore che è appena abbastanza vicino ora sto costretto a cercare di ottimizzare il mio. Ho ripetuti schemi che potrei accorciare per fare spazio per piegare gli altri.
wyldstallyns,

3
Non so quanto tu sia attivo su meta, quindi questo per farti sapere che ho nominato questa risposta per il meglio di PPCG 2016 .
Peter Taylor,

5

Memoria della linea di ritardo - 51 x 2880 = 146880

Immagine

Zoom indietro:

Immagine

L'output esce dalla cima di ogni loop.

Ho messo tutti gli stati direttamente sul filo con questo lua, facendo gollyavanzare gli elettroni tra i bit in modo da non dover seguire il filo con un cursore.

Ho usato questo metodo ingenuo per impostare un bar e un corso di crash wireworld, golly e 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

Per i test ho aggiunto questi fili superiori e ho visto i loro suggerimenti.

Imgur

Ecco lo script per raccogliere i 4 set di BCD a 4 fili sul bulbo oculare.

-- 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 risposta finale richiede la potatura delle linee sempre zero e l'instradamento del resto ai loro ingressi BCD corretti.


requisiti modificati in modo da poter omettere le uscite sempre zero. i bit 4s e 8s per le decine di ore non vengono mai utilizzati, né i bit 8s per le decine di minuti.
Sparr,

2
Questa è un'implementazione divertente e fantastica!
Sparr,

1
Ok, sono stato battuto con un altro orologio funzionale all'undicesima ora. Ho intenzione di attaccare i loop più lunghi e più brevi con diversi trucchi.
wyldstallyns,

Non lo farò. Posso salvare 1/4 della dimensione passando a impulsi da 3 micron, ma non si avvolgerà mai abbastanza forte da battere Niemiro.
wyldstallyns,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.