/*****************************************************************************/
/* Copyright 1992 to 1996 MBARI                                              */
/*****************************************************************************/
/* Summary  : Emergency Recovery Dcon Interface Module for VxWorks           */
/* Filename : ersDcon.c                                                      */
/* Author   : Andrew Pearce                                                  */
/* Project  : Tiburon ROV                                                    */
/* Version  : Version 1.0                                                    */
/* Created  : 04/10/95                                                       */
/* Modified : 09/10/97                                                       */
/* Archived :                                                                */
/*****************************************************************************/
/* Modification History:                                                     */
/* $Header: $
 * $Log:
  */
/*****************************************************************************/
#include <vxWorks.h>                /* vxWorks system declarations           */
#include <semLib.h>                 /* vxWorks semaphore functions           */
#include <taskLib.h>                /* vxWorks task library functions        */
#include <systime.h>                /* vxWorks time and date functions       */
#include <strLib.h>                 /* vxWorks string function library       */
#include <msgQLib.h>                /* vxWorks Message Queue Library         */

#include <mbariTypes.h>             /* MBARI style guide type declarations   */
#include <mbariConst.h>             /* Miscellaneous constants               */
#include <trig.h>                   /* Trigonometric constants (Pi)          */

#include <rovPriority.h>            /* MBARI Rov Application Priorities      */
#include <time.h>
#include <usrTime.h>                /* MBARI time and date functions         */

#include <datamgr.h>                /* Data Manager declarations             */
#include <dm_errno.h>               /* Data Manager error declarations       */

#include "powerAlloc.h"             /* Device Power Requirements             */
#include "powerDM.h"                /* Power System Data Manager Items       */
#include "powerTypes.h"             /* Power management Data Types           */
#include "console.h"                /* Topside Console Data Manager Items    */

#include "sio32Drv.h"               /* Sio32 hardware and driver information */
#include "sio32Server.h"            /* Sio32 server communication services   */
#include "sio32Client.h"            /* Sio32 client communication services   */
#include "tiburon.h"                /* Tiburon definitions                   */
#include "ersDcon.h"                /* Emergency Dcon Can Definitions        */
#include "sensorDcon.h"             /* Sensor Dcon Definitions               */
#include "vbSystem.h"               /* Variable Buoyancy System definitions  */
#include "filter.h"                 /* median filter data structers          */

#include "microasm.h"               /* Microcontroller constants             */
#include "applic.h"                 /* Microcontroller applications          */
#include "microcmd.h"               /* Microcontroller commands              */
#include "microDm.h"                /* Micro Data Manager Items & Functions  */
#include "microTask.h"              /* Microcontroller Task IO definitions   */

#define Boolean MBool               /* Map microcontroller Boolean to MBool  */

#include "timer.h"                  /* IBC Micro Timer Definitions           */
#include "ibc_card.h"               /* IBC Card Types                        */
#include "ibc_cmd.h"                /* IBC Serial Commands                   */
#include "filter.h"                 /* IBC General IIR Filter Routines       */
#include "gf_board.h"               /* GF/5V Controller Board Definitions    */
#include "low_pwr.h"                /* Low Power Switch Board Definitions    */

#include "ibc.h"                    /* Function Prototypes for ibc.c         */
#include "switch.h"                 /* IBC Function Libarary Definitions     */
#include "ibcDm.h"                  /* IBC Data Manager Interface Functions  */
#include "lpsDm.h"                  /* IBC LPS Board Interface Functions     */
#include "gf_5vDm.h"                /* IBC Ground Fault Board DMgr Functions */
#include "gf_5v.h"                  /* IBC Ground Fault Board Definitions    */
#include "quadSerDm.h"              /* Quad Serial Board Data Manager Funcs  */

#include "ers.h"                    /* Emergency Recovery Dcon Micro         */
#include "ecu.h"                    /* ECU Board Definitions                 */
                                    /* Emergency Dcon Device Name            */
MLocal char* const ersDconName = "ERS Dcon";
                                    /* Emergency Dcon DM Item Name Prefix    */
MLocal char* const ersDconDmPrefix  = ERS_DCON_DM_PREFIX;

#define GF5V_BOARD_ADDR             (Word) GROUND_FAULT_0_ADDR
#define ATOD_BOARD_ADDR             (Word) QUAD_A_TO_D_0_ADDR
#define SERIAL_BOARD_ADDR           (Word) QUAD_SERIAL_0_ADDR
#define DATA_SWITCH_BOARD_ADDR      (Word) DATA_SWITCH_BOARD_0_ADDR

#define LPS_BOARDS          3       /* Number of LPS Board in Emergency Dcon */

MLocal Word lpsBoardAddr[LPS_BOARDS] =  /* LPS Board Assignments             */
{
    LOW_PWR_SWITCH_12V_0_ADDR,
    LOW_PWR_SWITCH_24V_0_ADDR,
    LOW_PWR_SWITCH_24V_1_ADDR
};

MLocal ibcCardConfig ibcCardSet =
{
    LPS_BOARDS + 5,                 /* Number of IBC Cards Expected          */
    {
         CPU196,
         GF5V_BOARD_ADDR,
         LOW_PWR_SWITCH_12V_0_ADDR,
         LOW_PWR_SWITCH_24V_0_ADDR,
         LOW_PWR_SWITCH_24V_1_ADDR,
         ATOD_BOARD_ADDR,
         SERIAL_BOARD_ADDR,
         DATA_SWITCH_BOARD_ADDR
    }
};

MBool compLevelCal = FALSE;        /* Enable printing of compensation sensor */

#define ECU_BOARD_SERIAL_CHAN    3 /* Quad serial Channel for ECU Board      */

Byte ECU_OutputState[nModules];    /* Keeps track of output state            */

                                   /* Build signed value from integer        */
                                   /* and fractional parts                   */
#define FALMOUTH_VALUE(intPart, fractPart) (Flt64) ((((Flt64) abs(intPart)) + \
       (Flt64) fractPart / 10000.0) * (intPart < 0 ? -1.0 : 1.0))

                                    /* 12 V LPS Board Channel Assignments    */
#define PRESSURE_PWR_CHAN         0 /* Falmouth Pressure Sensor Power        */
#define VB_LEVEL_SENSOR_PWR_CHAN  1 /* VB system level sensor excitation     */
#define COMP_LEVEL_PWR_CHAN       2 /* Compensation System level sensor pwr  */
#define SCIENCE_PORT_12V_PWR_CHAN 3 /* 12V Science Port                      */

                                    /* 24 V LPS Board #0 Channel Assignments */
#define ECU_PWR_CHAN              0 /* ECU ValvePack Controler Power Channel */
#define SCIENCE_PORT_24V_PWR_CHAN 1 /* 24 V Science Port                     */

                                    /* 24 V LPS Board #1 Channel Assignments */
#define VB_FILL_SOLENOID          0 /* VB Fill Solenoid Valve control        */
#define DEPLOYMENT_LATCH_RELEASE  1 /* Vehicle Deployment Latch Release      */
#define TOOLSLED_LATCH_RELEASE    2 /* Toolsled Latch Release control        */
#define ACOUSTIC_MODEM_PWR_CHAN   3 /* Acoustic Modem power                  */

#define ERS_SENSOR_DM_PERIOD 100000 /* ERS sensor update period 10 Hz        */
#define ERS_DCON_DM_PERIOD   500000 /* Emergency Dcon Data period 2 Hz       */
#define HUMIDITY_DM_PERIOD  2000000 /* Humidity sensor period .5Hz           */

#define ERS_ONE_SEC_DM_PERIOD USECS_PER_SEC
#define ERS_ONE_MIN_DM_PERIOD USECS_PER_SEC * 60

#define NUM_TASKS                 3 /* Number of co-operating tasks         */

typedef struct                      /* Emergency Dcon Data Mgr Item Handles  */
{
    DM_Item canWaterAlarm;          /* Housing Water Alarm Detected          */
    DM_Item jboxWaterAlarm;         /* J Box Water Alarm Detected            */
    DM_Item waterAlarmThresh;       /* Water Alarm Threshold                 */

    DM_Item vehicleInWater;         /* Vehicle in water sensor status        */
    DM_Item ersOperatingMode;       /* ERS Operating Mode                    */

    DM_Item toolsled240VSwitchReq;
    DM_Item toolsled240VSwitchStatus;

    DM_Item toolsled48VSwitchReq;
    DM_Item toolsled48VSwitchStatus;

    DM_Item deploymentLatchArm;
    DM_Item deploymentLatchRelease;
    DM_Item deploymentLatchJog;
    DM_Item deploymentLatchStatus;
    DM_Item deploymentLatchOnTime;

    DM_Item hydPressure;            /* Hydraulic System pressure PSIA        */
    DM_Item hydPressureWarnThresh;  /* Hydraulic pressure Warning Level PSIA */
    DM_Item hydPressureAlarmThresh; /* Hydraulic pressure Alarm Level PSIA   */
    DM_Item hydPressureAlarm;       /* Hydraulic System pressure Alarm       */

    DM_Item batteryCurrent;         /* Emergency DCon Battery Current mA     */
    DM_Item batteryVoltage;         /* Emergency DCon Battery Voltage mV     */
    DM_Item batteryVoltWarnThresh;  /* Battery Voltage Warning Level mV      */
    DM_Item batteryVoltAlarmThresh; /* Battery Voltage Alarm Level mV        */
    DM_Item batteryVoltAlarm;       /* Battery Voltage Alarm                 */
    DM_Item batteryVoltageCmd;      /* Read Battery Voltage Command          */

    DM_Item batteryLife;
    DM_Item batteryLifeWarnThresh;
    DM_Item batteryLifeAlarmThresh;
    DM_Item batteryLifeAlarm;

    DM_Item vbLevelMM;              /* VB System Level  (mm)                 */
    DM_Item vbVolume;               /* VB System Volume (mm3)                */
    DM_Item vbWeight;               /* VB System Weight (Kg)                 */
    DM_Item vbMotorRunDm;           /* VB Motor Running Status               */

    DM_Item ersDepth;               /* ERS Depth (Meters)                    */
    DM_Item rovnavCmd;              /* ROVNAV Command Received String        */

    DM_Item compLevelPercent;       /* Compensation System Percent Level     */
    DM_Item compLevelVolume;        /* Compensation System Volume  (liters)  */
    DM_Item compLevelAlarm;         /* Compensation Level Alarm              */
    DM_Item compWarnLevel;          /* Compensation Warning Level            */
    DM_Item compAlarmLevel;         /* Compensation Alarm Level              */
    DM_Item compMinLevel;           /* Compensation Minimum Level            */
    DM_Item compMaxLevel;           /* Compensation Maximum Level            */

    DM_Item valve1aSwitch;
    DM_Item valve1bSwitch;
    DM_Item valve2aSwitch;
    DM_Item valve2bSwitch;
    DM_Item valve3aSwitch;
    DM_Item valve3bSwitch;
    DM_Item valve4aSwitch;
    DM_Item valve4bSwitch;
    DM_Item valve5aSwitch;
    DM_Item valve5bSwitch;
    DM_Item valve6aSwitch;
    DM_Item valve6bSwitch;
    DM_Item valve7aSwitch;
    DM_Item valve7bSwitch;

    DM_Item valvePackEnableSwitch;

    DM_Item toolsledHydraulicSwitch;
    DM_Item schillingArmHydraulicSwitch;
    DM_Item spareHydraulicSwitch;
    DM_Item vbHydraulicSwitch;


    ibcCpuDmItems  ibcDm;           /* IBC CPU Data Manager Items            */
    ibcGf5vDmItems gf5vDm;          /* GF/5V Board Data Manager Items        */
    ibcLpsDmItems lpsDm[LPS_BOARDS];/* LPS Board Data manager Items          */
    ibcQuadSerDmItems quadSerDm;    /* Quad Serial Board Data Manager Items  */
} ersDconDmItems;

/*****************************************************************************/

Void ersDconInTask(Reg ersDconDmItems *dmItems,  microIOControl *microIOCtrl);
Void ersDconOutTask(Reg ersDconDmItems *dmItems, microIOControl *microIOCtrl);

MLocal Word processErsDconSRQ(Reg ersDconDmItems* dmItems,
    microIOControl *microIOCtrl);

MLocal Void initEmergencyDconDmItems(ersDconDmItems* dmItems,
         sio32Chan* ersDconDataChan);

STATUS initECUDigitalOutputs(sio32Chan *serialChan);

STATUS setECUDigitalOutputs(sio32Chan *serialChan, int chan, 
         MBool outputValue );
 
/*****************************************************************************/
/* Function    : ersGetWaterAlarmThresh                                 */
/* Purpose     : Reads water alarm threshold value from IBC CPU              */
/* Inputs      : Sio32 channel, pointer to water alarm threshold             */
/* Outputs     : Returns OK or ERROR                                         */
/*****************************************************************************/
    LOCAL STATUS
ersGetWaterAlarmThresh( sio32Chan *IBC_SerialChan,
    Int16 *waterAlarmThresh )
{
                                    /* Send command to microcontroller       */
    return (microCommand( IBC_SerialChan,
          EREC_DCON_APP | GET_WATER_ALARM_THRESH, (Nat16 *)waterAlarmThresh) );
} /* ersGetWaterAlarmThresh() */

/*****************************************************************************/
/* Function    : initWaterAlarmThreshDm                                      */
/* Purpose     : Read Water Alarm Threshold and update data manager item     */
/* Inputs      : Sio32 channel, water alarm threshold dm item handle         */
/* Outputs     : Returns OK or ERROR                                         */
/*****************************************************************************/
    LOCAL STATUS
initWaterAlarmThreshDm( sio32Chan *IBC_SerialChan,
    DM_Item waterAlarmThreshDm )
{
    Int16   waterAlarmThresh;           /* Water Alarm Threshold from IBC    */

                                        /* Get Water Alarm Threshold         */
    if (ersGetWaterAlarmThresh( IBC_SerialChan, &waterAlarmThresh )
        != OK) return (ERROR);
                                        /* We MUST use urgent open here as   */
                                        /* another task is normal provider   */
    return (urgentWriteDmItem(waterAlarmThreshDm, &waterAlarmThresh,
                      sizeof(waterAlarmThresh)) );
} /* initWaterAlarmThreshDm() */

/*****************************************************************************/
/* Function    : writeWaterAlarmThresh                                       */
/* Purpose     : Get water alarm threshold value from dm and send to IBC     */
/* Inputs      : Sio32 channel, water threshold dm item handle               */
/* Outputs     : Returns OK or ERROR                                         */
/*****************************************************************************/
    LOCAL STATUS
writeWaterAlarmThresh( sio32Chan *sio32DataChan, DM_Item waterAlarmThreshDm )
{
    Word   status;                 /* Result of dm_read                     */
    Int16   waterAlarmThresh;       /* Water Alarm Threshold                 */

                                    /* Read Water Alarm Thresh from dmgr     */
    status = dm_read( waterAlarmThreshDm, (char *) &waterAlarmThresh,
         sizeof(waterAlarmThresh), (DM_Time *) NULL);
                                        /* Check for successful dm_read      */
    if ((status == SUCCESS) || (status == EDM_NOPROVIDER))

                                    /* Send command to microcontroller       */
        if ( sendMicroCommand( sio32DataChan, &status, sizeof(status), 2,
             EREC_DCON_APP | SET_WATER_ALARM_THRESH, waterAlarmThresh )
             != ERROR )
                                    /* Check command result                  */
            return (wordFromBuf(&status, 0) == CMD_OK ? OK : ERROR);

    return(ERROR);
} /* writeWaterAlarmThresh() */

/*****************************************************************************/
/* Function    : updateWaterAlarmDm                                          */
/* Purpose     : Reads micro Water Alarm status & updates dmgr items         */
/* Inputs      : Sio32 chan & water alarm status data manager item handles   */
/* Outputs     : Returns OK or ERROR                                         */
/*****************************************************************************/
    LOCAL STATUS
updateWaterAlarmDm( sio32Chan *sio32DataChan,
    DM_Item canWaterAlarmDm, DM_Item jboxWaterAlarmDm )
{
    Word waterAlarmStatus;          /* Microcontroller Water Alarm Status    */
    MBool status;                   /* Boolean state of Water Alarm          */
                                    /* Read Water Alarm Status               */

                                    /* Send command to microcontroller       */
    if (microCommand(sio32DataChan, EREC_DCON_APP | GET_WATER_ALARM,
        &waterAlarmStatus) == ERROR)
        return (ERROR);

    status = ( (waterAlarmStatus & HOUSING_WATER_ALARM_BIT) ? TRUE : FALSE);
    writeDmItem(canWaterAlarmDm, &status, sizeof(status));

    status = ( (waterAlarmStatus & JBOX_WATER_ALARM_BIT) ? TRUE : FALSE);

                                    /* Write water alarm status to Dmgr      */
    return ( writeDmItem(jboxWaterAlarmDm, &status, sizeof(status)) );
} /* updateWaterAlarmDm() */

/*****************************************************************************/
/* Function    : updateERSStateDm                                            */
/* Purpose     : Reads ERS state values and updates dmgr items               */
/* Inputs      : Sio32 chan & in water status data manager item handle       */
/* Outputs     : Returns OK or ERROR                                         */
/*****************************************************************************/
    LOCAL STATUS
