/****************************************************************************/
/* Copyright 1992 to 1996 MBARI                                             */
/****************************************************************************/
/* Summary  : Camera Dcon Interface Module for VxWorks                      */
/* Filename : cameraDcon.c                                                  */
/* Author   : Douglas Au                                                    */
/* Project  : Tiburon                                                       */
/* Version  : Version 1.0                                                   */
/* Created  : 07/08/93                                                      */
/* Modified : 08/17/96                                                      */
/* Archived :                                                               */
/****************************************************************************/
/* Modification History:                                                    */
/* $Header: cameraDcon.c,v 1.1 94/06/14 14:15:48 audo Exp $
 * $Log:        cameraDcon.c,v $
 * Revision 1.1  94/06/14  14:15:48  14:15:48  audo (Douglas Au)
 * Initial revision
 * Revision 1.1  96/08/16  11:57:00  11:57:00  audo (Douglas Au)
 * Initial revision
 *
 */
/****************************************************************************/

#include <vxWorks.h>                /* vxWorks system declarations          */
#include <semLib.h>                 /* vxWorks semaphore functions          */
#include <taskLib.h>                /* vxWorks task library functions       */
#include <lstLib.h>                 /* vxWorks linked list library          */
#include <wdLib.h>                  /* vxWorks watch dog timer functions    */
#include <systime.h>                /* vxWorks time and date functions      */
#include <msgQLib.h>                /* vxWorks Message Queue Library        */

#include <mbariTypes.h>             /* MBARI style guide type declarations  */
#include <mbariConst.h>             /* Miscellaneous constants              */

#include <rovPriority.h>            /* MBARI Rov Application Priorities     */
#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 "sio32.h"                  /* SIO32 hardware and driver information*/
#include "sio32Server.h"            /* Sio32 server communication services  */
#include "sio32Client.h"            /* Sio32 client communication services  */
#include "camera.h"                 /* Camera Definitions                   */
#include "cameraDcon.h"             /* Camera Dcon Can Definitions          */

#include "filter.h"                 /* median filter data structers         */

#include "applic.h"                 /* Microcontroller applications         */
#include "microcmd.h"               /* Microcontroller commands             */
#include "microDm.h"                /* Micro Data Manager Items & Functions */

#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 "camDcon.h"                /* Camera Dcon Micro 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 "vspDm.h"                  /* VSP Data Manager Interface Functions */
#include "vspCmd.h"                 /* VSP Function Prototypes              */
#include "microTask.h"              /* Microcontroller Task IO definitions  */

                                    /* Camera Dcon device Name              */
MLocal char* const cameraDconName = "Camera Dcon";
                                    /* Camera Dcon Data Mgr Item Name Prefix*/
MLocal char* const cameraIbcDmPrefix  = CAMERA_IBC_DM_PREFIX;

#define NUM_TASKS 3                 /* Number of co-operating tasks         */
#define GF5V_BOARD_ADDR     (Word) GROUND_FAULT_0_ADDR
#define SERIAL_BOARD_ADDR   (Word) QUAD_SERIAL_0_ADDR
#define ISOLATED_IO_BOARD_0_ADDR    (Word) ISO_IO_0_ADDR
#define LPS_BOARDS          2       /* Number of LPS Board in Camera Dcon   */
#define ISO_IO_SWITCHES     4       /* Number of Isolated Io Switches       */

MLocal Word lpsBoardAddr[LPS_BOARDS] =  /* LPS Board Assignments            */
{
    LOW_PWR_SWITCH_12V_0_ADDR,
    LOW_PWR_SWITCH_12V_1_ADDR
};

MLocal ibcCardConfig ibcCardSet =
{
    6,                              /* Number of IBC Cards Expected          */
    {
         CPU196,
         GF5V_BOARD_ADDR,
         LOW_PWR_SWITCH_12V_0_ADDR,
         LOW_PWR_SWITCH_12V_1_ADDR,
         ISOLATED_IO_BOARD_0_ADDR,
         SERIAL_BOARD_ADDR
    }
};


#define VSP_CHAN                         0

                                    /* Isolated IO Board 0 Assignments      */
#define SWITCH_0_CHAN                    0 /* Switch 0 On/Off channel       */
#define SWITCH_1_CHAN                    1 /* Switch 1 On/Off channel       */
#define SWITCH_2_CHAN                    2 /* Switch 2 On/Off channel       */
#define SWITCH_3_CHAN                    3 /* Switch 3 On/Off channel       */

                                    /* LPS Board Channel Assignments        */
#define PORT_COLOR_CAMERA_SWITCH_CHAN    0 /* Port Color Camera Power       */
#define BIO_LUME_CAMERA_SWITCH_CHAN      1 /* Bio Lume Camera Power         */
#define PILOT_SIT_CAMERA_SWITCH_CHAN     2 /* Pilot Sit Camera Power        */
#define GEN_BW_CAMERA2_SWITCH_CHAN       3 /* Generic BW Camera 2 Power     */

#define STBD_COLOR_CAMERA_SWITCH_CHAN    0 /* STBD Color Camera Power       */
#define GEN_COLOR_CAMERA_SWITCH_CHAN     1 /* Generic Color Camera Power    */
#define GEN_BW_CAMERA1_SWITCH_CHAN       2 /* Generic BW Camera 1 Power     */


#define CAMERA_DM_PERIOD        100000 /* Camera Data period 10 Hz          */
#define HUMIDITY_DM_PERIOD     2000000 /* Humidity camera period .5Hz       */
#define CAMERA_IBC_DM_PERIOD    100000 /* Camera Dcon Data period 10 Hz     */

#define CAMERA_IBC_IN_STACKSIZE   3000 /* Camera Dcon Input Task size & TCB */
#define CAMERA_IBC_OUT_STACKSIZE  4000 /* Camera Dcon Output Task size & TCB*/
#define CAMERA_IBC_TASK_STACKSIZE 4000

typedef struct                      /* Camera Dcon Data Manager Item Handles*/
{
    DM_Item powerSwitch;            /* Data Concentrator Power Switch       */
    DM_Item canWaterAlarm;          /* Housing Water Alarm Detected         */
    DM_Item jboxWaterAlarm;         /* J Box Water Alarm Detected           */
    DM_Item waterAlarmThresh;       /* Water Alarm Threshold                */
    DM_Item genBwCamShutterSwitch;  /* Generic Bw Cam Shutter Switch        */
    DM_Item bioLumeCamShutterSwitch;/* Bio Lume Camera Shutter Switch       */
    DM_Item isoIoSpareSwitch0;      /* Isolated Io Spare Switch 0           */
    DM_Item isoIoSpareSwitch1;      /* Isolated Io Spare Switch 1           */
    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 */
    ibcVspDmItems   vspDm;          /* VSP Data Manager Items               */
} cameraDconDmItems;


