/**
 * @brief           I2C Manager
 * @author          AXELL CORPORATION
 * @description     I2C Manager Layer
 * @note            none
 * @history         2017_02_22  初版
 * @history         2017_10_26  Ver2.0
 * @history         2019_03_08  [SDK2.2] I2Cでの軽微な変数実初期化の修正 (#2111)
 */
/* DOM-IGNORE-BEGIN */
/*
 * This program was created by AXELL CORPORATION.
 * Copyright (C) 2017-2019 AXELL CORPORATION, all rights reserved.
 */
/* DOM-IGNORE-END */

#include "AG903_errno.h"
#include "AG903_intno.h"
#include "i2c/i2cmgr.h"
#include "i2c/i2cprm.h"
#include "i2c.h"
#include "int/intmgr.h"


typedef void (*AG903_I2CMgrIntHdr)(void);	/* コールバック関数型 */

typedef union _AG903_I2CMgrArg{
	AG903_I2CMgrWriteParam	wr;	/** Writeパラメータ */
	AG903_I2CMgrReadParam	rd;	/** Readパラメータ */
} AG903_I2CMgrArg;

typedef struct _AG903_I2CMgrQue{
	AG903_I2CMgrArg	arg;		/** 処理引数 */
	uint32_t	proc;			/** 処理プロセス */
	uint32_t	hdlnum;			/** ハンドル番号 */
} AG903_I2CMgrQue;

typedef struct _AG903_I2CMgrQueStat{
	AG903_I2CMgrQue	que[AG903_I2C_QUENUM]; /* Que */
	uint32_t	wp;				/** Write Pointer */
	uint32_t	rp;				/** Read Pointer */
} AG903_I2CMgrQueStat;

typedef struct _AG903_I2CMgrChStat{
	AG903_I2CMgrArg 	arg;	/** I2C通信パラメタ― */
	uint32_t	hdlnum;			/** ハンドル番号 */
	uint32_t	stat;			/** I2C通信状態 */
	uint32_t	sequence;		/** 処理シーケンスNo. */
	uint32_t	cnt;			/** データカウント */
	int32_t		hdrid;			/** ハンドラID */
} AG903_I2CMgrChStat;

typedef struct _AG903_I2CMgrHandleStat{
	AG903_I2CMgrClbk	clbk;	/** コールバック */
	uint32_t	stat;			/** ハンドル状態 */
	uint8_t		lock;			/** ロック */
	uint8_t		reserve[3];		/** 予約 */
} AG903_I2CMgrHandleStat;

static AG903_I2CMgrChStat		I2cChStat[AG903_I2C_CH_NUM];							/** ch状態 */
static AG903_I2CMgrHandleStat	I2cHandleStat[AG903_I2C_CH_NUM][AG903_I2C_HANDLE_NUM];	/** handle状態 */
static AG903_I2CMgrQueStat		I2cQue[AG903_I2C_CH_NUM];								/** Que状態 */

static void I2CMgr_InitState(uint8_t ch);
static void I2CMgr_MainProcess(uint8_t ch);
static int32_t I2CMgr_ExecuteProcess(uint8_t ch, uint32_t hdlnum, uint32_t proc, AG903_I2CMgrArg* arg);
static int32_t I2CMgr_MasterWrite(uint8_t ch, uint32_t hdlnum, AG903_I2CMgrWriteParam* param);
static int32_t I2CMgr_MasterRead(uint8_t ch, uint32_t hdlnum, AG903_I2CMgrReadParam* param);
static int32_t I2CMgr_SlaveWrite(uint8_t ch, uint32_t hdlnum, AG903_I2CMgrWriteParam* param);
static int32_t I2CMgr_SlaveRead(uint8_t ch, uint32_t hdlnum, AG903_I2CMgrReadParam* param);
static int32_t I2CMgr_SetFrequency(uint8_t ch, uint32_t freq);
static int32_t I2CMgr_SetClock(uint8_t ch, uint32_t cdr, uint16_t tsr, uint8_t gsr);
static int32_t I2CMgr_CheckHandle(AG903_I2CMgrHandle* handle, uint8_t* ch, uint32_t* hdlnum);
static int32_t I2CMgr_SetQue(uint8_t ch, AG903_I2CMgrQue* que);
static int32_t I2CMgr_GetQue(uint8_t ch, AG903_I2CMgrQue* que);
static uint32_t I2CMgr_GetNextQuePoint(uint32_t current);
static int32_t I2CMgr_GetQueCount(uint8_t ch, uint32_t* count);
static void I2CMgr_Inthdr0(void);
static void I2CMgr_Inthdr1(void);
static void I2CMgr_IntProcess(uint8_t ch);
static int32_t I2CMgr_IntMasterWrite(uint8_t ch, uint32_t* event);
static int32_t I2CMgr_IntMasterRead(uint8_t ch, uint32_t* event);
static int32_t I2CMgr_IntSlaveWrite(uint8_t ch, uint32_t* event);
static int32_t I2CMgr_IntSlaveRead(uint8_t ch, uint32_t* event);


static const AG903_I2CMgrIntHdr I2cIntHdr[AG903_I2C_CH_NUM] =
{ I2CMgr_Inthdr0, I2CMgr_Inthdr1 };

/**
 * @brief           I2Cモジュール初期化
 * @param           ch [in] I2Cチャネル番号（0〜1）
 * @return          初期化結果
 * @retval          AG903_ENONE   正常終了
 * @retval          -AG903_EINVAL 引数異常、デフォルト設定値異常
 * @retval          -AG903_EFAULT 処理失敗（割込みハンドラ登録失敗）
 * @description     内部状態の初期化とSCLクロック設定をします。システム起動時にCALLして下さい。<p>
 *                  SCLは以下の定義に従って設定されます。<p>
 *                  AG903_I2C_DFLT_SCL , AG903_I2C_DFLT_GSR , AG903_I2C_DFLT_TSR
 * @note            使用を中止するときは必要に応じアプリでAG903_INTMgrDisableIntによりI2Cの割り込みを無効にして下さい。
*/
int32_t	AG903_I2CMgrInit(uint8_t ch)
{
	AG903_INTMgrHdrPrm inthdr;
	int32_t	 retval = AG903_ENONE;
	int32_t	 hdrid;

	if(AG903_I2C_CH_NUM <= ch) {
		return -AG903_EINVAL;
	}

	I2CMgr_InitState(ch);	/* 内部状態初期化 */

	if(0 >= I2cChStat[ch].hdrid) {
		inthdr.atr   = AG903_INT_HLNG;
		inthdr.intno = AG903_IRQ44_IIC0+ch;
		inthdr.func  = (void*)I2cIntHdr[ch];
		hdrid = AG903_INTMgrSetHandler(&inthdr);
		if(0 >= hdrid) {
			return -AG903_EFAULT;
		}
		I2cChStat[ch].hdrid = hdrid;
	}
	
	AG903_INTMgrEnableInt(AG903_IRQ44_IIC0+ch);

	retval = I2CMgr_SetFrequency(ch, AG903_I2C_DFLT_SCL);

	return retval;
}

