diff --git a/Readme.md b/Readme.md index a9bf4a4..5c2b3f4 100644 --- a/Readme.md +++ b/Readme.md @@ -1,4 +1,4 @@ -PinChangeInterrupt Library 1.2.3 +PinChangeInterrupt Library 1.2.4 ================================ ![Header Picture](header.png) @@ -25,7 +25,7 @@ See [PCINT pin table](https://github.com/NicoHood/PinChangeInterrupt/#pinchangei A11 (65), A12 (66), A13 (67), A14 (68), A15 (69) Arduino Leonardo/Micro: 8, 9, 10, 11, 14 (MISO), 15 (SCK), 16 (MOSI) HoodLoader2: All (broken out 1-7) pins are usable - Attiny 24/44/84: All pins are usable + Attiny 24/44/84: All pins are usable Attiny 25/45/85: All pins are usable Attiny 13: All pins are usable Attiny 441/841: All pins are usable @@ -283,6 +283,9 @@ the new PinChangeInterrupts may help you a lot. Version History =============== ``` +1.2.4 Release (16.04.2016) +* Fixed Attinyx4/x5 Issue #8 + 1.2.3 Release (24.12.2015) * Added Attiny441/841 support diff --git a/examples/PinChangeInterrupt_Led/PinChangeInterrupt_Led.ino b/examples/PinChangeInterrupt_Led/PinChangeInterrupt_Led.ino index 4667aa0..87e31d6 100644 --- a/examples/PinChangeInterrupt_Led/PinChangeInterrupt_Led.ino +++ b/examples/PinChangeInterrupt_Led/PinChangeInterrupt_Led.ino @@ -1,34 +1,34 @@ /* -Copyright (c) 2014-2015 NicoHood -See the readme for credit to other people. + Copyright (c) 2014-2015 NicoHood + See the readme for credit to other people. -PinChangeInterrupt_TickTock -Demonstrates how to use the library + PinChangeInterrupt_TickTock + Demonstrates how to use the library -Connect a button/cable to pin 7 and ground. -The Led state will change if the pin state does. + Connect a button/cable to pin 7 and ground. + The Led state will change if the pin state does. -PinChangeInterrupts are different than normal Interrupts. -See readme for more information. -Dont use Serial or delay inside interrupts! -This library is not compatible with SoftSerial. + PinChangeInterrupts are different than normal Interrupts. + See readme for more information. + Dont use Serial or delay inside interrupts! + This library is not compatible with SoftSerial. -The following pins are usable for PinChangeInterrupt: -Arduino Uno/Nano/Mini: All pins are usable -Arduino Mega: 10, 11, 12, 13, 50, 51, 52, 53, A8 (62), A9 (63), A10 (64), + The following pins are usable for PinChangeInterrupt: + Arduino Uno/Nano/Mini: All pins are usable + Arduino Mega: 10, 11, 12, 13, 50, 51, 52, 53, A8 (62), A9 (63), A10 (64), A11 (65), A12 (66), A13 (67), A14 (68), A15 (69) -Arduino Leonardo/Micro: 8, 9, 10, 11, 14 (MISO), 15 (SCK), 16 (MOSI) -HoodLoader2: All (broken out 1-7) pins are usable -Attiny 24/44/84: All pins are usable -Attiny 25/45/85: All pins are usable -Attiny 13: All pins are usable -Attiny 441/841: All pins are usable -ATmega644P/ATmega1284P: All pins are usable + Arduino Leonardo/Micro: 8, 9, 10, 11, 14 (MISO), 15 (SCK), 16 (MOSI) + HoodLoader2: All (broken out 1-7) pins are usable + Attiny 24/44/84: All pins are usable + Attiny 25/45/85: All pins are usable + Attiny 13: All pins are usable + Attiny 441/841: All pins are usable + ATmega644P/ATmega1284P: All pins are usable */ #include "PinChangeInterrupt.h" -// choose a valid PinChangeInterrupt pin of your Arduino board +// Choose a valid PinChangeInterrupt pin of your Arduino board #define pinBlink 7 void setup() { @@ -36,15 +36,15 @@ void setup() { pinMode(pinBlink, INPUT_PULLUP); pinMode(LED_BUILTIN, OUTPUT); - // attach the new PinChangeInterrupt and enable event function below + // Attach the new PinChangeInterrupt and enable event function below attachPCINT(digitalPinToPCINT(pinBlink), blinkLed, CHANGE); } void blinkLed(void) { - // switch Led state + // Switch Led state digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN)); } void loop() { - // nothing to do here + // Nothing to do here } diff --git a/library.properties b/library.properties index 087273c..fddfd27 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=PinChangeInterrupt -version=1.2.3 +version=1.2.4 author=NicoHood maintainer=NicoHood sentence=A simple & compact PinChangeInterrupt library for Arduino. diff --git a/src/PinChangeInterrupt.cpp b/src/PinChangeInterrupt.cpp index 44ce0fe..05f5207 100644 --- a/src/PinChangeInterrupt.cpp +++ b/src/PinChangeInterrupt.cpp @@ -123,7 +123,34 @@ void enablePinChangeInterruptHelper(const uint8_t pcintPort, const uint8_t pcint // Pin change mask registers decide which pins are ENABLE as triggers #ifdef PCMSK0 - *(&PCMSK0 + pcintPort) |= pcintMask; +#ifdef PCMSK1 + // Special case for Attinyx4 where PCMSK1 and PCMSK0 are not next to each other + if(&PCMSK1 - &PCMSK0 == 1){ +#endif + *(&PCMSK0 + pcintPort) |= pcintMask; +#ifdef PCMSK1 + } + else{ + switch(pcintPort){ + case 0: + PCMSK0 |= pcintMask; + break; + case 1: + PCMSK1 |= pcintMask; + break; +#ifdef PCMSK2 + case 2: + PCMSK2 |= pcintMask; + break; +#endif +#ifdef PCMSK3 + case 3: + PCMSK3 |= pcintMask; + break; +#endif + } + } +#endif #elif defined(PCMSK) *(&PCMSK + pcintPort) |= pcintMask; #endif @@ -141,19 +168,71 @@ void enablePinChangeInterruptHelper(const uint8_t pcintPort, const uint8_t pcint } void disablePinChangeInterruptHelper(const uint8_t pcintPort, const uint8_t pcintMask) { + bool disable = false; #ifdef PCMSK0 - // disable the mask. - *(&PCMSK0 + pcintPort) &= ~pcintMask; +#ifdef PCMSK1 + // Special case for Attinyx4 where PCMSK1 and PCMSK0 are not next to each other + if(&PCMSK1 - &PCMSK0 == 1){ +#endif + // disable the mask. + *(&PCMSK0 + pcintPort) &= ~pcintMask; - // if that's the last one, disable the interrupt. - if (*(&PCMSK0 + pcintPort) == 0) + // if that's the last one, disable the interrupt. + if (*(&PCMSK0 + pcintPort) == 0) + disable = true; +#ifdef PCMSK1 + } + else{ + switch(pcintPort){ + case 0: + // disable the mask. + PCMSK0 &= ~pcintMask; + + // if that's the last one, disable the interrupt. + if (!PCMSK0) + disable = true; + break; + case 1: + // disable the mask. + PCMSK1 &= ~pcintMask; + + // if that's the last one, disable the interrupt. + if (!PCMSK1) + disable = true; + break; +#ifdef PCMSK2 + case 2: + // disable the mask. + PCMSK2 &= ~pcintMask; + + // if that's the last one, disable the interrupt. + if (!PCMSK2) + disable = true; + break; +#endif +#ifdef PCMSK3 + case 3: + // disable the mask. + PCMSK3 &= ~pcintMask; + + // if that's the last one, disable the interrupt. + if (!PCMSK3) + disable = true; + break; +#endif + } + } +#endif #elif defined(PCMSK) // disable the mask. *(&PCMSK + pcintPort) &= ~pcintMask; // if that's the last one, disable the interrupt. if (*(&PCMSK + pcintPort) == 0) + disable = true; #endif + if(disable) + { #ifdef PCICR PCICR &= ~(1 << (pcintPort + PCIE0)); #elif defined(GIMSK) && defined(PCIE0) /* e.g. ATtiny X4 */ @@ -163,6 +242,7 @@ void disablePinChangeInterruptHelper(const uint8_t pcintPort, const uint8_t pcin #else #error MCU has no such a register #endif + } } /* diff --git a/src/PinChangeInterrupt.h b/src/PinChangeInterrupt.h index d05be7f..98e887f 100644 --- a/src/PinChangeInterrupt.h +++ b/src/PinChangeInterrupt.h @@ -25,7 +25,7 @@ THE SOFTWARE. #pragma once // software version -#define PCINT_VERSION 123 +#define PCINT_VERSION 124 #include "Arduino.h" @@ -78,7 +78,13 @@ PinChangeInterruptEventPCINT ## pcint PCINT_MACRO_BRACKETS // convert a normal pin to its PCINT number (0 - max 23), used by the user // calculates the pin by the Arduino definitions -#define digitalPinToPinChangeInterrupt(p) (digitalPinToPCICR(p) ? ((8 * digitalPinToPCICRbit(p)) + digitalPinToPCMSKbit(p)) : NOT_AN_INTERRUPT) +#if defined(PCIE0) +#define digitalPinToPinChangeInterrupt(p) (digitalPinToPCICR(p) ? ((8 * (digitalPinToPCICRbit(p) - PCIE0)) + digitalPinToPCMSKbit(p)) : NOT_AN_INTERRUPT) +#elif defined(PCIE) +#define digitalPinToPinChangeInterrupt(p) (digitalPinToPCICR(p) ? ((8 * (digitalPinToPCICRbit(p) - PCIE)) + digitalPinToPCMSKbit(p)) : NOT_AN_INTERRUPT) +#else +#error MCU has no such a register +#endif // alias for shorter writing #define PCINTEvent(n) PinChangeInterruptEvent_Wrapper(n) diff --git a/src/PinChangeInterruptSettings.h b/src/PinChangeInterruptSettings.h index 190c9d2..d81c67c 100644 --- a/src/PinChangeInterruptSettings.h +++ b/src/PinChangeInterruptSettings.h @@ -216,8 +216,8 @@ The order is also okay. */ #if defined(__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__) // Port1 is connected to reset, crystal and Pin Interrupt 0 -// deactivate it by default -#if defined(PCINT_ENABLE_PCINT1) -#undef PCINT_ENABLE_PCINT1 +// Deactivate it by default +#if defined(PCINT_ENABLE_PORT1) +#undef PCINT_ENABLE_PORT1 #endif #endif