/****************************************************************************/
/* Copyright 1992 to 1996 MBARI                                             */
/****************************************************************************/
/* SummAry  : IBC HPS Board Data Manager Functions for VxWorks              */
/* Filename : hpsDm.c                                                       */
/* Author   : Andrew Pearce                                                 */
/* Project  : Tiburon ROV                                                   */
/* Version  : Version 1.0                                                   */
/* Created  : 06/08/93                                                      */
/* Modified : 08/12/96                                                      */
/* Archived :                                                               */
/****************************************************************************/
/* Modification History:                                                    */
/* $Header: hpsDm.c,v 1.1 93/07/01 14:34:29 pean Exp $
 * $Log:        hpsDm.c,v $
 * Revision 1.1  93/07/01  14:34:29  14:34:29  pean (Andrew Pearce)
 * Initial revision
 *
 *
 */
/****************************************************************************/

#include <vxWorks.h>                /* vxWorks system declarations          */
#include <semLib.h>                 /* vxWorks semaphore functions          */
#include <msgQLib.h>                /* vxWorks Message Queue Library        */

#include <mbariTypes.h>             /* MBARI style guide type declarations  */
#include <mbariConst.h>             /* Miscellaneous MBARI constants        */

#include "sio32.h"                  /* SIO32 hardware and driver information*/
#include <sio32Server.h>            /* Sio32 server communication services  */
#include <sio32Client.h>            /* Sio32 client communication services  */
#include <powerTypes.h>             /* Power management Data Types          */
#include <powerDM.h>                /* Power/Switching Data Manager Items   */

#include <datamgr.h>                /* Data Manager declarations            */
#include <dm_errno.h>               /* Data Manager error declarations      */

#define Boolean MBool               /* Map microcontroller Boolean to MBool */

#include "microcmd.h"               /* Microcontroller commands             */
#include "ibc_card.h"               /* IBC Card Types                       */
#include "ibc_cmd.h"                /* IBC Serial Commands                  */
#include "filter.h"                 /* General Filter Routines              */
#include "high_pwr.h"               /* HPS Board Definitions                */

#include "microDm.h"                /* Micro Data Manager Items & Functions */
#include "switch.h"                 /* IBC Function Libarary Definitions    */
#include "hpsDm.h"                  /* Defines & Functions for hpsDm.c      */

/*****************************************************************************/
/* Function    : createIbcHpsDmItems                                         */
/* Purpose     : Initialize Data Manager Item Handles for IBC HPS Board      */
/* Inputs      : Pointer to structure containing IBC HPS Data Manager Handles*/
/*               and IBC Data Concentrator Name                              */
/* Outputs     : None, but Data Manager Items change                         */
/*****************************************************************************/
    STATUS
createIbcHpsDmItems( ibcHpsDmItems *hpsDmItems, const char* ibcDmPrefix,
   const char* ibcDataCon, Int16 hpsBoardNum )
{
    Int32   item;                   /* Counter for DM Item Initialization   */
    Errno   status;                 /* Result of dm_create function call    */
    const   char   itemPrefix[DM_ITEM_NAME_LEN];
                                    /* Data Manager Item Prefix Name        */

    struct                          /* Data Manager Item Table for table    */
    {                               /* driven item initialization           */
        DM_Item *dmItem;            /* pointer to actual dm item handle     */
        char    *errorMsg;          /* Message to display of dmCreate fails */
        char    *name;              /* Data Manager Item Name               */
        DM_Type type;               /* Data Manager Item Type               */
        DM_Num  len;                /* Data Manager Item Element Count      */
    } hpsDmInit[] =

      { { &hpsDmItems->current,            "HPS Switch Current",
              HPS_CURRENT_DM,                 DM_NAT16, 1 },

        { &hpsDmItems->currentWarnThresh,  "HPS Switch Current Warning Thresh",
              HPS_CURRENT_WARN_THRESH_DM,     DM_NAT16, 1 },

        { &hpsDmItems->currentAlarmThresh, "HPS Switch Current Alarm Thresh",
              HPS_CURRENT_ALARM_THRESH_DM,    DM_NAT16, 1 },

        { &hpsDmItems->currentAlarm,       "HPS Switch Current Alarm",
              HPS_CURRENT_ALARM_DM,           DM_ENUM, 1 },

        { &hpsDmItems->switchTripAlarm,    "HPS Switch Trip Alarm",
              HPS_SWITCH_TRIP_ALARM_DM,       DM_EMPTY, 1 },

        { NO_ITEM, NULL, NULL, DM_ENDT, 0 } };

    sprintf(itemPrefix, "%sHPS%d.", ibcDmPrefix, hpsBoardNum);

                                    /* Clear list of Data Manager Item handles*/
    bzero(hpsDmItems, sizeof(ibcHpsDmItems));

                                   /* Initialize Data Manager Items from table*/
    for (item = 0; hpsDmInit[item].dmItem != NO_ITEM; item++)
    {
        if ((*hpsDmInit[item].dmItem =
             initMicroDmItem(itemPrefix, hpsDmInit[item].name,
             hpsDmInit[item].type, hpsDmInit[item].len)) == ERROR)

        {                           /* Error occurred so print message & exit */
            logMsg("%s: Error Initializing %s DM Item\n",
                ibcDataCon, hpsDmInit[item].errorMsg);
            return(ERROR);
        } /* if */
    } /* for */

    return(OK);                     /* All IBC CPU Data Mgr items initialized */
} /* createIbcHpsDmItems() */

    Void
