/alps/ipecamera

To get this branch, use:
bzr branch http://suren.me/webbzr/alps/ipecamera

« back to all changes in this revision

Viewing changes to ipecamera/ipecamera.c

  • Committer: Suren A. Chilingaryan
  • Date: 2011-12-12 04:45:35 UTC
  • Revision ID: csa@dside.dyndns.org-20111212044535-6no1q7g230i8uvlv
multithread preprocessing of ipecamera frames and code reorganization

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
#define _IPECAMERA_IMAGE_C
2
2
#define _BSD_SOURCE
 
3
#define _GNU_SOURCE
3
4
 
4
5
#include <stdio.h>
5
6
#include <stdlib.h>
13
14
 
14
15
#include "../tools.h"
15
16
#include "../error.h"
 
17
#include "../event.h"
16
18
 
17
19
#include "pcilib.h"
18
 
 
 
20
#include "private.h"
19
21
#include "model.h"
20
 
#include "event.h"
21
 
#include "image.h"
 
22
#include "reader.h"
 
23
#include "events.h"
 
24
#include "data.h"
22
25
 
23
26
#include "dma/nwl_dma.h"
24
27
 
27
30
#endif /* IPECAMERA_DEBUG */
28
31
 
29
32
 
30
 
#define IPECAMERA_BUG_EXTRA_DATA
31
 
#define IPECAMERA_BUG_MULTIFRAME_PACKETS
32
 
#define IPECAMERA_BUG_INCOMPLETE_PACKETS
33
 
 
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
40
 
 
41
 
#define IPECAMERA_MAX_LINES 1088
42
 
#define IPECAMERA_EXPECTED_STATUS 0x08409FFFF
43
 
#define IPECAMERA_END_OF_SEQUENCE 0x1F001001
44
 
 
45
 
#define IPECAMERA_MAX_CHANNELS 16
46
 
#define IPECAMERA_PIXELS_PER_CHANNEL 128
47
 
#define IPECAMERA_WIDTH (IPECAMERA_MAX_CHANNELS * IPECAMERA_PIXELS_PER_CHANNEL)
48
 
 
49
 
/*
50
 
#define IPECAMERA_HEIGHT 1088
51
 
#if IPECAMERA_HEIGHT < IPECAMERA_MAX_LINES
52
 
# undef IPECAMERA_MAX_LINES
53
 
# define IPECAMERA_MAX_LINES IPECAMERA_HEIGHT
54
 
#endif 
55
 
*/
56
 
 
57
 
//#define IPECAMERA_MEMORY 
58
 
 
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
64
 
 
65
 
 
66
 
typedef uint32_t ipecamera_payload_t;
67
 
 
68
 
typedef struct {
69
 
    pcilib_event_id_t evid;
70
 
    struct timeval timestamp;
71
 
} ipecamera_autostop_t;
72
 
 
73
 
struct ipecamera_s {
74
 
    pcilib_context_t event;
75
 
    ufo_decoder ipedec;
76
 
 
77
 
    char *data;
78
 
    ipecamera_pixel_t *image;
79
 
    size_t size;
80
 
 
81
 
    pcilib_event_callback_t cb;
82
 
    void *cb_user;
83
 
 
84
 
    pcilib_event_id_t event_id;
85
 
    pcilib_event_id_t reported_id;
86
 
    
87
 
    pcilib_dma_engine_t rdma, wdma;
88
 
 
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;
93
 
    uint16_t line_reg;
94
 
    pcilib_register_t exposure_reg;
95
 
    pcilib_register_t flip_reg;
96
 
 
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 */
100
 
 
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;
104
 
 
105
 
    struct timeval autostop_time;
106
 
 
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 */
113
 
    
114
 
    size_t image_size;          /**< Size of a single image in bytes */
115
 
    
116
 
    int width, height;
117
 
 
118
 
    
119
 
//    void *raw_buffer;
120
 
    void *buffer;
121
 
    ipecamera_change_mask_t *cmask;
122
 
    ipecamera_event_info_t *frame_info;
123
 
    
124
 
 
125
 
    ipecamera_image_dimensions_t dim;
126
 
 
127
 
    pthread_t rthread;
128
 
};
129
 
 
130
 
 
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) { \
222
124
}
223
125
 
