
'
'  Trust Design LLC : SECS/HSMS Communication library
' 
'  (c) Copyright Trust Design LLC.  2010-2021.  All rights reserved.
'


' ==============================================================================
' 
'  VBIo : Test and sample program
' 
'    Construct a message in AP and simply send and receive SECS messages.
'
'    (Note) In this sample, when making an HSMS connection, it is assumed that
'	the HOST side executes Passive connection and the EQUIP side executes
'	Active connection.
' 
' 
'  Starting method
' 
'    VBIo {h|e} [option]
'    ~~~~~~~~~~~~~~~~~~~
'    h    : Refer to [HOST]  section of Sample.ini to determine operation
'    e    : Refer to [EQUIP] section of Sample.ini to determine operation
'
'    option : Options for setting the details of operation (optional)
'	      Specify as a decimal number or as a hexadecimal number with 0x or
'	      x as a prefix.
'	      The details of the specified value for each bit are shown below.
'    F		 54 3210
'   +----+----+----+----+
'    |		 || |||+-- Function to use
'    |		 || |||    =0: _TDSCommXxxxx()		1:_TDSUDrvXxxx()
'    |		 || ||+--- SECS Header Byte order
'    |		 || ||	   =0: System order		1: Network order
'    |		 || |+---- Format for displaying messages in SECS list format
'    |		 || |	   =0: TDS Format		1: SML Format
'    |		 || +----- Whether to use MssgNextL() for SECS message display
'    |		 ||	   =0: Not use			1: Use
'    |		 |+------- Whether to use the SECS message definition file
'    |		 |	   =0: Not use			1: Use
'    |		 +-------- Whether to execute SECS message reception in a
'    |			   dedicated thread
'    |			   =0: No			1: Yes
'    +-------------------- Synchronize the connection status with communication
'			   control processing thread
'			   =0: No			1: Yes
'
'    Normally, "VBIo h" and "VBIo e" both operate on same machine or
'    different machines to communicate with each other. The communication
'    partner may be BasicIo.exe or Callbackio.exe.
'
'    After startup, refer to the menu display, enter request code etc. and the
'    function is executed.
' 
'    When host starts up, it waits for a connection from equipment.
'    When device side is started, connection request and Select request are
'    automatically issued to host side.
'    On host side, repeat '1:Recv' processing, and confirm that display is
'    'STATUS=951: No data'. After that, exchange any message. On receiving side,
'    do not forget to reap received data until 'STATUS=951'.
'
'    The transaction ID used when transmitting secondary message uses that of
'    primary message received immediately before.
'
'    This sample omits some of abnormal processing.
'
'    "SECS_MODE" defined below is defined to determine whether or not connection
'    processing to Passive side in case of Active connection is performed when
'    using _TDSCommXxxx() as processing function.
'    (Note) Changing this value alone does not make TDS aware of the change in
'       SECS1 or HSMS.  TDS determines SECS1 or HSMS based on the setting of
'       SECSMODE in the configuration file (.ini).  To change this value, you
'       must change the setting of SECSMODE in .ini.
'
'    If the second parameter (option) at startup is not specified, the details
'    of operation are determined by the following constants.
'
'    "FUNC_TYPE" is defined to select type of processing function to be used.
'    If you use _TDSUDrvXxxx(), there is no need to perform connection
'    processing for HSMS-SS Active connection, so there is no need to set
'    "SECS_MODE" in principle.
'    Since TDS switches SECS-1 connection or HSMS-SS connection in setting file
'    (.ini), user AP does not need to know connection method (SECS-1or HSMS and
'    Passive/Active at HSMS) as long as _TDSUDrvXxxx() is used as processing
'    function.
'
'    By changing values of "MSSG_USE_FILE" and "MSSG_DISP_TYPE" defined below,
'    you can change output format of SECS message displayed by this AP.
'    By changing value of "MSSG_USE_NEXTL", it is possible to change whether to
'    acquire field values as data or display list format when analyzing message
'    contents.
'    If "HEADER_BO" is set to 1, Byte Order of SECS message header obtained at
'    the time of Receive and Send can be obtained as the original network Byte
'    Order of the SECS message.
'    Similarly, when "USE_RECVTHREAD" is set to =1, a thread for performing
'    receiving process is activated, and display of received message and output
'    of the secondary message are automatically performed in the thread.
'    When using the receiving thread, keep in mind that prompt message may be
'    distorted.
' 
'
' ==============================================================================
' 
'  VBIo : テスト 及び サンプル・プログラム
' 
'    ＡＰ内でメッセージを構築し、単純に SECS メッセージの送受信を行う。
'
'    (注) 本サンプルでは HSMS 接続する場合、HOST 側が Passive 接続、EQUIP 側が
'       Active 接続を実行すると仮定している。
' 
' 
'  起動方法
' 
'    VBIo {h|e} [option]
'    ~~~~~~~~~~~~~~~~~~~
'    h    : Sample.ini の [HOST]  セクションを参照し動作を決定する
'    e    : Sample.ini の [EQUIP]      :              :
' 
'   option : 動作の詳細を設定するオプション (省略可能)
'	      10進数 もしくは 接頭文字として 0x もしくは x を付与した 16進数
'	      で指定する。
'	      以下に指定値のビット毎の詳細を以下に示す。
'    F		 54 3210
'   +----+----+----+----+
'    |		 || |||+-- 使用する関数
'    |		 || |||    =0: _TDSCommXxxxx()		1:_TDSUDrvXxxx()
'    |		 || ||+--- SECS Header Byte order
'    |		 || ||	   =0: System order		1: Network order
'    |		 || |+---- SECS リスト形式でメッセージを表示する場合の形式
'    |		 || |	   =0: TDS 形式			1: SML 形式
'    |		 || +----- SECS メッセージ表示に MssgNextL() を使用するか否か
'    |		 ||	   =0: 使用しない		1: 使用する
'    |		 |+------- SECS メッセージ定義ファイル使用の有無
'    |		 |	   =0: 使用しない		1: 使用する
'    |		 +-------- SECS メッセージ受信を専用スレッドで実行するか否か
'    |			   =0: No			1: Yes
'    +-------------------- 接続状態を通信制御部に同期する
'			   =0: No			1: Yes
' 
'    通常、VBIo h 及び VBIo e の両方を、同一マシン、もしくは異なるマシン上で
'    動作させて、相互通信を行う。通信相手は、BasicIo.exe、Callbackio.exe でも
'    よい。
' 
'    起動後、メニュ表示を参照し、要求コード等を入力し、機能を実行する。
'  
'    ホスト側は起動すると、装置側からの接続を待つ。装置側を起動すると、自動的
'    にホスト側に接続要求、Select 要求を発行する。ホスト側では、1:Recv 処理を
'    繰り返し行い、表示が「STATUS=951 : No data」となるのを確認する。その後、
'    任意のメッセージのやりとりを行う。受信側では、受信データの刈り取りを「
'    STATUS=951」になるまで行うことを忘れぬこと。
' 
'    ２次メッセージを送信する際のトランザクションＩＤは、直前に受信した１次
'    メッセージのものを使用する。
' 
'    本サンプルは、異常時処理を一部省略している。
'
'    以下で定義する "SECS_MODE" は、処理関数として _TDSCommXxxx() を使用する
'    場合で Active 接続の場合の Passive 側への接続処理の実行の有無を判断する
'    ために定義する。
'    (注) この値の変更だけで TDS が SECS1 or HSMS の変更を認識するわけではない。 
'       TDS は SECS1 or HSMS を判断するのは設定ファイル (.ini) の SECSMODE の
'       設定によるので、この値を変更する場合は ,ini の SECSMODE の設定変更を
'       しなければならない。
'
'    起動時の2番目のパラメータ (option) を指定しない場合は、以下の定数により
'    動作の詳細を決定する。
'
'    "FUNC_TYPE" は、使用する処理関数の種別を選択するために定義する。
'    _TDSUDrvXxxx() を使用する場合は、HSMS-SS Active 接続の場合の接続処理を行う
'    必要がないので、本来であれば "SECS_MODE" の設定も必要がない。
'    TDS は、SECS-1 接続 or HSMS-SS 接続の切替は、設定ファイル (.ini) にて行う
'    ため、処理関数として _TDSUDrvXxxx() を使用する限りは、ユーザＡＰでは、
'    接続方式（SECS-1/HSMS-SS そして HSMS-SS時の Passive/Active）を知る必要は
'    ない。
'
'    以下で定義する "MSSG_USE_FILE"、"MSSG_DISP_TYPE" の値を変更すると、本ＡＰ
'    にて表示する SECS メッセージの出力形式を変更できる。
'    "MSSG_USE_NEXTL" の値を変更すると、メッセージ内容を解析する際に、項目値を
'    データとして取得するか、表示リスト形式で取得するかを変更できる。
'    "HEADER_BO" を 1 とすると、Receive、Send 時に取得する SECS メッセージ・
'    ヘッダのバイトオーダーを SECS メッセージ本来のネットワーク・バイトオーダー
'    として取得できる。
'    同様に "USE_RECVTHREAD" を =1 とすると、受信処理を行うスレッドを起動し、そ
'    のスレッド内で受信メッセージの表示、２次メッセージの出力を自動で行う。
'    受信スレッドを使用する場合、入力促進用メッセージに乱れが生じる事に留意
'    すること。
' 
' ==============================================================================

