summaryrefslogtreecommitdiffstats
path: root/plugins/dexela/uca-dexela-camera.c
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/dexela/uca-dexela-camera.c')
-rw-r--r--plugins/dexela/uca-dexela-camera.c543
1 files changed, 0 insertions, 543 deletions
diff --git a/plugins/dexela/uca-dexela-camera.c b/plugins/dexela/uca-dexela-camera.c
deleted file mode 100644
index 3e22c06..0000000
--- a/plugins/dexela/uca-dexela-camera.c
+++ /dev/null
@@ -1,543 +0,0 @@
-/* Copyright (C) 2011, 2012 Mihael Koep <koep@softwareschneiderei.de>
- (Softwareschneiderei GmbH)
-
- This library is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by the
- Free Software Foundation; either version 2.1 of the License, or (at your
- option) any later version.
-
- This library is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
- FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
- details.
-
- You should have received a copy of the GNU Lesser General Public License along
- with this library; if not, write to the Free Software Foundation, Inc., 51
- Franklin St, Fifth Floor, Boston, MA 02110, USA */
-
-#include <string.h>
-#include <gio/gio.h>
-#include <gmodule.h>
-#include <math.h>
-#include "uca-dexela-camera.h"
-#include "dexela/dexela_api.h"
-#include "software-roi.h"
-
-#define UCA_DEXELA_CAMERA_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), UCA_TYPE_DEXELA_CAMERA, UcaDexelaCameraPrivate))
-
-static void uca_dexela_camera_initable_iface_init (GInitableIface *iface);
-
-G_DEFINE_TYPE_WITH_CODE (UcaDexelaCamera, uca_dexela_camera, UCA_TYPE_CAMERA,
- G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE,
- uca_dexela_camera_initable_iface_init))
-/**
- * UcaDexelaCameraError:
- * @UCA_DEXELA_CAMERA_ERROR_LIBDEXELA_INIT: Initializing libdexela failed
- */
-GQuark uca_dexela_camera_error_quark()
-{
- return g_quark_from_static_string("uca-dexela-camera-error-quark");
-}
-
-enum {
- PROP_GAIN_MODE = N_BASE_PROPERTIES,
- PROP_TEST_MODE,
- N_PROPERTIES
-};
-
-static gint base_overrideables[] = {
- PROP_NAME,
- PROP_SENSOR_WIDTH,
- PROP_SENSOR_HEIGHT,
- PROP_SENSOR_PIXEL_WIDTH,
- PROP_SENSOR_PIXEL_HEIGHT,
- PROP_SENSOR_BITDEPTH,
- PROP_SENSOR_HORIZONTAL_BINNING,
- PROP_SENSOR_HORIZONTAL_BINNINGS,
- PROP_SENSOR_VERTICAL_BINNING,
- PROP_SENSOR_VERTICAL_BINNINGS,
- PROP_EXPOSURE_TIME,
- PROP_TRIGGER_SOURCE,
- PROP_ROI_X,
- PROP_ROI_Y,
- PROP_ROI_WIDTH,
- PROP_ROI_HEIGHT,
- PROP_ROI_WIDTH_MULTIPLIER,
- PROP_ROI_HEIGHT_MULTIPLIER,
- PROP_HAS_STREAMING,
- PROP_HAS_CAMRAM_RECORDING,
- 0
-};
-
-static GParamSpec *dexela_properties[N_PROPERTIES] = { NULL, };
-
-static const gdouble MICROS_TO_SECONDS_FACTOR = 1e6d;
-static const gdouble MINIMUM_EXPOSURE_TIME_IN_SECONDS = 0.017d; // 17ms as per documentation
-static const gdouble PIXEL_SIZE = 74.8e-6; // 74.8µm as per data sheet
-
-struct _UcaDexelaCameraPrivate {
- GError* init_error;
-
- GValueArray *binnings;
- guint width;
- guint height;
- guint roi_x;
- guint roi_y;
- guint roi_width;
- guint roi_height;
- guint bits;
- gsize num_bytes;
- UcaCameraTriggerSource uca_trigger_source;
- UcaCameraTriggerType uca_trigger_type;
-};
-
-/**
- * Hardcode possible binnings for now
- */
-static void fill_binnings(UcaDexelaCameraPrivate *priv)
-{
- GValue val = {0};
- g_value_init(&val, G_TYPE_UINT);
-
- priv->binnings = g_value_array_new(3);
- g_value_set_uint(&val, 1);
- g_value_array_append(priv->binnings, &val);
- g_value_set_uint(&val, 2);
- g_value_array_append(priv->binnings, &val);
- g_value_set_uint(&val, 4);
- g_value_array_append(priv->binnings, &val);
-}
-
-static void map_dexela_trigger_mode_to_uca_source(UcaDexelaCameraPrivate *priv, GValue* value, TriggerMode mode)
-{
- if (mode == SOFTWARE) {
- priv->uca_trigger_source = UCA_CAMERA_TRIGGER_SOURCE_AUTO;
- }
- if (mode == EDGE || mode == DURATION) {
- priv->uca_trigger_source = UCA_CAMERA_TRIGGER_SOURCE_EXTERNAL;
- }
- g_value_set_enum(value, priv->uca_trigger_source);
-}
-
-static void map_dexela_trigger_mode_to_uca_type(UcaDexelaCameraPrivate *priv, GValue* value, TriggerMode mode)
-{
- if (mode == EDGE) {
- priv->uca_trigger_type = UCA_CAMERA_TRIGGER_TYPE_EDGE;
- }
- if (mode == DURATION) {
- priv->uca_trigger_type = UCA_CAMERA_TRIGGER_TYPE_LEVEL;
- }
- g_value_set_enum(value, priv->uca_trigger_type);
-}
-
-static void set_triggering(UcaDexelaCameraPrivate *priv, UcaCameraTriggerSource source, UcaCameraTriggerType type)
-{
- priv->uca_trigger_source = source;
- priv->uca_trigger_type = type;
- if (source == UCA_CAMERA_TRIGGER_SOURCE_AUTO) {
- dexela_set_trigger_mode(SOFTWARE);
- return;
- }
- if (source == UCA_CAMERA_TRIGGER_SOURCE_SOFTWARE) {
- dexela_set_trigger_mode(SOFTWARE);
- return;
- }
- if (source == UCA_CAMERA_TRIGGER_SOURCE_EXTERNAL) {
- if (type == UCA_CAMERA_TRIGGER_TYPE_EDGE) {
- dexela_set_trigger_mode(EDGE);
- return;
- }
- if (type == UCA_CAMERA_TRIGGER_TYPE_LEVEL) {
- dexela_set_trigger_mode(DURATION);
- return;
- }
- }
- g_warning("Unsupported uca trigger source and type: %d/%d", source, type);
-}
-
-static gboolean is_binning_allowed(UcaDexelaCameraPrivate *priv, guint binning)
-{
- for (int i = 0; i < priv->binnings->n_values; i++) {
- guint allowedBinning = g_value_get_uint(g_value_array_get_nth(priv->binnings, i));
- if (binning == allowedBinning) {
- return TRUE;
- }
- }
- return FALSE;
-}
-
-static guint real_width(UcaDexelaCameraPrivate *priv)
-{
- return priv->width / dexela_get_binning_mode_horizontal();
-}
-
-static guint real_height(UcaDexelaCameraPrivate *priv)
-{
- return priv->height / dexela_get_binning_mode_vertical();
-}
-
-static void adjust_roi_width(UcaDexelaCameraPrivate *priv, guint requested_width)
-{
- guint maxRoiWidth = real_width(priv) - priv->roi_x;
- priv->roi_width = min(maxRoiWidth, requested_width);
-}
-
-static void adjust_roi_height(UcaDexelaCameraPrivate *priv, guint requested_height)
-{
- guint maxRoiHeight = real_height(priv) - priv->roi_y;
- priv->roi_height = min(maxRoiHeight, requested_height);
-}
-
-static void uca_dexela_camera_get_property(GObject *object, guint property_id, GValue *value, GParamSpec *pspec)
-{
- UcaDexelaCameraPrivate *priv = UCA_DEXELA_CAMERA_GET_PRIVATE(object);
-
- switch (property_id) {
- case PROP_NAME:
- {
- gchar* model = dexela_get_model();
- g_value_set_string(value, g_strdup_printf("Dexela %s", model));
- g_free(model);
- break;
- }
- case PROP_EXPOSURE_TIME:
- {
- g_value_set_double(value, dexela_get_exposure_time_micros() / MICROS_TO_SECONDS_FACTOR);
- break;
- }
- case PROP_HAS_CAMRAM_RECORDING:
- {
- g_value_set_boolean(value, FALSE);
- break;
- }
- case PROP_HAS_STREAMING:
- {
- g_value_set_boolean(value, FALSE);
- break;
- }
- case PROP_SENSOR_BITDEPTH:
- {
- g_value_set_uint(value, priv->bits);
- break;
- }
- case PROP_SENSOR_WIDTH:
- {
- g_value_set_uint(value, priv->width);
- break;
- }
- case PROP_SENSOR_HEIGHT:
- {
- g_value_set_uint(value, priv->height);
- break;
- }
- case PROP_SENSOR_PIXEL_WIDTH:
- {
- g_value_set_double(value, PIXEL_SIZE);
- break;
- }
- case PROP_SENSOR_PIXEL_HEIGHT:
- {
- g_value_set_double(value, PIXEL_SIZE);
- break;
- }
- case PROP_ROI_X:
- {
- g_value_set_uint(value, priv->roi_x);
- break;
- }
- case PROP_ROI_Y:
- {
- g_value_set_uint(value, priv->roi_y);
- break;
- }
- case PROP_ROI_WIDTH:
- {
- g_value_set_uint(value, priv->roi_width);
- break;
- }
- case PROP_ROI_HEIGHT:
- {
- g_value_set_uint(value, priv->roi_height);
- break;
- }
- case PROP_SENSOR_HORIZONTAL_BINNING:
- {
- g_value_set_uint(value, dexela_get_binning_mode_horizontal());
- break;
- }
- case PROP_SENSOR_HORIZONTAL_BINNINGS:
- {
- g_value_set_boxed(value, priv->binnings);
- break;
- }
- case PROP_SENSOR_VERTICAL_BINNING:
- {
- g_value_set_uint(value, dexela_get_binning_mode_vertical());
- break;
- }
- case PROP_SENSOR_VERTICAL_BINNINGS:
- {
- g_value_set_boxed(value, priv->binnings);
- break;
- }
- case PROP_GAIN_MODE:
- {
- g_value_set_uint(value, dexela_get_gain());
- break;
- }
- case PROP_TEST_MODE:
- {
- g_value_set_boolean(value, dexela_get_control_register() & 1);
- break;
- }
- case PROP_TRIGGER_SOURCE:
- {
- map_dexela_trigger_mode_to_uca_source(priv, value, dexela_get_trigger_mode());
- break;
- }
- case PROP_TRIGGER_TYPE:
- {
- map_dexela_trigger_mode_to_uca_type(priv, value, dexela_get_trigger_mode());
- break;
- }
- default:
- {
- G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
- break;
- }
- }
-}
-
-static void uca_dexela_camera_set_property(GObject *object, guint property_id, const GValue *value, GParamSpec *pspec)
-{
- g_return_if_fail (UCA_IS_DEXELA_CAMERA (object));
- UcaDexelaCameraPrivate *priv = UCA_DEXELA_CAMERA_GET_PRIVATE (object);
-
- if (uca_camera_is_recording (UCA_CAMERA (object)) && !uca_camera_is_writable_during_acquisition (UCA_CAMERA (object), pspec->name)) {
- g_warning ("Property '%s' cant be changed during acquisition", pspec->name);
- return;
- }
-
- switch (property_id) {
- case PROP_EXPOSURE_TIME:
- {
- const gdouble exposureTimeInSeconds = fmax(MINIMUM_EXPOSURE_TIME_IN_SECONDS, g_value_get_double(value));
- dexela_set_exposure_time_micros((gint) (exposureTimeInSeconds * MICROS_TO_SECONDS_FACTOR));
- break;
- }
- case PROP_ROI_X:
- {
- guint maxRoiX = real_width(priv) - 1;
- guint requestedRoiX = g_value_get_uint(value);
- priv->roi_x = min(maxRoiX, requestedRoiX);
- adjust_roi_width(priv, priv->roi_width);
- break;
- }
- case PROP_ROI_Y:
- {
- guint maxRoiY = real_height(priv) -1;
- guint requestedRoiY = g_value_get_uint(value);
- priv->roi_y = min(maxRoiY, requestedRoiY);
- adjust_roi_height(priv, priv->roi_height);
- break;
- }
- case PROP_ROI_WIDTH:
- {
- adjust_roi_width(priv, g_value_get_uint(value));
- break;
- }
- case PROP_ROI_HEIGHT:
- {
- adjust_roi_height(priv, g_value_get_uint(value));
- break;
- }
- case PROP_SENSOR_HORIZONTAL_BINNING:
- {
- const guint horizontalBinning = g_value_get_uint(value);
- if (!is_binning_allowed(priv, horizontalBinning)) {
- g_warning("Tried to set illegal horizontal binning: %d", horizontalBinning);
- return;
- }
- dexela_set_binning_mode(horizontalBinning, horizontalBinning);
- adjust_roi_width(priv, priv->roi_width);
- break;
- }
- case PROP_SENSOR_VERTICAL_BINNING:
- {
- const guint verticalBinning = g_value_get_uint(value);
- if (!is_binning_allowed(priv, verticalBinning)) {
- g_warning("Tried to set illegal vertical binning: %d", verticalBinning);
- return;
- }
- dexela_set_binning_mode(verticalBinning, verticalBinning);
- adjust_roi_height(priv, priv->roi_height);
- break;
- }
- case PROP_GAIN_MODE:
- {
- const guint gain = g_value_get_uint(value);
- if (gain == 0) {
- dexela_set_gain(LOW);
- return;
- }
- if (gain == 1) {
- dexela_set_gain(HIGH);
- return;
- }
- g_warning("Illegal attempt to set gain: %d", gain);
- break;
- }
- case PROP_TEST_MODE:
- {
- if (g_value_get_boolean(value)) {
- dexela_set_control_register(dexela_get_control_register() | 1);
- return;
- }
- dexela_set_control_register(dexela_get_control_register() & 0xFFFE);
- break;
- }
- case PROP_TRIGGER_SOURCE:
- {
- set_triggering(priv, g_value_get_enum(value), priv->uca_trigger_type);
- break;
- }
- case PROP_TRIGGER_TYPE:
- {
- set_triggering(priv, priv->uca_trigger_source, g_value_get_enum(value));
- break;
- }
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
- return;
- }
-}
-
-static void uca_dexela_camera_start_recording(UcaCamera *camera, GError **error)
-{
- g_debug("start recording called");
- dexela_start_acquisition();
-}
-
-static void uca_dexela_camera_stop_recording(UcaCamera *camera, GError **error)
-{
- g_debug("stop recording called");
- dexela_stop_acquisition();
-}
-
-static gboolean uca_dexela_camera_grab(UcaCamera *camera, gpointer data, GError **error)
-{
- g_debug("grab called");
- g_return_val_if_fail(UCA_IS_DEXELA_CAMERA(camera), FALSE);
- UcaDexelaCameraPrivate *priv = UCA_DEXELA_CAMERA_GET_PRIVATE(camera);
-
- if (priv->uca_trigger_source == UCA_CAMERA_TRIGGER_SOURCE_SOFTWARE) {
- // TODO: wait for a signal from uca_camera_trigger()
- }
- guchar* fullFrame = dexela_grab();
- apply_software_roi(fullFrame, real_width(priv), priv->num_bytes, data, priv->roi_x, priv->roi_y, priv->roi_width, priv->roi_height);
- return TRUE;
-}
-
-static void uca_dexela_camera_finalize(GObject *object)
-{
- UcaDexelaCameraPrivate *priv = UCA_DEXELA_CAMERA_GET_PRIVATE(object);
- g_value_array_free(priv->binnings);
-
- G_OBJECT_CLASS(uca_dexela_camera_parent_class)->finalize(object);
-}
-
-static gboolean uca_dexela_camera_initable_init(GInitable *initable, GCancellable *cancellable, GError **error)
-{
- g_return_val_if_fail (UCA_IS_DEXELA_CAMERA (initable), FALSE);
- UcaDexelaCameraPrivate *priv = UCA_DEXELA_CAMERA_GET_PRIVATE(initable);
-
- if (cancellable != NULL) {
- g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
- "Cancellable initialization not supported");
- return FALSE;
- }
- if (priv->init_error != NULL) {
- if (error) {
- *error = g_error_copy (priv->init_error);
- }
- return FALSE;
- }
- return TRUE;
-}
-
-static void uca_dexela_camera_initable_iface_init(GInitableIface *iface)
-{
- iface->init = uca_dexela_camera_initable_init;
-}
-
-static void uca_dexela_camera_class_init(UcaDexelaCameraClass *klass)
-{
- GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
- gobject_class->set_property = uca_dexela_camera_set_property;
- gobject_class->get_property = uca_dexela_camera_get_property;
- gobject_class->finalize = uca_dexela_camera_finalize;
-
- UcaCameraClass *camera_class = UCA_CAMERA_CLASS(klass);
- camera_class->start_recording = uca_dexela_camera_start_recording;
- camera_class->stop_recording = uca_dexela_camera_stop_recording;
- camera_class->grab = uca_dexela_camera_grab;
-
- 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]]);
- }
- dexela_properties[PROP_GAIN_MODE] =
- g_param_spec_uint("gain-mode",
- "High or Low Full Well",
- "High (1) or Low (0) Full Well",
- 0, 1, 0, G_PARAM_READWRITE);
- dexela_properties[PROP_TEST_MODE] =
- g_param_spec_boolean("test-mode",
- "Enable or disable test mode",
- "Enable (true) or disable (false) test mode",
- FALSE, G_PARAM_READWRITE);
- for (guint id = N_BASE_PROPERTIES; id < N_PROPERTIES; id++) {
- g_object_class_install_property(gobject_class, id, dexela_properties[id]);
- }
- g_type_class_add_private(klass, sizeof(UcaDexelaCameraPrivate));
-}
-
-static gboolean setup_dexela(UcaDexelaCameraPrivate *priv)
-{
- if (!dexela_open_detector(DEFAULT_FMT_FILE_PATH)) {
- g_set_error_literal(&priv->init_error, G_IO_ERROR, G_IO_ERROR_FAILED, "Failed to open dexela detector. Check cable, driver and permissions.");
- return FALSE;
- }
- // TODO implement more error checking
- dexela_init_serial_connection();
- priv->bits = dexela_get_bit_depth();
- priv->width = dexela_get_width();
- priv->height = dexela_get_height();
- priv->roi_x = 0;
- priv->roi_y = 0;
- priv->roi_width = real_width(priv);
- priv->roi_height = real_height(priv);
- priv->num_bytes = 2;
- return TRUE;
-}
-
-static void uca_dexela_camera_init(UcaDexelaCamera *self)
-{
- UcaDexelaCameraPrivate *priv = UCA_DEXELA_CAMERA_GET_PRIVATE(self);
- self->priv = priv;
- fill_binnings(priv);
- priv->uca_trigger_source = UCA_CAMERA_TRIGGER_SOURCE_AUTO;
- priv->uca_trigger_type = UCA_CAMERA_TRIGGER_TYPE_EDGE;
- setup_dexela(priv);
-}
-
-G_MODULE_EXPORT GType
-uca_camera_get_type (void)
-{
- return UCA_TYPE_DEXELA_CAMERA;
-}
-
-G_MODULE_EXPORT UcaCamera *
-uca_camera_impl_new (GError **error)
-{
- return UCA_CAMERA(uca_dexela_camera_new(error));
-}