/*
* 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_lradc.h"
#include "hal_gpio.h"
#include "hal_common.h"
#include "hal_cmu.h"
#include "board.h"


/**
* @brief        set channel phase
* @details
* @param[in]    lradc_num
                    0: 32
                    1: 16
                    2: 8
                    3: 4
                    4: 2
* @return       None
* @note         None
*/
void hal_lradc_set_channelphase(uint32_t lradc_num)
{
    uint32_t reg_value;
    reg_value = ((uint32_t)lradc_num << 1) & AON_LRADC_CTL_LRADC_NUM_MASK;
    AON_LRADC->CTL &= ~AON_LRADC_CTL_LRADC_NUM_MASK;
    AON_LRADC->CTL |= reg_value;
}

/**
* @brief        set sample average
* @details
* @param[in]    lradc_port
* @param[in]    avg
                    0: 1 Sample
                    1: 2 Sample
                    2: 4 Sample
                    3: 8 Sample
                    4: 16 Sample
                    5: 32 Sample
* @return       None
* @note         None
*/
void hal_lradc_set_sampleaverage(lradc_port_t lradc_port, uint32_t avg)
{
    uint32_t reg_value;
    reg_value = ((uint32_t)avg << 4) & AON_LRADC_CFGn_AVG_MASK;
    AON_LRADC->CFGn[lradc_port] &= ~AON_LRADC_CFGn_AVG_MASK;
    AON_LRADC->CFGn[lradc_port] |= reg_value;
}

/**
* @brief        set sample rate
* @details
* @param[in]    lradc_port
* @param[in]    sr
                    0: /1
                    1: /2
                    2: /4
                    3: /8
* @return       None
* @note         None
*/
void hal_lradc_set_samplerate(lradc_port_t lradc_port, uint32_t sr)
{
    uint32_t reg_value;
    reg_value = ((uint32_t)sr << 2) & AON_LRADC_CFGn_SR_MASK;
    AON_LRADC->CFGn[lradc_port] &= ~AON_LRADC_CFGn_SR_MASK;
    AON_LRADC->CFGn[lradc_port] |= reg_value;
}

/**
* @brief        set sample mode
* @details
* @param[in]    lradc_port
* @param[in]    mode
                    0: Single Mode
                    1: Continue Mode
* @return       None
* @note         None
*/
void hal_lradc_set_samplemode(lradc_port_t lradc_port, uint32_t mode)
{
    uint32_t reg_value;
    reg_value = ((uint32_t)mode << 1) & AON_LRADC_CFGn_MODE_MASK;
    AON_LRADC->CFGn[lradc_port] &= ~AON_LRADC_CFGn_MODE_MASK;
    AON_LRADC->CFGn[lradc_port] |= reg_value;
}

/**
* @brief        enable or disable the lradc
* @details
* @param[in]    lradc_port
* @param[in]    state:
*                    ENABLE
*                    DISABLE
* @return       None
* @note         None
*/
void hal_lradc_enable(lradc_port_t lradc_port, uint32_t state)
{
    if (state != DISABLE)
    {
        AON_LRADC->CFGn[lradc_port] |= LRADC_ENABLE;
    }
    else
    {
        AON_LRADC->CFGn[lradc_port] &= ~LRADC_ENABLE;
    }
}

/**
* @brief        hal_lradc_start
* @details
* @param[in]    None
* @param[in]    None
* @return       None
* @note         None
*/
void hal_lradc_start(void)
{
    AON_LRADC->CTL |= LRADC_START;
}

/**
* @brief        hal_lradc_stop
* @details
* @param[in]    None
* @param[in]    None
* @return       None
* @note         None
*/
void hal_lradc_stop(void)
{
    AON_LRADC->CTL &= ~LRADC_START;
}


/**
* @brief        read data from DATn[lradc_port] register
* @details
* @param[in]    lradc_port
* @return       value
* @note         None
*/
int32_t hal_lradc_sampledata(lradc_port_t lradc_port)
{
    int32_t value;
    value = AON_LRADC->DATn[lradc_port] & AON_LRADC_DATn_DATA_MASK;
    return value;
}