224
126
pcilib_dma_context_t *ipecamera_init_dma(pcilib_context_t *vctx) {
225
 
    ipecamera_t *ctx = (ipecamera_t*)vctx;
 
127
//    ipecamera_t *ctx = (ipecamera_t*)vctx;
226
128
    
227
129
    pcilib_model_description_t *model_info = pcilib_get_model_description(vctx->pcilib);
228
130
    if ((!model_info->dma_api)||(!model_info->dma_api->init)) {
331
233
    return 0;    
332
234
}
333
235
 
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;
337
 
 
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;
341
 
    } else {
342
 
        diff = ctx->event_id - evid;
343
 
        if (diff >= ctx->buffer_size) return -1;
344
 
    }
345
 
    
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;
348
 
}
349
 
 
350
 
static inline int ipecamera_new_frame(ipecamera_t *ctx) {
351
 
    ctx->frame_info[ctx->buffer_pos].raw_size = ctx->cur_size;
352
 
 
353
 
    if (ctx->cur_size < ctx->raw_size) ctx->frame_info[ctx->buffer_pos].info.flags |= PCILIB_EVENT_INFO_FLAG_BROKEN;
354
 
    
355
 
    ctx->buffer_pos = (++ctx->event_id) % ctx->buffer_size;
356
 
    ctx->cur_size = 0;
357
 
 
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;
361
 
 
362
 
    if ((ctx->event_id == ctx->autostop.evid)&&(ctx->event_id)) {
363
 
        ctx->run_reader = 0;
364
 
        return 1;
365
 
    }
366
 
        
367
 
    if (pcilib_check_deadline(&ctx->autostop.timestamp, PCILIB_DMA_TIMEOUT)) {
368
 
        ctx->run_reader = 0;
369
 
        return 1;
370
 
    }
371
 
    
372
 
    return 0;
373
 
}
374
 
 
375
 
static uint32_t frame_magic[6] = { 0x51111111, 0x52222222, 0x53333333, 0x54444444, 0x55555555, 0x56666666 };
376
 
 
377
 
static int ipecamera_data_callback(void *user, pcilib_dma_flags_t flags, size_t bufsize, void *buf) {
378
 
    int eof = 0;
379
 
 
380
 
#ifdef IPECAMERA_BUG_MULTIFRAME_PACKETS
381
 
    size_t extra_data = 0;
382
 
#endif /* IPECAMERA_BUG_MULTIFRAME_PACKETS */
383
 
 
384
 
    ipecamera_t *ctx = (ipecamera_t*)user;
385
 
 
386
 
    if (!ctx->cur_size) {
387
 
#if defined(IPECAMERA_BUG_INCOMPLETE_PACKETS)||defined(IPECAMERA_BUG_MULTIFRAME_PACKETS)
388
 
        size_t startpos;
389
 
        for (startpos = 0; (startpos + 8) < bufsize; startpos++) {
390
 
            if (!memcmp(buf + startpos, frame_magic, sizeof(frame_magic))) break;
391
 
        }
392
 
        
393
 
        if (startpos) {
394
 
            buf += startpos;
395
 
            bufsize -= startpos;
396
 
        }
397
 
#endif /* IPECAMERA_BUG_INCOMPLETE_PACKETS */
398
 
 
399
 
        if ((bufsize >= 8)&&(!memcmp(buf, frame_magic, sizeof(frame_magic)))) {
400
 
/*
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;
404
 
*/
405
 
            gettimeofday(&ctx->frame_info[ctx->buffer_pos].info.timestamp, NULL);
406
 
        } else {
407
 
//          pcilib_warning("Frame magic is not found, ignoring broken data...");
408
 
            return PCILIB_STREAMING_CONTINUE;
409
 
        }
410
 
    }
411
 
 
412
 
#ifdef IPECAMERA_BUG_MULTIFRAME_PACKETS
413
 
    if (ctx->cur_size + bufsize > ctx->raw_size) {
414
 
        size_t need;
415
 
        
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;
418
 
        }
419
 
        
420
 
        if (need < bufsize) {
421
 
            extra_data = bufsize - need;
422
 
            //bufsize = need;
423
 
            eof = 1;
424
 
        }
425
 
        
426
 
            // just rip of padding
427
 
        bufsize = ctx->raw_size - ctx->cur_size;
428
 
    }
429
 
#endif /* IPECAMERA_BUG_MULTIFRAME_PACKETS */
430
 
 
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;
435
 
        }
436
 
 
437
 
        memcpy(ctx->buffer + ctx->buffer_pos * ctx->padded_size +  ctx->cur_size, buf, bufsize);
