FastArduino v1.10
C++ library to build fast but small Arduino/AVR projects
Loading...
Searching...
No Matches
pci.h
Go to the documentation of this file.
1// Copyright 2016-2023 Jean-Francois Poilpret
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
16
25#ifndef PCI_HH
26#define PCI_HH
27
28#include "boards/board.h"
29#include "boards/board_traits.h"
30#include <avr/interrupt.h>
31#include "interrupts.h"
32#include "utilities.h"
33
44#define REGISTER_PCI_ISR_METHOD(PCI_NUM, HANDLER, CALLBACK, PIN, ...) \
45 ISR(CAT3(PCINT, PCI_NUM, _vect)) \
46 { \
47 interrupt::isr_handler_pci::pci_method<PCI_NUM, HANDLER, CALLBACK, PIN, ##__VA_ARGS__>(); \
48 }
49
59#define REGISTER_PCI_ISR_FUNCTION(PCI_NUM, CALLBACK, PIN, ...) \
60 ISR(CAT3(PCINT, PCI_NUM, _vect)) \
61 { \
62 interrupt::isr_handler_pci::pci_function<PCI_NUM, CALLBACK, PIN, ##__VA_ARGS__>(); \
63 }
64
74#define REGISTER_PCI_ISR_EMPTY(PCI_NUM, PIN, ...) \
75 extern "C" void CAT3(PCINT, PCI_NUM, _vect)(void) NAKED_SIGNAL; \
76 void CAT3(PCINT, PCI_NUM, _vect)(void) \
77 { \
78 interrupt::isr_handler_pci::check_pci_pins<PCI_NUM, PIN, ##__VA_ARGS__>(); \
79 __asm__ __volatile__("reti" ::); \
80 }
81
88#define DECL_PCI_ISR_HANDLERS_FRIEND \
89 friend struct interrupt::isr_handler_pci; \
90 DECL_PCINT_ISR_FRIENDS
91
92namespace board
93{
94 template<InterruptPin PCI> constexpr DigitalPin PCI_PIN() INLINE;
98 template<InterruptPin PCI> constexpr DigitalPin PCI_PIN()
99 {
100 return DigitalPin(uint8_t(PCI));
101 }
102};
103
104namespace interrupt
105{
106 // All PCI-related methods called by pre-defined ISR are defined here
107 //====================================================================
108
110 struct isr_handler_pci
111 {
112 template<uint8_t PCI_NUM_, board::InterruptPin PCIPIN_>
113 static constexpr uint8_t get_pci_pin_bit()
114 {
115 constexpr board::DigitalPin PIN = board::PCI_PIN<PCIPIN_>();
116 using PINTRAIT = board_traits::DigitalPin_trait<PIN>;
117 using PORTTRAIT = board_traits::Port_trait<PINTRAIT::PORT>;
118 return bits::BV8(PINTRAIT::BIT) << PORTTRAIT::PCI_SHIFT;
119 }
120
121 template<uint8_t PCI_NUM_> static void check_pci_pins() {}
122
123 template<uint8_t PCI_NUM_, board::InterruptPin PCIPIN1_, board::InterruptPin... PCIPINS_>
124 static void check_pci_pins()
125 {
126 static_assert(board_traits::PCI_trait<PCI_NUM_>::SUPPORTED, "PCI_NUM must support PCI");
127 constexpr board::DigitalPin PIN = board::PCI_PIN<PCIPIN1_>();
128 using PINTRAIT = board_traits::DigitalPin_trait<PIN>;
129 using PORTTRAIT = board_traits::Port_trait<PINTRAIT::PORT>;
130 using PCITRAIT = board_traits::PCI_trait<PCI_NUM_>;
131 static_assert(PORTTRAIT::PCINT == PCI_NUM_, "PIN PORT must use this PCINT");
132 static_assert(PCITRAIT::PCI_MASK & get_pci_pin_bit<PCI_NUM_, PCIPIN1_>(),
133 "PIN must be a PCI within this PCINT");
134 // Check other pins
135 check_pci_pins<PCI_NUM_, PCIPINS_...>();
136 }
137
138 template<uint8_t PCI_NUM_, typename HANDLER_, void (HANDLER_::*CALLBACK_)(), board::InterruptPin... PCIPINS_>
139 static void pci_method()
140 {
141 // Check pin is compliant
142 check_pci_pins<PCI_NUM_, PCIPINS_...>();
143 // Call handler back
144 interrupt::CallbackHandler<void (HANDLER_::*)(), CALLBACK_>::call();
145 }
146
147 template<uint8_t PCI_NUM_, void (*CALLBACK_)(), board::InterruptPin... PCIPINS_> static void pci_function()
148 {
149 // Check pin is compliant
150 check_pci_pins<PCI_NUM_, PCIPINS_...>();
151 // Call handler back
152 CALLBACK_();
153 }
154 };
156
176 template<uint8_t PCINT_> class PCISignal
177 {
178 private:
179 using TRAIT = board_traits::PCI_trait<PCINT_>;
180
181 public:
182 PCISignal(const PCISignal&) = delete;
183 PCISignal& operator=(const PCISignal&) = delete;
184
186 //NOTE this constructor exists only to add a static_assert checked when
187 // PCISignal is constructed not when its template type gets instantiated.
188 PCISignal()
189 {
190 static_assert(TRAIT::SUPPORTED, "PCINT_ must be a valid PCINT number");
191 }
193
195 static constexpr const uint8_t PCINT = PCINT_;
196
211 void enable()
212 {
213 synchronized TRAIT::PCICR_ |= TRAIT::PCICR_MASK;
214 }
215
228 void disable()
229 {
230 synchronized TRAIT::PCICR_ &= bits::COMPL(TRAIT::PCICR_MASK);
231 }
232
243 void clear()
244 {
245 synchronized TRAIT::PCIFR_ |= TRAIT::PCIFR_MASK;
246 }
247
262 void set_enable_pins(uint8_t mask)
263 {
264 synchronized TRAIT::PCMSK_ = mask;
265 }
266
286 void enable_pins(uint8_t mask)
287 {
288 synchronized TRAIT::PCMSK_ |= mask;
289 }
290
310 void disable_pins(uint8_t mask)
311 {
312 synchronized TRAIT::PCMSK_ &= bits::COMPL(mask);
313 }
314
328 template<board::InterruptPin PIN> void enable_pin()
329 {
330 check_pin_pci<PIN>();
331 enable_pins(isr_handler_pci::get_pci_pin_bit<PCINT, PIN>());
332 }
333
346 template<board::InterruptPin PIN> void disable_pin()
347 {
348 check_pin_pci<PIN>();
349 disable_pins(isr_handler_pci::get_pci_pin_bit<PCINT, PIN>());
350 }
351
366 void enable_()
367 {
368 TRAIT::PCICR_ |= TRAIT::PCICR_MASK;
369 }
370
383 void disable_()
384 {
385 TRAIT::PCICR_ &= bits::COMPL(TRAIT::PCICR_MASK);
386 }
387
398 void clear_()
399 {
400 TRAIT::PCIFR_ |= TRAIT::PCIFR_MASK;
401 }
402
417 void set_enable_pins_(uint8_t mask)
418 {
419 TRAIT::PCMSK_ = mask;
420 }
421
441 void enable_pins_(uint8_t mask)
442 {
443 TRAIT::PCMSK_ |= mask;
444 }
445
465 void disable_pins_(uint8_t mask)
466 {
467 TRAIT::PCMSK_ &= bits::COMPL(mask);
468 }
469
483 template<board::InterruptPin PIN> void enable_pin_()
484 {
485 check_pin_pci<PIN>();
486 enable_pins_(isr_handler_pci::get_pci_pin_bit<PCINT, PIN>());
487 }
488
501 template<board::InterruptPin PIN> void disable_pin_()
502 {
503 check_pin_pci<PIN>();
504 disable_pins_(isr_handler_pci::get_pci_pin_bit<PCINT, PIN>());
505 }
506
507 private:
508 template<board::InterruptPin PIN> void check_pin_pci()
509 {
510 isr_handler_pci::check_pci_pins<PCINT, PIN>();
511 }
512 };
513
533 template<board::InterruptPin PIN> struct PCIType
534 {
535 private:
536 using PIN_TRAIT = board_traits::DigitalPin_trait<board::PCI_PIN<PIN>()>;
537 using PORT_TRAIT = board_traits::Port_trait<PIN_TRAIT::PORT>;
538
539 public:
541 static constexpr const uint8_t PCINT = PORT_TRAIT::PCINT;
544 };
545
567 template<board::InterruptPin PIN>
569
573 template<board::Port PORT>
575}
576
577#endif /* PCI_HH */
Handler of a Pin Change Interrupt vector.
Definition: pci.h:177
void enable()
Enable pin change interrupts handled by this PCISignal.
Definition: pci.h:211
void disable_pins(uint8_t mask)
Disable pin change interrupts for several pins of this PCINT.
Definition: pci.h:310
void clear_()
Clear the interrupt flag for this pin change interrupt vector.
Definition: pci.h:398
void enable_pins(uint8_t mask)
Enable pin change interrupts for several pins of this PCINT.
Definition: pci.h:286
void set_enable_pins(uint8_t mask)
Set the exact list of pins, in this PCINT, for which Pin Change Interrupts must be enabled.
Definition: pci.h:262
void enable_pins_(uint8_t mask)
Enable pin change interrupts for several pins of this PCINT.
Definition: pci.h:441
void disable_pin_()
Disable Pin Change Interrupts for PIN.
Definition: pci.h:501
void disable_()
Disable all pin change interrupts for this PCISignal.
Definition: pci.h:383
void enable_()
Enable pin change interrupts for this PCISignal.
Definition: pci.h:366
void disable()
Disable all pin change interrupts handled by this PCISignal.
Definition: pci.h:228
void disable_pin()
Disable Pin Change Interrupts for PIN.
Definition: pci.h:346
void clear()
Clear the interrupt flag for this pin change interrupt vector.
Definition: pci.h:243
void enable_pin()
Enable Pin Change Interrupts for PIN.
Definition: pci.h:328
void enable_pin_()
Enable Pin Change Interrupts for PIN.
Definition: pci.h:483
void set_enable_pins_(uint8_t mask)
Set the exact list of pins, in this PCINT, for which Pin Change Interrupts must be enabled.
Definition: pci.h:417
void disable_pins_(uint8_t mask)
Disable pin change interrupts for several pins of this PCINT.
Definition: pci.h:465
#define INLINE
Specific GCC attribute to force the compiler to always inline code of a given function.
Definition: defines.h:57
General API for handling AVR interrupt vectors.
static constexpr uint8_t COMPL(uint8_t value)
Return the uint8_t 2-complement of a byte.
Definition: bits.h:253
static constexpr uint8_t BV8(uint8_t bit)
Create a uint8_t bitmask for the given bit number.
Definition: bits.h:41
Defines all types and constants specific to support a specific MCU target.
Definition: empty.h:38
DigitalPin
Defines all available digital input/output pins of the target MCU.
Definition: empty.h:56
InterruptPin
Defines all digital output pins of target MCU, usable as pin change interrupt (PCI) pins.
Definition: empty.h:98
constexpr DigitalPin PCI_PIN() INLINE
Convert an InterruptPin to the matching DigitalPin.
Definition: pci.h:98
Defines API to handle AVR interruptions.
Definition: int.h:100
typename PCIType< PIN >::TYPE PCI_SIGNAL
Useful alias type to the PCISignal type matching a given board::InterruptPin.
Definition: pci.h:568
Helper class that easily converts a PIN into the right PCISignal.
Definition: pci.h:534
General utilities API that have broad application in programs.