0.4.0 FastShiftOut

This commit is contained in:
Rob Tillaart 2024-09-19 14:17:25 +02:00
parent f458e0690e
commit 6ce71e3145
11 changed files with 527 additions and 75 deletions

View File

@ -6,6 +6,18 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/)
and this project adheres to [Semantic Versioning](http://semver.org/).
## [0.4.0] - 2024-09-03
- fix #15, loop unroll option, improving performance, kudos to nt314p
- fixed bug in test program (see #15)
- added flag to select LOOP UNROLL (is optional as it gives larger code size)
- optimized the not unrolled loop with ideas of the unrolling version.
- corrected type lastValue to uint8_t
- add FastShiftOut_scope_test.ino
- update readme.md
- minor edits
----
## [0.3.3] - 2024-07-23
- Fix #13, add wrapper functions
- write16/24/32, write(array, size)

View File

@ -13,7 +13,9 @@ FastShiftOut FSO(12, 13, LSBFIRST);
void setup()
{
Serial.begin(115200);
Serial.print("example fastShiftOut: ");
Serial.print(__FILE__);
Serial.print("FASTSHIFTOUT_LIB_VERSION: ");
Serial.println(FASTSHIFTOUT_LIB_VERSION);
Serial.println("\nPerformance - time in us");

View File

@ -0,0 +1,69 @@
//
// FILE: FastShiftOut_scope_test.ino
// AUTHOR: Rob Tillaart
// PURPOSE: test sketch for scope
// URL: https://github.com/RobTillaart/FastShiftOut
#include "FastShiftOut.h"
FastShiftOut FSO(12, 13, LSBFIRST);
uint32_t start, duration1, duration2;
void setup()
{
Serial.begin(115200);
Serial.println(__FILE__);
Serial.print("FASTSHIFTOUT_LIB_VERSION: ");
Serial.println(FASTSHIFTOUT_LIB_VERSION);
Serial.println();
// test1();
pinMode(12, OUTPUT);
}
void test1()
{
for (int i = 0; i < 1000; i++)
{
FSO.write(0x55);
}
}
void test2()
{
for (int i = 0; i < 1000; i++)
{
FSO.writeLSBFIRST(0x88);
}
}
void test3()
{
for (int i = 0; i < 1000; i++)
{
FSO.write32(0x55555555);
}
}
void loop()
{
// ~ 1000 Hz test
// digitalWrite(12, HIGH);
// delayMicroseconds(1000);
// digitalWrite(12, LOW);
// delayMicroseconds(1000);
// reference
// shiftOut(12, 13, MSBFIRST, 0x55);
FSO.write(0x55);
delayMicroseconds(100);
}
// -- END OF FILE --

View File

@ -1,10 +1,9 @@
//
// FILE: FastShiftOut_test.ino
// AUTHOR: Rob Tillaart
// PURPOSE: test sketch
// PURPOSE: performance test sketch
// URL: https://github.com/RobTillaart/FastShiftOut
#include "FastShiftOut.h"
FastShiftOut FSO(12, 13, LSBFIRST);
@ -15,7 +14,9 @@ uint32_t start, duration1, duration2;
void setup()
{
Serial.begin(115200);
Serial.print("example fastShiftOut: ");
Serial.println(__FILE__);
Serial.print("FASTSHIFTOUT_LIB_VERSION: ");
Serial.println(FASTSHIFTOUT_LIB_VERSION);
Serial.println("\nPerformance - time in us");
@ -24,6 +25,9 @@ void setup()
test3();
test4();
test5();
test6();
test7();
test8();
Serial.println("\ndone ...\n");
}
@ -72,8 +76,8 @@ void test2()
start = micros();
for (int i = 0; i < 1000; i++)
{
FSO.write(0x55);
FSO.write(0x55);
FSO.writeLSBFIRST(0x55);
FSO.writeLSBFIRST(0x55);
}
duration2 = micros() - start;
Serial.print("writeLSBFIRST: ");
@ -90,7 +94,7 @@ void test3()
start = micros();
for (int i = 0; i < 1000; i++)
{
FSO.write(0x55);
FSO.writeMSBFIRST(0x55);
}
duration1 = micros() - start;
Serial.print("writeMSBFIRST: ");
@ -142,6 +146,90 @@ void test4()
void test5()
{
start = micros();
for (int i = 0; i < 1000; i++)
{
FSO.write16(0x5555);
}
duration1 = micros() - start;
Serial.print(" write16: ");
Serial.println(duration1 * 0.001);
delay(100);
start = micros();
for (int i = 0; i < 1000; i++)
{
FSO.write16(0x5555);
FSO.write16(0x5555);
}
duration2 = micros() - start;
Serial.print(" write16: ");
Serial.println(duration2 * 0.001);
Serial.print(" Delta: ");
Serial.println((duration2 - duration1) * 0.001);
Serial.println();
delay(100);
}
void test6()
{
start = micros();
for (int i = 0; i < 1000; i++)
{
FSO.write24(0x555555);
}
duration1 = micros() - start;
Serial.print(" write24: ");
Serial.println(duration1 * 0.001);
delay(100);
start = micros();
for (int i = 0; i < 1000; i++)
{
FSO.write24(0x555555);
FSO.write24(0x555555);
}
duration2 = micros() - start;
Serial.print(" write24: ");
Serial.println(duration2 * 0.001);
Serial.print(" Delta: ");
Serial.println((duration2 - duration1) * 0.001);
Serial.println();
delay(100);
}
void test7()
{
start = micros();
for (int i = 0; i < 1000; i++)
{
FSO.write32(0x55555555);
}
duration1 = micros() - start;
Serial.print(" write32: ");
Serial.println(duration1 * 0.001);
delay(100);
start = micros();
for (int i = 0; i < 1000; i++)
{
FSO.write32(0x55555555);
FSO.write32(0x55555555);
}
duration2 = micros() - start;
Serial.print(" write32: ");
Serial.println(duration2 * 0.001);
Serial.print(" Delta: ");
Serial.println((duration2 - duration1) * 0.001);
Serial.println();
delay(100);
}
void test8()
{
Serial.println("\nTest print interface");
start = micros();
@ -172,6 +260,7 @@ void test5()
duration1 = micros() - start;
Serial.print("println(3.14159265, 4): \t");
Serial.println(duration1 * 0.01);
Serial.println();
delay(100);
}

View File

@ -0,0 +1,41 @@
IDE: 1.8.19
Board: UNO
FASTSHIFTOUT_LIB_VERSION: 0.3.3
Performance - time in us
write: 23.51
write: 45.78
Delta: 22.27
writeLSBFIRST: 22.51
writeLSBFIRST: 44.76
Delta: 22.25
writeMSBFIRST: 22.51
writeMSBFIRST: 44.77
Delta: 22.26
Standard shiftOut1: 89.85
Standard shiftOut2: 179.44
Delta: 89.59
write16: 45.65
write16: 91.04
Delta: 45.39
write24: 67.90
write24: 135.56
Delta: 67.66
write32: 90.16
write32: 180.07
Delta: 89.91
Test print interface
println("Hello world"): 328.92
println(1357): 311.60
println(3.14159265, 4): 716.04
done ...

View File

@ -0,0 +1,45 @@
IDE: 1.8.19
Board: UNO
loop unrolled version
FASTSHIFTOUT_LIB_VERSION: 0.4.0
Performance - time in us
write: 12.76
write: 24.27
Delta: 11.51
writeLSBFIRST: 11.76
writeLSBFIRST: 23.26
Delta: 11.50
writeMSBFIRST: 11.76
writeMSBFIRST: 23.27
Delta: 11.50
Standard shiftOut1: 89.85
Standard shiftOut2: 179.45
Delta: 89.60
write16: 24.14
write16: 48.04
Delta: 23.89
write24: 35.66
write24: 71.05
Delta: 35.40
write32: 47.16
write32: 94.06
Delta: 46.90
Test print interface
println("Hello world"): 189.20
println(1357): 247.12
println(3.14159265, 4): 629.96
done ...

View File

@ -1,7 +1,7 @@
//
// FILE: FastShiftOut.cpp
// AUTHOR: Rob Tillaart
// VERSION: 0.3.2
// VERSION: 0.4.0
// PURPOSE: ShiftOut that implements the Print interface
// DATE: 2013-08-22
// URL: https://github.com/RobTillaart/FastShiftOut
@ -47,7 +47,6 @@ size_t FastShiftOut::write(uint8_t data)
}
// EXPERIMENTAL 0.3.3
size_t FastShiftOut::write16(uint16_t data)
{
if (_bitOrder == LSBFIRST)
@ -64,7 +63,6 @@ size_t FastShiftOut::write16(uint16_t data)
}
// EXPERIMENTAL 0.3.3
size_t FastShiftOut::write24(uint32_t data)
{
if (_bitOrder == LSBFIRST)
@ -85,7 +83,6 @@ size_t FastShiftOut::write24(uint32_t data)
}
// EXPERIMENTAL 0.3.3
size_t FastShiftOut::write32(uint32_t data)
{
if (_bitOrder == LSBFIRST)
@ -109,10 +106,8 @@ size_t FastShiftOut::write32(uint32_t data)
}
// EXPERIMENTAL 0.3.3
size_t FastShiftOut::write(uint8_t * array, size_t size)
{
size_t n = 0;
if (_bitOrder == LSBFIRST)
{
for (size_t i = size; i > 0; ) // from end to begin ????
@ -155,7 +150,6 @@ uint8_t FastShiftOut::getBitOrder(void)
}
size_t FastShiftOut::writeLSBFIRST(uint8_t data)
{
uint8_t value = data;
@ -163,23 +157,103 @@ size_t FastShiftOut::writeLSBFIRST(uint8_t data)
#if defined(ARDUINO_ARCH_AVR) || defined(ARDUINO_ARCH_MEGAAVR)
#if defined(FASTSHIFTOUT_AVR_LOOP_UNROLLED) // AVR SPEED OPTIMIZED
uint8_t cbmask1 = _clockBit;
uint8_t cbmask2 = ~_clockBit;
uint8_t outmask1 = _dataOutBit;
uint8_t outmask2 = ~_dataOutBit;
for (uint8_t m = 1; m > 0; m <<= 1)
{
volatile uint8_t* localDataOutRegister = _dataOutRegister;
volatile uint8_t* localClockRegister = _clockRegister;
// disable interrupts (for all bits)
uint8_t oldSREG = SREG;
noInterrupts();
if ((value & m) == 0) *_dataOutRegister &= outmask2;
else *_dataOutRegister |= outmask1;
*_clockRegister |= cbmask1;
*_clockRegister &= cbmask2;
if ((value & 0x01) == 0) *localDataOutRegister &= outmask2;
else *localDataOutRegister |= outmask1;
// *_clockRegister |= cbmask1;
// *_clockRegister &= cbmask2;
// following code is allowed as interrupts are disabled.
// so register can not change
uint8_t r = *localClockRegister;
*localClockRegister = r | cbmask1; // set one bit
*localClockRegister = r; // reset bit
if ((value & 0x02) == 0) *localDataOutRegister &= outmask2;
else *localDataOutRegister |= outmask1;
r = *localClockRegister;
*localClockRegister = r | cbmask1; // set one bit
*localClockRegister = r; // reset it
if ((value & 0x04) == 0) *localDataOutRegister &= outmask2;
else *localDataOutRegister |= outmask1;
r = *localClockRegister;
*localClockRegister = r | cbmask1; // set one bit
*localClockRegister = r; // reset it
if ((value & 0x08) == 0) *localDataOutRegister &= outmask2;
else *localDataOutRegister |= outmask1;
r = *localClockRegister;
*localClockRegister = r | cbmask1; // set one bit
*localClockRegister = r; // reset it
if ((value & 0x10) == 0) *localDataOutRegister &= outmask2;
else *localDataOutRegister |= outmask1;
r = *localClockRegister;
*localClockRegister = r | cbmask1; // set one bit
*localClockRegister = r; // reset it
if ((value & 0x20) == 0) *localDataOutRegister &= outmask2;
else *localDataOutRegister |= outmask1;
r = *localClockRegister;
*localClockRegister = r | cbmask1; // set one bit
*localClockRegister = r; // reset it
if ((value & 0x40) == 0) *localDataOutRegister &= outmask2;
else *localDataOutRegister |= outmask1;
r = *localClockRegister;
*localClockRegister = r | cbmask1; // set one bit
*localClockRegister = r; // reset it
if ((value & 0x80) == 0) *localDataOutRegister &= outmask2;
else *localDataOutRegister |= outmask1;
r = *localClockRegister;
*localClockRegister = r | cbmask1; // set one bit
*localClockRegister = r; // reset it
// restore interrupt state
SREG = oldSREG;
#else // AVR SIZE OPTIMIZED
uint8_t cbmask1 = _clockBit;
uint8_t outmask1 = _dataOutBit;
uint8_t outmask2 = ~_dataOutBit;
volatile uint8_t* localDataOutRegister = _dataOutRegister;
volatile uint8_t* localClockRegister = _clockRegister;
// disable interrupts (for all bits)
uint8_t oldSREG = SREG;
noInterrupts();
for (uint8_t m = 1; m > 0; m <<= 1)
{
// process one bit
if ((value & m) == 0) *localDataOutRegister &= outmask2;
else *localDataOutRegister |= outmask1;
uint8_t r = *localClockRegister;
*localClockRegister = r | cbmask1; // set one bit
*localClockRegister = r; // reset it
}
#else
// restore interrupt state
SREG = oldSREG;
#endif // if (AVR)
#else // other platforms reference shiftOut()
shiftOut(_dataPinOut, _clockPin, LSBFIRST, value);
@ -196,23 +270,104 @@ size_t FastShiftOut::writeMSBFIRST(uint8_t data)
#if defined(ARDUINO_ARCH_AVR) || defined(ARDUINO_ARCH_MEGAAVR)
#if defined(FASTSHIFTOUT_AVR_LOOP_UNROLLED) // AVR SPEED OPTIMIZED
uint8_t cbmask1 = _clockBit;
uint8_t cbmask2 = ~_clockBit;
// uint8_t cbmask2 = ~_clockBit;
uint8_t outmask1 = _dataOutBit;
uint8_t outmask2 = ~_dataOutBit;
for (uint8_t m = 0x80; m > 0; m >>= 1)
{
volatile uint8_t* localDataOutRegister = _dataOutRegister;
volatile uint8_t* localClockRegister = _clockRegister;
// disable interrupts (for all bits)
uint8_t oldSREG = SREG;
noInterrupts();
if ((value & m) == 0) *_dataOutRegister &= outmask2;
else *_dataOutRegister |= outmask1;
*_clockRegister |= cbmask1;
*_clockRegister &= cbmask2;
if ((value & 0x80) == 0) *localDataOutRegister &= outmask2;
else *localDataOutRegister |= outmask1;
// *localClockRegister |= cbmask1;
// *localClockRegister &= cbmask2;
// following code is allowed as interrupts are disabled.
// so register can not change
uint8_t r = *localClockRegister;
*localClockRegister = r | cbmask1; // set one bit
*localClockRegister = r; // reset it
if ((value & 0x40) == 0) *localDataOutRegister &= outmask2;
else *localDataOutRegister |= outmask1;
r = *localClockRegister;
*localClockRegister = r | cbmask1; // set one bit
*localClockRegister = r; // reset it
if ((value & 0x20) == 0) *localDataOutRegister &= outmask2;
else *localDataOutRegister |= outmask1;
r = *localClockRegister;
*localClockRegister = r | cbmask1; // set one bit
*localClockRegister = r; // reset it
if ((value & 0x10) == 0) *localDataOutRegister &= outmask2;
else *localDataOutRegister |= outmask1;
r = *localClockRegister;
*localClockRegister = r | cbmask1; // set one bit
*localClockRegister = r; // reset it
if ((value & 0x08) == 0) *localDataOutRegister &= outmask2;
else *localDataOutRegister |= outmask1;
r = *localClockRegister;
*localClockRegister = r | cbmask1; // set one bit
*localClockRegister = r; // reset it
if ((value & 0x04) == 0) *localDataOutRegister &= outmask2;
else *localDataOutRegister |= outmask1;
r = *localClockRegister;
*localClockRegister = r | cbmask1; // set one bit
*localClockRegister = r; // reset it
if ((value & 0x02) == 0) *localDataOutRegister &= outmask2;
else *localDataOutRegister |= outmask1;
r = *localClockRegister;
*localClockRegister = r | cbmask1; // set one bit
*localClockRegister = r; // reset it
if ((value & 0x01) == 0) *localDataOutRegister &= outmask2;
else *localDataOutRegister |= outmask1;
r = *localClockRegister;
*localClockRegister = r | cbmask1; // set one bit
*localClockRegister = r; // reset it
// restore interrupt state
SREG = oldSREG;
#else // AVR SIZE OPTIMIZED
uint8_t cbmask1 = _clockBit;
uint8_t outmask1 = _dataOutBit;
uint8_t outmask2 = ~_dataOutBit;
volatile uint8_t* localDataOutRegister = _dataOutRegister;
volatile uint8_t* localClockRegister = _clockRegister;
// disable interrupts (for all bits)
uint8_t oldSREG = SREG;
noInterrupts();
for (uint8_t m = 0x80; m > 0; m >>= 1)
{
// process one bit
if ((value & m) == 0) *localDataOutRegister &= outmask2;
else *localDataOutRegister |= outmask1;
uint8_t r = *localClockRegister;
*localClockRegister = r | cbmask1; // set one bit
*localClockRegister = r; // reset it
}
#else
// restore interrupt state
SREG = oldSREG;
#endif // if (AVR)
#else // other platforms reference shiftOut()
shiftOut(_dataPinOut, _clockPin, MSBFIRST, value);

View File

@ -2,7 +2,7 @@
//
// FILE: FastShiftOut.h
// AUTHOR: Rob Tillaart
// VERSION: 0.3.3
// VERSION: 0.4.0
// PURPOSE: shiftOut class that implements the Print interface
// DATE: 2013-08-22
// URL: https://github.com/RobTillaart/FastShiftOut
@ -11,7 +11,10 @@
#include "Arduino.h"
#include "Print.h"
#define FASTSHIFTOUT_LIB_VERSION (F("0.3.3"))
#define FASTSHIFTOUT_LIB_VERSION (F("0.4.0"))
// uncomment next line to get SPEED OPTIMIZED CODE
#define FASTSHIFTOUT_AVR_LOOP_UNROLLED 1
class FastShiftOut : public Print
@ -39,7 +42,7 @@ public:
private:
uint8_t _bitOrder;
int _lastValue;
uint8_t _lastValue;
#if defined(ARDUINO_ARCH_AVR) || defined(ARDUINO_ARCH_MEGAAVR)

View File

@ -16,8 +16,8 @@ Arduino library for **AVR** optimized shiftOut - e.g. 74HC595.
## Description
FastShiftOut is a class that has optimized code (AVR only) to shift out data faster
than the normal **shiftOut()** function.
FastShiftOut is a class that has optimized code (**AVR** only) to shift out data faster
than the default provided **shiftOut()** function.
It speeds up the shift using low level ports and masks. These are predetermined
in the constructor of the FastShiftOut object.
@ -33,27 +33,48 @@ These are write16(), write24(), write32() and write(array, size).
The latter is used to shift out any size object.
### 0.4.0 breaking changes
The 0.4.0 version has a flag to unroll the inner loop in **writeLSBFIRST()**
and **writeMSBFIRST()**. The AVR optimized code blocks the interrupts per byte.
Note: this optimization is new and thus experimental.
Feedback, including improvements, is welcome.
### Performance
The performance of **write()** is substantially faster for **AVR** than the default
Arduino **shiftOut()**, 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
| function | 0.2.4 | 0.3.1 | 0.3.3 |
|:-------------------------|--------:|---------:|---------:|
| write() | 21.66 | 22.48 | 22.37 |
| writeLSBFIRST() | 22.94 | 23.37 | 23.26 |
| writeMSBFIRST() | 20.30 | 21.86 | 21.75 |
| reference shiftOut() | 89.74 | 89.74 | 89.60 |
| println("Hello world") | | 328.92 | 328.92 |
| println(1357) | | 313.56 | 311.68 |
| println(3.14159265, 4) | | 717.36 | 716.04 |
Arduino **shiftOut()**, but not as fast as HW SPI (need test?).
Exact how large the performance gain is can be seen with the example **FastShiftOut_test.ino**.
It does a measurement of different functions and shows how the class is to be used.
See also table below.
Note: 0.3.3 has improved the measurement, not the code sec.
#### Measurements
Numbers may vary depending on bit-order flag.
Indicative time in microseconds, Arduino UNO, IDE 1.8.19, measured over 1000 calls.
(delta between 2 calls and 1 call to eliminate overhead)
| function | 0.2.4 | 0.3.1 | 0.3.3 | 0.4.0 | 0.4.0L |
|:-------------------------|--------:|---------:|---------:|---------:|---------:|
| write() | 21.66 | 22.48 | 22.27 | 14.10 | 11.51 |
| writeLSBFIRST() | 22.94 | 23.37 | 22.25 | 14.09 | 11.50 |
| writeMSBFIRST() | 20.30 | 21.86 | 22.26 | 14.08 | 11.50 |
| reference shiftOut() | 89.74 | 89.74 | 89.59 | 89.60 | 89.60 |
| write16() | na | na | 45.39 | 29.06 | 23.89 |
| write24() | na | na | 67.66 | 43.12 | 35.40 |
| write32() | na | na | 89.91 | 57.22 | 46.90 |
| println("Hello world") | na | 328.92 | 328.92 | 222.68 | 189.20 |
| println(1357) | na | 313.56 | 311.60 | 262.60 | 247.12 |
| println(3.14159265, 4) | na | 717.36 | 716.04 | 650.68 | 629.96 |
- Note: 0.3.3 has improved the measurement, not the code sec.
- Note: 0.3.3 numbers fixed when implementing 0.4.0. (error in test sketch).
- Note: 0.4.0 measured with loop unroll flag disabled.
- Note: 0.4.0L measured with loop unrolled flag enabled.
### Related
@ -73,33 +94,42 @@ Note: 0.3.3 has improved the measurement, not the code sec.
### Constructor
bitOrder = { LSBFIRST, MSBFIRST };
- **FastShiftOut(uint8_t dataOut, uint8_t clockPin, uint8_t bitOrder = LSBFIRST)** Constructor.
### Functions
- **size_t write(uint8_t data)** send a byte, also the workhorse of the **Print** interface.
- **size_t write16(uint16_t data)** send 2 bytes.
- **size_t write24(uint32_t data)** send 3 bytes.
- **size_t write32(uint32_t data)** send 4 bytes.
- **size_t write(uint8_t \*array, size_t size)** send size bytes.
- **size_t write16(uint16_t data)** send 2 bytes. Wrapper around 8 bit calls.
- **size_t write24(uint32_t data)** send 3 bytes. Wrapper around 8 bit calls.
- **size_t write32(uint32_t data)** send 4 bytes. Wrapper around 8 bit calls.
- **size_t write(uint8_t \*array, size_t size)** send array of size bytes.
- **uint8_t lastWritten()** returns last byte written.
### Meta
- **bool setBitOrder(uint8_t bitOrder)** set LSBFIRST or MSBFIRST. Returns false for other values.
- **uint8_t getBitOrder(void)** returns LSBFIRST or MSBFIRST.
- **size_t writeLSBFIRST(uint8_t data)** most optimized.
- **size_t writeMSBFIRST(uint8_t data)** most optimized.
- **size_t writeLSBFIRST(uint8_t data)** lowest level function, optimized for LSB.
- **size_t writeMSBFIRST(uint8_t data)** lowest level function, optimized for MSB.
As a FastShiftOut object implements the Print interface, one can also call
### BitOrder
- **FSO.print(any type)** or
- **FSO.println(any type)**
- **bool setBitOrder(uint8_t bitOrder)** set LSBFIRST or MSBFIRST.
Returns false for other values ==> no change.
- **uint8_t getBitOrder(void)** returns LSBFIRST or MSBFIRST as set in constructor
or latest set from **setBitOrder()**.
### Print interface
As the FastShiftOut library implements the Print interface, one can also call
- **size_t FSO.print(any type)** or
- **size_t FSO.println(any type)**
to send e.g. a float with 4 digits over the line, or some text string.
Note: **FSO.print()** returns the number of characters printed, including an optional \\r or \\n.
Note: **FSO.print()** and **FSO.println()** return the number of characters printed,
including an optional \\r and \\n.
### Byte order
@ -117,6 +147,8 @@ If the BIT-order is not the BYTE-order, the user has two options
- call **write()** multiple times and merge the bytes in the order needed.
- call **write32()** (a.o) and reorder the bytes in a separate function.
The library will not support such functionality.
## Notes
@ -138,15 +170,19 @@ pull up resistors, especially if wires are exceeding 10 cm (4").
#### Could
- investigate separate **BYTE**-order,
- only MSBFirst and LSBFirst
- **void setByteOrder()** + **uint8_t getByteOrder()**
- investigate ESP32 optimization readLSBFIRST readMSBFIRST
- performance ESP32
- example schema
- add invert flag?
- if ((value & m) == 0) ==> if ((value & m) == invertFlag...
- derived class?
#### Wont
- investigate separate **BYTE**-order,
- only MSBFirst and LSBFirst
- **void setByteOrder()** + **uint8_t getByteOrder()**
## Support

View File

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

View File

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