Show Posts
Pages: 1 [2] 3 4 ... 6
16  Community / Exhibition / Gallery / Version 2.13beta is now out. ...Important and major bugfix release! on: November 16, 2012, 10:32:31 pm
******************************************************************************

        PinChangeInt
        ---- RELEASE NOTES ---

******************************************************************************
Version 2.13 (beta) Mon Nov 12 09:33:06 CST 2012
SIGNIFICANT BUGFIX release! Significant changes:
1. PCintPort::curr bug. Interrupts that occur rapidly will likely not get serviced properly by PCint().
2. PCint() interrupt handler optimization.
3. PCIFR port bit set bug fix.
4. Many static variables added for debugging; used only when #define PINMODE is on.
5. detachInterrupt() no longer does a delete(), since that wasn't working anyway. When you detachInterrupt(), the PORT just disables interrupts for that pin; the PCintPin object remains in memory and in the linked list of pins (possibly slowing down your interrupts a couple of micros).  You can reenable a detached interrupt- but you must do it within the PinChangeInt library (would anyone ever enable an interrupt on a pin, then disable it, then have need to reenable it but not using the library?).
6. attachInterrupt() now returns a uint8_t value:  1 on successful attach, 0 on successful attach but using an already-enabled pin, and -1 if the new() operator failed to create a PCintPin object.
Also, modified these release notes.

Details:

Uncovered a nasty bug, thanks to robtillaart on the Arduino Forums and Andre' Franken who posted to the PinChangeInt groups. This bug was introduced by me when I assigned PCintPort::curr early in the interrupt handler:
Code:
ISR(PCINT0_vect) {
    PCintPort::curr = portB.portInputReg;
    portB.PCint();
}
Later, in the interrupt handler PCint(), we loop as long as PCIFR indicates a new interrupt wants to be triggered, provided DISABLE_PCINT_MULTI_SERVICE is not defined (it is not by default):
Code:
#ifndef DISABLE_PCINT_MULTI_SERVICE
        pcifr = PCIFR & PCICRbit;
        PCIFR = pcifr;  // clear the interrupt if we will process it (no effect if bit is zero)
} while(pcifr);
#endif
...Well. Problem is, if a pin pops up and causes the PCIFR to change, we have to reread the port and look at how it is now! I wasn't doing that before, so if a new interrupt appeared while I was still servicing the old one, odd behavior would take place. For example, an interrupt would register but then the userFunc would not be called upon to service it.  The code needs to be:
Code:
        pcifr = PCIFR & PCICRbit;
        PCIFR = pcifr;  // clear the interrupt if we will process it (no effect if bit is zero)
        PCintPort::curr=portInputReg; // ...Fixed in 2.11beta.
} while(pcifr);

Also, made the interrupt handler even faster with an optimization from robtillaart to take out the checks for changed pins from the while() loop that steps through the pins:
Code:
uint8_t changedPins = (PCintPort::curr ^ lastPinView) &
                      ((portRisingPins & PCintPort::curr ) | ( portFallingPins & ~PCintPort::curr ));
...This speedup is offset by more changes in the PCint() handler, which now looks like the following; there are two bug fixes:
----------------------------
FIX 1: sbi(PCIFR, PCICRbit);
FIX 2: ...the aforementioned PCintPort::curr=portInputReg;
Here's the new code:
----------------------------
Code:
    #ifndef DISABLE_PCINT_MULTI_SERVICE
        pcifr = PCIFR & PCICRbit;
        if (pcifr) {
        //if (PCIFR & PCICRbit) { // believe it or not, this adds .6 micros
            sbi(PCIFR, PCICRbit); // This was a BUG: PCIFR = pcifr  ...And here is the fix.
            #ifdef PINMODE
            PCintPort::pcint_multi++;
            if (PCIFR & PCICRbit) PCintPort::PCIFRbug=1; // PCIFR & PCICRbit should ALWAYS be 0 here!
            #endif
            PCintPort::curr=portInputReg; // ...Fixed in 2.11beta.
            goto loop;  // A goto!!! Don't want to look at the portInputReg gratuitously, so the while() will not do.
        }
    #endif

