COMMENT @%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

	Copyright (c) Geoworks 1996 -- All Rights Reserved

PROJECT:	General FSM Engine
MODULE:		FSM Library Interface
FILE:		fsm.def

AUTHOR:		Eugene Ng, Jun  5, 1996

MACROS:
	Name			Description
	----			-----------

REVISION HISTORY:
	Name	Date		Description
	----	----		-----------
	EN	6/ 5/96   	Initial revision


DESCRIPTION:
	
		
	$Id: fsm.def,v 1.1 97/04/04 14:21:44 newdeal Exp $

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%@


SetDef	__FSMLIB

StartLibrary	fsm


;-----------------------------------------------------------------------------
;		Constants & Structures
;-----------------------------------------------------------------------------


; **************************************************************************
;			        Instructions
; **************************************************************************
; The FSM Engine requires the user to supply a "state table." A state table is
; a table of FsmStateStruct. The ordering of the FsmStateStruct's in the state
; table is important. They have to be listed in the same order as their
; FsmStateSymbol's are enum'ed (The first two are always FSST_START and
; FSST_STOP). Each FsmStateSymbol *must* have a corresponding FsmStateStruct
; in the state table. 
;
; Note that application program that uses the FSM library should put the
; state table and the other related structures in a separate resource, and
; this resource must be locked down before fsmEngineInvoke is called.
;
; Each state in the FSM, with the exception of FSST_STOP, must have at least
; one transition leading to another state. This transition may be
; unconditional (epsilon transition).
;
; Non-deterministic FSM are not acceptable.
;
;
; e.g.	A state table that has only one state, FSST_ONE, besides the default
;	FSST_START and FSST_STOP will have the following:
;
;	Defining the FsmStateSymbol:
;	FSST_ONE		enum	FsmStateSymbolType
;
;	Defining the State Table:
;	stateTable	FsmStateStruct \
;			<FSST_START,
;			offset startEntryFunc,
;			offset startWaitFunc,
;			offset startExitFunc,
;			offset startErrorFunc,
;			offset startTransitionStruct,
;			startNumTransitions,
;			offset startExtra>,
;
;			<FSST_STOP,
;			    ...
;			offset stopExtra>,
;
;			<FSST_ONE,
;			    ...
;			offset oneExtra>
;
;
;	startTransitionStruct	FsmTransitionStruct	\
;			<FSST_ONE,
;			offset startToOneTest,
;			offset startToOneOutput>,
;
;			<FSST_STOP,
;			offset startToStopTest,
;			offset startToStopOutput>
;
;	oneTransitionStruct ....
;
;
; State functions are called by the FSM Engine in the order of: entry, wait,
; test, output (if any), and finally exit. In the event when an error
; occurred, the error function is called and the error function decides
; the next action to take.
;
; When determining what transition to make, the FSM Engine calls the test
; functions in the list of FsmTransitionStructs in the order they are listed
; until a good transition is found or all the FsmTransitionStructs have been
; visited (therefore an error). If a good transition is found, the
; corresponding output function (if any) will be called.
;
; Each state (except the stop state) must have at least one transition
; (can be a epsilon transition) leading out of the state. To implement an
; epsilon transition, all the user needs is a test function that will
; always return carry cleared.
;
; Some state functions (entry, wait, output, exit) that are not useful to a
; state may be left out as NULL_FUNCTION.
;
; The entry function of the start state (FSST_START) is always called first,
; and therefore all common setup work can be done there.
;
; The entry function of the stop state (FSST_STOP) is always called last,
; right before the FSM stops. Common clean up work can be conveniently done
; in this function.
;
; ***************************************************************************



; ***************************************************************************
;				Constants
; ***************************************************************************


;
; used as a place holder for left out functions
;
NULL_FUNCTION		equ	0xffff


;
; this constant is very important to the operation of the FSM Engine and
; *must* be exactly the same as the size of an FsmStateStruct. See CheckHack
; below
;
SIZE_OF_FSM_STATE_STRUCT	equ	16


;
; Each state of any acceptable FSM must be uniquely identified by a symbol
; of type FsmStateSymbolType. In addition, FSST_START and FSST_STOP must
; exist to indicate the start and stop states (already pre-defined).
;
FsmStateSymbolType		etype	word, 0, SIZE_OF_FSM_STATE_STRUCT
FSST_START			enum	FsmStateSymbolType
FSST_STOP			enum	FsmStateSymbolType


