Commit 5abf41fd authored by Éric Thiébaut's avatar Éric Thiébaut
Browse files

Implement more methods for remote swavefront sensors

parent c7c26a62
......@@ -20,6 +20,104 @@
#include "tao-generic.h"
#include "tao-remote-sensors-private.h"
static inline size_t round_size(
size_t size,
size_t align)
{
// FIXME: Can be (size + align - 1) & (-align) when align is a power of 2
// (which it should be).
return TAO_ROUND_UP(size, align);
}
static inline tao_remote_sensor_config* primary_config(
tao_remote_sensor* wfs)
{
return &wfs->config;
}
static inline tao_remote_sensor_config* secondary_config(
tao_remote_sensor* wfs)
{
return TAO_COMPUTED_ADDRESS(wfs, wfs->config2_offset);
}
extern tao_remote_sensor* tao_remote_sensor_create(
const char* owner,
long nbufs,
long max_nsubs,
long max_ninds,
unsigned flags)
{
// Check arguments.
if (owner == NULL || owner[0] == 0 || strlen(owner) >= TAO_OWNER_SIZE) {
tao_store_error(__func__, TAO_BAD_NAME);
return NULL;
}
if (nbufs < 2) {
tao_store_error(__func__, TAO_BAD_BUFFERS);
return NULL;
}
if (max_nsubs < 1 || max_ninds < 1) {
tao_store_error(__func__, TAO_BAD_SIZE);
return NULL;
}
if (max_nsubs > max_ninds) {
tao_store_error(__func__, TAO_BAD_NUMBER);
return NULL;
}
size_t config_align = sizeof(double);
size_t inds_elsize = sizeof(long);
size_t subs_elsize = sizeof(tao_wavefront_sensor_subpupil);
size_t subs_align = sizeof(double);
// Offsets and sizes of layout indices and definitions of sub-pupils in
// `tao_remote_sensor_config` structure.
size_t config_inds_size = max_ninds*inds_elsize;
size_t config_subs_size = max_nsubs*subs_elsize;
size_t config_inds_offset = TAO_OFFSET_OF(tao_remote_sensor_config, inds);
size_t config_subs_offset = round_size(
config_inds_offset + config_inds_size, subs_align);
size_t config_size = config_subs_offset + config_subs_size;
// Offsets of primary and secondary configurations in `tao_remote_sensor`
// structure.
size_t config1_offset = TAO_OFFSET_OF(tao_remote_sensor, config);
size_t config2_offset = round_size(
config1_offset + config_size, config_align);
// Offset to the first data-frame.
size_t offset = round_size(
config2_offset + config_size, TAO_ALIGNMENT);
// Size of header part and of a single data element in data-frame.
size_t header_size = TAO_OFFSET_OF(tao_remote_sensor_dataframe, data);
size_t data_elsize = sizeof(tao_wavefront_sensor_data);
// Size of a data-frame.
size_t stride = round_size(
header_size + max_nsubs*data_elsize, TAO_ALIGNMENT);
// Total size.
size_t size = offset + nbufs*stride;
// Allocate remote shared object.
tao_remote_sensor* wfs = (tao_remote_sensor*)tao_remote_object_create(
owner, TAO_REMOTE_SENSOR, nbufs, offset, stride, size, flags);
if (wfs == NULL) {
return NULL;
}
// Instantiate object.
tao_forced_store(&wfs->max_ninds, max_ninds);
tao_forced_store(&wfs->max_nsubs, max_nsubs);
tao_forced_store(&wfs->config2_offset, config2_offset);
tao_forced_store(&primary_config(wfs)->subs_offset, config_subs_offset);
tao_forced_store(&secondary_config(wfs)->subs_offset, config_subs_offset);
return wfs;
}
tao_status tao_remote_sensor_check_config(
const tao_remote_sensor* wfs,
const tao_remote_sensor_config* cfg,
......@@ -40,17 +138,84 @@ tao_status tao_remote_sensor_check_config(
long dim2 = cfg->base.dims[1];
long ninds = dim1*dim2;
long nsubs = cfg->base.nsubs;
if (ninds > wfs->max_size || nsubs > wfs->max_nsubs) {
if (ninds > wfs->max_ninds || nsubs > wfs->max_nsubs) {
tao_store_error(__func__, TAO_OUT_OF_RANGE);
return TAO_ERROR;
}
return TAO_OK;
}
tao_serial tao_remote_sensor_get_mark(
const tao_remote_sensor* wfs)
const char* tao_remote_sensor_get_camera(
const tao_remote_sensor* wfs,
tao_shmid* shmid_ptr,
long* dims)
{
if (wfs == NULL) {
if (shmid_ptr != NULL) {
*shmid_ptr = TAO_BAD_SHMID;
}
if (dims != NULL) {
dims[0] = 0;
dims[1] = 0;
}
return "";
} else {
if (shmid_ptr != NULL) {
*shmid_ptr = wfs->config.camera.shmid;
}
if (dims != NULL) {
dims[0] = wfs->config.camera.width;
dims[1] = wfs->config.camera.height;
}
return wfs->config.camera.owner;
}
}
static tao_serial send_simple_command(
const char* func,
tao_remote_sensor* wfs,
tao_command cmd,
double secs)
{
// Check arguments.
if (wfs == NULL) {
tao_store_error(func, TAO_BAD_ADDRESS);
return TAO_ERROR;
}
if (cmd == TAO_COMMAND_NONE) {
tao_store_error(__func__, TAO_BAD_COMMAND);
return -1;
}
// Attempt to lock the remote sensor and wait for it becomes ready for a
// new command.
tao_serial num = tao_remote_object_lock_for_command(
tao_remote_object_cast(wfs), cmd, secs);
if (num > 0 && tao_remote_sensor_unlock(wfs) != TAO_OK) {
num = -1;
}
return num;
}
tao_serial tao_remote_sensor_start(
tao_remote_sensor* wfs,
double secs)
{
return send_simple_command(__func__, wfs, TAO_COMMAND_START, secs);
}
tao_serial tao_remote_sensor_stop(
tao_remote_sensor* wfs,
double secs)
{
return send_simple_command(__func__, wfs, TAO_COMMAND_STOP, secs);
}
tao_serial tao_remote_sensor_kill(
tao_remote_sensor* wfs,
double secs)
{
return (wfs == NULL) ? 0 : wfs->mark;
return send_simple_command(__func__, wfs, TAO_COMMAND_KILL, secs);
}
#define TYPE remote_sensor
......
......@@ -19,40 +19,49 @@ TAO_BEGIN_DECLS
/**
* Structure describing the complete configuration of a wavefront sensor.
*
*/
typedef struct tao_remote_sensor_config_ {
tao_wavefront_sensor_config base;
struct {
char owner[TAO_OWNER_SIZE];
long width;
long height;
tao_shmid shmid;
char owner[TAO_OWNER_SIZE];
} camera;
const size_t subs_offset;///< Offset to the sub-pupil definitions.
// This structure has a fixed size part followed by two variable size
// parts: the layout of the sub-pupils grid and the list of sub-pupils
// definitions. Since the structure is meant to be stored in shared
// memory, offsets relative to the address of the structure (and not
// absolute addresses in memory) of the variable size parts may be in the
// structure. If the first variable size part immediately (with some
// padding for correct alignment) follows the fixed size part, it can also
// be the last member of the structure.
size_t subs_offset;///< Offset to the sub-pupil definitions.
// To save one offset The layout must be the last member, its reserved size is `max_size`, its actual size is `dims[0]*dims[1]` and it is followed by `max_nsubs` dims[0]*dims[1]`.
long layout[1];///< Layout of sub-pupils grid.
// Last member, actual size large enough for `max_ninds` elements.
long inds[1];///< Layout indices.
} tao_remote_sensor_config;
// This structure has a fixed size part followed by two variable size parts:
// the layout of the sub-pupils grid and the list of sub-pupils definitions.
// Since the structure is meant to be stored in shared memory, offsets relative
// to the address of the structure (and not absolute addresses in memory) of
// the variable size parts may be in the structure. If the first variable size
// part immediately (with some padding for correct alignment) follows the fixed
// size part, it can also be the last member of the structure.
struct tao_remote_sensor_ {
tao_remote_object base;///< Common part for all shared objects.
const long max_nsubs;///< Maximum number of sub-pupils.
const long max_size;///< Maximum size of sub-pupil grid.
const long refs_offset;///< Offset to sub-pupil reference (in bytes).
tao_serial mark;///< Serial number of last data-frame.
tao_remote_sensor_config config;///< Current configuration.
tao_remote_object base;///< Common part for all shared objects.
const long max_ninds;///< Maximum number of nodes in sub-pupil
/// grid.
const long max_nsubs;///< Maximum number of sub-pupils.
const size_t config2_offset;///< Offset to the secondary configuration.
// Last member.
tao_remote_sensor_config config;///< Primary configuration.
};
/**
* @brief Data-frame of remote wavefront sensor as stored in shared memory.
*
*/
typedef struct tao_remote_sensor_dataframe_ {
tao_dataframe_header base;
long nsubs;
tao_wavefront_sensor_data data[1];
} tao_remote_sensor_dataframe;
TAO_END_DECLS
#endif // TAO_REMOTE_SENSORS_PRIVATE__H_
......@@ -83,7 +83,7 @@ typedef struct tao_remote_sensor_ tao_remote_sensor;
*
* @param nbufs The number of cyclic data-frame buffers.
*
* @param max_size The maximum number of nodes in of the 2-dimensional layout
* @param max_ninds The maximum number of nodes in of the 2-dimensional layout
* grid.
*
* @param max_nsubs The maximum number of the sub-pupils.
......@@ -96,8 +96,8 @@ typedef struct tao_remote_sensor_ tao_remote_sensor;
extern tao_remote_sensor* tao_remote_sensor_create(
const char* owner,
long nbufs,
long max_ninds,
long max_nsubs,
long max_size,
unsigned flags);
/**
......@@ -528,19 +528,26 @@ extern int tao_remote_sensor_is_alive(
const tao_remote_sensor* wfs);
/**
* Get the mark set for the next wavefront sensor data-frame.
* Get the camera of a remote wavefront sensor.
*
* The caller shall own the lock on the remote wavefront sensor.
* @param wfs Pointer to a remote wavefront sensor attached to the address
* space of the caller.
*
* @param shmid Address where to store the shared memory identifier of
* the camera. Can be `NULL` to not retrieve this information.
*
* @param wfs Pointer to remote wavefront sensor in caller's address space
* (can be `NULL`).
* @param dims Address where to store the dimensions (width and height) of
* the camera. Can be `NULL` to not retrieve this information.
*
* @return The mark set for the next wavefront sensor frame, 0 if `wfs` is
* `NULL` or no mark has been applied yet. Whatever the result, this
* getter function leaves the caller's last error unchanged.
* @return The name of the server owning the camera of the remote wavefront
* sensor; an empty string if `wfs` is `NULL` or currently has no
* associated remote camera. Whatever the result, this getter function
* leaves the caller's last error unchanged.
*/
extern tao_serial tao_remote_sensor_get_mark(
const tao_remote_sensor* wfs);
const char* tao_remote_sensor_get_camera(
const tao_remote_sensor* wfs,
tao_shmid* shmid,
long* dims);
/**
* Start processing by a remote wavefront sensor.
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment