API
 
Loading...
Searching...
No Matches
picamCtrl.hpp
Go to the documentation of this file.
1/** \file picamCtrl.hpp
2 * \brief The MagAO-X Princeton Instruments EMCCD camera controller.
3 *
4 * \author Jared R. Males (jaredmales@gmail.com)
5 *
6 * \ingroup picamCtrl_files
7 */
8
9#ifndef picamCtrl_hpp
10#define picamCtrl_hpp
11
12
13//#include <ImageStruct.h>
14#include <ImageStreamIO/ImageStreamIO.h>
15
16#include <picam_advanced.h>
17
18#include "../../libMagAOX/libMagAOX.hpp" //Note this is included on command line to trigger pch
19#include "../../magaox_git_version.h"
20
21#define DEBUG
22
23#ifdef DEBUG
24#define BREADCRUMB std::cerr << __FILE__ << " " << __LINE__ << "\n";
25#else
26#define BREADCRUMB
27#endif
28
29inline
30std::string PicamEnum2String( PicamEnumeratedType type, piint value )
31{
32 const pichar* string;
33 Picam_GetEnumerationString( type, value, &string );
34 std::string str(string);
35 Picam_DestroyString( string );
36
37 return str;
38}
39
40namespace MagAOX
41{
42namespace app
43{
44
45int readoutParams( piint & adcQual,
46 piflt & adcSpeed,
47 const std::string & rosn
48 )
49{
50 if(rosn == "ccd_00_1MHz")
51 {
52 adcQual = PicamAdcQuality_LowNoise;
53 adcSpeed = 0.1;
54 }
55 else if(rosn == "ccd_01MHz")
56 {
57 adcQual = PicamAdcQuality_LowNoise;
58 adcSpeed = 1;
59 }
60 else if(rosn == "emccd_05MHz")
61 {
62 adcQual = PicamAdcQuality_ElectronMultiplied;
63 adcSpeed = 5;
64 }
65 else if(rosn == "emccd_10MHz")
66 {
67 adcQual = PicamAdcQuality_ElectronMultiplied;
68 adcSpeed = 10;
69 }
70 else if(rosn == "emccd_20MHz")
71 {
72 adcQual = PicamAdcQuality_ElectronMultiplied;
73 adcSpeed = 20;
74 }
75 else if(rosn == "emccd_30MHz")
76 {
77 adcQual = PicamAdcQuality_ElectronMultiplied;
78 adcSpeed = 30;
79 }
80 else
81 {
82 return -1;
83 }
84
85 return 0;
86}
87
88int vshiftParams( piflt & vss,
89 const std::string & vsn
90 )
91{
92 if(vsn == "0_7us")
93 {
94 vss = 0.7;
95 }
96 else if(vsn == "1_2us")
97 {
98 vss = 1.2;
99 }
100 else if(vsn == "2_0us")
101 {
102 vss = 2.0;
103 }
104 else if(vsn == "5_0us")
105 {
106 vss = 5.0;
107 }
108 else
109 {
110 return -1;
111 }
112
113 return 0;
114}
115
116
117/** \defgroup picamCtrl Princeton Instruments EMCCD Camera
118 * \brief Control of a Princeton Instruments EMCCD Camera.
119 *
120 * <a href="../handbook/operating/software/apps/picamCtrl.html">Application Documentation</a>
121 *
122 * \ingroup apps
123 *
124 */
125
126/** \defgroup picamCtrl_files Princeton Instruments EMCCD Camera Files
127 * \ingroup picamCtrl
128 */
129
130/** MagAO-X application to control a Princeton Instruments EMCCD
131 *
132 * \ingroup picamCtrl
133 *
134 * \todo Config item for ImageStreamIO name filename
135 * \todo implement ImageStreamIO circular buffer, with config setting
136 */
137class picamCtrl : public MagAOXApp<>, public dev::stdCamera<picamCtrl>, public dev::frameGrabber<picamCtrl>, public dev::dssShutter<picamCtrl>, public dev::telemeter<picamCtrl>
138{
139
140 friend class dev::stdCamera<picamCtrl>;
141 friend class dev::frameGrabber<picamCtrl>;
142 friend class dev::dssShutter<picamCtrl>;
143 friend class dev::telemeter<picamCtrl>;
144
146
147public:
148 /** \name app::dev Configurations
149 *@{
150 */
151 static constexpr bool c_stdCamera_tempControl = true; ///< app::dev config to tell stdCamera to expose temperature controls
152
153 static constexpr bool c_stdCamera_temp = true; ///< app::dev config to tell stdCamera to expose temperature
154
155 static constexpr bool c_stdCamera_readoutSpeed = true; ///< app::dev config to tell stdCamera to expose readout speed controls
156
157 static constexpr bool c_stdCamera_vShiftSpeed = true; ///< app:dev config to tell stdCamera to expose vertical shift speed control
158
159 static constexpr bool c_stdCamera_emGain = true; ///< app::dev config to tell stdCamera to expose EM gain controls
160
161 static constexpr bool c_stdCamera_exptimeCtrl = true; ///< app::dev config to tell stdCamera to expose exposure time controls
162
163 static constexpr bool c_stdCamera_fpsCtrl = false; ///< app::dev config to tell stdCamera not to expose FPS controls
164
165 static constexpr bool c_stdCamera_fps = true; ///< app::dev config to tell stdCamera not to expose FPS status
166
167 static constexpr bool c_stdCamera_synchro = false; ///< app::dev config to tell stdCamera to not expose synchro mode controls
168
169 static constexpr bool c_stdCamera_usesModes = false; ///< app:dev config to tell stdCamera not to expose mode controls
170
171 static constexpr bool c_stdCamera_usesROI = true; ///< app:dev config to tell stdCamera to expose ROI controls
172
173 static constexpr bool c_stdCamera_cropMode = false; ///< app:dev config to tell stdCamera to expose Crop Mode controls
174
175 static constexpr bool c_stdCamera_hasShutter = true; ///< app:dev config to tell stdCamera to expose shutter controls
176
177 static constexpr bool c_stdCamera_usesStateString = false; ///< app::dev confg to tell stdCamera to expose the state string property
178
179 static constexpr bool c_frameGrabber_flippable = true; ///< app:dev config to tell framegrabber this camera can be flipped
180
181 ///@}
182
183protected:
184
185 /** \name configurable parameters
186 *@{
187 */
188 std::string m_serialNumber; ///< The camera's identifying serial number
189
190
191 ///@}
192
193 int m_depth {0};
194
196 pi64s m_tsRes; // time stamp resolution
198 double m_camera_timestamp {0.0};
201
202
203
204
205
206
207
210
213
214 std::string m_cameraName;
215 std::string m_cameraModel;
216
217public:
218
219 ///Default c'tor
220 picamCtrl();
221
222 ///Destructor
224
225 /// Setup the configuration system (called by MagAOXApp::setup())
226 virtual void setupConfig();
227
228 /// load the configuration system results (called by MagAOXApp::setup())
229 virtual void loadConfig();
230
231 /// Startup functions
232 /** Sets up the INDI vars.
233 *
234 */
235 virtual int appStartup();
236
237 /// Implementation of the FSM for the Siglent SDG
238 virtual int appLogic();
239
240 /// Implementation of the on-power-off FSM logic
241 virtual int onPowerOff();
242
243 /// Implementation of the while-powered-off FSM
245
246 /// Do any needed shutdown tasks. Currently nothing in this app.
247 virtual int appShutdown();
248
250 int getPicamParameter( piint & value,
252 );
253
254 int getPicamParameter( piflt & value,
256 );
257
259 pi64s value,
260 bool commit = true
261 );
262
264 piint value,
265 bool commit = true
266 );
267
270 piflt value,
271 bool commit = true
272 );
273
276 piint value,
277 bool commit = true
278 );
279
280
282 piflt value,
283 bool commit = true
284 );
285
288 piflt value
289 );
290
292 piflt value
293 );
294
297 piint value
298 );
299
301 piint value
302 );
303
304 int connect();
305
307
308 int getTemps();
309
310 // stdCamera interface:
311
312 //This must set the power-on default values of
313 /* -- m_ccdTempSetpt
314 * -- m_currentROI
315 */
316 int powerOnDefaults();
317
318 int setTempControl();
319 int setTempSetPt();
320 int setReadoutSpeed();
321 int setVShiftSpeed();
322 int setEMGain();
323 int setExpTime();
324 int capExpTime(piflt& exptime);
325 int setFPS();
326
327 /// Check the next ROI
328 /** Checks if the target values are valid and adjusts them to the closest valid values if needed.
329 *
330 * \returns 0 if successful
331 * \returns -1 otherwise
332 */
333 int checkNextROI();
334
335 int setNextROI();
336
337 /// Sets the shutter state, via call to dssShutter::setShutterState(int) [stdCamera interface]
338 /**
339 * \returns 0 always
340 */
341 int setShutter(int sh);
342
343 //Framegrabber interface:
345 float fps();
346 int startAcquisition();
348 int loadImageIntoStream(void * dest);
349 int reconfig();
350
351
352 //INDI:
354
356
357public:
359
360 /** \name Telemeter Interface
361 *
362 * @{
363 */
364 int checkRecordTimes();
365
367
368
369 ///@}
370};
371
372inline
374{
375 m_powerMgtEnabled = true;
376
377 m_acqBuff.memory_size = 0;
378 m_acqBuff.memory = 0;
379
380 m_defaultReadoutSpeed = "emccd_05MHz";
381 m_readoutSpeedNames = {"ccd_00_1MHz", "ccd_01MHz", "emccd_05MHz", "emccd_10MHz", "emccd_20MHz", "emccd_30MHz"};
382 m_readoutSpeedNameLabels = {"CCD 0.1 MHz", "CCD 1 MHz", "EMCCD 5 MHz", "EMCCD 10 MHz", "EMCCD 20 MHz", "EMCCD 30 MHz"};
383
384 m_defaultVShiftSpeed = "1_2us";
385 m_vShiftSpeedNames = {"0_7us", "1_2us", "2_0us", "5_0us"};
386 m_vShiftSpeedNameLabels = {"0.7 us", "1.2 us", "2.0 us", "5.0 us"};
387
388
389 m_default_x = 511.5;
390 m_default_y = 511.5;
391 m_default_w = 1024;
392 m_default_h = 1024;
393
394 m_full_x = 511.5;
395 m_full_y = 511.5;
396 m_full_w = 1024;
397 m_full_h = 1024;
398
399 m_maxEMGain = 1000;
400
401 return;
402}
403
404inline
406{
407 if(m_acqBuff.memory)
408 {
409 free(m_acqBuff.memory);
410 }
411
412 return;
413}
414
415inline
417{
418 config.add("camera.serialNumber", "", "camera.serialNumber", argType::Required, "camera", "serialNumber", false, "int", "The identifying serial number of the camera.");
419
424}
425
426inline
439
440inline
442{
443
444 // DELETE ME
445 //m_outfile = fopen("/home/xsup/test2.txt", "w");
446
447 createROIndiNumber( m_indiP_readouttime, "readout_time", "Readout Time (s)");
448 indi::addNumberElement<float>( m_indiP_readouttime, "value", 0.0, std::numeric_limits<float>::max(), 0.0, "%0.1f", "readout time");
450
451
452 m_minTemp = -55;
453 m_maxTemp = 25;
454 m_stepTemp = 0;
455
456 m_minROIx = 0;
457 m_maxROIx = 1023;
458 m_stepROIx = 0;
459
460 m_minROIy = 0;
461 m_maxROIy = 1023;
462 m_stepROIy = 0;
463
464 m_minROIWidth = 1;
465 m_maxROIWidth = 1024;
466 m_stepROIWidth = 4;
467
468 m_minROIHeight = 1;
469 m_maxROIHeight = 1024;
470 m_stepROIHeight = 1;
471
475
477 m_maxROIBinning_y = 1024;
479
481 {
483 }
484
486 {
488 }
489
491 {
493 }
494
496 {
497 return log<software_error,-1>({__FILE__,__LINE__});
498 }
499
500 return 0;
501
502}
503
504inline
506{
507 //and run stdCamera's appLogic
509 {
510 return log<software_error, -1>({__FILE__, __LINE__});
511 }
512
513 //first run frameGrabber's appLogic to see if the f.g. thread has exited.
515 {
516 return log<software_error, -1>({__FILE__, __LINE__});
517 }
518
519 //and run dssShutter's appLogic
521 {
522 return log<software_error, -1>({__FILE__, __LINE__});
523 }
524
525
527 {
528 m_reconfig = true; //Trigger a f.g. thread reconfig.
529
530 //Might have gotten here because of a power off.
531 if(powerState() != 1 || powerStateTarget() != 1) return 0;
532
533 std::unique_lock<std::mutex> lock(m_indiMutex);
534 if(connect() < 0)
535 {
536 if(powerState() != 1 || powerStateTarget() != 1) return 0;
538 }
539
540 if(state() != stateCodes::CONNECTED) return 0;
541 }
542
544 {
545 //Get a lock
546 std::unique_lock<std::mutex> lock(m_indiMutex);
547
548 if( getAcquisitionState() < 0 )
549 {
550 if(powerState() != 1 || powerStateTarget() != 1) return 0;
552 }
553
554 if( setTempSetPt() < 0 ) //m_ccdTempSetpt already set on power on
555 {
556 if(powerState() != 1 || powerStateTarget() != 1) return 0;
558 }
559
560
562 {
564 }
565
567
568
569 }
570
572 {
573 //Get a lock if we can
574 std::unique_lock<std::mutex> lock(m_indiMutex, std::try_to_lock);
575
576 //but don't wait for it, just go back around.
577 if(!lock.owns_lock()) return 0;
578
579 if(getAcquisitionState() < 0)
580 {
581 if(powerState() != 1 || powerStateTarget() != 1) return 0;
582
584 return 0;
585 }
586
587
588
589 if(getTemps() < 0)
590 {
591 if(powerState() != 1 || powerStateTarget() != 1) return 0;
592
594 return 0;
595 }
596
598 {
600 }
601
603 {
605 }
606
608 {
610 return 0;
611 }
612
613 }
614
615 //Fall through check?
616 return 0;
617
618}
619
620inline
622{
623 std::lock_guard<std::mutex> lock(m_indiMutex);
624
626 {
628 m_cameraHandle = 0;
629 }
630
632
634 {
636 }
637
639 {
641 }
642
643 return 0;
644}
645
646inline
648{
650 {
652 }
653
655 {
657 }
658
659 return 0;
660}
661
662inline
664{
666
668 {
670 m_cameraHandle = 0;
671 }
672
674
675 ///\todo error check these base class fxns.
678
679 return 0;
680}
681
682inline
685 )
686{
688
689 if(MagAOXAppT::m_powerState == 0) return -1; //Flag error but don't log
690
691 if(error != PicamError_None)
692 {
693 if(powerState() != 1 || powerStateTarget() != 1) return -1;
695 return -1;
696 }
697
698 return 0;
699}
700
701inline
704 )
705{
707
708 if(MagAOXAppT::m_powerState == 0) return -1; //Flag error but don't log
709
710 if(error != PicamError_None)
711 {
712 if(powerState() != 1 || powerStateTarget() != 1) return -1;
714 return -1;
715 }
716
717 return 0;
718}
719
720inline
722 pi64s value,
723 bool commit
724 )
725{
727 if(error != PicamError_None)
728 {
729 if(powerState() != 1 || powerStateTarget() != 1) return -1;
731 return -1;
732 }
733
734 if(!commit) return 0;
735
738
740 if(error != PicamError_None)
741 {
742 if(powerState() != 1 || powerStateTarget() != 1) return -1;
744 return -1;
745 }
746
747 for( int i=0; i< failed_parameters_count; ++i)
748 {
750 {
752 return log<text_log,-1>( "Parameter not committed");
753 }
754 }
755
757
758 return 0;
759}
760
761inline
764 piflt value,
765 bool commit
766 )
767{
769 if(error != PicamError_None)
770 {
771 if(powerState() != 1 || powerStateTarget() != 1) return -1;
773 return -1;
774 }
775
776 if(!commit) return 0;
777
780
782 if(error != PicamError_None)
783 {
784 if(powerState() != 1 || powerStateTarget() != 1) return -1;
786 return -1;
787 }
788
789 for( int i=0; i< failed_parameters_count; ++i)
790 {
792 {
794 return log<text_log,-1>( "Parameter not committed");
795 }
796 }
797
799
800 return 0;
801}
802
803inline
806 piint value,
807 bool commit
808 )
809{
811 if(error != PicamError_None)
812 {
813 if(powerState() != 1 || powerStateTarget() != 1) return -1;
815 return -1;
816 }
817
818 if(!commit) return 0;
819
822
824 if(error != PicamError_None)
825 {
826 if(powerState() != 1 || powerStateTarget() != 1) return -1;
828 return -1;
829 }
830
831 for( int i=0; i< failed_parameters_count; ++i)
832 {
834 {
836 return log<text_log,-1>( "Parameter not committed");
837 }
838 }
839
841
842 return 0;
843}
844
845inline
853
854inline
862
863inline
866 piflt value
867 )
868{
870 if(error != PicamError_None)
871 {
872 if(powerState() != 1 || powerStateTarget() != 1) return -1;
874 return -1;
875 }
876
877 return 0;
878}
879
880inline
887
888inline
891 piint value
892 )
893{
895 if(error != PicamError_None)
896 {
897 if(powerState() != 1 || powerStateTarget() != 1) return -1;
899 return -1;
900 }
901
902 return 0;
903}
904
905inline
912
913inline
915{
916
917 PicamError error;
920
921 if(m_acqBuff.memory)
922 {
923 free(m_acqBuff.memory);
924 m_acqBuff.memory = NULL;
925 m_acqBuff.memory_size = 0;
926 }
927
929
930 //Have to initialize the library every time. Otherwise we won't catch a newly booted camera.
932
934 {
936 m_cameraHandle = 0;
937 }
938
940
941 if(powerState() != 1 || powerStateTarget() != 1) return 0;
942
943 if(id_count == 0)
944 {
946
948
950 if(!stateLogged())
951 {
952 log<text_log>("no P.I. Cameras available.");
953 }
954 return 0;
955 }
956
957 for(int i=0; i< id_count; ++i)
958 {
959 if( std::string(id_array[i].serial_number) == m_serialNumber )
960 {
961 log<text_log>("Camera was found. Now connecting.");
962
964 if(error == PicamError_None)
965 {
966 m_cameraName = id_array[i].sensor_name;
968
970 if( error != PicamError_None )
971 {
972 log<software_error>({__FILE__, __LINE__, "failed to get camera model"});
973 }
974
976 log<text_log>("Connected to " + m_cameraName + " [S/N " + m_serialNumber + "]");
977
979
982
983 return 0;
984 }
985 else
986 {
987 if(powerState() != 1 || powerStateTarget() != 1) return 0;
988
990 if(!stateLogged())
991 {
992 log<software_error>({__FILE__,__LINE__, 0, error, "Error connecting to camera."});
993 }
994
996
998 return -1;
999 }
1000 }
1001 }
1002
1004 if(!stateLogged())
1005 {
1006 log<text_log>("Camera not found in available ids.");
1007 }
1008
1010
1011
1013
1014
1015 return 0;
1016}
1017
1018
1019inline
1021{
1022 pibln running = false;
1023
1025
1026 if(MagAOXAppT::m_powerState == 0) return 0;
1027
1028 if(error != PicamError_None)
1029 {
1030 if(powerState() != 1 || powerStateTarget() != 1) return -1;
1033 return -1;
1034 }
1035
1038
1039 if(!running)
1040 {
1041 log<text_log>("acqusition stopped. restarting", logPrio::LOG_ERROR);
1042 m_reconfig = true;
1043 }
1044
1045 return 0;
1046
1047}
1048
1049inline
1051{
1053
1055 {
1056 if(powerState() != 1 || powerStateTarget() != 1) return -1;
1057
1060 return -1;
1061 }
1062
1064
1065 //PicamSensorTemperatureStatus
1066 piint status;
1067
1069 {
1070 if(powerState() != 1 || powerStateTarget() != 1) return -1;
1071
1074 return -1;
1075 }
1076
1077 if(status == 1)
1078 {
1079 m_tempControlStatus = true;
1080 m_tempControlOnTarget = false;
1081 m_tempControlStatusStr = "UNLOCKED";
1082 }
1083 else if(status == 2)
1084 {
1085 m_tempControlStatus = true;
1086 m_tempControlOnTarget = true;
1087 m_tempControlStatusStr = "LOCKED";
1088 }
1089 else if(status == 3)
1090 {
1091 m_tempControlStatus = false;
1092 m_tempControlOnTarget = false;
1093 m_tempControlStatusStr = "FAULTED";
1094 log<text_log>("temperature control faulted", logPrio::LOG_ALERT);
1095 }
1096 else
1097 {
1098 m_tempControlStatus = false;
1099 m_tempControlOnTarget = false;
1100 m_tempControlStatusStr = "UNKNOWN";
1101 }
1102
1103 recordCamera();
1104
1105 return 0;
1106
1107}
1108
1109inline
1111{
1112 return 0;
1113}
1114
1115inline
1117{
1118 m_ccdTempSetpt = -55; //This is the power on setpoint
1119
1120 m_currentROI.x = 511.5;
1121 m_currentROI.y = 511.5;
1122 m_currentROI.w = 1024;
1123 m_currentROI.h = 1024;
1124 m_currentROI.bin_x = 1;
1125 m_currentROI.bin_y = 1;
1126
1127 m_readoutSpeedName = "emccd_05MHz";
1128 m_vShiftSpeedName = "1_2us";
1129 return 0;
1130}
1131
1132inline
1134{
1135 //Always on
1136 m_tempControlStatus = true;
1138 updateSwitchIfChanged(m_indiP_tempcont, "toggle", pcf::IndiElement::On, INDI_IDLE);
1139 recordCamera(true);
1140 return 0;
1141}
1142
1143inline
1145{
1146 ///\todo bounds check here.
1147 m_reconfig = true;
1148
1149 recordCamera(true);
1150 return 0;
1151}
1152
1153inline
1155{
1156 m_reconfig = true;
1157 recordCamera(true);
1158 return 0;
1159}
1160
1161inline
1163{
1164 m_reconfig = true;
1165 recordCamera(true);
1166 return 0;
1167}
1168
1169inline
1171{
1172 piint adcQual;
1173 piflt adcSpeed;
1174
1175 if(readoutParams(adcQual, adcSpeed, m_readoutSpeedName) < 0)
1176 {
1177 log<software_error>({__FILE__, __LINE__, "Invalid readout speed: " + m_readoutSpeedNameSet});
1179 return -1;
1180 }
1181
1183 {
1184 m_emGain = 1;
1185 m_adcSpeed = adcSpeed;
1186 recordCamera(true);
1187 log<text_log>("Attempt to set EM gain while in conventional amplifier.", logPrio::LOG_NOTICE);
1188 return 0;
1189 }
1190
1192 if(emg < 0)
1193 {
1194 emg = 0;
1195 log<text_log>("EM gain limited to 0", logPrio::LOG_WARNING);
1196 }
1197
1198 if(emg > m_maxEMGain)
1199 {
1200 emg = m_maxEMGain;
1201 log<text_log>("EM gain limited to maxEMGain = " + std::to_string(emg), logPrio::LOG_WARNING);
1202 }
1203
1204 recordCamera(true);
1206 {
1207 if(powerState() != 1 || powerStateTarget() != 1) return -1;
1208 log<software_error>({__FILE__, __LINE__, "Error setting EM gain"});
1209 return -1;
1210 }
1211
1214 {
1215 if(powerState() != 1 || powerStateTarget() != 1) return -1;
1216 return log<software_error,-1>({__FILE__, __LINE__, "could not get AdcEMGain"});
1217 }
1219 m_adcSpeed = adcSpeed;
1220 recordCamera(true);
1221 return 0;
1222}
1223
1224inline
1226{
1227 long intexptime = m_expTimeSet * 1000 * 10000 + 0.5;
1228 piflt exptime = ((double)intexptime)/10000;
1229 capExpTime(exptime);
1230
1231 int rv;
1232
1233 recordCamera(true);
1234
1236 {
1238 }
1239 else
1240 {
1242 }
1243
1244 if(rv < 0)
1245 {
1246 if(powerState() != 1 || powerStateTarget() != 1) return -1;
1247 log<software_error>({__FILE__, __LINE__, "Error setting exposure time"});
1248 return -1;
1249 }
1250
1251 m_expTime = exptime/1000.0;
1252
1253 recordCamera(true);
1254
1256
1258 {
1259 if(powerState() != 1 || powerStateTarget() != 1) return -1;
1260 log<software_error>({__FILE__, __LINE__, "could not get FrameRateCalculation"});
1261 }
1263
1264 recordCamera(true);
1265
1266 return 0;
1267}
1268
1269inline
1271{
1272 // cap at minimum possible value
1273 if(exptime < m_ReadOutTimeCalculation)
1274 {
1275 if(powerState() != 1 || powerStateTarget() != 1) return -1;
1276 log<text_log>("Got exposure time " + std::to_string(exptime) + " ms but min value is " + std::to_string(m_ReadOutTimeCalculation) + " ms");
1277 long intexptime = m_ReadOutTimeCalculation * 10000 + 0.5;
1278 exptime = ((double)intexptime)/10000;
1279 }
1280
1281 return 0;
1282}
1283
1284inline
1286{
1287 return 0;
1288}
1289
1290//Set ROI property to busy if accepted, set toggle to Off and Idlw either way.
1291//Set ROI actual
1292//Update current values (including struct and indiP) and set to OK when done
1293inline
1295{
1296 m_reconfig = true;
1297
1298 updateSwitchIfChanged(m_indiP_roi_set, "request", pcf::IndiElement::Off, INDI_IDLE);
1299
1300 return 0;
1301
1302}
1303
1304inline
1309
1310inline
1312{
1313
1317 //piint frameSize;
1319
1320 m_camera_timestamp = 0; // reset tracked timestamp
1321
1322 std::unique_lock<std::mutex> lock(m_indiMutex);
1323
1324
1325 // Time stamp handling
1327 {
1328 if(powerState() != 1 || powerStateTarget() != 1) return -1;
1329 log<software_error>({__FILE__,__LINE__, "Could not set time stamp mask"});
1330 }
1332 {
1333 if(powerState() != 1 || powerStateTarget() != 1) return -1;
1334 log<software_error>({__FILE__,__LINE__, "Could not get timestamp resolution"}) ;
1335 }
1336
1337 //=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
1338 //=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
1339 // Check Frame Transfer
1340 //=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
1341 //=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
1342
1343 piint cmode;
1345 {
1346 if(powerState() != 1 || powerStateTarget() != 1) return -1;
1347 log<software_error>({__FILE__,__LINE__, "could not get Readout Control Mode"});
1348 return -1;
1349 }
1350
1352 {
1353 if(powerState() != 1 || powerStateTarget() != 1) return -1;
1354 log<software_error>({__FILE__,__LINE__, "Readout Control Mode not configured for frame transfer"}) ;
1355 return -1;
1356 }
1357
1358 //=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
1359 //=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
1360 // Temperature
1361 //=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
1362 //=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
1363
1365 {
1366 if(powerState() != 1 || powerStateTarget() != 1) return -1;
1367 log<software_error>({__FILE__, __LINE__, "Error setting temperature setpoint"});
1369 return -1;
1370 }
1371
1372 //log<text_log>( "Set temperature set point: " + std::to_string(m_ccdTempSetpt) + " C");
1373
1374 //=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
1375 //=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
1376 // ADC Speed and Quality
1377 //=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
1378 //=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
1379
1380 piint adcQual;
1381 piflt adcSpeed;
1382
1383 if(readoutParams(adcQual, adcSpeed, m_readoutSpeedNameSet) < 0)
1384 {
1385 if(powerState() != 1 || powerStateTarget() != 1) return -1;
1386 log<software_error>({__FILE__, __LINE__, "Invalid readout speed: " + m_readoutSpeedNameSet});
1388 return -1;
1389 }
1390
1391 if( setPicamParameter(m_modelHandle, PicamParameter_AdcSpeed, adcSpeed, false) < 0) //don't commit b/c it will error if quality mismatched
1392 {
1393 if(powerState() != 1 || powerStateTarget() != 1) return -1;
1394 log<software_error>({__FILE__, __LINE__, "Error setting ADC Speed"});
1395 //state(stateCodes::ERROR);
1396 //return -1;
1397 }
1398
1400 {
1401 if(powerState() != 1 || powerStateTarget() != 1) return -1;
1402 log<software_error>({__FILE__, __LINE__, "Error setting ADC Quality"});
1404 return -1;
1405 }
1406 m_adcSpeed = adcSpeed;
1408 log<text_log>( "Readout speed set to: " + m_readoutSpeedNameSet);
1409
1411 {
1412 m_emGain = 1.0;
1413 m_emGainSet = 1.0;
1414 }
1415
1416 //=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
1417 //=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
1418 // Vertical Shift Rate
1419 //=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
1420 //=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
1421
1422 piflt vss;
1424 {
1425 if(powerState() != 1 || powerStateTarget() != 1) return -1;
1426 log<software_error>({__FILE__, __LINE__, "Invalid vertical shift speed: " + m_vShiftSpeedNameSet});
1428 return -1;
1429 }
1430
1432 {
1433 if(powerState() != 1 || powerStateTarget() != 1) return -1;
1434 log<software_error>({__FILE__, __LINE__, "Error setting Vertical Shift Rate"});
1436 return -1;
1437 }
1438
1441 log<text_log>( "Vertical Shift Rate set to: " + m_vShiftSpeedName);
1442
1443 //=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
1444 //=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
1445 // Dimensions
1446 //=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
1447 //=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
1448
1451
1452 nextrois.roi_array = &nextroi;
1453 nextrois.roi_count = 1;
1454
1455 int roi_err = false;
1457 {
1458 nextroi.x = ((1023-m_nextROI.x) - 0.5*( (float) m_nextROI.w - 1.0));
1459 }
1460 else
1461 {
1462 nextroi.x = (m_nextROI.x - 0.5*( (float) m_nextROI.w - 1.0));
1463 }
1464
1465 if(nextroi.x < 0)
1466 {
1467 log<software_error>({__FILE__, __LINE__, "can't set ROI to x center < 0"});
1468 roi_err = true;
1469 }
1470
1471 if(nextroi.x > 1023)
1472 {
1473 log<software_error>({__FILE__, __LINE__, "can't set ROI to x center > 1023"});
1474 roi_err = true;
1475 }
1476
1477
1479 {
1480 nextroi.y = ((1023 - m_nextROI.y) - 0.5*( (float) m_nextROI.h - 1.0));
1481 }
1482 else
1483 {
1484 nextroi.y = (m_nextROI.y - 0.5*( (float) m_nextROI.h - 1.0));
1485 }
1486
1487 if(nextroi.y < 0)
1488 {
1489 log<software_error>({__FILE__, __LINE__, "can't set ROI to y center < 0"});
1490 roi_err = true;
1491 }
1492
1493 if(nextroi.y > 1023)
1494 {
1495 log<software_error>({__FILE__, __LINE__, "can't set ROI to y center > 1023"});
1496 roi_err = true;
1497 }
1498
1499 nextroi.width = m_nextROI.w;
1500
1501 if(nextroi.width < 0)
1502 {
1503 log<software_error>({__FILE__, __LINE__, "can't set ROI to width to be < 0"});
1504 roi_err = true;
1505 }
1506
1507 if(nextroi.x + nextroi.width > 1024)
1508 {
1509 log<software_error>({__FILE__, __LINE__, "can't set ROI to width such that edge is > 1023"});
1510 roi_err = true;
1511 }
1512
1513 nextroi.height = m_nextROI.h;
1514
1515 if(nextroi.y + nextroi.height > 1024)
1516 {
1517 log<software_error>({__FILE__, __LINE__, "can't set ROI to height such that edge is > 1023"});
1518 roi_err = true;
1519 }
1520
1521 if(nextroi.height < 0)
1522 {
1523 log<software_error>({__FILE__, __LINE__, "can't set ROI to height to be < 0"});
1524 roi_err = true;
1525 }
1526
1527 nextroi.x_binning = m_nextROI.bin_x;
1528
1529 if(nextroi.x_binning < 0)
1530 {
1531 log<software_error>({__FILE__, __LINE__, "can't set ROI x binning < 0"});
1532 roi_err = true;
1533 }
1534
1535 nextroi.y_binning = m_nextROI.bin_y;
1536
1537 if(nextroi.y_binning < 0)
1538 {
1539 log<software_error>({__FILE__, __LINE__, "can't set ROI y binning < 0"});
1540 roi_err = true;
1541 }
1542
1543 PicamError error;
1544
1545 if(!roi_err)
1546 {
1548 if( error != PicamError_None )
1549 {
1550 if(powerState() != 1 || powerStateTarget() != 1) return -1;
1551 std::cerr << PicamEnum2String(PicamEnumeratedType_Error, error) << "\n";
1554 return -1;
1555 }
1556 }
1557
1559 {
1560 if(powerState() != 1 || powerStateTarget() != 1) return -1;
1561 log<software_error>({__FILE__, __LINE__, "Error getting readout stride"});
1563 return -1;
1564 }
1565
1567 {
1568 if(powerState() != 1 || powerStateTarget() != 1) return -1;
1569 log<software_error>({__FILE__, __LINE__, "Error getting frame stride"});
1571
1572 return -1;
1573 }
1574
1576 {
1577 if(powerState() != 1 || powerStateTarget() != 1) return -1;
1578 log<software_error>({__FILE__, __LINE__, "Error getting frames per readout"});
1580 return -1;
1581 }
1582
1584 {
1585 if(powerState() != 1 || powerStateTarget() != 1) return -1;
1586 log<software_error>({__FILE__, __LINE__, "Error getting frame size"});
1588 return -1;
1589 }
1590
1592 {
1593 if(powerState() != 1 || powerStateTarget() != 1) return -1;
1594 log<software_error>({__FILE__, __LINE__,"Error getting pixel bit depth"});
1596 return -1;
1597 }
1599
1600 const PicamRois* rois;
1602 if( error != PicamError_None )
1603 {
1604 if(powerState() != 1 || powerStateTarget() != 1) return -1;
1607 return -1;
1608 }
1609 m_xbinning = rois->roi_array[0].x_binning;
1610 m_currentROI.bin_x = m_xbinning;
1611 m_ybinning = rois->roi_array[0].y_binning;
1612 m_currentROI.bin_y = m_ybinning;
1613
1614 std::cerr << rois->roi_array[0].x << "\n";
1615 std::cerr << (rois->roi_array[0].x-1) << "\n";
1616 std::cerr << rois->roi_array[0].width << "\n";
1617 std::cerr << 0.5*( (float) (rois->roi_array[0].width - 1.0)) << "\n";
1618
1619
1621 {
1622 m_currentROI.x = (1023.0-rois->roi_array[0].x) - 0.5*( (float) (rois->roi_array[0].width - 1.0)) ;
1623 //nextroi.x = ((1023-m_nextROI.x) - 0.5*( (float) m_nextROI.w - 1.0));
1624 }
1625 else
1626 {
1627 m_currentROI.x = (rois->roi_array[0].x) + 0.5*( (float) (rois->roi_array[0].width - 1.0)) ;
1628 }
1629
1630
1632 {
1633 m_currentROI.y = (1023.0-rois->roi_array[0].y) - 0.5*( (float) (rois->roi_array[0].height - 1.0)) ;
1634 //nextroi.y = ((1023 - m_nextROI.y) - 0.5*( (float) m_nextROI.h - 1.0));
1635 }
1636 else
1637 {
1638 m_currentROI.y = (rois->roi_array[0].y) + 0.5*( (float) (rois->roi_array[0].height - 1.0)) ;
1639 }
1640
1641
1642
1643
1644
1645 m_currentROI.w = rois->roi_array[0].width;
1646 m_currentROI.h = rois->roi_array[0].height;
1647
1648 m_width = rois->roi_array[0].width / rois->roi_array[0].x_binning;
1649 m_height = rois->roi_array[0].height / rois->roi_array[0].y_binning;
1651
1652
1659
1660
1661 //We also update target to the settable values
1662 m_nextROI.x = m_currentROI.x;
1663 m_nextROI.y = m_currentROI.y;
1664 m_nextROI.w = m_currentROI.w;
1665 m_nextROI.h = m_currentROI.h;
1666 m_nextROI.bin_x = m_currentROI.bin_x;
1667 m_nextROI.bin_y = m_currentROI.bin_y;
1668
1675
1676
1677 //=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
1678 //=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
1679 // Exposure Time and Frame Rate
1680 //=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
1681 //=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
1682
1684 {
1685 if(powerState() != 1 || powerStateTarget() != 1) return -1;
1686 return log<software_error, -1>({__FILE__, __LINE__, "could not get ReadOutTimeCalculation"});
1687 }
1688 std::cerr << "Readout time is: " << m_ReadOutTimeCalculation << "\n";
1689 updateIfChanged( m_indiP_readouttime, "value", m_ReadOutTimeCalculation/1000.0, INDI_OK); // convert from msec to sec
1690
1694
1695 if(constraint_count != 1)
1696 {
1697 if(powerState() != 1 || powerStateTarget() != 1) return -1;
1698 log<text_log>("Constraint count is not 1: " + std::to_string(constraint_count) + " constraints",logPrio::LOG_ERROR);
1699 }
1700 else
1701 {
1702 m_minExpTime = constraint_array[0].minimum;
1703 m_maxExpTime = constraint_array[0].maximum;
1704 m_stepExpTime = constraint_array[0].increment;
1705
1706 m_indiP_exptime["current"].setMin(m_minExpTime);
1707 m_indiP_exptime["current"].setMax(m_maxExpTime);
1708 m_indiP_exptime["current"].setStep(m_stepExpTime);
1709
1710 m_indiP_exptime["target"].setMin(m_minExpTime);
1711 m_indiP_exptime["target"].setMax(m_maxExpTime);
1712 m_indiP_exptime["target"].setStep(m_stepExpTime);
1713 }
1714
1715 if(m_expTimeSet > 0)
1716 {
1717 long intexptime = m_expTimeSet * 1000 * 10000 + 0.5;
1718 piflt exptime = ((double)intexptime)/10000;
1719 capExpTime(exptime);
1720 std::cerr << "Setting exposure time to " << m_expTimeSet << "\n";
1722
1723 if(rv < 0)
1724 {
1725 if(powerState() != 1 || powerStateTarget() != 1) return -1;
1726 return log<software_error, -1>({__FILE__, __LINE__, "Error setting exposure time"});
1727 }
1728 }
1729
1730 piflt exptime;
1732 {
1733 if(powerState() != 1 || powerStateTarget() != 1) return -1;
1734 return log<software_error,-1>({__FILE__, __LINE__, "Error getting exposure time"});
1735 }
1736 else
1737 {
1738 capExpTime(exptime);
1739 m_expTime = exptime/1000.0;
1740 m_expTimeSet = m_expTime; //At this point it must be true.
1743 }
1744
1746 {
1747 if(powerState() != 1 || powerStateTarget() != 1) return -1;
1748 return log<software_error,-1>({__FILE__, __LINE__, "Error getting frame rate"});
1749 }
1750 else
1751 {
1754 }
1755 std::cerr << "FrameRate is: " << m_FrameRateCalculation << "\n";
1756
1759 {
1760 std::cerr << "could not get AdcQuality\n";
1761 }
1763 std::cerr << "AdcQuality is: " << adcqStr << "\n";
1764
1767 {
1768 std::cerr << "could not get VerticalShiftRate\n";
1769 }
1770 std::cerr << "VerticalShiftRate is: " << verticalShiftRate << "\n";
1771
1774 {
1775 std::cerr << "could not get AdcSpeed\n";
1776 }
1777 std::cerr << "AdcSpeed is: " << AdcSpeed << "\n";
1778
1779
1780 std::cerr << "************************************************************\n";
1781
1782
1785 {
1786 std::cerr << "could not get AdcAnalogGain\n";
1787 }
1789 std::cerr << "AdcAnalogGain is: " << adcgStr << "\n";
1790
1791 if(m_readoutSpeedName == "ccd_00_1MHz" || m_readoutSpeedName == "ccd_01MHz")
1792 {
1793 m_emGain = 1;
1794 }
1795 else
1796 {
1799 {
1800 std::cerr << "could not get AdcEMGain\n";
1801 }
1803 }
1804
1805/*
1806 std::cerr << "Onlineable:\n";
1807 pibln onlineable;
1808 Picam_CanSetParameterOnline(m_modelHandle, PicamParameter_ReadoutControlMode,&onlineable);
1809 std::cerr << "ReadoutControlMode: " << onlineable << "\n"; //0
1810
1811 Picam_CanSetParameterOnline(m_modelHandle, PicamParameter_AdcQuality,&onlineable);
1812 std::cerr << "AdcQuality: " << onlineable << "\n"; //0
1813
1814 Picam_CanSetParameterOnline(m_modelHandle, PicamParameter_AdcAnalogGain,&onlineable);
1815 std::cerr << "AdcAnalogGain: " << onlineable << "\n"; //1
1816
1817 Picam_CanSetParameterOnline(m_modelHandle, PicamParameter_DisableCoolingFan,&onlineable);
1818 std::cerr << "DisableCoolingFan: " << onlineable << "\n";//0
1819
1820 Picam_CanSetParameterOnline(m_modelHandle, PicamParameter_SensorTemperatureSetPoint,&onlineable);
1821 std::cerr << "SensorTemperatureSetPoint: " << onlineable << "\n"; //0
1822
1823 Picam_CanSetParameterOnline(m_modelHandle, PicamParameter_AdcEMGain,&onlineable);
1824 std::cerr << "AdcEMGain: " << onlineable << "\n"; //1
1825
1826 Picam_CanSetParameterOnline(m_modelHandle, PicamParameter_FrameRateCalculation,&onlineable);
1827 std::cerr << "FrameRateCalculation: " << onlineable << "\n"; //0
1828
1829 std::cerr << "************************************************************\n";
1830*/
1831
1832 //If not previously allocated, allocate a nice big buffer to play with
1833 pi64s newbuffsz = framesPerReadout*readoutStride*10; //Save room for 10 frames
1834 if( newbuffsz > m_acqBuff.memory_size)
1835 {
1836 if(m_acqBuff.memory)
1837 {
1838 std::cerr << "Clearing\n";
1839 free(m_acqBuff.memory);
1840 m_acqBuff.memory = NULL;
1842 }
1843
1844 m_acqBuff.memory_size = newbuffsz;
1845 std::cerr << "m_acqBuff.memory_size: " << m_acqBuff.memory_size << "\n";
1846 m_acqBuff.memory = malloc(m_acqBuff.memory_size);
1847
1849 if(error != PicamError_None)
1850 {
1853
1854 std::cerr << "-->" << PicamEnum2String(PicamEnumeratedType_Error, error) << "\n";
1855 }
1856 }
1857
1858 //Start continuous acquisition
1860 {
1861 log<software_error>({__FILE__, __LINE__, "Error setting readouts=0"});
1863 return -1;
1864 }
1865
1866 recordCamera();
1867
1869 if(error != PicamError_None)
1870 {
1873
1874 return -1;
1875 }
1876
1877 m_dataType = _DATATYPE_UINT16; //Where does this go?
1878
1879 return 0;
1880
1881}
1882
1883inline
1885{
1886 return m_fps;
1887}
1888
1889inline
1891{
1892 return 0;
1893}
1894
1895inline
1897{
1898 piint camTimeOut = 1000; //1 second keeps us responsive without busy-waiting too much
1899
1901
1903
1904 PicamError error;
1906
1907 if(error == PicamError_TimeOutOccurred)
1908 {
1909 return 1; //This sends it back to framegrabber to check for reconfig, etc.
1910 }
1911
1913
1914 if(error != PicamError_None)
1915 {
1918
1919 return -1;
1920 }
1921
1922 m_available.initial_readout = available.initial_readout;
1923 m_available.readout_count = available.readout_count;
1924
1925 if(m_available.initial_readout == 0)
1926 {
1927 return 1;
1928 }
1929
1930 //std::cerr << "readout: " << m_available.initial_readout << " " << m_available.readout_count << "\n";
1931
1932 // camera time stamp
1933 pibyte *frame = NULL;
1935
1936 frame = static_cast<pibyte*>(m_available.initial_readout);
1937 metadataOffset = (pi64s)frame + m_frameSize;
1938
1939 pi64s *tmpPtr = reinterpret_cast<pi64s*>(metadataOffset);
1940
1941 double cam_ts = (double)*tmpPtr/(double)m_tsRes;
1943
1944 // check for a frame skip
1945 if(delta_ts > 1.5 / m_FrameRateCalculation){
1946 std::cerr << "Skipped frame(s)! (Expected a " << 1000./m_FrameRateCalculation << " ms gap but got " << 1000*delta_ts << " ms)\n";
1947 }
1948 // print
1949
1950 m_camera_timestamp = cam_ts; // update to latest
1951
1952 //fprintf(m_outfile, "%d %-15.8f\n", m_imageStream->md->cnt0+1, (double)*tmpPtr/(double)m_tsRes);
1953
1954 return 0;
1955
1956}
1957
1958inline
1960{
1961 if( frameGrabber<picamCtrl>::loadImageIntoStreamCopy(dest, m_available.initial_readout, m_width, m_height, m_typeSize) == nullptr) return -1;
1962
1963 return 0;
1964}
1965
1966inline
1968{
1969 ///\todo clean this up. Just need to wait on acquisition update the first time probably.
1970
1972 if(error != PicamError_None)
1973 {
1976
1977 return -1;
1978 }
1979
1980 pibln running = true;
1981
1983
1984 while(running)
1985 {
1986 if(MagAOXAppT::m_powerState == 0) return 0;
1987 sleep(1);
1988
1990
1991 if(error != PicamError_None)
1992 {
1995 return -1;
1996 }
1997
1998 piint camTimeOut = 1000;
1999
2001
2003
2005 if(error != PicamError_None)
2006 {
2009 return -1;
2010 }
2011
2012// if(! status.running )
2013// {
2014// std::cerr << "Not running \n";
2015//
2016// std::cerr << "status.running: " << status.running << "\n";
2017// std::cerr << "status.errors: " << status.errors << "\n";
2018// std::cerr << "CameraFaulted: " << (int)(status.errors & PicamAcquisitionErrorsMask_CameraFaulted) << "\n";
2019// std::cerr << "CannectionLost: " << (int)(status.errors & PicamAcquisitionErrorsMask_ConnectionLost) << "\n";
2020// std::cerr << "DataLost: " << (int)(status.errors & PicamAcquisitionErrorsMask_DataLost) << "\n";
2021// std::cerr << "DataNotArriving: " << (int)(status.errors & PicamAcquisitionErrorsMask_DataNotArriving) << "\n";
2022// std::cerr << "None: " << (int)(status.errors & PicamAcquisitionErrorsMask_None) << "\n";
2023// std::cerr << "ShutterOverheated: " << (int)(status.errors & PicamAcquisitionErrorsMask_ShutterOverheated) << "\n";
2024// std::cerr << "status.readout_rate: " << status.readout_rate << "\n";
2025// }
2026
2028 if(error != PicamError_None)
2029 {
2032 return -1;
2033 }
2034 }
2035
2036 return 0;
2037}
2038
2039
2040
2045
2047{
2048 return recordCamera(true);
2049}
2050
2051
2052
2053}//namespace app
2054} //namespace MagAOX
2055#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_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.
int createROIndiNumber(pcf::IndiProperty &prop, const std::string &propName, const std::string &propLabel="", const std::string &propGroup="")
Create a ReadOnly INDI Number property.
int registerIndiPropertyReadOnly(pcf::IndiProperty &prop)
Register an INDI property which is read only.
std::mutex m_indiMutex
Mutex for locking INDI communications.
MagAO-X Uniblitz DSS Shutter interface.
void loadConfig(mx::app::appConfigurator &config)
load the configuration system results
int appShutdown()
applogic shutdown
void setupConfig(mx::app::appConfigurator &config)
Setup the configuration system.
int m_xbinning
The x-binning according to the framegrabber.
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
int m_ybinning
The y-binning according to the framegrabber.
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
float m_minExpTime
The minimum exposure time, used for INDI attributes.
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()
std::string m_defaultReadoutSpeed
The default readout speed of the camera.
float m_expTime
The current exposure time, in seconds.
float m_maxExpTime
The maximum exposure time, used for INDI attributes.
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.
pcf::IndiProperty m_indiP_roi_bin_x
Property used to set the ROI x binning.
float m_full_x
The full ROI center x coordinate.
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.
float m_stepExpTime
The maximum exposure time stepsize, used for INDI attributes.
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.
bool m_tempControlStatusSet
Desired state of temperature control.
std::string m_readoutSpeedNameSet
The user requested readout speed name, to be set by derived()
int recordTelem(const telem_stdcam *)
int loadImageIntoStream(void *dest)
static constexpr bool c_stdCamera_usesROI
app:dev config to tell stdCamera to expose ROI controls
virtual void loadConfig()
load the configuration system results (called by MagAOXApp::setup())
std::string m_cameraModel
std::string m_serialNumber
The camera's identifying serial number.
static constexpr bool c_stdCamera_exptimeCtrl
app::dev config to tell stdCamera to expose exposure time controls
static constexpr bool c_stdCamera_synchro
app::dev config to tell stdCamera to not expose synchro mode controls
int setShutter(int sh)
Sets the shutter state, via call to dssShutter::setShutterState(int) [stdCamera interface].
virtual int appShutdown()
Do any needed shutdown tasks. Currently nothing in this app.
static constexpr bool c_stdCamera_vShiftSpeed
app:dev config to tell stdCamera to expose vertical shift speed control
virtual void setupConfig()
Setup the configuration system (called by MagAOXApp::setup())
int checkNextROI()
Check the next ROI.
PicamHandle m_cameraHandle
static constexpr bool c_stdCamera_fpsCtrl
app::dev config to tell stdCamera not to expose FPS controls
static constexpr bool c_stdCamera_cropMode
app:dev config to tell stdCamera to expose Crop Mode controls
PicamHandle m_modelHandle
static constexpr bool c_stdCamera_hasShutter
app:dev config to tell stdCamera to expose shutter controls
static constexpr bool c_stdCamera_tempControl
app::dev config to tell stdCamera to expose temperature controls
static constexpr bool c_stdCamera_temp
app::dev config to tell stdCamera to expose temperature
~picamCtrl() noexcept
Destructor.
static constexpr bool c_stdCamera_emGain
app::dev config to tell stdCamera to expose EM gain controls
pcf::IndiProperty m_indiP_readouttime
virtual int whilePowerOff()
Implementation of the while-powered-off FSM.
int getPicamParameter(piint &value, PicamParameter parameter)
picamCtrl()
Default c'tor.
int setPicamParameter(PicamParameter parameter, pi64s value, bool commit=true)
static constexpr bool c_stdCamera_readoutSpeed
app::dev config to tell stdCamera to expose readout speed controls
virtual int onPowerOff()
Implementation of the on-power-off FSM logic.
static constexpr bool c_stdCamera_usesModes
app:dev config to tell stdCamera not to expose mode controls
static constexpr bool c_stdCamera_usesStateString
app::dev confg to tell stdCamera to expose the state string property
int setPicamParameterOnline(PicamHandle handle, PicamParameter parameter, piflt value)
static constexpr bool c_frameGrabber_flippable
app:dev config to tell framegrabber this camera can be flipped
PicamAvailableData m_available
static constexpr bool c_stdCamera_fps
app::dev config to tell stdCamera not to expose FPS status
virtual int appStartup()
Startup functions.
virtual int appLogic()
Implementation of the FSM for the Siglent SDG.
PicamAcquisitionBuffer m_acqBuff
int capExpTime(piflt &exptime)
#define INDI_NEWCALLBACK_DECL(class, prop)
Declare the callback for a new property request, and declare and define the static wrapper.
@ OPERATING
The device is operating, other than homing.
@ NODEVICE
No device exists for the application to control.
@ 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.
#define INDI_IDLE
Definition indiUtils.hpp:28
#define INDI_OK
Definition indiUtils.hpp:29
int readoutParams(int &newa, int &newhss, const std::string &ron)
int vshiftParams(int &newvs, const std::string &vssn, float &vs)
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.
static constexpr logPrioT LOG_ALERT
This should only be used if some action is required by operators to keep the system safe.
std::string PicamEnum2String(PicamEnumeratedType type, piint value)
Definition picamCtrl.hpp:30
A device base class which saves telemetry.
Definition telemeter.hpp:69
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