/**
 * @brief           BMU Primitive
 * @author          AXELL CORPORATION
 * @description     BMU Primitive Layer.
 * @note            none
 * @history         2017_02_22  初版
 * @history         2017_10_26  Ver2.0
 * @history         2019_03_08  [SDK2.2] BMU設定の引数チェックを追加 (#2208)
 * @history         2019_03_08  [SDK2.2] BMUバッファ数0を8とみなす仕様を追加 (#2209)
 */
/* 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 "bmu/bmuprm.h"

/**
 * @brief           CTRLレジスタへの書き込み.
 * @param           unit [in] バッファ管理のユニット番号
 * @param           en [in] バッファ管理の有効・無効
 * @return          void
 * @description     AG903_BMU->CTRL にライトします.
 * @note            none
 */
void AG903_BMUPrmSetCTRL(uint8_t unit, uint8_t en)
{
	ASSERT(unit < AG903_BMU_UNIT_NUM);
	ASSERT(en <= 1);

	AG903_BMUn(unit)->CTRL = (en << AG903_BMUn_CTRL_EN_POS) & AG903_BMUn_CTRL_EN_MSK;
}

/**
 * @brief           CTRLレジスタからの読み込み.
 * @param           unit [in] バッファ管理のユニット番号
 * @param           en [out] バッファ管理の有効・無効
 * @return          void
 * @description     AG903_BMU->CTRL からリードします.
 * @note            none
 */
void AG903_BMUPrmGetCTRL(uint8_t unit, uint8_t *en)
{
	ASSERT(unit < AG903_BMU_UNIT_NUM);
	ASSERT(en != NULL);

	*en = (AG903_BMUn(unit)->CTRL & AG903_BMUn_CTRL_EN_MSK) >> AG903_BMUn_CTRL_EN_POS;
}

/**
 * @brief           MODレジスタへの書き込み.
 * @param           unit [in] バッファ管理のユニット番号
 * @param           ini [in] シンクモジュールのウェイト動作
 * @param           mgr [in] バッファ管理の方式
 * @param           src [in] ソースモジュールのID
 * @return          void
 * @description     AG903_BMU->MOD にライトします.
 * @note            none
 */
void AG903_BMUPrmSetMOD(uint8_t unit, uint8_t ini, uint8_t mgr, uint8_t src)
{
	ASSERT(unit < AG903_BMU_UNIT_NUM);
	ASSERT(ini <= 1);
	ASSERT(mgr <= 3);

	uint32_t reg = 0;
	reg |= (ini << AG903_BMUn_MOD_INI_POS) & AG903_BMUn_MOD_INI_MSK;
	reg |= (mgr << AG903_BMUn_MOD_MGR_POS) & AG903_BMUn_MOD_MGR_MSK;
	reg |= (src << AG903_BMUn_MOD_SRC_POS) & AG903_BMUn_MOD_SRC_MSK;
	AG903_BMUn(unit)->MOD = reg;
}

/**
 * @brief           MODレジスタからの読み込み.
 * @param           unit [in] バッファ管理のユニット番号
 * @param			ini [out] シンクモジュールのウェイト動作
 * @param			mgr [out] バッファ管理の方式
 * @param			src [out] ソースモジュールのID
 * @return          void
 * @description     AG903_BMU->MOD からリードします.
 * @note            none
 */
void AG903_BMUPrmGetMOD(uint8_t unit, uint8_t *ini, uint8_t *mgr, uint8_t *src)
{
	ASSERT(unit < AG903_BMU_UNIT_NUM);
	ASSERT(ini != NULL);
	ASSERT(mgr != NULL);

	uint32_t reg = AG903_BMUn(unit)->MOD;
	*ini = (reg & AG903_BMUn_MOD_INI_MSK) >> AG903_BMUn_MOD_INI_POS;
	*mgr = (reg & AG903_BMUn_MOD_MGR_MSK) >> AG903_BMUn_MOD_MGR_POS;
	*src = (reg & AG903_BMUn_MOD_SRC_MSK) >> AG903_BMUn_MOD_SRC_POS;
}

