0.1.5 bitHelpers

This commit is contained in:
rob tillaart 2021-12-14 11:51:15 +01:00
parent 9e35d9b6bc
commit 9648c886cb
6 changed files with 192 additions and 63 deletions

View File

@ -1,6 +1,6 @@
MIT License
Copyright (c) 2015-2021 Rob Tillaart
Copyright (c) 2015-2022 Rob Tillaart
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@ -8,7 +8,7 @@
# bitHelpers
Arduino library with functions on bit level
Arduino library with functions on bit level.
## Description
@ -19,9 +19,9 @@ 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.
If they don't please let me know.
If they don't please file an issue on GitHub.
New bit functions can be added or investigated, please post an issue.
New bit functions can be added or investigated, please file an issue on GitHub.
## Interface
@ -30,34 +30,41 @@ New bit functions can be added or investigated, please post an issue.
### 0.1.0
BitCount, several implementations to compare performance.
- **uint8_t bitCountReference(uint32_t val)** returns nr of bits set in a value.
- **uint8_t bitCountKR(uint32_t val)** Kerningham Ritchie bitCount
- **uint8_t bitCountArray(uint32_t val)** count per nybble with lookup table
- **uint8_t bitCountF1(uint32_t val)** SWAG algorithm variant
- **uint8_t bitCountF2(uint32_t val)** SWAG algorithm variant
- **uint8_t bitCountReference(uint32_t value)** returns number of bits set in a value.
- **uint8_t bitCountKR(uint32_t value)** Kerningham Ritchie bitCount.
- **uint8_t bitCountArray(uint32_t value)** count per nybble with lookup table.
- **uint8_t bitCountF1(uint32_t value)** SWAG algorithm variant.
- **uint8_t bitCountF2(uint32_t value)** SWAG algorithm variant.
BitCount - fastest version, SWAG algorithm
- **uint8_t bitCount(uint8_t val)** available for 16, 32 and 64 bit.
- **uint8_t bitCount(uint8_t value)** available for 16, 32 and 64 bit.
Reverse: uint8_t .. uint64_t
- **T bitReverse(T val)** reverses bits in a uint8_t .. uint64_t
- **T nybbleReverse(T val)** reverses nibbles (4 bit) in a uint8_t .. uint64_t
- **T byteReverse(T val)** reverses bytes (8 bit) in a uint16_t .. uint64_t
- **T wordReverse(T val)** reverses words (16 bit) in uint32_t and uint64_t
Swap upper and lower half: uint8_t .. uint64_t
- **T swap(T val)** 0x12345678 ==> 0x56781234
- **T bitReverse(T value)** reverses bits in a uint8_t .. uint64_t.
- **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.
Swap upper and lower half: uint8_t .. uint64_t.
- **T swap(T value)** 0x12345678 ==> 0x56781234.
Rotate Left / Right: uint8_t .. uint64_t
if pos larger than # bits original value is returned.
- **T bitRotateLeft(T value, uint8_t pos)**
- **T bitRotateRight(T value, uint8_t pos)**
BitFlip: uint8_t .. uint64_t a.k.a toggle
if pos larger than # bits original value is returned.
- **T bitFlip(T value, uint8_t pos)** flips a single bit at pos
BitRot: uint8_t .. uint64_t
- **T bitRot(T value, float chance = 0.5)** random damage to a single bit of a value,
chance = float 0.0 .. 1.0 that one random bit is toggled.
**bitRot()** is a function that can be used to mimic single bit errors in communication protocols.
@ -67,18 +74,21 @@ chance = float 0.0 .. 1.0 that one random bit is toggled.
### 0.1.1 added
How many bits are needed to store / transmit a number?
- **bitsNeededReference(n)** reference implementation for uit to uint64_t.
- **bitsNeededReference(n)** reference implementation for uint8_t to uint64_t.
- **bitsNeeded(n)** A 'recursive strategy' for uint8_t .. uint64_t provides a fast answer.
The following functions are made as the normal **bitset()** etc do not work for 64 bit.
The following functions are made as the normal **bitset()** etcetera do not work for 64 bit.
These functions are optimized for speed for **AVR**, **ESP32** and **ESP8266**.
- **void bitSet64(uint64 & x, uint8_t bit)** set bit of uint64_t
- **void bitClear64(uint64 & x, uint8_t bit)** clear bit of uint64_t
- **void bitToggle64(uint64 & x, uint8_t bit)** toggle bit of uint64_t
- **void bitWrite64(uint64 & x, uint8_t bit, uint8_t value)** set bit of uint64_t to 0 or 1
- **void bitRead64(uint64 & x, uint8_t bit)** reads bit from uint64_t
- **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
Also added are macro versions of these five functions.
- **mbitSet64(x, bit)** set bit of uint64_t
- **mbitClear64(x, bit)** clear bit of uint64_t
- **mbitToggle64(x, bit)** toggle bit of uint64_t
@ -103,10 +113,15 @@ Added Arduino-CI and unit tests
- update readme.md with badges
### 0.1.5
- update library.json, minor edits
## BitReverse n bit number
Trick to reverse a number of n bits ( 0 < n < 32 ).
Could also be done similar with 64 bit and or byte / nybble reverse.
Could also be done similar with 64 bit and or byte / nibble reverse.
not as fast as a dedicated version.
```cpp
@ -121,6 +136,8 @@ Could be added in next release...
## Future
- improve documentation
- improve readability of code (val => value and pos => position)
- 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.
@ -135,6 +152,7 @@ specific position. e.g.
- add **byteInverse(uint32_t x)** (a,b,c,d) => (255-a, 255-b, 255-c, 255-d)
- performance tests
## Operations
See examples.

View File

@ -2,7 +2,7 @@
//
// FILE: bitHelpers.h
// AUTHOR: Rob Tillaart
// VERSION: 0.1.4
// VERSION: 0.1.5
// DATE: 2015-11-07
// PURPOSE: Arduino library with functions on bit level
// URL: https://github.com/RobTillaart/bitHelpers
@ -14,11 +14,12 @@
// 0.1.2 2020-12-14 add Arduino-CI + unit tests
// 0.1.3 2021-08-09 update readme.md + unit tests
// 0.1.4 2021-10-19 update Arduino-CI + badges
// 0.1.5 2021-12-14 update library.json, license, minor edits
#include "Arduino.h"
#define BITHELPER_LIB_VERSION (F("0.1.4"))
#define BITHELPER_LIB_VERSION (F("0.1.5"))
#define BH_BIG_NR 1000000000
@ -149,9 +150,9 @@ uint8_t bitCount(uint64_t value)
//
// BIT REVERSE
//
uint8_t bitReverse(uint8_t val)
uint8_t bitReverse(uint8_t value)
{
uint8_t x = val;
uint8_t x = value;
x = (((x & 0xAA) >> 1) | ((x & 0x55) << 1));
x = (((x & 0xCC) >> 2) | ((x & 0x33) << 2));
x = (x >> 4) | (x << 4);
@ -159,9 +160,9 @@ uint8_t bitReverse(uint8_t val)
}
uint16_t bitReverse(uint16_t val)
uint16_t bitReverse(uint16_t value)
{
uint16_t x = val;
uint16_t x = value;
x = (((x & 0xAAAA) >> 1) | ((x & 0x5555) << 1));
x = (((x & 0xCCCC) >> 2) | ((x & 0x3333) << 2));
x = (((x & 0xF0F0) >> 4) | ((x & 0x0F0F) << 4));
@ -170,9 +171,9 @@ uint16_t bitReverse(uint16_t val)
}
uint32_t bitReverse(uint32_t val)
uint32_t bitReverse(uint32_t value)
{
uint32_t x = val;
uint32_t x = value;
x = (((x & 0xAAAAAAAA) >> 1) | ((x & 0x55555555) << 1));
x = (((x & 0xCCCCCCCC) >> 2) | ((x & 0x33333333) << 2));
x = (((x & 0xF0F0F0F0) >> 4) | ((x & 0x0F0F0F0F) << 4));
@ -182,9 +183,9 @@ uint32_t bitReverse(uint32_t val)
}
uint64_t bitReverse(uint64_t val)
uint64_t bitReverse(uint64_t value)
{
uint64_t x = val;
uint64_t x = value;
x = (((x & 0xAAAAAAAAAAAAAAAA) >> 1) | ((x & 0x5555555555555555) << 1));
x = (((x & 0xCCCCCCCCCCCCCCCC) >> 2) | ((x & 0x3333333333333333) << 2));
x = (((x & 0xF0F0F0F0F0F0F0F0) >> 4) | ((x & 0x0F0F0F0F0F0F0F0F) << 4));
@ -199,26 +200,26 @@ uint64_t bitReverse(uint64_t val)
//
// NYBBLE REVERSE
//
uint8_t nybbleReverse(uint8_t val)
uint8_t nybbleReverse(uint8_t value)
{
uint8_t x = val;
uint8_t x = value;
x = (x >> 4) | (x << 4);
return x;
}
uint16_t nybbleReverse(uint16_t val)
uint16_t nybbleReverse(uint16_t value)
{
uint16_t x = val;
uint16_t x = value;
x = (((x & 0xF0F0) >> 4) | ((x & 0x0F0F) << 4));
x = (x >> 8) | (x << 8);
return x;
}
uint32_t nybbleReverse(uint32_t val)
uint32_t nybbleReverse(uint32_t value)
{
uint32_t x = val;
uint32_t x = value;
x = (((x & 0xF0F0F0F0) >> 4) | ((x & 0x0F0F0F0F) << 4));
x = (((x & 0xFF00FF00) >> 8) | ((x & 0x00FF00FF) << 8));
x = (x >> 16) | (x << 16);
@ -226,9 +227,9 @@ uint32_t nybbleReverse(uint32_t val)
}
uint64_t nybbleReverse(uint64_t val)
uint64_t nybbleReverse(uint64_t value)
{
uint64_t x = val;
uint64_t x = value;
x = (((x & 0xF0F0F0F0F0F0F0F0) >> 4) | ((x & 0x0F0F0F0F0F0F0F0F) << 4));
x = (((x & 0xFF00FF00FF00FF00) >> 8) | ((x & 0x00FF00FF00FF00FF) << 8));
x = (((x & 0xFFFF0000FFFF0000) >> 16) | ((x & 0x0000FFFF0000FFFF) << 16));
@ -241,26 +242,26 @@ uint64_t nybbleReverse(uint64_t val)
//
// BYTE REVERSE
//
uint16_t byteReverse(uint16_t val)
uint16_t byteReverse(uint16_t value)
{
uint16_t x = val;
uint16_t x = value;
x = (x >> 8) | (x << 8);
return x;
}
uint32_t byteReverse(uint32_t val)
uint32_t byteReverse(uint32_t value)
{
uint32_t x = val;
uint32_t x = value;
x = (((x & 0xFF00FF00) >> 8) | ((x & 0x00FF00FF) << 8));
x = (x >> 16) | (x << 16);
return x;
}
uint64_t byteReverse(uint64_t val)
uint64_t byteReverse(uint64_t value)
{
uint64_t x = val;
uint64_t x = value;
x = (((x & 0xFF00FF00FF00FF00) >> 8) | ((x & 0x00FF00FF00FF00FF) << 8));
x = (((x & 0xFFFF0000FFFF0000) >> 16) | ((x & 0x0000FFFF0000FFFF) << 16));
x = (x >> 32) | (x << 32);
@ -272,17 +273,17 @@ uint64_t byteReverse(uint64_t val)
//
// WORD REVERSE
//
uint32_t wordReverse(uint32_t val)
uint32_t wordReverse(uint32_t value)
{
uint32_t x = val;
uint32_t x = value;
x = (x >> 16) | (x << 16);
return x;
}
uint64_t wordReverse(uint64_t val)
uint64_t wordReverse(uint64_t value)
{
uint64_t x = val;
uint64_t x = value;
x = (((x & 0xFFFF0000FFFF0000) >> 16) | ((x & 0x0000FFFF0000FFFF) << 16));
x = (x >> 32) | (x << 32);
return x;
@ -293,27 +294,27 @@ uint64_t wordReverse(uint64_t val)
//
// SWAP HI LO
//
uint8_t swap(uint8_t val)
uint8_t swap(uint8_t value)
{
return (val << 4) | (val >> 4);
return (value << 4) | (value >> 4);
}
uint16_t swap(uint16_t val)
uint16_t swap(uint16_t value)
{
return (val << 8) | (val >> 8);
return (value << 8) | (value >> 8);
}
uint32_t swap(uint32_t val)
uint32_t swap(uint32_t value)
{
return (val << 16) | (val >> 16);
return (value << 16) | (value >> 16);
}
uint64_t swap(uint64_t val)
uint64_t swap(uint64_t value)
{
return (val << 32) | (val >> 32);
return (value << 32) | (value >> 32);
}

View File

@ -0,0 +1,109 @@
//
// FILE: bitHelpers_test.ino
// AUTHOR: Rob Tillaart
// VERSION: 0.1.0
// PURPOSE: demo
// DATE: 2021-08-04
// URL: https://github.com/RobTillaart/bitHelpers
#include "bitHelpers.h"
uint32_t start, stop;
void setup()
{
Serial.begin(115200);
Serial.println();
Serial.println(__FILE__);
Serial.println();
test_32_bit();
test_24_bit();
Serial.println("\nDone...");
}
void loop()
{
}
//////////////////////////////////
void test_24_bit()
{
Serial.println();
Serial.println(__FUNCTION__);
uint32_t x = 0x9B3FAA;
uint32_t y = byteReverse(x);
uint32_t z = byteReverse(x) >> 8;
Serial.println(x, HEX);
Serial.println(y, HEX);
Serial.println(z, HEX);
Serial.println();
printHex32(y);
printHex32(z);
Serial.println();
x = 0x5D9504;
y = byteReverse(x);
z = byteReverse(x) >> 8;
Serial.println(x, HEX);
Serial.println(y, HEX);
Serial.println(z, HEX);
Serial.println();
Serial.println();
}
void test_32_bit()
{
Serial.println();
Serial.println(__FUNCTION__);
Serial.println();
}
void printHex16(uint16_t x)
{
if (x < 0x1000) Serial.print('0');
if (x < 0x100) Serial.print('0');
if (x < 0x10) Serial.print('0');
Serial.println(x, HEX);
}
void printHex24(uint32_t x)
{
if (x < 0x100000) Serial.print('0');
if (x < 0x10000) Serial.print('0');
if (x < 0x1000) Serial.print('0');
if (x < 0x100) Serial.print('0');
if (x < 0x10) Serial.print('0');
Serial.println(x, HEX);
}
void printHex32(uint32_t x)
{
if (x < 0x10000000) Serial.print('0');
if (x < 0x1000000) Serial.print('0');
if (x < 0x100000) Serial.print('0');
if (x < 0x10000) Serial.print('0');
if (x < 0x1000) Serial.print('0');
if (x < 0x100) Serial.print('0');
if (x < 0x10) Serial.print('0');
Serial.println(x, HEX);
}
// -- END OF FILE --

View File

@ -15,8 +15,9 @@
"type": "git",
"url": "https://github.com/RobTillaart/bitHelpers.git"
},
"version": "0.1.4",
"version": "0.1.5",
"license": "MIT",
"frameworks": "*",
"platforms": "*"
"platforms": "*",
"headers": "bitHelpers.h"
}

View File

@ -1,5 +1,5 @@
name=bitHelpers
version=0.1.4
version=0.1.5
author=Rob Tillaart <rob.tillaart@gmail.com>
maintainer=Rob Tillaart <rob.tillaart@gmail.com>
sentence=Arduino library with functions on bit level