/*
 * Copyright 2020-2022 Yuntu Microelectronics co.,ltd
 * All rights reserved.
 *
 * YUNTU Confidential. This software is owned or controlled by YUNTU and may
 * only be used strictly in accordance with the applicable license terms. By expressly
 * accepting such terms or by downloading, installing, activating and/or otherwise
 * using the software, you are agreeing that you have read, and that you agree to
 * comply with and are bound by, such license terms. If you do not agree to be
 * bound by the applicable license terms, then you may not retain, install,
 * activate or otherwise use the software. The production use license in
 * Section 2.3 is expressly granted for this software.
 */
/*!
 * @file etmr_ic_driver.c
 */

#include "etmr_ic_driver.h"
#include "etmr_hw_access.h"
#include "interrupt_manager.h"

/*******************************************************************************
 * Code
 ******************************************************************************/
#if FEATURE_eTMR_HAS_HARDWARE_CAPTURE

void eTMR0_Ch0_Ch1_IRQHandler(void)
{
    for (uint8_t channel = 0; channel < 2; channel++)
    {
        eTMR_DRV_InputCaptureHandler(0, channel);
    }

    eTMR_DRV_ClearChnFlag(0, 1 << 0 | 1 << 1);
}

void eTMR0_Ch2_Ch3_IRQHandler(void)
{
    for (uint8_t channel = 2; channel < 4; channel++)
    {
        eTMR_DRV_InputCaptureHandler(0, channel);
    }
    eTMR_DRV_ClearChnFlag(0, 1 << 2 | 1 << 3);
}

void eTMR0_Ch4_Ch5_IRQHandler(void)
{
    for (uint8_t channel = 4; channel < 6; channel++)
    {
        eTMR_DRV_InputCaptureHandler(0, channel);
    }
    eTMR_DRV_ClearChnFlag(0, 1 << 4 | 1 << 5);
}

void eTMR0_Ch6_Ch7_IRQHandler(void)
{
    for (uint8_t channel = 6; channel < 8; channel++)
    {
        eTMR_DRV_InputCaptureHandler(0, channel);
    }
    eTMR_DRV_ClearChnFlag(0, 1 << 6 | 1 << 7);
}

void eTMR1_Ch0_Ch1_IRQHandler(void)
{
    for (uint8_t channel = 0; channel < 2; channel++)
    {
        eTMR_DRV_InputCaptureHandler(1, channel);
    }
    eTMR_DRV_ClearChnFlag(1, 1 << 0 | 1 << 1);
}

void eTMR1_Ch2_Ch3_IRQHandler(void)
{
    for (uint8_t channel = 2; channel < 4; channel++)
    {
        eTMR_DRV_InputCaptureHandler(1, channel);
    }
    eTMR_DRV_ClearChnFlag(1, 1 << 2 | 1 << 3);
}

void eTMR1_Ch4_Ch5_IRQHandler(void)
{
    for (uint8_t channel = 4; channel < 6; channel++)
    {
        eTMR_DRV_InputCaptureHandler(1, channel);
    }
    eTMR_DRV_ClearChnFlag(1, 1 << 4 | 1 << 5);
}

void eTMR1_Ch6_Ch7_IRQHandler(void)
{
    for (uint8_t channel = 6; channel < 8; channel++)
    {
        eTMR_DRV_InputCaptureHandler(1, channel);
    }
    eTMR_DRV_ClearChnFlag(1, 1 << 6 | 1 << 7);
}

#if eTMR_INSTANCE_COUNT > 2U
void eTMR2_Ch0_Ch1_IRQHandler(void)
{
    for (uint8_t channel = 0; channel < 2; channel++)
    {
        eTMR_DRV_InputCaptureHandler(2, channel);
    }
    eTMR_DRV_ClearChnFlag(2, 1 << 0 | 1 << 1);
}

void eTMR2_Ch2_Ch3_IRQHandler(void)
{
    for (uint8_t channel = 2; channel < 4; channel++)
    {
        eTMR_DRV_InputCaptureHandler(2, channel);
    }
    eTMR_DRV_ClearChnFlag(2, 1 << 2 | 1 << 3);
}

void eTMR2_Ch4_Ch5_IRQHandler(void)
{
    for (uint8_t channel = 4; channel < 6; channel++)
    {
        eTMR_DRV_InputCaptureHandler(2, channel);
    }
    eTMR_DRV_ClearChnFlag(2, 1 << 4 | 1 << 5);
}

void eTMR2_Ch6_Ch7_IRQHandler(void)
{
    for (uint8_t channel = 6; channel < 8; channel++)
    {
        eTMR_DRV_InputCaptureHandler(2, channel);
    }
    eTMR_DRV_ClearChnFlag(2, 1 << 6 | 1 << 7);
}
#endif

#if eTMR_INSTANCE_COUNT > 3U
void eTMR3_Ch0_Ch1_IRQHandler(void)
{
    for (uint8_t channel = 0; channel < 2; channel++)
    {
        eTMR_DRV_InputCaptureHandler(3, channel);
    }
    eTMR_DRV_ClearChnFlag(3, 1 << 0 | 1 << 1);
}

void eTMR3_Ch2_Ch3_IRQHandler(void)
{
    for (uint8_t channel = 2; channel < 4; channel++)
    {
        eTMR_DRV_InputCaptureHandler(3, channel);
    }
    eTMR_DRV_ClearChnFlag(3, 1 << 2 | 1 << 3);
}

void eTMR3_Ch4_Ch5_IRQHandler(void)
{
    for (uint8_t channel = 4; channel < 6; channel++)
    {
        eTMR_DRV_InputCaptureHandler(3, channel);
    }
    eTMR_DRV_ClearChnFlag(3, 1 << 4 | 1 << 5);
}