;
; One FsmTransitionStruct is required for each transition edge in the FSM.
; Therefore, there *must* be at least one FsmTransitionStruct for each state
; except for the stop state: FSST_STOP.
;
; FTS_test_func determines whether the transition to FTS_next_state should
; be taken; while FTS_output_func produces the necessary output associated
; with the transition iff the transition is taken.
;
FsmTransitionStruct		struct

	FTS_next_state		FsmStateSymbolType
	;
	; The next state to go to iff the transition is taken.
	;

	FTS_test_func		nptr.near	NULL_FUNCTION
	;
	; The function to call to determine if this transition is to be taken.
	;
	;	PASS:	ax	= input
	;		cx:dx	= extra inputs if necessary
	;		ds:[di] = current FsmStateStruct
	;		ds:[si] = current FsmTransitonStruct
	;
	;	RETURN:	carry cleared if the transition should be taken
	;		carry set if the transition is not to be taken
	;			and ax = FsmErrorCodeType
	;
	;	DESTROY: nothing
	;

	FTS_output_func		nptr.near	NULL_FUNCTION
	;
	; The function to call to generate the output for this transition.
	;
	;	PASS:	ds:[di] = current FsmStateStruct
	;		ds:[si] = current FsmTransitionStruct
	;
	;	RETURN:	carry set if error, cleared otherwise
	;		ax	= FsmErrorCodeType
	;		cx:dx	= Additional error info if necessary
	;
	;	DESTROY: nothing
	;

FsmTransitionStruct		ends


;
; A FsmStateStruct defines the properties of a state
;
FsmStateStruct			struct

	FSS_state		FsmStateSymbolType
	;
	; The state symbol of this state
	;

	FSS_entry_func		nptr.near	NULL_FUNCTION
	;
	; The function to call on entry of this state. Everything the
	; state needs to accomplish should be here.
	;
	;	PASS:	ds:[di]	= current FsmStateStruct
	;
	;	RETURN:	carry set if error, cleared otherwise
	;		ax	= FsmErrorCodeType
	;		cx:dx	= additional error info if necessary
	;
	;	DESTROY: nothing
	;

	FSS_wait_func		nptr.near	NULL_FUNCTION
	;
	; The function to call after entry to wait for inputs. Timeout is
	; possible, and should use the error code to reflect a timeout.
	;
	;	PASS:	ds:[di]	= current FsmStateStruct
	;
	;	RETURN:	carry set if error, cleared otherwise
	;		ax	= FsmErrorCodeType if error
	;		     or	= Input value if no error
	;		cx:dx	= additional error info if error
	;		     or	= additional input if no error
	;
	;	DESTROY: nothing
	;

	FSS_exit_func		nptr.near	NULL_FUNCTION
	;
	; The function to call before exiting the current state. All common
	; cleanup work should be done here.
	;
	;	PASS:	ds:[di]	= current FsmStateStruct
	;
	;	RETURN:	carry set if error, cleared otherwise
	;		ax	= FsmErrorCodeType
	;		cx:dx	= additional error info
	;
	;	DESTROY: nothing
	;

	FSS_error_func		nptr.near	NULL_FUNCTION
	;
	; The function to call when any other state function returns error.
	; The supplier of this function must then diagnose the problem and
	; inform the FSM Engine of the next action.
	;
	;	PASS:	ax	= FsmErrorCodeType
	;		cx:dx	= additional error info
	;		bx	= FsmStepType when the error occurred
	;		ds:[di]	= current FsmStateStruct
	;
	;	RETURN:	bx	= FsmNextActionType
	;
	;	DESTROY: nothing
	;

	FSS_transitions		nptr.FsmTransitionStruct
	;
	; This points to the beginning of a table of FsmTransitionStruct,
	; which define the possible transitions, and supply the necessary
	; query functions to determine if any transition is to be taken.
	; In addition, output functions are also supplied if needed.
	;

	FSS_num_transitions	word		0
	;
	; The total number of FsmTransitionStruct's for this state
	;

	FSS_extra		nptr
	;
	; Any extra data structure that this state wants to keep. The
	; FSM Engine will not be responsible for maintenance of these
	; data. User can put, for examples, input and output strings here
	; and greatly simplify transition test functions and output functions.
	;

