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
407 static constexpr bool c_stdCamera_emGain = true; ///< app::dev config to tell stdCamera to expose EM gain controls
408
409 static constexpr bool c_stdCamera_exptimeCtrl = true; ///< app::dev config to tell stdCamera to expose exposure time controls
410
411 static constexpr bool c_stdCamera_fpsCtrl = false; ///< app::dev config to tell stdCamera to not expose FPS controls
412
413 static constexpr bool c_stdCamera_fps = true; ///< app::dev config to tell stdCamera not to expose FPS status
414
415 static constexpr bool c_stdCamera_synchro = false; ///< app::dev config to tell stdCamera to not expose synchro mode controls
416
417 static constexpr bool c_stdCamera_usesModes = false; ///< app:dev config to tell stdCamera not to expose mode controls
418
419 static constexpr bool c_stdCamera_usesROI = true; ///< app:dev config to tell stdCamera to expose ROI controls
420
421 static constexpr bool c_stdCamera_cropMode = true; ///< app:dev config to tell stdCamera to expose Crop Mode controls
422
423 static constexpr bool c_stdCamera_hasShutter = true; ///< app:dev config to tell stdCamera to expose shutter controls
424
425 static constexpr bool c_stdCamera_usesStateString = false; ///< app::dev confg to tell stdCamera to expose the state string property
426
427 static constexpr bool c_edtCamera_relativeConfigPath = false; ///< app::dev config to tell edtCamera to use absolute path to camera config file
428
429 static constexpr bool c_frameGrabber_flippable = false; ///< app:dev config to tell framegrabber this camera can not be flipped
430
431 ///@}
432
433protected:
434
435 /** \name configurable parameters
436 *@{
437 */
438
439
440
441
442 ///@}
443
444 std::string m_configFile; ///< The path, relative to configDir, where to write and read the temporary config file.
445
446 bool m_libInit {false}; ///< Whether or not the Andor SDK library is initialized.
447
448 bool m_poweredOn {false};
449
450public:
451
452 ///Default c'tor
453 andorCtrl();
454
455 ///Destructor
457
458 /// Setup the configuration system (called by MagAOXApp::setup())
459 virtual void setupConfig();
460
461 /// load the configuration system results (called by MagAOXApp::setup())
462 virtual void loadConfig();
463
464 /// Startup functions
465 /** Sets up the INDI vars.
466 *
467 */
468 virtual int appStartup();
469
470 /// Implementation of the FSM for the Siglent SDG
471 virtual int appLogic();
472
473 /// Implementation of the on-power-off FSM logic
474 virtual int onPowerOff();
475
476 /// Implementation of the while-powered-off FSM
478
479 /// Do any needed shutdown tasks. Currently nothing in this app.
480 virtual int appShutdown();
481
482 int cameraSelect();
483
484 int getTemp();
485
486 int getFPS();
487
488 int setFPS(float fps);
489
490 /// Set the output amplifier and readout speed
491 /** Sets according to stdCamera::m_readoutSpeedNameSet
492 */
493 int setReadoutSpeed();
494
495 /// Set the vertical shift speed
496 /** Sets according to std::Camera::m_vShiftSpeedNameSet
497 */
498 int setVShiftSpeed();
499
500 int getEMGain();
501
502 int setEMGain();
503
504 int setCropMode();
505
507
508 int setShutter( unsigned os);
509
510
511 int writeConfig();
512
513 /** \name stdCamera Interface
514 *
515 * @{
516 */
517
518 /// Set defaults for a power on state.
519 /**
520 * \returns 0 on success
521 * \returns -1 on error
522 */
523 int powerOnDefaults();
524
525 /// Turn temperature control on or off.
526 /** Sets temperature control on or off based on the current value of m_tempControlStatus
527 * \returns 0 on success
528 * \returns -1 on error
529 */
530 int setTempControl();
531
532 /// Set the CCD temperature setpoint [stdCamera interface].
533 /** Sets the temperature to m_ccdTempSetpt.
534 * \returns 0 on success
535 * \returns -1 on error
536 */
537 int setTempSetPt();
538
539 /// Required by stdCamera, but this does not do anything for this camera [stdCamera interface]
540 /**
541 * \returns 0 always
542 */
543 int setExpTime();
544
545 /// Check the next ROI
546 /** Checks if the target values are valid and adjusts them to the closest valid values if needed.
547 *
548 * \returns 0 if successfull
549 * \returns -1 otherwise
550 */
551 int checkNextROI();
552
553 /// Required by stdCamera, but this does not do anything for this camera [stdCamera interface]
554 /**
555 * \returns 0 always
556 */
557 int setNextROI();
558
559 ///@}
560
561
562
563 /** \name framegrabber Interface
564 *
565 * @{
566 */
567
569 float fps();
570 int startAcquisition();
572 int loadImageIntoStream(void * dest);
573 int reconfig();
574
575
576 //INDI:
578
579public:
580
581 /** \name Telemeter Interface
582 *
583 * @{
584 */
585 int checkRecordTimes();
586
588
589 ///@}
590};
591
592inline
594{
595 m_powerMgtEnabled = true;
596 m_powerOnWait = 10;
597
598 m_startupTemp = -45;
599
600 m_defaultReadoutSpeed = "emccd_17MHz";
601 m_readoutSpeedNames = {"ccd_00_08MHz", "ccd_01MHz", "ccd_03MHz", "emccd_01MHz", "emccd_05MHz", "emccd_10MHz", "emccd_17MHz"};
602 m_readoutSpeedNameLabels = {"CCD 0.08 MHz", "CCD 1 MHz", "CCD 3 MHz", "EMCCD 1 MHz", "EMCCD 5 MHz", "EMCCD 10 MHz", "EMCCD 17 MHz"};
603
604 m_defaultVShiftSpeed = "3_3us";
605 m_vShiftSpeedNames = {"0_3us", "0_5us", "0_9us", "1_7us", "3_3us"};
606 m_vShiftSpeedNameLabels = {"0.3 us", "0.5 us", "0.9 us", "1.7 us", "3.3 us"};
607
608 m_maxEMGain = 300;
609
610
611 m_default_x = 255.5;
612 m_default_y = 255.5;
613 m_default_w = 512;
614 m_default_h = 512;
615
620 m_nextROI.bin_x = 1;
621 m_nextROI.bin_y = 1;
622
623 m_full_x = 255.5;
624 m_full_y = 255.5;
625 m_full_w = 512;
626 m_full_h = 512;
627
628
629 return;
630}
631
632inline
634{
635 return;
636}
637
638inline
652
653inline
655{
657
658 m_configFile = "/tmp/andor_";
660 m_configFile += ".cfg";
661 m_cameraModes["onlymode"] = dev::cameraConfig({m_configFile, "", 255, 255, 512, 512, 1, 1, 1000});
662 m_startupMode = "onlymode";
663
664 if(writeConfig() < 0)
665 {
667 m_shutdown = true;
668 return;
669 }
670
672
673
674 if(m_maxEMGain < 1)
675 {
676 m_maxEMGain = 1;
677 log<text_log>("maxEMGain set to 1");
678 }
679
680 if(m_maxEMGain > 300)
681 {
682 m_maxEMGain = 300;
683 log<text_log>("maxEMGain set to 300");
684 }
685
687
689
690}
691
692inline
694{
696 {
698 }
699
701 {
703 }
704
706 {
708 }
709
711 {
712 return log<software_error,-1>({__FILE__,__LINE__});
713 }
714
716
717 return 0;
718
719}
720
721
722
723inline
725{
726 //run stdCamera's appLogic
728 {
729 return log<software_error, -1>({__FILE__, __LINE__});
730 }
731
732 //run edtCamera's appLogic
734 {
735 return log<software_error, -1>({__FILE__, __LINE__});
736 }
737
738 //run frameGrabber's appLogic to see if the f.g. thread has exited.
740 {
741 return log<software_error, -1>({__FILE__, __LINE__});
742 }
743
744 if( state() == stateCodes::POWERON)
745 {
746 return 0;
747 }
748
750 {
751 //Might have gotten here because of a power off.
752 if(m_powerState == 0) return 0;
753
754 int ret = cameraSelect();
755
756 if( ret != 0)
757 {
758 return log<software_critical,-1>({__FILE__, __LINE__});
759 }
760 }
761
763 {
764 sleep(30);
765 writeConfig();
766 m_shutterStatus = "READY";
767
769
770 if(m_poweredOn && m_ccdTempSetpt > -999)
771 {
772 m_poweredOn = false;
773 if(setTempSetPt() < 0)
774 {
775 if(powerState() != 1 || powerStateTarget() != 1) return 0;
777 }
778 }
779 }
780
782 {
783 //Get a lock if we can
784 std::unique_lock<std::mutex> lock(m_indiMutex, std::try_to_lock);
785
786 //but don't wait for it, just go back around.
787 if(!lock.owns_lock()) return 0;
788
789 if(getTemp() < 0)
790 {
791 if(m_powerState == 0) return 0;
792
794 return 0;
795 }
796
797 if(getFPS() < 0)
798 {
799 if(m_powerState == 0) return 0;
800
802 return 0;
803 }
804
805 if(getEMGain () < 0)
806 {
807 if(m_powerState == 0) return 0;
808
810 return 0;
811 }
812
814 {
817 return 0;
818 }
819
821 {
824 return 0;
825 }
826
828 {
831 return 0;
832 }
833
835 {
837 return 0;
838 }
839
840 }
841
842 //Fall through check?
843
844 return 0;
845
846}
847
848inline
850{
851 if(m_libInit)
852 {
853 ShutDown();
854 m_libInit = false;
855 }
856
858
859 std::lock_guard<std::mutex> lock(m_indiMutex);
860
861 m_shutterStatus = "POWEROFF";
862 m_shutterState = 0;
863
865 {
867 }
868
870 {
872 }
873
875 {
877 }
878
879 //Setting m_poweredOn
880 m_poweredOn = true;
881
882 return 0;
883}
884
885inline
887{
888 m_shutterStatus = "POWEROFF";
889 m_shutterState = 0;
890
892 {
894 }
895
897 {
899 }
900
901 return 0;
902}
903
904
905inline
907{
908 if(m_libInit)
909 {
910 ShutDown();
911 m_libInit = false;
912 }
913
915
917
918 return 0;
919}
920
921
922
923inline
925{
926 unsigned int error;
927
928 if(!m_libInit)
929 {
930 char path[] = "/usr/local/etc/andor/";
931 error = Initialize(path);
932
933 if(error == DRV_USBERROR || error == DRV_ERROR_NOCAMERA || error == DRV_VXDNOTINSTALLED)
934 {
936 if(!stateLogged())
937 {
938 log<text_log>("No Andor USB camera found", logPrio::LOG_WARNING);
939 }
940
941 ShutDown();
942
943 //Not an error, appLogic should just go on.
944 return 0;
945 }
946 else if(error!=DRV_SUCCESS)
947 {
948 log<software_critical>({__FILE__, __LINE__, "ANDOR SDK initialization failed: " + andorSDKErrorName(error)});
949 ShutDown();
950 return -1;
951 }
952
953 m_libInit = true;
954 }
955
956 at_32 lNumCameras = 0;
958
959 if(error != DRV_SUCCESS)
960 {
961 log<software_critical>({__FILE__, __LINE__, "ANDOR SDK GetAvailableCameras failed: " + andorSDKErrorName(error)});
962 return -1;
963 }
964
965 if(lNumCameras < 1)
966 {
967 if(!stateLogged())
968 {
969 log<text_log>("No Andor cameras found after initialization", logPrio::LOG_WARNING);
970 }
972 return 0;
973 }
974
975 int iSelectedCamera = 0; //We're hard-coded for just one camera!
976
977 int serialNumber = 0;
979
980 if(error != DRV_SUCCESS)
981 {
982 log<software_critical>({__FILE__, __LINE__, "ANDOR SDK GetCameraSerialNumber failed: " + andorSDKErrorName(error)});
983 return -1;
984 }
985
986 log<text_log>(std::string("Found Andor USB Camera with serial number ") + std::to_string(serialNumber));
987
990
991 if(error != DRV_SUCCESS)
992 {
993 log<software_critical>({__FILE__, __LINE__, "ANDOR SDK GetCameraHandle failed: " + andorSDKErrorName(error)});
994 return -1;
995 }
996
998
999 if(error != DRV_SUCCESS)
1000 {
1001 log<software_critical>({__FILE__, __LINE__, "ANDOR SDK SetCurrentCamera failed: " + andorSDKErrorName(error)});
1002 return -1;
1003 }
1004
1005 char name[MAX_PATH];
1006
1007 error = GetHeadModel(name);
1008 if(error != DRV_SUCCESS)
1009 {
1010 log<software_critical>({__FILE__, __LINE__, "ANDOR SDK GetHeadModel failed: " + andorSDKErrorName(error)});
1011 return -1;
1012 }
1013
1015 log<text_log>(std::string("Connected to ") + name + " with serial number " + std::to_string(serialNumber));
1016
1017 unsigned int eprom;
1018 unsigned int cofFile;
1019 unsigned int vxdRev;
1020 unsigned int vxdVer;
1021 unsigned int dllRev;
1022 unsigned int dllVer;
1024 if(error != DRV_SUCCESS)
1025 {
1026 log<software_critical>({__FILE__, __LINE__, "ANDOR SDK GetSoftwareVersion failed: " + andorSDKErrorName(error)});
1027 return -1;
1028 }
1029
1030 log<text_log>(std::string("eprom: ") + std::to_string(eprom));
1031 log<text_log>(std::string("cofFile: ") + std::to_string(cofFile));
1032 log<text_log>(std::string("vxd: ") + std::to_string(vxdVer) + "." + std::to_string(vxdRev));
1033 log<text_log>(std::string("dll: ") + std::to_string(dllVer) + "." + std::to_string(dllRev));
1034
1035 unsigned int PCB;
1036 unsigned int Decode;
1037 unsigned int dummy1;
1038 unsigned int dummy2;
1039 unsigned int CameraFirmwareVersion;
1040 unsigned int CameraFirmwareBuild;
1042 if(error != DRV_SUCCESS)
1043 {
1044 log<software_critical>({__FILE__, __LINE__, "ANDOR SDK GetHardwareVersion failed: " + andorSDKErrorName(error)});
1045 return -1;
1046 }
1047
1048 log<text_log>(std::string("PCB: ") + std::to_string(PCB));
1049 log<text_log>(std::string("Decode: ") + std::to_string(Decode));
1050 log<text_log>(std::string("f/w: ") + std::to_string(CameraFirmwareVersion) + "." + std::to_string(CameraFirmwareBuild));
1051
1052#if 0 //We don't normally need to do this, but keep here in case we want to check in the future
1053 int em_speeds;
1054 error=GetNumberHSSpeeds(0,0, &em_speeds);
1055 if(error != DRV_SUCCESS)
1056 {
1057 return log<software_error,-1>({__FILE__, __LINE__, std::string("Andor SDK Error from GetNumberHSSpeeds: ") + andorSDKErrorName(error)});
1058 }
1059
1060 std::cerr << "Number of EM HS speeds: " << em_speeds << "\n";
1061 for(int i=0; i< em_speeds; ++i)
1062 {
1063 float speed;
1064 error=GetHSSpeed(0,0,i, &speed);
1065 std::cerr << i << " " << speed << "\n";
1066 }
1067
1068 int conv_speeds;
1069 error=GetNumberHSSpeeds(0,1, &conv_speeds);
1070 if(error != DRV_SUCCESS)
1071 {
1072 return log<software_error,-1>({__FILE__, __LINE__, std::string("Andor SDK Error from GetNumberHSSpeeds: ") + andorSDKErrorName(error)});
1073 }
1074
1075 std::cerr << "Number of Conventional HS speeds: " << conv_speeds << "\n";
1076 for(int i=0; i< conv_speeds; ++i)
1077 {
1078 float speed;
1079 error=GetHSSpeed(0,1,i, &speed);
1080 std::cerr << i << " " << speed << "\n";
1081 }
1082#endif
1083#if 0 //We don't normally need to do this, but keep here in case we want to check in the future
1084 int v_speeds;
1086 if(error != DRV_SUCCESS)
1087 {
1088 return log<software_error,-1>({__FILE__, __LINE__, std::string("Andor SDK Error from GetNumberVSSpeeds: ") + andorSDKErrorName(error)});
1089 }
1090
1091 std::cerr << "Number of VS speeds: " << v_speeds << "\n";
1092 for(int i=0; i< v_speeds; ++i)
1093 {
1094 float speed;
1095 error=GetVSSpeed(i, &speed);
1096 std::cerr << i << " " << speed << "\n";
1097 }
1098#endif
1099
1100
1101 //Initialize Shutter to SHUT
1102 int ss = 2;
1103 if(m_shutterState == 1) ss = 1;
1104 else m_shutterState = 0; //handles startup case
1105 error = SetShutter(1,ss,500,500);
1106 if(error != DRV_SUCCESS)
1107 {
1108 log<software_critical>({__FILE__, __LINE__, "ANDOR SDK SetShutter failed: " + andorSDKErrorName(error)});
1109 return -1;
1110 }
1111
1112 // Set CameraLink
1113 error = SetCameraLinkMode(1);
1114 if(error != DRV_SUCCESS)
1115 {
1116 log<software_critical>({__FILE__, __LINE__, "ANDOR SDK SetCameraLinkMode failed: " + andorSDKErrorName(error)});
1117 return -1;
1118 }
1119
1120 //Set Read Mode to --Image--
1121 error = SetReadMode(4);
1122 if(error != DRV_SUCCESS)
1123 {
1124 return log<software_error,-1>({__FILE__, __LINE__, "Andor SDK Error from SetReadMode: " + andorSDKErrorName(error)});
1125 }
1126
1127 //Set Acquisition mode to --Run Till Abort--
1128 error = SetAcquisitionMode(5);
1129 if(error != DRV_SUCCESS)
1130 {
1131 return log<software_error,-1>({__FILE__, __LINE__, "Andor SDK Error from SetAcquisitionMode: " + andorSDKErrorName(error)});
1132 }
1133
1134 //Set to frame transfer mode
1135 error = SetFrameTransferMode(1);
1136 if(error != DRV_SUCCESS)
1137 {
1138 return log<software_error,-1>({__FILE__, __LINE__, "Andor SDK Error from SetFrameTransferMode: " + andorSDKErrorName(error)});
1139 }
1140
1141 //Set to real gain mode
1142 error = SetEMGainMode(3);
1143 if(error != DRV_SUCCESS)
1144 {
1145 return log<software_error,-1>({__FILE__, __LINE__, "Andor SDK Error from SetEMGainMode: " + andorSDKErrorName(error)});
1146 }
1147
1148 //Set default amplifier and speed
1151
1152 int newa;
1153 int newhss;
1154
1156 {
1157 return log<text_log,-1>("invalid default readout speed: " + m_readoutSpeedNameSet, logPrio::LOG_ERROR);
1158 }
1159
1160 // Set the HSSpeed to first index
1161 /* See page 284
1162 */
1163 error = SetHSSpeed(newa,newhss);
1164 if(error != DRV_SUCCESS)
1165 {
1166 return log<software_error,-1>({__FILE__, __LINE__, std::string("Andor SDK Error from SetHSSpeed: ") + andorSDKErrorName(error)});
1167 }
1168
1171
1172 int newvs;
1173 float vs;
1175 {
1176 return log<text_log,-1>("invalid default vert. shift speed: " + m_vShiftSpeedNameSet, logPrio::LOG_ERROR);
1177 }
1178
1179 // Set the VSSpeed to first index
1180 error = SetVSSpeed(newvs);
1181 if(error != DRV_SUCCESS)
1182 {
1183 return log<software_error,-1>({__FILE__, __LINE__, std::string("Andor SDK Error from SetVSSpeed: ") + andorSDKErrorName(error)});
1184 }
1185
1186 m_vshiftSpeed = vs;
1187 // Set the amplifier
1188 /* See page 298
1189 */
1190 error = SetOutputAmplifier(newa);
1191 if(error != DRV_SUCCESS)
1192 {
1193 return log<software_error,-1>({__FILE__, __LINE__, std::string("Andor SDK Error from SetOutputAmplifier: ") + andorSDKErrorName(error)});
1194 }
1195
1196 //Set initial exposure time
1197 error = SetExposureTime(0.1);
1198 if(error != DRV_SUCCESS)
1199 {
1200 return log<software_error,-1>({__FILE__, __LINE__, "Andor SDK Error from SetExposureTime: " + andorSDKErrorName(error)});
1201 }
1202
1203 //Turn cooling on:
1204 if(m_ccdTempSetpt > -999)
1205 {
1206 error = CoolerON();
1207 if(error != DRV_SUCCESS)
1208 {
1209 log<software_critical,-1>({__FILE__, __LINE__, "ANDOR SDK CoolerON failed: " + andorSDKErrorName(error)});
1210 }
1211 m_tempControlStatus = true;
1212 m_tempControlStatusStr = "COOLING";
1213 log<text_log>("enabled temperature control");
1214 }
1215
1216 int nc;
1218 std::cout << "NumberADChannels: " << nc << "\n";
1219
1220 GetNumberAmp(&nc);
1221 std::cout << "NumberAmp; " << nc << "\n";
1222
1223 return 0;
1224
1225}
1226
1227inline
1229{
1230 //unsigned int error;
1231 //int temp_low {999}, temp_high {999};
1232 //error = GetTemperatureRange(&temp_low, &temp_high);
1233
1234 float temp = -999;
1235 unsigned int status = GetTemperatureF(&temp);
1236
1237 std::string cooling;
1238 switch(status)
1239 {
1240 case DRV_TEMPERATURE_OFF:
1241 m_tempControlStatusStr = "OFF";
1242 m_tempControlStatus = false;
1243 m_tempControlOnTarget = false;
1244 break;
1246 m_tempControlStatusStr = "STABILIZED";
1247 m_tempControlStatus = true;
1248 m_tempControlOnTarget = true;
1249 break;
1251 m_tempControlStatusStr = "COOLING";
1252 m_tempControlStatus = true;
1253 m_tempControlOnTarget = false;
1254 break;
1256 m_tempControlStatusStr = "NOT STABILIZED";
1257 m_tempControlStatus = true;
1258 m_tempControlOnTarget = false;
1259 break;
1261 m_tempControlStatusStr = "DRIFTING";
1262 m_tempControlStatus = true;
1263 m_tempControlOnTarget = false;
1264 break;
1265 default:
1266 m_tempControlStatusStr = "UNKOWN";
1267 m_tempControlStatus = false;
1268 m_tempControlOnTarget = false;
1269 m_ccdTemp = -999;
1270 log<software_error>({__FILE__, __LINE__, "ANDOR SDK GetTemperatureF:" + andorSDKErrorName(status)});
1271 return -1;
1272 }
1273
1274 m_ccdTemp = temp;
1275 recordCamera();
1276
1277 return 0;
1278
1279}
1280
1281inline
1283{
1284 unsigned int error;
1285 int gain;
1286
1287 error = GetEMCCDGain(&gain);
1288 if( error !=DRV_SUCCESS)
1289 {
1290 log<software_error>({__FILE__,__LINE__, "Andor SDK error from GetEMCCDGain: " + andorSDKErrorName(error)});
1291 return -1;
1292 }
1293
1294 if(gain == 0) gain = 1;
1295
1296 m_emGain = gain;
1297
1298 return 0;
1299}
1300
1301inline
1303{
1304 recordCamera(true);
1305 AbortAcquisition();
1307
1308 int newa;
1309 int newhss;
1310
1312 {
1313 return log<text_log,-1>("invalid readout speed: " + m_readoutSpeedNameSet);
1314 }
1315
1316 if(newa == 1 && m_cropMode)
1317 {
1318 log<text_log>("disabling crop mode for CCD readout", logPrio::LOG_NOTICE);
1319 m_cropModeSet = false;
1320 }
1321 // Set the HSSpeed to first index
1322 /* See page 284
1323 */
1324 unsigned int error = SetHSSpeed(newa,newhss);
1325 if(error != DRV_SUCCESS)
1326 {
1327 return log<software_error,-1>({__FILE__, __LINE__, std::string("Andor SDK Error from SetHSSpeed: ") + andorSDKErrorName(error)});
1328 }
1329
1330 // Set the amplifier
1331 /* See page 298
1332 */
1333 error = SetOutputAmplifier(newa);
1334 if(error != DRV_SUCCESS)
1335 {
1336 return log<software_error,-1>({__FILE__, __LINE__, std::string("Andor SDK Error from SetOutputAmplifier: ") + andorSDKErrorName(error)});
1337 }
1338
1339 log<text_log>("Set readout speed to " + m_readoutSpeedNameSet + " (" + std::to_string(newa) + "," + std::to_string(newhss) + ")");
1340
1341
1343
1345 m_reconfig = true;
1346
1347 return 0;
1348}
1349
1350
1351
1352inline
1354{
1355 recordCamera(true);
1356 AbortAcquisition();
1358
1359 int newvs;
1360 float vs;
1362 {
1363 return log<text_log,-1>("invalid vertical shift speed: " + m_vShiftSpeedNameSet);
1364 }
1365
1366 // Set the VSSpeed
1367 unsigned int error = SetVSSpeed(newvs);
1368 if(error != DRV_SUCCESS)
1369 {
1370 return log<software_error,-1>({__FILE__, __LINE__, std::string("Andor SDK Error from SetVSSpeed: ") + andorSDKErrorName(error)});
1371 }
1372
1373
1374 log<text_log>("Set vertical shift speed to " + m_vShiftSpeedNameSet + " (" + std::to_string(newvs) + ")");
1375
1376
1378 m_vshiftSpeed = vs;
1379
1381 m_reconfig = true;
1382
1383 return 0;
1384}
1385
1386inline
1388{
1389 int amp;
1390 int hss;
1391
1393
1394 if(amp != 0)
1395 {
1396 log<text_log>("Attempt to set EM gain while in conventional amplifier.", logPrio::LOG_NOTICE);
1397 return 0;
1398 }
1399
1400 int emg = m_emGainSet;
1401
1402 if(emg == 1) emg = 0;
1403
1404 if(emg < 0)
1405 {
1406 emg = 0;
1407 log<text_log>("EM gain limited to 0", logPrio::LOG_WARNING);
1408 }
1409
1410 if(emg > m_maxEMGain)
1411 {
1412 emg = m_maxEMGain;
1413 log<text_log>("EM gain limited to maxEMGain = " + std::to_string(emg), logPrio::LOG_WARNING);
1414 }
1415
1416 unsigned int error = SetEMCCDGain(emg);
1417 if( error !=DRV_SUCCESS)
1418 {
1419 log<software_error>({__FILE__,__LINE__, "Andor SDK error from SetEMCCDGain: " + andorSDKErrorName(error)});
1420 return -1;
1421 }
1422
1423 log<text_log>("Set EM Gain to: " + std::to_string(emg), logPrio::LOG_WARNING);
1424
1425 return 0;
1426}
1427
1428inline
1430{
1431 recordCamera(true);
1432 AbortAcquisition();
1434
1435 //Check if we're in the EMCCD amplifier
1436 if(m_cropModeSet == true)
1437 {
1438 int amp;
1439 int hss;
1440
1442
1443 if(amp == 1)
1444 {
1445 m_cropModeSet = false;
1446 log<text_log>("Can not set crop mode in CCD mode", logPrio::LOG_ERROR);
1447 }
1448 }
1449
1451 m_reconfig = true;
1452
1453 return 0;
1454}
1455
1456inline
1457int andorCtrl::setShutter( unsigned os )
1458{
1459 recordCamera(true);
1460 AbortAcquisition();
1462
1463 if(os == 0) //Shut
1464 {
1465 int error = SetShutter(1,2,500,500);
1466 if(error != DRV_SUCCESS)
1467 {
1468 return log<software_error, -1>({__FILE__, __LINE__, "ANDOR SDK SetShutter failed: " + andorSDKErrorName(error)});
1469 }
1470
1471 m_shutterState = 0;
1472 }
1473 else //Open
1474 {
1475 int error = SetShutter(1,1,500,500);
1476 if(error != DRV_SUCCESS)
1477 {
1478 return log<software_error, -1>({__FILE__, __LINE__, "ANDOR SDK SetShutter failed: " + andorSDKErrorName(error)});
1479 }
1480
1481 m_shutterState = 1;
1482 }
1483
1485 m_reconfig = true;
1486
1487 return 0;
1488}
1489
1490
1491
1492
1493
1494
1495inline
1497{
1498 std::string configFile = "/tmp/andor_";
1500 configFile += ".cfg";
1501
1502 std::ofstream fout;
1503 fout.open(configFile);
1504
1505 if(fout.fail())
1506 {
1507 log<software_error>({__FILE__, __LINE__, "error opening config file for writing"});
1508 return -1;
1509 }
1510
1511 int w = m_nextROI.w / m_nextROI.bin_x;
1512 int h = m_nextROI.h / m_nextROI.bin_y;
1513
1514 fout << "camera_class: \"Andor\"\n";
1515 fout << "camera_model: \"iXon Ultra 897\"\n";
1516 fout << "camera_info: \"512x512 (1-tap, freerun)\"\n";
1517 fout << "width: " << w << "\n";
1518 fout << "height: " << h << "\n";
1519 fout << "depth: 16\n";
1520 fout << "extdepth: 16\n";
1521 fout << "CL_DATA_PATH_NORM: 0f # single tap\n";
1522 fout << "CL_CFG_NORM: 02\n";
1523
1524 fout.close();
1525
1526 return 0;
1527
1528}
1529//------------------------------------------------------------------------
1530//----------------------- stdCamera interface ---------------------------
1531//------------------------------------------------------------------------
1532
1533inline
1535{
1536 //Camera boots up with this true in most cases.
1537 m_tempControlStatus = false;
1538 m_tempControlStatusSet = false;
1539 m_tempControlStatusStr = "OFF";
1540 m_tempControlOnTarget = false;
1541
1548
1553 m_nextROI.bin_x = m_default_bin_x;
1554 m_nextROI.bin_y = m_default_bin_y;
1555
1556 return 0;
1557}
1558
1559inline
1561{
1563 {
1564 unsigned int error = CoolerON();
1565 if(error != DRV_SUCCESS)
1566 {
1567 log<software_critical>({__FILE__, __LINE__, "ANDOR SDK CoolerON failed: " + andorSDKErrorName(error)});
1568 return -1;
1569 }
1570 m_tempControlStatus = true;
1571 m_tempControlStatusStr = "COOLING";
1572 recordCamera();
1573 log<text_log>("enabled temperature control");
1574 return 0;
1575 }
1576 else
1577 {
1578 unsigned int error = CoolerOFF();
1579 if(error != DRV_SUCCESS)
1580 {
1581 log<software_critical>({__FILE__, __LINE__, "ANDOR SDK CoolerOFF failed: " + andorSDKErrorName(error)});
1582 return -1;
1583 }
1584 m_tempControlStatus = false;
1585 m_tempControlStatusStr = "OFF";
1586 recordCamera();
1587 log<text_log>("disabled temperature control");
1588 return 0;
1589 }
1590}
1591
1592inline
1594{
1595 int temp = m_ccdTempSetpt + 0.5;
1596
1597 unsigned int error = SetTemperature(temp);
1598
1599 if(error != DRV_SUCCESS)
1600 {
1601 log<software_critical>({__FILE__, __LINE__, "ANDOR SDK setTemperature failed: " + andorSDKErrorName(error)});
1602 return -1;
1603 }
1604
1605 return 0;
1606
1607}
1608
1609inline
1611{
1612 float exptime;
1613 float accumCycletime;
1614 float kinCycletime;
1615
1616 unsigned int error = GetAcquisitionTimings(&exptime, &accumCycletime, &kinCycletime);
1617 if(error != DRV_SUCCESS)
1618 {
1619 return log<software_error,-1>({__FILE__, __LINE__, "ANDOR SDK error from GetAcquisitionTimings: " + andorSDKErrorName(error)});
1620 }
1621
1622 m_expTime = exptime;
1623
1624 float readoutTime;
1625 error = GetReadOutTime(&readoutTime);
1626 if(error != DRV_SUCCESS)
1627 {
1628 return log<software_error,-1>({__FILE__, __LINE__, "ANDOR SDK error from GetReadOutTime: " + andorSDKErrorName(error)});
1629 }
1630
1631 m_fps = 1.0/accumCycletime;
1632
1633 return 0;
1634
1635}
1636
1637inline
1639{
1640 recordCamera(true);
1641 AbortAcquisition();
1643
1644 unsigned int error = SetExposureTime(m_expTimeSet);
1645 if(error != DRV_SUCCESS)
1646 {
1647 log<software_critical>({__FILE__, __LINE__, "ANDOR SDK SetExposureTime failed: " + andorSDKErrorName(error)});
1648 return -1;
1649 }
1651 m_reconfig = true;
1652 return 0;
1653}
1654
1655inline
1657{
1658 return 0;
1659}
1660
1661inline
1663{
1664 recordCamera(true);
1665 AbortAcquisition();
1667
1669 m_reconfig = true;
1670
1671 updateSwitchIfChanged(m_indiP_roi_set, "request", pcf::IndiElement::Off, INDI_IDLE);
1672
1673 return 0;
1674}
1675
1676//------------------------------------------------------------------------
1677//------------------- framegrabber interface ---------------------------
1678//------------------------------------------------------------------------
1679
1680inline
1682{
1683 //lock mutex
1684 std::unique_lock<std::mutex> lock(m_indiMutex);
1685
1686 unsigned int error;
1687
1688 int status;
1689 error = GetStatus(&status);
1690 if(error != DRV_SUCCESS)
1691 {
1693 return log<software_error,-1>({__FILE__, __LINE__, "Andor SDK Error from GetStatus: " + andorSDKErrorName(error)});
1694 }
1695
1696 if(status != DRV_IDLE)
1697 {
1698 return 0;
1699 }
1700
1701 int x0 = (m_nextROI.x - 0.5*(m_nextROI.w - 1)) + 1;
1702 int y0 = (m_nextROI.y - 0.5*(m_nextROI.h - 1)) + 1;
1703
1704 if(m_cropModeSet)
1705 {
1707
1708 error = SetIsolatedCropModeEx(1, m_nextROI.h, m_nextROI.w, m_nextROI.bin_y, m_nextROI.bin_x, x0, y0);
1709
1710 if(error != DRV_SUCCESS)
1711 {
1712 if(error == DRV_P2INVALID)
1713 {
1714 log<text_log>(std::string("crop mode invalid height: ") + std::to_string(m_nextROI.h), logPrio::LOG_ERROR);
1715 }
1716 else if(error == DRV_P3INVALID)
1717 {
1718 log<text_log>(std::string("crop mode invalid width: ") + std::to_string(m_nextROI.w), logPrio::LOG_ERROR);
1719 }
1720 else if(error == DRV_P4INVALID)
1721 {
1722 log<text_log>(std::string("crop mode invalid y binning: ") + std::to_string(m_nextROI.bin_y), logPrio::LOG_ERROR);
1723 }
1724 else if(error == DRV_P5INVALID)
1725 {
1726 log<text_log>(std::string("crop mode invalid x binning: ") + std::to_string(m_nextROI.bin_x), logPrio::LOG_ERROR);
1727 }
1728 else if(error == DRV_P6INVALID)
1729 {
1730 log<text_log>(std::string("crop mode invalid x center: ") + std::to_string(m_nextROI.x) + "/" + std::to_string(x0), logPrio::LOG_ERROR);
1731 }
1732 else if(error == DRV_P7INVALID)
1733 {
1734 log<text_log>(std::string("crop mode invalid y center: ") + std::to_string(m_nextROI.y) + "/" + std::to_string(y0), logPrio::LOG_ERROR);
1735 }
1736 else
1737 {
1738 log<software_error>({__FILE__, __LINE__, "Andor SDK Error from SetIsolatedCropModeEx: " + andorSDKErrorName(error)});
1739 }
1740
1741 m_nextROI.x = m_currentROI.x;
1742 m_nextROI.y = m_currentROI.y;
1743 m_nextROI.w = m_currentROI.w;
1744 m_nextROI.h = m_currentROI.h;
1745 m_nextROI.bin_x = m_currentROI.bin_x;
1746 m_nextROI.bin_y = m_currentROI.bin_y;
1747
1749
1751 return -1;
1752 }
1753
1754 //Set low-latency crop mode
1755 error = SetIsolatedCropModeType(1);
1756 if(error != DRV_SUCCESS)
1757 {
1758 log<software_error>({__FILE__, __LINE__, "SetIsolatedCropModeType: " + andorSDKErrorName(error)});
1759 }
1760 }
1761 else
1762 {
1764
1765 error = SetIsolatedCropModeEx(0, m_nextROI.h, m_nextROI.w, m_nextROI.bin_y, m_nextROI.bin_x, x0, y0);
1766 if(error != DRV_SUCCESS)
1767 {
1768 log<software_error>({__FILE__, __LINE__, "SetIsolatedCropModeEx(0,): " + andorSDKErrorName(error)});
1769 }
1770
1771 //Setup Image dimensions
1772 /* SetImage(int hbin, int vbin, int hstart, int hend, int vstart, int vend)
1773 * hbin: number of pixels to bin horizontally
1774 * vbin: number of pixels to bin vertically
1775 * hstart: Starting Column (inclusive)
1776 * hend: End column (inclusive)
1777 * vstart: Start row (inclusive)
1778 * vend: End row (inclusive)
1779 */
1780 error = SetImage(m_nextROI.bin_x, m_nextROI.bin_y, x0, x0 + m_nextROI.w - 1, y0, y0 + m_nextROI.h - 1);
1781 if(error != DRV_SUCCESS)
1782 {
1783 if(error == DRV_P1INVALID)
1784 {
1785 log<text_log>(std::string("invalid x-binning: ") + std::to_string(m_nextROI.bin_x), logPrio::LOG_ERROR);
1786 }
1787 else if(error == DRV_P2INVALID)
1788 {
1789 log<text_log>(std::string("invalid y-binning: ") + std::to_string(m_nextROI.bin_y), logPrio::LOG_ERROR);
1790 }
1791 else if(error == DRV_P3INVALID)
1792 {
1793 log<text_log>(std::string("invalid x-center: ") + std::to_string(m_nextROI.x) + "/" + std::to_string(x0), logPrio::LOG_ERROR);
1794 }
1795 else if(error == DRV_P4INVALID)
1796 {
1797 log<text_log>(std::string("invalid width: ") + std::to_string(m_nextROI.w), logPrio::LOG_ERROR);
1798 }
1799 else if(error == DRV_P5INVALID)
1800 {
1801 log<text_log>(std::string("invalid y-center: ") + std::to_string(m_nextROI.y) + "/" + std::to_string(y0), logPrio::LOG_ERROR);
1802 }
1803 else if(error == DRV_P6INVALID)
1804 {
1805 log<text_log>(std::string("invalid height: ") + std::to_string(m_nextROI.h), logPrio::LOG_ERROR);
1806 }
1807 else
1808 {
1809 log<software_error>({__FILE__, __LINE__, "Andor SDK Error from SetImage: " + andorSDKErrorName(error)});
1810 }
1811
1812 m_nextROI.x = m_currentROI.x;
1813 m_nextROI.y = m_currentROI.y;
1814 m_nextROI.w = m_currentROI.w;
1815 m_nextROI.h = m_currentROI.h;
1816 m_nextROI.bin_x = m_currentROI.bin_x;
1817 m_nextROI.bin_y = m_currentROI.bin_y;
1818
1820
1822 return -1;
1823 }
1824
1825
1826 }
1827
1828 m_currentROI.bin_x = m_nextROI.bin_x;
1829 m_currentROI.bin_y = m_nextROI.bin_y;
1830 m_currentROI.x = x0 - 1.0 + 0.5*(m_nextROI.w - 1);
1831 m_currentROI.y = y0 - 1.0 + 0.5*(m_nextROI.h - 1);
1832 m_currentROI.w = m_nextROI.w;
1833 m_currentROI.h = m_nextROI.h;
1834
1841
1842 //We also update target to the settable values
1843 m_nextROI.x = m_currentROI.x;
1844 m_nextROI.y = m_currentROI.y;
1845 m_nextROI.w = m_currentROI.w;
1846 m_nextROI.h = m_currentROI.h;
1847 m_nextROI.bin_x = m_currentROI.bin_x;
1848 m_nextROI.bin_y = m_currentROI.bin_y;
1849
1856
1857
1858 ///\todo This should check whether we have a match between EDT and the camera right?
1862
1863
1864 // Print Detector Frame Size
1865 //std::cout << "Detector Frame is: " << width << "x" << height << "\n";
1866
1867 recordCamera(true);
1868
1869 return 0;
1870}
1871
1872inline
1874{
1875 return m_fps;
1876}
1877
1878inline
1880{
1881 unsigned int error;
1882 int status;
1883 error = GetStatus(&status);
1884 if(error != DRV_SUCCESS)
1885 {
1887 return log<software_error,-1>({__FILE__, __LINE__, "Andor SDK Error from GetStatus: " + andorSDKErrorName(error)});
1888 }
1889
1890 if(status != DRV_IDLE)
1891 {
1893 return 0;
1894 }
1895
1896 error = StartAcquisition();
1897 if(error != DRV_SUCCESS)
1898 {
1900 return log<software_error,-1>({__FILE__, __LINE__, "Andor SDK Error from StartAcquisition: " + andorSDKErrorName(error)});
1901 }
1902
1904 recordCamera();
1905
1906 sleep(1); //make sure camera is rully running before we try to synch with it.
1907
1909}
1910
1911inline
1917
1918inline
1920{
1922
1923 return 0;
1924 }
1925
1926inline
1928{
1929 //lock mutex
1930 //std::unique_lock<std::mutex> lock(m_indiMutex);
1931 recordCamera(true);
1932 AbortAcquisition();
1934
1935 writeConfig();
1936
1938 if(rv < 0) return rv;
1939
1941
1943 return 0;
1944}
1945
1946inline
1951
1952inline
1954{
1955 return recordCamera(true);
1956}
1957
1958}//namespace app
1959} //namespace MagAOX
1960#endif
The base-class for MagAO-X applications.
Definition MagAOXApp.hpp:73
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
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_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:57
u_char * m_image_p
The image data grabbed.
Definition edtCamera.hpp:80
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.
void setupConfig(mx::app::appConfigurator &config)
Setup the configuration system.
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.
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].
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.
void loadConfig(mx::app::appConfigurator &config)
load the configuration system results
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()
@ 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.
#define INDI_IDLE
Definition indiUtils.hpp:28
#define INDI_OK
Definition indiUtils.hpp:29
A camera configuration.
Definition stdCamera.hpp:32
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:24
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:69
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.
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