/*
* Copyright (c) 2023-2028, SpaceTouch Inc.
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date          Author      Notes
* 2023-07-18    zhixiongl       the first version
*/


#include <stdio.h>
#include <stdarg.h>

#include "platform.h"
#include "hal_log.h"
#include "hal_pwm.h"
#include "hal_gpio.h"
#include "hal_common.h"
#include "hal_cmu.h"
//#include "board.h"


//---------------------------------------------------duty mode correlation function---------------------start--------------
/**
* @brief        dutymode_config
* @details
* @param[in]    pwm_port
* @param[in]    pwm_dutymode_init
* @return       None
* @note         None
*/
void hal_pwm_dutymode_config(pwm_port_t pwm_port, pwm_dutymode_init_t *pwm_dutymode_init)
{
    uint32_t reg_value;
    reg_value = pwm_dutymode_init->mode
                | (((pwm_dutymode_init->period_cycles - 1) << 8) & DEV_PWM_CTL_DutyMode_LEN_MASK)
                | ((pwm_dutymode_init->duty_cycles << 16) & DEV_PWM_CTL_DutyMode_DUTY_MASK)
                | ((pwm_dutymode_init->pending_number << 26) & DEV_PWM_CTL_DutyMode_NUM_MASK);

    if (pwm_port == PWM0)
    {
        DEV_PWM->CTL[0] = reg_value;
    }

    if (pwm_port == PWM1)
    {
        DEV_PWM->CTL[1] = reg_value;
    }

    if (pwm_port == PWM2)
    {
        DEV_PWM->CTL[2] = reg_value;
    }

    if (pwm_port == PWM3)
    {
        DEV_PWM->CTL[3] = reg_value;
    }

    if (pwm_port == PWM4)
    {
        DEV_PWM->CTL[4] = reg_value;
    }

    if (pwm_port == PWM5)
    {
        DEV_PWM->CTL[5] = reg_value;
    }

    if (pwm_port == PWM6)
    {
        DEV_PWM->CTL[6] = reg_value;
    }

    if (pwm_port == PWM7)
    {
        DEV_PWM->CTL[7] = reg_value;
    }
}

/**
* @brief        set period cycles
* @details
* @param[in]    pwm_port
* @param[in]    period_cycles
                    scope: 0~255
* @return       None
* @note         None
*/
void hal_pwm_set_periodcycles(pwm_port_t pwm_port, uint32_t period_cycles)
{
    uint32_t reg_value;
    HAL_PWM_LOG("period_cycles: %d\n", period_cycles);
    reg_value = ((uint32_t)(period_cycles - 1) << 8) & DEV_PWM_CTL_DutyMode_LEN_MASK;

    if (pwm_port == PWM0)
    {
        DEV_PWM->CTL[0] &= ~DEV_PWM_CTL_DutyMode_LEN_MASK;
        DEV_PWM->CTL[0] |= reg_value;
    }

    if (pwm_port == PWM1)
    {
        DEV_PWM->CTL[1] &= ~DEV_PWM_CTL_DutyMode_LEN_MASK;
        DEV_PWM->CTL[1] |= reg_value;
    }

    if (pwm_port == PWM2)
    {
        DEV_PWM->CTL[2] &= ~DEV_PWM_CTL_DutyMode_LEN_MASK;
        DEV_PWM->CTL[2] |= reg_value;
    }

    if (pwm_port == PWM3)
    {
        DEV_PWM->CTL[3] &= ~DEV_PWM_CTL_DutyMode_LEN_MASK;
        DEV_PWM->CTL[3] |= reg_value;
    }

    if (pwm_port == PWM4)
    {
        DEV_PWM->CTL[4] &= ~DEV_PWM_CTL_DutyMode_LEN_MASK;
        DEV_PWM->CTL[4] |= reg_value;
    }

    if (pwm_port == PWM5)
    {
        DEV_PWM->CTL[5] &= ~DEV_PWM_CTL_DutyMode_LEN_MASK;
        DEV_PWM->CTL[5] |= reg_value;
    }

    if (pwm_port == PWM6)
    {
        DEV_PWM->CTL[6] &= ~DEV_PWM_CTL_DutyMode_LEN_MASK;
        DEV_PWM->CTL[6] |= reg_value;
    }

    if (pwm_port == PWM7)
    {
        DEV_PWM->CTL[7] &= ~DEV_PWM_CTL_DutyMode_LEN_MASK;
        DEV_PWM->CTL[7] |= reg_value;
    }
}

/**
* @brief        get period cycles
* @details
* @param[in]    pwm_port
* @return       period_cycles
* @note         None
*/
uint32_t hal_pwm_get_periodcycles(pwm_port_t pwm_port)
{
    uint32_t reg_value = 0;
    uint32_t period_cycles;

    if (pwm_port == PWM0)
    {
        reg_value = DEV_PWM->CTL[0];
    }

    if (pwm_port == PWM1)
    {
        reg_value = DEV_PWM->CTL[1];
    }

    if (pwm_port == PWM2)
    {
        reg_value = DEV_PWM->CTL[2];
    }

    if (pwm_port == PWM3)
    {
        reg_value = DEV_PWM->CTL[3];
    }

    if (pwm_port == PWM4)
    {
        reg_value = DEV_PWM->CTL[4];
    }

    if (pwm_port == PWM5)
    {
        reg_value = DEV_PWM->CTL[5];
    }

    if (pwm_port == PWM6)
    {
        reg_value = DEV_PWM->CTL[6];
    }

    if (pwm_port == PWM7)
    {
        reg_value = DEV_PWM->CTL[7];
    }

    period_cycles = ((reg_value & DEV_PWM_CTL_DutyMode_LEN_MASK) >> 8) + 1;
    return period_cycles;
}

/**
* @brief        set duty cycles
* @details
* @param[in]    pwm_port
* @param[in]    duty_cycles
                    scope: 0~255
* @return       None
* @note         None
*/
void hal_pwm_set_dutycycles(pwm_port_t pwm_port, uint32_t duty_cycles)
{
    uint32_t reg_value;
    HAL_PWM_LOG("period_cycles: %d\n", duty_cycles);
    reg_value = ((uint32_t)duty_cycles << 16) & DEV_PWM_CTL_DutyMode_DUTY_MASK;

    if (pwm_port == PWM0)
    {
        DEV_PWM->CTL[0] &= ~DEV_PWM_CTL_DutyMode_DUTY_MASK;
        DEV_PWM->CTL[0] |= reg_value;
    }

    if (pwm_port == PWM1)
    {
        DEV_PWM->CTL[1] &= ~DEV_PWM_CTL_DutyMode_DUTY_MASK;
        DEV_PWM->CTL[1] |= reg_value;
    }

    if (pwm_port == PWM2)
    {
        DEV_PWM->CTL[2] &= ~DEV_PWM_CTL_DutyMode_DUTY_MASK;
        DEV_PWM->CTL[2] |= reg_value;
    }

    if (pwm_port == PWM3)
    {
        DEV_PWM->CTL[3] &= ~DEV_PWM_CTL_DutyMode_DUTY_MASK;
        DEV_PWM->CTL[3] |= reg_value;
    }

    if (pwm_port == PWM4)
    {
        DEV_PWM->CTL[4] &= ~DEV_PWM_CTL_DutyMode_DUTY_MASK;
        DEV_PWM->CTL[4] |= reg_value;
    }

    if (pwm_port == PWM5)
    {
        DEV_PWM->CTL[5] &= ~DEV_PWM_CTL_DutyMode_DUTY_MASK;
        DEV_PWM->CTL[5] |= reg_value;
    }

    if (pwm_port == PWM6)
    {
        DEV_PWM->CTL[6] &= ~DEV_PWM_CTL_DutyMode_DUTY_MASK;
        DEV_PWM->CTL[6] |= reg_value;
    }

    if (pwm_port == PWM7)
    {
        DEV_PWM->CTL[7] &= ~DEV_PWM_CTL_DutyMode_DUTY_MASK;
        DEV_PWM->CTL[7] |= reg_value;
    }
}


/**
* @brief        get duty cycles
* @details
* @param[in]    pwm_port
* @return       duty_cycles
* @note         None
*/
uint32_t hal_pwm_get_dutycycles(pwm_port_t pwm_port)
{
    uint32_t reg_value = 0;
    uint32_t duty_cycles;

    if (pwm_port == PWM0)
    {
        reg_value = DEV_PWM->CTL[0];
    }

    if (pwm_port == PWM1)
    {
        reg_value = DEV_PWM->CTL[1];
    }

    if (pwm_port == PWM2)
    {
        reg_value = DEV_PWM->CTL[2];
    }

    if (pwm_port == PWM3)
    {
        reg_value = DEV_PWM->CTL[3];
    }

    if (pwm_port == PWM4)
    {
        reg_value = DEV_PWM->CTL[4];
    }

    if (pwm_port == PWM5)
    {
        reg_value = DEV_PWM->CTL[5];
    }

    if (pwm_port == PWM6)
    {
        reg_value = DEV_PWM->CTL[6];
    }

    if (pwm_port == PWM7)
    {
        reg_value = DEV_PWM->CTL[7];
    }

    duty_cycles = (reg_value & DEV_PWM_CTL_DutyMode_DUTY_MASK) >> 16;
    return duty_cycles;
}

