I've been meaning to do this for a long long time and finally got around to it tonight. As some of you know, I'm quite fond of low-level bit banging commands using macros like this:
This produces very small and fast code but it can be difficult to modify later. However, pinMode() and digitalWrite() are too bloated and slow for me to even contemplate using so they are not an option either for anything except the most quick and dirty test code. But I like their format since it is easy to see what is going on and I find digital pin numbers easier to work than PB5 for instance. Well feast your eyes on these little beauties! They are as easy to look at as the Arduino functions they replace but they only add 2 bytes of program size and they each execute in a single clock cycle since all this looking up is done at compile time rather than run time. The only efficiency I give up is you can't change more than one pin per clock cycle. Hope this helps others, I plan to fold this back into most of my code. If anyone spots a way to improve this please let me know.
// Macros to define the ports and bitmasks for the pins on the 328p succinctly
#if defined(__AVR_ATmega328P__)
#define DirRegFromPin(pin) pin<8 ? 0x0A : pin<14 ? 0x04 : 0x07 // Register which controls input or output
#define DataRegFromPin(pin) pin<8 ? 0x0B : pin<14 ? 0x05 : 0x08 // Register which controls high or low
#define BitmaskFromPin(pin) pin<8 ? 1<<pin : pin<14 ? 1<<(pin-8) : 1<<(pin-14)
#endif
// Bit-banging macros - each adds 2 bytes of sketch size and takes 1 clock cycle to execute
#define MakeOutput(pin) _SFR_IO8(DirRegFromPin(pin)) |= BitmaskFromPin(pin)
#define MakeInput(pin) _SFR_IO8(DirRegFromPin(pin)) &= ~(BitmaskFromPin(pin))
#define PullHigh(pin) _SFR_IO8(DataRegFromPin(pin)) |= BitmaskFromPin(pin)
#define PullLow(pin) _SFR_IO8(DataRegFromPin(pin)) &= ~(BitmaskFromPin(pin))
Just in case it isn't obvious, they are used like so:
MakeOutput(9);
PullHigh(9); // LED is on now
PullLow(9); // LED is off now
MakeInput(9);
or even better like so:
#define LED 9
MakeOutput(LED);
PullHigh(LED); // LED is on now
PullLow(LED); // LED is off now
MakeInput(LED);