robobuggy / arduino / InterruptRCRecieverReference / PinChangeInt / RELEASE_NOTES @ c5d6b0e8
History | View | Annotate | Download (19.2 KB)
1 |
****************************************************************************** |
---|---|
2 |
|
3 |
PinChangeInt |
4 |
---- RELEASE NOTES --- |
5 |
|
6 |
Version 2.19 (beta) Tue Nov 20 07:33:37 CST 2012 |
7 |
SANGUINO SUPPORT! ...And Mioduino! |
8 |
...The ATmega644 chip is so cool, how can I not? 4 full ports of Pin Change Interrupt bliss! 32 i/o pins! 64k Flash! 4k RAM! Well I wish I had one. That said, Sanguino users, PLEASE send in your bug or bliss reports! Your interrupt-loving brethren and sistren are depending on you, so I can assure everyone that my changes work on that platform. Thanks. |
9 |
|
10 |
Modified the addPin() method to save 12 bytes; thanks again robtilllart! |
11 |
if (firstPin != NULL) { |
12 |
tmp=firstPin; |
13 |
do { |
14 |
if (tmp->arduinoPin == arduinoPin) { enable(tmp, userFunc, mode); return(0); } |
15 |
if (tmp->next == NULL) break; |
16 |
tmp=tmp->next; |
17 |
} while (true); |
18 |
} |
19 |
Also changed the goto in the PCint() loop to be a while/break combination. No change to |
20 |
code speed, but it looks better and passes the cleanliness "gut check". |
21 |
|
22 |
Includes PinChangeIntTest 1.5 sketch. |
23 |
|
24 |
...Ooops! Forgot the GetPSTR library, needed for the PinChangeIntTest code! Now it's included. |
25 |
****************************************************************************** |
26 |
Version 2.17 (beta) Sat Nov 17 09:46:50 CST 2012 |
27 |
Another bugfix in the PCINT_MULTI_SERVICE section. I was using sbi(PCIFR, PCICRbit); |
28 |
I didn't realize that was for I/O ports, and not ATmega registers. |
29 |
But according to "deprecated.h", |
30 |
"These macros became obsolete, as reading and writing IO ports can |
31 |
be done by simply using the IO port name in an expression, and all |
32 |
bit manipulation (including those on IO ports) can be done using |
33 |
generic C bit manipulation operators." |
34 |
So now I do: |
35 |
PCIFR |= PCICRbit; |
36 |
****************************************************************************** |
37 |
Version 2.15 (beta) Sat Nov 17 01:17:44 CST 2012 |
38 |
Fixed it so that attachInterrupt() will now follow your changes to the user function, |
39 |
as well as the mode. detachInterrupt() still does not delete the PCintPin object but |
40 |
at least you can detach and reattach at will, using different modes (RISING, FALLING, |
41 |
CHANGE) and different functions as you wish. |
42 |
|
43 |
****************************************************************************** |
44 |
Version 2.13 (beta) Mon Nov 12 09:33:06 CST 2012 |
45 |
SIGNIFICANT BUGFIX release! Significant changes: |
46 |
1. PCintPort::curr bug. Interrupts that occur rapidly will likely not get serviced properly by PCint(). |
47 |
2. PCint() interrupt handler optimization. |
48 |
3. PCIFR port bit set bug fix. |
49 |
4. Many static variables added for debugging; used only when #define PINMODE is on. |
50 |
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?). |
51 |
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. |
52 |
Also, modified these release notes. |
53 |
|
54 |
Details: |
55 |
|
56 |
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: |
57 |
ISR(PCINT0_vect) { |
58 |
PCintPort::curr = portB.portInputReg; |
59 |
portB.PCint(); |
60 |
} |
61 |
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): |
62 |
#ifndef DISABLE_PCINT_MULTI_SERVICE |
63 |
pcifr = PCIFR & PCICRbit; |
64 |
PCIFR = pcifr; // clear the interrupt if we will process it (no effect if bit is zero) |
65 |
} while(pcifr); |
66 |
#endif |
67 |
...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: |
68 |
pcifr = PCIFR & PCICRbit; |
69 |
PCIFR = pcifr; // clear the interrupt if we will process it (no effect if bit is zero) |
70 |
PCintPort::curr=portInputReg; // ...Fixed in 2.11beta. |
71 |
} while(pcifr); |
72 |
|
73 |
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: |
74 |
uint8_t changedPins = (PCintPort::curr ^ lastPinView) & |
75 |
((portRisingPins & PCintPort::curr ) | ( portFallingPins & ~PCintPort::curr )); |
76 |
|
77 |
...This speedup is offset by more changes in the PCint() handler, which now looks like the following; there are two bug fixes: |
78 |
---------------------------- |
79 |
FIX 1: sbi(PCIFR, PCICRbit); |
80 |
FIX 2: ...the aforementioned PCintPort::curr=portInputReg; |
81 |
Here's the new code: |
82 |
---------------------------- |
83 |
#ifndef DISABLE_PCINT_MULTI_SERVICE |
84 |
pcifr = PCIFR & PCICRbit; |
85 |
if (pcifr) { |
86 |
//if (PCIFR & PCICRbit) { // believe it or not, this adds .6 micros |
87 |
sbi(PCIFR, PCICRbit); // This was a BUG: PCIFR = pcifr ...And here is the fix. |
88 |
#ifdef PINMODE |
89 |
PCintPort::pcint_multi++; |
90 |
if (PCIFR & PCICRbit) PCintPort::PCIFRbug=1; // PCIFR & PCICRbit should ALWAYS be 0 here! |
91 |
#endif |
92 |
PCintPort::curr=portInputReg; // ...Fixed in 2.11beta. |
93 |
goto loop; // A goto!!! Don't want to look at the portInputReg gratuitously, so the while() will not do. |
94 |
} |
95 |
#endif |
96 |
|
97 |
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... :-( |
98 |
|
99 |
Finally, I am not putting newlines in this commentary so I can make it easier to paste online. |
100 |
|
101 |
****************************************************************************** |
102 |
Version 2.11 (beta) Mon Nov 12 09:33:06 CST 2012 |
103 |
See version 2.13 (beta) above. No change other than tidying up the release notes. |
104 |
****************************************************************************** |
105 |
Version 2.01 (beta) Thu Jun 28 12:35:48 CDT 2012 |
106 |
...Wow, Version 2! What? Why? |
107 |
Modified the way that the pin is tested inside the interrupt subroutine (ISR) PCintPort::PCint(), |
108 |
to make the interrupt quicker and slightly reduce the memory footprint. The interrupt's time is |
109 |
reduced by 2 microseconds or about 7%. Instead of using the mode variable, two bitmasks are maintained |
110 |
for each port. One bitmask contains all the pins that are configured to work on RISING signals, the other |
111 |
on FALLING signals. A pin configured to work on CHANGE signals will appear in both bitmasks of the port. |
112 |
Then, the test for a change goes like this: |
113 |
if (thisChangedPin) { |
114 |
if ((thisChangedPin & portRisingPins & PCintPort::curr ) || |
115 |
(thisChangedPin & portFallingPins & ~PCintPort::curr )) { |
116 |
where portRisingPins is the bitmask for the pins configured to interrupt on RISING signals, and |
117 |
portFallingPins is the bitmask for the pins configured to interrupt on FALLING signals. Each port includes |
118 |
these two bitmask variables. |
119 |
|
120 |
This is a significant change to some core functionality to the library, and it saves an appreciable amount |
121 |
of time (2 out of 36 or so micros). Hence, the 2.00 designation. |
122 |
|
123 |
Tue Jun 26 12:42:20 CDT 2012 |
124 |
I was officially given permission to use the PCint library: |
125 |
|
126 |
Re: PCint library |
127 |
« Sent to: GreyGnome on: Today at 08:10:33 AM » |
128 |
« You have forwarded or responded to this message. » |
129 |
Quote Reply Remove |
130 |
HI, |
131 |
Yeah, I wrote the original PCint library. It was a bit of a hack and the new one has better features. |
132 |
I intended the code to be freely usable. Didn't really think about a license. Feel free to use it in |
133 |
your code: I hereby grant you permission. |
134 |
|
135 |
I'll investigate the MIT license, and see if it is appropriate. |
136 |
Chris J. Kiick |
137 |
Robot builder and all around geek. |
138 |
|
139 |
Version 1.81 (beta) Tue Jun 19 07:29:08 CDT 2012 |
140 |
Created the getPCIntVersion function, and its associated GET_PCINT_VERSION preprocessor macro. The version |
141 |
is a 16-bit int, therefore versions are represented as a 4-digit integer. 1810, then, is the first beta |
142 |
release of 1.81x series. 1811 would be a bugfix of 1.810. 1820 would be the production release. |
143 |
|
144 |
Reversed the order of this list, so the most recent notes come first. |
145 |
|
146 |
Made some variables "volatile", because they are changed in the interrupt code. Thanks, Tony Cappellini! |
147 |
|
148 |
Added support for the Arduino Mega! Thanks to cserveny...@gmail.com! |
149 |
NOTE: I don't have a Mega, so I rely on you to give me error (or working) reports! |
150 |
To sum it up for the Mega: No Port C, no Port D. Instead, you get Port J and Port K. Port B remains. |
151 |
Port J, however, is practically useless because there is only 1 pin available for interrupts. |
152 |
Most of the Port J pins are not even connected to a header connector. Caveat Programmer. |
153 |
|
154 |
Created a function to report the version of this code. Put this #define ahead of the #include of this file, |
155 |
in your sketch: |
156 |
#define GET_PCINT_VERSION |
157 |
Then you can call |
158 |
uint16_t getPCIntVersion (); |
159 |
and it will return a 16-bit integer representation of the version of this library. That is, version 1.73beta |
160 |
will be reported as "1730". 1.74, then, will return "1740". And so on, for whatever version of the library |
161 |
this happens to be. The odd number in the 10's position will indicate a beta version, as per usual, and the |
162 |
number in the 1s place will indicate the beta revision (bugs may necessitate a 1.731, 1.732, etc.). |
163 |
|
164 |
Here are some of his notes based on his changes: |
165 |
Mega and friends are using port B, J and K for interrupts. B is working without any modifications. |
166 |
|
167 |
J is mostly useless, because of the hardware UART. I was not able to get pin change notifications from |
168 |
the TX pin (14), so only 15 left. All other (PORT J) pins are not connected on the Arduino boards. |
169 |
|
170 |
K controls Arduino pin A8-A15, working fine. |
171 |
|
172 |
328/168 boards use C and D. So in case the lib is compiled with Mega target, the C and D will be |
173 |
disabled. Also you cannot see port J/K with other targets. For J and K new flags introduced: |
174 |
NO_PORTJ_PINCHANGES and NO_PORTK_PINCHANGES. |
175 |
Maybe we should have PORTJ_PINCHANGES to enable PJ, because they will be most likely unused. |
176 |
|
177 |
Enjoy! |
178 |
|
179 |
Note: To remain consistent, I have not included PORTJ_PINCHANGES. All ports behave the same, |
180 |
no matter how trivial those ports may seem... no surprises... |
181 |
|
182 |
Version 1.72 Wed Mar 14 18:57:55 CDT 2012 |
183 |
Release. |
184 |
|
185 |
Version 1.71beta Sat Mar 10 12:57:05 CST 2012 |
186 |
Code reordering: Starting in version 1.3 of this library, I put the code that enables |
187 |
interrupts for the given pin, and the code that enables Pin Change Interrupts, ahead of actually |
188 |
setting the user's function for the pin. Thus in the small interval between turning on the |
189 |
interrupts and actually creating a valid link to an interrupt handler, it is possible to get an |
190 |
interrupt. At that point the value of the pointer is 0, so this means that the Arduino |
191 |
will start over again from memory location 0- just as if you'd pressed the reset button. Oops! |
192 |
|
193 |
I corrected it so the code now operates in the proper order. |
194 |
(EDITORIAL NOTE: If you want to really learn something, teach it!) |
195 |
|
196 |
Minor code clean-up: All references to PCintPort::curr are now explicit. This changes the compiled |
197 |
hex code not one whit. I just sleep better at night. |
198 |
|
199 |
Numbering: Changed the numbering scheme. Beta versions will end with an odd number in the hundredths |
200 |
place- because they may be odd- and continue to be marked "beta". I'll just sleep better at night. :-) |
201 |
|
202 |
Version 1.70beta Mon Feb 27 07:20:42 CST 2012 |
203 |
Happy Birthday to me! Happy Birthday tooooo meee! Happy Birthday, Dear Meeeeee-eeeee! |
204 |
Happy Birthday to me! |
205 |
|
206 |
Yes, it is on this auspicious occasion of mine (and Elizabeth Taylor's [R.I.P.]) birthday that I |
207 |
humbly submit to you, gracious Arduino PinChangeInt user, version 1.70beta of the PinChangeInt |
208 |
library. I hope you enjoy it. |
209 |
|
210 |
New in this release: |
211 |
The PinChangeIntTest sketch was created, which can be found in the Examples directory. It exercises: |
212 |
* Two interrupting pins, one on each of the Arduino's PORTs. |
213 |
* detachInterrupt() (and subsequent attachInterrupt()s). |
214 |
Hopefully this will help avoid the embarrassing bugs that I have heretofore missed. |
215 |
|
216 |
As well, it has come to this author's (GreyGnome) attention that the Serial class in Arduino 1.0 |
217 |
uses an interrupt that, if you attempt to print from an interrupt (which is what I was doing in my |
218 |
tests) can easily lock up the Arduino. So I have taken SigurðurOrn's excellent ByteBuffer library |
219 |
and modified it for my own nefarious purposes. (see http://siggiorn.com/?p=460). The zipfile |
220 |
comes complete with the ByteBuffer library; see the ByteBuffer/ByteBuffer.h file for a list of |
221 |
changes, and see the PinChangeIntTest sketch for a usage scenario. Now the (interrupt-less and) |
222 |
relatively fast operation of filling a circular buffer is used in the interrupt routines. The buffer |
223 |
is then printed from loop(). |
224 |
|
225 |
The library has been modified so it can be used in other libraries, such as my AdaEncoder library |
226 |
(http://code.google.com/p/adaencoder/). When #include'd by another library you should #define |
227 |
the LIBCALL_PINCHANGEINT macro. For example: |
228 |
#ifndef PinChangeInt_h |
229 |
#define LIBCALL_PINCHANGEINT |
230 |
#include "../PinChangeInt/PinChangeInt.h" |
231 |
#endif |
232 |
This is necessary because the IDE compiles both your sketch and the .cpp file of your library, and |
233 |
the .h file is included in both places. But since the .h file actually contains the code, any variable |
234 |
or function definitions would occur twice and cause compilation errors- unless #ifdef'ed out. |
235 |
|
236 |
Version 1.6beta Fri Feb 10 08:48:35 CST 2012 |
237 |
Set the value of the current register settings, first thing in each ISR; e.g., |
238 |
ISR(PCINT0_vect) { |
239 |
PCintPort::curr = portB.portInputReg; // version 1.6 |
240 |
... |
241 |
...instead of at the beginning of the PCintPort::PCint() static method. This means that the port is read |
242 |
closer to the beginning of the interrupt, and may be slightly more accurate- only by a couple of microseconds, |
243 |
really, but it's a cheap win. |
244 |
|
245 |
Fixed a bug- a BUG!- in the attachInterrupt() and detachInterrupt() methods. I didn't have breaks in my |
246 |
switch statements! Augh! What am I, a (UNIX) shell programmer? ...Uh, generally, yes... |
247 |
|
248 |
Added the PINMODE define and the PCintPort::pinmode variable. |
249 |
|
250 |
Version 1.51 Sun Feb 5 23:28:02 CST 2012 |
251 |
Crap, a bug! Changed line 392 from this: |
252 |
PCintPort::pinState=curr & changedPins ? HIGH : LOW; |
253 |
to this: |
254 |
PCintPort::pinState=curr & p->mask ? HIGH : LOW; |
255 |
Also added a few lines of (commented-out) debug code. |
256 |
|
257 |
Version 1.5 Thu Feb 2 18:09:49 CST 2012 |
258 |
Added the PCintPort::pinState static variable to allow the programmer to query the state of the pin |
259 |
at the time of interrupt. |
260 |
Added two new #defines, NO_PIN_STATE and NO_PIN_NUMBER so as to reduce the code size by 20-50 bytes, |
261 |
and to speed up the interrupt routine slightly by declaring that you don't care if the static variables |
262 |
PCintPort::pinState and/or PCintPort::arduinoPin are set and made available to your interrupt routine. |
263 |
// #define NO_PIN_STATE // to indicate that you don't need the pinState |
264 |
// #define NO_PIN_NUMBER // to indicate that you don't need the arduinoPin |
265 |
|
266 |
Version 1.4 Tue Jan 10 09:41:14 CST 2012 |
267 |
All the code has been moved into this .h file, so as to allow #define's to work from the user's |
268 |
sketch. Thanks to Paul Stoffregen from pjrc.com for the inspiration! (Check out his website for |
269 |
some nice [lots more memory] Arduino-like boards at really good prices. ...This has been an unsolicited |
270 |
plug. Now back to our regular programming. ...Hehe, "programming", get it?) |
271 |
|
272 |
As a result, we no longer use the PinChangeIntConfig.h file. The user must #define things in his/her |
273 |
sketch. Which is better anyway. |
274 |
|
275 |
Removed the pcIntPorts[] array, which created all the ports by default no matter what. Now, only |
276 |
those ports (PCintPort objects) that you need will get created if you use the NO_PORTx_PINCHANGES #defines. |
277 |
This saves flash memory, and actually we get a bit of a memory savings anyway even if all the ports are |
278 |
left enabled. |
279 |
|
280 |
The attachInterrupt and detachInterrupt routines were modified to handle the new PCintPort objects. |
281 |
|
282 |
Version 1.3 Sat Dec 3 22:56:20 CST 2011 |
283 |
Significant internal changes: |
284 |
Tested and modified to work with Arduino 1.0. |
285 |
|
286 |
Modified to use the new() operator and symbolic links instead of creating a pre-populated |
287 |
PCintPins[]. Renamed some variables to simplify or make their meaning more obvious (IMHO anyway). |
288 |
Modified the PCintPort::PCint() code (ie, the interrupt code) to loop over a linked-list. For |
289 |
those who love arrays, I have left some code in there that should work to loop over an array |
290 |
instead. But it is commented out in the release version. |
291 |
|
292 |
For Arduino versions prior to 1.0: The new() operator requires the cppfix.h library, which is |
293 |
included with this package. For Arduino 1.0 and above: new.h comes with the distribution, and |
294 |
that is #included. |
295 |
|
296 |
Version 1.2 Sat Dec 3 Sat Dec 3 09:15:52 CST 2011 |
297 |
Modified Thu Sep 8 07:33:17 CDT 2011 by GreyGnome. Fixes a bug with the initial port |
298 |
value. Now it sets the initial value to be the state of the port at the time of |
299 |
attachInterrupt(). The line is port.PCintLast=port.portInputReg; in attachInterrupt(). |
300 |
See GreyGnome comment, below. |
301 |
|
302 |
Added the "arduinoPin" variable, so the user's function will know exactly which pin on |
303 |
the Arduino was triggered. |
304 |
|
305 |
Version 1.1 Sat Dec 3 00:06:03 CST 2011 |
306 |
...updated to fix the "delPin" function as per "pekka"'s bug report. Thanks! |
307 |
|
308 |
---- ^^^ VERSIONS ^^^ (NOTE TO SELF: Update the PCINT_VERSION define, below) ------------- |
309 |
|
310 |
See google code project for latest, bugs and info http://code.google.com/p/arduino-pinchangeint/ |
311 |
For more information Refer to avr-gcc header files, arduino source and atmega datasheet. |
312 |
|
313 |
This library was inspired by and derived from "johnboiles" (it seems) |
314 |
PCInt Arduino Playground example here: http://www.arduino.cc/playground/Main/PcInt |
315 |
If you are the original author, please let us know at the google code page |
316 |
|
317 |
It provides an extension to the interrupt support for arduino by |
318 |
adding pin change interrupts, giving a way for users to have |
319 |
interrupts drive off of any pin. |
320 |
|
321 |
This program is free software: you can redistribute it and/or modify |
322 |
it under the terms of the GNU General Public License as published by |
323 |
the Free Software Foundation, either version 3 of the License, or |
324 |
(at your option) any later version. |
325 |
|
326 |
This program is distributed in the hope that it will be useful, |
327 |
but WITHOUT ANY WARRANTY; without even the implied warranty of |
328 |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
329 |
GNU General Public License for more details. |
330 |
|
331 |
You should have received a copy of the GNU General Public License |
332 |
along with this program. If not, see <http://www.gnu.org/licenses/>. |