2021-01-29 06:31:58 -05:00
|
|
|
|
2023-10-18 10:28:52 -04:00
|
|
|
[![Arduino CI](https://github.com/RobTillaart/BitHelpers/workflows/Arduino%20CI/badge.svg)](https://github.com/marketplace/actions/arduino_ci)
|
|
|
|
[![Arduino-lint](https://github.com/RobTillaart/BitHelpers/actions/workflows/arduino-lint.yml/badge.svg)](https://github.com/RobTillaart/BitHelpers/actions/workflows/arduino-lint.yml)
|
|
|
|
[![JSON check](https://github.com/RobTillaart/BitHelpers/actions/workflows/jsoncheck.yml/badge.svg)](https://github.com/RobTillaart/BitHelpers/actions/workflows/jsoncheck.yml)
|
|
|
|
[![GitHub issues](https://img.shields.io/github/issues/RobTillaart/BitHelpers.svg)](https://github.com/RobTillaart/BitHelpers/issues)
|
|
|
|
|
|
|
|
[![License: MIT](https://img.shields.io/badge/license-MIT-green.svg)](https://github.com/RobTillaart/BitHelpers/blob/master/LICENSE)
|
|
|
|
[![GitHub release](https://img.shields.io/github/release/RobTillaart/BitHelpers.svg?maxAge=3600)](https://github.com/RobTillaart/BitHelpers/releases)
|
|
|
|
[![PlatformIO Registry](https://badges.registry.platformio.org/packages/robtillaart/library/BitHelpers.svg)](https://registry.platformio.org/libraries/robtillaart/BitHelpers)
|
2021-01-29 06:31:58 -05:00
|
|
|
|
|
|
|
|
|
|
|
# bitHelpers
|
|
|
|
|
2021-12-14 05:51:15 -05:00
|
|
|
Arduino library with functions on bit level.
|
2021-01-29 06:31:58 -05:00
|
|
|
|
2021-10-19 10:59:51 -04:00
|
|
|
|
2021-01-29 06:31:58 -05:00
|
|
|
## Description
|
|
|
|
|
2021-08-09 15:39:09 -04:00
|
|
|
This library contains functions to manipulate bits and bit patterns in an
|
2021-01-29 06:31:58 -05:00
|
|
|
efficient way.
|
|
|
|
For most functions a 8 - 64 bit optimized version exist.
|
|
|
|
|
|
|
|
The library is tested on ESP32 and Arduino UNO but not for all possible values.
|
|
|
|
other platforms are expected to work without modification.
|
2021-12-14 05:51:15 -05:00
|
|
|
If they don't please file an issue on GitHub.
|
2021-01-29 06:31:58 -05:00
|
|
|
|
2021-12-14 05:51:15 -05:00
|
|
|
New bit functions can be added or investigated, please file an issue on GitHub.
|
2021-01-29 06:31:58 -05:00
|
|
|
|
|
|
|
|
|
|
|
## Interface
|
|
|
|
|
2023-02-08 10:01:06 -05:00
|
|
|
```cpp
|
|
|
|
#include "bitHelpers.h"
|
|
|
|
```
|
2021-08-10 16:16:36 -04:00
|
|
|
|
2023-02-08 10:01:06 -05:00
|
|
|
#### BitCount
|
2021-08-10 16:16:36 -04:00
|
|
|
|
2023-02-08 10:01:06 -05:00
|
|
|
several implementations to compare performance.
|
2021-12-14 05:51:15 -05:00
|
|
|
|
|
|
|
- **uint8_t bitCountReference(uint32_t value)** returns number of bits set in a value.
|
|
|
|
- **uint8_t bitCountKR(uint32_t value)** Kerningham Ritchie bitCount.
|
2023-02-08 10:01:06 -05:00
|
|
|
- **uint8_t bitCountArray(uint32_t value)** count per nibble with lookup table.
|
2021-12-14 05:51:15 -05:00
|
|
|
- **uint8_t bitCountF1(uint32_t value)** SWAG algorithm variant.
|
|
|
|
- **uint8_t bitCountF2(uint32_t value)** SWAG algorithm variant.
|
2021-01-29 06:31:58 -05:00
|
|
|
|
2021-08-09 15:39:09 -04:00
|
|
|
BitCount - fastest version, SWAG algorithm
|
2021-12-14 05:51:15 -05:00
|
|
|
|
2023-02-08 10:01:06 -05:00
|
|
|
- **uint8_t bitCount(uint8_t value)**
|
|
|
|
- **uint8_t bitCount(uint16_t value)**
|
|
|
|
- **uint8_t bitCount(uint32_t value)**
|
|
|
|
- **uint8_t bitCount(uint64_t value)**
|
|
|
|
|
2021-01-29 06:31:58 -05:00
|
|
|
|
2023-02-08 10:01:06 -05:00
|
|
|
#### Reverse
|
2021-01-29 06:31:58 -05:00
|
|
|
|
2023-02-08 10:01:06 -05:00
|
|
|
T = uint8_t .. uint64_t
|
|
|
|
|
|
|
|
- **T bitReverse(T value)** reverses bits.
|
2021-12-14 05:51:15 -05:00
|
|
|
- **T nybbleReverse(T value)** reverses nibbles (4 bit) in a uint8_t .. uint64_t.
|
|
|
|
- **T byteReverse(T value)** reverses bytes (8 bit) in a uint16_t .. uint64_t.
|
|
|
|
- **T wordReverse(T value)** reverses words (16 bit) in uint32_t and uint64_t.
|
|
|
|
|
2023-02-08 10:01:06 -05:00
|
|
|
#### Swap
|
|
|
|
|
|
|
|
swap upper and lower half: uint8_t .. uint64_t. Is like rotate 50%
|
2021-12-14 05:51:15 -05:00
|
|
|
|
|
|
|
- **T swap(T value)** 0x12345678 ==> 0x56781234.
|
2021-01-29 06:31:58 -05:00
|
|
|
|
2023-02-08 10:01:06 -05:00
|
|
|
|
|
|
|
#### BitRotate
|
|
|
|
|
2021-01-29 06:31:58 -05:00
|
|
|
Rotate Left / Right: uint8_t .. uint64_t
|
2021-08-09 15:39:09 -04:00
|
|
|
if pos larger than # bits original value is returned.
|
2021-12-14 05:51:15 -05:00
|
|
|
|
2021-08-09 15:39:09 -04:00
|
|
|
- **T bitRotateLeft(T value, uint8_t pos)**
|
|
|
|
- **T bitRotateRight(T value, uint8_t pos)**
|
2021-01-29 06:31:58 -05:00
|
|
|
|
2023-02-08 10:01:06 -05:00
|
|
|
|
|
|
|
#### BitFlip
|
|
|
|
|
2021-01-29 06:31:58 -05:00
|
|
|
BitFlip: uint8_t .. uint64_t a.k.a toggle
|
2021-08-09 15:39:09 -04:00
|
|
|
if pos larger than # bits original value is returned.
|
2021-12-14 05:51:15 -05:00
|
|
|
|
2021-08-09 15:39:09 -04:00
|
|
|
- **T bitFlip(T value, uint8_t pos)** flips a single bit at pos
|
2021-01-29 06:31:58 -05:00
|
|
|
|
2023-02-08 10:01:06 -05:00
|
|
|
|
|
|
|
#### BitRot
|
|
|
|
|
2021-01-29 06:31:58 -05:00
|
|
|
BitRot: uint8_t .. uint64_t
|
2021-12-14 05:51:15 -05:00
|
|
|
|
2023-02-08 10:01:06 -05:00
|
|
|
- **T bitRotRef(T value, float chance = 0.5, uint8_t times = 1)** reference implementation.
|
2022-04-13 13:33:48 -04:00
|
|
|
- **T bitRot(T value, float chance = 0.5, uint8_t times = 1)** random damage to a single bit of a value,
|
2021-08-09 15:39:09 -04:00
|
|
|
chance = float 0.0 .. 1.0 that one random bit is toggled.
|
2022-04-13 13:33:48 -04:00
|
|
|
The times parameter allows to apply this n times.
|
2023-02-08 10:01:06 -05:00
|
|
|
**bitRot()** is a function that can be used to mimic (single) bit errors in communication protocols.
|
2021-01-29 06:31:58 -05:00
|
|
|
*Note: a chance of 50% for 2 uint8_t is not equal to 50% chance for 1 uint16_t.*
|
|
|
|
|
2021-08-10 16:16:36 -04:00
|
|
|
|
2023-02-08 10:01:06 -05:00
|
|
|
#### BitsNeeded
|
2021-01-29 06:31:58 -05:00
|
|
|
|
|
|
|
How many bits are needed to store / transmit a number?
|
2021-12-14 05:51:15 -05:00
|
|
|
|
|
|
|
- **bitsNeededReference(n)** reference implementation for uint8_t to uint64_t.
|
2021-01-29 06:31:58 -05:00
|
|
|
- **bitsNeeded(n)** A 'recursive strategy' for uint8_t .. uint64_t provides a fast answer.
|
|
|
|
|
2023-02-08 10:01:06 -05:00
|
|
|
|
|
|
|
#### BitSet64 et al.
|
|
|
|
|
2021-12-14 05:51:15 -05:00
|
|
|
The following functions are made as the normal **bitset()** etcetera do not work for 64 bit.
|
2021-01-29 06:31:58 -05:00
|
|
|
These functions are optimized for speed for **AVR**, **ESP32** and **ESP8266**.
|
2021-12-14 05:51:15 -05:00
|
|
|
|
|
|
|
- **void bitSet64(uint64_t & x, uint8_t bit)** set bit of uint64_t
|
|
|
|
- **void bitClear64(uint64_t & x, uint8_t bit)** clear bit of uint64_t
|
|
|
|
- **void bitToggle64(uint64_t & x, uint8_t bit)** toggle bit of uint64_t
|
|
|
|
- **void bitWrite64(uint64_t & x, uint8_t bit, uint8_t value)** set bit of uint64_t to 0 or 1
|
|
|
|
- **void bitRead64(uint64_t & x, uint8_t bit)** reads bit from uint64_t
|
2021-01-29 06:31:58 -05:00
|
|
|
|
|
|
|
Also added are macro versions of these five functions.
|
2021-12-14 05:51:15 -05:00
|
|
|
|
2021-01-29 06:31:58 -05:00
|
|
|
- **mbitSet64(x, bit)** set bit of uint64_t
|
|
|
|
- **mbitClear64(x, bit)** clear bit of uint64_t
|
|
|
|
- **mbitToggle64(x, bit)** toggle bit of uint64_t
|
|
|
|
- **mbitWrite64(x, bit, value)** set bit of uint64_t to 0 or 1
|
|
|
|
- **mbitRead64(x, bit)** reads bit from uint64_t
|
|
|
|
|
2021-08-10 16:16:36 -04:00
|
|
|
|
2022-04-12 09:50:42 -04:00
|
|
|
## Future
|
|
|
|
|
2023-02-08 10:01:06 -05:00
|
|
|
#### Must
|
|
|
|
|
2022-04-12 09:50:42 -04:00
|
|
|
- improve documentation
|
|
|
|
- improve readability of code
|
2023-02-08 10:01:06 -05:00
|
|
|
|
|
|
|
#### Should
|
|
|
|
|
2022-04-12 09:50:42 -04:00
|
|
|
- add performance tests
|
2023-02-08 10:01:06 -05:00
|
|
|
- **bitRotateLeftRight()** should it do modulo pos?
|
|
|
|
- **bitsNeededRef()** correct for value 0?
|
|
|
|
- **nybbleReverse()** => **nibbleReverse()**
|
2021-01-29 06:31:58 -05:00
|
|
|
|
|
|
|
|
2023-02-08 10:01:06 -05:00
|
|
|
#### Could
|
2021-10-19 10:59:51 -04:00
|
|
|
|
2022-04-12 09:50:42 -04:00
|
|
|
- besides **bitRot()** one can also have timing issues when clocking in bits.
|
|
|
|
A function could be created to mimic such timing error, by shifting bits from a
|
|
|
|
specific position. e.g.
|
|
|
|
- **parShiftLeft(00001010, 3)** ==> 00011010
|
|
|
|
- **bitBurst(00000000, 3)** ==> 00111000 any group of 3 bits will toggle. edges?
|
2023-02-08 10:01:06 -05:00
|
|
|
- **bitRot(value, chance = 50%, times = 1)** extension...
|
2022-04-12 09:50:42 -04:00
|
|
|
- **bitNoggle(value, bit)** - toggle all but one bit. (why?)
|
|
|
|
- **bitSort(value)** 00101001 ==> 00000111
|
|
|
|
or with minimal # toggles?
|
2023-02-08 10:01:06 -05:00
|
|
|
- **bitReverse(uint32_t x, uint8_t n)** see below.
|
2022-04-12 09:50:42 -04:00
|
|
|
- **byteReverse24(uint32_t x)** dedicated 24 bit = 3 bytes e.g RGB
|
2022-04-13 13:33:48 -04:00
|
|
|
- **byteInverse(uint32_t x)** (a,b,c,d) => (255-a, 255-b, 255-c, 255-d) = rather simple ~?
|
2022-04-12 09:50:42 -04:00
|
|
|
- **isBitPalindrome()** byte, word ...
|
2022-04-13 13:33:48 -04:00
|
|
|
- **bitSwap(value, p, q)**
|
2023-02-08 10:01:06 -05:00
|
|
|
- many more :)
|
2021-10-19 10:59:51 -04:00
|
|
|
|
|
|
|
|
2023-02-08 10:01:06 -05:00
|
|
|
#### Wont
|
2021-12-14 05:51:15 -05:00
|
|
|
|
|
|
|
|
|
|
|
|
2023-02-08 10:01:06 -05:00
|
|
|
## ideas
|
|
|
|
|
2022-04-12 09:50:42 -04:00
|
|
|
#### BitReverse n bit number
|
2021-08-10 16:16:36 -04:00
|
|
|
|
|
|
|
Trick to reverse a number of n bits ( 0 < n < 32 ).
|
2021-12-14 05:51:15 -05:00
|
|
|
Could also be done similar with 64 bit and or byte / nibble reverse.
|
2021-08-10 16:16:36 -04:00
|
|
|
|
|
|
|
not as fast as a dedicated version.
|
|
|
|
```cpp
|
|
|
|
uint32_t bitReverse(uint32_t x, uint8_t n)
|
|
|
|
{
|
|
|
|
uint32_t r = bitReverse(x);
|
2023-02-08 10:01:06 -05:00
|
|
|
return r >> (32 - n); // reverse only top n bits.
|
2021-08-10 16:16:36 -04:00
|
|
|
}
|
|
|
|
```
|
|
|
|
Could be added in next release...
|
|
|
|
|
2022-04-12 09:50:42 -04:00
|
|
|
Q: what to do with the first (32-n) bits?
|
|
|
|
Just reverse the last 24 bits and clear bit 24-31 is different than
|
2023-02-08 10:01:06 -05:00
|
|
|
reversing the last 24 bits and keep bit 24-31 as is.
|
2022-04-12 09:50:42 -04:00
|
|
|
```cpp
|
|
|
|
uint32_t bitReverse(uint32_t x, uint8_t n)
|
|
|
|
{
|
|
|
|
uint32_t y = (x >> n) << n;
|
|
|
|
uint32_t r = bitReverse(x);
|
|
|
|
r >>= (32 - n);
|
|
|
|
return y | r;
|
|
|
|
}
|
2023-10-18 10:28:52 -04:00
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
## Support
|
|
|
|
|
|
|
|
If you appreciate my libraries, you can support the development and maintenance.
|
|
|
|
Improve the quality of the libraries by providing issues and Pull Requests, or
|
|
|
|
donate through PayPal or GitHub sponsors.
|
|
|
|
|
|
|
|
Thank you,
|
|
|
|
|