/**
 * @brief       DSP Primitive
 * @author      AXELL CORPORATION
 * @description DSP Primitive
 * @note        none
 * @history     2017_09_04  初版
 * @history     2017_10_26  Ver2.0
 */
/* DOM-IGNORE-BEGIN */
/*
 * This program was created by AXELL CORPORATION.
 * Copyright (C) 2017-2019 AXELL CORPORATION, all rights reserved.
 */
/* DOM-IGNORE-END */

#include "AG903_common.h"

#include "dsp/dspprm.h"
#include "dsp/dspmgr.h"

/**
 * @brief           CTRLレジスタからの読み込み. 
 * @param           ch [in] DSPチャンネル (0-1)
 * @param           *don [out] 表示回路動作設定（0:OFF 1:ON）
 * @return          void
 * @description     AG903_DSP->CTRL からリードします. 
 */
void AG903_DSPPrmGetCTRL(uint8_t ch, uint32_t *don)
{
	ASSERT(ch < AG903_DSP_CH_NUM);

	uint32_t reg = AG903_DSPn(ch)->CTRL;
	*don = (reg & AG903_DSPn_CTRL_DON_MSK) >> AG903_DSPn_CTRL_DON_POS;
}

/**
 * @brief           CTRLレジスタへの書き込み. 
 * @param           ch [in] DSPチャンネル (0-1)
 * @param           don [in] 表示回路動作設定（0:OFF 1:ON）
 * @return          void
 * @description     AG903_DSP->CTRL にライトします. 
 */
void AG903_DSPPrmSetCTRL(uint8_t ch, uint32_t don)
{
	ASSERT(ch < AG903_DSP_CH_NUM);

	AG903_DSPn(ch)->CTRL = (don << AG903_DSPn_CTRL_DON_POS) & AG903_DSPn_CTRL_DON_MSK;
}

/**
 * @brief           MODレジスタからの読み込み.
 * @param           ch [in] DSPチャンネル (0-1)
 * @param           *mod [out] 設定値
 * @return          void
 * @description     AG903_DSP->MOD からリードします.
 * @seealso         設定値については DSPPrmParamMOD を参照.
 */
void AG903_DSPPrmGetMOD(uint8_t ch, DSPPrmParamMOD *mod)
{
	ASSERT(ch < AG903_DSP_CH_NUM);

	uint32_t reg = AG903_DSPn(ch)->MOD;
	mod->de   = (reg & AG903_DSPn_MOD_DE_MSK  ) >> AG903_DSPn_MOD_DE_POS;
	mod->ip   = (reg & AG903_DSPn_MOD_IP_MSK  ) >> AG903_DSPn_MOD_IP_POS;
	mod->upd  = (reg & AG903_DSPn_MOD_UPD_MSK ) >> AG903_DSPn_MOD_UPD_POS;
	mod->bmr  = (reg & AG903_DSPn_MOD_BMR_MSK ) >> AG903_DSPn_MOD_BMR_POS;
	mod->lut  = (reg & AG903_DSPn_MOD_LUT_MSK ) >> AG903_DSPn_MOD_LUT_POS;
	mod->dith = (reg & AG903_DSPn_MOD_DITH_MSK) >> AG903_DSPn_MOD_DITH_POS;
}

/**
 * @brief           MODレジスタへの書き込み.
 * @param           ch [in] DSPチャンネル (0-1)
 * @param           *mod [in] 設定値
 * @return          void
 * @description     AG903_DSP->MOD にライトします.
 * @seealso         設定値については DSPPrmParamMOD を参照.
 */
void AG903_DSPPrmSetMOD(uint8_t ch, DSPPrmParamMOD *mod)
{
	ASSERT(ch < AG903_DSP_CH_NUM);

	uint32_t reg = 0;
	reg |= (mod->de   << AG903_DSPn_MOD_DE_POS  ) & AG903_DSPn_MOD_DE_MSK;
	reg |= (mod->ip   << AG903_DSPn_MOD_IP_POS  ) & AG903_DSPn_MOD_IP_MSK;
	reg |= (mod->upd  << AG903_DSPn_MOD_UPD_POS ) & AG903_DSPn_MOD_UPD_MSK;
	reg |= (mod->bmr  << AG903_DSPn_MOD_BMR_POS ) & AG903_DSPn_MOD_BMR_MSK;
	reg |= (mod->lut  << AG903_DSPn_MOD_LUT_POS ) & AG903_DSPn_MOD_LUT_MSK;
	reg |= (mod->dith << AG903_DSPn_MOD_DITH_POS) & AG903_DSPn_MOD_DITH_MSK;

	AG903_DSPn(ch)->MOD = reg;
}

/**
 * @brief           SYNCレジスタからの読み込み.
 * @param           ch [in] DSPチャンネル (0-1)
 * @param           *sync [out] 設定値
 * @return          void
 * @description     AG903_DSP->SYNC からリードします.
 * @seealso         設定値については DSPPrmParamSYNC を参照.
 */
void AG903_DSPPrmGetSYNC(uint8_t ch, DSPPrmParamSYNC *sync)
{
	ASSERT(ch < AG903_DSP_CH_NUM);

	uint32_t reg = AG903_DSPn(ch)->SYNC;
	sync->sel = (reg & AG903_DSPn_SYNC_SEL_MSK) >> AG903_DSPn_SYNC_SEL_POS;
	sync->dly = (reg & AG903_DSPn_SYNC_DLY_MSK) >> AG903_DSPn_SYNC_DLY_POS;
	sync->ip  = (reg & AG903_DSPn_SYNC_IP_MSK ) >> AG903_DSPn_SYNC_IP_POS;
	sync->vp  = (reg & AG903_DSPn_SYNC_VP_MSK ) >> AG903_DSPn_SYNC_VP_POS;
	sync->fp  = (reg & AG903_DSPn_SYNC_FP_MSK ) >> AG903_DSPn_SYNC_FP_POS;
	sync->msk = (reg & AG903_DSPn_SYNC_MSK_MSK) >> AG903_DSPn_SYNC_MSK_POS;
}

/**
 * @brief           SYNCレジスタへの書き込み.
 * @param           ch [in] DSPチャンネル (0-1)
 * @param           *sync [in] 設定値
 * @return          void
 * @description     AG903_DSP->SYNC にライトします.
 * @seealso         設定値については DSPPrmParamSYNC を参照.
 */
void AG903_DSPPrmSetSYNC(uint8_t ch, DSPPrmParamSYNC *sync)
{
	ASSERT(ch < AG903_DSP_CH_NUM);

	uint32_t reg = 0;
	reg |= (sync->sel << AG903_DSPn_SYNC_SEL_POS) & AG903_DSPn_SYNC_SEL_MSK;
	reg |= (sync->dly << AG903_DSPn_SYNC_DLY_POS) & AG903_DSPn_SYNC_DLY_MSK;
	reg |= (sync->ip  << AG903_DSPn_SYNC_IP_POS ) & AG903_DSPn_SYNC_IP_MSK;
	reg |= (sync->vp  << AG903_DSPn_SYNC_VP_POS ) & AG903_DSPn_SYNC_VP_MSK;
	reg |= (sync->fp  << AG903_DSPn_SYNC_FP_POS ) & AG903_DSPn_SYNC_FP_MSK;
	reg |= (sync->msk << AG903_DSPn_SYNC_MSK_POS) & AG903_DSPn_SYNC_MSK_MSK;

	AG903_DSPn(ch)->SYNC = reg;
}

/**
 * @brief           BGCOLレジスタからの読み込み.
 * @param           ch [in] DSPチャンネル (0-1)
 * @param           *bgcol [out] 背景色
 * @return          void
 * @description     AG903_DSP->BGCOL からリードします.
 */
void AG903_DSPPrmGetBGCOL(uint8_t ch, uint32_t *bgcol)
{
	ASSERT(ch < AG903_DSP_CH_NUM);

	*bgcol = AG903_DSPn(ch)->BGCOL;
}

/**
 * @brief           BGCOLレジスタへの書き込み.
 * @param           ch [in] DSPチャンネル (0-1)
 * @param           bgcol [in] 背景色
 * @return          void
 * @description     AG903_DSP->BGCOL にライトします.
 */
void AG903_DSPPrmSetBGCOL(uint8_t ch, uint32_t bgcol)
{
	ASSERT(ch < AG903_DSP_CH_NUM);

	AG903_DSPn(ch)->BGCOL = bgcol;
}

