SlsDetectorCamera.cpp 33.4 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
//###########################################################################
// This file is part of LImA, a Library for Image Acquisition
//
// Copyright (C) : 2009-2011
// European Synchrotron Radiation Facility
// BP 220, Grenoble 38043
// FRANCE
//
// This is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 3 of the License, or
// (at your option) any later version.
//
// This software is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, see <http://www.gnu.org/licenses/>.
//###########################################################################

23
#include "SlsDetectorCamera.h"
24

25
#include <limits.h>
26
#include <algorithm>
27
#include <numeric>
28
#include <cmath>
29
30
#include <iostream>
#include <fstream>
31

32
33
34
35
using namespace std;
using namespace lima;
using namespace lima::SlsDetector;

36

37
Camera::AppInputData::AppInputData(string cfg_fname) 
38
	: config_file_name(cfg_fname)
39
{
40
	DEB_CONSTRUCTOR();
41
42
43
	parseConfigFile();
}

44
void Camera::AppInputData::parseConfigFile()
45
{
46
47
	DEB_MEMBER_FUNCT();

48
	ifstream config_file(config_file_name);
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
	while (config_file) {
		string s;
		config_file >> s;
		RegEx re;
		FullMatch full_match;
		MatchList match_list;
		MatchListIt lit, lend;

		re = "hostname";
		if (re.match(s, full_match)) {
			string host_name;
			config_file >> host_name;
			RegEx re("([A-Za-z0-9]+)\\+?");
			re.multiSearch(host_name, match_list);
			lend = match_list.end();
			for (lit = match_list.begin(); lit != lend; ++lit) {
				const FullMatch& full_match = *lit;
				const SingleMatch& single_match = full_match[1];
				host_name_list.push_back(single_match);
			}
69
			DEB_TRACE() << DEB_VAR1(host_name_list);
70
71
72
			continue;
		}

73
		re = "(([0-9]+):)?rx_tcpport";
74
		if (re.match(s, full_match)) {
75
76
77
78
79
80
81
82
			int id = 0;
			if (full_match[2].found()) {
				istringstream is(full_match[2]);
				is >> id;
				if (id < 0)
					THROW_HW_FATAL(InvalidValue) << 
						"Invalid detector id: " << id;
			}
83
84
85
86
87
88
89
90
			int rx_tcpport;
			config_file >> rx_tcpport;
			recv_port_map[id] = rx_tcpport;
			continue;
		}
	}
}

91
92
93
Camera::AcqThread::ExceptionCleanUp::ExceptionCleanUp(AcqThread& thread,
						      AutoMutex& l)
	: Thread::ExceptionCleanUp(thread), m_lock(l)
94
95
96
97
98
99
100
101
{
	DEB_CONSTRUCTOR();
}

Camera::AcqThread::ExceptionCleanUp::~ExceptionCleanUp()
{
	DEB_DESTRUCTOR();
	AcqThread *thread = static_cast<AcqThread *>(&m_thread);
102
	thread->cleanUp(m_lock);
103
104
}

105
Camera::AcqThread::AcqThread(Camera *cam)
106
	: m_cam(cam), m_cond(m_cam->m_cond), m_state(m_cam->m_state)
107
108
{
	DEB_CONSTRUCTOR();
109
110
}

111
void Camera::AcqThread::start(AutoMutex& l)
112
113
114
{
	DEB_MEMBER_FUNCT();

115
116
117
	if ((&l.mutex() != &m_cond.mutex()) || !l.locked())
		THROW_HW_ERROR(Error) << "Invalid AutoMutex";

118
	m_state = Starting;
119
	Thread::start();
120
121

	struct sched_param param;
122
	param.sched_priority = sched_get_priority_min(SCHED_RR);
123
124
	int ret = pthread_setschedparam(m_thread, SCHED_RR, &param);
	if (ret != 0)
125
		DEB_ERROR() << "Could not set AcqThread real-time priority!!";
126

127
	while (m_state == Starting)
128
129
130
		m_cond.wait();
}

131
void Camera::AcqThread::stop(AutoMutex& l, bool wait)
132
133
{
	DEB_MEMBER_FUNCT();
134
135
136
	if ((&l.mutex() != &m_cond.mutex()) || !l.locked())
		THROW_HW_ERROR(Error) << "Invalid AutoMutex";

137
138
	m_state = StopReq;
	m_cond.broadcast();
139
	while (wait && (m_state != Stopped) && (m_state != Idle))
140
141
142
143
144
145
146
147
		m_cond.wait();
}

