diff options
author | Suren A. Chilingaryan <csa@dside.dyndns.org> | 2011-12-09 07:12:44 +0100 |
---|---|---|
committer | Suren A. Chilingaryan <csa@dside.dyndns.org> | 2011-12-09 07:12:44 +0100 |
commit | 1ac7751e5b9df5f09500aca9e5b34bb9cfa912b4 (patch) | |
tree | 42e3705aa8b20fc7f03025cb83ae2f928350174d | |
parent | c3812d3569aa98e23953eea323d980912580e659 (diff) | |
download | ipecamera-1ac7751e5b9df5f09500aca9e5b34bb9cfa912b4.tar.gz ipecamera-1ac7751e5b9df5f09500aca9e5b34bb9cfa912b4.tar.bz2 ipecamera-1ac7751e5b9df5f09500aca9e5b34bb9cfa912b4.tar.xz ipecamera-1ac7751e5b9df5f09500aca9e5b34bb9cfa912b4.zip |
Initial support of event streaming in cli
-rw-r--r-- | BUGS | 18 | ||||
-rw-r--r-- | ToDo | 9 | ||||
-rw-r--r-- | cli.c | 221 | ||||
-rw-r--r-- | ipecamera/image.c | 83 | ||||
-rw-r--r-- | ipecamera/ipecamera.h | 4 | ||||
-rw-r--r-- | pci.h | 2 | ||||
-rw-r--r-- | pcilib.h | 19 | ||||
-rw-r--r-- | tools.c | 46 | ||||
-rw-r--r-- | tools.h | 9 |
9 files changed, 327 insertions, 84 deletions
@@ -0,0 +1,18 @@ +IPECamera Hardware Bugs +======================= + 1. Strange sequence writting CMOSIS registers + 2. Extra 8 byte padding in the end of frames + 3. Solve the conflict between DMA packet_length register and FPGA registers + + +Incomplete Frames +----------------- + If I'm trying to stream the data, the camera from time to time returns + incomplete frames. The provided part of the frame is coherent. But instead + of at least 3063824 bytes (just full frame without padding, normally I get + more due to the padding) I get only 3063808 bytes. This number 3063808 looks + like to be constant. + + If I send another frame request, however, it looks I got the missing data with + the next frame. + @@ -15,11 +15,16 @@ Normal Priority (it would make just few things a bit easier) 2. Support FIFO reads/writes from/to registers 3. Provide OR and AND operations on registers in cli 4. Support writting a data from a binary file in cli - 5. Use bus-addresses instead of physcial addresses for DMA - + 5. Use bus-addresses instead of physcial addresses for DMA + 6. Instead of waiting in the end of trigger function to satisfy delay required + between consequent triggers, measure the timestamp when next trigger is + allowed and check it in the beginning of the trigger function. + Low Priority (only as generalization for other projects) ============ 1. XML configurations describing registers (and DMA engines?) 2. Access register/bank lookups using hash tables 3. Support for Network Registers and Network DMA 4. Define a syntax for register dependencies / delays (?) + +
\ No newline at end of file @@ -1,4 +1,5 @@ #define _POSIX_C_SOURCE 200112L +#define _BSD_SOURCE #include <stdio.h> #include <stdlib.h> @@ -241,14 +242,15 @@ void Usage(int argc, char *argv[], const char *format, ...) { " -a [fifo|dma]<bits> - Access type and bits per word (default: 32)\n" " -e <l|b> - Endianess Little/Big (default: host)\n" " -o <file> - Append output to file (default: stdout)\n" -" -t <timeout> - Timeout in microseconds\n" +" -t <timeout|unlimited> - Timeout in microseconds\n" "\n" " Event Options:\n" " --event <evt> - Specifies event for trigger and grab modes\n" " --data <type> - Data type to request for the events\n" -" --run-time <us> - Grab/trigger events during the specified time\n" -" --trigger-rate <tps> - Generate tps triggers per second\n" -" --trigger-time <us> - Specifies delay between triggers in microseconds\n" +" --run-time <us> - Limit time to grab/trigger events\n" +" -t <timeout|unlimited> - Timeout to stop if no events triggered\n" +" --trigger-rate <tps> - Generate tps triggers per second\n" +" --trigger-time <us> - Specifies delay between triggers (us)\n" " -s <num|unlimited> - Number of events to grab and trigger\n" " --format [type] - Specifies how event data should be stored\n" " raw - Just write all events sequentially\n" @@ -1072,19 +1074,41 @@ typedef struct { pcilib_event_data_type_t data; FILE *output; + pcilib_timeout_t timeout; size_t run_time; size_t trigger_time; + size_t max_triggers; + + int event_pending; /**< Used to detect that we have read previously triggered event */ + int trigger_thread_started; /**< Indicates that trigger thread is ready and we can't procced to start event recording */ + int started; /**< Indicates that recording is started */ int run_flag; + + struct timeval last_frame; + size_t trigger_count; + size_t frame_count; + size_t broken_count; + + struct timeval stop_time; } GRABContext; int GrabCallback(pcilib_event_id_t event_id, pcilib_event_info_t *info, void *user) { -/* int err; + int err; void *data; size_t size, written; GRABContext *ctx = (GRABContext*)user; pcilib_t *handle = ctx->handle; + + gettimeofday(&ctx->last_frame, NULL); + + ctx->event_pending = 0; + ctx->frame_count++; + + if (info->flags&PCILIB_EVENT_INFO_FLAG_BROKEN) ctx->broken_count++; + +/* FILE *o = ctx->output; data = pcilib_get_data(handle, ctx->event, ctx->data, &size); @@ -1109,47 +1133,171 @@ int raw_data(pcilib_event_id_t event_id, pcilib_event_info_t *info, pcilib_event // printf("%i\n", event_id); } + void *Trigger(void *user) { + struct timeval start; + GRABContext *ctx = (GRABContext*)user; + size_t trigger_time = ctx->trigger_time; + size_t max_triggers = ctx->max_triggers; - pcilib_trigger(ctx->handle, PCILIB_EVENT0, 0, NULL); - usleep(3000); - pcilib_trigger(ctx->handle, PCILIB_EVENT0, 0, NULL); + ctx->trigger_thread_started = 1; + ctx->event_pending = 1; + while (!ctx->started); + + gettimeofday(&start, NULL); + do { + pcilib_trigger(ctx->handle, PCILIB_EVENT0, 0, NULL); + if ((++ctx->trigger_count == max_triggers)&&(max_triggers)) break; + + if (trigger_time) { + pcilib_add_timeout(&start, trigger_time); + if ((ctx->stop_time.tv_sec)&&(pcilib_timecmp(&start, &ctx->stop_time)>0)) break; + pcilib_sleep_until_deadline(&start); + } else { + while ((ctx->event_pending)&&(ctx->run_flag)) usleep(10); + ctx->event_pending = 1; + } + } while (ctx->run_flag); + + ctx->trigger_thread_started = 0; + return NULL; } -int TriggerAndGrab(pcilib_t *handle, GRAB_MODE grab_mode, const char *event, const char *data_type, size_t num, size_t run_time, size_t trigger_time, PARTITION partition, FORMAT format, size_t buffer_size, FILE *ofile) { +void *Monitor(void *user) { + struct timeval deadline; + + GRABContext *ctx = (GRABContext*)user; + pcilib_timeout_t timeout = ctx->timeout; + + if (timeout == PCILIB_TIMEOUT_INFINITE) timeout = 0; + +// while (!ctx->started); + + if (timeout) { + memcpy(&deadline, &ctx->last_frame, sizeof(struct timeval)); + pcilib_add_timeout(&deadline, timeout); + } + + while (ctx->run_flag) { + if (timeout) { + if (pcilib_calc_time_to_deadline(&deadline) == 0) { + memcpy(&deadline, &ctx->last_frame, sizeof(struct timeval)); + pcilib_add_timeout(&deadline, timeout); + + if (pcilib_calc_time_to_deadline(&deadline) == 0) { + pcilib_stop(ctx->handle, PCILIB_EVENT_FLAG_STOP_ONLY); + break; + } + } + } + + usleep(100000); + } + + return NULL; +} + +int TriggerAndGrab(pcilib_t *handle, GRAB_MODE grab_mode, const char *event, const char *data_type, size_t num, size_t run_time, size_t trigger_time, pcilib_timeout_t timeout, PARTITION partition, FORMAT format, size_t buffer_size, FILE *ofile) { int err; GRABContext ctx; void *data = NULL; size_t size, written; + pthread_t monitor_thread; pthread_t trigger_thread; + pthread_attr_t attr; + struct sched_param sched; + + struct timeval start, end; + pcilib_event_flags_t flags; ctx.handle = handle; ctx.output = ofile; ctx.event = PCILIB_EVENT0; ctx.run_time = run_time; - ctx.trigger_time = trigger_time; + ctx.timeout = timeout; + ctx.frame_count = 0; + + ctx.started = 0; + ctx.trigger_thread_started = 0; ctx.run_flag = 1; - // ignoring event for now - pcilib_configure_autostop(handle, 2, 1000000);//PCILIB_TIMEOUT_TRIGGER); + memset(&ctx.stop_time, 0, sizeof(struct timeval)); + +// printf("Limits: %lu %lu %lu\n", num, run_time, timeout); + pcilib_configure_autostop(handle, num, run_time);//PCILIB_TIMEOUT_TRIGGER); pcilib_configure_rawdata_callback(handle, &raw_data, NULL); + + flags = PCILIB_EVENT_FLAGS_DEFAULT; + // PCILIB_EVENT_FLAG_RAW_DATA_ONLY + + if (grab_mode&GRAB_MODE_TRIGGER) { + if (!trigger_time) { + // Otherwise, we will trigger next event after previous one is read + if (((grab_mode&GRAB_MODE_GRAB) == 0)&&((flags&PCILIB_EVENT_FLAG_RAW_DATA_ONLY)==0)) trigger_time = PCILIB_TRIGGER_TIMEOUT; + } + + ctx.max_triggers = num; + ctx.trigger_count = 0; + ctx.trigger_time = trigger_time; + + // We don't really care if RT priority is imposible + pthread_attr_init(&attr); + if (!pthread_attr_setschedpolicy(&attr, SCHED_FIFO)) { + sched.sched_priority = sched_get_priority_min(SCHED_FIFO); + pthread_attr_setschedparam(&attr, &sched); + } + + // Start triggering thread and wait until it is schedulled + if (pthread_create(&trigger_thread, &attr, Trigger, (void*)&ctx)) + Error("Error spawning trigger thread"); + + while (!ctx.trigger_thread_started) usleep(10); + } + + gettimeofday(&start, NULL); + + if (grab_mode&GRAB_MODE_GRAB) { + err = pcilib_start(handle, PCILIB_EVENTS_ALL, PCILIB_EVENT_FLAGS_DEFAULT); + if (err) Error("Failed to start event engine, error %i", err); + } + + ctx.started = 1; + + if (run_time) { + ctx.stop_time.tv_usec = start.tv_usec + run_time%1000000; + if (ctx.stop_time.tv_usec > 999999) { + ctx.stop_time.tv_usec -= 1000000; + __sync_synchronize(); + ctx.stop_time.tv_sec = start.tv_sec + 1 + run_time / 1000000; + } else { + __sync_synchronize(); + ctx.stop_time.tv_sec = start.tv_sec + run_time / 1000000; + } + } + + memcpy(&ctx.last_frame, &start, sizeof(struct timeval)); + if (pthread_create(&monitor_thread, NULL, Monitor, (void*)&ctx)) + Error("Error spawning monitoring thread"); - err = pcilib_start(handle, PCILIB_EVENTS_ALL, PCILIB_EVENT_FLAGS_DEFAULT); - if (err) Error("Failed to start event engine, error %i", err); + if (grab_mode&GRAB_MODE_GRAB) { + err = pcilib_stream(handle, &GrabCallback, &ctx); + if (err) Error("Error streaming events, error %i", err); + } - if (pthread_create(&trigger_thread, NULL, Trigger, (void*)&ctx)) - Error("Error starting trigger thread"); + ctx.run_flag = 0; -// sleep(1); - err = pcilib_stream(handle, &GrabCallback, &ctx); - if (err) Error("Error streaming events, error %i", err); + if (grab_mode&GRAB_MODE_TRIGGER) { + while (ctx.trigger_thread_started) usleep(10); + } - pcilib_stop(handle, PCILIB_EVENT_FLAGS_DEFAULT); + if (grab_mode&GRAB_MODE_GRAB) { + pcilib_stop(handle, PCILIB_EVENT_FLAGS_DEFAULT); + } /* err = pcilib_grab(handle, PCILIB_EVENTS_ALL, &size, &data, PCILIB_TIMEOUT_TRIGGER); @@ -1157,8 +1305,14 @@ int TriggerAndGrab(pcilib_t *handle, GRAB_MODE grab_mode, const char *event, con Error("Grabbing event is failed"); } */ - ctx.run_flag = 0; - pthread_join(trigger_thread, NULL); + + pthread_join(monitor_thread, NULL); + + if (grab_mode&GRAB_MODE_TRIGGER) { + pthread_join(trigger_thread, NULL); + } + + // print information return 0; } @@ -1675,6 +1829,7 @@ int main(int argc, char **argv) { int size_set = 0; int timeout_set = 0; + int run_time_set = 0; while ((c = getopt_long(argc, argv, "hqilr::w::g::d:m:t:b:a:s:e:o:", long_options, NULL)) != (unsigned char)-1) { extern int optind; @@ -1887,7 +2042,7 @@ int main(int argc, char **argv) { if (strcasecmp(optarg, "unlimited")) Usage(argc, argv, "Invalid size is specified (%s)", optarg); else - size = (size_t)-1; + size = 0;//(size_t)-1; size_set = 1; break; @@ -1903,7 +2058,10 @@ int main(int argc, char **argv) { break; case OPT_TIMEOUT: if ((!isnumber(optarg))||(sscanf(optarg, "%zu", &timeout) != 1)) - Usage(argc, argv, "Invalid timeout is specified (%s)", optarg); + if (strcasecmp(optarg, "unlimited")) + Usage(argc, argv, "Invalid timeout is specified (%s)", optarg); + else + timeout = PCILIB_TIMEOUT_INFINITE; timeout_set = 1; break; case OPT_OUTPUT: @@ -1921,7 +2079,11 @@ int main(int argc, char **argv) { break; case OPT_RUN_TIME: if ((!isnumber(optarg))||(sscanf(optarg, "%zu", &run_time) != 1)) - Usage(argc, argv, "Invalid timeout is specified (%s)", optarg); + if (strcasecmp(optarg, "unlimited")) + Usage(argc, argv, "Invalid run-time is specified (%s)", optarg); + else + run_time = 0; + run_time_set = 1; break; case OPT_TRIGGER_TIME: if ((!isnumber(optarg))||(sscanf(optarg, "%zu", &trigger_time) != 1)) @@ -1931,7 +2093,7 @@ int main(int argc, char **argv) { if ((!isnumber(optarg))||(sscanf(optarg, "%zu", &ztmp) != 1)) Usage(argc, argv, "Invalid trigger-rate is specified (%s)", optarg); - trigger_time = 1000000 / ztmp + (1000000 % ztmp)?1:0; + trigger_time = (1000000 / ztmp) + ((1000000 % ztmp)?1:0); break; case OPT_BUFFER: if (optarg) num_offset = optarg; @@ -2099,6 +2261,11 @@ int main(int argc, char **argv) { else if (!strcmp(fsname, "raw")) partition = PARTITION_RAW; } } + + if (!timeout_set) { + if (run_time) timeout = PCILIB_TIMEOUT_INFINITE; + else timeout = PCILIB_EVENT_TIMEOUT; + } } if (mode != MODE_GRAB) { @@ -2167,7 +2334,7 @@ int main(int argc, char **argv) { pcilib_reset(handle); break; case MODE_GRAB: - TriggerAndGrab(handle, grab_mode, event, data_type, size, run_time, trigger_time, partition, format, buffer, ofile); + TriggerAndGrab(handle, grab_mode, event, data_type, size, run_time, trigger_time, timeout, partition, format, buffer, ofile); break; case MODE_LIST_DMA: ListDMA(handle, fpga_device, model_info); diff --git a/ipecamera/image.c b/ipecamera/image.c index ad99246..3b3c9df 100644 --- a/ipecamera/image.c +++ b/ipecamera/image.c @@ -70,9 +70,6 @@ int ipecamera_channel_order[IPECAMERA_MAX_CHANNELS] = { 15, 13, 14, 12, 10, 8, 1 typedef uint32_t ipecamera_payload_t; -typedef struct { - pcilib_event_info_t info; -} ipecamera_event_info_t; typedef struct { pcilib_event_id_t evid; @@ -114,14 +111,9 @@ struct ipecamera_s { ipecamera_autostop_t autostop; struct timeval autostop_time; -// int ready; /**< New frame is ready */ -// int check_time; /**< Streaming is time-limited */ size_t buffer_size; /**< How many images to store */ size_t buffer_pos; /**< Current image offset in the buffer, due to synchronization reasons should not be used outside of reader_thread */ -// size_t stream_count; /**< Number of images read so far */ -// size_t stream_max; /**< Maximum number of images to read */ -// struct timeval stream_stop; /**< Time to stop streaming */ size_t cur_size; /**< Already written part of data in bytes */ size_t raw_size; /**< Size of raw data in bytes */ size_t full_size; /**< Size of raw data including the padding */ @@ -373,10 +365,14 @@ static int ipecamera_resolve_event_id(ipecamera_t *ctx, pcilib_event_id_t evid) } static inline int ipecamera_new_frame(ipecamera_t *ctx) { + ctx->frame_info[ctx->buffer_pos].raw_size =ctx->cur_size; + if (ctx->cur_size < ctx->raw_size) ctx->frame_info[ctx->buffer_pos].info.flags |= PCILIB_EVENT_INFO_FLAG_BROKEN; + ctx->buffer_pos = (++ctx->event_id) % ctx->buffer_size; ctx->cur_size = 0; ctx->frame_info[ctx->buffer_pos].info.type = PCILIB_EVENT0; + ctx->frame_info[ctx->buffer_pos].info.flags = 0; // memset(ctx->cmask + ctx->buffer_pos * ctx->dim.height, 0, ctx->dim.height * sizeof(ipecamera_change_mask_t)); if ((ctx->event_id == ctx->autostop.evid)&&(ctx->event_id)) { @@ -384,7 +380,7 @@ static inline int ipecamera_new_frame(ipecamera_t *ctx) { return 1; } - if (check_deadline(&ctx->autostop.timestamp, PCILIB_DMA_TIMEOUT)) { + if (pcilib_check_deadline(&ctx->autostop.timestamp, PCILIB_DMA_TIMEOUT)) { ctx->run_reader = 0; return 1; } @@ -395,6 +391,7 @@ static inline int ipecamera_new_frame(ipecamera_t *ctx) { static uint32_t frame_magic[6] = { 0x51111111, 0x52222222, 0x53333333, 0x54444444, 0x55555555, 0x56666666 }; #define IPECAMERA_BUG_MULTIFRAME_PACKETS +#define IPECAMERA_BUG_INCOMPLETE_PACKETS static int ipecamera_data_callback(void *user, pcilib_dma_flags_t flags, size_t bufsize, void *buf) { int eof = 0; @@ -405,12 +402,28 @@ static int ipecamera_data_callback(void *user, pcilib_dma_flags_t flags, size_t ipecamera_t *ctx = (ipecamera_t*)user; + if (!ctx->cur_size) { +#if defined(IPECAMERA_BUG_INCOMPLETE_PACKETS)||defined(IPECAMERA_BUG_MULTIFRAME_PACKETS) + size_t startpos; + for (startpos = 0; (startpos + 8) < bufsize; startpos++) { + if (!memcmp(buf + startpos, frame_magic, sizeof(frame_magic))) break; + } + + if (startpos) { + buf += startpos; + bufsize -= startpos; + } +#endif /* IPECAMERA_BUG_INCOMPLETE_PACKETS */ - if ((bufsize >= 8)&&(!memcmp(buf, frame_magic, sizeof(frame_magic)))) { - //if (ctx->cur_size) ipecamera_new_frame(ctx); - ctx->frame_info[ctx->buffer_pos].info.seqnum = ((uint32_t*)buf)[6] & 0xF0000000; - ctx->frame_info[ctx->buffer_pos].info.offset = ((uint32_t*)buf)[7] & 0xF0000000; - gettimeofday(&ctx->frame_info[ctx->buffer_pos].info.timestamp, NULL); + if ((bufsize >= 8)&&(!memcmp(buf, frame_magic, sizeof(frame_magic)))) { + //if (ctx->cur_size) ipecamera_new_frame(ctx); + ctx->frame_info[ctx->buffer_pos].info.seqnum = ((uint32_t*)buf)[6] & 0xF0000000; + ctx->frame_info[ctx->buffer_pos].info.offset = ((uint32_t*)buf)[7] & 0xF0000000; + gettimeofday(&ctx->frame_info[ctx->buffer_pos].info.timestamp, NULL); + } else { +// pcilib_warning("Frame magic is not found, ignoring broken data..."); + return PCILIB_STREAMING_CONTINUE; + } } #ifdef IPECAMERA_BUG_MULTIFRAME_PACKETS @@ -423,9 +436,12 @@ static int ipecamera_data_callback(void *user, pcilib_dma_flags_t flags, size_t if (need < bufsize) { extra_data = bufsize - need; - bufsize = need; + //bufsize = need; eof = 1; } + + // just rip of padding + bufsize = ctx->raw_size - ctx->cur_size; } #endif /* IPECAMERA_BUG_MULTIFRAME_PACKETS */ @@ -471,15 +487,18 @@ static void *ipecamera_reader_thread(void *user) { if (err) { if (err == PCILIB_ERROR_TIMEOUT) { if (ctx->cur_size > ctx->raw_size) ipecamera_new_frame(ctx); - if (check_deadline(&ctx->autostop.timestamp, PCILIB_DMA_TIMEOUT)) { +#ifdef IPECAMERA_BUG_INCOMPLETE_PACKETS + else if (ctx->cur_size > 0) ipecamera_new_frame(ctx); +#endif /* IPECAMERA_BUG_INCOMPLETE_PACKETS */ + if (pcilib_check_deadline(&ctx->autostop.timestamp, PCILIB_DMA_TIMEOUT)) { ctx->run_reader = 0; break; } usleep(IPECAMERA_NOFRAME_SLEEP); } else pcilib_error("DMA error while reading IPECamera frames, error: %i", err); - } + } else printf("no error\n"); - usleep(1000); + //usleep(1000); } ctx->run_streamer = 0; @@ -667,6 +686,11 @@ int ipecamera_stop(pcilib_context_t *vctx, pcilib_event_flags_t flags) { return PCILIB_ERROR_NOTINITIALIZED; } + if (flags&PCILIB_EVENT_FLAG_STOP_ONLY) { + ctx->run_reader = 0; + return 0; + } + if (ctx->started) { ctx->run_reader = 0; err = pthread_join(ctx->rthread, &retcode); @@ -734,22 +758,10 @@ int ipecamera_trigger(pcilib_context_t *vctx, pcilib_event_t event, size_t trigg SET_REG(control_reg, IPECAMERA_IDLE|IPECAMERA_READOUT_FLAG); -// SET_REG(control_reg, IPECAMERA_READOUT); + // DS: Just measure when next trigger is allowed instead and wait in the beginning usleep(IPECAMERA_NEXT_FRAME_DELAY); // minimum delay between End Of Readout and next Frame Req - // DS: check for overflow -/* - - err = ipecamera_get_image(ctx); - if (!err) { - if (ctx->cb) { - err = ctx->cb(event, ctx->event_id, ctx->cb_user); - ctx->reported_id = ctx->event_id; - } - } - - return err; -*/ + return 0; } int ipecamera_stream(pcilib_context_t *vctx, pcilib_event_callback_t callback, void *user) { @@ -798,8 +810,7 @@ int ipecamera_stream(pcilib_context_t *vctx, pcilib_event_callback_t callback, v ipecamera_stop(vctx, PCILIB_EVENT_FLAGS_DEFAULT); } - - + return err; } @@ -820,9 +831,9 @@ int ipecamera_next_event(pcilib_context_t *vctx, pcilib_event_t event_mask, pcil if (ctx->reported_id == ctx->event_id) { if (timeout) { - calc_deadline(&tv, timeout); + pcilib_calc_deadline(&tv, timeout); - while ((calc_time_to_deadline(&tv) > 0)&&(ctx->reported_id == ctx->event_id)) + while ((pcilib_calc_time_to_deadline(&tv) > 0)&&(ctx->reported_id == ctx->event_id)) usleep(IPECAMERA_NOFRAME_SLEEP); } diff --git a/ipecamera/ipecamera.h b/ipecamera/ipecamera.h index d15d1f2..c89c6c9 100644 --- a/ipecamera/ipecamera.h +++ b/ipecamera/ipecamera.h @@ -23,6 +23,10 @@ typedef enum { typedef uint16_t ipecamera_change_mask_t; typedef uint16_t ipecamera_pixel_t; +typedef struct { + pcilib_event_info_t info; + size_t raw_size; /**< Indicates the actual size of raw data */ +} ipecamera_event_info_t; int ipecamera_set_buffer_size(ipecamera_t *ctx, int size); @@ -1,6 +1,8 @@ #ifndef _PCITOOL_PCI_H #define _PCITOOL_PCI_H +#define PCILIB_EVENT_TIMEOUT 1000000 /**< us */ +#define PCILIB_TRIGGER_TIMEOUT 100000 /**< us */ #define PCILIB_DMA_TIMEOUT 10000 /**< us */ #define PCILIB_DMA_SKIP_TIMEOUT 1000000 /**< us */ #define PCILIB_REGISTER_TIMEOUT 10000 /**< us */ @@ -86,11 +86,16 @@ typedef enum { typedef enum { PCILIB_EVENT_FLAGS_DEFAULT = 0, - PCILIB_EVENT_FLAG_RAW_DATA_ONLY = 1, - PCILIB_EVENT_FLAG_EOF = 2 + PCILIB_EVENT_FLAG_RAW_DATA_ONLY = 1, /**< Do not parse data, just read raw and pass it to rawdata callback */ + PCILIB_EVENT_FLAG_STOP_ONLY = 1, /**< Do not cleanup, just stop acquiring new frames, the cleanup should be requested afterwards */ + PCILIB_EVENT_FLAG_EOF = 2 /**< Indicates that it is the last part of the frame (not required) */ } pcilib_event_flags_t; typedef enum { + PCILIB_EVENT_INFO_FLAG_BROKEN = 1 /**< Indicates broken frames (if this flag is fales, the frame still can be broken) */ +} pcilib_event_info_flags_t; + +typedef enum { PCILIB_REGISTER_STANDARD = 0, PCILIB_REGISTER_FIFO, PCILIB_REGISTER_BITS @@ -118,18 +123,16 @@ typedef enum { #define PCILIB_EVENT3 8 #define PCILIB_EVENTS_ALL ((pcilib_event_t)-1) #define PCILIB_EVENT_INVALID ((pcilib_event_t)-1) -//#define PCILIB_EVENT_ID_INVALID 0 #define PCILIB_TIMEOUT_INFINITE ((pcilib_timeout_t)-1) #define PCILIB_TIMEOUT_IMMEDIATE 0 -#define PCILIB_TIMEOUT_TRIGGER 0 #define PCILIB_IRQ_SOURCE_DEFAULT 0 - typedef struct { pcilib_event_t type; - uint64_t seqnum; /* we will add seqnum_overflow if required */ - uint64_t offset; /* nanoseconds */ - struct timeval timestamp; /* most accurate timestamp */ + uint64_t seqnum; /**< we will add seqnum_overflow if required */ + uint64_t offset; /**< nanoseconds */ + struct timeval timestamp; /**< most accurate timestamp */ + pcilib_event_info_flags_t flags; /**< flags */ } pcilib_event_info_t; /**< @@ -1,9 +1,12 @@ +#define _POSIX_C_SOURCE 200112L + #include <stdio.h> #include <string.h> #include <unistd.h> #include <stdint.h> #include <assert.h> #include <ctype.h> +#include <time.h> #include <arpa/inet.h> #include <sys/time.h> @@ -251,20 +254,24 @@ int pcilib_get_page_mask() { return pagemask; } -int calc_deadline(struct timeval *tv, pcilib_timeout_t timeout) { - gettimeofday(tv, NULL); +int pcilib_add_timeout(struct timeval *tv, pcilib_timeout_t timeout) { tv->tv_usec += timeout%1000000; if (tv->tv_usec > 999999) { tv->tv_usec -= 1000000; - tv->tv_sec = 1 + timeout/1000000; + tv->tv_sec += 1 + timeout/1000000; } else { - tv->tv_sec = timeout/1000000; + tv->tv_sec += timeout/1000000; } - +} + +int pcilib_calc_deadline(struct timeval *tv, pcilib_timeout_t timeout) { + gettimeofday(tv, NULL); + pcilib_add_timeout(tv, timeout); + return 0; } -int check_deadline(struct timeval *tve, pcilib_timeout_t timeout) { +int pcilib_check_deadline(struct timeval *tve, pcilib_timeout_t timeout) { int64_t res; struct timeval tvs; @@ -272,12 +279,15 @@ int check_deadline(struct timeval *tve, pcilib_timeout_t timeout) { gettimeofday(&tvs, NULL); res = ((tve->tv_sec - tvs.tv_sec)*1000000 + (tve->tv_usec - tvs.tv_usec)); - if (res < timeout) return 1; + // Hm... Some problems comparing signed and unsigned. So, sign check first + if ((res < 0)||(res < timeout)) { + return 1; + } return 0; } -pcilib_timeout_t calc_time_to_deadline(struct timeval *tve) { +pcilib_timeout_t pcilib_calc_time_to_deadline(struct timeval *tve) { int64_t res; struct timeval tvs; @@ -287,3 +297,23 @@ pcilib_timeout_t calc_time_to_deadline(struct timeval *tve) { if (res < 0) return 0; return res; } + +int pcilib_sleep_until_deadline(struct timeval *tv) { + struct timespec wait; + pcilib_timeout_t duration; + + duration = pcilib_calc_time_to_deadline(tv); + wait.tv_sec = duration / 1000000; + wait.tv_nsec = 1000 * (duration % 1000000); + nanosleep(&wait, NULL); + + return 0; +} + +int pcilib_timecmp(struct timeval *tv1, struct timeval *tv2) { + if (tv1->tv_sec > tv2->tv_sec) return 1; + else if (tv1->tv_sec > tv2->tv_sec) return -1; + else if (tv1->tv_usec > tv2->tv_usec) return 1; + else if (tv1->tv_usec < tv2->tv_usec) return -1; + return 0; +} @@ -34,8 +34,11 @@ void * pcilib_datacpy32(void * dst, void const * src, uint8_t size, size_t n, pc int pcilib_get_page_mask(); -int calc_deadline(struct timeval *tv, pcilib_timeout_t timeout); -int check_deadline(struct timeval *tve, pcilib_timeout_t timeout); -pcilib_timeout_t calc_time_to_deadline(struct timeval *tve); +int pcilib_add_timeout(struct timeval *tv, pcilib_timeout_t timeout); +int pcilib_calc_deadline(struct timeval *tv, pcilib_timeout_t timeout); +int pcilib_check_deadline(struct timeval *tve, pcilib_timeout_t timeout); +pcilib_timeout_t pcilib_calc_time_to_deadline(struct timeval *tve); +int pcilib_sleep_until_deadline(struct timeval *tv); +int pcilib_timecmp(struct timeval *tv1, struct timeval *tv2); #endif /* _PCITOOL_TOOS_H */ |