/* ======================================================================
 *   Copyright (c) 2022 Texas Instruments Incorporated
 *
 *   All rights reserved. Property of Texas Instruments Incorporated.
 *   Restricted rights to use, duplicate or disclose this code are
 *   granted through contract.
 *
 *   The program may not be used without the written permission
 *   of Texas Instruments Incorporated or against the terms and conditions
 *   stipulated in the agreement under which this program has been
 *   supplied.
 * ==================================================================== */

/**
 *  \file     WdgApp.c
 *
 *  \brief    This file contains the SPI test example for WdgApp
 *
 */

/* ========================================================================== */
/*                             Include Files                                  */
/* ========================================================================== */

/*LDRA_NOANALYSIS*/
#include "Std_Types.h"
/*LDRA_ANALYSIS*/
#include "Det.h"
#include "Dem.h"
#include "Wdg.h"
#include "SchM_Wdg.h"
#include "EcuM_Cbk.h"
#include "Mcu.h"
#include "Port_Cfg.h"
#include "Port.h"
/*LDRA_NOANALYSIS*/
#include "string.h"
/*LDRA_ANALYSIS*/
#include "trace.h"

/* Starterware Includes */
#include "sys_vim.h"
#include "app_utils.h"
#include "soc.h"

#include "hw_ctrl_core.h"
#include "WdgApp.h"

/* ========================================================================== */
/*                           Macros & Typedefs                                */
/* ========================================================================== */

#define ARRAYSIZE(x)                    (sizeof ((x)) / sizeof (x[0]))
#define TIME_METRICS_ENABLED        STD_OFF

//#define WDGTIMER_QT 1 

/* ========================================================================== */
/*                         Structures and Enums                               */
/* ========================================================================== */

/* None */

/* ========================================================================== */
/*                 Internal Function Declarations                             */
/* ========================================================================== */

static void WdgApp_wdgTest(const WdgApp_TestParams *testPrms);

static void WdgApp_platformInit(void);

/* ========================================================================== */
/*                            Global Variables                                */
/* ========================================================================== */

uint32 gTestPassed;
static Mcu_RamSectionConfigType gWdgAppMcuRamConfig[] =
{
};

#if (STD_OFF == MCU_NO_PLL)
extern CONST(Mcu_ConfigType, MCU_PBCFG) McuModuleConfiguration_0;
#endif

#define WDGAPP_RTI_SYSCLK1_CLKSRCID    (0)

static Mcu_ClockConfigType      gWdgAppMcuClockConfig[] =
{
     [0] =
     {
         .Mcu_ClockModuleId = MCU_CLKSRC_MODULE_ID_SCI0,
         .Mcu_ClockSourceId = MCU_CLKSRC_3,
         .Mcu_ClockDiv = 3,
         .Mcu_InitCfg  = TRUE,
     },
     [1] =
     {
         .Mcu_ClockModuleId = MCU_CLKSRC_MODULE_ID_RTI0,
         .Mcu_ClockSourceId = MCU_CLKSRC_2,
         .Mcu_ClockDiv = 0,
         .Mcu_InitCfg  = TRUE,
     },
     [2] =
     {
         .Mcu_ClockModuleId = MCU_CLKSRC_MODULE_ID_RTI1,
         .Mcu_ClockSourceId = MCU_CLKSRC_2,
         .Mcu_ClockDiv = 0,
         .Mcu_InitCfg  = TRUE,
     },
     [3] =
     {
         .Mcu_ClockModuleId = MCU_CLKSRC_MODULE_ID_RTI2,
         .Mcu_ClockSourceId = MCU_CLKSRC_2,
         .Mcu_ClockDiv = 0,
         .Mcu_InitCfg  = TRUE,
     },
     [4] =
     {
         .Mcu_ClockModuleId = MCU_CLKSRC_MODULE_ID_WDT0,
         .Mcu_ClockSourceId = MCU_CLKSRC_2,
         .Mcu_ClockDiv = 0,
         .Mcu_InitCfg  = TRUE,
     },
};

static Mcu_ConfigType           gWdgAppMcuConfig =
{
    .Mcu_ResetMode           = MCU_PERFORM_RESET_MODE_WARM,
    .Mcu_ConfigRamSection    = &(gWdgAppMcuRamConfig[0]),
    .Mcu_NumberOfRamSectors  = ARRAYSIZE(gWdgAppMcuRamConfig),
    .Mcu_ClockConfig         = &(gWdgAppMcuClockConfig[0]),
    .Mcu_NumberOfClockConfig = ARRAYSIZE(gWdgAppMcuClockConfig)
};

/* ========================================================================== */
/*                          Function Definitions                              */
/* ========================================================================== */

