arduino/libraries/PinChangeInt/Posting_Raising_Question.txt

45 lines
4.5 KiB
Text

Prompted by this thread: https://groups.google.com/a/arduino.cc/forum/#!topic/developers/GkCunoVbuVA , I thought I would introduce a thread to spur discussion of creating a bona fide library that would enable Pin Change Interrupts on the Arduino (ATmega-based) processors, as first class interrupts equivalent to attachInterrupt(). I have been maintaining a library for the Arduino, and thinking about the technical details of such a thing for a while now as well.
Ultimately, any solution is going to carry with it some ugliness because the ATmega328p's interrupt model is, at least to a beginning user, ugly. Having two interrupt types is confusing and annoying; the attachInterrupt() function, like the whole concept of External vs Pin Change Interrupts, contains complexities specific to the ATmega 8-bit line. At the moment, the programmer needs to keep in mind this translation table:
Board int.0 int.1 int.2 int.3 int.4 int.5
Uno, Ethernet 2 3
Mega2560 2 3 21 20 19 18
Leonardo 3 2 0 1 7
Due (no translation necessary, the pin number is referenced)
So if you have an 8-bit processor, there's no official support for "interrupt on any pin" so you must translate External Interrupts as per the table. If you are not (eg, Due): just use the pin number. To me that's the most intuitive and it's what I expected to see back when I was first working on the Arduino. But the situation is hard to fix: Different types of interrupts don't all respond to the same stimuli. External Interrupts respond on rising, or falling, or change (either high or low), or low level. Interrupts on 32-bit processors appear to support all of that, plus high level. Pin Change Interrupts by default only support change.
That said, what would be the ultimate goal of such a library? I think it makes the most sense to have a library that supports the concept of "Interrupt by pin number", and it would support as many modes as possible, with the PinChangeInterrupt mimicking the low and high modes in software. Here's some ideas:
* create a new enable function in the Arduino API, referencing the proper interrupt type under the covers. Only Arduino pin numbers are given as arguments but many of those pin numbers will not be available as External Interrupts on (especially) the ATmega328. So, to use the other pins, you have to make them Pin Change Interrupts, and OR the pin number with the flag PINCHANGEINTERRUPT. As its value is 0 on other architectures, it has no effect on the Due and Galileo.
* Or, add code to the attachInterrupt() call to make it work with Pin Change Interrupts. Essentially, it would operate like the above.
* Or, just create another library call, just for 8-bit Arduinos and their wonky Pin Change Interrupts (this is what I'd created).
Concerning a new function in the Arduino API, called for example, "enableInterrupt()":
This call could look the same on any platform, and for 8-bit chips you'd need a flag so as to create the proper interrupt type for the programmer. The flag would be a no-op on other (32-bit) chips. For example:
#ifdef defined(EICRA) && defined(EICRB) && defined(EIMSK)
#define PINCHANGEINTERRUPT 0x80
#define SLOWINTERRUPT 0x80
...
#ifdef NOT_ATMEGA
#define PINCHANGEINTERRUPT 0
#define SLOWINTERRUPT 0
#endif
void enableInterrupt(interruptNumber, function, mode); // declaration
enableInterrupt(2, 0, myFunction, LOW); // Usage example; this sets an interrupt on Arduino pin 2.
// It is an external interrupt.
// The following examples show that the 8-bit chips will create Pin Change Interrupts.
// On the Due and Galileo, they will be regular interrupts (Because SLOWINTERRUPT==0 there).
enableInterrupt(PINCHANGEINTERRUPT | 4, myFunction, RISING); // usage example for pin 4
enableInterrupt(SLOWINTERRUPT | 4, myFunction, RISING); // same thing.
enableInterrupt(4, myFunction, RISING); // ...as will this.
I don't see a way around the complexity and confusion of this call:
enableInterrupt(PINCHANGEINTERRUPT | 4, myFunction, RISING); // usage example for pin 4
but I think it's clearer than our current situation, where External Interrupts are officially supported but for Pin Change Interrupts the user is on his or her own, or they find a library somewhere.
On Monday, August 11, 2014 9:54:11 AM UTC-5, David A. Mellis wrote:
Just to throw in a random opinion: I think something like this would be good to include, although I haven't thought about the technical details. If it does get added, though, it should probably be called something like attachPinChangeInterrupt() as opposed to something with "PCINT" or "int".