Imports		System.Threading
Imports		TDVBL

namespace	TDVBSTest


class		VBIo

' ------------------------------------------------------------------------------

private const	E_BADF		as integer	=9
private const	E_BUSY		as integer	=16
private const	E_NOMEM		as integer	=12
private const	E_NODEV		as integer	=19
private const	E_2BIG		as integer	=7

private const	E_NOTCONNECT	as integer	=999
private const	E_DESELECT	as integer	=998
private const	E_REJECT	as integer	=997
private const	E_SEPARATE	as integer	=996
private const	E_SELECT	as integer	=992
private const	E_CONNECT	as integer	=991
private const	E_RETRYOVER	as integer	=989
private const	E_T8TIMEDOUT	as integer	=988
private const	E_T7TIMEDOUT	as integer	=987
private const	E_T6TIMEDOUT	as integer	=986
private const	E_T5TIMEDOUT	as integer	=985
private const	E_T4TIMEDOUT	as integer	=984
private const	E_T3TIMEDOUT	as integer	=983
private const	E_T2TIMEDOUT	as integer	=982
private const	E_T1TIMEDOUT	as integer	=981
private const	E_ILLBLOCK	as integer	=980
private const	E_NODATA	as integer	=951


' ------------------------------------------------------------------------------

private const	SECS_MODE	as integer =1	' SECS/HSMS mode
						' 0    : SECS-1
						' 1    : HSMS
						' (Note) See comments above 
						' (注) 上部コメント参照
private const	UDRV_MASK	as integer =&h8383ffff
						' Mask value of UDrvOpen()
						' 0	     : Set =&h49
						' &h8383ffff : All event

private const	FUNC_TYPE	as integer =1	' Type of function used
						' 通信に使用する関数の種別
						' 0    : _TDSCommXxxxx
						' 1    : _TDSUDrvXxxxx
private const	HEADER_BO	as integer =1	' Header byte order
						' 取得するヘッダの Byte Order
						' 0    : System  Order
						' 1    : Network Order
private const	MSSG_DISP_TYPE	as integer =&h20 'SECS Message display format
						' &h00 : TDS Format
						' &h20 : SML Format
private const	MSSG_USE_NEXTL	as integer =1	' Use MssgNext() or not
						' 0    : Not use
						' 1    : Use

private const	MSSG_USE_FILE	as integer =&h00 'Message definition file
						' &h00 : Not use
						' &h80 : Use to display item
						'	 names
						'	 使用して項目名表示する
private const	USE_RECVTHREAD	as integer =1	' Execute receiving process on
						' its own thread
						' 受信処理を自前スレッドで実行
						' 0    : Not use
						' 1    : Use

private const	SYNC_STATUS	as integer =1	' Synchronize connection status
						' 接続状態の同期
						' 0    : No
						' 1    : Yes
private const	SEND_WAIT	as integer =2000 ' Message sending interval (ms)
private const	SEND_NO		as integer =10	 ' #of times until message
						 ' transmission break
private const	SEND_SLEEP	as integer =10000 ' Waiting time	    (ms)
private const	ERROR_SLEEP	as integer =10000 ' Waiting time when an  error
						  ' occurs		    (ms)

private const	PARAMFILE	as string ="Sample.ini"


' ------------------------------------------------------------------------------

private shared	FuncType	as integer =FUNC_TYPE		' argv[1]&0x0001
private shared	HeaderBO	as integer =HEADER_BO		' argv[1]&0x0002
private shared	MssgDispType	as integer =MSSG_DISP_TYPE	' argv[1]&0x0004
private shared	MssgUseNextL	as integer =MSSG_USE_NEXTL	' argv[1]&0x0008
private shared	MssgUseFile	as integer =MSSG_USE_FILE	' argv[1]&0x0010
private shared	UseRecvThrd	as integer =USE_RECVTHREAD	' argv[1]&0x0020
private shared	SyncStatus	as integer =SYNC_STATUS		' argv[1]&0x8000

private shared	SendWait	as integer =SEND_WAIT		' argv[2]
private shared	SendSleep	as integer =SEND_SLEEP		' argv[3]

private shared	Td		as TDS		' TDS Class instans
private shared	Fd		as integer =0	' Communication identifier
private shared	Md		as integer =0	' Message analysis identifier
private shared	OType		as integer =0	' Operation type (0:Host 1:Equip)
private shared	Break		as integer =0	' End instruction to thread
						' スレッド終了指示

private shared	Dim Cs1		as New Object


' ------------------------------------------------------------------------------

private declare sub Sleep lib "kernel32" alias "Sleep" (byval ms as integer)



' ==============================================================================
' Common function ==============================================================


' ------------------------------------------------------------------------------
' Display SECS messages on standard output -------------------------------------
' SECS メッセージを標準出力に表示する ------------------------------------------

private shared sub			_
DispSECSMssgRightParentheses(		_
byval	la		as integer,	_
byval	no		as integer)

  dim	i,j		as integer

  i=la
  do while i>no
    for j=1 to i
      console.write("  ")			' Display ' '
    next j
    console.writeline(">")			' Display '>'
    i=i-1
  loop
end sub



private shared sub			_
DispSECSMssg(				_
byval	tp		as integer,	_
byval	hd()		as byte,	_
byval	did		as integer,	_
byval	sf		as integer,	_
byval	xid		as integer,	_
byval	msg()		as byte,	_
byval	len		as integer)

