/****************************************************************************/
/* Copyright 1992 to 1995 MBARI                                             */
/****************************************************************************/
/* Summary  : Virtual Serial Port Task for VxWorks                          */
/* Filename : vspTaskTop.c                                                  */
/* Author   : Douglas Au                                                    */
/* Project  : New ROV                                                       */
/* Version  : Version 1.0                                                   */
/* Created  : 12/07/94                                                      */
/* Modified : 01/31/95                                                      */
/* Archived :                                                               */
/****************************************************************************/
/* Modification History:                                                    */
/* $Header: vspTaskTop.c,v 1.1 94/06/14 14:15:48 audo Exp $
 * $Log:	vspTaskTop.c,v $
 * Revision 1.1  94/06/14  14:15:48  14:15:48  audo (Douglas Au)
 * Initial revision
 * 
 */
/****************************************************************************/

#include <vxWorks.h>                /* vxWorks system declarations          */
#include <semLib.h>                 /* vxWorks semaphore functions          */
#include <taskLib.h>                /* vxWorks task library functions       */
#include <lstLib.h>                 /* vxWorks linked list library          */
#include <wdLib.h>                  /* vxWorks watch dog timer functions    */
#include <systime.h>                /* vxWorks time and date functions      */
#include <msgQLib.h>		    /* vxWorks Message Queue Library        */

#include <ioLib.h>                  /* vxWorks I/O Libraries                */
#include <iosLib.h>
#include <tyLib.h>                  /* vxWorks tty Functions                */

#include <types.h>                  /* MBARI style guide type declarations  */
#include <const.h>                  /* Miscellaneous constants              */

#include <rovPriority.h>            /* MBARI Rov Application Priorities     */
#include <usrTime.h>                /* MBARI time and date functions        */

#include <datamgr.h>                /* Data Manager declarations            */
#include <dm_errno.h>               /* Data Manager error declarations      */
#include <ttyHwOpt.h>

#include <proto.h>                  /* Microcontroller serial Protocol      */
#include <sio4.h>                   /* MV162 board tty drivers              */
#include "h/vspDmTop.h"             /* VSP Data Manager Interface Functions */

#define VSP_OUT_STACKSIZE  4000    /* VSP Output Task size & TCB            */
#define VSP_IN_STACKSIZE   1500    /* VSP Input Task size & TCB             */

#define CHAN_PER_BOARD        8    /* Number of Channels per board          */
/****************************************************************************/

Void vspInTask(Reg ibcVspDmItems *dmItems, Int16 ttyFd);

    MLocal Int32
openVspSerialPort(Int16 board, Int16 port)
{
    Int32 fd;
    char  devName[32];

    struct  termControl term_control;

    sprintf(devName, "/serial%d/chan%d", board, port); 

    if ( (fd = open(devName, O_RDONLY, 0)) == ERROR)
	return (ERROR);

    ioctl(fd, FIOGETOPTIONS, (int) &term_control);
    term_control.tc_oflag = ONLCR;
    term_control.tc_iflag = IGNCR | IGNBRK | IGNPAR;
    term_control.tc_iflag = 0;
    ioctl(fd, FIOSETOPTIONS, (int) &term_control);

    return (fd);
} /* openVspSerialPort() */

/****************************************************************************/
/* Function    : vspTaskTopTask                                             */
/* Purpose     : Task spawns Vsp Input Task, reads setup parameters from    */
/*               a file, sets up DM Items and tty parameters, then waits    */
/*               for dm items to change or input from tty port              */
/* Inputs      : None                                                       */
/*                                                                          */
/* Outputs     : Normally runs forever, but returns ERROR on fatal error    */
/****************************************************************************/
    STATUS
