/******************************************************************************/
/* Copyright 1997 MBARI                                                       */
/******************************************************************************/
/* Summary  : Video overlay for Tiburon                                       */
/* Filename : videoOverlay1.c                                                 */
/* Author   : Janice Tarrant                                                  */
/* Project  : Tiburon                                                         */
/* Version  : Version 1.0                                                     */
/* Created  : 07/16/97                                                        */
/* Modified :                                                                 */
/* Archived :                                                                 */
/*******************************************************************************
/* Modification History :                                                     */
/* Header$
 * $Log$
 *
 */
/******************************************************************************/

#include <stdioLib.h>                   /* VxWorks standard I/O library       */
#include <mbariTypes.h>                 /* MBARI style guide type declarations*/
#include "dmvideo.h"                    /* data manager definitions           */
#include "OVtypes.h"                    /* video overlay type definitions     */
#include "dy4std.h"                     /* DY4 standard definitions           */
#include "mygraphics.h"                 /* graphics alignment definitions     */
#include "dy4driver.h"                  /* DY4 driver definitions             */
#include "Item.h"                       /* Item class definitions             */
#include "Alarm.h"                      /* Alarm class definitions            */
#include "Condition.h"                  /* Condition class definitions        */
#include "Config.h"                     /* Config class definitions           */
#include "Overlay.h"                    /* Overlay class definitions          */
#include "Video.h"                      /* Video class definitions            */
#include "videoOverlayDM.h"             /* data manager definitions           */

#define CONFIG_FILENAME 1               /* index = column number              */

    void
