Files
MarklinController/shiftreg.h
2022-03-21 21:22:18 +01:00

82 lines
1.8 KiB
C++

#pragma once
#include <util/delay.h>
template <int BITS> class ShiftReg
{
private:
static constexpr int BYTES = (BITS % 8 == 0) ? (BITS/8) : (BITS/8+1);
static constexpr bool invert = true;
volatile unsigned char *_port;
const unsigned char _pinSer;
const unsigned char _pinSerClk;
const unsigned char _pinRClk;
unsigned char _lastData[BYTES] = {};
public:
ShiftReg(volatile unsigned char* const port, const unsigned char pinSer, const unsigned char pinSerClk,
const unsigned char pinRClk):
_port(port), _pinSer(pinSer), _pinSerClk(pinSerClk), _pinRClk(pinRClk)
{
clear();
}
void setBit(unsigned char bit, bool value)
{
if(BITS <= bit)
return;
bit = BITS - bit - 1;
if(value)
_lastData[bit/8] |= (1<<(bit%8));
else
_lastData[bit/8] &= ~(1<<(bit%8));
write(_lastData);
}
bool getBit(unsigned char bit)
{
if(BITS <= bit)
return false;
bit = BITS - bit - 1;
return _lastData[bit/8] & (1<<(bit%8));
}
void write(const unsigned char * const in)
{
for(unsigned char i = 0 ; i < BYTES; ++i)
_lastData[i] = in[i];
if constexpr(invert)
{
*_port |= ((1<<_pinSer) | (1<<_pinSerClk));
*_port |= (1<<_pinRClk);
for(unsigned char i = 0; i < BITS; ++i)
{
in[i/8] & (1<<(i%8)) ? (*_port &= ~(1 << _pinSer)) : (*_port |= (1 << _pinSer));
*_port |= (1 << _pinSerClk);
*_port &= ~(1 << _pinSerClk);
}
*_port &= ~(1<<_pinRClk);
}
else
{
*_port &= ~((1<<_pinSer) | (1<<_pinSerClk));
*_port &= ~(1<<_pinRClk);
for(unsigned char i = 0; i < BITS; ++i)
{
*_port &= ~(1 << _pinSerClk);
in[i/8] & (1<<(i%8)) ? (*_port |= (1 << _pinSer)) : (*_port &= ~(1 << _pinSer));
*_port |= (1 << _pinSerClk);
}
*_port |= 1<<_pinRClk;
}
}
void clear(bool value = false)
{
for(unsigned char i = 0 ; i < BYTES; ++i)
_lastData[i] = value ? 0xff : 0x00;
write(_lastData);
}
};