/*
 * Copyright 2019 NXP
 * All rights reserved.
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */
#include "fsl_gpt.h"
#include "fsl_debug_console.h"
#include "gpt.h"

#define EXAMPLE_GPT GPT2
#define EXAMPLE_GPT_CLOCK_SOURCE_SELECT (0U)
#define EXAMPLE_GPT_CLK_FREQ CLOCK_GetFreq(kCLOCK_Osc24M)


uint32_t gptFreq;
static uint32_t cnt1;


void gp_timer_measure_begin(void)
{
    cnt1 = gp_timer_get_cnt();
}

uint32_t gp_timer_measure_end(void)
{
    uint32_t cnt2;    
    uint32_t us = 0;
    cnt2 = gp_timer_get_cnt();
    us = gp_timer_compute_us(cnt2, cnt1);

    //PRINTF("us: %d, %d, %d\r\n", us, cnt2, cnt1);
    return us;
}

uint32_t gp_timer_get_cnt(void)
{
    return GPT_GetCurrentTimerCount(EXAMPLE_GPT);
}

uint32_t correct_error(uint32_t us)
{
    return us*86/95;
}

/*
    For cnt1 and cnt2, get the time in us.
*/
uint32_t gp_timer_compute_us(uint32_t cnt2, uint32_t cnt1)
{
    int delta;
    double t;

    delta = cnt2 - cnt1;
    //PRINTF("delta = %d, \r\n", delta);
    t = gptFreq;
    t = 1/t;
    t = t*1000*1000; // to us
    t = delta * t;
    
    return (uint32_t)t;
}

void gp_timer_delay(uint32_t us_delay)
{
    uint32_t cnt1;
    uint32_t cnt2;
    uint32_t cnt2_pre;
    uint32_t period = 0;
    uint32_t us     = 0;
    
    cnt1 = gp_timer_get_cnt();
    cnt2 = cnt1;
    cnt2_pre = cnt2;

    while(us < us_delay)
    {
        cnt2 = gp_timer_get_cnt();
        if(cnt2 < cnt2_pre)
        {
            period++;
        }
        us = gp_timer_compute_us(cnt2 + period * gptFreq, cnt1);
        cnt2_pre = cnt2;
    }
}

#define COUNT_MAX_PERIOD_SECOND 100
void gp_timer_init(void)
{
    gpt_config_t gptConfig;
    clock_root_config_t rootCfg;

    /*
        000 - OSC_RC_48M_DIV2
        001 - OSC_24M
        010 - OSC_RC_400M
        011 - OSC_RC_16M
        100 - SYS_PLL3_DIV2
        101 - SYS_PLL1_DIV5
        110 - SYS_PLL3_PFD2
        111 - SYS_PLL3_PFD3
    */
    rootCfg.mux = 1; // Set root clock to be OSC_24M
    rootCfg.div = 0;
    CLOCK_SetRootClock(kCLOCK_Root_Gpt1, &rootCfg);

    GPT_GetDefaultConfig(&gptConfig);    
	/*
		gpt1_ipg_clk          GPT1_CLK_ROOT
		gpt1_ipg_clk_s        GPT1_CLK_ROOT
		gpt1_ipg_clk_32k      GPT1_CLK_ROOT
		gpt1_ipg_clk_highfreq GPT1_CLK_ROOT
		gpt1_ipg_clk_24m      RCOSC_16M
	*/
    gptConfig.clockSource = kGPT_ClockSource_Periph; // GPT clock root
    GPT_Init(EXAMPLE_GPT, &gptConfig);
    GPT_SetClockDivider(EXAMPLE_GPT, 3);
    gptFreq  = CLOCK_GetFreq(kCLOCK_Osc24M);
    gptFreq /= 3;
    GPT_SetOutputCompareValue(EXAMPLE_GPT, kGPT_OutputCompare_Channel1, gptFreq*COUNT_MAX_PERIOD_SECOND);
    GPT_StartTimer(EXAMPLE_GPT);

    PRINTF("gptFreq: %d\n\r", gptFreq);
}

