SlsDetectorEiger.cpp 34.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
23
//###########################################################################
// 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/>.
//###########################################################################

#include "SlsDetectorEiger.h"
24
#include "lima/MiscUtils.h"
25

26
#include <emmintrin.h>
27
#include <sched.h>
28

29
30
31
using namespace std;
using namespace lima;
using namespace lima::SlsDetector;
32
using namespace lima::SlsDetector::Defs;
33
34
35
36

const int Eiger::ChipSize = 256;
const int Eiger::ChipGap = 2;
const int Eiger::HalfModuleChips = 4;
37
const int Eiger::NbRecvPorts = EigerNbRecvPorts;
38

39
40
41
42
43
44
45
const int Eiger::BitsPerXfer = 4;
const int Eiger::SuperColNbCols = 8;
const double Eiger::BaseChipXferFreq = 200; // Mbit/s
const double Eiger::MaxFebBebBandwidth = 25600; // Mbit/s
const Eiger::LinScale Eiger::ChipXfer2Buff(2.59, 0.85);
const Eiger::LinScale Eiger::ChipRealReadout(1.074, -4);

46
47
48
49
const unsigned long Eiger::BebFpgaWritePtrAddr = 0xD10000C4;
const unsigned long Eiger::BebFpgaReadPtrAddr = 0xD10000E4;
const unsigned long Eiger::BebFpgaPtrRange = 0x10000000;

50
51
Eiger::CorrBase::CorrBase(Eiger *eiger)
	: m_eiger(eiger)
52
53
{
	DEB_CONSTRUCTOR();
54
	m_nb_eiger_modules = m_eiger->getNbEigerModules();
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
}

Eiger::CorrBase::~CorrBase()
{
	DEB_DESTRUCTOR();
	if (m_eiger)
		m_eiger->removeCorr(this);
}

void Eiger::CorrBase::prepareAcq()
{
	DEB_MEMBER_FUNCT();

	if (!m_eiger)
		THROW_HW_ERROR(InvalidValue) << "Correction already removed";

71
	const FrameDim& recv_dim = m_eiger->getRecvFrameDim();
72
	m_mod_frame_dim = recv_dim * Point(1, 2);
73
74
75
	m_frame_size = m_mod_frame_dim.getSize() * Point(1, m_nb_eiger_modules);
	m_inter_lines.resize(m_nb_eiger_modules);
	for (int i = 0; i < m_nb_eiger_modules - 1; ++i) {
76
77
78
		m_inter_lines[i] = m_eiger->getInterModuleGap(i);
		m_frame_size += Point(0, m_inter_lines[i]);
	}
79
80
81
	m_inter_lines[m_nb_eiger_modules - 1] = 0;
}

82
83
84
85
86
87
void Eiger::BadRecvFrameCorr::BadFrameData::reset()
{
	last_idx = 0;
	bad_frame_list.clear();
}

88
89
Eiger::BadRecvFrameCorr::BadRecvFrameCorr(Eiger *eiger)
	: CorrBase(eiger)
90
91
{
	DEB_CONSTRUCTOR();
92
93
94
95
96
97
98
99
100

	m_cam = m_eiger->getCamera();
}

void Eiger::BadRecvFrameCorr::prepareAcq()
{
	DEB_MEMBER_FUNCT();

	CorrBase::prepareAcq();
101
	m_bfd.reset();
102
103
}

104
void Eiger::BadRecvFrameCorr::correctFrame(FrameType frame, void *ptr)
105
106
{
	DEB_MEMBER_FUNCT();
107

108
	char *bptr = (char *) ptr;
109
110
111
112
113
114
115
116
117
118
119
120
	IntList& bfl = m_bfd.bad_frame_list;
	int& last_idx = m_bfd.last_idx;
	if (bfl.empty()) {
		int bad_frames = m_cam->getNbBadFrames(0);
		if (bad_frames == last_idx)
			return;
		m_cam->getBadFrameList(0, last_idx, bad_frames, bfl);
	}
	IntList::iterator end = bfl.end();
	if (find(bfl.begin(), end, frame) != end) {
		Eiger::Geometry *geom = m_eiger->getGeometry();
		for (int i = 0; i < geom->getNbRecvs(); ++i) {
121
122
			Eiger::Geometry::Recv *recv = geom->getRecv(i);
			recv->fillBadFrame(frame, bptr);
123
		}
124
	}
125
126
127
128
	if (*(end - 1) > int(frame))
		return;
	last_idx += bfl.size();
	bfl.clear();
129
130
}

131
Eiger::InterModGapCorr::InterModGapCorr(Eiger *eiger)
132
	: CorrBase(eiger)
133
134
135
136
137
138
139
140
141
142
143
144
145
146
{
	DEB_CONSTRUCTOR();
}

