add attach PCINT function

235 views
Skip to first unread message

Nevada Smith

unread,
Aug 10, 2014, 10:33:34 AM8/10/14
to devel...@arduino.cc
Hi.
It would be nice to have an attachPCINT function like the normal attach interrupt function. This could improve a few things:
User can easily use this function
Softserial doesnt use all PCINT at the same time
Softserial and other libraries wont block each other (at least only one port is blocked)
One could detect if a PCINT is already set

In know that PCINT with SoftSerial and other libraries may conflict because of speed. However we could solve it this way: Softserial searches the right Port and adds the PCINT. The other library has to choose a different Port. Advantage of this is that we can use two PCINTs.
On top of that we could add a mechanism that enables more than one function. But then wee need a priority system because Softserial needs to be fast and for example my Infrared library doesnt.

I could possibly implement the attach function. Not sure how slow it is to start the attached function pointer that SoftSerial would break. http://www.gammon.com.au/forum/?id=11488

Just found this:
http://playground.arduino.cc/Main/PinChangeInt

What do you think?

David Mellis

unread,
Aug 11, 2014, 10:54:11 AM8/11/14
to Arduino Developer's List
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".


--
You received this message because you are subscribed to the Google Groups "Developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email to developers+...@arduino.cc.

Paul Stoffregen

unread,
Aug 11, 2014, 1:44:59 PM8/11/14
to devel...@arduino.cc
On 08/11/2014 07:54 AM, David 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".

Why wouldn't it simply be part of attachInterrupt(), with code inside attachInterrupt to transparently handle which hardware resource is used?  Why add another function that, to the user, does exactly the same thing?

Nevada Smith

unread,
Aug 11, 2014, 1:57:27 PM8/11/14
to devel...@arduino.cc
Paul, because:
PCINT is a pinchange interrupt. You still need to check if it was YOUR pin that interrupted. Thatswhy you need to check if its low (for a pullup). Also the user should know what he is doing. adding more than one function to time critial stuff on a pcint will probably cause errors. Lets say we use all 8 pins. checking if the actualy pin is low may be too slow if we check every pin. it might already be high. also functions like Softserial needs to be executed first, because its more timecritical than infrared for example.
What we could to to solve the first problem is to save the whole PORT and there we have all 8 values. then we need to run the function thats specified on this pin. not sure if we should run function by function and the function itself checks if its active or if we should call the right functuion to the right pin. this could be a nice idea if we asume every port that should be used for pcint has a pullup set. this will give us some overhead that might be critical for Softserial. anyways i like the idea. and would use mellis function name.

Brian Cook

unread,
Aug 11, 2014, 2:06:51 PM8/11/14
to devel...@arduino.cc

> Paul, because:
> PCINT is a pinchange interrupt. You still need to check if it was YOUR
> pin that interrupted.

Or, the API could easily do that. It is fairly easy to mimic
attachInterrupt functionality using pin-change interrupts.

- Brian

Nevada Smith

unread,
Aug 11, 2014, 2:15:13 PM8/11/14
to devel...@arduino.cc
Brian, its not about checking if its interrupt, pcint or nothing.

If a PCINT was triggered on the uno for example (0-7) it could be every port. 8 possibilities. you need to know what pin actually triggered the change. therefore you could check if its high or low. or the function could set this too. we could built stuff around this but its not that easy. the biggest problem is the time.

example:
*PCint for softserial and infrared was set on pin 6 and 7.
*PCINT was triggered
*routine saves the whole register
*routive compares register to the ports that were added (6 and 7), ignore port 0-5
*routine checks if port for int 6 is HIGH or LOW depending on the setting. if it is it will trigger its interrupt routine.
*if not it will check the other port
*if its still not the 2nd port it will close, because another pin (0-5) triggered.

clearer?

Brian Cook

unread,
Aug 11, 2014, 2:44:35 PM8/11/14
to devel...@arduino.cc

> Brian, its not about checking if its interrupt, pcint or nothing.
>
> If a PCINT was triggered on the uno for example (0-7) it could be
> every port. 8 possibilities. you need to know what pin actually
> triggered the change. therefore you could check if its high or low. or
> the function could set this too. we could built stuff around this but
> its not that easy.

"Not that easy"? Bah.

