/* -*-C-*-
 * gendef.h -	CANopen; home of generic definitions
 *
 *-----------------------------------------------------------------------
 *
 *                Copyright (c) 1998 JANZ Computer AG
 *                        All Rights Reserved
 *
 * Permission is hereby granted to licensees of JANZ Computer AG
 * products to use or abstract this computer program for the sole
 * purpose of implementing a product based on JANZ Computer AG
 * products.   No other rights to reproduce, use, or disseminate
 * this computer program, whether in part or in whole, are granted.
 *
 * JANZ Computer AG makes no representation or warranties with respect
 * to the performance of this computer program, and specifically
 * disclaims any responsibility for any damages, special or consequential,
 * connected with the use of this program.
 *
 * JANZ Computer AG products are not authorized for use as critical
 * components in life support devices or systems without the express
 * written approval of JANZ Computer AG.
 *
 *-----------------------------------------------------------------------
 *
 * $Id: gendef.h,v 1.1 2001-04-09 13:32:55 tbretz Exp $
 *
 *-----------------------------------------------------------------------
 *
 * $Log: not supported by cvs2svn $
 * Revision 1.7  2000/02/18 11:22:11  jens
 * adding variable in global variable structure: incomingSdoBehaviour
 *
 * Revision 1.6  1999/10/29 11:07:51  gerd
 * Add support for Linux.
 *
 * Revision 1.5  1999/09/16 14:50:02  gerd
 * Add support for PSOS
 *
 * Revision 1.4  1999/09/06 14:20:54  wolfgang
 * Add macros and variable for MS-DOS.
 *
 * Revision 1.3  1999/06/18 12:08:15  jens
 * made VMOD-ICAN/CAN104 dependend headers conditional (CAL_CANOPEN_CLAMPED)
 * made pdoTagTables available at CAL_CANOPEN_CLAMPED-section only
 *
 * Revision 1.2  1999/06/10 14:10:36  wolfgang
 * Add NT40 part for CANopen stuff.
 *
 * Revision 1.1  1999/03/08 16:55:13  jens
 * Initial revision
 *
 *
 *-----------------------------------------------------------------------
 */

#ifndef gendef_DEFINED
#define gendef_DEFINED

