/*
 *	clipdirs.h
 *
 *	演出シーケンサ
 *
 *	CLiP - Common Library for P/ECE
 *	Copyright (C) 2015 Naoyuki Sawa
 *
 *	* Sun Feb 08 19:01:54 JST 2015 Naoyuki Sawa
 *	- 1st リリース。
 *	* Thu Apr 23 21:42:53 JST 2015 Naoyuki Sawa
 *	- DirSeq_Stop(),DirSeqCh_Stop()を追加しました。
 *	  演出テーブルをクリアせずに、現在実行中の演出シーケンスを停止したい場合に使用します。
 *	  例えば、'あるトリガ'から??秒後に'ある表示'を行うような演出シーケンスを開始した後に、何らかの条件でその予約を取り消す場合等です。
 *	* Tue May 05 17:15:43 JST 2015 Naoyuki Sawa
 *	- DirSeqCh_SetTblNo()を追加しました。
 */
#ifndef __CLIP_DIRS_H__
#define __CLIP_DIRS_H__
/****************************************************************************
 *	
 ****************************************************************************/
//□命令仕様
//
//	#--- 疑似命令 ---
//	[def] ﾗﾍﾞﾙ名
//	#--- 共通命令 ---
//	end							#00000000
//	#--- 演出ｼｰｹﾝｽ命令 ---
//	repeat							#00000001 11111111							┐
//	repeat 繰り返し回数					#00000001 uuuuuuuu							┴u:繰返し回数		0=不可(ｴﾗｰ停止),1~254=繰返し回数,255=無限｡
//	wait   待ち時間						#00000010 uuuuuuuu uuuuuuuu						─u:待ち時間		0=不可(ｴﾗｰ停止),1~65535=待ち時間｡
//	call   相対位置						#00000011 ssssssss ssssssss ssssssss					─s:相対位置		次の命令の位置を基準とする｡
//	act    演出番号						#00000100 uuuuuuuu uuuuuuuu uuuuuuuu					┬u:演出番号		ｱﾌﾟﾘｹｰｼｮﾝ定義の任意の24ﾋﾞｯﾄ値｡
//	act    演出番号 flush					#00000101 uuuuuuuu uuuuuuuu uuuuuuuu					┘
//	#--- 演出ﾃｰﾌﾞﾙ命令 ---
//	on ﾄﾘｶﾞ番号        [goto] ﾗﾍﾞﾙ名               		#00000110 uuuuuuuu ssssssss ssssssss ssssssss 00000000 00000000		┐u=ﾄﾘｶﾞ番号		0~255=ﾄﾘｶﾞ番号｡0は'set',255は'clr'でも可｡
//	on ﾄﾘｶﾞ番号        [goto] ﾗﾍﾞﾙ名 [lock] ﾛｯｸ時間		#00000110 uuuuuuuu ssssssss ssssssss ssssssss vvvvvvvv vvvvvvvv		┼s=相対位置		次の命令の位置を基準とする｡
//	on ﾄﾘｶﾞ番号 unlock [goto] ﾗﾍﾞﾙ名               		#00000111 uuuuuuuu ssssssss ssssssss ssssssss 00000000 00000000		┤v=ﾛｯｸ時間		0=ﾛｯｸしない,1~65535=ﾛｯｸ時間｡
//	on ﾄﾘｶﾞ番号 unlock [goto] ﾗﾍﾞﾙ名 [lock] ﾛｯｸ時間		#00000111 uuuuuuuu ssssssss ssssssss ssssssss vvvvvvvv vvvvvvvv		┘
//
/*--------------------------------------------------------------------------*/
//□命令コード定義用マクロ
#define DirSeq_Inst_end()			0x00
#define DirSeq_Inst_repeat(u)			0x01,((uint8_t)(u))
#define DirSeq_Inst_wait(u)			0x02,((uint8_t)(u)),((uint8_t)((u)>>8))
#define DirSeq_Inst_call(s)			0x03,((uint8_t)(s)),((uint8_t)((s)>>8)),((uint8_t)((s)>>16))
#define DirSeq_Inst_act(u)			0x04,((uint8_t)(u)),((uint8_t)((u)>>8)),((uint8_t)((u)>>16))
#define DirSeq_Inst_act_flush(u)		0x05,((uint8_t)(u)),((uint8_t)((u)>>8)),((uint8_t)((u)>>16))
#define DirSeq_Inst_on_lock(            u,  v)	0x06,DirSeq_Inst_on_goto_lock(       u,0,v)
#define DirSeq_Inst_on_goto(            u,s  )	0x06,DirSeq_Inst_on_goto_lock(       u,s,0)
#define DirSeq_Inst_on_goto_lock(       u,s,v)	0x06,((uint8_t)(u)),((uint8_t)(s)),((uint8_t)((s)>>8)),((uint8_t)((s)>>16)),((uint8_t)(v)),((uint8_t)((v)>>8))
#define DirSeq_Inst_on_unlock(          u    )	0x07,DirSeq_Inst_on_unlock_goto_lock(u,0,0)
#define DirSeq_Inst_on_unlock_lock(     u,  v)	0x07,DirSeq_Inst_on_unlock_goto_lock(u,0,v)
#define DirSeq_Inst_on_unlock_goto(     u,s  )	0x07,DirSeq_Inst_on_unlock_goto_lock(u,s,0)
#define DirSeq_Inst_on_unlock_goto_lock(u,s,v)	0x07,((uint8_t)(u)),((uint8_t)(s)),((uint8_t)((s)>>8)),((uint8_t)((s)>>16)),((uint8_t)(v)),((uint8_t)((v)>>8))
/*--------------------------------------------------------------------------*/
#define DirSeqCh_LockBufSize	  3	//ロックバッファサイズ		1〜   で調整可		調整可ではあるがアプリケーション毎に調整する事は想定していない。変更する場合はライブラリをリビルドせよ。
#define DirSeqCh_StackSize	  3	//スタッサイズ			1〜255で調整可		調整可ではあるがアプリケーション毎に調整する事は想定していない。変更する場合はライブラリをリビルドせよ。
//演出シーケンサチャネル
typedef struct _ST_DirSeqCh {
	const uint8_t*		pDirTbl;				//+ 0, 4 現在設定されている演出テーブル			NULL=無し
	const uint8_t*		pDirSeq;				//+ 4, 4 演出シーケンスの次に実行する命令位置		NULL=停止中
	uint16_t		WaitCnt;				//+ 8, 2 残り待ち時間
	//--- ロック ---
	uint16_t		LockCnt;				//+10, 2 残りロック時間
	const uint8_t*		TBL_LockBuf[DirSeqCh_LockBufSize];	//+12,12 ロック終了を待っている演出シーケンス		NULL要素で終端		'on'命令の3バイト目を指す
	//--- スタック ---
	uint8_t			StackLev;				//+24, 1 スタックレベル
	uint8_t			TBL_StackRep[DirSeqCh_StackSize];	//+25, 3 0=Callスタック,1〜254=Repeatスタックの残り繰返し回数,255=Repeatスタック(無限)
	const uint8_t*		TBL_StackRet[DirSeqCh_StackSize];	//+28,12 戻り先の命令位置							call,又は,repeatの次の命令を指す
} ST_DirSeqCh;								//=40
/*--------------------------------------------------------------------------*/
#ifndef DirSeqCh_Max
#define DirSeqCh_Max		  3	//演出シーケンサチャネル番号の最大値(この値も含む)	当モジュールをアプリケーションに含めてビルドする場合はDirSeqCh_Maxをアプリケーション側で定義可能。
#endif//DirSeqCh_Max
#define DirSeq_ActBufSize	256	//演出番号バッファサイズ	1〜65535で調整可	調整可ではあるがアプリケーション毎に調整する事は想定していない。変更する場合はライブラリをリビルドせよ。
//演出シーケンサ
typedef struct _ST_DirSeq {
	void			(*fnAct)(int ActNo);			//+ 0, 4 演出実行関数へのポインタ
	uint8_t			(*pActBuf/*[DirSeq_ActBufSize]*/)[3];	//+ 4, 4 演出番号バッファへのポインタ			_DirSeq_SetActBuf()にてスタック上に確保したバッファのポインタをバッファが有効な期間中のみST_DirSeq.pActBufに設定する。充分なサイズ,かつ,スタックが溢れないようにDirSeq_ActBufSizeを調整せよ。
	uint16_t		ActBufCnt;				//+ 8, 2 演出番号バッファの格納数
	uint16_t		ActBufPos;				//+10, 2 演出番号バッファの読出し位置
	ST_DirSeqCh		TBL_DirSeqCh[(DirSeqCh_Max+1)];		//+12,40*(DirSeqCh_Max+1)
} ST_DirSeq;								//=12+40*(DirSeqCh_Max+1)
/****************************************************************************
 *	
 ****************************************************************************/
