/****************************************************************************/
/* Copyright 1994 MBARI                                                     */
/****************************************************************************/
/* Summary  : IBC Isolated Input/Output Board Functions                     */
/* Filename : iso_ioc                                                       */
/* Author   : Andrew Pearce                                                 */
/* Project  : New ROV IBC Based Data Concentrator                           */
/* Version  : 1.0                                                           */
/* Created  : 11/08/94                                                      */
/* Modified : 11/08/94                                                      */
/* Archived :                                                               */
/****************************************************************************/
/* Modification History:                                                    */
/* $Header: /usr/tiburon/.cvsroot/micro/ibc/boards/iso_io/iso_io.c,v 1.2 1997/05/07 15:30:17 pean Exp $
 * $Log: iso_io.c,v $
 * Revision 1.2  1997/05/07 15:30:17  pean
 * Cleaned up Include files and makefile for new directory structure.
 *
 * Revision 1.1.1.1  1997/05/02 18:51:29  pean
 * Initial check in of IBC microcontroller software
 *
 * Revision 1.1  95/02/17  12:29:33  12:29:33  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 "iso_io.h"                     /* Isolated Board Definituions      */

/****************************************************************************/
/* Function    : iso_IO_BoardSearch                                         */
/* Purpose     : Scans IBC backplane looking for Isolated IO Boards         */
/* Inputs      : Pointer to IBC Board Entry Table and maximum table size    */
/* Outputs     : Returns number of boards found                             */
/****************************************************************************/
    Int16
iso_IO_BoardSearch( IBC_BoardEntry *IBC_Boards[], Int16 maxCards )
{
    Byte  *addr;                        /* Parallel IO Board base address   */
    Int16 board;                        /* Counts number of PIO board found */
    IBC_BoardEntry *boardEntry;         /* Pointer to PIO board data struct */

    board = 0;                          /* Set board count to zero          */
    if (maxCards > 0)                   /* Check for space in IBC Card Table*/
    {
                                        /* Search for Parallel IO Boards    */
        for (addr =  (Byte *) ISO_IO_0_ADDR;
             addr <= (Byte *) ISO_IO_2_ADDR;
             addr+= (ISO_IO_1_ADDR - ISO_IO_0_ADDR) )
        {                               /* NULL boardEntry if board missing */
            if ((boardEntry = (IBC_BoardEntry *) iso_IO_BoardInit(addr)) !=NULL)
            {                           /* Add ISO data struct to IBC Table */
                IBC_Boards[board++] = boardEntry;
                if (board == maxCards)  /* Check if IBC Card Table is full  */
                    return(board);      /* Return number of ISO boards found*/
            } /* if */
        } /* for */
    } /* if */

    return(board);                      /* Return number of ISO boards found*/
} /* iso_IO_BoardSearch() */

/****************************************************************************/
/* Function    : iso_IO_BoardInit                                           */
/* Purpose     : Isolated IO Board Initialization routine                   */
/* Inputs      : Base address of Isolated IO board                          */
/* Outputs     : Returns pointer to IBC board data structure                */
/****************************************************************************/
    iso_IO_BoardEntry*
iso_IO_BoardInit( Byte *boardBaseAddr )
{
     iso_IO_BoardEntry  *iso_IO_Board;  /* Pointer to board entry           */

                                        /* Check if board exists by reading */
                                        /* IO input register                */
                                        /* Returns OK if board asserts xack */
    if ( ibcBusReadByte( boardBaseAddr + ISO_IO_INPUT_REG) == ERROR )
        return(( iso_IO_BoardEntry *) NULL);
                                        /* Board doesn't exist return NULL  */

                                        /* Allocate space for board entry   */
    iso_IO_Board = (iso_IO_BoardEntry *) malloc( sizeof (iso_IO_BoardEntry) );
    if (iso_IO_Board == (iso_IO_BoardEntry *) NULL )
        return( (iso_IO_BoardEntry *) NULL);
                                        /* Insufficient memory return ERROR */

                                        /* Configure Output Port            */
    ibcBusWriteByte(ISO_IO_OUTPUT_REG((Nat16) boardBaseAddr), 0);

                                        /* Configure Analog Output Ports    */
    ibcBusWriteByte( ISO_IO_DAC_REG(boardBaseAddr, 0), 0 );
    ibcBusWriteByte( ISO_IO_DAC_REG(boardBaseAddr, 1), 0 );
    ibcBusWriteByte( ISO_IO_DAC_REG(boardBaseAddr, 2), 0 );
    ibcBusWriteByte( ISO_IO_DAC_REG(boardBaseAddr, 3), 0 );

                                        /* Fill out board entry structure   */
    iso_IO_Board->IBC_Board.baseAddress = boardBaseAddr;
    iso_IO_Board->IBC_Board.boardType   = ISOLATED_IO;
    iso_IO_Board->IBC_Board.intrLevel   = IBC_INT_LVL_OFF;

    iso_IO_Board->outputPortCopy = 0;   /* Output port is all 0's           */

                                        /* Switch On ISO Board LED          */
    ibcBusReadByte( boardBaseAddr + ISO_IO_LED_ON);

    return (iso_IO_Board);              /* Return pointer to ISO data struct*/
} /* iso_IO_BoardInit() */