/**
* @brief        get sample value
* @details
* @param[in]    lradc_port
* @return       value
* @note         None
*/
int32_t hal_lradc_getvalue(lradc_port_t lradc_port)
{
    int32_t value = 0;

    if (lradc_port == LRADC0)
    {
        while (hal_lradc_get_it_status(AON_LRADC_PD_LRADC00_END_PD) == 0);

        value = (int32_t)hal_lradc_sampledata(lradc_port);
        hal_lradc_clear_it_pending_bit(AON_LRADC_PD_LRADC00_END_PD);
    }
    else if (lradc_port == LRADC1)
    {
        while (hal_lradc_get_it_status(AON_LRADC_PD_LRADC01_END_PD) == 0);

        value = (int32_t)hal_lradc_sampledata(lradc_port);
        hal_lradc_clear_it_pending_bit(AON_LRADC_PD_LRADC01_END_PD);
    }
    else if (lradc_port == LRADC2)
    {
        while (hal_lradc_get_it_status(AON_LRADC_PD_LRADC02_END_PD) == 0);

        value = (int32_t)hal_lradc_sampledata(lradc_port);
        hal_lradc_clear_it_pending_bit(AON_LRADC_PD_LRADC02_END_PD);
    }
    else if (lradc_port == LRADC3)
    {
        while (hal_lradc_get_it_status(AON_LRADC_PD_LRADC03_END_PD) == 0);

        value = (int32_t)hal_lradc_sampledata(lradc_port);
        hal_lradc_clear_it_pending_bit(AON_LRADC_PD_LRADC03_END_PD);
    }
    else if (lradc_port == LRADC4)
    {
        while (hal_lradc_get_it_status(AON_LRADC_PD_LRADC04_END_PD) == 0);

        value = (int32_t)hal_lradc_sampledata(lradc_port);
        hal_lradc_clear_it_pending_bit(AON_LRADC_PD_LRADC04_END_PD);
    }
    else if (lradc_port == LRADC5)
    {
        while (hal_lradc_get_it_status(AON_LRADC_PD_LRADC05_END_PD) == 0);

        value = (int32_t)hal_lradc_sampledata(lradc_port);
        hal_lradc_clear_it_pending_bit(AON_LRADC_PD_LRADC05_END_PD);
    }
    else if (lradc_port == LRADC6)
    {
        while (hal_lradc_get_it_status(AON_LRADC_PD_LRADC06_END_PD) == 0);

        value = (int32_t)hal_lradc_sampledata(lradc_port);
        hal_lradc_clear_it_pending_bit(AON_LRADC_PD_LRADC06_END_PD);
    }
    else if (lradc_port == LRADC7)
    {
        while (hal_lradc_get_it_status(AON_LRADC_PD_LRADC07_END_PD) == 0);

        value = (int32_t)hal_lradc_sampledata(lradc_port);
        hal_lradc_clear_it_pending_bit(AON_LRADC_PD_LRADC07_END_PD);
    }
    else if (lradc_port == LRADC8)
    {
        while (hal_lradc_get_it_status(AON_LRADC_PD_LRADC08_END_PD) == 0);

        value = (int32_t)hal_lradc_sampledata(lradc_port);
        hal_lradc_clear_it_pending_bit(AON_LRADC_PD_LRADC08_END_PD);
    }
    else if (lradc_port == LRADC10)
    {
        while (hal_lradc_get_it_status(AON_LRADC_PD_LRADC10_END_PD) == 0);

        value = (int32_t)hal_lradc_sampledata(lradc_port);
        hal_lradc_clear_it_pending_bit(AON_LRADC_PD_LRADC10_END_PD);
    }

    return value;
}