updateERSStateDm( sio32Chan *sio32DataChan, ersDconDmItems *dmItems )
{
    ersOperatingMode operatingMode; /* ERS Operating Mode                    */
    Word ersOprMode;                /* ERS Operating mode (word format)      */
    Word vehicleInWater;            /* Vehicle In Water Status               */
    Word toolsledStatus;            /* Toolsled Latch Status Word            */

    Int16 cmdStatus;
    Word  reply[4];                 /* Command Result from microcontroller  */

                                    /* Send command to microcontroller      */
    if ( sendMicroCommand( sio32DataChan, &reply, sizeof(Word) * 4,
         1, EREC_DCON_APP | GET_ERS_STATE ) == ERROR )
        return(ERROR);

                                    /* Check if command result is CMD OK    */
    if (wordFromBuf(&reply, 0) != CMD_OK)
    {
        logMsg("Error reading ERS State Values\n");
        return (ERROR);
    } /* if */
                                    /* Command OK so update thresholds      */
    wordsFromBuf(reply, 4, &cmdStatus, &ersOprMode, &vehicleInWater,
         &toolsledStatus);

    operatingMode = (ersOperatingMode) ersOprMode;

                         /* Use urgent open here as another task is provider*/
    writeDmItem(dmItems->ersOperatingMode, &operatingMode,
         sizeof(operatingMode));

    writeBooleanDmItem(dmItems->vehicleInWater,
        (vehicleInWater ? TRUE : FALSE));


    return (OK);
} /* updateERSStateDm() */

/****************************************************************************/
/* Function    : initCompLevelAlarmThreshDm                                 */
/* Purpose     : Initialize Comp System Alarm Threshold Data Manager Items  */
/* Inputs      : Sio32 channel, pointers to comp level data mgr items       */
/* Outputs     : Returns OK or ERROR                                        */
/****************************************************************************/
    LOCAL STATUS
initCompLevelAlarmThreshDm( sio32Chan *sio32DataChan, DM_Item warnThreshDm,
    DM_Item alarmThreshDm)
{
    Int16 warnLevel, alarmLevel;
    Int16 cmdStatus;
    Word  reply[3];                 /* Command Result from microcontroller  */

                                    /* Send command to microcontroller      */
    if ( sendMicroCommand( sio32DataChan, &reply, sizeof(Word) * 3,
         1, EREC_DCON_APP | GET_COMP_ALARM_LEVELS )
         == ERROR ) return(ERROR);

                                    /* Check if command result is CMD OK    */
    if (wordFromBuf(&reply, 0) != CMD_OK)
    {
        logMsg("Error reading Comp Level Alarm Thresholds\n");
        return (ERROR);
    } /* if */

                                    /* Command OK so update thresholds      */
    wordsFromBuf(reply, 3, &cmdStatus, &warnLevel,  &alarmLevel);

                         /* Use urgent open here as another task is provider*/
    urgentWriteDmItem( warnThreshDm,  &warnLevel,  sizeof(warnLevel));
    urgentWriteDmItem( alarmThreshDm, &alarmLevel, sizeof(alarmLevel));
} /* initCompLevelAlarmThreshDm() */

/****************************************************************************/
/* Function    : updateERSCompLevelAlarmDm                                  */
/* Purpose     : Reads Comp Level Alarm status & updates dmgr items         */
/* Inputs      : Sio32 chan & Comp Level Alarm status data mgr item handle  */
/* Outputs     : Returns OK or ERROR                                        */
/****************************************************************************/
    LOCAL STATUS
updateERSCompLevelAlarmDm( sio32Chan *sio32DataChan,
    DM_Item compLevelAlarmDm )
{
    Word compLevelAlarmStatus;      /* Compensation Level Alarm Status      */
    ibcAlarm compAlarm;             /* Comp Level Alarm in ibcAlarm format  */

                                    /* Send command to microcontroller      */
    if ( microCommand(sio32DataChan, EREC_DCON_APP | GET_COMP_LEVEL_ALARM,
        &compLevelAlarmStatus) );

    compAlarm = (ibcAlarm) compLevelAlarmStatus;

                                    /* Write Comp Level alarm status to Dmgr*/
    return ( writeDmItem(compLevelAlarmDm, &compAlarm, sizeof(compAlarm)) );
} /* updateERSCompLevelAlarmDm() */

/****************************************************************************/
/* Function    : ersDconGetCompLevel                                       */
/* Purpose     : Reads Compensation System Level                            */
/* Inputs      : Sio32 channel, pointer to comp level reading               */
/* Outputs     : Returns OK or ERROR                                        */
/****************************************************************************/
    LOCAL STATUS
ersDconGetCompLevel( sio32Chan *sio32DataChan, Nat16 *compLevel )
{
    Int16 cmdStatus;
    Nat16 rawValue;
    Word  reply[3];                 /* Command Result from microcontroller  */

                                    /* Send command to microcontroller      */
    if ( sendMicroCommand( sio32DataChan, &reply, sizeof(Word) * 3,
         1, EREC_DCON_APP | GET_COMP_LEVEL)
          == ERROR ) return(ERROR);

                                    /* Check if command result is CMD OK    */
    if (wordFromBuf(&reply, 0) != CMD_OK)
    {
        logMsg("Error reading Comp Level\n");
        return (ERROR);
    } /* if */
                                    /* Command OK so update thresholds      */
    wordsFromBuf(reply, 3, &cmdStatus, compLevel,  &rawValue);

    if (compLevelCal != FALSE)
        printf ("Comp raw %5d\n",rawValue);

    return (OK);
} /* ersDconGetCompLevel() */

/****************************************************************************/
/* Function    : updateCompSystemLevelDm                                    */
/* Purpose     : Reads Compensation System Level & updates Data Mgr item    */
/* Inputs      : Sio32 chan & Comp System Level data manager item handle    */
/* Outputs     : Returns OK or ERROR                                        */
/****************************************************************************/
    LOCAL STATUS
updateCompSystemLevelDm( sio32Chan *sio32DataChan, DM_Item levelPercentDm,
    DM_Item levelVolumeDm )
{
    Nat16 compLevel;                /* Comp System Level                    */
    Flt32 volume;                   /* Comp System Volume                   */
                                    /* Read Compensation Level Value        */
    if (ersDconGetCompLevel(sio32DataChan, &compLevel) != OK)
        return(ERROR);

    volume = ((Flt32) compLevel) * COMP_SYSTEM_CAPACITY / 100.0;
    writeDmItem(levelVolumeDm, &volume, sizeof(volume));

    return (writeDmItem(levelPercentDm, &compLevel, sizeof(compLevel)));
} /* updateCompSystemLevelDm() */

/****************************************************************************/
/* Function    : initCompLevelMinMaxDm                                      */
/* Purpose     : Initialize Comp System Min/Max Values Data Manager Items   */
/* Inputs      : Sio32 channel, pointers to comp level data mgr items       */
/* Outputs     : Returns OK or ERROR                                        */
/****************************************************************************/
    LOCAL STATUS
initCompLevelMinMaxDm( sio32Chan *sio32DataChan, DM_Item minLevelDm,
    DM_Item maxLevelDm)
{
    Int16 minLevel, maxLevel;
    Int16 cmdStatus;
    Word  reply[3];                 /* Command Result from microcontroller  */

                                    /* Send command to microcontroller      */
    if ( sendMicroCommand( sio32DataChan, &reply, sizeof(Word) * 3,
         1, EREC_DCON_APP | GET_COMP_LEVEL_SCALING )
         == ERROR ) return(ERROR);

                                    /* Check if command result is CMD OK    */
    if (wordFromBuf(&reply, 0) != CMD_OK)
    {
        logMsg("Error reading Comp Level Min & Max Value\n");
        return (ERROR);
    } /* if */

                                    /* Command OK so update thresholds      */
    wordsFromBuf(reply, 3, &cmdStatus, &minLevel,  &maxLevel);

    if ((minLevel == 0) && (maxLevel == 0))
    {
        minLevel = SENSOR_COMP_LEVEL_MIN;
        maxLevel = SENSOR_COMP_LEVEL_MAX;
    } /* if */

                         /* Use urgent open here as another task is provider*/
    urgentWriteDmItem( minLevelDm, &minLevel, sizeof(minLevel));
    urgentWriteDmItem( maxLevelDm, &maxLevel, sizeof(maxLevel));
} /* initCompLevelMinMaxDm() */

/****************************************************************************/
/* Function    : writeCompMinMaxLevels                                      */
/* Purpose     : Send Compensation System Min/Max values to ERS Dcon        */
/* Inputs      : Sio32 channel, Min/Max level item handles                  */
/* Outputs     : Returns OK or ERROR                                        */
/****************************************************************************/
    MLocal STATUS
writeCompMinMaxLevels( sio32Chan* sio32DataChan,
    DM_Item minLevelDm, DM_Item maxLevelDm )
{
    Nat16 compMinLevel, compMaxLevel;
    Word  status;                      /* Result of serial command         */

    dm_read( minLevelDm, (char *) &compMinLevel,
            sizeof(compMinLevel), (DM_Time *) NULL);

    dm_read( maxLevelDm, (char *) &compMaxLevel,
            sizeof(compMaxLevel), (DM_Time *) NULL);

                                    /* Send command to microcontroller      */
    if ( sendMicroCommand( sio32DataChan, &status, sizeof(status), 3,
             EREC_DCON_APP | SET_COMP_LEVEL_SCALING,
             compMinLevel, compMaxLevel ) != ERROR )

                                    /* Check command result                  */
        return (wordFromBuf(&status, 0) == CMD_OK ? OK : ERROR);

    return(ERROR);
} /* writeCompMinMaxLevels() */

/****************************************************************************/
/* Function    : writeCompAlarmLevels                                       */
/* Purpose     : Send Compensation System Warn/Alarm thresholds ERS Dcon    */
/* Inputs      : Sio32 channel, Warn/Alarm thresholds level item handles    */
/* Outputs     : Returns OK or ERROR                                        */
/****************************************************************************/
    MLocal STATUS
writeCompAlarmLevels( sio32Chan* sio32DataChan,
    DM_Item warnThreshDm, DM_Item alarmThreshDm )
{
    Nat16 warnThresh, alarmThresh;
    Word  status;                      /* Result of serial command         */

    dm_read( warnThreshDm, (char *) & warnThresh, sizeof( warnThresh),
       (DM_Time *) NULL);

    dm_read( alarmThreshDm, (char *) &alarmThresh, sizeof(alarmThresh),
       (DM_Time *) NULL);

                                    /* Send command to microcontroller      */
    if ( sendMicroCommand( sio32DataChan, &status, sizeof(status), 3,
             EREC_DCON_APP | SET_COMP_ALARM_LEVELS,
             warnThresh, alarmThresh ) != ERROR )

                                    /* Check command result                  */
        return (wordFromBuf(&status, 0) == CMD_OK ? OK : ERROR);

    return(ERROR);
} /* writeCompAlarmLevels() */

/****************************************************************************/
/* Function    : initERSBatteryLifeAlarmThreshDm                            */
/* Purpose     : Initialize Battery Life Alarm Threshold Data Manager Items */
/* Inputs      : Sio32 channel, pointers to battery level data mgr items    */
/* Outputs     : Returns OK or ERROR                                        */
/****************************************************************************/
    LOCAL STATUS
initERSBatteryLifeAlarmThreshDm( sio32Chan *sio32DataChan,
    DM_Item warnThreshDm, DM_Item alarmThreshDm)
{
    Flt32 battWarnLevel, battAlarmLevel;
    Int16 warnLevel, alarmLevel;
    Int16 cmdStatus;
    Word  reply[3];                 /* Command Result from microcontroller  */

                                    /* Send command to microcontroller      */
    if ( sendMicroCommand( sio32DataChan, &reply, sizeof(Word) * 3,
         1, EREC_DCON_APP | GET_BAT_LIFE_ALARM_LEVELS )
         == ERROR ) return(ERROR);

                                    /* Check if command result is CMD OK    */
    if (wordFromBuf(&reply, 0) != CMD_OK)
    {
        logMsg("Error reading battery life alarm thresholds\n");
        return (ERROR);
    } /* if */

                                    /* Command OK so update thresholds      */
    wordsFromBuf(reply, 3, &cmdStatus, &warnLevel,  &alarmLevel);

    battWarnLevel  = (Flt32) warnLevel  / 10.0;
    battAlarmLevel = (Flt32) alarmLevel / 10.0;

                         /* Use urgent open here as another task is provider*/
    urgentWriteDmItem(warnThreshDm,  &battWarnLevel,  sizeof(battWarnLevel));
    urgentWriteDmItem(alarmThreshDm, &battAlarmLevel, sizeof(battAlarmLevel));
} /* initERSBatteryLifeAlarmThreshDm() */

/****************************************************************************/
/* Function    : writeERSBatteryLifeAlarmThresh                             */
/* Purpose     : Send Battery Life Warn/Alarm thresholds ERS Dcon           */
/* Inputs      : Sio32 channel, Warn/Alarm thresholds level item handles    */
/* Outputs     : Returns OK or ERROR                                        */
/****************************************************************************/
    MLocal STATUS
writeERSBatteryLifeAlarmThresh( sio32Chan* sio32DataChan,
    DM_Item warnThreshDm, DM_Item alarmThreshDm )
{
    Flt32 battWarnThresh, battAlarmThresh;
    Nat16 warnThresh, alarmThresh;
    Word  status;                      /* Result of serial command         */

    dm_read( warnThreshDm,  (char *) &battWarnThresh, sizeof(battWarnThresh),
       (DM_Time *) NULL);

    dm_read( alarmThreshDm, (char *) &battAlarmThresh, sizeof(battAlarmThresh),
       (DM_Time *) NULL);

    warnThresh  = ((Nat16) battWarnThresh)  * 10;
    alarmThresh = ((Nat16) battAlarmThresh) * 10;

                                    /* Send command to microcontroller      */
    if ( sendMicroCommand( sio32DataChan, &status, sizeof(status), 3,
        EREC_DCON_APP | SET_BAT_LIFE_ALARM_LEVELS, warnThresh, alarmThresh )
        != ERROR )

                                    /* Check command result                  */
        return (wordFromBuf(&status, 0) == CMD_OK ? OK : ERROR);

    return(ERROR);
} /* writeERSBatteryLifeAlarmThresh() */

/****************************************************************************/
/* Function    : updateERSBatteryLifeAlarmsDm                               */
/* Purpose     : Reads Battery Life Alarm status & updates dmgr items       */
/* Inputs      : Sio32 chan & battery alarms data mgr item handles          */
/* Outputs     : Returns OK or ERROR                                        */
/****************************************************************************/
    LOCAL STATUS
updateERSBatteryAlarmsDm( sio32Chan *sio32DataChan,
    DM_Item batteryLifeAlarmDm, DM_Item batteryVoltageAlarmDm)
{
    ibcAlarm batteryAlarm;          /* Battery Alarm in ibcAlarm format    */
    Word  batteryLifeAlarm;
    Word  batteryVoltageAlarm;
    Int16 cmdStatus;
    Word  reply[3];                 /* Command Result from microcontroller  */

                                    /* Send command to microcontroller      */
    if ( sendMicroCommand( sio32DataChan, &reply, sizeof(Word) * 3,
         1, EREC_DCON_APP | GET_BATTERY_ALARMS ) == ERROR )
        return(ERROR);

                                    /* Check if command result is CMD OK    */
    if (wordFromBuf(&reply, 0) != CMD_OK)
    {
        logMsg("Error reading battery alarms\n");
        return (ERROR);
    } /* if */

                                    /* Command OK so update thresholds      */
    wordsFromBuf(reply, 3, &cmdStatus, &batteryLifeAlarm,
         &batteryVoltageAlarm);

    batteryAlarm = (ibcAlarm) batteryVoltageAlarm;
    writeDmItem(batteryVoltageAlarmDm, &batteryAlarm, sizeof(batteryAlarm));

    batteryAlarm = (ibcAlarm) batteryLifeAlarm;
    return ( writeDmItem(batteryLifeAlarmDm, &batteryAlarm,
         sizeof(batteryAlarm)) );
} /* updateERSBatteryAlarmsDm() */

/****************************************************************************/
/* Function    : initERSBatteryVoltAlarmThreshDm                            */
/* Purpose     : Initialize Battery Volt Alarm Threshold Data Manager Items */
/* Inputs      : Sio32 channel, pointers to battery alarm data mgr items    */
/* Outputs     : Returns OK or ERROR                                        */
/****************************************************************************/
    LOCAL STATUS
initERSBatteryVoltAlarmThreshDm( sio32Chan *sio32DataChan,
    DM_Item warnThreshDm, DM_Item alarmThreshDm)
{
    Int16 warnLevel, alarmLevel;
    Int16 cmdStatus;
    Word  reply[3];                 /* Command Result from microcontroller  */

                                    /* Send command to microcontroller      */
    if ( sendMicroCommand( sio32DataChan, &reply, sizeof(Word) * 3,
         1, EREC_DCON_APP | GET_BAT_VOLT_ALARM_LEVELS )
         == ERROR ) return(ERROR);

                                    /* Check if command result is CMD OK    */
    if (wordFromBuf(&reply, 0) != CMD_OK)
    {
        logMsg("Error reading battery volt alarm thresholds\n");
        return (ERROR);
    } /* if */

                                    /* Command OK so update thresholds      */
    wordsFromBuf(reply, 3, &cmdStatus, &warnLevel,  &alarmLevel);

                         /* Use urgent open here as another task is provider*/
    urgentWriteDmItem( warnThreshDm,  &warnLevel,  sizeof(warnLevel));
    urgentWriteDmItem( alarmThreshDm, &alarmLevel, sizeof(alarmLevel));
} /* initERSBatteryVoltAlarmThreshDm() */

/****************************************************************************/
/* Function    : writeERSBatteryVoltAlarmThresh                             */
/* Purpose     : Send Battery Voltage Warn/Alarm thresholds ERS Dcon        */
/* Inputs      : Sio32 channel, Warn/Alarm thresholds level item handles    */
/* Outputs     : Returns OK or ERROR                                        */
/****************************************************************************/
    MLocal STATUS
