/****************************************************************************/
/* Copyright 1992, 1993 MBARI                                               */
/****************************************************************************/
/* Summary  : IBC High Power Switch Board Functions                         */
/* Filename : high_power.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/high_pwr/high_pwr.c,v 1.2 1997/05/07 15:29:01 pean Exp $
 * $Log: high_pwr.c,v $
 * Revision 1.2  1997/05/07 15:29:01  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.2  93/07/02  09:31:57  09:31:57  pean (Andrew Pearce)
 * Minor bug fixes and enhancements for Prototype Vehicle Tests
 *
 * Revision 1.1  93/03/05  14:23:35  14:23:35  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 "microasm.h"                   /* Assembly language functions      */
#include "microdef.h"                   /* Microcontroller definitions      */
#include "microlib.h"                   /* Microcontroller Library decls.   */
#include "malloc.h"                     /* Malloc support routines          */
#include "microCmd.h"                   /* microcontroller commands         */
#include "applay.h"                     /* Application layer funcitions     */

#include "filter.h"                     /* General Filter Routines          */
#include "ibc_card.h"                   /* IBC Board Types and Addresses    */
#include "ibc_cmd.h"                    /* Core IBC application definitions */
#include "ibc.h"                        /* IBC Function Library Definitions */
#include "ibc_asm.h"                    /* IBC Assembly Language Functions  */

#include "high_pwr.h"                   /* IBC High Power Switch Board Defs */

                                        /* Forward declarations for MLocals */
MLocal Int16 HPS_BoardReadCurrent( HPS_BoardEntry *HPS_Board );
MLocal Void  HPS_CheckCurrent( HPS_BoardEntry *HPS_Board );

/****************************************************************************/
/* Function    : HPS_BoardSearch                                            */
/* Purpose     : Scans IBC backplane looking for High Power Switch Boards   */
/* Inputs      : IBC Board Entry Table and maximum table size               */
/* Outputs     : Returns number of boards found                             */
/****************************************************************************/
    Int16
HPS_BoardSearch( IBC_BoardEntry *IBC_Boards[], Int16 maxCards )
{
    Byte  *addr;                        /* HPS Board base address           */
    Int16 board;                        /* Counts number of HPS board found */
    IBC_BoardEntry *boardEntry;         /* Pointer to HPS board data struct */

    board = 0;                          /* Set board count to zero          */
    if (maxCards > 0)                   /* Check for space in IBC Card Table*/
    {
                                        /* Search for High Power Switch Brds*/
        for (addr =  (Byte *) HIGH_PWR_SWITCH_0_ADDR;
             addr <= (Byte *) HIGH_PWR_SWITCH_7_ADDR;
             addr+= (HIGH_PWR_SWITCH_1_ADDR - HIGH_PWR_SWITCH_0_ADDR) )
        {                               /* NULL boardEntry if board missing */
            if ((boardEntry = (IBC_BoardEntry *) HPS_BoardInit(addr)) != NULL)
            {                           /* Add HPS data struct to IBC Table */
                IBC_Boards[board++] = boardEntry;
                if (board == maxCards)  /* Check if IBC Card Table is full  */
                    return(board);      /* Return number of HPS boards found*/
            } /* if */
        } /* for */
    } /* if */

    return(board);                      /* Return number of HPS boards found*/
} /* HPS_BoardSearch() */

/****************************************************************************/
/* Function    : HPS_BoardInit                                              */
/* Purpose     : High Power Switch Board Initialization routine             */
/* Inputs      : Base address of High Power Switch board                    */
/* Outputs     : Returns pointer to IBC board data structure                */
/****************************************************************************/
    HPS_BoardEntry*
