/****************************************************************************/
/* Copyright 1991, 1992, 1993 MBARI                                         */
/****************************************************************************/
/* Summary  : IBC Navigation Interface Board Functions                      */
/* Filename : nav_if.c                                                      */
/* Author   : Andrew Pearce                                                 */
/* Project  : New ROV IBC Based Data Concentrator                           */
/* Version  : 1.0                                                           */
/* Created  : 09/17/92                                                      */
/* Modified : 03/05/93                                                      */
/* Archived :                                                               */
/****************************************************************************/
/* Modification History:                                                    */
/* $Header: /usr/tiburon/.cvsroot/micro/ibc/boards/nav_if/nav_if.c,v 1.2 1997/05/07 15:31:20 pean Exp $
 * $Log: nav_if.c,v $
 * Revision 1.2  1997/05/07 15:31:20  pean
 * Cleaned up Include files and makefile for new directory structure.
 *
 * Revision 1.1.1.1  1997/05/02 18:51:30  pean
 * Initial check in of IBC microcontroller software
 *
 * Revision 1.2  93/07/02  09:36:54  09:36:54  pean (Andrew Pearce)
 * Minor bug fixes and enhancements for Prototype Vehicle Tests
 * 
 * Revision 1.1  93/03/05  15:57:36  15:57:36  pean (Andrew Pearce)
 * Initial revision
 *
*/
/****************************************************************************/

#pragma model(196)
#pragma nosignedchar

#include "C:/C96/include/stddef.h"      /* C Standard Definitions           */
#include "const.h"                      /* Misc. constants - TRUE/FALSE etc */
#include "types.h"                      /* MBARI style guide declarations   */
#include "malloc.h"                     /* Malloc support routines          */
#include "microdef.h"                   /* Microcontroller definitions      */
#include "microCmd.h"                   /* microcontroller commands         */
#include "applay.h"                     /* Application layer funcitions     */

#include "ibc_card.h"                   /* IBC Board Types and Addresses    */
#include "ibc_cmd.h"                    /* Core IBC application definitions */
#include "ibc_asm.h"                    /* IBC Assembly Language Functions  */

#include "nav_if.h"                     /* Navigation Interface Board Defs  */

/****************************************************************************/
/* Function    : NavBoardSearch                                             */
/* Purpose     : Scans IBC backplane looking for Navigation Interface Boards*/
/* Inputs      : IBC Board Entry Table and maximum table size               */
/* Outputs     : Returns number of boards found                             */
/****************************************************************************/
    Int16
NavBoardSearch(IBC_BoardEntry *IBC_Boards[], Int16 maxCards )
{
    Byte  *addr;                        /* Nav If Board base address        */
    Int16 board;                        /* Counts number of boards found    */
    IBC_BoardEntry *boardEntry;         /* Points to NavIf board data struct*/

    board = 0;                          /* Set board count to zero          */
    if (maxCards > 0)                   /* Check for space in IBC Card Table*/
    {                                   /* Search for Nav Interface Boards  */
        if ( (boardEntry = (IBC_BoardEntry *)
                                        /* NULL boardEntry if board missing */
            NavBoardInit( (Byte *) NAV_INTERFACE_ADDR )) != NULL )
        {                               /* Add Nav If board to IBC Table    */
            IBC_Boards[board++] = boardEntry;
            if (board == maxCards) return(board);
        } /* if */
    } /* if */

    return(board);                      /* Return number of HPS boards found*/
} /* NavBoardSearch() */

/****************************************************************************/
/* Function    : NavBoardInit                                               */
/* Purpose     : Navigation Interface Board Initialization routine          */
/* Inputs      : Base address of navigation interface board                 */
/* Outputs     : Returns pointer to IBC board data structure                */
/****************************************************************************/
    NavBoardEntry*
NavBoardInit( Byte *boardBaseAddr )
{
    NavBoardEntry *NavBoard;            /* Pointer to board entry           */
                                        /* Read Status Register to check if */
                                        /* Board exists                     */
                                        /* Returns OK if board asserts xack */
    if ( ibcBusReadByte( boardBaseAddr + NAV_STATUS_REG ) == ERROR )
        return(( NavBoardEntry *) NULL);
                                       /* Board doesn't exist return NULL  */

                                       /* Allocate space for board entry   */
    NavBoard = (NavBoardEntry *) malloc( sizeof (NavBoardEntry) );
    if (NavBoard == (NavBoardEntry *) NULL )
            return( (NavBoardEntry *) NULL);
                                       /* Insufficient memory return ERROR */

                                       /* Fill out board entry structure   */
    NavBoard->IBC_Board.baseAddress  = boardBaseAddr;
    NavBoard->IBC_Board.boardType    = NAV_INTERFACE;
    NavBoard->IBC_Board.intrLevel    = IBC_INT_LVL_OFF;
    NavBoard->PSU_status = 0;

    return (NavBoard);                  /* Return pointer to Nav If struct */
} /* NavBoardInit() */

/****************************************************************************/
/* Function    : NavBoardReadStatus                                         */
/* Purpose     : Return Navigation Interface Board Status Byte              */
/* Inputs      : Nav Interface Board data structure                         */
/* Outputs     : Returns Board Status Byte or ERROR if IBC bus timeout      */
/****************************************************************************/
    MLocal Int16
NavBoardReadStatus( NavBoardEntry *NavBoard )
{
    if ( NavBoard == NULL)          /* Check for valid Nav If structure     */
         return (ERROR);
                                    /* Read and return Nav If Status Reg    */
    return(ibcBusReadByte (NavBoard->IBC_Board.baseAddress + NAV_STATUS_REG));
} /* NavBoardReadStatus() */