/**
 * @brief           SCLクロック設定
 * @param           ch [in] I2Cチャネル番号（0〜1）
 * @param           param [in] パラメータ
 * @return          SCLクロック設定結果
 * @retval          AG903_ENONE   正常終了
 * @retval          -AG903_EINVAL 引数異常
 * @description     SCLクロックを設定します。<p>
 *                  CLK_FTPの周波数は AG903_I2C_CLK で定義します。
 * @note            パラメータについては『AX51903仕様書』を参照して下さい。
*/
int32_t AG903_I2CMgrSetClock(uint8_t ch, AG903_I2CMgrClkPrm* param)
{
	int32_t retval = AG903_ENONE;
	
	if( (AG903_I2C_CH_NUM <= ch) ||
		(NULL == param) ) {
		return -AG903_EINVAL;
	}
	
	retval = I2CMgr_SetClock(ch, param->cdr_val, param->tsr_val, param->gsr_val);

	return retval;
}

/**
 * @brief           スレーブアドレス設定
 * @param           ch [in] I2Cチャネル番号（0〜1）
 * @param           saddr [in] スレーブアドレス
 * @return          スレーブアドレス設定結果
 * @retval          AG903_ENONE   正常終了
 * @retval          -AG903_EINVAL 引数異常
 * @description     スレーブアドレスの設定を行います。
*/
int32_t AG903_I2CMgrSetSlaveAddress(uint8_t ch, uint16_t saddr)
{
	int32_t	 retval = AG903_ENONE;
	
	if( (AG903_I2C_CH_NUM <= ch) ||
		(0xFC00 & saddr) ){
		return -AG903_EINVAL;
	}
	
	AG903_I2CPrmSetSlaveAddr(ch, saddr);
	
	return retval;
}

/**
 * @brief           I2Cハンドル取得
 * @param           ch [in] I2Cチャネル番号（0〜1）
 * @param           handle [out] 該当のI2Cハンドル
 * @return          ハンドル取得結果
 * @retval          AG903_ENONE   正常終了
 * @retval          -AG903_EINVAL 引数異常
 * @retval          -AG903_EBUSY  ハンドル使用中（空き不足）
 * @description     指定したCHのハンドルを取得します。
 * @note            CH毎のハンドル数と処理のキューイング数は以下で定義します。<p>
 *                  AG903_I2C_HANDLE_NUM , AG903_I2C_QUENUM<p>
 *                  AG903_I2C_HANDLE_NUM<= AG903_I2C_QUENUMとして、ハンドル数に対して十分なキュー数を設定して下さい。
*/
int32_t	AG903_I2CMgrGetHandle(uint8_t ch,  AG903_I2CMgrHandle** handle)
{
	int32_t	 retval = AG903_ENONE;
	uint32_t loop;
	
	if( (AG903_I2C_CH_NUM <= ch) ||
		(NULL == handle) ) {
		return -AG903_EINVAL;
	}
	
	for(loop=0; loop<AG903_I2C_HANDLE_NUM; loop++) {
		if(false == I2cHandleStat[ch][loop].lock) {
			I2cHandleStat[ch][loop].lock = true;
			break;
		}
	}
	if(AG903_I2C_HANDLE_NUM <= loop) {
		return -AG903_EBUSY;
	}
	
	I2cHandleStat[ch][loop].stat = AG903_I2C_HANDLE_IDLE;
	I2cHandleStat[ch][loop].clbk = NULL;

	(*handle) = (AG903_I2CMgrHandle*)&I2cHandleStat[ch][loop];

	return retval;
}

/**
 * @brief           I2Cハンドル解放
 * @param           handle [in] I2Cハンドル
 * @return          ハンドル解放結果
 * @retval          AG903_ENONE   正常終了
 * @retval          -AG903_EINVAL 引数異常
 * @retval          -AG903_EBUSY  ハンドル使用中（解放不可）
 * @description     ハンドルを解放します。<p>動作中にハンドルが解放された場合はエラーを返します。
*/
int32_t	AG903_I2CMgrReleaseHandle(AG903_I2CMgrHandle* handle)
{
	int32_t	 retval = AG903_ENONE;
	int32_t	 result;
	uint32_t hdlnum;
	uint8_t	 ch;
	
	result = I2CMgr_CheckHandle(handle, &ch, &hdlnum);
	if(AG903_ENONE != result) {
		return -AG903_EINVAL;
	}
	if(AG903_I2C_HANDLE_IDLE != I2cHandleStat[ch][hdlnum].stat) {
		return -AG903_EBUSY;
	}
	
	I2cHandleStat[ch][hdlnum].clbk = NULL;
	I2cHandleStat[ch][hdlnum].lock = false;
	
	return retval;
}

/**
 * @brief           コールバック登録
 * @param           handle [in] I2Cハンドル
 * @param           clbk [in] コールバック関数ポインタ
 * @return          コールバック登録結果
 * @retval          AG903_ENONE   正常終了
 * @retval          -AG903_EINVAL 引数異常
 * @description     コールバック関数を登録します。
*/
int32_t AG903_I2CMgrSetCallback(AG903_I2CMgrHandle* handle, AG903_I2CMgrClbk clbk)
{
	int32_t	 retval = AG903_ENONE;
	int32_t	 result;
	uint32_t hdlnum;
	uint8_t	 ch;

	result = I2CMgr_CheckHandle(handle, &ch, &hdlnum);
	if(AG903_ENONE != result) {
		return -AG903_EINVAL;
	}
	
	I2cHandleStat[ch][hdlnum].clbk = clbk;
	
	return retval;
}