HPS_BoardInit( Byte *boardBaseAddr )
{
    HPS_BoardEntry *HPS_Board;          /* Pointer to board entry           */
                                        /* Check if board exists by reading */
                                        /* Status Register. Returns OK if   */
                                        /* board asserts xack               */
    if ( ibcBusReadByte( boardBaseAddr + HPS_STATUS_REG) == ERROR )
        return(( HPS_BoardEntry *) NULL);
                                        /* Board doesn't exist return NULL  */

                                        /* Allocate space for board entry   */
    HPS_Board = (HPS_BoardEntry *) malloc( sizeof (HPS_BoardEntry) );
    if (HPS_Board == (HPS_BoardEntry *) NULL )
            return( (HPS_BoardEntry *) NULL);
                                        /* Insufficient memory return NULL  */

                                        /* Fill out board entry structure   */
    HPS_Board->IBC_Board.baseAddress  = boardBaseAddr;
    HPS_Board->IBC_Board.boardType    = HIGH_POWER_SWITCH;
    HPS_Board->IBC_Board.intrLevel    = IBC_INT_LVL_OFF;

    HPS_Board->cmdReg = 0;              /* Clear Copy of Command Register   */

    HPS_BoardSwitch( HPS_Board, OFF );  /* Switch OFF High Power Switch     */

                                        /* Check if A to D board installed  */
    HPS_Board->status.adcInstalled = HPS_adcBoardInstalled( HPS_Board );

                                        /* Clear trip detected flag         */
    HPS_Board->status.tripDetected = FALSE;

                                        /* Initialize default alarm levels  */
    HPS_Board->currentWarning = HPS_CURRENT_WARNING;
    HPS_Board->currentAlarm   = HPS_CURRENT_ALARM;
                                        /* Clear current alarm status bits  */
    HPS_Board->status.currentAlarm = (unsigned) MICRO_ALARM_OK;

                                        /* Initialize filtered current data */
    initIIRFilter(&HPS_Board->filter, HPS_MAX_CURRENT);
    HPS_Board->filteredCurrent = 0;

    return (HPS_Board);                 /* Return pointer to HPS data struct*/
} /* HPS_BoardInit() */

/****************************************************************************/
/* Function    : HPS_adcBoardInstalled                                      */
/* Purpose     : Tests for presence of optional A to D convertor board      */
/* Inputs      : HPS Board data structure                                   */
/* Outputs     : Returns TRUE or FALSE                                      */
/****************************************************************************/
    MLocal Boolean
HPS_adcBoardInstalled( HPS_BoardEntry *HPS_Board )
{
                                        /* Assume A to D is installed       */
    HPS_Board->status.adcInstalled = TRUE;
    return (HPS_BoardReadCurrent( HPS_Board) != ERROR);
} /* HPS_adcBoardInstalled() */

/****************************************************************************/
/* Function    : HPS_BoardSwitch                                            */
/* Purpose     : Control state of High Power Switch - On or Off             */
/* Inputs      : HPS Board data structure and desired switch state          */
/* Outputs     : Returns result of IBC Bus Write - OK or ERROR if timeout   */
/****************************************************************************/
   Int16
HPS_BoardSwitch( HPS_BoardEntry *HPS_Board, Boolean state )
{
    if ( HPS_Board == NULL)             /* Check for valid HPS data struct  */
         return (ERROR);

    if (state == ON)                    /* Desired switch state is On       */
    {                                   /* Set software copy of switch state*/
        HPS_Board->status.switchState = ON;
        HPS_Board->cmdReg |= HPS_SWITCH_ON;  /* Set Switch On Bit           */
    } /* if */
    else                                /* Desired switch state is Off      */
    {                                   /* Set software copy of switch state*/
        HPS_Board->status.switchState = OFF;
        HPS_Board->cmdReg &= ~HPS_SWITCH_ON; /* Clear Switch On Bit         */
    } /* else */

    return(ibcBusWriteByte(             /* Set physical switch state        */
        HPS_Board->IBC_Board.baseAddress + HPS_COMMAND_REG, HPS_Board->cmdReg));
} /* HPS_BoardSwitch() */

/****************************************************************************/
/* Function    : HPS_BoardSwitchState                                       */
/* Purpose     : Return Switch and Relay state bits from High Power Switch  */
/* Inputs      : HPS Board data structure                                   */
/* Outputs     : Returns Switch and Relay state bits or ERROR if timeout    */
/****************************************************************************/
    Int16
