Урок 6 (бонус). Munching Squares: живой узор 1962 года

В картинках

После этого урока на третьем экране оживёт узор из «жующих» квадратов — одна из первых компьютерных анимаций. В 1962 году её написали программой на PDP-1, мы соберём её логикой.


6.1. Идея: (x XOR y) < t

Точка горит, если (x XOR y) < t, а t растёт на 1 после каждого кадра. При маленьком t горит узкая полоса вдоль диагонали, с каждым кадром от неё отрастают квадраты, «съедают» экран — и всё начинается снова.

t = 4t = 12t = 28t = 48
Кадры Munching Squares: при t = 4 горит полоса вдоль диагонали, с каждым кадром от неё отрастают квадраты всё больше. При t = 64 горит весь экран, потом t снова 0.
  • t — ещё один CNT6, он считает кадры; шаг ему разрешает cy — перенос счётчика строки на последней точке кадра;
  • x XOR y — 6 XOR;
  • v < t — цепочка сравнения от младшего разряда к старшему: разряд говорит «меньше», если у него v = 0, t = 1, а если разряды равны — передаёт ответ младших.

6.2. Сборка

Тот же проект: развёртка, треугольник и «игра в хаос» остаются, рядом встаёт третий экран.

История. В 1962 году в MIT на компьютере PDP-1 написали несколько строк, которые рисовали на экране узор из «жующих» квадратов — Munching Squares, одна из первых компьютерных анимаций. Правило простое: точка горит, если (x XOR y) < t, а t растёт на 1 после каждого кадра. Мы соберём то же самое без программы — одной логикой.

Как собрать.

  • t — ещё один CNT6: он считает кадры. Шаг ему разрешает cy — перенос счётчика строки, он горит на последней точке кадра.
  • x XOR y — 6 XOR, по разряду.
  • v < t — сравнение. Сравнивают числа как в словаре: идут от старшего разряда, первый разряд, где они разные, решает. Удобнее собрать цепочку от младшего: каждый разряд говорит «меньше», если у него v = 0, t = 1, а если разряды равны — передаёт ответ младших. Последний, старший, и выдаёт ответ.
vtСравнение по разрядам (старший слева)v < t
5 = 0001016 = 000110разряд 1: v = 0, t = 1 — и старше равныда
6 = 0001105 = 000101разряд 1: v = 1, t = 0нет
3 = 0000113 = 000011все равны — от младших пришло 0нет

Шаг 1. CMP1 — сравнение одного разряда

ДетальНогаМетка
Порт входавыходV
Порт входавыходT
Порт входавыходLI
NOTI0
O0
V
nv
AND (здесь меньше)I0
I1
O0
nv
T
lt
XOR (разные?)I0
I1
O0
V
T
ne
NOTI0
O0
ne
eq
AND (равны — решают младшие)I0
I1
O0
eq
LI
pass
ORI0
I1
O0
lt
pass
LO
Порт выходавходLO

Ctrl+G → имя CMP1. Ноги: входы V, T, LI (ответ младших); выход LO.

Шаг 2. Холст: счётчик кадров, XOR, цепочка сравнения, третий экран

ДетальНогаМетка
CNT6 (кадры t)CLK
EN
RST
Q0
Q1
Q2
Q3
Q4
Q5
CO
CLK
cy
RST
t0
t1
t2
t3
t4
t5
ct
XOR (разряд 0)I0
I1
O0
x0
y0
v0
XOR (разряд 1)I0
I1
O0
x1
y1
v1
XOR (разряд 2)I0
I1
O0
x2
y2
v2
XOR (разряд 3)I0
I1
O0
x3
y3
v3
XOR (разряд 4)I0
I1
O0
x4
y4
v4
XOR (разряд 5)I0
I1
O0
x5
y5
v5
CMP1 (разряд 0)V
T
LI
LO
v0
t0
GND
l1
CMP1 (разряд 1)V
T
LI
LO
v1
t1
l1
l2
CMP1 (разряд 2)V
T
LI
LO
v2
t2
l2
l3
CMP1 (разряд 3)V
T
LI
LO
v3
t3
l3
l4
CMP1 (разряд 4)V
T
LI
LO
v4
t4
l4
l5
CMP1 (разряд 5)V
T
LI
LO
v5
t5
l5
ms
Dot display (третий)X0
X1
X2
X3
X4
X5
Y0
Y1
Y2
Y3
Y4
Y5
D0
WE
CLK
CLR
x0
x1
x2
x3
x4
x5
y0
y1
y2
y3
y4
y5
ms
VCC
nCLK
GND

LI у младшего разряда — GND: если все разряды равны, v не меньше t.

6.3. Проверка

№Что сделатьЧто видно
1третий экран — те же настройки (Dots, 64 × 64, 1 dot)—
2RST = 1, один такт, RST = 0; генератор MAXна третьем экране из диагонали растут квадраты, «съедают» экран и начинают снова
3генератор 4kHzвидно, как каждый кадр рисуется заново с новым t

Если квадраты не растут — проверь EN счётчика кадров: он на cy. Если узор «рваный» — проверь цепочку CMP1: LO каждого разряда идёт на LI следующего, а V/T — разряды одного номера.


Вставка урока 6 (Cmd+I)

Нужны NOT, AND, OR, XOR, CNT6; метки x0–x5, y0–y5, cy, CLK, nCLK, RST — с урока 3.

# Урок 6 (бонус) — Munching Squares (MIT, PDP-1, 1962): точка горит, если (x XOR y) < t; t растёт на 1 каждый кадр.# Вставка: Cmd+I поверх урока 5 (нужны NOT, AND, OR, XOR, CNT6; x0–x5, y0–y5, cy, CLK, nCLK, RST — с урока 3). # --- сравнение одного разряда: v < t по этому и младшим разрядам ---# если разряды разные — решает этот разряд (v = 0, t = 1 → меньше); если равны — то, что пришло от младших (LI)chip CMP1 {  portIn(V)  portIn(T)  portIn(LI)  portOut(LO)  NOT(V, nv)  AND(nv, T, lt)  XOR(V, T, ne)  NOT(ne, eq)  AND(eq, LI, pass)  OR(lt, pass, LO)} # --- на холст: счётчик кадров t, узор (x XOR y) < t, третий экран ---# t считает кадры: шаг — на последней точке кадра (перенос счётчика строки cy)CNT6(CLK=CLK, EN=cy, RST=RST, Q0=t0, Q1=t1, Q2=t2, Q3=t3, Q4=t4, Q5=t5, CO=ct)XOR(x0, y0, v0)XOR(x1, y1, v1)XOR(x2, y2, v2)XOR(x3, y3, v3)XOR(x4, y4, v4)XOR(x5, y5, v5)CMP1(V=v0, T=t0, LI=GND, LO=l1)CMP1(V=v1, T=t1, LI=l1, LO=l2)CMP1(V=v2, T=t2, LI=l2, LO=l3)CMP1(V=v3, T=t3, LI=l3, LO=l4)CMP1(V=v4, T=t4, LI=l4, LO=l5)CMP1(V=v5, T=t5, LI=l5, LO=ms)dotdisplay SCR3{layout=dots, w=64, h=64}(X0=x0, X1=x1, X2=x2, X3=x3, X4=x4, X5=x5, Y0=y0, Y1=y1, Y2=y2, Y3=y3, Y4=y4, Y5=y5, D0=ms, WE=VCC, CLK=nCLK, CLR=GND)

Не получается? Что-то не работает →