oni.h

Version Macros

See https://semver.org/ for a complete explanation of these macro definitions.

ONI_VERSION_MAJOR

MAJOR version for incompatible API changes

ONI_VERSION_MINOR

MINOR version for added functionality that is backwards compatible

ONI_VERSION_PATCH

PATCH version for backwards compatible bug fixes

ONI_MAKE_VERSION(major, minor, patch)

Defined as

MAJOR * 10000 + MINOR * 100 + PATCH

Provides compile-time access to the API version.

ONI_VERSION

Compile-time API version. Defined as

ONI_MAKE_VERSION(ONI_VERSION_MAJOR ONI_VERSION_MINOR, ONI_VERSION_PATCH).

Acquisition Context

typedef struct oni_ctx_impl *oni_ctx

An ONI-compliant acquisition context implementation. oni_ctx is an opaque handle to a structure which manages hardware state.

Attention

Context details are hidden in the implementation file (oni.c). Direct manipulation of oni_ctx data members is never nessesary or correct.

Each oni_ctx instance manages the device driver, device table, read and write buffers, acquisition run state, etc. Following a hardware reset, which is triggered either by a call to oni_init_ctx() or oni_set_opt() using the ONI_OPT_RESET context option, the context run state is set to UNINTIALIZED and the device table is pushed onto the host signal stream by the host hardware as COBS-encoded packets. On the signal stream, the device table is organized as follows,

... | DEVICEMAPACK, uint32_t num_devices | DEVICEINST oni_device_t dev_0
    | DEVICEINST oni_device_t dev_1 | ... | DEVICEINST oni_device_t dev_n
    | ...

where “|” represents a packet delimiter. During a call to oni_init_ctx(), the device table is decoded from the signal stream. It can then be examined using calls to oni_get_opt() using the ONI_OPT_DEVICETABLE option. After the device table is received, the context run state becomes IDLE. A call to oni_set_opt() with the ONI_OPT_RUNNING option can then be used to start acquisition uy transitioning the context run state to RUNNING.

Device

struct oni_device_t
oni_size_t idx

Fully qualified RSV.RSV.HUB.IDX device table index.

RSV

8-bit unsigned integer (reserved)

HUB

8-bit unsigned integer indicating the hub index

IDX

8-bit unsigned integer indicating the device index

oni_dev_id_t id

Device ID number (see onix.h for ONIX-specific definitions)

oni_size_t read_size

Device data read size per frame in bytes

oni_size_t write_size

Device data write size per frame in bytes

An ONI-compliant device implementation. An oni_device_t describes one of potentially many pieces of hardware managed by an oni_ctx. Examples of individual devices might include ephys chips, IMUs, optical stimulators, camera sensors, etc. Each valid device type has a unique ONIX ID which is enumerated in the auxiliary onix.h file or, potentially, some other header for those wishing to extend this use this library for their own hardware. ONIX device IDs are provided in onix.h as a set of enumerations.

Tip

Look at device index defintions in onix.h to see available ONIX-specific device definitions and enum ranges that will not interfere with ONIX for custom or closed-source projects.

Todo

Device registers are described in their datasheet (link to datasheets and examples of register programming and access)

A device table is read from hardware and stored in the current context via a call to oni_init_ctx(). This table can be examined via calls to oni_get_opt() using the ONI_OPT_DEVICETABLE option.

Frame

struct oni_frame_t
const oni_fifo_time_t time

Frame time (ONI_OPT_ACQCLKHZ host clock counter)

const oni_fifo_dat_t dev_idx

Device index that produced or accepts the frame

const oni_fifo_dat_t data_sz

Size of data in bytes

uint8_t *data

Raw data block. This pointer is a zero-copy “view” into a private, referenced-counted buffer managed by the acquisition context. The handle to this buffer is hidden by the API using some C union magic.

An ONI-compliant data frame implementation. oni_frame_t’s are produced by calls to oni_read_frame() and consumed by calls to oni_write_frame().

See also

oni_create_frame()

Create frames for use with oni_write_frame().

oni_write_frame()

Write frames to hardware.

oni_read_frame()

Read frames from hardware.

oni_destroy_frame()

Free a frame and underlying resources allocated by oni_create_frame() or oni_read_frame().

Functions

The functions in oni.h form the basis of the API and are all that is needed during the development of user-facing software.

