/**
 * @brief       TIMR Primitive
 * @author      AXELL CORPORATION
 * @description TIMR Primitive Layer
 * @note        none
 * @history     2017_02_22  初版
 * @history     2017_10_26  Ver2.0
 * @history     2019_03_08  [SDK2.2] Timrの割り込みクリアの軽微な修正 (#2187)
*/
/* 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_common.h"
#include "timr/timrprm.h"
#include "register/AG903_timreg.h"


#define	AG903_TIMR_READ_REGn(CH,REG)			(AG903_TIMn(CH)->REG)
#define	AG903_TIMR_READ_FLDn(CH,REG,POS,MSK)	( ( (AG903_TIMn(CH)->REG) & MSK ) >> POS )
#define	AG903_TIMR_WRITE_REGn(CH,REG,VAL)		(AG903_TIMn(CH)->REG  = (uint32_t)(VAL))
#define	AG903_TIMR_CLR_REGn(CH,REG,VAL)			(AG903_TIMn(CH)->REG &= (uint32_t)(~VAL))
#define	AG903_TIMR_SET_REGn(CH,REG,VAL)			(AG903_TIMn(CH)->REG |= (uint32_t)(VAL))
#define	AG903_TIMR_WRITE_REG(REG,VAL)			(AG903_TIM->REG  = (uint32_t)(VAL))


/**
 * @brief           TIMnINMODのレジスタWrite
 * @param           ch [in] TIMRチャネル
 * @param           param [in] 設定パラメータ
 * @return          void
 * @description     TIMnINMODのレジスタWrite
*/
void AG903_TIMRPrmSetInMode(uint8_t ch, AG903_TIMRPrmInModeParam* param)
{
	uint32_t	val=0;
	
	ASSERT(AG903_TIMR_CH_NUM > ch);
	ASSERT(NULL != param);
	
	val |= (param->eve&0x3F);	/* 有効bit [5:0] */
	val <<= 6;
	val |= (param->lo&0x01);	/* 有効bit [0] */
	val <<= 2;
	val |= (param->ch&0x03);	/* 有効bit [1:0] */
	val <<= 8;
	val |= (param->pol&0x01);	/* 有効bit [0] */
	val <<= 8;
	val |= (param->res&0x03);	/* 有効bit [1:0] */
	
	AG903_TIMR_WRITE_REGn(ch,INMOD,val);
	
	return;
}

/**
 * @brief           TIMnOUTMODのレジスタWrite
 * @param           ch [in] TIMRチャネル
 * @param           param [in] 設定パラメータ
 * @return          void
 * @description     TIMnOUTMODのレジスタWrite
*/
void AG903_TIMRPrmSetOutMode(uint8_t ch, AG903_TIMRPrmOutModeParam* param)
{
	uint32_t	val=0;
	
	ASSERT(AG903_TIMR_CH_NUM > ch);
	ASSERT(NULL != param);
	
	val |= (param->cm&0x01);	/* 有効bit [0] */
	val <<= 1;
	val |= (param->ovf&0x01);	/* 有効bit [0] */
	val <<= 8;
	val |= (param->ch&0x03);	/* 有効bit [1:0] */
	val <<= 8;
	val |= (param->pol&0x01);	/* 有効bit [0] */
	val <<= 8;
	val |= (param->mod&0x03);	/* 有効bit [1:0] */
	
	AG903_TIMR_WRITE_REGn(ch,OUTMOD,val);
	
	return;
}

/**
 * @brief           TIMnRSTTRGのレジスタWrite
 * @param           ch [in] TIMRチャネル
 * @param           param [in] 設定パラメータ
 * @return          void
 * @description     TIMnRSTTRGのレジスタWrite
*/
void AG903_TIMRPrmSetResetTrigger(uint8_t ch, AG903_TIMRPrmResetTriggerParam* param)
{
	uint32_t	val=0;

	ASSERT(AG903_TIMR_CH_NUM > ch);
	ASSERT(NULL != param);
	
	val |= (param->eve&0x3F);	/* 有効bit [5:0] */
	val <<= 6;
	val |= (param->lo&0x01);	/* 有効bit [0] */
	val <<= 2;
	val |= (param->ch&0x03);	/* 有効bit [1:0] */
	val <<= 8;
	val |= (param->pol&0x01);	/* 有効bit [0] */
	val <<= 4;
	val |= (param->res&0x03);	/* 有効bit [1:0] */
	val <<= 2;
	val |= (param->boot&0x03);	/* 有効bit [1:0] */
	val <<= 2;
	val |= (param->en&0x03);	/* 有効bit [1:0] */
	
	AG903_TIMR_WRITE_REGn(ch,RSTTRG,val);
	
	return;
}