/**
 * @brief           WINNUMレジスタからの読み込み.
 * @param           ch [in] DSPチャンネル (0-1)
 * @param           *act [out] 使用中ウィンドウ数
 * @param           *conf [out] ウィンドウ数
 * @return          void
 * @description     AG903_DSP->WINNUM からリードします.
 */
void AG903_DSPPrmGetWINNUM(uint8_t ch, uint32_t *act, uint32_t *conf)
{
	ASSERT(ch < AG903_DSP_CH_NUM);
	ASSERT(act != NULL);
	ASSERT(conf != NULL);

	uint32_t reg = AG903_DSPn(ch)->WINNUM;
	*act  = (reg & AG903_DSPn_WINNUM_ACT_MSK ) >> AG903_DSPn_WINNUM_ACT_POS;
	*conf = (reg & AG903_DSPn_WINNUM_CONF_MSK) >> AG903_DSPn_WINNUM_CONF_POS;
}

/**
 * @brief           WINNUMレジスタへの書き込み.
 * @param           ch [in] DSPチャンネル (0-1)
 * @param           conf [in] ウィンドウ数
 * @return          void
 * @description     AG903_DSP->WINNUM にライトします.
 */
void AG903_DSPPrmSetWINNUM(uint8_t ch, uint32_t conf)
{
	ASSERT(ch < AG903_DSP_CH_NUM);

	AG903_DSPn(ch)->WINNUM = (conf << AG903_DSPn_WINNUM_CONF_POS) & AG903_DSPn_WINNUM_CONF_MSK;
}

/**
 * @brief           WATNUMレジスタからの読み込み.
 * @param           ch [in] DSPチャンネル (0-1)
 * @param           *num [out] ウィンドウアトリビュート個数
 * @return          void
 * @description     AG903_DSP->WATNUM からリードします.
 */
void AG903_DSPPrmGetWATNUM(uint8_t ch, uint32_t *num)
{
	ASSERT(ch < AG903_DSP_CH_NUM);
	ASSERT(num != NULL);

	*num = (AG903_DSPn(ch)->WATNUM & AG903_DSPn_WATNUM_NUM_MSK) >> AG903_DSPn_WATNUM_NUM_POS;
}

/**
 * @brief           WATNUMレジスタへの書き込み.
 * @param           ch [in] DSPチャンネル (0-1)
 * @param           num [in] ウィンドウアトリビュート個数
 * @return          void
 * @description     AG903_DSP->WATNUM にライトします.
 */
void AG903_DSPPrmSetWATNUM(uint8_t ch, uint32_t num)
{
	ASSERT(ch < AG903_DSP_CH_NUM);

	AG903_DSPn(ch)->WATNUM = (num << AG903_DSPn_WATNUM_NUM_POS) & AG903_DSPn_WATNUM_NUM_MSK;
}

/**
 * @brief           WATBASEレジスタからの読み込み.
 * @param           ch [in] DSPチャンネル (0-1)
 * @param           *addr [out] ウィンドウアトリビュートベースアドレス
 * @return          void
 * @description     AG903_DSP->WATBASE からリードします.
 */
void AG903_DSPPrmGetWATBASE(uint8_t ch, uint32_t *addr)
{
	ASSERT(ch < AG903_DSP_CH_NUM);
	ASSERT(addr != NULL);

	*addr = AG903_DSPn(ch)->WATBASE;
}

/**
 * @brief           WATBASEレジスタへの書き込み.
 * @param           ch [in] DSPチャンネル (0-1)
 * @param           addr [in] ウィンドウアトリビュートベースアドレス
 * @return          void
 * @description     AG903_DSP->WATBASE にライトします.
 */
void AG903_DSPPrmSetWATBASE(uint8_t ch, uint32_t addr)
{
	ASSERT(ch < AG903_DSP_CH_NUM);

	AG903_DSPn(ch)->WATBASE = addr & AG903_DSPn_WATBASE_ADDR_MSK;
}

/**
 * @brief           LSTCTRLレジスタからの読み込み.
 * @param           ch [in] DSPチャンネル (0-1)
 * @param           *pal [out] パレット読み出し設定
 * @param           *wat [out] ウィンドウアトリビュート読み出し設定
 * @return          void
 * @description     AG903_DSP->LSTCTRL からリードします.
 */
void AG903_DSPPrmGetLSTCTRL(uint8_t ch, uint32_t *pal, uint32_t *wat)
{
	ASSERT(ch < AG903_DSP_CH_NUM);
	ASSERT(pal != NULL);
	ASSERT(wat != NULL);

	uint32_t reg = AG903_DSPn(ch)->LSTCTRL;
	*pal = (reg & AG903_DSPn_LSTCTRL_PAL_MSK) >> AG903_DSPn_LSTCTRL_PAL_POS;
	*wat = (reg & AG903_DSPn_LSTCTRL_WAT_MSK) >> AG903_DSPn_LSTCTRL_WAT_POS;
}

/**
 * @brief           LSTCTRLレジスタへの書き込み.
 * @param           ch [in] DSPチャンネル (0-1)
 * @param           pal [in] パレット読み出し設定
 * @param           wat [in] ウィンドウアトリビュート読み出し設定
 * @return          void
 * @description     AG903_DSP->LSTCTRL にライトします.
 * @seealso         反映されるタイミングについては DSPPrmParamMOD.UPD を参照.
 */
void AG903_DSPPrmSetLSTCTRL(uint8_t ch, uint32_t pal, uint32_t wat)
{
	ASSERT(ch < AG903_DSP_CH_NUM);

	uint32_t reg = 0;
	reg |= (pal << AG903_DSPn_LSTCTRL_PAL_POS) & AG903_DSPn_LSTCTRL_PAL_MSK;
	reg |= (wat << AG903_DSPn_LSTCTRL_WAT_POS) & AG903_DSPn_LSTCTRL_WAT_MSK;
	AG903_DSPn(ch)->LSTCTRL = reg;
}

/**
 * @brief           HRZPRM0レジスタからの読み込み.
 * @param           ch [in] DSPチャンネル (0-1)
 * @param           *hpw [out] 水平同期信号パルス幅
 * @return          void
 * @description     AG903_DSP->HRZPRM0 からリードします.
 */
void AG903_DSPPrmGetHRZPRM0(uint8_t ch, uint32_t *hpw)
{
	ASSERT(ch < AG903_DSP_CH_NUM);
	ASSERT(hpw != NULL);

	*hpw = (AG903_DSPn(ch)->HRZPRM0 & AG903_DSPn_HRZPRM0_HPW_MSK) >> AG903_DSPn_HRZPRM0_HPW_POS;
}

/**
 * @brief           HRZPRM0レジスタへの書き込み.
 * @param           ch [in] DSPチャンネル (0-1)
 * @param           hpw [in] 水平同期信号パルス幅
 * @return          void
 * @description     AG903_DSP->HRZPRM0 にライトします.
 */
void AG903_DSPPrmSetHRZPRM0(uint8_t ch, uint32_t hpw)
{
	ASSERT(ch < AG903_DSP_CH_NUM);

	AG903_DSPn(ch)->HRZPRM0 = (hpw << AG903_DSPn_HRZPRM0_HPW_POS) & AG903_DSPn_HRZPRM0_HPW_MSK;
}

/**
 * @brief           HRZPRM1レジスタからの読み込み.
 * @param           ch [in] DSPチャンネル (0-1)
 * @param           *hfp [out] 水平フロントポーチ
 * @param           *hbp [out] 水平バックポーチ
 * @return          void
 * @description     AG903_DSP->HRZPRM1 からリードします.
 */
void AG903_DSPPrmGetHRZPRM1(uint8_t ch, uint32_t *hfp, uint32_t *hbp)
{
	ASSERT(ch < AG903_DSP_CH_NUM);
	ASSERT(hfp != NULL);
	ASSERT(hbp != NULL);

	uint32_t reg = AG903_DSPn(ch)->HRZPRM1;
	*hfp = (reg & AG903_DSPn_HRZPRM1_HFP_MSK) >> AG903_DSPn_HRZPRM1_HFP_POS;
	*hbp = (reg & AG903_DSPn_HRZPRM1_HBP_MSK) >> AG903_DSPn_HRZPRM1_HBP_POS;
}

/**
 * @brief           HRZPRM1レジスタへの書き込み.
 * @param           ch [in] DSPチャンネル (0-1)
 * @param           hfp [in] 水平フロントポーチ
 * @param           hbp [in] 水平バックポーチ
 * @return          void
 * @description     AG903_DSP->HRZPRM1 にライトします.
 */