438
 
    }
439
 
 
440
 
    ctx->cur_size += bufsize;
441
 
//    printf("%i: %i %i\n", ctx->buffer_pos, ctx->cur_size, bufsize);
442
 
 
443
 
    if (ctx->cur_size >= ctx->full_size) eof = 1;
444
 
 
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);
447
 
    }
448
 
    
449
 
    if (eof) {
450
 
        if (ipecamera_new_frame(ctx)) {
451
 
            return PCILIB_STREAMING_STOP;
452
 
        }
453
 
        
454
 
#ifdef IPECAMERA_BUG_MULTIFRAME_PACKETS
455
 
        if (extra_data) {
456
 
            return ipecamera_data_callback(user, flags, extra_data, buf + bufsize);
457
 
        }
458
 
#endif /* IPECAMERA_BUG_MULTIFRAME_PACKETS */
459
 
    }
460
 
 
461
 
    return PCILIB_STREAMING_REQ_FRAGMENT;
462
 
}
463
 
 
464
 
static void *ipecamera_reader_thread(void *user) {
465
 
    int err;
466
 
    ipecamera_t *ctx = (ipecamera_t*)user;
467
 
    
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);
470
 
        if (err) {
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)) {
477
 
                    ctx->run_reader = 0;
478
 
                    break;
479
 
                }
480
 
                usleep(IPECAMERA_NOFRAME_SLEEP);
481
 
            } else pcilib_error("DMA error while reading IPECamera frames, error: %i", err);
482
 
        } else printf("no error\n");
483
 
 
484
 
        //usleep(1000);
485
 
    }
486
 
    
487
 
    ctx->run_streamer = 0;
488
 
    
489
 
    if (ctx->cur_size)
490
 
        pcilib_error("partialy read frame after stop signal, %zu bytes in the buffer", ctx->cur_size);
491
 
 
492
 
    return NULL;
493
 
}
494
236
 
495
237
int ipecamera_start(pcilib_context_t *vctx, pcilib_event_t event_mask, pcilib_event_flags_t flags) {
 
238
    int i;
496
239
    int err = 0;
497
240
    ipecamera_t *ctx = (ipecamera_t*)vctx;
498
241
    pcilib_t *pcilib = vctx->pcilib;
527
270
 
528
271
 
529
272
    ctx->event_id = 0;
 
273
    ctx->preproc_id = 0;
530
274
    ctx->reported_id = 0;
531
275
    ctx->buffer_pos = 0;
532
276
    ctx->parse_data = (flags&PCILIB_EVENT_FLAG_RAW_DATA_ONLY)?0:1;
551
295
 
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);
556
 
        return err;
 
300
        return PCILIB_ERROR_MEMORY;
557
301
    }
558
302
 
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));
563
 
        return err;
 
307
        return PCILIB_ERROR_MEMORY;
564
308
    }
565
309
 
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");
570
 
        return err;
 
314
        return PCILIB_ERROR_MEMORY;
571
315
    }
572
316
 
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));
 
318
    if (!ctx->frame) {
 
319
        ipecamera_stop(vctx, PCILIB_EVENT_FLAGS_DEFAULT);
576
320
        pcilib_error("Unable to allocate frame-info buffer");
577
 
        return err;
 
321
        return PCILIB_ERROR_MEMORY;
 
322
    }
 
323
    
 
324
    memset(ctx->frame, 0, ctx->buffer_size * sizeof(ipecamera_frame_t));
 
325
    
 
326
    for (i = 0; i < ctx->buffer_size; i++) {
 
327
        err = pthread_rwlock_init(&ctx->frame[i].mutex, NULL);
 
328
        if (err) break;
 
329
    }
 
330
 
 
331
    ctx->frame_mutex_destroy = i;
 
332
 
 
333
    if (err) {
 
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;
578
337
    }
579
338
    
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;
584
344
    }
615
375
 
616
376
/*
617
377
    SET_REG(packet_len_reg, IPECAMERA_DMA_PACKET_LENGTH);
618
 
    if (err) return err;
619
378
*/
620
379
 
 
380
    if (err) {
 
381
        ipecamera_stop(vctx, PCILIB_EVENT_FLAGS_DEFAULT);
 
382
        return err;
 
383
    }
 
384
 
621
385
        // Clean DMA