/**
 * @brief           TIMnCTRLレジスタのOSビットSet
 * @param           ch [in] TIMRチャネル
 * @return          void
 * @description     TIMnCTRLレジスタのOSビットSet
 * @note            レジスタをリードモディファイライトします。
*/
void AG903_TIMRPrmEnableOneshot(uint8_t ch)
{
	ASSERT(AG903_TIMR_CH_NUM > ch);
	AG903_TIMR_SET_REGn(ch,CTRL,(1<<AG903_TIMn_CTRL_OS_POS));
	return;
}

/**
 * @brief           TIMnCTRLレジスタのOSビットClear
 * @param           ch [in] TIMRチャネル
 * @return          void
 * @description     TIMnCTRLレジスタのOSビットClear
 * @note            レジスタをリードモディファイライトします。
*/
void AG903_TIMRPrmDisableOneshot(uint8_t ch)
{
	ASSERT(AG903_TIMR_CH_NUM > ch);
	AG903_TIMR_CLR_REGn(ch,CTRL,(1<<AG903_TIMn_CTRL_OS_POS));
	return;
}

/**
 * @brief           TIMnCTRLレジスタのMODフィールドWrite
 * @param           ch [in] TIMRチャネル
 * @param           mode [in] カウントモード
 * @return          void
 * @description     TIMnCTRLレジスタのMODフィールドWrite
 * @note            レジスタをリードモディファイライトします。
*/
void AG903_TIMRPrmSetCntMode(uint8_t ch, uint8_t mode)
{
	ASSERT(AG903_TIMR_CH_NUM > ch);
	AG903_TIMR_CLR_REGn(ch,CTRL,AG903_TIMn_CTRL_MOD_MSK);
	AG903_TIMR_SET_REGn(ch,CTRL,(mode<<AG903_TIMn_CTRL_MOD_POS));
	return;
}

/**
 * @brief           TIMnCTRLレジスタのMODフィールドRead
 * @param           ch [in] TIMRチャネル
 * @param           mode [out] カウントモード
 * @return          void
 * @description     TIMnCTRLレジスタのMODフィールドRead
*/
void AG903_TIMRPrmGetCntMode(uint8_t ch, uint8_t* mode)
{
	ASSERT(AG903_TIMR_CH_NUM > ch);
	ASSERT(NULL != mode);
	(*mode) = AG903_TIMR_READ_FLDn(ch,CTRL,AG903_TIMn_CTRL_MOD_POS,AG903_TIMn_CTRL_MOD_MSK);
	return;
}

/**
 * @brief           TIMnCNTのレジスタWrite
 * @param           ch [in] TIMRチャネル
 * @param           count [in] カウント値
 * @return          void
 * @description     TIMnCNTのレジスタWrite
 * @note            動作中に書き込んだ場合の動作は不定です。
*/
void AG903_TIMRPrmSetCount(uint8_t ch, uint32_t count)
{
	ASSERT(AG903_TIMR_CH_NUM > ch);
	AG903_TIMR_WRITE_REGn(ch,CNT,count);
	return;
}

/**
 * @brief           TIMnCNTのレジスタRead
 * @param           ch [in] TIMRチャネル
 * @param           count [out] カウント値
 * @return          void
 * @description     TIMnCNTのレジスタRead
*/
void AG903_TIMRPrmGetCount(uint8_t ch, uint32_t* count)
{
	ASSERT(AG903_TIMR_CH_NUM > ch);
	ASSERT(NULL != count);
	(*count) = AG903_TIMR_READ_REGn(ch,CNT);
	return;
}

/**
 * @brief           TIMnPERIODのレジスタWrite
 * @param           ch [in] TIMRチャネル
 * @param           period [in] 周期値
 * @return          void
 * @description     TIMnPERIODのレジスタWrite
*/
void AG903_TIMRPrmSetPeriod(uint8_t ch, uint32_t period)
{
	ASSERT(AG903_TIMR_CH_NUM > ch);
	AG903_TIMR_WRITE_REGn(ch,PERIOD,period);
	return;
}

/**
 * @brief           TIMnPERIODのレジスタRead
 * @param           ch [in] TIMRチャネル
 * @param           period [out] 周期値
 * @return          void
 * @description     TIMnPERIODのレジスタRead
*/
void AG903_TIMRPrmGetPeriod(uint8_t ch, uint32_t* period)
{
	ASSERT(AG903_TIMR_CH_NUM > ch);
	ASSERT(NULL != period);
	(*period) = AG903_TIMR_READ_REGn(ch,PERIOD);
	return;
}