initIbcHpsProvider( ibcHpsDmItems* hpsItems, Period period )
{
    dm_start_provider(hpsItems->current, period);
} /* initIbcHpsProvider() */

    Void
initIbcHpsAlarmProvider( ibcHpsDmItems* hpsItems )
{
    dm_start_provider(hpsItems->currentAlarm,    DM_STATIC);
    dm_start_provider(hpsItems->switchTripAlarm, DM_STATIC);
} /* initIbcHpsAlarmProvider() */

    DWord
initIbcHpsConsumer( ibcHpsDmItems* hpsItems, hpsUpdateBits *hpsBits,
    SEM_ID updateSem )
{
    DWord hpsGroup;

    hpsGroup = dm_create_group();    /* Create Data Manager Group for HPS  */

    dm_start_consumer(hpsItems->currentWarnThresh,  DM_STATIC, updateSem);
    dm_start_consumer(hpsItems->currentAlarmThresh, DM_STATIC, updateSem);

    dm_group_add_item(hpsGroup, hpsItems->currentWarnThresh,
         &hpsBits->currentWarnBit );

    dm_group_add_item(hpsGroup, hpsItems->currentAlarmThresh,
         &hpsBits->currentAlarmBit );

    return (hpsGroup);
} /* initIbcHpsConsumer() */

    STATUS
ibcConnectHpsDmItems( ibcHpsDmItems *hps, switchEntry *device,
    const char *dataConName,  const char *itemName, char *current,
    char *currentAlarm, char *currentWarnThresh,  char *currentAlarmThresh,
    char *tripAlarm )
{
                                    /* Current Data Manager Items             */
    if ( (device->currentDm = initMicroDmItem(POWER_DM_PREFIX,
          current, DM_NAT16, 1)) == ERROR) return(ERROR);

                                    /* Current Warning Thresh Dm Item         */
    if ( (device->currentWarnThreshDm = initMicroDmItem(POWER_DM_PREFIX,
          currentWarnThresh, DM_NAT16, 1)) == ERROR) return(ERROR);

                                    /* Current Alarm Thresh Dm Item           */
    if ( (device->currentAlarmThreshDm = initMicroDmItem(POWER_DM_PREFIX,
          currentAlarmThresh, DM_NAT16, 1)) == ERROR) return(ERROR);

                                    /* Current Alarm Status Dm Item           */
    if ( (device->currentAlarmDm = initMicroDmItem(POWER_DM_PREFIX,
          currentAlarm, DM_ENUM, 1)) == ERROR) return(ERROR);

                                    /* Trip Event Alarm Status Dm Item        */
    if ( (device->tripAlarmDm = initMicroDmItem(POWER_DM_PREFIX,
          tripAlarm, DM_EMPTY, 1)) == ERROR) return(ERROR);


    dm_connect(hps->current,                 device->currentDm);
    dm_connect(hps->currentAlarm,            device->currentAlarmDm);
    dm_connect(hps->switchTripAlarm,         device->tripAlarmDm);
    dm_connect(device->currentWarnThreshDm,  hps->currentWarnThresh);
    dm_connect(device->currentAlarmThreshDm, hps->currentAlarmThresh);

    hps->deviceSwitch = device;     /* Save switchEntry ptr in hps struct so  */
                                    /* we can set switch state to POWER_ERROR */
                                    /* when a trip event occurs               */

    return(OK);
} /* ibcConnectHpsItems() */

    STATUS
updateIbcHpsDm( sio32Chan *sio32DataChan, Word boardAddr, ibcHpsDmItems *hps )
{
    Nat16 hpsCurrent;

    if (IBC_HPS_GetCurrent( sio32DataChan, boardAddr, &hpsCurrent) != OK)
        return (ERROR);

    return (writeDmItem(hps->current, &hpsCurrent, sizeof(hpsCurrent) ));
} /* updateIbcHpsDm() */

    STATUS
updateIbcHpsAlarmsDm( sio32Chan *sio32DataChan, Word boardAddr,
    ibcHpsDmItems *hps )
{
    ibcAlarm currentAlarm;

    if (IBC_HPS_GetAlarmStatus( sio32DataChan, boardAddr, &currentAlarm) != OK)
        return (ERROR);

                                    /* Write alarm status to Data Manager */
    return (writeDmItem(hps->currentAlarm, &currentAlarm,
                        sizeof(currentAlarm) ));
} /* updateIbcHpsAlarmsDm() */

/*****************************************************************************/
/* Function    : updateIbcHpsDmItems                                         */
/* Purpose     : Reads HPS Board parameters from IBC & update Data Manager   */
/* Inputs      : Array of Data Manager Item handles & serial chan structure  */
/* Outputs     : None, but Data Manager Items change                         */
/*****************************************************************************/
    Void
