API
stdCamera.hpp
Go to the documentation of this file.
1 /** \file stdCamera.hpp
2  * \brief Standard camera interface
3  *
4  * \author Jared R. Males (jaredmales@gmail.com)
5  *
6  * \ingroup app_files
7  */
8 
9 #ifndef stdCamera_hpp
10 #define stdCamera_hpp
11 
12 #include <string>
13 #include <unordered_map>
14 
15 #include <mx/app/application.hpp>
16 
17 #include "../MagAOXApp.hpp"
18 
19 namespace MagAOX
20 {
21 namespace app
22 {
23 namespace dev
24 {
25 
26 #define CAMCTRL_E_NOCONFIGS (-10)
27 
28 /// A camera configuration
29 /** a.k.a. a mode
30  */
31 struct cameraConfig
32 {
33  std::string m_configFile; ///< The file to use for this mode, e.g. an EDT configuration file.
34  std::string m_serialCommand; ///< The command to send to the camera to place it in this mode.
35  unsigned m_centerX {0};
36  unsigned m_centerY {0};
37  unsigned m_sizeX {0};
38  unsigned m_sizeY {0};
39  unsigned m_binningX {0};
40  unsigned m_binningY {0};
41 
42  unsigned m_digitalBinX {0};
43  unsigned m_digitalBinY {0};
44 
45  float m_maxFPS {0};
46 };
47 
48 typedef std::unordered_map<std::string, cameraConfig> cameraConfigMap;
49 
50 ///Load the camera configurations contained in the app configuration into a map
51 int loadCameraConfig( cameraConfigMap & ccmap, ///< [out] the map in which to place the configurations found in config
52  mx::app::appConfigurator & config ///< [in] the application configuration structure
53  );
54 
55 /// MagAO-X standard camera interface
56 /** Implements the standard interface to a MagAO-X camera. The derived class `derivedT` must
57  * meet the following requirements:
58  *
59  * - The derived class `derivedT` must be a `MagAOXApp<true>`
60  *
61  * - Must declare this class a friend like so:
62  * \code
63  * friend class dev::stdCamera<DERIVEDNAME>; //replace DERIVEDNAME with derivedT class name
64  * \endcode
65  *
66  * - Must declare the following typedef:
67  * \code
68  * typedef dev::stdCamera<DERIVEDNAME> stdCameraT; //replace DERIVEDNAME with derivedT class name
69  * \endcode
70  *
71  * - Must declare a series of `static constexpr` flags to manage static compile-time configuration. Each of these
72  * flags must be defined in derivedT to be either true or false.
73  *
74  * - Temperature Control and Status:
75  *
76  * - A static configuration variable must be defined in derivedT as
77  * \code
78  * static constexpr bool c_stdCamera_tempControl = true; //or: false
79  * \endcode
80  * which determines whether or not temperature controls are exposed.
81  *
82  * - If `(c_stdCamera_tempControl == true)` then the derived class must implement the following interfaces
83  * \code
84  * int setTempControl(); // set temp control status according to m_tempControlStatusSet
85  * int setTempSetPt(); // set the temperature set point accordin to m_ccdTempSetpt
86  * \endcode
87  *
88  * - A static configuration variable must be defined in derivedT as
89  * \code
90  * static constexpr bool c_stdCamera_temp = true; //or: false
91  * \endcode
92  * which determines whether or not temperature reporting is exposed. Note that if
93  * `(c_stdCamera_tempControl == true)`, then the behavior is as if `c_stdCamera_temp == true`,
94  * but thus constexpr must still be defined.
95  *
96  * - If either `(c_stdCamera_tempControl == true)` or `c_stdCamera_temp == true` then the INDI property "temp_ccd"
97  * will be updated from the value of \ref m_ccdTemp.
98  *
99  * - Readout Speed:
100  *
101  * - A static configuration variable must be defined in derivedT as
102  * \code
103  * static constexpr bool c_stdCamera_readoutSpeed = true; //or: false
104  * \endcode
105  * which determines whether or not readout speed controls are exposed. If true, then the implementation should populate
106  * \ref m_readoutSpeedNames and \ref m_readoutSpeedNameLabels (vectors of strings) on construction to the allowed values. This
107  * facility is normally used to control both amplifier and readout/adc speed with names like "ccd_1MHz" and "emccd_17MHz".
108  *
109  * - If used (and true) then the following interface must be implemented:
110  * \code
111  * int setReadoutSpeed(); // configures camera using m_readoutSpeedNameSet
112  * \endcode
113  * This configures the camera according to \ref m_readoutSpeedNameSet.
114  * The implementation must also manage \ref m_readoutSpeedName, keeping it up to date with the current setting.
115  *
116  * - If true, the configuration setting "camera.defaultReadoutSpeed"
117  * is also exposed, and \ref m_defaultReadoutSpeed will be set according to it. The implementation can
118  * set a sensible default on construction.
119  *
120  * - Vertical Shift Speed:
121  *
122  * - A static configuration variable must be defined in derivedT as
123  * \code
124  * static constexpr bool c_stdCamera_vShiftSpeed = true; //or: false
125  * \endcode
126  * which determines whether or not vertical shift speed controls are exposed.
127  *
128  * - If true, then the implementation should populate \ref m_vShiftSpeedNames and \ref m_vShiftSpeedLabels
129  * (vectors of strings) on construction to the allowed values. This
130  * facility is normally used with names like "0_3us" and "1_3us".
131  *
132  * - If true then the following interface must be defined:
133  * \code
134  * int setVShiftSpeed(); // configures camera according to m_vShiftSpeedNameSet
135  * \endcode
136  * function must be defined which sets the camera according to \ref m_vShiftSpeedNameSet.
137  * The implementation must also manage m_vShiftSpeedName, keeping it up to date.
138  *
139  * - The configuration setting "camera.defaultVShiftSpeed"
140  * is also exposed, and \ref m_defaultVShiftSpeed will be set accordingly. derivedT can set a sensible default
141  * on constuction.
142  *
143  * - Exposure Time:
144  * - A static configuration variable must be defined in derivedT as
145  * \code
146  * static constexpr bool c_stdCamera_exptimeCtrl = true; //or: false
147  * \endcode
148  * - If true, the following interface must be implemented:
149  * \code
150  * int setExpTime(); // set camera exposure time according to m_expTimeSet.
151  * \endcode
152  * to configure the camera according to \ref m_expTimeSet. derivedT must also keep \ref m_expTime up to date.
153  *
154  * - Frames per Second (FPS) Control and Status:
155  * - A static configuration variable must be defined in derivedT as
156  * \code
157  * static constexpr bool c_stdCamera_fpsCtrl = true; //or: false
158  * \endcode
159  *
160  * - If that is set to true the derivedT must implement
161  * \code
162  * int setFPS(); // set camera FS according to m_fps
163  * \endcode
164  * to configure the camera according to \ref m_fpsSet.
165  *
166  * - A static configuration variable must be defined in derivedT as
167  * \code
168  * static constexpr bool c_stdCamera_fps = true; //or: false
169  * \endcode
170  * Note that the value of c_stdCamera_fps does not matter if c_stdCamera_fpsCtrl == true.
171  *
172  * - If either `c_stdCamera_fpsCtrl == true` or `c_stdCamera_fps == true` then derivedT must also
173  * keep \ref m_fps up to date.
174  *
175  * - Synchro Control:
176  *
177  * - A static configuration variable must be defined in derivedT as
178  * \code
179  * static constexpr bool c_stdCamera_synchro = true; //or: false
180  * \endcode
181  * - If that is set to true the derivedT must implement
182  * \code
183  * int setSynchro(); // configure the camera based m_synchroSet.
184  * \endcode
185  * to configure the camera based on \ref m_synchroSet. The implementation should also keep
186  * \ref m_synchro up to date.
187  *
188  * - EM Gain:
189  * - A static configuration variable must be defined in derivedT as
190  * \code
191  * static constexpr bool c_stdCamera_emGain = true; //or: false
192  * \endcode
193  * which determines whether or not EM gain controls are exposed.
194  *
195  * - If the camera uses EM Gain, then a function
196  * \code
197  * int setEMGain(); // set EM gain based on m_emGainSet.
198  * \endcode
199  * must be defined which sets the camera EM Gain to \ref m_emGainSet.
200  *
201  * - If true the implementation must keep \ref m_emGain up to date.
202  *
203  * - If true the value of \ref m_maxEMGain should be set by the implementation and managed
204  * as needed. Additionally the configuration setting "camera.maxEMGain" is exposed.
205  *
206  * - Camera Modes:
207  *
208  * - A static configuration variable must be defined in derivedT as
209  * \code
210  * static constexpr bool c_stdCamera_usesModes= true; //or: false
211  * \endcode
212  *
213  * - If true, then modes are read from the configuration file. See \ref loadCameraConfig()
214  *
215  * - If true, then the configuration setting "camera.startupMode" is exposed, which sets the mode at startup by its name.
216  *
217  * - Regions of Interest
218  *
219  * - A static configuration variable must be defined in derivedT as
220  * \code
221  * static constexpr bool c_stdCamera_usesROI = true; //or: false
222  * \endcode
223  *
224  * - The default values of m_currentROI should be set before calling stdCamera::appStartup().
225  *
226  * - The derived class must implement:
227  * \code
228  * int checkNextROI(); // verifies m_nextROI values and modifies to closest valid values if needed
229  * int setNextROI(); // sets the ROI to the new target values.
230  * \endcode
231  *
232  * - Crop Mode ROIs:
233  *
234  * - A static configuration variable must be defined in derivedT as
235  * \code
236  * static constexpr bool c_stdCamera_cropMode = true; //or: false
237  * \endcode
238  *
239  * - If true the derived class must implement
240  * \code
241  * int setCropMode(); // set crop mode according to m_cropModeSet
242  * \endcode
243  * which changes the crop mode according to \ref m_cropModeSet.
244  *
245  * - `derivedT` must also maintain the value of \ref m_cropMode.
246  *
247  * - Shutters:
248  *
249  * - A static configuration variable must be defined in derivedT as
250  * \code
251  * static constexpr bool c_stdCamera_hasShutter = true; //or: false
252  * \endcode
253  *
254  * - If true the following interface must be implemented:
255  * \code
256  * int setShutter(int); // shut the shutter if 0, open the shutter otherwise.
257  * \endcode
258  * which shuts the shutter if the argument is 0, opens it otherwise.
259  *
260  * - State:
261  *
262  * - A static configuration variable must be defined in derivedT as
263  * \code
264  * static constexpr bool c_stdCamera_usesStateString = true; //or: false
265  * \endcode
266  * which determines whether the class provides a state string for dark management.
267  *
268  * - If true, the following functions must be defined in derivedT:
269  * \code
270  * std::string stateString(); //String capturing the current state. Must not include "__T".
271  * bool stateStringValid(); //Whether or not the current state string is valid, i.e. not changing.
272  * \endcode
273  *
274  *
275  * - The derived class must implement:
276  * \code
277  * int powerOnDefaults(); // called on power-on after powerOnWaitElapsed has occurred.
278  * \endcode
279  *
280  * - Calls to this class's setupConfig(), loadConfig(), appStartup(), appLogic(), appShutdown()
281  * onPowerOff(), and whilePowerOff(), must be placed in the derived class's functions of the same name.
282  *
283  * \ingroup appdev
284  */
285 template<class derivedT>
287 {
288 protected:
289 
290  /** \name Configurable Parameters
291  * @{
292  */
293 
294  cameraConfigMap m_cameraModes; ///< Map holding the possible camera mode configurations
295 
296  std::string m_startupMode; ///< The camera mode to load during first init after a power-on.
297 
298  float m_startupTemp {-999}; ///< The temperature to set after a power-on. Set to <= -999 to not use [default].
299 
300  std::string m_defaultReadoutSpeed; ///< The default readout speed of the camera.
301  std::string m_defaultVShiftSpeed; ///< The default readout speed of the camera.
302 
303  ///@}
304 
305  /** \name Temperature Control Interface
306  * @{
307  */
308 
309  float m_minTemp {-60};
310  float m_maxTemp {30};
311  float m_stepTemp {0};
312 
313  float m_ccdTemp {-999}; ///< The current temperature, in C
314 
315  float m_ccdTempSetpt {-999}; ///< The desired temperature, in C
316 
317  bool m_tempControlStatus {false}; ///< Whether or not temperature control is active
318  bool m_tempControlStatusSet {false}; ///< Desired state of temperature control
319 
320  bool m_tempControlOnTarget {false}; ///< Whether or not the temperature control system is on its target temperature
321 
322  std::string m_tempControlStatusStr; ///< Camera specific description of temperature control status.
323 
324  pcf::IndiProperty m_indiP_temp;
325  pcf::IndiProperty m_indiP_tempcont;
326  pcf::IndiProperty m_indiP_tempstat;
327 
328  ///@}
329 
330  /** \name Readout Control
331  * @{
332  */
333 
334  std::vector<std::string> m_readoutSpeedNames;
335  std::vector<std::string> m_readoutSpeedNameLabels;
336 
337  std::string m_readoutSpeedName; ///< The current readout speed name
338  std::string m_readoutSpeedNameSet; ///< The user requested readout speed name, to be set by derived()
339 
340  std::vector<std::string> m_vShiftSpeedNames;
341  std::vector<std::string> m_vShiftSpeedNameLabels;
342 
343  std::string m_vShiftSpeedName; ///< The current vshift speed name
344  std::string m_vShiftSpeedNameSet; ///< The user requested vshift speed name, to be set by derived()
345 
346  float m_adcSpeed {0};
347  float m_vshiftSpeed {0};
348 
349  float m_emGain {1}; ///< The camera's current EM gain (if available).
350  float m_emGainSet {1}; ///< The camera's EM gain, as set by the user.
351  float m_maxEMGain {1}; ///< The configurable maximum EM gain. To be enforced in derivedT.
352 
353  pcf::IndiProperty m_indiP_readoutSpeed;
354  pcf::IndiProperty m_indiP_vShiftSpeed;
355 
356  pcf::IndiProperty m_indiP_emGain;
357 
358  ///@}
359 
360  /** \name Exposure Control
361  * @{
362  */
363  float m_minExpTime {0}; ///< The minimum exposure time, used for INDI attributes
364  float m_maxExpTime {std::numeric_limits<float>::max()}; ///< The maximum exposure time, used for INDI attributes
365  float m_stepExpTime {0}; ///< The maximum exposure time stepsize, used for INDI attributes
366 
367  float m_expTime {0}; ///< The current exposure time, in seconds.
368  float m_expTimeSet {0}; ///< The exposure time, in seconds, as set by user.
369 
370  float m_minFPS{0}; ///< The minimum FPS, used for INDI attributes
371  float m_maxFPS{std::numeric_limits<float>::max()}; ///< The maximum FPS, used for INDI attributes
372  float m_stepFPS{0}; ///< The FPS step size, used for INDI attributes
373 
374  float m_fps {0}; ///< The current FPS.
375  float m_fpsSet {0}; ///< The commanded fps, as set by user.
376 
377  pcf::IndiProperty m_indiP_exptime;
378 
379  pcf::IndiProperty m_indiP_fps;
380 
381  ///@}
382 
383  /** \name External Synchronization
384  * @{
385  */
386  bool m_synchroSet {false}; ///< Target status of m_synchro
387 
388  bool m_synchro {false}; ///< Status of synchronization, true is on, false is off.
389 
390  pcf::IndiProperty m_indiP_synchro;
391 
392  ///@}
393 
394  /** \name Modes
395  *
396  * @{
397  */
398  std::string m_modeName; ///< The current mode name
399 
400  std::string m_nextMode; ///< The mode to be set by the next reconfiguration
401 
402  pcf::IndiProperty m_indiP_mode; ///< Property used to report the current mode
403 
404  pcf::IndiProperty m_indiP_reconfig; ///< Request switch which forces the framegrabber to go through the reconfigure process.
405 
406  ///@}
407 
408  /** \name ROIs
409  * ROI controls are exposed if derivedT::c_stdCamera_usesROI==true
410  * @{
411  */
412  struct roi
413  {
414  float x {0};
415  float y {0};
416  int w {0};
417  int h {0};
418  int bin_x {0};
419  int bin_y {0};
420  };
421 
425 
426  float m_minROIx {0};
427  float m_maxROIx {1023};
428  float m_stepROIx {0};
429 
430  float m_minROIy {0};
431  float m_maxROIy {1023};
432  float m_stepROIy {0};
433 
434  int m_minROIWidth {1};
435  int m_maxROIWidth {1024};
436  int m_stepROIWidth {1};
437 
438  int m_minROIHeight {1};
439  int m_maxROIHeight {1024};
441 
445 
449 
450  float m_default_x {0}; ///< Power-on ROI center x coordinate.
451  float m_default_y {0}; ///< Power-on ROI center y coordinate.
452  int m_default_w {0}; ///< Power-on ROI width.
453  int m_default_h {0}; ///< Power-on ROI height.
454  int m_default_bin_x {1}; ///< Power-on ROI x binning.
455  int m_default_bin_y {1}; ///< Power-on ROI y binning.
456 
457  float m_full_x{0}; ///< The full ROI center x coordinate.
458  float m_full_y{0}; ///< The full ROI center y coordinate.
459  int m_full_w{0}; ///< The full ROI width.
460  int m_full_h{0}; ///< The full ROI height.
461  int m_full_bin_x{1}; ///< The x-binning in the full ROI.
462  int m_full_bin_y{1}; ///< The y-binning in the full ROI.
463 
464  float m_full_currbin_x{0}; ///< The current-binning full ROI center x coordinate.
465  float m_full_currbin_y{0}; ///< The current-binning full ROI center y coordinate.
466  int m_full_currbin_w{0}; ///< The current-binning full ROI width.
467  int m_full_currbin_h{0}; ///< The current-binning full ROI height.
468 
469  pcf::IndiProperty m_indiP_roi_x; ///< Property used to set the ROI x center coordinate
470  pcf::IndiProperty m_indiP_roi_y; ///< Property used to set the ROI x center coordinate
471  pcf::IndiProperty m_indiP_roi_w; ///< Property used to set the ROI width
472  pcf::IndiProperty m_indiP_roi_h; ///< Property used to set the ROI height
473  pcf::IndiProperty m_indiP_roi_bin_x; ///< Property used to set the ROI x binning
474  pcf::IndiProperty m_indiP_roi_bin_y; ///< Property used to set the ROI y binning
475 
476  pcf::IndiProperty m_indiP_fullROI; ///< Property used to preset the full ROI dimensions.
477 
478  pcf::IndiProperty m_indiP_roi_check; ///< Property used to trigger checking the target ROI
479 
480  pcf::IndiProperty m_indiP_roi_set; ///< Property used to trigger setting the ROI
481 
482  pcf::IndiProperty m_indiP_roi_full; ///< Property used to trigger setting the full ROI.
483  pcf::IndiProperty m_indiP_roi_fullbin; ///< Property used to trigger setting the full in current binning ROI.
484  pcf::IndiProperty m_indiP_roi_loadlast; ///< Property used to trigger loading the last ROI as the target.
485  pcf::IndiProperty m_indiP_roi_last; ///< Property used to trigger setting the last ROI.
486  pcf::IndiProperty m_indiP_roi_default; ///< Property used to trigger setting the default and startup ROI.
487 
488  ///@}
489 
490  /** \name Crop Mode
491  * Crop mode controls are exposed if derivedT::c_stdCamera_cropMode==true
492  * @{
493  */
494  bool m_cropMode {false}; ///< Status of crop mode ROIs, if enabled for this camera.
495  bool m_cropModeSet {false}; ///< Desired status of crop mode ROIs, if enabled for this camera.
496 
497  pcf::IndiProperty m_indiP_cropMode; ///< Property used to toggle crop mode on and off.
498  ///@}
499 
500  /** \name Shutter Control
501  * Shutter controls are exposed if derivedT::c_stdCamera_hasShutter == true.
502  * @{
503  */
504  std::string m_shutterStatus {"UNKNOWN"};
505  int m_shutterState {-1}; /// State of the shutter. 0 = shut, 1 = open, -1 = unknown.
506 
507  pcf::IndiProperty m_indiP_shutterStatus; ///< Property to report shutter status
508  pcf::IndiProperty m_indiP_shutter; ///< Property used to control the shutter, a switch.
509 
510  ///@}
511 
512  /** \name State String
513  * The State string is exposed if derivedT::c_stdCamera_usesStateString is true.
514  * @{
515  */
516  pcf::IndiProperty m_indiP_stateString;
517  ///@}
518 
519 public:
520 
521  ///Destructor.
522  ~stdCamera() noexcept;
523 
524  /// Setup the configuration system
525  /**
526  * This should be called in `derivedT::setupConfig` as
527  * \code
528  stdCamera<derivedT>::setupConfig(config);
529  \endcode
530  * with appropriate error checking.
531  */
532  void setupConfig(mx::app::appConfigurator & config /**< [out] the derived classes configurator*/);
533 
534  /// load the configuration system results
535  /**
536  * This should be called in `derivedT::loadConfig` as
537  * \code
538  stdCamera<derivedT>::loadConfig(config);
539  \endcode
540  * with appropriate error checking.
541  */
542  void loadConfig(mx::app::appConfigurator & config /**< [in] the derived classes configurator*/);
543 
544 protected:
545  //workers to create indi variables if needed
546  int createReadoutSpeed(const mx::meta::trueFalseT<true> & t);
547 
548  int createReadoutSpeed(const mx::meta::trueFalseT<false> & f);
549 
550  int createVShiftSpeed(const mx::meta::trueFalseT<true> & t);
551 
552  int createVShiftSpeed(const mx::meta::trueFalseT<false> & f);
553 
554 public:
555  /// Startup function
556  /**
557  * This should be called in `derivedT::appStartup` as
558  * \code
559  stdCamera<derivedT>::appStartup();
560  \endcode
561  * with appropriate error checking.
562  *
563  * You should set the default/startup values of m_currentROI as well as the min/max/step values for the ROI parameters
564  * before calling this function.
565  *
566  * \returns 0 on success
567  * \returns -1 on error, which is logged.
568  */
569  int appStartup();
570 
571  /// Application logic
572  /** Checks the stdCamera thread
573  *
574  * This should be called from the derived's appLogic() as in
575  * \code
576  stdCamera<derivedT>::appLogic();
577  \endcode
578  * with appropriate error checking.
579  *
580  * \returns 0 on success
581  * \returns -1 on error, which is logged.
582  */
583  int appLogic();
584 
585  /// Actions on power off
586  /**
587  * This should be called from the derived's onPowerOff() as in
588  * \code
589  stdCamera<derivedT>::onPowerOff();
590  \endcode
591  * with appropriate error checking.
592  *
593  * The INDI mutex should be locked before calling.
594  *
595  * \returns 0 on success
596  * \returns -1 on error, which is logged.
597  */
598  int onPowerOff();
599 
600  /// Actions while powered off
601  /**
602  * This should be called from the derived's whilePowerOff() as in
603  * \code
604  stdCamera<derivedT>::whilePowerOff();
605  \endcode
606  * with appropriate error checking.
607  *
608  * \returns 0 on success
609  * \returns -1 on error, which is logged.
610  */
612 
613  /// Application shutdown
614  /** Shuts down the stdCamera thread
615  *
616  * \code
617  stdCamera<derivedT>::appShutdown();
618  \endcode
619  * with appropriate error checking.
620  *
621  * \returns 0 on success
622  * \returns -1 on error, which is logged.
623  */
624  int appShutdown();
625 
626 protected:
627 
628 
629  /** \name INDI
630  *
631  *@{
632  */
633 public:
634 
635  /// The static callback function to be registered for stdCamera properties
636  /** Calls newCallback_stdCamera
637  *
638  * \returns 0 on success.
639  * \returns -1 on error.
640  */
641  static int st_newCallBack_stdCamera( void * app, ///< [in] a pointer to this, will be static_cast-ed to derivedT.
642  const pcf::IndiProperty &ipRecv ///< [in] the INDI property sent with the the new property request.
643  );
644 
645  /// The callback function for stdCamera properties
646  /** Dispatches to the relevant handler
647  *
648  * \returns 0 on success.
649  * \returns -1 on error.
650  */
651  int newCallBack_stdCamera( const pcf::IndiProperty &ipRecv /**< [in] the INDI property sent with the the new property request.*/);
652 
653  /// Interface to setTempSetPt when the derivedT has temperature control
654  /** Tag-dispatch resolution of c_stdCamera_tempControl==true will call this function.
655  * Calls derivedT::setTempSetPt.
656  */
657  int setTempSetPt( const mx::meta::trueFalseT<true> & t);
658 
659  /// Interface to setTempSetPt when the derivedT does not have temperature control
660  /** Tag-dispatch resolution of c_stdCamera_tempControl==false will call this function.
661  * Prevents requiring derivedT::setTempSetPt.
662  */
663  int setTempSetPt( const mx::meta::trueFalseT<false> & f);
664 
665  /// Callback to process a NEW CCD temp request
666  /**
667  * \returns 0 on success.
668  * \returns -1 on error.
669  */
670  int newCallBack_temp( const pcf::IndiProperty &ipRecv /**< [in] the INDI property sent with the the new property request.*/);
671 
672  /// Interface to setTempControl when the derivedT has temperature control
673  /** Tag-dispatch resolution of c_stdCamera_tempControl==true will call this function.
674  * Calls derivedT::setTempControl.
675  */
676  int setTempControl( const mx::meta::trueFalseT<true> & t);
677 
678  /// Interface to setTempControl when the derivedT does not have temperature control
679  /** Tag-dispatch resolution of c_stdCamera_tempControl==false will call this function.
680  * Prevents requiring derivedT::setTempControl.
681  */
682  int setTempControl( const mx::meta::trueFalseT<false> & f);
683 
684  /// Callback to process a NEW CCD temp control request
685  /**
686  * \returns 0 on success.
687  * \returns -1 on error.
688  */
689  int newCallBack_temp_controller( const pcf::IndiProperty &ipRecv /**< [in] the INDI property sent with the the new property request.*/);
690 
691  /// Interface to setReadoutSpeed when the derivedT has readout speed control
692  /** Tag-dispatch resolution of c_stdCamera_readoutSpeed==true will call this function.
693  * Calls derivedT::setReadoutSpeed.
694  */
695  int setReadoutSpeed( const mx::meta::trueFalseT<true> & t);
696 
697  /// Interface to setReadoutSpeed when the derivedT does not have readout speed control
698  /** Tag-dispatch resolution of c_stdCamera_readoutSpeed==false will call this function.
699  * Just returns 0.
700  */
701  int setReadoutSpeed( const mx::meta::trueFalseT<false> & f);
702 
703  /// Callback to process a NEW readout speed request
704  /**
705  * \returns 0 on success.
706  * \returns -1 on error.
707  */
708  int newCallBack_readoutSpeed( const pcf::IndiProperty &ipRecv /**< [in] the INDI property sent with the the new property request.*/);
709 
710  /// Interface to setVShiftSpeed when the derivedT has vshift speed control
711  /** Tag-dispatch resolution of c_stdCamera_vShiftSpeed==true will call this function.
712  * Calls derivedT::setVShiftSpeed.
713  */
714  int setVShiftSpeed( const mx::meta::trueFalseT<true> & t);
715 
716  /// Interface to setVShiftSpeed when the derivedT does not have vshift speed control
717  /** Tag-dispatch resolution of c_stdCamera_vShiftSpeed==false will call this function.
718  * Just returns 0.
719  */
720  int setVShiftSpeed( const mx::meta::trueFalseT<false> & f);
721 
722  /// Callback to process a NEW vshift speed request
723  /**
724  * \returns 0 on success.
725  * \returns -1 on error.
726  */
727  int newCallBack_vShiftSpeed( const pcf::IndiProperty &ipRecv /**< [in] the INDI property sent with the the new property request.*/);
728 
729  /// Interface to setEMGain when the derivedT has EM Gain
730  /** Tag-dispatch resolution of c_stdCamera_emGain==true will call this function.
731  * Calls derivedT::setEMGain.
732  */
733  int setEMGain( const mx::meta::trueFalseT<true> & t);
734 
735  /// Interface to setEMGain when the derivedT does not have EM Gain
736  /** Tag-dispatch resolution of c_stdCamera_emGain==false will call this function.
737  * This prevents requiring derivedT to have its own setEMGain().
738  */
739  int setEMGain( const mx::meta::trueFalseT<false> & f);
740 
741  /// Callback to process a NEW EM gain request
742  /**
743  * \returns 0 on success.
744  * \returns -1 on error.
745  */
746  int newCallBack_emgain( const pcf::IndiProperty &ipRecv /**< [in] the INDI property sent with the the new property request.*/);
747 
748  /// Interface to setExpTime when the derivedT uses exposure time controls
749  /** Tag-dispatch resolution of c_stdCamera_exptimeCtrl==true will call this function.
750  * Calls derivedT::setExpTime.
751  */
752  int setExpTime( const mx::meta::trueFalseT<true> & t );
753 
754  /// Interface to setExptime when the derivedT does not use exposure time controls.
755  /** Tag-dispatch resolution of c_stdCamera_exptimeCtrl==false will call this function.
756  * This prevents requiring derivedT to have its own setExpTime().
757  */
758  int setExpTime( const mx::meta::trueFalseT<false> & f );
759 
760  /// Callback to process a NEW exposure time request
761  /**
762  * \returns 0 on success.
763  * \returns -1 on error.
764  */
765  int newCallBack_exptime( const pcf::IndiProperty &ipRecv /**< [in] the INDI property sent with the the new property request.*/);
766 
767  /// Interface to setFPS when the derivedT uses FPS controls
768  /** Tag-dispatch resolution of c_stdCamera_fpsCtrl==true will call this function.
769  * Calls derivedT::setFPS.
770  */
771  int setFPS( const mx::meta::trueFalseT<true> & t );
772 
773  /// Interface to setFPS when the derivedT does not use FPS controls.
774  /** Tag-dispatch resolution of c_stdCamera_hasFPS==false will call this function.
775  * This prevents requiring derivedT to have its own setFPS().
776  */
777  int setFPS( const mx::meta::trueFalseT<false> & f );
778 
779  /// Callback to process a NEW fps request
780  /**
781  * \returns 0 on success.
782  * \returns -1 on error.
783  */
784  int newCallBack_fps( const pcf::IndiProperty &ipRecv /**< [in] the INDI property sent with the the new property request.*/);
785 
786  /// Interface to setSynchro when the derivedT has synchronization
787  /** Tag-dispatch resolution of c_stdCamera_synchro==true will call this function.
788  * Calls derivedT::setSynchro.
789  */
790  int setSynchro( const mx::meta::trueFalseT<true> & t );
791 
792  /// Interface to setSynchro when the derivedT does not have synchronization
793  /** Tag-dispatch resolution of c_stdCamera_ynchro==false will call this function.
794  * This prevents requiring derivedT to have its own setSynchro().
795  */
796  int setSynchro( const mx::meta::trueFalseT<false> & f );
797 
798  /// Callback to process a NEW synchro request
799  /**
800  * \returns 0 on success.
801  * \returns -1 on error.
802  */
803  int newCallBack_synchro( const pcf::IndiProperty &ipRecv /**< [in] the INDI property sent with the the new property request.*/);
804 
805  /// Callback to process a NEW mode request
806  /**
807  * \returns 0 on success.
808  * \returns -1 on error.
809  */
810  int newCallBack_mode( const pcf::IndiProperty &ipRecv /**< [in] the INDI property sent with the the new property request.*/);
811 
812  /// Callback to process a NEW reconfigure request
813  /**
814  * \returns 0 on success.
815  * \returns -1 on error.
816  */
817  int newCallBack_reconfigure( const pcf::IndiProperty &ipRecv /**< [in] the INDI property sent with the the new property request.*/);
818 
819  /// Interface to setCropMode when the derivedT has crop mode
820  /** Tag-dispatch resolution of c_stdCamera_cropMode==true will call this function.
821  * Calls derivedT::setCropMode.
822  */
823  int setCropMode( const mx::meta::trueFalseT<true> & t);
824 
825  /// Interface to setCropMode when the derivedT does not have crop mode
826  /** Tag-dispatch resolution of c_stdCamera_cropMode==false will call this function.
827  * This prevents requiring derivedT to have its own setCropMode().
828  */
829  int setCropMode( const mx::meta::trueFalseT<false> & f);
830 
831  /// Callback to process a NEW cropMode request
832  /**
833  * \returns 0 on success.
834  * \returns -1 on error.
835  */
836  int newCallBack_cropMode( const pcf::IndiProperty &ipRecv /**< [in] the INDI property sent with the the new property request.*/);
837 
838  /// Callback to process a NEW roi_x request
839  /**
840  * \returns 0 on success.
841  * \returns -1 on error.
842  */
843  int newCallBack_roi_x( const pcf::IndiProperty &ipRecv /**< [in] the INDI property sent with the the new property request.*/);
844 
845  /// Callback to process a NEW roi_y request
846  /**
847  * \returns 0 on success.
848  * \returns -1 on error.
849  */
850  int newCallBack_roi_y( const pcf::IndiProperty &ipRecv /**< [in] the INDI property sent with the the new property request.*/);
851 
852  /// Callback to process a NEW roi_w request
853  /**
854  * \returns 0 on success.
855  * \returns -1 on error.
856  */
857  int newCallBack_roi_w( const pcf::IndiProperty &ipRecv /**< [in] the INDI property sent with the the new property request.*/);
858 
859  /// Callback to process a NEW roi_h request
860  /**
861  * \returns 0 on success.
862  * \returns -1 on error.
863  */
864  int newCallBack_roi_h( const pcf::IndiProperty &ipRecv /**< [in] the INDI property sent with the the new property request.*/);
865 
866  /// Callback to process a NEW bin_x request
867  /**
868  * \returns 0 on success.
869  * \returns -1 on error.
870  */
871  int newCallBack_roi_bin_x( const pcf::IndiProperty &ipRecv /**< [in] the INDI property sent with the the new property request.*/);
872 
873  /// Callback to process a NEW bin_y request
874  /**
875  * \returns 0 on success.
876  * \returns -1 on error.
877  */
878  int newCallBack_roi_bin_y( const pcf::IndiProperty &ipRecv /**< [in] the INDI property sent with the the new property request.*/);
879 
880  /// Interface to checkNextROI when the derivedT uses ROIs
881  /** Tag-dispatch resolution of c_stdCamera_usesROI==true will call this function.
882  * Calls derivedT::checkNextROI.
883  */
884  int checkNextROI( const mx::meta::trueFalseT<true> & t);
885 
886  /// Interface to checkNextROI when the derivedT does not use ROIs.
887  /** Tag-dispatch resolution of c_stdCamera_usesROI==false will call this function.
888  * This prevents requiring derivedT to have its own checkNextROI().
889  */
890  int checkNextROI( const mx::meta::trueFalseT<false> & f);
891 
892  /// Callback to process a NEW roi_check request
893  /**
894  * \returns 0 on success.
895  * \returns -1 on error.
896  */
897  int newCallBack_roi_check( const pcf::IndiProperty &ipRecv /**< [in] the INDI property sent with the the new property request.*/);
898 
899  /// Interface to setNextROI when the derivedT uses ROIs
900  /** Tag-dispatch resolution of c_stdCamera_usesROI==true will call this function.
901  * Calls derivedT::setNextROI.
902  */
903  int setNextROI( const mx::meta::trueFalseT<true> & t);
904 
905  /// Interface to setNextROI when the derivedT does not use ROIs.
906  /** Tag-dispatch resolution of c_stdCamera_usesROI==false will call this function.
907  * This prevents requiring derivedT to have its own setNextROI().
908  */
909  int setNextROI( const mx::meta::trueFalseT<false> & f);
910 
911  /// Callback to process a NEW roi_set request
912  /**
913  * \returns 0 on success.
914  * \returns -1 on error.
915  */
916  int newCallBack_roi_set( const pcf::IndiProperty &ipRecv /**< [in] the INDI property sent with the the new property request.*/);
917 
918  /// Callback to process a NEW roi_full request
919  /**
920  * \returns 0 on success.
921  * \returns -1 on error.
922  */
923  int newCallBack_roi_full( const pcf::IndiProperty &ipRecv /**< [in] the INDI property sent with the the new property request.*/);
924 
925  /// Callback to process a NEW roi_fullbin request
926  /**
927  * \returns 0 on success.
928  * \returns -1 on error.
929  */
930  int newCallBack_roi_fullbin( const pcf::IndiProperty &ipRecv /**< [in] the INDI property sent with the the new property request.*/);
931 
932  /// Callback to process a NEW roi_loadlast request
933  /**
934  * \returns 0 on success.
935  * \returns -1 on error.
936  */
937  int newCallBack_roi_loadlast( const pcf::IndiProperty &ipRecv /**< [in] the INDI property sent with the the new property request.*/);
938 
939  /// Callback to process a NEW roi_last request
940  /**
941  * \returns 0 on success.
942  * \returns -1 on error.
943  */
944  int newCallBack_roi_last( const pcf::IndiProperty &ipRecv /**< [in] the INDI property sent with the the new property request.*/);
945 
946  /// Callback to process a NEW roi_default request
947  /**
948  * \returns 0 on success.
949  * \returns -1 on error.
950  */
951  int newCallBack_roi_default( const pcf::IndiProperty &ipRecv /**< [in] the INDI property sent with the the new property request.*/);
952 
953  /// Interface to setShutter when the derivedT has a shutter
954  /** Tag-dispatch resolution of c_stdCamera_hasShutter==true will call this function.
955  * Calls derivedT::setShutter.
956  */
957  int setShutter( int ss,
958  const mx::meta::trueFalseT<true> & t
959  );
960 
961  /// Interface to setShutter when the derivedT does not have a shutter.
962  /** Tag-dispatch resolution of c_stdCamera_hasShutter==false will call this function.
963  * This prevents requiring derivedT to have its own setShutter().
964  */
965  int setShutter( int ss,
966  const mx::meta::trueFalseT<false> & f
967  );
968 
969  /// Callback to process a NEW shutter request
970  /**
971  * \returns 0 on success.
972  * \returns -1 on error.
973  */
974  int newCallBack_shutter( const pcf::IndiProperty &ipRecv /**< [in] the INDI property sent with the the new property request.*/);
975 
976  /// Interface to stateString when the derivedT provides it
977  /** Tag-dispatch resolution of c_stdCamera_usesStateString==true will call this function.
978  * Calls derivedT::stateString.
979  */
980  std::string stateString( const mx::meta::trueFalseT<true> & t);
981 
982  /// Interface to stateString when the derivedT does not provide it
983  /** Tag-dispatch resolution of c_stdCamera_usesStateString==false will call this function.
984  * returns "".
985  */
986  std::string stateString( const mx::meta::trueFalseT<false> & f);
987 
988  /// Interface to stateStringValid when the derivedT provides it
989  /** Tag-dispatch resolution of c_stdCamera_usesStateString==true will call this function.
990  * Calls derivedT::stateStringValid.
991  */
992  bool stateStringValid( const mx::meta::trueFalseT<true> & t);
993 
994  /// Interface to stateStringValid when the derivedT does not provide it
995  /** Tag-dispatch resolution of c_stdCamera_usesStateString==false will call this function.
996  * returns false.
997  */
998  bool stateStringValid( const mx::meta::trueFalseT<false> & f);
999 
1000  /// Update the INDI properties for this device controller
1001  /** You should call this once per main loop.
1002  * It is not called automatically.
1003  *
1004  * \returns 0 on success.
1005  * \returns -1 on error.
1006  */
1007  int updateINDI();
1008 
1009  ///@}
1010 
1011  /** \name Telemeter Interface
1012  * @{
1013  */
1014 
1015  int recordCamera( bool force = false );
1016 
1017  ///@}
1018 
1019 private:
1020  derivedT & derived()
1021  {
1022  return *static_cast<derivedT *>(this);
1023  }
1024 };
1025 
1026 template<class derivedT>
1028 {
1029  return;
1030 }
1031 
1032 
1033 
1034 template<class derivedT>
1035 void stdCamera<derivedT>::setupConfig(mx::app::appConfigurator & config)
1036 {
1037  if(derivedT::c_stdCamera_tempControl)
1038  {
1039  config.add("camera.startupTemp", "", "camera.startupTemp", argType::Required, "camera", "startupTemp", false, "float", "The temperature setpoint to set after a power-on [C]. Default is 20 C.");
1040  }
1041 
1042  if(derivedT::c_stdCamera_readoutSpeed)
1043  {
1044  config.add("camera.defaultReadoutSpeed", "", "camera.defaultReadoutSpeed", argType::Required, "camera", "defaultReadoutSpeed", false, "string", "The default amplifier and readout speed.");
1045  }
1046 
1047  if(derivedT::c_stdCamera_vShiftSpeed)
1048  {
1049  config.add("camera.defaultVShiftSpeed", "", "camera.defaultVShiftSpeed", argType::Required, "camera", "defaultVShiftSpeed", false, "string", "The default vertical shift speed.");
1050  }
1051 
1052  if(derivedT::c_stdCamera_emGain)
1053  {
1054  config.add("camera.maxEMGain", "", "camera.maxEMGain", argType::Required, "camera", "maxEMGain", false, "unsigned", "The maximum EM gain which can be set by the user.");
1055  }
1056 
1057  if(derivedT::c_stdCamera_usesModes)
1058  {
1059  config.add("camera.startupMode", "", "camera.startupMode", argType::Required, "camera", "startupMode", false, "string", "The mode to set upon power on or application startup.");
1060  }
1061 
1062  if(derivedT::c_stdCamera_usesROI)
1063  {
1064  config.add("camera.default_x", "", "camera.default_x", argType::Required, "camera", "default_x", false, "float", "The default ROI x position.");
1065  config.add("camera.default_y", "", "camera.default_y", argType::Required, "camera", "default_y", false, "float", "The default ROI y position.");
1066  config.add("camera.default_w", "", "camera.default_w", argType::Required, "camera", "default_w", false, "int", "The default ROI width.");
1067  config.add("camera.default_h", "", "camera.default_h", argType::Required, "camera", "default_h", false, "int", "The default ROI height.");
1068  config.add("camera.default_bin_x", "", "camera.default_bin_x", argType::Required, "camera", "default_bin_x", false, "int", "The default ROI x binning.");
1069  config.add("camera.default_bin_y", "", "camera.default_bin_y", argType::Required, "camera", "default_bin_y", false, "int", "The default ROI y binning.");
1070  }
1071 }
1072 
1073 template<class derivedT>
1074 void stdCamera<derivedT>::loadConfig(mx::app::appConfigurator & config)
1075 {
1076  if(derivedT::c_stdCamera_tempControl)
1077  {
1078  config(m_startupTemp, "camera.startupTemp");
1079  }
1080 
1081  if(derivedT::c_stdCamera_readoutSpeed)
1082  {
1083  config(m_defaultReadoutSpeed, "camera.defaultReadoutSpeed");
1084  }
1085 
1086  if(derivedT::c_stdCamera_vShiftSpeed)
1087  {
1088  config(m_defaultVShiftSpeed, "camera.defaultVShiftSpeed");
1089  }
1090 
1091  if(derivedT::c_stdCamera_emGain)
1092  {
1093  config(m_maxEMGain, "camera.maxEMGain");
1094  }
1095 
1096  if(derivedT::c_stdCamera_usesModes)
1097  {
1098  int rv = loadCameraConfig(m_cameraModes, config);
1099 
1100  if(rv < 0)
1101  {
1102  if(rv == CAMCTRL_E_NOCONFIGS)
1103  {
1104  derivedT::template log<text_log>("No camera configurations found.", logPrio::LOG_CRITICAL);
1105  }
1106  }
1107 
1108  config(m_startupMode, "camera.startupMode");
1109 
1110  }
1111 
1112  if(derivedT::c_stdCamera_usesROI)
1113  {
1114  config(m_default_x, "camera.default_x");
1115  config(m_default_y, "camera.default_y");
1116  config(m_default_w, "camera.default_w");
1117  config(m_default_h, "camera.default_h");
1118  config(m_default_bin_x, "camera.default_bin_x");
1119  config(m_default_bin_y, "camera.default_bin_y");
1120  }
1121 }
1122 
1123 template<class derivedT>
1124 int stdCamera<derivedT>::createReadoutSpeed(const mx::meta::trueFalseT<true> & t)
1125 {
1126  static_cast<void>(t);
1127 
1128  derived().createStandardIndiSelectionSw(m_indiP_readoutSpeed, "readout_speed", m_readoutSpeedNames, "Readout Speed");
1129 
1130  //Set the labes if provided
1131  if(m_readoutSpeedNameLabels.size() == m_readoutSpeedNames.size())
1132  {
1133  for(size_t n=0; n< m_readoutSpeedNames.size(); ++n) m_indiP_readoutSpeed[m_readoutSpeedNames[n]].setLabel(m_readoutSpeedNameLabels[n]);
1134  }
1135 
1136  derived().registerIndiPropertyNew(m_indiP_readoutSpeed, st_newCallBack_stdCamera);
1137 
1138  return 0;
1139 }
1140 
1141 template<class derivedT>
1142 int stdCamera<derivedT>::createReadoutSpeed(const mx::meta::trueFalseT<0> & f)
1143 {
1144  static_cast<void>(f);
1145 
1146  return 0;
1147 }
1148 
1149 template<class derivedT>
1150 int stdCamera<derivedT>::createVShiftSpeed(const mx::meta::trueFalseT<true> & t)
1151 {
1152  static_cast<void>(t);
1153 
1154  derived().createStandardIndiSelectionSw(m_indiP_vShiftSpeed, "vshift_speed", m_vShiftSpeedNames, "Vert. Shift Speed");
1155 
1156  if(m_vShiftSpeedNameLabels.size() == m_vShiftSpeedNames.size())
1157  {
1158  for(size_t n=0; n< m_vShiftSpeedNames.size(); ++n) m_indiP_vShiftSpeed[m_vShiftSpeedNames[n]].setLabel(m_vShiftSpeedNameLabels[n]);
1159  }
1160 
1161  derived().registerIndiPropertyNew(m_indiP_vShiftSpeed, st_newCallBack_stdCamera);
1162 
1163  return 0;
1164 }
1165 
1166 template<class derivedT>
1167 int stdCamera<derivedT>::createVShiftSpeed(const mx::meta::trueFalseT<0> & f)
1168 {
1169  static_cast<void>(f);
1170 
1171  return 0;
1172 }
1173 
1174 template<class derivedT>
1176 {
1177 
1178  if(derivedT::c_stdCamera_tempControl)
1179  {
1180  //The min/max/step values should be set in derivedT before this is called.
1181  derived().createStandardIndiNumber( m_indiP_temp, "temp_ccd", m_minTemp, m_maxTemp, m_stepTemp, "%0.1f","CCD Temperature", "CCD Temperature");
1182  m_indiP_temp["current"].set(m_ccdTemp);
1183  m_indiP_temp["target"].set(m_ccdTempSetpt);
1184  if( derived().registerIndiPropertyNew( m_indiP_temp, st_newCallBack_stdCamera) < 0)
1185  {
1186  #ifndef STDCAMERA_TEST_NOLOG
1187  derivedT::template log<software_error>({__FILE__,__LINE__});
1188  #endif
1189  return -1;
1190  }
1191 
1192  derived().createStandardIndiToggleSw( m_indiP_tempcont, "temp_controller", "CCD Temperature", "Control On/Off");
1193  m_indiP_tempcont["toggle"].set(pcf::IndiElement::Off);
1194  if( derived().registerIndiPropertyNew( m_indiP_tempcont, st_newCallBack_stdCamera) < 0)
1195  {
1196  #ifndef STDCAMERA_TEST_NOLOG
1197  derivedT::template log<software_error>({__FILE__,__LINE__});
1198  #endif
1199  return -1;
1200  }
1201 
1202  derived().createROIndiText( m_indiP_tempstat, "temp_control", "status", "CCD Temperature", "", "CCD Temperature");
1203  if( derived().registerIndiPropertyReadOnly( m_indiP_tempstat ) < 0)
1204  {
1205  #ifndef STDCAMERA_TEST_NOLOG
1206  derivedT::template log<software_error>({__FILE__,__LINE__});
1207  #endif
1208  return -1;
1209  }
1210  }
1211  else if(derivedT::c_stdCamera_temp)
1212  {
1213  derived().createROIndiNumber( m_indiP_temp, "temp_ccd", "CCD Temperature", "CCD Temperature");
1214  m_indiP_temp.add(pcf::IndiElement("current"));
1215  m_indiP_temp["current"].set(m_ccdTemp);
1216  if( derived().registerIndiPropertyReadOnly( m_indiP_temp) < 0)
1217  {
1218  #ifndef STDCAMERA_TEST_NOLOG
1219  derivedT::template log<software_error>({__FILE__,__LINE__});
1220  #endif
1221  return -1;
1222  }
1223  }
1224 
1225  if(derivedT::c_stdCamera_readoutSpeed)
1226  {
1227  mx::meta::trueFalseT<derivedT::c_stdCamera_readoutSpeed> tf;
1228  if(createReadoutSpeed(tf) < 0)
1229  {
1230  #ifndef STDCAMERA_TEST_NOLOG
1231  derivedT::template log<software_error>({__FILE__,__LINE__});
1232  #endif
1233  return -1;
1234  }
1235 
1236  }
1237 
1238  if(derivedT::c_stdCamera_vShiftSpeed)
1239  {
1240  mx::meta::trueFalseT<derivedT::c_stdCamera_vShiftSpeed> tf;
1241  if(createVShiftSpeed(tf) < 0)
1242  {
1243  #ifndef STDCAMERA_TEST_NOLOG
1244  derivedT::template log<software_error>({__FILE__,__LINE__});
1245  #endif
1246  return -1;
1247  }
1248 
1249  }
1250 
1251  if(derivedT::c_stdCamera_emGain)
1252  {
1253  derived().createStandardIndiNumber( m_indiP_emGain, "emgain", 0, 1000, 1, "%0.3f");
1254  if( derived().registerIndiPropertyNew( m_indiP_emGain, st_newCallBack_stdCamera) < 0)
1255  {
1256  #ifndef STDCAMERA_TEST_NOLOG
1257  derivedT::template log<software_error>({__FILE__,__LINE__});
1258  #endif
1259  return -1;
1260  }
1261  }
1262 
1263  if(derivedT::c_stdCamera_exptimeCtrl)
1264  {
1265  derived().createStandardIndiNumber( m_indiP_exptime, "exptime", m_minExpTime, m_maxExpTime, m_stepExpTime, "%0.3f");
1266  if( derived().registerIndiPropertyNew( m_indiP_exptime, st_newCallBack_stdCamera) < 0)
1267  {
1268  #ifndef STDCAMERA_TEST_NOLOG
1269  derivedT::template log<software_error>({__FILE__,__LINE__});
1270  #endif
1271  return -1;
1272  }
1273  }
1274 
1275  if(derivedT::c_stdCamera_fpsCtrl)
1276  {
1277  derived().createStandardIndiNumber( m_indiP_fps, "fps", m_minFPS, m_maxFPS, m_stepFPS, "%0.2f");
1278  if( derived().registerIndiPropertyNew( m_indiP_fps, st_newCallBack_stdCamera) < 0)
1279  {
1280  #ifndef STDCAMERA_TEST_NOLOG
1281  derivedT::template log<software_error>({__FILE__,__LINE__});
1282  #endif
1283  return -1;
1284  }
1285  }
1286  else if(derivedT::c_stdCamera_fps)
1287  {
1288  derived().createROIndiNumber( m_indiP_fps, "fps");
1289  m_indiP_fps.add(pcf::IndiElement("current"));
1290  m_indiP_fps["current"].setMin(m_minFPS);
1291  m_indiP_fps["current"].setMax(m_maxFPS);
1292  m_indiP_fps["current"].setStep(m_stepFPS);
1293  m_indiP_fps["current"].setFormat("%0.2f");
1294 
1295  if( derived().registerIndiPropertyReadOnly( m_indiP_fps ) < 0)
1296  {
1297  #ifndef STDCAMERA_TEST_NOLOG
1298  derivedT::template log<software_error>({__FILE__,__LINE__});
1299  #endif
1300  return -1;
1301  }
1302  }
1303 
1304  if(derivedT::c_stdCamera_synchro)
1305  {
1306  derived().createStandardIndiToggleSw( m_indiP_synchro, "synchro", "Synchronization", "Synchronization");
1307  if( derived().registerIndiPropertyNew( m_indiP_synchro, st_newCallBack_stdCamera) < 0)
1308  {
1309  #ifndef STDCAMERA_TEST_NOLOG
1310  derivedT::template log<software_error>({__FILE__,__LINE__});
1311  #endif
1312  return -1;
1313  }
1314  }
1315 
1316  if(derivedT::c_stdCamera_usesModes)
1317  {
1318  std::vector<std::string> modeNames;
1319  for(auto it = m_cameraModes.begin(); it!=m_cameraModes.end(); ++it)
1320  {
1321  modeNames.push_back(it->first);
1322  }
1323 
1324  if(derived().createStandardIndiSelectionSw( m_indiP_mode, "mode", modeNames) < 0)
1325  {
1326  derivedT::template log<software_critical>({__FILE__, __LINE__});
1327  return -1;
1328  }
1329  if( derived().registerIndiPropertyNew( m_indiP_mode, st_newCallBack_stdCamera) < 0)
1330  {
1331  #ifndef STDCAMERA_TEST_NOLOG
1332  derivedT::template log<software_error>({__FILE__,__LINE__});
1333  #endif
1334  return -1;
1335  }
1336  }
1337 
1338  derived().createStandardIndiRequestSw( m_indiP_reconfig, "reconfigure");
1339  if( derived().registerIndiPropertyNew( m_indiP_reconfig, st_newCallBack_stdCamera) < 0)
1340  {
1341  #ifndef STDCAMERA_TEST_NOLOG
1342  derivedT::template log<software_error>({__FILE__,__LINE__});
1343  #endif
1344  return -1;
1345  }
1346 
1347  if(derivedT::c_stdCamera_usesROI)
1348  {
1349  //The min/max/step values should be set in derivedT before this is called.
1350  derived().createStandardIndiNumber( m_indiP_roi_x, "roi_region_x", m_minROIx, m_maxROIx, m_stepROIx, "%0.1f");
1351  if( derived().registerIndiPropertyNew( m_indiP_roi_x, st_newCallBack_stdCamera) < 0)
1352  {
1353  #ifndef STDCAMERA_TEST_NOLOG
1354  derivedT::template log<software_error>({__FILE__,__LINE__});
1355  #endif
1356  return -1;
1357  }
1358 
1359  derived().createStandardIndiNumber( m_indiP_roi_y, "roi_region_y", m_minROIy, m_maxROIy, m_stepROIy, "%0.1f");
1360  if( derived().registerIndiPropertyNew( m_indiP_roi_y, st_newCallBack_stdCamera) < 0)
1361  {
1362  #ifndef STDCAMERA_TEST_NOLOG
1363  derivedT::template log<software_error>({__FILE__,__LINE__});
1364  #endif
1365  return -1;
1366  }
1367 
1368  derived().createStandardIndiNumber( m_indiP_roi_w, "roi_region_w", m_minROIWidth, m_maxROIWidth, m_stepROIWidth, "%d");
1369  if( derived().registerIndiPropertyNew( m_indiP_roi_w, st_newCallBack_stdCamera) < 0)
1370  {
1371  #ifndef STDCAMERA_TEST_NOLOG
1372  derivedT::template log<software_error>({__FILE__,__LINE__});
1373  #endif
1374  return -1;
1375  }
1376 
1377  derived().createStandardIndiNumber( m_indiP_roi_h, "roi_region_h", m_minROIHeight, m_maxROIHeight, m_stepROIHeight, "%d");
1378  if( derived().registerIndiPropertyNew( m_indiP_roi_h, st_newCallBack_stdCamera) < 0)
1379  {
1380  #ifndef STDCAMERA_TEST_NOLOG
1381  derivedT::template log<software_error>({__FILE__,__LINE__});
1382  #endif
1383  return -1;
1384  }
1385 
1386  derived().createStandardIndiNumber( m_indiP_roi_bin_x, "roi_region_bin_x", m_minROIBinning_x, m_maxROIBinning_x, m_stepROIBinning_x, "%f");
1387  if( derived().registerIndiPropertyNew( m_indiP_roi_bin_x, st_newCallBack_stdCamera) < 0)
1388  {
1389  #ifndef STDCAMERA_TEST_NOLOG
1390  derivedT::template log<software_error>({__FILE__,__LINE__});
1391  #endif
1392  return -1;
1393  }
1394 
1395  derived().createStandardIndiNumber( m_indiP_roi_bin_y, "roi_region_bin_y", m_minROIBinning_y, m_maxROIBinning_y, m_stepROIBinning_y, "%f");
1396  if( derived().registerIndiPropertyNew( m_indiP_roi_bin_y, st_newCallBack_stdCamera) < 0)
1397  {
1398  #ifndef STDCAMERA_TEST_NOLOG
1399  derivedT::template log<software_error>({__FILE__,__LINE__});
1400  #endif
1401  return -1;
1402  }
1403 
1404  derived().createROIndiNumber( m_indiP_fullROI, "roi_full_region");
1405  m_indiP_fullROI.add(pcf::IndiElement("x"));
1406  m_indiP_fullROI["x"] = 0;
1407  m_indiP_fullROI.add(pcf::IndiElement("y"));
1408  m_indiP_fullROI["y"] = 0;
1409  m_indiP_fullROI.add(pcf::IndiElement("w"));
1410  m_indiP_fullROI["w"] = 0;
1411  m_indiP_fullROI.add(pcf::IndiElement("h"));
1412  m_indiP_fullROI["h"] = 0;
1413  if( derived().registerIndiPropertyReadOnly( m_indiP_fullROI ) < 0)
1414  {
1415  #ifndef STDCAMERA_TEST_NOLOG
1416  derivedT::template log<software_error>({__FILE__,__LINE__});
1417  #endif
1418  return -1;
1419  }
1420 
1421  derived().createStandardIndiRequestSw( m_indiP_roi_check, "roi_region_check");
1422  if( derived().registerIndiPropertyNew( m_indiP_roi_check, st_newCallBack_stdCamera) < 0)
1423  {
1424  #ifndef STDCAMERA_TEST_NOLOG
1425  derivedT::template log<software_error>({__FILE__,__LINE__});
1426  #endif
1427  return -1;
1428  }
1429 
1430  derived().createStandardIndiRequestSw( m_indiP_roi_set, "roi_set");
1431  if( derived().registerIndiPropertyNew( m_indiP_roi_set, st_newCallBack_stdCamera) < 0)
1432  {
1433  #ifndef STDCAMERA_TEST_NOLOG
1434  derivedT::template log<software_error>({__FILE__,__LINE__});
1435  #endif
1436  return -1;
1437  }
1438 
1439  derived().createStandardIndiRequestSw( m_indiP_roi_full, "roi_set_full");
1440  if( derived().registerIndiPropertyNew( m_indiP_roi_full, st_newCallBack_stdCamera) < 0)
1441  {
1442  #ifndef STDCAMERA_TEST_NOLOG
1443  derivedT::template log<software_error>({__FILE__,__LINE__});
1444  #endif
1445  return -1;
1446  }
1447 
1448  derived().createStandardIndiRequestSw( m_indiP_roi_fullbin, "roi_set_full_bin");
1449  if( derived().registerIndiPropertyNew( m_indiP_roi_fullbin, st_newCallBack_stdCamera) < 0)
1450  {
1451  #ifndef STDCAMERA_TEST_NOLOG
1452  derivedT::template log<software_error>({__FILE__,__LINE__});
1453  #endif
1454  return -1;
1455  }
1456 
1457  derived().createStandardIndiRequestSw( m_indiP_roi_loadlast, "roi_load_last");
1458  if( derived().registerIndiPropertyNew( m_indiP_roi_loadlast, st_newCallBack_stdCamera) < 0)
1459  {
1460  #ifndef STDCAMERA_TEST_NOLOG
1461  derivedT::template log<software_error>({__FILE__,__LINE__});
1462  #endif
1463  return -1;
1464  }
1465 
1466  derived().createStandardIndiRequestSw( m_indiP_roi_last, "roi_set_last");
1467  if( derived().registerIndiPropertyNew( m_indiP_roi_last, st_newCallBack_stdCamera) < 0)
1468  {
1469  #ifndef STDCAMERA_TEST_NOLOG
1470  derivedT::template log<software_error>({__FILE__,__LINE__});
1471  #endif
1472  return -1;
1473  }
1474 
1475  derived().createStandardIndiRequestSw( m_indiP_roi_default, "roi_set_default");
1476  if( derived().registerIndiPropertyNew( m_indiP_roi_default, st_newCallBack_stdCamera) < 0)
1477  {
1478  #ifndef STDCAMERA_TEST_NOLOG
1479  derivedT::template log<software_error>({__FILE__,__LINE__});
1480  #endif
1481  return -1;
1482  }
1483  }
1484 
1485  if(derivedT::c_stdCamera_cropMode)
1486  {
1487  derived().createStandardIndiToggleSw( m_indiP_cropMode, "roi_crop_mode", "Crop Mode", "Crop Mode");
1488  if( derived().registerIndiPropertyNew( m_indiP_cropMode, st_newCallBack_stdCamera) < 0)
1489  {
1490  #ifndef STDCAMERA_TEST_NOLOG
1491  derivedT::template log<software_error>({__FILE__,__LINE__});
1492  #endif
1493  return -1;
1494  }
1495  }
1496 
1497  //Set up INDI for shutter
1498  if(derivedT::c_stdCamera_hasShutter)
1499  {
1500  derived().createROIndiText( m_indiP_shutterStatus, "shutter_status", "status", "Shutter Status", "Shutter", "Status");
1501  m_indiP_shutterStatus["status"] = m_shutterStatus;
1502  if( derived().registerIndiPropertyReadOnly( m_indiP_shutterStatus ) < 0)
1503  {
1504  #ifndef STDCAMERA_TEST_NOLOG
1505  derivedT::template log<software_error>({__FILE__,__LINE__});
1506  #endif
1507  return -1;
1508  }
1509 
1510  derived().createStandardIndiToggleSw( m_indiP_shutter, "shutter", "Shutter", "Shutter");
1511  if( derived().registerIndiPropertyNew( m_indiP_shutter, st_newCallBack_stdCamera) < 0)
1512  {
1513  #ifndef STDCAMERA_TEST_NOLOG
1514  derivedT::template log<software_error>({__FILE__,__LINE__});
1515  #endif
1516  return -1;
1517  }
1518 
1519  }
1520 
1521  if(derivedT::c_stdCamera_usesStateString)
1522  {
1523  derived().createROIndiText( m_indiP_stateString, "state_string", "current", "State String", "State", "String");
1524  m_indiP_stateString.add(pcf::IndiElement("valid"));
1525  m_indiP_stateString["valid"] = "no";
1526  if( derived().registerIndiPropertyReadOnly( m_indiP_stateString ) < 0)
1527  {
1528  #ifndef STDCAMERA_TEST_NOLOG
1529  derivedT::template log<software_error>({__FILE__,__LINE__});
1530  #endif
1531  return -1;
1532  }
1533  }
1534 
1535  return 0;
1536 }//int stdCamera<derivedT>::appStartup()
1537 
1538 template<class derivedT>
1540 {
1541  if( derived().state() == stateCodes::POWERON )
1542  {
1543  if(derived().powerOnWaitElapsed())
1544  {
1545  derived().state(stateCodes::NOTCONNECTED);
1546 
1547  //Set power-on defaults
1548  derived().powerOnDefaults();
1549 
1550  if(derivedT::c_stdCamera_tempControl)
1551  {
1552  //then set startupTemp if configured
1553  if(m_startupTemp > -999) m_ccdTempSetpt = m_startupTemp;
1554  derived().updateIfChanged(m_indiP_temp, "target", m_ccdTempSetpt, INDI_IDLE);
1555  }
1556 
1557  if(derivedT::c_stdCamera_usesROI)
1558  {
1559  //m_currentROI should be set to default/startup values in derivedT::powerOnDefaults
1560  m_nextROI.x = m_currentROI.x;
1561  m_nextROI.y = m_currentROI.y;
1562  m_nextROI.w = m_currentROI.w;
1563  m_nextROI.h = m_currentROI.h;
1564  m_nextROI.bin_x = m_currentROI.bin_x;
1565  m_nextROI.bin_y = m_currentROI.bin_y;
1566 
1567  derived().updateIfChanged(m_indiP_roi_x, "current", m_currentROI.x, INDI_IDLE);
1568  derived().updateIfChanged(m_indiP_roi_x, "target", m_nextROI.x, INDI_IDLE);
1569 
1570  derived().updateIfChanged(m_indiP_roi_y, "current", m_currentROI.y, INDI_IDLE);
1571  derived().updateIfChanged(m_indiP_roi_y, "target", m_nextROI.y, INDI_IDLE);
1572 
1573  derived().updateIfChanged(m_indiP_roi_w, "current", m_currentROI.w, INDI_IDLE);
1574  derived().updateIfChanged(m_indiP_roi_w, "target", m_nextROI.w, INDI_IDLE);
1575 
1576  derived().updateIfChanged(m_indiP_roi_h, "current", m_currentROI.h, INDI_IDLE);
1577  derived().updateIfChanged(m_indiP_roi_h, "target", m_nextROI.h, INDI_IDLE);
1578 
1579  derived().updateIfChanged(m_indiP_roi_bin_x, "current", m_currentROI.bin_x, INDI_IDLE);
1580  derived().updateIfChanged(m_indiP_roi_bin_x, "target", m_nextROI.bin_x, INDI_IDLE);
1581 
1582  derived().updateIfChanged(m_indiP_roi_bin_y, "current", m_currentROI.bin_y, INDI_IDLE);
1583  derived().updateIfChanged(m_indiP_roi_bin_y, "target", m_nextROI.bin_y, INDI_IDLE);
1584  }
1585 
1586  if(derivedT::c_stdCamera_hasShutter)
1587  {
1588  if(m_shutterStatus == "OPERATING")
1589  {
1590  derived().updateIfChanged(m_indiP_shutterStatus, "status", m_shutterStatus, INDI_BUSY);
1591  }
1592  if(m_shutterStatus == "POWERON" || m_shutterStatus == "READY")
1593  {
1594  derived().updateIfChanged(m_indiP_shutterStatus, "status", m_shutterStatus, INDI_OK);
1595  }
1596  else
1597  {
1598  derived().updateIfChanged(m_indiP_shutterStatus, "status", m_shutterStatus, INDI_IDLE);
1599  }
1600 
1601  if(m_shutterState == 1)
1602  {
1603  derived().updateSwitchIfChanged(m_indiP_shutter, "toggle", pcf::IndiElement::On, INDI_OK);
1604  }
1605  else
1606  {
1607  derived().updateSwitchIfChanged(m_indiP_shutter, "toggle", pcf::IndiElement::Off, INDI_IDLE);
1608  }
1609  }
1610 
1611  return 0;
1612  }
1613  else
1614  {
1615  return 0;
1616  }
1617  }
1618  else if( derived().state() == stateCodes::READY || derived().state() == stateCodes::OPERATING )
1619  {
1620  if(derivedT::c_stdCamera_usesROI)
1621  {
1622  derived().updateIfChanged(m_indiP_roi_x, "current", m_currentROI.x, INDI_IDLE);
1623  derived().updateIfChanged(m_indiP_roi_x, "target", m_nextROI.x, INDI_IDLE);
1624 
1625  derived().updateIfChanged(m_indiP_roi_y, "current", m_currentROI.y, INDI_IDLE);
1626  derived().updateIfChanged(m_indiP_roi_y, "target", m_nextROI.y, INDI_IDLE);
1627 
1628  derived().updateIfChanged(m_indiP_roi_w, "current", m_currentROI.w, INDI_IDLE);
1629  derived().updateIfChanged(m_indiP_roi_w, "target", m_nextROI.w, INDI_IDLE);
1630 
1631  derived().updateIfChanged(m_indiP_roi_h, "current", m_currentROI.h, INDI_IDLE);
1632  derived().updateIfChanged(m_indiP_roi_h, "target", m_nextROI.h, INDI_IDLE);
1633 
1634  derived().updateIfChanged(m_indiP_roi_bin_x, "current", m_currentROI.bin_x, INDI_IDLE);
1635  derived().updateIfChanged(m_indiP_roi_bin_x, "target", m_nextROI.bin_x, INDI_IDLE);
1636 
1637  derived().updateIfChanged(m_indiP_roi_bin_y, "current", m_currentROI.bin_y, INDI_IDLE);
1638  derived().updateIfChanged(m_indiP_roi_bin_y, "target", m_nextROI.bin_y, INDI_IDLE);
1639  }
1640  }
1641 
1642  return 0;
1643 
1644 }
1645 
1646 template<class derivedT>
1648 {
1649  if( !derived().m_indiDriver ) return 0;
1650 
1651  if(derivedT::c_stdCamera_usesModes)
1652  {
1653  for(auto it = m_cameraModes.begin();it!=m_cameraModes.end();++it)
1654  {
1655  derived().updateSwitchIfChanged(m_indiP_mode, it->first, pcf::IndiElement::Off, INDI_IDLE);
1656  }
1657  }
1658 
1659  if(derivedT::c_stdCamera_usesROI)
1660  {
1661  indi::updateIfChanged(m_indiP_roi_x, "current", std::string(""), derived().m_indiDriver, INDI_IDLE);
1662  indi::updateIfChanged(m_indiP_roi_x, "target", std::string(""), derived().m_indiDriver, INDI_IDLE);
1663 
1664  indi::updateIfChanged(m_indiP_roi_y, "current", std::string(""), derived().m_indiDriver, INDI_IDLE);
1665  indi::updateIfChanged(m_indiP_roi_y, "target", std::string(""), derived().m_indiDriver, INDI_IDLE);
1666 
1667  indi::updateIfChanged(m_indiP_roi_w, "current", std::string(""), derived().m_indiDriver, INDI_IDLE);
1668  indi::updateIfChanged(m_indiP_roi_w, "target", std::string(""), derived().m_indiDriver, INDI_IDLE);
1669 
1670  indi::updateIfChanged(m_indiP_roi_h, "current", std::string(""), derived().m_indiDriver, INDI_IDLE);
1671  indi::updateIfChanged(m_indiP_roi_h, "target", std::string(""), derived().m_indiDriver, INDI_IDLE);
1672 
1673  indi::updateIfChanged(m_indiP_roi_bin_x, "current", std::string(""), derived().m_indiDriver, INDI_IDLE);
1674  indi::updateIfChanged(m_indiP_roi_bin_x, "target", std::string(""), derived().m_indiDriver, INDI_IDLE);
1675 
1676  indi::updateIfChanged(m_indiP_roi_bin_y, "current", std::string(""), derived().m_indiDriver, INDI_IDLE);
1677  indi::updateIfChanged(m_indiP_roi_bin_y, "target", std::string(""), derived().m_indiDriver, INDI_IDLE);
1678  }
1679 
1680  //Shutters can be independent pieces of hardware . . .
1681  if(derivedT::c_stdCamera_hasShutter)
1682  {
1683  if(m_shutterStatus == "OPERATING")
1684  {
1685  derived().updateIfChanged(m_indiP_shutterStatus, "status", m_shutterStatus, INDI_BUSY);
1686  }
1687  if(m_shutterStatus == "POWERON" || m_shutterStatus == "READY")
1688  {
1689  derived().updateIfChanged(m_indiP_shutterStatus, "status", m_shutterStatus, INDI_OK);
1690  }
1691  else
1692  {
1693  derived().updateIfChanged(m_indiP_shutterStatus, "status", m_shutterStatus, INDI_IDLE);
1694  }
1695 
1696  if(m_shutterState == 0)
1697  {
1698  derived().updateSwitchIfChanged(m_indiP_shutter, "toggle", pcf::IndiElement::On, INDI_OK);
1699  }
1700  else
1701  {
1702  derived().updateSwitchIfChanged(m_indiP_shutter, "toggle", pcf::IndiElement::Off, INDI_IDLE);
1703  }
1704  }
1705 
1706  return 0;
1707 }
1708 
1709 template<class derivedT>
1711 {
1712  //Shutters can be independent pieces of hardware . . .
1713  if(derivedT::c_stdCamera_hasShutter)
1714  {
1715  if(m_shutterStatus == "OPERATING")
1716  {
1717  derived().updateIfChanged(m_indiP_shutterStatus, "status", m_shutterStatus, INDI_BUSY);
1718  }
1719  if(m_shutterStatus == "POWERON" || m_shutterStatus == "READY")
1720  {
1721  derived().updateIfChanged(m_indiP_shutterStatus, "status", m_shutterStatus, INDI_OK);
1722  }
1723  else
1724  {
1725  derived().updateIfChanged(m_indiP_shutterStatus, "status", m_shutterStatus, INDI_IDLE);
1726  }
1727 
1728  if(m_shutterState == 0)
1729  {
1730  derived().updateSwitchIfChanged(m_indiP_shutter, "toggle", pcf::IndiElement::On, INDI_OK);
1731  }
1732  else
1733  {
1734  derived().updateSwitchIfChanged(m_indiP_shutter, "toggle", pcf::IndiElement::Off, INDI_IDLE);
1735  }
1736  }
1737 
1738  return 0;
1739 }
1740 
1741 template<class derivedT>
1743 {
1744  return 0;
1745 }
1746 
1747 
1748 template<class derivedT>
1750  const pcf::IndiProperty &ipRecv
1751  )
1752 {
1753  derivedT * _app = static_cast<derivedT *>(app);
1754  return _app->newCallBack_stdCamera(ipRecv);
1755 }
1756 
1757 template<class derivedT>
1759 {
1760 
1761  if(ipRecv.getDevice() != derived().configName())
1762  {
1763  #ifndef XWCTEST_INDI_CALLBACK_VALIDATION
1764  derivedT::template log<software_error>({__FILE__, __LINE__, "unknown INDI property"});
1765  #endif
1766 
1767  return -1;
1768  }
1769 
1770  std::string name = ipRecv.getName();
1771 
1772  if( name == "reconfigure") return newCallBack_reconfigure(ipRecv);
1773  else if(derivedT::c_stdCamera_temp && name == "temp_ccd") return newCallBack_temp(ipRecv);
1774  else if(derivedT::c_stdCamera_tempControl && name == "temp_ccd") return newCallBack_temp(ipRecv);
1775  else if(derivedT::c_stdCamera_tempControl && name == "temp_controller") return newCallBack_temp_controller(ipRecv);
1776  else if(derivedT::c_stdCamera_readoutSpeed && name == "readout_speed") return newCallBack_readoutSpeed(ipRecv);
1777  else if(derivedT::c_stdCamera_vShiftSpeed && name == "vshift_speed") return newCallBack_vShiftSpeed(ipRecv);
1778  else if(derivedT::c_stdCamera_emGain && name == "emgain") return newCallBack_emgain(ipRecv);
1779  else if(derivedT::c_stdCamera_exptimeCtrl && name == "exptime") return newCallBack_exptime(ipRecv);
1780  else if(derivedT::c_stdCamera_fpsCtrl && name == "fps") return newCallBack_fps(ipRecv);
1781  else if(derivedT::c_stdCamera_synchro && name == "synchro") return newCallBack_synchro(ipRecv);
1782  else if(derivedT::c_stdCamera_usesModes && name == "mode") return newCallBack_mode(ipRecv);
1783  else if(derivedT::c_stdCamera_cropMode && name == "roi_crop_mode") return newCallBack_cropMode(ipRecv);
1784  else if(derivedT::c_stdCamera_usesROI && name == "roi_region_x") return newCallBack_roi_x(ipRecv);
1785  else if(derivedT::c_stdCamera_usesROI && name == "roi_region_y") return newCallBack_roi_y(ipRecv);
1786  else if(derivedT::c_stdCamera_usesROI && name == "roi_region_w") return newCallBack_roi_w(ipRecv);
1787  else if(derivedT::c_stdCamera_usesROI && name == "roi_region_h") return newCallBack_roi_h(ipRecv);
1788  else if(derivedT::c_stdCamera_usesROI && name == "roi_region_bin_x") return newCallBack_roi_bin_x(ipRecv);
1789  else if(derivedT::c_stdCamera_usesROI && name == "roi_region_bin_y") return newCallBack_roi_bin_y(ipRecv);
1790  else if(derivedT::c_stdCamera_usesROI && name == "roi_region_check") return newCallBack_roi_check(ipRecv);
1791  else if(derivedT::c_stdCamera_usesROI && name == "roi_set") return newCallBack_roi_set(ipRecv);
1792  else if(derivedT::c_stdCamera_usesROI && name == "roi_set_full") return newCallBack_roi_full(ipRecv);
1793  else if(derivedT::c_stdCamera_usesROI && name == "roi_set_full_bin") return newCallBack_roi_fullbin(ipRecv);
1794  else if(derivedT::c_stdCamera_usesROI && name == "roi_load_last") return newCallBack_roi_loadlast(ipRecv);
1795  else if(derivedT::c_stdCamera_usesROI && name == "roi_set_last") return newCallBack_roi_last(ipRecv);
1796  else if(derivedT::c_stdCamera_usesROI && name == "roi_set_default") return newCallBack_roi_default(ipRecv);
1797  else if(derivedT::c_stdCamera_hasShutter && name == "shutter") return newCallBack_shutter(ipRecv);
1798 
1799  #ifndef XWCTEST_INDI_CALLBACK_VALIDATION
1800  derivedT::template log<software_error>({__FILE__,__LINE__, "unknown INDI property"});
1801  #endif
1802 
1803  return -1;
1804 }
1805 
1806 template<class derivedT>
1807 int stdCamera<derivedT>::setTempSetPt( const mx::meta::trueFalseT<true> & t)
1808 {
1809  static_cast<void>(t);
1810  return derived().setTempSetPt();
1811 }
1812 
1813 template<class derivedT>
1814 int stdCamera<derivedT>::setTempSetPt( const mx::meta::trueFalseT<false> & f)
1815 {
1816  static_cast<void>(f);
1817  return 0;
1818 }
1819 
1820 template<class derivedT>
1821 int stdCamera<derivedT>::newCallBack_temp( const pcf::IndiProperty &ipRecv )
1822 {
1823  if(derivedT::c_stdCamera_tempControl)
1824  {
1825  #ifdef XWCTEST_INDI_CALLBACK_VALIDATION
1826  return 0;
1827  #endif
1828 
1829  float target;
1830 
1831  std::unique_lock<std::mutex> lock(derived().m_indiMutex);
1832 
1833  if (derived().indiTargetUpdate(m_indiP_temp, target, ipRecv, true) < 0)
1834  {
1835  derivedT::template log<software_error>({__FILE__, __LINE__});
1836  return -1;
1837  }
1838 
1839  m_ccdTempSetpt = target;
1840 
1841  mx::meta::trueFalseT<derivedT::c_stdCamera_tempControl> tf;
1842  return setTempSetPt(tf);
1843  }
1844  else
1845  {
1846  return 0;
1847  }
1848 }
1849 
1850 template<class derivedT>
1851 int stdCamera<derivedT>::setTempControl( const mx::meta::trueFalseT<true> & t)
1852 {
1853  static_cast<void>(t);
1854  return derived().setTempControl();
1855 }
1856 
1857 template<class derivedT>
1858 int stdCamera<derivedT>::setTempControl( const mx::meta::trueFalseT<false> & f)
1859 {
1860  static_cast<void>(f);
1861  return 0;
1862 }
1863 
1864 template<class derivedT>
1866 {
1867  if(derivedT::c_stdCamera_tempControl)
1868  {
1869  #ifdef XWCTEST_INDI_CALLBACK_VALIDATION
1870  return 0;
1871  #endif
1872 
1873  if(!ipRecv.find("toggle")) return 0;
1874 
1875  m_tempControlStatusSet = false;
1876 
1877  std::unique_lock<std::mutex> lock(derived().m_indiMutex);
1878 
1879  if( ipRecv["toggle"].getSwitchState() == pcf::IndiElement::On)
1880  {
1881  m_tempControlStatusSet = true;
1882  derived().updateSwitchIfChanged(m_indiP_tempcont, "toggle", pcf::IndiElement::On, INDI_BUSY);
1883  }
1884  else if( ipRecv["toggle"].getSwitchState() == pcf::IndiElement::Off)
1885  {
1886  m_tempControlStatusSet = false;
1887  derived().updateSwitchIfChanged(m_indiP_tempcont, "toggle", pcf::IndiElement::Off, INDI_BUSY);
1888  }
1889 
1890  mx::meta::trueFalseT<derivedT::c_stdCamera_emGain> tf;
1891  return setTempControl(tf);
1892  }
1893  else
1894  {
1895  return 0;
1896  }
1897 }
1898 
1899 template<class derivedT>
1900 int stdCamera<derivedT>::setReadoutSpeed( const mx::meta::trueFalseT<true> & t)
1901 {
1902  static_cast<void>(t);
1903  return derived().setReadoutSpeed();
1904 }
1905 
1906 template<class derivedT>
1907 int stdCamera<derivedT>::setReadoutSpeed( const mx::meta::trueFalseT<false> & f)
1908 {
1909  static_cast<void>(f);
1910  return 0;
1911 }
1912 
1913 template<class derivedT>
1915 {
1916  if(derivedT::c_stdCamera_readoutSpeed)
1917  {
1918  #ifdef XWCTEST_INDI_CALLBACK_VALIDATION
1919  return 0;
1920  #endif
1921 
1922  std::unique_lock<std::mutex> lock(derived().m_indiMutex);
1923 
1924  std::string newspeed;
1925 
1926  for(size_t i=0; i< m_readoutSpeedNames.size(); ++i)
1927  {
1928  if(!ipRecv.find(m_readoutSpeedNames[i])) continue;
1929 
1930  if(ipRecv[m_readoutSpeedNames[i]].getSwitchState() == pcf::IndiElement::On)
1931  {
1932  if(newspeed != "")
1933  {
1934  derivedT::template log<text_log>("More than one readout speed selected", logPrio::LOG_ERROR);
1935  return -1;
1936  }
1937 
1938  newspeed = m_readoutSpeedNames[i];
1939  }
1940  }
1941 
1942  if(newspeed == "")
1943  {
1944  //We do a reset
1945  m_readoutSpeedNameSet = m_readoutSpeedName;
1946  }
1947  else
1948  {
1949  m_readoutSpeedNameSet = newspeed;
1950  }
1951 
1952  mx::meta::trueFalseT<derivedT::c_stdCamera_readoutSpeed> tf;
1953  return setReadoutSpeed(tf);
1954  }
1955 
1956  return 0;
1957 }
1958 
1959 template<class derivedT>
1960 int stdCamera<derivedT>::setVShiftSpeed( const mx::meta::trueFalseT<true> & t)
1961 {
1962  static_cast<void>(t);
1963  return derived().setVShiftSpeed();
1964 }
1965 
1966 template<class derivedT>
1967 int stdCamera<derivedT>::setVShiftSpeed( const mx::meta::trueFalseT<false> & f)
1968 {
1969  static_cast<void>(f);
1970  return 0;
1971 }
1972 
1973 template<class derivedT>
1975 {
1976  if(derivedT::c_stdCamera_vShiftSpeed)
1977  {
1978  #ifdef XWCTEST_INDI_CALLBACK_VALIDATION
1979  return 0;
1980  #endif
1981 
1982  std::unique_lock<std::mutex> lock(derived().m_indiMutex);
1983 
1984  std::string newspeed;
1985 
1986  for(size_t i=0; i< m_vShiftSpeedNames.size(); ++i)
1987  {
1988  if(!ipRecv.find(m_vShiftSpeedNames[i])) continue;
1989 
1990  if(ipRecv[m_vShiftSpeedNames[i]].getSwitchState() == pcf::IndiElement::On)
1991  {
1992  if(newspeed != "")
1993  {
1994  derivedT::template log<text_log>("More than one vShift speed selected", logPrio::LOG_ERROR);
1995  return -1;
1996  }
1997 
1998  newspeed = m_vShiftSpeedNames[i];
1999  }
2000  }
2001 
2002  if(newspeed == "")
2003  {
2004  //We do a reset
2005  m_vShiftSpeedNameSet = m_vShiftSpeedName;
2006  }
2007  else
2008  {
2009  m_vShiftSpeedNameSet = newspeed;
2010  }
2011 
2012  mx::meta::trueFalseT<derivedT::c_stdCamera_vShiftSpeed> tf;
2013  return setVShiftSpeed(tf);
2014  }
2015 
2016  return 0;
2017 }
2018 
2019 template<class derivedT>
2020 int stdCamera<derivedT>::setEMGain( const mx::meta::trueFalseT<true> & t)
2021 {
2022  static_cast<void>(t);
2023  return derived().setEMGain();
2024 }
2025 
2026 template<class derivedT>
2027 int stdCamera<derivedT>::setEMGain( const mx::meta::trueFalseT<false> & f)
2028 {
2029  static_cast<void>(f);
2030  return 0;
2031 }
2032 
2033 template<class derivedT>
2034 int stdCamera<derivedT>::newCallBack_emgain( const pcf::IndiProperty &ipRecv)
2035 {
2036  if(derivedT::c_stdCamera_emGain)
2037  {
2038  #ifdef XWCTEST_INDI_CALLBACK_VALIDATION
2039  return 0;
2040  #endif
2041 
2042  float target;
2043 
2044  std::unique_lock<std::mutex> lock(derived().m_indiMutex);
2045 
2046  if( derived().indiTargetUpdate( m_indiP_emGain, target, ipRecv, true) < 0)
2047  {
2048  derivedT::template log<software_error>({__FILE__,__LINE__});
2049  return -1;
2050  }
2051 
2052  m_emGainSet = target;
2053 
2054  mx::meta::trueFalseT<derivedT::c_stdCamera_emGain> tf;
2055  return setEMGain(tf);
2056  }
2057 
2058  return 0;
2059 }
2060 
2061 template<class derivedT>
2062 int stdCamera<derivedT>::setExpTime( const mx::meta::trueFalseT<true> & t)
2063 {
2064  static_cast<void>(t);
2065  return derived().setExpTime();
2066 }
2067 
2068 template<class derivedT>
2069 int stdCamera<derivedT>::setExpTime( const mx::meta::trueFalseT<false> & f)
2070 {
2071  static_cast<void>(f);
2072  return 0;
2073 }
2074 
2075 template<class derivedT>
2076 int stdCamera<derivedT>::newCallBack_exptime( const pcf::IndiProperty &ipRecv)
2077 {
2078  if(derivedT::c_stdCamera_exptimeCtrl)
2079  {
2080  #ifdef XWCTEST_INDI_CALLBACK_VALIDATION
2081  return 0;
2082  #endif
2083 
2084  float target;
2085 
2086  std::unique_lock<std::mutex> lock(derived().m_indiMutex);
2087 
2088  if( derived().indiTargetUpdate( m_indiP_exptime, target, ipRecv, true) < 0)
2089  {
2090  derivedT::template log<software_error>({__FILE__,__LINE__});
2091  return -1;
2092  }
2093 
2094  m_expTimeSet = target;
2095 
2096  mx::meta::trueFalseT<derivedT::c_stdCamera_exptimeCtrl> tf;
2097  return setExpTime(tf);
2098  }
2099 
2100  return 0;
2101 }
2102 
2103 template<class derivedT>
2104 int stdCamera<derivedT>::setFPS( const mx::meta::trueFalseT<true> & t)
2105 {
2106  static_cast<void>(t);
2107  return derived().setFPS();
2108 }
2109 
2110 template<class derivedT>
2111 int stdCamera<derivedT>::setFPS( const mx::meta::trueFalseT<false> & f)
2112 {
2113  static_cast<void>(f);
2114  return 0;
2115 }
2116 
2117 template<class derivedT>
2118 int stdCamera<derivedT>::newCallBack_fps( const pcf::IndiProperty &ipRecv)
2119 {
2120  if(derivedT::c_stdCamera_fpsCtrl)
2121  {
2122  #ifdef XWCTEST_INDI_CALLBACK_VALIDATION
2123  return 0;
2124  #endif
2125 
2126  float target;
2127 
2128  std::unique_lock<std::mutex> lock(derived().m_indiMutex);
2129 
2130  if( derived().indiTargetUpdate( m_indiP_fps, target, ipRecv, true) < 0)
2131  {
2132  derivedT::template log<software_error>({__FILE__,__LINE__});
2133  return -1;
2134  }
2135 
2136  m_fpsSet = target;
2137 
2138  mx::meta::trueFalseT<derivedT::c_stdCamera_fpsCtrl> tf;
2139  return setFPS(tf);
2140  }
2141 
2142  return 0;
2143 }
2144 
2145 template<class derivedT>
2146 int stdCamera<derivedT>::setSynchro( const mx::meta::trueFalseT<true> & t)
2147 {
2148  static_cast<void>(t);
2149  return derived().setSynchro();
2150 }
2151 
2152 template<class derivedT>
2153 int stdCamera<derivedT>::setSynchro( const mx::meta::trueFalseT<false> & f)
2154 {
2155  static_cast<void>(f);
2156  return 0;
2157 }
2158 
2159 template<class derivedT>
2160 int stdCamera<derivedT>::newCallBack_synchro( const pcf::IndiProperty &ipRecv)
2161 {
2162  if(derivedT::c_stdCamera_synchro)
2163  {
2164  #ifdef XWCTEST_INDI_CALLBACK_VALIDATION
2165  return 0;
2166  #endif
2167 
2168  if(!ipRecv.find("toggle")) return 0;
2169 
2170  if( ipRecv["toggle"].getSwitchState() == pcf::IndiElement::Off )
2171  {
2172  m_synchroSet = false;
2173  }
2174 
2175  if( ipRecv["toggle"].getSwitchState() == pcf::IndiElement::On )
2176  {
2177  m_synchroSet = true;
2178  }
2179 
2180  std::unique_lock<std::mutex> lock(derived().m_indiMutex);
2181 
2182  mx::meta::trueFalseT<derivedT::c_stdCamera_synchro> tf;
2183  return setSynchro(tf);
2184  }
2185 
2186  return 0;
2187 }
2188 
2189 template<class derivedT>
2190 int stdCamera<derivedT>::newCallBack_mode( const pcf::IndiProperty &ipRecv )
2191 {
2192  if(derivedT::c_stdCamera_usesModes)
2193  {
2194  #ifdef XWCTEST_INDI_CALLBACK_VALIDATION
2195  return 0;
2196  #endif
2197 
2198  std::unique_lock<std::mutex> lock(derived().m_indiMutex);
2199 
2200  if(ipRecv.getName() != m_indiP_mode.getName())
2201  {
2202  derivedT::template log<software_error>({__FILE__, __LINE__, "invalid indi property received"});
2203  return -1;
2204  }
2205 
2206  //look for selected mode switch which matches a known mode. Make sure only one is selected.
2207  std::string newName = "";
2208  for(auto it=m_cameraModes.begin(); it != m_cameraModes.end(); ++it)
2209  {
2210  if(!ipRecv.find(it->first)) continue;
2211 
2212  if(ipRecv[it->first].getSwitchState() == pcf::IndiElement::On)
2213  {
2214  if(newName != "")
2215  {
2216  derivedT::template log<text_log>("More than one camera mode selected", logPrio::LOG_ERROR);
2217  return -1;
2218  }
2219 
2220  newName = it->first;
2221  }
2222  }
2223 
2224  if(newName == "")
2225  {
2226  return 0;
2227  }
2228 
2229  //Now signal the f.g. thread to reconfigure
2230  m_nextMode = newName;
2231  derived().m_reconfig = true;
2232 
2233  return 0;
2234  }
2235  else
2236  {
2237  return 0;
2238  }
2239 }
2240 
2241 template<class derivedT>
2243 {
2244  #ifdef XWCTEST_INDI_CALLBACK_VALIDATION
2245  return 0;
2246  #endif
2247 
2248  if(!ipRecv.find("request")) return 0;
2249 
2250  if( ipRecv["request"].getSwitchState() == pcf::IndiElement::On)
2251  {
2252  std::unique_lock<std::mutex> lock(derived().m_indiMutex);
2253 
2254  indi::updateSwitchIfChanged(m_indiP_reconfig, "request", pcf::IndiElement::Off, derived().m_indiDriver, INDI_IDLE);
2255 
2256  m_nextMode = m_modeName;
2257  derived().m_reconfig = true;
2258  return 0;
2259  }
2260 
2261  return 0;
2262 }
2263 
2264 template<class derivedT>
2265 int stdCamera<derivedT>::setCropMode( const mx::meta::trueFalseT<true> & t)
2266 {
2267  static_cast<void>(t);
2268  return derived().setCropMode();
2269 }
2270 
2271 template<class derivedT>
2272 int stdCamera<derivedT>::setCropMode( const mx::meta::trueFalseT<false> & f)
2273 {
2274  static_cast<void>(f);
2275  return 0;
2276 }
2277 
2278 template<class derivedT>
2280 {
2281  if(derivedT::c_stdCamera_cropMode)
2282  {
2283  #ifdef XWCTEST_INDI_CALLBACK_VALIDATION
2284  return 0;
2285  #endif
2286 
2287  if(!ipRecv.find("toggle")) return 0;
2288 
2289  if( ipRecv["toggle"].getSwitchState() == pcf::IndiElement::Off )
2290  {
2291  m_cropModeSet = false;
2292  }
2293 
2294  if( ipRecv["toggle"].getSwitchState() == pcf::IndiElement::On )
2295  {
2296  m_cropModeSet = true;
2297  }
2298 
2299  std::unique_lock<std::mutex> lock(derived().m_indiMutex);
2300 
2301  mx::meta::trueFalseT<derivedT::c_stdCamera_cropMode> tf;
2302  return setCropMode(tf);
2303  }
2304 
2305  return 0;
2306 }
2307 
2308 ///\todo why don't these check if usesROI is true?
2309 template<class derivedT>
2310 int stdCamera<derivedT>::newCallBack_roi_x( const pcf::IndiProperty &ipRecv )
2311 {
2312  #ifdef XWCTEST_INDI_CALLBACK_VALIDATION
2313  return 0;
2314  #endif
2315 
2316  float target;
2317 
2318  std::unique_lock<std::mutex> lock(derived().m_indiMutex);
2319 
2320  if( derived().indiTargetUpdate( m_indiP_roi_x, target, ipRecv, false) < 0)
2321  {
2322  m_nextROI.x = m_currentROI.x;
2323  derivedT::template log<software_error>({__FILE__,__LINE__});
2324  return -1;
2325  }
2326 
2327  m_nextROI.x = target;
2328 
2329  return 0;
2330 }
2331 
2332 template<class derivedT>
2333 int stdCamera<derivedT>::newCallBack_roi_y( const pcf::IndiProperty &ipRecv )
2334 {
2335  #ifdef XWCTEST_INDI_CALLBACK_VALIDATION
2336  return 0;
2337  #endif
2338 
2339  float target;
2340 
2341  std::unique_lock<std::mutex> lock(derived().m_indiMutex);
2342 
2343  if( derived().indiTargetUpdate( m_indiP_roi_y, target, ipRecv, false) < 0)
2344  {
2345  m_nextROI.y = m_currentROI.y;
2346  derivedT::template log<software_error>({__FILE__,__LINE__});
2347  return -1;
2348  }
2349 
2350  m_nextROI.y = target;
2351 
2352  return 0;
2353 }
2354 
2355 template<class derivedT>
2356 int stdCamera<derivedT>::newCallBack_roi_w( const pcf::IndiProperty &ipRecv )
2357 {
2358  #ifdef XWCTEST_INDI_CALLBACK_VALIDATION
2359  return 0;
2360  #endif
2361 
2362  int target;
2363 
2364  std::unique_lock<std::mutex> lock(derived().m_indiMutex);
2365 
2366  if( derived().indiTargetUpdate( m_indiP_roi_w, target, ipRecv, false) < 0)
2367  {
2368  m_nextROI.w = m_currentROI.w;
2369  derivedT::template log<software_error>({__FILE__,__LINE__});
2370  return -1;
2371  }
2372 
2373  m_nextROI.w = target;
2374 
2375  return 0;
2376 }
2377 
2378 template<class derivedT>
2379 int stdCamera<derivedT>::newCallBack_roi_h( const pcf::IndiProperty &ipRecv )
2380 {
2381  #ifdef XWCTEST_INDI_CALLBACK_VALIDATION
2382  return 0;
2383  #endif
2384 
2385  int target;
2386 
2387  std::unique_lock<std::mutex> lock(derived().m_indiMutex);
2388 
2389  if( derived().indiTargetUpdate( m_indiP_roi_h, target, ipRecv, false) < 0)
2390  {
2391  derivedT::template log<software_error>({__FILE__,__LINE__});
2392  m_nextROI.h = m_currentROI.h;
2393  return -1;
2394  }
2395 
2396  m_nextROI.h = target;
2397 
2398  return 0;
2399 }
2400 
2401 template<class derivedT>
2402 int stdCamera<derivedT>::newCallBack_roi_bin_x ( const pcf::IndiProperty &ipRecv )
2403 {
2404  #ifdef XWCTEST_INDI_CALLBACK_VALIDATION
2405  return 0;
2406  #endif
2407 
2408  int target;
2409 
2410  std::unique_lock<std::mutex> lock(derived().m_indiMutex);
2411 
2412  if( derived().indiTargetUpdate( m_indiP_roi_bin_x, target, ipRecv, false) < 0)
2413  {
2414  derivedT::template log<software_error>({__FILE__,__LINE__});
2415  m_nextROI.bin_x = m_currentROI.bin_x;
2416  return -1;
2417  }
2418 
2419  m_nextROI.bin_x = target;
2420 
2421  return 0;
2422 }
2423 
2424 template<class derivedT>
2426 {
2427  #ifdef XWCTEST_INDI_CALLBACK_VALIDATION
2428  return 0;
2429  #endif
2430 
2431  int target;
2432 
2433  std::unique_lock<std::mutex> lock(derived().m_indiMutex);
2434 
2435  if( derived().indiTargetUpdate( m_indiP_roi_bin_y, target, ipRecv, false) < 0)
2436  {
2437  derivedT::template log<software_error>({__FILE__,__LINE__});
2438  m_nextROI.bin_y = m_currentROI.bin_y;
2439  return -1;
2440  }
2441 
2442  m_nextROI.bin_y = target;
2443 
2444  return 0;
2445 }
2446 
2447 template<class derivedT>
2448 int stdCamera<derivedT>::checkNextROI( const mx::meta::trueFalseT<true> & t)
2449 {
2450  static_cast<void>(t);
2451  return derived().checkNextROI();
2452 }
2453 
2454 template<class derivedT>
2455 int stdCamera<derivedT>::checkNextROI( const mx::meta::trueFalseT<false> & f)
2456 {
2457  static_cast<void>(f);
2458  return 0;
2459 }
2460 
2461 template<class derivedT>
2463 {
2464  if(derivedT::c_stdCamera_usesROI)
2465  {
2466  #ifdef XWCTEST_INDI_CALLBACK_VALIDATION
2467  return 0;
2468  #endif
2469 
2470  if(!ipRecv.find("request")) return 0;
2471 
2472  if( ipRecv["request"].getSwitchState() == pcf::IndiElement::On)
2473  {
2474  std::unique_lock<std::mutex> lock(derived().m_indiMutex);
2475 
2476  indi::updateSwitchIfChanged(m_indiP_roi_check, "request", pcf::IndiElement::Off, derived().m_indiDriver, INDI_IDLE);
2477 
2478  mx::meta::trueFalseT<derivedT::c_stdCamera_usesROI> tf;
2479  return checkNextROI(tf);
2480  }
2481 
2482  return 0;
2483  }
2484 
2485  return 0;
2486 }
2487 
2488 template<class derivedT>
2489 int stdCamera<derivedT>::setNextROI( const mx::meta::trueFalseT<true> & t)
2490 {
2491  static_cast<void>(t);
2492  return derived().setNextROI();
2493 }
2494 
2495 template<class derivedT>
2496 int stdCamera<derivedT>::setNextROI( const mx::meta::trueFalseT<false> & f)
2497 {
2498  static_cast<void>(f);
2499  return 0;
2500 }
2501 
2502 template<class derivedT>
2503 int stdCamera<derivedT>::newCallBack_roi_set( const pcf::IndiProperty &ipRecv )
2504 {
2505  if(derivedT::c_stdCamera_usesROI)
2506  {
2507  #ifdef XWCTEST_INDI_CALLBACK_VALIDATION
2508  return 0;
2509  #endif
2510 
2511  if(!ipRecv.find("request")) return 0;
2512 
2513  if( ipRecv["request"].getSwitchState() == pcf::IndiElement::On)
2514  {
2515  std::unique_lock<std::mutex> lock(derived().m_indiMutex);
2516 
2517  indi::updateSwitchIfChanged(m_indiP_roi_set, "request", pcf::IndiElement::Off, derived().m_indiDriver, INDI_IDLE);
2518 
2519  m_lastROI = m_currentROI;
2520 
2521  mx::meta::trueFalseT<derivedT::c_stdCamera_usesROI> tf;
2522  return setNextROI(tf);
2523  }
2524 
2525  return 0;
2526  }
2527 
2528  return 0;
2529 }
2530 
2531 template<class derivedT>
2532 int stdCamera<derivedT>::newCallBack_roi_full( const pcf::IndiProperty &ipRecv )
2533 {
2534  if(derivedT::c_stdCamera_usesROI)
2535  {
2536  #ifdef XWCTEST_INDI_CALLBACK_VALIDATION
2537  return 0;
2538  #endif
2539 
2540  if(!ipRecv.find("request")) return 0;
2541 
2542  if( ipRecv["request"].getSwitchState() == pcf::IndiElement::On)
2543  {
2544  std::unique_lock<std::mutex> lock(derived().m_indiMutex);
2545 
2546  indi::updateSwitchIfChanged(m_indiP_roi_full, "request", pcf::IndiElement::Off, derived().m_indiDriver, INDI_IDLE);
2547 
2548  m_nextROI.x = m_full_x;
2549  m_nextROI.y = m_full_y;
2550  m_nextROI.w = m_full_w;
2551  m_nextROI.h = m_full_h;
2552  m_nextROI.bin_x = m_full_bin_x;
2553  m_nextROI.bin_y = m_full_bin_y;
2554  m_lastROI = m_currentROI;
2555  mx::meta::trueFalseT<derivedT::c_stdCamera_usesROI> tf;
2556  return setNextROI(tf);
2557  }
2558 
2559  return 0;
2560  }
2561 
2562  return 0;
2563 }
2564 
2565 template<class derivedT>
2567 {
2568  if(derivedT::c_stdCamera_usesROI)
2569  {
2570  #ifdef XWCTEST_INDI_CALLBACK_VALIDATION
2571  return 0;
2572  #endif
2573 
2574  if(!ipRecv.find("request")) return 0;
2575 
2576  if( ipRecv["request"].getSwitchState() == pcf::IndiElement::On)
2577  {
2578  std::unique_lock<std::mutex> lock(derived().m_indiMutex);
2579 
2580  indi::updateSwitchIfChanged(m_indiP_roi_fullbin, "request", pcf::IndiElement::Off, derived().m_indiDriver, INDI_IDLE);
2581 
2582  bool reset = false;
2583 
2584  if(m_full_currbin_x == 0) //still defaulted
2585  {
2586  derivedT::template log<text_log>("current-binning full ROI not implemented for this camera", logPrio::LOG_WARNING);
2587  m_full_currbin_x = m_full_x;
2588  m_full_currbin_y = m_full_y;
2589  m_full_currbin_w = m_full_w;
2590  m_full_currbin_h = m_full_h;
2591  reset = true;
2592  }
2593 
2594 
2595 
2596  m_nextROI.x = m_full_currbin_x;
2597  m_nextROI.y = m_full_currbin_y;
2598  m_nextROI.w = m_full_currbin_w;
2599  m_nextROI.h = m_full_currbin_h;
2600  if(reset)
2601  {
2602  //Use full binning
2603  m_nextROI.bin_x = m_full_bin_x;
2604  m_nextROI.bin_y = m_full_bin_y;
2605 
2606  //restore defaults for next time
2607  m_full_currbin_x = 0;
2608  m_full_currbin_y = 0;
2609  m_full_currbin_w = 0;
2610  m_full_currbin_h = 0;
2611  }
2612  else
2613  {
2614  m_nextROI.bin_x = m_currentROI.bin_x;
2615  m_nextROI.bin_y = m_currentROI.bin_y;
2616  }
2617 
2618  m_lastROI = m_currentROI;
2619  mx::meta::trueFalseT<derivedT::c_stdCamera_usesROI> tf;
2620  return setNextROI(tf);
2621  }
2622 
2623  return 0;
2624  }
2625 
2626  return 0;
2627 }
2628 
2629 template<class derivedT>
2631 {
2632  if(derivedT::c_stdCamera_usesROI)
2633  {
2634  #ifdef XWCTEST_INDI_CALLBACK_VALIDATION
2635  return 0;
2636  #endif
2637 
2638  if(!ipRecv.find("request")) return 0;
2639 
2640  if( ipRecv["request"].getSwitchState() == pcf::IndiElement::On)
2641  {
2642  std::unique_lock<std::mutex> lock(derived().m_indiMutex);
2643 
2644  indi::updateSwitchIfChanged(m_indiP_roi_loadlast, "request", pcf::IndiElement::Off, derived().m_indiDriver, INDI_IDLE);
2645 
2646  m_nextROI = m_lastROI;
2647  return 0;
2648  }
2649 
2650  return 0;
2651  }
2652 
2653  return 0;
2654 }
2655 
2656 template<class derivedT>
2657 int stdCamera<derivedT>::newCallBack_roi_last( const pcf::IndiProperty &ipRecv )
2658 {
2659  if(derivedT::c_stdCamera_usesROI)
2660  {
2661  #ifdef XWCTEST_INDI_CALLBACK_VALIDATION
2662  return 0;
2663  #endif
2664  if(!ipRecv.find("request")) return 0;
2665 
2666  if( ipRecv["request"].getSwitchState() == pcf::IndiElement::On)
2667  {
2668  std::unique_lock<std::mutex> lock(derived().m_indiMutex);
2669 
2670  indi::updateSwitchIfChanged(m_indiP_roi_last, "request", pcf::IndiElement::Off, derived().m_indiDriver, INDI_IDLE);
2671 
2672  m_nextROI = m_lastROI;
2673  m_lastROI = m_currentROI;
2674  mx::meta::trueFalseT<derivedT::c_stdCamera_usesROI> tf;
2675  return setNextROI(tf);
2676  }
2677 
2678  return 0;
2679  }
2680 
2681  return 0;
2682 }
2683 
2684 template<class derivedT>
2686 {
2687  if(derivedT::c_stdCamera_usesROI)
2688  {
2689  #ifdef XWCTEST_INDI_CALLBACK_VALIDATION
2690  return 0;
2691  #endif
2692 
2693  if(!ipRecv.find("request")) return 0;
2694 
2695  if( ipRecv["request"].getSwitchState() == pcf::IndiElement::On)
2696  {
2697  std::unique_lock<std::mutex> lock(derived().m_indiMutex);
2698 
2699  indi::updateSwitchIfChanged(m_indiP_roi_default, "request", pcf::IndiElement::Off, derived().m_indiDriver, INDI_IDLE);
2700 
2701  m_nextROI.x = m_default_x;
2702  m_nextROI.y = m_default_y;
2703  m_nextROI.w = m_default_w;
2704  m_nextROI.h = m_default_h;
2705  m_nextROI.bin_x = m_default_bin_x;
2706  m_nextROI.bin_y = m_default_bin_y;
2707  m_lastROI = m_currentROI;
2708  mx::meta::trueFalseT<derivedT::c_stdCamera_usesROI> tf;
2709  return setNextROI(tf);
2710  }
2711 
2712  return 0;
2713  }
2714 
2715  return 0;
2716 }
2717 
2718 template<class derivedT>
2720  const mx::meta::trueFalseT<true> & t
2721  )
2722 {
2723  static_cast<void>(t);
2724  return derived().setShutter(ss);
2725 }
2726 
2727 template<class derivedT>
2729  const mx::meta::trueFalseT<false> & f
2730  )
2731 {
2732  static_cast<void>(ss);
2733  static_cast<void>(f);
2734  return 0;
2735 }
2736 
2737 template<class derivedT>
2738 int stdCamera<derivedT>::newCallBack_shutter( const pcf::IndiProperty &ipRecv )
2739 {
2740  if(derivedT::c_stdCamera_hasShutter)
2741  {
2742  #ifdef XWCTEST_INDI_CALLBACK_VALIDATION
2743  return 0;
2744  #endif
2745 
2746  if(!ipRecv.find("toggle")) return 0;
2747 
2748  mx::meta::trueFalseT<derivedT::c_stdCamera_hasShutter> tf;
2749 
2750  if( ipRecv["toggle"].getSwitchState() == pcf::IndiElement::Off )
2751  {
2752  setShutter(1, tf);
2753  }
2754 
2755  if( ipRecv["toggle"].getSwitchState() == pcf::IndiElement::On )
2756  {
2757  setShutter(0, tf);
2758  }
2759 
2760  return 0;
2761  }
2762  return 0;
2763 }
2764 
2765 template<class derivedT>
2766 std::string stdCamera<derivedT>::stateString( const mx::meta::trueFalseT<true> & t)
2767 {
2768  static_cast<void>(t);
2769  return derived().stateString();
2770 }
2771 
2772 template<class derivedT>
2773 std::string stdCamera<derivedT>::stateString( const mx::meta::trueFalseT<false> & f)
2774 {
2775  static_cast<void>(f);
2776  return "";
2777 }
2778 
2779 template<class derivedT>
2780 bool stdCamera<derivedT>::stateStringValid( const mx::meta::trueFalseT<true> & t)
2781 {
2782  static_cast<void>(t);
2783  return derived().stateStringValid();
2784 }
2785 
2786 template<class derivedT>
2787 bool stdCamera<derivedT>::stateStringValid( const mx::meta::trueFalseT<false> & f)
2788 {
2789  static_cast<void>(f);
2790  return false;
2791 }
2792 
2793 template<class derivedT>
2795 {
2796  if( !derived().m_indiDriver ) return 0;
2797 
2798  if(derivedT::c_stdCamera_readoutSpeed)
2799  {
2800  indi::updateSelectionSwitchIfChanged( m_indiP_readoutSpeed, m_readoutSpeedName, derived().m_indiDriver, INDI_OK);
2801  }
2802 
2803  if(derivedT::c_stdCamera_vShiftSpeed)
2804  {
2805  indi::updateSelectionSwitchIfChanged( m_indiP_vShiftSpeed, m_vShiftSpeedName, derived().m_indiDriver, INDI_OK);
2806  }
2807 
2808  if(derivedT::c_stdCamera_emGain)
2809  {
2810  derived().updateIfChanged(m_indiP_emGain, "current", m_emGain, INDI_IDLE);
2811  derived().updateIfChanged(m_indiP_emGain, "target", m_emGainSet, INDI_IDLE);
2812  }
2813 
2814  if(derivedT::c_stdCamera_exptimeCtrl)
2815  {
2816  derived().updateIfChanged(m_indiP_exptime, "current", m_expTime, INDI_IDLE);
2817  derived().updateIfChanged(m_indiP_exptime, "target", m_expTimeSet, INDI_IDLE);
2818  }
2819 
2820  if(derivedT::c_stdCamera_fpsCtrl)
2821  {
2822  derived().updateIfChanged(m_indiP_fps, "current", m_fps, INDI_IDLE);
2823  derived().updateIfChanged(m_indiP_fps, "target", m_fpsSet, INDI_IDLE);
2824  }
2825  else if(derivedT::c_stdCamera_fps)
2826  {
2827  derived().updateIfChanged(m_indiP_fps, "current", m_fps, INDI_IDLE);
2828  }
2829 
2830  if(derivedT::c_stdCamera_synchro)
2831  {
2832  if(m_synchro == false)
2833  {
2834  derived().updateSwitchIfChanged(m_indiP_synchro, "toggle", pcf::IndiElement::Off, INDI_IDLE);
2835  }
2836  else
2837  {
2838  derived().updateSwitchIfChanged(m_indiP_synchro, "toggle", pcf::IndiElement::On, INDI_OK);
2839  }
2840  }
2841 
2842  if(derivedT::c_stdCamera_usesModes)
2843  {
2844  auto st = pcf::IndiProperty::Ok;
2845  if(m_nextMode != "") st = pcf::IndiProperty::Busy;
2846 
2847  for(auto it = m_cameraModes.begin();it!=m_cameraModes.end();++it)
2848  {
2849  if(it->first == m_modeName) derived().updateSwitchIfChanged(m_indiP_mode, it->first, pcf::IndiElement::On, st);
2850  else derived().updateSwitchIfChanged(m_indiP_mode, it->first, pcf::IndiElement::Off, st);
2851  }
2852 
2853  }
2854 
2855  if(derivedT::c_stdCamera_cropMode)
2856  {
2857  if(m_cropMode == false)
2858  {
2859  derived().updateSwitchIfChanged(m_indiP_cropMode, "toggle", pcf::IndiElement::Off, INDI_IDLE);
2860  }
2861  else
2862  {
2863  derived().updateSwitchIfChanged(m_indiP_cropMode, "toggle", pcf::IndiElement::On, INDI_OK);
2864  }
2865  }
2866 
2867  if(derivedT::c_stdCamera_usesROI)
2868  {
2869  //These can't change after initialization, but might not be discoverable until powered on and connected.
2870  //so we'll check every time I guess.
2871  derived().updateIfChanged(m_indiP_fullROI, "x", m_full_x, INDI_IDLE);
2872  derived().updateIfChanged(m_indiP_fullROI, "y", m_full_y, INDI_IDLE);
2873  derived().updateIfChanged(m_indiP_fullROI, "w", m_full_w, INDI_IDLE);
2874  derived().updateIfChanged(m_indiP_fullROI, "h", m_full_h, INDI_IDLE);
2875  }
2876 
2877  if(derivedT::c_stdCamera_tempControl)
2878  {
2879  if(m_tempControlStatus == false)
2880  {
2881  derived().updateSwitchIfChanged( m_indiP_tempcont, "toggle", pcf::IndiElement::Off, INDI_IDLE);
2882  derived().updateIfChanged(m_indiP_temp, "current", m_ccdTemp, INDI_IDLE);
2883  derived().updateIfChanged(m_indiP_temp, "target", m_ccdTempSetpt, INDI_IDLE);
2884  derived().updateIfChanged( m_indiP_tempstat, "status", m_tempControlStatusStr, INDI_IDLE);
2885  }
2886  else
2887  {
2888  if(m_tempControlOnTarget)
2889  {
2890  derived().updateSwitchIfChanged( m_indiP_tempcont, "toggle", pcf::IndiElement::On, INDI_OK);
2891  derived().updateIfChanged(m_indiP_temp, "current", m_ccdTemp, INDI_OK);
2892  derived().updateIfChanged(m_indiP_temp, "target", m_ccdTempSetpt, INDI_OK);
2893  derived().updateIfChanged( m_indiP_tempstat, "status", m_tempControlStatusStr, INDI_OK);
2894  }
2895  else
2896  {
2897  derived().updateSwitchIfChanged( m_indiP_tempcont, "toggle", pcf::IndiElement::On, INDI_BUSY);
2898  derived().updateIfChanged(m_indiP_temp, "current", m_ccdTemp, INDI_BUSY);
2899  derived().updateIfChanged(m_indiP_temp, "target", m_ccdTempSetpt, INDI_BUSY);
2900  derived().updateIfChanged( m_indiP_tempstat, "status", m_tempControlStatusStr, INDI_BUSY);
2901  }
2902  }
2903  }
2904  else if(derivedT::c_stdCamera_temp)
2905  {
2906  derived().updateIfChanged(m_indiP_temp, "current", m_ccdTemp, INDI_IDLE);
2907  }
2908 
2909 
2910 
2911  if(derivedT::c_stdCamera_hasShutter)
2912  {
2913  if(m_shutterStatus == "OPERATING")
2914  {
2915  derived().updateIfChanged(m_indiP_shutterStatus, "status", m_shutterStatus, INDI_BUSY);
2916  }
2917  if(m_shutterStatus == "POWERON" || m_shutterStatus == "READY")
2918  {
2919  derived().updateIfChanged(m_indiP_shutterStatus, "status", m_shutterStatus, INDI_IDLE);
2920  }
2921  else
2922  {
2923  derived().updateIfChanged(m_indiP_shutterStatus, "status", m_shutterStatus, INDI_IDLE);
2924  }
2925 
2926  if(m_shutterState == 0) //0 shut, 1 open
2927  {
2928  derived().updateSwitchIfChanged(m_indiP_shutter, "toggle", pcf::IndiElement::On, INDI_OK);
2929  }
2930  else
2931  {
2932  derived().updateSwitchIfChanged(m_indiP_shutter, "toggle", pcf::IndiElement::Off, INDI_IDLE);
2933  }
2934  }
2935 
2936  if(derivedT::c_stdCamera_usesStateString)
2937  {
2938  mx::meta::trueFalseT<derivedT::c_stdCamera_usesStateString> tf;
2939  derived().updateIfChanged(m_indiP_stateString, "current", stateString(tf), INDI_IDLE);
2940  if(stateStringValid(tf))
2941  {
2942  derived().updateIfChanged(m_indiP_stateString, "valid", "yes", INDI_IDLE);
2943  }
2944  else
2945  {
2946  derived().updateIfChanged(m_indiP_stateString, "valid", "no", INDI_IDLE);
2947  }
2948  }
2949  return 0;
2950 }
2951 
2952 template<class derivedT>
2954 {
2955  static std::string last_mode;
2956  static roi last_roi;
2957  static float last_expTime = -1e30; //ensure first one goes
2958  static float last_fps = 0;
2959  static float last_adcSpeed = -1;
2960  static float last_emGain = -1;
2961  static float last_ccdTemp = 0;
2962  static float last_ccdTempSetpt = 0;
2963  static bool last_tempControlStatus = 0;
2964  static bool last_tempControlOnTarget = 0;
2965  static std::string last_tempControlStatusStr;
2966  static std::string last_shutterStatus;
2967  static int last_shutterState = false;
2968  static bool last_synchro = false;
2969  static float last_vshiftSpeed = -1;
2970  static bool last_cropMode = false;
2971 
2972 
2973  if(force || m_modeName != last_mode ||
2974  m_currentROI.x != last_roi.x ||
2975  m_currentROI.y != last_roi.y ||
2976  m_currentROI.w != last_roi.w ||
2977  m_currentROI.h != last_roi.h ||
2978  m_currentROI.bin_x != last_roi.bin_x ||
2979  m_currentROI.bin_y != last_roi.bin_y ||
2980  m_expTime != last_expTime ||
2981  m_fps != last_fps ||
2982  m_emGain != last_emGain ||
2983  m_adcSpeed != last_adcSpeed ||
2984  m_ccdTemp != last_ccdTemp ||
2985  m_ccdTempSetpt != last_ccdTempSetpt ||
2986  m_tempControlStatus != last_tempControlStatus ||
2987  m_tempControlOnTarget != last_tempControlOnTarget ||
2988  m_tempControlStatusStr != last_tempControlStatusStr ||
2989  m_shutterStatus != last_shutterStatus ||
2990  m_shutterState != last_shutterState ||
2991  m_synchro != last_synchro ||
2992  m_vshiftSpeed != last_vshiftSpeed ||
2993  m_cropMode != last_cropMode)
2994  {
2995  derived().template telem<telem_stdcam>({m_modeName, m_currentROI.x, m_currentROI.y,
2996  m_currentROI.w, m_currentROI.h, m_currentROI.bin_x, m_currentROI.bin_y,
2997  m_expTime, m_fps, m_emGain, m_adcSpeed, m_ccdTemp, m_ccdTempSetpt, (uint8_t) m_tempControlStatus,
2998  (uint8_t) m_tempControlOnTarget, m_tempControlStatusStr, m_shutterStatus, (int8_t) m_shutterState,
2999  (uint8_t) m_synchro, m_vshiftSpeed, (uint8_t) m_cropMode});
3000 
3001  last_mode = m_modeName;
3002  last_roi = m_currentROI;
3003  last_expTime = m_expTime;
3004  last_fps = m_fps;
3005  last_emGain = m_emGain;
3006  last_adcSpeed = m_adcSpeed;
3007  last_ccdTemp = m_ccdTemp;
3008  last_ccdTempSetpt = m_ccdTempSetpt;
3009  last_tempControlStatus = m_tempControlStatus;
3010  last_tempControlOnTarget = m_tempControlOnTarget;
3011  last_tempControlStatusStr = m_tempControlStatusStr;
3012  last_shutterStatus = m_shutterStatus;
3013  last_shutterState = m_shutterState;
3014  last_synchro = m_synchro;
3015  last_vshiftSpeed = m_vshiftSpeed;
3016  last_cropMode = m_cropMode;
3017  }
3018 
3019 
3020  return 0;
3021 
3022 }
3023 
3024 
3025 } //namespace dev
3026 } //namespace app
3027 } //namespace MagAOX
3028 
3029 #endif //stdCamera_hpp
MagAO-X standard camera interface.
Definition: stdCamera.hpp:287
float m_maxEMGain
The configurable maximum EM gain. To be enforced in derivedT.
Definition: stdCamera.hpp:351
std::vector< std::string > m_readoutSpeedNames
Definition: stdCamera.hpp:334
float m_minExpTime
The minimum exposure time, used for INDI attributes.
Definition: stdCamera.hpp:363
pcf::IndiProperty m_indiP_roi_fullbin
Property used to trigger setting the full in current binning ROI.
Definition: stdCamera.hpp:483
float m_fpsSet
The commanded fps, as set by user.
Definition: stdCamera.hpp:375
int newCallBack_temp(const pcf::IndiProperty &ipRecv)
Callback to process a NEW CCD temp request.
Definition: stdCamera.hpp:1821
int newCallBack_cropMode(const pcf::IndiProperty &ipRecv)
Callback to process a NEW cropMode request.
Definition: stdCamera.hpp:2279
bool m_synchroSet
Target status of m_synchro.
Definition: stdCamera.hpp:386
pcf::IndiProperty m_indiP_roi_y
Property used to set the ROI x center coordinate.
Definition: stdCamera.hpp:470
int createReadoutSpeed(const mx::meta::trueFalseT< true > &t)
Definition: stdCamera.hpp:1124
int m_full_currbin_w
The current-binning full ROI width.
Definition: stdCamera.hpp:466
int setShutter(int ss, const mx::meta::trueFalseT< true > &t)
Interface to setShutter when the derivedT has a shutter.
Definition: stdCamera.hpp:2719
float m_default_x
Power-on ROI center x coordinate.
Definition: stdCamera.hpp:450
std::string m_tempControlStatusStr
Camera specific description of temperature control status.
Definition: stdCamera.hpp:322
float m_emGain
The camera's current EM gain (if available).
Definition: stdCamera.hpp:349
int m_full_bin_x
The x-binning in the full ROI.
Definition: stdCamera.hpp:461
int newCallBack_readoutSpeed(const pcf::IndiProperty &ipRecv)
Callback to process a NEW readout speed request.
Definition: stdCamera.hpp:1914
std::vector< std::string > m_readoutSpeedNameLabels
Definition: stdCamera.hpp:335
float m_full_currbin_x
The current-binning full ROI center x coordinate.
Definition: stdCamera.hpp:464
int m_full_w
The full ROI width.
Definition: stdCamera.hpp:459
float m_emGainSet
The camera's EM gain, as set by the user.
Definition: stdCamera.hpp:350
std::string m_vShiftSpeedNameSet
The user requested vshift speed name, to be set by derived()
Definition: stdCamera.hpp:344
bool m_cropModeSet
Desired status of crop mode ROIs, if enabled for this camera.
Definition: stdCamera.hpp:495
int newCallBack_roi_bin_y(const pcf::IndiProperty &ipRecv)
Callback to process a NEW bin_y request.
Definition: stdCamera.hpp:2425
std::string m_defaultReadoutSpeed
The default readout speed of the camera.
Definition: stdCamera.hpp:300
pcf::IndiProperty m_indiP_shutterStatus
State of the shutter. 0 = shut, 1 = open, -1 = unknown.
Definition: stdCamera.hpp:507
float m_expTime
The current exposure time, in seconds.
Definition: stdCamera.hpp:367
int setExpTime(const mx::meta::trueFalseT< true > &t)
Interface to setExpTime when the derivedT uses exposure time controls.
Definition: stdCamera.hpp:2062
std::string m_nextMode
The mode to be set by the next reconfiguration.
Definition: stdCamera.hpp:400
pcf::IndiProperty m_indiP_tempstat
Definition: stdCamera.hpp:326
int m_default_bin_x
Power-on ROI x binning.
Definition: stdCamera.hpp:454
int m_default_w
Power-on ROI width.
Definition: stdCamera.hpp:452
int setTempControl(const mx::meta::trueFalseT< true > &t)
Interface to setTempControl when the derivedT has temperature control.
Definition: stdCamera.hpp:1851
int newCallBack_roi_h(const pcf::IndiProperty &ipRecv)
Callback to process a NEW roi_h request.
Definition: stdCamera.hpp:2379
int recordCamera(bool force=false)
Definition: stdCamera.hpp:2953
bool m_cropMode
Status of crop mode ROIs, if enabled for this camera.
Definition: stdCamera.hpp:494
float m_maxExpTime
The maximum exposure time, used for INDI attributes.
Definition: stdCamera.hpp:364
float m_stepFPS
The FPS step size, used for INDI attributes.
Definition: stdCamera.hpp:372
int newCallBack_mode(const pcf::IndiProperty &ipRecv)
Callback to process a NEW mode request.
Definition: stdCamera.hpp:2190
int m_default_h
Power-on ROI height.
Definition: stdCamera.hpp:453
pcf::IndiProperty m_indiP_roi_last
Property used to trigger setting the last ROI.
Definition: stdCamera.hpp:485
pcf::IndiProperty m_indiP_temp
Definition: stdCamera.hpp:324
float m_expTimeSet
The exposure time, in seconds, as set by user.
Definition: stdCamera.hpp:368
pcf::IndiProperty m_indiP_roi_h
Property used to set the ROI height.
Definition: stdCamera.hpp:472
void setupConfig(mx::app::appConfigurator &config)
Setup the configuration system.
Definition: stdCamera.hpp:1035
int m_full_h
The full ROI height.
Definition: stdCamera.hpp:460
pcf::IndiProperty m_indiP_synchro
Definition: stdCamera.hpp:390
int m_full_bin_y
The y-binning in the full ROI.
Definition: stdCamera.hpp:462
int checkNextROI(const mx::meta::trueFalseT< true > &t)
Interface to checkNextROI when the derivedT uses ROIs.
Definition: stdCamera.hpp:2448
int setVShiftSpeed(const mx::meta::trueFalseT< true > &t)
Interface to setVShiftSpeed when the derivedT has vshift speed control.
Definition: stdCamera.hpp:1960
float m_full_y
The full ROI center y coordinate.
Definition: stdCamera.hpp:458
static int st_newCallBack_stdCamera(void *app, const pcf::IndiProperty &ipRecv)
The static callback function to be registered for stdCamera properties.
Definition: stdCamera.hpp:1749
float m_maxFPS
The maximum FPS, used for INDI attributes.
Definition: stdCamera.hpp:371
std::string m_readoutSpeedName
The current readout speed name.
Definition: stdCamera.hpp:337
float m_ccdTempSetpt
The desired temperature, in C.
Definition: stdCamera.hpp:315
bool m_tempControlStatus
Whether or not temperature control is active.
Definition: stdCamera.hpp:317
pcf::IndiProperty m_indiP_fps
Definition: stdCamera.hpp:379
int newCallBack_roi_last(const pcf::IndiProperty &ipRecv)
Callback to process a NEW roi_last request.
Definition: stdCamera.hpp:2657
pcf::IndiProperty m_indiP_roi_loadlast
Property used to trigger loading the last ROI as the target.
Definition: stdCamera.hpp:484
pcf::IndiProperty m_indiP_roi_w
Property used to set the ROI width.
Definition: stdCamera.hpp:471
int newCallBack_roi_set(const pcf::IndiProperty &ipRecv)
Callback to process a NEW roi_set request.
Definition: stdCamera.hpp:2503
pcf::IndiProperty m_indiP_roi_default
Property used to trigger setting the default and startup ROI.
Definition: stdCamera.hpp:486
int newCallBack_stdCamera(const pcf::IndiProperty &ipRecv)
The callback function for stdCamera properties.
Definition: stdCamera.hpp:1758
std::string m_modeName
The current mode name.
Definition: stdCamera.hpp:398
pcf::IndiProperty m_indiP_reconfig
Request switch which forces the framegrabber to go through the reconfigure process.
Definition: stdCamera.hpp:404
int setSynchro(const mx::meta::trueFalseT< true > &t)
Interface to setSynchro when the derivedT has synchronization.
Definition: stdCamera.hpp:2146
pcf::IndiProperty m_indiP_roi_bin_x
Property used to set the ROI x binning.
Definition: stdCamera.hpp:473
int newCallBack_roi_loadlast(const pcf::IndiProperty &ipRecv)
Callback to process a NEW roi_loadlast request.
Definition: stdCamera.hpp:2630
pcf::IndiProperty m_indiP_readoutSpeed
Definition: stdCamera.hpp:353
int setEMGain(const mx::meta::trueFalseT< true > &t)
Interface to setEMGain when the derivedT has EM Gain.
Definition: stdCamera.hpp:2020
int newCallBack_vShiftSpeed(const pcf::IndiProperty &ipRecv)
Callback to process a NEW vshift speed request.
Definition: stdCamera.hpp:1974
std::string m_startupMode
The camera mode to load during first init after a power-on.
Definition: stdCamera.hpp:296
pcf::IndiProperty m_indiP_roi_check
Property used to trigger checking the target ROI.
Definition: stdCamera.hpp:478
pcf::IndiProperty m_indiP_vShiftSpeed
Definition: stdCamera.hpp:354
int newCallBack_roi_check(const pcf::IndiProperty &ipRecv)
Callback to process a NEW roi_check request.
Definition: stdCamera.hpp:2462
int newCallBack_roi_x(const pcf::IndiProperty &ipRecv)
Callback to process a NEW roi_x request.
Definition: stdCamera.hpp:2310
float m_full_x
The full ROI center x coordinate.
Definition: stdCamera.hpp:457
float m_startupTemp
The temperature to set after a power-on. Set to <= -999 to not use [default].
Definition: stdCamera.hpp:298
int appLogic()
Application logic.
Definition: stdCamera.hpp:1539
int m_full_currbin_h
The current-binning full ROI height.
Definition: stdCamera.hpp:467
pcf::IndiProperty m_indiP_exptime
Definition: stdCamera.hpp:377
int newCallBack_shutter(const pcf::IndiProperty &ipRecv)
Callback to process a NEW shutter request.
Definition: stdCamera.hpp:2738
bool m_synchro
Status of synchronization, true is on, false is off.
Definition: stdCamera.hpp:388
std::string m_vShiftSpeedName
The current vshift speed name.
Definition: stdCamera.hpp:343
int newCallBack_roi_full(const pcf::IndiProperty &ipRecv)
Callback to process a NEW roi_full request.
Definition: stdCamera.hpp:2532
int setCropMode(const mx::meta::trueFalseT< true > &t)
Interface to setCropMode when the derivedT has crop mode.
Definition: stdCamera.hpp:2265
pcf::IndiProperty m_indiP_emGain
Definition: stdCamera.hpp:356
float m_ccdTemp
The current temperature, in C.
Definition: stdCamera.hpp:313
int updateINDI()
Update the INDI properties for this device controller.
Definition: stdCamera.hpp:2794
std::vector< std::string > m_vShiftSpeedNames
Definition: stdCamera.hpp:340
int newCallBack_fps(const pcf::IndiProperty &ipRecv)
Callback to process a NEW fps request.
Definition: stdCamera.hpp:2118
std::string m_defaultVShiftSpeed
The default readout speed of the camera.
Definition: stdCamera.hpp:301
int newCallBack_roi_y(const pcf::IndiProperty &ipRecv)
Callback to process a NEW roi_y request.
Definition: stdCamera.hpp:2333
pcf::IndiProperty m_indiP_tempcont
Definition: stdCamera.hpp:325
bool m_tempControlOnTarget
Whether or not the temperature control system is on its target temperature.
Definition: stdCamera.hpp:320
int createVShiftSpeed(const mx::meta::trueFalseT< true > &t)
Definition: stdCamera.hpp:1150
cameraConfigMap m_cameraModes
Map holding the possible camera mode configurations.
Definition: stdCamera.hpp:294
float m_stepExpTime
The maximum exposure time stepsize, used for INDI attributes.
Definition: stdCamera.hpp:365
void loadConfig(mx::app::appConfigurator &config)
load the configuration system results
Definition: stdCamera.hpp:1074
int whilePowerOff()
Actions while powered off.
Definition: stdCamera.hpp:1710
int setFPS(const mx::meta::trueFalseT< true > &t)
Interface to setFPS when the derivedT uses FPS controls.
Definition: stdCamera.hpp:2104
int newCallBack_reconfigure(const pcf::IndiProperty &ipRecv)
Callback to process a NEW reconfigure request.
Definition: stdCamera.hpp:2242
int newCallBack_emgain(const pcf::IndiProperty &ipRecv)
Callback to process a NEW EM gain request.
Definition: stdCamera.hpp:2034
float m_full_currbin_y
The current-binning full ROI center y coordinate.
Definition: stdCamera.hpp:465
int appStartup()
Startup function.
Definition: stdCamera.hpp:1175
int newCallBack_roi_bin_x(const pcf::IndiProperty &ipRecv)
Callback to process a NEW bin_x request.
Definition: stdCamera.hpp:2402
std::vector< std::string > m_vShiftSpeedNameLabels
Definition: stdCamera.hpp:341
int setTempSetPt(const mx::meta::trueFalseT< true > &t)
Interface to setTempSetPt when the derivedT has temperature control.
Definition: stdCamera.hpp:1807
pcf::IndiProperty m_indiP_roi_full
Property used to trigger setting the full ROI.
Definition: stdCamera.hpp:482
int newCallBack_synchro(const pcf::IndiProperty &ipRecv)
Callback to process a NEW synchro request.
Definition: stdCamera.hpp:2160
int newCallBack_roi_default(const pcf::IndiProperty &ipRecv)
Callback to process a NEW roi_default request.
Definition: stdCamera.hpp:2685
pcf::IndiProperty m_indiP_roi_set
Property used to trigger setting the ROI.
Definition: stdCamera.hpp:480
int appShutdown()
Application shutdown.
Definition: stdCamera.hpp:1742
pcf::IndiProperty m_indiP_shutter
Property used to control the shutter, a switch.
Definition: stdCamera.hpp:508
int newCallBack_roi_w(const pcf::IndiProperty &ipRecv)
Callback to process a NEW roi_w request.
Definition: stdCamera.hpp:2356
pcf::IndiProperty m_indiP_stateString
Definition: stdCamera.hpp:516
pcf::IndiProperty m_indiP_mode
Property used to report the current mode.
Definition: stdCamera.hpp:402
pcf::IndiProperty m_indiP_cropMode
Property used to toggle crop mode on and off.
Definition: stdCamera.hpp:497
float m_default_y
Power-on ROI center y coordinate.
Definition: stdCamera.hpp:451
int setNextROI(const mx::meta::trueFalseT< true > &t)
Interface to setNextROI when the derivedT uses ROIs.
Definition: stdCamera.hpp:2489
pcf::IndiProperty m_indiP_fullROI
Property used to preset the full ROI dimensions.
Definition: stdCamera.hpp:476
bool stateStringValid(const mx::meta::trueFalseT< true > &t)
Interface to stateStringValid when the derivedT provides it.
Definition: stdCamera.hpp:2780
float m_fps
The current FPS.
Definition: stdCamera.hpp:374
std::string stateString(const mx::meta::trueFalseT< true > &t)
Interface to stateString when the derivedT provides it.
Definition: stdCamera.hpp:2766
pcf::IndiProperty m_indiP_roi_bin_y
Property used to set the ROI y binning.
Definition: stdCamera.hpp:474
pcf::IndiProperty m_indiP_roi_x
Property used to set the ROI x center coordinate.
Definition: stdCamera.hpp:469
int newCallBack_roi_fullbin(const pcf::IndiProperty &ipRecv)
Callback to process a NEW roi_fullbin request.
Definition: stdCamera.hpp:2566
int newCallBack_temp_controller(const pcf::IndiProperty &ipRecv)
Callback to process a NEW CCD temp control request.
Definition: stdCamera.hpp:1865
int newCallBack_exptime(const pcf::IndiProperty &ipRecv)
Callback to process a NEW exposure time request.
Definition: stdCamera.hpp:2076
int setReadoutSpeed(const mx::meta::trueFalseT< true > &t)
Interface to setReadoutSpeed when the derivedT has readout speed control.
Definition: stdCamera.hpp:1900
int m_default_bin_y
Power-on ROI y binning.
Definition: stdCamera.hpp:455
bool m_tempControlStatusSet
Desired state of temperature control.
Definition: stdCamera.hpp:318
float m_minFPS
The minimum FPS, used for INDI attributes.
Definition: stdCamera.hpp:370
int onPowerOff()
Actions on power off.
Definition: stdCamera.hpp:1647
std::string m_readoutSpeedNameSet
The user requested readout speed name, to be set by derived()
Definition: stdCamera.hpp:338
~stdCamera() noexcept
Destructor.
Definition: stdCamera.hpp:1027
@ OPERATING
The device is operating, other than homing.
Definition: stateCodes.hpp:55
@ READY
The device is ready for operation, but is not operating.
Definition: stateCodes.hpp:56
@ NOTCONNECTED
The application is not connected to the device or service.
Definition: stateCodes.hpp:49
@ POWERON
The device power is on.
Definition: stateCodes.hpp:48
#define INDI_IDLE
Definition: indiUtils.hpp:28
#define INDI_BUSY
Definition: indiUtils.hpp:30
#define INDI_OK
Definition: indiUtils.hpp:29
std::unordered_map< std::string, cameraConfig > cameraConfigMap
Definition: stdCamera.hpp:48
int loadCameraConfig(cameraConfigMap &ccmap, mx::app::appConfigurator &config)
Load the camera configurations contained in the app configuration into a map.
Definition: stdCamera.cpp:18
std::string m_serialCommand
The command to send to the camera to place it in this mode.
Definition: stdCamera.hpp:34
std::string m_configFile
The file to use for this mode, e.g. an EDT configuration file.
Definition: stdCamera.hpp:33
A camera configuration.
Definition: stdCamera.hpp:32
void updateIfChanged(pcf::IndiProperty &p, const std::string &el, const T &newVal, indiDriverT *indiDriver, pcf::IndiProperty::PropertyStateType newState=pcf::IndiProperty::Ok)
Update the value of the INDI element, but only if it has changed.
Definition: indiUtils.hpp:95
void updateSelectionSwitchIfChanged(pcf::IndiProperty &p, const std::string &el, indiDriverT *indiDriver, pcf::IndiProperty::PropertyStateType newState=pcf::IndiProperty::Ok)
Update the values of a one-of-many INDI switch vector, but only if it has changed.
Definition: indiUtils.hpp:249
void updateSwitchIfChanged(pcf::IndiProperty &p, const std::string &el, const pcf::IndiElement::SwitchStateType &newVal, indiDriverT *indiDriver, pcf::IndiProperty::PropertyStateType newState=pcf::IndiProperty::Ok)
Update the value of the INDI element, but only if it has changed.
Definition: indiUtils.hpp:212
const pcf::IndiProperty & ipRecv
Definition: MagAOXApp.hpp:3434
std::unique_lock< std::mutex > lock(m_indiMutex)
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_ERROR
An error has occured which the software will attempt to correct.
Definition: logPriority.hpp:40
constexpr static logPrioT LOG_WARNING
A condition has occurred which may become an error, but the process continues.
Definition: logPriority.hpp:43
#define CAMCTRL_E_NOCONFIGS
Definition: stdCamera.hpp:26