HPS_BoardSwitchState( HPS_BoardEntry *HPS_Board )
{
    Int16 HPS_status;                   /* Reads status bits from HPS board */

    if ( HPS_Board == NULL)             /* Check for valid HPS data struct  */
         return (ERROR);
                                        /* Read HPS Board Status Register   */
    if ( (HPS_status = ibcBusReadByte(HPS_Board->IBC_Board.baseAddress +
        HPS_STATUS_REG) ) == ERROR)
                return(ERROR);
    else                                /* Mask off two status bits         */
        return(HPS_status & (HPS_SWITCH_STATE | HPS_RELAY_ON) );
} /* HPS_BoardSwitchState() */

/****************************************************************************/
/* Function    : HPS_BoardSwitchCurrent                                     */
/* Purpose     : Return Current reading from High Power Switch              */
/* Inputs      : HPS Board data structure                                   */
/* Outputs     : Returns Current in milliamps                               */
/****************************************************************************/
    Int16
HPS_BoardSwitchCurrent( HPS_BoardEntry *HPS_Board )
{
    if ( HPS_Board == NULL)             /* Check for valid HPS data struct  */
         return (ERROR);
                                        /* Return filtered current          */
    return (HPS_Board->filteredCurrent);
} /* HPS_BoardSwitchCurrent() */

/****************************************************************************/
/* Function    : HPS_BoardReadADCReg                                        */
/* Purpose     : Reads 12 bit value from A to D convertor on High Power Sw  */
/* Inputs      : HPS Board data structure                                   */
/* Outputs     : Returns A to D convertor value or ERROR if timeout         */
/****************************************************************************/
    MLocal Nat32
HPS_BoardReadADCReg( HPS_BoardEntry *HPS_Board )
{
    Int16 HPS_AtoDHigh;                 /* High byte of A to D conversion   */
    Int16 HPS_AtoDLow;                  /* Low byte of A to D conversion    */

                                        /* Select A to D Convertor          */
    ibcBusWriteByte(HPS_Board->IBC_Board.baseAddress + HPS_COMMAND_REG,
         (HPS_Board->cmdReg |= HPS_ADC_SELECT));

                                        /* Read A/D Register High Byte      */
    if (( HPS_AtoDHigh = ibcBusReadByte(
            (HPS_Board->IBC_Board.baseAddress + HPS_ADC_HIGH) )) == ERROR)
                    return ((Nat32) ERROR);

                                        /* Read A/D Register Low Byte       */
    if (( HPS_AtoDLow = ibcBusReadByte(
            (HPS_Board->IBC_Board.baseAddress + HPS_ADC_LOW) )) == ERROR)
                    return ((Nat32) ERROR);

                                        /* Select Status Register           */
    ibcBusWriteByte(HPS_Board->IBC_Board.baseAddress + HPS_COMMAND_REG,
         (HPS_Board->cmdReg &= ~HPS_ADC_SELECT));

                                        /* Combine High and Low Bytes       */
    return( (Nat32) bytesToWord( (Byte) HPS_AtoDHigh, (Byte) HPS_AtoDLow ));
} /* HPS_BoardReadADCReg() */

/****************************************************************************/
/* Function    : HPS_BoardReadCurrent                                       */
/* Purpose     : Reads Current in milliamps from High Power Switch          */
/* Inputs      : HPS Board data structure                                   */
/* Outputs     : Returns current in milliamps or ERROR if timeout           */
/****************************************************************************/
    MLocal Int16
HPS_BoardReadCurrent( HPS_BoardEntry *HPS_Board )
{
    Nat16 startTime;                    /* Conversion start time in ticker  */
    Byte  adcStatus;                    /* A to D convertor status byte     */
    Nat32 HPS_current;                  /* Actual current draw              */

    if ( HPS_Board == NULL)             /* Check for valid HPS data struct  */
        return (ERROR);
                                        /* A to D Board not installed       */
    if (! HPS_Board->status.adcInstalled)
        return (HPS_NO_ADC_BOARD);

    startTime = read_sysclock();        /* record time for A to D timeout   */

                                        /* Start A/D Conversion             */
    HPS_current = HPS_BoardReadADCReg( HPS_Board );

                                        /* Wait for conversion to complete  */
    while ( (( (adcStatus =
        ibcBusReadByte(HPS_Board->IBC_Board.baseAddress + HPS_STATUS_REG))
        & HPS_ADC_DONE) == HPS_ADC_DONE )
        && (( read_sysclock() - startTime ) < HPS_TIMEOUT) );

    if ( (adcStatus & HPS_ADC_DONE) == HPS_ADC_DONE)
        return (ERROR);
                                        /* Read result of conversion        */
    HPS_current = HPS_BoardReadADCReg( HPS_Board );
                                        /* Check for IBC bus timeout        */

    if (( (Nat16) (HPS_current & 0x0000ffff)) == ERROR )
         return(ERROR);
    else                                /* Return current value             */
        return ( (Int16) HPS_MILLIAMPS(HPS_current) );
} /* HPS_BoardReadCurrent() */