/**
 * @brief           Master Write
 * @param           handle [in] I2Cハンドル
 * @param           param [in] パラメータ
 * @return          Master Write処理結果
 * @retval          AG903_ENONE   正常終了
 * @retval          -AG903_EINVAL 引数異常
 * @retval          -AG903_EBUSY  ハンドル使用中（キューイング数がMAX）
 * @description     Master Writeを行います。<p>
 *                  指定サイズ分のWrite完了でコールバックします。<p>
 *                  Stop Condition有とした場合は、Write完了後にStop Conditionを発行します。<p>
 *                  Restart conditionを伴うReadを行う場合はStop Condition無として、<p>
 *                  データWrite完了後に AG903_I2CmgrReadData 関数を使用して下さい。
*/
int32_t AG903_I2CMgrMasterWrite(AG903_I2CMgrHandle* handle, AG903_I2CMgrWriteParam* param)
{
	AG903_I2CMgrQue que;
	int32_t	 retval = AG903_ENONE;
	int32_t	 result;
	uint32_t hdlnum;
	uint8_t	 ch;

	result = I2CMgr_CheckHandle(handle, &ch, &hdlnum);
	if(AG903_ENONE != result) {
		return -AG903_EINVAL;
	}
	if(NULL == param) {
		return -AG903_EINVAL;
	}
	if( (NULL == param->buf) ||
		(0 == param->size) ) {
		return -AG903_EINVAL;
	}
	if(0xFF00 & param->addr) {
		if( (AG903_I2C_10BITADDR_SIG != (param->addr>>11)) ||
			(0x0100 & param->addr) ) {	/* bit8：R/W */
			return -AG903_EINVAL;
		}
	}
	else {
		if(0x0001 & param->addr) {      /* bit0：R/W */
			return -AG903_EINVAL;
		}
	}
	
	que.proc   = AG903_I2C_PROC_MASTER_WRITE;
	que.hdlnum = hdlnum;
	que.arg.wr = (*param);	/* 構造体コピー */
	retval = I2CMgr_SetQue(ch, &que);
	if(AG903_ENONE == retval) {
		I2cHandleStat[ch][hdlnum].stat = AG903_I2C_HANDLE_QUEUING;
		I2CMgr_MainProcess(ch);
	}

	return retval;
}

/**
 * @brief           Master Read
 * @param           handle [in] I2Cハンドル
 * @param           param [in] パラメータ
 * @return          Master Read処理結果
 * @retval          AG903_ENONE   正常終了
 * @retval          -AG903_EINVAL 引数異常
 * @retval          -AG903_EBUSY  ハンドル使用中（キューイング数がMAX）
 * @description     Master Readを行います。<p>
 *                  指定サイズ分のRead完了でコールバックします。
*/
int32_t AG903_I2CMgrMasterRead(AG903_I2CMgrHandle* handle, AG903_I2CMgrReadParam* param)
{
	AG903_I2CMgrQue que;
	int32_t	 retval = AG903_ENONE;
	int32_t	 result;
	uint32_t hdlnum;
	uint8_t	 ch;

	result = I2CMgr_CheckHandle(handle, &ch, &hdlnum);
	if(AG903_ENONE != result) {
		return -AG903_EINVAL;
	}
	if(NULL == param) {
		return -AG903_EINVAL;
	}
	if( (NULL == param->buf) ||
		(0 == param->size) ) {
		return -AG903_EINVAL;
	}
	if(0xFF00 & param->addr) {
		if( (AG903_I2C_10BITADDR_SIG != (param->addr>>11)) ||
			(0x0100 & ~param->addr) ) {	/* bit8：R/W */
			return -AG903_EINVAL;
		}
	}
	else {
		if(0x0001 & ~param->addr) {     /* bit0：R/W */
			return -AG903_EINVAL;
		}
	}
	
	que.proc   = AG903_I2C_PROC_MASTER_READ;
	que.hdlnum = hdlnum;
	que.arg.rd = (*param);	/* 構造体コピー */
	retval = I2CMgr_SetQue(ch, &que);
	if(AG903_ENONE == retval) {
		I2cHandleStat[ch][hdlnum].stat = AG903_I2C_HANDLE_QUEUING;
		I2CMgr_MainProcess(ch);
	}

	return retval;
}

/**
 * @brief           Slave Write
 * @param           handle [in] I2Cハンドル
 * @param           buf [in] Writeデータ
 * @param           size [in] Writeサイズ
 * @return          Slave Write処理結果
 * @retval          AG903_ENONE   正常終了
 * @retval          -AG903_EINVAL 引数異常
 * @retval          -AG903_EBUSY  ハンドル使用中（キューイング数がMAX）
 * @description     Slave Writeを行います。<p>
 *                  指定サイズ分のWrite完了でコールバックします。
*/
int32_t AG903_I2CMgrSlaveWrite(AG903_I2CMgrHandle* handle, uint8_t* buf, uint32_t size)
{
	AG903_I2CMgrQue que;
	int32_t	 retval = AG903_ENONE;
	int32_t	 result;
	uint32_t hdlnum;
	uint8_t	 ch;
	
	result = I2CMgr_CheckHandle(handle, &ch, &hdlnum);
	if(AG903_ENONE != result) {
		return -AG903_EINVAL;
	}
	if((NULL == buf) || (0 == size)) {
		return -AG903_EINVAL;
	}

	que.proc   = AG903_I2C_PROC_SLAVE_WRITE;
	que.hdlnum = hdlnum;
	que.arg.wr.buf  = buf;
	que.arg.wr.size = size;
	que.arg.wr.addr = 0;
	retval = I2CMgr_SetQue(ch, &que);
	if(AG903_ENONE == retval) {
		I2cHandleStat[ch][hdlnum].stat = AG903_I2C_HANDLE_QUEUING;
		I2CMgr_MainProcess(ch);
	}

	return retval;
}

/**
 * @brief           Slave Read
 * @param           handle [in] I2Cハンドル
 * @param           buf [in] Readデータ
 * @param           size [in] Readサイズ
 * @return          Slave Read処理結果
 * @retval          AG903_ENONE   正常終了
 * @retval          -AG903_EINVAL 引数異常
 * @retval          -AG903_EBUSY  ハンドル使用中（キューイング数がMAX）
 * @description     Slave Readを行います。<p>
 *                  指定サイズ分のRead完了でコールバックします。
*/
int32_t AG903_I2CMgrSlaveRead(AG903_I2CMgrHandle* handle, uint8_t* buf, uint32_t size)
{
	AG903_I2CMgrQue que;
	int32_t	 retval = AG903_ENONE;
	int32_t	 result;
	uint32_t hdlnum;
	uint8_t	 ch;
	
	result = I2CMgr_CheckHandle(handle, &ch, &hdlnum);
	if(AG903_ENONE != result) {
		return -AG903_EINVAL;
	}
	if((NULL == buf) || (0 == size)) {
		return -AG903_EINVAL;
	}

	que.proc   = AG903_I2C_PROC_SLAVE_READ;
	que.hdlnum = hdlnum;
	que.arg.wr.buf  = buf;
	que.arg.wr.size = size;
	que.arg.wr.addr = 0;
	retval = I2CMgr_SetQue(ch, &que);
	if(AG903_ENONE == retval) {
		I2cHandleStat[ch][hdlnum].stat = AG903_I2C_HANDLE_QUEUING;
		I2CMgr_MainProcess(ch);
	}

	return retval;
}

/**
 * @brief           コントローラ リセット
 * @param           handle [in] I2Cハンドル
 * @return          リセット結果
 * @retval          AG903_ENONE   正常終了
 * @retval          -AG903_EINVAL 引数異常、デフォルト設定値異常
 * @description     コントローラに対してリセットを行います。（即実行）<p>
 *                  キューの内容もクリアします。
*/
int32_t AG903_I2CMgrReset(AG903_I2CMgrHandle* handle)
{
	int32_t	 retval = AG903_ENONE;
	int32_t	 result;
	uint32_t hdlnum;
	uint32_t status;
	uint32_t loop;
	uint8_t	 ch;

	result = I2CMgr_CheckHandle(handle, &ch, &hdlnum);
	if(AG903_ENONE != result) {
		return -AG903_EINVAL;
	}
	
	AG903_I2CPrmResetController(ch);

	I2cQue[ch].wp = 0;
	I2cQue[ch].rp = 0;	/* Queクリア */

	I2cChStat[ch].stat  = AG903_I2C_CH_IDLE;	/* 状態初期化 */
	for(loop=0; loop<AG903_I2C_HANDLE_NUM; loop++) {
		I2cHandleStat[ch][loop].stat = AG903_I2C_HANDLE_IDLE;
	}

	AG903_I2CPrmGetStatus(ch, &status);	/* Read clear */
	retval = I2CMgr_SetFrequency(ch, AG903_I2C_DFLT_SCL);

	return retval;
}


/**
 * @brief           キューカウント取得
 * @param           handle [in] I2Cハンドル
 * @param           count [out] キューカウント値
 * @return          キューカウント取得結果
 * @retval          AG903_ENONE   正常終了
 * @retval          -AG903_EINVAL 引数異常
 * @description     キューに登録されている処理数（カウント数）を返します。
*/
int32_t AG903_I2CMgrGetQueCount(AG903_I2CMgrHandle* handle, uint32_t* count)
{
	int32_t	 retval = AG903_ENONE;
	int32_t	 result;
	uint32_t hdlnum;
	uint8_t	 ch;

	result = I2CMgr_CheckHandle(handle, &ch, &hdlnum);
	if(AG903_ENONE != result) {
		return -AG903_EINVAL;
	}
	if(NULL == count) {
		return -AG903_EINVAL;
	}
	
	retval = I2CMgr_GetQueCount(ch, count);
	
	return retval;
}


/*
	内部状態初期化.
	ch：I2Cチャネル番号（0〜1）.
*/
static void I2CMgr_InitState(uint8_t ch)
{
	uint32_t loop;

	I2cChStat[ch].hdlnum = 0;
	I2cChStat[ch].stat  = AG903_I2C_CH_IDLE;
	I2cChStat[ch].sequence = AG903_I2C_SEQ_NONE;
	I2cChStat[ch].cnt   = 0;
	I2cQue[ch].wp = 0;
	I2cQue[ch].rp = 0;
	for(loop=0; loop<AG903_I2C_HANDLE_NUM; loop++) {
		I2cHandleStat[ch][loop].clbk = NULL;
		I2cHandleStat[ch][loop].stat = AG903_I2C_HANDLE_IDLE;
		I2cHandleStat[ch][loop].lock = false;
	}

	return;
}

/*
	I2Cメイン関数.
	ch：I2Cチャネル番号（0〜1）.
*/
static void I2CMgr_MainProcess(uint8_t ch)
{
	AG903_I2CMgrQue que;
	int32_t	 result;
	
	if(AG903_I2C_CH_IDLE != I2cChStat[ch].stat) {
		return;	/* 処理中 */
	}
	
	result = I2CMgr_GetQue(ch, &que);
	if(AG903_ENONE != result) {
		return;	/* 待ち処理なし */
	}
	
	I2cHandleStat[ch][que.hdlnum].stat = AG903_I2C_HANDLE_EXECUTE;
	result = I2CMgr_ExecuteProcess(ch, que.hdlnum, que.proc, &que.arg);
	if(AG903_ENONE != result) {
		I2cHandleStat[ch][que.hdlnum].stat = AG903_I2C_HANDLE_IDLE;
	}
	
	return;
}

/*
	I2C処理実行関数.
	ch：I2Cチャネル番号（0〜1）.
	hdlnum：ハンドル番号.
	proc：プロセス種別.
	arg：引数パラメータ.
*/
static int32_t I2CMgr_ExecuteProcess(uint8_t ch, uint32_t hdlnum, uint32_t proc, AG903_I2CMgrArg* arg)
{
	int32_t	 retval = AG903_ENONE;

	switch(proc) {
		case AG903_I2C_PROC_MASTER_WRITE:
			retval = I2CMgr_MasterWrite(ch, hdlnum, &arg->wr);
			break;
		case AG903_I2C_PROC_MASTER_READ:
			retval = I2CMgr_MasterRead(ch, hdlnum, &arg->rd);
			break;
		case AG903_I2C_PROC_SLAVE_WRITE:
			retval = I2CMgr_SlaveWrite(ch, hdlnum, &arg->wr);
			break;
		case AG903_I2C_PROC_SLAVE_READ:
			retval = I2CMgr_SlaveRead(ch, hdlnum, &arg->rd);
			break;
		default:
			/* 処理なし */
			retval = -AG903_EINVAL;
			break;
	}
	
	return retval;
}

/*
	Master Write処理.
	ch：I2Cチャネル番号（0〜1）.
	hdlnum：ハンドル番号.
	param：パラメータ.
*/
static int32_t I2CMgr_MasterWrite(uint8_t ch, uint32_t hdlnum, AG903_I2CMgrWriteParam* param)
{
	int32_t	 retval = AG903_ENONE;

	if( (AG903_I2C_CH_NUM <= ch) ||
		(AG903_I2C_HANDLE_NUM <= hdlnum) ||
		(NULL == param) ) {
		return -AG903_EINVAL;
	}
	
	if(AG903_I2C_CH_IDLE != I2cChStat[ch].stat) {
		return -AG903_EBUSY;
	}
	
	I2cChStat[ch].stat = AG903_I2C_CH_MASTER_WRITE;
	I2cChStat[ch].arg.wr = (*param);	/* 構造体コピー */
	I2cChStat[ch].cnt = 0;
	I2cChStat[ch].hdlnum = hdlnum;
	if(0xFF00 & param->addr) {
		I2cChStat[ch].sequence = AG903_I2C_SEQ_SND_SADDR_H;
		AG903_I2CPrmSetExtAddrMode(ch);
		AG903_I2CPrmWriteData(ch, (uint8_t)(I2cChStat[ch].arg.wr.addr>>8));
	}
	else {
		I2cChStat[ch].sequence = AG903_I2C_SEQ_SND_SADDR_L;
		AG903_I2CPrmClearExtAddrMode(ch);
		AG903_I2CPrmWriteData(ch, (uint8_t)(I2cChStat[ch].arg.wr.addr));
	}
	AG903_I2CPrmClearControl(ch, (AG903_I2C_CR_STOP_BIT|AG903_I2C_CR_ACKNACK_BIT));
	AG903_I2CPrmSetControl(ch, AG903_I2C_CR_ALLINT_BIT|AG903_I2C_CR_I2CEN_BIT|AG903_I2C_CR_SCLEN_BIT|
		                                               AG903_I2C_CR_START_BIT|AG903_I2C_CR_TBEN_BIT);
	
	return retval;
}

