/****************************************************************************/
/* Copyright 1992 to 1995 MBARI                                             */
/****************************************************************************/
/* Summary  : Virtual Serial Port Interface for VxWorks                     */
/* Filename : vspDmTop.c                                                    */
/* Author   : Douglas Au                                                    */
/* Project  : New ROV                                                       */
/* Version  : Version 1.0                                                   */
/* Created  : 08/22/94                                                      */
/* Modified : 01/31/95                                                      */
/* Archived :                                                               */
/****************************************************************************/
/* Modification History:                                                    */
/* Initial revision                                                         */ 
/****************************************************************************/
#include <vxWorks.h>                /* vxWorks system declarations          */
#include <semLib.h>                 /* vxWorks semaphore functions          */
#include <rngLib.h>
#include <taskLib.h>                /* vxWorks task library functions       */
#include <wdLib.h>                  /* vxWorks watch dog timer functions    */
#include <systime.h>                /* vxWorks time and date functions      */
#include <msgQLib.h>		    /* vxWorks Message Queue Library        */
#include <selectLib.h>		    /* vxWorks select IO facilities         */
#include <ioLib.h>                  /* vxWorks I/O Libraries                */
#include <iosLib.h>
#include <tyLib.h>                  /* vxWorks tty Functions                */
#include <usrTime.h>                 

#include <types.h>  	            /* MBARI style guide type declarations  */
#include <const.h>                  /* Miscellaneous MBARI constants        */

#include "sio32.h"                  /* SIO32 hardware and driver information*/
#include <sio32Server.h>            /* Sio32 server communication services  */
#include <sio32Client.h>            /* Sio32 client communication services  */

#include <datamgr.h>                /* Data Manager declarations            */
#include <dm_errno.h>               /* Data Manager error declarations      */

#include <microDm.h>	            /* Microcontroller Data Manager Funcs   */ 
#include <sio4.h>                   /* MV162 board tty drivers              */

#include "../h/vspDmTop.h"

/*****************************************************************************/
/* Function    : createIbcVspTopDmItems                                      */
/* Purpose     : Initialize Data Manager Item Handles for Virtual Serial Port*/
/* Inputs      : Pointer to structure containing IBC VSP Data Manager Handles*/
/*               and IBC Data Concentrator Name                              */
/* Outputs     : None, but Data Manager Items change                         */
/*****************************************************************************/
    STATUS
