/**
 * @brief           DMAC Manager Header
 * @author          AXELL CORPORATION
 * @description     DMAC Manager提供ヘッダ。<p>DMAC Manager使用時にincludeして下さい。
 * @note            none
 * @history         2017_02_22  初版
 * @history         2017_05_09  [#1319]DMACMgrの一部APIがDoc_o_maticに正しく反映されない 
 * @history         2017_10_26  Ver2.0
 * @history         2025_03_06  [SDK3.7] DMACに割り込みコールバックバックを解除する関数を追加 (#5756)
 *  
*/
/* DOM-IGNORE-BEGIN */
/*
 * This program was created by Axell Corporation.
 * Copyright (C) 2017-2025 Axell Corporation, all rights reserved.
 */

#ifndef _DMACMGR_H_
#define _DMACMGR_H_
/* DOM-IGNORE-END */

#ifdef __cplusplus
extern "C" {
#endif

/** ディスクリプタのMaxリンク数 */
#define AG903_DMAC_DESC_LINK_MAX 	(16)

/** ローカルディスクリプタ Maxエントリ数 */
#define AG903_DMAC_LDD_ENTRY_NUM 	(32)

/** リモートディスクリプタ Maxエントリ数(変更可) */
#define AG903_DMAC_RDD_ENTRY_NUM 	(16)

/** ディスクリプタサイズ [バイト] */
#define AG903_DMAC_DESC_SIZE		(32)

/** TERM割込みステータスビット */
#define AG903_DMAC_INTSTS_TERM		(1<<0)

/** ABORT割込みステータスビット */
#define AG903_DMAC_INTSTS_ABORT		(1<<1)

/** WDT割込みステータスビット */
#define AG903_DMAC_INTSTS_WDT		(1<<2)

/** ERROR割込みステータスビット */
#define AG903_DMAC_INTSTS_ERROR		(1<<3)

/** DMACハンドル */
typedef uint32_t	AG903_DMACMgrHandle;

/** DMAC状態情報 */
typedef struct _AG903_DMACMgrStatus
{
	uint8_t enable;		/** Enable状態 */
	uint8_t reserve[3]; /** (削除可) */
} AG903_DMACMgrStatus;

/** ディスクリプタ型 */
typedef struct _AG903_DMACMgrDesc
{
	uint32_t SrcAddr;	/** 転送元アドレス */
	uint32_t DstAddr;	/** 転送先アドレス */

	void *next;		/** 次ディスクリプタのポインタ */ 

	/** Controlレジスタ */
	union
	{
		/** DMACnCTRL_REG レジスタのビット定義 */
		struct {
			unsigned int ChWEvent : 8; /** [7:0] チャンネルのイベント待機 */
			unsigned int WSync    : 1; /** [8] 最後の書き込み完了の待機 */
			unsigned int ChSEvent : 3; /** [11:9] チャンネルのイベント */
			unsigned int SEventEn : 1; /** [12] イベント設定 */
			unsigned int WEventEn : 1; /** [13] イベント待機 */
			unsigned int SDEn     : 1; /** [14] 2D転送 */
			unsigned int ExpEn    : 1; /** [15] 拡張制御 */
			unsigned int ChEn     : 1; /** [16] チャンネル */
			unsigned int WDTEn    : 1; /** [17] ウォッチドッグタイマ */
			unsigned int DstCtrl  : 2; /** [19:18] 転送先バーストタイプの制御方法 */
			unsigned int SrcCtrl  : 2; /** [21:20] 転送元バーストタイプの制御方法 */
			unsigned int DstWidth : 3; /** [24:22] 転送先のデータ幅 */
			unsigned int SrcWidth : 3; /** [27:25] 転送元のデータ幅 */
			unsigned int TCMsk    : 1; /** [28] ターミナルカウントのマスク */
			unsigned int SrcTcnt  : 3; /** [31:29] 1つのDMAハンドシェイク動作の転送元転送カウント単位 */
		} /*__attribute__((packed))*/ st;

		uint32_t val; /** DMACnCTRL_REG レジスタ */
	} Ctrl;

	/** Transfer Size */
	union
	{
		/** DMACnTRNS_SIZE_1D レジスタ */
		struct {
			unsigned int TCnt : 22; /** [21:0] 現在のディスクリプタの転送カウント */
			unsigned int      : 10;
		} /*__attribute__((packed))*/ d1;

		/** DMACnTRNS_SIZE_2D レジスタ */
		struct {
			unsigned int XTCnt : 16; /** [15:0] 現在のディスクリプタでX方向の転送カウント */
			unsigned int YTCnt : 16; /** [31:16] 現在のディスクリプタでY方向の転送カウント */
		} /*__attribute__((packed))*/ d2;

		uint32_t val; /** DMACnTRNS_SIZE_xD レジスタ */
	} Trns;
	
	/** SrcDst Stride */
	union
	{
		/** DMACnSTRIDE_SRC_DST_ADDR レジスタのビット定義 */
		struct {
			unsigned int SrcStride : 16; /** [15:0] 転送元ストライド値 */
			unsigned int DstStride : 16; /** [31:16] 転送先ストライド値 */
		} /*__attribute__((packed))*/ st;

		uint32_t val; /** DMACnSTRIDE_SRC_DST_ADDR レジスタ */
	} Stride;

} AG903_DMACMgrDesc;

/** Configuration型 */
typedef union _AG903_DMACMgrConfig
{
	/** DMACnCFG_REG レジスタのビット定義 */
	struct {
		unsigned int TCIntMsk    : 1; /** [0] ターミナルカウント割り込みマスク */
		unsigned int ErrIntMsk   : 1; /** [1] チャンネルエラー割り込みマスク */
		unsigned int AbtIntMsk   : 1; /** [2] チャンネルアボート割り込みマスク */
		unsigned int SrcRS       : 4; /** [6:3] 転送元ハンドシェイク要求のソース */
		unsigned int SrcHEn      : 1; /** [7] 転送元ハンドシェイク */
		unsigned int             : 1;
		unsigned int DstRS       : 4; /** [12:9] 転送先ハンドシェイク要求のソース */
		unsigned int DstHEn      : 1; /** [13] 転送先ハンドシェイク */
		unsigned int             : 2;
		unsigned int LLPCnt      : 4; /** [19:16] リンクリストポインタ増分カウンタ */
		unsigned int ChGntWin    : 8; /** [27:20] チャンネルアービトレーション許可ウィンドウのコマンド */
		unsigned int ChPri       : 1; /** [28] チャンネルアービトレーション優先順位 */
		unsigned int             : 1;
		unsigned int WOMode      : 1; /** [30] 書き込み専用モード */
		unsigned int UnalignMode : 1; /** [31] 非アライン転送モード */
	} /*__attribute__((packed))*/ st;
	uint32_t val; /** DMACnCFG_REG レジスタ */

} AG903_DMACMgrConfig;



int32_t AG903_DMACMgrGetHandle(int ch, AG903_DMACMgrHandle **handle);
int32_t AG903_DMACMgrReleaseHandle(AG903_DMACMgrHandle *handle);
int32_t AG903_DMACMgrGetIntStatus(AG903_DMACMgrHandle *handle, uint32_t *status);
int32_t AG903_DMACMgrClearInt(AG903_DMACMgrHandle *handle, uint32_t clrbit);
int32_t AG903_DMACMgrSetIntCallback(AG903_DMACMgrHandle *handle,
 void (*cb_term)(AG903_DMACMgrHandle*, AG903_DMACMgrDesc**, uint8_t*),
 void (*cb_abt)(AG903_DMACMgrHandle*),
 void (*cb_error)(AG903_DMACMgrHandle*));
int32_t AG903_DMACMgrUnsetIntCallback(AG903_DMACMgrHandle *handle);
int32_t AG903_DMACMgrEnable(AG903_DMACMgrHandle *handle);
int32_t AG903_DMACMgrAbort(AG903_DMACMgrHandle *handle);
int32_t AG903_DMACMgrSetSyncPeripheral(int port, int val);
int32_t AG903_DMACMgrSetWatchdog(int val);
int32_t AG903_DMACMgrSetConstantValue(uint32_t val);
int32_t AG903_DMACMgrSetEvent(int id);
int32_t AG903_DMACMgrClearEvent(int id);
int32_t AG903_DMACMgrGetEvent(int id, uint8_t *val);
int32_t AG903_DMACMgrSetSimpleTrnsDesc(AG903_DMACMgrHandle *handle, void *from, uint32_t from_size, void *to);
int32_t AG903_DMACMgrSetDescList(AG903_DMACMgrHandle *handle, AG903_DMACMgrConfig *config, AG903_DMACMgrDesc *desc_list, int list_num);
int32_t AG903_DMACMgrRemoveDescList(AG903_DMACMgrHandle *handle);
int32_t AG903_DMACMgrSetRemoteDescAddr(void *addr);
int32_t AG903_DMACMgrClearRemoteDescAddr(void);
int32_t AG903_DMACMgrGetStatus(AG903_DMACMgrHandle *handle, AG903_DMACMgrStatus *status);

#ifdef __cplusplus
}
#endif
#endif