/**
* @brief        set pendingnum
* @details
* @param[in]    pwm_port
* @param[in]    pending_num
                    scope: 0~63
* @return       None
* @note         None
*/
void hal_pwm_set_pendingnum(pwm_port_t pwm_port, uint32_t pending_num)
{
    uint32_t reg_value;
    reg_value = ((uint32_t)pending_num << 26) & DEV_PWM_CTL_DutyMode_NUM_MASK;

    if (pwm_port == PWM0)
    {
        DEV_PWM->CTL[0] &= ~DEV_PWM_CTL_DutyMode_NUM_MASK;
        DEV_PWM->CTL[0] |= reg_value;
    }

    if (pwm_port == PWM1)
    {
        DEV_PWM->CTL[1] &= ~DEV_PWM_CTL_DutyMode_NUM_MASK;
        DEV_PWM->CTL[1] |= reg_value;
    }

    if (pwm_port == PWM2)
    {
        DEV_PWM->CTL[2] &= ~DEV_PWM_CTL_DutyMode_NUM_MASK;
        DEV_PWM->CTL[2] |= reg_value;
    }

    if (pwm_port == PWM3)
    {
        DEV_PWM->CTL[3] &= ~DEV_PWM_CTL_DutyMode_NUM_MASK;
        DEV_PWM->CTL[3] |= reg_value;
    }

    if (pwm_port == PWM4)
    {
        DEV_PWM->CTL[4] &= ~DEV_PWM_CTL_DutyMode_NUM_MASK;
        DEV_PWM->CTL[4] |= reg_value;
    }

    if (pwm_port == PWM5)
    {
        DEV_PWM->CTL[5] &= ~DEV_PWM_CTL_DutyMode_NUM_MASK;
        DEV_PWM->CTL[5] |= reg_value;
    }

    if (pwm_port == PWM6)
    {
        DEV_PWM->CTL[6] &= ~DEV_PWM_CTL_DutyMode_NUM_MASK;
        DEV_PWM->CTL[6] |= reg_value;
    }

    if (pwm_port == PWM7)
    {
        DEV_PWM->CTL[7] &= ~DEV_PWM_CTL_DutyMode_NUM_MASK;
        DEV_PWM->CTL[7] |= reg_value;
    }
}

//---------------------------------------------------duty mode correlation function---------------------end--------------
//---------------------------------------------------breath mode correlation function---------------------start--------------
/**
* @brief        breathmode_config
* @details
* @param[in]    pwm_port
* @param[in]    pwm_breathmode_init
* @return       None
* @note         None
*/
void hal_pwm_breathmode_config(pwm_port_t pwm_port, pwm_breathmode_init_t *pwm_breathmode_init)
{
    uint32_t reg_value;
    reg_value = pwm_breathmode_init->mode
                | (((pwm_breathmode_init->high_cycles - 1) << 24) & DEV_PWM_CTL_BreathMode_HNUM_MASK)
                | (((pwm_breathmode_init->low_cycles - 1) << 16) & DEV_PWM_CTL_BreathMode_LNUM_MASK)
                | (((pwm_breathmode_init->rise_fall_cycles - 1) << 4) & DEV_PWM_CTL_BreathMode_QNUM_MASK);

    if (pwm_port == PWM0)
    {
        DEV_PWM->CTL[0] = reg_value;
    }

    if (pwm_port == PWM1)
    {
        DEV_PWM->CTL[1] = reg_value;
    }

    if (pwm_port == PWM2)
    {
        DEV_PWM->CTL[2] = reg_value;
    }

    if (pwm_port == PWM3)
    {
        DEV_PWM->CTL[3] = reg_value;
    }

    if (pwm_port == PWM4)
    {
        DEV_PWM->CTL[4] = reg_value;
    }

    if (pwm_port == PWM5)
    {
        DEV_PWM->CTL[5] = reg_value;
    }

    if (pwm_port == PWM6)
    {
        DEV_PWM->CTL[6] = reg_value;
    }

    if (pwm_port == PWM7)
    {
        DEV_PWM->CTL[7] = reg_value;
    }
}

/**
* @brief        set high cycles
* @details
* @param[in]    pwm_port
* @param[in]    high_cycles
                    scope: 0~255
* @return       None
* @note         None
*/
void hal_pwm_set_highcycles(pwm_port_t pwm_port, uint16_t high_cycles)
{
    uint32_t reg_value;
    reg_value = ((uint32_t)(high_cycles - 1) << 24) & DEV_PWM_CTL_BreathMode_HNUM_MASK;

    if (pwm_port == PWM0)
    {
        DEV_PWM->CTL[0] &= ~DEV_PWM_CTL_BreathMode_HNUM_MASK;
        DEV_PWM->CTL[0] |= reg_value;
    }

    if (pwm_port == PWM1)
    {
        DEV_PWM->CTL[1] &= ~DEV_PWM_CTL_BreathMode_HNUM_MASK;
        DEV_PWM->CTL[1] |= reg_value;
    }

    if (pwm_port == PWM2)
    {
        DEV_PWM->CTL[2] &= ~DEV_PWM_CTL_BreathMode_HNUM_MASK;
        DEV_PWM->CTL[2] |= reg_value;
    }

    if (pwm_port == PWM3)
    {
        DEV_PWM->CTL[3] &= ~DEV_PWM_CTL_BreathMode_HNUM_MASK;
        DEV_PWM->CTL[3] |= reg_value;
    }

    if (pwm_port == PWM4)
    {
        DEV_PWM->CTL[4] &= ~DEV_PWM_CTL_BreathMode_HNUM_MASK;
        DEV_PWM->CTL[4] |= reg_value;
    }

    if (pwm_port == PWM5)
    {
        DEV_PWM->CTL[5] &= ~DEV_PWM_CTL_BreathMode_HNUM_MASK;
        DEV_PWM->CTL[5] |= reg_value;
    }

    if (pwm_port == PWM6)
    {
        DEV_PWM->CTL[6] &= ~DEV_PWM_CTL_BreathMode_HNUM_MASK;
        DEV_PWM->CTL[6] |= reg_value;
    }

    if (pwm_port == PWM7)
    {
        DEV_PWM->CTL[7] &= ~DEV_PWM_CTL_BreathMode_HNUM_MASK;
        DEV_PWM->CTL[7] |= reg_value;
    }
}

/**
* @brief        set low cycles
* @details
* @param[in]    pwm_port
* @param[in]    low_cycles
                    scope: 0~255
* @return       None
* @note         None
*/
void hal_pwm_set_lowcycles(pwm_port_t pwm_port, uint16_t low_cycles)
{
    uint32_t reg_value;
    reg_value = ((uint32_t)(low_cycles - 1) << 16) & DEV_PWM_CTL_BreathMode_LNUM_MASK;

    if (pwm_port == PWM0)
    {
        DEV_PWM->CTL[0] &= ~DEV_PWM_CTL_BreathMode_LNUM_MASK;
        DEV_PWM->CTL[0] |= reg_value;
    }

    if (pwm_port == PWM1)
    {
        DEV_PWM->CTL[1] &= ~DEV_PWM_CTL_BreathMode_LNUM_MASK;
        DEV_PWM->CTL[1] |= reg_value;
    }

    if (pwm_port == PWM2)
    {
        DEV_PWM->CTL[2] &= ~DEV_PWM_CTL_BreathMode_LNUM_MASK;
        DEV_PWM->CTL[2] |= reg_value;
    }

    if (pwm_port == PWM3)
    {
        DEV_PWM->CTL[3] &= ~DEV_PWM_CTL_BreathMode_LNUM_MASK;
        DEV_PWM->CTL[3] |= reg_value;
    }

    if (pwm_port == PWM4)
    {
        DEV_PWM->CTL[4] &= ~DEV_PWM_CTL_BreathMode_LNUM_MASK;
        DEV_PWM->CTL[4] |= reg_value;
    }

    if (pwm_port == PWM5)
    {
        DEV_PWM->CTL[5] &= ~DEV_PWM_CTL_BreathMode_LNUM_MASK;
        DEV_PWM->CTL[5] |= reg_value;
    }

    if (pwm_port == PWM6)
    {
        DEV_PWM->CTL[6] &= ~DEV_PWM_CTL_BreathMode_LNUM_MASK;
        DEV_PWM->CTL[6] |= reg_value;
    }

    if (pwm_port == PWM7)
    {
        DEV_PWM->CTL[7] &= ~DEV_PWM_CTL_BreathMode_LNUM_MASK;
        DEV_PWM->CTL[7] |= reg_value;
    }
}