' tp	// i  : Message type
'	//	=0 : Transmission result
'	//	 1 : Received message
'	//	 2 : Send message
' hd	// i  : SECS Message Header
' did	// i  : SECS Message Device ID
' sf	// i  : SECS Message SF-Code
' xid	// i  : SECS Message Transaction IF
' msg	// i  : SECS Message Strage area (Header not include)
' len	// i  : SECS Message byte length

  dim	ctp()		as string	={"SRES","RECV","SEND"}
  dim	mname,iname	as string
  dim	itm(256)	as byte
  dim	vi1(256)	as sbyte
  dim	vi2(128)	as short
  dim	vi4( 64)	as integer
  dim	vi8( 32)	as long
  dim	vu1(256)	as byte
  dim	vu2(128)	as ushort
  dim	vu4( 64)	as uinteger
  dim	vu8( 32)	as ulong
  dim	vf4( 64)	as single
  dim	vf8( 32)	as double
  dim	str,rbit,wbit	as string
  dim	sdid,sfcode	as string
  dim	sitem		as string
  dim	rtn,mm,dp,fm	as integer
  dim	form,sz,noi,la	as integer
  dim	no0,no1,no2,i,j	as integer

  mm	= 0
  rbit	= " ":	if (did and &h8000)<>0 then	rbit = "R"
  wbit	= " ":	if (sf  and &h8000)<>0 then	wbit = "W"
  dp	= MssgUseFile or MssgDispType
	' [Note] Refer to [Note] described in DispSECSMssg () in SubFuncsion.h
	' [注意] SubFuncsion.h の DispSECSMssg() に記述の [注意] を参照すること

  if did< 0 then
    sdid= string.format("{0,6}"		,did)
  else
    sdid= string.format("0x{0:x4}"	,did)
  end if
  sfcode= string.format("S{0}F{1}",(sf and &h7f00) / &h0100,sf and &hff)
  console.writeline(							_
  "[{0}]  Dev={1,6}  {2,8}  {3}{4}  XId=0x{5:x4}.{6:x4}  Len={7,4}"+	_
  "  Head=0x{8:x2},{9:x2},{10:x2},{11:x2},{12:x2}"+			_
  ",{13:x2},{14:x2},{15:x2},{16:x2},{17:x2}"				_
	,ctp(tp),sdid,sfcode,rbit,wbit			_
	,(xid>>16) and &hffff,xid and &hffff,len			_
	,hd(0),hd(1),hd(2),hd(3),hd(4),hd(5),hd(6),hd(7),hd(8),hd(9))

  if (MssgUseFile and &h80)<>0 then:	fm = &h8000	' Use message definition file
  else:					fm = &h0000	' Not use
  end if

  if len>0 then
    if tp=1 then: dp= dp or &h3000:  fm= fm or &h3000	' In case of receiving
    else:	  dp= dp or &h2000:  fm= fm or &h2000	' In case of sending
    end if

    mname = ""
    mm	= Td._TDSMssgFind(fm,msg,len,Fd,hd,mname)
    if mm>0 then
      if mname<>"" then console.writeline("[{0}]",mname)' Message name
      la=0
      do
	if MssgUseNextL=0 then	' Get item value
	  sitem=""
	  rtn=Td._TDSMssgNext(mm,0,msg,form,sz,noi,itm,256,sitem)
	  form=form and &o077
	  if rtn		< 0	then	exit do
		  console.write("0x{0:x2}:{1}*{2,3:d}:",form,sz,noi)
	  select case form	 ' Display field value
				 ' The third and subsequent numbers are omitted
				 ' 数値の３番目以降は省略
	    case &o000: Console.WriteLine("L [{0,2:d}]"		,noi)
	    case &o010: Console.WriteLine("B [{0,2:d}]=0x{1,0:x2},{2,0:x2}"	_
								,noi,itm(0),itm(1))
	    case &o011: Console.WriteLine("T [{0,2:d}]={1,0},{2,0}"		_
								,noi,itm(0),itm(1))
	    case &o020: Console.WriteLine("A [{0,2:d}]={1}"	,noi,sitem)
	    case &o021: Console.WriteLine("J [{0,2:d}]={1}"	,noi,sitem)
	    case &o022: Console.WriteLine("K [{0,2:d}]={1}"	,noi,
		System.Text.Encoding.GetEncoding("SHIFT-JIS").GetString(itm,0,noi))
	    case &o030: Buffer.BlockCopy(itm,0,vi8,0,sz*noi)
			Console.WriteLine("I8[{0,2:d}]={1},{2}"	,noi,vi8(0),vi8(1))
	    case &o031: Buffer.BlockCopy(itm,0,vi1,0,sz*noi)
			Console.WriteLine("I1[{0,2:d}]={1},{2}"	,noi,vi1(0),vi1(1))
	    case &o032: Buffer.BlockCopy(itm,0,vi2,0,sz*noi)
			Console.WriteLine("I2[{0,2:d}]={1},{2}"	,noi,vi2(0),vi2(1))
	    case &o034: Buffer.BlockCopy(itm,0,vi4,0,sz*noi)
			Console.WriteLine("I4[{0,2:d}]={1},{2}"	,noi,vi4(0),vi4(1))
	    case &o040: Buffer.BlockCopy(itm,0,vf8,0,sz*noi)
			Console.WriteLine("F8[{0,2:d}]={1},{2}"	,noi,vf8(0),vf8(1))
	    case &o044: Buffer.BlockCopy(itm,0,vf4,0,sz*noi)
			Console.WriteLine("F4[{0,2:d}]={1},{2}"	,noi,vf4(0),vf4(1))
	    case &o050: Buffer.BlockCopy(itm,0,vu8,0,sz*noi)
			Console.WriteLine("U8[{0,2:d}]={1},{2}"	,noi,vu8(0),vu8(1))
	    case &o051: Buffer.BlockCopy(itm,0,vu1,0,sz*noi)
			Console.WriteLine("U1[{0,2:d}]={1},{2}"	,noi,vu1(0),vu1(1))
	    case &o052: Buffer.BlockCopy(itm,0,vu2,0,sz*noi)
			Console.WriteLine("U2[{0,2:d}]={1},{2}"	,noi,vu2(0),vu2(1))
	    case &o054: Buffer.BlockCopy(itm,0,vu4,0,sz*noi)
			Console.WriteLine("U4[{0,2:d}]={1},{2}"	,noi,vu4(0),vu4(1))
	  end select

	else						' Get in list format
	  str=""					' リスト表示形式で取得
	  rtn=Td._TDSMssgNextL(mm,dp,msg,form,noi,str)
	  form=form and &o077
	  if rtn		< 0	then	exit do
	  if (dp and &h70) > &h10 then			' In case of SML
	    DispSECSMssgRightParentheses(la,rtn)	' Display '>'
	  end if
	  la=rtn					' Save current hierarchy
							' 現在の階層を保存
	  console.writeline("  {0}",str)		' Display acquired field value
							' 取得した項目値を表示
	  if ((dp and &h70) > &h10) and (form=0) and (noi=0)  then
	    DispSECSMssgRightParentheses(la+1,la)	' '>' Processing for L0
	  end if					' L0 の場合の '>' 処理
	end if
      loop

      if MssgUseNextL<>0 then
	if (dp and &h70) > &h10 then
	  DispSECSMssgRightParentheses(la,0)		' Show remaining '>'
	end if						' 残りの '>' 表示
      end if
      Td._TDSMssgExit(mm,0,msg)
    end if

    if (MssgUseFile and &h80)<>0  and  MssgUseNextL<>0 then
		' Refer to the comment in corresponding section of SubFuncsion.h
		' SubFuncsion.h の該当箇所のコメントを参照すること
      sf = sf and &h7fff
      if Td._TDSMDMssgFind(Md,0,msg,len,sf,mname)	> 0 then
	Console.WriteLine("Message Definition Name = '{0}'"	,mname)

	if	sf = &h0115 then			' S1F21
	  no0=Td._TDSMDMssgNext(Md,0,msg,"VB"	, 0,itm)
	  if no0					>=0 then
	    Console.Write    ("VB          [{0,2:d}]=0x"	,no0)
	    for i=0 to no0-1
	      Console.Write  ("{0,0:x2} "			,itm(i))
	    next i
	    Console.WriteLine("")
	  end if
	  sitem=""
	  no0=Td._TDSMDMssgNext(Md,0,msg,"MDLN"	, 0,sitem)
	  if no0					>=0 then
	    Console.WriteLine("MDLN        [{0,2:d}]='{1}'"	,no0,sitem)
	  end if
	  no0=Td._TDSMDMssgNext(Md,0,msg,"VI4"	, 0,vi4)
	  if no0					>=0 then
	    Console.Write    ("VI4         [{0,2:d}]="		,no0)
	    for i=0 to no0-1
	      Console.Write  ("{0} "				,vi4(i))
	    next i
	    Console.WriteLine("")
	  end if
	  no0=Td._TDSMDMssgNext(Md,0,msg,"VF4"	, 0,vf4)
	  if no0					>=0 then
	    Console.Write    ("VF4         [{0,2:d}]="		,no0)
	    for i=0 to no0-1
	      Console.Write  ("{0:e} "				,vf4(i))
	    next i
	    Console.WriteLine("")
	  end if

	else if	sf = &h0116 then			' S1F22
	  no0=Td._TDSMDMssgNext(Md,0,msg,"VT"	, 0,itm)
	  if no0					>=0 then
	    Console.Write    ("VT          [{0,2:d}]=0x"	,no0)
	    for i=0 to no0-1
	      Console.Write  ("{0,0:x2} "			,itm(i))
	    next i
	    Console.WriteLine("")
	  end if
	  sitem=""
	  no0=Td._TDSMDMssgNext(Md,0,msg,"COMMENT", 0,sitem)
	  if no0					>=0 then
	    Console.WriteLine("COMMENT     [{0,2:d}]='{1}'"	,no0,sitem)
	  end if
	  no0=Td._TDSMDMssgNext(Md,0,msg,"AU8"	, 0,vu8)
	  if no0					>=0 then
	    Console.Write    ("AU8         [{0,2:d}]="		,no0)
	    for i=0 to no0-1
	      Console.Write  ("{0} "				,vu8(i))
	    next i
	    Console.WriteLine("")
	  end if
	  no0=Td._TDSMDMssgNext(Md,0,msg,"VF8"	, 0,vf8)
	  if no0					>=0 then
	    Console.Write    ("VF8         [{0,2:d}]="		,no0)
	    for i=0 to no0-1
	      Console.Write  ("{0:e} "				,vf8(i))
	    next i
	    Console.WriteLine("")
	  end if

	else if	sf = &h0231 then			' S2F49
	  if Td._TDSMDMssgNext (Md,0,msg,"NOI1"	, 0,vi4)> 0 then
	    no1=vi4(0)
	    Console.WriteLine("NOI1        [{0,2:d}]"		,no1)
	    sitem=""
	    for i=0 to no1-1
	      iname=string.format("NOI2:{0}"			,i+1)
		' Refer to the comment in corresponding section of SubFuncsion.h
		' SubFuncsion.h の該当箇所のコメントを参照すること
	      if Td._TDSMDMssgNext(Md,0,msg,iname,0,vi4)> 0 then
		no2=vi4(0)
		Console.WriteLine("{0,-12:s}[{1,2:d}]"		,iname,no2)
		for j=0 to no2-1
		  iname=string.format("WAFERID:{0}:{1}"	,i+1,j+1)
		  no0=Td._TDSMDMssgNext(Md,0,msg,iname,0,sitem)
		  if no0				>=0 then
		    Console.WriteLine("{0,-12:s}[{1,2:d}]='{2}'",iname,no0,sitem)
		  end if
		next j
	      end if
	    next i
	  end if

	else if	sf = &h060b then			' S6F11
	  no0=Td._TDSMDMssgNext(Md,0,msg,"DATAID", 0,vi2)
	  if no0					>=0 then
	    Console.Write    ("DATAIDB     [{0,2:d}]="		,no0)
	    for i=0 to no0-1
	      Console.Write  ("{0} "				,vi2(i))
	    next i
	    Console.WriteLine("")
	  end if
	end if
	Td._TDSMDMssgExit(Md,0,msg)
      end if
    end if
  end if

end sub



' ------------------------------------------------------------------------------
' Display sent and received data -----------------------------------------------

private shared function			_
DispData(				_
byval	tp		as integer,	_
byval	hd()		as byte,	_
byval	did		as integer,	_
byval	sf		as integer,	_
byval	xid		as integer,	_
byval	msg()		as byte,	_
byval	len		as integer,	_
byval	rtn		as integer)	_
			as integer