/**
* @brief        Configure interrupt
* @details
* @param[in]    lradc_ie:
                    AON_LRADC_IE_LRADC_MVK5_IE
                    AON_LRADC_IE_LRADC_MVK4_IE
                    AON_LRADC_IE_LRADC_MVK3_IE
                    AON_LRADC_IE_LRADC_MVK2_IE
                    AON_LRADC_IE_LRADC_MVK1_IE
                    AON_LRADC_IE_LRADC_MVK0_IE
                    AON_LRADC_IE_LRADC11_SVK_IE
                    AON_LRADC_IE_LRADC10_SVK_IE
                    AON_LRADC_IE_LRADC09_SVK_IE
                    AON_LRADC_IE_LRADC08_SVK_IE
                    AON_LRADC_IE_LRADC07_SVK_IE
                    AON_LRADC_IE_LRADC06_SVK_IE
                    AON_LRADC_IE_LRADC05_SVK_IE
                    AON_LRADC_IE_LRADC04_SVK_IE
                    AON_LRADC_IE_LRADC03_SVK_IE
                    AON_LRADC_IE_LRADC02_SVK_IE
                    AON_LRADC_IE_LRADC01_SVK_IE
                    AON_LRADC_IE_LRADC00_SVK_IE
                    AON_LRADC_IE_LRADC11_END_IE
                    AON_LRADC_IE_LRADC10_END_IE
                    AON_LRADC_IE_LRADC09_END_IE
                    AON_LRADC_IE_LRADC08_END_IE
                    AON_LRADC_IE_LRADC07_END_IE
                    AON_LRADC_IE_LRADC06_END_IE
                    AON_LRADC_IE_LRADC05_END_IE
                    AON_LRADC_IE_LRADC04_END_IE
                    AON_LRADC_IE_LRADC03_END_IE
                    AON_LRADC_IE_LRADC02_END_IE
                    AON_LRADC_IE_LRADC01_END_IE
                    AON_LRADC_IE_LRADC00_END_IE
* @param[in]    state:
*                   ENABLE
*                   DISABLE
* @return       None
* @note
*/
void hal_lradc_it_config(uint32_t lradc_ie, uint32_t state)
{
    if (state != DISABLE)
    {
        AON_LRADC->IE |= lradc_ie;
    }
    else
    {
        AON_LRADC->IE &= ~lradc_ie;
    }
}

/**
* @brief        get the interrupted pending
* @details
* @param[in]    lradc_pd:
                    AON_LRADC_PD_LRADC_MVK5_PD
                    AON_LRADC_PD_LRADC_MVK4_PD
                    AON_LRADC_PD_LRADC_MVK3_PD
                    AON_LRADC_PD_LRADC_MVK2_PD
                    AON_LRADC_PD_LRADC_MVK1_PD
                    AON_LRADC_PD_LRADC_MVK0_PD
                    AON_LRADC_PD_LRADC11_SVK_PD
                    AON_LRADC_PD_LRADC10_SVK_PD
                    AON_LRADC_PD_LRADC09_SVK_PD
                    AON_LRADC_PD_LRADC08_SVK_PD
                    AON_LRADC_PD_LRADC07_SVK_PD
                    AON_LRADC_PD_LRADC06_SVK_PD
                    AON_LRADC_PD_LRADC05_SVK_PD
                    AON_LRADC_PD_LRADC04_SVK_PD
                    AON_LRADC_PD_LRADC03_SVK_PD
                    AON_LRADC_PD_LRADC02_SVK_PD
                    AON_LRADC_PD_LRADC01_SVK_PD
                    AON_LRADC_PD_LRADC00_SVK_PD
                    AON_LRADC_PD_LRADC11_END_PD
                    AON_LRADC_PD_LRADC10_END_PD
                    AON_LRADC_PD_LRADC09_END_PD
                    AON_LRADC_PD_LRADC08_END_PD
                    AON_LRADC_PD_LRADC07_END_PD
                    AON_LRADC_PD_LRADC06_END_PD
                    AON_LRADC_PD_LRADC05_END_PD
                    AON_LRADC_PD_LRADC04_END_PD
                    AON_LRADC_PD_LRADC03_END_PD
                    AON_LRADC_PD_LRADC02_END_PD
                    AON_LRADC_PD_LRADC01_END_PD
                    AON_LRADC_PD_LRADC00_END_PD

* @return       @arg SET
*               @arg RESET
* @note
*/
uint32_t hal_lradc_get_it_status(uint32_t lradc_pd)
{
    uint32_t bitstatus = RESET;

    if (AON_LRADC->PD & lradc_pd)
    {
        bitstatus = SET;
    }
    else
    {
        bitstatus = RESET;
    }

    return bitstatus;
}

/**
* @brief        Clear the interrupted pending
* @details
* @param[in]    lradc_pd:
                    Refer to above……
* @return       None
* @note
*/
void hal_lradc_clear_it_pending_bit(uint32_t lradc_pd)
{
    AON_LRADC->PD &= lradc_pd;
}


