/**
 * @brief       TIMR Manager
 * @author      AXELL CORPORATION
 * @description TIMR Manager Layer
 * @note        none
 * @history     2017_02_22  初版
 * @history     2017_10_26  Ver2.0
 * @history     2019_12_27  [SDK3.0] Timrマネージャにチャンネル指定でのハンドラ取得を追加 (#2160)
*/
/* DOM-IGNORE-BEGIN */
/*
* This program was created by AXELL CORPORATION.
* Copyright (C) 2017-2019 AXELL CORPORATION, all rights reserved.
*/
/* DOM-IGNORE-END */

#include "AG903_errno.h"
#include "AG903_intno.h"
#include "timr/timrmgr.h"
#include "timr/timrprm.h"
#include "int/intmgr.h"

typedef void (*AG903_TIMRMgrIntHdr)(void);	/** コールバック関数型 */

typedef struct _AG903_TIMRMgrInthdrStat {
	int32_t	hdrid;		/** ハンドラID */
	void*	func;		/** 割込みハンドラの起動番地 */
}AG903_TIMRMgrInthdrStat;

typedef struct _AG903_TIMRMgrChStat{
	AG903_TIMRMgrInthdrStat	inthdr[AG903_TIMR_INTHDR_NUM];
	uint8_t		mode;		/** 動作モード */
	uint8_t		outmode;	/** 出力モード */
	uint8_t		reserve[2];	/** 予約 */
} AG903_TIMRMgrChStat;

typedef struct _AG903_TIMRMgrHandleStat{
	uint8_t		lock;		/** ロック */
	uint8_t		reserve[3];	/** 予約 */
} AG903_TIMRMgrHandleStat;

static AG903_TIMRMgrChStat		TimrChStat[AG903_TIMR_CH_NUM];		/** ch状態 */
static AG903_TIMRMgrHandleStat	TimrHandleStat[AG903_TIMR_CH_NUM];	/** handle状態 */

static const uint8_t TimrResolutionTypeTbl[AG903_TIMR_CNT_TYPENUM] =
{AG903_TIMR_RES_SYSCLK, AG903_TIMR_RES_TICK0, AG903_TIMR_RES_TICK1};	/** サンプリングクロック種別 */
static const uint8_t TimrOutModeTbl[AG903_TIMR_OUT_MODENUM] =
{AG903_TIMR_OUTMOD_PLUSE, AG903_TIMR_OUTMOD_LEVEL, AG903_TIMR_OUTMOD_PWM};	/** 出力モード */
static const uint8_t TimrInputReTbl[AG903_TIMR_INPUT_RETYPENUM][2] =
{{0,0},{0,2},{1,0},{1,2}};	/** ロータリエンコーダ入力種別 [lo,ch] */
static const uint8_t TimrInputTbl[AG903_TIMR_INPUT_TYPENUM][2] =
{{0,0},{0,1},{0,2},{0,3},{1,0},{1,1},{1,2},{1,3}};	/** タイマ入力種別 [lo,ch] */
static const uint8_t TimrResetTriggerTbl[AG903_TIMR_RSTTRG_TYPENUM] =
{AG903_TIMR_RSTEN_EXTPORT, AG903_TIMR_RSTEN_EVENT};	/** リセットトリガ種別 */

static void TIMRMgr_Init(uint8_t ch);
static int32_t TIMRMgr_CheckHandle(AG903_TIMRMgrHandle* handle, uint8_t* ch);
static _Bool TIMRMgr_CheckIdle(uint8_t ch);

/**
 * @brief           TIMRManager初期化
 * @param           none
 * @return          初期化結果
 * @retval          AG903_ENONE 正常終了
 * @description     内部変数を初期化します。システム起動時にCALLして下さい。<p>
 *                  タイマは「動作停止」状態になります。
 * @note            この関数はINTMgrを初期化してから呼び出して下さい。
*/
int32_t	AG903_TIMRMgrInit(void)
{
	int32_t	 retval = AG903_ENONE;
	uint32_t loop;
	
	for(loop=0; loop<AG903_TIMR_CH_NUM; loop++) {
		TIMRMgr_Init(loop);	/* 状態初期化 */
	}

	return retval;
}

/**
 * @brief           TIMRハンドル取得
 * @param           handle [out] TIMRハンドル
 * @return          ハンドル取得結果
 * @retval          AG903_ENONE   正常終了
 * @retval          -AG903_EINVAL 引数異常
 * @retval          -AG903_EBUSY  使用できるハンドルが不足.
 * @description     空きCHを検索してハンドルを確保します。
*/
int32_t	AG903_TIMRMgrGetHandle(AG903_TIMRMgrHandle** handle)
{
	int32_t	 retval = AG903_ENONE;
	uint32_t loop;
	
	if(NULL == handle) {
		return -AG903_EINVAL;
	}
	
	for(loop=0; loop<AG903_TIMR_CH_NUM; loop++) {
		if(false == TimrHandleStat[loop].lock) {
			TimrHandleStat[loop].lock = true;
			break;
		}
	}
	if(AG903_TIMR_CH_NUM <= loop) {
		return -AG903_EBUSY;
	}
	
	(*handle) = (AG903_TIMRMgrHandle*)&TimrHandleStat[loop];
	
	return retval;
}

/**
 * @brief           チャンネル指定でのTIMRハンドル取得
 * @param           handle [out] TIMRハンドル
 * @return          ハンドル取得結果
 * @retval          AG903_ENONE   正常終了
 * @retval          -AG903_EINVAL 引数異常
 * @retval          -AG903_EBUSY  指定のチャンネルが使用中
 * @description     確実に指定のチャンネルを取得するため、
 *                  通常のAG903_TIMRMgrGetHandleよりも先に実行して下さい。
*/
int32_t	AG903_TIMRMgrGetHandleCh(AG903_TIMRMgrHandle** handle, int ch)
{
	int32_t	 retval = AG903_ENONE;
	
	if(NULL == handle) {
		return -AG903_EINVAL;
	}
	if (ch < 0 || AG903_TIMR_CH_NUM <= ch) {
		return -AG903_EINVAL;
	}
	
	if(false == TimrHandleStat[ch].lock) {
		TimrHandleStat[ch].lock = true;
	} else {
		return -AG903_EBUSY;
	}
	
	(*handle) = (AG903_TIMRMgrHandle*)&TimrHandleStat[ch];
	
	return retval;
}

/**
 * @brief           TIMRハンドル解放
 * @param           handle [in] TIMRハンドルval
 * @return          ハンドル解放結果
 * @retval          AG903_ENONE   正常終了
 * @retval          -AG903_EINVAL 引数異常
 * @retval          -AG903_EBUSY  ハンドル使用中(タイマ動作中).
 * @description     ハンドルを解放します。<p>動作中にハンドルが解放された場合はエラーを返します。
 * @note            必要に応じアプリでAG903_INTMgrDisableIntによりTIMRの割り込みを無効にして下さい。
*/
int32_t	AG903_TIMRMgrReleaseHandle(AG903_TIMRMgrHandle* handle)
{
	int32_t	 retval = AG903_ENONE;
	int32_t	 result;
	uint8_t	 ch;
	uint8_t	 idle;
	
	result = TIMRMgr_CheckHandle(handle, &ch);
	if(AG903_ENONE != result) {
		return -AG903_EINVAL;
	}
	idle = TIMRMgr_CheckIdle(ch);
	if(true != idle) {
		return -AG903_EBUSY;
	}
	
	TimrHandleStat[ch].lock = false;
	
	return retval;
}

