---
title: "Bit operations"
description: "TapHome script bit functions GETBIT, GETBITS, SETBIT, SETBITS, GETBYTE, SETBYTE, BCD conversion, bit width by type and bitwise operators."
url: "https://taphome.com/en/docs/script/bit-operations/"
language: en
lastmod: 2026-11-06
generator: hugo
ai:
  topics: ["bit-operations","byte-manipulation","bitwise-operators","scripting-language"]
  questions: ["How do I read a single bit from a number in TapHome?","How to extract a byte from a number with GETBYTE?","How do I set a specific bit or byte in TapHome script?","How to perform a left or right bit shift in TapHome?","How do bitwise AND and OR work in TapHome scripts?","What are the Excel equivalents of TapHome bit operators?","How many bits do the bit functions use for a 16-bit or 64-bit value?","How do I convert a number to or from BCD?"]
---

# Bit operations

TapHome script bit and byte manipulation — GETBIT, GETBITS, SETBIT, SETBITS, GETBYTE, SETBYTE, TOBCD, FROMBCD, bit width by type and bitwise operators with Excel equivalents.

Last updated: 2026-11-06

These functions read and change single bits, bit fields and bytes of a whole number — typically status words and alarm registers read with `MODBUSR`. Bit 0 is the least significant (rightmost) bit and byte 0 the least significant byte.

## Bit width by type

How many bits a number has for the bit functions depends on its type:

| Type of `number` | Bits | `bit` / `startBit` | Byte `index` | Result of `GETBITS`, `SETBIT`, `SETBITS`, `SETBYTE` |
|---|---|---|---|---|
| `int8`, `uint8` | 8 | 0 – 7 | 0 | `uint` |
| `int16`, `uint16` | 16 | 0 – 15 | 0 – 1 | `uint` |
| `int64`, `uint64` | 64 | 0 – 63 | 0 – 7 | `uint64` |
| everything else (`double`, `float`, `int`, `uint`, …) | 32 | 0 – 31 | 0 – 3 | `uint` |

- `MODBUSR`, decimal literals, `PARSEJSON` and device values are `double`, so they count as 32 bits. Only typed variables, collection elements and the 64-bit Modbus data types have another width.
- A bit or byte outside the type is an error, for example `GETBIT(x, 16)` for a `uint16` variable: *GETBIT - bit must be between 0 and 15*. A bit field that **starts** inside the type but reaches over its top is allowed — `GETBITS` returns the bits that exist and `SETBITS` drops the rest.
- A `double` or `float` is rounded to a whole number and must be between −2 147 483 648 and 4 294 967 295; anything else, `NaN` included, is an error (*value X is out of the 32-bit range*). Negative values use two's complement, so `GETBITS(-1, 0, 16)` is `65535`.

**Available** — the width by type needs TapHome Next 2026.1.40665+. Older builds treat every value as 32 bits: a 64-bit value loses its upper half and a bit above an 8-bit or 16-bit type returns `0`.

## GETBIT

`GETBIT` returns the value of one bit of a number, `0` or `1`.

```text
GETBIT(number, bit)
```

**Example**

```taphome
# read a single bit of a literal number
GETBIT(2, 0);
# Result: 0
GETBIT(4, 2);
# Result: 1
# raise error 3 when bit 3 of the register is set
IF(GETBIT(MODBUSR(H, 600, Uint16), 3) = 1, ADDERROR(3, "Overheating"));
```

## GETBITS

`GETBITS` returns a bit field — `numberOfBits` bits starting at `startBit` — as an unsigned whole number.

```text
GETBITS(number, startBit, numberOfBits)
```

**Parameters** — `numberOfBits` is 1 – 32, or 1 – 64 for a 64-bit `number`.

**Example**

```taphome
GETBITS(216, 3, 2);
# Result: 3 (216 = 0b11011000, bits 3 and 4 are 1)
GETBITS(0xFF, 0, 4);
# Result: 15
```

A date and time packed as two bytes per register (Komfovent):

```taphome
VAR time := MODBUSR(H, 28, Uint16);
VAR date := MODBUSR(H, 30, Uint16);
GETBITS(time, 8, 8) + ":" + GETBITS(time, 0, 8) + " "
    + GETBITS(date, 0, 8) + "." + GETBITS(date, 8, 8) + "." + MODBUSR(H, 29, Uint16);
```