' tp	// i  : Message type
'	//	=0 : Transmission result
'	//	 1 : Received message
'	//	 2 : Send message
' hd	// i  : SECS Message Header
' did	// i  : SECS Message Device ID
' sf	// i  : SECS Message SF-Code
' xid	// i  : SECS Message Transaction IF
' msg	// i  : SECS Message body
' len	// i  : Byte length of 'msg'
' rtn	// i  : I/O retrun value

  dim	ok		as integer
  dim	stat		as integer

  SyncLock Cs1		' See notes in SubFuncsion.h
			' SubFuncsion.h の注記を参照すること
  ok	=0
  if rtn<0 then:	ok=1
    if (rtn<(-E_NOTCONNECT) or (-E_ILLBLOCK)<rtn) and rtn<>(-E_NODATA) then
      console.write("ERROR  [{0}]"		,rtn)
      if     rtn=(-E_NODEV) then
	console.writeline(" : No such device ID")
	len=0:		ok=0
      elseif rtn=(-E_2BIG)  then
	console.writeline(" : Data size to large")
	len=0:		ok=0
      else
	console.writeline("")
      end if

    else
      if FuncType=0 then:	stat=Td._TDSCommStatus(Fd,0)
      else:			stat=Td._TDSUDrvStatus(Fd,0)
      end if
      console.write("STATUS = {0},{1} : "	,-rtn,stat)
      select case (-rtn)
	case E_NODATA:		console.writeline("No data")
	case E_ILLBLOCK:	console.writeline("Illegal block#")
	case E_T1TIMEDOUT:	console.writeline("T1 Timeout occur")
	case E_T2TIMEDOUT:	console.writeline("T2 Timeout occur")
	case E_T3TIMEDOUT:	console.writeline("T3 Timeout occur")
	case E_T4TIMEDOUT:	console.writeline("T4 Timeout occur")
	case E_T5TIMEDOUT:	console.writeline("T5 Timeout occur")
	case E_T6TIMEDOUT:	console.writeline("T6 Timeout occur")
	case E_T7TIMEDOUT:	console.writeline("T7 Timeout occur")
	case E_T8TIMEDOUT:	console.writeline("T8 Timeout occur")
	case E_RETRYOVER:	console.writeline("Retry over")
	case E_CONNECT:		console.writeline("Connected")
	case E_SELECT:		console.writeline("Selected   (0x{0:x4})" ,did)
	case E_REJECT:		console.writeline("Rejected XId=0x{0:x4}" ,xid)
	case E_DESELECT:	console.writeline("Deselected (0x{0:x4})" ,did)
	case E_SEPARATE:	console.writeline("Separated  (0x{0:x4})" ,did)
	case E_NOTCONNECT:	console.writeline("Not connected")
	case else:		console.writeline("")
      end select
    end if
  end if

  if ok=0 then DispSECSMssg(tp,hd,did,sf,xid,msg,len)
  End SyncLock

  return 0
end function



' ==============================================================================
' S1F1 message construction and sending ----------------------------------------

private shared function			_
SendS1F1()		as integer

  dim	hd(12),msg(16)	as byte
  dim	rtn,sf,cmd,len	as integer

  sf	=&h8101
  cmd	=&h0000
  len	=0

			' See (Note) in SendS1F1() of SubFunction.h.
			' SubFunction.h の SendS1F1() 内 (注) を参照すること。
  if HeaderBO<>0 then:	cmd=&h2000:	end if
  if FuncType =0 then:	rtn=Td._TDSCommSend(Fd,cmd, -1,sf,  0,msg,len,hd)
  else:			rtn=Td._TDSUDrvSend(Fd,cmd, -1,sf,  0,msg,len,hd)
  end if
  DispData(2,hd, -1,sf,rtn,msg,len,rtn)

  return rtn
end function


' ------------------------------------------------------------------------------
' S1F2 message (Host) construction and sending ---------------------------------
' S1F2 メッセージ (Host) 構築及び送信 ------------------------------------------

private shared function			_
SendS1F2H(				_
byval	did		as integer,	_
byval	xid		as integer)	_
			as integer

  dim	hd(12),msg(256)	as byte
  dim	item(32)	as byte
  dim	rtn,sf,cmd,len	as integer
  dim	mm		as integer

  sf	=&h0102
  cmd	=&h0000
  len	=0

  if (MssgUseFile and &h80)=0	then		' Do not use message definition
    mm=		Td._TDSMssgInit   (   0,msg,  256,Fd)		' S1F2
		Td._TDSMssgBuild  (mm,0,msg,&o000,  0,item)	' L0
    len=	Td._TDSMssgEnd    (mm,0,msg)

  else						' Use message definition
		Td._TDSMDMssgInit (Md,0,msg,  256,"S1F2_H")
    len=	Td._TDSMDMssgEnd  (Md,0,msg)
  end if

  if len<0 then:	 rtn=len
  else
    if HeaderBO<>0 then: cmd=&h2000:	end if
    if FuncType =0 then: rtn=Td._TDSCommSend(Fd,cmd,did,sf,xid,msg,len,hd)
    else:		 rtn=Td._TDSUDrvSend(Fd,cmd,did,sf,xid,msg,len,hd)
    end if
  end if
  DispData(2,hd,did,sf,rtn,msg,len,rtn)

  return rtn
end function


' ------------------------------------------------------------------------------
' S1F2 message (Equipment) construction and sending ----------------------------
' S1F2 メッセージ (Equip) 構築及び送信 -----------------------------------------

private shared function			_
SendS1F2E(				_
byval	did		as integer,	_
byval	xid		as integer)	_
			as integer

  dim	hd(12),msg(256)	as byte
  dim	item(32)	as byte
  dim	rtn,sf,cmd,len	as integer
  dim	mm		as integer

  sf	=&h0102
  cmd	=&h0000
  len	=0

  if (MssgUseFile and &h80)=0	then		' Do not use message definition
    mm=		Td._TDSMssgInit   (   0,msg,  256,Fd)		' S1F2
		Td._TDSMssgBuild  (mm,0,msg,&o000,  2,item)	' L2
		Td._TDSMssgBuild  (mm,0,msg,&o020,  6,"EQUIP1")	'  MDLN
		Td._TDSMssgBuild  (mm,0,msg,&o020,  6,"11.111")	'  SOFTREV
    len=	Td._TDSMssgEnd    (mm,0,msg)

  else						' Use message definition
		Td._TDSMDMssgInit (Md,0,msg,  256,"S1F2_E")
    len=	Td._TDSMDMssgEnd  (Md,0,msg)
  end if

  if len<0 then:	 rtn=len
  else
    if HeaderBO<>0 then: cmd=&h2000:	end if
    if FuncType =0 then: rtn=Td._TDSCommSend(Fd,cmd,did,sf,xid,msg,len,hd)
    else:		 rtn=Td._TDSUDrvSend(Fd,cmd,did,sf,xid,msg,len,hd)
    end if
  end if
  DispData(2,hd,did,sf,rtn,msg,len,rtn)

  return rtn
end function
  

' ==============================================================================
' S1F21 message construction and sending ---------------------------------------
' 1F219 メッセージ構築及び送信 -------------------------------------------------

