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/).
## [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
- update readme.md
## [0.3.1] - 2023-02-20
- update readme.md
- update GitHub actions

View File

@ -39,6 +39,7 @@ void test1()
duration1 = micros() - start;
Serial.print(" write: ");
Serial.println(duration1 * 0.001);
delay(100);
start = micros();
for (int i = 0; i < 1000; i++)
@ -66,6 +67,7 @@ void test2()
duration1 = micros() - start;
Serial.print("writeLSBFIRST: ");
Serial.println(duration1 * 0.001);
delay(100);
start = micros();
for (int i = 0; i < 1000; i++)
@ -93,6 +95,7 @@ void test3()
duration1 = micros() - start;
Serial.print("writeMSBFIRST: ");
Serial.println(duration1 * 0.001);
delay(100);
start = micros();
for (int i = 0; i < 1000; i++)
@ -120,6 +123,7 @@ void test4()
duration1 = micros() - start;
Serial.print("Standard shiftOut1: ");
Serial.println(duration1 * 0.001);
delay(100);
start = micros();
for (int i = 0; i < 1000; i++)
@ -148,6 +152,7 @@ void test5()
duration1 = micros() - start;
Serial.print("println(\"Hello world\"): \t");
Serial.println(duration1 * 0.01);
delay(100);
start = micros();
for (int i = 0; i < 100; i++)
@ -157,7 +162,7 @@ void test5()
duration1 = micros() - start;
Serial.print("println(1357): \t\t\t");
Serial.println(duration1 * 0.01);
delay(100);
start = micros();
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
size_t write(const uint8_t \*buffer, size_t size)
// EXPERIMENTAL 0.3.3
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;
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 ????
{
i--;
n += writeLSBFIRST(buffer[i]);
writeLSBFIRST(array[i]);
}
}
else
{
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)
@ -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 --

View File

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

View File

@ -13,16 +13,10 @@
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
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.
It speeds up the shift using low level ports and masks. These are predetermined
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
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.
Exact how big the performance gain is can be seen with the example sketch.
### 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 |
|:-------------------------|--------:|---------:|
| write() | 21.66 | 22.48 |
| writeLSBFIRST() | 22.94 | 23.37 |
| writeMSBFIRST() | 20.30 | 21.86 |
| reference shiftOut() | 89.74 | 89.74 |
| println("Hello world") | | 328.92 |
| println(1357) | | 313.56 |
| println(3.14159265, 4) | | 717.36 |
| 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 |
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
@ -57,27 +71,53 @@ Time in microseconds, Arduino UNO
#include "FastShiftOut.h"
```
#### Functions
### 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.
### 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(const uint8_t data);** most optimized.
- **size_t writeMSBFIRST(const uint8_t data);** most optimized.
- **size_t writeLSBFIRST(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
- **FSO.print(any type);** or
- **FSO.println(any type);**
- **FSO.print(any type)** or
- **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.
### 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
- 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
- keep in sync with FastShiftIn()
#### Should
- extend unit tests
#### Could
- investigate separate **BYTE**-order,
- only MSBFirst and LSBFirst
- **void setByteOrder()** + **uint8_t getByteOrder()**
- investigate ESP32 optimization readLSBFIRST readMSBFIRST
- performance ESP32
- check optimized ESP32
- add **size_t write(const uint8_t \*buffer, size_t size)**
- example schema
#### Wont

View File

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

View File

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

View File

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