interrupt routines in a class - attachInterrupt()

Hello, this is my first post to 'programming questions'. I am designing a 'Building Controller' (BC) to be used in my hobby farm out buildings (greenhouse, shop, pole barn, main barn). They will be networked and use a Raspberry Pi (RPI) with a Gertboard (GB). The GB does I/O for RPI and contains an ATmega328p. A major component for the BC is reading and writing X10 control sequences on the power line. The Arduino X10 library is really for demos only, in that it has long delays that waste all the processing power. I am writing a class for X10 Tx/Rx using interrupts and no delays so many other tasks run efficiently. That is the background for my question(s). :)

I use INT0 to detect zero crossings of the power line and OC0A for timing Rx detection and Tx pulse width out.

Question one: Has anyone done a document on how the interrupts are already utilized by C++ functions like I2C, millisec(), etc.? I may have to use other interrupts to avoid interfering. I do not want to interfere with someone also using 'wiring' or other available functions/libraries that use interrupts. It would take a lot of time to make a list of what is in use, so if someone has done that...Great! Or I will have to try to find them all.

Question two: I am having problems implementing 'attachInterrupt(0, myISR, RISING);' in the class constructor. Does that have to do with the fact that I should have one interrupt routine no matter how many times the class is instantiated? BTW, of course this type of class would only be instantiated once.

Question three:: I want to make this package available to the community when I get it working properly, so I want it self contained in one pair of 'X10i.cpp/X10i.h' files. It should be instantiated to run the constructor and then used through the public functions. I could get the interrupts working if I had part of the implementation outside the class, but that is not a good way to give it to others.

Thank you for your time and consideration. Doug

Question two: I am having problems implementing 'attachInterrupt(0, myISR, RISING);' in the class constructor. Does that have to do with the fact that I should have one interrupt routine no matter how many times the class is instantiated? BTW, of course this type of class would only be instantiated once.

What problems in what code? The attachInterrupt() function needs to know what function to call when an interrupt occurs. It has no clue which instance of what class that function belongs to.

You need to define a static method that attachInterrupt() can call when the interrupt occurs. That static method needs to deal with which instance should care that the interrupt occurred. That there is only one instance makes that method's job easier.

Question three isn't a question that I can see.

BTW, of course this type of class would only be instantiated once.

Why make a class then? What about a namespace?

A class with one instance is like a group with one person in it.

A class with one instance is like a group with one person in it.

We use singletons at work quite a bit. A single instance of a class, where you do not need to worry about instancing it more than once CAN be useful.

Other things being equal, I'd prefer to use a singleton rather than static variables and functions in a namespace. There's no particular disadvantage, and it opens up the possibility of extending the capabilities in future (for example: substituting a different implementation class without breaking code that uses it; subclassing the singleton to augment or modify its behaviour; supporting systems where you discover you actually need more than one instance).

In this particular example, though, interrupts are problematic, which they aren't in a namespace. Singleton or not, you need to work around the fact that class members need the "this" pointer, unless you make it consist entirely of static members, which seems to me to be not far away from using a namespace instead.

@OP: You can make glue routines, or static members, to handle interrupts. I seem to recall having an example:

class Foo
{
  static void isr0 ();
  static void isr1 ();
  
  const byte whichISR_;
  static Foo * instance0_;
  static Foo * instance1_;
  
  void handleInterrupt ();
  
  volatile int counter_;
  
  public:
    Foo (const byte which);
    void begin ();
    
};  // end of class Foo

void Foo::begin ()
  {
  switch (whichISR_)
    {
    case 0: 
      attachInterrupt (0, isr0, FALLING); 
      instance0_ = this;
      break;
    
    case 1: 
      attachInterrupt (1, isr1, FALLING); 
      instance1_ = this;
    break;
    }  
  }  // end of Foo::begin 
  
// constructor
Foo::Foo (const byte whichISR) : whichISR_ (whichISR) 
    {
    counter_ = 0;
    }

// ISR glue routines
void Foo::isr0 ()
  {
  instance0_->handleInterrupt ();  
  }  // end of Foo::isr0

void Foo::isr1 ()
  {
  instance1_->handleInterrupt ();  
  }  // end of Foo::isr1
  
// for use by ISR glue routines
Foo * Foo::instance0_;
Foo * Foo::instance1_;

// class instance to handle an interrupt
void Foo::handleInterrupt ()
  {
  counter_++;
    
  }  // end of Foo::handleInterrupt

// instances of class
Foo firstFoo (0);
Foo secondFoo (1);

void setup()
  {
  firstFoo.begin (); 
  secondFoo.begin (); 
  }  // end of setup

void loop() { }

Hello and thanks!

The namespace would do the trick, but I like classes because I am more familiar with them (lazy? :blush:)

I ended up using an indirect approach. I did " XClass * object;", then "attachInterrupt(0, myXISR, RISING);", and a "void myXISR() { object->realISR(); }"

No compile errors, but need to check operation with the debugger (using VM applique on Visual Studio which does some debug capabilities for Arduino).

I would appreciate any comments on this approach.

Doug

That's pretty much what I did above:

// ISR glue routines
void Foo::isr0 ()
  {
  instance0_->handleInterrupt ();  
  }  // end of Foo::isr0

[quote author=Nick Gammon link=topic=160101.msg1199971#msg1199971 date=1365890704] That's pretty much what I did above:

// ISR glue routines
void Foo::isr0 ()
  {
  instance0_->handleInterrupt ();  
  }  // end of Foo::isr0

[/quote]

I agree.

I did this before seeing yours.

Yours is better because it allows more than one instantiation. Mine is less robust and only handles one instantiation.

My class implements X10 communication on the power-lines. No reason to have more than one instantiation.

I think that I learned a bit more about C++ by working it out myself, but when I read yours, I saw even a more sophisticated implementation...Thank you.

Doug