Object Oriented Arduino Interrupts: Using C++ Friend Functions
Most Arduino users won’t ever need interrupts or even C++/OOP for that matter.
But for writing a nice object-oriented library or advancing your programming
skills, both are very interesting subjects. But they clash somewhat: an
interrupt is basically a global function that takes no arguments (not even
this) and returns no value, either. It is not called by the main
program like regular functions, but instead runs when it is triggered by an
external signal, like a pin logic voltage level change. This idea has no place
in an OOP (let alone functional!) world - what object does the function belong
to? It is global and cannot see or modify anything but static data, and the
fact that it does not take arguments makes it impossible to call this function
with method syntax. If this is confusing, don’t worry: in C++, a function knows
which object it belongs to by the implicit, invisible argument
it is still confusing, don’t worry - it doesn’t really matter. It just means
that interrupts and OOP do not mix well.
C++ Friend Functions
A Friend Function is a function that can be at global scope (i.e. not belonging to a class) but still retain private access to all members of a specified class as if it was a member of that class. This class has to declare the function as a friend. Now, this function can be registered as interrupt!
There is one tiny ugly thing that remains: to access private members of a class instance, this instance has to be known by the interrupt. This can be done by having a global pointer to a class instance which is valid for the lifetime of the instance. If you attach your interrupts and set this pointer in your constructor you should be fine. Remember to detach the interrupts and set the pointer to
nullptr in the destructor, if this applies to your program.
Example Code: Simple library to interface an Arduino or Teensy device to an RC Receiver
Here is the code:
For a possibly more up-to-date version: github repo.