EspiaAcq.cpp 11.2 KB
Newer Older
1
2
3
#include "EspiaAcq.h"
#include "MemUtils.h"

4
5
#include <sstream>

6
using namespace lima;
7
using namespace lima::Espia;
8
using namespace std;
9
10
11
12
13

#define CHECK_CALL(ret)		ESPIA_CHECK_CALL(ret)

#define ESPIA_MIN_BUFFER_SIZE	(128 * 1024)

14
15
16
AcqEndCallback::AcqEndCallback()
	: m_acq(NULL)
{
17
	DEB_CONSTRUCTOR();
18
19
20
21
}

AcqEndCallback::~AcqEndCallback()
{
22
23
24
25
	DEB_DESTRUCTOR();

	if (m_acq) {
		DEB_TRACE() << "Unregistering from Acq";
26
		m_acq->unregisterAcqEndCallback(*this);
27
	}
28
29
30
31
32
33
34
35
36
}

Acq *AcqEndCallback::getAcq() const
{ 
	return m_acq; 
}

void AcqEndCallback::setAcq(Acq *acq)
{
37
	DEB_MEMBER_FUNCT();
38
	DEB_PARAM() << DEB_VAR1(acq);
39
40
41

	if (acq && m_acq) {
		DEB_ERROR() << "Acquisition already set";
42
		throw LIMA_HW_EXC(InvalidValue, "Acq already set");
43
44
	} else if (!acq && !m_acq) {
		DEB_ERROR() << "Acquisition already reset";
45
		throw LIMA_HW_EXC(InvalidValue, "Acq already reset");
46
	}
47
48
49
50

	m_acq = acq;
}

51

52
Acq::Acq(Dev& dev)
53
54
	: m_dev(dev)
{
55
	DEB_CONSTRUCTOR();
56
	DEB_PARAM() << DEB_VAR1(dev.getDevNb());
57
58
59
60
61
62
63
64

	ostringstream os;
	if (dev.isMeta())
		os << "MetaAcq";
	else
		os << "Acq#" << dev.getDevNb();
	DEB_SET_OBJ_NAME(os.str());

65
	m_nb_buffers = m_nb_buffer_frames = 0;
66
67
68
69
70
71
	m_real_frame_factor = m_real_frame_size = 0;
	
	m_nb_frames = 0;
	m_started = false;

	resetFrameInfo(m_last_frame_info);
72
73
	m_frame_cb_nb = Invalid;
	m_user_frame_cb_act = false;
74

75
76
	m_acq_end_cb = NULL;

77
	enableFrameCallback();
78
79
}

80
Acq::~Acq()
81
{
82
83
	DEB_DESTRUCTOR();

84
85
86
	if (m_acq_end_cb)
		unregisterAcqEndCallback(*m_acq_end_cb);

87
	bufferFree();
88
	disableFrameCallback();
89
90
}

91
92
93
94
95
Dev& Acq::getDev()
{
	return m_dev;
}

96
int Acq::dispatchFrameCallback(struct espia_cb_data *cb_data)
97
{
98
	DEB_STATIC_FUNCT();
99
	DEB_PARAM() << DEB_VAR1(cb_data->cb_nr);
100

101
	Acq *espia = (Acq *) cb_data->data;
102
	DEB_TRACE() << DEB_VAR1(DEB_OBJ_NAME(espia));
103

104
	void (Acq::*method)(struct espia_cb_data *cb_data) = NULL;
105

106
	int& cb_nb = cb_data->cb_nr;
107
108
	if (cb_nb == espia->m_frame_cb_nb) {
		DEB_TRACE() << "Processing FrameCallback";
109
		method = &Acq::processFrameCallback;
110
111
	}

112
113
114
	if (method) {
		try {
			(espia->*method)(cb_data);
115
116
		} catch (Exception& e) {
			DEB_ERROR() << e.getErrMsg();
117
		} catch (...) {
118
			DEB_ERROR() << "Unknown Error in frame callback";
119
120
		}
	}
121
	
122
123
124
	return ESPIA_OK;
}