void AG903_DSPPrmSetHRZPRM1(uint8_t ch, uint32_t hfp, uint32_t hbp)
{
	ASSERT(ch < AG903_DSP_CH_NUM);

	uint32_t reg = 0;
	reg |= (hfp << AG903_DSPn_HRZPRM1_HFP_POS) & AG903_DSPn_HRZPRM1_HFP_MSK;
	reg |= (hbp << AG903_DSPn_HRZPRM1_HBP_POS) & AG903_DSPn_HRZPRM1_HBP_MSK;
	AG903_DSPn(ch)->HRZPRM1 = reg;
}

/**
 * @brief           VTPRM0レジスタからの読み込み.
 * @param           ch [in] DSPチャンネル (0-1)
 * @param           *vtprm0 [out] 設定値
 * @return          void
 * @description     AG903_DSP->VTPRM0 からリードします.
 * @seealso         設定値については DSPPrmParamVTPRM0 を参照.
 */
void AG903_DSPPrmGetVTPRM0(uint8_t ch, DSPPrmParamVTPRM0 *vtprm0)
{
	ASSERT(ch < AG903_DSP_CH_NUM);
	ASSERT(vtprm0 != NULL);

	uint32_t reg = AG903_DSPn(ch)->VTPRM0;
	vtprm0->vpw = (reg & AG903_DSPn_VTPRM0_VPW_MSK) >> AG903_DSPn_VTPRM0_VPW_POS;
	vtprm0->ofp = (reg & AG903_DSPn_VTPRM0_OFP_MSK) >> AG903_DSPn_VTPRM0_OFP_POS;
	vtprm0->obp = (reg & AG903_DSPn_VTPRM0_OBP_MSK) >> AG903_DSPn_VTPRM0_OBP_POS;
	vtprm0->efp = (reg & AG903_DSPn_VTPRM0_EFP_MSK) >> AG903_DSPn_VTPRM0_EFP_POS;
	vtprm0->ebp = (reg & AG903_DSPn_VTPRM0_EBP_MSK) >> AG903_DSPn_VTPRM0_EBP_POS;
}

/**
 * @brief           VTPRM0レジスタへの書き込み.
 * @param           ch [in] DSPチャンネル (0-1)
 * @param           *vtprm0 [in] 設定値
 * @return          void
 * @description     AG903_DSP->VTPRM0 にライトします.
 * @seealso         設定値については DSPPrmParamVTPRM0 を参照.
 */
void AG903_DSPPrmSetVTPRM0(uint8_t ch, DSPPrmParamVTPRM0 *vtprm0)
{
	ASSERT(ch < AG903_DSP_CH_NUM);

	uint32_t reg = 0;
	reg |= (vtprm0->vpw << AG903_DSPn_VTPRM0_VPW_POS) & AG903_DSPn_VTPRM0_VPW_MSK;
	reg |= (vtprm0->ofp << AG903_DSPn_VTPRM0_OFP_POS) & AG903_DSPn_VTPRM0_OFP_MSK;
	reg |= (vtprm0->obp << AG903_DSPn_VTPRM0_OBP_POS) & AG903_DSPn_VTPRM0_OBP_MSK;
	reg |= (vtprm0->efp << AG903_DSPn_VTPRM0_EFP_POS) & AG903_DSPn_VTPRM0_EFP_MSK;
	reg |= (vtprm0->ebp << AG903_DSPn_VTPRM0_EBP_POS) & AG903_DSPn_VTPRM0_EBP_MSK;

	AG903_DSPn(ch)->VTPRM0 = reg;
}

/**
 * @brief           VTPRM1レジスタからの読み込み.
 * @param           ch [in] DSPチャンネル (0-1)
 * @param           *vfp [out] 垂直フロントポーチ
 * @param           *vbp [out] 垂直バックポーチ
 * @return          void
 * @description     AG903_DSP->VTPRM1 からリードします.
 */
void AG903_DSPPrmGetVTPRM1(uint8_t ch, uint32_t *vfp, uint32_t *vbp)
{
	ASSERT(ch < AG903_DSP_CH_NUM);
	ASSERT(vfp != NULL);
	ASSERT(vbp != NULL);

	uint32_t reg = AG903_DSPn(ch)->VTPRM1;
	*vfp = (reg & AG903_DSPn_VTPRM1_VFP_MSK) >> AG903_DSPn_VTPRM1_VFP_POS;
	*vbp = (reg & AG903_DSPn_VTPRM1_VBP_MSK) >> AG903_DSPn_VTPRM1_VBP_POS;
}

/**
 * @brief           VTPRM1レジスタへの書き込み.
 * @param           ch [in] DSPチャンネル (0-1)
 * @param           vfp [in] 垂直フロントポーチ
 * @param           vbp [in] 垂直バックポーチ
 * @return          void
 * @description     AG903_DSP->VTPRM1 にライトします.
 */
void AG903_DSPPrmSetVTPRM1(uint8_t ch, uint32_t vfp, uint32_t vbp)
{
	ASSERT(ch < AG903_DSP_CH_NUM);

	uint32_t reg = 0;
	reg |= (vfp << AG903_DSPn_VTPRM1_VFP_POS) & AG903_DSPn_VTPRM1_VFP_MSK;
	reg |= (vbp << AG903_DSPn_VTPRM1_VBP_POS) & AG903_DSPn_VTPRM1_VBP_MSK;
	AG903_DSPn(ch)->VTPRM1 = reg;
}

/**
 * @brief           FRMSIZEレジスタからの読み込み.
 * @param           ch [in] DSPチャンネル (0-1)
 * @param           *vfs [out] 垂直表示幅
 * @param           *hfs [out] 水平表示幅
 * @return          void
 * @description     AG903_DSP->FRMSIZE からリードします.
 */
void AG903_DSPPrmGetFRMSIZE(uint8_t ch, uint32_t *vfs, uint32_t *hfs)
{
	ASSERT(ch < AG903_DSP_CH_NUM);
	ASSERT(vfs != NULL);
	ASSERT(hfs != NULL);

	uint32_t reg = AG903_DSPn(ch)->FRMSIZE;
	*vfs = (reg & AG903_DSPn_FRMSIZE_VFS_MSK) >> AG903_DSPn_FRMSIZE_VFS_POS;
	*hfs = (reg & AG903_DSPn_FRMSIZE_HFS_MSK) >> AG903_DSPn_FRMSIZE_HFS_POS;
}

/**
 * @brief           FRMSIZEレジスタへの書き込み.
 * @param           ch [in] DSPチャンネル (0-1)
 * @param           vfs [in] 垂直表示幅
 * @param           hfs [in] 水平表示幅
 * @return          void
 * @description     AG903_DSP->FRMSIZE にライトします.
 */
void AG903_DSPPrmSetFRMSIZE(uint8_t ch, uint32_t vfs, uint32_t hfs)
{
	ASSERT(ch < AG903_DSP_CH_NUM);

	uint32_t reg = 0;
	reg |= (vfs << AG903_DSPn_FRMSIZE_VFS_POS) & AG903_DSPn_FRMSIZE_VFS_MSK;
	reg |= (hfs << AG903_DSPn_FRMSIZE_HFS_POS) & AG903_DSPn_FRMSIZE_HFS_MSK;
	AG903_DSPn(ch)->FRMSIZE = reg;
}

/**
 * @brief           CDCTRLレジスタからの読み込み.
 * @param           ch [in] DSPチャンネル (0-1)
 * @param           *cdctrl [out] 設定値
 * @return          void
 * @description     AG903_DSP->CDCTRL からリードします.
 * @seealso         設定値については DSPPrmParamCDCTRL を参照.
 */
void AG903_DSPPrmGetCDCTRL(uint8_t ch, DSPPrmParamCDCTRL *cdctrl)
{
	ASSERT(ch < AG903_DSP_CH_NUM);
	ASSERT(cdctrl != NULL);

	uint32_t reg = AG903_DSPn(ch)->CDCTRL;
	cdctrl->be = (reg & AG903_DSPn_CDCTRL_BE_MSK) >> AG903_DSPn_CDCTRL_BE_POS;
	cdctrl->ge = (reg & AG903_DSPn_CDCTRL_GE_MSK) >> AG903_DSPn_CDCTRL_GE_POS;
	cdctrl->re = (reg & AG903_DSPn_CDCTRL_RE_MSK) >> AG903_DSPn_CDCTRL_RE_POS;
	cdctrl->ae = (reg & AG903_DSPn_CDCTRL_AE_MSK) >> AG903_DSPn_CDCTRL_AE_POS;
}