/**
 * @brief           TIMnMATCHのレジスタWrite
 * @param           ch [in] TIMRチャネル
 * @param           match [in] 比較値
 * @return          void
 * @description     TIMnMATCHのレジスタWrite
*/
void AG903_TIMRPrmSetMatch(uint8_t ch, uint32_t match)
{
	ASSERT(AG903_TIMR_CH_NUM > ch);
	AG903_TIMR_WRITE_REGn(ch,MATCH,match);
	return;
}

/**
 * @brief           TIMnMATCHのレジスタRaed
 * @param           ch [in] TIMRチャネル
 * @param           match [out] 周期値
 * @return          void
 * @description     TIMnMATCHのレジスタRaed
*/
void AG903_TIMRPrmGetMatch(uint8_t ch, uint32_t* match)
{
	ASSERT(AG903_TIMR_CH_NUM > ch);
	ASSERT(NULL != match);
	(*match) = AG903_TIMR_READ_REGn(ch,MATCH);
	return;
}

/**
 * @brief           TIMnPULWIDのレジスタWrite
 * @param           ch [in] TIMRチャネル
 * @param           width [in] パルス幅
 * @return          void
 * @description     TIMnPULWIDのレジスタWrite
*/
void AG903_TIMRPrmSetPluseWidth(uint8_t ch, uint32_t width)
{
	ASSERT(AG903_TIMR_CH_NUM > ch);
	AG903_TIMR_WRITE_REGn(ch,PULWID,(width&AG903_TIMn_PULWID_VAL_MSK));
	return;
}

/**
 * @brief           TIMnPULWIDのレジスタRead
 * @param           ch [in] TIMRチャネル
 * @param           width [out] パルス幅
 * @return          void
 * @description     TIMnPULWIDのレジスタRead
*/
void AG903_TIMRPrmGetPluseWidth(uint8_t ch, uint32_t* width)
{
	ASSERT(AG903_TIMR_CH_NUM > ch);
	ASSERT(NULL != width);
	(*width) = AG903_TIMR_READ_FLDn(ch,PULWID,AG903_TIMn_PULWID_VAL_POS,AG903_TIMn_PULWID_VAL_MSK);
	return;
}

/**
 * @brief           TIMnINTMASKのレジスタWrite(指定ビットをSet)
 * @param           ch [in] TIMRチャネル
 * @param           target [in] 操作対象 (ビット指定)
 * @return          void
 * @description     TIMnINTMASKのレジスタWrite(指定ビットをSet)<p>
 *                  (指定可能ビット: 1\<\<AG903_TIMn_INTMASK_OVF_POS, 1\<\<AG903_TIMn_INTMASK_CM_POS)
 * @note            レジスタをリードモディファイライトします。
*/
void AG903_TIMRPrmEnableMask(uint8_t ch, uint32_t setbit)
{
	ASSERT(AG903_TIMR_CH_NUM > ch);
	AG903_TIMR_SET_REGn(ch,INTMASK,setbit);
	return;
}

/**
 * @brief           TIMnINTMASKのレジスタWrite(指定ビットをClear)
 * @param           ch [in] TIMRチャネル
 * @param           target [in] 操作対象 (ビット指定)
 * @return          void
 * @description     TIMnINTMASKのレジスタWrite(指定ビットをClear)<p>
 *                  (指定可能ビット: 1\<\<AG903_TIMn_INTMASK_OVF_POS, 1\<\<AG903_TIMn_INTMASK_CM_POS)
 * @note            レジスタをリードモディファイライトします。
*/
void AG903_TIMRPrmDisableMask(uint8_t ch, uint32_t clrbit)
{
	ASSERT(AG903_TIMR_CH_NUM > ch);
	AG903_TIMR_CLR_REGn(ch,INTMASK,clrbit);
	return;
}

/**
 * @brief           TIMnTRIGGERのレジスタWrite(指定ビットをSet)
 * @param           ch [in] TIMRチャネル
 * @param           target [in] 操作対象 (ビット指定)
 * @return          void
 * @description     TIMnTRIGGERのレジスタWrite(指定ビットをSet)<p>
 *                  (指定可能ビット: 1\<\<AG903_TIMn_TRIGGER_OVF_POS, 1\<\<AG903_TIMn_TRIGGER_CM_POS)
 * @note            レジスタをリードモディファイライトします。
*/
void AG903_TIMRPrmEnableEventTrigger(uint8_t ch, uint32_t setbit)
{
	ASSERT(AG903_TIMR_CH_NUM > ch);
	AG903_TIMR_SET_REGn(ch,TRIGGER,setbit);
	return;
}