void Camera::AcqThread::threadFunction()
{
	DEB_MEMBER_FUNCT();

	AutoMutex l = m_cam->lock();
148

149
150
151
152
	// cleanup is executed with lock, once state goes to Stopped
	// thread will be deleted in getEffectiveState without releasing lock
	ExceptionCleanUp cleanup(*this, l);

153
	GlobalCPUAffinityMgr& affinity_mgr = m_cam->m_global_cpu_affinity_mgr;
154
155
	{
		AutoMutexUnlock u(l);
156
157
		affinity_mgr.startAcq();
		startAcq();
158
159
	}
	m_state = Running;
160
	DEB_TRACE() << DEB_VAR1(m_state);
161
162
	m_cond.broadcast();

163
	SeqFilter seq_filter;
164
	bool had_frames = false;
165
	bool cont_acq = true;
166
	bool acq_end = false;
167
	do {
168
169
170
		while ((m_state != StopReq) && m_frame_queue.empty()) {
			if (!m_cond.wait(m_cam->m_new_frame_timeout)) {
				AutoMutexUnlock u(l);
171
172
173
174
175
176
177
				try {
					m_cam->checkLostPackets();
				} catch (Exception& e) {
					string name = ("Camera::AcqThread: "
						       "checkLostPackets");
					m_cam->reportException(e, name);
				}
178
179
			}
		}
180
		if (!m_frame_queue.empty()) {
181
			FrameType frame = m_frame_queue.front();
182
			m_frame_queue.pop();
183
184
185
186
187
188
			DEB_TRACE() << DEB_VAR1(frame);
			seq_filter.addVal(frame);
			SeqFilter::Range frames = seq_filter.getSeqRange();
			if (frames.nb > 0) {
				int f = frames.first;
				do {
189
190
					m_cam->m_buffer.waitLimaFrame(f, l);
					AutoMutexUnlock u(l);
191
					DEB_TRACE() << DEB_VAR1(f);
192
193
194
					Status status = newFrameReady(f);
					cont_acq = status.first;
					acq_end = status.second;
195
					had_frames = true;
196
				} while ((++f != frames.end()) && cont_acq);
197
198
			}
		}
199
	} while ((m_state != StopReq) && cont_acq);
200
	AcqState prev_state = m_state;
201

202
203
204
205
206
	if (acq_end && m_cam->m_skip_frame_freq) {
		AutoMutexUnlock u(l);
		m_cam->waitLastSkippedFrame();
	}
		
207
	m_state = Stopping;
208
	DEB_TRACE() << DEB_VAR2(prev_state, m_state);
209
210
	{
		AutoMutexUnlock u(l);
211
		stopAcq();
212

213
214
215
216
217
		IntList bfl;
		m_cam->getSortedBadFrameList(bfl);
		DEB_ALWAYS() << "bad_frames=" << bfl.size() << ": "
			     << PrettyIntList(bfl);

218
219
220
		Stats stats;
		m_cam->getStats(stats);
		DEB_ALWAYS() << DEB_VAR1(stats);
221

222
		FrameMap& m = m_cam->m_frame_map;
223
224
225
226
		if (m.getNbItems() > 1) {
			XYStat::LinRegress delay_stat = m.calcDelayStat();
			DEB_ALWAYS() << DEB_VAR1(delay_stat);
		}
227

228
		if (had_frames) {
229
230
			affinity_mgr.recvFinished();
			affinity_mgr.waitLimaFinished();
231
		} else {
232
			affinity_mgr.cleanUp();
233
		}
234
	}
235

236
	m_state = Stopped;
237
	DEB_TRACE() << DEB_VAR1(m_state);
238
239
240
	m_cond.broadcast();
}

241
242
243
244
245
246
247
248
249
void Camera::AcqThread::queueFinishedFrame(FrameType frame)
{
	DEB_MEMBER_FUNCT();
	DEB_PARAM() << DEB_VAR1(frame);
	AutoMutex l = m_cam->lock();
	m_frame_queue.push(frame);
	m_cond.broadcast();
}

250
void Camera::AcqThread::cleanUp(AutoMutex& l)
251
252
253
254
255
256
{
	DEB_MEMBER_FUNCT();

	if ((m_state == Stopped) || (m_state == Idle))
		return;

257
	AcqState prev_state = m_state;
258
259
260
261
262
263
264
265
	if ((m_state == Running) || (m_state == StopReq)) {
		m_state = Stopping;
		AutoMutexUnlock u(l);
		stopAcq();
	}

	{
		AutoMutexUnlock u(l);
266
267
268
		ostringstream err_msg;
		err_msg << "AcqThread: exception thrown: "
			<< "m_state=" << prev_state;
269
270
		Event::Code err_code = Event::CamFault;
		Event *event = new Event(Hardware, Event::Error, Event::Camera, 
271
					 err_code, err_msg.str());
272
273
274
275
276
277
278
279
280
281
282
		DEB_EVENT(*event) << DEB_VAR1(*event);
		m_cam->reportEvent(event);
	}

	m_state = Stopped;
	m_cond.broadcast();
}