updateIbcHpsDmItems( sio32Chan* sio32DataChan, Word boardAddr,
    ibcHpsDmItems* hps, const char* ibcDataCon )
{
    Nat16 warn, alarm;

    if (IBC_HPS_GetCurrentThresh( sio32DataChan, boardAddr, &warn, &alarm )
         == ERROR)
        logMsg("%s: Error reading HPS Current Alarm Threshold\n", ibcDataCon);

                                /* HPS Current Alarm Threshold initial values*/
    urgentWriteDmItem( dm_get_connect(hps->currentWarnThresh),
       &warn,  sizeof(warn));

    urgentWriteDmItem( dm_get_connect(hps->currentAlarmThresh),
       &alarm, sizeof(alarm));
} /* updateIbcHpsDmItems() */

    Void
ibcHpsUpdateCheck( sio32Chan* sio32DataChan, Word boardAddr,
    ibcHpsDmItems* hpsItems, hpsUpdateBits *hpsBits, DM_Group hpsGroup )
{
    DWord   hpsGroupBits;           /* Holds dm_group_changes bit vector     */
    Nat16   warn, alarm;

                                    /* Ask Data Manager If HPS items changed */
    if ( (hpsGroupBits = dm_get_group_changes(hpsGroup)) == 0)
        return;

                                    /* HPS Board Current Thresholds          */
    if ( (hpsGroupBits & hpsBits->currentWarnBit)  ||
         (hpsGroupBits & hpsBits->currentAlarmBit) )
    {
                                        /* Read Current Thresholds from dmgr*/
        dm_read( hpsItems->currentWarnThresh, (char *) &warn,
            sizeof(warn), (DM_Time *) NULL);

        dm_read( hpsItems->currentAlarmThresh, (char *) &alarm,
            sizeof(alarm), (DM_Time *) NULL);

       IBC_HPS_SetCurrentThresh(sio32DataChan, boardAddr, warn, alarm);
    } /* if */
} /* ibcHpsUpdateCheck() */

    STATUS
ibcHpsSetCurrentThresh(ibcHpsDmItems *hps, sio32Chan *sio32DataChan,
    Word boardAddr, Nat16 warnThresh, Nat16 alarmThresh)
{
                                /* HPS Current Alarm Threshold initial values*/
    urgentWriteDmItem( dm_get_connect(hps->currentWarnThresh),
       &warnThresh,  sizeof(warnThresh));

    urgentWriteDmItem( dm_get_connect(hps->currentAlarmThresh),
       &alarmThresh, sizeof(alarmThresh));

    IBC_HPS_SetCurrentThresh(sio32DataChan, boardAddr, warnThresh, alarmThresh);
} /* ibcHpsSetCurrentThresh() */

    MBool
processIbcHpsSRQ( Word srqRequest, Byte* buffer, Word hpsBoardAddr,
    ibcHpsDmItems* hps )
{
    Word boardAddr;                 /* IBC Board Address                      */
    Word channel;                   /* IBC Board Channel Number               */
    Word status;                    /* IBC Alarm Status Word                  */
    ibcAlarm alarmStatus;           /* IBC Alarm Status                       */

    switch (srqRequest)
    {
        case HPS_CURRENT_ALARM_SRQ:
            wordsFromBuf(buffer, 3, &srqRequest, &status, &boardAddr);
            alarmStatus = (ibcAlarm) status;

            if (boardAddr != hpsBoardAddr)
                return(FALSE);          /* Address missmatch                 */

            writeDmItem(hps->currentAlarm, &alarmStatus, sizeof(alarmStatus));

                                        /* Set Switch State to POWER_ERROR   */
            if (alarmStatus == MICRO_ALARM)
            {                           /* Post Trip Event Data Manager Item */
                writeDmItem(hps->switchTripAlarm, NULL, 0);
                ibcSwitchPowerError(hps->deviceSwitch);
            } /* if */
            break;

        case HPS_TRIP_DETECTED_SRQ:
            wordsFromBuf(buffer, 2, &srqRequest, &boardAddr);

            if (boardAddr != hpsBoardAddr)
                return(FALSE);          /* Address missmatch                 */
                                        /* Post Trip Event Data Manager Item */
            writeDmItem(hps->switchTripAlarm, NULL, 0);
                                        /* Set Switch State to POWER_ERROR   */
            ibcSwitchPowerError(hps->deviceSwitch);
            break;

        default:
            return(FALSE);              /* SRQ Request not recognized        */

    } /* switch */

    return(TRUE);                       /* SRQ Request recognized            */
} /* processIbcHpsSRQ() */

    STATUS
ibcHpsDefineGfBoard( switchEntry *device, Word gfBoardAddr )
{                               /* Associate GF Board with this HPS switch   */
    if (device == NO_SWITCH)
        return (ERROR);

    device->gfBoardAddr = gfBoardAddr;
    return(OK);
} /* ibcHpsDefineGfBoard() */










