summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt2
-rw-r--r--tests/roi.py37
-rw-r--r--tests/timeout.py43
-rw-r--r--uca-ufo-camera.c53
4 files changed, 124 insertions, 11 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 0671aaa..42f2131 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -52,6 +52,8 @@ include_directories(
${GIO2_INCLUDE_DIRS}
${CMAKE_CURRENT_BINARY_DIR})
+link_directories(${UCA_LIBRARY_DIRS})
+
add_library(ucaufo SHARED uca-ufo-camera.c)
target_link_libraries(ucaufo
diff --git a/tests/roi.py b/tests/roi.py
new file mode 100644
index 0000000..fad0717
--- /dev/null
+++ b/tests/roi.py
@@ -0,0 +1,37 @@
+import argparse
+import PyTango
+import tifffile
+
+
+def grab(camera, height=3840, offset=0):
+ if height < 3840:
+ camera.roi_y0 = offset
+ camera.roi_height = height
+ else:
+ camera.roi_height = height
+ camera.roi_y0 = offset
+
+ try:
+ camera.Start()
+ except:
+ camera.Stop()
+ camera.Start()
+
+ frame = camera.image
+ tifffile.imsave('frame-{}-{}.tif'.format(offset, height), frame)
+ camera.Stop()
+
+
+if __name__ == '__main__':
+ parser = argparse.ArgumentParser()
+ parser.add_argument('--device', '-d', type=str, required=True,
+ help="TANGO device path")
+
+ args = parser.parse_args()
+
+ camera = PyTango.DeviceProxy(args.device)
+ camera.trigger_source = 0
+
+ grab(camera)
+ grab(camera, height=3640)
+ grab(camera, height=3640, offset=200)
diff --git a/tests/timeout.py b/tests/timeout.py
new file mode 100644
index 0000000..eede1e7
--- /dev/null
+++ b/tests/timeout.py
@@ -0,0 +1,43 @@
+import time
+import argparse
+import PyTango
+
+
+def grab(camera, timeout, do_trigger):
+ camera.timeout = timeout
+ camera.trigger_source = 1
+
+ try:
+ camera.Start()
+ except:
+ camera.Stop()
+ camera.Start()
+
+ start = time.time()
+
+ try:
+ if do_trigger:
+ camera.Trigger()
+
+ frame = camera.image
+ end = time.time()
+ print("Success after {} s".format(end -start))
+ except PyTango.DevFailed:
+ end = time.time()
+ print("Timeout after {} s".format(end - start))
+
+ camera.Stop()
+
+
+if __name__ == '__main__':
+ parser = argparse.ArgumentParser()
+ parser.add_argument('--device', '-d', type=str, required=True,
+ help="TANGO device path")
+
+ args = parser.parse_args()
+
+ camera = PyTango.DeviceProxy(args.device)
+ grab(camera, 100000, False)
+ grab(camera, 100000, True)
+ grab(camera, 300000, False)
+ grab(camera, 300000, True)
diff --git a/uca-ufo-camera.c b/uca-ufo-camera.c
index 73bec6d..149220c 100644
--- a/uca-ufo-camera.c
+++ b/uca-ufo-camera.c
@@ -81,6 +81,7 @@ GQuark uca_ufo_camera_error_quark()
enum {
PROP_SENSOR_TEMPERATURE = N_BASE_PROPERTIES,
PROP_FPGA_TEMPERATURE,
+ PROP_TIMEOUT,
PROP_UFO_START,
N_MAX_PROPERTIES = 512
};
@@ -115,6 +116,7 @@ struct _UcaUfoCameraPrivate {
GHashTable *property_table; /* maps from prop_id to RegisterInfo* */
GThread *async_thread;
pcilib_t *handle;
+ pcilib_timeout_t timeout;
guint n_bits;
guint roi_height;
guint roi_start;
@@ -204,6 +206,9 @@ update_properties (UcaUfoCameraPrivate *priv)
case PCILIB_REGISTER_RW1I:
flags = G_PARAM_READWRITE;
break;
+ case PCILIB_REGISTER_INCONSISTENT:
+ g_warning ("%s is an inconsistent register, don't know how to handle that", reg->name);
+ break;
}
value = read_register_value (priv->handle, reg->name);
@@ -328,7 +333,6 @@ uca_ufo_camera_start_recording (UcaCamera *camera, GError **error)
"trigger-type", &trigger_type,
NULL);
- set_control_bit (priv, 3, trigger_source == UCA_CAMERA_TRIGGER_SOURCE_SOFTWARE);
set_control_bit (priv, 11, trigger_source == UCA_CAMERA_TRIGGER_SOURCE_AUTO);
set_control_bit (priv, 14, trigger_source == UCA_CAMERA_TRIGGER_SOURCE_EXTERNAL);
set_control_bit (priv, 15, trigger_type == UCA_CAMERA_TRIGGER_TYPE_EDGE &&
@@ -353,7 +357,6 @@ static void
uca_ufo_camera_stop_recording (UcaCamera *camera, GError **error)
{
UcaUfoCameraPrivate *priv;
- UcaCameraTriggerSource trigger_source;
pcilib_event_id_t event_id;
pcilib_event_info_t event_info;
int err;
@@ -365,8 +368,6 @@ uca_ufo_camera_stop_recording (UcaCamera *camera, GError **error)
set_control_bit (priv, 14, FALSE); /* disable external trigger */
set_control_bit (priv, 11, FALSE); /* disable streaming */
- g_object_get (G_OBJECT (camera), "trigger-source", &trigger_source, NULL);
-
if (priv->async_thread) {
err = pcilib_stop(priv->handle, PCILIB_EVENT_FLAG_STOP_ONLY);
PCILIB_SET_ERROR(err, UCA_UFO_CAMERA_ERROR_STOP_RECORDING);
@@ -375,7 +376,7 @@ uca_ufo_camera_stop_recording (UcaCamera *camera, GError **error)
}
/* read stale frames ... */
- while (!pcilib_get_next_event (priv->handle, 0, &event_id, sizeof (pcilib_event_info_t), &event_info))
+ while (!pcilib_get_next_event (priv->handle, priv->timeout, &event_id, sizeof (pcilib_event_info_t), &event_info))
;
err = pcilib_stop (priv->handle, PCILIB_EVENT_FLAGS_DEFAULT);
@@ -405,7 +406,18 @@ uca_ufo_camera_grab(UcaCamera *camera, gpointer data, GError **error)
const gsize size = CMOSIS_SENSOR_WIDTH * priv->roi_height * sizeof(guint16);
- err = pcilib_get_next_event (priv->handle, PCILIB_TIMEOUT_INFINITE, &event_id, sizeof(pcilib_event_info_t), &event_info);
+ err = pcilib_get_next_event (priv->handle, priv->timeout, &event_id, sizeof(pcilib_event_info_t), &event_info);
+
+ /*
+ * Try to recover from errors by flushing pending requests. This is curing
+ * symptoms but not the actual problem.
+ */
+ if (err != 0) {
+ set_control_bit (priv, 2, TRUE);
+ g_usleep (10);
+ set_control_bit (priv, 2, FALSE);
+ }
+
PCILIB_SET_ERROR_RETURN_FALSE (err, UCA_UFO_CAMERA_ERROR_NEXT_EVENT);
gpointer src = pcilib_get_data (priv->handle, event_id, PCILIB_EVENT_DATA, (size_t *) &err);
@@ -443,6 +455,9 @@ uca_ufo_camera_trigger (UcaCamera *camera, GError **error)
priv = UCA_UFO_CAMERA_GET_PRIVATE(camera);
+ set_control_bit (priv, 3, TRUE);
+ set_control_bit (priv, 3, FALSE);
+
/* XXX: What is PCILIB_EVENT0? */
err = pcilib_trigger (priv->handle, PCILIB_EVENT0, 0, NULL);
PCILIB_SET_ERROR (err, UCA_UFO_CAMERA_ERROR_TRIGGER);
@@ -539,6 +554,9 @@ uca_ufo_camera_set_property(GObject *object, guint property_id, const GValue *va
}
}
break;
+ case PROP_TIMEOUT:
+ priv->timeout = g_value_get_uint64 (value);
+ break;
default:
{
RegisterInfo *reg_info;
@@ -637,6 +655,9 @@ uca_ufo_camera_get_property(GObject *object, guint property_id, GValue *value, G
case PROP_NAME:
g_value_set_string (value, "Ufo Camera w/ CMOSIS CMV2000");
break;
+ case PROP_TIMEOUT:
+ g_value_set_uint64 (value, priv->timeout);
+ break;
default:
{
RegisterInfo *reg_info = g_hash_table_lookup (priv->property_table, GINT_TO_POINTER (property_id));
@@ -657,12 +678,14 @@ uca_ufo_camera_finalize(GObject *object)
priv = UCA_UFO_CAMERA_GET_PRIVATE (object);
- int err = pcilib_stop (priv->handle, PCILIB_EVENT_FLAGS_DEFAULT);
- PCILIB_WARN_ON_ERROR (err);
+ if (priv->handle != NULL) {
+ int err = pcilib_stop (priv->handle, PCILIB_EVENT_FLAGS_DEFAULT);
+ PCILIB_WARN_ON_ERROR (err);
- pcilib_close (priv->handle);
- g_clear_error (&priv->construct_error);
+ pcilib_close (priv->handle);
+ }
+ g_clear_error (&priv->construct_error);
G_OBJECT_CLASS (uca_ufo_camera_parent_class)->finalize (object);
}
@@ -734,6 +757,13 @@ uca_ufo_camera_class_init(UcaUfoCameraClass *klass)
-G_MAXDOUBLE, G_MAXDOUBLE, 0.0,
G_PARAM_READABLE);
+ ufo_properties[PROP_TIMEOUT] =
+ g_param_spec_uint64("timeout",
+ "Timeout in milliseconds",
+ "Timeout in milliseconds",
+ 0, G_MAXUINT64, 100000,
+ G_PARAM_READWRITE);
+
g_type_class_add_private(klass, sizeof(UcaUfoCameraPrivate));
}
@@ -747,6 +777,7 @@ uca_ufo_camera_init(UcaUfoCamera *self)
self->priv = priv = UCA_UFO_CAMERA_GET_PRIVATE(self);
priv->construct_error = NULL;
priv->async_thread = NULL;
+ priv->timeout = 100000;
if (!setup_pcilib (priv))
return;
@@ -762,7 +793,7 @@ uca_ufo_camera_init(UcaUfoCamera *self)
}
G_MODULE_EXPORT GType
-uca_camera_get_type (void)
+camera_plugin_get_type (void)
{
return UCA_TYPE_UFO_CAMERA;
}