FsmStateStruct			ends


;
; Make sure we counted the size right. This is important because the FSM
; Engine uses the size of FsmStateStruct to calculate the offset of each
; FsmStateStruct in the state table.
;
CheckHack	< SIZE_OF_FSM_STATE_STRUCT eq size FsmStateStruct >


;
; The user of the FSM Engine can define their own FsmErrorCodeType to
; identify different error conditions. The following error codes are defined
; for use with the auxiliary functions in the FSM Library.
;
FsmErrorCodeType		etype	word, 0, 1

FECT_SERIAL_PORT_UNSUPPORTED	enum	FsmErrorCodeType
; The SerialPortNum supplied is not supported by the auxiliary function.

FECT_SERIAL_IO_TIMEOUT		enum	FsmErrorCodeType
; Timeout occurred during a read/write

FECT_SERIAL_FORMAT_BAD		enum	FsmErrorCodeType
; The SerialFormat structure supplied is malformed.

FECT_SERIAL_PORT_OPEN_FAILED	enum	FsmErrorCodeType
; DR_STREAM_OPEN call to the serial driver has failed

FECT_SERIAL_PORT_NOT_OPENED	enum	FsmErrorCodeType
; The user has attempted to use a serial port that is not yet opened

FECT_SERIAL_PORT_ALREADY_OPENED	enum	FsmErrorCodeType
; The user attempted to open a serial port more than once

FECT_SERIAL_END_MARKER_NOT_FOUND	enum	FsmErrorCodeType
; The entire input buffer is full but still no end marker char in sight.


;
; Once an error occurred, the supplied error handling function must diagnose
; the problem and inform the FSM Engine to perform one of the following
; actions. The FSM Engine will only understand the following actions. Therefore
; the user should not attempt to expand this list.
;
; Please pay extra attention to the (*) notes below. Not all FsmNextActionType
; can be returned by an error function from all FsmStageType's. For example,
; it simply doesn't make any sense to try to jump into the output stage when
; and error occurred at the entry stage.
;
FsmNextActionType		etype	word, 0, 2

FNAT_START			enum	FsmNextActionType
; To restart the FSM from the start state FSST_START
; (*) Legal FsmStageType from which this action can be taken: Any

FNAT_ENTRY			enum	FsmNextActionType
; To re-enter the current state, recalling entry function and the whole smash.
; (*) Legal FsmStageType from which this action can be taken: Any

FNAT_WAIT			enum	FsmNextActionType
; To wait for the current state's expected input values again.
; (*) Legal FsmStageType from which this action can be taken: FST_WAIT,
;     FST_TRANS, FST_OUTPUT, FST_EXIT (Returning it from FST_ENTRY won't break
;     the execution of the FSM Engine, but it makes little sense)

FNAT_OUTPUT			enum	FsmNextActionType 
; To try to output again.
; (*) Legal FsmStageType from which this action can be taken: FST_OUTPUT,
;     FST_EXIT

FNAT_EXIT			enum	FsmNextActionType 
; To try calling the current state's exit function again.
; (*) Legal FsmStageType from which this action can be taken: FST_EXIT

FNAT_STOP			enum	FsmNextActionType
; To enter the stop state FSST_STOP and halt the FSM
; (*) Legal FsmStageType from which this action can be taken: Any


;
; This is used to indicate to the error handling function what stage
; in the FSM the FSM Engine is currently in.
;
FsmStageType			etype	word, 0, 1

FST_ENTRY			enum	FsmStageType
; Error occurred when calling entry function

FST_WAIT			enum	FsmStageType
; Error occurred when waiting for input

FST_TRANS			enum	FsmStageType
; None of the transition test functions returns good for the given input

FST_OUTPUT			enum	FsmStageType 
; Error occurred when calling the output function

FST_EXIT			enum	FsmStageType
; Error occurred when calling the exiting function



;-----------------------------------------------------------------------------
;		Library Routines
;-----------------------------------------------------------------------------

global	fsmEngineInvoke:far
;
; Invoke the FSM Engine on a given state table
;
;	PASS:		bx	= vseg where the state functions lie
;			ds	= segment of state table (must be locked down)
;			di	= offset to base of state table
;	RETURN:		nothing
;	DESTROYED:	nothing
;
;	Note: 1.All FsmStateStruct and FsmTransitionStruct must be
;		in ds and *must* be locked down.
;		All supplied functions must be in the vseg bx.
;
;	      2.All common initialization of the FSM should be done
;		in FSST_START's entry_func. All common clean up
;		should be done in FSST_STOP's entry_func.


global	fsmEngineGeneralSerialInit:far
;
; Perform initialization before using the serial port
;
;	PASS:		nothing
;	RETURN:		nothing
;	DESTROYED:	nothing


global	fsmEngineGeneralSerialOpen:far
;
; Open a desired serial port for I/O
;
;	PASS:		bx	= SerialPortNum to open
;			cx	= Input buffer size needed (in bytes)
;			dx	= Output buffer size needed (in bytes)
;	RETURN:		carry set if error, cleared otherwise
;			ax	= FsmErrorCodeType
;	DESTROYED:	nothing
;
;	*Must* be called before using the Input/Output functions
;	Buffer sizes must be at least as big as any conceivable
;	input/output sequence.
;
;	In addition, fsmEngineGeneralSerialInit must be called first.


global	fsmEngineGeneralSerialSetFormat:far
;
; Set the format of the opened serial port
;
;	PASS:		al	= SerialFormat to set
;			ah	= SerialMode to set
;			bx	= SerialPortNum
;			cx	= SerialBaud
;	RETURN:		carry set if error, cleared otherwise
;			ax	= FsmErrorCodeType
;	DESTROYED:	nothing
;
;	*Must* call fsmEngineGeneralSerialOpen first


global	fsmEngineGeneralSerialClose:far
;
; Close an opened serial port
;
;	PASS:		bx	= SerialPortNum to close
;	RETURN:		carry set if error, cleared otherwise
;			ax	= FsmErrorCodeType
;	DESTROYED:	nothing
;
;	All pending I/O will be discarded
;	*Must* call fsmEngineGeneralSerialInit first


global	fsmEngineGeneralSerialIn:far
;
; General serial input function to be used by FSMs
;
;	PASS:		bx	= SerialPortNum to read
;			cx	= size of passed buffer (must be big enough
;				  to hold input)
;			dl	= end marker character to look for
;			ds:si	= buffer to put input data (see note below)
;			di	= # of retries (each retry takes 1/2 seconds)
;				  (can be used to implement a timeout)
;	RETURN:		carry set if error, cleared otherwise
;			ax	= FsmErrorCodeType
;			if no error:	ds:si	= input
;	DESTROYED:	nothing
;
;	*Must* call fsmEngineGeneralSerialOpen first
;
;	IMPORTANT:	Caller must use the *same* buffer (ds:si) for
;			*all* calls to fsmEngineGeneralSerialIn and must
;			*not* alter the content of this buffer _if_ they
;			wish broken input segments across calls to be
;			recognized.
;
;			e.g. Suppose you are expecting abc. and xyz.
;			It could happen that during the first call,
;			abc.xy is received. If the caller pass the same
;			buffer again for the next call, xyz. can be
;			correctly recognized.
;
;			If a new buffer (different ds and/or different si)
;			is passed, this procedure will still function
;			correctly, only that all previously received partial
;			input (xy) will be lost.


global	fsmEngineGeneralSerialOut:far
;
; General serial output function to be used by FSMs
;
;	PASS:		bx	= SerialPortNum to write
;			cx	= number of bytes to write
;			ds:si	= buffer from which to write
;			di	= # of retries (each retry takes 1/2 seconds)
;				  (can be used to implement a timeout)
;	RETURN:		carry set if error, cleared otherwise
;			ax	= FsmErrorCodeType
;	DESTROYED:	nothing
;
;	*Must* call fsmEngineGeneralSerialOpen first.


global	fsmEngineNullTransitionTest:far
;
; "Intelligent" function that always returns good as a null transition test
;
;	PASS:		nothing
;	RETURN:		always carry cleared
;	DESTROYED:	nothing
;
;	FSM Engine users are probably better off writing their own
;	null transition test function to avoid the far call


global	fsmEngineGeneralCompare:far
;
; Compare to see if two strings are the same, up to the end marker character
;
;	PASS:		ax:bp	= string 1
;			cx:dx	= string 2
;			bl	= end marker character
;	RETURN:		carry cleared if matched, set otherwise
;	DESTROYED:	nothing



EndLibrary	fsm
