/************************************************************************/
/* Copyright 2009-2016 MBARI											*/
/************************************************************************/
/* Summary	: Definitions for remote serial and power ports for Modbus clients*/
/* Filename : remote.h													*/
/* Author	: Robert Herlien (rah)										*/
/* Project	: Oasis5 Mooring Controller									*/
/* Revision: 1.0														*/
/* Created	: 08/31/2016												*/
/*																			*/
/* MBARI provides this documentation and code "as is", with no warranty,	*/
/* express or implied, of its quality or consistency. It is provided without*/
/* support and without obligation on the part of the Monterey Bay Aquarium	*/
/* Research Institute to assist in its use, correction, modification, or	*/
/* enhancement. This information should not be published or distributed to	*/
/* third parties without specific written permission from MBARI.			*/
/*																			*/
/************************************************************************/
/* Modification History:												*/
/* 07apr2009 rah - created Oasis4 version								*/
/* 31aug2016 rah - created Oasis5 version from Oasis4 version			*/
/************************************************************************/

#ifndef INCremoteh
#define INCremoteh		1

#include <FreeRTOS.h>
#include <task.h>
#include <modbus.h>
#include <list.h>
#include <sem.h>


/****************************************/
/* Typedefs and definitions				*/
/****************************************/

#define VIRT_SER_PORTS	64				/* Up to 64 virtual serial ports*/
#define VIRT_PWR_PORTS	64				/* Up to 64 virtual power ports */
#define VIRT_OUT_PORTS	64				/* Up to 64 virtual output ports*/
#define REMOTE_IDS		32				/* Up to 32 chamber controllers */
#define CHAMBER_SER_PORTS 3				/* Num serial ports on chamber ctrlr*/
#define CHAMBER_PWR_PORTS 3				/* Num pwr ports on chamber ctrlr*/
#define CHAMBER_OUT_PORTS 8				/* Num out ports on chamber ctrlr*/
#define MAX_SER_PER_SLAVE 6
#define MAX_PWR_PER_SLAVE 6
#define MAX_OUTPUT_PER_SLAVE 8
#define SERBUF_SIZE		240				/* Size of serial buffer		*/		
#define SERREG_SIZE		(SERBUF_SIZE/2)
#define RNAME_SIZE		32				/* Size (chars) of remote name	*/

#define DFLT_MULT		(1.0)
#define DFLT_SURGE		500


typedef enum					/****************************************/
{								/* Type of Remote ModBus client			*/
	RemUnassigned=0,			/* This entry not used yet				*/
	RemUnknown,					/* Don't know type of client			*/
	RemOrigChamber,				/* Original chamber controller from BRS/MRS*/
	RemChamber2,				/* Chamber controller with updated firmware*/
	RemFOCESN,					/* FOCE Sensor Node (not used)			*/
	RemO5Expander,				/* Oasis5 Expander board				*/
	RemO5DB						/* Oasis5 Daughter Board (SPI based)	*/
} RemType;						/****************************************/

typedef struct					/****************************************/
{								/* Used keep track of ModBus clients	*/
	ModBusType	busType;		/* Serial or SPI ModBus?				*/
	Nat16		bus;			/* Ser port or SPI bus number			*/
	Nat16		slaveID;		/* ModBus slave ID						*/
								/* Following 4 fields must be in this order*/
	Nat16		remType;		/* Type of client - see enum above		*/
	Nat16		nSer;			/* Number of ser ports on client		*/
	Nat16		nPwr;			/* Number of power switches on client	*/
	Nat16		nIO;			/* Number of remote I/O bits on client	*/
	Nat32		msgs;			/* Message count for this slave			*/
	Nat32		errs;			/* Error count for this slave			*/
} RemID;						/****************************************/

typedef struct					/****************************************/
{								/* Remote Serial Port					*/
	RemID		*id;			/* ModBus client we're attached to		*/
	Semaphore	sem;			/* MUTEX semaphore to access serial port*/
	ModBusHandle handle;		/* Handle to the ModBus bus				*/
	TaskHandle_t owner;			/* Who opened this serial port			*/
	Byte		*bufPtr;		/* Ring buffer output ptr				*/
	Nat16		port;			/* Serial port on the slave				*/
	Nat16		bufChars;		/* Number of chars valid in buf			*/
	Nat16		rxQueued;		/* RxQueued reg. MUST be immed b4 buf	*/
	Byte		buf[SERBUF_SIZE]; /* Buffer for serial chars			*/
	char		name[RNAME_SIZE]; /* Name								*/
} RemSerPort;					/****************************************/

typedef RemSerPort *RemSerHandle;

typedef struct					/****************************************/
{								/* Used for Remote Power & Output Ports */
	RemID		*id;			/* ModBus client we're attached to		*/
	Nat16		coil;			/* Coil number on slave for power bit	*/
	MBool		coilState;		/* State coil is in						*/
	Flt32		multiplier;		/* Time multiplier for calibration		*/
	Nat32		surgeDelayMs;	/* Surge delay in milliseconds			*/
	char		name[RNAME_SIZE]; /* Name								*/
} RemIOPort;					/****************************************/