private shared function			_
SendS1F21()		as integer

  dim	vb  as byte    ()={                      1,                       &hff}
  dim	vt  as byte    ()={                      0,                          1}
  dim	vs0 as string 	 = "MSG61"
  dim	vs1 as string 	 = "ｿﾌﾄ 06"
  dim	vs2 as string 	 = "これは ｺﾒﾝﾄ (VBIo) です"
  dim	vi1 as sbyte   ()={                      2,                       -128}
  dim	vi2 as short   ()={                  32767,                     -32768}
  dim	vi4 as integer ()={             &h7ffffffe,                 &hfffffffe}
  dim	vi8 as long    ()={    &h7fffffffffffffffL,        &h800080008000800bL}
  dim	vu1 as byte    ()={                   &h7f,                       &hff}
  dim	vu2 as ushort  ()={                 &h7ffe,                     &hfffe}
  dim	vu4 as uinteger()={             &h7ffffffd,                &hfffffffdL}
  dim	vu8 as ulong   ()={    &h7fffffffffffffffL,       &h800080008000800bUL}
  dim	au8 as long    ()={  7, -6,  5, -4,  3, -2,  1,  0}
  dim	vf4 as single  ()={         9.87654321e-21,            -8.642097531e13}
  dim	vf8 as double  ()={-1.9283746574839201e123, 9.1827364546372819208e-213}
  dim	hd (12)		as byte
  dim	msg(1024)	as byte
  dim	rtn,sf,cmd,len	as integer
  dim	mm		as integer

  sf	=&h8100+21
  cmd	=&h0000
  len	=0
  
  if (MssgUseFile and &h80)=0 then		' Do not use message definition
    mm=		Td._TDSMssgInit   (   0,msg, 1024,Fd)		' S1F21
  		Td._TDSMssgBuild  (mm,0,msg,&o000,  4,vb)	' L4
  		Td._TDSMssgBuild  (mm,0,msg,&o000,  2,vb)	'  L2
  		Td._TDSMssgBuild  (mm,0,msg,&o010,  2,vb)	'   VB
  		Td._TDSMssgBuild  (mm,0,msg,&o011,  2,vt)	'   VT
  		Td._TDSMssgBuild  (mm,0,msg,&o000,  3,vb)	'  L3
  		Td._TDSMssgBuild  (mm,0,msg,&o020,  6,vs0)	'   MDLN
  		Td._TDSMssgBuild  (mm,0,msg,&o021,  0,vs1)	'   SOFTREV
  		Td._TDSMssgBuild  (mm,0,msg,&o022,  0,vs2)	'   COMMENT
  		Td._TDSMssgBuild  (mm,0,msg,&o000,  9,vb)	'  L9
  		Td._TDSMssgBuild  (mm,0,msg,&o031,  2,vi1)	'   VI1
  		Td._TDSMssgBuild  (mm,0,msg,&o032,  2,vi2)	'   VI2
  		Td._TDSMssgBuild  (mm,0,msg,&o034,  2,vi4)	'   VI4
  		Td._TDSMssgBuild  (mm,0,msg,&o030,  2,vi8)	'   VI8
  		Td._TDSMssgBuild  (mm,0,msg,&o051,  2,vu1)	'   VU1
  		Td._TDSMssgBuild  (mm,0,msg,&o052,  2,vu2)	'   VU2
  		Td._TDSMssgBuild  (mm,0,msg,&o054,  2,vu4)	'   VU4
  		Td._TDSMssgBuild  (mm,0,msg,&o050,  2,vu8)	'   VU8
  		Td._TDSMssgBuild  (mm,0,msg,&o050,  8,au8)	'   AU8
  		Td._TDSMssgBuild  (mm,0,msg,&o000,  2,vb)	'  L2
  		Td._TDSMssgBuild  (mm,0,msg,&o044,  2,vf4)	'   VF4
  		Td._TDSMssgBuild  (mm,0,msg,&o040,  2,vf8)	'   VF8
    len=	Td._TDSMssgEnd    (mm,0,msg)

  else						' Use message definition
		Td._TDSMDMssgInit (Md,0,msg, 1024,"S1F21_HE")
    len=	Td._TDSMDMssgEnd  (Md,0,msg)
  end if

  if len<0 then:	 rtn=len ' See (Note) in SendS1F1() of SubFunction.h
  else				 ' SubFunction.h の SendS1F1() 内 (注) を参照
    if HeaderBO<>0 then: cmd=&h2000:	end if
    if FuncType =0 then: rtn=Td._TDSCommSend(Fd,cmd, -1,sf,  0,msg,len,hd)
    else:		 rtn=Td._TDSUDrvSend(Fd,cmd, -1,sf,  0,msg,len,hd)
    end if
  end if
  DispData(2,hd, -1,sf,rtn,msg,len,rtn)

  return rtn
end function


' ------------------------------------------------------------------------------
' S1F22 message construction and sending ---------------------------------------
' S1F22 メッセージ構築及び送信 -------------------------------------------------

private shared function			_
SendS1F22(				_
byval	did		as integer,	_
byval	xid		as integer)	_
			as integer

  dim	vb  as byte    ()={                      2,                       &hfe}
  dim	vt  as byte    ()={                      1,                          0}
  dim	vs0 as string 	 = "MSG62"
  dim	vs1 as string 	 = "ﾚﾋﾞｼﾞｮﾝ"
  dim	vs2 as string 	 = "This is コメント (VBIo)"
  dim	vi1 as sbyte   ()={                    127,                         -2}
  dim	vi2 as short   ()={                  32767,                     -32768}
  dim	vi4 as integer ()={             2147483646,                -2147483648}
  dim	vi8 as long    ()={    &h8000000000000000L,        &h7ffffffffffffffeL}
  dim	vu1 as byte    ()={                    254,                       &hff}
  dim	vu2 as ushort  ()={                  65534,                     &hffff}
  dim	vu4 as uinteger()={             4294967294,                &hffffffffL}
  dim	vu8 as ulong   ()={ 18446744073709551614UL,       &hffffffffffffffffUL}
  dim	au8 as long    ()={ -1,  2, -3,  4, -5,  6, -7,  0}
  dim	vf4 as single  ()={         7.89012345e-12,            -4.321098765e31}
  dim	vf8 as double  ()={ 5.6473829101928374e189,-3.2109876543210987654e-179}
  dim	hd (12)		as byte
  dim	msg(1024)	as byte
  dim	rtn,sf,cmd,len	as integer
  dim	mm		as integer

  sf	=&h0100+22
  cmd	=&h0000
  len	=0

  if (MssgUseFile and &h80)=0 then		' Do not use message definition
    mm=		Td._TDSMssgInit   (   0,msg, 1024,Fd)		' S1F22
  		Td._TDSMssgBuild  (mm,0,msg,&o000,  4,vb)	' L4
  		Td._TDSMssgBuild  (mm,0,msg,&o000,  2,vb)	'  L2
  		Td._TDSMssgBuild  (mm,0,msg,&o010,  2,vb)	'   VB
  		Td._TDSMssgBuild  (mm,0,msg,&o011,  2,vt)	'   VT
  		Td._TDSMssgBuild  (mm,0,msg,&o000,  3,vb)	'  L3
  		Td._TDSMssgBuild  (mm,0,msg,&o020,  6,vs0)	'   MDLN
  		Td._TDSMssgBuild  (mm,0,msg,&o021,  0,vs1)	'   SOFTREV
  		Td._TDSMssgBuild  (mm,0,msg,&o022,  0,vs2)	'   COMMENT
  		Td._TDSMssgBuild  (mm,0,msg,&o000,  9,vb)	'  L9
  		Td._TDSMssgBuild  (mm,0,msg,&o031,  2,vi1)	'   VI1
  		Td._TDSMssgBuild  (mm,0,msg,&o032,  2,vi2)	'   VI2
  		Td._TDSMssgBuild  (mm,0,msg,&o034,  2,vi4)	'   VI4
  		Td._TDSMssgBuild  (mm,0,msg,&o030,  2,vi8)	'   VI8
  		Td._TDSMssgBuild  (mm,0,msg,&o051,  2,vu1)	'   VU1
  		Td._TDSMssgBuild  (mm,0,msg,&o052,  2,vu2)	'   VU2
  		Td._TDSMssgBuild  (mm,0,msg,&o054,  2,vu4)	'   VU4
  		Td._TDSMssgBuild  (mm,0,msg,&o050,  2,vu8)	'   VU8
  		Td._TDSMssgBuild  (mm,0,msg,&o050,  8,au8)	'   AU8
  		Td._TDSMssgBuild  (mm,0,msg,&o000,  2,vb)	'  L2
  		Td._TDSMssgBuild  (mm,0,msg,&o044,  2,vf4)	'   VF4
  		Td._TDSMssgBuild  (mm,0,msg,&o040,  2,vf8)	'   VF8
    len=	Td._TDSMssgEnd    (mm,0,msg)

  else						' Use message definition
		Td._TDSMDMssgInit (Md,0,msg, 1024,"S1F22_HE")
    len=	Td._TDSMDMssgEnd  (Md,0,msg)
  end if

  if len<0 then:	 rtn=len
  else
    if HeaderBO<>0 then: cmd=&h2000:	end if
    if FuncType =0 then: rtn=Td._TDSCommSend(Fd,cmd,did,sf,xid,msg,len,hd)
    else:		 rtn=Td._TDSUDrvSend(Fd,cmd,did,sf,xid,msg,len,hd)
    end if
  end if
  DispData(2,hd,did,sf,rtn,msg,len,rtn)

  return rtn
end function


' ==============================================================================
' S2F49 message construction and sending ---------------------------------------
' S2F49 メッセージ構築及び送信 -------------------------------------------------

