/**
 * @brief           EQS Primitive
 * @author          AXELL CORPORATION
 * @description     EQS Primitive Layer.
 * @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 AXELL CORPORATION, all rights reserved.
 */
/* DOM-IGNORE-END */

#include "AG903_common.h"

#include "register/AG903_eqsreg.h"
#include "eqs/eqsprm.h"
#include "eqs/eqsctl.h"

/**
 * @brief           MODレジスタへの書き込み.
 * @param           mode [in] EQS動作モード
 * @return          void
 * @description     AG903_EQS->MOD にライトします.
 */
void AG903_EQSPrmSetMOD(uint8_t mode)
{
	AG903_EQS->MOD = (uint32_t)((mode<<AG903_EQS_MOD_CM_POS)&AG903_EQS_MOD_CM_MSK);

	return;
}

/**
 * @brief           MODレジスタからの読み込み.
 * @param           mode [out] EQS動作モード
 * @return          void
 * @description     AG903_EQS->MOD からリードします.
 */
void AG903_EQSPrmGetMOD(uint8_t* mode)
{
	uint32_t val;
	
	ASSERT(mode != NULL);

	val = AG903_EQS->MOD;
	(*mode) = (uint8_t)((val&AG903_EQS_MOD_CM_MSK)>>AG903_EQS_MOD_CM_POS);

	return;
}

/**
 * @brief           DIVIDEレジスタへの書き込み.
 * @param           div [in] 分周率
 * @return          void
 * @description     AG903_EQS->DIVIDE にライトします.
 * @note            2以上の値を設定してください.
 */
void AG903_EQSPrmSetDivide(uint16_t div)
{
	ASSERT(div >= AG903_EQS_DIVIDE_MIN);

	AG903_EQS->DIVIDE = (uint32_t)((div<<AG903_EQS_DIVIDE_DIV_POS)&AG903_EQS_DIVIDE_DIV_MSK);

	return;
}

/**
 * @brief           DIVIDEレジスタからの読み込み.
 * @param           div [out] 分周率
 * @return          void
 * @description     AG903_EQS->DIVIDE からリードします.
 */
void AG903_EQSPrmGetDivide(uint16_t* div)
{
	uint32_t val;

	ASSERT(div != NULL);

	val = AG903_EQS->DIVIDE;
	(*div) = (uint16_t)((val&AG903_EQS_DIVIDE_DIV_MSK)>>AG903_EQS_DIVIDE_DIV_POS);

	return;
}

/**
 * @brief           WaitCycleレジスタへの書き込み.
 * @param           count [in] ウェイトサイクル
 * @return          void
 * @description     AG903_EQS->WaitCycle にライトします.
 * @note            0を設定した場合は65536サイクルになります.
 */
void AG903_EQSPrmSetWaitCycle(uint16_t count)
{
	AG903_EQS->WAITCYCLE = (uint32_t)((count<<AG903_EQS_WAITCYCLE_COUNT_POS)&AG903_EQS_WAITCYCLE_COUNT_MSK);

	return;
}

/**
 * @brief           WaitCycleレジスタからの読み込み.
 * @param           count [out] ウェイトサイクル
 * @return          void
 * @description     AG903_EQS->WaitCycle からリードします.
 */
void AG903_EQSPrmGetWaitCycle(uint16_t* count)
{
	uint32_t val;

	ASSERT(count != NULL);

	val = AG903_EQS->WAITCYCLE;
	(*count) = (uint16_t)((val&AG903_EQS_WAITCYCLE_COUNT_MSK)>>AG903_EQS_WAITCYCLE_COUNT_POS);

	return;
}

/**
 * @brief           Addressレジスタからの読み込み.
 * @param           area [in] EQSエリア番号
 * @param           addr [out] エリアアドレス
 * @return          void
 * @description     AG903_EQS->Address からリードします.
 * @note            EQSエリア番号の値域は0-3です.
 */
void AG903_EQSPrmGetAddress(uint8_t area, uint32_t* addr)
{
	ASSERT(area < AG903_EQS_AREA_MAX);
	ASSERT(addr != NULL);

	(*addr) = (uint32_t)(AG903_EQS_AREA_BASE + AG903_EQS_AREA_SIZ * area);

	return;
}

/**
 * @brief           RdFORMATレジスタへの書き込み.
 * @param           ch [in] EQSエリア番号
 * @param           format [in] フォーマット
 * @return          void
 * @description     AG903_EQS->RdFORMAT にライトします.
 * @note            EQSエリア番号の値域は0-3です.
 */
void AG903_EQSPrmSetRdFORMAT(uint8_t area, AG903_EQSPrmFormat* format)
{
	uint32_t val = 0;

	ASSERT(area < AG903_EQS_AREA_MAX);
	ASSERT(format != NULL);

	val |= (uint32_t)((format->command <<AG903_EQS_RDFMT0_CMD_POS)&AG903_EQS_RDFMT0_CMD_MSK);
	val |= (uint32_t)((format->wait    <<AG903_EQS_RDFMT0_WW_POS) &AG903_EQS_RDFMT0_WW_MSK);
	val |= (uint32_t)((format->addr_len<<AG903_EQS_RDFMT0_AW_POS) &AG903_EQS_RDFMT0_AW_MSK);
	val |= (uint32_t)((format->flow    <<AG903_EQS_RDFMT0_FC_POS) &AG903_EQS_RDFMT0_FC_MSK);

	switch(area) {
		case 0:
			AG903_EQS->RDFMT0 = val;
			break;
		case 1:
			AG903_EQS->RDFMT1 = val;
			break;
		case 2:
			AG903_EQS->RDFMT2 = val;
			break;
		case 3:
			AG903_EQS->RDFMT3 = val;
			break;
	}

	return;
}

/**
 * @brief           WrFORMATレジスタへの書き込み.
 * @param           ch [in] EQSエリア番号
 * @param           format [in] フォーマット
 * @return          void
 * @description     AG903_EQS->WrFORMAT にライトします.
 * @note            EQSエリア番号の値域は0-3です.
 */
void AG903_EQSPrmSetWrFORMAT(uint8_t area, AG903_EQSPrmFormat* format)
{
	uint32_t val = 0;

	ASSERT(area < AG903_EQS_AREA_MAX);
	ASSERT(format != NULL);

	val |= (uint32_t)((format->command <<AG903_EQS_WRFMT0_CMD_POS)&AG903_EQS_WRFMT0_CMD_MSK);
	val |= (uint32_t)((format->wait    <<AG903_EQS_WRFMT0_WW_POS) &AG903_EQS_WRFMT0_WW_MSK);
	val |= (uint32_t)((format->data_len<<AG903_EQS_WRFMT0_DW_POS) &AG903_EQS_WRFMT0_DW_MSK);
	val |= (uint32_t)((format->addr_len<<AG903_EQS_WRFMT0_AW_POS) &AG903_EQS_WRFMT0_AW_MSK);
	val |= (uint32_t)((format->flow    <<AG903_EQS_WRFMT0_FC_POS) &AG903_EQS_WRFMT0_FC_MSK);

	switch(area) {
		case 0:
			AG903_EQS->WRFMT0 = val;
			break;
		case 1:
			AG903_EQS->WRFMT1 = val;
			break;
		case 2:
			AG903_EQS->WRFMT2 = val;
			break;
		case 3:
			AG903_EQS->WRFMT3 = val;
			break;
	}

	return;
}
