0.3.3 FastShiftOut

This commit is contained in:
Rob Tillaart 2024-07-23 13:33:00 +02:00
parent bfc61cdb0e
commit da2e9fe077
8 changed files with 192 additions and 67 deletions

View File

@ -6,10 +6,16 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/)
and this project adheres to [Semantic Versioning](http://semver.org/). and this project adheres to [Semantic Versioning](http://semver.org/).
## [0.3.3] - 2024-07-23
- Fix #13, add wrapper functions
- write16/24/32, write(array, size)
- improved timing measurement in FastShiftOut_test.ino
- update readme.md
- minor edits
## [0.3.2] - 2023-10-31 ## [0.3.2] - 2023-10-31
- update readme.md - update readme.md
## [0.3.1] - 2023-02-20 ## [0.3.1] - 2023-02-20
- update readme.md - update readme.md
- update GitHub actions - update GitHub actions

View File

@ -39,6 +39,7 @@ void test1()
duration1 = micros() - start; duration1 = micros() - start;
Serial.print(" write: "); Serial.print(" write: ");
Serial.println(duration1 * 0.001); Serial.println(duration1 * 0.001);
delay(100);
start = micros(); start = micros();
for (int i = 0; i < 1000; i++) for (int i = 0; i < 1000; i++)
@ -66,6 +67,7 @@ void test2()
duration1 = micros() - start; duration1 = micros() - start;
Serial.print("writeLSBFIRST: "); Serial.print("writeLSBFIRST: ");
Serial.println(duration1 * 0.001); Serial.println(duration1 * 0.001);
delay(100);
start = micros(); start = micros();
for (int i = 0; i < 1000; i++) for (int i = 0; i < 1000; i++)
@ -93,6 +95,7 @@ void test3()
duration1 = micros() - start; duration1 = micros() - start;
Serial.print("writeMSBFIRST: "); Serial.print("writeMSBFIRST: ");
Serial.println(duration1 * 0.001); Serial.println(duration1 * 0.001);
delay(100);
start = micros(); start = micros();
for (int i = 0; i < 1000; i++) for (int i = 0; i < 1000; i++)
@ -120,6 +123,7 @@ void test4()
duration1 = micros() - start; duration1 = micros() - start;
Serial.print("Standard shiftOut1: "); Serial.print("Standard shiftOut1: ");
Serial.println(duration1 * 0.001); Serial.println(duration1 * 0.001);
delay(100);
start = micros(); start = micros();
for (int i = 0; i < 1000; i++) for (int i = 0; i < 1000; i++)
@ -148,6 +152,7 @@ void test5()
duration1 = micros() - start; duration1 = micros() - start;
Serial.print("println(\"Hello world\"): \t"); Serial.print("println(\"Hello world\"): \t");
Serial.println(duration1 * 0.01); Serial.println(duration1 * 0.01);
delay(100);
start = micros(); start = micros();
for (int i = 0; i < 100; i++) for (int i = 0; i < 100; i++)
@ -157,7 +162,7 @@ void test5()
duration1 = micros() - start; duration1 = micros() - start;
Serial.print("println(1357): \t\t\t"); Serial.print("println(1357): \t\t\t");
Serial.println(duration1 * 0.01); Serial.println(duration1 * 0.01);
delay(100);
start = micros(); start = micros();
for (int i = 0; i < 100; i++) for (int i = 0; i < 100; i++)
@ -176,4 +181,4 @@ void loop()
} }
// -- END OF FILE -- // -- END OF FILE --

View File