I know of two mature well debugged ready to use libraries. I suspect
there are more. The "hard part" is picking which one to use and getting
the author to agree.

- Brian

Nevada Smith

unread,
Aug 11, 2014, 2:55:35 PM8/11/14
to devel...@arduino.cc, bc...@rowdydogsoftware.com
Why not share the libraries with us?

Paul Stoffregen

unread,
Aug 11, 2014, 2:55:48 PM8/11/14
to devel...@arduino.cc
Speaking as the maker of a non-AVR third party board, I'd really like to
avoid expanding the Arduino API in a direction that's specific to 8 bit
hardware.

With Arduino Due already selling and Arduino Zero on the horizon, I'm
also pretty sure AVR-specific APIs aren't a good path for Arduino either.

Yes, it's easier in the short term. But in the long term, in a best
case scenario the API ends up a mess, and in a worst case, many third
party libraries and projects craft non-portable code that isn't easily
updated. Please, I beg of you, think of the long term when proposing
APIs for Arduino.


Brian Cook

unread,
Aug 11, 2014, 3:00:20 PM8/11/14
to devel...@arduino.cc

David Mellis

unread,
Aug 12, 2014, 10:09:14 AM8/12/14
to Arduino Developer's List
That could work too. I was commenting on the wording, not necessarily the API.

Nevada Smith

unread,
Nov 15, 2014, 2:02:50 PM11/15/14
to devel...@arduino.cc
I looked through the available resources and came to the following conclusion:

The most advanced PCINT library on github might be powerfull but is very complicated. People who understand this code can rather code this stuff manually, from my point of view.
And i also think the c++ increases the flash size.
https://github.com/GreyGnome/PinChangeInt

The next example on the playground works perfectly and seems to be somehow usefull. The problem with this one is that its only usable for a 328 and takes a lot of overhead + ram because of all function pointers. But at least its working fine.
http://playground.arduino.cc/Main/PcInt

Is there a way to somehow avoid to save a lot of function pointers or maybe we could limit it to a few?
So my solution for now is to provide a simple manual implementation for my IRL library which takes less flash + ram because i only use a single PCINT.
Any idea how to avoid this overhead and also make the lib useable for different avr MCUs?


And maybe an idea for the next IDE release: What about adding something like this?

volatile uint8_t *port_to_pcmask[] = {
  &PCMSK0,
  &PCMSK1,
  &PCMSK2
};

And we'd also have to solve this offset here:
PCICR &= ~(0x01 << port);

~Nico

GreyGnome

unread,
Nov 25, 2014, 6:16:35 PM11/25/14
to devel...@arduino.cc
On Saturday, November 15, 2014 1:02:50 PM UTC-6, Nevada Smith wrote:
I looked through the available resources and came to the following conclusion:

The most advanced PCINT library on github might be powerfull but is very complicated. People who understand this code can rather code this stuff manually, from my point of view.

Hello,
As the maintainer of the PinChangeInt library I thought I'd chime in ...

I am chastened to have the library called "very complicated". I guess it is, but I had hoped to isolate the programmer from the inner details of the Pin Change Interrupts, and so make it simple to use them- as easy as attachInterrupt(), to be sure. Obviously I did not communicate that well. I'll work on it.

The goals of the library are the following:
* Make interrupts on any pin as easy as attachInterrupt(); that is, relieve the programmer from having to concern themselves with the various registers that are necessary for PinChangeInterrupts.
* Allow the programmer to set those interrupts in any combination of modes: HIGH, LOW, or CHANGE.
* Be as quick as possible, with as little overhead as possible around the user's interrupt routines.
* Enable sophisticated programmers to optimize the library for speed and size.

When you know what pins you want and are willing to do the setup, it takes very little code to set up a Pin Change Interrupts. But presenting a simple interface to the programmer in the form of a general library comes at a cost: things get hairy quickly when you want to account for matching only certain pins on a port, and allowing for any of HIGH, LOW, or CHANGE. I don't know that it's possible to meet the design goals listed and make the code much smaller. I don't doubt some things can be done. But to reduce the code size appreciably would be difficult if it was to remain as easy to use as attachInterrupt().

