FrelonCamera.cpp 22.7 KB
Newer Older
1
#include "FrelonCamera.h"
2
#include "RegEx.h"
3
#include "MiscUtils.h"
4
#include <sstream>
5

6
using namespace lima;
7
8
9
using namespace lima::Frelon;
using namespace std;

10
11
const double Camera::BinChangeTime  = 2.0;
const double Camera::MaxReadoutTime = 0.7;
12

ahoms's avatar
ahoms committed
13

14
Camera::Camera(Espia::SerialLine& espia_ser_line)
ahoms's avatar
ahoms committed
15
	: m_ser_line(espia_ser_line), m_mis_cb_act(false)
16
{
17
18
	DEB_CONSTRUCTOR();

19
20
21
22
23
24
25
26
27
28
29
30
31
32
	sync();
}

Camera::~Camera()
{
	DEB_DESTRUCTOR();

}

void Camera::sync()
{
	DEB_MEMBER_FUNCT();

	DEB_TRACE() << "Synchronizing with the camera";
33
34
35
36
37

	string ver;
	getVersion(ver);
	int ser_nb;
	getSerialNb(ser_nb);
38

ahoms's avatar
ahoms committed
39
40
41
42
	double exp_time;
	getExpTime(exp_time);
	m_trig_mode = (exp_time == 0) ? ExtGate : IntTrig;

43
	readRegister(NbFrames, m_nb_frames);
44

45
	m_roi_offset = 0;
46
47
}

48
49
50
51
52
SerialLine& Camera::getSerialLine()
{
	return m_ser_line;
}

53
54
Espia::Dev& Camera::getEspiaDev()
{
55
	Espia::SerialLine& ser_line = m_ser_line.getEspiaSerialLine();
56
57
58
59
	Espia::Dev& dev = ser_line.getDev();
	return dev;
}

60
61
void Camera::sendCmd(Cmd cmd)
{
62
63
	DEB_MEMBER_FUNCT();
	const string& cmd_str = CmdStrMap[cmd];
64
	DEB_PARAM() << DEB_VAR2(cmd, cmd_str);
65
66
67
68
69
	if (cmd_str.empty()) {
		DEB_ERROR() << "Invalid command cmd=" << cmd;
		throw LIMA_HW_EXC(InvalidValue, "Invalid command");
	}

70
	string resp;
71
	m_ser_line.sendFmtCmd(cmd_str, resp);
72
73
74
75
}

void Camera::writeRegister(Reg reg, int val)
{
76
	DEB_MEMBER_FUNCT();
77
	m_ser_line.writeRegister(reg, val);
78
79
80
81
}

void Camera::readRegister(Reg reg, int& val)
{
82
	DEB_MEMBER_FUNCT();
83
	m_ser_line.readRegister(reg, val);
84
85
86
87
}

void Camera::hardReset()
{
88
	DEB_MEMBER_FUNCT();
89
90
91
	Espia::Dev& dev = getEspiaDev();
	dev.resetLink();

92
	DEB_TRACE() << "Reseting the camera";
93
	sendCmd(Reset);
94
95

	sync();
96
97
98
99
}

void Camera::getVersion(string& ver)
{
100
	DEB_MEMBER_FUNCT();
101
102
	string cmd = RegStrMap[Version] + "?";
	m_ser_line.sendFmtCmd(cmd, ver);
103
	DEB_RETURN() << DEB_VAR1(ver);
104
}
ahoms's avatar
ahoms committed
105
106
107

void Camera::getComplexSerialNb(int& complex_ser_nb)
{
108
	DEB_MEMBER_FUNCT();
ahoms's avatar
ahoms committed
109
	readRegister(CompSerNb, complex_ser_nb);
110
	DEB_RETURN() << DEB_VAR1(DEB_HEX(complex_ser_nb));
ahoms's avatar
ahoms committed
111
112
113
114
}

void Camera::getSerialNbParam(SerNbParam param, int& val)
{
115
116
	DEB_MEMBER_FUNCT();
	DEB_PARAM() << DEB_VAR1(DEB_HEX(param));
ahoms's avatar
ahoms committed
117
118
119
120
121
	int complex_ser_nb;
	getComplexSerialNb(complex_ser_nb);
	val = complex_ser_nb & int(param);
}

122
123
void Camera::getSerialNb(int& ser_nb)
{
124
	DEB_MEMBER_FUNCT();
125
	getSerialNbParam(SerNb, ser_nb);
126
	DEB_RETURN() << DEB_VAR1(ser_nb);
127
128
129
}

void Camera::isFrelon2k16(bool& is_frelon_2k16)
ahoms's avatar
ahoms committed
130
{
131
	DEB_MEMBER_FUNCT();
ahoms's avatar
ahoms committed
132
133
	int frelon_2k16;
	getSerialNbParam(F2k16, frelon_2k16);
134
	is_frelon_2k16 = bool(frelon_2k16);
135
	DEB_RETURN() << DEB_VAR1(is_frelon_2k16);
136
137
138
139
}

void Camera::isFrelon4M(bool& is_frelon_4m)
{
140
	DEB_MEMBER_FUNCT();
141
142
143
	int f4m;
	getSerialNbParam(F4M, f4m);
	is_frelon_4m = bool(f4m);
144
	DEB_RETURN() << DEB_VAR1(is_frelon_4m);
145
146
147
148
}