622
386
    err = pcilib_skip_dma(vctx->pcilib, ctx->rdma);
623
387
    if (err) {
 
388
        ipecamera_stop(vctx, PCILIB_EVENT_FLAGS_DEFAULT);
624
389
        pcilib_error("Can't start grabbing, device continuously writes unexpected data using DMA engine");
625
390
        return err;
626
391
    }
627
392
 
628
 
    if (err) {
629
 
        ipecamera_stop(vctx, PCILIB_EVENT_FLAGS_DEFAULT);
630
 
        return err;
631
 
    }
632
 
 
633
393
    if (vctx->params.autostop.duration) {
634
394
        gettimeofday(&ctx->autostop.timestamp, NULL);
635
395
        ctx->autostop.timestamp.tv_usec += vctx->params.autostop.duration % 1000000;
645
405
        ctx->autostop.evid = vctx->params.autostop.max_events;
646
406
    }
647
407
    
 
408
    if (flags&PCILIB_EVENT_FLAG_PREPROCESS) {
 
409
        ctx->n_preproc = pcilib_get_cpu_count();
 
410
        switch (ctx->n_preproc) {
 
411
            case 1: break;
 
412
            case 2-3: ctx->n_preproc -= 1; break;
 
413
            default: ctx->n_preproc -= 2; break;
 
414
        }
 
415
        
 
416
        ctx->preproc = (ipecamera_preprocessor_t*)malloc(ctx->n_preproc * sizeof(ipecamera_preprocessor_t));
 
417
        if (!ctx->preproc) {
 
418
            ipecamera_stop(vctx, PCILIB_EVENT_FLAGS_DEFAULT);
 
419
            pcilib_error("Unable to allocate memory for preprocessor contexts");
 
420
            return PCILIB_ERROR_MEMORY;
 
421
        }
 
422
 
 
423
        memset(ctx->preproc, 0, ctx->n_preproc * sizeof(ipecamera_preprocessor_t));
 
424
 
 
425
        err = pthread_mutex_init(&ctx->preproc_mutex, NULL);
 
426
        if (err) {
 
427
            ipecamera_stop(vctx, PCILIB_EVENT_FLAGS_DEFAULT);
 
428
            pcilib_error("Failed to initialize event mutex");
 
429
            return PCILIB_ERROR_FAILED;
 
430
        }
 
431
        ctx->preproc_mutex_destroy = 1;
 
432
        
 
433
 
 
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);
 
439
            if (err) {
 
440
                err = PCILIB_ERROR_FAILED;
 
441
                break;
 
442
            } else {
 
443
                ctx->preproc[i].started = 1;
 
444
            }
 
445
        }
 
446
        
 
447
        if (err) {
 
448
            ipecamera_stop(vctx, PCILIB_EVENT_FLAGS_DEFAULT);
 
449
            pcilib_error("Failed to schedule some of the preprocessor threads");
 
450
            return err;
 
451
        }
 
452
    } else {
 
453
        ctx->n_preproc = 0;
 
454
    }
 
455
 
648
456
    ctx->started = 1;
649
457
    ctx->run_reader = 1;
650
 
    
 
458
 
651
459
    pthread_attr_init(&attr);
652
460
 