void Eiger::InterModGapCorr::prepareAcq()
{
	DEB_MEMBER_FUNCT();

	CorrBase::prepareAcq();

	m_gap_list.clear();

	int mod_size = m_mod_frame_dim.getMemSize();
	int width = m_mod_frame_dim.getSize().getWidth();
147
148
	int ilw = width * m_mod_frame_dim.getDepth();
	for (int i = 0, start = 0; i < m_nb_eiger_modules - 1; ++i) {
149
		start += mod_size;
150
		int size = m_inter_lines[i] * ilw;
151
152
153
154
155
		m_gap_list.push_back(Block(start, size));
		start += size;
	}
}

156
void Eiger::InterModGapCorr::correctFrame(FrameType /*frame*/, void *ptr)
157
158
159
160
161
162
163
164
165
166
167
168
{
	DEB_MEMBER_FUNCT();
	
	char *dest = static_cast<char *>(ptr);
	BlockList::const_iterator it, end = m_gap_list.end();
	for (it = m_gap_list.begin(); it != end; ++it) {
		int start = it->first;
		int size = it->second;
		memset(dest + start, 0, size);
	}
}

169
Data Eiger::ModelReconstruction::processModel(Data& data)
170
171
172
{
	DEB_MEMBER_FUNCT();

173
	DEB_PARAM() << DEB_VAR4(m_eiger, data.frameNumber, 
174
				_processingInPlaceFlag, data.data());
175
176
177
178
	if (!m_eiger)
		return data;

	Data ret = _processingInPlaceFlag ? data : data.copy();
179

180
181
182
183
184
185
186
	FrameType frame = ret.frameNumber;
	void *ptr = ret.data();
	CorrList& corr_list = m_eiger->m_corr_list;
	CorrList::iterator it, end = corr_list.end();
	for (it = corr_list.begin(); it != end; ++it)
		(*it)->correctFrame(frame, ptr);

187
188
189
	return ret;
}

190
191
192
193
Eiger::Geometry::Recv::FrameData::FrameData()
{
}

194
Eiger::Geometry::Recv::FrameData::FrameData(const Receiver::ImagePackets& /*image*/,
195
					    char *d)
196
197
198
199
	: dst(d)
{
}

200
201
Eiger::Geometry::Recv::Port::Port(Recv *recv, int port)
	: m_recv(recv), m_recv_idx(m_recv->m_idx), m_port(port)
202
203
{
	DEB_CONSTRUCTOR();
204
	DEB_PARAM() << DEB_VAR2(m_recv_idx, m_port);
205
206
207
	m_top_half_recv = (m_recv_idx % 2 == 0);
}

208
void Eiger::Geometry::Recv::Port::prepareAcq()
209
210
211
212
{
	DEB_MEMBER_FUNCT();
	DEB_PARAM() << DEB_VAR1(m_recv_idx);

213
214
215
	Geometry *geom = m_recv->m_eiger_geom;
	m_raw = geom->m_raw;
	const FrameDim& frame_dim = geom->m_recv_frame_dim;
216
217
	const Size& size = frame_dim.getSize();
	int depth = frame_dim.getDepth();
218
	m_dst.lw = size.getWidth() * depth;
219
	int recv_size = frame_dim.getMemSize();
220
221
	int src_port_offset = 0;
	int dst_port_offset = recv_size * m_recv_idx;
222

223
	m_pchips = HalfModuleChips / NbRecvPorts;
224
225
	m_src.cw = ChipSize * depth;
	m_dst.cw = m_src.cw;
226
	if (m_recv->m_pixel_depth_4)
227
228
		m_src.cw /= 2;
	m_src.lw = m_pchips * m_src.cw;
229

230
	if (m_raw) {
231
		// vert. port concat.
232
		dst_port_offset += ChipSize * m_dst.lw * m_port;
233
234
	} else {
		// inter-chip horz. gap
235
		m_dst.cw += ChipGap * depth;
236
		// horz. port concat.
237
238
239
240
241
242
243
244
245
246
247
248
249
250
		dst_port_offset += m_pchips * m_dst.cw * m_port;

		int mod_idx = m_recv_idx / 2;
		for (int i = 0; i < mod_idx; ++i)
			dst_port_offset += (geom->getInterModuleGap(i) *
					    m_dst.lw);
		if (m_top_half_recv) {
			// top-half module: vert-flipped data
			src_port_offset += (ChipSize - 1) * m_src.lw;
			m_src.lw *= -1;
		} else {
			// bottom-half module: inter-chip vert. gap
			dst_port_offset += (ChipGap / 2) * m_dst.lw;
		}
251
252
	}

253
254
	const int block_len = sizeof(__m128i);
	const int chip_blocks = ChipSize / 2 / block_len;
255
256
257
258
259
260
261
262

	const int port_lines = m_raw ? ChipSize : 1;
	m_port_blocks = chip_blocks * m_pchips * port_lines;
	DEB_TRACE() << DEB_VAR2(port_lines, m_port_blocks);
	m_src.len = ChipSize * abs(m_src.lw);
	m_src.off = src_port_offset;
	m_dst.off = dst_port_offset;
	DEB_TRACE() << DEB_VAR3(m_src.len, m_src.off, m_dst.off);
263
264
}