125
void Acq::enableFrameCallback()
126
{
127
128
	DEB_MEMBER_FUNCT();

129
	int& cb_nb = m_frame_cb_nb;
130
131
	if (cb_nb != Invalid) {
		DEB_TRACE() << "Callback already enabled";
132
		return;
133
	}
134
135
136

	struct espia_cb_data cb_data;
	cb_data.type    = ESPIA_CB_ACQ;
137
	cb_data.cb      = dispatchFrameCallback;
138
	cb_data.data    = this;
139
	cb_data.timeout = SCDXIPCI_BLOCK_FOREVER;
140
141
142
143
144
145
146

	struct img_frame_info& req_finfo = cb_data.info.acq.req_finfo;
	req_finfo.buffer_nr    = ESPIA_ACQ_ANY;
	req_finfo.frame_nr     = ESPIA_ACQ_ANY;
	req_finfo.round_count  = ESPIA_ACQ_ANY;
	req_finfo.acq_frame_nr = ESPIA_ACQ_EACH;

147
	DEB_TRACE() << "Registering frame callback";
148
	m_dev.registerCallback(cb_data, cb_nb);
149
150
}

151
void Acq::disableFrameCallback()
152
{
153
154
	DEB_MEMBER_FUNCT();

155
	int& cb_nb = m_frame_cb_nb;
156
157
	if (cb_nb == Invalid) {
		DEB_TRACE() << "Callback already disabled";
158
		return;
159
	}
160

161
	DEB_TRACE() << "Unregistering frame callback";
162
	m_dev.unregisterCallback(cb_nb);
163
164
165
166
}

void Acq::setFrameCallbackActive(bool cb_active)
{
167
	DEB_MEMBER_FUNCT();
168
	DEB_PARAM() << DEB_VAR1(cb_active);
169
	m_user_frame_cb_act = cb_active;
170
171
}

172
void Acq::processFrameCallback(struct espia_cb_data *cb_data)
173
{
174
175
	DEB_MEMBER_FUNCT();

176
177
178
	AutoMutex l = acqLock();

	struct img_frame_info& cb_finfo = cb_data->info.acq.cb_finfo;
179
180
181
	bool aborted = finished_espia_frame_info(&cb_finfo, cb_data->ret);
	bool finished = aborted;
	if (!aborted) {
182
		m_last_frame_info = cb_finfo;
183
		bool endless = (m_nb_frames == 0);
184
185
		unsigned long last_frame = m_nb_frames - 1;
		finished = (!endless && (cb_finfo.acq_frame_nr == last_frame));
186
	}
187

188
	DEB_TRACE() << DEB_VAR2(aborted, finished);
189

190
191
192
193
194
	if (finished)
		m_started = false;

	l.unlock();

195
196
197
198
	HwFrameInfo hw_finfo;
	if (!aborted)
		real2virtFrameInfo(cb_finfo, hw_finfo);

199
	DEB_TRACE() << DEB_VAR1(hw_finfo);
200
201
202

	if (m_user_frame_cb_act) {
		DEB_TRACE() << "Calling user FrameCallback";
203
		newFrameReady(hw_finfo);
204
	}
205

206
207
	if ((m_acq_end_cb != NULL) && finished) {
		DEB_TRACE() << "Calling AcqEndCallback";
208
		m_acq_end_cb->acqFinished(hw_finfo);
209
	}
210
211
212
213
}

void Acq::bufferAlloc(int& nb_buffers, int nb_buffer_frames,
		      const FrameDim& frame_dim)
