/*---------------------------------------------------------------------------- H M _ A S I M A simulation histogramming memory driver for the ANSTO histogrammer. It has to be compiled with the C++ compiler and the SICServer has to be linked with C++. Paul Hathaway, September 2004 Copyright: see Copyright.txt ----------------------------------------------------------------------------*/ #include #include #include #include #include #include extern "C" { #include "fortify.h" #include "sics.h" #include "countdriv.h" #include "counter.h" #include "stringdict.h" #include "HistMem.h" #include "HistDriv.i" #include "hm_asim.h" } #include #define TESTVAL 128 /* define TESTVAL to set the simulated histogram to a fixed value for testing */ #define HM_ASIM_IDLE 0 #define HM_ASIM_BUSY 1 #define HM_ASIM_PAUSE 2 #define HM_ASIM_FAULT 3 #define HM_MODE_TIME 0 #define HM_MODE_COUNT 1 /*-------------------------------------------------------------------------*/ class AsimDetector { public: int iSet; HistInt iSetVal; AsimDetector(char *deviceName) { if(0 hm_data; HistMode eHistMode; vector hm_patch; vector hm_ctr; vector hm_tgt; static const long zero = 0; int iChannels; int iCounters; int iVetoCtr; int iMonCtr; long hm_monitor; int hm_state; int iCountMode; long lPreset; long lVetoThreshold; long iDuration; long iLastPollTime; long iRunningTime; float fFlux; }; /*---------------------------------------------------------------------------*/ float AsimDetector::SimRandom(void) { float fVal; fVal = ( (float) rand() / (float)RAND_MAX ) * 100.0; return fVal; } /*---------------------------------------------------------------------------*/ int AsimDetector::UpdateRunningTime() { time_t tD; time(&tD); /* This fn valid between Jan 1970 and Jan 2038 */ if (HM_ASIM_BUSY == hm_state) { iRunningTime += ((long)tD - iLastPollTime); } iLastPollTime = (long)tD; return 1; } /*----------------------------------------------------------------------------*/ int AsimDetector::UpdateCounters() { float fraction; switch (hm_state) { case HM_ASIM_BUSY: UpdateRunningTime(); fraction = (float)iRunningTime / (float)iDuration; FillCounters(fraction); // if (iRunningTime >= iDuration) // { // iRunningTime = iDuration; // FillCounters(1.0); // } // else /* Counting. Calculate intermediate counts */ // { // fraction = (float)iRunningTime / (float)iDuration; // FillCounters(fraction); // } if(1==IsCountComplete()) { hm_state = HM_ASIM_IDLE; } break; case HM_ASIM_PAUSE: UpdateRunningTime(); break; case HM_ASIM_IDLE: case HM_ASIM_FAULT: default: break; } return 1; } /*---------------------------------------------------------------------------*/ int AsimDetector::IsCountComplete() { switch(iCountMode) { case HM_MODE_TIME: if (iRunningTime >= iDuration) return 1; else return 0; break; case HM_MODE_COUNT: if (hm_monitor >= lPreset) return 1; else return 0; break; default: hm_state = HM_ASIM_FAULT; return 0; } } /*--------------------------------------------------------------------------*/ int AsimDetector::SetCounters(int numCounters) { // todo: test validity of numCounters hm_tgt.resize(numCounters); hm_ctr.resize(numCounters); for(int i=iCounters; iiChannels)||(destChn<0)) { return 0; } hm_patch[destChn] = srcCtr; return 1; } /*--------------------------------------------------------------------------*/ void AsimDetector::PatchHistogram() { for(int i=0;iiDuration) iDuration = 1; for(int i=0; i(iCounters-1))||(iCtr<0)) { iMonCtr = 0; return 0; } else { iMonCtr = iCtr; return 1; } } /*-------------------------------------------------------------------------*/ int AsimDetector::GetMonitor(HistInt *lData) { hm_monitor = hm_ctr[iMonCtr]; (*lData) = (HistInt) hm_monitor; return 1; } /*-------------------------------------------------------------------------*/ int AsimDetector::SetVetoInput(int iCtr) { if((iCtr>iChannels)||(iCtr<-1)) { iVetoCtr = -1; return 0; } iVetoCtr = iCtr; return 1; } /*-------------------------------------------------------------------------*/ int AsimDetector::SetVetoThreshold(HistInt lLevel) { lVetoThreshold = (long) lLevel; return 1; } /*-------------------------------------------------------------------------*/ int AsimDetector::GetVetoThreshold(HistInt *lLevel) { *lLevel = (HistInt) lVetoThreshold; return 1; } /*-------------------------------------------------------------------------*/ int AsimDetector::GetVeto(HistInt *lVeto) { if(0pPriv); // Configure TOF Mode if(pAsim->GetHistMode() == eHTOF) { for(i = 0; i < self->data->rank; i++) { iLength *= self->data->iDim[i]; } iLength *= self->data->nTimeChan; } // Configure Counters { int numCtrs = 0; float fVal; int iRet = StringDictGetAsNumber(pOption,"counters",&fVal); if(0SetCounters(numCtrs); numCtrs = pAsim->GetCounters(); sprintf(pBuffer,"STATUS:HM_ASIM: Register %d counters",numCtrs); SCWrite(pCon,pBuffer,eStatus); snprintf(pBuffer,10,"%-d",numCtrs); if(0==StringDictUpdate(pOption,"counters",pBuffer)) { StringDictAddPair(pOption,"counters",pBuffer); } } // Configure Channels { int numChan = 0; float fVal; int iRet = StringDictGetAsNumber(pOption,"channels",&fVal); if(0SetChannels(numChan); numChan = pAsim->GetChannels(); sprintf(pBuffer,"STATUS:HM_ASIM: Register %d channels",numChan); SCWrite(pCon,pBuffer,eStatus); snprintf(pBuffer,10,"%-d",numChan); if(0==StringDictUpdate(pOption,"channels",pBuffer)) { StringDictAddPair(pOption,"channels",pBuffer); } } // Configure Count Mode if (self->eCount == ePreset) { pAsim->SetCountMode(HM_MODE_COUNT); } else { pAsim->SetCountMode(HM_MODE_TIME); } // Configure Preset pAsim->SetPreset((long)(self->fCountPreset)); // Configure Channel to Counter patches int numChn = pAsim->GetChannels(); for(int ch=0; chSetPatch(ch,iCtr); sprintf(pBuffer,"STATUS:HM_ASIM: Patch Channel %d to Counter %d",ch,iCtr); } else { pAsim->SetPatch(ch,-1); sprintf(pBuffer,"STATUS:HM_ASIM: Disconnect Channel %d",ch); } SCWrite(pCon,pBuffer,eStatus); } // Configure Monitor Input (always set, default 0) { int iMonCtr = 0; float fVal; int iRet = StringDictGetAsNumber(pOption,"monitor_input",&fVal); if(0SetMonitorInput(iMonCtr); sprintf(pBuffer,"STATUS:HM_ASIM: Monitor Input Counter %d",iMonCtr); SCWrite(pCon,pBuffer,eStatus); snprintf(pBuffer,10,"%-d",iMonCtr); if(0==StringDictUpdate(pOption,"monitor_input",pBuffer)) { StringDictAddPair(pOption,"monitor_input",pBuffer); } } // Configure Veto Input (set to valid counter or disconnected(-1)) { int iVetoCtr; float fVal; int iRet = StringDictGetAsNumber(pOption,"veto_input",&fVal); if(0SetVetoInput(iVetoCtr); sprintf(pBuffer,"STATUS:HM_ASIM: Veto Input Counter %d",iVetoCtr); } else { iVetoCtr = -1; pAsim->SetVetoInput(iVetoCtr); sprintf(pBuffer,"STATUS:HM_ASIM: Veto Input Disconnected"); } SCWrite(pCon,pBuffer,eStatus); snprintf(pBuffer,10,"%-d",iVetoCtr); if(0==StringDictUpdate(pOption,"veto_input",pBuffer)) { StringDictAddPair(pOption,"veto_input",pBuffer); } } // Configure Veto Threshold (default 0) { HistInt lThreshold; float fVal; int iRet = StringDictGetAsNumber(pOption,"veto_threshold",&fVal); if(0SetVetoThreshold(lThreshold); pAsim->GetVetoThreshold(&lThreshold); sprintf(pBuffer,"STATUS:HM_ASIM: Veto Threshold %d",lThreshold); SCWrite(pCon,pBuffer,eStatus); snprintf(pBuffer,10,"%-d",lThreshold); if(0==StringDictUpdate(pOption,"veto_threshold",pBuffer)) { StringDictAddPair(pOption,"veto_threshold",pBuffer); } } // Configure Flux { float fVal; int iRet = StringDictGetAsNumber(pOption,"flux",&fVal); if(0SetFlux(fVal); } pAsim->GetFlux(&fVal); sprintf(pBuffer,"STATUS:HM_ASIM: Flux set to %.1f cps",fVal); SCWrite(pCon,pBuffer,eStatus); snprintf(pBuffer,16,"%.1f",fVal); if(0==StringDictUpdate(pOption,"flux",pBuffer)) { StringDictAddPair(pOption,"flux",pBuffer); } } pAsim->Reset(); if(1==iSuccess) { sprintf(pBuffer,"STATUS:HM_ASIM: AsimConfig Successful"); SCWrite(pCon,pBuffer,eStatus); return OKOK; } else { sprintf(pBuffer,"ERROR:HM_ASIM: AsimConfig Failed"); SCWrite(pCon,pBuffer,eError); return HWFault; } } /*-------------------------------------------------------------------------*/ static int AsimStart(pHistDriver self, SConnection *pCon) { AsimDetector *pAsim = NULL; pAsim = (AsimDetector *) (self->pPriv); // Configure Count Mode if (self->eCount == ePreset) pAsim->SetCountMode(HM_MODE_COUNT); else pAsim->SetCountMode(HM_MODE_TIME); pAsim->SetPreset((long)(self->fCountPreset)); if(1==pAsim->Start()) { SCWrite(pCon,"STATUS:HM_ASIM: Histogram Start Count",eStatus); return OKOK; } else { SCWrite(pCon,"ERROR:HM_ASIM: Histogram Start Count Failed",eError); return HWFault; } } /*-------------------------------------------------------------------------*/ static int AsimPause(pHistDriver self, SConnection *pCon) { AsimDetector *pAsim = NULL; pAsim = (AsimDetector *) (self->pPriv); if(1==pAsim->Pause()) { SCWrite(pCon,"STATUS:HM_ASIM: Histogram Pause Count",eStatus); return OKOK; } else { SCWrite(pCon,"ERROR:HM_ASIM: Histogram Pause Count Failed",eError); return HWFault; } } /*------------------------------------------------------------------------*/ static int AsimContinue(pHistDriver self, SConnection *pCon) { AsimDetector *pAsim = NULL; int iState; pAsim = (AsimDetector *) (self->pPriv); if(1==pAsim->Continue()) { SCWrite(pCon,"STATUS:HM_ASIM: Histogram Continue Count",eStatus); return OKOK; } else { SCWrite(pCon,"ERROR:HM_ASIM: Histogram Continue Count Failed",eError); return HWFault; } } /*-------------------------------------------------------------------------*/ static int AsimHalt(pHistDriver self) { AsimDetector *pAsim = NULL; pAsim = (AsimDetector *) (self->pPriv); if(1==pAsim->Halt()) return OKOK; else return HWFault; } /*-------------------------------------------------------------------------*/ static int AsimGetCountStatus(pHistDriver self, SConnection *pCon) { int status; int retCode; char error[80]; AsimDetector *pAsim = NULL; pAsim = (AsimDetector *) (self->pPriv); pAsim->GetCountStatus(&status); switch (status) { case HM_ASIM_IDLE: retCode = OKOK; break; case HM_ASIM_BUSY: retCode = HWBusy; break; case HM_ASIM_PAUSE: retCode = HWPause; break; case HM_ASIM_FAULT: default: retCode = HWFault; break; } return retCode; } /*-------------------------------------------------------------------------*/ static int AsimGetError(pHistDriver self, int *iCode, char *pError, int iLen) { AsimDetector *pAsim = NULL; pAsim = (AsimDetector *) (self->pPriv); *iCode = 0; strncpy(pError,"ERROR:HM_ASIM: 0", iLen); return OKOK; // QUESTION: Return 0 or OKOK; ? } /*-------------------------------------------------------------------------*/ static int AsimTryAndFixIt(pHistDriver self, int iCode) { int status; AsimDetector *pAsim = NULL; pAsim = (AsimDetector *) (self->pPriv); pAsim->GetCountStatus(&status); return AsimHalt(self); } /*--------------------------------------------------------------------------*/ static int AsimGetData(pHistDriver self, SConnection *pCon) { char error[80]; AsimDetector *pAsim = NULL; pAsim = (AsimDetector *) (self->pPriv); if (NULL!=pAsim) { if(0==pAsim->GetData()) { SCWrite(pCon,"ERROR:HM_ASIM: Histogram GetData failed",eError); return HWFault; } return OKOK; } return HWFault; } /*--------------------------------------------------------------------------*/ static int AsimGetHistogram(pHistDriver self, SConnection *pCon, int i, int iStart, int iEnd, HistInt *lData) { AsimDetector *pAsim = NULL; pAsim = (AsimDetector *) (self->pPriv); switch(AsimGetData(self,pCon)) { case OKOK: if(1==pAsim->GetHistogram(iStart,iEnd,lData)) { return OKOK; } else return HWFault; default: return HWFault; } return HWFault; } /*------------------------------------------------------------------------*/ static int AsimSetHistogram(pHistDriver self, SConnection *pCon, int i, int iStart, int iEnd, HistInt *lData) { AsimDetector *pAsim = NULL; pAsim = (AsimDetector *) (self->pPriv); pAsim->iSet = 1; pAsim->iSetVal = lData[0]; return OKOK; } /*-------------------------------------------------------------------------*/ static int AsimPreset(pHistDriver self, SConnection *pCon, HistInt iVal) { AsimDetector *pAsim = NULL; pAsim = (AsimDetector *) (self->pPriv); pAsim->iSet = 1; pAsim->iSetVal = iVal; return OKOK; } /*------------------------------------------------------------------------*/ static int AsimFreePrivate(pHistDriver self) { AsimDetector *pAsim = NULL; pAsim = (AsimDetector *) (self->pPriv); delete pAsim; return OKOK; } /*------------------------------------------------------------------------*/ static long AsimGetMonitor(pHistDriver self, int i, SConnection *pCon) { HistInt value; AsimDetector *pAsim = NULL; pAsim = (AsimDetector *) (self->pPriv); pAsim->GetMonitor(&value); return value; } /*------------------------------------------------------------------------*/ static float AsimGetTime(pHistDriver self, SConnection *pCon) { float value; AsimDetector *pAsim = NULL; pAsim = (AsimDetector *) (self->pPriv); pAsim->GetRunningTime(&value); return value; } /*-------------------------------------------------------------------------*/ pHistDriver CreateHmAsim(pStringDict pOpt) { pHistDriver pNew = NULL; AsimDetector *pAsim = NULL; /* create the general driver */ pNew = CreateHistDriver(pOpt); if(!pNew) { return NULL; } pAsim = new AsimDetector("simulation"); if(NULL==pAsim) { return NULL; } StringDictAddPair(pOpt,"device","hm_asim simulation"); pAsim->SetCounters(16); pAsim->SetChannels(10); /* if not using private data currently: pNew->pPriv = NULL; */ pNew->pPriv = pAsim; /* configure all those functions */ pNew->Configure = AsimConfig; pNew->Start = AsimStart; pNew->Halt = AsimHalt; pNew->GetCountStatus = AsimGetCountStatus; pNew->GetError = AsimGetError; pNew->TryAndFixIt = AsimTryAndFixIt; pNew->GetData = AsimGetData; pNew->GetHistogram = AsimGetHistogram; pNew->SetHistogram = AsimSetHistogram; pNew->GetMonitor = AsimGetMonitor; pNew->GetTime = AsimGetTime; pNew->Preset = AsimPreset; pNew->FreePrivate = AsimFreePrivate; pNew->Pause = AsimPause; pNew->Continue = AsimContinue; pNew->fCountPreset = 1; return pNew; }