/*
	Master Read処理.
	ch：I2Cチャネル番号（0〜1）.
	hdlnum：ハンドル番号.
	param：パラメータ.
*/
static int32_t I2CMgr_MasterRead(uint8_t ch, uint32_t hdlnum, AG903_I2CMgrReadParam* param)
{
	int32_t	retval = AG903_ENONE;

	if( (AG903_I2C_CH_NUM <= ch) ||
		(AG903_I2C_HANDLE_NUM <= hdlnum) ||
		(NULL == param) ) {
		return -AG903_EINVAL;
	}
	
	if(AG903_I2C_CH_IDLE != I2cChStat[ch].stat) {
		return -AG903_EBUSY;
	}

	I2cChStat[ch].stat = AG903_I2C_CH_MASTER_READ;
	I2cChStat[ch].arg.rd = (*param);	/* 構造体コピー */
	I2cChStat[ch].cnt = 0;
	I2cChStat[ch].hdlnum = hdlnum;
	if(0xFF00 & param->addr) {
		I2cChStat[ch].sequence = AG903_I2C_SEQ_SND_SADDR_H;
		AG903_I2CPrmSetExtAddrMode(ch);
		AG903_I2CPrmWriteData(ch, (uint8_t)(I2cChStat[ch].arg.wr.addr>>8));
	}
	else {
		I2cChStat[ch].sequence = AG903_I2C_SEQ_SND_SADDR_L;
		AG903_I2CPrmClearExtAddrMode(ch);
		AG903_I2CPrmWriteData(ch, (uint8_t)(I2cChStat[ch].arg.wr.addr));
	}
	AG903_I2CPrmClearControl(ch, AG903_I2C_CR_STOP_BIT|AG903_I2C_CR_ACKNACK_BIT);
	AG903_I2CPrmSetControl(ch, AG903_I2C_CR_ALLINT_BIT|AG903_I2C_CR_I2CEN_BIT|AG903_I2C_CR_SCLEN_BIT|
													   AG903_I2C_CR_START_BIT|AG903_I2C_CR_TBEN_BIT);

	return retval;
}

/*
	Slave Write処理.
	ch：I2Cチャネル番号（0〜1）.
	hdlnum：ハンドル番号.
	param：パラメータ.
*/
static int32_t I2CMgr_SlaveWrite(uint8_t ch, uint32_t hdlnum, AG903_I2CMgrWriteParam* param)
{
	int32_t	 retval = AG903_ENONE;

	if( (AG903_I2C_CH_NUM <= ch) ||
		(AG903_I2C_HANDLE_NUM <= hdlnum) ||
		(NULL == param) ) {
		return -AG903_EINVAL;
	}
	
	if(AG903_I2C_CH_IDLE != I2cChStat[ch].stat) {
		return -AG903_EBUSY;
	}
	
	I2cChStat[ch].stat = AG903_I2C_CH_SLAVE_WRITE;
	I2cChStat[ch].arg.wr = (*param);	/* 構造体コピー */
	I2cChStat[ch].cnt = 0;
	I2cChStat[ch].hdlnum = hdlnum;
	I2cChStat[ch].sequence = AG903_I2C_SEQ_RCV_SADDR;
	
	AG903_I2CPrmClearControl(ch, AG903_I2C_CR_SCLEN_BIT|AG903_I2C_CR_ACKNACK_BIT);
	AG903_I2CPrmSetControl(ch, AG903_I2C_CR_ALLINT_BIT|AG903_I2C_CR_I2CEN_BIT);
	
	return retval;
}

/*
	Slave Read処理.
	ch：I2Cチャネル番号（0〜1）.
	hdlnum：ハンドル番号.
	param：パラメータ.
*/
static int32_t I2CMgr_SlaveRead(uint8_t ch, uint32_t hdlnum, AG903_I2CMgrReadParam* param)
{
	int32_t	retval = AG903_ENONE;

	if( (AG903_I2C_CH_NUM <= ch) ||
		(AG903_I2C_HANDLE_NUM <= hdlnum) ||
		(NULL == param) ) {
		return -AG903_EINVAL;
	}
	
	if(AG903_I2C_CH_IDLE != I2cChStat[ch].stat) {
		return -AG903_EBUSY;
	}

	I2cChStat[ch].stat = AG903_I2C_CH_SLAVE_READ;
	I2cChStat[ch].arg.rd = (*param);	/* 構造体コピー */
	I2cChStat[ch].cnt = 0;
	I2cChStat[ch].hdlnum = hdlnum;
	I2cChStat[ch].sequence = AG903_I2C_SEQ_RCV_SADDR;

	AG903_I2CPrmClearControl(ch, AG903_I2C_CR_SCLEN_BIT);
	AG903_I2CPrmSetControl(ch, AG903_I2C_CR_ALLINT_BIT|AG903_I2C_CR_I2CEN_BIT|AG903_I2C_CR_ACKNACK_BIT);

	return retval;
}

/*
	I2Cクロックを設定する（周波数指定）.
	ch：I2Cチャネル番号（0〜1）.
	freq：周波数[Hz].
*/
static int32_t I2CMgr_SetFrequency(uint8_t ch, uint32_t freq)
{
	int32_t	retval = AG903_ENONE;
	int32_t	val;
	int32_t	cdr;
	
	if(AG903_I2C_CH_NUM <= ch) {
		return -AG903_EINVAL;
	}
	
	val = (AG903_I2C_DFLT_GSR >> 1);
	cdr = ((AG903_I2C_CLK >> 1) / freq) - (2 + val);							/* cdr  = (PCLK/(2*freq))-2-GSR/2 */
	
	retval = I2CMgr_SetClock(ch, cdr, AG903_I2C_DFLT_TSR, AG903_I2C_DFLT_GSR);	/* freq = PCLK/(2*(cdr+2)+GSR) */
	
	return retval;
}

