Project

General

Profile

Statistics
| Branch: | Revision:

robobuggy / arduino / InterruptRCRecieverReference / PinChangeInt.h @ c5d6b0e8

History | View | Annotate | Download (20.6 KB)

1
// We use 4-character tabstops, so IN VIM:  <esc>:set ts=4   and  <esc>:set sw=4
2
// ...that's: ESCAPE key, colon key, then "s-e-t SPACE key t-s-=-4"
3
//
4
/*
5
 *         This is the PinChangeInt library for the Arduino.
6

7
        See google code project for latest, bugs and info http://code.google.com/p/arduino-pinchangeint/
8
        For more information Refer to avr-gcc header files, arduino source and atmega datasheet.
9

10
        This library was inspired by and derived from "johnboiles" (it seems) 
11
        PCInt Arduino Playground example here: http://www.arduino.cc/playground/Main/PcInt
12
        If you are the original author, please let us know at the google code page
13
        
14
        It provides an extension to the interrupt support for arduino by
15
        adding pin change interrupts, giving a way for users to have
16
        interrupts drive off of any pin.
17

18
        This program is free software: you can redistribute it and/or modify
19
        it under the terms of the GNU General Public License as published by
20
        the Free Software Foundation, either version 3 of the License, or
21
        (at your option) any later version.
22

23
        This program is distributed in the hope that it will be useful,
24
        but WITHOUT ANY WARRANTY; without even the implied warranty of
25
        MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
26
        GNU General Public License for more details.
27

28
        You should have received a copy of the GNU General Public License
29
        along with this program.  If not, see <http://www.gnu.org/licenses/>.
30
        (the file gpl.txt is included with the library's zip package)
31
*/
32
//-------- define these in your sketch, if applicable ----------------------------------------------------------
33
//-------- These must go in your sketch ahead of the #include <PinChangeInt.h> statement -----------------------
34
// You can reduce the memory footprint of this handler by declaring that there will be no pin change interrupts
35
// on any one or two of the three ports.  If only a single port remains, the handler will be declared inline
36
// reducing the size and latency of the handler.
37
// #define NO_PORTB_PINCHANGES // to indicate that port b will not be used for pin change interrupts
38
// #define NO_PORTC_PINCHANGES // to indicate that port c will not be used for pin change interrupts
39
// #define NO_PORTD_PINCHANGES // to indicate that port d will not be used for pin change interrupts
40
// --- Mega support ---
41
// #define NO_PORTB_PINCHANGES // to indicate that port b will not be used for pin change interrupts
42
// #define NO_PORTJ_PINCHANGES // to indicate that port c will not be used for pin change interrupts
43
// #define NO_PORTK_PINCHANGES // to indicate that port d will not be used for pin change interrupts
44
// In the Mega, there is no Port C, no Port D.  Instead, you get Port J and Port K.  Port B remains.
45
// Port J, however, is practically useless because there is only 1 pin available for interrupts.  Most
46
// of the Port J pins are not even connected to a header connection.  // </end> "Mega Support" notes
47
// --- Sanguino, Mioduino support ---
48
// #define NO_PORTA_PINCHANGES // to indicate that port a will not be used for pin change interrupts
49
// --------------------
50
//
51
// Other preprocessor directives...
52
// You can reduce the code size by 20-50 bytes, and you can speed up the interrupt routine
53
// slightly by declaring that you don't care if the static variables PCintPort::pinState and/or
54
// PCintPort::arduinoPin are set and made available to your interrupt routine.
55
// #define NO_PIN_STATE        // to indicate that you don't need the pinState
56
// #define NO_PIN_NUMBER       // to indicate that you don't need the arduinoPin
57
// #define DISABLE_PCINT_MULTI_SERVICE // to limit the handler to servicing a single interrupt per invocation.
58
// #define GET_PCINT_VERSION   // to enable the uint16_t getPCIintVersion () function.
59
// The following is intended for testing purposes.  If defined, then a whole host of static variables can be read
60
// in your interrupt subroutine.  It is not defined by default, and you DO NOT want to define this in
61
// Production code!:
62
// #define PINMODE
63
//-------- define the above in your sketch, if applicable ------------------------------------------------------
64

    
65
/*
66
        PinChangeInt.h
67
        ---- VERSIONS --- (NOTE TO SELF: Update the PCINT_VERSION define, below) -----------------
68
Version 2.19 (beta) Tue Nov 20 07:33:37 CST 2012
69
Version 2.17 (beta) Sat Nov 17 09:46:50 CST 2012
70
Version 2.11 (beta) Mon Nov 12 09:33:06 CST 2012
71

72
        Version 2.01 (beta) Thu Jun 28 12:35:48 CDT 2012
73

74
        Version 1.72 Wed Mar 14 18:57:55 CDT 2012
75

76
        Version 1.71beta Sat Mar 10 12:57:05 CST 2012
77

78
        Version 1.6beta Fri Feb 10 08:48:35 CST 2012
79

80
        Version 1.51 Sun Feb  5 23:28:02 CST 2012
81

82
        Version 1.5 Thu Feb  2 18:09:49 CST 2012
83

84
        Version 1.4 Tue Jan 10 09:41:14 CST 2012
85

86
        Version 1.3 Sat Dec  3 22:56:20 CST 2011
87

88
        Version 1.2 Sat Dec  3 Sat Dec  3 09:15:52 CST 2011
89

90
        Version 1.1 Sat Dec  3 00:06:03 CST 2011
91
        */
