use attachInterrupt in libraries

does anyone know how to use "attachInterrupt" in the costructor of a class declared in a library? The interrupt service routine YYY is also a method of that library. I have only found dirty methods like this one: call attachInterrupt in the setup() on the main program

attachInterrupt(0, XXX, RISING)

Put a method XXX in the main program who call the method inside the class

void XXX()
{

  • myClass.YYY();*
    }

Thanks!

The attachInterrupt function can be called from anywhere. The method to call must be a static method, though. It can't be called on a specific instance. If the class contains some method of recording a specific instance to be referenced in the callback, you can access that data to get the instance, and then call other instance methods.

thank you very much! Could you post me an example of calling an interrupt in a library please?

Here is an example of something that has worked for me but I hope can be improved. It currently works with either INT0 or INT1 as determined by the pin number passed via the constructor. I would like to also support the 4 additional external interrupts available in the Mega but to do this, I have to replicate the interrupt handler for each potential interrupt source. This seems wasteful - is there a better way?

Thanks,
-Carl

myLib.h:

#ifndef _myLib_h
#define _myLib_h

#include <avr/interrupt.h>
#include <stdint.h>

volatile static uint8_t _irqRcvd0;
volatile static uint8_t _irqRcvd1;

class myLib
{
  public:
    myLib(uint8_t irqPin);
    uint8_t dataAvail();
    void clrIrq();
  private:
    uint8_t _irqPin;
    static void irqHandler0();
    static void irqHandler1();
};
#endif

myLib.cpp

#include <WProgram.h>
#include <myLib.h>

void myLib::irqHandler0() {
  _irqRcvd0 = true;
}

void myLib::irqHandler1() {
  _irqRcvd1 = true;
}

myLib::myLib(uint8_t irqPin)
{
  _irqPin = irqPin;                          // Note: pin 2 = INT0, 3 = INT1
  pinMode(_irqPin, INPUT);
  if (_irqPin == 2) {
    _irqRcvd0 = false;
    attachInterrupt(0, irqHandler0, FALLING);   // Monitor INT0
  } else if (_irqPin == 3) {
    _irqRcvd1 = false;
    attachInterrupt(1, irqHandler1, FALLING);   // Monitor INT1
  }
}

uint8_t myLib::dataAvail() {
  return ((_irqPin == 2 && _irqRcvd0) ||
          (_irqPin == 3 && _irqRcvd1));
}

void myLib::clrIrq() {
  uint8_t sreg;
  sreg = SREG;
  cli();
  if (_irqPin == 2)
    _irqRcvd0 = false;
  else if (_irqPin == 3)
    _irqRcvd1 = false;
  SREG = sreg;
}