653
461
    if (pthread_attr_setschedpolicy(&attr, SCHED_FIFO)) {
660
468
    if (pthread_create(&ctx->rthread, &attr, &ipecamera_reader_thread, (void*)ctx)) {
661
469
        ctx->started = 0;
662
470
        ipecamera_stop(vctx, PCILIB_EVENT_FLAGS_DEFAULT);
663
 
        err = PCILIB_ERROR_THREAD;
 
471
        err = PCILIB_ERROR_FAILED;
664
472
    }
665
473
    
666
474
    pthread_attr_destroy(&attr);    
670
478
 
671
479
 
672
480
int ipecamera_stop(pcilib_context_t *vctx, pcilib_event_flags_t flags) {
 
481
    int i;
673
482
    int err;
674
483
    void *retcode;
675
484
    ipecamera_t *ctx = (ipecamera_t*)vctx;
683
492
        ctx->run_reader = 0;
684
493
        return 0;
685
494
    }
686
 
    
 
495
 
687
496
    if (ctx->started) {
688
497
        ctx->run_reader = 0;
689
498
        err = pthread_join(ctx->rthread, &retcode);
690
499
        if (err) pcilib_error("Error joining the reader thread");
691
500
    }
 
501
    
 
502
    if (ctx->preproc) {
 
503
        ctx->run_preprocessors = 0;
 
504
        
 
505
        for (i = 0; i < ctx->n_preproc; i++) {
 
506
            if (ctx->preproc[i].started) {
 
507
                pthread_join(ctx->preproc[i].thread, &retcode);
 
508
                ctx->preproc[i].started = 0;
 
509
            }
 
510
        }
692
511
 
 
512
        if (ctx->preproc_mutex_destroy) {
 
513
            pthread_mutex_destroy(&ctx->preproc_mutex);
 
514
            ctx->preproc_mutex_destroy = 0;
 
515
        }
 
516
        
 
517
        free(ctx->preproc);
 
518
        ctx->preproc = NULL;
 
519
    }
 
520
    
 
521
    if (ctx->frame_mutex_destroy) {
 
522
        for (i = 0; i < ctx->frame_mutex_destroy; i++) {
 
523
            pthread_rwlock_destroy(&ctx->frame[i].mutex);
 
524
        }
 
525
        ctx->frame_mutex_destroy = 0;
 
526
    }
 
527
    
693
528
    if (ctx->wdma != PCILIB_DMA_ENGINE_INVALID) {
694
529
        pcilib_stop_dma(vctx->pcilib, ctx->wdma, PCILIB_DMA_FLAGS_DEFAULT);
695
530
        ctx->wdma = PCILIB_DMA_ENGINE_INVALID;
705
540
        ctx->ipedec = NULL;
706
541
    }
707
542
 
708
 
    if (ctx->frame_info) {
709
 
        free(ctx->frame_info);
710
 
        ctx->frame_info = NULL;
 
543
    if (ctx->frame) {
 
544
        free(ctx->frame);
 
545
        ctx->frame = NULL;
711
546
    }
712
547
 
713
548
    if (ctx->cmask) {
749
584
        return PCILIB_ERROR_NOTINITIALIZED;
750
585
    }
751
586
 
752
 
    if (!ctx->started) {
753
 
        pcilib_error("Can't trigger while grabbing is not started");
754
 
        return PCILIB_ERROR_INVALID_REQUEST;
755
 
    }
756
 
 
757
587
    SET_REG(control_reg, IPECAMERA_FRAME_REQUEST|IPECAMERA_READOUT_FLAG);
758
588
    usleep(IPECAMERA_WAIT_FRAME_RCVD_TIME);
759
589
    CHECK_REG(status_reg, IPECAMERA_EXPECTED_STATUS);
765
595
 
766
596
    return 0;
767
597
}
768
 
 
769
 
int ipecamera_stream(pcilib_context_t *vctx, pcilib_event_callback_t callback, void *user) {
770
 
    int err = 0;
771
 
    int do_stop = 0;
772
 
    pcilib_event_id_t reported;
773
 
    ipecamera_t *ctx = (ipecamera_t*)vctx;
774
 
 
775
 
    size_t events = 0;
776
 
 
777
 
    struct timeval stream_stop;
778
 
 
779
 
    if (!ctx) {
780
 
        pcilib_error("IPECamera imaging is not initialized");
781
 
        return PCILIB_ERROR_NOTINITIALIZED;
782
 
    }
783
 
 
784
 
    ctx->streaming = 1;
785
 
    ctx->run_streamer = 1;
786
 
 
787
 
    if (!ctx->started) {
788
 
        err = ipecamera_start(vctx, PCILIB_EVENTS_ALL, PCILIB_EVENT_FLAGS_DEFAULT);
789
 
        if (err) {
790
 
            ctx->streaming = 0;
791
 
            pcilib_error("IPECamera is not in grabbing state");
792
 
            return PCILIB_ERROR_INVALID_STATE;
793
 
        }
794
 
        
795
 
        do_stop = 1;
796
 
    }
797
 
    
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;
803
 
 
804
 
            callback(ctx->reported_id, (pcilib_event_info_t*)(ctx->frame_info + ((ctx->reported_id-1)%ctx->buffer_size)), user);
805
 
        }
806
 
        usleep(IPECAMERA_NOFRAME_SLEEP);
807
 
    }
808
 
 
809
 
    ctx->streaming = 0;
810
 
 
811
 
    if (do_stop) {
812
 
        ipecamera_stop(vctx, PCILIB_EVENT_FLAGS_DEFAULT);
813
 
    }