void eTMR3_Ch6_Ch7_IRQHandler(void)
{
    for (uint8_t channel = 6; channel < 8; channel++)
    {
        eTMR_DRV_InputCaptureHandler(3, channel);
    }
    eTMR_DRV_ClearChnFlag(3, 1 << 6 | 1 << 7);
}
#endif

#if eTMR_INSTANCE_COUNT > 4U
void eTMR4_Ch0_Ch1_IRQHandler(void)
{
    for (uint8_t channel = 0; channel < 2; channel++)
    {
        eTMR_DRV_InputCaptureHandler(4, channel);
    }
    eTMR_DRV_ClearChnFlag(4, 1 << 0 | 1 << 1);
}

void eTMR4_Ch2_Ch3_IRQHandler(void)
{
    for (uint8_t channel = 2; channel < 4; channel++)
    {
        eTMR_DRV_InputCaptureHandler(4, channel);
    }
    eTMR_DRV_ClearChnFlag(4, 1 << 2 | 1 << 3);
}

void eTMR4_Ch4_Ch5_IRQHandler(void)
{
    for (uint8_t channel = 4; channel < 6; channel++)
    {
        eTMR_DRV_InputCaptureHandler(4, channel);
    }
    eTMR_DRV_ClearChnFlag(4, 1 << 4 | 1 << 5);
}

void eTMR4_Ch6_Ch7_IRQHandler(void)
{
    for (uint8_t channel = 6; channel < 8; channel++)
    {
        eTMR_DRV_InputCaptureHandler(4, channel);
    }
    eTMR_DRV_ClearChnFlag(4, 1 << 6 | 1 << 7);
}
#endif

#if eTMR_INSTANCE_COUNT > 5U
void eTMR5_Ch0_Ch1_IRQHandler(void)
{
    for (uint8_t channel = 0; channel < 2; channel++)
    {
        eTMR_DRV_InputCaptureHandler(5, channel);
    }
    eTMR_DRV_ClearChnFlag(5, 1 << 0 | 1 << 1);
}

void eTMR5_Ch2_Ch3_IRQHandler(void)
{
    for (uint8_t channel = 2; channel < 4; channel++)
    {
        eTMR_DRV_InputCaptureHandler(5, channel);
    }
    eTMR_DRV_ClearChnFlag(5, 1 << 2 | 1 << 3);
}

void eTMR5_Ch4_Ch5_IRQHandler(void)
{
    for (uint8_t channel = 4; channel < 6; channel++)
    {
        eTMR_DRV_InputCaptureHandler(5, channel);
    }
    eTMR_DRV_ClearChnFlag(5, 1 << 4 | 1 << 5);
}

void eTMR5_Ch6_Ch7_IRQHandler(void)
{
    for (uint8_t channel = 6; channel < 8; channel++)
    {
        eTMR_DRV_InputCaptureHandler(5, channel);
    }
    eTMR_DRV_ClearChnFlag(5, 1 << 6 | 1 << 7);
}
#endif

#elif FEATURE_eTMR_HAS_COMBINATION_CAPTURE
#if defined(CPU_YTM32B1MC0)
void eTMR0_Ch0_Ch1_IRQHandler(void)
{
    bool en = false;
    uint8_t index = 0;

    en = eTMR_GetCh01CombMode(eTMR0);
    if (en)
    {
        index = eTMR_GetCh01CombSrc(eTMR0);
        eTMR_DRV_InputCaptureHandler(0, index);
    }
    else
    {
        for (uint8_t channel = 0; channel < 2; channel++)
        {
            eTMR_DRV_InputCaptureHandler(0, channel);
        }
    }

    eTMR_DRV_ClearChnFlag(0, 1 << 0 | 1 << 1);
}

void eTMR0_Ch2_Ch3_IRQHandler(void)
{
    bool en = false;
    uint8_t index = 0;

    en = eTMR_GetCh23CombMode(eTMR0);
    if (en)
    {
        index = eTMR_GetCh23CombSrc(eTMR0);
        eTMR_DRV_InputCaptureHandler(0, index + 2);
    }
    else
    {
        for (uint8_t channel = 2; channel < 4; channel++)
        {
            eTMR_DRV_InputCaptureHandler(0, channel);
        }
    }

    eTMR_DRV_ClearChnFlag(0, 1 << 2 | 1 << 3);
}

void eTMR0_Ch4_Ch5_IRQHandler(void)
{
    bool en = false;
    uint8_t index = 0;

    en = eTMR_GetCh45CombMode(eTMR0);
    if (en)
    {
        index = eTMR_GetCh45CombSrc(eTMR0);
        eTMR_DRV_InputCaptureHandler(0, index + 4);
    }
    else
    {
        for (uint8_t channel = 4; channel < 6; channel++)
        {
            eTMR_DRV_InputCaptureHandler(0, channel);
        }
    }

    eTMR_DRV_ClearChnFlag(0, 1 << 4 | 1 << 5);
}

void eTMR0_Ch6_Ch7_IRQHandler(void)
{
    bool en = false;
    uint8_t index = 0;

    en = eTMR_GetCh67CombMode(eTMR0);
    if (en)
    {
        index = eTMR_GetCh67CombSrc(eTMR0);
        eTMR_DRV_InputCaptureHandler(0, index + 6);
    }
    else
    {
        for (uint8_t channel = 6; channel < 8; channel++)
        {
            eTMR_DRV_InputCaptureHandler(0, channel);
        }
    }

    eTMR_DRV_ClearChnFlag(0, 1 << 6 | 1 << 7);
}

void eTMR1_Ch0_Ch1_IRQHandler(void)
{
    bool en = false;
    uint8_t index = 0;

    en = eTMR_GetCh01CombMode(eTMR1);
    if (en)
    {
        index = eTMR_GetCh01CombSrc(eTMR1);
        eTMR_DRV_InputCaptureHandler(1, index);
    }
    else
    {
        for (uint8_t channel = 0; channel < 2; channel++)
        {
            eTMR_DRV_InputCaptureHandler(1, channel);
        }
    }

    eTMR_DRV_ClearChnFlag(1, 1 << 0 | 1 << 1);
}

