Skip to content

C API

The library is built with hidden visibility, so the functions here are the whole of the public ABI. Everything else — the framer, the link, the servo helpers — stays internal and is free to change.

#include <eilik.h>
  • eilik_t — an opaque handle to an open robot, created by eilik_open or eilik_open_default and released with eilik_close.
  • eilik_status_t — the result every call returns: EILIK_OK on success, or one of EILIK_ERR_ARG, EILIK_ERR_PORT, EILIK_ERR_BUSY, EILIK_ERR_IO, EILIK_ERR_TIMEOUT, EILIK_ERR_PROTOCOL, EILIK_ERR_RANGE, EILIK_ERR_SERVO_FAULT. Turn a status into text with eilik_strerror.
  • eilik_joint_t — which joint a call refers to: EILIK_ARM_RIGHT, EILIK_ARM_LEFT, EILIK_BODY, EILIK_HEAD. Sides are the robot’s own, as anatomy is normally named — EILIK_ARM_LEFT is the robot’s left arm, which is the one you see on your right when facing it.
eilik_status_t eilik_open(const char *device, eilik_t **out);

Opens the robot at a given serial device path, writing the new handle to *out on success.

eilik_status_t eilik_open_default(eilik_t **out);

Opens the robot, discovering the serial port itself rather than being told one.

void eilik_close(eilik_t *robot);

Releases the serial port.

const char *eilik_strerror(eilik_status_t status);

Returns a human-readable message for a status code.

const char *eilik_version_string(void);

Returns the library’s version as a string.

Stage a target with eilik_set, then send every staged joint in a single 0xA2 packet with eilik_commit — separate packets per joint move the joints visibly out of step. Staged targets are clamped to the joint’s limits, and so is the centre that eilik_rest asks for; in strict mode eilik_set reports EILIK_ERR_RANGE instead of clamping.

eilik_status_t eilik_set(eilik_t *robot, eilik_joint_t joint, uint16_t position);

Stages a target position for one joint.

eilik_status_t eilik_commit(eilik_t *robot);

Sends every staged joint in a single packet.

eilik_status_t eilik_rest(eilik_t *robot);

Returns every joint to the centre.

eilik_status_t eilik_read_positions(eilik_t *robot, uint16_t out[4]);

Reads the four joint positions into out. Returns EILIK_ERR_SERVO_FAULT when every joint reads zero, which means the servo controller has stopped rather than that the robot is at position zero. A reply that does not report all four joints exactly once is rejected with EILIK_ERR_PROTOCOL, and leaves out untouched.

eilik_status_t eilik_get_limits(eilik_t *robot, eilik_joint_t joint,
uint16_t *lo, uint16_t *hi);

Reads a joint’s clamp limits into *lo and *hi.

eilik_status_t eilik_set_limits(eilik_t *robot, eilik_joint_t joint,
uint16_t lo, uint16_t hi);

Sets a joint’s clamp limits. Narrowing a joint’s limits re-clamps any value already staged for it.

eilik_status_t eilik_set_strict(eilik_t *robot, int strict);

Switches between clamping out-of-range positions (the default) and rejecting them with EILIK_ERR_RANGE.

The screen is 128×64 monochrome, one bit per pixel, 1024 bytes in total (EILIK_DISPLAY_WIDTH, EILIK_DISPLAY_HEIGHT, EILIK_DISPLAY_BYTES). The layout is SSD1306 page mode: 8 pages of 128 columns, and within a byte the least significant bit is the top row of its page, so pixel (x, y) is bit y % 8 of byte (y / 8) * 128 + x.

The panel is mounted rotated 180 degrees relative to that byte order, so a buffer written as-is appears upside down. Rotating is left to the caller, which is where the image is — the Python wrapper does it by default.

eilik_status_t eilik_write_display(eilik_t *robot,
const uint8_t framebuffer[EILIK_DISPLAY_BYTES]);

Writes a 1024-byte framebuffer to the screen, unchanged.

eilik_status_t eilik_read_display(eilik_t *robot,
uint8_t out[EILIK_DISPLAY_BYTES]);

Reads back the 1024-byte framebuffer currently shown, in the panel’s own order.