| gclib 2.4.1 Galil Communications Library

Loading...
Searching...
No Matches
Functions
Unsolicited Data
C » Controller

Get unsolicited messages, interrupts, or data records, in blocking or callback mode. More...

## Functions
gclib_result | gclib_set_interrupts (gclib_handle h, gclib_interrupt_type interrupt_mask, gclib_axis_flags motion_complete_axes, gclib_digital_input_flags digital_inputs)
| Configure which interrupts will be generated by the controller.
gclib_result | gclib_set_data_records (gclib_handle h, size_t period_ms)
| Configure controller data records.
gclib_result | gclib_subscribe_messages (gclib_handle h, void(callback)(void *user_data, const char *message), void *user_data)
| Subscribe to unsolicited messages.
gclib_result | gclib_subscribe_interrupts (gclib_handle h, void(callback)(void *user_data, gclib_interrupt_t interrupt), void *user_data)
| Subscribe to interrupts.
gclib_result | gclib_subscribe_data_records (gclib_handle h, void(callback)(void *user_data, gclib_data_record_handle data_record), void *user_data)
| Subscribe to data records.
gclib_result | gclib_subscribe_progress (gclib_handle h, void(callback)(void *user_data, size_t current, size_t max), void *user_data)
| Subscribe to progress for gclib_set_program(), gclib_set_array(), and gclib_set_firmware().
gclib_result | gclib_unsubscribe (gclib_handle h, void *callback)
| Unsubscribe from messages, interrupts, data records, or progress.
gclib_result | gclib_message (gclib_handle h, char *message, size_t len, int timeout)
| Get a queued unsolicited message, or wait up to timeout ms for one to arrive.
gclib_result | gclib_interrupt (gclib_handle h, gclib_interrupt_t *interrupt, int timeout)
| Get a queued interrupt, or wait up to timeout ms for one to arrive.
gclib_result | gclib_data_record (gclib_handle h, gclib_data_record_handle *data_record, int timeout)
| Get a queued data record, or wait up to timeout ms for one to arrive.

## Detailed Description

Get unsolicited messages, interrupts, or data records, in blocking or callback mode.

## Blocking Mode

Blocking mode is simpler to use, but has tradeoffs. If you want unsolicited data as soon as it arrives, you must block the thread to wait for it, which may not be ideal. If you want to keep the thread running, then you must periodically check for queued unsolicited data, which can add unwanted latency.

To subscribe in blocking mode, simply do not pass a callback or data pointer when you subscribe. These methods will begin queueing any unsolicited data sent by the controller.

gclib_subscribe_messages(h, NULL, NULL);
gclib_subscribe_interrupts(h, NULL, NULL);
gclib_subscribe_data_records(h, NULL, NULL);
gclib_subscribe_data_records
gclib_result gclib_subscribe_data_records(gclib_handle h, void(callback)(void *user_data, gclib_data_record_handle data_record), void *user_data)
Subscribe to data records.
gclib_subscribe_interrupts
gclib_result gclib_subscribe_interrupts(gclib_handle h, void(callback)(void *user_data, gclib_interrupt_t interrupt), void *user_data)
Subscribe to interrupts.
gclib_subscribe_messages
gclib_result gclib_subscribe_messages(gclib_handle h, void(callback)(void *user_data, const char *message), void *user_data)
Subscribe to unsolicited messages.

## Callback Mode

Callback mode allows your thread to stay running while enabling immediate response to unsolicited data. When data arrives, your callback function will be invoked on a separate, dedicated thread. Due to this, callback mode can be more complicated to use if you are not familiar with thread synchronization.

To subscribe in callback mode, pass a callback function and an optional data pointer when you subscribe. When unsolicited data arrives, your callback will be invoked and passed the data pointer. Use this to allow the callback function access to any data it needs, and to allow data to persist between callbacks.

void handle_message(void* user_data, const char* message) {
printf("Message received: %s\n", message);
}
void handle_interrupt(void* user_data, gclib_interrupt_t interrupt) {
printf("Interrupt received, type %i, raw status byte %i": interrupt.type, interrupt.status);
}
void handle_data_record(void* user_data, gclib_data_record_handle data_record) {
printf("Data record received, sample %i", gclib_data_record_sample(data_record));
}
gclib_interrupt_t::type
gclib_interrupt_type type
Definition gclib.h:56
gclib_interrupt_t::status
uint8_t status
The raw status byte generated by the controller. See the EI command reference for all possible values...
Definition gclib.h:62
gclib_data_record_handle
struct DataRecord * gclib_data_record_handle
A handle to a data record, for use in Data Record API calls.
Definition gclib.h:25
gclib_data_record_sample
uint16_t gclib_data_record_sample(gclib_data_record_handle h)
The sample in which this data record was generated.
gclib_interrupt_t
An interrupt generated by the controller.
Definition gclib.h:55
gclib_subscribe_messages(h, handle_messages, user_data);
gclib_subscribe_interrupts(h, handle_interrupts, user_data);
gclib_subscribe_data_records(h, handle_data_records, user_data);

### User Data

The user data pointer can be used to pass arbitrary data to the callback function. The following example uses a struct to provide the callback access to the gclib handle itself, a count to increment when messages are received, and an atomic bool to signal when the program is ready to exit. Note that the handle is safe to use concurrently, and the count doesn't need to be atomic (since it is only used in the callback thread). As soon as the tenth message is received, the program is stopped and the connection is closed from the callback method, and the main thread is signaled to exit.

#include <gclib.h>
#include <stdio.h>
#include <stdatomic.h>
#include "sleep.h"
struct context {
gclib_handle h; // gclib is thread-safe
int count; // Only used in the callback thread
atomic_bool done; // Used in both threads
};
void handle_message(void* user_data, const char* message) {
struct context* ctx = user_data;
ctx->count = ctx->count + 1;
printf("Received message #%i at TIME %i\n", ctx->count, (int)atof(message));
if (ctx->count == 10) {
gclib_command(ctx->h, "ST", NULL, 0);
gclib_close(&ctx->h);
ctx->done = true;
}
};
int main(int argc, char* argv[]) {
struct context ctx = {NULL, 0, 0};
gclib_open(&ctx.h, argv[1]);
gclib_subscribe_messages(ctx.h, handle_message, &ctx);
gclib_set_program(ctx.h, "#msg\nMGTIME\nWT100\nJP#msg\nEN", NULL);
gclib_command(ctx.h, "XQ", NULL, 0);
while (!ctx.done) {
msleep(100 * 1000); // Do work
}
}
gclib.h
gclib_close
gclib_result gclib_close(gclib_handle *h)
Close connection to controller.
gclib_open
gclib_result gclib_open(gclib_handle *h, const char *address)
Open a connection to a controller.
gclib_command
gclib_result gclib_command(gclib_handle h, const char *command, char *buf, size_t len)
Issues a command to the controller and provides the response.
gclib_set_program
gclib_result gclib_set_program(gclib_handle h, const char *program, const char *insert)
Set the program on the controller.
gclib_handle
struct Context * gclib_handle
A handle to an open connection given by gclib_open() for use in future API calls.
Definition gclib.h:23

## Function Documentation

## ◆ gclib_set_interrupts()

gclib_result gclib_set_interrupts | ( | gclib_handle | h,
|  | gclib_interrupt_type | interrupt_mask,
|  | gclib_axis_flags | motion_complete_axes,
|  | gclib_digital_input_flags | digital_inputs )

Configure which interrupts will be generated by the controller.

By default, the controller will not generate any interrupts.

Controllers can be configured to send only an exact list of desired interrupts, to avoid unnecessary processing and network traffic.

Example usage:

gclib_set_interrupts(h, GCLIB_ALL_INTERRUPTS, 0, 0); // Enable all interrupts.
gclib_set_interrupts(h,
GCLIB_MOTION_COMPLETE | GCLIB_DIGITAL_INPUT_LOW, // Only enable two interrupts
GCLIB_AXIS_A | GCLIB_AXIS_F, // Only trigger GCLIB_MOTION_COMPLETE on axis A or F
GCLIB_DIGITAL_INPUT_1 | GCLIB_DIGITAL_INPUT_4); // Only trigger GCLIB_DIGITAL_INPUT_LOW on digital input 1 and 4.
gclib_set_interrupts(h, 0, 0, 0); // Disable interrupts
gclib_set_interrupts
gclib_result gclib_set_interrupts(gclib_handle h, gclib_interrupt_type interrupt_mask, gclib_axis_flags motion_complete_axes, gclib_digital_input_flags digital_inputs)
Configure which interrupts will be generated by the controller.
GCLIB_DIGITAL_INPUT_4
@ GCLIB_DIGITAL_INPUT_4
Definition gclib.h:70
GCLIB_DIGITAL_INPUT_1
@ GCLIB_DIGITAL_INPUT_1
Definition gclib.h:67
GCLIB_AXIS_F
@ GCLIB_AXIS_F
Definition gclib.h:85
GCLIB_AXIS_A
@ GCLIB_AXIS_A
Definition gclib.h:80
GCLIB_ALL_INTERRUPTS
@ GCLIB_ALL_INTERRUPTS
Definition gclib.h:52
GCLIB_MOTION_COMPLETE
@ GCLIB_MOTION_COMPLETE
Definition gclib.h:44
GCLIB_DIGITAL_INPUT_LOW
@ GCLIB_DIGITAL_INPUT_LOW
Must be reenabled with gclib_set_interrupts() after each occurrence.
Definition gclib.h:51

See gclib_subscribe_interrupts() to enable receiving interrupts from the controller.

Parameters

  h | Handle to an open connection.
  interrupt_mask | Bitmask of desired interrupts. Use GCLIB_NO_INTERRUPTS (0) to disable interrupts. Note that User Interrupts cannot be disabled.
  axis_mask | When GCLIB_MOTION_COMPLETE is in interrupt_mask, this axis mask controls which axes will trigger a GCLIB_MOTION_COMPLETE interrupt. interrupts. If 0, all axes will be selected.
  digital_input_mask | When GCLIB_DIGITAL_INPUT_LOW is in interrupt_mask, this bitmask selects which digital inputs will trigger an interrupt. If 0, all digital inputs will be selected.

Returns
  GCLIB_TIMEOUT if no response from controller after configuring interrupts.

## ◆ gclib_set_data_records()

gclib_result gclib_set_data_records | ( | gclib_handle | h,
|  | size_t | period_ms )

Configure controller data records.

By default, data records are not sent by the controller.

See gclib_subscribe_data_records() to enable receiving data records from the controller.

Parameters

  h | Handle to an open connection.
  period_ms | Period between data records. Pass 0 to disable data records.

Returns
  GCLIB_TIMEOUT if no response from controller after configuring data records.

## ◆ gclib_subscribe_messages()

gclib_result gclib_subscribe_messages | ( | gclib_handle | h,
|  | void(callback)(void *user_data, const char *message) | ,
|  | void * | user_data )

Subscribe to unsolicited messages.

This method registers a callback to be run every time an unsolicited message is received from the controller.

Note
  The callback will be invoked on a separate, dedicated thread. Be careful when accessing any shared state.

When a callback is not provided, messages are instead queued for later retrieval by gclib_message().

On ethernet connections, a handle is opened for unsolicited data (if not already open) and the controller is configured to use it for messages.

Parameters

  h | Handle to an open connection.
  callback | Pass a callback function to get messages asynchronously, or NULL if you would like to use the gclib_message() blocking API.
  user_data | An arbitrary pointer that will be passed to your callback function. Can be used to provide state that persists between callbacks.

Returns
  GCLIB_NOT_SUBSCRIBED if unable to subscribe to messages.

## ◆ gclib_subscribe_interrupts()

gclib_result gclib_subscribe_interrupts | ( | gclib_handle | h,
|  | void(callback)(void *user_data, gclib_interrupt_t interrupt) | ,
|  | void * | user_data )

Subscribe to interrupts.

This method registers a callback to be run every time an interrupt is received from the controller. See gclib_set_interrupts() to enable and configure controller interrupts.

Note
  The callback will be invoked on a separate, dedicated thread. Be careful when accessing any shared state.

When a callback is not provided, interrupts are instead queued for later retrieval by gclib_interrupt().

On ethernet connections, a handle is opened for unsolicited data (if not already open) and the controller is configured to use it for interrupts.