265
FrameDim Eiger::Geometry::Recv::Port::getSrcFrameDim()
266
267
{
	DEB_MEMBER_FUNCT();
268
269
270
	FrameDim fdim(abs(m_src.lw), ChipSize, Bpp8);
	DEB_RETURN() << DEB_VAR1(fdim);
	return fdim;
271
272
}

273
void Eiger::Geometry::Recv::Port::copy(char *dst, char *src)
274
275
276
{
	DEB_MEMBER_FUNCT();

277
	bool valid_data = (src != NULL);
278
279
	src += m_src.off;
	dst += m_dst.off;
280

281
	const int& lines = ChipSize;
282
283
284
285
286
287
288
289
290
291
	if (m_raw) {
		int size = m_src.lw * lines;
		if (valid_data)
			memcpy(dst, src, size);
		else
			memset(dst, 0xff, size);
		return;
	}

	for (int i = 0; i < lines; ++i, src += m_src.lw, dst += m_dst.lw) {
292
293
		char *s = src;
		char *d = dst;
294
		for (int j = 0; j < m_pchips; ++j, s += m_src.cw, d += m_dst.cw)
295
			if (valid_data)
296
				memcpy(d, s, m_src.cw);
297
			else
298
				memset(d, 0xff, m_src.cw);
299
300
301
	}
}

302
Eiger::Geometry::Recv::Recv(Geometry *eiger_geom, int idx)
303
	: m_eiger_geom(eiger_geom), m_idx(idx)
304
305
306
307
308
309
310
311
312
313
{
	DEB_CONSTRUCTOR();
	DEB_PARAM() << DEB_VAR1(m_idx);

	for (int i = 0; i < NbRecvPorts; ++i) {
		Port *p = new Port(this, i);
		m_port_list.push_back(p);
	}
}

314
int Eiger::Geometry::Recv::getNbPorts()
315
316
317
318
319
320
{
	DEB_MEMBER_FUNCT();
	DEB_RETURN() << DEB_VAR1(NbRecvPorts);
	return NbRecvPorts;
}

321
Eiger::Geometry::Recv::Port *Eiger::Geometry::Recv::getPort(int port_idx)
322
323
324
325
326
{
	DEB_MEMBER_FUNCT();
	return m_port_list[port_idx];
}

327
void Eiger::Geometry::Recv::prepareAcq()
328
329
{
	DEB_MEMBER_FUNCT();
330
331
332

	m_pixel_depth_4 = (m_eiger_geom->m_pixel_depth == PixelDepth4);

333
334
335
336
337
	PortList::iterator it, end = m_port_list.end();
	for (it = m_port_list.begin(); it != end; ++it)
		(*it)->prepareAcq();
}

338
void Eiger::Geometry::Recv::copy(const FrameData& data)
339
340
341
{
	DEB_MEMBER_FUNCT();
	for (int i = 0; i < getNbPorts(); ++i)
342
		m_port_list[i]->copy(data.dst, data.src[i]);
343
344
345
346
347
}

void Eiger::Geometry::Recv::fillBadFrame(FrameType frame, char *bptr)
{
	DEB_MEMBER_FUNCT();
348
	DEB_PARAM() << DEB_VAR2(m_idx, frame);
349
350
351
352
	FrameData data;
	for (int i = 0; i < getNbPorts(); ++i)
		data.src[i] = NULL;
	data.dst = bptr;
353
	processFrame(data);
354
355
}