/**
* @brief        set risefall cycles
* @details      The number cycles from 0 to 100% and from 100% to 0(Real Number is 32 * (set+1))
* @param[in]    pwm_port
* @param[in]    rise_fall_cycles
                    scope: 0~15
* @return       None
* @note         None
*/
void hal_pwm_set_risefallcycles(pwm_port_t pwm_port, uint8_t rise_fall_cycles)
{
    uint32_t reg_value;
    reg_value = ((uint32_t)(rise_fall_cycles - 1) << 4) & DEV_PWM_CTL_BreathMode_QNUM_MASK;

    if (pwm_port == PWM0)
    {
        DEV_PWM->CTL[0] &= ~DEV_PWM_CTL_BreathMode_QNUM_MASK;
        DEV_PWM->CTL[0] |= reg_value;
    }

    if (pwm_port == PWM1)
    {
        DEV_PWM->CTL[1] &= ~DEV_PWM_CTL_BreathMode_QNUM_MASK;
        DEV_PWM->CTL[1] |= reg_value;
    }

    if (pwm_port == PWM2)
    {
        DEV_PWM->CTL[2] &= ~DEV_PWM_CTL_BreathMode_QNUM_MASK;
        DEV_PWM->CTL[2] |= reg_value;
    }

    if (pwm_port == PWM3)
    {
        DEV_PWM->CTL[3] &= ~DEV_PWM_CTL_BreathMode_QNUM_MASK;
        DEV_PWM->CTL[3] |= reg_value;
    }

    if (pwm_port == PWM4)
    {
        DEV_PWM->CTL[4] &= ~DEV_PWM_CTL_BreathMode_QNUM_MASK;
        DEV_PWM->CTL[4] |= reg_value;
    }

    if (pwm_port == PWM5)
    {
        DEV_PWM->CTL[5] &= ~DEV_PWM_CTL_BreathMode_QNUM_MASK;
        DEV_PWM->CTL[5] |= reg_value;
    }

    if (pwm_port == PWM6)
    {
        DEV_PWM->CTL[6] &= ~DEV_PWM_CTL_BreathMode_QNUM_MASK;
        DEV_PWM->CTL[6] |= reg_value;
    }

    if (pwm_port == PWM7)
    {
        DEV_PWM->CTL[7] &= ~DEV_PWM_CTL_BreathMode_QNUM_MASK;
        DEV_PWM->CTL[7] |= reg_value;
    }
}
//-----------------------------------------------------------------breath mode correlation function---------------------end--------------
//-----------------------------------------------------------------soft mode correlation function---------------------start--------------
/**
* @brief        softmode_config
* @details
* @param[in]    pwm_port
* @param[in]    pwm_softmode_init
* @return       None
* @note         only pwm0 and pwm2 additionally have the soft mode and the pdm mode
*/
void hal_pwm_softmode_config(pwm_port_t pwm_port, pwm_softmode_init_t *pwm_softmode_init)
{
    uint32_t reg_value;
    reg_value = pwm_softmode_init->mode
                | ((pwm_softmode_init->idle_out_enable << 31) & DEV_PWM_CTL_SoftMode_OUT_SET)
                | ((pwm_softmode_init->idle_out_value << 28) & DEV_PWM_CTL_SoftMode_OUT_VAL_MASK)
                | ((pwm_softmode_init->modulate_enable << 26) & DEV_PWM_CTL_SoftMode_MOD_OUT)
                | ((pwm_softmode_init->clk_out_enable << 25) & DEV_PWM_CTL_SoftMode_CLK_OUT)
                | ((pwm_softmode_init->signed_format << 24) & DEV_PWM_CTL_SoftMode_SGN_FMT_MASK)
                | ((pwm_softmode_init->out_format << 22)&DEV_PWM_CTL_SoftMode_OUT_FMT_MASK)
                | ((pwm_softmode_init->data_len_format << 15) & DEV_PWM_CTL_SoftMode_LEN_MASK)
                | ((pwm_softmode_init->fifo_empty_active << 14) & DEV_PWM_CTL_SoftMode_FIFO_CONT_MASK)
                | ((pwm_softmode_init->data_place_format << 12) & DEV_PWM_CTL_SoftMode_FMT_MASK)
                | ((pwm_softmode_init->data_repeat << 8) & DEV_PWM_CTL_SoftMode_RPT_MASK)
                | ((pwm_softmode_init->data_width_format << 4) & DEV_PWM_CTL_SoftMode_WIDTH_MASK);

    if (pwm_port == PWM0)
    {
        DEV_PWM->CTL[0] = reg_value;
    }

    if (pwm_port == PWM2)
    {
        DEV_PWM->CTL[2] = reg_value;
    }
}
//-----------------------------------------------------------------soft mode correlation function---------------------end--------------
//-----------------------------------------------------------------pdm mode correlation function---------------------start--------------
/**
* @brief        pdmmode_config
* @details
* @param[in]    pwm_port
* @param[in]    pwm_pdmmode_init
* @return       None
* @note         only pwm0 and pwm2 additionally have the soft mode and the pdm mode
*/
void hal_pwm_pdmmode_config(pwm_port_t pwm_port, pwm_pdmmode_init_t *pwm_pdmmode_init)
{
    uint32_t reg_value;
    reg_value = pwm_pdmmode_init->mode
                | ((pwm_pdmmode_init->fifo_empty_active << 14) & DEV_PWM_CTL_PDMMode_FIFO_CONT_MASK);

    if (pwm_port == PWM0)
    {
        DEV_PWM->CTL[0] = reg_value;
    }

    if (pwm_port == PWM2)
    {
        DEV_PWM->CTL[2] = reg_value;
    }
}
//-----------------------------------------------------------------pdm mode correlation function---------------------end--------------
//-----------------------------------------------------------------FIFO correlation function---------------------start--------------
/**
* @brief        Set the fifo threshold
* @details
* @param[in]    pwmX
* @param[in]    threshold
                    scope: 0~16
* @return       None
* @note         Only pwm0 pwm2 software mode and pdm mode exist cache
*/
void hal_pwm_set_fifo_threshold(pwm_port_t pwm_port, uint8_t threshold)
{
    uint32_t reg_value;
    reg_value = ((uint32_t)threshold << 16) & DEV_PWM_CTL_PDMMode_FIFO_THR_MASK;

    if (pwm_port == PWM0)
    {
        DEV_PWM->CTL[0] &= ~DEV_PWM_CTL_PDMMode_FIFO_THR_MASK;
        DEV_PWM->CTL[0] |= reg_value;
    }

    if (pwm_port == PWM2)
    {
        DEV_PWM->CTL[2] &= ~DEV_PWM_CTL_PDMMode_FIFO_THR_MASK;
        DEV_PWM->CTL[2] |= reg_value;
    }
}