void eTMR1_Ch2_Ch3_IRQHandler(void)
{
    bool en = false;
    uint8_t index = 0;

    en = eTMR_GetCh23CombMode(eTMR1);
    if (en)
    {
        index = eTMR_GetCh23CombSrc(eTMR1);
        eTMR_DRV_InputCaptureHandler(1, index + 2);
    }
    else
    {
        for (uint8_t channel = 2; channel < 4; channel++)
        {
            eTMR_DRV_InputCaptureHandler(1, channel);
        }
    }

    eTMR_DRV_ClearChnFlag(1, 1 << 2 | 1 << 3);
}

void eTMR1_Ch4_Ch5_IRQHandler(void)
{
    bool en = false;
    uint8_t index = 0;

    en = eTMR_GetCh45CombMode(eTMR1);
    if (en)
    {
        index = eTMR_GetCh45CombSrc(eTMR1);
        eTMR_DRV_InputCaptureHandler(1, index + 4);
    }
    else
    {
        for (uint8_t channel = 4; channel < 6; channel++)
        {
            eTMR_DRV_InputCaptureHandler(1, channel);
        }
    }

    eTMR_DRV_ClearChnFlag(1, 1 << 4 | 1 << 5);
}

void eTMR1_Ch6_Ch7_IRQHandler(void)
{
    bool en = false;
    uint8_t index = 0;

    en = eTMR_GetCh67CombMode(eTMR1);
    if (en)
    {
        index = eTMR_GetCh67CombSrc(eTMR1);
        eTMR_DRV_InputCaptureHandler(1, index + 6);
    }
    else
    {
        for (uint8_t channel = 6; channel < 8; channel++)
        {
            eTMR_DRV_InputCaptureHandler(1, channel);
        }
    }

    eTMR_DRV_ClearChnFlag(1, 1 << 6 | 1 << 7);
}
#endif
#else
void eTMR0_Ovf_IRQHandler(void)
{
    etmr_state_t *state = etmrStatePtr[0];
    /* When overflow, record overflow count */
    for (uint8_t index = 0; index < g_etmrChannelNum[0]; index++)
    {
        state->icOvfCntTemp[index]++;
    }
    /* Clear overflow flag */
    eTMR_DRV_ClearTofFlag(0);
}

void eTMR0_CH_0_7_IRQHandler(void)
{
    /* Traverse all channel to process capture event */
    for (uint8_t index = 0; index < g_etmrChannelNum[0]; index++)
    {
        /* If capture event occurs, process it */
        if (eTMR_DRV_GetChnFlag(0, index))
        {
            eTMR_DRV_InputCaptureHandler(0, index);
            eTMR_DRV_ClearChnFlag(0, 1 << index);
        }
    }
}

void eTMR1_IRQHandler(void)
{
    etmr_state_t *state = etmrStatePtr[1];
    /* When overflow, record overflow count */
    if (eTMR_DRV_GetTofFlag(1))
    {
        for (uint8_t index = 0; index < g_etmrChannelNum[1]; index++)
        {
            state->icOvfCntTemp[index]++;
        }
        eTMR_DRV_ClearTofFlag(1);
    }

    for (uint8_t index = 0; index < g_etmrChannelNum[1]; index++)
    {
        /* If capture event occurs, process it */
        if (eTMR_DRV_GetChnFlag(1, index))
        {
            eTMR_DRV_InputCaptureHandler(1, index);
            eTMR_DRV_ClearChnFlag(1, 1 << index);
        }
    }
}

void eTMR2_IRQHandler(void)
{
    etmr_state_t *state = etmrStatePtr[2];
    if (eTMR_DRV_GetTofFlag(2))
    {
        /* When overflow, record overflow count */
        for (uint8_t index = 0; index < g_etmrChannelNum[2]; index++)
        {
            state->icOvfCntTemp[index]++;
        }
        eTMR_DRV_ClearTofFlag(2);
    }

    for (uint8_t index = 0; index < g_etmrChannelNum[2]; index++)
    {
        /* If capture event occurs, process it */
        if (eTMR_DRV_GetChnFlag(2, index))
        {
            eTMR_DRV_InputCaptureHandler(2, index);
            eTMR_DRV_ClearChnFlag(2, 1 << index);
        }
    }
}
#endif

/*FUNCTION**********************************************************************
 *
 * Function Name : eTMR_DRV_InitInputCapture
 * Description   : This function initialize the channel in the Input Capture mode
 *
 * Implements    : eTMR_DRV_InitInputCapture_Activity
 *END**************************************************************************/
