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

#include "AG903_errno.h"
#include "AG903_common.h"
#include "register/AG903_bscreg.h"
#include "bsc/bscprm.h"


/**
 * @brief           BSCPBSTATのレジスタRead
 * @param           stat [out] バスステータス
 * @return          none
 * @description     BSCPBSTATのレジスタRead
 * @note            none
*/
void AG903_BSCPrmGetPbstat(AG903_BSCPrmPbstat* stat)
{
	uint32_t	val;
	
	ASSERT(NULL != stat);
	
	val = AG903_BSC->PBSTAT;
	
	if(AG903_BSC_PBSTAT_IDE_MSK & val){
		stat->ata_ctr = true;
	}else{
		stat->ata_ctr = false;
	}
	
	if(AG903_BSC_PBSTAT_PCC_MSK & val){
		stat->cf_ctr = true;
	}else{
		stat->cf_ctr = false;
	}
	
	if(AG903_BSC_PBSTAT_BSRQ_MSK & val){
		stat->bus_req = true;
	}else{
		stat->bus_req = false;
	}
	
	if(AG903_BSC_PBSTAT_BSGRT_MSK & val){
		stat->bus_grt = true;
	}else{
		stat->bus_grt = false;
	}
	
	if(AG903_BSC_PBSTAT_MDDV_MSK & val){
    	stat->pbus_mode = AG903_BSC_PBMODE_DEVICE;
	}else{
    	stat->pbus_mode = AG903_BSC_PBMODE_HOST;
	}
	
	if(AG903_BSC_PBSTAT_MDSRM32_MSK & val){
    	stat->bus_wid = AG903_BSC_DTWIDTH_32;
	}else{
		stat->bus_wid = AG903_BSC_DTWIDTH_16;
	}
	
	return;
}


/**
 * @brief           BSCPBINTMASKのレジスタWrite
 * @param           mask [in] マスク指定(ビット単位)
 * @return          none
 * @description     BSCPBINTMASKのレジスタWrite
 * @note            none
*/
void AG903_BSCPrmSetIntMask(uint8_t mask)
{
	AG903_BSC->PBINTMASK = (uint32_t)(mask & (AG903_BSC_PBINTMASK_INT0_MSK | AG903_BSC_PBINTMASK_INT1_MSK |
											  AG903_BSC_PBINTMASK_INT2_MSK | AG903_BSC_PBINTMASK_INT3_MSK));
	return;
}


/**
 * @brief           BSCPBINTMASKのレジスタRead
 * @param           mask [out] マスク状態(ビット単位)
 * @return          none
 * @description     BSCPBINTMASKのレジスタRead
 * @note            none
*/
void AG903_BSCPrmGetIntMask(uint8_t* mask)
{
	ASSERT(NULL != mask);
	(*mask) = (uint8_t)(AG903_BSC->PBINTMASK & (AG903_BSC_PBINTMASK_INT0_MSK | AG903_BSC_PBINTMASK_INT1_MSK |
											    AG903_BSC_PBINTMASK_INT2_MSK | AG903_BSC_PBINTMASK_INT3_MSK));
	return;
}


/**
 * @brief           BSCPBINTMODEのレジスタWrite
 * @param           mode [in] 割り込みモード
 * @return          none
 * @description     BSCPBINTMODEのレジスタWrite
 * @note            none
*/
void AG903_BSCPrmSetIntMode(uint8_t mode)
{
	AG903_BSC->PBINTMODE = (uint32_t)(mode & (AG903_BSC_PBINTMODE_INT0_MSK | AG903_BSC_PBINTMODE_INT1_MSK |
											  AG903_BSC_PBINTMODE_INT2_MSK | AG903_BSC_PBINTMODE_INT3_MSK));
	return;
}

/**
 * @brief           BSCPBINTMODEのレジスタRead
 * @param           mode [out] 割り込みモード
 * @return          none
 * @description     BSCPBINTMODEのレジスタRead
 * @note            none
*/
void AG903_BSCPrmGetIntMode(uint8_t* mode)
{
	ASSERT(NULL != mode);
	(*mode) = (uint8_t)(AG903_BSC->PBINTMODE & (AG903_BSC_PBINTMODE_INT0_MSK | AG903_BSC_PBINTMODE_INT1_MSK |
											    AG903_BSC_PBINTMODE_INT2_MSK | AG903_BSC_PBINTMODE_INT3_MSK));
	return;
}