@ -47,8 +47,70 @@ size_t FastShiftOut::write(uint8_t data)
} }
/* experimental // EXPERIMENTAL 0.3.3
size_t write(const uint8_t \*buffer, size_t size) size_t FastShiftOut::write16(uint16_t data)
{
if (_bitOrder == LSBFIRST)
{
writeLSBFIRST(data & 0xFF);
writeLSBFIRST(data >> 8);
}
else
{
writeMSBFIRST(data >> 8);
writeMSBFIRST(data & 0xFF);
}
return 2;
}
// EXPERIMENTAL 0.3.3
size_t FastShiftOut::write24(uint32_t data)
{
if (_bitOrder == LSBFIRST)
{
writeLSBFIRST(data & 0xFF);
data >>= 8;
writeLSBFIRST(data & 0xFF);
data >>= 8;
writeLSBFIRST(data & 0xFF);
}
else
{
writeMSBFIRST((data >> 16) & 0xFF);
writeMSBFIRST((data >> 8) & 0xFF);
writeMSBFIRST(data & 0xFF);
}
return 3;
}
// EXPERIMENTAL 0.3.3
size_t FastShiftOut::write32(uint32_t data)
{
if (_bitOrder == LSBFIRST)
{
writeLSBFIRST(data & 0xFF);
data >>= 8;
writeLSBFIRST(data & 0xFF);
data >>= 8;
writeLSBFIRST(data & 0xFF);
data >>= 8;
writeLSBFIRST(data & 0xFF);
}
else
{
writeMSBFIRST((data >> 24) & 0xFF);
writeMSBFIRST((data >> 16) & 0xFF);
writeMSBFIRST((data >> 8) & 0xFF);
writeMSBFIRST(data & 0xFF);
}
return 4;
}
// EXPERIMENTAL 0.3.3
size_t FastShiftOut::write(uint8_t * array, size_t size)
{ {
size_t n = 0; size_t n = 0;
if (_bitOrder == LSBFIRST) if (_bitOrder == LSBFIRST)
@ -56,19 +118,42 @@ size_t write(const uint8_t \*buffer, size_t size)
for (size_t i = size; i > 0; ) // from end to begin ???? for (size_t i = size; i > 0; ) // from end to begin ????
{ {
i--; i--;
n += writeLSBFIRST(buffer[i]); writeLSBFIRST(array[i]);
} }
} }
else else
{ {
for (size_t i = 0; i < size; i++) // from begin to end.. for (size_t i = 0; i < size; i++) // from begin to end..
{ {
n += writeMSBFIRST(buffer[i]); writeMSBFIRST(array[i]);
} }
} }
return n; return size;
} }
*/
uint8_t FastShiftOut::lastWritten(void)
{
return _lastValue;
}
bool FastShiftOut::setBitOrder(const uint8_t bitOrder)
{
if ((bitOrder == LSBFIRST) || (bitOrder == MSBFIRST))
{
_bitOrder = bitOrder;
return true;
};
return false;
}
uint8_t FastShiftOut::getBitOrder(void)
{
return _bitOrder;
}
size_t FastShiftOut::writeLSBFIRST(uint8_t data) size_t FastShiftOut::writeLSBFIRST(uint8_t data)
@ -137,28 +222,5 @@ size_t FastShiftOut::writeMSBFIRST(uint8_t data)
} }
uint8_t FastShiftOut::lastWritten(void)
{
return _lastValue;
}
bool FastShiftOut::setBitOrder(const uint8_t bitOrder)
{
if ((bitOrder == LSBFIRST) || (bitOrder == MSBFIRST))
{
_bitOrder = bitOrder;
return true;
};
return false;
}
uint8_t FastShiftOut::getBitOrder(void)
{
return _bitOrder;
}
// -- END OF FILE -- // -- END OF FILE --

View File

