API
 
Loading...
Searching...
No Matches
andorCtrl.hpp
Go to the documentation of this file.
1/** \file andorCtrl.hpp
2 * \brief The MagAO-X Andor EMCCD camera controller.
3 *
4 * \author Jared R. Males (jaredmales@gmail.com)
5 *
6 * \ingroup andorCtrl_files
7 */
8
9#ifndef andorCtrl_hpp
10#define andorCtrl_hpp
11
12#include "../../libMagAOX/libMagAOX.hpp" //Note this is included on command line to trigger pch
13#include "../../magaox_git_version.h"
14
15#include "atmcdLXd.h"
16
17namespace MagAOX
18{
19namespace app
20{
21
22std::string andorSDKErrorName(unsigned int error)
23{
24 switch(error)
25 {
26 case DRV_ERROR_CODES:
27 return "DRV_ERROR_CODES";
28 case DRV_SUCCESS:
29 return "DRV_SUCCESS";
30 case DRV_VXDNOTINSTALLED:
31 return "DRV_VXDNOTINSTALLED";
32 case DRV_ERROR_SCAN:
33 return "DRV_ERROR_SCAN";
34 case DRV_ERROR_CHECK_SUM:
35 return "DRV_ERROR_CHECK_SUM";
36 case DRV_ERROR_FILELOAD:
37 return "DRV_ERROR_FILELOAD";
38 case DRV_UNKNOWN_FUNCTION:
39 return "DRV_UNKNOWN_FUNCTION";
40 case DRV_ERROR_VXD_INIT:
41 return "DRV_ERROR_VXD_INIT";
42 case DRV_ERROR_ADDRESS:
43 return "DRV_ERROR_ADDRESS";
44 case DRV_ERROR_PAGELOCK:
45 return "DRV_ERROR_PAGELOCK";
46 case DRV_ERROR_PAGEUNLOCK:
47 return "DRV_ERROR_PAGEUNLOCK";
48 case DRV_ERROR_BOARDTEST:
49 return "DRV_ERROR_BOARDTEST";
50 case DRV_ERROR_ACK:
51 return "DRV_ERROR_ACK";
52 case DRV_ERROR_UP_FIFO:
53 return "DRV_ERROR_UP_FIFO";
54 case DRV_ERROR_PATTERN:
55 return "DRV_ERROR_PATTERN";
56 case DRV_ACQUISITION_ERRORS:
57 return "DRV_ACQUISITION_ERRORS";
58 case DRV_ACQ_BUFFER:
59 return "DRV_ACQ_BUFFER";
60 case DRV_ACQ_DOWNFIFO_FULL:
61 return "DRV_ACQ_DOWNFIFO_FULL";
62 case DRV_PROC_UNKONWN_INSTRUCTION:
63 return "DRV_PROC_UNKONWN_INSTRUCTION";
64 case DRV_ILLEGAL_OP_CODE:
65 return "DRV_ILLEGAL_OP_CODE";
66 case DRV_KINETIC_TIME_NOT_MET:
67 return "DRV_KINETIC_TIME_NOT_MET";
68 case DRV_ACCUM_TIME_NOT_MET:
69 return "DRV_ACCUM_TIME_NOT_MET";
70 case DRV_NO_NEW_DATA:
71 return "DRV_NO_NEW_DATA";
72 case DRV_SPOOLERROR:
73 return "DRV_SPOOLERROR";
74 case DRV_SPOOLSETUPERROR:
75 return "DRV_SPOOLSETUPERROR";
76 case DRV_FILESIZELIMITERROR:
77 return "DRV_FILESIZELIMITERROR";
78 case DRV_ERROR_FILESAVE:
79 return "DRV_ERROR_FILESAVE";
80 case DRV_TEMPERATURE_CODES:
81 return "DRV_TEMPERATURE_CODES";
82 case DRV_TEMPERATURE_OFF:
83 return "DRV_TEMPERATURE_OFF";
84 case DRV_TEMPERATURE_NOT_STABILIZED:
85 return "DRV_TEMPERATURE_NOT_STABILIZED";
86 case DRV_TEMPERATURE_STABILIZED:
87 return "DRV_TEMPERATURE_STABILIZED";
88 case DRV_TEMPERATURE_NOT_REACHED:
89 return "DRV_TEMPERATURE_NOT_REACHED";
90 case DRV_TEMPERATURE_OUT_RANGE:
91 return "DRV_TEMPERATURE_OUT_RANGE";
92 case DRV_TEMPERATURE_NOT_SUPPORTED:
93 return "DRV_TEMPERATURE_NOT_SUPPORTED";
94 case DRV_TEMPERATURE_DRIFT:
95 return "DRV_TEMPERATURE_DRIFT";
96 case DRV_GENERAL_ERRORS:
97 return "DRV_GENERAL_ERRORS";
98 case DRV_INVALID_AUX:
99 return "DRV_INVALID_AUX";
100 case DRV_COF_NOTLOADED:
101 return "DRV_COF_NOTLOADED";
102 case DRV_FPGAPROG:
103 return "DRV_FPGAPROG";
104 case DRV_FLEXERROR:
105 return "DRV_FLEXERROR";
106 case DRV_GPIBERROR:
107 return "DRV_GPIBERROR";
108 case DRV_EEPROMVERSIONERROR:
109 return "DRV_EEPROMVERSIONERROR";
110 case DRV_DATATYPE:
111 return "DRV_DATATYPE";
112 case DRV_DRIVER_ERRORS:
113 return "DRV_DRIVER_ERRORS";
114 case DRV_P1INVALID:
115 return "DRV_P1INVALID";
116 case DRV_P2INVALID:
117 return "DRV_P2INVALID";
118 case DRV_P3INVALID:
119 return "DRV_P3INVALID";
120 case DRV_P4INVALID:
121 return "DRV_P4INVALID";
122 case DRV_INIERROR:
123 return "DRV_INIERROR";
124 case DRV_COFERROR:
125 return "DRV_COFERROR";
126 case DRV_ACQUIRING:
127 return "DRV_ACQUIRING";
128 case DRV_IDLE:
129 return "DRV_IDLE";
130 case DRV_TEMPCYCLE:
131 return "DRV_TEMPCYCLE";
132 case DRV_NOT_INITIALIZED:
133 return "DRV_NOT_INITIALIZED";
134 case DRV_P5INVALID:
135 return "DRV_P5INVALID";
136 case DRV_P6INVALID:
137 return "DRV_P6INVALID";
138 case DRV_INVALID_MODE:
139 return "DRV_INVALID_MODE";
140 case DRV_INVALID_FILTER:
141 return "DRV_INVALID_FILTER";
142 case DRV_I2CERRORS:
143 return "DRV_I2CERRORS";
144 case DRV_I2CDEVNOTFOUND:
145 return "DRV_I2CDEVNOTFOUND";
146 case DRV_I2CTIMEOUT:
147 return "DRV_I2CTIMEOUT";
148 case DRV_P7INVALID:
149 return "DRV_P7INVALID";
150 case DRV_P8INVALID:
151 return "DRV_P8INVALID";
152 case DRV_P9INVALID:
153 return "DRV_P9INVALID";
154 case DRV_P10INVALID:
155 return "DRV_P10INVALID";
156 case DRV_P11INVALID:
157 return "DRV_P11INVALID";
158 case DRV_USBERROR:
159 return "DRV_USBERROR";
160 case DRV_IOCERROR:
161 return "DRV_IOCERROR";
162 case DRV_VRMVERSIONERROR:
163 return "DRV_VRMVERSIONERROR";
164 case DRV_GATESTEPERROR:
165 return "DRV_GATESTEPERROR";
166 case DRV_USB_INTERRUPT_ENDPOINT_ERROR:
167 return "DRV_USB_INTERRUPT_ENDPOINT_ERROR";
168 case DRV_RANDOM_TRACK_ERROR:
169 return "DRV_RANDOM_TRACK_ERROR";
170 case DRV_INVALID_TRIGGER_MODE:
171 return "DRV_INVALID_TRIGGER_MODE";
172 case DRV_LOAD_FIRMWARE_ERROR:
173 return "DRV_LOAD_FIRMWARE_ERROR";
174 case DRV_DIVIDE_BY_ZERO_ERROR:
175 return "DRV_DIVIDE_BY_ZERO_ERROR";
176 case DRV_INVALID_RINGEXPOSURES:
177 return "DRV_INVALID_RINGEXPOSURES";
178 case DRV_BINNING_ERROR:
179 return "DRV_BINNING_ERROR";
180 case DRV_INVALID_AMPLIFIER:
181 return "DRV_INVALID_AMPLIFIER";
182 case DRV_INVALID_COUNTCONVERT_MODE:
183 return "DRV_INVALID_COUNTCONVERT_MODE";
184 case DRV_USB_INTERRUPT_ENDPOINT_TIMEOUT:
185 return "DRV_USB_INTERRUPT_ENDPOINT_TIMEOUT";
186 case DRV_ERROR_NOCAMERA:
187 return "DRV_ERROR_NOCAMERA";
188 case DRV_NOT_SUPPORTED:
189 return "DRV_NOT_SUPPORTED";
190 case DRV_NOT_AVAILABLE:
191 return "DRV_NOT_AVAILABLE";
192 case DRV_ERROR_MAP:
193 return "DRV_ERROR_MAP";
194 case DRV_ERROR_UNMAP:
195 return "DRV_ERROR_UNMAP";
196 case DRV_ERROR_MDL:
197 return "DRV_ERROR_MDL";
198 case DRV_ERROR_UNMDL:
199 return "DRV_ERROR_UNMDL";
200 case DRV_ERROR_BUFFSIZE:
201 return "DRV_ERROR_BUFFSIZE";
202 case DRV_ERROR_NOHANDLE:
203 return "DRV_ERROR_NOHANDLE";
204 case DRV_GATING_NOT_AVAILABLE:
205 return "DRV_GATING_NOT_AVAILABLE";
206 case DRV_FPGA_VOLTAGE_ERROR:
207 return "DRV_FPGA_VOLTAGE_ERROR";
208 case DRV_OW_CMD_FAIL:
209 return "DRV_OW_CMD_FAIL";
210 case DRV_OWMEMORY_BAD_ADDR:
211 return "DRV_OWMEMORY_BAD_ADDR";
212 case DRV_OWCMD_NOT_AVAILABLE:
213 return "DRV_OWCMD_NOT_AVAILABLE";
214 case DRV_OW_NO_SLAVES:
215 return "DRV_OW_NO_SLAVES";
216 case DRV_OW_NOT_INITIALIZED:
217 return "DRV_OW_NOT_INITIALIZED";
218 case DRV_OW_ERROR_SLAVE_NUM:
219 return "DRV_OW_ERROR_SLAVE_NUM";
220 case DRV_MSTIMINGS_ERROR:
221 return "DRV_MSTIMINGS_ERROR";
222 case DRV_OA_NULL_ERROR:
223 return "DRV_OA_NULL_ERROR";
224 case DRV_OA_PARSE_DTD_ERROR:
225 return "DRV_OA_PARSE_DTD_ERROR";
226 case DRV_OA_DTD_VALIDATE_ERROR:
227 return "DRV_OA_DTD_VALIDATE_ERROR";
228 case DRV_OA_FILE_ACCESS_ERROR:
229 return "DRV_OA_FILE_ACCESS_ERROR";
230 case DRV_OA_FILE_DOES_NOT_EXIST:
231 return "DRV_OA_FILE_DOES_NOT_EXIST";
232 case DRV_OA_XML_INVALID_OR_NOT_FOUND_ERROR:
233 return "DRV_OA_XML_INVALID_OR_NOT_FOUND_ERROR";
234 case DRV_OA_PRESET_FILE_NOT_LOADED:
235 return "DRV_OA_PRESET_FILE_NOT_LOADED";
236 case DRV_OA_USER_FILE_NOT_LOADED:
237 return "DRV_OA_USER_FILE_NOT_LOADED";
238 case DRV_OA_PRESET_AND_USER_FILE_NOT_LOADED:
239 return "DRV_OA_PRESET_AND_USER_FILE_NOT_LOADED";
240 case DRV_OA_INVALID_FILE:
241 return "DRV_OA_INVALID_FILE";
242 case DRV_OA_FILE_HAS_BEEN_MODIFIED:
243 return "DRV_OA_FILE_HAS_BEEN_MODIFIED";
244 case DRV_OA_BUFFER_FULL:
245 return "DRV_OA_BUFFER_FULL";
246 case DRV_OA_INVALID_STRING_LENGTH:
247 return "DRV_OA_INVALID_STRING_LENGTH";
248 case DRV_OA_INVALID_CHARS_IN_NAME:
249 return "DRV_OA_INVALID_CHARS_IN_NAME";
250 case DRV_OA_INVALID_NAMING:
251 return "DRV_OA_INVALID_NAMING";
252 case DRV_OA_GET_CAMERA_ERROR:
253 return "DRV_OA_GET_CAMERA_ERROR";
254 case DRV_OA_MODE_ALREADY_EXISTS:
255 return "DRV_OA_MODE_ALREADY_EXISTS";
256 case DRV_OA_STRINGS_NOT_EQUAL:
257 return "DRV_OA_STRINGS_NOT_EQUAL";
258 case DRV_OA_NO_USER_DATA:
259 return "DRV_OA_NO_USER_DATA";
260 case DRV_OA_VALUE_NOT_SUPPORTED:
261 return "DRV_OA_VALUE_NOT_SUPPORTED";
262 case DRV_OA_MODE_DOES_NOT_EXIST:
263 return "DRV_OA_MODE_DOES_NOT_EXIST";
264 case DRV_OA_CAMERA_NOT_SUPPORTED:
265 return "DRV_OA_CAMERA_NOT_SUPPORTED";
266 case DRV_OA_FAILED_TO_GET_MODE:
267 return "DRV_OA_FAILED_TO_GET_MODE";
268 case DRV_OA_CAMERA_NOT_AVAILABLE:
269 return "DRV_OA_CAMERA_NOT_AVAILABLE";
270 case DRV_PROCESSING_FAILED:
271 return "DRV_PROCESSING_FAILED";
272 default:
273 return "UNKNOWN: " + std::to_string(error);
274 }
275}
276
277int readoutParams( int & newa,
278 int & newhss,
279 const std::string & ron
280 )
281{
282 if(ron == "ccd_00_08MHz")
283 {
284 newa = 1;
285 newhss = 2;
286 }
287 else if(ron == "ccd_01MHz")
288 {
289 newa = 1;
290 newhss = 1;
291 }
292 else if(ron == "ccd_03MHz")
293 {
294 newa = 1;
295 newhss = 0;
296 }
297 else if(ron == "emccd_01MHz")
298 {
299 newa = 0;
300 newhss = 3;
301 }
302 else if(ron == "emccd_05MHz")
303 {
304 newa = 0;
305 newhss = 2;
306 }
307 else if(ron == "emccd_10MHz")
308 {
309 newa = 0;
310 newhss = 1;
311 }
312 else if(ron == "emccd_17MHz")
313 {
314 newa = 0;
315 newhss = 0;
316 }
317 else
318 {
319 return -1;
320 }
321
322 return 0;
323}
324
325int vshiftParams( int & newvs,
326 const std::string & vssn,
327 float & vs
328 )
329{
330 if(vssn == "0_3us")
331 {
332 newvs = 0;
333 vs = 0.3;
334 return 0;
335 }
336 else if(vssn == "0_5us")
337 {
338 newvs = 1;
339 vs = 0.5;
340 return 0;
341 }
342 else if(vssn == "0_9us")
343 {
344 newvs = 2;
345 vs = 0.9;
346 return 0;
347 }
348 else if(vssn == "1_7us")
349 {
350 newvs = 3;
351 vs = 1.7;
352 return 0;
353 }
354 else if(vssn == "3_3us")
355 {
356 newvs = 4;
357 vs = 3.3;
358 return 0;
359 }
360 else
361 {
362 newvs = 0;
363 vs = 0.3;
364 return -1;
365 }
366}
367
368/** \defgroup andorCtrl Andor EMCCD Camera
369 * \brief Control of the Andor EMCCD Camera.
370 *
371 * <a href="../handbook/operating/software/apps/andorCtrl.html">Application Documentation</a>
372 *
373 * \ingroup apps
374 *
375 */
376
377/** \defgroup andorCtrl_files Andor EMCCD Camera Files
378 * \ingroup andorCtrl
379 */
380
381/** MagAO-X application to control the Andor EMCCD
382 *
383 * \ingroup andorCtrl
384 *
385 */
386class andorCtrl : public MagAOXApp<>, public dev::stdCamera<andorCtrl>, public dev::edtCamera<andorCtrl>,
387 public dev::frameGrabber<andorCtrl>, public dev::telemeter<andorCtrl>
388{
389
390 friend class dev::stdCamera<andorCtrl>;
391 friend class dev::edtCamera<andorCtrl>;
392 friend class dev::frameGrabber<andorCtrl>;
393 friend class dev::telemeter<andorCtrl>;
394
395public:
396 /** \name app::dev Configurations
397 *@{
398 */
399 static constexpr bool c_stdCamera_tempControl = true; ///< app::dev config to tell stdCamera to expose temperature controls
400
401 static constexpr bool c_stdCamera_temp = true; ///< app::dev config to tell stdCamera to expose temperature
402
403 static constexpr bool c_stdCamera_readoutSpeed = true; ///< app::dev config to tell stdCamera to expose readout speed controls
404
405 static constexpr bool c_stdCamera_vShiftSpeed = true; ///< app:dev config to tell stdCamera to expose vertical shift speed control
406 static constexpr bool c_stdCamera_fanSpeed = false; ///< app::dev config to tell stdCamera not to expose fan-speed control
407
408 static constexpr bool c_stdCamera_emGain = true; ///< app::dev config to tell stdCamera to expose EM gain controls
409
410 static constexpr bool c_stdCamera_exptimeCtrl = true; ///< app::dev config to tell stdCamera to expose exposure time controls
411
412 static constexpr bool c_stdCamera_fpsCtrl = false; ///< app::dev config to tell stdCamera to not expose FPS controls
413
414 static constexpr bool c_stdCamera_fps = true; ///< app::dev config to tell stdCamera not to expose FPS status
415
416 static constexpr bool c_stdCamera_synchro = false; ///< app::dev config to tell stdCamera to not expose synchro mode controls
417
418 static constexpr bool c_stdCamera_usesModes = false; ///< app:dev config to tell stdCamera not to expose mode controls
419
420 static constexpr bool c_stdCamera_usesROI = true; ///< app:dev config to tell stdCamera to expose ROI controls
421
422 static constexpr bool c_stdCamera_cropMode = true; ///< app:dev config to tell stdCamera to expose Crop Mode controls
423
424 static constexpr bool c_stdCamera_hasShutter = true; ///< app:dev config to tell stdCamera to expose shutter controls
425
426 static constexpr bool c_stdCamera_usesStateString = false; ///< app::dev confg to tell stdCamera to expose the state string property
427
428 static constexpr bool c_edtCamera_relativeConfigPath = false; ///< app::dev config to tell edtCamera to use absolute path to camera config file
429
430 static constexpr bool c_frameGrabber_flippable = false; ///< app:dev config to tell framegrabber this camera can not be flipped
431
432 ///@}
433
434protected:
435
436 /** \name configurable parameters
437 *@{
438 */
439
440
441
442
443 ///@}
444
445 std::string m_configFile; ///< The path, relative to configDir, where to write and read the temporary config file.
446
447 bool m_libInit {false}; ///< Whether or not the Andor SDK library is initialized.
448
449 bool m_poweredOn {false};
450
451public:
452
453 ///Default c'tor
454 andorCtrl();
455
456 ///Destructor
458
459 /// Setup the configuration system (called by MagAOXApp::setup())
460 virtual void setupConfig();
461
462 /// load the configuration system results (called by MagAOXApp::setup())
463 virtual void loadConfig();
464
465 /// Startup functions
466 /** Sets up the INDI vars.
467 *
468 */
469 virtual int appStartup();
470
471 /// Implementation of the FSM for the Siglent SDG
472 virtual int appLogic();
473
474 /// Implementation of the on-power-off FSM logic
475 virtual int onPowerOff();
476
477 /// Implementation of the while-powered-off FSM
479
480 /// Do any needed shutdown tasks. Currently nothing in this app.
481 virtual int appShutdown();
482
483 int cameraSelect();
484
485 int getTemp();
486
487 int getFPS();
488
489 int setFPS(float fps);
490
491 /// Set the output amplifier and readout speed
492 /** Sets according to stdCamera::m_readoutSpeedNameSet
493 */
494 int setReadoutSpeed();
495
496 /// Set the vertical shift speed
497 /** Sets according to std::Camera::m_vShiftSpeedNameSet
498 */
499 int setVShiftSpeed();
500
501 int getEMGain();
502
503 int setEMGain();
504
505 int setCropMode();
506
508
509 int setShutter( unsigned os);
510
511
512 int writeConfig();
513
514 /** \name stdCamera Interface
515 *
516 * @{
517 */
518
519 /// Set defaults for a power on state.
520 /**
521 * \returns 0 on success
522 * \returns -1 on error
523 */
524 int powerOnDefaults();
525
526 /// Turn temperature control on or off.
527 /** Sets temperature control on or off based on the current value of m_tempControlStatus
528 * \returns 0 on success
529 * \returns -1 on error
530 */
531 int setTempControl();
532
533 /// Set the CCD temperature setpoint [stdCamera interface].
534 /** Sets the temperature to m_ccdTempSetpt.
535 * \returns 0 on success
536 * \returns -1 on error
537 */
538 int setTempSetPt();
539
540 /// Required by stdCamera, but this does not do anything for this camera [stdCamera interface]
541 /**
542 * \returns 0 always
543 */
544 int setExpTime();
545
546 /// Check the next ROI
547 /** Checks if the target values are valid and adjusts them to the closest valid values if needed.
548 *
549 * \returns 0 if successfull
550 * \returns -1 otherwise
551 */
552 int checkNextROI();
553
554 /// Required by stdCamera, but this does not do anything for this camera [stdCamera interface]
555 /**
556 * \returns 0 always
557 */
558 int setNextROI();
559
560 ///@}
561
562
563
564 /** \name framegrabber Interface
565 *
566 * @{
567 */
568
570 float fps();
571 int startAcquisition();
573 int loadImageIntoStream(void * dest);
574 int reconfig();
575
576
577 //INDI:
579
580public:
581
582 /** \name Telemeter Interface
583 *
584 * @{
585 */
586 int checkRecordTimes();
587
589
590 ///@}
591};
592
593inline
595{
596 m_powerMgtEnabled = true;
597 m_powerOnWait = 10;
598
599 m_startupTemp = -45;
600
601 m_defaultReadoutSpeed = "emccd_17MHz";
602 m_readoutSpeedNames = {"ccd_00_08MHz", "ccd_01MHz", "ccd_03MHz", "emccd_01MHz", "emccd_05MHz", "emccd_10MHz", "emccd_17MHz"};
603 m_readoutSpeedNameLabels = {"CCD 0.08 MHz", "CCD 1 MHz", "CCD 3 MHz", "EMCCD 1 MHz", "EMCCD 5 MHz", "EMCCD 10 MHz", "EMCCD 17 MHz"};
604
605 m_defaultVShiftSpeed = "3_3us";
606 m_vShiftSpeedNames = {"0_3us", "0_5us", "0_9us", "1_7us", "3_3us"};
607 m_vShiftSpeedNameLabels = {"0.3 us", "0.5 us", "0.9 us", "1.7 us", "3.3 us"};
608
609 m_maxEMGain = 300;
610
611
612 m_default_x = 255.5;
613 m_default_y = 255.5;
614 m_default_w = 512;
615 m_default_h = 512;
616
621 m_nextROI.bin_x = 1;
622 m_nextROI.bin_y = 1;
623
624 m_full_x = 255.5;
625 m_full_y = 255.5;
626 m_full_w = 512;
627 m_full_h = 512;
628
629
630 return;
631}
632
633inline
635{
636 return;
637}
638
639inline
653
654inline
656{
658
659 m_configFile = "/tmp/andor_";
661 m_configFile += ".cfg";
662 m_cameraModes["onlymode"] = dev::cameraConfig({m_configFile, "", 255, 255, 512, 512, 1, 1, 1000});
663 m_startupMode = "onlymode";
664
665 if(writeConfig() < 0)
666 {
668 m_shutdown = true;
669 return;
670 }
671
673
674
675 if(m_maxEMGain < 1)
676 {
677 m_maxEMGain = 1;
678 log<text_log>("maxEMGain set to 1");
679 }
680
681 if(m_maxEMGain > 300)
682 {
683 m_maxEMGain = 300;
684 log<text_log>("maxEMGain set to 300");
685 }
686
688
690
691}
692
693inline
695{
697 {
699 }
700
702 {
704 }
705
707 {
709 }
710
712 {
713 return log<software_error,-1>({__FILE__,__LINE__});
714 }
715
717
718 return 0;
719
720}
721
722
723
724inline
726{
727 //run stdCamera's appLogic
729 {
730 return log<software_error, -1>({__FILE__, __LINE__});
731 }
732
733 //run edtCamera's appLogic
735 {
736 return log<software_error, -1>({__FILE__, __LINE__});
737 }
738
739 //run frameGrabber's appLogic to see if the f.g. thread has exited.
741 {
742 return log<software_error, -1>({__FILE__, __LINE__});
743 }
744
745 if( state() == stateCodes::POWERON)
746 {
747 return 0;
748 }
749
751 {
752 //Might have gotten here because of a power off.
753 if(m_powerState == 0) return 0;
754
755 int ret = cameraSelect();
756
757 if( ret != 0)
758 {
759 return log<software_critical,-1>({__FILE__, __LINE__});
760 }
761 }
762
764 {
765 sleep(30);
766 writeConfig();
767 m_shutterStatus = "READY";
768
770
771 if(m_poweredOn && m_ccdTempSetpt > -999)
772 {
773 m_poweredOn = false;
774 if(setTempSetPt() < 0)
775 {
776 if(powerState() != 1 || powerStateTarget() != 1) return 0;
778 }
779 }
780 }
781
783 {
784 //Get a lock if we can
785 std::unique_lock<std::mutex> lock(m_indiMutex, std::try_to_lock);
786
787 //but don't wait for it, just go back around.
788 if(!lock.owns_lock()) return 0;
789
790 if(getTemp() < 0)
791 {
792 if(m_powerState == 0) return 0;
793
795 return 0;
796 }
797
798 if(getFPS() < 0)
799 {
800 if(m_powerState == 0) return 0;
801
803 return 0;
804 }
805
806 if(getEMGain () < 0)
807 {
808 if(m_powerState == 0) return 0;
809
811 return 0;
812 }
813
815 {
818 return 0;
819 }
820
822 {
825 return 0;
826 }
827
829 {
832 return 0;
833 }
834
836 {
838 return 0;
839 }
840
841 }
842
843 //Fall through check?
844
845 return 0;
846
847}
848
849inline
851{
852 if(m_libInit)
853 {
854 ShutDown();
855 m_libInit = false;
856 }
857
859
860 std::lock_guard<std::mutex> lock(m_indiMutex);
861
862 m_shutterStatus = "POWEROFF";
863 m_shutterState = 0;
864
866 {
868 }
869
871 {
873 }
874
876 {
878 }
879
880 //Setting m_poweredOn
881 m_poweredOn = true;
882
883 return 0;
884}
885
886inline
888{
889 m_shutterStatus = "POWEROFF";
890 m_shutterState = 0;
891
893 {
895 }
896
898 {
900 }
901
902 return 0;
903}
904
905
906inline
908{
909 if(m_libInit)
910 {
911 ShutDown();
912 m_libInit = false;
913 }
914
916
918
919 return 0;
920}
921
922
923
924inline
926{
927 unsigned int error;
928
929 if(!m_libInit)
930 {
931 char path[] = "/usr/local/etc/andor/";
932 error = Initialize(path);
933
935 {
937 if(!stateLogged())
938 {
939 log<text_log>("No Andor USB camera found", logPrio::LOG_WARNING);
940 }
941
942 ShutDown();
943
944 //Not an error, appLogic should just go on.
945 return 0;
946 }
947 else if(error!=DRV_SUCCESS)
948 {
949 log<software_critical>({__FILE__, __LINE__, "ANDOR SDK initialization failed: " + andorSDKErrorName(error)});
950 ShutDown();
951 return -1;
952 }
953
954 m_libInit = true;
955 }
956
957 at_32 lNumCameras = 0;
959
960 if(error != DRV_SUCCESS)
961 {
962 log<software_critical>({__FILE__, __LINE__, "ANDOR SDK GetAvailableCameras failed: " + andorSDKErrorName(error)});
963 return -1;
964 }
965
966 if(lNumCameras < 1)
967 {
968 if(!stateLogged())
969 {
970 log<text_log>("No Andor cameras found after initialization", logPrio::LOG_WARNING);
971 }
973 return 0;
974 }
975
976 int iSelectedCamera = 0; //We're hard-coded for just one camera!
977
978 int serialNumber = 0;
980
981 if(error != DRV_SUCCESS)
982 {
983 log<software_critical>({__FILE__, __LINE__, "ANDOR SDK GetCameraSerialNumber failed: " + andorSDKErrorName(error)});
984 return -1;
985 }
986
987 log<text_log>(std::string("Found Andor USB Camera with serial number ") + std::to_string(serialNumber));
988
991
992 if(error != DRV_SUCCESS)
993 {
994 log<software_critical>({__FILE__, __LINE__, "ANDOR SDK GetCameraHandle failed: " + andorSDKErrorName(error)});
995 return -1;
996 }
997
999
1000 if(error != DRV_SUCCESS)
1001 {
1002 log<software_critical>({__FILE__, __LINE__, "ANDOR SDK SetCurrentCamera failed: " + andorSDKErrorName(error)});
1003 return -1;
1004 }
1005
1006 char name[MAX_PATH];
1007
1008 error = GetHeadModel(name);
1009 if(error != DRV_SUCCESS)
1010 {
1011 log<software_critical>({__FILE__, __LINE__, "ANDOR SDK GetHeadModel failed: " + andorSDKErrorName(error)});
1012 return -1;
1013 }
1014
1016 log<text_log>(std::string("Connected to ") + name + " with serial number " + std::to_string(serialNumber));
1017
1018 unsigned int eprom;
1019 unsigned int cofFile;
1020 unsigned int vxdRev;
1021 unsigned int vxdVer;
1022 unsigned int dllRev;
1023 unsigned int dllVer;
1025 if(error != DRV_SUCCESS)
1026 {
1027 log<software_critical>({__FILE__, __LINE__, "ANDOR SDK GetSoftwareVersion failed: " + andorSDKErrorName(error)});
1028 return -1;
1029 }
1030
1031 log<text_log>(std::string("eprom: ") + std::to_string(eprom));
1032 log<text_log>(std::string("cofFile: ") + std::to_string(cofFile));
1033 log<text_log>(std::string("vxd: ") + std::to_string(vxdVer) + "." + std::to_string(vxdRev));
1034 log<text_log>(std::string("dll: ") + std::to_string(dllVer) + "." + std::to_string(dllRev));
1035
1036 unsigned int PCB;
1037 unsigned int Decode;
1038 unsigned int dummy1;
1039 unsigned int dummy2;
1040 unsigned int CameraFirmwareVersion;
1041 unsigned int CameraFirmwareBuild;
1043 if(error != DRV_SUCCESS)
1044 {
1045 log<software_critical>({__FILE__, __LINE__, "ANDOR SDK GetHardwareVersion failed: " + andorSDKErrorName(error)});
1046 return -1;
1047 }
1048
1049 log<text_log>(std::string("PCB: ") + std::to_string(PCB));
1050 log<text_log>(std::string("Decode: ") + std::to_string(Decode));
1051 log<text_log>(std::string("f/w: ") + std::to_string(CameraFirmwareVersion) + "." + std::to_string(CameraFirmwareBuild));
1052
1053#if 0 //We don't normally need to do this, but keep here in case we want to check in the future
1054 int em_speeds;
1056 if(error != DRV_SUCCESS)
1057 {
1058 return log<software_error,-1>({__FILE__, __LINE__, std::string("Andor SDK Error from GetNumberHSSpeeds: ") + andorSDKErrorName(error)});
1059 }
1060
1061 std::cerr << "Number of EM HS speeds: " << em_speeds << "\n";
1062 for(int i=0; i< em_speeds; ++i)
1063 {
1064 float speed;
1065 error=GetHSSpeed(0,0,i, &speed);
1066 std::cerr << i << " " << speed << "\n";
1067 }
1068
1069 int conv_speeds;
1071 if(error != DRV_SUCCESS)
1072 {
1073 return log<software_error,-1>({__FILE__, __LINE__, std::string("Andor SDK Error from GetNumberHSSpeeds: ") + andorSDKErrorName(error)});
1074 }
1075
1076 std::cerr << "Number of Conventional HS speeds: " << conv_speeds << "\n";
1077 for(int i=0; i< conv_speeds; ++i)
1078 {
1079 float speed;
1080 error=GetHSSpeed(0,1,i, &speed);
1081 std::cerr << i << " " << speed << "\n";
1082 }
1083#endif
1084#if 0 //We don't normally need to do this, but keep here in case we want to check in the future
1085 int v_speeds;
1087 if(error != DRV_SUCCESS)
1088 {
1089 return log<software_error,-1>({__FILE__, __LINE__, std::string("Andor SDK Error from GetNumberVSSpeeds: ") + andorSDKErrorName(error)});
1090 }
1091
1092 std::cerr << "Number of VS speeds: " << v_speeds << "\n";
1093 for(int i=0; i< v_speeds; ++i)
1094 {
1095 float speed;
1096 error=GetVSSpeed(i, &speed);
1097 std::cerr << i << " " << speed << "\n";
1098 }
1099#endif
1100
1101
1102 //Initialize Shutter to SHUT
1103 int ss = 2;
1104 if(m_shutterState == 1) ss = 1;
1105 else m_shutterState = 0; //handles startup case
1106 error = SetShutter(1,ss,500,500);
1107 if(error != DRV_SUCCESS)
1108 {
1109 log<software_critical>({__FILE__, __LINE__, "ANDOR SDK SetShutter failed: " + andorSDKErrorName(error)});
1110 return -1;
1111 }
1112
1113 // Set CameraLink
1115 if(error != DRV_SUCCESS)
1116 {
1117 log<software_critical>({__FILE__, __LINE__, "ANDOR SDK SetCameraLinkMode failed: " + andorSDKErrorName(error)});
1118 return -1;
1119 }
1120
1121 //Set Read Mode to --Image--
1122 error = SetReadMode(4);
1123 if(error != DRV_SUCCESS)
1124 {
1125 return log<software_error,-1>({__FILE__, __LINE__, "Andor SDK Error from SetReadMode: " + andorSDKErrorName(error)});
1126 }
1127
1128 //Set Acquisition mode to --Run Till Abort--
1130 if(error != DRV_SUCCESS)
1131 {
1132 return log<software_error,-1>({__FILE__, __LINE__, "Andor SDK Error from SetAcquisitionMode: " + andorSDKErrorName(error)});
1133 }
1134
1135 //Set to frame transfer mode
1137 if(error != DRV_SUCCESS)
1138 {
1139 return log<software_error,-1>({__FILE__, __LINE__, "Andor SDK Error from SetFrameTransferMode: " + andorSDKErrorName(error)});
1140 }
1141
1142 //Set to real gain mode
1143 error = SetEMGainMode(3);
1144 if(error != DRV_SUCCESS)
1145 {
1146 return log<software_error,-1>({__FILE__, __LINE__, "Andor SDK Error from SetEMGainMode: " + andorSDKErrorName(error)});
1147 }
1148
1149 //Set default amplifier and speed
1152
1153 int newa;
1154 int newhss;
1155
1157 {
1158 return log<text_log,-1>("invalid default readout speed: " + m_readoutSpeedNameSet, logPrio::LOG_ERROR);
1159 }
1160
1161 // Set the HSSpeed to first index
1162 /* See page 284
1163 */
1165 if(error != DRV_SUCCESS)
1166 {
1167 return log<software_error,-1>({__FILE__, __LINE__, std::string("Andor SDK Error from SetHSSpeed: ") + andorSDKErrorName(error)});
1168 }
1169
1172
1173 int newvs;
1174 float vs;
1176 {
1177 return log<text_log,-1>("invalid default vert. shift speed: " + m_vShiftSpeedNameSet, logPrio::LOG_ERROR);
1178 }
1179
1180 // Set the VSSpeed to first index
1182 if(error != DRV_SUCCESS)
1183 {
1184 return log<software_error,-1>({__FILE__, __LINE__, std::string("Andor SDK Error from SetVSSpeed: ") + andorSDKErrorName(error)});
1185 }
1186
1187 m_vshiftSpeed = vs;
1188 // Set the amplifier
1189 /* See page 298
1190 */
1192 if(error != DRV_SUCCESS)
1193 {
1194 return log<software_error,-1>({__FILE__, __LINE__, std::string("Andor SDK Error from SetOutputAmplifier: ") + andorSDKErrorName(error)});
1195 }
1196
1197 //Set initial exposure time
1198 error = SetExposureTime(0.1);
1199 if(error != DRV_SUCCESS)
1200 {
1201 return log<software_error,-1>({__FILE__, __LINE__, "Andor SDK Error from SetExposureTime: " + andorSDKErrorName(error)});
1202 }
1203
1204 //Turn cooling on:
1205 if(m_ccdTempSetpt > -999)
1206 {
1207 error = CoolerON();
1208 if(error != DRV_SUCCESS)
1209 {
1210 log<software_critical,-1>({__FILE__, __LINE__, "ANDOR SDK CoolerON failed: " + andorSDKErrorName(error)});
1211 }
1212 m_tempControlStatus = true;
1213 m_tempControlStatusStr = "COOLING";
1214 log<text_log>("enabled temperature control");
1215 }
1216
1217 int nc;
1219 std::cout << "NumberADChannels: " << nc << "\n";
1220
1221 GetNumberAmp(&nc);
1222 std::cout << "NumberAmp; " << nc << "\n";
1223
1224 return 0;
1225
1226}
1227
1228inline
1230{
1231 //unsigned int error;
1232 //int temp_low {999}, temp_high {999};
1233 //error = GetTemperatureRange(&temp_low, &temp_high);
1234
1235 float temp = -999;
1236 unsigned int status = GetTemperatureF(&temp);
1237
1238 std::string cooling;
1239 switch(status)
1240 {
1242 m_tempControlStatusStr = "OFF";
1243 m_tempControlStatus = false;
1244 m_tempControlOnTarget = false;
1245 break;
1247 m_tempControlStatusStr = "STABILIZED";
1248 m_tempControlStatus = true;
1249 m_tempControlOnTarget = true;
1250 break;
1252 m_tempControlStatusStr = "COOLING";
1253 m_tempControlStatus = true;
1254 m_tempControlOnTarget = false;
1255 break;
1257 m_tempControlStatusStr = "NOT STABILIZED";
1258 m_tempControlStatus = true;
1259 m_tempControlOnTarget = false;
1260 break;
1262 m_tempControlStatusStr = "DRIFTING";
1263 m_tempControlStatus = true;
1264 m_tempControlOnTarget = false;
1265 break;
1266 default:
1267 m_tempControlStatusStr = "UNKOWN";
1268 m_tempControlStatus = false;
1269 m_tempControlOnTarget = false;
1270 m_ccdTemp = -999;
1271 log<software_error>({__FILE__, __LINE__, "ANDOR SDK GetTemperatureF:" + andorSDKErrorName(status)});
1272 return -1;
1273 }
1274
1275 m_ccdTemp = temp;
1276 recordCamera();
1277
1278 return 0;
1279
1280}
1281
1282inline
1284{
1285 unsigned int error;
1286 int gain;
1287
1288 error = GetEMCCDGain(&gain);
1289 if( error !=DRV_SUCCESS)
1290 {
1291 log<software_error>({__FILE__,__LINE__, "Andor SDK error from GetEMCCDGain: " + andorSDKErrorName(error)});
1292 return -1;
1293 }
1294
1295 if(gain == 0) gain = 1;
1296
1297 m_emGain = gain;
1298
1299 return 0;
1300}
1301
1302inline
1304{
1305 recordCamera(true);
1306 AbortAcquisition();
1308
1309 int newa;
1310 int newhss;
1311
1313 {
1314 return log<text_log,-1>("invalid readout speed: " + m_readoutSpeedNameSet);
1315 }
1316
1317 if(newa == 1 && m_cropMode)
1318 {
1319 log<text_log>("disabling crop mode for CCD readout", logPrio::LOG_NOTICE);
1320 m_cropModeSet = false;
1321 }
1322 // Set the HSSpeed to first index
1323 /* See page 284
1324 */
1325 unsigned int error = SetHSSpeed(newa,newhss);
1326 if(error != DRV_SUCCESS)
1327 {
1328 return log<software_error,-1>({__FILE__, __LINE__, std::string("Andor SDK Error from SetHSSpeed: ") + andorSDKErrorName(error)});
1329 }
1330
1331 // Set the amplifier
1332 /* See page 298
1333 */
1335 if(error != DRV_SUCCESS)
1336 {
1337 return log<software_error,-1>({__FILE__, __LINE__, std::string("Andor SDK Error from SetOutputAmplifier: ") + andorSDKErrorName(error)});
1338 }
1339
1340 log<text_log>("Set readout speed to " + m_readoutSpeedNameSet + " (" + std::to_string(newa) + "," + std::to_string(newhss) + ")");
1341
1342
1344
1346 m_reconfig = true;
1347
1348 return 0;
1349}
1350
1351
1352
1353inline
1355{
1356 recordCamera(true);
1357 AbortAcquisition();
1359
1360 int newvs;
1361 float vs;
1363 {
1364 return log<text_log,-1>("invalid vertical shift speed: " + m_vShiftSpeedNameSet);
1365 }
1366
1367 // Set the VSSpeed
1368 unsigned int error = SetVSSpeed(newvs);
1369 if(error != DRV_SUCCESS)
1370 {
1371 return log<software_error,-1>({__FILE__, __LINE__, std::string("Andor SDK Error from SetVSSpeed: ") + andorSDKErrorName(error)});
1372 }
1373
1374
1375 log<text_log>("Set vertical shift speed to " + m_vShiftSpeedNameSet + " (" + std::to_string(newvs) + ")");
1376
1377
1379 m_vshiftSpeed = vs;
1380
1382 m_reconfig = true;
1383
1384 return 0;
1385}
1386
1387inline
1389{
1390 int amp;
1391 int hss;
1392
1394
1395 if(amp != 0)
1396 {
1397 log<text_log>("Attempt to set EM gain while in conventional amplifier.", logPrio::LOG_NOTICE);
1398 return 0;
1399 }
1400
1401 int emg = m_emGainSet;
1402
1403 if(emg == 1) emg = 0;
1404
1405 if(emg < 0)
1406 {
1407 emg = 0;
1408 log<text_log>("EM gain limited to 0", logPrio::LOG_WARNING);
1409 }
1410
1411 if(emg > m_maxEMGain)
1412 {
1413 emg = m_maxEMGain;
1414 log<text_log>("EM gain limited to maxEMGain = " + std::to_string(emg), logPrio::LOG_WARNING);
1415 }
1416
1417 unsigned int error = SetEMCCDGain(emg);
1418 if( error !=DRV_SUCCESS)
1419 {
1420 log<software_error>({__FILE__,__LINE__, "Andor SDK error from SetEMCCDGain: " + andorSDKErrorName(error)});
1421 return -1;
1422 }
1423
1424 log<text_log>("Set EM Gain to: " + std::to_string(emg), logPrio::LOG_WARNING);
1425
1426 return 0;
1427}
1428
1429inline
1431{
1432 recordCamera(true);
1433 AbortAcquisition();
1435
1436 //Check if we're in the EMCCD amplifier
1437 if(m_cropModeSet == true)
1438 {
1439 int amp;
1440 int hss;
1441
1443
1444 if(amp == 1)
1445 {
1446 m_cropModeSet = false;
1447 log<text_log>("Can not set crop mode in CCD mode", logPrio::LOG_ERROR);
1448 }
1449 }
1450
1452 m_reconfig = true;
1453
1454 return 0;
1455}
1456
1457inline
1458int andorCtrl::setShutter( unsigned os )
1459{
1460 recordCamera(true);
1461 AbortAcquisition();
1463
1464 if(os == 0) //Shut
1465 {
1466 int error = SetShutter(1,2,500,500);
1467 if(error != DRV_SUCCESS)
1468 {
1469 return log<software_error, -1>({__FILE__, __LINE__, "ANDOR SDK SetShutter failed: " + andorSDKErrorName(error)});
1470 }
1471
1472 m_shutterState = 0;
1473 }
1474 else //Open
1475 {
1476 int error = SetShutter(1,1,500,500);
1477 if(error != DRV_SUCCESS)
1478 {
1479 return log<software_error, -1>({__FILE__, __LINE__, "ANDOR SDK SetShutter failed: " + andorSDKErrorName(error)});
1480 }
1481
1482 m_shutterState = 1;
1483 }
1484
1486 m_reconfig = true;
1487
1488 return 0;
1489}
1490
1491
1492
1493
1494
1495
1496inline
1498{
1499 std::string configFile = "/tmp/andor_";
1501 configFile += ".cfg";
1502
1503 std::ofstream fout;
1504 fout.open(configFile);
1505
1506 if(fout.fail())
1507 {
1508 log<software_error>({__FILE__, __LINE__, "error opening config file for writing"});
1509 return -1;
1510 }
1511
1512 int w = m_nextROI.w / m_nextROI.bin_x;
1513 int h = m_nextROI.h / m_nextROI.bin_y;
1514
1515 fout << "camera_class: \"Andor\"\n";
1516 fout << "camera_model: \"iXon Ultra 897\"\n";
1517 fout << "camera_info: \"512x512 (1-tap, freerun)\"\n";
1518 fout << "width: " << w << "\n";
1519 fout << "height: " << h << "\n";
1520 fout << "depth: 16\n";
1521 fout << "extdepth: 16\n";
1522 fout << "CL_DATA_PATH_NORM: 0f # single tap\n";
1523 fout << "CL_CFG_NORM: 02\n";
1524
1525 fout.close();
1526
1527 return 0;
1528
1529}
1530//------------------------------------------------------------------------
1531//----------------------- stdCamera interface ---------------------------
1532//------------------------------------------------------------------------
1533
1534inline
1536{
1537 //Camera boots up with this true in most cases.
1538 m_tempControlStatus = false;
1539 m_tempControlStatusSet = false;
1540 m_tempControlStatusStr = "OFF";
1541 m_tempControlOnTarget = false;
1542
1549
1554 m_nextROI.bin_x = m_default_bin_x;
1555 m_nextROI.bin_y = m_default_bin_y;
1556
1557 return 0;
1558}
1559
1560inline
1562{
1564 {
1565 unsigned int error = CoolerON();
1566 if(error != DRV_SUCCESS)
1567 {
1568 log<software_critical>({__FILE__, __LINE__, "ANDOR SDK CoolerON failed: " + andorSDKErrorName(error)});
1569 return -1;
1570 }
1571 m_tempControlStatus = true;
1572 m_tempControlStatusStr = "COOLING";
1573 recordCamera();
1574 log<text_log>("enabled temperature control");
1575 return 0;
1576 }
1577 else
1578 {
1579 unsigned int error = CoolerOFF();
1580 if(error != DRV_SUCCESS)
1581 {
1582 log<software_critical>({__FILE__, __LINE__, "ANDOR SDK CoolerOFF failed: " + andorSDKErrorName(error)});
1583 return -1;
1584 }
1585 m_tempControlStatus = false;
1586 m_tempControlStatusStr = "OFF";
1587 recordCamera();
1588 log<text_log>("disabled temperature control");
1589 return 0;
1590 }
1591}
1592
1593inline
1595{
1596 int temp = m_ccdTempSetpt + 0.5;
1597
1598 unsigned int error = SetTemperature(temp);
1599
1600 if(error != DRV_SUCCESS)
1601 {
1602 log<software_critical>({__FILE__, __LINE__, "ANDOR SDK setTemperature failed: " + andorSDKErrorName(error)});
1603 return -1;
1604 }
1605
1606 return 0;
1607
1608}
1609
1610inline
1612{
1613 float exptime;
1614 float accumCycletime;
1615 float kinCycletime;
1616
1617 unsigned int error = GetAcquisitionTimings(&exptime, &accumCycletime, &kinCycletime);
1618 if(error != DRV_SUCCESS)
1619 {
1620 return log<software_error,-1>({__FILE__, __LINE__, "ANDOR SDK error from GetAcquisitionTimings: " + andorSDKErrorName(error)});
1621 }
1622
1623 m_expTime = exptime;
1624
1625 float readoutTime;
1627 if(error != DRV_SUCCESS)
1628 {
1629 return log<software_error,-1>({__FILE__, __LINE__, "ANDOR SDK error from GetReadOutTime: " + andorSDKErrorName(error)});
1630 }
1631
1632 m_fps = 1.0/accumCycletime;
1633
1634 return 0;
1635
1636}
1637
1638inline
1640{
1641 recordCamera(true);
1642 AbortAcquisition();
1644
1645 unsigned int error = SetExposureTime(m_expTimeSet);
1646 if(error != DRV_SUCCESS)
1647 {
1648 log<software_critical>({__FILE__, __LINE__, "ANDOR SDK SetExposureTime failed: " + andorSDKErrorName(error)});
1649 return -1;
1650 }
1652 m_reconfig = true;
1653 return 0;
1654}
1655
1656inline
1658{
1659 return 0;
1660}
1661
1662inline
1664{
1665 recordCamera(true);
1666 AbortAcquisition();
1668
1670 m_reconfig = true;
1671
1672 updateSwitchIfChanged(m_indiP_roi_set, "request", pcf::IndiElement::Off, INDI_IDLE);
1673
1674 return 0;
1675}
1676
1677//------------------------------------------------------------------------
1678//------------------- framegrabber interface ---------------------------
1679//------------------------------------------------------------------------
1680
1681inline
1683{
1684 //lock mutex
1685 std::unique_lock<std::mutex> lock(m_indiMutex);
1686
1687 unsigned int error;
1688
1689 int status;
1690 error = GetStatus(&status);
1691 if(error != DRV_SUCCESS)
1692 {
1694 return log<software_error,-1>({__FILE__, __LINE__, "Andor SDK Error from GetStatus: " + andorSDKErrorName(error)});
1695 }
1696
1697 if(status != DRV_IDLE)
1698 {
1699 return 0;
1700 }
1701
1702 int x0 = (m_nextROI.x - 0.5*(m_nextROI.w - 1)) + 1;
1703 int y0 = (m_nextROI.y - 0.5*(m_nextROI.h - 1)) + 1;
1704
1705 if(m_cropModeSet)
1706 {
1708
1709 error = SetIsolatedCropModeEx(1, m_nextROI.h, m_nextROI.w, m_nextROI.bin_y, m_nextROI.bin_x, x0, y0);
1710
1711 if(error != DRV_SUCCESS)
1712 {
1713 if(error == DRV_P2INVALID)
1714 {
1715 log<text_log>(std::string("crop mode invalid height: ") + std::to_string(m_nextROI.h), logPrio::LOG_ERROR);
1716 }
1717 else if(error == DRV_P3INVALID)
1718 {
1719 log<text_log>(std::string("crop mode invalid width: ") + std::to_string(m_nextROI.w), logPrio::LOG_ERROR);
1720 }
1721 else if(error == DRV_P4INVALID)
1722 {
1723 log<text_log>(std::string("crop mode invalid y binning: ") + std::to_string(m_nextROI.bin_y), logPrio::LOG_ERROR);
1724 }
1725 else if(error == DRV_P5INVALID)
1726 {
1727 log<text_log>(std::string("crop mode invalid x binning: ") + std::to_string(m_nextROI.bin_x), logPrio::LOG_ERROR);
1728 }
1729 else if(error == DRV_P6INVALID)
1730 {
1731 log<text_log>(std::string("crop mode invalid x center: ") + std::to_string(m_nextROI.x) + "/" + std::to_string(x0), logPrio::LOG_ERROR);
1732 }
1733 else if(error == DRV_P7INVALID)
1734 {
1735 log<text_log>(std::string("crop mode invalid y center: ") + std::to_string(m_nextROI.y) + "/" + std::to_string(y0), logPrio::LOG_ERROR);
1736 }
1737 else
1738 {
1739 log<software_error>({__FILE__, __LINE__, "Andor SDK Error from SetIsolatedCropModeEx: " + andorSDKErrorName(error)});
1740 }
1741
1742 m_nextROI.x = m_currentROI.x;
1743 m_nextROI.y = m_currentROI.y;
1744 m_nextROI.w = m_currentROI.w;
1745 m_nextROI.h = m_currentROI.h;
1746 m_nextROI.bin_x = m_currentROI.bin_x;
1747 m_nextROI.bin_y = m_currentROI.bin_y;
1748
1750
1752 return -1;
1753 }
1754
1755 //Set low-latency crop mode
1757 if(error != DRV_SUCCESS)
1758 {
1759 log<software_error>({__FILE__, __LINE__, "SetIsolatedCropModeType: " + andorSDKErrorName(error)});
1760 }
1761 }
1762 else
1763 {
1765
1766 error = SetIsolatedCropModeEx(0, m_nextROI.h, m_nextROI.w, m_nextROI.bin_y, m_nextROI.bin_x, x0, y0);
1767 if(error != DRV_SUCCESS)
1768 {
1769 log<software_error>({__FILE__, __LINE__, "SetIsolatedCropModeEx(0,): " + andorSDKErrorName(error)});
1770 }
1771
1772 //Setup Image dimensions
1773 /* SetImage(int hbin, int vbin, int hstart, int hend, int vstart, int vend)
1774 * hbin: number of pixels to bin horizontally
1775 * vbin: number of pixels to bin vertically
1776 * hstart: Starting Column (inclusive)
1777 * hend: End column (inclusive)
1778 * vstart: Start row (inclusive)
1779 * vend: End row (inclusive)
1780 */
1781 error = SetImage(m_nextROI.bin_x, m_nextROI.bin_y, x0, x0 + m_nextROI.w - 1, y0, y0 + m_nextROI.h - 1);
1782 if(error != DRV_SUCCESS)
1783 {
1784 if(error == DRV_P1INVALID)
1785 {
1786 log<text_log>(std::string("invalid x-binning: ") + std::to_string(m_nextROI.bin_x), logPrio::LOG_ERROR);
1787 }
1788 else if(error == DRV_P2INVALID)
1789 {
1790 log<text_log>(std::string("invalid y-binning: ") + std::to_string(m_nextROI.bin_y), logPrio::LOG_ERROR);
1791 }
1792 else if(error == DRV_P3INVALID)
1793 {
1794 log<text_log>(std::string("invalid x-center: ") + std::to_string(m_nextROI.x) + "/" + std::to_string(x0), logPrio::LOG_ERROR);
1795 }
1796 else if(error == DRV_P4INVALID)
1797 {
1798 log<text_log>(std::string("invalid width: ") + std::to_string(m_nextROI.w), logPrio::LOG_ERROR);
1799 }
1800 else if(error == DRV_P5INVALID)
1801 {
1802 log<text_log>(std::string("invalid y-center: ") + std::to_string(m_nextROI.y) + "/" + std::to_string(y0), logPrio::LOG_ERROR);
1803 }
1804 else if(error == DRV_P6INVALID)
1805 {
1806 log<text_log>(std::string("invalid height: ") + std::to_string(m_nextROI.h), logPrio::LOG_ERROR);
1807 }
1808 else
1809 {
1810 log<software_error>({__FILE__, __LINE__, "Andor SDK Error from SetImage: " + andorSDKErrorName(error)});
1811 }
1812
1813 m_nextROI.x = m_currentROI.x;
1814 m_nextROI.y = m_currentROI.y;
1815 m_nextROI.w = m_currentROI.w;
1816 m_nextROI.h = m_currentROI.h;
1817 m_nextROI.bin_x = m_currentROI.bin_x;
1818 m_nextROI.bin_y = m_currentROI.bin_y;
1819
1821
1823 return -1;
1824 }
1825
1826
1827 }
1828
1829 m_currentROI.bin_x = m_nextROI.bin_x;
1830 m_currentROI.bin_y = m_nextROI.bin_y;
1831 m_currentROI.x = x0 - 1.0 + 0.5*(m_nextROI.w - 1);
1832 m_currentROI.y = y0 - 1.0 + 0.5*(m_nextROI.h - 1);
1833 m_currentROI.w = m_nextROI.w;
1834 m_currentROI.h = m_nextROI.h;
1835
1842
1843 //We also update target to the settable values
1844 m_nextROI.x = m_currentROI.x;
1845 m_nextROI.y = m_currentROI.y;
1846 m_nextROI.w = m_currentROI.w;
1847 m_nextROI.h = m_currentROI.h;
1848 m_nextROI.bin_x = m_currentROI.bin_x;
1849 m_nextROI.bin_y = m_currentROI.bin_y;
1850
1857
1858
1859 ///\todo This should check whether we have a match between EDT and the camera right?
1863
1864
1865 // Print Detector Frame Size
1866 //std::cout << "Detector Frame is: " << width << "x" << height << "\n";
1867
1868 recordCamera(true);
1869
1870 return 0;
1871}
1872
1873inline
1875{
1876 return m_fps;
1877}
1878
1879inline
1881{
1882 unsigned int error;
1883 int status;
1884 error = GetStatus(&status);
1885 if(error != DRV_SUCCESS)
1886 {
1888 return log<software_error,-1>({__FILE__, __LINE__, "Andor SDK Error from GetStatus: " + andorSDKErrorName(error)});
1889 }
1890
1891 if(status != DRV_IDLE)
1892 {
1894 return 0;
1895 }
1896
1898 if(error != DRV_SUCCESS)
1899 {
1901 return log<software_error,-1>({__FILE__, __LINE__, "Andor SDK Error from StartAcquisition: " + andorSDKErrorName(error)});
1902 }
1903
1905 recordCamera();
1906
1907 sleep(1); //make sure camera is rully running before we try to synch with it.
1908
1910}
1911
1912inline
1918
1919inline
1921{
1923
1924 return 0;
1925 }
1926
1927inline
1929{
1930 //lock mutex
1931 //std::unique_lock<std::mutex> lock(m_indiMutex);
1932 recordCamera(true);
1933 AbortAcquisition();
1935
1936 writeConfig();
1937
1939 if(rv < 0) return rv;
1940
1942
1944 return 0;
1945}
1946
1947inline
1952
1953inline
1955{
1956 return recordCamera(true);
1957}
1958
1959}//namespace app
1960} //namespace MagAOX
1961#endif
The base-class for XWCTk applications.
void updateIfChanged(pcf::IndiProperty &p, const std::string &el, const T &newVal, pcf::IndiProperty::PropertyStateType ipState=pcf::IndiProperty::Ok)
Update an INDI property element value if it has changed.
stateCodes::stateCodeT state()
Get the current state code.
int powerState()
Returns the current power state.
int m_shutdown
Flag to signal it's time to shutdown. When not 0, the main loop exits.
int m_powerState
Current power state, 1=On, 0=Off, -1=Unk.
int powerStateTarget()
Returns the target power state.
void updateSwitchIfChanged(pcf::IndiProperty &p, const std::string &el, const pcf::IndiElement::SwitchStateType &newVal, pcf::IndiProperty::PropertyStateType ipState=pcf::IndiProperty::Ok)
Update an INDI switch element value if it has changed.
int stateLogged()
Updates and returns the value of m_stateLogged. Will be 0 on first call after a state change,...
static int log(const typename logT::messageT &msg, logPrioT level=logPrio::LOG_DEFAULT)
Make a log entry.
unsigned long m_powerOnWait
Default time in sec to wait for device to boot after power on.
std::mutex m_indiMutex
Mutex for locking INDI communications.
std::string configName()
Get the config name.
int setTempSetPt()
Set the CCD temperature setpoint [stdCamera interface].
andorCtrl()
Default c'tor.
int checkNextROI()
Check the next ROI.
~andorCtrl() noexcept
Destructor.
int setFPS(float fps)
static constexpr bool c_stdCamera_fps
app::dev config to tell stdCamera not to expose FPS status
virtual void setupConfig()
Setup the configuration system (called by MagAOXApp::setup())
virtual void loadConfig()
load the configuration system results (called by MagAOXApp::setup())
static constexpr bool c_stdCamera_fanSpeed
app::dev config to tell stdCamera not to expose fan-speed control
static constexpr bool c_stdCamera_temp
app::dev config to tell stdCamera to expose temperature
virtual int appShutdown()
Do any needed shutdown tasks. Currently nothing in this app.
int setReadoutSpeed()
Set the output amplifier and readout speed.
static constexpr bool c_stdCamera_usesStateString
app::dev confg to tell stdCamera to expose the state string property
virtual int whilePowerOff()
Implementation of the while-powered-off FSM.
int setTempControl()
Turn temperature control on or off.
static constexpr bool c_stdCamera_cropMode
app:dev config to tell stdCamera to expose Crop Mode controls
virtual int appLogic()
Implementation of the FSM for the Siglent SDG.
static constexpr bool c_stdCamera_exptimeCtrl
app::dev config to tell stdCamera to expose exposure time controls
static constexpr bool c_frameGrabber_flippable
app:dev config to tell framegrabber this camera can not be flipped
int setExpTime()
Required by stdCamera, but this does not do anything for this camera [stdCamera interface].
int setNextROI()
Required by stdCamera, but this does not do anything for this camera [stdCamera interface].
int setShutter(unsigned os)
int powerOnDefaults()
Set defaults for a power on state.
static constexpr bool c_stdCamera_usesROI
app:dev config to tell stdCamera to expose ROI controls
static constexpr bool c_stdCamera_readoutSpeed
app::dev config to tell stdCamera to expose readout speed controls
static constexpr bool c_stdCamera_vShiftSpeed
app:dev config to tell stdCamera to expose vertical shift speed control
int loadImageIntoStream(void *dest)
static constexpr bool c_stdCamera_emGain
app::dev config to tell stdCamera to expose EM gain controls
bool m_libInit
Whether or not the Andor SDK library is initialized.
virtual int appStartup()
Startup functions.
virtual int onPowerOff()
Implementation of the on-power-off FSM logic.
std::string m_configFile
The path, relative to configDir, where to write and read the temporary config file.
static constexpr bool c_edtCamera_relativeConfigPath
app::dev config to tell edtCamera to use absolute path to camera config file
static constexpr bool c_stdCamera_synchro
app::dev config to tell stdCamera to not expose synchro mode controls
static constexpr bool c_stdCamera_tempControl
app::dev config to tell stdCamera to expose temperature controls
static constexpr bool c_stdCamera_usesModes
app:dev config to tell stdCamera not to expose mode controls
static constexpr bool c_stdCamera_fpsCtrl
app::dev config to tell stdCamera to not expose FPS controls
int recordTelem(const telem_stdcam *)
int setVShiftSpeed()
Set the vertical shift speed.
static constexpr bool c_stdCamera_hasShutter
app:dev config to tell stdCamera to expose shutter controls
MagAO-X EDT framegrabber interface.
Definition edtCamera.hpp:55
u_char * m_image_p
The image data grabbed.
Definition edtCamera.hpp:75
void setupConfig(mx::app::appConfigurator &config)
Setup the configuration system.
void loadConfig(mx::app::appConfigurator &config)
load the configuration system results
timespec m_currImageTimestamp
The timestamp of the current image.
uint32_t m_width
The width of the image, once deinterlaced etc.
int appShutdown()
Shuts down the framegrabber thread.
int loadConfig(mx::app::appConfigurator &config)
load the configuration system results
size_t m_typeSize
The size of the type, in bytes. Result of sizeof.
uint8_t m_dataType
The ImageStreamIO type code.
bool m_reconfig
Flag to set if a camera reconfiguration requires a framegrabber reset.
uint32_t m_height
The height of the image, once deinterlaced etc.
int setupConfig(mx::app::appConfigurator &config)
Setup the configuration system.
MagAO-X standard camera interface.
float m_maxEMGain
The configurable maximum EM gain. To be enforced in derivedT.
std::vector< std::string > m_readoutSpeedNames
pcf::IndiProperty m_indiP_roi_y
Property used to set the ROI x center coordinate.
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).
std::vector< std::string > m_readoutSpeedNameLabels
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.
std::string m_defaultReadoutSpeed
The default readout speed of the camera.
float m_expTime
The current exposure time, in seconds.
std::string m_nextMode
The mode to be set by the next reconfiguration.
int m_default_bin_x
Power-on ROI x binning.
bool m_cropMode
Status of crop mode ROIs, if enabled for this camera.
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.
float m_full_y
The full ROI center y coordinate.
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.
int setupConfig(mx::app::appConfigurator &config)
Setup the configuration system.
pcf::IndiProperty m_indiP_roi_w
Property used to set the ROI width.
std::string m_modeName
The current mode name.
pcf::IndiProperty m_indiP_roi_bin_x
Property used to set the ROI x binning.
std::string m_startupMode
The camera mode to load during first init after a power-on.
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 loadConfig(mx::app::appConfigurator &config)
load the configuration system results
std::string m_vShiftSpeedName
The current vshift speed name.
float m_ccdTemp
The current temperature, in C.
std::vector< std::string > m_vShiftSpeedNames
std::string m_defaultVShiftSpeed
The default readout speed of the camera.
bool m_tempControlOnTarget
Whether or not the temperature control system is on its target temperature.
cameraConfigMap m_cameraModes
Map holding the possible camera mode configurations.
std::vector< std::string > m_vShiftSpeedNameLabels
pcf::IndiProperty m_indiP_roi_set
Property used to trigger setting the ROI.
float m_default_y
Power-on ROI center y coordinate.
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 m_default_bin_y
Power-on ROI y binning.
bool m_tempControlStatusSet
Desired state of temperature control.
std::string m_readoutSpeedNameSet
The user requested readout speed name, to be set by derived()
#define protected
int nc
Definition cycle.cpp:13
#define INDI_IDLE
Definition indiUtils.hpp:27
#define INDI_OK
Definition indiUtils.hpp:28
A camera configuration.
Definition stdCamera.hpp:34
int readoutParams(int &newa, int &newhss, const std::string &ron)
int vshiftParams(int &newvs, const std::string &vssn, float &vs)
std::string andorSDKErrorName(unsigned int error)
Definition andorCtrl.hpp:22
std::unique_lock< std::mutex > lock(m_indiMutex)
Definition dm.hpp:19
static constexpr logPrioT LOG_NOTICE
A normal but significant condition.
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.
A device base class which saves telemetry.
Definition telemeter.hpp:75
int appShutdown()
Perform telemeter application shutdown.
int loadConfig(appConfigurator &config)
Load the device section from an application configurator.
int setupConfig(appConfigurator &config)
Setup an application configurator for the device section.
@ OPERATING
The device is operating, other than homing.
@ NODEVICE
No device exists for the application to control.
@ CONFIGURING
The application is configuring the device.
@ ERROR
The application has encountered an error, from which it is recovering (with or without intervention)
@ READY
The device is ready for operation, but is not operating.
@ CONNECTED
The application has connected to the device or service.
@ NOTCONNECTED
The application is not connected to the device or service.
@ POWERON
The device power is on.
Software CRITICAL log entry.
Software ERR log entry.
Log entry recording stdcam stage specific status.
A simple text log, a string-type log.
Definition text_log.hpp:24