Buffers
Before this: Reading a Variable
Next steps: Resetting
A buffer passes a value on one tick late. With that delay a circuit can feed
its own output back into itself, so memory can be built from gates alone, with
no variable and no handler.
Contents
button1 Held -> chip set
button2 Held -> chip reset
chip alarm -> light Enabled
Code
@left in set: bool
@left in reset: bool
let state = set || (held && !reset)
buffer held: bool = state
@right out alarm = state
This is a latch: set turns it on, reset turns it off, and it remembers in
between.
buffer held: bool = state makes held whatever state was one tick ago.
The line above already uses held, before it is declared: that is the loop.
state is on while set is pressed, or while it was on a tick ago and
reset is not pressed.
Walk through it. Press set: state turns on. A tick later held is on, so
state stays on after you let go. Press reset: state turns off, and a tick
later so does held.
What happens if you hold both buttons at once?
Run
- Compile the chip and paste it in-game. Place two Buttons and a Point Light.
- Wire one Button’s Held to
set, the other’s Held toreset, andalarmto the Point Light’s Enabled. - Press
set: the light comes on and stays on. Pressreset: it goes off and stays off. Hold both:setwins, and the light is on.
Under the Hood
Open the chip. There is an OR, an AND, a NOT and one Buffer (Ticks) gate set to wait one tick. Follow the wires: OR, into the buffer, into the AND, and back into the OR. The wires make a loop, and the buffer sits in it.
Every loop of wires needs a buffer somewhere in it. The game works out all pure gates together each tick, and a loop without a delay would need its own answer before it could work out its answer. The compiler refuses one. Here an output pin feeds itself:
@left in set: bool
@left in reset: bool
@right out alarm: bool = set || (alarm && !reset)
Error: [WS005] cycle in the wire graph has no barrier (a Buffer, Queue or EdgeDetector must break it); 3 gate(s) in the loop:
The error goes on to list each gate in the loop. Put a buffer anywhere in it
and the loop is legal.
The : bool on the buffer matters. state uses held before the compiler
reaches the buffer’s line, so without a type it does not yet know what held
holds:
@left in set: bool
@left in reset: bool
let state = set || (held && !reset)
buffer held = state
@right out alarm = state
Error: [WS004] no overload for '&&' on any, bool
The message is about &&, but the fix is on the next line: give the buffer
its type.
Modify
-
Make
resetwin when both are held:let state = !reset && (set || held). -
A buffer can count ticks. This one adds one to its own value every tick:
buffer tick: int = tick + 1 @right out text = "Ticks: ${tick}"Wire
textto a Text Decal’s Text. It climbs by about 60 every second. -
Turn the latch into a burglar alarm. Give a brick an Attached Zone and wire its Occupied output to
setinstead of the first button. The light comes on when someone walks in and stays on after they leave, until the reset button is pressed.
Make
Make a quiz buzzer for two players. Each player has a button and a light. The
first to press lights their own light, and the other player’s button then does
nothing until a third button resets both. Use one latch per player, and let
each latch’s set be blocked by the other latch.
button1 Held -> chip buzz1
button2 Held -> chip buzz2
button3 Held -> chip reset
chip lit1 -> light1 Enabled
chip lit2 -> light2 Enabled
Good to Know
- A buffer delays by one tick, about a sixtieth of a second, so the delay itself is too short to see.
onalready runs once when a button goes down, not while it is held. You do not need a buffer to catch the moment of a press.- A buffer read before its declaration needs a type. Without one the compiler
reports
WS004, pointing at whatever operator first uses the buffer.
Next: Resetting.