/**
 * @brief           割込みハンドラの登録
 * @param           handle [in] TIMRハンドル
 * @param           func [in] 割込みハンドラの起動番地
 * @param           param [in] パラメータ
 * @return          割り込みハンドラ登録結果
 * @retval          AG903_ENONE   正常終了
 * @retval          -AG903_EINVAL 引数異常
 * @retval          -AG903_EFAULT  処理失敗 (ハンドラが登録出来ない).
 * @description     割り込みハンドラを登録します。<p>
 *                  paramはコールバック関数に引数として渡されます。void (*func)(void* param)<p>
 *                  ひとつのタイマに登録可能な割込みハンドラ数は AG903_TIMR_INTHDR_NUM で定義します。
 * @note            同一チャンネルに設定できる割り込みハンドラの最大数はAG903_OSWprCreIsrAutoでの
 *                  実装の最大数とAG903_TIMR_INTHDR_NUMでの定義値の小さいほうになります。
 *                  (T-Kernelでは通常1つまでです)
 * @note            同一のハンドラを複数回登録した場合はその登録数だけコールバックされます。<p>
 *                  またその場合登録したハンドラを削除する場合は AG903_TIMRMgrDeleteIntHandler を
 *                  登録数と同じだけ実行して下さい。一部のハンドラだけ削除した場合は正常に動作しなくなることがあります。
 * @note            AG903_TIMR_INTHDR_NUMは必要に応じて変更可能です(現在は2で動作を確認しています)
 * @note            TIMRMgrが内部的に割り込みを制御しているため動作中はアプリから
                    AG903_INTMgrDisableInt 等でタイマ割り込みに関する設定を変更しないで下さい。
 * @note            この関数は割り込みハンドラの中から呼び出すことはできません。
*/
int32_t	AG903_TIMRMgrSetIntHandler(AG903_TIMRMgrHandle* handle, void* func, void* param)
{
	AG903_INTMgrHdrPrm inthdr;
	int32_t	 retval = AG903_ENONE;
	int32_t	 result;
	int32_t	 hdrid;
	uint32_t loop;
	uint8_t	 ch;

	result = TIMRMgr_CheckHandle(handle, &ch);
	if(AG903_ENONE != result) {
		return -AG903_EINVAL;
	}
	if(NULL == func) {
		return -AG903_EINVAL;
	}
	for(loop=0; loop<AG903_TIMR_INTHDR_NUM;	loop++) {
		if(NULL == TimrChStat[ch].inthdr[loop].func) {
			break;
		}
	}
	if(AG903_TIMR_INTHDR_NUM <= loop) {
		return -AG903_EFAULT;
	}
	
	inthdr.atr   = AG903_INT_HLNG;
	inthdr.intno = AG903_IRQ0_TIM0+ch;
	inthdr.func  = func;
	inthdr.exinf = param;
	hdrid = AG903_INTMgrSetHandler(&inthdr);
	if(0 >= hdrid) {
		return -AG903_EFAULT;
	}
	AG903_INTMgrEnableInt(AG903_IRQ0_TIM0+ch);
	TimrChStat[ch].inthdr[loop].hdrid = hdrid;
	TimrChStat[ch].inthdr[loop].func  = func;
	
	return retval;
}

/**
 * @brief           割込みハンドラの削除
 * @param           handle [in] TIMRハンドル
 * @param           func [in] 割込みハンドラの起動番地
 * @return          割り込みハンドラの削除結果
 * @retval          AG903_ENONE   正常終了
 * @retval          -AG903_EINVAL 引数異常
 * @description     割り込みハンドラを削除します。
*/
int32_t	AG903_TIMRMgrDeleteIntHandler(AG903_TIMRMgrHandle* handle, void* func)
{
	int32_t	 retval = AG903_ENONE;
	int32_t	 result;
	uint32_t loop;
	uint8_t	 ch;
	
	result = TIMRMgr_CheckHandle(handle, &ch);
	if(AG903_ENONE != result) {
		return -AG903_EINVAL;
	}
	if(NULL == func) {
		return -AG903_EINVAL;
	}
	for(loop=0; loop<AG903_TIMR_INTHDR_NUM;	loop++) {
		if(func == TimrChStat[ch].inthdr[loop].func) {
			break;
		}
	}
	if(AG903_TIMR_INTHDR_NUM <= loop) {
		return -AG903_EINVAL;
	}
	
	retval = AG903_INTMgrDeleteHandler(TimrChStat[ch].inthdr[loop].hdrid);
	if(AG903_ENONE == retval) {
		TimrChStat[ch].inthdr[loop].hdrid = 0;
		TimrChStat[ch].inthdr[loop].func  = NULL;
	}

	return retval;
}

/**
 * @brief           ロータリーエンコーダ入力モード設定
 * @param           handle [in] TIMRハンドル
 * @param           param [in] パラメータ
 * @return          ロータリーエンコーダ入力モード設定結果
 * @retval          AG903_ENONE   正常終了
 * @retval          -AG903_EINVAL 引数異常
 * @retval          -AG903_EBUSY  ハンドル使用中 (タイマ動作中)
 * @description     ロータリーエンコーダ入力モードを設定します。<p>
 *                  本モードのタイマ動作詳細は『AX51903仕様書』を参照して下さい。
*/
int32_t	AG903_TIMRMgrSetRotaryEncoderMode(AG903_TIMRMgrHandle* handle, AG903_TIMRMgrRotaryEncParam* param)
{
	AG903_TIMRPrmInModeParam		inprm  = {0};
	AG903_TIMRPrmOutModeParam		outprm = {0};
	AG903_TIMRPrmResetTriggerParam 	rstprm = {0};
	int32_t	 retval = AG903_ENONE;
	int32_t	 result;
	uint8_t	 ch;
	uint8_t	 idle;
	
	result = TIMRMgr_CheckHandle(handle, &ch);
	if(AG903_ENONE != result) {
		return -AG903_EINVAL;
	}
	if(NULL == param) {
		return -AG903_EINVAL;
	}
	if( (AG903_TIMR_INPUT_RETYPENUM <= param->intype) ||
		(AG903_TIMR_CNT_TYPENUM <= param->sampling) ) {
		return -AG903_EINVAL;
	}
	if(NULL != param->output) {
		if( (AG903_TIMR_EXTOUT_NUM  <= param->output->portch)   ||
		    (AG903_TIMR_POL_TYPENUM <= param->output->polarity) ||
		    (AG903_TIMR_OUT_PWM <= param->output->mode)		    || /* PWM出力 設定不可 */
		    ((AG903_TIMR_OUT_PLUSE == param->output->mode)&&(AG903_TIMR_PLUSEWIDTH_MAX < param->output->plusewidth)) ) {
			return -AG903_EINVAL;
		}
	}
	idle = TIMRMgr_CheckIdle(ch);
	if(true != idle) {
		return -AG903_EBUSY;
	}
	
	inprm.res = TimrResolutionTypeTbl[param->sampling];
	inprm.lo  = TimrInputReTbl[param->intype][0];
	inprm.ch  = TimrInputReTbl[param->intype][1];
	AG903_TIMRPrmSetInMode(ch, &inprm);
	AG903_TIMRPrmSetPeriod(ch, param->range);
	AG903_TIMRPrmSetMatch(ch, param->match);

	if(NULL == param->output) {
		outprm.mod = AG903_TIMR_OUTMOD_DISABLE;
	}
	else {
		outprm.ovf = 1;	/* RotaryEncoder入力モードはOVF検出なし */
		outprm.ch  = param->output->portch;
		outprm.pol = param->output->polarity;
		outprm.mod = TimrOutModeTbl[param->output->mode];
	}
	AG903_TIMRPrmSetOutMode(ch, &outprm);
	if(AG903_TIMR_OUTMOD_PLUSE == outprm.mod) {
		AG903_TIMRPrmSetPluseWidth(ch, param->output->plusewidth);
	}
	
 	rstprm.en = AG903_TIMR_RSTEN_DISABLE;
	AG903_TIMRPrmSetResetTrigger(ch, &rstprm);
	
	TimrChStat[ch].outmode = outprm.mod;
	TimrChStat[ch].mode    = AG903_TIMR_CTRLMOD_REIN;

	return retval;
}