/****************************************************************************/
/* Function    : NavBoardReadSyncro                                         */
/* Purpose     : Reads Navigation Interface Syncro convertor measurement    */
/* Inputs      : Nav Interface Board data structure                         */
/* Outputs     : Returns Syncro measurement or ERROR if IBC bus timeout     */
/****************************************************************************/
    Int16
NavBoardReadSyncro( NavBoardEntry *NavBoard )
{
    Nat32 ibcSyncro;                /* Return value from IBC bus read word  */
    Nat16 rawSyncro;                /* Raw 16 bit convertor reading         */
    Nat16 syncro;                   /* De-scrambled syncro reading          */

    if ( NavBoard == NULL)          /* Check for valid Nav If data struct   */
         return (ERROR);
                                    /* Read status register to syncronize   */
                                    /* hardware state machine & check status*/
    if ( !(ibcBusReadByte( NavBoard->IBC_Board.baseAddress + NAV_STATUS_REG)
            & NAV_SYNCRO_OK ) ) return(ERROR);
                                    /* Syncro status bit indicates bad data */

                                    /* Read 16 bit syncro reg from ibc bus  */
    ibcSyncro = ibcBusReadWord(
            (Word *) (NavBoard->IBC_Board.baseAddress + NAV_SYNCRO_REG) );

                                    /* Check for IBC bus timeout            */
    if ((ibcSyncro & 0x0000ffff) == ERROR)
            return (ERROR);         /* Bus timeout so return ERROR          */

                                    /* Extract result fo IBC bus read       */
    rawSyncro = (Word) (ibcSyncro >> 16);
                                    /* Arrange scrambled bits from hardware */
    syncro = (rawSyncro & 0x3f3f) | ((rawSyncro & 0xc000) >> 8);

    return (syncro);                /* Return syncro reading in bits        */
} /* NavBoardReadSyncro() */

/****************************************************************************/
/* Function    : NavBoardReadStatusCmd                                      */
/* Purpose     : Process command to read Nav Interface board status register*/
/* Inputs      : IBC Card Table, Number of cards & serial command buffer    */
/* Outputs     : None                                                       */
/****************************************************************************/
    Void
NavBoardReadStatusCmd( IBC_BoardEntry* IBC_CardTable[], Int16 IBC_CardCount )
{
    Nat16   card;                   /* Card index into Card Table           */
    Int16   status;                 /* Nav Interface Board status           */

                                    /* Find table index for Nav If Board    */
    if ( (card = ibcBoardTableIndex(IBC_CardTable, IBC_CardCount,
                 NAV_INTERFACE_ADDR, NAV_INTERFACE) ) == ERROR)
    {                               /* Card not present so return error     */
        replyToCommand(1, CMD_ERROR);
        return;
    } /* if */
                                    /* Read Nav Interface Board Status Reg  */
    if ((status = NavBoardReadStatus( (NavBoardEntry *) IBC_CardTable[card]))
                == ERROR)
        replyToCommand(1, CMD_ERROR);       /* Report ERROR to serial port  */
    else
        replyToCommand(2, CMD_OK, status);  /* Report status to serial port */
} /* NavBoardReadStatusCmd() */


/****************************************************************************/
/* Function    : NavBoardReadSyncroCmd                                      */
/* Purpose     : Process command to read Nav If board syncro convertor      */
/* Inputs      : IBC Card Table, Number of cards & serial command buffer    */
/* Outputs     : None                                                       */
/****************************************************************************/
   Void
NavBoardReadSyncroCmd(IBC_BoardEntry* IBC_CardTable[], Int16 IBC_CardCount)
{
    Nat16   card;               /* Card index into Card Table               */
    Int16   syncro;             /* Nav Interface syncro reading             */

                                /* Find card table index for Nav If Board   */
    if ( (card = ibcBoardTableIndex(IBC_CardTable, IBC_CardCount,
                 NAV_INTERFACE_ADDR, NAV_INTERFACE) ) == ERROR)
    {                           /* Card not present so return error         */
        replyToCommand(1, CMD_ERROR);
        return;
    } /* if */
                                /* Read Nav Interface Board Syncro Convertor*/
    if ((syncro = NavBoardReadSyncro( (NavBoardEntry *) IBC_CardTable[card]))
            == ERROR)
        replyToCommand(1, CMD_ERROR);       /* Report ERROR to serial port  */
    else
        replyToCommand(2, CMD_OK, syncro);  /* Report syncro to serial port */
} /* NavBoardReadSyncro() */

/****************************************************************************/
/* Function    : NavBoardFunctions                                          */
/* Purpose     : Navigation Interface Board real-time loop functions        */
/* Inputs      : Navigation Interface Board data structure                  */
/* Outputs     : None                                                       */
/****************************************************************************/
   Void
NavBoardFunctions( NavBoardEntry *NavBoard )
{
    Int16 PSU_status;                   /* Nav IF Power Supply Status       */

                                        /* Read new Power Supply Status     */
    if ( (PSU_status = NavBoardReadStatus( NavBoard )) != ERROR)
    {                                   /* Mask off Syncro status bit       */
        PSU_status = PSU_status & ~(NAV_SYNCRO_OK);

                                        /* compare it to the old status     */
        if (NavBoard->PSU_status != (Byte) PSU_status)
            writeServiceRequest(2, NAV_IF_PSU_STATUS, PSU_status);
                                        /* Save status value for next test  */
        NavBoard->PSU_status = (Byte) PSU_status;
    } /* if */

} /* NavBoardFunctions() */