void Camera::AcqThread::startAcq()
{
	DEB_MEMBER_FUNCT();
283
	sls::Detector *det = m_cam->m_det;
284
	DEB_TRACE() << "calling startReceiver";
285
	det->startReceiver();
286
287
	DEB_TRACE() << "calling Model::startAcq";
	m_cam->m_model->startAcq();
288
289
	DEB_TRACE() << "calling startDetector";
	det->startDetector();
290
291
292
293
294
}

void Camera::AcqThread::stopAcq()
{
	DEB_MEMBER_FUNCT();
295
	sls::Detector *det = m_cam->m_det;
296
297
298
299
	DetStatus det_status = m_cam->getDetStatus();
	bool xfer_active = m_cam->m_model->isXferActive();
	DEB_ALWAYS() << DEB_VAR2(det_status, xfer_active);
	if ((det_status == Defs::Running) || xfer_active) {
300
301
		DEB_TRACE() << "calling stopDetector";
		det->stopDetector();
302
		Timestamp t0 = Timestamp::now();
303
		while (m_cam->m_model->isAcqActive())
304
305
306
307
308
309
			Sleep(m_cam->m_abort_sleep_time);
		double milli_sec = (Timestamp::now() - t0) * 1e3;
		DEB_TRACE() << "Abort -> Idle: " << DEB_VAR1(milli_sec);
	}
	DEB_TRACE() << "calling stopReceiver";
	det->stopReceiver();
310
311
	DEB_TRACE() << "calling Model::stopAcq";
	m_cam->m_model->stopAcq();
312
313
}

314
Camera::AcqThread::Status Camera::AcqThread::newFrameReady(FrameType frame)
315
316
317
318
{
	DEB_MEMBER_FUNCT();
	HwFrameInfoType frame_info;
	frame_info.acq_frame_nb = frame;
319
	StdBufferCbMgr *cb_mgr = m_cam->m_buffer.getBufferCbMgr(LimaBuffer);
320
	bool cont_acq = cb_mgr->newFrameReady(frame_info);
321
322
323
	bool acq_end = (frame == m_cam->m_lima_nb_frames - 1);
	cont_acq &= !acq_end;
	return Status(cont_acq, acq_end);
324
325
}

326
327
328
Camera::Camera(string config_fname, int det_id) 
	: m_det_id(det_id),
	  m_model(NULL),
329
	  m_frame_map(this),
Alejandro Homs Puron's avatar
Alejandro Homs Puron committed
330
331
332
	  m_lima_nb_frames(1),
	  m_det_nb_frames(1),
	  m_skip_frame_freq(0),
333
	  m_last_skipped_frame_timeout(0.5),
334
	  m_lat_time(0),
335
	  m_buffer(this),
336
	  m_pixel_depth(PixelDepth16), 
337
	  m_image_type(Bpp16), 
338
	  m_raw_mode(false),
339
	  m_state(Idle),
340
	  m_new_frame_timeout(0.5),
341
	  m_abort_sleep_time(0.1),
342
	  m_tol_lost_packets(true),
343
	  m_time_ranges_cb(NULL),
344
	  m_global_cpu_affinity_mgr(this)
345
{
346
347
	DEB_CONSTRUCTOR();

348
	CPUAffinity::getNbSystemCPUs();
349

350
351
	m_input_data = new AppInputData(config_fname);

352
353
354
	bool remove_shmem = false;
	if (remove_shmem)
		removeSharedMem();
355
356
	createReceivers();

357
358
	DEB_TRACE() << "Creating the sls::Detector object";
	m_det = new sls::Detector(m_det_id);
359
	DEB_TRACE() << "Reading configuration file";
360
	const char *fname = m_input_data->config_file_name.c_str();
361
	EXC_CHECK(m_det->loadConfig(fname));
362

363
364
365
	EXC_CHECK(m_det->setRxSilentMode(1));
	EXC_CHECK(m_det->setRxFrameDiscardPolicy(
				  slsDetectorDefs::DISCARD_PARTIAL_FRAMES));
366
	setReceiverFifoDepth(1);
367

368
369
370
	sls::Result<int> dr_res;
	EXC_CHECK(dr_res = m_det->getDynamicRange());
	m_pixel_depth = PixelDepth(dr_res.squash(-1));
371

372
	setTrigMode(Defs::Auto);
373
374
375
	setNbFrames(1);
	setExpTime(0.99);
	setFramePeriod(1.0);
376
377
}

378
Camera::~Camera()
379
{
380
	DEB_DESTRUCTOR();
381

382
383
384
	if (m_time_ranges_cb)
		unregisterTimeRangesChangedCallback(*m_time_ranges_cb);

385
386
387
	if (!m_model)
		return;

388
	stopAcq();
389
390
391
	m_model->m_cam = NULL;
}

