24 #include "Win32Exceptions.h"
27 static void registerStructuredExceptionHandler() { }
28 static unsigned GetCurrentThreadId()
34 #include "registryFunction.h"
35 #include "epicsThread.h"
36 #include "epicsExit.h"
37 #include "epicsStdio.h"
38 #include "dbStaticLib.h"
39 #include "subRecord.h"
45 #include <epicsTypes.h>
46 #include <epicsTime.h>
47 #include <epicsThread.h>
48 #include <epicsString.h>
49 #include <epicsTimer.h>
50 #include <epicsMutex.h>
51 #include <epicsEvent.h>
52 #include <epicsMessageQueue.h>
57 #include <epicsGuard.h>
60 #define PLUGIN_NAME "epics"
62 #include "mpxpluginmgrapi.h"
66 #include <epicsExport.h>
70 static void debugOutput(
const char* msg)
77 static void epicsHelloWorldMenuItemFunc(MENUFUNCPAR par)
81 static void epicsFunc(
void* in,
void* out)
83 struct InParamStucture
90 InParamStucture *par= (InParamStucture*)in;
92 sprintf(message,
"Hello World\r(Inputs: %d,%lg,%lg,%c)",par->A,par->B[0],par->B[1],par->C);
98 static ExtFunctionInfo epicsFuncInfo={
108 {TYPE_DOUBLE,1,
"Out"}
112 "Function will show message box with gretings",
117 static int epicsFrameFilter(INTPTR userData, byte *in, byte *out)
119 FRAMEID fID = *(FRAMEID *) in;
120 ITEMID iID = *(ITEMID *) (in +
sizeof(FRAMEID));
123 g_epics->frameFilter(fID, iID, userData);
129 static ExtFunctionInfo epicsFrameFilterFuncInfo = {
134 {TYPE_U32, 1,
"ID of frame"},
135 {TYPE_U32, 1,
"ID of filter instance"},
141 "EPICS Frame Filter",
145 extern const FuncTableType *mgr;
148 static void mpxmgrExitCB(CBPARAM par, INTPTR userData)
155 static void mpxmgrStartCB(CBPARAM par, INTPTR userData)
160 static void mpxmgrFrameNewCB(CBPARAM par, INTPTR userData)
164 g_epics->pixelmanEventCB(pixelmanDriver::MPX_FRAMENEW, par, userData);
170 static void mpxctrlAcqStartCB(CBPARAM par, INTPTR userData)
174 g_epics->pixelmanEventCB(pixelmanDriver::MPX_ACQSTART, par, userData);
179 static void mpxctrlAcqPreStartCB(CBPARAM par, INTPTR userData)
183 g_epics->pixelmanEventCB(pixelmanDriver::MPX_ACQPRESTART, par, userData);
189 static void mpxctrlSingleAcqCompletedCB(CBPARAM par, INTPTR userData)
193 g_epics->pixelmanEventCB(pixelmanDriver::MPX_SINGLEACQCOMP, par, userData);
199 static void mpxctrlSeriesAcqCompletedCB(CBPARAM par, INTPTR userData)
203 g_epics->pixelmanEventCB(pixelmanDriver::MPX_SERIESACQCOMP, par, userData);
208 static int myLog(
const errlogSevEnum severity,
const char *pformat, ... )
212 va_start(pvar, pformat);
213 n = errlogSevVprintf(severity, pformat, pvar);
214 mgr->logMsgV(PLUGIN_NAME, pformat, 0, pvar);
220 static void mpxctrlMessageCB(CBPARAM par, INTPTR userData)
222 const char* msg = NULL;
224 if (mgr != NULL && g_epics != NULL)
226 status = mgr->mpxCtrlGetInfoMsg(g_epics->getDevId(), &msgType, &msg);
227 if (status == MPXERR_NOERROR && msg != NULL)
231 if (msgType != MPXERR_ACQABORTED)
235 errlogSevPrintf(errlogMajor,
"%s (%d)\n", msg, msgType);
239 errlogSevPrintf(errlogInfo,
"%s (%d)\n", msg, msgType);
253 registerStructuredExceptionHandler();
259 catch(
const std::exception& ex)
261 errlogSevPrintf(errlogMajor,
"pixelmanConfigure failed: %s", ex.what());
268 static const iocshArg initArg0 = {
"portName", iocshArgString};
269 static const iocshArg initArg1 = {
"devName", iocshArgString};
271 static const iocshArg *
const initArgs[] = { &initArg0, &initArg1 };
273 static const iocshFuncDef initFuncDef = {
"pixelmanConfigure",
sizeof(initArgs) /
sizeof(iocshArg*), initArgs};
275 static void initCallFunc(
const iocshArgBuf *args)
280 static void pixelmanRegister(
void)
282 iocshRegister(&initFuncDef, initCallFunc);
285 epicsExportRegistrar(pixelmanRegister);
289 extern "C" int pixelman_registerRecordDeviceDriver(
struct dbBase *pdbbase);
291 #define DBD_FILE "../dbd/pixelman.dbd"
292 #define DB_FILE "../db/pixelman.db"
305 mgr->logShowWindow(1);
315 if (freopen(
"pixelman_iocout.log",
"wt", stdout) == NULL)
317 mgr->logMsg(PLUGIN_NAME,
"Error redirecting stdout to pixelman_iocout.log", 0);
319 if (freopen(
"pixelman_iocerr.log",
"wt", stderr) == NULL)
321 mgr->logMsg(PLUGIN_NAME,
"Error redirecting stderr to pixelman_iocerr.log", 0);
323 if (setvbuf(stdout, NULL, _IONBF, 0) != 0)
325 mgr->logMsg(PLUGIN_NAME,
"Error making stdout unbuffered", 0);
327 if (setvbuf(stderr, NULL, _IONBF, 0) != 0)
329 mgr->logMsg(PLUGIN_NAME,
"Error making stderr unbuffered", 0);
332 if (mgr->registerCallback(MPXCTRL_NAME, MPXCTRL_CB_ACQPRESTART, mpxctrlAcqPreStartCB, NULL) != 0)
334 mgr->logMsg(PLUGIN_NAME,
"Error registering prestart callback", 0);
336 mgr->registerCallback(MPXCTRL_NAME, MPXCTRL_CB_ACQSERCOMPL, mpxctrlSeriesAcqCompletedCB, NULL);
337 mgr->registerCallback(MPXCTRL_NAME, MPXCTRL_CB_INFOMSG, mpxctrlMessageCB, NULL);
338 mgr->registerCallback(MPXCTRL_NAME, MPXCTRL_CB_ACQSTART, mpxctrlAcqStartCB, NULL);
342 mgr->registerCallback(MPXMGR_NAME, MPXMGR_CB_FRAME_NEW, mpxmgrFrameNewCB, NULL);
343 mgr->registerCallback(MPXCTRL_NAME, MPXCTRL_CB_ACQCOMPL, mpxctrlSingleAcqCompletedCB, NULL);
345 mgr->addFuncItem(&epicsFrameFilterFuncInfo);
347 const char* PIXELMANDIR = getenv(
"PIXELMANDIR");
348 if (PIXELMANDIR == NULL)
350 PIXELMANDIR =
"<UNKNOWN>";
352 mgr->logMsg(PLUGIN_NAME, (std::string(
"Camera directory: ") + PIXELMANDIR).c_str(), 0);
356 const char* PVPREFIX = getenv(
"MYPVPREFIX");
357 if (PVPREFIX == NULL)
361 epicsSnprintf(macros,
sizeof(macros),
"P=%s,Q=PIXELMAN:", PVPREFIX);
362 mgr->logMsg(PLUGIN_NAME,
"Starting EPICS IOC", 0);
365 mgr->logMsg(PLUGIN_NAME,
"Error in plugin function: cannot load DBD file", 0);
369 pixelman_registerRecordDeviceDriver(pdbbase);
376 mgr->logMsg(PLUGIN_NAME,
"Error in plugin function: cannot load DB file", 0);
383 mgr->logMsg(PLUGIN_NAME,
"Starting EPICS IOC - see pixelman_iocout.log and pixelman_iocerr.log", 0);
384 const char* PVPREFIX = getenv(
"MYPVPREFIX");
385 mgr->logMsg(PLUGIN_NAME,
"PV prefix P=%s", 0, (PVPREFIX != NULL ? PVPREFIX :
""));
386 const char* EPICSPIXELMAN = getenv(
"EPICSPIXELMAN");
387 if (EPICSPIXELMAN == NULL)
391 std::string pix_cmd = std::string(EPICSPIXELMAN) + std::string(
"/pixelman.cmd");
392 mgr->logMsg(PLUGIN_NAME, (std::string(
"Loading ") + pix_cmd).c_str(), 0);
393 if (iocsh(pix_cmd.c_str()))
395 mgr->logMsg(PLUGIN_NAME,
"Error in plugin function: cannot load pixelman.cmd", 0);
402 static const char *driverName =
"pixelmanDriver";
404 pixelmanDriver::pixelmanDriver(
const char *portName,
const char* devName)
410 asynInt32Mask | asynInt32ArrayMask | asynFloat64Mask | asynFloat64ArrayMask | asynOctetMask | asynDrvUserMask,
411 asynInt32Mask | asynInt32ArrayMask | asynFloat64Mask | asynFloat64ArrayMask | asynOctetMask,
416 m_acqRunning(false), m_cmd_running(false), m_start_running(false),
417 m_abort_running(false), m_devId(INVALID_DEVID_VALUE), m_autoRestart(0),
418 m_autoRestartDelay(0.0), m_eventCBQueue(40, sizeof(eventCBInfo)),
419 m_runEndQueue(40, sizeof(RunEndInfo)), m_frameQueue(40, sizeof(FrameInfo)), m_currentFrameID(0), m_pRaw(NULL)
422 const char *functionName =
"pixelmanDriver";
423 std::ostringstream pix_items;
428 createParam(P_acqAbortString, asynParamInt32, &P_acqAbort);
429 createParam(P_acqStartString, asynParamInt32, &P_acqStart);
430 createParam(P_trigAcqStartString, asynParamInt32, &P_trigAcqStart);
431 createParam(P_trigAcqStopString, asynParamInt32, &P_trigAcqStop);
432 createParam(P_numberOfAcqString, asynParamInt32, &P_numberOfAcq);
433 createParam(P_timeOfEachAcqString, asynParamFloat64, &P_timeOfEachAcq);
434 createParam(P_fileFlagsString, asynParamInt32, &P_fileFlags);
436 createParam(P_devIdString, asynParamInt32, &P_devId);
437 createParam(P_acqSActiveString, asynParamInt32, &P_acqSActive);
438 createParam(P_acqActiveString, asynParamInt32, &P_acqActive);
439 createParam(P_acqTypeString, asynParamInt32, &P_acqType);
440 createParam(P_acqTypeReqString, asynParamInt32, &P_acqTypeReq);
441 createParam(P_frameFilledString, asynParamInt32, &P_frameFilled);
442 createParam(P_acqTotalCountString, asynParamInt32, &P_acqTotalCount);
443 createParam(P_acqNumberString, asynParamInt32, &P_acqNumber);
444 createParam(P_acqModeString, asynParamInt32, &P_acqMode);
445 createParam(P_burstModeString, asynParamInt32, &P_burstMode);
446 createParam(P_extShutModeString, asynParamInt32, &P_extShutMode);
447 createParam(P_hwTimerString, asynParamInt32, &P_hwTimer);
448 createParam(P_saveConfigString, asynParamOctet, &P_saveConfig);
449 createParam(P_loadConfigString, asynParamOctet, &P_loadConfig);
450 createParam(P_saveDefConfigString, asynParamInt32, &P_saveDefConfig);
451 createParam(P_loadDefConfigString, asynParamInt32, &P_loadDefConfig);
452 createParam(P_acqHangString, asynParamInt32, &P_acqHang);
453 createParam(P_hangTimeString, asynParamFloat64, &P_hangTime);
454 createParam(P_autoRestartString, asynParamInt32, &P_autoRestart);
455 createParam(P_autoRestartDelayString, asynParamFloat64, &P_autoRestartDelay);
456 createParam(P_setPixelModeString, asynParamInt32, &P_setPixelMode);
457 createParam(P_frameIDString, asynParamInt32, &P_frameID);
459 setIntegerParam(ADAcquire, 0);
460 setIntegerParam(P_acqStart, 0);
461 setIntegerParam(P_acqAbort, 0);
462 setIntegerParam(P_acqSActive, 0);
463 setIntegerParam(P_acqActive, 0);
464 setIntegerParam(P_autoRestart, 0);
465 setDoubleParam(P_autoRestartDelay, 0.0);
466 setIntegerParam(P_frameID, 0);
468 int maxSizeX = 512, maxSizeY = 512;
469 NDDataType_t dataType = NDInt32;
470 int status = setStringParam (ADManufacturer,
"PIXELMAN");
471 status |= setStringParam (ADModel,
"PIXELMAN");
472 status |= setIntegerParam(ADMaxSizeX, maxSizeX);
473 status |= setIntegerParam(ADMaxSizeY, maxSizeY);
474 status |= setIntegerParam(ADMinX, 0);
475 status |= setIntegerParam(ADMinY, 0);
476 status |= setIntegerParam(ADBinX, 1);
477 status |= setIntegerParam(ADBinY, 1);
478 status |= setIntegerParam(ADReverseX, 0);
479 status |= setIntegerParam(ADReverseY, 0);
480 status |= setIntegerParam(ADSizeX, maxSizeX);
481 status |= setIntegerParam(ADSizeY, maxSizeY);
482 status |= setIntegerParam(NDArraySizeX, maxSizeX);
483 status |= setIntegerParam(NDArraySizeY, maxSizeY);
484 status |= setIntegerParam(NDArraySize, 0);
485 status |= setIntegerParam(NDDataType, dataType);
486 status |= setIntegerParam(ADImageMode, ADImageContinuous);
487 status |= setDoubleParam (ADAcquireTime, .001);
488 status |= setDoubleParam (ADAcquirePeriod, .005);
489 status |= setIntegerParam(ADNumImages, 100);
492 printf(
"%s: unable to set DAE parameters\n", functionName);
498 char name[NAME_LENGTH];
499 memset(name, 0, NAME_LENGTH);
501 DEVID devId = INVALID_DEVID_VALUE;
502 if ( mgr != NULL && mgr->mpxCtrlGetFirstMpx(&devId, &count) == 0 )
504 errlogSevPrintf(errlogInfo,
"There are %d devices available\n", count);
505 if (mgr->mpxCtrlGetCustomName(m_devId, name) == MPXERR_NOERROR)
507 name[NAME_LENGTH-1] =
'\0';
513 mgr->mpxCtrlGetDevInfo(devId, &devInfo);
514 errlogSevPrintf(errlogInfo,
"... devId %d name \"%s\" iface \"%s\" chipID \"%s\"\n", devId, name, devInfo.ifaceName, devInfo.chipboardID);
515 if (strcmp(devName, name) == 0 || strcmp(devName, devInfo.ifaceName) == 0)
517 errlogSevPrintf(errlogInfo,
"Found device \"%s\" (devId %d)\n", devName, devId);
519 memcpy(&m_devInfo, &devInfo,
sizeof(DevInfo));
520 printDevInfo(&m_devInfo, pix_items);
522 while(mgr->mpxCtrlGetNextMpx(&devId) == 0)
524 mgr->mpxCtrlGetCustomName(devId, name);
525 mgr->mpxCtrlGetDevInfo(devId, &devInfo);
526 errlogSevPrintf(errlogInfo,
"... devId %d name \"%s\" iface \"%s\" chipID \"%s\"\n", devId, name, devInfo.ifaceName, devInfo.chipboardID);
527 if (strcmp(devName, name) == 0 || strcmp(devName, devInfo.ifaceName) == 0)
529 errlogSevPrintf(errlogInfo,
"Found device \"%s\" (devId %d)\n", devName, devId);
531 memcpy(&m_devInfo, &devInfo,
sizeof(DevInfo));
532 printDevInfo(&m_devInfo, pix_items);
536 setIntegerParam(P_devId, m_devId);
537 if (getDevId() == INVALID_DEVID_VALUE)
539 errlogSevPrintf(errlogMajor,
"Device \"%s\" not found\n", devName);
544 getHwInfo(pix_items);
547 createParam(P_dataFileNameString, asynParamOctet, &P_dataFileName);
548 m_paramInfo[P_dataFileName] =
"DataFileName";
550 createParam(P_shutrCLKShiftString, asynParamInt32, &P_shutrCLKShift);
551 m_paramInfo[P_shutrCLKShift] =
"ShutrCLKShift";
552 createParam(P_tpxCubeBinString, asynParamFloat64, &P_tpxCubeBin);
553 m_paramInfo[P_tpxCubeBin] =
"TpxCubeBin";
554 createParam(P_dataAcqModeString, asynParamInt32, &P_dataAcqMode);
555 m_paramInfo[P_dataAcqMode] =
"AcqMode";
556 createParam(P_fileIndexString, asynParamInt32, &P_fileIndex);
557 m_paramInfo[P_fileIndex] =
"FileIndexToSaveDataInto";
559 createParam(P_saveRawDataString, asynParamInt32, &P_saveRawData);
560 m_paramInfo[P_saveRawData] =
"SaveRawData";
561 createParam(P_nShuttersPerBurstString, asynParamInt32, &P_nShuttersPerBurst);
562 m_paramInfo[P_nShuttersPerBurst] =
"TriggersPerBurst";
563 createParam(P_nTrigsBurstRefreshString, asynParamInt32, &P_nTrigsBurstRefresh);
564 m_paramInfo[P_nTrigsBurstRefresh] =
"BurstsToTake";
565 createParam(P_cameraStatusString, asynParamInt32, &P_cameraStatus);
566 m_paramInfo[P_cameraStatus] =
"CurrentStatus";
567 createParam(P_nTrigSavSubString, asynParamInt32, &P_nTrigSavSub);
568 m_paramInfo[P_nTrigSavSub] =
"NtrigBeforeSavingSubImgSpectra";
570 setIntegerParam(P_cameraStatus, STATUS_IDLE);
571 setIntegerParam(P_fileIndex, 0);
576 ExtCBEventInfo extCBEventInfo;
577 if (mgr->getRegFirstCBEvent(&cbEventID, &extCBEventInfo) == 0)
579 pix_items <<
"Plugin " << extCBEventInfo.pluginName <<
" offers event callback " << extCBEventInfo.cbEventName <<
" (" << extCBEventInfo.description <<
")" << std::endl;
580 while(mgr->getRegNextCBEvent(&cbEventID, &extCBEventInfo) == 0)
582 pix_items <<
"Plugin " << extCBEventInfo.pluginName <<
" offers event callback " << extCBEventInfo.cbEventName <<
" (" << extCBEventInfo.description <<
")" << std::endl;
585 char name[MENU_LENGTH];
587 if (mgr->getFirstMenuItem(&itemID, name) == 0)
589 pix_items <<
"Menu item " << name << std::endl;
590 while(mgr->getNextMenuItem(&itemID, name) == 0)
592 pix_items <<
"Menu item " << name << std::endl;
596 ExtFunctionInfo funcInfo;
597 if (mgr->getRegFirstFunc(&funcID, &funcInfo) == 0)
599 pix_items <<
"Plugin " << funcInfo.pluginName <<
" offers function " << funcInfo.functionName <<
" (" << funcInfo.description <<
")" << std::endl;
600 while(mgr->getRegNextFunc(&funcID, &funcInfo) == 0)
602 pix_items <<
"Plugin " << funcInfo.pluginName <<
" offers function " << funcInfo.functionName <<
" (" << funcInfo.description <<
")" << std::endl;
603 for(
int i=0; i<funcInfo.paramInCount; ++i)
605 pix_items <<
" arg_in[" << i <<
"] " << funcInfo.paramsInfoIn[i].description << std::endl;
607 for(
int i=0; i<funcInfo.paramOutCount; ++i)
609 pix_items <<
" arg_out[" << i <<
"] " << funcInfo.paramsInfoOut[i].description << std::endl;
617 std::fstream pfile(
"pixitems.txt", std::ios::out);
618 pfile << pix_items.str();
621 catch(
const std::exception& ex)
627 if (epicsThreadCreate(
"pixelmanDriverPoller",
628 epicsThreadPriorityMedium,
629 epicsThreadGetStackSize(epicsThreadStackMedium),
630 (EPICSTHREADFUNC)pollerThreadC,
this) == 0)
632 errlogSevPrintf(errlogMajor,
"%s:%s: epicsThreadCreate failure\n", driverName, functionName);
635 if (epicsThreadCreate(
"pixelmanDriverRestarter",
636 epicsThreadPriorityMedium,
637 epicsThreadGetStackSize(epicsThreadStackMedium),
638 (EPICSTHREADFUNC)pixelmanDriverRestarterC,
this) == 0)
640 errlogSevPrintf(errlogMajor,
"%s:%s: epicsThreadCreate failure\n", driverName, functionName);
643 if (epicsThreadCreate(
"pixelmanEventCBProcess",
644 epicsThreadPriorityMedium,
645 epicsThreadGetStackSize(epicsThreadStackMedium),
646 (EPICSTHREADFUNC)pixelmanEventCBProcessC,
this) == 0)
648 errlogSevPrintf(errlogMajor,
"%s:%s: epicsThreadCreate failure\n", driverName, functionName);
651 if (epicsThreadCreate(
"pixelmanDriverSaver",
652 epicsThreadPriorityMedium,
653 epicsThreadGetStackSize(epicsThreadStackMedium),
654 (EPICSTHREADFUNC)saverThreadC,
this) == 0)
656 errlogSevPrintf(errlogMajor,
"%s:%s: epicsThreadCreate failure\n", driverName, functionName);
661 int pixelmanDriver::getDevId()
const
666 void pixelmanDriver::pixelmanDriverRestarterC(
void* arg)
669 driver->pixelmanDriverRestarter();
672 static void myExitFunc(
const char* msg)
685 void pixelmanDriver::pixelmanDriverRestarter()
687 static const char* functionName =
"pixelmanDriverRestarter";
688 registerStructuredExceptionHandler();
694 epicsThreadSleep(delay);
695 if (m_autoRestart != 0)
697 epicsTimeGetCurrent(&now);
700 tdiff = epicsTimeDiffInSeconds(&now, &m_cmd_time);
701 if (tdiff > m_autoRestartDelay)
703 myExitFunc(
"pixelmanDriverRestarter: exiting (cmd)");
708 tdiff = epicsTimeDiffInSeconds(&now, &m_abort_time);
709 if (tdiff > m_autoRestartDelay)
711 myExitFunc(
"pixelmanDriverRestarter: exiting (abort)");
719 void pixelmanDriver::pollerThreadC(
void* arg)
722 driver->pollerThread();
725 void pixelmanDriver::saverThreadC(
void* arg)
728 driver->saverThread();
731 void pixelmanDriver::pollerThread()
733 static const char* functionName =
"pollerThread";
735 int acqNumber = 0, acqTotalCount = 0, acqType = 0, acqMode = 0, hwTimer = 0;
736 static u32 lastFrameFilled = 0;
739 epicsTimeStamp stop_begin, now;
741 int fileIndex, lastFileIndex = -1;
742 bool file_to_save =
false;
744 registerStructuredExceptionHandler();
745 epicsTimeGetCurrent(&stop_begin);
748 epicsThreadSleep(delay);
751 mgr->mpxCtrlGetAcqInfo(devId, &acqNumber, &acqTotalCount, &acqType, &frameFilled);
752 mgr->mpxCtrlGetAcqMode(devId, &acqMode);
753 mgr->mpxCtrlGetHwTimer(devId, &hwTimer);
755 getIntegerParam(P_autoRestart, &m_autoRestart);
756 getDoubleParam(P_autoRestartDelay, &m_autoRestartDelay);
757 getIntegerParam(P_cameraStatus, &cameraStatus);
758 getIntegerParam(P_fileIndex, &fileIndex);
759 if (lastFileIndex == -1)
761 lastFileIndex = fileIndex;
763 setIntegerParam(P_acqType, acqType);
764 setIntegerParam(P_frameFilled, frameFilled);
765 setIntegerParam(P_acqTotalCount, acqTotalCount);
766 setIntegerParam(P_acqNumber, acqNumber);
767 setIntegerParam(P_acqMode, (acqMode & 0xff) );
768 setIntegerParam(P_burstMode, ((acqMode & ACQMODE_BURST) != 0) );
769 setIntegerParam(P_extShutMode, ((acqMode & ACQMODE_EXTSHUTTER) != 0) );
770 setIntegerParam(P_hwTimer, hwTimer);
772 epicsTimeGetCurrent(&now);
773 double tdiff = epicsTimeDiffInSeconds(&now, &stop_begin);
774 bool acqHang =
false;
782 setIntegerParam(ADAcquire, 1);
783 setIntegerParam(P_acqActive, 1);
784 if (frameFilled == lastFrameFilled)
786 if (tdiff > m_autoRestartDelay)
789 if (m_autoRestart != 0)
791 myExitFunc(
"pollerThread: exiting");
797 lastFrameFilled = frameFilled;
798 epicsTimeGetCurrent(&stop_begin);
807 setIntegerParam(ADAcquire, 0);
808 setIntegerParam(P_acqActive, 0);
810 epicsTimeGetCurrent(&stop_begin);
813 setDoubleParam(P_hangTime, tdiff);
816 setIntegerParam(P_acqHang, 1);
820 setIntegerParam(P_acqHang, 0);
822 if (file_to_save && fileIndex > lastFileIndex)
824 saveFinished(lastFileIndex);
825 file_to_save =
false;
827 lastCameraStatus = cameraStatus;
828 lastFileIndex = fileIndex;
829 callParamCallbacks();
834 void pixelmanDriver::saveFinished(
int fileIndex)
837 getStringParam(P_dataFileName,
sizeof(info.fileName), info.fileName);
838 info.fileIndex = fileIndex;
839 m_runEndQueue.send(&info,
sizeof(RunEndInfo), 1.0);
842 static std::string quote(
const std::string& str)
848 void pixelmanDriver::saverThread()
851 const char* end_of_run = getenv(
"PIXELMANENDCMD");
852 const char* comspec = getenv(
"COMSPEC");
853 const char* pixelmandir = getenv(
"PIXELMANDIR");
854 epicsThreadSleep(1.0);
855 while( m_runEndQueue.receive(&info,
sizeof(RunEndInfo)) > 0 )
857 errlogSevPrintf(errlogInfo,
"Saved \"%s\" index %d\n", info.fileName, info.fileIndex);
858 mgr->logMsg(PLUGIN_NAME,
"Saved \"%s\" index %d", 0, info.fileName, info.fileIndex);
859 if (end_of_run != NULL)
861 errlogSevPrintf(errlogInfo,
"Executing \"%s\"\n", end_of_run);
862 mgr->logMsg(PLUGIN_NAME,
"Executing \"%s\"", 0, end_of_run);
864 sprintf(cFileIndex,
"%d", info.fileIndex);
866 if (_spawnl(_P_WAIT, comspec, comspec,
"/c", quote(end_of_run).c_str(), quote(pixelmandir).c_str(), quote(info.fileName).c_str(), cFileIndex, NULL) != 0)
871 mgr->logMsg(PLUGIN_NAME,
"ERROR executing \"%s\"", 0, end_of_run);
877 #define THROW_IF_ACQ_ACTIVE \
880 std::ostringstream acq_active_mess; \
881 acq_active_mess << functionName << ": cannot set " << paramName << " when acq active"; \
882 throw std::runtime_error(acq_active_mess.str().c_str()); \
885 #define THROW_IF_ACQ_NOT_ACTIVE \
888 std::ostringstream acq_not_active_mess; \
889 acq_not_active_mess << functionName << ": cannot set " << paramName << " when acq is not active"; \
890 throw std::runtime_error(acq_not_active_mess.str().c_str()); \
893 asynStatus pixelmanDriver::writeFloat64(asynUser *pasynUser, epicsFloat64 value)
895 int function = pasynUser->reason;
896 const char* functionName =
"writeFloat64";
897 asynStatus status = asynSuccess;
898 const char *paramName = NULL;
899 getParamName(
function, ¶mName);
901 if (
function < FIRST_MCP_PARAM)
903 return ADDriver::writeFloat64(pasynUser, value);
906 DEVID devId = getDevId();
907 registerStructuredExceptionHandler();
908 debugOutput(paramName);
916 throw std::runtime_error(
"pixelman not initialised");
918 else if (
function == P_tpxCubeBin)
921 setDoubleParam(
function, value);
922 setHwItem(m_paramInfo[
function],
function);
924 asynPrint(pasynUser, ASYN_TRACEIO_DRIVER,
925 "%s:%s: function=%d, name=%s, value=%f\n",
926 driverName, functionName,
function, paramName, value);
927 status = asynSuccess;
929 catch(
const std::exception& ex)
931 epicsSnprintf(pasynUser->errorMessage, pasynUser->errorMessageSize,
932 "%s:%s: status=%d, function=%d, name=%s, value=%f, error=%s",
933 driverName, functionName, status,
function, paramName, value, ex.what());
936 if (status == asynSuccess)
938 status = asynPortDriver::writeFloat64(pasynUser, value);
944 asynStatus pixelmanDriver::writeInt32(asynUser *pasynUser, epicsInt32 value)
946 int function = pasynUser->reason;
948 const char* functionName =
"writeInt32";
949 asynStatus status = asynSuccess;
950 const char *paramName = NULL;
951 getParamName(
function, ¶mName);
953 if (
function < FIRST_MCP_PARAM &&
function != ADAcquire)
955 return ADDriver::writeInt32(pasynUser, value);
958 DEVID devId = getDevId();
959 registerStructuredExceptionHandler();
960 debugOutput(paramName);
967 throw std::runtime_error(
"pixelman not initialised");
969 else if (
function == P_acqStart || (
function == ADAcquire && value == 1) )
972 setIntegerParam(ADAcquire, 1);
974 getIntegerParam(P_acqTypeReq, &acqTypeReq);
975 AcquisitionThreadArgs* args = createAcquisitionThreadArgs(acqTypeReq);
976 if (epicsThreadCreate(
"pixelmanAcquisitionStart",
977 epicsThreadPriorityMedium,
978 epicsThreadGetStackSize(epicsThreadStackMedium),
979 (EPICSTHREADFUNC)acquisitionThreadC, args) == 0)
981 errlogSevPrintf(errlogMajor,
"%s:%s: epicsThreadCreate failure\n", driverName, functionName);
984 epicsThreadSleep(0.1);
986 else if (
function == P_acqAbort || (
function == ADAcquire && value == 0) )
988 THROW_IF_ACQ_NOT_ACTIVE;
989 AcquisitionThreadArgs* args = createAcquisitionThreadArgs(
ACQ_ABORT);
998 acquisitionThreadC(args);
999 setIntegerParam(ADAcquire, 0);
1002 else if (
function == P_trigAcqStart)
1004 THROW_IF_ACQ_NOT_ACTIVE;
1005 mgr->mpxCtrlTrigger(devId, TRIGGER_ACQSTART);
1006 mgr->logMsg(PLUGIN_NAME,
"Acquisition Start triggered", 0);
1008 else if (
function == P_trigAcqStop)
1010 THROW_IF_ACQ_NOT_ACTIVE;
1011 mgr->mpxCtrlTrigger(devId, TRIGGER_ACQSTOP);
1012 mgr->logMsg(PLUGIN_NAME,
"Acquisition Stop triggered", 0);
1014 else if (
function == P_acqMode)
1016 THROW_IF_ACQ_ACTIVE;
1017 mgr->mpxCtrlGetAcqMode(devId, &acqMode);
1020 mgr->mpxCtrlSetAcqMode(devId, acqMode);
1022 else if (
function == P_burstMode)
1024 THROW_IF_ACQ_ACTIVE;
1025 mgr->mpxCtrlGetAcqMode(devId, &acqMode);
1028 acqMode |= ACQMODE_BURST;
1032 acqMode &= ~ACQMODE_BURST;
1034 mgr->mpxCtrlSetAcqMode(devId, acqMode);
1036 else if (
function == P_extShutMode)
1038 THROW_IF_ACQ_ACTIVE;
1039 mgr->mpxCtrlGetAcqMode(devId, &acqMode);
1042 acqMode |= ACQMODE_EXTSHUTTER;
1046 acqMode &= ~ACQMODE_EXTSHUTTER;
1048 mgr->mpxCtrlSetAcqMode(devId, acqMode);
1050 else if (
function == P_hwTimer)
1052 THROW_IF_ACQ_ACTIVE;
1053 mgr->mpxCtrlSetHwTimer(devId, value);
1055 else if (
function == P_saveDefConfig)
1057 THROW_IF_ACQ_ACTIVE;
1058 mgr->mpxCtrlSaveMpxCfgAsDefault(devId);
1060 else if (
function == P_loadDefConfig)
1062 THROW_IF_ACQ_ACTIVE;
1063 mgr->mpxCtrlLoadMpxCfg(devId, NULL);
1065 else if (
function == P_setPixelMode)
1067 THROW_IF_ACQ_ACTIVE;
1068 setPixelMode(value);
1070 else if (
function == P_shutrCLKShift ||
function == P_dataAcqMode ||
function == P_fileIndex ||
function == P_saveRawData ||
1071 function == P_nShuttersPerBurst ||
function == P_nTrigsBurstRefresh ||
function == P_nTrigSavSub)
1073 THROW_IF_ACQ_ACTIVE;
1074 setIntegerParam(
function, value);
1075 setHwItem(m_paramInfo[
function],
function);
1077 asynPrint(pasynUser, ASYN_TRACEIO_DRIVER,
1078 "%s:%s: function=%d, name=%s, value=%d\n",
1079 driverName, functionName,
function, paramName, value);
1080 status = asynSuccess;
1082 catch(
const std::exception& ex)
1084 epicsSnprintf(pasynUser->errorMessage, pasynUser->errorMessageSize,
1085 "%s:%s: status=%d, function=%d, name=%s, value=%d, error=%s",
1086 driverName, functionName, status,
function, paramName, value, ex.what());
1089 if (status == asynSuccess)
1091 if (
function == ADAcquire)
1093 status = ADDriver::writeInt32(pasynUser, value);
1097 status = asynPortDriver::writeInt32(pasynUser, value);
1104 asynStatus pixelmanDriver::writeOctet(asynUser *pasynUser,
const char *value,
size_t maxChars,
size_t *nActual)
1106 int function = pasynUser->reason;
1107 const char* functionName =
"writeOctet";
1108 asynStatus status = asynSuccess;
1109 const char *paramName = NULL;
1110 getParamName(
function, ¶mName);
1112 if (
function < FIRST_MCP_PARAM)
1114 return ADDriver::writeOctet(pasynUser, value, maxChars, nActual);
1117 DEVID devId = getDevId();
1118 registerStructuredExceptionHandler();
1119 debugOutput(paramName);
1122 std::string value_s;
1124 if ( (maxChars > 0) && (value[maxChars-1] ==
'\0') )
1126 value_s.assign(value, maxChars-1);
1130 value_s.assign(value, maxChars);
1137 throw std::runtime_error(
"pixelman not initialised");
1139 else if (
function == P_dataFileName)
1141 THROW_IF_ACQ_ACTIVE;
1142 std::string fname(value_s);
1143 const char* invalid_chars =
"<>:\"|?*";
1144 for(
int i=0; i<strlen(invalid_chars); ++i)
1146 std::replace(fname.begin(), fname.end(), invalid_chars[i],
'_');
1149 size_t pos = fname.find_last_of(
"/\\");
1151 if (pos != std::string::npos && pos > 0)
1153 char absPath[MAX_PATH];
1154 std::replace(fname.begin(), fname.end(),
'/',
'\\');
1155 if ( _fullpath(absPath, fname.substr(0,pos).c_str(),
sizeof(absPath)) == NULL )
1157 strncpy(absPath, fname.substr(0,pos).c_str(),
sizeof(absPath));
1159 if ( (_access(absPath, 0) != 0) && (SHCreateDirectoryEx(NULL, absPath, NULL) != ERROR_SUCCESS) )
1161 throw std::runtime_error( (std::string(
"Cannot create directory ") + absPath).c_str() );
1165 setStringParam(
function, value_s.c_str());
1166 setHwItem(m_paramInfo[
function],
function);
1168 else if (
function == P_saveConfig)
1170 THROW_IF_ACQ_ACTIVE;
1171 mgr->mpxCtrlSaveMpxCfg(devId, (value_s.size() > 0 ? value_s.c_str() : NULL) );
1173 else if (
function == P_loadConfig)
1175 THROW_IF_ACQ_ACTIVE;
1176 mgr->mpxCtrlLoadMpxCfg(devId, (value_s.size() > 0 ? value_s.c_str() : NULL) );
1178 asynPrint(pasynUser, ASYN_TRACEIO_DRIVER,
1179 "%s:%s: function=%d, name=%s, value=%s\n",
1180 driverName, functionName,
function, paramName, value_s.c_str());
1181 status = asynSuccess;
1183 catch(
const std::exception& ex)
1186 epicsSnprintf(pasynUser->errorMessage, pasynUser->errorMessageSize,
1187 "%s:%s: status=%d, function=%d, name=%s, value=%s, error=%s",
1188 driverName, functionName, status,
function, paramName, value_s.c_str(), ex.what());
1191 if (status == asynSuccess)
1193 *nActual = value_s.size();
1194 status = asynPortDriver::writeOctet(pasynUser, value, maxChars, nActual);
1204 void pixelmanDriver::pixelmanEventCB(PixelmanCBEvent e, CBPARAM par, INTPTR userData)
1206 eventCBInfo info(e, par, userData);
1207 m_eventCBQueue.send(&info,
sizeof(eventCBInfo), 1.0);
1211 void pixelmanDriver::pixelmanEventCBProcessC(
void* arg)
1214 driver->pixelmanEventCBProcess();
1217 void pixelmanDriver::pixelmanEventCBProcess()
1220 epicsThreadSleep(1.0);
1221 while(m_eventCBQueue.receive(&info,
sizeof(eventCBInfo)) > 0)
1226 case MPX_ACQPRESTART:
1228 setIntegerParam(ADAcquire, 1);
1229 setIntegerParam(P_acqActive, 1);
1230 setIntegerParam(P_acqSActive, 1);
1235 setIntegerParam(ADAcquire, 1);
1236 setIntegerParam(P_acqActive, 1);
1237 setIntegerParam(P_acqSActive, 1);
1240 case MPX_SINGLEACQCOMP:
1241 setIntegerParam(P_acqSActive, 0);
1244 case MPX_SERIESACQCOMP:
1245 m_acqRunning =
false;
1246 setIntegerParam(ADAcquire, 0);
1247 setIntegerParam(P_acqActive, 0);
1251 m_acqRunning =
true;
1252 m_currentFrameID = (FRAMEID)info.par;
1253 setIntegerParam(P_frameID, m_currentFrameID);
1259 callParamCallbacks();
1264 void pixelmanDriver::acquisitionThreadC(
void* arg)
1266 AcquisitionThreadArgs* args = (AcquisitionThreadArgs*)arg;
1267 args->driver->acquisitionThread(args);
1271 void pixelmanDriver::acquisitionThread(AcquisitionThreadArgs* args)
1273 registerStructuredExceptionHandler();
1276 errlogSevPrintf(errlogMajor,
"acquisitionThread: pixelman not initialised\n");
1282 sprintf(buffer,
"acquisitionThread start %d %d %d %d %d\n", GetCurrentThreadId(), args->acq_type, (m_acqRunning ? 1 : 0), (m_start_running ? 1 : 0), (m_abort_running ? 1 : 0));
1283 debugOutput(buffer);
1286 switch(args->acq_type)
1289 if (m_acq_start_mutex.tryLock())
1292 epicsTimeGetCurrent(&m_start_time);
1293 m_start_running =
true;
1294 m_acqRunning =
true;
1295 mgr->logMsg(PLUGIN_NAME,
"Starting frame acqusition: num %d time %f file flags %d file name \"%s\"", 0, args->numberOfAcq, args->timeOfEachAcq, args->fileFlags, args->fileName);
1296 if ( (status = mgr->mpxCtrlPerformFrameAcq(getDevId(), args->numberOfAcq, args->timeOfEachAcq, args->fileFlags, args->fileName)) != MPXERR_NOERROR )
1298 if (status != MPXERR_ACQABORTED)
1300 errlogSevPrintf(errlogMajor,
"Error from mpxCtrlPerformFrameAcq %d", status);
1305 mgr->logMsg(PLUGIN_NAME,
"Frame acqusition complete", 0);
1307 m_acqRunning =
false;
1308 m_start_running =
false;
1309 m_acq_start_mutex.unlock();
1313 mgr->logMsg(PLUGIN_NAME,
"Cannot start frame acqusition - already in progress", 0);
1314 debugOutput(
"Cannot start frame acqusition - already in progress\n");
1319 if (m_acq_start_mutex.tryLock())
1322 epicsTimeGetCurrent(&m_start_time);
1323 m_start_running =
true;
1324 m_acqRunning =
true;
1325 mgr->logMsg(PLUGIN_NAME,
"Starting integral acqusition: num %d time %f file flags %d file name \"%s\"", 0, args->numberOfAcq, args->timeOfEachAcq, args->fileFlags, args->fileName);
1326 if ( (status = mgr->mpxCtrlPerformIntegralAcq(getDevId(), args->numberOfAcq, args->timeOfEachAcq, args->fileFlags, args->fileName)) != MPXERR_NOERROR)
1328 if (status != MPXERR_ACQABORTED)
1330 errlogSevPrintf(errlogInfo,
"Error from mpxCtrlPerformIntegralAcq %d", status);
1335 mgr->logMsg(PLUGIN_NAME,
"Integral acqusition complete", 0);
1337 m_acqRunning =
false;
1338 m_start_running =
false;
1339 m_acq_start_mutex.unlock();
1343 mgr->logMsg(PLUGIN_NAME,
"Cannot start integral acqusition - already in progress", 0);
1344 debugOutput(
"Cannot start integral acqusition - already in progress\n");
1349 if (m_acq_abort_mutex.tryLock())
1352 epicsTimeGetCurrent(&m_abort_time);
1353 m_abort_running =
true;
1354 if ( (status = mgr->mpxCtrlAbortOperation(getDevId())) == MPXERR_NOERROR )
1356 m_acqRunning =
false;
1357 mgr->logMsg(PLUGIN_NAME,
"Acquisition Aborted", 0);
1361 errlogSevPrintf(errlogMajor,
"Error from mpxCtrlAbortOperation %d", status);
1362 mgr->logMsg(PLUGIN_NAME,
"Error Aborting Acquisition", 0);
1364 m_abort_running =
false;
1365 m_acq_abort_mutex.unlock();
1369 mgr->logMsg(PLUGIN_NAME,
"Cannot abort acqusition - already in progress", 0);
1370 debugOutput(
"Cannot abort acqusition - already in progress\n");
1375 mgr->logMsg(PLUGIN_NAME,
"Unknown acqusition mode requested", 0);
1380 catch(
const std::exception& ex)
1382 errlogSevPrintf(errlogMajor,
"Error from acquisitionThread %s", ex.what());
1386 errlogSevPrintf(errlogMajor,
"Error from acquisitionThread");
1388 sprintf(buffer,
"acquisitionThread stop %d %d %d %d %d\n", GetCurrentThreadId(), args->acq_type, (m_acqRunning ? 1 : 0), (m_start_running ? 1 : 0), (m_abort_running ? 1 : 0));
1389 debugOutput(buffer);
1393 void pixelmanDriver::getHwInfo(std::ostream& os)
1397 DEVID devId = getDevId();
1398 mgr->mpxCtrlGetHwInfoCount(devId, &hwcount);
1400 HwInfoItem* infoItem;
1401 int allocDataSize = 1024;
1403 for(
int i=0; i<hwcount; ++i)
1405 infoItem =
new HwInfoItem;
1406 infoItem->data =
new char[allocDataSize];
1407 dataSize = allocDataSize;
1408 if ( (status = mgr->mpxCtrlGetHwInfoItem(devId, i, infoItem, &dataSize)) != MPXERR_NOERROR )
1411 delete []((
char*)infoItem->data);
1412 infoItem->data =
new char[dataSize];
1413 status = mgr->mpxCtrlGetHwInfoItem(devId, i, infoItem, &dataSize);
1415 if (status != MPXERR_NOERROR)
1417 errlogSevPrintf(errlogMajor,
"getHwInfo: error from mpxCtrlGetHwInfoItem %d", status);
1420 m_hwInfo[infoItem->name] = HwInfo(infoItem, i, dataSize);
1421 os <<
"HWINFO: Found " << nameofType[infoItem->type] <<
"[" << infoItem->count <<
"] \"" << infoItem->name <<
"\" (" << infoItem->descr <<
")\n";
1425 void pixelmanDriver::getAllHwItems()
1427 for(std::map<int,std::string>::const_iterator it = m_paramInfo.begin(); it != m_paramInfo.end(); ++it)
1429 getHwItem(it->second, it->first);
1433 void pixelmanDriver::getHwItem(
const std::string& name,
int param)
1435 if ( m_hwInfo.find(name) == m_hwInfo.end() )
1439 DEVID devId = getDevId();
1440 HwInfo& info = m_hwInfo[name];
1441 int dataSize = info.dataSize;
1442 asynStatus astatus = asynSuccess;
1443 int status = mgr->mpxCtrlGetHwInfoItem(devId, info.index, info.item, &dataSize);
1444 if (status != MPXERR_NOERROR)
1446 delete []((
char*)info.item->data);
1447 info.item->data =
new char[dataSize];
1448 info.dataSize = dataSize;
1449 status = mgr->mpxCtrlGetHwInfoItem(devId, info.index, info.item, &dataSize);
1451 if (status != MPXERR_NOERROR)
1453 errlogSevPrintf(errlogMajor,
"getHwItem: error %d for %s", status, name.c_str());
1456 switch(info.item->type)
1460 astatus = setIntegerParam(param, *(
int*)info.item->data);
1464 astatus = setIntegerParam(param, *(
unsigned*)info.item->data);
1468 astatus = setDoubleParam(param, *(
float*)info.item->data);
1472 astatus = setDoubleParam(param, *(
double*)info.item->data);
1476 astatus = setIntegerParam(param, *(
short*)info.item->data);
1480 astatus = setIntegerParam(param, *(
unsigned short*)info.item->data);
1484 astatus = setIntegerParam(param, *(
unsigned char*)info.item->data);
1490 std::string s((
char*)info.item->data, info.item->count);
1491 astatus = setStringParam(param, s.c_str());
1496 astatus = setStringParam(param, (
char*)info.item->data);
1500 errlogSevPrintf(errlogMajor,
"getHwItem: unknown item type %d for %s", info.item->type, name.c_str());
1503 if (astatus != asynSuccess)
1505 errlogSevPrintf(errlogMajor,
"getHwItem: error setting asyn parameter for %s", name.c_str());
1510 void pixelmanDriver::setHwItem(
const std::string& name,
int param)
1512 if ( m_hwInfo.find(name) == m_hwInfo.end() )
1514 errlogSevPrintf(errlogMajor,
"setHwItem: unknown item \"%s\"", name.c_str());
1517 DEVID devId = getDevId();
1518 HwInfo& info = m_hwInfo[name];
1520 asynStatus astatus = asynSuccess;
1525 unsigned short usval;
1527 switch(info.item->type)
1532 if ( (astatus = getIntegerParam(param, &ival)) == asynSuccess )
1534 status = mgr->mpxCtrlSetHwInfoItem(devId, info.index, (byte*)&ival,
sizeof(ival));
1539 if ( (astatus = getDoubleParam(param, &dval)) == asynSuccess )
1542 status = mgr->mpxCtrlSetHwInfoItem(devId, info.index, (byte*)&fval,
sizeof(fval));
1547 if ( (astatus = getDoubleParam(param, &dval)) == asynSuccess )
1549 status = mgr->mpxCtrlSetHwInfoItem(devId, info.index, (byte*)&dval,
sizeof(dval));
1554 if ( (astatus = getIntegerParam(param, &ival)) == asynSuccess )
1557 status = mgr->mpxCtrlSetHwInfoItem(devId, info.index, (byte*)&sval,
sizeof(sval));
1562 if ( (astatus = getIntegerParam(param, &ival)) == asynSuccess )
1565 status = mgr->mpxCtrlSetHwInfoItem(devId, info.index, (byte*)&usval,
sizeof(usval));
1570 if ( (astatus = getIntegerParam(param, &ival)) == asynSuccess )
1573 status = mgr->mpxCtrlSetHwInfoItem(devId, info.index, &bval,
sizeof(bval));
1580 int n = info.item->count;
1581 char* buffer =
new char[n];
1582 memset(buffer, 0, n);
1583 if ( (astatus = getStringParam(param, n, buffer)) == asynSuccess )
1585 status = mgr->mpxCtrlSetHwInfoItem(devId, info.index, (byte*)buffer, n);
1593 char* buffer =
new char[info.dataSize];
1594 memset(buffer, 0, info.dataSize);
1595 if ( (astatus = getStringParam(param, info.dataSize, buffer)) == asynSuccess )
1597 status = mgr->mpxCtrlSetHwInfoItem(devId, info.index, (byte*)buffer, info.dataSize);
1604 errlogSevPrintf(errlogMajor,
"setHwItem: unknown item type %d for %s", info.item->type, name.c_str());
1607 if (astatus != asynSuccess)
1609 errlogSevPrintf(errlogMajor,
"setHwItem: error reading asyn parameter for %s", name.c_str());
1611 if (status != MPXERR_NOERROR)
1613 errlogSevPrintf(errlogMajor,
"setHwItem: error %d for %s", status, name.c_str());
1619 AcquisitionThreadArgs* args =
new AcquisitionThreadArgs(
this, at);
1620 memset(args->fileName, 0,
sizeof(args->fileName));
1621 getIntegerParam(P_numberOfAcq, &(args->numberOfAcq));
1622 getIntegerParam(P_fileFlags, reinterpret_cast<int*>(&(args->fileFlags)));
1623 getDoubleParam(P_timeOfEachAcq, &(args->timeOfEachAcq));
1624 getStringParam(P_dataFileName,
sizeof(args->fileName), args->fileName);
1629 void pixelmanDriver::setPixelMode(
unsigned mode)
1631 DEVID devId = getDevId();
1634 errlogSevPrintf(errlogMajor,
"setPixelMode: invalid mode");
1637 if (m_devInfo.numberOfChips * MATRIX_SIZE != m_devInfo.pixCount)
1639 errlogSevPrintf(errlogMajor,
"setPixelMode: invalid number of pixels");
1642 if (m_devInfo.mpxType != MPX_TPX)
1644 errlogSevPrintf(errlogMajor,
"setPixelMode: not timepix");
1647 int npixels = m_devInfo.pixCount;
1648 TpxPixCfg* pixels(
new TpxPixCfg[npixels]);
1649 if (mgr->mpxCtrlGetPixelsCfg(devId, reinterpret_cast<byte*>(pixels), npixels *
sizeof(TpxPixCfg), ALLCHIPS) != MPXERR_NOERROR)
1651 errlogSevPrintf(errlogMajor,
"setPixelMode: mpxCtrlGetPixelsCfg failed");
1655 for(
int i=0; i<npixels; ++i)
1657 pixels[i].mode = mode;
1659 if (mgr->mpxCtrlSetPixelsCfg(devId, reinterpret_cast<byte*>(pixels), npixels *
sizeof(TpxPixCfg), ALLCHIPS) != MPXERR_NOERROR)
1661 errlogSevPrintf(errlogMajor,
"setPixelMode: mpxCtrlSetPixelsCfg failed");
1669 void pixelmanDriver::printDevInfo(DevInfo* devInfo, std::ostream& os)
1671 os <<
"Number of pixels: " << devInfo->pixCount << std::endl;
1672 os <<
"Row length: " << devInfo->rowLen << std::endl;
1673 os <<
"Number of chips: " << devInfo->numberOfChips << std::endl;
1674 os <<
"Number rows: " << devInfo->numberOfRows << std::endl;
1675 os <<
"Medipix type: " << devInfo->mpxType << std::endl;
1676 os <<
"Supported acq modes: " << devInfo->suppAcqModes << std::endl;
1677 os <<
"Support callbacks: " << devInfo->suppCallback << std::endl;
1680 void pixelmanDriver::setADAcquire(
int acquire)
1685 asynStatus status = asynSuccess;
1688 getIntegerParam(ADStatus, &adstatus);
1689 getIntegerParam(ADAcquire, &acquiring);
1690 getIntegerParam(ADImageMode, &imageMode);
1691 if (acquire && !acquiring) {
1692 setStringParam(ADStatusMessage,
"Acquiring data");
1693 setIntegerParam(ADStatus, ADStatusAcquire);
1694 setIntegerParam(ADAcquire, 1);
1696 if (!acquire && acquiring) {
1697 setIntegerParam(ADAcquire, 0);
1698 setStringParam(ADStatusMessage,
"Acquisition stopped");
1699 if (imageMode == ADImageContinuous) {
1700 setIntegerParam(ADStatus, ADStatusIdle);
1702 setIntegerParam(ADStatus, ADStatusAborted);
1712 getIntegerParam(ADShutterMode, &shutterMode);
1713 if (shutterMode == ADShutterModeDetector) {
1715 setIntegerParam(ADShutterStatus, open);
1718 ADDriver::setShutter(open);
1723 void pixelmanDriver::frameFilter(FRAMEID fID, ITEMID iID, INTPTR userData)
1728 double queue_timeout = 0.015;
1729 FrameInfo info(fID, iID, userData);
1730 int stat = mgr->openFrame(fID, &refCount);
1733 if (m_frameQueue.send(&info,
sizeof(FrameInfo), queue_timeout) != 0)
1735 stat = mgr->closeFrame(fID, &refCount);
1741 void pixelmanDriver::frameProcess()
1744 u32 refCount, width, height, byteSize;
1747 Data_Types frame_type;
1748 while( m_frameQueue.receive(&info,
sizeof(FrameInfo)) > 0 )
1750 stat = mgr->getFrameType(info.fID, &frame_type);
1751 stat = mgr->getFrameSize(info.fID, &width, &height);
1752 buffer =
new u32[width * height];
1753 byteSize = width * height *
sizeof(u32) + 64;
1754 stat = mgr->getFrameData(info.fID, (byte*)buffer, &byteSize, TYPE_U32);
1755 if (byteSize != width * height *
sizeof(u32))
1760 stat = mgr->closeFrame(info.fID, &refCount);
1764 void pixelmanDriver::readFrame()
1766 u32 refCount, width = 0, height = 0, byteSize;
1769 FRAMEID FrameID = m_currentFrameID;
1771 stat = mgr->openFrame(FrameID, &refCount);
1777 stat = mgr->getFrameSize(FrameID, &width, &height);
1778 if (stat != 0 || width == 0 || height == 0)
1780 mgr->closeFrame(FrameID, &refCount);
1783 buffer =
new u32[width * height];
1786 mgr->closeFrame(FrameID, &refCount);
1789 byteSize = width * height *
sizeof(u32) + 64;
1790 stat = mgr->getFrameData(FrameID, (byte*)buffer, &byteSize, TYPE_U32);
1791 mgr->closeFrame(FrameID, &refCount);
1792 if ( stat != 0 || byteSize != width * height *
sizeof(u32) )
1798 processFrame(buffer, width, height);
1804 void pixelmanDriver::processFrame(u32* buffer, u32 width, u32 height)
1806 static const char* functionName =
"processFrame";
1808 int status = asynSuccess;
1810 int numImages, numImagesCounter;
1814 double acquireTime, acquirePeriod, delay;
1815 epicsTimeStamp startTime, endTime;
1818 setIntegerParam(ADSizeX, width);
1819 setIntegerParam(ADSizeY, height);
1820 getIntegerParam(ADAcquire, &acquiring);
1821 getDoubleParam(ADAcquirePeriod, &acquirePeriod);
1822 setIntegerParam(ADStatus, ADStatusAcquire);
1823 epicsTimeGetCurrent(&startTime);
1824 getIntegerParam(ADImageMode, &imageMode);
1827 getDoubleParam(ADAcquireTime, &acquireTime);
1830 callParamCallbacks();
1834 for(
int i=0; i<width*height; ++i)
1836 if (buffer[i] > maxval)
1849 setIntegerParam(ADStatus, ADStatusReadout);
1851 callParamCallbacks();
1853 pImage = this->pArrays[0];
1856 getIntegerParam(NDArrayCounter, &imageCounter);
1857 getIntegerParam(ADNumImages, &numImages);
1858 getIntegerParam(ADNumImagesCounter, &numImagesCounter);
1859 getIntegerParam(NDArrayCallbacks, &arrayCallbacks);
1862 setIntegerParam(NDArrayCounter, imageCounter);
1863 setIntegerParam(ADNumImagesCounter, numImagesCounter);
1866 pImage->uniqueId = imageCounter;
1867 pImage->timeStamp = startTime.secPastEpoch + startTime.nsec / 1.e9;
1868 updateTimeStamp(&pImage->epicsTS);
1871 this->getAttributes(pImage->pAttributeList);
1873 if (arrayCallbacks) {
1878 asynPrint(this->pasynUserSelf, ASYN_TRACE_FLOW,
1879 "%s:%s: calling imageData callback\n", driverName, functionName);
1880 doCallbacksGenericPointer(pImage, NDArrayData, 0);
1885 callParamCallbacks();
1887 epicsTimeGetCurrent(&endTime);
1888 elapsedTime = epicsTimeDiffInSeconds(&endTime, &startTime);
1889 delay = acquirePeriod - elapsedTime;
1890 asynPrint(this->pasynUserSelf, ASYN_TRACE_FLOW,
1891 "%s:%s: delay=%f\n",
1892 driverName, functionName, delay);
1908 int status = asynSuccess;
1909 NDDataType_t dataType;
1911 int binX, binY, minX, minY, sizeX, sizeY, reverseX, reverseY;
1912 int xDim=0, yDim=1, colorDim=-1;
1913 int maxSizeX, maxSizeY;
1916 NDDimension_t dimsOut[3];
1917 size_t dims[3], dims2[2];
1918 NDArrayInfo_t arrayInfo;
1920 const char* functionName =
"computeImage";
1924 status |= getIntegerParam(ADBinX, &binX);
1925 status |= getIntegerParam(ADBinY, &binY);
1926 status |= getIntegerParam(ADMinX, &minX);
1927 status |= getIntegerParam(ADMinY, &minY);
1928 status |= getIntegerParam(ADSizeX, &sizeX);
1929 status |= getIntegerParam(ADSizeY, &sizeY);
1930 status |= getIntegerParam(ADReverseX, &reverseX);
1931 status |= getIntegerParam(ADReverseY, &reverseY);
1932 status |= getIntegerParam(ADMaxSizeX, &maxSizeX);
1933 status |= getIntegerParam(ADMaxSizeY, &maxSizeY);
1934 status |= getIntegerParam(NDColorMode, &colorMode);
1935 status |= getIntegerParam(NDDataType, &itemp);
1936 dataType = (NDDataType_t)itemp;
1937 if (status) asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR,
1938 "%s:%s: error getting parameters\n",
1939 driverName, functionName);
1944 status |= setIntegerParam(ADBinX, binX);
1948 status |= setIntegerParam(ADBinY, binY);
1952 status |= setIntegerParam(ADMinX, minX);
1956 status |= setIntegerParam(ADMinY, minY);
1958 if (minX > maxSizeX-1) {
1960 status |= setIntegerParam(ADMinX, minX);
1962 if (minY > maxSizeY-1) {
1964 status |= setIntegerParam(ADMinY, minY);
1966 if (minX+sizeX > maxSizeX) {
1967 sizeX = maxSizeX-minX;
1968 status |= setIntegerParam(ADSizeX, sizeX);
1970 if (minY+sizeY > maxSizeY) {
1971 sizeY = maxSizeY-minY;
1972 status |= setIntegerParam(ADSizeY, sizeY);
1975 switch (colorMode) {
1976 case NDColorModeMono:
1981 case NDColorModeRGB1:
1987 case NDColorModeRGB2:
1993 case NDColorModeRGB3:
2004 if (m_pRaw) m_pRaw->release();
2008 size_t nelements = sizeX * sizeY;
2009 if (ndims > 2) dims[colorDim] = 3;
2010 m_pRaw = this->pNDArrayPool->alloc(ndims, dims, dataType, 0, NULL);
2013 asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR,
2014 "%s:%s: error allocating raw buffer\n",
2015 driverName, functionName);
2022 status |= computeArray<epicsInt8>(value, nelements, sizeX, sizeY);
2025 status |= computeArray<epicsUInt8>(value, nelements, sizeX, sizeY);
2028 status |= computeArray<epicsInt16>(value, nelements, sizeX, sizeY);
2031 status |= computeArray<epicsUInt16>(value, nelements, sizeX, sizeY);
2034 status |= computeArray<epicsInt32>(value, nelements, sizeX, sizeY);
2037 status |= computeArray<epicsUInt32>(value, nelements, sizeX, sizeY);
2040 status |= computeArray<epicsFloat32>(value, nelements, sizeX, sizeY);
2043 status |= computeArray<epicsFloat64>(value, nelements, sizeX, sizeY);
2050 m_pRaw->initDimension(&dimsOut[xDim], sizeX);
2051 m_pRaw->initDimension(&dimsOut[yDim], sizeY);
2052 if (ndims > 2) m_pRaw->initDimension(&dimsOut[colorDim], 3);
2053 dimsOut[xDim].binning = binX;
2054 dimsOut[xDim].offset = minX;
2055 dimsOut[xDim].reverse = reverseX;
2056 dimsOut[yDim].binning = binY;
2057 dimsOut[yDim].offset = minY;
2058 dimsOut[yDim].reverse = reverseY;
2061 if (this->pArrays[0]) this->pArrays[0]->release();
2062 status = this->pNDArrayPool->convert(m_pRaw,
2067 asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR,
2068 "%s:%s: error allocating buffer in convert()\n",
2069 driverName, functionName);
2072 pImage = this->pArrays[0];
2073 pImage->getInfo(&arrayInfo);
2074 status = asynSuccess;
2075 status |= setIntegerParam(NDArraySize, (
int)arrayInfo.totalBytes);
2076 status |= setIntegerParam(NDArraySizeX, (
int)pImage->dims[xDim].size);
2077 status |= setIntegerParam(NDArraySizeY, (
int)pImage->dims[yDim].size);
2078 if (status) asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR,
2079 "%s:%s: error setting parameters\n",
2080 driverName, functionName);
2085 template <
typename epicsType>
2086 int pixelmanDriver::computeArray(epicsUInt32* value,
size_t nelements,
int sizeX,
int sizeY)
2088 epicsType *pMono=NULL, *pRed=NULL, *pGreen=NULL, *pBlue=NULL;
2089 int columnStep=0, rowStep=0, colorMode;
2090 int status = asynSuccess;
2091 double exposureTime;
2094 status = getIntegerParam(NDColorMode, &colorMode);
2095 status = getDoubleParam (ADAcquireTime, &exposureTime);
2097 switch (colorMode) {
2098 case NDColorModeMono:
2099 pMono = (epicsType *)m_pRaw->pData;
2101 case NDColorModeRGB1:
2104 pRed = (epicsType *)m_pRaw->pData;
2105 pGreen = (epicsType *)m_pRaw->pData+1;
2106 pBlue = (epicsType *)m_pRaw->pData+2;
2108 case NDColorModeRGB2:
2110 rowStep = 2 * sizeX;
2111 pRed = (epicsType *)m_pRaw->pData;
2112 pGreen = (epicsType *)m_pRaw->pData + sizeX;
2113 pBlue = (epicsType *)m_pRaw->pData + 2*sizeX;
2115 case NDColorModeRGB3:
2118 pRed = (epicsType *)m_pRaw->pData;
2119 pGreen = (epicsType *)m_pRaw->pData + sizeX*sizeY;
2120 pBlue = (epicsType *)m_pRaw->pData + 2*sizeX*sizeY;
2123 m_pRaw->pAttributeList->add(
"ColorMode",
"Color mode", NDAttrInt32, &colorMode);
2124 memset(m_pRaw->pData, 0, m_pRaw->dataSize);
2125 for (i = sizeY-1; i>= 0; --i) {
2126 switch (colorMode) {
2127 case NDColorModeMono:
2128 for (j = 0; j<sizeX; j++) {
2129 *pMono = value[i*sizeX+j];
2133 case NDColorModeRGB1:
2134 case NDColorModeRGB2:
2135 case NDColorModeRGB3:
2136 for (j = 0; j<sizeX; j++) {
2137 *pRed = value[i*sizeX + j];
2138 *pGreen = value[i*sizeX + j];
2139 *pBlue = value[i*sizeX + j];
2141 pGreen += columnStep;
2142 pBlue += columnStep;
2156 void pixelmanDriver::readFrame()
2158 u32 refCount, width, height, byteSize;
2163 Data_Types frame_type;
2164 buffer =
new u32[m_devInfo.numberOfChips * MATRIX_SIZE];
2165 stat = mgr->mpxCtrlGetFrame32(m_devId, buffer, m_devInfo.numberOfChips * MATRIX_SIZE, 0);
2167 for (
int i = 0; i < m_devInfo.numberOfChips * MATRIX_SIZE; ++i)
2169 max = (max > buffer[i] ? max : buffer[i]);
2174 stat = mgr->mpxCtrlGetFrameID(m_devId, 0, &FrameID);
2177 stat = mgr->openFrame(FrameID, &refCount);
2180 stat = mgr->getFrameType(FrameID, &frame_type);
2183 stat = mgr->getFrameSize(FrameID, &width, &height);
2186 buffer =
new u32[width * height];
2187 byteSize = width * height *
sizeof(u32) + 64;
2188 stat = mgr->getFrameData(FrameID, (byte*)buffer, &byteSize, TYPE_U32);
2189 if (byteSize != width * height *
sizeof(u32))
2194 for (
int i = 0; i < width * height; ++i)
2196 max = (max > buffer[i] ? max : buffer[i]);
2199 stat = mgr->closeFrame(FrameID, &refCount);
start integral acquisition
Header for pixelman EPICS plugin.
dbLoadDatabase(TOP)/dbd/pixelman.dbd"
Register all support components ;.
iocInit
ISIS common init ;.
virtual void setShutter(int open)
Controls the shutter.
pixelmanConfigure("MCP","$(PIXDET=dummy)")
"BeARQuT" is the real MCP detector, "dummy" is the simulation mode ; PIXDET variable normally set in ...
int computeImage(epicsUInt32 *value, u32 width, u32 height)
Computes the new image data.
dbLoadRecords("NDTransform.template","P=$(MYPVPREFIX),R=PIXELMAN:AD:rawimage1:,PORT=ADRawImage1,ADDR=0,TIMEOUT=1,NDARRAY_PORT=MCP,NDARRAY_ADDR=0,DATATYPE=4,ENABLED=1")
This waveform ; TYPE=Int8,FTVL=UCHAR for 8 bit integer ; TYPE=Int32,FTVL=LONG,DATATYPE=4 for 32 bit i...