16 #include "../../libMagAOX/libMagAOX.hpp"
17 #include "../../magaox_git_version.h"
28 #ifndef PL_ERR_LIBRARY_NOT_INITIALIZED
29 #define PL_ERR_LIBRARY_NOT_INITIALIZED (157)
38 const std::string & more
41 char pvmsg[ERROR_MSG_LEN];
42 pl_error_message(pec, pvmsg);
44 std::string
msg = func +
" failed: " + pvmsg;
45 if(more !=
"")
msg +=
" " + more;
51 #define log_pvcam_software_error( func, \
55 int pec = pl_error_code(); \
56 log<software_error>({__FILE__, __LINE__, 0, pec , pvcamErrMessage(func, pec, more)}); \
273 const std::string & paramMnem
345 config.add(
"camera.serialNumber",
"",
"camera.serialNumber", argType::Required,
"camera",
"serialNumber",
false,
"int",
"The identifying serial number of the camera.");
348 config.add(
"camera.circBuffMaxBytes",
"",
"camera.circBuffMaxBytes", argType::Required,
"camera",
"circBuffMaxBytes",
false,
"int",
"Maximum size in bytes of the circular buffer to allocate. Default is 0.5 GB.");
409 return log<
software_critical, -1>({__FILE__, __LINE__, errno, 0,
"Initializing frame ready semaphore"});
476 log<software_error>({__FILE__, __LINE__});
493 log<software_error>({__FILE__, __LINE__});
499 return log<software_error,0>({__FILE__,__LINE__});
504 return log<software_error,0>({__FILE__,__LINE__});
509 log<software_error>({__FILE__, __LINE__});
530 if(!pl_pvcam_uninit())
541 log<software_error>({__FILE__, __LINE__,
"error from frameGrabberT::appShutdown()"});
546 log<software_error>({__FILE__, __LINE__,
"error from shutterT::appShutdown()"});
551 log<software_error>({__FILE__, __LINE__,
"error from telemeterT::appShutdown()"});
611 ulong64 minExpTime, maxExpTime;
613 if(!pl_get_param(
m_handle, PARAM_EXPOSURE_TIME, ATTR_MIN,
static_cast<void *
>(&minExpTime)))
616 log<software_error>({__FILE__, __LINE__,
"could not set exposure time"});
620 if(!pl_get_param(
m_handle, PARAM_EXPOSURE_TIME, ATTR_MAX,
static_cast<void *
>(&maxExpTime)))
623 log<software_error>({__FILE__, __LINE__,
"could not set exposure time"});
627 std::cerr <<
"Exposure time min: " << minExpTime <<
" max: " << maxExpTime <<
"\n";
717 if(pl_cam_deregister_callback(
m_handle, PL_CALLBACK_EOF) ==
false)
722 if(pl_cam_register_callback_ex3(
m_handle, PL_CALLBACK_EOF,
reinterpret_cast<void *
>(&
st_endOfFrameCallback),
static_cast<void *
>(
this)) !=
true)
759 if(pl_set_param(
m_handle, PARAM_READOUT_PORT,
static_cast<void *
>(&
value)) ==
false)
776 m_width = (pvROI.s2 - pvROI.s1 + 1) / pvROI.sbin;
777 m_height = (pvROI.p2 - pvROI.p1 + 1) / pvROI.pbin;
786 if(pl_exp_setup_cont(
m_handle, 1, &pvROI, TIMED_MODE, exptime, &fsize, CIRC_OVERWRITE) ==
false)
793 if (pl_get_param(
m_handle, PARAM_EXPOSURE_TIME, ATTR_CURRENT, &exptime) ==
false)
801 if(pl_get_param(
m_handle, PARAM_READOUT_TIME, ATTR_CURRENT, &readouttime) ==
false)
807 if(pl_get_param(
m_handle, PARAM_PRE_TRIGGER_DELAY, ATTR_CURRENT, &predelay) ==
false)
812 long64 postdelay = 0;
813 if(pl_get_param(
m_handle, PARAM_POST_TRIGGER_DELAY, ATTR_CURRENT, &postdelay) ==
false)
835 log<software_critical>({__FILE__, __LINE__,
"failed to allocate acquisition circular buffer."});
869 else if(errno != EAGAIN)
871 log<software_critical>({__FILE__, __LINE__, errno, 0,
"sem_trywait"});
877 if(clock_gettime(CLOCK_REALTIME, &ts) < 0)
879 log<software_critical>({__FILE__, __LINE__, errno, 0,
"clock_gettime"});
883 mx::sys::timespecAddNsec(ts, 1e9);
890 else if(errno != EAGAIN && errno != ETIMEDOUT)
892 log<software_critical>({__FILE__, __LINE__, errno, 0,
"sem_timedwait"});
905 if(pl_exp_get_latest_frame(
m_handle,
reinterpret_cast<void **
>(&frame)) ==
false)
912 uint16_t * dest16 =
static_cast<uint16_t*
>(dest);
913 uint8_t * src8 =
static_cast<uint8_t*
>(frame);
929 if(pl_exp_stop_cont(
m_handle,CCS_HALT) ==
false)
953 if(!pl_pvcam_uninit())
971 if(pl_cam_get_total(&nrOfCameras) != PV_OK)
987 log<text_log>(
"Found " + std::to_string(nrOfCameras) +
" pvcam cameras.",
logPrio::LOG_INFO);
990 for(
int n=0; n < nrOfCameras; ++n)
992 char camName[CAM_NAME_LEN] {
'\0'};
995 if(pl_cam_get_name(n, camName) != PV_OK)
1001 int16_t handle = -1;
1004 if(!pl_cam_open(camName, &handle, OPEN_EXCLUSIVE))
1012 rs_bool isAvailable;
1013 if(!pl_get_param(handle, PARAM_HEAD_SER_NUM_ALPHA, ATTR_AVAIL,
static_cast<void*
>(&isAvailable)))
1017 if(!pl_cam_close(handle))
1027 char camSerial[MAX_ALPHA_SER_NUM_LEN]{
'\0' };
1029 if(!pl_get_param(handle, PARAM_HEAD_SER_NUM_ALPHA, ATTR_CURRENT,
static_cast<void*
>(camSerial)))
1033 if(!pl_cam_close(handle))
1051 if(!pl_cam_close(handle))
1071 if(pl_set_param(
m_handle, PARAM_EXP_RES_INDEX, &idx) ==
false)
1076 if (pl_get_param(
m_handle, PARAM_EXP_RES, ATTR_CURRENT, &res) ==
false)
1081 if (pl_get_param(
m_handle, PARAM_EXP_RES_INDEX, ATTR_CURRENT, &idx) ==
false)
1109 if(pl_get_param(
m_handle, PARAM_READOUT_PORT, ATTR_COUNT,
static_cast<void *
>(&nports)) ==
false)
1115 std::cerr <<
"Found " << nports <<
" ports\n";
1119 for(uns32 p=0; p < nports; ++p)
1122 if(pl_enum_str_length(
m_handle, PARAM_READOUT_PORT, p, &strLength) ==
false)
1128 char* text =
new (std::nothrow)
char[strLength];
1132 std::cerr <<
"failed to allocate string\n";
1137 if(pl_get_enum_param(
m_handle, PARAM_READOUT_PORT, p, &
value, text, strLength) ==
false)
1148 std::cerr <<
"Port: " << p <<
" name: " << text <<
" value: " <<
value <<
"\n";
1152 if(pl_set_param(
m_handle, PARAM_READOUT_PORT,
static_cast<void *
>(&
value)) ==
false)
1159 if(pl_get_param(
m_handle, PARAM_SPDTAB_INDEX, ATTR_COUNT,
static_cast<void *
>(&nspeeds)) ==
false)
1164 std::cerr <<
" Speeds: " << nspeeds <<
"\n";
1166 m_ports[p].speeds.resize(nspeeds);
1168 for(uns32 s = 0; s < nspeeds; ++s)
1170 if(pl_set_param(
m_handle, PARAM_SPDTAB_INDEX,
static_cast<void *
>(&s)) ==
false)
1177 if(pl_get_param(
m_handle, PARAM_PIX_TIME, ATTR_CURRENT,
static_cast<void *
>(&pixtime)) ==
false)
1183 m_ports[p].speeds[s].pixTime = pixtime;
1186 if(pl_get_param(
m_handle, PARAM_GAIN_INDEX, ATTR_COUNT,
static_cast<void *
>(&ngains)) ==
false)
1193 if(pl_get_param(
m_handle, PARAM_GAIN_INDEX, ATTR_MIN,
static_cast<void *
>(&ming)) ==
false)
1200 if(pl_get_param(
m_handle, PARAM_GAIN_INDEX, ATTR_MIN,
static_cast<void *
>(&maxg)) ==
false)
1206 std::cerr <<
" Speed: " << s <<
" " <<
" pixtime: " << pixtime <<
" gains: " << ngains <<
" [" << ming <<
"-" << maxg <<
"]\n";
1208 m_ports[p].speeds[s].minG = ming;
1209 m_ports[p].speeds[s].maxG = maxg;
1211 m_ports[p].speeds[s].gains.resize(ngains);
1213 for(uns32 g=0; g < ngains; ++g)
1216 int16 gg = ming + g;
1217 if(pl_set_param(
m_handle, PARAM_GAIN_INDEX,
static_cast<void *
>(&gg)) ==
false)
1224 if(pl_get_param(
m_handle, PARAM_BIT_DEPTH, ATTR_CURRENT,
static_cast<void *
>(&bitdepth)) ==
false)
1229 std::cerr <<
" Gain: " << g <<
" bitdepth: " << bitdepth <<
"\n";
1244 if(PV_OK != pl_get_param(
m_handle, paramID, ATTR_COUNT,
static_cast<void *
>(&count)))
1252 std::cerr << paramMnem <<
": count 0\n";
1255 for (uns32 n = 0; n < count; ++n)
1258 if(PV_OK != pl_enum_str_length(
m_handle, paramID, n, &strLength))
1264 char *text =
new (std::nothrow)
char[strLength];
1271 if(PV_OK != pl_get_enum_param(
m_handle, paramID, n, &
value, text, strLength))
1279 fprintf(stderr,
" item at index %u, value: %d, text: '%s'\n", n,
value, text);
1285 std::cerr <<
"dumpEnum: not CONNECTED\n";
1297 rs_bool isAvailable;
1298 if(!pl_get_param(
m_handle, PARAM_TEMP_SETPOINT, ATTR_AVAIL,
static_cast<void*
>(&isAvailable)))
1308 if(!pl_get_param(
m_handle, PARAM_TEMP_SETPOINT, ATTR_CURRENT,
static_cast<void*
>(&stemp)))
1318 if(!pl_get_param(
m_handle, PARAM_TEMP, ATTR_AVAIL,
static_cast<void*
>(&isAvailable)))
1328 if(!pl_get_param(
m_handle, PARAM_TEMP, ATTR_CURRENT,
static_cast<void*
>(&ctemp)))
1368 log<software_critical>({__FILE__, __LINE__, errno, 0,
"Error posting to frame ready semaphore"});
The base-class for MagAO-X applications.
stateCodes::stateCodeT state()
Get the current state code.
int powerState()
Returns the current power state.
int m_shutdown
Flag to signal it's time to shutdown. When not 0, the main loop exits.
int powerStateTarget()
Returns the target power state.
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.
bool powerOnWaitElapsed()
This method tests whether the power on wait time has elapsed.
unsigned long m_powerOnWait
Time in sec to wait for device to boot after power on.
std::mutex m_indiMutex
Mutex for locking INDI communications.
MagAO-X Uniblitz DSS Shutter interface.
int appStartup()
Startup function.
void loadConfig(mx::app::appConfigurator &config)
load the configuration system results
int appLogic()
application logic
int appShutdown()
applogic shutdown
void setupConfig(mx::app::appConfigurator &config)
Setup the configuration system.
int setShutterState(int sh)
Change shutter state.
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 recordFGTimings(bool force=false)
int loadConfig(mx::app::appConfigurator &config)
load the configuration system results
int updateINDI()
Update the INDI properties for this device controller.
uint8_t m_dataType
The ImageStreamIO type code.
bool m_reconfig
Flag to set if a camera reconfiguration requires a framegrabber reset.
int appLogic()
Checks the framegrabber thread.
int appStartup()
Startup function.
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.
std::vector< std::string > m_readoutSpeedNames
float m_fpsSet
The commanded fps, as set by user.
float m_default_x
Power-on ROI center x coordinate.
std::string m_tempControlStatusStr
Camera specific description of temperature control status.
std::vector< std::string > m_readoutSpeedNameLabels
int m_full_w
The full ROI width.
std::string m_defaultReadoutSpeed
The default readout speed of the camera.
float m_expTime
The current exposure time, in seconds.
int m_default_bin_x
Power-on ROI x binning.
int m_default_w
Power-on ROI width.
int recordCamera(bool force=false)
int m_default_h
Power-on ROI height.
float m_expTimeSet
The exposure time, in seconds, as set by user.
void setupConfig(mx::app::appConfigurator &config)
Setup the configuration system.
int m_full_h
The full 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.
float m_full_x
The full ROI center x coordinate.
int appLogic()
Application logic.
float m_ccdTemp
The current temperature, in C.
int updateINDI()
Update the INDI properties for this device controller.
bool m_tempControlOnTarget
Whether or not the temperature control system is on its target temperature.
void loadConfig(mx::app::appConfigurator &config)
load the configuration system results
int appStartup()
Startup function.
float m_default_y
Power-on ROI center y coordinate.
float m_fps
The current FPS.
int m_default_bin_y
Power-on ROI y binning.
std::string m_readoutSpeedNameSet
The user requested readout speed name, to be set by derived()
The MagAO-X pvcam controller.
static constexpr bool c_stdCamera_exptimeCtrl
app::dev config to tell stdCamera to expose exposure time controls
int16 m_handle
Camera handle, set when camera is opened.
static constexpr bool c_stdCamera_usesROI
app:dev config to tell stdCamera to expose ROI controls
static constexpr bool c_stdCamera_emGain
app::dev config to tell stdCamera to expose EM gain controls
static constexpr bool c_stdCamera_usesStateString
app::dev confg to tell stdCamera to expose the state string property
static constexpr bool c_stdCamera_fps
app::dev config to tell stdCamera not to expose FPS status
friend class pvcamCtrl_test
void endOfFrameCallback(FRAME_INFO *finfo)
virtual void loadConfig()
static constexpr bool c_stdCamera_tempControl
app::dev config to tell stdCamera to expose temperature controls
int recordTelem(const telem_stdcam *)
static void st_endOfFrameCallback(FRAME_INFO *finfo, void *pvcamCtrlInst)
int setShutter(int sh)
Sets the shutter state, via call to dssShutter::setShutterState(int) [stdCamera interface].
static constexpr bool c_stdCamera_usesModes
app:dev config to tell stdCamera not to expose mode controls
std::vector< port > m_ports
virtual int appShutdown()
Shutdown the app.
uint32_t m_circBuffMaxBytes
Max size in bytes of the circular buffer to allocate. Default is 0.5 GB.
int checkNextROI()
Check the next ROI.
std::vector< speed > speeds
static constexpr bool c_stdCamera_hasShutter
app:dev config to tell stdCamera to expose shutter controls
int acquireAndCheckValid()
static constexpr bool c_stdCamera_fpsCtrl
app::dev config to tell stdCamera not to expose FPS controls
int configureAcquisition()
dev::stdCamera< pvcamCtrl > stdCameraT
dev::frameGrabber< pvcamCtrl > frameGrabberT
static constexpr bool c_stdCamera_temp
app::dev config to tell stdCamera to expose temperature
pvcamCtrl()
Default c'tor.
virtual int appLogic()
Implementation of the FSM for pvcamCtrl.
sem_t m_frSemaphore
Semaphore used to signal that a frame is ready.
int loadConfigImpl(mx::app::appConfigurator &_config)
Implementation of loadConfig logic, separated for testing.
~pvcamCtrl() noexcept
D'tor, declared and defined for noexcept.
std::string m_camName
Camera name, filled in as part of opening the camera.
virtual int appStartup()
Startup function.
int loadImageIntoStream(void *dest)
dev::dssShutter< pvcamCtrl > shutterT
static constexpr bool c_stdCamera_readoutSpeed
app::dev config to tell stdCamera to expose readout speed controls
void dumpEnum(uns32 paramID, const std::string ¶mMnem)
static constexpr bool c_stdCamera_synchro
app::dev config to tell stdCamera to not expose synchro mode controls
dev::telemeter< pvcamCtrl > telemeterT
std::vector< gain > gains
static constexpr bool c_stdCamera_cropMode
app:dev config to tell stdCamera to expose Crop Mode controls
float m_tempTol
Tolerance in degrees C to declare the temperature control locked.
std::string m_serialNumber
The camera serial number.
virtual void setupConfig()
static constexpr bool c_stdCamera_vShiftSpeed
app:dev config to tell stdCamera to expose vertical shift speed control
static constexpr bool c_frameGrabber_flippable
app:dev config to tell framegrabber this camera can be flipped
@ OPERATING
The device is operating, other than homing.
@ NODEVICE
No device exists for the application to control.
@ FAILURE
The application has failed, should be used when m_shutdown is set for an error.
@ ERROR
The application has encountered an error, from which it is recovering (with or without intervention)
@ READY
The device is ready for operation, but is not operating.
@ CONNECTED
The application has connected to the device or service.
@ NOTCONNECTED
The application is not connected to the device or service.
@ POWERON
The device power is on.
GeneratorWrapper< T > value(T &&value)
std::unique_lock< std::mutex > lock(m_indiMutex)
constexpr static logPrioT LOG_CRITICAL
The process can not continue and will shut down (fatal)
constexpr static logPrioT LOG_INFO
Informational. The info log level is the lowest level recorded during normal operations.
#define PL_ERR_LIBRARY_NOT_INITIALIZED
std::string pvcamErrMessage(const std::string &func, int pec, const std::string &more)
Format an error message using pvcam facilities.
#define log_pvcam_software_error(func, more)
Helper for logging an error from pvcam.
A device base class which saves telemetry.
int appShutdown()
Perform telemeter application shutdown.
int loadConfig(appConfigurator &config)
Load the device section from an application configurator.
int appLogic()
Perform telemeter application logic.
int setupConfig(appConfigurator &config)
Setup an application configurator for the device section.
int appStartup()
Starts the telemetry log thread.
int checkRecordTimes(const telT &tel, telTs... tels)
Check the time of the last record for each telemetry type and make an entry if needed.
Software CRITICAL log entry.
Log entry recording framegrabber timings.
Log entry recording stdcam stage specific status.