/**
 * @brief           CDCTRLレジスタへの書き込み.
 * @param           ch [in] DSPチャンネル (0-1)
 * @param           *cdctrl [in] 設定値
 * @return          void
 * @description     AG903_DSP->CDCTRL にライトします.
 * @seealso         設定値については DSPPrmParamCDCTRL を参照.
 */
void AG903_DSPPrmSetCDCTRL(uint8_t ch, DSPPrmParamCDCTRL *cdctrl)
{
	ASSERT(ch < AG903_DSP_CH_NUM);

	uint32_t reg = 0;
	reg |= (cdctrl->be << AG903_DSPn_CDCTRL_BE_POS) & AG903_DSPn_CDCTRL_BE_MSK;
	reg |= (cdctrl->ge << AG903_DSPn_CDCTRL_GE_POS) & AG903_DSPn_CDCTRL_GE_MSK;
	reg |= (cdctrl->re << AG903_DSPn_CDCTRL_RE_POS) & AG903_DSPn_CDCTRL_RE_MSK;
	reg |= (cdctrl->ae << AG903_DSPn_CDCTRL_AE_POS) & AG903_DSPn_CDCTRL_AE_MSK;
	AG903_DSPn(ch)->CDCTRL = reg;
}

/**
 * @brief           COLDETレジスタからの読み込み.
 * @param           ch [in] DSPチャンネル (0-1)
 * @param           *coldet [out] 設定値
 * @return          void
 * @description     AG903_DSP->COLDET からリードします.
 * @seealso         設定値については DSPPrmParamCOLDET を参照.
 */
void AG903_DSPPrmGetCOLDET(uint8_t ch, DSPPrmParamCOLDET *coldet)
{
	ASSERT(ch < AG903_DSP_CH_NUM);
	ASSERT(coldet != NULL);

	uint32_t reg = AG903_DSPn(ch)->COLDET;
	coldet->b = (reg & AG903_DSPn_COLDET_B_MSK) >> AG903_DSPn_COLDET_B_POS;
	coldet->g = (reg & AG903_DSPn_COLDET_G_MSK) >> AG903_DSPn_COLDET_G_POS;
	coldet->r = (reg & AG903_DSPn_COLDET_R_MSK) >> AG903_DSPn_COLDET_R_POS;
	coldet->a = (reg & AG903_DSPn_COLDET_A_MSK) >> AG903_DSPn_COLDET_A_POS;
}

/**
 * @brief           COLDETレジスタへの書き込み.
 * @param           ch [in] DSPチャンネル (0-1)
 * @param           *coldet [in] 設定値
 * @return          void
 * @description     AG903_DSP->COLDET にライトします.
 * @seealso         設定値については DSPPrmParamCOLDET を参照.
 */
void AG903_DSPPrmSetCOLDET(uint8_t ch, DSPPrmParamCOLDET *coldet)
{
	ASSERT(ch < AG903_DSP_CH_NUM);
	ASSERT(coldet != NULL);

	uint32_t reg = 0;
	reg |= (coldet->b << AG903_DSPn_COLDET_B_POS) & AG903_DSPn_COLDET_B_MSK;
	reg |= (coldet->g << AG903_DSPn_COLDET_G_POS) & AG903_DSPn_COLDET_G_MSK;
	reg |= (coldet->r << AG903_DSPn_COLDET_R_POS) & AG903_DSPn_COLDET_R_MSK;
	reg |= (coldet->a << AG903_DSPn_COLDET_A_POS) & AG903_DSPn_COLDET_A_MSK;
	AG903_DSPn(ch)->COLDET = reg;
}

/**
 * @brief           DITHAREA0Aレジスタからの読み込み.
 * @param           ch [in] DSPチャンネル (0-1)
 * @param           *x0 [out] 左上X座標
 * @param           *y0 [out] 左上Y座標
 * @return          void
 * @description     AG903_DSP->DITHAREA0A からリードします.
 */
void AG903_DSPPrmGetDITHAREA0A(uint8_t ch, uint32_t *x0, uint32_t *y0)
{
	ASSERT(ch < AG903_DSP_CH_NUM);
	ASSERT(y0 != NULL);
	ASSERT(x0 != NULL);

	uint32_t reg = AG903_DSPn(ch)->DITHAREA0A;
	*x0 = (reg & AG903_DSPn_DITHAREA0A_X0_MSK) >> AG903_DSPn_DITHAREA0A_X0_POS;
	*y0 = (reg & AG903_DSPn_DITHAREA0A_Y0_MSK) >> AG903_DSPn_DITHAREA0A_Y0_POS;
}

/**
 * @brief           DITHAREA0Aレジスタへの書き込み.
 * @param           ch [in] DSPチャンネル (0-1)
 * @param           x0 [in] 左上X座標
 * @param           y0 [in] 左上Y座標
 * @return          void
 * @description     AG903_DSP->DITHAREA0A にライトします.
 */
void AG903_DSPPrmSetDITHAREA0A(uint8_t ch, uint32_t x0, uint32_t y0)
{
	ASSERT(ch < AG903_DSP_CH_NUM);

	uint32_t reg = 0;
	reg |= (x0 << AG903_DSPn_DITHAREA0A_X0_POS) & AG903_DSPn_DITHAREA0A_X0_MSK;
	reg |= (y0 << AG903_DSPn_DITHAREA0A_Y0_POS) & AG903_DSPn_DITHAREA0A_Y0_MSK;
	AG903_DSPn(ch)->DITHAREA0A = reg;
}

/**
 * @brief           DITHAREA0Bレジスタからの読み込み.
 * @param           ch [in] DSPチャンネル (0-1)
 * @param           *x1 [out] 右下X座標
 * @param           *y1 [out] 右下Y座標
 * @return          void
 * @description     AG903_DSP->DITHAREA0B からリードします.
 */
void AG903_DSPPrmGetDITHAREA0B(uint8_t ch, uint32_t *x1, uint32_t *y1)
{
	ASSERT(ch < AG903_DSP_CH_NUM);
	ASSERT(y1 != NULL);
	ASSERT(x1 != NULL);

	uint32_t reg = AG903_DSPn(ch)->DITHAREA0B;
	*x1 = (reg & AG903_DSPn_DITHAREA0B_X1_MSK) >> AG903_DSPn_DITHAREA0B_X1_POS;
	*y1 = (reg & AG903_DSPn_DITHAREA0B_Y1_MSK) >> AG903_DSPn_DITHAREA0B_Y1_POS;
}

/**
 * @brief           DITHAREA0Bレジスタへの書き込み.
 * @param           ch [in] DSPチャンネル (0-1)
 * @param           x1 [in] 右下X座標
 * @param           y1 [in] 右下Y座標
 * @return          void
 * @description     AG903_DSP->DITHAREA0B にライトします.
 */
void AG903_DSPPrmSetDITHAREA0B(uint8_t ch, uint32_t x1, uint32_t y1)
{
	ASSERT(ch < AG903_DSP_CH_NUM);

	uint32_t reg = 0;
	reg |= (x1 << AG903_DSPn_DITHAREA0B_X1_POS) & AG903_DSPn_DITHAREA0B_X1_MSK;
	reg |= (y1 << AG903_DSPn_DITHAREA0B_Y1_POS) & AG903_DSPn_DITHAREA0B_Y1_MSK;
	AG903_DSPn(ch)->DITHAREA0B = reg;
}

/**
 * @brief           DITHAREA1Aレジスタからの読み込み.
 * @param           ch [in] DSPチャンネル (0-1)
 * @param           *x0 [out] 左上X座標
 * @param           *y0 [out] 左上Y座標
 * @return          void
 * @description     AG903_DSP->DITHAREA1A からリードします.
 */
void AG903_DSPPrmGetDITHAREA1A(uint8_t ch, uint32_t *x0, uint32_t *y0)
{
	ASSERT(ch < AG903_DSP_CH_NUM);
	ASSERT(y0 != NULL);
	ASSERT(x0 != NULL);

	uint32_t reg = AG903_DSPn(ch)->DITHAREA1A;
	*x0 = (reg & AG903_DSPn_DITHAREA1A_X0_MSK) >> AG903_DSPn_DITHAREA1A_X0_POS;
	*y0 = (reg & AG903_DSPn_DITHAREA1A_Y0_MSK) >> AG903_DSPn_DITHAREA1A_Y0_POS;
}