356
void Eiger::Geometry::Recv::expandPixelDepth4(const FrameData& data)
357
358
{
	DEB_MEMBER_FUNCT();
359
	DEB_PARAM() << DEB_VAR3(DEB_HEX((unsigned long) data.src[0]),
360
				DEB_HEX((unsigned long) data.src[1]),
361
				DEB_HEX((unsigned long) data.dst));
362

363
	const int nb_ports = NbRecvPorts;
364
	Port *port = m_port_list[0];
365
	const bool raw = port->m_raw;
366
	int pi;
367
368
369
	char *src[EigerNbRecvPorts];
	for (pi = 0; pi < nb_ports; ++pi) {
		src[pi] = data.src[pi] + m_port_list[pi]->m_src.off;
370
		unsigned long s = (unsigned long) src[pi];
371
372
373
374
		if ((s & 15) != 0)
			THROW_HW_ERROR(Error) << "Missaligned src: "
					      << DEB_VAR1(DEB_HEX(s));
	}
375
376
	pi = 0;
	char *dst = data.dst + port->m_dst.off;
377
	unsigned long d = (unsigned long) dst;
378
	int dest_misalign = (d & 15);
379
	if (raw && dest_misalign)
380
381
		THROW_HW_ERROR(Error) << "Missaligned dest: "
				      << DEB_VAR1(DEB_HEX(d));
382

383
	DEB_TRACE() << DEB_VAR1(dest_misalign);
384
385
386
	DEB_TRACE() << DEB_VAR3(DEB_HEX((unsigned long) src[0]),
				DEB_HEX((unsigned long) src[1]),
				DEB_HEX((unsigned long) dst));
387
388
	bool valid_data = data.valid.test(pi);
	const int block_len = sizeof(__m128i);
389
	int nb_blocks = port->m_src.len * nb_ports / block_len;
390
	const int chip_blocks = ChipSize / 2 / block_len;
391
	const int port_blocks = port->m_port_blocks;
392
393
	const __m128i *src128 = (const __m128i *) src[pi];
	__m128i *dst128 = (__m128i *) dst;
394
	const __m128i m = _mm_set1_epi8(0xf);
395
396
	const int block_bits = block_len * 8;
	const int gap_bits = ChipGap * 8;
397
398
	const __m128i block64_bits128 = _mm_set_epi64x(0, 64);
	const __m128i gap_bits128 = _mm_set_epi64x(0, gap_bits);
399
	int shift_l = 0;
400
401
402
	__m128i shift_l128, shift_r128;
	__m128i m64_0 = _mm_set_epi64x(0, -1);
	__m128i m64_1 = _mm_set_epi64x(-1, 0);
403
 	bool reverse = (port->m_src.lw < 0);
404
405
406
407
408
	__m128i m0, prev;
	int chip_count = 0;

#define load_dst128()							\
	do {								\
409
410
		dest_misalign = ((unsigned long) dst & 15);		\
		dst128 = (__m128i *) (dst - dest_misalign);		\
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
		shift_l = dest_misalign * 8;				\
		shift_l128 = _mm_set_epi64x(0, shift_l % 64);		\
		shift_r128 = _mm_sub_epi64(block64_bits128, shift_l128); \
		if (shift_l != 0) {					\
			m0 = _mm_srl_epi64(_mm_set1_epi8(0xff), shift_r128); \
			if (shift_l < 64)				\
				m0 = _mm_and_si128(m0, m64_0);		\
			prev = _mm_and_si128(_mm_load_si128(dst128), m0); \
		} else {						\
			prev = _mm_setzero_si128();			\
		}							\
	} while (0)

#define pad_dst128()							\
	do {								\
		shift_l += gap_bits;					\
		if (shift_l % 64 == 0)					\
			shift_l128 = _mm_setzero_si128();		\
		else							\
			shift_l128 = _mm_add_epi64(shift_l128, gap_bits128); \
		shift_r128 = _mm_sub_epi64(block64_bits128, shift_l128); \
		if (shift_l == block_bits) {				\
			_mm_store_si128(dst128++, prev);		\
			prev = _mm_setzero_si128();			\
			shift_l = 0;					\
		}							\
	} while (0)

#define sync_dst128()							\
	do {								\
		if (shift_l != 0) {					\
			m0 = _mm_sll_epi64(_mm_set1_epi8(0xff), shift_l128); \
			if (shift_l >= 64)				\
				m0 = _mm_and_si128(m0, m64_1);		\
			__m128i a = _mm_and_si128(_mm_load_si128(dst128), m0); \
			_mm_store_si128(dst128, _mm_or_si128(prev, a));	\
		}							\
	} while (0)

450
	if (!raw)
451
		load_dst128();
452
	for (int i = 0; i < nb_blocks; ++i) {
453
		if (i == 0)
454
455
456
			DEB_TRACE() << DEB_VAR3(DEB_HEX((unsigned long) src128),
						DEB_HEX((unsigned long) dst128),
						nb_blocks);
457
458
		if (!raw && i && (i % chip_blocks == 0) &&
		    (++chip_count % HalfModuleChips > 0))
459
460
461
462
			pad_dst128();
		if (i && (i % port_blocks == 0)) {
			if (reverse)
				src128 -= 2 * port_blocks;
463
			src[pi++] = (char *) src128;
464
465
			pi %= nb_ports;
			valid_data = data.valid.test(pi);
466
			src128 = (const __m128i *) src[pi];
467
468
469
470
471
472
473
474
475
476
477
478
		}
		__m128i p4_raw;
		if (valid_data)
			p4_raw = _mm_load_si128(src128);
		else
			p4_raw = _mm_set1_epi8(0xff);
		++src128;
		__m128i p4_shr = _mm_srli_epi16(p4_raw, 4);
		__m128i i8_0 = _mm_and_si128(p4_raw, m);
		__m128i i8_1 = _mm_and_si128(p4_shr, m);
		__m128i p8_0 = _mm_unpacklo_epi8(i8_0, i8_1);
		__m128i p8_1 = _mm_unpackhi_epi8(i8_0, i8_1);
479
		if (raw) {
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
506
507
508
509
510
			_mm_store_si128(dst128++, p8_0);
			_mm_store_si128(dst128++, p8_1);
			continue;
		}
		__m128i p8_0l = _mm_sll_epi64(p8_0, shift_l128);
		__m128i p8_0r = _mm_srl_epi64(p8_0, shift_r128);
		__m128i p8_1l = _mm_sll_epi64(p8_1, shift_l128);
		__m128i p8_1r = _mm_srl_epi64(p8_1, shift_r128);
		__m128i d0, d1, d2, d3, d4;
		if (shift_l < 64) {
			d0 = p8_0l;
			d1 = p8_0r;
			d2 = p8_1l;
			d3 = p8_1r;
			d4 = _mm_setzero_si128();
		} else {
			d0 = _mm_setzero_si128();
			d1 = p8_0l;
			d2 = p8_0r;
			d3 = p8_1l;
			d4 = p8_1r;
		}
		__m128i d10 = _mm_slli_si128(d1, 8);
		__m128i d11 = _mm_srli_si128(d1, 8);
		__m128i d30 = _mm_slli_si128(d3, 8);
		__m128i d31 = _mm_srli_si128(d3, 8);
		prev = _mm_or_si128(prev, d0);
		_mm_store_si128(dst128++, _mm_or_si128(prev, d10));
		prev = _mm_or_si128(d11, d2);
		_mm_store_si128(dst128++, _mm_or_si128(prev, d30));
		prev = _mm_or_si128(d31, d4);
511
	}
512
	if (!raw)
513
		sync_dst128();
514
515
}