writeERSBatteryVoltAlarmThresh( sio32Chan* sio32DataChan,
    DM_Item warnThreshDm, DM_Item alarmThreshDm )
{
    Flt32 battWarnThresh, battAlarmThresh;
    Nat16 warnThresh, alarmThresh;
    Word  status;                      /* Result of serial command         */

    dm_read( warnThreshDm,  (char *) &battWarnThresh, sizeof(battWarnThresh),
       (DM_Time *) NULL);

    dm_read( alarmThreshDm, (char *) &battAlarmThresh, sizeof(battAlarmThresh),
       (DM_Time *) NULL);

    warnThresh  = ((Nat16) battWarnThresh)  * 10;
    alarmThresh = ((Nat16) battAlarmThresh) * 10;

                                    /* Send command to microcontroller      */
    if ( sendMicroCommand( sio32DataChan, &status, sizeof(status), 3,
        EREC_DCON_APP | SET_BAT_VOLT_ALARM_LEVELS, warnThresh, alarmThresh )
        != ERROR )

                                    /* Check command result                  */
        return (wordFromBuf(&status, 0) == CMD_OK ? OK : ERROR);

    return(ERROR);
} /* writeERSBatteryVoltAlarmThresh() */

/****************************************************************************/
/* Function    : readERSBatteryVoltageCmd                                   */
/* Purpose     : Send Battery Voltage Command to ERS Dcon                   */
/* Inputs      : Sio32 channel                                              */
/* Outputs     : Returns OK or ERROR                                        */
/****************************************************************************/
    MLocal STATUS
readERSBatteryVoltageCmd( sio32Chan* sio32DataChan )
{
    Word  status;                    /* Result of serial command            */

    if ( sendMicroCommand( sio32DataChan, &status, sizeof(Word),
         1, EREC_DCON_APP | READ_BATTERY_VOLTAGE )
         == ERROR ) return(ERROR);

                                    /* Check command result                  */
    return (wordFromBuf(&status, 0) == CMD_OK ? OK : ERROR);
} /* readERSBatteryVoltageCmd() */

/****************************************************************************/
/* Function    : initHydPressureAlarmThreshDm                               */
/* Purpose     : Initialize Hydraulic Pressure Alarm Threshold DM Items     */
/* Inputs      : Sio32 channel, hyd pressure data mgr items                 */
/* Outputs     : Returns OK or ERROR                                        */
/****************************************************************************/
    LOCAL STATUS
initHydPressureAlarmThreshDm( sio32Chan *sio32DataChan, DM_Item warnThreshDm,
    DM_Item alarmThreshDm)
{
    Int16 warnLevel, alarmLevel;
    Int16 cmdStatus;
    Word  reply[3];                 /* Command Result from microcontroller  */

                                    /* Send command to microcontroller      */
    if ( sendMicroCommand( sio32DataChan, &reply, sizeof(Word) * 3,
         1, EREC_DCON_APP | GET_HYD_PRESS_ALARM_LVLS )
         == ERROR ) return(ERROR);

                                    /* Check if command result is CMD OK    */
    if (wordFromBuf(&reply, 0) != CMD_OK)
    {
        logMsg("Error reading Hydraulic Pressure Alarm Thresholds\n");
        return (ERROR);
    } /* if */
                                    /* Command OK so update thresholds      */
    wordsFromBuf(reply, 3, &cmdStatus, &warnLevel,  &alarmLevel);

                         /* Use urgent open here as another task is provider*/
    urgentWriteDmItem( warnThreshDm,  &warnLevel,  sizeof(warnLevel));
    urgentWriteDmItem( alarmThreshDm, &alarmLevel, sizeof(alarmLevel));
} /* initHydPressureAlarmThreshDm() */

/****************************************************************************/
/* Function    : writeHydPressureAlarmThresh                                */
/* Purpose     : Send Hydraulic Pressure Warn/Alarm thresholds ERS Dcon     */
/* Inputs      : Sio32 channel, Warn/Alarm thresholds level item handles    */
/* Outputs     : Returns OK or ERROR                                        */
/****************************************************************************/
    MLocal STATUS
writeHydPressureAlarmThresh( sio32Chan* sio32DataChan,
    DM_Item warnThreshDm, DM_Item alarmThreshDm )
{
    Nat16 warnThresh, alarmThresh;
    Word  status;                      /* Result of serial command         */

    dm_read( warnThreshDm,  (char *) &warnThresh, sizeof(warnThresh),
       (DM_Time *) NULL);

    dm_read( alarmThreshDm, (char *) &alarmThresh, sizeof(alarmThresh),
       (DM_Time *) NULL);

                                     /* Send command to microcontroller      */
    if ( sendMicroCommand( sio32DataChan, &status, sizeof(status), 3,
        EREC_DCON_APP | SET_HYD_PRESS_ALARM_LVLS, warnThresh, alarmThresh )
        != ERROR )
                                    /* Check command result                  */
        return (wordFromBuf(&status, 0) == CMD_OK ? OK : ERROR);

    return(ERROR);
} /* writeHydPressureAlarmThresh() */

/****************************************************************************/
/* Function    : updateVBSystemData                                         */
/* Purpose     : Update Variable Buoyancy system values                     */
/* Inputs      : Sio32 chan, VB heigth sensor value & dmItems               */
/* Outputs     : DM item values are updates                                 */
/****************************************************************************/
    LOCAL Void
updateVBSystemData(Int16 vbLevelDeciMM, ersDconDmItems *dmItems)
{
    Flt32 vbLevelMM;
    Flt32 vbLevelCM;
    Flt32 vbWeightKg;
    Flt32 sphereRadius = VB_SPHERE_RADIUS;
    Flt32 sphereVolume;
    Flt32 totalVolume;

                                       /* Convert to Millimeters              */
    vbLevelMM = (Flt32) vbLevelDeciMM /  10.0;
    writeDmItem(dmItems->vbLevelMM, &vbLevelMM,   sizeof(vbLevelMM));
    return;

                                       /* Subtract height sensor fixed offset */
    vbLevelDeciMM -= (VB_HEIGHT_SENSOR_OFFSET * 10);

    if (vbLevelDeciMM <= 0)
        vbLevelMM = vbLevelCM = totalVolume = vbWeightKg = 0.0;

    else
    {                                  /* Clip height sensor at sphere height */
        vbLevelDeciMM = min(vbLevelDeciMM , (Int16)(VB_SPHERE_RADIUS * 2 * 100));

                                       /* Convert to Millimeters              */
        vbLevelMM = (Flt32) vbLevelDeciMM /  10.0;
        vbLevelCM = (Flt32) vbLevelDeciMM / 100.0;

        sphereVolume = PI * ( (sphereRadius * vbLevelCM * vbLevelCM) -
                             ((vbLevelCM * vbLevelCM * vbLevelCM) / 3) );

        totalVolume = sphereVolume * (VB_SPHERE_COUNT - 1);

                                     /* Subtract height offset for 4th sphere */
        vbLevelCM -= VB_SPHERE_OFFSET;
        sphereVolume = PI * ( (sphereRadius * vbLevelCM * vbLevelCM) -
                             ((vbLevelCM * vbLevelCM * vbLevelCM) / 3) );

        totalVolume += sphereVolume;

        vbWeightKg = totalVolume * VB_FRESHWATER_DENSITY / 1000.0;
    } /* else */

    writeDmItem(dmItems->vbLevelMM, &vbLevelMM,   sizeof(vbLevelMM));
    writeDmItem(dmItems->vbVolume,  &totalVolume, sizeof(totalVolume));
    writeDmItem(dmItems->vbWeight,  &vbWeightKg,  sizeof(vbWeightKg));
} /* updateVBSystemDm() */

/****************************************************************************/
/* Function    : updateERSTelemetryDm                                       */
/* Purpose     : Reads Sensor Telemetry values from ERS & update Data Mgr   */
/* Inputs      : Sio32 chan, hyd pressure, vb Level & battery voltage items */
/* Outputs     : Returns OK or ERROR                                        */
/****************************************************************************/
    LOCAL STATUS
updateERSTelemetryDm(sio32Chan *sio32DataChan, ersDconDmItems *dmItems)
{
    Nat16 hydPressure;              /* Hydraulic Pressure Sensor            */
    Int16 vbLevelDeciMM;            /* vb System Level Millimeters/10       */
    Nat16 batteryUpdate;
    Nat16 batteryVoltage;           /* ERS Battery Voltage                  */
    Nat16 batteryCurrent;           /* ERS Battery Current                  */
    Nat16 batteryLife;              /* ERS Battery Life remaining           */

    Int16 pressureInteger;
    Int16 pressureFraction;
    Flt64 pressure, depth;
    Flt32 batteryLifeAmpHours;

    vbMotorRunMode vbMotorRun = VB_MOTOR_OFF;

    Int16 cmdStatus;
    Word  reply[9];                 /* Command Result from microcontroller  */

                                    /* Send command to microcontroller      */
    if ( sendMicroCommand( sio32DataChan, &reply, sizeof(Word) * 9,
         1, EREC_DCON_APP | GET_TELEMETRY ) == ERROR )
        return(ERROR);
                                    /* Check if command result is CMD OK    */
    if (wordFromBuf(&reply, 0) != CMD_OK)
    {
        logMsg("Error reading ERS Telemetry\n");
        return (ERROR);
    } /* if */
                                    /* Command OK so update thresholds      */
    wordsFromBuf(reply, 9, &cmdStatus, &hydPressure,  &vbLevelDeciMM,
        &batteryUpdate, &batteryLife, &batteryVoltage, &batteryCurrent,
        &pressureInteger, &pressureFraction);

    dm_read( dmItems->vbMotorRunDm, (char *) &vbMotorRun, sizeof(vbMotorRun),
        (DM_Time *) NULL );

    if (vbMotorRun == VB_MOTOR_OFF)
      hydPressure = 0;

    writeDmItem(dmItems->hydPressure, &hydPressure, sizeof(hydPressure));

    updateVBSystemData(vbLevelDeciMM, dmItems);

    pressure = FALMOUTH_VALUE(pressureInteger, pressureFraction);
    depth = (pressure * DECIBARS_TO_METERS);
    writeDmItem(dmItems->ersDepth, &depth, sizeof(depth));

    if (batteryUpdate & BATTERY_VOLTAGE_UPDATE)
        writeDmItem(dmItems->batteryVoltage, &batteryVoltage,
            sizeof(batteryVoltage));

    if (batteryUpdate & BATTERY_CURRENT_UPDATE)
        writeDmItem(dmItems->batteryCurrent, &batteryCurrent,
            sizeof(batteryCurrent));

    if (batteryUpdate & BATTERY_LIFE_UPDATE)
    {
        batteryLifeAmpHours = ((Flt32) (batteryLife)) / 10.0;
        return (writeDmItem(dmItems->batteryLife, &batteryLifeAmpHours,
            sizeof(batteryLifeAmpHours)));
    } /* if */
} /* updateERSTelemetryDm() */

    MLocal STATUS
killToolsledPower( ersDconDmItems *dmItems, SEM_ID dmUpdateSem )
{
    switchStatus switchState;
    switchStatus switchRequest = SWITCH_OFF;

    dm_read(dmItems->toolsled240VSwitchStatus, &switchState,
           sizeof(switchState), (DM_Time *) NULL);

    if (switchState != SWITCH_OFF)
    {                           /* Flush switch request semaphore    */
        semTake(dmUpdateSem, NO_WAIT);
                                /* Switch off Toolsled 240V Power    */
        writeDmItem(dmItems->toolsled240VSwitchReq, &switchRequest,
                    sizeof(switchRequest));

                                /* Wait for power to be switched off */
        if (semTake(dmUpdateSem, sysClkRateGet()) != OK)
            return (ERROR);

        if (dm_read(dmItems->toolsled240VSwitchStatus, &switchState,
            sizeof(switchState), (DM_Time *) NULL) != SUCCESS)
            return(ERROR);

        if (switchState != SWITCH_OFF)
            return (ERROR);
    } /* if */

    dm_read(dmItems->toolsled48VSwitchStatus, &switchState,
           sizeof(switchState), (DM_Time *) NULL);

    if (switchState != SWITCH_OFF)
    {                           /* Flush switch request semaphore    */
        semTake(dmUpdateSem, NO_WAIT);
                                /* Switch off Toolsled 48V Power     */
        writeDmItem(dmItems->toolsled48VSwitchReq, &switchRequest,
                    sizeof(switchRequest));

                                /* Wait for power to be switched off */
        if (semTake(dmUpdateSem, sysClkRateGet()) != OK)
            return (ERROR);

        if (dm_read(dmItems->toolsled48VSwitchStatus, &switchState,
            sizeof(switchState), (DM_Time *) NULL) != SUCCESS)
            return(ERROR);

        if (switchState != SWITCH_OFF)
            return (ERROR);
    } /* if */

    return(OK);
} /* killToolsledPower() */


    MLocal Void
writeErsLatchStatusDm( DM_Item toolsledLatchArmDm,
    DM_Item toolsledLatchStatusDm, ersLatchMode latchStatus)
{
    Nat16 armCode = 0;

    if (latchStatus == LATCH_DISARMED)
    {
        dm_read(toolsledLatchArmDm, (char *) &armCode, sizeof(armCode),
           (DM_Time *) NULL);

        if (armCode != 0)
        {
            armCode = 0;
            urgentWriteDmItem(toolsledLatchArmDm, &armCode, sizeof(armCode));
        } /* if */
    } /* if */

    urgentWriteDmItem(toolsledLatchStatusDm, &latchStatus,
         sizeof(latchStatus));
} /* writeErsLatchStatusDm() */


    MLocal STATUS
executeLatchArm(MBool armState, char *powerReqDmName, char *powerOkDmName,
    Int16 power, DM_Item latchArmDm, DM_Item latchStatusDm)
{
    if (armState == ON)
    {                              /* Request power from Power Manager       */
        if (staticPowerMgrRequest(powerReqDmName,
             powerOkDmName, power, A48, HOTEL) == OK)
           writeErsLatchStatusDm(latchArmDm, latchStatusDm, LATCH_ARMED);
        else
           writeErsLatchStatusDm(latchArmDm, latchStatusDm, LATCH_ARMED_NO_PWR);

        return (OK);  /* Arm = ON request succeeded         */
    } /* if */

    else
    {
        staticPowerMgrRequest(powerReqDmName, powerOkDmName, 0, A48, HOTEL);
        writeErsLatchStatusDm(latchArmDm, latchStatusDm, LATCH_DISARMED);

        return (OK);     /* Arm = OFF request succeeded        */
    } /* else */
} /* executeLatchArm() */


    MLocal STATUS
ersArmDeploymentLatch( sio32Chan* sio32DataChan, DM_Item deploymentLatchArmDm,
    DM_Item deploymentLatchStatusDm)
{
    Word  status;
    Nat16 armCode;

    if (dm_read(deploymentLatchArmDm, (char *) &armCode, sizeof(armCode),
        (DM_Time *) NULL) != SUCCESS)
        return(ERROR);

                                    /* Send command to microcontroller      */
    if (sendMicroCommand( sio32DataChan, &status, sizeof(status), 3,
        EREC_DCON_APP | ARM_DEPLOYMENT_LATCH, armCode, TRUE ) != ERROR )
    {                               /* Check that command was executed and  */
                                    /* confirm arm code is correct          */
        if (wordFromBuf(&status, 0) == CMD_OK)
        {
            executeLatchArm(ON, DEPLOYMENT_LATCH_PWR_REQ_DM,
               DEPLOYMENT_LATCH_PWR_OK_DM, DEPLOYMENT_LATCH_POWER,
               deploymentLatchArmDm, deploymentLatchStatusDm);
            return (OK);            /* Arm = ON request succeeded          */
        } /* if */
        else
        {
            executeLatchArm(OFF, DEPLOYMENT_LATCH_PWR_REQ_DM,
              DEPLOYMENT_LATCH_PWR_OK_DM, DEPLOYMENT_LATCH_POWER,
              deploymentLatchArmDm, deploymentLatchStatusDm);
            return (OK);            /* Arm = OFF request succeeded         */
        } /* else */
    } /* if */

    writeErsLatchStatusDm(deploymentLatchArmDm, deploymentLatchStatusDm,
        LATCH_DISARMED);

    return (ERROR);               /* Arm request failed for some reason     */
} /* ersArmDeploymentLatch() */

   MLocal
ersReleaseDeploymentLatch( sio32Chan* sio32DataChan,
   DM_Item deploymentLatchArmDm, DM_Item deploymentLatchOnTimeDm )
{
    Word  status;
    Nat16 armCode;
    Nat16 onTime;

    if (dm_read(deploymentLatchArmDm, (char *) &armCode, sizeof(armCode),
        (DM_Time *) NULL) != SUCCESS)
        return (ERROR);

    if (dm_read(deploymentLatchOnTimeDm, (char *) &onTime, sizeof(onTime),
        (DM_Time *) NULL) != SUCCESS)
        return (ERROR);
                                    /* Send command to microcontroller      */
    if (sendMicroCommand( sio32DataChan, &status, sizeof(status), 4,
             EREC_DCON_APP | RELEASE_DEPLOYMENT_LATCH,
             armCode, TRUE, onTime) != ERROR )
                                    /* Check command result                  */
        return ((wordFromBuf(&status, 0) == CMD_OK) ? OK: ERROR);

    return (ERROR);
} /* ersReleaseDeploymentLatch() */

   MLocal
ersJogDeploymentLatch( sio32Chan* sio32DataChan, DM_Item deploymentLatchArmDm,
    DM_Item deploymentLatchJogDm )
{
    Word  status;
    MBool state;
    Nat16 armCode;

    if (dm_read(deploymentLatchArmDm, (char *) &armCode, sizeof(armCode),
        (DM_Time *) NULL) != SUCCESS)
        return (ERROR);

    if (dm_read(deploymentLatchJogDm, (char *) &state, sizeof(state),
        (DM_Time *) NULL) != SUCCESS)
        return (ERROR);
                                    /* Send command to microcontroller      */
    if (sendMicroCommand( sio32DataChan, &status, sizeof(status), 4,
        EREC_DCON_APP | RELEASE_DEPLOYMENT_LATCH,
        armCode, (state ? TRUE : FALSE), DEPLOYMENT_LATCH_MANUAL) != ERROR )

                                    /* Check command result                  */
        return ((wordFromBuf(&status, 0) == CMD_OK) ? OK: ERROR);

    return (ERROR);
} /* ersJogDeploymentLatch() */


    MLocal STATUS
