> For the complete documentation index, see [llms.txt](https://docs.anthriq.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.anthriq.com/bxi-studio/developer/overview/devices/xsys.md).

# xSys

A biosignal amplifier with up to 13 externally wired channels. Electrodes are connected by hand, so there are no motors to drive — everything else matches [Instinct](/bxi-studio/developer/overview/devices/instinct.md).

|             |                                      |
| ----------- | ------------------------------------ |
| Device type | `anthriq-instinct`                   |
| Transport   | WebSocket, default port 9250         |
| Electrodes  | Up to 13, external and wired by hand |

## What it supports

| Feature     | Use it for                                | Page                                                                                 |
| ----------- | ----------------------------------------- | ------------------------------------------------------------------------------------ |
| `registers` | Gain, filtering, routing, channel mapping | [Configure channels](/bxi-studio/developer/overview/features/channels.md)            |
| `impedance` | Confirming electrode contact              | [Measure contact impedance](/bxi-studio/developer/overview/features/impedance.md)    |
| `eeg`       | Streaming live samples                    | [Stream EXG](/bxi-studio/developer/overview/features/exg.md)                         |
| `firmware`  | Over-the-air updates                      | [Update firmware](/bxi-studio/developer/overview/features/firmware.md)               |
| `system`    | Capabilities and connection state         | [Read device information](/bxi-studio/developer/overview/get-started/device-info.md) |

**No `motors`.** Electrodes are placed by hand, so [Position the headset](/bxi-studio/developer/overview/devices/instinct/motors.md) does not apply. Everything else behaves as it does on Instinct.

## Device parameters

Values that differ from the Instinct headset. The register mechanics are the same; these are the ranges this hardware accepts.

| Setting         | Options                            | Typical        |
| --------------- | ---------------------------------- | -------------- |
| Channels        | Up to 13, wired by hand            | —              |
| Gain, per stage | 1x, 2x, 4x, 6x, 8x, 12x, 20x, 24x  | Stage 1 at 20x |
| Frequency       | 100, 262, 524, 1048, 2096, 4192 Hz | 262 Hz         |

Total amplification is the two stages multiplied: 20x and 100x gives 2000x. `motor_associated` and `associated_motor_id` stay at their defaults, since there are no motors to bind to.

## Run a session

1. [Install and connect](/bxi-studio/developer/overview/get-started/connect.md) with device type `anthriq-instinct`.
2. Wire the electrodes to the amplifier's connector ports.
3. [Configure channels](/bxi-studio/developer/overview/features/channels.md) for gain and filtering.
4. [Measure contact impedance](/bxi-studio/developer/overview/features/impedance.md) and re-seat anything reading poorly.
5. [Stream EXG](/bxi-studio/developer/overview/features/exg.md), or [run parallel streams](/bxi-studio/developer/overview/features/parallel.md) to watch contact while recording.

## Set up

Amplifier with externally wired electrodes. Same device type as Instinct and the same calls, minus the motor step: place the electrodes by hand, then configure and stream.

{% tabs %}
{% tab title="Node.js" %}

```typescript
import { BxiClient, GainStage1, LpfSetting } from "@anthriq_dev/bxi-interface";

const client = new BxiClient<"anthriq-instinct">({ deviceType: "anthriq-instinct" });

// 1. Connect. A unit announces the variant in its mDNS hostname.
await client.initialize("ws://anthriq-instinct-xsys-v1-4FFD98.local:3333/ws");
await client.connect();

// 2. No motors on this device, so confirm before any code assumes them.
const capabilities = client.getCachedCapabilities();
if (capabilities.features.motors) {
  throw new Error("Motorised unit attached; use the Instinct sequence");
}

// 3. Configure a channel for the electrodes you wired.
await client.features.executeOperation("registers", "write", {
  type: "synap",
  synap_id: 0,
  fields: { enabled: 1, gain_stage_1: GainStage1.Gain20G, lpf_setting: LpfSetting.Hz300 },
});

// 4. Stream. Check contact impedance before recording for real.
const streamId = 20;

await client.features.executeOperation("eeg", "add_stream", {
  stream: {
    stream_id: streamId,
    protocol: "websocket",
    host: "127.0.0.1",
    port: 9020,
    elements_before_flush: 80,
  },
});
await new Promise((r) => setTimeout(r, 1000));

const subscription = await client.features.subscribeToOperation(
  "eeg",
  "stream",
  (update) => {
    if (update.success) process(update.data.details.payload.frames);
  },
  { stream_id: streamId }
);
await new Promise((r) => setTimeout(r, 2000));

await client.features.executeOperation("eeg", "start_stream", { stream_id: streamId });
await new Promise((r) => setTimeout(r, 10000));

// 5. Tear down in reverse.
await client.features.executeOperation("eeg", "stop_stream", { stream_id: streamId });
await new Promise((r) => setTimeout(r, 1500));
await client.features.unsubscribeFromOperation("eeg", "stream", {
  subscriptionId: subscription.data.subscriptionId,
});
await client.features.executeOperation("eeg", "remove_stream", { stream_id: streamId });

await client.shutdown();
```

{% endtab %}

{% tab title="Python" %}

```python
import asyncio
from anthriq_bxi_interface import BxiClient, GainStage1, LpfSetting

client = BxiClient(device_type="anthriq-instinct")

# 1. Connect. A unit announces the variant in its mDNS hostname.
await client.initialize("ws://anthriq-instinct-xsys-v1-4FFD98.local:3333/ws")
await client.connect()

# 2. No motors on this device, so confirm before any code assumes them.
capabilities = client.get_cached_capabilities()
if "motors" in capabilities.features:
    raise RuntimeError("Motorised unit attached; use the Instinct sequence")

# 3. Configure a channel for the electrodes you wired.
await client.execute_operation("registers", "write", {
    "type": "synap",
    "synap_id": 0,
    "fields": {"enabled": 1, "gain_stage_1": GainStage1.GAIN_20G,
               "lpf_setting": LpfSetting.HZ_300},
})

# 4. Stream. Check contact impedance before recording for real.
stream_id = 20

await client.execute_operation("eeg", "add_stream", {
    "stream": {
        "stream_id": stream_id,
        "protocol": "websocket",
        "host": "127.0.0.1",
        "port": 9020,
        "elements_before_flush": 80,
    },
})
await asyncio.sleep(1)

def on_frame(update):
    if update.success:
        process(update.data["details"]["payload"].get("frames", []))

subscription = await client.subscribe_to_operation(
    "eeg", "stream", on_frame, {"stream_id": stream_id}
)
await asyncio.sleep(2)

await client.execute_operation("eeg", "start_stream", {"stream_id": stream_id})
await asyncio.sleep(10)

# 5. Tear down in reverse.
await client.execute_operation("eeg", "stop_stream", {"stream_id": stream_id})
await asyncio.sleep(1.5)
await client.unsubscribe_from_operation(
    "eeg", "stream", {"subscriptionId": subscription.subscription_id}
)
await client.execute_operation("eeg", "remove_stream", {"stream_id": stream_id})

await client.shutdown()
```

{% endtab %}
{% endtabs %}

Each step in depth: [Configure channels](/bxi-studio/developer/overview/features/channels.md), [Measure contact impedance](/bxi-studio/developer/overview/features/impedance.md), [Stream EXG](/bxi-studio/developer/overview/features/exg.md).