/****************************************************************************/
/* Function    : HPS_BoardInterruptOn                                       */
/* Purpose     : Generate Interrupt from High Power Switch Board            */
/* Inputs      : HPS Board data structure                                   */
/* Outputs     : None                                                       */
/****************************************************************************/
    Void
HPS_BoardInterruptOn( HPS_BoardEntry *HPS_Board )
{
                                           /* Set Interrupt On Bit          */
    ibcBusWriteByte( HPS_Board->IBC_Board.baseAddress + HPS_COMMAND_REG,
         (HPS_Board->cmdReg |= HPS_INTERRUPT_ON) );
} /* HPS_BoardInterruptOn() */

/****************************************************************************/
/* Function    : HPS_BoardInterruptOff                                      */
/* Purpose     : Clear Interrupt from High Power Switch Board               */
/* Inputs      : HPS Board data structure                                   */
/* Outputs     : None                                                       */
/****************************************************************************/
    Void
HPS_BoardInterruptOff( HPS_BoardEntry *HPS_Board )
{
                                           /* Clear Interrupt On Bit        */
    ibcBusWriteByte( HPS_Board->IBC_Board.baseAddress + HPS_COMMAND_REG,
         (HPS_Board->cmdReg &= ~HPS_INTERRUPT_ON) );
} /* HPS_BoardInterruptOff() */

/****************************************************************************/
/* Function    : HPS_BoardIsr                                               */
/* Purpose     : High Power Switch Board Interrupt Service Routine          */
/* Inputs      : HPS Board data structure                                   */
/* Outputs     : None                                                       */
/****************************************************************************/
    Void
HPS_BoardIsr( HPS_BoardEntry *HPS_Board )
{                               /* Board interrupts when an over current or */
                                /* over temperature condition occurs        */
    HPS_Board->status.tripDetected = TRUE;

                                /* Clear interrupt by writing to HPS board  */
                                /* Desired state is Interrupt Off, Status   */
                                /* Register Selected and Switch Off since   */
                                /* the intr indicates the Switch is off     */
    HPS_BoardInterruptOff( HPS_Board );
} /* HPS_BoardIsr() */

/****************************************************************************/
/* Function    : HPS_SwitchControlCmd                                       */
/* Purpose     : Process command to set High Power Switch On or Off         */
/* Inputs      : IBC Card Table, Number of cards & serial command buffer    */
/* Outputs     : None, but switch state is modified                         */
/****************************************************************************/
    Void
HPS_SwitchControlCmd( IBC_BoardEntry* IBC_CardTable[], Int16 IBC_CardCount,
         Byte *commandBuf )
{
    Byte    *boardAddr;         /* HPS Board base address from command buf  */
    Boolean state;              /* HPS Board desired switch state           */
    Nat16   card;               /* Card index into Card Table               */
    Word    command;            /* Serial command word - ignored            */
    HPS_BoardEntry *HPS_Board;  /* HPS board data structure                 */

                                /* Extract command and arguments from buffer*/
    wordsFromBuf(commandBuf, 3, &command, &boardAddr, &state);

                                /* Find card table index for this address   */
    if ( (card = ibcBoardTableIndex(IBC_CardTable, IBC_CardCount,
                 boardAddr, HIGH_POWER_SWITCH) ) == ERROR)
    {                           /* Card not present so return error         */
        replyToCommand(1,EARGUMENT);
        return;
    } /* if */

                /* Get pointer to HPS data structure        */
    HPS_Board = (HPS_BoardEntry *) IBC_CardTable[card];

    state = (state ? ON : OFF); /* Translate any non-zero value to ON       */

                                /* Change physical switch state             */
    if (HPS_BoardSwitch( HPS_Board, state) != ERROR)
        replyToCommand(1, CMD_OK);      /* Report status to serial port     */
    else
        replyToCommand(1, CMD_ERROR);   /* Report ERROR to serial port      */

     if (state == OFF)
     {
         HPS_Board->filteredCurrent = 0;
         HPS_CheckCurrent(HPS_Board);
     } /* if */
} /* HPS_SwitchControlCmd() */

