/*-=-=-=-=-=-=-=-=-=-=-=- RCCL/RCI Notice of Copyright -=-=-=-=-=-=-=-=-=-=-*
 *									    *
 *	Copyright (C) 1987, 1991 by John E. Lloyd.			    *
 *									    *
 *	Information on copyright permissions, as well as a complete	    *
 *	disclaimer of warranty, is given in the file COPYRIGHT.		    *
 *									    *
 *-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/

#ifndef _RCITASK
#define _RCITASK

#include "../h/cdefs.h"
#include "../h/robot_jls.h"
#include "../h/robotControl.h"
#include "../h/IOdevice.h"

/* If MAX_RCI_TASKS is increased to more than 255, check out hashTable.h */
#define MAX_RCI_TASKS	8	/* max number of RCI tasks at any time */
/* #define MAX_MEM_LABELS 16	/* max memory sections attached to a task */
#define TASK_NAME_SIZE	31	/* max length of a task name */
#define MAX_TASKROBOTS	4	/* max robots attached to a task */

/* control modes */

#define IDLE		1	/* task is waiting to start */
#define ACTIVE		2	/* task is running */
#define RELEASING	3	/* task is waiting to finish wrapping up */

#define ON_CLOCK	1	/* schedule disciplines */
#define ON_FUNCTION	2
#define ON_TRIGGER	3
#define ON_SIGNAL	4

#define DEFAULT_LAG_COUNT	0
#define DEFAULT_BLK_COUNT	2
#define DEFAULT_LAG_WINDOW	100
#define DEFAULT_INTERVAL	100

#define RBT_NORMAL	1	/* codes for robot release function */
#define RBT_SOFTERROR	2
#define RBT_HARDERROR	3

#define DEFAULTVALUE	-2

typedef struct _RCI_TCB {

	/* ---- Fields accessible to the user ---- */

	/* state variables: */

	char controlMode;	/* ACTIVE or IDLE */
	 int cycleCount;	/* number of elapsed control cycles */

	/* control parameters */

	 int scheduleDisp;	/* scheduling discipline */
	 int maxBlkCount;	/* max time task can block */
	 int maxLagCount;	/* max number of posted run requests */
	 int lagWindow;		/* window over which to eval lag timeout */

	 int interval;		/* task wakeup rate */
	 int offset;		/* task wakeup offset */

	/* control and robot interface functions */

	 int (*triggerFxn)();	/* trigger function */
	 int triggerArg;	/* argument for trigger function */

	 int (*wakeupFxn)();	/* address of the wakeup function */
	 int wakeupArg;		/* argument for the wakeup function */

	 int (*startupFxn)();	/* task startup function */
	 int (*controlFxn)();	/* address of the control function */
	 int (*releaseFxn)();	/* task release function */
	 int controlArg;	/* argument to the control function */
	
	/* information variables and flags */

	 int lastTime;		/* the last time the task ran */
unsigned char newRate;		/* new rate request */

	/* user function support */

      void *sharedMem;		/* pointer to a shared section */
      void *globalMem;		/* pointer to a global section */
      void *privateMem;	/* pointer to private memory area */
	 int fxnNotice;		/* internal function error code */

	/* ---- fields used internally ---- */

	 int (*executeFxn)();	/* function to execute */
	 int executeArg;	/* argument to execute function */
	 int executeRet;	/* function return value */

	/* request flags */

	char cmodeReq;		/* request to change control mode */
	char abortReq;		/* request to abort */
	char nrateReq;		/* request to change rates */
	char blockReq;		/* request to block until task executes */

	/* internal information */

	 int blkTimeout;	/* time at which we will blk timeout */
       float lagAverage;	/* average lag per cycle */

	 int newInterval;	/* new rate interval */
	 int newOffset;		/* new offset */

	 int runTime;		/* next time the task should run */
	 int startTime;		/* "time 0" for the task */

	 int triggerAst;	/* trigger AST handle */
	 int timerAst;		/* timer AST handle */
	 int interruptSet;	/* records an interrupt or signal occurred */

	 int msg[16];		/* spare user message area */
} RCI_TCB;

#define ERROR_STACK_SIZE 1024	/* size of the each task's error stack */

typedef struct _RCI_RBT {
	struct _RCI_RBT *next;	/* internal list pointer */

	int id;			/* robot identifier */
	JLS *jls;		/* pointer to robot joint level parameters */
	HOW *how;		/* robot state variable */
	CHG *chg;		/* robot command 'blackboard' */
	KYN *kyn;		/* pointer to user defined kinematic params */
	void *var;		/* pointer to user defined state variable area */
	int kynSize;		/* size of the user defined kinematic params */
	int varSize;		/* size of the user defined variable area */

	int class;		/* robot class */
	char *name;		/* pointer to robot name */

	int (*startup)();	/* robot startup function */
	int (*release)();	/* robot release function */
	int (*input)();		/* robot input function */
	int (*output)();	/* robot output function */
	int (*wakeup)();	/* robot wakeup function */
	int (*ready)();		/* robot ready function */

	int wakeupArg;		/* argument for wakeup function */
	int readyArg;		/* argument for ready function */

	void *dev;		/* pointer to the I/O device */
	int idev;		/* pointer to interrupt fd */

	int notice;		/* scratch area for interface functions */
} RCI_RBT;

