/**
 * @brief           SSP Manager Header
 * @author          AXELL CORPORATION
 * @description     SSP Manager提供ヘッダ。<p>SSP Manager使用時にincludeして下さい。
 * @note            none
 * @history         2017_02_22  初版
 * @history         2017_10_26  Ver2.0
 * @history         2025_03_06  [SDK3.7] SSPライブラリにSPIモードでの送受信アクセス機能を追加 (#5662)
 * @history         2025_03_06  [SDK3.7] SSPライブラリにDMAによる送受信関数を追加 (#5780)
*/
/* DOM-IGNORE-BEGIN */
/*
 * This program was created by Axell Corporation.
 * Copyright (C) 2017-2025 Axell Corporation, all rights reserved.
 */

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

#include <stdint.h>
#include "lib_common/AG903_common.h"

#ifdef __cplusplus
extern "C" {
#endif

/** 送信キュー数 */
#define AG903_SSP_TXQUE_NUM			(8)

/** 受信キュー数 */
#define AG903_SSP_RXQUE_NUM			(8)

/** 送信FIFO Treshold */
#define AG903_SSP_TXFIFO_THRESHOLD	(8)

/** 受信FIFO Treshold */
#define AG903_SSP_RXFIFO_THRESHOLD	(1)

/** 極性 */
enum _AG903_SspPolarityType {
	AG903_SSP_POL_POSITIVE = 0,	/** 正論理 */
	AG903_SSP_POL_NEGATIVE,		/** 負論理 */
	AG903_SSP_POL_TYPENUM,		/** 極性定義数 */
};

/** MSB/LSB */
enum _AG903_SspFirstbitType {
	AG903_SSP_FIRSTBIT_MSB = 0,	/** MSB */
	AG903_SSP_FIRSTBIT_LSB,		/** LSB */
	AG903_SSP_FIRSTBIT_TYPENUM,	/** FIRSTBIT_TYPE定義数 */
};

/** SPIクロックモード */
enum _AG903_SspSpiClkMode {
	AG903_SSP_SPICLK_MODE0 = 0,	/** SCLKPO =0, SCLKPH =0 */
	AG903_SSP_SPICLK_MODE1,		/** SCLKPO =0, SCLKPH =1 */
	AG903_SSP_SPICLK_MODE2,		/** SCLKPO =1, SCLKPH =0 */
	AG903_SSP_SPICLK_MODE3,		/** SCLKPO =1, SCLKPH =1 */
	AG903_SSP_SPICLK_MODENUM,	/** SPIクロックモード数 */
};

/** パディングタイプ */
enum _AG903_SspJustifiedType {
	AG903_SSP_LEFT_JUSTIFIED = 0,	/** 左揃え（後パディング）*/
	AG903_SSP_RIGHT_JUSTIFIED,		/** 右揃え（前パディング）*/
	AG903_SSP_JUSTIFIED_TYPENUM,	/** パディングタイプ数 */
};

/** FS信号パルス幅（TDM用）*/
enum _AG903_SspI2sTdmFspw {
	AG903_SSP_I2STDM_FSPW_CYCLE = 0,	/** 1サイクル（単位：SCLK）*/
	AG903_SSP_I2STDM_FSPW_WORD,			/** 1ワード（先頭1スロット）*/
	AG903_SSP_I2STDM_FSPW_TYPENUM,		/** FS信号パルス幅（TDM用）定義数 */
};

/** イベント検出ビット （送信完了）*/
#define AG903_SSP_EVENT_SNDEND		(1<<0)

/** イベント検出ビット （受信完了）*/
#define AG903_SSP_EVENT_RCVEND		(1<<1)

/** イベント検出ビット （オーバーラン）*/
#define AG903_SSP_EVENT_OVERRUN		(1<<8)

/** イベント検出ビット （アンダーラン）*/
#define AG903_SSP_EVENT_UNDERRUN	(1<<9)

/** SSPハンドル */
typedef uint32_t	AG903_SSPMgrHandle;

/** コールバック関数の型。<p>
	handleはSSPハンドル、eventはイベント検出ビット(下表参照)。<p>
    <table>
    <tr><th>bit</th><th>内容</th></tr>
    <tr><td>31:10</td><td>reserve</td></tr>
    <tr><td>9</td><td>送信FIFOアンダーラン</td></tr>
    <tr><td>8</td><td>受信FIFOオーバーラン</td></tr>
    <tr><td>7:2</td><td>reserve</td></tr>
    <tr><td>1</td><td>受信完了</td></tr>
    <tr><td>0</td><td>送信完了</td></tr>
    </table> */
typedef void (*AG903_SSPMgrClbk)(AG903_SSPMgrHandle* handle, uint32_t event);

/** SSP設定パラメータ<p>
	clkdiv の最小値は「4」で奇数指定は不可です。またSlave動作時は設定無効です。<p>
	wordlen は伝送データのWord長をbit単位で設定します。<p>
	slave は true=Slave動作、false=Master動作 です。 */
typedef struct _AG903_SSPMgrSspParam{
	uint16_t  	clkdiv;			/** シリアルクロック分周率 */
	uint8_t	  	wordlen;		/** Word Length */
	uint8_t		slave;    		/** Slave動作設定 */
} AG903_SSPMgrSspParam;

/** SPI設定パラメータ<p>
	clkdiv の最小値は「2」で奇数指定は不可です。またSlave動作時は設定無効です。<p>
	wordlen は伝送データのWord長をbit単位で設定します。<p>
    polarity は右から指定します。 _AG903_SspPolarityType<p>
	firstbit は右から指定します。 _AG903_SspFirstbitType<p>
	sclktype は右から指定します。 _AG903_SspSpiClkMode<p>
	slave は true=Slave動作、false=Master動作 です。<p>
	flash は SPIフラッシュ特化モードでアクセスするとき1、その他のとき0です。<p>
 */
typedef struct _AG903_SSPMgrSpiParam{
	uint16_t  	clkdiv;			/** シリアルクロック分周率 */
	uint8_t	  	wordlen;		/** Word Length */
	uint8_t	  	polarity;		/** frame/sync 極性 */
	uint8_t	  	firstbit;		/** MSB first or LSB first */
	uint8_t	  	sclktype;		/** 0〜3 type */
	uint8_t		slave;			/** Slave動作設定 */
	uint8_t		flash;			/** SPIフラッシュ特化モード */
} AG903_SSPMgrSpiParam; 

/** I2S設定パラメータ<p>
	clkdiv の最小値は「4」で奇数指定は不可です。またSlave動作時は設定無効です。<p>
	wordlen は伝送データのWord長をbit単位で設定します。<p>
	mono は true=mono動作、false=stereo動作 です。<p>
    polarity は右から指定します。 _AG903_SspPolarityType<p>
	firstbit は右から指定します。 _AG903_SspFirstbitType<p>
	padlen は0埋めのPaddingサイズを指定します。<p>
	justified は右から指定します。 _AG903_SspJustifiedType<p>
	slave は true=Slave動作、false=Master動作 です。 */
typedef struct _AG903_SSPMgrI2sParam{
	uint16_t  	clkdiv;			/** SCLK = SSPCLK/ clkdiv */
	uint8_t	  	wordlen;		/** Word Length */
	uint8_t	  	mono;			/** stereo or mono */
	uint8_t	  	polarity;		/** LRCLK極性 */
	uint8_t	  	firstbit;		/** MSB first or LSB first */
	uint8_t	  	padlen;			/** Padding Length */
	uint8_t	  	justified;		/** 左揃え or 右揃え */
    uint8_t	  	slave;			/** Slave動作設定 */
	uint8_t	  	reserve[3];		/** 予約 */
} AG903_SSPMgrI2sParam;

/** S/PDIF設定パラメータ<p>
	datalen はオーディオデータ長を設定します。設定可能な値は、16,20,24です。<p>
	validity は true=オーディオデータ有効、false=オーディオデータ無効 です。 */
typedef struct _AG903_SSPMgrSpdifParam{
	uint8_t	 	datalen;		/** Audio Data Length */
	uint8_t	 	validity;		/** D/A or NOT */
	uint8_t	 	reserve[2];		/** 予約 */
} AG903_SSPMgrSpdifParam;

/** S/PDIF Cビット */
typedef struct _AG903_SSPMgrSpdifCbit{
	uint8_t	 status[5];			/** Channel Status Byte 0〜4 */
	uint8_t	 reserve[3];		/** 予約 */
} AG903_SSPMgrSpdifCbit;

/** S/PDIF Uビット */
typedef struct _AG903_SSPMgrSpdifUbit{
	uint32_t  userbit[12];		/** User bit 0〜383 */
} AG903_SSPMgrSpdifUbit;

/** キュー状態 */
typedef struct _AG903_SSPMgrQueStatus{
	uint32_t	txremain;		/** 実行キュー送信残サイズ[byte] */
	uint32_t	received;		/** 実行キュー受信済サイズ[byte] */
	uint32_t	txquecnt;		/** 送信キューイング数 */
	uint32_t	rxquecnt;		/** 受信キューイング数 */
} AG903_SSPMgrQueStatus;

/** ステータス<p>
    SSPnSSPStatus の内容になります。詳細は『AX51903仕様書』を参照して下さい。*/
typedef struct _AG903_SSPMgrStatus{
	uint8_t		txfifo_num;		/** 送信FIFOエントリ数 */
	uint8_t		rxfifo_num;		/** 受信FIFOエントリ数 */
	uint8_t		busy;			/** Busy [true=Busy] */
	uint8_t		txfifo_notfull; /** 送信FIFO Not Full [true=Not Full] */
	uint8_t		rxfifo_full;	/** 受信FIFO Full [true=Full] */
	uint8_t		reserve[3];		/** 予約 */
} AG903_SSPMgrStatus;


int32_t	AG903_SSPMgrInit(uint8_t ch);
int32_t	AG903_SSPMgrGetHandle(uint8_t ch, AG903_SSPMgrHandle** handle);
int32_t	AG903_SSPMgrReleaseHandle(AG903_SSPMgrHandle* handle);
int32_t	AG903_SSPMgrSetCallback(AG903_SSPMgrHandle* handle, AG903_SSPMgrClbk clbk);
int32_t	AG903_SSPMgrSetSspMode(AG903_SSPMgrHandle* handle, AG903_SSPMgrSspParam* param);
int32_t	AG903_SSPMgrSetSpiMode(AG903_SSPMgrHandle* handle, AG903_SSPMgrSpiParam* param);
int32_t	AG903_SSPMgrSetI2sMode(AG903_SSPMgrHandle* handle, AG903_SSPMgrI2sParam* param);
int32_t	AG903_SSPMgrSetSpdifMode(AG903_SSPMgrHandle* handle, AG903_SSPMgrSpdifParam* param);
int32_t	AG903_SSPMgrSetSpdifCbit(AG903_SSPMgrHandle* handle, AG903_SSPMgrSpdifCbit* cbit);
int32_t	AG903_SSPMgrSetSpdifUbit(AG903_SSPMgrHandle* handle, uint8_t offset, uint32_t ubit);
int32_t	AG903_SSPMgrSetSpdifUbitALL(AG903_SSPMgrHandle* handle, AG903_SSPMgrSpdifUbit* ubit);
int32_t	AG903_SSPMgrSetSendBuf(AG903_SSPMgrHandle* handle, uint8_t* buf, uint32_t size);
int32_t	AG903_SSPMgrSetReceiveBuf(AG903_SSPMgrHandle* handle, uint8_t* buf, uint32_t size);
int32_t	AG903_SSPMgrEnableDmaMode(AG903_SSPMgrHandle* handle, uint8_t mode);
int32_t	AG903_SSPMgrDisableDmaMode(AG903_SSPMgrHandle* handle);
int32_t	AG903_SSPMgrEnableTransfer(AG903_SSPMgrHandle* handle);
int32_t	AG903_SSPMgrDisableTransfer(AG903_SSPMgrHandle* handle);

int32_t AG903_SSPMgrSpiSend(AG903_SSPMgrHandle* handle, const void* buf, uint32_t num);
int32_t AG903_SSPMgrSpiReceive(AG903_SSPMgrHandle* handle, void* buf, uint32_t num);
int32_t AG903_SSPMgrSpiSendReceive(AG903_SSPMgrHandle* handle, const void* tx_buf, uint32_t tx_num, void *rx_buf, uint32_t rx_num);
int32_t AG903_SSPMgrSpiSendDma(AG903_SSPMgrHandle* handle, const void* buf, uint32_t num);
int32_t AG903_SSPMgrSpiReceiveDma(AG903_SSPMgrHandle* handle, void* buf, uint32_t num);
int32_t AG903_SSPMgrSpiSendReceiveDma(AG903_SSPMgrHandle* handle, const void* tx_buf, uint32_t tx_num, void *rx_buf, uint32_t rx_num);
int32_t AG903_SSPMgrSpiEnableTransfer(AG903_SSPMgrHandle* handle);
int32_t AG903_SSPMgrSpiDisableTransfer(AG903_SSPMgrHandle* handle);

int32_t AG903_SSPMgrAttachTxDma(AG903_SSPMgrHandle* handle, uint8_t dma_ch, uint8_t dma_if);
int32_t AG903_SSPMgrAttachRxDma(AG903_SSPMgrHandle* handle, uint8_t dma_ch, uint8_t dma_if);
int32_t AG903_SSPMgrDetachTxDma(AG903_SSPMgrHandle* handle);
int32_t AG903_SSPMgrDetachRxDma(AG903_SSPMgrHandle* handle);
int32_t AG903_SSPMgrSetTxDmaBeat(AG903_SSPMgrHandle* handle, uint8_t beat);
int32_t AG903_SSPMgrSetRxDmaBeat(AG903_SSPMgrHandle* handle, uint8_t beat);
int32_t AG903_SSPMgrSendDma(AG903_SSPMgrHandle* handle, const uint8_t* buf, uint32_t size);
int32_t AG903_SSPMgrReceiveDma(AG903_SSPMgrHandle* handle, uint8_t* buf, uint32_t size);

int32_t	AG903_SSPMgrGetStatus(AG903_SSPMgrHandle* handle, AG903_SSPMgrStatus* status);
int32_t	AG903_SSPMgrClearTxQue(AG903_SSPMgrHandle* handle);
int32_t	AG903_SSPMgrClearRxQue(AG903_SSPMgrHandle* handle);
int32_t	AG903_SSPMgrGetQueStatus(AG903_SSPMgrHandle* handle, AG903_SSPMgrQueStatus* status);
int32_t	AG903_SSPMgrClearTxFifo(AG903_SSPMgrHandle* handle);
int32_t	AG903_SSPMgrClearRxFifo(AG903_SSPMgrHandle* handle);
int32_t AG903_SSPMgrSetTxFifoThreshold(AG903_SSPMgrHandle* handle, uint8_t threshold);
int32_t AG903_SSPMgrSetRxFifoThreshold(AG903_SSPMgrHandle* handle, uint8_t threshold);	
int32_t	AG903_SSPMgrReset(AG903_SSPMgrHandle* handle);

#ifdef __cplusplus
}
#endif
#endif /* _SSPMGR_H_ */