516
517
Eiger::Geometry::Geometry()
	: m_raw(false), m_image_type(Bpp16), m_pixel_depth(PixelDepth16)
518
519
{
	DEB_CONSTRUCTOR();
520
}
521

522
523
524
525
526
527
528
int Eiger::Geometry::getInterModuleGap(int det)
{
	DEB_MEMBER_FUNCT();
	if (det >= getNbEigerModules() - 1)
		THROW_HW_ERROR(InvalidValue) << "Invalid " << DEB_VAR1(det);
	return 36;
}
529

530
531
532
533
534
535
536
537
538
539
540
541
void Eiger::Geometry::setNbRecvs(int nb_recv)
{
	DEB_MEMBER_FUNCT();
	DEB_PARAM() << DEB_VAR1(nb_recv);

	int curr_nb_recv = m_recv_list.size();
	if (curr_nb_recv > nb_recv) {
		m_recv_list.resize(nb_recv);
		return;
	}

	for (int i = curr_nb_recv; i < nb_recv; ++i) {
542
543
		Recv *r = new Recv(this, i);
		m_recv_list.push_back(r);
544
545
546
	}
}

547
void Eiger::Geometry::prepareAcq()
548
{
549
550
551
552
553
554
555
	DEB_MEMBER_FUNCT();

	m_recv_frame_dim = getRecvFrameDim(m_raw);

	RecvList::iterator rit, rend = m_recv_list.end();
	for (rit = m_recv_list.begin(); rit != rend; ++rit)
		(*rit)->prepareAcq();
556
557
}

558
FrameDim Eiger::Geometry::getFrameDim(bool raw)
559
560
561
{
	DEB_MEMBER_FUNCT();
	DEB_PARAM() << DEB_VAR1(raw);
562
	FrameDim frame_dim = getRecvFrameDim(raw);
563
	Size size = frame_dim.getSize();
564
	size *= Point(1, getNbRecvs());
565
	if (!raw)
566
		for (int i = 0; i < getNbEigerModules() - 1; ++i)
567
568
569
			size += Point(0, getInterModuleGap(i));
	frame_dim.setSize(size);
	DEB_RETURN() << DEB_VAR1(frame_dim);
570
	return frame_dim;
571
572
}

573
FrameDim Eiger::Geometry::getRecvFrameDim(bool raw)
574
575
576
{
	DEB_MEMBER_FUNCT();
	DEB_PARAM() << DEB_VAR1(raw);
577
578
	FrameDim frame_dim;
	frame_dim.setImageType(m_image_type);
579
	Size size(ChipSize * HalfModuleChips, ChipSize);
580
	if (raw) {
581
582
		size /= Point(NbRecvPorts, 1);
		size *= Point(1, NbRecvPorts);
583
	} else {
584
		size += Point(ChipGap, ChipGap) * Point(3, 1) / Point(1, 2);
585
	}
586
	frame_dim.setSize(size);
587
	DEB_RETURN() << DEB_VAR1(frame_dim);
588
589
590
	return frame_dim;
}

