The Monitor Window - create_monitor

Cogent Tools Demo and Tutorials: Version 4.0
Prev | Chapter 8. Photon Functions (in `phsimple.g`) | Next

# 8.2. The Monitor Window - `create_monitor`

       /*--------------------------------------------------------------------
        * Function:    create_monitor
        * Returns:     doesn't return
        * Description: Creates the Monitor window.
        *------------------------------------------------------------------*/
       function create_monitor ()
       {
         local wfile, window, monitor_win, slidesp, progmv, progpv;
         local slideauto, slidedp, numkp, numki, numkd, numprop, numint;
         local butam, butgood, butpoor, butosc, butout, butx;

         if (_os_ == "QNX4")
           wfile = PhabReadWidgetFile("phmonitorwin/wgt/Ptmonitor.wgtw");
         else
           wfile = PhabReadWidgetFile("ph2monitorwin/wgt/Ptmonitor.wgtw");

All of the windows in this demo and its tutorials were created in the Photon Application Builder ("PhAB" in QNX 4, the "Builder" in QNX 6). These windows and all their child widgets get imported into Gamma using either `PhabReadWidgetFile` or `PhabAttachWidgets`. The Monitor window discussed here gets imported using the `PhabReadWidgetFile` function. Since there are two widget files (one in Photon 1.14 for QNX 4, the other in Photon 2 for QNX 6), we have to choose the appropriate one using an `if` statement.

Now that we have the widget file, we can create all the window's child widgets in Gamma/Photon using the `PhabCreateWidgets` function. Then we can look up and name any individual widget, using Gamma/Photon's `PhabLookupWidget` function.

| The hash character (`#`) is a quote operator which protects a symbol from evaluation. We need to use this quote operator because the function takes the symbol as its argument, not the value of the symbol.

         window = PhabCreateWidgets(wfile, nil, nil);
         monitor_win = PhabLookupWidget(window, #Ptmonitor, nil);
         slidesp = PhabLookupWidget(window, #PtSliderSP, nil);
         slideclr = PhabLookupWidget(window, #RtProgressColor, nil);
         numfreq = PhabLookupWidget(window, #PtNum1, nil);
         numkp = PhabLookupWidget(window, #PtNum2, nil);
         numki = PhabLookupWidget(window, #PtNum3, nil);
         numkd = PhabLookupWidget(window, #PtNum4, nil);
         numprop = PhabLookupWidget(window, #PtNum5, nil);
         numint = PhabLookupWidget(window, #PtNum6, nil);

         butgood = PhabLookupWidget(window, #PtToggleGood, nil);
         butpoor = PhabLookupWidget(window, #PtTogglePoor, nil);
         butosc = PhabLookupWidget(window, #PtToggleOscillating, nil);
         butout = PhabLookupWidget(window, #PtToggleOOC, nil);
         butam = PhabLookupWidget(window, #PtOnOffButtonAutomode, nil);
         labprop = PhabLookupWidget(window, #PtLabelPropVal, nil);
         progmv = PhabLookupWidget(window, #ProgressMV, nil);
         progpv = PhabLookupWidget(window, #ProgressPV, nil);
         trend1 = PhabLookupWidget(window, #Trend1, nil);

         slidesp.gauge_value = read_point(#SP_001);
         slideclr.gauge_value = read_point(#SP_001);
         progmv.gauge_value = read_point(#MV_001);
         progpv.gauge_value = read_point(#PV_001);
         butam.onoff_state = read_point(#AUTO_001);
         numfreq.numeric_value = read_point(#FREQ_001);

         numeric_assign(numkp, numki, numkd, numprop, numint);

Once the widgets are named, they can be manipulated. Here we assign values to the slider and progress bars. (The slider was created using two widgets: a transparent slider, and a progress bar. Each of these widgets needs to be assigned a value.) The values being assigned are the values of corresponding points in the Cascade DataHub, collected by using the Gamma `read_point` function. The `numeric_assign` function was created to convert values in QNX 6 from hundredths to integers.

These assignments give the widgets an initial value, but the widgets also need to be updated every time the corresponding point in the Cascade DataHub changes its value. For this we use the Gamma functions `add_exception_function` and `add_echo_function`. These function lets you specify another function that will be called whenever the Cascade DataHub point changes value. In this case, our function is simply an assignment that sets the value of a widget's `.onoff_state` or `.gauge_value`.

         add_exception_function(#AUTO_001, `(@butam).onoff_state = AUTO_001);
         add_exception_function(#SP_001, `(@slideclr).gauge_value = SP_001);
         add_echo_function(#SP_001, `(@slideclr).gauge_value = SP_001);
         add_exception_function(#MV_001, `(@progmv).gauge_value = MV_001);
         add_exception_function(#PV_001, `(@progpv).gauge_value = PV_001);

| Notice the use of the quote operators ``` and `@` in the above function calls. The ``` operator prevents the assignment from taking place when the code is being read, but the `@` operator allows the name of the widget to be evaluated, so that its instance variable can be changed. The `#` operator is used in the first argument of the function to protect the Cascade DataHub point name from evaluation, but is not needed when making the assignment because there we want the value of the point.

         slider_callback (slidesp, #SP_001);

         num_callback (numfreq, #FREQ_001);
         num_callback (numkp, #PID1_Kp);
         num_callback (numki, #PID1_Ki);
         num_callback (numkd, #PID1_Kd);
         num_callback (numprop, #PROP_001);
         num_callback (numint, #INT_001);

In addition to getting data from the Cascade DataHub, we also need to write data back to it. To get values from the widgets into the Cascade DataHub, we use callbacks. The `slider_callback` and `num_callback` functions (above) assign callbacks and add exception functions for the slider and all the spin buttons. The radio buttons get their callbacks attached individually (below). Their callbacks activate the `change_settings` function, which changes the settings of the spin buttons, as well as writing new values to the Cascade DataHub.

         PtAttachCallback(butgood, Pt_CB_ACTIVATE,
                          `change_settings(t, @numfreq, 4, @numkp, .05,
                                           @numki, .45, @numkd, .05,
                                           @numprop, .7, @numint, 1.0,
                                           3.8, @butam));

         PtAttachCallback(butpoor, Pt_CB_ACTIVATE,
                          `change_settings(t, @numfreq, 10, @numkp, .05,
                                           @numki, .70, @numkd, .05,
                                           @numprop, .7, @numint, 5.0,
                                           3.8, @butam));

         PtAttachCallback(butosc, Pt_CB_ACTIVATE,
                          `change_settings(nil, @numfreq, 10, @numkp, .05,
                                           @numki, 1.37, @numkd, .05,
                                           @numprop, .7, @numint, .54,
                                           3.8, @butam));

         PtAttachCallback(butout, Pt_CB_ACTIVATE,
                          `change_settings(nil, @numfreq, 10, @numkp, .05,
                                           @numki, .45, @numkd, 1.00,
                                           @numprop, .7, @numint, .54,
                                           3.8, @butam));

         PtAttachCallback(butam, Pt_CB_ONOFF_NEW_VALUE, `toggle_sym(#AUTO_001));

         butx = PhabLookupWidget(window, #Ptxbut, nil);
         PtAttachCallback(butx, Pt_CB_ACTIVATE, #exit_program(-1));

The last noteworthy task is to set up the trend widget, using the Gamma `array` function, and then animate it using the `accumulate_trends` and `update_trends` functions.

         /* Set up the trend widget.  We must set the trend resources in the
          * order below to ensure that the trend widget knows what to do with
          * the line colors.  We want 3 traces, in the same colors that the
          * designer set when creating the slider and progress bars in the
          * Photon App Builder.
          */
         trend1.trend_count = 3;
         trend1.trend_color_list = array (slideclr.progress_bar_color,
                                          progmv.progress_bar_color,
                                          progpv.progress_bar_color);
         trend1.trend_attributes = array (1, 2, 3);

         /* Animate trends every tenth of a second.  The trend data arrays are
          * stored in the property lists of the associated database variables.
          * We can accumulate trend data faster than we display it by changing
          * the rates of accumulation and update.  It does not make sense to display
          * trend data faster than about 27Hz, because the eye cannot distinguish
          * anything beyond that from smooth motion.  In reality, 10Hz is plenty.
          */
         every (0.1, #accumulate_trends (#SP_001, #MV_001, #PV_001));
         every (0.1, #update_trends (trend1, #SP_001, #MV_001, #PV_001));

         monitor_win.SetPos(20, 250);
         PtRealizeWidget(monitor_win);

         //  PtMainLoop();
         while(t) next_event();

       }

Prev | Home | Next
Photon Functions (in `phsimple.g`) | Up | Button Functions - `toggle_sym`, `change_settings`

Copyright 1995-2002 by Cogent Real-Time Systems, Inc.