{ *************************************************************************** }
MODULE mod_tst_ctfe_proms ;
{  Created  27-NOV-1989   MICHIGAN STATE UNIVERSITY, TRIGGER CONTROL SOFTWARE }
{ *************************************************************************** }
INCLUDE
  mod_common_global_flags,
  mod_handle_tracing,
  mod_def_hardware_tables,
  mod_init_lsm,
  mod_handle_registers,
  mod_handle_cat_cards, 
  mod_init_thresholds,
  mod_tst_common,
  mod_tst_init,
  mod_tst_misc_util ;
{ *************************************************************************** }
EXPORT
  hardware_test_ctfe_proms ;
{ *************************************************************************** }
IMPORT

  status_type, ok, error_found,       {from module MOD_COMMON_GLOBAL_FLAGS    }

  handle_trc_err,                     {from module MOD_HANDLE_TRACING         }
  handle_trc_sys,                     {from module MOD_HANDLE_TRACING         }

  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    }
  phi_value,                          {from module MOD_DEF_HARDWARE_TABLES    }
  phi_per_fe_half_cell,               {from module MOD_DEF_HARDWARE_TABLES    }
  p_1_8, p_9_16, p_17_24, p_25_32,    {from module MOD_DEF_HARDWARE_TABLES    }
  ctfe_card_high_half,                {from module MOD_DEF_HARDWARE_TABLES    }
  cat2_card,                          {from module MOD_DEF_HARDWARE_TABLES    }
  cat2_EME_t1, cat2_HDE_t1, cat2_PxM_t1, cat2_PyM_t1,
  magn_eta_per_fe_cell,               {from module MOD_DEF_HARDWARE_TABLES    }
  e_1_4, e_21_24,                     {from module MOD_DEF_HARDWARE_TABLES    }
  relative_eta,                       {from module MOD_DEF_HARDWARE_TABLES    }
  relative_phi,                       {from module MOD_DEF_HARDWARE_TABLES    }
  relp_0, relp_1, relp_2, relp_3, relp_4, relp_5, relp_6, relp_7,
  adc_data_type_per_ctfe_channel,     {from module MOD_DEF_HARDWARE_TABLES    }
    EMEtZ0, HDEtZ0,                   {from module MOD_DEF_HARDWARE_TABLES    }
  imlro_eng1,{imlro_eng2,}            {from module MOD_DEF_HARDWARE_TABLES    }
  first_byte,{second_byte, third_byte, fourth_byte,  }

  mtgfwtss,                           {from module MOD_DEF_HARDWARE_TABLES    }
  mtgcttss,                           {from module MOD_DEF_HARDWARE_TABLES    }
  reading_from_pipe,                  {from module MOD_DEF_HARDWARE_TABLES    }
  tss_force_low, tss_force_high,      {from module MOD_DEF_HARDWARE_TABLES    }
  tss_fw_write_ab, tss_fw_read_ab,    {from module MOD_DEF_HARDWARE_TABLES    }
  tss_ct_write_ab, tss_ct_read_ab,    {from module MOD_DEF_HARDWARE_TABLES    }
  ctfe_ctrl,                          {from module MOD_DEF_HARDWARE_TABLES    }
  Momentum_sign, pos_m, neg_m,        {from module MOD_DEF_HARDWARE_TABLES    }

  lsm_fully_operational,              {from module MOD_INIT_LSM               }

  update_register,                    {from module MOD_HANDLE_REGISTER        }
  examine_multi_byte,                 {from module MOD_HANDLE_REGISTER        }
                              
  examine_cat2_operand,               {FROM MODULE MOD_HANDLE_CAT_CARDS       }

  zero_tree_corrections,              {from module MOD_INIT_THRESHOLDS        }

  reqstd_loop,                        {from module MOD_TST_COMMON             }
  low_eta_pol, hig_eta_pol,           {from module MOD_TST_COMMON             }
  low_eta_mag, hig_eta_mag,           {from module MOD_TST_COMMON             }
  low_phi, hig_phi,                   {from module MOD_TST_COMMON             }
  low_twr_typ, hig_twr_typ,           {from module MOD_TST_COMMON             }
  low_page_num, hig_page_num,         {from module MOD_TST_COMMON             }
  testtag,                            {from module MOD_TST_COMMON             }
  iotest,                             {from module MOD_TST_COMMON             }
  latch,                              {from module MOD_TST_COMMON             }
  constructed_quantities,             {from module MOD_TST_COMMON             }
  EM_quant, HD_quant, Px_quant, Py_quant,
  array_of_constructed_quantities,    {from module MOD_TST_COMMON             }
  single_shot_mtg,                    {from module MOD_TST_COMMON             }
  Check_FW_AndOr,                     {from module MOD_TST_COMMON             }

  init_mtg_for_caltrg,                {from module MOD_TST_INIT               }
  load_all_ctfe_in_cell,              {from module MOD_TST_INIT               }

  single_cycle_mtgs,                  {from module MOD_TST_MISC_UTIL          }
  mtg_preset_at_end_pattern,          {from module MOD_TST_MISC_UTIL          }
  mtg_stop_clock,                     {from module MOD_TST_MISC_UTIL          }
  mtg_preset_at_begin_pattern,        {from module MOD_TST_MISC_UTIL          }
  mtg_reset_prom_counter,             {from module MOD_TST_MISC_UTIL          }
  mtg_release_clock,                  {from module MOD_TST_MISC_UTIL          }
  select_lookup_page,                 {from module MOD_TST_MISC_UTIL          }
  update_buffer_pipe,                 {from module MOD_TST_MISC_UTIL          }
  inquire_fix_it,                     {from module MOD_TST_MISC_UTIL          }
  inquire_continue,                   {from module MOD_TST_MISC_UTIL          }
  inquire_action_after_error ;        {from module MOD_TST_MISC_UTIL          }

