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)
75 static void epicsHelloWorldMenuItemFunc(MENUFUNCPAR par)
80 static void epicsFunc(
void* in,
void* out)
82 struct InParamStucture
89 InParamStucture *par= (InParamStucture*)in;
91 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 extern const FuncTableType *mgr;
120 static void mpxmgrExitCB(CBPARAM par, INTPTR userData)
127 static void mpxmgrStartCB(CBPARAM par, INTPTR userData)
132 static void mpxmgrFrameNewCB(CBPARAM par, INTPTR userData)
134 FRAMEID frameID = par;
139 static void mpxctrlAcqStartCB(CBPARAM par, INTPTR userData)
143 g_epics->pixelmanEventCB(pixelmanDriver::MPX_ACQSTART, userData);
148 static void mpxctrlAcqPreStartCB(CBPARAM par, INTPTR userData)
152 g_epics->pixelmanEventCB(pixelmanDriver::MPX_ACQPRESTART, userData);
158 static void mpxctrlSingleAcqCompletedCB(CBPARAM par, INTPTR userData)
162 g_epics->pixelmanEventCB(pixelmanDriver::MPX_SINGLEACQCOMP, userData);
168 static void mpxctrlSeriesAcqCompletedCB(CBPARAM par, INTPTR userData)
172 g_epics->pixelmanEventCB(pixelmanDriver::MPX_SERIESACQCOMP, userData);
177 static int myLog(
const errlogSevEnum severity,
const char *pformat, ... )
181 va_start(pvar, pformat);
182 n = errlogSevVprintf(severity, pformat, pvar);
183 mgr->logMsgV(PLUGIN_NAME, pformat, 0, pvar);
189 static void mpxctrlMessageCB(CBPARAM par, INTPTR userData)
191 const char* msg = NULL;
193 if (mgr != NULL && g_epics != NULL)
195 status = mgr->mpxCtrlGetInfoMsg(g_epics->getDevId(), &msgType, &msg);
196 if (status == MPXERR_NOERROR && msg != NULL)
200 if (msgType != MPXERR_ACQABORTED)
204 errlogSevPrintf(errlogMajor,
"%s (%d)\n", msg, msgType);
208 errlogSevPrintf(errlogInfo,
"%s (%d)\n", msg, msgType);
222 registerStructuredExceptionHandler();
228 catch(
const std::exception& ex)
230 errlogSevPrintf(errlogMajor,
"pixelmanConfigure failed: %s", ex.what());
237 static const iocshArg initArg0 = {
"portName", iocshArgString};
238 static const iocshArg initArg1 = {
"devName", iocshArgString};
240 static const iocshArg *
const initArgs[] = { &initArg0, &initArg1 };
242 static const iocshFuncDef initFuncDef = {
"pixelmanConfigure",
sizeof(initArgs) /
sizeof(iocshArg*), initArgs};
244 static void initCallFunc(
const iocshArgBuf *args)
249 static void pixelmanRegister(
void)
251 iocshRegister(&initFuncDef, initCallFunc);
254 epicsExportRegistrar(pixelmanRegister);
258 extern "C" int pixelman_registerRecordDeviceDriver(
struct dbBase *pdbbase);
260 #define DBD_FILE "../dbd/pixelman.dbd"
261 #define DB_FILE "../db/pixelman.db"
274 mgr->logShowWindow(1);
284 if (freopen(
"pixelman_iocout.log",
"wt", stdout) == NULL)
286 mgr->logMsg(PLUGIN_NAME,
"Error redirecting stdout to pixelman_iocout.log", 0);
288 if (freopen(
"pixelman_iocerr.log",
"wt", stderr) == NULL)
290 mgr->logMsg(PLUGIN_NAME,
"Error redirecting stderr to pixelman_iocerr.log", 0);
292 if (setvbuf(stdout, NULL, _IONBF, 0) != 0)
294 mgr->logMsg(PLUGIN_NAME,
"Error making stdout unbuffered", 0);
296 if (setvbuf(stderr, NULL, _IONBF, 0) != 0)
298 mgr->logMsg(PLUGIN_NAME,
"Error making stderr unbuffered", 0);
301 if (mgr->registerCallback(MPXCTRL_NAME, MPXCTRL_CB_ACQPRESTART, mpxctrlAcqPreStartCB, NULL) != 0)
303 mgr->logMsg(PLUGIN_NAME,
"Error registering prestart callback", 0);
305 mgr->registerCallback(MPXCTRL_NAME, MPXCTRL_CB_ACQSERCOMPL, mpxctrlSeriesAcqCompletedCB, NULL);
306 mgr->registerCallback(MPXCTRL_NAME, MPXCTRL_CB_INFOMSG, mpxctrlMessageCB, NULL);
307 mgr->registerCallback(MPXCTRL_NAME, MPXCTRL_CB_ACQSTART, mpxctrlAcqStartCB, NULL);
315 const char* PIXELMANDIR = getenv(
"PIXELMANDIR");
316 if (PIXELMANDIR == NULL)
318 PIXELMANDIR =
"<UNKNOWN>";
320 mgr->logMsg(PLUGIN_NAME, (std::string(
"Camera directory: ") + PIXELMANDIR).c_str(), 0);
324 const char* PVPREFIX = getenv(
"MYPVPREFIX");
325 if (PVPREFIX == NULL)
329 epicsSnprintf(macros,
sizeof(macros),
"P=%s,Q=PIXELMAN:", PVPREFIX);
330 mgr->logMsg(PLUGIN_NAME,
"Starting EPICS IOC", 0);
333 mgr->logMsg(PLUGIN_NAME,
"Error in plugin function: cannot load DBD file", 0);
337 pixelman_registerRecordDeviceDriver(pdbbase);
344 mgr->logMsg(PLUGIN_NAME,
"Error in plugin function: cannot load DB file", 0);
351 mgr->logMsg(PLUGIN_NAME,
"Starting EPICS IOC - see pixelman_iocout.log and pixelman_iocerr.log", 0);
352 const char* PVPREFIX = getenv(
"MYPVPREFIX");
353 mgr->logMsg(PLUGIN_NAME,
"PV prefix P=%s", 0, (PVPREFIX != NULL ? PVPREFIX :
""));
354 const char* EPICSPIXELMAN = getenv(
"EPICSPIXELMAN");
355 if (EPICSPIXELMAN == NULL)
359 std::string pix_cmd = std::string(EPICSPIXELMAN) + std::string(
"/pixelman.cmd");
360 mgr->logMsg(PLUGIN_NAME, (std::string(
"Loading ") + pix_cmd).c_str(), 0);
361 if (iocsh(pix_cmd.c_str()))
363 mgr->logMsg(PLUGIN_NAME,
"Error in plugin function: cannot load pixelman.cmd", 0);
370 static const char *driverName =
"pixelmanDriver";
372 pixelmanDriver::pixelmanDriver(
const char *portName,
const char* devName)
373 : asynPortDriver(portName,
376 asynInt32Mask | asynFloat64Mask | asynOctetMask | asynDrvUserMask,
377 asynInt32Mask | asynFloat64Mask | asynOctetMask,
382 m_acqRunning(false), m_cmd_running(false), m_start_running(false),
383 m_abort_running(false), m_devId(INVALID_DEVID_VALUE), m_autoRestart(0),
384 m_autoRestartDelay(0.0), m_eventCBQueue(40, sizeof(eventCBInfo)), m_runEndQueue(40, sizeof(RunEndInfo))
387 const char *functionName =
"pixelmanDriver";
388 std::ostringstream pix_items;
390 createParam(P_acquireString, asynParamInt32, &P_acquire);
391 createParam(P_acqAbortString, asynParamInt32, &P_acqAbort);
392 createParam(P_acqStartString, asynParamInt32, &P_acqStart);
393 createParam(P_trigAcqStartString, asynParamInt32, &P_trigAcqStart);
394 createParam(P_trigAcqStopString, asynParamInt32, &P_trigAcqStop);
395 createParam(P_numberOfAcqString, asynParamInt32, &P_numberOfAcq);
396 createParam(P_timeOfEachAcqString, asynParamFloat64, &P_timeOfEachAcq);
397 createParam(P_fileFlagsString, asynParamInt32, &P_fileFlags);
399 createParam(P_devIdString, asynParamInt32, &P_devId);
400 createParam(P_acqSActiveString, asynParamInt32, &P_acqSActive);
401 createParam(P_acqActiveString, asynParamInt32, &P_acqActive);
402 createParam(P_acqTypeString, asynParamInt32, &P_acqType);
403 createParam(P_acqTypeReqString, asynParamInt32, &P_acqTypeReq);
404 createParam(P_frameFilledString, asynParamInt32, &P_frameFilled);
405 createParam(P_acqTotalCountString, asynParamInt32, &P_acqTotalCount);
406 createParam(P_acqNumberString, asynParamInt32, &P_acqNumber);
407 createParam(P_acqModeString, asynParamInt32, &P_acqMode);
408 createParam(P_burstModeString, asynParamInt32, &P_burstMode);
409 createParam(P_extShutModeString, asynParamInt32, &P_extShutMode);
410 createParam(P_hwTimerString, asynParamInt32, &P_hwTimer);
411 createParam(P_saveConfigString, asynParamOctet, &P_saveConfig);
412 createParam(P_loadConfigString, asynParamOctet, &P_loadConfig);
413 createParam(P_saveDefConfigString, asynParamInt32, &P_saveDefConfig);
414 createParam(P_loadDefConfigString, asynParamInt32, &P_loadDefConfig);
415 createParam(P_acqHangString, asynParamInt32, &P_acqHang);
416 createParam(P_hangTimeString, asynParamFloat64, &P_hangTime);
417 createParam(P_autoRestartString, asynParamInt32, &P_autoRestart);
418 createParam(P_autoRestartDelayString, asynParamFloat64, &P_autoRestartDelay);
419 createParam(P_setPixelModeString, asynParamInt32, &P_setPixelMode);
421 setIntegerParam(P_acquire, 0);
422 setIntegerParam(P_acqStart, 0);
423 setIntegerParam(P_acqAbort, 0);
424 setIntegerParam(P_acqSActive, 0);
425 setIntegerParam(P_acqActive, 0);
426 setIntegerParam(P_autoRestart, 0);
429 char name[NAME_LENGTH];
430 memset(name, 0, NAME_LENGTH);
432 DEVID devId = INVALID_DEVID_VALUE;
433 if ( mgr != NULL && mgr->mpxCtrlGetFirstMpx(&devId, &count) == 0 )
435 errlogSevPrintf(errlogInfo,
"There are %d devices available\n", count);
436 if (mgr->mpxCtrlGetCustomName(m_devId, name) == MPXERR_NOERROR)
438 name[NAME_LENGTH-1] =
'\0';
444 mgr->mpxCtrlGetDevInfo(devId, &devInfo);
445 errlogSevPrintf(errlogInfo,
"... devId %d name \"%s\" iface \"%s\" chipID \"%s\"\n", devId, name, devInfo.ifaceName, devInfo.chipboardID);
446 if (strcmp(devName, name) == 0 || strcmp(devName, devInfo.ifaceName) == 0)
448 errlogSevPrintf(errlogInfo,
"Found device \"%s\" (devId %d)\n", devName, devId);
450 memcpy(&m_devInfo, &devInfo,
sizeof(DevInfo));
451 printDevInfo(&m_devInfo, pix_items);
453 while(mgr->mpxCtrlGetNextMpx(&devId) == 0)
455 mgr->mpxCtrlGetCustomName(devId, name);
456 mgr->mpxCtrlGetDevInfo(devId, &devInfo);
457 errlogSevPrintf(errlogInfo,
"... devId %d name \"%s\" iface \"%s\" chipID \"%s\"\n", devId, name, devInfo.ifaceName, devInfo.chipboardID);
458 if (strcmp(devName, name) == 0 || strcmp(devName, devInfo.ifaceName) == 0)
460 errlogSevPrintf(errlogInfo,
"Found device \"%s\" (devId %d)\n", devName, devId);
462 memcpy(&m_devInfo, &devInfo,
sizeof(DevInfo));
463 printDevInfo(&m_devInfo, pix_items);
467 setIntegerParam(P_devId, m_devId);
468 if (getDevId() == INVALID_DEVID_VALUE)
470 errlogSevPrintf(errlogMajor,
"Device \"%s\" not found\n", devName);
475 getHwInfo(pix_items);
478 createParam(P_dataFileNameString, asynParamOctet, &P_dataFileName);
479 m_paramInfo[P_dataFileName] =
"DataFileName";
481 createParam(P_shutrCLKShiftString, asynParamInt32, &P_shutrCLKShift);
482 m_paramInfo[P_shutrCLKShift] =
"ShutrCLKShift";
483 createParam(P_tpxCubeBinString, asynParamFloat64, &P_tpxCubeBin);
484 m_paramInfo[P_tpxCubeBin] =
"TpxCubeBin";
485 createParam(P_dataAcqModeString, asynParamInt32, &P_dataAcqMode);
486 m_paramInfo[P_dataAcqMode] =
"AcqMode";
487 createParam(P_fileIndexString, asynParamInt32, &P_fileIndex);
488 m_paramInfo[P_fileIndex] =
"FileIndexToSaveDataInto";
490 createParam(P_saveRawDataString, asynParamInt32, &P_saveRawData);
491 m_paramInfo[P_saveRawData] =
"SaveRawData";
492 createParam(P_nShuttersPerBurstString, asynParamInt32, &P_nShuttersPerBurst);
493 m_paramInfo[P_nShuttersPerBurst] =
"TriggersPerBurst";
494 createParam(P_nTrigsBurstRefreshString, asynParamInt32, &P_nTrigsBurstRefresh);
495 m_paramInfo[P_nTrigsBurstRefresh] =
"BurstsToTake";
496 createParam(P_cameraStatusString, asynParamInt32, &P_cameraStatus);
497 m_paramInfo[P_cameraStatus] =
"CurrentStatus";
498 createParam(P_nTrigSavSubString, asynParamInt32, &P_nTrigSavSub);
499 m_paramInfo[P_nTrigSavSub] =
"NtrigBeforeSavingSubImgSpectra";
504 ExtCBEventInfo extCBEventInfo;
505 if (mgr->getRegFirstCBEvent(&cbEventID, &extCBEventInfo) == 0)
507 pix_items <<
"Plugin " << extCBEventInfo.pluginName <<
" offers event callback " << extCBEventInfo.cbEventName <<
" (" << extCBEventInfo.description <<
")" << std::endl;
508 while(mgr->getRegNextCBEvent(&cbEventID, &extCBEventInfo) == 0)
510 pix_items <<
"Plugin " << extCBEventInfo.pluginName <<
" offers event callback " << extCBEventInfo.cbEventName <<
" (" << extCBEventInfo.description <<
")" << std::endl;
513 char name[MENU_LENGTH];
515 if (mgr->getFirstMenuItem(&itemID, name) == 0)
517 pix_items <<
"Menu item " << name << std::endl;
518 while(mgr->getNextMenuItem(&itemID, name) == 0)
520 pix_items <<
"Menu item " << name << std::endl;
524 ExtFunctionInfo funcInfo;
525 if (mgr->getRegFirstFunc(&funcID, &funcInfo) == 0)
527 pix_items <<
"Plugin " << funcInfo.pluginName <<
" offers function " << funcInfo.functionName <<
" (" << funcInfo.description <<
")" << std::endl;
528 while(mgr->getRegNextFunc(&funcID, &funcInfo) == 0)
530 pix_items <<
"Plugin " << funcInfo.pluginName <<
" offers function " << funcInfo.functionName <<
" (" << funcInfo.description <<
")" << std::endl;
531 for(
int i=0; i<funcInfo.paramInCount; ++i)
533 pix_items <<
" arg_in[" << i <<
"] " << funcInfo.paramsInfoIn[i].description << std::endl;
535 for(
int i=0; i<funcInfo.paramOutCount; ++i)
537 pix_items <<
" arg_out[" << i <<
"] " << funcInfo.paramsInfoOut[i].description << std::endl;
545 std::fstream pfile(
"pixitems.txt", std::ios::out);
546 pfile << pix_items.str();
549 catch(
const std::exception& ex)
555 if (epicsThreadCreate(
"pixelmanDriverPoller",
556 epicsThreadPriorityMedium,
557 epicsThreadGetStackSize(epicsThreadStackMedium),
558 (EPICSTHREADFUNC)pollerThreadC,
this) == 0)
560 errlogSevPrintf(errlogMajor,
"%s:%s: epicsThreadCreate failure\n", driverName, functionName);
563 if (epicsThreadCreate(
"pixelmanDriverRestarter",
564 epicsThreadPriorityMedium,
565 epicsThreadGetStackSize(epicsThreadStackMedium),
566 (EPICSTHREADFUNC)pixelmanDriverRestarterC,
this) == 0)
568 errlogSevPrintf(errlogMajor,
"%s:%s: epicsThreadCreate failure\n", driverName, functionName);
571 if (epicsThreadCreate(
"pixelmanEventCBProcess",
572 epicsThreadPriorityMedium,
573 epicsThreadGetStackSize(epicsThreadStackMedium),
574 (EPICSTHREADFUNC)pixelmanEventCBProcessC,
this) == 0)
576 errlogSevPrintf(errlogMajor,
"%s:%s: epicsThreadCreate failure\n", driverName, functionName);
579 if (epicsThreadCreate(
"pixelmanDriverSaver",
580 epicsThreadPriorityMedium,
581 epicsThreadGetStackSize(epicsThreadStackMedium),
582 (EPICSTHREADFUNC)saverThreadC,
this) == 0)
584 errlogSevPrintf(errlogMajor,
"%s:%s: epicsThreadCreate failure\n", driverName, functionName);
589 int pixelmanDriver::getDevId()
const
594 void pixelmanDriver::pixelmanDriverRestarterC(
void* arg)
597 driver->pixelmanDriverRestarter();
600 static void myExitFunc(
const char* msg)
613 void pixelmanDriver::pixelmanDriverRestarter()
615 static const char* functionName =
"pixelmanDriverRestarter";
616 registerStructuredExceptionHandler();
622 epicsThreadSleep(delay);
623 if (m_autoRestart != 0)
625 epicsTimeGetCurrent(&now);
628 tdiff = epicsTimeDiffInSeconds(&now, &m_cmd_time);
629 if (tdiff > m_autoRestartDelay)
631 myExitFunc(
"pixelmanDriverRestarter: exiting (cmd)");
636 tdiff = epicsTimeDiffInSeconds(&now, &m_abort_time);
637 if (tdiff > m_autoRestartDelay)
639 myExitFunc(
"pixelmanDriverRestarter: exiting (abort)");
647 void pixelmanDriver::pollerThreadC(
void* arg)
650 driver->pollerThread();
653 void pixelmanDriver::saverThreadC(
void* arg)
656 driver->saverThread();
659 void pixelmanDriver::pollerThread()
661 static const char* functionName =
"pollerThread";
663 int acqNumber = 0, acqTotalCount = 0, acqType = 0, acqMode = 0, hwTimer = 0;
664 static u32 lastFrameFilled = 0;
667 epicsTimeStamp stop_begin, now;
669 int fileIndex, lastFileIndex = -1;
670 bool file_to_save =
false;
672 registerStructuredExceptionHandler();
673 epicsTimeGetCurrent(&stop_begin);
676 epicsThreadSleep(delay);
679 mgr->mpxCtrlGetAcqInfo(devId, &acqNumber, &acqTotalCount, &acqType, &frameFilled);
680 mgr->mpxCtrlGetAcqMode(devId, &acqMode);
681 mgr->mpxCtrlGetHwTimer(devId, &hwTimer);
683 getIntegerParam(P_autoRestart, &m_autoRestart);
684 getDoubleParam(P_autoRestartDelay, &m_autoRestartDelay);
685 getIntegerParam(P_cameraStatus, &cameraStatus);
686 getIntegerParam(P_fileIndex, &fileIndex);
687 if (lastFileIndex == -1)
689 lastFileIndex = fileIndex;
691 setIntegerParam(P_acqType, acqType);
692 setIntegerParam(P_frameFilled, frameFilled);
693 setIntegerParam(P_acqTotalCount, acqTotalCount);
694 setIntegerParam(P_acqNumber, acqNumber);
695 setIntegerParam(P_acqMode, (acqMode & 0xff) );
696 setIntegerParam(P_burstMode, ((acqMode & ACQMODE_BURST) != 0) );
697 setIntegerParam(P_extShutMode, ((acqMode & ACQMODE_EXTSHUTTER) != 0) );
698 setIntegerParam(P_hwTimer, hwTimer);
700 epicsTimeGetCurrent(&now);
701 double tdiff = epicsTimeDiffInSeconds(&now, &stop_begin);
702 bool acqHang =
false;
710 setIntegerParam(P_acquire, 1);
711 setIntegerParam(P_acqActive, 1);
712 if (frameFilled == lastFrameFilled)
714 if (tdiff > m_autoRestartDelay)
717 if (m_autoRestart != 0)
719 myExitFunc(
"pollerThread: exiting");
725 lastFrameFilled = frameFilled;
726 epicsTimeGetCurrent(&stop_begin);
732 setIntegerParam(P_acquire, 0);
733 setIntegerParam(P_acqActive, 0);
734 epicsTimeGetCurrent(&stop_begin);
737 setDoubleParam(P_hangTime, tdiff);
740 setIntegerParam(P_acqHang, 1);
744 setIntegerParam(P_acqHang, 0);
746 if (file_to_save && fileIndex > lastFileIndex)
748 saveFinished(lastFileIndex);
749 file_to_save =
false;
751 lastCameraStatus = cameraStatus;
752 lastFileIndex = fileIndex;
753 callParamCallbacks();
758 void pixelmanDriver::saveFinished(
int fileIndex)
761 getStringParam(P_dataFileName,
sizeof(info.fileName), info.fileName);
762 info.fileIndex = fileIndex;
763 m_runEndQueue.send(&info,
sizeof(RunEndInfo), 1.0);
766 static std::string quote(
const std::string& str)
772 void pixelmanDriver::saverThread()
775 const char* end_of_run = getenv(
"PIXELMANENDCMD");
776 const char* comspec = getenv(
"COMSPEC");
777 const char* pixelmandir = getenv(
"PIXELMANDIR");
778 epicsThreadSleep(1.0);
779 while( m_runEndQueue.receive(&info,
sizeof(RunEndInfo)) > 0 )
781 errlogSevPrintf(errlogInfo,
"Saved \"%s\" index %d\n", info.fileName, info.fileIndex);
782 mgr->logMsg(PLUGIN_NAME,
"Saved \"%s\" index %d", 0, info.fileName, info.fileIndex);
783 if (end_of_run != NULL)
785 errlogSevPrintf(errlogInfo,
"Executing \"%s\"\n", end_of_run);
786 mgr->logMsg(PLUGIN_NAME,
"Executing \"%s\"", 0, end_of_run);
788 sprintf(cFileIndex,
"%d", info.fileIndex);
790 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)
795 mgr->logMsg(PLUGIN_NAME,
"ERROR executing \"%s\"", 0, end_of_run);
801 #define THROW_IF_ACQ_ACTIVE \
804 std::ostringstream acq_active_mess; \
805 acq_active_mess << functionName << ": cannot set " << paramName << " when acq active"; \
806 throw std::runtime_error(acq_active_mess.str().c_str()); \
809 #define THROW_IF_ACQ_NOT_ACTIVE \
812 std::ostringstream acq_not_active_mess; \
813 acq_not_active_mess << functionName << ": cannot set " << paramName << " when acq is not active"; \
814 throw std::runtime_error(acq_not_active_mess.str().c_str()); \
817 asynStatus pixelmanDriver::writeFloat64(asynUser *pasynUser, epicsFloat64 value)
819 int function = pasynUser->reason;
820 const char* functionName =
"writeFloat64";
821 asynStatus status = asynSuccess;
822 const char *paramName = NULL;
823 getParamName(
function, ¶mName);
824 DEVID devId = getDevId();
825 registerStructuredExceptionHandler();
826 debugOutput(paramName);
833 throw std::runtime_error(
"pixelman not initialised");
835 else if (
function == P_tpxCubeBin)
838 setDoubleParam(
function, value);
839 setHwItem(m_paramInfo[
function],
function);
841 asynPrint(pasynUser, ASYN_TRACEIO_DRIVER,
842 "%s:%s: function=%d, name=%s, value=%f\n",
843 driverName, functionName,
function, paramName, value);
844 status = asynSuccess;
846 catch(
const std::exception& ex)
848 epicsSnprintf(pasynUser->errorMessage, pasynUser->errorMessageSize,
849 "%s:%s: status=%d, function=%d, name=%s, value=%f, error=%s",
850 driverName, functionName, status,
function, paramName, value, ex.what());
853 if (status == asynSuccess)
855 status = asynPortDriver::writeFloat64(pasynUser, value);
861 asynStatus pixelmanDriver::writeInt32(asynUser *pasynUser, epicsInt32 value)
863 int function = pasynUser->reason;
865 const char* functionName =
"writeInt32";
866 asynStatus status = asynSuccess;
867 const char *paramName = NULL;
868 getParamName(
function, ¶mName);
869 DEVID devId = getDevId();
870 registerStructuredExceptionHandler();
871 debugOutput(paramName);
878 throw std::runtime_error(
"pixelman not initialised");
880 else if (
function == P_acqStart || (
function == P_acquire && value == 1) )
883 setIntegerParam(P_acquire, 1);
885 getIntegerParam(P_acqTypeReq, &acqTypeReq);
886 AcquisitionThreadArgs* args = createAcquisitionThreadArgs(acqTypeReq);
887 if (epicsThreadCreate(
"pixelmanAcquisitionStart",
888 epicsThreadPriorityMedium,
889 epicsThreadGetStackSize(epicsThreadStackMedium),
890 (EPICSTHREADFUNC)acquisitionThreadC, args) == 0)
892 errlogSevPrintf(errlogMajor,
"%s:%s: epicsThreadCreate failure\n", driverName, functionName);
894 epicsThreadSleep(0.1);
896 else if (
function == P_acqAbort || (
function == P_acquire && value == 0) )
898 THROW_IF_ACQ_NOT_ACTIVE;
899 AcquisitionThreadArgs* args = createAcquisitionThreadArgs(
ACQ_ABORT);
908 acquisitionThreadC(args);
909 setIntegerParam(P_acquire, 0);
911 else if (
function == P_trigAcqStart)
913 THROW_IF_ACQ_NOT_ACTIVE;
914 mgr->mpxCtrlTrigger(devId, TRIGGER_ACQSTART);
915 mgr->logMsg(PLUGIN_NAME,
"Acquisition Start triggered", 0);
917 else if (
function == P_trigAcqStop)
919 THROW_IF_ACQ_NOT_ACTIVE;
920 mgr->mpxCtrlTrigger(devId, TRIGGER_ACQSTOP);
921 mgr->logMsg(PLUGIN_NAME,
"Acquisition Stop triggered", 0);
923 else if (
function == P_acqMode)
926 mgr->mpxCtrlGetAcqMode(devId, &acqMode);
929 mgr->mpxCtrlSetAcqMode(devId, acqMode);
931 else if (
function == P_burstMode)
934 mgr->mpxCtrlGetAcqMode(devId, &acqMode);
937 acqMode |= ACQMODE_BURST;
941 acqMode &= ~ACQMODE_BURST;
943 mgr->mpxCtrlSetAcqMode(devId, acqMode);
945 else if (
function == P_extShutMode)
948 mgr->mpxCtrlGetAcqMode(devId, &acqMode);
951 acqMode |= ACQMODE_EXTSHUTTER;
955 acqMode &= ~ACQMODE_EXTSHUTTER;
957 mgr->mpxCtrlSetAcqMode(devId, acqMode);
959 else if (
function == P_hwTimer)
962 mgr->mpxCtrlSetHwTimer(devId, value);
964 else if (
function == P_saveDefConfig)
967 mgr->mpxCtrlSaveMpxCfgAsDefault(devId);
969 else if (
function == P_loadDefConfig)
972 mgr->mpxCtrlLoadMpxCfg(devId, NULL);
974 else if (
function == P_setPixelMode)
979 else if (
function == P_shutrCLKShift ||
function == P_dataAcqMode ||
function == P_fileIndex ||
function == P_saveRawData ||
980 function == P_nShuttersPerBurst ||
function == P_nTrigsBurstRefresh ||
function == P_nTrigSavSub)
983 setIntegerParam(
function, value);
984 setHwItem(m_paramInfo[
function],
function);
986 asynPrint(pasynUser, ASYN_TRACEIO_DRIVER,
987 "%s:%s: function=%d, name=%s, value=%d\n",
988 driverName, functionName,
function, paramName, value);
989 status = asynSuccess;
991 catch(
const std::exception& ex)
993 epicsSnprintf(pasynUser->errorMessage, pasynUser->errorMessageSize,
994 "%s:%s: status=%d, function=%d, name=%s, value=%d, error=%s",
995 driverName, functionName, status,
function, paramName, value, ex.what());
998 if (status == asynSuccess)
1000 status = asynPortDriver::writeInt32(pasynUser, value);
1006 asynStatus pixelmanDriver::writeOctet(asynUser *pasynUser,
const char *value,
size_t maxChars,
size_t *nActual)
1008 int function = pasynUser->reason;
1009 const char* functionName =
"writeOctet";
1010 asynStatus status = asynSuccess;
1011 const char *paramName = NULL;
1012 getParamName(
function, ¶mName);
1013 DEVID devId = getDevId();
1014 registerStructuredExceptionHandler();
1015 debugOutput(paramName);
1018 std::string value_s;
1020 if ( (maxChars > 0) && (value[maxChars-1] ==
'\0') )
1022 value_s.assign(value, maxChars-1);
1026 value_s.assign(value, maxChars);
1033 throw std::runtime_error(
"pixelman not initialised");
1035 else if (
function == P_dataFileName)
1037 THROW_IF_ACQ_ACTIVE;
1038 std::string fname(value_s);
1039 const char* invalid_chars =
"<>:\"|?*";
1040 for(
int i=0; i<strlen(invalid_chars); ++i)
1042 std::replace(fname.begin(), fname.end(), invalid_chars[i],
'_');
1045 size_t pos = fname.find_last_of(
"/\\");
1047 if (pos != std::string::npos && pos > 0)
1049 char absPath[MAX_PATH];
1050 std::replace(fname.begin(), fname.end(),
'/',
'\\');
1051 if ( _fullpath(absPath, fname.substr(0,pos).c_str(),
sizeof(absPath)) == NULL )
1053 strncpy(absPath, fname.substr(0,pos).c_str(),
sizeof(absPath));
1055 if ( (_access(absPath, 0) != 0) && (SHCreateDirectoryEx(NULL, absPath, NULL) != ERROR_SUCCESS) )
1057 throw std::runtime_error( (std::string(
"Cannot create directory ") + absPath).c_str() );
1061 setStringParam(
function, value_s.c_str());
1062 setHwItem(m_paramInfo[
function],
function);
1064 else if (
function == P_saveConfig)
1066 THROW_IF_ACQ_ACTIVE;
1067 mgr->mpxCtrlSaveMpxCfg(devId, (value_s.size() > 0 ? value_s.c_str() : NULL) );
1069 else if (
function == P_loadConfig)
1071 THROW_IF_ACQ_ACTIVE;
1072 mgr->mpxCtrlLoadMpxCfg(devId, (value_s.size() > 0 ? value_s.c_str() : NULL) );
1074 asynPrint(pasynUser, ASYN_TRACEIO_DRIVER,
1075 "%s:%s: function=%d, name=%s, value=%s\n",
1076 driverName, functionName,
function, paramName, value_s.c_str());
1077 status = asynSuccess;
1079 catch(
const std::exception& ex)
1082 epicsSnprintf(pasynUser->errorMessage, pasynUser->errorMessageSize,
1083 "%s:%s: status=%d, function=%d, name=%s, value=%s, error=%s",
1084 driverName, functionName, status,
function, paramName, value_s.c_str(), ex.what());
1087 if (status == asynSuccess)
1089 *nActual = value_s.size();
1090 status = asynPortDriver::writeOctet(pasynUser, value, maxChars, nActual);
1100 void pixelmanDriver::pixelmanEventCB(PixelmanCBEvent e, intptr_t userData)
1102 eventCBInfo info(e);
1103 m_eventCBQueue.send(&info,
sizeof(eventCBInfo), 1.0);
1107 void pixelmanDriver::pixelmanEventCBProcessC(
void* arg)
1110 driver->pixelmanEventCBProcess();
1113 void pixelmanDriver::pixelmanEventCBProcess()
1116 epicsThreadSleep(1.0);
1117 while(m_eventCBQueue.receive(&info,
sizeof(eventCBInfo)) > 0)
1122 case MPX_ACQPRESTART:
1124 setIntegerParam(P_acquire, 1);
1125 setIntegerParam(P_acqActive, 1);
1126 setIntegerParam(P_acqSActive, 1);
1131 setIntegerParam(P_acquire, 1);
1132 setIntegerParam(P_acqActive, 1);
1133 setIntegerParam(P_acqSActive, 1);
1136 case MPX_SINGLEACQCOMP:
1137 setIntegerParam(P_acqSActive, 0);
1140 case MPX_SERIESACQCOMP:
1142 setIntegerParam(P_acquire, 0);
1143 setIntegerParam(P_acqActive, 0);
1149 callParamCallbacks();
1154 void pixelmanDriver::acquisitionThreadC(
void* arg)
1156 AcquisitionThreadArgs* args = (AcquisitionThreadArgs*)arg;
1157 args->driver->acquisitionThread(args);
1161 void pixelmanDriver::acquisitionThread(AcquisitionThreadArgs* args)
1163 registerStructuredExceptionHandler();
1166 errlogSevPrintf(errlogMajor,
"acquisitionThread: pixelman not initialised\n");
1172 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));
1173 debugOutput(buffer);
1176 switch(args->acq_type)
1179 if (m_acq_start_mutex.tryLock())
1182 epicsTimeGetCurrent(&m_start_time);
1183 m_start_running =
true;
1184 m_acqRunning =
true;
1185 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);
1186 if ( (status = mgr->mpxCtrlPerformFrameAcq(getDevId(), args->numberOfAcq, args->timeOfEachAcq, args->fileFlags, args->fileName)) != MPXERR_NOERROR )
1188 if (status != MPXERR_ACQABORTED)
1190 errlogSevPrintf(errlogMajor,
"Error from mpxCtrlPerformFrameAcq %d", status);
1195 mgr->logMsg(PLUGIN_NAME,
"Frame acqusition complete", 0);
1197 m_acqRunning =
false;
1198 m_start_running =
false;
1199 m_acq_start_mutex.unlock();
1203 mgr->logMsg(PLUGIN_NAME,
"Cannot start frame acqusition - already in progress", 0);
1204 debugOutput(
"Cannot start frame acqusition - already in progress\n");
1209 if (m_acq_start_mutex.tryLock())
1212 epicsTimeGetCurrent(&m_start_time);
1213 m_start_running =
true;
1214 m_acqRunning =
true;
1215 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);
1216 if ( (status = mgr->mpxCtrlPerformIntegralAcq(getDevId(), args->numberOfAcq, args->timeOfEachAcq, args->fileFlags, args->fileName)) != MPXERR_NOERROR)
1218 if (status != MPXERR_ACQABORTED)
1220 errlogSevPrintf(errlogInfo,
"Error from mpxCtrlPerformIntegralAcq %d", status);
1225 mgr->logMsg(PLUGIN_NAME,
"Integral acqusition complete", 0);
1227 m_acqRunning =
false;
1228 m_start_running =
false;
1229 m_acq_start_mutex.unlock();
1233 mgr->logMsg(PLUGIN_NAME,
"Cannot start integral acqusition - already in progress", 0);
1234 debugOutput(
"Cannot start integral acqusition - already in progress\n");
1239 if (m_acq_abort_mutex.tryLock())
1242 epicsTimeGetCurrent(&m_abort_time);
1243 m_abort_running =
true;
1244 if ( (status = mgr->mpxCtrlAbortOperation(getDevId())) == MPXERR_NOERROR )
1246 m_acqRunning =
false;
1247 mgr->logMsg(PLUGIN_NAME,
"Acquisition Aborted", 0);
1251 errlogSevPrintf(errlogMajor,
"Error from mpxCtrlAbortOperation %d", status);
1252 mgr->logMsg(PLUGIN_NAME,
"Error Aborting Acquisition", 0);
1254 m_abort_running =
false;
1255 m_acq_abort_mutex.unlock();
1259 mgr->logMsg(PLUGIN_NAME,
"Cannot abort acqusition - already in progress", 0);
1260 debugOutput(
"Cannot abort acqusition - already in progress\n");
1265 mgr->logMsg(PLUGIN_NAME,
"Unknown acqusition mode requested", 0);
1270 catch(
const std::exception& ex)
1272 errlogSevPrintf(errlogMajor,
"Error from acquisitionThread %s", ex.what());
1276 errlogSevPrintf(errlogMajor,
"Error from acquisitionThread");
1278 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));
1279 debugOutput(buffer);
1283 void pixelmanDriver::getHwInfo(std::ostream& os)
1287 DEVID devId = getDevId();
1288 mgr->mpxCtrlGetHwInfoCount(devId, &hwcount);
1290 HwInfoItem* infoItem;
1291 int allocDataSize = 1024;
1293 for(
int i=0; i<hwcount; ++i)
1295 infoItem =
new HwInfoItem;
1296 infoItem->data =
new char[allocDataSize];
1297 dataSize = allocDataSize;
1298 if ( (status = mgr->mpxCtrlGetHwInfoItem(devId, i, infoItem, &dataSize)) != MPXERR_NOERROR )
1301 delete []((
char*)infoItem->data);
1302 infoItem->data =
new char[dataSize];
1303 status = mgr->mpxCtrlGetHwInfoItem(devId, i, infoItem, &dataSize);
1305 if (status != MPXERR_NOERROR)
1307 errlogSevPrintf(errlogMajor,
"getHwInfo: error from mpxCtrlGetHwInfoItem %d", status);
1310 m_hwInfo[infoItem->name] = HwInfo(infoItem, i, dataSize);
1311 os <<
"HWINFO: Found " << nameofType[infoItem->type] <<
"[" << infoItem->count <<
"] \"" << infoItem->name <<
"\" (" << infoItem->descr <<
")\n";
1315 void pixelmanDriver::getAllHwItems()
1317 for(std::map<int,std::string>::const_iterator it = m_paramInfo.begin(); it != m_paramInfo.end(); ++it)
1319 getHwItem(it->second, it->first);
1323 void pixelmanDriver::getHwItem(
const std::string& name,
int param)
1325 if ( m_hwInfo.find(name) == m_hwInfo.end() )
1329 DEVID devId = getDevId();
1330 HwInfo& info = m_hwInfo[name];
1331 int dataSize = info.dataSize;
1332 asynStatus astatus = asynSuccess;
1333 int status = mgr->mpxCtrlGetHwInfoItem(devId, info.index, info.item, &dataSize);
1334 if (status != MPXERR_NOERROR)
1336 delete []((
char*)info.item->data);
1337 info.item->data =
new char[dataSize];
1338 info.dataSize = dataSize;
1339 status = mgr->mpxCtrlGetHwInfoItem(devId, info.index, info.item, &dataSize);
1341 if (status != MPXERR_NOERROR)
1343 errlogSevPrintf(errlogMajor,
"getHwItem: error %d for %s", status, name.c_str());
1346 switch(info.item->type)
1350 astatus = setIntegerParam(param, *(
int*)info.item->data);
1354 astatus = setIntegerParam(param, *(
unsigned*)info.item->data);
1358 astatus = setDoubleParam(param, *(
float*)info.item->data);
1362 astatus = setDoubleParam(param, *(
double*)info.item->data);
1366 astatus = setIntegerParam(param, *(
short*)info.item->data);
1370 astatus = setIntegerParam(param, *(
unsigned short*)info.item->data);
1374 astatus = setIntegerParam(param, *(
unsigned char*)info.item->data);
1380 std::string s((
char*)info.item->data, info.item->count);
1381 astatus = setStringParam(param, s.c_str());
1386 astatus = setStringParam(param, (
char*)info.item->data);
1390 errlogSevPrintf(errlogMajor,
"getHwItem: unknown item type %d for %s", info.item->type, name.c_str());
1393 if (astatus != asynSuccess)
1395 errlogSevPrintf(errlogMajor,
"getHwItem: error setting asyn parameter for %s", name.c_str());
1400 void pixelmanDriver::setHwItem(
const std::string& name,
int param)
1402 if ( m_hwInfo.find(name) == m_hwInfo.end() )
1404 errlogSevPrintf(errlogMajor,
"setHwItem: unknown item \"%s\"", name.c_str());
1407 DEVID devId = getDevId();
1408 HwInfo& info = m_hwInfo[name];
1410 asynStatus astatus = asynSuccess;
1415 unsigned short usval;
1417 switch(info.item->type)
1422 if ( (astatus = getIntegerParam(param, &ival)) == asynSuccess )
1424 status = mgr->mpxCtrlSetHwInfoItem(devId, info.index, (byte*)&ival,
sizeof(ival));
1429 if ( (astatus = getDoubleParam(param, &dval)) == asynSuccess )
1432 status = mgr->mpxCtrlSetHwInfoItem(devId, info.index, (byte*)&fval,
sizeof(fval));
1437 if ( (astatus = getDoubleParam(param, &dval)) == asynSuccess )
1439 status = mgr->mpxCtrlSetHwInfoItem(devId, info.index, (byte*)&dval,
sizeof(dval));
1444 if ( (astatus = getIntegerParam(param, &ival)) == asynSuccess )
1447 status = mgr->mpxCtrlSetHwInfoItem(devId, info.index, (byte*)&sval,
sizeof(sval));
1452 if ( (astatus = getIntegerParam(param, &ival)) == asynSuccess )
1455 status = mgr->mpxCtrlSetHwInfoItem(devId, info.index, (byte*)&usval,
sizeof(usval));
1460 if ( (astatus = getIntegerParam(param, &ival)) == asynSuccess )
1463 status = mgr->mpxCtrlSetHwInfoItem(devId, info.index, &bval,
sizeof(bval));
1470 int n = info.item->count;
1471 char* buffer =
new char[n];
1472 memset(buffer, 0, n);
1473 if ( (astatus = getStringParam(param, n, buffer)) == asynSuccess )
1475 status = mgr->mpxCtrlSetHwInfoItem(devId, info.index, (byte*)buffer, n);
1483 char* buffer =
new char[info.dataSize];
1484 memset(buffer, 0, info.dataSize);
1485 if ( (astatus = getStringParam(param, info.dataSize, buffer)) == asynSuccess )
1487 status = mgr->mpxCtrlSetHwInfoItem(devId, info.index, (byte*)buffer, info.dataSize);
1494 errlogSevPrintf(errlogMajor,
"setHwItem: unknown item type %d for %s", info.item->type, name.c_str());
1497 if (astatus != asynSuccess)
1499 errlogSevPrintf(errlogMajor,
"setHwItem: error reading asyn parameter for %s", name.c_str());
1501 if (status != MPXERR_NOERROR)
1503 errlogSevPrintf(errlogMajor,
"setHwItem: error %d for %s", status, name.c_str());
1509 AcquisitionThreadArgs* args =
new AcquisitionThreadArgs(
this, at);
1510 memset(args->fileName, 0,
sizeof(args->fileName));
1511 getIntegerParam(P_numberOfAcq, &(args->numberOfAcq));
1512 getIntegerParam(P_fileFlags, reinterpret_cast<int*>(&(args->fileFlags)));
1513 getDoubleParam(P_timeOfEachAcq, &(args->timeOfEachAcq));
1514 getStringParam(P_dataFileName,
sizeof(args->fileName), args->fileName);
1519 void pixelmanDriver::setPixelMode(
unsigned mode)
1521 DEVID devId = getDevId();
1524 errlogSevPrintf(errlogMajor,
"setPixelMode: invalid mode");
1527 if (m_devInfo.numberOfChips * MATRIX_SIZE != m_devInfo.pixCount)
1529 errlogSevPrintf(errlogMajor,
"setPixelMode: invalid number of pixels");
1532 if (m_devInfo.mpxType != MPX_TPX)
1534 errlogSevPrintf(errlogMajor,
"setPixelMode: not timepix");
1537 int npixels = m_devInfo.pixCount;
1538 TpxPixCfg* pixels(
new TpxPixCfg[npixels]);
1539 if (mgr->mpxCtrlGetPixelsCfg(devId, reinterpret_cast<byte*>(pixels), npixels *
sizeof(TpxPixCfg), ALLCHIPS) != MPXERR_NOERROR)
1541 errlogSevPrintf(errlogMajor,
"setPixelMode: mpxCtrlGetPixelsCfg failed");
1545 for(
int i=0; i<npixels; ++i)
1547 pixels[i].mode = mode;
1549 if (mgr->mpxCtrlSetPixelsCfg(devId, reinterpret_cast<byte*>(pixels), npixels *
sizeof(TpxPixCfg), ALLCHIPS) != MPXERR_NOERROR)
1551 errlogSevPrintf(errlogMajor,
"setPixelMode: mpxCtrlSetPixelsCfg failed");
1559 void pixelmanDriver::printDevInfo(DevInfo* devInfo, std::ostream& os)
1561 os <<
"Number of pixels: " << devInfo->pixCount << std::endl;
1562 os <<
"Row length: " << devInfo->rowLen << std::endl;
1563 os <<
"Number of chips: " << devInfo->numberOfChips << std::endl;
1564 os <<
"Number rows: " << devInfo->numberOfRows << std::endl;
1565 os <<
"Medipix type: " << devInfo->mpxType << std::endl;
1566 os <<
"Supported acq modes: " << devInfo->suppAcqModes << std::endl;
1567 os <<
"Support callbacks: " << devInfo->suppCallback << std::endl;
dbLoadDatabase(TOP)/dbd/pixelman.dbd"
Register all support components ;.
iocInit
ISIS common init ;.
start integral acquisition
Header for pixelman EPICS plugin.
pixelmanConfigure("MCP","$(PIXDET=dummy)")
ISIS common init ;.
dbLoadRecords("$(TOP)/db/pixelman.db","P=$(MYPVPREFIX=),Q=PIXELMAN:")
ISIS common init ;.