92

    
93
#ifndef PinChangeInt_h
94
#define        PinChangeInt_h
95

    
96
#define PCINT_VERSION 2190 // This number MUST agree with the version number, above.
97

    
98
#include "stddef.h"
99

    
100
// Thanks to Maurice Beelen, nms277, Akesson Karlpetter, and Orly Andico for these fixes.
101
#if defined(ARDUINO) && ARDUINO >= 100
102
  #include <Arduino.h>
103
  #include <new.h>
104
  #include <wiring_private.h> // cby and sbi defined here
105
#else
106
  #include <WProgram.h>
107
  #include <pins_arduino.h>
108
  #ifndef   LIBCALL_PINCHANGEINT
109
    #include "../cppfix/cppfix.h"
110
  #endif
111
#endif
112

    
113

    
114
#undef DEBUG
115

    
116
/*
117
* Theory: all IO pins on Atmega168 are covered by Pin Change Interrupts.
118
* The PCINT corresponding to the pin must be enabled and masked, and
119
* an ISR routine provided.  Since PCINTs are per port, not per pin, the ISR
120
* must use some logic to actually implement a per-pin interrupt service.
121
*/
122

    
123
/* Pin to interrupt map:
124
* D0-D7 = PCINT 16-23 = PCIR2 = PD = PCIE2 = pcmsk2
125
* D8-D13 = PCINT 0-5 = PCIR0 = PB = PCIE0 = pcmsk0
126
* A0-A5 (D14-D19) = PCINT 8-13 = PCIR1 = PC = PCIE1 = pcmsk1
127
*/
128

    
129
#undef        INLINE_PCINT
130
#define INLINE_PCINT
131
// Thanks to cserveny...@gmail.com for MEGA support!
132
#if defined __AVR_ATmega2560__ || defined __AVR_ATmega1280__ || defined __AVR_ATmega1281__ || defined __AVR_ATmega2561__ || defined __AVR_ATmega640__
133
        #define __USE_PORT_JK
134
        // Mega does not have PORTA, C or D
135
        #define NO_PORTA_PINCHANGES
136
        #define NO_PORTC_PINCHANGES
137
        #define NO_PORTD_PINCHANGES
138
        #if ((defined(NO_PORTB_PINCHANGES) && defined(NO_PORTJ_PINCHANGES)) || \
139
                        (defined(NO_PORTJ_PINCHANGES) && defined(NO_PORTK_PINCHANGES)) || \
140
                        (defined(NO_PORTK_PINCHANGES) && defined(NO_PORTB_PINCHANGES)))
141
                #define        INLINE_PCINT inline
142
        #endif
143
#else
144
        #if defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644__)
145
                #ifndef NO_PORTA_PINCHANGES
146
                        #define __USE_PORT_A
147
                #endif
148
        #else
149
                #define NO_PORTA_PINCHANGES
150
        #endif
151
        // if defined only D .OR. only C .OR. only B .OR. only A, then inline it
152
        #if (   (defined(NO_PORTA_PINCHANGES) && defined(NO_PORTB_PINCHANGES) && defined(NO_PORTC_PINCHANGES)) || \
153
                        (defined(NO_PORTA_PINCHANGES) && defined(NO_PORTB_PINCHANGES) && defined(NO_PORTD_PINCHANGES)) || \
154
                        (defined(NO_PORTA_PINCHANGES) && defined(NO_PORTC_PINCHANGES) && defined(NO_PORTD_PINCHANGES)) || \
155
                        (defined(NO_PORTB_PINCHANGES) && defined(NO_PORTC_PINCHANGES) && defined(NO_PORTD_PINCHANGES)) )
156
                #define        INLINE_PCINT inline
157
        #endif
158
#endif
159

    
160
// Provide drop in compatibility with johnboiles PCInt project at
161
// http://www.arduino.cc/playground/Main/PcInt
162
#define        PCdetachInterrupt(pin)        PCintPort::detachInterrupt(pin)
163
#define        PCattachInterrupt(pin,userFunc,mode) PCintPort::attachInterrupt(pin, userFunc,mode)
164
#define PCgetArduinoPin() PCintPort::getArduinoPin()
165

    
166

    
167
typedef void (*PCIntvoidFuncPtr)(void);
168

    
169
class PCintPort {
170
public:
171
        PCintPort(int index,int pcindex, volatile uint8_t& maskReg) :
172
        portInputReg(*portInputRegister(index)),
173
        portPCMask(maskReg),
174
        PCICRbit(1 << pcindex),
175
        portRisingPins(0),
176
        portFallingPins(0),
177
        firstPin(NULL)
178
#ifdef PINMODE
179
        ,intrCount(0)
180
#endif
181
        {
182
                #ifdef FLASH
183
                ledsetup();
184
                #endif
185
        }
186
        volatile        uint8_t&                portInputReg;
187
        static                int8_t attachInterrupt(uint8_t pin, PCIntvoidFuncPtr userFunc, int mode);
188
        static                void detachInterrupt(uint8_t pin);
189
        INLINE_PCINT void PCint();
190
        static volatile uint8_t curr;
191
        #ifndef NO_PIN_NUMBER
192
        static        volatile uint8_t        arduinoPin;
193
        #endif
194
        #ifndef NO_PIN_STATE
195
        static volatile        uint8_t        pinState;
196
        #endif
197
        #ifdef PINMODE
198
        static volatile uint8_t pinmode;
199
        static volatile uint8_t s_portRisingPins;
200
        static volatile uint8_t s_portFallingPins;
201
        static volatile uint8_t s_lastPinView;
202
        static volatile uint8_t s_pmask;
203
        static volatile char s_PORT;
204
        static volatile uint8_t s_changedPins;
205
        static volatile uint8_t s_portRisingPins_nCurr;
206
        static volatile uint8_t s_portFallingPins_nNCurr;
207
        static volatile uint8_t s_currXORlastPinView;
208
        volatile uint8_t intrCount;
209
        static volatile uint8_t s_count;
210
        static volatile uint8_t pcint_multi;
211
        static volatile uint8_t PCIFRbug;
212
        #endif
213
        #ifdef FLASH
214
        static void ledsetup(void);
215
        #endif
216

    
217
protected:
218
        class PCintPin {
219
        public:
220
                PCintPin() :
221
                PCintFunc((PCIntvoidFuncPtr)NULL),
222
                mode(0) {}
223
                PCIntvoidFuncPtr PCintFunc;
224
                uint8_t         mode;
225
                uint8_t                mask;
226
                uint8_t arduinoPin;
227
                PCintPin* next;
228
        };
229
        void                 enable(PCintPin* pin, PCIntvoidFuncPtr userFunc, uint8_t mode);
230
        int8_t                addPin(uint8_t arduinoPin,PCIntvoidFuncPtr userFunc, uint8_t mode);
231
        volatile        uint8_t&                portPCMask;
232
        const                uint8_t                        PCICRbit;
233
        volatile        uint8_t                        portRisingPins;
234
        volatile        uint8_t                        portFallingPins;
235
        volatile uint8_t                lastPinView;
236
        PCintPin*        firstPin;
237
};
238

    
239
#ifndef LIBCALL_PINCHANGEINT // LIBCALL_PINCHANGEINT ***********************************************
240
volatile uint8_t PCintPort::curr=0;
241
#ifndef NO_PIN_NUMBER
242
volatile uint8_t PCintPort::arduinoPin=0;
243
#endif
244
#ifndef NO_PIN_STATE
245
volatile uint8_t PCintPort::pinState=0;
246
#endif
247
#ifdef PINMODE
248
volatile uint8_t PCintPort::pinmode=0;
249
volatile uint8_t PCintPort::s_portRisingPins=0;
250
volatile uint8_t PCintPort::s_portFallingPins=0;
251
volatile uint8_t PCintPort::s_lastPinView=0;
252
volatile uint8_t PCintPort::s_pmask=0;
253
volatile char         PCintPort::s_PORT='x';
254
volatile uint8_t PCintPort::s_changedPins=0;
255
volatile uint8_t PCintPort::s_portRisingPins_nCurr=0;
256
volatile uint8_t PCintPort::s_portFallingPins_nNCurr=0;
257
volatile uint8_t PCintPort::s_currXORlastPinView=0;
258
volatile uint8_t PCintPort::s_count=0;
259
volatile uint8_t PCintPort::pcint_multi=0;
260
volatile uint8_t PCintPort::PCIFRbug=0;
261
#endif
262

    
263
#ifdef FLASH
264
#define PINLED 13
265
volatile uint8_t *led_port;
266
uint8_t led_mask;
267
uint8_t not_led_mask;
268
boolean ledsetup_run=false;
269
void PCintPort::ledsetup(void) {
270
        if (! ledsetup_run) {
271
                led_port=portOutputRegister(digitalPinToPort(PINLED));
272
                led_mask=digitalPinToBitMask(PINLED);
273
                not_led_mask=led_mask^0xFF;
274
                pinMode(PINLED, OUTPUT); digitalWrite(PINLED, LOW);
275
                ledsetup_run=true;
276
        }
277
};
278
#endif
279

    
280

    
281
// ATMEGA 644 
282
//
283
#if defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644__) // Sanguino, Mosquino uino bobino bonanafannafofino, me my momino...
284

    
285
#ifndef NO_PORTA_PINCHANGES
286
PCintPort portA=PCintPort(1, 0,PCMSK0); // port PB==2  (from Arduino.h, Arduino version 1.0)
287
#endif
288
#ifndef NO_PORTB_PINCHANGES
289
PCintPort portB=PCintPort(2, 1,PCMSK1); // port PB==2  (from Arduino.h, Arduino version 1.0)
290
#endif
291
#ifndef NO_PORTC_PINCHANGES
292
PCintPort portC=PCintPort(3, 2,PCMSK2); // port PC==3  (also in pins_arduino.c, Arduino version 022)
293
#endif
294
#ifndef NO_PORTD_PINCHANGES
295
PCintPort portD=PCintPort(4, 3,PCMSK3); // port PD==4
296
#endif
297

    
298
#else // others
299

    
300
#ifndef NO_PORTB_PINCHANGES
301
PCintPort portB=PCintPort(2, 0,PCMSK0); // port PB==2  (from Arduino.h, Arduino version 1.0)
302
#endif
303
#ifndef NO_PORTC_PINCHANGES  // note: no PORTC on MEGA
304
PCintPort portC=PCintPort(3, 1,PCMSK1); // port PC==3  (also in pins_arduino.c, Arduino version 022)
305
#endif
306
#ifndef NO_PORTD_PINCHANGES  // note: no PORTD on MEGA
307
PCintPort portD=PCintPort(4, 2,PCMSK2); // port PD==4
308
#endif
309

    
310
#endif // defined __AVR_ATmega644__
311

    
312
#ifdef __USE_PORT_JK
313
#ifndef NO_PORTJ_PINCHANGES
314
PCintPort portJ=PCintPort(10,1,PCMSK1); // port PJ==10 
315
#endif
316
#ifndef NO_PORTK_PINCHANGES
317
PCintPort portK=PCintPort(11,2,PCMSK2); // port PK==11
318
#endif
319
#endif // USE_PORT_JK
320

    
321
static PCintPort *lookupPortNumToPort( int portNum ) {
322
    PCintPort *port = NULL;
323

    
324
        switch (portNum) {
325
#ifndef NO_PORTA_PINCHANGES
326
        case 1:
327
                port=&portA;
328
                break;
329
#endif
330
#ifndef NO_PORTB_PINCHANGES
331
        case 2:
332
                port=&portB;
333
                break;
334
#endif
335
#ifndef NO_PORTC_PINCHANGES
336
        case 3:
337
                port=&portC;
338
                break;
339
#endif
340
#ifndef NO_PORTD_PINCHANGES
341
        case 4:
342
                port=&portD;
343
                break;
344
#endif
345
#ifdef __USE_PORT_JK
346

    
347
#ifndef NO_PORTJ_PINCHANGES
348
        case 10:
349
                port=&portJ;
350
                break;
351
#endif
352

    
353
#ifndef NO_PORTK_PINCHANGES
354
        case 11:
355
                port=&portK;
356
                break;
357
#endif
358

    
359
#endif
360
    }
361

    
362
    return port;
363
}
364

    
365

    
366
void PCintPort::enable(PCintPin* p, PCIntvoidFuncPtr userFunc, uint8_t mode) {
367
        // Enable the pin for interrupts by adding to the PCMSKx register.
368
        // ...The final steps; at this point the interrupt is enabled on this pin.
369
        p->mode=mode;
370
        p->PCintFunc=userFunc;
371
        portPCMask |= p->mask;
372
        if ((p->mode == RISING) || (p->mode == CHANGE)) portRisingPins |= p->mask;
373
        if ((p->mode == FALLING) || (p->mode == CHANGE)) portFallingPins |= p->mask;
374
        PCICR |= PCICRbit;
375
}
376

    
377
int8_t PCintPort::addPin(uint8_t arduinoPin, PCIntvoidFuncPtr userFunc, uint8_t mode)
378
{
379
        PCintPin* tmp;
380

    
381
        // Add to linked list, starting with firstPin. If pin already exists, just enable.
382
        if (firstPin != NULL) {
383
                tmp=firstPin;
384
                do {
385
                        if (tmp->arduinoPin == arduinoPin) { enable(tmp, userFunc, mode); return(0); }
386
                        if (tmp->next == NULL) break;
387
                        tmp=tmp->next;
388
                } while (true);
389
        }
390

    
391
        // Create pin p:  fill in the data.
392
        PCintPin* p=new PCintPin;
393
        if (p == NULL) return(-1);
394
        p->arduinoPin=arduinoPin;
395
        p->mode = mode;
396
        p->next=NULL;
397
        p->mask = digitalPinToBitMask(arduinoPin); // the mask
398

    
399
        if (firstPin == NULL) firstPin=p;
400
        else tmp->next=p;
401

    
402
#ifdef DEBUG
403
        Serial.print("addPin. pin given: "); Serial.print(arduinoPin, DEC);
404
        int addr = (int) p;
405
        Serial.print(" instance addr: "); Serial.println(addr, HEX);
406
        Serial.print("userFunc addr: "); Serial.println((int)p->PCintFunc, HEX);
407
#endif
408

    
409
        enable(p, userFunc, mode);
410
#ifdef DEBUG
411
        Serial.print("addPin. pin given: "); Serial.print(arduinoPin, DEC), Serial.print (" pin stored: ");
412
        int addr = (int) p;
413
        Serial.print(" instance addr: "); Serial.println(addr, HEX);
414
#endif
415
        return(1);
416
}
417

    
418
/*
419
 * attach an interrupt to a specific pin using pin change interrupts.
420
 */