void Camera::hasTaper(bool& has_taper)
{
149
	DEB_MEMBER_FUNCT();
150
151
152
	int taper;
	getSerialNbParam(Taper, taper);
	has_taper = bool(taper);
153
	DEB_RETURN() << DEB_VAR1(has_taper);
ahoms's avatar
ahoms committed
154
155
156
157
}

void Camera::setChanMode(int chan_mode)
{
158
159
	DEB_MEMBER_FUNCT();
	DEB_PARAM() << DEB_VAR1(chan_mode);
ahoms's avatar
ahoms committed
160
161
162
163
164
	writeRegister(ChanMode, chan_mode);
}

void Camera::getChanMode(int& chan_mode)
{
165
	DEB_MEMBER_FUNCT();
ahoms's avatar
ahoms committed
166
	readRegister(ChanMode, chan_mode);
167
	DEB_RETURN() << DEB_VAR1(chan_mode);
ahoms's avatar
ahoms committed
168
169
170
171
}

void Camera::getBaseChanMode(FrameTransferMode ftm, int& base_chan_mode)
{
172
	DEB_MEMBER_FUNCT();
ahoms's avatar
ahoms committed
173
	base_chan_mode = FTMChanRangeMap[ftm].first;
174
	DEB_RETURN() << DEB_VAR1(base_chan_mode);
ahoms's avatar
ahoms committed
175
176
177
178
179
}

void Camera::getInputChanMode(FrameTransferMode ftm, InputChan input_chan,
			      int& chan_mode)
{
180
181
182
	DEB_MEMBER_FUNCT();
	DEB_PARAM() << DEB_VAR2(ftm, DEB_HEX(input_chan));

ahoms's avatar
ahoms committed
183
184
185
186
187
188
189
	getBaseChanMode(ftm, chan_mode);
	const InputChanList& chan_list = FTMInputChanListMap[ftm];
	InputChanList::const_iterator it;
	it = find(chan_list.begin(), chan_list.end(), input_chan);
	if (it == chan_list.end())
		throw LIMA_HW_EXC(InvalidValue, "Invalid input channel");
	chan_mode += it - chan_list.begin();
190
191

	DEB_RETURN() << DEB_VAR1(chan_mode);
ahoms's avatar
ahoms committed
192
193
194
195
}

void Camera::setInputChan(InputChan input_chan)
{
196
197
198
	DEB_MEMBER_FUNCT();
	DEB_PARAM() << DEB_VAR1(DEB_HEX(input_chan));

ahoms's avatar
ahoms committed
199
200
201
202
203
204
205
206
207
	FrameTransferMode ftm;
	getFrameTransferMode(ftm);
	int chan_mode;
	getInputChanMode(ftm, input_chan, chan_mode);
	setChanMode(chan_mode);
}

void Camera::getInputChan(InputChan& input_chan)
{
208
209
	DEB_MEMBER_FUNCT();

ahoms's avatar
ahoms committed
210
211
212
213
214
215
	FrameTransferMode ftm;
	getFrameTransferMode(ftm);
	int chan_mode, base_chan_mode;
	getChanMode(chan_mode);
	getBaseChanMode(ftm, base_chan_mode);
	input_chan = FTMInputChanListMap[ftm][chan_mode - base_chan_mode];
216
217

	DEB_RETURN() << DEB_VAR1(DEB_HEX(input_chan));
ahoms's avatar
ahoms committed
218
219
220
221
}

void Camera::setFrameTransferMode(FrameTransferMode ftm)
{
222
223
224
	DEB_MEMBER_FUNCT();
	DEB_PARAM() << DEB_VAR1(ftm);
	
ahoms's avatar
ahoms committed
225
226
227
228
229
230
231
	FrameTransferMode prev_ftm;
	getFrameTransferMode(prev_ftm);
	if (ftm == prev_ftm) {
		DEB_TRACE() << "Nothing to do";
		return;
	}

ahoms's avatar
ahoms committed
232
233
234
235
236
	InputChan input_chan;
	getInputChan(input_chan);
	int chan_mode;
	getInputChanMode(ftm, input_chan, chan_mode);
	setChanMode(chan_mode);
ahoms's avatar
ahoms committed
237
238
239
240
241
242
243
244

	if (!m_mis_cb_act) 
		return;

	FrameDim frame_dim;
	getFrameDim(frame_dim);
	DEB_TRACE() << "MaxImageSizeChanged: " << DEB_VAR1(frame_dim);
	maxImageSizeChanged(frame_dim.getSize(), frame_dim.getImageType());
ahoms's avatar
ahoms committed
245
246
247
248
}

void Camera::getFrameTransferMode(FrameTransferMode& ftm)
{
249
250
	DEB_MEMBER_FUNCT();

ahoms's avatar
ahoms committed
251
252
253
254
255
256
257
	int chan_mode;
	getChanMode(chan_mode);

	FTMChanRangeMapType::const_iterator it, end = FTMChanRangeMap.end();
	for (it = FTMChanRangeMap.begin(); it != end; ++it) {
		ftm = it->first;
		const ChanRange& range = it->second;
258
259
		if ((chan_mode >= range.first) && (chan_mode < range.second)) {
			DEB_RETURN() << DEB_VAR1(ftm);
ahoms's avatar
ahoms committed
260
			return;
261
		}
ahoms's avatar
ahoms committed
262
263
264
265
266
267
268
	}

	throw LIMA_HW_EXC(Error, "Invalid chan mode");
}

void Camera::getFrameDim(FrameDim& frame_dim)
{
269
270
	DEB_MEMBER_FUNCT();

ahoms's avatar
ahoms committed
271
272
273
274
275
	frame_dim = MaxFrameDim;
	FrameTransferMode ftm;
	getFrameTransferMode(ftm);
	if (ftm == FTM)
		frame_dim /= Point(1, 2);
276
277

	DEB_RETURN() << DEB_VAR1(frame_dim);
ahoms's avatar
ahoms committed
278
279
280
281
}

void Camera::setFlipMode(int flip_mode)
{
282
283
	DEB_MEMBER_FUNCT();
	DEB_PARAM() << DEB_VAR1(flip_mode);
284
	writeRegister(FlipMode, flip_mode);
ahoms's avatar
ahoms committed
285
286
287
288
}

void Camera::getFlipMode(int& flip_mode)
{
289
	DEB_MEMBER_FUNCT();
290
	readRegister(FlipMode, flip_mode);
291
	DEB_RETURN() << DEB_VAR1(flip_mode);
ahoms's avatar
ahoms committed
292
293
}

294
void Camera::checkFlip(Flip& flip)
ahoms's avatar
ahoms committed
295
{
296
297
	DEB_MEMBER_FUNCT();
	DEB_PARAM() << DEB_VAR1(flip);
298
299
300
301
302
303
304
305
306
	DEB_TRACE() << "All standard flip modes are supported";
	DEB_RETURN() << DEB_VAR1(flip);
}

void Camera::setFlip(const Flip& flip)
{
	DEB_MEMBER_FUNCT();
	DEB_PARAM() << DEB_VAR1(flip);
	int flip_mode = (flip.x << 1) | (flip.y << 0);
ahoms's avatar
ahoms committed
307
308
309
	setFlipMode(flip_mode);
}

310
void Camera::getFlip(Flip& flip)
ahoms's avatar
ahoms committed
311
{
312
313
	DEB_MEMBER_FUNCT();

ahoms's avatar
ahoms committed
314
315
316
317
	int flip_mode;
	getFlipMode(flip_mode);
	flip.x = (flip_mode >> 1) & 1;
	flip.y = (flip_mode >> 0) & 1;
318
319

	DEB_RETURN() << DEB_VAR1(flip);
ahoms's avatar
ahoms committed
320
321
}

322
323
void Camera::checkBin(Bin& bin)
{
324
325
326
	DEB_MEMBER_FUNCT();
	DEB_PARAM() << DEB_VAR1(bin);
	
327
328
329
	int bin_x = min(bin.getX(), int(MaxBinX));
	int bin_y = min(bin.getY(), int(MaxBinY));
	bin = Bin(bin_x, bin_y);
330
331

	DEB_RETURN() << DEB_VAR1(bin);
332
333
}

ahoms's avatar
ahoms committed
334
335
void Camera::setBin(const Bin& bin)
{
336
337
338
339
340
	DEB_MEMBER_FUNCT();
	DEB_PARAM() << DEB_VAR1(bin);
	
	if ((bin.getX() > 8) || (bin.getY() > 1024)) {
		DEB_ERROR() << "Invalid bin: " << bin << ". Must be <= 8x1024";
341
		throw LIMA_HW_EXC(InvalidValue, "Bin must be <= 8x1024");
342
	}
343

ahoms's avatar
ahoms committed
344
345
	Bin curr_bin;
	getBin(curr_bin);
346
347
	DEB_TRACE() << DEB_VAR1(curr_bin);
	if (bin == curr_bin) 
ahoms's avatar
ahoms committed
348
349
		return;

350
	DEB_TRACE() << "Reseting Roi";
351
352
353
	Roi roi;
	setRoi(roi);

ahoms's avatar
ahoms committed
354
355
	writeRegister(BinHorz, bin.getX());
	writeRegister(BinVert, bin.getY());
356
357
358

	DEB_TRACE() << "Sleeping " << DEB_VAR1(BinChangeTime);
	Sleep(BinChangeTime);
ahoms's avatar
ahoms committed
359
360
361
362
}

void Camera::getBin(Bin& bin)
{
363
	DEB_MEMBER_FUNCT();
ahoms's avatar
ahoms committed
364
365
366
367
	int bin_x, bin_y;
	readRegister(BinHorz, bin_x);
	readRegister(BinVert, bin_y);
	bin = Bin(bin_x, bin_y);
368
	DEB_RETURN() << DEB_VAR1(bin);
ahoms's avatar
ahoms committed
369
370
371
372
}

void Camera::setRoiMode(RoiMode roi_mode)
{
373
374
375
	DEB_MEMBER_FUNCT();
	DEB_PARAM() << DEB_VAR1(roi_mode);

ahoms's avatar
ahoms committed
376
377
378
	bool roi_hw   = (roi_mode == Slow) || (roi_mode == Fast);
	bool roi_fast = (roi_mode == Fast) || (roi_mode == Kinetic);
	bool roi_kin  = (roi_mode == Kinetic);
379
	DEB_TRACE() << DEB_VAR3(roi_hw, roi_fast, roi_kin);
ahoms's avatar
ahoms committed
380
381
382
383
384
385
386
387

	writeRegister(RoiEnable,  roi_hw);
	writeRegister(RoiFast,    roi_fast);
	writeRegister(RoiKinetic, roi_kin);
}