/****************************************************************************/

Void cameraDconInTask(Reg cameraDconDmItems *dmItems,
          microIOControl *microIOCtrl);

Void cameraDconOutTask(Reg cameraDconDmItems* dmItems,
          microIOControl *microIOCtrl);

MLocal Word processCameraDconSRQ( Reg cameraDconDmItems* dmItems,
          microIOControl *microIOCtrl);

MLocal Void initCameraDconDmItems(cameraDconDmItems* dmItems,
          sio32Chan* cameraDconDataChan);


/******************************************************************************/
/* Function    : cameraCanGetWaterAlarm                                       */
/* Purpose     : Read water alarm status from Camera Dcon microcontroller     */
/* Inputs      : Sio32 socket and pointer to water alarm status               */
/* Outputs     : Returns OK or ERROR                                          */
/******************************************************************************/
    LOCAL STATUS
cameraCanGetWaterAlarm( sio32Chan *IBC_SerialChan, Word *waterAlarmStatus )
{
                                    /* Send command to microcontroller        */
    return( microCommand(IBC_SerialChan, CAMERA_IBC_APP | GET_WATER_ALARM,
                        waterAlarmStatus) );
} /* cameraCanGetWaterAlarm() */

/****************************************************************************/
/* Function    : cameraGetWaterAlarmThresh                                  */
/* Purpose     : Reads water alarm threshold value from IBC CPU             */
/* Inputs      : Sio32 channel, pointer to water alarm threshold            */
/* Outputs     : Returns OK or ERROR                                        */
/****************************************************************************/
    LOCAL STATUS
cameraGetWaterAlarmThresh( sio32Chan *IBC_SerialChan, Int16 *waterAlarmThresh )
{
                                    /* Send command to microcontroller      */
    return (microCommand( IBC_SerialChan,
          CAMERA_IBC_APP | GET_WATER_ALARM_THRESH, waterAlarmThresh) );
} /* cameraGetWaterAlarmThresh() */

/****************************************************************************/
/* 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 (cameraGetWaterAlarmThresh( 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 )
{
    Errno   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,
             CAMERA_IBC_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              */
    if (cameraCanGetWaterAlarm(sio32DataChan, &waterAlarmStatus) != OK)
        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    : createCameraDconAppDmItems                                 */
/* Purpose     : Create Data Mgr Items specific to Camera Dcon Application  */
/* Inputs      : Pointer to structure of DM item handles, Dcon DM prefix,   */
/*               Camera DM prefix, Camera Data Concentrator Name            */
/* Outputs     : Returns OK or ERROR                                        */
/****************************************************************************/
    LOCAL STATUS
createCameraDconAppDmItems( cameraDconDmItems *cameraDmItems,
     const char* cameraDconDmPrefix, const char* cameraIbcDmPrefix,
     const char* cameraDconName )
{
    dmItemList cameraDconDmInit[] =

     {  { &cameraDmItems->canWaterAlarm,     "Housing Water Alarm",
                HOUSING_WATER_ALARM_DM,            DM_MBOOL, 1 },

        { &cameraDmItems->jboxWaterAlarm,    "J Box Water Alarm",
                JBOX_WATER_ALARM_DM,               DM_MBOOL, 1 },

        { &cameraDmItems->waterAlarmThresh,  "Water Alarm Threshold",
                WATER_ALARM_THRESH_DM,             DM_NAT16, 1 },

        { &cameraDmItems->genBwCamShutterSwitch,  "Gen BW Cam Shutter Switch",
                GEN_BW_CAMERA1_SHUTTER_SWITCH_DM,  DM_MBOOL, 1 },

        { &cameraDmItems->bioLumeCamShutterSwitch, "Bio Lume Cam Shutter Switch",
                BIO_LUME_CAMERA_SHUTTER_SWITCH_DM, DM_MBOOL, 1 },

        { &cameraDmItems->isoIoSpareSwitch0,  "Isolated Io Switch 0",
                ISO_IO_SPARE_SWITCH0_DM,           DM_MBOOL, 1 },

        { &cameraDmItems->isoIoSpareSwitch1,  "Isolated Io Switch 1",
                ISO_IO_SPARE_SWITCH1_DM,           DM_MBOOL, 1 },

        { NO_ITEM, NULL, NULL, DM_ENDT, 0 } };

                                   /* Initialize Data Manager Items from table*/
    if (initMicroDmItemList( cameraDconDmInit, cameraIbcDmPrefix,
        "Camera Dcon I/F" ) != OK)
        return(ERROR);

    if ( (cameraDmItems->powerSwitch = initMicroDmItem(
         "", CAMERA_DCON_SWITCH_STATUS_DM, DM_ENUM, 1)) == ERROR)
    {
        logMsg("Camera Dcon I/F: Error initializing Dcon Power Switch Item\n");
        return (ERROR);
    } /* if */

                                     /* Declare this task an item provider    */
    dm_start_provider(cameraDmItems->canWaterAlarm,  DM_STATIC);
    dm_start_provider(cameraDmItems->jboxWaterAlarm, DM_STATIC);

    dm_start_consumer(cameraDmItems->powerSwitch, DM_STATIC, SEM_NULL);

    return(OK);
} /* createCameraDconAppDmItems() */

/****************************************************************************/
/* Function    : cameraDconTask                                             */
/* Purpose     : Initializes communication with Camera Data Concentrator.   */
/*               Provides interface between Camera Data Concentrator and    */
/*               Data Manager items.                                        */
/* Inputs      : SIO32 serial channel number for Camera Data Concentrator   */
/*               Physically maps the Data Concentrators to a serial channel */
/* Outputs     : Normally runs forever, but returns ERROR on fatal error    */
/****************************************************************************/
    STATUS
