text: 
  /* Faster digitalWrite, digitalRead, pinMode for Arduino
     https://codebender.cc/library/digitalWriteFast#bonus%2FdigitalWrite%2Fdigital_write_macros.h
     - Basic scheme was developed by Paul Stoffregen with digitalWrite.
     - Extended to pinMode by John Raines
     - Extended to digitalRead by John Raines with considerable assistance
       by William Westfield
    Copyright (c) 2008-2010 PJRC.COM, LLC
  
    List of supported MCUs:
    - ATmega8/88/168/328/1280/1284P/2560 (Duemilanove, Uno, Nano, Mini, Pro, Mega)
    - ATmega16U4/32U4 (Leonardo, Micro)
    - ATtiny44/84/44A/84A Added by Wilfried Klaas
    - ATtiny45/85 (Trinket, Digispark)
    - SAMD21G18A (Arduino Zero) Added by Esben Soeltoft 03/09/2016
  
  Renamed since v7.0 to avoid naming collisions and so subtle bugs and anomalies
  if used along with third-party software using older/different versions of
  digitalWriteFast. All methods are defined in uppercase style to implicitly
  inform the reader of their definition as macros in the global scope.
   ______________________________________________________________________________
  
   Permission is hereby granted, free of charge, to any person obtaining a copy
   of this software and associated documentation files (the "Software"), to deal
   in the Software without restriction, including without limitation the rights
   to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
   copies of the Software, and to permit persons to whom the Software is
   furnished to do so, subject to the following conditions:
  
   The above copyright notice and this permission notice shall be included in
   all copies or substantial portions of the Software.
  
   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
   THE SOFTWARE. */
  
  #pragma once
  
  /* AVR ATmega1280/2560 - Arduino Mega ------------------------------------- */
  
  #if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
    #define PJON_IO_PIN_TO_PORT_REG(P) \
      ((P >= 22 && P <= 29) ? &PORTA : \
      (((P >= 10 && P <= 13) || (P >= 50 && P <= 53)) ? &PORTB : \
      ((P >= 30 && P <= 37) ? &PORTC : \
      (((P >= 18 && P <= 21) || P == 38) ? &PORTD : \
      (((P <= 3) || P == 5) ? &PORTE : \
      ((P >= 54 && P <= 61) ? &PORTF : \
      (((P >= 39 && P <= 41) || P == 4) ? &PORTG : \
      (((P >= 6 && P <= 9) || P == 16 || P == 17) ? &PORTH : \
      ((P == 14 || P == 15) ? &PORTJ : \
      ((P >= 62 && P <= 69) ? &PORTK : &PORTL))))))))))
  
    #define PJON_IO_PIN_TO_DDR_REG(P) \
      ((P >= 22 && P <= 29) ? &DDRA : \
      (((P >= 10 && P <= 13) || (P >= 50 && P <= 53)) ? &DDRB : \
      ((P >= 30 && P <= 37) ? &DDRC : \
      (((P >= 18 && P <= 21) || P == 38) ? &DDRD : \
      (((P <= 3) || P == 5) ? &DDRE : \
      ((P >= 54 && P <= 61) ? &DDRF : \
      (((P >= 39 && P <= 41) || P == 4) ? &DDRG : \
      (((P >= 6 && P <= 9) || P == 16 || P == 17) ? &DDRH : \
      ((P == 14 || P == 15) ? &DDRJ : \
      ((P >= 62 && P <= 69) ? &DDRK : &DDRL))))))))))
  
    #define PJON_IO_PIN_TO_PIN_REG(P) \
      ((P >= 22 && P <= 29) ? &PINA : \
      (((P >= 10 && P <= 13) || (P >= 50 && P <= 53)) ? &PINB : \
      ((P >= 30 && P <= 37) ? &PINC : \
      (((P >= 18 && P <= 21) || P == 38) ? &PIND : \
      (((P <= 3) || P == 5) ? &PINE : \
      ((P >= 54 && P <= 61) ? &PINF : \
      (((P >= 39 && P <= 41) || P == 4) ? &PING : \
      (((P >= 6 && P <= 9) || P == 16 || P == 17) ? &PINH : \
      ((P == 14 || P == 15) ? &PINJ : \
      ((P >= 62 && P <= 69) ? &PINK : &PINL))))))))))
  
    #ifndef PJON_IO_PIN_TO_BIT
      #define PJON_IO_PIN_TO_BIT(P) \
        ((P >=  7 && P <=  9) ? P - 3 : ((P >= 10 && P <= 13) ? P - 6 : \
        ((P >= 22 && P <= 29) ? P - 22 : ((P >= 30 && P <= 37) ? 37 - P : \
        ((P >= 39 && P <= 41) ? 41 - P : ((P >= 42 && P <= 49) ? 49 - P : \
        ((P >= 50 && P <= 53) ? 53 - P : ((P >= 54 && P <= 61) ? P - 54 : \
        ((P >= 62 && P <= 69) ? P - 62 : ((P == 0 || P == 15 || P == 17 || P == 21) \
        ? 0 : ((P == 1 || P == 14 || P == 16 || P == 20) ? 1 : ((P == 19) ? 2 : \
        ((P == 5 || P == 6 || P == 18) ? 3 : ((P == 2) ? 4 : \
        ((P == 3 || P == 4) ? 5 : 7)))))))))))))))
    #endif
  #endif
  
  /* AVR ATmega88/168/328/328P - Arduino Duemilanove, Uno, Nano, Mini, Pro -- */
  
  #if defined(__AVR_ATmega88__)  || defined(__AVR_ATmega168__) || \
      defined(__AVR_ATmega328__) || defined(__AVR_ATmega328P__)
    #define PJON_IO_PIN_TO_PORT_REG(P) \
      ((P <= 7) ? &PORTD : ((P >= 8 && P <= 13) ? &PORTB : &PORTC))
    #define PJON_IO_PIN_TO_DDR_REG(P) \
      ((P <= 7) ? &DDRD : ((P >= 8 && P <= 13) ? &DDRB : &DDRC))
    #define PJON_IO_PIN_TO_PIN_REG(P) \
      ((P <= 7) ? &PIND : ((P >= 8 && P <= 13) ? &PINB : &PINC))
    #ifndef PJON_IO_PIN_TO_BIT
      #define PJON_IO_PIN_TO_BIT(P) \
        ((P <= 7) ? P : ((P >= 8 && P <= 13) ? P - 8 : P - 14))
    #endif
  #endif
  
  /* AVR ATmega16U4/32U4 - Arduino Leonardo, Micro -------------------------- */
  
  #if defined(__AVR_ATmega16U4__) || defined(__AVR_ATmega32U4__)
    #define PJON_IO_PIN_TO_PORT_REG(P) \
      (((P <= 4) || P == 6 || P == 12 || P == 24 || P == 25 || P == 29) \
      ? &PORTD : ((P == 5 || P == 13) ? &PORTC : ((P >= 18 && P <= 23)) ? &PORTF : \
      ((P == 7) ? &PORTE : &PORTB)))
    #define PJON_IO_PIN_TO_DDR_REG(P) \
      (((P <= 4) || P == 6 || P == 12 || P == 24 || P == 25 || P == 29) \
      ? &DDRD : ((P == 5 || P == 13) ? &DDRC : ((P >= 18 && P <= 23)) ? \
      &DDRF : ((P == 7) ? &DDRE : &DDRB)))
    #define PJON_IO_PIN_TO_PIN_REG(P) \
      (((P <= 4) || P == 6 || P == 12 || P == 24 || P == 25 || P == 29) \
      ? &PIND : ((P == 5 || P == 13) ? &PINC : ((P >= 18 && P <= 23)) ? \
      &PINF : ((P == 7) ? &PINE : &PINB)))
    #ifndef PJON_IO_PIN_TO_BIT
      #define PJON_IO_PIN_TO_BIT(P) \
        ((P >= 8 && P <= 11) ? P - 4 : ((P >= 18 && P <= 21) ? 25 - P : \
        ((P == 0) ? 2 : ((P == 1) ? 3 : ((P == 2) ? 1 : ((P == 3) ? 0 : \
        ((P == 4) ? 4 : ((P == 6) ? 7 : ((P == 13) ? 7 : ((P == 14) ? 3 : \
        ((P == 15) ? 1 : ((P == 16) ? 2 : ((P == 17) ? 0 : ((P == 22) ? 1 : \
        ((P == 23) ? 0 : ((P == 24) ? 4 : ((P == 25) ? 7 : ((P == 26) ? 4 : \
        ((P == 27) ? 5 : 6 )))))))))))))))))))
    #endif
  #endif
  
  /* AVR ATtiny45/85 - Trinket, Digispark ----------------------------------- */
  
  #if defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
    #define PJON_IO_PIN_TO_PORT_REG(P) &PORTB
    #define PJON_IO_PIN_TO_DDR_REG(P) &DDRB
    #define PJON_IO_PIN_TO_PIN_REG(P) &PINB
    #ifndef PJON_IO_PIN_TO_BIT
      #define PJON_IO_PIN_TO_BIT(P) P
    #endif
  #endif
  
  /* AVR ATMEGA1284P -------------------------------------------------------- */
  
  #if defined(__AVR_ATmega1284P__)
    #define PJON_IO_PIN_TO_PORT_REG(P) \
      (P >= 24 ? &PORTA : (P <= 7 ? &PORTB : ((P >= 8 && P <=15) ? &PORTD : &PORTC)))
    #define PJON_IO_PIN_TO_DDR_REG(P) \
      (P >= 24 ? &DDRA : (P <= 7 ? &DDRB : ((P >= 8 && P <=15) ? &DDRD : &DDRC)))
    #define PJON_IO_PIN_TO_PIN_REG(P) \
      (P >= 24 ? &PINA : (P <= 7 ? &PINB : ((P >= 8 && P <=15) ? &PIND : &PINC)))
    #ifndef PJON_IO_PIN_TO_BIT
      #define PJON_IO_PIN_TO_BIT(P) \
        (P >= 24 ? P-24 : (P <= 7 ? P : ((P >= 8 && P <=15) ? P-8 : P-16 ) ) )
    #endif
  #endif
  
  /* AVR ATtiny44/84/44A/84A ------------------------------------------------ */
  #if defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__) || \
      defined(__AVR_ATtiny44A__) || defined(__AVR_ATtiny84A__)
    #define PJON_IO_PIN_TO_PORT_REG(P) \
      ((P <= 7) ? &PORTA : &PORTB )
    #define PJON_IO_PIN_TO_DDR_REG(P) \
      ((P <= 7) ? &DDRA : &DDRB )
    #define PJON_IO_PIN_TO_PIN_REG(P) \
      ((P <= 7) ? &PINA : &PINB)
    #ifndef PJON_IO_PIN_TO_BIT
      #define PJON_IO_PIN_TO_BIT(P) \
        ((P <= 7) ? P : ((P == 8) ? 2 : ( (P == 9) ? 3 : ( (P == 10) ? 1 : 0))))
    #endif
  #endif
  
  /* SAMD21G18A - Arduino Zero ---------------------------------------------- */
  
  #if defined(__SAMD21G18A__) || defined(ARDUINO_SAM_ZERO)  // Arduino Zero pins
    #define PJON_IO_PIN_TO_PORT_BIT(P) \
      ((P == 0) ? PORT_PA11  : ((P == 1) ? PORT_PA10  : ((P == 2) ? PORT_PA14  : \
      ((P == 3) ? PORT_PA09  : ((P == 4) ? PORT_PA08  : ((P == 5) ? PORT_PA15  : \
      ((P == 6) ? PORT_PA20  : ((P == 7) ? PORT_PA21  : ((P == 8) ? PORT_PA06  : \
      ((P == 9) ? PORT_PA07  : ((P == 10) ? PORT_PA18 : ((P == 11) ? PORT_PA16 : \
      ((P == 12) ? PORT_PA19 : ((P == 13) ? PORT_PA17 : ((P == A0) ? PORT_PA02 : \
      ((P == A1) ? PORT_PB08 : ((P == A2) ? PORT_PB09 : ((P == A3) ? PORT_PA04 : \
      ((P == A4) ? PORT_PA05 : ((P == A5) ? PORT_PB02 : ((P == SCK) ? PORT_PB11  : \
      ((P == MISO) ? PORT_PA12 : ((P == MOSI) ? PORT_PB10 : ((P == PIN_WIRE_SCL) ? \
      PORT_PA23 : ((P == PIN_WIRE_SDA) ? PORT_PA22 : PORT_PA13 \
      )))))))))))))))))))))))))
  
    #define PJON_IO_PIN_TO_PORT_REG(P) \
      ((P >= 15 && P <= 16) || (P == 19) || (P >= 23 && P <= 24) ? PORTB : PORTA )
    #define PJON_IO_PIN_TO_PORT_REGOUT(P) \
      ((P >= 15 && P <= 16) || (P == 19) || (P >= 23 && P <= 24) ? \
        REG_PORT_OUT1 : REG_PORT_OUT0)
    #define PJON_IO_PIN_TO_PORT_REGOUTSET(P) \
      ((P >= 15 && P <= 16) || (P == 19) || (P >= 23 && P <= 24) ? \
        REG_PORT_OUTSET1 : REG_PORT_OUTSET0)
    #define PJON_IO_PIN_TO_PORT_REGOUTCLR(P) \
      ((P >= 15 && P <= 16) || (P == 19) || (P >= 23 && P <= 24) ? \
        REG_PORT_OUTCLR1 : REG_PORT_OUTCLR0)
    #define PJON_IO_PIN_TO_PORT_REGPINCFG(P) \
      ((P >= 15 && P <= 16) || (P == 19) || (P >= 23 && P <= 24) ? \
        REG_PORT_PINCFG1 : REG_PORT_PINCFG0)
    #define PJON_IO_PIN_TO_PORT_REGDIRSET(P) \
      ((P >= 15 && P <= 16) || (P == 19) || (P >= 23 && P <= 24) ? \
        REG_PORT_DIRSET1 : REG_PORT_DIRSET0)
    #define PJON_IO_PIN_TO_PORT_REGDIRCLR(P) \
      ((P >= 15 && P <= 16) || (P == 19) || (P >= 23 && P <= 24) ? \
        REG_PORT_DIRCLR1 : REG_PORT_DIRCLR0)
    #define PJON_IO_PIN_TO_PORT_IN_REG(P) \
      ((P >= 15 && P <= 16) || (P == 19) || (P >= 23 && P <= 24) ? \
        REG_PORT_IN1 : REG_PORT_IN0)
  
    /* functions for read/write/pinmode fast for SAMD chips
     PWM pins 3, 4, 5, 6, 8, 9, 10, 11, 12, 13 provide 8-bit PWM output with the
     analogWrite() function analogWrite works on all analog pins and all digital
     PWM pins. You can supply it any value between 0 and 255. analog pins provide
     12bits resolution and provide a value between 0-4096.
  
     INPUT (0x0),
     OUTPUT (0x1),
     INPUT_PULLUP (0x2) Set pin to input mode with pull-up resistor enabled,
     INPUT_PULLDOWN (0x3) */
  
    #define PJON_IO_MODE(P, V) \
      do { if (__builtin_constant_p(P) && __builtin_constant_p(V)) { \
          if(V == 0x0) { \
            PJON_IO_PIN_TO_PORT_REGPINCFG(P) = (uint8_t)(PORT_PINCFG_INEN); \
            PJON_IO_PIN_TO_PORT_REGDIRCLR(P) = (uint32_t)PJON_IO_PIN_TO_PORT_BIT(P); \
          } else if(V == 0x2) { \
            PORT->Group[PJON_IO_PIN_TO_PORT_REG(11)].PINCFG[g_APinDescription[11].ulPin].reg = \
            (uint8_t)(PORT_PINCFG_INEN|PORT_PINCFG_PULLEN); \
            PJON_IO_PIN_TO_PORT_REGDIRCLR(P) = (uint32_t)PJON_IO_PIN_TO_PORT_BIT(P); \
            PJON_IO_PIN_TO_PORT_REGOUTSET(P) = (uint32_t)PJON_IO_PIN_TO_PORT_BIT(P); \
          } else if(V == 0x3) { \
            PORT->Group[g_APinDescription[11].ulPort].PINCFG[g_APinDescription[11].ulPin].reg = \
            (uint8_t)(PORT_PINCFG_INEN|PORT_PINCFG_PULLEN) ; \
            PJON_IO_PIN_TO_PORT_REGDIRCLR(P) = (uint32_t)PJON_IO_PIN_TO_PORT_BIT(P); \
            PJON_IO_PIN_TO_PORT_REGOUTCLR(P) = (uint32_t)PJON_IO_PIN_TO_PORT_BIT(P); \
          } else { \
            PJON_IO_PIN_TO_PORT_REGPINCFG(P) &= ~(uint8_t)(PORT_PINCFG_INEN); \
            PJON_IO_PIN_TO_PORT_REGDIRSET(P) = (uint32_t)PJON_IO_PIN_TO_PORT_BIT(P); \
          } \
        } else pinMode(P, V); \
      } while (0)
  
    #define PJON_IO_READ(P) ( (int) _PJON_IO_READ_(P) )
    #define _PJON_IO_READ_(P) \
      (__builtin_constant_p(P)) ? \
        (PJON_IO_PIN_TO_PORT_IN_REG(P) & PJON_IO_PIN_TO_PORT_BIT(P)) : digitalRead(P)
  
    #define PJON_IO_WRITE(P, V) \
      do { if (__builtin_constant_p(P) && __builtin_constant_p(V)) { \
          if(V) PJON_IO_PIN_TO_PORT_REGOUTSET(P) = PJON_IO_PIN_TO_PORT_BIT(P); \
          else PJON_IO_PIN_TO_PORT_REGOUTCLR(P) = PJON_IO_PIN_TO_PORT_BIT(P); \
        } else digitalWrite(P, V); \
      } while(0)
  
    #define PJON_IO_PULL_DOWN(P) \
      do { if(__builtin_constant_p(P)) { \
          PJON_IO_MODE(P, INPUT_PULLDOWN); \
        } else pinMode(P, INPUT_PULLDOWN); \
      } while(0)
  #endif
  
  /* AVR related ------------------------------------------------------------ */
  
  #ifdef __AVR__
    #define PJON_IO_ATOMIC_WRITE(A, P, V) \
      if ((int)(A) < 0x40) { bitWrite(*(A), PJON_IO_PIN_TO_BIT(P), V); }  \
      else { \
        uint8_t register saveSreg = SREG; \
        cli(); \
        bitWrite(*(A), PJON_IO_PIN_TO_BIT(P), V); \
        SREG = saveSreg; \
      }
  
    #ifndef PJON_IO_WRITE
      #define PJON_IO_WRITE(P, V) \
        do { \
          if(__builtin_constant_p(P) && __builtin_constant_p(V)) \
            PJON_IO_ATOMIC_WRITE((uint8_t*) PJON_IO_PIN_TO_PORT_REG(P), P, V) \
          else digitalWrite(P, V); \
        } while(0)
    #endif
  
    #ifndef PJON_IO_MODE
      #define PJON_IO_MODE(P, V) \
      do { \
        if(__builtin_constant_p(P) && __builtin_constant_p(V)) \
          PJON_IO_ATOMIC_WRITE((uint8_t*) PJON_IO_PIN_TO_DDR_REG(P), P, V) \
        else pinMode(P, V); \
      } while(0)
    #endif
  
    #ifndef PJON_IO_READ
      #define PJON_IO_READ(P) ((int) _PJON_IO_READ_(P))
      #define _PJON_IO_READ_(P) \
        (__builtin_constant_p(P)) ? ( \
        ((((*PJON_IO_PIN_TO_PIN_REG(P)) >> (PJON_IO_PIN_TO_BIT(P))) & 0x01))) : \
        digitalRead(P)
    #endif
  
    #define PJON_IO_PULL_DOWN(P) \
      do { if(__builtin_constant_p(P)) { \
          PJON_IO_WRITE(P, LOW); \
          PJON_IO_MODE(P, INPUT); \
        } else \
          digitalWrite(P, LOW); \
          pinMode(P, INPUT); \
      } while(0)
  #endif
  