/** @brief
 * @copyright 2020 Remsdaq Ltd.
 *
 * @file watchdog_test.c
 *
 *  @date: 4 Aug 2020
 *  @author: Dan Smithers
 */





/*******************************************************************************
 * Includes
 ******************************************************************************/

#include "c4_watchdog.h"
#include "watchdog_test.h"
#include "lib/c4_watchdog_types.h"
#include "fsl_wdog.h"
#include <stdio.h>

/*******************************************************************************
 * Defines
 ******************************************************************************/

/** @brief Macro to perform test and display result
 *
 * @param[in] fn Function and parameters to execute.
 * @param[out] rc return code.
 * @param[in] res Expected result
 */
#define TEST_IF(fn, res, rc)           \
    { rc = fn;                          \
      C4_displayError(#fn, rc, false);  \
      rc = ((rc == res) ? C4_ERR_OK : C4_ERR_FAILED); \
    }

/*******************************************************************************
 * External Declarations
 ******************************************************************************/

extern void BL_SysTick_DelayTicks(uint32_t n);

/*******************************************************************************
 * Structures
 ******************************************************************************/

/*******************************************************************************
 * Prototypes
 ******************************************************************************/

/*******************************************************************************
 * Variables
 ******************************************************************************/

/*******************************************************************************
 * Interface Implementation
 ******************************************************************************/

exit_code_t watchdog_test()
{

	uint16_t resetFlag = 0U;
	wdog_config_t config;

	NVIC_EnableIRQ(WDOG1_IRQn);
    /* Cast from our bitfield representation of WDOG registers to shift and mask used in FreeRTOS functions. */
	WDOG_EnableInterrupts((WDOG_Type *)sWdogRegisters[C4_WDOG1], kWDOG_InterruptEnable);
	printf("\r\n******** System Start ********\r\n");
	printf("System reset by:");

    /* Cast from our bitfield representation of WDOG registers to shift and mask used in FreeRTOS functions. */
	resetFlag = WDOG_GetStatusFlags((WDOG_Type *)sWdogRegisters[C4_WDOG1]);

	switch (resetFlag & (kWDOG_PowerOnResetFlag | kWDOG_TimeoutResetFlag | kWDOG_SoftwareResetFlag))
	{
	case kWDOG_PowerOnResetFlag:
		printf(" Power On Reset!\r\n");
		break;
	case kWDOG_TimeoutResetFlag:
		printf(" Time Out Reset!\r\n");
		break;
	case kWDOG_SoftwareResetFlag:
		printf(" Software Reset!\r\n");
		break;
	default:
		printf(" Error status!\r\n");
		break;
	}
	/* Disable wdog reset function test for some devices can't using this feature. */
#if (!(defined(EXAMPLE_DISABLE_WDOG_RESET_FUNCTION) && EXAMPLE_DISABLE_WDOG_RESET_FUNCTION))
	/* If system reset from power on, trigger a software reset. */
	if (resetFlag & kWDOG_PowerOnResetFlag)
	{
		printf("\r\n- 1.Testing System reset by software trigger...   ");
        /* Cast from our bitfield representation of WDOG registers to shift and mask used in FreeRTOS functions. */
		WDOG_TriggerSystemSoftwareReset((WDOG_Type *)sWdogRegisters[C4_WDOG1]);
	}

	/* If system reset from software trigger, testing the timeout reset. */
	if (resetFlag & kWDOG_SoftwareResetFlag)
	{
		printf("\r\n- 2.Testing system reset by WDOG timeout.\r\n");
		/*
		 * wdogConfig->enableWdog = true;
		 * wdogConfig->workMode.enableWait = true;
		 * wdogConfig->workMode.enableStop = false;
		 * wdogConfig->workMode.enableDebug = false;
		 * wdogConfig->enableInterrupt = false;
		 * wdogConfig->enablePowerdown = false;
		 * wdogConfig->resetExtension = flase;
		 * wdogConfig->timeoutValue = 0xFFU;
		 * wdogConfig->interruptTimeValue = 0x04u;
		 */
		WDOG_GetDefaultConfig(&config);
		config.timeoutValue = 0xFU; /* Timeout value is (0xF + 1)/2 = 8 sec. */
        /* Cast from our bitfield representation of WDOG registers to shift and mask used in FreeRTOS functions. */
		WDOG_Init((WDOG_Type *)sWdogRegisters[C4_WDOG1], &config);
		printf("--- wdog Init done---\r\n");

		/* without feed watch dog, wait until timeout. */
		while (1)
		{
		}
	}

	/* If system reset from WDOG timeout, testing the refresh function using interrupt. */
	if (resetFlag & kWDOG_TimeoutResetFlag)
	{
#endif
		printf("\r\n- 3.Test the WDOG refresh function by using interrupt.\r\n");
		/*
		 * wdogConfig->enableWdog = true;
		 * wdogConfig->workMode.enableWait = true;
		 * wdogConfig->workMode.enableStop = false;
		 * wdogConfig->workMode.enableDebug = false;
		 * wdogConfig->enableInterrupt = false;
		 * wdogConfig->enablePowerdown = false;
		 * wdogConfig->resetExtension = flase;
		 * wdogConfig->timeoutValue = 0xFFU;
		 * wdogConfig->interruptTimeValue = 0x04u;
		 */
		WDOG_GetDefaultConfig(&config);
		config.timeoutValue       = 0xFU; /* Timeout value is (0xF+1)/2 = 8 sec. */
		config.enableInterrupt    = true;
		config.interruptTimeValue = 0x8U; /* Interrupt occurred (0x4)/2 = 2 sec before WDOG timeout. */
        /* Cast from our bitfield representation of WDOG registers to shift and mask used in FreeRTOS functions. */
		WDOG_Init((WDOG_Type *)sWdogRegisters[C4_WDOG1], &config);

		printf("--- wdog Init done---\r\n");

#if (!(defined(EXAMPLE_DISABLE_WDOG_RESET_FUNCTION) && EXAMPLE_DISABLE_WDOG_RESET_FUNCTION))
	}
#endif

	while (1)
	{
        /* Cast from our bitfield representation of WDOG registers to shift and mask used in FreeRTOS functions. */
		WDOG_Refresh((WDOG_Type *)sWdogRegisters[C4_WDOG1]);
		/* User can feed WDG in their main thread. */
		printf(" \r\nWDOG has been refreshed!");

		/* Delay. */
		BL_SysTick_DelayTicks(7000);
	}
}

/*******************************************************************************/

exit_code_t watchdog_if_test(c4_wdog_t wdog)
{
	exit_code_t rc = C4_ERR_OK;
    // Check watchdog IDs
    TEST_IF(c4_setWdogTimeout(-1,100), C4_ERR_RANGE, rc);
    if (C4_ERR_OK == rc)
        TEST_IF(c4_setWdogTimeout(2,100), C4_ERR_RANGE, rc);
    if (C4_ERR_OK == rc)
        TEST_IF(c4_setWdogInterrupt(-1,100), C4_ERR_RANGE, rc);
    if (C4_ERR_OK == rc)
        TEST_IF(c4_setWdogInterrupt(2,100), C4_ERR_RANGE, rc);

    // Test timeout range
    if (C4_ERR_OK == rc)
        TEST_IF(c4_setWdogTimeout(wdog, 4), C4_ERR_RANGE, rc);
    if (C4_ERR_OK == rc)
        TEST_IF(c4_setWdogTimeout(wdog, 1281), C4_ERR_RANGE, rc);
    if (C4_ERR_OK == rc)
        TEST_IF(c4_setWdogInterrupt(wdog,-1), C4_ERR_RANGE, rc);
    if (C4_ERR_OK == rc)
        TEST_IF(c4_setWdogInterrupt(wdog,1276), C4_ERR_RANGE, rc);

    // Test re-initialisation of interrupt
    // This test assumes that the interrupt has been previously enabled.
    if (C4_ERR_OK == rc)
        TEST_IF(c4_setWdogInterrupt(wdog,400), C4_ERR_ALREADY_SET, rc);

	return rc;
}