status_t eTMR_DRV_InitInputCapture(uint32_t instance, const etmr_ic_param_t *param)
{
    DEV_ASSERT(instance < eTMR_INSTANCE_COUNT);
    DEV_ASSERT(param != NULL);
    eTMR_Type *const etmrBase = g_etmrBase[instance];
    etmr_state_t *state = etmrStatePtr[instance];
    uint8_t index;
    uint8_t hwChannel;
    status_t status = STATUS_SUCCESS;

    if (NULL != state)
    {
        eTMR_SetCntVal(etmrBase, 0U);
#if FEATURE_eTMR_HAS_CNT_INIT_SRC
        eTMR_SetCounterInitValSrc(etmrBase, true);
#endif
#if FEATURE_eTMR_HAS_INIT_REG
        /* Set initial value for counter */
        eTMR_SetInitVal(etmrBase, 0U);
#endif
        /* Set maximum value for counter */
        eTMR_SetMod(etmrBase, param->countValue);
        /* Get current MOD value */
        state->etmrModValue = param->countValue;

#if FEATURE_eTMR_HAS_COMBINATION_CAPTURE
        for (index = 0U; index < (param->numChannelPairs); index++)
        {
            uint8_t hwChannelPair = param->inputChPairConfig[index].hwChannelPairId;
            eTMR_DRV_SetChnCombMode(instance, hwChannelPair, param->inputChPairConfig[index].combEn);
            eTMR_DRV_SetChnCombSrc(instance, hwChannelPair, param->inputChPairConfig[index].combSrc);
        }
#endif

        /* Initialize channel configuration */
        for (index = 0U; index < (param->numChannels); index++)
        {
            hwChannel = param->inputChConfig[index].hwChannelId;

            /* Set input capture mode for channel */
            eTMR_SetChnMode(etmrBase, hwChannel, eTMR_INPUT_CAPTURE_MODE);
            state->etmrChnMode[hwChannel] = eTMR_STATE_INPUT_CAPTURE;
            /* Set edge detection */
            eTMR_SetChnCapEdge(etmrBase, hwChannel, param->inputChConfig[index].edge);
            state->captureEdge[hwChannel] = param->inputChConfig[index].edge;
            /* Store measurement type */
            state->measurementType[hwChannel] = param->inputChConfig[index].measurementType;
#if FEATURE_eTMR_HAS_CAPTURE_HOLD
            /* Set capture hold feature */
            eTMR_SetChnCapHoldEnable(etmrBase, hwChannel, param->inputChConfig[index].capHoldEn);
#endif
            /* Set filter sample counter/period for input capture channel */
            eTMR_SetChnCapFilterSampleCounter(etmrBase, hwChannel, param->inputChConfig[index].filterSampleCounter);
            eTMR_SetChnCapFilterSamplePeriod(etmrBase, hwChannel, param->inputChConfig[index].filterSamplePeriod);
            /* Set DMA */
            if (param->inputChConfig[index].dmaEnable)
            {
                eTMR_SetChnDmaEnable(etmrBase, hwChannel, true);
            }

            /* Set channel interrupt */
            if (param->inputChConfig[index].interruptEnable)
            {
                eTMR_DRV_EnableChnInt(instance, hwChannel);
                INT_SYS_EnableIRQ(g_etmrIrqId[instance][hwChannel]);
            }

            /* Clear state elements */
            for (int i = 0; i < 3; i++)
            {
                state->icOvfCnt[hwChannel][i] = 0;
                state->icCntVal[hwChannel][i] = 0;
                state->icCapPol[hwChannel][i] = 0;
            }
            state->icOvfCntTemp[hwChannel] = 0;
            state->icCnt[hwChannel] = 0;
            state->measurementComplete[hwChannel] = 0;
            state->measurementPeriod[hwChannel] = 0;
            state->measurementPosPulseCnt[hwChannel] = 0;
            state->measurementNegPulseCnt[hwChannel] = 0;
            state->measurementCapCnt[hwChannel] = 0;

            /* Save in state structure user define handlers */
            state->enableNotification[hwChannel] = param->inputChConfig[index].enableNotification;
            state->channelsCallbacksParams[hwChannel] = param->inputChConfig[index].channelsCallbacksParams;
            state->channelsCallbacks[hwChannel] = param->inputChConfig[index].channelsCallbacks;
        }
    }
    else /* state is NULL */
    {
        status = STATUS_ERROR;
    }

    return status;
}

/*FUNCTION**********************************************************************
 *
 * Function Name : eTMR_DRV_DeinitInputCapture
 * Description   : This function de-initialize input capture mode and configure
 *                 channel as none mode
 *
 * Implements    : eTMR_DRV_DeinitInputCapture_Activity
 *END**************************************************************************/
status_t eTMR_DRV_DeinitInputCapture(uint32_t instance, const etmr_ic_param_t *param)
{
    DEV_ASSERT(instance < eTMR_INSTANCE_COUNT);
    DEV_ASSERT(param != NULL);
    eTMR_Type *const etmrBase = g_etmrBase[instance];
    etmr_state_t *state = etmrStatePtr[instance];
    DEV_ASSERT(state != NULL);
    uint8_t index;
    uint8_t hwChannel;

    /* Deinit channel configuration */
#if FEATURE_eTMR_HAS_COMBINATION_CAPTURE
    for (index = 0U; index < (param->numChannelPairs); index++)
    {
        uint8_t hwChannelPair = param->inputChPairConfig[index].hwChannelPairId;
        eTMR_DRV_SetChnCombMode(instance, hwChannelPair, false);
        eTMR_DRV_SetChnCombSrc(instance, hwChannelPair, eTMR_COMB_SRC_EVEN);
    }
#endif

    for (index = 0U; index < param->numChannels; index++)
    {
        hwChannel = param->inputChConfig[index].hwChannelId;

        /* Set channel mode as none */
        eTMR_SetChnMode(etmrBase, hwChannel, eTMR_CHANNEL_DISABLE);
        /* Set channel capture edge as none */
        eTMR_SetChnCapEdge(etmrBase, hwChannel, eTMR_NOT_SEL_EDGE);
        /* Disable channel interrupt */
        eTMR_DRV_DisableChnInt(instance, hwChannel);
        /* Clear channel event flags */
        eTMR_DRV_ClearChnFlag(instance, hwChannel);
#if FEATURE_eTMR_HAS_HARDWARE_CAPTURE
        eTMR_DRV_ClearChnPosPulseRdyFlag(instance, hwChannel);
        eTMR_DRV_ClearChnNegPulseRdyFlag(instance, hwChannel);
#endif
#if FEATURE_eTMR_HAS_CAPTURE_HOLD
        eTMR_SetChnCapHoldEnable(etmrBase, hwChannel, false);
#endif
        /* Disable filter */
        eTMR_SetChnCapFilterSampleCounter(etmrBase, hwChannel, 0);
        eTMR_SetChnCapFilterSamplePeriod(etmrBase, hwChannel, 0);
        /* Disable DMA */
        eTMR_SetChnDmaEnable(etmrBase, hwChannel, false);
        /* Save etmr channel mode in state structure */
        state->etmrChnMode[hwChannel] = eTMR_STATE_NO_MODE;
        /* Clear capture edge */
        state->captureEdge[hwChannel] = eTMR_NOT_SEL_EDGE;
        /* Store measurement type */
        state->measurementType[hwChannel] = eTMR_POS_PULSE_MEASUREMENT;

        /* Clear state elements */
        for (int i = 0; i < 3; i++)
        {
            state->icOvfCnt[i][hwChannel] = 0;
            state->icCntVal[hwChannel][i] = 0;
            state->icCapPol[hwChannel][i] = 0;
        }
        state->icOvfCntTemp[hwChannel] = 0;
        state->icCnt[hwChannel] = 0;
        state->measurementComplete[hwChannel] = 0;
        state->measurementPeriod[hwChannel] = 0;
        state->measurementPosPulseCnt[hwChannel] = 0;
        state->measurementNegPulseCnt[hwChannel] = 0;
        state->measurementCapCnt[hwChannel] = 0;

        /* Clear Callbacks function from the state structure */
        state->enableNotification[index] = false;
        state->channelsCallbacksParams[index] = NULL;
        state->channelsCallbacks[index] = NULL;
    }

    return STATUS_SUCCESS;
}

