summaryrefslogtreecommitdiffstats
path: root/plugins/ufo/uca-ufo-camera.c
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/ufo/uca-ufo-camera.c')
-rw-r--r--plugins/ufo/uca-ufo-camera.c323
1 files changed, 231 insertions, 92 deletions
diff --git a/plugins/ufo/uca-ufo-camera.c b/plugins/ufo/uca-ufo-camera.c
index c4e05b0..145c2ee 100644
--- a/plugins/ufo/uca-ufo-camera.c
+++ b/plugins/ufo/uca-ufo-camera.c
@@ -15,6 +15,7 @@
with this library; if not, write to the Free Software Foundation, Inc., 51
Franklin St, Fifth Floor, Boston, MA 02110, USA */
+#include <gio/gio.h>
#include <gmodule.h>
#include <stdlib.h>
#include <stdio.h>
@@ -33,9 +34,22 @@
return; \
}
+#define PCILIB_SET_ERROR_RETURN_FALSE(err, err_type) \
+ if (err != 0) { \
+ g_set_error(error, UCA_UFO_CAMERA_ERROR, \
+ err_type, \
+ "%s:%i pcilib: %s (errcode = %d)", \
+ __FILE__, __LINE__, strerror(err), err);\
+ return FALSE; \
+ }
+
#define UCA_UFO_CAMERA_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), UCA_TYPE_UFO_CAMERA, UcaUfoCameraPrivate))
-G_DEFINE_TYPE(UcaUfoCamera, uca_ufo_camera, UCA_TYPE_CAMERA)
+static void uca_ufo_camera_initable_iface_init (GInitableIface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (UcaUfoCamera, uca_ufo_camera, UCA_TYPE_CAMERA,
+ G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE,
+ uca_ufo_camera_initable_iface_init))
static const guint SENSOR_WIDTH = 2048;
static const guint SENSOR_HEIGHT = 1088;
@@ -80,7 +94,6 @@ static gint base_overrideables[] = {
PROP_ROI_HEIGHT_MULTIPLIER,
PROP_HAS_STREAMING,
PROP_HAS_CAMRAM_RECORDING,
- PROP_TRIGGER_MODE,
0,
};
@@ -92,9 +105,11 @@ typedef struct _RegisterInfo {
static GParamSpec *ufo_properties[N_MAX_PROPERTIES] = { NULL, };
static guint N_PROPERTIES;
-static GHashTable *ufo_property_table; /* maps from prop_id to RegisterInfo* */
struct _UcaUfoCameraPrivate {
+ GError *construct_error;
+ GHashTable *property_table; /* maps from prop_id to RegisterInfo* */
+ GThread *async_thread;
pcilib_t *handle;
pcilib_timeout_t timeout;
guint n_bits;
@@ -102,7 +117,6 @@ struct _UcaUfoCameraPrivate {
FPGA_48MHZ = 0,
FPGA_40MHZ
} frequency;
- UcaCameraTrigger trigger;
};
static void
@@ -126,7 +140,8 @@ read_register_value (pcilib_t *handle, const gchar *name)
return (guint) reg_value;
}
-static int event_callback(pcilib_event_id_t event_id, pcilib_event_info_t *info, void *user)
+static int
+event_callback(pcilib_event_id_t event_id, pcilib_event_info_t *info, void *user)
{
UcaCamera *camera = UCA_CAMERA(user);
UcaUfoCameraPrivate *priv = UCA_UFO_CAMERA_GET_PRIVATE(camera);
@@ -134,47 +149,32 @@ static int event_callback(pcilib_event_id_t event_id, pcilib_event_info_t *info,
void *buffer = pcilib_get_data(priv->handle, event_id, PCILIB_EVENT_DATA, &error);
- if (buffer == NULL) {
- pcilib_trigger(priv->handle, PCILIB_EVENT0, 0, NULL);
+ if (buffer == NULL)
return PCILIB_STREAMING_CONTINUE;
- }
- camera->grab_func(buffer, camera->user_data);
- pcilib_return_data(priv->handle, event_id, PCILIB_EVENT_DATA, buffer);
- pcilib_trigger(priv->handle, PCILIB_EVENT0, 0, NULL);
+ camera->grab_func (buffer, camera->user_data);
+ pcilib_return_data (priv->handle, event_id, PCILIB_EVENT_DATA, buffer);
return PCILIB_STREAMING_CONTINUE;
}
-G_MODULE_EXPORT UcaCamera *
-uca_camera_impl_new (GError **error)
+static guint
+update_properties (UcaUfoCameraPrivate *priv)
{
- pcilib_model_t model = PCILIB_MODEL_DETECT;
- pcilib_model_description_t *model_description;
- pcilib_t *handle = pcilib_open("/dev/fpga0", model);
- guint prop = PROP_UFO_START;
- guint adc_resolution;
-
- if (handle == NULL) {
- g_set_error(error, UCA_UFO_CAMERA_ERROR, UCA_UFO_CAMERA_ERROR_INIT,
- "Initializing pcilib failed");
- return NULL;
- }
+ guint prop;
+ pcilib_model_description_t *description;
- pcilib_set_error_handler(&error_handler, &error_handler);
+ prop = PROP_UFO_START;
+ description = pcilib_get_model_description (priv->handle);
- /* Generate properties from model description */
- model_description = pcilib_get_model_description(handle);
- ufo_property_table = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_free);
-
- for (guint i = 0; model_description->registers[i].name != NULL; i++) {
+ for (guint i = 0; description->registers[i].name != NULL; i++) {
GParamFlags flags = 0;
RegisterInfo *reg_info;
gchar *prop_name;
pcilib_register_description_t *reg;
pcilib_register_value_t value;
- reg = &model_description->registers[i];
+ reg = &description->registers[i];
switch (reg->mode) {
case PCILIB_REGISTER_R:
@@ -190,12 +190,12 @@ uca_camera_impl_new (GError **error)
break;
}
- pcilib_read_register (handle, NULL, reg->name, &value);
+ pcilib_read_register (priv->handle, NULL, reg->name, &value);
reg_info = g_new0 (RegisterInfo, 1);
reg_info->name = g_strdup (reg->name);
reg_info->cached_value = (guint32) value;
- g_hash_table_insert (ufo_property_table, GINT_TO_POINTER (prop), reg_info);
+ g_hash_table_insert (priv->property_table, GINT_TO_POINTER (prop), reg_info);
prop_name = g_strdup_printf ("ufo-%s", reg->name);
ufo_properties[prop++] = g_param_spec_uint (
@@ -205,13 +205,32 @@ uca_camera_impl_new (GError **error)
g_free (prop_name);
}
- N_PROPERTIES = prop;
+ return prop;
+}
- UcaUfoCamera *camera = g_object_new(UCA_TYPE_UFO_CAMERA, NULL);
- UcaUfoCameraPrivate *priv = UCA_UFO_CAMERA_GET_PRIVATE(camera);
+static gboolean
+setup_pcilib (UcaUfoCameraPrivate *priv)
+{
+ pcilib_model_t model;
+ guint adc_resolution;
+
+ model = PCILIB_MODEL_DETECT;
+ priv->handle = pcilib_open("/dev/fpga0", model);
- priv->frequency = read_register_value (handle, "bit_mode");
- adc_resolution = read_register_value (handle, "adc_resolution");
+ if (priv->handle == NULL) {
+ g_set_error (&priv->construct_error,
+ UCA_UFO_CAMERA_ERROR, UCA_UFO_CAMERA_ERROR_INIT,
+ "Initializing pcilib failed");
+ return FALSE;
+ }
+
+ pcilib_set_error_handler (&error_handler, &error_handler);
+
+ priv->property_table = g_hash_table_new_full (g_direct_hash, g_direct_equal,
+ NULL, g_free);
+ N_PROPERTIES = update_properties (priv);
+ priv->frequency = read_register_value (priv->handle, "bit_mode");
+ adc_resolution = read_register_value (priv->handle, "adc_resolution");
switch (adc_resolution) {
case 0:
@@ -225,59 +244,115 @@ uca_camera_impl_new (GError **error)
break;
}
- priv->handle = handle;
+ return TRUE;
+}
+
+static void
+set_control_bit (UcaUfoCameraPrivate *priv, guint bit, gboolean set)
+{
+ static const gchar *name = "control";
+ pcilib_register_value_t flags;
+ pcilib_register_value_t mask;
+
+ pcilib_read_register (priv->handle, NULL, name, &flags);
+ mask = 1 << bit;
+
+ if (set)
+ flags |= mask;
+ else
+ flags = flags & ~mask;
- return UCA_CAMERA (camera);
+ pcilib_write_register(priv->handle, NULL, name, flags);
}
-static void uca_ufo_camera_start_recording(UcaCamera *camera, GError **error)
+static void
+set_streaming (UcaUfoCameraPrivate *priv, gboolean enable)
+{
+ set_control_bit (priv, 11, enable);
+}
+
+static gpointer
+stream_async (UcaCamera *camera)
{
UcaUfoCameraPrivate *priv;
+ priv = UCA_UFO_CAMERA_GET_PRIVATE (camera);
+ pcilib_stream (priv->handle, &event_callback, camera);
+
+ return NULL;
+}
+
+static void
+uca_ufo_camera_start_recording(UcaCamera *camera, GError **error)
+{
+ UcaUfoCameraPrivate *priv;
+ UcaCameraTrigger trigger;
gdouble exposure_time;
- int err;
+ gboolean transfer_async;
+ int err;
g_return_if_fail(UCA_IS_UFO_CAMERA(camera));
priv = UCA_UFO_CAMERA_GET_PRIVATE(camera);
+
+ g_object_get (G_OBJECT(camera),
+ "transfer-asynchronously", &transfer_async,
+ "exposure-time", &exposure_time,
+ "trigger-mode", &trigger,
+ NULL);
+
err = pcilib_start(priv->handle, PCILIB_EVENT_DATA, PCILIB_EVENT_FLAGS_DEFAULT);
PCILIB_SET_ERROR(err, UCA_UFO_CAMERA_ERROR_START_RECORDING);
- gboolean transfer_async = FALSE;
- g_object_get(G_OBJECT(camera),
- "transfer-asynchronously", &transfer_async,
- "exposure-time", &exposure_time,
- "trigger-mode", &priv->trigger,
- NULL);
+ if (trigger == UCA_CAMERA_TRIGGER_AUTO)
+ set_streaming (priv, TRUE);
priv->timeout = ((pcilib_timeout_t) (exposure_time * 1000 + 50.0) * 1000);
- if (transfer_async) {
- pcilib_trigger(priv->handle, PCILIB_EVENT0, 0, NULL);
- pcilib_stream(priv->handle, &event_callback, camera);
- }
+ if (transfer_async)
+ priv->async_thread = g_thread_create ((GThreadFunc) stream_async, camera, TRUE, error);
}
-static void uca_ufo_camera_stop_recording(UcaCamera *camera, GError **error)
+static void
+uca_ufo_camera_stop_recording(UcaCamera *camera, GError **error)
{
+ UcaUfoCameraPrivate *priv;
+ UcaCameraTrigger trigger;
g_return_if_fail(UCA_IS_UFO_CAMERA(camera));
- UcaUfoCameraPrivate *priv = UCA_UFO_CAMERA_GET_PRIVATE(camera);
- int err = pcilib_stop(priv->handle, PCILIB_EVENT_FLAGS_DEFAULT);
- PCILIB_SET_ERROR(err, UCA_UFO_CAMERA_ERROR_START_RECORDING);
+
+ priv = UCA_UFO_CAMERA_GET_PRIVATE(camera);
+
+ g_object_get (G_OBJECT (camera), "trigger-mode", &trigger, NULL);
+
+ if (priv->async_thread) {
+ int err = pcilib_stop(priv->handle, PCILIB_EVENT_FLAG_STOP_ONLY);
+ PCILIB_SET_ERROR(err, UCA_UFO_CAMERA_ERROR_STOP_RECORDING);
+ g_thread_join(priv->async_thread);
+ priv->async_thread = NULL;
+ }
+
+ int err = pcilib_stop (priv->handle, PCILIB_EVENT_FLAGS_DEFAULT);
+ PCILIB_SET_ERROR(err, UCA_UFO_CAMERA_ERROR_STOP_RECORDING);
+
+ if (trigger == UCA_CAMERA_TRIGGER_AUTO)
+ set_streaming (priv, FALSE);
}
-static void uca_ufo_camera_start_readout(UcaCamera *camera, GError **error)
+static void
+uca_ufo_camera_start_readout(UcaCamera *camera, GError **error)
{
g_return_if_fail(UCA_IS_UFO_CAMERA(camera));
}
-static void uca_ufo_camera_stop_readout(UcaCamera *camera, GError **error)
+static void
+uca_ufo_camera_stop_readout(UcaCamera *camera, GError **error)
{
g_return_if_fail(UCA_IS_UFO_CAMERA(camera));
}
-static void uca_ufo_camera_grab(UcaCamera *camera, gpointer *data, GError **error)
+static gboolean
+uca_ufo_camera_grab(UcaCamera *camera, gpointer data, GError **error)
{
- g_return_if_fail(UCA_IS_UFO_CAMERA(camera));
+ g_return_val_if_fail (UCA_IS_UFO_CAMERA(camera), FALSE);
UcaUfoCameraPrivate *priv = UCA_UFO_CAMERA_GET_PRIVATE(camera);
pcilib_event_id_t event_id;
pcilib_event_info_t event_info;
@@ -285,21 +360,13 @@ static void uca_ufo_camera_grab(UcaCamera *camera, gpointer *data, GError **erro
const gsize size = SENSOR_WIDTH * SENSOR_HEIGHT * sizeof(guint16);
- if (priv->trigger != UCA_CAMERA_TRIGGER_EXTERNAL) {
- err = pcilib_trigger(priv->handle, PCILIB_EVENT0, 0, NULL);
- PCILIB_SET_ERROR(err, UCA_UFO_CAMERA_ERROR_TRIGGER);
- }
-
- err = pcilib_get_next_event(priv->handle, priv->timeout, &event_id, sizeof(pcilib_event_info_t), &event_info);
- PCILIB_SET_ERROR(err, UCA_UFO_CAMERA_ERROR_NEXT_EVENT);
-
- if (*data == NULL)
- *data = g_malloc0(SENSOR_WIDTH * SENSOR_HEIGHT * sizeof(guint16));
+ err = pcilib_get_next_event (priv->handle, priv->timeout, &event_id, sizeof(pcilib_event_info_t), &event_info);
+ 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);
+ gpointer src = pcilib_get_data (priv->handle, event_id, PCILIB_EVENT_DATA, (size_t *) &err);
if (src == NULL)
- PCILIB_SET_ERROR(err, UCA_UFO_CAMERA_ERROR_NO_DATA);
+ PCILIB_SET_ERROR_RETURN_FALSE (err, UCA_UFO_CAMERA_ERROR_NO_DATA);
/*
* Apparently, we checked that err equals total size in previous version.
@@ -309,15 +376,29 @@ static void uca_ufo_camera_grab(UcaCamera *camera, gpointer *data, GError **erro
*/
/* assert(err == size); */
- memcpy(*data, src, size);
+ memcpy (data, src, size);
/*
* Another problem here. What does this help us? At this point we have
* already overwritten the original buffer but can only know here if the
* data is corrupted.
*/
- err = pcilib_return_data(priv->handle, event_id, PCILIB_EVENT_DATA, data);
- PCILIB_SET_ERROR(err, UCA_UFO_CAMERA_ERROR_MAYBE_CORRUPTED);
+ err = pcilib_return_data (priv->handle, event_id, PCILIB_EVENT_DATA, data);
+ PCILIB_SET_ERROR_RETURN_FALSE (err, UCA_UFO_CAMERA_ERROR_MAYBE_CORRUPTED);
+
+ return TRUE;
+}
+
+static void
+uca_ufo_camera_trigger (UcaCamera *camera, GError **error)
+{
+ UcaUfoCameraPrivate *priv;
+ g_return_if_fail (UCA_IS_UFO_CAMERA(camera));
+
+ priv = UCA_UFO_CAMERA_GET_PRIVATE(camera);
+
+ /* XXX: What is PCILIB_EVENT0? */
+ pcilib_trigger (priv->handle, PCILIB_EVENT0, 0, NULL);
}
static void
@@ -340,19 +421,18 @@ uca_ufo_camera_set_property(GObject *object, guint property_id, const GValue *va
g_debug("ROI feature not implemented yet");
break;
- case PROP_TRIGGER_MODE:
- priv->trigger = g_value_get_enum (value);
- break;
-
default:
{
- RegisterInfo *reg_info = g_hash_table_lookup (ufo_property_table, GINT_TO_POINTER (property_id));
+ RegisterInfo *reg_info;
+
+ reg_info = g_hash_table_lookup (priv->property_table,
+ GINT_TO_POINTER (property_id));
if (reg_info != NULL) {
pcilib_register_value_t reg_value;
reg_value = g_value_get_uint (value);
- pcilib_write_register(priv->handle, NULL, reg_info->name, reg_value);
+ pcilib_write_register (priv->handle, NULL, reg_info->name, reg_value);
pcilib_read_register (priv->handle, NULL, reg_info->name, &reg_value);
reg_info->cached_value = (guint) reg_value;
}
@@ -441,12 +521,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_TRIGGER_MODE:
- g_value_set_enum (value, priv->trigger);
- break;
default:
{
- RegisterInfo *reg_info = g_hash_table_lookup (ufo_property_table, GINT_TO_POINTER (property_id));
+ RegisterInfo *reg_info = g_hash_table_lookup (priv->property_table, GINT_TO_POINTER (property_id));
if (reg_info != NULL)
g_value_set_uint (value, reg_info->cached_value);
@@ -457,14 +534,56 @@ uca_ufo_camera_get_property(GObject *object, guint property_id, GValue *value, G
}
}
-static void uca_ufo_camera_finalize(GObject *object)
+static void
+uca_ufo_camera_finalize(GObject *object)
{
- UcaUfoCameraPrivate *priv = UCA_UFO_CAMERA_GET_PRIVATE(object);
- pcilib_close(priv->handle);
- G_OBJECT_CLASS(uca_ufo_camera_parent_class)->finalize(object);
+ UcaUfoCameraPrivate *priv;
+
+ priv = UCA_UFO_CAMERA_GET_PRIVATE (object);
+
+ pcilib_close (priv->handle);
+ g_clear_error (&priv->construct_error);
+
+ G_OBJECT_CLASS (uca_ufo_camera_parent_class)->finalize (object);
}
-static void uca_ufo_camera_class_init(UcaUfoCameraClass *klass)
+static gboolean
+ufo_ufo_camera_initable_init (GInitable *initable,
+ GCancellable *cancellable,
+ GError **error)
+{
+ UcaUfoCamera *camera;
+ UcaUfoCameraPrivate *priv;
+
+ g_return_val_if_fail (UCA_IS_UFO_CAMERA (initable), FALSE);
+
+ if (cancellable != NULL) {
+ g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
+ "Cancellable initialization not supported");
+ return FALSE;
+ }
+
+ camera = UCA_UFO_CAMERA (initable);
+ priv = camera->priv;
+
+ if (priv->construct_error != NULL) {
+ if (error)
+ *error = g_error_copy (priv->construct_error);
+
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static void
+uca_ufo_camera_initable_iface_init (GInitableIface *iface)
+{
+ iface->init = ufo_ufo_camera_initable_init;
+}
+
+static void
+uca_ufo_camera_class_init(UcaUfoCameraClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
gobject_class->set_property = uca_ufo_camera_set_property;
@@ -477,6 +596,7 @@ static void uca_ufo_camera_class_init(UcaUfoCameraClass *klass)
camera_class->start_readout = uca_ufo_camera_start_readout;
camera_class->stop_readout = uca_ufo_camera_stop_readout;
camera_class->grab = uca_ufo_camera_grab;
+ camera_class->trigger = uca_ufo_camera_trigger;
for (guint i = 0; base_overrideables[i] != 0; i++)
g_object_class_override_property(gobject_class, base_overrideables[i], uca_camera_props[base_overrideables[i]]);
@@ -505,7 +625,26 @@ static void uca_ufo_camera_class_init(UcaUfoCameraClass *klass)
g_type_class_add_private(klass, sizeof(UcaUfoCameraPrivate));
}
-static void uca_ufo_camera_init(UcaUfoCamera *self)
+static void
+uca_ufo_camera_init(UcaUfoCamera *self)
+{
+ UcaCamera *camera;
+ UcaUfoCameraPrivate *priv;
+
+ self->priv = priv = UCA_UFO_CAMERA_GET_PRIVATE(self);
+ priv->construct_error = NULL;
+ priv->async_thread = NULL;
+
+ if (!setup_pcilib (priv))
+ return;
+
+ camera = UCA_CAMERA (self);
+ uca_camera_register_unit (camera, "sensor-temperature", UCA_UNIT_DEGREE_CELSIUS);
+ uca_camera_register_unit (camera, "fpga-temperature", UCA_UNIT_DEGREE_CELSIUS);
+}
+
+G_MODULE_EXPORT GType
+uca_camera_get_type (void)
{
- self->priv = UCA_UFO_CAMERA_GET_PRIVATE(self);
+ return UCA_TYPE_UFO_CAMERA;
}