#include <avr/io.h>
#include <avr/interrupt.h>
#define DEFINE_AVR_PORT(ClassName, PortReg, PinReg, DdrReg) \
class ClassName { \
template <typename Context> \
friend struct AvrPins; \
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 TPort, int PortPin>
struct AvrPin {
typedef TPort Port;
static const int port_pin = PortPin;
};
template <typename Pin>
void pinSetInput ()
{
cli();
Pin::Port::setDdr(Pin::Port::getDdr() & ~(1 << Pin::port_pin));
sei();
}
template <typename Pin>
void pinSetOutput ()
{
cli();
Pin::Port::setDdr(Pin::Port::getDdr() | (1 << Pin::port_pin));
sei();
}
template <typename Pin>
bool pinGet ()
{
return (Pin::Port::getPin() & (1 << Pin::port_pin));
}
template <typename Pin>
void pinSet (, bool x)
{
cli();
if (x) {
Pin::Port::setPort(Pin::Port::getPort() | (1 << Pin::port_pin));
} else {
Pin::Port::setPort(Pin::Port::getPort() & ~(1 << Pin::port_pin));
}
sei();
}
template <typename Pin>
void pinFflip ()
{
cli();
Pin::Port::setPort(Pin::Port::getPort() ^ (1 << Pin::port_pin));
sei();
}
int main ()
{
typedef AvrPin<AvrPortA, 0> OutPin;
pinSetOutput<OutPin>();
pinSet<OutPin>(true);
typedef AvrPin<AvrPortA, 1> InPin;
pinSetInput<InPin>();
bool value = pinGet<InPin>(true);
}
I2luY2x1ZGUgPGF2ci9pby5oPgojaW5jbHVkZSA8YXZyL2ludGVycnVwdC5oPgoKI2RlZmluZSBERUZJTkVfQVZSX1BPUlQoQ2xhc3NOYW1lLCBQb3J0UmVnLCBQaW5SZWcsIERkclJlZykgXApjbGFzcyBDbGFzc05hbWUgeyBcCiAgICB0ZW1wbGF0ZSA8dHlwZW5hbWUgQ29udGV4dD4gXAogICAgZnJpZW5kIHN0cnVjdCBBdnJQaW5zOyBcCiAgICBzdGF0aWMgdm9pZCBzZXRQb3J0ICh1aW50OF90IHgpIHsgUG9ydFJlZyA9IHg7IH0gXAogICAgc3RhdGljIHVpbnQ4X3QgZ2V0UG9ydCAoKSB7IHJldHVybiBQb3J0UmVnOyB9IFwKICAgIHN0YXRpYyB2b2lkIHNldERkciAodWludDhfdCB4KSB7IERkclJlZyA9IHg7IH0gXAogICAgc3RhdGljIHVpbnQ4X3QgZ2V0RGRyICgpIHsgcmV0dXJuIERkclJlZzsgfSBcCiAgICBzdGF0aWMgdWludDhfdCBnZXRQaW4gKCkgeyByZXR1cm4gUGluUmVnOyB9IFwKfTsKCkRFRklORV9BVlJfUE9SVChBdnJQb3J0QSwgUE9SVEEsIFBJTkEsIEREUkEpCkRFRklORV9BVlJfUE9SVChBdnJQb3J0QiwgUE9SVEIsIFBJTkIsIEREUkIpCkRFRklORV9BVlJfUE9SVChBdnJQb3J0QywgUE9SVEMsIFBJTkMsIEREUkMpCkRFRklORV9BVlJfUE9SVChBdnJQb3J0RCwgUE9SVEQsIFBJTkQsIEREUkQpCgp0ZW1wbGF0ZSA8dHlwZW5hbWUgVFBvcnQsIGludCBQb3J0UGluPgpzdHJ1Y3QgQXZyUGluIHsKICAgIHR5cGVkZWYgVFBvcnQgUG9ydDsKICAgIHN0YXRpYyBjb25zdCBpbnQgcG9ydF9waW4gPSBQb3J0UGluOwp9OwoKdGVtcGxhdGUgPHR5cGVuYW1lIFBpbj4Kdm9pZCBwaW5TZXRJbnB1dCAoKQp7CiAgICBjbGkoKTsKICAgIFBpbjo6UG9ydDo6c2V0RGRyKFBpbjo6UG9ydDo6Z2V0RGRyKCkgJiB+KDEgPDwgUGluOjpwb3J0X3BpbikpOwogICAgc2VpKCk7Cn0KCnRlbXBsYXRlIDx0eXBlbmFtZSBQaW4+CnZvaWQgcGluU2V0T3V0cHV0ICgpCnsKICAgIGNsaSgpOwogICAgUGluOjpQb3J0OjpzZXREZHIoUGluOjpQb3J0OjpnZXREZHIoKSB8ICgxIDw8IFBpbjo6cG9ydF9waW4pKTsKICAgIHNlaSgpOwp9Cgp0ZW1wbGF0ZSA8dHlwZW5hbWUgUGluPgpib29sIHBpbkdldCAoKQp7CiAgICByZXR1cm4gKFBpbjo6UG9ydDo6Z2V0UGluKCkgJiAoMSA8PCBQaW46OnBvcnRfcGluKSk7Cn0KCnRlbXBsYXRlIDx0eXBlbmFtZSBQaW4+CnZvaWQgcGluU2V0ICgsIGJvb2wgeCkKewogICAgY2xpKCk7CiAgICBpZiAoeCkgewogICAgICAgIFBpbjo6UG9ydDo6c2V0UG9ydChQaW46OlBvcnQ6OmdldFBvcnQoKSB8ICgxIDw8IFBpbjo6cG9ydF9waW4pKTsKICAgIH0gZWxzZSB7CiAgICAgICAgUGluOjpQb3J0OjpzZXRQb3J0KFBpbjo6UG9ydDo6Z2V0UG9ydCgpICYgfigxIDw8IFBpbjo6cG9ydF9waW4pKTsKICAgIH0KICAgIHNlaSgpOwp9Cgp0ZW1wbGF0ZSA8dHlwZW5hbWUgUGluPgp2b2lkIHBpbkZmbGlwICgpCnsKICAgIGNsaSgpOwogICAgUGluOjpQb3J0OjpzZXRQb3J0KFBpbjo6UG9ydDo6Z2V0UG9ydCgpIF4gKDEgPDwgUGluOjpwb3J0X3BpbikpOwogICAgc2VpKCk7Cn0KCmludCBtYWluICgpCnsKICAgIHR5cGVkZWYgQXZyUGluPEF2clBvcnRBLCAwPiBPdXRQaW47CiAgICBwaW5TZXRPdXRwdXQ8T3V0UGluPigpOwogICAgcGluU2V0PE91dFBpbj4odHJ1ZSk7CiAgICAKICAgIHR5cGVkZWYgQXZyUGluPEF2clBvcnRBLCAxPiBJblBpbjsKICAgIHBpblNldElucHV0PEluUGluPigpOwogICAgYm9vbCB2YWx1ZSA9IHBpbkdldDxJblBpbj4odHJ1ZSk7Cn0K