/*
	I2Cクロックを設定する（レジスタ設定）.
	ch：I2Cチャネル番号（0〜1）.
	cdr：CDR設定値.
	tsr：TSR設定値.
	gsr：GSR設定値.
*/
static int32_t I2CMgr_SetClock(uint8_t ch, uint32_t cdr, uint16_t tsr, uint8_t gsr)
{
	if(	(AG903_I2C_CH_NUM <= ch) ||
		(0 >= tsr) ||
		(0xFC00 & tsr) || /* max 10bit */
		(0xF0   & gsr) || /* max 4bit */
		(cdr <= (3U+gsr+tsr)) ) {	/* コントローラ制限 */
		return -AG903_EINVAL;
	}

	AG903_I2CPrmSetClockDivision(ch, cdr);
	AG903_I2CPrmSetGlitchSuppression(ch, tsr, gsr);

	return AG903_ENONE;
}

/*
	ハンドルチェック.
	handle：I2Cハンドル.
	ch：I2Cチャネル.
	hdlnum：ハンドル番号.
*/
static int32_t I2CMgr_CheckHandle(AG903_I2CMgrHandle* handle, uint8_t* ch, uint32_t* hdlnum)
{
	int32_t	 retval = AG903_ENONE;
	uint32_t val;
	uint32_t get_num;
	uint32_t get_ch;
	
	val = ((uint32_t)handle - (uint32_t)I2cHandleStat) / sizeof(AG903_I2CMgrHandleStat);
	get_ch  = val / AG903_I2C_HANDLE_NUM;
	get_num = val % AG903_I2C_HANDLE_NUM;
	
	if( (AG903_I2C_CH_NUM <= get_ch) ||
		(&I2cHandleStat[get_ch][get_num] != (AG903_I2CMgrHandleStat*)handle) ) {
		return -AG903_EINVAL;
	}
	
 	(*ch) = (uint8_t)get_ch;
 	(*hdlnum) = get_num;
	
	return retval;
}

/*
	キュー 書込み.
	ch：I2Cチャネル.
	que：書込みキュー.
*/
static int32_t I2CMgr_SetQue(uint8_t ch, AG903_I2CMgrQue* que)
{
	int32_t	 	retval = AG903_ENONE;
	uint32_t	next_wp;
	
	if( (AG903_I2C_CH_NUM <= ch) ||
		(NULL == que) ){
		return -AG903_EINVAL;
	}
	
	if(1 >= AG903_I2C_QUENUM) {	/* キュー数が1 */
		if(0 < I2cQue[ch].wp) {
			retval = -AG903_EBUSY;	/* 空なし */
		}
		else {
			I2cQue[ch].que[0] = (*que);	/* 構造体コピー */
			I2cQue[ch].wp++;
		}
	}
	else {
		next_wp = I2CMgr_GetNextQuePoint(I2cQue[ch].wp);
		if(next_wp == I2cQue[ch].rp) {
			retval = -AG903_EBUSY;	/* 空なし */
		}
		else {
			I2cQue[ch].que[next_wp] = (*que);	/* 構造体コピー */
			I2cQue[ch].wp = next_wp;
		}
	}
	
	return retval;
}

/*
	キュー 読出し.
	ch：I2Cチャネル.
	que：読出しキュー.
*/
static int32_t I2CMgr_GetQue(uint8_t ch, AG903_I2CMgrQue* que)
{
	int32_t	 retval = AG903_ENONE;
	uint32_t next_rp;
	
	if( (AG903_I2C_CH_NUM <= ch) ||
		(NULL == que) ){
		return -AG903_EINVAL;
	}
	
	if(1 >= AG903_I2C_QUENUM) {	/* キュー数が1 */
		if(0 >= I2cQue[ch].wp) {
			retval = -AG903_ENOMSG;	/* キュー空 */
		}
		else {
			(*que)  = I2cQue[ch].que[0];	/* 構造体コピー */
			I2cQue[ch].wp--;
		}
	}
	else {
		if(I2cQue[ch].wp == I2cQue[ch].rp) {
			retval = -AG903_ENOMSG;	/* キュー空 */
		}
		else {
			next_rp = I2CMgr_GetNextQuePoint(I2cQue[ch].rp);
			(*que)  = I2cQue[ch].que[next_rp];	/* 構造体コピー */
			I2cQue[ch].rp = next_rp;
		}
	}
	
	return retval;
}

/*
	次キューポインタ取得.
	current：現在値.
	next：次キューポインタ.
*/
static uint32_t I2CMgr_GetNextQuePoint(uint32_t current)
{
	uint32_t next;
	
	next = current+1;
	if(AG903_I2C_QUENUM <= next) {
		next = 0;
	}
	
	return next;
}

/*
	キューカウント取得.
	ch：I2Cチャネル.
	count：キューカウント値.
*/
static int32_t I2CMgr_GetQueCount(uint8_t ch, uint32_t* count)
{
	int32_t	 retval = AG903_ENONE;
	
	if( (AG903_I2C_CH_NUM <= ch) ||
		(NULL == count) ) {
		return -AG903_EINVAL;
	}
	
	if(I2cQue[ch].rp <= I2cQue[ch].wp) {
		(*count) = I2cQue[ch].wp - I2cQue[ch].rp;
	}
	else {
		(*count) = AG903_I2C_QUENUM - I2cQue[ch].rp + I2cQue[ch].wp + 1;
	}

	return retval;
}


/*
	割込みハンドラ(CH0).
*/
static void I2CMgr_Inthdr0(void)
{
	I2CMgr_IntProcess(0);	/* CH0 */
	return;
}

/*
	割込みハンドラ(CH1).
*/
static void I2CMgr_Inthdr1(void)
{
	I2CMgr_IntProcess(1);	/* CH1 */
	return;
}

/*
	割込み処理.
	ch：I2Cチャネル.
*/
static void I2CMgr_IntProcess(uint8_t ch)
{
	int32_t result = AG903_ENONE;
	uint32_t event = 0;
	
	switch(I2cChStat[ch].stat) {
		case AG903_I2C_CH_MASTER_WRITE:
			result = I2CMgr_IntMasterWrite(ch, &event);
			if(AG903_ENONE != result) {
				/* 処理なし */
			}
			break;
		case AG903_I2C_CH_MASTER_READ:
			result = I2CMgr_IntMasterRead(ch, &event);
			if(AG903_ENONE != result) {
				/* 処理なし */
			}
			break;
		case AG903_I2C_CH_SLAVE_WRITE:
			result = I2CMgr_IntSlaveWrite(ch, &event);
			if(AG903_ENONE != result) {
				/* 処理なし */
			}
			break;
		case AG903_I2C_CH_SLAVE_READ:
			result = I2CMgr_IntSlaveRead(ch, &event);
			if(AG903_ENONE != result) {
				/* 処理なし */
			}
			break;
		default:
			/* 処理なし */
			break;
	}
	
	if(0 != event) {
		I2cHandleStat[ch][I2cChStat[ch].hdlnum].stat = AG903_I2C_HANDLE_IDLE;
		if(NULL != I2cHandleStat[ch][I2cChStat[ch].hdlnum].clbk) {
			I2cHandleStat[ch][I2cChStat[ch].hdlnum].clbk
					((AG903_I2CMgrHandle*)&I2cHandleStat[ch][I2cChStat[ch].hdlnum], event);	/* コールバック */
		}
	}
	
	I2CMgr_MainProcess(ch);
	
	return;
}