Also I added a lot of variables for debugging when PINMODE is defined, for routing out nasty bugs. I may need them in the future... :-(

Finally, I am not putting newlines in this commentary so I can make it easier to paste online.
17  Products / Arduino Due / Re: Purchase the SAM3X8E? on: November 14, 2012, 09:44:52 am

...Octopart, you let me down!  Thanks, CrossRoads. I guess checking the major distributors was a little too obvious for me :-)
18  Community / Exhibition / Gallery / Re: PinChangeInt library- To attach interrupts to multiple Arduino (Uno/Due) pins on: November 14, 2012, 12:57:02 am
I assume its a memory leak as my understanding is that delete does not free memory in Arduino and the current implementation of detach seems to assume that delete works.
Yes, I ran a test and noticed that my memory got gobbled up pretty quickly. Drat!!! ...The problem is not merely in delete(), because delete just calls free().  The problem is that free() doesn't seem to work.

Anyway, regardless of that I like your idea of having detachInterrupt() simply disable the pin from interrupting, rather than using the delete() operator. I am working on it doing just that.

attachInterrupt() will return -1 on error, 0 if the pin has already been added to the list (the pin will be enabled if it is called and had previously been created already), and 1 if a new pin is created.
19  Community / Exhibition / Gallery / Re: PinChangeInt library- To attach interrupts to multiple Arduino (Uno/Due) pins on: November 13, 2012, 07:38:57 am
Hi,
There are two current forum topics where pinchangeint is being used to read incoming rc signals. In both topics, the ops would like to detach pin change interrupts and later reattach them to enter and exit autonomous and RC Modes. I have suggested that this is not the best approach due to the memory leak in detach. As an alternative, would you consider adding an enable function that will set or clear the relevant bit for given pin in the pin change port masks allowing the user to disable pin changes for one more pins and reenable them later without memory leaks.

Duane B
Memory leaks!  Yikes! Could you tell me more about that issue? On the face of it I don't mind such a "pause" function, but moreso I am not comfortable with such a bug. It should be fixed.
20  Products / Arduino Due / Purchase the SAM3X8E? on: November 13, 2012, 01:08:04 am
Hi,
I did a quick (Octopart/Google) search for the SAM3X8E chip in the Due, and I don't see it readily available for sale. Anybody have a link to purchase them?

Thanks.
21  Community / Exhibition / Gallery / Re: PinChangeInt library- To attach interrupts to multiple Arduino (Uno/Due) pins on: November 13, 2012, 12:53:37 am
@GreyGnome
did you have time to look at my remark in #28 regarding your optimization proposal of the boolean expression.

there is a diff in the formulas when rising = 0, falling = 1 and curr = 0

Yes- sorry. I have been a busy busy busy little beaver! Geez, what a week!

