Questions about FspTimer.h

Hi all , after spending every spare moment over the last few weeks reading the forum and googling , I keep going around in circles getting no where. So I have joined the forum in the hope that I can get help .
I am not a total newbie to programming or Arduinos but I am still very unfamiliar .I managed to get Timers working on R3 using direct timer registers and that all made sense to me but this R4 is a whole new ball game .

My intention is to make a phase controller .I have a zero crossing detector that I is working and triggers an interrupt every mains half-cycle crossing . I then wanted to get it to set a timer in one-shot which would trigger another interrupt to set an output pin that will drive the optocoupled TRIAC.( That bit is easy as I've been doing electronics for 40 odd years .) The period of the one-shot is adjustable up to 10mS and sets the phase angle .LOL , all this could be done with some simple electronics , but where's the fun in that .

This is where I have come unstuck .The Timer one library does not seem to work on the R4 and all other topics are referring to FspTimer.h which looks like an absolute nightmare to use .I have looked at the few Topics on here about it . Seen the "under hood" example by Phil shatsman , looked at the posts by gjacobs101 , KurtE and others . a lot of them seem to be about using Timer to generate Periodic rather than one-shots .

Regardless , I have tried copy and paste of their code just to get a starting point but that is where I have discovered that FspTimer.h is not part of the R4 built in library . Nor can I find it in the extensive Library list in my latest version IDE 2.3.5

It has taken me all this time to realize that FspTimer seems to be have written by Reneasas but there is another version FspTimer.h for Arduino . I see references on google to get it from Guthub .I have tried countless times and can't figure it out .Please correct me about any of this.

Sorry about the long winded intro ,I was just trying to give you an understanding of my level of ability and what I had done so far .
I feel I am missing the bleeding obvious . Or if there is another Library that is available that would easily create a one-shot time ,I'm all ears .
Thanks in advance .

It's been about a year since I last played around with FspTimer, so my memory is a bit hazy, but I can give you some hints.

The begin method of FspTimer is defined as follows.

or

The definition of the first argument, timer_mode_t mode, is as follows:

So you can specify TIMER_MODE_ONE_SHOT as mode. And AGT_TIMER (16bit) or GPT_TIMER (32bit) can be specified at tp.

I need some more time to remember how to use it more specifically. :sweat_smile:

Thankyou Embedded kiddie for the reply .That link seems to have some good explainations on it .

I noticed you linked to FspTimer.cc .
What is the difference between that and FspTimer.h ?

Incidentally , I did manage to get copied code to compile . I had forgotten to specify R4 board after reinstalling IDE and it does indeed seem that FspTimer.h is included in it . :flushed_face:

Do the FspTimer.cc codes work on FspTimer.h ?

I appreciate any help when you can .

It took me a while to remember how to use FspTimer :grin:

#include <Arduino.h>
#include <FspTimer.h>
#include <math.h> // for round()

FspTimer fsp_timer;
volatile uint32_t lap_time;
volatile bool irq_fired = false;

static void IrqCallback(timer_callback_args_t* p_args) {
  lap_time = millis() - lap_time;
  irq_fired = true;
}

void setup() {
  Serial.begin(115200);
  while (!Serial);

  pinMode(LED_BUILTIN, OUTPUT);

  // Get available timer from from the timer pool (GPT32 x 2, GPT16 x 6 and AGT x 2).
  // Note: Two of the GPT32 timers are already in use, so we can only get 16-bit timers.
  uint8_t type = -1;
  int channel = FspTimer::get_available_timer(type); // Get GPT_TIMER as a priority
  if (channel == -1) {
    Serial.println("Cannot get timer.");
    return;
  }

#if   0

  // Generate an interrupt after 10 milliseconds.
  fsp_timer.begin(TIMER_MODE_ONE_SHOT, type, channel, 100.0 /* Hz */, 50.0 /* % */, IrqCallback, nullptr);

#else

  // Get frequency of acquired timer.
  uint32_t freq_hz;
  if (type == GPT_TIMER) {
    freq_hz = R_FSP_SystemClockHzGet(FSP_PRIV_CLOCK_PCLKD);
    Serial.println("GPT_TIMER channel " + String(channel) + " : " + String(freq_hz) + " Hz");
  } else {
    freq_hz = R_FSP_SystemClockHzGet(FSP_PRIV_CLOCK_PCLKB);
    Serial.println("AGT_TIMER channel " + String(channel) + " : " + String(freq_hz) + " Hz");
  }

  /* PCLK divisors
    https://github.com/arduino/ArduinoCore-renesas/blob/main/variants/MINIMA/includes/ra/fsp/inc/api/r_timer_api.h#L130-L144
  typedef enum e_timer_source_div
  {
      TIMER_SOURCE_DIV_1    = 0,         ///< Timer clock source divided by 1
      TIMER_SOURCE_DIV_2    = 1,         ///< Timer clock source divided by 2
      TIMER_SOURCE_DIV_4    = 2,         ///< Timer clock source divided by 4
      TIMER_SOURCE_DIV_8    = 3,         ///< Timer clock source divided by 8
      TIMER_SOURCE_DIV_16   = 4,         ///< Timer clock source divided by 16
      TIMER_SOURCE_DIV_32   = 5,         ///< Timer clock source divided by 32
      TIMER_SOURCE_DIV_64   = 6,         ///< Timer clock source divided by 64
      TIMER_SOURCE_DIV_128  = 7,         ///< Timer clock source divided by 128
      TIMER_SOURCE_DIV_256  = 8,         ///< Timer clock source divided by 256
      TIMER_SOURCE_DIV_512  = 9,         ///< Timer clock source divided by 512
      TIMER_SOURCE_DIV_1024 = 10,        ///< Timer clock source divided by 1024
  } timer_source_div_t;
  */
  // Calculate the number of counts for 10 ms
  uint32_t counts = round((10.0f /* msec */ / 1000.0f) * freq_hz / (1 << TIMER_SOURCE_DIV_1024));

  // Generate an interrupt after 10 milliseconds. (The count starts from 0)
  fsp_timer.begin(TIMER_MODE_ONE_SHOT, type, channel, counts - 1, 1, TIMER_SOURCE_DIV_1024, IrqCallback, nullptr);

#endif

  // Start the timer
  fsp_timer.setup_overflow_irq();
  fsp_timer.open();
  fsp_timer.start();

  lap_time = millis();
  Serial.println("Start.");
}

void loop() {
  if (irq_fired) {
    irq_fired = false;
    digitalWrite(LED_BUILTIN, HIGH);
    Serial.println("Fired after " + String(lap_time) + " msec");
  }
}

Thanks again for your reply .Sorry
been busy and trying to interpret your code . Still very confused but getting closer.


  // Get available timer from from the timer pool (GPT32 x 2, GPT16 x 6 and AGT x 2).
  // Note: Two of the GPT32 timers are already in use, so we can only get 16-bit timers.
  uint8_t type = -1;
  int channel = FspTimer::get_available_timer(type); // Get GPT_TIMER as a priority
  if (channel == -1) {
    Serial.println("Cannot get timer.");
    return;
  }

what is the significance of -1. How does it relate to the timer type ?

It seems to have caused confusion. I just didn't want it to look like an indefinite value, and -1 is completely unnecessary. Simply uint8_t type; is fine.

Also, when I looked at the RA4M1 manual again, I found that there was inappropriate code.

Renesas RA4M1 Group User’s Manual: Hardware

The division ratios of AGT_TIMER and GPT_TIMER to the respective source clocks have the following constraints:

I will post the retested code:

#include <Arduino.h>
#include <FspTimer.h>
#include <math.h> // for round()

FspTimer fsp_timer;
volatile uint32_t lap_time;
volatile bool irq_fired = false;

static void IrqCallback(timer_callback_args_t* p_args) {
  lap_time = millis() - lap_time;
  irq_fired = true;
}

void setup() {
  Serial.begin(115200);
  while (!Serial);

  pinMode(LED_BUILTIN, OUTPUT);

  // Get available timer from the timer pool (GPT32 x 2, GPT16 x 6 and AGT x 2).
  // Note: Two of the GPT32 timers are already in use, so we can only get 16-bit timers.
  uint8_t type;
  int channel = FspTimer::get_available_timer(type); // Get GPT_TIMER as a priority
  if (channel == -1) {
    Serial.println("Cannot get timer.");
    return;
  }

#if   0

  // Generate an interrupt after 10 milliseconds.
  fsp_timer.begin(TIMER_MODE_ONE_SHOT, type, channel, 100.0 /* Hz */, 50.0 /* % */, IrqCallback, nullptr);

#else

  /* PCLK divisors
    https://github.com/arduino/ArduinoCore-renesas/blob/main/variants/MINIMA/includes/ra/fsp/inc/api/r_timer_api.h#L130-L144
  typedef enum e_timer_source_div
  {
      TIMER_SOURCE_DIV_1    = 0,         ///< Timer clock source divided by 1
      TIMER_SOURCE_DIV_2    = 1,         ///< Timer clock source divided by 2
      TIMER_SOURCE_DIV_4    = 2,         ///< Timer clock source divided by 4
      TIMER_SOURCE_DIV_8    = 3,         ///< Timer clock source divided by 8
      TIMER_SOURCE_DIV_16   = 4,         ///< Timer clock source divided by 16
      TIMER_SOURCE_DIV_32   = 5,         ///< Timer clock source divided by 32
      TIMER_SOURCE_DIV_64   = 6,         ///< Timer clock source divided by 64
      TIMER_SOURCE_DIV_128  = 7,         ///< Timer clock source divided by 128
      TIMER_SOURCE_DIV_256  = 8,         ///< Timer clock source divided by 256
      TIMER_SOURCE_DIV_512  = 9,         ///< Timer clock source divided by 512
      TIMER_SOURCE_DIV_1024 = 10,        ///< Timer clock source divided by 1024
  } timer_source_div_t;
  */

  // Get source clock frequency of the acquired timer.
  uint32_t clock_hz;
  timer_source_div_t src_div;

  if (type == GPT_TIMER) {
    clock_hz = R_FSP_SystemClockHzGet(FSP_PRIV_CLOCK_PCLKD);
    src_div = TIMER_SOURCE_DIV_1024; // 1, 4, 16, 64, 256, 1024
    Serial.print("GPT_TIMER ");
  } else {
    clock_hz = R_FSP_SystemClockHzGet(FSP_PRIV_CLOCK_PCLKB);
    src_div = TIMER_SOURCE_DIV_8; // 1, 2, 8
    Serial.print("AGT_TIMER ");
  }

  // Calculate the number of counts for 10 msec
  uint32_t counts = round((10.0f /* msec */ / 1000.0f) * clock_hz / (1 << src_div));

  Serial.print("channel:"  + String(channel));
  Serial.print(", clock:"  + String(clock_hz));
  Serial.print(", div:"    + String(1 << src_div));
  Serial.print(", counts:" + String(counts) + "\n");

  // Generate an interrupt after 10 milliseconds. (The count starts from 0)
  fsp_timer.begin(TIMER_MODE_ONE_SHOT, type, channel, counts - 1, 1, src_div, IrqCallback, nullptr);

#endif

  // Start the timer
  fsp_timer.setup_overflow_irq();
  fsp_timer.open();
  fsp_timer.start();

  lap_time = millis();
  Serial.println("Start.");
}

void loop() {
  if (irq_fired) {
    irq_fired = false;
    digitalWrite(LED_BUILTIN, HIGH);
    Serial.println("Fired after " + String(lap_time) + " msec");
  }
}

If the divide ratio is not set correctly it will not work as expected, however specifying the frequency with begin() will set the appropriate divide ratio and is recommended.