initDeploymentLatchOnTime( DM_Item deploymentLatchOnTimeDm)
{
    Nat16 onTime;

    if (dm_read(deploymentLatchOnTimeDm, (char *) &onTime,
        sizeof(onTime), (DM_Time *) NULL) != SUCCESS)
        return (ERROR);

    if (onTime != 0)
        return (OK);

    onTime = DEPLOYMENT_LATCH_MAX_TIME;
    return (urgentWriteDmItem(deploymentLatchOnTimeDm, &onTime,
       sizeof(onTime)));
} /* initDeploymentLatchOnTime() */

/*****************************************************************************/
/* Function    : createEmergencyDconAppDmItems                               */
/* Purpose     : Create Data Mgr Items specific to Emergency Dcon Application*/
/* Inputs      : Pointer to structure of DM item handles, Dcon DM prefix,    */
/*               Emergency DM prefix, Emergency Data Concentrator Name       */
/* Outputs     : Returns OK or ERROR                                         */
/*****************************************************************************/
    LOCAL STATUS
createEmergencyDconAppDmItems( ersDconDmItems *ersDconDmItems,
    const char* ersDconDmPrefix )
{
    dmItemList ersDconDmInit[] =

     {  { &ersDconDmItems->canWaterAlarm,     "Housing Water Alarm",
                HOUSING_WATER_ALARM_DM,          DM_MBOOL, 1 },

        { &ersDconDmItems->jboxWaterAlarm,    "J Box Water Alarm",
                JBOX_WATER_ALARM_DM,             DM_MBOOL, 1 },

        { &ersDconDmItems->waterAlarmThresh,  "Water Alarm Threshold",
                WATER_ALARM_THRESH_DM,           DM_NAT16, 1 },


        { &ersDconDmItems->ersOperatingMode,  "ERS Operating Mode",
                ERS_OPERATING_MODE_DM,           DM_ENUM, 1 },


        { &ersDconDmItems->batteryCurrent,         "Battery Current",
                BATTERY_CURRENT_DM,              DM_NAT16, 1 },

        { &ersDconDmItems->batteryVoltage,         "Battery Voltage",
                BATTERY_VOLTAGE_DM,              DM_NAT16, 1 },

        { &ersDconDmItems->batteryVoltageCmd,      "Battery Voltage Command",
                BATTERY_VOLTAGE_CMD_DM,          DM_EMPTY, 1 },

        { &ersDconDmItems->batteryVoltAlarm,      "Battery Voltage Alarm",
                BATTERY_VOLTAGE_ALARM_DM,        DM_ENUM, 1 },

        { &ersDconDmItems->batteryVoltWarnThresh,
                "Battery Voltage Warn Thrshold",
                BATTERY_VOLTAGE_WARN_THRESH_DM,  DM_NAT16, 1 },

        { &ersDconDmItems->batteryVoltAlarmThresh,
               "Battery Voltage Alarm Thrshold",
                BATTERY_VOLTAGE_ALARM_THRESH_DM, DM_NAT16, 1 },

        { &ersDconDmItems->batteryLife,            "Battery Life",
                BATTERY_LIFE_DM,                 DM_FLT32, 1 },

        { &ersDconDmItems->batteryLifeAlarm,       "Battery Life Alarm",
                BATTERY_LIFE_ALARM_DM,           DM_ENUM, 1 },

        { &ersDconDmItems->batteryLifeWarnThresh,  "Battery Life Warn Thrshold",
                BATTERY_LIFE_WARN_THRESH_DM,     DM_FLT32, 1 },

        { &ersDconDmItems->batteryLifeAlarmThresh,"Battery Life Alarm Thrshold",
                BATTERY_LIFE_ALARM_THRESH_DM,    DM_FLT32, 1 },

        { &ersDconDmItems->ersDepth,             "ERS Depth Meters",
                ERS_DEPTH_METERS_DM,             DM_FLT64, 1 },

        { &ersDconDmItems->rovnavCmd,            "ROVNAV Command Received",
                ERS_ROVNAV_CMD_DM,               DM_CHAR, ROVNAV_CMD_LEN + 2 },

        { NO_ITEM, NULL, NULL, DM_ENDT, 0 } };


    dmItemList ersPowerDconDmInit[] =
     {  { &ersDconDmItems->toolsled240VSwitchReq,    "ERS Dcon Toolsled 240V",
           TOOLSLED_240V_SWITCH_REQ_DM,           DM_ENUM, 1 },

        { &ersDconDmItems->toolsled240VSwitchStatus, "ERS Dcon Toolsled 240V",
           TOOLSLED_240V_SWITCH_STATUS_DM,        DM_ENUM, 1 },

        { &ersDconDmItems->toolsled48VSwitchReq,    "ERS Dcon Toolsled 48V",
           TOOLSLED_48V_SWITCH_REQ_DM,            DM_ENUM, 1 },

        { &ersDconDmItems->toolsled48VSwitchStatus, "ERS Dcon Toolsled 48V",
           TOOLSLED_48V_SWITCH_STATUS_DM,         DM_ENUM, 1 },

        { NO_ITEM, NULL, NULL, DM_ENDT, 0 } };


    dmItemList vehicleDmInit[] =

     {  { &ersDconDmItems->vehicleInWater,    "Vehicle In-Water Flag",
                TIBURON_IN_WATER_DM,              DM_MBOOL, 1 },


        { &ersDconDmItems->compLevelPercent,  "Compensation System Percentage",
                COMP_SYSTEM_LEVEL_PERCENT_DM,     DM_NAT16, 1 },

        { &ersDconDmItems->compLevelVolume,   "Compensation System Volume",
                COMP_SYSTEM_LEVEL_VOLUME_DM,      DM_FLT32, 1 },

        { &ersDconDmItems->compLevelAlarm,    "Comp System Level Alarm",
                COMP_SYSTEM_LEVEL_ALARM_DM,       DM_ENUM, 1 },

        { &ersDconDmItems->compWarnLevel,     "Comp System Warning Level",
                COMP_SYSTEM_WARN_LEVEL_DM,        DM_NAT16, 1 },

        { &ersDconDmItems->compAlarmLevel,    "Comp System Alarm Level",
                COMP_SYSTEM_ALARM_LEVEL_DM,       DM_NAT16, 1 },

        { &ersDconDmItems->compMinLevel,      "Comp System Minimum Level",
                COMP_SYSTEM_MIN_LEVEL_DM,         DM_NAT16, 1 },

        { &ersDconDmItems->compMaxLevel,      "Comp System Maximum Level",
                COMP_SYSTEM_MAX_LEVEL_DM,         DM_NAT16, 1 },



        { &ersDconDmItems->hydPressure,            "Hydraulic Pressure",
                HYDRAULIC_PRESSURE_DM,               DM_NAT16, 1 },

        { &ersDconDmItems->hydPressureAlarm,       "Hydraulic Pressure Alarm",
                HYDRAULIC_PRESSURE_ALARM_DM,         DM_ENUM, 1 },

        { &ersDconDmItems->hydPressureWarnThresh,  "Hydraulic Pressure Warning",
                HYDRAULIC_PRESSURE_WARN_THRESH_DM,   DM_NAT16, 1 },

        { &ersDconDmItems->hydPressureAlarmThresh, "Hydraulic Pressure Alarm",
                HYDRAULIC_PRESSURE_ALARM_THRESH_DM,  DM_NAT16, 1 },


        { &ersDconDmItems->vbLevelMM,            "VB System Level Millimeters",
                VB_SYSTEM_LEVEL_MM_DM,            DM_FLT32, 1 },

        { &ersDconDmItems->vbVolume,             "VB System Volume mm3",
                VB_SYSTEM_VOLUME_DM,              DM_FLT32, 1 },

        { &ersDconDmItems->vbWeight,             "VB System Weight Kg",
                VB_SYSTEM_WEIGHT_DM,              DM_FLT32, 1 },


        { &ersDconDmItems->deploymentLatchArm,     "Deployment Latch Arm",
                DEPLOYMENT_LATCH_ARM_DM,          DM_NAT16, 1 },

        { &ersDconDmItems->deploymentLatchRelease, "Deployment Latch Release",
                DEPLOYMENT_LATCH_RELEASE_DM,      DM_EMPTY, 1 },

        { &ersDconDmItems->deploymentLatchJog,     "Deployment Latch Jog",
                DEPLOYMENT_LATCH_JOG_DM,          DM_MBOOL, 1 },

        { &ersDconDmItems->deploymentLatchStatus,  "Deployment Latch Status",
                DEPLOYMENT_LATCH_STATUS_DM,       DM_ENUM, 1 },

        { &ersDconDmItems->deploymentLatchOnTime,  "Deployment Latch On Time",
                DEPLOYMENT_LATCH_ON_TIME_DM,      DM_NAT16, 1 },

        { &ersDconDmItems->valve1aSwitch,      "Valve 1a Switch",
                VALVE_1A_SWITCH_DM,                DM_MBOOL, 1 },

        { &ersDconDmItems->valve1bSwitch,      "Valve 1b Switch",
                VALVE_1B_SWITCH_DM,                DM_MBOOL, 1 },

        { &ersDconDmItems->valve2aSwitch,      "Valve 2a Switch",
                VALVE_2A_SWITCH_DM,                DM_MBOOL, 1 },

        { &ersDconDmItems->valve2bSwitch,      "Valve 2b Switch",
                VALVE_2B_SWITCH_DM,                DM_MBOOL, 1 },

        { &ersDconDmItems->valve3aSwitch,      "Valve 3a Switch",
                VALVE_3A_SWITCH_DM,                DM_MBOOL, 1 },

        { &ersDconDmItems->valve3bSwitch,      "Valve 3b Switch",
                VALVE_3B_SWITCH_DM,                DM_MBOOL, 1 },

        { &ersDconDmItems->valve4aSwitch,      "Valve 4a Switch",
                VALVE_4A_SWITCH_DM,                DM_MBOOL, 1 },

        { &ersDconDmItems->valve4bSwitch,      "Valve 4b Switch",
                VALVE_4B_SWITCH_DM,                DM_MBOOL, 1 },

        { &ersDconDmItems->valve5aSwitch,      "Valve 5a Switch",
                VALVE_5A_SWITCH_DM,                DM_MBOOL, 1 },

        { &ersDconDmItems->valve5bSwitch,      "Valve 5b Switch",
                VALVE_5B_SWITCH_DM,                DM_MBOOL, 1 },

        { &ersDconDmItems->valve6aSwitch,      "Valve 6a Switch",
                VALVE_6A_SWITCH_DM,                DM_MBOOL, 1 },

        { &ersDconDmItems->valve6bSwitch,      "Valve 6b Switch",
                VALVE_6B_SWITCH_DM,                DM_MBOOL, 1 },

        { &ersDconDmItems->valve7aSwitch,      "Valve 7a Switch",
                VALVE_7A_SWITCH_DM,                DM_MBOOL, 1 },

        { &ersDconDmItems->valve7bSwitch,      "Valve 7b Switch",
                VALVE_7B_SWITCH_DM,                DM_MBOOL, 1 },


        { &ersDconDmItems->valvePackEnableSwitch, "Valve Pack Enable Switch",
                VALVE_PACK_ENABLE_SWITCH_DM,       DM_MBOOL, 1 },


        { &ersDconDmItems->toolsledHydraulicSwitch, "Toolsled Hydraulic Switch",
                TOOLSLED_HYDRAULIC_SWITCH_DM,        DM_MBOOL, 1},

        { &ersDconDmItems->schillingArmHydraulicSwitch,"Schilling Arm Hydraulic Switch",
                SCHILLING_ARM_HYDRAULIC_SWITCH_DM,      DM_MBOOL, 1},

        { &ersDconDmItems->spareHydraulicSwitch,    "Spare Hydraulic Switch",
                SPARE_HYDRAULIC_SWITCH_DM,              DM_MBOOL, 1},

        { &ersDconDmItems->vbHydraulicSwitch,       "VB Hydraulic Switch",
                VB_HYDRAULIC_SWITCH_DM,                  DM_MBOOL,1},

        { NO_ITEM, NULL, NULL, DM_ENDT, 0 } };

                                 /* Initialize Data Manager Items from table */
    if (initMicroDmItemList( ersDconDmInit, ersDconDmPrefix,
        "ERS Dcon I/F" ) != OK)
        return(ERROR);

                                 /* Initialize Data Manager Items from table */
    if (initMicroDmItemList( ersPowerDconDmInit, "", "ERS Dcon Power" ) != OK)
        return(ERROR);

                                 /* Create Vehicle In-water DM Item          */
    if (initMicroDmItemList( vehicleDmInit, TIBURON_DM_PREFIX, "ERS Dcon I/F" )
        != OK)
        return(ERROR);

    ersDconDmItems->vbMotorRunDm =
      initMicroDmItem(VB_MOTOR_DM_PREFIX, VB_MOTOR_RUN_DM, DM_ENUM, 1);

                                 /* Declare this task an item provider       */
    dm_start_provider(ersDconDmItems->canWaterAlarm,         DM_STATIC);
    dm_start_provider(ersDconDmItems->jboxWaterAlarm,        DM_STATIC);
    dm_start_provider(ersDconDmItems->vehicleInWater,        DM_STATIC);
    dm_start_provider(ersDconDmItems->ersOperatingMode,      DM_STATIC);

    dm_start_provider(ersDconDmItems->hydPressureAlarm,      DM_STATIC);
    dm_start_provider(ersDconDmItems->batteryVoltAlarm,      DM_STATIC);
    dm_start_provider(ersDconDmItems->batteryLifeAlarm,      DM_STATIC);
    dm_start_provider(ersDconDmItems->compLevelAlarm,        DM_STATIC);

    dm_start_provider(ersDconDmItems->rovnavCmd,             DM_STATIC);

    return(OK);
} /* createEmergencyDconAppDmItems() */

/*****************************************************************************/
/* Function    : ersDconTask                                            */
/* Purpose     : Initializes communication with Emergency Data Concentrator. */
/*               Provides interface between Emergency Data Concentrator and  */
/*               Data Manager items.                                         */
/* Inputs      : SIO32 serial channel number for Emergency Data Concentrator */
/*               Physically maps the Data Concentrators to a serial channel  */
/* Outputs     : Normally runs forever, but returns ERROR on fatal error     */
/*****************************************************************************/
    STATUS
ersDconTask( Nat16 serialChannel )
{
    ersDconDmItems dmItems;         /* Emergency Application DM item handles*/
    microIOControl microIOCtrl;     /* Microcontroller IO Task control      */
    Int16   board;                  /* Low Power Switch Board Index         */

                                    /* Initialize serial channel and task   */
                                    /* synchronization resources            */
    if (initMicroTaskIO( &microIOCtrl, NUM_TASKS, serialChannel,
       ersDconDmPrefix, "/sio32/ersDcon", NO_ITEM ) == ERROR)
    {
        logMsg("Error initializing IO for ERS DCon");
        return(ERROR);
    } /* if */
                                   /* Clear Emergency DCon DM handles        */
    bzero((char *) &dmItems, sizeof(dmItems));

                                   /* Create IBC CPU Data Manager Items      */
    if (createIbcCpuDmItems(&dmItems.ibcDm, ersDconDmPrefix, ersDconName)
        == ERROR)
    {                              /* Error occurred so print message & exit */
        sio32ChanDestroy( serialChannel, &microIOCtrl.sio32DataChan );
        return(ERROR);
    } /* if */

                                   /* Create Emergency Dcon Application Items*/
    if (createEmergencyDconAppDmItems(&dmItems, ersDconDmPrefix)
       == ERROR)
    {                              /* Error occurred so print message & exit */
        sio32ChanDestroy( serialChannel, &microIOCtrl.sio32DataChan );
        return(ERROR);
    } /* if */
                                   /* Create GF/5V Board Data Manager Items  */
    createIbcGf5vDmItems( &dmItems.gf5vDm, ersDconDmPrefix, ersDconName );
    initIbcGf5vAlarmProvider( &dmItems.gf5vDm );

                                   /* Create LPS Board Data Manager Items    */
    for (board = 0; board < LPS_BOARDS; board++)
    {                               /* Create LPS Data Manager Items         */
        createIbcLpsDmItems( &dmItems.lpsDm[board], ersDconDmPrefix,
           ersDconName, board );

        initIbcLpsAlarmProvider( &dmItems.lpsDm[board] );
    } /* for */

                                    /* Create Quad Serial Data Mgr Items    */
    createIbcQuadSerDmItems( &dmItems.quadSerDm, ersDconDmPrefix,
        ersDconName, 0 );
    initIbcQuadSerAlarmProvider( &dmItems.quadSerDm );

                                    /* Initialize Emergency Dcon Data Out Task*/
    if ((microIOCtrl.childTasks[OUT_TASK].taskId =
         taskSpawn("ersDconOut", ERS_DCON_OUT_PRIORITY, VX_FP_TASK,
         ERS_DCON_OUT_STACKSIZE, (FUNCPTR) ersDconOutTask,
         (int) &dmItems, (int) &microIOCtrl, 0, 0, 0, 0, 0, 0, 0, 0)) == ERROR)
    {
                                    /* Close serial communication channel    */
        sio32ChanDestroy( serialChannel, &microIOCtrl.sio32DataChan );
        logMsg("ERS Dcon: Error spawning data output task\n");
        return(ERROR);
    } /* if */

                                    /* Initialize Emergency Dcon Data In Task*/
    if (( microIOCtrl.childTasks[IN_TASK].taskId =
         taskSpawn( "ersDconIn", ERS_DCON_IN_PRIORITY, VX_FP_TASK,
         ERS_DCON_IN_STACKSIZE, (FUNCPTR) ersDconInTask,
         (int) &dmItems, (int) &microIOCtrl, 0, 0, 0, 0, 0, 0, 0, 0) ) == ERROR)
    {                               /* Delete Emergency Dcon In Task */
        taskDelete(microIOCtrl.childTasks[OUT_TASK].taskId);
        sio32ChanDestroy( serialChannel, &microIOCtrl.sio32DataChan );
        logMsg("ERS Dcon: Error spawning data input task\n");
        return(ERROR);
    } /* if */


    FOREVER
    {                               /* Check if ERS DCon is switched on       */
        if ((microDevPowerSwitchState(&microIOCtrl) != SWITCH_ON) ||
           ((microDevPowerSwitchState(&microIOCtrl) == SWITCH_ON) &&
            (microIOCtrl.resetEventCount != 0)))

                                    /* Process SRQ's from  micro              */
           while(processErsDconSRQ(&dmItems, &microIOCtrl) != MICRO_RESET_SRQ);

        microIOCtrl.resetEventCount++;   /* Count reset events ffrom micro    */

                                    /* Reset event received from Micro so     */
                                    /* Mark serial coms link as up            */
        setSerialLinkState(&microIOCtrl, LINK_UP);

                                    /* Initialize Static IBC DM Items         */
        if (initIbcCpuDmItems( &dmItems.ibcDm, &microIOCtrl.sio32DataChan,
            ersDconName, ibcCardSet) == OK)

        {                           /* Initialize Emergency Dcon Applic Items */
            initEmergencyDconDmItems( &dmItems, &microIOCtrl.sio32DataChan );

            updateIbcGf5vAlarmsDm( &microIOCtrl.sio32DataChan, GF5V_BOARD_ADDR,
               &dmItems.gf5vDm );

            for (board = 0; board < LPS_BOARDS; board++)
                updateIbcLpsAlarmsDm(&microIOCtrl.sio32DataChan,
                    lpsBoardAddr[board], &dmItems.lpsDm[board] );

            updateIbcQuadSerAlarmsDm( &microIOCtrl.sio32DataChan,
                SERIAL_BOARD_ADDR, &dmItems.quadSerDm );

                                     /* Wake up output task to configure micro*/
            semGive(microIOCtrl.childTasks[OUT_TASK].taskSyncSem);
        } /* if */
        else
            setSerialLinkState(&microIOCtrl, LINK_DOWN);

    } /* FOREVER  */

                                    /* Delete Child Tasks                     */
    taskDelete(microIOCtrl.childTasks[IN_TASK].taskId);
    taskDelete(microIOCtrl.childTasks[OUT_TASK].taskId);

                                    /* Close serial communication channel    */
    sio32ChanDestroy( serialChannel, &microIOCtrl.sio32DataChan );

                        /* dm_stop_provider, dm_stop_consumer, etc are NOT   */
                        /* required when the task exits as the Data Manager  */
                        /* does this automatically when the task is deleted  */
                        /* via taskDeleteHookAdd() and dm_task_exit function */

    return(OK);         /* That's all folks                                  */
} /* ersDconTask() */