/*
	Master Write処理（割込み）.
	ch：I2Cチャネル番号（0〜1）.
	event：発生イベント.
*/
static int32_t I2CMgr_IntMasterWrite(uint8_t ch, uint32_t* event)
{
	int32_t	 retval = AG903_ENONE;
	uint32_t status;
	uint32_t set_bit = 0;
	uint8_t  nextdata = 0;
	
	(*event) = 0;

	if( (AG903_I2C_CH_NUM <= ch) ||
		(NULL == event) ) {
		return -AG903_EINVAL;
	}
	
	AG903_I2CPrmGetStatus(ch, &status);
	
	if(status&AG903_I2C_SR_AL_BIT) {	/* arbitration負け */
		(*event) |= AG903_I2C_EVENT_LOSES_ARBITRATION;
	}
	if(status&AG903_I2C_SR_BERR_BIT) {	/* Slave non-ACK */
		(*event) |= AG903_I2C_EVENT_SEQUENCE_ERR;
	}
	
	if((0 == (*event)) && (status&AG903_I2C_SR_DT_BIT)) {
		switch(I2cChStat[ch].sequence) {
			case AG903_I2C_SEQ_SND_SADDR_H:
				nextdata = (uint8_t)I2cChStat[ch].arg.wr.addr;
				set_bit  = AG903_I2C_CR_TBEN_BIT;
				I2cChStat[ch].sequence = AG903_I2C_SEQ_SND_SADDR_L;
				break;
			case AG903_I2C_SEQ_SND_SADDR_L:
				nextdata = (*(I2cChStat[ch].arg.wr.buf+I2cChStat[ch].cnt));
				set_bit  = AG903_I2C_CR_TBEN_BIT;
				if(((I2cChStat[ch].cnt+1) >= I2cChStat[ch].arg.wr.size) && (true == I2cChStat[ch].arg.wr.stop)){
					set_bit |= AG903_I2C_CR_STOP_BIT;	/* Stop Condition */
				}
				I2cChStat[ch].sequence = AG903_I2C_SEQ_SND;
				break;
			case AG903_I2C_SEQ_SND:
				I2cChStat[ch].cnt++;
				if(I2cChStat[ch].arg.wr.size <= I2cChStat[ch].cnt) {
					(*event) |= AG903_I2C_EVENT_WRITE_END;	/* Write完了 */
				}
				else {
					nextdata = (*(I2cChStat[ch].arg.wr.buf+I2cChStat[ch].cnt));
					set_bit  = AG903_I2C_CR_TBEN_BIT;
					if(((I2cChStat[ch].cnt+1) >= I2cChStat[ch].arg.wr.size) && (true == I2cChStat[ch].arg.wr.stop)){
						set_bit |= AG903_I2C_CR_STOP_BIT;	/* Stop Condition */
					}
				}
				break;
			default:
				(*event) |= AG903_I2C_EVENT_WRITE_ERR;
				break;
		}
		if(0 == (*event)) {
			AG903_I2CPrmWriteData(ch, nextdata);
			AG903_I2CPrmClearControl(ch, (AG903_I2C_CR_START_BIT|AG903_I2C_CR_STOP_BIT));
			AG903_I2CPrmSetControl(ch, set_bit);	/* 次データWrite */
		}
	}
	
	if(0 != (*event)) {
		AG903_I2CPrmClearControl(ch, (AG903_I2C_CR_ALLINT_BIT|AG903_I2C_CR_ALLCTRL_BIT));
		I2cChStat[ch].stat = AG903_I2C_CH_IDLE;
	}

	return retval;
}

/*
	Master Read処理（割込み）.
	ch：I2Cチャネル番号（0〜1）.
	event：発生イベント.
*/
static int32_t I2CMgr_IntMasterRead(uint8_t ch, uint32_t* event)
{
	int32_t	 retval = AG903_ENONE;
	uint32_t status;
	
	(*event) = 0;

	if( (AG903_I2C_CH_NUM <= ch) ||
		(NULL == event) ) {
		return -AG903_EINVAL;
	}
	
	AG903_I2CPrmGetStatus(ch, &status);

	if(status&AG903_I2C_SR_AL_BIT) {	/* arbitration負け */
		(*event) |= AG903_I2C_EVENT_LOSES_ARBITRATION;
	}

	switch(I2cChStat[ch].sequence) {
		case AG903_I2C_SEQ_SND_SADDR_H:
			if(status&AG903_I2C_SR_BERR_BIT) {	/* Slave non-ACK */
				(*event) |= AG903_I2C_EVENT_SEQUENCE_ERR;
			}
			if((0 == (*event)) && (status&AG903_I2C_SR_DT_BIT)) {
				AG903_I2CPrmWriteData(ch, (uint8_t)I2cChStat[ch].arg.rd.addr);
				AG903_I2CPrmClearControl(ch, (AG903_I2C_CR_START_BIT|AG903_I2C_CR_STOP_BIT));
				AG903_I2CPrmSetControl(ch, AG903_I2C_CR_TBEN_BIT);
				I2cChStat[ch].sequence = AG903_I2C_SEQ_SND_SADDR_L;
			}
			break;
		case AG903_I2C_SEQ_SND_SADDR_L:
			if(status&AG903_I2C_SR_BERR_BIT) {	/* Slave non-ACK */
				(*event) |= AG903_I2C_EVENT_SEQUENCE_ERR;
			}
			if((0 == (*event)) && (status&AG903_I2C_SR_DT_BIT)) {
				AG903_I2CPrmClearControl(ch, (AG903_I2C_CR_START_BIT|AG903_I2C_CR_STOP_BIT));
				if(1 >= I2cChStat[ch].arg.rd.size) {
					AG903_I2CPrmSetControl(ch, (AG903_I2C_CR_TBEN_BIT|AG903_I2C_CR_ACKNACK_BIT|AG903_I2C_CR_STOP_BIT));
					I2cChStat[ch].sequence = AG903_I2C_SEQ_RCV_LAST;	/* Last */
				}
				else {
					AG903_I2CPrmSetControl(ch, AG903_I2C_CR_TBEN_BIT);
					I2cChStat[ch].sequence = AG903_I2C_SEQ_RCV;
				}
			}
			break;
		case AG903_I2C_SEQ_RCV:
			if((0 == (*event)) && (status&AG903_I2C_SR_DR_BIT)) {
				AG903_I2CPrmReadData(ch, (uint8_t*)(I2cChStat[ch].arg.rd.buf+I2cChStat[ch].cnt));
				I2cChStat[ch].cnt++;
				AG903_I2CPrmClearControl(ch, (AG903_I2C_CR_START_BIT|AG903_I2C_CR_STOP_BIT));
				if((I2cChStat[ch].arg.rd.size-1) <= I2cChStat[ch].cnt) {
					AG903_I2CPrmSetControl(ch, (AG903_I2C_CR_TBEN_BIT|AG903_I2C_CR_ACKNACK_BIT|AG903_I2C_CR_STOP_BIT));
					I2cChStat[ch].sequence = AG903_I2C_SEQ_RCV_LAST;	/* Last */
				}
				else {
					AG903_I2CPrmSetControl(ch, AG903_I2C_CR_TBEN_BIT);
					I2cChStat[ch].sequence = AG903_I2C_SEQ_RCV;
				}
			}
			break;
		case AG903_I2C_SEQ_RCV_LAST:
			if(0 == (status&AG903_I2C_SR_ACK_BIT)) {	/* ACK受信 */
				(*event) |= AG903_I2C_EVENT_SEQUENCE_ERR;
			}
			if((0 == (*event)) && (status&AG903_I2C_SR_DR_BIT)) {
				AG903_I2CPrmReadData(ch, (uint8_t*)(I2cChStat[ch].arg.rd.buf+I2cChStat[ch].cnt));
				I2cChStat[ch].cnt++;
				(*event) |= AG903_I2C_EVENT_READ_END;
			}
			break;
		default:
			(*event) |= AG903_I2C_EVENT_READ_ERR;
			break;
	}

	if(0 != (*event)) {
		AG903_I2CPrmClearControl(ch, (AG903_I2C_CR_ALLINT_BIT|AG903_I2C_CR_ALLCTRL_BIT));
		I2cChStat[ch].stat = AG903_I2C_CH_IDLE;
	}

	return retval;
}

