{ *************************************************************************** }
MODULE mod_handle_monit_pool ;
{  Created  10-JUL-1989 MICHIGAN STATE UNIVERSITY, TRIGGER CONTROL SOFTWARE   }
{  Modified 26-OCT-1990 move load sbsc request closer to spy capture          }
{  Modified 26-OCT-1990 back to reading elapsed beam X from data block        }
{  Renamed   4-FEB-1991 mod_handle_shared_area -> mod_handle_monit_pool       }
{  Move     25-MAR-1991 to mpool_server.pas code to read Mpool,               } 
{  Move     25-MAR-1991 to mpool_data.typ declaration of area and sections    }
{  Modif    25-MAR-1991 use find_area_lock                                    }
{  Modif     5-APR-1991 improve transfer of refset                            }
{  Modif    10-APR-1991 add trouble warning bits                              }
{  Modif    20-APR-1992 add to monit pool 68k states, per bunch and fe busy   }
{  Modif    27-APR-1992 add to monit pool level 1.5 scalers                   }
{  Modif     2-SEP-1992 add new per bunch scalers                             }
{  Modif    20-OCT-1992 delete area object before quitting                    }
{  Modif     3-NOV-1992 fill foreign scaler snapshot                          }
{  Modif    19-FEB-1993 add exception handler                                 }
{  Modif     7-APR-1993 replace direct reset of COMINT by an init_auxi file   }
{  Modif    27-JAN-1994 Dual COMINT Pilot/Assitant with Spy splicing          }
{ *************************************************************************** }
INCLUDE
  mod_common_global_flags,
  mod_common_soft_conn,
  mod_handle_console,
  mod_handle_tracing,
  mod_handle_shared_area,
  mod_handle_mail,
  mod_def_hardware_tables,
  mod_def_physics_tables,
  mod_handle_scalers,
  mod_handle_sptrg,
  mod_init_auxi,
  mod_common_hard_io,                 {from the TRICS hardware IO library     }
  mod_tcs_io_spy_handling,            {from the TRICS hardware IO library     }
  mod_tcs_io_twb_handling,            {from the TRICS hardware IO library     }
  mod_io_allocation_handling,         {from the TRICS hardware IO library     }
  mod_coor_global_execute,
  $MUTEX,                             {from ELN$:RTLOBJECT.OLB                }
  $KERNEL ;                           {from ELN$:RTLOBJECT.OLB                }
{ *************************************************************************** }
EXPORT
            
  proc_rfrsh_mpool,         {PROCESS variable: refresh monit pool task        }
  set_mpool_rate,           {PROCEDURE change monitoring pool refresh rate    }
  start_rfrsh_mpool_proc,   {PROCEDURE create process refreshing monit pool   }
  delete_rfrsh_mpool_proc ; {PROCEDURE delete process refreshing monit pool   }

