From 882f2771140f9e5722a2f50d91f0364861af7059 Mon Sep 17 00:00:00 2001 From: Douglas Araujo Date: Mon, 3 Apr 2023 10:51:02 +0200 Subject: [PATCH 1/8] Add dcambuf_release() function to release the internal receiving buffer in the DCAM module when stop an acquisition --- ADHamaApp/src/hama.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/ADHamaApp/src/hama.cpp b/ADHamaApp/src/hama.cpp index 3b8b3cc..2084859 100644 --- a/ADHamaApp/src/hama.cpp +++ b/ADHamaApp/src/hama.cpp @@ -2113,8 +2113,14 @@ return 0; asynStatus Hama::stopAcquire(void) { asynStatus status = asynSuccess; - dcamcap_stop(m_hdcam); + m_err = dcamcap_stop(m_hdcam); + if(failed(m_err)) { + printError(m_hdcam, m_err, "dcamcap_stop()"); + status = asynError; + } printf("Stop Capture\n"); + + freeBuffers(); return status; } From 11a7e3fe9e2219369a735f9e01d10a597023fb67 Mon Sep 17 00:00:00 2001 From: Douglas Araujo Date: Wed, 17 May 2023 12:32:06 +0200 Subject: [PATCH 2/8] Add external (EVR) timestamp --- ADHama.Makefile | 1 + ADHamaApp/Db/hama.template | 37 ++++++++++++++++++++++--------- ADHamaApp/src/hama.cpp | 45 +++++++++++++++++++++++++------------- ADHamaApp/src/hama.h | 6 ++++- cmds/st.cmd | 9 ++++++++ 5 files changed, 72 insertions(+), 26 deletions(-) diff --git a/ADHama.Makefile b/ADHama.Makefile index 4324898..fb86eff 100644 --- a/ADHama.Makefile +++ b/ADHama.Makefile @@ -38,6 +38,7 @@ endif REQUIRED += adcore REQUIRED += busy +REQUIRED += seq ############################################################################ diff --git a/ADHamaApp/Db/hama.template b/ADHamaApp/Db/hama.template index e4965a4..b7f9016 100644 --- a/ADHamaApp/Db/hama.template +++ b/ADHamaApp/Db/hama.template @@ -90,23 +90,40 @@ record(mbbi, "$(P)$(R)ColorMode_RBV") { field(SVVL, "") } -record(longin, "$(P)$(R)ArrayCounter_RBV") -{ - field(FLNK, "$(P)$(R)#EVRTimeProc.PROC") +record(ao, "$(P)$(R)ExtTriggerFreq-S") { + field(DESC, "External trigger frequency") + field(PREC, "3") + field(EGU, "Hz") + field(DRVL, "0") + field(DRVH, "500") + field(FLNK, "$(P)$(R)EVRAcquireTime-S.PROC PP MS") } -record(ai, "$(P)$(R)#EVRTimeProc") { +record(stringin, "$(P)$(R)#EVRTimeProc") { field(DESC, "Start proce the EVRTime record") - field(TSEL, "$(EVR):Evt$(E)Cnt-I.TIME") field(DTYP, "Soft Timestamp") - field(FLNK, "$(P)$(R)EVRTime-R.PROC") + field(SDIS, "$(EVR):Evt$(E)Cnt-I CP MS") + field(DISV, "-1") + field(TSEL, "$(EVR):Evt$(E)Cnt-I.TIME") + field(INP, "@%s.%f") + field(FLNK, "$(P)$(R)EVRTime-R.PROC PP MS") } -record(calc, "$(P)$(R)EVRTime-R") { +# holds TS value in 'sec.nsec' format +record(stringout, "$(P)$(R)EVRTime-R") { field(DESC, "EPICS epoch EVRTime timestamp") - field(CALC, "a+b") - field(INPA, "631152000") - field(INPB, "$(P)$(R)#EVRTimeProc") + field(DOL, "$(P)$(R)#EVRTimeProc MS") + field(OMSL, "closed_loop") + field(DTYP, "asynOctetWrite") + field(OUT, "@asyn($(PORT),$(ADDR),$(TIMEOUT))EVR_TIMESTAMP") +} + +record(calcout, "$(P)$(R)EVRAcquireTime-S") { + field(DESC, "Set EVR acquire time in seconds") + field(CALC, "A=0?B:(1/A)*B") + field(INPA, "$(P)$(R)ExtTriggerFreq-S") + field(INPB, "88052500") + field(OUT, "$(EVR):PS-1-Div-SP PP") } record(ai, "$(P)$(R)TimeStamp-RB") { diff --git a/ADHamaApp/src/hama.cpp b/ADHamaApp/src/hama.cpp index 2084859..fe9bcbc 100644 --- a/ADHamaApp/src/hama.cpp +++ b/ADHamaApp/src/hama.cpp @@ -185,6 +185,7 @@ Hama::Hama(const char* portName, int cameraId, int maxBuffers, size_t maxMemory, createParam( hFrameStampProducerString, asynParamInt32, &hFrameStampProducer); createParam( hTimeStampString, asynParamFloat64, &hTimeStamp); + createParam(evrTimeStampString, asynParamOctet, &evrTimeStamp); setIntegerParam(NDArrayCallbacks, 1); callParamCallbacks(); @@ -831,7 +832,7 @@ void Hama::imageTask(){ lock(); if (prevAcquisitionCount < (uint64_t)captransferinfo.nFrameCount) { - //printf("nFrameCount: %d, nNewestFrameIndex: %d\n", captransferinfo.nFrameCount, captransferinfo.nNewestFrameIndex); + printf("nFrameCount: %d\n", captransferinfo.nFrameCount); prevAcquisitionCount = captransferinfo.nFrameCount; // get image information @@ -855,11 +856,12 @@ void Hama::imageTask(){ count++; setIntegerParam(NDArrayCounter, count); - int32 ts_sec = 0, ts_microsec = 0; + epicsUInt32 ts_sec = 0, ts_microsec = 0; accessCapturedImage(m_hdcam, captransferinfo.nNewestFrameIndex, image, width * 2, width, height, ts_sec, ts_microsec); - double exposure_time, readout_time, timestamp; + double exposure_time, readout_time; + long double timestamp; //double _readouttime, _internal_frameinternal, _cyclictriggerperiod, _mintriggerblanking; //dcamprop_getvalue(m_hdcam, DCAM_IDPROP_TIMING_READOUTTIME, &_readouttime); @@ -874,11 +876,22 @@ void Hama::imageTask(){ dcamprop_getvalue(m_hdcam, DCAM_IDPROP_TIMING_READOUTTIME, &readout_time); dcamprop_getvalue(m_hdcam, DCAM_IDPROP_EXPOSURETIME, &exposure_time); - timestamp = (ts_sec + ts_microsec / 1.0e6) - (exposure_time + readout_time); + + printf("readout_time: %f - exposure_time: %f\n", readout_time, exposure_time); + timestamp = (ts_sec + ts_microsec / 1.0e6L) - (exposure_time + readout_time); status = setDoubleParam(hTimeStamp, timestamp); - //printf("Timestamp from camera: %f\n", (ts_sec + ts_microsec / 1.0e6)); - //printf("Timestamp from camera with correction: %f\n", timestamp); + char buf[256]; + getStringParam(evrTimeStamp, 256, buf); + + // remember parsed timestamp values + sscanf(buf, "%u.%u", &mTimeStampSec, &mTimeStampNsec); + //printf("ts_sec: %u - ts_microsec: %u\n", ts_sec, ts_microsec); + printf("mTimeStampSec: %u - mTimeStampNsec: %u\n", mTimeStampSec, mTimeStampNsec); + printf("Timestamp from camera : %f\n", (ts_sec + ts_microsec / 1.0e6)); + printf("Timestamp from camera with correction (long double): %.9Lf\n", timestamp); + printf("Timestamp from camera with correction (float): %f\n", (ts_sec + ts_microsec / 1.0e6) - (exposure_time + readout_time)); + printf("Timestamp from evr : %.9Lf\n", (mTimeStampSec + mTimeStampNsec / 1.0e9L)); epicsTimeGetCurrent(¤tAcqTime); elapsedTime = epicsTimeDiffInSeconds(¤tAcqTime, &prevAcqTime); @@ -899,8 +912,13 @@ void Hama::imageTask(){ if(pImage) { pImage->uniqueId = count; - pImage->timeStamp = ts_sec + (ts_microsec / 1.0e6); - updateTimeStamp(&pImage->epicsTS); + //pImage->timeStamp = timestamp; + //updateTimeStamp(&pImage->epicsTS); + + pImage->timeStamp = mTimeStampSec + mTimeStampNsec / 1.e9; + pImage->epicsTS.secPastEpoch = mTimeStampSec; + pImage->epicsTS.nsec = mTimeStampNsec; + //updateTimeStamp(&pImage->epicsTS); memcpy(pImage->pData, (epicsUInt16 *)image, pImage->dataSize); @@ -1618,9 +1636,9 @@ asynStatus Hama::writeInt32(asynUser *pasynUser, epicsInt32 value){ printf("[+DEBUG]:: ADDriver::writeInit32 %s\n", paramName); //ADDriver::writeInt32(pasynUser, value); } - else{ - printf("[-DEBUG]::function writeInt32 did not find a parameter index = %d, %s\n", index, paramName); - } + //else{ + // printf("[-DEBUG]::function writeInt32 did not find a parameter index = %d, %s\n", index, paramName); + //} } setIntegerParam(index, value); @@ -1816,9 +1834,6 @@ else if (index == hInternalLineInterval) { status = ADDriver::writeFloat64(pasynUser, value); printf("[+DEBUG]:: ADDriver::writeInit32 %s\n", paramName); } - else{ - printf("[-DEBUG]::function writeFloat64 did not find a parameter index = %d, %s\n", index, paramName); - } } if (status) @@ -2171,7 +2186,7 @@ inline void* memcpy_s( void* dst, size_t dstsize, const void* src, size_t srclen //============================================================================ asynStatus Hama::accessCapturedImage(HDCAM hdcam, int32 iFrame, void* buf, int32 rowbytes, int32 cx, int32 cy, - int32& ts_sec, int32& ts_microsec) + epicsUInt32& ts_sec, epicsUInt32& ts_microsec) { DCAMERR err; diff --git a/ADHamaApp/src/hama.h b/ADHamaApp/src/hama.h index 7000c76..1d4ad54 100644 --- a/ADHamaApp/src/hama.h +++ b/ADHamaApp/src/hama.h @@ -129,6 +129,7 @@ #define hTimeStampProducerString "H_TIMESTAMP_PRODUCER" /* asynInt32 ro */ #define hFrameStampProducerString "H_FRAMESTAMP_PRODUCER" /* asynInt32 ro */ #define hTimeStampString "H_TIMESTAMP" /* asynFloat64 ro */ +#define evrTimeStampString "EVR_TIMESTAMP" // For some reason these two addresses are not defined in the dcamapi4 neither in dcamprop.h #define DETECTOR_PIXEL_NUM_HORZ 0x00420830 @@ -151,6 +152,8 @@ public: int readParameter(int paramIndex); int readParameterStr(int paramIndex); + epicsUInt32 mTimeStampSec; + epicsUInt32 mTimeStampNsec; void imageTask(); void temperatureTask(); @@ -265,6 +268,7 @@ protected: int hImageDetectorPixelNumVert; int hTimeStampProducer; int hFrameStampProducer; + int evrTimeStamp; //---- int hTimeStamp; //#define LAST_HAMA_PARAM hTimeStamp @@ -288,7 +292,7 @@ private: asynStatus startAcquire(void); asynStatus stopAcquire(void); void getImageInformation(HDCAM hdcam, int32& pixeltype, int32& width, int32& rowbytes, int32& height, int32& framebytes); - asynStatus accessCapturedImage(HDCAM hdcam, int32 iFrame, void* buf, int32 rowbytes, int32 cx, int32 cy, int32& ts_sec, int32& ts_microsec); + asynStatus accessCapturedImage(HDCAM hdcam, int32 iFrame, void* buf, int32 rowbytes, int32 cx, int32 cy, epicsUInt32& ts_sec, epicsUInt32& ts_microsec); asynStatus imageTransferStatus(HDCAM hdcam, DCAMCAP_TRANSFERINFO &captransferinfo); // wrapper functions for dcamapi diff --git a/cmds/st.cmd b/cmds/st.cmd index ebb4796..1ad7c0b 100644 --- a/cmds/st.cmd +++ b/cmds/st.cmd @@ -1,6 +1,7 @@ # This should be a test startup script require adhama require adpluginkafka +require seq epicsEnvSet("PREFIX", "Hama:") @@ -65,11 +66,19 @@ dbpf Hama:cam1:PoolUsedMem.SCAN 0 dbpf Hama:image1:EnableCallbacks 1 dbpf Hama:Kfk1:EnableCallbacks 1 +#dbpf Hama:cam1:AcquireTime .0005 +#dbpf Hama:cam1:TriggerSource-S 1 # external +#dbpf Hama:cam1:NumImages 10 +#dbpf Hama:cam1:ImageMode 1 + #dbpf Hama:cam1:TriggerPolarity-S # 2-positive, 1-negative epicsThreadSleep(1.0) dbl > pv.list + +#seq external_acquire "EVR=$(EVR),PREFIX=${PREFIX},R=cam1:" + # # END of st.cmd # From 5751c2b7032c608d563818eb5c93a2dc94c9e8a4 Mon Sep 17 00:00:00 2001 From: Douglas Araujo Date: Sat, 20 May 2023 09:27:02 +0200 Subject: [PATCH 3/8] Add logic to select the correct timestamp source --- ADHamaApp/Db/hama.template | 9 ------ ADHamaApp/src/hama.cpp | 56 ++++++++++++-------------------------- ADHamaApp/src/hama.h | 4 +-- 3 files changed, 18 insertions(+), 51 deletions(-) diff --git a/ADHamaApp/Db/hama.template b/ADHamaApp/Db/hama.template index b7f9016..187cab2 100644 --- a/ADHamaApp/Db/hama.template +++ b/ADHamaApp/Db/hama.template @@ -126,15 +126,6 @@ record(calcout, "$(P)$(R)EVRAcquireTime-S") { field(OUT, "$(EVR):PS-1-Div-SP PP") } -record(ai, "$(P)$(R)TimeStamp-RB") { - field(DESC, "DCAM Timestamp when trigger received") - field(DTYP, "asynFloat64") - field(INP, "@asyn($(PORT),$(ADDR),$(TIMEOUT))H_TIMESTAMP") - field(PREC, "3") - field(SCAN, "I/O Intr") - field(PINI, "YES") -} - record(ai, "$(P)$(R)FrameRate-R") { field(DESC, "Acquisition frame rate") field(DTYP, "asynFloat64") diff --git a/ADHamaApp/src/hama.cpp b/ADHamaApp/src/hama.cpp index fe9bcbc..eb82e50 100644 --- a/ADHamaApp/src/hama.cpp +++ b/ADHamaApp/src/hama.cpp @@ -183,7 +183,6 @@ Hama::Hama(const char* portName, int cameraId, int maxBuffers, size_t maxMemory, createParam( hImageDetectorPixelNumVertString, asynParamInt32, &hImageDetectorPixelNumVert); createParam( hTimeStampProducerString, asynParamInt32, &hTimeStampProducer); createParam( hFrameStampProducerString, asynParamInt32, &hFrameStampProducer); - createParam( hTimeStampString, asynParamFloat64, &hTimeStamp); createParam(evrTimeStampString, asynParamOctet, &evrTimeStamp); @@ -790,10 +789,9 @@ void Hama::imageTask(){ epicsTimeStamp prevAcqTime, currentAcqTime; double elapsedTime; - //static const char *functionName = "imageTask"; + int triggerMode = DCAMPROP_TRIGGERSOURCE__INTERNAL; lock(); - while(1) { getIntegerParam(ADAcquire, &acquire); if(!acquire) { @@ -801,7 +799,6 @@ void Hama::imageTask(){ unlock(); status = epicsEventWait(startEvent_); - puts("Starting request received"); lock(); /* We are acquiring. */ @@ -810,7 +807,6 @@ void Hama::imageTask(){ status = startAcquire(); epicsTimeGetCurrent(&prevAcqTime); - printf("Status: %d\n", status); if (status != asynSuccess) { //acquireStatusError = 1; epicsThreadSleep(.1); @@ -860,38 +856,26 @@ void Hama::imageTask(){ accessCapturedImage(m_hdcam, captransferinfo.nNewestFrameIndex, image, width * 2, width, height, ts_sec, ts_microsec); - double exposure_time, readout_time; - long double timestamp; - - //double _readouttime, _internal_frameinternal, _cyclictriggerperiod, _mintriggerblanking; - //dcamprop_getvalue(m_hdcam, DCAM_IDPROP_TIMING_READOUTTIME, &_readouttime); - //dcamprop_getvalue(m_hdcam, DCAM_IDPROP_INTERNAL_FRAMEINTERVAL, &_internal_frameinternal); - //dcamprop_getvalue(m_hdcam, DCAM_IDPROP_TIMING_CYCLICTRIGGERPERIOD, &_cyclictriggerperiod); - //dcamprop_getvalue(m_hdcam, DCAM_IDPROP_TIMING_MINTRIGGERBLANKING, &_mintriggerblanking); - //printf("DCAM_IDPROP_TIMING_READOUTTIME: %f\n", _readouttime); - //printf("DCAM_IDPROP_INTERNAL_FRAMEINTERVAL: %f\n", _internal_frameinternal); - //printf("DCAM_IDPROP_TIMING_CYCLICTRIGGERPERIOD: %f\n", _cyclictriggerperiod); - //printf("DCAM_IDPROP_TIMING_MINTRIGGERBLANKING: %f\n", _mintriggerblanking); - + double exposure_time, readout_time, timestamp; dcamprop_getvalue(m_hdcam, DCAM_IDPROP_TIMING_READOUTTIME, &readout_time); dcamprop_getvalue(m_hdcam, DCAM_IDPROP_EXPOSURETIME, &exposure_time); - printf("readout_time: %f - exposure_time: %f\n", readout_time, exposure_time); - timestamp = (ts_sec + ts_microsec / 1.0e6L) - (exposure_time + readout_time); - status = setDoubleParam(hTimeStamp, timestamp); - char buf[256]; - getStringParam(evrTimeStamp, 256, buf); + getIntegerParam(hTriggerSource, &triggerMode); + if (triggerMode == DCAMPROP_TRIGGERSOURCE__EXTERNAL) { + char buf[256]; + getStringParam(evrTimeStamp, 256, buf); - // remember parsed timestamp values - sscanf(buf, "%u.%u", &mTimeStampSec, &mTimeStampNsec); - //printf("ts_sec: %u - ts_microsec: %u\n", ts_sec, ts_microsec); - printf("mTimeStampSec: %u - mTimeStampNsec: %u\n", mTimeStampSec, mTimeStampNsec); - printf("Timestamp from camera : %f\n", (ts_sec + ts_microsec / 1.0e6)); - printf("Timestamp from camera with correction (long double): %.9Lf\n", timestamp); - printf("Timestamp from camera with correction (float): %f\n", (ts_sec + ts_microsec / 1.0e6) - (exposure_time + readout_time)); - printf("Timestamp from evr : %.9Lf\n", (mTimeStampSec + mTimeStampNsec / 1.0e9L)); + // remember parsed timestamp values + sscanf(buf, "%u.%u", &mTimeStampSec, &mTimeStampNsec); + timestamp = mTimeStampSec + mTimeStampNsec / 1.e9; + printf("mTimeStampSec: %u - mTimeStampNsec: %u\n", mTimeStampSec, mTimeStampNsec); + printf("Timestamp from evr: %f\n", timestamp); + } else { + timestamp = (ts_sec + ts_microsec / 1.0e6) - (exposure_time + readout_time); + printf("Timestamp from camera: %f\n", timestamp); + } epicsTimeGetCurrent(¤tAcqTime); elapsedTime = epicsTimeDiffInSeconds(¤tAcqTime, &prevAcqTime); @@ -912,13 +896,8 @@ void Hama::imageTask(){ if(pImage) { pImage->uniqueId = count; - //pImage->timeStamp = timestamp; - //updateTimeStamp(&pImage->epicsTS); - - pImage->timeStamp = mTimeStampSec + mTimeStampNsec / 1.e9; - pImage->epicsTS.secPastEpoch = mTimeStampSec; - pImage->epicsTS.nsec = mTimeStampNsec; - //updateTimeStamp(&pImage->epicsTS); + pImage->timeStamp = timestamp; + updateTimeStamp(&pImage->epicsTS); memcpy(pImage->pData, (epicsUInt16 *)image, pImage->dataSize); @@ -941,7 +920,6 @@ void Hama::imageTask(){ stopAcquire(); setIntegerParam(ADAcquire, 0); } - callParamCallbacks(); } } diff --git a/ADHamaApp/src/hama.h b/ADHamaApp/src/hama.h index 1d4ad54..88fadf6 100644 --- a/ADHamaApp/src/hama.h +++ b/ADHamaApp/src/hama.h @@ -128,7 +128,6 @@ #define hImageDetectorPixelNumVertString "H_IMAGE_DETECTOR_PIXEL_NUM_VERT" /* asynInt32 ro */ #define hTimeStampProducerString "H_TIMESTAMP_PRODUCER" /* asynInt32 ro */ #define hFrameStampProducerString "H_FRAMESTAMP_PRODUCER" /* asynInt32 ro */ -#define hTimeStampString "H_TIMESTAMP" /* asynFloat64 ro */ #define evrTimeStampString "EVR_TIMESTAMP" // For some reason these two addresses are not defined in the dcamapi4 neither in dcamprop.h @@ -270,8 +269,7 @@ protected: int hFrameStampProducer; int evrTimeStamp; //---- - int hTimeStamp; - //#define LAST_HAMA_PARAM hTimeStamp + //#define LAST_HAMA_PARAM evrTimeStamp private: From 25e346e970d34f3b9f88b26073e544803435afaf Mon Sep 17 00:00:00 2001 From: Douglas Araujo Date: Tue, 23 May 2023 11:25:18 +0200 Subject: [PATCH 4/8] Add logic to start and stop evr sequencer --- ADHamaApp/Db/hama.template | 123 ++++++++++++++++++++++++++++++++++++- ADHamaApp/src/hama.cpp | 7 ++- cmds/st.cmd | 6 +- 3 files changed, 127 insertions(+), 9 deletions(-) diff --git a/ADHamaApp/Db/hama.template b/ADHamaApp/Db/hama.template index 187cab2..a1395c7 100644 --- a/ADHamaApp/Db/hama.template +++ b/ADHamaApp/Db/hama.template @@ -96,7 +96,7 @@ record(ao, "$(P)$(R)ExtTriggerFreq-S") { field(EGU, "Hz") field(DRVL, "0") field(DRVH, "500") - field(FLNK, "$(P)$(R)EVRAcquireTime-S.PROC PP MS") + field(FLNK, "$(P)$(R)#EVRAcquireTime-S.PROC PP MS") } record(stringin, "$(P)$(R)#EVRTimeProc") { @@ -118,7 +118,7 @@ record(stringout, "$(P)$(R)EVRTime-R") { field(OUT, "@asyn($(PORT),$(ADDR),$(TIMEOUT))EVR_TIMESTAMP") } -record(calcout, "$(P)$(R)EVRAcquireTime-S") { +record(calcout, "$(P)$(R)#EVRAcquireTime-S") { field(DESC, "Set EVR acquire time in seconds") field(CALC, "A=0?B:(1/A)*B") field(INPA, "$(P)$(R)ExtTriggerFreq-S") @@ -132,9 +132,128 @@ record(ai, "$(P)$(R)FrameRate-R") { field(INP, "@asyn($(PORT),$(ADDR),$(TIMEOUT))H_FRAMERATE") field(PREC, "2") field(SCAN, "I/O Intr") +} + +# PV that actually start the "burst" of events (On Demand) +# when the burst is finish, FLNK causes the sequencers to stop +record(busy, "$(P)$(R)StartFixedCycles") { + field(DESC, "StartFixedCycles") + field(OUT, "$(P)$(R)#SeqStartFixCycles.PROC PP") + field(FLNK, "$(P)$(R)#SeqDisableAll") +} + +# Procedure to start burst of events +record(seq, "$(P)$(R)#SeqStartFixCycles") { + field(SELM, "All") + + # Enable sequence stopper + field(DOL1, "0") + field(LNK1, "$(P)$(R)#StopAfterCycles.DISA") + + # Start sequencer as usual + field(DOL2, "1") + field(LNK2, "$(P)$(R)#Seq-Enable-Cond.PROC PP") + + # Only process this record when busy = 1 + field(SDIS, "$(P)$(R)StartFixedCycles") + field(DISV, "0") +} + +# When user selects "on demand" or when burst is ended +record(seq, "$(P)$(R)#SeqDisableAll") { + field(SELM, "All") + + # Disable sequencer 0 + field(DOL1, "1") + field(LNK1, "$(EVR):SoftSeq-0-Disable-Cmd CP") + + # Save current number of cycles + field(DOL2, "$(P)$(R)Cycle-Cnt") + field(LNK2, "$(P)$(R)#NCyclesPartial PP") + + # Disable Cycle Counter + field(DOL3, "1") + field(LNK3, "$(P)$(R)#StopAfterCycles.DISA") +} + + +record(longin, "$(P)$(R)Cycle-Cnt") { + field(DESC, "Cycle Counter") + field(SCAN, "Passive") + field(INP, "$(EVR):SoftSeq-0-NumOfStarts-I CPP") +} + +# Acts as a variable to store num. cycles before burst +record(ai, "$(P)$(R)#NCyclesPartial") { + field(DESC, "Num. cycles before burst") + field(DTYP, "Soft Channel") + field(SCAN, "Passive") +} + +## Stop sequence after N cycles +record(calcout, "$(P)$(R)#StopAfterCycles") { + field(DESC, "StopAfterCycles") + field(CALC, "C < (A + B)") + field(INPA, "$(P)$(R)#NCyclesPartial NPP") + field(INPB, "$(P)$(R)NCycles NPP") + field(INPC, "$(P)$(R)Cycle-Cnt CPP") + field(DISA, "1") + + # Write "Done" to busy when VAL(CALC) goes to zero + field(OOPT, "When Zero") + field(OUT, "$(P)$(R)StartFixedCycles PP") +} + +# User input for number of cycles when mode = On Demand (burst) +record(ao, "$(P)$(R)NCycles") { + field(DESC, "Number of cycles for fixed mode") + field(VAL, "10") field(PINI, "YES") } + +######################################################## +# Auxiliary record to indicate if EVM sequencers should +# be enabled (used by On Demand mode) +######################################################## +record(calc, "$(P)$(R)#Seq-Enable-Cond") { + field(INPA, "$(P)$(R)StartFixedCycles NPP") + + # Only enable SoftSeq-0 when the burst started (busy == 1) + field(CALC, "A=1 ? 2 : 1") + field(FLNK, "$(P)$(R)#SeqMainProcess PP") +} + + +record(seq, "$(P)$(R)#SeqMainProcess") { + field(SELM, "All") + # Conditionally enable sequencer + field(DOL1, "1") + field(LNK1, "$(P)$(R)#Seq-Enable-Disable.PROC") +} + + +######################################################## +# Trigger the processing of the record that decides +# if sequencer should be enabled or not +######################################################## +record(fanout, "$(P)$(R)#Seq-Enable-Disable") { + field(SELM, "Specified") + field(SELL, "$(P)$(R)#Seq-Enable-Cond") + field(LNK2, "$(P)$(R)#SoftSeq-Enable PP") +} + +record(seq, "$(P)$(R)#SoftSeq-Enable") { + field(SELM, "All") + # reset prescaler + field(DOL1, "123") + field(LNK1, "$(EVR):Evt-ResetPS-SP PP") + field(DOL2, "123") + field(LNK2, "$(EVR):EvtCode-SP.PROC PP") + field(LNK3, "$(EVR):SoftSeq-0-Enable-Cmd.PROC PP") +} + + ########################################################################## # General properties # ########################################################################## diff --git a/ADHamaApp/src/hama.cpp b/ADHamaApp/src/hama.cpp index eb82e50..57e9518 100644 --- a/ADHamaApp/src/hama.cpp +++ b/ADHamaApp/src/hama.cpp @@ -1147,8 +1147,9 @@ asynStatus Hama::writeInt32(asynUser *pasynUser, epicsInt32 value){ status = setIntegerParam(index, value); - if (index == ADAcquire) { - printf("[DEBUG]::writeInit32 ADAcquire\n"); + if (index == ADAcquire) { + printf("[DEBUG]::writeInit32 ADAcquire\n"); + printf("ADstatus: %d\n", adstatus); if (value) { /* Send an event to wake up the acq task.*/ puts("Requested acquire start event. Sending acquire start event signal to thread"); @@ -1159,7 +1160,7 @@ asynStatus Hama::writeInt32(asynUser *pasynUser, epicsInt32 value){ setShutter(0); stopAcquire(); } - } + } /* else if (index == ADMaxSizeX_RBV) { dcamprop_setvalue(m_hdcam, DETECTOR_PIXEL_NUM_HORZ, value); diff --git a/cmds/st.cmd b/cmds/st.cmd index 1ad7c0b..ba78033 100644 --- a/cmds/st.cmd +++ b/cmds/st.cmd @@ -66,8 +66,8 @@ dbpf Hama:cam1:PoolUsedMem.SCAN 0 dbpf Hama:image1:EnableCallbacks 1 dbpf Hama:Kfk1:EnableCallbacks 1 -#dbpf Hama:cam1:AcquireTime .0005 -#dbpf Hama:cam1:TriggerSource-S 1 # external +dbpf Hama:cam1:AcquireTime .05 +dbpf Hama:cam1:TriggerSource-S 1 # external #dbpf Hama:cam1:NumImages 10 #dbpf Hama:cam1:ImageMode 1 @@ -77,8 +77,6 @@ epicsThreadSleep(1.0) dbl > pv.list -#seq external_acquire "EVR=$(EVR),PREFIX=${PREFIX},R=cam1:" - # # END of st.cmd # From 7b73325de8018f32b11b1f1036f35957800a02d2 Mon Sep 17 00:00:00 2001 From: Douglas Araujo Date: Tue, 23 May 2023 14:59:20 +0200 Subject: [PATCH 5/8] Remove dcamwait frame since this is done by acquisition epicsThread --- ADHamaApp/src/hama.cpp | 42 +++++++----------------------------------- 1 file changed, 7 insertions(+), 35 deletions(-) diff --git a/ADHamaApp/src/hama.cpp b/ADHamaApp/src/hama.cpp index 57e9518..4d5bae8 100644 --- a/ADHamaApp/src/hama.cpp +++ b/ADHamaApp/src/hama.cpp @@ -801,10 +801,6 @@ void Hama::imageTask(){ status = epicsEventWait(startEvent_); lock(); - /* We are acquiring. */ - //acquireStatusError = 0; - setIntegerParam(ADStatus, ADStatusAcquire); - status = startAcquire(); epicsTimeGetCurrent(&prevAcqTime); if (status != asynSuccess) { @@ -812,16 +808,13 @@ void Hama::imageTask(){ epicsThreadSleep(.1); } else { + setIntegerParam(ADStatus, ADStatusAcquire); acquire = 1; - /* Get the current time */ prevAcquisitionCount = 0; setIntegerParam(ADNumImagesCounter, 0); } } - /* Added this delay for the thread not to hog the processor. No need to run on full speed. */ - //epicsThreadSleep(0.001); - // get image transfer status. unlock(); imageTransferStatus(m_hdcam, captransferinfo); @@ -919,6 +912,7 @@ void Hama::imageTask(){ setShutter(0); stopAcquire(); setIntegerParam(ADAcquire, 0); + setIntegerParam(ADStatus, ADStatusIdle); } callParamCallbacks(); } @@ -1127,10 +1121,7 @@ return status; //============================================================================ -asynStatus Hama::writeInt32(asynUser *pasynUser, epicsInt32 value){ - - - //printf("[DEBUG]::writeInt32\t"); +asynStatus Hama::writeInt32(asynUser *pasynUser, epicsInt32 value) { asynStatus status = asynSuccess; const char* functionName = "writeInt32"; const char* paramName; @@ -1148,17 +1139,15 @@ asynStatus Hama::writeInt32(asynUser *pasynUser, epicsInt32 value){ status = setIntegerParam(index, value); if (index == ADAcquire) { - printf("[DEBUG]::writeInit32 ADAcquire\n"); - printf("ADstatus: %d\n", adstatus); - if (value) { + if (value && adstatus != ADStatusAcquire) { /* Send an event to wake up the acq task.*/ puts("Requested acquire start event. Sending acquire start event signal to thread"); epicsEventSignal(this->startEvent_); } - else if (!value && (adstatus == ADStatusAcquire || adstatus == ADStatusError)) { + else if (!value && (adstatus == ADStatusAcquire || adstatus == ADStatusError || adstatus == ADStatusWaiting)) { /* This was a command to stop acquisition */ - setShutter(0); - stopAcquire(); + setIntegerParam(ADStatus, ADStatusAborted); + stopAcquire(); } } /* @@ -2087,7 +2076,6 @@ int Hama::disconnectCamera(void){ int Hama::allocateBuffers(unsigned int nBuffers) { m_err = dcambuf_alloc(m_hdcam, nBuffers); if(failed(m_err)) { - puts("banana"); printError(m_hdcam, m_err, "dcambuf_alloc()"); return asynError; } @@ -2135,21 +2123,6 @@ asynStatus Hama::startAcquire(void) printError(m_hdcam, m_err, "dcamcap_start()"); status = asynError; } - else { - printf( "\nStart Capture\n" ); - // set wait param - DCAMWAIT_START waitstart; - memset( &waitstart, 0, sizeof(waitstart) ); - waitstart.size = sizeof(waitstart); - waitstart.eventmask = DCAMWAIT_CAPEVENT_FRAMEREADY; - waitstart.timeout = DCAMWAIT_TIMEOUT_INFINITE; - - m_err = dcamwait_start(hwait, &waitstart); - if(failed(m_err)) { - printError(m_hdcam, m_err, "dcamwait_start()"); - status = asynError; - } - } return status; } @@ -2282,7 +2255,6 @@ asynStatus Hama::imageTransferStatus(HDCAM hdcam, DCAMCAP_TRANSFERINFO &captrans } if(captransferinfo.nFrameCount < 1) { - printf( "not capture image\n" ); return asynError; } From 63fc03a41ee973f3e8d7440dce47d91ec1b5c2d4 Mon Sep 17 00:00:00 2001 From: Douglas Araujo Date: Wed, 24 May 2023 15:30:44 +0200 Subject: [PATCH 6/8] Add logic to PV AcquirePeriod controls the EVR pulse period --- ADHamaApp/Db/hama.template | 53 +++++++++++++++++--------------------- ADHamaApp/src/hama.cpp | 34 ++++++++++-------------- cmds/st.cmd | 2 +- 3 files changed, 38 insertions(+), 51 deletions(-) diff --git a/ADHamaApp/Db/hama.template b/ADHamaApp/Db/hama.template index a1395c7..0473265 100644 --- a/ADHamaApp/Db/hama.template +++ b/ADHamaApp/Db/hama.template @@ -90,15 +90,19 @@ record(mbbi, "$(P)$(R)ColorMode_RBV") { field(SVVL, "") } -record(ao, "$(P)$(R)ExtTriggerFreq-S") { - field(DESC, "External trigger frequency") - field(PREC, "3") - field(EGU, "Hz") - field(DRVL, "0") - field(DRVH, "500") +record("*", "$(P)$(R)AcquirePeriod_RBV") +{ field(FLNK, "$(P)$(R)#EVRAcquireTime-S.PROC PP MS") } +record(calcout, "$(P)$(R)#EVRAcquireTime-S") { + field(DESC, "Set EVR acquire time in seconds") + field(CALC, "A=0?B:A*B") + field(INPA, "$(P)$(R)AcquirePeriod_RBV") + field(INPB, "88052500") + field(OUT, "$(EVR):PS-1-Div-SP PP") +} + record(stringin, "$(P)$(R)#EVRTimeProc") { field(DESC, "Start proce the EVRTime record") field(DTYP, "Soft Timestamp") @@ -118,14 +122,6 @@ record(stringout, "$(P)$(R)EVRTime-R") { field(OUT, "@asyn($(PORT),$(ADDR),$(TIMEOUT))EVR_TIMESTAMP") } -record(calcout, "$(P)$(R)#EVRAcquireTime-S") { - field(DESC, "Set EVR acquire time in seconds") - field(CALC, "A=0?B:(1/A)*B") - field(INPA, "$(P)$(R)ExtTriggerFreq-S") - field(INPB, "88052500") - field(OUT, "$(EVR):PS-1-Div-SP PP") -} - record(ai, "$(P)$(R)FrameRate-R") { field(DESC, "Acquisition frame rate") field(DTYP, "asynFloat64") @@ -442,21 +438,20 @@ record(mbbi, "$(P)$(R)BitPerChannel-RB") { ########################################################################## # Trigger source (mode 4) record(mbbo, "$(P)$(R)TriggerSource-S") { - field(DESC,"") - field(PINI, "YES") - field(DTYP, "asynInt32") - field(ZRVL, "1") - field(ZRST, "Internal") - field(ONVL, "2") - field(ONST, "External") - field(TWVL, "3") - field(TWST, "Software") - field(THVL, "4") - field(THST, "Master Pulse") -# field(DRVL, "1") -# field(DRVH, "4") - field(OUT, "@asyn($(PORT),$(ADDR),$(TIMEOUT))H_TRIGGER_SOURCE") - field(VAL, "1") + field(DESC,"") + field(PINI, "YES") + field(DTYP, "asynInt32") + field(ZRVL, "1") + field(ZRST, "Internal") + field(ONVL, "2") + field(ONST, "External") + field(TWVL, "3") + field(TWST, "Software") + field(THVL, "4") + field(THST, "Master Pulse") + field(OUT, "@asyn($(PORT),$(ADDR),$(TIMEOUT))H_TRIGGER_SOURCE") + field(VAL, "1") + field(FLNK, "$(P)$(R)AcquirePeriod.PROC PP MS") } record(mbbi, "$(P)$(R)TriggerSource-RB") { diff --git a/ADHamaApp/src/hama.cpp b/ADHamaApp/src/hama.cpp index 4d5bae8..7f7d396 100644 --- a/ADHamaApp/src/hama.cpp +++ b/ADHamaApp/src/hama.cpp @@ -1642,35 +1642,27 @@ asynStatus Hama::writeFloat64(asynUser *pasynUser, epicsFloat64 value){ //-- Feature if(index == ADAcquireTime) { printf("[DEBUG]::function ADAcquireTime from camera: %f\n", value); - status = setFeature(DCAM_IDPROP_EXPOSURETIME, value); - m_err = dcamprop_setgetvalue(m_hdcam, DCAM_IDPROP_EXPOSURETIME, &dvalue); - if(failed(m_err)) { - printError(m_hdcam, m_err, "dcamprop_setgetvalue()", "IDPROP:0x%08x, VALUE:%f\n", index, dvalue); - status = asynError; - } - /* int trigger_mode = 0; + int trigger_mode = 0; getIntegerParam(hTriggerSource, &trigger_mode); + m_err = dcamprop_getvalue(m_hdcam, DCAM_IDPROP_EXPOSURETIME, &dvalue); - if (trigger_mode != DCAMPROP_TRIGGERSOURCE__EXTERNAL) { + if (trigger_mode == DCAMPROP_TRIGGERSOURCE__EXTERNAL) { + if (dvalue <= value) status = asynError; + } + + else { status = setFeature(DCAM_IDPROP_EXPOSURETIME, value); - m_err = dcamprop_setgetvalue(m_hdcam, DCAM_IDPROP_EXPOSURETIME, &dvalue); - if(failed(m_err)) { - printError(m_hdcam, m_err, "dcamprop_setgetvalue()", "IDPROP:0x%08x, VALUE:%f\n", index, dvalue); - } + m_err = dcamprop_getvalue(m_hdcam, DCAM_IDPROP_EXPOSURETIME, &dvalue); double acquire_period = 0; status = getDoubleParam(ADAcquirePeriod, &acquire_period); if (value >= acquire_period) { - status = setDoubleParam(ADAcquirePeriod, 0); status = setFeature(DCAM_IDPROP_TRIGGERSOURCE, DCAMPROP_TRIGGERSOURCE__INTERNAL); status = setIntegerParam(hTriggerSource, DCAMPROP_TRIGGERSOURCE__INTERNAL); callParamCallbacks(); } - } - - else status = asynError; - */ + } } else if(index == ADAcquirePeriod) { @@ -1679,13 +1671,11 @@ asynStatus Hama::writeFloat64(asynUser *pasynUser, epicsFloat64 value){ int trigger_mode = 0; getIntegerParam(hTriggerSource, &trigger_mode); + m_err = dcamprop_getvalue(m_hdcam, DCAM_IDPROP_EXPOSURETIME, &dvalue); if (trigger_mode != DCAMPROP_TRIGGERSOURCE__EXTERNAL) { - m_err = dcamprop_getvalue(m_hdcam, DCAM_IDPROP_EXPOSURETIME, &dvalue); - if (value <= dvalue) { status = setFeature(DCAM_IDPROP_TRIGGERSOURCE, DCAMPROP_TRIGGERSOURCE__INTERNAL); status = setIntegerParam(hTriggerSource, DCAMPROP_TRIGGERSOURCE__INTERNAL); - value = 0; } else { status = setFeature(DCAM_IDPROP_TRIGGERSOURCE, DCAMPROP_TRIGGERSOURCE__MASTERPULSE); @@ -1698,7 +1688,9 @@ asynStatus Hama::writeFloat64(asynUser *pasynUser, epicsFloat64 value){ status = setIntegerParam(hMasterPulseMode, DCAMPROP_MASTERPULSE_MODE__CONTINUOUS); } } - else status = asynError; + else { + if (value <= dvalue) status = asynError; + } } //-- Trigger diff --git a/cmds/st.cmd b/cmds/st.cmd index ba78033..cca1e4a 100644 --- a/cmds/st.cmd +++ b/cmds/st.cmd @@ -67,7 +67,7 @@ dbpf Hama:image1:EnableCallbacks 1 dbpf Hama:Kfk1:EnableCallbacks 1 dbpf Hama:cam1:AcquireTime .05 -dbpf Hama:cam1:TriggerSource-S 1 # external +#dbpf Hama:cam1:TriggerSource-S 1 # external #dbpf Hama:cam1:NumImages 10 #dbpf Hama:cam1:ImageMode 1 From bfd746ac675dd53690b14f034b3d4448508932da Mon Sep 17 00:00:00 2001 From: Douglas Araujo Date: Wed, 24 May 2023 17:11:24 +0200 Subject: [PATCH 7/8] Fix acquireTime blocker logic to external trigger --- ADHamaApp/src/hama.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/ADHamaApp/src/hama.cpp b/ADHamaApp/src/hama.cpp index 7f7d396..49cf33f 100644 --- a/ADHamaApp/src/hama.cpp +++ b/ADHamaApp/src/hama.cpp @@ -1644,19 +1644,19 @@ asynStatus Hama::writeFloat64(asynUser *pasynUser, epicsFloat64 value){ printf("[DEBUG]::function ADAcquireTime from camera: %f\n", value); int trigger_mode = 0; - getIntegerParam(hTriggerSource, &trigger_mode); - m_err = dcamprop_getvalue(m_hdcam, DCAM_IDPROP_EXPOSURETIME, &dvalue); + double acquire_period = 0; + status = getDoubleParam(ADAcquirePeriod, &acquire_period); + status = getIntegerParam(hTriggerSource, &trigger_mode); if (trigger_mode == DCAMPROP_TRIGGERSOURCE__EXTERNAL) { - if (dvalue <= value) status = asynError; + if (value >= acquire_period) status = asynError; + else { + status = setFeature(DCAM_IDPROP_EXPOSURETIME, value); + } } else { status = setFeature(DCAM_IDPROP_EXPOSURETIME, value); - m_err = dcamprop_getvalue(m_hdcam, DCAM_IDPROP_EXPOSURETIME, &dvalue); - - double acquire_period = 0; - status = getDoubleParam(ADAcquirePeriod, &acquire_period); if (value >= acquire_period) { status = setFeature(DCAM_IDPROP_TRIGGERSOURCE, DCAMPROP_TRIGGERSOURCE__INTERNAL); status = setIntegerParam(hTriggerSource, DCAMPROP_TRIGGERSOURCE__INTERNAL); From a66877b3540c267e1f0afb177dc72f2528a715eb Mon Sep 17 00:00:00 2001 From: Douglas Araujo Date: Wed, 24 May 2023 17:17:04 +0200 Subject: [PATCH 8/8] Update the enable/disable EVR softSequencer logic to work with different kinds of acquisition modes --- ADHamaApp/Db/hama.template | 129 +++++++------------------------------ 1 file changed, 24 insertions(+), 105 deletions(-) diff --git a/ADHamaApp/Db/hama.template b/ADHamaApp/Db/hama.template index 0473265..0b32b5e 100644 --- a/ADHamaApp/Db/hama.template +++ b/ADHamaApp/Db/hama.template @@ -130,125 +130,44 @@ record(ai, "$(P)$(R)FrameRate-R") { field(SCAN, "I/O Intr") } -# PV that actually start the "burst" of events (On Demand) -# when the burst is finish, FLNK causes the sequencers to stop -record(busy, "$(P)$(R)StartFixedCycles") { - field(DESC, "StartFixedCycles") - field(OUT, "$(P)$(R)#SeqStartFixCycles.PROC PP") - field(FLNK, "$(P)$(R)#SeqDisableAll") -} - -# Procedure to start burst of events -record(seq, "$(P)$(R)#SeqStartFixCycles") { - field(SELM, "All") - - # Enable sequence stopper - field(DOL1, "0") - field(LNK1, "$(P)$(R)#StopAfterCycles.DISA") - - # Start sequencer as usual - field(DOL2, "1") - field(LNK2, "$(P)$(R)#Seq-Enable-Cond.PROC PP") - - # Only process this record when busy = 1 - field(SDIS, "$(P)$(R)StartFixedCycles") - field(DISV, "0") -} - -# When user selects "on demand" or when burst is ended -record(seq, "$(P)$(R)#SeqDisableAll") { - field(SELM, "All") - +record(seq, "$(P)$(R)#SoftSeqDisable") { + field(SELM, "All") # Disable sequencer 0 field(DOL1, "1") field(LNK1, "$(EVR):SoftSeq-0-Disable-Cmd CP") - - # Save current number of cycles - field(DOL2, "$(P)$(R)Cycle-Cnt") - field(LNK2, "$(P)$(R)#NCyclesPartial PP") - - # Disable Cycle Counter - field(DOL3, "1") - field(LNK3, "$(P)$(R)#StopAfterCycles.DISA") } - -record(longin, "$(P)$(R)Cycle-Cnt") { - field(DESC, "Cycle Counter") - field(SCAN, "Passive") - field(INP, "$(EVR):SoftSeq-0-NumOfStarts-I CPP") -} - -# Acts as a variable to store num. cycles before burst -record(ai, "$(P)$(R)#NCyclesPartial") { - field(DESC, "Num. cycles before burst") - field(DTYP, "Soft Channel") - field(SCAN, "Passive") -} - -## Stop sequence after N cycles -record(calcout, "$(P)$(R)#StopAfterCycles") { - field(DESC, "StopAfterCycles") - field(CALC, "C < (A + B)") - field(INPA, "$(P)$(R)#NCyclesPartial NPP") - field(INPB, "$(P)$(R)NCycles NPP") - field(INPC, "$(P)$(R)Cycle-Cnt CPP") - field(DISA, "1") - - # Write "Done" to busy when VAL(CALC) goes to zero - field(OOPT, "When Zero") - field(OUT, "$(P)$(R)StartFixedCycles PP") -} - -# User input for number of cycles when mode = On Demand (burst) -record(ao, "$(P)$(R)NCycles") { - field(DESC, "Number of cycles for fixed mode") - field(VAL, "10") - field(PINI, "YES") -} - - -######################################################## -# Auxiliary record to indicate if EVM sequencers should -# be enabled (used by On Demand mode) -######################################################## -record(calc, "$(P)$(R)#Seq-Enable-Cond") { - field(INPA, "$(P)$(R)StartFixedCycles NPP") - - # Only enable SoftSeq-0 when the burst started (busy == 1) - field(CALC, "A=1 ? 2 : 1") - field(FLNK, "$(P)$(R)#SeqMainProcess PP") -} - - -record(seq, "$(P)$(R)#SeqMainProcess") { - field(SELM, "All") - # Conditionally enable sequencer - field(DOL1, "1") - field(LNK1, "$(P)$(R)#Seq-Enable-Disable.PROC") -} - - -######################################################## -# Trigger the processing of the record that decides -# if sequencer should be enabled or not -######################################################## -record(fanout, "$(P)$(R)#Seq-Enable-Disable") { - field(SELM, "Specified") - field(SELL, "$(P)$(R)#Seq-Enable-Cond") - field(LNK2, "$(P)$(R)#SoftSeq-Enable PP") -} - -record(seq, "$(P)$(R)#SoftSeq-Enable") { +record(seq, "$(P)$(R)#SoftSeqEnable") { field(SELM, "All") # reset prescaler field(DOL1, "123") field(LNK1, "$(EVR):Evt-ResetPS-SP PP") field(DOL2, "123") field(LNK2, "$(EVR):EvtCode-SP.PROC PP") + # Enable sequencer 0 field(LNK3, "$(EVR):SoftSeq-0-Enable-Cmd.PROC PP") } +record("*", "$(P)$(R)Acquire") +{ + field(FLNK, "$(P)$(R)#CalcSoftSeqCtrl PP MS") +} + +record(calcout, "$(P)$(R)#CalcSoftSeqCtrl") { + field(DESC, "Calc software sequencer control") + field(CALC, "(A = 1 && B = 1) ? 1 : 0") + field(INPA, "$(P)$(R)Acquire") + field(INPB, "$(P)$(R)TriggerSource-RB") + field(OOPT, "On Change") + field(OUT, "$(P)$(R)#SoftSeqControl.PROC") +} + +record(fanout, "$(P)$(R)#SoftSeqControl") { + field(SELM, "Specified") + field(SELL, "$(P)$(R)#CalcSoftSeqCtrl") + field(LNK0, "$(P)$(R)#SoftSeqDisable PP") + field(LNK1, "$(P)$(R)#SoftSeqEnable PP") +} ########################################################################## # General properties #