/****************************************************************************/
/* Function    : HPS_SwitchStatusCmd                                        */
/* Purpose     : Process command to read state of HPS switch and relay      */
/* Inputs      : IBC Card Table, Number of cards & serial command buffer    */
/* Outputs     : None                                                       */
/****************************************************************************/
    Void
HPS_SwitchStatusCmd( IBC_BoardEntry* IBC_CardTable[], Int16 IBC_CardCount,
         Byte *commandBuf )
{
    Byte    *boardAddr;         /* HPS Board base address from command buf  */
    Nat16   card;               /* Card index into Card Table               */
    Word    switchState;        /* High Power Switch State                  */

                                /* Extract board address from buffer        */
    boardAddr = (Byte*) wordFromBuf(commandBuf, sizeof(Word));

                                /* Find card table index for this address   */
    if ( (card = ibcBoardTableIndex(IBC_CardTable, IBC_CardCount,
                 boardAddr, HIGH_POWER_SWITCH) ) == ERROR)
    {                           /* Card not present so return error         */
        replyToCommand(1, EARGUMENT);
        return;
    } /* if */
                                /* Read physical switch state from HPS Board*/
    if (( switchState = HPS_BoardSwitchState( (HPS_BoardEntry *)
         IBC_CardTable[card] )) == ERROR)
        replyToCommand(1, CMD_ERROR);         /* Report ERROR to serial port*/
    else
                                              /* Report switch status       */
        replyToCommand(2, CMD_OK, switchState);
} /* HPS_SwitchStatusCmd() */

/****************************************************************************/
/* Function    : HPS_ReadCurrentCmd                                         */
/* Purpose     : Process command to read current from High Power Switch     */
/* Inputs      : IBC Card Table, Number of cards & serial command buffer    */
/* Outputs     : None                                                       */
/****************************************************************************/
    Void
HPS_ReadCurrentCmd( IBC_BoardEntry* IBC_CardTable[], Int16 IBC_CardCount,
     Byte *commandBuf )
{
    Byte    *boardAddr;         /* HPS Board base address from command buf  */
    Nat16   card;               /* Card index into Card Table               */
    Word    switchCurrent;      /* High Power Switch Current Measurement    */

    boardAddr = (Byte*) wordFromBuf(commandBuf, sizeof(Word));
                                /* Find card table index for this address   */
    if ( (card = ibcBoardTableIndex(IBC_CardTable, IBC_CardCount,
                 boardAddr, HIGH_POWER_SWITCH) ) == ERROR)
    {                           /* Card not present so return error         */
        replyToCommand(1, EARGUMENT);
        return;
    } /* if */
                                /* Send filtered current to serial port     */
    replyToCommand(2, CMD_OK,
           (Word) ((HPS_BoardEntry *) IBC_CardTable[card])->filteredCurrent );
} /* HPS_ReadCurrentCmd() */

/****************************************************************************/
/* Function    : HPS_SetCurrentThreshCmd                                    */
/* Purpose     : Process command to set current warning & alarm set points  */
/* Inputs      : IBC Card Table, Number of cards & serial command buffer    */
/* Outputs     : None                                                       */
/****************************************************************************/
    Void