/**
 * @brief           BSCPBINTPOLのレジスタWrite
 * @param           pol [in] 極性設定
 * @return          none
 * @description     BSCPBINTPOLのレジスタWrite
 * @note            none
*/
void AG903_BSCPrmSetIntPol(uint8_t pol)
{
	AG903_BSC->PBINTPOL = (uint32_t)(pol & (AG903_BSC_PBINTPOL_INT0_MSK | AG903_BSC_PBINTPOL_INT1_MSK |
											AG903_BSC_PBINTPOL_INT2_MSK | AG903_BSC_PBINTPOL_INT3_MSK));
	return;
}


/**
 * @brief           BSCPBINTPOLのレジスタRead
 * @param           pol [out] 極性設定
 * @return          none
 * @description     BSCPBINTPOLのレジスタRead
 * @note            none
*/
void AG903_BSCPrmGetIntPol(uint8_t* pol)
{
	ASSERT(NULL != pol);
	(*pol) = (uint32_t)(AG903_BSC->PBINTMODE & (AG903_BSC_PBINTPOL_INT0_MSK | AG903_BSC_PBINTPOL_INT1_MSK |
												AG903_BSC_PBINTPOL_INT2_MSK | AG903_BSC_PBINTPOL_INT3_MSK));
	return;
}


/**
 * @brief           BSCPBINTCLRのレジスタWrite
 * @param           clr [in] クリア指定
 * @return          none
 * @description     BSCPBINTCLRのレジスタWrite
 * @note            none
*/
void AG903_BSCPrmSetIntClr(uint8_t clr)
{
	AG903_BSC->PBINTCLR = (uint32_t)(clr & (AG903_BSC_PBINTCLR_INT0_MSK | AG903_BSC_PBINTCLR_INT1_MSK |
											AG903_BSC_PBINTCLR_INT2_MSK | AG903_BSC_PBINTCLR_INT3_MSK));
	return;
}


/**
 * @brief           BSCCFMODEのレジスタWrite
 * @param           mode [in] 動作モード
 * @return          none
 * @description     BSCCFMODEのレジスタWrite
 * @note            modeが不正な場合は何も行いません。
*/
void AG903_BSCPrmSetCfMode(uint8_t mode)
{
	if((AG903_BSC_CFMODE_CF==mode) || (AG903_BSC_CFMODE_ATA==mode)) {
		AG903_BSC->CFMODE = mode;
	}

	return;
}


/**
 * @brief           BSCCFMODEのレジスタRead
 * @param           mode [out] 動作モード
 * @return          none
 * @description     BSCCFMODEのレジスタRead
 * @note            none
*/
void AG903_BSCPrmGetCfMode(uint8_t* mode)
{
	ASSERT(NULL != mode);
	
	(*mode) = (uint8_t)(AG903_BSC->CFMODE & AG903_BSC_CFMODE_MDCF_MSK);
	
	return;
}


/**
 * @brief           BSCPBDMAPOLのレジスタWrite
 * @param           req [in] nHDMAREQの極性
 * @param           ack [in] nHDMAACKの極性
 * @return          none
 * @description     BSCPBDMAPOLのレジスタWrite
 * @note            none
*/
void AG903_BSCPrmSetDmaPol(uint8_t req, uint8_t ack)
{
	uint32_t	val = 0;
	
	if(AG903_BSC_POL_POSITIVE == req) {
		val |= (req << AG903_BSC_PBDMAPOL_DRQ_POS);
	}
	if(AG903_BSC_POL_POSITIVE == ack) {
		val |= (ack << AG903_BSC_PBDMAPOL_DCK_POS);
	}
	AG903_BSC->PBDMAPOL = val;
	
	return;
}


/**
 * @brief           BSCPBDMAPOLのレジスタRead
 * @param           req [out] nHDMAREQの極性
 * @param           ack [out] nHDMAACKの極性
 * @return          none
 * @description     BSCPBDMAPOLのレジスタRead
 * @note            none
*/
void AG903_BSCPrmGetDmaPol(uint8_t* req, uint8_t* ack)
{
	uint32_t	val;
	
	ASSERT(NULL != ack);
	ASSERT(NULL != req);
	
	val = AG903_BSC->PBDMAPOL;
	if(AG903_BSC_PBDMAPOL_DRQ_MSK & val) {
		(*req) = AG903_BSC_POL_POSITIVE;
	}
	else {
		(*req) = AG903_BSC_POL_NEGATIVE;
	}
	if(AG903_BSC_PBDMAPOL_DCK_MSK & val) {
		(*ack) = AG903_BSC_POL_POSITIVE;
	}
	else {
		(*ack) = AG903_BSC_POL_NEGATIVE;
	}
	
	return;
}


