Skip to content

Instantly share code, notes, and snippets.

@branw
Created September 8, 2018 17:37
Show Gist options
  • Save branw/480df674a3e243a3f402a0e9dd0c2a23 to your computer and use it in GitHub Desktop.
Save branw/480df674a3e243a3f402a0e9dd0c2a23 to your computer and use it in GitHub Desktop.
digitalWrite() but without the overhead
namespace detail {
template<char port, int pin>
constexpr int get_pin() {
// In an ideal world, we could do something like this:
// return digitalPinToPort(pin) == port ? (1 << digitalPinToBitMask(pin)) : 0;
// But alas, C++11's constexpr support is very limited
return (port == 'A' && pin == 69) ? (1 << 0) :
(port == 'A' && pin == 68) ? (1 << 1) :
(port == 'A' && pin == 61) ? (1 << 2) :
(port == 'A' && pin == 60) ? (1 << 3) :
(port == 'A' && pin == 69) ? (1 << 4) :
(port == 'A' && pin == 58) ? (1 << 6) :
(port == 'A' && pin == 31) ? (1 << 7) :
(port == 'A' && pin == 0) ? (1 << 8) :
(port == 'A' && pin == 1) ? (1 << 9) :
(port == 'A' && pin == 19) ? (1 << 10) :
(port == 'A' && pin == 18) ? (1 << 11) :
(port == 'A' && pin == 17) ? (1 << 12) :
(port == 'A' && pin == 16) ? (1 << 13) :
(port == 'A' && pin == 23) ? (1 << 14) :
(port == 'A' && pin == 24) ? (1 << 15) :
(port == 'A' && pin == 54) ? (1 << 16) :
(port == 'A' && pin == 70) ? (1 << 17) :
(port == 'A' && pin == 71) ? (1 << 18) :
(port == 'A' && pin == 42) ? (1 << 19) :
(port == 'A' && pin == 43) ? (1 << 20) :
(port == 'A' && pin == 73) ? (1 << 21) :
(port == 'A' && pin == 57) ? (1 << 22) :
(port == 'A' && pin == 56) ? (1 << 23) :
(port == 'A' && pin == 55) ? (1 << 24) :
(port == 'A' && pin == 74) ? (1 << 25) :
(port == 'A' && pin == 75) ? (1 << 26) :
(port == 'A' && pin == 76) ? (1 << 27) :
(port == 'A' && pin == 10) ? (1 << 28) :
(port == 'A' && pin == 77) ? (1 << 28) :
(port == 'A' && pin == 4) ? (1 << 29) :
(port == 'B' && pin == 20) ? (1 << 12) :
(port == 'B' && pin == 21) ? (1 << 13) :
(port == 'B' && pin == 53) ? (1 << 14) :
(port == 'B' && pin == 66) ? (1 << 15) :
(port == 'B' && pin == 67) ? (1 << 16) :
(port == 'B' && pin == 62) ? (1 << 17) :
(port == 'B' && pin == 63) ? (1 << 18) :
(port == 'B' && pin == 64) ? (1 << 19) :
(port == 'B' && pin == 65) ? (1 << 20) :
(port == 'B' && pin == 52) ? (1 << 21) :
(port == 'B' && pin == 78) ? (1 << 23) :
(port == 'B' && pin == 2) ? (1 << 25) :
(port == 'B' && pin == 22) ? (1 << 26) :
(port == 'B' && pin == 13) ? (1 << 27) :
(port == 'C' && pin == 33) ? (1 << 1) :
(port == 'C' && pin == 34) ? (1 << 2) :
(port == 'C' && pin == 35) ? (1 << 3) :
(port == 'C' && pin == 36) ? (1 << 4) :
(port == 'C' && pin == 37) ? (1 << 5) :
(port == 'C' && pin == 38) ? (1 << 6) :
(port == 'C' && pin == 39) ? (1 << 7) :
(port == 'C' && pin == 40) ? (1 << 8) :
(port == 'C' && pin == 41) ? (1 << 9) :
(port == 'C' && pin == 51) ? (1 << 12) :
(port == 'C' && pin == 50) ? (1 << 13) :
(port == 'C' && pin == 49) ? (1 << 14) :
(port == 'C' && pin == 48) ? (1 << 15) :
(port == 'C' && pin == 47) ? (1 << 16) :
(port == 'C' && pin == 46) ? (1 << 17) :
(port == 'C' && pin == 45) ? (1 << 18) :
(port == 'C' && pin == 44) ? (1 << 19) :
(port == 'C' && pin == 9) ? (1 << 21) :
(port == 'C' && pin == 8) ? (1 << 22) :
(port == 'C' && pin == 7) ? (1 << 23) :
(port == 'C' && pin == 6) ? (1 << 24) :
(port == 'C' && pin == 5) ? (1 << 25) :
(port == 'C' && pin == 3) ? (1 << 28) :
(port == 'C' && pin == 72) ? (1 << 30) :
(port == 'D' && pin == 25) ? (1 << 0) :
(port == 'D' && pin == 26) ? (1 << 1) :
(port == 'D' && pin == 27) ? (1 << 2) :
(port == 'D' && pin == 28) ? (1 << 3) :
(port == 'D' && pin == 14) ? (1 << 4) :
(port == 'D' && pin == 15) ? (1 << 5) :
(port == 'D' && pin == 29) ? (1 << 6) :
(port == 'D' && pin == 11) ? (1 << 7) :
(port == 'D' && pin == 12) ? (1 << 8) :
(port == 'D' && pin == 30) ? (1 << 9) :
(port == 'D' && pin == 32) ? (1 << 10) : 0;
}
template<char port>
constexpr int get_pins() {
return 0;
}
template<char port, int pin, int... pins>
constexpr int get_pins() {
return get_pin<port, pin>() | get_pins<port, pins...>();
}
}
#define _SET_REG_FOR_PINS(reg, ...) do { \
int a = detail::get_pins<'A', __VA_ARGS__>(); if (a) REG_PIOA_##reg = a;\
int b = detail::get_pins<'B', __VA_ARGS__>(); if (b) REG_PIOB_##reg = b;\
int c = detail::get_pins<'C', __VA_ARGS__>(); if (c) REG_PIOC_##reg = c;\
int d = detail::get_pins<'D', __VA_ARGS__>(); if (d) REG_PIOD_##reg = d;\
} while (0)
#define SET_PINS(...) _SET_REG_FOR_PINS(SODR, __VA_ARGS__)
#define CLEAR_PINS(...) _SET_REG_FOR_PINS(CODR, __VA_ARGS__)
#define SET_ONLY_PINS(...) do { \
REG_PIOA_ODSR = detail::get_pins<'A', __VA_ARGS__>();\
REG_PIOB_ODSR = detail::get_pins<'B', __VA_ARGS__>();\
REG_PIOC_ODSR = detail::get_pins<'C', __VA_ARGS__>();\
REG_PIOD_ODSR = detail::get_pins<'D', __VA_ARGS__>();\
} while (0)
#define TOGGLE_PINS(...) do { \
int a = detail::get_pins<'A', __VA_ARGS__>(); if (a) REG_PIOA_ODSR ^= a;\
int b = detail::get_pins<'B', __VA_ARGS__>(); if (b) REG_PIOB_ODSR ^= b;\
int c = detail::get_pins<'C', __VA_ARGS__>(); if (c) REG_PIOC_ODSR ^= c;\
int d = detail::get_pins<'D', __VA_ARGS__>(); if (d) REG_PIOD_ODSR ^= d;\
} while (0)
const int PIN_A = 31;
const int PIN_B = 33;
const int PIN_C = 35;
void setup() {
// Enable output on all I/O lines
REG_PIOA_OER = REG_PIOB_OER = REG_PIOC_OER = REG_PIOD_OER = 0xFFFFFFFF;
// Enable writing directly to PIO lines
REG_PIOA_OWER = REG_PIOB_OWER = REG_PIOC_OWER = REG_PIOD_OWER = 0xFFFFFFFF;
}
void loop() {
SET_PINS(PIN_A, PIN_B, PIN_C);
delay(50);
CLEAR_PINS(PIN_A, PIN_B, PIN_C);
delay(50);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment