From 99b737ae9f3f1d35a4696594821fa3bc39e8aa87 Mon Sep 17 00:00:00 2001 From: Matthias Vogelgesang Date: Fri, 28 Sep 2012 18:16:56 +0200 Subject: Fix #146: Make a new top-level directory for cams ... and build a package for each camera. Moreover, for some reason we can live without the CMake generated spec file for RPM generation. AFAICS, the RPMs are prefixed correctly. --- plugins/CMakeLists.txt | 5 + plugins/mock/CMakeLists.txt | 18 + plugins/mock/uca-mock-camera.c | 409 +++++++++++ plugins/mock/uca-mock-camera.h | 65 ++ plugins/package-plugin.sh.in | 1 + plugins/pco/CMakeLists.txt | 30 + plugins/pco/uca-pco-camera.c | 1398 ++++++++++++++++++++++++++++++++++++++ plugins/pco/uca-pco-camera.h | 91 +++ plugins/pf/CMakeLists.txt | 30 + plugins/pf/uca-pf-camera.c | 351 ++++++++++ plugins/pf/uca-pf-camera.h | 74 ++ plugins/pylon/CMakeLists.txt | 24 + plugins/pylon/uca-pylon-camera.c | 391 +++++++++++ plugins/pylon/uca-pylon-camera.h | 74 ++ plugins/ufo/CMakeLists.txt | 24 + plugins/ufo/uca-ufo-camera.c | 497 ++++++++++++++ plugins/ufo/uca-ufo-camera.h | 76 +++ 17 files changed, 3558 insertions(+) create mode 100644 plugins/CMakeLists.txt create mode 100644 plugins/mock/CMakeLists.txt create mode 100644 plugins/mock/uca-mock-camera.c create mode 100644 plugins/mock/uca-mock-camera.h create mode 100644 plugins/package-plugin.sh.in create mode 100644 plugins/pco/CMakeLists.txt create mode 100644 plugins/pco/uca-pco-camera.c create mode 100644 plugins/pco/uca-pco-camera.h create mode 100644 plugins/pf/CMakeLists.txt create mode 100644 plugins/pf/uca-pf-camera.c create mode 100644 plugins/pf/uca-pf-camera.h create mode 100644 plugins/pylon/CMakeLists.txt create mode 100644 plugins/pylon/uca-pylon-camera.c create mode 100644 plugins/pylon/uca-pylon-camera.h create mode 100644 plugins/ufo/CMakeLists.txt create mode 100644 plugins/ufo/uca-ufo-camera.c create mode 100644 plugins/ufo/uca-ufo-camera.h (limited to 'plugins') diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt new file mode 100644 index 0000000..5131280 --- /dev/null +++ b/plugins/CMakeLists.txt @@ -0,0 +1,5 @@ +add_subdirectory(mock) +add_subdirectory(pf) +add_subdirectory(pco) +add_subdirectory(pylon) +add_subdirectory(ufo) diff --git a/plugins/mock/CMakeLists.txt b/plugins/mock/CMakeLists.txt new file mode 100644 index 0000000..75d8635 --- /dev/null +++ b/plugins/mock/CMakeLists.txt @@ -0,0 +1,18 @@ +cmake_minimum_required(VERSION 2.8) +project(ucamock) + +set(UCA_CAMERA_NAME "mock") + +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/../package-plugin.sh.in + ${CMAKE_CURRENT_BINARY_DIR}/../../package-plugin-${UCA_CAMERA_NAME}.sh) + +add_library(ucamock SHARED + uca-mock-camera.c) + +target_link_libraries(ucamock + uca + ${UCA_DEPS}) + +install(TARGETS ucamock + LIBRARY DESTINATION ${LIB_INSTALL_DIR}/uca + COMPONENT ${UCA_CAMERA_NAME}) diff --git a/plugins/mock/uca-mock-camera.c b/plugins/mock/uca-mock-camera.c new file mode 100644 index 0000000..7cd4689 --- /dev/null +++ b/plugins/mock/uca-mock-camera.c @@ -0,0 +1,409 @@ +/* Copyright (C) 2011, 2012 Matthias Vogelgesang + (Karlsruhe Institute of Technology) + + 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 +#include +#include "uca-mock-camera.h" + +#define UCA_MOCK_CAMERA_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), UCA_TYPE_MOCK_CAMERA, UcaMockCameraPrivate)) + +G_DEFINE_TYPE(UcaMockCamera, uca_mock_camera, UCA_TYPE_CAMERA) + +enum { + PROP_FRAMERATE = N_BASE_PROPERTIES, + N_PROPERTIES +}; + +static const gint mock_overrideables[] = { + PROP_NAME, + PROP_SENSOR_WIDTH, + PROP_SENSOR_HEIGHT, + PROP_SENSOR_BITDEPTH, + PROP_SENSOR_HORIZONTAL_BINNING, + PROP_SENSOR_HORIZONTAL_BINNINGS, + PROP_SENSOR_VERTICAL_BINNING, + PROP_SENSOR_VERTICAL_BINNINGS, + PROP_TRIGGER_MODE, + PROP_EXPOSURE_TIME, + PROP_ROI_X, + PROP_ROI_Y, + PROP_ROI_WIDTH, + PROP_ROI_HEIGHT, + PROP_ROI_HEIGHT_MULTIPLIER, + PROP_ROI_WIDTH_MULTIPLIER, + PROP_SENSOR_MAX_FRAME_RATE, + PROP_HAS_STREAMING, + PROP_HAS_CAMRAM_RECORDING, + 0, +}; + +static GParamSpec *mock_properties[N_PROPERTIES] = { NULL, }; + +struct _UcaMockCameraPrivate { + guint width; + guint height; + guint roi_x, roi_y, roi_width, roi_height; + gfloat frame_rate; + gfloat max_frame_rate; + gdouble exposure_time; + guint8 *dummy_data; + guint current_frame; + + gboolean thread_running; + + GThread *grab_thread; + GValueArray *binnings; +}; + +static const char g_digits[10][20] = { + /* 0 */ + { 0x00, 0xff, 0xff, 0x00, + 0xff, 0x00, 0x00, 0xff, + 0xff, 0x00, 0x00, 0xff, + 0xff, 0x00, 0x00, 0xff, + 0x00, 0xff, 0xff, 0x00 }, + /* 1 */ + { 0x00, 0x00, 0xff, 0x00, + 0x00, 0xff, 0xff, 0x00, + 0x00, 0x00, 0xff, 0x00, + 0x00, 0x00, 0xff, 0x00, + 0x00, 0x00, 0xff, 0x00 }, + /* 2 */ + { 0x00, 0xff, 0xff, 0x00, + 0xff, 0x00, 0x00, 0xff, + 0x00, 0x00, 0xff, 0x00, + 0x00, 0xff, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff }, + /* 3 */ + { 0x00, 0xff, 0xff, 0x00, + 0xff, 0x00, 0x00, 0xff, + 0x00, 0x00, 0xff, 0x00, + 0xff, 0x00, 0x00, 0xff, + 0x00, 0xff, 0xff, 0x00 }, + /* 4 */ + { 0xff, 0x00, 0x00, 0x00, + 0xff, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff }, + /* 5 */ + { 0xff, 0xff, 0xff, 0xff, + 0xff, 0x00, 0x00, 0x00, + 0x00, 0xff, 0xff, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0x00 }, + /* 6 */ + { 0x00, 0xff, 0xff, 0xff, + 0xff, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0x00, + 0xff, 0x00, 0x00, 0xff, + 0x00, 0xff, 0xff, 0x00 }, + /* 7 */ + { 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0xff, 0x00, + 0x00, 0xff, 0x00, 0x00, + 0xff, 0x00, 0x00, 0x00 }, + /* 8 */ + { 0x00, 0xff, 0xff, 0x00, + 0xff, 0x00, 0x00, 0xff, + 0x00, 0xff, 0xff, 0x00, + 0xff, 0x00, 0x00, 0xff, + 0x00, 0xff, 0xff, 0x00 }, + /* 9 */ + { 0x00, 0xff, 0xff, 0x00, + 0xff, 0x00, 0x00, 0xff, + 0x00, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0x00 } +}; + +static const guint DIGIT_WIDTH = 4; +static const guint DIGIT_HEIGHT = 5; + +static void print_number(gchar *buffer, guint number, guint x, guint y, guint width) +{ + for (int i = 0; i < DIGIT_WIDTH; i++) { + for (int j = 0; j < DIGIT_HEIGHT; j++) { + buffer[(y+j)*width + (x+i)] = g_digits[number][j*DIGIT_WIDTH+i]; + } + } +} + +static void print_current_frame(UcaMockCameraPrivate *priv, gchar *buffer) +{ + guint number = priv->current_frame; + guint divisor = 100000000; + int x = 10; + while (divisor > 1) { + print_number(buffer, number / divisor, x, 10, priv->width); + number = number % divisor; + divisor = divisor / 10; + x += DIGIT_WIDTH + 1; + } +} + +static gpointer mock_grab_func(gpointer data) +{ + UcaMockCamera *mock_camera = UCA_MOCK_CAMERA(data); + g_return_val_if_fail(UCA_IS_MOCK_CAMERA(mock_camera), NULL); + + UcaMockCameraPrivate *priv = UCA_MOCK_CAMERA_GET_PRIVATE(mock_camera); + UcaCamera *camera = UCA_CAMERA(mock_camera); + const gulong sleep_time = (gulong) G_USEC_PER_SEC / priv->frame_rate; + + while (priv->thread_running) { + camera->grab_func(priv->dummy_data, camera->user_data); + g_usleep(sleep_time); + } + + return NULL; +} + +static void uca_mock_camera_start_recording(UcaCamera *camera, GError **error) +{ + gboolean transfer_async = FALSE; + UcaMockCameraPrivate *priv; + g_return_if_fail(UCA_IS_MOCK_CAMERA(camera)); + + priv = UCA_MOCK_CAMERA_GET_PRIVATE(camera); + /* TODO: check that roi_x + roi_width < priv->width */ + priv->dummy_data = (guint8 *) g_malloc0(priv->roi_width * priv->roi_height); + + g_object_get(G_OBJECT(camera), + "transfer-asynchronously", &transfer_async, + NULL); + + /* + * In case asynchronous transfer is requested, we start a new thread that + * invokes the grab callback, otherwise nothing will be done here. + */ + if (transfer_async) { + GError *tmp_error = NULL; + priv->thread_running = TRUE; + priv->grab_thread = g_thread_create(mock_grab_func, camera, TRUE, &tmp_error); + + if (tmp_error != NULL) { + priv->thread_running = FALSE; + g_propagate_error(error, tmp_error); + } + } +} + +static void uca_mock_camera_stop_recording(UcaCamera *camera, GError **error) +{ + gboolean transfer_async = FALSE; + UcaMockCameraPrivate *priv; + g_return_if_fail(UCA_IS_MOCK_CAMERA(camera)); + + priv = UCA_MOCK_CAMERA_GET_PRIVATE(camera); + g_free(priv->dummy_data); + priv->dummy_data = NULL; + + g_object_get(G_OBJECT(camera), + "transfer-asynchronously", &transfer_async, + NULL); + + if (transfer_async) { + priv->thread_running = FALSE; + g_thread_join(priv->grab_thread); + } +} + +static void uca_mock_camera_grab(UcaCamera *camera, gpointer *data, GError **error) +{ + g_return_if_fail(UCA_IS_MOCK_CAMERA(camera)); + g_return_if_fail(data != NULL); + + UcaMockCameraPrivate *priv = UCA_MOCK_CAMERA_GET_PRIVATE(camera); + + if (*data == NULL) + *data = g_malloc0(priv->width * priv->height); + + g_memmove(*data, priv->dummy_data, priv->width * priv->height); + print_current_frame(priv, *data); + priv->current_frame++; +} + +static void uca_mock_camera_set_property(GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) +{ + g_return_if_fail(UCA_IS_MOCK_CAMERA(object)); + UcaMockCameraPrivate *priv = UCA_MOCK_CAMERA_GET_PRIVATE(object); + + switch (property_id) { + case PROP_EXPOSURE_TIME: + priv->exposure_time = g_value_get_double(value); + break; + case PROP_FRAMERATE: + priv->frame_rate = g_value_get_float(value); + break; + case PROP_ROI_X: + priv->roi_x = g_value_get_uint(value); + break; + case PROP_ROI_Y: + priv->roi_y = g_value_get_uint(value); + break; + case PROP_ROI_WIDTH: + priv->roi_width = g_value_get_uint(value); + break; + case PROP_ROI_HEIGHT: + priv->roi_height = g_value_get_uint(value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); + return; + } +} + +static void uca_mock_camera_get_property(GObject *object, guint property_id, GValue *value, GParamSpec *pspec) +{ + UcaMockCameraPrivate *priv = UCA_MOCK_CAMERA_GET_PRIVATE(object); + + switch (property_id) { + case PROP_NAME: + g_value_set_string(value, "mock camera"); + 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_BITDEPTH: + g_value_set_uint(value, 8); + break; + case PROP_SENSOR_HORIZONTAL_BINNING: + g_value_set_uint(value, 1); + break; + case PROP_SENSOR_HORIZONTAL_BINNINGS: + g_value_set_boxed(value, priv->binnings); + break; + case PROP_SENSOR_VERTICAL_BINNING: + g_value_set_uint(value, 1); + break; + case PROP_SENSOR_VERTICAL_BINNINGS: + g_value_set_boxed(value, priv->binnings); + break; + case PROP_EXPOSURE_TIME: + g_value_set_double(value, priv->exposure_time); + break; + case PROP_TRIGGER_MODE: + g_value_set_enum(value, UCA_CAMERA_TRIGGER_AUTO); + 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_ROI_WIDTH_MULTIPLIER: + g_value_set_uint(value, 1); + break; + case PROP_ROI_HEIGHT_MULTIPLIER: + g_value_set_uint(value, 1); + break; + case PROP_SENSOR_MAX_FRAME_RATE: + g_value_set_float(value, priv->max_frame_rate); + break; + case PROP_HAS_STREAMING: + g_value_set_boolean(value, TRUE); + break; + case PROP_HAS_CAMRAM_RECORDING: + g_value_set_boolean(value, FALSE); + break; + case PROP_FRAMERATE: + g_value_set_float(value, priv->frame_rate); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); + break; + } +} + +static void uca_mock_camera_finalize(GObject *object) +{ + UcaMockCameraPrivate *priv = UCA_MOCK_CAMERA_GET_PRIVATE(object); + + if (priv->thread_running) { + priv->thread_running = FALSE; + g_thread_join(priv->grab_thread); + } + + g_free(priv->dummy_data); + g_value_array_free(priv->binnings); + + G_OBJECT_CLASS(uca_mock_camera_parent_class)->finalize(object); +} + +static void uca_mock_camera_class_init(UcaMockCameraClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS(klass); + gobject_class->set_property = uca_mock_camera_set_property; + gobject_class->get_property = uca_mock_camera_get_property; + gobject_class->finalize = uca_mock_camera_finalize; + + UcaCameraClass *camera_class = UCA_CAMERA_CLASS(klass); + camera_class->start_recording = uca_mock_camera_start_recording; + camera_class->stop_recording = uca_mock_camera_stop_recording; + camera_class->grab = uca_mock_camera_grab; + + for (guint i = 0; mock_overrideables[i] != 0; i++) + g_object_class_override_property(gobject_class, mock_overrideables[i], uca_camera_props[mock_overrideables[i]]); + + mock_properties[PROP_FRAMERATE] = + g_param_spec_float("frame-rate", + "Frame rate", + "Number of frames per second that are taken", + 1.0f, 100.0f, 100.0f, + G_PARAM_READWRITE); + + for (guint id = N_BASE_PROPERTIES; id < N_PROPERTIES; id++) + g_object_class_install_property(gobject_class, id, mock_properties[id]); + + g_type_class_add_private(klass, sizeof(UcaMockCameraPrivate)); +} + +static void uca_mock_camera_init(UcaMockCamera *self) +{ + self->priv = UCA_MOCK_CAMERA_GET_PRIVATE(self); + self->priv->roi_x = 0; + self->priv->roi_y = 0; + self->priv->width = self->priv->roi_width = 640; + self->priv->height = self->priv->roi_height = 480; + self->priv->frame_rate = self->priv->max_frame_rate = 100000.0f; + self->priv->grab_thread = NULL; + self->priv->current_frame = 0; + + self->priv->binnings = g_value_array_new(1); + GValue val = {0}; + g_value_init(&val, G_TYPE_UINT); + g_value_set_uint(&val, 1); + g_value_array_append(self->priv->binnings, &val); +} + +G_MODULE_EXPORT UcaCamera * +uca_camera_impl_new (GError **error) +{ + UcaCamera *camera = UCA_CAMERA (g_object_new (UCA_TYPE_MOCK_CAMERA, NULL)); + return camera; +} diff --git a/plugins/mock/uca-mock-camera.h b/plugins/mock/uca-mock-camera.h new file mode 100644 index 0000000..9ee9190 --- /dev/null +++ b/plugins/mock/uca-mock-camera.h @@ -0,0 +1,65 @@ +/* Copyright (C) 2011, 2012 Matthias Vogelgesang + (Karlsruhe Institute of Technology) + + 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 */ + +#ifndef __UCA_MOCK_CAMERA_H +#define __UCA_MOCK_CAMERA_H + +#include +#include "uca-camera.h" + +G_BEGIN_DECLS + +#define UCA_TYPE_MOCK_CAMERA (uca_mock_camera_get_type()) +#define UCA_MOCK_CAMERA(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), UCA_TYPE_MOCK_CAMERA, UcaMockCamera)) +#define UCA_IS_MOCK_CAMERA(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), UCA_TYPE_MOCK_CAMERA)) +#define UCA_MOCK_CAMERA_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), UFO_TYPE_MOCK_CAMERA, UfoMockCameraClass)) +#define UCA_IS_MOCK_CAMERA_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), UCA_TYPE_MOCK_CAMERA)) +#define UCA_MOCK_CAMERA_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), UCA_TYPE_MOCK_CAMERA, UcaMockCameraClass)) + +typedef struct _UcaMockCamera UcaMockCamera; +typedef struct _UcaMockCameraClass UcaMockCameraClass; +typedef struct _UcaMockCameraPrivate UcaMockCameraPrivate; + +/** + * UcaMockCamera: + * + * Creates #UcaMockCamera instances by loading corresponding shared objects. The + * contents of the #UcaMockCamera structure are private and should only be + * accessed via the provided API. + */ +struct _UcaMockCamera { + /*< private >*/ + UcaCamera parent; + + UcaMockCameraPrivate *priv; +}; + +/** + * UcaMockCameraClass: + * + * #UcaMockCamera class + */ +struct _UcaMockCameraClass { + /*< private >*/ + UcaCameraClass parent; +}; + +GType uca_mock_camera_get_type(void); + +G_END_DECLS + +#endif diff --git a/plugins/package-plugin.sh.in b/plugins/package-plugin.sh.in new file mode 100644 index 0000000..c624d52 --- /dev/null +++ b/plugins/package-plugin.sh.in @@ -0,0 +1 @@ +cpack -D CPACK_INSTALL_CMAKE_PROJECTS="${CMAKE_CURRENT_BINARY_DIR}/;Project;${UCA_CAMERA_NAME};/" -D CPACK_PACKAGE_FILE_NAME="uca-plugin-${UCA_CAMERA_NAME}-${UCA_VERSION_MAJOR}.${UCA_VERSION_MINOR}.${UCA_VERSION_PATCH}" diff --git a/plugins/pco/CMakeLists.txt b/plugins/pco/CMakeLists.txt new file mode 100644 index 0000000..7c016b9 --- /dev/null +++ b/plugins/pco/CMakeLists.txt @@ -0,0 +1,30 @@ +cmake_minimum_required(VERSION 2.8) +project(ucapco) + +find_package(PCO) +find_package(FgLib5) +find_package(ClSerMe4) + +if (PCO_FOUND AND CLSERME4_FOUND AND FGLIB5_FOUND) + set(UCA_CAMERA_NAME "pco") + + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/../package-plugin.sh.in + ${CMAKE_CURRENT_BINARY_DIR}/../../package-plugin-${UCA_CAMERA_NAME}.sh) + + include_directories(${PCO_INCLUDE_DIRS} + ${CLSERME4_INCLUDE_DIR} + ${FGLIB5_INCLUDE_DIR}) + + add_library(ucapco SHARED + uca-pco-camera.c) + + target_link_libraries(ucapco + ${UCA_DEPS} + ${PCO_LIBRARIES} + ${CLSERME4_LIBRARY} + ${FGLIB5_LIBRARY}) + + install(TARGETS ucapco + LIBRARY DESTINATION ${LIB_INSTALL_DIR}/uca + COMPONENT ${UCA_CAMERA_NAME}) +endif() diff --git a/plugins/pco/uca-pco-camera.c b/plugins/pco/uca-pco-camera.c new file mode 100644 index 0000000..8bf2936 --- /dev/null +++ b/plugins/pco/uca-pco-camera.c @@ -0,0 +1,1398 @@ +/* Copyright (C) 2011, 2012 Matthias Vogelgesang + (Karlsruhe Institute of Technology) + + 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 +#include +#include +#include +#include +#include +#include +#include "uca-camera.h" +#include "uca-pco-camera.h" +#include "uca-enums.h" + +#define FG_TRY_PARAM(fg, camobj, param, val_addr, port) \ + { int r = Fg_setParameter(fg, param, val_addr, port); \ + if (r != FG_OK) { \ + g_set_error(error, UCA_PCO_CAMERA_ERROR, \ + UCA_PCO_CAMERA_ERROR_FG_GENERAL, \ + "%s", Fg_getLastErrorDescription(fg)); \ + g_object_unref(camobj); \ + return NULL; \ + } } + +#define FG_SET_ERROR(err, fg, err_type) \ + if (err != FG_OK) { \ + g_set_error(error, UCA_PCO_CAMERA_ERROR, \ + err_type, \ + "%s", Fg_getLastErrorDescription(fg)); \ + return; \ + } + +#define HANDLE_PCO_ERROR(err) \ + if ((err) != PCO_NOERROR) { \ + g_set_error(error, UCA_PCO_CAMERA_ERROR, \ + UCA_PCO_CAMERA_ERROR_LIBPCO_GENERAL,\ + "libpco error %x", err); \ + return; \ + } + +#define UCA_PCO_CAMERA_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), UCA_TYPE_PCO_CAMERA, UcaPcoCameraPrivate)) + +G_DEFINE_TYPE(UcaPcoCamera, uca_pco_camera, UCA_TYPE_CAMERA) + +#define TIMEBASE_INVALID 0xDEAD + +/** + * UcaPcoCameraRecordMode: + * @UCA_PCO_CAMERA_RECORD_MODE_SEQUENCE: Store all frames and stop if necessary + * @UCA_PCO_CAMERA_RECORD_MODE_RING_BUFFER: Store frames in ring-buffer fashion + * and overwrite if necessary + */ + +/** + * UcaPcoCameraAcquireMode: + * @UCA_PCO_CAMERA_ACQUIRE_MODE_AUTO: Take all images + * @UCA_PCO_CAMERA_ACQUIRE_MODE_EXTERNAL: Use signal + */ + +/** + * UcaPcoCameraTimestamp: + * @UCA_PCO_CAMERA_TIMESTAMP_NONE: Don't embed any timestamp + * @UCA_PCO_CAMERA_TIMESTAMP_BINARY: Embed a BCD-coded timestamp in the first + * bytes + * @UCA_PCO_CAMERA_TIMESTAMP_ASCII: Embed a visible ASCII timestamp in the image + */ + +/** + * UcaPcoCameraError: + * @UCA_PCO_CAMERA_ERROR_LIBPCO_INIT: Initializing libpco failed + * @UCA_PCO_CAMERA_ERROR_LIBPCO_GENERAL: General libpco error + * @UCA_PCO_CAMERA_ERROR_UNSUPPORTED: Camera type is not supported + * @UCA_PCO_CAMERA_ERROR_FG_INIT: Framegrabber initialization failed + * @UCA_PCO_CAMERA_ERROR_FG_GENERAL: General framegrabber error + * @UCA_PCO_CAMERA_ERROR_FG_ACQUISITION: Framegrabber acquisition error + */ +GQuark uca_pco_camera_error_quark() +{ + return g_quark_from_static_string("uca-pco-camera-error-quark"); +} + +enum { + PROP_SENSOR_EXTENDED = N_BASE_PROPERTIES, + PROP_SENSOR_WIDTH_EXTENDED, + PROP_SENSOR_HEIGHT_EXTENDED, + PROP_SENSOR_TEMPERATURE, + PROP_SENSOR_PIXELRATES, + PROP_SENSOR_PIXELRATE, + PROP_SENSOR_ADCS, + PROP_SENSOR_MAX_ADCS, + PROP_DELAY_TIME, + PROP_HAS_DOUBLE_IMAGE_MODE, + PROP_DOUBLE_IMAGE_MODE, + PROP_OFFSET_MODE, + PROP_RECORD_MODE, + PROP_ACQUIRE_MODE, + PROP_COOLING_POINT, + PROP_COOLING_POINT_MIN, + PROP_COOLING_POINT_MAX, + PROP_COOLING_POINT_DEFAULT, + PROP_NOISE_FILTER, + PROP_TIMESTAMP_MODE, + N_PROPERTIES +}; + +static gint base_overrideables[] = { + PROP_NAME, + PROP_SENSOR_WIDTH, + PROP_SENSOR_HEIGHT, + PROP_SENSOR_BITDEPTH, + PROP_SENSOR_HORIZONTAL_BINNING, + PROP_SENSOR_HORIZONTAL_BINNINGS, + PROP_SENSOR_VERTICAL_BINNING, + PROP_SENSOR_VERTICAL_BINNINGS, + PROP_SENSOR_MAX_FRAME_RATE, + PROP_EXPOSURE_TIME, + PROP_TRIGGER_MODE, + 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 *pco_properties[N_PROPERTIES] = { NULL, }; + +/* + * This structure defines type-specific properties of PCO cameras. + */ +typedef struct { + int camera_type; + const char *so_file; + int cl_type; + int cl_format; + gfloat max_frame_rate; + gboolean has_camram; +} pco_cl_map_entry; + +struct _UcaPcoCameraPrivate { + pco_handle pco; + pco_cl_map_entry *camera_description; + + Fg_Struct *fg; + guint fg_port; + dma_mem *fg_mem; + + guint frame_width; + guint frame_height; + gsize num_bytes; + guint16 *grab_buffer; + + guint16 width, height; + guint16 width_ex, height_ex; + guint16 binning_h, binning_v; + guint16 roi_x, roi_y; + guint16 roi_width, roi_height; + guint16 roi_horizontal_steps, roi_vertical_steps; + GValueArray *horizontal_binnings; + GValueArray *vertical_binnings; + GValueArray *pixelrates; + + /* The time bases are given as pco time bases (TIMEBASE_NS and so on) */ + guint16 delay_timebase; + guint16 exposure_timebase; + + frameindex_t last_frame; + guint16 active_segment; + guint num_recorded_images; + guint current_image; +}; + +static pco_cl_map_entry pco_cl_map[] = { + { CAMERATYPE_PCO_EDGE, "libFullAreaGray8.so", FG_CL_8BIT_FULL_10, FG_GRAY, 30.0f, FALSE }, + { CAMERATYPE_PCO4000, "libDualAreaGray16.so", FG_CL_SINGLETAP_16_BIT, FG_GRAY16, 5.0f, TRUE }, + { CAMERATYPE_PCO_DIMAX_STD, "libFullAreaGray16.so", FG_CL_SINGLETAP_8_BIT, FG_GRAY16, 1279.0f, TRUE }, + { 0, NULL, 0, 0, 0.0f, FALSE } +}; + +static pco_cl_map_entry *get_pco_cl_map_entry(int camera_type) +{ + pco_cl_map_entry *entry = pco_cl_map; + + while (entry->camera_type != 0) { + if (entry->camera_type == camera_type) + return entry; + entry++; + } + + return NULL; +} + +static guint fill_binnings(UcaPcoCameraPrivate *priv) +{ + uint16_t *horizontal = NULL; + uint16_t *vertical = NULL; + guint num_horizontal, num_vertical; + + guint err = pco_get_possible_binnings(priv->pco, + &horizontal, &num_horizontal, + &vertical, &num_vertical); + + GValue val = {0}; + g_value_init(&val, G_TYPE_UINT); + + if (err == PCO_NOERROR) { + priv->horizontal_binnings = g_value_array_new(num_horizontal); + priv->vertical_binnings = g_value_array_new(num_vertical); + + for (guint i = 0; i < num_horizontal; i++) { + g_value_set_uint(&val, horizontal[i]); + g_value_array_append(priv->horizontal_binnings, &val); + } + + for (guint i = 0; i < num_vertical; i++) { + g_value_set_uint(&val, vertical[i]); + g_value_array_append(priv->vertical_binnings, &val); + } + } + + free(horizontal); + free(vertical); + return err; +} + +static void fill_pixelrates(UcaPcoCameraPrivate *priv, guint32 rates[4], gint num_rates) +{ + GValue val = {0}; + g_value_init(&val, G_TYPE_UINT); + priv->pixelrates = g_value_array_new(num_rates); + + for (gint i = 0; i < num_rates; i++) { + g_value_set_uint(&val, (guint) rates[i]); + g_value_array_append(priv->pixelrates, &val); + } +} + +static guint override_temperature_range(UcaPcoCameraPrivate *priv) +{ + int16_t default_temp, min_temp, max_temp; + guint err = pco_get_cooling_range(priv->pco, &default_temp, &min_temp, &max_temp); + + if (err == PCO_NOERROR) { + GParamSpecInt *spec = (GParamSpecInt *) pco_properties[PROP_COOLING_POINT]; + spec->minimum = min_temp; + spec->maximum = max_temp; + spec->default_value = default_temp; + } + else + g_warning("Unable to retrieve cooling range"); + + return err; +} + +static void property_override_default_guint_value (GObjectClass *oclass, const gchar *property_name, guint new_default) +{ + GParamSpecUInt *pspec = G_PARAM_SPEC_UINT (g_object_class_find_property (oclass, property_name)); + + if (pspec != NULL) + pspec->default_value = new_default; + else + g_warning ("pspec for %s not found\n", property_name); +} + +static void override_maximum_adcs(UcaPcoCameraPrivate *priv) +{ + GParamSpecInt *spec = (GParamSpecInt *) pco_properties[PROP_SENSOR_ADCS]; + spec->maximum = pco_get_maximum_number_of_adcs(priv->pco); +} + +static gdouble convert_timebase(guint16 timebase) +{ + switch (timebase) { + case TIMEBASE_NS: + return 1e-9; + case TIMEBASE_US: + return 1e-6; + case TIMEBASE_MS: + return 1e-3; + default: + g_warning("Unknown timebase"); + } + return 1e-3; +} + +static void read_timebase(UcaPcoCameraPrivate *priv) +{ + pco_get_timebase(priv->pco, &priv->delay_timebase, &priv->exposure_timebase); +} + +static gdouble get_suitable_timebase(gdouble time) +{ + if (time * 1e3 >= 1.0) + return TIMEBASE_MS; + if (time * 1e6 >= 1.0) + return TIMEBASE_US; + if (time * 1e9 >= 1.0) + return TIMEBASE_NS; + return TIMEBASE_INVALID; +} + +static int fg_callback(frameindex_t frame, struct fg_apc_data *apc) +{ + UcaCamera *camera = UCA_CAMERA(apc); + UcaPcoCameraPrivate *priv = UCA_PCO_CAMERA_GET_PRIVATE(camera); + gpointer data = Fg_getImagePtrEx(priv->fg, frame, priv->fg_port, priv->fg_mem); + + if (priv->camera_description->camera_type != CAMERATYPE_PCO_EDGE) + camera->grab_func(data, camera->user_data); + else { + pco_get_reorder_func(priv->pco)(priv->grab_buffer, data, priv->frame_width, priv->frame_height); + camera->grab_func(priv->grab_buffer, camera->user_data); + } + + return 0; +} + +static gboolean setup_fg_callback(UcaCamera *camera) +{ + UcaPcoCameraPrivate *priv = UCA_PCO_CAMERA_GET_PRIVATE(camera); + struct FgApcControl ctrl; + + /* Jeez, as if a NULL pointer would not be good enough. */ + ctrl.data = (struct fg_apc_data *) camera; + ctrl.version = 0; + ctrl.func = &fg_callback; + ctrl.flags = FG_APC_DEFAULTS; + ctrl.timeout = 1; + + if (priv->grab_buffer) + g_free(priv->grab_buffer); + + priv->grab_buffer = g_malloc0(priv->frame_width * priv->frame_height * sizeof(guint16)); + + return Fg_registerApcHandler(priv->fg, priv->fg_port, &ctrl, FG_APC_CONTROL_BASIC) == FG_OK; +} + +static void uca_pco_camera_start_recording(UcaCamera *camera, GError **error) +{ + g_return_if_fail(UCA_IS_PCO_CAMERA(camera)); + guint err = PCO_NOERROR; + + UcaPcoCameraPrivate *priv = UCA_PCO_CAMERA_GET_PRIVATE(camera); + guint16 binned_width, binned_height; + gboolean use_extended = FALSE; + gboolean transfer_async = FALSE; + + g_object_get (camera, "sensor-extended", &use_extended, NULL); + + if (use_extended) { + binned_width = priv->width_ex; + binned_height = priv->height_ex; + } + else { + binned_width = priv->width; + binned_height = priv->height; + } + + binned_width /= priv->binning_h; + binned_height /= priv->binning_v; + + if ((priv->roi_x + priv->roi_width > binned_width) || (priv->roi_y + priv->roi_height > binned_height)) { + g_set_error(error, UCA_PCO_CAMERA_ERROR, UCA_PCO_CAMERA_ERROR_UNSUPPORTED, + "ROI of size %ix%i @ (%i, %i) is outside of (binned) sensor size %ix%i\n", + priv->roi_width, priv->roi_height, priv->roi_x, priv->roi_y, binned_width, binned_height); + return; + } + + /* + * All parameters are valid. Now, set them on the camera. + */ + guint16 roi[4] = { priv->roi_x + 1, priv->roi_y + 1, priv->roi_x + priv->roi_width, priv->roi_y + priv->roi_height }; + + if (pco_set_roi(priv->pco, roi) != PCO_NOERROR) { + g_set_error(error, UCA_PCO_CAMERA_ERROR, UCA_PCO_CAMERA_ERROR_LIBPCO_GENERAL, + "Could not set ROI via pco_set_roi()"); + return; + } + + g_object_get(G_OBJECT(camera), "transfer-asynchronously", &transfer_async, NULL); + + /* + * FIXME: We cannot set the binning here as this breaks communication with + * the camera. Setting the binning works _before_ initializing the frame + * grabber though. However, it is rather inconvenient to initialize and + * de-initialize the frame grabber for each recording sequence. + */ + + /* if (pco_set_binning(priv->pco, priv->binning_h, priv->binning_v) != PCO_NOERROR) */ + /* g_warning("Cannot set binning\n"); */ + + if (priv->frame_width != priv->roi_width || priv->frame_height != priv->roi_height || priv->fg_mem == NULL) { + guint fg_width = priv->camera_description->camera_type == CAMERATYPE_PCO_EDGE ? 2 * priv->roi_width : priv->roi_width; + + priv->frame_width = priv->roi_width; + priv->frame_height = priv->roi_height; + priv->num_bytes = 2; + + Fg_setParameter(priv->fg, FG_WIDTH, &fg_width, priv->fg_port); + Fg_setParameter(priv->fg, FG_HEIGHT, &priv->frame_height, priv->fg_port); + + if (priv->fg_mem) + Fg_FreeMemEx(priv->fg, priv->fg_mem); + + const guint num_buffers = 2; + priv->fg_mem = Fg_AllocMemEx(priv->fg, + num_buffers * priv->frame_width * priv->frame_height * sizeof(uint16_t), num_buffers); + + if (priv->fg_mem == NULL) { + g_set_error(error, UCA_PCO_CAMERA_ERROR, UCA_PCO_CAMERA_ERROR_FG_INIT, + "%s", Fg_getLastErrorDescription(priv->fg)); + g_object_unref(camera); + return; + } + } + + if (transfer_async) + setup_fg_callback(camera); + + if ((priv->camera_description->camera_type == CAMERATYPE_PCO_DIMAX_STD) || + (priv->camera_description->camera_type == CAMERATYPE_PCO4000)) + pco_clear_active_segment(priv->pco); + + priv->last_frame = 0; + + err = pco_arm_camera(priv->pco); + HANDLE_PCO_ERROR(err); + + err = pco_start_recording(priv->pco); + HANDLE_PCO_ERROR(err); + + err = Fg_AcquireEx(priv->fg, priv->fg_port, GRAB_INFINITE, ACQ_STANDARD, priv->fg_mem); + FG_SET_ERROR(err, priv->fg, UCA_PCO_CAMERA_ERROR_FG_ACQUISITION); +} + +static void uca_pco_camera_stop_recording(UcaCamera *camera, GError **error) +{ + g_return_if_fail(UCA_IS_PCO_CAMERA(camera)); + UcaPcoCameraPrivate *priv = UCA_PCO_CAMERA_GET_PRIVATE(camera); + + guint err = pco_stop_recording(priv->pco); + HANDLE_PCO_ERROR(err); + + err = Fg_stopAcquireEx(priv->fg, priv->fg_port, priv->fg_mem, STOP_SYNC); + FG_SET_ERROR(err, priv->fg, UCA_PCO_CAMERA_ERROR_FG_ACQUISITION); + + err = Fg_setStatusEx(priv->fg, FG_UNBLOCK_ALL, 0, priv->fg_port, priv->fg_mem); + if (err == FG_INVALID_PARAMETER) + g_warning(" Unable to unblock all\n"); +} + +static void uca_pco_camera_start_readout(UcaCamera *camera, GError **error) +{ + g_return_if_fail(UCA_IS_PCO_CAMERA(camera)); + UcaPcoCameraPrivate *priv = UCA_PCO_CAMERA_GET_PRIVATE(camera); + + /* + * TODO: Check if readout mode is possible. This is not the case for the + * edge. + */ + + guint err = pco_get_active_segment(priv->pco, &priv->active_segment); + HANDLE_PCO_ERROR(err); + + err = pco_get_num_images(priv->pco, priv->active_segment, &priv->num_recorded_images); + HANDLE_PCO_ERROR(err); + + priv->current_image = 1; +} + +static void uca_pco_camera_trigger(UcaCamera *camera, GError **error) +{ + g_return_if_fail(UCA_IS_PCO_CAMERA(camera)); + UcaPcoCameraPrivate *priv = UCA_PCO_CAMERA_GET_PRIVATE(camera); + + /* TODO: Check if we can trigger */ + guint32 success = 0; + pco_force_trigger(priv->pco, &success); + + if (!success) + g_set_error(error, UCA_PCO_CAMERA_ERROR, UCA_PCO_CAMERA_ERROR_LIBPCO_GENERAL, + "Could not trigger frame acquisition"); +} + +static void uca_pco_camera_grab(UcaCamera *camera, gpointer *data, GError **error) +{ + static const gint MAX_TIMEOUT = G_MAXINT; + + g_return_if_fail(UCA_IS_PCO_CAMERA(camera)); + UcaPcoCameraPrivate *priv = UCA_PCO_CAMERA_GET_PRIVATE(camera); + + gboolean is_readout = FALSE; + g_object_get(G_OBJECT(camera), "is-readout", &is_readout, NULL); + + if (is_readout) { + if (priv->current_image == priv->num_recorded_images) { + *data = NULL; + return; + } + + /* + * No joke, the pco firmware allows to read a range of images but + * implements only reading single images ... + */ + pco_read_images(priv->pco, priv->active_segment, priv->current_image, priv->current_image); + priv->current_image++; + } + + pco_request_image(priv->pco); + priv->last_frame = Fg_getLastPicNumberBlockingEx(priv->fg, priv->last_frame+1, priv->fg_port, MAX_TIMEOUT, priv->fg_mem); + + if (priv->last_frame <= 0) { + guint err = FG_OK + 1; + FG_SET_ERROR(err, priv->fg, UCA_PCO_CAMERA_ERROR_FG_GENERAL); + } + + guint16 *frame = Fg_getImagePtrEx(priv->fg, priv->last_frame, priv->fg_port, priv->fg_mem); + + if (*data == NULL) + *data = g_malloc0(priv->frame_width * priv->frame_height * priv->num_bytes); + + if (priv->camera_description->camera_type == CAMERATYPE_PCO_EDGE) + pco_get_reorder_func(priv->pco)((guint16 *) *data, frame, priv->frame_width, priv->frame_height); + else + memcpy((gchar *) *data, (gchar *) frame, priv->frame_width * priv->frame_height * priv->num_bytes); +} + +static void uca_pco_camera_set_property(GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) +{ + UcaPcoCameraPrivate *priv = UCA_PCO_CAMERA_GET_PRIVATE(object); + + switch (property_id) { + case PROP_SENSOR_EXTENDED: + { + guint16 format = g_value_get_boolean (value) ? SENSORFORMAT_EXTENDED : SENSORFORMAT_STANDARD; + pco_set_sensor_format(priv->pco, format); + } + break; + + case PROP_ROI_X: + priv->roi_x = g_value_get_uint(value); + break; + + case PROP_ROI_Y: + priv->roi_y = g_value_get_uint(value); + break; + + case PROP_ROI_WIDTH: + { + guint width = g_value_get_uint(value); + + if (width % priv->roi_horizontal_steps) + g_warning("ROI width %i is not a multiple of %i", width, priv->roi_horizontal_steps); + else + priv->roi_width = width; + } + break; + + case PROP_ROI_HEIGHT: + { + guint height = g_value_get_uint(value); + + if (height % priv->roi_vertical_steps) + g_warning("ROI height %i is not a multiple of %i", height, priv->roi_vertical_steps); + else + priv->roi_height = height; + } + break; + + case PROP_SENSOR_HORIZONTAL_BINNING: + priv->binning_h = g_value_get_uint(value); + break; + + case PROP_SENSOR_VERTICAL_BINNING: + priv->binning_v = g_value_get_uint(value); + break; + + case PROP_EXPOSURE_TIME: + { + const gdouble time = g_value_get_double(value); + + if (priv->exposure_timebase == TIMEBASE_INVALID) + read_timebase(priv); + + /* + * Lets check if we can express the time in the current time + * base. If not, we need to adjust that. + */ + guint16 suitable_timebase = get_suitable_timebase(time); + + if (suitable_timebase == TIMEBASE_INVALID) { + g_warning("Cannot set such a small exposure time"); + } + else { + if (suitable_timebase != priv->exposure_timebase) { + priv->exposure_timebase = suitable_timebase; + if (pco_set_timebase(priv->pco, priv->delay_timebase, suitable_timebase) != PCO_NOERROR) + g_warning("Cannot set exposure time base"); + } + + gdouble timebase = convert_timebase(suitable_timebase); + guint32 timesteps = time / timebase; + if (pco_set_exposure_time(priv->pco, timesteps) != PCO_NOERROR) + g_warning("Cannot set exposure time"); + } + } + break; + + case PROP_DELAY_TIME: + { + const gdouble time = g_value_get_double(value); + + if (priv->delay_timebase == TIMEBASE_INVALID) + read_timebase(priv); + + /* + * Lets check if we can express the time in the current time + * base. If not, we need to adjust that. + */ + guint16 suitable_timebase = get_suitable_timebase(time); + + if (suitable_timebase == TIMEBASE_INVALID) { + if (time == 0.0) { + /* + * If we want to suppress any pre-exposure delays, we + * can set the 0 seconds in whatever time base that is + * currently active. + */ + if (pco_set_delay_time(priv->pco, 0) != PCO_NOERROR) + g_warning("Cannot set zero delay time"); + } + else + g_warning("Cannot set such a small exposure time"); + } + else { + if (suitable_timebase != priv->delay_timebase) { + priv->delay_timebase = suitable_timebase; + if (pco_set_timebase(priv->pco, suitable_timebase, priv->exposure_timebase) != PCO_NOERROR) + g_warning("Cannot set delay time base"); + } + + gdouble timebase = convert_timebase(suitable_timebase); + guint32 timesteps = time / timebase; + if (pco_set_delay_time(priv->pco, timesteps) != PCO_NOERROR) + g_warning("Cannot set delay time"); + } + } + break; + + case PROP_SENSOR_ADCS: + { + const guint num_adcs = g_value_get_uint(value); + if (pco_set_adc_mode(priv->pco, num_adcs) != PCO_NOERROR) + g_warning("Cannot set the number of ADCs per pixel\n"); + } + break; + + case PROP_SENSOR_PIXELRATE: + { + guint desired_pixel_rate = g_value_get_uint(value); + guint32 pixel_rate = 0; + + for (guint i = 0; i < priv->pixelrates->n_values; i++) { + if (g_value_get_uint(g_value_array_get_nth(priv->pixelrates, i)) == desired_pixel_rate) { + pixel_rate = desired_pixel_rate; + break; + } + } + + if (pixel_rate != 0) { + if (pco_set_pixelrate(priv->pco, pixel_rate) != PCO_NOERROR) + g_warning("Cannot set pixel rate"); + } + else + g_warning("%i Hz is not possible. Please check the \"sensor-pixelrates\" property", desired_pixel_rate); + } + break; + + case PROP_DOUBLE_IMAGE_MODE: + if (!pco_is_double_image_mode_available(priv->pco)) + g_warning("Double image mode is not available on this pco model"); + else + pco_set_double_image_mode(priv->pco, g_value_get_boolean(value)); + break; + + case PROP_OFFSET_MODE: + pco_set_offset_mode(priv->pco, g_value_get_boolean(value)); + break; + + case PROP_COOLING_POINT: + { + int16_t temperature = (int16_t) g_value_get_int(value); + pco_set_cooling_temperature(priv->pco, temperature); + } + break; + + case PROP_RECORD_MODE: + { + /* TODO: setting this is not possible for the edge */ + UcaPcoCameraRecordMode mode = (UcaPcoCameraRecordMode) g_value_get_enum(value); + + if (mode == UCA_PCO_CAMERA_RECORD_MODE_SEQUENCE) + pco_set_record_mode(priv->pco, RECORDER_SUBMODE_SEQUENCE); + else if (mode == UCA_PCO_CAMERA_RECORD_MODE_RING_BUFFER) + pco_set_record_mode(priv->pco, RECORDER_SUBMODE_RINGBUFFER); + else + g_warning("Unknown record mode"); + } + break; + + case PROP_ACQUIRE_MODE: + { + UcaPcoCameraAcquireMode mode = (UcaPcoCameraAcquireMode) g_value_get_enum(value); + unsigned int err = PCO_NOERROR; + + if (mode == UCA_PCO_CAMERA_ACQUIRE_MODE_AUTO) + err = pco_set_acquire_mode(priv->pco, ACQUIRE_MODE_AUTO); + else if (mode == UCA_PCO_CAMERA_ACQUIRE_MODE_EXTERNAL) + err = pco_set_acquire_mode(priv->pco, ACQUIRE_MODE_EXTERNAL); + else + g_warning("Unknown acquire mode"); + + if (err != PCO_NOERROR) + g_warning("Cannot set acquire mode"); + } + break; + + case PROP_TRIGGER_MODE: + { + UcaCameraTrigger trigger_mode = (UcaCameraTrigger) g_value_get_enum(value); + + switch (trigger_mode) { + case UCA_CAMERA_TRIGGER_AUTO: + pco_set_trigger_mode(priv->pco, TRIGGER_MODE_AUTOTRIGGER); + break; + case UCA_CAMERA_TRIGGER_INTERNAL: + pco_set_trigger_mode(priv->pco, TRIGGER_MODE_SOFTWARETRIGGER); + break; + case UCA_CAMERA_TRIGGER_EXTERNAL: + pco_set_trigger_mode(priv->pco, TRIGGER_MODE_EXTERNALTRIGGER); + break; + } + } + break; + + case PROP_NOISE_FILTER: + { + guint16 filter_mode = g_value_get_boolean(value) ? NOISE_FILTER_MODE_ON : NOISE_FILTER_MODE_OFF; + pco_set_noise_filter_mode(priv->pco, filter_mode); + } + break; + + case PROP_TIMESTAMP_MODE: + { + guint16 modes[] = { + TIMESTAMP_MODE_OFF, /* 0 */ + TIMESTAMP_MODE_BINARY, /* 1 = 1 << 0 */ + TIMESTAMP_MODE_ASCII, /* 2 = 1 << 1 */ + TIMESTAMP_MODE_BINARYANDASCII, /* 3 = 1 << 0 | 1 << 1 */ + }; + pco_set_timestamp_mode(priv->pco, modes[g_value_get_flags(value)]); + } + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); + return; + } +} + +static void uca_pco_camera_get_property(GObject *object, guint property_id, GValue *value, GParamSpec *pspec) +{ + UcaPcoCameraPrivate *priv = UCA_PCO_CAMERA_GET_PRIVATE(object); + + switch (property_id) { + case PROP_SENSOR_EXTENDED: + { + guint16 format; + pco_get_sensor_format(priv->pco, &format); + g_value_set_boolean(value, format == SENSORFORMAT_EXTENDED); + } + 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_WIDTH_EXTENDED: + g_value_set_uint(value, priv->width_ex < priv->width ? priv->width : priv->width_ex); + break; + + case PROP_SENSOR_HEIGHT_EXTENDED: + g_value_set_uint(value, priv->height_ex < priv->height ? priv->height : priv->height_ex); + break; + + case PROP_SENSOR_HORIZONTAL_BINNING: + g_value_set_uint(value, priv->binning_h); + break; + + case PROP_SENSOR_HORIZONTAL_BINNINGS: + g_value_set_boxed(value, priv->horizontal_binnings); + break; + + case PROP_SENSOR_VERTICAL_BINNING: + g_value_set_uint(value, priv->binning_v); + break; + + case PROP_SENSOR_VERTICAL_BINNINGS: + g_value_set_boxed(value, priv->vertical_binnings); + break; + + case PROP_SENSOR_MAX_FRAME_RATE: + g_value_set_float(value, priv->camera_description->max_frame_rate); + break; + + case PROP_SENSOR_BITDEPTH: + g_value_set_uint(value, 16); + break; + + case PROP_SENSOR_TEMPERATURE: + { + gint32 ccd, camera, power; + pco_get_temperature(priv->pco, &ccd, &camera, &power); + g_value_set_double(value, ccd / 10.0); + } + break; + + case PROP_SENSOR_ADCS: + { + /* + * Up to now, the ADC mode corresponds directly to the number of + * ADCs in use. + */ + pco_adc_mode mode; + if (pco_get_adc_mode(priv->pco, &mode) != PCO_NOERROR) + g_warning("Cannot read number of ADCs per pixel"); + g_value_set_uint(value, mode); + } + break; + + case PROP_SENSOR_MAX_ADCS: + { + GParamSpecUInt *spec = (GParamSpecUInt *) pco_properties[PROP_SENSOR_ADCS]; + g_value_set_uint(value, spec->maximum); + } + break; + + case PROP_SENSOR_PIXELRATES: + g_value_set_boxed(value, priv->pixelrates); + break; + + case PROP_SENSOR_PIXELRATE: + { + guint32 pixelrate; + pco_get_pixelrate(priv->pco, &pixelrate); + g_value_set_uint(value, pixelrate); + } + break; + + case PROP_EXPOSURE_TIME: + { + uint32_t exposure_time; + pco_get_exposure_time(priv->pco, &exposure_time); + + if (priv->exposure_timebase == TIMEBASE_INVALID) + read_timebase(priv); + + g_value_set_double(value, convert_timebase(priv->exposure_timebase) * exposure_time); + } + break; + + case PROP_DELAY_TIME: + { + uint32_t delay_time; + pco_get_delay_time(priv->pco, &delay_time); + + if (priv->delay_timebase == TIMEBASE_INVALID) + read_timebase(priv); + + g_value_set_double(value, convert_timebase(priv->delay_timebase) * delay_time); + } + break; + + case PROP_HAS_DOUBLE_IMAGE_MODE: + g_value_set_boolean(value, pco_is_double_image_mode_available(priv->pco)); + break; + + case PROP_DOUBLE_IMAGE_MODE: + if (!pco_is_double_image_mode_available(priv->pco)) + g_warning("Double image mode is not available on this pco model"); + else { + bool on; + pco_get_double_image_mode(priv->pco, &on); + g_value_set_boolean(value, on); + } + break; + + case PROP_OFFSET_MODE: + { + bool on; + pco_get_offset_mode(priv->pco, &on); + g_value_set_boolean(value, on); + } + break; + + case PROP_HAS_STREAMING: + g_value_set_boolean(value, TRUE); + break; + + case PROP_HAS_CAMRAM_RECORDING: + g_value_set_boolean(value, priv->camera_description->has_camram); + break; + + case PROP_RECORD_MODE: + { + guint16 mode; + pco_get_record_mode(priv->pco, &mode); + + if (mode == RECORDER_SUBMODE_SEQUENCE) + g_value_set_enum(value, UCA_PCO_CAMERA_RECORD_MODE_SEQUENCE); + else if (mode == RECORDER_SUBMODE_RINGBUFFER) + g_value_set_enum(value, UCA_PCO_CAMERA_RECORD_MODE_RING_BUFFER); + else + g_warning("pco record mode not handled"); + } + break; + + case PROP_ACQUIRE_MODE: + { + guint16 mode; + pco_get_acquire_mode(priv->pco, &mode); + + if (mode == ACQUIRE_MODE_AUTO) + g_value_set_enum(value, UCA_PCO_CAMERA_ACQUIRE_MODE_AUTO); + else if (mode == ACQUIRE_MODE_EXTERNAL) + g_value_set_enum(value, UCA_PCO_CAMERA_ACQUIRE_MODE_EXTERNAL); + else + g_warning("pco acquire mode not handled"); + } + break; + + case PROP_TRIGGER_MODE: + { + guint16 mode; + pco_get_trigger_mode(priv->pco, &mode); + + switch (mode) { + case TRIGGER_MODE_AUTOTRIGGER: + g_value_set_enum(value, UCA_CAMERA_TRIGGER_AUTO); + break; + case TRIGGER_MODE_SOFTWARETRIGGER: + g_value_set_enum(value, UCA_CAMERA_TRIGGER_INTERNAL); + break; + case TRIGGER_MODE_EXTERNALTRIGGER: + g_value_set_enum(value, UCA_CAMERA_TRIGGER_EXTERNAL); + break; + default: + g_warning("pco trigger mode not handled"); + } + } + 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_ROI_WIDTH_MULTIPLIER: + g_value_set_uint(value, priv->roi_horizontal_steps); + break; + + case PROP_ROI_HEIGHT_MULTIPLIER: + g_value_set_uint(value, priv->roi_vertical_steps); + break; + + case PROP_NAME: + { + gchar *name = NULL; + pco_get_name(priv->pco, &name); + g_value_set_string(value, name); + g_free(name); + } + break; + + case PROP_COOLING_POINT: + { + int16_t temperature; + if (pco_get_cooling_temperature(priv->pco, &temperature) != PCO_NOERROR) + g_warning("Cannot read cooling temperature\n"); + g_value_set_int(value, temperature); + } + break; + + case PROP_COOLING_POINT_MIN: + { + GParamSpecInt *spec = (GParamSpecInt *) pco_properties[PROP_COOLING_POINT]; + g_value_set_int(value, spec->minimum); + } + break; + + case PROP_COOLING_POINT_MAX: + { + GParamSpecInt *spec = (GParamSpecInt *) pco_properties[PROP_COOLING_POINT]; + g_value_set_int(value, spec->maximum); + } + break; + + case PROP_COOLING_POINT_DEFAULT: + { + GParamSpecInt *spec = (GParamSpecInt *) pco_properties[PROP_COOLING_POINT]; + g_value_set_int(value, spec->default_value); + } + break; + + case PROP_NOISE_FILTER: + { + guint16 mode; + pco_get_noise_filter_mode(priv->pco, &mode); + g_value_set_boolean(value, mode != NOISE_FILTER_MODE_OFF); + } + break; + + case PROP_TIMESTAMP_MODE: + { + guint16 mode; + pco_get_timestamp_mode(priv->pco, &mode); + + switch (mode) { + case TIMESTAMP_MODE_OFF: + g_value_set_flags(value, UCA_PCO_CAMERA_TIMESTAMP_NONE); + break; + case TIMESTAMP_MODE_BINARY: + g_value_set_flags(value, UCA_PCO_CAMERA_TIMESTAMP_BINARY); + break; + case TIMESTAMP_MODE_BINARYANDASCII: + g_value_set_flags(value, + UCA_PCO_CAMERA_TIMESTAMP_BINARY | UCA_PCO_CAMERA_TIMESTAMP_ASCII); + break; + case TIMESTAMP_MODE_ASCII: + g_value_set_flags(value, UCA_PCO_CAMERA_TIMESTAMP_ASCII); + break; + } + } + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); + break; + } +} + +static void uca_pco_camera_finalize(GObject *object) +{ + UcaPcoCameraPrivate *priv = UCA_PCO_CAMERA_GET_PRIVATE(object); + + if (priv->horizontal_binnings) + g_value_array_free(priv->horizontal_binnings); + + if (priv->vertical_binnings) + g_value_array_free(priv->vertical_binnings); + + if (priv->pixelrates) + g_value_array_free(priv->pixelrates); + + if (priv->fg) { + if (priv->fg_mem) + Fg_FreeMemEx(priv->fg, priv->fg_mem); + + Fg_FreeGrabber(priv->fg); + } + + if (priv->pco) + pco_destroy(priv->pco); + + g_free(priv->grab_buffer); + + G_OBJECT_CLASS(uca_pco_camera_parent_class)->finalize(object); +} + +static void uca_pco_camera_class_init(UcaPcoCameraClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS(klass); + gobject_class->set_property = uca_pco_camera_set_property; + gobject_class->get_property = uca_pco_camera_get_property; + gobject_class->finalize = uca_pco_camera_finalize; + + UcaCameraClass *camera_class = UCA_CAMERA_CLASS(klass); + camera_class->start_recording = uca_pco_camera_start_recording; + camera_class->stop_recording = uca_pco_camera_stop_recording; + camera_class->start_readout = uca_pco_camera_start_readout; + camera_class->trigger = uca_pco_camera_trigger; + camera_class->grab = uca_pco_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]]); + + /** + * UcaPcoCamera:sensor-extended: + * + * Activate larger sensor area that contains surrounding pixels for dark + * references and dummies. Use #UcaPcoCamera:sensor-width-extended and + * #UcaPcoCamera:sensor-height-extended to query the resolution of the + * larger area. + */ + pco_properties[PROP_SENSOR_EXTENDED] = + g_param_spec_boolean("sensor-extended", + "Use extended sensor format", + "Use extended sensor format", + FALSE, G_PARAM_READWRITE); + + pco_properties[PROP_SENSOR_WIDTH_EXTENDED] = + g_param_spec_uint("sensor-width-extended", + "Width of extended sensor", + "Width of the extended sensor in pixels", + 1, G_MAXUINT, 1, + G_PARAM_READABLE); + + pco_properties[PROP_SENSOR_HEIGHT_EXTENDED] = + g_param_spec_uint("sensor-height-extended", + "Height of extended sensor", + "Height of the extended sensor in pixels", + 1, G_MAXUINT, 1, + G_PARAM_READABLE); + + /** + * UcaPcoCamera:sensor-pixelrate: + * + * Read and write the pixel rate or clock of the sensor in terms of Hertz. + * Make sure to query the possible pixel rates through the + * #UcaPcoCamera:sensor-pixelrates property. Any other value will be + * rejected by the camera. + */ + pco_properties[PROP_SENSOR_PIXELRATE] = + g_param_spec_uint("sensor-pixelrate", + "Pixel rate", + "Pixel rate", + 1, G_MAXUINT, 1, + G_PARAM_READWRITE); + + pco_properties[PROP_SENSOR_PIXELRATES] = + g_param_spec_value_array("sensor-pixelrates", + "Array of possible sensor pixel rates", + "Array of possible sensor pixel rates", + pco_properties[PROP_SENSOR_PIXELRATE], + G_PARAM_READABLE); + + pco_properties[PROP_NAME] = + g_param_spec_string("name", + "Name of the camera", + "Name of the camera", + "", G_PARAM_READABLE); + + pco_properties[PROP_SENSOR_TEMPERATURE] = + g_param_spec_double("sensor-temperature", + "Temperature of the sensor", + "Temperature of the sensor in degree Celsius", + -G_MAXDOUBLE, G_MAXDOUBLE, 0.0, + G_PARAM_READABLE); + + pco_properties[PROP_HAS_DOUBLE_IMAGE_MODE] = + g_param_spec_boolean("has-double-image-mode", + "Is double image mode supported by this model", + "Is double image mode supported by this model", + FALSE, G_PARAM_READABLE); + + pco_properties[PROP_DOUBLE_IMAGE_MODE] = + g_param_spec_boolean("double-image-mode", + "Use double image mode", + "Use double image mode", + FALSE, G_PARAM_READWRITE); + + pco_properties[PROP_OFFSET_MODE] = + g_param_spec_boolean("offset-mode", + "Use offset mode", + "Use offset mode", + FALSE, G_PARAM_READWRITE); + + pco_properties[PROP_RECORD_MODE] = + g_param_spec_enum("record-mode", + "Record mode", + "Record mode", + UCA_TYPE_PCO_CAMERA_RECORD_MODE, UCA_PCO_CAMERA_RECORD_MODE_SEQUENCE, + G_PARAM_READWRITE); + + pco_properties[PROP_ACQUIRE_MODE] = + g_param_spec_enum("acquire-mode", + "Acquire mode", + "Acquire mode", + UCA_TYPE_PCO_CAMERA_ACQUIRE_MODE, UCA_PCO_CAMERA_ACQUIRE_MODE_AUTO, + G_PARAM_READWRITE); + + pco_properties[PROP_DELAY_TIME] = + g_param_spec_double("delay-time", + "Delay time", + "Delay before starting actual exposure", + 0.0, G_MAXDOUBLE, 0.0, + G_PARAM_READWRITE); + + pco_properties[PROP_NOISE_FILTER] = + g_param_spec_boolean("noise-filter", + "Noise filter", + "Noise filter", + FALSE, G_PARAM_READWRITE); + + /** + * UcaPcoCamera:cooling-point: + * + * The value range is set arbitrarily, because we are not yet connected to + * the camera and just don't know the cooling range. We override these + * values in #uca_pco_camera_new(). + */ + pco_properties[PROP_COOLING_POINT] = + g_param_spec_int("cooling-point", + "Cooling point of the camera", + "Cooling point of the camera in degree celsius", + 0, 10, 5, G_PARAM_READWRITE); + + pco_properties[PROP_COOLING_POINT_MIN] = + g_param_spec_int("cooling-point-min", + "Minimum cooling point", + "Minimum cooling point in degree celsius", + G_MININT, G_MAXINT, 0, G_PARAM_READABLE); + + pco_properties[PROP_COOLING_POINT_MAX] = + g_param_spec_int("cooling-point-max", + "Maximum cooling point", + "Maximum cooling point in degree celsius", + G_MININT, G_MAXINT, 0, G_PARAM_READABLE); + + pco_properties[PROP_COOLING_POINT_DEFAULT] = + g_param_spec_int("cooling-point-default", + "Default cooling point", + "Default cooling point in degree celsius", + G_MININT, G_MAXINT, 0, G_PARAM_READABLE); + + pco_properties[PROP_SENSOR_ADCS] = + g_param_spec_uint("sensor-adcs", + "Number of ADCs to use", + "Number of ADCs to use", + 1, 2, 1, + G_PARAM_READWRITE); + + pco_properties[PROP_SENSOR_MAX_ADCS] = + g_param_spec_uint("sensor-max-adcs", + "Maximum number of ADCs", + "Maximum number of ADCs that can be set with \"sensor-adcs\"", + 1, G_MAXUINT, 1, + G_PARAM_READABLE); + + pco_properties[PROP_TIMESTAMP_MODE] = + g_param_spec_flags("timestamp-mode", + "Timestamp mode", + "Timestamp mode", + UCA_TYPE_PCO_CAMERA_TIMESTAMP, UCA_PCO_CAMERA_TIMESTAMP_NONE, + G_PARAM_READWRITE); + + for (guint id = N_BASE_PROPERTIES; id < N_PROPERTIES; id++) + g_object_class_install_property(gobject_class, id, pco_properties[id]); + + g_type_class_add_private(klass, sizeof(UcaPcoCameraPrivate)); +} + +static void uca_pco_camera_init(UcaPcoCamera *self) +{ + self->priv = UCA_PCO_CAMERA_GET_PRIVATE(self); + self->priv->fg = NULL; + self->priv->fg_mem = NULL; + self->priv->pco = NULL; + self->priv->horizontal_binnings = NULL; + self->priv->vertical_binnings = NULL; + self->priv->pixelrates = NULL; + self->priv->camera_description = NULL; + self->priv->last_frame = 0; + self->priv->grab_buffer = NULL; + + self->priv->delay_timebase = TIMEBASE_INVALID; + self->priv->exposure_timebase = TIMEBASE_INVALID; +} + +G_MODULE_EXPORT UcaCamera * +uca_camera_impl_new (GError **error) +{ + pco_handle pco = pco_init(); + + if (pco == NULL) { + g_set_error(error, UCA_PCO_CAMERA_ERROR, UCA_PCO_CAMERA_ERROR_LIBPCO_INIT, + "Initializing libpco failed"); + return NULL; + } + + UcaPcoCamera *camera = g_object_new(UCA_TYPE_PCO_CAMERA, NULL); + UcaPcoCameraPrivate *priv = UCA_PCO_CAMERA_GET_PRIVATE(camera); + priv->pco = pco; + + pco_get_resolution(priv->pco, &priv->width, &priv->height, &priv->width_ex, &priv->height_ex); + pco_get_binning(priv->pco, &priv->binning_h, &priv->binning_v); + pco_set_storage_mode(pco, STORAGE_MODE_RECORDER); + pco_set_auto_transfer(pco, 1); + + guint16 roi[4]; + pco_get_roi(priv->pco, roi); + pco_get_roi_steps(priv->pco, &priv->roi_horizontal_steps, &priv->roi_vertical_steps); + + priv->roi_x = roi[0] - 1; + priv->roi_y = roi[1] - 1; + priv->roi_width = roi[2] - roi[0] + 1; + priv->roi_height = roi[3] - roi[1] + 1; + + guint16 camera_type, camera_subtype; + pco_get_camera_type(priv->pco, &camera_type, &camera_subtype); + pco_cl_map_entry *map_entry = get_pco_cl_map_entry(camera_type); + priv->camera_description = map_entry; + + if (map_entry == NULL) { + g_set_error(error, UCA_PCO_CAMERA_ERROR, UCA_PCO_CAMERA_ERROR_UNSUPPORTED, + "Camera type is not supported"); + g_object_unref(camera); + return NULL; + } + + priv->fg_port = PORT_A; + priv->fg = Fg_Init(map_entry->so_file, priv->fg_port); + + if (priv->fg == NULL) { + g_set_error(error, UCA_PCO_CAMERA_ERROR, UCA_PCO_CAMERA_ERROR_FG_INIT, + "%s", Fg_getLastErrorDescription(priv->fg)); + g_object_unref(camera); + return NULL; + } + + const guint32 fg_height = priv->height; + const guint32 fg_width = camera_type == CAMERATYPE_PCO_EDGE ? priv->width * 2 : priv->width; + + FG_TRY_PARAM(priv->fg, camera, FG_CAMERA_LINK_CAMTYP, &map_entry->cl_type, priv->fg_port); + FG_TRY_PARAM(priv->fg, camera, FG_FORMAT, &map_entry->cl_format, priv->fg_port); + FG_TRY_PARAM(priv->fg, camera, FG_WIDTH, &fg_width, priv->fg_port); + FG_TRY_PARAM(priv->fg, camera, FG_HEIGHT, &fg_height, priv->fg_port); + + int val = FREE_RUN; + FG_TRY_PARAM(priv->fg, camera, FG_TRIGGERMODE, &val, priv->fg_port); + + fill_binnings(priv); + + /* + * Here we override property ranges because we didn't know them at property + * installation time. + */ + GObjectClass *camera_class = G_OBJECT_CLASS (UCA_CAMERA_GET_CLASS (camera)); + property_override_default_guint_value (camera_class, "roi-width", priv->width); + property_override_default_guint_value (camera_class, "roi-height", priv->height); + + guint32 rates[4] = {0}; + gint num_rates = 0; + + if (pco_get_available_pixelrates(priv->pco, rates, &num_rates) == PCO_NOERROR) { + GObjectClass *pco_camera_class = G_OBJECT_CLASS (UCA_PCO_CAMERA_GET_CLASS (camera)); + + fill_pixelrates(priv, rates, num_rates); + property_override_default_guint_value (pco_camera_class, "sensor-pixelrate", rates[0]); + } + + override_temperature_range (priv); + override_maximum_adcs (priv); + + return UCA_CAMERA (camera); +} diff --git a/plugins/pco/uca-pco-camera.h b/plugins/pco/uca-pco-camera.h new file mode 100644 index 0000000..73ae44e --- /dev/null +++ b/plugins/pco/uca-pco-camera.h @@ -0,0 +1,91 @@ +/* Copyright (C) 2011, 2012 Matthias Vogelgesang + (Karlsruhe Institute of Technology) + + 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 */ + +#ifndef __UCA_PCO_CAMERA_H +#define __UCA_PCO_CAMERA_H + +#include +#include "uca-camera.h" + +G_BEGIN_DECLS + +#define UCA_TYPE_PCO_CAMERA (uca_pco_camera_get_type()) +#define UCA_PCO_CAMERA(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), UCA_TYPE_PCO_CAMERA, UcaPcoCamera)) +#define UCA_IS_PCO_CAMERA(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), UCA_TYPE_PCO_CAMERA)) +#define UCA_PCO_CAMERA_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), UCA_TYPE_PCO_CAMERA, UcaPcoCameraClass)) +#define UCA_IS_PCO_CAMERA_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), UCA_TYPE_PCO_CAMERA)) +#define UCA_PCO_CAMERA_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), UCA_TYPE_PCO_CAMERA, UcaPcoCameraClass)) + +#define UCA_PCO_CAMERA_ERROR uca_pco_camera_error_quark() +typedef enum { + UCA_PCO_CAMERA_ERROR_LIBPCO_INIT, + UCA_PCO_CAMERA_ERROR_LIBPCO_GENERAL, + UCA_PCO_CAMERA_ERROR_UNSUPPORTED, + UCA_PCO_CAMERA_ERROR_FG_INIT, + UCA_PCO_CAMERA_ERROR_FG_GENERAL, + UCA_PCO_CAMERA_ERROR_FG_ACQUISITION +} UcaPcoCameraError; + +typedef struct _UcaPcoCamera UcaPcoCamera; +typedef struct _UcaPcoCameraClass UcaPcoCameraClass; +typedef struct _UcaPcoCameraPrivate UcaPcoCameraPrivate; + +typedef enum { + UCA_PCO_CAMERA_RECORD_MODE_SEQUENCE, + UCA_PCO_CAMERA_RECORD_MODE_RING_BUFFER, +} UcaPcoCameraRecordMode; + +typedef enum { + UCA_PCO_CAMERA_ACQUIRE_MODE_AUTO, + UCA_PCO_CAMERA_ACQUIRE_MODE_EXTERNAL +} UcaPcoCameraAcquireMode; + +typedef enum { + UCA_PCO_CAMERA_TIMESTAMP_NONE = 0, + UCA_PCO_CAMERA_TIMESTAMP_BINARY = 1 << 0, + UCA_PCO_CAMERA_TIMESTAMP_ASCII = 1 << 1 +} UcaPcoCameraTimestamp; + +/** + * UcaPcoCamera: + * + * Creates #UcaPcoCamera instances by loading corresponding shared objects. The + * contents of the #UcaPcoCamera structure are private and should only be + * accessed via the provided API. + */ +struct _UcaPcoCamera { + /*< private >*/ + UcaCamera parent; + + UcaPcoCameraPrivate *priv; +}; + +/** + * UcaPcoCameraClass: + * + * #UcaPcoCamera class + */ +struct _UcaPcoCameraClass { + /*< private >*/ + UcaCameraClass parent; +}; + +GType uca_pco_camera_get_type(void); + +G_END_DECLS + +#endif diff --git a/plugins/pf/CMakeLists.txt b/plugins/pf/CMakeLists.txt new file mode 100644 index 0000000..f392603 --- /dev/null +++ b/plugins/pf/CMakeLists.txt @@ -0,0 +1,30 @@ +cmake_minimum_required(VERSION 2.8) +project(ucapf) + +find_package(PF) +find_package(FgLib5) +find_package(ClSerMe4) + +if (PF_FOUND AND CLSERME4_FOUND AND FGLIB5_FOUND) + set(UCA_CAMERA_NAME "pco") + + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/../package-plugin.sh.in + ${CMAKE_CURRENT_BINARY_DIR}/../../package-plugin-${UCA_CAMERA_NAME}.sh) + + include_directories(${PF_INCLUDE_DIRS} + ${CLSERME4_INCLUDE_DIR} + ${FGLIB5_INCLUDE_DIR}) + + add_library(ucapf SHARED + uca-pf-camera.c) + + target_link_libraries(ucapf + ${UCA_DEPS} + ${PF_LIBRARIES} + ${CLSERME4_LIBRARY} + ${FGLIB5_LIBRARY}) + + install(TARGETS ucapf + LIBRARY DESTINATION ${LIB_INSTALL_DIR}/uca + COMPONENT ${UCA_CAMERA_NAME}) +endif() diff --git a/plugins/pf/uca-pf-camera.c b/plugins/pf/uca-pf-camera.c new file mode 100644 index 0000000..35b5edd --- /dev/null +++ b/plugins/pf/uca-pf-camera.c @@ -0,0 +1,351 @@ +/* Copyright (C) 2011, 2012 Matthias Vogelgesang + (Karlsruhe Institute of Technology) + + 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 +#include +#include +#include +#include +#include +#include +#include +#include "uca-camera.h" +#include "uca-pf-camera.h" + +#define FG_TRY_PARAM(fg, camobj, param, val_addr, port) \ + { int r = Fg_setParameter(fg, param, val_addr, port); \ + if (r != FG_OK) { \ + g_set_error(error, UCA_PF_CAMERA_ERROR, \ + UCA_PF_CAMERA_ERROR_FG_GENERAL, \ + "%s", Fg_getLastErrorDescription(fg)); \ + g_object_unref(camobj); \ + return NULL; \ + } } + +#define FG_SET_ERROR(err, fg, err_type) \ + if (err != FG_OK) { \ + g_set_error(error, UCA_PF_CAMERA_ERROR, \ + err_type, \ + "%s", Fg_getLastErrorDescription(fg)); \ + return; \ + } + +#define UCA_PF_CAMERA_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), UCA_TYPE_PF_CAMERA, UcaPfCameraPrivate)) + +G_DEFINE_TYPE(UcaPfCamera, uca_pf_camera, UCA_TYPE_CAMERA) + +/** + * UcaPfCameraError: + * @UCA_PF_CAMERA_ERROR_INIT: Initializing pcilib failed + * @UCA_PF_CAMERA_ERROR_FG_GENERAL: Frame grabber errors + * @UCA_PF_CAMERA_ERROR_FG_ACQUISITION: Acquisition errors related to the frame + * grabber + * @UCA_PF_CAMERA_ERROR_START_RECORDING: Starting failed + * @UCA_PF_CAMERA_ERROR_STOP_RECORDING: Stopping failed + */ +GQuark uca_pf_camera_error_quark() +{ + return g_quark_from_static_string("uca-pf-camera-error-quark"); +} + +static gint base_overrideables[] = { + PROP_NAME, + PROP_SENSOR_WIDTH, + PROP_SENSOR_HEIGHT, + PROP_SENSOR_BITDEPTH, + PROP_SENSOR_HORIZONTAL_BINNING, + PROP_SENSOR_HORIZONTAL_BINNINGS, + PROP_SENSOR_VERTICAL_BINNING, + PROP_SENSOR_VERTICAL_BINNINGS, + PROP_SENSOR_MAX_FRAME_RATE, + PROP_EXPOSURE_TIME, + 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 +}; + +enum { + PROP_FOO = N_BASE_PROPERTIES, + N_PROPERTIES +}; + + +struct _UcaPfCameraPrivate { + guint roi_width; + guint roi_height; + guint last_frame; + + Fg_Struct *fg; + guint fg_port; + dma_mem *fg_mem; +}; + +/* + * We just embed our private structure here. + */ +struct { + UcaCamera *camera; +} fg_apc_data; + +static int me4_callback(frameindex_t frame, struct fg_apc_data *apc) +{ + UcaCamera *camera = UCA_CAMERA(apc); + UcaPfCameraPrivate *priv = UCA_PF_CAMERA_GET_PRIVATE(camera); + camera->grab_func(Fg_getImagePtrEx(priv->fg, frame, priv->fg_port, priv->fg_mem), camera->user_data); + return 0; +} + +static void uca_pf_camera_start_recording(UcaCamera *camera, GError **error) +{ + g_return_if_fail(UCA_IS_PF_CAMERA(camera)); + UcaPfCameraPrivate *priv = UCA_PF_CAMERA_GET_PRIVATE(camera); + guint err = FG_OK; + + if (priv->fg_mem == NULL) { + const guint num_buffers = 2; + priv->fg_mem = Fg_AllocMemEx(priv->fg, num_buffers * priv->roi_width * priv->roi_height, num_buffers); + + if (priv->fg_mem == NULL) { + g_set_error(error, UCA_PF_CAMERA_ERROR, UCA_PF_CAMERA_ERROR_FG_ACQUISITION, + "%s", Fg_getLastErrorDescription(priv->fg)); + g_object_unref(camera); + return; + } + } + + gboolean transfer_async = FALSE; + g_object_get(G_OBJECT(camera), + "transfer-asynchronously", &transfer_async, + NULL); + + if (transfer_async) { + struct FgApcControl ctrl = { + .version = 0, + .data = (struct fg_apc_data *) camera, + .func = &me4_callback, + .flags = FG_APC_DEFAULTS, + .timeout = 1 + }; + + err = Fg_registerApcHandler(priv->fg, priv->fg_port, &ctrl, FG_APC_CONTROL_BASIC); + FG_SET_ERROR(err, priv->fg, UCA_PF_CAMERA_ERROR_FG_ACQUISITION); + } + + err = Fg_AcquireEx(priv->fg, priv->fg_port, GRAB_INFINITE, ACQ_STANDARD, priv->fg_mem); + FG_SET_ERROR(err, priv->fg, UCA_PF_CAMERA_ERROR_FG_ACQUISITION); +} + +static void uca_pf_camera_stop_recording(UcaCamera *camera, GError **error) +{ + g_return_if_fail(UCA_IS_PF_CAMERA(camera)); + UcaPfCameraPrivate *priv = UCA_PF_CAMERA_GET_PRIVATE(camera); + + guint err = Fg_stopAcquireEx(priv->fg, priv->fg_port, priv->fg_mem, STOP_SYNC); + FG_SET_ERROR(err, priv->fg, UCA_PF_CAMERA_ERROR_FG_ACQUISITION); + + err = Fg_setStatusEx(priv->fg, FG_UNBLOCK_ALL, 0, priv->fg_port, priv->fg_mem); + if (err == FG_INVALID_PARAMETER) + g_print(" Unable to unblock all\n"); +} + +static void uca_pf_camera_start_readout(UcaCamera *camera, GError **error) +{ + g_return_if_fail(UCA_IS_PF_CAMERA(camera)); + g_set_error(error, UCA_CAMERA_ERROR, UCA_CAMERA_ERROR_NOT_IMPLEMENTED, + "This photon focus camera does not support recording to internal memory"); +} + +static void uca_pf_camera_grab(UcaCamera *camera, gpointer *data, GError **error) +{ + g_return_if_fail(UCA_IS_PF_CAMERA(camera)); + UcaPfCameraPrivate *priv = UCA_PF_CAMERA_GET_PRIVATE(camera); + + priv->last_frame = Fg_getLastPicNumberBlockingEx(priv->fg, priv->last_frame+1, priv->fg_port, 5, priv->fg_mem); + + if (priv->last_frame <= 0) { + guint err = FG_OK + 1; + FG_SET_ERROR(err, priv->fg, UCA_PF_CAMERA_ERROR_FG_GENERAL); + } + + guint16 *frame = Fg_getImagePtrEx(priv->fg, priv->last_frame, priv->fg_port, priv->fg_mem); + + if (*data == NULL) + *data = g_malloc0(priv->roi_width * priv->roi_height); + + memcpy((gchar *) *data, (gchar *) frame, priv->roi_width * priv->roi_height); +} + +static void uca_pf_camera_set_property(GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) +{ + switch (property_id) { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); + return; + } +} + +static void uca_pf_camera_get_property(GObject *object, guint property_id, GValue *value, GParamSpec *pspec) +{ + switch (property_id) { + case PROP_SENSOR_WIDTH: + g_value_set_uint(value, 1280); + break; + case PROP_SENSOR_HEIGHT: + g_value_set_uint(value, 1024); + break; + case PROP_SENSOR_BITDEPTH: + g_value_set_uint(value, 8); + break; + case PROP_SENSOR_HORIZONTAL_BINNING: + break; + case PROP_SENSOR_HORIZONTAL_BINNINGS: + break; + case PROP_SENSOR_VERTICAL_BINNING: + break; + case PROP_SENSOR_VERTICAL_BINNINGS: + break; + case PROP_SENSOR_MAX_FRAME_RATE: + g_value_set_float(value, 488.0); + break; + case PROP_HAS_STREAMING: + g_value_set_boolean(value, TRUE); + break; + case PROP_HAS_CAMRAM_RECORDING: + g_value_set_boolean(value, FALSE); + break; + case PROP_EXPOSURE_TIME: + break; + case PROP_ROI_X: + g_value_set_uint(value, 0); + break; + case PROP_ROI_Y: + g_value_set_uint(value, 0); + break; + case PROP_ROI_WIDTH: + g_value_set_uint(value, 1280); + break; + case PROP_ROI_HEIGHT: + g_value_set_uint(value, 1024); + break; + case PROP_ROI_WIDTH_MULTIPLIER: + g_value_set_uint(value, 1); + break; + case PROP_ROI_HEIGHT_MULTIPLIER: + g_value_set_uint(value, 1); + break; + case PROP_NAME: + g_value_set_string(value, "Photon Focus MV2-D1280-640-CL"); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); + break; + } +} + +static void uca_pf_camera_finalize(GObject *object) +{ + UcaPfCameraPrivate *priv = UCA_PF_CAMERA_GET_PRIVATE(object); + + if (priv->fg) { + if (priv->fg_mem) + Fg_FreeMemEx(priv->fg, priv->fg_mem); + + Fg_FreeGrabber(priv->fg); + } + + G_OBJECT_CLASS(uca_pf_camera_parent_class)->finalize(object); +} + +static void uca_pf_camera_class_init(UcaPfCameraClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS(klass); + gobject_class->set_property = uca_pf_camera_set_property; + gobject_class->get_property = uca_pf_camera_get_property; + gobject_class->finalize = uca_pf_camera_finalize; + + UcaCameraClass *camera_class = UCA_CAMERA_CLASS(klass); + camera_class->start_recording = uca_pf_camera_start_recording; + camera_class->stop_recording = uca_pf_camera_stop_recording; + camera_class->start_readout = uca_pf_camera_start_readout; + camera_class->grab = uca_pf_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]]); + + g_type_class_add_private(klass, sizeof(UcaPfCameraPrivate)); +} + +static void uca_pf_camera_init(UcaPfCamera *self) +{ + self->priv = UCA_PF_CAMERA_GET_PRIVATE(self); + self->priv->fg = NULL; + self->priv->fg_mem = NULL; + self->priv->last_frame = 0; +} + +G_MODULE_EXPORT UcaCamera * +uca_camera_impl_new (GError **error) +{ + static const gchar *so_file = "libFullAreaGray8.so"; + static const int camera_link_type = FG_CL_8BIT_FULL_8; + static const int camera_format = FG_GRAY; + + /* + gint num_ports; + if (pfPortInit(&num_ports) < 0) { + g_set_error(error, UCA_PF_CAMERA_ERROR, UCA_PF_CAMERA_ERROR_INIT, + "Could not initialize ports"); + return NULL; + } + + if (pfDeviceOpen(0) < 0) { + g_set_error(error, UCA_PF_CAMERA_ERROR, UCA_PF_CAMERA_ERROR_INIT, + "Could not open device"); + return NULL; + } + */ + + UcaPfCamera *camera = g_object_new(UCA_TYPE_PF_CAMERA, NULL); + UcaPfCameraPrivate *priv = UCA_PF_CAMERA_GET_PRIVATE(camera); + + priv->fg_port = PORT_A; + priv->fg = Fg_Init(so_file, priv->fg_port); + + /* TODO: get this from the camera */ + priv->roi_width = 1280; + priv->roi_height = 1024; + + if (priv->fg == NULL) { + g_set_error(error, UCA_PF_CAMERA_ERROR, UCA_PF_CAMERA_ERROR_INIT, + "%s", Fg_getLastErrorDescription(priv->fg)); + g_object_unref(camera); + return NULL; + } + + FG_TRY_PARAM(priv->fg, camera, FG_CAMERA_LINK_CAMTYP, &camera_link_type, priv->fg_port); + FG_TRY_PARAM(priv->fg, camera, FG_FORMAT, &camera_format, priv->fg_port); + FG_TRY_PARAM(priv->fg, camera, FG_WIDTH, &priv->roi_width, priv->fg_port); + FG_TRY_PARAM(priv->fg, camera, FG_HEIGHT, &priv->roi_height, priv->fg_port); + + return UCA_CAMERA (camera); +} diff --git a/plugins/pf/uca-pf-camera.h b/plugins/pf/uca-pf-camera.h new file mode 100644 index 0000000..3a309aa --- /dev/null +++ b/plugins/pf/uca-pf-camera.h @@ -0,0 +1,74 @@ +/* Copyright (C) 2011, 2012 Matthias Vogelgesang + (Karlsruhe Institute of Technology) + + 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 */ + +#ifndef __UCA_PF_CAMERA_H +#define __UCA_PF_CAMERA_H + +#include +#include "uca-camera.h" + +G_BEGIN_DECLS + +#define UCA_TYPE_PF_CAMERA (uca_pf_camera_get_type()) +#define UCA_PF_CAMERA(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), UCA_TYPE_PF_CAMERA, UcaPfCamera)) +#define UCA_IS_PF_CAMERA(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), UCA_TYPE_PF_CAMERA)) +#define UCA_PF_CAMERA_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), UCA_TYPE_PF_CAMERA, UcaPfCameraClass)) +#define UCA_IS_PF_CAMERA_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), UCA_TYPE_PF_CAMERA)) +#define UCA_PF_CAMERA_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), UCA_TYPE_PF_CAMERA, UcaPfCameraClass)) + +#define UCA_PF_CAMERA_ERROR uca_pf_camera_error_quark() +typedef enum { + UCA_PF_CAMERA_ERROR_INIT, + UCA_PF_CAMERA_ERROR_FG_GENERAL, + UCA_PF_CAMERA_ERROR_FG_ACQUISITION, + UCA_PF_CAMERA_ERROR_START_RECORDING, + UCA_PF_CAMERA_ERROR_STOP_RECORDING +} UcaPfCameraError; + +typedef struct _UcaPfCamera UcaPfCamera; +typedef struct _UcaPfCameraClass UcaPfCameraClass; +typedef struct _UcaPfCameraPrivate UcaPfCameraPrivate; + +/** + * UcaPfCamera: + * + * Creates #UcaPfCamera instances by loading corresponding shared objects. The + * contents of the #UcaPfCamera structure are private and should only be + * accessed via the provided API. + */ +struct _UcaPfCamera { + /*< private >*/ + UcaCamera parent; + + UcaPfCameraPrivate *priv; +}; + +/** + * UcaPfCameraClass: + * + * #UcaPfCamera class + */ +struct _UcaPfCameraClass { + /*< private >*/ + UcaCameraClass parent; +}; + +GType uca_pf_camera_get_type(void); + +G_END_DECLS + +#endif diff --git a/plugins/pylon/CMakeLists.txt b/plugins/pylon/CMakeLists.txt new file mode 100644 index 0000000..18823a4 --- /dev/null +++ b/plugins/pylon/CMakeLists.txt @@ -0,0 +1,24 @@ +cmake_minimum_required(VERSION 2.8) +project(ucapylon) + +find_package(Pylon) + +if (PYLON_FOUND) + set(UCA_CAMERA_NAME "pylon") + + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/../package-plugin.sh.in + ${CMAKE_CURRENT_BINARY_DIR}/../../package-plugin-${UCA_CAMERA_NAME}.sh) + + include_directories(${LIBPYLONCAM_INCLUDEDIR}) + + add_library(ucapylon SHARED + uca-pylon-camera.c) + + target_link_libraries(ucapylon + ${UCA_DEPS} + ${LIBPYLONCAM_LIBRARIES}) + + install(TARGETS ucapylon + LIBRARY DESTINATION ${LIB_INSTALL_DIR}/uca + COMPONENT ${UCA_CAMERA_NAME}) +endif() diff --git a/plugins/pylon/uca-pylon-camera.c b/plugins/pylon/uca-pylon-camera.c new file mode 100644 index 0000000..541b69b --- /dev/null +++ b/plugins/pylon/uca-pylon-camera.c @@ -0,0 +1,391 @@ +/* Copyright (C) 2012 Volker Kaiser + (Karlsruhe Institute of Technology) + + 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 +#include +#include +#include +#include "uca-camera.h" +#include "uca-pylon-camera.h" + +#define UCA_PYLON_CAMERA_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), UCA_TYPE_PYLON_CAMERA, UcaPylonCameraPrivate)) + +G_DEFINE_TYPE(UcaPylonCamera, uca_pylon_camera, UCA_TYPE_CAMERA) + +/** + * UcapylonCameraError: + * @UCA_PYLON_CAMERA_ERROR_LIBPYLON_INIT: Initializing libpylon failed + * @UCA_PYLON_CAMERA_ERROR_LIBPYLON_GENERAL: General libpylon error + * @UCA_PYLON_CAMERA_ERROR_UNSUPPORTED: Camera type is not supported + * @UCA_PYLON_CAMERA_ERROR_FG_INIT: Framegrabber initialization failed + * @UCA_PYLON_CAMERA_ERROR_FG_GENERAL: General framegrabber error + * @UCA_PYLON_CAMERA_ERROR_FG_ACQUISITION: Framegrabber acquisition error + */ +GQuark uca_pylon_camera_error_quark() +{ + return g_quark_from_static_string("uca-pylon-camera-error-quark"); +} + +enum { + PROP_ROI_WIDTH_DEFAULT = N_BASE_PROPERTIES, + PROP_ROI_HEIGHT_DEFAULT, + PROP_GAIN, + N_PROPERTIES +}; + +static gint base_overrideables[] = { + PROP_NAME, + PROP_SENSOR_WIDTH, + PROP_SENSOR_HEIGHT, + PROP_SENSOR_BITDEPTH, + PROP_SENSOR_HORIZONTAL_BINNING, + PROP_SENSOR_HORIZONTAL_BINNINGS, + PROP_SENSOR_VERTICAL_BINNING, + PROP_SENSOR_VERTICAL_BINNINGS, + PROP_SENSOR_MAX_FRAME_RATE, + PROP_TRIGGER_MODE, + PROP_EXPOSURE_TIME, + 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 *pylon_properties[N_PROPERTIES] = { NULL, }; + + +struct _UcaPylonCameraPrivate { + guint bit_depth; + gsize num_bytes; + + guint width; + guint height; + guint16 roi_x, roi_y; + guint16 roi_width, roi_height; + GValueArray *binnings; +}; + + +static void pylon_get_roi(GObject *object, GError** error) +{ + UcaPylonCameraPrivate *priv = UCA_PYLON_CAMERA_GET_PRIVATE(object); + pylon_camera_get_roi(&priv->roi_x, &priv->roi_y, &priv->roi_width, &priv->roi_height, error); +} + +static void pylon_set_roi(GObject *object, GError** error) +{ + UcaPylonCameraPrivate *priv = UCA_PYLON_CAMERA_GET_PRIVATE(object); + pylon_camera_set_roi(priv->roi_x, priv->roi_y, priv->roi_width, priv->roi_height, error); +} + +UcaPylonCamera *uca_pylon_camera_new(GError **error) +{ + UcaPylonCamera *camera = g_object_new(UCA_TYPE_PYLON_CAMERA, NULL); + UcaPylonCameraPrivate *priv = UCA_PYLON_CAMERA_GET_PRIVATE(camera); + + pylon_camera_new("/usr/local/lib64", "141.52.111.110", error); + + if (*error != NULL) + return NULL; + + pylon_camera_get_sensor_size(&priv->width, &priv->height, error); + + if (*error != NULL) + return NULL; + + return camera; +} + +static void uca_pylon_camera_start_recording(UcaCamera *camera, GError **error) +{ + g_return_if_fail(UCA_IS_PYLON_CAMERA(camera)); + UcaPylonCameraPrivate *priv = UCA_PYLON_CAMERA_GET_PRIVATE(camera); + + priv->num_bytes = 2; + pylon_camera_start_acquision(error); + +} + +static void uca_pylon_camera_stop_recording(UcaCamera *camera, GError **error) +{ + g_return_if_fail(UCA_IS_PYLON_CAMERA(camera)); + pylon_camera_stop_acquision(error); +} + +static void uca_pylon_camera_grab(UcaCamera *camera, gpointer *data, GError **error) +{ + g_return_if_fail(UCA_IS_PYLON_CAMERA(camera)); + UcaPylonCameraPrivate *priv = UCA_PYLON_CAMERA_GET_PRIVATE(camera); + + if (*data == NULL) { + *data = g_malloc0(priv->width * priv->height * priv->num_bytes); + } + pylon_camera_grab(data, error); +} + +static void uca_pylon_camera_set_property(GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) +{ + UcaPylonCameraPrivate *priv = UCA_PYLON_CAMERA_GET_PRIVATE(object); + GError* error = NULL; + + switch (property_id) { + case PROP_SENSOR_HORIZONTAL_BINNING: + /* intentional fall-through*/ + case PROP_SENSOR_VERTICAL_BINNING: + /* intentional fall-through*/ + case PROP_TRIGGER_MODE: + break; + + case PROP_ROI_X: + { + priv->roi_x = g_value_get_uint(value); + pylon_set_roi(object, &error); + } + break; + + case PROP_ROI_Y: + { + priv->roi_y = g_value_get_uint(value); + pylon_set_roi(object, &error); + } + break; + + case PROP_ROI_WIDTH: + { + priv->roi_width = g_value_get_uint(value); + pylon_set_roi(object, &error); + } + break; + + case PROP_ROI_HEIGHT: + { + priv->roi_height = g_value_get_uint(value); + pylon_set_roi(object, &error); + } + break; + + case PROP_EXPOSURE_TIME: + pylon_camera_set_exposure_time(g_value_get_double(value), &error); + break; + + case PROP_GAIN: + pylon_camera_set_gain(g_value_get_int(value), &error); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); + return; + } +} + +static void uca_pylon_camera_get_property(GObject *object, guint property_id, GValue *value, GParamSpec *pspec) +{ + UcaPylonCameraPrivate *priv = UCA_PYLON_CAMERA_GET_PRIVATE(object); + GError* error = NULL; + + switch (property_id) { + case PROP_SENSOR_WIDTH: + pylon_camera_get_sensor_size(&priv->width, &priv->height, &error); + g_value_set_uint(value, priv->width); + break; + + case PROP_SENSOR_HEIGHT: + pylon_camera_get_sensor_size(&priv->width, &priv->height, &error); + g_value_set_uint(value, priv->height); + break; + + case PROP_SENSOR_BITDEPTH: + pylon_camera_get_bit_depth(&priv->bit_depth, &error); + g_value_set_uint(value, priv->bit_depth); + break; + + case PROP_SENSOR_HORIZONTAL_BINNING: + g_value_set_uint(value, 1); + break; + + case PROP_SENSOR_HORIZONTAL_BINNINGS: + g_value_set_boxed(value, priv->binnings); + break; + + case PROP_SENSOR_VERTICAL_BINNING: + g_value_set_uint(value, 1); + break; + + case PROP_SENSOR_VERTICAL_BINNINGS: + g_value_set_boxed(value, priv->binnings); + break; + + case PROP_SENSOR_MAX_FRAME_RATE: + g_value_set_float(value, 0.0); + break; + + case PROP_TRIGGER_MODE: + g_value_set_enum(value, UCA_CAMERA_TRIGGER_AUTO); + break; + + case PROP_HAS_STREAMING: + g_value_set_boolean(value, FALSE); + break; + + case PROP_HAS_CAMRAM_RECORDING: + g_value_set_boolean(value, FALSE); + break; + + case PROP_ROI_X: + { + pylon_get_roi(object, &error); + g_value_set_uint(value, priv->roi_x); + } + break; + + case PROP_ROI_Y: + { + pylon_get_roi(object, &error); + g_value_set_uint(value, priv->roi_y); + } + break; + + case PROP_ROI_WIDTH: + { + pylon_get_roi(object, &error); + g_value_set_uint(value, priv->roi_width); + } + break; + + case PROP_ROI_HEIGHT: + { + pylon_get_roi(object, &error); + g_value_set_uint(value, priv->roi_height); + } + break; + + case PROP_ROI_WIDTH_DEFAULT: + pylon_camera_get_sensor_size(&priv->width, &priv->height, &error); + g_value_set_uint(value, priv->width); + break; + + case PROP_ROI_HEIGHT_DEFAULT: + pylon_camera_get_sensor_size(&priv->width, &priv->height, &error); + g_value_set_uint(value, priv->height); + break; + + case PROP_GAIN: + { + gint gain=0; + pylon_camera_get_gain(&gain, &error); + g_value_set_int(value, gain); + } + break; + + case PROP_ROI_WIDTH_MULTIPLIER: + g_value_set_uint(value, 1); + break; + + case PROP_ROI_HEIGHT_MULTIPLIER: + g_value_set_uint(value, 1); + break; + + case PROP_EXPOSURE_TIME: + { + gdouble exp_time = 0.0; + pylon_camera_get_exposure_time(&exp_time, &error); + g_value_set_double(value, exp_time); + } + break; + + case PROP_NAME: + g_value_set_string(value, "Pylon Camera"); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); + break; + } +} + +static void uca_pylon_camera_finalize(GObject *object) +{ + UcaPylonCameraPrivate *priv = UCA_PYLON_CAMERA_GET_PRIVATE(object); + g_value_array_free(priv->binnings); + + G_OBJECT_CLASS(uca_pylon_camera_parent_class)->finalize(object); +} + +static void uca_pylon_camera_class_init(UcaPylonCameraClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS(klass); + gobject_class->set_property = uca_pylon_camera_set_property; + gobject_class->get_property = uca_pylon_camera_get_property; + gobject_class->finalize = uca_pylon_camera_finalize; + + UcaCameraClass *camera_class = UCA_CAMERA_CLASS(klass); + camera_class->start_recording = uca_pylon_camera_start_recording; + camera_class->stop_recording = uca_pylon_camera_stop_recording; + camera_class->grab = uca_pylon_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]]); + + pylon_properties[PROP_NAME] = + g_param_spec_string("name", + "Name of the camera", + "Name of the camera", + "", G_PARAM_READABLE); + + pylon_properties[PROP_ROI_WIDTH_DEFAULT] = + g_param_spec_uint("roi-width-default", + "ROI width default value", + "ROI width default value", + 0, G_MAXUINT, 0, + G_PARAM_READABLE); + + pylon_properties[PROP_ROI_HEIGHT_DEFAULT] = + g_param_spec_uint("roi-height-default", + "ROI height default value", + "ROI height default value", + 0, G_MAXUINT, 0, + G_PARAM_READABLE); + + pylon_properties[PROP_GAIN] = + g_param_spec_int("gain", + "gain", + "gain", + 0, G_MAXINT, 0, + G_PARAM_READWRITE); + + for (guint id = N_BASE_PROPERTIES; id < N_PROPERTIES; id++) + g_object_class_install_property(gobject_class, id, pylon_properties[id]); + + g_type_class_add_private(klass, sizeof(UcaPylonCameraPrivate)); +} + +static void uca_pylon_camera_init(UcaPylonCamera *self) +{ + self->priv = UCA_PYLON_CAMERA_GET_PRIVATE(self); + + /* binnings */ + GValue val = {0}; + g_value_init(&val, G_TYPE_UINT); + g_value_set_uint(&val, 1); + self->priv->binnings = g_value_array_new(1); + g_value_array_append(self->priv->binnings, &val); +} diff --git a/plugins/pylon/uca-pylon-camera.h b/plugins/pylon/uca-pylon-camera.h new file mode 100644 index 0000000..eebf63c --- /dev/null +++ b/plugins/pylon/uca-pylon-camera.h @@ -0,0 +1,74 @@ +/* Copyright (C) 2011, 2012 Matthias Vogelgesang + (Karlsruhe Institute of Technology) + + 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 */ + +#ifndef __UCA_PYLON_CAMERA_H +#define __UCA_PYLON_CAMERA_H + +#include +#include "uca-camera.h" + +G_BEGIN_DECLS + +#define UCA_TYPE_PYLON_CAMERA (uca_pylon_camera_get_type()) +#define UCA_PYLON_CAMERA(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), UCA_TYPE_PYLON_CAMERA, UcaPylonCamera)) +#define UCA_IS_PYLON_CAMERA(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), UCA_TYPE_PYLON_CAMERA)) +#define UCA_PYLON_CAMERA_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), UFO_TYPE_PYLON_CAMERA, UfoPylonCameraClass)) +#define UCA_IS_PYLON_CAMERA_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), UCA_TYPE_PYLON_CAMERA)) +#define UCA_PYLON_CAMERA_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), UCA_TYPE_PYLON_CAMERA, UcaPylonCameraClass)) + +#define UCA_PYLON_CAMERA_ERROR uca_pylon_camera_error_quark() +typedef enum { + UCA_PYLON_CAMERA_ERROR_LIBPYLON_INIT, + UCA_PYLON_CAMERA_ERROR_LIBPYLON_GENERAL, + UCA_PYLON_CAMERA_ERROR_UNSUPPORTED, +} UcaPylonCameraError; + +typedef struct _UcaPylonCamera UcaPylonCamera; +typedef struct _UcaPylonCameraClass UcaPylonCameraClass; +typedef struct _UcaPylonCameraPrivate UcaPylonCameraPrivate; + +/** + * UcaPylonCamera: + * + * Creates #UcaPylonCamera instances by loading corresponding shared objects. The + * contents of the #UcaPylonCamera structure are private and should only be + * accessed via the provided API. + */ +struct _UcaPylonCamera { + /*< private >*/ + UcaCamera parent; + + UcaPylonCameraPrivate *priv; +}; + +/** + * UcaPylonCameraClass: + * + * #UcaPylonCamera class + */ +struct _UcaPylonCameraClass { + /*< private >*/ + UcaCameraClass parent; +}; + +UcaPylonCamera *uca_pylon_camera_new(GError **error); + +GType uca_pylon_camera_get_type(void); + +G_END_DECLS + +#endif diff --git a/plugins/ufo/CMakeLists.txt b/plugins/ufo/CMakeLists.txt new file mode 100644 index 0000000..fe89668 --- /dev/null +++ b/plugins/ufo/CMakeLists.txt @@ -0,0 +1,24 @@ +cmake_minimum_required(VERSION 2.8) +project(ucaufo) + +find_package(IPE) + +if (IPE_FOUND) + set(UCA_CAMERA_NAME "ufo") + + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/../package-plugin.sh.in + ${CMAKE_CURRENT_BINARY_DIR}/../../package-plugin-${UCA_CAMERA_NAME}.sh) + + include_directories(${IPE_INCLUDE_DIRS}) + + add_library(ucaufo SHARED + uca-ufo-camera.c) + + target_link_libraries(ucaufo + ${UCA_DEPS} + ${IPE_LIBRARIES}) + + install(TARGETS ucaufo + LIBRARY DESTINATION ${LIB_INSTALL_DIR}/uca + COMPONENT ${UCA_CAMERA_NAME}) +endif() diff --git a/plugins/ufo/uca-ufo-camera.c b/plugins/ufo/uca-ufo-camera.c new file mode 100644 index 0000000..7542fdf --- /dev/null +++ b/plugins/ufo/uca-ufo-camera.c @@ -0,0 +1,497 @@ +/* Copyright (C) 2011, 2012 Matthias Vogelgesang + (Karlsruhe Institute of Technology) + + 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 +#include +#include +#include +#include +#include +#include "uca-camera.h" +#include "uca-ufo-camera.h" + +#define PCILIB_SET_ERROR(err, err_type) \ + if (err != 0) { \ + g_set_error(error, UCA_UFO_CAMERA_ERROR, \ + err_type, \ + "pcilib: %s", strerror(err)); \ + return; \ + } + +#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 const guint SENSOR_WIDTH = 2048; +static const guint SENSOR_HEIGHT = 1088; +static const gdouble EXPOSURE_TIME_SCALE = 2.69e6; + +/** + * UcaUfoCameraError: + * @UCA_UFO_CAMERA_ERROR_INIT: Initializing pcilib failed + * @UCA_UFO_CAMERA_ERROR_START_RECORDING: Starting failed + * @UCA_UFO_CAMERA_ERROR_STOP_RECORDING: Stopping failed + * @UCA_UFO_CAMERA_ERROR_TRIGGER: Triggering a frame failed + * @UCA_UFO_CAMERA_ERROR_NEXT_EVENT: No event happened + * @UCA_UFO_CAMERA_ERROR_NO_DATA: No data was transmitted + * @UCA_UFO_CAMERA_ERROR_MAYBE_CORRUPTED: Data is potentially corrupted + */ +GQuark uca_ufo_camera_error_quark() +{ + return g_quark_from_static_string("uca-ufo-camera-error-quark"); +} + +enum { + PROP_SENSOR_TEMPERATURE = N_BASE_PROPERTIES, + PROP_FPGA_TEMPERATURE, + PROP_UFO_START, + N_MAX_PROPERTIES = 512 +}; + +static gint base_overrideables[] = { + PROP_NAME, + PROP_SENSOR_WIDTH, + PROP_SENSOR_HEIGHT, + PROP_SENSOR_HORIZONTAL_BINNING, + PROP_SENSOR_VERTICAL_BINNING, + PROP_SENSOR_MAX_FRAME_RATE, + PROP_SENSOR_BITDEPTH, + PROP_EXPOSURE_TIME, + 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, + PROP_TRIGGER_MODE, + 0, +}; + +typedef struct _RegisterInfo { + gchar *name; + guint cached_value; +} 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 { + pcilib_t *handle; + pcilib_timeout_t timeout; + guint n_bits; + enum { + FPGA_48MHZ = 0, + FPGA_40MHZ + } frequency; +}; + +static void +error_handler (const char *format, ...) +{ + va_list args; + gchar *message; + + va_start (args, format); + message = g_strdup_vprintf (format, args); + g_warning ("%s", message); + va_end (args); +} + +static guint +read_register_value (pcilib_t *handle, const gchar *name) +{ + pcilib_register_value_t reg_value; + + pcilib_read_register(handle, NULL, name, ®_value); + return (guint) reg_value; +} + +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); + size_t error = 0; + + void *buffer = pcilib_get_data(priv->handle, event_id, PCILIB_EVENT_DATA, &error); + + if (buffer == NULL) { + pcilib_trigger(priv->handle, PCILIB_EVENT0, 0, 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); + + return PCILIB_STREAMING_CONTINUE; +} + +G_MODULE_EXPORT UcaCamera * +uca_camera_impl_new (GError **error) +{ + 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; + } + + pcilib_set_error_handler(&error_handler, &error_handler); + + /* 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++) { + GParamFlags flags = 0; + RegisterInfo *reg_info; + gchar *prop_name; + pcilib_register_description_t *reg; + pcilib_register_value_t value; + + reg = &model_description->registers[i]; + + switch (reg->mode) { + case PCILIB_REGISTER_R: + flags = G_PARAM_READABLE; + break; + case PCILIB_REGISTER_W: + case PCILIB_REGISTER_W1C: + flags = G_PARAM_WRITABLE; + break; + case PCILIB_REGISTER_RW: + case PCILIB_REGISTER_RW1C: + flags = G_PARAM_READWRITE; + break; + } + + pcilib_read_register (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); + prop_name = g_strdup_printf ("ufo-%s", reg->name); + + ufo_properties[prop++] = g_param_spec_uint ( + prop_name, reg->description, reg->description, + 0, G_MAXUINT, reg->defvalue, flags); + + g_free (prop_name); + } + + N_PROPERTIES = prop; + + UcaUfoCamera *camera = g_object_new(UCA_TYPE_UFO_CAMERA, NULL); + UcaUfoCameraPrivate *priv = UCA_UFO_CAMERA_GET_PRIVATE(camera); + + priv->frequency = read_register_value (handle, "bit_mode"); + adc_resolution = read_register_value (handle, "adc_resolution"); + + switch (adc_resolution) { + case 0: + priv->n_bits = 10; + break; + case 1: + priv->n_bits = 11; + break; + case 2: + priv->n_bits = 12; + break; + } + + priv->handle = handle; + + return UCA_CAMERA (camera); +} + +static void uca_ufo_camera_start_recording(UcaCamera *camera, GError **error) +{ + UcaUfoCameraPrivate *priv; + gdouble exposure_time; + int err; + + g_return_if_fail(UCA_IS_UFO_CAMERA(camera)); + + priv = UCA_UFO_CAMERA_GET_PRIVATE(camera); + 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, + NULL); + + 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); + } +} + +static void uca_ufo_camera_stop_recording(UcaCamera *camera, GError **error) +{ + 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); +} + +static void uca_ufo_camera_start_readout(UcaCamera *camera, GError **error) +{ + g_return_if_fail(UCA_IS_UFO_CAMERA(camera)); + g_set_error(error, UCA_CAMERA_ERROR, UCA_CAMERA_ERROR_NOT_IMPLEMENTED, + "Ufo camera does not support recording to internal memory"); +} + +static void uca_ufo_camera_grab(UcaCamera *camera, gpointer *data, GError **error) +{ + g_return_if_fail(UCA_IS_UFO_CAMERA(camera)); + UcaUfoCameraPrivate *priv = UCA_UFO_CAMERA_GET_PRIVATE(camera); + pcilib_event_id_t event_id; + pcilib_event_info_t event_info; + size_t err; + + const gsize size = SENSOR_WIDTH * SENSOR_HEIGHT * sizeof(guint16); + + 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)); + + gpointer src = pcilib_get_data(priv->handle, event_id, PCILIB_EVENT_DATA, &err); + + if (src == NULL) + PCILIB_SET_ERROR(err, UCA_UFO_CAMERA_ERROR_NO_DATA); + + /* + * Apparently, we checked that err equals total size in previous version. + * This is problematic because errno is positive and size could be equal + * even when an error condition is met, e.g. with a very small ROI. However, + * we don't know if src will always be NULL when an error occured. + */ + /* assert(err == 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); +} + +static void +uca_ufo_camera_set_property(GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) +{ + UcaUfoCameraPrivate *priv = UCA_UFO_CAMERA_GET_PRIVATE(object); + + switch (property_id) { + case PROP_EXPOSURE_TIME: + { + const guint frequency = priv->frequency == FPGA_40MHZ ? 40 : 48; + pcilib_register_value_t reg_value = (pcilib_register_value_t) 129 / frequency * 1000 * 1000 * g_value_get_double(value); + pcilib_write_register(priv->handle, NULL, "cmosis_exp_time", reg_value); + } + break; + case PROP_ROI_X: + case PROP_ROI_Y: + case PROP_ROI_WIDTH: + case PROP_ROI_HEIGHT: + g_debug("ROI feature not implemented yet"); + break; + + default: + { + RegisterInfo *reg_info = g_hash_table_lookup (ufo_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_read_register (priv->handle, NULL, reg_info->name, ®_value); + reg_info->cached_value = (guint) reg_value; + } + else + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); + } + return; + } +} + + +static void +uca_ufo_camera_get_property(GObject *object, guint property_id, GValue *value, GParamSpec *pspec) +{ + UcaUfoCameraPrivate *priv = UCA_UFO_CAMERA_GET_PRIVATE(object); + + switch (property_id) { + case PROP_SENSOR_WIDTH: + g_value_set_uint(value, SENSOR_WIDTH); + break; + case PROP_SENSOR_HEIGHT: + g_value_set_uint(value, SENSOR_HEIGHT); + break; + case PROP_SENSOR_BITDEPTH: + g_value_set_uint (value, priv->n_bits); + break; + case PROP_SENSOR_HORIZONTAL_BINNING: + g_value_set_uint(value, 1); + break; + case PROP_SENSOR_VERTICAL_BINNING: + g_value_set_uint(value, 1); + break; + case PROP_SENSOR_MAX_FRAME_RATE: + g_value_set_float(value, 340.0); + break; + case PROP_SENSOR_TEMPERATURE: + { + const double a = priv->frequency == FPGA_48MHZ ? 0.3 : 0.25; + const double b = priv->frequency == FPGA_48MHZ ? 1000 : 1200; + guint32 temperature; + + temperature = read_register_value (priv->handle, "sensor_temperature"); + g_value_set_double (value, a * (temperature - b)); + } + break; + case PROP_FPGA_TEMPERATURE: + { + const double a = 503.975 / 1024.0; + const double b = 273.15; + guint32 temperature; + + temperature = read_register_value (priv->handle, "fpga_temperature"); + g_value_set_double (value, a * temperature - b); + } + break; + case PROP_EXPOSURE_TIME: + { + const gdouble frequency = priv->frequency == FPGA_40MHZ ? 40.0 : 48.0; + g_value_set_double (value, read_register_value (priv->handle, "cmosis_exp_time") * 129 / frequency / 1000 / 1000 ); + } + break; + case PROP_HAS_STREAMING: + g_value_set_boolean(value, TRUE); + break; + case PROP_HAS_CAMRAM_RECORDING: + g_value_set_boolean(value, FALSE); + break; + case PROP_ROI_X: + g_value_set_uint(value, 0); + break; + case PROP_ROI_Y: + g_value_set_uint(value, 0); + break; + case PROP_ROI_WIDTH: + g_value_set_uint(value, SENSOR_WIDTH); + break; + case PROP_ROI_HEIGHT: + g_value_set_uint(value, SENSOR_HEIGHT); + break; + case PROP_ROI_WIDTH_MULTIPLIER: + g_value_set_uint(value, 1); + break; + case PROP_ROI_HEIGHT_MULTIPLIER: + g_value_set_uint(value, 1); + break; + case PROP_NAME: + g_value_set_string(value, "Ufo Camera w/ CMOSIS CMV2000"); + break; + case PROP_TRIGGER_MODE: + break; + default: + { + RegisterInfo *reg_info = g_hash_table_lookup (ufo_property_table, GINT_TO_POINTER (property_id)); + + if (reg_info != NULL) + g_value_set_uint (value, reg_info->cached_value); + else + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); + } + break; + } +} + +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); +} + +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; + gobject_class->get_property = uca_ufo_camera_get_property; + gobject_class->finalize = uca_ufo_camera_finalize; + + UcaCameraClass *camera_class = UCA_CAMERA_CLASS(klass); + camera_class->start_recording = uca_ufo_camera_start_recording; + camera_class->stop_recording = uca_ufo_camera_stop_recording; + camera_class->start_readout = uca_ufo_camera_start_readout; + camera_class->grab = uca_ufo_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]]); + + ufo_properties[PROP_SENSOR_TEMPERATURE] = + g_param_spec_double("sensor-temperature", + "Temperature of the sensor", + "Temperature of the sensor in degree Celsius", + -G_MAXDOUBLE, G_MAXDOUBLE, 0.0, + G_PARAM_READABLE); + + ufo_properties[PROP_FPGA_TEMPERATURE] = + g_param_spec_double("fpga-temperature", + "Temperature of the FPGA", + "Temperature of the FPGA in degree Celsius", + -G_MAXDOUBLE, G_MAXDOUBLE, 0.0, + G_PARAM_READABLE); + + /* + * This automatic property installation includes the properties created + * dynamically in uca_ufo_camera_new(). + */ + for (guint id = N_BASE_PROPERTIES; id < N_PROPERTIES; id++) + g_object_class_install_property(gobject_class, id, ufo_properties[id]); + + g_type_class_add_private(klass, sizeof(UcaUfoCameraPrivate)); +} + +static void uca_ufo_camera_init(UcaUfoCamera *self) +{ + self->priv = UCA_UFO_CAMERA_GET_PRIVATE(self); +} diff --git a/plugins/ufo/uca-ufo-camera.h b/plugins/ufo/uca-ufo-camera.h new file mode 100644 index 0000000..7030389 --- /dev/null +++ b/plugins/ufo/uca-ufo-camera.h @@ -0,0 +1,76 @@ +/* Copyright (C) 2011, 2012 Matthias Vogelgesang + (Karlsruhe Institute of Technology) + + 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 */ + +#ifndef __UCA_UFO_CAMERA_H +#define __UCA_UFO_CAMERA_H + +#include +#include "uca-camera.h" + +G_BEGIN_DECLS + +#define UCA_TYPE_UFO_CAMERA (uca_ufo_camera_get_type()) +#define UCA_UFO_CAMERA(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), UCA_TYPE_UFO_CAMERA, UcaUfoCamera)) +#define UCA_IS_UFO_CAMERA(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), UCA_TYPE_UFO_CAMERA)) +#define UCA_UFO_CAMERA_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), UCA_TYPE_UFO_CAMERA, UcaUfoCameraClass)) +#define UCA_IS_UFO_CAMERA_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), UCA_TYPE_UFO_CAMERA)) +#define UCA_UFO_CAMERA_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), UCA_TYPE_UFO_CAMERA, UcaUfoCameraClass)) + +#define UCA_UFO_CAMERA_ERROR uca_ufo_camera_error_quark() +typedef enum { + UCA_UFO_CAMERA_ERROR_INIT, + UCA_UFO_CAMERA_ERROR_START_RECORDING, + UCA_UFO_CAMERA_ERROR_STOP_RECORDING, + UCA_UFO_CAMERA_ERROR_TRIGGER, + UCA_UFO_CAMERA_ERROR_NEXT_EVENT, + UCA_UFO_CAMERA_ERROR_NO_DATA, + UCA_UFO_CAMERA_ERROR_MAYBE_CORRUPTED +} UcaUfoCameraError; + +typedef struct _UcaUfoCamera UcaUfoCamera; +typedef struct _UcaUfoCameraClass UcaUfoCameraClass; +typedef struct _UcaUfoCameraPrivate UcaUfoCameraPrivate; + +/** + * UcaUfoCamera: + * + * Creates #UcaUfoCamera instances by loading corresponding shared objects. The + * contents of the #UcaUfoCamera structure are private and should only be + * accessed via the provided API. + */ +struct _UcaUfoCamera { + /*< private >*/ + UcaCamera parent; + + UcaUfoCameraPrivate *priv; +}; + +/** + * UcaUfoCameraClass: + * + * #UcaUfoCamera class + */ +struct _UcaUfoCameraClass { + /*< private >*/ + UcaCameraClass parent; +}; + +GType uca_ufo_camera_get_type(void); + +G_END_DECLS + +#endif -- cgit v1.2.3 From b8d34c22c479bd5def2744eae3a9380d3ff843c2 Mon Sep 17 00:00:00 2001 From: Matthias Vogelgesang Date: Mon, 1 Oct 2012 09:08:52 +0200 Subject: Define plugins as C projects Otherwise CMake complains about non-existent C++ compilers, which are not needed here anyway. --- plugins/mock/CMakeLists.txt | 2 +- plugins/pco/CMakeLists.txt | 2 +- plugins/pf/CMakeLists.txt | 2 +- plugins/pylon/CMakeLists.txt | 3 +-- plugins/ufo/CMakeLists.txt | 2 +- 5 files changed, 5 insertions(+), 6 deletions(-) (limited to 'plugins') diff --git a/plugins/mock/CMakeLists.txt b/plugins/mock/CMakeLists.txt index 75d8635..d5b6771 100644 --- a/plugins/mock/CMakeLists.txt +++ b/plugins/mock/CMakeLists.txt @@ -1,5 +1,5 @@ cmake_minimum_required(VERSION 2.8) -project(ucamock) +project(ucamock C) set(UCA_CAMERA_NAME "mock") diff --git a/plugins/pco/CMakeLists.txt b/plugins/pco/CMakeLists.txt index 7c016b9..a526f4d 100644 --- a/plugins/pco/CMakeLists.txt +++ b/plugins/pco/CMakeLists.txt @@ -1,5 +1,5 @@ cmake_minimum_required(VERSION 2.8) -project(ucapco) +project(ucapco C) find_package(PCO) find_package(FgLib5) diff --git a/plugins/pf/CMakeLists.txt b/plugins/pf/CMakeLists.txt index f392603..ef11f8f 100644 --- a/plugins/pf/CMakeLists.txt +++ b/plugins/pf/CMakeLists.txt @@ -1,5 +1,5 @@ cmake_minimum_required(VERSION 2.8) -project(ucapf) +project(ucapf C) find_package(PF) find_package(FgLib5) diff --git a/plugins/pylon/CMakeLists.txt b/plugins/pylon/CMakeLists.txt index 18823a4..9a3c15c 100644 --- a/plugins/pylon/CMakeLists.txt +++ b/plugins/pylon/CMakeLists.txt @@ -1,7 +1,6 @@ cmake_minimum_required(VERSION 2.8) -project(ucapylon) +project(ucapylon C) -find_package(Pylon) if (PYLON_FOUND) set(UCA_CAMERA_NAME "pylon") diff --git a/plugins/ufo/CMakeLists.txt b/plugins/ufo/CMakeLists.txt index fe89668..c7fd21b 100644 --- a/plugins/ufo/CMakeLists.txt +++ b/plugins/ufo/CMakeLists.txt @@ -1,5 +1,5 @@ cmake_minimum_required(VERSION 2.8) -project(ucaufo) +project(ucaufo C) find_package(IPE) -- cgit v1.2.3 From 21bce1b4a01ff6735325457297aa9bd8fcdebe8f Mon Sep 17 00:00:00 2001 From: Matthias Vogelgesang Date: Tue, 9 Oct 2012 14:12:18 +0200 Subject: Load correct framegrabber plugin --- plugins/pco/uca-pco-camera.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'plugins') diff --git a/plugins/pco/uca-pco-camera.c b/plugins/pco/uca-pco-camera.c index 8bf2936..352c5f0 100644 --- a/plugins/pco/uca-pco-camera.c +++ b/plugins/pco/uca-pco-camera.c @@ -190,7 +190,7 @@ struct _UcaPcoCameraPrivate { static pco_cl_map_entry pco_cl_map[] = { { CAMERATYPE_PCO_EDGE, "libFullAreaGray8.so", FG_CL_8BIT_FULL_10, FG_GRAY, 30.0f, FALSE }, { CAMERATYPE_PCO4000, "libDualAreaGray16.so", FG_CL_SINGLETAP_16_BIT, FG_GRAY16, 5.0f, TRUE }, - { CAMERATYPE_PCO_DIMAX_STD, "libFullAreaGray16.so", FG_CL_SINGLETAP_8_BIT, FG_GRAY16, 1279.0f, TRUE }, + { CAMERATYPE_PCO_DIMAX_STD, "libDualAreaGray16.so", FG_CL_SINGLETAP_8_BIT, FG_GRAY16, 1279.0f, TRUE }, { 0, NULL, 0, 0, 0.0f, FALSE } }; -- cgit v1.2.3 From 805129cf7452e37c6d1042a87fadd297098fac9c Mon Sep 17 00:00:00 2001 From: Matthias Vogelgesang Date: Tue, 9 Oct 2012 14:35:06 +0200 Subject: Fix #149: Make timestamp mode an enum --- plugins/pco/uca-pco-camera.c | 40 +++++++++++++++++----------------------- plugins/pco/uca-pco-camera.h | 7 ++++--- 2 files changed, 21 insertions(+), 26 deletions(-) (limited to 'plugins') diff --git a/plugins/pco/uca-pco-camera.c b/plugins/pco/uca-pco-camera.c index 352c5f0..ccccf82 100644 --- a/plugins/pco/uca-pco-camera.c +++ b/plugins/pco/uca-pco-camera.c @@ -77,6 +77,7 @@ G_DEFINE_TYPE(UcaPcoCamera, uca_pco_camera, UCA_TYPE_CAMERA) * @UCA_PCO_CAMERA_TIMESTAMP_BINARY: Embed a BCD-coded timestamp in the first * bytes * @UCA_PCO_CAMERA_TIMESTAMP_ASCII: Embed a visible ASCII timestamp in the image + * @UCA_PCO_CAMERA_TIMESTAMP_BOTH: Embed both types of timestamps */ /** @@ -769,13 +770,14 @@ static void uca_pco_camera_set_property(GObject *object, guint property_id, cons case PROP_TIMESTAMP_MODE: { - guint16 modes[] = { - TIMESTAMP_MODE_OFF, /* 0 */ - TIMESTAMP_MODE_BINARY, /* 1 = 1 << 0 */ - TIMESTAMP_MODE_ASCII, /* 2 = 1 << 1 */ - TIMESTAMP_MODE_BINARYANDASCII, /* 3 = 1 << 0 | 1 << 1 */ + guint16 table[] = { + TIMESTAMP_MODE_OFF, + TIMESTAMP_MODE_BINARY, + TIMESTAMP_MODE_BINARYANDASCII, + TIMESTAMP_MODE_ASCII, }; - pco_set_timestamp_mode(priv->pco, modes[g_value_get_flags(value)]); + + pco_set_timestamp_mode(priv->pco, table[g_value_get_flags(value)]); } break; @@ -1055,23 +1057,15 @@ static void uca_pco_camera_get_property(GObject *object, guint property_id, GVal case PROP_TIMESTAMP_MODE: { guint16 mode; - pco_get_timestamp_mode(priv->pco, &mode); + UcaPcoCameraTimestamp table[] = { + UCA_PCO_CAMERA_TIMESTAMP_NONE, + UCA_PCO_CAMERA_TIMESTAMP_BINARY, + UCA_PCO_CAMERA_TIMESTAMP_BOTH, + UCA_PCO_CAMERA_TIMESTAMP_ASCII + }; - switch (mode) { - case TIMESTAMP_MODE_OFF: - g_value_set_flags(value, UCA_PCO_CAMERA_TIMESTAMP_NONE); - break; - case TIMESTAMP_MODE_BINARY: - g_value_set_flags(value, UCA_PCO_CAMERA_TIMESTAMP_BINARY); - break; - case TIMESTAMP_MODE_BINARYANDASCII: - g_value_set_flags(value, - UCA_PCO_CAMERA_TIMESTAMP_BINARY | UCA_PCO_CAMERA_TIMESTAMP_ASCII); - break; - case TIMESTAMP_MODE_ASCII: - g_value_set_flags(value, UCA_PCO_CAMERA_TIMESTAMP_ASCII); - break; - } + pco_get_timestamp_mode(priv->pco, &mode); + g_value_set_enum (value, table[mode]); } break; @@ -1280,7 +1274,7 @@ static void uca_pco_camera_class_init(UcaPcoCameraClass *klass) G_PARAM_READABLE); pco_properties[PROP_TIMESTAMP_MODE] = - g_param_spec_flags("timestamp-mode", + g_param_spec_enum("timestamp-mode", "Timestamp mode", "Timestamp mode", UCA_TYPE_PCO_CAMERA_TIMESTAMP, UCA_PCO_CAMERA_TIMESTAMP_NONE, diff --git a/plugins/pco/uca-pco-camera.h b/plugins/pco/uca-pco-camera.h index 73ae44e..d134fb1 100644 --- a/plugins/pco/uca-pco-camera.h +++ b/plugins/pco/uca-pco-camera.h @@ -55,9 +55,10 @@ typedef enum { } UcaPcoCameraAcquireMode; typedef enum { - UCA_PCO_CAMERA_TIMESTAMP_NONE = 0, - UCA_PCO_CAMERA_TIMESTAMP_BINARY = 1 << 0, - UCA_PCO_CAMERA_TIMESTAMP_ASCII = 1 << 1 + UCA_PCO_CAMERA_TIMESTAMP_NONE, + UCA_PCO_CAMERA_TIMESTAMP_BINARY, + UCA_PCO_CAMERA_TIMESTAMP_ASCII, + UCA_PCO_CAMERA_TIMESTAMP_BOTH } UcaPcoCameraTimestamp; /** -- cgit v1.2.3 From 4a27a2e95aa1a2312ad17404d7ab236b2fa6f1b7 Mon Sep 17 00:00:00 2001 From: Matthias Vogelgesang Date: Tue, 9 Oct 2012 15:43:10 +0200 Subject: Fix #150: Add "frames-per-second" property Right now, there is only information for the DIMAX camera about the actual inherent system delay. For all other cameras fps = 1. / t_exp. --- plugins/pco/uca-pco-camera.c | 111 +++++++++++++++++++++++++++++++++++-------- 1 file changed, 91 insertions(+), 20 deletions(-) (limited to 'plugins') diff --git a/plugins/pco/uca-pco-camera.c b/plugins/pco/uca-pco-camera.c index ccccf82..893a480 100644 --- a/plugins/pco/uca-pco-camera.c +++ b/plugins/pco/uca-pco-camera.c @@ -129,6 +129,7 @@ static gint base_overrideables[] = { PROP_SENSOR_VERTICAL_BINNINGS, PROP_SENSOR_MAX_FRAME_RATE, PROP_EXPOSURE_TIME, + PROP_FRAMES_PER_SECOND, PROP_TRIGGER_MODE, PROP_ROI_X, PROP_ROI_Y, @@ -208,7 +209,8 @@ static pco_cl_map_entry *get_pco_cl_map_entry(int camera_type) return NULL; } -static guint fill_binnings(UcaPcoCameraPrivate *priv) +static guint +fill_binnings(UcaPcoCameraPrivate *priv) { uint16_t *horizontal = NULL; uint16_t *vertical = NULL; @@ -241,7 +243,8 @@ static guint fill_binnings(UcaPcoCameraPrivate *priv) return err; } -static void fill_pixelrates(UcaPcoCameraPrivate *priv, guint32 rates[4], gint num_rates) +static void +fill_pixelrates(UcaPcoCameraPrivate *priv, guint32 rates[4], gint num_rates) { GValue val = {0}; g_value_init(&val, G_TYPE_UINT); @@ -253,7 +256,8 @@ static void fill_pixelrates(UcaPcoCameraPrivate *priv, guint32 rates[4], gint nu } } -static guint override_temperature_range(UcaPcoCameraPrivate *priv) +static guint +override_temperature_range(UcaPcoCameraPrivate *priv) { int16_t default_temp, min_temp, max_temp; guint err = pco_get_cooling_range(priv->pco, &default_temp, &min_temp, &max_temp); @@ -270,7 +274,8 @@ static guint override_temperature_range(UcaPcoCameraPrivate *priv) return err; } -static void property_override_default_guint_value (GObjectClass *oclass, const gchar *property_name, guint new_default) +static void +property_override_default_guint_value (GObjectClass *oclass, const gchar *property_name, guint new_default) { GParamSpecUInt *pspec = G_PARAM_SPEC_UINT (g_object_class_find_property (oclass, property_name)); @@ -280,13 +285,15 @@ static void property_override_default_guint_value (GObjectClass *oclass, const g g_warning ("pspec for %s not found\n", property_name); } -static void override_maximum_adcs(UcaPcoCameraPrivate *priv) +static void +override_maximum_adcs(UcaPcoCameraPrivate *priv) { GParamSpecInt *spec = (GParamSpecInt *) pco_properties[PROP_SENSOR_ADCS]; spec->maximum = pco_get_maximum_number_of_adcs(priv->pco); } -static gdouble convert_timebase(guint16 timebase) +static gdouble +convert_timebase(guint16 timebase) { switch (timebase) { case TIMEBASE_NS: @@ -301,12 +308,14 @@ static gdouble convert_timebase(guint16 timebase) return 1e-3; } -static void read_timebase(UcaPcoCameraPrivate *priv) +static void +read_timebase(UcaPcoCameraPrivate *priv) { pco_get_timebase(priv->pco, &priv->delay_timebase, &priv->exposure_timebase); } -static gdouble get_suitable_timebase(gdouble time) +static gdouble +get_suitable_timebase(gdouble time) { if (time * 1e3 >= 1.0) return TIMEBASE_MS; @@ -317,7 +326,24 @@ static gdouble get_suitable_timebase(gdouble time) return TIMEBASE_INVALID; } -static int fg_callback(frameindex_t frame, struct fg_apc_data *apc) +static gdouble +get_internal_delay (UcaPcoCamera *camera) +{ + if (camera->priv->camera_description->camera_type == CAMERATYPE_PCO_DIMAX_STD) { + gdouble sensor_rate; + g_object_get (camera, "sensor-rate", &sensor_rate, NULL); + + if (sensor_rate == 55000000.0) + return 0.000079; + else if (sensor_rate == 62500000.0) + return 0.000069; + } + + return 0.0; +} + +static int +fg_callback(frameindex_t frame, struct fg_apc_data *apc) { UcaCamera *camera = UCA_CAMERA(apc); UcaPcoCameraPrivate *priv = UCA_PCO_CAMERA_GET_PRIVATE(camera); @@ -333,7 +359,8 @@ static int fg_callback(frameindex_t frame, struct fg_apc_data *apc) return 0; } -static gboolean setup_fg_callback(UcaCamera *camera) +static gboolean +setup_fg_callback(UcaCamera *camera) { UcaPcoCameraPrivate *priv = UCA_PCO_CAMERA_GET_PRIVATE(camera); struct FgApcControl ctrl; @@ -353,7 +380,8 @@ static gboolean setup_fg_callback(UcaCamera *camera) return Fg_registerApcHandler(priv->fg, priv->fg_port, &ctrl, FG_APC_CONTROL_BASIC) == FG_OK; } -static void uca_pco_camera_start_recording(UcaCamera *camera, GError **error) +static void +uca_pco_camera_start_recording(UcaCamera *camera, GError **error) { g_return_if_fail(UCA_IS_PCO_CAMERA(camera)); guint err = PCO_NOERROR; @@ -451,7 +479,8 @@ static void uca_pco_camera_start_recording(UcaCamera *camera, GError **error) FG_SET_ERROR(err, priv->fg, UCA_PCO_CAMERA_ERROR_FG_ACQUISITION); } -static void uca_pco_camera_stop_recording(UcaCamera *camera, GError **error) +static void +uca_pco_camera_stop_recording(UcaCamera *camera, GError **error) { g_return_if_fail(UCA_IS_PCO_CAMERA(camera)); UcaPcoCameraPrivate *priv = UCA_PCO_CAMERA_GET_PRIVATE(camera); @@ -467,7 +496,8 @@ static void uca_pco_camera_stop_recording(UcaCamera *camera, GError **error) g_warning(" Unable to unblock all\n"); } -static void uca_pco_camera_start_readout(UcaCamera *camera, GError **error) +static void +uca_pco_camera_start_readout(UcaCamera *camera, GError **error) { g_return_if_fail(UCA_IS_PCO_CAMERA(camera)); UcaPcoCameraPrivate *priv = UCA_PCO_CAMERA_GET_PRIVATE(camera); @@ -486,7 +516,8 @@ static void uca_pco_camera_start_readout(UcaCamera *camera, GError **error) priv->current_image = 1; } -static void uca_pco_camera_trigger(UcaCamera *camera, GError **error) +static void +uca_pco_camera_trigger(UcaCamera *camera, GError **error) { g_return_if_fail(UCA_IS_PCO_CAMERA(camera)); UcaPcoCameraPrivate *priv = UCA_PCO_CAMERA_GET_PRIVATE(camera); @@ -500,7 +531,8 @@ static void uca_pco_camera_trigger(UcaCamera *camera, GError **error) "Could not trigger frame acquisition"); } -static void uca_pco_camera_grab(UcaCamera *camera, gpointer *data, GError **error) +static void +uca_pco_camera_grab(UcaCamera *camera, gpointer *data, GError **error) { static const gint MAX_TIMEOUT = G_MAXINT; @@ -543,7 +575,8 @@ static void uca_pco_camera_grab(UcaCamera *camera, gpointer *data, GError **erro memcpy((gchar *) *data, (gchar *) frame, priv->frame_width * priv->frame_height * priv->num_bytes); } -static void uca_pco_camera_set_property(GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) +static void +uca_pco_camera_set_property(GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { UcaPcoCameraPrivate *priv = UCA_PCO_CAMERA_GET_PRIVATE(object); @@ -624,6 +657,29 @@ static void uca_pco_camera_set_property(GObject *object, guint property_id, cons } break; + case PROP_FRAMES_PER_SECOND: + { + gdouble n_frames_per_second; + gdouble exposure_time; + gdouble delay; + + /* + * We want to expose n frames in one second, each frame takes + * exposure time + delay time. Thus we have + * + * 1s = n * (t_exp + t_delay) <=> t_exp = 1s/n - t_delay. + */ + delay = get_internal_delay (UCA_PCO_CAMERA (object)); + n_frames_per_second = g_value_get_double (value); + exposure_time = 1.0 / n_frames_per_second - delay; + + if (exposure_time <= 0.0) + g_warning ("Too many frames per second requested."); + else + g_object_set (object, "exposure-time", exposure_time, NULL); + } + break; + case PROP_DELAY_TIME: { const gdouble time = g_value_get_double(value); @@ -787,7 +843,8 @@ static void uca_pco_camera_set_property(GObject *object, guint property_id, cons } } -static void uca_pco_camera_get_property(GObject *object, guint property_id, GValue *value, GParamSpec *pspec) +static void +uca_pco_camera_get_property(GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { UcaPcoCameraPrivate *priv = UCA_PCO_CAMERA_GET_PRIVATE(object); @@ -892,6 +949,17 @@ static void uca_pco_camera_get_property(GObject *object, guint property_id, GVal } break; + case PROP_FRAMES_PER_SECOND: + { + gdouble exposure_time; + gdouble delay; + + delay = get_internal_delay (UCA_PCO_CAMERA (object)); + g_object_get (object, "exposure-time", &exposure_time, NULL); + g_value_set_double (value, 1.0 / (exposure_time + delay)); + } + break; + case PROP_DELAY_TIME: { uint32_t delay_time; @@ -1075,7 +1143,8 @@ static void uca_pco_camera_get_property(GObject *object, guint property_id, GVal } } -static void uca_pco_camera_finalize(GObject *object) +static void +uca_pco_camera_finalize(GObject *object) { UcaPcoCameraPrivate *priv = UCA_PCO_CAMERA_GET_PRIVATE(object); @@ -1103,7 +1172,8 @@ static void uca_pco_camera_finalize(GObject *object) G_OBJECT_CLASS(uca_pco_camera_parent_class)->finalize(object); } -static void uca_pco_camera_class_init(UcaPcoCameraClass *klass) +static void +uca_pco_camera_class_init(UcaPcoCameraClass *klass) { GObjectClass *gobject_class = G_OBJECT_CLASS(klass); gobject_class->set_property = uca_pco_camera_set_property; @@ -1286,7 +1356,8 @@ static void uca_pco_camera_class_init(UcaPcoCameraClass *klass) g_type_class_add_private(klass, sizeof(UcaPcoCameraPrivate)); } -static void uca_pco_camera_init(UcaPcoCamera *self) +static void +uca_pco_camera_init(UcaPcoCamera *self) { self->priv = UCA_PCO_CAMERA_GET_PRIVATE(self); self->priv->fg = NULL; -- cgit v1.2.3 From 0d329da1679e1a3a8639131560ad101d94aace9b Mon Sep 17 00:00:00 2001 From: Matthias Vogelgesang Date: Tue, 9 Oct 2012 15:51:41 +0200 Subject: Set sane default exposure time --- plugins/mock/uca-mock-camera.c | 1 + 1 file changed, 1 insertion(+) (limited to 'plugins') diff --git a/plugins/mock/uca-mock-camera.c b/plugins/mock/uca-mock-camera.c index 7cd4689..7ab1d4a 100644 --- a/plugins/mock/uca-mock-camera.c +++ b/plugins/mock/uca-mock-camera.c @@ -393,6 +393,7 @@ static void uca_mock_camera_init(UcaMockCamera *self) self->priv->frame_rate = self->priv->max_frame_rate = 100000.0f; self->priv->grab_thread = NULL; self->priv->current_frame = 0; + self->priv->exposure_time = 0.05; self->priv->binnings = g_value_array_new(1); GValue val = {0}; -- cgit v1.2.3 From b72daf9dbba95a208a4fb84e5b1c629d64a72c00 Mon Sep 17 00:00:00 2001 From: Matthias Vogelgesang Date: Tue, 9 Oct 2012 16:05:20 +0200 Subject: Fix #151: Rename trigger enum value --- plugins/pco/uca-pco-camera.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'plugins') diff --git a/plugins/pco/uca-pco-camera.c b/plugins/pco/uca-pco-camera.c index 893a480..5415867 100644 --- a/plugins/pco/uca-pco-camera.c +++ b/plugins/pco/uca-pco-camera.c @@ -807,7 +807,7 @@ uca_pco_camera_set_property(GObject *object, guint property_id, const GValue *va case UCA_CAMERA_TRIGGER_AUTO: pco_set_trigger_mode(priv->pco, TRIGGER_MODE_AUTOTRIGGER); break; - case UCA_CAMERA_TRIGGER_INTERNAL: + case UCA_CAMERA_TRIGGER_SOFTWARE: pco_set_trigger_mode(priv->pco, TRIGGER_MODE_SOFTWARETRIGGER); break; case UCA_CAMERA_TRIGGER_EXTERNAL: @@ -1040,7 +1040,7 @@ uca_pco_camera_get_property(GObject *object, guint property_id, GValue *value, G g_value_set_enum(value, UCA_CAMERA_TRIGGER_AUTO); break; case TRIGGER_MODE_SOFTWARETRIGGER: - g_value_set_enum(value, UCA_CAMERA_TRIGGER_INTERNAL); + g_value_set_enum(value, UCA_CAMERA_TRIGGER_SOFTWARE); break; case TRIGGER_MODE_EXTERNALTRIGGER: g_value_set_enum(value, UCA_CAMERA_TRIGGER_EXTERNAL); -- cgit v1.2.3 From 5b0a76d69d631838a08a2678388b55c8dacd6d74 Mon Sep 17 00:00:00 2001 From: Matthias Vogelgesang Date: Wed, 10 Oct 2012 09:28:45 +0200 Subject: More elegant error reporting when libpco fails --- plugins/pco/uca-pco-camera.c | 100 ++++++++++++++++++++++--------------------- 1 file changed, 52 insertions(+), 48 deletions(-) (limited to 'plugins') diff --git a/plugins/pco/uca-pco-camera.c b/plugins/pco/uca-pco-camera.c index 5415867..e20d683 100644 --- a/plugins/pco/uca-pco-camera.c +++ b/plugins/pco/uca-pco-camera.c @@ -380,6 +380,16 @@ setup_fg_callback(UcaCamera *camera) return Fg_registerApcHandler(priv->fg, priv->fg_port, &ctrl, FG_APC_CONTROL_BASIC) == FG_OK; } +static void +check_pco_property_error (guint err, guint property_id) +{ + if (err != PCO_NOERROR) { + g_warning ("Call to libpco failed with error code %x for property `%s'", + err, + pco_properties[property_id]->name); + } +} + static void uca_pco_camera_start_recording(UcaCamera *camera, GError **error) { @@ -579,12 +589,13 @@ static void uca_pco_camera_set_property(GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { UcaPcoCameraPrivate *priv = UCA_PCO_CAMERA_GET_PRIVATE(object); + guint err = PCO_NOERROR; switch (property_id) { case PROP_SENSOR_EXTENDED: { guint16 format = g_value_get_boolean (value) ? SENSORFORMAT_EXTENDED : SENSORFORMAT_STANDARD; - pco_set_sensor_format(priv->pco, format); + err = pco_set_sensor_format(priv->pco, format); } break; @@ -645,14 +656,13 @@ uca_pco_camera_set_property(GObject *object, guint property_id, const GValue *va else { if (suitable_timebase != priv->exposure_timebase) { priv->exposure_timebase = suitable_timebase; - if (pco_set_timebase(priv->pco, priv->delay_timebase, suitable_timebase) != PCO_NOERROR) - g_warning("Cannot set exposure time base"); + err = pco_set_timebase(priv->pco, priv->delay_timebase, suitable_timebase); + break; } gdouble timebase = convert_timebase(suitable_timebase); guint32 timesteps = time / timebase; - if (pco_set_exposure_time(priv->pco, timesteps) != PCO_NOERROR) - g_warning("Cannot set exposure time"); + err = pco_set_exposure_time(priv->pco, timesteps); } } break; @@ -700,8 +710,7 @@ uca_pco_camera_set_property(GObject *object, guint property_id, const GValue *va * can set the 0 seconds in whatever time base that is * currently active. */ - if (pco_set_delay_time(priv->pco, 0) != PCO_NOERROR) - g_warning("Cannot set zero delay time"); + err = pco_set_delay_time(priv->pco, 0); } else g_warning("Cannot set such a small exposure time"); @@ -709,14 +718,12 @@ uca_pco_camera_set_property(GObject *object, guint property_id, const GValue *va else { if (suitable_timebase != priv->delay_timebase) { priv->delay_timebase = suitable_timebase; - if (pco_set_timebase(priv->pco, suitable_timebase, priv->exposure_timebase) != PCO_NOERROR) - g_warning("Cannot set delay time base"); + err = pco_set_timebase(priv->pco, suitable_timebase, priv->exposure_timebase); } gdouble timebase = convert_timebase(suitable_timebase); guint32 timesteps = time / timebase; - if (pco_set_delay_time(priv->pco, timesteps) != PCO_NOERROR) - g_warning("Cannot set delay time"); + err = pco_set_delay_time(priv->pco, timesteps); } } break; @@ -724,8 +731,7 @@ uca_pco_camera_set_property(GObject *object, guint property_id, const GValue *va case PROP_SENSOR_ADCS: { const guint num_adcs = g_value_get_uint(value); - if (pco_set_adc_mode(priv->pco, num_adcs) != PCO_NOERROR) - g_warning("Cannot set the number of ADCs per pixel\n"); + err = pco_set_adc_mode(priv->pco, num_adcs); } break; @@ -742,8 +748,7 @@ uca_pco_camera_set_property(GObject *object, guint property_id, const GValue *va } if (pixel_rate != 0) { - if (pco_set_pixelrate(priv->pco, pixel_rate) != PCO_NOERROR) - g_warning("Cannot set pixel rate"); + err = pco_set_pixelrate(priv->pco, pixel_rate); } else g_warning("%i Hz is not possible. Please check the \"sensor-pixelrates\" property", desired_pixel_rate); @@ -754,17 +759,17 @@ uca_pco_camera_set_property(GObject *object, guint property_id, const GValue *va if (!pco_is_double_image_mode_available(priv->pco)) g_warning("Double image mode is not available on this pco model"); else - pco_set_double_image_mode(priv->pco, g_value_get_boolean(value)); + err = pco_set_double_image_mode(priv->pco, g_value_get_boolean(value)); break; case PROP_OFFSET_MODE: - pco_set_offset_mode(priv->pco, g_value_get_boolean(value)); + err = pco_set_offset_mode(priv->pco, g_value_get_boolean(value)); break; case PROP_COOLING_POINT: { int16_t temperature = (int16_t) g_value_get_int(value); - pco_set_cooling_temperature(priv->pco, temperature); + err = pco_set_cooling_temperature(priv->pco, temperature); } break; @@ -774,9 +779,9 @@ uca_pco_camera_set_property(GObject *object, guint property_id, const GValue *va UcaPcoCameraRecordMode mode = (UcaPcoCameraRecordMode) g_value_get_enum(value); if (mode == UCA_PCO_CAMERA_RECORD_MODE_SEQUENCE) - pco_set_record_mode(priv->pco, RECORDER_SUBMODE_SEQUENCE); + err = pco_set_record_mode(priv->pco, RECORDER_SUBMODE_SEQUENCE); else if (mode == UCA_PCO_CAMERA_RECORD_MODE_RING_BUFFER) - pco_set_record_mode(priv->pco, RECORDER_SUBMODE_RINGBUFFER); + err = pco_set_record_mode(priv->pco, RECORDER_SUBMODE_RINGBUFFER); else g_warning("Unknown record mode"); } @@ -785,7 +790,6 @@ uca_pco_camera_set_property(GObject *object, guint property_id, const GValue *va case PROP_ACQUIRE_MODE: { UcaPcoCameraAcquireMode mode = (UcaPcoCameraAcquireMode) g_value_get_enum(value); - unsigned int err = PCO_NOERROR; if (mode == UCA_PCO_CAMERA_ACQUIRE_MODE_AUTO) err = pco_set_acquire_mode(priv->pco, ACQUIRE_MODE_AUTO); @@ -793,9 +797,6 @@ uca_pco_camera_set_property(GObject *object, guint property_id, const GValue *va err = pco_set_acquire_mode(priv->pco, ACQUIRE_MODE_EXTERNAL); else g_warning("Unknown acquire mode"); - - if (err != PCO_NOERROR) - g_warning("Cannot set acquire mode"); } break; @@ -805,13 +806,13 @@ uca_pco_camera_set_property(GObject *object, guint property_id, const GValue *va switch (trigger_mode) { case UCA_CAMERA_TRIGGER_AUTO: - pco_set_trigger_mode(priv->pco, TRIGGER_MODE_AUTOTRIGGER); + err = pco_set_trigger_mode(priv->pco, TRIGGER_MODE_AUTOTRIGGER); break; case UCA_CAMERA_TRIGGER_SOFTWARE: - pco_set_trigger_mode(priv->pco, TRIGGER_MODE_SOFTWARETRIGGER); + err = pco_set_trigger_mode(priv->pco, TRIGGER_MODE_SOFTWARETRIGGER); break; case UCA_CAMERA_TRIGGER_EXTERNAL: - pco_set_trigger_mode(priv->pco, TRIGGER_MODE_EXTERNALTRIGGER); + err = pco_set_trigger_mode(priv->pco, TRIGGER_MODE_EXTERNALTRIGGER); break; } } @@ -820,7 +821,7 @@ uca_pco_camera_set_property(GObject *object, guint property_id, const GValue *va case PROP_NOISE_FILTER: { guint16 filter_mode = g_value_get_boolean(value) ? NOISE_FILTER_MODE_ON : NOISE_FILTER_MODE_OFF; - pco_set_noise_filter_mode(priv->pco, filter_mode); + err = pco_set_noise_filter_mode(priv->pco, filter_mode); } break; @@ -833,7 +834,7 @@ uca_pco_camera_set_property(GObject *object, guint property_id, const GValue *va TIMESTAMP_MODE_ASCII, }; - pco_set_timestamp_mode(priv->pco, table[g_value_get_flags(value)]); + err = pco_set_timestamp_mode(priv->pco, table[g_value_get_flags(value)]); } break; @@ -841,18 +842,21 @@ uca_pco_camera_set_property(GObject *object, guint property_id, const GValue *va G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); return; } + + check_pco_property_error (err, property_id); } static void uca_pco_camera_get_property(GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { UcaPcoCameraPrivate *priv = UCA_PCO_CAMERA_GET_PRIVATE(object); + guint err = PCO_NOERROR; switch (property_id) { case PROP_SENSOR_EXTENDED: { guint16 format; - pco_get_sensor_format(priv->pco, &format); + err = pco_get_sensor_format(priv->pco, &format); g_value_set_boolean(value, format == SENSORFORMAT_EXTENDED); } break; @@ -900,7 +904,7 @@ uca_pco_camera_get_property(GObject *object, guint property_id, GValue *value, G case PROP_SENSOR_TEMPERATURE: { gint32 ccd, camera, power; - pco_get_temperature(priv->pco, &ccd, &camera, &power); + err = pco_get_temperature(priv->pco, &ccd, &camera, &power); g_value_set_double(value, ccd / 10.0); } break; @@ -912,8 +916,7 @@ uca_pco_camera_get_property(GObject *object, guint property_id, GValue *value, G * ADCs in use. */ pco_adc_mode mode; - if (pco_get_adc_mode(priv->pco, &mode) != PCO_NOERROR) - g_warning("Cannot read number of ADCs per pixel"); + err = pco_get_adc_mode(priv->pco, &mode); g_value_set_uint(value, mode); } break; @@ -932,7 +935,7 @@ uca_pco_camera_get_property(GObject *object, guint property_id, GValue *value, G case PROP_SENSOR_PIXELRATE: { guint32 pixelrate; - pco_get_pixelrate(priv->pco, &pixelrate); + err = pco_get_pixelrate(priv->pco, &pixelrate); g_value_set_uint(value, pixelrate); } break; @@ -940,7 +943,7 @@ uca_pco_camera_get_property(GObject *object, guint property_id, GValue *value, G case PROP_EXPOSURE_TIME: { uint32_t exposure_time; - pco_get_exposure_time(priv->pco, &exposure_time); + err = pco_get_exposure_time(priv->pco, &exposure_time); if (priv->exposure_timebase == TIMEBASE_INVALID) read_timebase(priv); @@ -963,7 +966,7 @@ uca_pco_camera_get_property(GObject *object, guint property_id, GValue *value, G case PROP_DELAY_TIME: { uint32_t delay_time; - pco_get_delay_time(priv->pco, &delay_time); + err = pco_get_delay_time(priv->pco, &delay_time); if (priv->delay_timebase == TIMEBASE_INVALID) read_timebase(priv); @@ -981,7 +984,7 @@ uca_pco_camera_get_property(GObject *object, guint property_id, GValue *value, G g_warning("Double image mode is not available on this pco model"); else { bool on; - pco_get_double_image_mode(priv->pco, &on); + err = pco_get_double_image_mode(priv->pco, &on); g_value_set_boolean(value, on); } break; @@ -989,7 +992,7 @@ uca_pco_camera_get_property(GObject *object, guint property_id, GValue *value, G case PROP_OFFSET_MODE: { bool on; - pco_get_offset_mode(priv->pco, &on); + err = pco_get_offset_mode(priv->pco, &on); g_value_set_boolean(value, on); } break; @@ -1005,7 +1008,7 @@ uca_pco_camera_get_property(GObject *object, guint property_id, GValue *value, G case PROP_RECORD_MODE: { guint16 mode; - pco_get_record_mode(priv->pco, &mode); + err = pco_get_record_mode(priv->pco, &mode); if (mode == RECORDER_SUBMODE_SEQUENCE) g_value_set_enum(value, UCA_PCO_CAMERA_RECORD_MODE_SEQUENCE); @@ -1019,7 +1022,7 @@ uca_pco_camera_get_property(GObject *object, guint property_id, GValue *value, G case PROP_ACQUIRE_MODE: { guint16 mode; - pco_get_acquire_mode(priv->pco, &mode); + err = pco_get_acquire_mode(priv->pco, &mode); if (mode == ACQUIRE_MODE_AUTO) g_value_set_enum(value, UCA_PCO_CAMERA_ACQUIRE_MODE_AUTO); @@ -1033,7 +1036,7 @@ uca_pco_camera_get_property(GObject *object, guint property_id, GValue *value, G case PROP_TRIGGER_MODE: { guint16 mode; - pco_get_trigger_mode(priv->pco, &mode); + err = pco_get_trigger_mode(priv->pco, &mode); switch (mode) { case TRIGGER_MODE_AUTOTRIGGER: @@ -1078,8 +1081,8 @@ uca_pco_camera_get_property(GObject *object, guint property_id, GValue *value, G case PROP_NAME: { gchar *name = NULL; - pco_get_name(priv->pco, &name); - g_value_set_string(value, name); + err = pco_get_name (priv->pco, &name); + g_value_set_string (value, name); g_free(name); } break; @@ -1087,8 +1090,7 @@ uca_pco_camera_get_property(GObject *object, guint property_id, GValue *value, G case PROP_COOLING_POINT: { int16_t temperature; - if (pco_get_cooling_temperature(priv->pco, &temperature) != PCO_NOERROR) - g_warning("Cannot read cooling temperature\n"); + err = pco_get_cooling_temperature(priv->pco, &temperature); g_value_set_int(value, temperature); } break; @@ -1117,7 +1119,7 @@ uca_pco_camera_get_property(GObject *object, guint property_id, GValue *value, G case PROP_NOISE_FILTER: { guint16 mode; - pco_get_noise_filter_mode(priv->pco, &mode); + err = pco_get_noise_filter_mode(priv->pco, &mode); g_value_set_boolean(value, mode != NOISE_FILTER_MODE_OFF); } break; @@ -1132,15 +1134,17 @@ uca_pco_camera_get_property(GObject *object, guint property_id, GValue *value, G UCA_PCO_CAMERA_TIMESTAMP_ASCII }; - pco_get_timestamp_mode(priv->pco, &mode); + err = pco_get_timestamp_mode (priv->pco, &mode); g_value_set_enum (value, table[mode]); } break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); - break; + return; } + + check_pco_property_error (err, property_id); } static void -- cgit v1.2.3 From a0e94969bbee79a6342f1608acffda0dc2f235bc Mon Sep 17 00:00:00 2001 From: Matthias Vogelgesang Date: Wed, 10 Oct 2012 09:31:24 +0200 Subject: Use correct pixel rate property name --- plugins/pco/uca-pco-camera.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'plugins') diff --git a/plugins/pco/uca-pco-camera.c b/plugins/pco/uca-pco-camera.c index e20d683..791d154 100644 --- a/plugins/pco/uca-pco-camera.c +++ b/plugins/pco/uca-pco-camera.c @@ -331,7 +331,7 @@ get_internal_delay (UcaPcoCamera *camera) { if (camera->priv->camera_description->camera_type == CAMERATYPE_PCO_DIMAX_STD) { gdouble sensor_rate; - g_object_get (camera, "sensor-rate", &sensor_rate, NULL); + g_object_get (camera, "sensor-pixelrate", &sensor_rate, NULL); if (sensor_rate == 55000000.0) return 0.000079; -- cgit v1.2.3 From fce1b3762b2a3b3035b9a3c2a6be038bde10aa1c Mon Sep 17 00:00:00 2001 From: Matthias Vogelgesang Date: Wed, 10 Oct 2012 09:49:49 +0200 Subject: Set timestamp as enum not flag --- plugins/pco/uca-pco-camera.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'plugins') diff --git a/plugins/pco/uca-pco-camera.c b/plugins/pco/uca-pco-camera.c index 791d154..725ffbf 100644 --- a/plugins/pco/uca-pco-camera.c +++ b/plugins/pco/uca-pco-camera.c @@ -834,7 +834,7 @@ uca_pco_camera_set_property(GObject *object, guint property_id, const GValue *va TIMESTAMP_MODE_ASCII, }; - err = pco_set_timestamp_mode(priv->pco, table[g_value_get_flags(value)]); + err = pco_set_timestamp_mode(priv->pco, table[g_value_get_enum(value)]); } break; -- cgit v1.2.3 From 95a22bf2f02ad11c2602df5ac5ffd04fee93588c Mon Sep 17 00:00:00 2001 From: Matthias Vogelgesang Date: Wed, 10 Oct 2012 17:44:34 +0200 Subject: Implement experimental histogram view --- plugins/mock/uca-mock-camera.c | 4 ---- plugins/pf/uca-pf-camera.c | 1 + 2 files changed, 1 insertion(+), 4 deletions(-) (limited to 'plugins') diff --git a/plugins/mock/uca-mock-camera.c b/plugins/mock/uca-mock-camera.c index 7ab1d4a..65c4240 100644 --- a/plugins/mock/uca-mock-camera.c +++ b/plugins/mock/uca-mock-camera.c @@ -37,7 +37,6 @@ static const gint mock_overrideables[] = { PROP_SENSOR_HORIZONTAL_BINNINGS, PROP_SENSOR_VERTICAL_BINNING, PROP_SENSOR_VERTICAL_BINNINGS, - PROP_TRIGGER_MODE, PROP_EXPOSURE_TIME, PROP_ROI_X, PROP_ROI_Y, @@ -301,9 +300,6 @@ static void uca_mock_camera_get_property(GObject *object, guint property_id, GVa case PROP_EXPOSURE_TIME: g_value_set_double(value, priv->exposure_time); break; - case PROP_TRIGGER_MODE: - g_value_set_enum(value, UCA_CAMERA_TRIGGER_AUTO); - break; case PROP_ROI_X: g_value_set_uint(value, priv->roi_x); break; diff --git a/plugins/pf/uca-pf-camera.c b/plugins/pf/uca-pf-camera.c index 35b5edd..473ffd3 100644 --- a/plugins/pf/uca-pf-camera.c +++ b/plugins/pf/uca-pf-camera.c @@ -234,6 +234,7 @@ static void uca_pf_camera_get_property(GObject *object, guint property_id, GValu g_value_set_boolean(value, FALSE); break; case PROP_EXPOSURE_TIME: + g_value_set_double(value, 1. / 488.0); break; case PROP_ROI_X: g_value_set_uint(value, 0); -- cgit v1.2.3 From ef7ff789e9c15f4f4b8c65585de7e7fa4f9c9438 Mon Sep 17 00:00:00 2001 From: Matthias Vogelgesang Date: Fri, 12 Oct 2012 14:47:07 +0200 Subject: Add ring buffer recording for assessment --- plugins/mock/uca-mock-camera.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'plugins') diff --git a/plugins/mock/uca-mock-camera.c b/plugins/mock/uca-mock-camera.c index 65c4240..38caf0d 100644 --- a/plugins/mock/uca-mock-camera.c +++ b/plugins/mock/uca-mock-camera.c @@ -146,9 +146,10 @@ static void print_number(gchar *buffer, guint number, guint x, guint y, guint wi static void print_current_frame(UcaMockCameraPrivate *priv, gchar *buffer) { guint number = priv->current_frame; - guint divisor = 100000000; + guint divisor = 10000000; int x = 10; - while (divisor > 1) { + + while (divisor > 0) { print_number(buffer, number / divisor, x, 10, priv->width); number = number % divisor; divisor = divisor / 10; -- cgit v1.2.3 From de2e8e3191eae37b91f672a03e028a35c8863c9d Mon Sep 17 00:00:00 2001 From: Matthias Vogelgesang Date: Tue, 16 Oct 2012 12:40:18 +0200 Subject: Add temperature unit and descriptions for pco --- plugins/mock/uca-mock-camera.c | 2 ++ plugins/pco/uca-pco-camera.c | 14 ++++++++++++++ 2 files changed, 16 insertions(+) (limited to 'plugins') diff --git a/plugins/mock/uca-mock-camera.c b/plugins/mock/uca-mock-camera.c index 38caf0d..bf3124e 100644 --- a/plugins/mock/uca-mock-camera.c +++ b/plugins/mock/uca-mock-camera.c @@ -397,6 +397,8 @@ static void uca_mock_camera_init(UcaMockCamera *self) g_value_init(&val, G_TYPE_UINT); g_value_set_uint(&val, 1); g_value_array_append(self->priv->binnings, &val); + + uca_camera_register_unit (UCA_CAMERA (self), "frame-rate", UCA_UNIT_COUNT); } G_MODULE_EXPORT UcaCamera * diff --git a/plugins/pco/uca-pco-camera.c b/plugins/pco/uca-pco-camera.c index 725ffbf..92f814e 100644 --- a/plugins/pco/uca-pco-camera.c +++ b/plugins/pco/uca-pco-camera.c @@ -1363,6 +1363,8 @@ uca_pco_camera_class_init(UcaPcoCameraClass *klass) static void uca_pco_camera_init(UcaPcoCamera *self) { + UcaCamera *camera; + self->priv = UCA_PCO_CAMERA_GET_PRIVATE(self); self->priv->fg = NULL; self->priv->fg_mem = NULL; @@ -1376,6 +1378,18 @@ uca_pco_camera_init(UcaPcoCamera *self) self->priv->delay_timebase = TIMEBASE_INVALID; self->priv->exposure_timebase = TIMEBASE_INVALID; + + camera = UCA_CAMERA (self); + uca_camera_register_unit (camera, "sensor-width-extended", UCA_UNIT_PIXEL); + uca_camera_register_unit (camera, "sensor-height-extended", UCA_UNIT_PIXEL); + uca_camera_register_unit (camera, "temperature", UCA_UNIT_DEGREE_CELSIUS); + uca_camera_register_unit (camera, "cooling-point", UCA_UNIT_DEGREE_CELSIUS); + uca_camera_register_unit (camera, "cooling-point-min", UCA_UNIT_DEGREE_CELSIUS); + uca_camera_register_unit (camera, "cooling-point-max", UCA_UNIT_DEGREE_CELSIUS); + uca_camera_register_unit (camera, "cooling-point-default", UCA_UNIT_DEGREE_CELSIUS); + uca_camera_register_unit (camera, "sensor-adcs", UCA_UNIT_COUNT); + uca_camera_register_unit (camera, "sensor-max-adcs", UCA_UNIT_COUNT); + uca_camera_register_unit (camera, "delay-time", UCA_UNIT_SECOND); } G_MODULE_EXPORT UcaCamera * -- cgit v1.2.3 From a1ab005916ba3aa50923294c5be3da0ded16fbc0 Mon Sep 17 00:00:00 2001 From: Matthias Vogelgesang Date: Thu, 18 Oct 2012 10:56:30 +0200 Subject: Add download button and make dimax work --- plugins/pco/uca-pco-camera.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'plugins') diff --git a/plugins/pco/uca-pco-camera.c b/plugins/pco/uca-pco-camera.c index 92f814e..d5f5593 100644 --- a/plugins/pco/uca-pco-camera.c +++ b/plugins/pco/uca-pco-camera.c @@ -554,7 +554,8 @@ uca_pco_camera_grab(UcaCamera *camera, gpointer *data, GError **error) if (is_readout) { if (priv->current_image == priv->num_recorded_images) { - *data = NULL; + g_set_error (error, UCA_CAMERA_ERROR, UCA_CAMERA_ERROR_END_OF_STREAM, + "End of data stream"); return; } -- cgit v1.2.3 From 983005dfbc3b07093145c0b964063e334b928d48 Mon Sep 17 00:00:00 2001 From: Matthias Vogelgesang Date: Thu, 18 Oct 2012 12:44:40 +0200 Subject: Fix download of in-camera frames --- plugins/pco/uca-pco-camera.c | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) (limited to 'plugins') diff --git a/plugins/pco/uca-pco-camera.c b/plugins/pco/uca-pco-camera.c index d5f5593..03a1a17 100644 --- a/plugins/pco/uca-pco-camera.c +++ b/plugins/pco/uca-pco-camera.c @@ -385,7 +385,7 @@ check_pco_property_error (guint err, guint property_id) { if (err != PCO_NOERROR) { g_warning ("Call to libpco failed with error code %x for property `%s'", - err, + err, pco_properties[property_id]->name); } } @@ -523,9 +523,27 @@ uca_pco_camera_start_readout(UcaCamera *camera, GError **error) err = pco_get_num_images(priv->pco, priv->active_segment, &priv->num_recorded_images); HANDLE_PCO_ERROR(err); + err = Fg_AcquireEx(priv->fg, priv->fg_port, GRAB_INFINITE, ACQ_STANDARD, priv->fg_mem); + FG_SET_ERROR(err, priv->fg, UCA_PCO_CAMERA_ERROR_FG_ACQUISITION); + + priv->last_frame = 0; priv->current_image = 1; } +static void +uca_pco_camera_stop_readout(UcaCamera *camera, GError **error) +{ + g_return_if_fail(UCA_IS_PCO_CAMERA(camera)); + UcaPcoCameraPrivate *priv = UCA_PCO_CAMERA_GET_PRIVATE(camera); + + guint err = Fg_stopAcquireEx(priv->fg, priv->fg_port, priv->fg_mem, STOP_SYNC); + FG_SET_ERROR(err, priv->fg, UCA_PCO_CAMERA_ERROR_FG_ACQUISITION); + + err = Fg_setStatusEx(priv->fg, FG_UNBLOCK_ALL, 0, priv->fg_port, priv->fg_mem); + if (err == FG_INVALID_PARAMETER) + g_warning(" Unable to unblock all\n"); +} + static void uca_pco_camera_trigger(UcaCamera *camera, GError **error) { @@ -568,7 +586,7 @@ uca_pco_camera_grab(UcaCamera *camera, gpointer *data, GError **error) } pco_request_image(priv->pco); - priv->last_frame = Fg_getLastPicNumberBlockingEx(priv->fg, priv->last_frame+1, priv->fg_port, MAX_TIMEOUT, priv->fg_mem); + priv->last_frame = Fg_getLastPicNumberBlockingEx(priv->fg, priv->last_frame + 1, priv->fg_port, MAX_TIMEOUT, priv->fg_mem); if (priv->last_frame <= 0) { guint err = FG_OK + 1; @@ -1189,6 +1207,7 @@ uca_pco_camera_class_init(UcaPcoCameraClass *klass) camera_class->start_recording = uca_pco_camera_start_recording; camera_class->stop_recording = uca_pco_camera_stop_recording; camera_class->start_readout = uca_pco_camera_start_readout; + camera_class->stop_readout = uca_pco_camera_stop_readout; camera_class->trigger = uca_pco_camera_trigger; camera_class->grab = uca_pco_camera_grab; @@ -1383,7 +1402,7 @@ uca_pco_camera_init(UcaPcoCamera *self) camera = UCA_CAMERA (self); uca_camera_register_unit (camera, "sensor-width-extended", UCA_UNIT_PIXEL); uca_camera_register_unit (camera, "sensor-height-extended", UCA_UNIT_PIXEL); - uca_camera_register_unit (camera, "temperature", UCA_UNIT_DEGREE_CELSIUS); + uca_camera_register_unit (camera, "sensor-temperature", UCA_UNIT_DEGREE_CELSIUS); uca_camera_register_unit (camera, "cooling-point", UCA_UNIT_DEGREE_CELSIUS); uca_camera_register_unit (camera, "cooling-point-min", UCA_UNIT_DEGREE_CELSIUS); uca_camera_register_unit (camera, "cooling-point-max", UCA_UNIT_DEGREE_CELSIUS); -- cgit v1.2.3 From 184fc22ce23f8ab7c8127b5ac0657fc20ddea924 Mon Sep 17 00:00:00 2001 From: Matthias Vogelgesang Date: Thu, 18 Oct 2012 16:07:00 +0200 Subject: Add "recorded-frames" property --- plugins/pco/uca-pco-camera.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'plugins') diff --git a/plugins/pco/uca-pco-camera.c b/plugins/pco/uca-pco-camera.c index 03a1a17..d34e0f4 100644 --- a/plugins/pco/uca-pco-camera.c +++ b/plugins/pco/uca-pco-camera.c @@ -139,6 +139,7 @@ static gint base_overrideables[] = { PROP_ROI_HEIGHT_MULTIPLIER, PROP_HAS_STREAMING, PROP_HAS_CAMRAM_RECORDING, + PROP_RECORDED_FRAMES, 0 }; @@ -504,6 +505,9 @@ uca_pco_camera_stop_recording(UcaCamera *camera, GError **error) err = Fg_setStatusEx(priv->fg, FG_UNBLOCK_ALL, 0, priv->fg_port, priv->fg_mem); if (err == FG_INVALID_PARAMETER) g_warning(" Unable to unblock all\n"); + + err = pco_get_num_images(priv->pco, priv->active_segment, &priv->num_recorded_images); + HANDLE_PCO_ERROR(err); } static void @@ -1024,6 +1028,10 @@ uca_pco_camera_get_property(GObject *object, guint property_id, GValue *value, G g_value_set_boolean(value, priv->camera_description->has_camram); break; + case PROP_RECORDED_FRAMES: + g_value_set_uint(value, priv->num_recorded_images); + break; + case PROP_RECORD_MODE: { guint16 mode; @@ -1440,6 +1448,7 @@ uca_camera_impl_new (GError **error) priv->roi_y = roi[1] - 1; priv->roi_width = roi[2] - roi[0] + 1; priv->roi_height = roi[3] - roi[1] + 1; + priv->num_recorded_images = 0; guint16 camera_type, camera_subtype; pco_get_camera_type(priv->pco, &camera_type, &camera_subtype); -- cgit v1.2.3 From a7a48c55df8dc3e34a2ce50b18b70c0cd101766d Mon Sep 17 00:00:00 2001 From: Matthias Vogelgesang Date: Thu, 18 Oct 2012 16:27:45 +0200 Subject: Show download progress --- plugins/pco/uca-pco-camera.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'plugins') diff --git a/plugins/pco/uca-pco-camera.c b/plugins/pco/uca-pco-camera.c index d34e0f4..5d08acf 100644 --- a/plugins/pco/uca-pco-camera.c +++ b/plugins/pco/uca-pco-camera.c @@ -506,7 +506,11 @@ uca_pco_camera_stop_recording(UcaCamera *camera, GError **error) if (err == FG_INVALID_PARAMETER) g_warning(" Unable to unblock all\n"); + err = pco_get_active_segment(priv->pco, &priv->active_segment); + HANDLE_PCO_ERROR(err); + err = pco_get_num_images(priv->pco, priv->active_segment, &priv->num_recorded_images); + g_print ("images: %i\n", priv->num_recorded_images); HANDLE_PCO_ERROR(err); } -- cgit v1.2.3 From f9c8476e1ce1a5089cd5fc7f4a40329e0c5a70b7 Mon Sep 17 00:00:00 2001 From: Matthias Vogelgesang Date: Fri, 19 Oct 2012 14:26:04 +0200 Subject: Don't soft trigger on external signal --- plugins/ufo/uca-ufo-camera.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) (limited to 'plugins') diff --git a/plugins/ufo/uca-ufo-camera.c b/plugins/ufo/uca-ufo-camera.c index 7542fdf..0b040c6 100644 --- a/plugins/ufo/uca-ufo-camera.c +++ b/plugins/ufo/uca-ufo-camera.c @@ -79,7 +79,6 @@ static gint base_overrideables[] = { PROP_ROI_HEIGHT_MULTIPLIER, PROP_HAS_STREAMING, PROP_HAS_CAMRAM_RECORDING, - PROP_TRIGGER_MODE, 0, }; @@ -101,6 +100,7 @@ struct _UcaUfoCameraPrivate { FPGA_48MHZ = 0, FPGA_40MHZ } frequency; + UcaCameraTrigger trigger; }; static void @@ -244,6 +244,7 @@ static void uca_ufo_camera_start_recording(UcaCamera *camera, GError **error) g_object_get(G_OBJECT(camera), "transfer-asynchronously", &transfer_async, "exposure-time", &exposure_time, + "trigger-mode", &priv->trigger, NULL); priv->timeout = ((pcilib_timeout_t) (exposure_time * 1000 + 50.0) * 1000); @@ -265,8 +266,11 @@ static void uca_ufo_camera_stop_recording(UcaCamera *camera, GError **error) static void uca_ufo_camera_start_readout(UcaCamera *camera, GError **error) { g_return_if_fail(UCA_IS_UFO_CAMERA(camera)); - g_set_error(error, UCA_CAMERA_ERROR, UCA_CAMERA_ERROR_NOT_IMPLEMENTED, - "Ufo camera does not support recording to internal memory"); +} + +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) @@ -279,8 +283,10 @@ static void uca_ufo_camera_grab(UcaCamera *camera, gpointer *data, GError **erro const gsize size = SENSOR_WIDTH * SENSOR_HEIGHT * sizeof(guint16); - err = pcilib_trigger(priv->handle, PCILIB_EVENT0, 0, NULL); - PCILIB_SET_ERROR(err, UCA_UFO_CAMERA_ERROR_TRIGGER); + 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); @@ -429,8 +435,6 @@ 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: - break; default: { RegisterInfo *reg_info = g_hash_table_lookup (ufo_property_table, GINT_TO_POINTER (property_id)); @@ -462,6 +466,7 @@ static void uca_ufo_camera_class_init(UcaUfoCameraClass *klass) camera_class->start_recording = uca_ufo_camera_start_recording; camera_class->stop_recording = uca_ufo_camera_stop_recording; 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; for (guint i = 0; base_overrideables[i] != 0; i++) -- cgit v1.2.3 From e4deaf621246d6e97950d56e244345c8e13a6044 Mon Sep 17 00:00:00 2001 From: Matthias Vogelgesang Date: Fri, 19 Oct 2012 14:29:29 +0200 Subject: Store trigger mode --- plugins/ufo/uca-ufo-camera.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'plugins') diff --git a/plugins/ufo/uca-ufo-camera.c b/plugins/ufo/uca-ufo-camera.c index 0b040c6..2b289a5 100644 --- a/plugins/ufo/uca-ufo-camera.c +++ b/plugins/ufo/uca-ufo-camera.c @@ -79,6 +79,7 @@ static gint base_overrideables[] = { PROP_ROI_HEIGHT_MULTIPLIER, PROP_HAS_STREAMING, PROP_HAS_CAMRAM_RECORDING, + PROP_TRIGGER_MODE, 0, }; @@ -338,6 +339,10 @@ 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)); @@ -435,6 +440,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)); -- cgit v1.2.3 From 9e45cb5ffdea8592077ee42223caecda492326cd Mon Sep 17 00:00:00 2001 From: Matthias Vogelgesang Date: Fri, 19 Oct 2012 15:40:10 +0200 Subject: Always return correct number of recorded frames --- plugins/pco/uca-pco-camera.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) (limited to 'plugins') diff --git a/plugins/pco/uca-pco-camera.c b/plugins/pco/uca-pco-camera.c index 5d08acf..2a5d034 100644 --- a/plugins/pco/uca-pco-camera.c +++ b/plugins/pco/uca-pco-camera.c @@ -506,11 +506,6 @@ uca_pco_camera_stop_recording(UcaCamera *camera, GError **error) if (err == FG_INVALID_PARAMETER) g_warning(" Unable to unblock all\n"); - err = pco_get_active_segment(priv->pco, &priv->active_segment); - HANDLE_PCO_ERROR(err); - - err = pco_get_num_images(priv->pco, priv->active_segment, &priv->num_recorded_images); - g_print ("images: %i\n", priv->num_recorded_images); HANDLE_PCO_ERROR(err); } @@ -525,9 +520,6 @@ uca_pco_camera_start_readout(UcaCamera *camera, GError **error) * edge. */ - guint err = pco_get_active_segment(priv->pco, &priv->active_segment); - HANDLE_PCO_ERROR(err); - err = pco_get_num_images(priv->pco, priv->active_segment, &priv->num_recorded_images); HANDLE_PCO_ERROR(err); @@ -1033,6 +1025,7 @@ uca_pco_camera_get_property(GObject *object, guint property_id, GValue *value, G break; case PROP_RECORDED_FRAMES: + err = pco_get_num_images (priv->pco, priv->active_segment, &priv->num_recorded_images); g_value_set_uint(value, priv->num_recorded_images); break; @@ -1439,6 +1432,7 @@ uca_camera_impl_new (GError **error) UcaPcoCameraPrivate *priv = UCA_PCO_CAMERA_GET_PRIVATE(camera); priv->pco = pco; + pco_get_active_segment(priv->pco, &priv->active_segment); pco_get_resolution(priv->pco, &priv->width, &priv->height, &priv->width_ex, &priv->height_ex); pco_get_binning(priv->pco, &priv->binning_h, &priv->binning_v); pco_set_storage_mode(pco, STORAGE_MODE_RECORDER); -- cgit v1.2.3 From 6f12303cf4c4130d544c30f8ad5e2445a1fa3e61 Mon Sep 17 00:00:00 2001 From: Matthias Vogelgesang Date: Fri, 19 Oct 2012 15:41:02 +0200 Subject: Fix compile error --- plugins/pco/uca-pco-camera.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'plugins') diff --git a/plugins/pco/uca-pco-camera.c b/plugins/pco/uca-pco-camera.c index 2a5d034..bb7bd5a 100644 --- a/plugins/pco/uca-pco-camera.c +++ b/plugins/pco/uca-pco-camera.c @@ -512,6 +512,8 @@ uca_pco_camera_stop_recording(UcaCamera *camera, GError **error) static void uca_pco_camera_start_readout(UcaCamera *camera, GError **error) { + guint err; + g_return_if_fail(UCA_IS_PCO_CAMERA(camera)); UcaPcoCameraPrivate *priv = UCA_PCO_CAMERA_GET_PRIVATE(camera); -- cgit v1.2.3