/**
 * @brief           BSCCFPMCMDのレジスタWrite
 * @param           slp [in] 電源異常検出による遷移の実施有無
 * @param           act [in] カード挿入による遷移の実施有無
 * @param           cmd [in] 電源管理シーケンサへのコマンド
 * @return          none
 * @description     BSCCFPMCMDのレジスタWrite
 * @note            none
*/
void AG903_BSCPrmSetCfpmCmd(uint8_t slp, uint8_t act, uint8_t cmd)
{
	uint32_t	val = 0;

	if(false == slp) {
		val |= (1 << AG903_BSC_CFPMCMD_SLP_POS);	/* 1b：遷移を行わない */
	}

	if(false == act) {
		val |= (1 << AG903_BSC_CFPMCMD_ACT_POS);	/* 1b：遷移を行わない */
	}
	
	val |= (cmd << AG903_BSC_CFPMCMD_CMD_POS) & AG903_BSC_CFPMCMD_CMD_MSK;

	AG903_BSC->CFPMCMD = val;

	return;
}


/**
 * @brief           BSCCFPMCMDのレジスタRead
 * @param           slp [out] 電源異常検出による遷移の実施有無
 * @param           act [out] カード挿入による遷移の実施有無
 * @return          none
 * @description     BSCCFPMCMDのレジスタRead
 * @note            none
*/
void AG903_BSCPrmGetCfpmCmd(uint8_t* slp, uint8_t* act)
{
	uint32_t	val;
	
	ASSERT(NULL != slp);
	ASSERT(NULL != act);
	
	val = AG903_BSC->CFPMCMD;
	
	if(AG903_BSC_CFPMCMD_SLP_MSK & val) {
		(*slp) = false;	/* 1b：遷移を行わない */
	}
	else {
		(*slp) = true;
	}
	
	if(AG903_BSC_CFPMCMD_ACT_MSK & val) {
		(*act) = false;	/* 1b：遷移を行わない */
	}
	else {
		(*act) = true;
	}

	return;
}


/**
 * @brief           BSCCFPMSTATのレジスタRead
 * @param           cd   [out] CF_nCD 端子の状態
 * @param           stat [out] 電源管理シーケンサの状態
 * @return          none
 * @description     BSCCFPMSTATのレジスタRead
 * @note            none
*/
void AG903_BSCPrmGetCfpmStat(uint8_t* cd, uint8_t* stat)
{
	uint32_t	val;
	
	ASSERT(NULL != cd);
	ASSERT(NULL != stat);
	
	val = AG903_BSC->CFPMSTAT;
	(*cd)	= (uint8_t)((val & AG903_BSC_CFPMSTAT_CD_MSK) >> AG903_BSC_CFPMSTAT_CD_POS);
	(*stat) = (uint8_t)((val & AG903_BSC_CFPMSTAT_STAT_MSK) >> AG903_BSC_CFPMSTAT_STAT_POS);
	
	return;
}


/**
 * @brief           BSCCFPMTONのレジスタWrite
 * @param           cycle [in] CF電源投入安定待ち時間
 * @return          none
 * @description     BSCCFPMTONのレジスタWrite
 * @note            cycleは0.1ms以上を設定。（CFカード動作仕様）
*/
void AG903_BSCPrmSetCfpmTon(uint32_t cycle)
{
	AG903_BSC->CFPMTON = cycle & AG903_BSC_CFPMTON_CYCLE_MSK;
	
	return;
}


/**
 * @brief           BSCCFPMTONのレジスタRead
 * @param           cycle [out] CF電源投入安定待ち時間 (単位：パラレルバスホストクロック)
 * @return          none
 * @description     BSCCFPMTONのレジスタRead
 * @note            none
*/
void AG903_BSCPrmGetCfpmTon(uint32_t* cycle)
{
	ASSERT(NULL != cycle);
	
	(*cycle) = AG903_BSC->CFPMTON & AG903_BSC_CFPMTON_CYCLE_MSK;
	
	return;
}