/**
 * @brief           SINKMODULEレジスタへの書き込み.
 * @param           unit [in] バッファ管理のユニット番号
 * @param           valid [in] シンクモジュールの有効・無効
 * @return          void
 * @description     AG903_BMU->SINKMODULE にライトします.
 * @note            複数のSINKを選択した場合は、バッファの切り替わるタイミングに注意が必要です。
 */
void AG903_BMUPrmSetSINKMODULE(uint8_t unit, uint32_t valid)
{
	ASSERT(unit < AG903_BMU_UNIT_NUM);
	ASSERT((valid & 0xFFFF0000) == 0);

	AG903_BMUn(unit)->SINKMODULE = valid;
}

/**
 * @brief           SINKMODULEレジスタからの読み込み.
 * @param           unit [in] バッファ管理のユニット番号
 * @param           valid [in] シンクモジュールの有効・無効の格納先
 * @return          void
 * @description     AG903_BMU->SINKMODULE からリードします.
 * @note            none
 */
void AG903_BMUPrmGetSINKMODULE(uint8_t unit, uint32_t* valid)
{
	ASSERT(unit < AG903_BMU_UNIT_NUM);
	ASSERT(valid != NULL);

	*valid = AG903_BMUn(unit)->SINKMODULE;
}

/**
 * @brief           SINKSTATレジスタからの読み込み.
 * @param           unit [in] バッファ管理のユニット番号
 * @param           stat [in] シンクモジュールのステータス格納先
 * @return          void
 * @description     AG903_BMU->SINKSTAT からリードします.
 * @note            値はレジスタに保存されないため、値を参照するタイミングは注意が必要です。
 */
void AG903_BMUPrmGetSINKSTAT(uint8_t unit, uint32_t* stat)
{
	ASSERT(unit < AG903_BMU_UNIT_NUM);
	ASSERT(stat != NULL);

	*stat = AG903_BMUn(unit)->SINKSTAT;
}

/**
 * @brief           BASEADRレジスタへの書き込み.
 * @param           unit [in] バッファ管理のユニット番号
 * @param           adr [in] ベースアドレス（128Byte単位）
 * @return          void
 * @description     AG903_BMU->BASEADR にライトします.
 * @note            下位7bitは"0b"に固定されます.
 */
void AG903_BMUPrmSetBASEADR(uint8_t unit, uint32_t adr)
{
	ASSERT(unit < AG903_BMU_UNIT_NUM);

	AG903_BMUn(unit)->BASEADR = (adr & AG903_BMUn_BASEADR_ADR_MSK);
}

/**
 * @brief           BASEADRレジスタからの読み込み.
 * @param           unit [in] バッファ管理のユニット番号
 * @param           adr [out] ベースアドレス（128Byte単位）
 * @return          void
 * @description     AG903_BMU->BASEADR からリードします.
 * @note            none
 */
void AG903_BMUPrmGetBASEADR(uint8_t unit, uint32_t *adr)
{
	ASSERT(unit < AG903_BMU_UNIT_NUM);
	ASSERT(adr != NULL);

	*adr = AG903_BMUn(unit)->BASEADR;
}

/**
 * @brief           STRIDEレジスタへの書き込み.
 * @param           unit [in] バッファ管理のユニット番号
 * @param           stride [in] バッファのサイズ
 * @return          void
 * @description     AG903_BMU->STRIDE にライトします.
 * @note            下位7bitは"0b"に固定されます.
 */
void AG903_BMUPrmSetSTRIDE(uint8_t unit, uint32_t stride)
{
	ASSERT(unit < AG903_BMU_UNIT_NUM);

	AG903_BMUn(unit)->STRIDE = (stride & AG903_BMUn_STRIDE_STRIDE_MSK);
}

/**
 * @brief           STRIDEレジスタからの読み込み.
 * @param           unit [in] バッファ管理のユニット番号
 * @param           stride [out] バッファのサイズ
 * @return          void
 * @description     AG903_BMU->STRIDE からリードします.
 * @note            none
 */
void AG903_BMUPrmGetSTRIDE(uint8_t unit, uint32_t *stride)
{
	ASSERT(unit < AG903_BMU_UNIT_NUM);
	ASSERT(stride != NULL);

	*stride = AG903_BMUn(unit)->STRIDE;
}

