There's a fairly elegant way to have instance-specific ISRs using a table of instance pointers and some template trickery:
// ------------------------------ Define the Number of Interrupts Available for Various Boards ------------------
// Teensy (and maybe others) define these automatically
#if !defined(CORE_NUM_INTERRUPT)
// Arduino Uno
#if defined(__AVR_ATmega328P__)
#define CORE_NUM_INTERRUPT 2
// Arduino Mega
#elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
#define CORE_NUM_INTERRUPT 6
// ESP32
#elif defined(ESP32)
#define CORE_NUM_INTERRUPT 40
#endif
#endif
// ------------------------------ Add More Boards as Necessary ------------------
#if !defined(CORE_NUM_INTERRUPT)
#error CORE_NUM_INTERRUPT Not Defined!!!
#endif
class Motor {
public:
Motor(uint8_t p): pinEncA(p) {};
~Motor() {
if(intAttached) {
detachInterrupt(interruptNum);
}
}
bool begin();
private:
int interruptNum {-1};
bool intAttached {false};
using isrFunct = void (*)();
static Motor *objectTable[CORE_NUM_INTERRUPT];
uint8_t pinEncA;
void cbkEncA ();
template<uint8_t NUM_INTERRUPTS = CORE_NUM_INTERRUPT>
static isrFunct getIsr(uint8_t intNumber);
};
Motor * Motor::objectTable[CORE_NUM_INTERRUPT];
template<uint8_t NUM_INTERRUPTS>
Motor::isrFunct Motor::getIsr(uint8_t intNumber) {
if (intNumber == (NUM_INTERRUPTS - 1)) {
return [] {
(objectTable[NUM_INTERRUPTS - 1])->cbkEncA();
};
}
return getIsr < NUM_INTERRUPTS - 1 > (intNumber);
}
template<>
inline Motor::isrFunct Motor::getIsr<0>(uint8_t intNum) {
(void) intNum;
return nullptr;
}
bool Motor::begin() {
pinMode(pinEncA, INPUT_PULLUP);
intAttached = false;
interruptNum = digitalPinToInterrupt(pinEncA);
if ((interruptNum < 0) || (interruptNum >= CORE_NUM_INTERRUPT)) {
return false;
}
isrFunct isr {getIsr(interruptNum)};
if (isr == nullptr) {
return false;
}
objectTable[interruptNum] = this;
attachInterrupt(interruptNum, isr, RISING);
intAttached = true;
return true;
}
// Instance-specific ISR Here
void Motor::cbkEncA() {
}
Motor motor(3);
void setup() {
Serial.begin(115200);
delay(1000);
if (!motor.begin()) {
Serial.println("Attach Interrupt Failed");
while (1) {}
}
Serial.println("Attached");
}
void loop() {
}