Commit c84b84b7 authored by Alejandro Homs Puron's avatar Alejandro Homs Puron Committed by Operator for ID00
Browse files

Add support for dynamic TimeRanges: readout time and max. frame rate (period)

parent fb0a2719
......@@ -120,6 +120,38 @@ public:
typedef std::set<int> SortedIntList;
typedef std::vector<FrameType> FrameArray;
struct TimeRanges {
TimeRanges() :
min_exp_time(-1.),
max_exp_time(-1.),
min_lat_time(-1.),
max_lat_time(-1.),
min_frame_period(-1.),
max_frame_period(-1.)
{}
double min_exp_time;
double max_exp_time;
double min_lat_time;
double max_lat_time;
double min_frame_period;
double max_frame_period;
};
class TimeRangesChangedCallback {
DEB_CLASS_NAMESPC(DebModCamera, "TimeRangesChangedCallback",
"SlsDetector::Camera");
public:
TimeRangesChangedCallback();
virtual ~TimeRangesChangedCallback();
protected:
virtual void timeRangesChanged(TimeRanges time_ranges) = 0;
private:
friend class Camera;
Camera *m_cam;
};
static bool isValidFrame(FrameType frame)
{ return (frame != FrameType(-1)); }
......@@ -184,6 +216,8 @@ public:
FloatList& factor_list,
FloatList& min_val_list) = 0;
virtual void getTimeRanges(TimeRanges& time_ranges) = 0;
protected:
void updateCameraModel();
......@@ -381,6 +415,9 @@ public:
void startAcq();
void stopAcq();
void registerTimeRangesChangedCallback(TimeRangesChangedCallback& cb);
void unregisterTimeRangesChangedCallback(TimeRangesChangedCallback& cb);
private:
typedef RegEx::SingleMatchType SingleMatch;
typedef RegEx::FullMatchType FullMatch;
......@@ -476,8 +513,9 @@ private:
{ return AutoMutex(m_cond.mutex()); }
void updateImageSize();
void updateTimeRanges();
int64_t NSec(double x)
static int64_t NSec(double x)
{ return int64_t(x * 1e9); }
State getEffectiveState();
......@@ -544,6 +582,7 @@ private:
IntList m_bad_frame_list;
Stats m_lock_stats;
Stats m_port_cb_stats;
TimeRangesChangedCallback *m_time_ranges_cb;
};
std::ostream& operator <<(std::ostream& os, Camera::State state);
......
......@@ -78,6 +78,8 @@ class Eiger : public Camera::Model
FloatList& factor_list,
FloatList& min_val_list);
virtual void getTimeRanges(Camera::TimeRanges& time_ranges);
// the returned object must be deleted by the caller
Correction *createCorrectionTask();
......@@ -305,6 +307,9 @@ class Eiger : public Camera::Model
int getNbEigerModules()
{ return m_nb_det_modules / 2; }
static double KiloHzPeriod(double f)
{ return 1e6 / (f * 1e3); }
void getRecvFrameDim(FrameDim& frame_dim, bool raw, bool geom);
CorrBase *createPixelDepth4Corr();
......
......@@ -120,7 +120,22 @@ class SyncCtrlObj : public HwSyncCtrlObj
static TrigModeMap Lima2CamTrigModeMap;
private:
class TimeRangesChangedCallback :
public Camera::TimeRangesChangedCallback
{
DEB_CLASS_NAMESPC(DebModCamera, "TimeRangesChangedCallback",
"SlsDetector::SynCtrlObj");
public:
TimeRangesChangedCallback(SyncCtrlObj *sync);
protected:
virtual void timeRangesChanged(Camera::TimeRanges time_ranges);
private:
friend class SyncCtrlObj;
SyncCtrlObj *m_sync;
};
Camera& m_cam;
TimeRangesChangedCallback m_time_ranges_cb;
};
......
......@@ -50,6 +50,16 @@ public:
PixelDepth32 = 32,
};
struct TimeRanges {
TimeRanges();
double min_exp_time;
double max_exp_time;
double min_lat_time;
double max_lat_time;
double min_frame_period;
double max_frame_period;
};
static bool isValidFrame(unsigned long frame);
static unsigned long latestFrame(unsigned long a, unsigned long b);
......@@ -79,6 +89,9 @@ public:
std::vector<double>& factor_list /Out/,
std::vector<double>& min_val_list /Out/) = 0;
virtual void getTimeRanges(SlsDetector::Camera::TimeRanges&
time_ranges /Out/) = 0;
protected:
void updateCameraModel();
......
......@@ -60,6 +60,9 @@ class Eiger : public SlsDetector::Camera::Model
std::vector<double>& factor_list /Out/,
std::vector<double>& min_val_list /Out/);
virtual void getTimeRanges(SlsDetector::Camera::TimeRanges&
time_ranges /Out/);
protected:
virtual void updateImageSize();
......
......@@ -33,6 +33,19 @@ using namespace std;
using namespace lima;
using namespace lima::SlsDetector;
Camera::TimeRangesChangedCallback::TimeRangesChangedCallback()
: m_cam(NULL)
{
DEB_CONSTRUCTOR();
}
Camera::TimeRangesChangedCallback::~TimeRangesChangedCallback()
{
DEB_DESTRUCTOR();
if (m_cam)
m_cam->unregisterTimeRangesChangedCallback(*this);
}
Camera::FrameType Camera::getLatestFrame(const FrameArray& l)
{
......@@ -551,7 +564,8 @@ Camera::Camera(string config_fname)
m_state(Idle),
m_new_frame_timeout(1),
m_abort_sleep_time(1),
m_tol_lost_packets(true)
m_tol_lost_packets(true),
m_time_ranges_cb(NULL)
{
DEB_CONSTRUCTOR();
......@@ -579,6 +593,9 @@ Camera::~Camera()
{
DEB_DESTRUCTOR();
if (m_time_ranges_cb)
unregisterTimeRangesChangedCallback(*m_time_ranges_cb);
if (!m_model)
return;
......@@ -758,6 +775,15 @@ void Camera::setFramePeriod(double frame_period)
{
DEB_MEMBER_FUNCT();
DEB_PARAM() << DEB_VAR1(frame_period);
if (m_model) {
TimeRanges time_ranges;
m_model->getTimeRanges(time_ranges);
if ((frame_period < time_ranges.min_frame_period) ||
(frame_period > time_ranges.max_frame_period))
THROW_HW_ERROR(InvalidValue) << DEB_VAR1(frame_period);
}
waitState(Idle);
m_det->setExposurePeriod(NSec(frame_period));
m_frame_period = frame_period;
......@@ -780,6 +806,21 @@ void Camera::updateImageSize()
maxImageSizeChanged(frame_dim.getSize(), frame_dim.getImageType());
}
void Camera::updateTimeRanges()
{
DEB_MEMBER_FUNCT();
TimeRanges time_ranges;
m_model->getTimeRanges(time_ranges);
DEB_TRACE() << "TimeRangesChanged: "
<< DEB_VAR6(time_ranges.min_exp_time,
time_ranges.max_exp_time,
time_ranges.min_lat_time,
time_ranges.max_lat_time,
time_ranges.min_frame_period,
time_ranges.max_frame_period);
m_time_ranges_cb->timeRangesChanged(time_ranges);
}
void Camera::setPixelDepth(PixelDepth pixel_depth)
{
DEB_MEMBER_FUNCT();
......@@ -803,8 +844,10 @@ void Camera::setPixelDepth(PixelDepth pixel_depth)
m_det->setDynamicRange(pixel_depth);
m_pixel_depth = pixel_depth;
if (m_model)
if (m_model) {
updateImageSize();
updateTimeRanges();
}
}
void Camera::getPixelDepth(PixelDepth& pixel_depth)
......@@ -1212,6 +1255,8 @@ void Camera::setClockDiv(ClockDiv clock_div)
DEB_MEMBER_FUNCT();
DEB_PARAM() << DEB_VAR1(clock_div);
m_det->setSpeed(slsDetectorDefs::CLOCK_DIVIDER, clock_div);
if (m_model)
updateTimeRanges();
}
void Camera::getClockDiv(ClockDiv& clock_div)
......@@ -1242,6 +1287,8 @@ void Camera::setReadoutFlags(ReadoutFlags flags)
DetFlags det_flags = static_cast<DetFlags>(*it);
m_det->setReadOutFlags(det_flags);
}
updateTimeRanges();
}
void Camera::getReadoutFlags(ReadoutFlags& flags)
......@@ -1343,3 +1390,26 @@ void Camera::getBadFrameList(IntList& bad_frame_list)
}
DEB_RETURN() << DEB_VAR1(PrettyIntList(bad_frame_list));
}
void Camera::registerTimeRangesChangedCallback(TimeRangesChangedCallback& cb)
{
DEB_MEMBER_FUNCT();
if (m_time_ranges_cb)
THROW_HW_ERROR(InvalidValue) << "a cb is already registered";
cb.m_cam = this;
m_time_ranges_cb = &cb;
}
void Camera::unregisterTimeRangesChangedCallback(TimeRangesChangedCallback& cb)
{
DEB_MEMBER_FUNCT();
if (&cb != m_time_ranges_cb)
THROW_HW_ERROR(InvalidValue) << "the cb is not registered";
m_time_ranges_cb = NULL;
cb.m_cam = NULL;
}
......@@ -421,6 +421,72 @@ void Eiger::getADCInfo(NameList& name_list, IntList& idx_list,
}
}
void Eiger::getTimeRanges(Camera::TimeRanges& time_ranges)
{
DEB_MEMBER_FUNCT();
Camera* cam = getCamera();
ReadoutFlags readout_flags;
cam->getReadoutFlags(readout_flags);
Camera::ClockDiv clock_div;
cam->getClockDiv(clock_div);
Camera::PixelDepth pixel_depth;
cam->getPixelDepth(pixel_depth);
bool parallel = (readout_flags & Parallel);
double min_exp = 10;
double min_lat = 500;
double min_period = 500;
double max_freq_p = 0;
double readout_p = 0;
double readout_np = 0;
if (pixel_depth == Camera::PixelDepth4) {
min_lat = 10;
min_period = KiloHzPeriod(22);
} else if (pixel_depth == Camera::PixelDepth8) {
min_lat = 10;
min_period = KiloHzPeriod(11);
} else if (pixel_depth == Camera::PixelDepth16) {
if (clock_div == FullSpeed) {
max_freq_p = 6;
readout_p = 2.75;
readout_np = 126;
} else if (clock_div == HalfSpeed) {
max_freq_p = 2.9;
readout_p = 5.36;
readout_np = 252;
} else if (clock_div == QuarterSpeed) {
max_freq_p = 1.5;
readout_p = 10.6;
readout_np = 504;
}
} else if (clock_div == QuarterSpeed) {
max_freq_p = 2;
readout_p = 10.6;
readout_np = 504;
}
if (max_freq_p * readout_p * readout_np != 0) {
min_lat = parallel ? readout_p : readout_np;
min_period = min_lat + KiloHzPeriod(max_freq_p) - readout_p;
}
time_ranges.min_exp_time = min_exp * 1e-6;
time_ranges.max_exp_time = 1e3;
time_ranges.min_lat_time = min_lat * 1e-6;
time_ranges.max_lat_time = 1e3;
time_ranges.min_frame_period = min_period * 1e-6;
time_ranges.max_frame_period = 1e3;
DEB_RETURN() << DEB_VAR2(time_ranges.min_exp_time,
time_ranges.max_exp_time);
DEB_RETURN() << DEB_VAR2(time_ranges.min_lat_time,
time_ranges.max_lat_time);
DEB_RETURN() << DEB_VAR2(time_ranges.min_frame_period,
time_ranges.max_frame_period);
}
void Eiger::updateImageSize()
{
DEB_MEMBER_FUNCT();
......
......@@ -168,6 +168,28 @@ void DetInfoCtrlObj::unregisterMaxImageSizeCallback(
* \brief SyncCtrlObj constructor
*******************************************************************/
SyncCtrlObj::
TimeRangesChangedCallback::TimeRangesChangedCallback(SyncCtrlObj *sync)
: m_sync(sync)
{
DEB_CONSTRUCTOR();
}
void SyncCtrlObj::
TimeRangesChangedCallback::timeRangesChanged(Camera::TimeRanges time_ranges)
{
DEB_MEMBER_FUNCT();
if (!m_sync)
return;
ValidRangesType valid_ranges(time_ranges.min_exp_time,
time_ranges.max_exp_time,
time_ranges.min_lat_time,
time_ranges.max_lat_time);
m_sync->validRangesChanged(valid_ranges);
}
typedef pair<TrigMode, Defs::TrigMode> TrigPair;
static const TrigPair Lima2CamTrigModeCList[] = {
TrigPair(IntTrig, Defs::Auto),
......@@ -179,14 +201,16 @@ SyncCtrlObj::TrigModeMap
SyncCtrlObj::Lima2CamTrigModeMap(C_LIST_ITERS(Lima2CamTrigModeCList));
SyncCtrlObj::SyncCtrlObj(Camera& cam)
: m_cam(cam)
: m_cam(cam), m_time_ranges_cb(this)
{
DEB_CONSTRUCTOR();
m_cam.registerTimeRangesChangedCallback(m_time_ranges_cb);
}
SyncCtrlObj::~SyncCtrlObj()
{
DEB_DESTRUCTOR();
m_time_ranges_cb.m_sync = NULL;
}
bool SyncCtrlObj::checkTrigMode(TrigMode trig_mode)
......@@ -277,11 +301,17 @@ void SyncCtrlObj::getValidRanges(ValidRangesType& valid_ranges)
{
DEB_MEMBER_FUNCT();
valid_ranges.min_exp_time = 100e-6;
valid_ranges.max_exp_time = 1e3;
valid_ranges.min_lat_time = 100e-6;
valid_ranges.max_lat_time = 1e3;
Camera::Model *model = m_cam.getModel();
if (model) {
Camera::TimeRanges time_ranges;
model->getTimeRanges(time_ranges);
valid_ranges.min_exp_time = time_ranges.min_exp_time;
valid_ranges.max_exp_time = time_ranges.max_exp_time;
valid_ranges.min_lat_time = time_ranges.min_lat_time;
valid_ranges.max_lat_time = time_ranges.max_lat_time;
} else {
valid_ranges = ValidRangesType();
}
DEB_RETURN() << DEB_VAR2(valid_ranges.min_exp_time,
valid_ranges.max_exp_time);
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment