{ *************************************************************************** } MODULE mod_handle_trgtwr ; { Created 11-MAY-1989 MICHIGAN STATE UNIVERSITY, TRIGGER CONTROL SOFTWARE } { *************************************************************************** } INCLUDE mod_common_global_flags, mod_def_hardware_tables, mod_def_physics_tables, mod_handle_tracing, mod_handle_result_files, mod_handle_registers, mod_handle_cat_cards, mod_common_hard_io ; {from the TRICS hardware IO library } { *************************************************************************** } EXPORT set_trgtwr_ref, {PROCEDURE program trg twr ref and update object data base} Set_LgTile_Ref, {PROCEDURE program Lg Tile Ref and update object data base} set_trgtwr_simu, {PROCEDURE program trg twr simu data and update obj dbase } change_trgtwr_simu, {PROCEDURE similar to above, when already in simu mode } load_trgtwr_DAC, {PROCEDURE load trigger tower pedestal DAC byte } find_DAC_byte, {PROCEDURE finds DAC byte for maximum histogram at zeresp } MeV_to_GeV_str ; {FUNCTION returns a string after scaling MeV to GeV } { *************************************************************************** } IMPORT status_type, ok,{already_done,}io_failure, not_found, {from module MOD_COMMON_GLOBAL_FLAGS } trace_info,{trace_warn,}trace_error,{from module MOD_HANDLE_TRACING } inline_tracing, {from module MOD_HANDLE_TRACING } handle_trc_inf, {from module MOD_HANDLE_TRACING } handle_trc_sta, {from module MOD_HANDLE_TRACING } handle_trc_sys, {from module MOD_HANDLE_TRACING } handle_trc_err, {from module MOD_HANDLE_TRACING } set_trc_exc_mode, {from module MOD_HANDLE_TRACING } result_file_record, {from module MOD_HANDLE_RESULT_FILES } open_result_file, {from module MOD_HANDLE_RESULT_FILES } close_result_file, {from module MOD_HANDLE_RESULT_FILES } handle_write_result, {from module MOD_HANDLE_RESULT_FILES } cbus_register, {from module MOD_DEF_HARDWARE_TABLES } eta_polarity, {from module MOD_DEF_HARDWARE_TABLES } eta_magnitude, {from module MOD_DEF_HARDWARE_TABLES } phi_value, {from module MOD_DEF_HARDWARE_TABLES } magn_eta_per_fe_cell, {from module MOD_DEF_HARDWARE_TABLES } phi_per_fe_half_cell, {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 } comparison_number, {from module MOD_DEF_HARDWARE_TABLES } relative_eta, rele_0, rele_1, rele_2, rele_3, adc_data_type_per_ctfe_channel, EMEtZ0, HDEtZ0, {lookup_data_topic,}Et,{L2, P,} {from module MOD_DEF_HARDWARE_TABLES } EM_PROM, HD_PROM, {from module MOD_DEF_HARDWARE_TABLES } {prom_page_value,} prom_page_1, {cat2_bit_field,}bit_0_5, {from module MOD_DEF_HARDWARE_TABLES } ctfe_card_low_half, {from module MOD_DEF_HARDWARE_TABLES } ctfe_card_high_half, {from module MOD_DEF_HARDWARE_TABLES } ctfe_data, {from module MOD_DEF_HARDWARE_TABLES } ctfe_ctrl, {from module MOD_DEF_HARDWARE_TABLES } cat2_card, {from module MOD_DEF_HARDWARE_TABLES } cat2_PxM_t1, cat2_PyM_t1, {from module MOD_DEF_HARDWARE_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 } update_register, {from module MOD_HANDLE_REGISTERS } {examine_register, {from module MOD_HANDLE_REGISTERS } histogram_register, {from module MOD_HANDLE_REGISTERS } load_cat2_threshold, {FROM MODULE MOD_HANDLE_CAT_CARDS } array_0_255, {from module MOD_COMMON_HARD_IO } cbus_param_list ; {from module MOD_COMMON_HARD_IO } { *************************************************************************** } { *************************************************************************** } TYPE bit = [BIT(1)] 0..1 ; byte = [BYTE] 0..255 ; VAR tag : VARYING_STRING(8) := 'HTT/ODB%' ; { **************************************************************************** } { ***************************************************************************** } PROCEDURE set_trgtwr_ref ( tagext : VARYING_STRING(8) := '' ; eta_pol : eta_polarity ; eta_mag : eta_magnitude ; phi_val : phi_value ; ref_typ : threshold_reference_set_type ; ref_num : threshold_reference_set_number ; energy_threshold : INTEGER := -1 ; byte_threshold : INTEGER := 0 ; iopar :^cbus_param_list ; VAR status : [OPTIONAL] status_type ) ; VAR e_fe : magn_eta_per_fe_cell ; rele : relative_eta ; p_ctfe_ctrl :^ctfe_card_high_half ; p_ctfe_ref_reg :^cbus_register ; p_trgtwr :^cal_trig_tower ; io_status : status_type ; BEGIN IF PRESENT(status) THEN status := ok ; e_fe := CONVERT ( magn_eta_per_fe_cell, (ORD(eta_mag)-1) DIV 4 ) ; rele := CONVERT ( relative_eta, (ORD(eta_mag)-1) MOD 4 ) ; p_ctfe_ctrl := ADDRESS ( ctfe_ctrl[eta_pol,e_fe,phi_val] ) ; p_ctfe_ref_reg := ADDRESS ( p_ctfe_ctrl^.thrreg[rele,ref_typ,ref_num] ) ; p_trgtwr := trgtwr[eta_pol,eta_mag,phi_val] ; IF ( ( energy_threshold >= 0 ) AND ( p_trgtwr^.lookup_scale[Et] <> 0 ) ) THEN BEGIN { *** change scale MeV to LSB of ADC *** } byte_threshold := ROUND ( energy_threshold / p_trgtwr^.lookup_scale[Et] ) ; { *** put in the correction for zero energy response *** } { *** and for the fact that the lower bit of TOT Et is dropped *** } CASE ref_typ OF EMEt_ref : byte_threshold := byte_threshold + p_trgtwr^.lookup[EM_PROM,PROM_page_1].zeresp ; HDEt_veto : byte_threshold := byte_threshold + p_trgtwr^.lookup[HD_PROM,PROM_page_1].zeresp ; TOTEt_ref : byte_threshold := ( byte_threshold + p_trgtwr^.lookup[EM_PROM,PROM_page_1].zeresp + p_trgtwr^.lookup[HD_PROM,PROM_page_1].zeresp ) DIV 2 ; END ; { *** all hardware comparisons are exclusive, *** } { *** decrement to allow this computed threshold value to pass *** } byte_threshold := byte_threshold - 1 ; { *** take care of saturation problems, before writing register *** } IF ( byte_threshold < 0 ) THEN byte_threshold := 0 ; IF ( byte_threshold > 255 ) THEN byte_threshold := 255 ; END ; energy_threshold := byte_threshold + 1 ; CASE ref_typ OF EMEt_ref : energy_threshold := energy_threshold - p_trgtwr^.lookup[EM_PROM,PROM_page_1].zeresp ; HDEt_veto : energy_threshold := energy_threshold - p_trgtwr^.lookup[HD_PROM,PROM_page_1].zeresp ; TOTEt_ref : energy_threshold := 2 * ( energy_threshold - ( p_trgtwr^.lookup[EM_PROM,PROM_page_1].zeresp + p_trgtwr^.lookup[HD_PROM,PROM_page_1].zeresp ) DIV 2 ) ; END ; energy_threshold := energy_threshold * p_trgtwr^.lookup_scale[Et] ; IF ( inline_tracing(trace_info) <> 0 ) THEN handle_trc_inf ( TAG := tag + tagext, MESSAGE := ' Set Twr Thrsh' + ' ' + CONVERT(STRING(3),eta_pol) + ',' + CONVERT(STRING,eta_mag) + ',' + CONVERT(STRING,phi_val) + ' ' + CONVERT(STRING,ref_typ) + ',' + CONVERT(STRING,ref_num) + ' to' + ' ' + CONVERT(STRING,byte_threshold) + ' = ' + MeV_to_GeV_str(energy_threshold) + ' GeV' ) ; update_register ( TAGEXT := tagext, CARD := p_ctfe_ctrl, REGISTER := p_ctfe_ref_reg, IOPAR := iopar, DATA := byte_threshold, STATUS := io_status ) ; IF ( io_status = io_failure ) THEN BEGIN IF ( inline_tracing(trace_error) <> 0 ) THEN handle_trc_err ( TAG := tag + tagext, MESSAGE := ' Failure Programming Trig Tower' + ' ' + CONVERT(STRING(3),eta_pol) + ',' + CONVERT(STRING,eta_mag) + ',' + CONVERT(STRING,phi_val) + ' ' + CONVERT(STRING,ref_typ) + ',' + CONVERT(STRING,ref_num) ) ; IF PRESENT(status) THEN status := io_status ; END ; IF ( byte_threshold <> 255 ) THEN p_trgtwr^.threshold[ref_num,ref_typ] := energy_threshold ELSE {1,000 GeV as flag to TRGMON that this is full scale } {Note: The ability to recover the programming from this value isn't lost.} {Calling this routine again with this value will produce the same result.} p_trgtwr^.threshold[ref_num,ref_typ] := 1000000 ; END ; { **************************************************************************** } { ***************************************************************************** } PROCEDURE Set_LgTile_Ref ( tagext : VARYING_STRING(8) := '' ; eta_pol : eta_polarity ; lt_eta : magn_eta_per_fe_cell ; lt_phi : phi_per_fe_half_cell ; ref_num : threshold_reference_set_number ; energy_threshold : INTEGER := -1 ; count_threshold : INTEGER := 0 ; iopar :^cbus_param_list ; VAR status : [OPTIONAL] status_type ) ; VAR rel_cmp : comparison_number ; p_t1_cat2 :^cat2_card ; p_cmp_reg :^cbus_register ; p_LgTile :^Cal_Large_Tile ; io_status : status_type ; BEGIN IF PRESENT(status) THEN status := ok ; rel_cmp := CONVERT ( comparison_number, ORD(ref_num) MOD 4 ) ; IF ( (ORD(ref_num) DIV 4) = 0 ) THEN p_t1_cat2 := ADDRESS( cat2_PyM_t1[eta_pol,lt_eta,lt_phi]::cat2_card ) ELSE p_t1_cat2 := ADDRESS( cat2_PxM_t1[eta_pol,lt_eta,lt_phi]::cat2_card ); p_cmp_reg := ADDRESS( p_t1_cat2^.compreg[rel_cmp,bit_0_5] ) ; p_LgTile := LgTile[eta_pol,lt_eta,lt_phi] ; IF ( energy_threshold >= 0 ) THEN BEGIN { *** change scale MeV to LSB of Large Tile Count *** } { *** and put in the correction for zero energy response *** } count_threshold := ROUND ( energy_threshold / p_LgTile^.energy_scale ) + p_LgTile^.zeresp ; { *** take care of saturation problems, before writing register *** } IF ( count_threshold < 0 ) THEN count_threshold := 0 ; IF ( count_threshold > 4*8*255 ) THEN count_threshold := 4*8*255 + 1 ; END ; energy_threshold := ( count_threshold - p_LgTile^.zeresp ) * p_LgTile^.energy_scale ; IF ( inline_tracing(trace_info) <> 0 ) THEN handle_trc_inf ( TAG := tag + tagext, MESSAGE := ' Set Lrg Tile Thrsh' + ' ' + CONVERT(STRING(3),eta_pol) + ',' + CONVERT(STRING,lt_eta) + ',' + CONVERT(STRING,lt_phi) + ',' + CONVERT(STRING,ref_num) + ' to' + ' ' + CONVERT(STRING,count_threshold) + ' = ' + MeV_to_GeV_str(energy_threshold) + ' GeV' ) ; load_cat2_threshold ( TAGEXT := tagext, CARD := p_t1_cat2, REGISTER := p_cmp_reg, IOPAR := iopar, THRESHOLD := count_threshold, STATUS := io_status ) ; IF ( io_status = io_failure ) THEN BEGIN IF ( inline_tracing(trace_error) <> 0 ) THEN handle_trc_err ( TAG := tag + tagext, MESSAGE := ' Failure Programming Lrg Tile' + ' ' + CONVERT(STRING(3),eta_pol) + ',' + CONVERT(STRING,lt_eta) + ',' + CONVERT(STRING,lt_phi) + ',' + CONVERT(STRING,ref_num) ) ; IF PRESENT(status) THEN status := io_status ; END ; IF ( count_threshold < 4*8*255 ) THEN p_LgTile^.threshold[ref_num] := energy_threshold ELSE {10,000 GeV as flag to TRGMON that this is full scale } {Note: The ability to recover the programming from this value isn't lost.} {Calling this routine again with this value will produce the same result.} p_LgTile^.threshold[ref_num] := 10000000 ; quit_set_lgtile_ref: END ; { **************************************************************************** } { **************************************************************************** } PROCEDURE set_trgtwr_simu ( tagext : VARYING_STRING(8) := '' ; eta_pol : eta_polarity ; eta_mag : eta_magnitude ; phi_val : phi_value ; twr_typ : adc_data_type_per_ctfe_channel ; simu_state : BOOLEAN := TRUE ; simu_byte : byte := 0 ; simu_energy : INTEGER := -1 ; iopar :^cbus_param_list ; VAR status : [OPTIONAL] status_type ) ; {******************************************************************************} {* This routine may be called from 2 different contexts, *} {* 1) when COOR asks to EXCLUDE or de-EXCLUDE a tower *} {* The procedure temporarily puts the ctfe card in simu mode *} {* It will restore other channels to normal mode if needed. *} {* 2) when running diagnostics to load a simu value bypassing the ADC *} {* The procedure will update manually update the particular channel *} {* and leave the other simulation values unchanged. *} {* *} {* The Timing signals need not be running as the routine will manually pulse *} {* the ADC clock. That also means that the simu byte is effective immediately *} {* (as opposed to change_trgtwr_simu below) *} {******************************************************************************} VAR e_fe : magn_eta_per_fe_cell ; rele : relative_eta ; p_ctfe_ctrl :^ctfe_card_high_half ; p_trgtwr :^cal_trig_tower ; step_status : status_type ; glob_status : status_type ; prev_load_mask : byte ; updt_twr_mask : byte ; prev_brdctrl : byte ; BEGIN IF PRESENT(status) THEN status := ok ; glob_status := ok ; e_fe := CONVERT ( magn_eta_per_fe_cell, (ORD(eta_mag)-1) DIV 4 ) ; rele := CONVERT ( relative_eta, (ORD(eta_mag)-1) MOD 4 ) ; p_ctfe_ctrl := ADDRESS ( ctfe_ctrl[eta_pol,e_fe,phi_val] ) ; p_trgtwr := trgtwr[eta_pol,eta_mag,phi_val] ; updt_twr_mask := inline_set_bit_in_chan_ctrl ( twr_typ, rele ) ; IF ( simu_state = TRUE ) THEN BEGIN IF ( simu_energy > 0 ) THEN simu_byte := ROUND ( simu_energy / p_trgtwr^.adc_scale ) + p_trgtwr^.adconv[twr_typ].zeresp ELSE simu_energy := ( simu_byte - p_trgtwr^.adconv[twr_typ].zeresp ) * p_trgtwr^.adc_scale ; IF ( inline_tracing(trace_info) <> 0 ) THEN handle_trc_inf ( TAG := tag + tagext, MESSAGE := ' Set Tower Simu' + ' ' + CONVERT(STRING(3),eta_pol) + ',' + CONVERT(STRING,eta_mag) + ',' + CONVERT(STRING,phi_val) + ' ' + CONVERT(STRING,twr_typ) + ' to' + ' ' + CONVERT(STRING,simu_byte) + ' =' + MeV_to_GeV_str(simu_energy) + ' GeV' ) ; prev_load_mask := p_ctfe_ctrl^.chanctrl.content ; {remember previous mask} update_register ( TAGEXT := tagext, CARD := p_ctfe_ctrl, REGISTER := ADDRESS(p_ctfe_ctrl^.chanctrl), IOPAR := iopar, DATA := updt_twr_mask, {only this channel updated @TSS } STATUS := step_status ) ; IF ( step_status = io_failure ) THEN glob_status := io_failure ; prev_brdctrl := p_ctfe_ctrl^.brdctrl.content ; IF ( prev_brdctrl <> 128 ) THEN BEGIN update_register ( TAGEXT := tagext, CARD := p_ctfe_ctrl, REGISTER := ADDRESS(p_ctfe_ctrl^.brdctrl), IOPAR := iopar, DATA := 128, {load simu byte mode} STATUS := step_status ) ; IF ( step_status = io_failure ) THEN glob_status := io_failure ; END ; update_register ( TAGEXT := tagext, CARD := p_ctfe_ctrl, REGISTER := ADDRESS(p_ctfe_ctrl^.loadsimreg), IOPAR := iopar, DATA := simu_byte, {write simu byte} STATUS := step_status ) ; IF ( step_status = io_failure ) THEN glob_status := io_failure ; {find if any OTHER towers were updated before modifying this one} updt_twr_mask := inline_byte_and ( prev_load_mask, 255 - updt_twr_mask ) ; {force a clock pulse before clearing changing update control register } {that is for the case were the MTG are in simgle shot mode } update_register ( TAGEXT := tagext, CARD := p_ctfe_ctrl, REGISTER := ADDRESS(p_ctfe_ctrl^.brdctrl), IOPAR := iopar, DATA := 128 + 2, {force ADC clock HIGH} STATUS := step_status ) ; IF ( step_status = io_failure ) THEN glob_status := io_failure ; update_register ( TAGEXT := tagext, CARD := p_ctfe_ctrl, REGISTER := ADDRESS(p_ctfe_ctrl^.brdctrl), IOPAR := iopar, DATA := 128, {return ADC clock to normal mode} STATUS := step_status ) ; IF ( step_status = io_failure ) THEN glob_status := io_failure ; {return to previous mode if necessary to keep OTHER towers updated by ADC } {or stay in simu mode if NO OTHER tower is updated anyway } IF ( ( prev_brdctrl <> 128 ) AND ( updt_twr_mask <> 0 ) ) THEN BEGIN update_register ( TAGEXT := tagext, CARD := p_ctfe_ctrl, REGISTER := ADDRESS(p_ctfe_ctrl^.chanctrl), IOPAR := iopar, DATA := updt_twr_mask, {restore OTHER updated chan} STATUS := step_status ) ; IF ( step_status = io_failure ) THEN glob_status := io_failure ; update_register ( TAGEXT := tagext, CARD := p_ctfe_ctrl, REGISTER := ADDRESS(p_ctfe_ctrl^.brdctrl), IOPAR := iopar, DATA := prev_brdctrl, {restore board control mode} STATUS := step_status ) ; END {the whole card is in simu mode, so that no channel are now updated} ELSE update_register ( TAGEXT := tagext, CARD := p_ctfe_ctrl, REGISTER := ADDRESS(p_ctfe_ctrl^.chanctrl), IOPAR := iopar, DATA := 0, {NO channel updated} STATUS := step_status ) ; IF ( step_status = io_failure ) THEN glob_status := io_failure ; {record in data base that this tower is now in simu mode} p_trgtwr^.adconv[twr_typ].simu_state := TRUE ; p_trgtwr^.adconv[twr_typ].simu_value := simu_byte ; END ELSE BEGIN {cancel simulation mode} IF ( inline_tracing(trace_info) <> 0 ) THEN handle_trc_inf ( TAG := tag + tagext, MESSAGE := ' Setting Tower' + ' ' + CONVERT(STRING(3),eta_pol) + ',' + CONVERT(STRING,eta_mag) + ',' + CONVERT(STRING,phi_val) + ' ' + CONVERT(STRING,twr_typ) + ' to use ADC Data' ) ; prev_brdctrl := p_ctfe_ctrl^.brdctrl.content ; IF ( prev_brdctrl <> 129 ) THEN BEGIN update_register ( TAGEXT := tagext, CARD := p_ctfe_ctrl, REGISTER := ADDRESS(p_ctfe_ctrl^.brdctrl), IOPAR := iopar, DATA := 129, {ADC data, simu reg in load mode} STATUS := step_status ) ; IF ( step_status = io_failure ) THEN glob_status := io_failure ; update_register ( TAGEXT := tagext, CARD := p_ctfe_ctrl, REGISTER := ADDRESS(p_ctfe_ctrl^.chanctrl), IOPAR := iopar, DATA := 0, {clear simu register (~~extra safety~~)} STATUS := step_status ) ; IF ( step_status = io_failure ) THEN glob_status := io_failure ; END ; p_trgtwr^.adconv[twr_typ].simu_state := FALSE ; {add this tower to the already ADC-updated channels} prev_load_mask := p_ctfe_ctrl^.chanctrl.content ; updt_twr_mask := inline_byte_or ( prev_load_mask, updt_twr_mask ) ; update_register ( TAGEXT := tagext, CARD := p_ctfe_ctrl, REGISTER := ADDRESS(p_ctfe_ctrl^.chanctrl), IOPAR := iopar, DATA := updt_twr_mask, {select updated channels} STATUS := step_status ) ; IF ( step_status = io_failure ) THEN glob_status := io_failure ; END ; quit_set_trgtwr_simu : IF ( glob_status = io_failure ) THEN BEGIN IF PRESENT(status) THEN status := io_failure ; IF ( inline_tracing(trace_error) <> 0 ) THEN handle_trc_err ( TAG := tag + tagext, MESSAGE := ' Failure Programming Trig Tower Data Input' + ' ' + CONVERT(STRING(3),eta_pol) + ',' + CONVERT(STRING,eta_mag) + ',' + CONVERT(STRING,phi_val) + ' ' + CONVERT(STRING,twr_typ) ) ; END ; END ; { *************************************************************************** } { *************************************************************************** } PROCEDURE change_trgtwr_simu ( tagext : VARYING_STRING(8) := '' ; eta_pol : eta_polarity ; eta_mag : eta_magnitude ; phi_val : phi_value ; twr_typ : adc_data_type_per_ctfe_channel ; simu_byte : byte ; iopar :^cbus_param_list ; VAR status : [OPTIONAL] status_type ) ; {******************************************************************************} {* This routine is quicker than set_trgtwr_simu, *} {* 1) but the WHOLE card must already be in simu mode (i.e. brdctrl = 128) *} {* 2) but the data will ONLY be updated when the next ADC pulse occurs *} {* change_trgtwr_simu does not require the timing signals to be running *} {* DURING procedure execution (e.g single shot mode), *} {******************************************************************************} VAR e_fe : magn_eta_per_fe_cell ; rele : relative_eta ; p_ctfe_ctrl :^ctfe_card_high_half ; p_trgtwr :^cal_trig_tower ; step_status : status_type ; glob_status : status_type ; updt_twr_mask : byte ; BEGIN IF PRESENT(status) THEN status := ok ; e_fe := CONVERT ( magn_eta_per_fe_cell, (ORD(eta_mag)-1) DIV 4 ) ; rele := CONVERT ( relative_eta, (ORD(eta_mag)-1) MOD 4 ) ; p_ctfe_ctrl := ADDRESS ( ctfe_ctrl[eta_pol,e_fe,phi_val] ) ; p_trgtwr := trgtwr[eta_pol,eta_mag,phi_val] ; updt_twr_mask := inline_set_bit_in_chan_ctrl ( twr_typ, rele ) ; IF ( inline_tracing(trace_info) <> 0 ) THEN handle_trc_inf ( TAG := tag + tagext, MESSAGE := ' Set Tower Simu' + ' ' + CONVERT(STRING(3),eta_pol) + ',' + CONVERT(STRING,eta_mag) + ',' + CONVERT(STRING,phi_val) + ' ' + CONVERT(STRING,twr_typ) + ' to' + ' ' + CONVERT(STRING,simu_byte) ) ; {select new channel to be updated, previous channel remains at previous simu} update_register ( TAGEXT := tagext, CARD := p_ctfe_ctrl, REGISTER := ADDRESS(p_ctfe_ctrl^.chanctrl), IOPAR := iopar, DATA := updt_twr_mask, {this channel updated @TSS } STATUS := step_status ) ; IF ( step_status = io_failure ) THEN glob_status := io_failure ; {write new simu for newly selected channel} update_register ( TAGEXT := tagext, CARD := p_ctfe_ctrl, REGISTER := ADDRESS(p_ctfe_ctrl^.loadsimreg), IOPAR := iopar, DATA := simu_byte, {write simu byte} STATUS := step_status ) ; IF ( step_status = io_failure ) THEN glob_status := io_failure ; p_trgtwr^.adconv[twr_typ].simu_value := simu_byte ; quit_change_trgtwr_simu : IF ( glob_status = io_failure ) THEN BEGIN IF PRESENT(status) THEN status := io_failure ; IF ( inline_tracing(trace_error) <> 0 ) THEN handle_trc_err ( TAG := tag + tagext, MESSAGE := ' Failure Programming Trig Tower Data Input' + ' ' + CONVERT(STRING(3),eta_pol) + ',' + CONVERT(STRING,eta_mag) + ',' + CONVERT(STRING,phi_val) + ' ' + CONVERT(STRING,twr_typ) ) ; END ; END ; { *************************************************************************** } { *************************************************************************** } PROCEDURE load_trgtwr_DAC ( tagext : VARYING_STRING(8) := '' ; eta_pol : eta_polarity ; eta_mag : eta_magnitude ; phi_val : phi_value ; twr_typ : adc_data_type_per_ctfe_channel ; dac_byte : INTEGER := -1 ; iopar :^cbus_param_list ; VAR status : [OPTIONAL] status_type ) ; VAR e_fe : magn_eta_per_fe_cell ; rele : relative_eta ; p_ctfe_ctrl :^ctfe_card_high_half ; p_trgtwr :^cal_trig_tower ; io_status : status_type ; BEGIN IF PRESENT(status) THEN status := ok ; e_fe := CONVERT ( magn_eta_per_fe_cell, (ORD(eta_mag)-1) DIV 4 ) ; rele := CONVERT ( relative_eta, (ORD(eta_mag)-1) MOD 4 ) ; p_ctfe_ctrl := ADDRESS ( ctfe_ctrl[eta_pol,e_fe,phi_val] ) ; p_trgtwr := trgtwr[eta_pol,eta_mag,phi_val] ; IF ( dac_byte < 0 ) THEN dac_byte := p_trgtwr^.ADConv[twr_typ].dac_byte ; IF ( inline_tracing(trace_info) <> 0 ) THEN handle_trc_inf ( TAG := tag + tagext, MESSAGE := ' Load Trigger Tower DAC byte ' + ' ' + CONVERT(STRING(3),eta_pol) + ',' + CONVERT(STRING,eta_mag) + ',' + CONVERT(STRING,phi_val) + ' ' + CONVERT(STRING,twr_typ) + ' with' + ' ' + CONVERT(STRING,dac_byte) ) ; {write new simu for newly selected channel} update_register ( TAGEXT := tagext, CARD := p_ctfe_ctrl, REGISTER := ADDRESS(p_ctfe_ctrl^.pedreg[rele,twr_typ]), IOPAR := iopar, DATA := dac_byte, STATUS := io_status ) ; IF ( io_status = io_failure ) THEN BEGIN IF PRESENT(status) THEN status := io_status ; IF ( inline_tracing(trace_error) <> 0 ) THEN handle_trc_err ( TAG := tag + tagext, MESSAGE := ' Failure Loading DAC byte' + ' ' + CONVERT(STRING(3),eta_pol) + ',' + CONVERT(STRING,eta_mag) + ',' + CONVERT(STRING,phi_val) + ' ' + CONVERT(STRING,twr_typ) + ' with' + ' ' + CONVERT(STRING,dac_byte) ) ; END ; END ; { *************************************************************************** } { *************************************************************************** } PROCEDURE find_DAC_byte ( tagext : VARYING_STRING(8) := '' ; eta_pol : eta_polarity ; eta_mag : eta_magnitude ; phi_val : phi_value ; twr_typ : adc_data_type_per_ctfe_channel ; VAR result : byte ; iopar :^cbus_param_list ; result_file :^result_file_record := NIL ; result_open : INTEGER := 0 ; VAR status : [OPTIONAL] status_type ) ; CONST observed_spread = 16 ; { spread in dac_bytes, i.e. max dac byte for zeresp=0 } safety_margin = 5 ; { +/- 5 away from the expected range of value } dac_to_adc_ratio = 3 ; fast_search_sample_size = 10 ; deep_search_sample_size = 1000 ; three_time_const = -600000 ; { 0.06s = 3 time const = ADC settle within 5 % } TYPE search_stage_type = ( quick_search, deep_search ) ; VAR local_file : BOOLEAN := TRUE ; message : VARYING_STRING(132) ; msg_fix_part : VARYING_STRING(40) ; e_fe : magn_eta_per_fe_cell ; rele : relative_eta ; p_trgtwr :^cal_trig_tower ; p_ctfe_ctrl :^ctfe_card_high_half ; p_ctfe_data :^ctfe_card_low_half ; p_adc_reg :^cbus_register ; p_ped_reg :^cbus_register ; zeresp_goal : byte ; io_status : status_type ; sample_size : INTEGER ; search_min : byte ; search_max : byte ; search_stage : [BYTE] search_stage_type ; dac_byte : INTEGER ; histogram : array_0_255 ; indicator_level : INTEGER := 0 ; { } FUNCTION exchand_find_dac_byte OF TYPE EXCEPTION_HANDLER ; { } BEGIN { } set_trc_exc_mode ( TRUE ) ; { } handle_trc_sta ( TAG := 'DAC/EXC%', { } STATUS := signal_args.name ) ; { } IF ( result_open = 1 ) THEN close_result_file ( result_file ) ; { } handle_trc_sys ( TAG := 'DAC/EXC%', MESSAGE := ' Resignaling') ; { } exchand_find_dac_byte := FALSE ; { } END ; { } FUNCTION quick_median : INTEGER ; { } VAR sum_to_i, i : integer ; { } BEGIN { } sum_to_i := 0 ; { } FOR i := -4 TO +4 { } DO BEGIN { } sum_to_i := sum_to_i + histogram[zeresp_goal+i] ; { } IF ( sum_to_i > sample_size/2 ) THEN GOTO done ; { } END ; { } done: IF ( i >= +4 ) THEN quick_median := zeresp_goal - 4 { } ELSE quick_median := zeresp_goal + i ; { } END ; BEGIN IF PRESENT(status) THEN status := ok ; IF ( result_file = NIL ) THEN BEGIN NEW(result_file) ; result_file^.origin := 'FIND_DAC_BYTE' ; result_file^.name := 'DAC_' + CONVERT(STRING(3),eta_pol) + '_' + CONVERT(STRING,eta_mag) + '_' + CONVERT(STRING,phi_val) + '_' + CONVERT(STRING,twr_typ) + '.LOG' ; open_result_file ( RESULT_FILE := result_file, STATUS := result_open ) ; END ELSE local_file := FALSE ; IF ( result_open = 1 ) {nested exception handler } THEN ESTABLISH ( exchand_find_dac_byte ) ; {closing result file } e_fe := CONVERT ( magn_eta_per_fe_cell, (ORD(eta_mag)-1) DIV 4 ) ; rele := CONVERT ( relative_eta, (ORD(eta_mag)-1) MOD 4 ) ; p_trgtwr := trgtwr[eta_pol,eta_mag,phi_val] ; zeresp_goal := p_trgtwr^.adconv[twr_typ].zeresp ; p_ctfe_ctrl := ADDRESS ( ctfe_ctrl[eta_pol,e_fe,phi_val] ) ; p_ped_reg := ADDRESS ( p_ctfe_ctrl^.pedreg[rele,twr_typ] ) ; p_ctfe_data := ADDRESS ( ctfe_data[eta_pol,e_fe,phi_val] ) ; p_adc_reg := ADDRESS ( p_ctfe_data^.muxout[rele,twr_typ] ) ; search_min := dac_to_adc_ratio*zeresp_goal - safety_margin ; search_max := dac_to_adc_ratio*zeresp_goal + observed_spread + safety_margin ; IF ( search_min < 0 ) THEN search_min := 0 ; IF ( search_max > 255 ) THEN search_max := 255 ; msg_fix_part := ' ' + CONVERT(STRING(3),eta_pol) + ',' + CONVERT(STRING,eta_mag) + ',' + CONVERT(STRING,phi_val) + ' ' + CONVERT(STRING,twr_typ) + ' for ADC zeresp' + ' ' + CONVERT(STRING,zeresp_goal) ; IF ( result_open = 1 ) THEN BEGIN message := ' Looking for DAC byte' + msg_fix_part + ' within ' + CONVERT(STRING,search_min) + ':' + CONVERT(STRING,search_max) ; handle_write_result ( result_file, message ) ; END ; search_stage := quick_search ; sample_size := fast_search_sample_size ; FOR dac_byte := search_min TO search_max DO BEGIN update_register ( TAGEXT := tagext, CARD := p_ctfe_ctrl, REGISTER := p_ped_reg, IOPAR := iopar, DATA := dac_byte, STATUS := io_status ) ; IF ( io_status = io_failure ) THEN BEGIN IF PRESENT(status) THEN status := io_status ; message := ' Failure Loading DAC byte' + msg_fix_part + ' with ' + CONVERT(STRING,dac_byte) ; IF ( inline_tracing(trace_error) <> 0 ) THEN handle_trc_err ( TAG := tag + tagext, MESSAGE := message ) ; IF ( result_open = 1 ) THEN handle_write_result ( result_file, message ) ; GOTO quit_looking_for_dac_byte ; END ; WAIT_ANY ( TIME := three_time_const ) ; {wait for DAC voltage filtering!} histogram := ZERO ; histogram_register ( TAGEXT := tagext, CARD := p_ctfe_data, REGISTER := p_adc_reg, SLICEAGE := 0, IOPAR := iopar, HISTOGRAM := ADDRESS(histogram), SAMPLE_SIZE := sample_size ) ; IF ( result_open = 1 ) THEN handle_write_result ( RESULT_FILE := result_file, OUTSTRING := 'DAC =' + ' ' + CONVERT(STRING(3),dac_byte) + ' HIST =' + ' ' + CONVERT(STRING(4),histogram[zeresp_goal-4]) + ' ' + CONVERT(STRING(4),histogram[zeresp_goal-3]) + ' ' + CONVERT(STRING(4),histogram[zeresp_goal-2]) + ' ' + CONVERT(STRING(4),histogram[zeresp_goal-1]) + ' ' + ' ' + CONVERT(STRING(4),histogram[zeresp_goal ]) + ' ' + ' ' + CONVERT(STRING(4),histogram[zeresp_goal+1]) + ' ' + CONVERT(STRING(4),histogram[zeresp_goal+2]) + ' ' + CONVERT(STRING(4),histogram[zeresp_goal+3]) + ' ' + CONVERT(STRING(4),histogram[zeresp_goal+4]) ); IF ( search_stage = quick_search ) THEN BEGIN IF ( histogram[zeresp_goal] <> 0 ) THEN IF ( (zeresp_goal - quick_median) <= 1 ) THEN BEGIN IF ( result_open = 1 ) THEN handle_write_result ( RESULT_FILE := result_file, OUTSTRING := ' Starting deep search' ) ; search_stage := deep_search ; sample_size := deep_search_sample_size ; END ELSE handle_trc_err ( TAG := tag + tagext, MESSAGE := ' Median still too far ' + CONVERT(STRING,quick_median) + ' at ' + msg_fix_part ) ; END ELSE BEGIN IF ( histogram[zeresp_goal] < indicator_level ) THEN IF ( (zeresp_goal - quick_median) <= 0 ) THEN BEGIN {the goal was just exceeded by 1} result := dac_byte - 1 ; IF ( result_open = 1 ) THEN BEGIN MESSAGE := ' DAC byte found' + msg_fix_part + ' is ' + CONVERT(STRING,result) ; handle_write_result ( result_file, message ) ; END ; GOTO quit_looking_for_dac_byte ; END ELSE handle_trc_err ( TAG := tag + tagext, MESSAGE := ' Median too far ' + CONVERT(STRING,quick_median) + ' continue ' + msg_fix_part ) ; END ; indicator_level := histogram[zeresp_goal] ; END ; IF PRESENT(status) THEN status := not_found ; result := 0 ; message := ' Failure finding DAC byte' + msg_fix_part + ' within' + ' ' + CONVERT(STRING,search_min) + ':' + CONVERT(STRING,search_max) ; IF ( inline_tracing(trace_error) <> 0 ) THEN handle_trc_err ( TAG := tag + tagext, MESSAGE := message ) ; IF ( result_open = 1 ) THEN handle_write_result ( result_file, message ) ; quit_looking_for_dac_byte: {restore downloaded DAC byte to official value} update_register ( TAGEXT := tagext, CARD := p_ctfe_ctrl, REGISTER := ADDRESS(p_ctfe_ctrl^.pedreg[rele,twr_typ]), IOPAR := iopar, DATA := p_trgtwr^.ADConv[twr_typ].dac_byte, STATUS := io_status ) ; IF ( local_file = TRUE ) THEN BEGIN IF ( result_open = 1 ) THEN close_result_file ( RESULT_FILE := result_file ) ; DISPOSE(result_file) ; END ; END ; { *************************************************************************** } { *************************************************************************** } [INLINE] FUNCTION inline_set_bit_in_chan_ctrl ( twr_typ : adc_data_type_per_ctfe_channel ; rele : relative_eta ) : byte ; BEGIN CASE twr_typ OF EMEtZ0 : CASE rele OF rele_0 : inline_set_bit_in_chan_ctrl := 1 ; rele_1 : inline_set_bit_in_chan_ctrl := 4 ; rele_2 : inline_set_bit_in_chan_ctrl := 16 ; rele_3 : inline_set_bit_in_chan_ctrl := 64 ; END ; HDEtZ0 : CASE rele OF rele_0 : inline_set_bit_in_chan_ctrl := 2 ; rele_1 : inline_set_bit_in_chan_ctrl := 8 ; rele_2 : inline_set_bit_in_chan_ctrl := 32 ; rele_3 : inline_set_bit_in_chan_ctrl := 128 ; END ; END ; END ; { *************************************************************************** } [INLINE] FUNCTION inline_byte_and ( op1 , op2 : byte ) : byte ; VAR bool1, bool2, bool3 : BOOLEAN ; BEGIN bool1::BYTE_DATA := op1::BYTE_DATA ; bool2::BYTE_DATA := op2::BYTE_DATA ; bool3 := bool1 AND bool2 ; inline_byte_and::BYTE_DATA := bool3::BYTE_DATA ; END ; { *************************************************************************** } [INLINE] FUNCTION inline_byte_or ( op1 , op2 : byte ) : byte ; VAR bool1, bool2, bool3 : BOOLEAN ; BEGIN bool1::BYTE_DATA := op1::BYTE_DATA ; bool2::BYTE_DATA := op2::BYTE_DATA ; bool3 := bool1 OR bool2 ; inline_byte_or::BYTE_DATA := bool3::BYTE_DATA ; END ; { *************************************************************************** } { *************************************************************************** } FUNCTION Mev_to_Gev_str ( energy : INTEGER ) : VARYING_STRING(8) ; CONST max_digits = 7 ; VAR MeV : STRING(max_digits) ; GeV : STRING(max_digits+1) ; charnum : INTEGER ; BEGIN MeV := CONVERT(STRING,energy) ; charnum := max_digits ; WHILE ( ( SUBSTR(MeV,charnum,1) = ' ' ) AND ( charnum > 0 ) ) DO charnum := charnum - 1 ; CASE charnum OF 0 : Mev_to_Gev_str := '0.000' ; 1 : Mev_to_Gev_str := '0.00' + SUBSTR(MeV,1,1) ; 2 : Mev_to_Gev_str := '0.0' + SUBSTR(MeV,1,2) ; 3 : Mev_to_Gev_str := '0.' + SUBSTR(MeV,1,3) ; OTHERWISE Mev_to_Gev_str := SUBSTR(MeV,1,charnum-3) + '.' + SUBSTR(MeV,charnum-2,3) ; END ; END ; { *************************************************************************** } END .