/**
* @brief        config wake up
* @details
* @param[in]    lradc_wakeup:
                    AON_LRADC_WKEN_LRADC_MVK5_WKEN
                    AON_LRADC_WKEN_LRADC_MVK4_WKEN
                    AON_LRADC_WKEN_LRADC_MVK3_WKEN
                    AON_LRADC_WKEN_LRADC_MVK2_WKEN
                    AON_LRADC_WKEN_LRADC_MVK1_WKEN
                    AON_LRADC_WKEN_LRADC_MVK0_WKEN
                    AON_LRADC_WKEN_LRADC11_SVK_WKEN
                    AON_LRADC_WKEN_LRADC10_SVK_WKEN
                    AON_LRADC_WKEN_LRADC09_SVK_WKEN
                    AON_LRADC_WKEN_LRADC08_SVK_WKEN
                    AON_LRADC_WKEN_LRADC07_SVK_WKEN
                    AON_LRADC_WKEN_LRADC06_SVK_WKEN
                    AON_LRADC_WKEN_LRADC05_SVK_WKEN
                    AON_LRADC_WKEN_LRADC04_SVK_WKEN
                    AON_LRADC_WKEN_LRADC03_SVK_WKEN
                    AON_LRADC_WKEN_LRADC02_SVK_WKEN
                    AON_LRADC_WKEN_LRADC01_SVK_WKEN
                    AON_LRADC_WKEN_LRADC00_SVK_WKEN
                    AON_LRADC_WKEN_LRADC11_END_WKEN
                    AON_LRADC_WKEN_LRADC10_END_WKEN
                    AON_LRADC_WKEN_LRADC09_END_WKEN
                    AON_LRADC_WKEN_LRADC08_END_WKEN
                    AON_LRADC_WKEN_LRADC07_END_WKEN
                    AON_LRADC_WKEN_LRADC06_END_WKEN
                    AON_LRADC_WKEN_LRADC05_END_WKEN
                    AON_LRADC_WKEN_LRADC04_END_WKEN
                    AON_LRADC_WKEN_LRADC03_END_WKEN
                    AON_LRADC_WKEN_LRADC02_END_WKEN
                    AON_LRADC_WKEN_LRADC01_END_WKEN
                    AON_LRADC_WKEN_LRADC00_END_WKEN
* @param[in]    state:
*                   ENABLE
*                   DISABLE
* @return       None
* @note
*/
void hal_lradc_wakeup_config(uint32_t lradc_wakeup, uint32_t state)
{
    if (state != DISABLE)
    {
        AON_LRADC->WKEN |= lradc_wakeup;
    }
    else
    {
        AON_LRADC->WKEN &= ~lradc_wakeup;
    }
}

/**
* @brief        hal_lradc_init
* @details
* @param[in]    lradc_port
* @return       HAL_LRADC_EOK
* @note         None
*/
int32_t hal_lradc_init(lradc_port_t lradc_port)
{
    cmu_aon_lradc_set_clk(CMU_Clock_OSC_ADC, 1);
    AON_LRADC->CFGn[lradc_port] = 0x00;
    AON_LRADC->CTL = 0x01;
    AON_LRADC->ANA = 0x01 | 0x01 << 8;
    AON_LRADC->CFGn[11] = 0x03;
    if (lradc_port == LRADC0)
    {
        AON_GPIO->SPIOn_CTL[0] = 0;
    }

    if (lradc_port == LRADC1)
    {
        AON_GPIO->SPIOn_CTL[1] = 0;
    }

    if (lradc_port == LRADC2)
    {
        AON_GPIO->SPIOn_CTL[2] = 0;
    }

    if (lradc_port == LRADC3)
    {
#ifdef HAL_LRADC3_PIN
        hal_gpio_pinmux_set_function(HAL_LRADC3_PIN, GPIO_MUXSEL_GPIO);
#endif
    }

    if (lradc_port == LRADC4)
    {
#ifdef HAL_LRADC4_PIN
        hal_gpio_pinmux_set_function(HAL_LRADC4_PIN, GPIO_MUXSEL_GPIO);
#endif
    }

    if (lradc_port == LRADC5)
    {
#ifdef HAL_LRADC5_PIN
        hal_gpio_pinmux_set_function(HAL_LRADC5_PIN, GPIO_MUXSEL_GPIO);
#endif
    }

    if (lradc_port == LRADC6)
    {
#ifdef HAL_LRADC6_PIN
        hal_gpio_pinmux_set_function(HAL_LRADC6_PIN, GPIO_MUXSEL_GPIO);
#endif
    }

    HAL_LRADC_LOG("lradc: %d init\n", lradc_port);
    return HAL_LRADC_EOK;
}