/**
 * @brief           TIMnTRIGGERのレジスタWrite(指定ビットをClear)
 * @param           ch [in] TIMRチャネル
 * @param           target [in] 操作対象 (ビット指定)
 * @return          void
 * @description     TIMnTRIGGERのレジスタWrite(指定ビットをClear)<p>
 *                  (指定可能ビット: 1\<\<AG903_TIMn_TRIGGER_OVF_POS, 1\<\<AG903_TIMn_TRIGGER_CM_POS)
 * @note            レジスタをリードモディファイライトします。
*/
void AG903_TIMRPrmDisableEventTrigger(uint8_t ch, uint32_t clrbit)
{
	ASSERT(AG903_TIMR_CH_NUM > ch);
	AG903_TIMR_CLR_REGn(ch,TRIGGER,clrbit);
	return;
}

/**
 * @brief           TIMnDMAREQのレジスタWrite(指定ビットをSet)
 * @param           ch [in] TIMRチャネル
 * @param           target [in] 操作対象 (ビット指定)
 * @return          void
 * @description     TIMnDMAREQのレジスタWrite(指定ビットをSet)<p>
 *                  (指定可能ビット: 1\<\<AG903_TIMn_DMAREQ_OVF_POS, 1\<\<AG903_TIMn_DMAREQ_CM_POS)
 * @note            レジスタをリードモディファイライトします。
*/
void AG903_TIMRPrmEnableDmaRequest(uint8_t ch, uint32_t setbit)
{
	ASSERT(AG903_TIMR_CH_NUM > ch);
	AG903_TIMR_SET_REGn(ch,DMAREQ,setbit);
	return;
}

/**
 * @brief           TIMnDMAREQのレジスタWrite(指定ビットをClear)
 * @param           ch [in] TIMRチャネル
 * @param           target [in] 操作対象 (ビット指定)
 * @return          void
 * @description     TIMnDMAREQのレジスタWrite(指定ビットをClear)<p>
 *                  (指定可能ビット: 1\<\<AG903_TIMn_DMAREQ_OVF_POS, 1\<\<AG903_TIMn_DMAREQ_CM_POS)
 * @note            レジスタをリードモディファイライトします。
*/
void AG903_TIMRPrmDisableDmaRequest(uint8_t ch, uint32_t clrbit)
{
	ASSERT(AG903_TIMR_CH_NUM > ch);
	AG903_TIMR_CLR_REGn(ch,DMAREQ,clrbit);
	return;
}

/**
 * @brief           TIMnSTATのレジスタRead
 * @param           ch [in] TIMRチャネル
 * @param           status [out] ステータス
 * @return          void
 * @description     TIMnSTATのレジスタRead
*/
void AG903_TIMRPrmGetStatus(uint8_t ch, uint32_t* status)
{
	ASSERT(AG903_TIMR_CH_NUM > ch);
	ASSERT(NULL != status);
	(*status) = AG903_TIMR_READ_REGn(ch,STAT);
	return;
}

/**
 * @brief           TIMnCLRのレジスタWrite(指定ビットをSet)
 * @param           ch [in] TIMRチャネル
 * @param           target [in] 操作対象 (ビット指定)
 * @return          void
 * @description     TIMnCLRのレジスタWrite(指定ビットをSet)<p>
 *                  (指定可能ビット: 1\<\<AG903_TIMn_STAT_OVF_POS, 1\<\<AG903_TIMn_STAT_CM_POS,
 *                  1\<\<AG903_TIMn_STAT_DR_POS)
 * @note            レジスタをリードモディファイライトします。
*/
void AG903_TIMRPrmClearStatus(uint8_t ch, uint32_t setbit)
{
	ASSERT(AG903_TIMR_CH_NUM > ch);
	AG903_TIMR_WRITE_REGn(ch,CLR,setbit);
	return;
}

/**
 * @brief           TIMBOOTTRGのレジスタWrite
 * @param           chbit [in] TIMRチャネル (ビット指定)
 * @return          void
 * @description     TIMBOOTTRGのレジスタWrite<p>
 *                  (指定可能ビット: <p>
 *                  1\<\<AG903_TIM_BOOTTRG_CH0_POS,<p>
 *                  ...
 *                  1\<\<AG903_TIM_BOOTTRG_CH7_POS)<p>
 */
void AG903_TIMRPrmSetBootTrigger(uint8_t chbit)
{
	AG903_TIMR_WRITE_REG(BOOTTRG,chbit);
	return;
}