I have compiled Receive_PinChangeInterrupt_Basic.ino from the IRLremote library and it comes in at 3170 bytes. Using the PinChangeInt library with all of its compile-time optimizations turned on, it comes in at 4426 bytes. That's a 1300 byte difference for the library. Pricey? Perhaps, but then again so is Serial.print(). As well, my tests showed that the PinChangeInterrupt's interruption time- from interrupt, to a simple routine, and back out to loop(), took about 29 microseconds. In a head-to-head comparison, the External Interrupts took 14 microseconds. Someone has to decide it's worth the time and effort to squeeze more time and space out of the library.

GreyGnome

unread,
Nov 25, 2014, 6:18:49 PM11/25/14
to devel...@arduino.cc
Regarding Performance and code size:
I can tell you this: I built a control panel for my daughter's play kitchen. The thing displays a clock, has a timer function, responds to two quad encoders, two switches, and two potentiometers, reads sound files in a FAT filesystem on a micro SD card and sends them to an MP3 player, and draws pretty patterns on an LED display. It is able to do all of this on an ATmega328p and using the Pin Change Interrupt library. I don't know that further space or speed optimization is necessary, especially for a beginner programmer. An advanced person might not use the Pin Change Interrupt library anyway; if they are that tight on space and time they will go ahead and optimize their code. At that point, they may not even use the Arduino...

Regarding whether a general purpose API is possible:
The problem on the ATmega chips is deciding whether you meant External Interrupts or Pin Change Interrupts. You would need logic that determined that the user did or did not only call the two External Interrupt pins on the ATmega328, for example. To do this, the user would have to indicate this at compile time, prior to the #include of the library, which now adds a bit of 8-bit wonkiness to the works. If that's ok, then the API could certainly be generalized for a whole range of CPUs.

It could work that the library simply calls Pin Change Interrupts by default, and if someone knew enough to request External Interrupts, they could add that functionality. But this paradigm breaks down for the ATmega2560 series of chips, at least, because there the advantages of the Pin Change Interrupt library are much reduced (only a subset of the pins are available for these interrupts).


Finally, getting the authors to agree to share the code would be simple. The Pin Change Interrupt code's license has been changed to the Apache 2.0, for maximum sharing.

-GreyGnome (aka Mike Schwager), maintainer of the PinChangeInterrupt library

Nevada Smith

unread,
Dec 3, 2014, 12:29:39 PM12/3/14
to devel...@arduino.cc
I've come up with a very compact version of a new PCINT library.

I actually have a 2nd version i mind for more advanced users to deactivate some ports and pass the while port trigger to 3 separate weak functions. But thats not the point right now.

So ive got a very simple and small setup with very small flash and ram usage. The problem now is just to put it into a single .h file (or with a c/cpp as well). I have problems to get it working with the same sketch size. Could anyone review this code and maybe help to put this into a normal library? At the time of writing this post its not converted into a library though. I might find a solution and update the github repository.

https://github.com/NicoHood/PinChangeInterrupt

Nevada Smith

unread,
Feb 22, 2015, 7:53:01 AM2/22/15
to devel...@arduino.cc
The new dev update of my PCINT library is now highly customizable.

You can deactivate single ports and even pins.
Only the used pins will be compiled. This all happens automatically by makros.
If there is no hardware support for the PCINT, then it wont be used.
Pin priority can be reordered (for example pin 0-3 on Uno is not likely used)
It also only used the needed ram setting for the used ports (3 per port).
No ram nor progmem pointers needed anymore.
Maximum speed (looked at the asm output, no better way to do it).
Executing the last PCINT function takes 4uS.
Code is very clean (beside a lot of makro definitions for easy deactivating pins)
Easy to use examples for beginners who dont care about the optional advanced settings.

One thing that would make the library nearly perfect is only compiling the needed ISRs.
I tested some things and I need some help to understand the compiling process of the IDE.

If i place a 2nd .cpp with an ISR inside a library folder it will always compile it (uses 20 bytes of flash for en empty ISR).
If i do the same inside the Arduino Core it wont compile. Only if I use a function inside the .cpp file (like HW Serial0).
Why does this happen and how can I achieve the same for a library? Or do I have to move the PCINT library inside the core to make this happen?

So there are only a few things left that can be improved:
Only compile the ISRs of the used PORTs
Add port3 support (no arduino board uses this though)

I could also add a ram pointer version, but this does not make sense to me since it just removes the fixed function name in the cost of NUM_PCINTS * 2 bytes of ram.