private shared function			_
SendS2F49()		as integer

  static cnt		as integer	=0
  dim	hd(12),msg(1024) as byte
  dim	vb(32)		as byte
  dim	vi(4)		as integer
  dim	str,itm		as string
  dim	rtn,sf,cmd,len	as integer
  dim	mm,no1,no2,i,j	as integer

  sf	=&h8200+49
  cmd	=&h0000
  len	=0
  cnt	=cnt+1
  no1	=(cnt mod 2)+1:	no2=(cnt mod 10)+1
  str=string.Format("LOTID ({0,0:d4})",cnt)
  
  if (MssgUseFile and &h80)=0 then		' Do not use message definition
    mm=		Td._TDSMssgInit   (   0,msg, 1024,Fd)		' S2F49
  		Td._TDSMssgBuild  (mm,0,msg,&o000,  3,vb)	' L3
    vb(0)=0:	Td._TDSMssgBuild  (mm,0,msg,&o010,  1,vb)	'  DATAIDB
  		Td._TDSMssgBuild  (mm,0,msg,&o020,  0,"LOAD")	'  RCMD
  		Td._TDSMssgBuild  (mm,0,msg,&o000,  4,vb)	'  L4
    vb(0)=1:	Td._TDSMssgBuild  (mm,0,msg,&o010,  1,vb)	'   STID
    vb(0)=0:	Td._TDSMssgBuild  (mm,0,msg,&o010,  1,vb)	'   MTKD
  		Td._TDSMssgBuild  (mm,0,msg,&o020, 20,str)	'   LOTID
		Td._TDSMssgBuild  (mm,0,msg,&o000,no1,vb)	'   L[no1]
    for i=1 to no1
		Td._TDSMssgBuild  (mm,0,msg,&o000,no2,vb)	'    L[no2]
      for j=1 to no2
		Td._TDSMssgBuild  (mm,0,msg,&o000,  2,vb)	'     L[2]
	str=string.Format("WAFER({0,0:d4}-{1,0:d1}-{2,0:d2})",cnt,i,j)
  		Td._TDSMssgBuild  (mm,0,msg,&o020, 20,str)	'      WAFERID
	str=string.Format("PPID ({0,0:d4}-{1,0:d1}-{2,0:d2})",cnt,i,j)
  		Td._TDSMssgBuild  (mm,0,msg,&o020, 16,str)	'      PPID
      next j
    next i
    len=	Td._TDSMssgEnd    (mm,0,msg)

  else						' Use message definition
		Td._TDSMDMssgInit (Md,0,msg, 1024,"S2F49_H")
  		Td._TDSMDMssgBuild(Md,0,msg,"LOTID",0,str)	'   LOTID
    vi(0)=no1:	Td._TDSMDMssgBuild(Md,0,msg,"NOI1" ,1,vi)	'   L[no1]
    for i=1 to no1
      itm  =string.Format("NOI2:{0,0:d1}"		,i)
      vi(0)=no2:Td._TDSMDMssgBuild(Md,0,msg,itm    ,1,vi)	'    L[no2]
      for j=0 to no2
	itm=string.Format("WAFERID:{0,0:d1}:{1,0:d1}"	,i,j)
	str=string.Format("WAFERID[{0,0:d4}-{1,0:d1}-{1,0:d2}]",cnt,i,j)
  		Td._TDSMDMssgBuild(Md,0,msg,itm    ,0,str)	'     WAFERID
	itm=string.Format("PPID:{0,0:d1}:{1,0:d1}"	,i,j)
	str=string.Format("PPID [{0,0:d4}-{1,0:d1}-{1,0:d2}]"  ,cnt,i,j)
  		Td._TDSMDMssgBuild(Md,0,msg,itm    ,0,str)	'     PPID
      next j
    next i
    len=	Td._TDSMDMssgEnd  (Md,0,msg)
  end if

  if len<0 then:	 rtn=len ' See (Note) in SendS1F1() of SubFunction.h
  else				 ' SubFunction.h の SendS1F1() 内 (注) を参照
    if HeaderBO<>0 then: cmd=&h2000:	end if
    if FuncType =0 then: rtn=Td._TDSCommSend(Fd,cmd, -1,sf,  0,msg,len,hd)
    else:		 rtn=Td._TDSUDrvSend(Fd,cmd, -1,sf,  0,msg,len,hd)
    end if
  end if
  DispData(2,hd, -1,sf,rtn,msg,len,rtn)

  return rtn
end function


' ------------------------------------------------------------------------------
' S2F50 message construction and sending ---------------------------------------
' S2F50 メッセージ構築及び送信 -------------------------------------------------

private shared function			_
SendS2F50(				_
byval	did		as integer,	_
byval	xid		as integer)	_
			as integer

  static cnt		as integer	=0
  dim	hd(12),msg(256)	as byte
  dim	vb(32)		as byte
  dim	str		as string
  dim	rtn,sf,cmd,len	as integer
  dim	mm		as integer

  sf	=&h0200+50
  cmd	=&h0000
  len	=0
  cnt	=cnt+1
  str=string.Format("LOTID ({0,0:d4})"	,cnt)

  if (MssgUseFile and &h80)=0 then		' Do not use message definition
    mm=		Td._TDSMssgInit   (   0,msg,  256,Fd)		' S2F50
		Td._TDSMssgBuild  (mm,0,msg,&o000,  2,vb)	' L2
    vb(0)=0:	Td._TDSMssgBuild  (mm,0,msg,&o010,  1,vb)	'  HCACK
		Td._TDSMssgBuild  (mm,0,msg,&o000,  2,vb)	'  L2
  		Td._TDSMssgBuild  (mm,0,msg,&o020, 16,"PPID")	'   PPID
  		Td._TDSMssgBuild  (mm,0,msg,&o020, 20,str)	'   LOTID
    len=	Td._TDSMssgEnd    (mm,0,msg)

  else						' Use message definition
		Td._TDSMDMssgInit (Md,0,msg,  256,"S2F50_E")
		Td._TDSMDMssgBuild(Md,0,msg,"LOTID",  0,str)	'   LOTID
    len=	Td._TDSMDMssgEnd  (Md,0,msg)
  end if

  if len<0 then:	 rtn=len
  else
    if HeaderBO<>0 then: cmd=&h2000:	end if
    if FuncType =0 then: rtn=Td._TDSCommSend(Fd,cmd,did,sf,xid,msg,len,hd)
    else:		 rtn=Td._TDSUDrvSend(Fd,cmd,did,sf,xid,msg,len,hd)
    end if
  end if
  DispData(2,hd,did,sf,rtn,msg,len,rtn)

  return rtn
end function


' ==============================================================================
' S6F11 message construction and sending ---------------------------------------
' S6F11 メッセージ構築及び送信 -------------------------------------------------

private shared function			_
SendS6F11()		as integer

  static cnt		as integer	=0
  dim	hd(12),msg(256)	as byte
  dim	vs(4)		as short
  dim	vu(4)		as ushort
  dim	rtn,sf,cmd,len	as integer
  dim	mm		as integer

  sf	=&h8600+11
  cmd	=&h0000
  len	=0
  cnt	=cnt+1:		if cnt = 32768 then	cnt=0

  if (MssgUseFile and &h80)=0 then		' Do not use message definition
    mm=		Td._TDSMssgInit   (   0,msg,  256,Fd)		' S2F50
		Td._TDSMssgBuild  (mm,0,msg,&o000,  3,vs)	' L3
    vu(0)=cnt:	Td._TDSMssgBuild  (mm,0,msg,&o052,  1,vu)	'  DATAID
    vu(0)=8:	Td._TDSMssgBuild  (mm,0,msg,&o052,  1,vu)	'  CEID
  		Td._TDSMssgBuild  (mm,0,msg,&o000,  3,vs)	'  L3
  		Td._TDSMssgBuild  (mm,0,msg,&o020, 16,"DATA1")	'   DATA1
  		Td._TDSMssgBuild  (mm,0,msg,&o020, 16,"DATA2")	'   DATA2
  		Td._TDSMssgBuild  (mm,0,msg,&o020, 14,"YYYYMMDDhhmmss")
			' @TIME Actually I set current time, but omitted.
			' @TIME 本当は現在時刻を設定するのだが、省略
    len=	Td._TDSMssgEnd    (mm,0,msg)

  else						' Use message definition
		Td._TDSMDMssgInit (Md,0,msg,  256,"S6F11_E0")
    vs(0)=cnt:  Td._TDSMDMssgBuild(Md,0,msg,"DATAID",1,vs)	'  DATAID
    len=	Td._TDSMDMssgEnd  (Md,0,msg)
  end if

  if len<0 then:	 rtn=len ' See (Note) in SendS1F1() of SubFunction.h
  else				 ' SubFunction.h の SendS1F1() 内 (注) を参照
    if HeaderBO<>0 then: cmd=&h2000:	end if
    if FuncType =0 then: rtn=Td._TDSCommSend(Fd,cmd, -1,sf,  0,msg,len,hd)
    else:		 rtn=Td._TDSUDrvSend(Fd,cmd, -1,sf,  0,msg,len,hd)
    end if
  end if
  DispData(2,hd, -1,sf,rtn,msg,len,rtn)

  return rtn
end function



' ------------------------------------------------------------------------------
' S6F12 message construction and sending ---------------------------------------

private shared function			_
SendS6F12(				_
byval	did		as integer,	_
byval	xid		as integer)	_
			as integer

  static cnt		as integer	=0
  dim	hd(12),msg(256)	as byte
  dim	vb(32)		as byte
  dim	rtn,sf,cmd,len	as integer
  dim	mm		as integer

  sf	=&h0600+12
  cmd	=&h0000+12
  len	=0

  if (MssgUseFile and &h80)=0 then		' Do not use message definition
    mm=		Td._TDSMssgInit   (   0,msg,  256,Fd)		' S2F50
    vb(0)=0:	Td._TDSMssgBuild  (mm,0,msg,&o010,  1,vb)	' ACKC
    len=	Td._TDSMssgEnd    (mm,0,msg)

  else						' Use message definition
		Td._TDSMDMssgInit (Md,0,msg,  256,"S6F12_H")
    len=	Td._TDSMDMssgEnd  (Md,0,msg)
  end if

  if len<0 then:	 rtn=len
  else
    if HeaderBO<>0 then: cmd=&h2000:	end if
    if FuncType =0 then: rtn=Td._TDSCommSend(Fd,cmd,did,sf,xid,msg,len,hd)
    else:		 rtn=Td._TDSUDrvSend(Fd,cmd,did,sf,xid,msg,len,hd)
    end if
  end if
  DispData(2,hd,did,sf,rtn,msg,len,rtn)

  return rtn
end function



' ==============================================================================
' Callback Function ============================================================

private shared function			_
CBRecvProc(				_
byval	req		as integer,	_
byval	rtn		as integer,	_
byval	did		as integer,	_
byval	xsf		as integer,	_
byval	xid		as integer,	_
byval	xhd()		as byte,	_
byval	xmsg()		as byte)	_
			as integer

