# FAL and FSC — Loop Over an Array

Source: https://rungs.dev/docs/ladder-logic/instructions/fal-fsc

> FAL and FSC in rungs.dev run one expression once per array element. FAL stores each answer; FSC stops at the first element that passes. Use them to scale a batch or find a value.

Works out an expression once for every element of an array and stores each answer, with the control tag counting the elements off.

Tests an expression against each element of an array in turn and stops at the first one that passes.

## What they do [#what-they-do]

Every other array instruction does **one fixed job**: copy, fill, sort, average. `FAL` and
`FSC` let you write the job yourself.

`FAL` is "do this to every element": scale every raw count into engineering units, add an
offset to a whole recipe, square every deviation.

`FSC` is "find the first element where this is true": the first alarm still active, the first
free slot in a table, the first reading over a limit.

Both write the element number they are on into `.POS` **as they go**, and your expression reads
it back to pick the element. That is the whole idea:

```
FAL(Ctl, ?, ?, ALL, Scaled[Ctl.POS], Raw[Ctl.POS] * 2)
```

with `Ctl.LEN` set to 5 on the tag. On the first pass `Ctl.POS` is 0, so this is `Scaled[0] := Raw[0] * 2`. Then 1, then 2, and so
on. The control tag does the counting.

## Operands [#operands]

### FAL [#fal]

| Name         | Type                          | Notes                                   |
| ------------ | ----------------------------- | --------------------------------------- |
| `control`    | `CONTROL`                     | Counts the elements off                 |
| `length`     | number                        | How many elements to work through       |
| `position`   | number                        | Which element to start at. Usually `0`  |
| `mode`       | `ALL`, `INC`, or a number     | How many per scan — see below           |
| `dest`       | `DINT`, `INT`, `SINT`, `REAL` | Where each answer goes. Usually indexed |
| `expression` | an expression                 | Worked out once per element             |

### FSC [#fsc]

The same first four, then `expression`. There is no destination — the answer decides whether
the search stops, and `.FD` reports whether it found anything.

`mode` takes a keyword or a number. Start typing and a short list offers `ALL` and `INC`;
type a digit instead and the list steps aside, because a count is a number you write rather
than one you pick. It can never be a tag — the controller refuses one there, so Studio does
not offer it.

## Mode — how many per scan [#mode--how-many-per-scan]

| Mode     | What happens                                                                    |
| -------- | ------------------------------------------------------------------------------- |
| `ALL`    | The whole run, in one scan, on the rising edge                                  |
| `INC`    | One element per rising edge — one pulse, one element                            |
| a number | That many per scan, **every scan**, until done — even after the rung goes false |

`ALL` is what you want most of the time. Reach for a number when the array is long enough that
doing it all in one scan would stretch the scan time; the run then finishes over several scans
on its own.

> **INFO**
>
> **A numerical run keeps going after the rung drops**
>
> That is deliberate: it is how a long job finishes without you having to hold the rung true for
> it. `.EN` stays on while the run is in progress and clears the moment it finishes.

## The expression [#the-expression]

`FAL`'s expression is the same one [`CPT`](https://rungs.dev/docs/ladder-logic/instructions/cpt) takes: arithmetic, brackets, the bitwise
operators, and the maths functions. No comparisons — it has to produce a number to store.

`FSC`'s is the same one [`CMP`](https://rungs.dev/docs/ladder-logic/instructions/cmp) takes: it adds the comparisons and the logical operators.
An element **passes** when the answer is anything other than zero, so a plain sum works as well
as a comparison — `Src[Ctl.POS] + 1` passes on every element except the one holding `-1`.

See [Expressions in Ladder](https://rungs.dev/docs/ladder-logic/expressions) for the full operator table.

## How It Works [#how-it-works]

| Event                    | What happens                                            |
| ------------------------ | ------------------------------------------------------- |
| Rung goes true           | Starts from the current `.POS` and works forward        |
| The last element is done | `.DN` turns on, `.POS` stays on that element            |
| Rung stays true          | Nothing more, unless the mode is a number               |
| Rung false after `.DN`   | `.POS` and every bit go back to `0`                     |
| `FSC` finds a match      | `.FD` and `.IN` turn on, `.POS` is the matching element |

`.POS` always names the **last element worked on**, so a finished run leaves it at
`.LEN - 1`, not `.LEN`.

### Resuming an FSC search [#resuming-an-fsc-search]

When `FSC` matches it sets `.IN`, which parks the search — a held rung and a false rung both
leave it exactly where it stopped. Clear `.IN` from your logic and the search carries on from
the **next** element:

```ladder
XIC(FindNext)OTU(SearchCtl.IN)
```

A pass that reaches the end without a match clears `.FD` and sets `.DN`.

## Example — Scale a Whole Batch [#example--scale-a-whole-batch]

```ladder
XIC(NewBatch)FAL(ScaleCtl,?,?,ALL,Scaled[ScaleCtl.POS],Raw[ScaleCtl.POS] * 4)

ScaleCtl.LEN = 10
ScaleCtl.POS = 0
```

## Example — Find the First Reading Over Limit [#example--find-the-first-reading-over-limit]

```ladder
XIC(Check)FSC(FindCtl,?,?,ALL,Readings[FindCtl.POS] > Limit);XIC(FindCtl.FD)OTE(OverLimit)

FindCtl.LEN = 10
FindCtl.POS = 0
```

When it finds one, `FindCtl.POS` is the element number — read it to know _which_ reading was
over.

## Common Mistakes [#common-mistakes]

- Forgetting `Ctl.POS` in the expression. Without it, every pass reads and writes the same
  element.
- Looking for a way to put a tag in the Mode row. There isn't one — it is a pick list.
- Expecting `FSC` to keep searching after a match. It parks on `.IN`; clear it to carry on.
- Reading `.POS` as a count. It is an index — one less than the number done.
- Setting `.LEN` longer than the array. The subscript stops the program part-way through, and
  the elements before it are already written.

## Related [#related]

- [Array instructions overview](https://rungs.dev/docs/ladder-logic/instructions/array-instructions)
- [CPT](https://rungs.dev/docs/ladder-logic/instructions/cpt) and [CMP](https://rungs.dev/docs/ladder-logic/instructions/cmp) — the same two expression grammars, on one value
- [Expressions in Ladder](https://rungs.dev/docs/ladder-logic/expressions) — the operator table