214
{
215
	DEB_MEMBER_FUNCT();
216
	DEB_PARAM() << DEB_VAR3(nb_buffers, nb_buffer_frames, frame_dim);
217

218
	if (!frame_dim.isValid() || (nb_buffers <= 0) || 
219
220
	    (nb_buffer_frames <= 0)) {
		DEB_ERROR() << "Invalid parameters";
221
		throw LIMA_HW_EXC(InvalidValue, "Invalid frame_dim, "
222
				  "nb_buffers and/or nb_buffer_frames");
223
	}
224
225

	if ((frame_dim == m_frame_dim) && (nb_buffers == m_nb_buffers) &&
226
227
	    (nb_buffer_frames == m_nb_buffer_frames)) {
		DEB_TRACE() << "Requested buffers already allocated";
228
		return;
229
	}
230
231
232
233

	bufferFree();

	int& virt_buffers   = nb_buffers;
234
	int& virt_frames    = nb_buffer_frames;
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253

	int real_buffers    = virt_buffers;
	int real_frames     = virt_frames;
	int real_frame_size = frame_dim.getMemSize();
	if (virt_frames == 1) {
		int page_size;
		GetPageSize(page_size);
		real_frame_size += page_size - 1;
		real_frame_size &= ~(page_size - 1);
	}

	int real_buffer_size = real_frame_size * real_frames;
	int frame_factor = 1;
	if (real_buffer_size < ESPIA_MIN_BUFFER_SIZE) {
		frame_factor  = ESPIA_MIN_BUFFER_SIZE / real_buffer_size;
		real_frames  *= frame_factor;
		real_buffers += frame_factor - 1;
		real_buffers /= frame_factor;
		virt_buffers  = real_buffers * frame_factor;
254

255
256
		DEB_TRACE() << DEB_VAR3(frame_factor, virt_buffers, 
					virt_frames);
257
258
	}

259
	DEB_TRACE() << "Calling espia_buffer_alloc";
260
	DEB_TRACE() << DEB_VAR3(real_buffers, real_frames, real_frame_size); 
261
262
263
264
265
	CHECK_CALL(espia_buffer_alloc(m_dev, real_buffers, real_frames,
				      real_frame_size));

	m_frame_dim         = frame_dim;
	m_nb_buffers        = virt_buffers;
266
	m_nb_buffer_frames  = virt_frames;
267
268
	m_real_frame_factor = frame_factor;
	m_real_frame_size   = real_frame_size;
269

270
	DEB_RETURN() << DEB_VAR1(nb_buffers);
271
272
}

273
void Acq::bufferFree()
274
{
275
276
277
278
	DEB_MEMBER_FUNCT();

	if ((m_nb_buffers == 0) || (m_nb_buffer_frames == 0)) {
		DEB_TRACE() << "Buffers already freed";
279
		return;
280
	}
281

282
	stop();
283

284
	DEB_TRACE() << "Calling espia_buffer_free";
285
286
287
	CHECK_CALL(espia_buffer_free(m_dev));

	m_frame_dim = FrameDim();
288
	m_nb_buffers = m_nb_buffer_frames = 0;
289
290
291
	m_real_frame_factor = m_real_frame_size = 0;
}

292
const FrameDim& Acq::getFrameDim()
293
{
294
	DEB_MEMBER_FUNCT();
295
	DEB_RETURN() << DEB_VAR1(m_frame_dim);
296
	return m_frame_dim;
297
298
}

299
void Acq::getNbBuffers(int& nb_buffers)
300
{
301
	DEB_MEMBER_FUNCT();
302
	DEB_RETURN() << DEB_VAR1(nb_buffers);
303
304
305
	nb_buffers = m_nb_buffers;
}

306
void Acq::getNbBufferFrames(int& nb_buffer_frames)
307
{
308
	DEB_MEMBER_FUNCT();
309
	DEB_RETURN() << DEB_VAR1(nb_buffer_frames);
310
	nb_buffer_frames = m_nb_buffer_frames;
311
312
}