/**
 * @brief           BSCCFPMTR0のレジスタWrite
 * @param           cycle [in] CFリセット前待ち時間 (単位：パラレルバスホストクロック)
 * @return          none
 * @description     BSCCFPMTR0のレジスタWrite
 * @note            cycleは1ms以上を設定。（CFカード動作仕様）
*/
void AG903_BSCPrmSetCfpmTr0(uint32_t cycle)
{
	AG903_BSC->CFPMTR0 = cycle & AG903_BSC_CFPMTR0_CYCLE_MSK;
	
	return;
}


/**
 * @brief           BSCCFPMTR0のレジスタRead
 * @param           cycle [out] CFリセット前待ち時間 (単位：パラレルバスホストクロック)
 * @return          none
 * @description     BSCCFPMTR0のレジスタRead
 * @note            none
*/
void AG903_BSCPrmGetCfpmTr0(uint32_t* cycle)
{
	ASSERT(NULL != cycle);
	
	(*cycle) = AG903_BSC->CFPMTR0 & AG903_BSC_CFPMTR0_CYCLE_MSK;
	
	return;
}


/**
 * @brief           BSCCFPMTR1のレジスタWrite
 * @param           cycle [in] CFリセット中待ち時間 (単位：パラレルバスホストクロック)
 * @return          none
 * @description     BSCCFPMTR1のレジスタWrite
 * @note            cycleは0.01ms以上を設定。（CFカード動作仕様）
*/
void AG903_BSCPrmSetCfpmTr1(uint32_t cycle)
{
	AG903_BSC->CFPMTR1 = cycle & AG903_BSC_CFPMTR1_CYCLE_MSK;
	
	return;
}


/**
 * @brief           BSCCFPMTR1のレジスタRead
 * @param           cycle [out] CFリセット中待ち時間 (単位：パラレルバスホストクロック)
 * @return          none
 * @description     BSCCFPMTR1のレジスタRead
 * @note            none
*/
void AG903_BSCPrmGetCfpmTr1(uint32_t* cycle)
{
	ASSERT(NULL != cycle);
	
	(*cycle) = AG903_BSC->CFPMTR1 & AG903_BSC_CFPMTR1_CYCLE_MSK;
	
	return;
}


/**
 * @brief           BSCCFPMTR2のレジスタWrite
 * @param           cycle [in] CFリセット後待ち時間 (単位：パラレルバスホストクロック)
 * @return          none
 * @description     BSCCFPMTR2のレジスタWrite
 * @note            cycleは20ms以上を設定。（CFカード動作仕様）
*/
void AG903_BSCPrmSetCfpmTr2(uint32_t cycle)
{
	AG903_BSC->CFPMTR2 = cycle & AG903_BSC_CFPMTR2_CYCLE_MSK;
	
	return;
}


/**
 * @brief           BSCCFPMTR2のレジスタRead
 * @param           cycle [out] CFリセット後待ち時間 (単位：パラレルバスホストクロック)
 * @return          none
 * @description     BSCCFPMTR2のレジスタRead
 * @note            none
*/
void AG903_BSCPrmGetCfpmTr2(uint32_t* cycle)
{
	ASSERT(NULL != cycle);
	
	(*cycle) = AG903_BSC->CFPMTR2 & AG903_BSC_CFPMTR2_CYCLE_MSK;
	
	return;
}


/**
 * @brief           BSCCFPMTPRのレジスタWrite
 * @param           cycle [in] CFアクセス保護時間 (単位：パラレルバスホストクロック)
 * @return          none
 * @description     BSCCFPMTPRのレジスタWrite
 * @note            cycleは1us以上を設定。（CFカード動作仕様）
*/
void AG903_BSCPrmSetCfpmTpr(uint32_t cycle)
{
	AG903_BSC->CFPMTPR = cycle & AG903_BSC_CFPMTPR_CYCLE_MSK;

	return;
}


/**
 * @brief           BSCCFPMTPRのレジスタRead
 * @param           cycle [out] CFアクセス保護時間 (単位：パラレルバスホストクロック)
 * @return          none
 * @description     BSCCFPMTPRのレジスタRead
 * @note            none
*/
void AG903_BSCPrmGetCfpmTpr(uint32_t* cycle)
{
	ASSERT(NULL != cycle);

	(*cycle) = AG903_BSC->CFPMTPR & AG903_BSC_CFPMTPR_CYCLE_MSK;

	return;
}