/**
 * @brief           DITHAREA1Aレジスタへの書き込み.
 * @param           ch [in] DSPチャンネル (0-1)
 * @param           x0 [in] 左上X座標
 * @param           y0 [in] 左上Y座標
 * @return          void
 * @description     AG903_DSP->DITHAREA1A にライトします.
 */
void AG903_DSPPrmSetDITHAREA1A(uint8_t ch, uint32_t x0, uint32_t y0)
{
	ASSERT(ch < AG903_DSP_CH_NUM);

	uint32_t reg = 0;
	reg |= (x0 << AG903_DSPn_DITHAREA1A_X0_POS) & AG903_DSPn_DITHAREA1A_X0_MSK;
	reg |= (y0 << AG903_DSPn_DITHAREA1A_Y0_POS) & AG903_DSPn_DITHAREA1A_Y0_MSK;
	AG903_DSPn(ch)->DITHAREA1A = reg;
}

/**
 * @brief           DITHAREA1Bレジスタからの読み込み.
 * @param           ch [in] DSPチャンネル (0-1)
 * @param           *x1 [out] 右下X座標
 * @param           *y1 [out] 右下Y座標
 * @return          void
 * @description     AG903_DSP->DITHAREA1B からリードします.
 */
void AG903_DSPPrmGetDITHAREA1B(uint8_t ch, uint32_t *x1, uint32_t *y1)
{
	ASSERT(ch < AG903_DSP_CH_NUM);
	ASSERT(y1 != NULL);
	ASSERT(x1 != NULL);

	uint32_t reg = AG903_DSPn(ch)->DITHAREA1B;
	*x1 = (reg & AG903_DSPn_DITHAREA1B_X1_MSK) >> AG903_DSPn_DITHAREA1B_X1_POS;
	*y1 = (reg & AG903_DSPn_DITHAREA1B_Y1_MSK) >> AG903_DSPn_DITHAREA1B_Y1_POS;
}

/**
 * @brief           DITHAREA1Bレジスタへの書き込み.
 * @param           ch [in] DSPチャンネル (0-1)
 * @param           x1 [in] 右下X座標
 * @param           y1 [in] 右下Y座標
 * @return          void
 * @description     AG903_DSP->DITHAREA1B にライトします.
 */
void AG903_DSPPrmSetDITHAREA1B(uint8_t ch, uint32_t x1, uint32_t y1)
{
	ASSERT(ch < AG903_DSP_CH_NUM);

	uint32_t reg = 0;
	reg |= (x1 << AG903_DSPn_DITHAREA1B_X1_POS) & AG903_DSPn_DITHAREA1B_X1_MSK;
	reg |= (y1 << AG903_DSPn_DITHAREA1B_Y1_POS) & AG903_DSPn_DITHAREA1B_Y1_MSK;
	AG903_DSPn(ch)->DITHAREA1B = reg;
}

/**
 * @brief           DITHAREA2Aレジスタからの読み込み.
 * @param           ch [in] DSPチャンネル (0-1)
 * @param           *x0 [out] 左上X座標
 * @param           *y0 [out] 左上Y座標
 * @return          void
 * @description     AG903_DSP->DITHAREA2A からリードします.
 */
void AG903_DSPPrmGetDITHAREA2A(uint8_t ch, uint32_t *x0, uint32_t *y0)
{
	ASSERT(ch < AG903_DSP_CH_NUM);
	ASSERT(y0 != NULL);
	ASSERT(x0 != NULL);

	uint32_t reg = AG903_DSPn(ch)->DITHAREA2A;
	*x0 = (reg & AG903_DSPn_DITHAREA2A_X0_MSK) >> AG903_DSPn_DITHAREA2A_X0_POS;
	*y0 = (reg & AG903_DSPn_DITHAREA2A_Y0_MSK) >> AG903_DSPn_DITHAREA2A_Y0_POS;
}

/**
 * @brief           DITHAREA2Aレジスタへの書き込み.
 * @param           ch [in] DSPチャンネル (0-1)
 * @param           x0 [in] 左上X座標
 * @param           y0 [in] 左上Y座標
 * @return          void
 * @description     AG903_DSP->DITHAREA2A にライトします.
 */
void AG903_DSPPrmSetDITHAREA2A(uint8_t ch, uint32_t x0, uint32_t y0)
{
	ASSERT(ch < AG903_DSP_CH_NUM);

	uint32_t reg = 0;
	reg |= (x0 << AG903_DSPn_DITHAREA2A_X0_POS) & AG903_DSPn_DITHAREA2A_X0_MSK;
	reg |= (y0 << AG903_DSPn_DITHAREA2A_Y0_POS) & AG903_DSPn_DITHAREA2A_Y0_MSK;
	AG903_DSPn(ch)->DITHAREA2A = reg;
}

/**
 * @brief           DITHAREA2Bレジスタからの読み込み.
 * @param           ch [in] DSPチャンネル (0-1)
 * @param           *x1 [out] 右下X座標
 * @param           *y1 [out] 右下Y座標
 * @return          void
 * @description     AG903_DSP->DITHAREA2B からリードします.
 */
void AG903_DSPPrmGetDITHAREA2B(uint8_t ch, uint32_t *x1, uint32_t *y1)
{
	ASSERT(ch < AG903_DSP_CH_NUM);
	ASSERT(y1 != NULL);
	ASSERT(x1 != NULL);

	uint32_t reg = AG903_DSPn(ch)->DITHAREA2B;
	*x1 = (reg & AG903_DSPn_DITHAREA2B_X1_MSK) >> AG903_DSPn_DITHAREA2B_X1_POS;
	*y1 = (reg & AG903_DSPn_DITHAREA2B_Y1_MSK) >> AG903_DSPn_DITHAREA2B_Y1_POS;
}

/**
 * @brief           DITHAREA2Bレジスタへの書き込み.
 * @param           ch [in] DSPチャンネル (0-1)
 * @param           x1 [in] 右下X座標
 * @param           y1 [in] 右下Y座標
 * @return          void
 * @description     AG903_DSP->DITHAREA2B にライトします.
 */
void AG903_DSPPrmSetDITHAREA2B(uint8_t ch, uint32_t x1, uint32_t y1)
{
	ASSERT(ch < AG903_DSP_CH_NUM);

	uint32_t reg = 0;
	reg |= (x1 << AG903_DSPn_DITHAREA2B_X1_POS) & AG903_DSPn_DITHAREA2B_X1_MSK;
	reg |= (y1 << AG903_DSPn_DITHAREA2B_Y1_POS) & AG903_DSPn_DITHAREA2B_Y1_MSK;
	AG903_DSPn(ch)->DITHAREA2B = reg;
}

/**
 * @brief           DITHAREA3Aレジスタからの読み込み.
 * @param           ch [in] DSPチャンネル (0-1)
 * @param           *x0 [out] 左上X座標
 * @param           *y0 [out] 左上Y座標
 * @return          void
 * @description     AG903_DSP->DITHAREA3A からリードします.
 */
void AG903_DSPPrmGetDITHAREA3A(uint8_t ch, uint32_t *x0, uint32_t *y0)
{
	ASSERT(ch < AG903_DSP_CH_NUM);
	ASSERT(y0 != NULL);
	ASSERT(x0 != NULL);

	uint32_t reg = AG903_DSPn(ch)->DITHAREA3A;
	*x0 = (reg & AG903_DSPn_DITHAREA3A_X0_MSK) >> AG903_DSPn_DITHAREA3A_X0_POS;
	*y0 = (reg & AG903_DSPn_DITHAREA3A_Y0_MSK) >> AG903_DSPn_DITHAREA3A_Y0_POS;
}

/**
 * @brief           DITHAREA3Aレジスタへの書き込み.
 * @param           ch [in] DSPチャンネル (0-1)
 * @param           x0 [in] 左上X座標
 * @param           y0 [in] 左上Y座標
 * @return          void
 * @description     AG903_DSP->DITHAREA3A にライトします.
 */
void AG903_DSPPrmSetDITHAREA3A(uint8_t ch, uint32_t x0, uint32_t y0)
{
	ASSERT(ch < AG903_DSP_CH_NUM);

	uint32_t reg = 0;
	reg |= (x0 << AG903_DSPn_DITHAREA3A_X0_POS) & AG903_DSPn_DITHAREA3A_X0_MSK;
	reg |= (y0 << AG903_DSPn_DITHAREA3A_Y0_POS) & AG903_DSPn_DITHAREA3A_Y0_MSK;
	AG903_DSPn(ch)->DITHAREA3A = reg;
}