createIbcVspTopDmItems( ibcVspDmItems *vspDmItems, const char* ibcDmPrefix,
		    const char* ibcDataCon, Int16 quadSerBoardNum)
{   
    Int32   item;                   /* Counter for DM Item Initialization    */
    Errno   status;                 /* Result of dm_create function call     */
    const   char   itemPrefix[32];  /* Data Manager Item Prefix Name         */ 
    char dmItemName[MAX_NMLEN];     /* Complete item name string             */

    struct                          /* Data Manager Item Table for table     */
    {                               /* driven item initialization            */
        DM_Item *dmItem;            /* pointer to actual dm item handle      */
        char    *errorMsg;          /* Message to display of dmCreate fails  */
        char    *name;              /* Data Manager Item Name                */
	DM_Type type;               /* Data Manager Item Type                */
        DM_Num  len;                /* Data Manager Item Element Count       */
    } vspDmInit[] =

      { { &vspDmItems->vspBaud,          "VSP Baud Rate",
              VSP_BAUD_DM,                    DM_NAT16, 1 },

        { &vspDmItems->vspData,          "VSP Data Bits",
              VSP_DATA_BITS_DM,               DM_NAT16, 1 },

        { &vspDmItems->vspStop,          "VSP Stop Bits",
              VSP_STOP_BITS_DM,               DM_NAT16, 1 },

        { &vspDmItems->vspPar,           "VSP Parity", 
              VSP_PARITY_DM,                  DM_NAT16, 1 },
         
        { &vspDmItems->vspMsgReceived,   "VSP Message Received Flag",
              VSP_MSG_RECEIVED_DM,            DM_EMPTY, 0 },
 
        { &vspDmItems->vspHandshake,     "VSP Handshake Mode",
              VSP_HANDSHAKE_DM,               DM_MBOOL, 1 },
        
        { &vspDmItems->vspProtocol,      "VSP Protocol",
              VSP_PROTOCOL_DM,                DM_NAT16, 1 }, 

        { &vspDmItems->vspBreak,         "VSP Break Character Received Flag",
              VSP_BREAK_DM,                   DM_NAT16, 1 },
        
        { &vspDmItems->vspError,         "VSP Error Flag",
              VSP_ERROR_DM,                   DM_NAT16, 0 },
#if 0        
        { &vspDmItems->vspPortName,      "VSP Port Name",
              VSP_PORT_NAME_DM,               DM_STRING, 1},
#endif
        { NO_ITEM, NULL, NULL, DM_ENDT, 0 } };
                                
                                    /*  Build Name from Prefix and Name       */
    sprintf(itemPrefix, "%s.VSP%d.", ibcDmPrefix, quadSerBoardNum); 

				    /* Clear list of Data Manager Item handles*/
    bzero(*vspDmItems, sizeof(*vspDmItems));

                                    /*Initialize Data Manager Items from table*/
    for (item = 0; vspDmInit[item].dmItem != NO_ITEM; item++)
    {
        if ((*vspDmInit[item].dmItem =
             initMicroDmItem(itemPrefix, vspDmInit[item].name,
             vspDmInit[item].type, vspDmInit[item].len)) == ERROR)

        {                           /* Error occurred so print message & exit */
            logMsg("%s: Error Initializing %s DM Item\n",
                ibcDataCon, vspDmInit[item].errorMsg);
            return(ERROR);
        } /* if */
    } /* for */

    /* Build name from name prefix & name     */
    sprintf(dmItemName, "%s.VSP%d.%s", ibcDmPrefix, quadSerBoardNum,
                  VSP_MSGOUT_DM );
   
                                       /* Initilize VSP MsgOut DM Item      */
    status = dm_create(dmItemName, 1, &vspDmItems->vspMsgOut,
                       DM_NAT16, 1, DM_CHAR, MAX_PACKET_LEN, DM_ENDT);

                                    /* Treat item exists the same as success  */
    if ( (status != SUCCESS) && (status != EDM_NAME_EXISTS) )
    {                               /* Error occurred so print message & exit */
        logMsg("%s: Error Initializing %s DM Item\n",
                ibcDataCon, vspDmInit[item].errorMsg);
        return(ERROR);
    } /* if */
    
    /* Build name from name prefix & name     */
    sprintf(dmItemName, "%s.VSP%d.%s", ibcDmPrefix, quadSerBoardNum,
                  VSP_MSGIN_DM );
                                       /* Initilize VSP MsgIn DM Item      */
    status = dm_create(dmItemName, 1, &vspDmItems->vspMsgIn,
                       DM_NAT16, 1, DM_CHAR, MAX_PACKET_LEN, DM_ENDT);

                                    /* Treat item exists the same as success  */
    if ( (status != SUCCESS) && (status != EDM_NAME_EXISTS) )
    {                               /* Error occurred so print message & exit */
        logMsg("%s: Error Initializing %s DM Item\n",
                ibcDataCon, vspDmInit[item].errorMsg);
        return(ERROR);
    } /* if */
    return(OK);			    /* All IBC CPU Data Mgr items initialized */
} /* createIbcVspTopDmItems() */ 

    Void
initIbcVspTopProvider( ibcVspDmItems* vspItems, Period period )
{
    dm_start_provider(vspItems->vspMsgOut, period);
} /* initIbcVspTopProvider() */

    DWord