void Camera::getRoiMode(RoiMode& roi_mode)
{
388
389
	DEB_MEMBER_FUNCT();

ahoms's avatar
ahoms committed
390
391
392
393
	int roi_hw, roi_fast, roi_kin;
	readRegister(RoiEnable,  roi_hw);
	readRegister(RoiFast,    roi_fast);
	readRegister(RoiKinetic, roi_kin);
394
	DEB_TRACE() << DEB_VAR3(roi_hw, roi_fast, roi_kin);
ahoms's avatar
ahoms committed
395
396
397
398
399
400
401
402
403

	if (roi_fast && roi_kin)
		roi_mode = Kinetic;
	else if (roi_fast && roi_hw)
		roi_mode = Fast;
	else if (roi_hw)
		roi_mode = Slow;
	else
		roi_mode = None;
404
405

	DEB_RETURN() << DEB_VAR1(roi_mode);
ahoms's avatar
ahoms committed
406
407
}

408
Flip Camera::getMirror()
ahoms's avatar
ahoms committed
409
{
410
	DEB_MEMBER_FUNCT();
411

412
413
	InputChan curr;
	getInputChan(curr);
414
	Flip mirror;
415
416
	mirror.x = isChanActive(curr, Chan12) || isChanActive(curr, Chan34);
	mirror.y = isChanActive(curr, Chan13) || isChanActive(curr, Chan24);
417

418
	DEB_RETURN() << DEB_VAR1(mirror);
419
	return mirror;
ahoms's avatar
ahoms committed
420
421
}

422
Point Camera::getNbChan()
ahoms's avatar
ahoms committed
423
{
424
	DEB_MEMBER_FUNCT();
425
	Point nb_chan = Point(getMirror()) + 1;
426
	DEB_RETURN() << DEB_VAR1(nb_chan);
427
	return nb_chan;
ahoms's avatar
ahoms committed
428
429
}

430
Size Camera::getCcdSize()
ahoms's avatar
ahoms committed
431
{
432
	DEB_MEMBER_FUNCT();
ahoms's avatar
ahoms committed
433
434
	FrameDim frame_dim;
	getFrameDim(frame_dim);
435
	Size ccd_size = frame_dim.getSize();
436
	DEB_RETURN() << DEB_VAR1(ccd_size);
437
	return ccd_size;
ahoms's avatar
ahoms committed
438
439
}

440
Size Camera::getChanSize()
ahoms's avatar
ahoms committed
441
{
442
	DEB_MEMBER_FUNCT();
443
	Size chan_size = getCcdSize() / getNbChan();
444
	DEB_RETURN() << DEB_VAR1(chan_size);
445
446
447
448
449
450
451
452
453
	return chan_size;
}

Flip Camera::getRoiInsideMirror()
{
	DEB_MEMBER_FUNCT();
	Flip roi_inside_mirror(m_roi_offset.x > 0, m_roi_offset.y > 0);
	DEB_RETURN() << DEB_VAR1(roi_inside_mirror);
	return roi_inside_mirror;
ahoms's avatar
ahoms committed
454
455
}

456
void Camera::xformChanCoords(const Point& point, Point& xform_point, 
ahoms's avatar
ahoms committed
457
458
			     Corner& ref_corner)
{
459
460
461
	DEB_MEMBER_FUNCT();
	DEB_PARAM() << DEB_VAR1(point);

462
463
	Flip chan_flip;
	getFlip(chan_flip);
464
465
	Flip mirror = getMirror();
	Size chan_size = getChanSize();
ahoms's avatar
ahoms committed
466

467
468
469
470
471
	InputChan curr;
	getInputChan(curr);
	bool right  = !isChanActive(curr, Chan1) && !isChanActive(curr, Chan3);
	bool bottom = !isChanActive(curr, Chan1) && !isChanActive(curr, Chan2);
	Flip readout_flip(right, bottom);
472
	DEB_TRACE() << DEB_VAR2(chan_flip, readout_flip);
473

474
475
	Flip effect_flip = chan_flip & readout_flip;
	DEB_TRACE() << "After flip: " << DEB_VAR1(effect_flip);
ahoms's avatar
ahoms committed
476
477

	if (mirror.x)
478
		effect_flip.x = (point.x >= chan_size.getWidth());
ahoms's avatar
ahoms committed
479
	if (mirror.y)
480
481
		effect_flip.y = (point.y >= chan_size.getHeight());
	DEB_TRACE() << "After mirror: " << DEB_VAR1(effect_flip);
ahoms's avatar
ahoms committed
482

483
	ref_corner = effect_flip.getRefCorner();
ahoms's avatar
ahoms committed
484

485
486
487
	Size ccd_size = getCcdSize();
	xform_point = ccd_size.getCornerCoords(point, ref_corner);
	DEB_RETURN() << DEB_VAR2(xform_point, ref_corner);
ahoms's avatar
ahoms committed
488
489
}

490
491
void Camera::calcImageRoi(const Roi& chan_roi, const Flip& roi_inside_mirror,
			  Roi& image_roi, Point& roi_bin_offset)
