Lesson 6 (bonus). Munching Squares: a living pattern from 1962
In picturesAfter this lesson a pattern of "munching" squares comes alive on the third screen — one of the first computer animations. In 1962 it was a program on the PDP-1; we build it from logic.
6.1. The idea: (x XOR y) < t
A dot is lit if (x XOR y) < t, and t grows by 1 after every frame. With a small t a narrow band along the diagonal is lit; with every frame squares grow from it, "eat" the screen — and it all starts again.
tis one moreCNT6, it counts frames; its step is allowed bycy— the row counter carry on the last dot of the frame;x XOR y— 6XORgates;v < t— a comparison chain from the lowest bit to the top: a bit says "less" if it hasv = 0, t = 1, and if the bits are equal it passes on the answer of the lower bits.
6.2. Building
The same project: the scan, the triangle and the chaos game stay, a third screen goes next to them.
History. In 1962 at MIT a few lines on the PDP-1 drew a pattern of "munching" squares — Munching Squares, one of the first computer animations. The rule is simple: a dot is lit if (x XOR y) < t, and t grows by 1 after every frame. We build the same thing with no program — just logic.
How to build it.
tis one moreCNT6: it counts frames. Its step is allowed bycy— the row counter carry, lit on the last dot of the frame.x XOR y— 6XORgates, one per bit.v < t— comparison. Numbers are compared like words in a dictionary: from the top bit, the first bit where they differ decides. It is easier to build a chain from the lowest bit: each bit says "less" if it hasv = 0, t = 1, and if the bits are equal it passes on the answer of the lower bits. The last, top one gives the answer.
| v | t | Bit by bit (top bit on the left) | v < t |
|---|---|---|---|
| 5 = 000101 | 6 = 000110 | bit 1: v = 0, t = 1 — and the higher bits are equal | yes |
| 6 = 000110 | 5 = 000101 | bit 1: v = 1, t = 0 | no |
| 3 = 000011 | 3 = 000011 | all equal — 0 came from the lower bits | no |
Step 1. CMP1 — comparing one bit
| Part | Pin | Label |
|---|---|---|
| Input port | out | V |
| Input port | out | T |
| Input port | out | LI |
| NOT | I0 O0 | V nv |
| AND (less here) | I0 I1 O0 | nv T lt |
| XOR (different?) | I0 I1 O0 | V T ne |
| NOT | I0 O0 | ne eq |
| AND (equal — lower bits decide) | I0 I1 O0 | eq LI pass |
| OR | I0 I1 O0 | lt pass LO |
| Output port | in | LO |
Ctrl+G → name CMP1. Pins: inputs V, T, LI (the answer of the lower bits); output LO.
Step 2. Canvas: frame counter, XOR, comparison chain, third screen
| Part | Pin | Label |
|---|---|---|
| CNT6 (frames t) | CLK EN RST Q0 Q1 Q2 Q3 Q4 Q5 CO | CLK cy RST t0 t1 t2 t3 t4 t5 ct |
| XOR (bit 0) | I0 I1 O0 | x0 y0 v0 |
| XOR (bit 1) | I0 I1 O0 | x1 y1 v1 |
| XOR (bit 2) | I0 I1 O0 | x2 y2 v2 |
| XOR (bit 3) | I0 I1 O0 | x3 y3 v3 |
| XOR (bit 4) | I0 I1 O0 | x4 y4 v4 |
| XOR (bit 5) | I0 I1 O0 | x5 y5 v5 |
| CMP1 (bit 0) | V T LI LO | v0 t0 GND l1 |
| CMP1 (bit 1) | V T LI LO | v1 t1 l1 l2 |
| CMP1 (bit 2) | V T LI LO | v2 t2 l2 l3 |
| CMP1 (bit 3) | V T LI LO | v3 t3 l3 l4 |
| CMP1 (bit 4) | V T LI LO | v4 t4 l4 l5 |
| CMP1 (bit 5) | V T LI LO | v5 t5 l5 ms |
| Dot display (third) | 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 of the lowest bit is GND: if all bits are equal, v is not less than t.
6.3. Check
| № | What to do | What you see |
|---|---|---|
| 1 | third screen — same settings (Dots, 64 × 64, 1 dot) | — |
| 2 | RST = 1, one clock, RST = 0; clock at MAX | on the third screen squares grow from the diagonal, "eat" the screen and start again |
| 3 | clock at 4kHz | you can see every frame redrawn with a new t |
If the squares do not grow, check the frame counter EN: it is on cy. If the pattern is "torn", check the CMP1 chain: the LO of each bit goes to the LI of the next, and V/T are bits with the same number.
Lesson 6 paste (Cmd+I)
Needs NOT, AND, OR, XOR, CNT6; the labels x0–x5, y0–y5, cy, CLK, nCLK, RST come from lesson 3.
# Lesson 6 (bonus) — Munching Squares: (x XOR y) < t, t counts frames.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)} 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)¿No te sale? Algo no funciona →