392
Type Camera::getType()
393
394
{
	DEB_MEMBER_FUNCT();
395
396
397
398
399
400
	slsDetectorDefs::detectorType sls_type;
	const char *err_msg = "Detector types are different";
	EXC_CHECK(sls_type = m_det->getDetectorType().tsquash(err_msg));
	Type det_type;
	switch (sls_type) {
	case slsDetectorDefs::GENERIC:
401
		det_type = GenericDet;
402
403
		break;
	case slsDetectorDefs::EIGER:
404
		det_type = EigerDet;
405
406
		break;
	case slsDetectorDefs::JUNGFRAU:
407
		det_type = JungfrauDet;
408
409
410
		break;
	default:
		det_type = UnknownDet;
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
	}
	DEB_RETURN() << DEB_VAR1(det_type);
	return det_type;
}

void Camera::setModel(Model *model)
{
	DEB_MEMBER_FUNCT();
	DEB_PARAM() << DEB_VAR2(model, m_model);
	
	if (model && (model->getType() != getType()))
		THROW_HW_ERROR(InvalidValue) << DEB_VAR2(getType(), 
							 model->getType());
	if (m_model == model)
		return;
	if (m_model)
		m_model->m_cam = NULL;
	m_model = model;
429
430
431
	if (!m_model)
		return;

432
433
434
435
436
437
	int nb_udp_ifaces;
	m_model->getNbUDPInterfaces(nb_udp_ifaces);
	DEB_ALWAYS() << "Using " << m_model->getName()
		     << " with " << getNbDetModules() << "x" << nb_udp_ifaces
		     << " UDP interfaces";

438
439
440
	int nb_items = m_model->getNbFrameMapItems();
	m_frame_map.setNbItems(nb_items);
	m_model->updateFrameMapItems(&m_frame_map);
441

442
	setPixelDepth(m_pixel_depth);
443
444
}

445
446
447
void Camera::removeSharedMem()
{
	DEB_MEMBER_FUNCT();
448
449
	ostringstream cmd;
	cmd << "sls_detector_get " << m_det_id << "-free";
450
451
452
453
	string cmd_str = cmd.str();
	int ret = system(cmd_str.c_str());
	if (ret != 0)
		THROW_HW_ERROR(Error) << "Error executing " << DEB_VAR1(cmd_str);
454
455
}

456
void Camera::createReceivers()
457
{
458
459
	DEB_MEMBER_FUNCT();

460
	DEB_TRACE() << "Receivers:";
461
462
463
464
465
	const RecvPortMap& recv_port_map = m_input_data->recv_port_map;
	RecvPortMap::const_iterator mit, mend = recv_port_map.end();
	int idx = 0;
	for (mit = recv_port_map.begin(); mit != mend; ++mit, ++idx) {
		unsigned int id = mit->first;
466
467
468
		if (id >= m_input_data->host_name_list.size())
			THROW_HW_FATAL(InvalidValue) << DEB_VAR1(id) 
						     << "too high";
469
470
		const string& host_name = m_input_data->host_name_list[id];
		int rx_port = mit->second;
471
		DEB_TRACE() << "  " << host_name << ": " << DEB_VAR1(rx_port);
472

473
		AutoPtr<Receiver> recv_obj = new Receiver(this, idx, rx_port);
474
475
476
477
		m_recv_list.push_back(recv_obj);
	}
}

478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
string Camera::execCmd(const string& s, bool put, int idx)
{
	DEB_MEMBER_FUNCT();
	DEB_PARAM() << "s=\"" << s << "\", " << DEB_VAR2(put, idx);

	string prog_name = string("sls_detector_") + (put ? "put" : "get");
	ostringstream os;
	os << prog_name << " ";
	if (idx >= 0)
		os << idx << ':';
	os << s;
	SystemCmdPipe cmd(os.str(), prog_name, false);
	cmd.setPipe(SystemCmdPipe::StdOut, SystemCmdPipe::DoPipe);
	cmd.setPipe(SystemCmdPipe::StdErr, SystemCmdPipe::DoPipe);
	StringList out, err;
	int ret = cmd.execute(out, err);
	DEB_TRACE() << DEB_VAR3(ret, out, err);
	string err_str = accumulate(err.begin(), err.end(), string());
	if ((ret != 0) || (err_str.find("ERROR") != string::npos))
		THROW_HW_ERROR(Error) << prog_name << "(" << ret << "): "
				      << err_str;
	else if (!err_str.empty())
		cerr << err_str;
	string out_str = accumulate(out.begin(), out.end(), string());
	DEB_RETURN() << DEB_VAR1(out_str);
	return out_str;
}

506
void Camera::putCmd(const string& s, int idx)
507
{
508
	DEB_MEMBER_FUNCT();
509
	execCmd(s, true, idx);
510
511
}