https://github.com/NicoHood/PinChangeInterrupt/tree/dev

Is there anything that looks bad for you? May I have some feedback? What else would you change?

Tom Igoe

unread,
Feb 22, 2015, 4:50:32 PM2/22/15
to devel...@arduino.cc
Looks promising. How well does it play with other libraries that use things like timer interrupts, like the servo lib, tone() or analogRead()?  Imagining an  example where someone uses this lib to read buttons instead of doing digitalWrite(), then uses the button presses to control a rudimentary synthesizer using the tone() command. Feasible, or would the interrupt handlers conflict?

t.


Nevada Smith

unread,
Feb 23, 2015, 10:00:40 AM2/23/15
to devel...@arduino.cc
Well it would conflict the same as the normal Interrupts. If the user adds to long function calls inside the ISR or Serial print etc this will fail and maybe crash the program. But its just the same positive or negatives aspects a normal interrupt has (like on pin 2 or 3).

The speed also isnt a big deal since I measured 4uS to actually execute the correct sketch. I can imagine that the not so optimized Arduino functions for a single pin are ironically slower. If more pins are attached at the same time, and triggered very often this could conflict in missed ISRs. But thats a genral ISR problem the user should be aware and has nothing to do with the library. Only do short things inside the ISR.

It would break SoftSerial though. At least you cannot use both at the same time. I tried to integrat the Softserial with this library but since it has fixed function names this would need function pointers or some workaround. I could get it working in my first attempt and I had not the mood to continue with it (because noone even merges the perfect Softserial fix of blathijs on github, so I shouldnt care about SS compatibility before this happens and anyone shows interrest in merging this perfect PR).

The really only disadvantage is the fixed function naming. Then It is not that easy to create libraries which uses PCINT with a passed in pin. The user has to add the ISR in the .ino file (see my IRL remote on github with an old version of the pcint lib). The rest is just the same as normal pin interrupts. Just that we now can use all Arduino pins for that :)

Tom Igoe

unread,
Feb 23, 2015, 10:09:46 AM2/23/15
to devel...@arduino.cc
On Feb 23, 2015, at 10:00 AM, Nevada Smith <nico...@web.de> wrote:

Well it would conflict the same as the normal Interrupts. If the user adds to long function calls inside the ISR or Serial print etc this will fail and maybe crash the program. But its just the same positive or negatives aspects a normal interrupt has (like on pin 2 or 3).

That’s the same weakness that the current attachInterrupt() has, so I wouldn’t consider it introducing a new problem. I think it’s a matter of training users how to use ISRs carefully. 


The speed also isnt a big deal since I measured 4uS to actually execute the correct sketch. I can imagine that the not so optimized Arduino functions for a single pin are ironically slower. If more pins are attached at the same time, and triggered very often this could conflict in missed ISRs. But thats a genral ISR problem the user should be aware and has nothing to do with the library. Only do short things inside the ISR.

I wasn’t too worried about speed, but that’s nice to know. 


It would break SoftSerial though. At least you cannot use both at the same time. I tried to integrat the Softserial with this library but since it has fixed function names this would need function pointers or some workaround. I could get it working in my first attempt and I had not the mood to continue with it (because noone even merges the perfect Softserial fix of blathijs on github, so I shouldnt care about SS compatibility before this happens and anyone shows interrest in merging this perfect PR).

Would it be possible to have it spit out an error message if it detects SoftSerial, or another library that it breaks, on compile?  That might address the issue. (that’d be a useful feature for many libraries, of course, but probably a separate problem).


The really only disadvantage is the fixed function naming. Then It is not that easy to create libraries which uses PCINT with a passed in pin. The user has to add the ISR in the .ino file (see my IRL remote on github with an old version of the pcint lib). The rest is just the same as normal pin interrupts. Just that we now can use all Arduino pins for that :)

Oh, I didn’t pick up on that reading it through. Looking through the examples now I see it. Yeah, that’s a bit awkward, but probably solvable with some creative UI thinking. Calling it PinChangeEvent(pinNumber) for example, if that’s possible, seems manageable to me. Just my opinion, though. 

Nevada Smith

