#pragma once #include template 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) { *_port |= (1 << _pinSerClk); in[i/8] & (1<<(i%8)) ? (*_port &= ~(1 << _pinSer)) : (*_port |= (1 << _pinSer)); *_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); } };