/**
 * @brief           PWM入力モード設定
 * @param           handle [in] TIMRハンドル
 * @param           param [in] パラメータ
 * @return          PWM入力モード設定結果
 * @retval          AG903_ENONE   正常終了
 * @retval          -AG903_EINVAL 引数異常
 * @retval          -AG903_EBUSY  ハンドル使用中 (タイマ動作中).
 * @description     PWM入力モードを設定します。<p>
 *                  本モードのタイマ動作詳細は『AX51903仕様書』を参照して下さい。
*/
int32_t	AG903_TIMRMgrSetPwmInMode(AG903_TIMRMgrHandle* handle, AG903_TIMRMgrPwmInParam* param)
{
	AG903_TIMRPrmInModeParam		inprm  = {0};
	AG903_TIMRPrmOutModeParam		outprm = {0};
	AG903_TIMRPrmResetTriggerParam 	rstprm = {0};
	int32_t	 retval = AG903_ENONE;
	int32_t	 result;
	uint8_t	 ch;
	uint8_t	 idle;
	
	result = TIMRMgr_CheckHandle(handle, &ch);
	if(AG903_ENONE != result) {
		return -AG903_EINVAL;
	}
	if(NULL == param) {
		return -AG903_EINVAL;
	}
	if( (AG903_TIMR_INPUT_TYPENUM <= param->intype)   ||
		(AG903_TIMR_CNT_TYPENUM <= param->resolution) ||
		(AG903_TIMR_POL_TYPENUM <= param->polarity) ) {
		return -AG903_EINVAL;
	}
	if(NULL != param->output) {
		if( (AG903_TIMR_EXTOUT_NUM  <= param->output->portch)   ||
		    (AG903_TIMR_POL_TYPENUM <= param->output->polarity) ||
		    (AG903_TIMR_OUT_PWM <= param->output->mode)		    || /* PWM出力 設定不可 */
		    ((AG903_TIMR_OUT_PLUSE == param->output->mode)&&(AG903_TIMR_PLUSEWIDTH_MAX < param->output->plusewidth)) ) {
			return -AG903_EINVAL;
		}
	}
	idle = TIMRMgr_CheckIdle(ch);
	if(true != idle) {
		return -AG903_EBUSY;
	}
	
	inprm.res = TimrResolutionTypeTbl[param->resolution];
	inprm.lo  = TimrInputTbl[param->intype][0];
	inprm.ch  = TimrInputTbl[param->intype][1];
	inprm.pol = param->polarity;
	AG903_TIMRPrmSetInMode(ch, &inprm);
	if(true == param->oneshot) {
		AG903_TIMRPrmEnableOneshot(ch);
	}
	else {
		AG903_TIMRPrmDisableOneshot(ch);
	}

	if(NULL == param->output) {
		outprm.mod = AG903_TIMR_OUTMOD_DISABLE;
	}
	else {
		outprm.cm  = 1;	/* PWM入力モードはCM検出なし */
		outprm.ch  = param->output->portch;
		outprm.pol = param->output->polarity;
		outprm.mod = TimrOutModeTbl[param->output->mode];
	}
	AG903_TIMRPrmSetOutMode(ch, &outprm);
	if(AG903_TIMR_OUTMOD_PLUSE == outprm.mod) {
		AG903_TIMRPrmSetPluseWidth(ch, param->output->plusewidth);
	}

 	rstprm.en = AG903_TIMR_RSTEN_DISABLE;
	AG903_TIMRPrmSetResetTrigger(ch, &rstprm);

	TimrChStat[ch].outmode = outprm.mod;
	TimrChStat[ch].mode    = AG903_TIMR_CTRLMOD_PWMIN;

	return retval;
}

/**
 * @brief           クロック・Tick計測モード設定
 * @param           handle [in] TIMRハンドル
 * @param           param [in] パラメータ
 * @return          AG903_ENONE   正常終了
 * @return          -AG903_EINVAL 引数異常
 * @return          -AG903_EBUSY  ハンドル使用中 (タイマ動作中).
 * @description     クロック・Tick計測モードを設定します。<p>
 *                  本モードのタイマ動作詳細は『AX51903仕様書』を参照して下さい。
*/
int32_t	AG903_TIMRMgrSetTickCountMode(AG903_TIMRMgrHandle* handle, AG903_TIMRMgrTickCntParam* param)
{
	AG903_TIMRPrmInModeParam		inprm  = {0};
	AG903_TIMRPrmOutModeParam		outprm = {0};
	AG903_TIMRPrmResetTriggerParam 	rstprm = {0};
	int32_t	 retval = AG903_ENONE;
	int32_t	 result;
	uint8_t	 ch;
	uint8_t	 idle;
	
	result = TIMRMgr_CheckHandle(handle, &ch);
	if(AG903_ENONE != result) {
		return -AG903_EINVAL;
	}
	if(NULL == param) {
		return -AG903_EINVAL;
	}
	if(AG903_TIMR_CNT_TYPENUM <= param->resolution) {
		return -AG903_EINVAL;
	}
	if(NULL != param->output) {
		if( (AG903_TIMR_EXTOUT_NUM  <= param->output->portch)   ||
		    (AG903_TIMR_POL_TYPENUM <= param->output->polarity) ||
		    (AG903_TIMR_OUT_MODENUM <= param->output->mode)		||
		    ((AG903_TIMR_OUT_PLUSE == param->output->mode)&&(AG903_TIMR_PLUSEWIDTH_MAX < param->output->plusewidth)) ) {
			return -AG903_EINVAL;
		}
	}
	idle = TIMRMgr_CheckIdle(ch);
	if(true != idle) {
		return -AG903_EBUSY;
	}
	
	inprm.res = TimrResolutionTypeTbl[param->resolution];
	AG903_TIMRPrmSetInMode(ch, &inprm);
	AG903_TIMRPrmSetPeriod(ch, param->period);
	AG903_TIMRPrmSetMatch(ch, param->match);
	if(true == param->oneshot) {
		AG903_TIMRPrmEnableOneshot(ch);
	}
	else {
		AG903_TIMRPrmDisableOneshot(ch);
	}
	
	if(NULL == param->output) {
		outprm.mod = AG903_TIMR_OUTMOD_DISABLE;
	}
	else {
		if(AG903_TIMR_COMPARE_BIT & param->output->mask) {
			outprm.cm  = 1;	/* 1b：マスク有効 */
		}
		if(AG903_TIMR_OVERFLOW_BIT & param->output->mask) {
			outprm.ovf = 1;	/* 1b：マスク有効 */
		}
		outprm.ch  = param->output->portch;
		outprm.pol = param->output->polarity;
		outprm.mod = TimrOutModeTbl[param->output->mode];
	}
	AG903_TIMRPrmSetOutMode(ch, &outprm);
	if(AG903_TIMR_OUTMOD_PLUSE == outprm.mod) {
		AG903_TIMRPrmSetPluseWidth(ch, param->output->plusewidth);
	}
	
 	rstprm.en   = AG903_TIMR_RSTEN_DISABLE;
 	rstprm.boot = AG903_TIMR_RSTBOOT_TICKCNT;
	AG903_TIMRPrmSetResetTrigger(ch, &rstprm);
	
	TimrChStat[ch].outmode = outprm.mod;
	TimrChStat[ch].mode    = AG903_TIMR_CTRLMOD_TICKCNT;
	
	return retval;
}