/*
	Slave Write処理（割込み）.
	ch：I2Cチャネル番号（0〜1）.
	event：発生イベント.
*/
static int32_t I2CMgr_IntSlaveWrite(uint8_t ch, uint32_t* event)
{
	int32_t	 retval = AG903_ENONE;
	uint32_t status;
	
	(*event) = 0;

	if( (AG903_I2C_CH_NUM <= ch) ||
		(NULL == event) ) {
		return -AG903_EINVAL;
	}
	
	AG903_I2CPrmGetStatus(ch, &status);
	
	switch(I2cChStat[ch].sequence) {
		case AG903_I2C_SEQ_RCV_SADDR:
			if((status&AG903_I2C_SR_SAM_BIT) && (status&AG903_I2C_SR_DR_BIT) && (status&AG903_I2C_SR_I2CB_BIT)) {
				AG903_I2CPrmWriteData(ch, (uint8_t)(*(I2cChStat[ch].arg.wr.buf+I2cChStat[ch].cnt)));
				AG903_I2CPrmSetControl(ch, AG903_I2C_CR_TBEN_BIT);
				I2cChStat[ch].sequence = AG903_I2C_SEQ_SND;
			}
			break;
		case AG903_I2C_SEQ_SND:
			if(status&AG903_I2C_SR_DT_BIT) {
				I2cChStat[ch].cnt++;
				if(I2cChStat[ch].arg.wr.size <= I2cChStat[ch].cnt) {
					(*event) |= AG903_I2C_EVENT_WRITE_END;	/* Write完了 */
				}
				else {
					if((status&AG903_I2C_SR_ACK_BIT) || (status&AG903_I2C_SR_STOP_BIT)) {
						I2cChStat[ch].sequence = AG903_I2C_SEQ_RCV_SADDR;
					}
					else {
						AG903_I2CPrmWriteData(ch, (uint8_t)(*(I2cChStat[ch].arg.wr.buf+I2cChStat[ch].cnt)));
						AG903_I2CPrmSetControl(ch, AG903_I2C_CR_TBEN_BIT);
					}
				}
			}
			break;
		default:
			(*event) |= AG903_I2C_EVENT_WRITE_ERR;
			break;
	}
	
	if(0 != (*event)) {
		AG903_I2CPrmClearControl(ch, (AG903_I2C_CR_ALLINT_BIT|AG903_I2C_CR_ALLCTRL_BIT));
		I2cChStat[ch].stat = AG903_I2C_CH_IDLE;
	}

	return retval;
}

/*
	Slave Read処理（割込み）.
	ch：I2Cチャネル番号（0〜1）.
	event：発生イベント.
*/
static int32_t I2CMgr_IntSlaveRead(uint8_t ch, uint32_t* event)
{
	int32_t	 retval = AG903_ENONE;
	uint32_t status;
	
	(*event) = 0;

	if( (AG903_I2C_CH_NUM <= ch) ||
		(NULL == event) ) {
		return -AG903_EINVAL;
	}
	
	AG903_I2CPrmGetStatus(ch, &status);

	switch(I2cChStat[ch].sequence) {
		case AG903_I2C_SEQ_RCV_SADDR:
			if((status&AG903_I2C_SR_SAM_BIT) && (status&AG903_I2C_SR_DR_BIT) && (status&AG903_I2C_SR_I2CB_BIT)) {
				AG903_I2CPrmSetControl(ch, AG903_I2C_CR_TBEN_BIT);
				I2cChStat[ch].sequence = AG903_I2C_SEQ_RCV;
			}
			break;
		case AG903_I2C_SEQ_RCV:
			if (status&AG903_I2C_SR_DR_BIT) {
				AG903_I2CPrmReadData(ch, (uint8_t*)(I2cChStat[ch].arg.rd.buf+I2cChStat[ch].cnt));
				I2cChStat[ch].cnt++;
				if((I2cChStat[ch].arg.rd.size) <= I2cChStat[ch].cnt) {
					(*event) |= AG903_I2C_EVENT_READ_END;
				}
				if(status&AG903_I2C_SR_STOP_BIT) {
					I2cChStat[ch].sequence = AG903_I2C_SEQ_RCV_SADDR;
				}
				if((0==(*event)) && (AG903_I2C_SEQ_RCV==I2cChStat[ch].sequence)) {
					AG903_I2CPrmSetControl(ch, AG903_I2C_CR_TBEN_BIT);
				}
			}
			break;
		default:
			(*event) |= AG903_I2C_EVENT_WRITE_ERR;
			break;
	}
	
	if(0 != (*event)) {
		AG903_I2CPrmClearControl(ch, (AG903_I2C_CR_ALLINT_BIT|AG903_I2C_CR_ALLCTRL_BIT));
		I2cChStat[ch].stat = AG903_I2C_CH_IDLE;
	}

	return retval;
}