313
void *Acq::getBufferFramePtr(int buffer_nb, int frame_nb)
314
{
315
	DEB_MEMBER_FUNCT();
316
	DEB_PARAM() << DEB_VAR2(buffer_nb, frame_nb);
317

318
319
320
	int real_buffer = realBufferNb(buffer_nb, frame_nb);
	int real_frame  = realFrameNb(buffer_nb, frame_nb);
	void *ptr;
321
	DEB_TRACE() << "Calling espia_frame_address";
322
	CHECK_CALL(espia_frame_address(m_dev, real_buffer, real_frame, &ptr));
323
	DEB_RETURN() << DEB_VAR1(ptr);
324
325
326
	return ptr;
}

327
void *Acq::getAcqFramePtr(int acq_frame_nb)
328
{
329
	DEB_MEMBER_FUNCT();
330
	DEB_PARAM() << DEB_VAR1(acq_frame_nb);
331

332
	unsigned long buffer_nb = ESPIA_ACQ_ANY;
333
	void *ptr;
334
	DEB_TRACE() << "Calling espia_frame_address";
335
	CHECK_CALL(espia_frame_address(m_dev, buffer_nb, acq_frame_nb, &ptr));
336
	DEB_RETURN() << DEB_VAR1(ptr);
337
338
339
	return ptr;
}

340
void Acq::getFrameInfo(int acq_frame_nb, HwFrameInfoType& info)
341
{
342
	DEB_MEMBER_FUNCT();
343
	DEB_PARAM() << DEB_VAR1(acq_frame_nb);
344

345
346
347
348
349
	struct img_frame_info finfo;
	finfo.buffer_nr    = ESPIA_ACQ_ANY;
	finfo.frame_nr     = ESPIA_ACQ_ANY;
	finfo.round_count  = ESPIA_ACQ_ANY;
	finfo.acq_frame_nr = acq_frame_nb;
350

351
	DEB_TRACE() << "Calling espia_get_frame";
352
353
	int ret = espia_get_frame(m_dev, &finfo, SCDXIPCI_NO_BLOCK);
	if (ret == SCDXIPCI_ERR_NOTREADY) {
354
		DEB_TRACE() << "Frame not ready yet";
355
356
357
358
		info = HwFrameInfo();
		return;
	}
	CHECK_CALL(ret);
359
360

	real2virtFrameInfo(finfo, info);
361
	DEB_RETURN() << DEB_VAR1(info);
362
363
}

364
365
void Acq::real2virtFrameInfo(const struct img_frame_info& real_info, 
			     HwFrameInfoType& virt_info)
366
{
367
368
	DEB_MEMBER_FUNCT();

369
370
371
372
373
374
	char *buffer_ptr = (char *) real_info.buffer_ptr;
	int frame_offset = real_info.frame_nr * m_real_frame_size;

	virt_info.acq_frame_nb    = real_info.acq_frame_nr;
	virt_info.frame_ptr       = buffer_ptr + frame_offset;
	virt_info.frame_dim       = &m_frame_dim;
375
	virt_info.frame_timestamp = USec2Sec(real_info.time_us);
376
377
378
	virt_info.valid_pixels    = real_info.pixels;
}

379
void Acq::resetFrameInfo(struct img_frame_info& frame_info)
380
{
381
382
	DEB_MEMBER_FUNCT();

383
	frame_info.buffer_ptr   = NULL;
384
385
386
387
	frame_info.buffer_nr    = SCDXIPCI_INVALID;
	frame_info.frame_nr     = SCDXIPCI_INVALID;
	frame_info.round_count  = SCDXIPCI_INVALID;
	frame_info.acq_frame_nr = SCDXIPCI_INVALID;
388
389
390
391
	frame_info.time_us      = 0;
	frame_info.pixels       = 0;
}

392
void Acq::setNbFrames(int nb_frames)
393
{
394
	DEB_MEMBER_FUNCT();
395
	DEB_PARAM() << DEB_VAR1(nb_frames);
396
397

	if (nb_frames < 0) {
398
		DEB_ERROR() << "Invalid " << DEB_VAR1(nb_frames);
399
		throw LIMA_HW_EXC(InvalidValue, "Invalid nb of frames");
400
	}
401
402
403
404

	m_nb_frames = nb_frames;
}