591
592
593
594
595
Eiger::Beb::Beb(const std::string& host_name)
	: shell(host_name), fpga_mem(shell)
{
}

596
597
Eiger::Thread::Thread(Eiger *eiger, int idx)
	: m_eiger(eiger), m_idx(idx)
598
599
600
{
	DEB_MEMBER_FUNCT();

601
	AutoMutex l = lock();
602
603
604
605
606
607
608
609
610
611
612
	m_state = Init;

	start();

	struct sched_param param;
	param.sched_priority = 50;
	int ret = pthread_setschedparam(m_thread, SCHED_RR, &param);
	if (ret != 0)
		DEB_ERROR() << "Could not set real-time priority!!";

	while (m_state == Init)
613
		wait();
614
615
}

616
Eiger::Thread::~Thread()
617
{
618
619
620
	DEB_DESTRUCTOR();

	AutoMutex l = lock();
621
	m_state = Quitting;
622
623
624
	broadcast();
	while (m_state != End)
		wait();
625
626
}

627
void Eiger::Thread::threadFunction()
628
629
630
{
	DEB_MEMBER_FUNCT();

631
632
	State& s = m_state;

633
	AutoMutex l = lock();
634
	s = Ready;
635
	broadcast();
636

637
638
639
640
641
642
643
644
645
	while (s != Quitting) {
		while ((s == Ready) || (s == Stopping)
		       || ((s == Running) && m_eiger->allFramesAcquired())) {
			if (s == Stopping) {
				s = Ready;
				broadcast();
			}
			wait();
		}
646
647
648
649
650
651
652
653
654
655
656
		if (s == Running) {
			try {
				AutoMutexUnlock u(l);
				m_eiger->processPackets();
			} catch (Exception& e) {
				Camera *cam = m_eiger->getCamera();
				string name = ("Eiger::Thread::"
					       "threadFunction");
				cam->reportException(e, name);
			}
		}
657
	}
658

659
	s = End;
660
	broadcast();
661
662
}

663
void Eiger::Thread::setCPUAffinity(CPUAffinity aff)
664
665
{
	DEB_MEMBER_FUNCT();
666
	DEB_PARAM() << DEB_VAR1(aff);
667

668
        aff.applyToTask(getThreadID(), false);
669
670
}

671
void Eiger::Thread::prepareAcq()
672
673
674
675
{
	DEB_MEMBER_FUNCT();
}

676
Eiger::Eiger(Camera *cam)
677
	: Model(cam, EigerDet), m_fixed_clock_div(false)
678
679
680
681
682
683
{
	DEB_CONSTRUCTOR();

	int nb_det_modules = getNbDetModules();
	DEB_TRACE() << "Using Eiger detector, " << DEB_VAR1(nb_det_modules);

684
	NameList host_name_list = cam->getHostnameList();
685
686
687
688
689
690
	NameList::const_iterator it, end = host_name_list.end();
	for (it = host_name_list.begin(); it != end; ++it) {
		Beb *beb = new Beb(*it);
		m_beb_list.push_back(beb);
	}

691
692
	m_geom.setNbRecvs(nb_det_modules);

693
694
	for (int i = 0; i < nb_det_modules; ++i)
		m_recv_list.push_back(cam->getRecv(i));
695

696
697
	setNbProcessingThreads(1);

698
699
700
701
702
	if (isTenGigabitEthernetEnabled()) {
		DEB_TRACE() << "Forcing 10G Ethernet flow control";
		setFlowControl10G(true);
	}

703
704
	m_reconstruction = new ModelReconstruction(this);

705
706
707
708
709
710
711
712
	updateCameraModel();

	getClockDiv(m_clock_div);
}

Eiger::~Eiger()
{
	DEB_DESTRUCTOR();
713
	getCamera()->waitAcqState(Idle);
714
715
	m_reconstruction->m_eiger = NULL;
	m_reconstruction->unref();
716
717
718
719
720
721
722
723
724
	removeAllCorr();
}

void Eiger::getFrameDim(FrameDim& frame_dim, bool raw)
{
	DEB_MEMBER_FUNCT();
	DEB_PARAM() << DEB_VAR1(raw);
	frame_dim = m_geom.getFrameDim(raw);
	DEB_RETURN() << DEB_VAR1(frame_dim);
725
726
}

727
728
729
730
731
732
void Eiger::getDetMap(Data& /*det_map*/)
{
	DEB_MEMBER_FUNCT();
	THROW_HW_ERROR(NotSupported) << "DetMap not implemented yet";
}

733
734
735
736
737
string Eiger::getName()
{
	DEB_MEMBER_FUNCT();
	ostringstream os;
	os << "PSI/Eiger-";
738
	int nb_modules = getNbEigerModules();
739
740
	if (nb_modules == 1) {
		os << "500k";
741
742
	} else if (nb_modules % 2 == 0) {
		os << (nb_modules / 2) << "M";
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
	} else {
		os << nb_modules << "-Modules";
	}
	string name = os.str();
	DEB_RETURN() << DEB_VAR1(name);
	return name;
}

void Eiger::getPixelSize(double& x_size, double& y_size)
{
	DEB_MEMBER_FUNCT();
	x_size = y_size = 75e-6;
	DEB_RETURN() << DEB_VAR2(x_size, y_size);
}

758
759
void Eiger::getDACInfo(NameList& name_list, IntList& idx_list,
		       IntList& milli_volt_list)
760
761
762
{
	DEB_MEMBER_FUNCT();

763
#define EIGER_DAC(x)			{x, 0}
764
765
766
767
768
769
#define EIGER_DAC_MV(x)			{x, 1}

	static struct DACData {
		DACIndex idx;
		int milli_volt;
	} EigerDACList[] = {
770
771
772
773
774
		EIGER_DAC(EigerVcmpLL),
		EIGER_DAC(EigerVcmpLR),
		EIGER_DAC(EigerVcmpRL),
		EIGER_DAC(EigerVcmpRR),
		EIGER_DAC(Threshold),
775
776
777
778
	};
	const unsigned int size = C_LIST_SIZE(EigerDACList);

	name_list.resize(size);
779
	idx_list.resize(size);
780
781
782
	milli_volt_list.resize(size);
	struct DACData *data = EigerDACList;
	for (unsigned int i = 0; i < size; ++i, ++data) {
783
		ostringstream os;
784
		os << data->idx;
785
		name_list[i] = os.str();
786
787
		idx_list[i] = int(data->idx);
		milli_volt_list[i] = data->milli_volt;
788
		DEB_RETURN() << DEB_VAR2(name_list[i], idx_list[i]);
789
790
791
	}
}

792
793
void Eiger::getADCInfo(NameList& name_list, IntList& idx_list,
		       FloatList& factor_list, FloatList& min_val_list)
794
795
796
{
	DEB_MEMBER_FUNCT();

797
798
#define EIGER_TEMP_FACTOR		(1 / 1000.0)

799
#define EIGER_TEMP(x)			{x, EIGER_TEMP_FACTOR, 0}
800
801
802
803
804
805
806
807
808
809
810
811
812

	static struct ADCData {
		ADCIndex idx;
		double factor, min_val;
	} EigerADCList[] = {
		EIGER_TEMP(TempFPGA),
		EIGER_TEMP(TempFPGAExt),
		EIGER_TEMP(Temp10GE),
		EIGER_TEMP(TempDCDC),
		EIGER_TEMP(TempSODL),
		EIGER_TEMP(TempSODR),
		EIGER_TEMP(TempFPGAFL),
		EIGER_TEMP(TempFPGAFR),
813
814
815
816
	};
	const unsigned int size = C_LIST_SIZE(EigerADCList);

	name_list.resize(size);
817
818
819
820
821
	idx_list.resize(size);
	factor_list.resize(size);
	min_val_list.resize(size);
	struct ADCData *data = EigerADCList;
	for (unsigned int i = 0; i < size; ++i, ++data) {
822
		ostringstream os;
823
		os << data->idx;
824
		name_list[i] = os.str();
825
826
827
828
829
		idx_list[i] = int(data->idx);
		factor_list[i] = data->factor;
		min_val_list[i] = data->min_val;
		DEB_RETURN() << DEB_VAR4(name_list[i], idx_list[i], 
					 factor_list[i], min_val_list[i]);
830
831
832
	}
}

833
void Eiger::getTimeRanges(TimeRanges& time_ranges)
834
835
836
{
	DEB_MEMBER_FUNCT();

837
	PixelDepth pixel_depth;
838
	Camera* cam = getCamera();
839
	cam->getPixelDepth(pixel_depth);
840
841
842
843
844
845
	ClockDiv clock_div;
	getClockDiv(clock_div);
	ParallelMode parallel_mode;
	getParallelMode(parallel_mode);

	calcTimeRanges(pixel_depth, clock_div, parallel_mode, time_ranges);
846
847
848

	double readout_time;
	measureReadoutTime(readout_time);
849
850
851
852
853
854
855
856
}