oni_ctx oni_create_ctx(const char *drv_name)
int oni_init_ctx(oni_ctx ctx, int host_idx)
int oni_destroy_ctx(oni_ctx ctx)
int oni_get_opt(oni_ctx ctx, int option, void *value, size_t *size)
int oni_set_opt(oni_ctx ctx, int option, const void *value, size_t size)
int oni_get_driver_opt(const oni_ctx ctx, int drv_opt, void *value, size_t *size)
int oni_set_driver_opt(oni_ctx ctx, int drv_opt, const void *value, size_t size)
int oni_read_reg(const oni_ctx ctx, oni_dev_idx_t dev_idx, oni_reg_addr_t addr, oni_reg_val_t *value)
int oni_write_reg(const oni_ctx ctx, oni_dev_idx_t dev_idx, oni_reg_addr_t addr, oni_reg_val_t value)
int oni_read_frame(const oni_ctx ctx, oni_frame_t **frame)
int oni_create_frame(const oni_ctx ctx, oni_frame_t **frame, oni_dev_idx_t dev_idx, void *data, size_t data_sz)
int oni_write_frame(const oni_ctx ctx, const oni_frame_t *frame)
void oni_destroy_frame(oni_frame_t *frame)
void oni_version(int *major, int *minor, int *patch)
const char *oni_error_str(int err)
oni_ctx oni_create_ctx(const char *drv_name)

Creates an acquisition context, oni_ctx, which is an opaque handle to a structure that manages device drivers, the device table, data streaming, memory management, etc. On success the selected driver is loaded and an oni_ctx is allocated and created, and its handle is passed to the user. Many API functions take a oni_ctx as a first agrument.

Parameters
  • drv_name – A string specifying the device driver used by the context to control hardware. This string corresponds a compiled implementation of onidriver.h that has the name onidriver_<drv_name>.<so/dll>. If this library is not on the dynamic library search path, the function will error.

Returns

An opaque handle to the newly created context if successful. Otherwise it shall return NULL and set errno to EAGAIN.

Example

See Acquisition Context Creation

See also

oni_get_opt()

Inspect oni_ctx state

oni_set_opt()

Modify oni_ctx state

int oni_init_ctx(oni_ctx ctx, int host_idx)

Initialize an acquisition context. This function initializes the selected device driver, opens all communication channels, and acquires a device table that maps out the device control and streaming hierarchy. Specifically, during a successful call to oni_init_ctx(), the following events occur:

  1. All required data streams are opened.

  2. A hardware reset issued using ONI_OPT_RESET

  3. A device table is obtained from the hardware.

  4. The minimal ONI_OPT_BLOCKREADSIZE and ONI_OPT_BLOCKWRITESIZE values are calculated and stored.

  5. The context run state is moved from UNINITIALIZED to IDLE.

Parameters
  • ctx – The acquisition context to be initialized

  • host_idx – The index of the hardware we are going to manage using the initialized context and driver. A value of -1 will attempt to open the default host index and is useful if there is only a single ONIX host managed by driver selected in oni_create_ctx()

Returns

0 on success otherwise see Error Codes.

Example

See Acquisition Context Creation

int oni_destroy_ctx(oni_ctx ctx)

Terminate a context and free bound resources. During context destruction, all resources allocated by oni_create_ctx() and oni_init_ctx() are freed. This function can be called from any context run state. When called, an interrupt signal (TODO: Which?) is raised and any blocking operations will return immediately. Attached resources (device drivers, data buffers, etc.) are closed and their resources freed.

Parameters
  • ctx – The acquisition context to close.

Returns

0 on success otherwise see Error Codes.

Example

See Closing an Acquisition Context

int oni_get_opt(oni_ctx ctx, int option, void *value, size_t *size)

Retrieves the option specified by the option argument within the acquisition context ctx and stores it in the value buffer. The size provides a pointer to the size of the value buffer, in bytes. Upon successful completion oni_get_opt() modifies the value pointed to by size to indicate the actual size of the option value stored in the buffer. If the value pointed to by size is too small to store the value, the function will error. Additionally, some context options are write-only and others can only be read in certain acquisition states. If these constraints are disobeyed, the function will error. See Context Options for a description of each possible option, including access constraints.

Parameters
  • ctxoni_ctx context to read an option from

  • option – Selected option to read. See Context Options for valid options.

  • value – buffer to store value of option after it is read

  • size – Pointer to the size of value buffer (including terminating null character, if applicable) in bytes.

Returns

0 on success otherwise see Error Codes.

Example

See Examining the Device Table and Setting Read and Write Buffer Sizes

See also

Context Options

Valid context options with access and type specifications.

int oni_set_opt(oni_ctx ctx, int option, const void *value, size_t size)

Sets the option specified by the option argument within the acquisition context ctx to the contents of the value buffer. The size indicates the size of the value buffer, in bytes. Upon successful completion, oni_set_opt() modifies the value pointed to by size to indicate the actual size of the option value stored in the functions will error. Additionally, some context options are read-only and others can only be written in certain acquisition states. If these constraints are disobeyed, the function will error. See Context Options for description of each possible option, including access constraints.

Parameters
  • ctxoni_ctx context to read an option from

  • option – Selected option to set. See Context Options for valid options.

  • value – buffer containing data to be written to option

  • size – Size of value buffer (including terminating null character, if applicable) in bytes.

Returns

0 on success otherwise see Error Codes

Example

See Examining the Device Table and Setting Read and Write Buffer Sizes

See also

Context Options

Valid context options with access and type specifications.