/**
* @brief        write data to fifo
* @details
* @param[in]    pwmX
* @param[in]    Data
* @return       None
* @note         Only pwm0 pwm2 software mode and pdm mode exist cache
*/
void hal_pwm_write_fifo_data(pwm_port_t pwm_port, uint32_t data)
{
    if (pwm_port == PWM0)
    {
        DEV_PWM->PWM0_TX_DAT = data;
    }

    if (pwm_port == PWM2)
    {
        DEV_PWM->PWM2_TX_DAT = data;
    }
}
/**
* @brief        reset PWM FIFO
* @details
* @param[in]    pwmX
* @return       None
* @note         The cached data is discarded and the address of the queue goes back to the team.
                Only pwm0 pwm2 software mode and pdm mode exist cache
*/
void hal_pwm_set_fifo_reset(pwm_port_t pwm_port)
{
    if (pwm_port == PWM0)
    {
        DEV_PWM->CTL[0] |= DEV_PWM_CTL_PDMMode_FIFO_RST_MASK;
        DEV_PWM->CTL[0] &= ~DEV_PWM_CTL_PDMMode_FIFO_RST_MASK;
    }

    if (pwm_port == PWM2)
    {
        DEV_PWM->CTL[2] |= DEV_PWM_CTL_PDMMode_FIFO_RST_MASK;
        DEV_PWM->CTL[2] &= ~DEV_PWM_CTL_PDMMode_FIFO_RST_MASK;
    }
}

/**
* @brief        get fifo status
* @details
* @param[in]    pwm_port
* @param[in]    pwm_flag:
                    DEV_PWM_PWM0_STA_WLEVEL_MASK
                    DEV_PWM_PWM0_STA_EMPTY
                    DEV_PWM_PWM0_STA_FULL
* @return       @arg SET
*               @arg RESET
* @note         Only pwm0 and pwm2 software mode and pdm mode exist fifo cache
*/
uint32_t hal_pwm_get_fifo_status(pwm_port_t pwm_port, uint32_t pwm_flag)
{
    uint32_t bitstatus = RESET;

    if (pwm_port == PWM0)
    {
        if (DEV_PWM->PWM0_STA & pwm_flag)
        {
            bitstatus = SET;
        }
        else
        {
            bitstatus = RESET;
        }
    }
    else if (pwm_port == PWM2)
    {
        if (DEV_PWM->PWM2_STA & pwm_flag)
        {
            bitstatus = SET;
        }
        else
        {
            bitstatus = RESET;
        }
    }

    return bitstatus;
}

//-----------------------------------------------------------------FIFO correlation function---------------------end--------------

/**
* @brief        enable or disable the pwm
* @details
* @param[in]    pwm_port
* @param[in]    state:
*                    ENABLE
*                    DISABLE
* @return       None
* @note         None
*/
void hal_pwm_cmd(pwm_port_t pwm_port, uint32_t state)
{
    if (state != DISABLE)
    {
        if (pwm_port == PWM0)
        {
            DEV_PWM->CTL[0] |= PWM_ENABLE;
        }

        if (pwm_port == PWM1)
        {
            DEV_PWM->CTL[1] |= PWM_ENABLE;
        }

        if (pwm_port == PWM2)
        {
            DEV_PWM->CTL[2] |= PWM_ENABLE;
        }

        if (pwm_port == PWM3)
        {
            DEV_PWM->CTL[3] |= PWM_ENABLE;
        }

        if (pwm_port == PWM4)
        {
            DEV_PWM->CTL[4] |= PWM_ENABLE;
        }

        if (pwm_port == PWM5)
        {
            DEV_PWM->CTL[5] |= PWM_ENABLE;
        }

        if (pwm_port == PWM6)
        {
            DEV_PWM->CTL[6] |= PWM_ENABLE;
        }

        if (pwm_port == PWM7)
        {
            DEV_PWM->CTL[7] |= PWM_ENABLE;
        }
    }
    else
    {
        if (pwm_port == PWM0)
        {
            DEV_PWM->CTL[0] &= ~PWM_ENABLE;
        }

        if (pwm_port == PWM1)
        {
            DEV_PWM->CTL[1] &= ~PWM_ENABLE;
        }

        if (pwm_port == PWM2)
        {
            DEV_PWM->CTL[2] &= ~PWM_ENABLE;
        }

        if (pwm_port == PWM3)
        {
            DEV_PWM->CTL[3] &= ~PWM_ENABLE;
        }

        if (pwm_port == PWM4)
        {
            DEV_PWM->CTL[4] &= ~PWM_ENABLE;
        }

        if (pwm_port == PWM5)
        {
            DEV_PWM->CTL[5] &= ~PWM_ENABLE;
        }

        if (pwm_port == PWM6)
        {
            DEV_PWM->CTL[6] &= ~PWM_ENABLE;
        }

        if (pwm_port == PWM7)
        {
            DEV_PWM->CTL[7] &= ~PWM_ENABLE;
        }
    }
}

