# BSL and BSR — Bit Shift

Source: https://rungs.dev/docs/ladder-logic/instructions/bsl-bsr

> BSL and BSR in rungs.dev move every bit of a DINT array one place along on each rising edge, feeding a new bit in at one end. Use them to track parts down a conveyor.

Shifts every bit of a DINT array one place toward the high end on each rising edge, feeding the source bit in at bit 0.

Shifts every bit of a DINT array one place toward the low end on each rising edge, feeding the source bit in at the far end.

## What a shift register is [#what-a-shift-register-is]

A **shift register** is a row of bits that all move along together, one place at a time. Think of a conveyor with a station every metre: each time the belt advances one station, whatever was at station 1 is now at station 2, station 2 moves to station 3, and a fresh reading enters at station 1.

`BSL` (Bit Shift Left) moves the bits toward the high end and feeds the new bit in at bit 0. `BSR` (Bit Shift Right) moves them toward bit 0 and feeds the new bit in at bit `length − 1`.

Both work on a `DINT` array and keep their state in a [`CONTROL`](https://rungs.dev/docs/ladder-logic/instructions/array-instructions#control-tag-members) tag, the way a timer keeps its state in a `TIMER`. Give each shift instruction its own control tag, even a `BSL` and a `BSR` on the same array: the bit that falls off the end is reported in the control's `.UL`, and a second instruction on the same control overwrites it.

## Operands [#operands]

| Name        | Type      | Notes                                                         |
| ----------- | --------- | ------------------------------------------------------------- |
| `array`     | `DINT[]`  | Where the region starts — `Buf` or `Buf[2]`                   |
| `control`   | `CONTROL` | Holds the length, position and status bits                    |
| `sourceBit` | `BOOL`    | The bit fed in at the near end                                |
| `length`    | number    | How many bits long the register is. A plain number, 1 or more |

`length` is typed as a number, not a tag, and it is stored on the control tag as its `.LEN` — the box shows the tag's value there, the way a timer shows its preset. The instruction reads `.LEN` from the tag on every run, so logic can change it.

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

Both instructions act on the **rising edge** — the scan where the rung goes from false to true. Holding the rung true shifts once and no more.

| Event                     | What happens                                                 |
| ------------------------- | ------------------------------------------------------------ |
| Rung goes true            | One shift. `.EN` and `.DN` turn on, `.POS` becomes `.LEN`    |
| Rung stays true           | Nothing more                                                 |
| Rung false                | `.EN`, `.DN`, `.ER` and `.POS` go to `0` — but `.UL` is kept |
| `.LEN` below zero         | `.ER` turns on and nothing shifts                            |
| [`RES`](https://rungs.dev/docs/ladder-logic/instructions/res) on the tag | `.POS` and every status bit go to `0`; `.LEN` is kept        |

### Which bit falls out [#which-bit-falls-out]

`.UL` is a **copy** of the bit that left the register — bit `length − 1` for `BSL`, bit 0 for `BSR`. It is a copy, not a removal: the bit still moves along inside the register as well.

> **INFO**
>
> **.UL survives a false rung**
>
> Every other status bit is cleared when the rung goes false. `.UL` is not. That is deliberate — it is how you read the bit that just fell off the end on a later scan, after the rung has already dropped.

## Example — Conveyor Tracker [#example--conveyor-tracker]

A part sensor at the head of a conveyor, and an ejector 8 stations later. Each pulse of `Advance` moves the whole picture along one station.

```ladder
XIC(Advance)BSL(Stations,Track,PartPresent,?);XIC(Stations[0].7)OTE(Eject)

Track.LEN = 8
```

`Stations[0].7` is bit 7 — the eighth station. When a part reaches it, the ejector fires.

## The shift covers whole words [#the-shift-covers-whole-words]

> **WARNING**
>
> **A DINT is 32 bits, and all 32 move**
>
> A length of 8 does **not** mean only 8 bits move. The instruction shifts whole `DINT` words: a length of 1 to 32 shifts one word, 33 to 64 shifts two, and so on. Bits above `length − 1` inside that word move as well, and a bit pushed off the top of the last word is thrown away.
>
> So if you use bit 20 of a register declared with a length of 8, it will drift. Keep anything you want left alone out of the array the shift register lives in.

The same rule decides how much array the instruction needs. A length of 40 needs two `DINT` elements, so `BSL(Buf[1], …, 40)` on a `DINT[2]` has only one element left to work with, and the overrun stops the program with a major fault.

## Common Mistakes [#common-mistakes]

- Adding an `ONS` in front — unnecessary. `BSL` and `BSR` already act on the rising edge.
- Expecting only `length` bits to move. See the callout above — the shift is by whole words.
- Reading `.UL` as "the bit was taken out". It was copied; it also moved along.
- Writing `.LEN` from logic and forgetting the array has to be long enough for it.

## Related [#related]

- [Array instructions overview](https://rungs.dev/docs/ladder-logic/instructions/array-instructions) — the `CONTROL` members and where `.LEN` comes from
- [RES](https://rungs.dev/docs/ladder-logic/instructions/res) — clears `.POS` and the status bits, keeps `.LEN`
- [Arrays](https://rungs.dev/docs/tags/arrays) — declaring the `DINT` array a shift register lives in