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::cerr << __LINE__ << '\n';
534 std::unique_lock<std::mutex> lock(m_indiMutex);
535 if(connect() < 0)
536 {
537 if(powerState() != 1 || powerStateTarget() != 1) return 0;
539 }
540
541 if(state() != stateCodes::CONNECTED) return 0;
542 }
543
545 {
546 //Get a lock
547 std::unique_lock<std::mutex> lock(m_indiMutex);
548
549 if( getAcquisitionState() < 0 )
550 {
551 if(powerState() != 1 || powerStateTarget() != 1) return 0;
553 }
554
555 if( setTempSetPt() < 0 ) //m_ccdTempSetpt already set on power on
556 {
557 if(powerState() != 1 || powerStateTarget() != 1) return 0;
559 }
560
561
563 {
565 }
566
568
569
570 }
571
573 {
574 //Get a lock if we can
575 std::unique_lock<std::mutex> lock(m_indiMutex, std::try_to_lock);
576
577 //but don't wait for it, just go back around.
578 if(!lock.owns_lock()) return 0;
579
580 if(getAcquisitionState() < 0)
581 {
582 if(powerState() != 1 || powerStateTarget() != 1) return 0;
583
585 return 0;
586 }
587
588
589
590 if(getTemps() < 0)
591 {
592 if(powerState() != 1 || powerStateTarget() != 1) return 0;
593
595 return 0;
596 }
597
599 {
601 }
602
604 {
606 }
607
609 {
611 return 0;
612 }
613
614 }
615
616 //Fall through check?
617 return 0;
618
619}
620
621inline
623{
624 std::lock_guard<std::mutex> lock(m_indiMutex);
625
627 {
629 m_cameraHandle = 0;
630 }
631
633
635 {
637 }
638
640 {
642 }
643
644 return 0;
645}
646
647inline
649{
651 {
653 }
654
656 {
658 }
659
660 return 0;
661}
662
663inline
665{
667
669 {
671 m_cameraHandle = 0;
672 }
673
675
676 ///\todo error check these base class fxns.
679
680 return 0;
681}
682
683inline
686 )
687{
689
690 if(MagAOXAppT::m_powerState == 0) return -1; //Flag error but don't log
691
692 if(error != PicamError_None)
693 {
694 if(powerState() != 1 || powerStateTarget() != 1) return -1;
696 return -1;
697 }
698
699 return 0;
700}
701
702inline
705 )
706{
708
709 if(MagAOXAppT::m_powerState == 0) return -1; //Flag error but don't log
710
711 if(error != PicamError_None)
712 {
713 if(powerState() != 1 || powerStateTarget() != 1) return -1;
715 return -1;
716 }
717
718 return 0;
719}
720
721inline
723 pi64s value,
724 bool commit
725 )
726{
728 if(error != PicamError_None)
729 {
730 if(powerState() != 1 || powerStateTarget() != 1) return -1;
732 return -1;
733 }
734
735 if(!commit) return 0;
736
739
741 if(error != PicamError_None)
742 {
743 if(powerState() != 1 || powerStateTarget() != 1) return -1;
745 return -1;
746 }
747
748 for( int i=0; i< failed_parameters_count; ++i)
749 {
751 {
753 return log<text_log,-1>( "Parameter not committed");
754 }
755 }
756
758
759 return 0;
760}
761
762inline
765 piflt value,
766 bool commit
767 )
768{
770 if(error != PicamError_None)
771 {
772 if(powerState() != 1 || powerStateTarget() != 1) return -1;
774 return -1;
775 }
776
777 if(!commit) return 0;
778
781
783 if(error != PicamError_None)
784 {
785 if(powerState() != 1 || powerStateTarget() != 1) return -1;
787 return -1;
788 }
789
790 for( int i=0; i< failed_parameters_count; ++i)
791 {
793 {
795 return log<text_log,-1>( "Parameter not committed");
796 }
797 }
798
800
801 return 0;
802}
803
804inline
807 piint value,
808 bool commit
809 )
810{
812 if(error != PicamError_None)
813 {
814 if(powerState() != 1 || powerStateTarget() != 1) return -1;
816 return -1;
817 }
818
819 if(!commit) return 0;
820
823
825 if(error != PicamError_None)
826 {
827 if(powerState() != 1 || powerStateTarget() != 1) return -1;
829 return -1;
830 }
831
832 for( int i=0; i< failed_parameters_count; ++i)
833 {
835 {
837 return log<text_log,-1>( "Parameter not committed");
838 }
839 }
840
842
843 return 0;
844}
845
846inline
854
855inline
863
864inline
867 piflt value
868 )
869{
871 if(error != PicamError_None)
872 {
873 if(powerState() != 1 || powerStateTarget() != 1) return -1;
875 return -1;
876 }
877
878 return 0;
879}
880
881inline
888
889inline
892 piint value
893 )
894{
896 if(error != PicamError_None)
897 {
898 if(powerState() != 1 || powerStateTarget() != 1) return -1;
900 return -1;
901 }
902
903 return 0;
904}
905
906inline
913
914inline
916{
917 std::cerr << __LINE__ << '\n';
918 PicamError error;
921
922 if(m_acqBuff.memory)
923 {
924 free(m_acqBuff.memory);
925 m_acqBuff.memory = NULL;
926 m_acqBuff.memory_size = 0;
927 }
928
929 std::cerr << __LINE__ << '\n';
930
932
933 std::cerr << __LINE__ << '\n';
934
935 //Have to initialize the library every time. Otherwise we won't catch a newly booted camera.
937
938 std::cerr << __LINE__ << '\n';
939
941 {
943 m_cameraHandle = 0;
944 }
945
946 std::cerr << __LINE__ << '\n';
947
949
950 std::cerr << __LINE__ << '\n';
951
952 if(powerState() != 1 || powerStateTarget() != 1) return 0;
953
954 std::cerr << __LINE__ << '\n';
955
956 if(id_count == 0)
957 {
959
961
963 if(!stateLogged())
964 {
965 log<text_log>("no P.I. Cameras available.", logPrio::LOG_NOTICE);
966 }
967 return 0;
968 }
969 else
970 {
971 std::cerr << "found " << id_count << " PI cameras.\n";
972 }
973
974 for(int i=0; i< id_count; ++i)
975 {
976 if( std::string(id_array[i].serial_number) == m_serialNumber )
977 {
978 log<text_log>("Camera was found. Now connecting.");
979
981 if(error == PicamError_None)
982 {
983 m_cameraName = id_array[i].sensor_name;
985
987 if( error != PicamError_None )
988 {
989 log<software_error>({__FILE__, __LINE__, "failed to get camera model"});
990 }
991
993 log<text_log>("Connected to " + m_cameraName + " [S/N " + m_serialNumber + "]");
994
996
999
1000 return 0;
1001 }
1002 else
1003 {
1004 if(powerState() != 1 || powerStateTarget() != 1) return 0;
1005
1007 if(!stateLogged())
1008 {
1009 log<software_error>({__FILE__,__LINE__, 0, error, "Error connecting to camera."});
1010 }
1011
1013
1015 return -1;
1016 }
1017 }
1018 }
1019
1021 if(!stateLogged())
1022 {
1023 log<text_log>("Camera not found in available ids.");
1024 }
1025
1027
1028
1030
1031
1032 return 0;
1033}
1034
1035
1036inline
1038{
1039 pibln running = false;
1040
1042
1043 if(MagAOXAppT::m_powerState == 0) return 0;
1044
1045 if(error != PicamError_None)
1046 {
1047 if(powerState() != 1 || powerStateTarget() != 1) return -1;
1050 return -1;
1051 }
1052
1055
1056 if(!running)
1057 {
1058 log<text_log>("acqusition stopped. restarting", logPrio::LOG_ERROR);
1059 m_reconfig = true;
1060 }
1061
1062 return 0;
1063
1064}
1065
1066inline
1068{
1070
1072 {
1073 if(powerState() != 1 || powerStateTarget() != 1) return -1;
1074
1077 return -1;
1078 }
1079
1081
1082 //PicamSensorTemperatureStatus
1083 piint status;
1084
1086 {
1087 if(powerState() != 1 || powerStateTarget() != 1) return -1;
1088
1091 return -1;
1092 }
1093
1094 if(status == 1)
1095 {
1096 m_tempControlStatus = true;
1097 m_tempControlOnTarget = false;
1098 m_tempControlStatusStr = "UNLOCKED";
1099 }
1100 else if(status == 2)
1101 {
1102 m_tempControlStatus = true;
1103 m_tempControlOnTarget = true;
1104 m_tempControlStatusStr = "LOCKED";
1105 }
1106 else if(status == 3)
1107 {
1108 m_tempControlStatus = false;
1109 m_tempControlOnTarget = false;
1110 m_tempControlStatusStr = "FAULTED";
1111 log<text_log>("temperature control faulted", logPrio::LOG_ALERT);
1112 }
1113 else
1114 {
1115 m_tempControlStatus = false;
1116 m_tempControlOnTarget = false;
1117 m_tempControlStatusStr = "UNKNOWN";
1118 }
1119
1120 recordCamera();
1121
1122 return 0;
1123
1124}
1125
1126inline
1128{
1129 return 0;
1130}
1131
1132inline
1134{
1135 m_ccdTempSetpt = -55; //This is the power on setpoint
1136
1137 m_currentROI.x = 511.5;
1138 m_currentROI.y = 511.5;
1139 m_currentROI.w = 1024;
1140 m_currentROI.h = 1024;
1141 m_currentROI.bin_x = 1;
1142 m_currentROI.bin_y = 1;
1143
1144 m_readoutSpeedName = "emccd_05MHz";
1145 m_vShiftSpeedName = "1_2us";
1146 return 0;
1147}
1148
1149inline
1151{
1152 //Always on
1153 m_tempControlStatus = true;
1155 updateSwitchIfChanged(m_indiP_tempcont, "toggle", pcf::IndiElement::On, INDI_IDLE);
1156 recordCamera(true);
1157 return 0;
1158}
1159
1160inline
1162{
1163 ///\todo bounds check here.
1164 m_reconfig = true;
1165
1166 recordCamera(true);
1167 return 0;
1168}
1169
1170inline
1172{
1173 m_reconfig = true;
1174 recordCamera(true);
1175 return 0;
1176}
1177
1178inline
1180{
1181 m_reconfig = true;
1182 recordCamera(true);
1183 return 0;
1184}
1185
1186inline
1188{
1189 piint adcQual;
1190 piflt adcSpeed;
1191
1192 if(readoutParams(adcQual, adcSpeed, m_readoutSpeedName) < 0)
1193 {
1194 log<software_error>({__FILE__, __LINE__, "Invalid readout speed: " + m_readoutSpeedNameSet});
1196 return -1;
1197 }
1198
1200 {
1201 m_emGain = 1;
1202 m_adcSpeed = adcSpeed;
1203 recordCamera(true);
1204 log<text_log>("Attempt to set EM gain while in conventional amplifier.", logPrio::LOG_NOTICE);
1205 return 0;
1206 }
1207
1209 if(emg < 0)
1210 {
1211 emg = 0;
1212 log<text_log>("EM gain limited to 0", logPrio::LOG_WARNING);
1213 }
1214
1215 if(emg > m_maxEMGain)
1216 {
1217 emg = m_maxEMGain;
1218 log<text_log>("EM gain limited to maxEMGain = " + std::to_string(emg), logPrio::LOG_WARNING);
1219 }
1220
1221 recordCamera(true);
1223 {
1224 if(powerState() != 1 || powerStateTarget() != 1) return -1;
1225 log<software_error>({__FILE__, __LINE__, "Error setting EM gain"});
1226 return -1;
1227 }
1228
1231 {
1232 if(powerState() != 1 || powerStateTarget() != 1) return -1;
1233 return log<software_error,-1>({__FILE__, __LINE__, "could not get AdcEMGain"});
1234 }
1236 m_adcSpeed = adcSpeed;
1237 recordCamera(true);
1238 return 0;
1239}
1240
1241inline
1243{
1244 long intexptime = m_expTimeSet * 1000 * 10000 + 0.5;
1245 piflt exptime = ((double)intexptime)/10000;
1246 capExpTime(exptime);
1247
1248 int rv;
1249
1250 recordCamera(true);
1251
1253 {
1255 }
1256 else
1257 {
1259 }
1260
1261 if(rv < 0)
1262 {
1263 if(powerState() != 1 || powerStateTarget() != 1) return -1;
1264 log<software_error>({__FILE__, __LINE__, "Error setting exposure time"});
1265 return -1;
1266 }
1267
1268 m_expTime = exptime/1000.0;
1269
1270 recordCamera(true);
1271
1273
1275 {
1276 if(powerState() != 1 || powerStateTarget() != 1) return -1;
1277 log<software_error>({__FILE__, __LINE__, "could not get FrameRateCalculation"});
1278 }
1280
1281 recordCamera(true);
1282
1283 return 0;
1284}
1285
1286inline
1288{
1289 // cap at minimum possible value
1290 if(exptime < m_ReadOutTimeCalculation)
1291 {
1292 if(powerState() != 1 || powerStateTarget() != 1) return -1;
1293 log<text_log>("Got exposure time " + std::to_string(exptime) + " ms but min value is " + std::to_string(m_ReadOutTimeCalculation) + " ms");
1294 long intexptime = m_ReadOutTimeCalculation * 10000 + 0.5;
1295 exptime = ((double)intexptime)/10000;
1296 }
1297
1298 return 0;
1299}
1300
1301inline
1303{
1304 return 0;
1305}
1306
1307//Set ROI property to busy if accepted, set toggle to Off and Idlw either way.
1308//Set ROI actual
1309//Update current values (including struct and indiP) and set to OK when done
1310inline
1312{
1313 m_reconfig = true;
1314
1315 updateSwitchIfChanged(m_indiP_roi_set, "request", pcf::IndiElement::Off, INDI_IDLE);
1316
1317 return 0;
1318
1319}
1320
1321inline
1326
1327inline
1329{
1330
1334 //piint frameSize;
1336
1337 m_camera_timestamp = 0; // reset tracked timestamp
1338
1339 std::unique_lock<std::mutex> lock(m_indiMutex);
1340
1341
1342 // Time stamp handling
1344 {
1345 if(powerState() != 1 || powerStateTarget() != 1) return -1;
1346 log<software_error>({__FILE__,__LINE__, "Could not set time stamp mask"});
1347 }
1349 {
1350 if(powerState() != 1 || powerStateTarget() != 1) return -1;
1351 log<software_error>({__FILE__,__LINE__, "Could not get timestamp resolution"}) ;
1352 }
1353
1354 //=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
1355 //=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
1356 // Check Frame Transfer
1357 //=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
1358 //=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
1359
1360 piint cmode;
1362 {
1363 if(powerState() != 1 || powerStateTarget() != 1) return -1;
1364 log<software_error>({__FILE__,__LINE__, "could not get Readout Control Mode"});
1365 return -1;
1366 }
1367
1369 {
1370 if(powerState() != 1 || powerStateTarget() != 1) return -1;
1371 log<software_error>({__FILE__,__LINE__, "Readout Control Mode not configured for frame transfer"}) ;
1372 return -1;
1373 }
1374
1375 //=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
1376 //=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
1377 // Temperature
1378 //=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
1379 //=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
1380
1382 {
1383 if(powerState() != 1 || powerStateTarget() != 1) return -1;
1384 log<software_error>({__FILE__, __LINE__, "Error setting temperature setpoint"});
1386 return -1;
1387 }
1388
1389 //log<text_log>( "Set temperature set point: " + std::to_string(m_ccdTempSetpt) + " C");
1390
1391 //=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
1392 //=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
1393 // ADC Speed and Quality
1394 //=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
1395 //=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
1396
1397 piint adcQual;
1398 piflt adcSpeed;
1399
1400 if(readoutParams(adcQual, adcSpeed, m_readoutSpeedNameSet) < 0)
1401 {
1402 if(powerState() != 1 || powerStateTarget() != 1) return -1;
1403 log<software_error>({__FILE__, __LINE__, "Invalid readout speed: " + m_readoutSpeedNameSet});
1405 return -1;
1406 }
1407
1408 if( setPicamParameter(m_modelHandle, PicamParameter_AdcSpeed, adcSpeed, false) < 0) //don't commit b/c it will error if quality mismatched
1409 {
1410 if(powerState() != 1 || powerStateTarget() != 1) return -1;
1411 log<software_error>({__FILE__, __LINE__, "Error setting ADC Speed"});
1412 //state(stateCodes::ERROR);
1413 //return -1;
1414 }
1415
1417 {
1418 if(powerState() != 1 || powerStateTarget() != 1) return -1;
1419 log<software_error>({__FILE__, __LINE__, "Error setting ADC Quality"});
1421 return -1;
1422 }
1423 m_adcSpeed = adcSpeed;
1425 log<text_log>( "Readout speed set to: " + m_readoutSpeedNameSet);
1426
1428 {
1429 m_emGain = 1.0;
1430 m_emGainSet = 1.0;
1431 }
1432
1433 //=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
1434 //=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
1435 // Vertical Shift Rate
1436 //=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
1437 //=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
1438
1439 piflt vss;
1441 {
1442 if(powerState() != 1 || powerStateTarget() != 1) return -1;
1443 log<software_error>({__FILE__, __LINE__, "Invalid vertical shift speed: " + m_vShiftSpeedNameSet});
1445 return -1;
1446 }
1447
1449 {
1450 if(powerState() != 1 || powerStateTarget() != 1) return -1;
1451 log<software_error>({__FILE__, __LINE__, "Error setting Vertical Shift Rate"});
1453 return -1;
1454 }
1455
1458 log<text_log>( "Vertical Shift Rate set to: " + m_vShiftSpeedName);
1459
1460 //=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
1461 //=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
1462 // Dimensions
1463 //=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
1464 //=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
1465
1468
1469 nextrois.roi_array = &nextroi;
1470 nextrois.roi_count = 1;
1471
1472 int roi_err = false;
1474 {
1475 nextroi.x = ((1023-m_nextROI.x) - 0.5*( (float) m_nextROI.w - 1.0));
1476 }
1477 else
1478 {
1479 nextroi.x = (m_nextROI.x - 0.5*( (float) m_nextROI.w - 1.0));
1480 }
1481
1482 if(nextroi.x < 0)
1483 {
1484 log<software_error>({__FILE__, __LINE__, "can't set ROI to x center < 0"});
1485 roi_err = true;
1486 }
1487
1488 if(nextroi.x > 1023)
1489 {
1490 log<software_error>({__FILE__, __LINE__, "can't set ROI to x center > 1023"});
1491 roi_err = true;
1492 }
1493
1494
1496 {
1497 nextroi.y = ((1023 - m_nextROI.y) - 0.5*( (float) m_nextROI.h - 1.0));
1498 }
1499 else
1500 {
1501 nextroi.y = (m_nextROI.y - 0.5*( (float) m_nextROI.h - 1.0));
1502 }
1503
1504 if(nextroi.y < 0)
1505 {
1506 log<software_error>({__FILE__, __LINE__, "can't set ROI to y center < 0"});
1507 roi_err = true;
1508 }
1509
1510 if(nextroi.y > 1023)
1511 {
1512 log<software_error>({__FILE__, __LINE__, "can't set ROI to y center > 1023"});
1513 roi_err = true;
1514 }
1515
1516 nextroi.width = m_nextROI.w;
1517
1518 if(nextroi.width < 0)
1519 {
1520 log<software_error>({__FILE__, __LINE__, "can't set ROI to width to be < 0"});
1521 roi_err = true;
1522 }
1523
1524 if(nextroi.x + nextroi.width > 1024)
1525 {
1526 log<software_error>({__FILE__, __LINE__, "can't set ROI to width such that edge is > 1023"});
1527 roi_err = true;
1528 }
1529
1530 nextroi.height = m_nextROI.h;
1531
1532 if(nextroi.y + nextroi.height > 1024)
1533 {
1534 log<software_error>({__FILE__, __LINE__, "can't set ROI to height such that edge is > 1023"});
1535 roi_err = true;
1536 }
1537
1538 if(nextroi.height < 0)
1539 {
1540 log<software_error>({__FILE__, __LINE__, "can't set ROI to height to be < 0"});
1541 roi_err = true;
1542 }
1543
1544 nextroi.x_binning = m_nextROI.bin_x;
1545
1546 if(nextroi.x_binning < 0)
1547 {
1548 log<software_error>({__FILE__, __LINE__, "can't set ROI x binning < 0"});
1549 roi_err = true;
1550 }
1551
1552 nextroi.y_binning = m_nextROI.bin_y;
1553
1554 if(nextroi.y_binning < 0)
1555 {
1556 log<software_error>({__FILE__, __LINE__, "can't set ROI y binning < 0"});
1557 roi_err = true;
1558 }
1559
1560 PicamError error;
1561
1562 if(!roi_err)
1563 {
1565 if( error != PicamError_None )
1566 {
1567 if(powerState() != 1 || powerStateTarget() != 1) return -1;
1568 std::cerr << PicamEnum2String(PicamEnumeratedType_Error, error) << "\n";
1571 return -1;
1572 }
1573 }
1574
1576 {
1577 if(powerState() != 1 || powerStateTarget() != 1) return -1;
1578 log<software_error>({__FILE__, __LINE__, "Error getting readout stride"});
1580 return -1;
1581 }
1582
1584 {
1585 if(powerState() != 1 || powerStateTarget() != 1) return -1;
1586 log<software_error>({__FILE__, __LINE__, "Error getting frame stride"});
1588
1589 return -1;
1590 }
1591
1593 {
1594 if(powerState() != 1 || powerStateTarget() != 1) return -1;
1595 log<software_error>({__FILE__, __LINE__, "Error getting frames per readout"});
1597 return -1;
1598 }
1599
1601 {
1602 if(powerState() != 1 || powerStateTarget() != 1) return -1;
1603 log<software_error>({__FILE__, __LINE__, "Error getting frame size"});
1605 return -1;
1606 }
1607
1609 {
1610 if(powerState() != 1 || powerStateTarget() != 1) return -1;
1611 log<software_error>({__FILE__, __LINE__,"Error getting pixel bit depth"});
1613 return -1;
1614 }
1616
1617 const PicamRois* rois;
1619 if( error != PicamError_None )
1620 {
1621 if(powerState() != 1 || powerStateTarget() != 1) return -1;
1624 return -1;
1625 }
1626 m_xbinning = rois->roi_array[0].x_binning;
1627 m_currentROI.bin_x = m_xbinning;
1628 m_ybinning = rois->roi_array[0].y_binning;
1629 m_currentROI.bin_y = m_ybinning;
1630
1631 std::cerr << rois->roi_array[0].x << "\n";
1632 std::cerr << (rois->roi_array[0].x-1) << "\n";
1633 std::cerr << rois->roi_array[0].width << "\n";
1634 std::cerr << 0.5*( (float) (rois->roi_array[0].width - 1.0)) << "\n";
1635
1636
1638 {
1639 m_currentROI.x = (1023.0-rois->roi_array[0].x) - 0.5*( (float) (rois->roi_array[0].width - 1.0)) ;
1640 //nextroi.x = ((1023-m_nextROI.x) - 0.5*( (float) m_nextROI.w - 1.0));
1641 }
1642 else
1643 {
1644 m_currentROI.x = (rois->roi_array[0].x) + 0.5*( (float) (rois->roi_array[0].width - 1.0)) ;
1645 }
1646
1647
1649 {
1650 m_currentROI.y = (1023.0-rois->roi_array[0].y) - 0.5*( (float) (rois->roi_array[0].height - 1.0)) ;
1651 //nextroi.y = ((1023 - m_nextROI.y) - 0.5*( (float) m_nextROI.h - 1.0));
1652 }
1653 else
1654 {
1655 m_currentROI.y = (rois->roi_array[0].y) + 0.5*( (float) (rois->roi_array[0].height - 1.0)) ;
1656 }
1657
1658
1659
1660
1661
1662 m_currentROI.w = rois->roi_array[0].width;
1663 m_currentROI.h = rois->roi_array[0].height;
1664
1665 m_width = rois->roi_array[0].width / rois->roi_array[0].x_binning;
1666 m_height = rois->roi_array[0].height / rois->roi_array[0].y_binning;
1668
1669
1676
1677
1678 //We also update target to the settable values
1679 m_nextROI.x = m_currentROI.x;
1680 m_nextROI.y = m_currentROI.y;
1681 m_nextROI.w = m_currentROI.w;
1682 m_nextROI.h = m_currentROI.h;
1683 m_nextROI.bin_x = m_currentROI.bin_x;
1684 m_nextROI.bin_y = m_currentROI.bin_y;
1685
1692
1693
1694 //=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
1695 //=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
1696 // Exposure Time and Frame Rate
1697 //=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
1698 //=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
1699
1701 {
1702 if(powerState() != 1 || powerStateTarget() != 1) return -1;
1703 return log<software_error, -1>({__FILE__, __LINE__, "could not get ReadOutTimeCalculation"});
1704 }
1705 std::cerr << "Readout time is: " << m_ReadOutTimeCalculation << "\n";
1706 updateIfChanged( m_indiP_readouttime, "value", m_ReadOutTimeCalculation/1000.0, INDI_OK); // convert from msec to sec
1707
1711
1712 if(constraint_count != 1)
1713 {
1714 if(powerState() != 1 || powerStateTarget() != 1) return -1;
1715 log<text_log>("Constraint count is not 1: " + std::to_string(constraint_count) + " constraints",logPrio::LOG_ERROR);
1716 }
1717 else
1718 {
1719 m_minExpTime = constraint_array[0].minimum;
1720 m_maxExpTime = constraint_array[0].maximum;
1721 m_stepExpTime = constraint_array[0].increment;
1722
1723 m_indiP_exptime["current"].setMin(m_minExpTime);
1724 m_indiP_exptime["current"].setMax(m_maxExpTime);
1725 m_indiP_exptime["current"].setStep(m_stepExpTime);
1726
1727 m_indiP_exptime["target"].setMin(m_minExpTime);
1728 m_indiP_exptime["target"].setMax(m_maxExpTime);
1729 m_indiP_exptime["target"].setStep(m_stepExpTime);
1730 }
1731
1732 if(m_expTimeSet > 0)
1733 {
1734 long intexptime = m_expTimeSet * 1000 * 10000 + 0.5;
1735 piflt exptime = ((double)intexptime)/10000;
1736 capExpTime(exptime);
1737 std::cerr << "Setting exposure time to " << m_expTimeSet << "\n";
1739
1740 if(rv < 0)
1741 {
1742 if(powerState() != 1 || powerStateTarget() != 1) return -1;
1743 return log<software_error, -1>({__FILE__, __LINE__, "Error setting exposure time"});
1744 }
1745 }
1746
1747 piflt exptime;
1749 {
1750 if(powerState() != 1 || powerStateTarget() != 1) return -1;
1751 return log<software_error,-1>({__FILE__, __LINE__, "Error getting exposure time"});
1752 }
1753 else
1754 {
1755 capExpTime(exptime);
1756 m_expTime = exptime/1000.0;
1757 m_expTimeSet = m_expTime; //At this point it must be true.
1760 }
1761
1763 {
1764 if(powerState() != 1 || powerStateTarget() != 1) return -1;
1765 return log<software_error,-1>({__FILE__, __LINE__, "Error getting frame rate"});
1766 }
1767 else
1768 {
1771 }
1772 std::cerr << "FrameRate is: " << m_FrameRateCalculation << "\n";
1773
1776 {
1777 std::cerr << "could not get AdcQuality\n";
1778 }
1780 std::cerr << "AdcQuality is: " << adcqStr << "\n";
1781
1784 {
1785 std::cerr << "could not get VerticalShiftRate\n";
1786 }
1787 std::cerr << "VerticalShiftRate is: " << verticalShiftRate << "\n";
1788
1791 {
1792 std::cerr << "could not get AdcSpeed\n";
1793 }
1794 std::cerr << "AdcSpeed is: " << AdcSpeed << "\n";
1795
1796
1797 std::cerr << "************************************************************\n";
1798
1799
1802 {
1803 std::cerr << "could not get AdcAnalogGain\n";
1804 }
1806 std::cerr << "AdcAnalogGain is: " << adcgStr << "\n";
1807
1808 if(m_readoutSpeedName == "ccd_00_1MHz" || m_readoutSpeedName == "ccd_01MHz")
1809 {
1810 m_emGain = 1;
1811 }
1812 else
1813 {
1816 {
1817 std::cerr << "could not get AdcEMGain\n";
1818 }
1820 }
1821
1822/*
1823 std::cerr << "Onlineable:\n";
1824 pibln onlineable;
1825 Picam_CanSetParameterOnline(m_modelHandle, PicamParameter_ReadoutControlMode,&onlineable);
1826 std::cerr << "ReadoutControlMode: " << onlineable << "\n"; //0
1827
1828 Picam_CanSetParameterOnline(m_modelHandle, PicamParameter_AdcQuality,&onlineable);
1829 std::cerr << "AdcQuality: " << onlineable << "\n"; //0
1830
1831 Picam_CanSetParameterOnline(m_modelHandle, PicamParameter_AdcAnalogGain,&onlineable);
1832 std::cerr << "AdcAnalogGain: " << onlineable << "\n"; //1
1833
1834 Picam_CanSetParameterOnline(m_modelHandle, PicamParameter_DisableCoolingFan,&onlineable);
1835 std::cerr << "DisableCoolingFan: " << onlineable << "\n";//0
1836
1837 Picam_CanSetParameterOnline(m_modelHandle, PicamParameter_SensorTemperatureSetPoint,&onlineable);
1838 std::cerr << "SensorTemperatureSetPoint: " << onlineable << "\n"; //0
1839
1840 Picam_CanSetParameterOnline(m_modelHandle, PicamParameter_AdcEMGain,&onlineable);
1841 std::cerr << "AdcEMGain: " << onlineable << "\n"; //1
1842
1843 Picam_CanSetParameterOnline(m_modelHandle, PicamParameter_FrameRateCalculation,&onlineable);
1844 std::cerr << "FrameRateCalculation: " << onlineable << "\n"; //0
1845
1846 std::cerr << "************************************************************\n";
1847*/
1848
1849 //If not previously allocated, allocate a nice big buffer to play with
1850 pi64s newbuffsz = framesPerReadout*readoutStride*10; //Save room for 10 frames
1851 if( newbuffsz > m_acqBuff.memory_size)
1852 {
1853 if(m_acqBuff.memory)
1854 {
1855 std::cerr << "Clearing\n";
1856 free(m_acqBuff.memory);
1857 m_acqBuff.memory = NULL;
1859 }
1860
1861 m_acqBuff.memory_size = newbuffsz;
1862 std::cerr << "m_acqBuff.memory_size: " << m_acqBuff.memory_size << "\n";
1863 m_acqBuff.memory = malloc(m_acqBuff.memory_size);
1864
1866 if(error != PicamError_None)
1867 {
1870
1871 std::cerr << "-->" << PicamEnum2String(PicamEnumeratedType_Error, error) << "\n";
1872 }
1873 }
1874
1875 //Start continuous acquisition
1877 {
1878 log<software_error>({__FILE__, __LINE__, "Error setting readouts=0"});
1880 return -1;
1881 }
1882
1883 recordCamera();
1884
1886 if(error != PicamError_None)
1887 {
1890
1891 return -1;
1892 }
1893
1894 m_dataType = _DATATYPE_UINT16; //Where does this go?
1895
1896 return 0;
1897
1898}
1899
1900inline
1902{
1903 return m_fps;
1904}
1905
1906inline
1908{
1909 return 0;
1910}
1911
1912inline
1914{
1915 piint camTimeOut = 1000; //1 second keeps us responsive without busy-waiting too much
1916
1918
1920
1921 PicamError error;
1923
1924 if(error == PicamError_TimeOutOccurred)
1925 {
1926 return 1; //This sends it back to framegrabber to check for reconfig, etc.
1927 }
1928
1930
1931 if(error != PicamError_None)
1932 {
1935
1936 return -1;
1937 }
1938
1939 m_available.initial_readout = available.initial_readout;
1940 m_available.readout_count = available.readout_count;
1941
1942 if(m_available.initial_readout == 0)
1943 {
1944 return 1;
1945 }
1946
1947 //std::cerr << "readout: " << m_available.initial_readout << " " << m_available.readout_count << "\n";
1948
1949 // camera time stamp
1950 pibyte *frame = NULL;
1952
1953 frame = static_cast<pibyte*>(m_available.initial_readout);
1954 metadataOffset = (pi64s)frame + m_frameSize;
1955
1956 pi64s *tmpPtr = reinterpret_cast<pi64s*>(metadataOffset);
1957
1958 double cam_ts = (double)*tmpPtr/(double)m_tsRes;
1960
1961 // check for a frame skip
1962 if(delta_ts > 1.5 / m_FrameRateCalculation){
1963 std::cerr << "Skipped frame(s)! (Expected a " << 1000./m_FrameRateCalculation << " ms gap but got " << 1000*delta_ts << " ms)\n";
1964 }
1965 // print
1966
1967 m_camera_timestamp = cam_ts; // update to latest
1968
1969 //fprintf(m_outfile, "%d %-15.8f\n", m_imageStream->md->cnt0+1, (double)*tmpPtr/(double)m_tsRes);
1970
1971 return 0;
1972
1973}
1974
1975inline
1977{
1978 if( frameGrabber<picamCtrl>::loadImageIntoStreamCopy(dest, m_available.initial_readout, m_width, m_height, m_typeSize) == nullptr) return -1;
1979
1980 return 0;
1981}
1982
1983inline
1985{
1986 ///\todo clean this up. Just need to wait on acquisition update the first time probably.
1987
1989 if(error != PicamError_None)
1990 {
1993
1994 return -1;
1995 }
1996
1997 pibln running = true;
1998
2000
2001 while(running)
2002 {
2003 if(MagAOXAppT::m_powerState == 0) return 0;
2004 sleep(1);
2005
2007
2008 if(error != PicamError_None)
2009 {
2012 return -1;
2013 }
2014
2015 piint camTimeOut = 1000;
2016
2018
2020
2022 if(error != PicamError_None)
2023 {
2026 return -1;
2027 }
2028
2029// if(! status.running )
2030// {
2031// std::cerr << "Not running \n";
2032//
2033// std::cerr << "status.running: " << status.running << "\n";
2034// std::cerr << "status.errors: " << status.errors << "\n";
2035// std::cerr << "CameraFaulted: " << (int)(status.errors & PicamAcquisitionErrorsMask_CameraFaulted) << "\n";
2036// std::cerr << "CannectionLost: " << (int)(status.errors & PicamAcquisitionErrorsMask_ConnectionLost) << "\n";
2037// std::cerr << "DataLost: " << (int)(status.errors & PicamAcquisitionErrorsMask_DataLost) << "\n";
2038// std::cerr << "DataNotArriving: " << (int)(status.errors & PicamAcquisitionErrorsMask_DataNotArriving) << "\n";
2039// std::cerr << "None: " << (int)(status.errors & PicamAcquisitionErrorsMask_None) << "\n";
2040// std::cerr << "ShutterOverheated: " << (int)(status.errors & PicamAcquisitionErrorsMask_ShutterOverheated) << "\n";
2041// std::cerr << "status.readout_rate: " << status.readout_rate << "\n";
2042// }
2043
2045 if(error != PicamError_None)
2046 {
2049 return -1;
2050 }
2051 }
2052
2053 return 0;
2054}
2055
2056
2057
2062
2064{
2065 return recordCamera(true);
2066}
2067
2068
2069
2070}//namespace app
2071} //namespace MagAOX
2072#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.
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.
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: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:26
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