/**
* @brief        enable or disable the pwm output as clock
* @details      None
* @param[in]    pwm_port
* @param[in]    state :
                    ENABLE
                    DISABLE
* @return       None
* @note         None
*/
void hal_pwm_clockoutput_cmd(pwm_port_t pwm_port, uint32_t state)
{
    if (state != DISABLE)
    {
        if (pwm_port == PWM0)
        {
            DEV_PWM->CTL[0] |= PWM_CLK_OUT;
        }

        if (pwm_port == PWM1)
        {
            DEV_PWM->CTL[1] |= PWM_CLK_OUT;
        }

        if (pwm_port == PWM2)
        {
            DEV_PWM->CTL[2] |= PWM_CLK_OUT;
        }

        if (pwm_port == PWM3)
        {
            DEV_PWM->CTL[3] |= PWM_CLK_OUT;
        }

        if (pwm_port == PWM4)
        {
            DEV_PWM->CTL[4] |= PWM_CLK_OUT;
        }

        if (pwm_port == PWM5)
        {
            DEV_PWM->CTL[5] |= PWM_CLK_OUT;
        }

        if (pwm_port == PWM6)
        {
            DEV_PWM->CTL[6] |= PWM_CLK_OUT;
        }

        if (pwm_port == PWM7)
        {
            DEV_PWM->CTL[7] |= PWM_CLK_OUT;
        }
    }
    else
    {
        if (pwm_port == PWM0)
        {
            DEV_PWM->CTL[0] &= ~PWM_CLK_OUT;
        }

        if (pwm_port == PWM1)
        {
            DEV_PWM->CTL[1] &= ~PWM_CLK_OUT;
        }

        if (pwm_port == PWM2)
        {
            DEV_PWM->CTL[2] &= ~PWM_CLK_OUT;
        }

        if (pwm_port == PWM3)
        {
            DEV_PWM->CTL[3] &= ~PWM_CLK_OUT;
        }

        if (pwm_port == PWM4)
        {
            DEV_PWM->CTL[4] &= ~PWM_CLK_OUT;
        }

        if (pwm_port == PWM5)
        {
            DEV_PWM->CTL[5] &= ~PWM_CLK_OUT;
        }

        if (pwm_port == PWM6)
        {
            DEV_PWM->CTL[6] &= ~PWM_CLK_OUT;
        }

        if (pwm_port == PWM7)
        {
            DEV_PWM->CTL[7] &= ~PWM_CLK_OUT;
        }
    }
}

/**
* @brief        Configure interrupt
* @details
* @param[in]    pwm_ie:
                    DEV_PWM_IE_DMA1_EN
                    DEV_PWM_IE_DMA0_EN
                    DEV_PWM_IE_DAT2_END
                    DEV_PWM_IE_DAT0_END
                    DEV_PWM_IE_FIFO1_UF
                    DEV_PWM_IE_FIFO1_OF
                    DEV_PWM_IE_FIFO1_THR
                    DEV_PWM_IE_FIFO0_UF
                    DEV_PWM_IE_FIFO0_OF
                    DEV_PWM_IE_FIFO0_THR
                    DEV_PWM_IE_BTH_END_MASK
                    DEV_PWM_IE_PWM_END_MASK
* @param[in]    state:
*                   ENABLE
*                   DISABLE
* @return       None
* @note
*/
void hal_pwm_it_config(uint32_t pwm_ie, uint32_t state)
{
    if (state != DISABLE)
    {
        DEV_PWM->IE |= pwm_ie;
    }
    else
    {
        DEV_PWM->IE &= ~pwm_ie;
    }
}

/**
* @brief        get the interrupted pending
* @details
* @param[in]    pwm_pd:
                    DEV_PWM_PD_DAT2_END
                    DEV_PWM_PD_DAT0_END
                    DEV_PWM_PD_FIFO1_UF
                    DEV_PWM_PD_FIFO1_OF
                    DEV_PWM_PD_FIFO1_THR
                    DEV_PWM_PD_FIFO0_UF
                    DEV_PWM_PD_FIFO0_OF
                    DEV_PWM_PD_FIFO0_THR
                    DEV_PWM_PD_BTH_END_MASK
                    DEV_PWM_PD_PWM_END_MASK
* @return       @arg SET
*               @arg RESET
* @note
*/
uint32_t hal_pwm_get_it_status(uint32_t pwm_pd)
{
    uint32_t bitstatus = RESET;

    if (DEV_PWM->PD & pwm_pd)
    {
        bitstatus = SET;
    }
    else
    {
        bitstatus = RESET;
    }

    return bitstatus;
}

/**
* @brief        Clear the interrupted pending
* @details
* @param[in]    pwm_pd:
                    DEV_PWM_PD_DAT2_END
                    DEV_PWM_PD_DAT0_END
                    DEV_PWM_PD_FIFO1_UF
                    DEV_PWM_PD_FIFO1_OF
                    DEV_PWM_PD_FIFO1_THR
                    DEV_PWM_PD_FIFO0_UF
                    DEV_PWM_PD_FIFO0_OF
                    DEV_PWM_PD_FIFO0_THR
                    DEV_PWM_PD_BTH_END_MASK
                    DEV_PWM_PD_PWM_END_MASK
* @return       None
* @note
*/
void hal_pwm_clear_it_pending_bit(uint32_t pwm_pd)
{
    DEV_PWM->PD &= pwm_pd;
}