@ -2,7 +2,7 @@
// //
// FILE: FastShiftOut.h // FILE: FastShiftOut.h
// AUTHOR: Rob Tillaart // AUTHOR: Rob Tillaart
// VERSION: 0.3.2 // VERSION: 0.3.3
// PURPOSE: shiftOut class that implements the Print interface // PURPOSE: shiftOut class that implements the Print interface
// DATE: 2013-08-22 // DATE: 2013-08-22
// URL: https://github.com/RobTillaart/FastShiftOut // URL: https://github.com/RobTillaart/FastShiftOut
@ -11,7 +11,7 @@
#include "Arduino.h" #include "Arduino.h"
#include "Print.h" #include "Print.h"
#define FASTSHIFTOUT_LIB_VERSION (F("0.3.2")) #define FASTSHIFTOUT_LIB_VERSION (F("0.3.3"))
class FastShiftOut : public Print class FastShiftOut : public Print
@ -21,14 +21,19 @@ public:
FastShiftOut(uint8_t dataOut, uint8_t clockPin, uint8_t bitOrder = LSBFIRST); FastShiftOut(uint8_t dataOut, uint8_t clockPin, uint8_t bitOrder = LSBFIRST);
size_t write(uint8_t data); size_t write(uint8_t data);
// experimental
// size_t write(const uint8_t \*buffer, size_t size);
uint8_t lastWritten(void); uint8_t lastWritten(void);
// EXPERIMENTAL (wrappers)
size_t write16(uint16_t data);
size_t write24(uint32_t data);
size_t write32(uint32_t data);
size_t write(uint8_t * array, size_t size);
// META
bool setBitOrder(uint8_t bitOrder); bool setBitOrder(uint8_t bitOrder);
uint8_t getBitOrder(void); uint8_t getBitOrder(void);
// overrule bitOrder (most optimized). // overrule bitOrder, most optimized.
size_t writeLSBFIRST(uint8_t data); size_t writeLSBFIRST(uint8_t data);
size_t writeMSBFIRST(uint8_t data); size_t writeMSBFIRST(uint8_t data);

View File