/**
 * @brief           DITHAREA3Bレジスタからの読み込み.
 * @param           ch [in] DSPチャンネル (0-1)
 * @param           *x1 [out] 右下X座標
 * @param           *y1 [out] 右下Y座標
 * @return          void
 * @description     AG903_DSP->DITHAREA3B からリードします.
 */
void AG903_DSPPrmGetDITHAREA3B(uint8_t ch, uint32_t *x1, uint32_t *y1)
{
	ASSERT(ch < AG903_DSP_CH_NUM);
	ASSERT(y1 != NULL);
	ASSERT(x1 != NULL);

	uint32_t reg = AG903_DSPn(ch)->DITHAREA3B;
	*x1 = (reg & AG903_DSPn_DITHAREA3B_X1_MSK) >> AG903_DSPn_DITHAREA3B_X1_POS;
	*y1 = (reg & AG903_DSPn_DITHAREA3B_Y1_MSK) >> AG903_DSPn_DITHAREA3B_Y1_POS;
}

/**
 * @brief           DITHAREA3Bレジスタへの書き込み.
 * @param           ch [in] DSPチャンネル (0-1)
 * @param           x1 [in] 右下X座標
 * @param           y1 [in] 右下Y座標
 * @return          void
 * @description     AG903_DSP->DITHAREA3B にライトします.
 */
void AG903_DSPPrmSetDITHAREA3B(uint8_t ch, uint32_t x1, uint32_t y1)
{
	ASSERT(ch < AG903_DSP_CH_NUM);

	uint32_t reg = 0;
	reg |= (x1 << AG903_DSPn_DITHAREA3B_X1_POS) & AG903_DSPn_DITHAREA3B_X1_MSK;
	reg |= (y1 << AG903_DSPn_DITHAREA3B_Y1_POS) & AG903_DSPn_DITHAREA3B_Y1_MSK;
	AG903_DSPn(ch)->DITHAREA3B = reg;
}

/**
 * @brief           ERRSTATレジスタからの読み込み.
 * @param           ch [in] DSPチャンネル (0-1)
 * @param           *errstat [out] エラー状態
 * @return          void
 * @description     AG903_DSP->ERRSTAT からリードします.
 * @seealso         設定値については DSPPrmParamERRSTAT を参照.
 */
void AG903_DSPPrmGetERRSTAT(uint8_t ch, DSPPrmParamERRSTAT *errstat)
{
	ASSERT(ch < AG903_DSP_CH_NUM);
	ASSERT(errstat != NULL);

	uint32_t reg = AG903_DSPn(ch)->ERRSTAT;
	errstat->line = (reg & AG903_DSPn_ERRSTAT_LINE_MSK) >> AG903_DSPn_ERRSTAT_LINE_POS;
	errstat->ue	  = (reg & AG903_DSPn_ERRSTAT_UE_MSK	) >> AG903_DSPn_ERRSTAT_UE_POS;
	errstat->le	  = (reg & AG903_DSPn_ERRSTAT_LE_MSK	) >> AG903_DSPn_ERRSTAT_LE_POS;
	errstat->pe	  = (reg & AG903_DSPn_ERRSTAT_PE_MSK	) >> AG903_DSPn_ERRSTAT_PE_POS;
}

/**
 * @brief           ERRCLRレジスタへの書き込み.
 * @param           ch [in] DSPチャンネル (0-1)
 * @param           *errclr [in] 設定値
 * @return          void
 * @description     AG903_DSP->ERRCLR にライトします.
 * @seealso         設定値については DSPPrmParamERRCLR を参照.
 */
void AG903_DSPPrmSetERRCLR(uint8_t ch, DSPPrmParamERRCLR *errclr)
{
	ASSERT(ch < AG903_DSP_CH_NUM);
	ASSERT(errclr != NULL);

	uint32_t reg = 0;
	reg |= (errclr->line << AG903_DSPn_ERRCLR_LINE_POS) & AG903_DSPn_ERRCLR_LINE_MSK;
	reg |= (errclr->ue   << AG903_DSPn_ERRCLR_UE_POS  ) & AG903_DSPn_ERRCLR_UE_MSK;
	reg |= (errclr->le   << AG903_DSPn_ERRCLR_LE_POS  ) & AG903_DSPn_ERRCLR_LE_MSK;
	reg |= (errclr->pe   << AG903_DSPn_ERRCLR_PE_POS  ) & AG903_DSPn_ERRCLR_PE_MSK;
	AG903_DSPn(ch)->ERRCLR = reg;
}

/**
 * @brief           INTレジスタからの読み込み.
 * @param           ch [in] DSPチャンネル (0-1)
 * @param           *intprm [out] 設定値
 * @return          void
 * @description     AG903_DSP->INT からリードします.
 * @seealso         設定値については DSPPrmParamINT を参照.
 */
void AG903_DSPPrmGetINT(uint8_t ch, DSPPrmParamINT *intprm)
{
	ASSERT(ch < AG903_DSP_CH_NUM);
	ASSERT(intprm != NULL);

	uint32_t reg = AG903_DSPn(ch)->INT;
	intprm->line	= (reg & AG903_DSPn_INT_LINE_MSK ) >> AG903_DSPn_INT_LINE_POS;
	intprm->fcnt	= (reg & AG903_DSPn_INT_FCNT_MSK ) >> AG903_DSPn_INT_FCNT_POS;
	intprm->hline = (reg & AG903_DSPn_INT_HLINE_MSK) >> AG903_DSPn_INT_HLINE_POS;
	intprm->vblk	= (reg & AG903_DSPn_INT_VBLK_MSK ) >> AG903_DSPn_INT_VBLK_POS;
}

/**
 * @brief           INTレジスタへの書き込み.
 * @param           ch [in] DSPチャンネル (0-1)
 * @param           *intprm [in] 設定値
 * @return          void
 * @description     AG903_DSP->INT にライトします.
 * @seealso         設定値については DSPPrmParamINT を参照.
 */
void AG903_DSPPrmSetINT(uint8_t ch, DSPPrmParamINT *intprm)
{
	ASSERT(ch < AG903_DSP_CH_NUM);
	ASSERT(intprm != NULL);

	uint32_t reg = 0;
	reg |= (intprm->line  << AG903_DSPn_INT_LINE_POS ) & AG903_DSPn_INT_LINE_MSK;
	reg |= (intprm->fcnt  << AG903_DSPn_INT_FCNT_POS ) & AG903_DSPn_INT_FCNT_MSK;
	reg |= (intprm->hline << AG903_DSPn_INT_HLINE_POS) & AG903_DSPn_INT_HLINE_MSK;
	reg |= (intprm->vblk  << AG903_DSPn_INT_VBLK_POS ) & AG903_DSPn_INT_VBLK_MSK;
	AG903_DSPn(ch)->INT = reg;
}

/**
 * @brief           TRIGGERレジスタからの読み込み.
 * @param           ch [in] DSPチャンネル (0-1)
 * @param           *out [out] イベント出力選択
 * @param           *hrz [out] 水平イベントタイミング
 * @param           *vt [out] 垂直イベントタイミング
 * @return          void
 * @description     AG903_DSP->TRIGGER からリードします.
 */
void AG903_DSPPrmGetTRIGGER(uint8_t ch, uint32_t *out, uint32_t *hrz, uint32_t *vt)
{
	ASSERT(ch < AG903_DSP_CH_NUM);
	ASSERT(out != NULL);
	ASSERT(hrz != NULL);
	ASSERT(vt  != NULL);

	uint32_t reg = AG903_DSPn(ch)->TRIGGER;
	*out = (reg & AG903_DSPn_TRIGGER_OUT_MSK ) >> AG903_DSPn_TRIGGER_OUT_POS;
	*hrz = (reg & AG903_DSPn_TRIGGER_HRZ_MSK ) >> AG903_DSPn_TRIGGER_HRZ_POS;
	*vt  = (reg & AG903_DSPn_TRIGGER_VT_MSK  ) >> AG903_DSPn_TRIGGER_VT_POS;
}

/**
 * @brief           TRIGGERレジスタへの書き込み.
 * @param           ch [in] DSPチャンネル (0-1)
 * @param           out [in] イベント出力選択
 * @param           hrz [in] 水平イベントタイミング
 * @param           vt [in] 垂直イベントタイミング
 * @return          void
 * @description     AG903_DSP->TRIGGER にライトします.
 */