#ifdef __cplusplus
extern "C" {
#endif 

#ifdef WIN95 
#include <windows.h>
#endif

#ifdef WIN_NT40 
#include <windows.h>
#endif

#include "icanconf.h"
#include "calconf.h"
#include "cms.h"

#include "bcan.h"

#ifndef CAL_CANOPEN_CLAMPED
#include "mican.h"
#include "dpm.h"
#include "can_lib.h"
#endif 

#include <stdio.h>
#include <string.h>

#ifdef WIN95

#define LCL_SLEEP(sleepTimeInMs) \
	Sleep(sleepTimeInMs)

#define CREATE_SEMAPHORE(pSecure, initCount, maxCount, pName) \
	CreateSemaphore(pSecure, initCount, maxCount, pName);

#define	WAIT_FOR_SEMAPHORE(semId, howLong) \
	WaitForSingleObject(semId, howLong)

#define	RELEASE_SEMAPHORE(semId, count, addrPrevCount) \
	ReleaseSemaphore(semId, count, addrPrevCount)
#endif

	
#ifdef WIN_NT40

#define LCL_SLEEP(sleepTimeInMs) \
	Sleep(sleepTimeInMs)

#define CREATE_SEMAPHORE(pSecure, initCount, maxCount, pName) \
	CreateSemaphore(pSecure, initCount, maxCount, pName);

#define	WAIT_FOR_SEMAPHORE(semId, howLong) \
	WaitForSingleObject(semId, howLong)

#define	RELEASE_SEMAPHORE(semId, count, addrPrevCount) \
	ReleaseSemaphore(semId, count, addrPrevCount)

#endif

#ifdef VXWORKS
#include <taskLib.h>
#include <sysLib.h>

#define INFINITE	0

#define LCL_SLEEP(sleepTimeInMs) \
	taskDelay(((sleepTimeInMs * 100) / (100000 / sysClkRateGet())) + 1)

#define CREATE_SEMAPHORE(pSecure, initCount, maxCount, pName) \
	semBCreate(SEM_Q_FIFO, (SEM_B_STATE)initCount);

#define	WAIT_FOR_SEMAPHORE(semId, howLong) \
	semTake(semId, WAIT_FOREVER)

#define	RELEASE_SEMAPHORE(semId, count, addrPrevCount) \
	semGive(semId)
#endif

#ifdef  MSDOS

#define LCL_SLEEP(sleepTimeInMs) \
	delay(sleepTimeInMs) 

#define	WAIT_FOR_SEMAPHORE(semId, howLong) \
	{do{delay(100);}while(((myVars->pMsgHandler)((void*)myVars))==1);} 

#define	RELEASE_SEMAPHORE(semId, count, addrPrevCount) 

#endif

#ifdef PSOS
#include	"sysdep.h"
#include	<types.h>
#include	<psos.h>
#include	<configs.h>
#include	<bspfuncs.h>
#include	<drv_intf.h>
#include	<stdlib.h>

#include	"defs.h"


extern NODE_CT	*anchor;

/* The following functions are used to translate vxWorks functions 	*/
/* to pSOS+ system calls 						*/
/* This functions will be removed within later versions.		*/ 

static int
semBCreate(int options, int state)
{
	unsigned long	semid;
	char	semname[4];

	semname[0] = 'S';
	semname[1] = 'M';
	semname[2] = '0';
	semname[3] = '0';

	if(sm_create(semname, (unsigned long)state,
			SM_GLOBAL | SM_FIFO, &semid) != 0) 
		return(0);

	return((int)semid);
}

/* end of vxWorks to pSOS+ translation */

#define CLOCKS_PER_SEC	(anchor->psosct->kc_ticks2sec)

#define LCL_SLEEP(sleepTimeInMs) \
	tm_wkafter(((sleepTimeInMs * 100) / (100000 / CLOCKS_PER_SEC)) + 1)

#define CREATE_SEMAPHORE(pSecure, initCount, maxCount, pName) \
	semBCreate(0, (int)initCount);

#define	WAIT_FOR_SEMAPHORE(semId, howLong) \
	sm_p((unsigned long)semId, SM_WAIT, 0) 

#define	RELEASE_SEMAPHORE(semId, count, addrPrevCount) \
	sm_v(semId);
	
#endif

#ifdef LINUX
#include	<unistd.h>
#include	<sys/ipc.h>
#include	<sys/sem.h>

#define	WAIT_FOREVER	0

extern int semBCreate(int options, int initCount);
extern int semTake(int semId, int timeout);
extern int semGive(int semId);

#if 0
static int
semBCreate(int options, int initCount)
{
	int			semId;

        if((semId = semget(IPC_PRIVATE, 1, 0766|IPC_CREAT)) < 0) {
                return(0);
        }

	if(semctl(semId, 0, SETVAL, (union semun) initCount) < 0) {
		return(0);
	}

	return((int)semId);
}

static int
semTake(int semId, int timeout)
{
	static struct sembuf	semaphor;

	semaphor.sem_op = -1;
	semaphor.sem_flg = SEM_UNDO;

	return( (int)semop(semId, &semaphor, 1) );
}

static int
semGive(int semId)
{
	static struct sembuf	semaphor;

	semaphor.sem_op = 1;
	semaphor.sem_flg = SEM_UNDO;

	return( (int)semop(semId, &semaphor, 1) );
}
#endif

#define LCL_SLEEP(sleepTimeInMs)	(void)usleep(sleepTimeInMs * 1000)


#define CREATE_SEMAPHORE(pSecure, initCount, maxCount, pName) \
	semBCreate(0, (int)initCount);

#define	WAIT_FOR_SEMAPHORE(semId, howLong)	\
	semTake(semId, WAIT_FOREVER)

#define	RELEASE_SEMAPHORE(semId, count, addrPrevCount)	\
	semGive(semId)
	
#endif	/* LINUX */

/*
 *	generic variable types
 */
#define	LWORD_t		unsigned long
#define	WORD_t		unsigned short
#define	BYTE_t		unsigned char

#define	LWORDS_t	long
#define	WORDS_t		short
#define	BYTES_t		char

#define	VOID_t		void

#define	INT_t		int

/*
 *	CANopen specific structures/defines
 */

/* 
 * Translation: CANopen data-type -> machine data-type
 */
#define	Boolean			char

#define	Integer8		char
#define	Integer16		short
#define	Integer32		long

#define	Signed8			char
#define	Signed16		short
#define	Signed32		long

#define	Unsigned8		unsigned char
#define	Unsigned16		unsigned short
#define	Unsigned32		unsigned long

#define	FloatingPoint	float

#define VisString		char


/* 
 * machine dependant size of data-type
 */
#define	Boolean_size		sizeof(char)

#define	Integer8_size		sizeof(char)
#define	Integer16_size		(2 * sizeof(char))
#define	Integer32_size		(4 * sizeof(char))
#define	Integer64_size		(8 * sizeof(char))

#define	Signed8_size		sizeof(char)
#define	Signed16_size		(2 * sizeof(char))
#define	Signed32_size		(4 * sizeof(char))
#define	Signed64_size		(8 * sizeof(char))

#define	Unsigned8_size		sizeof(char)
#define	Unsigned16_size		(2 * sizeof(char))
#define	Unsigned32_size		(4 * sizeof(char))
#define	Unsigned64_size		(8 * sizeof(char))



#define	FloatingPoint_size	sizeof(float)

#define VisString_size		(255 * sizeof(char))


struct dataType64bit {
	LWORD_t	highBytes;
	LWORD_t	lowBytes;
};


#define	NIL	(void *)0

/* define values for FALSE and TRUE */

#ifndef MSDOS

#ifdef LINUX
#define	TRUE		1
#define	FALSE		0
#else
#ifndef	TRUE
#define	TRUE		0
#endif

#ifndef	FALSE
#define	FALSE		(-1)
#endif
#endif

#else
#define	TRUE		1
#define	FALSE		0
#endif

#ifdef CAL_CANOPEN_CLAMPED
	#define LCL_NIL_CMSO	NIL_CMSO
#else
	#define LCL_NIL_CMSO	0
#endif


struct Node {
	struct Node	*Next;			/* next node */
	WORD_t		objDicIndex;	/* data stored in node */
	VOID_t		*pEntry;		/* pointer to entry of object dictionary */
};

struct  hashTabs {
	struct	Node **pComProfHashTab;
	struct	Node **pManProfHashTab;
	struct	Node **pDevProfHashTab;
	struct	Node **pDataTypHashTab;
	struct	Node **pIec1131ProfHashTab;
};

struct pdoDataArray {
	BYTE_t	data[8];
	BYTE_t	arrivedLength;
};

struct mSpErrField {
	BYTE_t	mSpErrData[5];
};

#define NIL_SDO_DATA_AREA	(struct sdoDataArea *)0

#define NUM_OF_TAG_BYTES	64	/* will be enough for 512 (* 2) PDOs */
#define	RX_PDO_TAG			0
#define	TX_PDO_TAG			1

#define	SDO_ARRIVED			1
#define	PDO_ARRIVED			2


#define	NUM_BIT_RATE_TABLE_ENTRY	9
#define	CANOPEN_DEFAULT_BIT_RATE	4

struct baudTable {
	WORD_t	bitMacro;
	WORD_t	bitRate;
};

/* Code switch settings for LMT configuration */
#define CS_SET_BIT_RATE			0xf0
#define	CS_SET_DEFAULT_BIT_RATE	0x00

/* 
 * Place of global variables 
 */


struct globVars	{ 
	struct	hashTabs	haTab;		/* place where pointer to */
									/* hash tables are stored */

	BYTE_t			nodeState;		/* current CANopen slave node state */
	BYTE_t			nodeClass;		/* NMT node-class of slave node to create */

	/* global entries from DCF: [DeviceCommisioning] */
	BYTE_t			nodeId;			/* CANopen node ID */
	BYTE_t			nodeName[7];	/* CANopen LMT node name */
	WORD_t			bitRateMacro;	/* current CANopen CAN-Bus-bit-rate */ 

	struct baudTable	bitRateTable[NUM_BIT_RATE_TABLE_ENTRY];	/* CANopen bit-rate-table */


	/* field which holds manufacturer specific error for EMCY */
	struct	mSpErrField	myManSpErrorField;

	/* 
	 * Holding number of TPDOs and RPDOs
	 */
	BYTE_t			numRxPdo;
	BYTE_t			numTxPdo;

	/*
	 * behaviour on incoming SDOs in relationship to Slave nodeState
	 */
	BYTE_t			incomingSdoBehaviour;

#ifdef CAL_CANOPEN_CLAMPED
	/*
	 * This table holds a tag if data which are
	 * mapped to a PDO (txDataTable) or if data
	 * of a PDO (rxDataTable) had changed. The
	 * Table is bit oriented and holds 512 RxPDOs
	 * and 512 TxPDOs
	 */
	BYTE_t			rxPdoTagTable[NUM_OF_TAG_BYTES];	
	BYTE_t			txPdoTagTable[NUM_OF_TAG_BYTES];	

	/* 
	 * Holding a table, where data[8] of each RPDO
	 * is hold to grant access without scrolling 
	 * through Object Dictionary
	 */
	struct pdoDataArray	*dataTablePdo;

	/* 
	 * This variable gives a chance to decide,
	 * if the tag entry in the PDO-change-array
	 * was caused by a PDO arrival or by SDO-
	 * communication.
	 */
	BYTE_t	lastDataFromPdoSdo;

	/* This linked list holds the created (and enabled, coded!) TPDOs */
	struct pdoSendList	*pPdoSendList;	
	
#endif
	/*
	 * array to hold temp VisString-OD-data
	 */
	char	charBuf[256];

#ifndef CAL_CANOPEN_CLAMPED
	/* stuff for communication to VMOD-ICAN3 */
	Message	msgBufferTx;				/* message buffer */
	int		fd;							/* file descriptor of module */
	WORD_t	cmsDefinitionTimeout;		/* timeout in milliseconds to */
										/* wait for module response at */
										/* cms definition services */
	char	lastCmsDefinitionName[13];	/* ID from VMOD-ICAN3 at definition response */
	WORD_t	lastCmsDefinitionId;		/* ID from VMOD-ICAN3 at definition response */


	/* for CANopen manager functionality: */
	WORD_t	variableSDOIdToIcan3;
	WORD_t	variableSDOIdFromIcan3;
	WORD_t	sdoResponseTimeout;			/* timeout in milliseconds to */
										/* wait for peer nodes' SDO response */
	BYTE_t 	sdoRxBuffer[256];	/* place for SDO data exchange (Rx) */
	BYTE_t	sdoTxBuffer[256];	/* place for SDO data exchange (Tx) */
	BYTE_t	sdoValidData;		/* number of received SDO data */
	BYTE_t	sdoResponse;				/* flag for answer of peer SDO */

#ifdef WIN95
	HANDLE	hThreadCopSlv;				/* thread handle */
#endif
#ifdef VXWORKS
	int		hThreadCopSlv;				/* task ID */
#endif
#ifdef PSOS
	unsigned long	hThreadCopSlv;				/* task ID */
#endif
#ifdef LINUX
	unsigned long	hThreadCopSlv;				/* task ID */
#endif
#ifdef WIN_NT40
	HANDLE	hThreadCopSlv;				/* thread handle */
#endif

#ifdef WIN95
	HANDLE	hSemCopSlv;
	HANDLE	hSemIcanCom;				/* semaphore for thread-save comunication */
										/* between receive thread and lib */
#endif

#ifdef WIN_NT40
	HANDLE	hSemCopSlv;
	HANDLE	hSemIcanCom;				/* semaphore for thread-save comunication */
										/* between receive thread and lib */
	HANDLE	hSemPlainQueue;				/* semaphore to signal application that a message is */
										/* inside the to-host plain queue */
	HANDLE	hSemFastQueue;				/* semaphore to signal application that a message is */
										/* inside the to-host fast queue */
#endif

#ifdef VXWORKS
	SEM_ID	hSemCopSlv;
	SEM_ID	hSemIcanCom;				/* semaphore for thread-save comunication */
										/* between receive thread and lib */
#endif
#ifdef PSOS
	SEM_ID	hSemCopSlv;
	SEM_ID	hSemIcanCom;				/* semaphore for thread-save comunication */
							/* between receive thread and lib */
#endif
#ifdef LINUX
	int	hSemCopSlv;
	int	hSemIcanCom;				/* semaphore for thread-save comunication */
							/* between receive thread and lib */
#endif

#ifdef MSDOS
 	int	(*pMsgHandler) (void*);
#endif
	int		tIdCopSlv;
	Message	msgBufferRx;

	LWORD_t	usedDpmCount;				/* variable for objects interfacing to DPM, */
										/* counts the actual offset to start of PP-area */

	int (*drvRead)();					/* driver function to call on internal DPM-read */
	void (*drvWrite)();					/* driver function to call on internal DPM-write */
#endif

};


#if KDEBUG==1
/* DEBUG tool KPRINTF */
extern long freeMemDebug;
#endif

#ifdef __cplusplus
}
#endif

#endif /* !gendef_DEFINED */              
