How to pass a function name into a library

Hi Guys,
i am working into a small project (library) that will configure the interrupt to call a function at every X millisecond that you want.

i got the librarie working, the class, the include part all going well.
BUT...:wink:
i got jam in the part that i need to send the function name to the interrupt routine.
right now the call is TimeCall.go(millisecond); and i would like it to be TimeCall.go(function, millisecond) and to get the ISR to call that function.

Right now i do a digital write (toggle) as a proof of concept but this is where i would like to insert the function call that TimeCall.go would have send.

Does anyone could pin point how to do that?
Thanks in advance.

Here is all my working code

#include <TimeCall.h>

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

TimeCall montime;


void setup() {
  montime.go(100); // This will make a interrupt a every 100ms
}

void loop() {
}
/*
TimeCall.h - Library for calling a function at an interval time interrupt
Created by Patgadget, October 2, 2010
Released into the public domain
*/

#ifndef TimeCall_h
#define TimeCall_h

#include "WProgram.h"

class TimeCall
{
  public:
      void go(uint16_t millisecond );
  private:
    int _variable;
};

#endif
/*
  TimeCall.cpp - Library for calling a function at an interval time interrupt
  Created by Patgadget, October 2, 2010
  Released into the public domain
*/

#include "WProgram.h"
#include <TimeCall.h>

volatile int32_t int_counter;
volatile uint16_t internal_millisecond;


void TimeCall::go(uint16_t millisecond)
{
  internal_millisecond = millisecond;
  //Timer2 Settings: Timer Prescaler /64,
  TCCR2B = 0;
  TCCR2A = 0;
  TCCR2B |= (1<<CS22);
  TCCR2B &= ~(1<<CS21);
  TCCR2B &= ~(1<<CS20);
  // Use normal mode
  TCCR2A &= ~((1<<WGM21) | (1<<WGM20));
  TCCR2B &= ~(1<<WGM22);
  // Use internal clock - external clock not used in Arduino
  ASSR |= (0<<AS2);
   //Timer2 Overflow Interrupt Enable
  TIMSK2 |= (1<<TOIE2);
  TIMSK2 &= ~((1<<OCIE2B) | (1<<OCIE2B));
  TCNT2 = 6;
}
  
ISR(TIMER2_OVF_vect) {
  TCNT2 = 6;
  int_counter += 1;
  if (int_counter == internal_millisecond) {
    int_counter = 0;
    digitalWrite(13,1-digitalRead(13));  // THIS IS WHAT i want to replace with a function call
  }
}

Sounds like you need a "pointer to a function". I prefer typedefs...

typedef void (*TCallThisEvery)( void );

void MyCallback( void )
{
}

void setup() {
  montime.go(100, MyCallback); // This will make a interrupt a every 100ms
}