/*FUNCTION**********************************************************************
 *
 * Function Name : eTMR_DRV_GetInputCaptureComplete
 * Description   : This function is used to get complete status.
 *
 * Implements    : eTMR_DRV_GetInputCaptureComplete_Activity
 *END**************************************************************************/
bool eTMR_DRV_GetInputCaptureComplete(uint32_t instance, uint8_t channel)
{
    DEV_ASSERT(instance < eTMR_INSTANCE_COUNT);
    DEV_ASSERT(channel < g_etmrChannelNum[instance]);
    etmr_state_t *state = etmrStatePtr[instance];
    uint8_t value = 0U;

    if (state != NULL)
    {
        value = state->measurementComplete[channel];
    }

    return value;
}

/*FUNCTION**********************************************************************
 *
 * Function Name : eTMR_DRV_ClearInputCaptureComplete
 * Description   : This function is used to clear complete status.
 *
 * Implements    : eTMR_DRV_ClearInputCaptureComplete_Activity
 *END**************************************************************************/
status_t eTMR_DRV_ClearInputCaptureComplete(uint32_t instance, uint8_t channel)
{
    DEV_ASSERT(instance < eTMR_INSTANCE_COUNT);
    DEV_ASSERT(channel < g_etmrChannelNum[instance]);
    etmr_state_t *state = etmrStatePtr[instance];

    if (state != NULL)
    {
        state->measurementComplete[channel] = 0;
    }

    return STATUS_SUCCESS;
}

/*FUNCTION**********************************************************************
 *
 * Function Name : eTMR_DRV_GetInputCaptureMeasurementPeriod
 * Description   : This function is used to get the period of pwm. The
 *                 calculation is available in the eTMR_DRV_InputCaptureHandler
 *                 function.
 *
 * Implements    : eTMR_DRV_GetInputCaptureMeasurementPeriod_Activity
 *END**************************************************************************/
uint32_t eTMR_DRV_GetInputCaptureMeasurementPeriod(uint32_t instance, uint8_t channel)
{
    DEV_ASSERT(instance < eTMR_INSTANCE_COUNT);
    DEV_ASSERT(channel < g_etmrChannelNum[instance]);
    etmr_state_t *state = etmrStatePtr[instance];
    uint32_t value = 0U;

    if (state != NULL)
    {
        value = state->measurementPeriod[channel];
    }

    return value;
}

/*FUNCTION**********************************************************************
 *
 * Function Name : eTMR_DRV_GetInputCapturePositivePulseCount
 * Description   : This function is used to get positive pulse count value.
 *
 * Implements    : eTMR_DRV_GetInputCapturePositivePulseCount_Activity
 *END**************************************************************************/
uint32_t eTMR_DRV_GetInputCapturePositivePulseCount(uint32_t instance, uint8_t channel)
{
    DEV_ASSERT(instance < eTMR_INSTANCE_COUNT);
    DEV_ASSERT(channel < g_etmrChannelNum[instance]);
    const etmr_state_t *state = etmrStatePtr[instance];
    uint32_t value = 0;

    if (state != NULL)
    {
        value = state->measurementPosPulseCnt[channel];
    }

    return value;
}

/*FUNCTION**********************************************************************
 *
 * Function Name : eTMR_DRV_GetInputCaptureNegativePulseCount
 * Description   : This function is used to get negative pulse count value.
 *
 * Implements    : eTMR_DRV_GetInputCaptureNegativePulseCount_Activity
 *END**************************************************************************/
uint32_t eTMR_DRV_GetInputCaptureNegativePulseCount(uint32_t instance, uint8_t channel)
{
    DEV_ASSERT(instance < eTMR_INSTANCE_COUNT);
    DEV_ASSERT(channel < g_etmrChannelNum[instance]);
    const etmr_state_t *state = etmrStatePtr[instance];
    uint32_t value = 0;

    if (state != NULL)
    {
        value = state->measurementNegPulseCnt[channel];
    }

    return value;
}

/*FUNCTION**********************************************************************
 *
 * Function Name : eTMR_DRV_GetInputCaptureValue
 * Description   : This function is used to get capture count value.
 *
 * Implements    : eTMR_DRV_GetInputCaptureValue_Activity
 *END**************************************************************************/
uint32_t eTMR_DRV_GetInputCaptureValue(uint32_t instance, uint8_t channel)
{
    DEV_ASSERT(instance < eTMR_INSTANCE_COUNT);
    DEV_ASSERT(channel < g_etmrChannelNum[instance]);
    eTMR_Type *etmrBase = g_etmrBase[instance];
    return eTMR_GetChnCapVal(etmrBase, channel);
}

#if FEATURE_eTMR_HAS_HARDWARE_CAPTURE
/*FUNCTION**********************************************************************
 *
 * Function Name : eTMR_DRV_InputCaptureHandler
 * Description   : This function is used to calculate measurement for input capture.
 *
 * Implements    : eTMR_DRV_InputCaptureHandler_Activity
 *END**************************************************************************/
void eTMR_DRV_InputCaptureHandler(uint32_t instance, uint8_t channel)
{
    DEV_ASSERT(instance < eTMR_INSTANCE_COUNT);
    DEV_ASSERT(channel < g_etmrChannelNum[instance]);

    eTMR_Type *etmrBase = g_etmrBase[instance];
    etmr_state_t *state = etmrStatePtr[instance];

    if (state->measurementType[channel] == eTMR_PERIOD_MEASUREMENT)
    {
        /* Get positive and negative pulse counts */
        if (eTMR_DRV_GetChnPosPulseRdyFlag(instance, channel) == true &&
            eTMR_DRV_GetChnNegPulseRdyFlag(instance, channel) == true)
        {
            state->measurementPosPulseCnt[channel] = eTMR_GetChnPosPulseWidthCapVal(etmrBase, channel) +
                                                     eTMR_GetChnPosPulseCntPeriodNum(etmrBase, channel) * state->etmrModValue;
            state->measurementNegPulseCnt[channel] = eTMR_GetChnNegPulseWidthCapVal(etmrBase, channel) +
                                                     eTMR_GetChnNegPulseCntPeriodNum(etmrBase, channel) * state->etmrModValue;
            state->measurementPeriod[channel] = state->measurementPosPulseCnt[channel] + state->measurementNegPulseCnt[channel];
            eTMR_DRV_ClearChnNegPulseRdyFlag(instance, channel);
            eTMR_DRV_ClearChnPosPulseRdyFlag(instance, channel);
            state->measurementComplete[channel] = true;
        }
    }
    else if (state->measurementType[channel] == eTMR_POS_PULSE_MEASUREMENT)
    {
        if (eTMR_DRV_GetChnPosPulseRdyFlag(instance, channel) == true)
        {
            state->measurementPosPulseCnt[channel] = eTMR_GetChnPosPulseWidthCapVal(etmrBase, channel) +
                                                     eTMR_GetChnPosPulseCntPeriodNum(etmrBase, channel) * state->etmrModValue;
            eTMR_DRV_ClearChnPosPulseRdyFlag(instance, channel);
            state->measurementComplete[channel] = true;
        }
    }
    else // eTMR_NEG_PULSE_MEASUREMENT
    {
        if (eTMR_DRV_GetChnNegPulseRdyFlag(instance, channel) == true)
        {
            state->measurementNegPulseCnt[channel] = eTMR_GetChnNegPulseWidthCapVal(etmrBase, channel) +
                                                     eTMR_GetChnNegPulseCntPeriodNum(etmrBase, channel) * state->etmrModValue;
            eTMR_DRV_ClearChnNegPulseRdyFlag(instance, channel);
            state->measurementComplete[channel] = true;
        }
    }

    /* If the callback is defined to use it */
    if ((state->channelsCallbacks[channel] != NULL) && (state->enableNotification[channel] == true))
    {
        state->channelsCallbacks[channel](IC_EVENT_MEASUREMENT_COMPLETE, state->channelsCallbacksParams[channel]);
    }
}
#elif FEATURE_eTMR_HAS_COMBINATION_CAPTURE
/*FUNCTION**********************************************************************
 *
 * Function Name : eTMR_DRV_InputCaptureHandler
 * Description   : This function is used to calculate measurement for input capture.
 *
 * Implements    : eTMR_DRV_InputCaptureHandler_Activity
 *END**************************************************************************/
