-sentence=Small and easy to use Arduino library for using push buttons at INT0/pin2 and / or INT1/pin3 using interrupts.
Functions for long and double press detection are included.
Just connect buttons between ground and pin 2 or 3 of your Arduino - that's it
No call of begin() or polling function like update() required. No blocking debouncing delay.
-paragraph=
Define an EasyButtonIn in you main program and use ButtonStateIsActive or ButtonToggleState to determine your action.
Or use a callback function which will be called once on every button press or release.
Usage:#define USE_BUTTON_0
#include "EasyButtonAtInt01.cpp.h"
EasyButton Button0AtPin2;
void setup() {}
void loop() {
...
digitalWrite(LED_BUILTIN, Button0AtPin2.ButtonToggleState);
...
}
New: 2 sets of constructors.
+maintainer=Armin Joachimsmeyer
+sentence=Small and easy to use Arduino library for using push buttons at INT0/pin2 and / or any PinChangeInterrupt pin.
Functions for long and double press detection are included.
Just connect buttons between ground and any pin of your Arduino - that's it
No call of begin() or polling function like update() required. No blocking debouncing delay.
+paragraph=
Define an EasyButtonIn in you main program and use ButtonStateIsActive or ButtonToggleState to determine your action.
Or use a callback function which will be called once on every button press or release.
Usage:#define USE_BUTTON_0
#include "EasyButtonAtInt01.cpp.h"
EasyButton Button0AtPin2;
void setup() {}
void loop() {
...
digitalWrite(LED_BUILTIN, Button0AtPin2.ButtonToggleState);
...
}
New: Second button now possible on each ATmega328 pin.
category=Signal Input/Output
url=https://github.com/ArminJo/EasyButtonAtInt01
architectures=avr
diff --git a/src/EasyButtonAtInt01.cpp.h b/src/EasyButtonAtInt01.cpp.h
index 9c9ecf9..c6b4619 100644
--- a/src/EasyButtonAtInt01.cpp.h
+++ b/src/EasyButtonAtInt01.cpp.h
@@ -34,6 +34,7 @@
* along with this program. If not, see .
*/
+#if defined(__AVR__)
#include
#include "EasyButtonAtInt01.h"
@@ -52,17 +53,19 @@
// For external measurement of code timing
//#define MEASURE_EASY_BUTTON_INTERRUPT_TIMING
-#if defined(MEASURE_EASY_BUTTON_INTERRUPT_TIMING) || defined (LED_FEEDBACK_TEST)
+#if defined(MEASURE_EASY_BUTTON_INTERRUPT_TIMING) || defined(LED_FEEDBACK_TEST)
#include "digitalWriteFast.h"
#endif
#if defined(USE_BUTTON_0)
-EasyButton * EasyButton::sPointerToButton0ForISR;
+EasyButton *EasyButton::sPointerToButton0ForISR;
#endif
#if defined(USE_BUTTON_1)
-EasyButton * EasyButton::sPointerToButton1ForISR;
+EasyButton *EasyButton::sPointerToButton1ForISR;
#endif
+// @formatter:off // the eclipse formatter has problems with // comments in undefined code blocks
+
/*
* These constructors are deterministic if only one button is enabled
* If two buttons are enabled they can be taken for the 1. button at INT0
@@ -267,19 +270,25 @@ void EasyButton::init(bool aIsButtonAtINT0) {
GIMSK |= 1 << PCIE; // PCINT enable, we have only one
PCMSK = digitalPinToBitMask(INT1_PIN);
# endif
-# elif (INT1_PIN != 3)
- /*
- * ATmega328 (Uno, Nano ) etc. Enable pin change interrupt for port PD0 to PD7 (Arduino pin 0 to 7)
- */
- PCICR |= 1 << PCIE2;
- PCMSK2 = digitalPinToBitMask(INT1_PIN);
+# elif INT1_PIN == 4 || INT1_PIN == 5 || INT1_PIN == 6 || INT1_PIN == 7
+ //ATmega328 (Uno, Nano ) etc. Enable pin change interrupt for port PD0 to PD7 (Arduino pin 0 to 7)
+ PCICR |= 1 << PCIE2;
+ PCMSK2 = digitalPinToBitMask(INT1_PIN);
+# elif INT1_PIN == 8 || INT1_PIN == 9 || INT1_PIN == 10 || INT1_PIN == 11 || INT1_PIN == 12 || INT1_PIN == 13
+ //ATmega328 (Uno, Nano ) etc. Enable pin change interrupt 0 to 5 for port PB0 to PB5 (Arduino pin 8 to 13)
+ PCICR |= _BV(PCIE0);
+ PCMSK0 = digitalPinToBitMask(INT1_PIN);
+# elif INT1_PIN == A0 || INT1_PIN == A1 || INT1_PIN == A2 || INT1_PIN == A3 || INT1_PIN == A4 || INT1_PIN == A5
+ //ATmega328 (Uno, Nano ) etc. Enable pin change interrupt 8 to 13 for port PC0 to PC5 (Arduino pin A0 to A5)
+ PCICR |= _BV(PCIE1);
+ PCMSK1 = digitalPinToBitMask(INT1_PIN);
# else
# if defined(USE_ATTACH_INTERRUPT)
- attachInterrupt(digitalPinToInterrupt(INT1_PIN), &handleINT1Interrupt, CHANGE);
+ attachInterrupt(digitalPinToInterrupt(INT1_PIN), &handleINT1Interrupt, CHANGE);
# else
- EICRA |= (1 << ISC10); // interrupt on any logical change
- EIFR |= 1 << INTF1; // clear interrupt bit
- EIMSK |= 1 << INT1; // enable interrupt on next change
+ EICRA |= (1 << ISC10); // interrupt on any logical change
+ EIFR |= 1 << INTF1; // clear interrupt bit
+ EIMSK |= 1 << INT1; // enable interrupt on next change
# endif //USE_ATTACH_INTERRUPT
# endif // ! defined(ISC10)
}
@@ -294,35 +303,37 @@ void EasyButton::init(bool aIsButtonAtINT0) {
bool EasyButton::readButtonState() {
#if defined(USE_BUTTON_0) && not defined(USE_BUTTON_1)
# if defined(BUTTON_IS_ACTIVE_HIGH)
- return (INT0_IN_PORT & _BV(INT0_BIT)); // = digitalReadFast(2);
+ return (INT0_IN_PORT & _BV(INT0_BIT)); // = digitalReadFast(2);
# else
- return !(INT0_IN_PORT & _BV(INT0_BIT)); // = digitalReadFast(2);
+ return !(INT0_IN_PORT & _BV(INT0_BIT)); // = digitalReadFast(2);
# endif
#elif defined(USE_BUTTON_1) && not defined(USE_BUTTON_0)
# if defined(BUTTON_IS_ACTIVE_HIGH)
- return (INT1_IN_PORT & _BV(INT1_BIT)); // = digitalReadFast(3);
+ return (INT1_IN_PORT & _BV(INT1_BIT)); // = digitalReadFast(3);
# else
- return !(INT1_IN_PORT & _BV(INT1_BIT)); // = digitalReadFast(3);
+ return !(INT1_IN_PORT & _BV(INT1_BIT)); // = digitalReadFast(3);
# endif
#elif defined(USE_BUTTON_0) && defined(USE_BUTTON_1)
# if defined(BUTTON_IS_ACTIVE_HIGH)
- if (isButtonAtINT0) {
- return (INT0_IN_PORT & _BV(INT0_BIT)); // = digitalReadFast(2);
- } else {
- return (INT1_IN_PORT & _BV(INT1_BIT)); // = digitalReadFast(3);
- }
+ if (isButtonAtINT0) {
+ return (INT0_IN_PORT & _BV(INT0_BIT)); // = digitalReadFast(2);
+ } else {
+ return (INT1_IN_PORT & _BV(INT1_BIT)); // = digitalReadFast(3);
+ }
# else
- if (isButtonAtINT0) {
- return !(INT0_IN_PORT & _BV(INT0_BIT)); // = digitalReadFast(2);
- } else {
- return !(INT1_IN_PORT & _BV(INT1_BIT)); // = digitalReadFast(3);
- }
+ if (isButtonAtINT0) {
+ return !(INT0_IN_PORT & _BV(INT0_BIT)); // = digitalReadFast(2);
+ } else {
+ return !(INT1_IN_PORT & _BV(INT1_BIT)); // = digitalReadFast(3);
+ }
# endif
#endif
}
+// @formatter:on // the eclipse formatter has problems with // comments in undefined code blocks
+
/*
* Returns stored state if in debouncing period otherwise current state of button
*/
@@ -654,9 +665,15 @@ ISR(INT0_vect) {
# if (! defined(ISC10)) || ((defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__)) && INT1_PIN != 3)
// on ATtinyX5 we do not have a INT1_vect but we can use the PCINT0_vect
ISR(PCINT0_vect)
-# elif (INT1_PIN != 3)
+# elif INT1_PIN == 4 || INT1_PIN == 5 || INT1_PIN == 6 || INT1_PIN == 7
// PCINT for ATmega328 Arduino pins 0 to 7
ISR(PCINT2_vect)
+# elif INT1_PIN == 8 || INT1_PIN == 9 || INT1_PIN == 10 || INT1_PIN == 11 || INT1_PIN == 12 || INT1_PIN == 13
+// PCINT for ATmega328 Arduino pins 8 (PB0) to 13 (PB5) - (PCINT 0 to 5)
+ISR(PCINT0_vect)
+# elif INT1_PIN == A0 || INT1_PIN == A1 || INT1_PIN == A2 || INT1_PIN == A3 || INT1_PIN == A4 || INT1_PIN == A5
+// PCINT for ATmega328 Arduino pins A1 (PC0) to A5 (PC5) - (PCINT 8 to 13)
+ISR(PCINT1_vect)
# else
ISR(INT1_vect)
# endif
@@ -671,3 +688,5 @@ ISR(INT1_vect)
}
# endif
#endif // not defined(USE_ATTACH_INTERRUPT)
+
+#endif // defined(__AVR__)
diff --git a/src/EasyButtonAtInt01.h b/src/EasyButtonAtInt01.h
index cef0c8d..4ce6041 100644
--- a/src/EasyButtonAtInt01.h
+++ b/src/EasyButtonAtInt01.h
@@ -34,33 +34,12 @@
#ifndef EASY_BUTTON_AT_INT01_H_
#define EASY_BUTTON_AT_INT01_H_
-#define VERSION_EASY_BUTTON "3.1.0"
+#define VERSION_EASY_BUTTON "3.2.0"
#define VERSION_EASY_BUTTON_MAJOR 3
-#define VERSION_EASY_BUTTON_MINOR 1
-
-/*
- * Version 3.1.0 - 6/2020
- * - 2 sets of constructors, one for only one button used and one for the second button if two buttons used.
- * - Map pin numbers for Digispark pro boards, for use with with digispark library.
- *
- * Version 3.0.0 - 5/2020
- * - Added button release handler and adapted examples.
- * - Revoke change for "only one true result per press for checkForLongPressBlocking()". It is superseded by button release handler.
- * - Support buttons which are active high by defining BUTTON_IS_ACTIVE_HIGH.
- * - Improved detection of maximum bouncing period used in DebounceTest.
- *
- * Version 2.1.0 - 5/2020
- * - Avoid 1 ms delay for checkForLongPressBlocking() if button is not pressed.
- * - Only one true result per press for checkForLongPressBlocking().
- *
- * Version 2.0.0 - 1/2020
- * - Ported to ATtinyX5 and ATiny167.
- * - Support also PinChangeInterrupt for button 1 on Pin PA0 to PA7 for ATtiniy87/167.
- * - Long press detection support.
- * - Double press detection support.
- * - Renamed to EasyButtonAtInt01.cpp.h
- */
+#define VERSION_EASY_BUTTON_MINOR 2
+// The change log is at the bottom of the file
+#if defined(__AVR__)
#include
/*
@@ -82,7 +61,7 @@
//#define BUTTON_IS_ACTIVE_HIGH
/*
* Define USE_ATTACH_INTERRUPT to force use of the arduino function attachInterrupt().
- * Needed if you get the error " multiple definition of `__vector_1'" (or `__vector_2'), because another library uses the attachInterrupt() function.
+ * Required if you get the error " multiple definition of `__vector_1'" (or `__vector_2'), because another library uses the attachInterrupt() function.
* For one button it needs additional 160 bytes FLASH, for 2 buttons it needs additional 88 bytes.
*/
//#define USE_ATTACH_INTERRUPT
@@ -105,7 +84,7 @@
#endif
/*
- * Comment this out to save 2 bytes RAM and 64 bytes FLASH
+ * Activate this to save 2 bytes RAM and 64 bytes FLASH
*/
//#define NO_BUTTON_RELEASE_CALLBACK
//
@@ -123,9 +102,9 @@
* Activate LED_BUILTIN as long as button is pressed
*/
//#define LED_FEEDBACK_TEST
-#if defined (LED_FEEDBACK_TEST)
+#if defined(LED_FEEDBACK_TEST)
# if ! defined(BUTTON_TEST_FEEDBACK_LED_PIN)
-# if defined (LED_BUILTIN)
+# if defined(LED_BUILTIN)
# define BUTTON_TEST_FEEDBACK_LED_PIN LED_BUILTIN // if not specified, use built in led - pin 13 on Uno board
# else
# error "LED_FEEDBACK_TEST defined but no BUTTON_TEST_FEEDBACK_LED_PIN or LED_BUILTIN defined"
@@ -145,7 +124,7 @@
//#define TRACE
#ifdef TRACE
-#warning "If using TRACE, the timing of the interrupt service routine changes, e.g. you will see more spikes, than expected!"
+#warning If using TRACE, the timing of the interrupt service routine changes, e.g. you will see more spikes, than expected!
#endif
/*
@@ -170,7 +149,7 @@
# if ! defined(INT1_PIN)
#define INT1_PIN 3
# elif (INT1_PIN != 2) && (INT1_PIN > 5)
-#error "INT1_PIN (for PCINT0 interrupt) can only be 0,1,3,4,5"
+#error INT1_PIN (for PCINT0 interrupt) can only be 0,1,3,4,5
# endif
#define INT1_DDR_PORT (DDRB)
#define INT1_IN_PORT (PINB)
@@ -217,11 +196,11 @@
#undef INT1_PIN
#define INT1_PIN 6 // PA6
# else
-#error "INT1_PIN (for PCINT0 interrupt) can only be 5 to 12"
+#error INT1_PIN (for PCINT0 interrupt) can only be 5 to 12
# endif
# else // defined(ARDUINO_AVR_DIGISPARKPRO)
# if (INT1_PIN > 7)
-#error "INT1_PIN (for PCINT0 interrupt) can only be 0 to 7"
+#error INT1_PIN (for PCINT0 interrupt) can only be 0 to 7
# endif
# endif // defined(ARDUINO_AVR_DIGISPARKPRO)
#define INT1_DDR_PORT (DDRA)
@@ -240,7 +219,7 @@
# if ! defined(INT1_PIN)
#define INT1_PIN 3
# elif (INT1_PIN > 7)
-#error "INT1_PIN (for PCINT2 interrupt) can only be Arduino pins 0 to 7 (PD0 to PD7)"
+#error INT1_PIN (for PCINT2 interrupt) can only be Arduino pins 0 to 7 (PD0 to PD7)
# endif
#define INT1_DDR_PORT (DDRD)
#define INT1_IN_PORT (PIND)
@@ -254,7 +233,7 @@
#if defined(USE_BUTTON_1) && ((! defined(ISC10)) || ((defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__)) && INT1_PIN != 3)) \
&& ! defined(INTENTIONALLY_USE_PCI0_FOR_BUTTON1) && !(defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__))
-#warning "Using PCINT0 interrupt for button 1"
+#warning Using PCINT0 interrupt for button 1
#endif
#if defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
@@ -356,10 +335,10 @@ class EasyButton {
#endif
#if defined(USE_BUTTON_0)
- static EasyButton * sPointerToButton0ForISR;
+ static EasyButton *sPointerToButton0ForISR;
#endif
#if defined(USE_BUTTON_1)
- static EasyButton * sPointerToButton1ForISR;
+ static EasyButton *sPointerToButton1ForISR;
#endif
};
// end of class definition
@@ -378,6 +357,31 @@ void __attribute__ ((weak)) handleINT0Interrupt();
void __attribute__ ((weak)) handleINT1Interrupt();
#endif
+#endif // defined(__AVR__)
+
+/*
+ * Version 3.1.0 - 6/2020
+ * - 2 sets of constructors, one for only one button used and one for the second button if two buttons used.
+ * - Map pin numbers for Digispark pro boards, for use with with digispark library.
+ *
+ * Version 3.0.0 - 5/2020
+ * - Added button release handler and adapted examples.
+ * - Revoke change for "only one true result per press for checkForLongPressBlocking()". It is superseded by button release handler.
+ * - Support buttons which are active high by defining BUTTON_IS_ACTIVE_HIGH.
+ * - Improved detection of maximum bouncing period used in DebounceTest.
+ *
+ * Version 2.1.0 - 5/2020
+ * - Avoid 1 ms delay for checkForLongPressBlocking() if button is not pressed.
+ * - Only one true result per press for checkForLongPressBlocking().
+ *
+ * Version 2.0.0 - 1/2020
+ * - Ported to ATtinyX5 and ATiny167.
+ * - Support also PinChangeInterrupt for button 1 on Pin PA0 to PA7 for ATtiniy87/167.
+ * - Long press detection support.
+ * - Double press detection support.
+ * - Renamed to EasyButtonAtInt01.cpp.h
+ */
+
#endif /* EASY_BUTTON_AT_INT01_H_ */
#pragma once
diff --git a/src/digitalWriteFast.h b/src/digitalWriteFast.h
index 8e83af1..3bbfc97 100644
--- a/src/digitalWriteFast.h
+++ b/src/digitalWriteFast.h
@@ -39,7 +39,7 @@
#endif
// workarounds for ARM microcontrollers
-#if (!defined(__AVR__) || \
+#if (!defined(__AVR__) && !defined(ESP8266) || \
defined(ARDUINO_ARCH_SAM) || \
defined(ARDUINO_ARCH_SAMD))
@@ -209,9 +209,22 @@
(((P) == 3 || (P) == 4) ? 5 : 7)))))))))))))))
-// --- Arduino 644 ---
-#elif (defined(__AVR_ATmega644__) || \
- defined(__AVR_ATmega644P__))
+// --- Arduino MightyCore standard pinout ---
+#elif defined(__AVR_ATmega1284P__) || \
+ defined(__AVR_ATmega1284P__) || \
+ defined(__AVR_ATmega644P__) || \
+ defined(__AVR_ATmega644__) || \
+ defined(__AVR_ATmega324PB__) || \
+ defined(__AVR_ATmega324PA__) || \
+ defined(__AVR_ATmega324P__) || \
+ defined(__AVR_ATmega324A__) || \
+ defined(__AVR_ATmega164P__) || \
+ defined(__AVR_ATmega164A__) || \
+ defined(__AVR_ATmega32__) || \
+ defined(__AVR_ATmega16__) || \
+ defined(__AVR_ATmega8535__) && \
+ !defined(BOBUINO_PINOUT) && \
+ !defined(SANGUINO_PINOUT)
#define UART_RX_PIN (8) //PD0
#define UART_TX_PIN (9) //PD1
@@ -224,6 +237,16 @@
#define SPI_HW_MISO_PIN (6) //PB6
#define SPI_HW_SCK_PIN (7) //PB7
+#if defined(__AVR_ATmega324PB__)
+#define __digitalPinToPortReg(P) \
+(((P) >= 0 && (P) <= 7) ? &PORTB : (((P) >= 8 && (P) <= 15) ? &PORTD : (((P) >= 16 && (P) <= 23) ? &PORTC : (((P) >= 24 && (P) <= 31) ? &PORTA : &PORTE))))
+#define __digitalPinToDDRReg(P) \
+(((P) >= 0 && (P) <= 7) ? &DDRB : (((P) >= 8 && (P) <= 15) ? &DDRD : (((P) >= 8 && (P) <= 15) ? &DDRC : (((P) >= 24 && (P) <= 31) ? &DDRA : &DDRE))))
+#define __digitalPinToPINReg(P) \
+(((P) >= 0 && (P) <= 7) ? &PINB : (((P) >= 8 && (P) <= 15) ? &PIND : (((P) >= 8 && (P) <= 15) ? &PINC : (((P) >= 24 && (P) <= 31) ? &PINA : &PINE))))
+#define __digitalPinToBit(P) \
+(((P) >= 0 && (P) <= 7) ? (P) : (((P) >= 8 && (P) <= 15) ? (P) - 8 : (((P) >= 16 && (P) <= 23) ? (P) - 16 : (((P) >= 16 && (P) <= 23) ? (P) - 24 : (P) - 32))))
+#else
#define __digitalPinToPortReg(P) \
(((P) >= 0 && (P) <= 7) ? &PORTB : (((P) >= 8 && (P) <= 15) ? &PORTD : (((P) >= 16 && (P) <= 23) ? &PORTC : &PORTA)))
#define __digitalPinToDDRReg(P) \
@@ -232,7 +255,7 @@
(((P) >= 0 && (P) <= 7) ? &PINB : (((P) >= 8 && (P) <= 15) ? &PIND : (((P) >= 8 && (P) <= 15) ? &PINC : &PINA)))
#define __digitalPinToBit(P) \
(((P) >= 0 && (P) <= 7) ? (P) : (((P) >= 8 && (P) <= 15) ? (P) - 8 : (((P) >= 16 && (P) <= 23) ? (P) - 16 : (P) - 24)))
-
+#endif
// --- Arduino Leonardo and ATmega16U4/32U4 based boards ---
#elif (defined(ARDUINO_AVR_LEONARDO) || \
@@ -263,9 +286,15 @@
// --- Arduino Uno and ATmega168/328 based boards ---
#elif (defined(ARDUINO_AVR_UNO) || \
defined(ARDUINO_AVR_DUEMILANOVE) || \
+ defined(__AVR_ATmega8__) || \
+ defined(__AVR_ATmega48__) || \
+ defined(__AVR_ATmega48P__) || \
+ defined(__AVR_ATmega48PB__) || \
+ defined(__AVR_ATmega88P__) || \
+ defined(__AVR_ATmega88PB__) || \
defined(__AVR_ATmega168__) || \
- defined(__AVR_ATmega168A__) || \
defined(__AVR_ATmega168PA__) || \
+ defined(__AVR_ATmega168PB__) || \
defined(__AVR_ATmega328__) || \
defined(__AVR_ATmega328P__) || \
defined(__AVR_ATmega328PB__))
@@ -281,7 +310,7 @@
#define SPI_HW_MISO_PIN (12) //PB3
#define SPI_HW_SCK_PIN (13) //PB1
-#if defined(__AVR_ATmega328PB__)
+#if defined(__AVR_ATmega48PB__) || defined(__AVR_ATmega88PB__) || defined(__AVR_ATmega168PB__) || defined(__AVR_ATmega328PB__)
#define __digitalPinToPortReg(P) \
(((P) >= 0 && (P) <= 7) ? &PORTD : (((P) >= 8 && (P) <= 13) ? &PORTB : (((P) >= 14 && (P) <= 19) ? &PORTC : &PORTE)))
#define __digitalPinToDDRReg(P) \
@@ -301,14 +330,52 @@
(((P) >= 0 && (P) <= 7) ? (P) : (((P) >= 8 && (P) <= 13) ? (P) - 8 : (P) - 14))
#endif
+#elif defined(__AVR_ATmega4809__) // Uno WiFi Rev 2, Nano Every
+
+#define UART_RX_PIN (0) //PB0
+#define UART_TX_PIN (1) //PB1
+
+#define I2C_SDA_PIN (22) //PA2
+#define I2C_SCL_PIN (23) //PA3
+
+#define SPI_HW_SS_PIN (8) //PE3
+#define SPI_HW_MOSI_PIN (11) //PE0
+#define SPI_HW_MISO_PIN (12) //PE1
+#define SPI_HW_SCK_PIN (13) //PE2
+
+#define __digitalPinToPortReg(P) \
+(((P) == 2 || (P) == 7 ) ? &VPORTA.OUT : ((P) == 5 || (P) == 9 || (P) == 10) ? &VPORTB.OUT : ((P) == 4) ? &VPORTC.OUT : (((P) >= 14 && (P) <= 17) || (P) == 20 || (P) == 21) ? &VPORTD.OUT : ((P) == 8 || (P) == 11 || (P) == 12 || (P) == 13) ? &VPORTE.OUT : &VPORTF.OUT)
+#define __digitalPinToDDRReg(P) \
+(((P) == 2 || (P) == 7 ) ? &VPORTA.DIR : ((P) == 5 || (P) == 9 || (P) == 10) ? &VPORTB.DIR : ((P) == 4) ? &VPORTC.DIR : (((P) >= 14 && (P) <= 17) || (P) == 20 || (P) == 21) ? &VPORTD.DIR : ((P) == 8 || (P) == 11 || (P) == 12 || (P) == 13) ? &VPORTE.DIR : &VPORTF.DIR)
+#define __digitalPinToPINReg(P) \
+(((P) == 2 || (P) == 7 ) ? &VPORTA.IN : ((P) == 5 || (P) == 9 || (P) == 10) ? &VPORTB.IN : ((P) == 4) ? &VPORTC.IN : (((P) >= 14 && (P) <= 17) || (P) == 20 || (P) == 21) ? &VPORTD.IN : ((P) == 8 || (P) == 11 || (P) == 12 || (P) == 13) ? &VPORTE.IN : &VPORTF.IN)
+#define __digitalPinToBit(P) \
+(((P) == 2 || (P) == 9 || (P) == 11 || (P) == 17) ? 0 : ((P) == 7 || (P) == 10 || (P) == 12 || (P) == 16) ? 1 : ((P) == 5 || (P) == 13 || (P) == 15 || (P) == 18) ? 2 : ((P) == 9 || (P) == 14 || (P) == 19) ? 3 : ((P) == 6 || (P) == 20) ? 4 : ((P) == 3 || (P) == 21) ? 5 : 6 )
+
+
// --- ATtinyX5 ---
#elif defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
// we have only PORTB
#define __digitalPinToPortReg(P) (&PORTB)
#define __digitalPinToDDRReg(P) (&DDRB)
#define __digitalPinToPINReg(P) (&PINB)
-#define __digitalPinToBit(P) \
-(((P) >= 0 && (P) <= 7) ? (P) : (((P) >= 8 && (P) <= 13) ? (P) - 8 : (P) - 14))
+#define __digitalPinToBit(P) (( (P) <= 7) ? (P) : (((P) >= 8 && (P) <= 13) ? (P) - 8 : (P) - 14))
+
+
+// --- ATtiny88 ---
+#elif defined(__AVR_ATtiny88__)
+# if defined(ARDUINO_AVR_DIGISPARKPRO)
+#define __digitalPinToPortReg(P) ((P) <= 7 ? &PORTD : ((P) <= 14 ? &PORTB : ((P) <= 18 ? &PORTA : &PORTC)))
+#define __digitalPinToDDRReg(P) ((P) <= 7 ? &DDRD : ((P) <= 14 ? &DDRB : ((P) <= 18 ? &DDRA : &DDRC)))
+#define __digitalPinToPINReg(P) ((P) <= 7 ? &PIND : ((P) <= 14 ? &PINB : ((P) <= 18 ? &PINA : &PINC)))
+#define __digitalPinToBit(P) ( (P) <= 7 ? (P) : ((P) <= 13 ? ((P) - 8) : ((P) == 14 ? 7 : ((P) <= 16 ? ((P) - 14) : ((P) <= 18 ? ((P) - 17) : ((P) == 25 ? 7 : ((P) - 19)))))) )
+# else
+#define __digitalPinToPortReg(P) ((P) <= 7 ? &PORTD : ((P) <= 15 ? &PORTB : ((P) <= 22 ? &PORTC : ((P) <= 26 ? &PORTA : &PORTC))))
+#define __digitalPinToDDRReg(P) ((P) <= 7 ? &DDRD : ((P) <= 15 ? &DDRB : ((P) <= 22 ? &DDRC : ((P) <= 26 ? &DDRA : &DDRC))))
+#define __digitalPinToPINReg(P) ((P) <= 7 ? &PIND : ((P) <= 15 ? &PINB : ((P) <= 22 ? &PINC : ((P) <= 26 ? &PINA : &PINC))))
+#define __digitalPinToBit(P) ((P) <= 15 ? ((P) & 0x7) : ((P) == 16 ? (7) : ((P) <= 22 ? ((P) - 17) : ((P) == 27 ? (6) : ((P) - 23)))))
+# endif
+
// --- ATtinyX4 + ATtinyX7 ---
#elif defined(__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__) || defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__)
@@ -328,6 +395,7 @@
#define __digitalPinToBit(P) (((P) <= 7) ? (P) : (P) - 8 )
# endif
+
// --- Other ---
#else
@@ -346,7 +414,7 @@
#ifndef digitalWriteFast
#if (defined(__AVR__) || defined(ARDUINO_ARCH_AVR))
#define digitalWriteFast(P, V) \
-if (__builtin_constant_p(P) && __builtin_constant_p(V)) { \
+if (__builtin_constant_p(P)) { \
BIT_WRITE(*__digitalPinToPortReg(P), __digitalPinToBit(P), (V)); \
} else { \
digitalWrite((P), (V)); \
@@ -361,8 +429,8 @@ if (__builtin_constant_p(P) && __builtin_constant_p(V)) { \
#define pinModeFast(P, V) \
if (__builtin_constant_p(P) && __builtin_constant_p(V)) { \
if (V == INPUT_PULLUP) {\
- BIT_WRITE(*__digitalPinToDDRReg(P), __digitalPinToBit(P), (INPUT)); \
- BIT_WRITE(*__digitalPinToPortReg(P), __digitalPinToBit(P), (HIGH)); \
+ BIT_CLEAR(*__digitalPinToDDRReg(P), __digitalPinToBit(P)); \
+ BIT_SET(*__digitalPinToPortReg(P), __digitalPinToBit(P)); \
} else { \
BIT_WRITE(*__digitalPinToDDRReg(P), __digitalPinToBit(P), (V)); \
} \
@@ -378,8 +446,8 @@ if (__builtin_constant_p(P) && __builtin_constant_p(V)) { \
#if (defined(__AVR__) || defined(ARDUINO_ARCH_AVR))
#define digitalReadFast(P) ( (int) __digitalReadFast((P)) )
#define __digitalReadFast(P ) \
- (__builtin_constant_p(P) ) ? ( \
- ( BIT_READ(*__digitalPinToPINReg(P), __digitalPinToBit(P))) ? HIGH:LOW ) : \
+ (__builtin_constant_p(P) ) ? \
+ (( BIT_READ(*__digitalPinToPINReg(P), __digitalPinToBit(P))) ? HIGH:LOW ) : \
digitalRead((P))
#else
#define digitalReadFast digitalRead
@@ -388,7 +456,14 @@ if (__builtin_constant_p(P) && __builtin_constant_p(V)) { \
#ifndef digitalToggleFast
#if (defined(__AVR__) || defined(ARDUINO_ARCH_AVR))
-#define digitalToggleFast(P) BIT_SET(*__digitalPinToPINReg(P), __digitalPinToBit(P))
+#define digitalToggleFast(P) \
+if (__builtin_constant_p(P)) { \
+ BIT_SET(*__digitalPinToPINReg(P), __digitalPinToBit(P)); \
+} else { \
+ digitalWrite(P, ! digitalRead(P)); \
+}
+#else
+#define digitalToggleFast(P) digitalWrite(P, ! digitalRead(P))
#endif
#endif