FFL and FFU — FIFO Queue

FFL and FFU in rungs.dev build a first-in first-out queue in an array — load a value at one end, take the oldest out at the other. Use them to track parts waiting their turn.

FFL

Source

source

(DN)

Array

array

(EM)

Control

control

Length

length

Position

position

Puts a value into the next free slot of a queue on each rising edge, and stops once the queue holds .LEN of them.

FFU

Array

array

(DN)

Destination

destination

(EM)

Control

control

Length

length

Position

position

Takes the oldest value out of a queue on each rising edge, shifting the rest down one place.

What a FIFO is

FIFO means first in, first out — a queue, like people waiting at a counter. The first value you put in is the first one you get back out.

Use one whenever something has to wait its turn: part numbers queuing for an inspection station, recipe steps waiting to run, alarm codes waiting to be shown.

The queue lives in an array you declare, and its state lives in a CONTROL tag. FFL loads; FFU unloads. They normally share one control tag — that is how they agree on how full the queue is.

Operands

FFL

NameTypeNotes
sourcenumericThe value to put in. A tag or a number
arraynumeric[]Where the queue starts — Buf or Buf[2]
controlCONTROLThe queue's state
lengthnumberHow many slots the queue has
positionnumberHow many are in use at start-up. Usually 0

FFU

NameTypeNotes
arraynumeric[]Where the queue starts
destinationnumericWhere the unloaded value goes
controlCONTROLThe same control tag the FFL uses
lengthnumberSame as the FFL's
positionnumberSame as the FFL's

The array can be DINT, INT, SINT or REAL. A value of a different type converts on the way in and out, exactly as MOVE does.

How It Works

Both act on the rising edge. Holding the rung true loads or unloads once and no more.

EventFFLFFU
Rung goes trueWrites source at .POS, then .POS goes up 1Reads the element at the start, shifts the rest down, .POS goes down 1
Queue already fullLoads nothing
Queue emptyWrites 0 to the destination and leaves the array alone
Rung false.EN goes to 0. Nothing else changes.EU goes to 0. Nothing else changes

After either one runs, .DN and .EM are worked out again from .POS:

  • .DN is on when the queue is full.POS has reached .LEN.
  • .EM is on when the queue is empty.POS is 0.

.DN and .EM are results, not switches

They are recomputed from .POS every time the instruction runs, so writing .DN := 1 yourself does not stop the next load. If you want to stop a load, condition the rung.

Example — A Parts Queue

Each part detected joins the queue; each press of Take pulls the oldest one out.

0

PartSeen

FFL

Source

PartId

(DN)

Array

Queue

(EM)

Control

QCtl

Length

8

Position

0

1

Take

FFU

Array

Queue

(DN)

Destination

NextPart

(EM)

Control

QCtl

Length

8

Position

0

2

QCtl.EM

QueueEmpty

Both instructions name QCtl, so the load and the unload see the same queue.

Where Length comes from

length and position are written into the control tag once, when the program starts — the instruction reads .LEN and .POS from the tag after that. See Array Instructions.

Common Mistakes

  • Giving the FFL and the FFU different control tags. They then disagree about how full the queue is. One queue, one control.
  • Adding an ONS in front — unnecessary. Both already act on the rising edge.
  • Expecting FFU to leave the destination alone when the queue is empty. It writes 0.
  • Declaring the array shorter than length. It stops the program with a major fault.

On this page