/*****************************************************************************/
/* Function    : initEmergencyDconDmItems                                    */
/* Purpose     : Reads parameters from Emergency Dcon & update Data Mgr items*/
/* Inputs      : Array of Data Manager Item handles & serial chan structure  */
/* Outputs     : None, but Data Manager Items change                         */
/*****************************************************************************/
    LOCAL Void
initEmergencyDconDmItems( ersDconDmItems *dmItems,
    sio32Chan *ersDconDataChan )
{
                                /* Set Micro Water Alarms initial value      */
    if (updateWaterAlarmDm(ersDconDataChan,
             dmItems->canWaterAlarm, dmItems->jboxWaterAlarm) == ERROR)
          logMsg("ERS Dcon: Error checking water alarm status\n");

    if (updateERSStateDm(ersDconDataChan, dmItems) == ERROR)
          logMsg("ERS Dcon: Error reading ERS status values\n");

    if (updateERSCompLevelAlarmDm(ersDconDataChan,
        dmItems->compLevelAlarm) == ERROR)
        logMsg("ERS Dcon: Error reading Comp Level Alarm\n");

    if (updateERSBatteryAlarmsDm(ersDconDataChan,
        dmItems->batteryVoltAlarm, dmItems->batteryLifeAlarm) == ERROR)
        logMsg("ERS Dcon: Error reading Battery Alarms\n");
} /* initEmergencyDconDmItems() */

/*****************************************************************************/
/* Function    : ersDconOutTask                                              */
/* Purpose     : Emergency Dcon Out. Read DM items & write to Emergency Dcon */
/* Inputs      : Array of Data Manager Item handles & serial chan structure  */
/* Outputs     : Normally runs forever, but exits if error occurs            */
/*****************************************************************************/
     Void
ersDconOutTask(Reg ersDconDmItems *dmItems, Reg microIOControl *microIOCtrl)
{
    DM_Group ersGroup;              /* ERS DCon Data Manager Item Group      */
    DM_Group cpuGroup;              /* CPU & Misc Item Data Manager Group    */
    DM_Group gf5vGroup;             /* GF/5V Board Data Manager Group        */
    DM_Group lpsGroup[LPS_BOARDS];  /* LPS Board Data Manager Group          */

    SEM_ID  dmUpdateSem;            /* Data Manager Item Change wakeup sem   */
    SEM_ID  powerReqSem;            /* Power Request Update Semaphore        */
    SEM_ID  powerStatusSem;         /* Power Status Update Semaphore         */

    Int16 board;                    /* LPS Board Index                       */
    ersOperatingMode operatingMode; /* ERS Operating Mode                    */
  
    switchStatus valveSwitchState;  /* Switch State of ECU Board             */
  
    cpuUpdateBits   ibcCpuBits;     /* CPU Board Parameter Update Bits       */
    gf5vUpdateBits  gf5vBits;       /* GF/5V Board Paramater Update Bits     */
    lpsUpdateBits   lpsBits[LPS_BOARDS];  /* LPS Board Parameter Update Bits */

    DWord   ersDconGroupBits;       /* Holds dm_group_changes bit vector     */
    DWord   ibcCpuGroupBits;        /* Holds dm_group_changes bit vector     */

    DWord   waterAlarmThreshBit;    /* Water alarm threshold item change bit */
    DWord   operatingModeBit;       /* ERS Operating Mode changed bit        */

    DWord   deploymentArmBit;       /* Deployment Latch Arm item change bit  */
    DWord   deploymentReleaseBit;   /* Deployment Latch Release item chng bit*/
    DWord   deploymentJogBit;       /* Deployment Latch Jog item chng bit    */

    DWord   lpsEnableBit[LPS_BOARDS];  /* LPS 48 V Enable Request changed bit*/
    DWord   ersDconSwitchBit;       /*  Dcon Power Switch changed bit        */

    DWord   pressureSensorSwitchBit;
    DWord   vbLevelSensorSwitchBit;
    DWord   compLevelSensorSwitchBit;
    DWord   sciencePort12vSwitchBit;

    DWord   acousticModemSwitchBit;

    DWord   vbFillSwitchBit;

    DWord   ecuPowerSwitchBit;
    DWord   sciencePort24vSwitchBit;

    DWord   hydPressureWarnThreshBit;
    DWord   hydPressureAlarmThreshBit;

    DWord   batteryLifeWarnThreshBit;
    DWord   batteryLifeAlarmThreshBit;
    DWord   batteryVoltWarnThreshBit;
    DWord   batteryVoltAlarmThreshBit;
    DWord   batteryVoltageReadCmdBit;

    DWord   compWarnLevelBit;       /* Compensation Warning Level changed bit*/
    DWord   compAlarmLevelBit;      /* Compensation Alarm Level changed bit  */
    DWord   compMinLevelBit;        /* Compensation Minimum Level changed bit*/
    DWord   compMaxLevelBit;        /* Compensation Maximum Level changed bit*/

                                    /* Sensor Dcon LPS Output Enable switches*/
    switchEntry ersLpsEnableSwitch[LPS_BOARDS];

                                    /* Valve Pack Valve Switches             */
    DWord   valve1aSwitchBit;       /* ECU Digital Output1  */
    DWord   valve1bSwitchBit;       /* ECU Digital Output2  */
    DWord   valve2aSwitchBit;       /* ECU Digital Output3  */
    DWord   valve2bSwitchBit;       /* ECU Digital Output4  */
    DWord   valve3aSwitchBit;       /* ECU Digital Output5  */
    DWord   valve3bSwitchBit;       /* ECU Digital Output6  */
    DWord   valve4aSwitchBit;       /* ECU Digital Output7  */
    DWord   valve4bSwitchBit;       /* ECU Digital Output8  */
    DWord   valve5aSwitchBit;       /* ECU Digital Output9  */
    DWord   valve5bSwitchBit;       /* ECU Digital Output10 */
    DWord   valve6aSwitchBit;       /* ECU Digital Output11 */
    DWord   valve6bSwitchBit;       /* ECU Digital Output12 */
    DWord   valve7aSwitchBit;       /* ECU Digital Output13 */
    DWord   valve7bSwitchBit;       /* ECU Digital Output14 */
    DWord   valvePackEnableSwitchBit;

    DWord   toolsledHydraulicSwitchBit;
    DWord   schillingArmHydraulicSwitchBit;
    DWord   spareHydraulicSwitchBit;
    DWord   vbHydraulicSwitchBit;


    switchEntry ersDconSwitch;      /* Emergency DCon  Switch                */
    switchEntry pressureSensorSwitch;
    switchEntry vbLevelSensorSwitch;
    switchEntry compLevelSensorSwitch;
    switchEntry sciencePort12vSwitch;

    switchEntry acousticModemSwitch;

    switchEntry vbFillSwitch;

    switchEntry ecuPowerSwitch;
    switchEntry sciencePort24vSwitch;

    MBool       valve1aSwitch;
    MBool       valve1bSwitch;
    MBool       valve2aSwitch;
    MBool       valve2bSwitch;
    MBool       valve3aSwitch;
    MBool       valve3bSwitch;
    MBool       valve4aSwitch;
    MBool       valve4bSwitch;
    MBool       valve5aSwitch;
    MBool       valve5bSwitch;
    MBool       valve6aSwitch;
    MBool       valve6bSwitch;
    MBool       valve7aSwitch;
    MBool       valve7bSwitch;
    MBool       valvePackEnableSwitch;

    MBool       toolsledHydraulicSwitch;
    MBool       schillingArmHydraulicSwitch;
    MBool       spareHydraulicSwitch;
    MBool       vbHydraulicSwitch;


/*****************************************************************************/
/* The code in this task implements the following interconnected switches for
   the power can, ers data concentrator, and sensors.

             48V Dcon     12V LPS Enable     LPS 0-4
   48V Bus _____ \_____________ \______________ \_____ pressure sensor ______
                       |                 |                                   |
                       |                 |_____ \_____ VB Level Sensor ______|
                       |                 |                                   |
                       |                 |_____ \_____ Comp Level Sensor ____|
                       |                 |                                   |
                       |                 |_____ \_____ Science Port 12v  ____|
                       |
                       |  24V LPS Enable     LPS 0-4
                       |_______ \______________ \_____ ECU Board Power ______
                       |                 |                                   |
                       |                 |_____ \_____ Science Port 24v _____|
                       |                 |                                   |
                       |                 |_____ \_____ Not Used        ______|
                       |                 |                                   |
                       |                 |_____ \_____ Not Used        ______|
		       |
                       |  24V LPS Enable     LPS 0-4
                       |_______ \______________ \_____ VB Fill Solenoid _____
                                         |                                   |
                                         |_____ \_____ Deployment Latch _____|
                                         |                                   |
                                         |_____ \_____ Not Used       _______|
                                         |                                   |
                                         |_____ \_____ Acoustic Modem _______|


   */
/*****************************************************************************/

                                    /* Create switch & power sync semaphores */
    if ( ((dmUpdateSem    = semBCreate(SEM_Q_FIFO, SEM_EMPTY)) == NULL) ||
         ((powerReqSem    = semBCreate(SEM_Q_FIFO, SEM_EMPTY)) == NULL) ||
         ((powerStatusSem = semBCreate(SEM_Q_FIFO, SEM_EMPTY)) == NULL) )
    {
        logMsg("ERS Dcon: Error initializing Input Task Resources\n");
        return;
    } /* if */

    duplicateIbcSwitchEntry( &ersDconSwitch,
        ERS_DCON_SWITCH_REQ_DM,  ERS_DCON_SWITCH_STATUS_DM,
        dmUpdateSem, ersDconName, "ERS DCon 48V Switch");

    initIbcSwitchEntry( &ersLpsEnableSwitch[0], SERIAL_CHAN,
        VICOR_STANDBY_POWER,        A48,                      HOTEL,
        LOW_POWER_SWITCH,           lpsBoardAddr[0],      LPS_VICOR_ENABLE,
        ERS_LPS0_12V_ENABLE_SWITCH_REQ_DM, ERS_LPS0_12V_ENABLE_STATUS_DM,
        dmUpdateSem,
        ERS_LPS0_12V_ENABLE_PWR_REQ_DM,    ERS_LPS0_12V_ENABLE_PWR_OK_DM,
        powerReqSem,                ersDconName,      "LPS 0 12V Enable");

    initIbcSwitchEntry( &ersLpsEnableSwitch[1], SERIAL_CHAN,
        VICOR_STANDBY_POWER,        A48,                      HOTEL,
        LOW_POWER_SWITCH,           lpsBoardAddr[1],      LPS_VICOR_ENABLE,
        ERS_LPS0_24V_ENABLE_SWITCH_REQ_DM, ERS_LPS0_24V_ENABLE_STATUS_DM,
        dmUpdateSem,
        ERS_LPS0_24V_ENABLE_PWR_REQ_DM,    ERS_LPS0_24V_ENABLE_PWR_OK_DM,
        powerReqSem,                ersDconName,      "LPS 0 24V Enable");

    initIbcSwitchEntry( &ersLpsEnableSwitch[2], SERIAL_CHAN,
        VICOR_STANDBY_POWER,        A48,                      HOTEL,
        LOW_POWER_SWITCH,           lpsBoardAddr[2],      LPS_VICOR_ENABLE,
        ERS_LPS1_24V_ENABLE_SWITCH_REQ_DM, ERS_LPS1_24V_ENABLE_STATUS_DM,
        dmUpdateSem,
        ERS_LPS1_24V_ENABLE_PWR_REQ_DM,    ERS_LPS1_24V_ENABLE_PWR_OK_DM,
        powerReqSem,                ersDconName,      "LPS 1 24V Enable");


    initIbcSwitchEntry( &pressureSensorSwitch, SERIAL_CHAN,
        PRESSURE_SENSOR_POWER,      A48,                      HOTEL,
        LOW_POWER_SWITCH,           lpsBoardAddr[0],      PRESSURE_PWR_CHAN,
        ERS_PRESSURE_SENSOR_SWITCH_REQ_DM, ERS_PRESSURE_SENSOR_SWITCH_STATUS_DM,
        dmUpdateSem,
        ERS_PRESSURE_SENSOR_PWR_REQ_DM,    ERS_PRESSURE_SENSOR_PWR_OK_DM,
        powerReqSem,                ersDconName,  "Pressure Sensor Switch");

    initIbcSwitchEntry( &vbLevelSensorSwitch, SERIAL_CHAN,
        VB_LEVEL_SENSOR_POWER,      A48,                      HOTEL,
        LOW_POWER_SWITCH,           lpsBoardAddr[0],  VB_LEVEL_SENSOR_PWR_CHAN,
        VB_LEVEL_SENSOR_SWITCH_REQ_DM, VB_LEVEL_SENSOR_SWITCH_STATUS_DM,
        dmUpdateSem,
        VB_LEVEL_SENSOR_PWR_REQ_DM,    VB_LEVEL_SENSOR_PWR_OK_DM,
        powerReqSem,                ersDconName,  "VB Level Sensor Switch");

    initIbcSwitchEntry( &compLevelSensorSwitch, SERIAL_CHAN,
        COMP_LEVEL_SENSOR_POWER,    A48,                      HOTEL,
        LOW_POWER_SWITCH,           lpsBoardAddr[0],      COMP_LEVEL_PWR_CHAN,
        COMP_LEVEL_SENSOR_SWITCH_REQ_DM, COMP_LEVEL_SENSOR_SWITCH_STATUS_DM,
        dmUpdateSem,
        COMP_LEVEL_SENSOR_PWR_REQ_DM,    COMP_LEVEL_SENSOR_PWR_OK_DM,
        powerReqSem,                ersDconName,  "Comp Level Sensor Switch");

    initIbcSwitchEntry( &sciencePort12vSwitch, SERIAL_CHAN,
        LPS_12V_SPARE_POWER,    A48,                      HOTEL,
        LOW_POWER_SWITCH,           lpsBoardAddr[0],      SCIENCE_PORT_12V_PWR_CHAN,
        SCIENCE_PORT_12V_SWITCH_REQ_DM, SCIENCE_PORT_12V_SWITCH_STATUS_DM,
        dmUpdateSem,
        SCIENCE_PORT_12V_PWR_REQ_DM,    SCIENCE_PORT_12V_PWR_OK_DM,
        powerReqSem,                ersDconName,  "Science Port 12v Switch");

    initIbcSwitchEntry( &ecuPowerSwitch, SERIAL_CHAN,
        ECU_POWER,                       A48,                             HOTEL,
        LOW_POWER_SWITCH,            lpsBoardAddr[1],  ECU_PWR_CHAN,
        ECU_SWITCH_REQ_DM,    ECU_SWITCH_STATUS_DM,
        dmUpdateSem,
        ECU_PWR_REQ_DM,       ECU_PWR_OK_DM,
        powerReqSem,  ersDconName, "ECU Board PowerSwitch");

    initIbcSwitchEntry( &sciencePort24vSwitch, SERIAL_CHAN,
        LPS_24V_SPARE_POWER,    A48,                      HOTEL,
        LOW_POWER_SWITCH,           lpsBoardAddr[0],      SCIENCE_PORT_24V_PWR_CHAN,
        SCIENCE_PORT_24V_SWITCH_REQ_DM, SCIENCE_PORT_24V_SWITCH_STATUS_DM,
        dmUpdateSem,
        SCIENCE_PORT_24V_PWR_REQ_DM,    SCIENCE_PORT_24V_PWR_OK_DM,
        powerReqSem,                ersDconName,  "Science Port 24v Switch");

    initIbcSwitchEntry( &vbFillSwitch, SERIAL_CHAN,
        VB_FILL_POWER,                   A48,                             HOTEL,
        LOW_POWER_SWITCH,           lpsBoardAddr[2],  VB_FILL_SOLENOID,
        VB_FILL_SWITCH_REQ_DM,      VB_FILL_SWITCH_STATUS_DM,
        dmUpdateSem,
        VB_FILL_PWR_REQ_DM,         VB_FILL_PWR_OK_DM,
        powerReqSem,                ersDconName, "VB Fill Solenoid Switch");

    initIbcSwitchEntry( &acousticModemSwitch, SERIAL_CHAN,
        ACOUSTIC_MODEM_POWER, A48,                             HOTEL,
        LOW_POWER_SWITCH,           lpsBoardAddr[2],  ACOUSTIC_MODEM_PWR_CHAN,
        ACOUSTIC_MODEM_SWITCH_REQ_DM,       ACOUSTIC_MODEM_SWITCH_STATUS_DM,
        dmUpdateSem,
        ACOUSTIC_MODEM_PWR_REQ_DM,          ACOUSTIC_MODEM_PWR_OK_DM,
        powerReqSem,              ersDconName, "Acoustic Modem Switch");


                                   /* Devices on Emergency Can 48V Bus       */
    ibcAddSwitchInSeries( &ersDconSwitch, &ersLpsEnableSwitch[0] );
    ibcAddSwitchInSeries( &ersDconSwitch, &ersLpsEnableSwitch[1] );
    ibcAddSwitchInSeries( &ersDconSwitch, &ersLpsEnableSwitch[2] );

                                  /* Devices on ERS DCon Low Power Switches  */
    ibcAddSwitchInSeries( &ersLpsEnableSwitch[0], &pressureSensorSwitch);
    ibcAddSwitchInSeries( &ersLpsEnableSwitch[0], &vbLevelSensorSwitch);
    ibcAddSwitchInSeries( &ersLpsEnableSwitch[0], &compLevelSensorSwitch);
    ibcAddSwitchInSeries( &ersLpsEnableSwitch[0], &sciencePort12vSwitch);

    ibcAddSwitchInSeries( &ersLpsEnableSwitch[1], &ecuPowerSwitch);
    ibcAddSwitchInSeries( &ersLpsEnableSwitch[0], &sciencePort24vSwitch);

    ibcAddSwitchInSeries( &ersLpsEnableSwitch[2], &vbFillSwitch);
    ibcAddSwitchInSeries( &ersLpsEnableSwitch[2], &acousticModemSwitch);

    ibcConnectLpsDmItems( &dmItems->lpsDm[0], &pressureSensorSwitch,
         ersDconName, "Pressure Sensor",   PRESSURE_PWR_CHAN,
         ERS_PRESSURE_SENSOR_CURRENT_DM,   ERS_PRESSURE_SENSOR_CURRENT_ALARM_DM,
         ERS_PRESSURE_SENSOR_CURRENT_WARN_THRESH_DM,
         ERS_PRESSURE_SENSOR_CURRENT_ALARM_THRESH_DM);

    ibcConnectLpsDmItems( &dmItems->lpsDm[0], &vbLevelSensorSwitch,
         ersDconName, "VB Level Sensor",   VB_LEVEL_SENSOR_PWR_CHAN,
         VB_LEVEL_SENSOR_CURRENT_DM,       VB_LEVEL_SENSOR_CURRENT_ALARM_DM,
         VB_LEVEL_SENSOR_CURRENT_WARN_THRESH_DM,
         VB_LEVEL_SENSOR_CURRENT_ALARM_THRESH_DM);

    ibcConnectLpsDmItems( &dmItems->lpsDm[0], &compLevelSensorSwitch,
         ersDconName, "Comp Level Sensor",   COMP_LEVEL_SENSOR_PWR_CHAN,
         COMP_LEVEL_SENSOR_CURRENT_DM,       COMP_LEVEL_SENSOR_CURRENT_ALARM_DM,
         COMP_LEVEL_SENSOR_CURRENT_WARN_THRESH_DM,
         COMP_LEVEL_SENSOR_CURRENT_ALARM_THRESH_DM);

    ibcConnectLpsDmItems( &dmItems->lpsDm[0], &sciencePort12vSwitch,
         ersDconName, "Science Port 12v",   SCIENCE_PORT_12V_PWR_CHAN,
         SCIENCE_PORT_12V_CURRENT_DM,       SCIENCE_PORT_12V_CURRENT_ALARM_DM,
         SCIENCE_PORT_12V_CURRENT_WARN_THRESH_DM,
         SCIENCE_PORT_12V_CURRENT_ALARM_THRESH_DM);

    ibcConnectLpsDmItems( &dmItems->lpsDm[1], &ecuPowerSwitch,
         ersDconName, "ECU Power Switch",   ECU_PWR_CHAN,
         ECU_CURRENT_DM,
         ECU_CURRENT_ALARM_DM,
         ECU_CURRENT_WARN_THRESH_DM,
         ECU_CURRENT_ALARM_THRESH_DM);

    ibcConnectLpsDmItems( &dmItems->lpsDm[1], &sciencePort24vSwitch,
         ersDconName, "Science Port 24v",   SCIENCE_PORT_24V_PWR_CHAN,
         SCIENCE_PORT_24V_CURRENT_DM,       SCIENCE_PORT_24V_CURRENT_ALARM_DM,
         SCIENCE_PORT_24V_CURRENT_WARN_THRESH_DM,
         SCIENCE_PORT_24V_CURRENT_ALARM_THRESH_DM);

    ibcConnectLpsDmItems( &dmItems->lpsDm[2], &vbFillSwitch,
         ersDconName, "VB Fill Sensor",    VB_FILL_SOLENOID,
         VB_FILL_CURRENT_DM,       VB_FILL_CURRENT_ALARM_DM,
         VB_FILL_CURRENT_WARN_THRESH_DM,
         VB_FILL_CURRENT_ALARM_THRESH_DM);

    ibcConnectLpsDmItems( &dmItems->lpsDm[2], &acousticModemSwitch,
         ersDconName, "Acoustic Modem",          ACOUSTIC_MODEM_PWR_CHAN,
         ACOUSTIC_MODEM_CURRENT_DM,
         ACOUSTIC_MODEM_CURRENT_ALARM_DM,
         ACOUSTIC_MODEM_CURRENT_WARN_THRESH_DM,
         ACOUSTIC_MODEM_CURRENT_ALARM_THRESH_DM);

    ersGroup = dm_create_group();    /* Create DM Group for ERS Application  */

                                     /* Create Data Manager Group for items  */
    cpuGroup = initIbcCpuConsumer(&dmItems->ibcDm, &ibcCpuBits, dmUpdateSem);

                                    /* Use CPU Group for misc parameters     */
    dm_start_consumer(dmItems->waterAlarmThresh, DM_STATIC, dmUpdateSem);

    dm_start_consumer(dmItems->ersOperatingMode,       DM_STATIC, dmUpdateSem);

    dm_start_consumer(dmItems->batteryLifeWarnThresh,  DM_STATIC, dmUpdateSem);
    dm_start_consumer(dmItems->batteryLifeAlarmThresh, DM_STATIC, dmUpdateSem);
    dm_start_consumer(dmItems->batteryVoltWarnThresh,  DM_STATIC, dmUpdateSem);
    dm_start_consumer(dmItems->batteryVoltAlarmThresh, DM_STATIC, dmUpdateSem);
    dm_start_consumer(dmItems->batteryVoltageCmd,      DM_STATIC, dmUpdateSem);

    dm_start_consumer(dmItems->hydPressureWarnThresh,  DM_STATIC, dmUpdateSem);
    dm_start_consumer(dmItems->hydPressureAlarmThresh, DM_STATIC, dmUpdateSem);

    dm_start_consumer(dmItems->compMinLevel,           DM_STATIC, dmUpdateSem);
    dm_start_consumer(dmItems->compMaxLevel,           DM_STATIC, dmUpdateSem);
    dm_start_consumer(dmItems->compWarnLevel,          DM_STATIC, dmUpdateSem);
    dm_start_consumer(dmItems->compAlarmLevel,         DM_STATIC, dmUpdateSem);


    dm_start_consumer(dmItems->deploymentLatchArm,     DM_STATIC, dmUpdateSem);
    dm_start_consumer(dmItems->deploymentLatchRelease, DM_STATIC, dmUpdateSem);
    dm_start_consumer(dmItems->deploymentLatchJog,     DM_STATIC, dmUpdateSem);
    dm_start_consumer(dmItems->deploymentLatchOnTime,  DM_STATIC, SEM_NULL);

    dm_start_consumer(dmItems->valve1aSwitch,          DM_STATIC, dmUpdateSem);
    dm_start_consumer(dmItems->valve1bSwitch,          DM_STATIC, dmUpdateSem);

    dm_start_consumer(dmItems->valve2aSwitch,          DM_STATIC, dmUpdateSem);
    dm_start_consumer(dmItems->valve2bSwitch,          DM_STATIC, dmUpdateSem);

    dm_start_consumer(dmItems->valve3aSwitch,          DM_STATIC, dmUpdateSem);
    dm_start_consumer(dmItems->valve3bSwitch,          DM_STATIC, dmUpdateSem);

    dm_start_consumer(dmItems->valve4aSwitch,          DM_STATIC, dmUpdateSem);
    dm_start_consumer(dmItems->valve4bSwitch,          DM_STATIC, dmUpdateSem);

    dm_start_consumer(dmItems->valve5aSwitch,          DM_STATIC, dmUpdateSem);
    dm_start_consumer(dmItems->valve5bSwitch,          DM_STATIC, dmUpdateSem);

    dm_start_consumer(dmItems->valve6aSwitch,          DM_STATIC, dmUpdateSem);
    dm_start_consumer(dmItems->valve6bSwitch,          DM_STATIC, dmUpdateSem);

    dm_start_consumer(dmItems->valve7aSwitch,          DM_STATIC, dmUpdateSem);
    dm_start_consumer(dmItems->valve7bSwitch,          DM_STATIC, dmUpdateSem);

    dm_start_consumer(dmItems->valvePackEnableSwitch,  DM_STATIC, dmUpdateSem);

    dm_start_consumer(dmItems->toolsledHydraulicSwitch, DM_STATIC, dmUpdateSem);
    dm_start_consumer(dmItems->schillingArmHydraulicSwitch, DM_STATIC, dmUpdateSem);

    dm_start_consumer(dmItems->spareHydraulicSwitch,   DM_STATIC, dmUpdateSem);
    dm_start_consumer(dmItems->vbHydraulicSwitch,      DM_STATIC, dmUpdateSem);

    dm_start_multiple(dmItems->toolsled48VSwitchReq);
    dm_start_multiple(dmItems->toolsled240VSwitchReq);

    dm_start_provider(dmItems->deploymentLatchStatus, DM_STATIC);

    dm_start_consumer(dmItems->toolsled48VSwitchStatus,  DM_STATIC,
        powerStatusSem);

    dm_start_consumer(dmItems->toolsled240VSwitchStatus, DM_STATIC,
        powerStatusSem);

#if 0
    dm_group_add_item(ersGroup, dmItems->waterAlarmThresh,
         &waterAlarmThreshBit);
#endif

    dm_group_add_item(ersGroup, dmItems->ersOperatingMode,
         &operatingModeBit);

    dm_group_add_item(ersGroup, dmItems->batteryLifeWarnThresh,
         &batteryLifeWarnThreshBit);

    dm_group_add_item(ersGroup, dmItems->batteryLifeAlarmThresh,
         &batteryLifeAlarmThreshBit);

    dm_group_add_item(ersGroup, dmItems->batteryVoltWarnThresh,
         &batteryVoltWarnThreshBit);

    dm_group_add_item(ersGroup, dmItems->batteryVoltAlarmThresh,
         &batteryVoltAlarmThreshBit);

    dm_group_add_item(ersGroup, dmItems->batteryVoltageCmd,
         &batteryVoltageReadCmdBit);

    dm_group_add_item(ersGroup, dmItems->hydPressureWarnThresh,
         &hydPressureWarnThreshBit);

    dm_group_add_item(ersGroup, dmItems->hydPressureAlarmThresh,
         &hydPressureAlarmThreshBit);

    dm_group_add_item(ersGroup, dmItems->compWarnLevel,  &compWarnLevelBit);
    dm_group_add_item(ersGroup, dmItems->compAlarmLevel, &compAlarmLevelBit);
    dm_group_add_item(ersGroup, dmItems->compMinLevel,   &compMinLevelBit);
    dm_group_add_item(ersGroup, dmItems->compMaxLevel,   &compMaxLevelBit);


    dm_group_add_item(ersGroup, dmItems->deploymentLatchArm,
        &deploymentArmBit);

    dm_group_add_item(ersGroup, dmItems->deploymentLatchRelease,
        &deploymentReleaseBit);

    dm_group_add_item(ersGroup, dmItems->deploymentLatchJog,
        &deploymentJogBit);

    dm_group_add_item(cpuGroup, dmItems->valve1aSwitch, &valve1aSwitchBit);
    dm_group_add_item(cpuGroup, dmItems->valve1bSwitch, &valve1bSwitchBit);
    dm_group_add_item(cpuGroup, dmItems->valve2aSwitch, &valve2aSwitchBit);
    dm_group_add_item(cpuGroup, dmItems->valve2bSwitch, &valve2bSwitchBit);
    dm_group_add_item(cpuGroup, dmItems->valve3aSwitch, &valve3aSwitchBit);
    dm_group_add_item(cpuGroup, dmItems->valve3bSwitch, &valve3bSwitchBit);
    dm_group_add_item(cpuGroup, dmItems->valve4aSwitch, &valve4aSwitchBit);
    dm_group_add_item(cpuGroup, dmItems->valve4bSwitch, &valve4bSwitchBit);
    dm_group_add_item(cpuGroup, dmItems->valve5aSwitch, &valve5aSwitchBit);
    dm_group_add_item(cpuGroup, dmItems->valve5bSwitch, &valve5bSwitchBit);
    dm_group_add_item(cpuGroup, dmItems->valve6aSwitch, &valve6aSwitchBit);
    dm_group_add_item(cpuGroup, dmItems->valve6bSwitch, &valve6bSwitchBit);
    dm_group_add_item(cpuGroup, dmItems->valve7aSwitch, &valve7aSwitchBit);
    dm_group_add_item(cpuGroup, dmItems->valve7bSwitch, &valve7bSwitchBit);

    dm_group_add_item(cpuGroup, dmItems->valvePackEnableSwitch,   &valvePackEnableSwitchBit);
    dm_group_add_item(cpuGroup, dmItems->toolsledHydraulicSwitch, &toolsledHydraulicSwitchBit);
    dm_group_add_item(cpuGroup, dmItems->schillingArmHydraulicSwitch, &schillingArmHydraulicSwitchBit);
    dm_group_add_item(cpuGroup, dmItems->spareHydraulicSwitch, &spareHydraulicSwitchBit);
    dm_group_add_item(cpuGroup, dmItems->vbHydraulicSwitch,    &vbHydraulicSwitchBit);


                                      /* Create GF/5V Data Manager Group     */
    gf5vGroup = initIbcGf5vConsumer( &dmItems->gf5vDm, &gf5vBits, dmUpdateSem);

                                      /* Add Switches to DM Group            */
    dm_group_add_item(ersGroup, ersDconSwitch.switchStatusDm,
                      &ersDconSwitchBit);

    for (board = 0; board < LPS_BOARDS; board++)
    {                                 /* Create LPS Data Manager Group       */
        lpsGroup[board] =
            initIbcLpsConsumer( &dmItems->lpsDm[board], &lpsBits[board],
               dmUpdateSem );
                                      /* Add Switch Requests to DM Group     */
        dm_group_add_item(ersGroup,
           ersLpsEnableSwitch[board].switchRequestDm, &lpsEnableBit[board]);
    } /* for */

    dm_group_add_item(ersGroup, pressureSensorSwitch.switchRequestDm,
                      &pressureSensorSwitchBit);

    dm_group_add_item(ersGroup, vbLevelSensorSwitch.switchRequestDm,
                      &vbLevelSensorSwitchBit);

    dm_group_add_item(ersGroup, compLevelSensorSwitch.switchRequestDm,
                      &compLevelSensorSwitchBit);

    dm_group_add_item(ersGroup, sciencePort12vSwitch.switchRequestDm,
                      &sciencePort12vSwitchBit);

    dm_group_add_item(ersGroup, ecuPowerSwitch.switchRequestDm,
                      &ecuPowerSwitchBit);

    dm_group_add_item(ersGroup, sciencePort24vSwitch.switchRequestDm,
                      &sciencePort24vSwitchBit);

    dm_group_add_item(ersGroup, vbFillSwitch.switchRequestDm,
                      &vbFillSwitchBit);

    dm_group_add_item(ersGroup, acousticModemSwitch.switchRequestDm,
                      &acousticModemSwitchBit);

    initDeploymentLatchOnTime(dmItems->deploymentLatchOnTime);

    FOREVER
    {                               /* Mark micro configuration as invalid   */
        microIOCtrl->microConfigured = FALSE;

                                    /* Wait for micro reset via SRQ Task     */
        semTake(microIOCtrl->childTasks[OUT_TASK].taskSyncSem, WAIT_FOREVER);

        /* We need to initialize default state of Data manager Items here    */

        ibcSetSwitchState (&pressureSensorSwitch,      SWITCH_ON);
        ibcSetSwitchState (&vbLevelSensorSwitch,       SWITCH_ON);
        ibcSetSwitchState (&compLevelSensorSwitch,     SWITCH_ON);
        ibcSetSwitchState (&sciencePort12vSwitch,      SWITCH_OFF);

        ibcSetSwitchState (&ecuPowerSwitch,            SWITCH_OFF);
        ibcSetSwitchState (&sciencePort24vSwitch,      SWITCH_OFF);

        ibcSetSwitchState (&vbFillSwitch,              SWITCH_OFF);
        ibcSetSwitchState (&acousticModemSwitch,       SWITCH_ON);

                                    /* Initialize DM item values and default */
        for (board = 0; board < LPS_BOARDS; board++)
            ibcSetSwitchState (&ersLpsEnableSwitch[board], SWITCH_ON );

        initIbcHumidityThreshDm(SERIAL_CHAN,
            dmItems->ibcDm.humidityWarnThresh,
            dmItems->ibcDm.humidityAlarmThresh);

        initWaterAlarmThreshDm(SERIAL_CHAN, dmItems->waterAlarmThresh);

        updateIbcGf5vDmItems( SERIAL_CHAN, GF5V_BOARD_ADDR,
                             &dmItems->gf5vDm, ersDconName );

                                     /* Set default charge time for PWR IBC B*/
        setGf5vChargeTimes( &dmItems->gf5vDm,
            LOW_VOLTAGE_GF_CHARGE_TIME, LOW_VOLTAGE_GF_CHARGE_TIME,
            LOW_VOLTAGE_GF_CHARGE_TIME, LOW_VOLTAGE_GF_CHARGE_TIME );

        enableGf5vMonitoring( SERIAL_CHAN, GF5V_BOARD_ADDR,
           &dmItems->gf5vDm, TRUE );

        runGf5vBoardSelftest( SERIAL_CHAN, GF5V_BOARD_ADDR, &dmItems->gf5vDm );

        for (board = 0; board < LPS_BOARDS; board++)
            updateIbcLpsDmItems( SERIAL_CHAN, lpsBoardAddr[board],
                &dmItems->lpsDm[board], ersDconName );

        initCompLevelMinMaxDm(SERIAL_CHAN, dmItems->compMinLevel,
            dmItems->compMaxLevel);

        writeCompMinMaxLevels(SERIAL_CHAN, dmItems->compMinLevel,
            dmItems->compMaxLevel);

        initCompLevelAlarmThreshDm(SERIAL_CHAN, dmItems->compWarnLevel,
            dmItems->compAlarmLevel);

        initHydPressureAlarmThreshDm(SERIAL_CHAN,
            dmItems->hydPressureWarnThresh,
            dmItems->hydPressureAlarmThresh);

        initERSBatteryLifeAlarmThreshDm(SERIAL_CHAN,
            dmItems->batteryLifeWarnThresh, dmItems->batteryLifeAlarmThresh);

        initERSBatteryVoltAlarmThreshDm(SERIAL_CHAN,
            dmItems->batteryVoltWarnThresh, dmItems->batteryVoltAlarmThresh);

        writeErsLatchStatusDm(dmItems->deploymentLatchArm,
            dmItems->deploymentLatchStatus, LATCH_DISARMED);

                                    /* Ignore any Data Manager Item changes  */
        ibcCpuGroupBits  = dm_get_group_changes(cpuGroup);
        ersDconGroupBits = dm_get_group_changes(ersGroup);

                                    /* Flag that micro has been configured   */
        microIOCtrl->microConfigured = TRUE;

                                    /* Wake up input task to read from micro */
        semGive(microIOCtrl->childTasks[IN_TASK].taskSyncSem);

        while (microIOCtrl->serialLinkState == LINK_UP)
        {                           /* Repeat until micro controller reset   */
                                    /* Wait for any data items to change     */
            semTake(dmUpdateSem, WAIT_FOREVER);

                                    /* Ask Data Manager which items changed  */
            ibcCpuGroupBits  = dm_get_group_changes(cpuGroup);
            ersDconGroupBits = dm_get_group_changes(ersGroup);

                                    /* Check if micro Reset Event occurred   */
            if (ibcCpuGroupBits & ibcCpuBits.resetEventBit)
                break;              /* Exit loop and re-initialize DM items  */

            taskSafe();             /* Prevent task from being deleted during*/
                                    /* serial IO and Data Manager updates    */

            if (ersDconGroupBits & operatingModeBit)
            {
                if ( (dm_read(dmItems->ersOperatingMode, &operatingMode,
                     sizeof(operatingMode), (DM_Time *) NULL) == SUCCESS) &&
                     (operatingMode == OPERATING_MODE) )
                {
                                    /* Initialize DM item values and default */
                    for (board = 0; board < LPS_BOARDS; board++)
                        ibcSetSwitchState (&ersLpsEnableSwitch[board],
                           SWITCH_ON);

                    ibcProcessSwitchRequest(&pressureSensorSwitch);
                    ibcProcessSwitchRequest(&vbLevelSensorSwitch);
                    ibcProcessSwitchRequest(&compLevelSensorSwitch);
                } /* if */
            } /* if */

                                    /* ERS Dcon Power Switch Request         */
            if (ersDconGroupBits & ersDconSwitchBit)
                ibcProcessDupSwitchRequest( &ersDconSwitch );

                                    /* ERS Dcon LPS Output Enable Request    */
            if (ersDconGroupBits & lpsEnableBit[0])
                ibcProcessSwitchRequest( &ersLpsEnableSwitch[0] );

            if (ersDconGroupBits & lpsEnableBit[1])
                ibcProcessSwitchRequest( &ersLpsEnableSwitch[1] );

            if (ersDconGroupBits & lpsEnableBit[2])
                ibcProcessSwitchRequest( &ersLpsEnableSwitch[2] );

                                    /* Pressure Sensor Power Switch Request  */
            if (ersDconGroupBits & pressureSensorSwitchBit)
                ibcProcessSwitchRequest( &pressureSensorSwitch );

            if (ersDconGroupBits & vbLevelSensorSwitchBit)
                ibcProcessSwitchRequest( &vbLevelSensorSwitch );

            if (ersDconGroupBits & compLevelSensorSwitchBit)
                ibcProcessSwitchRequest( &compLevelSensorSwitch );

            if (ersDconGroupBits & sciencePort12vSwitchBit)
                ibcProcessSwitchRequest( &sciencePort12vSwitch );

            if (ersDconGroupBits & ecuPowerSwitchBit)
            {
                ibcProcessSwitchRequest( &ecuPowerSwitch );
                taskDelay(CLOCKS_PER_SEC / (USECS_PER_SEC / POWER_DELAY));

                dm_read(ecuPowerSwitch.switchStatusDm, &valveSwitchState,
                        sizeof(valveSwitchState), (DM_Time *) NULL);
    
                if(valveSwitchState == SWITCH_ON)    
                   if(initECUDigitalOutputs(SERIAL_CHAN)==ERROR)
                    {
                        printf("ECU INIT Failed failed\n");

                    }


            }

            if (ersDconGroupBits & sciencePort24vSwitchBit)
                ibcProcessSwitchRequest( &sciencePort24vSwitch );

            if (ersDconGroupBits & vbFillSwitchBit)
                ibcProcessSwitchRequest( &vbFillSwitch );

            if (ersDconGroupBits & acousticModemSwitchBit)
                ibcProcessSwitchRequest( &acousticModemSwitch );

                                    /* ECU Output 1 Request         */
            if (ibcCpuGroupBits & valve1aSwitchBit)
            {
                dm_read( dmItems->valve1aSwitch,
                         (char *) &valve1aSwitch,
                            sizeof(valve1aSwitch), (DM_Time *) NULL);
                setECUDigitalOutputs(SERIAL_CHAN, 1,
                               valve1aSwitch ? ON : OFF);
            }

                                    /* ECU Output 2 Request         */
            if (ibcCpuGroupBits & valve1bSwitchBit)
            {
                dm_read( dmItems->valve1bSwitch,
                         (char *) &valve1bSwitch,
                            sizeof(valve1bSwitch), (DM_Time *) NULL);
                setECUDigitalOutputs(SERIAL_CHAN, 2,
                               valve1bSwitch ? ON : OFF);
            }


                                    /* ECU Output 3 Request         */
            if (ibcCpuGroupBits & valve2aSwitchBit)
            {
                dm_read( dmItems->valve2aSwitch,
                         (char *) &valve2aSwitch,
                            sizeof(valve2aSwitch), (DM_Time *) NULL);
                setECUDigitalOutputs(SERIAL_CHAN, 3,
                               valve2aSwitch ? ON : OFF);
            }

                                    /* ECU Output 4 Request         */
            if (ibcCpuGroupBits & valve2bSwitchBit)
            {
                dm_read( dmItems->valve2bSwitch,
                         (char *) &valve2bSwitch,
                            sizeof(valve2bSwitch), (DM_Time *) NULL);
                setECUDigitalOutputs(SERIAL_CHAN, 4,
                               valve2bSwitch ? ON : OFF);
            }

                                    /* ECU Output 5 Request         */
            if (ibcCpuGroupBits & valve3aSwitchBit)
            {
                dm_read( dmItems->valve3aSwitch,
                         (char *) &valve3aSwitch,
                            sizeof(valve3aSwitch), (DM_Time *) NULL);
                setECUDigitalOutputs(SERIAL_CHAN, 5,
                               valve3aSwitch ? ON : OFF);
            }

                                    /* ECU Output 6 Request         */
            if (ibcCpuGroupBits & valve3bSwitchBit)
            {
                dm_read( dmItems->valve3bSwitch,
                         (char *) &valve3bSwitch,
                            sizeof(valve3bSwitch), (DM_Time *) NULL);
                setECUDigitalOutputs(SERIAL_CHAN, 6,
                               valve3bSwitch ? ON : OFF);
            }


                                    /* ECU Output 7 Request         */
            if (ibcCpuGroupBits & valve4aSwitchBit)
            {
                dm_read( dmItems->valve4aSwitch,
                         (char *) &valve4aSwitch,
                            sizeof(valve4aSwitch), (DM_Time *) NULL);
                setECUDigitalOutputs(SERIAL_CHAN, 7,
                               valve4aSwitch ? ON : OFF);
            }

                                    /* ECU Output 8 Request         */
            if (ibcCpuGroupBits & valve4bSwitchBit)
            {
                dm_read( dmItems->valve4bSwitch,
                         (char *) &valve4bSwitch,
                            sizeof(valve4bSwitch), (DM_Time *) NULL);
                setECUDigitalOutputs(SERIAL_CHAN, 8,
                               valve4bSwitch ? ON : OFF);
            }


                                    /* ECU Output 9 Request         */
            if (ibcCpuGroupBits & valve5aSwitchBit)
            {
                dm_read( dmItems->valve5aSwitch,
                         (char *) &valve5aSwitch,
                            sizeof(valve5aSwitch), (DM_Time *) NULL);
                setECUDigitalOutputs(SERIAL_CHAN, 9,
                               valve5aSwitch ? ON : OFF);
            }

                                    /* ECU Output 10 Request         */
            if (ibcCpuGroupBits & valve5bSwitchBit)
            {
                dm_read( dmItems->valve5bSwitch,
                         (char *) &valve5bSwitch,
                            sizeof(valve5bSwitch), (DM_Time *) NULL);
                setECUDigitalOutputs(SERIAL_CHAN, 10,
                               valve5bSwitch ? ON : OFF);
            }


                                    /* ECU Output 11 Request         */
            if (ibcCpuGroupBits & valve6aSwitchBit)
            {
                dm_read( dmItems->valve6aSwitch,
                         (char *) &valve6aSwitch,
                            sizeof(valve6aSwitch), (DM_Time *) NULL);
                setECUDigitalOutputs(SERIAL_CHAN, 11,
                               valve6aSwitch ? ON : OFF);
            }

                                    /* ECU Output 12 Request         */
            if (ibcCpuGroupBits & valve6bSwitchBit)
            {
                dm_read( dmItems->valve6bSwitch,
                         (char *) &valve6bSwitch,
                            sizeof(valve6bSwitch), (DM_Time *) NULL);
                setECUDigitalOutputs(SERIAL_CHAN, 12,
                               valve6bSwitch ? ON : OFF);
            }

                                    /* ECU Output 13 Request         */
            if (ibcCpuGroupBits & valve7aSwitchBit)
            {
                dm_read( dmItems->valve7aSwitch,
                         (char *) &valve7aSwitch,
                            sizeof(valve7aSwitch), (DM_Time *) NULL);
                setECUDigitalOutputs(SERIAL_CHAN, 13,
                               valve7aSwitch ? ON : OFF);
            }

                                    /* ECU Output 14 Request         */
            if (ibcCpuGroupBits & valve7bSwitchBit)
            {
                dm_read( dmItems->valve7bSwitch,
                         (char *) &valve7bSwitch,
                            sizeof(valve7bSwitch), (DM_Time *) NULL);
                setECUDigitalOutputs(SERIAL_CHAN, 14,
                               valve7bSwitch ? ON : OFF);
            }

                                    /* ECU Output 16 Request         */
            if (ibcCpuGroupBits & valvePackEnableSwitchBit)
            {
                dm_read( dmItems->valvePackEnableSwitch,
                         (char *) &valvePackEnableSwitch,
                            sizeof(valvePackEnableSwitch), (DM_Time *) NULL);
                setECUDigitalOutputs(SERIAL_CHAN, 16,
                               valvePackEnableSwitch ? ON : OFF);
            }

                                 /* ECU Output 17 Request         */
            if (ibcCpuGroupBits & spareHydraulicSwitchBit)
            {
                dm_read( dmItems->spareHydraulicSwitch,
                         (char *) &spareHydraulicSwitch,
                            sizeof(spareHydraulicSwitch), (DM_Time *) NULL);
                setECUDigitalOutputs(SERIAL_CHAN, 17,
                               spareHydraulicSwitch ? ON : OFF);
            }

                               /* ECU Output 18 Request         */
            if (ibcCpuGroupBits & schillingArmHydraulicSwitchBit)
            {
                dm_read( dmItems->schillingArmHydraulicSwitch,
                         (char *) &schillingArmHydraulicSwitch,
                            sizeof(schillingArmHydraulicSwitch), (DM_Time *) NULL);
                setECUDigitalOutputs(SERIAL_CHAN, 18,
                               schillingArmHydraulicSwitch ? ON : OFF);
            }

                               /* ECU Output 19 Request         */
            if (ibcCpuGroupBits & vbHydraulicSwitchBit)
            {
                dm_read( dmItems->vbHydraulicSwitch,
                         (char *) &vbHydraulicSwitch,
                            sizeof(vbHydraulicSwitch), (DM_Time *) NULL);
                setECUDigitalOutputs(SERIAL_CHAN, 19,
                               vbHydraulicSwitch ? ON : OFF);
            }
          
                                /* ECU Output 20 Request         */
            if (ibcCpuGroupBits & toolsledHydraulicSwitchBit)
            {
                dm_read( dmItems->toolsledHydraulicSwitch,
                         (char *) &toolsledHydraulicSwitch,
                            sizeof(toolsledHydraulicSwitch), (DM_Time *) NULL);
                setECUDigitalOutputs(SERIAL_CHAN, 20,
                               toolsledHydraulicSwitch ? ON : OFF);
            }


                                    /* Check for GF/5V Board Parameter Update */
            ibcGf5vUpdateCheck( SERIAL_CHAN, GF5V_BOARD_ADDR,
                &dmItems->gf5vDm, &gf5vBits, gf5vGroup );

            for (board = 0; board < LPS_BOARDS; board++)
                                    /* Check for LPS Board Parameter Update   */
                ibcLpsUpdateCheck( SERIAL_CHAN, lpsBoardAddr[board],
                    &dmItems->lpsDm[board], &lpsBits[board], lpsGroup[board] );

                                    /* Send Set Water Alarm Threshold cmd     */
            if (ersDconGroupBits & waterAlarmThreshBit)
                writeWaterAlarmThresh(SERIAL_CHAN, dmItems->waterAlarmThresh);

                                    /* Send Set Humidity Alarm Threshold cmd  */
            if ( (ibcCpuGroupBits & ibcCpuBits.humidityWarnThreshBit)   ||
                 (ibcCpuGroupBits & ibcCpuBits.humidityAlarmThreshBit) )
                writeIbcHumidityThresh(SERIAL_CHAN,
                     dmItems->ibcDm.humidityWarnThresh,
                     dmItems->ibcDm.humidityAlarmThresh);

                                    /* Send Set Battery Life Alarm Threshold  */
            if ( (ersDconGroupBits & batteryLifeWarnThreshBit) ||
                 (ersDconGroupBits & batteryLifeAlarmThreshBit) )
                writeERSBatteryLifeAlarmThresh(SERIAL_CHAN,
                   dmItems->batteryLifeWarnThresh,
                   dmItems->batteryLifeAlarmThresh);

                                    /* Send Set Battery Voltage Alarm Thresh */
            if ( (ersDconGroupBits & batteryVoltWarnThreshBit) ||
                 (ersDconGroupBits & batteryVoltAlarmThreshBit) )
                writeERSBatteryVoltAlarmThresh(SERIAL_CHAN,
                   dmItems->batteryVoltWarnThresh,
                   dmItems->batteryVoltAlarmThresh);

                                    /* Send Read Battery Voltage Command     */
            if (ersDconGroupBits & batteryVoltageReadCmdBit)
                readERSBatteryVoltageCmd(SERIAL_CHAN);

                                    /* Send Comp Level Warn/Alarm Thresholds  */
            if ( (ersDconGroupBits & compWarnLevelBit) ||
                 (ersDconGroupBits & compAlarmLevelBit) )
                writeCompAlarmLevels(SERIAL_CHAN,
                      dmItems->compWarnLevel, dmItems->compAlarmLevel );

                                    /* Send Set Comp Level Min/Max cmd        */
            if ( (ersDconGroupBits & compMinLevelBit) ||
                 (ersDconGroupBits & compMaxLevelBit) )
                writeCompMinMaxLevels(SERIAL_CHAN,
                      dmItems->compMinLevel, dmItems->compMaxLevel );

                                    /* Send Hydraulic Pressure Alarm Thresh  */
            if ( (ersDconGroupBits & hydPressureWarnThreshBit)  ||
                 (ersDconGroupBits & hydPressureAlarmThreshBit) )
                writeHydPressureAlarmThresh(SERIAL_CHAN,
                     dmItems->hydPressureWarnThresh,
                     dmItems->hydPressureAlarmThresh);


            if (ersDconGroupBits & deploymentArmBit)
                ersArmDeploymentLatch(SERIAL_CHAN,
                    dmItems->deploymentLatchArm,
                    dmItems->deploymentLatchStatus);

            if (ersDconGroupBits & deploymentReleaseBit)
                ersReleaseDeploymentLatch(SERIAL_CHAN,
                    dmItems->deploymentLatchArm,
                    dmItems->deploymentLatchOnTime);

            if (ersDconGroupBits & deploymentJogBit)
                ersJogDeploymentLatch(SERIAL_CHAN,
                    dmItems->deploymentLatchArm, dmItems->deploymentLatchJog);

                                    /* Check if Reset Command requested       */
            if (ibcCpuGroupBits & ibcCpuBits.resetCmdBit)
            {                       /* Mark serial link as down               */
                setSerialLinkState(microIOCtrl, LINK_DOWN);
                                    /* Manual reset so ammounce it            */
                microIOCtrl->announceResets = TRUE;
                                    /* Send Reset Command to Microcontroller  */
                microResetCmd(SERIAL_CHAN);
                break;              /* Exit loop and wait for RESET           */
            } /* if */

            taskUnsafe();           /* Task may now be safely deleted         */

        } /* while (LINK_UP) */
    } /* FOREVER */

                        /* dm_stop_provider, dm_stop_consumer, dm_delete_group*/
                        /* etc are NOT required when the task exits as the    */
                        /* Data Manager does this automatically when the task */
                        /* is deleted via the taskDeleteHookAdd() and         */
                        /* dm_task_exit functions.                            */

                        /* That's all folks !                                 */
} /* ersDconOutTask() */

