From 252524d32fea5fa63e49f500a1641a619946c036 Mon Sep 17 00:00:00 2001
From: "Suren A. Chilingaryan" <csa@dside.dyndns.org>
Date: Tue, 9 Oct 2012 17:53:27 +0200
Subject: Support both UFO4 and UFO5 frame formats

---
 ipecamera/ipecamera.c | 21 +++++++++++++++++----
 ipecamera/private.h   |  4 ++++
 ipecamera/reader.c    | 18 +++++++++++++-----
 3 files changed, 34 insertions(+), 9 deletions(-)

(limited to 'ipecamera')

diff --git a/ipecamera/ipecamera.c b/ipecamera/ipecamera.c
index 1ea54f4..f8136d4 100644
--- a/ipecamera/ipecamera.c
+++ b/ipecamera/ipecamera.c
@@ -66,6 +66,9 @@
 	} \
     }
 
+#define IPECAMERA_GET_EXPECTED_STATUS(ctx) ((ctx->firmware == 4)?IPECAMERA_EXPECTED_STATUS_4:IPECAMERA_EXPECTED_STATUS)
+#define CHECK_STATUS_REG() CHECK_REG(status_reg, IPECAMERA_GET_EXPECTED_STATUS(ctx))
+
 #define CHECK_VALUE(value, val) \
     if ((!err)&&(value != val)) { \
 	pcilib_error("Unexpected value (0x%x) in data stream (0x%x is expected)", value, val); \
@@ -103,6 +106,7 @@ pcilib_context_t *ipecamera_init(pcilib_t *pcilib) {
 	FIND_REG(exposure_reg, "cmosis", "cmosis_exp_time");
 	FIND_REG(flip_reg, "cmosis", "cmosis_image_flipping");
 	
+	FIND_REG(firmware_version_reg, "fpga", "firmware_version");
 	FIND_REG(adc_resolution_reg, "fpga", "adc_resolution");
 	FIND_REG(output_mode_reg, "fpga", "output_mode");
 	
@@ -224,15 +228,14 @@ int ipecamera_reset(pcilib_context_t *vctx) {
 
     usleep(10000);
 
-        
     err = pcilib_read_register_by_id(pcilib, status, &value);
     if (err) {
 	pcilib_error("Error reading status register");
 	return err;
     }
 
-    if (value != IPECAMERA_EXPECTED_STATUS) {
-	pcilib_error("Unexpected value (%lx) of status register, expected %lx", value, IPECAMERA_EXPECTED_STATUS);
+    if (value != IPECAMERA_GET_EXPECTED_STATUS(ctx)) {
+	pcilib_error("Unexpected value (%lx) of status register, expected %lx", value, IPECAMERA_GET_EXPECTED_STATUS(ctx));
 	return PCILIB_ERROR_VERIFY;
     }
 
@@ -261,10 +264,20 @@ int ipecamera_start(pcilib_context_t *vctx, pcilib_event_t event_mask, pcilib_ev
     }
 
 
+    GET_REG(firmware_version_reg, value);
+    switch (value) {
+     case 4:
+     case 5:
+	ctx->firmware = value;
+	break;
+     default:
+        pcilib_error("Unsupported version of firmware (%lu)", value);
+    }
+
 	// Allow readout and clean the FRAME_REQUEST mode if set for some reason
     SET_REG(control_reg, IPECAMERA_IDLE|IPECAMERA_READOUT_FLAG);
     usleep(IPECAMERA_SLEEP_TIME);
-    CHECK_REG(status_reg, IPECAMERA_EXPECTED_STATUS);
+    CHECK_STATUS_REG();
     if (err) return err;
 
     ctx->event_id = 0;
diff --git a/ipecamera/private.h b/ipecamera/private.h
index a200b75..f5300a2 100644
--- a/ipecamera/private.h
+++ b/ipecamera/private.h
@@ -18,7 +18,9 @@
 #define IPECAMERA_NOFRAME_PREPROC_SLEEP 100
 
 #define IPECAMERA_MAX_LINES 1088
+#define IPECAMERA_EXPECTED_STATUS_4 0x08409FFFF
 #define IPECAMERA_EXPECTED_STATUS 0x08449FFFF
+
 #define IPECAMERA_END_OF_SEQUENCE 0x1F001001
 
 #define IPECAMERA_MAX_CHANNELS 16
@@ -84,6 +86,7 @@ struct ipecamera_s {
     pcilib_register_t exposure_reg;
     pcilib_register_t flip_reg;
 
+    pcilib_register_t firmware_version_reg;
     pcilib_register_t adc_resolution_reg;
     pcilib_register_t output_mode_reg;
     
@@ -116,6 +119,7 @@ struct ipecamera_s {
     size_t image_size;		/**< Size of a single image in bytes */
     
     size_t max_frames;		/**< Maximal number of frames what may be buffered in camera DDR memory */
+    int firmware;		/**< Firmware version */
     int cmosis_outputs;		/**< Number of active cmosis outputs: 4 or 16 */
     int width, height;
 
diff --git a/ipecamera/reader.c b/ipecamera/reader.c
index cf5fc5c..048f536 100644
--- a/ipecamera/reader.c
+++ b/ipecamera/reader.c
@@ -21,14 +21,22 @@
 
 
 int ipecamera_compute_buffer_size(ipecamera_t *ctx, size_t lines) {
-    const size_t line_size = (1 + IPECAMERA_PIXELS_PER_CHANNEL) * 32;
     const size_t header_size = 8 * sizeof(ipecamera_payload_t);
     const size_t footer_size = 8 * sizeof(ipecamera_payload_t);
 
-    size_t raw_size, padded_blocks;
-    
-    raw_size = header_size + lines * line_size - 32 + footer_size;
-    raw_size *= 16 / ctx->cmosis_outputs;
+    size_t line_size, raw_size, padded_blocks;
+
+
+    switch (ctx->firmware) {
+     case 4:
+	line_size = IPECAMERA_MAX_CHANNELS * (2 + IPECAMERA_PIXELS_PER_CHANNEL / 3) * sizeof(ipecamera_payload_t);
+	raw_size = header_size + lines * line_size + footer_size;
+	break;
+     default:
+	line_size = (1 + IPECAMERA_PIXELS_PER_CHANNEL) * 32; 
+	raw_size = header_size + lines * line_size - 32 + footer_size;
+	raw_size *= 16 / ctx->cmosis_outputs;
+    }
 
     padded_blocks = raw_size / IPECAMERA_DMA_PACKET_LENGTH + ((raw_size % IPECAMERA_DMA_PACKET_LENGTH)?1:0);
     
-- 
cgit v1.2.3