28#include "boards/board.h"
29#include "boards/board_traits.h"
30#include <avr/interrupt.h>
44#define REGISTER_PCI_ISR_METHOD(PCI_NUM, HANDLER, CALLBACK, PIN, ...) \
45 ISR(CAT3(PCINT, PCI_NUM, _vect)) \
47 interrupt::isr_handler_pci::pci_method<PCI_NUM, HANDLER, CALLBACK, PIN, ##__VA_ARGS__>(); \
59#define REGISTER_PCI_ISR_FUNCTION(PCI_NUM, CALLBACK, PIN, ...) \
60 ISR(CAT3(PCINT, PCI_NUM, _vect)) \
62 interrupt::isr_handler_pci::pci_function<PCI_NUM, CALLBACK, PIN, ##__VA_ARGS__>(); \
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) \
78 interrupt::isr_handler_pci::check_pci_pins<PCI_NUM, PIN, ##__VA_ARGS__>(); \
79 __asm__ __volatile__("reti" ::); \
88#define DECL_PCI_ISR_HANDLERS_FRIEND \
89 friend struct interrupt::isr_handler_pci; \
90 DECL_PCINT_ISR_FRIENDS
110 struct isr_handler_pci
112 template<u
int8_t PCI_NUM_, board::InterruptPin PCIPIN_>
113 static constexpr uint8_t get_pci_pin_bit()
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;
121 template<u
int8_t PCI_NUM_>
static void check_pci_pins() {}
124 static void check_pci_pins()
126 static_assert(board_traits::PCI_trait<PCI_NUM_>::SUPPORTED,
"PCI_NUM must support PCI");
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");
135 check_pci_pins<PCI_NUM_, PCIPINS_...>();
138 template<uint8_t PCI_NUM_,
typename HANDLER_, void (HANDLER_::*CALLBACK_)(),
board::InterruptPin... PCIPINS_>
139 static void pci_method()
142 check_pci_pins<PCI_NUM_, PCIPINS_...>();
144 interrupt::CallbackHandler<void (HANDLER_::*)(), CALLBACK_>::call();
147 template<uint8_t PCI_NUM_, void (*CALLBACK_)(),
board::InterruptPin... PCIPINS_>
static void pci_function()
150 check_pci_pins<PCI_NUM_, PCIPINS_...>();
179 using TRAIT = board_traits::PCI_trait<PCINT_>;
190 static_assert(TRAIT::SUPPORTED,
"PCINT_ must be a valid PCINT number");
195 static constexpr const uint8_t PCINT = PCINT_;
213 synchronized TRAIT::PCICR_ |= TRAIT::PCICR_MASK;
230 synchronized TRAIT::PCICR_ &=
bits::COMPL(TRAIT::PCICR_MASK);
245 synchronized TRAIT::PCIFR_ |= TRAIT::PCIFR_MASK;
264 synchronized TRAIT::PCMSK_ = mask;
288 synchronized TRAIT::PCMSK_ |= mask;
330 check_pin_pci<PIN>();
331 enable_pins(isr_handler_pci::get_pci_pin_bit<PCINT, PIN>());
348 check_pin_pci<PIN>();
349 disable_pins(isr_handler_pci::get_pci_pin_bit<PCINT, PIN>());
368 TRAIT::PCICR_ |= TRAIT::PCICR_MASK;
400 TRAIT::PCIFR_ |= TRAIT::PCIFR_MASK;
419 TRAIT::PCMSK_ = mask;
443 TRAIT::PCMSK_ |= mask;
485 check_pin_pci<PIN>();
486 enable_pins_(isr_handler_pci::get_pci_pin_bit<PCINT, PIN>());
503 check_pin_pci<PIN>();
504 disable_pins_(isr_handler_pci::get_pci_pin_bit<PCINT, PIN>());
508 template<board::InterruptPin PIN>
void check_pin_pci()
510 isr_handler_pci::check_pci_pins<PCINT, PIN>();
533 template<board::InterruptPin PIN>
struct PCIType
536 using PIN_TRAIT = board_traits::DigitalPin_trait<board::PCI_PIN<PIN>()>;
537 using PORT_TRAIT = board_traits::Port_trait<PIN_TRAIT::PORT>;
541 static constexpr const uint8_t PCINT = PORT_TRAIT::PCINT;
567 template<board::InterruptPin PIN>
573 template<board::Port PORT>
Handler of a Pin Change Interrupt vector.
void enable()
Enable pin change interrupts handled by this PCISignal.
void disable_pins(uint8_t mask)
Disable pin change interrupts for several pins of this PCINT.
void clear_()
Clear the interrupt flag for this pin change interrupt vector.
void enable_pins(uint8_t mask)
Enable pin change interrupts for several pins of this PCINT.
void set_enable_pins(uint8_t mask)
Set the exact list of pins, in this PCINT, for which Pin Change Interrupts must be enabled.
void enable_pins_(uint8_t mask)
Enable pin change interrupts for several pins of this PCINT.
void disable_pin_()
Disable Pin Change Interrupts for PIN.
void disable_()
Disable all pin change interrupts for this PCISignal.
void enable_()
Enable pin change interrupts for this PCISignal.
void disable()
Disable all pin change interrupts handled by this PCISignal.
void disable_pin()
Disable Pin Change Interrupts for PIN.
void clear()
Clear the interrupt flag for this pin change interrupt vector.
void enable_pin()
Enable Pin Change Interrupts for PIN.
void enable_pin_()
Enable Pin Change Interrupts for PIN.
void set_enable_pins_(uint8_t mask)
Set the exact list of pins, in this PCINT, for which Pin Change Interrupts must be enabled.
void disable_pins_(uint8_t mask)
Disable pin change interrupts for several pins of this PCINT.
#define INLINE
Specific GCC attribute to force the compiler to always inline code of a given function.
General API for handling AVR interrupt vectors.
static constexpr uint8_t COMPL(uint8_t value)
Return the uint8_t 2-complement of a byte.
static constexpr uint8_t BV8(uint8_t bit)
Create a uint8_t bitmask for the given bit number.
Defines all types and constants specific to support a specific MCU target.
DigitalPin
Defines all available digital input/output pins of the target MCU.
InterruptPin
Defines all digital output pins of target MCU, usable as pin change interrupt (PCI) pins.
constexpr DigitalPin PCI_PIN() INLINE
Convert an InterruptPin to the matching DigitalPin.
Defines API to handle AVR interruptions.
typename PCIType< PIN >::TYPE PCI_SIGNAL
Useful alias type to the PCISignal type matching a given board::InterruptPin.
Helper class that easily converts a PIN into the right PCISignal.
General utilities API that have broad application in programs.