/*
 * Copyright 2020-2024 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 hw_adc.c
 */

 #include <stdint.h>
 #include <stddef.h>
 #include "hw_adc.h"
 #include "device_registers.h"
 #include "status.h"
 #include "interrupt_manager.h"
 
 /*******************************************************************************
  * Definitions
  ******************************************************************************/

void HW_SetupAdcSeqMode(const uint8_t *channels, uint8_t channel_cnt, const isr_t adcISR)
{
    eADC_Type *base = eADC0;
    /* Reset adc module */
    IPC->CTRL[IPC_eADC0_INDEX] |= IPC_CTRL_SWREN(1);
    IPC->CTRL[IPC_eADC0_INDEX] &= ~IPC_CTRL_SWREN_MASK;

    /* Setup adc configuration */
    base->CFG0 = eADC_CFG0_SEQCFG(03U)| 
                 eADC_CFG0_HSEQSEL(0U)| 
                 eADC_CFG0_MODE(0U)|
                 eADC_CFG0_HSEQLEN(3U);       /* Sequence length */                             /* Hardware trigger mode */

    base->CFG1 = (eADC_CFG1_SMPAVGE(0U)|eADC_CFG1_SWITCHCNT(32U))|eADC_CFG1_STCNT(80U);                  /* Start time count */
    base->SMP = eADC_SMP_SMP0(10U) | eADC_SMP_SMP1(10U);                                         /* Sample time */
    
    for (int i = 0; i < channel_cnt; i++)
    {
        base->CHSEL[i] = eADC_CHSEL_OVRMOD(1U) |
                         eADC_CHSEL_CHSEL(channels[i]);               /* Setup channel */      
    }

    base->INTE = eADC_INTE_HEOSEQIE(1U);                                   /* Enable end of sequence interrupt */
    INT_SYS_InstallHandler(eADC0_IRQn, adcISR, NULL);
    INT_SYS_EnableIRQ(eADC0_IRQn);
    base->CTRL = eADC_CTRL_TSEN(1U) |                                     /* Enable temperature sensor */
                 eADC_CTRL_ADEN(1U);                                      /* Enable ADC */
    base->CTRL |= eADC_CTRL_ADSTART(1U);                                  /* Start ADC */
    while(!(base->STS & eADC_STS_ADRDY_MASK));                           /* Wait for ADC ready */
}

void HW_DeinitADC(void)
{
    /* Stop ADC */
    eADC0->CTRL = eADC_CTRL_ADSTOP_MASK;
    /* Disable ADC interrupt */
    eADC0->INTE = 0U;
    INT_SYS_DisableIRQ(eADC0_IRQn);
    /* Reset ADC register */
    IPC->CTRL[IPC_eADC0_INDEX] |= IPC_CTRL_SWREN(1);
    IPC->CTRL[IPC_eADC0_INDEX] &= ~IPC_CTRL_SWREN_MASK;
}