## SETBIT

`SETBIT` returns the number with one bit set to 0 (when `value` is 0) or to 1 (any other `value`).

```text
SETBIT(number, bit, value)
```

**Example**

```taphome
# set bit 1 of 1 to 1, then bit 2 of 4 to 0
SETBIT(1, 1, 1);
# Result: 3
SETBIT(4, 2, 0);
# Result: 0
# set bit 40 of a 64-bit variable and read it back
uint64 alarms := 0;
alarms := SETBIT(alarms, 40, 1);
GETBIT(alarms, 40);
# Result: 1 (a 64-bit variable has bits 0 to 63)
```

## SETBITS

`SETBITS` returns the number with the bit field of `numberOfBits` bits starting at `startBit` replaced by `value`.

```text
SETBITS(number, startBit, numberOfBits, value)
```

**Example**

```taphome
SETBITS(192, 4, 2, 3);
# Result: 240
SETBITS(192, 5, 2, 3);
# Result: 224
```

**Errors** — *Given number of bits (2) is not enought for storing the value 4.* when `value` does not fit into the field (the message is spelled this way).

## GETBYTE

`GETBYTE` returns one byte of a number (0 – 255) as a `uint`.

```text
GETBYTE(number, index)
```

**Example**

```taphome
# index 0 is the lowest byte, index 1 the next one
GETBYTE(256, 0);
# Result: 0
GETBYTE(256, 1);
# Result: 1
# 259 is 0x0103, so byte 0 is 3
GETBYTE(259, 0);
# Result: 3
```

## SETBYTE

`SETBYTE` returns the number with the byte at `index` replaced by `value` (0 – 255).

```text
SETBYTE(number, index, value)
```

**Example**

```taphome
SETBYTE(256, 0, 255);
# Result: 511
SETBYTE(259, 1, 2);
# Result: 515
```

**Errors** — *Given value (X) is bigger than maximum byte value.*; *Given value is less than 0.*

## TOBCD

`TOBCD` converts a whole number to packed BCD — each decimal digit in its own 4 bits — and returns it as a `uint`; up to 8 digits are kept.

```text
TOBCD(number)
```

**Example**

```taphome
TOBCD(1234);
# Result: 4660 (0x1234)
```

## FROMBCD

`FROMBCD` converts a packed BCD value back to an ordinary number.

```text
FROMBCD(number)
```

**Example**

```taphome
FROMBCD(0x1234);
# Result: 1234
```

**Errors** — *FROMBCD - number 26 is not in BCD format* and the position of the digit when a group of 4 bits is greater than 9 (here `0x1A`).

## Bitwise operators and Excel equivalents

The operators work on whole numbers; a `double` operand is converted to `int64` first and a `Null` operand gives `Null`. The full list and priorities are on [Operators](https://taphome.com/en/docs/script/operators/).

| Operator | Example | Result | Excel |
|---|---|---|---|
| `<<` left bit shift | `8 << 2` | `32` | `BITLSHIFT(number, shift_amount)` |
| `>>` right bit shift | `32 >> 2` | `8` | `BITRSHIFT(number, shift_amount)` |
| `&` bitwise AND | `3 & 1` | `1` | `BITAND(number1, number2)` |
| `\|` bitwise OR | `2 \| 1` | `3` | `BITOR(number1, number2)` |
| `^` bitwise XOR | `5 ^ 1` | `4` | `BITXOR(number1, number2)` |

> [!WARNING]
> The bitwise operators bind more loosely than comparisons: `a & 1 > 0` means `a & (1 > 0)`. Always use parentheses.

```taphome
VAR status := MODBUSR(H, 5, Uint16);
IF((status & 0x04) > 0, "Door open", "Door closed");
```

See the example of bit operations in [Google Sheets](https://docs.google.com/spreadsheets/d/1hF5FMpGMJbgYh-YLwWrq2n186_ATyGyLUb689__IhLY/edit?usp=sharing), or try the interactive tool at [bitwisecmd.com](http://bitwisecmd.com/).
