#pragma once template class InputShiftReg { private: static constexpr int BYTES = (BITS % 8 == 0) ? (BITS/8) : (BITS/8+1); static constexpr bool invert = true; static constexpr bool invertInput = false; volatile unsigned char *_port; volatile unsigned char *_pin; const unsigned char _pinSerOut; const unsigned char _pinClk; const unsigned char _pinParallelLoad; unsigned char data[BYTES]; public: InputShiftReg(volatile unsigned char* const portReg, volatile unsigned char* const pinReg, const unsigned char clk, const unsigned char serOut, const unsigned char parallelLoad): _port(portReg), _pin(pinReg), _pinSerOut(serOut), _pinClk(clk), _pinParallelLoad(parallelLoad) { } bool getBit(unsigned char bit) { if(BITS <= bit) return false; bit = BITS - bit - 1; return data[bit/8] & (1<<(bit%8)); } unsigned char* read() { if constexpr(invert) { *_port &= ~(1<<_pinParallelLoad); *_port |= (1<<_pinParallelLoad); *_port &= ~(1<<_pinParallelLoad); for(unsigned char i = 0; i < BITS; ++i) { *_port &= ~(1 << _pinClk); bool value = *_pin & (1 << _pinSerOut); if constexpr(invertInput) value = !value; if(value) data[i/8] |= (1<<(i%8)); else data[i/8] &= ~(1<<(i%8)); *_port |= (1 << _pinClk); } } else { *_port |= (1<<_pinParallelLoad); *_port &= ~(1<<_pinParallelLoad); *_port |= (1<<_pinParallelLoad); for(unsigned char i = 0; i < BITS; ++i) { *_port |= (1 << _pinClk); bool value = *_pin & (1 << _pinSerOut); if constexpr(invertInput) value = !value; if(value) data[i/8] |= (1<<(i%8)); else data[i/8] &= ~(1<<(i%8)); *_port &= ~(1 << _pinClk); } } return data; } };