typedef struct _RCI_DESC {
	char taskID;		/* ID of the RCI task */
	unsigned long taskCode; /* Code of the RCI task */
	char cpu;		/* processor the thing is running on */
	int interruptNumber;	/* interrupt unit the device is attached to */
	int signalNumber;	/* for connecting task to UNIX signals */

	RCI_TCB   *tcb;		/* pointer to system control data */
	RCI_RBT   *rbt;		/* pointer to robot specific data */
	void *   msg;		/* message root */
	void *   dev;		/* pointer to the IO device */
	void *	  estk;		/* pointer to the error stack */

	RCI_RBT *rbts[MAX_TASKROBOTS]; /* robots attached to task */
	int numRobots;		/* number of robots attached to task */
	int devAttached;	/* is a device attached */

} RCI_DESC;

extern unsigned char *rciIOpage;
extern unsigned char *rciBus;

#ifndef PROTO
#ifndef NO_PROTOTYPES
#define PROTO(x) x
#else
#define PROTO(x) ()
#endif
#endif

#ifndef NO_PROTOTYPES
#include <sys/time.h>	/* need for a prototype below */
#endif

extern RCI_DESC *getRciTask PROTO((const char*));
extern RCI_DESC *rciDescriptor PROTO((const char*));
extern RCI_DESC *findRciTask PROTO((int));
extern RCI_DESC *getCurrentTask PROTO(());
extern char *rciTaskName PROTO((RCI_DESC*));
extern void *getSharedMemory PROTO((const char*));
extern void *getGlobalMemory PROTO((const char*));
extern void *getLocalMemory PROTO((const char*));
extern void *findSharedMemory PROTO((void*));
extern void *findGlobalMemory PROTO((void*));
extern RCI_RBT *getTaskRobot PROTO((const char*));
extern RCI_RBT *findTaskRobot PROTO((int));
extern unsigned long rciAllocCpus PROTO((unsigned long));
extern rciAllocDevice PROTO((RCI_DESC*, struct devAddr*, int));
extern rciDeallocDevice PROTO((RCI_DESC*));
extern rciAttachRobot PROTO((RCI_DESC*, const char*, struct devAddr*));
extern rciDetachRobot PROTO((RCI_DESC*, int));
extern rciBlock PROTO((RCI_DESC*));
extern rciControlFxns PROTO((RCI_DESC*, int(*)(), int(*)(), int(*)(), int));
extern RCI_DESC *rciCreate PROTO((const char*, unsigned long, int simflag));
extern rciClose PROTO(());
extern rciExecute PROTO((RCI_DESC*, int(*)(), int, int*));
extern JLS *rciGetJls PROTO((const char*));
extern KYN *rciGetKyn PROTO((const char*, int*));
extern rciOnInterrupt PROTO((RCI_DESC*));
extern rciTimeReady PROTO((RCI_DESC*));

extern rciPrintVf PROTO((const char*, float*, int));
/* extern rciPrintf PROTO((char*, ...)); */
extern rciPrintToTerminal PROTO((int));
extern rciRate PROTO((RCI_DESC*, int, int));
extern rciTimeout PROTO((RCI_DESC*, int, int, int));
extern rciScheduling PROTO((RCI_DESC*, int, int));

/* extern rciErrorMsg PROTO((RCI_DESC*, int, char*, ...)); */
extern char *rciGetErrorMsg PROTO((RCI_DESC*, int));
extern rciGetErrorCode PROTO((RCI_DESC*, int));
extern rciSetErrorCode PROTO((RCI_DESC*, int, int));
extern rciNumErrors PROTO((RCI_DESC*));
extern rciPopError PROTO((RCI_DESC*));
extern rciClearErrors PROTO((RCI_DESC*));
extern char *rciDumpErrorMsgs PROTO((RCI_DESC*, char*, int));
extern rciPrintErrors PROTO((RCI_DESC*)); 

extern rciSend PROTO((unsigned long, const char*, int));
extern rciReceive PROTO((unsigned long, char*, int, RCI_DESC**));
extern rciFlush PROTO((unsigned long));

extern unsigned long rciSetOptions PROTO((unsigned long));
extern unsigned long rciClearOptions PROTO((unsigned long));
extern unsigned long rciPutOptions PROTO((unsigned long));
extern unsigned long rciGetOptions PROTO((unsigned long));

extern void *rciSharedMemory PROTO((const char*, int, RCI_DESC*));
extern void *rciGlobalMemory PROTO((const char*, int, unsigned long, int));
extern void *rciLocalMemory PROTO((const char*, int, RCI_DESC*));
extern rciSharedData PROTO((void*, int, RCI_DESC*, unsigned long));
extern rciSignal PROTO((int));
extern rciTime PROTO(());
extern float rciTimeInterval PROTO(());
extern rciBadAddr PROTO((void*, int));
extern rciStart PROTO((unsigned long));
extern rciRelease PROTO((unsigned long));
extern rciWakeupOn PROTO((RCI_DESC*, int(*)(), int));
extern rciSetTrigger PROTO((int(*)(), int));
extern simScheduling PROTO((RCI_DESC*));
extern simSetTimer PROTO((int, struct timeval *));
extern simAttachRobot PROTO((RCI_DESC*, const char*, const char*));
extern simRobotsReady PROTO((RCI_DESC*));
/* extern rciAbort PROTO((int,...)); */
extern int (*rciAbortHandler PROTO((int(*)())) )();

extern void *rciMalloc PROTO((int));
extern rciInterruptOpen PROTO((IO_INTERRUPT*,int));
extern rciInterruptClose PROTO((int));
#ifdef LINUX_CFG
extern rciStartJLS();
extern rciStopJLS();
#endif

#endif
