/**
 * @brief           EQS Controller
 * @author          AXELL CORPORATION
 * @description     EQS Controller Layer.
 * @note            none
 * @history         2017_09_05  初版
 * @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 "eqs/eqsprm.h"
#include "eqs/eqsctl.h"

/**
 * @brief           EQSモジュール初期化
 * @param           div [in] 分周率
 * @param           cnt [in] ウェイトサイクル
 * @return          AG903_ENONE     正常終了
 * @return          -AG903_EINVAL   引数異常
 * @description     必ず他のEQSCtl関連APIより先に呼び出してください.<p>
 *                  分周率の最低値は 2 です.<p>
 *                  ウェイトサイクルは、CS信号ネゲートからアサートまでの最少待ち時間です.<p>
 *                  待ち時間の単位はシステムクロックで、0を設定した場合は65536サイクルになります.<p>
 *                  初期化時の通信モードはAG903_EQS_MODE_NORM(SPIモード)です.
 */
int32_t AG903_EQSCtlInit(uint16_t div, uint16_t cnt)
{
	int32_t			rc        = AG903_ENONE;
	const uint32_t	clk3KHz   = (AG903_EQS_SYS_CLK / (3 * 1000));			/* 最小通信速度	*/
	const uint32_t	clk100MHz = (AG903_EQS_SYS_CLK / (100 * 1000 * 1000));	/* 最大通信速度	*/

	if ((div > clk3KHz) || (div < clk100MHz)) {
		/* 分周率が2以上でない(通信速度3KHz〜100MHz外) */
		rc = -AG903_EINVAL;
	}

	if (rc == AG903_ENONE) {
		AG903_EQSPrmSetMOD(AG903_EQS_MODE_NORM);
		AG903_EQSPrmSetDivide(div);
		AG903_EQSPrmSetWaitCycle(cnt);
	}

	return rc;
}

/**
 * @brief           通信モード設定
 * @param           mode [in] 通信モード
 * @return          エラーコード
 * @retval          AG903_ENONE     正常終了
 * @retval          -AG903_EINVAL   引数異常
 * @description     EQSの通信モードを変更します.<p>
 *                  'AG903_EQS_MODE_NORM'=SPIモード, 'AG903_EQS_MODE_QUAD'=SQIモード.
 */
int32_t AG903_EQSCtlSetMode(uint8_t mode)
{
	int32_t		rc = AG903_ENONE;

	if (mode > AG903_EQS_MODE_QUAD) {
		rc = -AG903_EINVAL;
	}

	if (rc == AG903_ENONE) {
		AG903_EQSPrmSetMOD((mode & 0x1));
	}

	return rc;
}

/**
 * @brief           エリアアドレス取得
 * @param           area [in] EQSエリア番号
 * @param           addr [out] EQSエリアアドレス格納バッファ
 * @return          エラーコード
 * @retval          AG903_ENONE     正常終了
 * @retval          -AG903_EINVAL   引数異常
 * @description     指定したエリアに対応するアドレスを取得します.
 */
int32_t AG903_EQSCtlGetAddress(uint8_t area, uint32_t *addr)
{
	int32_t	rc = AG903_ENONE;

	if ((area >= AG903_EQS_AREA_NUM) || (addr == NULL)) {
		rc = -AG903_EINVAL;
	}

	if (rc == AG903_ENONE) {
		AG903_EQSPrmGetAddress(area, addr);
	}

	return rc;
}

/**
 * @brief           EQSセットアップ
 * @param           area [in] EQSエリア番号
 * @param           dir [in] I/O方向
 * @param           format [in] フォーマット
 * @return          エラーコード
 * @retval          AG903_ENONE     正常終了
 * @retval          -AG903_EINVAL   引数異常
 * @description     指定したアクセス内容のフォーマットを変更します.
 */
int32_t AG903_EQSCtlSetup(uint8_t area, uint8_t dir, AG903_EQSCtlFormat *format)
{
	AG903_EQSPrmFormat param;
	int32_t	rc = AG903_ENONE;

	if ((area >= AG903_EQS_AREA_NUM) || (format == NULL)) {
		rc = -AG903_EINVAL;
	}

	if (rc == AG903_ENONE) {
		if (AG903_EQS_DIR_READ == dir) {
			param.command  = format->command;
			param.wait     = format->wait;
			param.data_len = 0;
			param.addr_len = format->addr_len;
			param.flow     = format->flow;
			AG903_EQSPrmSetRdFORMAT(area, &param);
		}
		else {
			param.command  = format->command;
			param.wait     = format->wait;
			param.data_len = format->data_len;
			param.addr_len = format->addr_len;
			param.flow     = format->flow;
			AG903_EQSPrmSetWrFORMAT(area, &param);
		}
	}

	return rc;
}
