#include <avr/io.h>
#include <avr/interrupt.h>
#define DEFINE_AVR_PORT(ClassName, PortReg, PinReg, DdrReg) \
struct ClassName { \
static void setPort (uint8_t x) { PortReg = x; } \
static uint8_t getPort () { return PortReg; } \
static void setDdr (uint8_t x) { DdrReg = x; } \
static uint8_t getDdr () { return DdrReg; } \
static uint8_t getPin () { return PinReg; } \
};
DEFINE_AVR_PORT(AvrPortA, PORTA, PINA, DDRA)
DEFINE_AVR_PORT(AvrPortB, PORTB, PINB, DDRB)
DEFINE_AVR_PORT(AvrPortC, PORTC, PINC, DDRC)
DEFINE_AVR_PORT(AvrPortD, PORTD, PIND, DDRD)
template <typename Port, int PortPin>
struct PinInterface {
void setOutput () const
{
Port::setDdr(Port::getDdr() | (1 << PortPin));
}
void setInput () const
{
Port::setDdr(Port::getDdr() & ~(1 << PortPin));
}
void operator= (bool state) const
{
if (state) {
Port::setPort(Port::getPort() | (1 << PortPin));
} else {
Port::setPort(Port::getPort() & ~(1 << PortPin));
}
}
operator bool () const
{
return (Port::getPin() & (1 << PortPin));
}
};
static PinInterface<AvrPortA, 0> PinA0;
static PinInterface<AvrPortA, 1> PinA1;
// and so on...
int main ()
{
PinA0.setInput();
PinA0 == true; // seems like operator bool works all right, no need for operator==
}
I2luY2x1ZGUgPGF2ci9pby5oPgojaW5jbHVkZSA8YXZyL2ludGVycnVwdC5oPgoKI2RlZmluZSBERUZJTkVfQVZSX1BPUlQoQ2xhc3NOYW1lLCBQb3J0UmVnLCBQaW5SZWcsIERkclJlZykgXApzdHJ1Y3QgQ2xhc3NOYW1lIHsgXAogICAgc3RhdGljIHZvaWQgc2V0UG9ydCAodWludDhfdCB4KSB7IFBvcnRSZWcgPSB4OyB9IFwKICAgIHN0YXRpYyB1aW50OF90IGdldFBvcnQgKCkgeyByZXR1cm4gUG9ydFJlZzsgfSBcCiAgICBzdGF0aWMgdm9pZCBzZXREZHIgKHVpbnQ4X3QgeCkgeyBEZHJSZWcgPSB4OyB9IFwKICAgIHN0YXRpYyB1aW50OF90IGdldERkciAoKSB7IHJldHVybiBEZHJSZWc7IH0gXAogICAgc3RhdGljIHVpbnQ4X3QgZ2V0UGluICgpIHsgcmV0dXJuIFBpblJlZzsgfSBcCn07CgpERUZJTkVfQVZSX1BPUlQoQXZyUG9ydEEsIFBPUlRBLCBQSU5BLCBERFJBKQpERUZJTkVfQVZSX1BPUlQoQXZyUG9ydEIsIFBPUlRCLCBQSU5CLCBERFJCKQpERUZJTkVfQVZSX1BPUlQoQXZyUG9ydEMsIFBPUlRDLCBQSU5DLCBERFJDKQpERUZJTkVfQVZSX1BPUlQoQXZyUG9ydEQsIFBPUlRELCBQSU5ELCBERFJEKQoKdGVtcGxhdGUgPHR5cGVuYW1lIFBvcnQsIGludCBQb3J0UGluPgpzdHJ1Y3QgUGluSW50ZXJmYWNlIHsKICAgIHZvaWQgc2V0T3V0cHV0ICgpIGNvbnN0CiAgICB7CiAgICAgICAgUG9ydDo6c2V0RGRyKFBvcnQ6OmdldERkcigpIHwgKDEgPDwgUG9ydFBpbikpOwogICAgfQogICAgCiAgICB2b2lkIHNldElucHV0ICgpIGNvbnN0CiAgICB7CiAgICAgICAgUG9ydDo6c2V0RGRyKFBvcnQ6OmdldERkcigpICYgfigxIDw8IFBvcnRQaW4pKTsKICAgIH0KICAgIAogICAgdm9pZCBvcGVyYXRvcj0gKGJvb2wgc3RhdGUpIGNvbnN0CiAgICB7CiAgICAgICAgaWYgKHN0YXRlKSB7CiAgICAgICAgICAgIFBvcnQ6OnNldFBvcnQoUG9ydDo6Z2V0UG9ydCgpIHwgKDEgPDwgUG9ydFBpbikpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIFBvcnQ6OnNldFBvcnQoUG9ydDo6Z2V0UG9ydCgpICYgfigxIDw8IFBvcnRQaW4pKTsKICAgICAgICB9CiAgICB9CiAgICAKICAgIG9wZXJhdG9yIGJvb2wgKCkgY29uc3QKICAgIHsKICAgICAgICByZXR1cm4gKFBvcnQ6OmdldFBpbigpICYgKDEgPDwgUG9ydFBpbikpOwogICAgfQp9OwoKc3RhdGljIFBpbkludGVyZmFjZTxBdnJQb3J0QSwgMD4gUGluQTA7CnN0YXRpYyBQaW5JbnRlcmZhY2U8QXZyUG9ydEEsIDE+IFBpbkExOwovLyBhbmQgc28gb24uLi4KCmludCBtYWluICgpCnsKICAgIFBpbkEwLnNldElucHV0KCk7CiAgICBQaW5BMCA9PSB0cnVlOyAvLyBzZWVtcyBsaWtlIG9wZXJhdG9yIGJvb2wgd29ya3MgYWxsIHJpZ2h0LCBubyBuZWVkIGZvciBvcGVyYXRvcj09Cn0K