ahoms's avatar
ahoms committed
492
{
493
494
495
	DEB_MEMBER_FUNCT();
	DEB_PARAM() << DEB_VAR1(chan_roi);

496
497
	Point image_tl, chan_tl = chan_roi.getTopLeft();
	Point image_br, chan_br = chan_roi.getBottomRight();
ahoms's avatar
ahoms committed
498
	Corner c_tl, c_br;
499
500
501
502
	xformChanCoords(chan_tl, image_tl, c_tl);
	xformChanCoords(chan_br, image_br, c_br);
	Roi unbinned_roi(image_tl, image_br);
	DEB_TRACE() << "Before mirror shift " << DEB_VAR1(unbinned_roi);
503

ahoms's avatar
ahoms committed
504
505
	Bin bin;
	getBin(bin);
506
507
508
509
510
511
512
513
	Size bin_size = Point(bin);
	Point mirr_shift = roi_inside_mirror * (bin_size - 1);
	DEB_TRACE() << DEB_VAR1(mirr_shift);

	image_tl = unbinned_roi.getTopLeft() + mirr_shift;
	unbinned_roi.setTopLeft(image_tl);
	DEB_TRACE() << "Before mirror shift " << DEB_VAR1(unbinned_roi);

ahoms's avatar
ahoms committed
514
	image_roi = unbinned_roi.getBinned(bin);
515

516
517
518
519
520
521
522
	image_tl %= bin_size;
	c_tl = roi_inside_mirror.getRefCorner();
	DEB_TRACE() << DEB_VAR2(image_tl, c_tl);

	roi_bin_offset = bin_size.getCornerCoords(image_tl, c_tl) % bin_size;

	DEB_RETURN() << DEB_VAR2(image_roi, roi_bin_offset);
ahoms's avatar
ahoms committed
523
524
}

525
526
void Camera::calcFinalRoi(const Roi& image_roi, const Point& roi_offset,
			  Roi& final_roi)
ahoms's avatar
ahoms committed
527
{
528
529
530
	DEB_MEMBER_FUNCT();
	DEB_PARAM() << DEB_VAR2(image_roi, roi_offset);

ahoms's avatar
ahoms committed
531
	Point tl = image_roi.getTopLeft() + roi_offset;
532
	Point nb_chan = getNbChan();
ahoms's avatar
ahoms committed
533
534
	Size size = image_roi.getSize() * nb_chan;
	final_roi = Roi(tl, size);
535
536

	DEB_RETURN() << DEB_VAR1(final_roi);
ahoms's avatar
ahoms committed
537
538
}

539
540
void Camera::calcChanRoi(const Roi& image_roi, Roi& chan_roi,
			 Flip& roi_inside_mirror)
ahoms's avatar
ahoms committed
541
{
542
543
544
	DEB_MEMBER_FUNCT();
	DEB_PARAM() << DEB_VAR1(image_roi);

ahoms's avatar
ahoms committed
545
546
547
	Bin bin;
	getBin(bin);
	Roi unbinned_roi = image_roi.getUnbinned(bin);
548
549
	DEB_TRACE() << DEB_VAR1(unbinned_roi);

550
551
	Point chan_tl, image_tl = unbinned_roi.getTopLeft();
	Point chan_br, image_br = unbinned_roi.getBottomRight();
ahoms's avatar
ahoms committed
552
	Corner c_tl, c_br;
553
554
	xformChanCoords(image_tl, chan_tl, c_tl);
	xformChanCoords(image_br, chan_br, c_br);
ahoms's avatar
ahoms committed
555
556

	chan_roi.setCorners(chan_tl, chan_br);
557
558
	DEB_TRACE() << "xformChanCoords: " << DEB_VAR3(chan_roi, c_tl, c_br);

ahoms's avatar
ahoms committed
559
560
561
562
563
	chan_tl = chan_roi.getTopLeft();
	chan_br = chan_roi.getBottomRight();

	bool two_xchan = (c_tl.getX() != c_br.getX());
	bool two_ychan = (c_tl.getY() != c_br.getY());
564
565
	DEB_TRACE() << DEB_VAR2(two_xchan, two_ychan);

566
	Size chan_size = getChanSize();
ahoms's avatar
ahoms committed
567
568
569
570
571
572
	if (two_xchan)
		chan_br.x = chan_size.getWidth() - 1;
	if (two_ychan)
		chan_br.y = chan_size.getHeight() - 1;

	chan_roi.setCorners(chan_tl, chan_br);
573
574
575
576
577

	roi_inside_mirror.x = (image_tl.x > chan_br.x);
	roi_inside_mirror.y = (image_tl.y > chan_br.y);

	DEB_RETURN() << DEB_VAR2(chan_roi, roi_inside_mirror);
ahoms's avatar
ahoms committed
578
579
}

580
581
void Camera::calcImageRoiOffset(const Roi& req_roi, const Roi& image_roi,
				Point& roi_offset)
ahoms's avatar
ahoms committed
582
{
583
584
585
	DEB_MEMBER_FUNCT();
	DEB_PARAM() << DEB_VAR2(req_roi, image_roi);

ahoms's avatar
ahoms committed
586
587
	Point virt_tl = image_roi.getTopLeft();

588
	Size image_size, ccd_size = getCcdSize();
589
590
591
592
	Bin bin;
	getBin(bin);
	ccd_size /= bin;

ahoms's avatar
ahoms committed
593
	image_size = image_roi.getSize();
594
	Point image_br = image_roi.getBottomRight();
ahoms's avatar
ahoms committed
595

596
	Point mirror_tl = ccd_size - (image_br + 1) - image_size;
ahoms's avatar
ahoms committed
597
	Point req_tl = req_roi.getTopLeft();
598
	if (req_tl.x > image_br.x)
ahoms's avatar
ahoms committed
599
		virt_tl.x = mirror_tl.x;
600
	if (req_tl.y > image_br.y)
ahoms's avatar
ahoms committed
601
602
603
		virt_tl.y = mirror_tl.y;

	roi_offset = virt_tl - image_roi.getTopLeft();
604
	DEB_RETURN() << DEB_VAR1(roi_offset);
ahoms's avatar
ahoms committed
605
606
607
608
}

