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..0b32b5e 100644 --- a/ADHamaApp/Db/hama.template +++ b/ADHamaApp/Db/hama.template @@ -90,32 +90,36 @@ record(mbbi, "$(P)$(R)ColorMode_RBV") { field(SVVL, "") } -record(longin, "$(P)$(R)ArrayCounter_RBV") +record("*", "$(P)$(R)AcquirePeriod_RBV") { - field(FLNK, "$(P)$(R)#EVRTimeProc.PROC") + field(FLNK, "$(P)$(R)#EVRAcquireTime-S.PROC PP MS") } -record(ai, "$(P)$(R)#EVRTimeProc") { +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(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") -} - -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") + field(DOL, "$(P)$(R)#EVRTimeProc MS") + field(OMSL, "closed_loop") + field(DTYP, "asynOctetWrite") + field(OUT, "@asyn($(PORT),$(ADDR),$(TIMEOUT))EVR_TIMESTAMP") } record(ai, "$(P)$(R)FrameRate-R") { @@ -124,7 +128,45 @@ record(ai, "$(P)$(R)FrameRate-R") { field(INP, "@asyn($(PORT),$(ADDR),$(TIMEOUT))H_FRAMERATE") field(PREC, "2") field(SCAN, "I/O Intr") - field(PINI, "YES") +} + +record(seq, "$(P)$(R)#SoftSeqDisable") { + field(SELM, "All") + # Disable sequencer 0 + field(DOL1, "1") + field(LNK1, "$(EVR):SoftSeq-0-Disable-Cmd CP") +} + +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") } ########################################################################## @@ -315,21 +357,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 3b8b3cc..49cf33f 100644 --- a/ADHamaApp/src/hama.cpp +++ b/ADHamaApp/src/hama.cpp @@ -183,8 +183,8 @@ 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); setIntegerParam(NDArrayCallbacks, 1); callParamCallbacks(); @@ -789,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) { @@ -800,38 +799,29 @@ void Hama::imageTask(){ unlock(); status = epicsEventWait(startEvent_); - puts("Starting request received"); lock(); - /* We are acquiring. */ - //acquireStatusError = 0; - setIntegerParam(ADStatus, ADStatusAcquire); - status = startAcquire(); epicsTimeGetCurrent(&prevAcqTime); - printf("Status: %d\n", status); if (status != asynSuccess) { //acquireStatusError = 1; 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); 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,30 +845,30 @@ 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 _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); - - 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); - status = setDoubleParam(hTimeStamp, timestamp); + printf("readout_time: %f - exposure_time: %f\n", readout_time, exposure_time); - //printf("Timestamp from camera: %f\n", (ts_sec + ts_microsec / 1.0e6)); - //printf("Timestamp from camera with correction: %f\n", timestamp); + 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); + 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); @@ -899,7 +889,7 @@ void Hama::imageTask(){ if(pImage) { pImage->uniqueId = count; - pImage->timeStamp = ts_sec + (ts_microsec / 1.0e6); + pImage->timeStamp = timestamp; updateTimeStamp(&pImage->epicsTS); memcpy(pImage->pData, (epicsUInt16 *)image, pImage->dataSize); @@ -922,8 +912,8 @@ void Hama::imageTask(){ setShutter(0); stopAcquire(); setIntegerParam(ADAcquire, 0); + setIntegerParam(ADStatus, ADStatusIdle); } - callParamCallbacks(); } } @@ -1131,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; @@ -1151,19 +1138,18 @@ asynStatus Hama::writeInt32(asynUser *pasynUser, epicsInt32 value){ status = setIntegerParam(index, value); - if (index == ADAcquire) { - printf("[DEBUG]::writeInit32 ADAcquire\n"); - if (value) { + if (index == ADAcquire) { + 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(); } - } + } /* else if (index == ADMaxSizeX_RBV) { dcamprop_setvalue(m_hdcam, DETECTOR_PIXEL_NUM_HORZ, value); @@ -1618,9 +1604,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); @@ -1656,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; - getIntegerParam(hTriggerSource, &trigger_mode); + int trigger_mode = 0; + double acquire_period = 0; + status = getDoubleParam(ADAcquirePeriod, &acquire_period); + status = getIntegerParam(hTriggerSource, &trigger_mode); - if (trigger_mode != DCAMPROP_TRIGGERSOURCE__EXTERNAL) { - 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); + if (trigger_mode == DCAMPROP_TRIGGERSOURCE__EXTERNAL) { + if (value >= acquire_period) status = asynError; + else { + status = setFeature(DCAM_IDPROP_EXPOSURETIME, value); } + } - double acquire_period = 0; - status = getDoubleParam(ADAcquirePeriod, &acquire_period); + else { + status = setFeature(DCAM_IDPROP_EXPOSURETIME, value); 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) { @@ -1693,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); @@ -1712,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 @@ -1816,9 +1794,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) @@ -2093,7 +2068,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; } @@ -2113,8 +2087,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; } @@ -2135,21 +2115,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; } @@ -2165,7 +2130,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; @@ -2282,7 +2247,6 @@ asynStatus Hama::imageTransferStatus(HDCAM hdcam, DCAMCAP_TRANSFERINFO &captrans } if(captransferinfo.nFrameCount < 1) { - printf( "not capture image\n" ); return asynError; } diff --git a/ADHamaApp/src/hama.h b/ADHamaApp/src/hama.h index 7000c76..88fadf6 100644 --- a/ADHamaApp/src/hama.h +++ b/ADHamaApp/src/hama.h @@ -128,7 +128,7 @@ #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 #define DETECTOR_PIXEL_NUM_HORZ 0x00420830 @@ -151,6 +151,8 @@ public: int readParameter(int paramIndex); int readParameterStr(int paramIndex); + epicsUInt32 mTimeStampSec; + epicsUInt32 mTimeStampNsec; void imageTask(); void temperatureTask(); @@ -265,9 +267,9 @@ protected: int hImageDetectorPixelNumVert; int hTimeStampProducer; int hFrameStampProducer; + int evrTimeStamp; //---- - int hTimeStamp; - //#define LAST_HAMA_PARAM hTimeStamp + //#define LAST_HAMA_PARAM evrTimeStamp private: @@ -288,7 +290,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..cca1e4a 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,17 @@ dbpf Hama:cam1:PoolUsedMem.SCAN 0 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:NumImages 10 +#dbpf Hama:cam1:ImageMode 1 + #dbpf Hama:cam1:TriggerPolarity-S # 2-positive, 1-negative epicsThreadSleep(1.0) dbl > pv.list + # # END of st.cmd #