void AG903_DSPPrmSetTRIGGER(uint8_t ch, uint32_t out, uint32_t hrz, uint32_t vt)
{
	ASSERT(ch < AG903_DSP_CH_NUM);

	uint32_t reg = 0;
	reg |= (out << AG903_DSPn_TRIGGER_OUT_POS) & AG903_DSPn_TRIGGER_OUT_MSK;
	reg |= (hrz << AG903_DSPn_TRIGGER_HRZ_POS) & AG903_DSPn_TRIGGER_HRZ_MSK;
	reg |= (vt  << AG903_DSPn_TRIGGER_VT_POS ) & AG903_DSPn_TRIGGER_VT_MSK;
	AG903_DSPn(ch)->TRIGGER = reg;
}

/**
 * @brief           INTSTATレジスタからの読み込み.
 * @param           ch [in] DSPチャンネル (0-1)
 * @param           *intstat [out] 割り込み状態
 * @return          void
 * @description     AG903_DSP->INTSTAT からリードします.
 * @seealso         設定値については DSPPrmParamINTSTAT を参照.
 */
void AG903_DSPPrmGetINTSTAT(uint8_t ch, DSPPrmParamINTSTAT *intstat)
{
	ASSERT(ch < AG903_DSP_CH_NUM);
	ASSERT(intstat  != NULL);

	uint32_t reg = AG903_DSPn(ch)->INTSTAT;
	intstat->vblk  = (reg & AG903_DSPn_INTSTAT_VBLK_MSK ) >> AG903_DSPn_INTSTAT_VBLK_POS;
	intstat->hline = (reg & AG903_DSPn_INTSTAT_HLINE_MSK) >> AG903_DSPn_INTSTAT_HLINE_POS;
	intstat->doff  = (reg & AG903_DSPn_INTSTAT_DOFF_MSK ) >> AG903_DSPn_INTSTAT_DOFF_POS;
	intstat->dreq  = (reg & AG903_DSPn_INTSTAT_DREQ_MSK ) >> AG903_DSPn_INTSTAT_DREQ_POS;
}

/**
 * @brief           INTCLRレジスタへの書き込み.
 * @param           ch [in] DSPチャンネル (0-1)
 * @param           vblk [in] 垂直ブランク割り込みクリア
 * @param           hline [in] ライン割り込みクリア
 * @param           doff [in] 表示回路停止割り込みクリア
 * @return          void
 * @description     AG903_DSP->INTCLR にライトします.
 */
void AG903_DSPPrmSetINTCLR(uint8_t ch, uint32_t vblk, uint32_t hline, uint32_t doff)
{
	ASSERT(ch < AG903_DSP_CH_NUM);

	uint32_t reg = 0;
	reg |= (vblk  << AG903_DSPn_INTCLR_VBLK_POS ) & AG903_DSPn_INTCLR_VBLK_MSK;
	reg |= (hline << AG903_DSPn_INTCLR_HLINE_POS) & AG903_DSPn_INTCLR_HLINE_MSK;
	reg |= (doff  << AG903_DSPn_INTCLR_DOFF_POS ) & AG903_DSPn_INTCLR_DOFF_MSK;
	AG903_DSPn(ch)->INTCLR = reg;
}

/**
 * @brief           INTMASKレジスタからの読み込み.
 * @param           ch [in] DSPチャンネル (0-1)
 * @param           *intmask [out] 設定値
 * @return          void
 * @description     AG903_DSP->INTMASK からリードします.
 * @seealso         設定値については DSPPrmParamINTMASK を参照.
 */
void AG903_DSPPrmGetINTMASK(uint8_t ch, DSPPrmParamINTMASK *intmask)
{
	ASSERT(ch < AG903_DSP_CH_NUM);
	ASSERT(intmask != NULL);

	uint32_t reg = AG903_DSPn(ch)->INTMASK;
	intmask->vblk  = (reg & AG903_DSPn_INTMASK_VBLK_MSK ) >> AG903_DSPn_INTMASK_VBLK_POS;
	intmask->hline = (reg & AG903_DSPn_INTMASK_HLINE_MSK) >> AG903_DSPn_INTMASK_HLINE_POS;
	intmask->doff  = (reg & AG903_DSPn_INTMASK_DOFF_MSK ) >> AG903_DSPn_INTMASK_DOFF_POS;
	intmask->err   = (reg & AG903_DSPn_INTMASK_ERR_MSK  ) >> AG903_DSPn_INTMASK_ERR_POS;
}

/**
 * @brief           INTMASKレジスタへの書き込み.
 * @param           ch [in] DSPチャンネル (0-1)
 * @param           *intmask [in] 設定値
 * @return          void
 * @description     AG903_DSP->INTMASK にライトします.
 * @seealso         設定値については DSPPrmParamINTMASK を参照.
 */
void AG903_DSPPrmSetINTMASK(uint8_t ch, DSPPrmParamINTMASK *intmask)
{
	ASSERT(ch < AG903_DSP_CH_NUM);
	ASSERT(intmask != NULL);

	uint32_t reg = 0;
	reg |= (intmask->vblk  << AG903_DSPn_INTMASK_VBLK_POS ) & AG903_DSPn_INTMASK_VBLK_MSK;
	reg |= (intmask->hline << AG903_DSPn_INTMASK_HLINE_POS) & AG903_DSPn_INTMASK_HLINE_MSK;
	reg |= (intmask->doff  << AG903_DSPn_INTMASK_DOFF_POS ) & AG903_DSPn_INTMASK_DOFF_MSK;
	reg |= (intmask->err   << AG903_DSPn_INTMASK_ERR_POS  ) & AG903_DSPn_INTMASK_ERR_MSK;
	AG903_DSPn(ch)->INTMASK = reg;
}

/**
 * @brief           DMAREQレジスタからの読み込み.
 * @param           ch [in] DSPチャンネル (0-1)
 * @param           *req [out] DMAリクエストタイミング
 * @return          void
 * @description     AG903_DSP->DMAREQ からリードします.
 */
void AG903_DSPPrmGetDMAREQ(uint8_t ch, uint32_t *req)
{
	ASSERT(ch < AG903_DSP_CH_NUM);
	ASSERT(req  != NULL);

	*req = (AG903_DSPn(ch)->DMAREQ & AG903_DSPn_DMAREQ_REQ_MSK) >> AG903_DSPn_DMAREQ_REQ_POS;
}

/**
 * @brief           DMAREQレジスタへの書き込み.
 * @param           ch [in] DSPチャンネル (0-1)
 * @param           req [in] DMAリクエストタイミング
 * @return          void
 * @description     AG903_DSP->DMAREQ にライトします.
 */
void AG903_DSPPrmSetDMAREQ(uint8_t ch, uint32_t req)
{
	ASSERT(ch < AG903_DSP_CH_NUM);

	AG903_DSPn(ch)->DMAREQ = (req << AG903_DSPn_DMAREQ_REQ_POS) & AG903_DSPn_DMAREQ_REQ_MSK;
}

/**
 * @brief           HRZSTATレジスタからの読み込み.
 * @param           ch [in] DSPチャンネル (0-1)
 * @param           *pix [out] 処理中のピクセル数
 * @param           *stat [out] 回路状態
 * @return          void
 * @description     AG903_DSP->HRZSTAT からリードします.
 */
void AG903_DSPPrmGetHRZSTAT(uint8_t ch, uint32_t *pix, uint32_t *stat)
{
	ASSERT(ch < AG903_DSP_CH_NUM);
	ASSERT(pix != NULL);
	ASSERT(stat != NULL);

	uint32_t reg = AG903_DSPn(ch)->HRZSTAT;
	*pix  = (reg & AG903_DSPn_HRZSTAT_PIX_MSK ) >> AG903_DSPn_HRZSTAT_PIX_POS;
	*stat = (reg & AG903_DSPn_HRZSTAT_STAT_MSK) >> AG903_DSPn_HRZSTAT_STAT_POS;
}

/**
 * @brief           VTSTATレジスタからの読み込み.
 * @param           ch [in] DSPチャンネル (0-1)
 * @param           *line [out] 処理中のライン数
 * @param           *stat [out] 回路状態
 * @param           *fcnt [out] フレームカウンタ
 * @return          void
 * @description     AG903_DSP->VTSTAT からリードします.
 */
