Hi All
Looking around, i did not found a faster replacement for the shiftOut procedure (
http://www.arduino.cc/en/Reference/ShiftOut) which is also compatible to the existing procedure. So i wrote a new procedure:
- Same interface as shiftOut
- 3-4x faster
- Restrictions: Does not turn of PWM and does not modify port directions
The restrictions mean, that you have to configure the clock and data pin correctly before using the replacement.
digitalWrite(clockPin, LOW);
digitalWrite(dataPin, LOW);
should be fine for this.
I did some performance tests with the SpaceTrash game form the DOGM128 Library (Arduino Uno, DOGS102 Display)
DOUBLE_MEM, shiftOut: 9 FPS (frames per second)
DOUBLE_MEM, shiftOutFast: 31 FPS
DOUBLE_MEM, Hardware SPI: 42 FPS
Here is the code:
#include "wiring_private.h"
#include "pins_arduino.h"
void shiftOutFast(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder, uint8_t val)
{
uint8_t cnt;
uint8_t bitData;
uint8_t bitClock;
volatile uint8_t *outData;
volatile uint8_t *outClock;
uint8_t dataLow, dataHigh, clockLow, clockHigh;
outData = portOutputRegister(digitalPinToPort(dataPin));
outClock = portOutputRegister(digitalPinToPort(clockPin));
bitData = digitalPinToBitMask(dataPin);
bitClock = digitalPinToBitMask(clockPin);
dataHigh = *outData;
dataHigh |= bitData;
bitData ^= 0x0ff;
dataLow = dataHigh;
dataLow &= bitData;
clockHigh = *outClock;
clockHigh |= bitClock;
bitClock ^= 0x0ff;
clockLow = clockHigh;
clockLow &= bitClock;
cnt = 8;
if (bitOrder == LSBFIRST)
{
do
{
if ( val & 1 )
*outData = dataHigh;
else
*outData = dataLow;
*outClock = clockHigh;
val >>= 1;
*outClock = clockLow;
cnt--;
} while( cnt != 0 );
}
else
{
do
{
if ( val & 128 )
*outData = dataHigh;
else
*outData = dataLow;
*outClock = clockHigh;
val <<= 1;
*outClock = clockLow;
cnt--;
} while( cnt != 0 );
}
}
Oliver