unread,
Feb 23, 2015, 10:24:38 AM2/23/15
to devel...@arduino.cc
Tom,
you cannot detect it I think. Maybe the Arduino built environment could if you have a look at the preprocessors makros for the include guard. The problem simply is that softserial Implements EVERY Pcint ISR routine. So then the sketch wont compile because they are implemented. That of course only happens if you try to use both at the same time. A simple documentation note should be fine. You cannot have everything at the same time. AltSoftSerial would still work I think (uses timers).

As you can see in the example you can use PinChangeEvent(pinNumber)just that the passed in pinNumber has to be text. If you look at the source, this is a makro which uses some makro tricks to create if statements with makros. So the input has to happen via a makro like
#define myPin 3
or just passing the pin directly PinChangeEvent(3)
What not work (also stated in the example) is use a
const int myPin = 3;
Since the makro cannot convert this (due to the fixed functions)

We COULD use function pointers to solve this though. I havent tried to integrate this library to the core, then it could make sense to use function pointers. Function pointers would enable using different function names, correct the problem described above and may be used easier with other libs and chaning the interrupts at runtime. But I am not sure if it is worth it. In the worst case it eats the number of available PCINT pins, 2 bytes per function pointer. In the best case it only compiled for the used port, this is 12, 12 and 16 bytes for the Uno ports.

What I'd like to see, and would make things a lot easier is to use the PCINT as library (like spi and Softserial). The problem with that is the linkage. Someone has do add something like library.properties where you can say compileAsDotA file. Because if you compile it as .a file it only uses the needed ISRs of the library and not all. (thats how I understood it, blathijs explained me that in the Arduino irc chat).

So: Would you like to see this as core file or as external library. As library we need a .a compiling option. (not a genrat fix since this could break other libs).
And would you like to use function pointers or not? Its relatively easy to add, it just takes more flash which I dont really want to spend since PCINT should be a simple and compact addition to the Arduino and not use up more ram. As the stysle of a library I could add a makro for fixed/ram functions maybe. Like deacticating ports manually right now. But that would take more work of course.

Tom Igoe

unread,
Feb 23, 2015, 10:51:47 AM2/23/15
to devel...@arduino.cc
On Feb 23, 2015, at 10:24 AM, Nevada Smith <nico...@web.de> wrote:

Tom,
you cannot detect it I think. Maybe the Arduino built environment could if you have a look at the preprocessors makros for the include guard. The problem simply is that softserial Implements EVERY Pcint ISR routine. So then the sketch wont compile because they are implemented. That of course only happens if you try to use both at the same time. A simple documentation note should be fine. You cannot have everything at the same time. AltSoftSerial would still work I think (uses timers).

Okay, so that is a problem for the future, not for this. I’d suggest you just add that to the readMe for now.


As you can see in the example you can use PinChangeEvent(pinNumber)just that the passed in pinNumber has to be text. If you look at the source, this is a makro which uses some makro tricks to create if statements with makros. So the input has to happen via a makro like
#define myPin 3
or just passing the pin directly PinChangeEvent(3)
What not work (also stated in the example) is use a
const int myPin = 3;
Since the makro cannot convert this (due to the fixed functions)

Of those, passing the pin directly is the best for the end user, I think. Though I can see it might cause a problem for some users who want to pass the pin number in via a variable. 


We COULD use function pointers to solve this though. I havent tried to integrate this library to the core, then it could make sense to use function pointers. Function pointers would enable using different function names, correct the problem described above and may be used easier with other libs and chaning the interrupts at runtime. But I am not sure if it is worth it. In the worst case it eats the number of available PCINT pins, 2 bytes per function pointer. In the best case it only compiled for the used port, this is 12, 12 and 16 bytes for the Uno ports.

You know, Paul Stoffergen and Michael Margolis did a nice job with function pointers (I think) in the TimeAlarms library. You get to pass in a function name without it having to be a pointer, and it just works. Don’t know if that’s useful in this case, but maybe worth a look. 


What I'd like to see, and would make things a lot easier is to use the PCINT as library (like spi and Softserial). The problem with that is the linkage. Someone has do add something like library.properties where you can say compileAsDotA file. Because if you compile it as .a file it only uses the needed ISRs of the library and not all. (thats how I understood it, blathijs explained me that in the Arduino irc chat).

I’ll defer to Federico and Cristian on that, I don’t have an informed opinion yet. 