int main(void)
{
    WdgApp_TestParams *testPrms;
    Mcu_ResetType mcu_reset_reason = MCU_RESET_UNDEFINED;

    gTestPassed = E_OK;

    AppUtils_defaultInit();

    WdgApp_platformInit();

    mcu_reset_reason = Mcu_GetResetReason();

    if(mcu_reset_reason != MCU_WARM_RESET_WDT0)
    {
        /* Application has not executed */
        *(uint32*)0x72000000 = 0x00000000;
#ifndef WDGTIMER_QT        
        AppUtils_printf(" Press Enter to start the application\r\n");
        AppUtils_getChar();
#endif         
        AppUtils_printf(APP_NAME ": Sample Application - STARTS !!!\r\n");
        testPrms         = &gWdgAppTestPrms[0];
        WdgApp_wdgTest(testPrms);
    }
    else
    {
        if (((gWdgAppTestPrms[0].numServiceCount+2) > (*(uint32*)0x72000000)) &&
            ((gWdgAppTestPrms[0].numServiceCount-2) < (*(uint32*)0x72000000)))
        {
            AppUtils_printf("Test Passed!! \n\r");
        }
        else
        {
            AppUtils_printf("Test Failed!! \n\r");
            AppUtils_printf("Service Count %d \n\r",(*(uint32*)0x72000000));
            AppUtils_printf("Service Count Expected %d \n\r",
                            gWdgAppTestPrms[0].numServiceCount);
        }
    }

    AppUtils_printf("WDG Test Completed !!!\r\n");

    GT_1trace(McalAppTrace, GT_INFO,
        " WDG Stack Usage: %d bytes\r\n", AppUtils_getStackUsage());
    if (AppUtils_checkStackAndSectionCorruption() != E_OK)
    {
        gTestPassed = E_NOT_OK;
        GT_0trace(McalAppTrace, GT_ERR, " WDG Stack/section corruption!!!\r\n");
    }

    return (0);
}

#if (STD_ON == TIME_METRICS_ENABLED)
uint32 gServiceInterval = 0;
#endif

static void WdgApp_wdgTest(const WdgApp_TestParams *testPrms)
{
    uint32 triggerValue;
    uint32 maxServiceInterval;
    uint32 preloadVal;
    uint32 Cnt =0;
#if (STD_ON == TIME_METRICS_ENABLED)
    uint32              startTime;
    uint32              triggerTime;
#endif

#if (WDG_CFG_GET_VERSION_INFO_API == STD_ON)
    Std_VersionInfoType versioninfo;
    /* Get and print version */
    Wdg_GetVersionInfo(&versioninfo);
    AppUtils_printf(" \r\n");
    AppUtils_printf("WDG MCAL Version Info\r\n");
    AppUtils_printf("---------------------\r\n");
    AppUtils_printf("Vendor ID           : %d\r\n", versioninfo.vendorID);
    AppUtils_printf("Module ID           : %d\r\n", versioninfo.moduleID);
    AppUtils_printf("SW Major Version    : %d\r\n", versioninfo.sw_major_version);
    AppUtils_printf("SW Minor Version    : %d\r\n", versioninfo.sw_minor_version);
    AppUtils_printf("SW Patch Version    : %d\r\n", versioninfo.sw_patch_version);
    AppUtils_printf(" \r\n");
#endif  /* #if (WDG_CFG_VERSION_INFO_API == STD_ON) */

    AppUtils_printf("Starting WDG test  !!!\r\n");

    AppUtils_printf("Service Count %d\r\n", testPrms->numServiceCount);

    AppUtils_printf("Service Interval %d milliseconds\r\n",
                    testPrms->serviceInterval);

    triggerValue = ((testPrms->numServiceCount) * (testPrms->serviceInterval));
    AppUtils_printf("Trigger Value = %d milliseconds\r\n", triggerValue);

    /* check if the service interval is valid or not */

    if (testPrms->wdgConfig->defaultMode == WDGIF_FAST_MODE)
    {
        preloadVal = testPrms->wdgConfig->fastModeCfg.preloadValue;
    }
    else
    {
        preloadVal = testPrms->wdgConfig->slowModeCfg.preloadValue;
    }

    /* calculate the maximum service interval */
    maxServiceInterval = (preloadVal + 1) * 8192;
    maxServiceInterval = maxServiceInterval/(WDG_CFG_RTI_FREQUENCY * 1000);

    AppUtils_printf("Maximum Service Interval %d milliseconds\r\n",
                    maxServiceInterval);

    if (testPrms->serviceInterval >= maxServiceInterval)
    {
        AppUtils_printf("service interval should not be greater than maximum interval\n\r");
        AppUtils_printf("Test Failed!!\n\r");
        return;
    }

    /* Init */
    Wdg_Init(testPrms->wdgConfig);
    if (gTestPassed == E_NOT_OK)
    {
        AppUtils_printf("Error in WatchDog Initialization\n\r");
        AppUtils_printf("Test Failed!!\n\r");
        return;
    }
#ifdef WDGTIMER_QT
    Wdg_SetTriggerCondition(5);
#else     
    Wdg_SetTriggerCondition(triggerValue);
#endif 

    do {
#if (STD_ON == TIME_METRICS_ENABLED)
        startTime = AppUtils_getCurTimeInMsec();
#endif
#ifdef WDGTIMER_QT
        AppUtils_delay(1);
#else 
        AppUtils_delay(testPrms->serviceInterval);
#endif

#if (STD_ON == TIME_METRICS_ENABLED)
        triggerTime      = AppUtils_getCurTimeInMsec();
        gServiceInterval = (triggerTime - startTime);
#endif
        Wdg_Trigger();
        (*(uint32*)0x72000000) = (*(uint32*)0x72000000) + 1;
        AppUtils_printf("cnt: %d\r\n", (*(uint32*)0x72000000));
    } while (1);
}

