Construye un reloj digital en Wireworld

32

Inspirado en esta pregunta de Game of Life .

Wireworld simula los "electrones" que fluyen a través de los "cables", cuyos arreglos simples producen el comportamiento típico de la puerta lógica.

Te desafío a construir un reloj digital en el autómata celular Wireworld. Su reloj debe contar hacia arriba de 00:00 a 23:59 de la manera habitual, o hasta las 11:59 con un indicador AM / PM, luego reiniciar.

Su entrada debe estar visiblemente dividida en dos partes. La Parte A debe contener toda la lógica de no visualización, todas las partes involucradas en el incremento y el bucle de los dígitos. La Parte B será la pantalla y la lógica que lo impulsa. La única conexión entre estas dos partes debe ser 16 cables que representan los cuatro dígitos del tiempo en BCD (con un cable opcional para el indicador AM / PM y un cable opcional para una línea de reloj de señal si sus señales no son continuas). (EDITAR: siempre se pueden omitir cables cero)

El momento del comportamiento del reloj debe ser consistente. La simulación debería tomar la misma cantidad de ticks para cada una de las 1440 transiciones entre estados. Todos los electrones en los 16 cables deben emitirse desde la parte A al mismo tiempo y comenzar su viaje en paralelo.

Esta es una competencia de código de golf. Su puntaje es el área del cuadro delimitador alineado con el eje que rodea la parte A.

Por analogía, si este fuera un lenguaje textual, su puntaje sería el tamaño de la función de gestión del reloj que produce cuatro salidas de 4 bits, que contiene un bucle y la lógica para 4 contadores, no la función que decodifica e imprime esa salida.

Su parte B puede ser tan grande o pequeña como desee. Solo es necesario para que alguien que lo ejecute pueda ver la salida de su envío, ya que no hay una manera fácil de simplemente "depurar" las salidas de un circuito de mundo de cables. Hay varios circuitos BCD-> 7 segmentos disponibles en línea. Siéntase libre de usar el que desee, o haga el suyo si necesita una línea de señal sincronizada, y muestre su indicador AM / PM a una escala similar a los dígitos.

EDITAR: la Parte B ahora es opcional. Si solo tiene las salidas BCD de su parte A, no dude en enviarlas. Será más tedioso confirmar que el reloj funciona, pero puedo leer una fila de bits muy bien en una simulación en pausa.

Sparr
fuente
Aquí hay un pequeño simulador en línea.
NonlinearFruit
He estado trabajando en esto, pero solo lo vi la semana pasada, así que probablemente extrañaré la recompensa. No puedo encontrar una versión de 4 hilos de un mundo bcd-> 7 segmentos; Construir un convertidor de 4 a 2 frente al popular dispositivo de 2 hilos y 7 segmentos (como el que viene con Golly) puede ser el camino a seguir. Un problema con ese dispositivo es que, aunque tiene un aspecto agradable, su actualización es lenta, lo que aumentará el tamaño de la Parte A porque puede bombear los números más rápido de lo que se pueden mostrar y debe reducirse artificialmente.
wyldstallyns
Tengo una célula 150.000 de trabajo Parte A que puedo demostrar las obras, pero actualmente carece de una Parte B. conforme con las reglas
wyldstallyns
No esperaba que la parte B fuera difícil. ¿A qué distancia están sus electrones en la parte A?
Sparr
1
@wyldstallyns Cierra a las 16/12/2016 03: 30: 35Z (puede desplazarse sobre el 'mañana' para obtener los horarios precisos). La mejor de las suertes para ti. Realmente me gusta tu reloj. Es una idea elegante y simple y una excelente ejecución. Debo admitir que también me sorprendió la cantidad de espacio que la mina terminó ocupando al final. Y me interesaría ver cualquier mejora que pueda encontrar en la suya. Entonces, la mejor de las suertes :)
niemiro

Respuestas:

36

Reloj de enganche

Puntuación: 53,508 (de los cuales solo 36,828 se usan activamente debido al diseño en forma de L)

Reloj corriendo