' req	// i  : Request code to library
' rtn	// i  : Return code from library
' did	// i  : SECS Message Device ID
' xsf	// i  : SECS Message SF-Code
' xid	// i  : SECS Message Transaction ID
' xhd	// i  : SECS Message Header
' xmsg	// i  : SECS Message Body

  dim	hd(12),msg(256)	as byte
  dim	rname,sname	as string
  dim	len,sf,cmd,scd	as integer

  cmd=&h0000
  DispData(1,xhd,did,xsf,xid,xmsg,rtn,rtn)

  if req=0 and rtn>=0 then
    if (MssgUseFile and &h80)=0 then
		' If you do not use message definition file, check SF-Code on
		' your own, determine necessity of sending secondary message,
		' and send it if necessary.
		' メッセージ定義ファイルを使用しない場合、自力で SF-Code を調べ
		' ２次メッセージの送出の必要性を判断し、必要な場合は送出する。
      if      xsf=(&h8100+ 1) and OType=0 then:	SendS1F2H (did,xid)
      else if xsf=(&h8100+ 1) and OType=1 then:	SendS1F2E (did,xid)
      else if xsf=(&h8100+21)		  then:	SendS1F22 (did,xid)
      else if xsf=(&h8200+49)		  then:	SendS2F50 (did,xid)
      else if xsf=(&h8600+11)		  then:	SendS6F12 (did,xid)
      end  if

    else if (xsf and &h8000)<>0 then
		' When using a message definition file, this sample uses the
		' automatic reply function.
		' メッセージ定義ファイルを使用する場合は、本サンプルでは、自動
		' 返信機能を利用する。
      msg=xmsg:	rname="": sname=""
      len=Td._TDSMDMssgAutoRes(Md,0,xhd,msg,rtn,1024,rname,sname,sf)
      if len >= 0 then
	scd = sf / &h0100
	console.writeline("RECV {0} ..  Auto respond {1} [S{2}F{3}]"	_
			,rname,sname,scd,sf and &hff)
	if HeaderBO<>0 then: cmd=&h2000:	end if
	if FuncType =0 then: rtn=Td._TDSCommSend(Fd,cmd,did,sf,xid,msg,len,hd)
	else:		     rtn=Td._TDSUDrvSend(Fd,cmd,did,sf,xid,msg,len,hd)
	end if
	DispData(2,hd,did,sf,xid,msg,len,rtn)
      else
	if len<>(-930) and len<>(-931) then
	  console.writeline("RECV Auto response error ({0})",len)
	end if
      end if
    end if
  end if

  return 0
end function



' ------------------------------------------------------------------------------

private shared sub			_
RecvProcThread(				_
byval	param		as object)

  dim	hd(12),msg(1024) as byte
  dim	rtn,sf,cmd,xid	as integer
  dim	req,did		as integer

  do until Break<>0
    req=0
    if HeaderBO<>0 then: cmd=&h2000
    else:		 cmd=&h0000
    end if
    if FuncType =0 then: rtn=Td._TDSCommRecv(Fd,cmd,did,sf,xid,msg,1024,hd)
    else:		 rtn=Td._TDSUDrvRecv(Fd,cmd,did,sf,xid,msg,1024,hd)
    end if
    if rtn=(-951) then
      Sleep(100)
    else
      if (-1000)<rtn and rtn<(-959) then	req=(-rtn)-900
      CBRecvProc(req,rtn,did,sf,xid,hd,msg)
    end if
  loop

end sub



' ==============================================================================
' Main process -----------------------------------------------------------------

public shared function			_
Main(					_
byval	argv()		as string)	_
			as integer

  dim	tvers,svers	as string
  dim	tdate,sdate	as string
  dim	tcomp,scomp	as string
  dim	bits		as integer
  dim	opt		as integer

  Td = new TDS
  ' ----------------------------------------------------------------------------
  tvers="":	svers=""	' Display TDS information
  tdate="":	sdate=""	' This code has nothing to do with running TDS.
  tcomp="":	scomp=""
  bits=Td._TDSGetInform(tvers,svers,tdate,sdate,tcomp,scomp)
  console.writeline("Version ={0,-20} {1,-20}"	,tvers,svers)
  console.writeline("Date    ={0,-20} {1,-20}"	,tdate,sdate)
  console.writeline("Compile ={0,-20} {1,-20}"	,tcomp,scomp)
  console.writeline("#of Bit ={0}"		,bits)
  ' ----------------------------------------------------------------------------

  ' ----------------------------------------------------------------------------
  opt=0				' Analysis of running parameters
  if FuncType		<>0	then	opt = opt Or &h0001
  if HeaderBO		<>0	then	opt = opt Or &h0002
  if MssgDispType	<>&h00	then	opt = opt Or &h0004
  if MssgUseNextL	<>0	then	opt = opt Or &h0008
  if MssgUseFile	<>&h00	then	opt = opt Or &h0010
  if UseRecvThrd	<>0	then	opt = opt Or &h0020
  if SyncStatus		<>0	then	opt = opt Or &h8000
  if     argv.Length>1	then
    if      string.Compare (argv(1).Substring(0,1),"x",True)=0 then
      opt = Convert.ToInt32(argv(1).Substring(1  ),16)
    else if string.Compare (argv(1).Substring(0,1),"0",True)=0 and
	    string.Compare (argv(1).substring(1,1),"x",True)=0 then
      opt = Convert.ToInt32(argv(1).Substring(2  ),16)
    else
      opt = Convert.ToInt32(argv(1))
    end if
    if (opt and &h0001)<>0 then FuncType    =1:	   else FuncType    =0
    if (opt and &h0002)<>0 then HeaderBO    =1:	   else HeaderBO    =0
    if (opt and &h0004)<>0 then MssgDispType=&h20: else MssgDispType=&h00
    if (opt and &h0008)<>0 then MssgUseNextL=1:	   else MssgUseNextL=0
    if (opt and &h0010)<>0 then MssgUseFile =&h80: else MssgUseFile =&h00
    if (opt and &h0020)<>0 then UseRecvThrd =1:	   else UseRecvThrd =0
    if (opt and &h8000)<>0 then SyncStatus  =1:	   else SyncStatus  =0
  end if
  if	 argv.Length>2	then	SendWait    =Convert.ToInt32(argv(2))
  if	 argv.Length>3	then	SendSleep   =Convert.ToInt32(argv(3))

  console.writeline("option      =0x{0,0:x2},{1}"	,opt,opt)
  console.writeline("FuncType    ={0}"			,FuncType)
  console.writeline("HeaderBO    ={0}"			,HeaderBO)
  console.writeline("MssgDispType=0x{0,0:x2}"		,MssgDispType)
  console.writeline("MssgUseNextL={0}"			,MssgUseNextL)
  console.writeline("MssgUseFile =0x{0,0:x2}"		,MssgUseFile)
  console.writeline("UseRecvThrd ={0}"			,UseRecvThrd)
  console.writeline("SyncStatus  ={0}"			,SyncStatus)
  console.writeline("SendWait    ={0}"			,SendWait)
  console.writeline("SendSleep   ={0}"			,SendSleep)
  ' ----------------------------------------------------------------------------

  if	  argv.Length<1 then
    Usage()

  else if argv(0)<>"h" and argv(0)<>"e" then
    Usage()

  else
    if argv(0)="h" then: Host ()
    else:		 Equip()
    end if
  end if

  return 0
end function


' ------------------------------------------------------------------------------

private shared sub	_
Usage()

  console.writeline("")
  console.writeline("Usage: VBIo {h|e} [option [send_wait [send_sleep]]]")
  console.writeline("")
  console.writeline("  option")
  console.writeline("   F           54 3210")
  console.writeline("  +----+----+----+----+")
  console.writeline("   |           || |||+-- Function to use")
  console.writeline("   |           || |||    =0: _TDSCommXxxxx()           1:_TDSUDrvXxxx()")
  console.writeline("   |           || ||+--- SECS Header Byte order")
  console.writeline("   |           || ||     =0: System order              1: Network order")
  console.writeline("   |           || |+---- Format for displaying messages in SECS list format")
  console.writeline("   |           || |      =0: TDS Format                1: SML Format")
  console.writeline("   |           || +----- Whether to use MssgNextL() for SECS message display")
  console.writeline("   |           ||        =0: Not use                   1: Use")
  console.writeline("   |           |+------- Whether to use the SECS message definition file")
  console.writeline("   |           |         =0: Not use                   1: Use")
  console.writeline("   |           +-------- Whether to execute SECS message reception in a dedicated thread")
  console.writeline("   |                     =0: No                        1: Yes")
  console.writeline("   +-------------------- Synchronize connection status")
  console.writeline("                         =0: No                        1: Yes")
  console.writeline("  send_wait   : Message sending interval     ({0}ms)\n",SendWait)
  console.writeline("  send_sleep  : Wait time                    ({0}ms)\n",SendSleep)
  console.writeline("")
end sub



' ==============================================================================
' Host side process ------------------------------------------------------------