HPS_SetCurrentThreshCmd( IBC_BoardEntry* IBC_CardTable[], Int16 IBC_CardCount,
         Byte *commandBuf )
{
    Nat16   card;               /* Card index into Card Table               */
    Word    command;            /* Serial command word - ignored            */
    Byte    *boardAddr;         /* HPS Board base address from command buf  */
    HPS_BoardEntry *HPS_Board;  /* HPS board data structure                 */

    Nat16   currentWarn;        /* Current warning threshold                */
    Nat16   currentAlarm;       /* Current alarm threshold                  */

                                /* Extract command and arguments from buffer*/
    wordsFromBuf(commandBuf, 4, &command, &boardAddr,
                 &currentWarn, &currentAlarm);

                                /* Find card table index for this address   */
    if ( (card = ibcBoardTableIndex(IBC_CardTable, IBC_CardCount,
                 boardAddr, HIGH_POWER_SWITCH) ) == ERROR)
    {                           /* Card not present so return error         */
        replyToCommand(1, EARGUMENT);
        return;
    } /* if */
                /* Get pointer to HPS data structure        */
    HPS_Board = (HPS_BoardEntry *) IBC_CardTable[card];

                                /* Store new thresholds in HPS data struct  */
    HPS_Board->currentWarning = currentWarn;
    HPS_Board->currentAlarm   = currentAlarm;

    replyToCommand(1, CMD_OK);  /* Report OK to serial port                 */
} /* HPS_SetCurrentThreshCmd() */

/****************************************************************************/
/* Function    : HPS_GetCurrentThreshCmd                                    */
/* Purpose     : Process command to read current warning & alarm set points */
/* Inputs      : IBC Card Table, Number of cards & serial command buffer    */
/* Outputs     : None                                                       */
/****************************************************************************/
    Void
HPS_GetCurrentThreshCmd( IBC_BoardEntry* IBC_CardTable[], Int16 IBC_CardCount,
         Byte *commandBuf )
{
    Nat16   card;               /* Card index into Card Table               */
    Byte    *boardAddr;         /* HPS Board base address from command buf  */
    HPS_BoardEntry *HPS_Board;  /* HPS board data structure                 */

                                /* Extract HPS board address from buffer    */
    boardAddr = (Byte*) wordFromBuf(commandBuf, sizeof(Word));

                                /* Find card table index for this address   */
    if ( (card = ibcBoardTableIndex(IBC_CardTable, IBC_CardCount,
            boardAddr, HIGH_POWER_SWITCH) ) == ERROR)
    {                           /* Card not present so return error         */
        replyToCommand(1, EARGUMENT);
        return;
    } /* if */

                                /* Get pointer to HPS data structure        */
    HPS_Board = (HPS_BoardEntry *) IBC_CardTable[card];

    replyToCommand(3, CMD_OK,   /* Send threshold values to serial port     */
         (Word) HPS_Board->currentWarning,
         (Word) HPS_Board->currentAlarm);
} /* HPS_GetCurrentThreshCmd() */

/****************************************************************************/
/* Function    : HPS_GetAlarmStatusCmd                                      */
/* Purpose     : Process command to read HPS Board Alarm Status             */
/* Inputs      : IBC Card Table, Number of cards & serial command buffer    */
/* Outputs     : None                                                       */
/****************************************************************************/
    Void
HPS_GetAlarmStatusCmd( IBC_BoardEntry* IBC_CardTable[], Int16 IBC_CardCount,
         Byte *commandBuf )
{
    Nat16   card;               /* Card index into Card Table               */
    Byte    *boardAddr;         /* HPS Board base address from command buf  */
    HPS_BoardEntry *HPS_Board;  /* HPS Board Entry data structure           */

                                /* Extract command and arguments from buffer*/
    boardAddr = (Byte*) wordFromBuf(commandBuf, sizeof(Word));

                                /* Find card table index for this address   */
    if ( (card = ibcBoardTableIndex(IBC_CardTable, IBC_CardCount,
                 boardAddr, HIGH_POWER_SWITCH) ) == ERROR)
    {                           /* Card not present so return error         */
        replyToCommand(1, EARGUMENT);
        return;
    } /* if */
                                /* Extract pointer to HPS data structure    */
    HPS_Board = (HPS_BoardEntry *) IBC_CardTable[card];

                                /* Send Alarm Status to serial port         */
    replyToCommand(2, CMD_OK, (Word) HPS_Board->status.currentAlarm);
 } /* HPS_GetAlarmStatusCmd() */

/****************************************************************************/
/* Function    : HPS_CheckCurrent                                           */
/* Purpose     : Compare current to alarm threshold & shutdown switch       */
/* Inputs      : HPS Board data structure                                   */
/* Outputs     : None                                                       */
/****************************************************************************/
    MLocal Void
