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 m_full_x = 511.5;
389 m_full_y = 511.5;
390 m_full_w = 1024;
391 m_full_h = 1024;
392
393 m_maxEMGain = 1000;
394
395 return;
396}
397
398inline
400{
401 if(m_acqBuff.memory)
402 {
403 free(m_acqBuff.memory);
404 }
405
406 return;
407}
408
409inline
411{
412 config.add("camera.serialNumber", "", "camera.serialNumber", argType::Required, "camera", "serialNumber", false, "int", "The identifying serial number of the camera.");
413
418}
419
420inline
433
434inline
436{
437
438 // DELETE ME
439 //m_outfile = fopen("/home/xsup/test2.txt", "w");
440
441 createROIndiNumber( m_indiP_readouttime, "readout_time", "Readout Time (s)");
442 indi::addNumberElement<float>( m_indiP_readouttime, "value", 0.0, std::numeric_limits<float>::max(), 0.0, "%0.1f", "readout time");
444
445
446 m_minTemp = -55;
447 m_maxTemp = 25;
448 m_stepTemp = 0;
449
450 m_minROIx = 0;
451 m_maxROIx = 1023;
452 m_stepROIx = 0;
453
454 m_minROIy = 0;
455 m_maxROIy = 1023;
456 m_stepROIy = 0;
457
458 m_minROIWidth = 1;
459 m_maxROIWidth = 1024;
460 m_stepROIWidth = 4;
461
462 m_minROIHeight = 1;
463 m_maxROIHeight = 1024;
464 m_stepROIHeight = 1;
465
469
471 m_maxROIBinning_y = 1024;
473
475 {
477 }
478
480 {
482 }
483
485 {
487 }
488
490 {
491 return log<software_error,-1>({__FILE__,__LINE__});
492 }
493
494 return 0;
495
496}
497
498inline
500{
501 //and run stdCamera's appLogic
503 {
504 return log<software_error, -1>({__FILE__, __LINE__});
505 }
506
507 //first run frameGrabber's appLogic to see if the f.g. thread has exited.
509 {
510 return log<software_error, -1>({__FILE__, __LINE__});
511 }
512
513 //and run dssShutter's appLogic
515 {
516 return log<software_error, -1>({__FILE__, __LINE__});
517 }
518
519
521 {
522 m_reconfig = true; //Trigger a f.g. thread reconfig.
523
524 //Might have gotten here because of a power off.
525 if(powerState() != 1 || powerStateTarget() != 1) return 0;
526
527 std::cerr << __LINE__ << '\n';
528 std::unique_lock<std::mutex> lock(m_indiMutex);
529 if(connect() < 0)
530 {
531 if(powerState() != 1 || powerStateTarget() != 1) return 0;
533 }
534
535 if(state() != stateCodes::CONNECTED) return 0;
536 }
537
539 {
540 //Get a lock
541 std::unique_lock<std::mutex> lock(m_indiMutex);
542
543 if( getAcquisitionState() < 0 )
544 {
545 if(powerState() != 1 || powerStateTarget() != 1) return 0;
547 }
548
549 if( setTempSetPt() < 0 ) //m_ccdTempSetpt already set on power on
550 {
551 if(powerState() != 1 || powerStateTarget() != 1) return 0;
553 }
554
555
557 {
559 }
560
562
563
564 }
565
567 {
568 //Get a lock if we can
569 std::unique_lock<std::mutex> lock(m_indiMutex, std::try_to_lock);
570
571 //but don't wait for it, just go back around.
572 if(!lock.owns_lock()) return 0;
573
574 if(getAcquisitionState() < 0)
575 {
576 if(powerState() != 1 || powerStateTarget() != 1) return 0;
577
579 return 0;
580 }
581
582
583
584 if(getTemps() < 0)
585 {
586 if(powerState() != 1 || powerStateTarget() != 1) return 0;
587
589 return 0;
590 }
591
593 {
595 }
596
598 {
600 }
601
603 {
605 return 0;
606 }
607
608 }
609
610 //Fall through check?
611 return 0;
612
613}
614
615inline
617{
618 std::lock_guard<std::mutex> lock(m_indiMutex);
619
621 {
623 m_cameraHandle = 0;
624 }
625
627
629 {
631 }
632
634 {
636 }
637
638 return 0;
639}
640
641inline
643{
645 {
647 }
648
650 {
652 }
653
654 return 0;
655}
656
657inline
659{
661
663 {
665 m_cameraHandle = 0;
666 }
667
669
670 ///\todo error check these base class fxns.
673
674 return 0;
675}
676
677inline
680 )
681{
683
684 if(MagAOXAppT::m_powerState == 0) return -1; //Flag error but don't log
685
687 {
688 if(powerState() != 1 || powerStateTarget() != 1) return -1;
690 return -1;
691 }
692
693 return 0;
694}
695
696inline
699 )
700{
702
703 if(MagAOXAppT::m_powerState == 0) return -1; //Flag error but don't log
704
706 {
707 if(powerState() != 1 || powerStateTarget() != 1) return -1;
709 return -1;
710 }
711
712 return 0;
713}
714
715inline
717 pi64s value,
718 bool commit
719 )
720{
723 {
724 if(powerState() != 1 || powerStateTarget() != 1) return -1;
726 return -1;
727 }
728
729 if(!commit) return 0;
730
733
736 {
737 if(powerState() != 1 || powerStateTarget() != 1) return -1;
739 return -1;
740 }
741
742 for( int i=0; i< failed_parameters_count; ++i)
743 {
745 {
747 return log<text_log,-1>( "Parameter not committed");
748 }
749 }
750
752
753 return 0;
754}
755
756inline
759 piflt value,
760 bool commit
761 )
762{
765 {
766 if(powerState() != 1 || powerStateTarget() != 1) return -1;
768 return -1;
769 }
770
771 if(!commit) return 0;
772
775
778 {
779 if(powerState() != 1 || powerStateTarget() != 1) return -1;
781 return -1;
782 }
783
784 for( int i=0; i< failed_parameters_count; ++i)
785 {
787 {
789 return log<text_log,-1>( "Parameter not committed");
790 }
791 }
792
794
795 return 0;
796}
797
798inline
801 piint value,
802 bool commit
803 )
804{
807 {
808 if(powerState() != 1 || powerStateTarget() != 1) return -1;
810 return -1;
811 }
812
813 if(!commit) return 0;
814
817
820 {
821 if(powerState() != 1 || powerStateTarget() != 1) return -1;
823 return -1;
824 }
825
826 for( int i=0; i< failed_parameters_count; ++i)
827 {
829 {
831 return log<text_log,-1>( "Parameter not committed");
832 }
833 }
834
836
837 return 0;
838}
839
840inline
848
849inline
857
858inline
874
875inline
882
883inline
899
900inline
907
908inline
910{
911 std::cerr << __LINE__ << '\n';
915
916 if(m_acqBuff.memory)
917 {
918 free(m_acqBuff.memory);
919 m_acqBuff.memory = NULL;
920 m_acqBuff.memory_size = 0;
921 }
922
923 std::cerr << __LINE__ << '\n';
924
926
927 std::cerr << __LINE__ << '\n';
928
929 //Have to initialize the library every time. Otherwise we won't catch a newly booted camera.
931
932 std::cerr << __LINE__ << '\n';
933
935 {
937 m_cameraHandle = 0;
938 }
939
940 std::cerr << __LINE__ << '\n';
941
943
944 std::cerr << __LINE__ << '\n';
945
946 if(powerState() != 1 || powerStateTarget() != 1) return 0;
947
948 std::cerr << __LINE__ << '\n';
949
950 if(id_count == 0)
951 {
953
955
957 if(!stateLogged())
958 {
959 log<text_log>("no P.I. Cameras available.", logPrio::LOG_NOTICE);
960 }
961 return 0;
962 }
963 else
964 {
965 std::cerr << "found " << id_count << " PI cameras.\n";
966 }
967
968 for(int i=0; i< id_count; ++i)
969 {
970 if( std::string(id_array[i].serial_number) == m_serialNumber )
971 {
972 log<text_log>("Camera was found. Now connecting.");
973
976 {
977 m_cameraName = id_array[i].sensor_name;
979
981 if( error != PicamError_None )
982 {
983 log<software_error>({__FILE__, __LINE__, "failed to get camera model"});
984 }
985
987 log<text_log>("Connected to " + m_cameraName + " [S/N " + m_serialNumber + "]");
988
990
993
994 return 0;
995 }
996 else
997 {
998 if(powerState() != 1 || powerStateTarget() != 1) return 0;
999
1001 if(!stateLogged())
1002 {
1003 log<software_error>({__FILE__,__LINE__, 0, error, "Error connecting to camera."});
1004 }
1005
1007
1009 return -1;
1010 }
1011 }
1012 }
1013
1015 if(!stateLogged())
1016 {
1017 log<text_log>("Camera not found in available ids.");
1018 }
1019
1021
1022
1024
1025
1026 return 0;
1027}
1028
1029
1030inline
1032{
1033 pibln running = false;
1034
1036
1037 if(MagAOXAppT::m_powerState == 0) return 0;
1038
1039 if(error != PicamError_None)
1040 {
1041 if(powerState() != 1 || powerStateTarget() != 1) return -1;
1044 return -1;
1045 }
1046
1049
1050 if(!running)
1051 {
1052 log<text_log>("acqusition stopped. restarting", logPrio::LOG_ERROR);
1053 m_reconfig = true;
1054 }
1055
1056 return 0;
1057
1058}
1059
1060inline
1062{
1064
1066 {
1067 if(powerState() != 1 || powerStateTarget() != 1) return -1;
1068
1071 return -1;
1072 }
1073
1075
1076 //PicamSensorTemperatureStatus
1077 piint status;
1078
1080 {
1081 if(powerState() != 1 || powerStateTarget() != 1) return -1;
1082
1085 return -1;
1086 }
1087
1089 {
1090 m_tempControlStatus = true;
1091 m_tempControlOnTarget = false;
1092 m_tempControlStatusStr = "UNLOCKED";
1093 }
1094 else if(status == PicamSensorTemperatureStatus_Locked)
1095 {
1096 m_tempControlStatus = true;
1097 m_tempControlOnTarget = true;
1098 m_tempControlStatusStr = "LOCKED";
1099 }
1100 else if(status == PicamSensorTemperatureStatus_Faulted)
1101 {
1102 m_tempControlStatus = false;
1103 m_tempControlOnTarget = false;
1104 m_tempControlStatusStr = "FAULTED";
1105 log<text_log>("temperature control faulted", logPrio::LOG_ALERT);
1106 }
1107 else
1108 {
1109 m_tempControlStatus = false;
1110 m_tempControlOnTarget = false;
1111 m_tempControlStatusStr = "UNKNOWN";
1112 }
1113
1114 recordCamera();
1115
1116 return 0;
1117
1118}
1119
1120inline
1122{
1123 return 0;
1124}
1125
1126inline
1128{
1129 m_ccdTempSetpt = -55; //This is the power on setpoint
1130
1131 /*m_currentROI.x = 511.5;
1132 m_currentROI.y = 511.5;
1133 m_currentROI.w = 1024;
1134 m_currentROI.h = 1024;
1135 m_currentROI.bin_x = 1;
1136 m_currentROI.bin_y = 1;*/
1137
1138 m_readoutSpeedName = "emccd_05MHz";
1139 m_vShiftSpeedName = "1_2us";
1140 return 0;
1141}
1142
1143inline
1145{
1146 //Always on
1147 m_tempControlStatus = true;
1149 updateSwitchIfChanged(m_indiP_tempcont, "toggle", pcf::IndiElement::On, INDI_IDLE);
1150 recordCamera(true);
1151 return 0;
1152}
1153
1154inline
1156{
1157 ///\todo bounds check here.
1158 m_reconfig = true;
1159
1160 recordCamera(true);
1161 return 0;
1162}
1163
1164inline
1166{
1167 m_reconfig = true;
1168 recordCamera(true);
1169 return 0;
1170}
1171
1172inline
1174{
1175 m_reconfig = true;
1176 recordCamera(true);
1177 return 0;
1178}
1179
1180inline
1182{
1183 piint adcQual;
1184 piflt adcSpeed;
1185
1186 if(readoutParams(adcQual, adcSpeed, m_readoutSpeedName) < 0)
1187 {
1188 log<software_error>({__FILE__, __LINE__, "Invalid readout speed: " + m_readoutSpeedNameSet});
1190 return -1;
1191 }
1192
1194 {
1195 m_emGain = 1;
1196 m_adcSpeed = adcSpeed;
1197 recordCamera(true);
1198 log<text_log>("Attempt to set EM gain while in conventional amplifier.", logPrio::LOG_NOTICE);
1199 return 0;
1200 }
1201
1203 if(emg < 0)
1204 {
1205 emg = 0;
1206 log<text_log>("EM gain limited to 0", logPrio::LOG_WARNING);
1207 }
1208
1209 if(emg > m_maxEMGain)
1210 {
1211 emg = m_maxEMGain;
1212 log<text_log>("EM gain limited to maxEMGain = " + std::to_string(emg), logPrio::LOG_WARNING);
1213 }
1214
1215 recordCamera(true);
1217 {
1218 if(powerState() != 1 || powerStateTarget() != 1) return -1;
1219 log<software_error>({__FILE__, __LINE__, "Error setting EM gain"});
1220 return -1;
1221 }
1222
1225 {
1226 if(powerState() != 1 || powerStateTarget() != 1) return -1;
1227 return log<software_error,-1>({__FILE__, __LINE__, "could not get AdcEMGain"});
1228 }
1230 m_adcSpeed = adcSpeed;
1231 recordCamera(true);
1232 return 0;
1233}
1234
1235inline
1237{
1238 long intexptime = m_expTimeSet * 1000 * 10000 + 0.5;
1239 piflt exptime = ((double)intexptime)/10000;
1240 capExpTime(exptime);
1241
1242 int rv;
1243
1244 recordCamera(true);
1245
1247 {
1249 }
1250 else
1251 {
1253 }
1254
1255 if(rv < 0)
1256 {
1257 if(powerState() != 1 || powerStateTarget() != 1) return -1;
1258 log<software_error>({__FILE__, __LINE__, "Error setting exposure time"});
1259 return -1;
1260 }
1261
1262 m_expTime = exptime/1000.0;
1263
1264 recordCamera(true);
1265
1267
1269 {
1270 if(powerState() != 1 || powerStateTarget() != 1) return -1;
1271 log<software_error>({__FILE__, __LINE__, "could not get FrameRateCalculation"});
1272 }
1274
1275 recordCamera(true);
1276
1277 return 0;
1278}
1279
1280inline
1282{
1283 // cap at minimum possible value
1284 if(exptime < m_ReadOutTimeCalculation)
1285 {
1286 if(powerState() != 1 || powerStateTarget() != 1) return -1;
1287 log<text_log>("Got exposure time " + std::to_string(exptime) + " ms but min value is " + std::to_string(m_ReadOutTimeCalculation) + " ms");
1288 long intexptime = m_ReadOutTimeCalculation * 10000 + 0.5;
1289 exptime = ((double)intexptime)/10000;
1290 }
1291
1292 return 0;
1293}
1294
1295inline
1297{
1298 return 0;
1299}
1300
1301//Set ROI property to busy if accepted, set toggle to Off and Idlw either way.
1302//Set ROI actual
1303//Update current values (including struct and indiP) and set to OK when done
1304inline
1306{
1307 m_reconfig = true;
1308
1309 updateSwitchIfChanged(m_indiP_roi_set, "request", pcf::IndiElement::Off, INDI_IDLE);
1310
1311 return 0;
1312
1313}
1314
1315inline
1320
1321inline
1323{
1324
1328 //piint frameSize;
1330
1331 m_camera_timestamp = 0; // reset tracked timestamp
1332
1333 std::unique_lock<std::mutex> lock(m_indiMutex);
1334
1335
1336 // Time stamp handling
1338 {
1339 if(powerState() != 1 || powerStateTarget() != 1) return -1;
1340 log<software_error>({__FILE__,__LINE__, "Could not set time stamp mask"});
1341 }
1343 {
1344 if(powerState() != 1 || powerStateTarget() != 1) return -1;
1345 log<software_error>({__FILE__,__LINE__, "Could not get timestamp resolution"}) ;
1346 }
1347
1348 //=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
1349 //=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
1350 // Check Frame Transfer
1351 //=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
1352 //=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
1353
1354 piint cmode;
1356 {
1357 if(powerState() != 1 || powerStateTarget() != 1) return -1;
1358 log<software_error>({__FILE__,__LINE__, "could not get Readout Control Mode"});
1359 return -1;
1360 }
1361
1363 {
1364 if(powerState() != 1 || powerStateTarget() != 1) return -1;
1365 log<software_error>({__FILE__,__LINE__, "Readout Control Mode not configured for frame transfer"}) ;
1366 return -1;
1367 }
1368
1369 //=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
1370 //=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
1371 // Temperature
1372 //=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
1373 //=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
1374
1376 {
1377 if(powerState() != 1 || powerStateTarget() != 1) return -1;
1378 log<software_error>({__FILE__, __LINE__, "Error setting temperature setpoint"});
1380 return -1;
1381 }
1382
1383 //log<text_log>( "Set temperature set point: " + std::to_string(m_ccdTempSetpt) + " C");
1384
1385 //=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
1386 //=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
1387 // ADC Speed and Quality
1388 //=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
1389 //=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
1390
1391 piint adcQual;
1392 piflt adcSpeed;
1393
1394 if(readoutParams(adcQual, adcSpeed, m_readoutSpeedNameSet) < 0)
1395 {
1396 if(powerState() != 1 || powerStateTarget() != 1) return -1;
1397 log<software_error>({__FILE__, __LINE__, "Invalid readout speed: " + m_readoutSpeedNameSet});
1399 return -1;
1400 }
1401
1402 if( setPicamParameter(m_modelHandle, PicamParameter_AdcSpeed, adcSpeed, false) < 0) //don't commit b/c it will error if quality mismatched
1403 {
1404 if(powerState() != 1 || powerStateTarget() != 1) return -1;
1405 log<software_error>({__FILE__, __LINE__, "Error setting ADC Speed"});
1406 //state(stateCodes::ERROR);
1407 //return -1;
1408 }
1409
1411 {
1412 if(powerState() != 1 || powerStateTarget() != 1) return -1;
1413 log<software_error>({__FILE__, __LINE__, "Error setting ADC Quality"});
1415 return -1;
1416 }
1417 m_adcSpeed = adcSpeed;
1419 log<text_log>( "Readout speed set to: " + m_readoutSpeedNameSet);
1420
1422 {
1423 m_emGain = 1.0;
1424 m_emGainSet = 1.0;
1425 }
1426
1427 //=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
1428 //=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
1429 // Vertical Shift Rate
1430 //=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
1431 //=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
1432
1433 piflt vss;
1435 {
1436 if(powerState() != 1 || powerStateTarget() != 1) return -1;
1437 log<software_error>({__FILE__, __LINE__, "Invalid vertical shift speed: " + m_vShiftSpeedNameSet});
1439 return -1;
1440 }
1441
1443 {
1444 if(powerState() != 1 || powerStateTarget() != 1) return -1;
1445 log<software_error>({__FILE__, __LINE__, "Error setting Vertical Shift Rate"});
1447 return -1;
1448 }
1449
1452 log<text_log>( "Vertical Shift Rate set to: " + m_vShiftSpeedName);
1453
1454 //=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
1455 //=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
1456 // Dimensions
1457 //=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
1458 //=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
1459
1462
1463 nextrois.roi_array = &nextroi;
1464 nextrois.roi_count = 1;
1465
1466 int roi_err = false;
1468 {
1469 nextroi.x = ((1023-m_nextROI.x) - 0.5*( (float) m_nextROI.w - 1.0));
1470 }
1471 else
1472 {
1473 nextroi.x = (m_nextROI.x - 0.5*( (float) m_nextROI.w - 1.0));
1474 }
1475
1476 if(nextroi.x < 0)
1477 {
1478 log<software_error>({__FILE__, __LINE__, "can't set ROI to x center < 0"});
1479 roi_err = true;
1480 }
1481
1482 if(nextroi.x > 1023)
1483 {
1484 log<software_error>({__FILE__, __LINE__, "can't set ROI to x center > 1023"});
1485 roi_err = true;
1486 }
1487
1488
1490 {
1491 nextroi.y = ((1023 - m_nextROI.y) - 0.5*( (float) m_nextROI.h - 1.0));
1492 }
1493 else
1494 {
1495 nextroi.y = (m_nextROI.y - 0.5*( (float) m_nextROI.h - 1.0));
1496 }
1497
1498 if(nextroi.y < 0)
1499 {
1500 log<software_error>({__FILE__, __LINE__, "can't set ROI to y center < 0"});
1501 roi_err = true;
1502 }
1503
1504 if(nextroi.y > 1023)
1505 {
1506 log<software_error>({__FILE__, __LINE__, "can't set ROI to y center > 1023"});
1507 roi_err = true;
1508 }
1509
1510 nextroi.width = m_nextROI.w;
1511
1512 if(nextroi.width < 0)
1513 {
1514 log<software_error>({__FILE__, __LINE__, "can't set ROI to width to be < 0"});
1515 roi_err = true;
1516 }
1517
1518 if(nextroi.x + nextroi.width > 1024)
1519 {
1520 log<software_error>({__FILE__, __LINE__, "can't set ROI to width such that edge is > 1023"});
1521 roi_err = true;
1522 }
1523
1524 nextroi.height = m_nextROI.h;
1525
1526 if(nextroi.y + nextroi.height > 1024)
1527 {
1528 log<software_error>({__FILE__, __LINE__, "can't set ROI to height such that edge is > 1023"});
1529 roi_err = true;
1530 }
1531
1532 if(nextroi.height < 0)
1533 {
1534 log<software_error>({__FILE__, __LINE__, "can't set ROI to height to be < 0"});
1535 roi_err = true;
1536 }
1537
1538 nextroi.x_binning = m_nextROI.bin_x;
1539
1540 if(nextroi.x_binning < 0)
1541 {
1542 log<software_error>({__FILE__, __LINE__, "can't set ROI x binning < 0"});
1543 roi_err = true;
1544 }
1545
1546 nextroi.y_binning = m_nextROI.bin_y;
1547
1548 if(nextroi.y_binning < 0)
1549 {
1550 log<software_error>({__FILE__, __LINE__, "can't set ROI y binning < 0"});
1551 roi_err = true;
1552 }
1553
1555
1556 if(!roi_err)
1557 {
1559 if( error != PicamError_None )
1560 {
1561 if(powerState() != 1 || powerStateTarget() != 1) return -1;
1562 std::cerr << PicamEnum2String(PicamEnumeratedType_Error, error) << "\n";
1565 return -1;
1566 }
1567 }
1568
1570 {
1571 if(powerState() != 1 || powerStateTarget() != 1) return -1;
1572 log<software_error>({__FILE__, __LINE__, "Error getting readout stride"});
1574 return -1;
1575 }
1576
1578 {
1579 if(powerState() != 1 || powerStateTarget() != 1) return -1;
1580 log<software_error>({__FILE__, __LINE__, "Error getting frame stride"});
1582
1583 return -1;
1584 }
1585
1587 {
1588 if(powerState() != 1 || powerStateTarget() != 1) return -1;
1589 log<software_error>({__FILE__, __LINE__, "Error getting frames per readout"});
1591 return -1;
1592 }
1593
1595 {
1596 if(powerState() != 1 || powerStateTarget() != 1) return -1;
1597 log<software_error>({__FILE__, __LINE__, "Error getting frame size"});
1599 return -1;
1600 }
1601
1603 {
1604 if(powerState() != 1 || powerStateTarget() != 1) return -1;
1605 log<software_error>({__FILE__, __LINE__,"Error getting pixel bit depth"});
1607 return -1;
1608 }
1610
1611 const PicamRois* rois;
1613 if( error != PicamError_None )
1614 {
1615 if(powerState() != 1 || powerStateTarget() != 1) return -1;
1618 return -1;
1619 }
1620 m_xbinning = rois->roi_array[0].x_binning;
1621 m_currentROI.bin_x = m_xbinning;
1622 m_ybinning = rois->roi_array[0].y_binning;
1623 m_currentROI.bin_y = m_ybinning;
1624
1625 std::cerr << rois->roi_array[0].x << "\n";
1626 std::cerr << (rois->roi_array[0].x-1) << "\n";
1627 std::cerr << rois->roi_array[0].width << "\n";
1628 std::cerr << 0.5*( (float) (rois->roi_array[0].width - 1.0)) << "\n";
1629
1630
1632 {
1633 m_currentROI.x = (1023.0-rois->roi_array[0].x) - 0.5*( (float) (rois->roi_array[0].width - 1.0)) ;
1634 //nextroi.x = ((1023-m_nextROI.x) - 0.5*( (float) m_nextROI.w - 1.0));
1635 }
1636 else
1637 {
1638 m_currentROI.x = (rois->roi_array[0].x) + 0.5*( (float) (rois->roi_array[0].width - 1.0)) ;
1639 }
1640
1641
1643 {
1644 m_currentROI.y = (1023.0-rois->roi_array[0].y) - 0.5*( (float) (rois->roi_array[0].height - 1.0)) ;
1645 //nextroi.y = ((1023 - m_nextROI.y) - 0.5*( (float) m_nextROI.h - 1.0));
1646 }
1647 else
1648 {
1649 m_currentROI.y = (rois->roi_array[0].y) + 0.5*( (float) (rois->roi_array[0].height - 1.0)) ;
1650 }
1651
1652
1653
1654
1655
1656 m_currentROI.w = rois->roi_array[0].width;
1657 m_currentROI.h = rois->roi_array[0].height;
1658
1659 m_width = rois->roi_array[0].width / rois->roi_array[0].x_binning;
1660 m_height = rois->roi_array[0].height / rois->roi_array[0].y_binning;
1662
1663
1670
1671
1672 //We also update target to the settable values
1673 m_nextROI.x = m_currentROI.x;
1674 m_nextROI.y = m_currentROI.y;
1675 m_nextROI.w = m_currentROI.w;
1676 m_nextROI.h = m_currentROI.h;
1677 m_nextROI.bin_x = m_currentROI.bin_x;
1678 m_nextROI.bin_y = m_currentROI.bin_y;
1679
1686
1687
1688 //=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
1689 //=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
1690 // Exposure Time and Frame Rate
1691 //=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
1692 //=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
1693
1695 {
1696 if(powerState() != 1 || powerStateTarget() != 1) return -1;
1697 return log<software_error, -1>({__FILE__, __LINE__, "could not get ReadOutTimeCalculation"});
1698 }
1699 std::cerr << "Readout time is: " << m_ReadOutTimeCalculation << "\n";
1700 updateIfChanged( m_indiP_readouttime, "value", m_ReadOutTimeCalculation/1000.0, INDI_OK); // convert from msec to sec
1701
1705
1706 if(constraint_count != 1)
1707 {
1708 if(powerState() != 1 || powerStateTarget() != 1) return -1;
1709 log<text_log>("Constraint count is not 1: " + std::to_string(constraint_count) + " constraints",logPrio::LOG_ERROR);
1710 }
1711 else
1712 {
1713 m_minExpTime = constraint_array[0].minimum;
1714 m_maxExpTime = constraint_array[0].maximum;
1715 m_stepExpTime = constraint_array[0].increment;
1716
1717 m_indiP_exptime["current"].setMin(m_minExpTime);
1718 m_indiP_exptime["current"].setMax(m_maxExpTime);
1719 m_indiP_exptime["current"].setStep(m_stepExpTime);
1720
1721 m_indiP_exptime["target"].setMin(m_minExpTime);
1722 m_indiP_exptime["target"].setMax(m_maxExpTime);
1723 m_indiP_exptime["target"].setStep(m_stepExpTime);
1724 }
1725
1726 if(m_expTimeSet > 0)
1727 {
1728 long intexptime = m_expTimeSet * 1000 * 10000 + 0.5;
1729 piflt exptime = ((double)intexptime)/10000;
1730 capExpTime(exptime);
1731 std::cerr << "Setting exposure time to " << m_expTimeSet << "\n";
1733
1734 if(rv < 0)
1735 {
1736 if(powerState() != 1 || powerStateTarget() != 1) return -1;
1737 return log<software_error, -1>({__FILE__, __LINE__, "Error setting exposure time"});
1738 }
1739 }
1740
1741 piflt exptime;
1743 {
1744 if(powerState() != 1 || powerStateTarget() != 1) return -1;
1745 return log<software_error,-1>({__FILE__, __LINE__, "Error getting exposure time"});
1746 }
1747 else
1748 {
1749 capExpTime(exptime);
1750 m_expTime = exptime/1000.0;
1751 m_expTimeSet = m_expTime; //At this point it must be true.
1754 }
1755
1757 {
1758 if(powerState() != 1 || powerStateTarget() != 1) return -1;
1759 return log<software_error,-1>({__FILE__, __LINE__, "Error getting frame rate"});
1760 }
1761 else
1762 {
1765 }
1766 std::cerr << "FrameRate is: " << m_FrameRateCalculation << "\n";
1767
1770 {
1771 std::cerr << "could not get AdcQuality\n";
1772 }
1774 std::cerr << "AdcQuality is: " << adcqStr << "\n";
1775
1778 {
1779 std::cerr << "could not get VerticalShiftRate\n";
1780 }
1781 std::cerr << "VerticalShiftRate is: " << verticalShiftRate << "\n";
1782
1785 {
1786 std::cerr << "could not get AdcSpeed\n";
1787 }
1788 std::cerr << "AdcSpeed is: " << AdcSpeed << "\n";
1789
1790
1791 std::cerr << "************************************************************\n";
1792
1793
1796 {
1797 std::cerr << "could not get AdcAnalogGain\n";
1798 }
1800 std::cerr << "AdcAnalogGain is: " << adcgStr << "\n";
1801
1802 if(m_readoutSpeedName == "ccd_00_1MHz" || m_readoutSpeedName == "ccd_01MHz")
1803 {
1804 m_emGain = 1;
1805 }
1806 else
1807 {
1810 {
1811 std::cerr << "could not get AdcEMGain\n";
1812 }
1814 }
1815
1816/*
1817 std::cerr << "Onlineable:\n";
1818 pibln onlineable;
1819 Picam_CanSetParameterOnline(m_modelHandle, PicamParameter_ReadoutControlMode,&onlineable);
1820 std::cerr << "ReadoutControlMode: " << onlineable << "\n"; //0
1821
1822 Picam_CanSetParameterOnline(m_modelHandle, PicamParameter_AdcQuality,&onlineable);
1823 std::cerr << "AdcQuality: " << onlineable << "\n"; //0
1824
1825 Picam_CanSetParameterOnline(m_modelHandle, PicamParameter_AdcAnalogGain,&onlineable);
1826 std::cerr << "AdcAnalogGain: " << onlineable << "\n"; //1
1827
1828 Picam_CanSetParameterOnline(m_modelHandle, PicamParameter_DisableCoolingFan,&onlineable);
1829 std::cerr << "DisableCoolingFan: " << onlineable << "\n";//0
1830
1831 Picam_CanSetParameterOnline(m_modelHandle, PicamParameter_SensorTemperatureSetPoint,&onlineable);
1832 std::cerr << "SensorTemperatureSetPoint: " << onlineable << "\n"; //0
1833
1834 Picam_CanSetParameterOnline(m_modelHandle, PicamParameter_AdcEMGain,&onlineable);
1835 std::cerr << "AdcEMGain: " << onlineable << "\n"; //1
1836
1837 Picam_CanSetParameterOnline(m_modelHandle, PicamParameter_FrameRateCalculation,&onlineable);
1838 std::cerr << "FrameRateCalculation: " << onlineable << "\n"; //0
1839
1840 std::cerr << "************************************************************\n";
1841*/
1842
1843 //If not previously allocated, allocate a nice big buffer to play with
1844 pi64s newbuffsz = framesPerReadout*readoutStride*10; //Save room for 10 frames
1845 if( newbuffsz > m_acqBuff.memory_size)
1846 {
1847 if(m_acqBuff.memory)
1848 {
1849 std::cerr << "Clearing\n";
1850 free(m_acqBuff.memory);
1851 m_acqBuff.memory = NULL;
1853 }
1854
1855 m_acqBuff.memory_size = newbuffsz;
1856 std::cerr << "m_acqBuff.memory_size: " << m_acqBuff.memory_size << "\n";
1857 m_acqBuff.memory = malloc(m_acqBuff.memory_size);
1858
1860 if(error != PicamError_None)
1861 {
1864
1865 std::cerr << "-->" << PicamEnum2String(PicamEnumeratedType_Error, error) << "\n";
1866 }
1867 }
1868
1869 //Start continuous acquisition
1871 {
1872 log<software_error>({__FILE__, __LINE__, "Error setting readouts=0"});
1874 return -1;
1875 }
1876
1877 recordCamera();
1878
1880 if(error != PicamError_None)
1881 {
1884
1885 return -1;
1886 }
1887
1888 m_dataType = _DATATYPE_UINT16; //Where does this go?
1889
1890 return 0;
1891
1892}
1893
1894inline
1896{
1897 return m_fps;
1898}
1899
1900inline
1902{
1903 return 0;
1904}
1905
1906inline
1908{
1909 piint camTimeOut = 1000; //1 second keeps us responsive without busy-waiting too much
1910
1912
1914
1917
1919 {
1920 return 1; //This sends it back to framegrabber to check for reconfig, etc.
1921 }
1922
1924
1925 if(error != PicamError_None)
1926 {
1929
1930 return -1;
1931 }
1932
1933 m_available.initial_readout = available.initial_readout;
1934 m_available.readout_count = available.readout_count;
1935
1936 if(m_available.initial_readout == 0)
1937 {
1938 return 1;
1939 }
1940
1941 //std::cerr << "readout: " << m_available.initial_readout << " " << m_available.readout_count << "\n";
1942
1943 // camera time stamp
1944 pibyte *frame = NULL;
1946
1947 frame = static_cast<pibyte*>(m_available.initial_readout);
1948 metadataOffset = (pi64s)frame + m_frameSize;
1949
1950 pi64s *tmpPtr = reinterpret_cast<pi64s*>(metadataOffset);
1951
1952 double cam_ts = (double)*tmpPtr/(double)m_tsRes;
1954
1955 // check for a frame skip
1956 if(delta_ts > 1.5 / m_FrameRateCalculation){
1957 std::cerr << "Skipped frame(s)! (Expected a " << 1000./m_FrameRateCalculation << " ms gap but got " << 1000*delta_ts << " ms)\n";
1958 }
1959 // print
1960
1961 m_camera_timestamp = cam_ts; // update to latest
1962
1963 //fprintf(m_outfile, "%d %-15.8f\n", m_imageStream->md->cnt0+1, (double)*tmpPtr/(double)m_tsRes);
1964
1965 return 0;
1966
1967}
1968
1969inline
1971{
1972 if( frameGrabber<picamCtrl>::loadImageIntoStreamCopy(dest, m_available.initial_readout, m_width, m_height, m_typeSize) == nullptr) return -1;
1973
1974 return 0;
1975}
1976
1977inline
1979{
1980 ///\todo clean this up. Just need to wait on acquisition update the first time probably.
1981
1983 if(error != PicamError_None)
1984 {
1987
1988 return -1;
1989 }
1990
1991 pibln running = true;
1992
1994
1995 while(running)
1996 {
1997 if(MagAOXAppT::m_powerState == 0) return 0;
1998 sleep(1);
1999
2001
2002 if(error != PicamError_None)
2003 {
2006 return -1;
2007 }
2008
2009 piint camTimeOut = 1000;
2010
2012
2014
2016 if(error != PicamError_None)
2017 {
2020 return -1;
2021 }
2022
2023// if(! status.running )
2024// {
2025// std::cerr << "Not running \n";
2026//
2027// std::cerr << "status.running: " << status.running << "\n";
2028// std::cerr << "status.errors: " << status.errors << "\n";
2029// std::cerr << "CameraFaulted: " << (int)(status.errors & PicamAcquisitionErrorsMask_CameraFaulted) << "\n";
2030// std::cerr << "CannectionLost: " << (int)(status.errors & PicamAcquisitionErrorsMask_ConnectionLost) << "\n";
2031// std::cerr << "DataLost: " << (int)(status.errors & PicamAcquisitionErrorsMask_DataLost) << "\n";
2032// std::cerr << "DataNotArriving: " << (int)(status.errors & PicamAcquisitionErrorsMask_DataNotArriving) << "\n";
2033// std::cerr << "None: " << (int)(status.errors & PicamAcquisitionErrorsMask_None) << "\n";
2034// std::cerr << "ShutterOverheated: " << (int)(status.errors & PicamAcquisitionErrorsMask_ShutterOverheated) << "\n";
2035// std::cerr << "status.readout_rate: " << status.readout_rate << "\n";
2036// }
2037
2039 if(error != PicamError_None)
2040 {
2043 return -1;
2044 }
2045 }
2046
2047 return 0;
2048}
2049
2050
2051
2056
2058{
2059 return recordCamera(true);
2060}
2061
2062
2063
2064}//namespace app
2065} //namespace MagAOX
2066#endif
The base-class for XWCTk applications.
void updateIfChanged(pcf::IndiProperty &p, const std::string &el, const T &newVal, pcf::IndiProperty::PropertyStateType ipState=pcf::IndiProperty::Ok)
Update an INDI property element value if it has changed.
stateCodes::stateCodeT state()
Get the current state code.
int powerState()
Returns the current power state.
int m_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.
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.
float m_full_y
The full ROI center y coordinate.
std::string m_readoutSpeedName
The current readout speed name.
float m_ccdTempSetpt
The desired temperature, in C.
bool m_tempControlStatus
Whether or not temperature control is active.
int setupConfig(mx::app::appConfigurator &config)
Setup the configuration system.
pcf::IndiProperty m_indiP_roi_w
Property used to set the ROI width.
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.
int loadConfig(mx::app::appConfigurator &config)
load the configuration system results
std::string m_vShiftSpeedName
The current vshift speed name.
float m_ccdTemp
The current temperature, in C.
std::vector< std::string > m_vShiftSpeedNames
std::string m_defaultVShiftSpeed
The default readout speed of the camera.
bool m_tempControlOnTarget
Whether or not the temperature control system is on its target temperature.
float m_stepExpTime
The maximum exposure time stepsize, used for INDI attributes.
std::vector< std::string > m_vShiftSpeedNameLabels
pcf::IndiProperty m_indiP_roi_set
Property used to trigger setting the ROI.
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:27
#define INDI_OK
Definition indiUtils.hpp:28
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:28
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:75
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