/**
 * @brief           内部イベント計測モード設定
 * @param           handle [in] TIMRハンドル
 * @param           param [in] パラメータ
 * @return          内部イベント計測モード設定結果
 * @retval          AG903_ENONE   正常終了
 * @retval          -AG903_EINVAL 引数異常
 * @retval          -AG903_EBUSY  ハンドル使用中 (タイマ動作中).
 * @description     内部イベント計測モードを設定します。<p>
 *                  本モードのタイマ動作詳細は『AX51903仕様書』を参照して下さい。
*/
int32_t	AG903_TIMRMgrSetEventCountMode(AG903_TIMRMgrHandle* handle, AG903_TIMRMgrEventCntParam* param)
{
	AG903_TIMRPrmInModeParam		inprm  = {0};
	AG903_TIMRPrmOutModeParam		outprm = {0};
	AG903_TIMRPrmResetTriggerParam 	rstprm = {0};
	int32_t	 retval = AG903_ENONE;
	int32_t	 result;
	uint8_t	 ch;
	uint8_t	 idle;
	
	result = TIMRMgr_CheckHandle(handle, &ch);
	if(AG903_ENONE != result) {
		return -AG903_EINVAL;
	}
	if(NULL == param) {
		return -AG903_EINVAL;
	}
	if(AG903_TIMR_EVENT_NUM <= param->event) {
		return -AG903_EINVAL;
	}
	if(NULL != param->output) {
		if( (AG903_TIMR_EXTOUT_NUM  <= param->output->portch)   ||
		    (AG903_TIMR_POL_TYPENUM <= param->output->polarity) ||
		    (AG903_TIMR_OUT_PWM <= param->output->mode)		    || /* PWM出力 設定不可 */
		    ((AG903_TIMR_OUT_PLUSE == param->output->mode)&&(AG903_TIMR_PLUSEWIDTH_MAX < param->output->plusewidth)) ) {
			return -AG903_EINVAL;
		}
	}
	idle = TIMRMgr_CheckIdle(ch);
	if(true != idle) {
		return -AG903_EBUSY;
	}
	
	inprm.eve = param->event;
	AG903_TIMRPrmSetInMode(ch, &inprm);
	AG903_TIMRPrmSetPeriod(ch, param->period);
	AG903_TIMRPrmSetMatch(ch, param->match);
	if(true == param->oneshot) {
		AG903_TIMRPrmEnableOneshot(ch);
	}
	else {
		AG903_TIMRPrmDisableOneshot(ch);
	}

	if(NULL == param->output) {
		outprm.mod = AG903_TIMR_OUTMOD_DISABLE;
	}
	else {
		if(AG903_TIMR_COMPARE_BIT & param->output->mask) {
			outprm.cm  = 1;	/* 1b：マスク有効 */
		}
		if(AG903_TIMR_OVERFLOW_BIT & param->output->mask) {
			outprm.ovf = 1;	/* 1b：マスク有効 */
		}
		outprm.ch  = param->output->portch;
		outprm.pol = param->output->polarity;
		outprm.mod = TimrOutModeTbl[param->output->mode];
	}
	AG903_TIMRPrmSetOutMode(ch, &outprm);
	if(AG903_TIMR_OUTMOD_PLUSE == outprm.mod) {
		AG903_TIMRPrmSetPluseWidth(ch, param->output->plusewidth);
	}
	
 	rstprm.en   = AG903_TIMR_RSTEN_DISABLE;
 	rstprm.boot = AG903_TIMR_RSTBOOT_EVENTCNT;
	AG903_TIMRPrmSetResetTrigger(ch, &rstprm);
	
	TimrChStat[ch].outmode = outprm.mod;
	TimrChStat[ch].mode    = AG903_TIMR_CTRLMOD_EVENTCNT;

	return retval;
}

/**
 * @brief           入力端子パルス計測モード設定
 * @param           handle [in] TIMRハンドル
 * @param           param [in] パラメータ
 * @return          入力端子パルス計測モード設定結果
 * @retval          AG903_ENONE   正常終了
 * @retval          -AG903_EINVAL 引数異常
 * @retval          -AG903_EBUSY  ハンドル使用中 (タイマ動作中).
 * @description     入力端子パルス計測モードを設定します。<p>
 *                  本モードのタイマ動作詳細は『AX51903仕様書』を参照して下さい。
*/
int32_t	AG903_TIMRMgrSetPulseCountMode(AG903_TIMRMgrHandle* handle, AG903_TIMRMgrPulseCntParam* param)
{
	AG903_TIMRPrmInModeParam		inprm  = {0};
	AG903_TIMRPrmOutModeParam		outprm = {0};
	AG903_TIMRPrmResetTriggerParam 	rstprm = {0};
	int32_t	 retval = AG903_ENONE;
	int32_t	 result;
	uint8_t	 ch;
	uint8_t	 idle;
	
	result = TIMRMgr_CheckHandle(handle, &ch);
	if(AG903_ENONE != result) {
		return -AG903_EINVAL;
	}
	if(NULL == param) {
		return -AG903_EINVAL;
	}
	if( (AG903_TIMR_INPUT_TYPENUM <= param->intype) ||
		(AG903_TIMR_CNT_TYPENUM <= param->sampling) ||
		(AG903_TIMR_POL_TYPENUM <= param->polarity) ) {
		return -AG903_EINVAL;
	}
	if(NULL != param->output) {
		if( (AG903_TIMR_EXTOUT_NUM  <= param->output->portch)   ||
		    (AG903_TIMR_POL_TYPENUM <= param->output->polarity) ||
		    (AG903_TIMR_OUT_PWM <= param->output->mode)		    || /* PWM出力 設定不可 */
		    ((AG903_TIMR_OUT_PLUSE == param->output->mode)&&(AG903_TIMR_PLUSEWIDTH_MAX < param->output->plusewidth)) ) {
			return -AG903_EINVAL;
		}
	}
	idle = TIMRMgr_CheckIdle(ch);
	if(true != idle) {
		return -AG903_EBUSY;
	}
	
	inprm.res = TimrResolutionTypeTbl[param->sampling];
	inprm.lo  = TimrInputTbl[param->intype][0];
	inprm.ch  = TimrInputTbl[param->intype][1];
	inprm.pol = param->polarity;
	AG903_TIMRPrmSetInMode(ch, &inprm);
	AG903_TIMRPrmSetPeriod(ch, param->period);
	AG903_TIMRPrmSetMatch(ch, param->match);
	if(true == param->oneshot) {
		AG903_TIMRPrmEnableOneshot(ch);
	}
	else {
		AG903_TIMRPrmDisableOneshot(ch);
	}
	
	if(NULL == param->output) {
		outprm.mod = AG903_TIMR_OUTMOD_DISABLE;
	}
	else {
		if(AG903_TIMR_COMPARE_BIT & param->output->mask) {
			outprm.cm  = 1;	/* 1b：マスク有効 */
		}
		if(AG903_TIMR_OVERFLOW_BIT & param->output->mask) {
			outprm.ovf = 1;	/* 1b：マスク有効 */
		}
		outprm.ch  = param->output->portch;
		outprm.pol = param->output->polarity;
		outprm.mod = TimrOutModeTbl[param->output->mode];
	}
	AG903_TIMRPrmSetOutMode(ch, &outprm);
	if(AG903_TIMR_OUTMOD_PLUSE == outprm.mod) {
		AG903_TIMRPrmSetPluseWidth(ch, param->output->plusewidth);
	}

 	rstprm.en   = AG903_TIMR_RSTEN_DISABLE;
 	rstprm.boot = AG903_TIMR_RSTBOOT_PLUSECNT;
	AG903_TIMRPrmSetResetTrigger(ch, &rstprm);

	TimrChStat[ch].outmode = outprm.mod;
	TimrChStat[ch].mode    = AG903_TIMR_CTRLMOD_PLUSECNT;

	return retval;
}