cameraDconTask( Nat16 cameraDconSerialChan )
{
    cameraDconDmItems cameraDmItems; /* Camera Application Data Mgr handles  */
    microIOControl microIOCtrl;      /* Microcontroller IO Task control     */
    Int16   lps;                     /* Low Power Switch Board Index         */

                                    /* Initialize serial channel and task     */
                                    /* synchronization resources              */
    if (initMicroTaskIO( &microIOCtrl, NUM_TASKS, cameraDconSerialChan,
        cameraIbcDmPrefix, "/sio32/cameraDcon",
        CAMERA_DCON_SWITCH_STATUS_DM ) == ERROR)
    {
        logMsg("Error initializing IO for Camera DCon");
        return(ERROR);
    } /* if */

    bzero(&cameraDmItems, sizeof(cameraDmItems));

                                   /* Create IBC CPU Data Manager Items      */
    if (createIbcCpuDmItems(&(cameraDmItems.ibcDm), cameraIbcDmPrefix,
            cameraDconName)     == ERROR)
    {                              /* Error occurred so print message & exit */
        sio32ChanDestroy( cameraDconSerialChan, &microIOCtrl.sio32DataChan );
        return(ERROR);
    } /* if */

                         /* Create Virtual Serial Port Data Manager Items */
    if (createIbcVspDmItems(&cameraDmItems.vspDm, cameraIbcDmPrefix,
         cameraDconName, 0 )== ERROR)
    {                       /* Error occured so print message & exit         */
       sio32ChanDestroy( cameraDconSerialChan, &microIOCtrl.sio32DataChan );
       return(ERROR);
    } /* if */

                                   /* Create Camera Dcon Application Items   */
    if (createCameraDconAppDmItems(&cameraDmItems, cameraIbcDmPrefix,
           cameraIbcDmPrefix, cameraDconName) == ERROR)
    {                              /* Error occurred so print message & exit */
        sio32ChanDestroy( cameraDconSerialChan, &microIOCtrl.sio32DataChan );
        return(ERROR);
    } /* if */


    initIbcVspProvider  (&cameraDmItems.vspDm);

                                /* Create GF/5V Board Data Manager Items */
    createIbcGf5vDmItems( &cameraDmItems.gf5vDm, cameraIbcDmPrefix,
         cameraDconName );

    initIbcGf5vAlarmProvider( &cameraDmItems.gf5vDm );

                                    /* Create Quad Serial Board Data Mgr Items*/
    createIbcQuadSerDmItems( &cameraDmItems.quadSerDm, cameraIbcDmPrefix,
        cameraDconName, 0);

    initIbcQuadSerAlarmProvider( &cameraDmItems.quadSerDm );

    updateIbcQuadSerAlarmsDm( &microIOCtrl.sio32DataChan, SERIAL_BOARD_ADDR,
       &cameraDmItems.quadSerDm );


    for (lps = 0; lps < LPS_BOARDS; lps++)
    {                               /* Create IBC LPS Data Manager Items     */
        createIbcLpsDmItems( &cameraDmItems.lpsDm[lps], cameraIbcDmPrefix,
                cameraDconName, lps );
        initIbcLpsAlarmProvider( &cameraDmItems.lpsDm[lps] );
        updateIbcLpsAlarmsDm( &microIOCtrl.sio32DataChan, lpsBoardAddr[lps],
                         &cameraDmItems.lpsDm[lps] );
    } /* for */

                                    /* Initialize Camera Dcon Data Out Task   */
    if ((microIOCtrl.childTasks[OUT_TASK].taskId =
         taskSpawn("cameraDconOut", CAMERA_IBC_OUT_PRIORITY, 0,
         CAMERA_IBC_OUT_STACKSIZE, (FUNCPTR) cameraDconOutTask,
         (int) &cameraDmItems, (int) &microIOCtrl,
         0, 0, 0, 0, 0, 0, 0, 0)) == ERROR)
    {
                                    /* Close serial communication channel     */
        sio32ChanDestroy( cameraDconSerialChan, &microIOCtrl.sio32DataChan );
        logMsg("Camera Dcon: Error spawning data output task\n");
        return(ERROR);
    } /* if */

                                    /* Initialize Camera Dcon Data In Task    */
    if (( microIOCtrl.childTasks[IN_TASK].taskId =
         taskSpawn( "cameraDconIn", CAMERA_IBC_IN_PRIORITY, 0,
         CAMERA_IBC_IN_STACKSIZE, (FUNCPTR) cameraDconInTask,
         (int) &cameraDmItems, (int) &microIOCtrl,
         0, 0, 0, 0, 0, 0, 0, 0) ) == ERROR)
    {                               /* Delete Camera Dcon Out Task            */
        taskDelete(microIOCtrl.childTasks[OUT_TASK].taskId);
        sio32ChanDestroy( cameraDconSerialChan, &microIOCtrl.sio32DataChan );
        logMsg("Camera Dcon: Error spawning data input task\n");
        return(ERROR);
    } /* if */


    FOREVER
    {                               /* Check if Dcon is switched on           */
        if ((microDevPowerSwitchState(&microIOCtrl) != SWITCH_ON) ||
           ((microDevPowerSwitchState(&microIOCtrl) == SWITCH_ON) &&
            (microIOCtrl.resetEventCount != 0)))

                                    /* Process SRQ's from micro               */
        while(processCameraDconSRQ(&cameraDmItems, &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);

        /******* Re-initialize Data Manager items after reset received ***** */

                                    /* Initialize IBC Static Data Mgr Items  */
        if(initIbcCpuDmItems( &cameraDmItems.ibcDm, &microIOCtrl.sio32DataChan,
            cameraDconName, ibcCardSet )==OK)
        {
                                    /* Initialize Camera Dcon Applic Items   */
           initCameraDconDmItems( &cameraDmItems, &microIOCtrl.sio32DataChan );

           updateIbcGf5vAlarmsDm( &microIOCtrl.sio32DataChan, GF5V_BOARD_ADDR,
               &cameraDmItems.gf5vDm);

           updateIbcQuadSerAlarmsDm( &microIOCtrl.sio32DataChan,
               SERIAL_BOARD_ADDR,  &cameraDmItems.quadSerDm );

           for (lps = 0; lps < LPS_BOARDS; lps++)
               updateIbcLpsAlarmsDm( &microIOCtrl.sio32DataChan,
                  lpsBoardAddr[lps], &cameraDmItems.lpsDm[lps] );

           updateIbcVspDmItems( &microIOCtrl.sio32DataChan, SERIAL_BOARD_ADDR,
               VSP_CHAN,  &cameraDmItems.vspDm, cameraDconName );

                                    /* 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( cameraDconSerialChan, &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 functions*/

    return(OK);         /* That's all folks                                  */
} /* cameraDconTask() */

/*****************************************************************************/
/* Function    : initCameraDconDmItems                                       */
/* Purpose     : Reads parameters from Camera Dcon & update Data Mgr items   */
/* Inputs      : Array of Data Manager Item handles & serial chan structure  */
/* Outputs     : None, but Data Manager Items change                         */
/*****************************************************************************/
    LOCAL Void
initCameraDconDmItems( cameraDconDmItems* dmItems, sio32Chan*
    cameraDconDataChan )
{
                                /* Set Micro Water Alarms initial value      */
    if (updateWaterAlarmDm(cameraDconDataChan,
             dmItems->canWaterAlarm, dmItems->jboxWaterAlarm) == ERROR)
          logMsg("Camera Dcon: Error checking water alarm status\n");

} /* initCameraDconDmItems() */

/*****************************************************************************/
/* Function    : cameraDconOutTask                                           */
/* Purpose     : Camera Dcon Out Task. Read DM items & write to Camera Dcon  */
/* Inputs      : Array of Data Manager Item handles & serial chan structure  */
/* Outputs     : Normally runs forever, but exits if error occurs            */
/*****************************************************************************/
     Void
cameraDconOutTask(Reg cameraDconDmItems *dmItems, microIOControl *microIOCtrl)
{
    DM_Group cpuGroup;              /* CPU & Misc Item Data Manager Group    */
    DM_Group gf5vGroup;             /* GF/5V Board Data Manager Group        */

    DM_Group vspGroup;              /* VSP Data Manager Group                */

    DM_Group lpsGroup[LPS_BOARDS];  /* LPS 12V Board Data Manager Group      */

    SEM_ID  dmUpdateSem;            /* Data Manager Item Change wakeup sem   */
    SEM_ID  powerReqSem;            /* Power Request Update Semaphore        */

    Int16   lpsBoard;               /* Lps Board index                       */

    cpuUpdateBits   ibcCpuBits;     /* CPU Board Parameter Update Bits       */
    gf5vUpdateBits  gf5vBits;       /* GF/5V Board Paramater Update Bits     */

    vspUpdateBits   vspBits;        /* VSP Parameter Update Bits             */

    lpsUpdateBits   lpsBits[LPS_BOARDS];/* LPS Board Paramater Update Bits   */

    DWord   cameraDconGroupBits;    /* Holds dm_group_changes bit vector     */
    DWord   waterAlarmThreshBit;    /* Water alarm threshold item change bit */

    DWord   lps0EnableBit;          /* LPS 0 Enable Request changed bit      */
    DWord   lps1EnableBit;          /* LPS 0 Enable Request changed bit      */

    DWord   portColorCameraSwitchBit;/* Port Color Camera Switch bit         */
    DWord   bioLumeCameraSwitchBit; /* Bio Lume Camera Switch bit            */
    DWord   pilotSitCameraSwitchBit; /* Pilot Sit Camera Switch bit          */
    DWord   genBWCamera2SwitchBit;  /* Generic BW Camera2 Switch bit         */

    DWord   stbdColorCameraSwitchBit;/* Starboard Color Camera Switch bit    */
    DWord   genColorCameraSwitchBit;/* Generic Color Camera Switch bit       */
    DWord   genBWCamera1SwitchBit;  /* Generic BW Camera1 Switch bit         */

    DWord   isoIoSwitch0Bit;        /* Isolated IO switch 0 bit              */
    DWord   isoIoSwitch1Bit;        /* Isolated IO switch 1 bit              */
    DWord   isoIoSwitch2Bit;        /* Isolated IO switch 2 bit              */
    DWord   isoIoSwitch3Bit;        /* Isolated IO switch 3 bit              */
    DWord   cameraDconSwitchBit;    /* CameraDcon Switch Request changed bit */

                                    /* Camera Dcon LPS Output Enable switches*/
    switchEntry cameraLps0EnableSwitch;
    switchEntry cameraLps1EnableSwitch;

    switchEntry cameraDconSwitch;    /* Camera DCon Switch                   */

    switchEntry portColorCameraSwitch;/* Port Color Camera Switch            */
    switchEntry bioLumeCameraSwitch;  /* Bio Lume Camera Switch              */
    switchEntry pilotSitCameraSwitch;/* Pilot Sit Camera Switch              */
    switchEntry genBWCamera2Switch;  /* Generic Black/White Camera 2 Switch  */

    switchEntry stbdColorCameraSwitch;/* Starboard Color Camera Switch       */     switchEntry genColorCameraSwitch;/* Generic Color Camera Switch          */
    switchEntry genBWCamera1Switch;  /* Generic Black/White Camera 2 Switch  */

    MBool       genBwCamShutterSwitch;
    MBool       bioLumeCamShutterSwitch;
    MBool       isoIoSpareSwitch0;
    MBool       isoIoSpareSwitch1;

/*****************************************************************************/
/* The code is this task implements the following interconnected switches for
   the camera data concentrator, and 7 cameras

             Camera Dcon     12V LPS Enable  LPS 0-4
   48V Bus _____ \_____________ \______________ \__Port Color Camera LPS____|
                      |                      |                              |
                      |                      |_ \__Bio-Lume Camera LPS______|
                      |                      |                              |
                      |                      |_ \__Pilot Sit Camera LPS_ ___|
                      |                      |                              |
                      |                      |_ \__Generic B/W Camera2 LPS__|
                      |                                                     |
                      |      12V LPS Enable LPS 0-4                         |
                      |________ \______________ \__STBD Color Camera LPS____|
                                             |                              |
                                             |_ \__Generic Color Camera LPS_|
                                             |                              |
                                             |_ \__Generic B/W Camera1 LPS__|
                                             |                              |
                                             |_ \_____ spare 12V LPS  ______|


                                                                              */
/* isolated IO Board has 4 switches used as contact closures                  */


/******************************************************************************/

                                    /* Create switch & power sync semaphores */
    if ( ((dmUpdateSem = semBCreate(SEM_Q_FIFO, SEM_EMPTY)) == NULL) ||
         ((powerReqSem = semBCreate(SEM_Q_FIFO, SEM_EMPTY)) == NULL) )
    {
        logMsg("Camera Dcon: Error initializing Input Task Resources\n");
        return;
    } /* if */

    duplicateIbcSwitchEntry( &cameraDconSwitch,
        CAMERA_DCON_SWITCH_REQ_DM,  CAMERA_DCON_SWITCH_STATUS_DM,
        dmUpdateSem, cameraDconName, "Camera DCon Switch");

    initIbcSwitchEntry( &cameraLps0EnableSwitch, SERIAL_CHAN,
        VICOR_STANDBY_POWER,        B48,                      HOTEL,
        LOW_POWER_SWITCH,           lpsBoardAddr[0],      LPS_VICOR_ENABLE,
        CAMERA_LPS0_ENABLE_SWITCH_REQ_DM, CAMERA_LPS0_ENABLE_STATUS_DM,
        dmUpdateSem,
        CAMERA_LPS0_ENABLE_PWR_REQ_DM,    CAMERA_LPS0_ENABLE_PWR_OK_DM,
        powerReqSem,                cameraDconName,      "LPS 0 Enable");

    initIbcSwitchEntry( &portColorCameraSwitch, SERIAL_CHAN,
        PORT_COLOR_CAMERA_POWER,      B48,                      HOTEL,
        LOW_POWER_SWITCH,     lpsBoardAddr[0],  PORT_COLOR_CAMERA_SWITCH_CHAN,
        PORT_COLOR_CAMERA_SWITCH_REQ_DM, PORT_COLOR_CAMERA_SWITCH_STATUS_DM,
        dmUpdateSem,
        PORT_COLOR_CAMERA_PWR_REQ_DM,    PORT_COLOR_CAMERA_PWR_OK_DM,
        powerReqSem,         cameraDconName,   "Port Color Camera Switch");


    initIbcSwitchEntry( &bioLumeCameraSwitch, SERIAL_CHAN,
        BIO_LUME_CAMERA_POWER,      B48,                      HOTEL,
        LOW_POWER_SWITCH,     lpsBoardAddr[0],  BIO_LUME_CAMERA_SWITCH_CHAN,
        BIO_LUME_CAMERA_SWITCH_REQ_DM, BIO_LUME_CAMERA_SWITCH_STATUS_DM,
        dmUpdateSem,
        BIO_LUME_CAMERA_PWR_REQ_DM,    BIO_LUME_CAMERA_PWR_OK_DM,
        powerReqSem,         cameraDconName,   "Bio-Lume Camera Switch");

    initIbcSwitchEntry( &pilotSitCameraSwitch, SERIAL_CHAN,
        PILOT_SIT_CAMERA_POWER,      B48,                      HOTEL,
        LOW_POWER_SWITCH,     lpsBoardAddr[0],  PILOT_SIT_CAMERA_SWITCH_CHAN,
        PILOT_SIT_CAMERA_SWITCH_REQ_DM, PILOT_SIT_CAMERA_SWITCH_STATUS_DM,
        dmUpdateSem,
        PILOT_SIT_CAMERA_PWR_REQ_DM,    PILOT_SIT_CAMERA_PWR_OK_DM,
        powerReqSem,         cameraDconName,   "Pilot Sit Camera Switch");

    initIbcSwitchEntry( &genBWCamera2Switch, SERIAL_CHAN,
        GEN_BW_CAMERA2_POWER,      B48,                      HOTEL,
        LOW_POWER_SWITCH,     lpsBoardAddr[0],  GEN_BW_CAMERA2_SWITCH_CHAN,
        GEN_BW_CAMERA2_SWITCH_REQ_DM, GEN_BW_CAMERA2_SWITCH_STATUS_DM,
        dmUpdateSem,
        GEN_BW_CAMERA2_PWR_REQ_DM,    GEN_BW_CAMERA2_PWR_OK_DM,
        powerReqSem,         cameraDconName,   "Generic BW Camera2 Switch");

    initIbcSwitchEntry( &cameraLps1EnableSwitch, SERIAL_CHAN ,
        VICOR_STANDBY_POWER,        B48,                      HOTEL,
        LOW_POWER_SWITCH,           lpsBoardAddr[1],      LPS_VICOR_ENABLE,
        CAMERA_LPS1_ENABLE_SWITCH_REQ_DM, CAMERA_LPS1_ENABLE_STATUS_DM,
        dmUpdateSem,
        CAMERA_LPS1_ENABLE_PWR_REQ_DM,    CAMERA_LPS1_ENABLE_PWR_OK_DM,
        powerReqSem,                cameraDconName,      "LPS 1 Enable");

    initIbcSwitchEntry( &stbdColorCameraSwitch, SERIAL_CHAN,
        STBD_COLOR_CAMERA_POWER,      B48,                      HOTEL,
        LOW_POWER_SWITCH,     lpsBoardAddr[1],  STBD_COLOR_CAMERA_SWITCH_CHAN,
        STBD_COLOR_CAMERA_SWITCH_REQ_DM, STBD_COLOR_CAMERA_SWITCH_STATUS_DM,
        dmUpdateSem,
        STBD_COLOR_CAMERA_PWR_REQ_DM,    STBD_COLOR_CAMERA_PWR_OK_DM,
        powerReqSem,         cameraDconName,   "Starboard Color Camera Switch");

    initIbcSwitchEntry( &genColorCameraSwitch, SERIAL_CHAN,
        GEN_COLOR_CAMERA_POWER,      B48,                      HOTEL,
        LOW_POWER_SWITCH,   lpsBoardAddr[1], GEN_COLOR_CAMERA_SWITCH_CHAN,
        GEN_COLOR_CAMERA_SWITCH_REQ_DM,
        GEN_COLOR_CAMERA_SWITCH_STATUS_DM,           dmUpdateSem,
        GEN_COLOR_CAMERA_PWR_REQ_DM,    GEN_COLOR_CAMERA_PWR_OK_DM,
        powerReqSem,         cameraDconName,   "Generic Color Camera Switch");

    initIbcSwitchEntry( &genBWCamera1Switch, SERIAL_CHAN,
        GEN_BW_CAMERA1_POWER,      B48,                      HOTEL,
        LOW_POWER_SWITCH,     lpsBoardAddr[1],  GEN_BW_CAMERA1_SWITCH_CHAN,
        GEN_BW_CAMERA1_SWITCH_REQ_DM, GEN_BW_CAMERA1_SWITCH_STATUS_DM,
        dmUpdateSem,
        GEN_BW_CAMERA1_PWR_REQ_DM,    GEN_BW_CAMERA1_PWR_OK_DM,
        powerReqSem,         cameraDconName,   "Generic BW Camera1 Switch");


    ibcAddSwitchInSeries( &cameraDconSwitch, &cameraLps0EnableSwitch );
    ibcAddSwitchInSeries( &cameraDconSwitch, &cameraLps1EnableSwitch );

                                   /* Devices on Camera Can Low Power Switches*/
    ibcAddSwitchInSeries( &cameraLps0EnableSwitch, &portColorCameraSwitch );
    ibcAddSwitchInSeries( &cameraLps0EnableSwitch, &bioLumeCameraSwitch );
    ibcAddSwitchInSeries( &cameraLps0EnableSwitch, &pilotSitCameraSwitch );
    ibcAddSwitchInSeries( &cameraLps0EnableSwitch, &genBWCamera2Switch );

    ibcAddSwitchInSeries( &cameraLps1EnableSwitch, &stbdColorCameraSwitch );
    ibcAddSwitchInSeries( &cameraLps1EnableSwitch, &genColorCameraSwitch );
    ibcAddSwitchInSeries( &cameraLps1EnableSwitch, &genBWCamera1Switch );

    ibcConnectLpsDmItems( &dmItems->lpsDm[0], &portColorCameraSwitch,
         cameraDconName, "Port Color Camera", PORT_COLOR_CAMERA_SWITCH_CHAN,
         PORT_COLOR_CAMERA_CURRENT_DM, PORT_COLOR_CAMERA_CURRENT_ALARM_DM,
         PORT_COLOR_CAMERA_CURRENT_WARN_THRESH_DM,
         PORT_COLOR_CAMERA_CURRENT_ALARM_THRESH_DM);

    ibcConnectLpsDmItems( &dmItems->lpsDm[0], &bioLumeCameraSwitch,
         cameraDconName, "Bio Lume Camera", BIO_LUME_CAMERA_SWITCH_CHAN,
         BIO_LUME_CAMERA_CURRENT_DM, BIO_LUME_CAMERA_CURRENT_ALARM_DM,
         BIO_LUME_CAMERA_CURRENT_WARN_THRESH_DM,
         BIO_LUME_CAMERA_CURRENT_ALARM_THRESH_DM);

    ibcConnectLpsDmItems( &dmItems->lpsDm[0], &pilotSitCameraSwitch,
         cameraDconName, "Pilot Sit Camera", PILOT_SIT_CAMERA_SWITCH_CHAN,
         PILOT_SIT_CAMERA_CURRENT_DM, PILOT_SIT_CAMERA_CURRENT_ALARM_DM,
         PILOT_SIT_CAMERA_CURRENT_WARN_THRESH_DM,
         PILOT_SIT_CAMERA_CURRENT_ALARM_THRESH_DM);

    ibcConnectLpsDmItems( &dmItems->lpsDm[0], &genBWCamera2Switch,
         cameraDconName, "Generic BW Camera2", GEN_BW_CAMERA2_SWITCH_CHAN,
         GEN_BW_CAMERA2_CURRENT_DM, GEN_BW_CAMERA2_CURRENT_ALARM_DM,
         GEN_BW_CAMERA2_CURRENT_WARN_THRESH_DM,
         GEN_BW_CAMERA2_CURRENT_ALARM_THRESH_DM);

    ibcConnectLpsDmItems( &dmItems->lpsDm[1], &stbdColorCameraSwitch,
         cameraDconName, "Starboard Color Camera",STBD_COLOR_CAMERA_SWITCH_CHAN,
         STBD_COLOR_CAMERA_CURRENT_DM, STBD_COLOR_CAMERA_CURRENT_ALARM_DM,
         STBD_COLOR_CAMERA_CURRENT_WARN_THRESH_DM,
         STBD_COLOR_CAMERA_CURRENT_ALARM_THRESH_DM);

    ibcConnectLpsDmItems( &dmItems->lpsDm[1], &genBWCamera1Switch,
         cameraDconName, "Generic Color Camera",
         GEN_COLOR_CAMERA_SWITCH_CHAN,
         GEN_COLOR_CAMERA_CURRENT_DM,
         GEN_COLOR_CAMERA_CURRENT_ALARM_DM,
         GEN_COLOR_CAMERA_CURRENT_WARN_THRESH_DM,
         GEN_COLOR_CAMERA_CURRENT_ALARM_THRESH_DM);

    ibcConnectLpsDmItems( &dmItems->lpsDm[1], &genBWCamera1Switch,
         cameraDconName, "Generic BW Camera1", GEN_BW_CAMERA1_SWITCH_CHAN,
         GEN_BW_CAMERA1_CURRENT_DM, GEN_BW_CAMERA1_CURRENT_ALARM_DM,
         GEN_BW_CAMERA1_CURRENT_WARN_THRESH_DM,
         GEN_BW_CAMERA1_CURRENT_ALARM_THRESH_DM);

                                     /* 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->genBwCamShutterSwitch,
                      DM_STATIC, dmUpdateSem);
    dm_start_consumer(dmItems->bioLumeCamShutterSwitch,
                      DM_STATIC, dmUpdateSem);
    dm_start_consumer(dmItems->isoIoSpareSwitch0,
                      DM_STATIC, dmUpdateSem);
    dm_start_consumer(dmItems->isoIoSpareSwitch1,
                      DM_STATIC, dmUpdateSem);

    dm_group_add_item(cpuGroup, cameraDconSwitch.switchStatusDm,
                      &cameraDconSwitchBit);

    dm_group_add_item(cpuGroup, dmItems->waterAlarmThresh,
                      &waterAlarmThreshBit);

                                     /* Isolated I/O Switches                 */
    dm_group_add_item(cpuGroup, dmItems->genBwCamShutterSwitch,
                      &isoIoSwitch0Bit);
    dm_group_add_item(cpuGroup, dmItems->bioLumeCamShutterSwitch,
                      &isoIoSwitch1Bit);
    dm_group_add_item(cpuGroup, dmItems->isoIoSpareSwitch0,
                      &isoIoSwitch2Bit);
    dm_group_add_item(cpuGroup, dmItems->isoIoSpareSwitch1,
                      &isoIoSwitch3Bit);



                                      /* Create GF/5V Data Manager Group     */
    gf5vGroup = initIbcGf5vConsumer( &dmItems->gf5vDm, &gf5vBits, dmUpdateSem );

                            /* Create Virtual Serial Port Data Manager Group */
    vspGroup = initIbcVspConsumer( &dmItems->vspDm, &vspBits, dmUpdateSem );

                                      /* Create LPS Data Manager Group        */
    for (lpsBoard = 0; lpsBoard < LPS_BOARDS; lpsBoard++)
        lpsGroup[lpsBoard] = initIbcLpsConsumer(&dmItems->lpsDm[lpsBoard],
                                &lpsBits[lpsBoard], dmUpdateSem);

                                      /* Add Switch Requests to DM Group     */
    dm_group_add_item(cpuGroup, cameraLps0EnableSwitch.switchRequestDm,
                      &lps0EnableBit);

    dm_group_add_item(cpuGroup, cameraLps1EnableSwitch.switchRequestDm,
                      &lps1EnableBit);

    dm_group_add_item(cpuGroup, portColorCameraSwitch.switchRequestDm,
                      &portColorCameraSwitchBit);

    dm_group_add_item(cpuGroup, bioLumeCameraSwitch.switchRequestDm,
                      &bioLumeCameraSwitchBit);

    dm_group_add_item(cpuGroup, pilotSitCameraSwitch.switchRequestDm,
                      &pilotSitCameraSwitchBit);

    dm_group_add_item(cpuGroup, genBWCamera2Switch.switchRequestDm,
                      &genBWCamera2SwitchBit);

    dm_group_add_item(cpuGroup, stbdColorCameraSwitch.switchRequestDm,
                      &stbdColorCameraSwitchBit);

    dm_group_add_item(cpuGroup, genColorCameraSwitch.switchRequestDm,
                      &genColorCameraSwitchBit);

    dm_group_add_item(cpuGroup, genBWCamera1Switch.switchRequestDm,
                      &genBWCamera1SwitchBit);

                                    /* Clear Changed Bits before we Start    */
    cameraDconGroupBits = dm_get_group_changes(cpuGroup);

    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    */

                                    /* Initialize DM item values and default */
                                    /* IBC Switch states                     */
        ibcSetSwitchState (&bioLumeCameraSwitch,    SWITCH_OFF);
        ibcSetSwitchState (&pilotSitCameraSwitch,   SWITCH_OFF);
        ibcSetSwitchState (&genColorCameraSwitch,   SWITCH_OFF);

        ibcSetSwitchState (&cameraLps0EnableSwitch, SWITCH_ON );
        ibcSetSwitchState (&cameraLps1EnableSwitch, SWITCH_ON );
        ibcSetSwitchState (&portColorCameraSwitch,  SWITCH_ON );
        ibcSetSwitchState (&stbdColorCameraSwitch,  SWITCH_ON );
        ibcSetSwitchState (&genBWCamera1Switch,     SWITCH_ON );
        ibcSetSwitchState (&genBWCamera2Switch,     SWITCH_ON );


        initIbcHumidityThreshDm( SERIAL_CHAN, dmItems->ibcDm.humidityWarnThresh,
           dmItems->ibcDm.humidityAlarmThresh);

        initWaterAlarmThreshDm( SERIAL_CHAN, dmItems->waterAlarmThresh);

        updateIbcGf5vDmItems( SERIAL_CHAN, GF5V_BOARD_ADDR,
            &dmItems->gf5vDm, cameraDconName );

        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, FALSE);

        runGf5vBoardSelftest( SERIAL_CHAN, GF5V_BOARD_ADDR, &dmItems->gf5vDm );

        updateIbcVspDmItems( SERIAL_CHAN, SERIAL_BOARD_ADDR,
            VSP_CHAN, &dmItems->vspDm, cameraDconName );

        updateIbcLpsDmItems( SERIAL_CHAN, lpsBoardAddr[0],
            &dmItems->lpsDm[0], cameraDconName );

        updateIbcLpsDmItems( SERIAL_CHAN, lpsBoardAddr[1],
            &dmItems->lpsDm[1], cameraDconName );

                                   /* Clear Changed Bits before we start      */
        cameraDconGroupBits = dm_get_group_changes(cpuGroup);
                                    /* Flag that micro has been configured    */
        microIOCtrl->microConfigured = TRUE;

                                    /* Wake up input task to read from micro  */
        semGive(microIOCtrl->childTasks[IN_TASK].taskSyncSem);

                                    /* Clear changed item bits in DM         */
        cameraDconGroupBits = dm_get_group_changes(cpuGroup);

        while (microIOCtrl->serialLinkState == LINK_UP)
        {                           /* Wait for any data items to change     */
            semTake(dmUpdateSem, WAIT_FOREVER);

                                   /* Ask Data Manager which items changed   */
            cameraDconGroupBits = dm_get_group_changes(cpuGroup);

                                    /* Check if micro Reset Event occurred   */
            if (cameraDconGroupBits & ibcCpuBits.resetEventBit)
                break;              /* Exit loop and re-initialize DM items  */

            taskSafe();             /* Prevent task from being deleted during*/
                                    /* serial IO and Data Manager updates    */

                                    /* Camera Dcon Power Switch Request      */
            if (cameraDconGroupBits & cameraDconSwitchBit)
            {
                ibcProcessDupSwitchRequest( &cameraDconSwitch );
                if (microDevPowerSwitchState(microIOCtrl) != SWITCH_ON)
                {                   /* DCon is switched off so link is down  */
                    setSerialLinkState(microIOCtrl, LINK_DOWN);
                    taskSafe();
                    break;
                } /* if */
            } /* if */

                                    /* Camera Can LPS Output Enable Request  */
            if (cameraDconGroupBits & lps0EnableBit)
                ibcProcessSwitchRequest( &cameraLps0EnableSwitch );

            if (cameraDconGroupBits & lps1EnableBit)
                ibcProcessSwitchRequest( &cameraLps1EnableSwitch );


            if (cameraDconGroupBits & portColorCameraSwitchBit)
                ibcProcessSwitchRequest( &portColorCameraSwitch );

                                    /* Bio Lume Camera Power Switch Request   */
            if (cameraDconGroupBits & bioLumeCameraSwitchBit)
                ibcProcessSwitchRequest( &bioLumeCameraSwitch );

                                    /* Pilot Sit Camera Power Switch Request  */
            if (cameraDconGroupBits & pilotSitCameraSwitchBit)
                ibcProcessSwitchRequest( &pilotSitCameraSwitch );

                                    /* Generic BW Camera2 Power Switch Request*/
            if (cameraDconGroupBits & genBWCamera2SwitchBit)
                ibcProcessSwitchRequest( &genBWCamera2Switch );

                                    /* Stbd Color Camera Power Switch Request */
            if (cameraDconGroupBits & stbdColorCameraSwitchBit)
                ibcProcessSwitchRequest( &stbdColorCameraSwitch );

                                  /* Generic Color Camera Power Switch Request*/
            if (cameraDconGroupBits & genColorCameraSwitchBit)
                ibcProcessSwitchRequest( &genColorCameraSwitch );

                                    /* Generic BW Camera1 Power Switch Request*/
            if (cameraDconGroupBits & genBWCamera1SwitchBit)
                ibcProcessSwitchRequest( &genBWCamera1Switch );

                                    /* Isolated I/O Switch 0 Request         */
            if (cameraDconGroupBits & isoIoSwitch0Bit)
            {
                dm_read( dmItems->bioLumeCamShutterSwitch,
                         (char *) &bioLumeCamShutterSwitch,
                            sizeof(bioLumeCamShutterSwitch), (DM_Time *) NULL);
                ibcSwitchControl(SERIAL_CHAN, ISOLATED_IO,
                               ISOLATED_IO_BOARD_0_ADDR, SWITCH_0_CHAN,
                                                bioLumeCamShutterSwitch);
            }

                                    /* Isolated I/O Switch 1 Request         */
            if (cameraDconGroupBits & isoIoSwitch1Bit)
            {
                dm_read( dmItems->genBwCamShutterSwitch,
                         (char *) &genBwCamShutterSwitch,
                              sizeof(genBwCamShutterSwitch), (DM_Time *) NULL);

                ibcSwitchControl(SERIAL_CHAN, ISOLATED_IO,
                               ISOLATED_IO_BOARD_0_ADDR, SWITCH_1_CHAN,
                                                   genBwCamShutterSwitch);
            }

                                    /* Isolated I/O Switch 2 Request         */
            if (cameraDconGroupBits & isoIoSwitch2Bit)
            {
                dm_read( dmItems->isoIoSpareSwitch0,
                         (char *) &isoIoSpareSwitch0,
                              sizeof(isoIoSpareSwitch0), (DM_Time *) NULL);
                  ibcSwitchControl(SERIAL_CHAN, ISOLATED_IO,
                               ISOLATED_IO_BOARD_0_ADDR, SWITCH_2_CHAN,
                                                         isoIoSpareSwitch0);
            }

                                    /* Isolated I/O Switch 3 Request         */
            if (cameraDconGroupBits & isoIoSwitch3Bit)
            {
                dm_read( dmItems->isoIoSpareSwitch1,
                         (char *) &isoIoSpareSwitch1,
                              sizeof(isoIoSpareSwitch1), (DM_Time *) NULL);
                  ibcSwitchControl(SERIAL_CHAN, ISOLATED_IO,
                               ISOLATED_IO_BOARD_0_ADDR, SWITCH_3_CHAN,
                                                        isoIoSpareSwitch1);
            }


                                    /* Check for GF/5V Board Parameter Update*/
            ibcGf5vUpdateCheck( SERIAL_CHAN, GF5V_BOARD_ADDR,
                              &dmItems->gf5vDm, &gf5vBits, gf5vGroup );

                             /* Check for Virtual Serial Port Parameter Update*/
            ibcVspUpdateCheck( SERIAL_CHAN, SERIAL_BOARD_ADDR,
               VSP_CHAN, &dmItems->vspDm, &vspBits, vspGroup );

                                    /* Check for LPS Board Parameter Update  */
            for (lpsBoard = 0; lpsBoard < LPS_BOARDS; lpsBoard++)
                  ibcLpsUpdateCheck( SERIAL_CHAN, lpsBoardAddr[lpsBoard],
                              &dmItems->lpsDm[lpsBoard], &lpsBits[lpsBoard],
                              lpsGroup[lpsBoard] );

                                     /* Send Set Humidity Alarm Threshold cmd*/
            if ((cameraDconGroupBits & ibcCpuBits.humidityWarnThreshBit) ||
                (cameraDconGroupBits & ibcCpuBits.humidityAlarmThreshBit))
                writeIbcHumidityThresh(SERIAL_CHAN,
                              dmItems->ibcDm.humidityWarnThresh,
                              dmItems->ibcDm.humidityAlarmThresh);

                                    /* Send Set Water Alarm Threshold cmd    */
            if (cameraDconGroupBits & waterAlarmThreshBit)
                writeWaterAlarmThresh(SERIAL_CHAN,
                                      dmItems->waterAlarmThresh);
                                    /* If Reset Command request occurred     */

            if (cameraDconGroupBits & 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 !                                 */
} /* cameraDconOutTask() */


/*****************************************************************************/
/* Function    : cameraDconInTask                                            */
/* Purpose     : Camera Dcon Input Task. Wakes up periodically, read data    */
/*               from the Camera 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
cameraDconInTask(Reg cameraDconDmItems* dmItems, microIOControl *microIOCtrl)
{
    SEM_ID  wakeupSem;              /* Used by watch dog to wake up this task*/
    Int32   updates = 0;            /* Counts dm updates for rate calculation*/

                                    /* Create wakeup semaphore for provider  */
                                    /* rate control                          */
    if ((wakeupSem = semBCreate(SEM_Q_FIFO, SEM_EMPTY)) == NULL)
    {
        logMsg("Camera 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,   CAMERA_IBC_DM_PERIOD);
    initIbcLpsProvider  (&dmItems->lpsDm[0], CAMERA_IBC_DM_PERIOD);
    initIbcLpsProvider  (&dmItems->lpsDm[1], CAMERA_IBC_DM_PERIOD);

    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    */

        if ((updates % (HUMIDITY_DM_PERIOD / CAMERA_IBC_DM_PERIOD)) == 0)
            updateIbcHumidityDm( SERIAL_CHAN, dmItems->ibcDm.microHumidity );

        updateNewIbcGf5vDm( SERIAL_CHAN, GF5V_BOARD_ADDR,
                             &dmItems->gf5vDm );

        updateIbcLpsDm( SERIAL_CHAN, lpsBoardAddr[0],
                             &dmItems->lpsDm[0] );

        updateIbcLpsDm( SERIAL_CHAN, lpsBoardAddr[1],
                             &dmItems->lpsDm[1] );

        taskUnsafe();               /* task may now be deleted safely         */
                                    /* increment & range check update counter*/
            if (++updates == 10000) updates = 0;

        semTake(wakeupSem,          /* pend until sem timeout wakes us up     */
                sysClkRateGet() / ( USECS_PER_SEC / CAMERA_IBC_DM_PERIOD));
        } /* while */
    }/* FOREVER */

    semDelete(wakeupSem);           /* reclaim semaphore resource             */


                        /* 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 !                                 */
} /* cameraDConInTask() */

/******************************************************************************/
/* Function    : processCameraDconSRQ                                         */
/* Purpose     : Decode Service Request and take appropriate action           */
/* Inputs      : SRQ code, array of DM items, serial channel                  */
/* Outputs     : Returns Reset Status & many DM items are changed             */
/******************************************************************************/
    LOCAL Word
processCameraDconSRQ( Reg cameraDconDmItems* dmItems,
                      microIOControl *microIOCtrl )
{
    Word srqRequest;                /* Service Request Value                  */
    Byte buffer[SRQ_PACKET_LEN];    /* Buffer for micro communications data   */

                                    /* Block on Reading Service Request       */
    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;

      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 (processIbcGf5vSRQ(srqRequest, buffer, GF5V_BOARD_ADDR,
                    &dmItems->gf5vDm  ) != TRUE)

        if (processIbcVspSRQ(srqRequest, buffer,
                   SERIAL_BOARD_ADDR, VSP_CHAN, &dmItems->vspDm )
                   != TRUE)

        if (processIbcQuadSerSRQ(srqRequest, buffer,
                    SERIAL_BOARD_ADDR, &dmItems->quadSerDm ) != TRUE)

        printf("Camera Dcon: Unrecognized SRQ 0x%x\n", srqRequest);

        break;
    } /* switch */
    return (srqRequest);                     /* Return SRQ Received To Caller */
} /* processCameraDconSRQ() */



