You're right- my optimization was messed up because I made a mistake in my truth table. I think your expression is about the best that we can do. Second- there are more dragons lying about than I had bargained for! I spent the better part of a week's free time wrestling with a big bug in my posted code; I said:
Code:
PCintPort::curr ^ lastPinView & (portRisingPins...
and I should have said: 
Code:
(PCintPort::curr ^ lastPinView) & (portRisingPins...

...Operator precedence. It's not just a good idea, it's the law! OMG what a debugging session I had.

The extra nice thing is, because of my debugging, I uncovered a significant flaw in my code! This is a big deal if you have fast interrupts, and it is real nasty when you have, for example, switches that bounce (don't they all?).  The end of the PCint() function should look like this:
Code:
   #ifndef DISABLE_PCINT_MULTI_SERVICE
        pcifr = PCIFR & PCICRbit;
        PCIFR = pcifr;  // clear the interrupt if we will process it (no effect if bit is zero)
        PCintPort::curr=portInputReg; // BUG! ...Fixed in 2.11beta. Without this, we get really weird interrupt behavior. Sheesh.
                                      // This fix slows down the code, though. Even with only 1 pin interrupting.
    } while(pcifr);
    #endif

...don't worry about the speed slowdown mentioned in the comment. With your fix, robtillaart, my tests speed up by a couple of micros. Sadly, that PCintPort::curr=portInputReg will be run even if pcifr is 0. But it's either that or an if statement, in any event. If you don't need it, best to define DISABLE_PCINT_MULTI_SERVICE.

I hope to post version 2.11beta soon. Right now I think I've uncovered/fixed/optimised/edited/compiled everything necessary, but the code is in a bit of a shambles right now so give me a day or two to clean up. In the meantime, there is that damn bug that you can fix in v. 2.01beta by copying from my snippet above.
22  Community / Exhibition / Gallery / Re: PinChangeInt library- To attach interrupts to multiple Arduino (Uno/Due) pins on: November 04, 2012, 12:10:15 pm
Looked at the PCint() code and came up with this.

Code:
    // if fastmask eq zero there will be no irq in the linked list, optimization!
    if (fastMask != 0)
    {
}

Thanks, Rob. That looks like a really good idea; I'm going to change it and run a speed test.  I note that the if statement, above, is certainly (in my mind) not needed, because of the portPCMask. Unless the programmer is creating Pin Change Interrupts outside of this library, any pin that interrupts will by definition mean that fastmask is non-zero.

Also, I have simplified the boolean a little bit so rather than calling it "fastmask", I rather like to leave it at "changedpins" since that is what the bitmask represents.  Hence we have:
Code:
uint8_t changedPins = PCintPort::curr ^ lastPinView & (portRisingPins & (PCintPort::curr | portFallingPins));
We'll see if these optimizations make the code any faster; the compiler is pretty good at getting rid of cruft I think; whether it was able to optimize the invariants, I think the speed test will tell.

Thanks for the optimizations!
23  Community / Exhibition / Gallery / Re: PinChangeInt library- To attach interrupts to multiple Arduino (Uno/Due) pins on: November 03, 2012, 01:53:23 pm

You use a linked list for the PCintPin objects.
you could keep this list in sorted order to speed up the average search time of void PCintPort::PCint()
On average the nr of search steps would be half of the current implementation,

- addPin would be slightly complexer to keep the list sorted.     - http://stackoverflow.com/questions/4825030/c-add-to-linked-list-in-sorted-order -
- addPin could detect that the pin already has in ISR() attached.
- delPin does not need to change as it already can delete from the middle of the list

it might be more robust to add a return value for addPin and delPin that indicates the #pins added /delete. addPin might return -1 if pin exist.
These values can be propagated to attachInterrupt/detachIRQ.

Thanks for the feedback, Rob.

I had considered the sorted linked list, but then I realized that sorting on pin number may not be what the user wants.  It only speeds up the average search time if you can guarantee an even distribution of interrupts. I would rather let the programmer decide in which order he or she decides to add pins.

Having addPin() and attachInterrupt() return values seems pretty easy and somewhat smart, so I will look into doing that.
24  Using Arduino / Programming Questions / Re: PinChangeInt within a custom library on: November 03, 2012, 01:47:02 pm
Thank you so much!
It's too bad there isn't a more convenient and conservative way, but it works!
Well, 3 months later but anyway, for posterity:  Look at the ooPinChangeInt library.
25  Community / Exhibition / Gallery / Re: PinChangeInt library- To attach interrupts to multiple Arduino (Uno/Due) pins on: November 03, 2012, 07:45:28 am
> The test for p == NULL should be directly after PCintPin* p=new PCintPin;
> as one cannot access the members of p when p == NULL

Fixed. Nice catch, thanks!
-GreyGnome
26  Community / Exhibition / Gallery / Version 2.01beta is now out. ...Includes speedups to the ISR! on: June 28, 2012, 12:56:44 pm
June 28, 2012: Version 2.01beta has been released! I had a brainstorm and modified how the ISR loops over the list of possible pins, thereby saving 2 microseconds in the ISR. Look at the notes for the download (here:  http://code.google.com/p/arduino-pinchangeint/downloads/detail?name=pinchangeint-v2.01beta.zip) or read the VERSIONS section of PinChangeInt.h for more information.
27  General Category / General Discussion / Re: Default licence of examples on Arduino Playground? on: June 23, 2012, 07:48:41 pm
Hello, GreyGnome here... I've been maintaining the PinChangeInt library.

Thanks for bringing up the issue of the licenses.  In my eagerness to update the library, I just took it and ran with it without cleaning up the original "johnboiles" attribution, which should really go to ckiick as he posted the original page in December 2008.

Personally, my contract with the user of the library is that, in exchange for my time and efforts, I would like the code to remain free: hence I "impose" the GPL.  See http://www.gnu.org/philosophy/why-not-lgpl.html  I'm not interested in the popularity of my changes, I'm more interested in the freedom of the code, and I'm not interested in the lgpl (the Arduino's authors' choice notwithstanding).

That said, not following up on the PCint derivation was a mistake that I hope to rectify.

- GreyGnome

28  Community / Exhibition / Gallery / Version 1.81beta is now out. Adds MEGA support. on: June 23, 2012, 07:28:08 pm
PinChangeInt Library version 1.81beta has now been released.  It adds MEGA support, for the ATmega1280 and its brethren.  See http://code.google.com/p/arduino-pinchangeint/

From the release notes:

To sum it up for the Mega: No Port C, no Port D. Instead, you get Port J and Port K. Port B remains. Port J, however, is practically useless because there is only 1 pin available for interrupts. Most of the Port J pins are not even connected to a header connector. Caveat Programmer.

From cserveny's (the author of the MEGA stuff) notes:

Mega and friends are using port B, J and K for interrupts. B is working without any modifications.

J is mostly useless, because of the hardware UART. I was not able to get pin change notifications from the TX pin (14), so only 15 left. All other (PORT J) pins are not connected on the Arduino boards. If you can verify this for me, I would love to know for user. Please send me an email or post to the bug reports section. Thanks. -Ed

K controls Arduino pin A8-A15, working fine.

328/168 boards use C and D. So in case the lib is compiled with Mega target, the C and D will be disabled. Also you cannot see port J/K with other targets. For J and K new flags introduced:

NO_PORTJ_PINCHANGES and NO_PORTK_PINCHANGES.

My MEGA changes have not been tested.  The library compiles and runs on my Duemilanove, but I don't have an Arduino Mega.  I would appreciate feedback.  Thanks.
- GreyGnome
29  Using Arduino / Programming Questions / Re: Using PinChangeInt in multiple libraries on: June 23, 2012, 07:21:01 pm
Sorry, laziness on my part. I meant PCintPort::attachInterrupt() and PCintPort::detachInterrupt()

Not intending to be attaching and detaching continually. Just wanted to hide the low level configuration from the end user of a library, so that the attaching is not done in the top sketch. I suppose I could define a preprocessor macro in the library header file, which then gets put in the top sketch, and expanded when the PCintPort methods are in the compiler scope.

Point taken about the $5 chip though...

Thanks for your input.

In the header of the PinChangeInt.h file, I write:


The library has been modified so it can be used in other libraries, such as my AdaEncoder library
   (http://code.google.com/p/adaencoder/).  When #include'd by another library you should #define
   the LIBCALL_PINCHANGEINT macro.  For example:
   #ifndef PinChangeInt_h
   #define LIBCALL_PINCHANGEINT
   #include "../PinChangeInt/PinChangeInt.h"
   #endif
   This is necessary because the IDE compiles both your sketch and the .cpp file of your library, and
   the .h file is included in both places.  But since the .h file actually contains the code, any variable
   or function definitions would occur twice and cause compilation errors- unless #ifdef'ed out.

Hopefully that helps.  See http://code.google.com/p/arduino-pinchangeint/wiki/Usage#Use_from_Another_Library
30  Community / Exhibition / Gallery / Re: Tigger library released: A library for reading digital switches on the Arduino on: March 24, 2012, 02:11:38 pm
Thanks.  I hope you like it!
Pages: 1 [2] 3 4 ... 6