/****************************************************************************/
/* Function    : iso_IO_ReadPort                                            */
/* Purpose     : Read byte from Isolated IO Board Input Port                */
/* Inputs      : Pointer to ISO IO board data structure                     */
/* Outputs     : Returns result of ibcBusReadByte                           */
/****************************************************************************/
   Int16
iso_IO_ReadPort( iso_IO_BoardEntry *iso_IO_Board )
{
    return ( IBCBusReadByte( iso_IO_Board->IBC_Board.baseAddress +
                ISO_IO_INPUT_REG ));
} /* iso_IO_ReadPort */

/****************************************************************************/
/* Function    : iso_IO_WritePort                                           */
/* Purpose     : Write byte to Isolated IO Board Output Port                */
/* Inputs      : Pointer to ISO IO data struct, value to write              */
/* Outputs     : Returns result of ibcBusWriteByte                          */
/****************************************************************************/
   Int16
iso_IO_WritePort( iso_IO_BoardEntry *iso_IO_Board, Byte value )
{
    iso_IO_Board->outputPortCopy = value;

    return (ibcBusWriteByte(ISO_IO_OUTPUT_REG((Nat16)
            iso_IO_Board->IBC_Board.baseAddress), value));
} /* iso_IO_WritePort */

/****************************************************************************/
/* Function    : iso_IO_SetPortBit                                          */
/* Purpose     : Change Isolated IO Board Output Port bit state             */
/* Inputs      : Pointer to ISO IO data struct, bit number, desired state   */
/* Outputs     : Returns result of ibcBusWriteByte                          */
/****************************************************************************/
   Int16
iso_IO_SetPortBit( iso_IO_BoardEntry *iso_IO_Board, Word portBit, MBool state )
{
    if (state)
        iso_IO_Board->outputPortCopy |=  (1 << portBit);
    else
        iso_IO_Board->outputPortCopy &= ~(1 << portBit);

    return (ibcBusWriteByte(
            ISO_IO_OUTPUT_REG((Nat16) iso_IO_Board->IBC_Board.baseAddress),
            iso_IO_Board->outputPortCopy) );
} /* iso_IO_SetPortBit */

/****************************************************************************/
/* Function    : iso_IO_WriteDacPort                                        */
/* Purpose     : Write byte to Isolated IO Board DAC Output Port            */
/* Inputs      : Pointer to ISO IO data struct, DAC Number, value to write  */
/* Outputs     : Returns result of ibcBusWriteByte                          */
/****************************************************************************/
   Int16
iso_IO_WriteDacPort( iso_IO_BoardEntry *iso_IO_Board, Byte dac, Byte value )
{
    return ( IBCBusWriteByte(
        ISO_IO_DAC_REG(iso_IO_Board->IBC_Board.baseAddress, dac), value ));
} /* iso_IO_WriteDacPort */

/****************************************************************************/
/* Function    : iso_IO_ReadPortCmd                                         */
/* Purpose     : Process command to read Isolated IO board input port       */
/* Inputs      : IBC Card Table, Number of cards & serial command buffer    */
/* Outputs     : None                                                       */
/****************************************************************************/
    Void
iso_IO_ReadPortCmd( IBC_BoardEntry* IBC_CardTable[], Int16 IBC_CardCount,
    Byte *commandBuf )
{
    Nat16   card;               /* Card index into Card Table               */
    Word    command;            /* Serial command - discarded               */
    Byte    *boardAddr;         /* ISO Board base address from command buf  */

                                /* Extract command and arguments from buffer*/
    wordsFromBuf(commandBuf, 2, &command, &boardAddr);

                                /* Find card table index for this address   */
    if ( (card = ibcBoardTableIndex(IBC_CardTable, IBC_CardCount,
                 boardAddr, ISOLATED_IO) ) == ERROR)
    {                           /* Card not present so return error         */
        replyToCommand(1, EARGUMENT);
        return;
    } /* if */

    replyToCommand( 2, CMD_OK,
        iso_IO_ReadPort( (iso_IO_BoardEntry *) IBC_CardTable[card]) );
} /* iso_IO_ReadPortCmd() */