void eTMR_DRV_InputCaptureHandler(uint32_t instance, uint8_t channel)
{
    DEV_ASSERT(instance < eTMR_INSTANCE_COUNT);
    DEV_ASSERT(channel < g_etmrChannelNum[instance]);
    uint32_t temp = 0;
    etmr_state_t *state = etmrStatePtr[instance];
    eTMR_Type *base = g_etmrBase[instance];

    if (state->measurementType[channel] == eTMR_PERIOD_MEASUREMENT)
    {
        /* no combine, hold and interrupt is enabled */
        if (state->icCnt[channel] == 0)
        {
            state->measurementCapCnt[channel] = eTMR_GetChnCapVal(base, channel);
            state->icCnt[channel]++;
        }
        else
        {
            temp = eTMR_GetChnCapVal(base, channel);
            if (temp > state->measurementCapCnt[channel])
            {
                state->measurementPeriod[channel] = temp - state->measurementCapCnt[channel];
            }
            else
            {
                state->measurementPeriod[channel] = 0xFFFFU - state->measurementCapCnt[channel] + temp;
            }
            state->measurementComplete[channel] = true;
            state->icCnt[channel] = 0;
        }
    }
    else
    {
        /* combine source from even channel */
        if (channel % 2 == 0)
        {
            if (eTMR_DRV_GetChnFlag(instance, channel) == 0)
            {
                state->measurementCapCnt[channel] = eTMR_GetChnCapVal(base, channel);
            }
            else
            {
                // even channel is configured as rising edge capture, and hold is true, interrupt is false.
                // odd channel is configured as falling edge capture, and hold is true, interrupt is true.
                if (state->measurementType[channel] == eTMR_POS_PULSE_MEASUREMENT)
                {
                    state->measurementPosPulseCnt[channel] = eTMR_GetChnCapVal(base, channel + 1) - eTMR_GetChnCapVal(base, channel);
                }
                else
                // even channel is configured as falling edge capture, and hold is true, interrupt is false.
                // odd channel is configured as rising edge capture, and hold is true, interrupt is true.
                {
                    state->measurementNegPulseCnt[channel] = eTMR_GetChnCapVal(base, channel + 1) - eTMR_GetChnCapVal(base, channel);
                }
                state->measurementComplete[channel] = true;
            }
        }
        else /* combine source from odd channel */
        {
            if (eTMR_DRV_GetChnFlag(instance, channel - 1) == 0)
            {
                state->measurementCapCnt[channel] = eTMR_GetChnCapVal(base, channel);
            }
            else
            {
                // even channel is configured as rising edge capture, and hold is true, interrupt is false.
                // odd channel is configured as falling edge capture, and hold is true, interrupt is true.
                if (state->measurementType[channel] == eTMR_POS_PULSE_MEASUREMENT)
                {
                    state->measurementPosPulseCnt[channel] = eTMR_GetChnCapVal(base, channel) - eTMR_GetChnCapVal(base, channel - 1);
                }
                // even channel is configured as falling edge capture, and hold is true, interrupt is false.
                // odd channel is configured as rising edge capture, and hold is true, interrupt is true.
                else
                {
                    state->measurementNegPulseCnt[channel] = eTMR_GetChnCapVal(base, channel) - eTMR_GetChnCapVal(base, channel - 1);
                }
                state->measurementComplete[channel] = true;
            }
        }
    }

    /* If the callback is defined to use it */
    if ((state->channelsCallbacks[channel] != NULL) && (state->enableNotification[channel] == true))
    {
        state->channelsCallbacks[channel](IC_EVENT_MEASUREMENT_COMPLETE, state->channelsCallbacksParams[channel]);
    }
}
#else
/*FUNCTION**********************************************************************
 *
 * Function Name : eTMR_DRV_InputCaptureHandler
 * Description   : This function is used to calculate measurement for input capture.
 *
 * Implements    : eTMR_DRV_InputCaptureHandler_Activity
 *END**************************************************************************/
void eTMR_DRV_InputCaptureHandler(uint32_t instance, uint8_t channel)
{
    DEV_ASSERT(instance < eTMR_INSTANCE_COUNT);
    DEV_ASSERT(channel < g_etmrChannelNum[instance]);
    etmr_state_t *state = etmrStatePtr[instance];
    eTMR_Type *etmrBase = g_etmrBase[instance];

    /* This branch is used to capture signal period and duty of the pwm signal */
    if (state->measurementType[channel] == eTMR_PERIOD_MEASUREMENT)
    {
        /* Get capture value */
        state->icCntVal[channel][state->icCnt[channel]] = eTMR_GetChnCapVal(etmrBase, channel);
        /* Get io status */
        state->icCapPol[channel][state->icCnt[channel]] = eTMR_DRV_GetChnIoStatus(instance, channel);
        /* Get current overflow count */
        state->icOvfCnt[channel][state->icCnt[channel]] = state->icOvfCntTemp[channel];

        /* Use dual edges capture method to measure period */
        if (state->captureEdge[channel] == eTMR_DUAL_EDGES)
        {
            /* Capture three edges, when capture count is equal to 3, capture complete */
            if (state->icCnt[channel] < 2)
            {
                state->icCnt[channel]++;
            }
            else
            {
                state->measurementComplete[channel] = true;
                state->icCnt[channel] = 0;
                state->icOvfCntTemp[channel] = 0;
            }
        }
        else /* Use positive edge or negative edge capture method to measure period */
        {
            /* Capture two edges, when capture count is equal to 2, capture complete */
            if (state->icCnt[channel] < 1)
            {
                state->icCnt[channel]++;
            }
            else
            {
                state->measurementComplete[channel] = true;
                state->icCnt[channel] = 0;
                state->icOvfCntTemp[channel] = 0;
            }
        }
    }
    else /* Measure one positive pulse or one negative pulse */
    {
        /* When capturing one positive pulse or one negative pulse, it is necessary to use dual edges capture */
        if (state->captureEdge[channel] == eTMR_DUAL_EDGES)
        {
            state->icCapPol[channel][state->icCnt[channel]] = eTMR_DRV_GetChnIoStatus(instance, channel);
            state->icCntVal[channel][state->icCnt[channel]] = eTMR_GetChnCapVal(etmrBase, channel);
            state->icOvfCnt[channel][state->icCnt[channel]] = state->icOvfCntTemp[channel];
            /* When capture count is equal to 2, capture complete */
            if (state->icCnt[channel] < 1)
            {
                state->icCnt[channel]++;
            }
            else
            {
                state->measurementComplete[channel] = true;
                state->icCnt[channel] = 0;
                state->icOvfCntTemp[channel] = 0;
            }
        }
    }

    /* Re-update MOD value */
    state->etmrModValue = eTMR_GetMod(etmrBase);

    /* If the callback is defined to use it */
    if ((state->channelsCallbacks[channel] != NULL) && (state->enableNotification[channel] == true))
    {
        state->channelsCallbacks[channel](IC_EVENT_MEASUREMENT_COMPLETE, state->channelsCallbacksParams[channel]);
    }
}

