27
30
#endif /* IPECAMERA_DEBUG */
30
#define IPECAMERA_BUG_EXTRA_DATA
31
#define IPECAMERA_BUG_MULTIFRAME_PACKETS
32
#define IPECAMERA_BUG_INCOMPLETE_PACKETS
34
#define IPECAMERA_DEFAULT_BUFFER_SIZE 64 //**< should be power of 2 */
35
#define IPECAMERA_RESERVE_BUFFERS 2 //**< Return Frame is Lost error, if requested frame will be overwritten after specified number of frames
36
#define IPECAMERA_SLEEP_TIME 250000 //**< Michele thinks 250 should be enough, but reset failing in this case */
37
#define IPECAMERA_NEXT_FRAME_DELAY 1000 //**< Michele requires 30000 to sync between End Of Readout and next Frame Req */
38
#define IPECAMERA_WAIT_FRAME_RCVD_TIME 0 //**< by Uros ,wait 6 ms */
39
#define IPECAMERA_NOFRAME_SLEEP 100
41
#define IPECAMERA_MAX_LINES 1088
42
#define IPECAMERA_EXPECTED_STATUS 0x08409FFFF
43
#define IPECAMERA_END_OF_SEQUENCE 0x1F001001
45
#define IPECAMERA_MAX_CHANNELS 16
46
#define IPECAMERA_PIXELS_PER_CHANNEL 128
47
#define IPECAMERA_WIDTH (IPECAMERA_MAX_CHANNELS * IPECAMERA_PIXELS_PER_CHANNEL)
50
#define IPECAMERA_HEIGHT 1088
51
#if IPECAMERA_HEIGHT < IPECAMERA_MAX_LINES
52
# undef IPECAMERA_MAX_LINES
53
# define IPECAMERA_MAX_LINES IPECAMERA_HEIGHT
57
//#define IPECAMERA_MEMORY
59
#define IPECAMERA_FRAME_REQUEST 0x1E9
60
#define IPECAMERA_READOUT_FLAG 0x200
61
#define IPECAMERA_READOUT 0x3E1
62
#define IPECAMERA_IDLE 0x1E1
63
#define IPECAMERA_START_INTERNAL_STIMULI 0x1F1
66
typedef uint32_t ipecamera_payload_t;
69
pcilib_event_id_t evid;
70
struct timeval timestamp;
71
} ipecamera_autostop_t;
74
pcilib_context_t event;
78
ipecamera_pixel_t *image;
81
pcilib_event_callback_t cb;
84
pcilib_event_id_t event_id;
85
pcilib_event_id_t reported_id;
87
pcilib_dma_engine_t rdma, wdma;
89
pcilib_register_t packet_len_reg;
90
pcilib_register_t control_reg, status_reg;
91
pcilib_register_t start_reg, end_reg;
92
pcilib_register_t n_lines_reg;
94
pcilib_register_t exposure_reg;
95
pcilib_register_t flip_reg;
97
int started; /**< Camera is in grabbing mode (start function is called) */
98
int streaming; /**< Camera is in streaming mode (we are within stream call) */
99
int parse_data; /**< Indicates if some processing of the data is required, otherwise only rawdata_callback will be called */
101
int run_reader; /**< Instructs the reader thread to stop processing */
102
int run_streamer; /**< Indicates request to stop streaming events and can be set by reader_thread upon exit or by user request */
103
ipecamera_autostop_t autostop;
105
struct timeval autostop_time;
107
size_t buffer_size; /**< How many images to store */
108
size_t buffer_pos; /**< Current image offset in the buffer, due to synchronization reasons should not be used outside of reader_thread */
109
size_t cur_size; /**< Already written part of data in bytes */
110
size_t raw_size; /**< Size of raw data in bytes */
111
size_t full_size; /**< Size of raw data including the padding */
112
size_t padded_size; /**< Size of buffer for raw data, including the padding for performance */
114
size_t image_size; /**< Size of a single image in bytes */
121
ipecamera_change_mask_t *cmask;
122
ipecamera_event_info_t *frame_info;
125
ipecamera_image_dimensions_t dim;
131
33
#define FIND_REG(var, bank, name) \
132
34
ctx->var = pcilib_find_register(pcilib, bank, name); \
133
35
if (ctx->var == PCILIB_REGISTER_INVALID) { \
334
// DS: Currently, on event_id overflow we are assuming the buffer is lost
335
static int ipecamera_resolve_event_id(ipecamera_t *ctx, pcilib_event_id_t evid) {
336
pcilib_event_id_t diff;
338
if (evid > ctx->event_id) {
339
diff = (((pcilib_event_id_t)-1) - ctx->event_id) + evid;
340
if (diff >= ctx->buffer_size) return -1;
342
diff = ctx->event_id - evid;
343
if (diff >= ctx->buffer_size) return -1;
346
// DS: Request buffer_size to be power of 2 and replace to shifts (just recompute in set_buffer_size)
347
return (evid - 1) % ctx->buffer_size;
350
static inline int ipecamera_new_frame(ipecamera_t *ctx) {
351
ctx->frame_info[ctx->buffer_pos].raw_size = ctx->cur_size;
353
if (ctx->cur_size < ctx->raw_size) ctx->frame_info[ctx->buffer_pos].info.flags |= PCILIB_EVENT_INFO_FLAG_BROKEN;
355
ctx->buffer_pos = (++ctx->event_id) % ctx->buffer_size;
358
ctx->frame_info[ctx->buffer_pos].info.type = PCILIB_EVENT0;
359
ctx->frame_info[ctx->buffer_pos].info.flags = 0;
360
ctx->frame_info[ctx->buffer_pos].image_ready = 0;
362
if ((ctx->event_id == ctx->autostop.evid)&&(ctx->event_id)) {
367
if (pcilib_check_deadline(&ctx->autostop.timestamp, PCILIB_DMA_TIMEOUT)) {
375
static uint32_t frame_magic[6] = { 0x51111111, 0x52222222, 0x53333333, 0x54444444, 0x55555555, 0x56666666 };
377
static int ipecamera_data_callback(void *user, pcilib_dma_flags_t flags, size_t bufsize, void *buf) {
380
#ifdef IPECAMERA_BUG_MULTIFRAME_PACKETS
381
size_t extra_data = 0;
382
#endif /* IPECAMERA_BUG_MULTIFRAME_PACKETS */
384
ipecamera_t *ctx = (ipecamera_t*)user;
386
if (!ctx->cur_size) {
387
#if defined(IPECAMERA_BUG_INCOMPLETE_PACKETS)||defined(IPECAMERA_BUG_MULTIFRAME_PACKETS)
389
for (startpos = 0; (startpos + 8) < bufsize; startpos++) {
390
if (!memcmp(buf + startpos, frame_magic, sizeof(frame_magic))) break;
397
#endif /* IPECAMERA_BUG_INCOMPLETE_PACKETS */
399
if ((bufsize >= 8)&&(!memcmp(buf, frame_magic, sizeof(frame_magic)))) {
401
// Not implemented in hardware yet
402
ctx->frame_info[ctx->buffer_pos].info.seqnum = ((uint32_t*)buf)[6] & 0xF0000000;
403
ctx->frame_info[ctx->buffer_pos].info.offset = ((uint32_t*)buf)[7] & 0xF0000000;
405
gettimeofday(&ctx->frame_info[ctx->buffer_pos].info.timestamp, NULL);
407
// pcilib_warning("Frame magic is not found, ignoring broken data...");
408
return PCILIB_STREAMING_CONTINUE;
412
#ifdef IPECAMERA_BUG_MULTIFRAME_PACKETS
413
if (ctx->cur_size + bufsize > ctx->raw_size) {
416
for (need = ctx->raw_size - ctx->cur_size; need < bufsize; need += sizeof(uint32_t)) {
417
if (*(uint32_t*)(buf + need) == frame_magic[0]) break;
420
if (need < bufsize) {
421
extra_data = bufsize - need;
426
// just rip of padding
427
bufsize = ctx->raw_size - ctx->cur_size;
429
#endif /* IPECAMERA_BUG_MULTIFRAME_PACKETS */
431
if (ctx->parse_data) {
432
if (ctx->cur_size + bufsize > ctx->full_size) {
433
pcilib_error("Unexpected event data, we are expecting at maximum (%zu) bytes, but (%zu) already read", ctx->full_size, ctx->cur_size + bufsize);
434
return -PCILIB_ERROR_TOOBIG;
437
memcpy(ctx->buffer + ctx->buffer_pos * ctx->padded_size + ctx->cur_size, buf, bufsize);
440
ctx->cur_size += bufsize;
441
// printf("%i: %i %i\n", ctx->buffer_pos, ctx->cur_size, bufsize);
443
if (ctx->cur_size >= ctx->full_size) eof = 1;
445
if (ctx->event.params.rawdata.callback) {
446
ctx->event.params.rawdata.callback(ctx->event_id, (pcilib_event_info_t*)(ctx->frame_info + ctx->buffer_pos), (eof?PCILIB_EVENT_FLAG_EOF:PCILIB_EVENT_FLAGS_DEFAULT), bufsize, buf, ctx->event.params.rawdata.user);
450
if (ipecamera_new_frame(ctx)) {
451
return PCILIB_STREAMING_STOP;
454
#ifdef IPECAMERA_BUG_MULTIFRAME_PACKETS
456
return ipecamera_data_callback(user, flags, extra_data, buf + bufsize);
458
#endif /* IPECAMERA_BUG_MULTIFRAME_PACKETS */
461
return PCILIB_STREAMING_REQ_FRAGMENT;
464
static void *ipecamera_reader_thread(void *user) {
466
ipecamera_t *ctx = (ipecamera_t*)user;
468
while (ctx->run_reader) {
469
err = pcilib_stream_dma(ctx->event.pcilib, ctx->rdma, 0, 0, PCILIB_DMA_FLAG_MULTIPACKET, PCILIB_DMA_TIMEOUT, &ipecamera_data_callback, user);
471
if (err == PCILIB_ERROR_TIMEOUT) {
472
if (ctx->cur_size > ctx->raw_size) ipecamera_new_frame(ctx);
473
#ifdef IPECAMERA_BUG_INCOMPLETE_PACKETS
474
else if (ctx->cur_size > 0) ipecamera_new_frame(ctx);
475
#endif /* IPECAMERA_BUG_INCOMPLETE_PACKETS */
476
if (pcilib_check_deadline(&ctx->autostop.timestamp, PCILIB_DMA_TIMEOUT)) {
480
usleep(IPECAMERA_NOFRAME_SLEEP);
481
} else pcilib_error("DMA error while reading IPECamera frames, error: %i", err);
482
} else printf("no error\n");
487
ctx->run_streamer = 0;
490
pcilib_error("partialy read frame after stop signal, %zu bytes in the buffer", ctx->cur_size);
495
237
int ipecamera_start(pcilib_context_t *vctx, pcilib_event_t event_mask, pcilib_event_flags_t flags) {
497
240
ipecamera_t *ctx = (ipecamera_t*)vctx;
498
241
pcilib_t *pcilib = vctx->pcilib;
552
296
ctx->buffer = malloc(ctx->padded_size * ctx->buffer_size);
553
297
if (!ctx->buffer) {
554
err = PCILIB_ERROR_MEMORY;
298
ipecamera_stop(vctx, PCILIB_EVENT_FLAGS_DEFAULT);
555
299
pcilib_error("Unable to allocate ring buffer (%lu bytes)", ctx->padded_size * ctx->buffer_size);
300
return PCILIB_ERROR_MEMORY;
559
303
ctx->image = (ipecamera_pixel_t*)malloc(ctx->image_size * ctx->buffer_size * sizeof(ipecamera_pixel_t));
560
304
if (!ctx->image) {
561
err = PCILIB_ERROR_MEMORY;
305
ipecamera_stop(vctx, PCILIB_EVENT_FLAGS_DEFAULT);
562
306
pcilib_error("Unable to allocate image buffer (%lu bytes)", ctx->image_size * ctx->buffer_size * sizeof(ipecamera_pixel_t));
307
return PCILIB_ERROR_MEMORY;
566
310
ctx->cmask = malloc(ctx->dim.height * ctx->buffer_size * sizeof(ipecamera_change_mask_t));
567
311
if (!ctx->cmask) {
568
err = PCILIB_ERROR_MEMORY;
312
ipecamera_stop(vctx, PCILIB_EVENT_FLAGS_DEFAULT);
569
313
pcilib_error("Unable to allocate change-mask buffer");
314
return PCILIB_ERROR_MEMORY;
573
ctx->frame_info = malloc(ctx->buffer_size * sizeof(ipecamera_event_info_t));
574
if (!ctx->frame_info) {
575
err = PCILIB_ERROR_MEMORY;
317
ctx->frame = (ipecamera_frame_t*)malloc(ctx->buffer_size * sizeof(ipecamera_frame_t));
319
ipecamera_stop(vctx, PCILIB_EVENT_FLAGS_DEFAULT);
576
320
pcilib_error("Unable to allocate frame-info buffer");
321
return PCILIB_ERROR_MEMORY;
324
memset(ctx->frame, 0, ctx->buffer_size * sizeof(ipecamera_frame_t));
326
for (i = 0; i < ctx->buffer_size; i++) {
327
err = pthread_rwlock_init(&ctx->frame[i].mutex, NULL);
331
ctx->frame_mutex_destroy = i;
334
ipecamera_stop(vctx, PCILIB_EVENT_FLAGS_DEFAULT);
335
pcilib_error("Initialization of rwlock mutexes for frame synchronization has failed");
336
return PCILIB_ERROR_FAILED;
580
339
ctx->ipedec = ufo_decoder_new(ctx->dim.height, ctx->dim.width, NULL, 0);
581
340
if (!ctx->ipedec) {
341
ipecamera_stop(vctx, PCILIB_EVENT_FLAGS_DEFAULT);
582
342
pcilib_error("Unable to initialize IPECamera decoder library");
583
343
return PCILIB_ERROR_FAILED;
645
405
ctx->autostop.evid = vctx->params.autostop.max_events;
408
if (flags&PCILIB_EVENT_FLAG_PREPROCESS) {
409
ctx->n_preproc = pcilib_get_cpu_count();
410
switch (ctx->n_preproc) {
412
case 2-3: ctx->n_preproc -= 1; break;
413
default: ctx->n_preproc -= 2; break;
416
ctx->preproc = (ipecamera_preprocessor_t*)malloc(ctx->n_preproc * sizeof(ipecamera_preprocessor_t));
418
ipecamera_stop(vctx, PCILIB_EVENT_FLAGS_DEFAULT);
419
pcilib_error("Unable to allocate memory for preprocessor contexts");
420
return PCILIB_ERROR_MEMORY;
423
memset(ctx->preproc, 0, ctx->n_preproc * sizeof(ipecamera_preprocessor_t));
425
err = pthread_mutex_init(&ctx->preproc_mutex, NULL);
427
ipecamera_stop(vctx, PCILIB_EVENT_FLAGS_DEFAULT);
428
pcilib_error("Failed to initialize event mutex");
429
return PCILIB_ERROR_FAILED;
431
ctx->preproc_mutex_destroy = 1;
434
ctx->run_preprocessors = 1;
435
for (i = 0; i < ctx->n_preproc; i++) {
436
ctx->preproc[i].i = i;
437
ctx->preproc[i].ipecamera = ctx;
438
err = pthread_create(&ctx->preproc[i].thread, NULL, ipecamera_preproc_thread, ctx->preproc + i);
440
err = PCILIB_ERROR_FAILED;
443
ctx->preproc[i].started = 1;
448
ipecamera_stop(vctx, PCILIB_EVENT_FLAGS_DEFAULT);
449
pcilib_error("Failed to schedule some of the preprocessor threads");
648
456
ctx->started = 1;
649
457
ctx->run_reader = 1;
651
459
pthread_attr_init(&attr);
653
461
if (pthread_attr_setschedpolicy(&attr, SCHED_FIFO)) {
769
int ipecamera_stream(pcilib_context_t *vctx, pcilib_event_callback_t callback, void *user) {
772
pcilib_event_id_t reported;
773
ipecamera_t *ctx = (ipecamera_t*)vctx;
777
struct timeval stream_stop;
780
pcilib_error("IPECamera imaging is not initialized");
781
return PCILIB_ERROR_NOTINITIALIZED;
785
ctx->run_streamer = 1;
788
err = ipecamera_start(vctx, PCILIB_EVENTS_ALL, PCILIB_EVENT_FLAGS_DEFAULT);
791
pcilib_error("IPECamera is not in grabbing state");
792
return PCILIB_ERROR_INVALID_STATE;
798
// This loop iterates while the generation
799
while ((ctx->run_streamer)||(ctx->reported_id != ctx->event_id)) {
800
while (ctx->reported_id != ctx->event_id) {
801
if ((ctx->event_id - ctx->reported_id) > (ctx->buffer_size - IPECAMERA_RESERVE_BUFFERS)) ctx->reported_id = ctx->event_id - (ctx->buffer_size - 1) - IPECAMERA_RESERVE_BUFFERS;
802
else ++ctx->reported_id;
804
callback(ctx->reported_id, (pcilib_event_info_t*)(ctx->frame_info + ((ctx->reported_id-1)%ctx->buffer_size)), user);
806
usleep(IPECAMERA_NOFRAME_SLEEP);
812
ipecamera_stop(vctx, PCILIB_EVENT_FLAGS_DEFAULT);
819
int ipecamera_next_event(pcilib_context_t *vctx, pcilib_event_t event_mask, pcilib_timeout_t timeout, pcilib_event_id_t *evid, pcilib_event_info_t **info) {
821
ipecamera_t *ctx = (ipecamera_t*)vctx;
824
pcilib_error("IPECamera imaging is not initialized");
825
return PCILIB_ERROR_NOTINITIALIZED;
829
pcilib_error("IPECamera is not in grabbing mode");
830
return PCILIB_ERROR_INVALID_REQUEST;
833
if (ctx->reported_id == ctx->event_id) {
835
pcilib_calc_deadline(&tv, timeout);
837
while ((pcilib_calc_time_to_deadline(&tv) > 0)&&(ctx->reported_id == ctx->event_id))
838
usleep(IPECAMERA_NOFRAME_SLEEP);
841
if (ctx->reported_id == ctx->event_id) return PCILIB_ERROR_TIMEOUT;
844
if ((ctx->event_id - ctx->reported_id) > (ctx->buffer_size - IPECAMERA_RESERVE_BUFFERS)) ctx->reported_id = ctx->event_id - (ctx->buffer_size - 1) - IPECAMERA_RESERVE_BUFFERS;
845
else ++ctx->reported_id;
847
if (evid) *evid = ctx->reported_id;
848
if (info) *info = (pcilib_event_info_t*)(ctx->frame_info + ((ctx->reported_id-1)%ctx->buffer_size));
854
inline static int ipecamera_decode_frame(ipecamera_t *ctx, pcilib_event_id_t event_id) {
859
int buf_ptr = (event_id - 1) % ctx->buffer_size;
861
if (!ctx->frame_info[buf_ptr].image_ready) {
862
if (ctx->frame_info[buf_ptr].info.flags&PCILIB_EVENT_INFO_FLAG_BROKEN) return PCILIB_ERROR_INVALID_DATA;
864
ufo_decoder_set_raw_data(ctx->ipedec, ctx->buffer + buf_ptr * ctx->padded_size, ctx->raw_size);
866
pixels = ctx->image + buf_ptr * ctx->image_size;
867
memset(ctx->cmask + ctx->buffer_pos * ctx->dim.height, 0, ctx->dim.height * sizeof(ipecamera_change_mask_t));
868
err = ufo_decoder_get_next_frame(ctx->ipedec, &pixels, &tmp, &tmp, ctx->cmask + ctx->buffer_pos * ctx->dim.height);
869
if (err) return PCILIB_ERROR_FAILED;
871
ctx->frame_info[buf_ptr].image_ready = 1;
873
if (ipecamera_resolve_event_id(ctx, event_id) < 0) {
874
ctx->frame_info[buf_ptr].image_ready = 0;
875
return PCILIB_ERROR_TIMEOUT;
882
void* ipecamera_get(pcilib_context_t *vctx, pcilib_event_id_t event_id, pcilib_event_data_type_t data_type, size_t arg_size, void *arg, size_t *size, void *data) {
886
ipecamera_t *ctx = (ipecamera_t*)vctx;
890
pcilib_error("IPECamera imaging is not initialized");
895
buf_ptr = ipecamera_resolve_event_id(ctx, event_id);
896
if (buf_ptr < 0) return NULL;
898
switch ((ipecamera_data_type_t)data_type) {
899
case IPECAMERA_RAW_DATA:
900
raw_size = ctx->frame_info[buf_ptr].raw_size;
902
if ((!size)||(*size < raw_size)) return NULL;
903
memcpy(data, ctx->buffer + buf_ptr * ctx->padded_size, raw_size);
904
if (ipecamera_resolve_event_id(ctx, event_id) < 0) return NULL;
908
if (size) *size = raw_size;
909
return ctx->buffer + buf_ptr * ctx->padded_size;
910
case IPECAMERA_IMAGE_DATA:
911
err = ipecamera_decode_frame(ctx, event_id);
912
if (err) return NULL;
915
if ((!size)||(*size < ctx->image_size * sizeof(ipecamera_pixel_t))) return NULL;
916
memcpy(data, ctx->image + buf_ptr * ctx->image_size, ctx->image_size * sizeof(ipecamera_pixel_t));
917
if (ipecamera_resolve_event_id(ctx, event_id) < 0) return NULL;
918
*size = ctx->image_size * sizeof(ipecamera_pixel_t);
922
if (size) *size = ctx->image_size * sizeof(ipecamera_pixel_t);
923
return ctx->image + buf_ptr * ctx->image_size;
924
case IPECAMERA_CHANGE_MASK:
925
err = ipecamera_decode_frame(ctx, event_id);
926
if (err) return NULL;
929
if ((!size)||(*size < ctx->dim.height * sizeof(ipecamera_change_mask_t))) return NULL;
930
memcpy(data, ctx->image + buf_ptr * ctx->dim.height, ctx->dim.height * sizeof(ipecamera_change_mask_t));
931
if (ipecamera_resolve_event_id(ctx, event_id) < 0) return NULL;
932
*size = ctx->dim.height * sizeof(ipecamera_change_mask_t);
937
if (size) *size = ctx->dim.height * sizeof(ipecamera_change_mask_t);
938
return ctx->cmask + buf_ptr * ctx->dim.height;
939
case IPECAMERA_DIMENSIONS:
940
if (size) *size = sizeof(ipecamera_image_dimensions_t);
942
case IPECAMERA_IMAGE_REGION:
943
case IPECAMERA_PACKED_IMAGE:
944
// Shall we return complete image or only changed parts?
945
case IPECAMERA_PACKED_LINE:
946
case IPECAMERA_PACKED_PAYLOAD:
947
pcilib_error("Support for data type (%li) is not implemented yet", data_type);
950
pcilib_error("Unknown data type (%li) is requested", data_type);
957
int ipecamera_return(pcilib_context_t *vctx, pcilib_event_id_t event_id, void *data) {
958
ipecamera_t *ctx = (ipecamera_t*)vctx;
961
pcilib_error("IPECamera imaging is not initialized");
962
return PCILIB_ERROR_NOTINITIALIZED;
966
if (ipecamera_resolve_event_id(ctx, event_id) < 0) {
967
return PCILIB_ERROR_NOTAVAILABLE;