/****************************************/
/* Remote Serial I/O Definitions		*/
/****************************************/

#define MIN_READ				10		/* Min number of regs to read	*/

/* Register and Coil Definitions		*/
#define SerRxStatusReg			0xfe
#define SerTxStatusReg			0xff
#define TxBusy(val, port)		(val & (1 << (2*port)))
#define RxAvail(val, port)		(val & (1 << (4*port+1)))
#define TxErr(val, port)		(val & (1 << (2*port+1)))

#define BoardTypeReg			(1)
#define BlinkyReg				(8)
#define BLINKY_ERROR_MODE		(4)
#define BaudReg(port)			(0x100 * (port + 1))
#define ModeReg(port)			((0x100 * port) + 0x101)
#define RxCtlReg(port)			((0x100 * port) + 0x102)
#define RxQReg(port)			((0x100 * port) + 0x107)
#define TxQueuedReg(port)		((0x100 * port) + 0x183)
#define TxCtlReg(port)			((0x100 * port) + 0x184)
#define TxBreakReg(port)		((0x100 * port) + 0x185)
#define TxReqReg(port)			((0x100 * port) + 0x187)
#define PowerBit(port)			(port + 1)
#define TxEnable(port)			(port + 9)
#define BlinkyDebugCoil			(15)
#define BlinkyStateCoil			(16)

/* Different macros for Respirometer Chamber Controller  */
#define TxBusyChamber(val, port) (val & (1 << (4*port)))
#define TxErrChamber(val, port)	(val & (1 << (4*port+2)))
#define OutputBit(port)			(port + 1)
#define PowerBitChamber(port)	(port + 9)
#define TxEnableChamber(port)	(port + 12)


#define REM_NO_PTY		0
#define REM_EVEN_PTY	2
#define REM_ODD_PTY		4
#define REM_STOP2		1
#define REM_TX_FLUSH	0x20
#define REM_RX_FLUSH	0x20
#define REM_BREAK		1

/****************************************/
/* Function Declarations				*/
/****************************************/

Void			initRemoteLib(Void);
Void			takeRemoteSem(Void);
Void			giveRemoteSem(Nat32 delay_ms);
Int16			findRemPwrPort(char *s);
Int16			findRemOutputPort(char *s);
RemSerHandle	getVirtSerPort(Nat32 virtPort);
RemSerHandle	findRemSerHandle(ModBusType busType, Nat16 bus, Nat16 slave, Nat16 port);
RemSerHandle	remSerOpen(ModBusType busType, Nat16 bus, Nat16 slave, Nat16 port, MBool async);
Errno			openRemSerHandle(RemSerHandle rsh, MBool async);
Errno			remSerClose(RemSerHandle rsh);
Errno			remOpenVirtSer(Nat32 virtPort, MBool async);
Errno			remCloseVirtSer(Nat32 virtPort);
Errno			remSerInit(RemSerHandle rsh, Nat32 baud, Nat32 mode);
Errno			remVirtSerInit(Nat32 virtPort, Nat32 baud, Nat32 mode);
RemID			*findRemoteID(ModBusType busType, Port_t bus, Nat16 slave);
RemID			*assignRemoteID(ModBusType busType, Port_t bus, Nat16 slave);
void			findRemoteSlaveType(ModBusHandle mh, RemID *rp);
Errno			assignVirtSerial(char *name, Nat32 virtPort, ModBusType busType,
								 Nat16 bus, Nat16 slave, Nat16 port, Flt32, Nat32);
Errno			assignVirtPwr(char *name, Nat32 virtPort, ModBusType busType, Nat16 bus,
							  Nat16 slave, Nat16 coil, Flt32 mult, Nat32 surgeDelay);
Errno			assignVirtOutput(char *name, Nat32 virtPort, ModBusType busType, Nat16 bus,
								 Nat16 slave, Nat16 coil, Flt32 mult, Nat32 surgeDelay);
Errno			remPower(Nat32 pwrnum, MBool onoff);
Errno			remOutput(Nat32 pwrnum, MBool onoff);
Errno			remIsPowerOn(Port_t bus);
Errno			remIsOutputOn(Port_t bus);
Errno			remOff(Void);
Errno			remOutPulseOn(Nat32 bitNum, Flt32 sec);
Errno			remOutPulseOnByVolume(Nat32 bitNum, Flt32 vol);
Errno			remOutPulseOff(Nat32 bitNum, Flt32 sec);
Nat32			remSerRead(RemSerHandle rsh, char *buffer, Nat32 len);
Nat32			remSerWrite(RemSerHandle rsh, const char *buffer, Nat32 len);
Errno			remSerDrain(RemSerHandle rsh, Nat32 tmout);
Errno			remSerIFlush(RemSerHandle rsh);
Errno			remSerOFlush(RemSerHandle rsh);
Int16			remSerRxCount(RemSerHandle rsh);
Errno			remSerBreak(RemSerHandle rsh, Nat16 breakTime);
void			remTaskExit(TaskHandle_t *td);
void			remSetError();

#endif	/* INCremoteh */
