/* mc2coda - function to accept a list of data and convert it into a CODA3 Raw Event format */ #include #include #include #include #include #include "mc2coda.h" /* Global mc2coda Library Variables */ int mc2coda_inited = MC2CINIT_NULL; CODA_EXP_INFO mc2coda_expid; int mc2coda_maxevsize = 0; /* Local variables */ static int mc2coda_ncrates_defined = 0; static unsigned int *dabufp, *StartOfRocBank; /* Include module specific definitions */ #include "mc2coda_modules.c" /* Initialize the Crate/Module maps for crates in the system Must be called prior to calling the mc2coda event packer. - Returns an expID (experiment setup structure pointer) */ CODA_EXP_INFO * mc2codaInitExp(int nCrates, const char *name) { int ii; if(nCrates>MAX_CRATES) { printf("mc2codaInitExp: ERROR: Too many crates defined for the system\n"); return (NULL); } /* Initialize a new experiment config structure */ if(mc2coda_inited) { printf("mc2codaInitExp: ERROR: Experiment already Initialized - Call mc2codaFree(expid) first\n"); return(NULL); } printf("Exp name = %s\n",name); bzero((char *) &mc2coda_expid,sizeof(CODA_EXP_INFO)); strncpy(mc2coda_expid.expname,name,64); mc2coda_expid.ncrates = nCrates; for(ii=0;iicrate_id = ii; } mc2coda_expid.inited = MC2CINIT_DEFINED; /* Only partially initialized */ mc2coda_expid.openevents = 0; /* No open events using this experiment config */ mc2coda_ncrates_defined = 0; printf("Initialized: Experiment %s (id = 0x%x) consisting of %d crates/ROCs\n", mc2coda_expid.expname,&mc2coda_expid,mc2coda_expid.ncrates); return(&mc2coda_expid); } /* Set Crate specific info for a given expID - All crates must be defined - with module types before an experiment config can generate RAW events. This function must be called at least once for each crate defined by mc2codaInitExp pass number of modules, and module and detector id arrays returns Number of crates initialized or Error (-1) */ int mc2codaSetCrate(CODA_EXP_INFO *expID, int crateid, int nmod, int *modules, int *detid) { int ii; /* check that parameters are valid */ if ((crateid<0)||(crateid > expID->ncrates)) { printf("mc2codaSetCrate: ERROR: crate ID out of range %d > %d (ncrates) \n", crateid, expID->ncrates); return(-1); } if(nmod >= MAX_SLOTS) { printf("mc2codaSetCrate: ERROR: Number of modules out of range %d\n",nmod); return(-1); } if(mc2coda_ncrates_defined >= expID->ncrates) { mc2coda_ncrates_defined = expID->ncrates - 1; printf("mc2codaSetCrate: WARN: overwriting Crate %d module map\n",crateid); } /* Fill the Crate structure */ printf("mc2codSetCrate: INFO: Crate %d has %d modules for readout\n",crateid, nmod); expID->crate[(crateid-1)]->nModules = nmod; expID->crate[(crateid-1)]->moduleMask = 0; for (ii=0;iicrate[(crateid-1)]->module_map[ii] = modules[ii]; expID->crate[(crateid-1)]->det_map[ii] = detid[ii]; if(modules[ii] != 0) expID->crate[(crateid-1)]->moduleMask |= (1<ncrates) { printf("mc2codaSetCrate: All %d crates defined: Initialization complete.\n",mc2coda_ncrates_defined); mc2coda_inited = MC2CINIT_COMPLETE; } return(mc2coda_ncrates_defined); } /* Open a RAW event for population - Returns an eventID */ CODA_EVENT_INFO * mc2codaOpenEvent(CODA_EXP_INFO *expID, uint64_t eventNum, uint64_t trigTime, unsigned short eventType, int maxSize) { int ii, jj, kk, has_tt = 0; unsigned int *evbuf; CODA_EVENT_INFO *evinfo; if(expID == 0) { printf("m2codaOpenEvent: ERROR: expID not defined\n"); return(NULL); }else{ /*check if the event number is Valid */ if(eventNum == 0) { printf("mc2codaOpenEvent: ERROR: event Number invalid (0)\n"); return(NULL); } if(trigTime == 0) has_tt=0; else has_tt=1; } /* Allocate an Event Info structure */ evinfo = (CODA_EVENT_INFO *) malloc(sizeof(CODA_EVENT_INFO)); evinfo->nhits = 0; evinfo->eventid = eventNum; evinfo->trigtime = trigTime; evinfo->evtype = eventType&0x0000ffff; evinfo->expid = expID; /* Allocate Hit Arrays for each valid crate/slot */ for (ii=0; ii<(expID->ncrates); ii++) { for(jj=1; jj<(MAX_SLOTS); jj++) { /* Skip CPU slot */ evinfo->hcount[ii][jj] = 0; /* Check if there is a valid module for this crate/slot pair and allocate the MAX number of HIT structures for that slot */ if((expID->crate[ii]->moduleMask)&(1<hits[ii][jj] = (CODA_HIT_INFO *) malloc(MAX_HITS_PER_SLOT * sizeof(CODA_HIT_INFO)); }else{ evinfo->hits[ii][jj] = NULL; } } } /* Allocate an Event buffer */ if(maxSize) { evbuf = (unsigned int *) malloc (maxSize); mc2coda_maxevsize = maxSize; }else{ evbuf = (unsigned int *) malloc (MAX_EVENT_SIZE); mc2coda_maxevsize = MAX_EVENT_SIZE; } bzero((char *)evbuf, mc2coda_maxevsize); evinfo->evbuf = (unsigned int *)evbuf; evinfo->maxBytes = mc2coda_maxevsize; /* Populate the Event header and trigger Bank */ if(has_tt) { evbuf[0] = 10; evbuf[1] = 0xff511001; evbuf[2] = 8; evbuf[3] = 0xff212000 | ((expID->ncrates)&0xff); evbuf[4] = 0x010a0004; memcpy((char *)&evbuf[5],(char *)&eventNum,8); memcpy((char *)&evbuf[7],(char *)&trigTime,8); evbuf[9] = 0x01050001; evbuf[10] = (eventType); }else{ evbuf[0] = 8; evbuf[1] = 0xff501001; evbuf[2] = 6; evbuf[3] = 0xff202000 | ((expID->ncrates)&0xff); evbuf[4] = 0x010a0004; memcpy((char *)&evbuf[5],(char *)&eventNum,8); evbuf[7] = 0x01050001; evbuf[8] = (eventType); } /* Bump the openevents counter */ expID->openevents++; return(evinfo); } /* Write Monte Carlo hit(s) info into the event. This routine allocates local hit structures and copies hit infomation into them and then updates a list. Once the function returns the original hit structures can be freed or cleared. This routine must be reentrant so that different threads can write hits asynchonously. No attempt is made to reorder hits. Only copy them and updates list totals. Returns: # of hits written to the Event */ int mc2codaWrite(CODA_EVENT_INFO *event, int nHits, struct coda_hit_info *codaHits) { int ii, jj, cnt, lcnt, crate, slot; CODA_EXP_INFO *exp; CODA_HIT_INFO *tmpH; /* check for valid hits */ if((nHits <= 0) || (codaHits == NULL)) { return(0); } /* Check for a valid event pointer */ if(event) { exp = event->expid; if(exp->openevents <= 0) { printf("mc2codaWrite: ERROR: Invalid or Corrupted event ID\n"); return(-1); } }else{ printf("mc2codaWrite: ERROR: Null event ID\n"); return(-1); } /* Now loop through all new hits and sort/save them*/ lcnt = 0; for (ii=0; iihcount[crate][slot]; /* printf("DEBUG: Writing hit %d for crate,slot = %d,%d\n",cnt,crate,slot); */ if(cnt > MAX_HITS_PER_SLOT) { printf("mc2codaWrite: ERROR: No available space to store hit %d for crate/slot = %d/%d\n", codaHits->hit_id,crate,slot); } else { tmpH = (CODA_HIT_INFO *)&event->hits[crate][slot][cnt]; memcpy((char *)&(tmpH->hit_id),(char *)&(codaHits[ii].hit_id),sizeof(CODA_HIT_INFO)) ; /* printf("DEBUG: malloc data array\n"); */ tmpH->hdata = (uint32_t *) malloc((codaHits[ii].nwords)<<2); memcpy((char *)(tmpH->hdata), (char *)(codaHits[ii].hdata),(codaHits[ii].nwords)<<2); event->hcount[crate][slot] += 1; } event->nhits++; lcnt++; } return(lcnt); } /* Close out the event packer and return pointer to Event Buffer for writing function also returns number of total words in the event (eventID[0] */ unsigned int mc2codaCloseEvent(CODA_EVENT_INFO *event) { int ii, jj, kk, hcnt, nwords; unsigned int roc, det, mod; unsigned int *StartofEvent; CODA_EXP_INFO *expID = event->expid; CODA_CRATE_MAP *crate; if(event == NULL) { printf("mc2codaCloseEvent: ERROR: Null Event Pointer!!\n"); return(0); } /* Setup pointers */ StartofEvent = &(event->evbuf[0]); dabufp = StartofEvent + (event->evbuf[0] + 1); /* Set data pointer to end of the event */ /* Loop through all ROCs */ for(ii=0; iincrates; ii++) { roc = expID->rocid[ii]; crate = expID->crate[ii]; det = crate->det_map[0]; /* Open a ROC data Bank */ ROC_BANK_OPEN(0,roc,1); /* Open a Data Bank */ DATA_BANK_OPEN(0,det,1); /* Loop through all modules */ for(jj=0; jjmoduleMask)) == 0) continue; mod = crate->module_map[jj]; /* printf(" slot %d module %d \n",(jj+1),mod); */ switch (mod) { case FADC250: fadc250_write_data (event, roc,(jj+1) , FADC250_MODE_IP); break; case FADC125: fadc125_write_data (event, roc,(jj+1) , FADC125_MODE_IP); break; case F1TDC32: f1tdc32_write_data (event, roc,(jj+1) ,0); break; case F1TDC48: f1tdc48_write_data (event, roc,(jj+1), 0); break; case CAEN1290: caen1290_write_data (event, roc,(jj+1), 0); break; default: break; } } DATA_BANK_CLOSE; } ROC_BANK_CLOSE; *StartofEvent = (uint32_t) (dabufp - StartofEvent - 1); return((*StartofEvent+1)); } /* Reset the Existing event for use again. This is equivilent to OpenEvent so that new event Number, trigger time and event type must be specified but it avoids mallocing the necessary memory and structures all over again. returns 0 - OK or -1 Error */ int mc2codaResetEvent(CODA_EVENT_INFO *eventID, uint64_t eventNum, uint64_t trigTime, unsigned short eventType) { CODA_EXP_INFO *exp; CODA_HIT_INFO *tmpH; int ii, jj, kk, ccnt, hcnt, lcnt; if(eventID != NULL) { exp = eventID->expid; if(exp->openevents <= 0) { printf("mc2codaResetEvent: ERROR: Invalid or Corrupted event ID\n"); return(-1); } ccnt = exp->ncrates; hcnt = eventID->nhits; } else { printf("mc2codaResetEvent: ERROR: NULL pointer to Event Buffer\n"); return(-1); } /* First free the data arrays that have been allocated for individual hits */ for (ii=0; iihits[ii][jj] != NULL) { /* crate,slot array exists, now check if it has hits */ lcnt = eventID->hcount[ii][jj]; if(lcnt) { /* free all the hit data */ for(kk=0;kkhits[ii][jj][kk]; free(tmpH->hdata); } eventID->hcount[ii][jj] = 0; /* Set Hit count to 0 */ } } } } /* Now clear the existing event structure and buffer and reset with the new info */ eventID->nhits = 0; eventID->eventid = eventNum; eventID->trigtime = trigTime; eventID->evtype = eventType&0x0000ffff; if(eventID->maxBytes > 0) { bzero((char *)eventID->evbuf, eventID->maxBytes); }else{ printf("mc2codaResetEvent: ERROR: Event buffer size is invalid (%d)\n",eventID->maxBytes); return(-1); } /* Populate the Event header and trigger Bank */ if(trigTime) { eventID->evbuf[0] = 10; eventID->evbuf[1] = 0xff511001; eventID->evbuf[2] = 8; eventID->evbuf[3] = 0xff212000 | ((exp->ncrates)&0xff); eventID->evbuf[4] = 0x010a0004; memcpy((char *)&eventID->evbuf[5],(char *)&eventNum,8); memcpy((char *)&eventID->evbuf[7],(char *)&trigTime,8); eventID->evbuf[9] = 0x01050001; eventID->evbuf[10] = (eventType); }else{ eventID->evbuf[0] = 8; eventID->evbuf[1] = 0xff501001; eventID->evbuf[2] = 6; eventID->evbuf[3] = 0xff202000 | ((exp->ncrates)&0xff); eventID->evbuf[4] = 0x010a0004; memcpy((char *)&eventID->evbuf[5],(char *)&eventNum,8); eventID->evbuf[7] = 0x01050001; eventID->evbuf[8] = (eventType); } return(0); } /* Free the event buffer for the specified event */ int mc2codaFreeEvent(CODA_EVENT_INFO *eventID) { CODA_EXP_INFO *exp; CODA_HIT_INFO *tmpH; int ii, jj, kk, ccnt, hcnt, lcnt; /* Get the crate and Hit counts */ exp = eventID->expid; ccnt = exp->ncrates; hcnt = eventID->nhits; if(eventID != NULL) { /* First free the Event Buffer */ if(eventID->evbuf != NULL) { free(eventID->evbuf); eventID->evbuf = NULL; } else { printf("mc2codaFreeEvent: ERROR invalid pointer to Event Buffer\n"); } /* Free all the allocated Arrays of Hit structures and their associated data array*/ for (ii=0; iihits[ii][jj] != NULL) { /* crate,slot array exists, now check if it has hits */ lcnt = eventID->hcount[ii][jj]; if(lcnt) { /* free all the hit data */ for(kk=0;kkhits[ii][jj][kk]; free(tmpH->hdata); } } /* Now free the hit structure array */ /* printf("DEBUG: freeing Hit array for crate,slot = %d,%d\n",ii,jj); */ free(eventID->hits[ii][jj]); eventID->hits[ii][jj] = NULL; } } } /* Free the Event Structure */ free(eventID); eventID = NULL; /* Decrement the openevents counter */ exp->openevents--; }else{ printf("mc2codaFreeEvent: ERROR invalid eventID \n"); return(ERROR); } return(0); } /* Free the Experiment Config (including any open events for it) */ void mc2codaFree(CODA_EXP_INFO *expID) { int ii; if(expID == NULL) { printf("mc2codaFree: ERROR invalid expID\n"); return; } /* Check if there are open events */ if(expID->openevents) { printf("mc2codaFree: ERROR: Cannot Free experiment. There are currently %d open events\n", expID->openevents); return; } if(expID->inited > MC2CINIT_NULL) { printf("mc2codaFree: WARN: Deleting Experiment %s\n",expID->expname); for(ii=0;ii<(expID->ncrates);ii++) free(expID->crate[ii]); bzero(expID,sizeof(CODA_EXP_INFO)); } } /* Print out various statistics about the event */ void mc2codaStats(CODA_EVENT_INFO *eventID, int sflag) { CODA_EXP_INFO *exp; CODA_HIT_INFO *tmpH; int ii, jj, kk, ccnt, hcnt, lcnt; int chits [MAX_CRATES]; if(eventID == NULL) { printf("mc2codaStats: ERROR: Null Event ID\n"); return; } /* Get the crate and Hit counts */ exp = eventID->expid; ccnt = exp->ncrates; hcnt = eventID->nhits; /* Print out Experiment Info */ printf("Experiment: %s # of Open Events: %d\n",exp->expname, exp->openevents); printf(" Total Crates: %d Total Hits: %d\n",ccnt, hcnt); /* Count up Hits per Crate and print out Crate map with hit info*/ printf("Crate Map: moduleID( hit_count) for each slot in each crate\n"); for(ii=0;iihcount[ii][jj]; printf("%1d(%4d) ",exp->crate[ii]->module_map[jj],eventID->hcount[ii][jj]); } printf("\n"); } return; }