/********************************************************************\ Name: frontend.c Created by: Stefan Ritt Contents: Experiment specific readout code (user part) of Midas frontend. This example simulates a "trigger event" and a "scaler event" which are filled with CAMAC or random data. The trigger event is filled with two banks (ADC0 and TDC0), the scaler event with one bank (SCLR). $Id: frontend.c 3384 2006-10-21 04:29:18Z amaudruz $ Modifed by: qp Jan/20/2008 for simulation Jan 21, add on ROOT method: keep old C functions in extern "C" {} define new c++ funcions with ROOT read pulse shape from pulseTemplate#.txt \********************************************************************/ #include #include #include #include #include "midas.h" //#include "mcstd.h" #include "experim.h" #include /* ROOT include */ #include "TSystem.h" #include "TROOT.h" #include "TFile.h" #include "TH1.h" #include "TH2.h" #include "WFDIndex.h" WFDIndex *myWFDIndex; /* for WFD Simu */ const INT n_fills=5000; /*** number of fills per segment from ODB ***/ const INT n_pulses_max=30; INT n_pulses = 30; /*** number of muons decayed in one fill ***/ const int N_WFD=340; const int N_SHAPE=2400; const int N_ISLAND=24; int N_STEP = N_SHAPE/N_ISLAND; int debug = 1; // 0 for no message, 1 for message, 2 for verbose message typedef struct { char ADC[24]; DWORD separator; DWORD time; } ISLAND; static ISLAND island, island_random; ISLAND gIsland[N_WFD][n_fills*n_pulses_max+1]; INT gCount[N_WFD]; float gShape[N_WFD][N_SHAPE]; INT gPeak[N_WFD]; TFile *f, *fout; char histname0[80], histname[80]; /* make frontend functions callable from the C framework */ #ifdef __cplusplus extern "C" { #endif #include "mcstd.h" /*-- Globals -------------------------------------------------------*/ /* The frontend name (client name) as seen by other MIDAS clients */ char *frontend_name = "WFD Simu"; //"Sample Frontend"; /* The frontend file name, don't change it */ char *frontend_file_name = __FILE__; /* frontend_loop is called periodically if this variable is TRUE */ BOOL frontend_call_loop = TRUE; /* a frontend status page is displayed with this frequency in ms */ INT display_period = 3000; /* maximum event size produced by this frontend */ INT max_event_size = 5 * 1024 * 1024; /* maximum event size for fragmented events (EQ_FRAGMENTED) */ INT max_event_size_frag = 2* max_event_size; /* buffer size to hold events */ INT event_buffer_size = 2 * max_event_size; /* number of channels */ #define N_ADC 4 #define N_TDC 4 #define N_SCLR 4 /* CAMAC crate and slots */ #define CRATE 0 #define SLOT_IO 23 #define SLOT_ADC 1 #define SLOT_TDC 2 #define SLOT_SCLR 3 /*-- Function declarations -----------------------------------------*/ INT frontend_init(); INT frontend_exit(); INT begin_of_run(INT run_number, char *error); INT end_of_run(INT run_number, char *error); INT pause_run(INT run_number, char *error); INT resume_run(INT run_number, char *error); INT frontend_loop(); INT read_simu_event(char *pevent, INT off); INT read_scaler_event(char *pevent, INT off); void register_cnaf_callback(int debug); INT poll_event(INT source, INT count, BOOL test); INT interrupt_configure(INT cmd, INT source, POINTER_T adr); /*-- Equipment list ------------------------------------------------*/ #undef USE_INT EQUIPMENT equipment[] = { {"WFD_SIMU", /* equipment name */ {1, 0, /* event ID, trigger mask */ "SYSTEM", /* event buffer */ #ifdef USE_INT EQ_INTERRUPT, /* equipment type */ #else EQ_POLLED, /* equipment type */ #endif LAM_SOURCE(0, 0xFFFFFF), /* event source crate 0, all stations */ "MIDAS", /* format */ TRUE, /* enabled */ RO_RUNNING, // | /* read only when running */ // RO_ODB, /* and update ODB */ 5000, /* poll for 500ms */ 0, /* stop run after this event limit */ 0, /* number of sub events */ 0, /* don't log history */ "", "", "",}, read_simu_event, /* readout routine */ }, {"Scaler", /* equipment name */ {2, 0, /* event ID, trigger mask */ "SYSTEM", /* event buffer */ EQ_PERIODIC | EQ_MANUAL_TRIG, /* equipment type */ 0, /* event source */ "MIDAS", /* format */ TRUE, /* enabled */ RO_RUNNING | RO_TRANSITIONS | /* read when running and on transitions */ RO_ODB, /* and update ODB */ 10000, /* read every 10 sec */ 0, /* stop run after this event limit */ 0, /* number of sub events */ 0, /* log history */ "", "", "",}, read_scaler_event, /* readout routine */ }, {""} }; #ifdef __cplusplus } #endif INT wfd_get_shape(void); INT wfd_get_hist(void); double wfd_get_random(int sn, int choice); /********************************************************************\ Callback routines for system transitions These routines are called whenever a system transition like start/ stop of a run occurs. The routines are called on the following occations: frontend_init: When the frontend program is started. This routine should initialize the hardware. frontend_exit: When the frontend program is shut down. Can be used to releas any locked resources like memory, commu- nications ports etc. begin_of_run: When a new run is started. Clear scalers, open rungates, etc. end_of_run: Called on a request to stop a run. Can send end-of-run event and close run gates. pause_run: When a run is paused. Should disable trigger events. resume_run: When a run is resumed. Should enable trigger events. \********************************************************************/ /*-- Frontend Init -------------------------------------------------*/ INT frontend_init() { /* hardware initialization */ cam_init(); cam_crate_clear(CRATE); cam_crate_zinit(CRATE); /* enable LAM in IO unit */ camc(CRATE, SLOT_IO, 0, 26); /* enable LAM in crate controller */ cam_lam_enable(CRATE, SLOT_IO); /* reset external LAM Flip-Flop */ camo(CRATE, SLOT_IO, 1, 16, 0xFF); camo(CRATE, SLOT_IO, 1, 16, 0); /* register CNAF functionality from cnaf_callback.c with debug output */ register_cnaf_callback(1); /* print message and return FE_ERR_HW if frontend should not be started */ wfd_get_hist(); wfd_get_shape(); myWFDIndex = new WFDIndex(); return SUCCESS; } /*-- Frontend Exit -------------------------------------------------*/ INT frontend_exit() { return SUCCESS; } /*-- Begin of Run --------------------------------------------------*/ INT begin_of_run(INT run_number, char *error) { /* put here clear scalers etc. */ island.ADC[0] = 5; island.ADC[1] = 6; island.ADC[2] = 7; island.ADC[3] = 5; island.ADC[4] = 7; island.ADC[5] = 20; island.ADC[6] = 30; island.ADC[7] = 50; island.ADC[8] = 90; island.ADC[9] = 120; island.ADC[10] = 150; island.ADC[11] = 200; island.ADC[12] = 165; island.ADC[13] = 130; island.ADC[14] = 110; island.ADC[15] = 90; island.ADC[16] = 30; island.ADC[17] = 10; island.ADC[18] = 7; island.ADC[19] = 4; island.ADC[20] = 6; island.ADC[21] = 5; island.ADC[22] = 3; island.ADC[23] = 6; //island.ADC[24] = 7; //island.ADC[25] = 6; //island.ADC[26] = 6; //island.ADC[27] = 7; //island.ADC[28] = 5; //island.ADC[29] = 5; //island.ADC[30] = 6; //island.ADC[31] = 5; island.separator = 0x0; island.time = 0x00010001; // wfd_get_hist(); return SUCCESS; } INT wfd_get_hist(void) { gROOT->Reset(); char filename0[] = "IslandParameters"; char runname[] = "57140-57170"; Char_t dirname[100], filename[100]; sprintf(dirname,"/home/qzpeng/2006data/histos/"); sprintf(filename, "%s%s%s.root", dirname, filename0, runname); f = new TFile(filename); if (f->IsZombie()!=0) { printf("ROOT File %s not exist\n", filename); return 0; } sprintf(histname0,"hTime"); sprintf(histname,"%s%03d",histname0,1); TH1D *thisHist = (TH1D*) f->Get(histname); if (thisHist==NULL) { printf("Histogram %s not exist, exit...\n", histname); return 0; } delete thisHist; /* sprintf(filename, "%s.root", filename0); fout = new TFile(filename,"RECREATE"); fout->cd(); */ return SUCCESS; } double wfd_get_random(int sn, int choice) { if (choice==1) { sprintf(histname,"hTime%03d",sn); } else if (choice==2) { sprintf(histname,"hAmp%03d",sn); } else if (choice==3) { sprintf(histname,"hPed%03d",sn); } TH1D *thisHist = (TH1D*) f->Get(histname); if (thisHist==NULL) { printf("Histo %s for SN %d not exist, Next...\n",histname,sn); return -1; } double myRandom = thisHist->GetRandom(); delete thisHist; return myRandom; } INT wfd_get_shape(void) { char fname0_shape[]="pulseTemplate"; char dir_shape[]="/home/qzpeng/simu/pulseTemplates/"; char fname_shape[100]; char line[80]; double sample; FILE *f_shape; for (int sn=1; sn<=N_WFD; sn++) { sprintf(fname_shape,"%s%s%03d.txt",dir_shape,fname0_shape,sn); f_shape=fopen(fname_shape,"r"); if (f_shape==NULL){ printf("error: %s not found...\n",fname_shape); continue; } int j=0; while (!feof(f_shape)){ fscanf(f_shape,"%[^\n]\n",line); if (line[0]=='#') { //printf("skipping comment line\n"); continue; } else { if (jN_WFD) sn=N_WFD; else if (sn<1) sn=1; /*** generate pulses ***/ fittime = wfd_get_random(sn,1); amp = wfd_get_random(sn,2); ped = wfd_get_random(sn,3); iClock = int(fittime); iPeak = gPeak[sn-1]+int(N_STEP*drand48())-N_STEP/2; // random around the peak for (jj=iClock, jClock=iPeak; jj>=0; jj--,jClock-=N_STEP) { if (jClock<0) jClock=0; amp_real = gShape[sn-1][jClock]*amp+ped; if (amp_real>255) gIsland[sn-1][gCount[sn-1]].ADC[jj]=255; else if (amp_real<0) gIsland[sn-1][gCount[sn-1]].ADC[jj]=0; else gIsland[sn-1][gCount[sn-1]].ADC[jj]=BYTE(amp_real); } for (jj=iClock+1, jClock=iPeak+N_STEP; jj<24; jj++, jClock+=N_STEP) { if (jClock>=N_SHAPE) jClock=N_SHAPE-1; amp_real = gShape[sn-1][jClock]*amp+ped; if (amp_real>255) gIsland[sn-1][gCount[sn-1]].ADC[jj]=255; else if (amp_real<0) gIsland[sn-1][gCount[sn-1]].ADC[jj]=0; else gIsland[sn-1][gCount[sn-1]].ADC[jj]=BYTE(amp_real); } decaytime = drand48()*1000; filltime=fill; filltime<<=16; filltime+=WORD(decaytime); gIsland[sn-1][gCount[sn-1]].time = filltime; gCount[sn-1]++; } // pulses in one fill } // fills if (debug>0) { for (i=0; i<10; i++) { printf("N_Pulse[%d]=%d\n", i, gCount[i]); } } /* init bank structure */ bk_init32(pevent); int crate, slot; char ch; for (crate=1; crate<=6; crate++) { for (slot=2; slot<20; slot++) { if (slot==6 || slot==13 || slot==14) continue; for (ch=0; ch<4; ch++) { sprintf(bkName,"B%1d%c%1d",crate,(char)slot+'a'-1,ch); bkName[4]='\0'; sn = myWFDIndex->GetSerialNumber(bkName); if (sn<1 || sn>N_WFD) continue; bk_create(pevent, bkName, TID_DWORD, &pdata); pdata[0] = gCount[sn-1]+1; /* +1 to account for reset block */ pdata[1] = gCount[sn-1]+1; pdata[2] = 0; pdata += 3; /*** reset block ***/ bzero(pdata, sizeof(island)); // memset(pdata,0,sizeof(island)); pdata += island_len_words; for (ii=0; ii