COSA
An Object-Oriented Platform for Arduino Programming
PinChangeInterrupt.cpp
Go to the documentation of this file.
1 
22 
23 // Define symbols for enable/disable pin change interrupts
24 #if defined(GIMSK)
25 #define PCICR GIMSK
26 #endif
27 #if !defined(PCIE0)
28 #define PCIE0 PCIE
29 #endif
30 #if defined(PCIE3)
31 #define PCIEN (_BV(PCIE3) | _BV(PCIE2) | _BV(PCIE1) | _BV(PCIE0))
32 #elif defined(PCIE2)
33 #define PCIEN (_BV(PCIE2) | _BV(PCIE1) | _BV(PCIE0))
34 #elif defined(PCIE1)
35 #define PCIEN (_BV(PCIE1) | _BV(PCIE0))
36 #elif defined(PCIE0)
37 #define PCIEN (_BV(PCIE0))
38 #endif
39 
40 PinChangeInterrupt* PinChangeInterrupt::s_pin[Board::PCMSK_MAX] = { NULL };
41 uint8_t PinChangeInterrupt::s_state[Board::PCMSK_MAX] = { 0 };
42 
43 void
45 {
46  // Enable in pin change mask register and add to list of handlers
47  synchronized {
48  *PCIMR() |= m_mask;
49  if (m_next == NULL) {
50  uint8_t ix = PCIMR() - &PCMSK0;
51  if (ix >= Board::PCMSK_MAX) ix = Board::PCMSK_MAX - 1;
52  m_next = s_pin[ix];
53  s_pin[ix] = this;
54  }
55  }
56 }
57 
58 void
60 {
61  synchronized *PCIMR() &= ~m_mask;
62 }
63 
64 void
66 {
67  // Initiate the pin state vector
68 #if defined(BOARD_ATTINYX61)
69  s_state[0] = PINA;
70  s_state[1] = PINB;
71 #elif defined(BOARD_ATTINYX5)
72  s_state[0] = PINB;
73 #elif defined(BOARD_ATTINYX4)
74  s_state[0] = PINA;
75  s_state[1] = PINB;
76 #elif defined(BOARD_ATMEGA328P)
77  s_state[0] = PINB;
78  s_state[1] = PINC;
79  s_state[2] = PIND;
80 #elif defined(BOARD_ATMEGA32U4)
81  s_state[0] = PINB;
82 #elif defined(BOARD_AT90USB1286)
83  s_state[0] = PINB;
84 #elif defined(BOARD_ATMEGA2560)
85  s_state[0] = PINB;
86  s_state[1] = PINJ;
87  s_state[2] = PINK;
88 #elif defined(BOARD_ATMEGA1248P)
89  s_state[0] = PINA;
90  s_state[1] = PINB;
91  s_state[2] = PINC;
92  s_state[3] = PIND;
93 #elif defined(BOARD_ATMEGA256RFR2)
94  s_state[0] = PINB;
95  s_state[1] = PINE;
96 #endif
97 
98  // Enable the pin change interrupt(s)
99  synchronized bit_mask_set(PCICR, PCIEN);
100 }
101 
102 void
104 {
105  // Disable the pin change interrupt(s)
106  synchronized bit_mask_clear(PCICR, PCIEN);
107 }
108 
109 void
110 PinChangeInterrupt::on_interrupt(uint8_t vec, uint8_t mask, uint8_t port)
111 {
112  uint8_t old_state = s_state[vec];
113  uint8_t new_state = port;
114  uint8_t changed = (new_state ^ old_state) & mask;
115 
116  // Find the interrupt handler for the changed value and check mode
117  for (PinChangeInterrupt* pin = s_pin[vec]; pin != NULL; pin = pin->m_next)
118  if ((pin->m_mask & changed)
119  && ((pin->m_mode == ON_CHANGE_MODE)
120  || pin->m_mode == ((pin->m_mask & new_state) == 0)))
121  pin->on_interrupt();
122 
123  // Save the new pin state
124  s_state[vec] = new_state;
125 }
126 
127 #define PCINT_ISR(vec,pin) \
128 ISR(PCINT ## vec ## _vect) \
129 { \
130  PinChangeInterrupt::on_interrupt(vec, PCMSK ## vec, pin); \
131 }
132 
133 #if defined(BOARD_ATTINYX61)
134 
136 {
137  if (GIFR & _BV(INTF0)) {
139  } else {
140  PinChangeInterrupt::on_interrupt(1, PCMSK1, PINB);
141  }
142 }
143 
144 #elif defined(BOARD_ATTINYX5)
145 
146 PCINT_ISR(0, PINB);
147 
148 #elif defined(BOARD_ATTINYX4)
149 
150 PCINT_ISR(0, PINA);
151 PCINT_ISR(1, PINB);
152 
153 #elif defined(BOARD_ATMEGA328P)
154 
155 PCINT_ISR(0, PINB);
156 PCINT_ISR(1, PINC);
157 PCINT_ISR(2, PIND);
158 
159 #elif defined(BOARD_ATMEGA32U4)
160 
161 PCINT_ISR(0, PINB);
162 
163 #elif defined(BOARD_AT90USB1286)
164 
165 PCINT_ISR(0, PINB);
166 
167 #elif defined(BOARD_ATMEGA2560)
168 
169 PCINT_ISR(0, PINB);
170 PCINT_ISR(1, PINJ);
171 PCINT_ISR(2, PINK);
172 
173 #elif defined(BOARD_ATMEGA1248P)
174 
175 PCINT_ISR(0, PINA);
176 PCINT_ISR(1, PINB);
177 PCINT_ISR(2, PINC);
178 PCINT_ISR(3, PIND);
179 
180 #elif defined(BOARD_ATMEGA256RFR2)
181 
182 PCINT_ISR(0, PINB);
183 PCINT_ISR(1, PINE);
184 
185 #endif
#define PCINT_ISR(vec, pin)
#define bit_mask_clear(p, m)
Definition: Bits.h:30
uint8_t pin() const
Definition: Pin.hh:103
#define NULL
Definition: Types.h:101
ISR(ANALOG_COMP_vect)
#define PCMSK0
Definition: ATtinyX5.hh:227
friend void PCINT0_vect(void)
#define PCIEN
#define bit_mask_set(p, m)
Definition: Bits.h:29
virtual void on_interrupt(uint16_t arg=0)=0
const uint8_t m_mask
Definition: Pin.hh:227
volatile uint8_t * PCIMR() const
Definition: Pin.hh:263