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// #include <ImageStruct.h>
13#include <ImageStreamIO/ImageStreamIO.h>
14
15#include <picam_advanced.h>
16
17#include "../../libMagAOX/libMagAOX.hpp" //Note this is included on command line to trigger pch
18#include "../../magaox_git_version.h"
19
20#define DEBUG
21
22#ifdef DEBUG
23 #define BREADCRUMB std::cerr << __FILE__ << " " << __LINE__ << "\n";
24#else
25 #define BREADCRUMB
26#endif
27
28inline std::string PicamEnum2String( PicamEnumeratedType type, piint value )
29{
30 const pichar *string;
31 Picam_GetEnumerationString( type, value, &string );
32 std::string str( string );
33 Picam_DestroyString( string );
34
35 return str;
36}
37
38namespace MagAOX
39{
40namespace app
41{
42
43int readoutParams( piint &adcQual, piflt &adcSpeed, const std::string &rosn )
44{
45 if( rosn == "ccd_00_1MHz" )
46 {
47 adcQual = PicamAdcQuality_LowNoise;
48 adcSpeed = 0.1;
49 }
50 else if( rosn == "ccd_01MHz" )
51 {
52 adcQual = PicamAdcQuality_LowNoise;
53 adcSpeed = 1;
54 }
55 else if( rosn == "emccd_05MHz" )
56 {
57 adcQual = PicamAdcQuality_ElectronMultiplied;
58 adcSpeed = 5;
59 }
60 else if( rosn == "emccd_10MHz" )
61 {
62 adcQual = PicamAdcQuality_ElectronMultiplied;
63 adcSpeed = 10;
64 }
65 else if( rosn == "emccd_20MHz" )
66 {
67 adcQual = PicamAdcQuality_ElectronMultiplied;
68 adcSpeed = 20;
69 }
70 else if( rosn == "emccd_30MHz" )
71 {
72 adcQual = PicamAdcQuality_ElectronMultiplied;
73 adcSpeed = 30;
74 }
75 else
76 {
77 return -1;
78 }
79
80 return 0;
81}
82
83int vshiftParams( piflt &vss, const std::string &vsn )
84{
85 if( vsn == "0_7us" )
86 {
87 vss = 0.7;
88 }
89 else if( vsn == "1_2us" )
90 {
91 vss = 1.2;
92 }
93 else if( vsn == "2_0us" )
94 {
95 vss = 2.0;
96 }
97 else if( vsn == "5_0us" )
98 {
99 vss = 5.0;
100 }
101 else
102 {
103 return -1;
104 }
105
106 return 0;
107}
108
109/** \defgroup picamCtrl Princeton Instruments EMCCD Camera
110 * \brief Control of a Princeton Instruments EMCCD Camera.
111 *
112 * <a href="../handbook/operating/software/apps/picamCtrl.html">Application Documentation</a>
113 *
114 * \ingroup apps
115 *
116 */
117
118/** \defgroup picamCtrl_files Princeton Instruments EMCCD Camera Files
119 * \ingroup picamCtrl
120 */
121
122/** MagAO-X application to control a Princeton Instruments EMCCD
123 *
124 * \ingroup picamCtrl
125 *
126 * \todo Config item for ImageStreamIO name filename
127 * \todo implement ImageStreamIO circular buffer, with config setting
128 */
129class picamCtrl : public MagAOXApp<>,
130 public dev::stdCamera<picamCtrl>,
131 public dev::frameGrabber<picamCtrl>,
132 public dev::dssShutter<picamCtrl>,
133 public dev::telemeter<picamCtrl>
134{
135
136 friend class dev::stdCamera<picamCtrl>;
137 friend class dev::frameGrabber<picamCtrl>;
138 friend class dev::dssShutter<picamCtrl>;
139 friend class dev::telemeter<picamCtrl>;
140
142
143 public:
144 /** \name app::dev Configurations
145 *@{
146 */
147 static constexpr bool c_stdCamera_tempControl =
148 true; ///< app::dev config to tell stdCamera to expose temperature controls
149
150 static constexpr bool c_stdCamera_temp = true; ///< app::dev config to tell stdCamera to expose temperature
151
152 static constexpr bool c_stdCamera_readoutSpeed =
153 true; ///< app::dev config to tell stdCamera to expose readout speed controls
154
155 static constexpr bool c_stdCamera_vShiftSpeed =
156 true; ///< app:dev config to tell stdCamera to expose vertical shift speed control
157 static constexpr bool c_stdCamera_fanSpeed =
158 true; ///< app::dev config to tell stdCamera to expose fan-speed control
159
160 static constexpr bool c_stdCamera_emGain = true; ///< app::dev config to tell stdCamera to expose EM gain controls
161
162 static constexpr bool c_stdCamera_exptimeCtrl =
163 true; ///< app::dev config to tell stdCamera to expose exposure time controls
164
165 static constexpr bool c_stdCamera_fpsCtrl = false; ///< app::dev config to tell stdCamera not to expose FPS controls
166
167 static constexpr bool c_stdCamera_fps = true; ///< app::dev config to tell stdCamera not to expose FPS status
168
169 static constexpr bool c_stdCamera_synchro =
170 true; ///< app::dev config to tell stdCamera to not expose synchro mode controls
171
172 static constexpr bool c_stdCamera_usesModes =
173 false; ///< app:dev config to tell stdCamera not to expose mode controls
174
175 static constexpr bool c_stdCamera_usesROI = true; ///< app:dev config to tell stdCamera to expose ROI controls
176
177 static constexpr bool c_stdCamera_cropMode =
178 false; ///< app:dev config to tell stdCamera to expose Crop Mode controls
179
180 static constexpr bool c_stdCamera_hasShutter =
181 true; ///< app:dev config to tell stdCamera to expose shutter controls
182
183 static constexpr bool c_stdCamera_hasFocus =
184 true; ///< app:dev config to tell stdCamera to expose focus-state reporting and goto-focus control
185
186 static constexpr bool c_stdCamera_usesStateString =
187 false; ///< app::dev confg to tell stdCamera to expose the state string property
188
189 static constexpr bool c_frameGrabber_flippable =
190 true; ///< app:dev config to tell framegrabber this camera can be flipped
191 ///@}
192
193 protected:
194 /** \name configurable parameters
195 *@{
196 */
197 std::string m_serialNumber; ///< The camera's identifying serial number
198
199 ///@}
200
201 int m_depth{ 0 };
202
203 piint m_timeStampMask{ PicamTimeStampsMask_ExposureStarted }; // time stamp at end of exposure
204 pi64s m_tsRes; // time stamp resolution
206 double m_camera_timestamp{ 0.0 };
209
210 std::string m_fxngenName{ "fxngensync" }; ///< Default fxngen device name
211 std::string m_fxngenCh{ "C2" }; ///< Default fxngen channel
212
213 std::string m_otherCamName;
214
217
220
221 std::string m_cameraName;
222 std::string m_cameraModel;
223 bool m_fanControlSupported{ false }; ///< True when the camera exposes the DisableCoolingFan control parameter.
224 bool m_fanStatusSupported{ false }; ///< True when the camera exposes readable cooling-fan status.
225 bool m_fanForcedOn{ false }; ///< True while the camera reports the cooling fan is forced on for protection.
227 false }; ///< True when the next successful fan apply should emit a notice even without a state change.
228
229 public:
230 /// Default c'tor
231 picamCtrl();
232
233 /// Destructor
235
236 /// Setup the configuration system (called by MagAOXApp::setup())
237 virtual void setupConfig();
238
239 /// load the configuration system results (called by MagAOXApp::setup())
240 virtual void loadConfig();
241
242 /// Startup functions
243 /** Sets up the INDI vars.
244 *
245 */
246 virtual int appStartup();
247
248 /// Implementation of the FSM for the Siglent SDG
249 virtual int appLogic();
250
251 /// Implementation of the on-power-off FSM logic
252 virtual int onPowerOff();
253
254 /// Implementation of the while-powered-off FSM
256
257 /// Do any needed shutdown tasks. Currently nothing in this app.
258 virtual int appShutdown();
259
260 protected:
262
264
266
268
270
272
274
276
278
280
282
283 int connect();
284
286
287 /// Get the current cooling-fan state from the camera.
288 int getFanSpeed();
289
290 int getTemps();
291
292 // stdCamera interface:
293
294 // This must set the power-on default values of
295 /* -- m_ccdTempSetpt
296 * -- m_currentROI
297 */
298 int powerOnDefaults();
299
300 int setTempControl();
301 int setTempSetPt();
302 int setReadoutSpeed();
303 int setVShiftSpeed();
304 /// Request a cooling-fan state change through the next reconfiguration.
305 int setFanSpeed();
306 int setEMGain();
307 int setExpTime();
308 int capExpTime( piflt &exptime );
309 int setFPS();
310 int setSynchro();
311 void updateFxnGenSync();
312
313 /// Check the next ROI
314 /** Checks if the target values are valid and adjusts them to the closest valid values if needed.
315 *
316 * \returns 0 if successful
317 * \returns -1 otherwise
318 */
319 int checkNextROI();
320
321 /// Reports whether the camera is currently in focus. [stdCamera interface]
322 /**
323 * \returns `true` when the configured external focus switch indicates the camera is in focus.
324 * \returns `false` otherwise
325 */
326 bool checkFocus();
327
328 int setNextROI();
329
330 /// Requests the configured focus preset. [stdCamera interface]
331 /**
332 * \returns 0 on success
333 * \returns -1 if the goto-focus helper is not fully configured
334 */
335 int gotoFocus();
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 // INDI:
352 protected:
354 pcf::IndiProperty m_indiP_fxngensync_freq; ///< Property for setting fxngensync frequency
355 pcf::IndiProperty m_indiP_fxngensync_output; ///< Proprety for turning on fxngensync
356
357 pcf::IndiProperty m_indiP_receiveSynchro; ///< Synchro that can only be triggered from the otherCam
358 pcf::IndiProperty m_indiP_receiveExptime; ///< Exptime that can only be triggered from the otherCam
359
360 pcf::IndiProperty m_indiP_otherCamExptime; ///< Property for setting otherCam exptime
361 pcf::IndiProperty m_indiP_otherCamSynchro; ///< Property for setting otherCam synchro
362
363 public:
365
367
369
370 /** \name Telemeter Interface
371 *
372 * @{
373 */
374 int checkRecordTimes();
375
377
378 ///@}
379};
380
382{
383 m_powerMgtEnabled = true;
384
385 m_acqBuff.memory_size = 0;
386 m_acqBuff.memory = 0;
387
388 m_defaultReadoutSpeed = "emccd_05MHz";
389 m_readoutSpeedNames = { "ccd_00_1MHz", "ccd_01MHz", "emccd_05MHz", "emccd_10MHz", "emccd_20MHz", "emccd_30MHz" };
391 "CCD 0.1 MHz", "CCD 1 MHz", "EMCCD 5 MHz", "EMCCD 10 MHz", "EMCCD 20 MHz", "EMCCD 30 MHz" };
392
393 m_defaultVShiftSpeed = "1_2us";
394 m_vShiftSpeedNames = { "0_7us", "1_2us", "2_0us", "5_0us" };
395 m_vShiftSpeedNameLabels = { "0.7 us", "1.2 us", "2.0 us", "5.0 us" };
396
397 m_defaultFanSpeed = "on";
398 m_fanSpeedNames = { "on", "off" };
399 m_fanSpeedNameLabels = { "On", "Off" };
402
403 m_full_x = 511.5;
404 m_full_y = 511.5;
405 m_full_w = 1024;
406 m_full_h = 1024;
407
408 m_maxEMGain = 1000;
409
410 return;
411}
412
414{
415 if( m_acqBuff.memory )
416 {
417 free( m_acqBuff.memory );
418 }
419
420 return;
421}
422
423/// Interface to setSynchro when the derivedT has synchronization
424/** Tag-dispatch resolution of c_stdCamera_synchro==true will call this function.
425 * Calls derivedT::setSynchro.
426 */
428{
429 if( !m_otherCamName.empty() )
430 {
431 if( m_synchroSet )
432 {
433 std::cerr << "Turning synchro on for " << m_otherCamName << std::endl;
434 m_indiP_otherCamSynchro["toggle"] = pcf::IndiElement::On;
436
437 std::cerr << "Setting " << m_otherCamName << "'s exposure time" << std::endl;
440 }
441 else
442 {
443 std::cerr << "Turning synchro off for " << m_otherCamName << std::endl;
444 m_indiP_otherCamSynchro["toggle"] = pcf::IndiElement::Off;
446 }
447 }
448
449 recordCamera( true );
450 m_reconfig = true;
451
452 return 0;
453}
454
456{
457 config.add( "camera.serialNumber",
458 "",
459 "camera.serialNumber",
460 argType::Required,
461 "camera",
462 "serialNumber",
463 false,
464 "int",
465 "The identifying serial number of the camera." );
466
467 config.add( "synchro.deviceName",
468 "",
469 "synchro.deviceName",
470 argType::Required,
471 "synchro",
472 "deviceName",
473 false,
474 "string",
475 "The fxngen device name used for synchronizing the camera." );
476 config.add( "synchro.channel",
477 "",
478 "synchro.channel",
479 argType::Required,
480 "synchro",
481 "channel",
482 false,
483 "string",
484 "The fxngen channel used for synchronizing the camera." );
485 config.add( "synchro.otherCamName",
486 "",
487 "synchro.otherCamName",
488 argType::Required,
489 "synchro",
490 "otherCamName",
491 false,
492 "string",
493 "The other camera (used for coupling exposure time while synchro'd)" );
494
499}
500
502{
503
504 config( m_serialNumber, "camera.serialNumber" );
505 config( m_fxngenName, "synchro.deviceName" );
506 config( m_fxngenCh, "synchro.channel" );
507 config( m_otherCamName, "synchro.otherCamName" );
508
513}
514
516{
517
518 // DELETE ME
519 // m_outfile = fopen("/home/xsup/test2.txt", "w");
520
521 createROIndiNumber( m_indiP_readouttime, "readout_time", "Readout Time (s)" );
522 indi::addNumberElement<float>(
523 m_indiP_readouttime, "value", 0.0, std::numeric_limits<float>::max(), 0.0, "%0.1f", "readout time" );
525
526 m_minTemp = -55;
527 m_maxTemp = 25;
528 m_stepTemp = 0;
529
530 m_minROIx = 0;
531 m_maxROIx = 1023;
532 m_stepROIx = 0;
533
534 m_minROIy = 0;
535 m_maxROIy = 1023;
536 m_stepROIy = 0;
537
538 m_minROIWidth = 1;
539 m_maxROIWidth = 1024;
540 m_stepROIWidth = 4;
541
542 m_minROIHeight = 1;
543 m_maxROIHeight = 1024;
544 m_stepROIHeight = 1;
545
549
551 m_maxROIBinning_y = 1024;
553
555 {
556 return log<software_critical, -1>( { __FILE__, __LINE__ } );
557 }
558
560 {
561 return log<software_critical, -1>( { __FILE__, __LINE__ } );
562 }
563
565 {
566 return log<software_critical, -1>( { __FILE__, __LINE__ } );
567 }
568
570 {
571 return log<software_error, -1>( { __FILE__, __LINE__ } );
572 }
573
574 m_indiP_fxngensync_freq = pcf::IndiProperty( pcf::IndiProperty::Number );
576 m_indiP_fxngensync_freq.setName( m_fxngenCh + "freq" );
577 m_indiP_fxngensync_freq.add( pcf::IndiElement( "target" ) );
578
579 m_indiP_fxngensync_output = pcf::IndiProperty( pcf::IndiProperty::Text );
581 m_indiP_fxngensync_output.setName( m_fxngenCh + "outp" );
582 m_indiP_fxngensync_output.add( pcf::IndiElement( "value" ) );
583
585 "receiveExptime",
589 "%0.3f",
590 "Exptime",
591 "Other cam" );
593
594 m_indiP_otherCamExptime = pcf::IndiProperty( pcf::IndiProperty::Number );
596 m_indiP_otherCamExptime.setName( "receiveExptime" );
597 m_indiP_otherCamExptime.add( pcf::IndiElement( "target" ) );
598
599 m_indiP_otherCamSynchro = pcf::IndiProperty( pcf::IndiProperty::Switch );
601 m_indiP_otherCamSynchro.setName( "receiveSynchro" );
602 m_indiP_otherCamSynchro.add( pcf::IndiElement( "toggle" ) );
603
604 return 0;
605}
606
608{
609 // and run stdCamera's appLogic
611 {
612 return log<software_error, -1>( { __FILE__, __LINE__ } );
613 }
614
615 // first run frameGrabber's appLogic to see if the f.g. thread has exited.
617 {
618 return log<software_error, -1>( { __FILE__, __LINE__ } );
619 }
620
621 // and run dssShutter's appLogic
623 {
624 return log<software_error, -1>( { __FILE__, __LINE__ } );
625 }
626
628 {
629 m_reconfig = true; // Trigger a f.g. thread reconfig.
630
631 // Might have gotten here because of a power off.
632 if( powerState() != 1 || powerStateTarget() != 1 )
633 return 0;
634
635 std::cerr << __LINE__ << '\n';
636 std::unique_lock<std::mutex> lock( m_indiMutex );
637 if( connect() < 0 )
638 {
639 if( powerState() != 1 || powerStateTarget() != 1 )
640 return 0;
642 }
643
645 return 0;
646 }
647
649 {
650 // Get a lock
651 std::unique_lock<std::mutex> lock( m_indiMutex );
652
653 if( getAcquisitionState() < 0 )
654 {
655 if( powerState() != 1 || powerStateTarget() != 1 )
656 return 0;
658 }
659
660 if( setTempSetPt() < 0 ) // m_ccdTempSetpt already set on power on
661 {
662 if( powerState() != 1 || powerStateTarget() != 1 )
663 return 0;
665 }
666
668 {
669 if( powerState() != 1 || powerStateTarget() != 1 )
670 return 0;
672 }
673
675 {
677 }
678 }
679
681 {
682 // Get a lock if we can
683 std::unique_lock<std::mutex> lock( m_indiMutex, std::try_to_lock );
684
685 // but don't wait for it, just go back around.
686 if( !lock.owns_lock() )
687 return 0;
688
689 if( getAcquisitionState() < 0 )
690 {
691 if( powerState() != 1 || powerStateTarget() != 1 )
692 return 0;
693
695 return 0;
696 }
697
698 if( getTemps() < 0 )
699 {
700 if( powerState() != 1 || powerStateTarget() != 1 )
701 return 0;
702
704 return 0;
705 }
706
708 {
709 if( powerState() != 1 || powerStateTarget() != 1 )
710 return 0;
711
713 return 0;
714 }
715
717 {
719 }
720
722 {
724 }
725
727 {
729 return 0;
730 }
731 }
732
733 // Fall through check?
734 return 0;
735}
736
738{
739 std::lock_guard<std::mutex> lock( m_indiMutex );
740
741 if( m_cameraHandle )
742 {
744 m_cameraHandle = 0;
745 }
746
748
750 {
752 }
753
755 {
757 }
758
759 return 0;
760}
761
763{
765 {
767 }
768
770 {
772 }
773
774 return 0;
775}
776
778{
780
781 if( m_cameraHandle )
782 {
784 m_cameraHandle = 0;
785 }
786
788
789 ///\todo error check these base class fxns.
792
793 return 0;
794}
795
797{
799
800 if( MagAOXAppT::m_powerState == 0 )
801 return -1; // Flag error but don't log
802
803 if( error != PicamError_None )
804 {
805 if( powerState() != 1 || powerStateTarget() != 1 )
806 return -1;
808 return -1;
809 }
810
811 return 0;
812}
813
815{
817
818 if( MagAOXAppT::m_powerState == 0 )
819 return -1; // Flag error but don't log
820
821 if( error != PicamError_None )
822 {
823 if( powerState() != 1 || powerStateTarget() != 1 )
824 return -1;
826 return -1;
827 }
828
829 return 0;
830}
831
833{
835 if( error != PicamError_None )
836 {
837 if( powerState() != 1 || powerStateTarget() != 1 )
838 return -1;
840 return -1;
841 }
842
843 if( !commit )
844 return 0;
845
848
850 if( error != PicamError_None )
851 {
852 if( powerState() != 1 || powerStateTarget() != 1 )
853 return -1;
855 return -1;
856 }
857
858 for( int i = 0; i < failed_parameters_count; ++i )
859 {
861 {
863 return log<text_log, -1>( "Parameter not committed" );
864 }
865 }
866
868
869 return 0;
870}
871
873{
875 if( error != PicamError_None )
876 {
877 if( powerState() != 1 || powerStateTarget() != 1 )
878 return -1;
880 return -1;
881 }
882
883 if( !commit )
884 return 0;
885
888
890 if( error != PicamError_None )
891 {
892 if( powerState() != 1 || powerStateTarget() != 1 )
893 return -1;
895 return -1;
896 }
897
898 for( int i = 0; i < failed_parameters_count; ++i )
899 {
901 {
903 return log<text_log, -1>( "Parameter not committed" );
904 }
905 }
906
908
909 return 0;
910}
911
913{
915 if( error != PicamError_None )
916 {
917 if( powerState() != 1 || powerStateTarget() != 1 )
918 return -1;
920 return -1;
921 }
922
923 if( !commit )
924 return 0;
925
928
930 if( error != PicamError_None )
931 {
932 if( powerState() != 1 || powerStateTarget() != 1 )
933 return -1;
935 return -1;
936 }
937
938 for( int i = 0; i < failed_parameters_count; ++i )
939 {
941 {
943 return log<text_log, -1>( "Parameter not committed" );
944 }
945 }
946
948
949 return 0;
950}
951
956
961
963{
965 if( error != PicamError_None )
966 {
967 if( powerState() != 1 || powerStateTarget() != 1 )
968 return -1;
970 return -1;
971 }
972
973 return 0;
974}
975
980
982{
984 if( error != PicamError_None )
985 {
986 if( powerState() != 1 || powerStateTarget() != 1 )
987 return -1;
989 return -1;
990 }
991
992 return 0;
993}
994
999
1001{
1002 std::cerr << __LINE__ << '\n';
1006
1007 if( m_acqBuff.memory )
1008 {
1009 free( m_acqBuff.memory );
1010 m_acqBuff.memory = NULL;
1011 m_acqBuff.memory_size = 0;
1012 }
1013
1014 std::cerr << __LINE__ << '\n';
1015
1017
1018 std::cerr << __LINE__ << '\n';
1019
1020 // Have to initialize the library every time. Otherwise we won't catch a newly booted camera.
1022
1023 std::cerr << __LINE__ << '\n';
1024
1025 if( m_cameraHandle )
1026 {
1028 m_cameraHandle = 0;
1029 }
1030
1031 std::cerr << __LINE__ << '\n';
1032
1033 Picam_GetAvailableCameraIDs( const_cast<const PicamCameraID **>( &id_array ), &id_count );
1034
1035 std::cerr << __LINE__ << '\n';
1036
1037 if( powerState() != 1 || powerStateTarget() != 1 )
1038 return 0;
1039
1040 std::cerr << __LINE__ << '\n';
1041
1042 if( id_count == 0 )
1043 {
1045
1047
1049 if( !stateLogged() )
1050 {
1051 log<text_log>( "no P.I. Cameras available.", logPrio::LOG_NOTICE );
1052 }
1053 return 0;
1054 }
1055 else
1056 {
1057 std::cerr << "found " << id_count << " PI cameras.\n";
1058 }
1059
1060 for( int i = 0; i < id_count; ++i )
1061 {
1062 if( std::string( id_array[i].serial_number ) == m_serialNumber )
1063 {
1064 log<text_log>( "Camera was found. Now connecting." );
1065
1067 if( error == PicamError_None )
1068 {
1069 m_cameraName = id_array[i].sensor_name;
1071
1073 if( error != PicamError_None )
1074 {
1075 log<software_error>( { __FILE__, __LINE__, "failed to get camera model" } );
1076 }
1077
1078 m_fanControlSupported = false;
1079 m_fanStatusSupported = false;
1080
1082 {
1083 pibln exists = false;
1084
1086 if( error != PicamError_None )
1087 {
1088 if( powerState() != 1 || powerStateTarget() != 1 )
1089 return 0;
1090
1093 { __FILE__, __LINE__, 0, error, "Error checking DisableCoolingFan support." } );
1095 return -1;
1096 }
1097
1099
1101 {
1102 if( powerState() != 1 || powerStateTarget() != 1 )
1103 return 0;
1104
1107 __LINE__,
1108 "Fan control enabled in config, but DisableCoolingFan is not supported "
1109 "by this camera." } );
1111 return -1;
1112 }
1113
1114 exists = false;
1116 if( error != PicamError_None )
1117 {
1118 if( powerState() != 1 || powerStateTarget() != 1 )
1119 return 0;
1120
1123 { __FILE__, __LINE__, 0, error, "Error checking CoolingFanStatus support." } );
1125 return -1;
1126 }
1127
1128 if( exists )
1129 {
1130 pibln readable = false;
1131
1133 if( error != PicamError_None )
1134 {
1135 if( powerState() != 1 || powerStateTarget() != 1 )
1136 return 0;
1137
1140 { __FILE__, __LINE__, 0, error, "Error checking CoolingFanStatus readability." } );
1142 return -1;
1143 }
1144
1146 }
1147
1149 {
1151 "cooling-fan status parameter unavailable; using commanded state without hardware readback",
1153 }
1154 }
1155
1157 log<text_log>( "Connected to " + m_cameraName + " [S/N " + m_serialNumber + "]" );
1158
1160
1164 {
1166 m_fanSpeedLogPending = true;
1167 }
1168
1169 return 0;
1170 }
1171 else
1172 {
1173 if( powerState() != 1 || powerStateTarget() != 1 )
1174 return 0;
1175
1177 if( !stateLogged() )
1178 {
1179 log<software_error>( { __FILE__, __LINE__, 0, error, "Error connecting to camera." } );
1180 }
1181
1183
1185 return -1;
1186 }
1187 }
1188 }
1189
1191 if( !stateLogged() )
1192 {
1193 log<text_log>( "Camera not found in available ids." );
1194 }
1195
1197
1199
1200 return 0;
1201}
1202
1204{
1205 pibln running = false;
1206
1208
1209 if( MagAOXAppT::m_powerState == 0 )
1210 return 0;
1211
1212 if( error != PicamError_None )
1213 {
1214 if( powerState() != 1 || powerStateTarget() != 1 )
1215 return -1;
1218 return -1;
1219 }
1220
1221 if( running )
1223 else
1225
1226 if( !running )
1227 {
1228 log<text_log>( "acqusition stopped. restarting", logPrio::LOG_ERROR );
1229 m_reconfig = true;
1230 }
1231
1232 return 0;
1233}
1234
1236{
1238
1240 {
1241 if( powerState() != 1 || powerStateTarget() != 1 )
1242 return -1;
1243
1246 return -1;
1247 }
1248
1250
1251 // PicamSensorTemperatureStatus
1252 piint status;
1253
1255 {
1256 if( powerState() != 1 || powerStateTarget() != 1 )
1257 return -1;
1258
1261 return -1;
1262 }
1263
1265 {
1266 m_tempControlStatus = true;
1267 m_tempControlOnTarget = false;
1268 m_tempControlStatusStr = "UNLOCKED";
1269 }
1270 else if( status == PicamSensorTemperatureStatus_Locked )
1271 {
1272 m_tempControlStatus = true;
1273 m_tempControlOnTarget = true;
1274 m_tempControlStatusStr = "LOCKED";
1275 }
1276 else if( status == PicamSensorTemperatureStatus_Faulted )
1277 {
1278 m_tempControlStatus = false;
1279 m_tempControlOnTarget = false;
1280 m_tempControlStatusStr = "FAULTED";
1281 log<text_log>( "temperature control faulted", logPrio::LOG_ALERT );
1282 }
1283 else
1284 {
1285 m_tempControlStatus = false;
1286 m_tempControlOnTarget = false;
1287 m_tempControlStatusStr = "UNKNOWN";
1288 }
1289
1290 recordCamera();
1291
1292 return 0;
1293}
1294
1296{
1298 return 0;
1299
1300 piint status;
1301
1303 {
1304 if( powerState() != 1 || powerStateTarget() != 1 )
1305 return -1;
1306
1309 return -1;
1310 }
1311
1312 bool fanForcedOn = false;
1313
1314 if( status == PicamCoolingFanStatus_Off )
1315 {
1316 m_fanSpeedName = "off";
1317 }
1318 else if( status == PicamCoolingFanStatus_On )
1319 {
1320 m_fanSpeedName = "on";
1321 }
1322 else if( status == PicamCoolingFanStatus_ForcedOn )
1323 {
1324 m_fanSpeedName = "on";
1325 fanForcedOn = true;
1326 }
1327 else
1328 {
1329 return log<software_error, -1>( { __FILE__, __LINE__, "Unknown cooling-fan status returned by PICam." } );
1330 }
1331
1332 if( fanForcedOn && !m_fanForcedOn )
1333 {
1334 log<text_log>( "cooling fan forced on by camera", logPrio::LOG_NOTICE );
1335 }
1336
1338 m_fanSpeedValid = true;
1339 recordCamera();
1340
1341 return 0;
1342}
1343
1345{
1346 return 0;
1347}
1348
1350{
1351 m_ccdTempSetpt = -55; // This is the power on setpoint
1352
1353 /*m_currentROI.x = 511.5;
1354 m_currentROI.y = 511.5;
1355 m_currentROI.w = 1024;
1356 m_currentROI.h = 1024;
1357 m_currentROI.bin_x = 1;
1358 m_currentROI.bin_y = 1;*/
1359
1360 m_readoutSpeedName = "emccd_05MHz";
1361 m_vShiftSpeedName = "1_2us";
1362
1364 {
1367 }
1368 else
1369 {
1370 m_fanSpeedName.clear();
1371 m_fanSpeedNameSet.clear();
1372 }
1373
1374 m_fanForcedOn = false;
1375 m_fanControlSupported = false;
1376 m_fanStatusSupported = false;
1377 m_fanSpeedValid = false;
1379
1380 return 0;
1381}
1382
1384{
1385 // Always on
1386 m_tempControlStatus = true;
1388 updateSwitchIfChanged( m_indiP_tempcont, "toggle", pcf::IndiElement::On, INDI_IDLE );
1389 recordCamera( true );
1390 return 0;
1391}
1392
1394{
1395 ///\todo bounds check here.
1396 recordCamera( true );
1397 m_reconfig = true;
1398 return 0;
1399}
1400
1402{
1403 recordCamera( true );
1404 m_reconfig = true;
1405 return 0;
1406}
1407
1409{
1410 recordCamera( true );
1411 m_reconfig = true;
1412 return 0;
1413}
1414
1416{
1417 m_fanSpeedLogPending = true;
1418 recordCamera( true );
1419 m_reconfig = true;
1420 return 0;
1421}
1422
1424{
1425 piint adcQual;
1426 piflt adcSpeed;
1427
1428 if( readoutParams( adcQual, adcSpeed, m_readoutSpeedName ) < 0 )
1429 {
1430 log<software_error>( { __FILE__, __LINE__, "Invalid readout speed: " + m_readoutSpeedNameSet } );
1432 return -1;
1433 }
1434
1436 {
1437 m_emGain = 1;
1438 m_adcSpeed = adcSpeed;
1439 recordCamera( true );
1440 log<text_log>( "Attempt to set EM gain while in conventional amplifier.", logPrio::LOG_NOTICE );
1441 return 0;
1442 }
1443
1445 if( emg < 0 )
1446 {
1447 emg = 0;
1448 log<text_log>( "EM gain limited to 0", logPrio::LOG_WARNING );
1449 }
1450
1451 if( emg > m_maxEMGain )
1452 {
1453 emg = m_maxEMGain;
1454 log<text_log>( "EM gain limited to maxEMGain = " + std::to_string( emg ), logPrio::LOG_WARNING );
1455 }
1456
1457 recordCamera( true );
1459 {
1460 if( powerState() != 1 || powerStateTarget() != 1 )
1461 return -1;
1462 log<software_error>( { __FILE__, __LINE__, "Error setting EM gain" } );
1463 return -1;
1464 }
1465
1468 {
1469 if( powerState() != 1 || powerStateTarget() != 1 )
1470 return -1;
1471 return log<software_error, -1>( { __FILE__, __LINE__, "could not get AdcEMGain" } );
1472 }
1474 m_adcSpeed = adcSpeed;
1475 recordCamera( true );
1476 return 0;
1477}
1478
1480{
1481
1482 std::cerr << "Setting fxngen frequency to " << std::to_string( m_fps ) << " Hz" << std::endl;
1483 m_indiP_fxngensync_freq["target"] = m_fps;
1485
1486 // make sure fxngen is on!
1487 m_indiP_fxngensync_output["value"] = "On";
1489}
1490
1492{
1493 long intexptime = m_expTimeSet * 1000 * 10000 + 0.5;
1494 piflt exptime = ( (double)intexptime ) / 10000;
1495 capExpTime( exptime );
1496
1497 int rv;
1498
1499 recordCamera( true );
1500
1501 if( state() == stateCodes::OPERATING )
1502 {
1504 }
1505 else
1506 {
1508 }
1509
1510 if( rv < 0 )
1511 {
1512 if( powerState() != 1 || powerStateTarget() != 1 )
1513 return -1;
1514 log<software_error>( { __FILE__, __LINE__, "Error setting exposure time" } );
1515 return -1;
1516 }
1517
1518 m_expTime = exptime / 1000.0;
1519
1520 recordCamera( true );
1521
1523
1525 {
1526 if( powerState() != 1 || powerStateTarget() != 1 )
1527 return -1;
1528 log<software_error>( { __FILE__, __LINE__, "could not get FrameRateCalculation" } );
1529 }
1531
1532 if( m_synchro && !m_otherCamName.empty() )
1533 {
1534 std::cerr << "Setting " << m_otherCamName << " exptime to " << std::to_string( m_expTime ) << std::endl;
1537
1539 }
1540
1541 recordCamera( true );
1542
1543 return 0;
1544}
1545
1546inline int picamCtrl::capExpTime( piflt &exptime )
1547{
1548 // cap at minimum possible value
1549 if( exptime < m_ReadOutTimeCalculation )
1550 {
1551 if( powerState() != 1 || powerStateTarget() != 1 )
1552 return -1;
1553 log<text_log>( "Got exposure time " + std::to_string( exptime ) + " ms but min value is " +
1554 std::to_string( m_ReadOutTimeCalculation ) + " ms" );
1555 long intexptime = m_ReadOutTimeCalculation * 10000 + 0.5;
1556 exptime = ( (double)intexptime ) / 10000;
1557 }
1558
1559 return 0;
1560}
1561
1563{
1564 return 0;
1565}
1566
1567// Set ROI property to busy if accepted, set toggle to Off and Idlw either way.
1568// Set ROI actual
1569// Update current values (including struct and indiP) and set to OK when done
1571{
1572 updateSwitchIfChanged( m_indiP_roi_set, "request", pcf::IndiElement::Off, INDI_IDLE );
1573 m_reconfig = true;
1574
1575 return 0;
1576}
1577
1579{
1580 return checkFocusSwitchState();
1581}
1582
1584{
1585 return sendGotoFocusCommand();
1586}
1587
1588inline int picamCtrl::setShutter( int sh )
1589{
1591}
1592
1594{
1595
1599 // piint frameSize;
1601
1602 m_camera_timestamp = 0; // reset tracked timestamp
1603
1604 std::unique_lock<std::mutex> lock( m_indiMutex );
1605
1606 // Time stamp handling
1608 {
1609 if( powerState() != 1 || powerStateTarget() != 1 )
1610 return -1;
1611 log<software_error>( { __FILE__, __LINE__, "Could not set time stamp mask" } );
1612 }
1614 {
1615 if( powerState() != 1 || powerStateTarget() != 1 )
1616 return -1;
1617 log<software_error>( { __FILE__, __LINE__, "Could not get timestamp resolution" } );
1618 }
1619
1620 //=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
1621 //=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
1622 // Check Frame Transfer
1623 //=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
1624 //=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
1625
1626 piint cmode;
1628 {
1629 if( powerState() != 1 || powerStateTarget() != 1 )
1630 return -1;
1631 log<software_error>( { __FILE__, __LINE__, "could not get Readout Control Mode" } );
1632 return -1;
1633 }
1634
1636 {
1637 if( powerState() != 1 || powerStateTarget() != 1 )
1638 return -1;
1639 log<software_error>( { __FILE__, __LINE__, "Readout Control Mode not configured for frame transfer" } );
1640 return -1;
1641 }
1642
1643 //=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
1644 //=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
1645 // Cooling Fan
1646 //=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
1647 //=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
1648
1650 {
1651 static constexpr piint c_enableCoolingFan = 0;
1652 static constexpr piint c_disableCoolingFan = 1;
1653
1654 std::string priorFanSpeed = m_fanSpeedName;
1656
1657 if( m_fanSpeedNameSet == "on" )
1658 {
1660 }
1661 else if( m_fanSpeedNameSet == "off" )
1662 {
1664 }
1665 else
1666 {
1667 if( powerState() != 1 || powerStateTarget() != 1 )
1668 return -1;
1669 log<software_error>( { __FILE__, __LINE__, "Invalid fan speed: " + m_fanSpeedNameSet } );
1671 return -1;
1672 }
1673
1675 {
1676 if( powerState() != 1 || powerStateTarget() != 1 )
1677 return -1;
1678 log<software_error>( { __FILE__, __LINE__, "Error setting cooling-fan state" } );
1680 return -1;
1681 }
1682
1684 m_fanSpeedValid = true;
1685 m_fanForcedOn = false;
1686
1688 {
1689 log<text_log>( "fan speed changed from '" + priorFanSpeed + "' to '" + m_fanSpeedName + "'",
1691 }
1692 else if( m_fanSpeedLogPending )
1693 {
1694 log<text_log>( "fan speed set to '" + m_fanSpeedName + "'", logPrio::LOG_NOTICE );
1695 }
1696
1697 m_fanSpeedLogPending = false;
1698 }
1699
1700 //=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
1701 //=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
1702 // Temperature
1703 //=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
1704 //=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
1705
1707 {
1708 if( powerState() != 1 || powerStateTarget() != 1 )
1709 return -1;
1710 log<software_error>( { __FILE__, __LINE__, "Error setting temperature setpoint" } );
1712 return -1;
1713 }
1714
1715 // log<text_log>( "Set temperature set point: " + std::to_string(m_ccdTempSetpt) + " C");
1716
1717 //=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
1718 //=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
1719 // ADC Speed and Quality
1720 //=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
1721 //=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
1722
1723 piint adcQual;
1724 piflt adcSpeed;
1725
1726 if( readoutParams( adcQual, adcSpeed, m_readoutSpeedNameSet ) < 0 )
1727 {
1728 if( powerState() != 1 || powerStateTarget() != 1 )
1729 return -1;
1730 log<software_error>( { __FILE__, __LINE__, "Invalid readout speed: " + m_readoutSpeedNameSet } );
1732 return -1;
1733 }
1734
1736 0 ) // don't commit b/c it will error if quality mismatched
1737 {
1738 if( powerState() != 1 || powerStateTarget() != 1 )
1739 return -1;
1740 log<software_error>( { __FILE__, __LINE__, "Error setting ADC Speed" } );
1741 // state(stateCodes::ERROR);
1742 // return -1;
1743 }
1744
1746 {
1747 if( powerState() != 1 || powerStateTarget() != 1 )
1748 return -1;
1749 log<software_error>( { __FILE__, __LINE__, "Error setting ADC Quality" } );
1751 return -1;
1752 }
1753 m_adcSpeed = adcSpeed;
1755 log<text_log>( "Readout speed set to: " + m_readoutSpeedNameSet );
1756
1758 {
1759 m_emGain = 1.0;
1760 m_emGainSet = 1.0;
1761 }
1762
1763 //=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
1764 //=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
1765 // Vertical Shift Rate
1766 //=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
1767 //=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
1768
1769 piflt vss;
1771 {
1772 if( powerState() != 1 || powerStateTarget() != 1 )
1773 return -1;
1774 log<software_error>( { __FILE__, __LINE__, "Invalid vertical shift speed: " + m_vShiftSpeedNameSet } );
1776 return -1;
1777 }
1778
1780 {
1781 if( powerState() != 1 || powerStateTarget() != 1 )
1782 return -1;
1783 log<software_error>( { __FILE__, __LINE__, "Error setting Vertical Shift Rate" } );
1785 return -1;
1786 }
1787
1790 log<text_log>( "Vertical Shift Rate set to: " + m_vShiftSpeedName );
1791
1792 //=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
1793 //=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
1794 // Dimensions
1795 //=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
1796 //=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
1797
1800
1801 nextrois.roi_array = &nextroi;
1802 nextrois.roi_count = 1;
1803
1804 int roi_err = false;
1806 {
1807 nextroi.x = ( ( 1023 - m_nextROI.x ) - 0.5 * ( (float)m_nextROI.w - 1.0 ) );
1808 }
1809 else
1810 {
1811 nextroi.x = ( m_nextROI.x - 0.5 * ( (float)m_nextROI.w - 1.0 ) );
1812 }
1813
1814 if( nextroi.x < 0 )
1815 {
1816 log<software_error>( { __FILE__, __LINE__, "can't set ROI to x center < 0" } );
1817 roi_err = true;
1818 }
1819
1820 if( nextroi.x > 1023 )
1821 {
1822 log<software_error>( { __FILE__, __LINE__, "can't set ROI to x center > 1023" } );
1823 roi_err = true;
1824 }
1825
1827 {
1828 nextroi.y = ( ( 1023 - m_nextROI.y ) - 0.5 * ( (float)m_nextROI.h - 1.0 ) );
1829 }
1830 else
1831 {
1832 nextroi.y = ( m_nextROI.y - 0.5 * ( (float)m_nextROI.h - 1.0 ) );
1833 }
1834
1835 if( nextroi.y < 0 )
1836 {
1837 log<software_error>( { __FILE__, __LINE__, "can't set ROI to y center < 0" } );
1838 roi_err = true;
1839 }
1840
1841 if( nextroi.y > 1023 )
1842 {
1843 log<software_error>( { __FILE__, __LINE__, "can't set ROI to y center > 1023" } );
1844 roi_err = true;
1845 }
1846
1847 nextroi.width = m_nextROI.w;
1848
1849 if( nextroi.width < 0 )
1850 {
1851 log<software_error>( { __FILE__, __LINE__, "can't set ROI to width to be < 0" } );
1852 roi_err = true;
1853 }
1854
1855 if( nextroi.x + nextroi.width > 1024 )
1856 {
1857 log<software_error>( { __FILE__, __LINE__, "can't set ROI to width such that edge is > 1023" } );
1858 roi_err = true;
1859 }
1860
1861 nextroi.height = m_nextROI.h;
1862
1863 if( nextroi.y + nextroi.height > 1024 )
1864 {
1865 log<software_error>( { __FILE__, __LINE__, "can't set ROI to height such that edge is > 1023" } );
1866 roi_err = true;
1867 }
1868
1869 if( nextroi.height < 0 )
1870 {
1871 log<software_error>( { __FILE__, __LINE__, "can't set ROI to height to be < 0" } );
1872 roi_err = true;
1873 }
1874
1875 nextroi.x_binning = m_nextROI.bin_x;
1876
1877 if( nextroi.x_binning < 0 )
1878 {
1879 log<software_error>( { __FILE__, __LINE__, "can't set ROI x binning < 0" } );
1880 roi_err = true;
1881 }
1882
1883 nextroi.y_binning = m_nextROI.bin_y;
1884
1885 if( nextroi.y_binning < 0 )
1886 {
1887 log<software_error>( { __FILE__, __LINE__, "can't set ROI y binning < 0" } );
1888 roi_err = true;
1889 }
1890
1892
1893 if( !roi_err )
1894 {
1896 if( error != PicamError_None )
1897 {
1898 if( powerState() != 1 || powerStateTarget() != 1 )
1899 return -1;
1900 std::cerr << PicamEnum2String( PicamEnumeratedType_Error, error ) << "\n";
1904 return -1;
1905 }
1906 }
1907
1909 {
1910 if( powerState() != 1 || powerStateTarget() != 1 )
1911 return -1;
1912 log<software_error>( { __FILE__, __LINE__, "Error getting readout stride" } );
1914 return -1;
1915 }
1916
1918 {
1919 if( powerState() != 1 || powerStateTarget() != 1 )
1920 return -1;
1921 log<software_error>( { __FILE__, __LINE__, "Error getting frame stride" } );
1923
1924 return -1;
1925 }
1926
1928 {
1929 if( powerState() != 1 || powerStateTarget() != 1 )
1930 return -1;
1931 log<software_error>( { __FILE__, __LINE__, "Error getting frames per readout" } );
1933 return -1;
1934 }
1935
1937 {
1938 if( powerState() != 1 || powerStateTarget() != 1 )
1939 return -1;
1940 log<software_error>( { __FILE__, __LINE__, "Error getting frame size" } );
1942 return -1;
1943 }
1944
1946 {
1947 if( powerState() != 1 || powerStateTarget() != 1 )
1948 return -1;
1949 log<software_error>( { __FILE__, __LINE__, "Error getting pixel bit depth" } );
1951 return -1;
1952 }
1954
1955 const PicamRois *rois;
1957 if( error != PicamError_None )
1958 {
1959 if( powerState() != 1 || powerStateTarget() != 1 )
1960 return -1;
1963 return -1;
1964 }
1965 m_xbinning = rois->roi_array[0].x_binning;
1966 m_currentROI.bin_x = m_xbinning;
1967 m_ybinning = rois->roi_array[0].y_binning;
1968 m_currentROI.bin_y = m_ybinning;
1969
1970 std::cerr << rois->roi_array[0].x << "\n";
1971 std::cerr << ( rois->roi_array[0].x - 1 ) << "\n";
1972 std::cerr << rois->roi_array[0].width << "\n";
1973 std::cerr << 0.5 * ( (float)( rois->roi_array[0].width - 1.0 ) ) << "\n";
1974
1976 {
1977 m_currentROI.x = ( 1023.0 - rois->roi_array[0].x ) - 0.5 * ( (float)( rois->roi_array[0].width - 1.0 ) );
1978 // nextroi.x = ((1023-m_nextROI.x) - 0.5*( (float) m_nextROI.w - 1.0));
1979 }
1980 else
1981 {
1982 m_currentROI.x = ( rois->roi_array[0].x ) + 0.5 * ( (float)( rois->roi_array[0].width - 1.0 ) );
1983 }
1984
1986 {
1987 m_currentROI.y = ( 1023.0 - rois->roi_array[0].y ) - 0.5 * ( (float)( rois->roi_array[0].height - 1.0 ) );
1988 // nextroi.y = ((1023 - m_nextROI.y) - 0.5*( (float) m_nextROI.h - 1.0));
1989 }
1990 else
1991 {
1992 m_currentROI.y = ( rois->roi_array[0].y ) + 0.5 * ( (float)( rois->roi_array[0].height - 1.0 ) );
1993 }
1994
1995 m_currentROI.w = rois->roi_array[0].width;
1996 m_currentROI.h = rois->roi_array[0].height;
1997
1998 m_width = rois->roi_array[0].width / rois->roi_array[0].x_binning;
1999 m_height = rois->roi_array[0].height / rois->roi_array[0].y_binning;
2001
2008
2009 // We also update target to the settable values
2010 m_nextROI.x = m_currentROI.x;
2011 m_nextROI.y = m_currentROI.y;
2012 m_nextROI.w = m_currentROI.w;
2013 m_nextROI.h = m_currentROI.h;
2014 m_nextROI.bin_x = m_currentROI.bin_x;
2015 m_nextROI.bin_y = m_currentROI.bin_y;
2016
2023
2024 //=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
2025 //=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
2026 // Exposure Time and Frame Rate
2027 //=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
2028 //=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
2029
2031 {
2032 if( powerState() != 1 || powerStateTarget() != 1 )
2033 return -1;
2034 return log<software_error, -1>( { __FILE__, __LINE__, "could not get ReadOutTimeCalculation" } );
2035 }
2036 std::cerr << "Readout time is: " << m_ReadOutTimeCalculation << "\n";
2038 m_indiP_readouttime, "value", m_ReadOutTimeCalculation / 1000.0, INDI_OK ); // convert from msec to sec
2039
2044
2045 if( constraint_count != 1 )
2046 {
2047 if( powerState() != 1 || powerStateTarget() != 1 )
2048 return -1;
2049 log<text_log>( "Constraint count is not 1: " + std::to_string( constraint_count ) + " constraints",
2051 }
2052 else
2053 {
2054 m_minExpTime = constraint_array[0].minimum;
2055 m_maxExpTime = constraint_array[0].maximum;
2056 m_stepExpTime = constraint_array[0].increment;
2057
2058 m_indiP_exptime["current"].setMin( m_minExpTime );
2059 m_indiP_exptime["current"].setMax( m_maxExpTime );
2060 m_indiP_exptime["current"].setStep( m_stepExpTime );
2061
2062 m_indiP_exptime["target"].setMin( m_minExpTime );
2063 m_indiP_exptime["target"].setMax( m_maxExpTime );
2064 m_indiP_exptime["target"].setStep( m_stepExpTime );
2065 }
2066
2067 if( m_expTimeSet > 0 )
2068 {
2069 long intexptime = m_expTimeSet * 1000 * 10000 + 0.5;
2070 piflt exptime = ( (double)intexptime ) / 10000;
2071 capExpTime( exptime );
2072 std::cerr << "Setting exposure time to " << m_expTimeSet << "\n";
2074
2075 if( rv < 0 )
2076 {
2077 if( powerState() != 1 || powerStateTarget() != 1 )
2078 return -1;
2079 return log<software_error, -1>( { __FILE__, __LINE__, "Error setting exposure time" } );
2080 }
2081 }
2082
2083 piflt exptime;
2085 {
2086 if( powerState() != 1 || powerStateTarget() != 1 )
2087 return -1;
2088 return log<software_error, -1>( { __FILE__, __LINE__, "Error getting exposure time" } );
2089 }
2090 else
2091 {
2092 capExpTime( exptime );
2093 m_expTime = exptime / 1000.0;
2094 m_expTimeSet = m_expTime; // At this point it must be true.
2097 }
2098
2100 {
2101 if( powerState() != 1 || powerStateTarget() != 1 )
2102 return -1;
2103 return log<software_error, -1>( { __FILE__, __LINE__, "Error getting frame rate" } );
2104 }
2105 else
2106 {
2109 }
2110 std::cerr << "FrameRate is: " << m_FrameRateCalculation << "\n";
2111
2114 {
2115 std::cerr << "could not get AdcQuality\n";
2116 }
2118 std::cerr << "AdcQuality is: " << adcqStr << "\n";
2119
2122 {
2123 std::cerr << "could not get VerticalShiftRate\n";
2124 }
2125 std::cerr << "VerticalShiftRate is: " << verticalShiftRate << "\n";
2126
2129 {
2130 std::cerr << "could not get AdcSpeed\n";
2131 }
2132 std::cerr << "AdcSpeed is: " << AdcSpeed << "\n";
2133
2134 std::cerr << "************************************************************\n";
2135
2138 {
2139 std::cerr << "could not get AdcAnalogGain\n";
2140 }
2142 std::cerr << "AdcAnalogGain is: " << adcgStr << "\n";
2143
2144 if( m_readoutSpeedName == "ccd_00_1MHz" || m_readoutSpeedName == "ccd_01MHz" )
2145 {
2146 m_emGain = 1;
2147 }
2148 else
2149 {
2152 {
2153 std::cerr << "could not get AdcEMGain\n";
2154 }
2156 }
2157
2158 /*
2159 std::cerr << "Onlineable:\n";
2160 pibln onlineable;
2161 Picam_CanSetParameterOnline(m_modelHandle, PicamParameter_ReadoutControlMode,&onlineable);
2162 std::cerr << "ReadoutControlMode: " << onlineable << "\n"; //0
2163
2164 Picam_CanSetParameterOnline(m_modelHandle, PicamParameter_AdcQuality,&onlineable);
2165 std::cerr << "AdcQuality: " << onlineable << "\n"; //0
2166
2167 Picam_CanSetParameterOnline(m_modelHandle, PicamParameter_AdcAnalogGain,&onlineable);
2168 std::cerr << "AdcAnalogGain: " << onlineable << "\n"; //1
2169
2170 Picam_CanSetParameterOnline(m_modelHandle, PicamParameter_DisableCoolingFan,&onlineable);
2171 std::cerr << "DisableCoolingFan: " << onlineable << "\n";//0
2172
2173 Picam_CanSetParameterOnline(m_modelHandle, PicamParameter_SensorTemperatureSetPoint,&onlineable);
2174 std::cerr << "SensorTemperatureSetPoint: " << onlineable << "\n"; //0
2175
2176 Picam_CanSetParameterOnline(m_modelHandle, PicamParameter_AdcEMGain,&onlineable);
2177 std::cerr << "AdcEMGain: " << onlineable << "\n"; //1
2178
2179 Picam_CanSetParameterOnline(m_modelHandle, PicamParameter_FrameRateCalculation,&onlineable);
2180 std::cerr << "FrameRateCalculation: " << onlineable << "\n"; //0
2181
2182 std::cerr << "************************************************************\n";
2183 */
2184
2185 // If not previously allocated, allocate a nice big buffer to play with
2186 pi64s newbuffsz = framesPerReadout * readoutStride * 10; // Save room for 10 frames
2187 if( newbuffsz > m_acqBuff.memory_size )
2188 {
2189 if( m_acqBuff.memory )
2190 {
2191 std::cerr << "Clearing\n";
2192 free( m_acqBuff.memory );
2193 m_acqBuff.memory = NULL;
2195 }
2196
2197 m_acqBuff.memory_size = newbuffsz;
2198 std::cerr << "m_acqBuff.memory_size: " << m_acqBuff.memory_size << "\n";
2199 m_acqBuff.memory = malloc( m_acqBuff.memory_size );
2200
2202 if( error != PicamError_None )
2203 {
2207
2208 std::cerr << "-->" << PicamEnum2String( PicamEnumeratedType_Error, error ) << "\n";
2209 }
2210 }
2211
2212 // Hardware trigger
2213 if( m_synchroSet )
2214 {
2216
2217 std::cerr << "Turning synchro on" << std::endl;
2220 m_synchro = true;
2221 updateSwitchIfChanged( m_indiP_synchro, "toggle", pcf::IndiElement::On, INDI_IDLE );
2222 }
2223 else
2224 {
2225 std::cerr << "Turning synchro off" << std::endl;
2227 m_synchro = false;
2228 updateSwitchIfChanged( m_indiP_synchro, "toggle", pcf::IndiElement::Off, INDI_IDLE );
2229 }
2230
2231 // Start continuous acquisition
2233 {
2234 log<software_error>( { __FILE__, __LINE__, "Error setting readouts=0" } );
2236 return -1;
2237 }
2238
2239 recordCamera();
2240
2242 if( error != PicamError_None )
2243 {
2246
2247 return -1;
2248 }
2249
2250 m_dataType = _DATATYPE_UINT16; // Where does this go?
2251
2252 return 0;
2253}
2254
2255inline float picamCtrl::fps()
2256{
2257 return m_fps;
2258}
2259
2261{
2262 return 0;
2263}
2264
2266{
2267 piint camTimeOut = 1000; // 1 second keeps us responsive without busy-waiting too much
2268
2270
2272
2275
2277 {
2278 return 1; // This sends it back to framegrabber to check for reconfig, etc.
2279 }
2280
2282
2283 if( error != PicamError_None )
2284 {
2287
2288 return -1;
2289 }
2290
2291 m_available.initial_readout = available.initial_readout;
2292 m_available.readout_count = available.readout_count;
2293
2294 if( m_available.initial_readout == 0 )
2295 {
2296 return 1;
2297 }
2298
2299 // std::cerr << "readout: " << m_available.initial_readout << " " << m_available.readout_count << "\n";
2300
2301 // camera time stamp
2302 pibyte *frame = NULL;
2304
2305 frame = static_cast<pibyte *>( m_available.initial_readout );
2306 metadataOffset = (pi64s)frame + m_frameSize;
2307
2308 pi64s *tmpPtr = reinterpret_cast<pi64s *>( metadataOffset );
2309
2310 double cam_ts = (double)*tmpPtr / (double)m_tsRes;
2312
2313 // check for a frame skip
2314 if( delta_ts > 1.5 / m_FrameRateCalculation )
2315 {
2316 std::cerr << "Skipped frame(s)! (Expected a " << 1000. / m_FrameRateCalculation << " ms gap but got "
2317 << 1000 * delta_ts << " ms)\n";
2318 }
2319 // print
2320
2321 m_camera_timestamp = cam_ts; // update to latest
2322
2323 // fprintf(m_outfile, "%d %-15.8f\n", m_imageStream->md->cnt0+1, (double)*tmpPtr/(double)m_tsRes);
2324
2325 return 0;
2326}
2327
2329{
2331 dest, m_available.initial_readout, m_width, m_height, m_typeSize ) == nullptr )
2332 return -1;
2333
2334 return 0;
2335}
2336
2338{
2339 ///\todo clean this up. Just need to wait on acquisition update the first time probably.
2340
2342 if( error != PicamError_None )
2343 {
2346
2347 return -1;
2348 }
2349
2350 pibln running = true;
2351
2353
2354 while( running )
2355 {
2356 if( MagAOXAppT::m_powerState == 0 )
2357 return 0;
2358 sleep( 1 );
2359
2361
2362 if( error != PicamError_None )
2363 {
2367 return -1;
2368 }
2369
2370 piint camTimeOut = 1000;
2371
2373
2375
2377 if( error != PicamError_None )
2378 {
2382 return -1;
2383 }
2384
2385 // if(! status.running )
2386 // {
2387 // std::cerr << "Not running \n";
2388 //
2389 // std::cerr << "status.running: " << status.running << "\n";
2390 // std::cerr << "status.errors: " << status.errors << "\n";
2391 // std::cerr << "CameraFaulted: " << (int)(status.errors & PicamAcquisitionErrorsMask_CameraFaulted) <<
2392 // "\n"; std::cerr << "CannectionLost: " << (int)(status.errors &
2393 // PicamAcquisitionErrorsMask_ConnectionLost) << "\n"; std::cerr << "DataLost: " << (int)(status.errors
2394 // & PicamAcquisitionErrorsMask_DataLost) << "\n"; std::cerr << "DataNotArriving: " <<
2395 // (int)(status.errors & PicamAcquisitionErrorsMask_DataNotArriving) << "\n"; std::cerr << "None: " <<
2396 // (int)(status.errors & PicamAcquisitionErrorsMask_None) << "\n"; std::cerr << "ShutterOverheated: "
2397 // << (int)(status.errors & PicamAcquisitionErrorsMask_ShutterOverheated) << "\n"; std::cerr <<
2398 // "status.readout_rate: " << status.readout_rate << "\n";
2399 // }
2400
2402 if( error != PicamError_None )
2403 {
2407 return -1;
2408 }
2409 }
2410
2411 return 0;
2412}
2413
2418
2420{
2421 return recordCamera( true );
2422}
2423
2425{
2426
2428
2429 if( ipRecv.getName() != m_indiP_receiveSynchro.getName() )
2430 {
2431 log<software_error>( { __FILE__, __LINE__, "wrong INDI property received" } );
2432
2433 return -1;
2434 }
2435
2436 if( !ipRecv.find( "toggle" ) )
2437 {
2438 return 0;
2439 }
2440
2441 if( ipRecv["toggle"].getSwitchState() == pcf::IndiElement::On )
2442 {
2443 updateSwitchIfChanged( m_indiP_receiveSynchro, "toggle", pcf::IndiElement::On, INDI_IDLE );
2444
2445 m_synchroSet = true;
2446 }
2447 else
2448 {
2449 updateSwitchIfChanged( m_indiP_receiveSynchro, "toggle", pcf::IndiElement::Off, INDI_IDLE );
2450
2451 m_synchroSet = false;
2452 }
2453
2454 m_reconfig = true;
2455
2456 return 0;
2457}
2458
2460{
2461
2463
2464 if( ipRecv.getName() != m_indiP_receiveExptime.getName() )
2465 {
2466 log<software_error>( { __FILE__, __LINE__, "wrong INDI property received" } );
2467
2468 return -1;
2469 }
2470
2471 if( !ipRecv.find( "target" ) )
2472 {
2473 return 0;
2474 }
2475
2476 m_expTimeSet = ipRecv["target"].get<double>();
2477
2479
2480 // we don't need to strictly reconfig because setExpTime works online, but this
2481 // eludes an infinite loop of triggering the 'otherCam' in setExptime
2482 m_reconfig = 1;
2483
2484 return 0;
2485}
2486
2487} // namespace app
2488} // namespace MagAOX
2489#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.
int sendNewProperty(const pcf::IndiProperty &ipSend, const std::string &el, const T &newVal)
Send a newProperty command to another device (using the INDI Client interface)
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.
bool m_synchroSet
Target status of m_synchro.
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_fanSpeedNames
Valid fan-control option names for the INDI selection switch.
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.
std::string m_fanSpeedNameSet
Requested fan-control option name.
bool m_fanSpeedControlEnabled
Whether or not fan-speed control is published through INDI.
float m_full_y
The full ROI center y coordinate.
std::string m_readoutSpeedName
The current readout speed name.
bool checkFocusSwitchState()
Evaluate the configured focus-state switch helper as an in-focus boolean.
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.
std::string m_fanSpeedName
Current fan-control option name.
float m_full_x
The full ROI center x coordinate.
int loadConfig(mx::app::appConfigurator &config)
load the configuration system results
bool m_synchro
Status of synchronization, true is on, false is off.
std::string m_vShiftSpeedName
The current vshift speed name.
std::string m_defaultFanSpeed
The default fan speed to apply after power on.
float m_ccdTemp
The current temperature, in C.
bool m_fanSpeedValid
True once the current fan-control state is known.
std::vector< std::string > m_vShiftSpeedNames
int sendGotoFocusCommand()
Format and send the configured goto-focus switch command.
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.
std::vector< std::string > m_fanSpeedNameLabels
Optional GUI labels for the fan-control options.
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()
bool m_fanStatusSupported
True when the camera exposes readable cooling-fan status.
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())
pcf::IndiProperty m_indiP_otherCamSynchro
Property for setting otherCam synchro.
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
bool m_fanControlSupported
True when the camera exposes the DisableCoolingFan control parameter.
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
pcf::IndiProperty m_indiP_receiveSynchro
Synchro that can only be triggered from the otherCam.
static constexpr bool c_stdCamera_fpsCtrl
app::dev config to tell stdCamera not to expose FPS controls
bool m_fanForcedOn
True while the camera reports the cooling fan is forced on for protection.
static constexpr bool c_stdCamera_fanSpeed
app::dev config to tell stdCamera to expose fan-speed control
static constexpr bool c_stdCamera_cropMode
app:dev config to tell stdCamera to expose Crop Mode controls
std::string m_otherCamName
PicamHandle m_modelHandle
static constexpr bool c_stdCamera_hasShutter
app:dev config to tell stdCamera to expose shutter controls
pcf::IndiProperty m_indiP_otherCamExptime
Property for setting otherCam exptime.
static constexpr bool c_stdCamera_tempControl
app::dev config to tell stdCamera to expose temperature controls
static constexpr bool c_stdCamera_hasFocus
app:dev config to tell stdCamera to expose focus-state reporting and goto-focus control
bool checkFocus()
Reports whether the camera is currently in focus. [stdCamera interface].
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
int setSynchro()
Interface to setSynchro when the derivedT has synchronization.
pcf::IndiProperty m_indiP_readouttime
bool m_fanSpeedLogPending
True when the next successful fan apply should emit a notice even without a state change.
int gotoFocus()
Requests the configured focus preset. [stdCamera interface].
virtual int whilePowerOff()
Implementation of the while-powered-off FSM.
pcf::IndiProperty m_indiP_fxngensync_freq
Property for setting fxngensync frequency.
int setFanSpeed()
Request a cooling-fan state change through the next reconfiguration.
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
pcf::IndiProperty m_indiP_receiveExptime
Exptime that can only be triggered from the otherCam.
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)
std::string m_fxngenCh
Default fxngen channel.
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.
pcf::IndiProperty m_indiP_fxngensync_output
Proprety for turning on fxngensync.
int getFanSpeed()
Get the current cooling-fan state from the camera.
PicamAcquisitionBuffer m_acqBuff
int capExpTime(piflt &exptime)
std::string m_fxngenName
Default fxngen device name.
#define protected
#define INDI_NEWCALLBACK_DEFN(class, prop)
Define the callback for a new property request.
#define CREATE_REG_INDI_NEW_TOGGLESWITCH(prop, name)
Create and register a NEW INDI property as a standard toggle switch, using the standard callback name...
#define CREATE_REG_INDI_NEW_NUMBERD(prop, name, min, max, step, format, label, group)
Create and register a NEW INDI property as a standard number as double, using the standard callback n...
#define INDI_NEWCALLBACK_DECL(class, prop)
Declare the callback for a new property request, and declare and define the static wrapper.
#define INDI_VALIDATE_CALLBACK_PROPS(prop1, prop2)
Standard check for matching INDI properties in a callback.
#define INDI_IDLE
Definition indiUtils.hpp:27
#define INDI_OK
Definition indiUtils.hpp:28
const pcf::IndiProperty & ipRecv
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:19
static constexpr logPrioT LOG_NOTICE
A normal but significant condition.
static constexpr logPrioT LOG_WARNING
A condition has occurred which may become an error, but the process continues.
static constexpr logPrioT LOG_ERROR
An error has occured which the software will attempt to correct.
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:28
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.
@ 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.
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