//演出シーケンサを初期化する。
void DirSeq_Init(void (*fnAct)(int ActNo/*[31]=オーバーフロー,[30:24]=未定義,[23:0]=演出番号*/));
//演出シーケンサを実行する。
void DirSeq_Exec();
//演出テーブルを設定,又は,クリアする。
void DirSeq_ClrTbl();
void DirSeqCh_SetTbl(int iCh, const uint8_t* pDirTbl/*NULL=クリア*/);
//トリガを送信する。
void DirSeq_SendTrig(int iTrig);
void DirSeqCh_SendTrig(int iCh, int iTrig);
//ロックを解除する。
void DirSeq_Unlock();
void DirSeqCh_Unlock(int iCh);
//演出シーケンスを停止する。
void DirSeq_Stop();
void DirSeqCh_Stop(int iCh);
/****************************************************************************
 *	dDirSeqC.exeが出力したバイナリ形式を扱うためのユーティリティ関数
 ****************************************************************************/
#define USE_DIRSEQ_BIN	//ユーティリティ関数が不要ならばこのシンボル定義をコメントアウトしてください。
#ifdef  USE_DIRSEQ_BIN
void DirSeqCh_SetTblNo(int iCh, const void* pDirSeqBin, int iDirTblNo);
#endif//USE_DIRSEQ_BIN
#endif//__CLIP_DIRS_H__