{ *************************************************************************** }
{ *************************************************************************** }

TYPE

  bit  = [BIT(1)] 0..1     ;
  byte = [BYTE]   0..255   ;

VAR

  pol_cell    : eta_polarity ;
  eta_cell    : magn_eta_per_fe_cell ;
  phi_cell    : phi_per_fe_half_cell ;
  t1_sum      : ARRAY [pos_e..neg_e,e_1_4..e_21_24,p_1_8..p_25_32] OF
                                             array_of_constructed_quantities ;
  t1_trunc    : array_of_constructed_quantities ;
  watch_t1_trunc : ARRAY [EM_quant..Py_quant] OF BOOLEAN ; 

  act_resp    : array_of_constructed_quantities ;
  exp_resp    : array_of_constructed_quantities ;
  resp_offset : array_of_constructed_quantities ;

{ *************************************************************************** }
{ declare the FORTRAN routines of LSMLIB                                      }
  %INCLUDE 'LSMLIB.EXT/LIST'

{ *************************************************************************** }
{ *************************************************************************** }
PROCEDURE hardware_test_ctfe_proms ;

VAR

  loop_count  : INTEGER ;
  error_count : INTEGER ;
  page_num    : INTEGER ;
  eta_pol     : eta_polarity ;
  phi_val     : phi_value ;
  eta_mag     : eta_magnitude ;
  rele        : relative_eta ;
  twr_typ     : adc_data_type_per_ctfe_channel ;
  p_ctfe_ctrl :^ctfe_card_high_half ;
  simu        : INTEGER ;
  EM_ADC_byte : INTEGER ;
  HD_ADC_byte : INTEGER ;
  tmp_e_c     : magn_eta_per_fe_cell ;
  tmp_p_c     : phi_per_fe_half_cell ;
  step_status : status_type ;
  prom_status : status_type ;
  Px_Sign, Py_Sign : Momentum_sign ;
  redo_loop   : BOOLEAN ;
  re_synch    : BOOLEAN ;

BEGIN

  IF ( lsm_fully_operational <> TRUE )
  THEN BEGIN
    handle_trc_err ( TAG := 'HRD/TST%'+testtag,
                 MESSAGE := ' LSM Data Base not Initialized, Test Aborted ' ) ;
    GOTO abort_test ;
  END ;

{ *** start necessary timing signals                                      *** }
  init_mtg_for_caltrg ;

{ *** remove the tree correction loaded in tier #3 CAT3 cards             *** }
  zero_tree_corrections ( TAGEXT := testtag,
                          INIPAR := iotest,
                          STATUS := step_status ) ;

{ *** test starts here *** }

  error_count := ZERO ;
  FOR loop_count := 1 TO reqstd_loop
  DO BEGIN

    handle_trc_sys ( 'loop : ' + CONVERT(STRING,loop_count)
                   + ' / ' + CONVERT(STRING,reqstd_loop) ) ;

    FOR page_num := low_page_num TO hig_page_num
    DO BEGIN

      IF ( single_shot_mtg = TRUE )
      THEN BEGIN
        mtg_preset_at_begin_pattern ( MTG := ADDRESS(mtgcttss) ) ;
      END ;

      FOR    eta_pol  := low_eta_pol TO hig_eta_pol
      DO FOR tmp_p_c  := CONVERT(phi_per_fe_half_cell, (ORD(low_phi)-1) DIV 8 ) 
                      TO CONVERT(phi_per_fe_half_cell, (ORD(hig_phi)-1) DIV 8 ) 
      DO FOR tmp_e_c  := CONVERT(magn_eta_per_fe_cell, (ORD(low_eta_mag)-1) DIV 4 ) 
                      TO CONVERT(magn_eta_per_fe_cell, (ORD(hig_eta_mag)-1) DIV 4 ) 
      DO load_all_ctfe_in_cell ( CELL_SIGN_ETA := eta_pol,
                                 CELL_MAGN_ETA := tmp_e_c,
                            HALF_CELL_QUAD_PHI := tmp_p_c,
                               COMMON_ADC_SIMU := 0 ) ;

      IF ( single_shot_mtg = TRUE )
      THEN BEGIN
        mtg_preset_at_end_pattern ( MTG := ADDRESS(mtgcttss) ) ;
      END ;

      exp_resp := ZERO ;
      act_resp := ZERO ;
      resp_offset := ZERO ;
      t1_sum := ZERO ;

      select_lookup_page ( TAGEXT := testtag,
                   ENRG_1st_INDEX := page_num,
                   ENRG_2nd_INDEX := page_num,
                   MOMT_1st_INDEX := page_num,
                   MOMT_2nd_INDEX := page_num ) ;

     {find initial response of PROM to ADC count of zero}
      FOR    eta_pol := low_eta_pol TO hig_eta_pol
      DO FOR phi_val := low_phi     TO hig_phi
      DO FOR eta_mag := low_eta_mag TO hig_eta_mag
      DO BEGIN

        expected_prom_response ( PAGE := page_num,
                              ETA_POL := eta_pol,
                              ETA_MAG := eta_mag,
                              PHI_VAL := phi_val,
                              EM_ENRG := 0,
                              HD_ENRG := 0,
                             RESPONSE := exp_resp ) ;

        pol_cell := eta_pol ;
        eta_cell := CONVERT(magn_eta_per_fe_cell, (ORD(eta_mag)-1) DIV 4 ) ;
        phi_cell := CONVERT(phi_per_fe_half_cell, (ORD(phi_val)-1) DIV 8 ) ;

        CASE phi_cell OF 
          p_1_8,  p_25_32 : Px_Sign := pos_m ;
          p_9_16, p_17_24 : Px_Sign := neg_m ;
        END ; 
        CASE phi_cell OF 
          p_1_8,   p_9_16  : Py_Sign := pos_m ;
          p_17_24, p_25_32 : Py_Sign := neg_m ;
        END ; 

        increase_offsets ( Px_SIGN := Px_Sign,
                           Py_SIGN := Py_Sign ) ;
        increase_tier1_quant ( POL_CELL := pol_cell,
                               ETA_CELL := eta_cell,
                               PHI_CELL := phi_cell ) ;
      END ; {rele&phi_val&eta_pol}

     {now check what the reality is, and offer to correct the expectation}
      IF ( single_shot_mtg = TRUE ) THEN single_cycle_mtgs ;
      update_buffer_pipe ;
      read_global_responses ( act_resp ) ;
      check_actual_and_fix_expected ;

{ ***  Initialization done, the test starts here *** }

     {start scanning the channels}
      FOR    eta_pol := low_eta_pol TO hig_eta_pol
      DO FOR phi_val := low_phi     TO hig_phi
      DO FOR eta_mag := low_eta_mag TO hig_eta_mag
      DO BEGIN

        pol_cell := eta_pol ;
        eta_cell := CONVERT(magn_eta_per_fe_cell, (ORD(eta_mag)-1) DIV 4 ) ;
        phi_cell := CONVERT(phi_per_fe_half_cell, (ORD(phi_val)-1) DIV 8 ) ;

        CASE phi_cell OF 
          p_1_8,  p_25_32 : Px_Sign := pos_m ;
          p_9_16, p_17_24 : Px_Sign := neg_m ;
        END ; 
        CASE phi_cell OF 
          p_1_8,   p_9_16  : Py_Sign := pos_m ;
          p_17_24, p_25_32 : Py_Sign := neg_m ;
        END ; 

        rele := CONVERT ( relative_eta, (ORD(eta_mag)-1) MOD 4 ) ;
        p_ctfe_ctrl := ADDRESS ( ctfe_ctrl[eta_pol,eta_cell,phi_val] ) ;
        EM_ADC_byte := 0 ;
        HD_ADC_byte := 0 ;

       {first, remove contribution of channel that is going to be tested}
        expected_prom_response ( PAGE := page_num,
                              ETA_POL := eta_pol,
                              ETA_MAG := eta_mag,
                              PHI_VAL := phi_val,
                              EM_ENRG := EM_ADC_byte,
                              HD_ENRG := HD_ADC_byte,
                             RESPONSE := exp_resp ) ;

        decrease_offsets ( Px_SIGN := Px_Sign,
                           Py_SIGN := Py_Sign ) ;
        decrease_tier1_quant ( POL_CELL := pol_cell,
                               ETA_CELL := eta_cell,
                               PHI_CELL := phi_cell ) ;
        find_t1_truncation ;

        FOR twr_typ := low_twr_typ TO hig_twr_typ
        DO BEGIN

          handle_trc_sys ( TAG := 'HRD/TST%'+testtag,
                       MESSAGE := ' Ramping PROM input'
                                + ' ' + CONVERT(STRING(3),eta_pol)
                                + ',' + CONVERT(STRING,eta_mag)
                                + ',' + CONVERT(STRING,phi_val)
                                + ',' + CONVERT(STRING(2),twr_typ) 
                                + ' page #' + CONVERT(STRING,page_num) ) ;

          select_ctfe_channel ( p_ctfe_ctrl, rele, twr_typ ) ;
          prom_status := ok ;

          FOR simu := 1 TO 255
          DO BEGIN

           redo_loop_entry_point:

            update_simu_reg ( p_ctfe_ctrl, simu ) ;

            CASE twr_typ OF
              EMEtZ0 : EM_ADC_byte := simu ;
              HDEtZ0 : HD_ADC_byte := simu ;
            END ;
            expected_prom_response ( PAGE := page_num,
                                  ETA_POL := eta_pol,
                                  ETA_MAG := eta_mag,
                                  PHI_VAL := phi_val,
                                  EM_ENRG := EM_ADC_byte,
                                  HD_ENRG := HD_ADC_byte,
                                 RESPONSE := exp_resp ) ;

            check_t1_trunc_crossing ( Px_SIGN := Px_Sign,
                                      Py_SIGN := Py_Sign ) ;

            IF ( single_shot_mtg = TRUE ) THEN single_cycle_mtgs ;
            update_buffer_pipe ;

            read_global_responses ( act_resp ) ;

            compare_actual_to_expected ( Px_SIGN := Px_Sign,
                                         Py_SIGN := Py_Sign,
                                          STATUS := step_status ) ;
            IF ( step_status <> ok )
            THEN BEGIN
              error_count := error_count + 1 ;
              handle_trc_err ( TAG := 'HRD/TST%'+testtag,
                           MESSAGE := ' Error Detected at'
                                    + ' ' + CONVERT(STRING(3),eta_pol)
                                    + ',' + CONVERT(STRING,eta_mag)
                                    + ',' + CONVERT(STRING,phi_val)
                                    + ' page #' + CONVERT(STRING,page_num)
                                    + ' EM ' + CONVERT(STRING(3),EM_ADC_byte)
                                    + ' & HD ' + CONVERT(STRING(3),HD_ADC_byte) ) ;
              prom_status := error_found ;
              inquire_action_after_error ( LOOP_COUNT := loop_count,
                                          ERROR_COUNT := error_count,
                                       REDO_SAME_LOOP := redo_loop,
                                             RE_SYNCH := re_synch,
                                               STATUS := step_status ) ;
              IF ( Re_synch = TRUE )
              THEN BEGIN
                handle_trc_err ( TAG := 'HRD/TST%'+testtag,
                             MESSAGE := ' Re-Synchronizing Offsets using Values Read' ) ;
                resp_offset[EM_quant] := act_resp[EM_quant] - exp_resp[EM_quant] ;
                resp_offset[HD_quant] := act_resp[HD_quant] - exp_resp[HD_quant] ;
                resp_offset[Px_quant] := act_resp[Px_quant] - exp_resp[Px_quant] ;
                resp_offset[Py_quant] := act_resp[Py_quant] - exp_resp[Py_quant] ;
                handle_trc_err ( TAG := 'HRD/TST%'+testtag,
                             MESSAGE := ' Done Re-Synchronizing, Redoing Same Loop' ) ;
                step_status := ok ;
                GOTO redo_loop_entry_point ;
              END 
              ELSE IF ( redo_loop = TRUE ) THEN GOTO redo_loop_entry_point 
              ELSE IF ( step_status <> ok ) THEN GOTO abort_test ;
            END ;

          END ; {simu}

          IF ( prom_status <> ok )
          THEN BEGIN
            handle_trc_err ( TAG := 'HRD/TST%'+testtag,
                         MESSAGE := ' PROM Failed Test at'
                                  + ' ' + CONVERT(STRING(3),eta_pol)
                                  + ',' + CONVERT(STRING,eta_mag)
                                  + ',' + CONVERT(STRING,phi_val)
                                  + ',' + CONVERT(STRING,twr_typ)
                                  + ' Page #' + CONVERT(STRING,page_num) ) ;
            inquire_continue ( STATUS := step_status ) ;
            IF ( step_status <> ok ) THEN GOTO abort_test ;
          END ;

        END ; {twr_typ}

        increase_offsets ( Px_SIGN := Px_Sign,
                           Py_SIGN := Py_Sign ) ;
        increase_tier1_quant ( POL_CELL := pol_cell,
                               ETA_CELL := eta_cell,
                               PHI_CELL := phi_cell ) ;

      END ; {rele&phi_val&eta_pol}

     END ; {page_num}

  END ; {loop_count}

abort_test:
END ;
{ *************************************************************************** }
{ *************************************************************************** }
[INLINE]
PROCEDURE select_ctfe_channel ( p_ctfe_ctrl :^ctfe_card_high_half ;
                                       rele : relative_eta ;
                                    twr_typ : adc_data_type_per_ctfe_channel ) ;
BEGIN

  update_register ( TAGEXT := testtag,
                      CARD := p_ctfe_ctrl,
                  REGISTER := ADDRESS(p_ctfe_ctrl^.chanctrl),
                     IOPAR := iotest,
                      DATA := latch[rele,twr_typ] ) ; { sel updated channel }
  update_register ( TAGEXT := testtag,
                      CARD := p_ctfe_ctrl,
                  REGISTER := ADDRESS(p_ctfe_ctrl^.loadsimreg),
                     IOPAR := iotest,
                      DATA := 0 ) ; { clear simu reg }

END ;
{ *************************************************************************** }
{ *************************************************************************** }
[INLINE]
PROCEDURE update_simu_reg ( p_ctfe_ctrl :^ctfe_card_high_half ;
                                   simu : byte ) ;
BEGIN

  update_register ( TAGEXT := testtag,
                      CARD := p_ctfe_ctrl,
                  REGISTER := ADDRESS(p_ctfe_ctrl^.loadsimreg),
                     IOPAR := iotest,
                      DATA := simu ) ; { load simu reg }

END ;
{ *************************************************************************** }
{ *************************************************************************** }
[INLINE]
PROCEDURE expected_prom_response ( page : INTEGER ;
                                eta_pol : eta_polarity ;
                                eta_mag : eta_magnitude ;
                                phi_val : phi_value ;
                                em_enrg : INTEGER ;
                                hd_enrg : INTEGER ;
                           VAR response : array_of_constructed_quantities ) ;
VAR

  sign_eta : INTEGER ;
  magn_eta : INTEGER ;
  val_phi  : INTEGER ;

BEGIN

  {translate variables for call to LSM prom_response}
  sign_eta  := ORD(eta_pol) ;
  magn_eta  := ORD(eta_mag) ;
  val_phi   := ORD(phi_val) ;

  prom_response_by_index ( sign_eta, magn_eta, val_phi,
                           page,
                           EM_enrg, HD_enrg,
                           response ) ;

END ;
{ *************************************************************************** }
{ *************************************************************************** }
[INLINE]
PROCEDURE
read_global_responses ( VAR act_resp : array_of_constructed_quantities ) ;

TYPE

  signed_24bit = [LONG] 
  PACKED RECORD
    three_byte :  [POS(0)] -8388608..8388607 ; {24 bit signed number}
    unused     : [POS(24)] 0..255 ; 
  END ;

VAR
  count_read : signed_24bit ; 

BEGIN

  IF ( low_twr_typ = EMEtZ0 ) THEN 
  examine_multi_byte ( TAGEXT := testtag,
                         CARD := ADDRESS(imlro_eng1),
                     REGISTER := ADDRESS(imlro_eng1.EM_Et_eng[first_byte]),
                        IOPAR := iotest,
             THREE_BYTE_VALUE := count_read::INTEGER ) ;
  act_resp[EM_quant] := count_read.three_byte ;

  IF ( hig_twr_typ = HDEtZ0 ) THEN 
  examine_multi_byte ( TAGEXT := testtag,
                         CARD := ADDRESS(imlro_eng1),
                     REGISTER := ADDRESS(imlro_eng1.HD_Et_eng[first_byte]),
                        IOPAR := iotest,
             THREE_BYTE_VALUE := count_read::INTEGER ) ;
  act_resp[HD_quant] := count_read.three_byte ;

  IF ( low_twr_typ <> hig_twr_typ ) THEN 
  examine_multi_byte ( TAGEXT := testtag,
                         CARD := ADDRESS(imlro_eng1),
                     REGISTER := ADDRESS(imlro_eng1.Px_moment[first_byte]),
                        IOPAR := iotest,
             THREE_BYTE_VALUE := count_read::INTEGER ) ;
  act_resp[Px_quant] := count_read.three_byte ;

  IF ( low_twr_typ <> hig_twr_typ ) THEN 
  examine_multi_byte ( TAGEXT := testtag,
                         CARD := ADDRESS(imlro_eng1),
                     REGISTER := ADDRESS(imlro_eng1.Py_moment[first_byte]),
                        IOPAR := iotest,
             THREE_BYTE_VALUE := count_read::INTEGER ) ;
  act_resp[Py_quant] := count_read.three_byte ;

END ;
{ *************************************************************************** }
{ *************************************************************************** }
PROCEDURE check_actual_and_fix_expected ;

VAR
  fix_status : status_type ;

BEGIN

  IF ( low_twr_typ = EMEtZ0 ) THEN 
  IF ( act_resp[EM_quant] <> resp_offset[EM_quant] )
  THEN BEGIN
    fix_status := error_found ;
    handle_trc_err ( TAG := 'HRD/TST%'+testtag,
                 MESSAGE := ' EM initial global count is ' + CONVERT(STRING,act_resp[EM_quant])
                          + ' instead of ' + CONVERT(STRING,resp_offset[EM_quant]) ) ;
    display_cat_inputs ( EM_quant ) ;
    inquire_fix_it ( STATUS := fix_status ) ;
    IF ( fix_status = ok ) THEN resp_offset[EM_quant] := act_resp[EM_quant] ;
  END ;

  IF ( hig_twr_typ = HDEtZ0 ) THEN 
  IF ( act_resp[HD_quant] <> resp_offset[HD_quant] )
  THEN BEGIN
    fix_status := error_found ;
    handle_trc_err ( TAG := 'HRD/TST%'+testtag,
                 MESSAGE := ' HD initial global count is ' + CONVERT(STRING,act_resp[HD_quant])
                          + ' instead of ' + CONVERT(STRING,resp_offset[HD_quant]) ) ;
    display_cat_inputs ( HD_quant ) ;
    inquire_fix_it ( STATUS := fix_status ) ;
    IF ( fix_status = ok ) THEN resp_offset[HD_quant] := act_resp[HD_quant] ;
  END ;

  IF ( low_twr_typ <> hig_twr_typ ) THEN 
  IF ( act_resp[Px_quant] <> resp_offset[Px_quant] )
  THEN BEGIN
    fix_status := error_found ;
    handle_trc_err ( TAG := 'HRD/TST%'+testtag,
                 MESSAGE := ' Px initial global count is ' + CONVERT(STRING,act_resp[Px_quant])
                          + ' instead of ' + CONVERT(STRING,resp_offset[Px_quant]) ) ;
    display_cat_inputs ( Px_quant ) ;
    inquire_fix_it ( STATUS := fix_status ) ;
    IF ( fix_status = ok ) THEN resp_offset[Px_quant] := act_resp[Px_quant] ;
  END ;

  IF ( low_twr_typ <> hig_twr_typ ) THEN 
  IF ( act_resp[Py_quant] <> resp_offset[Py_quant] )
  THEN BEGIN
    fix_status := error_found ;
    handle_trc_err ( TAG := 'HRD/TST%'+testtag,
                 MESSAGE := ' Py initial global count is ' + CONVERT(STRING,act_resp[Py_quant])
                          + ' instead of ' + CONVERT(STRING,resp_offset[Py_quant]) ) ;
    display_cat_inputs ( Py_quant ) ;
    inquire_fix_it ( STATUS := fix_status ) ;
    IF ( fix_status = ok ) THEN resp_offset[Py_quant] := act_resp[Py_quant] ;
  END ;

END ;
{ *************************************************************************** }
{ *************************************************************************** }
[INLINE]
PROCEDURE 
compare_actual_to_expected ( Px_Sign, Py_Sign : Momentum_sign ;
                         VAR status : status_type ) ;
BEGIN

  status := ok ;

  IF ( low_twr_typ = EMEtZ0 ) THEN 
  IF ( (act_resp[EM_quant] + t1_trunc[EM_quant])
    <> (resp_offset[EM_quant] + exp_resp[EM_quant]) )
  THEN BEGIN
    handle_trc_err ( TAG := 'HRD/TST%'+testtag,
                 MESSAGE := ' EM PROM answer is ' + CONVERT(STRING,act_resp[EM_quant]-resp_offset[EM_quant]+t1_trunc[EM_quant])
                          + ' i.of ' + CONVERT(STRING,exp_resp[EM_quant])
                          + ' global is ' + CONVERT(STRING,act_resp[EM_quant]) 
                          + ' T1 trunc ' + CONVERT(STRING,t1_trunc[EM_quant]) ) ;
    display_cat_inputs ( EM_quant ) ;
    status := error_found ;
  END ;

  IF ( hig_twr_typ = HDEtZ0 ) THEN 
  IF ( (act_resp[HD_quant] + t1_trunc[HD_quant]) 
    <> (resp_offset[HD_quant] + exp_resp[HD_quant]) )
  THEN BEGIN
    handle_trc_err ( TAG := 'HRD/TST%'+testtag,
                 MESSAGE := ' HD PROM answer is ' + CONVERT(STRING,act_resp[HD_quant]-resp_offset[HD_quant]+t1_trunc[HD_quant])
                          + ' instead of ' + CONVERT(STRING,exp_resp[HD_quant])
                          + ' global is now ' + CONVERT(STRING,act_resp[HD_quant]) 
                          + ' T1 trunc ' + CONVERT(STRING,t1_trunc[HD_quant]) ) ;
    display_cat_inputs ( HD_quant ) ;
    status := error_found ;
  END ;

  IF ( low_twr_typ <> hig_twr_typ ) 
  THEN BEGIN

    IF ( Px_sign = Pos_M ) 
    THEN IF ( (act_resp[Px_quant] + t1_trunc[Px_quant]) 
           <> (resp_offset[Px_quant] + exp_resp[Px_quant]) ) 
    THEN BEGIN
      handle_trc_err ( TAG := 'HRD/TST%'+testtag,
                   MESSAGE := ' Px PROM answer is ' + CONVERT(STRING,act_resp[Px_quant]-resp_offset[Px_quant]+t1_trunc[Px_quant])
                            + ' instead of ' + CONVERT(STRING,exp_resp[Px_quant])
                            + ' global is now ' + CONVERT(STRING,act_resp[Px_quant]) 
                            + ' T1 trunc ' + CONVERT(STRING,t1_trunc[Px_quant]) ) ;
      display_cat_inputs ( Px_quant ) ;
      status := error_found ;
    END ;

    IF ( Px_sign = Neg_M ) 
    THEN IF ( (act_resp[Px_quant] + t1_trunc[Px_quant])
           <> (resp_offset[Px_quant] - exp_resp[Px_quant]) ) 
    THEN BEGIN
      handle_trc_err ( TAG := 'HRD/TST%'+testtag,
                   MESSAGE := ' Px PROM answer is ' + CONVERT(STRING,resp_offset[Px_quant]-act_resp[Px_quant]-t1_trunc[Px_quant])
                            + ' instead of ' + CONVERT(STRING,exp_resp[Px_quant])
                            + ' global is now ' + CONVERT(STRING,act_resp[Px_quant]) 
                            + ' T1 trunc ' + CONVERT(STRING,t1_trunc[Px_quant]) ) ;
      display_cat_inputs ( Px_quant ) ;
      status := error_found ;
    END ;

    IF ( Py_sign = Pos_M ) 
    THEN IF ( (act_resp[Py_quant] + t1_trunc[Py_quant])
           <> (resp_offset[Py_quant] + exp_resp[Py_quant]) ) 
    THEN BEGIN
      handle_trc_err ( TAG := 'HRD/TST%'+testtag,
                   MESSAGE := ' Py PROM answer is ' + CONVERT(STRING,act_resp[Py_quant]-resp_offset[Py_quant]+t1_trunc[Py_quant])
                            + ' instead of ' + CONVERT(STRING,exp_resp[Py_quant])
                            + ' global is now ' + CONVERT(STRING,act_resp[Py_quant]) 
                            + ' T1 trunc ' + CONVERT(STRING,t1_trunc[Py_quant]) ) ;
      display_cat_inputs ( Py_quant ) ;
      status := error_found ;
    END ;

    IF ( Py_sign = Neg_M ) 
    THEN IF ( (act_resp[Py_quant] + t1_trunc[Py_quant])
           <> (resp_offset[Py_quant] - exp_resp[Py_quant]) ) 
    THEN BEGIN
      handle_trc_err ( TAG := 'HRD/TST%'+testtag,
                   MESSAGE := ' Py PROM answer is ' + CONVERT(STRING,resp_offset[Py_quant]-act_resp[Py_quant]-t1_trunc[Py_quant])
                            + ' instead of ' + CONVERT(STRING,exp_resp[Py_quant])
                            + ' global is now ' + CONVERT(STRING,act_resp[Py_quant]) 
                            + ' T1 trunc ' + CONVERT(STRING,t1_trunc[Py_quant]) ) ;
      display_cat_inputs ( Py_quant ) ;
      status := error_found ;
    END ;
  END ;

END ;
{ *************************************************************************** }
{ *************************************************************************** }
PROCEDURE display_cat_inputs ( quantity : constructed_quantities ) ;
VAR
  cat_address :^cat2_card ;
  rel_phi     : relative_phi ;
  cat_input   :  ARRAY [relp_0..relp_7] OF INTEGER ;
BEGIN

  CASE quantity OF
    EM_quant : cat_address := ADDRESS(cat2_EME_t1[pol_cell,eta_cell,phi_cell]::cat2_card) ;
    HD_quant : cat_address := ADDRESS(cat2_HDE_t1[pol_cell,eta_cell,phi_cell]::cat2_card) ;
    Px_quant : cat_address := ADDRESS(cat2_PxM_t1[pol_cell,eta_cell,phi_cell]::cat2_card) ;
    Py_quant : cat_address := ADDRESS(cat2_PyM_t1[pol_cell,eta_cell,phi_cell]::cat2_card) ;
  END ;

  FOR rel_phi := relp_0 TO relp_7
  DO examine_cat2_operand ( TAGEXT := testtag,
                              CARD := cat_address,
                            OP_NUM := ORD(rel_phi)+1,
                          OP_VALUE := cat_input[rel_phi],
                             IOPAR := iotest ) ;

  handle_trc_err ( TAG := 'HRD/TST%'+testtag,
               MESSAGE := ' ' + CONVERT(STRING(2),quantity)
                        + ' CAT inputs are'
                        + ' ' + CONVERT(STRING(4),cat_input[relp_0])
                        + ',' + CONVERT(STRING(4),cat_input[relp_1])
                        + ',' + CONVERT(STRING(4),cat_input[relp_2])
                        + ',' + CONVERT(STRING(4),cat_input[relp_3])
                        + ',' + CONVERT(STRING(4),cat_input[relp_4])
                        + ',' + CONVERT(STRING(4),cat_input[relp_5])
                        + ',' + CONVERT(STRING(4),cat_input[relp_6])
                        + ',' + CONVERT(STRING(4),cat_input[relp_7]) ) ;

END ;
{ *************************************************************************** }
{ *************************************************************************** }
[INLINE]
PROCEDURE increase_offsets ( Px_Sign, Py_Sign : Momentum_sign ) ;
BEGIN

  resp_offset[EM_quant] := resp_offset[EM_quant] + exp_resp[EM_quant] ;
  resp_offset[HD_quant] := resp_offset[HD_quant] + exp_resp[HD_quant] ;

  CASE Px_Sign OF
    pos_m : resp_offset[Px_quant] := resp_offset[Px_quant] + exp_resp[Px_quant] ;
    neg_m : resp_offset[Px_quant] := resp_offset[Px_quant] - exp_resp[Px_quant] ;
  END ;

  CASE Py_Sign OF
    pos_m : resp_offset[Py_quant] := resp_offset[Py_quant] + exp_resp[Py_quant] ;
    neg_m : resp_offset[Py_quant] := resp_offset[Py_quant] - exp_resp[Py_quant] ;
  END ;

END ;
{ *************************************************************************** }
[INLINE]
PROCEDURE decrease_offsets ( Px_Sign, Py_Sign : Momentum_sign ) ;
BEGIN

  resp_offset[EM_quant] := resp_offset[EM_quant] - exp_resp[EM_quant] ;
  resp_offset[HD_quant] := resp_offset[HD_quant] - exp_resp[HD_quant] ;

  CASE Px_Sign OF
    pos_m : resp_offset[Px_quant] := resp_offset[Px_quant] - exp_resp[Px_quant] ;
    neg_m : resp_offset[Px_quant] := resp_offset[Px_quant] + exp_resp[Px_quant] ;
  END ;

  CASE Py_Sign OF
    pos_m : resp_offset[Py_quant] := resp_offset[Py_quant] - exp_resp[Py_quant] ;
    neg_m : resp_offset[Py_quant] := resp_offset[Py_quant] + exp_resp[Py_quant] ;
  END ;

END ;
{ *************************************************************************** }
{ *************************************************************************** }
[INLINE]
PROCEDURE increase_tier1_quant ( pol_cell : eta_polarity ;
                                 eta_cell : magn_eta_per_fe_cell ;
                                 phi_cell : phi_per_fe_half_cell ) ;
BEGIN

  t1_sum[pol_cell,eta_cell,phi_cell,EM_quant] 
        := t1_sum[pol_cell,eta_cell,phi_cell,EM_quant] + exp_resp[EM_quant] ;
  t1_sum[pol_cell,eta_cell,phi_cell,HD_quant]
        := t1_sum[pol_cell,eta_cell,phi_cell,HD_quant] + exp_resp[HD_quant] ;
  t1_sum[pol_cell,eta_cell,phi_cell,Px_quant]
        := t1_sum[pol_cell,eta_cell,phi_cell,Px_quant] + exp_resp[Px_quant] ;
  t1_sum[pol_cell,eta_cell,phi_cell,Py_quant]
        := t1_sum[pol_cell,eta_cell,phi_cell,Py_quant] + exp_resp[Py_quant] ;

END ;
{ *************************************************************************** }
[INLINE]
PROCEDURE decrease_tier1_quant ( pol_cell : eta_polarity ;
                                 eta_cell : magn_eta_per_fe_cell ;
                                 phi_cell : phi_per_fe_half_cell ) ;
BEGIN

  t1_sum[pol_cell,eta_cell,phi_cell,EM_quant] 
        := t1_sum[pol_cell,eta_cell,phi_cell,EM_quant] - exp_resp[EM_quant] ;
  t1_sum[pol_cell,eta_cell,phi_cell,HD_quant]
        := t1_sum[pol_cell,eta_cell,phi_cell,HD_quant] - exp_resp[HD_quant] ;
  t1_sum[pol_cell,eta_cell,phi_cell,Px_quant]
        := t1_sum[pol_cell,eta_cell,phi_cell,Px_quant] - exp_resp[Px_quant] ;
  t1_sum[pol_cell,eta_cell,phi_cell,Py_quant]
        := t1_sum[pol_cell,eta_cell,phi_cell,Py_quant] - exp_resp[Py_quant] ;

END ;
{ *************************************************************************** }
[INLINE]
PROCEDURE find_t1_truncation ;
TYPE

  extract_bit13 = [LONG]
  PACKED RECORD
    first12 : 0..4095 ;
    bit13   : [POS(12)] bit ;
    unused  : 0..524287 ;
  END ;

VAR
  tmp_e_c : magn_eta_per_fe_cell ;
  tmp_p_c : phi_per_fe_half_cell ;
  tmp_s_c : eta_polarity ;
  t1_temp : extract_bit13 ;
  tmp_Pxs : Momentum_sign ;
  tmp_pys : Momentum_sign ;

BEGIN

  t1_trunc := ZERO ;

  FOR    tmp_s_c := low_eta_pol TO hig_eta_pol
  DO FOR tmp_e_c := CONVERT(magn_eta_per_fe_cell, (ORD(low_eta_mag)-1) DIV 4 )
                 TO CONVERT(magn_eta_per_fe_cell, (ORD(hig_eta_mag)-1) DIV 4 )
  DO FOR tmp_p_c := CONVERT( phi_per_fe_half_cell, (ORD(low_phi)-1) DIV 8 )
                 TO CONVERT( phi_per_fe_half_cell, (ORD(hig_phi)-1) DIV 8 )
  DO BEGIN

    t1_temp::INTEGER := t1_sum[tmp_s_c,tmp_e_c,tmp_p_c,EM_quant];

    IF ( t1_temp.bit13 <> 0 ) THEN t1_trunc[EM_quant] := t1_trunc[EM_quant] + 4096 ;

    t1_temp::INTEGER := t1_sum[tmp_s_c,tmp_e_c,tmp_p_c,HD_quant];
    IF ( t1_temp.bit13 <> 0 ) THEN t1_trunc[HD_quant] := t1_trunc[HD_quant] + 4096 ;

    t1_temp::INTEGER := t1_sum[tmp_s_c,tmp_e_c,tmp_p_c,Px_quant] ;
    IF ( t1_temp.bit13 <> 0 ) 
    THEN CASE tmp_p_c OF 
        p_1_8,  p_25_32 : t1_trunc[Px_quant] := t1_trunc[Px_quant] + 4096 ; {Px Positive} 
        p_9_16, p_17_24 : t1_trunc[Px_quant] := t1_trunc[Px_quant] - 4096 ; {Px Negative}
    END ;

    t1_temp::INTEGER := t1_sum[tmp_s_c,tmp_e_c,tmp_p_c,Py_quant] ;
    IF ( t1_temp.bit13 <> 0 ) 
    THEN CASE tmp_p_c OF 
        p_1_8,   p_9_16  : t1_trunc[Py_quant] := t1_trunc[Py_quant] + 4096 ; {Py Positive} 
        p_17_24, p_25_32 : t1_trunc[Py_quant] := t1_trunc[Py_quant] - 4096 ; {Py Negative}
    END ;

  END ;

 {See if we may cross the truncation boundary while ramping this channel}
   {To cross the boundary while testing this channel, }
   {we need to already be close engough to the 4096 boundary }

  watch_t1_trunc := ZERO ;

  IF ( ( t1_sum[pol_cell,eta_cell,phi_cell,EM_quant] < 4096 )
   AND ( t1_sum[pol_cell,eta_cell,phi_cell,EM_quant] >= (4096 - 256) ) )
  THEN watch_t1_trunc[EM_quant] := TRUE ;

  IF ( ( t1_sum[pol_cell,eta_cell,phi_cell,HD_quant] < 4096 )
   AND ( t1_sum[pol_cell,eta_cell,phi_cell,HD_quant] >= (4096 - 256) ) )
  THEN watch_t1_trunc[HD_quant] := TRUE ;

  IF ( ( t1_sum[pol_cell,eta_cell,phi_cell,Px_quant] < 4096 )
   AND ( t1_sum[pol_cell,eta_cell,phi_cell,Px_quant] >= (4096 - 256) ) )
  THEN watch_t1_trunc[Px_quant] := TRUE ;

  IF ( ( t1_sum[pol_cell,eta_cell,phi_cell,Py_quant] < 4096 )
   AND ( t1_sum[pol_cell,eta_cell,phi_cell,Py_quant] >= (4096 - 256) ) )
  THEN watch_t1_trunc[Py_quant] := TRUE ;


END ;
{ *************************************************************************** }
[INLINE]
PROCEDURE check_t1_trunc_crossing ( Px_Sign, Py_Sign : Momentum_sign ) ;
BEGIN

  IF ( watch_t1_trunc[EM_quant] = TRUE ) 
  THEN IF ( (t1_sum[pol_cell,eta_cell,phi_cell,EM_quant] + exp_resp[EM_quant])
           >= 4096 )
  THEN BEGIN
    t1_trunc[EM_quant] := t1_trunc[EM_quant] + 4096 ;
    watch_t1_trunc[EM_quant] := FALSE ;
  END ;  

  IF ( watch_t1_trunc[HD_quant] = TRUE ) 
  THEN IF ( (t1_sum[pol_cell,eta_cell,phi_cell,HD_quant] + exp_resp[HD_quant])
           >= 4096 )
  THEN BEGIN
    t1_trunc[HD_quant] := t1_trunc[HD_quant] + 4096 ;
    watch_t1_trunc[HD_quant] := FALSE ;
  END ;  

  IF ( watch_t1_trunc[Px_quant] = TRUE ) 
  THEN IF ( (t1_sum[pol_cell,eta_cell,phi_cell,Px_quant] + exp_resp[Px_quant])
           >= 4096 )
  THEN BEGIN
    CASE Px_Sign OF
      pos_m : t1_trunc[Px_quant] := t1_trunc[Px_quant] + 4096 ;
      neg_m : t1_trunc[Px_quant] := t1_trunc[Px_quant] - 4096 ;
    END ;
    watch_t1_trunc[Px_quant] := FALSE ;
  END ;  

  IF ( watch_t1_trunc[Py_quant] = TRUE ) 
  THEN IF ( (t1_sum[pol_cell,eta_cell,phi_cell,Py_quant] + exp_resp[Py_quant])
           >= 4096 )
  THEN BEGIN
    CASE Py_Sign OF
      pos_m : t1_trunc[Py_quant] := t1_trunc[Py_quant] + 4096 ;
      neg_m : t1_trunc[Py_quant] := t1_trunc[Py_quant] - 4096 ;
    END ;
    watch_t1_trunc[Py_quant] := FALSE ;
  END ;  

END ;
{ *************************************************************************** }
END .
