/***************************************************************************/ /* emcspy_lib.c, * * Modification history: * 4-8-97 S.Miscetti: created. * modification of l2spy.c .. * - process is in the template. * -- include all the goodies from emcmon in cxx. * - ready for pedestals.. soon for monitoring * a lot of functions from Simona: DaqPoi,EmcReadPeds,CeleMaker */ /***************************************************************************/ /* #define DEBUG_ON */ #include <math.h> #include <stdio.h> #include <time.h> #include <sys/times.h> #include <sys/signal.h> #include <unistd.h> #include <errno.h> #include <spy.h> #include <rockml2frame.h> /* Error */ #include "Error.h" /* proctmpl */ #include "template.h" extern struct command_list *first_cmd; /* L2 */ /* #include <l2defs.h> */ #include <l2defs.h> #include "emcspy.h" #include <l2event.h> #include <l2buffer.h> #include <l2ybos.h> #include <YbosLocate.h> #include <dmap.h> #include <GeoVme.h> #include "raw2cele.h" /* unfortunately here we need some global variables .. pedval expecially + monitor values for Emc */ typedef struct EmcMonVal_ { int Dpoi; float occneg; float occpos; float mip; float deltat0; } EmcMonVal; #define FirstPedRound 200 SysTestPeds PedVal[NumberOfSlots][NumberOfChannels]; EmcMonVal MonVal[NumberOfSlots][NumberOfChannels]; /* for double round loop on peds */ int pedEvents[NumberOfSlots][NumberOfChannels][2] = 0; int adcminval[NumberOfSlots][NumberOfChannels] = 100; int adcmaxval[NumberOfSlots][NumberOfChannels] = 500; /* .... NOW EmC PROTOTYPING .... */ /* The basic fundamental one */ int DaqPoiUpk(int *DaqPoi, int *Chain, int *Crate, int *Slot, int *Chan); int CELEMaker(int *NWords, int *YBDataPoi, CELEStru *CaloEv, int *CELELen); /* useful simple functions to get mean & rms */ float emc_get_mean(int nev, float sum); float emc_get_rms(int nev, float mean, float sum2); /* basic for monitoring */ int EmcReadPeds(char *PedFile); int EmcInitMonitor(char *MonFile); int EmcMakeMonitor(int celelen, CELEStru *CaloEv); int EmcCloseMonitor(char *MonFile); /* basic for pedestals ... suggestion: same functions inside Builder to do it for all ADCs ... TDCs .. per chain .. better typedef to be defined */ int EmcInitPeds(void); int EmcClosPeds(char *PedOut); int EmcMakePeds(int banklen, int* bankptr); static SPY_id spy_id; /* counters */ static u_long events_spy = 0; static u_long bytes_processed = 0; /* timing */ static struct tms tms_begin, tms_end; static u_long t_begin, t_end; static unsigned int count_events = 0; /***************************************************************************/ int EmcspyInit (AskVariables* ask_var) /*------------------------------------- * Should be called at program start. */ /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ { /*.........................................................................*/ DEBUG(("EmcspyInit> IN\n")); DEBUG(("EmcspyInit> OUT\n")); return (Error_NO); } /***************************************************************************/ int EmcspyBegin (AskVariables* ask_var) /*------------------------------------- * Should do all to make the state transition END_STATE -> RESUME_STATE to * allow a 'warm' start afterwards. It should also allow a defined restart * after EmcspyEnd() has be called! */ /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ { /*.........................................................................*/ DEBUG(("EmcspyBegin> IN\n")); /* 1. Map to multiple circular buffer. */ if ( spy_open_local(BUILD_CIRC_NAME,&spy_id) != SPY_ERROR_OK) { return Error_YES; } events_spy = 0; /* at begin run .. please read your maps or gracefully exit the program */ { int Status; GeoVmeLoadMap("geovmefile"); /* Load GeoVmeMap */ Status = dmap_load("dmapfile"); /* Load DMAP */ if ( Status != DMAP_ERROR_OK ) { printf("Error in dmap_load \n"); return Error_YES; } if( ask_var->monitor[0]!='m') { printf("emcspy: Reading Pedestals file from pedfile"); Status = EmcReadPeds("pedfile"); /* Read Peds File */ if ( Status != 0 ) { return Error_YES; } Status = EmcInitMonitor("monfile"); } else if ( ask_var->monitor[0]!='p') { int islot,ichan; printf("emcspy: opening Pedestals file pedout"); Status = EmcInitPeds(); if ( Status != 0 ) { return Error_YES; } } else { printf(" Please select a default running condition m or p"); printf(" by typing: ask emcspy monitor xx" ); } } /* FillChainDef(); */ YbosInit(); /* 1. Open output file and put begin-of-run record */ if (ask_var->record[0]!='\0') { YbosOpen(&ask_var->runnr,ask_var->record,ask_var->basedir,"spy"); } DEBUG(("EmcspyBegin> OUT\n")); return (Error_NO); } /***************************************************************************/ int EmcspyEnd (AskVariables* ask_var) /*----------------------------------- * Should do all to make the state transition BEGIN_STATE -> END_STATE. * With EmcspyBegin() a defined restart should be possible also with * modified parameters (number of nodes etc.). In principle it should * never be necessary to kill the l2send process. */ /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ { /*.........................................................................*/ DEBUG(("EmcspyEnd> IN\n")); /* 1. Close output file and put end-of-run record */ if (ask_var->record[0]!='\0') { (void)YbosClose(&ask_var->runnr); printf("File closed...\n"); } /* 2. Unmap from to multiple circular buffer. */ spy_close(spy_id); /* 3. close all opened files */ if ( ask_var->monitor[0] == 'm' ) { EmcCloseMonitor("monfile"); } else if( ask_var->monitor[0] == 'p') { EmcClosePeds("pedout"); } else printf(" Nothing to close .."); DEBUG(("EmcspyEnd> OUT\n")); return (Error_NO); } /***************************************************************************/ int EmcspyProcess (AskVariables* ask_var) /*---------------------------------------- */ /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ { struct timeval *wait = &ask_var->timeout; int i, n; int end_of_run = FALSE; /*.........................................................................*/ DEBUG(("EmcspyProcess> IN, build events from %d source\n",ncirc)); if (ask_var->runstate == RUNNING_STATE) { /* start timing */ t_begin = times(&tms_begin); printf("EmcspyProcess> Timing started ...\n"); } while (ask_var->runstate == RUNNING_STATE) { l2buffer_header *buf; int buflen; int err; /* we read the streams of events from the head of the multiple circular * buffer. All pieces shoud have the same sequence event number because * they belong to the same events. */ err = spy_get(spy_id,(char **) &buf,&buflen); if ( err == SPY_ERROR_OK) { int i, j, Status, CELELen; char *ptr = buf->data; CELEStru *CaloEv; for (i=0; i<buf->events_in_buffer; i++) { l2buffer_event *ibuf = (l2buffer_event *) ptr; int banklen,j; int *bankptr; ptr += ibuf->length+sizeof(int); yboslocateinit_( (int *) ibuf->data); yboslocate_((int *) ibuf->data,"CALR", &banklen,&bankptr); if( ask_var->monitor[0]!='p') { Status = EmcMakePeds(banklen, bankptr); if ( Status != 0 ) { printf(" RAW2CELE> Error while creating CELE structure. \n"); exit(1); } } else if( ask_var->monitor[0]!='m') { CaloEv = (CELEStru* )calloc(banklen,sizeof(CELEStru)); Status = CELEMaker(&banklen,bankptr,(CELEStru*) CaloEv,&CELELen); if ( Status != 0 ) { printf(" RAW2CELE> Error while creating CELE structure. \n"); exit(1); } Status = EmcMakeMonitor(CELELen, (CELEStru*) CaloEv); free(CaloEv); } } free(buf); } else /* polling time */ { select (1, (FD_SET_T)0, (FD_SET_T)0, (FD_SET_T)0, wait); ask_var->timeouts++; } /* new command arrived ? */ check_for_command: if (first_cmd != NULL) check_command(NULL); } return (Error_NO); } /***************************************************************************/ void EmcspyStatus (AskVariables* ask_var) /*---------------------------------------- */ /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ { int i; double ticks, dt, dtcpu, bytes_rate; /*.........................................................................*/ ticks = (double)sysconf(_SC_CLK_TCK); t_end = times(&tms_end); dt=(double)(t_end-t_begin)/ticks; dtcpu=(double)(tms_end.tms_utime-tms_begin.tms_utime+ tms_end.tms_stime-tms_begin.tms_stime)/ticks; bytes_rate = (double)bytes_processed/1024./1024./dt; printf("------------------------------------------------------------\n"); printf("Run state: %d\n ",ask_var->runstate); printf("Total Time: %.1f sec, CPU usage: %4.1f%% for %d sub-events\n", dt,dtcpu/dt*100.,events_spy); printf("%u bytes processed ==> MByte/sec: %3.1f\n", bytes_processed,bytes_rate) ; printf("buffer empty timeouts: %d\n",ask_var->timeouts); printf("------------------------------------------------------------\n"); } /**********************************************************************/ int EmcMakePeds(int banklen, int *YBDataPoi) /********************************************************************* It assumes a global matrix of structures for Pedestals *********************************************************************/ { int YBosData; int iloop,Status; rockm_l2frame Frame; DMAP_CHAN_EL El2Cal; for (iloop=0; iloop < banklen; iloop++) { int chan,crate,slot,chain,value, bit13; YBosData = (unsigned int) (YBDataPoi[iloop]); rockm_l2frame_raw2l2frame(YBosData,Frame); if (Frame.chain == 0 ) Frame.chain = 1; Frame.chan &= 31; chan = Frame.chan; chain = Frame.chain; crate = Frame.crate; slot = Frame.slot; bit13 = Frame.res; value = Frame.data; Status = dmap_get(chain, crate, slot, chan, &El2Cal); if ( Status != DMAP_ERROR_OK ) { printf("EmcMakePeds> Wrong DMAP association \n"); return -1; } else { if( El2Cal.btype == DMAP_BTYPE_CALADC) { if ( bit13 == 0 ) { /* if( pedEvents[slot][chan][0] == FirstPedRound) { int nev; float sum,sum2; float mean,rms; nev = pedEvents[slot][chan][0]; sum = pedEvents[slot][chan].PedL; sum2= pedEvents[slot][chan].SigL; mean = get_mean(nev,sum); rms = get_rms (nev,mean,sum2); adcminval[slot][chan] = mean-3*rms; adcmaxval[slot][chan] = mean+3*rms; adc } */ if( value > adcminval[slot][chan] || value < adcmaxval[slot][chan] ) { pedEvents[slot][chan][0]++; PedVal[slot][chan].PedL= PedVal[slot][chan].PedL + value; PedVal[slot][chan].SigL = PedVal[slot][chan].SigL + value*value ; } } else { if( value > adcminval[slot][chan] || value < adcmaxval[slot][chan] ) { pedEvents[slot][chan][1]++; PedVal[slot][chan].PedH= PedVal[slot][chan].PedH + value; PedVal[slot][chan].SigH = PedVal[slot][chan].SigH + value*value ; } } } } } } /***************************************************************/ float emc_get_mean(int nev, float sum) /***************************************************************/ { float mean; mean = -999.; if( nev>0) mean = sum/nev; return mean; } /***************************************************************/ float emc_get_rms(int nev, float mean, float sum2) /***************************************************************/ { float rms,meda2; rms = -999.; if( nev>0 || mean != -999. ) meda2 = sum2/nev; rms = sqrtf( abs(meda2-mean*mean)); return rms; } /***************************************************************/ /**********************************************************************/ int EmcClosePeds(char *pedout) /********************************************************************* It assumes a global matrix of structures for Pedestals *********************************************************************/ { int slot,chan,chain,crate,daqpoi,prognum,status; float med_all_2; float ped2_med; FILE* UsedFile; printf("Opening Output file for Pedestals pedout"); UsedFile = fopen(pedout,"w"); if( UsedFile == NULL ) { printf(" EmcInitPeds> Failure opening PEDs file \n"); return -1; } chain = 1; crate = 3; prognum = 0; for (slot=0; slot<NumberOfSlots; slot++) { for(chan=0; chan<NumberOfChannels; chan++) { int nev; float sum,sum2; float mean,rms; if( pedEvents[slot][chan][0]>0 ) { nev = pedEvents[slot][chan][0]; sum = PedVal[slot][chan].PedL; sum2= PedVal[slot][chan].SigL; mean = emc_get_mean(nev,sum); rms = emc_get_rms (nev,mean,sum2); PedVal[slot][chan].PedL = mean; PedVal[slot][chan].SigL = rms; } if( pedEvents[slot][chan][1]>0) { nev = pedEvents[slot][chan][1]; sum = PedVal[slot][chan].PedH; sum2= PedVal[slot][chan].SigH; mean = emc_get_mean(nev,sum); rms = emc_get_rms (nev,mean,sum2); PedVal[slot][chan].PedH = mean; PedVal[slot][chan].SigH = rms; } prognum++; daqpoi = 0; status = DaqPoiUpk(&daqpoi,&chain,&crate,&slot,&chan); fprintf(UsedFile,"%d %d %f %f %f %f %f %f",prognum,daqpoi, PedVal[slot][chan].PedL,PedVal[slot][chan].SigL,PedVal[slot][chan].ChiL, PedVal[slot][chan].PedH,PedVal[slot][chan].SigH,PedVal[slot][chan].ChiH); } } fclose(UsedFile); return 0; } int EmcInitMonitor(char *MonFile) { printf(" Not Yet Implemented"); return 0; } int EmcMakeMonitor(int celelen, CELEStru *CaloEv) { printf(" Not Yet Implemented"); return 0; } int EmcCloseMonitor(char *MonFile) { printf(" Not Yet Implemented"); return 0; } /*-----------------------------------------------------*/ int EmcInitPeds(void) { int slot,chan; for (slot=0; slot<NumberOfSlots; slot++) { for(chan=0; chan<NumberOfChannels; chan++) { PedVal[slot][chan].PedL = 0; PedVal[slot][chan].SigL = 0; PedVal[slot][chan].ChiL = 0; PedVal[slot][chan].PedH = 0; PedVal[slot][chan].SigH = 0; PedVal[slot][chan].ChiH = 0; } } return 0; } /* ===================================================================== Unpack DAQ Pointer to get chain, crate, slot and channel number ===================================================================== */ int DaqPoiUpk(int *DaqPoi, int *Chain, int *Crate, int *Slot, int *Chan) { int ChainMax = 1; int CratePerChain = 8; int BoardPerCrate = 16; int ChanPerBoard = 30; int ChanPerCrate, Pointer; int CrateNum, SlotNum, ChanNum; Pointer = *DaqPoi; ChanPerCrate = BoardPerCrate*ChanPerBoard; CrateNum = (Pointer-1)/ChanPerCrate + 1; SlotNum = (Pointer-1-(CrateNum-1)*ChanPerCrate) / ChanPerBoard; ChanNum = Pointer-1-(CrateNum-1)*ChanPerCrate-ChanPerBoard*SlotNum; *Chain = ChainMax; *Crate = CrateNum; *Slot = SlotNum; *Chan = ChanNum; return 0; } /* ===================================================================== Read PEDs value from "pedfile" ===================================================================== */ int EmcReadPeds(char *PedFile) { int ILoop, Status; int SerNum, DaqPoi; int Chain, Crate, Slot, Chan; float PedValL, SigmaL, ChiSqL, PedValH, SigmaH, ChiSqH; FILE* UsedFile; printf(" ReadPeds> Opening PEDs File %s \n",PedFile); UsedFile = fopen(PedFile,"r"); if( UsedFile == NULL ) { printf(" ReadPeds> Failure opening PEDs file \n"); return -1; } ILoop = 0; while ( ILoop < 480 ) { fscanf(UsedFile,"%d %d %f %f %f %f %f %f",&SerNum,&DaqPoi, &PedValL,&SigmaL,&ChiSqL,&PedValH,&SigmaH,&ChiSqH); if ( PedValH > 4096 ) { DaqPoi = 480 + ILoop; PedValH = PedValH - 4095; } Chain = 0; Crate = 0; Slot = 0; Chan = 0; Status = DaqPoiUpk(&DaqPoi,&Chain,&Crate,&Slot,&Chan); if ( Status != 0 ) { printf(" ReadPeds> Unable unpacking daqpointer %d \n",DaqPoi); return -1; } PedVal[Slot][Chan].DPoi = DaqPoi; PedVal[Slot][Chan].PedL = PedValL; PedVal[Slot][Chan].SigL = SigmaL; PedVal[Slot][Chan].ChiL = ChiSqL; PedVal[Slot][Chan].PedH = PedValH; PedVal[Slot][Chan].SigH = SigmaH; PedVal[Slot][Chan].ChiH = ChiSqH; ILoop++; } fclose(UsedFile); return 0; } /* ===================================================================== Create CELE-like event from RAW data ===================================================================== */ int CELEMaker(int *NWords, int *YBDataPoi, CELEStru *CaloEv, int *CELELen) { int ILoop, Status, NVal; int YBosData, JLoop, *CELEAdr; int FstVal, DataFlg, NumEle, CELEPoi; int CELEAddress, CELE_Id, CELExist; float Ped, Sig, ADCVal, TDCVal; rockm_l2frame Frame; DMAP_CHAN_EL El2Cal; NVal = *NWords; FstVal = *YBDataPoi; NumEle = 0; CELEAdr = (int* )calloc(NVal,sizeof(int)); for ( ILoop=0; ILoop<NVal; ILoop++ ) { YBosData = (unsigned int) (YBDataPoi[ILoop]); rockm_l2frame_raw2l2frame(YBosData,Frame); Frame.chan &= 31; if (Frame.chain == 0 ) Frame.chain = 1; Status = dmap_get(Frame.chain,Frame.crate,Frame.slot,Frame.chan,&El2Cal); if ( Status != DMAP_ERROR_OK ) { printf("CELEMaker> Wrong DMAP association \n"); return -1; } else { DataFlg = 0; ADCVal = 0.; TDCVal = 0.; switch ( El2Cal.btype ) { case DMAP_BTYPE_CALADC: if ( Frame.res == 0 ) { Ped = PedVal[Frame.slot][Frame.chan].PedL; Sig = PedVal[Frame.slot][Frame.chan].SigL; } else { Ped = PedVal[Frame.slot][Frame.chan].PedH; Sig = PedVal[Frame.slot][Frame.chan].SigH; } if ( Sig > 20. ) Sig=20.; ADCVal = Frame.data - Ped; if ( abs(ADCVal) > 3*Sig ) DataFlg = 1; break; case DMAP_BTYPE_CALTDC: if ( Frame.data < 4095 ) DataFlg = 1; TDCVal = Frame.data; break; default: printf("CELEMaker> Invalid BTYPE for CALR %d \n",El2Cal.btype); return 0; } } if( DataFlg==1 ) { CELE_Id = 0; CELExist = 0; CELEAddress = El2Cal.data.cal.detector | El2Cal.data.cal.module << 8 | El2Cal.data.cal.plane <<16 | El2Cal.data.cal.column <<24; for ( JLoop=0; JLoop<NumEle; JLoop++ ) { if ( CELEAdr[JLoop] == CELEAddress ) { CELExist = 1; CELE_Id = JLoop; } } if ( CELExist != 1 ) { CELEPoi = NumEle; CELEAdr[CELEPoi] = CELEAddress; CaloEv[CELEPoi].Det = El2Cal.data.cal.detector; CaloEv[CELEPoi].Wed = El2Cal.data.cal.module; CaloEv[CELEPoi].Col = El2Cal.data.cal.column; CaloEv[CELEPoi].Pla = El2Cal.data.cal.plane; NumEle = NumEle + 1; } else CELEPoi = CELE_Id; switch ( El2Cal.btype ) { case DMAP_BTYPE_CALADC: if ( El2Cal.data.cal.side == 1 ) CaloEv[CELEPoi].Ea = ADCVal; if ( El2Cal.data.cal.side == 2 ) CaloEv[CELEPoi].Eb = ADCVal; break; case DMAP_BTYPE_CALTDC: if ( El2Cal.data.cal.side == 1 ) CaloEv[CELEPoi].Ta = TDCVal; if ( El2Cal.data.cal.side == 2 ) CaloEv[CELEPoi].Tb = TDCVal; break; default: ; } } } *CELELen = NumEle; free (CELEAdr); return 0; }