{ *************************************************************************** }
IMPORT

  framework_state_type,               {from module MOD_COMMON_GLOBAL_FLAGS    }
 {running,}paused,                    {from module MOD_COMMON_GLOBAL_FLAGS    }
  framework_state,                    {from module MOD_COMMON_GLOBAL_FLAGS    }
  status_type, ok, {already_done,} io_failure, not_found,
                                      {from module MOD_COMMON_GLOBAL_FLAGS    }
  boot_directory_name,                {from module MOD_COMMON_GLOBAL_FLAGS    }

  disp_not_busy,                      {from module MOD_COMMON_SOFT_CONN       }

  lock_console,                       {from module MOD_HANDLE_CONSOLE         }
  unlock_console,                     {from module MOD_HANDLE_CONSOLE         }
  esc, save_cursor, restore_cursor,   {from module MOD_HANDLE_CONSOLE         }
  display_console, goxy,              {from module MOD_HANDLE_CONSOLE         }
  inline_open_left_eye,               {from module MOD_HANDLE_CONSOLE         }
  inline_close_left_eye,              {from module MOD_HANDLE_CONSOLE         }
  inline_open_right_eye,              {from module MOD_HANDLE_CONSOLE         }
  inline_close_right_eye,             {from module MOD_HANDLE_CONSOLE         }
  display_global_rate,                {from module MOD_HANDLE_CONSOLE         }

  handle_trc_sys,                     {from module MOD_HANDLE_TRACING         }
  handle_trc_sta,                     {from module MOD_HANDLE_TRACING         }
  handle_trc_err,                     {from module MOD_HANDLE_TRACING         }
  inline_time_now,                    {from module MOD_HANDLE_TRACING         }
  set_trc_exc_mode,                   {from module MOD_HANDLE_TRACING         }
  handle_exception,                   {from module MOD_HANDLE_TRACING         }

  find_area_lock,                     {from module MOD_HANDLE_SHARED_AREA     }

  send_mail,                          {from module MOD_HANDLE_MAIL            }

  sptrg_per_fstd, st_0_3, st_28_31,   {from module MOD_DEF_HARDWARE_TABLES    }
  sbscdis, sbscaofired,               {from module MOD_DEF_HARDWARE_TABLES    }
  sbscstdig, sbscfebz,                {from module MOD_DEF_HARDWARE_TABLES    }
  eta_polarity,                       {from module MOD_DEF_HARDWARE_TABLES    }
  pos_e, neg_e,                       {from module MOD_DEF_HARDWARE_TABLES    }
  eta_magnitude,                      {from module MOD_DEF_HARDWARE_TABLES    }
  magn_eta_per_fe_cell,               {from module MOD_DEF_HARDWARE_TABLES    }
  e_1_4, e_17_20,                     {from module MOD_DEF_HARDWARE_TABLES    }
  phi_per_fe_half_cell,               {from module MOD_DEF_HARDWARE_TABLES    }
  p_1_8, p_25_32,                     {from module MOD_DEF_HARDWARE_TABLES    }
  EMEtZ0, HDEtZ0,                     {from module MOD_DEF_HARDWARE_TABLES    }
  e_1, e_20,                          {from module MOD_DEF_HARDWARE_TABLES    }
  phi_value,                          {from module MOD_DEF_HARDWARE_TABLES    }
  p_1, p_16, p_32,                    {from module MOD_DEF_HARDWARE_TABLES    }
 {threshold_reference_set_type,}      {from module MOD_DEF_HARDWARE_TABLES    }
  EMEt_ref, HDEt_veto, TOTEt_ref,     {from module MOD_DEF_HARDWARE_TABLES    }
 {threshold_reference_set_number,}    {from module MOD_DEF_HARDWARE_TABLES    }
  ref_0, ref_1, ref_2, ref_3,         {from module MOD_DEF_HARDWARE_TABLES    }
  ref_4, ref_5, ref_6, ref_7,         {from module MOD_DEF_HARDWARE_TABLES    }
  EMEt_cmp, TOTEt_cmp,                {from module MOD_DEF_HARDWARE_TABLES    }
  mtgtwb,                             {from module MOD_DEF_HARDWARE_TABLES    }
  sbscL15_cnf_rej,                    {from module MOD_DEF_HARDWARE_TABLES    }
  sbscL15_cyc_skp,                    {from module MOD_DEF_HARDWARE_TABLES    }
  sbscL15_dead_to,                    {from module MOD_DEF_HARDWARE_TABLES    }


  spec_trig,                          {from module MOD_DEF_PHYSICS_TABLES     }
  geographic_section,                 {from module MOD_DEF_PHYSICS_TABLES     }
  sptrg,                              {from module MOD_DEF_PHYSICS_TABLES     }
  geosec,                             {from module MOD_DEF_PHYSICS_TABLES     }
  cal_trig_tower,                     {from module MOD_DEF_PHYSICS_TABLES     }
  trgtwr,                             {from module MOD_DEF_PHYSICS_TABLES     }
  cal_large_tile,                     {from module MOD_DEF_PHYSICS_TABLES     }
  LgTile,                             {from module MOD_DEF_PHYSICS_TABLES     }
  energy_threshold,                   {from module MOD_DEF_PHYSICS_TABLES     }
  count_threshold,                    {from module MOD_DEF_PHYSICS_TABLES     }
  firstetasign, lastetasign,          {from module MOD_DEF_PHYSICS_TABLES     }
  firstetamagn, lastetamagn,          {from module MOD_DEF_PHYSICS_TABLES     }
  firstphival, lastphival,            {from module MOD_DEF_PHYSICS_TABLES     }
  force_db_mode,                      {from module MOD_DEF_PHYSICS_TABLES     }

  load_sbscalers,                     {from module MOD_HANDLE_SCALERS         }
  read_sbscalers,                     {from module MOD_HANDLE_SCALERS         }

  force_datablock,                    {from module MOD_HANDLE_SPTRG           }

  init_auxi,                          {from module MOD_INIT_AUXI              }

 {p_dblock_low,{p_dblock_high,}       {from module MOD_COMMON_HARD_IO         }
  array_data_block_spy,               {from module MOD_COMMON_HARD_IO         }
  cbus_param_list,                    {from module MOD_COMMON_HARD_IO         }
  pilot, assist,                      {from module MOD_COMMON_HARD_IO         }

  proced_tcs_request_spy,             {from module MOD_TCS_IO_SPY_HANDLING    }
  proced_tcs_read_db_spy,             {from module MOD_TCS_IO_SPY_HANDLING    }

  proced_tcs_read_twb,                {from module MOD_TCS_IO_TWB_HANDLING    }

  deallocate_trigger,                 {from module MOD_IO_ALLOCATION_HADLLING }

  AREA_LOCK_VARIABLE,                 {from module $MUTEX                     }
  ELN$LOCK_AREA,                      {from module $MUTEX                     }
  ELN$UNLOCK_AREA,                    {from module $MUTEX                     }
  KER$NAME_OBJECT ;                   {from module $KERNEL                    }
{ *************************************************************************** }
CONST

  one_second = 10000000 ;

  %INCLUDE 'SITE_DEPENDENT.CST/LIST'

TYPE

  byte = [BYTE] 0..255 ;
  word = [WORD] 0..65535 ;

{ *** full data block as seen in VMS (level 2, trigger monitoring,...)  ***** }
  %INCLUDE 'TABLE_DBLOCK_967.TYP/LIST'

{ *** detailed Pilot and Assitant COMINT Spy structure                  ***** }
  %INCLUDE 'TABLE_DBLOCK_SPY.TYP/LIST'

{ *** description of shared monitoring data and transferred data sections     }
  %INCLUDE 'MPOOL_DATA.TYP/LIST'

VAR

  name_mpool_proc    : NAME ;
  proc_rfrsh_mpool   : PROCESS ;

  mpool_obj          : AREA ;
  mpool_rec          :^monitoring_data ;

  refresh_interval   : LARGE_INTEGER ;
  rfrsh_mpool_active : BOOLEAN ;

{ *************************************************************************** }
{ *************************************************************************** }
PROCESS_BLOCK block_rfrsh_mpool ;

VAR

  sha_status    : INTEGER ;

  dblock_pilot  :^data_block_spy_pilot ;
  dblock_assist :^data_block_spy_assist ;
  monitpar      :^cbus_param_list ;

  sptrgnum      : INTEGER ;
  gsectnum      : INTEGER ;

  spy_status : status_type ;
  spy_status_pilot  : status_type ;
  spy_status_assist : status_type ;
  spy_state     : spy_state_type ;
  loadsbsc_status : status_type ;
  sbscloaded    : BOOLEAN ;

  spy_snap_time : LARGE_INTEGER ;
  next_refresh_abs_time : LARGE_INTEGER ;
  stale_start_time : LARGE_INTEGER := 0 ;
  reset_threshold  : LARGE_INTEGER ;
  time_now         : LARGE_INTEGER ;
  reset_status     : status_type ;

  delta_st_dig  : large_int_by_long ;
  delta_transf  : large_int_by_long ;
  delta_time    : large_int_by_long ;

  p_anytype     :^ANYTYPE ;

BEGIN

  ESTABLISH ( exchand_mpool_server ) ;

  rfrsh_mpool_active := TRUE ;

  send_mail ( SUBJECT := ' Start Refresh Monit Pool,'
                       + ' PROMs=' 
                       + CONVERT(STRING, SIZE(comint_prom_pilot) DIV 2 ) 
                       + '/' 
                       + CONVERT(STRING, SIZE(comint_prom_assist) DIV 2 ) 
                       + ';967=' 
                       + CONVERT(STRING, SIZE(data_block_967) DIV 2 ) 
                       + ' Items ' ) ;

  NEW ( dblock_pilot ) ;
  NEW ( dblock_assist ) ;
  NEW ( monitpar ) ;

  inline_open_right_eye ;  inline_open_left_eye ;

  find_area_lock ( CALLER := 'TRICS',
                AREA_NAME := mpool_area_name,
              AREA_OBJECT := mpool_obj,
             AREA_POINTER := mpool_rec,
                AREA_SIZE := SIZE(mpool_rec^),
                   STATUS := sha_status ) ;
  IF ( sha_status <> 1 ) THEN GOTO quit_refresh_mpool ;

  inline_lock_mpool ;

   {initialize by pieces because of size limitation of the function ZERO}
    mpool_rec^.status   := ZERO ; 
    mpool_rec^.twb      := ZERO ;
    mpool_rec^.dblock   := ZERO ; 
    mpool_rec^.sptrg    := ZERO ; 
    mpool_rec^.gsect    := ZERO ;
    mpool_rec^.current  := ZERO ;
    mpool_rec^.previous := ZERO ;
    mpool_rec^.twr      := ZERO ;
    mpool_rec^.refset   := ZERO ;
    mpool_rec^.thresh   := ZERO ;

    mpool_rec^.status.spy := stale ;

  inline_unlock_mpool ;

 {convert the constants}
  refresh_interval := - TIME_VALUE ( mpool_refresh_interval ) ;
  reset_threshold  := - TIME_VALUE ( reset_comint_threshold ) ;
  GET_TIME ( next_refresh_abs_time ) ;

REPEAT {start regular refresh of the monitoring pool}

 { *** request a copy of the next data block                              *** }
  proced_tcs_request_spy ( STATUS := spy_status ) ;
  IF ( spy_status = io_failure ) THEN GOTO quit_refresh_mpool ;

 { *** wait for a data block to be built for a real acquisition event     *** }
  proced_tcs_read_db_spy ( DBSPY := ADDRESS(dblock_pilot^.word), 
                          COMINT := Pilot,
                        MAX_WAIT := -(refresh_interval - one_second), { 4 s }
                       SNAP_TIME := spy_snap_time,
                          STATUS := spy_status_pilot ) ;

  proced_tcs_read_db_spy ( DBSPY := ADDRESS(dblock_assist^.word), 
                          COMINT := Assist, 
                        MAX_WAIT := 0, {assistant should already have one}
                          STATUS := spy_status_assist ) ;


 { *** if the acquisition is not collecting events, try forcing your own  *** }
  IF ( spy_status_pilot = not_found ) 
  THEN IF ( force_db_mode = TRUE ) 
  THEN BEGIN { we will have to force our own datablock }

    force_datablock ( TAGEXT := 'mpool%', IOPAR := monitpar ) ;
      
    proced_tcs_read_db_spy ( DBSPY := ADDRESS(dblock_pilot^.word), 
                            COMINT := Pilot,
                            REPORT := FALSE, 
                          MAX_WAIT := -100000, { 10 ms, data block being built }
                         SNAP_TIME := spy_snap_time,
                            STATUS := spy_status_pilot ) ;

    proced_tcs_read_db_spy ( DBSPY := ADDRESS(dblock_assist^.word), 
                            COMINT := Assist, 
                            REPORT := FALSE, 
                          MAX_WAIT := 0, {assistant should already have one}
                            STATUS := spy_status_assist ) ;
  END ;
    
 { *** latch all SBSC cards, with a somewhat fixed delay from snap_time  *** }
  load_sbscalers ( IOPAR := monitpar, STATUS := loadsbsc_status ) ;


 { *** Reset the fresh/stale flip-flop, and reset COMINT card if needed  *** }
  IF ( ( spy_status_pilot = ok ) AND ( spy_status_assist = ok ) ) 

  THEN BEGIN {ok, we caught a regular data block or forced one}

    IF ( spy_state = stale )
    THEN handle_trc_sys ( TAG := 'MPL/FRH%',
                      MESSAGE := ' Start Getting Fresh Data Blocks @ '
                               + inline_time_now ) ;
    spy_state := fresh ;

    stale_start_time := 0 ;

  END
  ELSE BEGIN {we couldn't even force a data block}

    IF ( spy_status_pilot = ok ) 
    THEN handle_trc_err ( TAG := 'MPL/STL%',
                      MESSAGE := ' Pilot captured Spy, but not Assistant' ) ;

    IF ( spy_status_assist = ok ) 
    THEN handle_trc_err ( TAG := 'MPL/STL%',
                      MESSAGE := ' Assistant captured Spy, but not Pilot' ) ;

    IF ( spy_state = fresh )
    THEN handle_trc_sys ( TAG := 'MPL/STL%',
                      MESSAGE := ' Stop  Getting Fresh Data Blocks @ '
                               + inline_time_now ) ;
    spy_state := stale ;

   {see if we should start worrying about not getting data blocks}
    IF ( ( framework_state = paused ) OR ( force_db_mode = FALSE ) )
    THEN stale_start_time := 0 
    ELSE IF ( stale_start_time = 0 ) THEN GET_TIME ( stale_start_time ) ;    

   {see for how long we have been missing data blocks... and maybe kick COMINT}
    IF ( stale_start_time <> 0 )
    THEN BEGIN
      GET_TIME ( time_now ) ;
      IF ( ( time_now - stale_start_time ) > reset_threshold ) 
      THEN BEGIN
        {steal the IO allocation if necessary }
        deallocate_trigger ( TAGEXT := 'mpool%' ) ;
        { *** reset COMINT card *** }
        { for flexibility we use a message command file (init_auxi),   }
        { but first grab the dispatcher-not-busy semaphore             }
        { to prevent mutual data corruption with dispatcher            }
        WAIT_ANY (disp_not_busy) ;
        init_auxi ( TAGEXT := 'mpool%', 
                  FILENAME := boot_directory_name + reset_directives_file,
                    STATUS := reset_status ) ;
        SIGNAL (disp_not_busy) ;

        IF ( reset_status <> ok ) 
        THEN send_mail ( SUBJECT := ' Error during Reset COMINT file ' ) 
        ELSE send_mail ( SUBJECT := ' TRICS has reset COMINT ' ) ;

        stale_start_time := time_now ; {it should be fixed, but wait again}

      END ;
    END ;

  END ;

 { *** The arrival of data block is somewhat irregular,                  *** }
 { *** but the refreshing of the pool is brought to a constant time      *** }
  inline_open_right_eye ;

   next_refresh_abs_time := next_refresh_abs_time + refresh_interval ; 

   GET_TIME ( time_now ) ;
   IF ( time_now > next_refresh_abs_time ) 
   THEN next_refresh_abs_time := time_now       { prevent catch up race }
   ELSE WAIT_ANY ( TIME := next_refresh_abs_time ) ;

  inline_close_right_eye ;

 {------------------}
  inline_lock_mpool ;
 {------------------}

   { *** fill status section                                               *** }
    mpool_rec^.status.spy := spy_state ;
    mpool_rec^.status.framework := framework_state ;

   { *** fill programming sections                                         *** }
    FOR sptrgnum := firstsptrg TO lastsptrg
    DO mpool_rec^.sptrg[sptrgnum] := sptrg[sptrgnum]^ ;

    FOR gsectnum := firstgeosec TO lastgeosec
    DO mpool_rec^.gsect[gsectnum] := geosec[gsectnum]^ ;

    copy_twr_and_refset_programming ( MPOOL_TWR := ADDRESS(mpool_rec^.twr),
                                   MPOOL_REFSET := ADDRESS(mpool_rec^.refset) );

    mpool_rec^.thresh.gl_energy::STRING( SIZE(energy_threshold) ) 
            := energy_threshold::STRING( SIZE(energy_threshold) ) ;
    mpool_rec^.thresh.gl_count::STRING( SIZE(count_threshold) ) 
            := count_threshold::STRING( SIZE(count_threshold) ) ;

   { *** save previous snapshot of scalers for differences and rates       *** }
    mpool_rec^.previous := mpool_rec^.current ;

   {remember current snapshot time}
    mpool_rec^.current.time := spy_snap_time ;


   { *** fill data block section                                           *** }
    IF ( spy_state = fresh )

    THEN BEGIN {only need to refresh if this is a new data block}

      {copy the data block, taking care of alignment between spy and 967}
      {27-JAN-1994 splice Pilot and assistant contributions back together}
        {obsolete p_anytype := ADDRESS( dblock^.word[p_dblock_low+1] ) ;}
        {obsolete mpool_rec^.dblock := p_anytype^::data_block_967 ; }

      mpool_rec^.dblock.fw_current   := dblock_assist^.content.fw_current ;
      mpool_rec^.dblock.ct_current   := dblock_assist^.content.ct_current ;
      mpool_rec^.dblock.adc_current  := dblock_pilot^.content.adc_current ;
      mpool_rec^.dblock.fw_previous  := dblock_assist^.content.fw_previous ;
      mpool_rec^.dblock.ct_previous  := dblock_assist^.content.ct_previous ;
      mpool_rec^.dblock.adc_previous := dblock_pilot^.content.adc_previous ;
      mpool_rec^.dblock.pattern      := dblock_pilot^.content.pattern ;
      mpool_rec^.dblock.trig_prog    := dblock_assist^.content.trig_prog ;
      mpool_rec^.dblock.lt_pattern   := dblock_assist^.content.lt_pattern ; 
      mpool_rec^.dblock.level15      := dblock_assist^.content.level15 ; 
      mpool_rec^.dblock.level1_scl   := dblock_assist^.content.level1_scl ; 
      mpool_rec^.dblock.foreign      := dblock_assist^.content.foreign ; 

      {now remove Tier#3 energy offsets}
      fix_dblock_energy ( mpool_rec^.dblock.ct_current.glo_EMEt ) ;
      fix_dblock_energy ( mpool_rec^.dblock.ct_current.glo_HDEt ) ;
      fix_dblock_energy ( mpool_rec^.dblock.ct_current.glo_EML2 ) ;
      fix_dblock_energy ( mpool_rec^.dblock.ct_current.glo_HDL2 ) ;
      fix_dblock_energy ( mpool_rec^.dblock.ct_previous.glo_EMEt ) ;
      fix_dblock_energy ( mpool_rec^.dblock.ct_previous.glo_HDEt ) ;
      fix_dblock_energy ( mpool_rec^.dblock.ct_previous.glo_EML2 ) ;
      fix_dblock_energy ( mpool_rec^.dblock.ct_previous.glo_HDL2 ) ;

     {take current snapshot of scalers from data block}
      extract_needed_DBSC_counts ( DBLOCK := ADDRESS( mpool_rec^.dblock ),
                                 SNAPSHOT := ADDRESS( mpool_rec^.current ) ) ;

    END ;


   { *** fill SBSC information                                             *** }

   {read andor fired scalers, spread into target structure ordered by sptrg}
   {read and reorder veto scalers in increasing bit number of FSTD enable mask}
    read_sptrg_SBSC ( PARAM := monitpar,
                   SNAPSHOT := ADDRESS( mpool_rec^.current ) ) ;

   {Extract Beam crossing count at the time the SBSCs were loaded}
    mpool_rec^.current.vetoxcnt
               := mpool_rec^.current.sptrgcnt[firstsptrg].stvetos[7]::INTEGER ;

   {read start digitization scalers}
    read_SBSCalers ( TAGEXT := 'mpool%',
                       CARD := ADDRESS(sbscstdig),
                   REGISTER := ADDRESS(sbscstdig.datareg),
                     LOADED := TRUE,
                    SCALERS := ADDRESS(mpool_rec^.current.strtdigtz), 
                      IOPAR := monitpar ) ;

   {read front-end busy scalers}
    read_SBSCalers ( TAGEXT := 'mpool%',
                       CARD := ADDRESS(sbscfebz),
                   REGISTER := ADDRESS(sbscfebz.datareg),
                     LOADED := TRUE,
                    SCALERS := ADDRESS(mpool_rec^.current.fendbusy),
                      IOPAR := monitpar ) ;

   { *** read Trouble Warning Bits                                         *** }
    Read_Trouble_Warning_Bits ( PARAM := monitpar,
                                  TWB := mpool_rec^.twb ) ;


   { *** the monitoring information is now refreshed                       *** }

   {prepare variables for trigger rate in upper box of console screen}
    delta_St_Dig::LARGE_INTEGER := mpool_rec^.current.stdigcnt::LARGE_INTEGER 
                                 - mpool_rec^.previous.stdigcnt::LARGE_INTEGER ;
    delta_Transf::LARGE_INTEGER := mpool_rec^.current.transfcnt::LARGE_INTEGER 
                                 - mpool_rec^.previous.transfcnt::LARGE_INTEGER ;
    delta_Time::LARGE_INTEGER   := mpool_rec^.current.time
                                 - mpool_rec^.previous.time ;
  
 {--------------------}
  inline_unlock_mpool ;
 {--------------------}

 {display trigger rate in upper box of console screen}
  IF ( delta_time.long[0] > 0 ) 
  THEN display_global_rate ( STDIG_RATE := delta_St_Dig.long[0] 
                                         / delta_Time.long[0] * one_second, 
                             TRNSF_RATE := delta_Transf.long[0] 
                                         / delta_Time.long[0] * one_second ) ;


{quit when the SBSC couldn't be latched, most likely because of power off}
{in any case, mpool is refreshed at least once}
UNTIL ( loadsbsc_status = io_failure ) ; 


quit_refresh_mpool:

  handle_trc_sys ( TAG := 'MPL/EXI%',
               MESSAGE := ' Process Refresh Monit Pool Exit' ) ;

 {last one out turn off the lights...}
  mpool_rec^.status.monit_pool := not_refreshed ; {this is a twb}

  rfrsh_mpool_active := FALSE ;
  send_mail ( SUBJECT := ' Exit Refresh Monit Pool' ) ;

 {go take a nap...}
  inline_close_right_eye ;  inline_close_left_eye ;

  DISPOSE ( dblock_pilot ) ;
  DISPOSE ( dblock_assist ) ;
  DISPOSE ( monitpar ) ;
  DELETE  ( mpool_obj ) ;

END ;
{ *************************************************************************** }
{ *************************************************************************** }
FUNCTION exchand_mpool_server OF TYPE EXCEPTION_HANDLER ;

BEGIN

  set_trc_exc_mode ( TRUE ) ;

  exchand_mpool_server := handle_exception ( TAG := 'MPL/EXC%', 
                                        EXC_CODE := signal_args.name ) ;

  handle_trc_sys ( TAG := 'MPL/EXC%', MESSAGE := 'Override: Debugging');
  exchand_mpool_server := FALSE ;
  
  set_trc_exc_mode ( FALSE ) ;

END ;
{ *************************************************************************** }
{ *************************************************************************** }
[INLINE] PROCEDURE fix_dblock_energy ( VAR energy_array : energy_quantity ) ;

{remove a fixed count from an energy quantity in the data block. The quantity }
{needs to be spliced back into a longword, corrected and split apart again }

CONST 
  first_sub_item = 0 ; secnd_sub_item = 1 ; third_sub_item = 2 ;

TYPE 
  int_by_byt = [LONG]
  PACKED RECORD
    byte : ARRAY [1..4] OF byte ;
  END ;

VAR 
  temp : int_by_byt ;

BEGIN

  temp := ZERO ;

  temp.byte[1] := energy_array[first_sub_item].low_byte ;
  temp.byte[2] := energy_array[secnd_sub_item].low_byte ;
  temp.byte[3] := energy_array[third_sub_item].low_byte ;

  IF ( temp.byte[3] >= 128 ) THEN temp.byte[4] := 255 ;{extend negative numbers}

  temp::INTEGER := temp::INTEGER - T3_offset_saved ;

  energy_array[first_sub_item].low_byte := temp.byte[1] ;
  energy_array[secnd_sub_item].low_byte := temp.byte[2] ;
  energy_array[third_sub_item].low_byte := temp.byte[3] ;

END ;
{ *************************************************************************** }
{ *************************************************************************** }
PROCEDURE extract_needed_DBSC_counts ( dblock :^data_block_967 ;
                                     snapshot :^count_snapshot ) ;

VAR 

  bytenum   : INTEGER ;
  sptrgnum  : INTEGER ;
  bunch     : INTEGER ;
  scalernum : INTEGER ;

BEGIN

  FOR bytenum := 0 TO 4 {5 bytes DBSC}
  DO BEGIN
   
    snapshot^.beamxcnt.byte[bytenum] 
           := dblock^.fw_current.beamx_num[bytenum].low_byte ;
    snapshot^.transfcnt.byte[bytenum]  
           := dblock^.fw_current.Transf_num[bytenum].low_byte ;
    snapshot^.stdigcnt.byte[bytenum]  
           := dblock^.fw_current.StDig_num[bytenum].low_byte ;
    snapshot^.lv0cnt.byte[bytenum] 
           := dblock^.fw_current.LV0_Good[bytenum].low_byte ;
    
    FOR sptrgnum := 0 TO 31
    DO BEGIN
      snapshot^.sptrgcnt[sptrgnum].stfired.byte[bytenum]
           := dblock^.fw_current.sptrg_cnt[sptrgnum].fired[bytenum].low_byte  ; 
      snapshot^.sptrgcnt[sptrgnum].stenbld.byte[bytenum]
           := dblock^.fw_current.sptrg_cnt[sptrgnum].enbld[bytenum].low_byte  ; 
    END ;
  
    snapshot^.Vtrans_idle.byte[bytenum] 
           := dblock^.level1_scl.Vtrans_idle[bytenum].low_byte ;
    snapshot^.DBB_busy.byte[bytenum] 
           := dblock^.level1_scl.DBB_busy[bytenum].low_byte ;
    snapshot^.Vtrans_prepare.byte[bytenum] 
           := dblock^.level1_scl.Vtrans_prepare[bytenum].low_byte ;
    snapshot^.Vtrans_wait_VBD.byte[bytenum] 
           := dblock^.level1_scl.Vtrans_wait_VBD[bytenum].low_byte ;
    snapshot^.Vtrans_wait_DMA.byte[bytenum] 
           := dblock^.level1_scl.Vtrans_wait_DMA[bytenum].low_byte ;
    snapshot^.Vtrans_display.byte[bytenum] 
           := dblock^.level1_scl.Vtrans_display[bytenum].low_byte ;

    FOR bunch := 1 TO 6
    DO BEGIN
      snapshot^.L1_per_bunch[bunch].byte[bytenum] 
           := dblock^.level1_scl.L1_per_bunch[bunch,bytenum].low_byte ;
      snapshot^.L0_per_bunch[bunch].byte[bytenum] 
           := dblock^.level1_scl.L0_per_bunch[bunch,bytenum].low_byte ;
    END ;

    snapshot^.L15_Potential.byte[bytenum] 
           := dblock^.fw_current.L15_Pot[bytenum].low_byte ;

    snapshot^.L15_Cycle.byte[bytenum] 
           := dblock^.fw_current.L15_Cycle[bytenum].low_byte ;

    snapshot^.L15_Accept.byte[bytenum] 
           := dblock^.level15.End_Cnt.Accept[bytenum].low_byte ;

    snapshot^.L15_Reject.byte[bytenum] 
           := dblock^.level15.End_Cnt.Reject[bytenum].low_byte ;

    snapshot^.L15_Skip.byte[bytenum] 
           := dblock^.Level1_scl.L15_Skip[bytenum].low_byte ;

    snapshot^.L15_TimeOut.byte[bytenum] 
           := dblock^.level15.End_cnt.TimeOut[bytenum].low_byte ;

    snapshot^.L15_DeadX.byte[bytenum] 
           := dblock^.level15.End_cnt.DeadX[bytenum].low_byte ;

    FOR scalernum := 1 TO 44
    DO snapshot^.foreign.scaler[scalernum].byte[bytenum]
           := dblock^.foreign.scaler[scalernum,bytenum].low_byte  ; 
  END ;

END ;
{ *************************************************************************** }
{ *************************************************************************** }
PROCEDURE read_sptrg_SBSC ( param :^cbus_param_list ;
                         snapshot :^count_snapshot ) ;
VAR

  sptrgnum      : INTEGER ;
  vetonum       : INTEGER ;
  st_fd         : sptrg_per_fstd ;
  relst         : INTEGER ;
  sptrg_offset  : INTEGER ;
  relst_offset  : INTEGER ;
  aofired         : ARRAY [0..31] OF INTEGER ;
  L15_st_Cnf_rej  : ARRAY [0..31] OF INTEGER ; 
  L15_st_cyc_skp  : ARRAY [0..31] OF INTEGER ; 
  L15_st_dead_to  : ARRAY [0..31] OF INTEGER ; 
  veto            : ARRAY [0..31] OF INTEGER ; 

BEGIN

 {read andor fired scalers}
  read_sbscalers ( TAGEXT := 'mpool%',
                     CARD := ADDRESS(sbscaofired),
                 REGISTER := ADDRESS(sbscaofired.datareg),
                   LOADED := TRUE,
                  SCALERS := ADDRESS(aofired),
                    IOPAR := param ) ;

 {read Level 1.5 Confirm/Reject scalers}
  read_SBSCalers ( TAGEXT := 'mpool%',
                     CARD := ADDRESS(sbscL15_cnf_rej),
                 REGISTER := ADDRESS(sbscL15_cnf_rej.datareg),
                   LOADED := TRUE,
                  SCALERS := ADDRESS(L15_st_Cnf_rej), 
               {L15_Confirm and L15_st_reject will be filled at the same time}
                    IOPAR := param ) ;

 {read Level 1.5 Cycle/Skip scalers}
  read_SBSCalers ( TAGEXT := 'mpool%',
                     CARD := ADDRESS(sbscL15_cyc_skp),
                 REGISTER := ADDRESS(sbscL15_cyc_skp.datareg),
                   LOADED := TRUE,
                  SCALERS := ADDRESS(L15_st_Cyc_skp), 
               {L15_st_cycle and L15_st_skip will be filled at the same time}
                    IOPAR := param ) ;

 {read Level 1.5 Dead Crossing/Timeout scalers}
  read_SBSCalers ( TAGEXT := 'mpool%',
                     CARD := ADDRESS(sbscL15_dead_to),
                 REGISTER := ADDRESS(sbscL15_dead_to.datareg),
                   LOADED := TRUE,
                  SCALERS := ADDRESS(L15_st_Dead_to), 
               {L15_st_DeadX and L15_st_timout will be filled at the same time}
                    IOPAR := param ) ;

 {spread counts into target structure ordered by sptrg}
  FOR sptrgnum := 0 TO 15
  DO BEGIN
    snapshot^.sptrgcnt[sptrgnum].aofired        := aofired[ sptrgnum ] ;
    snapshot^.sptrgcnt[sptrgnum].L15.st_Confirm := L15_st_Cnf_Rej[      sptrgnum ] ;
    snapshot^.sptrgcnt[sptrgnum].L15.st_Reject  := L15_st_Cnf_Rej[ 16 + sptrgnum ] ;
    snapshot^.sptrgcnt[sptrgnum].L15.st_Cycle   := L15_st_Cyc_skp[      sptrgnum ] ;
    snapshot^.sptrgcnt[sptrgnum].L15.st_Skip    := L15_st_Cyc_skp[ 16 + sptrgnum ] ;
    snapshot^.sptrgcnt[sptrgnum].L15.st_DeadX   := L15_st_dead_to[      sptrgnum ] ;
    snapshot^.sptrgcnt[sptrgnum].L15.st_TimeOut := L15_st_dead_to[ 16 + sptrgnum ] ;
  END ;
  FOR sptrgnum := 16 TO 31
  DO BEGIN
    snapshot^.sptrgcnt[sptrgnum].aofired
         := aofired[ sptrgnum ] ;
  END ;

 {read and reorder veto scaler in increasing bit number of fstd enable mask}
  sptrg_offset := 0 ;

  FOR st_fd := st_0_3 TO st_28_31
  DO BEGIN

    read_sbscalers ( TAGEXT := 'mpool%',
                       CARD := ADDRESS(sbscdis[st_fd]),
                   REGISTER := ADDRESS(sbscdis[st_fd].datareg),
                     LOADED := TRUE,
                    SCALERS := ADDRESS(veto), 
                      IOPAR := param ) ;

    relst_offset := 0 ; 

    FOR relst := 0 TO 3
    DO BEGIN

      sptrgnum := sptrg_offset + relst ; 

      FOR vetonum := 0 TO 7
      DO snapshot^.sptrgcnt[sptrgnum].stvetos[vetonum]
             := veto[ 31 - relst_offset - vetonum ] ;

      relst_offset := relst_offset + 8 ; 

    END ;

    sptrg_offset := sptrg_offset + 4 ;

  END ;

END ;
{ *************************************************************************** }
{ *************************************************************************** }
PROCEDURE copy_twr_and_refset_programming ( mpool_twr    :^trig_tower_array ;
                                            mpool_refset :^refset_section ) ;
                                            

VAR

  eta_pol       : eta_polarity ;  
  eta_mag       : eta_magnitude ; 
  phi_val       : phi_value ;     
  lt_eta        : magn_eta_per_fe_cell ;
  lt_phi        : phi_per_fe_half_cell ;
  p_trgtwr      :^cal_trig_tower ;
  p_LgTile      :^cal_Large_Tile ;
  p_anytype     :^ANYTYPE ;

BEGIN

  FOR    eta_pol := firstetasign TO lastetasign 
  DO FOR eta_mag := firstetamagn TO lastetamagn 
  DO FOR phi_val := firstphival  TO lastphival
{  DO FOR ref_typ := EMEt_ref     TO TOTEt_ref \ replaced with the code below}
{  DO FOR ref_num := ref_0        TO ref_      / but not for eta, phi        }
  DO BEGIN                                  {because trgtwr are only pointers}
                                {and nothing ensures that they are contiguous}

    p_trgtwr := trgtwr[eta_pol,eta_mag,phi_val] ;

    {this is the tower status section}
    p_trgtwr^.status[EMEtZ0].excluded := p_trgtwr^.adconv[EMEtZ0].simu_state ;
    p_trgtwr^.status[HDEtZ0].excluded := p_trgtwr^.adconv[HDEtZ0].simu_state ;
    mpool_twr^[eta_pol,eta_mag,phi_val] := p_trgtwr^.status::word ;

    {this is the reference set section}
    p_anytype := ADDRESS( 
      mpool_refset^.pattern[EMEt_ref,ref_0,eta_pol,eta_mag,phi_val] ) ;
    p_anytype^::INTEGER := p_trgtwr^.threshold[ ref_0,  EMEt_ref ] ;

    p_anytype::INTEGER  := p_anytype::INTEGER + SIZE(refset_pattern) ;
    p_anytype^::INTEGER := p_trgtwr^.threshold[ ref_1,  EMEt_ref ] ;

    p_anytype::INTEGER  := p_anytype::INTEGER + SIZE(refset_pattern) ;
    p_anytype^::INTEGER := p_trgtwr^.threshold[ ref_2,  EMEt_ref ] ;

    p_anytype::INTEGER  := p_anytype::INTEGER + SIZE(refset_pattern) ;
    p_anytype^::INTEGER := p_trgtwr^.threshold[ ref_3,  EMEt_ref ] ;

    p_anytype::INTEGER  := p_anytype::INTEGER + SIZE(refset_pattern) ;
    p_anytype^::INTEGER := p_trgtwr^.threshold[ ref_0, HDEt_veto ] ;

    p_anytype::INTEGER  := p_anytype::INTEGER + SIZE(refset_pattern) ;
    p_anytype^::INTEGER := p_trgtwr^.threshold[ ref_1, HDEt_veto ] ;

    p_anytype::INTEGER  := p_anytype::INTEGER + SIZE(refset_pattern) ;
    p_anytype^::INTEGER := p_trgtwr^.threshold[ ref_2, HDEt_veto ] ;

    p_anytype::INTEGER  := p_anytype::INTEGER + SIZE(refset_pattern) ;
    p_anytype^::INTEGER := p_trgtwr^.threshold[ ref_3, HDEt_veto ] ;

    p_anytype::INTEGER  := p_anytype::INTEGER + SIZE(refset_pattern) ;
    p_anytype^::INTEGER := p_trgtwr^.threshold[ ref_0, TOTEt_ref ] ;

    p_anytype::INTEGER  := p_anytype::INTEGER + SIZE(refset_pattern) ;
    p_anytype^::INTEGER := p_trgtwr^.threshold[ ref_1, TOTEt_ref ] ;

    p_anytype::INTEGER  := p_anytype::INTEGER + SIZE(refset_pattern) ;
    p_anytype^::INTEGER := p_trgtwr^.threshold[ ref_2, TOTEt_ref ] ;

    p_anytype::INTEGER  := p_anytype::INTEGER + SIZE(refset_pattern) ;
    p_anytype^::INTEGER := p_trgtwr^.threshold[ ref_3, TOTEt_ref ] ;

  END ;

  FOR    eta_pol := pos_e TO neg_e
  DO FOR lt_eta  := e_1_4 TO e_17_20 
  DO FOR lt_phi  := p_1_8 TO p_25_32
  DO BEGIN

    p_LgTile := LgTile[eta_pol,lt_eta,lt_phi] ;

    {this is the large tile reference set section}
    p_anytype := ADDRESS( 
      mpool_refset^.LT_pattern[ref_0,eta_pol,LT_eta,LT_phi] ) ;
    p_anytype^::INTEGER := p_LgTile^.threshold[ ref_0 ] ;

    p_anytype::INTEGER  := p_anytype::INTEGER + SIZE(LT_refset_pattern) ;
    p_anytype^::INTEGER := p_LgTile^.threshold[ ref_1 ] ;

    p_anytype::INTEGER  := p_anytype::INTEGER + SIZE(LT_refset_pattern) ;
    p_anytype^::INTEGER := p_LgTile^.threshold[ ref_2 ] ;

    p_anytype::INTEGER  := p_anytype::INTEGER + SIZE(LT_refset_pattern) ;
    p_anytype^::INTEGER := p_LgTile^.threshold[ ref_3 ] ;

    p_anytype::INTEGER  := p_anytype::INTEGER + SIZE(LT_refset_pattern) ;
    p_anytype^::INTEGER := p_LgTile^.threshold[ ref_4 ] ;

    p_anytype::INTEGER  := p_anytype::INTEGER + SIZE(LT_refset_pattern) ;
    p_anytype^::INTEGER := p_LgTile^.threshold[ ref_5 ] ;

    p_anytype::INTEGER  := p_anytype::INTEGER + SIZE(LT_refset_pattern) ;
    p_anytype^::INTEGER := p_LgTile^.threshold[ ref_6 ] ;

    p_anytype::INTEGER  := p_anytype::INTEGER + SIZE(LT_refset_pattern) ;
    p_anytype^::INTEGER := p_LgTile^.threshold[ ref_7 ] ;

  END ;

END ;
{ *************************************************************************** }
{ *************************************************************************** }
PROCEDURE read_trouble_warning_bits ( param :^cbus_param_list ;
                                    VAR twb : int_by_byte ) ;
BEGIN

    param^.cbus := mtgtwb.cbus ;
    param^.mba  := mtgtwb.mba ;
    param^.ca   := mtgtwb.ca ;
    param^.fa   := mtgtwb.twbreg.fa ;

    proced_tcs_read_twb ( PARAM := param, TWB := twb.byte[0] ) ;

END ;
{ **************************************************************************** }
{ *************************************************************************** }
[INLINE] PROCEDURE inline_lock_mpool ;
BEGIN ELN$LOCK_AREA ( mpool_obj, mpool_rec^.lock ) ; END ;
{ *************************************************************************** }
[INLINE] PROCEDURE inline_unlock_mpool ;
BEGIN ELN$UNLOCK_AREA ( mpool_obj, mpool_rec^.lock ) ; END ;
{ **************************************************************************** }
{ *************************************************************************** }
PROCEDURE set_mpool_rate ( rate : INTEGER ) ;

{*** this declaration is also repeated as EXTERNAL in mod_phat_execute    *** }
{*** remember to propagate any change                                     *** }

BEGIN 
  refresh_interval := rate ; 
END ;
{ *************************************************************************** }
{ *************************************************************************** }
PROCEDURE start_rfrsh_mpool_proc ;

{*** this declaration is also repeated as EXTERNAL in mod_phat_execute    *** }
{*** remember to propagate any change                                     *** }

VAR  
  status    : INTEGER ;
BEGIN

  IF ( rfrsh_mpool_active = TRUE ) 
  THEN BEGIN
    handle_trc_sys ( TAG := 'MPL/CRE%',
                 MESSAGE := ' Process Refresh Monit Pool Already Exists' ) ;
    GOTO quit_create_rfrsh_mpool ;
  END ;

  handle_trc_sys ( TAG := 'MPL/CRE%',
               MESSAGE := ' Creating Process Refresh Monit Pool ' ) ;

  CREATE_PROCESS ( proc_rfrsh_mpool, block_rfrsh_mpool, STATUS := status );
  IF ( ( status mod 8 ) <> 1 ) 
  THEN handle_trc_sta ( TAG := 'CRE/PRC%mpool%', STATUS := status ) ;


  KER$NAME_OBJECT( name_mpool_proc, 'RFRSH M_POOL', proc_rfrsh_mpool, 
                   STATUS := status ) ;
  handle_trc_sta ( TAG := 'NAM/PRC%mpool%', STATUS := status ) ;

quit_create_rfrsh_mpool :
END ;
{ *************************************************************************** }
PROCEDURE delete_rfrsh_mpool_proc ;

{*** this declaration is also repeated as EXTERNAL in mod_phat_execute    *** }
{*** remember to propagate any change                                     *** }

VAR  
  status    : INTEGER ;

BEGIN

  IF ( rfrsh_mpool_active = FALSE ) 
  THEN BEGIN
    handle_trc_sys ( TAG := 'MPL/DEL%',
                 MESSAGE := ' Process Refresh Monit Pool Does not Exist' ) ;
    GOTO quit_delete_rfrsh_mpool ;
  END ;

  handle_trc_sys ( TAG := 'MPL/DEL%',
               MESSAGE := ' Deleting Process Refresh Monit Pool ' ) ;

  inline_lock_mpool ;

  lock_console ;
  SIGNAL ( proc_rfrsh_mpool, STATUS := status );
  unlock_console ;
  handle_trc_sta ( TAG := 'SIG/PRC%mpool%', STATUS := status ) ;

  inline_unlock_mpool ;

  DELETE ( name_mpool_proc, STATUS := status ) ;
  handle_trc_sta ( TAG := 'DEL/NAM%mpool%',
                STATUS := status ) ;

  inline_close_right_eye ;
  inline_close_left_eye ;

  rfrsh_mpool_active := FALSE ;
  mpool_rec^.status.monit_pool := not_refreshed ; {this is a twb}

  DELETE  ( mpool_obj ) ;

quit_delete_rfrsh_mpool:
END ;
{ *************************************************************************** }
{ *************************************************************************** }
END .