@ -13,16 +13,10 @@
Arduino library for **AVR** optimized shiftOut - e.g. 74HC595. Arduino library for **AVR** optimized shiftOut - e.g. 74HC595.
Related libraries
- https://github.com/RobTillaart/FastShiftIn
- https://github.com/RobTillaart/FastShiftInOut
- https://github.com/RobTillaart/ShiftInSlow
- https://github.com/RobTillaart/ShiftOutSlow
## Description ## Description
FastShiftOut is a class that has optimized code for AVR to shift out data faster FastShiftOut is a class that has optimized code (AVR only) to shift out data faster
than the normal **shiftOut()** function. than the normal **shiftOut()** function.
It speeds up the shift using low level ports and masks. These are predetermined It speeds up the shift using low level ports and masks. These are predetermined
in the constructor of the FastShiftOut object. in the constructor of the FastShiftOut object.
@ -30,25 +24,45 @@ in the constructor of the FastShiftOut object.
If not an **ARDUINO_ARCH_AVR** or **ARDUINO_ARCH_MEGAAVR** the class falls back If not an **ARDUINO_ARCH_AVR** or **ARDUINO_ARCH_MEGAAVR** the class falls back
to the default shiftOut() implementation. to the default shiftOut() implementation.
The library allows to set (and get) the bitOrder and apply this to multiple write()
calls. It also provide access to **writeLSBFIRST()** and **writeMSBFIRST()** which
are the low level workers and most optimized code (so far).
## Performance The library provides wrapper functions to write multi-byte variables.
These are write16(), write24(), write32() and write(array, size).
The latter is used to shift out any size object.
The performance of **write()** is substantially faster than the default Arduino
**shiftOut()**, but not as fast as HW SPI. ### Performance
Exact how big the performance gain is can be seen with the example sketch.
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. It does a comparison and shows how the class is to be used.
Time in microseconds, Arduino UNO Time in microseconds, Arduino UNO
| function | 0.2.4 | 0.3.1 | | function | 0.2.4 | 0.3.1 | 0.3.3 |
|:-------------------------|--------:|---------:| |:-------------------------|--------:|---------:|---------:|
| write() | 21.66 | 22.48 | | write() | 21.66 | 22.48 | 22.37 |
| writeLSBFIRST() | 22.94 | 23.37 | | writeLSBFIRST() | 22.94 | 23.37 | 23.26 |
| writeMSBFIRST() | 20.30 | 21.86 | | writeMSBFIRST() | 20.30 | 21.86 | 21.75 |
| reference shiftOut() | 89.74 | 89.74 | | reference shiftOut() | 89.74 | 89.74 | 89.60 |
| println("Hello world") | | 328.92 | | println("Hello world") | | 328.92 | 328.92 |
| println(1357) | | 313.56 | | println(1357) | | 313.56 | 311.68 |
| println(3.14159265, 4) | | 717.36 | | println(3.14159265, 4) | | 717.36 | 716.04 |
Note: 0.3.3 has improved the measurement, not the code sec.
### Related
- https://github.com/RobTillaart/FastShiftIn
- https://github.com/RobTillaart/FastShiftInOut
- https://github.com/RobTillaart/FastShiftOut
- https://github.com/RobTillaart/ShiftInSlow
- https://github.com/RobTillaart/ShiftOutSlow
## Interface ## Interface
@ -57,27 +71,53 @@ Time in microseconds, Arduino UNO
#include "FastShiftOut.h" #include "FastShiftOut.h"
``` ```
#### Functions ### Constructor
- **FastShiftOut(uint8_t dataOut, uint8_t clockPin, uint8_t bitOrder = LSBFIRST)** Constructor. - **FastShiftOut(uint8_t dataOut, uint8_t clockPin, uint8_t bitOrder = LSBFIRST)** Constructor.
- **size_t write(const uint8_t data)** send a byte, also the workhorse of the **Print** interface.
### 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.
- **uint8_t lastWritten()** returns last byte written. - **uint8_t lastWritten()** returns last byte written.
### Meta
- **bool setBitOrder(uint8_t bitOrder)** set LSBFIRST or MSBFIRST. Returns false for other values. - **bool setBitOrder(uint8_t bitOrder)** set LSBFIRST or MSBFIRST. Returns false for other values.
- **uint8_t getBitOrder(void)** returns LSBFIRST or MSBFIRST. - **uint8_t getBitOrder(void)** returns LSBFIRST or MSBFIRST.
- **size_t writeLSBFIRST(const uint8_t data);** most optimized. - **size_t writeLSBFIRST(uint8_t data)** most optimized.
- **size_t writeMSBFIRST(const uint8_t data);** most optimized. - **size_t writeMSBFIRST(uint8_t data)** most optimized.
As a FastShiftOut object implements the Print interface, one can also call As a FastShiftOut object implements the Print interface, one can also call
- **FSO.print(any type);** or - **FSO.print(any type)** or
- **FSO.println(any type);** - **FSO.println(any type)**
to send e.g. a float with 4 digits over the line, or some text string. 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()** returns the number of characters printed, including an optional \\r or \\n.
### Byte order
The functions **write16()**, **write24()** and **write32()** 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 **write16()** can have two, **write24()** can have six and **write32()** 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 **write()** multiple times and merge the bytes in the order needed.
- call **write32()** (a.o) and reorder the bytes in a separate function.
## Notes ## Notes
- The optimizations are AVR only for now, other platforms may follow. - The optimizations are AVR only for now, other platforms may follow.
@ -90,15 +130,19 @@ pull up resistors, especially if wires are exceeding 10 cm (4").
#### Must #### Must
- keep in sync with FastShiftIn()
#### Should #### Should
- extend unit tests - extend unit tests
#### Could #### Could
- investigate separate **BYTE**-order,
- only MSBFirst and LSBFirst
- **void setByteOrder()** + **uint8_t getByteOrder()**
- investigate ESP32 optimization readLSBFIRST readMSBFIRST
- performance ESP32 - performance ESP32
- check optimized ESP32
- add **size_t write(const uint8_t \*buffer, size_t size)**
- example schema - example schema
#### Wont #### Wont

View File

@ -6,6 +6,9 @@ FastShiftOut KEYWORD1
# Methods and Functions (KEYWORD2) # Methods and Functions (KEYWORD2)
write KEYWORD2 write KEYWORD2
write16 KEYWORD2
write24 KEYWORD2
write32 KEYWORD2
lastWritten KEYWORD2 lastWritten KEYWORD2

View File

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

View File

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