XTOS / OPEN SOURCE REAL-TIME SYSTEMOPEN SOURCE · VERSION 0.9.0 · BUILD FROM SOURCE
DocsCode examples

Code examples

Three complete C examples: an RT queue, synthetic signal processing, and a BCI session.

On this page

Prerequisites

Save the three code blocks as rt-example.c, signal-example.c, and bci-example.c in the OpenXTOS repository root. Build the three SDKs first, then run the matching gcc command. The code uses only public-header APIs.

RT uses SCHED_OTHER, leaves affinity unchanged, and does not call mlock. Signal uses synthetic arrays only. BCI needs a registered XTOS device and shows start/stop plus statistics without reading the format-gapped float path.

RT example

The example sets and reads back an ordinary policy in the calling thread, then demonstrates deep-copy push/pop and EAGAIN on an empty queue. Sequential single-thread use satisfies SPSC; it proves neither concurrent throughput nor hardware real-time latency. Input and output are caller stack objects; the queue is destroyed after all operations.

Complete file: rt-example.c
#define _GNU_SOURCE
#include <errno.h>
#include <inttypes.h>
#include <sched.h>
#include <stdint.h>
#include <stdio.h>
#include <xtos/rt.h>
#include <xtos/spsc.h>

int main(void)
{
    const struct xtos_rt_config config = {
        .policy = SCHED_OTHER, .priority = 0, .cpu = XTOS_RT_NO_CPU
    };
    struct xtos_spsc_queue *queue;
    int32_t input[2] = {1200, -3400};
    int32_t output[2];
    struct xtos_sample_frame sent = {
        .timestamp_ns = UINT64_C(1000000000), .sequence = 1,
        .channels = 2, .sample_rate_hz = 250, .quality_flags = 0,
        .samples_nv = input
    };
    struct xtos_sample_frame received;
    struct xtos_spsc_stats stats;
    int policy, priority;

    if (xtos_rt_apply(&config) < 0 ||
        xtos_rt_get_current(&policy, &priority) < 0) {
        perror("scheduler");
        return 1;
    }
    queue = xtos_spsc_create(4, 2);
    if (queue == NULL) {
        perror("queue");
        return 1;
    }
    if (xtos_spsc_push(queue, &sent) < 0 ||
        xtos_spsc_pop(queue, &received, output, 2) < 0) {
        perror("frame");
        xtos_spsc_destroy(queue);
        return 1;
    }
    printf("policy=%d priority=%d\n", policy, priority);
    printf("sequence=%" PRIu64 " timestamp_ns=%" PRIu64
           " samples_nv=%" PRId32 ",%" PRId32 "\n",
           received.sequence, received.timestamp_ns, output[0], output[1]);
    if (xtos_spsc_pop(queue, &received, output, 2) != -1 || errno != EAGAIN) {
        fputs("expected empty queue\n", stderr);
        xtos_spsc_destroy(queue);
        return 1;
    }
    xtos_spsc_get_stats(queue, &stats);
    printf("pushed=%" PRIu64 " popped=%" PRIu64 " empty=EAGAIN\n",
           stats.pushed, stats.popped);
    xtos_spsc_destroy(queue);
    return 0;
}
bash
gcc -std=c11 -Wall -Wextra -Werror -O2 \
  -Isdk/libxtos-rt/include rt-example.c \
  sdk/libxtos-rt/libxtos-rt.a -o rt-example
./rt-example

Success means exit status 0, SCHED_OTHER/0 readback, preserved samples and sequence, pushed/popped both 1, and EAGAIN from the second pop. Before FIFO/RR, verify permission, policy restoration, and shutdown.

Signal example

The example generates 256 points at 256 Hz with 10/20/9 Hz components, reconstructs and validates timestamps, then applies a 50 Hz notch and 5–40 Hz band-pass. DFT/SSVEP use the original array; filtering reports its final value separately. P300 uses a separate baseline and artificial peak for numeric demonstration only.

Complete file: signal-example.c
#include <inttypes.h>
#include <math.h>
#include <stdint.h>
#include <stdio.h>
#include <xtos/signal.h>

#define N 256
#define FS 256U
#define PI 3.14159265358979323846

