Commit 601b12b9 authored by Éric Thiébaut's avatar Éric Thiébaut
Browse files

Changes in camera API

- frame_number -> serial in tao_acquisition_buffer
- updating and getting camera configuration is now done by 2 different
  functions;
- names have been "normalized";
parent 48744c3a
......@@ -310,7 +310,7 @@ tao_camera* andor_open_camera(
// Allocate camera instance with the device number provided as contextual
// data. The remaining initialization will done by the `on_initialize`
// virtual method.
return tao_create_camera(&ops, &dev, sizeof(andor_device));
return tao_camera_create(&ops, &dev, sizeof(andor_device));
}
// In case of errors during initialization, we simply call the `on_finalize`
......@@ -383,7 +383,7 @@ static tao_status on_reset(
// We shall revert to run-level 1 (sleeping) if possible. FIXME: This is
// not yet implemented, we could reset the USB device as done in Julia
// code.
tao_store_error("tao_reset_camera", TAO_UNSUPPORTED);
tao_store_error("tao_camera_reset", TAO_UNSUPPORTED);
return TAO_ERROR;
}
......@@ -398,14 +398,14 @@ static tao_status on_check_config(
const tao_camera_config* cfg)
{
return check_configuration((andor_device*)cam, cfg,
"tao_check_camera_configuration");
"tao_camera_check_configuration");
}
static tao_status on_set_config(
tao_camera* cam,
const tao_camera_config* cfg)
{
const char* func = "tao_set_camera_configuration";
const char* func = "tao_camera_set_configuration";
int status;
bool changes = false;
......@@ -562,7 +562,7 @@ static tao_status on_set_config(
static tao_status on_start(
tao_camera* cam)
{
const char* func = "tao_start_acquisition"; // name of the caller
const char* func = "tao_camera_start_acquisition"; // name of the caller
AT_64 ival;
AT_BOOL bval;
int idx, status;
......@@ -629,7 +629,7 @@ static tao_status on_start(
cam->bufs[i].height = height;
cam->bufs[i].stride = stride;
cam->bufs[i].encoding = bufferencoding;
cam->bufs[i].frame_number = 0;
cam->bufs[i].serial = 0;
cam->bufs[i].frame_start = unknown_time;
cam->bufs[i].frame_end = unknown_time;
cam->bufs[i].buffer_ready = unknown_time;
......@@ -777,7 +777,7 @@ static tao_status on_wait_buffer(
int last = (cam->last + 1)%cam->nbufs;
cam->bufs[last].data = ptr;
cam->bufs[last].size = siz;
cam->bufs[last].frame_number = ++cam->info.frames;
cam->bufs[last].serial = ++cam->info.frames;
cam->bufs[last].frame_start = now;
cam->bufs[last].frame_end = now;
cam->bufs[last].buffer_ready = now;
......@@ -1213,7 +1213,7 @@ static tao_status check_configuration(
const char* func)
{
// Check region of interest.
if (tao_check_camera_roi(&cfg->roi,
if (tao_camera_roi_check(&cfg->roi,
dev->base.info.sensorwidth,
dev->base.info.sensorheight) != TAO_OK) {
tao_store_error(func, TAO_BAD_ROI);
......
......@@ -43,7 +43,7 @@
// other processes. Access to the "private" resources (including the camera
// device `dev`) is controlled by locking/unlocking the camera device `dev`,
// access to the "public" resources is controlled by locking/unlocking the
// shared camera `shmcam = tao_get_framegrabber_shared_camera(vfg)`.
// shared camera `shmcam = tao_framegrabber_get_shared_camera(vfg)`.
//
// FIXME: it is important to qualify as "volatile" the variables that may
// change.
......@@ -307,18 +307,20 @@ int main(
// Retrieve initial configuration. Make sure to synchronize the actual
// configuration after any changes in case some parameters are not exactly
// the requested ones.
if (tao_get_camera_configuration(dev, &cfg, true) != TAO_OK) {
if (tao_camera_update_configuration(dev) != TAO_OK ||
tao_camera_get_configuration(dev, &cfg) != TAO_OK) {
tao_report_error();
return EXIT_FAILURE;
}
if (debuglevel > 0) {
// Apply the current configuration. Should not change anything (this
// is just for debugging purposes).
if (tao_set_camera_configuration(dev, &cfg) != TAO_OK) {
if (tao_camera_set_configuration(dev, &cfg) != TAO_OK) {
tao_report_error();
return EXIT_FAILURE;
}
if (tao_get_camera_configuration(dev, &cfg, true) != TAO_OK) {
if (tao_camera_update_configuration(dev) != TAO_OK ||
tao_camera_get_configuration(dev, &cfg) != TAO_OK) {
tao_report_error();
return EXIT_FAILURE;
}
......@@ -331,7 +333,7 @@ int main(
// the shared camera, except that the shared camera state is set to
// "sleeping" as it is not usable by clients until the worker thread has
// effectively started.
vfg = tao_create_framegrabber(accesspoint, nframes, perms);
vfg = tao_framegrabber_create(accesspoint, nframes, perms);
if (vfg == NULL) {
fprintf(stderr, "%s: failed to create the virtual frame-grabber\n",
progname);
......@@ -342,9 +344,9 @@ int main(
fprintf(stderr, "%s: virtual frame grabber created with %d buffers\n",
progname, nframes);
}
shcam = tao_get_framegrabber_shared_camera(vfg);
shcam = tao_framegrabber_get_shared_camera(vfg);
wrlock_shared_camera();
(void)tao_reflect_camera_information(shcam, dev);
(void)tao_camera_reflect_configuration(shcam, dev);
shcam->info.state = TAO_STATE_INITIALIZING;
unlock_shared_camera();
if (tao_any_errors(NULL)) {
......@@ -483,13 +485,13 @@ static void on_return(
wrlock_shared_camera();
shcam->info.state = TAO_STATE_KILLED;
unlock_shared_camera();
(void)tao_destroy_framegrabber(vfg);
(void)tao_framegrabber_destroy(vfg);
vfg = NULL;
}
if (dev != NULL) {
// Finally close camera device.
debug(CONTROL_DEBUGLEVEL, "Close camera device...");
tao_destroy_camera(dev);
tao_camera_destroy(dev);
debug(CONTROL_DEBUGLEVEL, "Camera device closed");
dev = NULL;
}
......@@ -700,7 +702,7 @@ static tao_status process_frame(
long stride = buf->stride;
tao_encoding bufenc = buf->encoding;
const void* data = (unsigned char*)buf->data + buf->offset;
tao_shared_array* arr = tao_get_framegrabber_buffer(vfg);
tao_shared_array* arr = tao_framegrabber_get_buffer(vfg);
tao_encoding arrenc;
switch (TAO_SHARED_ARRAY_ELTYPE(arr)) {
case TAO_UINT8:
......@@ -735,7 +737,7 @@ static tao_status process_frame(
arr->ts[1] = buf->frame_end;
arr->ts[2] = buf->buffer_ready;
wrlock_shared_camera();
(void)tao_post_framegrabber_buffer(vfg);
(void)tao_framegrabber_post_buffer(vfg);
unlock_shared_camera();
}
return TAO_OK;
......@@ -789,7 +791,7 @@ static void* run_worker(
const tao_acquisition_buffer* buf;
tao_status status;
unlock_monitor();
status = tao_wait_acquisition_buffer(dev, &buf, timeout, drop);
status = tao_camera_wait_acquisition_buffer(dev, &buf, timeout, drop);
lock_monitor();
if (status == TAO_OK) {
// Process the acquisition buffer unless aborting or suspended.
......@@ -802,7 +804,7 @@ static void* run_worker(
status = on_processing(buf);
lock_monitor();
}
tao_release_acquisition_buffer(dev);
tao_camera_release_acquisition_buffer(dev);
}
if (status == TAO_ERROR) {
// Report errors while owning the camera. FIXME: We probably
......@@ -1187,7 +1189,7 @@ static tao_state get_stable_state(
{
while (dev->runlevel == 3 && reset > 0) {
// Try to reset.
if (tao_reset_camera(dev) != TAO_OK) {
if (tao_camera_reset(dev) != TAO_OK) {
tao_report_error();
}
--reset;
......@@ -1234,15 +1236,15 @@ static void trigger_acquisition(
// to a stable state.
tao_status status;
if (starting) {
status = tao_start_acquisition(dev);
status = tao_camera_start_acquisition(dev);
} else {
status = tao_stop_acquisition(dev);
status = tao_camera_stop_acquisition(dev);
}
if (status == TAO_OK) {
if (starting) {
status = tao_start_framegrabber_acquisition(vfg);
status = tao_framegrabber_start_acquisition(vfg);
} else {
status = tao_stop_framegrabber_acquisition(vfg);
status = tao_framegrabber_stop_acquisition(vfg);
}
}
change_state(get_stable_state(dev, 1));
......@@ -1493,7 +1495,7 @@ static tao_status on_set_config(
(req.bufferencoding = tao_parse_encoding(val)) !=
TAO_ENCODING_UNKNOWN);
GETOPT("buffers", buffers,
tao_parse_int(val, &req.buffers, 10) == TAO_OK
tao_parse_long(val, &req.buffers, 10) == TAO_OK
&& req.buffers >= 2);
} else if (c == 'e') {
GETOPT("exposuretime", exposuretime,
......@@ -1594,7 +1596,10 @@ static tao_status on_set_config(
// reflect the actual configuration into the shared camera data.
// FIXME: Any errors registered by the camera will be extracted as an
// error message.
status = tao_get_camera_configuration(dev, &cfg, true);
status = tao_camera_update_configuration(dev);
if (status == TAO_OK) {
status = tao_camera_get_configuration(dev, &cfg);
}
if (status == TAO_OK) {
bool change = false;
SETOPT(bufferencoding);
......@@ -1609,11 +1614,11 @@ static tao_status on_set_config(
SETOPT(roi.ybin);
SETOPT(roi.yoff);
SETOPT(sensorencoding);
if (change && tao_set_camera_configuration(dev, &cfg) != TAO_OK) {
if (change && tao_camera_set_configuration(dev, &cfg) != TAO_OK) {
status = TAO_ERROR;
}
wrlock_shared_camera();
if (tao_reflect_camera_information(shcam, dev) != TAO_OK) {
if (tao_camera_reflect_configuration(shcam, dev) != TAO_OK) {
status = TAO_ERROR;
}
unlock_shared_camera();
......
......@@ -68,7 +68,10 @@ int main(
status = tao_get_monotonic_time(&t0);
}
if (status == TAO_OK) {
status = tao_get_camera_configuration(cam, &cfg, true);
status = tao_camera_update_configuration(cam);
}
if (status == TAO_OK) {
status = tao_camera_get_configuration(cam, &cfg);
}
if (status == TAO_OK) {
status = tao_get_monotonic_time(&t1);
......@@ -81,7 +84,7 @@ int main(
status = tao_get_monotonic_time(&t0);
}
if (status == TAO_OK) {
status = tao_get_camera_configuration(cam, &cfg, false);
status = tao_camera_get_configuration(cam, &cfg);
}
if (status == TAO_OK) {
status = tao_get_monotonic_time(&t1);
......@@ -90,7 +93,7 @@ int main(
fprintf(stdout, "Time to retrieve configuration: %.3f µs\n",
1E6*elapsed_seconds(&t1, &t0));
}
if (tao_destroy_camera(cam) != TAO_OK) {
if (tao_camera_destroy(cam) != TAO_OK) {
status = TAO_ERROR;
}
if (status != TAO_OK) {
......
......@@ -409,7 +409,7 @@ int main(
}
// Destroy camera.
tao_destroy_camera((tao_camera*)camera);
tao_camera_destroy((tao_camera*)camera);
if (tao_any_errors(NULL)) {
tao_report_error();
return EXIT_FAILURE;
......
......@@ -64,18 +64,19 @@ int main(
// Measure time taken for updating all the configuration and compare to
// time taken to just retrieve the configuration.
tao_get_monotonic_time(&t0);
tao_get_camera_configuration(cam, &cfg, true);
tao_camera_update_configuration(cam);
tao_camera_get_configuration(cam, &cfg);
tao_get_monotonic_time(&t1);
fprintf(stdout, "Time to update configuration: %.3f µs\n",
1E6*elapsed_seconds(&t1, &t0));
tao_get_monotonic_time(&t0);
tao_get_camera_configuration(cam, &cfg, false);
tao_camera_get_configuration(cam, &cfg);
tao_get_monotonic_time(&t1);
fprintf(stdout, "Time to retrieve configuration: %.3f µs\n",
1E6*elapsed_seconds(&t1, &t0));
// Get current configuration and change some parameters.
tao_get_camera_configuration(cam, &cfg, false);
tao_camera_get_configuration(cam, &cfg);
//cfg.roi.xbin = 1;
//cfg.roi.ybin = 1;
//cfg.roi.xoff = 300;
......@@ -86,13 +87,13 @@ int main(
cfg.exposuretime = 0.005;
cfg.buffers = 4;
//cfg.pixelencoding = ANDOR_ENCODING_MONO12PACKED;
if (tao_set_camera_configuration(cam, &cfg) != TAO_OK) {
if (tao_camera_set_configuration(cam, &cfg) != TAO_OK) {
tao_report_error();
return EXIT_FAILURE;
}
fprintf(stdout, "\n");
tao_camera_info_print(stdout, &cam->info);
tao_get_camera_configuration(cam, &cfg, false);
tao_camera_get_configuration(cam, &cfg);
// Allocate an array to save some images.
nimgs = 5;
......@@ -102,7 +103,7 @@ int main(
// Start acquisition.
tao_get_monotonic_time(&t0);
if (tao_start_acquisition(cam) != TAO_OK) {
if (tao_camera_start_acquisition(cam) != TAO_OK) {
tao_report_error();
return EXIT_FAILURE;
}
......@@ -115,7 +116,7 @@ int main(
for (int k = 0; k < 100; ++k) {
const tao_acquisition_buffer* buf;
t0 = t1;
tao_status status = tao_wait_acquisition_buffer(cam, &buf, 0.1, 0);
tao_status status = tao_camera_wait_acquisition_buffer(cam, &buf, 0.1, 0);
tao_get_monotonic_time(&t1);
if (status == TAO_OK) {
fprintf(stdout, "%3d: %10.3f ms\n", k+1,
......@@ -130,27 +131,27 @@ int main(
buf->stride);
++j;
}
if (tao_release_acquisition_buffer(cam) != TAO_OK) {
if (tao_camera_release_acquisition_buffer(cam) != TAO_OK) {
tao_report_error();
(void)tao_stop_acquisition(cam);
(void)tao_camera_stop_acquisition(cam);
return EXIT_FAILURE;
}
} else if (status == TAO_TIMEOUT) {
fprintf(stderr, "%3d: Timeout!\n", k+1);
} else {
tao_report_error();
(void)tao_stop_acquisition(cam);
(void)tao_camera_stop_acquisition(cam);
return EXIT_FAILURE;
}
}
if (tao_stop_acquisition(cam) != TAO_OK) {
if (tao_camera_stop_acquisition(cam) != TAO_OK) {
tao_report_error();
return EXIT_FAILURE;
}
tao_save_array_to_fits_file(arr, "/tmp/test-andor5.fits", true);
tao_unreference_array(arr);
tao_destroy_camera(cam);
tao_camera_destroy(cam);
return EXIT_SUCCESS;
}
......@@ -35,7 +35,7 @@ static inline void fatal_error(
//-----------------------------------------------------------------------------
// REGIONS OF INTEREST
tao_camera_roi* tao_copy_camera_roi(
tao_camera_roi* tao_camera_roi_copy(
tao_camera_roi* dest,
const tao_camera_roi* src)
{
......@@ -43,7 +43,7 @@ tao_camera_roi* tao_copy_camera_roi(
return dest;
}
tao_camera_roi* tao_define_camera_roi(
tao_camera_roi* tao_camera_roi_define(
tao_camera_roi* roi,
long xbin,
long ybin,
......@@ -61,7 +61,7 @@ tao_camera_roi* tao_define_camera_roi(
return roi;
}
tao_status tao_check_camera_roi(
tao_status tao_camera_roi_check(
const tao_camera_roi* roi,
long sensorwidth,
long sensorheight)
......@@ -80,7 +80,7 @@ tao_status tao_check_camera_roi(
return TAO_OK;
}
void tao_show_camera_roi_option(
void tao_camera_roi_option_show(
FILE* file,
const tao_option* opt)
{
......@@ -89,7 +89,7 @@ void tao_show_camera_roi_option(
roi->xoff, roi->yoff, roi->width, roi->height);
}
bool tao_parse_camera_roi_option(
bool tao_camera_roi_option_parse(
const tao_option* opt,
char* args[])
{
......@@ -182,7 +182,7 @@ static void invalid_runlevel(
tao_store_error(func, code);
}
static tao_status do_buffers(
static tao_status manage_buffers(
tao_camera* cam,
int nbufs)
{
......@@ -206,7 +206,7 @@ static tao_status do_buffers(
return TAO_OK;
}
tao_camera* tao_create_camera(
tao_camera* tao_camera_create(
const tao_camera_ops* ops,
void* ctx,
size_t size)
......@@ -223,15 +223,15 @@ tao_camera* tao_create_camera(
if (size < sizeof(tao_camera)) {
size = sizeof(tao_camera);
}
tao_camera* cam = (tao_camera*)tao_malloc(size);
tao_camera* cam = tao_malloc(size);
if (cam == NULL) {
return NULL;
}
memset((void*)cam, 0, size);
memset(cam, 0, size);
if (tao_mutex_initialize(&cam->mutex, false) != TAO_OK) {
goto error1;
}
if (tao_condition_initialize(&cam->notify, false) != TAO_OK) {
if (tao_condition_initialize(&cam->notify, false) != TAO_OK) {
goto error2;
}
cam->ops = ops;
......@@ -246,6 +246,7 @@ tao_camera* tao_create_camera(
cam->info.state = TAO_STATE_WAITING;
return cam;
// Branch here in case of errors.
error3:
pthread_cond_destroy(&cam->notify);
error2:
......@@ -255,7 +256,7 @@ tao_camera* tao_create_camera(
return NULL;
}
tao_status tao_destroy_camera(
tao_status tao_camera_destroy(
tao_camera* cam)
{
if (cam != NULL) {
......@@ -274,7 +275,7 @@ tao_status tao_destroy_camera(
// Free acquisition buffers **after** calling the "finalize" virtual
// method to make sure that these buffers are not in use somewhere.
do_buffers(cam, 0);
manage_buffers(cam, 0);
// Destroy condition variable and mutex.
pthread_cond_destroy(&cam->notify);
......@@ -298,7 +299,7 @@ tao_status tao_destroy_camera(
// variable was not signaled until the specified timeout or EINTR if the call
// was interrupted by a signal.
void tao_lock_camera(
void tao_camera_lock(
tao_camera* cam)
{
int code = pthread_mutex_lock(&cam->mutex);
......@@ -308,7 +309,7 @@ void tao_lock_camera(
}
}
tao_status tao_try_lock_camera(
tao_status tao_camera_try_lock(
tao_camera* cam)
{
int code = pthread_mutex_trylock(&cam->mutex);
......@@ -323,7 +324,7 @@ tao_status tao_try_lock_camera(
}
}
void tao_unlock_camera(
void tao_camera_unlock(
tao_camera* cam)
{
int code = pthread_mutex_unlock(&cam->mutex);
......@@ -333,27 +334,27 @@ void tao_unlock_camera(
}
}
void tao_notify_camera(
void tao_camera_notify(
tao_camera* cam)
{
// Manual pages say that pthread_cond_signal never returns an error code.
(void)pthread_cond_signal(&cam->notify);
}
tao_status tao_wait_camera(
tao_status tao_camera_wait(
tao_camera* cam)
{
return tao_condition_wait(&cam->notify, &cam->mutex);
}
tao_status tao_abstimed_wait_camera(
tao_status tao_camera_abstimed_wait(
tao_camera* cam,
const tao_time* abstime)
{
return tao_condition_abstimed_wait(&cam->notify, &cam->mutex, abstime);
}
tao_status tao_timed_wait_camera(
tao_status tao_camera_timed_wait(
tao_camera* cam,
double secs)
{
......@@ -390,7 +391,7 @@ static tao_status fix_camera_state(
return TAO_OK;
}
tao_status tao_start_acquisition(
tao_status tao_camera_start_acquisition(
tao_camera* cam)
{
switch (cam->runlevel) {
......@@ -403,13 +404,14 @@ tao_status tao_start_acquisition(
tao_store_error(__func__, TAO_BAD_BUFFERS);
return TAO_ERROR;
}
if (do_buffers(cam, cam->info.config.buffers + 1) != TAO_OK) {
if (manage_buffers(cam, cam->info.config.buffers + 1) != TAO_OK) {
return TAO_ERROR;
}
for (int i = 0; i < cam->nbufs; ++i) {
// Reset the counter and data address of all acquisition buffers.
// Reset the serial number and data address of all acquisition
// buffers.
cam->bufs[i].data = NULL;
cam->bufs[i].frame_number = 0;
cam->bufs[i].serial = 0;
}
cam->events = 0;
cam->pending = 0;
......@@ -445,7 +447,7 @@ tao_status tao_start_acquisition(
// however be a good idea to make acquisition buffers available outside
// acquisition. However I do not know what does the Phoenix with internal
// buffers so it is safer to keep the restriction for now.
tao_status tao_stop_acquisition(
tao_status tao_camera_stop_acquisition(
tao_camera* cam)
{
switch (cam->runlevel) {
......@@ -477,7 +479,7 @@ tao_status tao_stop_acquisition(
}
}
tao_status tao_wait_acquisition_buffer(
tao_status tao_camera_wait_acquisition_buffer(
tao_camera* cam,
const tao_acquisition_buffer** bufptr,
double secs,
......@@ -529,7 +531,7 @@ tao_status tao_wait_acquisition_buffer(
return TAO_OK;
}
tao_status tao_release_acquisition_buffer(
tao_status tao_camera_release_acquisition_buffer(
tao_camera* cam)
{
// Check arguments, then release buffer from the internal camera list.
......@@ -552,7 +554,7 @@ long tao_number_of_pending_acquisition_buffers(
return (cam != NULL && cam->runlevel == 2 ? cam->pending : 0);
}
tao_status tao_reset_camera(
tao_status tao_camera_reset(
tao_camera* cam)
{
switch (cam->runlevel) {
......@@ -563,7 +565,7 @@ tao_status tao_reset_camera(
case 2:
// Resetting is equivalent to stopping acquisition.
return tao_stop_acquisition(cam);
return tao_camera_stop_acquisition(cam);
case 3:
// Recoverable error. Attempt to reset the camera.
......@@ -583,7 +585,7 @@ tao_status tao_reset_camera(
}
}
tao_status tao_check_camera_configuration(
tao_status tao_camera_check_configuration(
tao_camera* cam,
const tao_camera_config* cfg)
{
......@@ -593,26 +595,37 @@ tao_status tao_check_camera_configuration(
return TAO_OK;
}
tao_status tao_get_camera_configuration(
tao_camera* cam,
tao_camera_config* cfg,
bool update)
// Update settings from hardware.
tao_status tao_camera_update_configuration(
tao_camera* cam)
{
if (update) {
// Update settings from hardware.
if (cam->runlevel != 1) {
invalid_runlevel(cam, __func__);
return TAO_ERROR;
}
if (cam->ops->update_config(cam) != TAO_OK) {
return TAO_ERROR;
}
if (cam == NULL) {
tao_store_error(__func__, TAO_BAD_ADDRESS);
return TAO_ERROR;
}
if (cam->runlevel != 1) {
invalid_runlevel(cam, __func__);
return TAO_ERROR;
}
if (cam->ops->update_config(cam) != TAO_OK) {
return TAO_ERROR;
}
return TAO_OK;
}