static void WdgApp_platformInit(void)
{
    uint16 mss_uart_tx_pin, mss_uart_rx_pin;
#if (STD_OFF == MCU_NO_PLL)    
    uint32 sys_clk_freq_vclk_const;

    /* MCU PLL Config */
    gWdgAppMcuConfig.Mcu_PllConfig = McuModuleConfiguration_0.Mcu_PllConfig;
    gWdgAppMcuConfig.Mcu_PllSourceId = McuModuleConfiguration_0.Mcu_PllSourceId;
#endif
    
    Mcu_Init(&gWdgAppMcuConfig);
    Port_Init(PortConfigSet_0_pt);
    mss_uart_tx_pin = 13;
    mss_uart_rx_pin = 14;

    #if defined AWR29XXETS_PLATFORM
      mss_uart_tx_pin = 12;
      mss_uart_rx_pin = 8; 
    #elif defined TPR12_PLATFORM
      mss_uart_tx_pin = 101;
      mss_uart_rx_pin = 80;
    #endif     

    /* Set up the pinmux for UART tx */
    Port_SetPinMode(mss_uart_tx_pin, PORT_PIN_MODE_LIN0);

    /* Set up the pinmux for UART rx */
    Port_SetPinMode(mss_uart_rx_pin, PORT_PIN_MODE_LIN0);
    Port_SetPinDirection(mss_uart_rx_pin, PORT_PIN_IN);

#if (STD_OFF == MCU_NO_PLL)
    if(McuModuleConfiguration_0.Mcu_PllSourceId == MCU_CLKSRC_DPLL)
    {
        sys_clk_freq_vclk_const = (McuModuleConfiguration_0.Mcu_PllConfig[MCU_CLKSRC_DPLL].Mcu_PllClk1.MCU_PLL_HSDIV2 / (2e6)) * 30;
    }
    else
    {
        sys_clk_freq_vclk_const = (McuModuleConfiguration_0.Mcu_PllConfig[MCU_CLKSRC_APLL].Mcu_PllClk1.MCU_PLL_HSDIV0 / (2e6)) * 30;
    }
    Enable_Uart();
#else
    Enable_Uart();
#endif

    return;
}

uint8 Intc_status;

void  SchM_Enter_Mcu_MCU_EXCLUSIVE_AREA_0()
{
    AppUtils_SchM_Enter_EXCLUSIVE_AREA_0();
}

void   SchM_Exit_Mcu_MCU_EXCLUSIVE_AREA_0()
{
     AppUtils_SchM_Exit_EXCLUSIVE_AREA_0();
}

void SchM_Enter_Wdg_WDG_EXCLUSIVE_AREA_0(void)
{
    __asm (" CPSID I");
}

void SchM_Exit_Wdg_WDG_EXCLUSIVE_AREA_0(void)
{
    __asm (" CPSIE I");
}

void  SchM_Enter_Port_PORT_EXCLUSIVE_AREA_0()
{
    __asm (" CPSID I");

}

void   SchM_Exit_Port_PORT_EXCLUSIVE_AREA_0()
{

  __asm (" CPSIE I");

}

Std_ReturnType Det_ReportError(uint16 ModuleId,
                               uint8  InstanceId,
                               uint8  ApiId,
                               uint8  ErrorId)
{
    gTestPassed = E_NOT_OK;
    GT_assert(McalAppTrace, FALSE);
    return (E_OK);
}

void Dem_ReportErrorStatus(Dem_EventIdType     eventId,
                           Dem_EventStatusType eventStatus)
{
    if (DEM_EVENT_STATUS_FAILED == eventStatus)
    {
        gTestPassed = E_NOT_OK;
        AppUtils_printf("WDG Hardware Error!!\r\n");
        GT_assert(McalAppTrace, FALSE);
    }

    return;
}


