/****************************************************************************/
/* Copyright 2015 MBARI                                                     */
/****************************************************************************/
/* Summary  : Serial I/O for OASIS5 on PIC32MX470F512L                      */
/* Filename : serial.h                                                      */
/* Author   : Robert Herlien (rah)                                          */
/* Project  : OASIS Mooring Replacement (OASIS5)                            */
/* Revision: 1.0                                                            */
/* Created  : 07/13/2015                                                    */
/*                                                                          */
/* 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:                                                    */
/* 13jul2015 rah - created                                                  */
/* 20jun2016 rah - Merged with Oasis3/4 source								*/
/****************************************************************************/

#ifndef SERIAL_H
#define SERIAL_H

#include <mbariTypes.h>					/* MBARI type definitions			*/
#include <oasis.h>
#include <buffer.h>
#include <modbus.h>
#include <time.h>


/********************************************/
/*      Typedefs and Constants              */
/********************************************/

#define PIC_UARTS       5
#define PHYS_SER_PORTS  PIC_UARTS
#define NUM_DBS			2
#define UARTS_PER_DB	6
#define DB_UARTS        (NUM_DBS * UARTS_PER_DB)
#define BASE_SER_PORTS	(PIC_UARTS + DB_UARTS)

#define physSer(virt)	((virt < PIC_UARTS) ? virt : 0)
#define isPhysSer(virt) (virt < PIC_UARTS)

/* Serial relays also directly switch power	*/
#define PHYS_PWR_PORTS	PIC_UARTS
#define BASE_PWR_PORTS	BASE_SER_PORTS
#define isPhysPwr(virt)	(virt && (virt < PHYS_PWR_PORTS))


#define CPU_SER			0				/* CPU serial port is port 0		*/
#define XON				0x11			/* Xon ASCII character				*/
#define XOFF			0x13			/* Xoff ASCII character				*/

#define RX_BUFF_SIZE    512
#define TX_BUFF_SIZE    256

#define UxMODE          0x8800
#define UxSTA           0x1400
#define UxSTA_MODBUS    0x0400

#define FastBRG(baud)   (unsigned int)((PBCLK/(4*baud)) - 1)
#define StdBRG(baud)    (unsigned int)((PBCLK/(16*baud)) - 1)

#define SER_PORT_0     0
#define SER_PORT_1     1
#define SER_PORT_2     2
#define SER_PORT_3     3
#define SER_PORT_4     4

#define SER_CONSOLE    0
#define STD_BAUD	   9600
#define CONSOLE_BAUD   38400

/* Bit definitions for serMode word passed to serPortInit()					*/

#define PTY_MASK		3				/* Parity is bits 0, 1				*/
#define NO_PTY			0				/* No parity						*/
#define EVEN_PTY		1				/* Even parity						*/
#define ODD_PTY			2				/* Odd parity						*/
#define BIT8			0				/* 8 bit characters					*/
#define BIT7			4				/* 7 bit characters					*/
#define STOP2			8				/* 2 stop bits						*/
#define STOP1			0				/* 1 stop bit						*/

#define FLOW			0x10			/* Bit 4 on for XON/XOFF flow control*/
#define ECHO			0x20			/* Bit 5 on for local echo mode		*/
#define NMODE			0xc0			/* Bits 6 & 7 are \n mode			*/
#define AUTOCR			0x40			/* 01 = Add CR before LF			*/
#define NEWCR			0x80			/* 10 = Replace newline with CR		*/
#define NOLF			0xc0			/* 11 = Don't output LF				*/
#define LF_NORMAL		0x00			/* 00 = Leave LF alone				*/

/* data/parity settings for PIC24/32 */
#define D8_NONE         0
#define D8_EVEN         1
#define D8_ODD          2
#define D9_NONE         3


/* Aggregate definitions used for Driver Descriptors	*/

#define MODE_N81		(NO_PTY	  | BIT8 | STOP1 | FLOW)
#define MODE_N81NF		(NO_PTY	  | BIT8 | STOP1)
#define MODE_E71		(EVEN_PTY | BIT7 | STOP1 | FLOW)
#define MODE_N72NF		(NO_PTY	  | BIT7 | STOP2)


/********************************************/
/*		Serial Port Data Structures			*/
/********************************************/

typedef enum {INST_PORT=0, MB_PORT} SerType;

typedef struct					/****************************************/
{								/* Struct to hold serial data and state	*/
	ByteBuffer	rxBuff;			/* Receive buffer struct				*/
	Byte		rxBuffData[RX_BUFF_SIZE];  /* Rcv buffer data			*/
	ByteBuffer	txBuff;			/* Receive buffer struct				*/
	Byte		txBuffData[TX_BUFF_SIZE];  /* Tx buffer data			*/
	SerType		serType;		/* Used for instrument or ModBus?		*/
	Nat32		baudRate;		/* Baud Rate							*/
	MBool		do_xon;			/* TRUE if doing XON/XOFF				*/
	MBool		xoff_status;	/* TRUE if XOFF'd						*/
	time_t		xoff_time;		/* Time got XOFF						*/
	Nat32		rxOverFlowCnt;	/* Rx Overflow count					*/
} SerStruct;					/****************************************/

typedef union					/****************************************/
{								/* Union of Serial & Modbus structs		*/
	SerStruct	ser;			/* Serial struct						*/
	ModBusStruct mb;			/* ModBus struct						*/
} SerUnion;						/****************************************/


#define getSerialSem(port)	getSerialSemTmout(port, portMAX_DELAY);

/********************************************/
/*      Function Declarations               */
/********************************************/

Errno	serInit(void); 
Errno	getSerialSemTmout(Port_t serport, TickType_t tmout);
void	releaseSerialSem(Port_t serport);
SerStruct *getSerialStruct(Port_t serport);
MBool	serPortInit(Port_t port, Nat32 baud, Nat32 mode);
void	serCheckXoffStatus(void);
MBool	ser_putc(Port_t port, Byte b);
int		ser_getc(Port_t port);
int		ser_sndsts(Port_t port);
int		serRxCount(Port_t port);
void	serRxFlush(Port_t port);
void	serTxFlush(Port_t port);
void	serWaitTxComplete(int port);
MBool	serAnyTxActive(void);
Nat32	serGetRxOvflCnt(Port_t port);
void	ser_break(Port_t port, TickType_t count);
int		ser_read(Port_t port, char *buffer, Int32 nbytes, TickType_t tmout);
int		ser_write(Port_t port, const char *buffer, Int32 nbytes, TickType_t tmout);
#ifdef DEBUG_SERIAL_CMD
int		serDump(Nat32 pmask, Parm_t serchan);
#endif


/* Non-Oasis4 functions		*/
void	setSerModbus(Port_t port, MBool start);
int		serPutString(int port, char* buff);
void	serGetConfig(int port, unsigned long *baud, int *data_par, int *stop);
void	setupConsoleWakeFromSleep(void);
void	clearConsoleWakeFromSleep(void);
MBool	consoleWakeupReceived(void);

int		serGetXonStatus(Port_t port, time_t *xtime);
void	serSetXonStatus(Port_t port, MBool onoff);

#endif
