API
 
Loading...
Searching...
No Matches
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
19namespace MagAOX
20{
21namespace app
22{
23namespace dev
24{
25
26#define CAMCTRL_E_NOCONFIGS (-10)
27
28/// A camera configuration
29/** a.k.a. a mode
30 */
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
48typedef std::unordered_map<std::string, cameraConfig> cameraConfigMap;
49
50///Load the camera configurations contained in the app configuration into a map
51int 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 */
285template<class derivedT>
287{
288protected:
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
435 int m_maxROIWidth {1024};
437
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
519public:
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
544protected:
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
554public:
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 */
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 */
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 */
625
626protected:
627
628
629 /** \name INDI
630 *
631 *@{
632 */
633public:
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 */
1008
1009 ///@}
1010
1011 /** \name Telemeter Interface
1012 * @{
1013 */
1014
1015 int recordCamera( bool force = false );
1016
1017 ///@}
1018
1019private:
1020 derivedT & derived()
1021 {
1022 return *static_cast<derivedT *>(this);
1023 }
1024};
1025
1026template<class derivedT>
1028{
1029 return;
1030}
1031
1032
1033
1034template<class derivedT>
1035void 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
1073template<class derivedT>
1074void 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
1123template<class derivedT>
1124int 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
1141template<class derivedT>
1142int stdCamera<derivedT>::createReadoutSpeed(const mx::meta::trueFalseT<0> & f)
1143{
1144 static_cast<void>(f);
1145
1146 return 0;
1147}
1148
1149template<class derivedT>
1150int 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
1166template<class derivedT>
1167int stdCamera<derivedT>::createVShiftSpeed(const mx::meta::trueFalseT<0> & f)
1168{
1169 static_cast<void>(f);
1170
1171 return 0;
1172}
1173
1174template<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
1538template<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
1646template<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
1709template<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
1741template<class derivedT>
1743{
1744 return 0;
1745}
1746
1747
1748template<class derivedT>
1750 const pcf::IndiProperty &ipRecv
1751 )
1752{
1753 derivedT * _app = static_cast<derivedT *>(app);
1754 return _app->newCallBack_stdCamera(ipRecv);
1755}
1756
1757template<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
1806template<class derivedT>
1807int stdCamera<derivedT>::setTempSetPt( const mx::meta::trueFalseT<true> & t)
1808{
1809 static_cast<void>(t);
1810 return derived().setTempSetPt();
1811}
1812
1813template<class derivedT>
1814int stdCamera<derivedT>::setTempSetPt( const mx::meta::trueFalseT<false> & f)
1815{
1816 static_cast<void>(f);
1817 return 0;
1818}
1819
1820template<class derivedT>
1821int 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
1850template<class derivedT>
1851int stdCamera<derivedT>::setTempControl( const mx::meta::trueFalseT<true> & t)
1852{
1853 static_cast<void>(t);
1854 return derived().setTempControl();
1855}
1856
1857template<class derivedT>
1858int stdCamera<derivedT>::setTempControl( const mx::meta::trueFalseT<false> & f)
1859{
1860 static_cast<void>(f);
1861 return 0;
1862}
1863
1864template<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
1899template<class derivedT>
1900int stdCamera<derivedT>::setReadoutSpeed( const mx::meta::trueFalseT<true> & t)
1901{
1902 static_cast<void>(t);
1903 return derived().setReadoutSpeed();
1904}
1905
1906template<class derivedT>
1907int stdCamera<derivedT>::setReadoutSpeed( const mx::meta::trueFalseT<false> & f)
1908{
1909 static_cast<void>(f);
1910 return 0;
1911}
1912
1913template<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
1959template<class derivedT>
1960int stdCamera<derivedT>::setVShiftSpeed( const mx::meta::trueFalseT<true> & t)
1961{
1962 static_cast<void>(t);
1963 return derived().setVShiftSpeed();
1964}
1965
1966template<class derivedT>
1967int stdCamera<derivedT>::setVShiftSpeed( const mx::meta::trueFalseT<false> & f)
1968{
1969 static_cast<void>(f);
1970 return 0;
1971}
1972
1973template<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
2019template<class derivedT>
2020int stdCamera<derivedT>::setEMGain( const mx::meta::trueFalseT<true> & t)
2021{
2022 static_cast<void>(t);
2023 return derived().setEMGain();
2024}
2025
2026template<class derivedT>
2027int stdCamera<derivedT>::setEMGain( const mx::meta::trueFalseT<false> & f)
2028{
2029 static_cast<void>(f);
2030 return 0;
2031}
2032
2033template<class derivedT>
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
2061template<class derivedT>
2062int stdCamera<derivedT>::setExpTime( const mx::meta::trueFalseT<true> & t)
2063{
2064 static_cast<void>(t);
2065 return derived().setExpTime();
2066}
2067
2068template<class derivedT>
2069int stdCamera<derivedT>::setExpTime( const mx::meta::trueFalseT<false> & f)
2070{
2071 static_cast<void>(f);
2072 return 0;
2073}
2074
2075template<class derivedT>
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
2103template<class derivedT>
2104int stdCamera<derivedT>::setFPS( const mx::meta::trueFalseT<true> & t)
2105{
2106 static_cast<void>(t);
2107 return derived().setFPS();
2108}
2109
2110template<class derivedT>
2111int stdCamera<derivedT>::setFPS( const mx::meta::trueFalseT<false> & f)
2112{
2113 static_cast<void>(f);
2114 return 0;
2115}
2116
2117template<class derivedT>
2118int 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
2145template<class derivedT>
2146int stdCamera<derivedT>::setSynchro( const mx::meta::trueFalseT<true> & t)
2147{
2148 static_cast<void>(t);
2149 return derived().setSynchro();
2150}
2151
2152template<class derivedT>
2153int stdCamera<derivedT>::setSynchro( const mx::meta::trueFalseT<false> & f)
2154{
2155 static_cast<void>(f);
2156 return 0;
2157}
2158
2159template<class derivedT>
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
2189template<class derivedT>
2190int 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
2241template<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
2264template<class derivedT>
2265int stdCamera<derivedT>::setCropMode( const mx::meta::trueFalseT<true> & t)
2266{
2267 static_cast<void>(t);
2268 return derived().setCropMode();
2269}
2270
2271template<class derivedT>
2272int stdCamera<derivedT>::setCropMode( const mx::meta::trueFalseT<false> & f)
2273{
2274 static_cast<void>(f);
2275 return 0;
2276}
2277
2278template<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?
2309template<class derivedT>
2310int 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
2332template<class derivedT>
2333int 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
2355template<class derivedT>
2356int 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
2378template<class derivedT>
2379int 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
2401template<class derivedT>
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
2424template<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
2447template<class derivedT>
2448int stdCamera<derivedT>::checkNextROI( const mx::meta::trueFalseT<true> & t)
2449{
2450 static_cast<void>(t);
2451 return derived().checkNextROI();
2452}
2453
2454template<class derivedT>
2455int stdCamera<derivedT>::checkNextROI( const mx::meta::trueFalseT<false> & f)
2456{
2457 static_cast<void>(f);
2458 return 0;
2459}
2460
2461template<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
2488template<class derivedT>
2489int stdCamera<derivedT>::setNextROI( const mx::meta::trueFalseT<true> & t)
2490{
2491 static_cast<void>(t);
2492 return derived().setNextROI();
2493}
2494
2495template<class derivedT>
2496int stdCamera<derivedT>::setNextROI( const mx::meta::trueFalseT<false> & f)
2497{
2498 static_cast<void>(f);
2499 return 0;
2500}
2501
2502template<class derivedT>
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
2531template<class derivedT>
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
2565template<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
2629template<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
2656template<class derivedT>
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
2684template<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
2718template<class derivedT>
2720 const mx::meta::trueFalseT<true> & t
2721 )
2722{
2723 static_cast<void>(t);
2724 return derived().setShutter(ss);
2725}
2726
2727template<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
2737template<class derivedT>
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
2765template<class derivedT>
2766std::string stdCamera<derivedT>::stateString( const mx::meta::trueFalseT<true> & t)
2767{
2768 static_cast<void>(t);
2769 return derived().stateString();
2770}
2771
2772template<class derivedT>
2773std::string stdCamera<derivedT>::stateString( const mx::meta::trueFalseT<false> & f)
2774{
2775 static_cast<void>(f);
2776 return "";
2777}
2778
2779template<class derivedT>
2780bool stdCamera<derivedT>::stateStringValid( const mx::meta::trueFalseT<true> & t)
2781{
2782 static_cast<void>(t);
2783 return derived().stateStringValid();
2784}
2785
2786template<class derivedT>
2787bool stdCamera<derivedT>::stateStringValid( const mx::meta::trueFalseT<false> & f)
2788{
2789 static_cast<void>(f);
2790 return false;
2791}
2792
2793template<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
2952template<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.
float m_maxEMGain
The configurable maximum EM gain. To be enforced in derivedT.
std::vector< std::string > m_readoutSpeedNames
float m_minExpTime
The minimum exposure time, used for INDI attributes.
pcf::IndiProperty m_indiP_roi_fullbin
Property used to trigger setting the full in current binning ROI.
float m_fpsSet
The commanded fps, as set by user.
int newCallBack_temp(const pcf::IndiProperty &ipRecv)
Callback to process a NEW CCD temp request.
int newCallBack_cropMode(const pcf::IndiProperty &ipRecv)
Callback to process a NEW cropMode request.
bool m_synchroSet
Target status of m_synchro.
pcf::IndiProperty m_indiP_roi_y
Property used to set the ROI x center coordinate.
int createReadoutSpeed(const mx::meta::trueFalseT< true > &t)
int m_full_currbin_w
The current-binning full ROI width.
int setShutter(int ss, const mx::meta::trueFalseT< true > &t)
Interface to setShutter when the derivedT has a shutter.
float m_default_x
Power-on ROI center x coordinate.
std::string m_tempControlStatusStr
Camera specific description of temperature control status.
float m_emGain
The camera's current EM gain (if available).
int m_full_bin_x
The x-binning in the full ROI.
int newCallBack_readoutSpeed(const pcf::IndiProperty &ipRecv)
Callback to process a NEW readout speed request.
std::vector< std::string > m_readoutSpeedNameLabels
float m_full_currbin_x
The current-binning full ROI center x coordinate.
int m_full_w
The full ROI width.
float m_emGainSet
The camera's EM gain, as set by the user.
std::string m_vShiftSpeedNameSet
The user requested vshift speed name, to be set by derived()
bool m_cropModeSet
Desired status of crop mode ROIs, if enabled for this camera.
int newCallBack_roi_bin_y(const pcf::IndiProperty &ipRecv)
Callback to process a NEW bin_y request.
std::string m_defaultReadoutSpeed
The default readout speed of the camera.
pcf::IndiProperty m_indiP_shutterStatus
State of the shutter. 0 = shut, 1 = open, -1 = unknown.
float m_expTime
The current exposure time, in seconds.
int setExpTime(const mx::meta::trueFalseT< true > &t)
Interface to setExpTime when the derivedT uses exposure time controls.
std::string m_nextMode
The mode to be set by the next reconfiguration.
pcf::IndiProperty m_indiP_tempstat
int m_default_bin_x
Power-on ROI x binning.
int m_default_w
Power-on ROI width.
int setTempControl(const mx::meta::trueFalseT< true > &t)
Interface to setTempControl when the derivedT has temperature control.
int newCallBack_roi_h(const pcf::IndiProperty &ipRecv)
Callback to process a NEW roi_h request.
int recordCamera(bool force=false)
bool m_cropMode
Status of crop mode ROIs, if enabled for this camera.
float m_maxExpTime
The maximum exposure time, used for INDI attributes.
float m_stepFPS
The FPS step size, used for INDI attributes.
int newCallBack_mode(const pcf::IndiProperty &ipRecv)
Callback to process a NEW mode request.
int m_default_h
Power-on ROI height.
pcf::IndiProperty m_indiP_roi_last
Property used to trigger setting the last ROI.
pcf::IndiProperty m_indiP_temp
float m_expTimeSet
The exposure time, in seconds, as set by user.
pcf::IndiProperty m_indiP_roi_h
Property used to set the ROI height.
void setupConfig(mx::app::appConfigurator &config)
Setup the configuration system.
int m_full_h
The full ROI height.
pcf::IndiProperty m_indiP_synchro
int m_full_bin_y
The y-binning in the full ROI.
int checkNextROI(const mx::meta::trueFalseT< true > &t)
Interface to checkNextROI when the derivedT uses ROIs.
int setVShiftSpeed(const mx::meta::trueFalseT< true > &t)
Interface to setVShiftSpeed when the derivedT has vshift speed control.
float m_full_y
The full ROI center y coordinate.
static int st_newCallBack_stdCamera(void *app, const pcf::IndiProperty &ipRecv)
The static callback function to be registered for stdCamera properties.
float m_maxFPS
The maximum FPS, used for INDI attributes.
std::string m_readoutSpeedName
The current readout speed name.
float m_ccdTempSetpt
The desired temperature, in C.
bool m_tempControlStatus
Whether or not temperature control is active.
pcf::IndiProperty m_indiP_fps
int newCallBack_roi_last(const pcf::IndiProperty &ipRecv)
Callback to process a NEW roi_last request.
pcf::IndiProperty m_indiP_roi_loadlast
Property used to trigger loading the last ROI as the target.
pcf::IndiProperty m_indiP_roi_w
Property used to set the ROI width.
int newCallBack_roi_set(const pcf::IndiProperty &ipRecv)
Callback to process a NEW roi_set request.
pcf::IndiProperty m_indiP_roi_default
Property used to trigger setting the default and startup ROI.
int newCallBack_stdCamera(const pcf::IndiProperty &ipRecv)
The callback function for stdCamera properties.
std::string m_modeName
The current mode name.
pcf::IndiProperty m_indiP_reconfig
Request switch which forces the framegrabber to go through the reconfigure process.
int setSynchro(const mx::meta::trueFalseT< true > &t)
Interface to setSynchro when the derivedT has synchronization.
pcf::IndiProperty m_indiP_roi_bin_x
Property used to set the ROI x binning.
int newCallBack_roi_loadlast(const pcf::IndiProperty &ipRecv)
Callback to process a NEW roi_loadlast request.
pcf::IndiProperty m_indiP_readoutSpeed
int setEMGain(const mx::meta::trueFalseT< true > &t)
Interface to setEMGain when the derivedT has EM Gain.
int newCallBack_vShiftSpeed(const pcf::IndiProperty &ipRecv)
Callback to process a NEW vshift speed request.
std::string m_startupMode
The camera mode to load during first init after a power-on.
pcf::IndiProperty m_indiP_roi_check
Property used to trigger checking the target ROI.
pcf::IndiProperty m_indiP_vShiftSpeed
int newCallBack_roi_check(const pcf::IndiProperty &ipRecv)
Callback to process a NEW roi_check request.
int newCallBack_roi_x(const pcf::IndiProperty &ipRecv)
Callback to process a NEW roi_x request.
float m_full_x
The full ROI center x coordinate.
float m_startupTemp
The temperature to set after a power-on. Set to <= -999 to not use [default].
int appLogic()
Application logic.
int m_full_currbin_h
The current-binning full ROI height.
pcf::IndiProperty m_indiP_exptime
int newCallBack_shutter(const pcf::IndiProperty &ipRecv)
Callback to process a NEW shutter request.
bool m_synchro
Status of synchronization, true is on, false is off.
std::string m_vShiftSpeedName
The current vshift speed name.
int newCallBack_roi_full(const pcf::IndiProperty &ipRecv)
Callback to process a NEW roi_full request.
int setCropMode(const mx::meta::trueFalseT< true > &t)
Interface to setCropMode when the derivedT has crop mode.
pcf::IndiProperty m_indiP_emGain
float m_ccdTemp
The current temperature, in C.
int updateINDI()
Update the INDI properties for this device controller.
std::vector< std::string > m_vShiftSpeedNames
int newCallBack_fps(const pcf::IndiProperty &ipRecv)
Callback to process a NEW fps request.
std::string m_defaultVShiftSpeed
The default readout speed of the camera.
int newCallBack_roi_y(const pcf::IndiProperty &ipRecv)
Callback to process a NEW roi_y request.
pcf::IndiProperty m_indiP_tempcont
bool m_tempControlOnTarget
Whether or not the temperature control system is on its target temperature.
int createVShiftSpeed(const mx::meta::trueFalseT< true > &t)
cameraConfigMap m_cameraModes
Map holding the possible camera mode configurations.
float m_stepExpTime
The maximum exposure time stepsize, used for INDI attributes.
void loadConfig(mx::app::appConfigurator &config)
load the configuration system results
int whilePowerOff()
Actions while powered off.
int setFPS(const mx::meta::trueFalseT< true > &t)
Interface to setFPS when the derivedT uses FPS controls.
int newCallBack_reconfigure(const pcf::IndiProperty &ipRecv)
Callback to process a NEW reconfigure request.
int newCallBack_emgain(const pcf::IndiProperty &ipRecv)
Callback to process a NEW EM gain request.
float m_full_currbin_y
The current-binning full ROI center y coordinate.
int appStartup()
Startup function.
int newCallBack_roi_bin_x(const pcf::IndiProperty &ipRecv)
Callback to process a NEW bin_x request.
std::vector< std::string > m_vShiftSpeedNameLabels
int setTempSetPt(const mx::meta::trueFalseT< true > &t)
Interface to setTempSetPt when the derivedT has temperature control.
pcf::IndiProperty m_indiP_roi_full
Property used to trigger setting the full ROI.
int newCallBack_synchro(const pcf::IndiProperty &ipRecv)
Callback to process a NEW synchro request.
int newCallBack_roi_default(const pcf::IndiProperty &ipRecv)
Callback to process a NEW roi_default request.
pcf::IndiProperty m_indiP_roi_set
Property used to trigger setting the ROI.
int appShutdown()
Application shutdown.
pcf::IndiProperty m_indiP_shutter
Property used to control the shutter, a switch.
int newCallBack_roi_w(const pcf::IndiProperty &ipRecv)
Callback to process a NEW roi_w request.
pcf::IndiProperty m_indiP_stateString
pcf::IndiProperty m_indiP_mode
Property used to report the current mode.
pcf::IndiProperty m_indiP_cropMode
Property used to toggle crop mode on and off.
float m_default_y
Power-on ROI center y coordinate.
int setNextROI(const mx::meta::trueFalseT< true > &t)
Interface to setNextROI when the derivedT uses ROIs.
pcf::IndiProperty m_indiP_fullROI
Property used to preset the full ROI dimensions.
bool stateStringValid(const mx::meta::trueFalseT< true > &t)
Interface to stateStringValid when the derivedT provides it.
float m_fps
The current FPS.
std::string stateString(const mx::meta::trueFalseT< true > &t)
Interface to stateString when the derivedT provides it.
pcf::IndiProperty m_indiP_roi_bin_y
Property used to set the ROI y binning.
pcf::IndiProperty m_indiP_roi_x
Property used to set the ROI x center coordinate.
int newCallBack_roi_fullbin(const pcf::IndiProperty &ipRecv)
Callback to process a NEW roi_fullbin request.
int newCallBack_temp_controller(const pcf::IndiProperty &ipRecv)
Callback to process a NEW CCD temp control request.
int newCallBack_exptime(const pcf::IndiProperty &ipRecv)
Callback to process a NEW exposure time request.
int setReadoutSpeed(const mx::meta::trueFalseT< true > &t)
Interface to setReadoutSpeed when the derivedT has readout speed control.
int m_default_bin_y
Power-on ROI y binning.
bool m_tempControlStatusSet
Desired state of temperature control.
float m_minFPS
The minimum FPS, used for INDI attributes.
int onPowerOff()
Actions on power off.
std::string m_readoutSpeedNameSet
The user requested readout speed name, to be set by derived()
~stdCamera() noexcept
Destructor.
@ OPERATING
The device is operating, other than homing.
@ READY
The device is ready for operation, but is not operating.
@ NOTCONNECTED
The application is not connected to the device or service.
@ POWERON
The device power is on.
#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.
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.
const pcf::IndiProperty & ipRecv
std::unique_lock< std::mutex > lock(m_indiMutex)
Definition dm.hpp:24
static constexpr logPrioT LOG_CRITICAL
The process can not continue and will shut down (fatal)
static constexpr logPrioT LOG_WARNING
A condition has occurred which may become an error, but the process continues.
static constexpr logPrioT LOG_ERROR
An error has occured which the software will attempt to correct.
#define CAMCTRL_E_NOCONFIGS
Definition stdCamera.hpp:26