0.3.4 FastShiftIn

This commit is contained in:
Rob Tillaart 2024-07-23 13:32:24 +02:00
parent f5bd30eeef
commit bfc61cdb0e
6 changed files with 125 additions and 64 deletions

View File

@ -6,10 +6,15 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/)
and this project adheres to [Semantic Versioning](http://semver.org/).
## [0.3.4] - 2024-07-22
- add **void read(uint8_t \*array, uint8_t size)** (experimental)
- update readme.md
- reorder functions in .cpp
- minor edits
## [0.3.3] - 2023-10-31
- update readme.md
## [0.3.2] - 2023-02-20
- add (experimental) read16(), read24(), read32() functions.
- changed return types of some functions.

View File

@ -1,12 +1,10 @@
//
// FILE: FastShiftIn.cpp
// AUTHOR: Rob Tillaart
// VERSION: 0.3.3
// VERSION: 0.3.4
// PURPOSE: Fast ShiftIn for 74HC165 register, AVR optimized
// DATE: 2013-09-29
// URL: https://github.com/RobTillaart/FastShiftIn
//
// HISTORY: see changelog.md
#include "FastShiftIn.h"
@ -19,7 +17,7 @@ FastShiftIn::FastShiftIn(uint8_t dataIn, uint8_t clockPin, uint8_t bitOrder)
pinMode(dataIn, INPUT);
pinMode(clockPin, OUTPUT);
// https://www.arduino.cc/reference/en/language/functions/advanced-io/shiftin/
digitalWrite(clockPin, LOW); // assume rising pulses from clock
digitalWrite(clockPin, LOW); // assume rising pulses from clock
#if defined(ARDUINO_ARCH_AVR) || defined(ARDUINO_ARCH_MEGAAVR)
@ -53,14 +51,13 @@ uint16_t FastShiftIn::read()
uint16_t FastShiftIn::read16()
{
uint16_t rv;
if (_bitOrder == LSBFIRST)
{
rv = readLSBFIRST();
uint16_t rv = readLSBFIRST();
rv += uint16_t(readLSBFIRST()) << 8;
return rv;
}
rv = readMSBFIRST();
uint16_t rv = readMSBFIRST();
rv <<= 8;
rv += readMSBFIRST();
return rv;
@ -69,15 +66,14 @@ uint16_t FastShiftIn::read16()
uint32_t FastShiftIn::read24()
{
uint32_t rv;
if (_bitOrder == LSBFIRST)
{
rv = readLSBFIRST();
uint32_t rv = readLSBFIRST();
rv += uint32_t(readLSBFIRST()) << 8;
rv += uint32_t(readLSBFIRST()) << 16;
return rv;
}
rv = readMSBFIRST();
uint32_t rv = readMSBFIRST();
rv <<= 8;
rv += readMSBFIRST();
rv <<= 8;
@ -88,16 +84,15 @@ uint32_t FastShiftIn::read24()
uint32_t FastShiftIn::read32()
{
uint32_t rv;
if (_bitOrder == LSBFIRST)
{
rv = readLSBFIRST();
uint32_t rv = readLSBFIRST();
rv += uint32_t(readLSBFIRST()) << 8;
rv += uint32_t(readLSBFIRST()) << 16;
rv += uint32_t(readLSBFIRST()) << 24;
return rv;
}
rv = readMSBFIRST();
uint32_t rv = readMSBFIRST();
rv <<= 8;
rv += readMSBFIRST();
rv <<= 8;
@ -108,6 +103,46 @@ uint32_t FastShiftIn::read32()
}
uint32_t FastShiftIn::lastRead(void)
{
return _lastValue;
}
void FastShiftIn::read(uint8_t * array, uint8_t size)
{
if (_bitOrder == LSBFIRST)
{
for (uint8_t i = 0; i < size; i++)
{
array[size - i - 1] = readLSBFIRST();
}
return;
}
for (uint8_t i = 0; i < size; i++)
{
array[i] = readMSBFIRST();
}
return;
}
bool FastShiftIn::setBitOrder(const uint8_t bitOrder)
{
if ((bitOrder == LSBFIRST) || (bitOrder == MSBFIRST))
{
_bitOrder = bitOrder;
return true;
};
return false;
}
uint8_t FastShiftIn::getBitOrder(void)
{
return _bitOrder;
}
uint8_t FastShiftIn::readLSBFIRST()
{
@ -118,9 +153,11 @@ uint8_t FastShiftIn::readLSBFIRST()
uint8_t cbmask2 = ~_clockBit;
uint8_t inmask1 = _dataInBit;
for (uint8_t m = 1; m > 0; m <<= 1)
for (uint8_t m = 0x01; m > 0; m <<= 1)
{
// remember state register
uint8_t oldSREG = SREG;
// disable interrupts
noInterrupts();
// clock pulse HIGH
*_clockRegister |= cbmask1;
@ -128,6 +165,7 @@ uint8_t FastShiftIn::readLSBFIRST()
if ((*_dataInRegister & inmask1) > 0) rv |= m;
// clock pulse LOW
*_clockRegister &= cbmask2;
// reset interrupts flag to previous state
SREG = oldSREG;
}
_lastValue = rv;
@ -154,7 +192,9 @@ uint8_t FastShiftIn::readMSBFIRST()
for (uint8_t m = 0x80; m > 0; m >>= 1)
{
// remember state register
uint8_t oldSREG = SREG;
// disable interrupts
noInterrupts();
// clock pulse HIGH
*_clockRegister |= cbmask1;
@ -162,6 +202,7 @@ uint8_t FastShiftIn::readMSBFIRST()
if ((*_dataInRegister & inmask1) > 0) rv |= m;
// clock pulse LOW
*_clockRegister &= cbmask2;
// reset interrupts flag to previous state
SREG = oldSREG;
}
_lastValue = rv;
@ -178,28 +219,5 @@ uint8_t FastShiftIn::readMSBFIRST()
}
uint32_t FastShiftIn::lastRead(void)
{
return _lastValue;
};
bool FastShiftIn::setBitOrder(const uint8_t bitOrder)
{
if ((bitOrder == LSBFIRST) || (bitOrder == MSBFIRST))
{
_bitOrder = bitOrder;
return true;
};
return false;
}
uint8_t FastShiftIn::getBitOrder(void)
{
return _bitOrder;
};
// -- END OF FILE --

View File

@ -2,7 +2,7 @@
//
// FILE: FastShiftIn.h
// AUTHOR: Rob Tillaart
// VERSION: 0.3.3
// VERSION: 0.3.4
// PURPOSE: Fast ShiftIn for 74HC165 register, AVR optimized
// DATE: 2013-09-29
// URL: https://github.com/RobTillaart/FastShiftIn
@ -11,7 +11,7 @@
#include "Arduino.h"
#define FASTSHIFTIN_LIB_VERSION (F("0.3.3"))
#define FASTSHIFTIN_LIB_VERSION (F("0.3.4"))
class FastShiftIn
@ -26,6 +26,9 @@ public:
uint32_t read32(void);
uint32_t lastRead(void);
// Experimental 0.3.4
void read(uint8_t * array, uint8_t size);
// returns false if bitOrder out of range.
bool setBitOrder(uint8_t bitOrder);
uint8_t getBitOrder(void);
@ -37,7 +40,7 @@ public:
private:
uint8_t _bitOrder;
uint32_t _lastValue;
#if defined(ARDUINO_ARCH_AVR) || defined(ARDUINO_ARCH_MEGAAVR)
volatile uint8_t *_dataInRegister;

View File

@ -15,7 +15,7 @@
"type": "git",
"url": "https://github.com/RobTillaart/FastShiftIn.git"
},
"version": "0.3.3",
"version": "0.3.4",
"license": "MIT",
"frameworks": "*",
"platforms": "*",

View File

@ -1,5 +1,5 @@
name=FastShiftIn
version=0.3.3
version=0.3.4
author=Rob Tillaart <rob.tillaart@gmail.com>
maintainer=Rob Tillaart <rob.tillaart@gmail.com>
sentence=Arduino library for (AVR) optimized shiftIn - e.g. for 74HC165

View File

@ -13,12 +13,6 @@
Arduino library for **AVR** optimized shiftIn - e.g. for 74HC165.
Related libraries
- https://github.com/RobTillaart/FastShiftOut
- https://github.com/RobTillaart/FastShiftInOut
- https://github.com/RobTillaart/ShiftInSlow
- https://github.com/RobTillaart/ShiftOutSlow
## Description
@ -28,17 +22,22 @@ It speeds up the shift using low level ports and masks. These are predetermined
in the constructor of the FastShiftIn object.
If not an **ARDUINO_ARCH_AVR** or **ARDUINO_ARCH_MEGAAVR** the class falls back
to the default shiftIn() implementation.
to the default **shiftIn()** implementation.
Since 0.3.2 read16(), read24() and read32() are added.
These are experimental and not fully tested yet.
The library allows to set (and get) the bitOrder and apply this to multiple read()
calls. It also provide access to **readLSBFIRST()** and **readMSBFIRST()** which
are the low level workers and most optimized code (so far).
The library provides wrapper functions to read multi-byte variables.
These are read16(), read24(), read32() and read(array, size).
The latter is used to shift in any size object.
## Performance
### Performance
The performance of **read()** is substantially faster than the default Arduino
**shiftIn()**, but not as fast as HW SPI.
Exact how big the performance gain is can be seen with the example sketch.
The performance of **read()** is substantially faster for **AVR** than the default
Arduino **shiftIn()**, but not as fast as HW SPI.
Exact how large the performance gain is can be seen with the example sketch.
It does a comparison and shows how the class is to be used.
Time in microseconds, Arduino UNO
@ -58,6 +57,14 @@ Time in microseconds, Arduino UNO
faster than the reference.
### Related libraries
- https://github.com/RobTillaart/FastShiftIn
- https://github.com/RobTillaart/FastShiftOut
- https://github.com/RobTillaart/FastShiftInOut
- https://github.com/RobTillaart/ShiftInSlow
- https://github.com/RobTillaart/ShiftOutSlow
## Interface
@ -65,14 +72,20 @@ faster than the reference.
#include "FastShiftIn.h"
```
#### Functions
### Constructor
- **FastShiftIn(uint8_t dataIn, uint8_t clockPin, uint8_t bitOrder = LSBFIRST)** Constructor
### Functions
- **uint16_t read(void)** reads a new value, 8 bit.
- **uint16_t read16(void)** reads a new value, 16 bit.
- **uint32_t read24(void)** reads a new value, 24 bit.
- **uint32_t read32(void)** reads a new value, 32 bit.
- **uint32_t lastRead()** returns last value read.
### Meta
- **bool setBitOrder(uint8_t bitOrder)** set LSBFIRST or MSBFIRST.
Returns false for other values.
- **uint8_t getBitOrder(void)** returns LSBFIRST or MSBFIRST.
@ -80,11 +93,28 @@ Returns false for other values.
- **uint16_t readMSBFIRST(void)** optimized MSB read(), 8 bit.
#### Byte order
### Experimental
It might be that **read16/24/32** has bytes not in the right order.
Then you should use multiple calls to **read()** and merge these
bytes in the order you want them.
- **void read(uint8_t \*array, uint8_t size)** read an array of values.
The order in the array follows as BYTE order MSB / LSB, that is why this function
is made experimental. This might change in the future, and fill the array
in arrival order.
### Byte order
The functions **read16()**, **read24()** and **read32()** of this library assume
that the BIT-order is also the BYTE-order.
This is not always the case as an n-byte element can have n! == factorial(n)
distinct byte orders.
So **read16()** can have two, **read24()** can have six and **read32()** can even have
(in theory) 24 distinct byte orders. Although LSB and MSB are the most common,
other byte orders exist, and sometimes one explicitly wants to reorder the bytes.
If the BIT-order is not the BYTE-order, the user has two options
- call **read()** multiple times and merge the bytes in the order needed.
- call **read32()** (a.o) and reorder the bytes in a separate function.
## Notes
@ -98,15 +128,20 @@ pull up resistors, especially if wires are exceeding 10 cm (4").
#### Must
#### Should
- extend unit tests
#### Could
- esp32 optimization readLSBFIRST readMSBFIRST
- **read(uint8_t \* arr, uint8_t nr)** ??
- example schema
- investigate separate **BYTE**-order,
- only MSBFirst and LSBFirst
- **void setByteOrder()** + **uint8_t getByteOrder()**
- other option is add parameters / overload to make byte order explicit
- **read32(1,0,3,2)** performance penalty + invalid combination.
- investigate ESP32 optimization readLSBFIRST readMSBFIRST
- example schemas
- would it be interesting to make a fastShiftIn16() etc?
- squeeze performance but more maintenance.?