/******************************************************************************/
/* Copyright 1994 MBARI                                                       */
/******************************************************************************/
/* Summary  : Functions to interface with the Acoustic Doppler Velocimeter    */
/*            serial port.                                                    */
/* Filename : advSerial.c                                                     */
/* Author   : Janice Tarrant                                                  */
/* Project  : Tiburon                                                         */
/* Version  : Version 1.0                                                     */
/* Created  : 11/22/94                                                        */
/* Modified :                                                                 */
/* Archived :                                                                 */
/******************************************************************************/
/* Modification History :                                                     */
/* $Header$
 * $Log$
 *
 */
/******************************************************************************/

#include <vxWorks.h>                    /* VxWorks system declarations        */
#include <ioLib.h>                      /* VxWorks I/O library                */
#include <stdioLib.h>                   /* VxWorks standard I/O library       */
#include <semLib.h>                     /* VxWorks semaphore library          */
#include <msgQLib.h>                    /* VxWorks message queue library      */
#include <mbariTypes.h>                 /* MBARI type declarations            */
#include <mbariConst.h>                 /* MBARI general purpose constants    */
#include <usrTime.h>                    /* MBARI time declarations            */
#include <sio32Server.h>                /* server and microcontroller protocol*/
#include <sio32Client.h>                /* microcontroller cmd communications */
#include <microCmd.h>                   /* microcontroller command functions  */
#include <sio32Chan.h>                  /* sio32 serial channel assignments   */
#include <quadSerCmd.h>                 /* VSP function prototypes            */

#include "/usr/micro/ibc/ibc/ibc_card.h"/* IBC board definitions              */

#include "advSerial.h"                  /* serial communication definitions   */

#define SERIAL_DELAY        10000       /* serial delay (microsec)            */
#define NUM_SERIAL_WAITS    3           /* number of times to wait for serial */
                                        /* port (30 millisecond duration)     */
                                        /* IBC Quad Serial Board Address      */
#define ADV_BOARD_ADDRESS  (Word) QUAD_SERIAL_0_ADDR


/******************************************************************************/
/* Function : initAdvSerial                                                   */
/* Purpose  : Initializes the virtual serial port.                            */
/* Inputs   : Serial channel pointer.                                         */
/* Outputs  : Returns OK or ERROR.                                            */
/******************************************************************************/
    Int16
initAdvSerial(sio32Chan *serialChannelPtr)
{
    Byte   buffer[MAX_PACKET_LEN];      /* serial buffer                      */
    MBool  handshake = OFF;             /* no handshaking                     */
#if 0                                   /* serial channel number              */
    Nat16  serialChannelNum = SONAR_IBC_SERIAL_CHAN;
#endif
    Nat16  baudRate = 9600;             /* baud rate                          */
    Nat16  dataBits = 8;                /* data bits                          */
    Nat16  stopBits = 1;                /* stop bits                          */
    Nat16  parity = 2;                  /* parity                             */
    Int16  numBytes;                    /* number of bytes                    */
    Int16  protocol = 1;                /* RS485 protocol                     */
    Int16  trys;                        /* Number of tries for Cmd Enable     */

#if 0
/* initialize the serial channel                                              */
    if (sio32ChanInit(serialChannelNum, "/sio32/adv", serialChannelPtr) ==
        ERROR)
    {
        logMsg("Doppler System WARNING : could not initialize serial channel\n");
        return(ERROR);
    }

/* send command enable to IBC micro                                           */
    for (trys = 0; ((microCmdEnable(serialChannelPtr) == ERROR) &&
         trys < MICRO_ENABLE_TRYS); trys++)
        taskDelay(sysClkRateGet() / 5);
    if (trys == MICRO_ENABLE_TRYS)
    {
        logMsg("Doppler System WARNING : error enabling microcontroller\n");
        return(ERROR);
    }
#endif
/* open quad serial Read port                                                 */
    if (Quad_Serial_Open(serialChannelPtr, (Word) ADV_BOARD_ADDRESS,
        (Word) ADV_READ_CHANNEL_NUMBER) == ERROR)
    {
        logMsg("Doppler System WARNING : could not open read serial port\n");
        return(ERROR);
    }

/* open quad serial Write port                                                */
    if (Quad_Serial_Open(serialChannelPtr, (Word) ADV_BOARD_ADDRESS,
        (Word) ADV_WRITE_CHANNEL_NUMBER) == ERROR)
    {
        logMsg("Doppler System WARNING : could not open write serial port\n");
        return(ERROR);
    }

/* set serial port parameters */
    if (Quad_Serial_SetLineParm(serialChannelPtr, (Word) ADV_BOARD_ADDRESS,
        (Word) ADV_READ_CHANNEL_NUMBER, baudRate, dataBits, stopBits, parity,
        handshake, protocol) == ERROR)
    {
        logMsg("Doppler System WARNING : could not set read port parameters\n");
        return(ERROR);
    }

    if (Quad_Serial_SetLineParm(serialChannelPtr, (Word) ADV_BOARD_ADDRESS,
        (Word) ADV_WRITE_CHANNEL_NUMBER, baudRate, dataBits, stopBits, parity,
        handshake, protocol) == ERROR)
    {
        logMsg("Doppler System WARNING :could not set write port parameters\n");
        return(ERROR);
    }

    return (OK);

} /* initAdvSerial */


