/*
 * Copyright 2021 NXP.
 * All rights reserved.
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */

#include "project_setup_lpcxpresso804.h"
#include "clock_config.h"
#include "pin_mux.h"

#include "fsl_usart.h"
#if FMSTR_SERIAL_ENABLE
#include "freemaster.h"
#include "freemaster_serial_usart.h"
#endif
#include "board.h"

/*******************************************************************************
 * Code
 ******************************************************************************/
/*!
 * @brief   Watchdog configuration function
 *
 *          Enables the watchdog. Also in Wait and Stop mode. Updates are allowed
 *
 * @param   wd_setup_value      //watchdog setup value for timeout
 *
 * @return  None
 */
void WatchdogEnable(uint32_t wd_setup_value)
{
    SYSCON->SYSAHBCLKCTRL0 |= SYSCON_SYSAHBCLKCTRL0_WWDT_MASK; /*Enable clock to WWDT*/
    SYSCON->PDRUNCFG &= ~(SYSCON_PDRUNCFG_LPOSC_PD_MASK);

    WWDT->TC      = WWDT_TC_COUNT(wd_setup_value); /*500mS refresh value */
    WWDT->MOD     = (WWDT_MOD_LOCK(0)) | WWDT_MOD_WDEN(1) | (WWDT_MOD_WDRESET(1));
    WWDT->WINDOW  = 0xFFFFFF; /* Disable Window mode */
    WWDT->WARNINT = 0;

    WWDT->FEED = 0xAA; /*Start WDOG */
    WWDT->FEED = 0x55;
}

/*!
 * @brief   Watchdog disabling function
 *
 * @param   None
 *
 * @return  None
 */
void WatchdogDisable(void)
{
    /* WDOG is disabled on LPC after reset by default */
}

/*!
 * @brief   Initialization of Systick timer
 *
 *          This function configures the Systick as a source of interrupt
 *
 * @param   reloadValue - defines the period of counter refresh
 *
 * @return  None
 */
void SystickInit(uint32_t reloadValue)
{
    SysTick->VAL  = 0;
    SysTick->LOAD = reloadValue;
    SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_ENABLE_Msk | SysTick_CTRL_TICKINT_Msk;
}

/* Second timer for CLOCK test */
void ReferenceTimerInit(void)
{
    SYSCON->SYSAHBCLKCTRL0 |= SYSCON_SYSAHBCLKCTRL0_WKT_MASK; /* Enable Clock to WKT regiter */

    SYSCON->PRESETCTRL0 &= ~(SYSCON_PRESETCTRL0_WKT_RST_N_MASK); // Reset the WKT
    SYSCON->PRESETCTRL0 |= (SYSCON_PRESETCTRL0_WKT_RST_N_MASK);

    SYSCON->PDRUNCFG &= ~(SYSCON_PDRUNCFG_LPOSC_PD_MASK);

    SYSCON->LPOSCCLKEN |= 0x2; /*Enable clock for WKT */

    WKT->CTRL  = 0x1;         /*Set LPO osc as clokc for WKT */
    WKT->COUNT = START_VALUE; /* Set start value for Decreasin of Counter */
}

/*!
 * @brief   Setup of clock
 *
 * @param   void
 *
 * @return  None
 *
 *
 */
void ClockInit(void)
{
    BOARD_BootClockFRO30M();

    /*Enable clock to IOCONN  and SWM*/
    SYSCON->SYSAHBCLKCTRL0 |= (SYSCON_SYSAHBCLKCTRL0_SWM(1) | SYSCON_SYSAHBCLKCTRL0_IOCON(1));
}

/*!
 * @brief   Initialization of CTIMER
 *
 *          This function initializes the CTIMER. CTIMER is used for After reset WDog test.
 *
 * @param   void
 *
 * @return  None
 */
void CTIMERInit(void)
{
    SYSCON->SYSAHBCLKCTRL0 |= SYSCON_SYSAHBCLKCTRL0_CTIMER_MASK; // Enable clock
    CTIMER0->CTCR = 0;                                           /* Give DEFAULT state, Timer mode selected */
    CTIMER0->MCR  = 0;                                           /* Default state*/
    CTIMER0->CCR  = 0;                                           /* Default state*/
    CTIMER0->EMR  = 0;                                           /* Default state*/
    CTIMER0->PWMC = 0;                                           /* Default state*/

    CTIMER0->PR = 0; /* Every APB bus clock */
}

/*!
 * @brief  Sets port direction and mux
 *
 * @param
 *
 * @return  None
 */