512
string Camera::getCmd(const string& s, int idx)
513
{
514
	DEB_MEMBER_FUNCT();
515
516
517
518
	string r = execCmd(s, false, idx);
	string::size_type p = s.find(':');
	string raw_s = s.substr((p == string::npos) ? 0 : (p + 1));
	DEB_TRACE() << DEB_VAR2(s, raw_s);
519
520
521
522
523
524
525
526
	bool multi_line = ((s == "list") || (s == "versions"));
	if (!multi_line) {
		if (r.find(raw_s + ' ') != 0)
			THROW_HW_ERROR(Error) << "Invalid response: " << r;
		string::size_type e = raw_s.size() + 1;
		p = r.find('\n', e);
		r = r.substr(e, (p == string::npos) ? p : (p - e));
	}
527
	DEB_RETURN() << DEB_VAR1(r);
528
	return r;
529
530
}

531
532
533
534
void Camera::setTrigMode(TrigMode trig_mode)
{
	DEB_MEMBER_FUNCT();
	DEB_PARAM() << DEB_VAR1(trig_mode);
535
	waitAcqState(Idle);
536
537
538
	TrigMode cam_trig_mode = trig_mode;
	if (trig_mode == Defs::SoftTriggerExposure)
		cam_trig_mode = Defs::TriggerExposure;
539
540
541
	typedef slsDetectorDefs::timingMode TimingMode;
	TimingMode mode = static_cast<TimingMode>(cam_trig_mode);
	EXC_CHECK(m_det->setTimingMode(mode));
542
	m_trig_mode = trig_mode;
Alejandro Homs Puron's avatar
Alejandro Homs Puron committed
543
	setNbFrames(m_lima_nb_frames);
544
545
546
547
548
549
550
551
552
}

void Camera::getTrigMode(TrigMode& trig_mode)
{
	DEB_MEMBER_FUNCT();
	trig_mode = m_trig_mode;
	DEB_RETURN() << DEB_VAR1(trig_mode);
}

553
void Camera::setNbFrames(FrameType nb_frames)
554
{
555
	DEB_MEMBER_FUNCT();
556
	DEB_PARAM() << DEB_VAR1(nb_frames);
557
558
559
560
561
562
563

	// Lima frame numbers are (signed) int
	const FrameType MaxFrames = INT_MAX;
	if (nb_frames >= MaxFrames)
		THROW_HW_ERROR(InvalidValue) << "too high " 
					     <<	DEB_VAR2(nb_frames, MaxFrames);

564
	waitAcqState(Idle);
Alejandro Homs Puron's avatar
Alejandro Homs Puron committed
565
566
567
	FrameType det_nb_frames = nb_frames;
	if (m_skip_frame_freq)
		det_nb_frames += nb_frames / m_skip_frame_freq;
568
	bool trig_exp = (m_trig_mode == Defs::TriggerExposure);
Alejandro Homs Puron's avatar
Alejandro Homs Puron committed
569
570
	int cam_frames = trig_exp ? 1 : det_nb_frames;
	int cam_triggers = trig_exp ? det_nb_frames : 1;
571
572
	EXC_CHECK(m_det->setNumberOfFrames(cam_frames));
	EXC_CHECK(m_det->setNumberOfTriggers(cam_triggers));
Alejandro Homs Puron's avatar
Alejandro Homs Puron committed
573
574
	m_lima_nb_frames = nb_frames;
	m_det_nb_frames = det_nb_frames;
575
}
576

577
void Camera::getNbFrames(FrameType& nb_frames)
578
579
{
	DEB_MEMBER_FUNCT();
Alejandro Homs Puron's avatar
Alejandro Homs Puron committed
580
	nb_frames = m_lima_nb_frames;
581
	DEB_RETURN() << DEB_VAR1(nb_frames);
582
}
583

Alejandro Homs Puron's avatar
Alejandro Homs Puron committed
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
void Camera::setSkipFrameFreq(FrameType skip_frame_freq)
{
	DEB_MEMBER_FUNCT();
	DEB_PARAM() << DEB_VAR1(skip_frame_freq);
	m_skip_frame_freq = skip_frame_freq;
	setNbFrames(m_lima_nb_frames);
}

void Camera::getSkipFrameFreq(FrameType& skip_frame_freq)
{
	DEB_MEMBER_FUNCT();
	skip_frame_freq = m_skip_frame_freq;
	DEB_RETURN() << DEB_VAR1(skip_frame_freq);
}

599
600
601
void Camera::setExpTime(double exp_time)
{
	DEB_MEMBER_FUNCT();
602
	DEB_PARAM() << DEB_VAR1(exp_time);
603
	waitAcqState(Idle);
604
	EXC_CHECK(m_det->setExptime(NSec(exp_time)));
605
606
	m_exp_time = exp_time;
}
607

608
609
610
611
void Camera::getExpTime(double& exp_time)
{ 
	DEB_MEMBER_FUNCT();
	exp_time = m_exp_time;
612
	DEB_RETURN() << DEB_VAR1(exp_time);
613
}
614