void Camera::checkRoiMode(const Roi& roi)
{
609
610
611
	DEB_MEMBER_FUNCT();
	DEB_PARAM() << DEB_VAR1(roi);

ahoms's avatar
ahoms committed
612
613
614
615
616
617
618
619
620
	RoiMode roi_mode;
	getRoiMode(roi_mode);
	if (!roi.isActive())
		roi_mode = None;
	else if (roi_mode == None)
		roi_mode = Slow;
	setRoiMode(roi_mode);
}

621
void Camera::checkRoi(const Roi& set_roi, Roi& hw_roi)
ahoms's avatar
ahoms committed
622
{
623
624
625
626
627
628
629
630
	DEB_MEMBER_FUNCT();
	DEB_PARAM() << DEB_VAR1(set_roi);

	if (set_roi.isActive()) {
		Roi chan_roi;
		Point roi_offset;
		processSetRoi(set_roi, hw_roi, chan_roi, roi_offset);
	} else 
631
		hw_roi = set_roi;
ahoms's avatar
ahoms committed
632

633
	DEB_RETURN() << DEB_VAR1(hw_roi);
ahoms's avatar
ahoms committed
634
635
}

636
637
void Camera::processSetRoi(const Roi& set_roi, Roi& hw_roi, 
			   Roi& chan_roi, Point& roi_offset)
ahoms's avatar
ahoms committed
638
{
639
640
641
	DEB_MEMBER_FUNCT();
	DEB_PARAM() << DEB_VAR1(set_roi);

642
643
	Roi aligned_roi = set_roi;
	aligned_roi.alignCornersTo(Point(32, 1), Ceil);
644
645
	Flip roi_inside_mirror;
	calcChanRoi(aligned_roi, chan_roi, roi_inside_mirror);
ahoms's avatar
ahoms committed
646
	Roi image_roi;
647
648
649
650
	Point roi_bin_offset;
	calcImageRoi(chan_roi, roi_inside_mirror, image_roi, roi_bin_offset);
	calcImageRoiOffset(set_roi, image_roi, roi_offset);
	calcFinalRoi(image_roi, roi_offset, hw_roi);
651
652

	DEB_RETURN() << DEB_VAR3(hw_roi, chan_roi, roi_offset);
ahoms's avatar
ahoms committed
653
654
}

655
void Camera::setRoi(const Roi& set_roi)
ahoms's avatar
ahoms committed
656
{
657
658
659
	DEB_MEMBER_FUNCT();
	DEB_PARAM() << DEB_VAR1(set_roi);

660
	checkRoiMode(set_roi);
661
662
	if (!set_roi.isActive()) {
		DEB_TRACE() << "Roi deactivated";
ahoms's avatar
ahoms committed
663
		return;
664
	}
ahoms's avatar
ahoms committed
665

666
	Roi hw_roi, chan_roi;
ahoms's avatar
ahoms committed
667
	Point roi_offset;
668
	processSetRoi(set_roi, hw_roi, chan_roi, roi_offset);
ahoms's avatar
ahoms committed
669

670
	writeChanRoi(chan_roi);
ahoms's avatar
ahoms committed
671
672
673
	m_roi_offset = roi_offset;
}

674
void Camera::getRoi(Roi& hw_roi)
ahoms's avatar
ahoms committed
675
{
676
677
	DEB_MEMBER_FUNCT();

678
679
680
681
682
683
684
	hw_roi.reset();

	RoiMode roi_mode;
	getRoiMode(roi_mode);
	if (roi_mode == None)
		return;

685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
	Roi chan_roi, image_roi;
	readChanRoi(chan_roi);

	Flip roi_inside_mirror = getRoiInsideMirror();
	Point roi_bin_offset;
	calcImageRoi(chan_roi, roi_inside_mirror, image_roi, roi_bin_offset);

	calcFinalRoi(image_roi, m_roi_offset, hw_roi);
	DEB_RETURN() << DEB_VAR1(hw_roi);
}

void Camera::writeChanRoi(const Roi& chan_roi)
{
	DEB_MEMBER_FUNCT();
	DEB_PARAM() << DEB_VAR1(chan_roi);
	
	Point tl  = chan_roi.getTopLeft();
	Size size = chan_roi.getSize();
	
	writeRegister(RoiPixelBegin, tl.x);
	writeRegister(RoiPixelWidth, size.getWidth());
	writeRegister(RoiLineBegin,  tl.y);
	writeRegister(RoiLineWidth,  size.getHeight());
}

void Camera::readChanRoi(Roi& chan_roi)
{
	DEB_MEMBER_FUNCT();

ahoms's avatar
ahoms committed
714
715
716
717
718
719
	int rpb, rpw, rlb, rlw;
	readRegister(RoiPixelBegin, rpb);
	readRegister(RoiPixelWidth, rpw);
	readRegister(RoiLineBegin,  rlb);
	readRegister(RoiLineWidth,  rlw);

720
721
722
	chan_roi = Roi(Point(rpb, rlb), Size(rpw, rlw));
	DEB_RETURN() << DEB_VAR1(chan_roi);
}
723