/*FUNCTION**********************************************************************
 *
 * Function Name : eTMR_DRV_CalculateChannelCaptureValue
 * Description   : This function is used to calculate period, positive pulse or
                   negative pulse count for each channel. When measurementType is 
                   eTMR_PERIOD_MEASUREMENT and captureEdge is eTMR_DUAL_EDGES,
                   period, positive pulse width and negative pulse width can be 
                   measured. When measurementType is eTMR_PERIOD_MEASUREMENT and
                   captureEdge is eTMR_POS_EDGE or eTMR_NEG_EDGE, period can be
                   measured. When measurementType is eTMR_POS_PULSE_MEASUREMENT
                   or eTMR_NEG_PULSE_MEASUREMENT, positive pulse width or negative
                   pulse width can be measured. It is necessary to use dual edges
                   capture method to measure positive pulse width or negative pulse
                   width.
 *
 * Implements    : eTMR_DRV_CalculateChannelCaptureValue_Activity
 *END**************************************************************************/
void eTMR_DRV_CalculateChannelCaptureValue(uint32_t instance, uint8_t channel)
{
    DEV_ASSERT(instance < eTMR_INSTANCE_COUNT);
    DEV_ASSERT(channel < g_etmrChannelNum[instance]);
    etmr_state_t *state = etmrStatePtr[instance];

    if (state->measurementType[channel] == eTMR_PERIOD_MEASUREMENT)
    {
        if (state->captureEdge[channel] == eTMR_DUAL_EDGES)
        {
            /* Process the first pulse */
            /* When first capture value is greater than the second capture value, overflow count is 1 at least, so if overflow n times,
             * it needs to add (n-1)*mod. */
            if (state->icCntVal[channel][0] > state->icCntVal[channel][1])
            {
                state->measurementCapCnt[channel] = state->icCntVal[channel][1] + 
                                                    (state->etmrModValue - state->icCntVal[channel][0]) +
                                                    state->etmrModValue * (state->icOvfCnt[channel][1] - state->icOvfCnt[channel][0] - 1);
            }
            else /* When first capture value is less than the second capture value, if overflow n times, need to add n*mod */
            {
                state->measurementCapCnt[channel] = state->icCntVal[channel][1] - 
                                                    state->icCntVal[channel][0] +
                                                    state->etmrModValue * (state->icOvfCnt[channel][1] - state->icOvfCnt[channel][0]);
            }

            /* When the first capture polarity is high, it means that the edge is positive edge, so pulse is positive pulse */
            if (state->icCapPol[channel][0] == 1)
            {
                state->measurementPosPulseCnt[channel] = state->measurementCapCnt[channel];
            }
            else /* if first capture polarity is low, it means that the edge is negative edge, so pulse is negative pulse */
            {
                state->measurementNegPulseCnt[channel] = state->measurementCapCnt[channel];
            }

            /* Process the second pulse */
            if (state->icCntVal[channel][1] > state->icCntVal[channel][2])
            {
                state->measurementCapCnt[channel] = state->icCntVal[channel][2] + 
                                                    (state->etmrModValue - state->icCntVal[channel][1]) +
                                                    state->etmrModValue * (state->icOvfCnt[channel][2] - state->icOvfCnt[channel][1] - 1);
            }
            else
            {
                state->measurementCapCnt[channel] = state->icCntVal[channel][2] - 
                                                    state->icCntVal[channel][1] +
                                                    state->etmrModValue * (state->icOvfCnt[channel][2] - state->icOvfCnt[channel][1]);
            }

            if (state->icCapPol[channel][1] == 1)
            {
                state->measurementPosPulseCnt[channel] = state->measurementCapCnt[channel];
            }
            else
            {
                state->measurementNegPulseCnt[channel] = state->measurementCapCnt[channel];
            }

            /* Calculate the period of signal according to positive pulse and negative pulse */
            state->measurementPeriod[channel] = state->measurementPosPulseCnt[channel] + 
                                                state->measurementNegPulseCnt[channel];
        }
        else /* eTMR_NEG_EDGE eTMR_POS_EDGE */
        {
            /* Use positive or negative edge to measure period, just need two edge capture value */
            if (state->icCntVal[channel][0] > state->icCntVal[channel][1])
            {
                state->measurementPeriod[channel] = state->icCntVal[channel][1] + 
                                                    (state->etmrModValue - state->icCntVal[channel][0]) +
                                                    state->etmrModValue * (state->icOvfCnt[channel][1] - state->icOvfCnt[channel][0] - 1);
            }
            else
            {
                state->measurementPeriod[channel] = state->icCntVal[channel][1] - 
                                                    state->icCntVal[channel][0] +
                                                    state->etmrModValue * (state->icOvfCnt[channel][1] - state->icOvfCnt[channel][0]);
            }
        }
    }
    else /* Capture one positive pulse or one negative pulse */
    {
        if (state->captureEdge[channel] == eTMR_DUAL_EDGES)
        {
            /* When first capture value is greater than the second capture value, overflow count is 1 at least, so if overflow n times,
             * it needs to add (n-1)*mod. */
            if (state->icCntVal[channel][0] > state->icCntVal[channel][1])
            {
                state->measurementCapCnt[channel] = state->icCntVal[channel][1] + 
                                                    (state->etmrModValue - state->icCntVal[channel][0]) +
                                                    state->etmrModValue * (state->icOvfCnt[channel][1] - state->icOvfCnt[channel][0] - 1);
            }
            /* When first capture value is less than the second capture value, overflow count is 0 at least, so if overflow n times,
               it needs to add n*mod */
            else
            {
                state->measurementCapCnt[channel] = state->icCntVal[channel][1] - 
                                                    state->icCntVal[channel][0] +
                                                    state->etmrModValue * (state->icOvfCnt[channel][1] - state->icOvfCnt[channel][0]);
            }

            /* According to the first capture polarity, determine positive pulse or negative pulse */
            if (state->icCapPol[channel][0] == 1)
            {
                state->measurementPosPulseCnt[channel] = state->measurementCapCnt[channel];
            }
            else
            {
                state->measurementNegPulseCnt[channel] = state->measurementCapCnt[channel];
            }
        }
    }
}
#endif

/*******************************************************************************
* EOF
******************************************************************************/