class TimeCall
{
  public:
    void go(uint16_t millisecond, TCallThisEvery callthis );
  private:
    TCallThisEvery _callthis;

void TimeCall::go(uint16_t millisecond, TCallThisEvery callthis)
{
  _callthis = callthis;  // This must be done before the ISR could be called

ISR(TIMER2_OVF_vect) {
    digitalWrite(13,1-digitalRead(13));  // THIS IS WHAT i want to replace with a function call
    _callthis();

Thanks a lot Coding Badly,
Almost work like a charm,
got a small last question,

This compile:

void TimeCall::go(uint16_t millisecond, TCallThisEvery callthis)
{
 _callthis = callthis;  // This must be done before the ISR could be called

But this does not?

ISR(TIMER2_OVF_vect) {
   digitalWrite(13,1-digitalRead(13));  // THIS IS WHAT i want to replace with a function call
   _callthis();

the _callthis is not reconize in the ISR, could it be becose the ISR is not part of the TimeCall class?
i figure a way around it by defining a global variable in the .cpp file,
is that ok?
Thanks for your help.
Patgadget

You have an instance of the TimeCall class, right? The _callback member is a field in that class. So, you need to call the function using myTimeClassInstance._callback() (assuming that _callback is public. If not, you'll need to add a method to return the pointer to the function (_callback)).

Well i did not get this to well PaulS, i am more of a Hardware guy than software,
so this is was is working now:

#include <TimeCall.h>

TimeCall timecall;

void setup() {
  timecall.go(toogle, 15);
}

void loop() {
}
 
void toogle()
{
  digitalWrite(13,(1-digitalRead(13)));
}
/*
TimeCall.h - Library for calling a function at an interval time interrupt
Created by Patgadget, October 2, 2010
Released into the public domain
*/

#ifndef TimeCall_h
#define TimeCall_h

#include "WProgram.h"
typedef void (*TCallThisEvery)( void );

class TimeCall
{
  public:
      void go(TCallThisEvery callthis,uint16_t millisecond );
};

#endif
/*
  TimeCall.cpp - Library for calling a function at an interval time interrupt
  Created by Patgadget, October 2, 2010
  Released into the public domain
*/

#include "WProgram.h"
#include <TimeCall.h>

volatile int32_t int_counter;
volatile uint16_t internal_millisecond;
volatile TCallThisEvery _callthis;


void TimeCall::go(TCallThisEvery callthis,uint16_t millisecond)
{
  _callthis = callthis;
  internal_millisecond = millisecond;
  //Timer2 Settings: Timer Prescaler /64,
  TCCR2B = 0;
  TCCR2A = 0;
  TCCR2B |= (1<<CS22);
  TCCR2B &= ~(1<<CS21);
  TCCR2B &= ~(1<<CS20);
  // Use normal mode
  TCCR2A &= ~((1<<WGM21) | (1<<WGM20));
  TCCR2B &= ~(1<<WGM22);
  // Use internal clock - external clock not used in Arduino
  ASSR |= (0<<AS2);
   //Timer2 Overflow Interrupt Enable
  TIMSK2 |= (1<<TOIE2);
  TIMSK2 &= ~((1<<OCIE2B) | (1<<OCIE2B));
  TCNT2 = 6;
}
  
ISR(TIMER2_OVF_vect) {
  TCNT2 = 6;
  int_counter += 1;
  if (int_counter == internal_millisecond) {
    int_counter = 0;
      _callthis();
  }
}

And this is what is not working!

#include <TimeCall.h>

TimeCall timecall;

void setup() {
  timecall.go(toogle, 15);
}

void loop() {
}
 
void toogle()
{
  digitalWrite(13,(1-digitalRead(13)));
}
/*
TimeCall.h - Library for calling a function at an interval time interrupt
Created by Patgadget, October 2, 2010
Released into the public domain
*/

#ifndef TimeCall_h
#define TimeCall_h

#include "WProgram.h"
typedef void (*TCallThisEvery)( void );

class TimeCall
{
  public:
      void go(TCallThisEvery callthis,uint16_t millisecond );
  private:
    TCallThisEvery _callthis; // NOTE THE PRIVATE DECLARATION HERE <<<<<<<<
};

#endif
/*
  TimeCall.cpp - Library for calling a function at an interval time interrupt
  Created by Patgadget, October 2, 2010
  Released into the public domain
*/

#include "WProgram.h"
#include <TimeCall.h>

volatile int32_t int_counter;
volatile uint16_t internal_millisecond;
//volatile TCallThisEvery _callthis;     // NO MORE DECLARATION HERE <<<<<<


void TimeCall::go(TCallThisEvery callthis,uint16_t millisecond)
{
  _callthis = callthis;
  internal_millisecond = millisecond;
  //Timer2 Settings: Timer Prescaler /64,
  TCCR2B = 0;
  TCCR2A = 0;
  TCCR2B |= (1<<CS22);
  TCCR2B &= ~(1<<CS21);
  TCCR2B &= ~(1<<CS20);
  // Use normal mode
  TCCR2A &= ~((1<<WGM21) | (1<<WGM20));
  TCCR2B &= ~(1<<WGM22);
  // Use internal clock - external clock not used in Arduino
  ASSR |= (0<<AS2);
   //Timer2 Overflow Interrupt Enable
  TIMSK2 |= (1<<TOIE2);
  TIMSK2 &= ~((1<<OCIE2B) | (1<<OCIE2B));
  TCNT2 = 6;
}
  
ISR(TIMER2_OVF_vect) {
  TCNT2 = 6;
  int_counter += 1;
  if (int_counter == internal_millisecond) {
    int_counter = 0;
      _callthis();
  }
}

Could you explain what should be add?
Thanks
Patgadget

But this does not?

Yikes! Sorry about that.

the _callthis is not reconize in the ISR, could it be becose the ISR is not part of the TimeCall class?

Exactly.

i figure a way around it by defining a global variable in the .cpp file, is that ok?

Yes.

PaulS's suggestion will work as well.

Could you explain what should be add?

Do you want the full explanation (e.g. why my code didn't compile and what choices are available) or do you want the short, just-get-it-working version?

Well,
the short one if it is ok like that i will keep it working that way

Thanks a lot for all your help

Patgadget

BTW you could use this librairie now as it is working (the top one) :wink:

the short one if it is ok

Private instance data (like _callthis) is only accessible in a method call of the class where the data is declared.

How's that for short? :smiley: