/*-*-C-*-*/ program Bic_Bunch("STN=HB60") /* **MEMBER**=SLCLIBS:xxxSHRLIB **CMS**=xxxUTIL ====================================================================== Abs: This sequence reads the raw bunch current data from either the shared memory interface (real data) or from the simulated data and prepares waveform data selected by mode (every 2nd or 3rd bunch) as well as totals' data. Name: BIC_BUNCH.ST Proto: none Auth: 22-Jul-1997, Ron Chestnut Rev: DD-MMM-YYYY, Reviewer's Name (.NE. Author's Name) ----------------------------------------------------------------------- Mod: (newest to oldest) 21-Feb-2001, Ron Chestnut Add phase error correction 5-Oct-2000, Ron Chestnut Revamp AVG phase calculation and add phase for 1656 4-Aug-2000, Ron Chestnut Added AVG_PHASE and WHICH_BIG to keep the phase arrays below 60 degrees 5-Jun-2000, Ron Chestnut Add easier "phase" calculation Add X ranges for 6 full strips showing buckets BNCHEXP:X1..6 8-Nov-1999, Ron Chestnut Add stop on Bad Calibration, Bad Buckets filled Shut off deconvolution on bad odd buckets 26-Oct-1999, Ron Chestnut Add use of Stop_Reason MBBO 02-Aug-1999, Ron Chestnut Raise the deconvolution peak detection threshold 23-Jul-1999, Ron Chestnut Add phase envelope calculations 16-Jul-1999, Ron Chestnut Add BAD_TRIGGER_MAX check to not terminate on one bad update from BXBCM 12-Jul-1999, Ron Chestnut Move NUMBUCK to Bic_Lum.st Add Magic bucket stuff for BPM/Feedback applications 23-Mar-1999, Ron Chestnut Incorporate four-phase logic for phase shift correction 26-Feb-1999, Ron Chestnut Use full waveforms; no more mode 2 and 3 27-Jan-1999, Ron Chestnut Add use of BNCHCURR:BUCKLIFE 12-Jan-1999, Ron Chestnut Add use of BNCHCURR:BUCKET and BNCHCURR:BUCKCURR Use new MPG/BIC shared memory structure 09-Dec-1998, Ron Chestnut Set the 20minute X scale offset to eliminate startup wierdness 22-Jul-1998, Ron Chestnut Removed 60HZ channels 05-Jun-1998, Ron Chestnut Add output of deconvoluted array Check for SMEAR adding to near 1.0 02-Jun-1998, Ron Chestnut Added +r option for reentrancy Changed to SMEAR0,...SMEAR4 from array Added support for SATISFIED Index Added comments 20-Mar-1998, Ron Chestnut: Added deconvolution to fixup ADC problem =======================================================================*/ option +r; /* make reentrant */ #include "bic_common.h" #include "bic_stat_macros.h" %%#include "epicsPrint.h" /*epicsPrintf */ %%#include "alarm.h" /*MAJOR_ALARM */ %%char* ring_name_c = "BUNCH: "; /* Map to all the relevant Database items */ long bic_state; assign bic_state to "{STN}:STATE:ACT"; monitor bic_state; short req_status_stop; assign req_status_stop to "{STN}:STATE:STOP"; short inj_stop_reason; assign inj_stop_reason to "{STN}:INJECT:SREASON"; long sim_debug; assign sim_debug to "{STN}:SIMULATR:DEBUG"; monitor sim_debug; float dcct_norm; assign dcct_norm to "{STN}:BNCHCURR:RATIO"; float goal[N_BUCKET]; assign goal to "{STN}:FILL:GOAL"; long x_array[N_BUCKET]; assign x_array to "{STN}:XAXIS"; long x_arrayC[N_ELEMC]; assign x_arrayC to "{STN}:XAXIS:COMP"; float x_20min[N_20MIN]; assign x_20min to "{STN}:DCCT:20MIN"; float bunch_phase[N_ELEMC]; assign bunch_phase to "{STN}:BNCHCURR:PHASE"; float b1656_phase; assign b1656_phase to "{STN}:BXBCM:PHASE:B1680"; float b0_phases[4];assign b0_phases to "{STN}:BUCKET:PHASES:B0"; float phase_deltas; assign phase_deltas to "{STN}:BXBCM:PHASE:DELTAS"; monitor phase_deltas; long delta_sign; assign delta_sign to "{STN}:BXBCM:DELTA:SIGN"; long calc_sign; assign calc_sign to "{STN}:BXBCM:DELTA:CALC"; monitor calc_sign; double dcct_didt; assign dcct_didt to "{STN}:DCCT:DIDT"; float dcct_value; assign dcct_value to "{STN}:DCCT:SUMY"; monitor dcct_value; double dcct_lifetime; assign dcct_lifetime to "{STN}:DCCT:LIFETIME"; float bunch_comp[N_ELEMC]; assign bunch_comp to "{STN}:BNCHCURR:COMP"; long bxbcm_trigger; assign bxbcm_trigger to "{STN}:BNCHCURR:BXBTRIGR"; long bxbcm_process_ix; assign bxbcm_process_ix to "{STN}:MPG:REQ:PRC"; long bxbcm_trigger_proc; assign bxbcm_trigger_proc to "{STN}:BNCHCURR:BXBTRIGR.PROC"; long bnch_trigger; assign bnch_trigger to "{STN}:BNCHCURR:FANOUT.PROC"; long mpg_process_ix; assign mpg_process_ix to "{STN}:BNCHCURR:PROCINDX"; long bnch_process_ix; assign bnch_process_ix to "{STN}:INJECT:PROCESS:INDEX"; long bunch_current[N_BUCKET]; assign bunch_current to "{STN}:BNCHCURR:PRE"; long bunch_phase1[N_BUCKET]; assign bunch_phase1 to "{STN}:BNCHCURR:PHASE1"; long bunch_phase2[N_BUCKET]; assign bunch_phase2 to "{STN}:BNCHCURR:PHASE2"; long bunch_bxb_oddped; assign bunch_bxb_oddped to "{STN}:BXB:ODDPED"; monitor bunch_bxb_oddped; long bunch_bxb_evenped; assign bunch_bxb_evenped to "{STN}:BXB:EVENPED"; monitor bunch_bxb_evenped; short bxbcm_mode; assign bxbcm_mode to "{STN}:BXBCM:PHASE:MODEOUT"; monitor bxbcm_mode; long bunch_current_c[N_BUCKET]; assign bunch_current_c to "{STN}:BNCHCURR"; float bunch_maxcurr; assign bunch_maxcurr to "{STN}:BNCHCURR:MAXCURR"; long bunch_maxadc; assign bunch_maxadc to "{STN}:BNCHCURR:MAXADC"; float bunch_bad[N_BUCKET]; assign bunch_bad to "{STN}:BNCHCURR:BAD"; float bunch_good[N_BUCKET]; assign bunch_good to "{STN}:BNCHCURR:GOOD"; float bunch_good_sum; assign bunch_good_sum to "{STN}:BNCHCURR:GOOD:SUMY"; float bunch_bad_sum; assign bunch_bad_sum to "{STN}:BNCHCURR:BAD:SUMY"; float bg_ratio; assign bg_ratio to "{STN}:BNCHCURR:BGRATIO"; float fill_thresh; assign fill_thresh to "{STN}:BNCHCURR:FILL:THRESH"; monitor fill_thresh; float bunch_sumf; assign bunch_sumf to "{STN}:BNCHCURR:SUMY"; float even_ped; assign even_ped to "{STN}:BNCHCURR:EVENPED"; float odd_ped; assign odd_ped to "{STN}:BNCHCURR:ODDPED"; float ped_diff; assign ped_diff to "{STN}:BNCHCURR:PEDDIF"; short back_from; assign back_from to "{STN}:BNCHCURR:BACKF"; monitor back_from; short back_to; assign back_to to "{STN}:BNCHCURR:BACKT"; monitor back_to; long single_bucket; assign single_bucket to "{STN}:BNCHCURR:BUCKET"; monitor single_bucket; short magic_bucket; assign magic_bucket to "{STN}:GOAL:FULLBUCK"; monitor magic_bucket; float magic_current; assign magic_current to "{STN}:BNCHCURR:MAGIC"; short new_trigger_seen; assign new_trigger_seen to "{STN}:BNCHCURR:UPDATING"; float single_current; assign single_current to "{STN}:BNCHCURR:BUCKCURR"; float single_lifetime; assign single_lifetime to "{STN}:BNCHCURR:BUCKLIFE"; float decay_arr[N_BUCKET]; assign decay_arr to "{STN}:DECAY"; #define MAX_SMEAR 5 short convolve_peak; assign convolve_peak to "{STN}:BXBCM:DECONP"; monitor convolve_peak; float convolve[MAX_SMEAR]; assign convolve[0] to "{STN}:BXBCM:SMEAR0"; assign convolve[1] to "{STN}:BXBCM:SMEAR1"; assign convolve[2] to "{STN}:BXBCM:SMEAR2"; assign convolve[3] to "{STN}:BXBCM:SMEAR3"; assign convolve[4] to "{STN}:BXBCM:SMEAR4"; #define N_582 582 short b_exp1[N_582]; assign b_exp1 to "{STN}:BNCHEXP:X1"; short b_exp2[N_582]; assign b_exp2 to "{STN}:BNCHEXP:X2"; short b_exp3[N_582]; assign b_exp3 to "{STN}:BNCHEXP:X3"; short b_exp4[N_582]; assign b_exp4 to "{STN}:BNCHEXP:X4"; short b_exp5[N_582]; assign b_exp5 to "{STN}:BNCHEXP:X5"; short b_exp6[N_582]; assign b_exp6 to "{STN}:BNCHEXP:X6"; short bexp_indx[6]; assign bexp_indx to { "{STN}:BNCHEXP:Y1.INDX","{STN}:BNCHEXP:Y2.INDX", "{STN}:BNCHEXP:Y3.INDX","{STN}:BNCHEXP:Y4.INDX", "{STN}:BNCHEXP:Y5.INDX","{STN}:BNCHEXP:Y6.INDX" }; long reset_conv; assign reset_conv to "{STN}:BXBCM:SMEAR:RESET"; monitor reset_conv; long anal_conv; assign anal_conv to "{STN}:BXBCM:SMEAR:ANAL"; monitor anal_conv; string state_msg1; assign state_msg1 to "{STN}:STATE:MSG1"; /* Local variables */ #define MAX_BKGD 2400. #define BAD_TRIGGER_MAX 2 short bad_trigger_count; long bkgd_search_cutoff; long i; long j; long k; long n_in_background_e; long n_in_background_o; short minute; float background_e; float background_o; float deconv_background; float deconv_peak_limit; long timer_count; long last_trigger; float value; float big_piece; double avg_phase; double sum_phase_x; double sum_phase_y; double xi; double yi; double phase_x[N_ELEMC]; double phase_y[N_ELEMC]; %%#include "taskLib.h" /* TaskDelay */ %%#include "math.h" /* fabs */ %%#include "string.h" /* memcpy */ ss bunchSpinSS { state init { when(1) { /* Set up all the X-axis arrays */ for (i=0; i1.5 || value > .02) { convolve[0]=1.; convolve[1]=convolve[2]=convolve[3]=convolve[4]=0.; for(i=0;i12 || last_trigger != bxbcm_trigger) { /* printf("B lt,trig,mi = %4u %4u %4u \n",last_trigger,bxbcm_trigger,mpg_process_ix); */ bnch_trigger=1; pvPut(bnch_trigger); timer_count = 0; if(last_trigger==bxbcm_trigger) { bad_trigger_count++; new_trigger_seen = 0; } else { new_trigger_seen = 1; bad_trigger_count = 0; } last_trigger = bxbcm_trigger; if(new_trigger_seen==1 || bad_trigger_count > BAD_TRIGGER_MAX) pvPut(new_trigger_seen); } state spin when(bic_state==Quiescent && reset_conv==1) { convolve[0]=1.; convolve[1]=convolve[2]=convolve[3]=convolve[4]=0.; for(i=0;iMAX_BKGD) bkgd_search_cutoff=MAX_BKGD; /* Get the goal array so we know which should have data */ pvGet(goal); /* Get a good guess at the backgrounds and remove the ADC smear from the digital data */ pvGet(bunch_phase1); if(bxbcm_mode==0) /* Phase_4 */ { if(bic_state==Quiescent) { minute++; /* Each minute do the phase calculation if in 4-phase mode */ } pvGet(bunch_phase2); even_ped = odd_ped = 0; sum_phase_x=0.; sum_phase_y=0.; b1656_phase=0.; for (i=0; i=10) { j=i/36; /* Special code for the phase of bucket 1656 */ if (i==1656 && goal[1656]>0 && xi != 0. && yi != 0.) { b1656_phase = 57.3* atan2(fabs(xi),fabs(yi)); } if(i%36==0 && goal[i]>0.) { phase_x[j]=xi; phase_y[j]=yi; sum_phase_x+=xi; sum_phase_y+=yi; } else if (i%36==0) { phase_x[j]=0.; phase_y[j]=0.; } else if (goal[i]>0.) { phase_x[j]+=xi; phase_y[j]+=yi; sum_phase_x+=xi; sum_phase_y+=yi; } } } if(minute>=10) { minute=0; if (sum_phase_x==0. && sum_phase_y==0.) avg_phase=0.; else avg_phase=57.3* atan2(fabs(sum_phase_x),fabs(sum_phase_y)); for(i=0;i0 && bunch_current[0]>100000) { pvGet(b0_phases); /* Find the phase with the highest value */ j=0; k=b0_phases[0]; for(i=1;i<4;i++) if(b0_phases[i]>k) { k=b0_phases[i]; j=i; } /* If the "higher" neighbor is also significantly positive, it becomes the cosine determining phase. 30% is signficant. */ i = (j+1)%4; if(b0_phases[i]>(k*3/10)) j=i; /* If it is 1 or 3, use a positive sign */ if((j%2)==1) delta_sign= 1; else delta_sign=-1; pvPut(delta_sign); } } } else /* Phase_1 */ { memcpy(&bunch_current[0],&bunch_phase1[0],N_BUCKET*4); } /* End of Phase_1 */ pvPut(bunch_current); even_ped = bunch_bxb_evenped + bkgd_search_cutoff; odd_ped = bunch_bxb_oddped + bkgd_search_cutoff; if (sim_debug==Debug_Calc) printf("Search E: %f,O: %f,Cut: %5lu\n",even_ped,odd_ped,bkgd_search_cutoff); n_in_background_e = n_in_background_o = 0; background_e = background_o = 0.0; if(back_from<0 || back_from>N_BUCKET) back_from=back_to=0; if(back_to<0 || back_to>N_BUCKET) back_from=back_to=0; if(back_to==0 && back_from==0) { back_to = N_BUCKET-4; for(i=N_BUCKET;i<1 && goal[i]==0.;i--) back_from = i+4; pvPut(back_to); pvPut(back_from); } for (i=back_from;i0) even_ped = background_e/n_in_background_e; if(n_in_background_o>0) odd_ped = background_o/n_in_background_o; /* Now the bunch_current array should be deconvoluted */ /* Use deconv_background for the average of the ion clearing gap area */ /* Use deconv_peak_limit for deconv_background offset by the background search cutoff */ deconv_background = (even_ped+odd_ped)/2.; deconv_peak_limit = deconv_background + bkgd_search_cutoff; if(anal_conv==1) { anal_conv=0; pvPut(anal_conv); if(bic_state==Quiescent) { j = convolve_peak; if(bunch_current[j]>deconv_peak_limit && goal[j]>0.) { value = 0; for(i=0;ibunch_maxadc) bunch_maxadc=bunch_current[i]; if(convolve[0]!=1.0 && goal[i]>0.0 && bunch_current[i]>deconv_peak_limit) { big_piece=(bunch_current[i]-deconv_background)/convolve[0]; bunch_current[i]=deconv_background+big_piece; for(j=1;jbunch_maxcurr) bunch_maxcurr = value; bunch_good[i] = value; bunch_comp[j] += value; if(goal[i]>0.0) bunch_good_sum += value; else { bunch_bad_sum += value; bunch_bad[i] = value; } if (i%36==35) j++; } /* get the current in the single bucket selected */ single_current = single_lifetime = magic_current = 0.; if(single_bucket>-1 && single_bucket < N_BUCKET) { pvGet(decay_arr); single_lifetime = -decay_arr[single_bucket]*60; value = bunch_current_c[single_bucket]; if(single_bucket%2==0) single_current=dcct_norm*(value-even_ped)/1000.; else single_current=dcct_norm*(value-odd_ped) /1000.; } /* get the current in the BPM/Feedback bucket selected */ if(magic_bucket>-1 && magic_bucket < N_BUCKET) { value = bunch_current_c[magic_bucket]; if(magic_bucket%2==0) magic_current=dcct_norm*(value-even_ped)/1000.; else magic_current=dcct_norm*(value-odd_ped) /1000.; } /* All currents are now in microamperes, do the average for COMPRESSED data */ for (i=0; i