initIbcVspTopConsumer( ibcVspDmItems* vspItems, vspUpdateBits *vspBits,
	       SEM_ID updateSem )
{
    DWord vspGroup;

    vspGroup = dm_create_group();    /* Create Data Manager Group for Vsp  */

    dm_start_consumer(vspItems->vspMsgIn,  DM_STATIC, updateSem);
    dm_start_consumer(vspItems->vspMsgReceived,  DM_STATIC, updateSem);
    
    dm_group_add_item(vspGroup, vspItems->vspMsgIn,
         &vspBits->msgInBit );

    dm_group_add_item(vspGroup, vspItems->vspMsgReceived,
         &vspBits->msgReceivedBit );

    dm_start_consumer(vspItems->vspBaud,  DM_STATIC, updateSem);
    dm_start_consumer(vspItems->vspData, DM_STATIC, updateSem);
    dm_start_consumer(vspItems->vspStop, DM_STATIC, updateSem);
    dm_start_consumer(vspItems->vspPar, DM_STATIC, updateSem);
    dm_start_consumer(vspItems->vspMsgOut, DM_STATIC, updateSem);
    dm_start_consumer(vspItems->vspHandshake, DM_STATIC, updateSem);
    dm_start_consumer(vspItems->vspProtocol, DM_STATIC, updateSem);

    dm_group_add_item(vspGroup, vspItems->vspBaud,
         &vspBits->baudBit );

    dm_group_add_item(vspGroup, vspItems->vspData,
         &vspBits->dataBit );

    dm_group_add_item(vspGroup, vspItems->vspStop,
         &vspBits->stopBit );

    dm_group_add_item(vspGroup, vspItems->vspPar,
         &vspBits->parityBit );

    dm_group_add_item(vspGroup, vspItems->vspMsgOut,
         &vspBits->msgOutBit );

    dm_group_add_item(vspGroup, vspItems->vspHandshake,
         &vspBits->handshakeBit );

    dm_group_add_item(vspGroup, vspItems->vspProtocol,
         &vspBits->protocolBit );

     return (vspGroup);
} /* initIbcVspTopConsumer() */

   Void
updateIbcVspTopDm( Int16 fd, ibcVspDmItems *vsp)
{
    messageStruct msgOut;
    fd_set fdSet;
    struct timeval timeout = {0, SERIAL_TIMEOUT};
    DM_Time updateTime;

    FOREVER
    {	
	FD_ZERO(&fdSet);		/* Wait forever for chars come in     */
	FD_SET(fd, &fdSet);
	
        select(FD_SETSIZE, &fdSet, (fd_set *) NULL, (fd_set *) NULL,
	       (struct timeval *) NULL);  

        /* Mabey Check for break Char here and do and urgent dm write  */ 

        if (( msgOut.len = read (fd, msgOut.buffer, MAX_PACKET_LEN)) != ERROR)
	{
	    while((msgOut.len <= MAX_PACKET_LEN) && 
		  (select(FD_SETSIZE, &fdSet, (fd_set *) NULL, (fd_set *) NULL,
                       &timeout) != 0))
		
		msgOut.len += read (fd, msgOut.buffer + msgOut.len,
		      MAX_PACKET_LEN - msgOut.len);

	    if (msgOut.len < MAX_PACKET_LEN)
                   msgOut.buffer[msgOut.len] = '\0';    

				    /* Get time & date from clock           */
            gettimeofday(&updateTime, (struct timezone *) NULL);

            /* Write actual values to Data Manager */
            dm_write(vsp->vspMsgOut, &msgOut,
                   sizeof(msgOut), &updateTime);       
        } /* if */
    } /* FOREVER */
}  /* updateIbcVspTopDm() */

/*****************************************************************************/
/* Function    : updateIbcVspTopDmItems                                      */
/* Purpose     : Reads Vsp parameters from tty & update Data Manager         */
/* Inputs      : Array of Data Manager Item handles & serial chan structure  */
/* Outputs     : None, but Data Manager Items change                         */
/*****************************************************************************/
    Void
updateIbcVspTopDmItems( ibcVspDmItems *vspItems, Nat16 baud, Nat16 data,
    Nat16 stop, Nat16 par, MBool handshake, Nat16 proto)
{   
                      /* Write DM items To set parameters for VSP */
    urgentWriteDmItem( vspItems->vspBaud, &baud, sizeof(baud));
        
    urgentWriteDmItem( vspItems->vspData, &data, sizeof(data));

    urgentWriteDmItem( vspItems->vspStop, &stop, sizeof(stop));
        
    urgentWriteDmItem( vspItems->vspPar, &par, sizeof(par));

    urgentWriteDmItem( vspItems->vspHandshake, &handshake,
            sizeof(handshake));
      
    urgentWriteDmItem( vspItems->vspProtocol, &proto, sizeof(proto));
} /* updateIbcVspTopDmItems() */

     Void