/****************************************************************************/
/* Function    : iso_IO_WritePortCmd                                        */
/* Purpose     : Process command to write Isolate IO board output port      */
/* Inputs      : IBC Card Table, Number of cards & serial command buffer    */
/* Outputs     : None                                                       */
/****************************************************************************/
    Void
iso_IO_WritePortCmd( IBC_BoardEntry* IBC_CardTable[], Int16 IBC_CardCount,
    Byte *commandBuf )
{
    Nat16   card;               /* Card index into Card Table               */
    Word    command;            /* Serial command - discarded               */
    Word    value;              /* ISO Board port value to write            */
    Byte    *boardAddr;         /* ISO Board base address from command buf  */

                                /* Extract command and arguments from buffer*/
    wordsFromBuf(commandBuf, 3, &command, &boardAddr, &value);

                                /* Find card table index for this address   */
    if ( (card = ibcBoardTableIndex(IBC_CardTable, IBC_CardCount,
                 boardAddr, ISOLATED_IO) ) == ERROR)
    {                           /* Card not present so return error         */
        replyToCommand(1, EARGUMENT);
        return;
    } /* if */

    if ( iso_IO_WritePort( (iso_IO_BoardEntry *) IBC_CardTable[card],
           (Byte) value ) != ERROR)
        replyToCommand(1, CMD_OK);
    else
        replyToCommand(1, CMD_ERROR);
} /* iso_IO_WritePortCmd() */

/****************************************************************************/
/* Function    : iso_IO_SetPortBBitCmd                                       */
/* Purpose     : Process command to set Isolate IO board output port bit    */
/* Inputs      : IBC Card Table, Number of cards & serial command buffer    */
/* Outputs     : None                                                       */
/****************************************************************************/
    Void
iso_IO_SetPortBitCmd( IBC_BoardEntry* IBC_CardTable[], Int16 IBC_CardCount,
    Byte *commandBuf )
{
    Nat16   card;               /* Card index into Card Table               */
    Word    command;            /* Serial command - discarded               */
    Byte    *boardAddr;         /* ISO Board base address from command buf  */
    Word    portBit;            /* ISO Board port bit number                */
    Word    state;              /* ISO Board port bit desired state         */

                                /* Extract command and arguments from buffer*/
    wordsFromBuf(commandBuf, 4, &command, &boardAddr, &portBit, &state);

                                /* Find card table index for this address   */
    if ( (card = ibcBoardTableIndex(IBC_CardTable, IBC_CardCount,
                 boardAddr, ISOLATED_IO) ) == ERROR)
    {                           /* Card not present so return error         */
        replyToCommand(1, EARGUMENT);
        return;
    } /* if */

    if (iso_IO_SetPortBit( (iso_IO_BoardEntry *) IBC_CardTable[card],
        portBit, state ) != ERROR)
        replyToCommand(1, CMD_OK);
    else
        replyToCommand(1, CMD_ERROR);
} /* iso_IO_SetPortBitCmd() */

/****************************************************************************/
/* Function    : iso_IO_WriteDacCmd                                         */
/* Purpose     : Process command to write Isolate IO board DAC output port  */
/* Inputs      : IBC Card Table, Number of cards & serial command buffer    */
/* Outputs     : None                                                       */
/****************************************************************************/
    Void
iso_IO_WriteDacCmd( IBC_BoardEntry* IBC_CardTable[], Int16 IBC_CardCount,
    Byte *commandBuf )
{
    Nat16   card;               /* Card index into Card Table               */
    Word    command;            /* Serial command - discarded               */
    Word    dac;                /* ISO Board DAC port number                */
    Word    value;              /* ISO Board port value to write            */
    Byte    *boardAddr;         /* ISO Board base address from command buf  */

                                /* Extract command and arguments from buffer*/
    wordsFromBuf(commandBuf, 4, &command, &boardAddr, &dac, &value);

                                /* Find card table index for this address   */
    if ( (card = ibcBoardTableIndex(IBC_CardTable, IBC_CardCount,
                 boardAddr, ISOLATED_IO) ) == ERROR)
    {                           /* Card not present so return error         */
        replyToCommand(1, EARGUMENT);
        return;
    } /* if */

    if ( iso_IO_WriteDacPort( (iso_IO_BoardEntry *) IBC_CardTable[card],
           (Byte) dac, (Byte) value ) != ERROR)
        replyToCommand(1, CMD_OK);
    else
        replyToCommand(1, CMD_ERROR);
} /* iso_IO_WriteDacCmd() */