615
616
617
618
619
620
621
622
623
624
625
626
627
628
void Camera::setLatTime(double lat_time)
{
	DEB_MEMBER_FUNCT();
	DEB_PARAM() << DEB_VAR1(lat_time);
	m_lat_time = lat_time;
}

void Camera::getLatTime(double& lat_time)
{ 
	DEB_MEMBER_FUNCT();
	lat_time = m_lat_time;
	DEB_RETURN() << DEB_VAR1(lat_time);
}

629
630
631
void Camera::setFramePeriod(double frame_period)
{
	DEB_MEMBER_FUNCT();
632
	DEB_PARAM() << DEB_VAR1(frame_period);
633
634
635

	if (m_model) {
		TimeRanges time_ranges;
636
		double e = 1e-6;
637
		m_model->getTimeRanges(time_ranges);
638
639
640
641
642
643
		if ((frame_period < time_ranges.min_frame_period - e) ||
		    (frame_period > time_ranges.max_frame_period + e))
			THROW_HW_ERROR(InvalidValue) 
				<< DEB_VAR3(frame_period,
					    time_ranges.min_frame_period, 
					    time_ranges.max_frame_period);
644
645
	}

646
	waitAcqState(Idle);
647
	EXC_CHECK(m_det->setPeriod(NSec(frame_period)));
648
649
	m_frame_period = frame_period;
}
650

651
652
653
654
void Camera::getFramePeriod(double& frame_period)
{
	DEB_MEMBER_FUNCT();
	frame_period = m_frame_period;
655
	DEB_RETURN() << DEB_VAR1(frame_period);
656
}
657

658
659
660
void Camera::updateImageSize()
{
	DEB_MEMBER_FUNCT();
661
662
663
	RecvList::iterator it, end = m_recv_list.end();
	for (it = m_recv_list.begin(); it != end; ++it)
		(*it)->setGapPixelsEnable(!m_raw_mode);
664
665
666
667
668
669
670
	m_model->updateImageSize();
	FrameDim frame_dim;
	getFrameDim(frame_dim, m_raw_mode);
	DEB_TRACE() << "MaxImageSizeChanged: " << DEB_VAR1(frame_dim);
	maxImageSizeChanged(frame_dim.getSize(), frame_dim.getImageType());
}

671
672
673
674
675
void Camera::updateTimeRanges()
{
	DEB_MEMBER_FUNCT();
	TimeRanges time_ranges;
	m_model->getTimeRanges(time_ranges);
676
677
	m_exp_time = max(m_exp_time, time_ranges.min_exp_time);
	m_frame_period = max(m_frame_period, time_ranges.min_frame_period);
678
679
680
681
682
683
684
	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);
685
686
	if (m_time_ranges_cb)
		m_time_ranges_cb->timeRangesChanged(time_ranges);
687
688
}

689
690
691
692
693
694
void Camera::updateCPUAffinity(bool recv_restarted)
{
	DEB_MEMBER_FUNCT();

	// receiver threads are restarted after DR change
	if (recv_restarted)
695
		m_global_cpu_affinity_mgr.updateRecvRestart();
696

697
698
699
	// apply the corresponding GlobalCPUAffinity
	GlobalCPUAffinity global_affinity = m_cpu_affinity_map[m_pixel_depth];
	m_global_cpu_affinity_mgr.applyAndSet(global_affinity);
700
701
}

702
void Camera::setRecvCPUAffinity(const RecvCPUAffinityList& recv_affinity_list)
703
704
{
	DEB_MEMBER_FUNCT();
705
	unsigned int nb_aff = recv_affinity_list.size();
706
	DEB_PARAM() << DEB_VAR1(nb_aff);
707
	RecvCPUAffinityList::const_iterator ait = recv_affinity_list.begin();
708
	RecvList::iterator rit = m_recv_list.begin();
709
710
	for (unsigned int i = 0; i < nb_aff; ++i, ++ait, ++rit)
		(*rit)->setCPUAffinity(*ait);
711
712
}

713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
void Camera::setModuleActive(int mod_idx, bool  active)
{
	DEB_MEMBER_FUNCT();
	DEB_PARAM() << DEB_VAR2(mod_idx, active);

	if ((mod_idx < 0) || (mod_idx >= getNbDetModules()))
		THROW_HW_ERROR(InvalidValue) << DEB_VAR1(mod_idx);

	Positions pos = Idx2Pos(mod_idx);
	EXC_CHECK(m_det->setActive(active, pos));
}

void Camera::getModuleActive(int mod_idx, bool& active)
{
	DEB_MEMBER_FUNCT();
	DEB_PARAM() << DEB_VAR1(mod_idx);

	if ((mod_idx < 0) || (mod_idx >= getNbDetModules()))
		THROW_HW_ERROR(InvalidValue) << DEB_VAR1(mod_idx);

	Positions pos = Idx2Pos(mod_idx);
	EXC_CHECK(active = m_det->getActive(pos).front());
	DEB_RETURN() << DEB_VAR1(active);
}