421
int8_t PCintPort::attachInterrupt(uint8_t arduinoPin, PCIntvoidFuncPtr userFunc, int mode)
422
{
423
        PCintPort *port;
424
        uint8_t portNum = digitalPinToPort(arduinoPin);
425
        if ((portNum == NOT_A_PORT) || (userFunc == NULL)) return(-1);
426

    
427
        port=lookupPortNumToPort(portNum);
428
        // Added by GreyGnome... must set the initial value of lastPinView for it to be correct on the 1st interrupt.
429
        // ...but even then, how do you define "correct"?  Ultimately, the user must specify (not provisioned for yet).
430
        port->lastPinView=port->portInputReg;
431

    
432
#ifdef DEBUG
433
        Serial.print("attachInterrupt FUNC: "); Serial.println(arduinoPin, DEC);
434
#endif
435
        // map pin to PCIR register
436
        return(port->addPin(arduinoPin,userFunc,mode));
437
}
438

    
439
void PCintPort::detachInterrupt(uint8_t arduinoPin)
440
{
441
        PCintPort *port;
442
        PCintPin* current;
443
        uint8_t mask;
444
#ifdef DEBUG
445
        Serial.print("detachInterrupt: "); Serial.println(arduinoPin, DEC);
446
#endif
447
        uint8_t portNum = digitalPinToPort(arduinoPin);
448
        if (portNum == NOT_A_PORT) return;
449
        port=lookupPortNumToPort(portNum);
450
        mask=digitalPinToBitMask(arduinoPin);
451
        current=port->firstPin;
452
        //PCintPin* prev=NULL;
453
        while (current) {
454
                if (current->mask == mask) { // found the target
455
                        uint8_t oldSREG = SREG;
456
                        cli(); // disable interrupts
457
                        port->portPCMask &= ~mask; // disable the mask entry.
458
                        if (port->portPCMask == 0) PCICR &= ~(port->PCICRbit);
459
                        port->portRisingPins &= ~current->mask; port->portFallingPins &= ~current->mask;
460
                        // Link the previous' next to the found next. Then remove the found.
461
                        //if (prev != NULL) prev->next=current->next; // linked list skips over current.
462
                        //else firstPin=current->next; // at the first pin; save the new first pin
463
                        SREG = oldSREG; // Restore register; reenables interrupts
464
                        return;
465
                }
466
                //prev=current;
467
                current=current->next;
468
        }
469
}
470

    
471
// common code for isr handler. "port" is the PCINT number.
472
// there isn't really a good way to back-map ports and masks to pins.
473
void PCintPort::PCint() {
474
        uint8_t thisChangedPin; //MIKE
475

    
476
        #ifdef FLASH
477
        if (*led_port & led_mask) *led_port&=not_led_mask;
478
        else *led_port|=led_mask;
479
    #endif
480
        #ifndef DISABLE_PCINT_MULTI_SERVICE
481
        uint8_t pcifr;
482
        while (true) {
483
        #endif
484
                // get the pin states for the indicated port.
485
                #ifdef PINMODE
486
                PCintPort::s_lastPinView=lastPinView;
487
                intrCount++;
488
                PCintPort::s_count=intrCount;
489
                #endif
490
                // OLD v. 2.01 technique: Test 1: 3163; Test 7: 3993
491
                // From robtillaart online: ------------ (starting v. 2.11beta)
492
                // uint8_t changedPins = PCintPort::curr ^ lastPinView;
493
                // lastPinView = PCintPort::curr;
494
                // uint8_t fastMask = changedPins & ((portRisingPins & PCintPort::curr ) | ( portFallingPins & ~PCintPort::curr ));
495
                // NEW v. 2.11 technique: Test 1: 3270 Test 7: 3987
496
                // -------------------------------------
497
                // was: uint8_t changedPins = PCintPort::curr ^ lastPinView;
498
                // makes test 6 of the PinChangeIntSpeedTest go from 3867 to 3923.  Not good.
499
                uint8_t changedPins = (PCintPort::curr ^ lastPinView) &
500
                                                          ((portRisingPins & PCintPort::curr ) | ( portFallingPins & ~PCintPort::curr ));
501

    
502
                #ifdef PINMODE
503
                PCintPort::s_currXORlastPinView=PCintPort::curr ^ lastPinView;
504
                PCintPort::s_portRisingPins_nCurr=portRisingPins & PCintPort::curr;
505
                PCintPort::s_portFallingPins_nNCurr=portFallingPins & ~PCintPort::curr;
506
                #endif
507
                lastPinView = PCintPort::curr;
508

    
509
                PCintPin* p = firstPin;
510
                while (p) {
511
                        // Trigger interrupt if the bit is high and it's set to trigger on mode RISING or CHANGE
512
                        // Trigger interrupt if the bit is low and it's set to trigger on mode FALLING or CHANGE
513
                        thisChangedPin=p->mask & changedPins; // PinChangeIntSpeedTest makes this 3673... weird.  But GOOD!!!
514
                        if (p->mask & changedPins) {
515
                                #ifndef NO_PIN_STATE
516
                                PCintPort::pinState=PCintPort::curr & p->mask ? HIGH : LOW;
517
                                #endif
518
                                #ifndef NO_PIN_NUMBER
519
                                PCintPort::arduinoPin=p->arduinoPin;
520
                                #endif
521
                                #ifdef PINMODE
522
                                PCintPort::pinmode=p->mode;
523
                                PCintPort::s_portRisingPins=portRisingPins;
524
                                PCintPort::s_portFallingPins=portFallingPins;
525
                                PCintPort::s_pmask=p->mask;
526
                                PCintPort::s_changedPins=changedPins;
527
                                #endif
528
                                p->PCintFunc();
529
                        }
530
                        p=p->next;
531
                }
532
        #ifndef DISABLE_PCINT_MULTI_SERVICE
533
                pcifr = PCIFR & PCICRbit;
534
                if (pcifr == 0) break;
535
                PCIFR |= PCICRbit;
536
                #ifdef PINMODE
537
                PCintPort::pcint_multi++;
538
                if (PCIFR & PCICRbit) PCintPort::PCIFRbug=1; // PCIFR & PCICRbit should ALWAYS be 0 here!
539
                #endif
540
                PCintPort::curr=portInputReg;
541
        }
542
        #endif
543
}
544

    
545
#ifndef NO_PORTA_PINCHANGES
546
ISR(PCINT0_vect) {
547
        #ifdef PINMODE
548
        PCintPort::s_PORT='A';
549
        #endif
550
        PCintPort::curr = portA.portInputReg;
551
        portA.PCint();
552
}
553
#define PORTBVECT PCINT1_vect
554
#define PORTCVECT PCINT2_vect
555
#define PORTDVECT PCINT3_vect
556
#else
557
#define PORTBVECT PCINT0_vect
558
#define PORTCVECT PCINT1_vect
559
#define PORTDVECT PCINT2_vect
560
#endif
561

    
562
#ifndef NO_PORTB_PINCHANGES
563
ISR(PORTBVECT) {
564
        #ifdef PINMODE
565
        PCintPort::s_PORT='B';
566
        #endif
567
        PCintPort::curr = portB.portInputReg;
568
        portB.PCint();
569
}
570
#endif
571

    
572
#ifndef NO_PORTC_PINCHANGES
573
ISR(PORTCVECT) {
574
        #ifdef PINMODE
575
        PCintPort::s_PORT='C';
576
        #endif
577
        PCintPort::curr = portC.portInputReg;
578
        portC.PCint();
579
}
580
#endif
581

    
582
#ifndef NO_PORTD_PINCHANGES
583
ISR(PORTDVECT){ 
584
        #ifdef PINMODE
585
        PCintPort::s_PORT='D';
586
        #endif
587
        PCintPort::curr = portD.portInputReg;
588
        portD.PCint();
589
}
590
#endif
591

    
592
#ifdef __USE_PORT_JK
593
#ifndef NO_PORTJ_PINCHANGES
594
ISR(PCINT1_vect) {
595
        #ifdef PINMODE
596
        PCintPort::s_PORT='J';
597
        #endif
598
        PCintPort::curr = portJ.portInputReg;
599
        portJ.PCint();
600
}
601
#endif
602

    
603
#ifndef NO_PORTK_PINCHANGES
604
ISR(PCINT2_vect){ 
605
        #ifdef PINMODE
606
        PCintPort::s_PORT='K';
607
        #endif
608
        PCintPort::curr = portK.portInputReg;
609
        portK.PCint();
610
}
611
#endif
612

    
613
#endif // __USE_PORT_JK
614

    
615
#ifdef GET_PCINT_VERSION
616
uint16_t getPCIntVersion () {
617
        return ((uint16_t) PCINT_VERSION);
618
}
619
#endif // GET_PCINT_VERSION
620
#endif // #ifndef LIBCALL_PINCHANGEINT *************************************************************
621
#endif // #ifndef PinChangeInt_h *******************************************************************