diff options
-rw-r--r-- | NEWS | 15 | ||||
-rw-r--r-- | README | 16 | ||||
-rw-r--r-- | bin/gui/control.c | 5 | ||||
-rw-r--r-- | bin/gui/control.glade | 109 | ||||
-rw-r--r-- | docs/style.css | 4 | ||||
-rw-r--r-- | plugins/CMakeLists.txt | 1 | ||||
-rw-r--r-- | plugins/pco/uca-pco-camera.c | 199 | ||||
-rw-r--r-- | plugins/xkit/CMakeLists.txt | 32 | ||||
-rw-r--r-- | plugins/xkit/uca-xkit-camera.cc | 357 | ||||
-rw-r--r-- | plugins/xkit/uca-xkit-camera.h | 76 |
10 files changed, 556 insertions, 258 deletions
@@ -1,6 +1,21 @@ Changelog ========= +Changes in libuca 1.4 +--------------------- + +### X-KIT detector plugin + +This release adds experimental support for X-KIT, a Medipix2 and timepix +detector system developed at IPE/KIT. Note, that this requires a pre-built +shared library and header files by the chip vendor. + +### Minor changes + +- `uca_camera_grab` does not set an error when the stream finished in + readout mode. Now, only `FALSE` is returned. + + Changes in libuca 1.3 --------------------- @@ -1,12 +1,12 @@ - -General Information +General information =================== -This directory contains libuca version 0.6. libuca (short for Unified Camera -access) is a library to access two-dimensional pixel detectors most commonly -called cameras. It gives the user a general interface to a variety of different -cameras and camera types. It is used to configure them via a property based -interface and acquire images. +This directory contains libuca (short for Unified Camera access), a GLib-based +library to access two-dimensional pixel detectors. It gives the user a general +interface to a variety of different cameras and camera types. You can read more +about it in our manual located at: + + http://ufo.kit.edu/extra/libuca/manual/manual.html Details of the latest version can be found on the UFO project page under: @@ -18,7 +18,7 @@ For changes see the file called NEWS. Installation ============ -Please see the file called INSTALL. +Please see the file called INSTALL or refer to the manual. Licensing diff --git a/bin/gui/control.c b/bin/gui/control.c index 069b825..b161e9b 100644 --- a/bin/gui/control.c +++ b/bin/gui/control.c @@ -53,7 +53,6 @@ typedef struct { GtkDialog *download_dialog; GtkProgressBar *download_progressbar; - GtkWidget *download_close_button; GtkAdjustment *download_adjustment; GtkAdjustment *count; GtkAdjustment *hadjustment, *vadjustment; @@ -636,7 +635,6 @@ download_frames (ThreadData *data) g_object_get (data->camera, "recorded-frames", &n_frames, NULL); gdk_threads_enter (); - gtk_widget_set_sensitive (data->download_close_button, FALSE); gtk_adjustment_set_upper (data->download_adjustment, n_frames); gdk_threads_leave (); @@ -676,7 +674,7 @@ download_frames (ThreadData *data) g_printerr ("Failed to stop reading out of camera memory: %s\n", error->message); gdk_threads_enter (); - gtk_widget_set_sensitive (data->download_close_button, TRUE); + gtk_dialog_response (data->download_dialog, GTK_RESPONSE_OK); gdk_threads_leave (); return NULL; @@ -812,7 +810,6 @@ create_main_window (GtkBuilder *builder, const gchar* camera_name) td.download_dialog = GTK_DIALOG (gtk_builder_get_object (builder, "download-dialog")); td.download_adjustment = GTK_ADJUSTMENT (gtk_builder_get_object (builder, "download-adjustment")); - td.download_close_button = GTK_WIDGET (gtk_builder_get_object (builder, "download-close-button")); /* Set initial data */ pixel_size = bits_per_sample > 8 ? 2 : 1; diff --git a/bin/gui/control.glade b/bin/gui/control.glade index e713371..7a339cf 100644 --- a/bin/gui/control.glade +++ b/bin/gui/control.glade @@ -82,10 +82,10 @@ <child> <object class="GtkButton" id="cancel-button"> <property name="label">gtk-quit</property> - <property name="use_action_appearance">False</property> <property name="visible">True</property> <property name="can_focus">True</property> <property name="receives_default">True</property> + <property name="use_action_appearance">False</property> <property name="use_stock">True</property> <signal name="clicked" handler="gtk_main_quit" swapped="no"/> </object> @@ -98,10 +98,10 @@ <child> <object class="GtkButton" id="proceed-button"> <property name="label">gtk-ok</property> - <property name="use_action_appearance">False</property> <property name="visible">True</property> <property name="can_focus">True</property> <property name="receives_default">True</property> + <property name="use_action_appearance">False</property> <property name="use_stock">True</property> </object> <packing> @@ -142,19 +142,7 @@ <property name="can_focus">False</property> <property name="layout_style">end</property> <child> - <object class="GtkButton" id="download-close-button"> - <property name="label">gtk-close</property> - <property name="use_action_appearance">False</property> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">True</property> - <property name="use_stock">True</property> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">0</property> - </packing> + <placeholder/> </child> </object> <packing> @@ -204,9 +192,6 @@ </child> </object> </child> - <action-widgets> - <action-widget response="0">download-close-button</action-widget> - </action-widgets> </object> <object class="GtkAdjustment" id="exposure-adjustment"> <property name="upper">100</property> @@ -228,36 +213,6 @@ <property name="step_increment">1</property> <property name="page_increment">10</property> </object> - <object class="GtkListStore" id="zoom-values"> - <columns> - <!-- column-name display --> - <column type="gchararray"/> - <!-- column-name factor --> - <column type="gdouble"/> - </columns> - <data> - <row> - <col id="0" translatable="yes">400 %</col> - <col id="1">4</col> - </row> - <row> - <col id="0" translatable="yes">200 %</col> - <col id="1">2</col> - </row> - <row> - <col id="0" translatable="yes">100 %</col> - <col id="1">1</col> - </row> - <row> - <col id="0" translatable="yes">50 %</col> - <col id="1">0.5</col> - </row> - <row> - <col id="0" translatable="yes">25 %</col> - <col id="1">0.25</col> - </row> - </data> - </object> <object class="GtkWindow" id="window"> <property name="can_focus">False</property> <property name="title" translatable="yes">Camera Control</property> @@ -274,9 +229,9 @@ <property name="can_focus">False</property> <child> <object class="GtkMenuItem" id="menuitem1"> - <property name="use_action_appearance">False</property> <property name="visible">True</property> <property name="can_focus">False</property> + <property name="use_action_appearance">False</property> <property name="label" translatable="yes">_File</property> <property name="use_underline">True</property> <child type="submenu"> @@ -286,9 +241,9 @@ <child> <object class="GtkImageMenuItem" id="imagemenuitem1"> <property name="label">gtk-new</property> - <property name="use_action_appearance">False</property> <property name="visible">True</property> <property name="can_focus">False</property> + <property name="use_action_appearance">False</property> <property name="use_underline">True</property> <property name="use_stock">True</property> </object> @@ -296,9 +251,9 @@ <child> <object class="GtkImageMenuItem" id="imagemenuitem2"> <property name="label">gtk-open</property> - <property name="use_action_appearance">False</property> <property name="visible">True</property> <property name="can_focus">False</property> + <property name="use_action_appearance">False</property> <property name="use_underline">True</property> <property name="use_stock">True</property> </object> @@ -306,9 +261,9 @@ <child> <object class="GtkImageMenuItem" id="save-item"> <property name="label">gtk-save-as</property> - <property name="use_action_appearance">False</property> <property name="visible">True</property> <property name="can_focus">False</property> + <property name="use_action_appearance">False</property> <property name="use_underline">True</property> <property name="use_stock">True</property> </object> @@ -322,9 +277,9 @@ <child> <object class="GtkImageMenuItem" id="imagemenuitem_quit"> <property name="label">gtk-quit</property> - <property name="use_action_appearance">False</property> <property name="visible">True</property> <property name="can_focus">False</property> + <property name="use_action_appearance">False</property> <property name="use_underline">True</property> <property name="use_stock">True</property> <signal name="activate" handler="gtk_main_quit" swapped="no"/> @@ -336,9 +291,9 @@ </child> <child> <object class="GtkMenuItem" id="menuitem4"> - <property name="use_action_appearance">False</property> <property name="visible">True</property> <property name="can_focus">False</property> + <property name="use_action_appearance">False</property> <property name="label" translatable="yes">_Help</property> <property name="use_underline">True</property> <child type="submenu"> @@ -348,9 +303,9 @@ <child> <object class="GtkImageMenuItem" id="imagemenuitem_about"> <property name="label">gtk-about</property> - <property name="use_action_appearance">False</property> <property name="visible">True</property> <property name="can_focus">False</property> + <property name="use_action_appearance">False</property> <property name="use_underline">True</property> <property name="use_stock">True</property> </object> @@ -372,9 +327,9 @@ <property name="can_focus">False</property> <child> <object class="GtkToolButton" id="start-button"> - <property name="use_action_appearance">False</property> <property name="visible">True</property> <property name="can_focus">False</property> + <property name="use_action_appearance">False</property> <property name="label" translatable="yes">Run</property> <property name="use_underline">True</property> <property name="stock_id">gtk-media-play</property> @@ -386,9 +341,9 @@ </child> <child> <object class="GtkToolButton" id="record-button"> - <property name="use_action_appearance">False</property> <property name="visible">True</property> <property name="can_focus">False</property> + <property name="use_action_appearance">False</property> <property name="label" translatable="yes">Record</property> <property name="use_underline">True</property> <property name="stock_id">gtk-media-record</property> @@ -400,9 +355,9 @@ </child> <child> <object class="GtkToolButton" id="stop-button"> - <property name="use_action_appearance">False</property> <property name="visible">True</property> <property name="can_focus">False</property> + <property name="use_action_appearance">False</property> <property name="label" translatable="yes">Stop</property> <property name="use_underline">True</property> <property name="stock_id">gtk-media-stop</property> @@ -414,9 +369,9 @@ </child> <child> <object class="GtkToolButton" id="download-button"> - <property name="use_action_appearance">False</property> <property name="visible">True</property> <property name="can_focus">False</property> + <property name="use_action_appearance">False</property> <property name="label" translatable="yes">Download</property> <property name="use_underline">True</property> <property name="icon_name">network-receive</property> @@ -625,10 +580,10 @@ <child> <object class="GtkCheckButton" id="repeat-checkbutton"> <property name="label" translatable="yes">Repeat</property> - <property name="use_action_appearance">False</property> <property name="visible">True</property> <property name="can_focus">True</property> <property name="receives_default">False</property> + <property name="use_action_appearance">False</property> <property name="xalign">0</property> <property name="draw_indicator">True</property> </object> @@ -865,11 +820,11 @@ <child> <object class="GtkCheckButton" id="histogram-checkbutton"> <property name="label" translatable="yes">Live Update</property> - <property name="use_action_appearance">False</property> <property name="visible">True</property> <property name="can_focus">True</property> <property name="receives_default">False</property> <property name="border_width">6</property> + <property name="use_action_appearance">False</property> <property name="xalign">0</property> <property name="active">True</property> <property name="draw_indicator">True</property> @@ -1079,11 +1034,11 @@ <child> <object class="GtkCheckButton" id="logarithmus-checkbutton"> <property name="label" translatable="yes">Logarithmus</property> - <property name="use_action_appearance">False</property> <property name="visible">True</property> <property name="can_focus">True</property> <property name="receives_default">False</property> <property name="border_width">10</property> + <property name="use_action_appearance">False</property> <property name="xalign">0</property> <property name="draw_indicator">True</property> </object> @@ -1160,4 +1115,34 @@ </object> </child> </object> + <object class="GtkListStore" id="zoom-values"> + <columns> + <!-- column-name display --> + <column type="gchararray"/> + <!-- column-name factor --> + <column type="gdouble"/> + </columns> + <data> + <row> + <col id="0" translatable="yes">400 %</col> + <col id="1">4</col> + </row> + <row> + <col id="0" translatable="yes">200 %</col> + <col id="1">2</col> + </row> + <row> + <col id="0" translatable="yes">100 %</col> + <col id="1">1</col> + </row> + <row> + <col id="0" translatable="yes">50 %</col> + <col id="1">0.5</col> + </row> + <row> + <col id="0" translatable="yes">25 %</col> + <col id="1">0.25</col> + </row> + </data> + </object> </interface> diff --git a/docs/style.css b/docs/style.css index 6d5b32d..3b9889c 100644 --- a/docs/style.css +++ b/docs/style.css @@ -130,10 +130,6 @@ ul#toc { list-style-type: none; } -li { - margin-top: 0.5em; -} - ul ul, ol ol { margin: 0 0 0 24px; diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt index e02359c..88acd86 100644 --- a/plugins/CMakeLists.txt +++ b/plugins/CMakeLists.txt @@ -7,3 +7,4 @@ add_subdirectory(pco) add_subdirectory(pylon) add_subdirectory(ufo) add_subdirectory(dexela) +add_subdirectory(xkit) diff --git a/plugins/pco/uca-pco-camera.c b/plugins/pco/uca-pco-camera.c index b327532..6eedff8 100644 --- a/plugins/pco/uca-pco-camera.c +++ b/plugins/pco/uca-pco-camera.c @@ -115,7 +115,6 @@ enum { 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, @@ -194,10 +193,6 @@ struct _UcaPcoCameraPrivate { 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; @@ -307,64 +302,6 @@ override_maximum_adcs(UcaPcoCameraPrivate *priv) 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 gboolean -check_timebase (gdouble time, gdouble scale) -{ - const gdouble EPSILON = 1e-3; - gdouble scaled = time * scale; - return scaled >= 1.0 && (scaled - ((int) scaled)) < EPSILON; -} - -static gdouble -get_suitable_timebase(gdouble time) -{ - if (check_timebase (time, 1e3)) - return TIMEBASE_MS; - if (check_timebase (time, 1e6)) - return TIMEBASE_US; - if (check_timebase (time, 1e9)) - return TIMEBASE_NS; - return TIMEBASE_INVALID; -} - -static gdouble -get_internal_delay (UcaPcoCamera *camera) -{ - if (camera->priv->description->type == CAMERATYPE_PCO_DIMAX_STD) { - guint sensor_rate; - g_object_get (camera, "sensor-pixelrate", &sensor_rate, NULL); - - if (sensor_rate == 55000000.0) - return 0.000079; - else if (sensor_rate == 62500000.0) - return 0.000036; - } - - return 0.0; -} - static int fg_callback(frameindex_t frame, struct fg_apc_data *apc) { @@ -606,11 +543,8 @@ uca_pco_camera_grab(UcaCamera *camera, gpointer data, GError **error) g_object_get(G_OBJECT(camera), "is-readout", &is_readout, NULL); if (is_readout) { - if (priv->current_image == priv->num_recorded_images) { - g_set_error (error, UCA_CAMERA_ERROR, UCA_CAMERA_ERROR_END_OF_STREAM, - "End of data stream"); + if (priv->current_image == priv->num_recorded_images) return FALSE; - } /* * No joke, the pco firmware allows to read a range of images but @@ -694,93 +628,23 @@ uca_pco_camera_set_property(GObject *object, guint property_id, const GValue *va case PROP_EXPOSURE_TIME: { - const gdouble time = g_value_get_double(value); + uint32_t exposure; + uint32_t framerate; - 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; - err = pco_set_timebase(priv->pco, priv->delay_timebase, suitable_timebase); - break; - } - - gdouble timebase = convert_timebase(suitable_timebase); - guint32 timesteps = time / timebase; - - err = pco_set_exposure_time(priv->pco, timesteps); - } + pco_get_framerate (priv->pco, &framerate, &exposure); + exposure = (uint32_t) (g_value_get_double (value) * 1000 * 1000 * 1000); + pco_set_framerate (priv->pco, framerate, exposure, false); } 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; + uint32_t exposure; + uint32_t framerate; - 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); - - 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. - */ - err = pco_set_delay_time(priv->pco, 0); - } - else - g_warning("Cannot set such a small exposure time"); - } - else { - if (suitable_timebase != priv->delay_timebase) { - priv->delay_timebase = suitable_timebase; - err = pco_set_timebase(priv->pco, suitable_timebase, priv->exposure_timebase); - } - - gdouble timebase = convert_timebase(suitable_timebase); - guint32 timesteps = time / timebase; - err = pco_set_delay_time(priv->pco, timesteps); - } + pco_get_framerate (priv->pco, &framerate, &exposure); + framerate = (uint32_t) (g_value_get_double (value) * 1000); + pco_set_framerate (priv->pco, framerate, exposure, true); } break; @@ -1012,36 +876,21 @@ uca_pco_camera_get_property(GObject *object, guint property_id, GValue *value, G case PROP_EXPOSURE_TIME: { - uint32_t exposure_time; - err = pco_get_exposure_time(priv->pco, &exposure_time); - - if (priv->exposure_timebase == TIMEBASE_INVALID) - read_timebase(priv); + uint32_t exposure; + uint32_t framerate; - g_value_set_double(value, convert_timebase(priv->exposure_timebase) * exposure_time); + pco_get_framerate (priv->pco, &framerate, &exposure); + g_value_set_double (value, exposure / 1000. / 1000. / 1000.); } 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; - err = pco_get_delay_time(priv->pco, &delay_time); + uint32_t exposure; + uint32_t framerate; - if (priv->delay_timebase == TIMEBASE_INVALID) - read_timebase(priv); - - g_value_set_double(value, convert_timebase(priv->delay_timebase) * delay_time); + pco_get_framerate (priv->pco, &framerate, &exposure); + g_value_set_double (value, framerate / 1000.); } break; @@ -1422,13 +1271,6 @@ uca_pco_camera_class_init(UcaPcoCameraClass *klass) 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", @@ -1607,8 +1449,6 @@ uca_pco_camera_init (UcaPcoCamera *self) priv->last_frame = 0; priv->grab_buffer = NULL; priv->construct_error = NULL; - priv->delay_timebase = TIMEBASE_INVALID; - priv->exposure_timebase = TIMEBASE_INVALID; if (!setup_pco_camera (priv)) return; @@ -1629,7 +1469,6 @@ uca_pco_camera_init (UcaPcoCamera *self) 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 GType diff --git a/plugins/xkit/CMakeLists.txt b/plugins/xkit/CMakeLists.txt new file mode 100644 index 0000000..f328f25 --- /dev/null +++ b/plugins/xkit/CMakeLists.txt @@ -0,0 +1,32 @@ +cmake_minimum_required(VERSION 2.8) +project(ucaxkit CXX) + +set(UCA_CAMERA_NAME "xkit") +set(PLUGIN_VERSION "0.1.0") +set(PLUGIN_REVISION "0") +set(PLUGIN_REQUIRES "libuca >= 1.2.0") + +find_path (XKIT_INCLUDE_DIR + NAMES dll_api.h mpxhw.h) + +find_library (XKIT_LIBRARIES + NAMES xKIT) + +if (XKIT_INCLUDE_DIR AND XKIT_LIBRARIES) + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/../package-plugin.sh.in + ${CMAKE_CURRENT_BINARY_DIR}/../../package-plugin-${UCA_CAMERA_NAME}.sh) + include_directories(${XKIT_INCLUDE_DIR}) + + # We have to compile with g++ because the included header files have C++ + # style comments ... + add_library(ucaxkit SHARED + uca-xkit-camera.cc) + + target_link_libraries(ucaxkit + ${UCA_DEPS} + ${XKIT_LIBRARIES}) + + install(TARGETS ucaxkit + LIBRARY DESTINATION ${LIB_INSTALL_DIR}/uca + COMPONENT ${UCA_CAMERA_NAME}) +endif () diff --git a/plugins/xkit/uca-xkit-camera.cc b/plugins/xkit/uca-xkit-camera.cc new file mode 100644 index 0000000..9b163c3 --- /dev/null +++ b/plugins/xkit/uca-xkit-camera.cc @@ -0,0 +1,357 @@ +/* Copyright (C) 2011-2013 Matthias Vogelgesang <matthias.vogelgesang@kit.edu> + (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 <dll_api.h> + +#undef FALSE +#undef TRUE + +#include <gio/gio.h> +#include <gmodule.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <errno.h> + +#include "uca-camera.h" +#include "uca-xkit-camera.h" + + +#define UCA_XKIT_CAMERA_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), UCA_TYPE_XKIT_CAMERA, UcaXkitCameraPrivate)) + +#define MEDIPIX_SENSOR_HEIGHT 256 + +static void uca_xkit_camera_initable_iface_init (GInitableIface *iface); + +G_DEFINE_TYPE_WITH_CODE (UcaXkitCamera, uca_xkit_camera, UCA_TYPE_CAMERA, + G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, + uca_xkit_camera_initable_iface_init)) + +GQuark uca_xkit_camera_error_quark() +{ + return g_quark_from_static_string("uca-xkit-camera-error-quark"); +} + +enum { + PROP_POSITIVE_POLARITY = N_BASE_PROPERTIES, + N_PROPERTIES +}; + +static gint base_overrideables[] = { + PROP_NAME, + PROP_SENSOR_WIDTH, + PROP_SENSOR_HEIGHT, + PROP_SENSOR_MAX_FRAME_RATE, + PROP_SENSOR_BITDEPTH, + PROP_EXPOSURE_TIME, + PROP_ROI_X, + PROP_ROI_Y, + PROP_ROI_WIDTH, + PROP_ROI_HEIGHT, + PROP_HAS_STREAMING, + PROP_HAS_CAMRAM_RECORDING, + 0, +}; + +static GParamSpec *xkit_properties[N_PROPERTIES] = { NULL, }; + +struct _UcaXkitCameraPrivate { + GError *construct_error; + Mpx2Interface *interface; + gint devices[4]; + gint n_devices; + gint device; + + DevInfo info; + AcqParams acq; +}; + + +static gboolean +setup_xkit (UcaXkitCameraPrivate *priv) +{ + + priv->interface = getMpx2Interface(); + priv->interface->findDevices (priv->devices, &priv->n_devices); + + if (priv->n_devices > 0) + priv->interface->init (priv->devices[0]); + + priv->device = priv->devices[0]; + priv->interface->getDevInfo (priv->device, &priv->info); + + /* TODO: find some sensible defaults */ + priv->acq.useHwTimer = TRUE; + priv->acq.enableCst = FALSE; + priv->acq.polarityPositive = TRUE; + priv->acq.mode = ACQMODE_ACQSTART_TIMERSTOP; + priv->acq.acqCount = 1; + priv->acq.time = 1.0; + + return TRUE; +} + +static void +uca_xkit_camera_start_recording (UcaCamera *camera, + GError **error) +{ + UcaXkitCameraPrivate *priv; + + g_return_if_fail (UCA_IS_XKIT_CAMERA (camera)); + priv = UCA_XKIT_CAMERA_GET_PRIVATE (camera); + + if (priv->interface->setAcqPars (priv->device, &priv->acq)) { + g_set_error_literal (error, UCA_CAMERA_ERROR, UCA_CAMERA_ERROR_RECORDING, + "Could not set acquisition parameters"); + } +} + +static void +uca_xkit_camera_stop_recording (UcaCamera *camera, + GError **error) +{ + g_return_if_fail (UCA_IS_XKIT_CAMERA (camera)); +} + +static void +uca_xkit_camera_start_readout (UcaCamera *camera, + GError **error) +{ + g_return_if_fail( UCA_IS_XKIT_CAMERA (camera)); +} + +static void +uca_xkit_camera_stop_readout (UcaCamera *camera, + GError **error) +{ + g_return_if_fail (UCA_IS_XKIT_CAMERA (camera)); +} + +static gboolean +uca_xkit_camera_grab (UcaCamera *camera, + gpointer data, + GError **error) +{ + UcaXkitCameraPrivate *priv; + guint32 size; + g_return_val_if_fail (UCA_IS_XKIT_CAMERA (camera), FALSE); + + /* XXX: For now we trigger on our own because the X-KIT chip does not + * provide auto triggering */ + + priv = UCA_XKIT_CAMERA_GET_PRIVATE (camera); + size = priv->info.pixCount; + + if (priv->interface->startAcquisition (priv->device)) { + g_set_error_literal (error, UCA_CAMERA_ERROR, UCA_CAMERA_ERROR_RECORDING, + "Could not pre-trigger"); + return FALSE; + } + + if (priv->interface->readMatrix (priv->device, (gint16 *) data, size)) { + g_set_error_literal (error, UCA_CAMERA_ERROR, UCA_CAMERA_ERROR_RECORDING, + "Could not grab frame"); + return FALSE; + } + + if (priv->interface->stopAcquisition (priv->device)) { + g_set_error_literal (error, UCA_CAMERA_ERROR, UCA_CAMERA_ERROR_RECORDING, + "Could stop acquisition"); + return FALSE; + } + + return TRUE; +} + +static void +uca_xkit_camera_trigger (UcaCamera *camera, + GError **error) +{ + g_return_if_fail (UCA_IS_XKIT_CAMERA (camera)); +} + +static void +uca_xkit_camera_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + UcaXkitCameraPrivate *priv = UCA_XKIT_CAMERA_GET_PRIVATE(object); + + switch (property_id) { + case PROP_EXPOSURE_TIME: + priv->acq.time = g_value_get_double (value); + break; + case PROP_POSITIVE_POLARITY: + priv->acq.polarityPositive = g_value_get_boolean (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + return; + } +} + +static void +uca_xkit_camera_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + UcaXkitCameraPrivate *priv = UCA_XKIT_CAMERA_GET_PRIVATE (object); + + switch (property_id) { + case PROP_NAME: + g_value_set_string (value, priv->info.ifaceName); + break; + case PROP_SENSOR_MAX_FRAME_RATE: + /* TODO: pretty arbitrary, huh? */ + g_value_set_float (value, 150.0f); + break; + case PROP_SENSOR_WIDTH: + g_value_set_uint (value, priv->info.rowLen); + break; + case PROP_SENSOR_HEIGHT: + g_value_set_uint (value, priv->info.numberOfRows * MEDIPIX_SENSOR_HEIGHT); + break; + case PROP_SENSOR_BITDEPTH: + g_value_set_uint (value, 11); + break; + case PROP_EXPOSURE_TIME: + g_value_set_double (value, priv->acq.time); + 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, priv->info.rowLen); + break; + case PROP_ROI_HEIGHT: + g_value_set_uint (value, priv->info.numberOfRows * MEDIPIX_SENSOR_HEIGHT); + break; + case PROP_POSITIVE_POLARITY: + g_value_set_boolean (value, priv->acq.polarityPositive); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void +uca_xkit_camera_finalize(GObject *object) +{ + UcaXkitCameraPrivate *priv; + + priv = UCA_XKIT_CAMERA_GET_PRIVATE (object); + g_clear_error (&priv->construct_error); + + G_OBJECT_CLASS (uca_xkit_camera_parent_class)->finalize (object); +} + +static gboolean +ufo_xkit_camera_initable_init (GInitable *initable, + GCancellable *cancellable, + GError **error) +{ + UcaXkitCamera *camera; + UcaXkitCameraPrivate *priv; + + g_return_val_if_fail (UCA_IS_XKIT_CAMERA (initable), FALSE); + + if (cancellable != NULL) { + g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, + "Cancellable initialization not supported"); + return FALSE; + } + + camera = UCA_XKIT_CAMERA (initable); + priv = camera->priv; + + if (priv->construct_error != NULL) { + if (error) + *error = g_error_copy (priv->construct_error); + + return FALSE; + } + + return TRUE; +} + +static void +uca_xkit_camera_initable_iface_init (GInitableIface *iface) +{ + iface->init = ufo_xkit_camera_initable_init; +} + +static void +uca_xkit_camera_class_init (UcaXkitCameraClass *klass) +{ + GObjectClass *oclass = G_OBJECT_CLASS (klass); + UcaCameraClass *camera_class = UCA_CAMERA_CLASS (klass); + + oclass->set_property = uca_xkit_camera_set_property; + oclass->get_property = uca_xkit_camera_get_property; + oclass->finalize = uca_xkit_camera_finalize; + + camera_class->start_recording = uca_xkit_camera_start_recording; + camera_class->stop_recording = uca_xkit_camera_stop_recording; + camera_class->start_readout = uca_xkit_camera_start_readout; + camera_class->stop_readout = uca_xkit_camera_stop_readout; + camera_class->grab = uca_xkit_camera_grab; + camera_class->trigger = uca_xkit_camera_trigger; + + for (guint i = 0; base_overrideables[i] != 0; i++) + g_object_class_override_property (oclass, base_overrideables[i], uca_camera_props[base_overrideables[i]]); + + xkit_properties[PROP_POSITIVE_POLARITY] = + g_param_spec_boolean ("positive-polarity", + "Is polarity positive", + "Is polarity positive", + TRUE, (GParamFlags) G_PARAM_READWRITE); + + for (guint id = N_BASE_PROPERTIES; id < N_PROPERTIES; id++) + g_object_class_install_property (oclass, id, xkit_properties[id]); + + g_type_class_add_private (klass, sizeof(UcaXkitCameraPrivate)); +} + +static void +uca_xkit_camera_init (UcaXkitCamera *self) +{ + UcaXkitCameraPrivate *priv; + + self->priv = priv = UCA_XKIT_CAMERA_GET_PRIVATE (self); + priv->construct_error = NULL; + + if (!setup_xkit (priv)) + return; +} + +G_MODULE_EXPORT GType +uca_camera_get_type (void) +{ + return UCA_TYPE_XKIT_CAMERA; +} diff --git a/plugins/xkit/uca-xkit-camera.h b/plugins/xkit/uca-xkit-camera.h new file mode 100644 index 0000000..6dc66f2 --- /dev/null +++ b/plugins/xkit/uca-xkit-camera.h @@ -0,0 +1,76 @@ +/* Copyright (C) 2011, 2012 Matthias Vogelgesang <matthias.vogelgesang@kit.edu> + (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_XKIT_CAMERA_H +#define __UCA_XKIT_CAMERA_H + +#include <glib-object.h> +#include "uca-camera.h" + +G_BEGIN_DECLS + +#define UCA_TYPE_XKIT_CAMERA (uca_xkit_camera_get_type()) +#define UCA_XKIT_CAMERA(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), UCA_TYPE_XKIT_CAMERA, UcaXkitCamera)) +#define UCA_IS_XKIT_CAMERA(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), UCA_TYPE_XKIT_CAMERA)) +#define UCA_XKIT_CAMERA_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), UCA_TYPE_XKIT_CAMERA, UcaXkitCameraClass)) +#define UCA_IS_XKIT_CAMERA_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), UCA_TYPE_XKIT_CAMERA)) +#define UCA_XKIT_CAMERA_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), UCA_TYPE_XKIT_CAMERA, UcaXkitCameraClass)) + +#define UCA_XKIT_CAMERA_ERROR uca_xkit_camera_error_quark() +typedef enum { + UCA_XKIT_CAMERA_ERROR_INIT, + UCA_XKIT_CAMERA_ERROR_START_RECORDING, + UCA_XKIT_CAMERA_ERROR_STOP_RECORDING, + UCA_XKIT_CAMERA_ERROR_TRIGGER, + UCA_XKIT_CAMERA_ERROR_NEXT_EVENT, + UCA_XKIT_CAMERA_ERROR_NO_DATA, + UCA_XKIT_CAMERA_ERROR_MAYBE_CORRUPTED +} UcaXkitCameraError; + +typedef struct _UcaXkitCamera UcaXkitCamera; +typedef struct _UcaXkitCameraClass UcaXkitCameraClass; +typedef struct _UcaXkitCameraPrivate UcaXkitCameraPrivate; + +/** + * UcaXkitCamera: + * + * Creates #UcaXkitCamera instances by loading corresponding shared objects. The + * contents of the #UcaXkitCamera structure are private and should only be + * accessed via the provided API. + */ +struct _UcaXkitCamera { + /*< private >*/ + UcaCamera parent; + + UcaXkitCameraPrivate *priv; +}; + +/** + * UcaXkitCameraClass: + * + * #UcaXkitCamera class + */ +struct _UcaXkitCameraClass { + /*< private >*/ + UcaCameraClass parent; +}; + +GType uca_xkit_camera_get_type(void); + +G_END_DECLS + +#endif |