/**
 * @brief           入力端子レベル計測モード設定
 * @param           handle [in] TIMRハンドル
 * @param           param [in] パラメータ
 * @return          入力端子レベル計測モード設定結果
 * @retval          AG903_ENONE   正常終了
 * @retval          -AG903_EINVAL 引数異常
 * @retval          -AG903_EBUSY  ハンドル使用中 (タイマ動作中).
 * @description     入力端子レベル計測モードを設定します。<p>
 *                  本モードのタイマ動作詳細は『AX51903仕様書』を参照して下さい。
*/
int32_t	AG903_TIMRMgrSetLevelCountMode(AG903_TIMRMgrHandle* handle, AG903_TIMRMgrLevelCntParam* param)
{
	AG903_TIMRPrmInModeParam		inprm  = {0};
	AG903_TIMRPrmOutModeParam		outprm = {0};
	AG903_TIMRPrmResetTriggerParam 	rstprm = {0};
	int32_t	 retval = AG903_ENONE;
	int32_t	 result;
	uint8_t	 ch;
	uint8_t	 idle;
	
	result = TIMRMgr_CheckHandle(handle, &ch);
	if(AG903_ENONE != result) {
		return -AG903_EINVAL;
	}
	if(NULL == param) {
		return -AG903_EINVAL;
	}
	if( (AG903_TIMR_INPUT_TYPENUM <= param->intype) ||
		(AG903_TIMR_CNT_TYPENUM <= param->sampling) ||
		(AG903_TIMR_POL_TYPENUM <= param->polarity) ) {
		return -AG903_EINVAL;
	}
	if(NULL != param->output) {
		if( (AG903_TIMR_EXTOUT_NUM  <= param->output->portch)   ||
		    (AG903_TIMR_POL_TYPENUM <= param->output->polarity) ||
		    (AG903_TIMR_OUT_PWM <= param->output->mode)		    || /* PWM出力 設定不可 */
		    ((AG903_TIMR_OUT_PLUSE == param->output->mode)&&(AG903_TIMR_PLUSEWIDTH_MAX < param->output->plusewidth)) ) {
			return -AG903_EINVAL;
		}
	}
	idle = TIMRMgr_CheckIdle(ch);
	if(true != idle) {
		return -AG903_EBUSY;
	}
	
	inprm.res = TimrResolutionTypeTbl[param->sampling];
	inprm.lo  = TimrInputTbl[param->intype][0];
	inprm.ch  = TimrInputTbl[param->intype][1];
	inprm.pol = param->polarity;
	AG903_TIMRPrmSetInMode(ch, &inprm);
	AG903_TIMRPrmSetPeriod(ch, param->period);
	AG903_TIMRPrmSetMatch(ch, param->match);
	if(true == param->oneshot) {
		AG903_TIMRPrmEnableOneshot(ch);
	}
	else {
		AG903_TIMRPrmDisableOneshot(ch);
	}
	
	if(NULL == param->output) {
		outprm.mod = AG903_TIMR_OUTMOD_DISABLE;
	}
	else {
		if(AG903_TIMR_COMPARE_BIT & param->output->mask) {
			outprm.cm  = 1;	/* 1b：マスク有効 */
		}
		if(AG903_TIMR_OVERFLOW_BIT & param->output->mask) {
			outprm.ovf = 1;	/* 1b：マスク有効 */
		}
		outprm.ch  = param->output->portch;
		outprm.pol = param->output->polarity;
		outprm.mod = TimrOutModeTbl[param->output->mode];
	}
	AG903_TIMRPrmSetOutMode(ch, &outprm);
	if(AG903_TIMR_OUTMOD_PLUSE == outprm.mod) {
		AG903_TIMRPrmSetPluseWidth(ch, param->output->plusewidth);
	}
	
 	rstprm.en   = AG903_TIMR_RSTEN_DISABLE;
 	rstprm.boot = AG903_TIMR_RSTBOOT_LEVELCNT;
	AG903_TIMRPrmSetResetTrigger(ch, &rstprm);
	
	TimrChStat[ch].outmode = outprm.mod;
	TimrChStat[ch].mode    = AG903_TIMR_CTRLMOD_LEVELCNT;

	return retval;
}

/**
 * @brief           タイマ起動
 * @param           handle [in] TIMRハンドル
 * @return          タイマ起動結果
 * @retval          AG903_ENONE   正常終了
 * @retval          -AG903_EINVAL 引数異常
 * @retval          -AG903_EBUSY  ハンドル使用中 (タイマ動作中).
 * @retval          -AG903_EFAULT 処理失敗 (動作モード不正).
 * @description     タイマ起動の設定をします。<p>
 *                  次の関数で設定されたモードでタイマを起動します。<p>
 *                  AG903_TIMRMgrSetRotaryEncoderMode , AG903_TIMRMgrSetPwmInMode , AG903_TIMRMgrSetTickCountMode,<p>
 *                  AG903_TIMRMgrSetEventCountMode , AG903_TIMRMgrSetPulseCountMode , AG903_TIMRMgrSetLevelCountMode
 * @note            先に動作モードの設定を行う必要があります。
*/
int32_t	AG903_TIMRMgrStart(AG903_TIMRMgrHandle* handle)
{
	int32_t	 retval = AG903_ENONE;
	int32_t	 result;
	uint8_t	 ch;
	uint8_t	 idle;
	
	result = TIMRMgr_CheckHandle(handle, &ch);
	if(AG903_ENONE != result) {
		return -AG903_EINVAL;
	}
	if(AG903_TIMR_CTRLMOD_MODENUM <= TimrChStat[ch].mode) {
		return -AG903_EFAULT;
	}
	idle = TIMRMgr_CheckIdle(ch);
	if(true != idle) {
		return -AG903_EBUSY;
	}
	
	AG903_TIMRPrmSetCntMode(ch, TimrChStat[ch].mode);
	
	return retval;
}

/**
 * @brief           タイマ停止
 * @param           handle [in] TIMRハンドル
 * @return          タイマ停止結果
 * @retval          AG903_ENONE   正常終了
 * @retval          -AG903_EINVAL 引数異常
 * @description     タイマを動作停止にします。
*/
int32_t	AG903_TIMRMgrStop(AG903_TIMRMgrHandle* handle)
{
	int32_t	 retval = AG903_ENONE;
	int32_t	 result;
	uint8_t	 ch;
	
	result = TIMRMgr_CheckHandle(handle, &ch);
	if(AG903_ENONE != result) {
		return -AG903_EINVAL;
	}

	AG903_TIMRPrmSetCntMode(ch, AG903_TIMR_CTRLMOD_STOP);
	
	return retval;
}

/**
 * @brief           タイマ起動（複数指定）
 * @param           chbit [in] TIMRチャネル（ビット指定、複数ビット可）
 * @return          タイマ起動（複数指定）結果
 * @retval          AG903_ENONE   正常終了
 * @description     タイマ起動（複数指定）の設定をします。<p>
 *                  TIMBOOTTRG を chbit でWriteします。
 * @note            以下の動作モードのタイマは指定しないで下さい。<p>
 *                  ・ロータリーエンコーダ入力モード<p>
 *                  ・PWM入力モード
*/
int32_t	AG903_TIMRMgrStartMulti(uint8_t chbit)
{
	int32_t	 retval = AG903_ENONE;
	
	AG903_TIMRPrmSetBootTrigger(chbit);
	
	return retval;
}

/**
 * @brief           リセットトリガ設定（Enable）
 * @param           handle [in] TIMRハンドル
 * @param           param [in] パラメータ
 * @retval          AG903_ENONE   正常終了
 * @retval          -AG903_EINVAL 引数異常
 * @retval          -AG903_EFAULT 処理失敗 (動作モード不正).
 * @description     リセットトリガを設定（Enable）にします。
 * @note            先に動作モードの設定を行う必要があります。<p>
 *                  動作モード未設定及びロータリーエンコーダ入力モード、PWM入力モードが設定されている<p>
 *                  タイマにはリセットトリガは設定出来ません
*/
int32_t	AG903_TIMRMgrEnableResetTrigger(AG903_TIMRMgrHandle* handle, AG903_TIMRMgrResetParam* param)
{
	AG903_TIMRPrmResetTriggerParam 	rstprm = {0};
	int32_t	 retval = AG903_ENONE;
	int32_t	 result;
	uint8_t	 ch;
	
	result = TIMRMgr_CheckHandle(handle, &ch);
	if(AG903_ENONE != result) {
		return -AG903_EINVAL;
	}
	if(NULL == param) {
		return -AG903_EINVAL;
	}
	if(AG903_TIMR_RSTTRG_TYPENUM <= param->trigger) {
		return -AG903_EINVAL;
	}
	if(AG903_TIMR_RSTTRG_EXTPORT == param->trigger) {
		if( (AG903_TIMR_INPUT_TYPENUM <= param->intype)   ||
			(AG903_TIMR_CNT_TYPENUM   <= param->sampling) ||
			(AG903_TIMR_POL_TYPENUM   <= param->polarity) ) {
			return -AG903_EINVAL;
		}
	}
	else  {
		if(AG903_TIMR_EVENT_NUM <= param->event) {
			return -AG903_EINVAL;
		}
	}
	
	switch(TimrChStat[ch].mode) {
		case AG903_TIMR_CTRLMOD_TICKCNT:
			rstprm.boot = AG903_TIMR_RSTBOOT_TICKCNT;
			break;
		case AG903_TIMR_CTRLMOD_EVENTCNT:
			rstprm.boot = AG903_TIMR_RSTBOOT_EVENTCNT;
			break;
		case AG903_TIMR_CTRLMOD_PLUSECNT:
			rstprm.boot = AG903_TIMR_RSTBOOT_PLUSECNT;
			break;
		case AG903_TIMR_CTRLMOD_LEVELCNT:
			rstprm.boot = AG903_TIMR_RSTBOOT_LEVELCNT;
			break;
		default:
			retval = -AG903_EFAULT;	/* リセット起動対象は上記のモードのみ */
			break;
	}

	if(AG903_ENONE == retval) {
		rstprm.en = TimrResetTriggerTbl[param->trigger];
		if(AG903_TIMR_RSTEN_EXTPORT == rstprm.en) {
			rstprm.res = TimrResolutionTypeTbl[param->sampling];
			rstprm.lo  = TimrInputTbl[param->intype][0];
			rstprm.ch  = TimrInputTbl[param->intype][1];
			rstprm.pol = param->polarity;
		}
		else {
			rstprm.eve = param->event;
		}
		AG903_TIMRPrmSetResetTrigger(ch, &rstprm);
	}

	return retval;
}