int main(void)
{
    uint64_t timestamps[N];
    double input[N], filtered[N], power[N / 2 + 1];
    double epoch[N] = {0};
    struct xtos_signal_validation validation;
    struct xtos_notch_filter notch;
    struct xtos_bandpass_filter bandpass;
    struct xtos_ssvep_feature ssvep;
    struct xtos_p300_feature p300;
    int status;

    if (xtos_signal_correct_timestamps(UINT64_C(1000000000), FS,
                                        timestamps, N) < 0) {
        perror("timestamps");
        return 1;
    }
    status = xtos_signal_validate_timestamps(timestamps, N, FS, 0, &validation);
    if (status != 0) {
        if (status < 0) perror("validate");
        else fputs("timestamp anomalies\n", stderr);
        return 1;
    }
    for (size_t i = 0; i < N; ++i) {
        double phase = 2.0 * PI * (double)i / FS;
        input[i] = sin(10.0 * phase) + 0.5 * sin(20.0 * phase)
                 + 0.25 * sin(9.0 * phase);
    }
    if (xtos_notch_init(&notch, FS, 50.0, 20.0) < 0 ||
        xtos_bandpass_init(&bandpass, FS, 5.0, 40.0) < 0 ||
        xtos_notch_process(&notch, input, filtered, N) < 0 ||
        xtos_bandpass_process(&bandpass, filtered, filtered, N) < 0 ||
        xtos_signal_fft_power(input, N, power, N / 2 + 1) < 0 ||
        xtos_signal_ssvep_feature(input, N, FS, 10.0, 2, 1, &ssvep) < 0) {
        perror("signal");
        return 1;
    }
    for (size_t i = 0; i < 32; ++i)
        epoch[i] = (i & 1U) ? 1.0 : -1.0;
    epoch[128] = 5.0;
    if (xtos_signal_p300_feature(epoch, N, FS, 32, 250, 500, 4.0, &p300) < 0) {
        perror("p300");
        return 1;
    }
    printf("interval_ns=%" PRIu64 " anomalies=%zu/%zu\n",
           validation.expected_interval_ns, validation.interval_anomalies,
           validation.timestamp_anomalies);
    printf("bins=%d power[10]=%.3f filtered_last=%.6f\n",
           N / 2 + 1, power[10], filtered[N - 1]);
    printf("ssvep_bin=%zu harmonics=%zu snr=%.3f snr_db=%.3f\n",
           ssvep.target_bin, ssvep.harmonics_used, ssvep.snr, ssvep.snr_db);
    printf("p300_detected=%d z=%.3f latency_ms=%.3f\n",
           p300.detected, p300.peak_z_score, p300.peak_latency_ms);
    return 0;
}
bash
gcc -std=c11 -Wall -Wextra -Werror -O2 \
  -Isdk/libxtos-signal/include signal-example.c \
  sdk/libxtos-signal/libxtos-signal.a -lm -o signal-example
./signal-example

Output includes interval and anomaly counts, spectrum length and bin power, filtered value, SSVEP harmonics, and P300 z score and latency. Spectrum capacity is N/2+1; filters are initialized before sequential processing. There is no real EEG, diagnosis, participant experiment, or hardware-latency result.

BCI example

The example reads cached device information, prints name with a length bound, starts and immediately stops, reads driver statistics, and cleans up. It changes no rate or gain, calls no placeholder calibration, reads no float samples, and does not call driver counts consumed frames. Without a device, compile only.

Complete file: bci-example.c; check compilation only without a device
#include <inttypes.h>
#include <stdio.h>
#include <xtos/bci.h>

int main(int argc, char **argv)
{
    const char *path = argc > 1 ? argv[1] : "/dev/xtos0";
    xtos_bci_session_t *session;
    struct xtos_bci_device_info info;
    struct xtos_bci_statistics stats;
    int exit_status = 1;

    session = xtos_bci_session_create(path);
    if (session == NULL) {
        perror("session_create");
        return 1;
    }
    if (xtos_bci_get_info(session, &info) < 0) {
        perror("get_info");
        goto cleanup;
    }
    if (info.num_channels == 0 || info.sampling_rate == 0) {
        fputs("invalid cached device info\n", stderr);
        goto cleanup;
    }
    printf("device=%.*s channels=%" PRIu32 " rate=%" PRIu32 " Hz\n",
           (int)sizeof(info.name), info.name, info.num_channels, info.sampling_rate);
    if (xtos_bci_start(session) < 0) {
        perror("start");
        goto cleanup;
    }
    /* Control-path example: do not interpret the published float read ABI. */
    if (xtos_bci_stop(session) < 0) {
        perror("stop");
        goto cleanup;
    }
    if (xtos_bci_get_stats(session, &stats) < 0) {
        perror("get_stats");
        goto cleanup;
    }
    printf("driver_samples=%" PRIu64 " dropped=%" PRIu64
           " errors=%" PRIu64 " overruns=%" PRIu64 "\n",
           stats.samples_read, stats.samples_dropped, stats.errors, stats.overruns);
    exit_status = 0;
cleanup:
    xtos_bci_session_destroy(session);
    return exit_status;
}
bash
gcc -std=c11 -Wall -Wextra -Werror -O2 \
  -Isdk/libxtos-bci/include bci-example.c \
  sdk/libxtos-bci/libxtos-bci.a -o bci-example

# Run only with a registered device and read/write permission:
./bci-example /dev/xtos0

For ENOENT, check device binding and registration. For EACCES, check node permission. For EBUSY, check the existing opener. invalid cached device info can indicate GET_INFO failed during create. Preserve start/stop errors and inspect driver logs; an empty device file is not a workaround.

Verification and extension

Record the public commit ID, gcc --version, complete commands, exit status, and raw stdout/stderr. RT/signal can run on an ordinary Linux host; recheck ABI and environment on target XTOS. BCI compilation proves linkable symbols and types only; device execution also needs driver, connection, and acquisition records.

To extend RT, use one acquisition thread and one consumer, then destroy the queue after both exit. For signal, validate cross-block filtering and timing with fixed input first. For BCI, resolve read format, serial-frame parsing, and timing before adding DSP.