vspTask(Int16 config)
{ 
    Int32    vspInputTask;          /* Vsp Input Task Ident                 */
    Int32    vspOutputTask;         /* Vsp Output Task Ident                */
    Int16    ttyFd;                 /* tty port file Descriptor             */
    DM_Group vspGroup;              /* VSP Data Manager Group               */

    SEM_ID   dmUpdateSem;	    /* Data Manager Item Change wakeup sem  */

    vspUpdateBits  vspBits;         /* VSP Parameter Update Bits            */

    ibcVspDmItems  vspDmItems;      /* VSP Data Manager Items               */ 

    struct termControl term_control;

                                    /* Line Parameter Variables             */
    Nat16 baud, data, stop, par, proto, boardNum, chan;

    Int16 sioBoardNum, sioPort;

    MBool handshake;
                                    /* Port Name and Dcon strings           */
    char vspTtyName[20], dconPrefix[20];     
                                    /* Setup Vsp TaskPriority               */
    taskPrioritySet(taskIdSelf(), VSP_OUT_PRIORITY);            

                                    /* Read Port Parameters from File       */
    if (fscanf(config,"%hd%hd%s%hd%hd%hd%hd%hd%hd%hd%hd", 
        &sioBoardNum, &sioPort,  dconPrefix,
	&boardNum, &chan, &baud, &data, &stop, &par, &handshake, &proto) != 11)
    {
	printf("Vsp Task: Error Reading Config File\n");
	fclose(config);
	return(ERROR);
    }

#if 0
                                   /* Open Serial port                       */
    if ( (ttyFd = open(vspTtyName, O_RDWR, 0)) == ERROR)
    {
	printf("Vsp Task: Error Openning tty %s\n", vspTtyName);
	return(ERROR);
    }
    printf("Vsp Task: tty port %s is open\n", vspTtyName); 

                                   /* Set parameters for Serial Port         */
    term_control.tc_oflag = setTermControl(baud, data, stop, par);
 
    term_control.tc_iflag = setTermControl(baud, data, stop, par);
                                   
    ioctl( ttyFd, OFLUSH | IFLUSH, 0);

    if( ioctl( ttyFd, SIOSETS, (int) &term_control)!= OK)
      printf ("VSP: Unable to set line options\n");
#endif
   while ((ttyFd = openVspSerialPort(sioBoardNum, sioPort)) == ERROR)
	taskDelay(sysClkRateGet() / 2);
                              
                                   /* Clear Sensor DCon Data Manager handles */
    bzero(&vspDmItems, sizeof(vspDmItems));

                            /* Create Virtual Serial Port Data Manager Items */
    if (createIbcVspTopDmItems(&vspDmItems, (char *) dconPrefix,
                     "VspTopTask", boardNum * CHAN_PER_BOARD + chan ) == ERROR)
    {	
        logMsg("Vsp Task: Error Creating VSP DM Items\n");
	return(ERROR);
    }     
                                    /* Create semaphores                     */
    if ( ((dmUpdateSem = semBCreate(SEM_Q_FIFO, SEM_EMPTY)) == NULL))
    {
        logMsg("VSP Top Task: Error initializing Input Task Resources\n");
        return(ERROR);
    } /* if */

                            /* Create Virtual Serial Port Data Manager Group */
    vspGroup = initIbcVspTopConsumer( &vspDmItems, &vspBits, dmUpdateSem );
  
    if (( vspInputTask =   /* Initialize VSP Input Task   */
         taskSpawn( "vspIn", VSP_IN_PRIORITY, 0,
         VSP_IN_STACKSIZE, (FUNCPTR) vspInTask,
         (int) &vspDmItems, ttyFd, 0, 0, 0, 0, 0, 0, 0, 0 ) ) == ERROR)
    {
        logMsg("VSP Task Top: Error spawning vsp input task\n");
        return(ERROR);
    } /* if */

                                /* Initialize DM item values and default     */
    updateIbcVspTopDmItems (&vspDmItems, baud, data, stop, par, handshake,
                               proto);

    FOREVER                     /* Repeat until micro controller reset       */
    {                           /* Wait for any data items to change         */
	semTake(dmUpdateSem, WAIT_FOREVER);
	
	taskSafe();             /* Prevent task from being deleted during    */
                                /* serial IO and Data Manager updates        */
	
		            /* Check for Virtual Serial Port Parameter Update*/
	ibcVspTopUpdateCheck( ttyFd, &vspDmItems, &vspBits, vspGroup );

	taskUnsafe();           /* Task may now be safely deleted            */

    } /*  FOREVER */

                        /* dm_stop_provider, dm_stop_consumer, dm_delete_group*/
                        /* etc are NOT required when the task exits as the    */
                        /* Data Manager does this automatically when the task */
                        /* is deleted via the taskDeleteHookAdd() and         */
                        /* dm_task_exit functions.                            */

    taskDelete(vspInputTask);          /* Delete Sensor Dcon Input Task       */
    return(OK);         /* That's all folks			              */
} /* vspTask() */

/*****************************************************************************/
/* Function    : vspInTask                                                   */
/* Purpose     : Vsp Input Task.                                             */
/*	                                                                     */
/* Inputs      : Array of Data Manager Item handles & serial chan structure  */
/* Outputs     : Normally runs forever, but exits if error occurs            */
/*****************************************************************************/
    Void
vspInTask(Reg ibcVspDmItems* dmItems, Int16 ttyFd)
{
                                    /* Provider Task for non-static data items*/
    initIbcVspTopProvider  (dmItems, DM_STATIC);
  
    FOREVER
    {
        updateIbcVspTopDm(ttyFd, dmItems ); 
    } /* FOREVER */


                        /* dm_stop_provider, dm_stop_consumer, dm_delete_group*/
                        /* etc are not required when the task exits as the    */
                        /* data manager does this automatically when the task */
                        /* is deleted via the taskDeleteHookAdd() and         */
                        /* dm_task_exit functions.                            */

                        /* that's all folks !                                 */
} /* vspInTask() */