/**
 * @brief           リセットトリガ無効設定（Disable）
 * @param           handle [in] TIMRハンドル
 * @return          リセットトリガ無効設定（Disable）結果
 * @retval          AG903_ENONE   正常終了
 * @retval          -AG903_EINVAL 引数異常
 * @description     リセットトリガを無効設定（Disable）にします。<p>
 *                  AG903_TIMRMgrEnableResetTrigger で設定されたリセットトリガを無効化します。
*/
int32_t	AG903_TIMRMgrDisableResetTrigger(AG903_TIMRMgrHandle* handle)
{
	AG903_TIMRPrmResetTriggerParam 	rstprm = {0};
	int32_t	 retval = AG903_ENONE;
	int32_t	 result;
	uint8_t	 ch;
	
	result = TIMRMgr_CheckHandle(handle, &ch);
	if(AG903_ENONE != result) {
		return -AG903_EINVAL;
	}

 	rstprm.en = AG903_TIMR_RSTEN_DISABLE;
	AG903_TIMRPrmSetResetTrigger(ch, &rstprm);

	return retval;
}

/**
 * @brief           ワンショット動作設定（Enable）
 * @param           handle [in] TIMRハンドル
 * @return          ワンショット動作設定（Enable）の結果
 * @retval          AG903_ENONE   正常終了
 * @retval          -AG903_EINVAL 引数異常
 * @retval          -AG903_EFAULT 処理失敗 (動作モード不正).
 * @description     ワンショット動作設定（Enable）をします。<p>
 *                  タイマ動作がピリオディックだった場合、ワンショットに変更します。
 * @note            先に動作モードの設定を行う必要があります。<p>
 *                  ロータリーエンコーダ入力モード時は無効です。
*/
int32_t	AG903_TIMRMgrEnableOneShot(AG903_TIMRMgrHandle* handle)
{
	int32_t	 retval = AG903_ENONE;
	int32_t	 result;
	uint8_t	 ch;
	
	result = TIMRMgr_CheckHandle(handle, &ch);
	if(AG903_ENONE != result) {
		return -AG903_EINVAL;
	}
	if(AG903_TIMR_CTRLMOD_REIN == TimrChStat[ch].mode) {
		return -AG903_EFAULT;
	}
	
	AG903_TIMRPrmEnableOneshot(ch);
	
	return retval;
}

/**
 * @brief           ワンショット動作無効設定（Disable）
 * @param           handle [in] TIMRハンドル
 * @return          ワンショット動作無効設定（Disable）結果
 * @retval          AG903_ENONE   正常終了
 * @retval          -AG903_EINVAL 引数異常
 * @description     ワンショット動作無効設定（Disable）をします。<p>
 *                  タイマ動作がワンショットだった場合、ピリオディックに変更します。
*/
int32_t	AG903_TIMRMgrDisableOneShot(AG903_TIMRMgrHandle* handle)
{
	int32_t	 retval = AG903_ENONE;
	int32_t	 result;
	uint8_t	 ch;
	
	result = TIMRMgr_CheckHandle(handle, &ch);
	if(AG903_ENONE != result) {
		return -AG903_EINVAL;
	}
	
	AG903_TIMRPrmDisableOneshot(ch);
	
	return retval;
}

/**
 * @brief           割込みマスク設定
 * @param           handle [in] TIMRハンドル
 * @param           target [in] 操作対象（ビット指定）
 * @return          割込みマスク設定結果
 * @retval          AG903_ENONE   正常終了
 * @retval          -AG903_EINVAL 引数異常
 * @description     割込みマスクを設定します。<p>
 *                  targetで指定した割込みがマスクされます。<p>
 *                  <table>
 *                  <tr><th>bit</th><th>割込み</th></tr>
 *                  <tr><td>1</td><td>コンペア・マッチ割込み</td></tr>
 *                  <tr><td>0</td><td>オーバーフロー割込み</td></tr>
 *                  </table>
 *                  1を設定するとマスク対象になります。
*/
int32_t	AG903_TIMRMgrEnableIntMask(AG903_TIMRMgrHandle* handle, uint8_t target)
{
	int32_t	 retval = AG903_ENONE;
	int32_t	 result;
	uint32_t setbit = 0;
	uint8_t	 ch;
	
	result = TIMRMgr_CheckHandle(handle, &ch);
	if(AG903_ENONE != result) {
		return -AG903_EINVAL;
	}
	
	if(AG903_TIMR_COMPARE_BIT & target) {
		setbit |= AG903_TIMR_INTMSK_CM_BIT;
	}
	if(AG903_TIMR_OVERFLOW_BIT & target) {
		setbit |= AG903_TIMR_INTMSK_OVF_BIT;
	}
	
	if(0 != setbit) {
		AG903_TIMRPrmEnableMask(ch, setbit);
	}
	
	return retval;
}

/**
 * @brief           割込みマスク無効設定（マスク解除）
 * @param           handle [in] TIMRハンドル
 * @param           target [in] 操作対象（ビット指定）
 * @return          割込みマスク無効設定（マスク解除）結果
 * @retval          AG903_ENONE   正常終了
 * @retval          -AG903_EINVAL 引数異常
 * @description     割込みマスク無効設定（マスク解除）をします。<p>
 *                  targetで指定した割込みがマスク解除されます。<p>
 *                  <table>
 *                  <tr><th>bit</th><th>割込み</th></tr>
 *                  <tr><td>1</td><td>コンペア・マッチ割込み</td></tr>
 *                  <tr><td>0</td><td>オーバーフロー割込み</td></tr>
 *                  </table>
 *                  1を設定するとマスク解除になります。
*/
int32_t	AG903_TIMRMgrDisableIntMask(AG903_TIMRMgrHandle* handle, uint8_t target)
{
	int32_t	 retval = AG903_ENONE;
	int32_t	 result;
	uint8_t  clrbit = 0;
	uint8_t	 ch;
	
	result = TIMRMgr_CheckHandle(handle, &ch);
	if(AG903_ENONE != result) {
		return -AG903_EINVAL;
	}
	
	if(AG903_TIMR_COMPARE_BIT & target) {
		clrbit |= AG903_TIMR_INTMSK_CM_BIT;
	}
	if(AG903_TIMR_OVERFLOW_BIT & target) {
		clrbit |= AG903_TIMR_INTMSK_OVF_BIT;
	}
	
	if(0 != clrbit) {
		AG903_TIMRPrmDisableMask(ch, clrbit);
	}
	
	return retval;
}

/**
 * @brief           イベントトリガ設定（Enable）
 * @param           handle [in] TIMRハンドル
 * @param           target [in] 操作対象（ビット指定）
 * @return          イベントトリガ設定（Enable）結果
 * @retval          AG903_ENONE   正常終了
 * @retval          -AG903_EINVAL 引数異常
 * @description     イベントトリガ設定（Enable）をします。<p>
 *                  targetで指定した条件でイベントトリガが生成されます。<p>
 *                  <table>
 *                  <tr><th>bit</th><th>割込み</th></tr>
 *                  <tr><td>1</td><td>コンペア・マッチ割込み</td></tr>
 *                  <tr><td>0</td><td>オーバーフロー割込み</td></tr>
 *                  </table>
 *                  1を設定するとイベントトリガが生成されます。
*/
int32_t	AG903_TIMRMgrEnableEventTrigger(AG903_TIMRMgrHandle* handle, uint8_t target)
{
	int32_t	 retval = AG903_ENONE;
	int32_t	 result;
	uint32_t setbit = 0;
	uint8_t	 ch;
	
	result = TIMRMgr_CheckHandle(handle, &ch);
	if(AG903_ENONE != result) {
		return -AG903_EINVAL;
	}
	
	if(AG903_TIMR_COMPARE_BIT & target) {
		setbit |= AG903_TIMR_TRIGGER_CM_BIT;
	}
	if(AG903_TIMR_OVERFLOW_BIT & target) {
		setbit |= AG903_TIMR_TRIGGER_OVF_BIT;
	}
	
	if(0 != setbit) {
		AG903_TIMRPrmEnableEventTrigger(ch, setbit);
	}
	
	return retval;
}