/******************************************************************************/
/* Function    : ersDconInTask                                               */
/* Purpose     : Emergency Dcon Input Task. Wakes up periodically, read data  */
/*               from the Emergency Dcon and write Data Manager Items         */
/* Inputs      : Array of Data Manager Item handles & serial chan structure   */
/* Outputs     : Normally runs forever, but exits if error occurs             */
/******************************************************************************/
    Void
ersDconInTask(Reg ersDconDmItems* dmItems, microIOControl *microIOCtrl)
{
    SEM_ID  wakeupSem;              /* Used by watch dog to wake up this task */
    Int32   updates = 0;            /* Counts dm updates for rate calculation */
    Int16   board;                  /* LPS Board Index                        */

                                    /* Create wakeup semaphore and watch dog  */
                                    /* timer for provider rate control        */
    if ((wakeupSem = semBCreate(SEM_Q_FIFO, SEM_EMPTY)) == NULL )
    {
        logMsg("ERS Dcon: Error initializing Input Task Resources\n");
        return;
    } /* if */
                                    /* Provider Task for non-static data items*/
    initIbcCpuProvider   (&dmItems->ibcDm,    HUMIDITY_DM_PERIOD);
    initIbcGf5vProvider  (&dmItems->gf5vDm,   ERS_DCON_DM_PERIOD);

    for (board = 0; board < LPS_BOARDS; board++)
        initIbcLpsProvider(&dmItems->lpsDm[board], ERS_DCON_DM_PERIOD);

    dm_start_provider(dmItems->compLevelPercent,   ERS_DCON_DM_PERIOD);
    dm_start_provider(dmItems->compLevelVolume,    ERS_DCON_DM_PERIOD);

    dm_start_provider(dmItems->ersDepth,           ERS_SENSOR_DM_PERIOD);
    dm_start_provider(dmItems->hydPressure,        ERS_SENSOR_DM_PERIOD);
    dm_start_provider(dmItems->vbLevelMM,          ERS_SENSOR_DM_PERIOD);
    dm_start_provider(dmItems->vbWeight,           ERS_SENSOR_DM_PERIOD);
    dm_start_provider(dmItems->vbVolume,           ERS_SENSOR_DM_PERIOD);

    dm_start_provider(dmItems->batteryCurrent,     ERS_ONE_SEC_DM_PERIOD);
    dm_start_provider(dmItems->batteryLife,        ERS_ONE_MIN_DM_PERIOD);
    dm_start_provider(dmItems->batteryVoltage,     DM_STATIC);

    dm_start_consumer(dmItems->vbMotorRunDm, DM_STATIC, SEM_NULL);

    FOREVER
    {                               /* Wait for IBC Coms to be initialized    */
        semTake(microIOCtrl->childTasks[IN_TASK].taskSyncSem, WAIT_FOREVER);

        while (microIOCtrl->serialLinkState == LINK_UP)
        {
            taskSafe();             /* Prevent task from being deleted during */
                                    /* serial IO and Data Manager updates     */

            updateERSTelemetryDm( SERIAL_CHAN, dmItems );

            if ((updates % (ERS_DCON_DM_PERIOD / ERS_SENSOR_DM_PERIOD)) == 0)
            {
                updateNewIbcGf5vDm(SERIAL_CHAN, GF5V_BOARD_ADDR,
                    &dmItems->gf5vDm);

                for (board = 0; board < LPS_BOARDS; board++)
                    updateIbcLpsDm( SERIAL_CHAN, lpsBoardAddr[board],
                        &dmItems->lpsDm[board] );

                updateCompSystemLevelDm( SERIAL_CHAN,
                   dmItems->compLevelPercent, dmItems->compLevelVolume );
            } /* if */

            if ((updates % (HUMIDITY_DM_PERIOD / ERS_SENSOR_DM_PERIOD)) == 0)
                updateIbcHumidityDm(SERIAL_CHAN, dmItems->ibcDm.microHumidity);

            taskUnsafe();           /* task may now be deleted safely         */

                                    /* increment & range check update counter */
            if (++updates == 10000) updates = 0;

                                    /* Pend until sem timeout wakes us up     */
            semTake(wakeupSem, sysClkRateGet() /
                    (USECS_PER_SEC / ERS_SENSOR_DM_PERIOD));
        } /* while */
    } /* FOREVER */

    semDelete(wakeupSem);           /* Release resources                      */

                        /* dm_stop_provider, dm_stop_consumer, dm_delete_group*/
                        /* etc are not required when the task exits as the    */
                        /* data manager does this automatically when the task */
                        /* is deleted via the taskDeleteHookAdd() and         */
                        /* dm_task_exit functions.                            */

} /* ersDConInTask() */ /* that's all folks !                                 */