So: Would you like to see this as core file or as external library. As library we need a .a compiling option. (not a genrat fix since this could break other libs).
And would you like to use function pointers or not? Its relatively easy to add, it just takes more flash which I dont really want to spend since PCINT should be a simple and compact addition to the Arduino and not use up more ram. As the stysle of a library I could add a makro for fixed/ram functions maybe. Like deacticating ports manually right now. But that would take more work of course.

In general i think I’d prefer as an external library. That’s my default for everything these days, as I think the system needs to remain as modular as possible, to manage download size, among other things. Theoretically, external libs can always become part of the core, but things written as part of the core only can’t be moved out if you need to make a small initial download.  

On a similar note, I’ve been looking at various BLE libraries lately that require that the user adds them to the core in order to work. It stops a lot of casual users from using those libraries. This is a pattern I’d like to see people avoid, if possible. 

Federico and Cristian may have reasons why this would be better as a core lib, but that’s my 2 cents, anyway.

Tom

Nevada Smith

unread,
Feb 23, 2015, 11:01:15 AM2/23/15
to devel...@arduino.cc
Yeah as library would make more sense. Official supported or not isnt that important for me right now. But I'd like to add the dynamic compiling through an .a file and this requires a patch in the IDE.

The problem with the ble boards might be:
They used the old ID where you cannot create a different core
Or the Core is not flexible enough.

I also created a new Core with better usb function which a lot of people now use. The problem is that just nothing happens on the dev list nor on github. There is a PR for a year now and nothing of this has been included since then. USB could need a lot of improvements. And the downside is to replace the core (in the old 1.0.x days) or nowadays copy the core and modify it and provide a hardware folder.

Same for the PCINT now. I'd have to provide a special new core for PCINT (which would then not be compatible with my hid core, or I have to integrate it there as well which I dont want to do). Or I have to provide new core files and the user has to patch this into every core he uses. Or I have to deal with the bad library compiling right now and cannot improve it any further. So if you say someone else is responsible for the .a compiling, would you contact them? Are they reading this? Should i open another issue on github? Or should I better accept that there wont be a fix for the next time?

Tom Igoe

unread,
Feb 23, 2015, 11:36:25 AM2/23/15
to devel...@arduino.cc

> On Feb 23, 2015, at 11:01 AM, Nevada Smith <nico...@web.de> wrote:
>
> Yeah as library would make more sense. Official supported or not isnt that important for me right now. But I'd like to add the dynamic compiling through an .a file and this requires a patch in the IDE.
>

Ideally, the path to the core for extensions would be through libraries.

> The problem with the ble boards might be:
> They used the old ID where you cannot create a different core
> Or the Core is not flexible enough.

Some of both, and some were sticking to 1.0.x rather than 1.5, assuming the latter was not stable. Hopefully that’ll change now.
>
> I also created a new Core with better usb function which a lot of people now use. The problem is that just nothing happens on the dev list nor on github. There is a PR for a year now and nothing of this has been included since then. USB could need a lot of improvements. And the downside is to replace the core (in the old 1.0.x days) or nowadays copy the core and modify it and provide a hardware folder.
>
> Same for the PCINT now. I'd have to provide a special new core for PCINT (which would then not be compatible with my hid core, or I have to integrate it there as well which I dont want to do). Or I have to provide new core files and the user has to patch this into every core he uses. Or I have to deal with the bad library compiling right now and cannot improve it any further. So if you say someone else is responsible for the .a compiling, would you contact them? Are they reading this? Should i open another issue on github? Or should I better accept that there wont be a fix for the next time?

Federico Fissore and Cristian Maglie, who are reading this list, are the senior programmers who work for Arduino and are responsible for all the codebase. You see them on this list regularly. They move on PRs and issues as fast as their work schedule permits, though they also have other duties. The changes you saw in 1.6, around library format and multiple cores, for example, were their priority for the last few months. They’re reading this, but they don't always respond, as much of the time they are coding (hopefully) or reviewing PRs and patches.

I defer to them always because they are more intimate with the codebase, and because that’s their job and I trust them. I’ve probably said it before, but in case it’s not clear, I’m less close to the core activities of Arduino these days, and I trust Massimo and David C, who are working FT on Arduino, and their teams to keep the core moving forward. So you should always take my opinions with that in mind.

I can’t comment on the USB upgrades you did because I haven’t had the opportunity to use them. I’ve followed the discussion when it’s come up here, but honestly, I haven’t done a deep dive on them because it wasn’t a priority for me in my work. The PCINT caught my attention, though, because I can see using it a lot in class as a default for buttons. But I wanted to understand the details more to see how compatible it was. Your comments helped me to get that, thanks.

As for the flexibility of the core: well, that was one big reason for the 1.5/1.6 changes. Those changes addressed some much-needed issues, but not all of them. So now we move forward to address the next ones.



Nevada Smith

unread,
Feb 23, 2015, 11:54:14 AM2/23/15
to devel...@arduino.cc
Okay cool.
So the plan now is to improve the current concept and maybe test ram pointers only if the library compilation has an option for this .a thing.

If you also have a change to test this, let me know how the results are. Things like buttons and blinking leds should be very easy for this. And it works on any (uno) pin :)

And yeah I see that this all consumes a lot of time in the process of developing. To listen to everybodys needs and still go further with new ideas and concepts. I know that for my personal projects. Now that you are reading this, may I ask a simple offtopic question? I've just started electronics and coding 1 year ago. All I do for Electronics/Arduino is of private interest. And i've just started my job career. I can imagine to maybe switch my job to something like this, since my current job is something mostly different (more pc and networking). Since it makes so much fun but consumes a lot of time and effort I maybe want to do this as job. I am talking of a time in about 3 years after my apprenticeship and university is over. Would there be a chance to apply for a job as Arduino developer? Or do you have any suggestion what I could do in the meantime while I am studying and doing my other job? I am really interested in this stuff and maybe you can point me into any direction. If you want to answer to this offtopic stuff you maybe want to contact me directly: https://nicohood.wordpress.com/about/

Thanks for the PCINT feedback!

Nevada Smith

unread,
Feb 27, 2015, 8:40:22 AM2/27/15
to devel...@arduino.cc
Not sure how you posted me that private, but I read your text Tom. Thanks a lot, that gave me some new ideas. Especially with the fact that if my hobby is my job it wont be my hobby anymore. I will find something for sure :)

Back to the library:
Today I tested compiling with an .a file. Its possible inside the .ino sketch folder and inside the core. I provided a new optional way to attach interrupts so only the needed ISRs get compiled. (not uploaded yet).

Also I tested function pointers. The ISR overhead is way bigger and not so simple. I looked at the asm.
So what I will do is to provide an optional layer to use function pointers and implement the weak functions. That gives us the possibilty to use the very fast library how it is right now and we could also use the API with function pointers for a bit easier use. Then its also easier to access via a different library. Its a bit slower and has more flahs and ram usage but for people who accept it and want a damn simple solution this would work. It cant be done better anyways so this is totally fine.

The best part is that the library will soon be compatible with .a compiling optimization or not. And it will also work with and without function pointers. And everything is still optimal. If you want to use the professional way you may want to use the strong functions and comment the source to deactivate unneeded interrupts. Otherwise just use the api. Feeling confident with the library now. New commits coming sooner or later.

David Mellis

unread,
Feb 27, 2015, 10:58:08 AM2/27/15
to Arduino Developer's List
A couple of thoughts.

One is that the current attachInterrupt() function uses (I believe) function pointers (and associated table). Has the overhead of that approach been a problem in practice? If not, it's not clear (at least to me) that we'd need pin change interrupt handling to be more optimized than regular interrupts. Consider also that the trend is towards microcontrollers with more memory and speed.

A second suggestion if that if we really want a way to optimize away the function pointers / table, it might be simpler simply to have (optional) functions / events with names based on their pin numbers. That is, to handle a pin change event on pin 10, you'd simply implement pinChangeInterruptEvent10(). That seems much simpler than introducing the two parentheses notation I see in your current example:

void PinChangeInterruptEvent(interruptBlink)(void)

In general, Arduino tries hard to avoid introducing new syntax and it would be nice to avoid it in this case too.

David

--

Michael Schwager

unread,
Feb 27, 2015, 1:43:38 PM2/27/15
to devel...@arduino.cc
(full disclosure: I'm the maintainer of https://code.google.com/p/arduino-pinchangeint/ and author of a new library at https://github.com/GreyGnome/EnableInterrupt that handles interrupts in the way I recommend below)

Yes, attachInterrupt() uses function pointers. But on an Arduino Uno there are only 2 External Interrupt pins, so there has been little concern.

There are 22 PCINT pins on an ATmega168/328p, ==22 Function pointers, ==44 bytes RAM. So if only 1 PCINT pin is in use, you'll have 42 wasted bytes of RAM or 4% of the total in an ATmega168 which I think is the smallest Arduino out there.

In return for gaining back those 42 bytes you introduce syntax that is more complicated than what attachInterrupt() requires. Harking back to my days as a beginner, I found Pin Change Interrupts to be both difficult to use and understand, and totally annoying. I don't think it's worth it, especially if Pin Change Interrupts' syntax differs from attachInterrupt().

For the Arduino, I think the aim should be to simplify the interface. That's its strong suit, and that's what attracted me to it in the first place. Later, you can learn the gory details (if you want) about why digitalWrite() is slow, or you can learn about using PROGMEM to store your string constants. You can use all the techniques you've learned to optimize your sketch. By this point in time, if you are concerned about 42 bytes, you are probably not going to use any interrupt library at all... it's more efficient to roll your own custom code, just like it's more efficient to do direct register access than digitalRead/Write().

Pin change interrupts will always be annoying to some extent, because they're so quirky. But I think they can be made to look almost like bona fide interrupts like External Interrupts, and they can be rolled into a standard library wherein any type of interrupt is supported, and all called by pin number, on any Arduino CPU architecture (Paul Stoffregen's idea from 08/2014 -ed.). Do most users care about the difference between a Pin Change Interrupt and External Interrupt, so long as their behavior looks the same? (For PCINTs, you'll always have some microseconds of latency between interrupt and pin determination which is an inescapable problem. Across Arduino CPUs, you'll always have some differences in interrupt modes supported depending not only on interrupt type but on CPU architecture; those problems are inescapable too.)

In any event, such a library could accept a simple interface, but it could present an optional macro system as David suggests, so that advanced users could optimize it so that only certain ISRs are enabled and function pointers are stored in PROGMEM.

That said, I don't even like the attachInterrupt() syntax.

attachInterrupt(interrupt, ISR, mode)

should by deprecated in favor of

new_function_call(pin, ISR, mode)

on any CPU.

On Fri, Feb 27, 2015 at 9:58 AM, David Mellis <d.me...@arduino.cc> wrote:
A couple of thoughts.

One is that the current attachInterrupt() function uses (I believe) function pointers (and associated table). Has the overhead of that approach been a problem in practice? If not, it's not clear (at least to me) that we'd need pin change interrupt handling to be more optimized than regular interrupts. Consider also that the trend is towards microcontrollers with more memory and speed.

A second suggestion if that if we really want a way to optimize away the function pointers / table, it might be simpler simply to have (optional) functions / events with names based on their pin numbers. That is, to handle a pin change event on pin 10, you'd simply implement pinChangeInterruptEvent10(). That seems much simpler than introducing the two parentheses notation I see in your current example:

void PinChangeInterruptEvent(interruptBlink)(void)

In general, Arduino tries hard to avoid introducing new syntax and it would be nice to avoid it in this case too.

--
-Mike Schwager aka GreyGnome

Nevada Smith

unread,
Feb 27, 2015, 3:32:21 PM2/27/15
to devel...@arduino.cc
Function pointers are easier to handle. Its more flexible. They can be set by other libraries without having the user to implement the strong function and set the interrupt function at runtime. It takes more ram and flash though. I am a perfectionist in this case, so I want to save this memory. I dont use more ram just because I can. I still want to do my best, also due to the fact that I am working with 500bytes of ram on the 16u2 for example. I will do both versions anyways. The ram version is just placed on top of the fixed name version.

What I could do is a makro for pinChangeInterruptEventPin10()
But the actual function has to be names with the PCINT number, not the pin number. Otherwise coding would be a mess.
I also think that pinChangeInterruptEventPin10() is more clear and the same sytax as the SerialEvent for example.
Its just the best optimization and still clear.

GreyGnome sorry, but your code looks so unclear for me and it would never work with libraries since you put the ISRs into the .h file. Ever thought of this? Or ever run into the problem with other libs where you then had to declare them static? The thousands of definitions and names and debug stuff is also not clear to me. Just wanna say that. Feel free to play your own game.
Reply all
Reply to author
Forward
0 new messages