724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751

void Camera::setRoiBinOffset(const Point& roi_bin_offset)
{
	DEB_MEMBER_FUNCT();
	DEB_PARAM() << DEB_VAR1(roi_bin_offset);

	Bin bin;
	getBin(bin);
	Size bin_size = Point(bin);
	Roi valid_offset_range(Point(0), bin_size);
	if (!valid_offset_range.containsPoint(roi_bin_offset)) {
		string err_msg = "Invalid unaligned ";
		DEB_ERROR() << err_msg << DEB_VAR1(roi_bin_offset);
		throw LIMA_HW_EXC(InvalidValue, err_msg + "roi_bin_offset");
	} else if (roi_bin_offset.x != 0) {
		string err_msg = "Roi must be horizontally aligned to bin";
		DEB_ERROR() << err_msg;
		throw LIMA_HW_EXC(InvalidValue, err_msg);
	}

	Roi chan_roi;
	readChanRoi(chan_roi);

	Point image_tl, image_br;
	Corner c_tl, c_br;
	xformChanCoords(chan_roi.getTopLeft(),     image_tl, c_tl);
	xformChanCoords(chan_roi.getBottomRight(), image_br, c_br);
	Roi image_roi(image_tl, image_br);
752
753
	DEB_TRACE() << DEB_VAR1(image_roi);

754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
	Flip roi_inside_mirror = getRoiInsideMirror();
	Point mirr_shift = roi_inside_mirror * (bin_size - 1);
	DEB_TRACE() << DEB_VAR1(mirr_shift);

	image_tl = image_roi.getTopLeft() + mirr_shift;
	image_tl -= image_tl % bin_size;
	DEB_TRACE() << "After alignment " << DEB_VAR1(image_tl);

	c_tl = roi_inside_mirror.getRefCorner();
	image_tl += roi_bin_offset * c_tl.getDir();
	DEB_TRACE() << "After roi_bin_offset " << DEB_VAR1(image_tl);

	Roi max_chan_roi(Point(0), getChanSize());
	bool ok = max_chan_roi.containsPoint(image_tl);
	if (ok) {
		DEB_TRACE() << "Image top-left is OK";
		image_roi.setTopLeft(image_tl);
		ok = max_chan_roi.containsRoi(image_roi);
	}
	if (!ok) {
		string err_msg = "Cannot apply requested ";
		DEB_ERROR() << err_msg << DEB_VAR1(roi_bin_offset);
		throw LIMA_HW_EXC(InvalidValue, err_msg + "roi_bin_offset");
	}

	Point chan_tl, chan_br;
	xformChanCoords(image_roi.getTopLeft(),     chan_tl, c_tl);
	xformChanCoords(image_roi.getBottomRight(), chan_br, c_br);
	chan_roi = Roi(chan_tl, chan_br);

	writeChanRoi(chan_roi);
}

void Camera::getRoiBinOffset(Point& roi_bin_offset)
{
	DEB_MEMBER_FUNCT();

	Roi chan_roi, image_roi;
	readChanRoi(chan_roi);

	Flip roi_inside_mirror = getRoiInsideMirror();
	calcImageRoi(chan_roi, roi_inside_mirror, image_roi, roi_bin_offset);

	DEB_RETURN() << DEB_VAR1(roi_bin_offset);
798
799
}

800

801
void Camera::setTrigMode(TrigMode trig_mode)
802
{
803
804
	DEB_MEMBER_FUNCT();
	DEB_PARAM() << DEB_VAR1(trig_mode);
805
	m_trig_mode = trig_mode;
806
	setNbFrames(m_nb_frames);
807
808
}

809
void Camera::getTrigMode(TrigMode& trig_mode)
810
{
811
	DEB_MEMBER_FUNCT();
812
	trig_mode = m_trig_mode;
813
	DEB_RETURN() << DEB_VAR1(trig_mode);
814
815
816
817
}

void Camera::setTimeUnitFactor(TimeUnitFactor time_unit_factor)
{
818
819
	DEB_MEMBER_FUNCT();
	DEB_PARAM() << DEB_VAR1(time_unit_factor);
820
821
822
823
824
825
	int time_unit = int(time_unit_factor);
	writeRegister(TimeUnit, time_unit);
}

void Camera::getTimeUnitFactor(TimeUnitFactor& time_unit_factor)
{
826
	DEB_MEMBER_FUNCT();
827
828
829
	int time_unit;
	readRegister(TimeUnit, time_unit);
	time_unit_factor = TimeUnitFactor(time_unit);
830
	DEB_RETURN() << DEB_VAR1(time_unit_factor);
831
832
833
834
}

void Camera::setExpTime(double exp_time)
{
835
836
837
	DEB_MEMBER_FUNCT();
	DEB_PARAM() << DEB_VAR1(exp_time);

838
839
840
841
842
843
844
	bool ok = false;
	int exp_val;
	TimeUnitFactor seq_clist[] = { Microseconds, Milliseconds };
	TimeUnitFactor *it, *end = C_LIST_END(seq_clist);
	for (it = seq_clist; it != end; ++it) {
		double factor = TimeUnitFactorMap[*it];
		exp_val = int(exp_time / factor + 0.1);
845
		ok = (exp_val <= MaxRegVal);
846
847
848
		if (ok)
			break;
	}
849
850
	if (!ok) {
		DEB_ERROR() << "Exp. time too high: " << DEB_VAR1(exp_time);
851
		throw LIMA_HW_EXC(InvalidValue, "Exposure time too high");
852
	}
853
854
855
856
857
858
859
860

	TimeUnitFactor time_unit_factor = (exp_val == 0) ? Milliseconds : *it;
	setTimeUnitFactor(time_unit_factor);
	writeRegister(ExpTime, exp_val);
}

