This page is version 1.2 of the protocol contract, so it cannot disagree with the software it describes.

Each version adds to the one before it: 1.4, 1.3, 1.2, 1.1, 1.0. Version 1.1 restates the whole contract as it stood then.

IntoMind BLE Protocol v1.2

Status: in force from firmware 1.2.0, 2026-09-25. It supersedes 1.1 by addition only, under the rules of section 0 of that document: a 1.1 host works against a 1.2 device, and a 1.2 host reads a 1.1 device's version and asks it nothing new.

What 1.2 adds:

Nothing already defined in 1.0 or 1.1 changes meaning, size, or number.

Numbers assigned by 1.2

KindNumberMeaning
Capability bit12embeddings, section 19
Capability bit13indicator, section 17
Capability bit14converter registers, section 18
Control opcode0x34GET_CONVERTER_REGISTERS
Control opcode0x44GET_INDICATOR
Control opcode0x45SET_INDICATOR
Control opcode0x46IDENTIFY
Control opcode0x87SET_EMBEDDINGS
Characteristic fill0x000BEmbeddings (notify)
Packet type0x03embedding
GET_MODEL_INFO byte 16appendedtokens per channel per window, section 19

None of these collides with a number in use or reserved (section 14 of 1.1).

17. Indicator

A device that sets capability bit 13 has a status lamp whose language a host can read and set. The language is one language at three levels of verbosity. A blink means the same thing at every level that shows it; a level only decides which things are shown.

17.1 Levels

LevelValueWhat the lamp shows
silent0nothing, ever
reserved1low battery, and a converter fault at power on. The default.
verbose2everything in reserved, plus waiting for a host, connected, streaming, and update in progress

The level is kept across power cycles. A factory reset returns it to reserved. Identify (17.4) is honored at every level, silent included, because the host asked for it at that moment.

17.2 What each thing means

Shown atThingThe device's rule
reserved, verboselow batterythe device's own charge estimate, the percent it reports in GET_BATTERY and in Status, has fallen below 20 percent. It clears once the estimate is back above 25 percent, or while the device is on external power. The band keeps the lamp from flickering at the edge.
reserved, verboseconverter faultthe analog converter failed the device's check at power on. Nothing can be recorded.
verbosewaiting for a hostadvertising, not connected
verboseconnecteda host is connected, nothing streaming
verbosestreamingsamples are leaving the device
verboseupdate in progressan image is being carried over the update service

When more than one thing is true, the lamp shows the most important: converter fault, then low battery, then update in progress, then streaming, then connected, then waiting. So in verbose a connected device with a low battery shows low battery, not connected.

The blink patterns themselves are the device's, documented on its device page, not in this contract; a host never decodes the lamp. What the contract fixes is the set of things, their meaning, the levels, and the priority, so that a host can explain the lamp to a user in words.

17.3 Reading and setting the level

GET_INDICATOR   0x44   no argument
  response payload:  u8  level        0 silent, 1 reserved, 2 verbose

SET_INDICATOR   0x45   argument u8 level
  response:          status only. A value other than 0, 1, 2 answers status 1.

The new level takes effect at once and is stored before the response is sent.

17.4 Identify

IDENTIFY        0x46   argument u8 seconds, 1 to 30; 0 stops an identify in progress
  response:          status only. A value above 30 answers status 1.

For the asked seconds the lamp shows the device's identify pattern, distinct from everything in 17.2, whatever the level; then the level's own language resumes. For a room with several devices.

On a device without capability bit 13 the three opcodes answer status 2.

18. Converter registers, read only

A device that sets capability bit 14 lets a host read the raw configuration registers of its analog converter, for debugging. The values are the chip's own, as its datasheet defines them; nothing in them is secret, and the protocol already reports the settings they encode. The contract carries the bytes and says which family of chip they belong to; what the bytes mean is the family's datasheet, and a host library may carry that knowledge keyed on the family the device declares, never on a device name.

GET_CONVERTER_REGISTERS   0x34   no argument
  response payload:
  u8      family        1 = the Texas Instruments ADS1299 family (ADS1299, ADS1299-4, ADS1299-6). The IntoMind One carries the ADS1299-4. No other value is defined by 1.2.
  u8      first         address of the first register carried, 0
  u8      count         registers carried
  u8[n]   values        count bytes, consecutive addresses from first, as the chip returned them

