1
#define _IPECAMERA_IMAGE_C
13
#include <ufodecode.h>
29
#define FIND_REG(var, bank, name) \
30
ctx->var = pcilib_find_register(pcilib, bank, name); \
31
if (ctx->var == PCILIB_REGISTER_INVALID) { \
32
err = PCILIB_ERROR_NOTFOUND; \
33
pcilib_error("Unable to find a %s register", name); \
37
#define GET_REG(reg, var) \
39
err = pcilib_read_register_by_id(pcilib, ctx->reg, &var); \
41
pcilib_error("Error reading %s register", ipecamera_registers[ctx->reg].name); \
45
#define SET_REG(reg, val) \
47
err = pcilib_write_register_by_id(pcilib, ctx->reg, val); \
49
pcilib_error("Error writting %s register", ipecamera_registers[ctx->reg].name); \
53
#define CHECK_REG(reg, check) \
55
err = pcilib_read_register_by_id(pcilib, ctx->reg, &value); \
57
pcilib_error("Error reading %s register", ipecamera_registers[ctx->reg].name); \
59
if (value != check) { \
60
pcilib_error("Unexpected value (0x%lx) of register %s", value, ipecamera_registers[ctx->reg].name); \
61
err = PCILIB_ERROR_INVALID_DATA; \
65
#define IPECAMERA_GET_EXPECTED_STATUS(ctx) ((ctx->firmware == 4)?IPECAMERA_EXPECTED_STATUS_4:IPECAMERA_EXPECTED_STATUS)
66
#define CHECK_STATUS_REG() CHECK_REG(status_reg, IPECAMERA_GET_EXPECTED_STATUS(ctx))
68
#define CHECK_VALUE(value, val) \
69
if ((!err)&&(value != val)) { \
70
pcilib_error("Unexpected value (0x%x) in data stream (0x%x is expected)", value, val); \
71
err = PCILIB_ERROR_INVALID_DATA; \
74
#define CHECK_FLAG(flag, check, ...) \
75
if ((!err)&&(!(check))) { \
76
pcilib_error("Unexpected value (0x%x) of " flag, __VA_ARGS__); \
77
err = PCILIB_ERROR_INVALID_DATA; \
81
pcilib_context_t *ipecamera_init(pcilib_t *pcilib) {
84
ipecamera_t *ctx = malloc(sizeof(ipecamera_t));
87
pcilib_register_value_t value;
89
memset(ctx, 0, sizeof(ipecamera_t));
91
ctx->buffer_size = IPECAMERA_DEFAULT_BUFFER_SIZE;
92
ctx->dim.bpp = sizeof(ipecamera_pixel_t) * 8;
94
// We need DMA engine initialized to resolve DMA registers
95
// FIND_REG(packet_len_reg, "fpga", "xrawdata_packet_length");
97
FIND_REG(status_reg, "fpga", "status");
98
FIND_REG(control_reg, "fpga", "control");
100
FIND_REG(status3_reg, "fpga", "status3");
102
FIND_REG(n_lines_reg, "cmosis", "cmosis_number_lines");
103
FIND_REG(line_reg, "cmosis", "cmosis_start1");
104
FIND_REG(exposure_reg, "cmosis", "cmosis_exp_time");
105
FIND_REG(flip_reg, "cmosis", "cmosis_image_flipping");
107
FIND_REG(firmware_version_reg, "fpga", "firmware_version");
108
FIND_REG(adc_resolution_reg, "fpga", "adc_resolution");
109
FIND_REG(output_mode_reg, "fpga", "output_mode");
111
FIND_REG(max_frames_reg, "fpga", "ddr_max_frames");
112
FIND_REG(num_frames_reg, "fpga", "ddr_num_frames");
115
GET_REG(firmware_version_reg, value);
119
ctx->firmware = value;
122
// pcilib_error("Unsupported version of firmware (%lu)", value);
126
#ifdef IPECAMERA_BUG_POSTPONED_READ
127
GET_REG(max_frames_reg, value);
128
if ((value + IPECAMERA_RESERVE_BUFFERS + 3) > ctx->buffer_size) {
129
ctx->buffer_size = (value + 1) + IPECAMERA_RESERVE_BUFFERS + 2;
131
#endif /* IPECAMERA_BUG_POSTPONED_READ */
134
ctx->rdma = PCILIB_DMA_ENGINE_INVALID;
135
ctx->wdma = PCILIB_DMA_ENGINE_INVALID;
143
return (pcilib_context_t*)ctx;
146
void ipecamera_free(pcilib_context_t *vctx) {
148
ipecamera_t *ctx = (ipecamera_t*)vctx;
149
ipecamera_stop(vctx, PCILIB_EVENT_FLAGS_DEFAULT);
154
pcilib_dma_context_t *ipecamera_init_dma(pcilib_context_t *vctx) {
155
#ifdef IPECAMERA_DMA_R3
156
ipecamera_t *ctx = (ipecamera_t*)vctx;
159
pcilib_model_description_t *model_info = pcilib_get_model_description(vctx->pcilib);
160
if ((!model_info->dma_api)||(!model_info->dma_api->init)) {
161
pcilib_error("The DMA engine is not configured in model");
166
#ifdef IPECAMERA_DMA_R3
168
return model_info->dma_api->init(vctx->pcilib, PCILIB_NWL_MODIFICATION_IPECAMERA, NULL);
170
return model_info->dma_api->init(vctx->pcilib, PCILIB_DMA_MODIFICATION_DEFAULT, NULL);
173
return model_info->dma_api->init(vctx->pcilib, PCILIB_DMA_MODIFICATION_DEFAULT, NULL);
178
int ipecamera_set_buffer_size(ipecamera_t *ctx, int size) {
180
pcilib_error("Can't change buffer size while grabbing");
181
return PCILIB_ERROR_INVALID_REQUEST;
185
pcilib_error("The buffer size is too small");
186
return PCILIB_ERROR_INVALID_REQUEST;
189
if (((size^(size-1)) < size) < size) {
190
pcilib_error("The buffer size is not power of 2");
193
ctx->buffer_size = size;
198
int ipecamera_reset(pcilib_context_t *vctx) {
200
ipecamera_t *ctx = (ipecamera_t*)vctx;
201
pcilib_t *pcilib = vctx->pcilib;
203
pcilib_register_t control, status;
204
pcilib_register_value_t value;
207
pcilib_error("IPECamera imaging is not initialized");
208
return PCILIB_ERROR_NOTINITIALIZED;
211
if (!ctx->firmware) {
212
pcilib_warning("Unsupported version of firmware (%lu)", ctx->firmware);
216
pcilib = vctx->pcilib;
217
control = ctx->control_reg;
218
status = ctx->status_reg;
220
// Set Reset bit to CMOSIS
221
err = pcilib_write_register_by_id(pcilib, control, 0x1e4);
223
pcilib_error("Error setting FPGA reset bit");
226
usleep(IPECAMERA_SLEEP_TIME);
228
// Remove Reset bit to CMOSIS
229
err = pcilib_write_register_by_id(pcilib, control, 0x1e1);
231
pcilib_error("Error reseting FPGA reset bit");
234
usleep(IPECAMERA_SLEEP_TIME);
236
// Special settings for CMOSIS v.2
237
value = 01; err = pcilib_write_register_space(pcilib, "cmosis", 115, 1, &value);
239
pcilib_error("Error setting CMOSIS configuration");
242
usleep(IPECAMERA_SLEEP_TIME);
244
value = 07; err = pcilib_write_register_space(pcilib, "cmosis", 82, 1, &value);
246
pcilib_error("Error setting CMOSIS configuration");
249
usleep(IPECAMERA_SLEEP_TIME);
251
// Set default parameters
252
err = pcilib_write_register_by_id(pcilib, control, IPECAMERA_IDLE);
254
pcilib_error("Error bringing FPGA in default mode");
260
err = pcilib_read_register_by_id(pcilib, status, &value);
262
pcilib_error("Error reading status register");
266
if (value != IPECAMERA_GET_EXPECTED_STATUS(ctx)) {
267
pcilib_error("Unexpected value (%lx) of status register, expected %lx", value, IPECAMERA_GET_EXPECTED_STATUS(ctx));
268
return PCILIB_ERROR_VERIFY;
275
int ipecamera_start(pcilib_context_t *vctx, pcilib_event_t event_mask, pcilib_event_flags_t flags) {
278
ipecamera_t *ctx = (ipecamera_t*)vctx;
279
pcilib_t *pcilib = vctx->pcilib;
280
pcilib_register_value_t value;
283
struct sched_param sched;
286
pcilib_error("IPECamera imaging is not initialized");
287
return PCILIB_ERROR_NOTINITIALIZED;
290
if (!ctx->firmware) {
291
pcilib_error("Unsupported version of firmware (%lu)", ctx->firmware);
292
return PCILIB_ERROR_INVALID_REQUEST;
296
pcilib_error("IPECamera grabbing is already started");
297
return PCILIB_ERROR_INVALID_REQUEST;
300
// Allow readout and clean the FRAME_REQUEST mode if set for some reason
301
GET_REG(control_reg, value);
302
SET_REG(control_reg, value|IPECAMERA_READOUT_FLAG);
303
usleep(IPECAMERA_SLEEP_TIME);
304
if (value&0x1000) ctx->fr_mode = 1;
313
ctx->reported_id = 0;
315
ctx->parse_data = (flags&PCILIB_EVENT_FLAG_RAW_DATA_ONLY)?0:1;
318
ctx->dim.width = IPECAMERA_WIDTH;
319
ctx->dim.height = IPECAMERA_MAX_LINES;
320
// GET_REG(n_lines_reg, ctx->dim.height);
322
GET_REG(output_mode_reg, value);
324
case IPECAMERA_MODE_16_CHAN_IO:
325
ctx->cmosis_outputs = 16;
327
case IPECAMERA_MODE_4_CHAN_IO:
328
ctx->cmosis_outputs = 4;
331
pcilib_error("IPECamera reporting invalid output_mode 0x%lx", value);
332
return PCILIB_ERROR_INVALID_STATE;
335
ipecamera_compute_buffer_size(ctx, ctx->dim.height);
337
ctx->raw_size = ctx->cur_raw_size;
338
ctx->full_size = ctx->cur_full_size;
339
ctx->padded_size = ctx->cur_padded_size;
341
ctx->image_size = ctx->dim.width * ctx->dim.height;
344
GET_REG(max_frames_reg, value);
345
ctx->max_frames = value;
347
ctx->buffer = malloc(ctx->padded_size * ctx->buffer_size);
349
ipecamera_stop(vctx, PCILIB_EVENT_FLAGS_DEFAULT);
350
pcilib_error("Unable to allocate ring buffer (%lu bytes)", ctx->padded_size * ctx->buffer_size);
351
return PCILIB_ERROR_MEMORY;
354
ctx->image = (ipecamera_pixel_t*)malloc(ctx->image_size * ctx->buffer_size * sizeof(ipecamera_pixel_t));
356
ipecamera_stop(vctx, PCILIB_EVENT_FLAGS_DEFAULT);
357
pcilib_error("Unable to allocate image buffer (%lu bytes)", ctx->image_size * ctx->buffer_size * sizeof(ipecamera_pixel_t));
358
return PCILIB_ERROR_MEMORY;
361
ctx->cmask = malloc(ctx->dim.height * ctx->buffer_size * sizeof(ipecamera_change_mask_t));
363
ipecamera_stop(vctx, PCILIB_EVENT_FLAGS_DEFAULT);
364
pcilib_error("Unable to allocate change-mask buffer");
365
return PCILIB_ERROR_MEMORY;
368
ctx->frame = (ipecamera_frame_t*)malloc(ctx->buffer_size * sizeof(ipecamera_frame_t));
370
ipecamera_stop(vctx, PCILIB_EVENT_FLAGS_DEFAULT);
371
pcilib_error("Unable to allocate frame-info buffer");
372
return PCILIB_ERROR_MEMORY;
375
memset(ctx->frame, 0, ctx->buffer_size * sizeof(ipecamera_frame_t));
377
for (i = 0; i < ctx->buffer_size; i++) {
378
err = pthread_rwlock_init(&ctx->frame[i].mutex, NULL);
382
ctx->frame_mutex_destroy = i;
385
ipecamera_stop(vctx, PCILIB_EVENT_FLAGS_DEFAULT);
386
pcilib_error("Initialization of rwlock mutexes for frame synchronization has failed");
387
return PCILIB_ERROR_FAILED;
390
ctx->ipedec = ufo_decoder_new(ctx->dim.height, ctx->dim.width, NULL, 0);
392
ipecamera_stop(vctx, PCILIB_EVENT_FLAGS_DEFAULT);
393
pcilib_error("Unable to initialize IPECamera decoder library");
394
return PCILIB_ERROR_FAILED;
398
ctx->rdma = pcilib_find_dma_by_addr(vctx->pcilib, PCILIB_DMA_FROM_DEVICE, IPECAMERA_DMA_ADDRESS);
399
if (ctx->rdma == PCILIB_DMA_ENGINE_INVALID) {
400
err = PCILIB_ERROR_NOTFOUND;
401
pcilib_error("The C2S channel of IPECamera DMA Engine (%u) is not found", IPECAMERA_DMA_ADDRESS);
403
err = pcilib_start_dma(vctx->pcilib, ctx->rdma, PCILIB_DMA_FLAGS_DEFAULT);
405
ctx->rdma = PCILIB_DMA_ENGINE_INVALID;
406
pcilib_error("Failed to initialize C2S channel of IPECamera DMA Engine (%u)", IPECAMERA_DMA_ADDRESS);
413
ctx->wdma = pcilib_find_dma_by_addr(vctx->pcilib, PCILIB_DMA_TO_DEVICE, IPECAMERA_DMA_ADDRESS);
414
if (ctx->wdma == PCILIB_DMA_ENGINE_INVALID) {
415
err = PCILIB_ERROR_NOTFOUND;
416
pcilib_error("The S2C channel of IPECamera DMA Engine (%u) is not found", IPECAMERA_DMA_ADDRESS);
418
err = pcilib_start_dma(vctx->pcilib, ctx->wdma, PCILIB_DMA_FLAGS_DEFAULT);
420
ctx->wdma = PCILIB_DMA_ENGINE_INVALID;
421
pcilib_error("Failed to initialize S2C channel of IPECamera DMA Engine (%u)", IPECAMERA_DMA_ADDRESS);
428
SET_REG(packet_len_reg, IPECAMERA_DMA_PACKET_LENGTH);
432
ipecamera_stop(vctx, PCILIB_EVENT_FLAGS_DEFAULT);
437
#ifndef IPECAMERA_BUG_POSTPONED_READ
438
err = pcilib_skip_dma(vctx->pcilib, ctx->rdma);
440
ipecamera_stop(vctx, PCILIB_EVENT_FLAGS_DEFAULT);
441
pcilib_error("Can't start grabbing, device continuously writes unexpected data using DMA engine");
444
#endif /* ! IPECAMERA_BUG_POSTPONED_READ */
446
if (vctx->params.autostop.duration) {
447
gettimeofday(&ctx->autostop.timestamp, NULL);
448
ctx->autostop.timestamp.tv_usec += vctx->params.autostop.duration % 1000000;
449
if (ctx->autostop.timestamp.tv_usec > 999999) {
450
ctx->autostop.timestamp.tv_sec += 1 + vctx->params.autostop.duration / 1000000;
451
ctx->autostop.timestamp.tv_usec -= 1000000;
453
ctx->autostop.timestamp.tv_sec += vctx->params.autostop.duration / 1000000;
457
if (vctx->params.autostop.max_events) {
458
ctx->autostop.evid = vctx->params.autostop.max_events;
461
if ((ctx->parse_data)&&(flags&PCILIB_EVENT_FLAG_PREPROCESS)) {
462
ctx->n_preproc = pcilib_get_cpu_count();
464
// it would be greate to detect hyperthreading cores and ban them
465
switch (ctx->n_preproc) {
467
case 2 ... 3: ctx->n_preproc -= 1; break;
468
default: ctx->n_preproc -= 2; break;
471
if ((vctx->params.parallel.max_threads)&&(vctx->params.parallel.max_threads < ctx->n_preproc))
472
ctx->n_preproc = vctx->params.parallel.max_threads;
474
ctx->preproc = (ipecamera_preprocessor_t*)malloc(ctx->n_preproc * sizeof(ipecamera_preprocessor_t));
476
ipecamera_stop(vctx, PCILIB_EVENT_FLAGS_DEFAULT);
477
pcilib_error("Unable to allocate memory for preprocessor contexts");
478
return PCILIB_ERROR_MEMORY;
481
memset(ctx->preproc, 0, ctx->n_preproc * sizeof(ipecamera_preprocessor_t));
483
err = pthread_mutex_init(&ctx->preproc_mutex, NULL);
485
ipecamera_stop(vctx, PCILIB_EVENT_FLAGS_DEFAULT);
486
pcilib_error("Failed to initialize event mutex");
487
return PCILIB_ERROR_FAILED;
489
ctx->preproc_mutex_destroy = 1;
492
ctx->run_preprocessors = 1;
493
for (i = 0; i < ctx->n_preproc; i++) {
494
ctx->preproc[i].i = i;
495
ctx->preproc[i].ipecamera = ctx;
496
err = pthread_create(&ctx->preproc[i].thread, NULL, ipecamera_preproc_thread, ctx->preproc + i);
498
err = PCILIB_ERROR_FAILED;
501
ctx->preproc[i].started = 1;
506
ipecamera_stop(vctx, PCILIB_EVENT_FLAGS_DEFAULT);
507
pcilib_error("Failed to schedule some of the preprocessor threads");
517
pthread_attr_init(&attr);
519
if (pthread_attr_setschedpolicy(&attr, SCHED_FIFO)) {
520
pcilib_warning("Can't schedule a real-time thread, you may consider running as root");
522
sched.sched_priority = sched_get_priority_max(SCHED_FIFO) - 1; // Let 1 priority for something really critcial
523
pthread_attr_setschedparam(&attr, &sched);
526
if (pthread_create(&ctx->rthread, &attr, &ipecamera_reader_thread, (void*)ctx)) {
528
ipecamera_stop(vctx, PCILIB_EVENT_FLAGS_DEFAULT);
529
err = PCILIB_ERROR_FAILED;
532
pthread_attr_destroy(&attr);
538
int ipecamera_stop(pcilib_context_t *vctx, pcilib_event_flags_t flags) {
542
ipecamera_t *ctx = (ipecamera_t*)vctx;
545
pcilib_error("IPECamera imaging is not initialized");
546
return PCILIB_ERROR_NOTINITIALIZED;
549
if (flags&PCILIB_EVENT_FLAG_STOP_ONLY) {
556
err = pthread_join(ctx->rthread, &retcode);
557
if (err) pcilib_error("Error joining the reader thread");
561
ctx->run_preprocessors = 0;
563
for (i = 0; i < ctx->n_preproc; i++) {
564
if (ctx->preproc[i].started) {
565
pthread_join(ctx->preproc[i].thread, &retcode);
566
ctx->preproc[i].started = 0;
570
if (ctx->preproc_mutex_destroy) {
571
pthread_mutex_destroy(&ctx->preproc_mutex);
572
ctx->preproc_mutex_destroy = 0;
579
if (ctx->frame_mutex_destroy) {
580
for (i = 0; i < ctx->frame_mutex_destroy; i++) {
581
pthread_rwlock_destroy(&ctx->frame[i].mutex);
583
ctx->frame_mutex_destroy = 0;
587
if (ctx->wdma != PCILIB_DMA_ENGINE_INVALID) {
588
pcilib_stop_dma(vctx->pcilib, ctx->wdma, PCILIB_DMA_FLAGS_DEFAULT);
589
ctx->wdma = PCILIB_DMA_ENGINE_INVALID;
592
if (ctx->rdma != PCILIB_DMA_ENGINE_INVALID) {
593
pcilib_stop_dma(vctx->pcilib, ctx->rdma, PCILIB_DMA_FLAGS_DEFAULT);
594
ctx->rdma = PCILIB_DMA_ENGINE_INVALID;
597
while (ctx->streaming) {
598
usleep(IPECAMERA_NOFRAME_SLEEP);
602
ufo_decoder_free(ctx->ipedec);
627
memset(&ctx->autostop, 0, sizeof(ipecamera_autostop_t));
630
ctx->reported_id = 0;
638
int ipecamera_trigger(pcilib_context_t *vctx, pcilib_event_t event, size_t trigger_size, void *trigger_data) {
640
pcilib_register_value_t value;
642
ipecamera_t *ctx = (ipecamera_t*)vctx;
643
pcilib_t *pcilib = vctx->pcilib;
646
pcilib_error("IPECamera imaging is not initialized");
647
return PCILIB_ERROR_NOTINITIALIZED;
650
if (!ctx->firmware) {
651
pcilib_error("Unsupported version of firmware (%lu)", ctx->firmware);
652
return PCILIB_ERROR_INVALID_REQUEST;
655
pcilib_sleep_until_deadline(&ctx->next_trigger);
657
GET_REG(num_frames_reg, value);
658
if (value == ctx->max_frames) {
659
return PCILIB_ERROR_BUSY;
664
GET_REG(status3_reg, value);
665
} while (value&0x20000000);
668
GET_REG(control_reg, value);
669
SET_REG(control_reg, value|IPECAMERA_FRAME_REQUEST);
670
usleep(IPECAMERA_WAIT_FRAME_RCVD_TIME);
671
//CHECK_REG(status_reg, IPECAMERA_EXPECTED_STATUS);
672
SET_REG(control_reg, value);
675
pcilib_calc_deadline(&ctx->next_trigger, IPECAMERA_NEXT_FRAME_DELAY);