# MEQ — Mask Equal To

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

> MEQ in rungs.dev compares two whole numbers bit by bit, but only in the bits a mask selects. Covers how the mask works, a worked status-word example, and how SINT and INT values are read.

Passes power when Source and Compare are equal in every bit the Mask has set to 1. Bits under a 0 in the Mask are ignored.

Many devices pack several facts into one number. A drive might report its state in the lowest four bits of a status word and use the other bits for alarms and flags. `EQ` compares the whole number, so a single alarm bit turning on makes the comparison fail. `MEQ` lets you say which bits matter and ignore the rest.

## Operands [#operands]

| Name      | Type                      |
| --------- | ------------------------- |
| `source`  | `DINT` \| `INT` \| `SINT` |
| `mask`    | `DINT` \| `INT` \| `SINT` |
| `compare` | `DINT` \| `INT` \| `SINT` |

Each operand can be a tag, an array element, a member such as `Tmr.ACC`, or a number you type in. `MEQ` is a ladder instruction only: Structured Text does not have it, and it cannot go inside a `CMP` expression.

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

A **mask** is a number used to pick bits. Every bit that is `1` in the mask is checked; every bit that is `0` is ignored. `MEQ` keeps only the checked bits of `source` and of `compare`, then tests whether what is left is equal:

`(source AND mask) = (compare AND mask)`

- A mask of `0` checks no bits, so the rung always passes.
- A mask of `-1` (all 32 bits set) checks every bit. When `source` and `compare` are the same type, `MEQ` then works like `EQ`. When one is a `SINT` or `INT` and the other is wider, it may not: see [SINT and INT values are read as their bits](#sint-and-int-values-are-read-as-their-bits).
- Like every compare instruction, `MEQ` is an input: it needs an output after it on the rung.

## Example — Check the State Bits of a Status Word [#example--check-the-state-bits-of-a-status-word]

`DriveStatus` holds the drive's state in bits 0–3, and state `6` means "running". Turn on `Running` whatever the other bits are doing:

```ladder
MEQ(DriveStatus,16#000F,6)OTE(Running)
```

With `DriveStatus = 16#0486`, the bits work out like this:

| Value                   | Bits 15–4        | Bits 3–0 |
| ----------------------- | ---------------- | -------- |
| `DriveStatus` = 16#0486 | `0000 0100 1000` | `0110`   |
| `mask` = 16#000F        | `0000 0000 0000` | `1111`   |
| `compare` = 6           | `0000 0000 0000` | `0110`   |

Only bits 3–0 are checked, and both hold `0110`, so `Running` turns on. Bits 7 and 10 are set in `DriveStatus` but not in `compare`; the mask hides them. `EQ(DriveStatus,6)` would be false here.

## SINT and INT Values Are Read as Their Bits [#sint-and-int-values-are-read-as-their-bits]

`MEQ` compares bit patterns, not signed numbers. A `SINT` or `INT` is taken as its own 8 or 16 bits, and the bits above them count as `0`. So a `SINT` holding `-1` is read as `16#FF` (eight ones), not as 32 ones.

This is different from maths, where a `SINT` holding `-1` stays `-1` when it is added to a `DINT`. It matters when the mask reaches past the narrow value's own bits:

```ladder
MEQ(ByteValue,16#FF00,16#FF00)OTE(HighBitsSet)
```

With `ByteValue` a `SINT` holding `-1`, `HighBitsSet` stays off: the `SINT` has no bits 8–15, so they count as `0`.

The same holds for a narrow mask: a `SINT` mask holding `-1` checks bits 0–7 only.

It is also why an all-ones mask does not turn `MEQ` into `EQ` across types. With `ByteValue` a `SINT` holding `-1` and `WordValue` a `DINT` holding `-1`, `EQ(ByteValue,WordValue)` is true, because both are the number `-1`. `MEQ(ByteValue,-1,WordValue)` is false, because it compares `16#FF` with `16#FFFFFFFF`.

## Common Mistakes [#common-mistakes]

- Using `MEQ` on a `REAL` or `BOOL` — it takes whole numbers only. To test one bit, use [`XIC`](https://rungs.dev/docs/ladder-logic/instructions/xic) on that bit, such as `XIC(DriveStatus.3)`.
- Setting bits in `compare` that the mask does not check. They are ignored, so `MEQ(Status,16#000F,16#0106)` behaves exactly like `MEQ(Status,16#000F,6)` — and the extra bits make the rung harder to read.
- Expecting a negative `SINT` or `INT` to fill the upper bits. See [SINT and INT values are read as their bits](#sint-and-int-values-are-read-as-their-bits).

## Related [#related]

- [Compare instructions](https://rungs.dev/docs/ladder-logic/instructions/compare) — `EQ` compares every bit
- [MOVE / MVM](https://rungs.dev/docs/ladder-logic/instructions/move) — `MVM` uses a mask the same way, to copy selected bits
- [Logical instructions](https://rungs.dev/docs/ladder-logic/instructions/logical) — `AND` applies a mask and keeps the result