/**
 * @brief           イベントトリガ無効設定（Disable）
 * @param           handle [in] TIMRハンドル
 * @param           target [in] 操作対象（ビット指定）
 * @return          イベントトリガ無効設定（Disable）結果
 * @retval          AG903_ENONE   正常終了
 * @retval          -AG903_EINVAL 引数異常
 * @description     イベントトリガ無効設定（Disable）をします。<p>
 *                  targetで指定した条件でイベントトリガ生成が無効化されます。<p>
 *                  <table>
 *                  <tr><th>bit</th><th>割込み</th></tr>
 *                  <tr><td>1</td><td>コンペア・マッチ割込み</td></tr>
 *                  <tr><td>0</td><td>オーバーフロー割込み</td></tr>
 *                  </table>
 *                  1を設定するとイベントトリガ生成が無効化されます。
*/
int32_t	AG903_TIMRMgrDisableEventTrigger(AG903_TIMRMgrHandle* handle, uint8_t target)
{
	int32_t	 retval = AG903_ENONE;
	int32_t	 result;
	uint32_t clrbit = 0;
	uint8_t	 ch;
	
	result = TIMRMgr_CheckHandle(handle, &ch);
	if(AG903_ENONE != result) {
		return -AG903_EINVAL;
	}
	
	if(AG903_TIMR_COMPARE_BIT & target) {
		clrbit |= AG903_TIMR_TRIGGER_CM_BIT;
	}
	if(AG903_TIMR_OVERFLOW_BIT & target) {
		clrbit |= AG903_TIMR_TRIGGER_OVF_BIT;
	}
	
	if(0 != clrbit) {
		AG903_TIMRPrmDisableEventTrigger(ch, clrbit);
	}
	
	return retval;
}

/**
 * @brief           DMAリクエスト生成設定（Enable）
 * @param           handle [in] TIMRハンドル
 * @param           target [in] 操作対象（ビット指定）
 * @return          DMAリクエスト生成設定（Enable）結果
 * @retval          AG903_ENONE   正常終了
 * @retval          -AG903_EINVAL 引数異常
 * @description     DMAリクエスト生成設定（Enable）をします<p>
 *                  targetで指定した条件でDMAリクエストが生成されます。<p>
 *                  <table>
 *                  <tr><th>bit</th><th>割込み</th></tr>
 *                  <tr><td>1</td><td>コンペア・マッチ割込み</td></tr>
 *                  <tr><td>0</td><td>オーバーフロー割込み</td></tr>
 *                  </table>
 *                  1を設定するとDMAリクエストが生成されます。
*/
int32_t	AG903_TIMRMgrEnableDmaRequest(AG903_TIMRMgrHandle* handle, uint8_t target)
{
	int32_t	 retval = AG903_ENONE;
	int32_t	 result;
	uint32_t setbit = 0;
	uint8_t	 ch;
	
	result = TIMRMgr_CheckHandle(handle, &ch);
	if(AG903_ENONE != result) {
		return -AG903_EINVAL;
	}
	
	if(AG903_TIMR_COMPARE_BIT & target) {
		setbit |= AG903_TIMR_DMAREQ_CM_BIT;
	}
	if(AG903_TIMR_OVERFLOW_BIT & target) {
		setbit |= AG903_TIMR_DMAREQ_OVF_BIT;
	}
	
	if(0 != setbit) {
		AG903_TIMRPrmEnableDmaRequest(ch, setbit);
	}
	
	return retval;
}

/**
 * @brief           DMAリクエスト生成無効設定（Disable）
 * @param           handle [in] TIMRハンドル
 * @param           target [in] 操作対象（ビット指定）
 * @return          DMAリクエスト生成無効設定（Disable）結果
 * @retval          AG903_ENONE   正常終了
 * @retval          -AG903_EINVAL 引数異常
 * @description     DMAリクエスト生成無効設定（Disable）をします。<p>
 *                  targetで指定した条件でDMAリクエスト生成が無効化されます。<p>
 *                  <table>
 *                  <tr><th>bit</th><th>割込み</th></tr>
 *                  <tr><td>1</td><td>コンペア・マッチ割込み</td></tr>
 *                  <tr><td>0</td><td>オーバーフロー割込み</td></tr>
 *                  </table>
 *                  1を設定するとDMAリクエスト生成が無効化されます。
*/
int32_t	AG903_TIMRMgrDisableDmaRequest(AG903_TIMRMgrHandle* handle, uint8_t target)
{
	int32_t	 retval = AG903_ENONE;
	int32_t	 result;
	uint32_t clrbit = 0;
	uint8_t	 ch;
	
	result = TIMRMgr_CheckHandle(handle, &ch);
	if(AG903_ENONE != result) {
		return -AG903_EINVAL;
	}
	
	if(AG903_TIMR_COMPARE_BIT & target) {
		clrbit |= AG903_TIMR_DMAREQ_CM_BIT;
	}
	if(AG903_TIMR_OVERFLOW_BIT & target) {
		clrbit |= AG903_TIMR_DMAREQ_OVF_BIT;
	}
	
	if(0 != clrbit) {
		AG903_TIMRPrmDisableDmaRequest(ch, clrbit);
	}
	
	return retval;
}

/**
 * @brief           ステータス取得
 * @param           handle [in] TIMRハンドル
 * @param           status [out] 状態
 * @return          ステータス取得結果
 * @retval          AG903_ENONE   正常終了
 * @retval          -AG903_EINVAL 引数異常
 * @description     ステータスを取得します。<p>
 *                  TIMnSTAT の内容を status にReadします。
*/
int32_t	AG903_TIMRMgrGetStatus(AG903_TIMRMgrHandle* handle, uint32_t* status)
{
	int32_t	 retval = AG903_ENONE;
	int32_t	 result;
	uint8_t	 ch;
	
	result = TIMRMgr_CheckHandle(handle, &ch);
	if(AG903_ENONE != result) {
		return -AG903_EINVAL;
	}
	if(NULL == status) {
		return -AG903_EINVAL;
	}
	
	AG903_TIMRPrmGetStatus(ch, status);
	
	return retval;
}

/**
 * @brief           ステータスクリア
 * @param           handle [in] TIMRハンドル
 * @param           target [in] 操作対象（ビット指定）
 * @return          ステータスクリア結果
 * @retval          AG903_ENONE   正常終了
 * @retval          -AG903_EINVAL 引数異常
 * @description     ステータスクリアをします。<p>
 *                  targetで指定した条件でステータスがクリアされます。<p>
 *                  <table>
 *                  <tr><th>bit</th><th>ステータス</th></tr>
 *                  <tr><td>1</td><td>コンペア・マッチ状態</td></tr>
 *                  <tr><td>0</td><td>オーバーフロー状態</td></tr>
 *                  </table>
 *                  1を設定するとステータスがクリアされます。
*/
int32_t	AG903_TIMRMgrClearStatus(AG903_TIMRMgrHandle* handle, uint32_t target)
{
	int32_t	 retval = AG903_ENONE;
	int32_t	 result;
	uint32_t clrbit = 0;
	uint8_t	 ch;
	
	result = TIMRMgr_CheckHandle(handle, &ch);
	if(AG903_ENONE != result) {
		return -AG903_EINVAL;
	}
	
	if(AG903_TIMR_COMPARE_BIT & target) {
		clrbit |= AG903_TIMR_STAT_CM_BIT;
	}
	if(AG903_TIMR_OVERFLOW_BIT & target) {
		clrbit |= AG903_TIMR_STAT_OVF_BIT;
	}
	
	if(0 != clrbit) {
		AG903_TIMRPrmClearStatus(ch, clrbit);
	}
	
	return retval;
}