Grabación de alta calidad - https://1drv.ms/u/s!ArQEzxH5nQLKhvt_HHfcqQKo2FODLQ
Patrón Golly - https://1drv.ms/u/s!ArQEzxH5nQLKhvwAmwCY-IPiBuBmBw

Principios rectores -

  • Como era la primera vez que usaba un autómata celular, evité unir componentes prefabricados grandes. Un enfoque válido que no adopté habría sido un sumador binario que comience en cero y agregue continuamente uno a la última salida, seguido de un convertidor binario a BCD, demultiplexor de pantalla, decodificador de 7 segmentos y pantalla de 7 segmentos.
  • Debería ser posible iniciar el reloj en frío. Me impuse la restricción adicional de que una sola cabeza de electrones colocada en una celda conductora específica debería iniciar correctamente el reloj. No quería requerir una cuidadosa sincronización manual de muchos flip-flops dispares y elementos de sincronización individuales antes de comenzar la simulación.

Parte I: El contador de minutos

Matemáticas

El conteo de 0 a 9 en binario (para el dígito de minutos menos significativo) es el siguiente:

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

Leyendo que como columnas, el flujo menos significativo (2 ^ 0 unidades de bits) va 01010101, el flujo de 2 ^ 1 unidades va 0011001100, el flujo de 2 ^ 2 unidades va 0000111100 y el flujo de 2 ^ 3 unidades va 0000000011.

El primero es fácil: solo voltear y voltear 01 para siempre. El tercero es un flujo de cuatro 1s, seis 0s, fase desplazada por seis ceros. El cuarto es un flujo de ocho ceros y dos ceros.

El segundo es un poco más difícil ya que tiene una asimetría desagradable. Sin embargo, noto que (donde. Es operador concat):

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

(Por cierto, como se mencionó más adelante, la mayoría de mi reloj funciona con un ticker de 60 latidos. La onda de doble longitud 00000000001111111111 es donde entra en juego la necesidad del ticker de 120 latidos).

Diseño

Los flujos de salida de arriba a abajo van Unidades de minutos (2 ^ 0, 2 ^ 1, 2 ^ 2, 2 ^ 3) y luego Decenas de minutos (2 ^ 0, 2 ^ 2, 2 ^ 1). Tenga en cuenta que los dos cables inferiores están cruzados.