void Eiger::calcTimeRanges(PixelDepth pixel_depth, ClockDiv clock_div,
			   ParallelMode parallel_mode,
			   TimeRanges& time_ranges)
{
	DEB_STATIC_FUNCT();
	DEB_PARAM() << DEB_VAR3(pixel_depth, clock_div, parallel_mode);
857

858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
	// times are in usec, freq in MHz
	int period_factor = 1 << int(clock_div);
	double xfer_freq = BaseChipXferFreq / period_factor;
	DEB_TRACE() << DEB_VAR2(period_factor, xfer_freq);

	double xfer_2_buff = ChipXfer2Buff.calcY(period_factor);
	DEB_TRACE() << DEB_VAR1(xfer_2_buff);

	const int super_col_pixels = SuperColNbCols * ChipSize;
	double theo_single_readout = super_col_pixels * BitsPerXfer / xfer_freq;
	// theoretical -> measured correction
	double real_single_readout = ChipRealReadout.calcY(theo_single_readout);
	DEB_TRACE() << DEB_VAR2(theo_single_readout, real_single_readout);

	int readout_cycles;
	if (pixel_depth == PixelDepth4)
		readout_cycles = 1;
	else if (pixel_depth == PixelDepth8)
		readout_cycles = 2;
	else
		readout_cycles = 3;
	double min_chip_readout = real_single_readout * readout_cycles;
	DEB_TRACE() << DEB_VAR2(readout_cycles, min_chip_readout);

	int mem_xfer_blocks = pixel_depth / BitsPerXfer;
	const int nb_super_cols = ChipSize / SuperColNbCols * HalfModuleChips;
	double feb_beb_bw = (xfer_freq * nb_super_cols / readout_cycles *
			     mem_xfer_blocks);
	DEB_TRACE() << DEB_VAR2(feb_beb_bw, MaxFebBebBandwidth);
	double chip_readout = min_chip_readout;
	if (feb_beb_bw > MaxFebBebBandwidth) {
		chip_readout *= feb_beb_bw / MaxFebBebBandwidth;
		DEB_TRACE() << "limiting chip readout freq: "
			    << DEB_VAR2(min_chip_readout, chip_readout);
892
	}
893
894
895
896
	double full_readout = xfer_2_buff + chip_readout;
	DEB_TRACE() << DEB_VAR1(full_readout);

	bool parallel = (parallel_mode == Parallel);
897

898
	double min_exp = 10;
899
900
	double min_period = (parallel ? 0 : min_exp) + full_readout;
	double min_lat = parallel ? xfer_2_buff : full_readout;
901

902
903
904
905
906
907
908
	// Timing hardware uses 32-bit, base-10 floating-point registers:
	//   29 bits: mantissa
	//    3 bits: exponent
	// Time unit: 10 nsec 
	// Max value: 2^29 * 10^(2^3 - 1) * 10 nsec = 1.7 years
	// Using 1000 sec as a reasonable upper limit

909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
	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);
}

924
void Eiger::measureReadoutTime(double& /*readout_time*/)
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
{
	DEB_MEMBER_FUNCT();

	Camera* cam = getCamera();

	class SyncParams
	{


	private:
		double prev_exp, prev_period;
		TrigMode prev_trig_mode;
	};

	// exp, period, trigmode, nb_frames
	double prev_exp, prev_period;
	cam->getExpTime(prev_exp);
	cam->getFramePeriod(prev_period);
	FrameType prev_nb_frames;
	cam->getNbFrames(prev_nb_frames);
	Defs::TrigMode prev_trig_mode;
	cam->getTrigMode(prev_trig_mode);


	/*
	DEB_ALWAYS() << "calling startAcquisition";
	cam->m_det->startAcquisition();

	DEB_ALWAYS() << "calling stopAcquisition";
	cam->m_det->stopAcquisition();

956
	readout_time = 0;
957
958
959
	 */
}

960
961
962
int Eiger::getNbFrameMapItems()
{
	DEB_MEMBER_FUNCT();
963
	int nb_items = 1;
964
965
966
967
968
969
970
971
972
	DEB_RETURN() << DEB_VAR1(nb_items);
	return nb_items;
}

void Eiger::updateFrameMapItems(FrameMap *map)
{
	DEB_MEMBER_FUNCT();
}

973
974
975
976
977
978
void Eiger::updateImageSize()
{
	DEB_MEMBER_FUNCT();

	removeAllCorr();

979
980
	createBadRecvFrameCorr();

981
982
	Camera *cam = getCamera();

983
	bool raw;
984
	cam->getRawMode(raw);
985
986
987
988
989
990
991
992
993
994
995
	ImageType image_type = cam->getImageType();
	PixelDepth pixel_depth;
	cam->getPixelDepth(pixel_depth);

	DEB_TRACE() << DEB_VAR3(raw, image_type, pixel_depth);

	m_geom.setRaw(raw);
	m_geom.setPixelDepth(pixel_depth);
	m_geom.setImageType(image_type);
	m_geom.prepareAcq();

996
997
998
999
	if (raw)
		return;

	createChipBorderCorr(image_type);
1000