void Camera::getExpTime(double& exp_time)
{
861
	DEB_MEMBER_FUNCT();
862
863
864
865
866
	TimeUnitFactor time_unit_factor;
	getTimeUnitFactor(time_unit_factor);
	int exp_val;
	readRegister(ExpTime, exp_val);
	exp_time = exp_val * TimeUnitFactorMap[time_unit_factor];
867
	DEB_RETURN() << DEB_VAR1(exp_time);
868
869
}

870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
void Camera::setShutCloseTime(double shut_time)
{
	DEB_MEMBER_FUNCT();
	DEB_PARAM() << DEB_VAR1(shut_time);
	int shut_val = int(shut_time / TimeUnitFactorMap[Milliseconds] + 0.1);
	writeRegister(ShutCloseTime, shut_val);
}

void Camera::getShutCloseTime(double& shut_time)
{
	DEB_MEMBER_FUNCT();
	int shut_val;
	readRegister(ShutCloseTime, shut_val);
	shut_time = shut_val * TimeUnitFactorMap[Milliseconds];
	DEB_RETURN() << DEB_VAR1(shut_time);
}

887
888
void Camera::setLatTime(double lat_time)
{
889
890
	DEB_MEMBER_FUNCT();
	DEB_PARAM() << DEB_VAR1(lat_time);
891
892
893
894
895
896
	int lat_val = int(lat_time / TimeUnitFactorMap[Milliseconds] + 0.1);
	writeRegister(LatencyTime, lat_val);
}

void Camera::getLatTime(double& lat_time)
{
897
	DEB_MEMBER_FUNCT();
898
899
900
	int lat_val;
	readRegister(LatencyTime, lat_val);
	lat_time = lat_val * TimeUnitFactorMap[Milliseconds];
901
	DEB_RETURN() << DEB_VAR1(lat_time);
902
903
904
905
}

void Camera::setNbFrames(int nb_frames)
{
906
907
908
	DEB_MEMBER_FUNCT();
	DEB_PARAM() << DEB_VAR1(nb_frames);

909
	TrigMode trig_mode;
910
	getTrigMode(trig_mode);
911
912
913
914
915
916
917
	int cam_nb_frames = (trig_mode == ExtTrigMult) ? 1 : nb_frames;
	writeRegister(NbFrames, cam_nb_frames);
	m_nb_frames = nb_frames;
}

void Camera::getNbFrames(int& nb_frames)
{
918
	DEB_MEMBER_FUNCT();
919
	nb_frames = m_nb_frames;
920
	DEB_RETURN() << DEB_VAR1(nb_frames);
921
922
}

923
924
void Camera::getStatus(Status& status)
{
925
	DEB_MEMBER_FUNCT();
926
927
928
929
	Espia::Dev& dev = getEspiaDev();
	int ccd_status;
	dev.getCcdStatus(ccd_status);
	status = Status(ccd_status);
930
	DEB_RETURN() << DEB_VAR1(DEB_HEX(status));
931
932
933
934
}

bool Camera::waitStatus(Status& status, double timeout)
{
935
936
937
	DEB_MEMBER_FUNCT();
	DEB_PARAM() << DEB_VAR2(status, timeout);

938
939
940
941
942
943
944
945
946
947
948
949
	Timestamp end;
	if (timeout > 0)
		end = Timestamp::now() + Timestamp(timeout);

	bool good_status = false;
	Status curr_status;
	while (!good_status && !end.isSet() || (Timestamp::now() < end)) {
		getStatus(curr_status);
		good_status = ((curr_status & status) == status);
	}

	status = curr_status;
950
	DEB_RETURN() << DEB_VAR2(status, good_status);
951
952
953
	return good_status;
}

954
955
void Camera::start()
{
956
957
	DEB_MEMBER_FUNCT();

958
	TrigMode trig_mode;
959
	getTrigMode(trig_mode);
960
961
	if (trig_mode == IntTrig) {
		DEB_TRACE() << "Starting camera by software";
962
		sendCmd(Start);
963
	}
964
965
966
967
}

void Camera::stop()
{
968
969
	DEB_MEMBER_FUNCT();

970
	TrigMode trig_mode;
971
	getTrigMode(trig_mode);
972
973
	if (trig_mode != ExtGate) {
		DEB_TRACE() << "Aborting possible acquisition";
974
		sendCmd(Stop);
975
	}
976

977
	DEB_TRACE() << "Waiting for camera to become idle";
978
979
980
981
982
	Status status = Wait;
	waitStatus(status);

	FrameTransferMode ftm;
	getFrameTransferMode(ftm);
983
984
985
	if (ftm == FTM) {
		DEB_TRACE() << "Waiting for possible FTM frame readout: "
			    << "sleeping " << DEB_VAR1(MaxReadoutTime);
986
		Sleep(MaxReadoutTime);
987
	}
ahoms's avatar
ahoms committed
988
989
}

ahoms's avatar
ahoms committed
990
991
992
993
void Camera::setMaxImageSizeCallbackActive(bool cb_active)
{
	m_mis_cb_act = cb_active;
}