private shared sub	_
Host()

  dim	hd(12),msg(1024) as byte
  dim	th		as Thread
  dim	str		as string
  dim	rtn,req,omd	as integer
  dim	sf,cmd		as integer
  dim	xid,xids,mno	as integer
  dim	did,dids	as integer
  dim	stat,i		as integer

  OType=0:	Break=0:	omd=&h0002:	sf=0
  if SyncStatus	<>0 then	omd=&h1002
  if FuncType	= 0 then: Fd=Td._TDSCommOpen(omd,PARAMFILE,"HOST")
  else:			  Fd=Td._TDSUDrvOpen(omd,PARAMFILE,"HOST",UDRV_MASK)
  end if
  if Fd<0 then							goto Conclude
  console.writeline("(H) Opened ({0})",Fd)
  if (MssgUseFile and &h80)<>0 then Md=Td._TDSMDMssgInitialize(&h4000,Fd,"")

  if UseRecvThrd<>0 then
    th=new Thread(new ParameterizedThreadStart(AddressOf RecvProcThread))
    th.Start("")
  end if

  do
    rtn=0
    if UseRecvThrd=0 then: console.write("Req (0:Exit 1:Recv 2:Send) : ")
    else:		   console.write("Req (0:Exit 2:Send 3:Continuous) : ")
    end if
    str=console.readline()
    req=Integer.Parse(str)
    if	    req=0 then:						exit do
    else if req=1 then
      if HeaderBO<>0 then: cmd=&h2000
      else:		   cmd=&h0000
      end if
      if FuncType =0 then: rtn=Td._TDSCommRecv(Fd,cmd,did,sf,xid,msg,1024,hd)
      else:		   rtn=Td._TDSUDrvRecv(Fd,cmd,did,sf,xid,msg,1024,hd)
      end if
      if rtn>=0 then
	dids=did
	xids=xid
      end if
      DispData(1,hd,did,sf,xid,msg,rtn,rtn)

    else if req=2 then
      if UseRecvThrd=0 then
	console.write("Message(1:S1F1 2:S1F21 3:S2F49  6:S1F2 7:S1F22 8:S6F12) : ")
      else
	console.write("Message(1:S1F1 2:S1F21 3:S2F49) : ")
      end if
      str=console.readline()
      mno=Integer.Parse(str)
      select case mno
	case 1: rtn=SendS1F1 ()
	case 2: rtn=SendS1F21()
	case 3: rtn=SendS2F49()
	case 6: rtn=SendS1F2H(dids,xids)
	case 7: rtn=SendS1F22(dids,xids)
	case 8: rtn=SendS6F12(dids,xids)
      end select

    else if req=3 then
      Break=0:	i=0
      do until Break<>0
	Sleep(SendWait)
	if FuncType =0 then:	stat=Td._TDSCommStatus(Fd,0)
	else:			stat=Td._TDSUDrvStatus(Fd,0)
	end if
	if stat=3 then
	  rtn=SendS2F49()
	  if rtn<0 then
	    console.writeline("(H) Send error ({0})\n",rtn): Sleep(ERROR_SLEEP)
	  end if
	  if (i mod SEND_NO)=0 then			     Sleep(SendSleep)
	end if
	i=i+1
      loop
      rtn=0
    end if

    if rtn<(-999) or ((-900)<rtn and rtn<0) then
      console.writeline("(H) I/O Error ({0})"	,rtn)
    end if
  loop

Conclude:
  Break=1
  if Fd>0 then
    if FuncType=0 then: Td._TDSCommClose(Fd,&h0000)
    else:		Td._TDSUDrvClose(Fd,&h0000)
    end if
  else:			console.writeline("(H) Error ({0})",Fd)
  end if
  if Md>0 then		Td._TDSMDMssgTerminate(Md,0)
end sub



' ==============================================================================
' Equipment side process -------------------------------------------------------

private shared sub	_
Equip()

  dim	hd(12),msg(1024) as byte
  dim	th		as Thread
  dim	str		as string
  dim	rtn,req,omd	as integer
  dim	sf,cmd		as integer
  dim	xid,xids,mno	as integer
  dim	did,dids	as integer
  dim	stat,i		as integer

  OType=1:	Break=0:	omd=&h0002:	sf=0
  if SyncStatus	<>0 then	omd=&h1002
  if FuncType	= 0 then: Fd=Td._TDSCommOpen(omd,PARAMFILE,"EQUIP"):
  else:			  Fd=Td._TDSUDrvOpen(omd,PARAMFILE,"EQUIP",UDRV_MASK):
  end if
  if Fd<0 then							goto Conclude
  console.writeline("(E) Opened ({0})",Fd)
  if (MssgUseFile and &h80)<>0 then Md=Td._TDSMDMssgInitialize(&h4000,Fd,"")

  if UseRecvThrd<>0 then
    th=new Thread(new ParameterizedThreadStart(AddressOf RecvProcThread))
    th.Start("")
  end if

  if SECS_MODE<>0 and FuncType=0 then	'In case of HSMS and use TDSCommXxxxx()
					' HSMS で TDSCommXxxxx() 使用の場合
    if Td._TDSCommSend(Fd,&h0100,0,0,0,msg,0,hd)<0 then		goto Conclude
    console.writeline("(E) Connected")
    if Td._TDSCommSend(Fd,&h0200,0,0,0,msg,0,hd)<0 then		goto Conclude
    console.writeline("(E) Selected")
  end if

  do
    rtn=0
    if UseRecvThrd=0 then: console.write("Req (0:Exit 1:Recv 2:Send) : ")
    else:		   console.write("Req (0:Exit 2:Send 3:Continuous) : ")
    end if
    str=console.readline()
    req=Integer.Parse(str)
    if	    req=0 then:						exit do
    else if req=1 then
      if HeaderBO<>0 then: cmd=&h2000
      else:		   cmd=&h0000
      end if
      if FuncType =0 then: rtn=Td._TDSCommRecv(Fd,cmd,did,sf,xid,msg,1024,hd)
      else:		   rtn=Td._TDSUDrvRecv(Fd,cmd,did,sf,xid,msg,1024,hd)
      end if
      if rtn>=0 then
	dids=did
	xids=xid
      end if
      DispData(1,hd,did,sf,xid,msg,rtn,rtn)

    else if req=2 then
      if UseRecvThrd=0 then
	console.write("Message(1:S1F1 2:S1F21 3:S6F11  6:S1F2 7:S1F22 8:S2F50) : ")
      else
	console.write("Message(1:S1F1 2:S1F21 3:S6F11) : ")
      end if
      str=console.readline()
      mno=Integer.Parse(str)
      select case mno
	case 1: rtn=SendS1F1 ()
	case 2: rtn=SendS1F21()
	case 3: rtn=SendS6F11()
	case 6: rtn=SendS1F2E(dids,xids)
	case 7: rtn=SendS1F22(dids,xids)
	case 8: rtn=SendS2F50(dids,xids)
      end select

    else if req=3 then
      Break=0:	i=0
      do until Break<>0
	Sleep(SendWait)
	if FuncType =0 then:	stat=Td._TDSCommStatus(Fd,0)
	else:			stat=Td._TDSUDrvStatus(Fd,0)
	end if
	if stat=3 then
	  rtn=SendS6F11()
	  if rtn<0 then
	    console.writeline("(E) Send error ({0})\n",rtn): Sleep(ERROR_SLEEP)
	  end if
	  if (i mod SEND_NO)=0 then			     Sleep(SendSleep)
	end if
	i=i+1
      loop
      rtn=0
    end if

    if rtn<(-999) or ((-900)<rtn and rtn<0) then
      console.writeline("(E) I/O Error ({0})"	,rtn)
    end if
  loop

  if   SECS_MODE<>0 then		' In case of HSMS, Shutdown process
					' HSMS 接続の場合、切断処理
    if FuncType= 0 then:	rtn=Td._TDSCommStatus(Fd,0)
    else:			rtn=Td._TDSUDrvStatus(Fd,0)
    end if
    if rtn	= 3 then
    ' Deselect request is not performed. (Of course you may go. However SEMI
    ' claims that HSMS-SS does not perform Deselect request.)
    ' Deselect request は行わない。 (もちろん行ってもよい。SEMI では HSMS-SS に
    ' おいて、Deselect request は行わない、としている。)
    ' if FuncType=0 then: rtn=Td._TDSCommSend(Fd,&h0800,0,0,0,msg,0,hd)
    ' else:		  rtn=Td._TDSUDrvSend(Fd,&h0800,0,0,0,msg,0,hd)
    ' end if
    ' if rtn< 0 then						goto Conclude
    ' console.writeline("(E) Deselected")
      if FuncType=0 then: rtn=Td._TDSCommSend(Fd,&h0900,0,0,0,msg,0,hd)
      else:		  rtn=Td._TDSUDrvSend(Fd,&h0900,0,0,0,msg,0,hd)
      end if
      if rtn< 0 then						goto Conclude
      console.writeline("(E) Separated")
    end if
  end if

Conclude:
  Break=1
  if Fd>0 then
    if FuncType=0 then: Td._TDSCommClose(Fd,0)
    else:		Td._TDSUDrvClose(Fd,0)
    end if
  else:			console.writeline("(E) Error ({0})",Fd)
  end if
  if Md>0 then		Td._TDSMDMssgTerminate(Md,0)
end sub

end class

end namespace
