summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile3
-rw-r--r--cli.c92
-rw-r--r--common.mk3
-rw-r--r--driver/base.c1
-rw-r--r--error.h1
-rw-r--r--ipecamera.h86
-rw-r--r--ipecamera/image.c287
-rw-r--r--ipecamera/image.h22
-rw-r--r--ipecamera/ipecamera.h6
-rw-r--r--ipecamera/model.c (renamed from ipecamera.c)18
-rw-r--r--ipecamera/model.h110
-rw-r--r--pci.c287
-rw-r--r--pci.h8
-rw-r--r--pcilib.h59
14 files changed, 866 insertions, 117 deletions
diff --git a/Makefile b/Makefile
index a1e3968..5183431 100644
--- a/Makefile
+++ b/Makefile
@@ -14,7 +14,7 @@ include common.mk
###############################################################
# Target definitions
-OBJECTS = pci.o ipecamera.o default.o tools.o
+OBJECTS = pci.o default.o tools.o ipecamera/model.o ipecamera/image.o
libpcilib.so: $(OBJECTS)
echo -e "LD \t$@"
@@ -26,6 +26,7 @@ pci: cli.o libpcilib.so
install: pci
install -m 644 pcilib.h $(DESTDIR)/include
+ install -m 644 ipecamera/ipecamera.h $(DESTDIR)/include
if [ -d $(DESTDIR)/lib64 ]; then install -m 755 libpcilib.so $(DESTDIR)/lib64; else install -m 755 libpcilib.so $(DESTDIR)/lib; fi
install -m 755 pci $(DESTDIR)/bin
ldconfig
diff --git a/cli.c b/cli.c
index 4fe56c9..9a54618 100644
--- a/cli.c
+++ b/cli.c
@@ -18,7 +18,6 @@
#include <getopt.h>
#include "pci.h"
-#include "ipecamera.h"
#include "tools.h"
#include "kernel.h"
@@ -50,7 +49,9 @@ typedef enum {
MODE_READ,
MODE_READ_REGISTER,
MODE_WRITE,
- MODE_WRITE_REGISTER
+ MODE_WRITE_REGISTER,
+ MODE_RESET,
+ MODE_GRAB
} MODE;
typedef enum {
@@ -60,11 +61,14 @@ typedef enum {
OPT_ACCESS = 'a',
OPT_ENDIANESS = 'e',
OPT_SIZE = 's',
+ OPT_OUTPUT = 'o',
OPT_INFO = 'i',
OPT_BENCHMARK = 'p',
OPT_LIST = 'l',
OPT_READ = 'r',
OPT_WRITE = 'w',
+ OPT_GRAB = 'g',
+ OPT_RESET = 128,
OPT_HELP = 'h',
} OPTIONS;
@@ -75,11 +79,14 @@ static struct option long_options[] = {
{"access", required_argument, 0, OPT_ACCESS },
{"endianess", required_argument, 0, OPT_ENDIANESS },
{"size", required_argument, 0, OPT_SIZE },
+ {"size", required_argument, 0, OPT_OUTPUT },
{"info", no_argument, 0, OPT_INFO },
{"list", no_argument, 0, OPT_LIST },
+ {"reset", no_argument, 0, OPT_RESET },
{"benchmark", no_argument, 0, OPT_BENCHMARK },
{"read", optional_argument, 0, OPT_READ },
{"write", optional_argument, 0, OPT_WRITE },
+ {"grab", optional_argument, 0, OPT_GRAB },
{"help", no_argument, 0, OPT_HELP },
{ 0, 0, 0, 0 }
};
@@ -108,6 +115,8 @@ void Usage(int argc, char *argv[], const char *format, ...) {
" -p - Performance Evaluation\n"
" -r <addr|reg> - Read Data/Register\n"
" -w <addr|reg> - Write Data/Register\n"
+" -g <event> - Grab Event\n"
+" --reset - Reset board\n"
" --help - Help message\n"
"\n"
" Addressing:\n"
@@ -121,6 +130,7 @@ void Usage(int argc, char *argv[], const char *format, ...) {
" -s <size> - Number of words (default: 1)\n"
" -a <bitness> - Bits per word (default: 32)\n"
" -e <l|b> - Endianess Little/Big (default: host)\n"
+" -o <file> - Output to file (default: stdout)\n"
"\n"
" Data:\n"
" Data can be specified as sequence of hexdecimal number or\n"
@@ -557,6 +567,38 @@ int WriteRegister(pcilib_t *handle, pcilib_model_t model, const char *bank, cons
return 0;
}
+int Grab(pcilib_t *handle, const char *output) {
+ int err;
+
+ void *data = NULL;
+ size_t size, written;
+
+ FILE *o;
+
+ err = pcilib_grab(handle, PCILIB_ALL_EVENTS, &size, &data, NULL);
+ if (err) {
+ Error("Grabbing event is failed");
+ }
+
+ if (output) {
+ o = fopen(output, "w");
+ if (!o) {
+ Error("Failed to open file \"%s\"", output);
+ }
+
+ printf("Writting %i bytes into %s...\n", size, output);
+ } else o = stdout;
+
+ written = fwrite(data, 1, size, o);
+ if (written != size) {
+ if (written > 0) Error("Write failed, only %z bytes out of %z are stored", written, size);
+ else Error("Write failed");
+ }
+
+ if (o != stdout) fclose(o);
+
+ return 0;
+}
int main(int argc, char **argv) {
int i;
@@ -571,16 +613,18 @@ int main(int argc, char **argv) {
const char *reg = NULL;
const char *bank = NULL;
char **data = NULL;
+ const char *event = NULL;
uintptr_t start = -1;
size_t size = 1;
access_t access = 4;
int skip = 0;
int endianess = 0;
+ const char *output = NULL;
pcilib_t *handle;
- while ((c = getopt_long(argc, argv, "hilpr::w::d:m:b:a:s:e:", long_options, NULL)) != (unsigned char)-1) {
+ while ((c = getopt_long(argc, argv, "hilpr::w::d:m:b:a:s:e:g:", long_options, NULL)) != (unsigned char)-1) {
extern int optind;
switch (c) {
case OPT_HELP:
@@ -596,6 +640,11 @@ int main(int argc, char **argv) {
mode = MODE_LIST;
break;
+ case OPT_RESET:
+ if (mode != MODE_INVALID) Usage(argc, argv, "Multiple operations are not supported");
+
+ mode = MODE_RESET;
+ break;
case OPT_BENCHMARK:
if (mode != MODE_INVALID) Usage(argc, argv, "Multiple operations are not supported");
@@ -615,6 +664,13 @@ int main(int argc, char **argv) {
if (optarg) addr = optarg;
else if ((optind < argc)&&(argv[optind][0] != '-')) addr = argv[optind++];
break;
+ case OPT_GRAB:
+ if (mode != MODE_INVALID) Usage(argc, argv, "Multiple operations are not supported");
+
+ mode = MODE_GRAB;
+ if (optarg) event = optarg;
+ else if ((optind < argc)&&(argv[optind][0] != '-')) event = argv[optind++];
+ break;
case OPT_DEVICE:
fpga_device = optarg;
break;
@@ -652,6 +708,9 @@ int main(int argc, char **argv) {
} else Usage(argc, argv, "Invalid endianess is specified (%s)", optarg);
break;
+ case OPT_OUTPUT:
+ output = optarg;
+ break;
default:
Usage(argc, argv, "Unknown option (%s)", argv[optind]);
}
@@ -674,11 +733,22 @@ int main(int argc, char **argv) {
if (!addr) Usage(argc, argv, "The address is not specified");
if (((argc - optind) == 1)&&(*argv[optind] == '*')) {
int vallen = strlen(argv[optind]);
- data = (char**)malloc(size * (vallen + sizeof(char*)));
- if (!data) Error("Error allocating memory for data array");
- for (i = 0; i < size; i++) {
- data[i] = ((char*)data) + size * sizeof(char*) + i * vallen;
- strcpy(data[i], argv[optind] + 1);
+ if (vallen > 1) {
+ data = (char**)malloc(size * (vallen + sizeof(char*)));
+ if (!data) Error("Error allocating memory for data array");
+
+ for (i = 0; i < size; i++) {
+ data[i] = ((char*)data) + size * sizeof(char*) + i * vallen;
+ strcpy(data[i], argv[optind] + 1);
+ }
+ } else {
+ data = (char**)malloc(size * (9 + sizeof(char*)));
+ if (!data) Error("Error allocating memory for data array");
+
+ for (i = 0; i < size; i++) {
+ data[i] = ((char*)data) + size * sizeof(char*) + i * 9;
+ sprintf(data[i], "%x", i);
+ }
}
} else if ((argc - optind) == size) data = argv + optind;
else Usage(argc, argv, "The %i data values is specified, but %i required", argc - optind, size);
@@ -757,6 +827,12 @@ int main(int argc, char **argv) {
if (reg) WriteRegister(handle, model, bank, reg, data);
else WriteRegisterRange(handle, model, bank, start, size, data);
break;
+ case MODE_RESET:
+ pcilib_reset(handle);
+ break;
+ case MODE_GRAB:
+ Grab(handle, output);
+ break;
}
pcilib_close(handle);
diff --git a/common.mk b/common.mk
index f8dae8b..e203330 100644
--- a/common.mk
+++ b/common.mk
@@ -19,6 +19,9 @@ CFLAGS += $(addprefix -I ,$(INCDIR)) -fPIC -std=c99
SRC = $(wildcard *.cpp)
SRCC = $(wildcard *.c)
+SRC += $(wildcard ipecamera/*.cpp)
+SRCC += $(wildcard ipecamera/*.c)
+
# Corresponding object files
OBJ = $(addprefix $(OBJDIR)/,$(SRC:.cpp=.o))
OBJ += $(addprefix $(OBJDIR)/,$(SRCC:.c=.o))
diff --git a/driver/base.c b/driver/base.c
index c740856..b999cac 100644
--- a/driver/base.c
+++ b/driver/base.c
@@ -626,6 +626,7 @@ int pcidriver_mmap_pci(pcidriver_privdata_t *privdata, struct vm_area_struct *vm
/* Check sizes */
vma_size = (vmap->vm_end - vmap->vm_start);
+
if ((vma_size != bar_length) &&
((bar_length < PAGE_SIZE) && (vma_size != PAGE_SIZE))) {
mod_info( "mmap size is not correct! bar: %lu - vma: %lu\n", bar_length, vma_size );
diff --git a/error.h b/error.h
index d64c518..198df3e 100644
--- a/error.h
+++ b/error.h
@@ -12,6 +12,7 @@ enum {
PCILIB_ERROR_NOTSUPPORTED,
PCILIB_ERROR_NOTFOUND,
PCILIB_ERROR_OUTOFRANGE,
+ PCILIB_ERROR_NOTINITIALIZED
} pcilib_errot_t;
diff --git a/ipecamera.h b/ipecamera.h
deleted file mode 100644
index 9061dea..0000000
--- a/ipecamera.h
+++ /dev/null
@@ -1,86 +0,0 @@
-#ifndef _IPECAMERA_H
-#define _IPECAMERA_H
-
-#include <stdio.h>
-
-#include "pcilib.h"
-
-#define IPECAMERA_REGISTER_SPACE 0xfeaffc00
-#define IPECAMERA_REGISTER_WRITE (IPECAMERA_REGISTER_SPACE + 0)
-#define IPECAMERA_REGISTER_READ (IPECAMERA_REGISTER_WRITE + 4)
-
-#ifdef _IPECAMERA_C
-pcilib_register_bank_description_t ipecamera_register_banks[] = {
- { PCILIB_REGISTER_BANK0, 128, IPECAMERA_REGISTER_PROTOCOL, IPECAMERA_REGISTER_READ, IPECAMERA_REGISTER_WRITE, PCILIB_BIG_ENDIAN, 8, PCILIB_LITTLE_ENDIAN, "cmosis", "CMOSIS CMV2000 Registers" },
- { PCILIB_REGISTER_BANK1, 64, PCILIB_DEFAULT_PROTOCOL, IPECAMERA_REGISTER_SPACE, IPECAMERA_REGISTER_SPACE, PCILIB_BIG_ENDIAN, 32, PCILIB_LITTLE_ENDIAN, "fpga", "IPECamera Registers" },
- { 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL }
-};
-
-pcilib_register_description_t ipecamera_registers[] = {
-{1, 16, 1088, PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "number_lines", ""},
-{3, 16, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "start1", ""},
-{5, 16, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "start2", ""},
-{7, 16, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "start3", ""},
-{9, 16, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "start4", ""},
-{11, 16, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "start5", ""},
-{13, 16, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "start6", ""},
-{15, 16, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "start7", ""},
-{17, 16, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "start8", ""},
-{19, 16, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "number_lines1", ""},
-{21, 16, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "number_lines2", ""},
-{23, 16, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "number_lines3", ""},
-{25, 16, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "number_lines4", ""},
-{27, 16, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "number_lines5", ""},
-{29, 16, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "number_lines6", ""},
-{31, 16, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "number_lines7", ""},
-{33, 16, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "number_lines8", ""},
-{35, 16, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "sub_s", ""},
-{37, 16, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "sub_a", ""},
-{39, 1, 1, PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "color", ""},
-{40, 2, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "image_flipping", ""},
-{41, 2, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "exp_flags", ""},
-{42, 24, 1088, PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "exp_time", ""},
-{45, 24, 1088, PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "exp_step", ""},
-{48, 24, 1, PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "exp_kp1", ""},
-{51, 24, 1, PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "exp_kp2", ""},
-{54, 2, 1, PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "nr_slopes", ""},
-{55, 8, 1, PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "exp_seq", ""},
-{56, 24, 1088, PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "exp_time2", ""},
-{59, 24, 1088, PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "exp_step2", ""},
-{68, 2, 1, PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "nr_slopes2", ""},
-{69, 8, 1, PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "exp_seq2", ""},
-{70, 16, 1, PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "number_frames", ""},
-{72, 2, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "output_mode", ""},
-{78, 12, 85, PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "training_pattern", ""},
-{80, 18, 0x3FFFF,PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "channel_en", ""},
-{89, 8, 96, PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "vlow2", ""},
-{90, 8, 96, PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "vlow3", ""},
-{100, 14, 16260, PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "offset", ""},
-{102, 2, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "pga", ""},
-{103, 8, 32, PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "adc_gain", ""},
-{111, 1, 1, PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "bit_mode", ""},
-{112, 2, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "adc_resolution", ""},
-{126, 16, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "temp", ""},
-{0, 32, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK1, "spi_conf_input", ""},
-{1, 32, 0, PCILIB_REGISTER_R, PCILIB_REGISTER_BANK1, "spi_conf_output", ""},
-{2, 32, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK1, "spi_clk_speed", ""},
-{3, 32, 0, PCILIB_REGISTER_R, PCILIB_REGISTER_BANK1, "firmware_version", ""},
-{6, 16, 0, PCILIB_REGISTER_R, PCILIB_REGISTER_BANK1, "cmosis_temperature", ""},
-{7, 32, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK1, "temperature_sample_timing", ""},
-{0, 0, 0, 0, 0, NULL, NULL}
-};
-
-pcilib_register_range_t ipecamera_register_ranges[] = {
- {0, 128, PCILIB_REGISTER_BANK0}, {0, 0, 0}
-};
-
-#else
-extern pcilib_register_description_t ipecamera_registers[];
-extern pcilib_register_bank_description_t ipecamera_register_banks[];
-extern pcilib_register_range_t ipecamera_register_ranges[];
-#endif
-
-int ipecamera_read(pcilib_t *ctx, pcilib_register_bank_description_t *bank, pcilib_register_addr_t addr, uint8_t bits, pcilib_register_value_t *value);
-int ipecamera_write(pcilib_t *ctx, pcilib_register_bank_description_t *bank, pcilib_register_addr_t addr, uint8_t bits, pcilib_register_value_t value);
-
-#endif /* _IPECAMERA_H */
diff --git a/ipecamera/image.c b/ipecamera/image.c
new file mode 100644
index 0000000..e7661b2
--- /dev/null
+++ b/ipecamera/image.c
@@ -0,0 +1,287 @@
+#define _IPECAMERA_IMAGE_C
+#define _BSD_SOURCE
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/time.h>
+#include <assert.h>
+
+#include "../tools.h"
+#include "../error.h"
+
+#include "pcilib.h"
+
+#include "model.h"
+#include "image.h"
+
+#define IPECAMERA_SLEEP_TIME 250000
+
+struct ipecamera_s {
+ pcilib_t *pcilib;
+
+ char *data;
+ size_t size;
+
+ pcilib_callback_t cb;
+ void *cb_user;
+
+ int width;
+ int height;
+
+ pcilib_event_id_t event_id;
+
+ pcilib_register_t control_reg, status_reg;
+ pcilib_register_t start_reg, end_reg;
+ pcilib_register_t lines_reg;
+ pcilib_register_t exposure_reg;
+
+ void *buffer;
+};
+
+
+#define FIND_REG(var, bank, name) \
+ ctx->var = pcilib_find_register(pcilib, bank, name); \
+ if (ctx->var == PCILIB_REGISTER_INVALID) { \
+ err = -1; \
+ pcilib_error("Unable to find a %s register", name); \
+ }
+
+
+#define GET_REG(reg, var) \
+ err = pcilib_read_register_by_id(pcilib, ctx->reg, &var); \
+ if (err) { \
+ pcilib_error("Error reading %s register", ipecamera_registers[ctx->reg].name); \
+ return err; \
+ }
+
+#define SET_REG(reg, val) \
+ err = pcilib_write_register_by_id(pcilib, ctx->reg, val); \
+ if (err) { \
+ pcilib_error("Error writting %s register", ipecamera_registers[ctx->reg].name); \
+ return err; \
+ }
+
+#define CHECK_REG(reg, check) \
+ err = pcilib_read_register_by_id(pcilib, ctx->reg, &value); \
+ if (err) { \
+ pcilib_error("Error reading %s register", ipecamera_registers[ctx->reg].name); \
+ return err; \
+ } \
+ if (!(check)) { \
+ pcilib_error("Unexpected value (%li) of register %s", value, ipecamera_registers[ctx->reg].name); \
+ return err; \
+ }
+
+
+void *ipecamera_init(pcilib_t *pcilib) {
+ int err = 0;
+
+ ipecamera_t *ctx = malloc(sizeof(ipecamera_t));
+
+ if (ctx) {
+ ctx->pcilib = pcilib;
+
+ ctx->data = pcilib_resolve_data_space(pcilib, 0, &ctx->size);
+ if (!ctx->data) {
+ err = -1;
+ pcilib_error("Unable to resolve the data space");
+ }
+
+ ctx->buffer = malloc(1088 * 2048 * 2);
+ if (!ctx->buffer) {
+ err = -1;
+ pcilib_error("Unable to allocate ring buffer");
+ }
+
+ FIND_REG(status_reg, "fpga", "status");
+ FIND_REG(control_reg, "fpga", "control");
+ FIND_REG(start_reg, "fpga", "start_address");
+ FIND_REG(end_reg, "fpga", "end_address");
+
+ FIND_REG(lines_reg, "cmosis", "number_lines");
+ FIND_REG(exposure_reg, "cmosis", "exp_time");
+
+ if (err) {
+ free(ctx);
+ return NULL;
+ }
+ }
+
+ return (void*)ctx;
+}
+
+void ipecamera_free(void *vctx) {
+ if (vctx) {
+ ipecamera_t *ctx = (ipecamera_t*)vctx;
+
+ if (ctx->buffer) free(ctx->buffer);
+ free(ctx);
+ }
+}
+
+int ipecamera_reset(void *vctx) {
+ int err;
+ pcilib_t *pcilib;
+ ipecamera_t *ctx = (ipecamera_t*)vctx;
+
+ pcilib_register_t control, status;
+ pcilib_register_value_t value;
+
+ if (!ctx) {
+ pcilib_error("IPECamera imaging is not initialized");
+ return PCILIB_ERROR_NOTINITIALIZED;
+ }
+
+ pcilib = ctx->pcilib;
+ control = ctx->control_reg;
+ status = ctx->status_reg;
+
+ // Set Reset bit to CMOSIS
+ err = pcilib_write_register_by_id(pcilib, control, 5);
+ if (err) {
+ pcilib_error("Error setting CMOSIS reset bit");
+ return err;
+ }
+ usleep(IPECAMERA_SLEEP_TIME);
+
+ // Remove Reset bit to CMOSIS
+ err = pcilib_write_register_by_id(pcilib, control, 1);
+ if (err) {
+ pcilib_error("Error reseting CMOSIS reset bit");
+ return err;
+ }
+ usleep(IPECAMERA_SLEEP_TIME);
+
+ // Special settings for CMOSIS v.2
+ value = 01; err = pcilib_write_register_space(pcilib, "cmosis", 115, 1, &value);
+ if (err) {
+ pcilib_error("Error setting CMOSIS configuration");
+ return err;
+ }
+ usleep(IPECAMERA_SLEEP_TIME);
+
+ value = 07; err = pcilib_write_register_space(pcilib, "cmosis", 82, 1, &value);
+ if (err) {
+ pcilib_error("Error setting CMOSIS configuration");
+ return err;
+ }
+ usleep(IPECAMERA_SLEEP_TIME);
+
+ // This is temporary for verification purposes
+ memset(ctx->data, 0, ctx->size);
+
+ err = pcilib_read_register_by_id(pcilib, status, &value);
+ if (err) {
+ pcilib_error("Error reading status register");
+ return err;
+ }
+
+ if (value != 0x0849FFFF) {
+ pcilib_error("Unexpected value (%lx) of status register", value);
+ return PCILIB_ERROR_VERIFY;
+ }
+
+ return 0;
+}
+
+int ipecamera_start(void *vctx, pcilib_event_t event_mask, pcilib_callback_t cb, void *user) {
+ ipecamera_t *ctx = (ipecamera_t*)vctx;
+
+ if (!ctx) {
+ pcilib_error("IPECamera imaging is not initialized");
+ return PCILIB_ERROR_NOTINITIALIZED;
+ }
+
+ ctx->cb = cb;
+ ctx->cb_user = user;
+
+
+ ctx->event_id = 0;
+
+ ctx->width = 1270;
+ ctx->height = 1088; //GET_REG(lines_reg, lines);
+
+ // allocate memory
+
+ return 0;
+}
+
+
+int ipecamera_stop(void *vctx) {
+ ipecamera_t *ctx = (ipecamera_t*)vctx;
+
+ if (!ctx) {
+ pcilib_error("IPECamera imaging is not initialized");
+ return PCILIB_ERROR_NOTINITIALIZED;
+ }
+
+ return 0;
+}
+
+
+static int ipecamera_get_line(ipecamera_t *ctx, int line) {
+ int err;
+ pcilib_t *pcilib = ctx->pcilib;
+ pcilib_register_value_t ptr, size, value;
+
+ ipecamera_reset((void*)ctx);
+
+ SET_REG(lines_reg, 1);
+
+ SET_REG(control_reg, 149);
+ usleep(IPECAMERA_SLEEP_TIME);
+ CHECK_REG(status_reg, 0x0849FFFF);
+
+ GET_REG(start_reg, ptr);
+ GET_REG(end_reg, size);
+ size -= ptr;
+
+ printf("%i: %i %i\n", line, ptr, size);
+
+ SET_REG(control_reg, 141);
+ usleep(IPECAMERA_SLEEP_TIME);
+ CHECK_REG(status_reg, 0x0849FFFF);
+}
+
+
+static int ipecamera_get_image(ipecamera_t *ctx) {
+ int err;
+ int i;
+ pcilib_t *pcilib = ctx->pcilib;
+
+ for (i = 0; i < 1088; i++) {
+ ipecamera_get_line(ctx, i);
+ }
+
+ ctx->event_id++;
+}
+
+
+int ipecamera_trigger(void *vctx, pcilib_event_t event, size_t trigger_size, void *trigger_data) {
+ int err;
+ pcilib_t *pcilib;
+ ipecamera_t *ctx = (ipecamera_t*)vctx;
+
+ if (!ctx) {
+ pcilib_error("IPECamera imaging is not initialized");
+ return PCILIB_ERROR_NOTINITIALIZED;
+
+ }
+
+ err = ipecamera_get_image(ctx);
+ if (!err) err = ctx->cb(event, ctx->event_id, ctx->cb_user);
+
+ return err;
+}
+
+
+void* ipecamera_get(void *ctx, pcilib_event_id_t event_id, pcilib_event_data_type_t data_type, size_t *size) {
+ if (size) *size = ctx->width * ctx->height * 2;
+ return ctx->buffer;
+}
+
+int ipecamera_return(void *ctx, pcilib_event_id_t event_id) {
+ return 0;
+}
diff --git a/ipecamera/image.h b/ipecamera/image.h
new file mode 100644
index 0000000..d174b95
--- /dev/null
+++ b/ipecamera/image.h
@@ -0,0 +1,22 @@
+#ifndef _IPECAMERA_IMAGE_H
+#define _IPECAMERA_IMAGE_H
+
+#include <stdio.h>
+
+#include "pcilib.h"
+
+typedef struct ipecamera_s ipecamera_t;
+
+void *ipecamera_init(pcilib_t *pcilib);
+void ipecamera_free(void *ctx);
+
+int ipecamera_reset(void *ctx);
+int ipecamera_start(void *ctx, pcilib_event_t event_mask, pcilib_callback_t cb, void *user);
+int ipecamera_stop(void *ctx);
+int ipecamera_trigger(void *ctx, pcilib_event_t event, size_t trigger_size, void *trigger_data);
+
+void* ipecamera_get(void *ctx, pcilib_event_id_t event_id, pcilib_event_data_type_t data_type, size_t *size);
+int ipecamera_return(void *ctx, pcilib_event_id_t event_id);
+
+
+#endif /* _IPECAMERA_IMAGE_H */
diff --git a/ipecamera/ipecamera.h b/ipecamera/ipecamera.h
new file mode 100644
index 0000000..8b27516
--- /dev/null
+++ b/ipecamera/ipecamera.h
@@ -0,0 +1,6 @@
+#ifndef _IPECAMERA_H
+#define _IPECAMERA_H
+
+
+
+#endif /* _IPECAMERA_H */
diff --git a/ipecamera.c b/ipecamera/model.c
index 9c238f5..4e475b1 100644
--- a/ipecamera.c
+++ b/ipecamera/model.c
@@ -1,10 +1,10 @@
-#define _IPECAMERA_C
+#define _IPECAMERA_MODEL_C
#include <sys/time.h>
#include <assert.h>
-#include "tools.h"
-#include "ipecamera.h"
-#include "error.h"
+#include "../tools.h"
+#include "../error.h"
+#include "model.h"
#define ADDR_MASK 0x7F00
#define WRITE_BIT 0x8000
@@ -110,6 +110,11 @@ retry:
}
if ((val & READ_READY_BIT) == 0) {
+ if (--retries > 0) {
+ pcilib_warning("Timeout occured during register write, retrying (try %i of %i)...", RETRIES - retries, RETRIES);
+ goto retry;
+ }
+
pcilib_error("Timeout writting register value");
return PCILIB_ERROR_TIMEOUT;
}
@@ -121,7 +126,7 @@ retry:
if (((val&ADDR_MASK) >> 8) != addr) {
if (--retries > 0) {
- pcilib_warning("Address verification failed during register read, retrying (try %i of %i)...", RETRIES - retries, RETRIES);
+ pcilib_warning("Address verification failed during register write, retrying (try %i of %i)...", RETRIES - retries, RETRIES);
goto retry;
}
pcilib_error("Address verification failed during register write");
@@ -137,3 +142,6 @@ retry:
return 0;
}
+
+
+
diff --git a/ipecamera/model.h b/ipecamera/model.h
new file mode 100644
index 0000000..f3f46dd
--- /dev/null
+++ b/ipecamera/model.h
@@ -0,0 +1,110 @@
+#ifndef _IPECAMERA_MODEL_H
+#define _IPECAMERA_MODEL_H
+
+#include <stdio.h>
+
+#include "pcilib.h"
+#include "image.h"
+
+#define IPECAMERA_REGISTER_SPACE 0xfeaffc00
+#define IPECAMERA_REGISTER_WRITE (IPECAMERA_REGISTER_SPACE + 0)
+#define IPECAMERA_REGISTER_READ (IPECAMERA_REGISTER_WRITE + 4)
+
+#ifdef _IPECAMERA_MODEL_C
+pcilib_register_bank_description_t ipecamera_register_banks[] = {
+ { PCILIB_REGISTER_BANK0, 128, IPECAMERA_REGISTER_PROTOCOL, IPECAMERA_REGISTER_READ, IPECAMERA_REGISTER_WRITE, PCILIB_BIG_ENDIAN, 8, PCILIB_LITTLE_ENDIAN, "cmosis", "CMOSIS CMV2000 Registers" },
+ { PCILIB_REGISTER_BANK1, 64, PCILIB_DEFAULT_PROTOCOL, IPECAMERA_REGISTER_SPACE, IPECAMERA_REGISTER_SPACE, PCILIB_BIG_ENDIAN, 32, PCILIB_LITTLE_ENDIAN, "fpga", "IPECamera Registers" },
+ { 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL }
+};
+
+pcilib_register_description_t ipecamera_registers[] = {
+{1, 0, 16, 1088, PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "number_lines", ""},
+{3, 0, 16, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "start1", ""},
+{5, 0, 16, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "start2", ""},
+{7, 0, 16, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "start3", ""},
+{9, 0, 16, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "start4", ""},
+{11, 0, 16, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "start5", ""},
+{13, 0, 16, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "start6", ""},
+{15, 0, 16, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "start7", ""},
+{17, 0, 16, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "start8", ""},
+{19, 0, 16, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "number_lines1", ""},
+{21, 0, 16, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "number_lines2", ""},
+{23, 0, 16, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "number_lines3", ""},
+{25, 0, 16, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "number_lines4", ""},
+{27, 0, 16, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "number_lines5", ""},
+{29, 0, 16, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "number_lines6", ""},
+{31, 0, 16, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "number_lines7", ""},
+{33, 0, 16, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "number_lines8", ""},
+{35, 0, 16, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "sub_s", ""},
+{37, 0, 16, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "sub_a", ""},
+{39, 0, 1, 1, PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "color", ""},
+{40, 0, 2, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "image_flipping", ""},
+{41, 0, 2, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "exp_flags", ""},
+{42, 0, 24, 1088, PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "exp_time", ""},
+{45, 0, 24, 1088, PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "exp_step", ""},
+{48, 0, 24, 1, PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "exp_kp1", ""},
+{51, 0, 24, 1, PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "exp_kp2", ""},
+{54, 0, 2, 1, PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "nr_slopes", ""},
+{55, 0, 8, 1, PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "exp_seq", ""},
+{56, 0, 24, 1088, PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "exp_time2", ""},
+{59, 0, 24, 1088, PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "exp_step2", ""},
+{68, 0, 2, 1, PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "nr_slopes2", ""},
+{69, 0, 8, 1, PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "exp_seq2", ""},
+{70, 0, 16, 1, PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "number_frames", ""},
+{72, 0, 2, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "output_mode", ""},
+{78, 0, 12, 85, PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "training_pattern", ""},
+{80, 0, 18, 0x3FFFF,PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "channel_en", ""},
+{89, 0, 8, 96, PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "vlow2", ""},
+{90, 0, 8, 96, PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "vlow3", ""},
+{100, 0, 14, 16260, PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "offset", ""},
+{102, 0, 2, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "pga", ""},
+{103, 0, 8, 32, PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "adc_gain", ""},
+{111, 0, 1, 1, PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "bit_mode", ""},
+{112, 0, 2, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "adc_resolution", ""},
+{126, 0, 16, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "temp", ""},
+{0, 0, 32, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK1, "spi_conf_input", ""},
+{1, 0, 32, 0, PCILIB_REGISTER_R, PCILIB_REGISTER_BANK1, "spi_conf_output", ""},
+{2, 0, 32, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK1, "spi_clk_speed", ""},
+{3, 0, 32, 0, PCILIB_REGISTER_R, PCILIB_REGISTER_BANK1, "firmware_version", ""},
+{4, 0, 32, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK1, "control", ""},
+{5, 0, 32, 0, PCILIB_REGISTER_R, PCILIB_REGISTER_BANK1, "status", ""},
+{6, 0, 16, 0, PCILIB_REGISTER_R, PCILIB_REGISTER_BANK1, "cmosis_temperature", ""},
+{7, 0, 32, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK1, "temperature_sample_timing", ""},
+{8, 0, 32, 0, PCILIB_REGISTER_R, PCILIB_REGISTER_BANK1, "start_address", ""},
+{9, 0, 32, 0, PCILIB_REGISTER_R, PCILIB_REGISTER_BANK1, "end_address", ""},
+{10, 0, 32, 0, PCILIB_REGISTER_R, PCILIB_REGISTER_BANK1, "last_write_address", ""},
+{11, 0, 32, 0, PCILIB_REGISTER_R, PCILIB_REGISTER_BANK1, "last_write_value", ""},
+{0, 0, 0, 0, 0, 0, NULL, NULL}
+};
+
+pcilib_register_range_t ipecamera_register_ranges[] = {
+ {0, 128, PCILIB_REGISTER_BANK0}, {0, 0, 0}
+};
+
+#else
+extern pcilib_register_description_t ipecamera_registers[];
+extern pcilib_register_bank_description_t ipecamera_register_banks[];
+extern pcilib_register_range_t ipecamera_register_ranges[];
+#endif
+
+#ifdef _IPECAMERA_IMAGE_C
+pcilib_event_api_description_t ipecamera_image_api = {
+ ipecamera_init,
+ ipecamera_free,
+
+ ipecamera_reset,
+ ipecamera_start,
+ ipecamera_stop,
+ ipecamera_trigger,
+
+ ipecamera_get,
+ ipecamera_return
+};
+#else
+extern pcilib_event_api_description_t ipecamera_image_api;
+#endif
+
+int ipecamera_read(pcilib_t *ctx, pcilib_register_bank_description_t *bank, pcilib_register_addr_t addr, uint8_t bits, pcilib_register_value_t *value);
+int ipecamera_write(pcilib_t *ctx, pcilib_register_bank_description_t *bank, pcilib_register_addr_t addr, uint8_t bits, pcilib_register_value_t value);
+
+#endif /* _IPECAMERA_MODEL_H */
diff --git a/pci.c b/pci.c
index 461d2f3..2a25e0d 100644
--- a/pci.c
+++ b/pci.c
@@ -1,4 +1,5 @@
#define _PCILIB_PCI_C
+#define _POSIX_C_SOURCE 199309L
#include <stdio.h>
#include <string.h>
@@ -17,7 +18,7 @@
#include "tools.h"
#include "pci.h"
-#include "ipecamera.h"
+#include "ipecamera/model.h"
#include "error.h"
#define BIT_MASK(bits) ((1l << (bits)) - 1)
@@ -34,6 +35,12 @@ struct pcilib_s {
pcilib_bar_t reg_bar;
char *reg_space;
+
+ pcilib_bar_t data_bar;
+ char *data_space;
+ size_t data_size;
+
+ void *event_ctx;
#ifdef PCILIB_FILE_IO
int file_io_handle;
@@ -60,6 +67,7 @@ int pcilib_set_error_handler(void (*err)(const char *msg, ...), void (*warn)(con
}
pcilib_t *pcilib_open(const char *device, pcilib_model_t model) {
+ pcilib_event_api_description_t *api;
pcilib_t *ctx = malloc(sizeof(pcilib_t));
if (ctx) {
@@ -67,6 +75,10 @@ pcilib_t *pcilib_open(const char *device, pcilib_model_t model) {
ctx->page_mask = (uintptr_t)-1;
ctx->model = model;
ctx->reg_space = NULL;
+
+ if (!model) model = pcilib_get_model(ctx);
+ api = pcilib_model[model].event_api;
+ if ((api)&&(api->init)) ctx->event_ctx = api->init(ctx);
}
return ctx;
@@ -297,12 +309,67 @@ static int pcilib_map_register_space(pcilib_t *ctx) {
}
}
- return -1;
+ return PCILIB_ERROR_NOTFOUND;
}
return 0;
}
+
+static int pcilib_map_data_space(pcilib_t *ctx, uintptr_t addr) {
+ int err;
+ int i;
+
+ if (!ctx->data_space) {
+ const pci_board_info *board_info = pcilib_get_board_info(ctx);
+
+ err = pcilib_map_register_space(ctx);
+ if (err) {
+ pcilib_error("Error mapping register space");
+ return err;
+ }
+
+ if (addr) {
+ }
+
+ int data_bar = -1;
+
+ for (i = 0; i < PCILIB_MAX_BANKS; i++) {
+ if ((i == ctx->reg_bar)||(!board_info->bar_length[i])) continue;
+
+ if (addr) {
+ if (board_info->bar_start[i] == addr) {
+ data_bar = i;
+ break;
+ }
+ } else {
+ if (data_bar >= 0) {
+ data_bar = -1;
+ break;
+ }
+
+ data_bar = i;
+ }
+ }
+
+ if (data_bar < 0) {
+ if (addr) pcilib_error("Unable to find the specified data space (%lx)", addr);
+ else pcilib_error("Unable to find the data space");
+ return PCILIB_ERROR_NOTFOUND;
+ }
+
+ ctx->data_bar = data_bar;
+ ctx->data_space = pcilib_map_bar(ctx, data_bar);
+ ctx->data_size = board_info->bar_length[data_bar];
+
+ if (!ctx->data_space) {
+ pcilib_error("Unable to map the data space");
+ return PCILIB_ERROR_FAILED;
+ }
+ }
+
+ return 0;
+}
static void pcilib_unmap_register_space(pcilib_t *ctx) {
if (ctx->reg_space) {
@@ -311,6 +378,13 @@ static void pcilib_unmap_register_space(pcilib_t *ctx) {
}
}
+static void pcilib_unmap_data_space(pcilib_t *ctx) {
+ if (ctx->data_space) {
+ pcilib_unmap_bar(ctx, ctx->data_bar, ctx->data_space);
+ ctx->data_space = NULL;
+ }
+}
+
char *pcilib_resolve_register_address(pcilib_t *ctx, uintptr_t addr) {
size_t offset = addr - ctx->board_info.bar_start[ctx->reg_bar];
if (offset < ctx->board_info.bar_length[ctx->reg_bar]) {
@@ -319,11 +393,31 @@ char *pcilib_resolve_register_address(pcilib_t *ctx, uintptr_t addr) {
return NULL;
}
+char *pcilib_resolve_data_space(pcilib_t *ctx, uintptr_t addr, size_t *size) {
+ int err;
+
+ err = pcilib_map_data_space(ctx, addr);
+ if (err) {
+ pcilib_error("Failed to map the specified address space (%lx)", addr);
+ return NULL;
+ }
+
+ if (size) *size = ctx->data_size;
+
+ return ctx->data_space + (ctx->board_info.bar_start[ctx->data_bar] & ctx->page_mask);
+}
+
void pcilib_close(pcilib_t *ctx) {
if (ctx) {
+ pcilib_model_t model = pcilib_get_model(ctx);
+ pcilib_event_api_description_t *api = pcilib_model[model].event_api;
+
+ if ((api)&&(api->free)) api->free(ctx->event_ctx);
+ if (ctx->data_space) pcilib_unmap_data_space(ctx);
if (ctx->reg_space) pcilib_unmap_register_space(ctx);
close(ctx->handle);
+
free(ctx);
}
}
@@ -491,17 +585,21 @@ int pcilib_write_register_by_id(pcilib_t *ctx, pcilib_register_t reg, pcilib_reg
pcilib_error("Big-endian byte order support is not implemented");
return PCILIB_ERROR_NOTSUPPORTED;
} else {
- for (i = 0, res = value; (res > 0)&&(i <= n); ++i) {
- buf[i] = res & BIT_MASK(b->access);
- res >>= b->access;
- }
+ if (b->access == sizeof(res) * 8) {
+ buf[i] = res;
+ } else {
+ for (i = 0, res = value; (res > 0)&&(i <= n); ++i) {
+ buf[i] = res & BIT_MASK(b->access);
+ res >>= b->access;
+ }
- if (res) {
- pcilib_error("Value %i is to big to fit in the register %s", value, r->name);
- return PCILIB_ERROR_OUTOFRANGE;
+ if (res) {
+ pcilib_error("Value %i is too big to fit in the register %s", value, r->name);
+ return PCILIB_ERROR_OUTOFRANGE;
+ }
}
}
-
+
err = pcilib_write_register_space_internal(ctx, r->bank, r->addr, n, bits, buf);
return err;
}
@@ -511,8 +609,175 @@ int pcilib_write_register(pcilib_t *ctx, const char *bank, const char *regname,
int reg;
reg = pcilib_find_register(ctx, bank, regname);
- if (reg < 0) pcilib_error("Register (%s) is not found", regname);
+ if (reg < 0) {
+ pcilib_error("Register (%s) is not found", regname);
+ return PCILIB_ERROR_NOTFOUND;
+ }
return pcilib_write_register_by_id(ctx, reg, value);
}
+
+int pcilib_reset(pcilib_t *ctx) {
+ pcilib_event_api_description_t *api;
+
+ pcilib_model_t model = pcilib_get_model(ctx);
+
+ api = pcilib_model[model].event_api;
+ if (!api) {
+ pcilib_error("Event API is not supported by the selected model");
+ return PCILIB_ERROR_NOTSUPPORTED;
+ }
+
+ if (api->reset)
+ return api->reset(ctx->event_ctx);
+
+ return 0;
+}
+
+int pcilib_start(pcilib_t *ctx, pcilib_event_t event_mask, void *callback, void *user) {
+ pcilib_event_api_description_t *api;
+
+ pcilib_model_t model = pcilib_get_model(ctx);
+
+ api = pcilib_model[model].event_api;
+ if (!api) {
+ pcilib_error("Event API is not supported by the selected model");
+ return PCILIB_ERROR_NOTSUPPORTED;
+ }
+
+ if (api->start)
+ return api->start(ctx->event_ctx, event_mask, callback, user);
+
+ return 0;
+}
+
+int pcilib_stop(pcilib_t *ctx) {
+ pcilib_event_api_description_t *api;
+
+ pcilib_model_t model = pcilib_get_model(ctx);
+
+ api = pcilib_model[model].event_api;
+ if (!api) {
+ pcilib_error("Event API is not supported by the selected model");
+ return PCILIB_ERROR_NOTSUPPORTED;
+ }
+
+ if (api->stop)
+ return api->stop(ctx->event_ctx);
+
+ return 0;
+}
+
+int pcilib_trigger(pcilib_t *ctx, pcilib_event_t event, size_t trigger_size, void *trigger_data) {
+ pcilib_event_api_description_t *api;
+
+ pcilib_model_t model = pcilib_get_model(ctx);
+
+ api = pcilib_model[model].event_api;
+ if (!api) {
+ pcilib_error("Event API is not supported by the selected model");
+ return PCILIB_ERROR_NOTSUPPORTED;
+ }
+
+ if (api->trigger)
+ return api->trigger(ctx->event_ctx, event, trigger_size, trigger_data);
+
+ pcilib_error("Self triggering is not supported by the selected model");
+ return PCILIB_ERROR_NOTSUPPORTED;
+}
+
+
+void *pcilib_get_data(pcilib_t *ctx, pcilib_event_id_t event_id, pcilib_event_data_type_t data_type, size_t *size) {
+ pcilib_event_api_description_t *api = pcilib_model[ctx->model].event_api;
+ if (!api) {
+ pcilib_error("Event API is not supported by the selected model");
+ return NULL;
+ }
+
+ if (api->get_data)
+ return api->get_data(ctx->event_ctx, event_id, data_type, size);
+
+ return NULL;
+}
+
+int pcilib_return_data(pcilib_t *ctx, pcilib_event_id_t event_id) {
+ pcilib_event_api_description_t *api = pcilib_model[ctx->model].event_api;
+ if (!api) {
+ pcilib_error("Event API is not supported by the selected model");
+ return PCILIB_ERROR_NOTSUPPORTED;
+ }
+
+ if (api->return_data)
+ return api->return_data(ctx->event_ctx, event_id);
+
+ return 0;
+}
+
+
+typedef struct {
+ pcilib_t *ctx;
+
+ size_t *size;
+ void **data;
+} pcilib_grab_callback_user_data_t;
+
+static int pcilib_grab_callback(pcilib_event_t event, pcilib_event_id_t event_id, void *vuser) {
+ int err;
+ void *data;
+ size_t size;
+ int allocated = 0;
+
+ pcilib_grab_callback_user_data_t *user = (pcilib_grab_callback_user_data_t*)vuser;
+
+ data = pcilib_get_data(user->ctx, event_id, PCILIB_EVENT_DATA, &size);
+ if (!data) {
+ pcilib_error("Error getting event data");
+ return PCILIB_ERROR_FAILED;
+ }
+
+ if (*(user->data)) {
+ if ((user->size)&&(*(user->size) < size)) {
+ pcilib_error("The supplied buffer does not have enough space to hold the event data. Buffer size is %z, but %z is required", user->size, size);
+ return PCILIB_ERROR_MEMORY;
+ }
+
+ *(user->size) = size;
+ } else {
+ *(user->data) = malloc(size);
+ if (!*(user->data)) {
+ pcilib_error("Memory allocation (%i bytes) for event data is failed");
+ return PCILIB_ERROR_MEMORY;
+ }
+ if (*(user->size)) *(user->size) = size;
+ allocated = 1;
+ }
+
+ memcpy(*(user->data), data, size);
+
+ err = pcilib_return_data(user->ctx, event_id);
+ if (err) {
+ if (allocated) {
+ free(*(user->data));
+ *(user->data) = NULL;
+ }
+ pcilib_error("The event data had been overwritten before it was returned, data corruption may occur");
+ return err;
+ }
+
+ return 0;
+}
+
+int pcilib_grab(pcilib_t *ctx, pcilib_event_t event_mask, size_t *size, void **data, const struct timespec *timeout) {
+ int err;
+
+ pcilib_grab_callback_user_data_t user = {ctx, size, data};
+
+ err = pcilib_start(ctx, event_mask, pcilib_grab_callback, &user);
+ if (!err) {
+ if (timeout) nanosleep(timeout, NULL);
+ else err = pcilib_trigger(ctx, event_mask, 0, NULL);
+ }
+ pcilib_stop(ctx);
+ return 0;
+}
diff --git a/pci.h b/pci.h
index 7da0a11..9426c33 100644
--- a/pci.h
+++ b/pci.h
@@ -11,13 +11,13 @@
const pci_board_info *pcilib_get_board_info(pcilib_t *ctx);
#ifdef _PCILIB_PCI_C
-# include "ipecamera.h"
+# include "ipecamera/model.h"
# include "default.h"
pcilib_model_description_t pcilib_model[3] = {
- { NULL, NULL, NULL },
- { NULL, NULL, NULL },
- { ipecamera_registers, ipecamera_register_banks, ipecamera_register_ranges }
+ { NULL, NULL, NULL, NULL },
+ { NULL, NULL, NULL, NULL },
+ { ipecamera_registers, ipecamera_register_banks, ipecamera_register_ranges, &ipecamera_image_api }
};
pcilib_protocol_description_t pcilib_protocol[3] = {
diff --git a/pcilib.h b/pcilib.h
index 7924128..57c68c9 100644
--- a/pcilib.h
+++ b/pcilib.h
@@ -3,8 +3,16 @@
#define PCILIB_MAX_BANKS 6
+#include <time.h>
#include <stdint.h>
+#ifndef __timespec_defined
+struct timespec {
+ time_t tv_sec;
+ long tv_nsec;
+};
+#endif /* __timespec_defined */
+
#define pcilib_memcpy pcilib_memcpy32
#define pcilib_datacpy pcilib_datacpy32
@@ -17,6 +25,9 @@ typedef uint8_t pcilib_register_bank_t; /**< Type holding the register bank num
typedef uint8_t pcilib_register_bank_addr_t; /**< Type holding the register bank number */
typedef uint8_t pcilib_register_size_t; /**< Type holding the size in bits of the register */
typedef uint32_t pcilib_register_value_t; /**< Type holding the register value */
+typedef uint64_t pcilib_event_id_t;
+
+typedef uint32_t pcilib_event_t;
typedef enum {
PCILIB_LITTLE_ENDIAN = 0,
@@ -35,12 +46,15 @@ typedef enum {
PCILIB_REGISTER_RW = 3
} pcilib_register_mode_t;
-
typedef enum {
PCILIB_DEFAULT_PROTOCOL,
IPECAMERA_REGISTER_PROTOCOL
} pcilib_register_protocol_t;
+typedef enum {
+ PCILIB_EVENT_DATA
+} pcilib_event_data_type_t;
+
#define PCILIB_BAR_DETECT ((pcilib_bar_t)-1)
#define PCILIB_REGISTER_INVALID ((pcilib_register_t)-1)
#define PCILIB_ADDRESS_INVALID ((uintptr_t)-1)
@@ -49,6 +63,7 @@ typedef enum {
#define PCILIB_REGISTER_BANK1 1
#define PCILIB_REGISTER_BANK2 2
#define PCILIB_REGISTER_BANK3 3
+#define PCILIB_ALL_EVENTS ((pcilib_event_t)-1)
typedef struct {
pcilib_register_bank_addr_t addr;
@@ -69,6 +84,7 @@ typedef struct {
typedef struct {
pcilib_register_addr_t addr;
+ pcilib_register_size_t offset;
pcilib_register_size_t bits;
pcilib_register_value_t defvalue;
pcilib_register_mode_t mode;
@@ -93,10 +109,28 @@ typedef struct {
int (*write)(pcilib_t *ctx, pcilib_register_bank_description_t *bank, pcilib_register_addr_t addr, uint8_t bits, pcilib_register_value_t value);
} pcilib_protocol_description_t;
+
+typedef int (*pcilib_callback_t)(pcilib_event_t event, pcilib_event_id_t event_id, void *user);
+
+typedef struct {
+ void *(*init)(pcilib_t *ctx);
+ void (*free)(void *ctx);
+
+ int (*reset)(void *ctx);
+
+ int (*start)(void *ctx, pcilib_event_t event_mask, pcilib_callback_t callback, void *user);
+ int (*stop)(void *ctx);
+ int (*trigger)(void *ctx, pcilib_event_t event, size_t trigger_size, void *trigger_data);
+ void* (*get_data)(void *ctx, pcilib_event_id_t event_id, pcilib_event_data_type_t data_type, size_t *size);
+ int (*return_data)(void *ctx, pcilib_event_id_t event_id);
+} pcilib_event_api_description_t;
+
typedef struct {
pcilib_register_description_t *registers;
pcilib_register_bank_description_t *banks;
pcilib_register_range_t *ranges;
+
+ pcilib_event_api_description_t *event_api;
} pcilib_model_description_t;
#ifndef _PCILIB_PCI_C
@@ -112,7 +146,8 @@ void pcilib_close(pcilib_t *ctx);
void *pcilib_map_bar(pcilib_t *ctx, pcilib_bar_t bar);
void pcilib_unmap_bar(pcilib_t *ctx, pcilib_bar_t bar, void *data);
-char *pcilib_resolve_register_address(pcilib_t *ctx, uintptr_t addr);
+char *pcilib_resolve_register_address(pcilib_t *ctx, uintptr_t addr);
+char *pcilib_resolve_data_space(pcilib_t *ctx, uintptr_t addr, size_t *size);
pcilib_register_bank_t pcilib_find_bank(pcilib_t *ctx, const char *bank);
pcilib_register_t pcilib_find_register(pcilib_t *ctx, const char *bank, const char *reg);
@@ -127,4 +162,24 @@ int pcilib_write_register_by_id(pcilib_t *ctx, pcilib_register_t reg, pcilib_reg
int pcilib_read_register(pcilib_t *ctx, const char *bank, const char *regname, pcilib_register_value_t *value);
int pcilib_write_register(pcilib_t *ctx, const char *bank, const char *regname, pcilib_register_value_t value);
+int pcilib_reset(pcilib_t *ctx);
+int pcilib_start(pcilib_t *ctx, pcilib_event_t event_mask, void *callback, void *user);
+int pcilib_stop(pcilib_t *ctx);
+
+int pcilib_trigger(pcilib_t *ctx, pcilib_event_t event, size_t trigger_size, void *trigger_data);
+
+void *pcilib_get_data(pcilib_t *ctx, pcilib_event_id_t event_id, pcilib_event_data_type_t data_type, size_t *size);
+/*
+ * This function is provided to find potentially corrupted data. If the data is overwritten by
+ * the time return_data is called it will return error.
+ */
+int pcilib_return_data(pcilib_t *ctx, pcilib_event_id_t event_id);
+
+/*
+ * @param data - will be allocated and shuld be freed if NULL, otherwise used and size should contain correct size.
+ * In case of failure the content of data is undefined.
+ * @param timeout - will be autotriggered if NULL
+ */
+int pcilib_grab(pcilib_t *ctx, pcilib_event_t event_mask, size_t *size, void **data, const struct timespec *timeout);
+
#endif /* _PCITOOL_PCILIB_H */