738
739
740
741
742
void Camera::setPixelDepth(PixelDepth pixel_depth)
{
	DEB_MEMBER_FUNCT();
	DEB_PARAM() << DEB_VAR1(pixel_depth);

743
	if (getAcqState() != Idle)
744
745
		THROW_HW_FATAL(Error) << "Camera is not idle";

746
	waitAcqState(Idle);
747
748
749
750
751
752
753
754
755
756
757
	switch (pixel_depth) {
	case PixelDepth4:
	case PixelDepth8:
		m_image_type = Bpp8;	break;
	case PixelDepth16:
		m_image_type = Bpp16;	break;
	case PixelDepth32:
		m_image_type = Bpp32;	break;
	default:
		THROW_HW_ERROR(InvalidValue) << DEB_VAR1(pixel_depth);
	}
758
	EXC_CHECK(m_det->setDynamicRange(pixel_depth));
759
760
	m_pixel_depth = pixel_depth;

761
	if (m_model) {
762
		updateImageSize();
763
		updateTimeRanges();
764
		updateCPUAffinity(true);
765
	}
766
767
768
769
770
771
772
773
774
}

void Camera::getPixelDepth(PixelDepth& pixel_depth)
{
	DEB_MEMBER_FUNCT();
	pixel_depth = m_pixel_depth; 
	DEB_RETURN() << DEB_VAR1(pixel_depth);
}

775
void Camera::setRawMode(bool raw_mode)
776
777
{
	DEB_MEMBER_FUNCT();
778
	DEB_PARAM() << DEB_VAR1(raw_mode);
779

780
	if (raw_mode == m_raw_mode)
781
		return;
782
	m_raw_mode = raw_mode;
783

784
	updateImageSize();
785
786
}

787
void Camera::getRawMode(bool& raw_mode)
788
789
{
	DEB_MEMBER_FUNCT();
790
791
	raw_mode = m_raw_mode; 
	DEB_RETURN() << DEB_VAR1(raw_mode);
792
793
}

794
AcqState Camera::getAcqState()
795
796
797
{
	DEB_MEMBER_FUNCT();
	AutoMutex l = lock();
798
	AcqState state = getEffectiveState();
799
800
	DEB_RETURN() << DEB_VAR1(state);
	return state;
801
802
}

803
AcqState Camera::getEffectiveState()
804
805
806
807
808
809
810
811
{
	if (m_state == Stopped) {
		m_acq_thread = NULL;
		m_state = Idle;
	}
	return m_state;
}

812
void Camera::waitAcqState(AcqState state)
813
814
{
	DEB_MEMBER_FUNCT();
815
	DEB_PARAM() << DEB_VAR1(state);
816
817
818
819
820
	AutoMutex l = lock();
	while (getEffectiveState() != state)
		m_cond.wait();
}

821
AcqState Camera::waitNotAcqState(AcqState state)
822
823
{
	DEB_MEMBER_FUNCT();
824
	DEB_PARAM() << DEB_VAR1(state);
825
826
827
	AutoMutex l = lock();
	while (getEffectiveState() == state)
		m_cond.wait();
828
829
830
	state = getEffectiveState();
	DEB_RETURN() << DEB_VAR1(state);
	return state;
831
832
}

833
834
835
836
void Camera::prepareAcq()
{
	DEB_MEMBER_FUNCT();

837
	StdBufferCbMgr *cb_mgr = m_buffer.getBufferCbMgr(AcqBuffer);
838
	if (!cb_mgr)
839
		THROW_HW_ERROR(Error) << "No Acq BufferCbMgr defined";
840
	else if (!m_buffer.getBufferCbMgr(LimaBuffer))
841
		THROW_HW_ERROR(Error) << "No Lima BufferCbMgr defined";
842
	if (!m_model)
843
		THROW_HW_ERROR(Error) << "No Model defined";
844

845
846
	m_buffer.prepareAcq();

847
848
	waitNotAcqState(Stopping);
	if (getAcqState() != Idle)
849
850
		THROW_HW_ERROR(Error) << "Camera is not idle";

Alejandro Homs Puron's avatar
Alejandro Homs Puron committed
851
	bool need_period = !m_lima_nb_frames || (m_lima_nb_frames > 1);
852
853
854
	need_period &= ((m_trig_mode == Defs::Auto) || 
			(m_trig_mode == Defs::BurstTrigger));
	if (need_period && (m_lat_time > 0))
855
856
		setFramePeriod(m_exp_time + m_lat_time);

857
	int nb_buffers;
858
	cb_mgr->getNbBuffers(nb_buffers);
859

860
861
	{
		AutoMutex l = lock();
862
		m_frame_map.setBufferSize(nb_buffers);
863
		m_frame_map.clear();
864
		m_prev_ifa.clear();
865
866
867
		RecvList::iterator it, end = m_recv_list.end();
		for (it = m_recv_list.begin(); it != end; ++it)
			(*it)->prepareAcq();
868
869
870

		m_missing_last_skipped_frame.clear();
		if (m_skip_frame_freq)
871
			for (int i = 0; i < getNbRecvs(); ++i)
872
				m_missing_last_skipped_frame.insert(i);
873
874

		m_next_ready_ts = Timestamp();
875
	}
876

877
	m_model->prepareAcq();
878
	m_global_cpu_affinity_mgr.prepareAcq();
879

880
	resetFramesCaught();
881
882
	EXC_CHECK(m_det->setFileWrite(0));
	EXC_CHECK(m_det->setNextFrameNumber(1));
883
884
}