ibcVspTopUpdateCheck( Int16 fd, ibcVspDmItems* vspItems, 
                       vspUpdateBits *vspBits, DM_Group vspGroup )
{
    DWord   vspGroupBits;           /* Holds dm_group_changes bit vector     */
    Int16   baud, proto;
    MBool   handshake;
    Nat16   data, stop, par, numOfBytes;
    messageStruct  msgIn;
    struct termControl term_control;

                                /* Ask Data Manager If VSP items changed */
    if ( (vspGroupBits = dm_get_group_changes(vspGroup)) == (DWord) 0)
	return;
     
				    /* VSP Parameters */
   
    if ( (vspGroupBits & vspBits->baudBit) || 
         (vspGroupBits & vspBits->dataBit) ||
         (vspGroupBits & vspBits->stopBit) ||
         (vspGroupBits & vspBits->parityBit) ||
         (vspGroupBits & vspBits->handshakeBit) ||
         (vspGroupBits & vspBits->protocolBit) )

    {                            /* Read VSP parameters from dmgr*/
        dm_read( vspItems->vspBaud, (char *) &baud, 
	    sizeof(baud), (DM_Time *) NULL);
        
        dm_read( vspItems->vspData, (char *) &data, 
	    sizeof(data), (DM_Time *) NULL);

        dm_read( vspItems->vspStop, (char *) &stop, 
	    sizeof(stop), (DM_Time *) NULL);
        
        dm_read( vspItems->vspPar, (char *) &par, 
	    sizeof(par), (DM_Time *) NULL);

        dm_read( vspItems->vspHandshake, (char *) &handshake,
            sizeof(handshake), (DM_Time *) NULL);
      
        dm_read( vspItems->vspProtocol, (char *) &proto,
            sizeof(proto), (DM_Time *) NULL);
       
        term_control.tc_oflag = setTermControl(baud, data, stop, par);
 
        term_control.tc_iflag = setTermControl(baud, data, stop, par);
                                      

        ioctl( fd, OFLUSH | IFLUSH, 0);
        if(ioctl( fd, SIOSETS, (int) &term_control)!= OK)
            printf ("VSP: Unable to set line options\n");

    } /* if */
    
    if  (vspGroupBits & vspBits->msgInBit) 	
    {
        dm_read( vspItems->vspMsgIn, (char *) &msgIn,
	    sizeof(msgIn), (DM_Time *) NULL);
        
        if (write(fd, msgIn.buffer, msgIn.len) == ERROR)
            logMsg("VSP Task: Can't Write to ttyFd\n");
    }/* if */

} /* ibcVspTopUpdateCheck() */


DWord setTermControl(Nat16 baud, Nat16 data, Nat16 stop, Nat16 par)
{
DWord controlWord;
DWord baudRate, dataBits, stopBits, parity;

switch(baud)
{
  case 0:
    baudRate = B0;
    break;
  case 1200:
    baudRate = B1200;
    break;
  case 2400:
    baudRate = B2400;
    break;
  case 4800:
    baudRate = B4800;
    break;
  case 9600:
    baudRate = B9600;
    break;
  case 19200:
    baudRate = B19200;
    break;
  case 38400:
    baudRate = B38400;
    break;
  default:
   break;
}

switch(dataBits)
{
  case 5:
    dataBits = CS5;
    break;
  case 6:
    dataBits = CS6;
    break;
  case 7:
    dataBits = CS7;
    break;
  case 8:
    dataBits = CS8;
    break;
  default:
    break;
}

switch(stopBits)
{
  case 2:
    stopBits = CSTOPB;
    break;
  default:
    stopBits = 0;
    break;
}

switch(parity)
{
  case 0:
    parity = 0;
    break;
  case 1:
    parity = PARENB;
    break; 
  case 2:
    parity = (PARENB | PARODD);
    break;
  default:
    break;
}

controlWord = (baudRate | dataBits | stopBits | parity);

return(controlWord);
}/* setTermControl */