/******************************************************************************/
/* Function    : processErsDconSRQ                                            */
/* Purpose     : Decode Service Request and take appropriate action           */
/* Inputs      : Array of DM items, serial channel                            */
/* Outputs     : Returns SRQ Received & many DM items are changed             */
/******************************************************************************/
    LOCAL Word
processErsDconSRQ(Reg ersDconDmItems* dmItems, microIOControl *microIOCtrl)
{
    Word srqRequest;                /* Service Request Value                  */
    Word status;                    /* IBC Alarm Status Word                  */
    Byte buffer[SRQ_PACKET_LEN];    /* Buffer for micro communications data   */
    ibcAlarm alarmStatus;           /* IBC Alarm Status                       */
    Nat16 batteryCurrent;           /* Battery Current Life                   */
    ersOperatingMode operatingMode; /* ERS Operating Mode                     */
    ersLatchMode latchStatus;       /* ERS Latch Mode                         */

                                    /* Wait for Service Requests              */
    if (readSRQPacket(SERIAL_CHAN, buffer, SRQ_PACKET_LEN, WAIT_FOREVER)
        == ERROR) return (ERROR);
                                    /* Service Request received so process it */
    srqRequest = wordFromBuf(buffer, 0);

    switch (srqRequest)             /* Decode Service Request from micro      */
    {
      case MICRO_RESET_SRQ:         /* Microcontroller Reset Occurred         */
                                    /* Post Reset Event DM Item               */
        if (microIOCtrl->announceResets)
            microResetEventDm(dmItems->ibcDm.microDm.resetEvent);
        break;

      case CAN_WATER_ALARM_ON_SRQ:    /* Housing Water Alarm Active     */
        writeBooleanDmItem(dmItems->canWaterAlarm, TRUE);
        break;

      case CAN_WATER_ALARM_OFF_SRQ:   /* Housing Water Alarm Inactive   */
        writeBooleanDmItem(dmItems->canWaterAlarm, FALSE);
        break;

      case JBOX_WATER_ALARM_ON_SRQ:   /* J Box Water Alarm Active       */
        writeBooleanDmItem(dmItems->jboxWaterAlarm, TRUE);
        break;

      case JBOX_WATER_ALARM_OFF_SRQ:  /* J Box Water Alarm Inactive     */
        writeBooleanDmItem(dmItems->jboxWaterAlarm, FALSE);
        break;

      case VEHICLE_IN_WATER_SRQ:      /* Vehicle In Water Status        */
        wordsFromBuf(buffer, 2, &srqRequest, &status);
        writeBooleanDmItem(dmItems->vehicleInWater, (MBool) status);
        break;

      case COMP_LEVEL_ALARM_SRQ:      /* Compensation Level Alarm       */
        wordsFromBuf(buffer, 2, &srqRequest, &status);
        alarmStatus = (ibcAlarm) status;
        writeDmItem(dmItems->compLevelAlarm, &alarmStatus, sizeof(alarmStatus));
        break;

      case ERS_MODE_SRQ:
        wordsFromBuf(buffer, 2, &srqRequest, &status);
        operatingMode = (ersOperatingMode) status;
        writeDmItem(dmItems->ersOperatingMode, &operatingMode,
            sizeof(operatingMode));
        break;

      case HYDRAULIC_PRES_ALARM_SRQ:
        wordsFromBuf(buffer, 2, &srqRequest, &status);
        alarmStatus = (ibcAlarm) status;
        writeDmItem(dmItems->hydPressureAlarm, &alarmStatus,
            sizeof(alarmStatus));
        break;

      case BATTERY_VOLTAGE_ALARM_SRQ:
        wordsFromBuf(buffer, 2, &srqRequest, &status);
        alarmStatus = (ibcAlarm) status;
        writeDmItem(dmItems->batteryVoltAlarm, &alarmStatus,
                    sizeof(alarmStatus));
        break;

      case BATTERY_LIFE_SRQ:
        wordsFromBuf(buffer, 2, &srqRequest, &status);
        alarmStatus = (ibcAlarm) status;
        writeDmItem(dmItems->batteryLifeAlarm, &alarmStatus,
           sizeof(alarmStatus));
        break;

      case DEPLOYMENT_LATCH_RUN_SRQ:
        wordsFromBuf(buffer, 2, &srqRequest, &status);
        if (status == TRUE)
             writeErsLatchStatusDm(dmItems->deploymentLatchArm,
                 dmItems->deploymentLatchStatus, LATCH_RUNNING);
        else
            executeLatchArm(OFF, DEPLOYMENT_LATCH_PWR_REQ_DM,
                DEPLOYMENT_LATCH_PWR_OK_DM, DEPLOYMENT_LATCH_POWER,
                dmItems->deploymentLatchArm, dmItems->deploymentLatchStatus);
        break;

      case ROVNAV_MSG_SRQ:
        writeDmItem(dmItems->rovnavCmd, buffer + 2, 4);
        break;

      default:
        if (processIbcCpuSRQ(srqRequest,  buffer, &dmItems->ibcDm) != TRUE)

        if (processIbcLpsSRQ(srqRequest,  buffer, lpsBoardAddr[0],
            &dmItems->lpsDm[0]) != TRUE)

        if (processIbcLpsSRQ(srqRequest,  buffer, lpsBoardAddr[1],
            &dmItems->lpsDm[1]) != TRUE)

        if (processIbcLpsSRQ(srqRequest,  buffer, lpsBoardAddr[2],
            &dmItems->lpsDm[2]) != TRUE)

        if (processIbcGf5vSRQ(srqRequest, buffer, GF5V_BOARD_ADDR,
            &dmItems->gf5vDm) != TRUE)

        if (processIbcQuadSerSRQ(srqRequest, buffer,
            SERIAL_BOARD_ADDR, &dmItems->quadSerDm) != TRUE)

            printf("ERS Dcon: Unrecognized SRQ 0x%x\n", srqRequest);
    } /* switch */

    return(srqRequest);                 /* Return SRQ received to caller      */
} /* processErsDconSRQ() */

STATUS initECUDigitalOutputs(sio32Chan *serialChan)
{
  STATUS status;
  Byte buffer[9];
  Int16 i, nBytes = 9;
  Byte checksum;

  ECU_OutputState[0] = 0;
  ECU_OutputState[1] = 0;
  ECU_OutputState[2] = 0;
  ECU_OutputState[3] = 0;

  if (Quad_Serial_Open( serialChan,
                             QUAD_SERIAL_0_ADDR,
                             ECU_BOARD_SERIAL_CHAN ) == ERROR)
    {
      printf("Quad Serial open failed\n");
     return(status);
    }

  if (Quad_Serial_SetLineParm( serialChan,
                             QUAD_SERIAL_0_ADDR,
                             ECU_BOARD_SERIAL_CHAN,
                             (Nat16) ECU_BAUD,
                             (Nat16) ECU_DATA,
                             (Nat16) ECU_STOP,
                             (Nat16) ECU_PAR,
			      ECU_HANDSHAKE,
                             ECU_PROTO) == ERROR)
    {
      printf("Quad Serial Set Line parameters failed\n");
     return(status);
    }



  buffer[0] = START_BYTE;
  buffer[1] = ALL_BOARDS;
  buffer[2] = DIG_OUT_FUNC;
  buffer[3] = 0x00;
  buffer[4] = 0x00;
  buffer[5] = 0x00;
  buffer[6] = 0x00;

  checksum = CHECKSUM_BASE;

  for(i=0; i<7; i++)
      checksum = checksum + buffer[i];

  buffer[7] = checksum;
  buffer[8] = END_BYTE;

  return Quad_Serial_Write( serialChan,
                             QUAD_SERIAL_0_ADDR,
                             ECU_BOARD_SERIAL_CHAN,
                             buffer, nBytes );
}

STATUS setECUDigitalOutputs(sio32Chan *serialChan, int chan, 
          MBool outputValue )
{
  STATUS status;
  Byte buffer[9];
  Int16 i, nBytes = 9;
  Byte checksum;
  Byte channelNo;
  Byte ECU_Board_Num;
  Int16 module;

  channelNo = (Byte)chan;

  if (channelNo <= 8)
  {
      ECU_Board_Num = BOARD_0;
      module        = MOTHER_BOARD;
  }
  else if(channelNo <= 16)
  {
      channelNo = channelNo - 8;
      ECU_Board_Num = BOARD_0;
      module        = EXPANSION_1;
  }
  else if(channelNo <= 24)
  {
      channelNo = channelNo - 16;
      ECU_Board_Num = BOARD_0;
      module        = EXPANSION_2;
  }
  else if(channelNo <= 32)
  {
      channelNo = channelNo - 24;
      ECU_Board_Num = BOARD_0;
      module        = EXPANSION_3;
  }


  switch (channelNo)
  {
    case 0:
      if (outputValue == ON)
      ECU_OutputState[module] |= CHANNEL_0;
      else if(outputValue == OFF)
      ECU_OutputState[module] &= ~CHANNEL_0;
      break;

    case 1:
      if (outputValue == ON)
      ECU_OutputState[module] |= CHANNEL_1;
      else if(outputValue == OFF)
      ECU_OutputState[module] &= ~CHANNEL_1;
      break;

    case 2:
      if (outputValue == ON)
      ECU_OutputState[module] |= CHANNEL_2;
      else if(outputValue == OFF)
      ECU_OutputState[module] &= ~CHANNEL_2;
      break;

    case 3:
      if (outputValue == ON)
      ECU_OutputState[module] |= CHANNEL_3;
      else if(outputValue == OFF)
      ECU_OutputState[module] &= ~CHANNEL_3;
      break;

    case 4:
      if (outputValue == ON)
      ECU_OutputState[module] |= CHANNEL_4;
      else if(outputValue == OFF)
      ECU_OutputState[module] &= ~CHANNEL_4;
      break;

    case 5:
      if (outputValue == ON)
      ECU_OutputState[module] |= CHANNEL_5;
      else if(outputValue == OFF)
      ECU_OutputState[module] &= ~CHANNEL_5;
      break;

    case 6:
      if (outputValue == ON)
      ECU_OutputState[module] |= CHANNEL_6;
      else if(outputValue == OFF)
      ECU_OutputState[module] &= ~CHANNEL_6;
      break;

    case 7:
      if (outputValue == ON)
      ECU_OutputState[module] |= CHANNEL_7;
      else if(outputValue == OFF)
      ECU_OutputState[module] &= ~CHANNEL_7;
      break;

    case 8:
      if (outputValue == ON)
      ECU_OutputState[module] |= CHANNEL_8;
      else if(outputValue == OFF)
      ECU_OutputState[module] &= ~CHANNEL_8;
      break;

  }

  buffer[0] = START_BYTE;
  buffer[1] = ECU_Board_Num;
  buffer[2] = DIG_OUT_FUNC;
  buffer[3] = ECU_OutputState[MOTHER_BOARD];
  buffer[4] = ECU_OutputState[EXPANSION_1];
  buffer[5] = ECU_OutputState[EXPANSION_2];
  buffer[6] = ECU_OutputState[EXPANSION_3];

  checksum = CHECKSUM_BASE;

  for(i=0; i<7; i++)
      checksum = checksum + buffer[i];

  buffer[7] = checksum;
  buffer[8] = END_BYTE;

  status =  Quad_Serial_Write( serialChan,
                             QUAD_SERIAL_0_ADDR,
                             ECU_BOARD_SERIAL_CHAN,
                             buffer, nBytes );
  if(status==ERROR)
    printf("Quad Serial Write failed\n");

  status = Quad_Serial_Read( serialChan,
                             QUAD_SERIAL_0_ADDR,
                             ECU_BOARD_SERIAL_CHAN,
                             buffer, nBytes );

  return(status);

}



