#define ROL_NAME__ "mcROL_ti" #define MAX_EVENT_LENGTH 1024*64 #define MAX_EVENT_POOL 100 /* POLLING_MODE */ #define POLLING___ #define POLLING_MODE //#define TEST_MODE #define INIT_NAME mcROL__init #include #include #include #include #include // The definition of the rol object can be found in: // // $CODA/common/include/rolInt.h //===================================================== // This section copied from the ti_slave_list.c file // provided by Dave A. /* Define TI Type (TI_MASTER or TI_SLAVE) */ #define TI_SLAVE /* TS Fiber Link trigger source (from TI Master, TD, or TS), POLL for available data */ #define TI_READOUT TI_READOUT_TS_POLL /* TI VME address, or 0 for Auto Initialize (search for TI by slot) */ #define TI_ADDR 0 /* Measured longest fiber length in system */ #define FIBER_LATENCY_OFFSET 0x4A #include "dmaBankTools.h" /* Macros for handling CODA banks */ #include "tiprimary_list.c" /* Source required for CODA readout lists using the TI */ /* Define buffering level */ #define BUFFERLEVEL 10 //===================================================== // The evio input file name is passed in as the user string // during prestart and so is set below. The string may // contain a "%d" which will be replaced with the value // in rol->pid (aka the ROC id). static char evioFileName[1024] = "nada"; // full path on gluonraid1 static char evioLocalFileName[1024] = "nada"; // path to file on local RAM disk // For EVIO static int handle; #define MCBUFSIZE 10000 static uint32_t mcbuffer[MCBUFSIZE]; // For cMsg char UDL[512] = "cMsg://gluondb1.jlab.org/cMsg/softROC"; char cMsgName[256] = "rocXXX"; char cMsgDescr[256] = "coda_roc running software trigger"; void *domainID = NULL; void MyCallback(void *msg, void *userArg); // This is used to slow down and roughly synchronize the // events between ROCs. If we are connected to the cMsg // server (i.e. if domainID is not NULL) then every // event will decrement this counter in the __done() // routine until it gets to 0. Then, it will go into // a sleep loop waiting for the counter to be non-zero. // If __reset() or __prestart() are called then // this is reset to "1". int USE_SOFTROC_CONTROLLER = 0; unsigned long Nevents_left = 1000; int END_AT_NEXT_BOUNDARY = 0; int blklevel = 1; int trigBankType = 0xff11; //------------------------- // download //------------------------- static void __download() { daLogMsg("INFO","Readout list compiled %s", DAYTIME); #ifdef POLLING___ rol->poll = 1; #endif *(rol->async_roc) = 0; /* Normal ROC */ // Turn off by default until we get a message from controller // This allows us to run without a controller USE_SOFTROC_CONTROLLER = 0; // Connect to remote cMsg server. // (This will be disconnected in __reset() ) sprintf(cMsgName, "roc%02d", rol->pid); int err = cMsgConnect(UDL, cMsgName, cMsgDescr, &domainID); if(err!=0){ printf("Could not connect to cMsg server! Remote event governor disabled.\n"); }else{ printf("Connected to cMsg server using: %s\n", UDL); printf("-- cMsg client name: %s\n", cMsgName); cMsgSubscribeConfig *config = cMsgSubscribeConfigCreate(); cMsgSubscribe(domainID, "softROC", "*", MyCallback, NULL, config, NULL); cMsgSubscribe(domainID, cMsgName, "*", MyCallback, NULL, config, NULL); cMsgReceiveStart(domainID); } // Full file name (on possibly remote system) sprintf(evioFileName, rol->usrString, rol->pid); // replace first %d with ROC id // Get full path to file on RAM disk int pos = strlen(evioFileName); for(pos--; pos>0; pos--) if(evioFileName[pos]=='/') break; sprintf(evioLocalFileName, "/dev/shm/%s", &evioFileName[++pos]); // If the file is available on the local filesystem then copy it from there. // Otherwise, we'll have to scp it from the raid disk. We create a command // that will copy it to the RAM disk either via cp or scp and execute it below. char cmd[512]; FILE *f = fopen(evioFileName, "r"); if(f != NULL){ // File exists locally. Close it. fclose(f); // This is option is mainly for use with a sandbox CODA setup // (like used in a virtual machine). This seems to take a // while to do the copy so check if the file already exists // on the RAM disk and don't bother recopying if it does. f = fopen(evioLocalFileName, "r"); if(f != NULL){ // File exists on RAM disk. Do not re-copy fclose(f); sprintf(cmd, "echo file %s already exists. Skipping copy", evioLocalFileName); }else{ // File does not exist on RAM disk sprintf(cmd, "cp %s %s", evioFileName, evioLocalFileName); } }else{ // Download data file to RAM disk. We must do this via scp // since some ROCs do not seem to have /gluonraid1 mounted sprintf(cmd, "scp gluonraid1-daq:%s %s", evioFileName, evioLocalFileName); } // Run the command and print result printf("%s\n", cmd); int status = system(cmd); printf("Command result: %d\n", status); //===================================================== /* Setup Address and data modes for DMA transfers * * vmeDmaConfig(addrType, dataType, sstMode); * * addrType = 0 (A16) 1 (A24) 2 (A32) * dataType = 0 (D16) 1 (D32) 2 (BLK32) 3 (MBLK) 4 (2eVME) 5 (2eSST) * sstMode = 0 (SST160) 1 (SST267) 2 (SST320) */ vmeDmaConfig(2,5,1); /* Define BLock Level variable to a default */ blockLevel = 1; /***************** * TI SETUP *****************/ /* Set the sync delay width to 0x40*32 = 2.048us */ tiSetSyncDelayWidth(0x54, 0x40, 1); /* Set Trigger Buffer Level */ tiSetBlockBufferLevel(BUFFERLEVEL); /* Init the SD library so we can get status info */ int stat = sdInit(); if(stat==0) { tiSetBusySource(TI_BUSY_SWB,1); sdSetActiveVmeSlots(0); sdStatus(0); } else { /* No SD or the TI is not in the Proper slot */ tiSetBusySource(TI_BUSY_LOOPBACK,1); } tiStatus(0); //===================================================== daLogMsg("INFO","User Download Executed"); } //------------------------- // prestart //------------------------- static void __prestart() { CTRIGINIT; *(rol->nevents) = 0; daLogMsg("INFO","Entering User Prestart"); TEST_INIT; CTRIGRSS(TEST,1,usrtrig,usrtrig_done); CRTTYPE(1,TEST,1); TESTflag = 0; TEST_prescale = 10000; // sets iterations of a loop to slow down event rate daLogMsg("INFO","User Prestart Executed"); if (__the_event__) WRITE_EVENT_; *(rol->nevents) = 0; rol->recNb = 0; // open evio file if(evOpen(evioLocalFileName,"r",&handle)!=S_SUCCESS) { printf("?unable to open file %s\n",evioLocalFileName); } else { printf("successfully opened file %s\n",evioLocalFileName); } // Initialize counter Nevents_left = 1000; END_AT_NEXT_BOUNDARY = 0; //===================================================== /* Unlock the VME Mutex */ vmeBusUnlock(); tiStatus(0); //===================================================== } //------------------------- // end //------------------------- static void __end() { // Only turn off triggering at an event block // boundary if we are being regulated by a // remote softROCcontroller program if(USE_SOFTROC_CONTROLLER){ END_AT_NEXT_BOUNDARY = 1; }else{ TESTflag = 0; // close evio file evClose(handle); } daLogMsg("INFO","User End Executed"); if (__the_event__) WRITE_EVENT_; //===================================================== tiStatus(0); //===================================================== } //------------------------- // pause //------------------------- static void __pause() { TESTflag = 0; daLogMsg("INFO","User Pause Executed"); if (__the_event__) WRITE_EVENT_; } //------------------------- // go //------------------------- static void __go() { daLogMsg("INFO","Entering User Go"); TESTflag = 1; if (__the_event__) WRITE_EVENT_; } //------------------------- // usrtrig //------------------------- void usrtrig(unsigned long EVTYPE,unsigned long EVSOURCE) { unsigned long evtnum = *(rol->nevents); CEOPEN(ROCID,BT_BANK,blklevel); //===================================================== /* Set TI output 1 high for diagnostics */ tiSetOutputPort(1,0,0,0); /* Readout the trigger block from the TI Trigger Block MUST be reaodut first */ int dCnt = tiReadTriggerBlock(dma_dabufp); if(dCnt<=0) { printf("No data or error. dCnt = %d\n",dCnt); } else { /* TI Data is already in a bank structure. Bump the pointer */ dma_dabufp += dCnt; } /* EXAMPLE: How to open a bank (type=5) and add data words by hand */ BANKOPEN(5,BT_UI4,blockLevel); *dma_dabufp++ = tiGetIntCount(); *dma_dabufp++ = 0xdead; *dma_dabufp++ = 0xcebaf111; *dma_dabufp++ = 0xcebaf222; BANKCLOSE; /* Set TI output 0 low */ tiSetOutputPort(0,0,0,0); //===================================================== #if 1 CBOPEN(trigBankType,BT_SEG,blklevel); if(trigBankType == 0xff11) { *rol->dabufp++ = (EVTYPE<<24)|(0x01<<16)|(3); }else{ *rol->dabufp++ = (EVTYPE<<24)|(0x01<<16)|(1); } *rol->dabufp++ = (blklevel*(evtnum-1) + 1); if(trigBankType == 0xff11) { *rol->dabufp++ = 0x12345678; *rol->dabufp++ = 0; } CBCLOSE; #endif #if 1 // Read in event from file int stat=evRead(handle,mcbuffer,MCBUFSIZE); if(stat!=S_SUCCESS) { evClose(handle); if(evOpen(evioLocalFileName,"r",&handle)!=S_SUCCESS) { printf("?unable to reopen file %s\n",evioFileName); } else { printf("successfully reopened file %s\n",evioFileName); stat=evRead(handle,mcbuffer,MCBUFSIZE); } } // Write EVIO event to ouput buffer if(stat==S_SUCCESS) { // copy from local to output buffer uint32_t nword = mcbuffer[0]+1; memcpy((char*)rol->dabufp,(char*)&(mcbuffer[0]),nword*sizeof(uint32_t)); rol->dabufp += nword; } #endif CECLOSE; } //------------------------- // usrtrig_done //------------------------- void usrtrig_done() { } //------------------------- // done //------------------------- void __done() { poolEmpty = 0; /* global Done, Buffers have been freed */ if(USE_SOFTROC_CONTROLLER!=0 && domainID!=NULL){ // We are connected to a cMsg server so decrement // the event counter and check it to see if we need // to wait here for a cMsg to tell us to continue. Nevents_left--; if(Nevents_left == 0){ if(END_AT_NEXT_BOUNDARY){ printf("Finished block of triggers and ending...\n"); TESTflag = 0; return; }else{ printf("Finished block of triggers. Waiting for softROCcontroller..\n"); void *cmsg = cMsgCreateMessage(); cMsgSetSubject(cmsg, "softROCcontroller"); cMsgSetType(cmsg, cMsgName); cMsgSetText(cmsg, "ready"); cMsgSend(domainID, cmsg); cMsgFreeMessage(&cmsg); } } while(Nevents_left == 0)usleep(100000); } } //------------------------- // reset //------------------------- void __reset () { // Disconnect from cMsg server if connected if(domainID != NULL){ printf("Disconnecting from cMsg server ... \n"); cMsgReceiveStop(domainID); cMsgDisconnect(&domainID); domainID = NULL; }else{ printf("No cMsg connection so skipping disconnect.\n"); } Nevents_left = 1; } //------------------------- // MyCallback //------------------------- void MyCallback(void *msg, void *userArg) { const char *subject = NULL; const char *type = NULL; const char *cmd = NULL; cMsgGetSubject(msg, &subject); cMsgGetType(msg, &type); cMsgGetText(msg, &cmd); printf("cMsg received:\n"); printf(" subject: %s\n", subject ? subject:""); printf(" type: %s\n", type ? type:""); printf(" cmd: %s\n", cmd ? cmd:""); // If we get any kind of message, it must mean a // softROCcontroller is running USE_SOFTROC_CONTROLLER = 1; // prepare response message in case we need to send it void *cmsg = cMsgCreateMessage(); cMsgSetSubject(cmsg, type); cMsgSetType(cmsg, cMsgName); int sendResponse = 0; if(!strcmp(cmd, "roll call")){ cMsgSetText(cmsg, "present"); sendResponse = 1; }else if(!strcmp(cmd, "process triggers")){ cMsgGetUserInt(msg, &Nevents_left); printf("--- set Nevents_left to: %d\n", Nevents_left); } // If flag is set, then send the response message if(sendResponse) cMsgSend(domainID, cmsg); // Free the response message cMsgFreeMessage(&cmsg); }