/**
 * @brief           カウント値取得
 * @param           handle [in] TIMRハンドル
 * @param           count [out] カウント値
 * @return          カウント値取得結果
 * @retval          AG903_ENONE   正常終了
 * @retval          -AG903_EINVAL 引数異常
 * @description     カウント値を取得します。
*/
int32_t	AG903_TIMRMgrGetCount(AG903_TIMRMgrHandle* handle, uint32_t* count)
{
	int32_t	 retval = AG903_ENONE;
	int32_t	 result;
	uint8_t	 ch;
	
	result = TIMRMgr_CheckHandle(handle, &ch);
	if(AG903_ENONE != result) {
		return -AG903_EINVAL;
	}
	if(NULL == count) {
		return -AG903_EINVAL;
	}
	
	AG903_TIMRPrmGetCount(ch, count);
	
	return retval;
}

/**
 * @brief           カウント値設定
 * @param           handle [in] TIMRハンドル
 * @param           count [in] カウント値
 * @return          カウント値設定結果
 * @retval          AG903_ENONE   正常終了
 * @retval          -AG903_EINVAL 引数異常
 * @retval          -AG903_EBUSY  ハンドル使用中 (タイマ動作中).
 * @description     カウント値を設定します。<p>
 *                  動作停止中のみ設定可能です。
*/
int32_t	AG903_TIMRMgrSetCount(AG903_TIMRMgrHandle* handle, uint32_t count)
{
	int32_t	 retval = AG903_ENONE;
	int32_t	 result;
	uint8_t	 ch;
	uint8_t	 idle;
	
	result = TIMRMgr_CheckHandle(handle, &ch);
	if(AG903_ENONE != result) {
		return -AG903_EINVAL;
	}
	idle = TIMRMgr_CheckIdle(ch);
	if(true != idle) {
		return -AG903_EBUSY;
	}
	
	AG903_TIMRPrmSetCount(ch, count);
	
	return retval;
}

/**
 * @brief           周期値取得
 * @param           handle [in] TIMRハンドル
 * @param           period [out] 周期値
 * @return          周期値取得結果
 * @retval          AG903_ENONE   正常終了
 * @retval          -AG903_EINVAL 引数異常
 * @description     周期値を取得します。
*/
int32_t	AG903_TIMRMgrGetPeriodValue(AG903_TIMRMgrHandle* handle, uint32_t* period)
{
	int32_t	 retval = AG903_ENONE;
	int32_t	 result;
	uint8_t	 ch;
	
	result = TIMRMgr_CheckHandle(handle, &ch);
	if(AG903_ENONE != result) {
		return -AG903_EINVAL;
	}
	if(NULL == period) {
		return -AG903_EINVAL;
	}
	
	AG903_TIMRPrmGetPeriod(ch, period);
	
	return retval;
}

/**
 * @brief           周期値設定
 * @param           handle [in] TIMRハンドル
 * @param           period [in] 周期値
 * @return          周期値設定結果
 * @retval          AG903_ENONE   正常終了
 * @retval          -AG903_EINVAL 引数異常
 * @description     周期値を設定します。
*/
int32_t	AG903_TIMRMgrSetPeriodValue(AG903_TIMRMgrHandle* handle, uint32_t period)
{
	int32_t	 retval = AG903_ENONE;
	int32_t	 result;
	uint8_t	 ch;
	
	result = TIMRMgr_CheckHandle(handle, &ch);
	if(AG903_ENONE != result) {
		return -AG903_EINVAL;
	}
	
	AG903_TIMRPrmSetPeriod(ch, period);
	
	return retval;
}

/**
 * @brief           比較値取得
 * @param           handle [in] TIMRハンドル
 * @param           match [out] 比較値
 * @return          比較値取得結果
 * @retval          AG903_ENONE   正常終了
 * @retval          -AG903_EINVAL 引数異常
 * @description     比較値を取得します。
*/
int32_t	AG903_TIMRMgrGetMatchValue(AG903_TIMRMgrHandle* handle, uint32_t* match)
{
	int32_t	 retval = AG903_ENONE;
	int32_t	 result;
	uint8_t	 ch;
	
	result = TIMRMgr_CheckHandle(handle, &ch);
	if(AG903_ENONE != result) {
		return -AG903_EINVAL;
	}
	if(NULL == match) {
		return -AG903_EINVAL;
	}
	
	AG903_TIMRPrmGetMatch(ch, match);
	
	return retval;
}

/**
 * @brief           比較値設定
 * @param           handle [in] TIMRハンドル
 * @param           match [in] 比較値
 * @return          比較値設定結果
 * @retval          AG903_ENONE   正常終了
 * @retval          -AG903_EINVAL 引数異常
 * @description     比較値を設定します。
*/
int32_t	AG903_TIMRMgrSetMatchValue(AG903_TIMRMgrHandle* handle, uint32_t match)
{
	int32_t	 retval = AG903_ENONE;
	int32_t	 result;
	uint8_t	 ch;
	
	result = TIMRMgr_CheckHandle(handle, &ch);
	if(AG903_ENONE != result) {
		return -AG903_EINVAL;
	}
	
	AG903_TIMRPrmSetMatch(ch, match);
	
	return retval;
}

/**
 * @brief           チャネル番号取得
 * @param           handle [in] TIMRハンドル
 * @param           ch [out] チャネル番号
 * @return          チャネル番号取得結果
 * @retval          AG903_ENONE   正常終了
 * @retval          -AG903_EINVAL 引数異常
 * @description     チャネル番号を取得します。
*/
int32_t	AG903_TIMRMgrGetChannel(AG903_TIMRMgrHandle* handle, uint8_t* ch)
{
	int32_t	 retval = AG903_ENONE;
	int32_t	 result;
	
	if(NULL == ch) {
		return -AG903_EINVAL;
	}

	result = TIMRMgr_CheckHandle(handle, ch);
	if(AG903_ENONE != result) {
		return -AG903_EINVAL;
	}

	return retval;
}

/*
	状態初期化.
	ch：TIMRチャネル.
*/
static void TIMRMgr_Init(uint8_t ch)
{
	uint32_t loop;
	
	if(AG903_TIMR_CH_NUM <= ch) {
		return;
	}

	for(loop=0; loop<AG903_TIMR_INTHDR_NUM; loop++) {
		TimrChStat[ch].inthdr[loop].hdrid = 0;
		TimrChStat[ch].inthdr[loop].func  = NULL;
	}
	TimrChStat[ch].mode    = AG903_TIMR_CTRLMOD_STOP;
	TimrChStat[ch].outmode = AG903_TIMR_OUTMOD_DISABLE;
	AG903_TIMRPrmSetCntMode(ch, AG903_TIMR_CTRLMOD_STOP);

	TimrHandleStat[ch].lock = false;

	return;
}

/*
	ハンドルチェック.
	handle：TIMRハンドル.
	ch：TIMRチャネル.
*/
static int32_t TIMRMgr_CheckHandle(AG903_TIMRMgrHandle* handle, uint8_t* ch)
{
	int32_t	 retval = AG903_ENONE;
	uint32_t get_ch;
	
	get_ch = ((uint32_t)handle - (uint32_t)TimrHandleStat) / sizeof(AG903_TIMRMgrHandleStat);
	
	if( (AG903_TIMR_CH_NUM <= get_ch) ||
		(&TimrHandleStat[get_ch] != (AG903_TIMRMgrHandleStat*)handle) ) {
		return -AG903_EINVAL;
	}
	(*ch) = (uint8_t)get_ch;
	
	return retval;
}

/*
	IDLEチェック.
	ch：TIMRチャネル.
	return：true（IDLE）
*/
static _Bool TIMRMgr_CheckIdle(uint8_t ch)
{
	uint8_t	mode=0;
	_Bool	retval=false;
	
	AG903_TIMRPrmGetCntMode(ch, &mode);
	if(AG903_TIMR_CTRLMOD_STOP == mode) {
		retval=true;
	}
	
	return retval;
}