/******************************************************************************/
/* Function : closeAdvSerial                                                  */
/* Purpose  : Closes the virtual serial port.                                 */
/* Inputs   : Serial channel pointer.                                         */
/* Outputs  : None.                                                           */
/******************************************************************************/
    Void
closeAdvSerial(sio32Chan *serialChannelPtr)
{
    Quad_Serial_Close(serialChannelPtr, (Word) ADV_BOARD_ADDRESS,
                  (Word) ADV_READ_CHANNEL_NUMBER);

    Quad_Serial_Close(serialChannelPtr, (Word) ADV_BOARD_ADDRESS,
                  (Word) ADV_WRITE_CHANNEL_NUMBER);

} /* closeAdvSerial */


/******************************************************************************/
/* Function : getAdvSerialData                                                */
/* Purpose  : Gets data from the virtual serial port.                         */
/* Inputs   : Serial data structure, buffer and number of bytes.              */
/* Outputs  : Returns number of bytes received.                               */
/******************************************************************************/
    Int16
getAdvSerialData(sio32Chan *serialChannelPtr, Byte buffer[], Int16 numBytes)
{
    Int16 numTermChars;                         /* number of terminal chars   */
    Int16 count = 0;                            /* counter                    */
    Int16 byte;                                 /* byte counter               */
    Int32 byteVal;                              /* byte decimal value         */
    Int32 checksum = 0;                         /* calculated checksum        */
    Int32 advChecksum;                          /* data ensemble checksum     */
    Int32 checkSumLsb, checkSumMsb;             /* checksum lsb and msb       */

/* wait for a terminal character in the buffer                                */
    while ( (numTermChars =
             Quad_Serial_TermChars(serialChannelPtr, (Word) ADV_BOARD_ADDRESS,
                                   (Word) ADV_READ_CHANNEL_NUMBER)) < 1)
    {
        if (count > NUM_SERIAL_WAITS)
        {
            logMsg("Doppler System WARNING : No response from doppler\n");
            return(ERROR);
        }
        taskDelay(sysClkRateGet() / (USECS_PER_SEC / SERIAL_DELAY));
    }

/* get the data ensemble (must flush after each read)                         */
    if (Quad_Serial_Read(serialChannelPtr, (Word) ADV_BOARD_ADDRESS,
        (Word) ADV_READ_CHANNEL_NUMBER, buffer, numBytes) == ERROR)
    {
        logMsg("Doppler System WARNING : problem reading serial port\n");
        return(ERROR);
    }
    Quad_Serial_Flush(serialChannelPtr, (Word) ADV_BOARD_ADDRESS,
                      (Word) ADV_READ_CHANNEL_NUMBER);

/* calculate ensemble checksum                                                */
    for (byte = 0; byte < (numBytes-4); byte+=2)
    {
        sscanf(buffer+byte, "%2x", &byteVal);
        checksum += byteVal;
    }

/* verify ensemble checksum                                                   */
    sscanf(buffer+numBytes-4, "%2x %2x", &checkSumLsb, &checkSumMsb);
    advChecksum = checkSumLsb | (checkSumMsb << 8);

    if (checksum == advChecksum)
        return(OK);
    else
    {
        logMsg("Doppler System WARNING : ensemble checksum incorrect\n");
        return(ERROR);
    }

} /* getAdvSerialData */








