API
pvcamCtrl.hpp
Go to the documentation of this file.
1 /** \file pvcamCtrl.hpp
2  * \brief The MagAO-X pvcam controller header file
3  *
4  * \ingroup pvcamCtrl_files
5  */
6 
7 #ifndef pvcamCtrl_hpp
8 #define pvcamCtrl_hpp
9 
10 #include <string.h>
11 
12 // PVCAM
13 #include <master.h>
14 #include <pvcam.h>
15 
16 #include "../../libMagAOX/libMagAOX.hpp" //Note this is included on command line to trigger pch
17 #include "../../magaox_git_version.h"
18 
19 /** \defgroup pvcamCtrl
20  * \brief The pvcam controller application for teledyne cameras
21  *
22  * <a href="../handbook/operating/software/apps/pvcamCtrl.html">Application Documentation</a>
23  *
24  * \ingroup apps
25  *
26  */
27 
28 #ifndef PL_ERR_LIBRARY_NOT_INITIALIZED
29 #define PL_ERR_LIBRARY_NOT_INITIALIZED (157)
30 #endif
31 
32 /// Format an error message using pvcam facilities
33 /**
34  * \returns a string of format "<func> failed: <pl_error_message>. <more>"
35  */
36 std::string pvcamErrMessage( const std::string & func, ///< [in] the pvcam function which failed
37  int pec, ///< [in] the code from pl_error_code
38  const std::string & more ///< [in] extra information to include
39  )
40 {
41  char pvmsg[ERROR_MSG_LEN];
42  pl_error_message(pec, pvmsg);
43 
44  std::string msg = func + " failed: " + pvmsg;
45  if(more != "") msg += " " + more;
46 
47  return msg;
48 }
49 
50 /// Helper for logging an error from pvcam
51 #define log_pvcam_software_error( func, /**< [in] the pvcam function which failed*/ \
52  more /**< [in] extra information to include*/ \
53  ) \
54 { \
55  int pec = pl_error_code(); \
56  log<software_error>({__FILE__, __LINE__, 0, pec , pvcamErrMessage(func, pec, more)}); \
57 }
58 
59 
60 /** \defgroup pvcamCtrl_files
61  * \ingroup pvcamCtrl
62  */
63 
64 namespace MagAOX
65 {
66 namespace app
67 {
68 
69 /// The MagAO-X pvcam controller
70 /**
71  * \ingroup pvcamCtrl
72  */
73 class pvcamCtrl : public MagAOXApp<true>, public dev::stdCamera<pvcamCtrl>, public dev::frameGrabber<pvcamCtrl>,
74  public dev::dssShutter<pvcamCtrl>,
75  public dev::telemeter<pvcamCtrl>
76 {
77 
82 
83  //Give the test harness access.
84  friend class pvcamCtrl_test;
85 
86  friend class dev::stdCamera<pvcamCtrl>;
87  friend class dev::frameGrabber<pvcamCtrl>;
88  friend class dev::dssShutter<pvcamCtrl>;
89  friend class dev::telemeter<pvcamCtrl>;
90 
92 
93 public:
94  /** \name app::dev Configurations
95  *@{
96  */
97  static constexpr bool c_stdCamera_tempControl = false; ///< app::dev config to tell stdCamera to expose temperature controls
98 
99  static constexpr bool c_stdCamera_temp = false; ///< app::dev config to tell stdCamera to expose temperature
100 
101  static constexpr bool c_stdCamera_readoutSpeed = true; ///< app::dev config to tell stdCamera to expose readout speed controls
102 
103  static constexpr bool c_stdCamera_vShiftSpeed = false; ///< app:dev config to tell stdCamera to expose vertical shift speed control
104 
105  static constexpr bool c_stdCamera_emGain = false; ///< app::dev config to tell stdCamera to expose EM gain controls
106 
107  static constexpr bool c_stdCamera_exptimeCtrl = true; ///< app::dev config to tell stdCamera to expose exposure time controls
108 
109  static constexpr bool c_stdCamera_fpsCtrl = true; ///< app::dev config to tell stdCamera not to expose FPS controls
110 
111  static constexpr bool c_stdCamera_fps = true; ///< app::dev config to tell stdCamera not to expose FPS status
112 
113  static constexpr bool c_stdCamera_synchro = false; ///< app::dev config to tell stdCamera to not expose synchro mode controls
114 
115  static constexpr bool c_stdCamera_usesModes = false; ///< app:dev config to tell stdCamera not to expose mode controls
116 
117  static constexpr bool c_stdCamera_usesROI = true; ///< app:dev config to tell stdCamera to expose ROI controls
118 
119  static constexpr bool c_stdCamera_cropMode = false; ///< app:dev config to tell stdCamera to expose Crop Mode controls
120 
121  static constexpr bool c_stdCamera_hasShutter = true; ///< app:dev config to tell stdCamera to expose shutter controls
122 
123  static constexpr bool c_stdCamera_usesStateString = false; ///< app::dev confg to tell stdCamera to expose the state string property
124 
125  static constexpr bool c_frameGrabber_flippable = false; ///< app:dev config to tell framegrabber this camera can be flipped
126 
127  ///@}
128 
129 
130 protected:
131 
132  /** \name Configurable Parameters
133  *@{
134  */
135 
136  std::string m_serialNumber; ///< The camera serial number.
137 
138  ///\todo implement config-ing of this
139  float m_tempTol {0.1}; ///< Tolerance in degrees C to declare the temperature control locked.
140 
141  uint32_t m_circBuffMaxBytes {536870912}; ///< Max size in bytes of the circular buffer to allocate. Default is 0.5 GB.
142 
143  ///@}
144 
145  int16 m_handle{ -1 }; ///< Camera handle, set when camera is opened
146 
147  std::string m_camName; ///< Camera name, filled in as part of opening the camera.
148 
149  struct gain
150  {
151  int index;
152  std::string name;
153 
154  int bitDepth;
155  };
156 
157  struct speed
158  {
159  int index;
160  int pixTime;
161  int minG;
162  int maxG;
163  std::vector<gain> gains;
164  };
165 
166  struct port
167  {
168  int index;
169  int value;
170  std::string name;
171 
172  std::vector<speed> speeds;
173  };
174 
175  std::vector<port> m_ports;
176 
177  bool m_8bit {false};
178 
179  uns32 m_circBuffBytes {0};
180  uns8 * m_circBuff {nullptr};
181 
182  FRAME_INFO m_frameInfo;
183 
184  sem_t m_frSemaphore; ///< Semaphore used to signal that a frame is ready.
185 
186 
187 public:
188  /// Default c'tor.
189  pvcamCtrl();
190 
191  /// D'tor, declared and defined for noexcept.
192  ~pvcamCtrl() noexcept
193  {}
194 
195 
196  // MagAOXApp:
197 
198  virtual void setupConfig();
199 
200  /// Implementation of loadConfig logic, separated for testing.
201  /** This is called by loadConfig().
202  */
203  int loadConfigImpl( mx::app::appConfigurator & _config /**< [in] an application configuration from which to load values*/);
204 
205  virtual void loadConfig();
206 
207  /// Startup function
208  /**
209  *
210  */
211  virtual int appStartup();
212 
213  /// Implementation of the FSM for pvcamCtrl.
214  /**
215  * \returns 0 on no critical error
216  * \returns -1 on an error requiring shutdown
217  */
218  virtual int appLogic();
219 
220  /// Shutdown the app.
221  /**
222  *
223  */
224  virtual int appShutdown();
225 
226 
227  // stdCamera interface:
228 
229  //This must set the power-on default values of
230  /* -- m_ccdTempSetpt
231  * -- m_currentROI
232  */
233  int powerOnDefaults();
234 
235  int setTempControl();
236  int setTempSetPt();
237  int setReadoutSpeed();
238  int setVShiftSpeed();
239  int setEMGain();
240  int setExpTime();
241  int setFPS();
242 
243  /// Check the next ROI
244  /** Checks if the target values are valid and adjusts them to the closest valid values if needed.
245  *
246  * \returns 0 if successful
247  * \returns -1 otherwise
248  */
249  int checkNextROI();
250 
251  int setNextROI();
252 
253  /// Sets the shutter state, via call to dssShutter::setShutterState(int) [stdCamera interface]
254  /**
255  * \returns 0 always
256  */
257  int setShutter(int sh);
258 
259  //Framegrabber interface:
260  int configureAcquisition();
261  float fps();
262  int startAcquisition();
263  int acquireAndCheckValid();
264  int loadImageIntoStream(void * dest);
265  int reconfig();
266 
267  // pvcam specific:
268  int connect();
269 
270  int fillSpeedTable();
271 
272  void dumpEnum( uns32 paramID,
273  const std::string & paramMnem
274  );
275 
276  int getTemp();
277 
278  static void st_endOfFrameCallback( FRAME_INFO * finfo,
279  void * pvcamCtrlInst
280  );
281 
282  void endOfFrameCallback( FRAME_INFO * finfo );
283 
284  /** \name Telemeter Interface
285  *
286  * @{
287  */
288  int checkRecordTimes();
289 
290  int recordTelem( const telem_stdcam * );
291 
292  int recordTelem( const telem_fgtimings * );
293 
294  ///@}
295 
296 };
297 
298 pvcamCtrl::pvcamCtrl() : MagAOXApp(MAGAOX_CURRENT_SHA1, MAGAOX_REPO_MODIFIED)
299 {
300  m_powerMgtEnabled = true;
301  m_powerOnWait = 15;
302 
303  m_expTime = 0.01;
304  m_expTimeSet = 0.01;
305 
306  m_default_x = 1599.5;
307  m_default_y = 1599.5;
308  m_default_w = 3200;
309  m_default_h = 3200;
310  m_default_bin_x = 1;
311  m_default_bin_y = 1;
312 
313  m_full_x = 1599.5;
314  m_full_y = 1599.5;
315  m_full_w = 3200;
316  m_full_h = 3200;
317 
324 
325  m_nextROI.x = m_currentROI.x;
326  m_nextROI.y = m_currentROI.y;
327  m_nextROI.w = m_currentROI.w;
328  m_nextROI.h = m_currentROI.h;
329  m_nextROI.bin_x = m_currentROI.bin_x;
330  m_nextROI.bin_y = m_currentROI.bin_y;
331 
332  m_defaultReadoutSpeed = "dynamic_range";
333  m_readoutSpeedNames = {"sensitivity", "speed", "dynamic_range", "sub_electron"};
334  m_readoutSpeedNameLabels = {"Sensitivity", "Speed", "Dynamic Range", "Sub-Electron"};
335 
338 
339 
340  return;
341 }
342 
344 {
345  config.add("camera.serialNumber", "", "camera.serialNumber", argType::Required, "camera", "serialNumber", false, "int", "The identifying serial number of the camera.");
346 
347  //put this in camera because it is a camera interface config, not a framegrabber thing per se:
348  config.add("camera.circBuffMaxBytes", "", "camera.circBuffMaxBytes", argType::Required, "camera", "circBuffMaxBytes", false, "int", "Maximum size in bytes of the circular buffer to allocate. Default is 0.5 GB.");
349 
350  stdCameraT::setupConfig(config);
352  shutterT::setupConfig(config);
353  telemeterT::setupConfig(config);
354 }
355 
356 int pvcamCtrl::loadConfigImpl( mx::app::appConfigurator & _config )
357 {
358  _config(m_serialNumber, "camera.serialNumber");
359  _config(m_circBuffMaxBytes, "camera.circBuffMaxBytes");
360 
361  if(m_serialNumber == "")
362  {
363  log<text_log>("camera serial number not provided", logPrio::LOG_CRITICAL);
364  return -1;
365  }
366 
367  stdCameraT::loadConfig(_config);
368 
375 
376  m_nextROI.x = m_currentROI.x;
377  m_nextROI.y = m_currentROI.y;
378  m_nextROI.w = m_currentROI.w;
379  m_nextROI.h = m_currentROI.h;
380  m_nextROI.bin_x = m_currentROI.bin_x;
381  m_nextROI.bin_y = m_currentROI.bin_y;
382 
384  shutterT::loadConfig(_config);
385  telemeterT::loadConfig(_config);
386 
387 
388  return 0;
389 }
390 
392 {
393  if(loadConfigImpl(config) != 0)
394  {
395  log<text_log>("error loading config", logPrio::LOG_CRITICAL);
396  m_shutdown = true;
397  }
398 }
399 
401 {
402  if(stdCameraT::appStartup() < 0)
403  {
404  return log<software_critical,-1>({__FILE__,__LINE__});
405  }
406 
407  if(sem_init(&m_frSemaphore, 0, 0) < 0)
408  {
409  return log<software_critical, -1>({__FILE__, __LINE__, errno, 0, "Initializing frame ready semaphore"});
410  }
411 
412  if(frameGrabberT::appStartup() < 0)
413  {
414  return log<software_critical, -1>({__FILE__, __LINE__});
415  }
416 
417  if(shutterT::appStartup() < 0)
418  {
419  return log<software_critical,-1>({__FILE__,__LINE__});
420  }
421 
422  if(telemeterT::appStartup() < 0)
423  {
424  return log<software_critical,-1>({__FILE__,__LINE__});
425  }
426 
427  return 0;
428 }
429 
431 {
432  ///\todo why do we run dev appLogics first?
433 
434  if( state() == stateCodes::POWERON)
435  {
436  if(!powerOnWaitElapsed())
437  {
438  return 0;
439  }
440 
442  }
443 
444  //run stdCamera's appLogic
445  if(stdCameraT::appLogic() < 0)
446  {
447  return log<software_error, -1>({__FILE__, __LINE__});
448  }
449 
450  // run frammerGrabbers's appLogic
451  if(frameGrabberT::appLogic() < 0)
452  {
453  return log<software_error, -1>({__FILE__, __LINE__});
454  }
455 
456  //and run dssShutter's appLogic
457  if(shutterT::appLogic() < 0)
458  {
459  return log<software_error, -1>({__FILE__, __LINE__});
460  }
461 
463  {
464  m_reconfig = true; //Trigger a f.g. thread reconfig.
465 
466  //Might have gotten here because of a power off.
467  if(powerState() != 1)
468  {
469  return 0;
470  }
471 
472  std::unique_lock<std::mutex> lock(m_indiMutex);
473  if(connect() < 0)
474  {
475  if(powerState() != 1 || powerStateTarget() != 1) return 0;
476  log<software_error>({__FILE__, __LINE__});
477  }
478 
479  if(state() != stateCodes::CONNECTED) return 0;
480  }
481 
482  if( state() == stateCodes::CONNECTED)
483  {
486  }
487 
489  {
490  if(getTemp() != 0)
491  {
492  if(powerState() != 1 || powerStateTarget() != 1) return 0;
493  log<software_error>({__FILE__, __LINE__});
494  return 0;
495  }
496 
497  if(stdCameraT::updateINDI() < 0)
498  {
499  return log<software_error,0>({__FILE__,__LINE__});
500  }
501 
502  if(frameGrabberT::updateINDI() < 0)
503  {
504  return log<software_error,0>({__FILE__,__LINE__});
505  }
506 
507  if(telemeterT::appLogic() < 0)
508  {
509  log<software_error>({__FILE__, __LINE__});
510  }
511 
512  recordCamera();
513  }
514 
515 
516  return 0;
517 }
518 
520 {
521  if(m_handle != -1)
522  {
523  if(!pl_cam_close(m_handle))
524  {
525  log_pvcam_software_error("pl_cam_close", "continuing");
526  }
527  m_handle = -1;
528  }
529 
530  if(!pl_pvcam_uninit())
531  {
532  if(pl_error_code() != PL_ERR_LIBRARY_NOT_INITIALIZED) /// \todo this error code is manually defined
533  {
534  log_pvcam_software_error("pl_pvcam_uninit", "continuing");
535  }
536  }
537 
538  ///\todo error check these base class fxns.
540  {
541  log<software_error>({__FILE__, __LINE__, "error from frameGrabberT::appShutdown()"});
542  }
543 
544  if(shutterT::appShutdown() < 0)
545  {
546  log<software_error>({__FILE__, __LINE__, "error from shutterT::appShutdown()"});
547  }
548 
549  if(telemeterT::appShutdown() < 0)
550  {
551  log<software_error>({__FILE__, __LINE__, "error from telemeterT::appShutdown()"});
552  }
553 
554  return 0;
555 }
556 
558 {
559  m_expTime = 0.01;
560  m_expTimeSet = 0.01;
561 
568 
573  m_nextROI.bin_x = m_default_bin_x;
574  m_nextROI.bin_y = m_default_bin_y;
575 
578 
579  return 0;
580 }
581 
583 {
584  return 0;
585 }
586 
588 {
589  return 0;
590 }
591 
593 {
595 
596  return 0;
597 }
598 
600 {
601  return 0;
602 }
603 
605 {
606  return 0;
607 }
608 
610 {
611  ulong64 minExpTime, maxExpTime;
612 
613  if(!pl_get_param(m_handle, PARAM_EXPOSURE_TIME, ATTR_MIN, static_cast<void *>(&minExpTime)))
614  {
615  log_pvcam_software_error("pl_get_param", "PARAM_EXPOSURE_TIME ATTR_MIN");
616  log<software_error>({__FILE__, __LINE__, "could not set exposure time"});
617  return -1;
618  }
619 
620  if(!pl_get_param(m_handle, PARAM_EXPOSURE_TIME, ATTR_MAX, static_cast<void *>(&maxExpTime)))
621  {
622  log_pvcam_software_error("pl_get_param", "PARAM_EXPOSURE_TIME ATTR_MAX");
623  log<software_error>({__FILE__, __LINE__, "could not set exposure time"});
624  return -1;
625  }
626 
627  std::cerr << "Exposure time min: " << minExpTime << " max: " << maxExpTime << "\n";
628 
629  if(m_expTimeSet*1e6 < minExpTime)
630  {
631  m_expTimeSet = (int) (minExpTime/1e6+0.5);
632  log<text_log>("increased m_expTimeSet to: " + std::to_string(m_expTimeSet), logPrio::LOG_INFO);
633  }
634 
635  if(m_expTimeSet * 1e6 > maxExpTime)
636  {
637  m_expTimeSet = (int) (maxExpTime / 1e6 - 0.5);
638  log<text_log>("decreased m_expTimeSet to: " + std::to_string(m_expTimeSet), logPrio::LOG_INFO);
639  }
640 
642 
643  return 0;
644 }
645 
647 {
648  m_expTimeSet = 1.0/m_fpsSet;
649  return setExpTime();
650 }
651 
653 {
654  if(m_nextROI.w > 3200)
655  {
656  m_nextROI.w = 3200;
657  }
658 
659  int x0 = m_nextROI.x - 0.5*m_nextROI.w;
660 
661  if(x0 < 0)
662  {
663  m_nextROI.w += x0;
664  m_nextROI.x = 0;
665  }
666 
667  int x1 = m_nextROI.x + 0.5*m_nextROI.w;
668 
669  if(x1 > 3199)
670  {
671  m_nextROI.w = 3199 - x0;
672  m_nextROI.x = x0 + 0.5*m_nextROI.w;
673  }
674 
675  if(m_nextROI.h > 3200)
676  {
677  m_nextROI.h = 3200;
678  }
679 
680  int y0 = m_nextROI.y - 0.5 * m_nextROI.h;
681 
682  if(y0 < 0)
683  {
684  m_nextROI.h += y0;
685  m_nextROI.y = 0;
686  }
687 
688  int y1 = m_nextROI.y + 0.5 * m_nextROI.h;
689 
690  if(y1 > 3199)
691  {
692  m_nextROI.h = 3199 - y0;
693  m_nextROI.y = y0 + 0.5 * m_nextROI.h;
694  }
695 
696  return 0;
697 }
698 
700 {
701  //This is done in setup acq
703  return 0;
704 }
705 
707 {
708  recordCamera(true);
709  return shutterT::setShutterState(sh);
710 }
711 
713 {
714 
715  recordCamera(true);
716  //-- 0: register the callback
717  if(pl_cam_deregister_callback(m_handle, PL_CALLBACK_EOF) == false) // Because we registered it last time we configured acq:
718  {
719  log_pvcam_software_error("pl_cam_deregister_callback", "PL_CALLBACK_EOF");
720  }
721 
722  if(pl_cam_register_callback_ex3(m_handle, PL_CALLBACK_EOF, reinterpret_cast<void *>(&st_endOfFrameCallback), static_cast<void *>(this)) != true)
723  {
724  log_pvcam_software_error("pl_cam_register_callback_ex3", "PL_CALLBACK_EOF");
725  return -1;
726  }
727 
728  //-- 1: Set speed:
729  int32 value;
730 
731  if(m_readoutSpeedNameSet == "sensitivity")
732  {
733  value=0;
734  m_8bit = false;
735  }
736  else if(m_readoutSpeedNameSet == "speed")
737  {
738  value=1;
739  m_8bit = true;
740  }
741  else if(m_readoutSpeedNameSet == "dynamic_range")
742  {
743  value=2;
744  m_8bit = false;
745  }
746  else if(m_readoutSpeedNameSet == "sub_electron")
747  {
748  value=3;
749  m_8bit = false;
750  }
751  else
752  {
753  value = 2;
754  m_8bit = false;
755  m_readoutSpeedNameSet = "dynamic_range";
756  }
758 
759  if(pl_set_param(m_handle, PARAM_READOUT_PORT, static_cast<void *>(&value)) == false)
760  {
761  log_pvcam_software_error("pl_set_param", "PARAM_READOUT_PORT");
762  return -1;
763  }
764 
765  //-- 2: Set ROI:
766  rgn_type pvROI;
767  pvROI.s1 = m_nextROI.x - 0.5*m_nextROI.w;
768  pvROI.s2 = pvROI.s1 + m_nextROI.w-1;
769  pvROI.sbin = m_nextROI.bin_x;
770  pvROI.p1 = m_nextROI.y - 0.5*m_nextROI.h;
771  pvROI.p2 = pvROI.p1 + m_nextROI.h-1;
772  pvROI.pbin = m_nextROI.bin_y;
773 
775 
776  m_width = (pvROI.s2 - pvROI.s1 + 1) / pvROI.sbin;
777  m_height = (pvROI.p2 - pvROI.p1 + 1) / pvROI.pbin;
778  m_dataType = _DATATYPE_UINT16;
779 
780 
781  //-- 3: Setup continuous acquisition
782  //std::cerr << pvROI.s1 << " " << pvROI.s2 << " " << pvROI.sbin << " " << pvROI.p1 << " " << pvROI.p2 << " " << pvROI.pbin << "\n";
783  uns32 fsize;
784 
785  uns32 exptime = m_expTimeSet * 1e6;
786  if(pl_exp_setup_cont(m_handle, 1, &pvROI, TIMED_MODE, exptime, &fsize, CIRC_OVERWRITE) == false)
787  {
788  log_pvcam_software_error("pl_exp_setup_cont", "");
789  m_shutdown = true;
790  return -1;
791  }
792 
793  if (pl_get_param(m_handle, PARAM_EXPOSURE_TIME, ATTR_CURRENT, &exptime) == false)
794  {
795  log_pvcam_software_error("pl_get_param", "PARAM_EXPOSURE_TIME");
796  }
797  m_expTime = (1.0*exptime) / 1e6;
799 
800  uns32 readouttime=0;
801  if(pl_get_param(m_handle, PARAM_READOUT_TIME, ATTR_CURRENT, &readouttime) == false)
802  {
803  log_pvcam_software_error("pl_get_param", "PARAM_READOUT_TIME");
804  }
805 
806  long64 predelay = 0;
807  if(pl_get_param(m_handle, PARAM_PRE_TRIGGER_DELAY, ATTR_CURRENT, &predelay) == false)
808  {
809  log_pvcam_software_error("pl_get_param", "PARAM_PRE_TRIGGER_DELAY");
810  }
811 
812  long64 postdelay = 0;
813  if(pl_get_param(m_handle, PARAM_POST_TRIGGER_DELAY, ATTR_CURRENT, &postdelay) == false)
814  {
815  log_pvcam_software_error("pl_get_param", "PARAM_POST_TRIGGER_DELAY");
816  }
817 
818  m_fps = 1.0/(m_expTime + predelay/1e9 + postdelay/1e9);
819  m_fpsSet = m_fps;
820 
821  //-- 4: Allocate the acq circular buffer
822  if(m_circBuff != nullptr)
823  {
824  delete[] m_circBuff;
825  m_circBuffBytes = 0;
826  m_circBuff = nullptr;
827  }
828 
829  m_circBuffBytes = ( (uns32) (m_circBuffMaxBytes / fsize)) * fsize;
830 
831  m_circBuff = new (std::nothrow) uns8[m_circBuffBytes];
832 
833  if(m_circBuff == nullptr)
834  {
835  log<software_critical>({__FILE__, __LINE__, "failed to allocate acquisition circular buffer."});
837  return -1;
838  }
839 
840  recordCamera(true);
841 
842  return 0;
843 }
844 
846 {
847  return m_fps;
848 }
849 
851 {
852  if(pl_exp_start_cont(m_handle, m_circBuff, m_circBuffBytes) == false)
853  {
854  log_pvcam_software_error("pv_exp_start_cont", "");
855  return -1;
856  }
857 
858  log<text_log>("continuous acquisition started", logPrio::LOG_INFO);
859  return 0;
860 }
861 
863 {
864  int rv = sem_trywait(&m_frSemaphore);
865  if( rv == 0)
866  {
867  return 0;
868  }
869  else if(errno != EAGAIN)
870  {
871  log<software_critical>({__FILE__, __LINE__, errno, 0, "sem_trywait"});
872  return -1;
873  }
874 
875  timespec ts;
876 
877  if(clock_gettime(CLOCK_REALTIME, &ts) < 0)
878  {
879  log<software_critical>({__FILE__, __LINE__, errno, 0, "clock_gettime"});
880  return -1;
881  }
882 
883  mx::sys::timespecAddNsec(ts, 1e9);
884 
885  rv = sem_timedwait(&m_frSemaphore, &ts);
886  if(rv == 0)
887  {
888  return 0;
889  }
890  else if(errno != EAGAIN && errno != ETIMEDOUT)
891  {
892  log<software_critical>({__FILE__, __LINE__, errno, 0, "sem_timedwait"});
893  return -1;
894  }
895 
896  return 1;
897 }
898 
900 {
901  clock_gettime(CLOCK_REALTIME, &m_currImageTimestamp);
902 
903  // Obtain a pointer to the last acquired frame
904  uns8 *frame;
905  if(pl_exp_get_latest_frame(m_handle, reinterpret_cast<void **>(&frame)) == false)
906  {
907  log_pvcam_software_error("pl_exp_get_latest_frame", "");
908  }
909 
910  if(m_8bit)
911  {
912  uint16_t * dest16 = static_cast<uint16_t*>(dest);
913  uint8_t * src8 = static_cast<uint8_t*>(frame);
914  for(uint32_t i=0; i < m_width*m_height; ++i)
915  {
916  dest16[i] = src8[i];
917  }
918  }
919  else
920  {
921  memcpy(dest, frame, m_width*m_height*2);
922  }
923 
924  return 0;
925 }
926 
928 {
929  if(pl_exp_stop_cont(m_handle,CCS_HALT) == false)
930  {
931  log_pvcam_software_error("pl_exp_stop_cont", "");
932  }
933  return 0;
934 }
935 
937 {
938 
939  //In picam, we had to initialize every time. We'll do that here too.
940 
941  //So close handle if it's open
942  if(m_handle != -1)
943  {
944  if(!pl_cam_close(m_handle))
945  {
946  log_pvcam_software_error("pl_cam_close", "");
947  return -1;
948  }
949  m_handle = -1;
950  }
951 
952  //Uninit
953  if(!pl_pvcam_uninit())
954  {
955  if(pl_error_code() != PL_ERR_LIBRARY_NOT_INITIALIZED) /// \todo this error code is manually defined
956  {
957  log_pvcam_software_error("pl_pvcam_uninit", "continuing");
958  }
959  }
960 
961  if(!pl_pvcam_init())
962  {
963  log_pvcam_software_error("pl_pvcam_init", "");
964  return -1;
965  }
966 
967  int16 nrOfCameras;
968 
969  // Read the number of cameras in the system.
970  // This will return total number of PVCAM cameras regardless of interface.
971  if(pl_cam_get_total(&nrOfCameras) != PV_OK)
972  {
973  log_pvcam_software_error("pl_cam_get_total", "");
974  return -1;
975  }
976 
977  if(nrOfCameras == 0)
978  {
979  if(!stateLogged())
980  {
981  log<text_log>("Found 0 pvcam cameras.", logPrio::LOG_INFO);
982  }
984  return 0;
985  }
986 
987  log<text_log>("Found " + std::to_string(nrOfCameras) + " pvcam cameras.", logPrio::LOG_INFO);
988 
989 
990  for(int n=0; n < nrOfCameras; ++n)
991  {
992  char camName[CAM_NAME_LEN] {'\0'};
993 
994  // Obtain PVCAM-name for this particular camera
995  if(pl_cam_get_name(n, camName) != PV_OK)
996  {
997  log_pvcam_software_error("pl_cam_get_name", "");
998  return -1;
999  }
1000 
1001  int16_t handle = -1;
1002 
1003  //Open to check its serial number
1004  if(!pl_cam_open(camName, &handle, OPEN_EXCLUSIVE))
1005  {
1006  log_pvcam_software_error("pl_cam_open", ""); //We log this for now, but with 2 apps running we prob want to ignore
1007  continue;
1008  }
1009 
1010  // Read the version of the Device Driver
1011 
1012  rs_bool isAvailable;
1013  if(!pl_get_param(handle, PARAM_HEAD_SER_NUM_ALPHA, ATTR_AVAIL, static_cast<void*>(&isAvailable)))
1014  {
1015  log_pvcam_software_error("pl_get_param", "PARAM_HEAD_SER_NUM_ALPHA ATTR_AVAIL");
1016 
1017  if(!pl_cam_close(handle))
1018  {
1019  log_pvcam_software_error("pl_cam_close", "");
1020  }
1021 
1022  return -1;
1023  }
1024 
1025  if(isAvailable)
1026  {
1027  char camSerial[MAX_ALPHA_SER_NUM_LEN]{ '\0' };
1028 
1029  if(!pl_get_param(handle, PARAM_HEAD_SER_NUM_ALPHA, ATTR_CURRENT, static_cast<void*>(camSerial)))
1030  {
1031  log_pvcam_software_error("pl_get_param", "PARAM_HEAD_SER_NUM_ALPHA ATTR_CURRENT");
1032 
1033  if(!pl_cam_close(handle))
1034  {
1035  log_pvcam_software_error("pl_cam_close", "");
1036  }
1037 
1038  return -1;
1039  }
1040 
1041  if(camSerial == m_serialNumber)
1042  {
1043  state(stateCodes::NOTCONNECTED); //not strictly true, but logically true until m_handle is set
1044  m_camName = camName;
1045  m_handle = handle;
1046  break;
1047  }
1048  }
1049 
1050  //If we're here then either it didn't have a serial number, or it didn't have the right serial number
1051  if(!pl_cam_close(handle))
1052  {
1053  log_pvcam_software_error("pl_cam_close", "");
1054  return -1;
1055  }
1056 
1057  }
1058 
1059  if(m_handle > -1)
1060  {
1061  log<text_log>("Opened camera " + m_serialNumber + " at " + m_camName, logPrio::LOG_INFO);
1063 
1064 
1065  int32 res;
1066  uns16 idx;
1067 
1068  //Set exposure resolution to usec.
1069 
1070  idx = 1;
1071  if(pl_set_param(m_handle, PARAM_EXP_RES_INDEX, &idx) == false)
1072  {
1073  log_pvcam_software_error("pl_set_param", "PARAM_EXP_RES_INDEX");
1074  }
1075 
1076  if (pl_get_param(m_handle, PARAM_EXP_RES, ATTR_CURRENT, &res) == false)
1077  {
1078  log_pvcam_software_error("pl_get_param", "PARAM_EXP_RES");
1079  }
1080 
1081  if (pl_get_param(m_handle, PARAM_EXP_RES_INDEX, ATTR_CURRENT, &idx) == false)
1082  {
1083  log_pvcam_software_error("pl_get_param", "PARAM_EXP_RES_INDEX");
1084  }
1085 
1086  fillSpeedTable();
1087  }
1088  else
1089  {
1090  if(!stateLogged())
1091  {
1092  log<text_log>("camera not found", logPrio::LOG_INFO);
1093  }
1095  }
1096 
1097  return 0;
1098 }
1099 
1101 {
1103  {
1104  return -1;
1105  }
1106 
1107  uns32 nports;
1108 
1109  if(pl_get_param(m_handle, PARAM_READOUT_PORT, ATTR_COUNT, static_cast<void *>(&nports)) == false)
1110  {
1111  log_pvcam_software_error("pl_get_param", "PARAM_READOUT_PORT");
1112  return -1;
1113  }
1114 
1115  std::cerr << "Found " << nports << " ports\n";
1116 
1117  m_ports.resize(nports);
1118 
1119  for(uns32 p=0; p < nports; ++p)
1120  {
1121  uns32 strLength;
1122  if(pl_enum_str_length(m_handle, PARAM_READOUT_PORT, p, &strLength) == false)
1123  {
1124  log_pvcam_software_error("pl_enum_str_length", "PARAM_READOUT_PORT");
1125  return -1;
1126  }
1127 
1128  char* text = new (std::nothrow) char[strLength];
1129  if (!text)
1130  {
1131  ///\todo log this properly
1132  std::cerr << "failed to allocate string\n";
1133  return -1;
1134  }
1135 
1136  int32 value;
1137  if(pl_get_enum_param(m_handle, PARAM_READOUT_PORT, p, &value, text, strLength) == false)
1138  {
1139  log_pvcam_software_error("pl_get_enum_param", "PARAM_READOUT_PORT");
1140  delete [] text;
1141  return false;
1142  }
1143 
1144  m_ports[p].index = p;
1145  m_ports[p].value = value;
1146  m_ports[p].name = text;
1147 
1148  std::cerr << "Port: " << p << " name: " << text << " value: " << value << "\n";
1149 
1150  delete [] text;
1151 
1152  if(pl_set_param(m_handle, PARAM_READOUT_PORT, static_cast<void *>(&value)) == false)
1153  {
1154  log_pvcam_software_error("pl_set_param", "PARAM_READOUT_PORT");
1155  return -1;
1156  }
1157 
1158  uns32 nspeeds;
1159  if(pl_get_param(m_handle, PARAM_SPDTAB_INDEX, ATTR_COUNT, static_cast<void *>(&nspeeds)) == false)
1160  {
1161  log_pvcam_software_error("pl_get_param", "PARAM_SPDTAB_INDEX");
1162  return -1;
1163  }
1164  std::cerr << " Speeds: " << nspeeds << "\n";
1165 
1166  m_ports[p].speeds.resize(nspeeds);
1167 
1168  for(uns32 s = 0; s < nspeeds; ++s)
1169  {
1170  if(pl_set_param(m_handle, PARAM_SPDTAB_INDEX, static_cast<void *>(&s)) == false)
1171  {
1172  log_pvcam_software_error("pl_set_param", "PARAM_SPDTAB_INDEX");
1173  return -1;
1174  }
1175 
1176  uns16 pixtime;
1177  if(pl_get_param(m_handle, PARAM_PIX_TIME, ATTR_CURRENT, static_cast<void *>(&pixtime)) == false)
1178  {
1179  log_pvcam_software_error("pl_get_param", "PARAM_PIX_TIME");
1180  return -1;
1181  }
1182 
1183  m_ports[p].speeds[s].pixTime = pixtime;
1184 
1185  uns32 ngains;
1186  if(pl_get_param(m_handle, PARAM_GAIN_INDEX, ATTR_COUNT, static_cast<void *>(&ngains)) == false)
1187  {
1188  log_pvcam_software_error("pl_get_param", "PARAM_GAIN_INDEX ATTR_COUNT");
1189  return -1;
1190  }
1191 
1192  int16 ming;
1193  if(pl_get_param(m_handle, PARAM_GAIN_INDEX, ATTR_MIN, static_cast<void *>(&ming)) == false)
1194  {
1195  log_pvcam_software_error("pl_get_param", "PARAM_GAIN_INDEX ATTR_MIN");
1196  return -1;
1197  }
1198 
1199  int16 maxg;
1200  if(pl_get_param(m_handle, PARAM_GAIN_INDEX, ATTR_MIN, static_cast<void *>(&maxg)) == false)
1201  {
1202  log_pvcam_software_error("pl_get_param", "PARAM_GAIN_INDEX ATTR_MAX");
1203  return -1;
1204  }
1205 
1206  std::cerr << " Speed: " << s << " " << " pixtime: " << pixtime << " gains: " << ngains << " [" << ming << "-" << maxg << "]\n";
1207 
1208  m_ports[p].speeds[s].minG = ming;
1209  m_ports[p].speeds[s].maxG = maxg;
1210 
1211  m_ports[p].speeds[s].gains.resize(ngains);
1212 
1213  for(uns32 g=0; g < ngains; ++g)
1214  {
1215 
1216  int16 gg = ming + g;
1217  if(pl_set_param(m_handle, PARAM_GAIN_INDEX, static_cast<void *>(&gg)) == false)
1218  {
1219  log_pvcam_software_error("pl_set_param", "PARAM_GAIN_INDEX");
1220  return -1;
1221  }
1222 
1223  int16 bitdepth;
1224  if(pl_get_param(m_handle, PARAM_BIT_DEPTH, ATTR_CURRENT, static_cast<void *>(&bitdepth)) == false)
1225  {
1226  log_pvcam_software_error("pl_get_param", "PARAM_BIT_DEPTH ATTR_CURRENT");
1227  return -1;
1228  }
1229  std::cerr << " Gain: " << g << " bitdepth: " << bitdepth << "\n";
1230  }
1231  }
1232  }
1233 
1234  return 0;
1235 }
1236 
1237 void pvcamCtrl::dumpEnum(uns32 paramID, const std::string & paramMnem)
1238 {
1239 
1240  if(state() == stateCodes::CONNECTED)
1241  {
1242  uns32 count;
1243 
1244  if(PV_OK != pl_get_param(m_handle, paramID, ATTR_COUNT, static_cast<void *>(&count)))
1245  {
1246  log_pvcam_software_error("pl_get_param", paramMnem);
1247  // TODO: Handle error
1248  return;
1249  }
1250  if(count == 0)
1251  {
1252  std::cerr << paramMnem << ": count 0\n";
1253  return;
1254  }
1255  for (uns32 n = 0; n < count; ++n)
1256  {
1257  uns32 strLength;
1258  if(PV_OK != pl_enum_str_length(m_handle, paramID, n, &strLength))
1259  {
1260  log_pvcam_software_error("pl_enum_str_length", paramMnem);
1261  // TODO: Handle error
1262  break;
1263  }
1264  char *text = new (std::nothrow) char[strLength];
1265  if(!text)
1266  {
1267  // TODO: Handle error
1268  break;
1269  }
1270  int32 value;
1271  if(PV_OK != pl_get_enum_param(m_handle, paramID, n, &value, text, strLength))
1272  {
1273  log_pvcam_software_error("pl_get_enum_param", paramMnem);
1274  // TODO: Handle error
1275  delete[] text;
1276  break;
1277  }
1278  std::cerr << paramMnem;
1279  fprintf(stderr, " item at index %u, value: %d, text: '%s'\n", n, value, text);
1280  delete[] text;
1281  }
1282  }
1283  else
1284  {
1285  std::cerr << "dumpEnum: not CONNECTED\n";
1286  }
1287 }
1288 
1289 
1291 {
1292  if(state() == stateCodes::OPERATING)
1293  {
1294  return 0;
1295  }
1296 
1297  rs_bool isAvailable;
1298  if(!pl_get_param(m_handle, PARAM_TEMP_SETPOINT, ATTR_AVAIL, static_cast<void*>(&isAvailable)))
1299  {
1300  if(powerState() != 1 || powerStateTarget() != 1) return 0;
1301  log_pvcam_software_error("pl_get_param", "PARAM_TEMP ATTR_AVAIL");
1303  }
1304 
1305  int16 stemp;
1306  if(isAvailable) //Maybe this is a separate check. Don't yet know what happens when acquiring
1307  {
1308  if(!pl_get_param(m_handle, PARAM_TEMP_SETPOINT, ATTR_CURRENT, static_cast<void*>(&stemp)))
1309  {
1310  if(powerState() != 1 || powerStateTarget() != 1) return 0;
1311  log_pvcam_software_error("pl_get_param", "PARAM_TEMP ATTR_AVAIL");
1313  }
1314 
1315  m_ccdTempSetpt = stemp/100.0;
1316  }
1317 
1318  if(!pl_get_param(m_handle, PARAM_TEMP, ATTR_AVAIL, static_cast<void*>(&isAvailable)))
1319  {
1320  if(powerState() != 1 || powerStateTarget() != 1) return 0;
1321  log_pvcam_software_error("pl_get_param", "PARAM_TEMP ATTR_AVAIL");
1323  }
1324 
1325  int16 ctemp;
1326  if(isAvailable) //Maybe this is a separate check. Don't yet know what happens when acquiring
1327  {
1328  if(!pl_get_param(m_handle, PARAM_TEMP, ATTR_CURRENT, static_cast<void*>(&ctemp)))
1329  {
1330  if(powerState() != 1 || powerStateTarget() != 1) return 0;
1331  log_pvcam_software_error("pl_get_param", "PARAM_TEMP ATTR_AVAIL");
1333  }
1334 
1335  m_ccdTemp = ctemp/100.0;
1336  }
1337 
1338  if(fabs(m_ccdTemp - m_ccdTempSetpt) > m_tempTol)
1339  {
1340  m_tempControlStatus = true;
1341  m_tempControlOnTarget = false;
1342  m_tempControlStatusStr = "UNLOCKED";
1343  }
1344  else
1345  {
1346  m_tempControlStatus = true;
1347  m_tempControlOnTarget = true;
1348  m_tempControlStatusStr = "LOCKED";
1349  }
1350 
1351  return 0;
1352 }
1353 
1354 void pvcamCtrl::st_endOfFrameCallback( FRAME_INFO *finfo,
1355  void *pvcamCtrlInst
1356  )
1357 {
1358  static_cast<pvcamCtrl *>(pvcamCtrlInst)->endOfFrameCallback(finfo);
1359 }
1360 
1361 void pvcamCtrl::endOfFrameCallback(FRAME_INFO *finfo)
1362 {
1363  m_frameInfo = *finfo;
1364 
1365  // Now tell the writer to get going
1366  if(sem_post(&m_frSemaphore) < 0)
1367  {
1368  log<software_critical>({__FILE__, __LINE__, errno, 0, "Error posting to frame ready semaphore"});
1369  return;
1370  }
1371 }
1372 
1374 {
1376 }
1377 
1379 {
1380  return recordCamera(true);
1381 }
1382 
1383 inline
1385 {
1386  return recordFGTimings(true);
1387 }
1388 
1389 } // namespace app
1390 } //namespace MagAOX
1391 
1392 #endif //pvcamCtrl_hpp
The base-class for MagAO-X applications.
Definition: MagAOXApp.hpp:75
stateCodes::stateCodeT state()
Get the current state code.
Definition: MagAOXApp.hpp:2082
int powerState()
Returns the current power state.
Definition: MagAOXApp.hpp:3179
int m_shutdown
Flag to signal it's time to shutdown. When not 0, the main loop exits.
Definition: MagAOXApp.hpp:102
int powerStateTarget()
Returns the target power state.
Definition: MagAOXApp.hpp:3187
int stateLogged()
Updates and returns the value of m_stateLogged. Will be 0 on first call after a state change,...
Definition: MagAOXApp.hpp:2140
static int log(const typename logT::messageT &msg, logPrioT level=logPrio::LOG_DEFAULT)
Make a log entry.
Definition: MagAOXApp.hpp:1590
bool powerOnWaitElapsed()
This method tests whether the power on wait time has elapsed.
Definition: MagAOXApp.hpp:3163
unsigned long m_powerOnWait
Time in sec to wait for device to boot after power on.
Definition: MagAOXApp.hpp:989
std::mutex m_indiMutex
Mutex for locking INDI communications.
Definition: MagAOXApp.hpp:540
bool m_powerMgtEnabled
Flag controls whether power mgt is used. Set this in the constructor of a derived app....
Definition: MagAOXApp.hpp:981
MagAO-X Uniblitz DSS Shutter interface.
Definition: dssShutter.hpp:37
void loadConfig(mx::app::appConfigurator &config)
load the configuration system results
Definition: dssShutter.hpp:322
void setupConfig(mx::app::appConfigurator &config)
Setup the configuration system.
Definition: dssShutter.hpp:304
int setShutterState(int sh)
Change shutter state.
Definition: dssShutter.hpp:486
timespec m_currImageTimestamp
The timestamp of the current image.
uint32_t m_width
The width of the image, once deinterlaced etc.
int appShutdown()
Shuts down the framegrabber thread.
void loadConfig(mx::app::appConfigurator &config)
load the configuration system results
void setupConfig(mx::app::appConfigurator &config)
Setup the configuration system.
int updateINDI()
Update the INDI properties for this device controller.
uint8_t m_dataType
The ImageStreamIO type code.
bool m_reconfig
Flag to set if a camera reconfiguration requires a framegrabber reset.
int appLogic()
Checks the framegrabber thread.
uint32_t m_height
The height of the image, once deinterlaced etc.
MagAO-X standard camera interface.
Definition: stdCamera.hpp:232
std::vector< std::string > m_readoutSpeedNames
Definition: stdCamera.hpp:279
float m_fpsSet
The commanded fps, as set by user.
Definition: stdCamera.hpp:320
float m_default_x
Power-on ROI center x coordinate.
Definition: stdCamera.hpp:395
std::string m_tempControlStatusStr
Camera specific description of temperature control status.
Definition: stdCamera.hpp:267
std::vector< std::string > m_readoutSpeedNameLabels
Definition: stdCamera.hpp:280
std::string m_defaultReadoutSpeed
The default readout speed of the camera.
Definition: stdCamera.hpp:245
float m_expTime
The current exposure time, in seconds.
Definition: stdCamera.hpp:312
int m_default_bin_x
Power-on ROI x binning.
Definition: stdCamera.hpp:399
int m_default_h
Power-on ROI height.
Definition: stdCamera.hpp:398
float m_expTimeSet
The exposure time, in seconds, as set by user.
Definition: stdCamera.hpp:313
void setupConfig(mx::app::appConfigurator &config)
Setup the configuration system.
Definition: stdCamera.hpp:980
float m_full_y
The full ROI center y coordinate.
Definition: stdCamera.hpp:403
std::string m_readoutSpeedName
The current readout speed name.
Definition: stdCamera.hpp:282
float m_ccdTempSetpt
The desired temperature, in C.
Definition: stdCamera.hpp:260
bool m_tempControlStatus
Whether or not temperature control is active.
Definition: stdCamera.hpp:262
float m_full_x
The full ROI center x coordinate.
Definition: stdCamera.hpp:402
float m_ccdTemp
The current temperature, in C.
Definition: stdCamera.hpp:258
int updateINDI()
Update the INDI properties for this device controller.
Definition: stdCamera.hpp:2739
bool m_tempControlOnTarget
Whether or not the temperature control system is on its target temperature.
Definition: stdCamera.hpp:265
void loadConfig(mx::app::appConfigurator &config)
load the configuration system results
Definition: stdCamera.hpp:1019
float m_default_y
Power-on ROI center y coordinate.
Definition: stdCamera.hpp:396
int m_default_bin_y
Power-on ROI y binning.
Definition: stdCamera.hpp:400
std::string m_readoutSpeedNameSet
The user requested readout speed name, to be set by derived()
Definition: stdCamera.hpp:283
The MagAO-X pvcam controller.
Definition: pvcamCtrl.hpp:76
static constexpr bool c_stdCamera_exptimeCtrl
app::dev config to tell stdCamera to expose exposure time controls
Definition: pvcamCtrl.hpp:107
int16 m_handle
Camera handle, set when camera is opened.
Definition: pvcamCtrl.hpp:145
static constexpr bool c_stdCamera_usesROI
app:dev config to tell stdCamera to expose ROI controls
Definition: pvcamCtrl.hpp:117
static constexpr bool c_stdCamera_emGain
app::dev config to tell stdCamera to expose EM gain controls
Definition: pvcamCtrl.hpp:105
static constexpr bool c_stdCamera_usesStateString
app::dev confg to tell stdCamera to expose the state string property
Definition: pvcamCtrl.hpp:123
static constexpr bool c_stdCamera_fps
app::dev config to tell stdCamera not to expose FPS status
Definition: pvcamCtrl.hpp:111
friend class pvcamCtrl_test
Definition: pvcamCtrl.hpp:84
void endOfFrameCallback(FRAME_INFO *finfo)
Definition: pvcamCtrl.hpp:1361
virtual void loadConfig()
Definition: pvcamCtrl.hpp:391
static constexpr bool c_stdCamera_tempControl
app::dev config to tell stdCamera to expose temperature controls
Definition: pvcamCtrl.hpp:97
int recordTelem(const telem_stdcam *)
Definition: pvcamCtrl.hpp:1378
static void st_endOfFrameCallback(FRAME_INFO *finfo, void *pvcamCtrlInst)
Definition: pvcamCtrl.hpp:1354
int setShutter(int sh)
Sets the shutter state, via call to dssShutter::setShutterState(int) [stdCamera interface].
Definition: pvcamCtrl.hpp:706
static constexpr bool c_stdCamera_usesModes
app:dev config to tell stdCamera not to expose mode controls
Definition: pvcamCtrl.hpp:115
std::vector< port > m_ports
Definition: pvcamCtrl.hpp:175
virtual int appShutdown()
Shutdown the app.
Definition: pvcamCtrl.hpp:519
uint32_t m_circBuffMaxBytes
Max size in bytes of the circular buffer to allocate. Default is 0.5 GB.
Definition: pvcamCtrl.hpp:141
int checkNextROI()
Check the next ROI.
Definition: pvcamCtrl.hpp:652
std::vector< speed > speeds
Definition: pvcamCtrl.hpp:172
static constexpr bool c_stdCamera_hasShutter
app:dev config to tell stdCamera to expose shutter controls
Definition: pvcamCtrl.hpp:121
static constexpr bool c_stdCamera_fpsCtrl
app::dev config to tell stdCamera not to expose FPS controls
Definition: pvcamCtrl.hpp:109
dev::stdCamera< pvcamCtrl > stdCameraT
Definition: pvcamCtrl.hpp:78
dev::frameGrabber< pvcamCtrl > frameGrabberT
Definition: pvcamCtrl.hpp:79
static constexpr bool c_stdCamera_temp
app::dev config to tell stdCamera to expose temperature
Definition: pvcamCtrl.hpp:99
pvcamCtrl()
Default c'tor.
Definition: pvcamCtrl.hpp:298
virtual int appLogic()
Implementation of the FSM for pvcamCtrl.
Definition: pvcamCtrl.hpp:430
sem_t m_frSemaphore
Semaphore used to signal that a frame is ready.
Definition: pvcamCtrl.hpp:184
int loadConfigImpl(mx::app::appConfigurator &_config)
Implementation of loadConfig logic, separated for testing.
Definition: pvcamCtrl.hpp:356
~pvcamCtrl() noexcept
D'tor, declared and defined for noexcept.
Definition: pvcamCtrl.hpp:192
std::string m_camName
Camera name, filled in as part of opening the camera.
Definition: pvcamCtrl.hpp:147
virtual int appStartup()
Startup function.
Definition: pvcamCtrl.hpp:400
int loadImageIntoStream(void *dest)
Definition: pvcamCtrl.hpp:899
dev::dssShutter< pvcamCtrl > shutterT
Definition: pvcamCtrl.hpp:80
static constexpr bool c_stdCamera_readoutSpeed
app::dev config to tell stdCamera to expose readout speed controls
Definition: pvcamCtrl.hpp:101
void dumpEnum(uns32 paramID, const std::string &paramMnem)
Definition: pvcamCtrl.hpp:1237
static constexpr bool c_stdCamera_synchro
app::dev config to tell stdCamera to not expose synchro mode controls
Definition: pvcamCtrl.hpp:113
dev::telemeter< pvcamCtrl > telemeterT
Definition: pvcamCtrl.hpp:81
std::vector< gain > gains
Definition: pvcamCtrl.hpp:163
static constexpr bool c_stdCamera_cropMode
app:dev config to tell stdCamera to expose Crop Mode controls
Definition: pvcamCtrl.hpp:119
float m_tempTol
Tolerance in degrees C to declare the temperature control locked.
Definition: pvcamCtrl.hpp:139
std::string m_serialNumber
The camera serial number.
Definition: pvcamCtrl.hpp:136
virtual void setupConfig()
Definition: pvcamCtrl.hpp:343
static constexpr bool c_stdCamera_vShiftSpeed
app:dev config to tell stdCamera to expose vertical shift speed control
Definition: pvcamCtrl.hpp:103
static constexpr bool c_frameGrabber_flippable
app:dev config to tell framegrabber this camera can be flipped
Definition: pvcamCtrl.hpp:125
@ OPERATING
The device is operating, other than homing.
Definition: stateCodes.hpp:50
@ NODEVICE
No device exists for the application to control.
Definition: stateCodes.hpp:41
@ FAILURE
The application has failed, should be used when m_shutdown is set for an error.
Definition: stateCodes.hpp:37
@ ERROR
The application has encountered an error, from which it is recovering (with or without intervention)
Definition: stateCodes.hpp:38
@ READY
The device is ready for operation, but is not operating.
Definition: stateCodes.hpp:51
@ CONNECTED
The application has connected to the device or service.
Definition: stateCodes.hpp:45
@ NOTCONNECTED
The application is not connected to the device or service.
Definition: stateCodes.hpp:44
@ POWERON
The device power is on.
Definition: stateCodes.hpp:43
GeneratorWrapper< T > value(T &&value)
Definition: catch.hpp:4001
std::ostream & cerr()
std::stringstream msg
Definition: dm.hpp:24
constexpr static logPrioT LOG_CRITICAL
The process can not continue and will shut down (fatal)
Definition: logPriority.hpp:37
constexpr static logPrioT LOG_INFO
Informational. The info log level is the lowest level recorded during normal operations.
Definition: logPriority.hpp:49
#define PL_ERR_LIBRARY_NOT_INITIALIZED
Definition: pvcamCtrl.hpp:29
std::string pvcamErrMessage(const std::string &func, int pec, const std::string &more)
Format an error message using pvcam facilities.
Definition: pvcamCtrl.hpp:36
#define log_pvcam_software_error(func, more)
Helper for logging an error from pvcam.
Definition: pvcamCtrl.hpp:51
A device which saves telemetry.
Definition: telemeter.hpp:52
int appShutdown()
Perform telemeter application shutdown.
Definition: telemeter.hpp:259
int loadConfig(appConfigurator &config)
Load the device section from an application configurator.
Definition: telemeter.hpp:208
int appLogic()
Perform telemeter application logic.
Definition: telemeter.hpp:253
int setupConfig(appConfigurator &config)
Setup an application configurator for the device section.
Definition: telemeter.hpp:195
int appStartup()
Starts the telemetry log thread.
Definition: telemeter.hpp:226
int checkRecordTimes(const telT &tel, telTs... tels)
Check the time of the last record for each telemetry type and make an entry if needed.
Definition: telemeter.hpp:266
Software CRITICAL log entry.
Software ERR log entry.
Log entry recording framegrabber timings.
Log entry recording stdcam stage specific status.