On a device without capability bit 14 the opcode answers status 2.

19. Embeddings

A device that sets capability bit 12 runs its encoder on each window and sends the result to the host, in one of two forms:

The weights never leave the device; both forms are outputs of the model, not the model, and the weights cannot be recovered from them.

GET_MODEL_INFO gains one byte, appended at offset 16: tokens_per_channel, the tokens the loaded model produces per channel per window. A 1.1 host never reads it; a 1.2 host reading a 1.1 device sees the message end at 16 bytes and knows the device sends no tokens.

19.1 Enabling

SET_EMBEDDINGS   0x87   argument u8 form
                        0 off, 1 the window embedding, 2 the tokens, 3 both
  response:           status only. A value above 3 answers status 1.

Embeddings flow only while streaming, with a ready model, and with a form enabled. No head is required: a device with no head, or with predictions off, still sends them when asked. On a device without capability bit 12 the opcode answers status 2.

19.2 The Embeddings characteristic (notify), fill 0x000B

One vector per notification, or per group of notifications when a vector does not fit one. A window embedding is one vector; a window's tokens are one vector per token.

offset type    field
0      u8      packet_type        0x03 = embedding
1      u8      flags              bit0 gap_in_window
                                  bit1 duty_reduced (the device skipped windows to stay within its compute budget)
                                  bit2 leadoff_in_window
                                  bit3 more_parts (another notification carries the rest of this window's values)
2      u8      embed_dim          values in the whole embedding
3      u8      first              index of the first value carried in this notification
4      u32     sample_index       raw stream index of the window's first sample
8      u64     device_time        device time of that sample
16     u16     window_samples     window length in raw samples at the current rate
18     u8[8]   encoder_id         the encoder that produced the embedding, as GET_MODEL_INFO reports it
26     u8      input_source       what the window was taken from, as in the prediction header: 0 the stream, 1 the natural signal, 2 the model's own chain
27     u8      token              0xFF for the window embedding; otherwise the token's index, channel-major over all channels: channel × tokens_per_channel + slice. A dead channel's tokens are sent too; the lead-off flag and the stream say which channels were live
28     i16[k]  values             little-endian, each the encoder's output times 4096, saturated, rounded half away from zero: exactly what a head receives (section 11)

19.3 What this makes possible on a host, and what stays off the device

With the window embedding a host trains heads without the weights: fitting the small open layer of section 11 on recorded embeddings. With the tokens a host generates signal without the weights: the open reconstruction head turns each token back into its slice, and synthesis in the embedding space (mixing, moving, or sampling tokens) followed by reconstruction is generating synthetic brain data. Both heads and the reconstruction head stay open and user-changeable; only the encoder is closed.

Generation on the device itself is not offered by 1.2 and cannot be on the IntoMind One as laid out: the reconstruction head is 38 kilobytes, the device's one megabyte of flash is fully assigned (two application slots, each 229 of 232 kilobytes used; the weights, 503,328 of 507,904 bytes used; four head slots of 4 kilobytes; the bootloader and its state), so nothing free is as large as 38 kilobytes, and a generated window is 24 kilobytes of samples to carry over the air where the tokens it would be made from are 17. If a later device or a smaller model makes it possible, it gets its own packet type, so a generated sample can never be mistaken for a measured one.

Additions to section 13, power-on defaults

SettingDefault
indicator levelreserved, unless a host's setting was persisted
embeddingsoff

Additions to section 15, conformance

Vectors for GET_INDICATOR, SET_INDICATOR, IDENTIFY, GET_CONVERTER_REGISTERS, SET_EMBEDDINGS, and the embedding packet, including a two-part embedding, each with its malformed forms; Device Info vectors claiming bits 12, 13 and 14; and the IntoMind One's profile updated: it claims all three.

What this version leaves to the device page, not the contract

The blink patterns and the identify pattern; the converter family's register map; the exact windows per second a device sustains. These are documented per device, because they are the device's, and the contract only carries what a host must be able to rely on across devices.