mirror of
https://github.com/RobTillaart/Arduino.git
synced 2024-10-03 18:09:02 -04:00
0.3.4 FastShiftIn
This commit is contained in:
parent
f5bd30eeef
commit
bfc61cdb0e
@ -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.
|
||||
|
@ -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 --
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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": "*",
|
||||
|
@ -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
|
||||
|
@ -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.?
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user