videoOverlayTask1(void)
{
    OV_char      *strings_a[NSTR];      /* array of strings                   */
    OV_char      zval[64];              /* to store data manager value        */
    OV_char      *Pzval = zval;
    MBool        alarmOn;               /* alarm on flag                      */
    MBool        acknowledge;           /* alarm acknowledge                  */
    MBool        startUp = TRUE;        /* overlay start flag                 */
    MBool        crosshairUp = FALSE;   /* crosshair on display flag          */
    MBool        onDisplay = FALSE;     /* overlay on display flag            */
    MBool        dmItemsExist = TRUE;   /* all data manager items exist flag  */
    DWord        conditionGroupBits;    /* condition group changes bit vector */
                                        /* alarm group changes bit vector     */
    DWord        alarmGroupBits[NUM_ALARM_GROUPS];
                                        /* alarm priority group changes bit   */
    DWord        priorityGroupBits[NUM_ALARM_GROUPS];       /* vector         */
    Nat16        alarmData;             /* alarm data                         */
    Nat16        priority;              /* alarm priority                     */
    OV_int       i_string;              /* string index                       */
    OV_int       i_item;                /* item index                         */
    OV_int       i_condition;           /* condition index                    */
    OV_int       i_group;               /* group index                        */
    OV_int       i_alarm;               /* alarm index                        */
    OV_int       i_overlay;             /* overlay index                      */
    OV_int       i_matrix;              /* matrix index                       */
    OV_int       numAlarms;             /* alarm counter                      */
    OV_int       numGroups;             /* group counter                      */
    OV_int       nb_overlays;           /* number of overlays                 */
    Int16        nb_alarms;             /* number of alarms                   */
    Errno        status;                /* data manager error code            */
    OV_float     values_a[NVAL];        /* array of values                    */
    OV_float     value;                 /* data manager value                 */
    OV_alignment alignment;             /* graphical alignment data           */
    OV_Context   alarmLink;             /* deleted alarm link                 */
    OV_Item      *p_item;               /* pointer to item                    */
    OV_Overlay   *p_overlay;            /* pointer to overlay                 */
    OV_Video     *p_video;              /* pointer to video                   */
    OV_Condition *p_condition;          /* pointer to condition               */
    OV_Alarm     *p_alarm;              /* pointer to alarm                   */
    DM_Time      startUpTime;           /* start up update time               */
    DM_Item      overlayStartDmi;       /* overlay start dm item              */
    DM_Define    dmiInit[] =            /* data manager item init values      */
    { { VIDEO_OVERLAY1_CROSSHAIR_DM, 1, DM_MBOOL, DMT_NULL, &crosshairUp },
      { NULL, 0, DM_ENDT, DMT_NULL, NULL } };

/* initialize video board and graphics                                        */
    My_ini_board(VME_770_ADDRESS1);
    My_ini_video();
    My_ini_graphics(&alignment);

/* create overlay start data manager item                                     */
    status = dm_create(VIDEO_OVERLAY1_START_DM, 1, &overlayStartDmi, DM_MBOOL,
                       1, DM_ENDT);
    checkCreate(status, VIDEO_OVERLAY1_START_DM, FALSE);
    status = dm_start_consumer(overlayStartDmi, DM_STATIC, SEM_NULL);
    checkConsumer(status, VIDEO_OVERLAY1_START_DM);
    status = dm_start_multiple(overlayStartDmi);
    gettimeofday(&startUpTime, (struct timezone *) NULL);
    status = dm_write(overlayStartDmi, (Void *) &startUp, sizeof(startUp),
                      &startUpTime);
    checkWrite(status, VIDEO_OVERLAY1_START_DM);

/* create overlay crosshair on display data manager item                      */
    status = dm_create_items(dmiInit);
    checkCreate(status, VIDEO_OVERLAY1_CROSSHAIR_DM, FALSE);

/* create the main video object                                               */
    p_video = Video_New("/usr/tiburon/config/video/overlay1.cfg");
    Video_Initialize(p_video);

    for (;;)
    {

/* check for restart of overlay                                               */
        status = dm_read(overlayStartDmi, (Void *) &startUp, sizeof(startUp),
                         ( (DM_Time *) NULL));
        if (checkRead(status, VIDEO_OVERLAY1_START_DM, FALSE) == ERROR)
        {
            logMsg("Video Overlay WARNING : could not read start flag\n");
            startUp = FALSE;
        }
        if (startUp)
        {

/* erase current display                                                      */
            if (onDisplay)
            {
                Overlay_Erase(&alignment, p_overlay);
                for (i_overlay = 0; i_overlay < p_video->nb_overlays_in_list;
                     i_overlay++)
                    if (p_video->p_overlays_list[i_overlay] != NULL)
                        Overlay_Delete(p_video->p_overlays_list[i_overlay]);
                Video_Initialize(p_video);
            }
            else
                onDisplay = TRUE;

/* read resource file                                                         */
            Video_OpenFile(p_video);
            Video_ReadHeader(p_video);
            nb_overlays = p_video->nb_overlays;

/* create overlays                                                            */
            i_matrix = 1;
            for (i_overlay = 0; i_overlay < nb_overlays; i_overlay++)
            {
                Video_ReadLine(p_video, i_matrix, i_overlay, values_a,
                               strings_a);
                p_overlay = Overlay_New(strings_a[CONFIG_FILENAME]);
                Overlay_Initialize(p_overlay);
                Video_AddOverlay(p_video, p_overlay);
            }
            Video_CloseFile(p_video);

/* initialize overlays                                                        */
            for (i_overlay = 0; i_overlay < nb_overlays; i_overlay++)
            {
                p_overlay = p_video->p_overlays_list[i_overlay];

/* load configuration file                                                    */
                Overlay_LoadConfig(p_overlay);

/* start dataManager consumer tasks for each item                             */
                Overlay_StartDmTasks(p_overlay, &dmItemsExist);

/* display all items on the screen                                            */
                Overlay_Display(&alignment, p_overlay);
            }

/* reset startup flag                                                         */
            startUp = FALSE;
            gettimeofday(&startUpTime, (struct timezone *) NULL);
            dm_write(overlayStartDmi, (Void *) &startUp, sizeof(startUp),
                     &startUpTime);
        }

/* keep looking for data manager items that did not exist on start up         */
        if (!dmItemsExist)
        {
            taskDelay( 2 * sysClkRateGet() );
            Overlay_ReStartDmTasks(p_overlay, &dmItemsExist);
        }

/* continually update overlay display                                         */
        for (i_overlay = 0; i_overlay < nb_overlays; i_overlay++)
        {
            p_overlay = p_video->p_overlays_list[i_overlay];

/* change plane according to overlay number */
            My_set_plane(i_overlay);

/* get regular item values                                                    */
            for (i_item = 0; i_item < p_overlay->nb_item_in_list; i_item++)
            {
                p_item = p_overlay->p_item_list[i_item];

                if ((p_item->dm_item != NULL) && (p_item->dm_item != NO_ITEM))
                {
                    My_get_dm_item(p_item->dm_item, p_item->dm_type,
                                   p_item->dm_size, Pzval);
                    Item_SetValue(p_item, Pzval);
                }
            }

/* get any changes in conditions for dependent items                          */
            conditionGroupBits =
                dm_get_group_changes(p_overlay->conditionGroup);
            for (i_condition = 0;
                 i_condition < p_overlay->nb_conditions_in_list; i_condition++)
            {
                p_condition = p_overlay->p_condition_list[i_condition];
                if (conditionGroupBits & p_condition->idBit)
                    Condition_Read(p_condition);
            }

/* get dependent item values                                                  */
           for (i_item = 0; i_item < p_overlay->nb_dep_items_in_list; i_item++)
           {
                p_item = p_overlay->p_depItem_list[i_item]->p_item;

                if (*(p_overlay->p_depItem_list[i_item]->on_display))
                    if ((p_item->dm_item != NULL) &&
                        (p_item->dm_item != NO_ITEM))
                    {
                        My_get_dm_item(p_item->dm_item, p_item->dm_type,
                                       p_item->dm_size, Pzval);
                        Item_SetValue(p_item, Pzval);
                    }
            }

/* get changes in alarm items and priorities                                  */
            for (i_group = 0; i_group < p_overlay->nb_alarm_groups; i_group++)
            {
                alarmGroupBits[i_group] =
                    dm_get_group_changes(p_overlay->alarmGroup[i_group]);
                priorityGroupBits[i_group] =
                    dm_get_group_changes(p_overlay->priorityGroup[i_group]);
            }
            numAlarms = 0;
            numGroups = 0;
            for (i_alarm = 0; i_alarm < p_overlay->nb_alarms_in_list; i_alarm++)
            {
                p_alarm = p_overlay->p_alarm_list[i_alarm];
                numAlarms++;
                if (numAlarms > GROUP_MAX)
                {
                    numAlarms = 1;
                    numGroups++;
                }

/* get alarm priority and acknowledgement changes                             */
                if (priorityGroupBits[numGroups] & p_alarm->priorityBit)
                {
                    dm_read(p_alarm->priority, (Void *) &alarmData,
                            sizeof(alarmData), (DM_Time *) NULL);
                    priority = 0xFF & alarmData;
                    acknowledge = alarmData >> 8;
/*
printf("alarm %s data %d pri %d ack %d\n", p_alarm->p_item->dm_name, alarmData,
       priority, acknowledge);
*/
                    if (priority == 1)
                        p_alarm->on_display = TRUE;
                    else
                        p_alarm->on_display = FALSE;
                    if (acknowledge)
                    {
                        if (p_overlay->alarm != NULL)
                        {
/*
printf("delete alarm (ack) %d %s\n", p_overlay->nb_alarms_linked,
       p_alarm->p_item->dm_name + strlen(ALARM_PREFIX));
*/
                        p_overlay->alarm =
                            Delete_AlarmLink(&alarmLink, p_overlay->alarm,
                                             &p_overlay->nb_alarms_linked,
                                             p_alarm->p_item->dm_name+
                                             strlen(ALARM_PREFIX));
                        }
                    }
                }  /* if priorityGroupBits */

/* get alarm value changes                                                    */
                if (alarmGroupBits[numGroups] & p_alarm->idBit)
                {
                    alarmOn = My_get_dm_alarm_item(p_alarm->p_item->dm_item,
                                                   p_alarm->p_item->type);
                    if (alarmOn && p_alarm->on_display)
                    {
                        nb_alarms = p_overlay->nb_alarms_linked;
                                                /* add alarm to list          */
                        if (nb_alarms < MAX_ALARMS_ON_DISPLAY)
                            p_overlay->alarmsUp[nb_alarms].name =
                                p_alarm->p_item->dm_name + strlen(ALARM_PREFIX);
/*
printf("alarm %d %s\n", p_overlay->nb_alarms_linked,
       p_alarm->p_item->dm_name + strlen(ALARM_PREFIX));
*/
                        p_overlay->alarm =
                            Add_AlarmLink(p_overlay->alarm,
                                          &p_overlay->nb_alarms_linked,
                                          p_alarm->p_item);

                        nb_alarms = 0;
                        Alarm_Display(&alignment, p_overlay->alarm,
                                      p_overlay->alarmsUp, &nb_alarms);
                    }
                    if ((!alarmOn) && p_alarm->on_display)
                    {                           /* delete alarm from list     */
                        if (p_overlay->alarm != NULL)
                        {
/*
printf("delete alarm (off) %s\n",
       p_alarm->p_item->dm_name + strlen(ALARM_PREFIX));
*/
                            p_overlay->alarm =
                                Delete_AlarmLink(&alarmLink, p_overlay->alarm,
                                                 &p_overlay->nb_alarms_linked,
                                                 p_alarm->p_item->dm_name+
                                                 strlen(ALARM_PREFIX));
                        }
                    }
                }  /* if alarmGroupBits */

            }  /* for i_alarm */

/* display new values to overlay */
            Overlay_Refresh(&alarmLink, &alignment, p_overlay);

/* delay corresponding to data refresh period*/
            My_dm_wait(p_overlay->p_config->refresh_period);

        } /* endfor i_overlay */

    } /* endforever */

    return;

}