885
void Camera::startAcq()
886
{
887
	DEB_MEMBER_FUNCT();
888

889
890
891
	AutoMutex l = lock();
	if (m_acq_thread)
		THROW_HW_ERROR(Error) << "Must call prepareAcq first";
892

893
	StdBufferCbMgr *cb_mgr = m_buffer.getBufferCbMgr(LimaBuffer);
894
	cb_mgr->setStartTimestamp(Timestamp::now());
895
896

	m_acq_thread = new AcqThread(this);
897
	m_acq_thread->start(l);
898
899
}

900
void Camera::stopAcq()
901
{
902
903
	DEB_MEMBER_FUNCT();

904
	m_global_cpu_affinity_mgr.stopAcq();
905

906
907
	AutoMutex l = lock();
	if (getEffectiveState() != Running)
908
909
		return;

910
	m_acq_thread->stop(l, true);
911
912
	if (getEffectiveState() != Idle)
		THROW_HW_ERROR(Error) << "Camera not Idle";
913
914
}

915
916
917
918
919
920
921
922
923
924
925
void Camera::triggerFrame()
{
	DEB_MEMBER_FUNCT();

	if (m_trig_mode != Defs::SoftTriggerExposure)
		THROW_HW_ERROR(InvalidValue) << "Wrong trigger mode";

	AutoMutex l = lock();
	if (getEffectiveState() != Running)
		THROW_HW_ERROR(Error) << "Camera not Running";

926
	EXC_CHECK(m_det->sendSoftwareTrigger());
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
	m_next_ready_ts = Timestamp::now();
	m_next_ready_ts += m_exp_time;
}

Camera::DetStatus Camera::getDetTrigStatus()
{
	DEB_MEMBER_FUNCT();

	if (m_trig_mode != Defs::SoftTriggerExposure)
		THROW_HW_ERROR(InvalidValue) << "Wrong trigger mode";

	Timestamp t = Timestamp::now();

	AutoMutex l = lock();
	bool ready = !m_next_ready_ts.isSet() || (m_next_ready_ts < t);
	DetStatus trig_status = ready ? Defs::Waiting : Defs::Running;
	DEB_RETURN() << DEB_VAR1(trig_status);
	return trig_status;
945
946
}

947
948
949
950
bool Camera::checkLostPackets()
{
	DEB_MEMBER_FUNCT();

951
952
953
	FrameArray ifa = m_frame_map.getItemFrameArray();
	if (ifa != m_prev_ifa) {
		m_prev_ifa = ifa;
954
955
956
		return false;
	}

957
958
	FrameType last_frame = getLatestFrame(ifa);
	if (getOldestFrame(ifa) == last_frame) {
959
960
961
		DEB_RETURN() << DEB_VAR1(false);
		return false;
	}
962

963
	if (!m_tol_lost_packets) {
964
		ostringstream err_msg;
965
		err_msg << "checkLostPackets: frame_map=" << m_frame_map;
966
967
968
969
970
971
972
973
974
		Event::Code err_code = Event::CamOverrun;
		Event *event = new Event(Hardware, Event::Error, Event::Camera, 
					 err_code, err_msg.str());
		DEB_EVENT(*event) << DEB_VAR1(*event);
		reportEvent(event);
		DEB_RETURN() << DEB_VAR1(true);
		return true;
	}

975
976
	int nb_items = m_model->getNbFrameMapItems();
	IntList first_bad(nb_items);
977
	if (DEB_CHECK_ANY(DebTypeWarning)) {
978
979
980
981
		for (int i = 0; i < nb_items; ++i) {
			FrameMap::Item *item = m_frame_map.getItem(i);
			first_bad[i] = item->getNbBadFrames();
		}
982
	}
983
984
	for (int i = 0; i < nb_items; ++i) {
		if (ifa[i] != last_frame) {
985
			char *bptr = m_buffer.getAcqFrameBufferPtr(last_frame);