/*
* This program was created by AXELL CORPORATION.
* Copyright (C) 2017 AXELL CORPORATION, all rights reserved.
*/
#include "sample_common.h"
#include "com.h"
#include "wdt/wdtctl.h"

/* プロトタイプ */
static int32_t Wdt_init_module(void);
static int32_t Wdt_term_module(void);
static void Wdt_SampleHelp(void);
static void Wdt_GenerateIntr(void);
static void Wdt_GenerateReset(void);

/* Macro */
#define	EPRINT(FMT, ...)		sys_print(0, FMT,##__VA_ARGS__)
#define	PRINT(FMT, ...)			sys_print(0, FMT"\r\n",##__VA_ARGS__)
#define WDT_ERROR(str)			sys_print(1, " ERROR:%s[%d] *%s*\r\n",__FUNCTION__, __LINE__, str)

static void (*func[])() = {
	Wdt_SampleHelp,
	Wdt_GenerateIntr,
	Wdt_GenerateReset,
};

#define WDT_SMP_CLK		(100000000)	/* WDTクロック周波数 [Hz] */

static volatile _Bool WdtIntrFlag=false;
static volatile _Bool WdtGetCharaFlag=false;

static void Wdt_IntHandler(void* param);
static void Wdt_GetCharaClbk(void);


/**
 * @brief	メイン処理
 * @param	param [in] 制御パラメータ
 * @return	none
 * @note	none
*/
void WDT_main(uint8_t param)
{
	uint8_t		mode = 0;
	char		input[2+2];

	((void)param);

	Wdt_SampleHelp();	/* Help表示 */

	Wdt_init_module();

	while (mode != 0xFF) {
		EPRINT(" -- Choose sample number (00h<HELP> to FFh): ");
		COM_GetNum_Wait(input, sizeof(input));
		mode = (ASCtoBIN(input[0]) << 4)
			 | (ASCtoBIN(input[1]) << 0);
		if(0xFF == mode) {
			break;
		}
		if(mode >= (sizeof(func)/sizeof(void*))) {
			func[0](); /* Help */
		}
		else {
			func[mode]();	/* Sample func実行 */
		}
	}

	Wdt_term_module();

	return;
}

/**
 * @brief	サブ処理
 * @param	param [in] 制御パラメータ
 * @return	none
 * @note	none
*/
void WDT_sub(uint32_t param)
{
	((void)param);
	/* 処理なし */
	return;
}

/**
 * @brief	モジュール初期化
 * @param	none
 * @retval	エラーコード
 * @note	none
*/
static int32_t Wdt_init_module(void)
{
	/* 処理なし */
	return AG903_ENONE;
}

/**
 * @brief	モジュール終了
 * @param	none
 * @retval	エラーコード
 * @note	none
*/
static int32_t Wdt_term_module(void)
{
	/* 処理なし */
	return AG903_ENONE;
}

/**
 * @brief	ヘルプ表示
 * @param	none
 * @return	none
 * @note	none
*/
static void Wdt_SampleHelp(void)
{
	PRINT("\t# 00 ... Help");
	PRINT("\t# 01 ... WDT Interrupt");
	PRINT("\t# 02 ... WDT Reset");
	PRINT("\t# FF ... Exit Sample");
	
	return;
}

/**
 * @brief	WDT割込み生成処理
 * @param	none
 * @return	none
 * @note	none
*/
static void Wdt_GenerateIntr(void)
{
	AG903_WDTCtlParam	pram;
	int32_t 	result;
	uint32_t	period;
	uint32_t	status;
	char		chara[4];

	PRINT(" Generate Reset");
	PRINT(" input period time. [s]");
	EPRINT(" ");

	COM_GetNum_Wait(chara, 3);  /* 3 = 1(period time)+CRLF */
	period  = ASCtoBIN(chara[0]);
	period *= 100000000;

	pram.count   = period;
	pram.intrlen = 0xFF;
	pram.enable  = AG903_WDT_SYSINTR_ENABLE;
	result = AG903_WDTCtlInit(&pram);
	if(AG903_ENONE != result) {
		WDT_ERROR("Init");
	}

	result = AG903_WDTCtlSetIntHandler((void*)Wdt_IntHandler,NULL);
	if(AG903_ENONE != result) {
		WDT_ERROR("SetIntHandler");
	}

	AG903_WDTCtlEnable();

	PRINT(" Press enter key to restart: ");
	EPRINT(" ");
	COM_GetChara(chara,2,(void*)Wdt_GetCharaClbk);  /* 2 = CRLF */

	while(1) {
		if(true==WdtIntrFlag) {
			WdtIntrFlag = false;
			break;
		}
		if(true==WdtGetCharaFlag) {
			WdtGetCharaFlag = false;
			AG903_WDTCtlRestart();
			COM_GetChara(chara,2,(void*)Wdt_GetCharaClbk);
		}
	}

    AG903_WDTCtlDisable();
	AG903_WDTCtlGetStatus(&status);
	PRINT(" Interrupt occurs. status:0x%02x", status);
	AG903_WDTCtlClearStatus();
	AG903_WDTCtlDeleteIntHandler();
	PRINT(" Press enter key to exit: ");
	while(1) {
		if(true==WdtGetCharaFlag) {
			WdtGetCharaFlag = false;
			break;
		}
	}

	return;
}

/**
 * @brief	WDTリセット生成処理
 * @param	none
 * @return	none
 * @note	none
*/
static void Wdt_GenerateReset(void)
{
	AG903_WDTCtlParam	pram;
	int32_t 	result;
	uint32_t	period;
	char		chara[4];
	

	PRINT(" Generate Reset");
	PRINT(" input period time. [s]");
	EPRINT(" ");

	COM_GetNum_Wait(chara, 3);  /* 3 = 1(period time)+CRLF */
	period  = ASCtoBIN(chara[0]);
	period *= 100000000;

	pram.count   = period;
	pram.intrlen = 0xFF;
	pram.enable  = AG903_WDT_SYSRESET_ENABLE;
	result = AG903_WDTCtlInit(&pram);
	if(AG903_ENONE != result) {
		WDT_ERROR("Init");
	}

	AG903_WDTCtlEnable();

	PRINT(" Press enter key to exit restart: ");
	EPRINT(" ");

	while(1) {
		COM_GetChara_Wait(chara, 2);  /* 2 = CRLF */
		AG903_WDTCtlRestart();
	}
}

/**
 * WDT割込み
*/
static void Wdt_IntHandler(void* param)
{
	((void)param);

	WdtIntrFlag = true;
	return;
}

/**
 * GetCharaコールバック
*/
static void Wdt_GetCharaClbk(void)
{
	WdtGetCharaFlag = true;
	return;
}

