Input Capture


I have a input signal and need to calculate the time between the rising edges (Capt_T) and the time between the rising and the falling edge (Capt_t).


In my current product (which has a ColdFire JM128) I am using a input capture pin and the following function:

// This function must be called in the capture interrupt
void taco_signal_capture(void)
      // Resets timeout counter
      taco_CapTimeout = 0;

      // Waiting for a rising edge
            // Reads the captured value
            Capt_T = TPM1C2V;

            // Resets timer counter
            TPM1CNT = 0;

            // Disables rising edge and enables falling edge
            (void)(TPM1C2SC == 0);
            TPM1C2SC = 0x48;
      // Waiting for a falling edge
            // Reads the captured value
            Capt_t = TPM1C2V;

            // Disables falling edge and enables rising edge
            (void)(TPM1C2SC == 0);
            TPM1C2SC = 0x44;

I tried to use the Synergy input capture driver to achieve the same result, but I can't find how to change the detection edge during runtime.

What is the best way to achieve this using the Synergy features?


Best regards.

  • Hi Mad River,

    Please find a similar thread:
    I hope this will help you.

  • Hello,

    This code extract will do what you require.
    I am using S7G2-SK board, SSP1.2.1
    I am using Timer on GPT0 as the input capture timer.
    Add Timer on GPT0 to your Synergy project and then no configuration via the properties window is required. All functionality is set at the register level as you will see.
    I have used Timer on GPT11 to generate an test output PWM (100ms/ 75% duty) that I fed into GPT0 to test the functionality.

    Hope this helps

    /* HAL-only entry function */
    #include "hal_data.h"

    /* #defines for the ISR creation and register level configuration */
    #include "../synergy/ssp/src/bsp/cmsis/Device/RENESAS/S7G2/Include/S7G2.h"
    #include "../synergy/ssp/inc/ssp_features.h"

    SSP_VECTOR_DEFINE_CHAN(gpt0_counter_compare_match_A_isr, GPT, CAPTURE_COMPARE_A, 0); // isr,ip,signal,channel

    /* User defined ISR */
    void gpt0_counter_compare_match_A_isr(void);

    /* Storage for timer values */
    volatile uint32_t Capt_T;
    volatile uint32_t Capt_t;

    /* Pointer to access the chosen timer that we wsih to modify for our specific usage */
    gpt_instance_ctrl_t * gp_ctrl; /* pointer to GPT control instance */
    R_GPTA0_Type * gp_gpt; /* pointer to GPT register */

    void hal_entry(void)
    /* TODO: add your own code here */

    /* These variables are used to set the ISR in the ICU & NVIC */
    fmi_feature_info_t info = {0U};
    ssp_feature_t ssp_feature = {{(ssp_ip_t) 0}};
    fmi_event_info_t event_info = {(IRQn_Type) 0U};
    ssp_vector_info_t * p_vector_info;

    /* open the timer on GPT that was added to the project */
    g_gpt0.p_api->open(g_gpt0.p_ctrl, g_gpt0.p_cfg);

    /* initialize access pointers */
    gp_ctrl = g_gpt0.p_ctrl;
    gp_gpt = gp_ctrl->p_reg;

    /* Configure the timer to capture a starting edge */
    gp_gpt->GTICASR_b.ASCARBL = 1; // Enable GTCCRA input capture on the rising edge of GTIOCA input when GTIOCB input is 0.
    gp_gpt->GTICASR_b.ASCARBH = 1; // Enable GTCCRA input capture on the rising edge of GTIOCA input when GTIOCB input is 1.

    /* Enable input capture buffer operation */
    gp_gpt->GTBER_b.CCRA = 1; // Single buffer operation (GTCCRA ↔ GTCCRC)

    /* Set the Period register to a value that will not cause the timer to reset */
    gp_gpt->GTPR = 0xffffffff;

    /* enable software clearing of the timer */
    gp_gpt->GTCSR_b.CCLR = 1;

    /* Enable the compare match interrupt for GPT0A*/ = 0;
    ssp_feature.unit = 0U; = SSP_IP_GPT;

    g_fmi_on_fmi.productFeatureGet(&ssp_feature, &info);
    g_fmi_on_fmi.eventInfoGet(&ssp_feature, SSP_SIGNAL_GPT_CAPTURE_COMPARE_A, &event_info);

    R_SSP_VectorInfoGet(event_info.irq, &p_vector_info);
    NVIC_SetPriority(event_info.irq, 8);


    /* Start the demo generation timer */
    /* Timer on gp11 has ben configured to generate a PWM - 100ms period / 75% duty */
    /* Input this output into that of GPT0 to test */
    g_gpt11.p_api->open(g_gpt11.p_ctrl, g_gpt11.p_cfg);


    /* User defined ISR based upon code supplied */
    void gpt0_counter_compare_match_A_isr(void)
    ssp_vector_info_t * p_vector_info = NULL;
    R_SSP_VectorInfoGet(R_SSP_CurrentIrqGet(), &p_vector_info);

    if( (gp_gpt->GTICASR_b.ASCARBL == 1) && (gp_gpt->GTICASR_b.ASCARBH == 1) ) // This is a rising edge interrupt
    /* Read the captured value */
    Capt_T = gp_gpt->GTCCRC;

    /* reconfigure for falling edge */
    gp_gpt->GTICASR = 0x00000c00;

    /* reset the timer */
    gp_gpt->GTCLR = 0x1;

    else if( (gp_gpt->GTICASR_b.ASCAFBL == 1) && (gp_gpt->GTICASR_b.ASCAFBH == 1) ) // This is a falling edge interrupt
    /* Read the captured value */
    Capt_t = gp_gpt->GTCCRC;

    /* reconfigure for rising edge */
    gp_gpt->GTICASR = 0x00000300;


    gp_gpt->GTST_b.TCFA = 0; // Clear the ISR flag in the peripheral

    /** Clear pending IRQ to make sure it doesn't fire again after exiting */
  • In reply to Richard:


    Hope this helps 

    Hi Richard,

    Thank you very much for your answer.

    I will test it tomorrow, as soon as I arrive at work.

    Meanwhile, my last attempt was to add the Input Capture Driver to my project.

    I generated the Synergy files and tried to compile it, but I am getting this error:
    fatal error: 'r_gpt.h' file not found hw_gpt_private.h /INV600_touch/synergy/ssp/src/driver/r_gpt_input_capture/hw line 32

    What am I missing? Do I need to add some other driver as well?

  • In reply to Mad River:

    If you wish to try and use the input capture driver, you have to add a "timer on gpt" module too as well as the input capture module.
    However, if you wish to use the code example I posted, you DO NOT need to add the input capture module. Just add a "timer on gpt" module, select the channel you want (gpt0 -> gpt13) and build the project.
    The only gpt api you will be using is the .open call. The code I supplied re-configures the gpt driver at the register level to do input capture functionality as required.
  • In reply to Richard:

    Hi Richard,

    I will start trying your solution right now.
    Yesterday I tried to add the Timer Driver on r_gpt to my project.
    Now I am getting:

    redefinition of 'g_vector_GPT_5_COUNTER_OVERFLOW' ssp_features.h /INV600_touch/synergy/ssp/inc line 93 C/C++ Problem

    redefinition of 'g_vector_info_GPT_5_COUNTER_OVERFLOW' ssp_features.h /INV600_touch/synergy/ssp/inc line 95 C/C++ Problem




    About your code, I am using S3A3, the registers names are the same?

    I changed from "#include "../synergy/ssp/src/bsp/cmsis/Device/RENESAS/S7G2/Include/S7G2.h" to "#include "../synergy/ssp/src/bsp/cmsis/Device/RENESAS/S3A3/Include/S3A3.h", but everything "register related" isn't compiling.

  • In reply to Mad River:

    The redefinition can occur if you have the interrupt enabled in the gpt module and the gpt input capture module. If you are trying to use the input capture module only set the properties in the input capture module. The standard gpt settings do not need to be touched.

    And if using the code I posted on the S3, please use "R_GPTB0_Type"
  • In reply to Richard:


    And if using the code I posted on the S3, please use "R_GPTB0_Type"

    The only remaining error is this:
    gp_gpt->GTST_b.TCFA = 0; // Clear the ISR flag in the peripheral
    Description Resource Path Location Type
    'struct <anonymous>' has no member named 'TCFA' blinky_thread_entry.c /INV600_touch/src line 104 C/C++ Problem
    Description Resource Path Location Type
    Field 'TCFA' could not be resolved blinky_thread_entry.c /INV600_touch/src line 104 Semantic Error
    In the GTST_b struct there is "__IO uint32_t  TCFB       :  1;               /*!< Input Capture/Compare Match Flag B".
    I suppose this is the correct one, right?
  • In reply to Mad River:

    No, that appears to be a bug in the header file.
    I'm sure that there should be an entry for
    __IO uint32_t TCFA : 1; /*!< Input Capture/Compare Match Flag A

    So you could add this field to your header file and once you have edited the file, save it and set its properties to read only. Otherwise it will get overwritten with the original file when you build your code.
    Or, the simpler option would be to clear the bit with
    gp_gpt->GTST &= ~0x1;
  • In reply to Richard:

    Hi Richard,

    I am trying your code.

    I replaced "gp_gpt->GTST_b.TCFA = 0;" for "gp_gpt->GTST &= (uint32_t)~0x1;".


    I am using pin P101 as input. It is configured as "Peripheral mode: GPT5_GTIOCA".

    In your code, I replaced " = 0;" for " = 5;". Is it correct?

    I didn't do anymore changes to your code.

    I didn't do any modifications to the Timer Driver in the configuration window.

    I am inserting a 1KHz signal in this input, but the ISR function is never called.

    Am I missing some other configuration?

  • In reply to Mad River:

    Did you change the interrupt number in the declaration at the top of the file?
    The final parameter needs to be updated too.

    SSP_VECTOR_DEFINE_CHAN(gpt5_counter_compare_match_A_isr, GPT, CAPTURE_COMPARE_A, 5);

    If this doesn't work then let me know.

  • In reply to Richard:

    Hi Richard,

    I am using your code and now the ISR is being called.
    How can I calculate the input frequency to check if it is the expected?
    I tried a few calculations, but it doesn't appears to be correct.
  • In reply to Mad River:

    Here is the test waveform that I'm capturing.

    You can see (sorry for the very small image!) that the oscilloscope is measuring "+ Width" 74.99ms, "- Width" 25.00ms and the "Period" is 99.99ms


    From the code I sent you, I get

    Capt_T = 3599946 timer counts

    Capt_t = 4799945 timer counts.

    In my example, the S3A7 is configured for PCLKA = 48MHz, to the GPT is running at 48MHz


    Therefore, 1 timer count = 1/48 MHz, and

    Capt_T = 3599946 x (1 / 48MHz) = 74.998875ms (as being shown by the oscilloscope)

    Capt_t = 4799945 x (1 / 48MHz) = 99.99885417ms (as being shown by the oscilloscope)


    The logic of Capt_T < Capt_t is because I have enabled register buffering and I'm reading the captured value form GTCCRC.

    If you read from GTCCRA then the Capt_T > Capt_t, as per your original diagram.


    Hope this all helps.




  • In reply to Richard:

    Hi Richard,

    It helped a lot.

    Thank you very much!