void AG903_DSPPrmGetVTSTAT(uint8_t ch, uint32_t *line, uint32_t *stat, uint32_t *fcnt)
{
	ASSERT(ch < AG903_DSP_CH_NUM);
	ASSERT(line != NULL);
	ASSERT(stat != NULL);
	ASSERT(fcnt != NULL);

	uint32_t reg = AG903_DSPn(ch)->VTSTAT;
	*line = (reg & AG903_DSPn_VTSTAT_LINE_MSK) >> AG903_DSPn_VTSTAT_LINE_POS;
	*stat = (reg & AG903_DSPn_VTSTAT_STAT_MSK) >> AG903_DSPn_VTSTAT_STAT_POS;
	*fcnt = (reg & AG903_DSPn_VTSTAT_FCNT_MSK) >> AG903_DSPn_VTSTAT_FCNT_POS;
}

/**
 * @brief           LUTRレジスタからの読み込み.
 * @param           ch [in] DSPチャンネル (0-1)
 * @param           table_no [in] テーブル番号 (0-63)
 * @param           *lutr [out] 設定値
 * @return          void
 * @description     AG903_DSP->LUTR からリードします.
 * @seealso         設定値については DSPPrmParamLUTR を参照.
 */
void AG903_DSPPrmGetLUTR(uint8_t ch, uint8_t table_no, DSPPrmParamLUTR *lutr)
{
	ASSERT(ch < AG903_DSP_CH_NUM);
	ASSERT(lutr != NULL);

	uint32_t reg = AG903_DSPn(ch)->LUTR[table_no];
	lutr->r0 = (reg & AG903_DSPn_LUTR_R0_MSK) >> AG903_DSPn_LUTR_R0_POS;
	lutr->r1 = (reg & AG903_DSPn_LUTR_R1_MSK) >> AG903_DSPn_LUTR_R1_POS;
	lutr->r2 = (reg & AG903_DSPn_LUTR_R2_MSK) >> AG903_DSPn_LUTR_R2_POS;
	lutr->r3 = (reg & AG903_DSPn_LUTR_R3_MSK) >> AG903_DSPn_LUTR_R3_POS;
}

/**
 * @brief           LUTRレジスタへの書き込み.
 * @param           ch [in] DSPチャンネル (0-1)
 * @param           table_no [in] テーブル番号 (0-63)
 * @param           *lutr [in] 設定値
 * @return          void
 * @description     AG903_DSP->LUTR にライトします.
 * @seealso         設定値については DSPPrmParamLUTR を参照.
 */
void AG903_DSPPrmSetLUTR(uint8_t ch, uint8_t table_no, DSPPrmParamLUTR *lutr)
{
	ASSERT(ch < AG903_DSP_CH_NUM);
	ASSERT(lutr != NULL);

	uint32_t reg = 0;
	reg |= (lutr->r0 << AG903_DSPn_LUTR_R0_POS) & AG903_DSPn_LUTR_R0_MSK;
	reg |= (lutr->r1 << AG903_DSPn_LUTR_R1_POS) & AG903_DSPn_LUTR_R1_MSK;
	reg |= (lutr->r2 << AG903_DSPn_LUTR_R2_POS) & AG903_DSPn_LUTR_R2_MSK;
	reg |= (lutr->r3 << AG903_DSPn_LUTR_R3_POS) & AG903_DSPn_LUTR_R3_MSK;
	AG903_DSPn(ch)->LUTR[table_no] = reg;
}

/**
 * @brief           LUTGレジスタからの読み込み.
 * @param           ch [in] DSPチャンネル (0-1)
 * @param           table_no [in] テーブル番号 (0-63)
 * @param           *lutg [out] 設定値
 * @return          void
 * @description     AG903_DSP->LUTG からリードします.
 * @seealso         設定値については DSPPrmParamLUTG を参照.
 */
void AG903_DSPPrmGetLUTG(uint8_t ch, uint8_t table_no, DSPPrmParamLUTG *lutg)
{
	ASSERT(ch < AG903_DSP_CH_NUM);
	ASSERT(lutg != NULL);

	uint32_t reg = AG903_DSPn(ch)->LUTG[table_no];
	lutg->g0 = (reg & AG903_DSPn_LUTG_G0_MSK) >> AG903_DSPn_LUTG_G0_POS;
	lutg->g1 = (reg & AG903_DSPn_LUTG_G1_MSK) >> AG903_DSPn_LUTG_G1_POS;
	lutg->g2 = (reg & AG903_DSPn_LUTG_G2_MSK) >> AG903_DSPn_LUTG_G2_POS;
	lutg->g3 = (reg & AG903_DSPn_LUTG_G3_MSK) >> AG903_DSPn_LUTG_G3_POS;
}

/**
 * @brief           LUTGレジスタへの書き込み.
 * @param           ch [in] DSPチャンネル (0-1)
 * @param           table_no [in] テーブル番号 (0-63)
 * @param           *lutg [in] 設定値
 * @return          void
 * @description     AG903_DSP->LUTG にライトします.
 * @seealso         設定値については DSPPrmParamLUTG を参照.
 */
void AG903_DSPPrmSetLUTG(uint8_t ch, uint8_t table_no, DSPPrmParamLUTG *lutg)
{
	ASSERT(ch < AG903_DSP_CH_NUM);
	ASSERT(lutg != NULL);

	uint32_t reg = 0;
	reg |= (lutg->g0 << AG903_DSPn_LUTG_G0_POS) & AG903_DSPn_LUTG_G0_MSK;
	reg |= (lutg->g1 << AG903_DSPn_LUTG_G1_POS) & AG903_DSPn_LUTG_G1_MSK;
	reg |= (lutg->g2 << AG903_DSPn_LUTG_G2_POS) & AG903_DSPn_LUTG_G2_MSK;
	reg |= (lutg->g3 << AG903_DSPn_LUTG_G3_POS) & AG903_DSPn_LUTG_G3_MSK;
	AG903_DSPn(ch)->LUTG[table_no] = reg;
}


/**
 * @brief           LUTBレジスタからの読み込み.
 * @param           ch [in] DSPチャンネル (0-1)
 * @param           table_no [in] テーブル番号 (0-63)
 * @param           *lutb [out] 設定値
 * @return          void
 * @description     AG903_DSP->LUTB からリードします.
 * @seealso         設定値については DSPPrmParamLUTB を参照.
 */
void AG903_DSPPrmGetLUTB(uint8_t ch, uint8_t table_no, DSPPrmParamLUTB *lutb)
{
	ASSERT(ch < AG903_DSP_CH_NUM);
	ASSERT(lutb != NULL);

	uint32_t reg = AG903_DSPn(ch)->LUTB[table_no];
	lutb->b0 = (reg & AG903_DSPn_LUTB_B0_MSK) >> AG903_DSPn_LUTB_B0_POS;
	lutb->b1 = (reg & AG903_DSPn_LUTB_B1_MSK) >> AG903_DSPn_LUTB_B1_POS;
	lutb->b2 = (reg & AG903_DSPn_LUTB_B2_MSK) >> AG903_DSPn_LUTB_B2_POS;
	lutb->b3 = (reg & AG903_DSPn_LUTB_B3_MSK) >> AG903_DSPn_LUTB_B3_POS;
}

/**
 * @brief           LUTBレジスタへの書き込み.
 * @param           ch [in] DSPチャンネル (0-1)
 * @param           table_no [in] テーブル番号 (0-63)
 * @param           *lutb [in] 設定値
 * @return          void
 * @description     AG903_DSP->LUTB にライトします.
 * @seealso         設定値については DSPPrmParamLUTB を参照.
 */
void AG903_DSPPrmSetLUTB(uint8_t ch, uint8_t table_no, DSPPrmParamLUTB *lutb)
{
	ASSERT(ch < AG903_DSP_CH_NUM);
	ASSERT(lutb != NULL);

	uint32_t reg = 0;
	reg |= (lutb->b0 << AG903_DSPn_LUTB_B0_POS) & AG903_DSPn_LUTB_B0_MSK;
	reg |= (lutb->b1 << AG903_DSPn_LUTB_B1_POS) & AG903_DSPn_LUTB_B1_MSK;
	reg |= (lutb->b2 << AG903_DSPn_LUTB_B2_POS) & AG903_DSPn_LUTB_B2_MSK;
	reg |= (lutb->b3 << AG903_DSPn_LUTB_B3_POS) & AG903_DSPn_LUTB_B3_MSK;
	AG903_DSPn(ch)->LUTB[table_no] = reg;
}