405
void Acq::getNbFrames(int& nb_frames)
406
{
407
	DEB_MEMBER_FUNCT();
408
	nb_frames = m_nb_frames;
409
	DEB_RETURN() << DEB_VAR1(nb_frames);
410
411
}

412
void Acq::start()
413
{
414
415
	DEB_MEMBER_FUNCT();

416
417
	AutoMutex l = acqLock();

418
419
	if (m_started) {
		DEB_ERROR() << "Acquisition already running";
420
		throw LIMA_HW_EXC(Error, "Acquisition already running");
421
	}
422
423
424

	resetFrameInfo(m_last_frame_info);

425
	DEB_TRACE() << "Calling espia_start_acq, m_nb_frames=" << m_nb_frames;
426
	CHECK_CALL(espia_start_acq(m_dev, 0, m_nb_frames, SCDXIPCI_NO_BLOCK));
427
428
429
430
431

	m_start_ts = Timestamp::now();
	m_started = true;
}

432
void Acq::stop()
433
{
434
435
	DEB_MEMBER_FUNCT();

436
437
438
	AutoMutex l = acqLock();
	if (!m_started)
		return;
439

440
	l.unlock();
441
	DEB_TRACE() << "Calling espia_stop_acq";
442
	CHECK_CALL(espia_stop_acq(m_dev));
443
444
	l.lock();

445
446
447
	m_started = false;
}

448
void Acq::getStatus(StatusType& status)
449
{
450
451
	DEB_MEMBER_FUNCT();

452
453
	AutoMutex l = acqLock();

454
	DEB_TRACE() << "Calling espia_acq_active";
455
456
457
458
	unsigned long acq_run_nb;
	int acq_running = espia_acq_active(m_dev, &acq_run_nb);
	CHECK_CALL(acq_running);

459
	status.running = m_started;
460
461
	status.run_nb  = acq_run_nb;
	status.last_frame_nb = m_last_frame_info.acq_frame_nr;
462

463
	DEB_RETURN() << DEB_VAR1(status);
464
465
}

466
467
void Acq::registerAcqEndCallback(AcqEndCallback& acq_end_cb)
{
468
	DEB_MEMBER_FUNCT();
469
	DEB_PARAM() << DEB_VAR2(&acq_end_cb, m_acq_end_cb);
470

471
472
	if (m_acq_end_cb) {
		DEB_ERROR() << "AcqEndCallback already registered";
473
474
		throw LIMA_HW_EXC(InvalidValue, 
				  "AcqEndCallback already registered");
475
476
	}

477
478
479
480
481
482
	acq_end_cb.setAcq(this);
	m_acq_end_cb = &acq_end_cb;
}

void Acq::unregisterAcqEndCallback(AcqEndCallback& acq_end_cb)
{
483
	DEB_MEMBER_FUNCT();
484
	DEB_PARAM() << DEB_VAR2(&acq_end_cb, m_acq_end_cb);
485

486
487
	if (m_acq_end_cb != &acq_end_cb) {
		DEB_ERROR() << "Specified AcqEndCallback not registered";
488
489
		throw LIMA_HW_EXC(InvalidValue, 
				  "Specified AcqEndCallback not registered");
490
491
	}

492
493
494
495
496
	stop();

	m_acq_end_cb = NULL;
	acq_end_cb.setAcq(NULL);
}
497
498
499
500
501
502
503
504
505
506
507
508
509


ostream& lima::operator <<(ostream& os, const Acq::StatusType& status)
{
	os << "<"
	   << "running=" << status.running << ", "
	   << "run_nb=" << status.run_nb << ", "
	   << "last_frame_nb=" << status.last_frame_nb
	   << ">";

	return os;

}