int oni_get_driver_opt(const oni_ctx ctx, int drv_opt, void *value, size_t *size)

Todo

Document

int oni_set_driver_opt(oni_ctx ctx, int drv_opt, const void *value, size_t size)

Todo

Document

int oni_read_reg(const oni_ctx ctx, oni_dev_idx_t dev_idx, oni_reg_addr_t addr, oni_reg_val_t *value)

Read the value of a configuration register from a specific device within the current device table. This can be used to verify the success of calls to oni_write_reg() or to obtain state information about devices managed by the current acquisition context. Register specifications (addresses, read- and write-access, and descriptions are provided on the ONI-device datasheet).

Todo

Links to example datasheets

Parameters
  • ctxoni_ctx context that manages the requested device

  • dev_idx – fully-qualifies device index within the device table

  • addr – Address of register to be read

  • value – Pointer to an unsigned integer that will store the value of the register at addr on dev_idx.

Returns

0 on success otherwise see Error Codes

Example

See Reading and Writing Device Registers

int oni_write_reg(const oni_ctx ctx, oni_dev_idx_t dev_idx, oni_reg_addr_t addr, oni_reg_val_t value)

Change the value of a configuration register from specific devices within the current device table. This can be used to change the functionality of devices, e.g. set filter bandwidth, select active channels, or change stimulation parameters). Register specifications (addresses, read- and write-access, acceptable values, and descriptions are provided on the ONI-device datasheet).

Todo

Links to example datasheets

Parameters
  • ctxoni_ctx context that manages the requested device

  • dev_idx – fully-qualified device index within the device table

  • addr – Address of register to be read

  • value – Value to write to the register at addr on dev_idx.

Returns

0 on success otherwise see Error Codes

Example

See Reading and Writing Device Registers

int oni_read_frame(const oni_ctx ctx, oni_frame_t **frame)

Read high-bandwidth data from the data input channel. oni_read_frame() allocates host memory and populates it with a single oni_frame_t struct using the data input stream. This call will block until either enough data available on the stream to construct an underlying block buffer (see :macro:ONI_OPT_BLOCKREADSIZE and Setting Read and Write Buffer Sizes). oni_frame_t’s created during calls to oni_read_frame() are zero-copy views into this buffer.

Attention

It is the user’s responsibility to free the resources allocated by this call by passing the resulting frame pointer to oni_destroy_frame()

Parameters
  • ctxoni_ctx context that manages the high-bandwidth input channel that the frame will be read from

  • frame – NULL pointer to reference using internal memory

Returns

0 on success otherwise see Error Codes

Example

See Reading Data Frames

int oni_create_frame(const oni_ctx ctx, oni_frame_t **frame, oni_dev_idx_t dev_idx, void *data, size_t data_sz)

Create an :oni_frame_t` for consumption by oni_write_frame().

Attention

It is the user’s responsibility to free the resources allocated by this call by passing the resulting frame pointer to oni_destroy_frame()

Parameters
  • ctxoni_ctx context that manages the high-bandwidth output channel that the frame will be written through

  • frame – NULL pointer to reference using internal memory

  • dev_idx – fully-qualified device index within the device table that the frame will be written to.

  • data – Raw data block to be copied into the frame.

  • data_sz – Size of data in byes.

Returns

0 on success otherwise see Error Codes

Example

See Writing Data Frames

Attention

data_sz Must be

  1. An integer multiple of the selected dev_idx’s write size as indicated within the device table

  2. Smaller than the internal write block memory size (see ONI_OPT_BLOCKWRITESIZE and Setting Read and Write Buffer Sizes)

int oni_write_frame(const oni_ctx ctx, const oni_frame_t *frame)

Write an oni_frame_t to a particular device within the device table using the high-bandwidth output channel.

Parameters
  • ctxoni_ctx context that manages the high-bandwidth output channel that the frame will be written through

  • frame – Pointer to frame created duing a call to oni_create_frame()

Returns

0 on success otherwise see Error Codes

Example

See Writing Data Frames

Tip

Frames created by using oni_create_frame() can be written to a device multiple times by using them as input arguments to oni_write_frame() multiple times. This allows pre-allocation of frame resources from improved latency and determinism in closed-loop applications.

void oni_destroy_frame(oni_frame_t *frame)

Note

Each call to oni_create_frame() or oni_read_frame() must matched by a call to oni_destroy_frame() to prevent memory leaks.

void oni_version(int *major, int *minor, int *patch)

Report the oepcie library version. This library uses Semantic Versioning. Briefly, the major revision is for incompatible API changes. Minor version is for backwards compatible changes. The patch number is for backwards-compatible bug fixes. When this function returns, input pointers will reference the library’s version.

Parameters
  • major – major library version for incompatible API changes

  • minor – minor library version for backwards compatible changes.

  • patch – patch number for backwards-compatible bug fixes.

const char *oni_error_str(int err)

Convert a return code (see Error Codes) into a human readable string.

Parameters
  • err – The error code to convert