814
 
    
815
 
 
816
 
    return err;
817
 
}
818
 
 
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) {
820
 
    struct timeval tv;
821
 
    ipecamera_t *ctx = (ipecamera_t*)vctx;
822
 
 
823
 
    if (!ctx) {
824
 
        pcilib_error("IPECamera imaging is not initialized");
825
 
        return PCILIB_ERROR_NOTINITIALIZED;
826
 
    }
827
 
 
828
 
    if (!ctx->started) {
829
 
        pcilib_error("IPECamera is not in grabbing mode");
830
 
        return PCILIB_ERROR_INVALID_REQUEST;
831
 
    }
832
 
 
833
 
    if (ctx->reported_id == ctx->event_id) {
834
 
        if (timeout) {
835
 
            pcilib_calc_deadline(&tv, timeout);
836
 
            
837
 
            while ((pcilib_calc_time_to_deadline(&tv) > 0)&&(ctx->reported_id == ctx->event_id))
838
 
                usleep(IPECAMERA_NOFRAME_SLEEP);
839
 
        }
840
 
        
841
 
        if (ctx->reported_id == ctx->event_id) return PCILIB_ERROR_TIMEOUT;
842
 
    }
843
 
 
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;
846
 
 
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));
849
 
    
850
 
    return 0;
851
 
}
852
 
 
853
 
 
854
 
inline static int ipecamera_decode_frame(ipecamera_t *ctx, pcilib_event_id_t event_id) {
855
 
    int err;
856
 
    uint32_t tmp;
857
 
    uint16_t *pixels;
858
 
    
859
 
    int buf_ptr = (event_id - 1) % ctx->buffer_size;
860
 
    
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;
863
 
        
864
 
        ufo_decoder_set_raw_data(ctx->ipedec, ctx->buffer + buf_ptr * ctx->padded_size, ctx->raw_size);
865
 
                
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;
870
 
            
871
 
        ctx->frame_info[buf_ptr].image_ready = 1;
872
 
 
873
 
        if (ipecamera_resolve_event_id(ctx, event_id) < 0) {
874
 
            ctx->frame_info[buf_ptr].image_ready = 0;
875
 
            return PCILIB_ERROR_TIMEOUT;
876
 
        }
877
 
    }
878
 
    
879
 
    return 0;
880
 
}
881
 
 
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) {
883
 
    int err;
884
 
    int buf_ptr;
885
 
    size_t raw_size;
886
 
    ipecamera_t *ctx = (ipecamera_t*)vctx;
887
 
    uint16_t *pixels;
888
 
 
889
 
    if (!ctx) {
890
 
        pcilib_error("IPECamera imaging is not initialized");
891
 
        return NULL;
892
 
    }
893
 
    
894
 
 
895
 
    buf_ptr = ipecamera_resolve_event_id(ctx, event_id);
896
 
    if (buf_ptr < 0) return NULL;
897
 
    
898
 
    switch ((ipecamera_data_type_t)data_type) {
899
 
        case IPECAMERA_RAW_DATA:
900
 
            raw_size = ctx->frame_info[buf_ptr].raw_size;
901
 
            if (data) {
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;
905
 
                *size = raw_size;
906
 
                return data;
907
 
            }
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;
913
 
 
914
 
            if (data) {
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);
919
 
                return data;
920
 
            }
921
 
        
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;
927
 
 
928
 
            if (data) {
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);
933
 
 
934
 
                return data;
935
 
            }
936
 
 
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);
941
 
            return &ctx->dim;
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);
948
 
            return NULL;
949
 
        default:
950
 
            pcilib_error("Unknown data type (%li) is requested", data_type);
951
 
            return NULL;
952
 
    }
953
 
}
954
 
 
955
 
 
956
 
 
957
 
int ipecamera_return(pcilib_context_t *vctx, pcilib_event_id_t event_id, void *data) {
958
 
    ipecamera_t *ctx = (ipecamera_t*)vctx;
959
 
 
960
 
    if (!ctx) {
961
 
        pcilib_error("IPECamera imaging is not initialized");
962
 
        return PCILIB_ERROR_NOTINITIALIZED;
963
 
 
964
 
    }
965
 
 
966
 
    if (ipecamera_resolve_event_id(ctx, event_id) < 0) {
967
 
        return PCILIB_ERROR_NOTAVAILABLE;
968
 
    }
969
 
 
970
 
    return 0;
971
 
}