/**
* @brief        hal_pwm_get_clk
* @details
* @param[in]    pwm_port
* @return       pwm_clock
* @note         None
*/
uint32_t hal_pwm_get_clk(pwm_port_t pwm_port)
{
    uint32_t pwm_clock = 0;
    uint32_t reg_value = 0;

    if (pwm_port == PWM0)
    {
        reg_value = DEV_CMU->PWMnCLK[0];
    }

    if (pwm_port == PWM1)
    {
        reg_value = DEV_CMU->PWMnCLK[1];
    }

    if (pwm_port == PWM2)
    {
        reg_value = DEV_CMU->PWMnCLK[2];
    }

    if (pwm_port == PWM3)
    {
        reg_value = DEV_CMU->PWMnCLK[3];
    }

    if (pwm_port == PWM4)
    {
        reg_value = DEV_CMU->PWMnCLK[4];
    }

    if (pwm_port == PWM5)
    {
        reg_value = DEV_CMU->PWMnCLK[5];
    }

    if (pwm_port == PWM6)
    {
        reg_value = DEV_CMU->PWMnCLK[6];
    }

    if (pwm_port == PWM7)
    {
        reg_value = DEV_CMU->PWMnCLK[7];
    }

    switch (reg_value & DEV_CMU_PWMnCLK_SEL_MASK)
    {
    case DEV_CMU_PWMnCLK_SEL_OSC_ADC:
        pwm_clock = 512000;
        break;

    case DEV_CMU_PWMnCLK_SEL_OSC_DEV:
        pwm_clock = 24000000;
        break;

    case DEV_CMU_PWMnCLK_SEL_OSC_XTAL:
        pwm_clock = 24000000;
        break;

    case DEV_CMU_PWMnCLK_SEL_OSC_USB:
        /* ignore now */
        pwm_clock = 0;
        break;

    case DEV_CMU_PWMnCLK_SEL_PLL_CORE:
        pwm_clock = cmu_get_pllcore_clk();
        break;

    case DEV_CMU_PWMnCLK_SEL_PLL_AUDIO:
        /* ignore now */
        pwm_clock = 0;
        break;

    case DEV_CMU_PWMnCLK_SEL_EXT_CLK:
        /* ignore now */
        pwm_clock = 0;
        break;

    default :
        break;
    }

    pwm_clock /= (((reg_value & DEV_CMU_PWMnCLK_DIV_MASK) >> 4) + 1);
    return pwm_clock;
    HAL_PWM_LOG("%u\n", pwm_clock);
}

/**
* @brief
* @details
* @param[in]    pwm_port
* @return       HAL_PWM_EOK
* @note         None
*/
int32_t hal_pwm_dutymode_init(pwm_port_t pwm_port)
{
    pwm_dutymode_init_t PWM_DutyInitStrust;
    PWM_DutyInitStrust.mode = PWM_DUTY_MODE;
    PWM_DutyInitStrust.period_cycles = 254;
    PWM_DutyInitStrust.pending_number = 0;
    PWM_DutyInitStrust.duty_cycles = 128;
    cmu_pwm_set_clk(pwm_port, CMU_Clock_OSC_XTAL, 2);

    if (pwm_port == PWM0)
    {
#ifdef HAL_PWM0_PIN

        if (HAL_PWM0_PIN == GPIO38)
        {
            hal_gpio_pinmux_set_function(HAL_PWM0_PIN, GPIO_MUXSEL_FUNCTION8);
        }
        else
        {
            hal_gpio_pinmux_set_function(HAL_PWM0_PIN, GPIO_MUXSEL_FUNCTION9);
        }

#endif
    }

    if (pwm_port == PWM1)
    {
#ifdef HAL_PWM1_PIN

        if (HAL_PWM1_PIN == GPIO39)
        {
            hal_gpio_pinmux_set_function(HAL_PWM1_PIN, GPIO_MUXSEL_FUNCTION8);
        }
        else
        {
            hal_gpio_pinmux_set_function(HAL_PWM1_PIN, GPIO_MUXSEL_FUNCTION9);
        }

#endif
    }

    if (pwm_port == PWM2)
    {
#ifdef HAL_PWM2_PIN
        hal_gpio_pinmux_set_function(HAL_PWM2_PIN, GPIO_MUXSEL_FUNCTION9);
#endif
    }

    if (pwm_port == PWM3)
    {
#ifdef HAL_PWM3_PIN
        hal_gpio_pinmux_set_function(HAL_PWM3_PIN, GPIO_MUXSEL_FUNCTION9);
#endif
    }

    if (pwm_port == PWM4)
    {
#ifdef HAL_PWM4_PIN
        hal_gpio_pinmux_set_function(HAL_PWM4_PIN, GPIO_MUXSEL_FUNCTION9);
#endif
    }

    if (pwm_port == PWM5)
    {
#ifdef HAL_PWM5_PIN
        hal_gpio_pinmux_set_function(HAL_PWM5_PIN, GPIO_MUXSEL_FUNCTION9);
#endif
    }

    if (pwm_port == PWM6)
    {
#ifdef HAL_PWM6_PIN
        hal_gpio_pinmux_set_function(HAL_PWM6_PIN, GPIO_MUXSEL_FUNCTION9);
#endif
    }

    if (pwm_port == PWM7)
    {
#ifdef HAL_PWM7_PIN
        hal_gpio_pinmux_set_function(HAL_PWM7_PIN, GPIO_MUXSEL_FUNCTION9);
#endif
    }

    hal_pwm_dutymode_config(pwm_port, &PWM_DutyInitStrust);
    HAL_PWM_LOG("PWM: %d init\n", pwm_port);
    return HAL_PWM_EOK;
}