Parameters

  h | Handle to an open connection.
  callback | Pass a callback function to get interrupts asynchronously, or NULL if you would like to use the gclib_interrupt() blocking API.
  user_data | An arbitrary pointer that will be passed to your callback function. Can be used to provide state that persists between callbacks.

Returns
  GCLIB_NOT_SUBSCRIBED if unable to subscribe to interrupts.

## ◆ gclib_subscribe_data_records()

gclib_result gclib_subscribe_data_records | ( | gclib_handle | h,
|  | void(callback)(void *user_data, gclib_data_record_handle data_record) | ,
|  | void * | user_data )

Subscribe to data records.

This method registers a callback to be run every time a data record is received from the controller. See gclib_set_data_records() to enable data records and configure how often they will be generated by the controller.

Note
  The callback will be invoked on a separate, dedicated thread. Be careful when accessing any shared state.

When a callback is not provided, data records are instead queued for later retrieval by gclib_data_record().

On ethernet connections, a handle is opened for unsolicited data (if not already open) and the controller is configured to use it for data records.

Parameters

  h | Handle to an open connection.
  callback | Pass a callback function to get data records asynchronously, or NULL if you would like to use the gclib_data_record() blocking API.
  user_data | An arbitrary pointer that will be passed to your callback function. Can be used to provide state that persists between callbacks.

Returns
  GCLIB_NOT_SUBSCRIBED if unable to subscribe to data records.

## ◆ gclib_subscribe_progress()

gclib_result gclib_subscribe_progress | ( | gclib_handle | h,
|  | void(callback)(void *user_data, size_t current, size_t max) | ,
|  | void * | user_data )

Subscribe to progress for gclib_set_program(), gclib_set_array(), and gclib_set_firmware().

Note
  The callback will be invoked on a separate, dedicated thread. Be careful when accessing any shared state.

Parameters

  h | Handle to an open connection.
  callback | A callback function that will get called anytime part of a large write is completed.
  user_data | An arbitrary pointer that will be passed to your callback function. Can be used to provide state that persists between callbacks.

Returns
  GCLIB_INVALID_ARGUMENT if callback is NULL.

## ◆ gclib_unsubscribe()

gclib_result gclib_unsubscribe | ( | gclib_handle | h,
|  | void * | callback )

Unsubscribe from messages, interrupts, data records, or progress.

Parameters

  h | Handle to an open connection.
  callback | The callback function that was previously used to subscribe. If NULL, all subscriptions will be cleared.

Returns
  GCLIB_INVALID_ARGUMENT if callback doesn't match any existing subscription.

## ◆ gclib_message()

gclib_result gclib_message | ( | gclib_handle | h,
|  | char * | message,
|  | size_t | len,
|  | int | timeout )

Get a queued unsolicited message, or wait up to timeout ms for one to arrive.

Parameters

  h | Handle to an open connection.
  message | Output buffer for the message.
  len | Length of output buffer.
  timeout | Timeout value in milliseconds. If -1, wait forever.

Returns
  - GCLIB_TIMEOUT if no message arrives for timeout ms.
  - GCLIB_BUFFER_TOO_SMALL if output does not fit in buffer.

## ◆ gclib_interrupt()

gclib_result gclib_interrupt | ( | gclib_handle | h,
|  | gclib_interrupt_t * | interrupt,
|  | int | timeout )

Get a queued interrupt, or wait up to timeout ms for one to arrive.

Parameters

  h | Handle to an open connection.
  interrupt | Output interrupt.
  timeout | Timeout value in milliseconds. If -1, wait forever.

Returns
  GCLIB_TIMEOUT if no interrupt arrives after timeout ms.

## ◆ gclib_data_record()

gclib_result gclib_data_record | ( | gclib_handle | h,
|  | gclib_data_record_handle * | data_record,
|  | int | timeout )

Get a queued data record, or wait up to timeout ms for one to arrive.

The returned handle remains valid until the next call to gclib_data_record().

Parameters

  h | Handle to an open connection.
  data_record | Output data record handle.
  timeout | Timeout value in milliseconds. If -1, wait forever.

Returns
  GCLIB_TIMEOUT if no data record arrives after timeout ms.