Contador de minutos anotado

  1. Reloj principal de 120 tiempos.
  2. Dónde colocar un electrón para un arranque en frío. Sin ninguna cola de electrones, se divide en dos direcciones, pero el diodo inmediatamente superior atrapa uno de estos, lo que da un buen electrón que gira y rodea el bucle de 120 latidos.
  3. Reloj secundario de 12 tiempos.
  4. La bobina del conductor + diodo inicia el reloj secundario de 12 tiempos. Las palabras no pueden describir lo difícil que era sincronizar esta pequeña pieza. Debe sincronizar los relojes de 120 y 60 tiempos, luego sincronizar en los pseudo relojes de 12 tiempos y frecuencia media de 24 tiempos, seguido de atar el reloj de 24 tiempos al reloj de 120 tiempos, de lo contrario la puerta XOR no funciona .
  5. Cambio de fase.
  6. Chanclas. Un solo electrón en la entrada golpea primero la línea establecida y luego, después de un período de tiempo muy específico, golpea la línea de reinicio dando exactamente un pulso de entrada, un pulso de salida.
  7. Agregar jorobas aquí: en la línea de reinicio, aumenta el retraso entre el ajuste y el reinicio en el flip-flop. Cada joroba extra da un pulso extra. El flip-flop a continuación tiene nueve jorobas adicionales, por lo que diez pulsos entre establecer y restablecer.
  8. Puerta XOR para mi difícil línea de 2 ^ 1 unidades de minutos.
  9. La compuerta AND-NOT y las longitudes de pieza muy específicas significan que cada pulso de electrones que pasa se duplica sobre sí mismo y aniquila el electrón detrás. Frecuencia a la mitad. Crea un reloj de 24 tiempos a partir de la fuente secundaria de 12 tiempos.
  10. Reloj secundario de 60 tiempos, que en realidad hace la mayor parte del trabajo. Es más fácil comenzar un reloj rápido desde uno más lento, por lo que el reloj más lento (120 latidos) es el maestro, aunque apenas se usa. El reloj de 60 latidos es el corazón de esta cosa.
  11. Cable de retroalimentación que transporta electrones solo cuando el reloj de 60 latidos está funcionando. Se usa junto con una compuerta AND-NOT para evitar que el reloj se reinicie repetidamente desde el maestro de 120 latidos. De lo contrario, suceden muchas cosas horribles y Ctrl-Z es el salvador.
  12. El diodo desde donde se inicia el reloj de 60 latidos.
  13. Todo este dispositivo es un flip flop, una compuerta AND y una compuerta AND-NOT combinadas. Le da un pestillo. Un pulso lo inicia, un pulso lo detiene.
  14. Lazo de cable para calibrar el pestillo a 10 pulsos encendidos, 10 pulsos apagados para una entrada de uno en diez pulsos. Sin ella tenemos 12 pulsos encendidos, 8 pulsos apagados. Estos cierres de diez en diez forman los componentes básicos de los bloques de diez minutos de la misma manera que las chanclas de 6 micrones (1 pulso) formaron los componentes básicos de las unidades de minutos.
  15. El pulso inicial de arranque en frío causó todo tipo de problemas, incluyendo estar dos latidos desfasados ​​con los relojes que arranca. Esto arruina los pestillos. Esta compuerta AND captura y elimina los impulsos no sincronizados, en particular el impulso inicial.
  16. Esta es una parte del diseño que de alguna manera lamento en retrospectiva. Toma un electrón, lo divide en cinco y aniquila los cinco electrones detrás, llevando 111111 a 100000.
  17. Esto toma un electrón y lo cose en el frente. Dos fases por delante para ser precisos. Toma 100000 y hace 101000. Combinado con la parte 16 obtenemos 111111 -> 100000 -> 101000. En retrospectiva, desearía haber hecho 111111 -> 101010 -> 101000; habría logrado el mismo efecto en menos espacio.
  18. Luego, los patrones anteriores se empujan hacia el pestillo inferior para lograr 20 encendido, 40 apagado. Esto se divide, la mitad se desplaza en fase por 20 unidades, y luego forman las dos corrientes de bits de orden superior de las decenas de minutos.

Parte II: El contador de horas

Explicación

La entrada al contador de horas es un pulso electrónico único, una vez por hora. El primer paso es reducir esto a un solo pulso de electrones, una vez cada doce horas. Esto se logra utilizando varias primitivas de "enganche y captura".

Un "pestillo" es un flip-flop de 6 micrones conectado a un AND-NOT y una compuerta AND para proporcionar un pestillo de encendido / apagado de 6 micrones. Una "captura" toma una corriente continua de electrones como entrada, permite el primer paso, luego aniquila todos los demás electrones detrás, hasta que la corriente termina en ese punto la captura se restablece.

Colocar un pestillo, seguido de una captura, en serie, da como resultado que un electrón entre -> enciende el pestillo, un electrón sale del otro extremo (el resto queda atrapado por la captura). Luego, el segundo electrón en -> apaga el pestillo, la captura se reinicia en silencio. Efecto neto: el primer electrón pasa a través, el segundo electrón se aniquila, y así sucesivamente, independientemente de cuánto tiempo transcurra el retraso entre esos electrones .

Ahora encadene dos "pestillos y capturas" en serie, y solo tendrá que pasar uno de cada cuatro electrones.

A continuación, tome un tercer "pestillo y atrape", pero esta vez incruste un cuarto pestillo y atrape en la línea SET de flip-flop, entre la puerta AND-NOT y el SET de flip-flop. Te dejo para que pienses cómo funciona esto, pero esta vez solo uno de cada tres electrones pasa, independientemente de cuánto tiempo transcurra el retraso entre esos electrones. .

Finalmente, tome el uno de cada cuatro electrones, y el uno de cada tres, combínelos con una puerta AND, y solo uno de cada doce electrones pasa. Toda esta sección es el desordenado garabato de caminos hacia la parte superior izquierda del contador de horas a continuación.

Luego, tome el electrón cada doce horas y vuelva a dividirlo en uno cada hora, pero envíe cada uno a un cable conductor diferente. Esto se logra utilizando el conductor en espiral largo con trece puntos de salida.

Tome estos electrones, uno por hora por diferentes conductores, y golpee una línea SET de flip-flop. La línea RESET en ese mismo flip flop es golpeada por el conductor de la siguiente hora, dando sesenta pulsos por cada cable por hora.

Finalmente, tome estos pulsos y páselos a siete bytes y medio de ROM (memoria de solo lectura) para generar los flujos de bits BCD correctos. Consulte aquí para obtener una explicación más detallada de WireWorld ROM: http://www.quinapalus.com/wires6.html

Diseño

Contador de horas anotado

  1. Un electrón por hora de entrada.
  2. Primer pestillo.
  3. Primera captura
  4. "Latch & catch" incrustado en una línea externa "pestillo y captura" SET.
  5. Y puerta.
  6. Cierre de AM / PM (encendido / apagado una vez cada doce horas).
  7. Cada lazo de cable es de 6x60 = 360 unidades de largo.
  8. Flip / Flop se volvió hacia un lado para crear un perfil más pequeño.
  9. Siete y medio bytes de ROM.

Notas

  1. Debido a su diseño de 6 micras de un electrón por minuto, ejecute la simulación a seis generaciones por minuto (una generación cada 10 segundos) para un reloj en tiempo real.
  2. La línea AM / PM es alta (1) para AM, baja (0) para PM. Puede parecer una forma un poco inusual de elegir, pero hay justificación. Durante un arranque en frío del reloj, la línea AM / PM es naturalmente baja (0) inicialmente. Tan pronto como la línea AM / PM se pone alta (1), esto indica que el conteo ha comenzado a las 12:00 AM. Toda salida antes de este punto debe ser descartada, toda salida después de este punto se considera significativa.

Enlaces útiles

niemiro
fuente
requisitos modificados para que se puedan omitir salidas siempre cero. los bits 4s y 8s para las decenas de horas nunca se usan, ni los bits 8s para decenas de minutos.
Sparr
¡Sólido! Verdadera ingeniería. ¿Alguna de las otras puertas lógicas habría sido útil? Estoy a punto de forzar la fuerza bruta.
wyldstallyns
1
Esto es hermoso
Sparr
1
Oh, Dios mío, está lo suficientemente cerca ahora que me veo obligado a intentar optimizar el mío. Tengo patrones repetitivos que podría acortar para hacer espacio para doblar a otros.
wyldstallyns
3
No sé qué tan activo eres en meta, así que esto es para hacerte saber que he nominado esta respuesta para el Mejor de PPCG 2016 .
Peter Taylor
5

Memoria de línea de retardo: 51 x 2880 = 146880

Imagen

Alejado:

Imagen

La salida sale de la parte superior de cada bucle.

Puse todos los estados directamente en el cable con este lua, dejando golly los electrones avancen entre los bits para que no tengamos que seguir el cable con un cursor.

Utilicé este método ingenuo para establecer un bar y un curso acelerado de Wireworld, Golly y 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

Para probar agregué estos cables superiores y observé sus consejos.

Imgur

Aquí está la secuencia de comandos para recopilar los 4 conjuntos de BCD de 4 hilos al globo ocular.

-- 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 respuesta final requiere la poda de las líneas siempre cero y enrutar el resto a sus entradas BCD correctas.

wyldstallyns
fuente
requisitos modificados para que las salidas siempre nulas puedan omitirse. los bits 4s y 8s por decenas de horas nunca se usan, ni los bits 8s por decenas de minutos.
Sparr
2
¡Esta es una implementación hilarante y asombrosa!
Sparr
1
Ok, he sido vencido con otro reloj funcional a la hora 11. Voy a atacar los bucles más largos y más cortos con diferentes trucos.
wyldstallyns
No voy a lograrlo. Puedo ahorrar 1/4 de tamaño cambiando a pulsos de 3 micras, pero todavía no se enrollará lo suficiente como para vencer a niemiro.
wyldstallyns