HPS_CheckCurrent( HPS_BoardEntry *HPS_Board )
{
    microAlarm alarmStatus;             /* Alarm status from bit field      */

                                        /* Extract current alarm status     */
    alarmStatus = (microAlarm) HPS_Board->status.currentAlarm;

                                        /* Check if current has exceeded the*/
                                        /* current WARNING/ALARM threshold  */
                                        /* & send alarm SRQ's if necessary  */
    if (IBC_AlarmThresholdCheck( HPS_Board->filteredCurrent,
        HPS_Board->currentWarning, HPS_Board->currentAlarm,
        HPS_CURRENT_HYSTERESIS, &alarmStatus ) == TRUE)

        writeServiceRequest(3, HPS_CURRENT_ALARM_SRQ, alarmStatus,
                    HPS_Board->IBC_Board.baseAddress);

                                        /* Update current WARNING bit field */
    HPS_Board->status.currentAlarm = (unsigned) alarmStatus;

    if (alarmStatus == MICRO_ALARM)     /* If Current alarm condition then  */
        HPS_BoardSwitch(HPS_Board, OFF);/* switch off HPS switch            */
} /* HPS_CheckCurrent() */

/****************************************************************************/
/* Function    : HPS_CheckTripDetect                                        */
/* Purpose     : Check for trip events from HPS board which don't interrupt */
/* Inputs      : HPS Board data structure                                   */
/* Outputs     : None                                                       */
/****************************************************************************/
    MLocal Void
HPS_CheckTripDetect( HPS_BoardEntry *HPS_Board )
{
    Int16 HPS_status;                   /* Reads status bits from HPS board */
                                        /* If this board uses interrupts    */
    if (HPS_Board->IBC_Board.intrLevel != IBC_INT_LVL_OFF)
        return;                         /* then do nothing. ISR traps trip  */

    HPS_status =                        /* Read HPS Board Status Register   */
        ibcBusReadByte(HPS_Board->IBC_Board.baseAddress + HPS_STATUS_REG);

    if (HPS_status == ERROR)            /* If IBC Bus timeout, then exit    */
        return;
                                        /* If actual switch state is OFF and*/
                                        /* software expects switch to be ON */
    if ( ( (HPS_status & HPS_SWITCH_STATE) != HPS_SWITCH_STATE ) &&
           (HPS_Board->status.switchState) )
    {
        HPS_BoardSwitch( HPS_Board, OFF );
                                        /* then set trip detected flag      */
        HPS_Board->status.tripDetected = TRUE;
    } /* if */
} /* HPS_CheckTripDetect() */

/****************************************************************************/
/* Function    : HPS_BoardFunctions                                         */
/* Purpose     : High Power Switch real-time loop functions                 */
/* Inputs      : HPS Board data structure                                   */
/* Outputs     : None                                                       */
/****************************************************************************/
    Void
HPS_BoardFunctions( HPS_BoardEntry *HPS_Board )
{
    HPS_CheckTripDetect(HPS_Board);     /* Check for trip events from boards*/
                                        /* with no interrupt assignment     */

                                        /* Check if trip condition was      */
                                        /* detected by HPS_BoardIsr or by   */
    if (HPS_Board->status.tripDetected) /* HPS_CheckTripDetect()            */
    {                                   /* Hardware trip detected so clear  */
                                        /* trip detected flag               */
        HPS_Board->status.tripDetected = FALSE;

                                        /* Report Trip Alarm to serial port */
        writeServiceRequest(2, HPS_TRIP_DETECTED_SRQ,
                            (Word) HPS_Board->IBC_Board.baseAddress);
    } /* if */

                                        /* A to D Board not installed       */
    if (! HPS_Board->status.adcInstalled)
        return;                         /* Ignore current measurements      */

                                        /* Measure and filter HPS current   */
    if ( (HPS_Board->status.switchState) &&
         (IIRfilter(HPS_BoardReadCurrent(HPS_Board),
         &HPS_Board->filteredCurrent, &HPS_Board->filter) == OK ) )

                                        /* Only check curent if switched on */
        HPS_CheckCurrent( HPS_Board );  /* Check for current warning & alarm*/
                                        /* thresholds and report alarm SRQ's*/
} /* HPS_BoardFunctions() */