/**
 * @brief           BUFNUMレジスタへの書き込み.
 * @param           unit [in] バッファ管理のユニット番号
 * @param           num [in] バッファの数
 * @return          void
 * @description     AG903_BMU->BUFNUM にライトします.
 * @note            none
 */
void AG903_BMUPrmSetBUFNUM(uint8_t unit, uint32_t num)
{
	ASSERT(unit < AG903_BMU_UNIT_NUM);
	ASSERT(num <= 8);

	AG903_BMUn(unit)->BUFNUM = (num << AG903_BMUn_BUFNUM_NUM_POS) & AG903_BMUn_BUFNUM_NUM_MSK;
}

/**
 * @brief           BUFNUMレジスタからの読み込み.
 * @param           unit [in] バッファ管理のユニット番号
 * @param           num [out] バッファの数
 * @return          void
 * @description     AG903_BMU->BUFNUM からリードします.
 * @note            none
 */
void AG903_BMUPrmGetBUFNUM(uint8_t unit, uint32_t *num)
{
	ASSERT(unit < AG903_BMU_UNIT_NUM);
	ASSERT(num  != NULL);

	*num = (AG903_BMUn(unit)->BUFNUM & AG903_BMUn_BUFNUM_NUM_MSK) >> AG903_BMUn_BUFNUM_NUM_POS;
}

/**
 * @brief           STATレジスタからの読み込み.
 * @param           unit [in] バッファ管理のユニット番号
 * @param           stat [out] バッファ管理のステータス情報
 * @return          void
 * @description     AG903_BMU->STAT からリードします.<p>
 *                  BMUPrmParamSTATの各メンバと意味は以下の通りです.
 *                  <table>
 *                  <tr><th>メンバ</th><th>意味</th></tr>
 *                  <tr><td>val</td><td>バッファの書き込み状態</td></tr>
 *                  <tr><td>empty</td><td>バッファが空かどうか</td></tr>
 *                  <tr><td>rwa</td><td>同期モードでシンク側にウェイトが発生したかどうか</td></tr>
 *                  <tr><td>rbsy</td><td>シンクのバッファ使用状況</td></tr>
 *                  <tr><td>rnum</td><td>シンクの使用しているバッファの番号</td></tr>
 *                  <tr><td>full</td><td>バッファのFULLフラグ</td></tr>
 *                  <tr><td>wwa</td><td>同期モードでソース側にウェイトが発生したかどうか</td></tr>
 *                  <tr><td>wbsy</td><td>ソースのバッファ使用状況</td></tr>
 *                  <tr><td>wnum</td><td>ソースの使用しているバッファの番号</td></tr>
 *                  </table>
 */
void AG903_BMUPrmGetSTAT(uint8_t unit, BMUPrmParamSTAT *stat)
{
	ASSERT(unit < AG903_BMU_UNIT_NUM);
	ASSERT(stat != NULL);

	uint32_t reg = AG903_BMUn(unit)->STAT;
	stat->val   = (reg & AG903_BMUn_STAT_VAL_MSK  ) >> AG903_BMUn_STAT_VAL_POS;
	stat->empty = (reg & AG903_BMUn_STAT_EMPTY_MSK) >> AG903_BMUn_STAT_EMPTY_POS;
	stat->rwa   = (reg & AG903_BMUn_STAT_RWA_MSK  ) >> AG903_BMUn_STAT_RWA_POS;
	stat->rbsy  = (reg & AG903_BMUn_STAT_RBSY_MSK ) >> AG903_BMUn_STAT_RBSY_POS;
	stat->rnum  = (reg & AG903_BMUn_STAT_RNUM_MSK ) >> AG903_BMUn_STAT_RNUM_POS;
	stat->full  = (reg & AG903_BMUn_STAT_FULL_MSK ) >> AG903_BMUn_STAT_FULL_POS;
	stat->wwa   = (reg & AG903_BMUn_STAT_WWA_MSK  ) >> AG903_BMUn_STAT_WWA_POS;
	stat->wbsy  = (reg & AG903_BMUn_STAT_WBSY_MSK ) >> AG903_BMUn_STAT_WBSY_POS;
	stat->wnum  = (reg & AG903_BMUn_STAT_WNUM_MSK ) >> AG903_BMUn_STAT_WNUM_POS;
}
