DCAITI Robot Hardware  1.0
PinChangeInt.h
Go to the documentation of this file.
1 /*
2  PinChangeInt.h
3 */
4 
5 
6 #ifndef PinChangeInt_h
7 #define PinChangeInt_h
8 
9 #if defined(ARDUINO) && ARDUINO >= 100
10 #include "Arduino.h"
11 #else
12 #include "WProgram.h"
13 #endif
14 
15 #include "PinChangeIntConfig.h"
16 #ifndef Pins_Arduino_h
17 #include "pins_arduino.h"
18 #endif
19 // This library was inspired by and derived from "johnboiles" (it seems) Main.PCInt Arduino Playground example
20 // see: http://www.arduino.cc/playground/Main/PcInt
21 
22 
23 // Interrupt management for PCI
24 /*
25  * an extension to the interrupt support for arduino.
26  * add pin change interrupts to the external interrupts, giving a way
27  * for users to have interrupts drive off of any pin.
28  * Refer to avr-gcc header files, arduino source and atmega datasheet.
29  */
30 
31 /*
32  * Theory: all IO pins on AtmegaX(168/328/1280/2560) are covered by Pin Change Interrupts.
33  * The PCINT corresponding to the pin must be enabled and masked, and
34  * an ISR routine provided. Since PCINTs are per port, not per pin, the ISR
35  * must use some logic to actually implement a per-pin interrupt service.
36  */
37 
38 /* Pin to interrupt map ON ATmega168/328:
39  * D0-D7 = PCINT 16-23 = PCIR2 = PD = PCIE2 = pcmsk2
40  * D8-D13 = PCINT 0-5 = PCIR0 = PB = PCIE0 = pcmsk0
41  * A0-A5 (D14-D19) = PCINT 8-13 = PCIR1 = PC = PCIE1 = pcmsk1
42  */
43 
44 
45 /* Pin to interrupt map ON ATmega1280/2560:
46  * D50-D53 = PCINT 3-0 = PCIR0 = PB = PCIE0 = pcmsk0
47  * D10-D13 = PCINT 4-7 = PCIR0 = PB = PCIE0 = pcmsk0
48  * A8-A15 (D62-D69) = PCINT 16-23 = PCIR2 = Pk = PCIE2 = pcmsk2
49 
50  * *******D0 = PCINT 8 = PCIR1 = PE = PCIE1 = pcmsk1**********
51  * *******D14-D15 = PCINT 10-9 = PJ = PCIE1 = pcmsk1*********
52  ********NOTE:PCINT 8-15 does NOT available in this library******
53  */
54 
55 
56 /*
57  Please make any configuration changes in the accompanying PinChangeIntConfig.h file.
58  This will help avoid having to reset your config in the event of changes to the
59  library code (just don't replace that file when you update).
60 
61 */
62 
63 
64 #ifndef MAX_PIN_CHANGE_PINS
65 #define MAX_PIN_CHANGE_PINS 8
66 #endif
67 
68 // You can reduce the memory footprint of this handler by declaring that there will be no pin change interrupts
69 // on any of the three ports.
70 // define NO_PORTB_PINCHANGES to indicate that port b will not be used for pin change interrupts
71 // define NO_PORTC_PINCHANGES to indicate that port c will not be used for pin change interrupts
72 // define NO_PORTD_PINCHANGES to indicate that port d will not be used for pin change interrupts
73 // If only a single port remains, the handler will be declared inline reducing the size and latency
74 // of the handler.
75 
76 // if their is only one PCInt vector in use the code can be inlined
77 // reducing latecncy and code size
78 #define INLINE_PCINT
79 #if ((defined(NO_PORTB_PINCHANGES) && defined(NO_PORTC_PINCHANGES)) || \
80  (defined(NO_PORTC_PINCHANGES) && defined(NO_PORTD_PINCHANGES)) || \
81  (defined(NO_PORTD_PINCHANGES) && defined(NO_PORTB_PINCHANGES)))
82 #undef INLINE_PCINT
83 #define INLINE_PCINT inline
84 #endif
85 
86 // Provide drop in compatibility with johnboiles PCInt project at
87 // http://www.arduino.cc/playground/Main/PcInt
88 #define PCdetachInterrupt(pin) PCintPort::detachInterrupt(pin)
89 #define PCattachInterrupt(pin,userFunc,mode) PCintPort::attachInterrupt(pin, userFunc,mode)
90 
91 
92 
93 typedef void (*PCIntvoidFuncPtr)(void);
94 
95 class PCintPort {
96  PCintPort(int index,volatile uint8_t& maskReg) :
97  #if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
98  portInputReg(*portInputRegister((index == 0)?(2):(index + 9))),
99 
100  #else
101  portInputReg(*portInputRegister(index + 2)),
102  #endif
103 
104  pcmask(maskReg),
105  PCICRbit(1 << index),
106  PCintLast(0) {
107  for (int i = 0; i < 9; i++) {
108  pcIntPins[i] = NULL;
109  }
110  }
111 public:
112  static void attachInterrupt(uint8_t pin, PCIntvoidFuncPtr userFunc, int mode);
113  static void detachInterrupt(uint8_t pin);
114  INLINE_PCINT void PCint();
116 
117 protected:
118  class PCintPin {
119  public:
122  PCintMode(0) {}
124  uint8_t PCintMode;
125  uint8_t PCIntMask;
127  };
128  void addPin(uint8_t mode,uint8_t mask,PCIntvoidFuncPtr userFunc);
129  void delPin(uint8_t mask);
130  volatile uint8_t& portInputReg;
131  volatile uint8_t& pcmask;
132  const uint8_t PCICRbit;
133  uint8_t PCintLast;
134  PCintPin* pcIntPins[9]; // extra entry is a barrier
135 };
136 #endif
void(* PCIntvoidFuncPtr)(void)
Definition: PinChangeInt.h:93
#define MAX_PIN_CHANGE_PINS
Definition: PinChangeInt.h:65
#define INLINE_PCINT
Definition: PinChangeInt.h:78
Definition: PinChangeInt.h:118
PCintPin()
Definition: PinChangeInt.h:120
PCIntvoidFuncPtr PCintFunc
Definition: PinChangeInt.h:123
static PCintPin pinDataAlloc[MAX_PIN_CHANGE_PINS]
Definition: PinChangeInt.h:126
uint8_t PCintMode
Definition: PinChangeInt.h:124
uint8_t PCIntMask
Definition: PinChangeInt.h:125
Definition: PinChangeInt.h:95
PCintPin * pcIntPins[9]
Definition: PinChangeInt.h:134
INLINE_PCINT void PCint()
Definition: PinChangeInt.cpp:139
void addPin(uint8_t mode, uint8_t mask, PCIntvoidFuncPtr userFunc)
Definition: PinChangeInt.cpp:17
static void detachInterrupt(uint8_t pin)
Definition: PinChangeInt.cpp:115
static void attachInterrupt(uint8_t pin, PCIntvoidFuncPtr userFunc, int mode)
Definition: PinChangeInt.cpp:81
uint8_t PCintLast
Definition: PinChangeInt.h:133
static PCintPort pcIntPorts[]
Definition: PinChangeInt.h:115
volatile uint8_t & portInputReg
Definition: PinChangeInt.h:130
const uint8_t PCICRbit
Definition: PinChangeInt.h:132
volatile uint8_t & pcmask
Definition: PinChangeInt.h:131
void delPin(uint8_t mask)
Definition: PinChangeInt.cpp:51