void PortInit(uint8_t *pByte,
              uint32_t *pDir,
              uint32_t *pIocon,
              uint32_t pinDir,
              uint32_t pinNum,
              uint32_t pull,
              uint32_t clock_enable_shift)
{
    /* Enable clock to GPIO module */
    SYSCON->SYSAHBCLKCTRL0 |= (1 << clock_enable_shift);

    *pIocon &= ~(IOCON_PIO_MODE_MASK); /*Clear PULL setting*/
    *pIocon |= IOCON_PIO_MODE(pull);   /*Set pullup*/

    if (pinDir == PIN_DIRECTION_OUT)
    {
        *pDir |= (1 << pinNum); /* PINx = 1 = output */
    }
    else if (pinDir == PIN_DIRECTION_IN)
    {
        *pDir &= ~(1 << pinNum); /* PINx = 0 = input */
    }
}

/*!
 * @brief   Initialization of ADC0
 *
 *          8 MHz System Oscillator Bus Clock is the source clock.
 *          single-ended 12-bit conversion
 *
 * @param   void
 *
 * @return  None
 */
#define FRO_CLK 30000000
void AdcInit(void)
{
    // uint8_t clkdiv = 0;
    uint32_t temp;
    // Step 1. Power up and reset the ADC, and enable clocks to peripheral
    SYSCON->PDRUNCFG &= ~(SYSCON_PDRUNCFG_ADC_PD_MASK);
    SYSCON->PRESETCTRL0 &= ~(SYSCON_PRESETCTRL0_ADC_RST_N_MASK);
    SYSCON->PRESETCTRL0 |= (SYSCON_PRESETCTRL0_ADC_RST_N_MASK);
    SYSCON->SYSAHBCLKCTRL0 |= (SYSCON_SYSAHBCLKCTRL0_ADC_MASK); /* Enable Clock to ADC */
    SYSCON->ADCCLKDIV = 1;                                      // Enable clock, and divide-by-1 at this clock divider
    SYSCON->ADCCLKSEL = 0;                                      // Use fro_clk as source for ADC async clock

    temp = ADC->CTRL;
    // Step 2. Perform a self-calibration
    // Choose a CLKDIV divider value that yields about 500 KHz.
    // clkdiv = (FRO_CLK / 500000) - 1;

    ADC->CTRL = temp;                              /*REstroe ADC setting*/
    ADC->CTRL |= 0x1;                              /*Clock Divider 2*/
    ADC->SEQ_CTRL[0] |= ADC_SEQ_CTRL_TRIGPOL_MASK; // polarity of triger

    // TODO Some macro for easy edit?
    SWM0->PINENABLE0 &= ~(SWM_PINENABLE0_ADC_0_MASK | SWM_PINENABLE0_ADC_3_MASK | SWM_PINENABLE0_ADC_7_MASK);
}

/* Configure UART0 for "brate" baud
 *
 **********************************************************/
void SerialInit(void)
{
    usart_config_t config;

    /* Select the main clock as source clock of USART0 (debug console) */
    CLOCK_Select(BOARD_DEBUG_USART_CLK_ATTACH);

    /* Board initialization */
    BOARD_InitPins();
    /*
     *   usartConfig->baudRate_Bps = UART_BAUD_RATE;
     *   usartConfig->parityMode = kUSART_ParityDisabled;
     *   usartConfig->stopBitCount = kUSART_OneStopBit;
     *   usartConfig->bitCountPerChar = kUSART_8BitsPerChar;
     *   usartConfig->loopback = false;
     *   usartConfig->enableTx = false;
     *   usartConfig->enableRx = false;
     */
    USART_GetDefaultConfig(&config);
    /* Override the Default configuration to satisfy FreeMASTER needs */
    config.baudRate_Bps = UART_BAUD_RATE;
    config.enableTx     = false;
    config.enableRx     = false;

    USART_Init((USART_Type *)BOARD_DEBUG_USART_BASEADDR, &config, BOARD_DEBUG_USART_CLK_FREQ);

#if FMSTR_SERIAL_ENABLE
    /* Register communication module used by FreeMASTER driver. */
    FMSTR_SerialSetBaseAddress((USART_Type *)BOARD_DEBUG_USART_BASEADDR);

#if FMSTR_SHORT_INTR || FMSTR_LONG_INTR
    /* Enable UART interrupts. */
    EnableIRQ(BOARD_UART_IRQ);
    EnableGlobalIRQ(0);
#endif

#endif // FMSTR_SERIAL_ENABLE
}
